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
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
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 -*-
|
||||
*.gz binary
|
||||
*.so binary
|
||||
*.dll binary
|
||||
*.dylib binary
|
||||
/build/bootstrap/* binary
|
||||
/usr/share/terminfo/* binary
|
||||
/usr/share/terminfo/*/* binary
|
||||
/build/bootstrap/*.com 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
|
||||
|
||||
env:
|
||||
COSMOCC_VERSION: 3.9.2
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
|
@ -22,48 +19,13 @@ jobs:
|
|||
matrix:
|
||||
mode: ["", tiny, rel, tinylinux, optlinux]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
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
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- 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
|
||||
run: sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
||||
|
||||
- name: make matrix
|
||||
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 -*-
|
||||
|
||||
/o
|
||||
/cosmocc
|
||||
/.cosmocc
|
||||
/.prompt.jtlp
|
||||
|
||||
# TODO: Find some way to have Python write to o/
|
||||
__pycache__
|
||||
|
@ -15,4 +14,3 @@ __pycache__
|
|||
/tool/emacs/*.elc
|
||||
/perf.data
|
||||
/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.
|
||||
|
||||
## 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
|
||||
|
||||
The first time you send a pull request, you need to send an email to
|
||||
Justine Tunney <jtunney@gmail.com> stating that you intend to assign her
|
||||
the copyright to the changes you contribute to Cosmopolitan. It only
|
||||
needs to happen once. This only applies to the code you *choose* to
|
||||
contribute. The email should be sent from an email address associated
|
||||
with your identity. Your email should link to your pull request.
|
||||
Please send an email to Justine Tunney <jtunney@gmail.com> stating that
|
||||
you intend to assign her the copyright to the changes you contribute to
|
||||
Cosmopolitan. Please use the same email address you use for git commits
|
||||
which should only contain original source code from you or other people
|
||||
who are also assigning copyright. Please note that, if you're employed,
|
||||
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:
|
||||
|
||||
> **From**: YOUR NAME (yname@gmail.com)
|
||||
> **To**: Justine Tunney (jtunney@gmail.com)
|
||||
> **Subject**: Cosmopolitan Copyright Assignment for YOUR NAME
|
||||
>
|
||||
> 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.
|
||||
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.
|
||||
Although that's less of an issue depending on the purpose of the files.
|
||||
For example, ownership is much less of a concern in the unit test files
|
||||
so you're encouraged to put your copyright on those, provided it's ISC.
|
||||
|
||||
## 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
|
||||
[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-*-┐
|
||||
#── 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
|
||||
#
|
||||
|
@ -21,23 +21,23 @@
|
|||
# make -j8 -O MODE=tiny
|
||||
#
|
||||
# # build individual target
|
||||
# make -j8 -O o//examples/hello
|
||||
# o//examples/hello
|
||||
# make -j8 -O o//examples/hello.com
|
||||
# o//examples/hello.com
|
||||
#
|
||||
# # view source
|
||||
# less examples/hello.c
|
||||
#
|
||||
# # view binary
|
||||
# o//tool/viz/bing o//examples/hello |
|
||||
# o//tool/viz/fold
|
||||
# o//tool/viz/bing.com o//examples/hello.com |
|
||||
# o//tool/viz/fold.com
|
||||
#
|
||||
# # view transitive closure of legalese
|
||||
# o//tool/viz/bing -n o//examples/hello |
|
||||
# o//tool/viz/fold
|
||||
# o//tool/viz/bing.com -n o//examples/hello.com |
|
||||
# o//tool/viz/fold.com
|
||||
#
|
||||
# # basic debugging
|
||||
# make -j8 -O MODE=dbg o/dbg/examples/crashreport
|
||||
# o/examples/crashreport
|
||||
# make -j8 -O MODE=dbg o/dbg/examples/crashreport.com
|
||||
# o/examples/crashreport.com
|
||||
# less examples/crashreport.c
|
||||
#
|
||||
# # extremely tiny binaries
|
||||
|
@ -51,7 +51,7 @@
|
|||
#
|
||||
# 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
|
||||
# etc.
|
||||
#
|
||||
|
@ -59,7 +59,7 @@
|
|||
#
|
||||
# build/config.mk
|
||||
|
||||
SHELL = build/bootstrap/cocmd
|
||||
SHELL = build/bootstrap/cocmd.com
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
.SUFFIXES:
|
||||
|
@ -73,51 +73,22 @@ MODE := $(m)
|
|||
endif
|
||||
endif
|
||||
|
||||
COMMA := ,
|
||||
PWD := $(shell pwd)
|
||||
|
||||
# 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)
|
||||
UNAME_M = $(shell uname -m)
|
||||
UNAME_S = $(shell uname -s)
|
||||
|
||||
# apple still distributes a 17 year old version of gnu make
|
||||
ifeq ($(MAKE_VERSION), 3.81)
|
||||
$(error please use https://cosmo.zip/pub/cosmos/bin/make)
|
||||
$(error please use build/bootstrap/make.com)
|
||||
endif
|
||||
|
||||
LC_ALL = C
|
||||
SOURCE_DATE_EPOCH = 0
|
||||
|
||||
ARFLAGS = rcsD
|
||||
ZFLAGS ?=
|
||||
XARGS ?= xargs -P4 -rs8000
|
||||
DOT ?= dot
|
||||
CLANG = clang
|
||||
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)
|
||||
# provide instructions to non-linux users on unbundling gcc
|
||||
ifeq ($(TOOLCHAIN),) # if TOOLCHAIN isn't defined
|
||||
ifeq ("$(wildcard o/third_party/gcc/bin/x86_64-linux-cosmo-*)","") # if our gcc isn't unbundled
|
||||
ifneq ($(UNAME_M)-$(UNAME_S), x86_64-Linux) # if this is not amd64 linux
|
||||
$(error you need to download https://justine.lol/cosmocc-0.0.12.zip and unzip it inside the cosmo directory)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# the default build modes is empty string
|
||||
# on x86_64 hosts, MODE= is the same as MODE=x86_64
|
||||
|
@ -131,52 +102,11 @@ MODE := aarch64
|
|||
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
|
||||
all: o
|
||||
o: o/$(MODE)
|
||||
o/$(MODE): \
|
||||
o/$(MODE)/ape \
|
||||
o/$(MODE)/ctl \
|
||||
o/$(MODE)/dsp \
|
||||
o/$(MODE)/net \
|
||||
o/$(MODE)/libc \
|
||||
|
@ -185,12 +115,7 @@ o/$(MODE): \
|
|||
o/$(MODE)/examples \
|
||||
o/$(MODE)/third_party
|
||||
|
||||
# TODO(jart): Make Emacs `C-c C-c` shortcut not need this.
|
||||
.PHONY: o/$(MODE)/ o/$(MODE)/.
|
||||
o/$(MODE)/: o/$(MODE)
|
||||
o/$(MODE)/.: o/$(MODE)
|
||||
|
||||
# check if we're using o//third_party/make/make
|
||||
# check if we're using o//third_party/make/make.com
|
||||
# we added sandboxing to guarantee cosmo's makefile is hermetic
|
||||
# it also shaves away 200ms of startup latency with native $(uniq)
|
||||
ifneq ($(LANDLOCKMAKE_VERSION),)
|
||||
|
@ -200,7 +125,7 @@ $(warning please run ape/apeinstall.sh if you intend to use landlock make)
|
|||
$(shell sleep .5)
|
||||
endif
|
||||
endif
|
||||
ifneq ($(TOOLCHAIN),)
|
||||
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
|
||||
.STRICT = 1
|
||||
endif
|
||||
endif
|
||||
|
@ -209,9 +134,10 @@ endif
|
|||
.UNVEIL += \
|
||||
libc/integral \
|
||||
libc/stdbool.h \
|
||||
libc/disclaimer.inc \
|
||||
rwc:/dev/shm \
|
||||
rx:.cosmocc \
|
||||
rx:build/bootstrap \
|
||||
rx:o/third_party/gcc \
|
||||
r:build/portcosmo.h \
|
||||
/proc/stat \
|
||||
rw:/dev/null \
|
||||
|
@ -232,163 +158,149 @@ include build/definitions.mk # ├──META
|
|||
include build/config.mk # │ You can build
|
||||
include build/rules.mk # │ You can topologically order
|
||||
include build/online.mk #─┘
|
||||
include libc/nexgen32e/BUILD.mk #─┐
|
||||
include libc/sysv/BUILD.mk # ├──SYSTEM SUPPORT
|
||||
include libc/nt/BUILD.mk # │ You can do math
|
||||
include libc/intrin/BUILD.mk # │ You can use the stack
|
||||
include third_party/compiler_rt/BUILD.mk # │ You can manipulate arrays
|
||||
include libc/tinymath/BUILD.mk # │ You can issue raw system calls
|
||||
include libc/str/BUILD.mk # │
|
||||
include third_party/xed/BUILD.mk # │
|
||||
include third_party/puff/BUILD.mk # │
|
||||
include libc/elf/BUILD.mk # │
|
||||
include ape/BUILD.mk # │
|
||||
include libc/fmt/BUILD.mk # │
|
||||
include libc/vga/BUILD.mk # │
|
||||
include libc/irq/BUILD.mk #─┘
|
||||
include libc/calls/BUILD.mk #─┐
|
||||
include libc/irq/BUILD.mk # ├──SYSTEMS RUNTIME
|
||||
include third_party/nsync/BUILD.mk # │ You can issue system calls
|
||||
include libc/runtime/BUILD.mk # │
|
||||
include libc/crt/BUILD.mk # │
|
||||
include third_party/dlmalloc/BUILD.mk #─┘
|
||||
include libc/mem/BUILD.mk #─┐
|
||||
include third_party/gdtoa/BUILD.mk # ├──DYNAMIC RUNTIME
|
||||
include third_party/nsync/mem/BUILD.mk # │ You can now use stdio
|
||||
include libc/proc/BUILD.mk # │ You can now use threads
|
||||
include libc/dlopen/BUILD.mk # │ You can now use processes
|
||||
include libc/thread/BUILD.mk # │ You can finally call malloc()
|
||||
include third_party/zlib/BUILD.mk # │
|
||||
include libc/stdio/BUILD.mk # │
|
||||
include tool/hello/BUILD.mk # │
|
||||
include third_party/tz/BUILD.mk # │
|
||||
include net/BUILD.mk # │
|
||||
include third_party/vqsort/BUILD.mk # │
|
||||
include libc/log/BUILD.mk # │
|
||||
include third_party/getopt/BUILD.mk # │
|
||||
include third_party/bzip2/BUILD.mk # │
|
||||
include dsp/core/BUILD.mk # │
|
||||
include third_party/zlib/gz/BUILD.mk # │
|
||||
include third_party/intel/BUILD.mk # │
|
||||
include third_party/aarch64/BUILD.mk # │
|
||||
include libc/BUILD.mk #─┘
|
||||
include libc/sock/BUILD.mk #─┐
|
||||
include net/http/BUILD.mk # ├──ONLINE RUNTIME
|
||||
include third_party/musl/BUILD.mk # │ You can communicate with the network
|
||||
include third_party/regex/BUILD.mk # │
|
||||
include third_party/tr/BUILD.mk # │
|
||||
include third_party/sed/BUILD.mk # │
|
||||
include libc/system/BUILD.mk # │
|
||||
include libc/x/BUILD.mk # │
|
||||
include dsp/scale/BUILD.mk # │
|
||||
include dsp/mpeg/BUILD.mk # │
|
||||
include dsp/tty/BUILD.mk # │
|
||||
include dsp/audio/BUILD.mk # │
|
||||
include dsp/prog/BUILD.mk # │
|
||||
include dsp/BUILD.mk # │
|
||||
include third_party/stb/BUILD.mk # │
|
||||
include third_party/mbedtls/BUILD.mk # │
|
||||
include third_party/ncurses/BUILD.mk # │
|
||||
include third_party/readline/BUILD.mk # │
|
||||
include third_party/libunwind/BUILD.mk # |
|
||||
include third_party/libcxxabi/BUILD.mk # |
|
||||
include third_party/double-conversion/BUILD.mk # │
|
||||
include ctl/BUILD.mk # │
|
||||
include third_party/libcxx/BUILD.mk # │
|
||||
include third_party/openmp/BUILD.mk # │
|
||||
include third_party/pcre/BUILD.mk # │
|
||||
include third_party/less/BUILD.mk # │
|
||||
include net/https/BUILD.mk #─┘
|
||||
include third_party/tidy/BUILD.mk
|
||||
include third_party/BUILD.mk
|
||||
include third_party/nsync/testing/BUILD.mk
|
||||
include libc/testlib/BUILD.mk
|
||||
include tool/viz/lib/BUILD.mk
|
||||
include tool/args/BUILD.mk
|
||||
include test/math/BUILD.mk
|
||||
include test/posix/BUILD.mk
|
||||
include test/ctl/BUILD.mk
|
||||
include test/libcxx/BUILD.mk
|
||||
include test/tool/args/BUILD.mk
|
||||
include third_party/linenoise/BUILD.mk
|
||||
include third_party/maxmind/BUILD.mk
|
||||
include net/finger/BUILD.mk
|
||||
include third_party/double-conversion/test/BUILD.mk
|
||||
include third_party/lua/BUILD.mk
|
||||
include third_party/tree/BUILD.mk
|
||||
include third_party/zstd/BUILD.mk
|
||||
include third_party/awk/BUILD.mk
|
||||
include third_party/hiredis/BUILD.mk
|
||||
include third_party/make/BUILD.mk
|
||||
include third_party/ctags/BUILD.mk
|
||||
include third_party/finger/BUILD.mk
|
||||
include third_party/argon2/BUILD.mk
|
||||
include third_party/smallz4/BUILD.mk
|
||||
include third_party/sqlite3/BUILD.mk
|
||||
include third_party/mbedtls/test/BUILD.mk
|
||||
include third_party/lz4cli/BUILD.mk
|
||||
include third_party/zip/BUILD.mk
|
||||
include third_party/xxhash/BUILD.mk
|
||||
include third_party/unzip/BUILD.mk
|
||||
include tool/build/lib/BUILD.mk
|
||||
include third_party/chibicc/BUILD.mk
|
||||
include third_party/chibicc/test/BUILD.mk
|
||||
include third_party/python/BUILD.mk
|
||||
include tool/build/BUILD.mk
|
||||
include tool/curl/BUILD.mk
|
||||
include third_party/qemu/BUILD.mk
|
||||
include third_party/libcxxabi/test/BUILD.mk
|
||||
include examples/BUILD.mk
|
||||
include examples/pyapp/BUILD.mk
|
||||
include examples/pylife/BUILD.mk
|
||||
include tool/decode/lib/BUILD.mk
|
||||
include tool/decode/BUILD.mk
|
||||
include tool/lambda/lib/BUILD.mk
|
||||
include tool/lambda/BUILD.mk
|
||||
include tool/plinko/lib/BUILD.mk
|
||||
include tool/plinko/BUILD.mk
|
||||
include test/tool/plinko/BUILD.mk
|
||||
include tool/net/BUILD.mk
|
||||
include tool/viz/BUILD.mk
|
||||
include tool/BUILD.mk
|
||||
include net/turfwar/BUILD.mk
|
||||
include test/libc/tinymath/BUILD.mk
|
||||
include test/libc/intrin/BUILD.mk
|
||||
include test/libc/mem/BUILD.mk
|
||||
include test/libc/nexgen32e/BUILD.mk
|
||||
include test/libc/runtime/BUILD.mk
|
||||
include test/libc/thread/BUILD.mk
|
||||
include test/libc/sock/BUILD.mk
|
||||
include test/libc/str/BUILD.mk
|
||||
include test/libc/log/BUILD.mk
|
||||
include test/libc/str/BUILD.mk
|
||||
include test/libc/calls/BUILD.mk
|
||||
include test/libc/x/BUILD.mk
|
||||
include test/libc/xed/BUILD.mk
|
||||
include test/libc/fmt/BUILD.mk
|
||||
include test/libc/time/BUILD.mk
|
||||
include test/libc/proc/BUILD.mk
|
||||
include test/libc/stdio/BUILD.mk
|
||||
include test/libc/system/BUILD.mk
|
||||
include test/libc/BUILD.mk
|
||||
include test/net/http/BUILD.mk
|
||||
include test/net/https/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
|
||||
include libc/nexgen32e/nexgen32e.mk #─┐
|
||||
include libc/sysv/sysv.mk # ├──SYSTEM SUPPORT
|
||||
include libc/nt/nt.mk # │ You can do math
|
||||
include libc/intrin/intrin.mk # │ You can use the stack
|
||||
include third_party/compiler_rt/compiler_rt.mk # │ You can manipulate arrays
|
||||
include libc/tinymath/tinymath.mk # │ You can issue raw system calls
|
||||
include libc/str/str.mk # │
|
||||
include third_party/xed/xed.mk # │
|
||||
include third_party/puff/puff.mk # │
|
||||
include libc/elf/elf.mk # │
|
||||
include ape/ape.mk # │
|
||||
include libc/fmt/fmt.mk # │
|
||||
include libc/vga/vga.mk #─┘
|
||||
include libc/calls/calls.mk #─┐
|
||||
include third_party/nsync/nsync.mk # │
|
||||
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
|
||||
include third_party/double-conversion/dc.mk # │ You can issue system calls
|
||||
include libc/crt/crt.mk # │
|
||||
include third_party/dlmalloc/dlmalloc.mk #─┘
|
||||
include libc/mem/mem.mk #─┐
|
||||
include third_party/gdtoa/gdtoa.mk # ├──DYNAMIC RUNTIME
|
||||
include third_party/nsync/mem/mem.mk # │ You can now use stdio
|
||||
include libc/proc/proc.mk # │ You can now use threads
|
||||
include libc/thread/thread.mk # │ You can now use processes
|
||||
include tool/hello/hello.mk # │ You can finally call malloc()
|
||||
include third_party/zlib/zlib.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
include libc/time/time.mk # │
|
||||
include net/net.mk # │
|
||||
include third_party/vqsort/vqsort.mk # │
|
||||
include libc/log/log.mk # │
|
||||
include third_party/getopt/getopt.mk # │
|
||||
include third_party/bzip2/bzip2.mk # │
|
||||
include dsp/core/core.mk # │
|
||||
include third_party/musl/musl.mk # │
|
||||
include libc/x/x.mk # │
|
||||
include third_party/stb/stb.mk # │
|
||||
include dsp/scale/scale.mk # │
|
||||
include dsp/mpeg/mpeg.mk # │
|
||||
include dsp/dsp.mk # │
|
||||
include third_party/zlib/gz/gz.mk # │
|
||||
include third_party/intel/intel.mk # │
|
||||
include third_party/aarch64/aarch64.mk # │
|
||||
include libc/libc.mk #─┘
|
||||
include libc/sock/sock.mk #─┐
|
||||
include dsp/tty/tty.mk # ├──ONLINE RUNTIME
|
||||
include libc/dns/dns.mk # │ You can communicate with the network
|
||||
include net/http/http.mk # │
|
||||
include third_party/mbedtls/mbedtls.mk # │
|
||||
include third_party/libcxx/libcxx.mk # │
|
||||
include third_party/ggml/ggml.mk # │
|
||||
include third_party/radpajama/radpajama.mk # │
|
||||
include net/https/https.mk # │
|
||||
include third_party/regex/regex.mk #─┘
|
||||
include third_party/tidy/tidy.mk
|
||||
include third_party/third_party.mk
|
||||
include third_party/nsync/testing/testing.mk
|
||||
include libc/testlib/testlib.mk
|
||||
include tool/viz/lib/vizlib.mk
|
||||
include tool/args/args.mk
|
||||
include test/tool/args/test.mk
|
||||
include third_party/linenoise/linenoise.mk
|
||||
include third_party/maxmind/maxmind.mk
|
||||
include net/finger/finger.mk
|
||||
include third_party/double-conversion/test/test.mk
|
||||
include third_party/lua/lua.mk
|
||||
include third_party/tree/tree.mk
|
||||
include third_party/zstd/zstd.mk
|
||||
include third_party/tr/tr.mk
|
||||
include third_party/sed/sed.mk
|
||||
include third_party/awk/awk.mk
|
||||
include third_party/hiredis/hiredis.mk
|
||||
include third_party/make/make.mk
|
||||
include third_party/ctags/ctags.mk
|
||||
include third_party/finger/finger.mk
|
||||
include third_party/argon2/argon2.mk
|
||||
include third_party/smallz4/smallz4.mk
|
||||
include third_party/sqlite3/sqlite3.mk
|
||||
include third_party/mbedtls/test/test.mk
|
||||
include third_party/quickjs/quickjs.mk
|
||||
include third_party/lz4cli/lz4cli.mk
|
||||
include third_party/zip/zip.mk
|
||||
include third_party/xxhash/xxhash.mk
|
||||
include third_party/unzip/unzip.mk
|
||||
include tool/build/lib/buildlib.mk
|
||||
include third_party/chibicc/chibicc.mk
|
||||
include third_party/chibicc/test/test.mk
|
||||
include third_party/python/python.mk
|
||||
include tool/build/build.mk
|
||||
include tool/curl/curl.mk
|
||||
include third_party/qemu/qemu.mk
|
||||
include examples/examples.mk
|
||||
include examples/pyapp/pyapp.mk
|
||||
include examples/pylife/pylife.mk
|
||||
include tool/decode/lib/decodelib.mk
|
||||
include tool/decode/decode.mk
|
||||
include tool/lambda/lib/lib.mk
|
||||
include tool/lambda/lambda.mk
|
||||
include tool/plinko/lib/lib.mk
|
||||
include tool/plinko/plinko.mk
|
||||
include test/tool/plinko/test.mk
|
||||
include tool/net/net.mk
|
||||
include tool/viz/viz.mk
|
||||
include tool/tool.mk
|
||||
include net/turfwar/turfwar.mk
|
||||
include test/libc/tinymath/test.mk
|
||||
include test/libc/intrin/test.mk
|
||||
include test/libc/mem/test.mk
|
||||
include test/libc/nexgen32e/test.mk
|
||||
include test/libc/runtime/test.mk
|
||||
include test/libc/thread/test.mk
|
||||
include test/libc/sock/test.mk
|
||||
include test/libc/str/test.mk
|
||||
include test/libc/log/test.mk
|
||||
include test/libc/str/test.mk
|
||||
include test/libc/calls/test.mk
|
||||
include test/libc/x/test.mk
|
||||
include test/libc/xed/test.mk
|
||||
include test/libc/fmt/test.mk
|
||||
include test/libc/dns/test.mk
|
||||
include test/libc/time/test.mk
|
||||
include test/libc/proc/test.mk
|
||||
include test/libc/stdio/test.mk
|
||||
include test/libc/release/test.mk
|
||||
include test/libc/test.mk
|
||||
include test/net/http/test.mk
|
||||
include test/net/https/test.mk
|
||||
include test/net/finger/test.mk
|
||||
include test/net/test.mk
|
||||
include test/tool/build/lib/test.mk
|
||||
include test/tool/build/test.mk
|
||||
include test/tool/viz/lib/test.mk
|
||||
include test/tool/viz/test.mk
|
||||
include test/tool/net/test.mk
|
||||
include test/tool/test.mk
|
||||
include test/dsp/core/test.mk
|
||||
include test/dsp/scale/test.mk
|
||||
include test/dsp/tty/test.mk
|
||||
include test/dsp/test.mk
|
||||
include examples/package/lib/build.mk
|
||||
include examples/package/build.mk
|
||||
#-φ-examples/package/new.sh
|
||||
include test/BUILD.mk
|
||||
include test/test.mk
|
||||
|
||||
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
|
||||
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)
|
||||
$(file >$@,$(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))))
|
||||
$(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)))
|
||||
|
||||
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) $@
|
||||
@o/$(MODE)/third_party/ctags/ctags $(TAGSFLAGS) -L $< -o $@
|
||||
@o/$(MODE)/third_party/ctags/ctags.com $(TAGSFLAGS) -L $< -o $@
|
||||
|
||||
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) $@
|
||||
@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: o/$(MODE)/tool/build/summy
|
||||
find -name \*.h -or -name \*.hpp -or -name \*.c -or -name \*.cc -or -name \*.cpp -or -name \*.S -or -name \*.mk | \
|
||||
loc: o/$(MODE)/tool/build/summy.com
|
||||
find -name \*.h -or -name \*.c -or -name \*.S | \
|
||||
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
|
||||
|
||||
COSMOPOLITAN = \
|
||||
CTL \
|
||||
DSP_AUDIO \
|
||||
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 \
|
||||
# PLEASE: MAINTAIN TOPOLOGICAL ORDER
|
||||
# FROM HIGHEST LEVEL TO LOWEST LEVEL
|
||||
COSMOPOLITAN_OBJECTS = \
|
||||
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 \
|
||||
DSP_AUDIO \
|
||||
LIBC \
|
||||
LIBC_CALLS \
|
||||
LIBC_DNS \
|
||||
LIBC_ELF \
|
||||
LIBC_FMT \
|
||||
LIBC_DLOPEN \
|
||||
LIBC_INTRIN \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
|
@ -517,6 +419,7 @@ COSMOPOLITAN_H_PKGS = \
|
|||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_THREAD \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_X \
|
||||
LIBC_VGA \
|
||||
|
@ -526,43 +429,30 @@ COSMOPOLITAN_H_PKGS = \
|
|||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_ZLIB_GZ \
|
||||
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: \
|
||||
$(call reverse,$(call uniq,$(foreach x,$(COSMOPOLITAN),$($(x)))))
|
||||
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
|
||||
|
||||
COSMOCC_HDRS = \
|
||||
$(wildcard libc/integral/*) \
|
||||
$(foreach x,$(COSMOCC_PKGS),$($(x)_HDRS)) \
|
||||
$(foreach x,$(COSMOCC_PKGS),$($(x)_INCS))
|
||||
|
||||
o/cosmocc.h.txt: Makefile libc $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x)))) $(HDRS) $(INCS)
|
||||
$(file >$@, $(call uniq,$(COSMOCC_HDRS)))
|
||||
|
||||
COSMOPOLITAN_H_ROOT_HDRS = \
|
||||
libc/integral/normalize.inc \
|
||||
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS))
|
||||
o/cosmopolitan.h: \
|
||||
o/$(MODE)/tool/build/rollup.com \
|
||||
libc/integral/normalize.inc \
|
||||
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)) \
|
||||
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_INCS))
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),libc/integral/normalize.inc $(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)))
|
||||
@$(ECHO) '#ifndef __STRICT_ANSI__' >$@
|
||||
@$(ECHO) '#define _COSMO_SOURCE' >>$@
|
||||
@$(ECHO) '#endif' >>$@
|
||||
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >>$@
|
||||
|
||||
o/cosmopolitan.html: private .UNSANDBOXED = 1
|
||||
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 %.cpp,$(filter-out %.cc,$(SRCS))) \
|
||||
$(SRCS) \
|
||||
$(HDRS)
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.cpp,$(filter-out %.cc,$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))))
|
||||
o/$(MODE)/third_party/chibicc/chibicc.dbg -J \
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))
|
||||
o/$(MODE)/third_party/chibicc/chibicc.com.dbg -J \
|
||||
-fno-common -include libc/integral/normalize.inc -o $@ \
|
||||
-DCOSMO @$(TMPDIR)/$(subst /,_,$@)
|
||||
|
||||
|
@ -576,6 +466,7 @@ $(SRCS): \
|
|||
|
||||
ifeq ($(ARCH), x86_64)
|
||||
TOOLCHAIN_ARTIFACTS = \
|
||||
o/cosmopolitan.h \
|
||||
o/$(MODE)/ape/ape.lds \
|
||||
o/$(MODE)/libc/crt/crt.o \
|
||||
o/$(MODE)/ape/ape.elf \
|
||||
|
@ -584,13 +475,13 @@ TOOLCHAIN_ARTIFACTS = \
|
|||
o/$(MODE)/ape/ape-no-modify-self.o \
|
||||
o/$(MODE)/cosmopolitan.a \
|
||||
o/$(MODE)/third_party/libcxx/libcxx.a \
|
||||
o/$(MODE)/tool/build/march-native \
|
||||
o/$(MODE)/tool/build/ar \
|
||||
o/$(MODE)/tool/build/mktemper \
|
||||
o/$(MODE)/tool/build/fixupobj \
|
||||
o/$(MODE)/tool/build/zipcopy \
|
||||
o/$(MODE)/tool/build/apelink \
|
||||
o/$(MODE)/tool/build/pecheck
|
||||
o/$(MODE)/tool/build/march-native.com \
|
||||
o/$(MODE)/tool/build/ar.com \
|
||||
o/$(MODE)/tool/build/mktemper.com \
|
||||
o/$(MODE)/tool/build/fixupobj.com \
|
||||
o/$(MODE)/tool/build/zipcopy.com \
|
||||
o/$(MODE)/tool/build/apelink.com \
|
||||
o/$(MODE)/tool/build/pecheck.com
|
||||
else
|
||||
TOOLCHAIN_ARTIFACTS = \
|
||||
o/$(MODE)/ape/ape.elf \
|
||||
|
@ -598,9 +489,9 @@ TOOLCHAIN_ARTIFACTS = \
|
|||
o/$(MODE)/libc/crt/crt.o \
|
||||
o/$(MODE)/cosmopolitan.a \
|
||||
o/$(MODE)/third_party/libcxx/libcxx.a \
|
||||
o/$(MODE)/tool/build/march-native \
|
||||
o/$(MODE)/tool/build/fixupobj \
|
||||
o/$(MODE)/tool/build/zipcopy
|
||||
o/$(MODE)/tool/build/march-native.com \
|
||||
o/$(MODE)/tool/build/fixupobj.com \
|
||||
o/$(MODE)/tool/build/zipcopy.com
|
||||
endif
|
||||
|
||||
.PHONY: toolchain
|
||||
|
|
573
README.md
573
README.md
|
@ -3,34 +3,38 @@
|
|||
[](https://github.com/jart/cosmopolitan/actions/workflows/build.yml)
|
||||
# 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
|
||||
interpreter or virtual machine. Instead, it reconfigures stock GCC and
|
||||
Clang to output a POSIX-approved polyglot format that runs natively on
|
||||
Linux + Mac + Windows + FreeBSD + OpenBSD 7.3 + NetBSD + BIOS with the
|
||||
best possible performance and the tiniest footprint imaginable.
|
||||
Linux + Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS with the best
|
||||
possible performance and the tiniest footprint imaginable.
|
||||
|
||||
## Background
|
||||
|
||||
For an introduction to this project, please read the [actually portable
|
||||
executable](https://justine.lol/ape.html) blog post and [cosmopolitan
|
||||
For an introduction to this project, please read the [αcτµαlly pδrταblε
|
||||
εxεcµταblε](https://justine.lol/ape.html) blog post and [cosmopolitan
|
||||
libc](https://justine.lol/cosmopolitan/index.html) website. We also have
|
||||
[API
|
||||
documentation](https://justine.lol/cosmopolitan/documentation.html).
|
||||
[API documentation](https://justine.lol/cosmopolitan/documentation.html).
|
||||
|
||||
## Getting Started
|
||||
|
||||
You can start by obtaining a release of our `cosmocc` compiler from
|
||||
<https://cosmo.zip/pub/cosmocc/>.
|
||||
It's recommended that Cosmopolitan be installed to `/opt/cosmo` and
|
||||
`/opt/cosmos` on your computer. The first has the monorepo. The second
|
||||
contains your non-monorepo artifacts.
|
||||
|
||||
```sh
|
||||
mkdir -p cosmocc
|
||||
cd cosmocc
|
||||
wget https://cosmo.zip/pub/cosmocc/cosmocc.zip
|
||||
unzip cosmocc.zip
|
||||
sudo mkdir -p /opt
|
||||
sudo chmod 1777 /opt
|
||||
git clone https://github.com/jart/cosmopolitan /opt/cosmo
|
||||
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
|
||||
// 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
|
||||
cosmocc -o hello hello.c
|
||||
./hello
|
||||
cosmocc -o hello.com hello.c
|
||||
./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
|
||||
|
@ -53,115 +72,445 @@ features by default, which are very useful for developers and admins.
|
|||
Here's how you can log system calls:
|
||||
|
||||
```sh
|
||||
./hello --strace
|
||||
./hello.com --strace
|
||||
```
|
||||
|
||||
Here's how you can get a much more verbose log of function calls:
|
||||
|
||||
```sh
|
||||
./hello --ftrace
|
||||
./hello.com --ftrace
|
||||
```
|
||||
|
||||
You can use the Cosmopolitan's toolchain to build conventional open
|
||||
source projects which use autotools. This strategy normally works:
|
||||
If you don't want rich runtime features like the above included, and you
|
||||
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
|
||||
export CC=x86_64-unknown-cosmo-cc
|
||||
export CXX=x86_64-unknown-cosmo-c++
|
||||
./configure --prefix=/opt/cosmos/x86_64
|
||||
export MODE=tiny
|
||||
cosmocc --update
|
||||
```
|
||||
|
||||
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 install
|
||||
```
|
||||
|
||||
## Cosmopolitan Source Builds
|
||||
|
||||
Cosmopolitan can be compiled from source on any of our supported
|
||||
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.
|
||||
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
|
||||
next move is to combine them into a single pristine `emacs.com` file.
|
||||
|
||||
```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
|
||||
bootstrap your build, you can install Cosmopolitan Make from this site:
|
||||
You can now scp your `emacs.com` build to seven operating systems for
|
||||
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
|
||||
curl -LO https://cosmo.zip/pub/cosmos/bin/make
|
||||
./make -j8
|
||||
o//examples/hello
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan.tar.gz
|
||||
tar xf cosmopolitan.tar.gz # see releases page
|
||||
cd cosmopolitan
|
||||
```
|
||||
|
||||
After you've built the repo once, you can also use the make from your
|
||||
cosmocc at `.cosmocc/current/bin/make`. You might even prefer to alias
|
||||
make to `$COSMO/.cosmocc/current/bin/make`.
|
||||
This will build the entire repository and run all the tests:
|
||||
|
||||
```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
|
||||
build one particular thing. Here's an example of a target that can be
|
||||
compiled relatively quickly, which is a simple POSIX test that only
|
||||
depends on core LIBC packages.
|
||||
build a particular thing. Cosmopolitan's build config does a good job at
|
||||
having minimal deterministic builds. For example, if you wanted to build
|
||||
only hello.com then you could do that as follows:
|
||||
|
||||
```sh
|
||||
rm -rf o//libc o//test
|
||||
.cosmocc/current/bin/make o//test/posix/signal_test
|
||||
o//test/posix/signal_test
|
||||
build/bootstrap/make.com o//examples/hello.com
|
||||
```
|
||||
|
||||
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
|
||||
all the unit tests in the `TEST_POSIX` package, you could say:
|
||||
list out each individual one. You can do that by asking make to build a
|
||||
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
|
||||
.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
|
||||
really tiny binaries (as small as 12kb in size) then you'd say:
|
||||
|
||||
```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
|
||||
have Cosmopolitan become much more similar to Musl Libc.
|
||||
Here's some other build modes you can try:
|
||||
|
||||
```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).
|
||||
|
||||
## 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
|
||||
cosmocc -o hello hello.c
|
||||
./hello --strace
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-3.0.zip
|
||||
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
|
||||
cosmocc -o hello hello.c
|
||||
./hello --ftrace
|
||||
./hello.com
|
||||
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
|
||||
able to be sent to a file by setting an environment variable.
|
||||
If `./hello.com` executed on Linux throws an error about not finding an
|
||||
interpreter, it should be fixed by running the following command (although
|
||||
note that it may not survive a system restart):
|
||||
|
||||
```sh
|
||||
export KPRINTF_LOG=log
|
||||
./hello --strace
|
||||
sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
|
||||
```
|
||||
|
||||
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
|
||||
|
||||
Here's the recommended `~/.gdbinit` config:
|
||||
|
@ -186,60 +535,46 @@ end
|
|||
src
|
||||
```
|
||||
|
||||
You normally run the `.dbg` file under gdb. If you need to debug the
|
||||
`` file itself, then you can load the debug symbols independently as
|
||||
You normally run the `.com.dbg` file under gdb. If you need to debug the
|
||||
`.com` file itself, then you can load the debug symbols independently as
|
||||
|
||||
```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`
|
||||
or simply upgrade to zsh 5.9+ (since we patched it two years ago). The
|
||||
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:
|
||||
If you're developing on MacOS you can install the GNU compiler
|
||||
collection for x86_64-elf via homebrew:
|
||||
|
||||
```sh
|
||||
jart@ubuntu:~$ wget https://cosmo.zip/pub/cosmos/bin/dash
|
||||
jart@ubuntu:~$ chmod +x dash
|
||||
jart@ubuntu:~$ ./dash
|
||||
run-detectors: unable to find an interpreter for ./dash
|
||||
brew install x86_64-elf-gcc
|
||||
```
|
||||
|
||||
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
|
||||
sudo wget -O /usr/bin/ape https://cosmo.zip/pub/cosmos/bin/ape-$(uname -m).elf
|
||||
sudo chmod +x /usr/bin/ape
|
||||
sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
||||
sudo sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
||||
```
|
||||
|
||||
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"
|
||||
mkdir -p o/third_party
|
||||
rm -rf o/third_party/gcc
|
||||
wget https://justine.lol/linux-compiler-on-windows/cross9.zip
|
||||
unzip cross9.zip
|
||||
mv cross9 o/third_party/gcc
|
||||
build/bootstrap/make.com
|
||||
```
|
||||
|
||||
## Discord Chatroom
|
||||
|
@ -249,16 +584,16 @@ server. You're welcome to join us! <https://discord.gg/FwAVVu7eJ4>
|
|||
|
||||
## Support Vector
|
||||
|
||||
| Platform | Min Version | Circa |
|
||||
| :--- | ---: | ---: |
|
||||
| AMD | K8 | 2003 |
|
||||
| Intel | Core | 2006 |
|
||||
| Linux | 2.6.18 | 2007 |
|
||||
| Windows | 8 [1] | 2012 |
|
||||
| Darwin (macOS) | 23.1.0+ | 2023 |
|
||||
| OpenBSD | 7.3 or earlier | 2023 |
|
||||
| FreeBSD | 13 | 2020 |
|
||||
| NetBSD | 9.2 | 2021 |
|
||||
| Platform | Min Version | Circa |
|
||||
| :--- | ---: | ---: |
|
||||
| AMD | K8 Venus | 2005 |
|
||||
| Intel | Core | 2006 |
|
||||
| Linux | 2.6.18 | 2007 |
|
||||
| Windows | 8 [1] | 2012 |
|
||||
| Mac OS X | 15.6 | 2018 |
|
||||
| OpenBSD | 7 | 2021 |
|
||||
| FreeBSD | 13 | 2020 |
|
||||
| NetBSD | 9.2 | 2021 |
|
||||
|
||||
[1] See our [vista branch](https://github.com/jart/cosmopolitan/tree/vista)
|
||||
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 -*-│
|
||||
│ 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"
|
||||
|
||||
ENTRY(_start)
|
||||
|
@ -12,7 +11,7 @@ OUTPUT_FORMAT("elf64-littleaarch64",
|
|||
|
||||
SECTIONS {
|
||||
|
||||
. = SEGMENT_START("text-segment", 0x000800000000);
|
||||
. = SEGMENT_START("text-segment", 0x010000000000);
|
||||
__executable_start = .;
|
||||
. += SIZEOF_HEADERS;
|
||||
|
||||
|
@ -90,12 +89,10 @@ SECTIONS {
|
|||
*(.ubsan.data)
|
||||
}
|
||||
|
||||
.notice : {
|
||||
__notices = .;
|
||||
KEEP(*(.notice))
|
||||
.comment : {
|
||||
__comment_start = .;
|
||||
KEEP(*(.comment))
|
||||
BYTE(0);
|
||||
BYTE(10);
|
||||
BYTE(10);
|
||||
}
|
||||
|
||||
.eh_frame_hdr : {
|
||||
|
@ -103,8 +100,10 @@ SECTIONS {
|
|||
*(.eh_frame_entry .eh_frame_entry.*)
|
||||
}
|
||||
|
||||
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
|
||||
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
|
||||
.eh_frame : ONLY_IF_RO {
|
||||
KEEP(*(.eh_frame))
|
||||
*(.eh_frame.*)
|
||||
}
|
||||
|
||||
.gcc_except_table : ONLY_IF_RO {
|
||||
*(.gcc_except_table .gcc_except_table.*)
|
||||
|
@ -125,11 +124,9 @@ SECTIONS {
|
|||
. += CONSTANT(MAXPAGESIZE);
|
||||
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
||||
|
||||
.eh_frame : {
|
||||
__eh_frame_start = .;
|
||||
.eh_frame : ONLY_IF_RW {
|
||||
KEEP(*(.eh_frame))
|
||||
*(.eh_frame.*)
|
||||
__eh_frame_end = .;
|
||||
}
|
||||
|
||||
.gnu_extab : ONLY_IF_RW {
|
||||
|
@ -160,11 +157,8 @@ SECTIONS {
|
|||
|
||||
.init_array : {
|
||||
__init_array_start = .;
|
||||
KEEP(*(.preinit_array))
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP(*(.init_array))
|
||||
KEEP(*(.ctors))
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||
__init_array_end = .;
|
||||
}
|
||||
|
||||
|
@ -259,9 +253,6 @@ SECTIONS {
|
|||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.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)) }
|
||||
.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_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;
|
||||
_tdata_size = _tdata_end - _tdata_start;
|
||||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tdata_align = ALIGNOF(.tdata);
|
||||
_tbss_align = ALIGNOF(.tbss);
|
||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
||||
_tls_align = 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 -*-│
|
||||
│ 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 │
|
||||
│ │
|
||||
|
@ -33,11 +33,12 @@
|
|||
│ αcτµαlly pδrταblε εxεcµταblε § program header │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "ape/macros.internal.h"
|
||||
#include "ape/notice.inc"
|
||||
#include "ape/relocations.h"
|
||||
#include "libc/calls/metalfile.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/macho.h"
|
||||
#include "libc/macho.internal.h"
|
||||
#include "libc/nexgen32e/uart.internal.h"
|
||||
#include "libc/nt/pedef.internal.h"
|
||||
#include "libc/runtime/pc.internal.h"
|
||||
|
@ -196,7 +197,7 @@ ape_mz:
|
|||
.quad ape_elf_entry // 18: e_entry
|
||||
.quad ape_elf_phoff // 20: e_phoff
|
||||
.quad ape_elf_shoff // 28: e_shoff
|
||||
.long 0x101ca75 // 30: ape e_flags
|
||||
.long 0 // 30: e_flags
|
||||
.short 64 // 34: e_ehsize
|
||||
.short 56 // 36: e_phentsize
|
||||
.short ape_elf_phnum // 38: e_phnum
|
||||
|
@ -591,7 +592,7 @@ ape_disk:
|
|||
|
||||
#ifdef APE_IS_SHELL_SCRIPT
|
||||
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"
|
||||
// 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_phoff,8 // 20: e_phoff
|
||||
.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 "\\070\\0" // 36: e_phentsize
|
||||
.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 */
|
||||
.ascii "exit $?\n"
|
||||
.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
|
||||
|
||||
// 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
|
||||
.section .ape.loader,"a",@progbits
|
||||
.balign 64
|
||||
|
@ -720,8 +748,6 @@ ape_loader_end:
|
|||
#if SupportsSystemv() || SupportsMetal()
|
||||
.section .elf.phdrs,"a",@progbits
|
||||
|
||||
.globl ape_phdrs
|
||||
ape_phdrs:
|
||||
.long PT_LOAD
|
||||
.long PF_R|PF_X
|
||||
.stub ape_cod_offset,quad
|
||||
|
@ -761,7 +787,7 @@ ape_phdrs:
|
|||
.quad 0
|
||||
.quad 0
|
||||
.quad 0
|
||||
.quad 16
|
||||
.stub ape_stack_align,quad
|
||||
|
||||
#if SupportsOpenbsd() || SupportsNetbsd()
|
||||
.long PT_NOTE
|
||||
|
@ -1036,7 +1062,7 @@ ape_pe: .ascin "PE",4
|
|||
.quad ape_pe_base // ImageBase
|
||||
.long ape_pe_sectionalignment // SectionAlignment
|
||||
.long ape_pe_filealignment // FileAlignment
|
||||
.short 10 // MajorOperatingSystemVersion
|
||||
.short v_ntversion // MajorOperatingSystemVersion
|
||||
.short 0 // MinorOperatingSystemVersion
|
||||
.short 0 // MajorImageVersion
|
||||
.short 0 // MinorImageVersion
|
||||
|
@ -1771,31 +1797,49 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
|||
.type ape_text_nops,@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
|
||||
.type ape_pad_head,@object
|
||||
.hidden ape_pad_head
|
||||
ape_pad_head:
|
||||
.previous
|
||||
|
||||
.section .ape.pad.text,"a",@progbits
|
||||
.type ape_pad_text,@object
|
||||
.hidden ape_pad_text
|
||||
ape_pad_text:
|
||||
.previous
|
||||
|
||||
.section .ape.pad.privileged,"a",@progbits
|
||||
.type ape_pad_privileged,@object
|
||||
.hidden ape_pad_privileged
|
||||
ape_pad_privileged:
|
||||
.previous
|
||||
|
||||
.section .ape.pad.data,"a",@progbits
|
||||
.type ape_pad_data,@object
|
||||
.hidden ape_pad_data
|
||||
ape_pad_data:
|
||||
.previous
|
||||
|
||||
#if SupportsWindows()
|
||||
.section .idata.ro,"a",@progbits
|
||||
.type ape_idata_ro,@object
|
||||
.hidden ape_idata_ro
|
||||
ape_idata_ro:
|
||||
.previous
|
||||
#endif /* SupportsWindows() */
|
||||
|
||||
.section .dataprologue,"aw",@progbits
|
||||
|
@ -1803,45 +1847,32 @@ ape_idata_ro:
|
|||
.globl __data_start
|
||||
.hidden __data_start
|
||||
__data_start:
|
||||
.previous
|
||||
|
||||
.section .dataepilogue,"aw",@progbits
|
||||
.type __data_end,@object
|
||||
.globl __data_end
|
||||
.hidden __data_end
|
||||
__data_end:
|
||||
.previous
|
||||
|
||||
.section .bssprologue,"aw",@nobits
|
||||
.type __bss_start,@object
|
||||
.globl __bss_start
|
||||
.hidden __bss_start
|
||||
__bss_start:
|
||||
.previous
|
||||
|
||||
.section .bssepilogue,"aw",@nobits
|
||||
.type __bss_end,@object
|
||||
.globl __bss_end
|
||||
.hidden __bss_end
|
||||
__bss_end:
|
||||
.previous
|
||||
|
||||
.section .fstls,"awT",@nobits
|
||||
.align TLS_ALIGNMENT
|
||||
|
||||
.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."
|
||||
.previous
|
||||
|
||||
.end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#define COSMOPOLITAN_APE_APE_H_
|
||||
|
||||
#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_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 -*-│
|
||||
│ 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 │
|
||||
│ │
|
||||
|
@ -229,6 +229,7 @@ SECTIONS {
|
|||
|
||||
/* Real Mode */
|
||||
KEEP(*(.head))
|
||||
KEEP(*(.apesh))
|
||||
KEEP(*(.text.head))
|
||||
|
||||
/* Executable & Linkable Format */
|
||||
|
@ -237,6 +238,10 @@ SECTIONS {
|
|||
KEEP(*(.elf.phdrs))
|
||||
ape_phdrs_end = .;
|
||||
|
||||
KEEP(*(.emushprologue))
|
||||
KEEP(*(.emush))
|
||||
KEEP(*(.emushepilogue))
|
||||
|
||||
/* OpenBSD */
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
ape_note = .;
|
||||
|
@ -282,9 +287,12 @@ SECTIONS {
|
|||
KEEP(*(SORT_BY_NAME(.init.*)))
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.initepilogue))
|
||||
KEEP(*(.pltprologue))
|
||||
*(.plt)
|
||||
KEEP(*(.pltepilogue))
|
||||
KEEP(*(.pltgotprologue))
|
||||
*(.plt.got)
|
||||
*(.iplt)
|
||||
KEEP(*(.pltgotepilogue))
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
|
@ -293,6 +301,7 @@ SECTIONS {
|
|||
KEEP(*(.textwindowsprologue))
|
||||
*(.text.windows)
|
||||
KEEP(*(.textwindowsepilogue))
|
||||
KEEP(*(.blink))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity))
|
||||
*(SORT_BY_ALIGNMENT(.text.modernity.*))
|
||||
*(SORT_BY_ALIGNMENT(.text.hot))
|
||||
|
@ -310,7 +319,7 @@ SECTIONS {
|
|||
. = ALIGN(__privileged_end > __privileged_start ? CONSTANT(COMMONPAGESIZE) : 0);
|
||||
/*END: morphable code */
|
||||
__privileged_start = .;
|
||||
*(.privileged .privileged.*)
|
||||
*(.privileged)
|
||||
__privileged_end = .;
|
||||
|
||||
KEEP(*(.ape.pad.text))
|
||||
|
@ -320,7 +329,7 @@ SECTIONS {
|
|||
|
||||
/*BEGIN: Read Only Data */
|
||||
|
||||
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
||||
.rodata . : {
|
||||
KEEP(*(.rodata.pytab.0));
|
||||
KEEP(*(.rodata.pytab.1));
|
||||
KEEP(*(.rodata.pytab.2));
|
||||
|
@ -329,16 +338,12 @@ SECTIONS {
|
|||
*(.ubsan.types)
|
||||
*(.ubsan.data)
|
||||
|
||||
__eh_frame_hdr_start_actual = .;
|
||||
*(.eh_frame_hdr)
|
||||
__eh_frame_hdr_end_actual = .;
|
||||
|
||||
/* Legal Notices */
|
||||
__notices = .;
|
||||
KEEP(*(.notice))
|
||||
BYTE(0);
|
||||
BYTE(10);
|
||||
BYTE(10);
|
||||
#if !defined(IM_FEELING_NAUGHTY) || defined(EMBED_NOTICES)
|
||||
KEEP(*(.commentprologue))
|
||||
KEEP(*(.comment))
|
||||
KEEP(*(.commentepilogue))
|
||||
#endif
|
||||
|
||||
/*BEGIN: read-only data that's only needed for initialization */
|
||||
|
||||
|
@ -386,13 +391,6 @@ SECTIONS {
|
|||
_tbss_end = .;
|
||||
} :Tls
|
||||
|
||||
.eh_frame : {
|
||||
__eh_frame_start = .;
|
||||
KEEP(*(.eh_frame))
|
||||
*(.eh_frame.*)
|
||||
__eh_frame_end = .;
|
||||
} :Ram
|
||||
|
||||
.data . : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
#if SupportsWindows()
|
||||
|
@ -401,28 +399,26 @@ SECTIONS {
|
|||
/*BEGIN: NT FORK COPYING */
|
||||
KEEP(*(.dataprologue))
|
||||
*(.data .data.*)
|
||||
*(.gnu_extab)
|
||||
*(.gcc_except_table .gcc_except_table.*)
|
||||
*(.exception_ranges*)
|
||||
*(.PyRuntime) /* for python */
|
||||
*(.subrs) /* for emacs */
|
||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||
. += . > 0 ? CODE_GRANULE : 0;
|
||||
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
__got_start = .;
|
||||
KEEP(*(.gotprologue))
|
||||
*(.got)
|
||||
__got_end = .;
|
||||
KEEP(*(.gotepilogue))
|
||||
|
||||
KEEP(*(.gotpltprologue))
|
||||
*(.got.plt)
|
||||
KEEP(*(.gotpltepilogue))
|
||||
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
__init_array_start = .;
|
||||
KEEP(*(.preinit_array))
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP(*(.init_array))
|
||||
KEEP(*(.ctors))
|
||||
KEEP(*(.init_array))
|
||||
KEEP(*(.preinit_array))
|
||||
__init_array_end = .;
|
||||
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
|
@ -439,7 +435,6 @@ SECTIONS {
|
|||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
KEEP(*(.piro.pad.data))
|
||||
*(.igot.plt)
|
||||
KEEP(*(.dataepilogue))
|
||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
||||
/*END: NT FORK COPYING */
|
||||
|
@ -520,9 +515,6 @@ SECTIONS {
|
|||
.debug_rnglists 0 : { *(.debug_rnglists) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.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)) }
|
||||
.GCC.command.line 0 : { *(.GCC.command.line) }
|
||||
|
||||
|
@ -541,9 +533,7 @@ SECTIONS {
|
|||
*(.piro.data.sort.iat.*)
|
||||
#endif
|
||||
*(__patchable_function_entries)
|
||||
*(.note.gnu.property)
|
||||
*(__mcount_loc)
|
||||
*(.rela.dyn)
|
||||
*(.discard)
|
||||
*(.yoink)
|
||||
}
|
||||
|
@ -566,9 +556,7 @@ _tdata_size = _tdata_end - _tdata_start;
|
|||
_tbss_size = _tbss_end - _tbss_start;
|
||||
_tbss_offset = _tbss_start - _tdata_start;
|
||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||
_tdata_align = ALIGNOF(.tdata);
|
||||
_tbss_align = ALIGNOF(.tbss);
|
||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
||||
_tls_align = 1;
|
||||
|
||||
ape_cod_offset = 0;
|
||||
ape_cod_vaddr = ADDR(.head);
|
||||
|
@ -586,11 +574,11 @@ ape_rom_memsz = ape_rom_filesz;
|
|||
ape_rom_align = CONSTANT(COMMONPAGESIZE);
|
||||
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_paddr = LOADADDR(.eh_frame);
|
||||
ape_ram_filesz = ADDR(.bss) - ADDR(.eh_frame);
|
||||
ape_ram_memsz = _end - ADDR(.eh_frame);
|
||||
ape_ram_paddr = LOADADDR(.data);
|
||||
ape_ram_filesz = ADDR(.bss) - ADDR(.data);
|
||||
ape_ram_memsz = _end - ADDR(.data);
|
||||
ape_ram_align = CONSTANT(COMMONPAGESIZE);
|
||||
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_paddr = ape_ram_paddr + ape_ram_filesz;
|
||||
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_filesz = ape_note_end - ape_note;
|
||||
|
@ -614,9 +604,6 @@ ape_text_memsz = ape_text_filesz;
|
|||
ape_text_align = CONSTANT(COMMONPAGESIZE);
|
||||
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 */
|
||||
/* 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 */
|
||||
|
@ -626,6 +613,29 @@ SHSTUB2(ape_loader_dd_count,
|
|||
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
|
||||
: 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()
|
||||
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 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 = LINK_WINDOWS ? RVA(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_ntsubversion = LINK_WINDOWS ? 6 : 5;
|
||||
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 -*-│
|
||||
│ 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 │
|
||||
│ │
|
||||
|
|
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 -*-│
|
||||
│ 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 │
|
||||
│ │
|
||||
|
@ -16,7 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// Calls _start() function of loaded program.
|
||||
//
|
||||
|
@ -31,16 +31,17 @@
|
|||
//
|
||||
// @param rdi is passed through as-is
|
||||
// @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 r8 is stack pointer (becomes zero)
|
||||
// @noreturn
|
||||
Launch:
|
||||
#ifdef __aarch64__
|
||||
|
||||
mov x16,x1
|
||||
mov sp,x4
|
||||
mov sp,x2
|
||||
mov x1,0
|
||||
mov x2,0
|
||||
mov x3,0
|
||||
mov x4,0
|
||||
mov x5,0
|
||||
mov x6,0
|
||||
|
@ -70,7 +71,6 @@ Launch:
|
|||
|
||||
#else
|
||||
|
||||
mov %r8,%rsp
|
||||
xor %r8d,%r8d
|
||||
xor %r9d,%r9d
|
||||
xor %r10d,%r10d
|
||||
|
@ -79,6 +79,8 @@ Launch:
|
|||
xor %r13d,%r13d
|
||||
xor %r14d,%r14d
|
||||
xor %r15d,%r15d
|
||||
mov %rdx,%rsp
|
||||
xor %edx,%edx
|
||||
push %rsi
|
||||
xor %esi,%esi
|
||||
xor %ebp,%ebp
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
|
@ -16,13 +16,13 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macho.h"
|
||||
#include "libc/macho.internal.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// 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
|
||||
|
||||
.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 -*-│
|
||||
│ 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 │
|
||||
│ │
|
||||
|
@ -87,8 +87,6 @@
|
|||
#define MIN(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 SupportsXnu() (SUPPORT_VECTOR & XNU)
|
||||
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
|
||||
|
@ -113,47 +111,41 @@
|
|||
#define EXTERN_C
|
||||
#endif
|
||||
|
||||
#define O_RDONLY 0
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_FIXED 16
|
||||
#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096)
|
||||
#define MAP_NORESERVE (IsLinux() ? 16384 : 0)
|
||||
#define ELFCLASS32 1
|
||||
#define ELFDATA2LSB 1
|
||||
#define EM_NEXGEN32E 62
|
||||
#define EM_AARCH64 183
|
||||
#define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define PF_X 1
|
||||
#define PF_W 2
|
||||
#define PF_R 4
|
||||
#define AT_PHDR 3
|
||||
#define AT_PHENT 4
|
||||
#define AT_PHNUM 5
|
||||
#define AT_PAGESZ 6
|
||||
#define AT_FLAGS 8
|
||||
#define AT_FLAGS_PRESERVE_ARGV0_BIT 0
|
||||
#define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
|
||||
#define AT_EXECFN_LINUX 31
|
||||
#define AT_EXECFN_NETBSD 2014
|
||||
#define X_OK 1
|
||||
#define XCR0_SSE 2
|
||||
#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 O_RDONLY 0
|
||||
#define PROT_NONE 0
|
||||
#define PROT_READ 1
|
||||
#define PROT_WRITE 2
|
||||
#define PROT_EXEC 4
|
||||
#define MAP_SHARED 1
|
||||
#define MAP_PRIVATE 2
|
||||
#define MAP_FIXED 16
|
||||
#define MAP_ANONYMOUS (IsLinux() ? 32 : 4096)
|
||||
#define MAP_NORESERVE (IsLinux() ? 16384 : 0)
|
||||
#define ELFCLASS32 1
|
||||
#define ELFDATA2LSB 1
|
||||
#define EM_NEXGEN32E 62
|
||||
#define EM_AARCH64 183
|
||||
#define ET_EXEC 2
|
||||
#define ET_DYN 3
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define PF_X 1
|
||||
#define PF_W 2
|
||||
#define PF_R 4
|
||||
#define AT_PHDR 3
|
||||
#define AT_PHENT 4
|
||||
#define AT_PHNUM 5
|
||||
#define AT_PAGESZ 6
|
||||
#define AT_EXECFN_LINUX 31
|
||||
#define AT_EXECFN_NETBSD 2014
|
||||
#define X_OK 1
|
||||
#define XCR0_SSE 2
|
||||
#define XCR0_AVX 4
|
||||
#define PR_SET_MM 35
|
||||
#define PR_SET_MM_EXE_FILE 13
|
||||
|
||||
#define READ32(S) \
|
||||
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
||||
|
@ -169,6 +161,13 @@
|
|||
(unsigned long)(255 & (S)[1]) << 010 | \
|
||||
(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 {
|
||||
unsigned char e_ident[16];
|
||||
unsigned short e_type;
|
||||
|
@ -213,43 +212,39 @@ struct PathSearcher {
|
|||
const char *name;
|
||||
const char *syspath;
|
||||
unsigned long namelen;
|
||||
char path[PATH_MAX];
|
||||
char path[1024];
|
||||
};
|
||||
|
||||
struct ApeLoader {
|
||||
union ElfPhdrBuf phdr;
|
||||
struct PathSearcher ps;
|
||||
char path[PATH_MAX];
|
||||
char path[1024];
|
||||
};
|
||||
|
||||
EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
|
||||
EXTERN_C void Launch(void *, long, void *, int, void *)
|
||||
__attribute__((__noreturn__));
|
||||
EXTERN_C void Launch(void *, long, void *, int) __attribute__((__noreturn__));
|
||||
|
||||
extern char __executable_start[];
|
||||
extern char _end[];
|
||||
|
||||
static unsigned long StrLen(const char *s) {
|
||||
unsigned long n = 0;
|
||||
while (*s++)
|
||||
++n;
|
||||
while (*s++) ++n;
|
||||
return n;
|
||||
}
|
||||
|
||||
static int StrCmp(const char *l, const char *r) {
|
||||
unsigned long i = 0;
|
||||
while (l[i] == r[i] && r[i])
|
||||
++i;
|
||||
while (l[i] == r[i] && r[i]) ++i;
|
||||
return (l[i] & 255) - (r[i] & 255);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
static const char *StrRChr(const char *s, int c) {
|
||||
const char *b = 0;
|
||||
static const char *BaseName(const char *s) {
|
||||
int c;
|
||||
const char *b = "";
|
||||
if (s) {
|
||||
for (; *s; ++s) {
|
||||
if (*s == c) {
|
||||
while ((c = *s++)) {
|
||||
if (c == '/') {
|
||||
b = s;
|
||||
}
|
||||
}
|
||||
|
@ -257,13 +252,6 @@ static const char *StrRChr(const char *s, int c) {
|
|||
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) {
|
||||
long z;
|
||||
char *p, *e;
|
||||
|
@ -338,7 +326,24 @@ static char *GetEnv(char **p, const char *s) {
|
|||
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;
|
||||
unsigned long i, a, b;
|
||||
i = 0;
|
||||
|
@ -358,8 +363,7 @@ static char *Utoa(char p[20], unsigned long x) {
|
|||
}
|
||||
|
||||
static char *Itoa(char p[21], long x) {
|
||||
if (x < 0)
|
||||
*p++ = '-', x = -(unsigned long)x;
|
||||
if (x < 0) *p++ = '-', x = -(unsigned long)x;
|
||||
return Utoa(p, x);
|
||||
}
|
||||
|
||||
|
@ -368,8 +372,7 @@ __attribute__((__noinline__)) static long CallSystem(long arg1, long arg2,
|
|||
long arg5, long arg6,
|
||||
long arg7, int numba,
|
||||
char os) {
|
||||
if (IsXnu())
|
||||
numba |= 0x2000000;
|
||||
if (IsXnu()) numba |= 0x2000000;
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
char ibuf[21];
|
||||
ibuf[0] = 0;
|
||||
if (rc)
|
||||
Itoa(ibuf, -rc);
|
||||
if (rc) Itoa(ibuf, -rc);
|
||||
Print(os, 2, "ape error: ", thing, ": ", reason,
|
||||
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) {
|
||||
if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path))
|
||||
return 0;
|
||||
if (pathlen && ps->path[pathlen - 1] != '/')
|
||||
ps->path[pathlen++] = '/';
|
||||
if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path)) return 0;
|
||||
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
||||
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
||||
ps->path[pathlen + ps->namelen] = 0;
|
||||
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) {
|
||||
if (!(ps->namelen = StrLen((ps->name = name))))
|
||||
return 0;
|
||||
if (ps->literally || MemChr(ps->name, '/', ps->namelen))
|
||||
return name;
|
||||
ps->os = os;
|
||||
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
|
||||
if (ps->namelen + 1 > sizeof(ps->path))
|
||||
return 0;
|
||||
ps->path[0] = 0;
|
||||
if (SearchPath(ps)) {
|
||||
if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
|
||||
if (ps->namelen + 1 > sizeof(ps->path)) return 0;
|
||||
if (FindCommand(ps)) {
|
||||
return ps->path;
|
||||
} else {
|
||||
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,
|
||||
struct ElfEhdr *e,
|
||||
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");
|
||||
}
|
||||
for (j = i + 1; j < e->e_phnum; ++j) {
|
||||
if (p[j].p_type != PT_LOAD)
|
||||
continue;
|
||||
if (p[j].p_type != PT_LOAD) continue;
|
||||
c = p[j].p_vaddr & -pagesz;
|
||||
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
|
||||
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) {
|
||||
rc = Mmap(0, virtmax - virtmin, PROT_NONE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0, os);
|
||||
if (rc < 0)
|
||||
Pexit(os, exe, rc, "pie mmap");
|
||||
if (rc < 0) Pexit(os, exe, rc, "pie mmap");
|
||||
dynbase = rc;
|
||||
if (dynbase & (pagesz - 1)) {
|
||||
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) {
|
||||
void *addr;
|
||||
unsigned long size;
|
||||
if (p[i].p_type != PT_LOAD)
|
||||
continue;
|
||||
if (p[i].p_type != PT_LOAD) continue;
|
||||
|
||||
/* configure mapping */
|
||||
prot = 0;
|
||||
flags = MAP_FIXED | MAP_PRIVATE;
|
||||
if (p[i].p_flags & PF_R)
|
||||
prot |= PROT_READ;
|
||||
if (p[i].p_flags & PF_W)
|
||||
prot |= PROT_WRITE;
|
||||
if (p[i].p_flags & PF_X)
|
||||
prot |= PROT_EXEC;
|
||||
if (p[i].p_flags & PF_R) prot |= PROT_READ;
|
||||
if (p[i].p_flags & PF_W) prot |= PROT_WRITE;
|
||||
if (p[i].p_flags & PF_X) prot |= PROT_EXEC;
|
||||
|
||||
if (p[i].p_filesz) {
|
||||
/* 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));
|
||||
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz;
|
||||
rc = Mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz, os);
|
||||
if (rc < 0)
|
||||
Pexit(os, exe, rc, "prog mmap");
|
||||
if (wipe)
|
||||
Bzero((void *)(dynbase + a), wipe);
|
||||
if (rc < 0) Pexit(os, exe, rc, "prog mmap");
|
||||
if (wipe) Bzero((void *)(dynbase + a), wipe);
|
||||
if (prot2 != prot1) {
|
||||
rc = Mprotect(addr, size, prot2, os);
|
||||
if (rc < 0)
|
||||
Pexit(os, exe, rc, "prog mprotect");
|
||||
if (rc < 0) Pexit(os, exe, rc, "prog mprotect");
|
||||
}
|
||||
/* allocate extra bss */
|
||||
if (c > b) {
|
||||
flags |= MAP_ANONYMOUS;
|
||||
rc = Mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0, os);
|
||||
if (rc < 0)
|
||||
Pexit(os, exe, rc, "extra bss mmap");
|
||||
if (rc < 0) Pexit(os, exe, rc, "extra bss mmap");
|
||||
}
|
||||
} else {
|
||||
/* 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;
|
||||
flags |= MAP_ANONYMOUS;
|
||||
rc = Mmap(addr, size, prot, flags, -1, 0, os);
|
||||
if (rc < 0)
|
||||
Pexit(os, exe, rc, "bss mmap");
|
||||
if (rc < 0) 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);
|
||||
|
||||
/* 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,
|
||||
char *exe, int fd, long *sp, long *auxv,
|
||||
const char *exe, int fd, long *sp, long *auxv,
|
||||
unsigned long pagesz, int os) {
|
||||
long i, rc;
|
||||
unsigned size;
|
||||
|
@ -811,8 +769,7 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
|||
struct ElfPhdr *p;
|
||||
|
||||
/* validate page size */
|
||||
if (!pagesz)
|
||||
pagesz = 4096;
|
||||
if (!pagesz) pagesz = 4096;
|
||||
if (pagesz & (pagesz - 1)) {
|
||||
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";
|
||||
}
|
||||
#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)) {
|
||||
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 */
|
||||
rc = Pread(fd, M->phdr.buf, size, e->e_phoff, os);
|
||||
if (rc < 0)
|
||||
return "failed to read ELF program headers";
|
||||
if (rc != size)
|
||||
return "truncated read of ELF program headers";
|
||||
if (rc < 0) return "failed to read ELF program headers";
|
||||
if (rc != size) return "truncated read of ELF program headers";
|
||||
|
||||
/* bail on recoverable program header errors */
|
||||
p = &M->phdr.phdr;
|
||||
|
@ -934,13 +885,18 @@ __attribute__((__noreturn__)) static void ShowUsage(int os, int fd, int rc) {
|
|||
"NAME\n"
|
||||
"\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"
|
||||
"\n"
|
||||
"USAGE\n"
|
||||
"\n"
|
||||
" ape PROG [ARGV1,ARGV2,...]\n"
|
||||
" ape - PROG [ARGV0,ARGV1,...]\n"
|
||||
" ape [FLAGS] PROG [ARGV1,ARGV2,...]\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",
|
||||
0l);
|
||||
Exit(rc, os);
|
||||
|
@ -950,16 +906,16 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
|||
char dl) {
|
||||
int rc, n;
|
||||
unsigned i;
|
||||
char literally;
|
||||
const char *ape;
|
||||
int c, fd, os, argc;
|
||||
struct ApeLoader *M;
|
||||
char arg0, literally;
|
||||
unsigned long pagesz;
|
||||
union ElfEhdrBuf *ebuf;
|
||||
long *auxv, *ap, *endp, *sp2;
|
||||
char *p, *pe, *exe, *prog, **argv, **envp;
|
||||
|
||||
(void)Printf;
|
||||
(void)Utox;
|
||||
|
||||
/* detect freebsd */
|
||||
if (SupportsXnu() && dl == XNU) {
|
||||
|
@ -984,30 +940,20 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
|||
|
||||
/* determine ape loader program name */
|
||||
ape = argv[0];
|
||||
if (!ape)
|
||||
ape = "ape";
|
||||
if (!ape) ape = "ape";
|
||||
|
||||
/* detect openbsd */
|
||||
if (SupportsOpenbsd() && !os && !auxv[0]) {
|
||||
os = OPENBSD;
|
||||
}
|
||||
|
||||
/* xnu passes auxv as an array of strings */
|
||||
if (os == XNU) {
|
||||
*auxv = 0;
|
||||
}
|
||||
|
||||
/* detect netbsd and find end of words */
|
||||
pagesz = 0;
|
||||
arg0 = 0;
|
||||
for (ap = auxv; ap[0]; ap += 2) {
|
||||
if (ap[0] == AT_PAGESZ) {
|
||||
pagesz = ap[1];
|
||||
} else if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_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) {
|
||||
|
@ -1020,13 +966,22 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
|||
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 */
|
||||
if (arg0) {
|
||||
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 ((literally = argc >= 3 && !StrCmp(argv[1], "-"))) {
|
||||
/* if the first argument is a hyphen then we give the user the
|
||||
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
|
||||
|
@ -1035,13 +990,9 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
|||
argc = sp[3] = sp[0] - 3;
|
||||
argv = (char **)((sp += 3) + 1);
|
||||
} 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 {
|
||||
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];
|
||||
argc = sp[1] = sp[0] - 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 */
|
||||
n = (endp - sp + 1) * sizeof(long);
|
||||
sp2 = (long *)__builtin_alloca(n);
|
||||
if ((long)sp2 & 15)
|
||||
++sp2;
|
||||
if ((long)sp2 & 15) ++sp2;
|
||||
for (; n > 0; n -= pagesz) {
|
||||
((char *)sp2)[n - 1] = 0;
|
||||
}
|
||||
|
@ -1087,6 +1037,12 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
|||
}
|
||||
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
|
||||
1. if ape, will scan shell script for elf printf statements
|
||||
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 -*-│
|
||||
│ 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 │
|
||||
│ │
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
|
@ -18,10 +18,123 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#ifndef APE_MACROS_H_
|
||||
#define APE_MACROS_H_
|
||||
#include "libc/macros.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#ifdef __ASSEMBLER__
|
||||
/* 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.
|
||||
// The most holiest of holy code.
|
||||
// @mode real
|
||||
|
@ -84,10 +197,9 @@
|
|||
/* clang-format on */
|
||||
#elif defined(__LINKER__)
|
||||
|
||||
#define BCX_NIBBLE(X) \
|
||||
((((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_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||
#define BCX_NIBBLE(X) ((((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_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||
#define BCXSTUB(SYM, X) \
|
||||
HIDDEN(SYM##_bcx0 = BCX_INT16((X) >> 48)); \
|
||||
HIDDEN(SYM##_bcx1 = BCX_INT16((X) >> 32)); \
|
||||
|
@ -99,12 +211,12 @@
|
|||
*
|
||||
* <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) \
|
||||
((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) \
|
||||
HIDDEN(SYM = (X)); \
|
||||
PFBYTE(SYM, X, 0); \
|
||||
|
@ -141,16 +253,23 @@
|
|||
: (X) < 10000000 ? BCD_RIGHT(BCD_SMEAR((X) / 1000)) \
|
||||
: (X) < 100000000 ? BCD_RIGHT(BCD_SMEAR((X) / 10000)) \
|
||||
: 0xffffffffffffffff)
|
||||
#define BCD_RIGHT(X) \
|
||||
(((X)) < 10000 ? 0x20202020 \
|
||||
: (X) < 100000 ? 0x20202030 + (X) % 10 \
|
||||
: (X) < 1000000 ? 0x20203030 + ((X) / 10) % 10 + (X) % 10 * 0x100 \
|
||||
: (X) < 10000000 ? 0x20303030 + ((X) / 100) % 10 + \
|
||||
((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)
|
||||
#define BCD_RIGHT(X) \
|
||||
(((X)) < 10000 ? 0x20202020 \
|
||||
: (X) < 100000 ? 0x20202030 + \
|
||||
(X) % 10 \
|
||||
: (X) < 1000000 ? 0x20203030 + \
|
||||
((X) / 10) % 10 + \
|
||||
(X) % 10 * 0x100 \
|
||||
: (X) < 10000000 ? 0x20303030 + \
|
||||
((X) / 100) % 10 + \
|
||||
((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.
|
||||
|
@ -159,11 +278,15 @@
|
|||
HIDDEN(SYM##_desc_ent0 = TSSDESC_ENT0(BASE, LIM)); \
|
||||
HIDDEN(SYM##_desc_ent1 = TSSDESC_ENT1(BASE)); \
|
||||
ASSERT((LIM) >= 0 && (LIM) <= 0xffff, "bare metal TSS is suspiciously fat")
|
||||
#define TSSDESC_ENT0(BASE, LIM) \
|
||||
(((LIM) << 0 & 0x000000000000ffff) | ((BASE) << 16 & 0x000000ffffff0000) | \
|
||||
0x89 << 40 | ((LIM) >> 16 << 48 & 0x000f000000000000) | 0x2 << 52 | \
|
||||
#define TSSDESC_ENT0(BASE, LIM) \
|
||||
(((LIM) << 0 & 0x000000000000ffff) | \
|
||||
((BASE) << 16 & 0x000000ffffff0000) | \
|
||||
0x89 << 40 | \
|
||||
((LIM) >> 16 << 48 & 0x000f000000000000) | \
|
||||
0x2 << 52 | \
|
||||
((BASE) >> 24 << 56 & 0xff00000000000000))
|
||||
#define TSSDESC_ENT1(BASE) ((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
||||
#define TSSDESC_ENT1(BASE) \
|
||||
((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* APE_MACROS_H_ */
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
#ifndef COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
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 __privileged_start[] __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_end[] __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 __ro[] __attribute__((__weak__));
|
||||
extern unsigned char __data_start[] __attribute__((__weak__));
|
||||
extern unsigned char __data_end[] __attribute__((__weak__));
|
||||
extern unsigned char __bss_start[] __attribute__((__weak__));
|
||||
extern unsigned char __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__));
|
||||
extern uint8_t __data_start[] __attribute__((__weak__));
|
||||
extern uint8_t __data_end[] __attribute__((__weak__));
|
||||
extern uint8_t __bss_start[] __attribute__((__weak__));
|
||||
extern uint8_t __bss_end[] __attribute__((__weak__));
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#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 -*-│
|
||||
│ 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 │
|
||||
│ │
|
||||
|
@ -18,12 +18,11 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "ape/ape.h"
|
||||
#include "libc/macros.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
#ifdef __aarch64__
|
||||
|
||||
_start: mov x1,sp
|
||||
and sp,x1,#-16
|
||||
mov x29,0
|
||||
bl ApeLoader
|
||||
.endfn _start,globl
|
||||
|
@ -34,7 +33,6 @@ XnuEntrypoint:
|
|||
mov $_HOSTXNU,%dl // xnu's not unix!
|
||||
ElfEntrypoint:
|
||||
mov %rsp,%rsi // save real stack
|
||||
andq $-16,%rsp // force SSE alignment
|
||||
call ApeLoader
|
||||
.endfn ElfEntrypoint,globl
|
||||
.endfn XnuEntrypoint,globl
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*-*- 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 │
|
||||
│ │
|
||||
|
@ -16,7 +16,7 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// 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