mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-04 00:40:27 +00:00
Compare commits
No commits in common. "master" and "3.0" have entirely different histories.
14076 changed files with 432281 additions and 1103596 deletions
|
@ -6,8 +6,6 @@ AlignConsecutiveMacros: true
|
||||||
AlignConsecutiveDeclarations: false
|
AlignConsecutiveDeclarations: false
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
AllowShortFunctionsOnASingleLine: false
|
AllowShortFunctionsOnASingleLine: false
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
IncludeBlocks: Merge
|
IncludeBlocks: Merge
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
# Run this command to always ignore formatting commits in git blame
|
|
||||||
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
|
||||||
|
|
||||||
# Upgraded clang-format to 19.0.0git
|
|
||||||
89fc95fefd40413706ff1bdaac2e8d98b328dbf1
|
|
||||||
# vim c++ filetype in modelines
|
|
||||||
04c6bc478e082263d67c41bedbd033dde2d429eb
|
|
||||||
# Ran clang-format
|
|
||||||
f032b5570b4cd87c6bb4abb54c0b98e69c939955
|
|
||||||
# Applied clang-format update to repo
|
|
||||||
6e6fc38935054db0534d5af4fb99c6193305b946
|
|
||||||
# revert retabbing
|
|
||||||
2b315626f3af765cdfbc61114647412cdb798b3a
|
|
||||||
# more modeline errata
|
|
||||||
3a8e01a77a7c97af0b16fb1651b230cee7f7d4c6
|
|
||||||
# fix more vi modelines
|
|
||||||
2fc507c98f53a76718f61f9a36602f86b5ac0cc9
|
|
||||||
# flip et/noet in modelines
|
|
||||||
e16a7d8f3b8f906c3ef76e79f57f3adfc7f25186
|
|
||||||
# fix vi modelines
|
|
||||||
394d998315f613a888cc6b6c051d4163bdf5cd6f
|
|
||||||
# clang-format
|
|
||||||
c0eacf2eb1e1c0b3bd4f71f12fef258f5b249c3f
|
|
||||||
# ape-m1 formatting cleanup
|
|
||||||
da8baf2aa5ce93b958aca90a0ae69f537806324b
|
|
||||||
# Run clang-format on most sources
|
|
||||||
369f9740de4534c28d0e81ab2afc99decbb9a3e6
|
|
||||||
# Get rid of .internal.h convention in LIBC_INTRIN
|
|
||||||
86d884cce24d773e298a2714c1e3d91ecab9be45
|
|
||||||
# Remove .internal from more header filenames
|
|
||||||
31194165d2afca36c2315a6e7ca2f0797dde09e3
|
|
8
.gitattributes
vendored
8
.gitattributes
vendored
|
@ -1,10 +1,4 @@
|
||||||
# -*- conf -*-
|
# -*- conf -*-
|
||||||
*.gz binary
|
*.gz binary
|
||||||
*.so binary
|
/build/bootstrap/*.com binary
|
||||||
*.dll binary
|
|
||||||
*.dylib binary
|
|
||||||
/build/bootstrap/* binary
|
|
||||||
/usr/share/terminfo/* binary
|
|
||||||
/usr/share/terminfo/*/* binary
|
|
||||||
/usr/share/zoneinfo/* binary
|
/usr/share/zoneinfo/* binary
|
||||||
/usr/share/zoneinfo/*/* binary
|
|
||||||
|
|
59
.github/ISSUE_TEMPLATE/01-bug-low.yml
vendored
59
.github/ISSUE_TEMPLATE/01-bug-low.yml
vendored
|
@ -1,59 +0,0 @@
|
||||||
name: Low Severity Bugs
|
|
||||||
description: Used to report low severity bugs in cosmopolitan (e.g. cosmetic issues, non critical UI glitches)
|
|
||||||
title: "Bug: "
|
|
||||||
labels: ["bug", "low severity"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
Please include information about your system, the steps to reproduce the bug,
|
|
||||||
and the version of cosmopolitan that you are using.
|
|
||||||
If possible, please provide a minimal code example that reproduces the bug.
|
|
||||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
|
||||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
|
||||||
- type: input
|
|
||||||
id: contact
|
|
||||||
attributes:
|
|
||||||
label: Contact Details
|
|
||||||
description: How can we get in touch with you if we need more info?
|
|
||||||
placeholder: ex. email@example.com
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: what-happened
|
|
||||||
attributes:
|
|
||||||
label: What happened?
|
|
||||||
description: Also tell us, what did you expect to happen?
|
|
||||||
placeholder: Tell us what you see!
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: What version of our software are you running? (use `--version` to get a version string)
|
|
||||||
placeholder: "cosmocc (GCC) 12.3.0"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: operating-system
|
|
||||||
attributes:
|
|
||||||
label: What operating system are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Linux
|
|
||||||
- Mac
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
59
.github/ISSUE_TEMPLATE/02-bug-medium.yml
vendored
59
.github/ISSUE_TEMPLATE/02-bug-medium.yml
vendored
|
@ -1,59 +0,0 @@
|
||||||
name: Medium Severity Bug
|
|
||||||
description: Used to report medium severity bugs in cosmopolitan (e.g. Malfunctioning Features but generally still useable)
|
|
||||||
title: "Bug: "
|
|
||||||
labels: ["bug", "medium severity"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
Please include information about your system, the steps to reproduce the bug,
|
|
||||||
and the version of cosmopolitan that you are using.
|
|
||||||
If possible, please provide a minimal code example that reproduces the bug.
|
|
||||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
|
||||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
|
||||||
- type: input
|
|
||||||
id: contact
|
|
||||||
attributes:
|
|
||||||
label: Contact Details
|
|
||||||
description: How can we get in touch with you if we need more info?
|
|
||||||
placeholder: ex. email@example.com
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: what-happened
|
|
||||||
attributes:
|
|
||||||
label: What happened?
|
|
||||||
description: Also tell us, what did you expect to happen?
|
|
||||||
placeholder: Tell us what you see!
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: What version of our software are you running? (use `--version` to get a version string)
|
|
||||||
placeholder: "cosmocc (GCC) 12.3.0"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: operating-system
|
|
||||||
attributes:
|
|
||||||
label: What operating system are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Linux
|
|
||||||
- Mac
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
59
.github/ISSUE_TEMPLATE/03-bug-high.yml
vendored
59
.github/ISSUE_TEMPLATE/03-bug-high.yml
vendored
|
@ -1,59 +0,0 @@
|
||||||
name: High Severity Bug
|
|
||||||
description: Used to report high severity bugs in cosmopolitan (e.g. Malfunctioning features hindering important common workflow)
|
|
||||||
title: "Bug: "
|
|
||||||
labels: ["bug", "high severity"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
Please include information about your system, the steps to reproduce the bug,
|
|
||||||
and the version of cosmopolitan that you are using.
|
|
||||||
If possible, please provide a minimal code example that reproduces the bug.
|
|
||||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
|
||||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
|
||||||
- type: input
|
|
||||||
id: contact
|
|
||||||
attributes:
|
|
||||||
label: Contact Details
|
|
||||||
description: How can we get in touch with you if we need more info?
|
|
||||||
placeholder: ex. email@example.com
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: what-happened
|
|
||||||
attributes:
|
|
||||||
label: What happened?
|
|
||||||
description: Also tell us, what did you expect to happen?
|
|
||||||
placeholder: Tell us what you see!
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: What version of our software are you running? (use `--version` to get a version string)
|
|
||||||
placeholder: "cosmocc (GCC) 12.3.0"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: operating-system
|
|
||||||
attributes:
|
|
||||||
label: What operating system are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Linux
|
|
||||||
- Mac
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
59
.github/ISSUE_TEMPLATE/04-bug-critical.yml
vendored
59
.github/ISSUE_TEMPLATE/04-bug-critical.yml
vendored
|
@ -1,59 +0,0 @@
|
||||||
name: Critical Severity Bug
|
|
||||||
description: Used to report critical severity bugs in cosmopolitan (e.g. Crashing, Corrupted, Dataloss)
|
|
||||||
title: "Bug: "
|
|
||||||
labels: ["bug", "critical severity"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
Please include information about your system, the steps to reproduce the bug,
|
|
||||||
and the version of cosmopolitan that you are using.
|
|
||||||
If possible, please provide a minimal code example that reproduces the bug.
|
|
||||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
|
||||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
|
||||||
- type: input
|
|
||||||
id: contact
|
|
||||||
attributes:
|
|
||||||
label: Contact Details
|
|
||||||
description: How can we get in touch with you if we need more info?
|
|
||||||
placeholder: ex. email@example.com
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: what-happened
|
|
||||||
attributes:
|
|
||||||
label: What happened?
|
|
||||||
description: Also tell us, what did you expect to happen?
|
|
||||||
placeholder: Tell us what you see!
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: What version of our software are you running? (use `--version` to get a version string)
|
|
||||||
placeholder: "cosmocc (GCC) 12.3.0"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: operating-system
|
|
||||||
attributes:
|
|
||||||
label: What operating system are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Linux
|
|
||||||
- Mac
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
51
.github/ISSUE_TEMPLATE/05-enhancement.yml
vendored
51
.github/ISSUE_TEMPLATE/05-enhancement.yml
vendored
|
@ -1,51 +0,0 @@
|
||||||
name: Enhancement template
|
|
||||||
description: Used to request enhancements for cosmopolitan
|
|
||||||
title: "Feature Request: "
|
|
||||||
labels: ["enhancement"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
[Please post your idea first in Discussion if there is not yet a consensus for this enhancement request. This will help to keep this issue tracker focused on enhancements that the community has agreed needs to be implemented.](https://github.com/jart/cosmopolitan/discussions/categories/ideas)
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: prerequisites
|
|
||||||
attributes:
|
|
||||||
label: Prerequisites
|
|
||||||
description: Please confirm the following before submitting your enhancement request.
|
|
||||||
options:
|
|
||||||
- label: I am running the latest code. Mention the version if possible as well.
|
|
||||||
required: true
|
|
||||||
- label: I carefully followed the [README.md](https://github.com/jart/cosmopolitan/blob/master/README.md).
|
|
||||||
required: true
|
|
||||||
- label: I searched using keywords relevant to my issue to make sure that I am creating a new issue that is not already open (or closed).
|
|
||||||
required: true
|
|
||||||
- label: I reviewed the [Discussions](https://github.com/jart/cosmopolitan/discussions), and have a new and useful enhancement to share.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: feature-description
|
|
||||||
attributes:
|
|
||||||
label: Feature Description
|
|
||||||
description: Please provide a detailed written description of what you were trying to do, and what you expected `cosmopolitan` to do as an enhancement.
|
|
||||||
placeholder: Detailed description of the enhancement
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: motivation
|
|
||||||
attributes:
|
|
||||||
label: Motivation
|
|
||||||
description: Please provide a detailed written description of reasons why this feature is necessary and how it is useful to `cosmopolitan` users.
|
|
||||||
placeholder: Explanation of why this feature is needed and its benefits
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: possible-implementation
|
|
||||||
attributes:
|
|
||||||
label: Possible Implementation
|
|
||||||
description: If you have an idea as to how it can be implemented, please write a detailed description. Feel free to give links to external sources or share visuals that might be helpful to understand the details better.
|
|
||||||
placeholder: Detailed description of potential implementation
|
|
||||||
validations:
|
|
||||||
required: false
|
|
52
.github/ISSUE_TEMPLATE/06-research.yml
vendored
52
.github/ISSUE_TEMPLATE/06-research.yml
vendored
|
@ -1,52 +0,0 @@
|
||||||
name: Research
|
|
||||||
description: Track new technical research area
|
|
||||||
title: "Research: "
|
|
||||||
labels: ["research"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Don't forget to check for any [duplicate research issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3A%22research+%F0%9F%94%AC%22)
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: research-stage
|
|
||||||
attributes:
|
|
||||||
label: Research Stage
|
|
||||||
description: Track general state of this research ticket
|
|
||||||
options:
|
|
||||||
- label: Background Research (Let's try to avoid reinventing the wheel)
|
|
||||||
- label: Hypothesis Formed (How do you think this will work and it's effect?)
|
|
||||||
- label: Strategy / Implementation Forming
|
|
||||||
- label: Analysis of results
|
|
||||||
- label: Debrief / Documentation (So people in the future can learn from us)
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: background
|
|
||||||
attributes:
|
|
||||||
label: Previous existing literature and research
|
|
||||||
description: Whats the current state of the art and whats the motivation for this research?
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: hypothesis
|
|
||||||
attributes:
|
|
||||||
label: Hypothesis
|
|
||||||
description: How do you think this will work and it's effect?
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: implementation
|
|
||||||
attributes:
|
|
||||||
label: Implementation
|
|
||||||
description: Got an approach? e.g. a PR ready to go?
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: analysis
|
|
||||||
attributes:
|
|
||||||
label: Analysis
|
|
||||||
description: How does the proposed implementation behave?
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
28
.github/ISSUE_TEMPLATE/07-refactor.yml
vendored
28
.github/ISSUE_TEMPLATE/07-refactor.yml
vendored
|
@ -1,28 +0,0 @@
|
||||||
name: Refactor (Maintainers)
|
|
||||||
description: Used to track refactoring opportunities
|
|
||||||
title: "Refactor: "
|
|
||||||
labels: ["refactor"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Don't forget to [check for existing refactor issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3Arefactoring) in case it's already covered.
|
|
||||||
Also you may want to check [Pull request refactor label as well](https://github.com/jart/cosmopolitan/pulls?q=is%3Aopen+is%3Apr+label%3Arefactoring) for duplicates too.
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: background-description
|
|
||||||
attributes:
|
|
||||||
label: Background Description
|
|
||||||
description: Please provide a detailed written description of the pain points you are trying to solve.
|
|
||||||
placeholder: Detailed description behind your motivation to request refactor
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: possible-approaches
|
|
||||||
attributes:
|
|
||||||
label: Possible Refactor Approaches
|
|
||||||
description: If you have some idea of possible approaches to solve this problem. You may want to make it a todo list.
|
|
||||||
placeholder: Your idea of possible refactoring opportunity/approaches
|
|
||||||
validations:
|
|
||||||
required: false
|
|
15
.github/ISSUE_TEMPLATE/config.yml
vendored
15
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -1,15 +0,0 @@
|
||||||
blank_issues_enabled: true
|
|
||||||
contact_links:
|
|
||||||
- name: FAQ
|
|
||||||
url: https://github.com/jart/cosmopolitan/wiki/FAQ
|
|
||||||
about: Is your question a common one? You may want to check here first.
|
|
||||||
- name: Got an idea?
|
|
||||||
url: https://github.com/jart/cosmopolitan/discussions/categories/ideas
|
|
||||||
about: Pop it there. It may then become an enhancement ticket.
|
|
||||||
- name: Got a question?
|
|
||||||
url: https://github.com/jart/cosmopolitan/discussions/categories/q-a
|
|
||||||
about: Ask a question there!
|
|
||||||
- name: Want to contribute?
|
|
||||||
url: https://github.com/jart/cosmopolitan/wiki/contribute
|
|
||||||
about: Head to the contribution guide page of the wiki for areas you can help with
|
|
||||||
|
|
49
.github/labeler.yml
vendored
49
.github/labeler.yml
vendored
|
@ -1,49 +0,0 @@
|
||||||
# https://github.com/actions/labeler
|
|
||||||
|
|
||||||
documentation:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- README.md
|
|
||||||
- LICENSE
|
|
||||||
- CONTRIBUTING.md
|
|
||||||
- libc/README.md
|
|
||||||
- tool/cosmocc/README.md
|
|
||||||
- third_party/getopt/README.txt
|
|
||||||
build:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- build/**
|
|
||||||
- Makefile
|
|
||||||
- '*/*.mk'
|
|
||||||
examples:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: examples/**
|
|
||||||
devops:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- .github/**
|
|
||||||
- .clang-format
|
|
||||||
dsp:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- dsp/**
|
|
||||||
ape:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- ape/**
|
|
||||||
libc:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- libc/**
|
|
||||||
net:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- net/**
|
|
||||||
third_party:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- third_party/**
|
|
||||||
tool:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- tool/**
|
|
42
.github/workflows/build.yml
vendored
42
.github/workflows/build.yml
vendored
|
@ -1,8 +1,5 @@
|
||||||
name: build
|
name: build
|
||||||
|
|
||||||
env:
|
|
||||||
COSMOCC_VERSION: 3.9.2
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
@ -22,48 +19,13 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
mode: ["", tiny, rel, tinylinux, optlinux]
|
mode: ["", tiny, rel, tinylinux, optlinux]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
with:
|
|
||||||
# Full checkout needed for git-restore-mtime-bare.
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
# TODO(jart): fork this action.
|
|
||||||
- uses: chetan/git-restore-mtime-action@v2
|
|
||||||
|
|
||||||
- uses: actions/cache/restore@v4
|
|
||||||
id: cache
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
.cosmocc
|
|
||||||
o
|
|
||||||
key: ${{ env.COSMOCC_VERSION }}-${{ matrix.mode }}-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.COSMOCC_VERSION }}-${{ matrix.mode }}-
|
|
||||||
${{ env.COSMOCC_VERSION }}-
|
|
||||||
|
|
||||||
- name: Restore mtimes
|
|
||||||
if: steps.cache.outputs.cache-hit == 'true'
|
|
||||||
run: |
|
|
||||||
while read mtime file; do
|
|
||||||
[ -f "$file" ] && touch -d "@$mtime" "$file"
|
|
||||||
done < o/.mtimes
|
|
||||||
|
|
||||||
- name: support ape bins 1
|
- name: support ape bins 1
|
||||||
run: sudo cp -a build/bootstrap/ape.elf /usr/bin/ape
|
run: sudo cp build/bootstrap/ape.elf /usr/bin/ape
|
||||||
|
|
||||||
- name: support ape bins 2
|
- name: support ape bins 2
|
||||||
run: sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
run: sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
||||||
|
|
||||||
- name: make matrix
|
- name: make matrix
|
||||||
run: V=0 make -j2 MODE=${{ matrix.mode }}
|
run: V=0 make -j2 MODE=${{ matrix.mode }}
|
||||||
|
|
||||||
- name: Save mtimes
|
|
||||||
run: |
|
|
||||||
find o -type f -exec stat -c "%Y %n" {} \; > o/.mtimes
|
|
||||||
|
|
||||||
- uses: actions/cache/save@v4
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
.cosmocc
|
|
||||||
o
|
|
||||||
key: ${{ env.COSMOCC_VERSION }}-${{ matrix.mode }}-${{ github.sha }}
|
|
||||||
|
|
17
.github/workflows/labeler.yml
vendored
17
.github/workflows/labeler.yml
vendored
|
@ -1,17 +0,0 @@
|
||||||
name: "Pull Request Labeler"
|
|
||||||
on:
|
|
||||||
- pull_request_target
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
labeler:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
repository: "jart/cosmopolitan"
|
|
||||||
- uses: actions/labeler@v5
|
|
||||||
with:
|
|
||||||
configuration-path: '.github/labeler.yml'
|
|
24
.github/workflows/nightly-cosmocc.yml
vendored
24
.github/workflows/nightly-cosmocc.yml
vendored
|
@ -1,24 +0,0 @@
|
||||||
name: Nightly cosmocc
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
# https://crontab.guru/#37_4_*_*_*
|
|
||||||
- cron: "37 4 * * *"
|
|
||||||
workflow_dispatch:
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
jobs:
|
|
||||||
build-cosmocc:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: |
|
|
||||||
sudo cp build/bootstrap/ape.elf /usr/bin/ape
|
|
||||||
sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
|
||||||
- run: tool/cosmocc/package.sh
|
|
||||||
# https://github.com/actions/upload-artifact/issues/590
|
|
||||||
- uses: actions/upload-artifact@v4.3.5
|
|
||||||
with:
|
|
||||||
name: cosmocc
|
|
||||||
path: cosmocc
|
|
||||||
compression-level: 9
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,8 +1,7 @@
|
||||||
# -*- conf -*-
|
# -*- conf -*-
|
||||||
|
|
||||||
/o
|
/o
|
||||||
/cosmocc
|
/.prompt.jtlp
|
||||||
/.cosmocc
|
|
||||||
|
|
||||||
# TODO: Find some way to have Python write to o/
|
# TODO: Find some way to have Python write to o/
|
||||||
__pycache__
|
__pycache__
|
||||||
|
@ -15,4 +14,3 @@ __pycache__
|
||||||
/tool/emacs/*.elc
|
/tool/emacs/*.elc
|
||||||
/perf.data
|
/perf.data
|
||||||
/perf.data.old
|
/perf.data.old
|
||||||
/qemu*core
|
|
||||||
|
|
109
.vscode/c_cpp_properties.json
vendored
Normal file
109
.vscode/c_cpp_properties.json
vendored
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Win32",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}"
|
||||||
|
],
|
||||||
|
"cStandard": "c11",
|
||||||
|
"cppStandard": "c++11",
|
||||||
|
"forcedInclude": ["${workspaceFolder}/.vscode/vscode.h"],
|
||||||
|
"defines": [
|
||||||
|
"libcesque=",
|
||||||
|
"pureconst=",
|
||||||
|
"paramsnonnull(x)=",
|
||||||
|
"alignas(x)",
|
||||||
|
"alignof(x)",
|
||||||
|
"artificial=",
|
||||||
|
"__wur=",
|
||||||
|
"mayalias=",
|
||||||
|
"forceinline=",
|
||||||
|
"forcealign(x)=",
|
||||||
|
"scanfesque(x)=",
|
||||||
|
"strftimeesque(x)=",
|
||||||
|
"wontreturn=",
|
||||||
|
"textreal=",
|
||||||
|
"mallocesque=",
|
||||||
|
"callocesque=",
|
||||||
|
"vallocesque=",
|
||||||
|
"reallocesque=",
|
||||||
|
"strlenesque=",
|
||||||
|
"memcpyesque=",
|
||||||
|
"hasatleast=",
|
||||||
|
"noinline=",
|
||||||
|
"textexit=",
|
||||||
|
"returnstwice=",
|
||||||
|
"textwindows=",
|
||||||
|
"privileged=",
|
||||||
|
"dontinstrument=",
|
||||||
|
"nodebuginfo=",
|
||||||
|
"interruptfn=",
|
||||||
|
"optimizespeed=",
|
||||||
|
"forcealignargpointer=",
|
||||||
|
"dontasan=",
|
||||||
|
"dontubsan=",
|
||||||
|
"donothing=",
|
||||||
|
"nosideeffect=",
|
||||||
|
"unreachable=",,
|
||||||
|
"notpossible=",
|
||||||
|
"thatispacked=",
|
||||||
|
"dontthrow=",
|
||||||
|
"nocallback=",
|
||||||
|
"relegated=",
|
||||||
|
"hidden=",
|
||||||
|
"textstartup=",
|
||||||
|
"initarray=",
|
||||||
|
"returnsnonnull=",
|
||||||
|
"returnspointerwithnoaliases=",
|
||||||
|
"printfesque(x)=",
|
||||||
|
"attributeallocsize(x)=",
|
||||||
|
"returnsaligned(x)=",
|
||||||
|
"attributeallocalign(x)=",
|
||||||
|
"nullterminated(x)="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}"
|
||||||
|
],
|
||||||
|
"cStandard": "gnu17",
|
||||||
|
"compilerPath": "${workspaceFolder}/o/third_party/gcc/bin/x86_64-linux-musl-gcc",
|
||||||
|
"compilerArgs": [
|
||||||
|
"-Wall",
|
||||||
|
"-Werror",
|
||||||
|
"-fdebug-prefix-map=${workspaceFolder}=",
|
||||||
|
"-frecord-gcc-switches",
|
||||||
|
"-Wa,-W",
|
||||||
|
"-Wa,-I.",
|
||||||
|
"-Wa,--noexecstack",
|
||||||
|
"-Og",
|
||||||
|
"-g",
|
||||||
|
"-gdescribe-dies",
|
||||||
|
"-msse3",
|
||||||
|
"-mno-red-zone",
|
||||||
|
"-fno-math-errno",
|
||||||
|
"-fno-trapping-math",
|
||||||
|
"-fno-fp-int-builtin-inexact",
|
||||||
|
"-fno-ident",
|
||||||
|
"-fno-common",
|
||||||
|
"-fno-gnu-unique",
|
||||||
|
"-fstrict-aliasing",
|
||||||
|
"-fstrict-overflow",
|
||||||
|
"-fno-semantic-interposition",
|
||||||
|
"-mno-omit-leaf-frame-pointer",
|
||||||
|
"-fno-jump-tables",
|
||||||
|
"-nostdinc",
|
||||||
|
"-iquote."
|
||||||
|
],
|
||||||
|
"forcedInclude": [
|
||||||
|
"libc/integral/normalize.inc"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"COSMO",
|
||||||
|
"MODE="
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
36
.vscode/settings.json
vendored
36
.vscode/settings.json
vendored
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
"C_Cpp.default.compilerPath": ".cosmocc/3.9.2/bin/aarch64-linux-cosmo-c++",
|
|
||||||
"C_Cpp.default.compilerArgs": [
|
|
||||||
"-nostdinc",
|
|
||||||
"-nostdlib",
|
|
||||||
"-iquote.",
|
|
||||||
"-isystemlibc/isystem",
|
|
||||||
"-isystemthird_party/libcxx",
|
|
||||||
"-includelibc/integral/normalize.inc",
|
|
||||||
"-D_COSMO_SOURCE",
|
|
||||||
"-D__aarch64__"
|
|
||||||
],
|
|
||||||
"[c]": {
|
|
||||||
"editor.tabSize": 2,
|
|
||||||
"editor.insertSpaces": true
|
|
||||||
},
|
|
||||||
"[cpp]": {
|
|
||||||
"editor.tabSize": 2,
|
|
||||||
"editor.insertSpaces": true
|
|
||||||
},
|
|
||||||
"[makefile]": {
|
|
||||||
"editor.tabSize": 8,
|
|
||||||
"editor.insertSpaces": false
|
|
||||||
},
|
|
||||||
"[make]": {
|
|
||||||
"editor.tabSize": 8,
|
|
||||||
"editor.insertSpaces": false
|
|
||||||
},
|
|
||||||
"[assembly]": {
|
|
||||||
"editor.tabSize": 8,
|
|
||||||
"editor.insertSpaces": true
|
|
||||||
},
|
|
||||||
"files.associations": {
|
|
||||||
"log.h": "c"
|
|
||||||
}
|
|
||||||
}
|
|
2
.vscode/vscode.h
vendored
Normal file
2
.vscode/vscode.h
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
#define __VSCODE_INTELLISENSE__ 1
|
||||||
|
#include "libc/integral/normalize.inc"
|
114
CONTRIBUTING.md
114
CONTRIBUTING.md
|
@ -2,77 +2,23 @@
|
||||||
|
|
||||||
We'd love to accept your patches! Please read this guide first.
|
We'd love to accept your patches! Please read this guide first.
|
||||||
|
|
||||||
## Identity Disclosure
|
|
||||||
|
|
||||||
This project does not accept anonymous contributions. Justine Tunney
|
|
||||||
won't merge pull requests from strangers. In order to change the Cosmo
|
|
||||||
codebase, and have your changes be upstreamed, she has to know who you
|
|
||||||
are. You're encouraged to disclose your full name and email address to
|
|
||||||
the public too, by including them in your git commit messages; however
|
|
||||||
that's not a requirement; as we're happy to respect the wishes of
|
|
||||||
contributors who prefer to remain anonymous to the public.
|
|
||||||
|
|
||||||
## Copyright Assignment
|
## Copyright Assignment
|
||||||
|
|
||||||
The first time you send a pull request, you need to send an email to
|
Please send an email to Justine Tunney <jtunney@gmail.com> stating that
|
||||||
Justine Tunney <jtunney@gmail.com> stating that you intend to assign her
|
you intend to assign her the copyright to the changes you contribute to
|
||||||
the copyright to the changes you contribute to Cosmopolitan. It only
|
Cosmopolitan. Please use the same email address you use for git commits
|
||||||
needs to happen once. This only applies to the code you *choose* to
|
which should only contain original source code from you or other people
|
||||||
contribute. The email should be sent from an email address associated
|
who are also assigning copyright. Please note that, if you're employed,
|
||||||
with your identity. Your email should link to your pull request.
|
you may need to get your employer's approval beforehand. If you can not
|
||||||
|
assign copyright due to local laws, then you may alternatively consider
|
||||||
|
disclaiming it using the language in [Unlicense](https://unlicense.org)
|
||||||
|
or [CC-0](http://creativecommons.org/share-your-work/public-domain/cc0)
|
||||||
|
|
||||||
To make things easy, here's an example of a good email you can use:
|
This is important because we can't produce 12kb single-file executables
|
||||||
|
that comply with license requirements if we have to embed lots of them.
|
||||||
> **From**: YOUR NAME (yname@gmail.com)
|
Although that's less of an issue depending on the purpose of the files.
|
||||||
> **To**: Justine Tunney (jtunney@gmail.com)
|
For example, ownership is much less of a concern in the unit test files
|
||||||
> **Subject**: Cosmopolitan Copyright Assignment for YOUR NAME
|
so you're encouraged to put your copyright on those, provided it's ISC.
|
||||||
>
|
|
||||||
> Hi Justine,
|
|
||||||
>
|
|
||||||
> I made my first contribution to Cosmopolitan in
|
|
||||||
> https://github.com/jart/cosmopolitan/pull/XXXX could you please take a
|
|
||||||
> look? I intend to assign you the copyright to the changes I contribute
|
|
||||||
> to Cosmopolitan.
|
|
||||||
>
|
|
||||||
> Thanks!
|
|
||||||
|
|
||||||
Please note that in order to give Justine the copyright, it has to be
|
|
||||||
yours to give in the first place. If you're employed, then you should
|
|
||||||
get your employer's approval to do this beforehand. Even with big
|
|
||||||
companies like Google, this process is quick and painless. Usually we
|
|
||||||
see employers granting authorization in less than one day.
|
|
||||||
|
|
||||||
If you live in a country that doesn't recognize one's ability to assign
|
|
||||||
copyright, then you may alternatively consider disclaiming it using the
|
|
||||||
language in [Unlicense](https://unlicense.org) or
|
|
||||||
[CC-0](http://creativecommons.org/share-your-work/public-domain/cc0).
|
|
||||||
|
|
||||||
If you're checking-in third party code, then you need to have headers at
|
|
||||||
the top of each source file (but never header files) documenting its
|
|
||||||
owners and the code should go in the `third_party/` folder. Every third
|
|
||||||
party project should have a `README.cosmo` file that documents its
|
|
||||||
provenance as well as any local changes you've made.
|
|
||||||
|
|
||||||
## Copyright Policy Exceptions
|
|
||||||
|
|
||||||
### Tests
|
|
||||||
|
|
||||||
You're encoraged to claim ownership of your test code. If you add a new
|
|
||||||
file under the `test/` directory, then you should put your name in the
|
|
||||||
ISC license header at the top of the file. If you add new test cases to
|
|
||||||
an existing unit test file, then you're encouraged to append a line with
|
|
||||||
your name to the existing copyright header of that file.
|
|
||||||
|
|
||||||
### Exceptional Features
|
|
||||||
|
|
||||||
Let's say you discovered a faster better way to implement `log10()` and
|
|
||||||
you want to give it to Cosmopolitan. In cases like this, it really isn't
|
|
||||||
appropriate for Justine to own your code. What you could do instead, is
|
|
||||||
write your own new and improved `log10.c` from scratch, put your name on
|
|
||||||
the top with the ISC license, and then add a `__notice()` directive so
|
|
||||||
that your name will be embedded inside every executable that links the
|
|
||||||
`log10()` function. This will help you get your name out there. Please
|
|
||||||
note you need get approval from Justine each time you want to do this.
|
|
||||||
|
|
||||||
## Style Guide
|
## Style Guide
|
||||||
|
|
||||||
|
@ -83,4 +29,34 @@ clang-format -i -style=file tool/net/redbean.c
|
||||||
```
|
```
|
||||||
|
|
||||||
If you use Emacs this can be automated on save for Cosmopolitan using
|
If you use Emacs this can be automated on save for Cosmopolitan using
|
||||||
[tool/emacs/cosmo-format.el](tool/emacs/cosmo-format.el).
|
[tool/emacs/cosmo-format.el]([tool/emacs/cosmo-format.el]).
|
||||||
|
|
||||||
|
### Source Files
|
||||||
|
|
||||||
|
- Must use include paths relative to the root of the repository
|
||||||
|
- Must have comment at top of file documenting copyright and license
|
||||||
|
- Must have notice embedding if not owned by Justine (exception: tests)
|
||||||
|
- May use language extensions that are supported by both GCC and Clang
|
||||||
|
- Should use Google indentation (otherwise use `/* clang-format off */`)
|
||||||
|
- Should use asm() instead of compiler APIs (exception: ctz, clz, memcpy)
|
||||||
|
|
||||||
|
### Header Files
|
||||||
|
|
||||||
|
- Must not have copyright or license comments
|
||||||
|
- Must have once guards (otherwise change `.h` to `.inc`)
|
||||||
|
- Must be ANSI C89 compatible to be included in the amalgamation header
|
||||||
|
- Must include its dependencies (exception: libc/integral/normalize.inc)
|
||||||
|
- Must not define objects (i.e. `cc -c -xc foo.h` will produce empty `.o`)
|
||||||
|
- Should not use typedefs
|
||||||
|
- Should not use forward declarations
|
||||||
|
- Should not include documentation comments
|
||||||
|
- Should not include parameter names in prototypes
|
||||||
|
- Should not pose problems if included by C++ or Assembly sources
|
||||||
|
- Should not declare non-ANSI code, at all, when the user requests ANSI
|
||||||
|
|
||||||
|
### Build Config
|
||||||
|
|
||||||
|
- Must not write files outside `o/`
|
||||||
|
- Must not communicate with Internet
|
||||||
|
- Must not depend on system libraries
|
||||||
|
- Must not depend on system commands (exception: sh, make, gzip, zip)
|
||||||
|
|
613
Makefile
613
Makefile
|
@ -1,5 +1,5 @@
|
||||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
|
@ -21,23 +21,23 @@
|
||||||
# make -j8 -O MODE=tiny
|
# make -j8 -O MODE=tiny
|
||||||
#
|
#
|
||||||
# # build individual target
|
# # build individual target
|
||||||
# make -j8 -O o//examples/hello
|
# make -j8 -O o//examples/hello.com
|
||||||
# o//examples/hello
|
# o//examples/hello.com
|
||||||
#
|
#
|
||||||
# # view source
|
# # view source
|
||||||
# less examples/hello.c
|
# less examples/hello.c
|
||||||
#
|
#
|
||||||
# # view binary
|
# # view binary
|
||||||
# o//tool/viz/bing o//examples/hello |
|
# o//tool/viz/bing.com o//examples/hello.com |
|
||||||
# o//tool/viz/fold
|
# o//tool/viz/fold.com
|
||||||
#
|
#
|
||||||
# # view transitive closure of legalese
|
# # view transitive closure of legalese
|
||||||
# o//tool/viz/bing -n o//examples/hello |
|
# o//tool/viz/bing.com -n o//examples/hello.com |
|
||||||
# o//tool/viz/fold
|
# o//tool/viz/fold.com
|
||||||
#
|
#
|
||||||
# # basic debugging
|
# # basic debugging
|
||||||
# make -j8 -O MODE=dbg o/dbg/examples/crashreport
|
# make -j8 -O MODE=dbg o/dbg/examples/crashreport.com
|
||||||
# o/examples/crashreport
|
# o/examples/crashreport.com
|
||||||
# less examples/crashreport.c
|
# less examples/crashreport.c
|
||||||
#
|
#
|
||||||
# # extremely tiny binaries
|
# # extremely tiny binaries
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
#
|
#
|
||||||
# TROUBLESHOOTING
|
# TROUBLESHOOTING
|
||||||
#
|
#
|
||||||
# make -j8 -O V=1 o//examples/hello
|
# make -j8 -O V=1 o//examples/hello.com
|
||||||
# make o//examples/life.elf -pn |& less
|
# make o//examples/life.elf -pn |& less
|
||||||
# etc.
|
# etc.
|
||||||
#
|
#
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
#
|
#
|
||||||
# build/config.mk
|
# build/config.mk
|
||||||
|
|
||||||
SHELL = build/bootstrap/cocmd
|
SHELL = build/bootstrap/cocmd.com
|
||||||
MAKEFLAGS += --no-builtin-rules
|
MAKEFLAGS += --no-builtin-rules
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
@ -73,51 +73,22 @@ MODE := $(m)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
COMMA := ,
|
UNAME_M = $(shell uname -m)
|
||||||
PWD := $(shell pwd)
|
UNAME_S = $(shell uname -s)
|
||||||
|
|
||||||
# detect wsl2 running cosmopolitan binaries on the host by checking whether:
|
|
||||||
# - user ran .cosmocc/current/bin/make, in which case make's working directory
|
|
||||||
# is in wsl
|
|
||||||
# - user ran make, in which case cocmd's working directory is in wsl
|
|
||||||
ifneq ($(findstring //wsl.localhost/,$(CURDIR) $(PWD)),)
|
|
||||||
$(warning wsl2 interop is enabled)
|
|
||||||
$(error you need to run sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop')
|
|
||||||
endif
|
|
||||||
|
|
||||||
UNAME_M := $(shell uname -m)
|
|
||||||
UNAME_S := $(shell uname -s)
|
|
||||||
|
|
||||||
# apple still distributes a 17 year old version of gnu make
|
# apple still distributes a 17 year old version of gnu make
|
||||||
ifeq ($(MAKE_VERSION), 3.81)
|
ifeq ($(MAKE_VERSION), 3.81)
|
||||||
$(error please use https://cosmo.zip/pub/cosmos/bin/make)
|
$(error please use build/bootstrap/make.com)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LC_ALL = C
|
# provide instructions to non-linux users on unbundling gcc
|
||||||
SOURCE_DATE_EPOCH = 0
|
ifeq ($(TOOLCHAIN),) # if TOOLCHAIN isn't defined
|
||||||
|
ifeq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","") # if our gcc isn't unbundled
|
||||||
ARFLAGS = rcsD
|
ifneq ($(UNAME_M)-$(UNAME_S), x86_64-Linux) # if this is not amd64 linux
|
||||||
ZFLAGS ?=
|
$(error you need to download https://justine.lol/cosmocc-0.0.12.zip and unzip it inside the cosmo directory)
|
||||||
XARGS ?= xargs -P4 -rs8000
|
endif
|
||||||
DOT ?= dot
|
endif
|
||||||
CLANG = clang
|
endif
|
||||||
TMPDIR = o/tmp
|
|
||||||
AR = $(BOOTSTRAP)/ar.ape
|
|
||||||
CP = $(BOOTSTRAP)/cp.ape
|
|
||||||
RM = $(BOOTSTRAP)/rm.ape -f
|
|
||||||
GZIP = $(BOOTSTRAP)/gzip.ape
|
|
||||||
ECHO = $(BOOTSTRAP)/echo.ape
|
|
||||||
CHMOD = $(BOOTSTRAP)/chmod.ape
|
|
||||||
TOUCH = $(BOOTSTRAP)/touch.ape
|
|
||||||
PKG = $(BOOTSTRAP)/package.ape
|
|
||||||
MKDEPS = $(BOOTSTRAP)/mkdeps
|
|
||||||
ZIPOBJ = $(BOOTSTRAP)/zipobj
|
|
||||||
ZIPCOPY = $(BOOTSTRAP)/zipcopy
|
|
||||||
PECHECK = $(BOOTSTRAP)/pecheck
|
|
||||||
FIXUPOBJ = $(BOOTSTRAP)/fixupobj
|
|
||||||
OBJBINCOPY = $(BOOTSTRAP)/objbincopy
|
|
||||||
MKDIR = $(BOOTSTRAP)/mkdir.ape -p
|
|
||||||
COMPILE = $(BOOTSTRAP)/compile.ape -V9 -M2048m -P8192 $(QUOTA)
|
|
||||||
|
|
||||||
# the default build modes is empty string
|
# the default build modes is empty string
|
||||||
# on x86_64 hosts, MODE= is the same as MODE=x86_64
|
# on x86_64 hosts, MODE= is the same as MODE=x86_64
|
||||||
|
@ -131,52 +102,11 @@ MODE := aarch64
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(findstring aarch64,$(MODE)),)
|
|
||||||
ARCH = aarch64
|
|
||||||
HOSTS ?= pi pi5 studio freebsdarm
|
|
||||||
else
|
|
||||||
ARCH = x86_64
|
|
||||||
HOSTS ?= freebsd rhel7 xnu openbsd netbsd win10 luna
|
|
||||||
endif
|
|
||||||
|
|
||||||
ZIPOBJ_FLAGS += -a$(ARCH)
|
|
||||||
|
|
||||||
export ADDR2LINE
|
|
||||||
export LC_ALL
|
|
||||||
export MKDIR
|
|
||||||
export MODE
|
|
||||||
export SOURCE_DATE_EPOCH
|
|
||||||
export TMPDIR
|
|
||||||
|
|
||||||
COSMOCC = .cosmocc/3.9.2
|
|
||||||
BOOTSTRAP = $(COSMOCC)/bin
|
|
||||||
TOOLCHAIN = $(COSMOCC)/bin/$(ARCH)-linux-cosmo-
|
|
||||||
DOWNLOAD := $(shell build/download-cosmocc.sh $(COSMOCC) 3.9.2 f4ff13af65fcd309f3f1cfd04275996fb7f72a4897726628a8c9cf732e850193)
|
|
||||||
|
|
||||||
IGNORE := $(shell $(MKDIR) $(TMPDIR))
|
|
||||||
|
|
||||||
AS = $(TOOLCHAIN)as
|
|
||||||
CC = $(TOOLCHAIN)gcc
|
|
||||||
CXX = $(TOOLCHAIN)g++
|
|
||||||
CXXFILT = $(TOOLCHAIN)c++filt
|
|
||||||
LD = $(TOOLCHAIN)ld.bfd
|
|
||||||
NM = $(TOOLCHAIN)nm
|
|
||||||
GCC = $(TOOLCHAIN)gcc
|
|
||||||
STRIP = $(TOOLCHAIN)strip
|
|
||||||
OBJCOPY = $(TOOLCHAIN)objcopy
|
|
||||||
OBJDUMP = $(TOOLCHAIN)objdump
|
|
||||||
ifneq ($(wildcard $(PWD)/$(TOOLCHAIN)addr2line),)
|
|
||||||
ADDR2LINE = $(PWD)/$(TOOLCHAIN)addr2line
|
|
||||||
else
|
|
||||||
ADDR2LINE = $(TOOLCHAIN)addr2line
|
|
||||||
endif
|
|
||||||
|
|
||||||
# primary build rules
|
# primary build rules
|
||||||
all: o
|
all: o
|
||||||
o: o/$(MODE)
|
o: o/$(MODE)
|
||||||
o/$(MODE): \
|
o/$(MODE): \
|
||||||
o/$(MODE)/ape \
|
o/$(MODE)/ape \
|
||||||
o/$(MODE)/ctl \
|
|
||||||
o/$(MODE)/dsp \
|
o/$(MODE)/dsp \
|
||||||
o/$(MODE)/net \
|
o/$(MODE)/net \
|
||||||
o/$(MODE)/libc \
|
o/$(MODE)/libc \
|
||||||
|
@ -185,12 +115,7 @@ o/$(MODE): \
|
||||||
o/$(MODE)/examples \
|
o/$(MODE)/examples \
|
||||||
o/$(MODE)/third_party
|
o/$(MODE)/third_party
|
||||||
|
|
||||||
# TODO(jart): Make Emacs `C-c C-c` shortcut not need this.
|
# check if we're using o//third_party/make/make.com
|
||||||
.PHONY: o/$(MODE)/ o/$(MODE)/.
|
|
||||||
o/$(MODE)/: o/$(MODE)
|
|
||||||
o/$(MODE)/.: o/$(MODE)
|
|
||||||
|
|
||||||
# check if we're using o//third_party/make/make
|
|
||||||
# we added sandboxing to guarantee cosmo's makefile is hermetic
|
# we added sandboxing to guarantee cosmo's makefile is hermetic
|
||||||
# it also shaves away 200ms of startup latency with native $(uniq)
|
# it also shaves away 200ms of startup latency with native $(uniq)
|
||||||
ifneq ($(LANDLOCKMAKE_VERSION),)
|
ifneq ($(LANDLOCKMAKE_VERSION),)
|
||||||
|
@ -200,7 +125,7 @@ $(warning please run ape/apeinstall.sh if you intend to use landlock make)
|
||||||
$(shell sleep .5)
|
$(shell sleep .5)
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
ifneq ($(TOOLCHAIN),)
|
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
|
||||||
.STRICT = 1
|
.STRICT = 1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
@ -209,9 +134,10 @@ endif
|
||||||
.UNVEIL += \
|
.UNVEIL += \
|
||||||
libc/integral \
|
libc/integral \
|
||||||
libc/stdbool.h \
|
libc/stdbool.h \
|
||||||
|
libc/disclaimer.inc \
|
||||||
rwc:/dev/shm \
|
rwc:/dev/shm \
|
||||||
rx:.cosmocc \
|
|
||||||
rx:build/bootstrap \
|
rx:build/bootstrap \
|
||||||
|
rx:o/third_party/gcc \
|
||||||
r:build/portcosmo.h \
|
r:build/portcosmo.h \
|
||||||
/proc/stat \
|
/proc/stat \
|
||||||
rw:/dev/null \
|
rw:/dev/null \
|
||||||
|
@ -232,163 +158,149 @@ include build/definitions.mk # ├──META
|
||||||
include build/config.mk # │ You can build
|
include build/config.mk # │ You can build
|
||||||
include build/rules.mk # │ You can topologically order
|
include build/rules.mk # │ You can topologically order
|
||||||
include build/online.mk #─┘
|
include build/online.mk #─┘
|
||||||
include libc/nexgen32e/BUILD.mk #─┐
|
include libc/nexgen32e/nexgen32e.mk #─┐
|
||||||
include libc/sysv/BUILD.mk # ├──SYSTEM SUPPORT
|
include libc/sysv/sysv.mk # ├──SYSTEM SUPPORT
|
||||||
include libc/nt/BUILD.mk # │ You can do math
|
include libc/nt/nt.mk # │ You can do math
|
||||||
include libc/intrin/BUILD.mk # │ You can use the stack
|
include libc/intrin/intrin.mk # │ You can use the stack
|
||||||
include third_party/compiler_rt/BUILD.mk # │ You can manipulate arrays
|
include third_party/compiler_rt/compiler_rt.mk # │ You can manipulate arrays
|
||||||
include libc/tinymath/BUILD.mk # │ You can issue raw system calls
|
include libc/tinymath/tinymath.mk # │ You can issue raw system calls
|
||||||
include libc/str/BUILD.mk # │
|
include libc/str/str.mk # │
|
||||||
include third_party/xed/BUILD.mk # │
|
include third_party/xed/xed.mk # │
|
||||||
include third_party/puff/BUILD.mk # │
|
include third_party/puff/puff.mk # │
|
||||||
include libc/elf/BUILD.mk # │
|
include libc/elf/elf.mk # │
|
||||||
include ape/BUILD.mk # │
|
include ape/ape.mk # │
|
||||||
include libc/fmt/BUILD.mk # │
|
include libc/fmt/fmt.mk # │
|
||||||
include libc/vga/BUILD.mk # │
|
include libc/vga/vga.mk #─┘
|
||||||
include libc/irq/BUILD.mk #─┘
|
include libc/calls/calls.mk #─┐
|
||||||
include libc/calls/BUILD.mk #─┐
|
include third_party/nsync/nsync.mk # │
|
||||||
include libc/irq/BUILD.mk # ├──SYSTEMS RUNTIME
|
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
|
||||||
include third_party/nsync/BUILD.mk # │ You can issue system calls
|
include third_party/double-conversion/dc.mk # │ You can issue system calls
|
||||||
include libc/runtime/BUILD.mk # │
|
include libc/crt/crt.mk # │
|
||||||
include libc/crt/BUILD.mk # │
|
include third_party/dlmalloc/dlmalloc.mk #─┘
|
||||||
include third_party/dlmalloc/BUILD.mk #─┘
|
include libc/mem/mem.mk #─┐
|
||||||
include libc/mem/BUILD.mk #─┐
|
include third_party/gdtoa/gdtoa.mk # ├──DYNAMIC RUNTIME
|
||||||
include third_party/gdtoa/BUILD.mk # ├──DYNAMIC RUNTIME
|
include third_party/nsync/mem/mem.mk # │ You can now use stdio
|
||||||
include third_party/nsync/mem/BUILD.mk # │ You can now use stdio
|
include libc/proc/proc.mk # │ You can now use threads
|
||||||
include libc/proc/BUILD.mk # │ You can now use threads
|
include libc/thread/thread.mk # │ You can now use processes
|
||||||
include libc/dlopen/BUILD.mk # │ You can now use processes
|
include tool/hello/hello.mk # │ You can finally call malloc()
|
||||||
include libc/thread/BUILD.mk # │ You can finally call malloc()
|
include third_party/zlib/zlib.mk # │
|
||||||
include third_party/zlib/BUILD.mk # │
|
include libc/stdio/stdio.mk # │
|
||||||
include libc/stdio/BUILD.mk # │
|
include libc/time/time.mk # │
|
||||||
include tool/hello/BUILD.mk # │
|
include net/net.mk # │
|
||||||
include third_party/tz/BUILD.mk # │
|
include third_party/vqsort/vqsort.mk # │
|
||||||
include net/BUILD.mk # │
|
include libc/log/log.mk # │
|
||||||
include third_party/vqsort/BUILD.mk # │
|
include third_party/getopt/getopt.mk # │
|
||||||
include libc/log/BUILD.mk # │
|
include third_party/bzip2/bzip2.mk # │
|
||||||
include third_party/getopt/BUILD.mk # │
|
include dsp/core/core.mk # │
|
||||||
include third_party/bzip2/BUILD.mk # │
|
include third_party/musl/musl.mk # │
|
||||||
include dsp/core/BUILD.mk # │
|
include libc/x/x.mk # │
|
||||||
include third_party/zlib/gz/BUILD.mk # │
|
include third_party/stb/stb.mk # │
|
||||||
include third_party/intel/BUILD.mk # │
|
include dsp/scale/scale.mk # │
|
||||||
include third_party/aarch64/BUILD.mk # │
|
include dsp/mpeg/mpeg.mk # │
|
||||||
include libc/BUILD.mk #─┘
|
include dsp/dsp.mk # │
|
||||||
include libc/sock/BUILD.mk #─┐
|
include third_party/zlib/gz/gz.mk # │
|
||||||
include net/http/BUILD.mk # ├──ONLINE RUNTIME
|
include third_party/intel/intel.mk # │
|
||||||
include third_party/musl/BUILD.mk # │ You can communicate with the network
|
include third_party/aarch64/aarch64.mk # │
|
||||||
include third_party/regex/BUILD.mk # │
|
include libc/libc.mk #─┘
|
||||||
include third_party/tr/BUILD.mk # │
|
include libc/sock/sock.mk #─┐
|
||||||
include third_party/sed/BUILD.mk # │
|
include dsp/tty/tty.mk # ├──ONLINE RUNTIME
|
||||||
include libc/system/BUILD.mk # │
|
include libc/dns/dns.mk # │ You can communicate with the network
|
||||||
include libc/x/BUILD.mk # │
|
include net/http/http.mk # │
|
||||||
include dsp/scale/BUILD.mk # │
|
include third_party/mbedtls/mbedtls.mk # │
|
||||||
include dsp/mpeg/BUILD.mk # │
|
include third_party/libcxx/libcxx.mk # │
|
||||||
include dsp/tty/BUILD.mk # │
|
include third_party/ggml/ggml.mk # │
|
||||||
include dsp/audio/BUILD.mk # │
|
include third_party/radpajama/radpajama.mk # │
|
||||||
include dsp/prog/BUILD.mk # │
|
include net/https/https.mk # │
|
||||||
include dsp/BUILD.mk # │
|
include third_party/regex/regex.mk #─┘
|
||||||
include third_party/stb/BUILD.mk # │
|
include third_party/tidy/tidy.mk
|
||||||
include third_party/mbedtls/BUILD.mk # │
|
include third_party/third_party.mk
|
||||||
include third_party/ncurses/BUILD.mk # │
|
include third_party/nsync/testing/testing.mk
|
||||||
include third_party/readline/BUILD.mk # │
|
include libc/testlib/testlib.mk
|
||||||
include third_party/libunwind/BUILD.mk # |
|
include tool/viz/lib/vizlib.mk
|
||||||
include third_party/libcxxabi/BUILD.mk # |
|
include tool/args/args.mk
|
||||||
include third_party/double-conversion/BUILD.mk # │
|
include test/tool/args/test.mk
|
||||||
include ctl/BUILD.mk # │
|
include third_party/linenoise/linenoise.mk
|
||||||
include third_party/libcxx/BUILD.mk # │
|
include third_party/maxmind/maxmind.mk
|
||||||
include third_party/openmp/BUILD.mk # │
|
include net/finger/finger.mk
|
||||||
include third_party/pcre/BUILD.mk # │
|
include third_party/double-conversion/test/test.mk
|
||||||
include third_party/less/BUILD.mk # │
|
include third_party/lua/lua.mk
|
||||||
include net/https/BUILD.mk #─┘
|
include third_party/tree/tree.mk
|
||||||
include third_party/tidy/BUILD.mk
|
include third_party/zstd/zstd.mk
|
||||||
include third_party/BUILD.mk
|
include third_party/tr/tr.mk
|
||||||
include third_party/nsync/testing/BUILD.mk
|
include third_party/sed/sed.mk
|
||||||
include libc/testlib/BUILD.mk
|
include third_party/awk/awk.mk
|
||||||
include tool/viz/lib/BUILD.mk
|
include third_party/hiredis/hiredis.mk
|
||||||
include tool/args/BUILD.mk
|
include third_party/make/make.mk
|
||||||
include test/math/BUILD.mk
|
include third_party/ctags/ctags.mk
|
||||||
include test/posix/BUILD.mk
|
include third_party/finger/finger.mk
|
||||||
include test/ctl/BUILD.mk
|
include third_party/argon2/argon2.mk
|
||||||
include test/libcxx/BUILD.mk
|
include third_party/smallz4/smallz4.mk
|
||||||
include test/tool/args/BUILD.mk
|
include third_party/sqlite3/sqlite3.mk
|
||||||
include third_party/linenoise/BUILD.mk
|
include third_party/mbedtls/test/test.mk
|
||||||
include third_party/maxmind/BUILD.mk
|
include third_party/quickjs/quickjs.mk
|
||||||
include net/finger/BUILD.mk
|
include third_party/lz4cli/lz4cli.mk
|
||||||
include third_party/double-conversion/test/BUILD.mk
|
include third_party/zip/zip.mk
|
||||||
include third_party/lua/BUILD.mk
|
include third_party/xxhash/xxhash.mk
|
||||||
include third_party/tree/BUILD.mk
|
include third_party/unzip/unzip.mk
|
||||||
include third_party/zstd/BUILD.mk
|
include tool/build/lib/buildlib.mk
|
||||||
include third_party/awk/BUILD.mk
|
include third_party/chibicc/chibicc.mk
|
||||||
include third_party/hiredis/BUILD.mk
|
include third_party/chibicc/test/test.mk
|
||||||
include third_party/make/BUILD.mk
|
include third_party/python/python.mk
|
||||||
include third_party/ctags/BUILD.mk
|
include tool/build/build.mk
|
||||||
include third_party/finger/BUILD.mk
|
include tool/curl/curl.mk
|
||||||
include third_party/argon2/BUILD.mk
|
include third_party/qemu/qemu.mk
|
||||||
include third_party/smallz4/BUILD.mk
|
include examples/examples.mk
|
||||||
include third_party/sqlite3/BUILD.mk
|
include examples/pyapp/pyapp.mk
|
||||||
include third_party/mbedtls/test/BUILD.mk
|
include examples/pylife/pylife.mk
|
||||||
include third_party/lz4cli/BUILD.mk
|
include tool/decode/lib/decodelib.mk
|
||||||
include third_party/zip/BUILD.mk
|
include tool/decode/decode.mk
|
||||||
include third_party/xxhash/BUILD.mk
|
include tool/lambda/lib/lib.mk
|
||||||
include third_party/unzip/BUILD.mk
|
include tool/lambda/lambda.mk
|
||||||
include tool/build/lib/BUILD.mk
|
include tool/plinko/lib/lib.mk
|
||||||
include third_party/chibicc/BUILD.mk
|
include tool/plinko/plinko.mk
|
||||||
include third_party/chibicc/test/BUILD.mk
|
include test/tool/plinko/test.mk
|
||||||
include third_party/python/BUILD.mk
|
include tool/net/net.mk
|
||||||
include tool/build/BUILD.mk
|
include tool/viz/viz.mk
|
||||||
include tool/curl/BUILD.mk
|
include tool/tool.mk
|
||||||
include third_party/qemu/BUILD.mk
|
include net/turfwar/turfwar.mk
|
||||||
include third_party/libcxxabi/test/BUILD.mk
|
include test/libc/tinymath/test.mk
|
||||||
include examples/BUILD.mk
|
include test/libc/intrin/test.mk
|
||||||
include examples/pyapp/BUILD.mk
|
include test/libc/mem/test.mk
|
||||||
include examples/pylife/BUILD.mk
|
include test/libc/nexgen32e/test.mk
|
||||||
include tool/decode/lib/BUILD.mk
|
include test/libc/runtime/test.mk
|
||||||
include tool/decode/BUILD.mk
|
include test/libc/thread/test.mk
|
||||||
include tool/lambda/lib/BUILD.mk
|
include test/libc/sock/test.mk
|
||||||
include tool/lambda/BUILD.mk
|
include test/libc/str/test.mk
|
||||||
include tool/plinko/lib/BUILD.mk
|
include test/libc/log/test.mk
|
||||||
include tool/plinko/BUILD.mk
|
include test/libc/str/test.mk
|
||||||
include test/tool/plinko/BUILD.mk
|
include test/libc/calls/test.mk
|
||||||
include tool/net/BUILD.mk
|
include test/libc/x/test.mk
|
||||||
include tool/viz/BUILD.mk
|
include test/libc/xed/test.mk
|
||||||
include tool/BUILD.mk
|
include test/libc/fmt/test.mk
|
||||||
include net/turfwar/BUILD.mk
|
include test/libc/dns/test.mk
|
||||||
include test/libc/tinymath/BUILD.mk
|
include test/libc/time/test.mk
|
||||||
include test/libc/intrin/BUILD.mk
|
include test/libc/proc/test.mk
|
||||||
include test/libc/mem/BUILD.mk
|
include test/libc/stdio/test.mk
|
||||||
include test/libc/nexgen32e/BUILD.mk
|
include test/libc/release/test.mk
|
||||||
include test/libc/runtime/BUILD.mk
|
include test/libc/test.mk
|
||||||
include test/libc/thread/BUILD.mk
|
include test/net/http/test.mk
|
||||||
include test/libc/sock/BUILD.mk
|
include test/net/https/test.mk
|
||||||
include test/libc/str/BUILD.mk
|
include test/net/finger/test.mk
|
||||||
include test/libc/log/BUILD.mk
|
include test/net/test.mk
|
||||||
include test/libc/str/BUILD.mk
|
include test/tool/build/lib/test.mk
|
||||||
include test/libc/calls/BUILD.mk
|
include test/tool/build/test.mk
|
||||||
include test/libc/x/BUILD.mk
|
include test/tool/viz/lib/test.mk
|
||||||
include test/libc/xed/BUILD.mk
|
include test/tool/viz/test.mk
|
||||||
include test/libc/fmt/BUILD.mk
|
include test/tool/net/test.mk
|
||||||
include test/libc/time/BUILD.mk
|
include test/tool/test.mk
|
||||||
include test/libc/proc/BUILD.mk
|
include test/dsp/core/test.mk
|
||||||
include test/libc/stdio/BUILD.mk
|
include test/dsp/scale/test.mk
|
||||||
include test/libc/system/BUILD.mk
|
include test/dsp/tty/test.mk
|
||||||
include test/libc/BUILD.mk
|
include test/dsp/test.mk
|
||||||
include test/net/http/BUILD.mk
|
include examples/package/lib/build.mk
|
||||||
include test/net/https/BUILD.mk
|
include examples/package/build.mk
|
||||||
include test/net/finger/BUILD.mk
|
|
||||||
include test/net/BUILD.mk
|
|
||||||
include test/tool/build/lib/BUILD.mk
|
|
||||||
include test/tool/build/BUILD.mk
|
|
||||||
include test/tool/viz/lib/BUILD.mk
|
|
||||||
include test/tool/viz/BUILD.mk
|
|
||||||
include test/tool/net/BUILD.mk
|
|
||||||
include test/tool/BUILD.mk
|
|
||||||
include test/dsp/core/BUILD.mk
|
|
||||||
include test/dsp/scale/BUILD.mk
|
|
||||||
include test/dsp/tty/BUILD.mk
|
|
||||||
include test/dsp/BUILD.mk
|
|
||||||
include examples/package/lib/BUILD.mk
|
|
||||||
include examples/package/BUILD.mk
|
|
||||||
#-φ-examples/package/new.sh
|
#-φ-examples/package/new.sh
|
||||||
include test/BUILD.mk
|
include test/test.mk
|
||||||
|
|
||||||
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
|
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
|
||||||
SRCS := $(foreach x,$(PKGS),$($(x)_SRCS))
|
SRCS := $(foreach x,$(PKGS),$($(x)_SRCS))
|
||||||
|
@ -414,7 +326,7 @@ o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(
|
||||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x)))) $(INCS) $(INCS)
|
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x)))) $(INCS) $(INCS)
|
||||||
$(file >$@,$(INCS))
|
$(file >$@,$(INCS))
|
||||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS)
|
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS)
|
||||||
$(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -s -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt
|
$(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt
|
||||||
|
|
||||||
o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||||
|
@ -422,87 +334,77 @@ o/$(MODE)/hdrs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS
|
||||||
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
||||||
|
|
||||||
TAGS: private .UNSANDBOXED = 1
|
TAGS: private .UNSANDBOXED = 1
|
||||||
TAGS: o/$(MODE)/srcs-old.txt $(SRCS) #o/$(MODE)/third_party/ctags/ctags
|
TAGS: o/$(MODE)/srcs-old.txt $(SRCS) #o/$(MODE)/third_party/ctags/ctags.com
|
||||||
@$(RM) $@
|
@$(RM) $@
|
||||||
@o/$(MODE)/third_party/ctags/ctags $(TAGSFLAGS) -L $< -o $@
|
@o/$(MODE)/third_party/ctags/ctags.com $(TAGSFLAGS) -L $< -o $@
|
||||||
|
|
||||||
HTAGS: private .UNSANDBOXED = 1
|
HTAGS: private .UNSANDBOXED = 1
|
||||||
HTAGS: o/$(MODE)/hdrs-old.txt $(filter-out third_party/libcxx/%,$(HDRS)) #o/$(MODE)/third_party/ctags/ctags
|
HTAGS: o/$(MODE)/hdrs-old.txt $(filter-out third_party/libcxx/%,$(HDRS)) #o/$(MODE)/third_party/ctags/ctags.com
|
||||||
@$(RM) $@
|
@$(RM) $@
|
||||||
@build/htags o/$(MODE)/third_party/ctags/ctags -L $< -o $@
|
@build/htags o/$(MODE)/third_party/ctags/ctags.com -L $< -o $@
|
||||||
|
|
||||||
loc: private .UNSANDBOXED = 1
|
loc: private .UNSANDBOXED = 1
|
||||||
loc: o/$(MODE)/tool/build/summy
|
loc: o/$(MODE)/tool/build/summy.com
|
||||||
find -name \*.h -or -name \*.hpp -or -name \*.c -or -name \*.cc -or -name \*.cpp -or -name \*.S -or -name \*.mk | \
|
find -name \*.h -or -name \*.c -or -name \*.S | \
|
||||||
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
|
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
|
||||||
|
|
||||||
COSMOPOLITAN = \
|
# PLEASE: MAINTAIN TOPOLOGICAL ORDER
|
||||||
CTL \
|
# FROM HIGHEST LEVEL TO LOWEST LEVEL
|
||||||
DSP_AUDIO \
|
COSMOPOLITAN_OBJECTS = \
|
||||||
LIBC_CALLS \
|
|
||||||
LIBC_DLOPEN \
|
|
||||||
LIBC_ELF \
|
|
||||||
LIBC_FMT \
|
|
||||||
LIBC_INTRIN \
|
|
||||||
LIBC_IRQ \
|
|
||||||
LIBC_LOG \
|
|
||||||
LIBC_MEM \
|
|
||||||
LIBC_NEXGEN32E \
|
|
||||||
LIBC_NT_ADVAPI32 \
|
|
||||||
LIBC_NT_BCRYPTPRIMITIVES \
|
|
||||||
LIBC_NT_COMDLG32 \
|
|
||||||
LIBC_NT_GDI32 \
|
|
||||||
LIBC_NT_IPHLPAPI \
|
|
||||||
LIBC_NT_KERNEL32 \
|
|
||||||
LIBC_NT_NTDLL \
|
|
||||||
LIBC_NT_PDH \
|
|
||||||
LIBC_NT_POWRPROF \
|
|
||||||
LIBC_NT_PSAPI \
|
|
||||||
LIBC_NT_REALTIME \
|
|
||||||
LIBC_NT_SHELL32 \
|
|
||||||
LIBC_NT_SYNCHRONIZATION \
|
|
||||||
LIBC_NT_USER32 \
|
|
||||||
LIBC_NT_WS2_32 \
|
|
||||||
LIBC_PROC \
|
|
||||||
LIBC_RUNTIME \
|
|
||||||
LIBC_SOCK \
|
|
||||||
LIBC_STDIO \
|
|
||||||
LIBC_STR \
|
|
||||||
LIBC_SYSTEM \
|
|
||||||
LIBC_SYSV \
|
|
||||||
LIBC_SYSV_CALLS \
|
|
||||||
LIBC_THREAD \
|
|
||||||
LIBC_TINYMATH \
|
|
||||||
LIBC_VGA \
|
|
||||||
LIBC_X \
|
|
||||||
NET_HTTP \
|
|
||||||
THIRD_PARTY_COMPILER_RT \
|
|
||||||
THIRD_PARTY_DLMALLOC \
|
|
||||||
THIRD_PARTY_DOUBLECONVERSION \
|
|
||||||
THIRD_PARTY_GDTOA \
|
|
||||||
THIRD_PARTY_GETOPT \
|
|
||||||
THIRD_PARTY_LIBCXXABI \
|
|
||||||
THIRD_PARTY_LIBUNWIND \
|
|
||||||
THIRD_PARTY_MUSL \
|
|
||||||
THIRD_PARTY_NSYNC \
|
|
||||||
THIRD_PARTY_NSYNC_MEM \
|
|
||||||
THIRD_PARTY_OPENMP \
|
|
||||||
THIRD_PARTY_PUFF \
|
|
||||||
THIRD_PARTY_REGEX \
|
|
||||||
THIRD_PARTY_TZ \
|
|
||||||
THIRD_PARTY_XED \
|
|
||||||
THIRD_PARTY_ZLIB \
|
|
||||||
THIRD_PARTY_ZLIB_GZ \
|
|
||||||
TOOL_ARGS \
|
TOOL_ARGS \
|
||||||
|
NET_HTTP \
|
||||||
|
LIBC_DNS \
|
||||||
|
LIBC_SOCK \
|
||||||
|
LIBC_NT_WS2_32 \
|
||||||
|
LIBC_NT_IPHLPAPI \
|
||||||
|
LIBC_X \
|
||||||
|
THIRD_PARTY_GETOPT \
|
||||||
|
LIBC_LOG \
|
||||||
|
LIBC_TIME \
|
||||||
|
THIRD_PARTY_MUSL \
|
||||||
|
THIRD_PARTY_ZLIB_GZ \
|
||||||
|
LIBC_STDIO \
|
||||||
|
THIRD_PARTY_GDTOA \
|
||||||
|
THIRD_PARTY_REGEX \
|
||||||
|
LIBC_THREAD \
|
||||||
|
LIBC_PROC \
|
||||||
|
THIRD_PARTY_NSYNC_MEM \
|
||||||
|
LIBC_MEM \
|
||||||
|
THIRD_PARTY_DLMALLOC \
|
||||||
|
LIBC_RUNTIME \
|
||||||
|
THIRD_PARTY_NSYNC \
|
||||||
|
LIBC_ELF \
|
||||||
|
LIBC_CALLS \
|
||||||
|
LIBC_SYSV_CALLS \
|
||||||
|
LIBC_VGA \
|
||||||
|
LIBC_NT_PSAPI \
|
||||||
|
LIBC_NT_POWRPROF \
|
||||||
|
LIBC_NT_PDH \
|
||||||
|
LIBC_NT_GDI32 \
|
||||||
|
LIBC_NT_COMDLG32 \
|
||||||
|
LIBC_NT_USER32 \
|
||||||
|
LIBC_NT_NTDLL \
|
||||||
|
LIBC_NT_ADVAPI32 \
|
||||||
|
LIBC_NT_SYNCHRONIZATION \
|
||||||
|
LIBC_FMT \
|
||||||
|
THIRD_PARTY_ZLIB \
|
||||||
|
THIRD_PARTY_PUFF \
|
||||||
|
THIRD_PARTY_COMPILER_RT \
|
||||||
|
LIBC_TINYMATH \
|
||||||
|
THIRD_PARTY_XED \
|
||||||
|
LIBC_STR \
|
||||||
|
LIBC_SYSV \
|
||||||
|
LIBC_INTRIN \
|
||||||
|
LIBC_NT_KERNEL32 \
|
||||||
|
LIBC_NEXGEN32E
|
||||||
|
|
||||||
COSMOPOLITAN_H_PKGS = \
|
COSMOPOLITAN_HEADERS = \
|
||||||
APE \
|
APE \
|
||||||
DSP_AUDIO \
|
|
||||||
LIBC \
|
LIBC \
|
||||||
LIBC_CALLS \
|
LIBC_CALLS \
|
||||||
|
LIBC_DNS \
|
||||||
LIBC_ELF \
|
LIBC_ELF \
|
||||||
LIBC_FMT \
|
LIBC_FMT \
|
||||||
LIBC_DLOPEN \
|
|
||||||
LIBC_INTRIN \
|
LIBC_INTRIN \
|
||||||
LIBC_LOG \
|
LIBC_LOG \
|
||||||
LIBC_MEM \
|
LIBC_MEM \
|
||||||
|
@ -517,6 +419,7 @@ COSMOPOLITAN_H_PKGS = \
|
||||||
LIBC_STR \
|
LIBC_STR \
|
||||||
LIBC_SYSV \
|
LIBC_SYSV \
|
||||||
LIBC_THREAD \
|
LIBC_THREAD \
|
||||||
|
LIBC_TIME \
|
||||||
LIBC_TINYMATH \
|
LIBC_TINYMATH \
|
||||||
LIBC_X \
|
LIBC_X \
|
||||||
LIBC_VGA \
|
LIBC_VGA \
|
||||||
|
@ -526,43 +429,30 @@ COSMOPOLITAN_H_PKGS = \
|
||||||
THIRD_PARTY_GDTOA \
|
THIRD_PARTY_GDTOA \
|
||||||
THIRD_PARTY_GETOPT \
|
THIRD_PARTY_GETOPT \
|
||||||
THIRD_PARTY_MUSL \
|
THIRD_PARTY_MUSL \
|
||||||
THIRD_PARTY_ZLIB \
|
|
||||||
THIRD_PARTY_ZLIB_GZ \
|
|
||||||
THIRD_PARTY_REGEX
|
THIRD_PARTY_REGEX
|
||||||
|
|
||||||
COSMOCC_PKGS = \
|
|
||||||
$(COSMOPOLITAN_H_PKGS) \
|
|
||||||
CTL \
|
|
||||||
THIRD_PARTY_AARCH64 \
|
|
||||||
THIRD_PARTY_LIBCXX \
|
|
||||||
THIRD_PARTY_LIBCXXABI \
|
|
||||||
THIRD_PARTY_LIBUNWIND \
|
|
||||||
THIRD_PARTY_OPENMP \
|
|
||||||
THIRD_PARTY_INTEL
|
|
||||||
|
|
||||||
o/$(MODE)/cosmopolitan.a: \
|
o/$(MODE)/cosmopolitan.a: \
|
||||||
$(call reverse,$(call uniq,$(foreach x,$(COSMOPOLITAN),$($(x)))))
|
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
|
||||||
|
|
||||||
COSMOCC_HDRS = \
|
o/cosmopolitan.h: \
|
||||||
$(wildcard libc/integral/*) \
|
o/$(MODE)/tool/build/rollup.com \
|
||||||
$(foreach x,$(COSMOCC_PKGS),$($(x)_HDRS)) \
|
libc/integral/normalize.inc \
|
||||||
$(foreach x,$(COSMOCC_PKGS),$($(x)_INCS))
|
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)) \
|
||||||
|
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_INCS))
|
||||||
o/cosmocc.h.txt: Makefile libc $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x)))) $(HDRS) $(INCS)
|
$(file >$(TMPDIR)/$(subst /,_,$@),libc/integral/normalize.inc $(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)))
|
||||||
$(file >$@, $(call uniq,$(COSMOCC_HDRS)))
|
@$(ECHO) '#ifndef __STRICT_ANSI__' >$@
|
||||||
|
@$(ECHO) '#define _COSMO_SOURCE' >>$@
|
||||||
COSMOPOLITAN_H_ROOT_HDRS = \
|
@$(ECHO) '#endif' >>$@
|
||||||
libc/integral/normalize.inc \
|
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >>$@
|
||||||
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS))
|
|
||||||
|
|
||||||
o/cosmopolitan.html: private .UNSANDBOXED = 1
|
o/cosmopolitan.html: private .UNSANDBOXED = 1
|
||||||
o/cosmopolitan.html: \
|
o/cosmopolitan.html: \
|
||||||
o/$(MODE)/third_party/chibicc/chibicc.dbg \
|
o/$(MODE)/third_party/chibicc/chibicc.com.dbg \
|
||||||
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \
|
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \
|
||||||
$(filter-out %.cpp,$(filter-out %.cc,$(SRCS))) \
|
$(SRCS) \
|
||||||
$(HDRS)
|
$(HDRS)
|
||||||
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.cpp,$(filter-out %.cc,$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))))
|
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))
|
||||||
o/$(MODE)/third_party/chibicc/chibicc.dbg -J \
|
o/$(MODE)/third_party/chibicc/chibicc.com.dbg -J \
|
||||||
-fno-common -include libc/integral/normalize.inc -o $@ \
|
-fno-common -include libc/integral/normalize.inc -o $@ \
|
||||||
-DCOSMO @$(TMPDIR)/$(subst /,_,$@)
|
-DCOSMO @$(TMPDIR)/$(subst /,_,$@)
|
||||||
|
|
||||||
|
@ -576,6 +466,7 @@ $(SRCS): \
|
||||||
|
|
||||||
ifeq ($(ARCH), x86_64)
|
ifeq ($(ARCH), x86_64)
|
||||||
TOOLCHAIN_ARTIFACTS = \
|
TOOLCHAIN_ARTIFACTS = \
|
||||||
|
o/cosmopolitan.h \
|
||||||
o/$(MODE)/ape/ape.lds \
|
o/$(MODE)/ape/ape.lds \
|
||||||
o/$(MODE)/libc/crt/crt.o \
|
o/$(MODE)/libc/crt/crt.o \
|
||||||
o/$(MODE)/ape/ape.elf \
|
o/$(MODE)/ape/ape.elf \
|
||||||
|
@ -584,13 +475,13 @@ TOOLCHAIN_ARTIFACTS = \
|
||||||
o/$(MODE)/ape/ape-no-modify-self.o \
|
o/$(MODE)/ape/ape-no-modify-self.o \
|
||||||
o/$(MODE)/cosmopolitan.a \
|
o/$(MODE)/cosmopolitan.a \
|
||||||
o/$(MODE)/third_party/libcxx/libcxx.a \
|
o/$(MODE)/third_party/libcxx/libcxx.a \
|
||||||
o/$(MODE)/tool/build/march-native \
|
o/$(MODE)/tool/build/march-native.com \
|
||||||
o/$(MODE)/tool/build/ar \
|
o/$(MODE)/tool/build/ar.com \
|
||||||
o/$(MODE)/tool/build/mktemper \
|
o/$(MODE)/tool/build/mktemper.com \
|
||||||
o/$(MODE)/tool/build/fixupobj \
|
o/$(MODE)/tool/build/fixupobj.com \
|
||||||
o/$(MODE)/tool/build/zipcopy \
|
o/$(MODE)/tool/build/zipcopy.com \
|
||||||
o/$(MODE)/tool/build/apelink \
|
o/$(MODE)/tool/build/apelink.com \
|
||||||
o/$(MODE)/tool/build/pecheck
|
o/$(MODE)/tool/build/pecheck.com
|
||||||
else
|
else
|
||||||
TOOLCHAIN_ARTIFACTS = \
|
TOOLCHAIN_ARTIFACTS = \
|
||||||
o/$(MODE)/ape/ape.elf \
|
o/$(MODE)/ape/ape.elf \
|
||||||
|
@ -598,9 +489,9 @@ TOOLCHAIN_ARTIFACTS = \
|
||||||
o/$(MODE)/libc/crt/crt.o \
|
o/$(MODE)/libc/crt/crt.o \
|
||||||
o/$(MODE)/cosmopolitan.a \
|
o/$(MODE)/cosmopolitan.a \
|
||||||
o/$(MODE)/third_party/libcxx/libcxx.a \
|
o/$(MODE)/third_party/libcxx/libcxx.a \
|
||||||
o/$(MODE)/tool/build/march-native \
|
o/$(MODE)/tool/build/march-native.com \
|
||||||
o/$(MODE)/tool/build/fixupobj \
|
o/$(MODE)/tool/build/fixupobj.com \
|
||||||
o/$(MODE)/tool/build/zipcopy
|
o/$(MODE)/tool/build/zipcopy.com
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: toolchain
|
.PHONY: toolchain
|
||||||
|
|
573
README.md
573
README.md
|
@ -3,34 +3,38 @@
|
||||||
[](https://github.com/jart/cosmopolitan/actions/workflows/build.yml)
|
[](https://github.com/jart/cosmopolitan/actions/workflows/build.yml)
|
||||||
# Cosmopolitan
|
# Cosmopolitan
|
||||||
|
|
||||||
[Cosmopolitan Libc](https://justine.lol/cosmopolitan/index.html) makes C/C++
|
[Cosmopolitan Libc](https://justine.lol/cosmopolitan/index.html) makes C
|
||||||
a build-once run-anywhere language, like Java, except it doesn't need an
|
a build-once run-anywhere language, like Java, except it doesn't need an
|
||||||
interpreter or virtual machine. Instead, it reconfigures stock GCC and
|
interpreter or virtual machine. Instead, it reconfigures stock GCC and
|
||||||
Clang to output a POSIX-approved polyglot format that runs natively on
|
Clang to output a POSIX-approved polyglot format that runs natively on
|
||||||
Linux + Mac + Windows + FreeBSD + OpenBSD 7.3 + NetBSD + BIOS with the
|
Linux + Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS with the best
|
||||||
best possible performance and the tiniest footprint imaginable.
|
possible performance and the tiniest footprint imaginable.
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
For an introduction to this project, please read the [actually portable
|
For an introduction to this project, please read the [αcτµαlly pδrταblε
|
||||||
executable](https://justine.lol/ape.html) blog post and [cosmopolitan
|
εxεcµταblε](https://justine.lol/ape.html) blog post and [cosmopolitan
|
||||||
libc](https://justine.lol/cosmopolitan/index.html) website. We also have
|
libc](https://justine.lol/cosmopolitan/index.html) website. We also have
|
||||||
[API
|
[API documentation](https://justine.lol/cosmopolitan/documentation.html).
|
||||||
documentation](https://justine.lol/cosmopolitan/documentation.html).
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
You can start by obtaining a release of our `cosmocc` compiler from
|
It's recommended that Cosmopolitan be installed to `/opt/cosmo` and
|
||||||
<https://cosmo.zip/pub/cosmocc/>.
|
`/opt/cosmos` on your computer. The first has the monorepo. The second
|
||||||
|
contains your non-monorepo artifacts.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mkdir -p cosmocc
|
sudo mkdir -p /opt
|
||||||
cd cosmocc
|
sudo chmod 1777 /opt
|
||||||
wget https://cosmo.zip/pub/cosmocc/cosmocc.zip
|
git clone https://github.com/jart/cosmopolitan /opt/cosmo
|
||||||
unzip cosmocc.zip
|
export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"
|
||||||
|
echo 'PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"' >>~/.profile
|
||||||
|
ape-install # optionally install a faster systemwide ape loader
|
||||||
|
cosmocc --update # pull cosmo and rebuild toolchain
|
||||||
```
|
```
|
||||||
|
|
||||||
Here's an example program we can write:
|
You've now successfully installed your very own cosmos. Now let's build
|
||||||
|
an example program:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
// hello.c
|
// hello.c
|
||||||
|
@ -41,11 +45,26 @@ int main() {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
It can be compiled as follows:
|
To compile the program, you can run the `cosmocc` command. It's
|
||||||
|
important to give it an output path that ends with `.com` so the output
|
||||||
|
format will be Actually Portable Executable. When this happens, a
|
||||||
|
concomitant debug binary is created automatically too.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cosmocc -o hello hello.c
|
cosmocc -o hello.com hello.c
|
||||||
./hello
|
./hello.com
|
||||||
|
./hello.com.dbg
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use the `cosmocc` toolchain to build conventional open source
|
||||||
|
projects which use autotools. This strategy normally works:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export CC=cosmocc
|
||||||
|
export CXX=cosmoc++
|
||||||
|
./configure --prefix=/opt/cosmos
|
||||||
|
make -j
|
||||||
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
The Cosmopolitan Libc runtime links some heavyweight troubleshooting
|
The Cosmopolitan Libc runtime links some heavyweight troubleshooting
|
||||||
|
@ -53,115 +72,445 @@ features by default, which are very useful for developers and admins.
|
||||||
Here's how you can log system calls:
|
Here's how you can log system calls:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./hello --strace
|
./hello.com --strace
|
||||||
```
|
```
|
||||||
|
|
||||||
Here's how you can get a much more verbose log of function calls:
|
Here's how you can get a much more verbose log of function calls:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./hello --ftrace
|
./hello.com --ftrace
|
||||||
```
|
```
|
||||||
|
|
||||||
You can use the Cosmopolitan's toolchain to build conventional open
|
If you don't want rich runtime features like the above included, and you
|
||||||
source projects which use autotools. This strategy normally works:
|
just want libc, and you want smaller simpler programs. In that case, you
|
||||||
|
can consider using `MODE=tiny`, which is preconfigured by the repo in
|
||||||
|
[build/config.mk](build/config.mk). Using this mode is much more
|
||||||
|
effective at reducing binary footprint than the `-Os` flag alone. You
|
||||||
|
can change your build mode by doing the following:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
export CC=x86_64-unknown-cosmo-cc
|
export MODE=tiny
|
||||||
export CXX=x86_64-unknown-cosmo-c++
|
cosmocc --update
|
||||||
./configure --prefix=/opt/cosmos/x86_64
|
```
|
||||||
|
|
||||||
|
We can also make our program slightly smaller by using the system call
|
||||||
|
interface directly, which is fine, since Cosmopolitan polyfills these
|
||||||
|
interfaces across platforms, including Windows. For example:
|
||||||
|
|
||||||
|
```c
|
||||||
|
// hello2.c
|
||||||
|
#include <unistd.h>
|
||||||
|
int main() {
|
||||||
|
write(1, "hello world\n", 12);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Once compiled, your APE binary should be ~36kb in size.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export MODE=tiny
|
||||||
|
cosmocc -Os -o hello2.com hello2.c
|
||||||
|
./hello2.com
|
||||||
|
```
|
||||||
|
|
||||||
|
But let's say you only care about your binaries running on Linux and you
|
||||||
|
don't want to use up all this additional space for platforms like WIN32.
|
||||||
|
In that case, you can try `MODE=tinylinux` for example which will create
|
||||||
|
executables more on the order of 8kb (similar to Musl Libc).
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export MODE=tinylinux
|
||||||
|
cosmocc --update
|
||||||
|
cosmocc -Os -o hello2.com hello2.c
|
||||||
|
./hello2.com # <-- actually an ELF executable
|
||||||
|
```
|
||||||
|
|
||||||
|
## ARM
|
||||||
|
|
||||||
|
Cosmo supports cross-compiling binaries for machines with ARM
|
||||||
|
microprocessors. For example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make -j8 m=aarch64 o/aarch64/third_party/ggml/llama.com
|
||||||
|
make -j8 m=aarch64-tiny o/aarch64-tiny/third_party/ggml/llama.com
|
||||||
|
```
|
||||||
|
|
||||||
|
That'll produce ELF executables that run natively on two operating
|
||||||
|
systems: Linux Arm64 (e.g. Raspberry Pi) and MacOS Arm64 (i.e. Apple
|
||||||
|
Silicon), thus giving you full performance. The catch is you have to
|
||||||
|
compile these executables on an x86_64-linux machine. The second catch
|
||||||
|
is that MacOS needs a little bit of help understanding the ELF format.
|
||||||
|
To solve that, we provide a tiny APE loader you can use on M1 machines.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scp ape/ape-m1.c macintosh:
|
||||||
|
scp o/aarch64/third_party/ggml/llama.com macintosh:
|
||||||
|
ssh macintosh
|
||||||
|
xcode-install
|
||||||
|
cc -o ape ape-m1.c
|
||||||
|
sudo cp ape /usr/local/bin/ape
|
||||||
|
```
|
||||||
|
|
||||||
|
You can run your ELF AARCH64 executable on Apple Silicon as follows:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ape ./llama.com
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want to run the `MODE=aarch64` unit tests, you need to have
|
||||||
|
qemu-aarch64 installed as a binfmt_misc interpreter. It needs to be a
|
||||||
|
static binary if you want it to work with Landlock Make's security. You
|
||||||
|
can use the build included in our `third_party/qemu/` folder.
|
||||||
|
|
||||||
|
```
|
||||||
|
doas cp o/third_party/qemu/qemu-aarch64 /usr/bin/qemu-aarch64
|
||||||
|
doas sh -c "echo ':qemu-aarch64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\xb7\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/usr/bin/qemu-aarch64:CF' > /proc/sys/fs/binfmt_misc/register"
|
||||||
|
make -j8 m=aarch64
|
||||||
|
```
|
||||||
|
|
||||||
|
Please note that the qemu-aarch64 binfmt_misc interpreter installation
|
||||||
|
process is *essential* for being able to use the `aarch64-unknown-cosmo`
|
||||||
|
toolchain to build fat APE binaries on your x86-64 machine.
|
||||||
|
|
||||||
|
## AMD64 + ARM64 fat APE binaries
|
||||||
|
|
||||||
|
If you've setup the qemu binfmt_misc interpreter, then you can can use
|
||||||
|
cosmo's toolchains to build fat ape binaries. It works by compiling your
|
||||||
|
program twice, so you can have a native build for both architectures in
|
||||||
|
the same file. The two programs are merged together by apelink.com which
|
||||||
|
also embeds multiple copies of APE loader and multiple symbols tables.
|
||||||
|
|
||||||
|
The easiest way to build fat APE is using `fatcosmocc`. This compiler
|
||||||
|
works by creating a concomitant `.aarch64/foo.o` for every `foo.o` you
|
||||||
|
compile. The only exception is the C preprocessor mode, which actually
|
||||||
|
runs x86-64 GCC except with macros like `__x86_64__` undefined.
|
||||||
|
|
||||||
|
This toolchain works great for C projects that are written in a portable
|
||||||
|
way and don't produce architecture-specific artifacts. One example of a
|
||||||
|
large project that can be easily built is GNU coreutils.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cd coreutils
|
||||||
|
fatcosmocc --update ||exit
|
||||||
|
./configure CC=fatcosmocc \
|
||||||
|
AR=fatcosmoar \
|
||||||
|
INSTALL=$(command -v fatcosmoinstall) \
|
||||||
|
--prefix=/opt/cosmos \
|
||||||
|
--disable-nls \
|
||||||
|
--disable-dependency-tracking \
|
||||||
|
--disable-silent-rules
|
||||||
|
make -j8
|
||||||
|
```
|
||||||
|
|
||||||
|
You'll then have a bunch of files like `src/ls` which are fat ape
|
||||||
|
binaries. If you want to run them on Windows, then you simply need to
|
||||||
|
rename the file so that it has the `.com` suffix. Better yet, consider
|
||||||
|
making that a symlink (a.k.a. reparse point). The biggest gotcha with
|
||||||
|
`fatcosmocc` though is ensuring builds don't strip binaries. For
|
||||||
|
example, Linux's `install -s` command actually understands Windows'
|
||||||
|
Portable Executable format well enough to remove the MS-DOS stub, which
|
||||||
|
is where the APE shell script is stored. You need to ensure that
|
||||||
|
`fatcosmoinstall` is used instead. Especially if your project needs to
|
||||||
|
install the libraries built by `fatacosmoar` into `/opt/cosmos`.
|
||||||
|
|
||||||
|
## Advanced Fat APE Builds
|
||||||
|
|
||||||
|
Once you get seriously involved in creating fat APE builds of software
|
||||||
|
you're going to eventually outgrow `fatcosmocc`. One example is Emacs
|
||||||
|
which is trickier to build, because it produces architecture-specific
|
||||||
|
files, and it also depends on shared files, e.g. zoneinfo. Since we like
|
||||||
|
having everything in a neat little single-file executable container that
|
||||||
|
doesn't need an "installation wizard", this tutorial will explain how we
|
||||||
|
manage to accomplish that.
|
||||||
|
|
||||||
|
What you're going to do is, instead of using `fatcosmocc`, you're going
|
||||||
|
to use both the `x86_64-unknown-cosmo-cc` and `aarch64-unknown-cosmo-cc`
|
||||||
|
toolchains independently, and then run `apelink` and `zip` to manually
|
||||||
|
build the final files. But there's a few tricks to learn first.
|
||||||
|
|
||||||
|
The first trick is to create a symlink on your system called `/zip`.
|
||||||
|
Cosmopolitan Libc normally uses that as a synthetic folder that lets you
|
||||||
|
access the assets in your zip executable. But since that's a read-only
|
||||||
|
file system, your build system should use the normal one.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
doas ln -sf /opt/cosmos /zip
|
||||||
|
```
|
||||||
|
|
||||||
|
Now create a file named `rebuild-fat.sh` which runs the build twice:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/sh
|
||||||
|
set -ex
|
||||||
|
export MODE=aarch64
|
||||||
|
export COSMOS=/opt/cosmos/aarch64
|
||||||
|
rebuild-cosmos.sh aarch64
|
||||||
|
export MODE=
|
||||||
|
export COSMOS=/opt/cosmos/x86_64
|
||||||
|
rebuild-cosmos.sh x86_64
|
||||||
|
wall.com 'finished building'
|
||||||
|
```
|
||||||
|
|
||||||
|
Then create a second file `rebuild-cosmos.sh` which runs your build:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
#!/bin/bash
|
||||||
|
set -ex
|
||||||
|
|
||||||
|
ARCH=${1:-x86_64}
|
||||||
|
export COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
export COSMOS=${COSMOS:-/opt/cosmos/$ARCH}
|
||||||
|
export AS=$(command -v $ARCH-unknown-cosmo-as) || exit
|
||||||
|
export CC=$(command -v $ARCH-unknown-cosmo-cc) || exit
|
||||||
|
export CXX=$(command -v $ARCH-unknown-cosmo-c++) || exit
|
||||||
|
export AR=$(command -v $ARCH-unknown-cosmo-ar) || exit
|
||||||
|
export STRIP=$(command -v $ARCH-unknown-cosmo-strip) || exit
|
||||||
|
export INSTALL=$(command -v $ARCH-unknown-cosmo-install) || exit
|
||||||
|
export OBJCOPY=$(command -v $ARCH-unknown-cosmo-objcopy) || exit
|
||||||
|
export OBJDUMP=$(command -v $ARCH-unknown-cosmo-objdump) || exit
|
||||||
|
export ADDR2LINE=$(command -v $ARCH-unknown-cosmo-addr2line) || exit
|
||||||
|
|
||||||
|
$CC --update
|
||||||
|
|
||||||
|
export COSMOPOLITAN_DISABLE_ZIPOS=1
|
||||||
|
|
||||||
|
cd ~/vendor/zlib
|
||||||
|
./configure --prefix=$COSMOS --static
|
||||||
|
make clean
|
||||||
|
make -j
|
||||||
|
make install
|
||||||
|
|
||||||
|
cd ~/vendor/ncurses-6.4
|
||||||
|
./configure --prefix=$COSMOS --sysconfdir=/zip --datarootdir=/zip/share --exec-prefix=/zip/$ARCH --disable-shared
|
||||||
|
make clean
|
||||||
|
make -j
|
||||||
|
make install
|
||||||
|
|
||||||
|
cd ~/vendor/readline-8.2
|
||||||
|
./configure --prefix=$COSMOS --sysconfdir=/zip --datarootdir=/zip/share --exec-prefix=/zip/$ARCH --disable-shared
|
||||||
|
make uninstall || true
|
||||||
|
make clean
|
||||||
|
make -j
|
||||||
|
make install
|
||||||
|
|
||||||
|
# NOTES:
|
||||||
|
# 1. You'll need to patch enum { FOO = x } that fails to build into a #define FOO
|
||||||
|
# 2. You'll need to patch configure.ac so it DOES NOT define USABLE_FIONREAD to 1
|
||||||
|
# 2. You'll need to patch configure.ac so it DOES NOT define INTERRUPT_INPUT to 1
|
||||||
|
cd ~/vendor/emacs-28.2
|
||||||
|
./configure --prefix=$COSMOS --sysconfdir=/zip --datarootdir=/zip/share --exec-prefix=/zip/$ARCH \
|
||||||
|
--without-x --with-threads --without-gnutls --disable-silent-rules --with-file-notification=no
|
||||||
|
make uninstall || true
|
||||||
|
make clean
|
||||||
make -j
|
make -j
|
||||||
make install
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cosmopolitan Source Builds
|
Once you've completed this build process, you'll have the ELF files
|
||||||
|
`/opt/cosmos/x86_64/bin/emacs` and `/opt/cosmos/aarch64/bin/emacs`. Your
|
||||||
Cosmopolitan can be compiled from source on any of our supported
|
next move is to combine them into a single pristine `emacs.com` file.
|
||||||
platforms. The Makefile will download cosmocc automatically.
|
|
||||||
|
|
||||||
It's recommended that you install a systemwide APE Loader. This command
|
|
||||||
requires `sudo` access to copy the `ape` command to a system folder and
|
|
||||||
register with binfmt_misc on Linux, for even more performance.
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
ape/apeinstall.sh
|
cd /zip
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
mkdir -p /opt/cosmos/bin
|
||||||
|
apelink \
|
||||||
|
-o /opt/cosmos/bin/emacs.com \
|
||||||
|
-l "$COSMO/o//ape/ape.elf" \
|
||||||
|
-l "$COSMO/o/aarch64/ape/ape.elf" \
|
||||||
|
-M "$COSMO/ape/ape-m1.c" \
|
||||||
|
/opt/cosmos/x86_64/bin/emacs \
|
||||||
|
/opt/cosmos/aarch64/bin/emacs
|
||||||
|
cd /zip
|
||||||
|
zip -r /opt/cosmos/bin/emacs.com \
|
||||||
|
aarch64/libexec \
|
||||||
|
x86_64/libexec \
|
||||||
|
share/terminfo \
|
||||||
|
$(find share/emacs -type f |
|
||||||
|
grep -v '\.el.gz$' |
|
||||||
|
grep -v refcards |
|
||||||
|
grep -v images)
|
||||||
```
|
```
|
||||||
|
|
||||||
You can now build the mono repo with any modern version of GNU Make. To
|
You can now scp your `emacs.com` build to seven operating systems for
|
||||||
bootstrap your build, you can install Cosmopolitan Make from this site:
|
two distinct kinds of microprocessors without any dependencies. All the
|
||||||
|
LISP, zoneinfo, and termcap files it needs are stored inside the ZIP
|
||||||
|
structure of the binary, which has performance that's equivalent to the
|
||||||
|
Linux filesystem (even though it decompresses artifacts on the fly!) For
|
||||||
|
this reason, you might actually find that fat APE Emacs goes faster if
|
||||||
|
you're using an operating system like Windows where files are go slow.
|
||||||
|
|
||||||
https://cosmo.zip/pub/cosmos/bin/make
|
If you like to use Vim instead of Emacs, then you can build that too.
|
||||||
|
However Vim's build system makes it a bit harder, since it's configured
|
||||||
|
to always strip binaries. The `apelink` program needs the symbol tables
|
||||||
|
to still be there when it creates the fat version. Otherwise tools like
|
||||||
|
`--ftrace` won't work.
|
||||||
|
|
||||||
E.g.:
|
## Monolithic Source Builds
|
||||||
|
|
||||||
|
Cosmopolitan can be compiled from source on any Linux distro. First, you
|
||||||
|
need to download or clone the repository.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -LO https://cosmo.zip/pub/cosmos/bin/make
|
wget https://justine.lol/cosmopolitan/cosmopolitan.tar.gz
|
||||||
./make -j8
|
tar xf cosmopolitan.tar.gz # see releases page
|
||||||
o//examples/hello
|
cd cosmopolitan
|
||||||
```
|
```
|
||||||
|
|
||||||
After you've built the repo once, you can also use the make from your
|
This will build the entire repository and run all the tests:
|
||||||
cosmocc at `.cosmocc/current/bin/make`. You might even prefer to alias
|
|
||||||
make to `$COSMO/.cosmocc/current/bin/make`.
|
```sh
|
||||||
|
build/bootstrap/make.com
|
||||||
|
o//examples/hello.com
|
||||||
|
find o -name \*.com | xargs ls -rShal | less
|
||||||
|
```
|
||||||
|
|
||||||
|
If you get an error running make.com then it's probably because you have
|
||||||
|
WINE installed to `binfmt_misc`. You can fix that by installing the the
|
||||||
|
APE loader as an interpreter. It'll improve build performance too!
|
||||||
|
|
||||||
|
```sh
|
||||||
|
bin/ape-install
|
||||||
|
```
|
||||||
|
|
||||||
Since the Cosmopolitan repository is very large, you might only want to
|
Since the Cosmopolitan repository is very large, you might only want to
|
||||||
build one particular thing. Here's an example of a target that can be
|
build a particular thing. Cosmopolitan's build config does a good job at
|
||||||
compiled relatively quickly, which is a simple POSIX test that only
|
having minimal deterministic builds. For example, if you wanted to build
|
||||||
depends on core LIBC packages.
|
only hello.com then you could do that as follows:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
rm -rf o//libc o//test
|
build/bootstrap/make.com o//examples/hello.com
|
||||||
.cosmocc/current/bin/make o//test/posix/signal_test
|
|
||||||
o//test/posix/signal_test
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Sometimes it's desirable to build a subset of targets, without having to
|
Sometimes it's desirable to build a subset of targets, without having to
|
||||||
list out each individual one. For example if you wanted to build and run
|
list out each individual one. You can do that by asking make to build a
|
||||||
all the unit tests in the `TEST_POSIX` package, you could say:
|
directory name. For example, if you wanted to build only the targets and
|
||||||
|
subtargets of the chibicc package including its tests, you would say:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
.cosmocc/current/bin/make o//test/posix
|
build/bootstrap/make.com o//third_party/chibicc
|
||||||
|
o//third_party/chibicc/chibicc.com --help
|
||||||
```
|
```
|
||||||
|
|
||||||
Cosmopolitan provides a variety of build modes. For example, if you want
|
Cosmopolitan provides a variety of build modes. For example, if you want
|
||||||
really tiny binaries (as small as 12kb in size) then you'd say:
|
really tiny binaries (as small as 12kb in size) then you'd say:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
.cosmocc/current/bin/make m=tiny
|
build/bootstrap/make.com m=tiny
|
||||||
```
|
```
|
||||||
|
|
||||||
You can furthermore cut out the bloat of other operating systems, and
|
Here's some other build modes you can try:
|
||||||
have Cosmopolitan become much more similar to Musl Libc.
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
.cosmocc/current/bin/make m=tinylinux
|
build/bootstrap/make.com m=dbg # asan + ubsan + debug
|
||||||
|
build/bootstrap/make.com m=asan # production memory safety
|
||||||
|
build/bootstrap/make.com m=opt # -march=native optimizations
|
||||||
|
build/bootstrap/make.com m=rel # traditional release binaries
|
||||||
|
build/bootstrap/make.com m=optlinux # optimal linux-only performance
|
||||||
|
build/bootstrap/make.com m=fastbuild # build 28% faster w/o debugging
|
||||||
|
build/bootstrap/make.com m=tinylinux # tiniest linux-only 4kb binaries
|
||||||
```
|
```
|
||||||
|
|
||||||
For further details, see [//build/config.mk](build/config.mk).
|
For further details, see [//build/config.mk](build/config.mk).
|
||||||
|
|
||||||
## Debugging
|
## Cosmopolitan Amalgamation
|
||||||
|
|
||||||
To print a log of system calls to stderr:
|
Another way to use Cosmopolitan is via our amalgamated release, where
|
||||||
|
we've combined everything into a single static archive and a single
|
||||||
|
header file. If you're doing your development work on Linux or BSD then
|
||||||
|
you need just five files to get started. Here's what you do on Linux:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cosmocc -o hello hello.c
|
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-3.0.zip
|
||||||
./hello --strace
|
unzip cosmopolitan-amalgamation-3.0.zip
|
||||||
|
printf 'main() { printf("hello world\\n"); }\n' >hello.c
|
||||||
|
gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
|
||||||
|
-fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs -gdwarf-4 \
|
||||||
|
-o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds -Wl,--gc-sections \
|
||||||
|
-Wl,-z,common-page-size=0x1000 -Wl,-z,max-page-size=0x1000 \
|
||||||
|
-include cosmopolitan.h crt.o ape-no-modify-self.o cosmopolitan.a
|
||||||
|
objcopy -S -O binary hello.com.dbg hello.com
|
||||||
```
|
```
|
||||||
|
|
||||||
To print a log of function calls to stderr:
|
You now have a portable program.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cosmocc -o hello hello.c
|
./hello.com
|
||||||
./hello --ftrace
|
bash -c './hello.com' # older zsh/fish workaround (patched in zsh 5.9 and fish 3.3.0)
|
||||||
```
|
```
|
||||||
|
|
||||||
Both strace and ftrace use the unbreakable kprintf() facility, which is
|
If `./hello.com` executed on Linux throws an error about not finding an
|
||||||
able to be sent to a file by setting an environment variable.
|
interpreter, it should be fixed by running the following command (although
|
||||||
|
note that it may not survive a system restart):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
export KPRINTF_LOG=log
|
sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
|
||||||
./hello --strace
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the same command produces puzzling errors on WSL or WINE when using
|
||||||
|
Redbean 2.x, they may be fixed by disabling binfmt_misc:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/status'
|
||||||
|
```
|
||||||
|
|
||||||
|
Since we used the `ape-no-modify-self.o` bootloader (rather than
|
||||||
|
`ape.o`) your executable will not modify itself when it's run. What
|
||||||
|
it'll instead do, is extract a 4kb program (the [APE loader](https://justine.lol/apeloader/))
|
||||||
|
to `${TMPDIR:-${HOME:-.}}` that maps your program into memory without
|
||||||
|
needing to copy it. The APE loader must be in an executable location
|
||||||
|
(e.g. not stored on a `noexec` mount) for it to run. See below for
|
||||||
|
alternatives:
|
||||||
|
|
||||||
|
It's possible to install the APE loader systemwide as follows.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# System-Wide APE Install
|
||||||
|
# for Linux, Darwin, and BSDs
|
||||||
|
# 1. Copies APE Loader to /usr/bin/ape
|
||||||
|
# 2. Registers w/ binfmt_misc too if Linux
|
||||||
|
bin/ape-install
|
||||||
|
|
||||||
|
# System-Wide APE Uninstall
|
||||||
|
# for Linux, Darwin, and BSDs
|
||||||
|
bin/ape-uninstall
|
||||||
|
```
|
||||||
|
|
||||||
|
It's also possible to convert APE binaries into the system-local format
|
||||||
|
by using the `--assimilate` flag. Please note that if binfmt_misc is in
|
||||||
|
play, you'll need to unregister it temporarily before doing this, since
|
||||||
|
the assimilate feature is part of the shell script header.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ file hello.com
|
||||||
|
hello.com: DOS/MBR boot sector
|
||||||
|
./hello.com --assimilate
|
||||||
|
$ file hello.com
|
||||||
|
hello.com: ELF 64-bit LSB executable
|
||||||
|
```
|
||||||
|
|
||||||
|
Now that you're up and running with Cosmopolitan Libc and APE, here's
|
||||||
|
some of the most important troubleshooting tools APE offers that you
|
||||||
|
should know, in case you encounter any issues:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./hello.com --strace # log system calls to stderr
|
||||||
|
./hello.com --ftrace # log function calls to stderr
|
||||||
|
```
|
||||||
|
|
||||||
|
Do you love tiny binaries? If so, you may not be happy with Cosmo adding
|
||||||
|
heavyweight features like tracing to your binaries by default. In that
|
||||||
|
case, you may want to consider using our build system:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make m=tiny
|
||||||
|
```
|
||||||
|
|
||||||
|
Which will cause programs such as `hello.com` and `life.com` to shrink
|
||||||
|
from 60kb in size to about 16kb. There's also a prebuilt amalgamation
|
||||||
|
online <https://justine.lol/cosmopolitan/cosmopolitan-tiny.zip> hosted
|
||||||
|
on our download page <https://justine.lol/cosmopolitan/download.html>.
|
||||||
|
|
||||||
## GDB
|
## GDB
|
||||||
|
|
||||||
Here's the recommended `~/.gdbinit` config:
|
Here's the recommended `~/.gdbinit` config:
|
||||||
|
@ -186,60 +535,46 @@ end
|
||||||
src
|
src
|
||||||
```
|
```
|
||||||
|
|
||||||
You normally run the `.dbg` file under gdb. If you need to debug the
|
You normally run the `.com.dbg` file under gdb. If you need to debug the
|
||||||
`` file itself, then you can load the debug symbols independently as
|
`.com` file itself, then you can load the debug symbols independently as
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
gdb foo -ex 'add-symbol-file foo.dbg 0x401000'
|
gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Platform Notes
|
## Alternative Development Environments
|
||||||
|
|
||||||
### Shells
|
### MacOS
|
||||||
|
|
||||||
If you use zsh and have trouble running APE programs try `sh -c ./prog`
|
If you're developing on MacOS you can install the GNU compiler
|
||||||
or simply upgrade to zsh 5.9+ (since we patched it two years ago). The
|
collection for x86_64-elf via homebrew:
|
||||||
same is the case for Python `subprocess`, old versions of fish, etc.
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
|
|
||||||
Some Linux systems are configured to launch MZ executables under WINE.
|
|
||||||
Other distros configure their stock installs so that APE programs will
|
|
||||||
print "run-detectors: unable to find an interpreter". For example:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
jart@ubuntu:~$ wget https://cosmo.zip/pub/cosmos/bin/dash
|
brew install x86_64-elf-gcc
|
||||||
jart@ubuntu:~$ chmod +x dash
|
|
||||||
jart@ubuntu:~$ ./dash
|
|
||||||
run-detectors: unable to find an interpreter for ./dash
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can fix that by registering APE with `binfmt_misc`:
|
Then in the above scripts just replace `gcc` and `objcopy` with
|
||||||
|
`x86_64-elf-gcc` and `x86_64-elf-objcopy` to compile your APE binary.
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
If you're developing on Windows then you need to download an
|
||||||
|
x86_64-pc-linux-gnu toolchain beforehand. See the [Compiling on
|
||||||
|
Windows](https://justine.lol/cosmopolitan/windows-compiling.html)
|
||||||
|
tutorial. It's needed because the ELF object format is what makes
|
||||||
|
universal binaries possible.
|
||||||
|
|
||||||
|
Cosmopolitan officially only builds on Linux. However, one highly
|
||||||
|
experimental (and currently broken) thing you could try, is building the
|
||||||
|
entire cosmo repository from source using the cross9 toolchain.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo wget -O /usr/bin/ape https://cosmo.zip/pub/cosmos/bin/ape-$(uname -m).elf
|
mkdir -p o/third_party
|
||||||
sudo chmod +x /usr/bin/ape
|
rm -rf o/third_party/gcc
|
||||||
sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
wget https://justine.lol/linux-compiler-on-windows/cross9.zip
|
||||||
sudo sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
unzip cross9.zip
|
||||||
```
|
mv cross9 o/third_party/gcc
|
||||||
|
build/bootstrap/make.com
|
||||||
You should be good now. APE will not only work, it'll launch executables
|
|
||||||
400µs faster now too. However if things still didn't work out, it's also
|
|
||||||
possible to disable `binfmt_misc` as follows:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/cli' # remove Ubuntu's MZ interpreter
|
|
||||||
sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/status' # remove ALL binfmt_misc entries
|
|
||||||
```
|
|
||||||
|
|
||||||
### WSL
|
|
||||||
|
|
||||||
It's normally unsafe to use APE in a WSL environment, because it tries
|
|
||||||
to run MZ executables as WIN32 binaries within the WSL environment. In
|
|
||||||
order to make it safe to use Cosmopolitan software on WSL, run this:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo sh -c "echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Discord Chatroom
|
## Discord Chatroom
|
||||||
|
@ -249,16 +584,16 @@ server. You're welcome to join us! <https://discord.gg/FwAVVu7eJ4>
|
||||||
|
|
||||||
## Support Vector
|
## Support Vector
|
||||||
|
|
||||||
| Platform | Min Version | Circa |
|
| Platform | Min Version | Circa |
|
||||||
| :--- | ---: | ---: |
|
| :--- | ---: | ---: |
|
||||||
| AMD | K8 | 2003 |
|
| AMD | K8 Venus | 2005 |
|
||||||
| Intel | Core | 2006 |
|
| Intel | Core | 2006 |
|
||||||
| Linux | 2.6.18 | 2007 |
|
| Linux | 2.6.18 | 2007 |
|
||||||
| Windows | 8 [1] | 2012 |
|
| Windows | 8 [1] | 2012 |
|
||||||
| Darwin (macOS) | 23.1.0+ | 2023 |
|
| Mac OS X | 15.6 | 2018 |
|
||||||
| OpenBSD | 7.3 or earlier | 2023 |
|
| OpenBSD | 7 | 2021 |
|
||||||
| FreeBSD | 13 | 2020 |
|
| FreeBSD | 13 | 2020 |
|
||||||
| NetBSD | 9.2 | 2021 |
|
| NetBSD | 9.2 | 2021 |
|
||||||
|
|
||||||
[1] See our [vista branch](https://github.com/jart/cosmopolitan/tree/vista)
|
[1] See our [vista branch](https://github.com/jart/cosmopolitan/tree/vista)
|
||||||
for a community supported version of Cosmopolitan that works on Windows
|
for a community supported version of Cosmopolitan that works on Windows
|
||||||
|
|
287
ape/BUILD.mk
287
ape/BUILD.mk
|
@ -1,287 +0,0 @@
|
||||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
|
||||||
#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
|
|
||||||
#
|
|
||||||
# OVERVIEW
|
|
||||||
#
|
|
||||||
# αcτµαlly pδrταblε εxεcµταblε
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# This file defines the libraries, runtimes, and build rules needed to
|
|
||||||
# create executables from your Linux workstation that'll run anywhere.
|
|
||||||
# Loading this package will make certain systemic modifications to the
|
|
||||||
# build like turning off the System V "Red Zone" optimization, because
|
|
||||||
# αcτµαlly pδrταblε εxεcµταblεs need to be able to run in kernelspace.
|
|
||||||
|
|
||||||
PKGS += APE
|
|
||||||
|
|
||||||
APE_FILES := $(wildcard ape/*.*)
|
|
||||||
APE_HDRS = $(filter %.h,$(APE_FILES))
|
|
||||||
APE_INCS = $(filter %.inc,$(APE_FILES))
|
|
||||||
|
|
||||||
ifeq ($(ARCH), aarch64)
|
|
||||||
|
|
||||||
APE = o/$(MODE)/ape/aarch64.lds
|
|
||||||
|
|
||||||
APELINK = \
|
|
||||||
$(COMPILE) \
|
|
||||||
-ALINK.ape \
|
|
||||||
$(LINK) \
|
|
||||||
$(LINKARGS) \
|
|
||||||
$(OUTPUT_OPTION) && \
|
|
||||||
$(COMPILE) \
|
|
||||||
-AFIXUP.ape \
|
|
||||||
-wT$@ \
|
|
||||||
$(FIXUPOBJ) \
|
|
||||||
$@
|
|
||||||
|
|
||||||
APE_SRCS = ape/ape.S ape/start.S ape/launch.S ape/systemcall.S
|
|
||||||
APE_OBJS = o/$(MODE)/ape/ape.o
|
|
||||||
APE_NO_MODIFY_SELF = $(APE)
|
|
||||||
APE_COPY_SELF = $(APE)
|
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/ape
|
|
||||||
o/$(MODE)/ape: $(APE)
|
|
||||||
|
|
||||||
o/$(MODE)/ape/aarch64.lds: \
|
|
||||||
ape/aarch64.lds \
|
|
||||||
libc/zip.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
libc/calls/struct/timespec.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/str/str.h
|
|
||||||
|
|
||||||
APE_LOADER_LDFLAGS = \
|
|
||||||
-pie \
|
|
||||||
-static \
|
|
||||||
-nostdlib \
|
|
||||||
--no-dynamic-linker \
|
|
||||||
-z norelro \
|
|
||||||
-z common-page-size=0x4000 \
|
|
||||||
-z max-page-size=0x4000
|
|
||||||
|
|
||||||
APE_LOADER_FLAGS = \
|
|
||||||
-DNDEBUG \
|
|
||||||
-iquote. \
|
|
||||||
-Wall \
|
|
||||||
-Wextra \
|
|
||||||
-fpie \
|
|
||||||
-Os \
|
|
||||||
-ffreestanding \
|
|
||||||
-mgeneral-regs-only \
|
|
||||||
-fno-asynchronous-unwind-tables \
|
|
||||||
-fno-stack-protector \
|
|
||||||
-fno-ident \
|
|
||||||
-fno-gnu-unique \
|
|
||||||
-c \
|
|
||||||
$(OUTPUT_OPTION) \
|
|
||||||
$<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
|
||||||
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
|
|
||||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.elf.dbg: \
|
|
||||||
o/$(MODE)/ape/start.o \
|
|
||||||
o/$(MODE)/ape/loader.o \
|
|
||||||
o/$(MODE)/ape/launch.o \
|
|
||||||
o/$(MODE)/ape/systemcall.o
|
|
||||||
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
|
||||||
|
|
||||||
o/$(MODE)/ape/loader.o: ape/loader.c ape/ape.h
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=33 -g $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/start.o: ape/start.S
|
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
|
||||||
o/$(MODE)/ape/launch.o: ape/launch.S
|
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
|
||||||
o/$(MODE)/ape/systemcall.o: ape/systemcall.S
|
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/ape
|
|
||||||
o/$(MODE)/ape: o/$(MODE)/ape/ape.elf
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
APE = o/$(MODE)/ape/ape.o \
|
|
||||||
o/$(MODE)/ape/ape.lds
|
|
||||||
|
|
||||||
APELINK = \
|
|
||||||
$(COMPILE) \
|
|
||||||
-ALINK.ape \
|
|
||||||
$(LINK) \
|
|
||||||
$(LINKARGS) \
|
|
||||||
$(OUTPUT_OPTION) && \
|
|
||||||
$(COMPILE) \
|
|
||||||
-AFIXUP.ape \
|
|
||||||
-wT$@ \
|
|
||||||
$(FIXUPOBJ) \
|
|
||||||
$@
|
|
||||||
|
|
||||||
APE_NO_MODIFY_SELF = \
|
|
||||||
o/$(MODE)/ape/ape.lds \
|
|
||||||
o/$(MODE)/ape/ape-no-modify-self.o
|
|
||||||
|
|
||||||
APE_COPY_SELF = \
|
|
||||||
o/$(MODE)/ape/ape.lds \
|
|
||||||
o/$(MODE)/ape/ape-copy-self.o
|
|
||||||
|
|
||||||
APE_LOADER_FLAGS = \
|
|
||||||
-DNDEBUG \
|
|
||||||
-iquote. \
|
|
||||||
-Wall \
|
|
||||||
-Wextra \
|
|
||||||
-Werror \
|
|
||||||
-pedantic-errors \
|
|
||||||
-fpie \
|
|
||||||
-Os \
|
|
||||||
-ffreestanding \
|
|
||||||
-mgeneral-regs-only \
|
|
||||||
-fno-stack-protector \
|
|
||||||
-fno-ident \
|
|
||||||
-fno-gnu-unique \
|
|
||||||
-c \
|
|
||||||
$(OUTPUT_OPTION) \
|
|
||||||
$<
|
|
||||||
|
|
||||||
APE_SRCS_C = ape/loader.c
|
|
||||||
APE_SRCS_S = $(filter %.S,$(APE_FILES))
|
|
||||||
APE_SRCS = $(APE_SRCS_C) $(APE_SRCS_S)
|
|
||||||
APE_OBJS = $(APE_SRCS_S:%.S=o/$(MODE)/%.o)
|
|
||||||
APE_CHECKS = $(APE_HDRS:%=o/%.ok)
|
|
||||||
|
|
||||||
o/ape/idata.inc: \
|
|
||||||
ape/idata.internal.h \
|
|
||||||
ape/relocations.h
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape-no-modify-self.o: \
|
|
||||||
ape/ape.S \
|
|
||||||
ape/ape.h \
|
|
||||||
ape/macros.internal.h \
|
|
||||||
ape/relocations.h \
|
|
||||||
ape/ape.internal.h \
|
|
||||||
libc/dce.h \
|
|
||||||
libc/elf/def.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
libc/macho.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/nexgen32e/uart.internal.h \
|
|
||||||
libc/calls/metalfile.internal.h \
|
|
||||||
libc/nt/pedef.internal.h \
|
|
||||||
libc/runtime/e820.internal.h \
|
|
||||||
libc/runtime/mman.internal.h \
|
|
||||||
libc/runtime/pc.internal.h \
|
|
||||||
libc/sysv/consts/prot.h \
|
|
||||||
o/$(MODE)/ape/ape.elf
|
|
||||||
@$(COMPILE) \
|
|
||||||
-AOBJECTIFY.S \
|
|
||||||
$(OBJECTIFY.S) \
|
|
||||||
$(OUTPUT_OPTION) \
|
|
||||||
-DAPE_NO_MODIFY_SELF \
|
|
||||||
-DAPE_LOADER='"o/$(MODE)/ape/ape.elf"' $<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape-copy-self.o: \
|
|
||||||
ape/ape.S \
|
|
||||||
ape/ape.h \
|
|
||||||
ape/macros.internal.h \
|
|
||||||
ape/relocations.h \
|
|
||||||
ape/ape.internal.h \
|
|
||||||
libc/dce.h \
|
|
||||||
libc/elf/def.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
libc/macho.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/nexgen32e/uart.internal.h \
|
|
||||||
libc/calls/metalfile.internal.h \
|
|
||||||
libc/nt/pedef.internal.h \
|
|
||||||
libc/runtime/e820.internal.h \
|
|
||||||
libc/runtime/mman.internal.h \
|
|
||||||
libc/runtime/pc.internal.h \
|
|
||||||
libc/sysv/consts/prot.h
|
|
||||||
@$(COMPILE) \
|
|
||||||
-AOBJECTIFY.S \
|
|
||||||
$(OBJECTIFY.S) \
|
|
||||||
$(OUTPUT_OPTION) \
|
|
||||||
-DAPE_NO_MODIFY_SELF $<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/loader.o: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -g $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/loader-gcc.asm: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/loader-clang.asm: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
|
||||||
|
|
||||||
o/$(MODE)/ape/loader-xnu.o: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -g $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/loader-xnu-gcc.asm: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
|
||||||
@$(COMPILE) -AOBJBINCOPY -w $(OBJBINCOPY) -f -o $@ $<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.elf.dbg
|
|
||||||
@$(COMPILE) -AOBJBINCOPY -w $(OBJBINCOPY) -fm -o $@ $<
|
|
||||||
|
|
||||||
APE_LOADER_LDFLAGS = \
|
|
||||||
-static \
|
|
||||||
-nostdlib \
|
|
||||||
--no-dynamic-linker \
|
|
||||||
-z separate-code \
|
|
||||||
-z common-page-size=0x1000 \
|
|
||||||
-z max-page-size=0x10000
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.elf.dbg: \
|
|
||||||
o/$(MODE)/ape/loader-macho.o \
|
|
||||||
o/$(MODE)/ape/start.o \
|
|
||||||
o/$(MODE)/ape/loader.o \
|
|
||||||
o/$(MODE)/ape/launch.o \
|
|
||||||
o/$(MODE)/ape/systemcall.o \
|
|
||||||
ape/loader.lds
|
|
||||||
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/ape
|
|
||||||
o/$(MODE)/ape: $(APE_CHECKS) \
|
|
||||||
o/$(MODE)/ape/ape.o \
|
|
||||||
o/$(MODE)/ape/ape.lds \
|
|
||||||
o/$(MODE)/ape/ape.elf \
|
|
||||||
o/$(MODE)/ape/ape.macho \
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
# these assembly files are safe to build on aarch64
|
|
||||||
o/$(MODE)/ape/ape.o: \
|
|
||||||
ape/ape.S \
|
|
||||||
ape/ape.h \
|
|
||||||
libc/dce.h \
|
|
||||||
libc/elf/def.h \
|
|
||||||
ape/relocations.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
ape/ape.internal.h \
|
|
||||||
ape/macros.internal.h \
|
|
||||||
libc/macho.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/sysv/consts/prot.h \
|
|
||||||
libc/nt/pedef.internal.h \
|
|
||||||
libc/runtime/pc.internal.h \
|
|
||||||
libc/runtime/e820.internal.h \
|
|
||||||
libc/runtime/mman.internal.h \
|
|
||||||
libc/nexgen32e/uart.internal.h \
|
|
||||||
libc/calls/metalfile.internal.h
|
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.lds: \
|
|
||||||
ape/ape.lds \
|
|
||||||
ape/macros.internal.h \
|
|
||||||
ape/relocations.h \
|
|
||||||
ape/ape.internal.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
libc/calls/struct/timespec.h \
|
|
||||||
libc/thread/thread.h \
|
|
||||||
libc/dce.h \
|
|
||||||
libc/elf/def.h \
|
|
||||||
libc/elf/pf2prot.internal.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/nt/pedef.internal.h \
|
|
||||||
libc/str/str.h \
|
|
||||||
libc/zip.h
|
|
|
@ -1,7 +1,6 @@
|
||||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/sysv/consts/prot.h"
|
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
@ -12,7 +11,7 @@ OUTPUT_FORMAT("elf64-littleaarch64",
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
|
|
||||||
. = SEGMENT_START("text-segment", 0x000800000000);
|
. = SEGMENT_START("text-segment", 0x010000000000);
|
||||||
__executable_start = .;
|
__executable_start = .;
|
||||||
. += SIZEOF_HEADERS;
|
. += SIZEOF_HEADERS;
|
||||||
|
|
||||||
|
@ -90,12 +89,10 @@ SECTIONS {
|
||||||
*(.ubsan.data)
|
*(.ubsan.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice : {
|
.comment : {
|
||||||
__notices = .;
|
__comment_start = .;
|
||||||
KEEP(*(.notice))
|
KEEP(*(.comment))
|
||||||
BYTE(0);
|
BYTE(0);
|
||||||
BYTE(10);
|
|
||||||
BYTE(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.eh_frame_hdr : {
|
.eh_frame_hdr : {
|
||||||
|
@ -103,8 +100,10 @@ SECTIONS {
|
||||||
*(.eh_frame_entry .eh_frame_entry.*)
|
*(.eh_frame_entry .eh_frame_entry.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
|
.eh_frame : ONLY_IF_RO {
|
||||||
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
|
KEEP(*(.eh_frame))
|
||||||
|
*(.eh_frame.*)
|
||||||
|
}
|
||||||
|
|
||||||
.gcc_except_table : ONLY_IF_RO {
|
.gcc_except_table : ONLY_IF_RO {
|
||||||
*(.gcc_except_table .gcc_except_table.*)
|
*(.gcc_except_table .gcc_except_table.*)
|
||||||
|
@ -125,11 +124,9 @@ SECTIONS {
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
||||||
|
|
||||||
.eh_frame : {
|
.eh_frame : ONLY_IF_RW {
|
||||||
__eh_frame_start = .;
|
|
||||||
KEEP(*(.eh_frame))
|
KEEP(*(.eh_frame))
|
||||||
*(.eh_frame.*)
|
*(.eh_frame.*)
|
||||||
__eh_frame_end = .;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.gnu_extab : ONLY_IF_RW {
|
.gnu_extab : ONLY_IF_RW {
|
||||||
|
@ -160,11 +157,8 @@ SECTIONS {
|
||||||
|
|
||||||
.init_array : {
|
.init_array : {
|
||||||
__init_array_start = .;
|
__init_array_start = .;
|
||||||
KEEP(*(.preinit_array))
|
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
|
||||||
KEEP(*(.init_array))
|
|
||||||
KEEP(*(.ctors))
|
|
||||||
__init_array_end = .;
|
__init_array_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,9 +253,6 @@ SECTIONS {
|
||||||
.debug_ranges 0 : { *(.debug_ranges) }
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
.debug_macro 0 : { *(.debug_macro) }
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
.debug_addr 0 : { *(.debug_addr) }
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
.debug_names 0 : { *(.debug_names) }
|
|
||||||
.debug_loclists 0 : { *(.debug_loclists) }
|
|
||||||
.debug_str_offsets 0 : { *(.debug_str_offsets) }
|
|
||||||
.ARM.attributes 0 : { KEEP(*(.ARM.attributes)) KEEP(*(.gnu.attributes)) }
|
.ARM.attributes 0 : { KEEP(*(.ARM.attributes)) KEEP(*(.gnu.attributes)) }
|
||||||
.note.gnu.arm.ident 0 : { KEEP(*(.note.gnu.arm.ident)) }
|
.note.gnu.arm.ident 0 : { KEEP(*(.note.gnu.arm.ident)) }
|
||||||
|
|
||||||
|
@ -289,13 +280,15 @@ SECTIONS {
|
||||||
|
|
||||||
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
||||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
|
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
|
||||||
ape_stack_prot = PROT_READ | PROT_WRITE;
|
ape_stack_align = DEFINED(ape_stack_align) ? ape_stack_align : 16;
|
||||||
|
ape_stack_round = -ape_stack_align;
|
||||||
|
|
||||||
_tls_size = _tbss_end - _tdata_start;
|
_tls_size = _tbss_end - _tdata_start;
|
||||||
_tdata_size = _tdata_end - _tdata_start;
|
_tdata_size = _tdata_end - _tdata_start;
|
||||||
_tbss_size = _tbss_end - _tbss_start;
|
_tbss_size = _tbss_end - _tbss_start;
|
||||||
_tbss_offset = _tbss_start - _tdata_start;
|
_tbss_offset = _tbss_start - _tdata_start;
|
||||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||||
_tdata_align = ALIGNOF(.tdata);
|
_tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
|
||||||
_tbss_align = ALIGNOF(.tbss);
|
|
||||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||||
|
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||||
|
|
982
ape/ape-m1.c
982
ape/ape-m1.c
File diff suppressed because it is too large
Load diff
89
ape/ape.S
89
ape/ape.S
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 nofixeol :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -33,11 +33,12 @@
|
||||||
│ αcτµαlly pδrταblε εxεcµταblε § program header │
|
│ αcτµαlly pδrταblε εxεcµταblε § program header │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "ape/macros.internal.h"
|
#include "ape/macros.internal.h"
|
||||||
|
#include "ape/notice.inc"
|
||||||
#include "ape/relocations.h"
|
#include "ape/relocations.h"
|
||||||
#include "libc/calls/metalfile.internal.h"
|
#include "libc/calls/metalfile.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/elf/def.h"
|
#include "libc/elf/def.h"
|
||||||
#include "libc/macho.h"
|
#include "libc/macho.internal.h"
|
||||||
#include "libc/nexgen32e/uart.internal.h"
|
#include "libc/nexgen32e/uart.internal.h"
|
||||||
#include "libc/nt/pedef.internal.h"
|
#include "libc/nt/pedef.internal.h"
|
||||||
#include "libc/runtime/pc.internal.h"
|
#include "libc/runtime/pc.internal.h"
|
||||||
|
@ -196,7 +197,7 @@ ape_mz:
|
||||||
.quad ape_elf_entry // 18: e_entry
|
.quad ape_elf_entry // 18: e_entry
|
||||||
.quad ape_elf_phoff // 20: e_phoff
|
.quad ape_elf_phoff // 20: e_phoff
|
||||||
.quad ape_elf_shoff // 28: e_shoff
|
.quad ape_elf_shoff // 28: e_shoff
|
||||||
.long 0x101ca75 // 30: ape e_flags
|
.long 0 // 30: e_flags
|
||||||
.short 64 // 34: e_ehsize
|
.short 64 // 34: e_ehsize
|
||||||
.short 56 // 36: e_phentsize
|
.short 56 // 36: e_phentsize
|
||||||
.short ape_elf_phnum // 38: e_phnum
|
.short ape_elf_phnum // 38: e_phnum
|
||||||
|
@ -591,7 +592,7 @@ ape_disk:
|
||||||
|
|
||||||
#ifdef APE_IS_SHELL_SCRIPT
|
#ifdef APE_IS_SHELL_SCRIPT
|
||||||
apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
||||||
.ascii "m=$(uname -m 2>/dev/null) || m=x86_64\n"
|
.ascii "m=\"$(uname -m)\"\n"
|
||||||
|
|
||||||
.ascii "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n"
|
.ascii "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n"
|
||||||
// Until all operating systems can be updated to support APE,
|
// Until all operating systems can be updated to support APE,
|
||||||
|
@ -669,7 +670,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
||||||
.shstub ape_elf_entry,8 // 18: e_entry
|
.shstub ape_elf_entry,8 // 18: e_entry
|
||||||
.shstub ape_elf_phoff,8 // 20: e_phoff
|
.shstub ape_elf_phoff,8 // 20: e_phoff
|
||||||
.shstub ape_elf_shoff,8 // 28: e_shoff
|
.shstub ape_elf_shoff,8 // 28: e_shoff
|
||||||
.ascii "\\165\\312\\1\\1" // 30: ape e_flags
|
.ascii "\\0\\0\\0\\0" // 30: e_flags
|
||||||
.ascii "\\100\\0" // 34: e_ehsize
|
.ascii "\\100\\0" // 34: e_ehsize
|
||||||
.ascii "\\070\\0" // 36: e_phentsize
|
.ascii "\\070\\0" // 36: e_phentsize
|
||||||
.shstub ape_elf_phnum,2 // 38: e_phnum
|
.shstub ape_elf_phnum,2 // 38: e_phnum
|
||||||
|
@ -699,10 +700,37 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
||||||
#endif /* APE_NO_MODIFY_SELF */
|
#endif /* APE_NO_MODIFY_SELF */
|
||||||
.ascii "exit $?\n"
|
.ascii "exit $?\n"
|
||||||
.ascii "fi\n" // x86_64
|
.ascii "fi\n" // x86_64
|
||||||
.ascii "echo error: this ape binary only supports x86_64 >&2\n"
|
// ...
|
||||||
.ascii "exit 1\n"
|
// decentralized section (.apesh)
|
||||||
|
// ...
|
||||||
|
.ascii "PHDRS='' <<'@'\n"
|
||||||
.endobj apesh
|
.endobj apesh
|
||||||
|
|
||||||
|
// elf program headers get inserted here
|
||||||
|
// because they need to be in the first 4096 bytes
|
||||||
|
.section .emushprologue,"a",@progbits
|
||||||
|
emush: .ascii "\n@\n#'\"\n"
|
||||||
|
.ascii "s=\"$(uname -s)\"\n"
|
||||||
|
// our script is running on a non-x86_64 architecture
|
||||||
|
// 1. `dd` out the appropriate blink vm blob
|
||||||
|
// 2. gunzip the blink virtual machine executable
|
||||||
|
// 3. relaunch this program inside the blink vm
|
||||||
|
.ascii "o=\"$(command -v \"$0\")\"\n"
|
||||||
|
.ascii "e=\"${TMPDIR:-${HOME:-.}}/.ape-blink-1.0.0\"\n"
|
||||||
|
.previous
|
||||||
|
// ...
|
||||||
|
// decentralized section (.emush)
|
||||||
|
// - __static_yoink("blink_linux_aarch64"); // for raspberry pi
|
||||||
|
// - __static_yoink("blink_xnu_aarch64"); // is apple silicon
|
||||||
|
// ...
|
||||||
|
.section .emushepilogue,"a",@progbits
|
||||||
|
.ascii "echo \"$0: this ape binary lacks $m support\" >&2\n"
|
||||||
|
.rept 16
|
||||||
|
.ascii "exit 127\n"
|
||||||
|
.endr
|
||||||
|
.ascii "exit 1\n"
|
||||||
|
.previous
|
||||||
|
|
||||||
#ifdef APE_LOADER
|
#ifdef APE_LOADER
|
||||||
.section .ape.loader,"a",@progbits
|
.section .ape.loader,"a",@progbits
|
||||||
.balign 64
|
.balign 64
|
||||||
|
@ -720,8 +748,6 @@ ape_loader_end:
|
||||||
#if SupportsSystemv() || SupportsMetal()
|
#if SupportsSystemv() || SupportsMetal()
|
||||||
.section .elf.phdrs,"a",@progbits
|
.section .elf.phdrs,"a",@progbits
|
||||||
|
|
||||||
.globl ape_phdrs
|
|
||||||
ape_phdrs:
|
|
||||||
.long PT_LOAD
|
.long PT_LOAD
|
||||||
.long PF_R|PF_X
|
.long PF_R|PF_X
|
||||||
.stub ape_cod_offset,quad
|
.stub ape_cod_offset,quad
|
||||||
|
@ -761,7 +787,7 @@ ape_phdrs:
|
||||||
.quad 0
|
.quad 0
|
||||||
.quad 0
|
.quad 0
|
||||||
.quad 0
|
.quad 0
|
||||||
.quad 16
|
.stub ape_stack_align,quad
|
||||||
|
|
||||||
#if SupportsOpenbsd() || SupportsNetbsd()
|
#if SupportsOpenbsd() || SupportsNetbsd()
|
||||||
.long PT_NOTE
|
.long PT_NOTE
|
||||||
|
@ -1036,7 +1062,7 @@ ape_pe: .ascin "PE",4
|
||||||
.quad ape_pe_base // ImageBase
|
.quad ape_pe_base // ImageBase
|
||||||
.long ape_pe_sectionalignment // SectionAlignment
|
.long ape_pe_sectionalignment // SectionAlignment
|
||||||
.long ape_pe_filealignment // FileAlignment
|
.long ape_pe_filealignment // FileAlignment
|
||||||
.short 10 // MajorOperatingSystemVersion
|
.short v_ntversion // MajorOperatingSystemVersion
|
||||||
.short 0 // MinorOperatingSystemVersion
|
.short 0 // MinorOperatingSystemVersion
|
||||||
.short 0 // MajorImageVersion
|
.short 0 // MajorImageVersion
|
||||||
.short 0 // MinorImageVersion
|
.short 0 // MinorImageVersion
|
||||||
|
@ -1771,31 +1797,49 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||||
.type ape_text_nops,@object
|
.type ape_text_nops,@object
|
||||||
.type __test_end,@object
|
.type __test_end,@object
|
||||||
|
|
||||||
|
.section .commentprologue,"a",@progbits
|
||||||
|
.globl __comment_start
|
||||||
|
.type __comment_start,@object
|
||||||
|
.hidden __comment_start
|
||||||
|
__comment_start:/*
|
||||||
|
...
|
||||||
|
decentralized content
|
||||||
|
...
|
||||||
|
*/.previous
|
||||||
|
.section .commentepilogue,"a",@progbits
|
||||||
|
.byte 0
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .ape.pad.head,"a",@progbits
|
.section .ape.pad.head,"a",@progbits
|
||||||
.type ape_pad_head,@object
|
.type ape_pad_head,@object
|
||||||
.hidden ape_pad_head
|
.hidden ape_pad_head
|
||||||
ape_pad_head:
|
ape_pad_head:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .ape.pad.text,"a",@progbits
|
.section .ape.pad.text,"a",@progbits
|
||||||
.type ape_pad_text,@object
|
.type ape_pad_text,@object
|
||||||
.hidden ape_pad_text
|
.hidden ape_pad_text
|
||||||
ape_pad_text:
|
ape_pad_text:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .ape.pad.privileged,"a",@progbits
|
.section .ape.pad.privileged,"a",@progbits
|
||||||
.type ape_pad_privileged,@object
|
.type ape_pad_privileged,@object
|
||||||
.hidden ape_pad_privileged
|
.hidden ape_pad_privileged
|
||||||
ape_pad_privileged:
|
ape_pad_privileged:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .ape.pad.data,"a",@progbits
|
.section .ape.pad.data,"a",@progbits
|
||||||
.type ape_pad_data,@object
|
.type ape_pad_data,@object
|
||||||
.hidden ape_pad_data
|
.hidden ape_pad_data
|
||||||
ape_pad_data:
|
ape_pad_data:
|
||||||
|
.previous
|
||||||
|
|
||||||
#if SupportsWindows()
|
#if SupportsWindows()
|
||||||
.section .idata.ro,"a",@progbits
|
.section .idata.ro,"a",@progbits
|
||||||
.type ape_idata_ro,@object
|
.type ape_idata_ro,@object
|
||||||
.hidden ape_idata_ro
|
.hidden ape_idata_ro
|
||||||
ape_idata_ro:
|
ape_idata_ro:
|
||||||
|
.previous
|
||||||
#endif /* SupportsWindows() */
|
#endif /* SupportsWindows() */
|
||||||
|
|
||||||
.section .dataprologue,"aw",@progbits
|
.section .dataprologue,"aw",@progbits
|
||||||
|
@ -1803,45 +1847,32 @@ ape_idata_ro:
|
||||||
.globl __data_start
|
.globl __data_start
|
||||||
.hidden __data_start
|
.hidden __data_start
|
||||||
__data_start:
|
__data_start:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .dataepilogue,"aw",@progbits
|
.section .dataepilogue,"aw",@progbits
|
||||||
.type __data_end,@object
|
.type __data_end,@object
|
||||||
.globl __data_end
|
.globl __data_end
|
||||||
.hidden __data_end
|
.hidden __data_end
|
||||||
__data_end:
|
__data_end:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .bssprologue,"aw",@nobits
|
.section .bssprologue,"aw",@nobits
|
||||||
.type __bss_start,@object
|
.type __bss_start,@object
|
||||||
.globl __bss_start
|
.globl __bss_start
|
||||||
.hidden __bss_start
|
.hidden __bss_start
|
||||||
__bss_start:
|
__bss_start:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .bssepilogue,"aw",@nobits
|
.section .bssepilogue,"aw",@nobits
|
||||||
.type __bss_end,@object
|
.type __bss_end,@object
|
||||||
.globl __bss_end
|
.globl __bss_end
|
||||||
.hidden __bss_end
|
.hidden __bss_end
|
||||||
__bss_end:
|
__bss_end:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .fstls,"awT",@nobits
|
.section .fstls,"awT",@nobits
|
||||||
.align TLS_ALIGNMENT
|
.align TLS_ALIGNMENT
|
||||||
|
.previous
|
||||||
.section .notice,"aR",@progbits
|
|
||||||
.asciz "\n\n\
|
|
||||||
Cosmopolitan\n\
|
|
||||||
Copyright 2024 Justine Alexandra Roberts Tunney\n\
|
|
||||||
\n\
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for\n\
|
|
||||||
any purpose with or without fee is hereby granted, provided that the\n\
|
|
||||||
above copyright notice and this permission notice appear in all copies.\n\
|
|
||||||
\n\
|
|
||||||
THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL\n\
|
|
||||||
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED\n\
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE\n\
|
|
||||||
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\n\
|
|
||||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\n\
|
|
||||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n\
|
|
||||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n\
|
|
||||||
PERFORMANCE OF THIS SOFTWARE."
|
|
||||||
|
|
||||||
.end
|
.end
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#define COSMOPOLITAN_APE_APE_H_
|
#define COSMOPOLITAN_APE_APE_H_
|
||||||
|
|
||||||
#define APE_VERSION_MAJOR 1
|
#define APE_VERSION_MAJOR 1
|
||||||
#define APE_VERSION_MINOR 10
|
#define APE_VERSION_MINOR 8
|
||||||
#define APE_VERSION_STR APE_VERSION_STR_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
|
#define APE_VERSION_STR APE_VERSION_STR_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
|
||||||
#define APE_VERSION_NOTE APE_VERSION_NOTE_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
|
#define APE_VERSION_NOTE APE_VERSION_NOTE_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
|
||||||
|
|
||||||
|
|
101
ape/ape.lds
101
ape/ape.lds
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -229,6 +229,7 @@ SECTIONS {
|
||||||
|
|
||||||
/* Real Mode */
|
/* Real Mode */
|
||||||
KEEP(*(.head))
|
KEEP(*(.head))
|
||||||
|
KEEP(*(.apesh))
|
||||||
KEEP(*(.text.head))
|
KEEP(*(.text.head))
|
||||||
|
|
||||||
/* Executable & Linkable Format */
|
/* Executable & Linkable Format */
|
||||||
|
@ -237,6 +238,10 @@ SECTIONS {
|
||||||
KEEP(*(.elf.phdrs))
|
KEEP(*(.elf.phdrs))
|
||||||
ape_phdrs_end = .;
|
ape_phdrs_end = .;
|
||||||
|
|
||||||
|
KEEP(*(.emushprologue))
|
||||||
|
KEEP(*(.emush))
|
||||||
|
KEEP(*(.emushepilogue))
|
||||||
|
|
||||||
/* OpenBSD */
|
/* OpenBSD */
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||||
ape_note = .;
|
ape_note = .;
|
||||||
|
@ -282,9 +287,12 @@ SECTIONS {
|
||||||
KEEP(*(SORT_BY_NAME(.init.*)))
|
KEEP(*(SORT_BY_NAME(.init.*)))
|
||||||
KEEP(*(.init))
|
KEEP(*(.init))
|
||||||
KEEP(*(.initepilogue))
|
KEEP(*(.initepilogue))
|
||||||
|
KEEP(*(.pltprologue))
|
||||||
*(.plt)
|
*(.plt)
|
||||||
|
KEEP(*(.pltepilogue))
|
||||||
|
KEEP(*(.pltgotprologue))
|
||||||
*(.plt.got)
|
*(.plt.got)
|
||||||
*(.iplt)
|
KEEP(*(.pltgotepilogue))
|
||||||
*(.text.startup .text.startup.*)
|
*(.text.startup .text.startup.*)
|
||||||
*(.text.exit .text.exit.*)
|
*(.text.exit .text.exit.*)
|
||||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
@ -293,6 +301,7 @@ SECTIONS {
|
||||||
KEEP(*(.textwindowsprologue))
|
KEEP(*(.textwindowsprologue))
|
||||||
*(.text.windows)
|
*(.text.windows)
|
||||||
KEEP(*(.textwindowsepilogue))
|
KEEP(*(.textwindowsepilogue))
|
||||||
|
KEEP(*(.blink))
|
||||||
*(SORT_BY_ALIGNMENT(.text.modernity))
|
*(SORT_BY_ALIGNMENT(.text.modernity))
|
||||||
*(SORT_BY_ALIGNMENT(.text.modernity.*))
|
*(SORT_BY_ALIGNMENT(.text.modernity.*))
|
||||||
*(SORT_BY_ALIGNMENT(.text.hot))
|
*(SORT_BY_ALIGNMENT(.text.hot))
|
||||||
|
@ -310,7 +319,7 @@ SECTIONS {
|
||||||
. = ALIGN(__privileged_end > __privileged_start ? CONSTANT(COMMONPAGESIZE) : 0);
|
. = ALIGN(__privileged_end > __privileged_start ? CONSTANT(COMMONPAGESIZE) : 0);
|
||||||
/*END: morphable code */
|
/*END: morphable code */
|
||||||
__privileged_start = .;
|
__privileged_start = .;
|
||||||
*(.privileged .privileged.*)
|
*(.privileged)
|
||||||
__privileged_end = .;
|
__privileged_end = .;
|
||||||
|
|
||||||
KEEP(*(.ape.pad.text))
|
KEEP(*(.ape.pad.text))
|
||||||
|
@ -320,7 +329,7 @@ SECTIONS {
|
||||||
|
|
||||||
/*BEGIN: Read Only Data */
|
/*BEGIN: Read Only Data */
|
||||||
|
|
||||||
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
.rodata . : {
|
||||||
KEEP(*(.rodata.pytab.0));
|
KEEP(*(.rodata.pytab.0));
|
||||||
KEEP(*(.rodata.pytab.1));
|
KEEP(*(.rodata.pytab.1));
|
||||||
KEEP(*(.rodata.pytab.2));
|
KEEP(*(.rodata.pytab.2));
|
||||||
|
@ -329,16 +338,12 @@ SECTIONS {
|
||||||
*(.ubsan.types)
|
*(.ubsan.types)
|
||||||
*(.ubsan.data)
|
*(.ubsan.data)
|
||||||
|
|
||||||
__eh_frame_hdr_start_actual = .;
|
|
||||||
*(.eh_frame_hdr)
|
|
||||||
__eh_frame_hdr_end_actual = .;
|
|
||||||
|
|
||||||
/* Legal Notices */
|
/* Legal Notices */
|
||||||
__notices = .;
|
#if !defined(IM_FEELING_NAUGHTY) || defined(EMBED_NOTICES)
|
||||||
KEEP(*(.notice))
|
KEEP(*(.commentprologue))
|
||||||
BYTE(0);
|
KEEP(*(.comment))
|
||||||
BYTE(10);
|
KEEP(*(.commentepilogue))
|
||||||
BYTE(10);
|
#endif
|
||||||
|
|
||||||
/*BEGIN: read-only data that's only needed for initialization */
|
/*BEGIN: read-only data that's only needed for initialization */
|
||||||
|
|
||||||
|
@ -386,13 +391,6 @@ SECTIONS {
|
||||||
_tbss_end = .;
|
_tbss_end = .;
|
||||||
} :Tls
|
} :Tls
|
||||||
|
|
||||||
.eh_frame : {
|
|
||||||
__eh_frame_start = .;
|
|
||||||
KEEP(*(.eh_frame))
|
|
||||||
*(.eh_frame.*)
|
|
||||||
__eh_frame_end = .;
|
|
||||||
} :Ram
|
|
||||||
|
|
||||||
.data . : {
|
.data . : {
|
||||||
/*BEGIN: Read/Write Data */
|
/*BEGIN: Read/Write Data */
|
||||||
#if SupportsWindows()
|
#if SupportsWindows()
|
||||||
|
@ -401,28 +399,26 @@ SECTIONS {
|
||||||
/*BEGIN: NT FORK COPYING */
|
/*BEGIN: NT FORK COPYING */
|
||||||
KEEP(*(.dataprologue))
|
KEEP(*(.dataprologue))
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu_extab)
|
|
||||||
*(.gcc_except_table .gcc_except_table.*)
|
|
||||||
*(.exception_ranges*)
|
|
||||||
*(.PyRuntime) /* for python */
|
*(.PyRuntime) /* for python */
|
||||||
*(.subrs) /* for emacs */
|
*(.subrs) /* for emacs */
|
||||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||||
. += . > 0 ? CODE_GRANULE : 0;
|
. += . > 0 ? CODE_GRANULE : 0;
|
||||||
|
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
KEEP(*(.gotprologue))
|
||||||
__got_start = .;
|
|
||||||
*(.got)
|
*(.got)
|
||||||
__got_end = .;
|
KEEP(*(.gotepilogue))
|
||||||
|
|
||||||
|
KEEP(*(.gotpltprologue))
|
||||||
*(.got.plt)
|
*(.got.plt)
|
||||||
|
KEEP(*(.gotpltepilogue))
|
||||||
|
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||||
__init_array_start = .;
|
__init_array_start = .;
|
||||||
KEEP(*(.preinit_array))
|
|
||||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
||||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
KEEP(*(.init_array))
|
|
||||||
KEEP(*(.ctors))
|
KEEP(*(.ctors))
|
||||||
|
KEEP(*(.init_array))
|
||||||
|
KEEP(*(.preinit_array))
|
||||||
__init_array_end = .;
|
__init_array_end = .;
|
||||||
|
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||||
|
@ -439,7 +435,6 @@ SECTIONS {
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||||
KEEP(*(.piro.pad.data))
|
KEEP(*(.piro.pad.data))
|
||||||
*(.igot.plt)
|
|
||||||
KEEP(*(.dataepilogue))
|
KEEP(*(.dataepilogue))
|
||||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
||||||
/*END: NT FORK COPYING */
|
/*END: NT FORK COPYING */
|
||||||
|
@ -520,9 +515,6 @@ SECTIONS {
|
||||||
.debug_rnglists 0 : { *(.debug_rnglists) }
|
.debug_rnglists 0 : { *(.debug_rnglists) }
|
||||||
.debug_macro 0 : { *(.debug_macro) }
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
.debug_addr 0 : { *(.debug_addr) }
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
.debug_names 0 : { *(.debug_names) }
|
|
||||||
.debug_loclists 0 : { *(.debug_loclists) }
|
|
||||||
.debug_str_offsets 0 : { *(.debug_str_offsets) }
|
|
||||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||||
.GCC.command.line 0 : { *(.GCC.command.line) }
|
.GCC.command.line 0 : { *(.GCC.command.line) }
|
||||||
|
|
||||||
|
@ -541,9 +533,7 @@ SECTIONS {
|
||||||
*(.piro.data.sort.iat.*)
|
*(.piro.data.sort.iat.*)
|
||||||
#endif
|
#endif
|
||||||
*(__patchable_function_entries)
|
*(__patchable_function_entries)
|
||||||
*(.note.gnu.property)
|
|
||||||
*(__mcount_loc)
|
*(__mcount_loc)
|
||||||
*(.rela.dyn)
|
|
||||||
*(.discard)
|
*(.discard)
|
||||||
*(.yoink)
|
*(.yoink)
|
||||||
}
|
}
|
||||||
|
@ -566,9 +556,7 @@ _tdata_size = _tdata_end - _tdata_start;
|
||||||
_tbss_size = _tbss_end - _tbss_start;
|
_tbss_size = _tbss_end - _tbss_start;
|
||||||
_tbss_offset = _tbss_start - _tdata_start;
|
_tbss_offset = _tbss_start - _tdata_start;
|
||||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||||
_tdata_align = ALIGNOF(.tdata);
|
_tls_align = 1;
|
||||||
_tbss_align = ALIGNOF(.tbss);
|
|
||||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
|
||||||
|
|
||||||
ape_cod_offset = 0;
|
ape_cod_offset = 0;
|
||||||
ape_cod_vaddr = ADDR(.head);
|
ape_cod_vaddr = ADDR(.head);
|
||||||
|
@ -586,11 +574,11 @@ ape_rom_memsz = ape_rom_filesz;
|
||||||
ape_rom_align = CONSTANT(COMMONPAGESIZE);
|
ape_rom_align = CONSTANT(COMMONPAGESIZE);
|
||||||
ape_rom_rva = RVA(ape_rom_vaddr);
|
ape_rom_rva = RVA(ape_rom_vaddr);
|
||||||
|
|
||||||
ape_ram_vaddr = ADDR(.eh_frame);
|
ape_ram_vaddr = ADDR(.data);
|
||||||
ape_ram_offset = ape_ram_vaddr - __executable_start;
|
ape_ram_offset = ape_ram_vaddr - __executable_start;
|
||||||
ape_ram_paddr = LOADADDR(.eh_frame);
|
ape_ram_paddr = LOADADDR(.data);
|
||||||
ape_ram_filesz = ADDR(.bss) - ADDR(.eh_frame);
|
ape_ram_filesz = ADDR(.bss) - ADDR(.data);
|
||||||
ape_ram_memsz = _end - ADDR(.eh_frame);
|
ape_ram_memsz = _end - ADDR(.data);
|
||||||
ape_ram_align = CONSTANT(COMMONPAGESIZE);
|
ape_ram_align = CONSTANT(COMMONPAGESIZE);
|
||||||
ape_ram_rva = RVA(ape_ram_vaddr);
|
ape_ram_rva = RVA(ape_ram_vaddr);
|
||||||
|
|
||||||
|
@ -600,7 +588,9 @@ ape_stack_offset = 0;
|
||||||
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
||||||
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
|
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
|
||||||
ape_stack_filesz = 0;
|
ape_stack_filesz = 0;
|
||||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 4 * 1024 * 1024;
|
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
|
||||||
|
ape_stack_align = DEFINED(ape_stack_align) ? ape_stack_align : 16;
|
||||||
|
ape_stack_round = -ape_stack_align;
|
||||||
|
|
||||||
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
|
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
|
||||||
ape_note_filesz = ape_note_end - ape_note;
|
ape_note_filesz = ape_note_end - ape_note;
|
||||||
|
@ -614,9 +604,6 @@ ape_text_memsz = ape_text_filesz;
|
||||||
ape_text_align = CONSTANT(COMMONPAGESIZE);
|
ape_text_align = CONSTANT(COMMONPAGESIZE);
|
||||||
ape_text_rva = RVA(ape_text_vaddr);
|
ape_text_rva = RVA(ape_text_vaddr);
|
||||||
|
|
||||||
__eh_frame_hdr_start = __eh_frame_hdr_end_actual > __eh_frame_hdr_start_actual ? __eh_frame_hdr_start_actual : 0;
|
|
||||||
__eh_frame_hdr_end = __eh_frame_hdr_end_actual > __eh_frame_hdr_start_actual ? __eh_frame_hdr_end_actual : 0;
|
|
||||||
|
|
||||||
/* we roundup here because xnu wants the file load segments page-aligned */
|
/* we roundup here because xnu wants the file load segments page-aligned */
|
||||||
/* but we don't want to add the nop padding to the ape program, so we'll */
|
/* but we don't want to add the nop padding to the ape program, so we'll */
|
||||||
/* let ape.S dd read past the end of the file into the wrapping binaries */
|
/* let ape.S dd read past the end of the file into the wrapping binaries */
|
||||||
|
@ -626,6 +613,29 @@ SHSTUB2(ape_loader_dd_count,
|
||||||
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
|
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
|
||||||
: 0);
|
: 0);
|
||||||
|
|
||||||
|
#if defined(APE_IS_SHELL_SCRIPT) && !IsTiny()
|
||||||
|
|
||||||
|
#define IDENTITY(X) X
|
||||||
|
|
||||||
|
#define APE_DECLARE_FIXED_DECIMAL(F, X) \
|
||||||
|
X##_quad = DEFINED(X) ? ((F(X) < 1000000000 ? 32 : F(X) / 1000000000 % 10 + 48) << 000 | \
|
||||||
|
(F(X) < 100000000 ? 32 : F(X) / 100000000 % 10 + 48) << 010 | \
|
||||||
|
(F(X) < 10000000 ? 32 : F(X) / 10000000 % 10 + 48) << 020 | \
|
||||||
|
(F(X) < 1000000 ? 32 : F(X) / 1000000 % 10 + 48) << 030 | \
|
||||||
|
(F(X) < 100000 ? 32 : F(X) / 100000 % 10 + 48) << 040 | \
|
||||||
|
(F(X) < 10000 ? 32 : F(X) / 10000 % 10 + 48) << 050 | \
|
||||||
|
(F(X) < 1000 ? 32 : F(X) / 1000 % 10 + 48) << 060 | \
|
||||||
|
(F(X) < 100 ? 32 : F(X) / 100 % 10 + 48) << 070) : 0; \
|
||||||
|
X##_short = DEFINED(X) ? ((F(X) < 10 ? 32 : F(X) / 10 % 10 + 48) << 000 | \
|
||||||
|
(F(X) % 10 + 48) << 010) : 0
|
||||||
|
|
||||||
|
APE_DECLARE_FIXED_DECIMAL(RVA, blink_linux_aarch64);
|
||||||
|
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_linux_aarch64_size);
|
||||||
|
APE_DECLARE_FIXED_DECIMAL(RVA, blink_xnu_aarch64);
|
||||||
|
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_xnu_aarch64_size);
|
||||||
|
|
||||||
|
#endif /* APE_IS_SHELL_SCRIPT */
|
||||||
|
|
||||||
#if SupportsMetal()
|
#if SupportsMetal()
|
||||||
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
|
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
|
||||||
v_ape_realbytes = v_ape_realsectors * 512;
|
v_ape_realbytes = v_ape_realsectors * 512;
|
||||||
|
@ -729,6 +739,7 @@ ape_idataz = LINK_WINDOWS ? RVA(ape_idata_iat) : 0;
|
||||||
ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0;
|
ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0;
|
||||||
ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0;
|
ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0;
|
||||||
ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0;
|
ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0;
|
||||||
|
v_ntversion = LINK_WINDOWS ? 6 : 1;
|
||||||
v_ntdllchar = LINK_WINDOWS ? 288 : 0;
|
v_ntdllchar = LINK_WINDOWS ? 288 : 0;
|
||||||
v_ntsubversion = LINK_WINDOWS ? 6 : 5;
|
v_ntsubversion = LINK_WINDOWS ? 6 : 5;
|
||||||
v_ntsubsystem = (LINK_WINDOWS
|
v_ntsubsystem = (LINK_WINDOWS
|
||||||
|
|
287
ape/ape.mk
Normal file
287
ape/ape.mk
Normal file
|
@ -0,0 +1,287 @@
|
||||||
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
|
#
|
||||||
|
# OVERVIEW
|
||||||
|
#
|
||||||
|
# αcτµαlly pδrταblε εxεcµταblε
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# This file defines the libraries, runtimes, and build rules needed to
|
||||||
|
# create executables from your Linux workstation that'll run anywhere.
|
||||||
|
# Loading this package will make certain systemic modifications to the
|
||||||
|
# build like turning off the System V "Red Zone" optimization, because
|
||||||
|
# αcτµαlly pδrταblε εxεcµταblεs need to be able to run in kernelspace.
|
||||||
|
|
||||||
|
PKGS += APE
|
||||||
|
|
||||||
|
APE_FILES := $(wildcard ape/*.*)
|
||||||
|
APE_HDRS = $(filter %.h,$(APE_FILES))
|
||||||
|
APE_INCS = $(filter %.inc,$(APE_FILES))
|
||||||
|
|
||||||
|
ifeq ($(ARCH), aarch64)
|
||||||
|
|
||||||
|
APE = o/$(MODE)/ape/aarch64.lds
|
||||||
|
|
||||||
|
APELINK = \
|
||||||
|
$(COMPILE) \
|
||||||
|
-ALINK.ape \
|
||||||
|
$(LINK) \
|
||||||
|
$(LINKARGS) \
|
||||||
|
$(OUTPUT_OPTION) && \
|
||||||
|
$(COMPILE) \
|
||||||
|
-AFIXUP.ape \
|
||||||
|
-wT$@ \
|
||||||
|
$(FIXUPOBJ) \
|
||||||
|
$@
|
||||||
|
|
||||||
|
APE_SRCS = ape/ape.S ape/start.S ape/launch.S ape/systemcall.S
|
||||||
|
APE_OBJS = o/$(MODE)/ape/ape.o
|
||||||
|
APE_NO_MODIFY_SELF = $(APE)
|
||||||
|
APE_COPY_SELF = $(APE)
|
||||||
|
|
||||||
|
.PHONY: o/$(MODE)/ape
|
||||||
|
o/$(MODE)/ape: $(APE)
|
||||||
|
|
||||||
|
o/$(MODE)/ape/aarch64.lds: \
|
||||||
|
ape/aarch64.lds \
|
||||||
|
libc/zip.internal.h \
|
||||||
|
libc/intrin/bits.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
|
libc/calls/struct/timespec.h \
|
||||||
|
libc/macros.internal.h \
|
||||||
|
libc/str/str.h
|
||||||
|
|
||||||
|
APE_LOADER_LDFLAGS = \
|
||||||
|
-pie \
|
||||||
|
-static \
|
||||||
|
-nostdlib \
|
||||||
|
--no-dynamic-linker \
|
||||||
|
-z norelro \
|
||||||
|
-z common-page-size=0x4000 \
|
||||||
|
-z max-page-size=0x4000
|
||||||
|
|
||||||
|
APE_LOADER_FLAGS = \
|
||||||
|
-DNDEBUG \
|
||||||
|
-iquote. \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-fpie \
|
||||||
|
-Os \
|
||||||
|
-ffreestanding \
|
||||||
|
-mgeneral-regs-only \
|
||||||
|
-fno-asynchronous-unwind-tables \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-ident \
|
||||||
|
-fno-gnu-unique \
|
||||||
|
-c \
|
||||||
|
$(OUTPUT_OPTION) \
|
||||||
|
$<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||||
|
$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.elf.dbg: \
|
||||||
|
o/$(MODE)/ape/start.o \
|
||||||
|
o/$(MODE)/ape/loader.o \
|
||||||
|
o/$(MODE)/ape/launch.o \
|
||||||
|
o/$(MODE)/ape/systemcall.o
|
||||||
|
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
||||||
|
|
||||||
|
o/$(MODE)/ape/loader.o: ape/loader.c ape/ape.h
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/start.o: ape/start.S
|
||||||
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
o/$(MODE)/ape/launch.o: ape/launch.S
|
||||||
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
o/$(MODE)/ape/systemcall.o: ape/systemcall.S
|
||||||
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
|
||||||
|
.PHONY: o/$(MODE)/ape
|
||||||
|
o/$(MODE)/ape: o/$(MODE)/ape/ape.elf
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
APE = o/$(MODE)/ape/ape.o \
|
||||||
|
o/$(MODE)/ape/ape.lds
|
||||||
|
|
||||||
|
APELINK = \
|
||||||
|
$(COMPILE) \
|
||||||
|
-ALINK.ape \
|
||||||
|
$(LINK) \
|
||||||
|
$(LINKARGS) \
|
||||||
|
$(OUTPUT_OPTION) && \
|
||||||
|
$(COMPILE) \
|
||||||
|
-AFIXUP.ape \
|
||||||
|
-wT$@ \
|
||||||
|
$(FIXUPOBJ) \
|
||||||
|
$@
|
||||||
|
|
||||||
|
APE_NO_MODIFY_SELF = \
|
||||||
|
o/$(MODE)/ape/ape.lds \
|
||||||
|
o/$(MODE)/ape/ape-no-modify-self.o
|
||||||
|
|
||||||
|
APE_COPY_SELF = \
|
||||||
|
o/$(MODE)/ape/ape.lds \
|
||||||
|
o/$(MODE)/ape/ape-copy-self.o
|
||||||
|
|
||||||
|
APE_LOADER_FLAGS = \
|
||||||
|
-DNDEBUG \
|
||||||
|
-iquote. \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-Werror \
|
||||||
|
-pedantic-errors \
|
||||||
|
-fpie \
|
||||||
|
-Os \
|
||||||
|
-ffreestanding \
|
||||||
|
-mgeneral-regs-only \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-ident \
|
||||||
|
-fno-gnu-unique \
|
||||||
|
-c \
|
||||||
|
$(OUTPUT_OPTION) \
|
||||||
|
$<
|
||||||
|
|
||||||
|
APE_SRCS_C = ape/loader.c
|
||||||
|
APE_SRCS_S = $(filter %.S,$(APE_FILES))
|
||||||
|
APE_SRCS = $(APE_SRCS_C) $(APE_SRCS_S)
|
||||||
|
APE_OBJS = $(APE_SRCS_S:%.S=o/$(MODE)/%.o)
|
||||||
|
APE_CHECKS = $(APE_HDRS:%=o/%.ok)
|
||||||
|
|
||||||
|
o/ape/idata.inc: \
|
||||||
|
ape/idata.internal.h \
|
||||||
|
ape/relocations.h
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||||
|
ape/ape.S \
|
||||||
|
ape/ape.h \
|
||||||
|
ape/macros.internal.h \
|
||||||
|
ape/notice.inc \
|
||||||
|
ape/relocations.h \
|
||||||
|
ape/ape.internal.h \
|
||||||
|
libc/dce.h \
|
||||||
|
libc/elf/def.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
|
libc/intrin/asancodes.h \
|
||||||
|
libc/macho.internal.h \
|
||||||
|
libc/macros.internal.h \
|
||||||
|
libc/nexgen32e/uart.internal.h \
|
||||||
|
libc/calls/metalfile.internal.h \
|
||||||
|
libc/nexgen32e/vidya.internal.h \
|
||||||
|
libc/nt/pedef.internal.h \
|
||||||
|
libc/runtime/e820.internal.h \
|
||||||
|
libc/runtime/mman.internal.h \
|
||||||
|
libc/runtime/pc.internal.h \
|
||||||
|
libc/sysv/consts/prot.h \
|
||||||
|
ape/blink-linux-aarch64.gz \
|
||||||
|
ape/blink-xnu-aarch64.gz \
|
||||||
|
o/$(MODE)/ape/ape.elf
|
||||||
|
@$(COMPILE) \
|
||||||
|
-AOBJECTIFY.S \
|
||||||
|
$(OBJECTIFY.S) \
|
||||||
|
$(OUTPUT_OPTION) \
|
||||||
|
-DAPE_NO_MODIFY_SELF \
|
||||||
|
-DAPE_LOADER='"o/$(MODE)/ape/ape.elf"' $<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape-copy-self.o: \
|
||||||
|
ape/ape.S \
|
||||||
|
ape/ape.h \
|
||||||
|
ape/macros.internal.h \
|
||||||
|
ape/notice.inc \
|
||||||
|
ape/relocations.h \
|
||||||
|
ape/ape.internal.h \
|
||||||
|
libc/dce.h \
|
||||||
|
libc/elf/def.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
|
libc/intrin/asancodes.h \
|
||||||
|
libc/macho.internal.h \
|
||||||
|
libc/macros.internal.h \
|
||||||
|
libc/nexgen32e/uart.internal.h \
|
||||||
|
libc/calls/metalfile.internal.h \
|
||||||
|
libc/nexgen32e/vidya.internal.h \
|
||||||
|
libc/nt/pedef.internal.h \
|
||||||
|
libc/runtime/e820.internal.h \
|
||||||
|
libc/runtime/mman.internal.h \
|
||||||
|
libc/runtime/pc.internal.h \
|
||||||
|
libc/sysv/consts/prot.h \
|
||||||
|
ape/blink-linux-aarch64.gz \
|
||||||
|
ape/blink-xnu-aarch64.gz
|
||||||
|
@$(COMPILE) \
|
||||||
|
-AOBJECTIFY.S \
|
||||||
|
$(OBJECTIFY.S) \
|
||||||
|
$(OUTPUT_OPTION) \
|
||||||
|
-DAPE_NO_MODIFY_SELF $<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/loader.o: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -g $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/loader-gcc.asm: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/loader-clang.asm: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
||||||
|
|
||||||
|
o/$(MODE)/ape/loader-xnu.o: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -g $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/loader-xnu-gcc.asm: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||||
|
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy.com -f -o $@ $<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.elf.dbg
|
||||||
|
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy.com -fm -o $@ $<
|
||||||
|
|
||||||
|
APE_LOADER_LDFLAGS = \
|
||||||
|
-static \
|
||||||
|
-nostdlib \
|
||||||
|
--no-dynamic-linker \
|
||||||
|
-z separate-code \
|
||||||
|
-z common-page-size=0x1000 \
|
||||||
|
-z max-page-size=0x10000
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.elf.dbg: \
|
||||||
|
o/$(MODE)/ape/loader-macho.o \
|
||||||
|
o/$(MODE)/ape/start.o \
|
||||||
|
o/$(MODE)/ape/loader.o \
|
||||||
|
o/$(MODE)/ape/launch.o \
|
||||||
|
o/$(MODE)/ape/systemcall.o \
|
||||||
|
ape/loader.lds
|
||||||
|
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
||||||
|
|
||||||
|
.PHONY: o/$(MODE)/ape
|
||||||
|
o/$(MODE)/ape: $(APE_CHECKS) \
|
||||||
|
o/$(MODE)/ape/ape.o \
|
||||||
|
o/$(MODE)/ape/ape.lds \
|
||||||
|
o/$(MODE)/ape/ape.elf \
|
||||||
|
o/$(MODE)/ape/ape.macho \
|
||||||
|
o/$(MODE)/ape/ape-copy-self.o \
|
||||||
|
o/$(MODE)/ape/ape-no-modify-self.o
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
# these assembly files are safe to build on aarch64
|
||||||
|
o/$(MODE)/ape/ape.o: ape/ape.S
|
||||||
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.o: \
|
||||||
|
ape/blink-linux-aarch64.gz \
|
||||||
|
ape/blink-xnu-aarch64.gz
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.lds: \
|
||||||
|
ape/ape.lds \
|
||||||
|
ape/macros.internal.h \
|
||||||
|
ape/relocations.h \
|
||||||
|
ape/ape.internal.h \
|
||||||
|
libc/intrin/bits.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
|
libc/calls/struct/timespec.h \
|
||||||
|
libc/thread/thread.h \
|
||||||
|
libc/dce.h \
|
||||||
|
libc/elf/def.h \
|
||||||
|
libc/elf/pf2prot.internal.h \
|
||||||
|
libc/macros.internal.h \
|
||||||
|
libc/nt/pedef.internal.h \
|
||||||
|
libc/str/str.h \
|
||||||
|
libc/zip.internal.h
|
|
@ -1,180 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
PROG=${0##*/}
|
|
||||||
MODE=${MODE:-$m}
|
|
||||||
TMPDIR=${TMPDIR:-/tmp}
|
|
||||||
COSMO=${COSMO:-/opt/cosmo}
|
|
||||||
COSMOS=${COSMOS:-/opt/cosmos}
|
|
||||||
|
|
||||||
if [ ! -f ape/loader.c ]; then
|
|
||||||
cd "$COSMO" || exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -x .cosmocc/current/bin/make ]; then
|
|
||||||
MAKE=.cosmocc/current/bin/make
|
|
||||||
else
|
|
||||||
MAKE=make
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$(id -u)" -eq 0 ]; then
|
|
||||||
SUDO=
|
|
||||||
elif command -v sudo >/dev/null 2>&1; then
|
|
||||||
SUDO=sudo
|
|
||||||
elif command -v doas >/dev/null 2>&1; then
|
|
||||||
SUDO=doas
|
|
||||||
else
|
|
||||||
echo "need root or sudo" >&2
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if command -v install >/dev/null 2>&1; then
|
|
||||||
if [ x"$(uname -s)" = xLinux ]; then
|
|
||||||
INSTALL="install -o root -g root -m 755"
|
|
||||||
else
|
|
||||||
INSTALL="install -o root -g wheel -m 755"
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
INSTALL="cp -f"
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Actually Portable Executable (APE) Installer" >&2
|
|
||||||
echo "Author: Justine Tunney <jtunney@gmail.com>" >&2
|
|
||||||
|
|
||||||
# special installation process for apple silicon
|
|
||||||
if [ x"$(uname -s)" = xDarwin ] && [ x"$(uname -m)" = xarm64 ]; then
|
|
||||||
echo "cc -O -o $TMPDIR/ape.$$ ape/ape-m1.c" >&2
|
|
||||||
cc -O -o "$TMPDIR/ape.$$" ape/ape-m1.c || exit
|
|
||||||
trap 'rm "$TMPDIR/ape.$$"' EXIT
|
|
||||||
if [ ! -d /usr/local/bin ]; then
|
|
||||||
echo "$SUDO mkdir -p /usr/local/bin" >&2
|
|
||||||
$SUDO mkdir -p /usr/local/bin || exit
|
|
||||||
fi
|
|
||||||
echo "$SUDO $INSTALL $TMPDIR/ape.$$ /usr/local/bin/ape" >&2
|
|
||||||
$SUDO $INSTALL "$TMPDIR/ape.$$" /usr/local/bin/ape || exit
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ x"$(uname -m)" = xarm64 ] || [ x"$(uname -m)" = xaarch64 ]; then
|
|
||||||
MODE=aarch64
|
|
||||||
EXT=elf
|
|
||||||
BEXT=aarch64
|
|
||||||
elif [ x"$(uname -m)" = xx86_64 ]; then
|
|
||||||
MODE=
|
|
||||||
if [ x"$(uname -s)" = xDarwin ]; then
|
|
||||||
EXT=macho
|
|
||||||
else
|
|
||||||
EXT=elf
|
|
||||||
fi
|
|
||||||
BEXT=$EXT
|
|
||||||
else
|
|
||||||
echo "unsupported architecture $(uname -m)" >&2
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# INSTALL APE LOADER SYSTEMWIDE
|
|
||||||
|
|
||||||
if [ -f o/$MODE/depend ] && $MAKE -j8 o/$MODE/ape; then
|
|
||||||
echo "successfully recompiled ape loader" >&2
|
|
||||||
elif [ -x o/$MODE/ape/ape.$EXT ]; then
|
|
||||||
echo "using ape loader you compiled earlier" >&2
|
|
||||||
elif [ -d build/bootstrap ]; then
|
|
||||||
# if make isn't being used then it's unlikely the user changed the sources
|
|
||||||
# in that case the prebuilt binaries should be completely up-to-date
|
|
||||||
echo "using prebuilt ape loader from cosmo repo" >&2
|
|
||||||
mkdir -p o/$MODE/ape || exit
|
|
||||||
cp -af build/bootstrap/ape.$BEXT o/$MODE/ape/ape.$EXT || exit
|
|
||||||
else
|
|
||||||
echo "no cosmopolitan libc repository here" >&2
|
|
||||||
echo "fetching ape loader from justine.lol" >&2
|
|
||||||
mkdir -p o/$MODE/ape || exit
|
|
||||||
if command -v wget >/dev/null 2>&1; then
|
|
||||||
wget -qO o/$MODE/ape/ape.$EXT https://justine.lol/ape.$BEXT || exit
|
|
||||||
else
|
|
||||||
curl -Rso o/$MODE/ape/ape.$EXT https://justine.lol/ape.$BEXT || exit
|
|
||||||
fi
|
|
||||||
chmod +x o/$MODE/ape/ape.$EXT || exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [ /usr/bin/ape -nt o/$MODE/ape/ape.$EXT ]; then
|
|
||||||
echo >&2
|
|
||||||
echo "installing o/$MODE/ape/ape.$EXT to /usr/bin/ape" >&2
|
|
||||||
echo "$SUDO $INSTALL o/$MODE/ape/ape.$EXT /usr/bin/ape" >&2
|
|
||||||
$SUDO $INSTALL o/$MODE/ape/ape.$EXT /usr/bin/ape || exit
|
|
||||||
echo "done" >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
# REGISTER APE LOADER WITH BINFMT_MISC TOO (LINUX-ONLY)
|
|
||||||
|
|
||||||
if [ x"$(uname -s)" = xLinux ]; then
|
|
||||||
|
|
||||||
if [ -e /proc/sys/fs/binfmt_misc/APE ]; then
|
|
||||||
echo >&2
|
|
||||||
echo it looks like APE is already registered with binfmt_misc >&2
|
|
||||||
echo To reinstall please run ape/apeuninstall.sh first >&2
|
|
||||||
echo please check that it is mapped to ape not /bin/sh >&2
|
|
||||||
echo cat /proc/sys/fs/binfmt_misc/APE >&2
|
|
||||||
cat /proc/sys/fs/binfmt_misc/APE >&2
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [ -e /proc/sys/fs/binfmt_misc ]; then
|
|
||||||
echo >&2
|
|
||||||
echo loading binfmt_misc into your kernel >&2
|
|
||||||
echo you may need to edit configs to persist across reboot >&2
|
|
||||||
echo $SUDO modprobe binfmt_misc >&2
|
|
||||||
$SUDO modprobe binfmt_misc || exit
|
|
||||||
echo done >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
if ! [ -e /proc/sys/fs/binfmt_misc/register ]; then
|
|
||||||
echo >&2
|
|
||||||
echo mounting binfmt_misc into your kernel >&2
|
|
||||||
echo you may need to edit configs to persist across reboot >&2
|
|
||||||
echo $SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc >&2
|
|
||||||
$SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc || exit
|
|
||||||
echo done >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
uname_r="$(uname -r)"
|
|
||||||
if printf '%s\n%s\n' 5.12 "$uname_r" | sort -CV; then
|
|
||||||
FLAGS=FP
|
|
||||||
else
|
|
||||||
FLAGS=F
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo >&2
|
|
||||||
echo registering APE with binfmt_misc >&2
|
|
||||||
echo you may need to edit configs to persist across reboot >&2
|
|
||||||
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
|
||||||
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
|
||||||
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
|
||||||
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
|
||||||
echo done >&2
|
|
||||||
|
|
||||||
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
|
||||||
echo >&2
|
|
||||||
echo enabling binfmt_misc >&2
|
|
||||||
echo you may need to edit configs to persist across reboot >&2
|
|
||||||
echo $SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' >&2
|
|
||||||
$SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' || exit
|
|
||||||
echo done >&2
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
|
|
||||||
################################################################################
|
|
||||||
|
|
||||||
{
|
|
||||||
echo
|
|
||||||
echo "------------------------------------------------------------------"
|
|
||||||
echo
|
|
||||||
echo "APE INSTALL COMPLETE"
|
|
||||||
echo
|
|
||||||
echo "If you decide to uninstall APE later on"
|
|
||||||
echo "you may do so using ape/apeuninstall.sh"
|
|
||||||
echo
|
|
||||||
echo "Enjoy your APE loader (>'.')>"
|
|
||||||
echo
|
|
||||||
} >&2
|
|
1
ape/apeinstall.sh
Symbolic link
1
ape/apeinstall.sh
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../bin/ape-install
|
|
@ -1,68 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
|
|
||||||
PROG=${0##*/}
|
|
||||||
MODE=${MODE:-$m}
|
|
||||||
COSMO=${COSMO:-/opt/cosmo}
|
|
||||||
COSMOS=${COSMOS:-/opt/cosmos}
|
|
||||||
|
|
||||||
if [ ! -f ape/loader.c ]; then
|
|
||||||
cd "$COSMO" || exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$UID" = "0" ]; then
|
|
||||||
SUDO=
|
|
||||||
elif command -v sudo >/dev/null 2>&1; then
|
|
||||||
SUDO=sudo
|
|
||||||
elif command -v doas >/dev/null 2>&1; then
|
|
||||||
SUDO=doas
|
|
||||||
else
|
|
||||||
echo "need root or sudo" >&2
|
|
||||||
exit
|
|
||||||
fi
|
|
||||||
|
|
||||||
{
|
|
||||||
echo
|
|
||||||
echo "APE Uninstaller intends to run (in pseudo-shell)"
|
|
||||||
echo
|
|
||||||
echo " sudo echo -1 into /proc/sys/fs/binfmt_misc/APE*"
|
|
||||||
echo " sudo rm -f /usr/bin/ape ~/.ape /tmp/.ape # etc."
|
|
||||||
echo
|
|
||||||
echo "You may then use ape/apeinstall.sh to reinstall it"
|
|
||||||
echo
|
|
||||||
} >&2
|
|
||||||
|
|
||||||
set -ex
|
|
||||||
for f in /proc/sys/fs/binfmt_misc/APE*; do
|
|
||||||
if [ -f $f ]; then
|
|
||||||
$SUDO sh -c "echo -1 >$f" || exit
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
# system installation
|
|
||||||
if [ -f /usr/bin/ape ]; then
|
|
||||||
$SUDO rm -f /usr/bin/ape
|
|
||||||
fi
|
|
||||||
if [ -f /usr/local/bin/ape ]; then
|
|
||||||
$SUDO rm -f /usr/local/bin/ape
|
|
||||||
fi
|
|
||||||
|
|
||||||
# legacy installations
|
|
||||||
rm -f o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape"
|
|
||||||
|
|
||||||
# ad-hoc installations
|
|
||||||
for x in .ape \
|
|
||||||
.ape-1.1 \
|
|
||||||
.ape-1.3 \
|
|
||||||
.ape-1.4 \
|
|
||||||
.ape-1.5 \
|
|
||||||
.ape-1.6 \
|
|
||||||
.ape-1.7 \
|
|
||||||
.ape-1.8 \
|
|
||||||
.ape-1.9 \
|
|
||||||
.ape-1.10; do
|
|
||||||
rm -f \
|
|
||||||
~/$x \
|
|
||||||
/tmp/$x \
|
|
||||||
o/tmp/$x \
|
|
||||||
"${TMPDIR:-/tmp}/$x"
|
|
||||||
done
|
|
1
ape/apeuninstall.sh
Symbolic link
1
ape/apeuninstall.sh
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
../bin/ape-uninstall
|
BIN
ape/blink-linux-aarch64.gz
Normal file
BIN
ape/blink-linux-aarch64.gz
Normal file
Binary file not shown.
BIN
ape/blink-xnu-aarch64.gz
Executable file
BIN
ape/blink-xnu-aarch64.gz
Executable file
Binary file not shown.
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
|
14
ape/launch.S
14
ape/launch.S
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
// Calls _start() function of loaded program.
|
// Calls _start() function of loaded program.
|
||||||
//
|
//
|
||||||
|
@ -31,16 +31,17 @@
|
||||||
//
|
//
|
||||||
// @param rdi is passed through as-is
|
// @param rdi is passed through as-is
|
||||||
// @param rsi is address of entrypoint (becomes zero)
|
// @param rsi is address of entrypoint (becomes zero)
|
||||||
// @param rdx is passed through as-is
|
// @param rdx is stack pointer (becomes zero)
|
||||||
// @param rcx is passed through as-is
|
// @param rcx is passed through as-is
|
||||||
// @param r8 is stack pointer (becomes zero)
|
|
||||||
// @noreturn
|
// @noreturn
|
||||||
Launch:
|
Launch:
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
|
|
||||||
mov x16,x1
|
mov x16,x1
|
||||||
mov sp,x4
|
mov sp,x2
|
||||||
mov x1,0
|
mov x1,0
|
||||||
|
mov x2,0
|
||||||
|
mov x3,0
|
||||||
mov x4,0
|
mov x4,0
|
||||||
mov x5,0
|
mov x5,0
|
||||||
mov x6,0
|
mov x6,0
|
||||||
|
@ -70,7 +71,6 @@ Launch:
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
mov %r8,%rsp
|
|
||||||
xor %r8d,%r8d
|
xor %r8d,%r8d
|
||||||
xor %r9d,%r9d
|
xor %r9d,%r9d
|
||||||
xor %r10d,%r10d
|
xor %r10d,%r10d
|
||||||
|
@ -79,6 +79,8 @@ Launch:
|
||||||
xor %r13d,%r13d
|
xor %r13d,%r13d
|
||||||
xor %r14d,%r14d
|
xor %r14d,%r14d
|
||||||
xor %r15d,%r15d
|
xor %r15d,%r15d
|
||||||
|
mov %rdx,%rsp
|
||||||
|
xor %edx,%edx
|
||||||
push %rsi
|
push %rsi
|
||||||
xor %esi,%esi
|
xor %esi,%esi
|
||||||
xor %ebp,%ebp
|
xor %ebp,%ebp
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -16,13 +16,13 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macho.h"
|
#include "libc/macho.internal.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
// Apple Mach-O Executable Headers
|
// Apple Mach-O Executable Headers
|
||||||
// Fixups are applied by objbincopy
|
// Fixups are applied by objbincopy.com
|
||||||
// There must exist a MAC_LC_SEGMENT_64 for every PT_LOAD
|
// There must exist a MAC_LC_SEGMENT_64 for every PT_LOAD
|
||||||
|
|
||||||
.section .macho,"a",@progbits
|
.section .macho,"a",@progbits
|
||||||
|
|
358
ape/loader.c
358
ape/loader.c
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -87,8 +87,6 @@
|
||||||
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
||||||
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
||||||
|
|
||||||
#define PATH_MAX 1024 /* XXX verify */
|
|
||||||
|
|
||||||
#define SupportsLinux() (SUPPORT_VECTOR & LINUX)
|
#define SupportsLinux() (SUPPORT_VECTOR & LINUX)
|
||||||
#define SupportsXnu() (SUPPORT_VECTOR & XNU)
|
#define SupportsXnu() (SUPPORT_VECTOR & XNU)
|
||||||
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
|
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
|
||||||
|
@ -113,47 +111,41 @@
|
||||||
#define EXTERN_C
|
#define EXTERN_C
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define O_RDONLY 0
|
#define O_RDONLY 0
|
||||||
#define PROT_NONE 0
|
#define PROT_NONE 0
|
||||||
#define PROT_READ 1
|
#define PROT_READ 1
|
||||||
#define PROT_WRITE 2
|
#define PROT_WRITE 2
|
||||||
#define PROT_EXEC 4
|
#define PROT_EXEC 4
|
||||||
#define MAP_SHARED 1
|
#define MAP_SHARED 1
|
||||||
#define MAP_PRIVATE 2
|
#define MAP_PRIVATE 2
|
||||||
#define MAP_FIXED 16
|
#define MAP_FIXED 16
|
||||||
#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096)
|
#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096)
|
||||||
#define MAP_NORESERVE (IsLinux() ? 16384 : 0)
|
#define MAP_NORESERVE (IsLinux() ? 16384 : 0)
|
||||||
#define ELFCLASS32 1
|
#define ELFCLASS32 1
|
||||||
#define ELFDATA2LSB 1
|
#define ELFDATA2LSB 1
|
||||||
#define EM_NEXGEN32E 62
|
#define EM_NEXGEN32E 62
|
||||||
#define EM_AARCH64 183
|
#define EM_AARCH64 183
|
||||||
#define ET_EXEC 2
|
#define ET_EXEC 2
|
||||||
#define ET_DYN 3
|
#define ET_DYN 3
|
||||||
#define PT_LOAD 1
|
#define PT_LOAD 1
|
||||||
#define PT_DYNAMIC 2
|
#define PT_DYNAMIC 2
|
||||||
#define PT_INTERP 3
|
#define PT_INTERP 3
|
||||||
#define EI_CLASS 4
|
#define EI_CLASS 4
|
||||||
#define EI_DATA 5
|
#define EI_DATA 5
|
||||||
#define PF_X 1
|
#define PF_X 1
|
||||||
#define PF_W 2
|
#define PF_W 2
|
||||||
#define PF_R 4
|
#define PF_R 4
|
||||||
#define AT_PHDR 3
|
#define AT_PHDR 3
|
||||||
#define AT_PHENT 4
|
#define AT_PHENT 4
|
||||||
#define AT_PHNUM 5
|
#define AT_PHNUM 5
|
||||||
#define AT_PAGESZ 6
|
#define AT_PAGESZ 6
|
||||||
#define AT_FLAGS 8
|
#define AT_EXECFN_LINUX 31
|
||||||
#define AT_FLAGS_PRESERVE_ARGV0_BIT 0
|
#define AT_EXECFN_NETBSD 2014
|
||||||
#define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
|
#define X_OK 1
|
||||||
#define AT_EXECFN_LINUX 31
|
#define XCR0_SSE 2
|
||||||
#define AT_EXECFN_NETBSD 2014
|
#define XCR0_AVX 4
|
||||||
#define X_OK 1
|
#define PR_SET_MM 35
|
||||||
#define XCR0_SSE 2
|
#define PR_SET_MM_EXE_FILE 13
|
||||||
#define XCR0_AVX 4
|
|
||||||
#define PR_SET_MM 35
|
|
||||||
#define PR_SET_MM_EXE_FILE 13
|
|
||||||
|
|
||||||
#define EF_APE_MODERN 0x101ca75
|
|
||||||
#define EF_APE_MODERN_MASK 0x1ffffff
|
|
||||||
|
|
||||||
#define READ32(S) \
|
#define READ32(S) \
|
||||||
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
||||||
|
@ -169,6 +161,13 @@
|
||||||
(unsigned long)(255 & (S)[1]) << 010 | \
|
(unsigned long)(255 & (S)[1]) << 010 | \
|
||||||
(unsigned long)(255 & (S)[0]) << 000)
|
(unsigned long)(255 & (S)[0]) << 000)
|
||||||
|
|
||||||
|
#define DEBUG(VAR) \
|
||||||
|
{ \
|
||||||
|
char ibuf[19] = {0}; \
|
||||||
|
Utox(ibuf, VAR); \
|
||||||
|
Print(os, 2, ibuf, " " #VAR, "\n", 0l); \
|
||||||
|
}
|
||||||
|
|
||||||
struct ElfEhdr {
|
struct ElfEhdr {
|
||||||
unsigned char e_ident[16];
|
unsigned char e_ident[16];
|
||||||
unsigned short e_type;
|
unsigned short e_type;
|
||||||
|
@ -213,43 +212,39 @@ struct PathSearcher {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *syspath;
|
const char *syspath;
|
||||||
unsigned long namelen;
|
unsigned long namelen;
|
||||||
char path[PATH_MAX];
|
char path[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ApeLoader {
|
struct ApeLoader {
|
||||||
union ElfPhdrBuf phdr;
|
union ElfPhdrBuf phdr;
|
||||||
struct PathSearcher ps;
|
struct PathSearcher ps;
|
||||||
char path[PATH_MAX];
|
char path[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
|
EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
|
||||||
EXTERN_C void Launch(void *, long, void *, int, void *)
|
EXTERN_C void Launch(void *, long, void *, int) __attribute__((__noreturn__));
|
||||||
__attribute__((__noreturn__));
|
|
||||||
|
|
||||||
extern char __executable_start[];
|
extern char __executable_start[];
|
||||||
extern char _end[];
|
extern char _end[];
|
||||||
|
|
||||||
static unsigned long StrLen(const char *s) {
|
static unsigned long StrLen(const char *s) {
|
||||||
unsigned long n = 0;
|
unsigned long n = 0;
|
||||||
while (*s++)
|
while (*s++) ++n;
|
||||||
++n;
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int StrCmp(const char *l, const char *r) {
|
static int StrCmp(const char *l, const char *r) {
|
||||||
unsigned long i = 0;
|
unsigned long i = 0;
|
||||||
while (l[i] == r[i] && r[i])
|
while (l[i] == r[i] && r[i]) ++i;
|
||||||
++i;
|
|
||||||
return (l[i] & 255) - (r[i] & 255);
|
return (l[i] & 255) - (r[i] & 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static const char *BaseName(const char *s) {
|
||||||
|
int c;
|
||||||
static const char *StrRChr(const char *s, int c) {
|
const char *b = "";
|
||||||
const char *b = 0;
|
|
||||||
if (s) {
|
if (s) {
|
||||||
for (; *s; ++s) {
|
while ((c = *s++)) {
|
||||||
if (*s == c) {
|
if (c == '/') {
|
||||||
b = s;
|
b = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,13 +252,6 @@ static const char *StrRChr(const char *s, int c) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *BaseName(const char *s) {
|
|
||||||
const char *b = StrRChr(s, '/');
|
|
||||||
return b ? b + 1 : s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void Bzero(void *a, unsigned long n) {
|
static void Bzero(void *a, unsigned long n) {
|
||||||
long z;
|
long z;
|
||||||
char *p, *e;
|
char *p, *e;
|
||||||
|
@ -338,7 +326,24 @@ static char *GetEnv(char **p, const char *s) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *Utoa(char p[20], unsigned long x) {
|
static char *Utox(char p[19], unsigned long x) {
|
||||||
|
int i;
|
||||||
|
if (x) {
|
||||||
|
*p++ = '0';
|
||||||
|
*p++ = 'x';
|
||||||
|
i = (__builtin_clzl(x) ^ (sizeof(long) * 8 - 1)) + 1;
|
||||||
|
i = (i + 3) & -4;
|
||||||
|
do {
|
||||||
|
*p++ = "0123456789abcdef"[(x >> (i -= 4)) & 15];
|
||||||
|
} while (i);
|
||||||
|
} else {
|
||||||
|
*p++ = '0';
|
||||||
|
}
|
||||||
|
*p = 0;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *Utoa(char p[21], unsigned long x) {
|
||||||
char t;
|
char t;
|
||||||
unsigned long i, a, b;
|
unsigned long i, a, b;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -358,8 +363,7 @@ static char *Utoa(char p[20], unsigned long x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *Itoa(char p[21], long x) {
|
static char *Itoa(char p[21], long x) {
|
||||||
if (x < 0)
|
if (x < 0) *p++ = '-', x = -(unsigned long)x;
|
||||||
*p++ = '-', x = -(unsigned long)x;
|
|
||||||
return Utoa(p, x);
|
return Utoa(p, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,8 +372,7 @@ __attribute__((__noinline__)) static long CallSystem(long arg1, long arg2,
|
||||||
long arg5, long arg6,
|
long arg5, long arg6,
|
||||||
long arg7, int numba,
|
long arg7, int numba,
|
||||||
char os) {
|
char os) {
|
||||||
if (IsXnu())
|
if (IsXnu()) numba |= 0x2000000;
|
||||||
numba |= 0x2000000;
|
|
||||||
return SystemCall(arg1, arg2, arg3, arg4, arg5, arg6, arg7, numba);
|
return SystemCall(arg1, arg2, arg3, arg4, arg5, arg6, arg7, numba);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,62 +520,10 @@ static long Print(int os, int fd, const char *s, ...) {
|
||||||
return Write(fd, b, n, os);
|
return Write(fd, b, n, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long Printf(int os, int fd, const char *fmt, ...) {
|
|
||||||
int i;
|
|
||||||
char c;
|
|
||||||
int k = 0;
|
|
||||||
unsigned u;
|
|
||||||
char b[512];
|
|
||||||
const char *s;
|
|
||||||
unsigned long d;
|
|
||||||
__builtin_va_list va;
|
|
||||||
__builtin_va_start(va, fmt);
|
|
||||||
for (;;) {
|
|
||||||
switch ((c = *fmt++)) {
|
|
||||||
case '\0':
|
|
||||||
__builtin_va_end(va);
|
|
||||||
return Write(fd, b, k, os);
|
|
||||||
case '%':
|
|
||||||
switch ((c = *fmt++)) {
|
|
||||||
case 's':
|
|
||||||
for (s = __builtin_va_arg(va, const char *); s && *s; ++s) {
|
|
||||||
if (k < 512)
|
|
||||||
b[k++] = *s;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
d = __builtin_va_arg(va, unsigned long);
|
|
||||||
for (i = 16; i--;) {
|
|
||||||
u = (d >> (i * 4)) & 15;
|
|
||||||
if (u < 10) {
|
|
||||||
c = '0' + u;
|
|
||||||
} else {
|
|
||||||
u -= 10;
|
|
||||||
c = 'a' + u;
|
|
||||||
}
|
|
||||||
if (k < 512)
|
|
||||||
b[k++] = c;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (k < 512)
|
|
||||||
b[k++] = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (k < 512)
|
|
||||||
b[k++] = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Perror(int os, const char *thing, long rc, const char *reason) {
|
static void Perror(int os, const char *thing, long rc, const char *reason) {
|
||||||
char ibuf[21];
|
char ibuf[21];
|
||||||
ibuf[0] = 0;
|
ibuf[0] = 0;
|
||||||
if (rc)
|
if (rc) Itoa(ibuf, -rc);
|
||||||
Itoa(ibuf, -rc);
|
|
||||||
Print(os, 2, "ape error: ", thing, ": ", reason,
|
Print(os, 2, "ape error: ", thing, ": ", reason,
|
||||||
rc ? " failed w/ errno " : "", ibuf, "\n", 0l);
|
rc ? " failed w/ errno " : "", ibuf, "\n", 0l);
|
||||||
}
|
}
|
||||||
|
@ -584,10 +535,8 @@ __attribute__((__noreturn__)) static void Pexit(int os, const char *c, int rc,
|
||||||
}
|
}
|
||||||
|
|
||||||
static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
|
static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
|
||||||
if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path))
|
if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) return 0;
|
||||||
return 0;
|
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
||||||
if (pathlen && ps->path[pathlen - 1] != '/')
|
|
||||||
ps->path[pathlen++] = '/';
|
|
||||||
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
||||||
ps->path[pathlen + ps->namelen] = 0;
|
ps->path[pathlen + ps->namelen] = 0;
|
||||||
return !Access(ps->path, X_OK, ps->os);
|
return !Access(ps->path, X_OK, ps->os);
|
||||||
|
@ -612,25 +561,45 @@ static char SearchPath(struct PathSearcher *ps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *Commandv(struct PathSearcher *ps, int os, char *name,
|
static char FindCommand(struct PathSearcher *ps) {
|
||||||
|
ps->path[0] = 0;
|
||||||
|
|
||||||
|
/* paths are always 100% taken literally when a slash exists
|
||||||
|
$ ape foo/bar.com arg1 arg2 */
|
||||||
|
if (MemChr(ps->name, '/', ps->namelen)) {
|
||||||
|
return AccessCommand(ps, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* we don't run files in the current directory
|
||||||
|
$ ape foo.com arg1 arg2
|
||||||
|
unless $PATH has an empty string entry, e.g.
|
||||||
|
$ expert PATH=":/bin"
|
||||||
|
$ ape foo.com arg1 arg2
|
||||||
|
however we will execute this
|
||||||
|
$ ape - foo.com foo.com arg1 arg2
|
||||||
|
because cosmo's execve needs it */
|
||||||
|
if (ps->literally && AccessCommand(ps, 0)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* otherwise search for name on $PATH */
|
||||||
|
return SearchPath(ps);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *Commandv(struct PathSearcher *ps, int os, const char *name,
|
||||||
const char *syspath) {
|
const char *syspath) {
|
||||||
if (!(ps->namelen = StrLen((ps->name = name))))
|
|
||||||
return 0;
|
|
||||||
if (ps->literally || MemChr(ps->name, '/', ps->namelen))
|
|
||||||
return name;
|
|
||||||
ps->os = os;
|
ps->os = os;
|
||||||
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
|
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
|
||||||
if (ps->namelen + 1 > sizeof(ps->path))
|
if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
|
||||||
return 0;
|
if (ps->namelen + 1 > sizeof(ps->path)) return 0;
|
||||||
ps->path[0] = 0;
|
if (FindCommand(ps)) {
|
||||||
if (SearchPath(ps)) {
|
|
||||||
return ps->path;
|
return ps->path;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
__attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
|
||||||
long *sp, unsigned long pagesz,
|
long *sp, unsigned long pagesz,
|
||||||
struct ElfEhdr *e,
|
struct ElfEhdr *e,
|
||||||
struct ElfPhdr *p) {
|
struct ElfPhdr *p) {
|
||||||
|
@ -678,8 +647,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
Pexit(os, exe, 0, "ELF segments overlap your APE loader");
|
Pexit(os, exe, 0, "ELF segments overlap your APE loader");
|
||||||
}
|
}
|
||||||
for (j = i + 1; j < e->e_phnum; ++j) {
|
for (j = i + 1; j < e->e_phnum; ++j) {
|
||||||
if (p[j].p_type != PT_LOAD)
|
if (p[j].p_type != PT_LOAD) continue;
|
||||||
continue;
|
|
||||||
c = p[j].p_vaddr & -pagesz;
|
c = p[j].p_vaddr & -pagesz;
|
||||||
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
|
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
|
||||||
if (MAX(a, c) < MIN(b, d)) {
|
if (MAX(a, c) < MIN(b, d)) {
|
||||||
|
@ -712,8 +680,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
if (e->e_type == ET_DYN) {
|
if (e->e_type == ET_DYN) {
|
||||||
rc = Mmap(0, virtmax - virtmin, PROT_NONE,
|
rc = Mmap(0, virtmax - virtmin, PROT_NONE,
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0, os);
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0, os);
|
||||||
if (rc < 0)
|
if (rc < 0) Pexit(os, exe, rc, "pie mmap");
|
||||||
Pexit(os, exe, rc, "pie mmap");
|
|
||||||
dynbase = rc;
|
dynbase = rc;
|
||||||
if (dynbase & (pagesz - 1)) {
|
if (dynbase & (pagesz - 1)) {
|
||||||
Pexit(os, exe, 0, "OS mmap incongruent w/ AT_PAGESZ");
|
Pexit(os, exe, 0, "OS mmap incongruent w/ AT_PAGESZ");
|
||||||
|
@ -729,18 +696,14 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
for (i = 0; i < e->e_phnum; ++i) {
|
for (i = 0; i < e->e_phnum; ++i) {
|
||||||
void *addr;
|
void *addr;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
if (p[i].p_type != PT_LOAD)
|
if (p[i].p_type != PT_LOAD) continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
/* configure mapping */
|
/* configure mapping */
|
||||||
prot = 0;
|
prot = 0;
|
||||||
flags = MAP_FIXED | MAP_PRIVATE;
|
flags = MAP_FIXED | MAP_PRIVATE;
|
||||||
if (p[i].p_flags & PF_R)
|
if (p[i].p_flags & PF_R) prot |= PROT_READ;
|
||||||
prot |= PROT_READ;
|
if (p[i].p_flags & PF_W) prot |= PROT_WRITE;
|
||||||
if (p[i].p_flags & PF_W)
|
if (p[i].p_flags & PF_X) prot |= PROT_EXEC;
|
||||||
prot |= PROT_WRITE;
|
|
||||||
if (p[i].p_flags & PF_X)
|
|
||||||
prot |= PROT_EXEC;
|
|
||||||
|
|
||||||
if (p[i].p_filesz) {
|
if (p[i].p_filesz) {
|
||||||
/* load from file */
|
/* load from file */
|
||||||
|
@ -767,21 +730,17 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz));
|
addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz));
|
||||||
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz;
|
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz;
|
||||||
rc = Mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz, os);
|
rc = Mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz, os);
|
||||||
if (rc < 0)
|
if (rc < 0) Pexit(os, exe, rc, "prog mmap");
|
||||||
Pexit(os, exe, rc, "prog mmap");
|
if (wipe) Bzero((void *)(dynbase + a), wipe);
|
||||||
if (wipe)
|
|
||||||
Bzero((void *)(dynbase + a), wipe);
|
|
||||||
if (prot2 != prot1) {
|
if (prot2 != prot1) {
|
||||||
rc = Mprotect(addr, size, prot2, os);
|
rc = Mprotect(addr, size, prot2, os);
|
||||||
if (rc < 0)
|
if (rc < 0) Pexit(os, exe, rc, "prog mprotect");
|
||||||
Pexit(os, exe, rc, "prog mprotect");
|
|
||||||
}
|
}
|
||||||
/* allocate extra bss */
|
/* allocate extra bss */
|
||||||
if (c > b) {
|
if (c > b) {
|
||||||
flags |= MAP_ANONYMOUS;
|
flags |= MAP_ANONYMOUS;
|
||||||
rc = Mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0, os);
|
rc = Mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0, os);
|
||||||
if (rc < 0)
|
if (rc < 0) Pexit(os, exe, rc, "extra bss mmap");
|
||||||
Pexit(os, exe, rc, "extra bss mmap");
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* allocate pure bss */
|
/* allocate pure bss */
|
||||||
|
@ -789,8 +748,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_memsz;
|
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_memsz;
|
||||||
flags |= MAP_ANONYMOUS;
|
flags |= MAP_ANONYMOUS;
|
||||||
rc = Mmap(addr, size, prot, flags, -1, 0, os);
|
rc = Mmap(addr, size, prot, flags, -1, 0, os);
|
||||||
if (rc < 0)
|
if (rc < 0) Pexit(os, exe, rc, "bss mmap");
|
||||||
Pexit(os, exe, rc, "bss mmap");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,11 +757,11 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
Msyscall(dynbase + code, codesize, os);
|
Msyscall(dynbase + code, codesize, os);
|
||||||
|
|
||||||
/* call program entrypoint */
|
/* call program entrypoint */
|
||||||
Launch(IsFreebsd() ? sp : 0, dynbase + e->e_entry, exe, os, sp);
|
Launch(IsFreebsd() ? sp : 0, dynbase + e->e_entry, sp, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
||||||
char *exe, int fd, long *sp, long *auxv,
|
const char *exe, int fd, long *sp, long *auxv,
|
||||||
unsigned long pagesz, int os) {
|
unsigned long pagesz, int os) {
|
||||||
long i, rc;
|
long i, rc;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
|
@ -811,8 +769,7 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
||||||
struct ElfPhdr *p;
|
struct ElfPhdr *p;
|
||||||
|
|
||||||
/* validate page size */
|
/* validate page size */
|
||||||
if (!pagesz)
|
if (!pagesz) pagesz = 4096;
|
||||||
pagesz = 4096;
|
|
||||||
if (pagesz & (pagesz - 1)) {
|
if (pagesz & (pagesz - 1)) {
|
||||||
Pexit(os, exe, 0, "AT_PAGESZ isn't two power");
|
Pexit(os, exe, 0, "AT_PAGESZ isn't two power");
|
||||||
}
|
}
|
||||||
|
@ -837,10 +794,6 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
||||||
return "couldn't find ELF header with x86-64 machine type";
|
return "couldn't find ELF header with x86-64 machine type";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((e->e_flags & EF_APE_MODERN_MASK) != EF_APE_MODERN && sp[0] > 0) {
|
|
||||||
/* change argv[0] to resolved path for older binaries */
|
|
||||||
((char **)(sp + 1))[0] = exe;
|
|
||||||
}
|
|
||||||
if (e->e_phentsize != sizeof(struct ElfPhdr)) {
|
if (e->e_phentsize != sizeof(struct ElfPhdr)) {
|
||||||
Pexit(os, exe, 0, "e_phentsize is wrong");
|
Pexit(os, exe, 0, "e_phentsize is wrong");
|
||||||
}
|
}
|
||||||
|
@ -851,10 +804,8 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
||||||
|
|
||||||
/* read program headers */
|
/* read program headers */
|
||||||
rc = Pread(fd, M->phdr.buf, size, e->e_phoff, os);
|
rc = Pread(fd, M->phdr.buf, size, e->e_phoff, os);
|
||||||
if (rc < 0)
|
if (rc < 0) return "failed to read ELF program headers";
|
||||||
return "failed to read ELF program headers";
|
if (rc != size) return "truncated read of ELF program headers";
|
||||||
if (rc != size)
|
|
||||||
return "truncated read of ELF program headers";
|
|
||||||
|
|
||||||
/* bail on recoverable program header errors */
|
/* bail on recoverable program header errors */
|
||||||
p = &M->phdr.phdr;
|
p = &M->phdr.phdr;
|
||||||
|
@ -934,13 +885,18 @@ __attribute__((__noreturn__)) static void ShowUsage(int os, int fd, int rc) {
|
||||||
"NAME\n"
|
"NAME\n"
|
||||||
"\n"
|
"\n"
|
||||||
" actually portable executable loader version " APE_VERSION_STR "\n"
|
" actually portable executable loader version " APE_VERSION_STR "\n"
|
||||||
" copyrights 2024 justine alexandra roberts tunney\n"
|
" copyright 2023 justine alexandra roberts tunney\n"
|
||||||
" https://justine.lol/ape.html\n"
|
" https://justine.lol/ape.html\n"
|
||||||
"\n"
|
"\n"
|
||||||
"USAGE\n"
|
"USAGE\n"
|
||||||
"\n"
|
"\n"
|
||||||
" ape PROG [ARGV1,ARGV2,...]\n"
|
" ape [FLAGS] PROG [ARGV1,ARGV2,...]\n"
|
||||||
" ape - PROG [ARGV0,ARGV1,...]\n"
|
" ape [FLAGS] - PROG [ARGV0,ARGV1,...]\n"
|
||||||
|
"\n"
|
||||||
|
"FLAGS\n"
|
||||||
|
"\n"
|
||||||
|
" -h show this help\n"
|
||||||
|
" -f force loading of program (do not use execve)\n"
|
||||||
"\n",
|
"\n",
|
||||||
0l);
|
0l);
|
||||||
Exit(rc, os);
|
Exit(rc, os);
|
||||||
|
@ -950,16 +906,16 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
char dl) {
|
char dl) {
|
||||||
int rc, n;
|
int rc, n;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
char literally;
|
||||||
const char *ape;
|
const char *ape;
|
||||||
int c, fd, os, argc;
|
int c, fd, os, argc;
|
||||||
struct ApeLoader *M;
|
struct ApeLoader *M;
|
||||||
char arg0, literally;
|
|
||||||
unsigned long pagesz;
|
unsigned long pagesz;
|
||||||
union ElfEhdrBuf *ebuf;
|
union ElfEhdrBuf *ebuf;
|
||||||
long *auxv, *ap, *endp, *sp2;
|
long *auxv, *ap, *endp, *sp2;
|
||||||
char *p, *pe, *exe, *prog, **argv, **envp;
|
char *p, *pe, *exe, *prog, **argv, **envp;
|
||||||
|
|
||||||
(void)Printf;
|
(void)Utox;
|
||||||
|
|
||||||
/* detect freebsd */
|
/* detect freebsd */
|
||||||
if (SupportsXnu() && dl == XNU) {
|
if (SupportsXnu() && dl == XNU) {
|
||||||
|
@ -984,30 +940,20 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
|
|
||||||
/* determine ape loader program name */
|
/* determine ape loader program name */
|
||||||
ape = argv[0];
|
ape = argv[0];
|
||||||
if (!ape)
|
if (!ape) ape = "ape";
|
||||||
ape = "ape";
|
|
||||||
|
|
||||||
/* detect openbsd */
|
/* detect openbsd */
|
||||||
if (SupportsOpenbsd() && !os && !auxv[0]) {
|
if (SupportsOpenbsd() && !os && !auxv[0]) {
|
||||||
os = OPENBSD;
|
os = OPENBSD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* xnu passes auxv as an array of strings */
|
|
||||||
if (os == XNU) {
|
|
||||||
*auxv = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* detect netbsd and find end of words */
|
/* detect netbsd and find end of words */
|
||||||
pagesz = 0;
|
pagesz = 0;
|
||||||
arg0 = 0;
|
|
||||||
for (ap = auxv; ap[0]; ap += 2) {
|
for (ap = auxv; ap[0]; ap += 2) {
|
||||||
if (ap[0] == AT_PAGESZ) {
|
if (ap[0] == AT_PAGESZ) {
|
||||||
pagesz = ap[1];
|
pagesz = ap[1];
|
||||||
} else if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) {
|
} else if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) {
|
||||||
os = NETBSD;
|
os = NETBSD;
|
||||||
} else if (SupportsLinux() && ap[0] == AT_FLAGS) {
|
|
||||||
// TODO(mrdomino): maybe set/insert this when we are called as "ape -".
|
|
||||||
arg0 = !!(ap[1] & AT_FLAGS_PRESERVE_ARGV0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!pagesz) {
|
if (!pagesz) {
|
||||||
|
@ -1020,13 +966,22 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
os = LINUX;
|
os = LINUX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* parse flags */
|
||||||
|
while (argc > 1) {
|
||||||
|
if (argv[1][0] != '-') break; /* normal argument */
|
||||||
|
if (!argv[1][1]) break; /* hyphen argument */
|
||||||
|
if (!StrCmp(argv[1], "-h") || !StrCmp(argv[1], "--help")) {
|
||||||
|
ShowUsage(os, 1, 0);
|
||||||
|
} else {
|
||||||
|
Print(os, 2, ape, ": invalid flag (pass -h for help)\n", 0l);
|
||||||
|
Exit(1, os);
|
||||||
|
}
|
||||||
|
*++sp = --argc;
|
||||||
|
++argv;
|
||||||
|
}
|
||||||
|
|
||||||
/* we can load via shell, shebang, or binfmt_misc */
|
/* we can load via shell, shebang, or binfmt_misc */
|
||||||
if (arg0) {
|
if ((literally = argc >= 3 && !StrCmp(argv[1], "-"))) {
|
||||||
literally = 1;
|
|
||||||
prog = (char *)sp[2];
|
|
||||||
argc = sp[2] = sp[0] - 2;
|
|
||||||
argv = (char **)((sp += 2) + 1);
|
|
||||||
} else if ((literally = argc >= 3 && !StrCmp(argv[1], "-"))) {
|
|
||||||
/* if the first argument is a hyphen then we give the user the
|
/* if the first argument is a hyphen then we give the user the
|
||||||
power to change argv[0] or omit it entirely. most operating
|
power to change argv[0] or omit it entirely. most operating
|
||||||
systems don't permit the omission of argv[0] but we do, b/c
|
systems don't permit the omission of argv[0] but we do, b/c
|
||||||
|
@ -1035,13 +990,9 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
argc = sp[3] = sp[0] - 3;
|
argc = sp[3] = sp[0] - 3;
|
||||||
argv = (char **)((sp += 3) + 1);
|
argv = (char **)((sp += 3) + 1);
|
||||||
} else if (argc < 2) {
|
} else if (argc < 2) {
|
||||||
ShowUsage(os, 2, 1);
|
Print(os, 2, ape, ": missing command name (pass -h for help)\n", 0l);
|
||||||
|
Exit(1, os);
|
||||||
} else {
|
} else {
|
||||||
if (argv[1][0] == '-') {
|
|
||||||
rc = !((argv[1][1] == 'h' && !argv[1][2]) ||
|
|
||||||
!StrCmp(argv[1] + 1, "-help"));
|
|
||||||
ShowUsage(os, 1 + rc, rc);
|
|
||||||
}
|
|
||||||
prog = (char *)sp[2];
|
prog = (char *)sp[2];
|
||||||
argc = sp[1] = sp[0] - 1;
|
argc = sp[1] = sp[0] - 1;
|
||||||
argv = (char **)((sp += 1) + 1);
|
argv = (char **)((sp += 1) + 1);
|
||||||
|
@ -1057,8 +1008,7 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
grows down the alloc by poking the guard pages */
|
grows down the alloc by poking the guard pages */
|
||||||
n = (endp - sp + 1) * sizeof(long);
|
n = (endp - sp + 1) * sizeof(long);
|
||||||
sp2 = (long *)__builtin_alloca(n);
|
sp2 = (long *)__builtin_alloca(n);
|
||||||
if ((long)sp2 & 15)
|
if ((long)sp2 & 15) ++sp2;
|
||||||
++sp2;
|
|
||||||
for (; n > 0; n -= pagesz) {
|
for (; n > 0; n -= pagesz) {
|
||||||
((char *)sp2)[n - 1] = 0;
|
((char *)sp2)[n - 1] = 0;
|
||||||
}
|
}
|
||||||
|
@ -1087,6 +1037,12 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
}
|
}
|
||||||
pe = ebuf->buf + rc;
|
pe = ebuf->buf + rc;
|
||||||
|
|
||||||
|
/* change argv[0] to resolved path if it's ambiguous */
|
||||||
|
if (argc > 0 && ((*prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
|
||||||
|
!StrCmp(BaseName(prog), argv[0]))) {
|
||||||
|
argv[0] = exe;
|
||||||
|
}
|
||||||
|
|
||||||
/* ape intended behavior
|
/* ape intended behavior
|
||||||
1. if ape, will scan shell script for elf printf statements
|
1. if ape, will scan shell script for elf printf statements
|
||||||
2. shell script may have multiple lines producing elf headers
|
2. shell script may have multiple lines producing elf headers
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -18,10 +18,123 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#ifndef APE_MACROS_H_
|
#ifndef APE_MACROS_H_
|
||||||
#define APE_MACROS_H_
|
#define APE_MACROS_H_
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.internal.h"
|
||||||
#ifdef __ASSEMBLER__
|
#ifdef __ASSEMBLER__
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Calls near (i.e. pc+pcrel<64kB) FUNCTION.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
// @cost 9 bytes overhead
|
||||||
|
.macro rlcall function:req
|
||||||
|
.byte 0x50 # push %[er]ax
|
||||||
|
.byte 0xb8,0,0 # mov $?,%[e]ax
|
||||||
|
jmp 911f
|
||||||
|
.byte 0x58 # pop %[er]ax
|
||||||
|
.byte 0xe8 # call Jvds
|
||||||
|
.long \function\()-.-4
|
||||||
|
jmp 912f
|
||||||
|
911: .byte 0x58 # pop %[er]ax
|
||||||
|
.byte 0xe8 # call Jvds
|
||||||
|
.short \function\()-.-2
|
||||||
|
912:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro movesdi address:req
|
||||||
|
.byte 0xbf # mov $0x????xxxx,%[e]di
|
||||||
|
.short \address>>4
|
||||||
|
.byte 0x8e,0xc7 # mov %di,%es
|
||||||
|
.byte 0xbf # mov $0x????xxxx,%[e]di
|
||||||
|
.short \address&0xf
|
||||||
|
jmp 297f
|
||||||
|
.byte 0xbf # mov $0x????xxxx,%edi
|
||||||
|
.long \address
|
||||||
|
297:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbmov constexpr:req abcd abcd.hi:req abcd.lo:req
|
||||||
|
.ifnb \abcd
|
||||||
|
.if (\constexpr)<128 && (\constexpr)>=0
|
||||||
|
pushpop \constexpr,\abcd
|
||||||
|
.exitm
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
movb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
movb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Compares 16-bit CONSTEXPR with Qw-register.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbcmp constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
cmpb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
jnz 387f
|
||||||
|
cmpb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
387:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Adds 16-bit CONSTEXPR to Qw-register.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbadd constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
addb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.if (\constexpr) != 0
|
||||||
|
adcb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Subtracts 16-bit CONSTEXPR from Qw-register.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbsub constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
subb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.if (\constexpr) != 0
|
||||||
|
sbbb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Ands Qw-register with 16-bit CONSTEXPR.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bband constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
.if ((\constexpr)&0xff) != 0xff || ((\constexpr)>>8&0xff) == 0xff
|
||||||
|
andb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.endif
|
||||||
|
.if ((\constexpr)>>8&0xff) != 0xff
|
||||||
|
andb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Ors Qw-register with 16-bit CONSTEXPR.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbor constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
.if ((\constexpr)&0xff) != 0 || ((\constexpr)>>8&0xff) != 0
|
||||||
|
orb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.endif
|
||||||
|
.if ((\constexpr)>>8&0xff) != 0
|
||||||
|
orb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Performs ACTION only if in real mode.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro rlo clobber:req action:vararg
|
||||||
|
990: mov $0,\clobber
|
||||||
|
.if .-990b!=3
|
||||||
|
.error "bad clobber or assembler mode"
|
||||||
|
.endif
|
||||||
|
991: \action
|
||||||
|
.rept 2-(.-991b)
|
||||||
|
nop
|
||||||
|
.endr
|
||||||
|
.if .-991b!=2
|
||||||
|
.error "ACTION must be 1-2 bytes"
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
// Initializes real mode stack.
|
// Initializes real mode stack.
|
||||||
// The most holiest of holy code.
|
// The most holiest of holy code.
|
||||||
// @mode real
|
// @mode real
|
||||||
|
@ -84,10 +197,9 @@
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
#elif defined(__LINKER__)
|
#elif defined(__LINKER__)
|
||||||
|
|
||||||
#define BCX_NIBBLE(X) \
|
#define BCX_NIBBLE(X) ((((X)&0xf) > 0x9) ? ((X)&0xf) + 0x37 : ((X)&0xf) + 0x30)
|
||||||
((((X) & 0xf) > 0x9) ? ((X) & 0xf) + 0x37 : ((X) & 0xf) + 0x30)
|
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
||||||
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||||
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
|
||||||
#define BCXSTUB(SYM, X) \
|
#define BCXSTUB(SYM, X) \
|
||||||
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
|
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
|
||||||
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
|
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
|
||||||
|
@ -99,12 +211,12 @@
|
||||||
*
|
*
|
||||||
* <p>This allows linker scripts to generate printf commands.
|
* <p>This allows linker scripts to generate printf commands.
|
||||||
*/
|
*/
|
||||||
#define BCO_OCTET(X) (((X) & 0x7) + 0x30)
|
#define BCO_OCTET(X) (((X)&0x7) + 0x30)
|
||||||
#define BCOB_UNIT(X) \
|
#define BCOB_UNIT(X) \
|
||||||
((BCO_OCTET((X) >> 0) << 24) | (BCO_OCTET((X) >> 3) << 16) | \
|
((BCO_OCTET((X) >> 0) << 24) | (BCO_OCTET((X) >> 3) << 16) | \
|
||||||
(BCO_OCTET(((X) & 0xff) >> 6) << 8) | 0x5c)
|
(BCO_OCTET(((X)&0xff) >> 6) << 8) | 0x5c)
|
||||||
|
|
||||||
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I) * 8)))
|
#define PFBYTE(SYM, X, I) HIDDEN(SYM##_bcs##I = BCOB_UNIT((X) >> ((I)*8)))
|
||||||
#define PFSTUB2(SYM, X) \
|
#define PFSTUB2(SYM, X) \
|
||||||
HIDDEN(SYM = (X)); \
|
HIDDEN(SYM = (X)); \
|
||||||
PFBYTE(SYM, X, 0); \
|
PFBYTE(SYM, X, 0); \
|
||||||
|
@ -141,16 +253,23 @@
|
||||||
: (X) < 10000000 ? BCD_RIGHT(BCD_SMEAR((X) / 1000)) \
|
: (X) < 10000000 ? BCD_RIGHT(BCD_SMEAR((X) / 1000)) \
|
||||||
: (X) < 100000000 ? BCD_RIGHT(BCD_SMEAR((X) / 10000)) \
|
: (X) < 100000000 ? BCD_RIGHT(BCD_SMEAR((X) / 10000)) \
|
||||||
: 0xffffffffffffffff)
|
: 0xffffffffffffffff)
|
||||||
#define BCD_RIGHT(X) \
|
#define BCD_RIGHT(X) \
|
||||||
(((X)) < 10000 ? 0x20202020 \
|
(((X)) < 10000 ? 0x20202020 \
|
||||||
: (X) < 100000 ? 0x20202030 + (X) % 10 \
|
: (X) < 100000 ? 0x20202030 + \
|
||||||
: (X) < 1000000 ? 0x20203030 + ((X) / 10) % 10 + (X) % 10 * 0x100 \
|
(X) % 10 \
|
||||||
: (X) < 10000000 ? 0x20303030 + ((X) / 100) % 10 + \
|
: (X) < 1000000 ? 0x20203030 + \
|
||||||
((X) / 10) % 10 * 0x100 + (X) % 10 * 0x10000 \
|
((X) / 10) % 10 + \
|
||||||
: (X) < 100000000 \
|
(X) % 10 * 0x100 \
|
||||||
? 0x30303030 + ((X) / 1000) % 10 + ((X) / 100) % 10 * 0x100 + \
|
: (X) < 10000000 ? 0x20303030 + \
|
||||||
((X) / 10) % 10 * 0x10000 + (X) % 10 * 0x1000000 \
|
((X) / 100) % 10 + \
|
||||||
: 0xffffffffffffffff)
|
((X) / 10) % 10 * 0x100 + \
|
||||||
|
(X) % 10 * 0x10000 \
|
||||||
|
: (X) < 100000000 ? 0x30303030 + \
|
||||||
|
((X) / 1000) % 10 + \
|
||||||
|
((X) / 100) % 10 * 0x100 + \
|
||||||
|
((X) / 10) % 10 * 0x10000 + \
|
||||||
|
(X) % 10 * 0x1000000 \
|
||||||
|
: 0xffffffffffffffff)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Laying out the GDT entries for a TSS for bare metal operation.
|
* Laying out the GDT entries for a TSS for bare metal operation.
|
||||||
|
@ -159,11 +278,15 @@
|
||||||
HIDDEN(SYM##_desc_ent0 = TSSDESC_ENT0(BASE, LIM)); \
|
HIDDEN(SYM##_desc_ent0 = TSSDESC_ENT0(BASE, LIM)); \
|
||||||
HIDDEN(SYM##_desc_ent1 = TSSDESC_ENT1(BASE)); \
|
HIDDEN(SYM##_desc_ent1 = TSSDESC_ENT1(BASE)); \
|
||||||
ASSERT((LIM) >= 0 && (LIM) <= 0xffff, "bare metal TSS is suspiciously fat")
|
ASSERT((LIM) >= 0 && (LIM) <= 0xffff, "bare metal TSS is suspiciously fat")
|
||||||
#define TSSDESC_ENT0(BASE, LIM) \
|
#define TSSDESC_ENT0(BASE, LIM) \
|
||||||
(((LIM) << 0 & 0x000000000000ffff) | ((BASE) << 16 & 0x000000ffffff0000) | \
|
(((LIM) << 0 & 0x000000000000ffff) | \
|
||||||
0x89 << 40 | ((LIM) >> 16 << 48 & 0x000f000000000000) | 0x2 << 52 | \
|
((BASE) << 16 & 0x000000ffffff0000) | \
|
||||||
|
0x89 << 40 | \
|
||||||
|
((LIM) >> 16 << 48 & 0x000f000000000000) | \
|
||||||
|
0x2 << 52 | \
|
||||||
((BASE) >> 24 << 56 & 0xff00000000000000))
|
((BASE) >> 24 << 56 & 0xff00000000000000))
|
||||||
#define TSSDESC_ENT1(BASE) ((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
#define TSSDESC_ENT1(BASE) \
|
||||||
|
((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
||||||
|
|
||||||
#endif /* __ASSEMBLER__ */
|
#endif /* __ASSEMBLER__ */
|
||||||
#endif /* APE_MACROS_H_ */
|
#endif /* APE_MACROS_H_ */
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#ifndef COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
#ifndef COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||||
#define COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
#define COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
extern const char __notices[] __attribute__((__weak__));
|
extern const char __comment_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __executable_start[] __attribute__((__weak__));
|
extern unsigned char __executable_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __privileged_start[] __attribute__((__weak__));
|
extern unsigned char __privileged_start[] __attribute__((__weak__));
|
||||||
extern unsigned char _ehead[] __attribute__((__weak__));
|
extern unsigned char _ehead[] __attribute__((__weak__));
|
||||||
|
@ -16,17 +17,13 @@ extern unsigned char _tdata_end[] __attribute__((__weak__));
|
||||||
extern unsigned char _tbss_start[] __attribute__((__weak__));
|
extern unsigned char _tbss_start[] __attribute__((__weak__));
|
||||||
extern unsigned char _tbss_end[] __attribute__((__weak__));
|
extern unsigned char _tbss_end[] __attribute__((__weak__));
|
||||||
extern unsigned char _tls_align[] __attribute__((__weak__));
|
extern unsigned char _tls_align[] __attribute__((__weak__));
|
||||||
extern unsigned char _tdata_align[] __attribute__((__weak__));
|
|
||||||
extern unsigned char _tbss_align[] __attribute__((__weak__));
|
|
||||||
extern unsigned char __test_start[] __attribute__((__weak__));
|
extern unsigned char __test_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __ro[] __attribute__((__weak__));
|
extern unsigned char __ro[] __attribute__((__weak__));
|
||||||
extern unsigned char __data_start[] __attribute__((__weak__));
|
extern uint8_t __data_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __data_end[] __attribute__((__weak__));
|
extern uint8_t __data_end[] __attribute__((__weak__));
|
||||||
extern unsigned char __bss_start[] __attribute__((__weak__));
|
extern uint8_t __bss_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __bss_end[] __attribute__((__weak__));
|
extern uint8_t __bss_end[] __attribute__((__weak__));
|
||||||
extern unsigned long __got_start[] __attribute__((__weak__));
|
|
||||||
extern unsigned long __got_end[] __attribute__((__weak__));
|
|
||||||
extern unsigned char ape_phdrs[] __attribute__((__weak__));
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_ */
|
#endif /* COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_ */
|
||||||
|
|
|
@ -1,703 +0,0 @@
|
||||||
# Actually Portable Executable Specification v0.1
|
|
||||||
|
|
||||||
Actually Portable Executable (APE) is an executable file format that
|
|
||||||
polyglots the Windows Portable Executable (PE) format with a UNIX Sixth
|
|
||||||
Edition style shell script that doesn't have a shebang. This makes it
|
|
||||||
possible to produce a single file binary that executes on the stock
|
|
||||||
installations of the many OSes and architectures.
|
|
||||||
|
|
||||||
## Supported OSes and Architectures
|
|
||||||
|
|
||||||
- AMD64
|
|
||||||
- Linux
|
|
||||||
- MacOS
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
|
|
||||||
- ARM64
|
|
||||||
- Linux
|
|
||||||
- MacOS
|
|
||||||
- FreeBSD
|
|
||||||
- Windows (non-native)
|
|
||||||
|
|
||||||
## File Header
|
|
||||||
|
|
||||||
APE defines three separate file magics, all of which are 8 characters
|
|
||||||
long. Any file that starts with one of these magic values can be
|
|
||||||
considered an APE program.
|
|
||||||
|
|
||||||
### (1) APE MZ Magic
|
|
||||||
|
|
||||||
- ASCII: `MZqFpD='`
|
|
||||||
- Hex: 4d 5a 71 46 70 44 3d 27
|
|
||||||
|
|
||||||
This is the canonical magic used by almost all APE programs. It enables
|
|
||||||
maximum portability between OSes. When interpreted as a shell script, it
|
|
||||||
is assigning a single quoted string to an unused variable. The shell
|
|
||||||
will then ignore subsequent binary content that's placed inside the
|
|
||||||
string.
|
|
||||||
|
|
||||||
It is strongly recommended that this magic value be immediately followed
|
|
||||||
by a newline (\n or hex 0a) character. Some shells, e.g. FreeBSD SH and
|
|
||||||
Zsh impose a binary safety check before handing off files that don't
|
|
||||||
have a shebang to `/bin/sh`. That check applies to the first line, which
|
|
||||||
can't contain NUL characters.
|
|
||||||
|
|
||||||
The letters were carefully chosen so as to be valid x86 instructions in
|
|
||||||
all operating modes. This makes it possible to store a BIOS bootloader
|
|
||||||
disk image inside an APE binary. For example, simple CLI programs built
|
|
||||||
with Cosmopolitan Libc will boot from BIOS into long mode if they're
|
|
||||||
treated as a floppy disk image.
|
|
||||||
|
|
||||||
The letters also allow for the possibility of being treated on x86-64 as
|
|
||||||
a flat executable, where the PE / ELF / Mach-O executable structures are
|
|
||||||
ignored, and execution simply begins at the beginning of the file,
|
|
||||||
similar to how MS-DOS .COM binaries work.
|
|
||||||
|
|
||||||
The 0x4a relative offset of the magic causes execution to jump into the
|
|
||||||
MS-DOS stub defined by Portable Executable. APE binaries built by Cosmo
|
|
||||||
Libc use tricks in the MS-DOS stub to check the operating mode and then
|
|
||||||
jump to the appropriate entrypoint, e.g. `_start()`.
|
|
||||||
|
|
||||||
#### Decoded as i8086
|
|
||||||
|
|
||||||
```asm
|
|
||||||
dec %bp
|
|
||||||
pop %dx
|
|
||||||
jno 0x4a
|
|
||||||
jo 0x4a
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Decoded as i386
|
|
||||||
|
|
||||||
```asm
|
|
||||||
push %ebp
|
|
||||||
pop %edx
|
|
||||||
jno 0x4a
|
|
||||||
jo 0x4a
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Decoded as x86-64
|
|
||||||
|
|
||||||
```asm
|
|
||||||
rex.WRB
|
|
||||||
pop %r10
|
|
||||||
jno 0x4a
|
|
||||||
jo 0x4a
|
|
||||||
```
|
|
||||||
|
|
||||||
### (2) APE UNIX-Only Magic
|
|
||||||
|
|
||||||
- ASCII: `jartsr='`
|
|
||||||
- Hex: 6a 61 72 74 73 72 3d 27
|
|
||||||
|
|
||||||
Being a novel executable format that was first published in 2020, the
|
|
||||||
APE file format is less understood by industry tools compared to the PE,
|
|
||||||
ELF, and Mach-O executable file formats, which have been around for
|
|
||||||
decades. For this reason, APE programs that use the MZ magic above can
|
|
||||||
attract attention from Windows AV software, which may be unwanted by
|
|
||||||
developers who aren't interested in targeting the Windows platform.
|
|
||||||
Therefore the `jartsr='` magic is defined which enables the creation of
|
|
||||||
APE binaries that can safely target all non-Windows platforms. Even
|
|
||||||
though this magic is less common, APE interpreters and binfmt-misc
|
|
||||||
installations MUST support this.
|
|
||||||
|
|
||||||
It is strongly recommended that this magic value be immediately followed
|
|
||||||
by a newline (\n or hex 0a) character. Some shells, e.g. FreeBSD SH and
|
|
||||||
Zsh impose a binary safety check before handing off files that don't
|
|
||||||
have a shebang to `/bin/sh`. That check applies to the first line, which
|
|
||||||
can't contain NUL characters.
|
|
||||||
|
|
||||||
The letters were carefully chosen so as to be valid x86 instructions in
|
|
||||||
all operating modes. This makes it possible to store a BIOS bootloader
|
|
||||||
disk image inside an APE binary. For example, simple CLI programs built
|
|
||||||
with Cosmopolitan Libc will boot from BIOS into long mode if they're
|
|
||||||
treated as a floppy disk image.
|
|
||||||
|
|
||||||
The letters also allow for the possibility of being treated on x86-64 as
|
|
||||||
a flat executable, where the PE / ELF / Mach-O executable structures are
|
|
||||||
ignored, and execution simply begins at the beginning of the file,
|
|
||||||
similar to how MS-DOS .COM binaries work.
|
|
||||||
|
|
||||||
The 0x78 relative offset of the magic causes execution to jump into the
|
|
||||||
MS-DOS stub defined by Portable Executable. APE binaries built by Cosmo
|
|
||||||
Libc use tricks in the MS-DOS stub to check the operating mode and then
|
|
||||||
jump to the appropriate entrypoint, e.g. `_start()`.
|
|
||||||
|
|
||||||
#### Decoded as i8086 / i386 / x86-64
|
|
||||||
|
|
||||||
```asm
|
|
||||||
push $0x61
|
|
||||||
jb 0x78
|
|
||||||
jae 0x78
|
|
||||||
```
|
|
||||||
|
|
||||||
### (3) APE Debug Magic
|
|
||||||
|
|
||||||
- ASCII: `APEDBG='`
|
|
||||||
- Hex: 41 50 45 44 42 47 3d 27
|
|
||||||
|
|
||||||
While APE files must be valid shell scripts, in practice, UNIX systems
|
|
||||||
will oftentimes be configured to provide a faster safer alternative to
|
|
||||||
loading an APE binary through `/bin/sh`. The Linux Kernel can be patched
|
|
||||||
to have execve() recognize the APE format and directly load its embedded
|
|
||||||
ELF header. Linux systems can also use binfmt-misc to recognize APE's MZ
|
|
||||||
and jartsr magic, and pass them to a userspace program named `ape` that
|
|
||||||
acts as an interpreter. In such environments, the need sometimes arises
|
|
||||||
to be able to test that the `/bin/sh` is working correctly, in which
|
|
||||||
case the `APEDBG='` magic is RECOMMENDED.
|
|
||||||
|
|
||||||
APE interpreters, execve() implementations, and binfmt-misc installs
|
|
||||||
MUST ignore this magic. If necessary, steps can be taken to help files
|
|
||||||
with this magic be passed to `/bin/sh` like a normal shebang-less shell
|
|
||||||
script for execution.
|
|
||||||
|
|
||||||
## Embedded ELF Header
|
|
||||||
|
|
||||||
APE binaries MAY embed an ELF header inside them. Unlike conventional
|
|
||||||
executable file formats, this header is not stored at a fixed offset.
|
|
||||||
It's instead encoded as octal escape codes in a shell script `printf`
|
|
||||||
statement. For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
printf '\177ELF\2\1\1\011\0\0\0\0\0\0\0\0\2\0\076\0\1\0\0\0\166\105\100\000\000\000\000\000\060\013\000\000\000\000\000\000\000\000\000\000\000\000\000\000\165\312\1\1\100\0\070\0\005\000\0\0\000\000\000\000'
|
|
||||||
```
|
|
||||||
|
|
||||||
This `printf` statement MUST appear in the first 8192 bytes of the APE
|
|
||||||
executable, so as to limit how much of the initial portion of a file an
|
|
||||||
interpreter must load.
|
|
||||||
|
|
||||||
Multiple such `printf` statements MAY appear in the first 8192 bytes, in
|
|
||||||
order to specify multiple architectures. For example, fat binaries built
|
|
||||||
by the `apelink` program (provided by Cosmo Libc) will have two encoded
|
|
||||||
ELF headers, for AMD64 and ARM64, each of which point into the proper
|
|
||||||
file offsets for their respective native code. Therefore, kernels and
|
|
||||||
interpreters which load the APE format directly MUST check the
|
|
||||||
`e_machine` field of the `Elf64_Ehdr` that's decoded from the octal
|
|
||||||
codes, before accepting a `printf` shell statement as valid.
|
|
||||||
|
|
||||||
These printf statements MUST always use only unescaped ASCII characters
|
|
||||||
or octal escape codes. These printf statements MUST NOT use space saving
|
|
||||||
escape codes such as `\n`. For example, rather than saying `\n` it would
|
|
||||||
be valid to say `\012` instead. It's also valid to say `\12` but only if
|
|
||||||
the encoded characters that follow aren't an octal digit.
|
|
||||||
|
|
||||||
For example, the following algorithm may be used for parsing octal:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static int ape_parse_octal(const unsigned char page[8192], int i, int *pc)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
if ('0' <= page[i] && page[i] <= '7') {
|
|
||||||
c = page[i++] - '0';
|
|
||||||
if ('0' <= page[i] && page[i] <= '7') {
|
|
||||||
c *= 8;
|
|
||||||
c += page[i++] - '0';
|
|
||||||
if ('0' <= page[i] && page[i] <= '7') {
|
|
||||||
c *= 8;
|
|
||||||
c += page[i++] - '0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pc = c;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
APE aware interpreters SHOULD only take `e_machine` into consideration.
|
|
||||||
It is the responsibility of the `_start()` function to detect the OS.
|
|
||||||
Therefore, multiple `printf` statements are only embedded in the shell
|
|
||||||
script for different CPU architectures.
|
|
||||||
|
|
||||||
The OS ABI field of an APE embedded `Elf64_Ehdr` SHOULD be set to
|
|
||||||
`ELFOSABI_FREEBSD`, since it's the only UNIX OS APE supports that
|
|
||||||
actually checks the field. However different values MAY be chosen for
|
|
||||||
binaries that don't intend to have FreeBSD in their support vector.
|
|
||||||
|
|
||||||
Counter-intuitively, the ARM64 ELF header is used on the MacOS ARM64
|
|
||||||
platform when loading from fat binaries.
|
|
||||||
|
|
||||||
## Embedded Mach-O Header (x86-64 only)
|
|
||||||
|
|
||||||
APE shell scripts that support MacOS on AMD64 must use the `dd` command
|
|
||||||
in a very specific way to specify how the embedded binary Macho-O header
|
|
||||||
is copied backward to the start of the file. For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
dd if="$o" of="$o" bs=8 skip=433 count=66 conv=notrunc
|
|
||||||
```
|
|
||||||
|
|
||||||
These `dd` statements have traditionally been generated by the GNU as
|
|
||||||
and ld.bfd programs by encoding ASCII into 64-bit linker relocations,
|
|
||||||
which necessitated a fixed width for integer values. It took several
|
|
||||||
iterations over APE's history before we eventually got it right:
|
|
||||||
|
|
||||||
- `arg=" 9293"` is how we originally had ape do it
|
|
||||||
- `arg=$(( 9293))` b/c busybox sh disliked quoted space
|
|
||||||
- `arg=9293 ` is generated by modern apelink program
|
|
||||||
|
|
||||||
Software that parses the APE file format, which needs to extract the
|
|
||||||
Macho-O x86-64 header SHOULD support the old binaries that use the
|
|
||||||
previous encodings. To make backwards compatibility simple the following
|
|
||||||
regular expression may be used, which generalizes to all defined
|
|
||||||
formats:
|
|
||||||
|
|
||||||
```c
|
|
||||||
regcomp(&rx,
|
|
||||||
"bs=" // dd block size arg
|
|
||||||
"(['\"] *)?" // #1 optional quote w/ space
|
|
||||||
"(\\$\\(\\( *)?" // #2 optional math w/ space
|
|
||||||
"([[:digit:]]+)" // #3
|
|
||||||
"( *\\)\\))?" // #4 optional math w/ space
|
|
||||||
"( *['\"])?" // #5 optional quote w/ space
|
|
||||||
" +" //
|
|
||||||
"skip=" // dd skip arg
|
|
||||||
"(['\"] *)?" // #6 optional quote w/ space
|
|
||||||
"(\\$\\(\\( *)?" // #7 optional math w/ space
|
|
||||||
"([[:digit:]]+)" // #8
|
|
||||||
"( *\\)\\))?" // #9 optional math w/ space
|
|
||||||
"( *['\"])?" // #10 optional quote w/ space
|
|
||||||
" +" //
|
|
||||||
"count=" // dd count arg
|
|
||||||
"(['\"] *)?" // #11 optional quote w/ space
|
|
||||||
"(\\$\\(\\( *)?" // #12 optional math w/ space
|
|
||||||
"([[:digit:]]+)", // #13
|
|
||||||
REG_EXTENDED);
|
|
||||||
```
|
|
||||||
|
|
||||||
For further details, see the canonical implementation in
|
|
||||||
`cosmopolitan/tool/build/assimilate.c`.
|
|
||||||
|
|
||||||
## Static Linking
|
|
||||||
|
|
||||||
Actually Portable Executables are always statically linked. This
|
|
||||||
revision of the specification does not define any facility for storing
|
|
||||||
code in dynamic shared objects.
|
|
||||||
|
|
||||||
Cosmopolitan Libc provides a solution that enables APE binaries have
|
|
||||||
limited access to dlopen(). By manually loading a platform-specific
|
|
||||||
executable and asking the OS-specific libc's dlopen() to load
|
|
||||||
OS-specific libraries, it becomes possible to use GPUs and GUIs. This
|
|
||||||
has worked great for AI projects like llamafile.
|
|
||||||
|
|
||||||
There is no way for an Actually Portable Executable to interact with
|
|
||||||
OS-specific dynamic shared object extension modules to programming
|
|
||||||
languages. For example, a Lua interpreter compiled as an Actually
|
|
||||||
Portable Executable would have no way of linking extension libraries
|
|
||||||
downloaded from the Lua Rocks package manager. This is primarily because
|
|
||||||
different OSes define incompatible ABIs.
|
|
||||||
|
|
||||||
While it was possible to polyglot PE+ELF+MachO to create multi-OS
|
|
||||||
executables, it simply isn't possible to do that same thing for
|
|
||||||
DLL+DYLIB+SO. Therefore, in order to have DSOs, APE would need to either
|
|
||||||
choose one of the existing formats or invent one of its own, and then
|
|
||||||
develop its own parallel ecosystem of extension software. In the future,
|
|
||||||
the APE specification may expand to encompass this. However the focus to
|
|
||||||
date has been exclusively on executables with limited dlopen() support.
|
|
||||||
|
|
||||||
## Application Binary Interface (ABI)
|
|
||||||
|
|
||||||
APE binaries use the System V ABI, as defined by:
|
|
||||||
|
|
||||||
- [System V ABI - AMD64 Architecture Processor Supplement](https://gitlab.com/x86-psABIs/x86-64-ABI)
|
|
||||||
- AARCH64 has a uniform consensus defined by ARM Limited
|
|
||||||
|
|
||||||
There are however a few changes we've had to make.
|
|
||||||
|
|
||||||
### No Red Zone
|
|
||||||
|
|
||||||
Actually Portable Executables that have Windows and/or bare metal in
|
|
||||||
their support vector MUST be compiled using `-mno-red-zone`. This is
|
|
||||||
because, on Windows, DLLs and other software lurking in the va-space
|
|
||||||
might use tricks like SetThreadContext() to take control of a thread
|
|
||||||
whereas on bare metal, it's also generally accepted that kernel-mode
|
|
||||||
code cannot assume a red zone either due to hardware interrupts that
|
|
||||||
pull the exact same kinds of stunts.
|
|
||||||
|
|
||||||
APE software that only has truly System V ABI conformant OSes (e.g.
|
|
||||||
Linux) in their support vector MAY use the red zone optimization.
|
|
||||||
|
|
||||||
### Thread Local Storage
|
|
||||||
|
|
||||||
#### aarch64
|
|
||||||
|
|
||||||
Here's the TLS memory layout on aarch64:
|
|
||||||
|
|
||||||
```
|
|
||||||
x28
|
|
||||||
%tpidr_el0
|
|
||||||
│
|
|
||||||
│ _Thread_local
|
|
||||||
┌───┼───┬──────────┬──────────┐
|
|
||||||
│tib│dtv│ .tdata │ .tbss │
|
|
||||||
├───┴───┴──────────┴──────────┘
|
|
||||||
│
|
|
||||||
__get_tls()
|
|
||||||
```
|
|
||||||
|
|
||||||
The ARM64 code in actually portable executables use the `x28` register
|
|
||||||
to store the address of the thread information block. All aarch64 code
|
|
||||||
linked into these executables SHOULD be compiled with `-ffixed-x28`
|
|
||||||
which is supported by both Clang and GCC.
|
|
||||||
|
|
||||||
The runtime library for an actually portable executables MAY choose to
|
|
||||||
use `tpidr_el0` instead, if OSes like MacOS aren't being targeted. For
|
|
||||||
example, if the goal is to create a Linux-only fat binary linker program
|
|
||||||
for Musl Libc, then choosing to use the existing `tpidr_el0` convention
|
|
||||||
would be friction-free alternative.
|
|
||||||
|
|
||||||
It's not possible for an APE runtime that targets the full range of OSes
|
|
||||||
to use the `tpidr_el0` register for TLS because Apple won't allow it. On
|
|
||||||
MacOS ARM64 systems, this register can only be used by a runtime to
|
|
||||||
implement the `sched_getcpu()` system call. It's reserved by MacOS.
|
|
||||||
|
|
||||||
#### x86-64
|
|
||||||
|
|
||||||
Here's the TLS memory layout on x86_64:
|
|
||||||
|
|
||||||
```
|
|
||||||
__get_tls()
|
|
||||||
│
|
|
||||||
%fs OpenBSD/NetBSD
|
|
||||||
_Thread_local │
|
|
||||||
┌───┬──────────┬──────────┼───┐
|
|
||||||
│pad│ .tdata │ .tbss │tib│
|
|
||||||
└───┴──────────┴──────────┼───┘
|
|
||||||
│
|
|
||||||
Linux/FreeBSD/Windows/Mac %gs
|
|
||||||
```
|
|
||||||
|
|
||||||
Quite possibly the greatest challenge in Actually Portable Executable
|
|
||||||
working, has been overcoming the incompatibilities between OSes in how
|
|
||||||
thread-local storage works on x86-64. The AMD64 architecture defines two
|
|
||||||
special segment registers. Every OS uses one of these segment registers
|
|
||||||
to implement TLS support. However not all OSes agree on which register
|
|
||||||
to use. Some OSes grant userspace the power to define either of these
|
|
||||||
registers to hold any value that is desired. Some OSes only effectively
|
|
||||||
allow a single one of them to be changed. Lastly, some OSes, e.g.
|
|
||||||
Windows, claim ownership of the memory layout these registers point
|
|
||||||
towards too.
|
|
||||||
|
|
||||||
Here's a breakdown on how much power is granted to userspace runtimes by
|
|
||||||
each OS when it comes to changing amd64 segment registers.
|
|
||||||
|
|
||||||
| | %fs | %gs |
|
|
||||||
|---------|--------------|--------------|
|
|
||||||
| Linux | unrestricted | unrestricted |
|
|
||||||
| MacOS | inaccessible | unrestricted |
|
|
||||||
| Windows | inaccessible | restricted |
|
|
||||||
| FreeBSD | unrestricted | unrestricted |
|
|
||||||
| NetBSD | unrestricted | broken |
|
|
||||||
| OpenBSD | unrestricted | inaccessible |
|
|
||||||
|
|
||||||
Therefore, regardless of which register one we choose, some OSes are
|
|
||||||
going to be incompatible.
|
|
||||||
|
|
||||||
APE binaries are always built with a Linux compiler. So another issue
|
|
||||||
arises in the fact that our Linux-flavored GCC and Clang toolchains
|
|
||||||
(which are used to produce cross-OS binaries) are also only capable of
|
|
||||||
producing TLS instructions that use the %fs convention.
|
|
||||||
|
|
||||||
To solve these challenges, the `cosmocc` compiler will rewrite binary
|
|
||||||
objects after they've been compiled by GCC, so that the `%gs` register
|
|
||||||
is used, rather than `%fs`. Morphing x86-64 binaries after they've been
|
|
||||||
compiled is normally difficult, due to the complexity of the machine
|
|
||||||
instruction language. However GCC provides `-mno-tls-direct-seg-refs`
|
|
||||||
which greatly reduces the complexity of this task. This flag forgoes
|
|
||||||
some optimizations to make the generated code simpler. Rather than doing
|
|
||||||
clever arithmetic with `%fs` prefixes, the compiler will always generate
|
|
||||||
the thread information block address load as a separate instruction.
|
|
||||||
|
|
||||||
```c
|
|
||||||
// Change AMD code to use %gs:0x30 instead of %fs:0
|
|
||||||
// We assume -mno-tls-direct-seg-refs has been used
|
|
||||||
static void ChangeTlsFsToGs(unsigned char *p, size_t n) {
|
|
||||||
unsigned char *e = p + n - 9;
|
|
||||||
while (p <= e) {
|
|
||||||
// we're checking for the following expression:
|
|
||||||
// 0144 == p[0] && // %fs
|
|
||||||
// 0110 == (p[1] & 0373) && // rex.w (and ignore rex.r)
|
|
||||||
// (0213 == p[2] || // mov reg/mem → reg (word-sized)
|
|
||||||
// 0003 == p[2]) && // add reg/mem → reg (word-sized)
|
|
||||||
// 0004 == (p[3] & 0307) && // mod/rm (4,reg,0) means sib → reg
|
|
||||||
// 0045 == p[4] && // sib (5,4,0) → (rbp,rsp,0) → disp32
|
|
||||||
// 0000 == p[5] && // displacement (von Neumann endian)
|
|
||||||
// 0000 == p[6] && // displacement
|
|
||||||
// 0000 == p[7] && // displacement
|
|
||||||
// 0000 == p[8] // displacement
|
|
||||||
uint64_t w = READ64LE(p) & READ64LE("\377\373\377\307\377\377\377\377");
|
|
||||||
if ((w == READ64LE("\144\110\213\004\045\000\000\000") ||
|
|
||||||
w == READ64LE("\144\110\003\004\045\000\000\000")) &&
|
|
||||||
!p[8]) {
|
|
||||||
p[0] = 0145; // change %fs to %gs
|
|
||||||
p[5] = 0x30; // change 0 to 0x30
|
|
||||||
p += 9;
|
|
||||||
} else {
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
By favoring `%gs` we've now ensured friction-free compatibility for the
|
|
||||||
APE runtime on MacOS, Linux, and FreeBSD which are all able to conform
|
|
||||||
easily to this convention. However additional work needs to be done at
|
|
||||||
runtime when an APE program is started on Windows, OpenBSD, and NetBSD.
|
|
||||||
On these platforms, all executable pages must be faulted and morphed to
|
|
||||||
fixup the TLS instructions.
|
|
||||||
|
|
||||||
On OpenBSD and NetBSD, this is as simple as undoing the example
|
|
||||||
operation above. Earlier at compile-time we turned `%fs` into `%gs`.
|
|
||||||
Now, at runtime, `%gs` must be turned back into `%fs`. Since the
|
|
||||||
executable is morphing itself, this is easier said than done.
|
|
||||||
|
|
||||||
OpenBSD for example enforces a `W^X` invariant. Code that's executing
|
|
||||||
can't modify itself at the same time. The way Cosmopolitan solves this
|
|
||||||
is by defining a special part of the binary called `.text.privileged`.
|
|
||||||
This section is aligned to page boundaries. A GNU ld linker script is
|
|
||||||
used to ensure that code which morphs code is placed into this section,
|
|
||||||
through the use of a header-defined cosmo-specific keyword `privileged`.
|
|
||||||
Additionally, the `fixupobj` program is used by the Cosmo build system
|
|
||||||
to ensure that compiled objects don't contain privileged functions that
|
|
||||||
call non-privileged functions. Needless to say, `mprotect()` needs to be
|
|
||||||
a privileged function, so that it can be used to disable the execute bit
|
|
||||||
on all other parts of the executable except for the privileged section,
|
|
||||||
thereby making it writable. Once this has been done, code can change.
|
|
||||||
|
|
||||||
On Windows the displacement bytes of the TLS instruction are changed to
|
|
||||||
use the `%gs:0x1480+i*8` ABI where `i` is a number assigned by the WIN32
|
|
||||||
`TlsAlloc()` API. This avoids the need to call `TlsGetValue()` which is
|
|
||||||
implemented this exact same way under the hood. Even though 0x1480 isn't
|
|
||||||
explicitly documented by MSDN, this ABI is believed to be stable because
|
|
||||||
MSVC generates binaries that use this offset directly. The only caveat
|
|
||||||
is that `TlsAlloc()` must be called as early in the runtime init as
|
|
||||||
possible, to ensure an index less than 64 is returned.
|
|
||||||
|
|
||||||
### Thread Information Block (TIB)
|
|
||||||
|
|
||||||
The Actually Portable Executable Thread Information Block (TIB) is
|
|
||||||
defined by this version of the specification as follows:
|
|
||||||
|
|
||||||
- The 64-bit TIB self-pointer is stored at offset 0x00.
|
|
||||||
- The 64-bit TIB self-pointer is also stored at offset 0x30.
|
|
||||||
- The 32-bit `errno` value is stored at offset 0x3c.
|
|
||||||
|
|
||||||
All other parts of the thread information block should be considered
|
|
||||||
unspecified and therefore reserved for future specifications.
|
|
||||||
|
|
||||||
The APE thread information block is aligned on a 64-byte boundary.
|
|
||||||
|
|
||||||
Cosmopolitan Libc v3.5.8 (c. 2024-07-21) currently implements a thread
|
|
||||||
information block that's 512 bytes in size.
|
|
||||||
|
|
||||||
### Foreign Function Calls
|
|
||||||
|
|
||||||
Even though APE programs always use the System V ABI, there arises the
|
|
||||||
occasional need to interface with foreign functions, e.g. WIN32. The
|
|
||||||
`__attribute__((__ms_abi__))` annotation introduced by GCC v6 is used
|
|
||||||
for this purpose.
|
|
||||||
|
|
||||||
The ability to change a function's ABI on a case-by-case basis is
|
|
||||||
surprisingly enough supported by GCC, Clang, NVCC, and even the AMD HIP
|
|
||||||
compilers for both UNIX systems and Windows. All of these compilers
|
|
||||||
support both the System V ABI and the Microsoft x64 ABI.
|
|
||||||
|
|
||||||
APE binaries will actually favor the Microsoft ABI even when running on
|
|
||||||
UNIX OSes for certain dlopen() use-cases. For example, if we control the
|
|
||||||
code to a CUDA module, which we compile on each OS separately from our
|
|
||||||
main APE binary, then any function that's inside the APE binary whose
|
|
||||||
pointer may be passed into a foreign module SHOULD be compiled to use
|
|
||||||
the Microsoft ABI. This is because in practice the OS-specific module
|
|
||||||
may need to be compiled by MSVC, where MS ABI is the *only* ABI, which
|
|
||||||
forces our UNIX programs to partially conform. Thankfully, all UNIX
|
|
||||||
compilers support doing it on a case-by-case basis.
|
|
||||||
|
|
||||||
### Char Signedness
|
|
||||||
|
|
||||||
Actually Portable Executable defines `char` as signed.
|
|
||||||
|
|
||||||
Therefore conformant APE software MUST use `-fsigned-char` when building
|
|
||||||
code for aarch64, as well as any other architecture that (unlike x86-64)
|
|
||||||
would otherwise define `char` as being `unsigned char` by default.
|
|
||||||
|
|
||||||
This decision was one of the cases where it made sense to offer a more
|
|
||||||
consistent runtime experience for fat multi-arch binaries. However you
|
|
||||||
SHOULD still write code to assume `char` can go either way. But if all
|
|
||||||
you care about is using APE, then you CAN assume `char` is signed.
|
|
||||||
|
|
||||||
### Long Double
|
|
||||||
|
|
||||||
On AMD64 platforms, APE binaries define `long double` as 80-bit.
|
|
||||||
|
|
||||||
On ARM64 platforms, APE binaries define `long double` as 128-bit.
|
|
||||||
|
|
||||||
We accept inconsistency in this case, because hardware acceleration is
|
|
||||||
far more valuable than stylistic consistency in the case of mathematics.
|
|
||||||
|
|
||||||
One challenge arises on AMD64 for supporting `long double` across OSes.
|
|
||||||
Unlike UNIX systems, the Windows Executive on x86-64 initializes the x87
|
|
||||||
FPU to have double (64-bit) precision rather than 80-bit. That's because
|
|
||||||
code compiled by MSVC treats `long double` as though it were `double` to
|
|
||||||
prefer always using the more modern SSE instructions. However System V
|
|
||||||
requires genuine 80-bit `long double` support on AMD64.
|
|
||||||
|
|
||||||
Therefore, if an APE program detects that it's been started on a Windows
|
|
||||||
x86-64 system, then it SHOULD use the following assembly to initialize
|
|
||||||
the x87 FPU in System V ABI mode.
|
|
||||||
|
|
||||||
```asm
|
|
||||||
fldcw 1f(%rip)
|
|
||||||
.rodata
|
|
||||||
.balign 2
|
|
||||||
// 8087 FPU Control Word
|
|
||||||
// IM: Invalid Operation ───────────────┐
|
|
||||||
// DM: Denormal Operand ───────────────┐│
|
|
||||||
// ZM: Zero Divide ───────────────────┐││
|
|
||||||
// OM: Overflow ─────────────────────┐│││
|
|
||||||
// UM: Underflow ───────────────────┐││││
|
|
||||||
// PM: Precision ──────────────────┐│││││
|
|
||||||
// PC: Precision Control ───────┐ ││││││
|
|
||||||
// {float,∅,double,long double}│ ││││││
|
|
||||||
// RC: Rounding Control ──────┐ │ ││││││
|
|
||||||
// {even, →-∞, →+∞, →0} │┌┤ ││││││
|
|
||||||
// ┌┤││ ││││││
|
|
||||||
// d││││rr││││││
|
|
||||||
1: .short 0b00000000000000000001101111111
|
|
||||||
.previous
|
|
||||||
```
|
|
||||||
|
|
||||||
## Executable File Alignment
|
|
||||||
|
|
||||||
Actually Portable Executable is a statically-linked flat executable file
|
|
||||||
format that is, as a thing in itself, agnostic to file alignments. For
|
|
||||||
example, the shell script payload at the beginning of the file and its
|
|
||||||
statements have no such requirements. Alignment requirements are however
|
|
||||||
imposed by the executable formats that APE wraps.
|
|
||||||
|
|
||||||
1. ELF requires that file offsets be congruent with virtual addresses
|
|
||||||
modulo the CPU page size. So when we add a shell script to the start
|
|
||||||
of an executable, we need to round up to the page size in order to
|
|
||||||
maintain ELF's invariant. Although no such roundup is required on the
|
|
||||||
program segments once the invariant is restored. ELF loaders will
|
|
||||||
happily map program headers from arbitrary file intervals (which may
|
|
||||||
overlap) onto arbitrarily virtual intervals (which don't need to be
|
|
||||||
contiguous). In order to do that, the loaders will generally use
|
|
||||||
UNIX's mmap() function which is more restrictive and only accepts
|
|
||||||
addresses and offsets that are page aligned. To make it possible to
|
|
||||||
map an unaligned ELF program header that could potentially start and
|
|
||||||
stop at any byte, ELF loaders round-out the intervals, which means
|
|
||||||
adjacent unrelated data might also get mapped, which may need to be
|
|
||||||
explicitly zero'd. Thanks to the cleverness of ELF, it's possible to
|
|
||||||
have an executable file be very tiny, without needing any alignment
|
|
||||||
bytes, and it'll be loaded into a properly aligned virtual space
|
|
||||||
where segments can be as sparse as we want them to be.
|
|
||||||
|
|
||||||
2. PE doesn't care about congruence and instead defines two separate
|
|
||||||
kinds of alignment. First, PE requires that the layout of segment
|
|
||||||
memory inside the file be aligned on at minimum the classic 512 byte
|
|
||||||
MS-DOS page size. This means that, unlike ELF, some alignment padding
|
|
||||||
may need to be encoded into the file, making it slightly larger. Next
|
|
||||||
PE imposes an alignment restriction on segments once they've been
|
|
||||||
mapped into the virtual address space, which must be rounded to the
|
|
||||||
system page size. Like ELF, PE segments need to be properly ordered
|
|
||||||
but they're allowed to drift apart once mapped in a non-contiguous
|
|
||||||
sparsely mapped way. When inserting shell script content at the start
|
|
||||||
of a PE file, the most problematic thing is the need to round up to
|
|
||||||
the 64kb system granularity, which results in a lot of needless bytes
|
|
||||||
of padding being inserted by a naive second-pass linker.
|
|
||||||
|
|
||||||
3. Apple's Mach-O format is the strictest of them all. While both ELF
|
|
||||||
and PE are defined in such a way that invites great creativity, XNU
|
|
||||||
will simply refuse to an executable that does anything creative with
|
|
||||||
alignment. All loaded segments need to both start and end on a page
|
|
||||||
aligned address. XNU also wants segments to be contiguous similar to
|
|
||||||
portable executable, except it applies to both the file and virtual
|
|
||||||
spaces, which must follow the same structure.
|
|
||||||
|
|
||||||
Actually Portable Executables must conform to the strictest requirements
|
|
||||||
demanded by the support vector. Therefore an APE binary that has headers
|
|
||||||
for all three of the above executable formats MUST conform to the Apple
|
|
||||||
way of doing things. GNU ld linker scripts aren't very good at producing
|
|
||||||
ELF binaries that rigidly conform to this simple naive layout. There are
|
|
||||||
so many ways things can go wrong, where third party code might slip its
|
|
||||||
own custom section name in-between the linker script sections that are
|
|
||||||
explicitly defined, thereby causing ELF's powerful features to manifest
|
|
||||||
and the resulting content overlapping. The best `ld` flag that helps is
|
|
||||||
`--orphan-handling=error` which can help with explaining such mysteries.
|
|
||||||
|
|
||||||
While Cosmopolitan was originally defined to just use stock GNU tools,
|
|
||||||
this proved intractable over time, and the project has been evolving in
|
|
||||||
the direction of building its own. Inventing the `apelink` program was
|
|
||||||
what enabled the project to achieve multi-architecture binaries whereas
|
|
||||||
previously it was only possible to do multi-OS binaries. In the future,
|
|
||||||
our hope is that a fast power linker like Mold can be adapted to produce
|
|
||||||
fat APE binaries directly from object files in one pass.
|
|
||||||
|
|
||||||
## Position Independent Code
|
|
||||||
|
|
||||||
APE doesn't currently support position independent executable formats.
|
|
||||||
This is because APE was originally written for the GNU linker, where PIC
|
|
||||||
and PIE were after-thoughts and never fully incorporated with the older
|
|
||||||
more powerful linker script techniques upon which APE relies. Future
|
|
||||||
iterations of this specification are intended to converge on modern
|
|
||||||
standards, as our tooling becomes developed enough to support it.
|
|
||||||
|
|
||||||
However this only applies to the wrapped executable formats themselves.
|
|
||||||
While our convention to date has been to always load ELF programs at the
|
|
||||||
4mb mark, this is not guaranteed across OSes and architectures. Programs
|
|
||||||
should have no expectations that a program will be loaded to any given
|
|
||||||
address. For example, Cosmo currently implements APE on AARCH64 as
|
|
||||||
loading executables to a starting address of 0x000800000000. This
|
|
||||||
address occupies a sweet spot of requirements.
|
|
||||||
|
|
||||||
## Address Space
|
|
||||||
|
|
||||||
In order to create a single binary that supports as many platforms as
|
|
||||||
possible without needing to be recompiled, there's a very narrow range
|
|
||||||
of addresses that can be used. That range is somewhere between 32 bits
|
|
||||||
and 39 bits.
|
|
||||||
|
|
||||||
- Embedded devices that claim to be 64-bit will oftentimes only support
|
|
||||||
a virtual address space that's 39 bits in size.
|
|
||||||
|
|
||||||
- We can't load executable images on AARCH64 beneath 0x100000000 (4gb)
|
|
||||||
because Apple forbids doing that, possibly in an effort to enforce a
|
|
||||||
best practice for spotting 32-bit to 64-bit transition bugs. Please
|
|
||||||
note that this restriction only applies to Apple ARM64 systems. The
|
|
||||||
x86-64 version of XNU will happily load APE binaries to 0x00400000.
|
|
||||||
|
|
||||||
- The AMD64 architecture on desktops and servers can usually be counted
|
|
||||||
upon to provide a 47-bit address space. The Linux Kernel for instance
|
|
||||||
grants each userspace program full dominion over addresses 0x00200000
|
|
||||||
through 0x00007fffffffffff provided the hardware supports this. On
|
|
||||||
modern workstations supporting Intel and AMD's new PML5T feature which
|
|
||||||
virtualizes memory using a radix trie that's five layers deep, Linux
|
|
||||||
is able to offer userspace its choice of fixed addresses from
|
|
||||||
0x00200000 through 0x00ffffffffffffff. The only exception to this rule
|
|
||||||
we've encountered so far is that Windows 7 and Windows Vista behaved
|
|
||||||
similar to embedded devices in reducing the number of va bits.
|
|
||||||
|
|
||||||
## Page Size
|
|
||||||
|
|
||||||
APE software MUST be page size agnostic. For many years the industry had
|
|
||||||
converged on a strong consensus of having a page size that's 4096 bytes.
|
|
||||||
However this convention was never guaranteed. New computers have become
|
|
||||||
extremely popular, such as Apple Silicon, that use a 16kb page size.
|
|
||||||
|
|
||||||
By convention, Cosmopolitan Libc currently generates ELF headers for
|
|
||||||
x86-64 that are strictly aligned on a 4096-byte page size. On ARM64
|
|
||||||
Cosmopolitan is currently implemented to always generate ELF headers
|
|
||||||
aligned on a 16kb page size.
|
|
||||||
|
|
||||||
In addition to being page size agnostic, APE software that cares about
|
|
||||||
working correctly on Windows needs to be aware of the concept of
|
|
||||||
allocation granularity. While the page size on Windows is generally 4kb
|
|
||||||
in size, memory mappings can only be created on addresses that aligned
|
|
||||||
to the system allocation granularity, which is generally 64kb. If you
|
|
||||||
use a function like mmap() with Cosmopolitan Libc, then the `addr` and
|
|
||||||
`offset` parameters need to be aligned to `sysconf(_SC_GRANSIZE)` or
|
|
||||||
else your software won't work on Windows. Windows has other limitations
|
|
||||||
too, such as lacking the ability to carve or punch holes in mappings.
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -18,12 +18,11 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "ape/ape.h"
|
#include "ape/ape.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
|
|
||||||
_start: mov x1,sp
|
_start: mov x1,sp
|
||||||
and sp,x1,#-16
|
|
||||||
mov x29,0
|
mov x29,0
|
||||||
bl ApeLoader
|
bl ApeLoader
|
||||||
.endfn _start,globl
|
.endfn _start,globl
|
||||||
|
@ -34,7 +33,6 @@ XnuEntrypoint:
|
||||||
mov $_HOSTXNU,%dl // xnu's not unix!
|
mov $_HOSTXNU,%dl // xnu's not unix!
|
||||||
ElfEntrypoint:
|
ElfEntrypoint:
|
||||||
mov %rsp,%rsi // save real stack
|
mov %rsp,%rsi // save real stack
|
||||||
andq $-16,%rsp // force SSE alignment
|
|
||||||
call ApeLoader
|
call ApeLoader
|
||||||
.endfn ElfEntrypoint,globl
|
.endfn ElfEntrypoint,globl
|
||||||
.endfn XnuEntrypoint,globl
|
.endfn XnuEntrypoint,globl
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
// Invokes system call.
|
// Invokes system call.
|
||||||
//
|
//
|
||||||
|
|
19
bin/aarch64-unknown-cosmo-addr2line
Executable file
19
bin/aarch64-unknown-cosmo-addr2line
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-${m:-aarch64}}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-addr2line"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
1
bin/aarch64-unknown-cosmo-apecopy
Symbolic link
1
bin/aarch64-unknown-cosmo-apecopy
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
apecopy
|
21
bin/aarch64-unknown-cosmo-ar
Executable file
21
bin/aarch64-unknown-cosmo-ar
Executable file
|
@ -0,0 +1,21 @@
|
||||||
|
#!/bin/sh
|
||||||
|
PROG=${0##*/}
|
||||||
|
MODE=${MODE:-${m:-aarch64}}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
|
||||||
|
fatal_error() {
|
||||||
|
echo "$PROG: $1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-ar" ]; then
|
||||||
|
fatal_error "you need to run: aarch64-unknown-cosmo-cc --update"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-ar" "$@"
|
19
bin/aarch64-unknown-cosmo-as
Executable file
19
bin/aarch64-unknown-cosmo-as
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-${m:-aarch64}}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-as"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
19
bin/aarch64-unknown-cosmo-nm
Executable file
19
bin/aarch64-unknown-cosmo-nm
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-${m:-aarch64}}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-nm"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
19
bin/aarch64-unknown-cosmo-objcopy
Executable file
19
bin/aarch64-unknown-cosmo-objcopy
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-${m:-aarch64}}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-objcopy"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
19
bin/aarch64-unknown-cosmo-objdump
Executable file
19
bin/aarch64-unknown-cosmo-objdump
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-${m:-aarch64}}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-objdump"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
19
bin/aarch64-unknown-cosmo-strip
Executable file
19
bin/aarch64-unknown-cosmo-strip
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-${m:-aarch64}}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos/aarch64}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/aarch64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-strip"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: aarch64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
134
bin/ape-install
Executable file
134
bin/ape-install
Executable file
|
@ -0,0 +1,134 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
PROG=${0##*/}
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
|
||||||
|
if [ ! -f ape/loader.c ]; then
|
||||||
|
cd "$COSMO" || exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(id -u)" -eq 0 ]; then
|
||||||
|
SUDO=
|
||||||
|
else
|
||||||
|
SUDO=sudo
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Actually Portable Executable (APE) Installer" >&2
|
||||||
|
echo "Author: Justine Tunney <jtunney@gmail.com>" >&2
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# INSTALL APE LOADER SYSTEMWIDE
|
||||||
|
|
||||||
|
if [ -f o/depend ] && make -j8 o//ape; then
|
||||||
|
echo "successfully recompiled ape loader" >&2
|
||||||
|
elif [ -x o//ape/ape.elf ] && [ -x o//ape/ape.macho ]; then
|
||||||
|
echo "using ape loader you compiled earlier" >&2
|
||||||
|
elif [ -d build/bootstrap ]; then
|
||||||
|
# if make isn't being used then it's unlikely the user changed the sources
|
||||||
|
# in that case the prebuilt binaries should be completely up-to-date
|
||||||
|
echo "using prebuilt ape loader from cosmo repo" >&2
|
||||||
|
mkdir -p o//ape || exit
|
||||||
|
cp -af build/bootstrap/ape.elf o//ape/ape.elf || exit
|
||||||
|
cp -af build/bootstrap/ape.macho o//ape/ape.macho || exit
|
||||||
|
else
|
||||||
|
echo "no cosmopolitan libc repository here" >&2
|
||||||
|
echo "fetching ape loader from justine.lol" >&2
|
||||||
|
mkdir -p o//ape || exit
|
||||||
|
if command -v wget >/dev/null 2>&1; then
|
||||||
|
wget -qO o//ape/ape.elf https://justine.lol/ape.elf || exit
|
||||||
|
wget -qO o//ape/ape.macho https://justine.lol/ape.macho || exit
|
||||||
|
else
|
||||||
|
curl -Rso o//ape/ape.elf https://justine.lol/ape.elf || exit
|
||||||
|
curl -Rso o//ape/ape.macho https://justine.lol/ape.macho || exit
|
||||||
|
fi
|
||||||
|
chmod +x o//ape/ape.elf || exit
|
||||||
|
chmod +x o//ape/ape.macho || exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$(uname -s)" = "Darwin" ]; then
|
||||||
|
if ! [ /usr/bin/ape -nt o//ape/ape.macho ]; then
|
||||||
|
echo >&2
|
||||||
|
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
|
||||||
|
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
|
||||||
|
$SUDO cp -f o//ape/ape.macho /usr/bin/ape || exit
|
||||||
|
echo "done" >&2
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if ! [ /usr/bin/ape -nt o//ape/ape.elf ]; then
|
||||||
|
echo >&2
|
||||||
|
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
|
||||||
|
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
|
||||||
|
$SUDO cp -f o//ape/ape.elf /usr/bin/ape || exit
|
||||||
|
echo "done" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# REGISTER APE LOADER WITH BINFMT_MISC TOO (LINUX-ONLY)
|
||||||
|
|
||||||
|
if [ x"$(uname -s)" = xLinux ]; then
|
||||||
|
|
||||||
|
if [ -e /proc/sys/fs/binfmt_misc/APE ]; then
|
||||||
|
echo >&2
|
||||||
|
echo it looks like APE is already registered with binfmt_misc >&2
|
||||||
|
echo To reinstall please run ape/apeuninstall.sh first >&2
|
||||||
|
echo please check that it is mapped to ape not /bin/sh >&2
|
||||||
|
echo cat /proc/sys/fs/binfmt_misc/APE >&2
|
||||||
|
cat /proc/sys/fs/binfmt_misc/APE >&2
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -e /proc/sys/fs/binfmt_misc ]; then
|
||||||
|
echo >&2
|
||||||
|
echo loading binfmt_misc into your kernel >&2
|
||||||
|
echo you may need to edit configs to persist across reboot >&2
|
||||||
|
echo $SUDO modprobe binfmt_misc >&2
|
||||||
|
$SUDO modprobe binfmt_misc || exit
|
||||||
|
echo done >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! [ -e /proc/sys/fs/binfmt_misc/register ]; then
|
||||||
|
echo >&2
|
||||||
|
echo mounting binfmt_misc into your kernel >&2
|
||||||
|
echo you may need to edit configs to persist across reboot >&2
|
||||||
|
echo $SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc >&2
|
||||||
|
$SUDO mount -t binfmt_misc none /proc/sys/fs/binfmt_misc || exit
|
||||||
|
echo done >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo >&2
|
||||||
|
echo registering APE with binfmt_misc >&2
|
||||||
|
echo you may need to edit configs to persist across reboot >&2
|
||||||
|
echo '$SUDO sh -c "echo '"'"':APE:M::MZqFpD::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||||
|
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||||
|
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||||
|
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||||
|
echo done >&2
|
||||||
|
|
||||||
|
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
||||||
|
echo >&2
|
||||||
|
echo enabling binfmt_misc >&2
|
||||||
|
echo you may need to edit configs to persist across reboot >&2
|
||||||
|
echo $SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' >&2
|
||||||
|
$SUDO sh -c 'echo 1 >/proc/sys/fs/binfmt_misc/status' || exit
|
||||||
|
echo done >&2
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
|
||||||
|
{
|
||||||
|
echo
|
||||||
|
echo "------------------------------------------------------------------"
|
||||||
|
echo
|
||||||
|
echo "APE INSTALL COMPLETE"
|
||||||
|
echo
|
||||||
|
echo "If you decide to uninstall APE later on"
|
||||||
|
echo "you may do so using ape/apeuninstall.sh"
|
||||||
|
echo
|
||||||
|
echo "Enjoy your APE loader (>'.')>"
|
||||||
|
echo
|
||||||
|
} >&2
|
60
bin/ape-uninstall
Executable file
60
bin/ape-uninstall
Executable file
|
@ -0,0 +1,60 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
PROG=${0##*/}
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
|
||||||
|
if [ ! -f ape/loader.c ]; then
|
||||||
|
cd "$COSMO" || exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$UID" = "0" ]; then
|
||||||
|
SUDO=
|
||||||
|
else
|
||||||
|
SUDO=sudo
|
||||||
|
fi
|
||||||
|
|
||||||
|
{
|
||||||
|
echo
|
||||||
|
echo "APE Uninstaller intends to run (in pseudo-shell)"
|
||||||
|
echo
|
||||||
|
echo " sudo echo -1 into /proc/sys/fs/binfmt_misc/APE*"
|
||||||
|
echo " sudo rm -f /usr/bin/ape ~/.ape /tmp/.ape # etc."
|
||||||
|
echo
|
||||||
|
echo "You may then use ape/apeinstall.sh to reinstall it"
|
||||||
|
echo
|
||||||
|
} >&2
|
||||||
|
|
||||||
|
set -ex
|
||||||
|
for f in /proc/sys/fs/binfmt_misc/APE*; do
|
||||||
|
if [ -f $f ]; then
|
||||||
|
$SUDO sh -c "echo -1 >$f" || exit
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# system installation
|
||||||
|
if [ -f /usr/bin/ape ]; then
|
||||||
|
$SUDO rm -f /usr/bin/ape
|
||||||
|
fi
|
||||||
|
|
||||||
|
# legacy installations
|
||||||
|
rm -f o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape"
|
||||||
|
|
||||||
|
# ad-hoc installations
|
||||||
|
for x in .ape \
|
||||||
|
.ape-1.1 \
|
||||||
|
.ape-1.3 \
|
||||||
|
.ape-1.4 \
|
||||||
|
.ape-1.5 \
|
||||||
|
.ape-1.6 \
|
||||||
|
.ape-1.7 \
|
||||||
|
.ape-1.8 \
|
||||||
|
.ape-blink-0.9.2 \
|
||||||
|
.ape-blink-1.0.0; do
|
||||||
|
rm -f \
|
||||||
|
~/$x \
|
||||||
|
/tmp/$x \
|
||||||
|
o/tmp/$x \
|
||||||
|
"${TMPDIR:-/tmp}/$x"
|
||||||
|
done
|
102
bin/apecopy
Executable file
102
bin/apecopy
Executable file
|
@ -0,0 +1,102 @@
|
||||||
|
#!/bin/sh
|
||||||
|
PROG=${0##*/}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
|
||||||
|
if [ x"$1" = x"--version" ]; then
|
||||||
|
cat <<EOF
|
||||||
|
$PROG 0.1
|
||||||
|
Copyright (c) 2023 Justine Alexandra Roberts Tunney
|
||||||
|
Cosmopolitan Libc and LLVM libcxx/compiler-rt are subject to non-GPL
|
||||||
|
notice licenses, e.g. ISC, MIT, etc. Your compiled programs must embed
|
||||||
|
our copyright notices. This toolchain is configured to do so default.
|
||||||
|
Cosmopolitan comes with absolutely NO WARRANTY of any kind.
|
||||||
|
For more information, see the Cosmopolitan LICENSE files.
|
||||||
|
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
This launches GNU GCC/Binutils subprocesses, which is free software; see
|
||||||
|
Cosmopolitan's third_party/gcc/ for source code and copying conditions.
|
||||||
|
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE.
|
||||||
|
EOF
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$1" = x"--help" ]; then
|
||||||
|
cat <<EOF
|
||||||
|
Usage: $PROG INPUT OUTPUT
|
||||||
|
Converts an executable linked by cosmocc to the Actually Portable
|
||||||
|
Executable file format. See $PROG --version for other details.
|
||||||
|
EOF
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
fatal_error() {
|
||||||
|
echo "$PROG: fatal error: $1" >&2
|
||||||
|
echo "operation terminated." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
CROSS=1
|
||||||
|
ARCH=${PROG%%-*} # split(prog, '-')[0]
|
||||||
|
if [ x"$ARCH" = x"$PROG" ]; then
|
||||||
|
ARCH=x86_64
|
||||||
|
CROSS=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$ARCH" = x"x86_64" ]; then
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
else
|
||||||
|
MODE=${MODE:-${m:-$ARCH}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $CROSS -eq 0 ]; then
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
else
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos/$ARCH}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$ARCH" = x"x86_64" ]; then
|
||||||
|
OBJCOPYFLAGS="-S -O binary"
|
||||||
|
elif [ x"$ARCH" = x"aarch64" ]; then
|
||||||
|
OBJCOPYFLAGS="-S"
|
||||||
|
else
|
||||||
|
fatal_error "$ARCH: unsupported architecture"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$COSMO" ]; then
|
||||||
|
fatal_error "you need to clone cosmopolitan to your $COSMO directory"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$COSMO/o//tool/build/zipcopy.com" ] ||
|
||||||
|
[ ! -f "$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-objcopy" ]; then
|
||||||
|
if [ $CROSS -eq 0 ]; then
|
||||||
|
fatal_error "you need to run: cosmocc --update"
|
||||||
|
else
|
||||||
|
fatal_error "you need to run: $ARCH-unknown-cosmo-cosmocc --update"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
INPUT=$1
|
||||||
|
OUTPUT=$2
|
||||||
|
if [ ! -f "$INPUT" ]; then
|
||||||
|
fatal_error "$INPUT: missing input and output arguments"
|
||||||
|
elif [ ! -f "$INPUT" ]; then
|
||||||
|
fatal_error "$INPUT: no such file"
|
||||||
|
elif [ ! -f "$INPUT" ]; then
|
||||||
|
fatal_error "$INPUT: missing output argument"
|
||||||
|
elif [ x"$INPUT" = x"$OUTPUT" ]; then
|
||||||
|
fatal_error "$INPUT: input and output file can't be the same"
|
||||||
|
fi
|
||||||
|
|
||||||
|
"$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-objcopy" \
|
||||||
|
$OBJCOPYFLAGS \
|
||||||
|
"$INPUT" \
|
||||||
|
"$OUTPUT" || exit
|
||||||
|
"$COSMO/o//tool/build/zipcopy.com" \
|
||||||
|
"$INPUT" \
|
||||||
|
"$OUTPUT" || exit
|
3
bin/apelink
Executable file
3
bin/apelink
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
exec "$COSMO/o//tool/build/apelink.com" "$@"
|
31
bin/cosmoaddr2line
Executable file
31
bin/cosmoaddr2line
Executable file
|
@ -0,0 +1,31 @@
|
||||||
|
#!/bin/sh
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
|
||||||
|
set -- -apifCe "$@"
|
||||||
|
|
||||||
|
if [ -n "$ADDR2LINE" ]; then
|
||||||
|
exec "$ADDR2LINE" "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
find_addr2line() {
|
||||||
|
if [ -x o/third_party/gcc/bin/$1-linux-cosmo-addr2line ]; then
|
||||||
|
ADDR2LINE=o/third_party/gcc/bin/$1-linux-cosmo-addr2line
|
||||||
|
elif [ -x o/third_party/gcc/bin/$1-linux-musl-addr2line ]; then
|
||||||
|
ADDR2LINE=o/third_party/gcc/bin/$1-linux-musl-addr2line
|
||||||
|
elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-addr2line" ]; then
|
||||||
|
ADDR2LINE="$COSMO/o/third_party/gcc/bin/$1-linux-cosmo-addr2line"
|
||||||
|
elif [ -x "$COSMO/o/third_party/gcc/bin/$1-linux-musl-addr2line" ]; then
|
||||||
|
ADDR2LINE="$COSMO/o/third_party/gcc/bin/$1-linux-musl-addr2line"
|
||||||
|
else
|
||||||
|
echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
for ARCH in x86_64 aarch64; do
|
||||||
|
find_addr2line $ARCH
|
||||||
|
"$ADDR2LINE" "$@" 2>/dev/null && exit
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "error: addr2line failed" >&2
|
||||||
|
exit 1
|
381
bin/cosmocc
Executable file
381
bin/cosmocc
Executable file
|
@ -0,0 +1,381 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# cosmopolitan c/c++ compiler
|
||||||
|
#
|
||||||
|
# getting started
|
||||||
|
#
|
||||||
|
# sudo chmod 1777 /opt # sticky bit isn't required
|
||||||
|
# git clone https://github.com/jart/cosmopolitan /opt/cosmo
|
||||||
|
# export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"
|
||||||
|
# echo 'export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"' >>~/.profile
|
||||||
|
# ape-install # optionally install a faster systemwide ape loader
|
||||||
|
# cosmocc --update # pull and rebuild toolchain artifacts
|
||||||
|
#
|
||||||
|
# getting started synopsis
|
||||||
|
#
|
||||||
|
# cosmocc -o hello.com hello.c
|
||||||
|
# ./foo.com
|
||||||
|
# ./foo.com --strace
|
||||||
|
# ./foo.com --ftrace
|
||||||
|
#
|
||||||
|
# how to build a project like lua 5.4.6
|
||||||
|
#
|
||||||
|
# make all test CC=cosmocc
|
||||||
|
# src/lua -e 'print("hi")'
|
||||||
|
# make install INSTALL_TOP=/opt/cosmos
|
||||||
|
# apecopy src/lua src/lua.com # convert to portable ape binary
|
||||||
|
#
|
||||||
|
# how to cross compile a project like lua 5.4.6
|
||||||
|
#
|
||||||
|
# aarch64-unknown-cosmo-cc --update
|
||||||
|
# make clean all test CC=aarch64-unknown-cosmo-cc AR='aarch64-unknown-cosmo-ar rc' -j8
|
||||||
|
# qemu-aarch64 src/lua -e 'print("hi")'
|
||||||
|
# make install INSTALL_TOP=/opt/cosmos/aarch64
|
||||||
|
#
|
||||||
|
# building in tiny mode
|
||||||
|
#
|
||||||
|
# export MODE=tiny
|
||||||
|
# cosmocc --update
|
||||||
|
# cosmocc -Os -o foo.com foo.c
|
||||||
|
#
|
||||||
|
# building in tiniest mode (linux only)
|
||||||
|
#
|
||||||
|
# export MODE=tinylinux
|
||||||
|
# cosmocc --update
|
||||||
|
# cosmocc -Os -o foo.com foo.c
|
||||||
|
#
|
||||||
|
# hardening programs with memory safety
|
||||||
|
#
|
||||||
|
# export MODE=asan
|
||||||
|
# cosmocc --update
|
||||||
|
# cosmocc -o foo.com foo.c
|
||||||
|
#
|
||||||
|
# detecting this environment
|
||||||
|
#
|
||||||
|
# - `__COSMOCC__` is defined when this compiler is in play
|
||||||
|
# - `__COSMOPOLITAN__` is always defined by Cosmopolitan Libc
|
||||||
|
#
|
||||||
|
# some notes on this compiler
|
||||||
|
#
|
||||||
|
# - the underlying compiler itself is gcc
|
||||||
|
# - we use cosmopoiltan libc rather than glibc
|
||||||
|
# - we use llvm's compiler-rt and libcxx runtimes
|
||||||
|
# - we patched gcc so switch case can have symbols
|
||||||
|
# - our scanf() implementation is somewhat troubled
|
||||||
|
#
|
||||||
|
# compiler flags that aren't supported
|
||||||
|
#
|
||||||
|
# - `-r` partial linking not implemented yet (todo)
|
||||||
|
# - `-S` you need to put your assembly behind #ifdefs instead
|
||||||
|
# - `-fexceptions` cosmopolitan doesn't support c++ exceptions yet
|
||||||
|
# - `-frtti` cosmopolitan doesn't support c++ runtime reflection yet
|
||||||
|
# - `-mred-zone` the system v red zone doesn't exist on windows and metal
|
||||||
|
# - `-fpic`, '-fPIC', `-shared`, `-pie`, etc. no shared object support yet
|
||||||
|
# - `-fsanitize=thread` cosmopolitan doesn't have thread sanitizer runtime yet
|
||||||
|
# - `-fomit-frame-pointer` is partially supported (apple forbids full removal)
|
||||||
|
#
|
||||||
|
# for further details, run `man gcc`
|
||||||
|
|
||||||
|
PROG=${0##*/}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
GCC_VERSION=11.2.0
|
||||||
|
|
||||||
|
if [ "$1" = "--version" ]; then
|
||||||
|
cat <<EOF
|
||||||
|
$PROG (GCC) $GCC_VERSION
|
||||||
|
Copyright (c) 2023 Justine Alexandra Roberts Tunney
|
||||||
|
Cosmopolitan Libc and LLVM libcxx/compiler-rt are subject to non-GPL
|
||||||
|
notice licenses, e.g. ISC, MIT, etc. Your compiled programs must embed
|
||||||
|
our copyright notices. This toolchain is configured to do so default.
|
||||||
|
Cosmopolitan comes with absolutely NO WARRANTY of any kind.
|
||||||
|
For more information, see the Cosmopolitan LICENSE files.
|
||||||
|
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
This launches GNU GCC/Binutils subprocesses, which is free software; see
|
||||||
|
Cosmopolitan's third_party/gcc/ for source code and copying conditions.
|
||||||
|
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE.
|
||||||
|
EOF
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
fatal_error() {
|
||||||
|
echo "$PROG: fatal error: $1" >&2
|
||||||
|
echo "compilation terminated." >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
log_command() {
|
||||||
|
if [ -n "$BUILDLOG" ]; then
|
||||||
|
printf '# %s\n(cd %s; %s)\n' "$ORIGINAL" "$PWD" "$*" >>"$BUILDLOG"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
ORIGINAL="$0 $*"
|
||||||
|
PLATFORM="-D__COSMOPOLITAN__ -D__COSMOCC__"
|
||||||
|
PREDEF="-include libc/integral/normalize.inc"
|
||||||
|
CFLAGS="-fportcosmo -fno-dwarf2-cfi-asm -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-semantic-interposition"
|
||||||
|
CPPFLAGS="-fno-pie -nostdinc -fno-math-errno -iquote $COSMO"
|
||||||
|
LDFLAGS="-static -no-pie -nostdlib -fuse-ld=bfd"
|
||||||
|
APEFLAGS="-Wl,--gc-sections"
|
||||||
|
PRECIOUS="-fno-omit-frame-pointer"
|
||||||
|
|
||||||
|
CROSS=1
|
||||||
|
ARCH=${PROG%%-*} # split(prog, '-')[0]
|
||||||
|
if [ x"$ARCH" = x"$PROG" ]; then
|
||||||
|
ARCH=x86_64
|
||||||
|
CROSS=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$ARCH" = x"x86_64" ]; then
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
else
|
||||||
|
MODE=${MODE:-${m:-$ARCH}}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $CROSS -eq 0 ]; then
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
else
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos/$ARCH}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
CC="$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-gcc"
|
||||||
|
CRT="$COSMO/o/$MODE/libc/crt/crt.o"
|
||||||
|
LDLIBS="$COSMO/o/$MODE/cosmopolitan.a"
|
||||||
|
CPPFLAGS="$CPPFLAGS -isystem $COSMOS/include -isystem $COSMO/libc/isystem"
|
||||||
|
LDFLAGS="$LDFLAGS -L$COSMOS/lib"
|
||||||
|
if [ x"$PROG" != x"${PROG%++}" ]; then
|
||||||
|
CC="$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-g++"
|
||||||
|
CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit"
|
||||||
|
LDLIBS="$COSMO/o/$MODE/third_party/libcxx/libcxx.a $LDLIBS"
|
||||||
|
fi
|
||||||
|
|
||||||
|
PAGESZ=4096
|
||||||
|
if [ x"$ARCH" = x"x86_64" ]; then
|
||||||
|
OBJCOPYFLAGS="-S -O binary"
|
||||||
|
CRT="$COSMO/o/$MODE/ape/ape-no-modify-self.o $CRT"
|
||||||
|
CPPFLAGS="$CPPFLAGS -mno-red-zone"
|
||||||
|
CFLAGS="$CFLAGS -mno-tls-direct-seg-refs"
|
||||||
|
LDFLAGS="$LDFLAGS -Wl,-T,$COSMO/o/$MODE/ape/ape.lds"
|
||||||
|
if [ x"$MODE" = x"aarch64" ]; then
|
||||||
|
fatal_error '$MODE must not be aarch64 when using x86_64 cross compiler'
|
||||||
|
elif [ x"$MODE" != x"${MODE#* }" ]; then
|
||||||
|
fatal_error '$MODE must not contain hyphens when targeting x86_64'
|
||||||
|
fi
|
||||||
|
elif [ x"$ARCH" = x"aarch64" ]; then
|
||||||
|
OBJCOPYFLAGS="-S"
|
||||||
|
PAGESZ=16384
|
||||||
|
CFLAGS="$CFLAGS -ffixed-x18 -ffixed-x28 -mno-outline-atomics"
|
||||||
|
LDFLAGS="$LDFLAGS -Wl,-T,$COSMO/o/$MODE/ape/aarch64.lds"
|
||||||
|
if [ x"$MODE" != x"aarch64" ] && [ x"$MODE" = x"${MODE#aarch64-*}" ]; then
|
||||||
|
fatal_error '$MODE must be either "aarch64" or "aarch64-FOO" when using aarch64 cross compiler'
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
fatal_error "$ARCH: unsupported architecture"
|
||||||
|
fi
|
||||||
|
|
||||||
|
LDFLAGS="$LDFLAGS -Wl,-z,common-page-size=$PAGESZ -Wl,-z,max-page-size=16384"
|
||||||
|
|
||||||
|
if [ ! -d "$COSMO" ]; then
|
||||||
|
fatal_error "you need to clone cosmopolitan to your $COSMO directory"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = "--update" ]; then
|
||||||
|
cd $COSMO || exit
|
||||||
|
echo "building cosmo host toolchain..." >&2
|
||||||
|
make --silent -j toolchain MODE= ARCH=x86_64 || exit
|
||||||
|
echo "building cosmo target (MODE=$MODE) toolchain..." >&2
|
||||||
|
make --silent -j toolchain MODE="$MODE" || exit
|
||||||
|
echo "setting up your cosmos..." >&2
|
||||||
|
mkdir -p "$COSMOS/lib" || exit
|
||||||
|
for lib in c dl gcc_s m pthread resolv rt dl z stdc++; do
|
||||||
|
if [ ! -f "$COSMOS/lib/lib${lib}.a" ]; then
|
||||||
|
printf '\041\074\141\162\143\150\076\012' >"$COSMOS/lib/lib${lib}.a" || exit
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
echo "successfully updated your cosmo toolchain" >&2
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$COSMOS/lib/libc.a" ] ||
|
||||||
|
[ ! -f "$COSMO/o/$MODE/cosmopolitan.a" ]; then
|
||||||
|
fatal_error "you need to run: $PROG --update"
|
||||||
|
fi
|
||||||
|
|
||||||
|
OPT=
|
||||||
|
FIRST=1
|
||||||
|
OUTPUT=
|
||||||
|
SFLAG=0
|
||||||
|
INTENT=ld
|
||||||
|
GOT_SOME=0
|
||||||
|
NEED_OUTPUT=
|
||||||
|
RELOCATABLE=0
|
||||||
|
for x; do
|
||||||
|
if [ $FIRST -eq 1 ]; then
|
||||||
|
set --
|
||||||
|
FIRST=0
|
||||||
|
fi
|
||||||
|
if [ -n "$NEED_OUTPUT" ]; then
|
||||||
|
NEED_OUTPUT=
|
||||||
|
OUTPUT=$x
|
||||||
|
set -- "$@" "$x"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
if [ x"$x" = x"-" ] || # is an argument
|
||||||
|
[ x"$x" = x"${x#-*}" ]; then # !startswith(x, "-")
|
||||||
|
GOT_SOME=1
|
||||||
|
elif [ x"$x" = x"-static-libstdc++" ]; then
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-static-libgcc" ]; then
|
||||||
|
continue
|
||||||
|
elif [ x"$x" != x"${x#-O}" ]; then
|
||||||
|
OPT=$x
|
||||||
|
elif [ x"$x" = x"-c" ]; then
|
||||||
|
INTENT=cc
|
||||||
|
elif [ x"$x" = x"-s" ]; then
|
||||||
|
SFLAG=1
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-r" ]; then
|
||||||
|
RELOCATABLE=1
|
||||||
|
elif [ x"$x" = x"-E" ]; then
|
||||||
|
INTENT=cpp
|
||||||
|
elif [ x"$x" = x"-o" ]; then
|
||||||
|
NEED_OUTPUT=1
|
||||||
|
elif [ x"$x" = x"-mcosmo" ]; then
|
||||||
|
CPPFLAGS="$CPPFLAGS -D_COSMO_SOURCE"
|
||||||
|
continue
|
||||||
|
elif [ x"$x" != x"${x#-o}" ]; then
|
||||||
|
OUTPUT=${x#-o}
|
||||||
|
elif [ x"$x" = x"-fpic" ]; then
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-fPIC" ]; then
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-r" ] ||
|
||||||
|
[ x"$x" = x"-pie" ] ||
|
||||||
|
[ x"$x" = x"-frtti" ] ||
|
||||||
|
[ x"$x" = x"-shared" ] ||
|
||||||
|
[ x"$x" = x"-nostdlib" ] ||
|
||||||
|
[ x"$x" = x"-mred-zone" ] ||
|
||||||
|
[ x"$x" = x"-fexceptions" ] ||
|
||||||
|
[ x"$x" = x"-fsanitize=thread" ]; then
|
||||||
|
echo "$PROG: $x not supported" >&2
|
||||||
|
exit 1
|
||||||
|
elif [ x"$x" = x"-fsanitize=all" ] ||
|
||||||
|
[ x"$x" = x"-fsanitize=address" ] ||
|
||||||
|
[ x"$x" = x"-fsanitize=undefined" ]; then
|
||||||
|
echo "$PROG: use cosmo MODE=dbg or MODE=asan rather than passing $x" >&2
|
||||||
|
exit 1
|
||||||
|
elif [ x"$x" = x"-fomit-frame-pointer" ]; then
|
||||||
|
# Quoth Apple "The frame pointer register must always address a
|
||||||
|
# valid frame record. Some functions — such as leaf functions or
|
||||||
|
# tail calls — may opt not to create an entry in this list. As a
|
||||||
|
# result, stack traces are always meaningful, even without debug
|
||||||
|
# information."
|
||||||
|
set -- "$@" -momit-leaf-frame-pointer -foptimize-sibling-calls
|
||||||
|
continue
|
||||||
|
elif [ x"$x" != x"${x#-Werror}" ] || \
|
||||||
|
[ x"$x" = x"-pedantic-errors" ]; then
|
||||||
|
# this toolchain is intended for building other people's code
|
||||||
|
# elevating warnings into errors, should only be done by devs
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-march=native" ]; then
|
||||||
|
if [ $CROSS -eq 0 ]; then
|
||||||
|
set -- "$@" $("$COSMO/o//tool/build/march-native.com")
|
||||||
|
else
|
||||||
|
fatal_error "-march=native can't be used when cross compiling"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-dumpversion" ]; then
|
||||||
|
echo $GCC_VERSION
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
set -- "$@" "$x"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$GOT_SOME" -eq 0 ]; then
|
||||||
|
fatal_error "no input files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $RELOCATABLE -eq 1 ]; then
|
||||||
|
LDFLAGS="$LDFLAGS -r"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$MODE" = x"nox87" ]; then
|
||||||
|
CPPFLAGS="$CPPFLAGS -mlong-double-64"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# support --ftrace unless optimizing for size
|
||||||
|
if [ x"$OPT" != x"-Os" ] && # $OPT != -Os
|
||||||
|
[ x"${MODE%tiny}" = x"${MODE}" ]; then # $MODE not in (tiny, aarch64-tiny)
|
||||||
|
if [ x"$ARCH" = x"x86_64" ]; then
|
||||||
|
CFLAGS="$CFLAGS -fpatchable-function-entry=18,16"
|
||||||
|
elif [ x"$ARCH" = x"aarch64" ]; then
|
||||||
|
CFLAGS="$CFLAGS -fpatchable-function-entry=7,6"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ask compiler to generate sanitization code in debug mode
|
||||||
|
if [ x"$MODE" != x"${MODE%*dbg}" ]; then # endswith($MODE, "dbg")
|
||||||
|
if [ x"$ARCH" = x"x86_64" ]; then
|
||||||
|
CPPFLAGS="$CPPFLAGS -fsanitize=address -fsanitize=undefined"
|
||||||
|
else
|
||||||
|
CPPFLAGS="$CPPFLAGS -fsanitize=undefined"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ask compiler to generate memory safety code in asan mode
|
||||||
|
if [ x"$MODE" != x"${MODE%*asan}" ]; then # endswith($MODE, "asan")
|
||||||
|
if [ x"$ARCH" = x"x86_64" ]; then
|
||||||
|
CPPFLAGS="$CPPFLAGS -fsanitize=address"
|
||||||
|
else
|
||||||
|
fatal_error "address sanitizer not supported on non-x86 yet"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# maximize frame pointers unless optimizing for size
|
||||||
|
if [ x"$OPT" != x"-Os" ] && # $OPT != "-Os"
|
||||||
|
[ x"$MODE" != x"${MODE%tiny}" ]; then # endswith($MODE, "tiny")
|
||||||
|
CFLAGS="$CFLAGS -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ $INTENT = cpp ]; then
|
||||||
|
set -- "$CC" $PLATFORM $CPPFLAGS "$@"
|
||||||
|
elif [ $INTENT = cc ]; then
|
||||||
|
set -- "$CC" $PLATFORM $PREDEF $CFLAGS $CPPFLAGS "$@" $PRECIOUS
|
||||||
|
else
|
||||||
|
set -- "$CC" $PLATFORM $PREDEF $CFLAGS $CPPFLAGS $CRT "$@" $LDFLAGS $LDLIBS $PRECIOUS
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_command "$@"
|
||||||
|
"$@" || exit
|
||||||
|
|
||||||
|
if [ -n "$OUTPUT" ] && [ -f "$OUTPUT" ]; then
|
||||||
|
if [ $INTENT = cc ] || [ $INTENT = ld ]; then
|
||||||
|
"$COSMO/o//tool/build/fixupobj.com" \
|
||||||
|
"$OUTPUT" || exit
|
||||||
|
fi
|
||||||
|
if [ $INTENT = ld ]; then
|
||||||
|
if [ x"$OUTPUT" != x"${OUTPUT%.com}" ] ||
|
||||||
|
[ x"$OUTPUT" != x"${OUTPUT%.exe}" ]; then
|
||||||
|
# cosmocc -o foo.com ...
|
||||||
|
# -> foo.com (ape)
|
||||||
|
# -> foo.com.dbg (elf)
|
||||||
|
mv -f "$OUTPUT" "$OUTPUT.dbg" || exit
|
||||||
|
"$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-objcopy" \
|
||||||
|
$OBJCOPYFLAGS \
|
||||||
|
"$OUTPUT.dbg" \
|
||||||
|
"$OUTPUT" || exit
|
||||||
|
"$COSMO/o//tool/build/zipcopy.com" \
|
||||||
|
"$OUTPUT.dbg" \
|
||||||
|
"$OUTPUT" || exit
|
||||||
|
elif [ $SFLAG -eq 1 ]; then
|
||||||
|
"$COSMO/o/third_party/gcc/bin/$ARCH-linux-$BRAND-strip" \
|
||||||
|
"$OUTPUT" || exit
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
119
bin/fatcosmoar
Executable file
119
bin/fatcosmoar
Executable file
|
@ -0,0 +1,119 @@
|
||||||
|
#!/bin/sh
|
||||||
|
PROG=${0##*/}
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
|
||||||
|
fatal_error() {
|
||||||
|
echo "$PROG: $1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar" ]; then
|
||||||
|
fatal_error "you need to run: fatcosmocc --update"
|
||||||
|
fi
|
||||||
|
|
||||||
|
AR_X86_64="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar"
|
||||||
|
AR_AARCH64="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-ar"
|
||||||
|
if [ "$1" = "--version" ]; then
|
||||||
|
# note: only the underlying gnu compiler binaries are gpl
|
||||||
|
# our shell script is released with the isc license
|
||||||
|
cat <<EOF
|
||||||
|
$PROG (GNU Binutils) 2.38
|
||||||
|
Copyright (C) 2022 Free Software Foundation, Inc.
|
||||||
|
This program is free software; you may redistribute it under the terms of
|
||||||
|
the GNU General Public License version 3 or (at your option) any later version.
|
||||||
|
This program has absolutely no warranty.
|
||||||
|
EOF
|
||||||
|
exit 0
|
||||||
|
elif [ "$1" = "--help" ]; then
|
||||||
|
"$AR_X86_64" --help |
|
||||||
|
sed "s!$AR_X86_64!$PROG!g" 2>/dev/null ||
|
||||||
|
"$AR_X86_64" --help
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
FIRST=1
|
||||||
|
STATE=0
|
||||||
|
OUTPUT_X86_64=
|
||||||
|
OUTPUT_AARCH64=
|
||||||
|
INPUTS=
|
||||||
|
for x; do
|
||||||
|
if [ $FIRST -eq 1 ]; then
|
||||||
|
set --
|
||||||
|
FIRST=0
|
||||||
|
fi
|
||||||
|
if [ $STATE -eq 0 ]; then
|
||||||
|
if [ x"$x" != x"${x#--*}" ]; then # startswith(x, "--")
|
||||||
|
set -- "$@" "$x" # this is a flag
|
||||||
|
else
|
||||||
|
set -- "$@" "$x" # command argument, e.g. rcu, rcsD
|
||||||
|
STATE=1
|
||||||
|
fi
|
||||||
|
elif [ $STATE -eq 1 ]; then
|
||||||
|
OUTPUT_X86_64=$x
|
||||||
|
STATE=2
|
||||||
|
elif [ x"$x" != x"${x#* }" ]; then
|
||||||
|
fatal_error "input arguments containing spaces unsupported"
|
||||||
|
elif [ x"$x" != x"${x#@}" ]; then
|
||||||
|
fatal_error "input argument @file not supported yet"
|
||||||
|
elif [ -z "$INPUTS" ]; then
|
||||||
|
INPUTS=$x
|
||||||
|
else
|
||||||
|
INPUTS="$INPUTS $x"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
if [ -z "$OUTPUT_X86_64" ]; then
|
||||||
|
fatal_error "missing output path"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mangle_object_path() {
|
||||||
|
path=$1
|
||||||
|
arch=$2
|
||||||
|
outdir=${path%/*}
|
||||||
|
outbas=${path##*/}
|
||||||
|
if [ x"$outdir" = x"$path" ]; then
|
||||||
|
outdir=
|
||||||
|
elif [ -n "$outdir" ]; then
|
||||||
|
outdir="$outdir/"
|
||||||
|
fi
|
||||||
|
if [ ! -d "$outdir.$arch" ]; then
|
||||||
|
mkdir -p "$outdir.$arch" || Exit
|
||||||
|
fi
|
||||||
|
mangled_path="${outdir}.$arch/$outbas"
|
||||||
|
}
|
||||||
|
|
||||||
|
OBJECTS_X86_64=
|
||||||
|
OBJECTS_AARCH64=
|
||||||
|
for x in $INPUTS; do
|
||||||
|
if [ ! -f "$x" ]; then
|
||||||
|
fatal_error "$x: no such file"
|
||||||
|
fi
|
||||||
|
mangle_object_path "$x" aarch64
|
||||||
|
if [ ! -f "$mangled_path" ]; then
|
||||||
|
fatal_error "$x: missing concomitant $mangled_path file"
|
||||||
|
fi
|
||||||
|
OBJECTS_X86_64="${OBJECTS_X86_64} $x"
|
||||||
|
OBJECTS_AARCH64="${OBJECTS_AARCH64} $mangled_path"
|
||||||
|
done
|
||||||
|
|
||||||
|
mangle_object_path "$OUTPUT_X86_64" aarch64
|
||||||
|
OUTPUT_AARCH64="$mangled_path"
|
||||||
|
|
||||||
|
"$AR_X86_64" "$@" "$OUTPUT_X86_64" $OBJECTS_X86_64 &
|
||||||
|
pid1=$!
|
||||||
|
|
||||||
|
"$AR_AARCH64" "$@" "$OUTPUT_AARCH64" $OBJECTS_AARCH64 &
|
||||||
|
pid2=$!
|
||||||
|
|
||||||
|
if ! wait $pid1; then
|
||||||
|
kill $pid2 2>/dev/null
|
||||||
|
wait
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
wait $pid2 || exit
|
1
bin/fatcosmoc++
Symbolic link
1
bin/fatcosmoc++
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
fatcosmocc
|
650
bin/fatcosmocc
Executable file
650
bin/fatcosmocc
Executable file
|
@ -0,0 +1,650 @@
|
||||||
|
#!/bin/sh
|
||||||
|
#
|
||||||
|
# fat cosmopolitan c/c++ compiler
|
||||||
|
#
|
||||||
|
# - this command is a drop-in replacement for the cc or gcc command.
|
||||||
|
# the difference is that (1) your binaries will be linked with the
|
||||||
|
# cosmopolitan c library, rather than your system specific tooling
|
||||||
|
# and (2) they'll be fat ape executables that run on the platforms
|
||||||
|
#
|
||||||
|
# * amd64
|
||||||
|
# + linux
|
||||||
|
# + macos
|
||||||
|
# + windows
|
||||||
|
# + freebsd
|
||||||
|
# + openbsd
|
||||||
|
# + netbsd
|
||||||
|
# * arm64
|
||||||
|
# + linux
|
||||||
|
# + macos
|
||||||
|
# + windows (non-native)
|
||||||
|
#
|
||||||
|
# - you need to use linux to build your binaries currently, but you
|
||||||
|
# can scp and distribute the output files to the above platforms!
|
||||||
|
#
|
||||||
|
# installation
|
||||||
|
#
|
||||||
|
# sudo chmod 1777 /opt # sticky bit isn't required
|
||||||
|
# git clone https://github.com/jart/cosmopolitan /opt/cosmo
|
||||||
|
# export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"
|
||||||
|
# echo 'export PATH="/opt/cosmo/bin:/opt/cosmos/bin:$PATH"' >>~/.profile
|
||||||
|
# ape-install # optionally install a faster systemwide ape loader
|
||||||
|
# fatcosmocc --update # pull and rebuild toolchain artifacts
|
||||||
|
#
|
||||||
|
# getting started
|
||||||
|
#
|
||||||
|
# fatcosmocc -o hello.com hello.c
|
||||||
|
# ./foo.com
|
||||||
|
# unzip -vl ./foo.com
|
||||||
|
# ./foo.com --strace
|
||||||
|
# ./foo.com --ftrace
|
||||||
|
#
|
||||||
|
# building in tiny mode
|
||||||
|
#
|
||||||
|
# export MODE=tiny
|
||||||
|
# fatcosmocc --update
|
||||||
|
# fatcosmocc -Os -o foo.com foo.c
|
||||||
|
#
|
||||||
|
# building in debug mode
|
||||||
|
#
|
||||||
|
# export MODE=dbg
|
||||||
|
# fatcosmocc --update
|
||||||
|
# fatcosmocc -g -o foo.com foo.c
|
||||||
|
#
|
||||||
|
# how to build a project like lua 5.4.6
|
||||||
|
#
|
||||||
|
# make all test CC=fatcosmocc AR='fatcosmoar rcu'
|
||||||
|
# make install INSTALL_TOP=/opt/cosmos INSTALL=fatcosmoinstall
|
||||||
|
#
|
||||||
|
# how to build a project like ncurses 6.4
|
||||||
|
#
|
||||||
|
# ./configure CC=fatcosmocc \
|
||||||
|
# CXX=fatcosmoc++ \
|
||||||
|
# AR=fatcosmoar \
|
||||||
|
# INSTALL="$(command -v fatcosmoinstall)" \
|
||||||
|
# --prefix=/opt/cosmos \
|
||||||
|
# --disable-shared
|
||||||
|
# make -j8
|
||||||
|
# make install
|
||||||
|
#
|
||||||
|
# detecting this environment
|
||||||
|
#
|
||||||
|
# - `__FATCOSMOCC__` is defined by fatcosmocc
|
||||||
|
# - `__COSMOCC__` is defined by cosmocc and fatcosmocc
|
||||||
|
# - `__COSMOPOLITAN__` is always defined by cosmopolitan
|
||||||
|
#
|
||||||
|
# some notes on this compiler
|
||||||
|
#
|
||||||
|
# - the underlying compiler itself is gcc
|
||||||
|
# - we use cosmopolitan libc rather than glibc
|
||||||
|
# - we use llvm's compiler-rt and libcxx runtimes
|
||||||
|
# - we patched gcc so switch case can have symbols
|
||||||
|
# - our scanf() implementation is somewhat troubled
|
||||||
|
# - you may need to recalibrate `make -jN` as `N/2`
|
||||||
|
#
|
||||||
|
# compiler flags that work differently
|
||||||
|
#
|
||||||
|
# - `-v` will log fatcosmocc subcommands to stderr
|
||||||
|
# you can also use `export BUILDLOG=/tmp/build.log`
|
||||||
|
# - `-s` will ask apelink to not embed symbol tables in zip
|
||||||
|
# - `-E` can't be fat and runs once with x86_64 macros undefined
|
||||||
|
# - `-save-temps` will prevent deleting your arch-specific executables
|
||||||
|
#
|
||||||
|
# compiler flags that aren't supported
|
||||||
|
#
|
||||||
|
# - `-fexceptions` cosmopolitan doesn't support c++ exceptions yet
|
||||||
|
# - `-frtti` cosmopolitan doesn't support c++ runtime reflection yet
|
||||||
|
# - `-mred-zone` the system v red zone doesn't exist on windows and metal
|
||||||
|
# - `-fpic`, '-fPIC', `-shared`, `-pie`, etc. no shared object support yet
|
||||||
|
# - `-fsanitize=thread` cosmopolitan doesn't have thread sanitizer runtime yet
|
||||||
|
# - `-fomit-frame-pointer` is partially supported (apple forbids full removal)
|
||||||
|
#
|
||||||
|
# for further details, run `man gcc`
|
||||||
|
|
||||||
|
PROG=${0##*/}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
ORIGINAL="$0 $*"
|
||||||
|
TMPDIR=${TMPDIR:-/tmp}
|
||||||
|
GCC_VERSION=11.2.0
|
||||||
|
|
||||||
|
if [ "$1" = "--version" ]; then
|
||||||
|
cat <<EOF
|
||||||
|
$PROG (GCC) $GCC_VERSION
|
||||||
|
Copyright (c) 2023 Justine Alexandra Roberts Tunney
|
||||||
|
Cosmopolitan Libc and LLVM libcxx/compiler-rt are subject to non-GPL
|
||||||
|
notice licenses, e.g. ISC, MIT, etc. Your compiled programs must embed
|
||||||
|
our copyright notices. This toolchain is configured to do so default.
|
||||||
|
Cosmopolitan comes with absolutely NO WARRANTY of any kind.
|
||||||
|
For more information, see the Cosmopolitan LICENSE files.
|
||||||
|
Copyright (C) 2019 Free Software Foundation, Inc.
|
||||||
|
This launches GNU GCC/Binutils subprocesses, which is free software; see
|
||||||
|
Cosmopolitan's third_party/gcc/ for source code and copying conditions.
|
||||||
|
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE.
|
||||||
|
EOF
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = "--help" ]; then
|
||||||
|
if [ -t 1 ]; then
|
||||||
|
exec less "$0"
|
||||||
|
else
|
||||||
|
exec cat "$0"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
if [ x"$MODE" = x"" ]; then
|
||||||
|
MODE_AARCH64=aarch64
|
||||||
|
elif [ x"$MODE" = x"tiny" ]; then
|
||||||
|
MODE_AARCH64=aarch64-tiny
|
||||||
|
elif [ x"$MODE" = x"zero" ]; then
|
||||||
|
MODE_AARCH64=aarch64-zero
|
||||||
|
elif [ x"$MODE" = x"dbg" ]; then
|
||||||
|
MODE_AARCH64=aarch64-dbg
|
||||||
|
else
|
||||||
|
echo "$PROG: build MODE=$MODE not supported by fatcosmocc" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$1" = "--update" ]; then
|
||||||
|
cd $COSMO || exit
|
||||||
|
echo "building cosmo host toolchain..." >&2
|
||||||
|
make --silent -j toolchain MODE= || exit
|
||||||
|
echo "building cosmo x86_64 target (MODE=$MODE) toolchain..." >&2
|
||||||
|
make --silent -j toolchain MODE="$MODE" || exit
|
||||||
|
echo "building cosmo aarch64 target (MODE=$MODE_AARCH64) toolchain..." >&2
|
||||||
|
make --silent -j toolchain MODE="$MODE_AARCH64" || exit
|
||||||
|
echo "setting up your cosmos..." >&2
|
||||||
|
for arch in "" .aarch64/; do
|
||||||
|
mkdir -p "$COSMOS/lib/$arch" || exit
|
||||||
|
for lib in c dl gcc_s m pthread resolv rt dl z stdc++; do
|
||||||
|
if [ ! -f "$COSMOS/lib/${arch}lib${lib}.a" ]; then
|
||||||
|
printf '\041\074\141\162\143\150\076\012' >"$COSMOS/lib/${arch}lib${lib}.a" || exit
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
|
echo "successfully updated your cosmo toolchain" >&2
|
||||||
|
exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$COSMO" ]; then
|
||||||
|
echo "$PROG: you need to clone cosmopolitan to your $COSMO directory" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$COSMOS/lib/libc.a" ] ||
|
||||||
|
[ ! -f "$COSMOS/lib/.aarch64/libc.a" ] ||
|
||||||
|
[ ! -f "$COSMO/o/$MODE/cosmopolitan.a" ] ||
|
||||||
|
[ ! -f "$COSMO/o/$MODE_AARCH64/cosmopolitan.a" ]; then
|
||||||
|
echo "$PROG: you need to run: $PROG --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
FIXUPOBJ="$COSMO/o//tool/build/fixupobj.com"
|
||||||
|
TEMP_FILES=
|
||||||
|
SAVE_TEMPS=0
|
||||||
|
|
||||||
|
Exit() {
|
||||||
|
rc=${1:-$?}
|
||||||
|
if [ $SAVE_TEMPS -eq 0 ]; then
|
||||||
|
rm -f $TEMP_FILES
|
||||||
|
fi
|
||||||
|
exit $rc
|
||||||
|
}
|
||||||
|
|
||||||
|
show_warning() {
|
||||||
|
echo "$PROG: warning: $1" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
fatal_error() {
|
||||||
|
echo "$PROG: fatal error: $1" >&2
|
||||||
|
echo "compilation terminated." >&2
|
||||||
|
Exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
log_original() {
|
||||||
|
if [ -n "$BUILDLOG" ]; then
|
||||||
|
printf '# %s\n' "$ORIGINAL" >>"$BUILDLOG"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
log_command() {
|
||||||
|
if [ -n "$BUILDLOG" ]; then
|
||||||
|
printf '(cd %s; %s)\n' "$PWD" "$*" >>"$BUILDLOG"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ x"$TMPDIR" != x"${TMPDIR#* }" ]; then
|
||||||
|
fatal_error '$TMPDIR containing spaces not supported'
|
||||||
|
elif [ ! -d "$TMPDIR" ]; then
|
||||||
|
if ! mkdir -p "$TMPDIR" 2>/dev/null; then
|
||||||
|
fatal_error "$TMPDIR: not a directory"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
OPT=
|
||||||
|
ARGS=
|
||||||
|
FLAGS=
|
||||||
|
OUTPUT=
|
||||||
|
MCOSMO=0
|
||||||
|
INTENT=ld
|
||||||
|
NEED_JOIN=
|
||||||
|
NEED_EQUAL=
|
||||||
|
NEED_OUTPUT=
|
||||||
|
APELINKFLAGS=
|
||||||
|
INPUT_FILE_COUNT=0
|
||||||
|
for x; do
|
||||||
|
if [ x"$x" != x"${x#* }" ]; then
|
||||||
|
fatal_error "arguments containing spaces unsupported: $x"
|
||||||
|
fi
|
||||||
|
if [ -n "$NEED_OUTPUT" ]; then
|
||||||
|
NEED_OUTPUT=
|
||||||
|
OUTPUT=$x
|
||||||
|
continue
|
||||||
|
elif [ -n "$NEED_JOIN" ]; then
|
||||||
|
x="${NEED_JOIN}${x}"
|
||||||
|
NEED_JOIN=
|
||||||
|
elif [ -n "$NEED_EQUAL" ]; then
|
||||||
|
x="${NEED_EQUAL}=${x}"
|
||||||
|
NEED_EQUAL=
|
||||||
|
elif [ x"$x" = x"-" ] || # is alias for stdin
|
||||||
|
[ x"$x" = x"${x#-*}" ]; then # !startswith(x, "-")
|
||||||
|
if [ x"$x" != x"${x%.s}" ] ||
|
||||||
|
[ x"$x" != x"${x%.S}" ]; then
|
||||||
|
fatal_error "$x: assembler input files not supported"
|
||||||
|
elif [ x"$x" != x"${x%.so}" ] ||
|
||||||
|
[ x"$x" != x"${x%.dll}" ] ||
|
||||||
|
[ x"$x" != x"${x%.dylib}" ]; then
|
||||||
|
fatal_error "$x: dynamic shared object input files not supported"
|
||||||
|
elif [ x"$x" != x"-" ] && [ ! -f "$x" ]; then
|
||||||
|
fatal_error "$x: no such file"
|
||||||
|
fi
|
||||||
|
INPUT_FILE_COUNT=$((INPUT_FILE_COUNT + 1))
|
||||||
|
ARGS="$ARGS $x" # don't add to $FLAGS array
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-o" ]; then
|
||||||
|
NEED_OUTPUT=1
|
||||||
|
continue
|
||||||
|
elif [ x"$x" != x"${x#-o}" ]; then # startswith(x, "-o")
|
||||||
|
OUTPUT=${x#-o}
|
||||||
|
continue
|
||||||
|
elif [ x"$x" != x"${x#-O}" ]; then # startswith(x, "-O")
|
||||||
|
OPT=$x
|
||||||
|
elif [ x"$x" = x"-c" ]; then
|
||||||
|
INTENT=cc
|
||||||
|
elif [ x"$x" = x"-E" ]; then
|
||||||
|
INTENT=cpp
|
||||||
|
elif [ x"$x" = x"-s" ]; then
|
||||||
|
APELINKFLAGS="$APELINKFLAGS -s"
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-v" ]; then
|
||||||
|
exec 3<&2 # dup2(2, 3) b/c stderr will be redirected later
|
||||||
|
BUILDLOG=/dev/fd/3
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-save-temps" ]; then
|
||||||
|
SAVE_TEMPS=1
|
||||||
|
elif [ x"$x" = x"-mcosmo" ]; then
|
||||||
|
MCOSMO=1
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-fomit-frame-pointer" ]; then
|
||||||
|
# Quoth Apple: "The frame pointer register must always address a
|
||||||
|
# valid frame record. Some functions — such as leaf functions or
|
||||||
|
# tail calls — may opt not to create an entry in this list. As a
|
||||||
|
# result, stack traces are always meaningful, even without debug
|
||||||
|
# information."
|
||||||
|
x="-momit-leaf-frame-pointer -foptimize-sibling-calls"
|
||||||
|
elif [ x"$x" = x"-r" ] ||
|
||||||
|
[ x"$x" = x"-S" ] ||
|
||||||
|
[ x"$x" = x"-pie" ] ||
|
||||||
|
[ x"$x" = x"-frtti" ] ||
|
||||||
|
[ x"$x" = x"-shared" ] ||
|
||||||
|
[ x"$x" = x"-nostdlib" ] ||
|
||||||
|
[ x"$x" = x"-mred-zone" ] ||
|
||||||
|
[ x"$x" = x"-fexceptions" ] ||
|
||||||
|
[ x"$x" = x"-fsanitize=thread" ]; then
|
||||||
|
fatal_error "$x flag not supported"
|
||||||
|
elif [ x"$x" = x"-fsanitize=all" ] ||
|
||||||
|
[ x"$x" = x"-fsanitize=address" ] ||
|
||||||
|
[ x"$x" = x"-fsanitize=undefined" ]; then
|
||||||
|
fatal_error "use cosmo MODE=dbg rather than passing $x"
|
||||||
|
elif [ x"$x" = x"-mno-red-zone" ]; then
|
||||||
|
# "Any memory below the stack beyond the red zone is considered
|
||||||
|
# volatile and may be modified by the operating system at any time."
|
||||||
|
# https://devblogs.microsoft.com/oldnewthing/20190111-00/?p=100685
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-fpic" ] || [ x"$x" = x"-fPIC" ]; then
|
||||||
|
# no support for building dynamic shared objects yet. reports
|
||||||
|
# indicate that ignoring these flags, helps let autoconf know
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-Werror" ] || \
|
||||||
|
[ x"$x" = x"-pedantic-errors" ]; then
|
||||||
|
# this toolchain is intended for building other people's code
|
||||||
|
# elevating warnings into errors, should only be done by devs
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-static-libgcc" ] || \
|
||||||
|
[ x"$x" = x"-shared-libgcc" ]; then
|
||||||
|
# cosmopolitan.a always has llvm compiler runtime static code
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"-march=native" ]; then
|
||||||
|
fatal_error "-march=native can't be used when building fat binaries"
|
||||||
|
elif [ x"$x" = x"-dumpversion" ]; then
|
||||||
|
echo $GCC_VERSION
|
||||||
|
Exit 0
|
||||||
|
elif [ x"$x" = x"-e" ] ||
|
||||||
|
[ x"$x" = x"-z" ] ||
|
||||||
|
[ x"$x" = x"-T" ] ||
|
||||||
|
[ x"$x" = x"-L" ] ||
|
||||||
|
[ x"$x" = x"-I" ] ||
|
||||||
|
[ x"$x" = x"-D" ] ||
|
||||||
|
[ x"$x" = x"-U" ] ||
|
||||||
|
[ x"$x" = x"-iquote" ] ||
|
||||||
|
[ x"$x" = x"-isystem" ] ||
|
||||||
|
[ x"$x" = x"-include" ]; then
|
||||||
|
NEED_JOIN=$x
|
||||||
|
continue
|
||||||
|
elif [ x"$x" = x"--param" ]; then
|
||||||
|
NEED_EQUAL=$x
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
FLAGS="$FLAGS $x"
|
||||||
|
ARGS="$ARGS $x"
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $INPUT_FILE_COUNT -eq 0 ]; then
|
||||||
|
fatal_error "no input files"
|
||||||
|
elif [ -z "$INPUT" ] &&
|
||||||
|
[ $INTENT != ld ] &&
|
||||||
|
[ $INPUT_FILE_COUNT -gt 1 ]; then
|
||||||
|
fatal_error "cannot specify '-o' with '-c', or '-E' with multiple files"
|
||||||
|
fi
|
||||||
|
|
||||||
|
PLATFORM="-D__COSMOPOLITAN__ -D__COSMOCC__ -D__FATCOSMOCC__"
|
||||||
|
PREDEF="-include libc/integral/normalize.inc"
|
||||||
|
CPPFLAGS="-fno-pie -nostdinc -fno-math-errno -iquote $COSMO -isystem $COSMOS/include -isystem $COSMO/libc/isystem"
|
||||||
|
CFLAGS="-fportcosmo -fno-dwarf2-cfi-asm -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-semantic-interposition"
|
||||||
|
LDFLAGS="-static -nostdlib -no-pie -fuse-ld=bfd -Wl,-z,norelro -Wl,--gc-sections"
|
||||||
|
PRECIOUS="-fno-omit-frame-pointer"
|
||||||
|
|
||||||
|
if [ x"$OPT" != x"-Os" ] && [ x"$MODE" != x"tiny" ]; then
|
||||||
|
CFLAGS="$CFLAGS -fno-optimize-sibling-calls -mno-omit-leaf-frame-pointer"
|
||||||
|
fi
|
||||||
|
|
||||||
|
CC_X86_64="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-gcc"
|
||||||
|
CC_AARCH64="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-gcc"
|
||||||
|
if [ x"$PROG" != x"${PROG%++}" ]; then
|
||||||
|
CC_X86_64="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-g++"
|
||||||
|
CC_AARCH64="$COSMO/o/third_party/gcc/bin/aarch64-linux-$BRAND-g++"
|
||||||
|
CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -fuse-cxa-atexit"
|
||||||
|
fi
|
||||||
|
|
||||||
|
CRT_X86_64="$COSMO/o/$MODE/ape/ape.o $COSMO/o/$MODE/libc/crt/crt.o"
|
||||||
|
CPPFLAGS_X86_64="$CPPFLAGS -mno-red-zone"
|
||||||
|
CFLAGS_X86_64="$CFLAGS -mno-tls-direct-seg-refs"
|
||||||
|
LDFLAGS_X86_64="$LDFLAGS -L$COSMOS/lib -Wl,-T,$COSMO/o/$MODE/ape/ape.lds -Wl,-z,common-page-size=4096 -Wl,-z,max-page-size=16384"
|
||||||
|
LDLIBS_X86_64="$COSMO/o/$MODE/cosmopolitan.a"
|
||||||
|
if [ $MCOSMO -eq 1 ]; then
|
||||||
|
CPPFLAGS_X86_64="${CPPFLAGS_X86_64} -D_COSMO_SOURCE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
CRT_AARCH64="$COSMO/o/$MODE_AARCH64/libc/crt/crt.o"
|
||||||
|
CPPFLAGS_AARCH64="$CPPFLAGS"
|
||||||
|
CFLAGS_AARCH64="$CFLAGS -ffixed-x18 -ffixed-x28 -mno-outline-atomics"
|
||||||
|
LDFLAGS_AARCH64="$LDFLAGS -L$COSMOS/lib/.aarch64 -Wl,-T,$COSMO/o/${MODE_AARCH64}/ape/aarch64.lds -Wl,-z,common-page-size=16384 -Wl,-z,max-page-size=16384"
|
||||||
|
LDLIBS_AARCH64="$COSMO/o/${MODE_AARCH64}/cosmopolitan.a"
|
||||||
|
|
||||||
|
if [ x"$OPT" != x"-Os" ] && [ x"$MODE" != x"tiny" ]; then
|
||||||
|
CFLAGS_X86_64="${CFLAGS_X86_64} -fpatchable-function-entry=18,16"
|
||||||
|
CFLAGS_AARCH64="${CFLAGS_AARCH64} -fpatchable-function-entry=7,6"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$PROG" != x"${PROG%++}" ]; then
|
||||||
|
LDLIBS_X86_64="$COSMO/o/$MODE/third_party/libcxx/libcxx.a ${LDLIBS_X86_64}"
|
||||||
|
LDLIBS_AARCH64="$COSMO/o/${MODE_AARCH64}/third_party/libcxx/libcxx.a ${LDLIBS_AARCH64}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ x"$MODE" = x"dbg" ]; then
|
||||||
|
CPPFLAGS_X86_64="${CPPFLAGS_X86_64} -fsanitize=address -fsanitize=undefined"
|
||||||
|
CPPFLAGS_AARCH64="${CPPFLAGS_AARCH64} -fsanitize=undefined"
|
||||||
|
fi
|
||||||
|
|
||||||
|
log_original
|
||||||
|
|
||||||
|
if [ $INTENT = cpp ]; then
|
||||||
|
if [ -n "$OUTPUT" ]; then
|
||||||
|
ARGS="$ARGS -o$OUTPUT"
|
||||||
|
fi
|
||||||
|
set -- \
|
||||||
|
"$CC_X86_64" \
|
||||||
|
-U__k8 \
|
||||||
|
-U__k8__ \
|
||||||
|
-U__amd64 \
|
||||||
|
-U__amd64__ \
|
||||||
|
-U__x86_64 \
|
||||||
|
-U__x86_64__ \
|
||||||
|
-U__SSE__ \
|
||||||
|
-U__SSE2__ \
|
||||||
|
-U__SSE2_MATH__ \
|
||||||
|
-mno-red-zone \
|
||||||
|
$PLATFORM \
|
||||||
|
$CPPFLAGS \
|
||||||
|
$ARGS
|
||||||
|
log_command "$@"
|
||||||
|
MODE="$MODE" exec "$@"
|
||||||
|
fi
|
||||||
|
|
||||||
|
mangle_object_path() {
|
||||||
|
path=$1
|
||||||
|
arch=$2
|
||||||
|
outdir=${path%/*}
|
||||||
|
outbas=${path##*/}
|
||||||
|
if [ x"$outdir" = x"$path" ]; then
|
||||||
|
outdir=
|
||||||
|
elif [ -n "$outdir" ]; then
|
||||||
|
outdir="$outdir/"
|
||||||
|
fi
|
||||||
|
if [ ! -d "$outdir.$arch" ]; then
|
||||||
|
mkdir -p "$outdir.$arch" || Exit
|
||||||
|
fi
|
||||||
|
mangled_path="${outdir}.$arch/$outbas"
|
||||||
|
}
|
||||||
|
|
||||||
|
mktemper() {
|
||||||
|
"$COSMO/o//tool/build/mktemper.com" \
|
||||||
|
"$TMPDIR/fatcosmocc.XXXXXXXXXXXXX$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
build_object() {
|
||||||
|
out2=$(mktemper .txt) || Exit
|
||||||
|
TEMP_FILES="${TEMP_FILES} $out2"
|
||||||
|
(
|
||||||
|
set -- \
|
||||||
|
"$CC_X86_64" \
|
||||||
|
-o"$OUTPUT_X86_64" \
|
||||||
|
$PLATFORM \
|
||||||
|
$PREDEF \
|
||||||
|
$CFLAGS_X86_64 \
|
||||||
|
$CPPFLAGS_X86_64 \
|
||||||
|
"$@" \
|
||||||
|
$PRECIOUS
|
||||||
|
log_command "$@"
|
||||||
|
"$@" || exit
|
||||||
|
set -- \
|
||||||
|
"$COSMO/o//tool/build/fixupobj.com" \
|
||||||
|
"$OUTPUT_X86_64"
|
||||||
|
log_command "$@"
|
||||||
|
exec "$@"
|
||||||
|
) &
|
||||||
|
pid1=$!
|
||||||
|
(
|
||||||
|
set -- \
|
||||||
|
"$CC_AARCH64" \
|
||||||
|
-o"$OUTPUT_AARCH64" \
|
||||||
|
$PLATFORM \
|
||||||
|
$PREDEF \
|
||||||
|
$CFLAGS_AARCH64 \
|
||||||
|
$CPPFLAGS_AARCH64 \
|
||||||
|
"$@" \
|
||||||
|
$PRECIOUS &&
|
||||||
|
log_command "$@"
|
||||||
|
"$@" || exit
|
||||||
|
set -- \
|
||||||
|
"$COSMO/o//tool/build/fixupobj.com" \
|
||||||
|
"$OUTPUT_AARCH64"
|
||||||
|
log_command "$@"
|
||||||
|
exec "$@"
|
||||||
|
) 2>"$out2" &
|
||||||
|
pid2=$!
|
||||||
|
if ! wait $pid1; then
|
||||||
|
kill $pid2 2>/dev/null
|
||||||
|
wait
|
||||||
|
Exit 1
|
||||||
|
fi
|
||||||
|
if ! wait $pid2; then
|
||||||
|
echo "$PROG: x86_64 succeeded but aarch64 failed to build object" >&2
|
||||||
|
cat "$out2" >&2
|
||||||
|
Exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# turn source files into objects
|
||||||
|
LDARGS_X86_64=
|
||||||
|
LDARGS_AARCH64=
|
||||||
|
for x in $ARGS; do
|
||||||
|
if [ x"$x" != x"-" ] && # is alias for stdin
|
||||||
|
[ x"$x" != x"${x#-*}" ]; then # startswith(x, "-")
|
||||||
|
# this argument is a flag
|
||||||
|
LDARGS_X86_64="${LDARGS_X86_64} $x"
|
||||||
|
if [ x"$x" != x"${x#-L}" ]; then # startswith(x, "-L")
|
||||||
|
x="$x/.aarch64"
|
||||||
|
fi
|
||||||
|
LDARGS_AARCH64="${LDARGS_AARCH64} $x"
|
||||||
|
else
|
||||||
|
# this argument is an input file
|
||||||
|
if [ x"$x" != x"${x%.o}" ] ||
|
||||||
|
[ x"$x" != x"${x%.a}" ]; then
|
||||||
|
if [ $INTENT = cc ]; then
|
||||||
|
show_warning "$x: linker input file unused because linking not done"
|
||||||
|
else
|
||||||
|
mangle_object_path "$x" aarch64
|
||||||
|
if [ ! -f "$mangled_path" ]; then
|
||||||
|
fatal_error "$x: linker input missing concomitant $mangled_path file"
|
||||||
|
fi
|
||||||
|
LDARGS_X86_64="${LDARGS_X86_64} $x"
|
||||||
|
LDARGS_AARCH64="${LDARGS_AARCH64} $mangled_path"
|
||||||
|
fi
|
||||||
|
elif [ $INTENT = cc ]; then
|
||||||
|
if [ -n "$OUTPUT" ]; then
|
||||||
|
# e.g. `cc -c -o bar.o foo.c` is specified by user
|
||||||
|
OUTPUT_X86_64=$OUTPUT
|
||||||
|
mangle_object_path "$OUTPUT" aarch64
|
||||||
|
OUTPUT_AARCH64="$mangled_path"
|
||||||
|
build_object $FLAGS -c "$x"
|
||||||
|
else
|
||||||
|
# e.g. `cc -c dir/foo.c` builds foo.o
|
||||||
|
o=${x##*/}
|
||||||
|
OUTPUT_X86_64="${o%.*}.o"
|
||||||
|
mangle_object_path "${o%.*}.o" aarch64
|
||||||
|
OUTPUT_AARCH64="$mangled_path"
|
||||||
|
build_object $FLAGS -c "$x"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# e.g. `cc foo.c` should build a.out
|
||||||
|
if [ -z "$OUTPUT" ]; then
|
||||||
|
OUTPUT=a.out
|
||||||
|
fi
|
||||||
|
# e.g. `cc -o foo foo.c` should *not* build foo.o
|
||||||
|
OUTPUT_X86_64=$(mktemper .o) || Exit
|
||||||
|
OUTPUT_AARCH64=$(mktemper .o) || Exit
|
||||||
|
TEMP_FILES="${TEMP_FILES} ${OUTPUT_X86_64} ${OUTPUT_AARCH64}"
|
||||||
|
build_object $FLAGS -c "$x"
|
||||||
|
LDARGS_X86_64="${LDARGS_X86_64} ${OUTPUT_X86_64}"
|
||||||
|
LDARGS_AARCH64="${LDARGS_AARCH64} ${OUTPUT_AARCH64}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ $INTENT != ld ]; then
|
||||||
|
Exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
OUTPUT_X86_64=$(mktemper ".com.dbg") || Exit
|
||||||
|
OUTPUT_AARCH64=$(mktemper ".aarch64.elf") || Exit
|
||||||
|
|
||||||
|
out2=$(mktemper .txt) || Exit
|
||||||
|
TEMP_FILES="${TEMP_FILES} $out2"
|
||||||
|
(
|
||||||
|
set -- \
|
||||||
|
"$CC_X86_64" \
|
||||||
|
-o"$OUTPUT_X86_64"\
|
||||||
|
$CRT_X86_64 \
|
||||||
|
$LDFLAGS_X86_64 \
|
||||||
|
$LDARGS_X86_64 \
|
||||||
|
$LDLIBS_X86_64
|
||||||
|
log_command "$@"
|
||||||
|
"$@" || exit
|
||||||
|
set -- \
|
||||||
|
"$COSMO/o//tool/build/fixupobj.com" \
|
||||||
|
"$OUTPUT_X86_64"
|
||||||
|
log_command "$@"
|
||||||
|
exec "$@"
|
||||||
|
) &
|
||||||
|
pid1=$!
|
||||||
|
(
|
||||||
|
set -- \
|
||||||
|
"$CC_AARCH64" \
|
||||||
|
-o"$OUTPUT_AARCH64"\
|
||||||
|
$CRT_AARCH64 \
|
||||||
|
$LDFLAGS_AARCH64 \
|
||||||
|
$LDARGS_AARCH64 \
|
||||||
|
$LDLIBS_AARCH64
|
||||||
|
log_command "$@"
|
||||||
|
"$@" || exit
|
||||||
|
set -- \
|
||||||
|
"$COSMO/o//tool/build/fixupobj.com" \
|
||||||
|
"$OUTPUT_AARCH64"
|
||||||
|
log_command "$@"
|
||||||
|
exec "$@"
|
||||||
|
) 2>"$out2" &
|
||||||
|
pid2=$!
|
||||||
|
if ! wait $pid1; then
|
||||||
|
kill $pid2 2>/dev/null
|
||||||
|
wait
|
||||||
|
Exit 1
|
||||||
|
fi
|
||||||
|
if ! wait $pid2; then
|
||||||
|
echo "$PROG: x86_64 succeeded but aarch64 failed to link executable" >&2
|
||||||
|
cat "$out2" >&2
|
||||||
|
Exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"$COSMO/o//tool/build/apelink.com" \
|
||||||
|
-l "$COSMO/o/$MODE/ape/ape.elf" \
|
||||||
|
-l "$COSMO/o/$MODE_AARCH64/ape/ape.elf" \
|
||||||
|
-M "$COSMO/ape/ape-m1.c" \
|
||||||
|
-o "$OUTPUT" \
|
||||||
|
$APELINKFLAGS \
|
||||||
|
"$OUTPUT_X86_64" \
|
||||||
|
"$OUTPUT_AARCH64"
|
||||||
|
log_command "$@"
|
||||||
|
"$@" || Exit
|
||||||
|
|
||||||
|
set -- \
|
||||||
|
"$COSMO/o//tool/build/pecheck.com" "$OUTPUT"
|
||||||
|
log_command "$@"
|
||||||
|
"$@" || Exit
|
||||||
|
|
||||||
|
if [ $INTENT = ld ] && [ $SAVE_TEMPS -eq 0 ]; then
|
||||||
|
mv -f "$OUTPUT_X86_64" "${OUTPUT%.com}.com.dbg" || Exit
|
||||||
|
mv -f "$OUTPUT_AARCH64" "${OUTPUT%.com}.aarch64.elf" || Exit
|
||||||
|
fi
|
||||||
|
|
||||||
|
Exit
|
1
bin/unknown-unknown-cosmo-ar
Symbolic link
1
bin/unknown-unknown-cosmo-ar
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
fatcosmoar
|
1
bin/unknown-unknown-cosmo-c++
Symbolic link
1
bin/unknown-unknown-cosmo-c++
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
fatcosmocc
|
1
bin/unknown-unknown-cosmo-cc
Symbolic link
1
bin/unknown-unknown-cosmo-cc
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
fatcosmocc
|
1
bin/unknown-unknown-cosmo-install
Symbolic link
1
bin/unknown-unknown-cosmo-install
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
fatcosmoinstall
|
19
bin/x86_64-unknown-cosmo-addr2line
Executable file
19
bin/x86_64-unknown-cosmo-addr2line
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-addr2line"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
1
bin/x86_64-unknown-cosmo-apecopy
Symbolic link
1
bin/x86_64-unknown-cosmo-apecopy
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
apecopy
|
22
bin/x86_64-unknown-cosmo-ar
Executable file
22
bin/x86_64-unknown-cosmo-ar
Executable file
|
@ -0,0 +1,22 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
PROG=${0##*/}
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
|
||||||
|
fatal_error() {
|
||||||
|
echo "$PROG: $1" >&2
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar" ]; then
|
||||||
|
fatal_error "you need to run: x86_64-unknown-cosmo-cc --update"
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-ar" "$@"
|
19
bin/x86_64-unknown-cosmo-as
Executable file
19
bin/x86_64-unknown-cosmo-as
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-as"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
1
bin/x86_64-unknown-cosmo-c++
Symbolic link
1
bin/x86_64-unknown-cosmo-c++
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
cosmocc
|
1
bin/x86_64-unknown-cosmo-cc
Symbolic link
1
bin/x86_64-unknown-cosmo-cc
Symbolic link
|
@ -0,0 +1 @@
|
||||||
|
cosmocc
|
19
bin/x86_64-unknown-cosmo-nm
Executable file
19
bin/x86_64-unknown-cosmo-nm
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-nm"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
19
bin/x86_64-unknown-cosmo-objcopy
Executable file
19
bin/x86_64-unknown-cosmo-objcopy
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-objcopy"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
19
bin/x86_64-unknown-cosmo-objdump
Executable file
19
bin/x86_64-unknown-cosmo-objdump
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-objdump"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
19
bin/x86_64-unknown-cosmo-strip
Executable file
19
bin/x86_64-unknown-cosmo-strip
Executable file
|
@ -0,0 +1,19 @@
|
||||||
|
#!/bin/sh
|
||||||
|
MODE=${MODE:-$m}
|
||||||
|
COSMO=${COSMO:-/opt/cosmo}
|
||||||
|
COSMOS=${COSMOS:-/opt/cosmos}
|
||||||
|
|
||||||
|
if [ -x "$COSMO/o/third_party/gcc/bin/x86_64-linux-musl-gcc" ]; then
|
||||||
|
BRAND=musl
|
||||||
|
else
|
||||||
|
BRAND=cosmo
|
||||||
|
fi
|
||||||
|
|
||||||
|
TOOL="$COSMO/o/third_party/gcc/bin/x86_64-linux-$BRAND-strip"
|
||||||
|
|
||||||
|
if [ ! -x "$TOOL" ]; then
|
||||||
|
echo "$0: you need to run: x86_64-unknown-cosmo-cc --update" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
exec "$TOOL" "$@"
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/bootstrap/ar.com
Executable file
BIN
build/bootstrap/ar.com
Executable file
Binary file not shown.
BIN
build/bootstrap/chmod.com
Executable file
BIN
build/bootstrap/chmod.com
Executable file
Binary file not shown.
Binary file not shown.
BIN
build/bootstrap/cocmd.com
Executable file
BIN
build/bootstrap/cocmd.com
Executable file
Binary file not shown.
BIN
build/bootstrap/compile.com
Executable file
BIN
build/bootstrap/compile.com
Executable file
Binary file not shown.
BIN
build/bootstrap/cp.com
Executable file
BIN
build/bootstrap/cp.com
Executable file
Binary file not shown.
BIN
build/bootstrap/echo.com
Executable file
BIN
build/bootstrap/echo.com
Executable file
Binary file not shown.
BIN
build/bootstrap/fixupobj.com
Executable file
BIN
build/bootstrap/fixupobj.com
Executable file
Binary file not shown.
|
@ -1,58 +0,0 @@
|
||||||
--nocompress-debug-sections
|
|
||||||
--noexecstack
|
|
||||||
-Wa,--nocompress-debug-sections
|
|
||||||
-Wa,--noexecstack
|
|
||||||
-Wa,-msse2avx
|
|
||||||
-Werror=maybe-uninitialized
|
|
||||||
-Wno-literal-suffix
|
|
||||||
-Wno-unused-but-set-variable
|
|
||||||
-Wunsafe-loop-optimizations
|
|
||||||
-fbranch-target-load-optimize
|
|
||||||
-fcx-limited-range
|
|
||||||
-fdelete-dead-exceptions
|
|
||||||
-femit-struct-debug-baseonly
|
|
||||||
-ffp-int-builtin-inexact
|
|
||||||
-finline-functions-called-once
|
|
||||||
-fipa-pta
|
|
||||||
-fivopts
|
|
||||||
-flimit-function-alignment
|
|
||||||
-fmerge-constants
|
|
||||||
-fmodulo-sched
|
|
||||||
-fmodulo-sched-allow-regmoves
|
|
||||||
-fno-align-jumps
|
|
||||||
-fno-align-labels
|
|
||||||
-fno-align-loops
|
|
||||||
-fno-code-hoisting
|
|
||||||
-fno-cx-limited-range
|
|
||||||
-fno-fp-int-builtin-inexact
|
|
||||||
-fno-gnu-unique
|
|
||||||
-fno-inline-functions-called-once
|
|
||||||
-fno-instrument-functions
|
|
||||||
-fno-schedule-insns2
|
|
||||||
-fno-whole-program
|
|
||||||
-fopt-info-vec
|
|
||||||
-fopt-info-vec-missed
|
|
||||||
-freg-struct-return
|
|
||||||
-freschedule-modulo-scheduled-loops
|
|
||||||
-frounding-math
|
|
||||||
-fsched2-use-superblocks
|
|
||||||
-fschedule-insns
|
|
||||||
-fschedule-insns2
|
|
||||||
-fshrink-wrap
|
|
||||||
-fshrink-wrap-separate
|
|
||||||
-fsignaling-nans
|
|
||||||
-fstack-clash-protection
|
|
||||||
-ftracer
|
|
||||||
-ftrapv
|
|
||||||
-ftree-loop-im
|
|
||||||
-ftree-loop-vectorize
|
|
||||||
-funsafe-loop-optimizations
|
|
||||||
-fversion-loops-for-strides
|
|
||||||
-fwhole-program
|
|
||||||
-gdescribe-dies
|
|
||||||
-gstabs
|
|
||||||
-mcall-ms2sysv-xlogues
|
|
||||||
-mdispatch-scheduler
|
|
||||||
-mfpmath=sse+387
|
|
||||||
-mmitigate-rop
|
|
||||||
-mno-fentry
|
|
BIN
build/bootstrap/gzip.com
Executable file
BIN
build/bootstrap/gzip.com
Executable file
Binary file not shown.
BIN
build/bootstrap/make.com
Executable file
BIN
build/bootstrap/make.com
Executable file
Binary file not shown.
BIN
build/bootstrap/mkdeps.com
Executable file
BIN
build/bootstrap/mkdeps.com
Executable file
Binary file not shown.
BIN
build/bootstrap/mkdir.com
Executable file
BIN
build/bootstrap/mkdir.com
Executable file
Binary file not shown.
BIN
build/bootstrap/objbincopy.com
Executable file
BIN
build/bootstrap/objbincopy.com
Executable file
Binary file not shown.
BIN
build/bootstrap/package.com
Executable file
BIN
build/bootstrap/package.com
Executable file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue