mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-03 16:30:29 +00:00
Compare commits
No commits in common. "master" and "pledge-1.7" have entirely different histories.
master
...
pledge-1.7
23731 changed files with 521483 additions and 1641459 deletions
|
@ -6,11 +6,8 @@ AlignConsecutiveMacros: true
|
|||
AlignConsecutiveDeclarations: false
|
||||
AlwaysBreakBeforeMultilineStrings: false
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
IncludeBlocks: Merge
|
||||
---
|
||||
Language: Cpp
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
|
|
|
@ -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
|
9
.gitattributes
vendored
9
.gitattributes
vendored
|
@ -1,10 +1,3 @@
|
|||
# -*- 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/**
|
49
.github/workflows/build.yml
vendored
49
.github/workflows/build.yml
vendored
|
@ -1,8 +1,5 @@
|
|||
name: build
|
||||
|
||||
env:
|
||||
COSMOCC_VERSION: 3.9.2
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
|
@ -20,50 +17,12 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
mode: ["", tiny, rel, tinylinux, optlinux]
|
||||
mode: ["", tiny, opt, rel]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
# Full checkout needed for git-restore-mtime-bare.
|
||||
fetch-depth: 0
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
# TODO(jart): fork this action.
|
||||
- uses: chetan/git-restore-mtime-action@v2
|
||||
|
||||
- uses: actions/cache/restore@v4
|
||||
id: cache
|
||||
with:
|
||||
path: |
|
||||
.cosmocc
|
||||
o
|
||||
key: ${{ env.COSMOCC_VERSION }}-${{ matrix.mode }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
${{ env.COSMOCC_VERSION }}-${{ matrix.mode }}-
|
||||
${{ env.COSMOCC_VERSION }}-
|
||||
|
||||
- name: Restore mtimes
|
||||
if: steps.cache.outputs.cache-hit == 'true'
|
||||
run: |
|
||||
while read mtime file; do
|
||||
[ -f "$file" ] && touch -d "@$mtime" "$file"
|
||||
done < o/.mtimes
|
||||
|
||||
- name: support ape bins 1
|
||||
run: sudo cp -a 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: support ape bins
|
||||
run: sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/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
|
5
.gitignore
vendored
5
.gitignore
vendored
|
@ -1,8 +1,6 @@
|
|||
# -*- conf -*-
|
||||
|
||||
/o
|
||||
/cosmocc
|
||||
/.cosmocc
|
||||
|
||||
# TODO: Find some way to have Python write to o/
|
||||
__pycache__
|
||||
|
@ -13,6 +11,3 @@ __pycache__
|
|||
/TAGS
|
||||
/bx_enh_dbg.ini
|
||||
/tool/emacs/*.elc
|
||||
/perf.data
|
||||
/perf.data.old
|
||||
/qemu*core
|
||||
|
|
112
.vscode/c_cpp_properties.json
vendored
Normal file
112
.vscode/c_cpp_properties.json
vendored
Normal file
|
@ -0,0 +1,112 @@
|
|||
{
|
||||
"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=",
|
||||
"dontdiscard=",
|
||||
"mayalias=",
|
||||
"forceinline=",
|
||||
"forcealign(x)=",
|
||||
"scanfesque(x)=",
|
||||
"strftimeesque(x)=",
|
||||
"wontreturn=",
|
||||
"textreal=",
|
||||
"mallocesque=",
|
||||
"callocesque=",
|
||||
"vallocesque=",
|
||||
"reallocesque=",
|
||||
"strlenesque=",
|
||||
"memcpyesque=",
|
||||
"hasatleast=",
|
||||
"noinline=",
|
||||
"textexit=",
|
||||
"returnstwice=",
|
||||
"textwindows=",
|
||||
"privileged=",
|
||||
"compatfn=",
|
||||
"noinstrument=",
|
||||
"nodebuginfo=",
|
||||
"interruptfn=",
|
||||
"optimizespeed=",
|
||||
"forcealignargpointer=",
|
||||
"noasan=",
|
||||
"noubsan=",
|
||||
"testonly=",
|
||||
"donothing=",
|
||||
"nosideeffect=",
|
||||
"unreachable=",
|
||||
"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",
|
||||
"-Wa,--nocompress-debug-sections",
|
||||
"-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=",
|
||||
"IMAGE_BASE_VIRTUAL=0x400000"
|
||||
]
|
||||
}
|
||||
],
|
||||
"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)
|
||||
|
|
743
Makefile
743
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,124 +59,20 @@
|
|||
#
|
||||
# build/config.mk
|
||||
|
||||
SHELL = build/bootstrap/cocmd
|
||||
SHELL = build/bootstrap/cocmd.com
|
||||
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 win10 xnu
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
.SUFFIXES:
|
||||
.DELETE_ON_ERROR:
|
||||
.FEATURES: output-sync
|
||||
.PHONY: all o bins check test depend tags aarch64 clean
|
||||
.PHONY: all o bins check test depend tags
|
||||
|
||||
ifneq ($(m),)
|
||||
ifeq ($(MODE),)
|
||||
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)
|
||||
|
||||
# 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)
|
||||
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)
|
||||
|
||||
# the default build modes is empty string
|
||||
# on x86_64 hosts, MODE= is the same as MODE=x86_64
|
||||
# on aarch64 hosts, MODE= is changed to MODE=aarch64
|
||||
ifeq ($(MODE),)
|
||||
ifeq ($(UNAME_M),arm64)
|
||||
MODE := aarch64
|
||||
endif
|
||||
ifeq ($(UNAME_M),aarch64)
|
||||
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,44 +81,18 @@ 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
|
||||
# we added sandboxing to guarantee cosmo's makefile is hermetic
|
||||
# it also shaves away 200ms of startup latency with native $(uniq)
|
||||
ifneq ($(LANDLOCKMAKE_VERSION),)
|
||||
ifeq ($(UNAME_S),Linux)
|
||||
ifeq ($(wildcard /usr/bin/ape),)
|
||||
$(warning please run ape/apeinstall.sh if you intend to use landlock make)
|
||||
$(shell sleep .5)
|
||||
endif
|
||||
endif
|
||||
ifneq ($(TOOLCHAIN),)
|
||||
.STRICT = 1
|
||||
endif
|
||||
endif
|
||||
|
||||
.PLEDGE += stdio rpath wpath cpath fattr proc
|
||||
.UNVEIL += \
|
||||
libc/integral \
|
||||
libc/stdbool.h \
|
||||
rwc:/dev/shm \
|
||||
rx:.cosmocc \
|
||||
rx:build/bootstrap \
|
||||
r:build/portcosmo.h \
|
||||
/proc/stat \
|
||||
rw:/dev/null \
|
||||
rw:/dev/full \
|
||||
w:o/stack.log \
|
||||
/etc/hosts \
|
||||
~/.runit.psk \
|
||||
/proc/self/status \
|
||||
rx:/usr/bin/qemu-aarch64 \
|
||||
rx:o/third_party/qemu/qemu-aarch64 \
|
||||
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
||||
.PLEDGE = stdio rpath wpath cpath fattr proc
|
||||
.UNVEIL = \
|
||||
libc/integral \
|
||||
libc/disclaimer.inc \
|
||||
rx:build/bootstrap \
|
||||
rx:o/third_party/gcc \
|
||||
/proc/self/status \
|
||||
rw:/dev/null \
|
||||
w:o/stack.log \
|
||||
/etc/hosts \
|
||||
~/.runit.psk
|
||||
|
||||
PKGS =
|
||||
|
||||
|
@ -231,164 +101,131 @@ include build/functions.mk #─┐
|
|||
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 build/online.mk # │
|
||||
include libc/stubs/stubs.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 libc/linux/linux.mk # │ You can manipulate arrays
|
||||
include libc/tinymath/tinymath.mk # │ You can issue raw system calls
|
||||
include third_party/compiler_rt/compiler_rt.mk # │
|
||||
include libc/str/str.mk # │
|
||||
include third_party/xed/xed.mk # │
|
||||
include third_party/zlib/zlib.mk # │
|
||||
include libc/elf/elf.mk # │
|
||||
include ape/ape.mk # │
|
||||
include libc/fmt/fmt.mk #─┘
|
||||
include libc/calls/calls.mk #─┐
|
||||
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
|
||||
include libc/crt/crt.mk # │ You can issue system calls
|
||||
include third_party/dlmalloc/dlmalloc.mk #─┘
|
||||
include libc/mem/mem.mk #─┐
|
||||
include libc/zipos/zipos.mk # ├──DYNAMIC RUNTIME
|
||||
include third_party/gdtoa/gdtoa.mk # │ You can now use stdio
|
||||
include libc/time/time.mk # │ You can finally call malloc()
|
||||
include libc/thread/thread.mk # │
|
||||
include libc/stdio/stdio.mk # │
|
||||
include third_party/libcxx/libcxx.mk # │
|
||||
include net/net.mk # │
|
||||
include libc/log/log.mk # │
|
||||
include third_party/bzip2/bzip2.mk # │
|
||||
include dsp/core/core.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/musl/musl.mk # │
|
||||
include third_party/getopt/getopt.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 net/https/https.mk # │
|
||||
include third_party/regex/regex.mk #─┘
|
||||
include third_party/tidy/tidy.mk
|
||||
include third_party/third_party.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/double-conversion.mk
|
||||
include third_party/lua/lua.mk
|
||||
include third_party/make/make.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/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/emucrt/emucrt.mk
|
||||
include tool/build/emubin/emubin.mk
|
||||
include tool/build/build.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/hash/hash.mk
|
||||
include tool/net/net.mk
|
||||
include tool/viz/viz.mk
|
||||
include tool/tool.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/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))
|
||||
|
@ -407,164 +244,130 @@ tags: TAGS HTAGS
|
|||
o/$(MODE)/.x:
|
||||
@$(COMPILE) -AMKDIR -tT$@ $(MKDIR) $(@D)
|
||||
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x)))) $(SRCS)
|
||||
o/$(MODE)/srcs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||
$(file >$@,$(SRCS))
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x)))) $(HDRS) $(INCS)
|
||||
o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(file >$@,$(HDRS) $(INCS))
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x)))) $(INCS) $(INCS)
|
||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x))))
|
||||
$(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)))
|
||||
o/$(MODE)/hdrs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(INCS),$(dir $(x))))
|
||||
$(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: .UNSANDBOXED = 1
|
||||
TAGS: o/$(MODE)/srcs-old.txt $(SRCS)
|
||||
@$(RM) $@
|
||||
@o/$(MODE)/third_party/ctags/ctags $(TAGSFLAGS) -L $< -o $@
|
||||
@$(TAGS) $(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: .UNSANDBOXED = 1
|
||||
HTAGS: o/$(MODE)/hdrs-old.txt $(HDRS)
|
||||
@$(RM) $@
|
||||
@build/htags o/$(MODE)/third_party/ctags/ctags -L $< -o $@
|
||||
@build/htags -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: .UNSANDBOXED = 1
|
||||
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 \
|
||||
TOOL_ARGS \
|
||||
COSMOPOLITAN_OBJECTS = \
|
||||
NET_HTTP \
|
||||
LIBC_DNS \
|
||||
LIBC_SOCK \
|
||||
LIBC_NT_WS2_32 \
|
||||
LIBC_NT_IPHLPAPI \
|
||||
LIBC_NT_MSWSOCK \
|
||||
LIBC_X \
|
||||
THIRD_PARTY_GETOPT \
|
||||
LIBC_LOG \
|
||||
LIBC_TIME \
|
||||
LIBC_ZIPOS \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_MUSL \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_REGEX \
|
||||
LIBC_MEM \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_ELF \
|
||||
LIBC_CALLS \
|
||||
LIBC_SYSV_CALLS \
|
||||
LIBC_NT_PSAPI \
|
||||
LIBC_NT_POWRPROF \
|
||||
LIBC_NT_PDH \
|
||||
LIBC_NT_GDI32 \
|
||||
LIBC_NT_COMDLG32 \
|
||||
LIBC_NT_URL \
|
||||
LIBC_NT_USER32 \
|
||||
LIBC_NT_NTDLL \
|
||||
LIBC_NT_ADVAPI32 \
|
||||
LIBC_FMT \
|
||||
THIRD_PARTY_COMPILER_RT \
|
||||
LIBC_THREAD \
|
||||
LIBC_TINYMATH \
|
||||
THIRD_PARTY_XED \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_INTRIN \
|
||||
LIBC_NT_KERNEL32 \
|
||||
LIBC_NEXGEN32E
|
||||
|
||||
COSMOPOLITAN_H_PKGS = \
|
||||
APE \
|
||||
DSP_AUDIO \
|
||||
LIBC \
|
||||
LIBC_CALLS \
|
||||
LIBC_ELF \
|
||||
LIBC_FMT \
|
||||
LIBC_DLOPEN \
|
||||
LIBC_INTRIN \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
LIBC_PROC \
|
||||
THIRD_PARTY_NSYNC \
|
||||
THIRD_PARTY_XED \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_THREAD \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_X \
|
||||
LIBC_VGA \
|
||||
NET_HTTP \
|
||||
TOOL_ARGS \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_GETOPT \
|
||||
THIRD_PARTY_MUSL \
|
||||
THIRD_PARTY_ZLIB \
|
||||
THIRD_PARTY_ZLIB_GZ \
|
||||
COSMOPOLITAN_HEADERS = \
|
||||
APE \
|
||||
LIBC \
|
||||
LIBC_CALLS \
|
||||
LIBC_DNS \
|
||||
LIBC_ELF \
|
||||
LIBC_FMT \
|
||||
LIBC_INTRIN \
|
||||
LIBC_LOG \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_NT \
|
||||
LIBC_RUNTIME \
|
||||
LIBC_SOCK \
|
||||
LIBC_STDIO \
|
||||
THIRD_PARTY_XED \
|
||||
LIBC_STR \
|
||||
LIBC_SYSV \
|
||||
LIBC_THREAD \
|
||||
LIBC_TIME \
|
||||
LIBC_TINYMATH \
|
||||
LIBC_X \
|
||||
LIBC_ZIPOS \
|
||||
NET_HTTP \
|
||||
THIRD_PARTY_DLMALLOC \
|
||||
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: \
|
||||
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
|
||||
|
||||
o/$(MODE)/cosmopolitan.a: \
|
||||
$(call reverse,$(call uniq,$(foreach x,$(COSMOPOLITAN),$($(x)))))
|
||||
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)))
|
||||
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >$@
|
||||
|
||||
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.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 /,_,$@)
|
||||
@$(TMPDIR)/$(subst /,_,$@)
|
||||
|
||||
$(SRCS): \
|
||||
libc/integral/normalize.inc \
|
||||
|
@ -574,50 +377,6 @@ $(SRCS): \
|
|||
libc/integral/lp64arg.inc \
|
||||
libc/integral/lp64.inc
|
||||
|
||||
ifeq ($(ARCH), x86_64)
|
||||
TOOLCHAIN_ARTIFACTS = \
|
||||
o/$(MODE)/ape/ape.lds \
|
||||
o/$(MODE)/libc/crt/crt.o \
|
||||
o/$(MODE)/ape/ape.elf \
|
||||
o/$(MODE)/ape/ape.o \
|
||||
o/$(MODE)/ape/ape-copy-self.o \
|
||||
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
|
||||
else
|
||||
TOOLCHAIN_ARTIFACTS = \
|
||||
o/$(MODE)/ape/ape.elf \
|
||||
o/$(MODE)/ape/aarch64.lds \
|
||||
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
|
||||
endif
|
||||
|
||||
.PHONY: toolchain
|
||||
toolchain: $(TOOLCHAIN_ARTIFACTS)
|
||||
|
||||
.PHONY: clean_toolchain
|
||||
clean_toolchain:
|
||||
$(RM) $(TOOLCHAIN_ARTIFACTS)
|
||||
|
||||
aarch64: private .INTERNET = true
|
||||
aarch64: private .UNSANDBOXED = true
|
||||
aarch64:
|
||||
$(MAKE) m=aarch64
|
||||
|
||||
clean:
|
||||
$(RM) -r o
|
||||
|
||||
# UNSPECIFIED PREREQUISITES TUTORIAL
|
||||
#
|
||||
# A build rule must exist for all files that make needs to consider in
|
||||
|
@ -642,9 +401,9 @@ $(SRCS):
|
|||
$(HDRS):
|
||||
$(INCS):
|
||||
.DEFAULT:
|
||||
@$(ECHO)
|
||||
@$(ECHO) NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@
|
||||
@$(ECHO)
|
||||
@$(ECHO) >&2
|
||||
@$(ECHO) NOTE: deleting o/$(MODE)/depend because of an unspecified prerequisite: $@ >&2
|
||||
@$(ECHO) >&2
|
||||
$(RM) o/$(MODE)/depend
|
||||
|
||||
-include o/$(MODE)/depend
|
||||
|
|
320
README.md
320
README.md
|
@ -3,170 +3,200 @@
|
|||
[](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/>.
|
||||
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
|
||||
mkdir -p cosmocc
|
||||
cd cosmocc
|
||||
wget https://cosmo.zip/pub/cosmocc/cosmocc.zip
|
||||
unzip cosmocc.zip
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan.zip
|
||||
unzip cosmopolitan.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 \
|
||||
-o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds \
|
||||
-include cosmopolitan.h crt.o ape-no-modify-self.o cosmopolitan.a
|
||||
objcopy -S -O binary hello.com.dbg hello.com
|
||||
```
|
||||
|
||||
Here's an example program we can write:
|
||||
|
||||
```c
|
||||
// hello.c
|
||||
#include <stdio.h>
|
||||
|
||||
int main() {
|
||||
printf("hello world\n");
|
||||
}
|
||||
```
|
||||
|
||||
It can be compiled as follows:
|
||||
You now have a portable program.
|
||||
|
||||
```sh
|
||||
cosmocc -o hello hello.c
|
||||
./hello
|
||||
./hello.com
|
||||
bash -c './hello.com' # zsh/fish workaround (we patched them in 2021)
|
||||
```
|
||||
|
||||
The Cosmopolitan Libc runtime links some heavyweight troubleshooting
|
||||
features by default, which are very useful for developers and admins.
|
||||
Here's how you can log system calls:
|
||||
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 to `${TMPDIR:-${HOME:-.}}`
|
||||
that maps your program into memory without needing to copy it. It's
|
||||
possible to install the APE loader systemwide as follows.
|
||||
|
||||
```sh
|
||||
./hello --strace
|
||||
# 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
|
||||
ape/apeinstall.sh
|
||||
|
||||
# System-Wide APE Uninstall
|
||||
# for Linux, Darwin, and BSDs
|
||||
ape/apeuninstall.sh
|
||||
```
|
||||
|
||||
Here's how you can get a much more verbose log of function calls:
|
||||
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
|
||||
./hello --ftrace
|
||||
$ file hello.com
|
||||
hello.com: DOS/MBR boot sector
|
||||
./hello.com --assimilate
|
||||
$ file hello.com
|
||||
hello.com: ELF 64-bit LSB executable
|
||||
```
|
||||
|
||||
You can use the Cosmopolitan's toolchain to build conventional open
|
||||
source projects which use autotools. This strategy normally works:
|
||||
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
|
||||
export CC=x86_64-unknown-cosmo-cc
|
||||
export CXX=x86_64-unknown-cosmo-c++
|
||||
./configure --prefix=/opt/cosmos/x86_64
|
||||
make -j
|
||||
make install
|
||||
./hello.com --strace # log system calls to stderr
|
||||
./hello.com --ftrace # log function calls to stderr
|
||||
```
|
||||
|
||||
## Cosmopolitan Source Builds
|
||||
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:
|
||||
|
||||
Cosmopolitan can be compiled from source on any of our supported
|
||||
platforms. The Makefile will download cosmocc automatically.
|
||||
```sh
|
||||
make -j8 MODE=tiny
|
||||
```
|
||||
|
||||
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.
|
||||
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>.
|
||||
|
||||
### MacOS
|
||||
|
||||
If you're developing on MacOS you can install the GNU compiler
|
||||
collection for x86_64-elf via homebrew:
|
||||
|
||||
```sh
|
||||
brew install x86_64-elf-gcc
|
||||
```
|
||||
|
||||
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.
|
||||
|
||||
```
|
||||
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
|
||||
```
|
||||
|
||||
## Source Builds
|
||||
|
||||
Cosmopolitan can be compiled from source on any Linux distro. First, you
|
||||
need to download or clone the repository.
|
||||
|
||||
```sh
|
||||
wget https://justine.lol/cosmopolitan/cosmopolitan.tar.gz
|
||||
tar xf cosmopolitan.tar.gz # see releases page
|
||||
cd cosmopolitan
|
||||
```
|
||||
|
||||
This will build the entire repository and run all the tests:
|
||||
|
||||
```sh
|
||||
build/bootstrap/make.com -j16
|
||||
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
|
||||
ape/apeinstall.sh
|
||||
```
|
||||
|
||||
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:
|
||||
|
||||
https://cosmo.zip/pub/cosmos/bin/make
|
||||
|
||||
E.g.:
|
||||
|
||||
```sh
|
||||
curl -LO https://cosmo.zip/pub/cosmos/bin/make
|
||||
./make -j8
|
||||
o//examples/hello
|
||||
```
|
||||
|
||||
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`.
|
||||
|
||||
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 -j16 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 -j16 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 -j16 MODE=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 -j16 MODE=dbg # asan + ubsan + debug
|
||||
build/bootstrap/make.com -j16 MODE=asan # production memory safety
|
||||
build/bootstrap/make.com -j16 MODE=opt # -march=native optimizations
|
||||
build/bootstrap/make.com -j16 MODE=rel # traditional release binaries
|
||||
build/bootstrap/make.com -j16 MODE=optlinux # optimal linux-only performance
|
||||
build/bootstrap/make.com -j16 MODE=tinylinux # tiniest linux-only 4kb binaries
|
||||
```
|
||||
|
||||
For further details, see [//build/config.mk](build/config.mk).
|
||||
|
||||
## Debugging
|
||||
|
||||
To print a log of system calls to stderr:
|
||||
|
||||
```sh
|
||||
cosmocc -o hello hello.c
|
||||
./hello --strace
|
||||
```
|
||||
|
||||
To print a log of function calls to stderr:
|
||||
|
||||
```sh
|
||||
cosmocc -o hello hello.c
|
||||
./hello --ftrace
|
||||
```
|
||||
|
||||
Both strace and ftrace use the unbreakable kprintf() facility, which is
|
||||
able to be sent to a file by setting an environment variable.
|
||||
|
||||
```sh
|
||||
export KPRINTF_LOG=log
|
||||
./hello --strace
|
||||
```
|
||||
|
||||
## GDB
|
||||
|
||||
Here's the recommended `~/.gdbinit` config:
|
||||
|
||||
```gdb
|
||||
```
|
||||
set host-charset UTF-8
|
||||
set target-charset UTF-8
|
||||
set target-wide-charset UTF-8
|
||||
|
@ -186,83 +216,25 @@ 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'
|
||||
```
|
||||
|
||||
## Platform Notes
|
||||
|
||||
### Shells
|
||||
|
||||
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:
|
||||
|
||||
```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
|
||||
gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
|
||||
```
|
||||
|
||||
You can fix that by registering APE with `binfmt_misc`:
|
||||
|
||||
```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"
|
||||
```
|
||||
|
||||
## Discord Chatroom
|
||||
|
||||
The Cosmopolitan development team collaborates on the Redbean Discord
|
||||
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 |
|
||||
|
||||
[1] See our [vista branch](https://github.com/jart/cosmopolitan/tree/vista)
|
||||
for a community supported version of Cosmopolitan that works on Windows
|
||||
Vista and Windows 7.
|
||||
| Platform | Min Version | Circa |
|
||||
| :--- | ---: | ---: |
|
||||
| AMD | K8 Venus | 2005 |
|
||||
| Intel | Core | 2006 |
|
||||
| Windows | Vista | 2006 |
|
||||
| Linux | 2.6.18 | 2007 |
|
||||
| Mac OS X | 15.6 | 2018 |
|
||||
| FreeBSD | 13 | 2020 |
|
||||
| OpenBSD | 6.4 | 2018 |
|
||||
| NetBSD | 9.2 | 2021 |
|
||||
|
||||
## Special Thanks
|
||||
|
||||
|
@ -270,10 +242,8 @@ Funding for this project is crowdsourced using
|
|||
[GitHub Sponsors](https://github.com/sponsors/jart) and
|
||||
[Patreon](https://www.patreon.com/jart). Your support is what makes this
|
||||
project possible. Thank you! We'd also like to give special thanks to
|
||||
the following groups and individuals:
|
||||
the following individuals:
|
||||
|
||||
- [Joe Drumgoole](https://github.com/jdrumgoole)
|
||||
- [Rob Figueiredo](https://github.com/robfig)
|
||||
- [Wasmer](https://wasmer.io/)
|
||||
|
||||
For publicly sponsoring our work at the highest tier.
|
||||
|
|
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
|
301
ape/aarch64.lds
301
ape/aarch64.lds
|
@ -1,301 +0,0 @@
|
|||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/thread/tls.h"
|
||||
|
||||
ENTRY(_start)
|
||||
OUTPUT_ARCH(aarch64)
|
||||
OUTPUT_FORMAT("elf64-littleaarch64",
|
||||
"elf64-bigaarch64",
|
||||
"elf64-littleaarch64")
|
||||
|
||||
SECTIONS {
|
||||
|
||||
. = SEGMENT_START("text-segment", 0x000800000000);
|
||||
__executable_start = .;
|
||||
. += SIZEOF_HEADERS;
|
||||
|
||||
.interp : { *(.interp) }
|
||||
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||
.hash : { *(.hash) }
|
||||
.gnu.hash : { *(.gnu.hash) }
|
||||
.dynsym : { *(.dynsym) }
|
||||
.dynstr : { *(.dynstr) }
|
||||
.gnu.version : { *(.gnu.version) }
|
||||
.gnu.version_d : { *(.gnu.version_d) }
|
||||
.gnu.version_r : { *(.gnu.version_r) }
|
||||
.rela.init : { *(.rela.init) }
|
||||
.rela.text : { *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) }
|
||||
.rela.fini : { *(.rela.fini) }
|
||||
.rela.rodata : { *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) }
|
||||
.rela.data.rel.ro : { *(.rela.data.rel.ro .rela.data.rel.ro.* .rela.gnu.linkonce.d.rel.ro.*) }
|
||||
.rela.data : { *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) }
|
||||
.rela.tdata : { *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) }
|
||||
.rela.tbss : { *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) }
|
||||
.rela.ctors : { *(.rela.ctors) }
|
||||
.rela.dtors : { *(.rela.dtors) }
|
||||
.rela.got : { *(.rela.got) }
|
||||
.rela.bss : { *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) }
|
||||
.rela.ifunc : { *(.rela.ifunc) }
|
||||
|
||||
.rela.plt : {
|
||||
*(.rela.plt)
|
||||
__rela_iplt_start = .;
|
||||
*(.rela.iplt)
|
||||
__rela_iplt_end = .;
|
||||
}
|
||||
|
||||
.init : {
|
||||
*(.start)
|
||||
KEEP(*(.initprologue))
|
||||
KEEP(*(SORT_NONE(.init)))
|
||||
KEEP(*(.initepilogue))
|
||||
} =0x1f2003d5
|
||||
|
||||
.plt : ALIGN(16) {
|
||||
*(.plt)
|
||||
*(.iplt)
|
||||
}
|
||||
|
||||
.text : {
|
||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||
*(.text.antiquity .text.antiquity.*)
|
||||
*(.text.exit .text.exit.*)
|
||||
*(.text.startup .text.startup.*)
|
||||
*(.text.hot .text.hot.*)
|
||||
*(.text.modernity .text.modernity.*)
|
||||
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||
*(.gnu.warning)
|
||||
} =0x1f2003d5
|
||||
|
||||
.fini : {
|
||||
KEEP(*(SORT_NONE(.fini)))
|
||||
} =0x1f2003d5
|
||||
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
|
||||
.privileged : {
|
||||
__privileged_start = ABSOLUTE(.) & -CONSTANT(MAXPAGESIZE);
|
||||
*(.privileged*)
|
||||
} =0x1f2003d6
|
||||
|
||||
.rodata : {
|
||||
KEEP(*(.rodata.pytab.0));
|
||||
KEEP(*(.rodata.pytab.1));
|
||||
KEEP(*(.rodata.pytab.2));
|
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
*(.ubsan.types)
|
||||
*(.ubsan.data)
|
||||
}
|
||||
|
||||
.notice : {
|
||||
__notices = .;
|
||||
KEEP(*(.notice))
|
||||
BYTE(0);
|
||||
BYTE(10);
|
||||
BYTE(10);
|
||||
}
|
||||
|
||||
.eh_frame_hdr : {
|
||||
*(.eh_frame_hdr)
|
||||
*(.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;
|
||||
|
||||
.gcc_except_table : ONLY_IF_RO {
|
||||
*(.gcc_except_table .gcc_except_table.*)
|
||||
}
|
||||
|
||||
.gnu_extab : ONLY_IF_RO {
|
||||
*(.gnu_extab*)
|
||||
}
|
||||
|
||||
.exception_ranges : ONLY_IF_RO {
|
||||
*(.exception_ranges*)
|
||||
}
|
||||
|
||||
__etext = .;
|
||||
_etext = .;
|
||||
PROVIDE(etext = .);
|
||||
|
||||
. += CONSTANT(MAXPAGESIZE);
|
||||
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
||||
|
||||
.eh_frame : {
|
||||
__eh_frame_start = .;
|
||||
KEEP(*(.eh_frame))
|
||||
*(.eh_frame.*)
|
||||
__eh_frame_end = .;
|
||||
}
|
||||
|
||||
.gnu_extab : ONLY_IF_RW {
|
||||
*(.gnu_extab)
|
||||
}
|
||||
|
||||
.gcc_except_table : ONLY_IF_RW {
|
||||
*(.gcc_except_table .gcc_except_table.*)
|
||||
}
|
||||
|
||||
.exception_ranges : ONLY_IF_RW {
|
||||
*(.exception_ranges*)
|
||||
}
|
||||
|
||||
.tdata : {
|
||||
_tdata_start = .;
|
||||
__tdata_start = .;
|
||||
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||
_tdata_end = .;
|
||||
}
|
||||
|
||||
.tbss : {
|
||||
_tbss_start = .;
|
||||
*(.tbss .tbss.* .gnu.linkonce.tb.*)
|
||||
*(.tcommon)
|
||||
_tbss_end = .;
|
||||
}
|
||||
|
||||
.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))
|
||||
__init_array_end = .;
|
||||
}
|
||||
|
||||
.fini_array : {
|
||||
__fini_array_start = .;
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(.fini_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||
__fini_array_end = .;
|
||||
}
|
||||
|
||||
.data.rel.ro : {
|
||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
||||
*(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*)
|
||||
*(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*)
|
||||
}
|
||||
|
||||
.dynamic : {
|
||||
*(.dynamic)
|
||||
}
|
||||
|
||||
.got : {
|
||||
*(.got)
|
||||
*(.igot)
|
||||
}
|
||||
|
||||
. = DATA_SEGMENT_RELRO_END(24, .);
|
||||
|
||||
.got.plt : {
|
||||
*(.got.plt)
|
||||
*(.igot.plt)
|
||||
}
|
||||
|
||||
.data : {
|
||||
__data_start = .;
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
*(.data .data.* .gnu.linkonce.d.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||
SORT(CONSTRUCTORS)
|
||||
}
|
||||
|
||||
_edata = .;
|
||||
PROVIDE(edata = .);
|
||||
|
||||
. = .;
|
||||
__bss_start = .;
|
||||
__bss_start__ = .;
|
||||
|
||||
.bss : {
|
||||
*(.dynbss)
|
||||
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
||||
*(COMMON)
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
}
|
||||
|
||||
_bss_end__ = .;
|
||||
__bss_end__ = .;
|
||||
. = ALIGN(64 / 8);
|
||||
. = SEGMENT_START("ldata-segment", .);
|
||||
. = ALIGN(64 / 8);
|
||||
__end__ = .;
|
||||
_end = .;
|
||||
PROVIDE(end = .);
|
||||
|
||||
. = DATA_SEGMENT_END(.);
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.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)) }
|
||||
|
||||
.zip 0 : {
|
||||
KEEP(*(.zip.file))
|
||||
__zip_cdir_start = .;
|
||||
KEEP(*(.zip.cdir))
|
||||
__zip_cdir_size = . - __zip_cdir_start;
|
||||
KEEP(*(.zip.eocd))
|
||||
}
|
||||
|
||||
/DISCARD/ : {
|
||||
*(__patchable_function_entries)
|
||||
*(.GCC.command.line)
|
||||
*(.note.GNU-stack)
|
||||
*(.gnu_debuglink)
|
||||
*(.text.windows)
|
||||
*(.gnu.lto_*)
|
||||
*(.eh_frame)
|
||||
*(.idata.*)
|
||||
*(.yoink)
|
||||
*(.head)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
_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)));
|
1139
ape/ape-m1.c
1139
ape/ape-m1.c
File diff suppressed because it is too large
Load diff
13
ape/ape.h
13
ape/ape.h
|
@ -1,13 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_APE_APE_H_
|
||||
#define COSMOPOLITAN_APE_APE_H_
|
||||
|
||||
#define APE_VERSION_MAJOR 1
|
||||
#define APE_VERSION_MINOR 10
|
||||
#define APE_VERSION_STR APE_VERSION_STR_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
|
||||
#define APE_VERSION_NOTE APE_VERSION_NOTE_(APE_VERSION_MAJOR, APE_VERSION_MINOR)
|
||||
|
||||
#define APE_VERSION_STR__(x, y) #x "." #y
|
||||
#define APE_VERSION_STR_(x, y) APE_VERSION_STR__(x, y)
|
||||
#define APE_VERSION_NOTE_(x, y) (100000000 * (x) + 1000000 * (y))
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_APE_H_ */
|
|
@ -1,9 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_APE_APE_INTERNAL_H_
|
||||
#define COSMOPOLITAN_APE_APE_INTERNAL_H_
|
||||
#include "libc/dce.h"
|
||||
|
||||
#if SupportsWindows() || SupportsMetal() || SupportsXnu()
|
||||
#define APE_IS_SHELL_SCRIPT
|
||||
#endif
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_APE_INTERNAL_H_ */
|
506
ape/ape.lds
506
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 │
|
||||
│ │
|
||||
|
@ -180,40 +180,16 @@
|
|||
#include "libc/elf/def.h"
|
||||
#include "libc/elf/pf2prot.internal.h"
|
||||
#include "libc/nt/pedef.internal.h"
|
||||
#include "libc/thread/tls.h"
|
||||
#include "ape/ape.internal.h"
|
||||
|
||||
/* uncomment if .com.dbg won't execute on your kernel (will break .com file) */
|
||||
/* #define APE_FIX_COM_DBG */
|
||||
|
||||
#ifdef __x86__
|
||||
#define CODE_GRANULE 1
|
||||
#else
|
||||
#define CODE_GRANULE 4
|
||||
#endif
|
||||
|
||||
#ifdef APE_FIX_COM_DBG
|
||||
#define SKEW SIZEOF_HEADERS
|
||||
#else
|
||||
#define SKEW 0
|
||||
#endif
|
||||
|
||||
#ifndef IMAGE_BASE_VIRTUAL
|
||||
#define IMAGE_BASE_VIRTUAL 0x400000
|
||||
#endif
|
||||
|
||||
#if IMAGE_BASE_VIRTUAL > 0xffffffff
|
||||
#error "please use 32-bit addresses for image data"
|
||||
#endif
|
||||
#include "libc/zip.h"
|
||||
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS {
|
||||
Head PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Cod PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Rom PT_LOAD FLAGS(PF_R);
|
||||
Tls PT_TLS FLAGS(PF_W|PF_R);
|
||||
Rom PT_LOAD FLAGS(PF_X|PF_R);
|
||||
Ram PT_LOAD FLAGS(PF_W|PF_R);
|
||||
Tls PT_TLS FLAGS(PF_W|PF_R);
|
||||
Bss PT_LOAD FLAGS(PF_W|PF_R);
|
||||
stack PT_GNU_STACK FLAGS(PF_W|PF_R);
|
||||
}
|
||||
|
||||
|
@ -224,44 +200,42 @@ SECTIONS {
|
|||
/*BEGIN: linux addressability guarantee */
|
||||
/*BEGIN: bsd addressability guarantee */
|
||||
|
||||
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) + SKEW : AT(IMAGE_BASE_REAL) {
|
||||
__executable_start = .;
|
||||
.head SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL) : AT(IMAGE_BASE_REAL) {
|
||||
HIDDEN(_base = .);
|
||||
|
||||
/* Real Mode */
|
||||
KEEP(*(.head))
|
||||
KEEP(*(.apesh))
|
||||
KEEP(*(.head2))
|
||||
KEEP(*(.text.head))
|
||||
|
||||
/* Executable & Linkable Format */
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
ape_phdrs = .;
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
HIDDEN(ape_phdrs = .);
|
||||
KEEP(*(.elf.phdrs))
|
||||
ape_phdrs_end = .;
|
||||
HIDDEN(ape_phdrs_end = .);
|
||||
|
||||
/* OpenBSD */
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
ape_note = .;
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
HIDDEN(ape_note = .);
|
||||
KEEP(*(.note.openbsd.ident))
|
||||
KEEP(*(.note.netbsd.ident))
|
||||
ape_note_end = .;
|
||||
HIDDEN(ape_note_end = .);
|
||||
|
||||
/* Portable Executable */
|
||||
KEEP(*(.pe.header))
|
||||
ape_pe_sections = .;
|
||||
HIDDEN(ape_pe_sections = .);
|
||||
KEEP(*(.pe.sections))
|
||||
ape_pe_sections_end = .;
|
||||
HIDDEN(ape_pe_sections_end = .);
|
||||
|
||||
/* Mach-O */
|
||||
KEEP(*(.macho))
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
ape_macho_end = .;
|
||||
|
||||
/* APE loader */
|
||||
KEEP(*(.ape.loader))
|
||||
. = ALIGN(. != 0 ? CODE_GRANULE : 0);
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
HIDDEN(ape_macho_end = .);
|
||||
|
||||
KEEP(*(.ape.pad.head))
|
||||
. = ALIGN(. != 0 ? (SupportsWindows() || SupportsMetal() ? CONSTANT(COMMONPAGESIZE) : 16) : 0);
|
||||
_ehead = .;
|
||||
. = ALIGN(SupportsWindows() || SupportsMetal() ? PAGESIZE : 16);
|
||||
HIDDEN(_ehead = .);
|
||||
} :Head
|
||||
|
||||
/*BEGIN: nt addressability guarantee */
|
||||
|
@ -271,10 +245,12 @@ SECTIONS {
|
|||
/* Code that needs to be addressable in Real Mode */
|
||||
*(.text.real)
|
||||
KEEP(*(SORT_BY_NAME(.sort.text.real.*)))
|
||||
_ereal = .;
|
||||
/* Code we want earlier in the binary w/o modifications */
|
||||
KEEP(*(.ape.loader))
|
||||
HIDDEN(_ereal = .);
|
||||
/*END: realmode addressability guarantee */
|
||||
/*BEGIN: morphable code */
|
||||
. += CODE_GRANULE;
|
||||
. += 1;
|
||||
|
||||
/* Normal Code */
|
||||
*(.start)
|
||||
|
@ -282,9 +258,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.*)
|
||||
|
@ -307,20 +286,17 @@ SECTIONS {
|
|||
|
||||
/* Privileged code invulnerable to magic */
|
||||
KEEP(*(.ape.pad.privileged));
|
||||
. = ALIGN(__privileged_end > __privileged_start ? CONSTANT(COMMONPAGESIZE) : 0);
|
||||
. += . > 0 ? 1 : 0;
|
||||
/*END: morphable code */
|
||||
__privileged_start = .;
|
||||
*(.privileged .privileged.*)
|
||||
__privileged_end = .;
|
||||
|
||||
KEEP(*(.ape.pad.text))
|
||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
||||
/*END: Read Only Data (only needed for initialization) */
|
||||
} :Cod
|
||||
HIDDEN(__privileged_start = .);
|
||||
. += . > 0 ? 1 : 0;
|
||||
*(.privileged)
|
||||
HIDDEN(__privileged_end = .);
|
||||
. += . > 0 ? 1 : 0;
|
||||
|
||||
/*BEGIN: Read Only Data */
|
||||
|
||||
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
||||
KEEP(*(.ape.pad.rodata));
|
||||
KEEP(*(.rodata.pytab.0));
|
||||
KEEP(*(.rodata.pytab.1));
|
||||
KEEP(*(.rodata.pytab.2));
|
||||
|
@ -329,139 +305,116 @@ SECTIONS {
|
|||
*(.ubsan.types)
|
||||
*(.ubsan.data)
|
||||
|
||||
__eh_frame_hdr_start_actual = .;
|
||||
*(.eh_frame_hdr)
|
||||
__eh_frame_hdr_end_actual = .;
|
||||
/* Unit Test & Fixture Registry */
|
||||
|
||||
/*BEGIN: Read only data that needn't be mapped after initialization */
|
||||
|
||||
/* 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 */
|
||||
|
||||
#if SupportsWindows()
|
||||
/* Windows DLL Import Directory */
|
||||
KEEP(*(.idata.ro));
|
||||
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
|
||||
#endif
|
||||
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
PROVIDE_HIDDEN(__init_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||
KEEP(*(.ctors))
|
||||
KEEP(*(.init_array))
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN(__init_array_end = .);
|
||||
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
PROVIDE_HIDDEN(__fini_array_start = .);
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(.dtors))
|
||||
PROVIDE_HIDDEN(__fini_array_end = .);
|
||||
|
||||
/* Encoded Data Structures w/ Linear Initialization Order */
|
||||
KEEP(*(.initroprologue))
|
||||
KEEP(*(SORT_BY_NAME(.initro.*)))
|
||||
KEEP(*(.initroepilogue))
|
||||
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
|
||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0); /* don't delete this line :o */
|
||||
|
||||
/*END: read-only data that's only needed for initialization */
|
||||
|
||||
KEEP(*(.ape.pad.text))
|
||||
. = ALIGN(PAGESIZE);
|
||||
HIDDEN(_etext = .);
|
||||
PROVIDE_HIDDEN(etext = .);
|
||||
/*END: Read Only Data (only needed for initialization) */
|
||||
/*END: Read Only Data */
|
||||
} :Rom
|
||||
|
||||
/* initialization image for thread-local storage, this is copied */
|
||||
/* out to actual TLS areas at runtime, so just make it read-only */
|
||||
.data ALIGN(PAGESIZE) : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.iat.*)))
|
||||
/*BEGIN: NT FORK COPYING */
|
||||
KEEP(*(.dataprologue))
|
||||
*(.data .data.*)
|
||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||
. += . > 0 ? 1 : 0;
|
||||
|
||||
KEEP(*(.gotprologue))
|
||||
*(.got)
|
||||
KEEP(*(.gotepilogue))
|
||||
|
||||
KEEP(*(.gotpltprologue))
|
||||
*(.got.plt)
|
||||
KEEP(*(.gotpltepilogue))
|
||||
|
||||
/*BEGIN: Post-Initialization Read-Only */
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
||||
PROVIDE_HIDDEN(__relo_end = .);
|
||||
. = ALIGN(__SIZEOF_POINTER__);
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||
KEEP(*(.piro.pad.data))
|
||||
KEEP(*(.dataepilogue))
|
||||
/*END: NT FORK COPYING */
|
||||
HIDDEN(_edata = .);
|
||||
PROVIDE_HIDDEN(edata = .);
|
||||
KEEP(*(SORT_BY_NAME(.zip.*)))
|
||||
HIDDEN(_ezip = .);
|
||||
} :Ram
|
||||
|
||||
.tdata . : {
|
||||
_tdata_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tdata))
|
||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||
. = ALIGN(16);
|
||||
_tdata_end = .;
|
||||
KEEP(*(.ape.pad.rodata))
|
||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
||||
_etext = .;
|
||||
PROVIDE(etext = .);
|
||||
} :Tls :Rom
|
||||
/*END: Read Only Data */
|
||||
. = ALIGN(PAGESIZE);
|
||||
} :Tls
|
||||
. = ALIGN(PAGESIZE);
|
||||
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
/*END: file content that's loaded by o/s */
|
||||
/*BEGIN: bss memory void */
|
||||
|
||||
/* this only tells the linker about the layout of uninitialized */
|
||||
/* TLS data, and does not advance the linker's location counter */
|
||||
.tbss : {
|
||||
.tbss . : {
|
||||
_tbss_start = .;
|
||||
*(SORT_BY_ALIGNMENT(.tbss))
|
||||
*(SORT_BY_ALIGNMENT(.tbss.*))
|
||||
KEEP(*(.fstls))
|
||||
. = ALIGN(16);
|
||||
/* the %fs register is based on this location */
|
||||
_tbss_end = .;
|
||||
} :Tls
|
||||
|
||||
.eh_frame : {
|
||||
__eh_frame_start = .;
|
||||
KEEP(*(.eh_frame))
|
||||
*(.eh_frame.*)
|
||||
__eh_frame_end = .;
|
||||
} :Ram
|
||||
|
||||
.data . : {
|
||||
/*BEGIN: Read/Write Data */
|
||||
#if SupportsWindows()
|
||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.iat.*)))
|
||||
#endif
|
||||
/*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 = .;
|
||||
*(.got)
|
||||
__got_end = .;
|
||||
|
||||
*(.got.plt)
|
||||
|
||||
. = 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))
|
||||
__init_array_end = .;
|
||||
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
__fini_array_start = .;
|
||||
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
|
||||
SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||
KEEP(*(.fini_array))
|
||||
KEEP(*(.dtors))
|
||||
__fini_array_end = .;
|
||||
|
||||
/*BEGIN: Post-Initialization Read-Only */
|
||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
||||
. = 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 */
|
||||
_edata = .;
|
||||
PROVIDE(edata = .);
|
||||
_ezip = .; /* <-- very deprecated */
|
||||
} :Ram
|
||||
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
|
||||
/*END: file content that's loaded by o/s */
|
||||
/*END: file content */
|
||||
/*BEGIN: bss memory that's addressable */
|
||||
|
||||
.bss : {
|
||||
.bss ALIGN(64) : {
|
||||
/*BEGIN: NT FORK COPYING */
|
||||
KEEP(*(.bssprologue))
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.init.*)))
|
||||
*(.piro.bss)
|
||||
KEEP(*(SORT_BY_NAME(.piro.bss.sort.*)))
|
||||
__piro_end = .;
|
||||
. += . > 0 ? CODE_GRANULE : 0;
|
||||
HIDDEN(__piro_end = .);
|
||||
. += . > 0 ? 1 : 0;
|
||||
/*END: Post-Initialization Read-Only */
|
||||
|
||||
/* Statically Allocated Empty Space */
|
||||
|
@ -472,15 +425,11 @@ SECTIONS {
|
|||
KEEP(*(SORT_BY_NAME(.sort.bss.*)))
|
||||
|
||||
KEEP(*(.bssepilogue))
|
||||
|
||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
||||
|
||||
/*END: NT FORK COPYING */
|
||||
} :Ram
|
||||
|
||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||
_end = .;
|
||||
PROVIDE(end = .);
|
||||
. = ALIGN(FRAMESIZE); /* for brk()/sbrk() allocation */
|
||||
HIDDEN(_end = .);
|
||||
PROVIDE_HIDDEN(end = .);
|
||||
} :Bss
|
||||
|
||||
/*END: nt addressability guarantee */
|
||||
/*END: bsd addressability guarantee */
|
||||
|
@ -508,7 +457,6 @@ SECTIONS {
|
|||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_line_str 0 : { *(.debug_line_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
|
@ -517,43 +465,19 @@ SECTIONS {
|
|||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.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) }
|
||||
|
||||
.zip 0 : {
|
||||
KEEP(*(.zip.file))
|
||||
__zip_cdir_start = .;
|
||||
KEEP(*(.zip.cdir))
|
||||
__zip_cdir_size = . - __zip_cdir_start;
|
||||
KEEP(*(.zip.eocd))
|
||||
}
|
||||
|
||||
/DISCARD/ : {
|
||||
#if !SupportsWindows()
|
||||
*(.idata.ro);
|
||||
*(.idata.ro.*)
|
||||
*(.piro.data.sort.iat.*)
|
||||
#endif
|
||||
*(__patchable_function_entries)
|
||||
*(.note.gnu.property)
|
||||
*(__mcount_loc)
|
||||
*(.rela.dyn)
|
||||
*(.discard)
|
||||
*(.yoink)
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
ape_pe_filealignment = 512;
|
||||
ape_pe_sectionalignment = 4096;
|
||||
ape_pe_sizeofheaders = SIZEOF(.head);
|
||||
ape_pe_sizeofimage = ROUNDUP(_end - __executable_start, ape_pe_sectionalignment);
|
||||
|
||||
PFSTUB8(ape_elf_entry, _start);
|
||||
PFSTUB8(ape_elf_phoff, RVA(ape_phdrs));
|
||||
PFSTUB8(ape_elf_shoff, 0);
|
||||
|
@ -561,61 +485,68 @@ PFSTUB4(ape_elf_phnum, (ape_phdrs_end - ape_phdrs) / 56);
|
|||
PFSTUB4(ape_elf_shnum, 0);
|
||||
PFSTUB4(ape_elf_shstrndx, 0);
|
||||
|
||||
_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)));
|
||||
HIDDEN(_tdata_size = _tdata_end - _tdata_start);
|
||||
HIDDEN(_tls_size = _tbss_end - _tdata_start);
|
||||
HIDDEN(_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start));
|
||||
|
||||
ape_cod_offset = 0;
|
||||
ape_cod_vaddr = ADDR(.head);
|
||||
ape_cod_paddr = LOADADDR(.head);
|
||||
ape_cod_filesz = ADDR(.rodata) - ADDR(.head);
|
||||
ape_cod_memsz = ape_cod_filesz;
|
||||
ape_cod_align = CONSTANT(COMMONPAGESIZE);
|
||||
ape_cod_rva = RVA(ape_cod_vaddr);
|
||||
HIDDEN(__privileged_addr = ROUNDDOWN(__privileged_start, PAGESIZE));
|
||||
HIDDEN(__privileged_size = (ROUNDUP(__privileged_end, PAGESIZE) -
|
||||
ROUNDDOWN(__privileged_start, PAGESIZE)));
|
||||
|
||||
ape_rom_vaddr = ADDR(.rodata);
|
||||
ape_rom_offset = ape_rom_vaddr - __executable_start;
|
||||
ape_rom_paddr = LOADADDR(.rodata);
|
||||
ape_rom_filesz = ADDR(.tbss) - ADDR(.rodata);
|
||||
ape_rom_memsz = ape_rom_filesz;
|
||||
ape_rom_align = CONSTANT(COMMONPAGESIZE);
|
||||
ape_rom_rva = RVA(ape_rom_vaddr);
|
||||
HIDDEN(ape_rom_offset = 0);
|
||||
HIDDEN(ape_rom_vaddr = ADDR(.head));
|
||||
HIDDEN(ape_rom_paddr = LOADADDR(.head));
|
||||
HIDDEN(ape_rom_filesz = LOADADDR(.data) - ape_rom_paddr);
|
||||
HIDDEN(ape_rom_memsz = ADDR(.data) - ADDR(.head));
|
||||
HIDDEN(ape_rom_align = PAGESIZE);
|
||||
HIDDEN(ape_rom_rva = RVA(ape_rom_vaddr));
|
||||
|
||||
ape_ram_vaddr = ADDR(.eh_frame);
|
||||
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_align = CONSTANT(COMMONPAGESIZE);
|
||||
ape_ram_rva = RVA(ape_ram_vaddr);
|
||||
HIDDEN(ape_ram_offset = ape_rom_offset + ape_rom_filesz);
|
||||
HIDDEN(ape_ram_vaddr = ADDR(.data));
|
||||
HIDDEN(ape_ram_paddr = LOADADDR(.data));
|
||||
HIDDEN(ape_ram_filesz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_ram_memsz = ADDR(.bss) + SIZEOF(.bss) - ape_ram_vaddr);
|
||||
HIDDEN(ape_ram_align = PAGESIZE);
|
||||
HIDDEN(ape_ram_rva = RVA(ape_ram_vaddr));
|
||||
|
||||
ape_stack_pf = DEFINED(ape_stack_pf) ? ape_stack_pf : PF_R | PF_W;
|
||||
ape_stack_prot = _PF2PROT(ape_stack_pf);
|
||||
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;
|
||||
HIDDEN(ape_stack_pf = DEFINED(ape_stack_pf) ? ape_stack_pf : PF_R | PF_W);
|
||||
HIDDEN(ape_stack_prot = _PF2PROT(ape_stack_pf));
|
||||
HIDDEN(ape_stack_offset = ape_ram_offset + ape_ram_filesz);
|
||||
HIDDEN(ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000);
|
||||
HIDDEN(ape_stack_paddr = ape_ram_paddr + ape_ram_filesz);
|
||||
HIDDEN(ape_stack_filesz = 0);
|
||||
HIDDEN(ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : STACKSIZE);
|
||||
HIDDEN(ape_stack_align = 16);
|
||||
|
||||
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
|
||||
ape_note_filesz = ape_note_end - ape_note;
|
||||
ape_note_memsz = ape_note_filesz;
|
||||
HIDDEN(ape_note_offset = ape_rom_offset + (ape_note - ape_rom_vaddr));
|
||||
HIDDEN(ape_note_vaddr = ape_note);
|
||||
HIDDEN(ape_note_paddr = ape_rom_paddr + ape_note_offset);
|
||||
HIDDEN(ape_note_filesz = ape_note_end - ape_note);
|
||||
HIDDEN(ape_note_memsz = ape_note_filesz);
|
||||
HIDDEN(ape_note_align = __SIZEOF_POINTER__);
|
||||
|
||||
ape_text_vaddr = ADDR(.text);
|
||||
ape_text_offset = ape_text_vaddr - __executable_start;
|
||||
ape_text_paddr = LOADADDR(.text);
|
||||
ape_text_filesz = ADDR(.rodata) - ADDR(.text);
|
||||
ape_text_memsz = ape_text_filesz;
|
||||
ape_text_align = CONSTANT(COMMONPAGESIZE);
|
||||
ape_text_rva = RVA(ape_text_vaddr);
|
||||
HIDDEN(ape_text_offset = ape_rom_offset + LOADADDR(.text) - ape_rom_paddr);
|
||||
HIDDEN(ape_text_paddr = LOADADDR(.text));
|
||||
HIDDEN(ape_text_vaddr = ADDR(.text));
|
||||
HIDDEN(ape_text_filesz = SIZEOF(.text));
|
||||
HIDDEN(ape_text_memsz = SIZEOF(.text));
|
||||
HIDDEN(ape_text_align = PAGESIZE);
|
||||
HIDDEN(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;
|
||||
HIDDEN(ape_data_offset = ape_ram_offset + LOADADDR(.data) - ape_ram_paddr);
|
||||
HIDDEN(ape_data_paddr = LOADADDR(.data));
|
||||
HIDDEN(ape_data_vaddr = ADDR(.data));
|
||||
HIDDEN(ape_data_filesz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_data_memsz = SIZEOF(.data) + SIZEOF(.tdata));
|
||||
HIDDEN(ape_data_align = PAGESIZE);
|
||||
HIDDEN(ape_data_rva = RVA(ape_data_vaddr));
|
||||
|
||||
HIDDEN(ape_bss_offset = ape_ram_offset + LOADADDR(.bss) - ape_ram_paddr);
|
||||
HIDDEN(ape_bss_paddr = LOADADDR(.bss));
|
||||
HIDDEN(ape_bss_vaddr = ADDR(.bss));
|
||||
HIDDEN(ape_bss_filesz = 0);
|
||||
HIDDEN(ape_bss_memsz = SIZEOF(.bss));
|
||||
HIDDEN(ape_bss_align = PAGESIZE);
|
||||
|
||||
/* 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 */
|
||||
|
@ -623,19 +554,26 @@ __eh_frame_hdr_end = __eh_frame_hdr_end_actual > __eh_frame_hdr_start_actual ? _
|
|||
SHSTUB2(ape_loader_dd_skip, DEFINED(ape_loader) ? RVA(ape_loader) / 64 : 0);
|
||||
SHSTUB2(ape_loader_dd_count,
|
||||
DEFINED(ape_loader_end)
|
||||
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
|
||||
? ROUNDUP(ape_loader_end - ape_loader, PAGESIZE) / 64
|
||||
: 0);
|
||||
|
||||
#if SupportsMetal()
|
||||
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
|
||||
v_ape_realbytes = v_ape_realsectors * 512;
|
||||
v_ape_realdwords = v_ape_realsectors * (512 / 4);
|
||||
v_ape_allsectors = ROUNDUP(RVA(_ezip), 512) / 512;
|
||||
v_ape_allbytes = v_ape_allsectors * 512;
|
||||
v_ape_highsectors = MIN(0xffff, v_ape_allsectors - v_ape_realsectors);
|
||||
TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
||||
HIDDEN(v_ape_realsectors =
|
||||
MIN(0x70000 - IMAGE_BASE_REAL,
|
||||
ROUNDUP(RVA(_edata), 4096)) / 512);
|
||||
HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512));
|
||||
HIDDEN(v_ape_highsectors =
|
||||
(ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors);
|
||||
#endif
|
||||
|
||||
/* ZIP End of Central Directory header */
|
||||
#define ZIPCONST(NAME, VAL) HIDDEN(NAME = DEFINED(__zip_start) ? VAL : 0);
|
||||
ZIPCONST(v_zip_cdoffset, __zip_start - IMAGE_BASE_VIRTUAL);
|
||||
ZIPCONST(v_zip_cdirsize, __zip_end - __zip_start);
|
||||
ASSERT(v_zip_cdirsize % kZipCdirHdrLinkableSize == 0, "bad zip cdir");
|
||||
ZIPCONST(v_zip_records, v_zip_cdirsize / kZipCdirHdrLinkableSize);
|
||||
ZIPCONST(v_zip_commentsize, _ezip - __zip_end - kZipCdirHdrMinSize);
|
||||
|
||||
#if SupportsXnu()
|
||||
/* Generates deterministic ID. */
|
||||
#define PHI 0x9e3779b9925d4c17
|
||||
|
@ -654,8 +592,19 @@ TSSDESCSTUB2(_tss, _tss, _tss_end ? _tss_end - _tss - 1 : 0);
|
|||
KMH(ape_uuid1, X); \
|
||||
XORSHIFT(ape_uuid2, X); \
|
||||
KMH(ape_uuid2, X)
|
||||
ape_uuid1 = 88172645463325252;
|
||||
ape_uuid2 = 88172645463325252;
|
||||
HIDDEN(ape_uuid1 = 88172645463325252);
|
||||
HIDDEN(ape_uuid2 = 88172645463325252);
|
||||
CHURN(ape_bss_align);
|
||||
CHURN(ape_bss_filesz);
|
||||
CHURN(ape_bss_memsz);
|
||||
CHURN(ape_bss_offset);
|
||||
CHURN(ape_bss_paddr);
|
||||
CHURN(ape_data_filesz);
|
||||
CHURN(ape_data_memsz);
|
||||
CHURN(ape_data_offset);
|
||||
CHURN(ape_data_paddr);
|
||||
CHURN(ape_data_rva);
|
||||
CHURN(ape_data_vaddr);
|
||||
CHURN(ape_elf_entry);
|
||||
CHURN(ape_elf_phnum);
|
||||
CHURN(ape_elf_phoff);
|
||||
|
@ -664,10 +613,13 @@ CHURN(ape_elf_shoff);
|
|||
CHURN(ape_elf_shstrndx);
|
||||
CHURN(ape_macho_end);
|
||||
CHURN(ape_note);
|
||||
CHURN(ape_note_align);
|
||||
CHURN(ape_note_end);
|
||||
CHURN(ape_note_filesz);
|
||||
CHURN(ape_note_memsz);
|
||||
CHURN(ape_note_offset);
|
||||
CHURN(ape_note_paddr);
|
||||
CHURN(ape_note_vaddr);
|
||||
CHURN(ape_ram_align);
|
||||
CHURN(ape_ram_filesz);
|
||||
CHURN(ape_ram_memsz);
|
||||
|
@ -681,14 +633,7 @@ CHURN(ape_rom_memsz);
|
|||
CHURN(ape_rom_offset);
|
||||
CHURN(ape_rom_paddr);
|
||||
CHURN(ape_rom_rva);
|
||||
CHURN(ape_cod_vaddr);
|
||||
CHURN(ape_cod_align);
|
||||
CHURN(ape_cod_filesz);
|
||||
CHURN(ape_cod_memsz);
|
||||
CHURN(ape_cod_offset);
|
||||
CHURN(ape_cod_paddr);
|
||||
CHURN(ape_cod_rva);
|
||||
CHURN(ape_cod_vaddr);
|
||||
CHURN(ape_rom_vaddr);
|
||||
CHURN(ape_text_align);
|
||||
CHURN(ape_text_filesz);
|
||||
CHURN(ape_text_memsz);
|
||||
|
@ -700,7 +645,7 @@ CHURN(ADDR(.bss));
|
|||
CHURN(_start);
|
||||
CHURN(ape_phdrs);
|
||||
#if SupportsMetal()
|
||||
CHURN(v_ape_allsectors);
|
||||
CHURN(v_ape_realsectors);
|
||||
#endif
|
||||
#if SupportsXnu()
|
||||
CHURN(ape_macho);
|
||||
|
@ -721,22 +666,22 @@ CHURN(WinMain);
|
|||
#if SupportsWindows() || SupportsMetal()
|
||||
#define LINK_WINDOWS (SupportsWindows() && !DEFINED(EfiMain))
|
||||
PFSTUB4(ape_pe_offset, ape_pe - ape_mz);
|
||||
ape_pe_optsz = ape_pe_sections - (ape_pe + 24);
|
||||
ASSERT(ape_pe_optsz % 8 == 0, "SizeOfOptionalHeader must be multiple of 8");
|
||||
ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40;
|
||||
ape_pe_base = IMAGE_BASE_VIRTUAL;
|
||||
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_ntdllchar = LINK_WINDOWS ? 288 : 0;
|
||||
v_ntsubversion = LINK_WINDOWS ? 6 : 5;
|
||||
v_ntsubsystem = (LINK_WINDOWS
|
||||
? (DEFINED(GetMessage)
|
||||
? kNtImageSubsystemWindowsGui
|
||||
: kNtImageSubsystemWindowsCui)
|
||||
: kNtImageSubsystemEfiApplication);
|
||||
ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain;
|
||||
HIDDEN(ape_pe_optsz = ape_pe_sections - (ape_pe + 24));
|
||||
HIDDEN(ape_pe_shnum = (ape_pe_sections_end - ape_pe_sections) / 40);
|
||||
HIDDEN(ape_pe_base = IMAGE_BASE_VIRTUAL);
|
||||
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_iat) : 0);
|
||||
HIDDEN(ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0);
|
||||
HIDDEN(ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0);
|
||||
HIDDEN(ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0);
|
||||
HIDDEN(v_ntversion = LINK_WINDOWS ? 6 : 1);
|
||||
HIDDEN(v_ntdllchar = LINK_WINDOWS ? 288 : 0);
|
||||
HIDDEN(v_ntsubversion = LINK_WINDOWS ? 6 : 5);
|
||||
HIDDEN(v_ntsubsystem = (LINK_WINDOWS
|
||||
? (DEFINED(GetMessage)
|
||||
? kNtImageSubsystemWindowsGui
|
||||
: kNtImageSubsystemWindowsCui)
|
||||
: kNtImageSubsystemEfiApplication));
|
||||
HIDDEN(ape_pe_entry = LINK_WINDOWS ? WinMain : EfiMain);
|
||||
#endif
|
||||
|
||||
#if SupportsXnu()
|
||||
|
@ -754,16 +699,17 @@ ASSERT(((DEFINED(__init_rodata_end) ? __init_rodata_end : 0) %
|
|||
ASSERT((!DEFINED(ape_grub) ? 1 : RVA(ape_grub) < 8192),
|
||||
"grub stub needs to be in first 8kb of image");
|
||||
|
||||
ASSERT(DEFINED(_start) || DEFINED(_start16),
|
||||
"please link a _start() or _start16() entrypoint");
|
||||
|
||||
ASSERT(!DEFINED(_start16) || REAL(_end) < 65536,
|
||||
"ape won't support non-tiny real mode programs");
|
||||
|
||||
ASSERT(IS2POW(ape_stack_memsz),
|
||||
"ape_stack_memsz must be a two power");
|
||||
|
||||
ASSERT(ape_stack_vaddr % ape_stack_memsz == 0,
|
||||
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000040000 & -ape_stack_memsz);");
|
||||
|
||||
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||
|
||||
ASSERT(DEFINED(main), "main() function not defined");
|
||||
ASSERT(!(ape_stack_vaddr & (ape_stack_memsz - 1)),
|
||||
"ape_stack_vaddr must have ape_stack_memsz alignment; try using STATIC_STACK_ADDR(0x700000000000 - ape_stack_memsz);");
|
||||
|
||||
/* Let's not be like Knight Capital. */
|
||||
/* NOCROSSREFS_TO(.test .text) */
|
||||
|
|
169
ape/ape.mk
Normal file
169
ape/ape.mk
Normal file
|
@ -0,0 +1,169 @@
|
|||
#-*-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 = o/$(MODE)/ape/ape.o \
|
||||
o/$(MODE)/ape/ape.lds
|
||||
|
||||
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
|
||||
|
||||
APELINK = \
|
||||
$(COMPILE) \
|
||||
-ALINK.ape \
|
||||
$(LINK) \
|
||||
$(LINKARGS) \
|
||||
$(OUTPUT_OPTION)
|
||||
|
||||
APE_LOADER_FLAGS = \
|
||||
-DNDEBUG \
|
||||
-iquote. \
|
||||
-Wall \
|
||||
-Wextra \
|
||||
-fpie \
|
||||
-Os \
|
||||
-ffreestanding \
|
||||
-mgeneral-regs-only \
|
||||
-mno-red-zone \
|
||||
-fno-ident \
|
||||
-fno-gnu-unique \
|
||||
-c \
|
||||
$(OUTPUT_OPTION) \
|
||||
$<
|
||||
|
||||
APE_FILES := $(wildcard ape/*.*)
|
||||
APE_HDRS = $(filter %.h,$(APE_FILES))
|
||||
APE_INCS = $(filter %.inc,$(APE_FILES))
|
||||
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/$(MODE)/ape/ape.lds: \
|
||||
ape/ape.lds \
|
||||
ape/macros.internal.h \
|
||||
ape/relocations.h \
|
||||
libc/intrin/bits.h \
|
||||
libc/calls/struct/timespec.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.h
|
||||
|
||||
o/ape/idata.inc: \
|
||||
ape/idata.internal.h \
|
||||
ape/relocations.h
|
||||
|
||||
o/$(MODE)/ape/ape-no-modify-self.o: \
|
||||
ape/ape.S \
|
||||
ape/macros.internal.h \
|
||||
ape/notice.inc \
|
||||
ape/relocations.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros-cpp.internal.inc \
|
||||
libc/macros.internal.h \
|
||||
libc/macros.internal.inc \
|
||||
libc/nexgen32e/uart.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/runtime/symbolic.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/macros.internal.h \
|
||||
ape/notice.inc \
|
||||
ape/relocations.h \
|
||||
libc/dce.h \
|
||||
libc/elf/def.h \
|
||||
libc/intrin/asancodes.h \
|
||||
libc/macho.internal.h \
|
||||
libc/macros-cpp.internal.inc \
|
||||
libc/macros.internal.h \
|
||||
libc/macros.internal.inc \
|
||||
libc/nexgen32e/uart.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/runtime/symbolic.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 ape/loader.h
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b01111001 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-gcc.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b01111001 -S -g0 $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-clang.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=0b01111001 -S -g0 $(APE_LOADER_FLAGS)
|
||||
|
||||
o/$(MODE)/ape/loader-xnu.o: ape/loader.c ape/loader.h
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b00001000 -g $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-xnu-gcc.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=0b00001000 -S -g0 $(APE_LOADER_FLAGS)
|
||||
o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=0b00001000 -S -g0 $(APE_LOADER_FLAGS)
|
||||
|
||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.macho.dbg
|
||||
|
||||
o/$(MODE)/ape/ape.elf.dbg: \
|
||||
o/$(MODE)/ape/loader.o \
|
||||
o/$(MODE)/ape/loader-elf.o \
|
||||
ape/loader.lds
|
||||
@$(ELFLINK) -z max-page-size=0x10
|
||||
|
||||
o/$(MODE)/ape/ape.macho.dbg: \
|
||||
o/$(MODE)/ape/loader-xnu.o \
|
||||
o/$(MODE)/ape/loader-macho.o \
|
||||
ape/loader-macho.lds
|
||||
@$(ELFLINK) -z max-page-size=0x10
|
||||
|
||||
.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
|
|
@ -1,107 +1,62 @@
|
|||
#!/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
|
||||
if [ $UID -eq 0 ]; then
|
||||
SUDO=
|
||||
elif command -v sudo >/dev/null 2>&1; then
|
||||
else
|
||||
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
|
||||
if [ -f o/depend ]; then
|
||||
# mkdeps.com build was successfully run so assume we can build
|
||||
echo >&2
|
||||
echo "recompiling ape loader" >&2
|
||||
echo "running: make -j8 o//ape" >&2
|
||||
make -j8 o//ape || exit
|
||||
echo "done" >&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
|
||||
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/$MODE/ape || exit
|
||||
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/$MODE/ape/ape.$EXT https://justine.lol/ape.$BEXT || exit
|
||||
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/$MODE/ape/ape.$EXT https://justine.lol/ape.$BEXT || exit
|
||||
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/$MODE/ape/ape.$EXT || exit
|
||||
chmod +x o//ape/ape.elf || exit
|
||||
chmod +x o//ape/ape.macho || 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
|
||||
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
|
||||
|
||||
################################################################################
|
||||
|
@ -137,20 +92,11 @@ if [ x"$(uname -s)" = xLinux ]; then
|
|||
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 '$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 done >&2
|
||||
|
||||
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
||||
|
|
|
@ -1,68 +1,24 @@
|
|||
#!/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
|
||||
SUDO=sudo
|
||||
fi
|
||||
|
||||
{
|
||||
echo
|
||||
echo "APE Uninstaller intends to run (in pseudo-shell)"
|
||||
echo "APE Uninstaller intends to run"
|
||||
echo
|
||||
echo " sudo echo -1 into /proc/sys/fs/binfmt_misc/APE*"
|
||||
echo " sudo rm -f /usr/bin/ape ~/.ape /tmp/.ape # etc."
|
||||
echo " $SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE'"
|
||||
echo " $SUDO rm -f /usr/bin/ape ~/.ape o/tmp/.ape /tmp/.ape"
|
||||
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
|
||||
if [ -f /proc/sys/fs/binfmt_misc/APE ]; then
|
||||
$SUDO sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/APE' || exit
|
||||
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
|
||||
$SUDO rm -f /usr/bin/ape ~/.ape o/tmp/.ape o/tmp/ape /tmp/.ape /tmp/ape || exit
|
||||
|
|
10
ape/config.h
Normal file
10
ape/config.h
Normal file
|
@ -0,0 +1,10 @@
|
|||
#ifndef COSMOPOLITAN_APE_CONFIG_H_
|
||||
#define COSMOPOLITAN_APE_CONFIG_H_
|
||||
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||
|
||||
#define STATIC_SYMBOL(NAME, VALUE) \
|
||||
asm(".equ\t" NAME "," VALUE "\n\t" \
|
||||
".globl\t" NAME)
|
||||
|
||||
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||
#endif /* COSMOPOLITAN_APE_CONFIG_H_ */
|
|
@ -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 │
|
||||
│ │
|
||||
|
@ -31,84 +31,80 @@
|
|||
// @see libc/nt/master.sh
|
||||
// @see ape/ape.lds
|
||||
// @see winimp
|
||||
.macro .imp dll:req fn:req actual:req
|
||||
#ifdef __x86_64__
|
||||
.dll "\dll"
|
||||
.section ".piro.data.sort.iat.2.\dll\().2.\actual","aw",@progbits
|
||||
.macro .imp dll:req fn:req actual:req hint
|
||||
.dll \dll
|
||||
.section .piro.data.sort.iat.2.\dll\().2.\actual,"aw",@progbits
|
||||
.type \fn,@object
|
||||
.align __SIZEOF_POINTER__
|
||||
\fn: .quad RVA(("\dll\().\actual"))
|
||||
\fn: .quad RVA((\dll\().\actual))
|
||||
.size \fn,.-\fn
|
||||
.globl \fn
|
||||
.hidden \fn
|
||||
.previous
|
||||
.section ".idata.ro.ilt.\dll\().2.\actual","a",@progbits
|
||||
"idata.ilt.\dll\().\actual":
|
||||
.quad RVA("\dll\().\actual")
|
||||
.type "idata.ilt.\dll\().\actual",@object
|
||||
.size "idata.ilt.\dll\().\actual",.-"idata.ilt.\dll\().\actual"
|
||||
.section .idata.ro.ilt.\dll\().2.\actual,"a",@progbits
|
||||
.Lidata.ilt.\dll\().\actual:
|
||||
.quad RVA((\dll\().\actual))
|
||||
.type .Lidata.ilt.\dll\().\actual,@object
|
||||
.size .Lidata.ilt.\dll\().\actual,.-.Lidata.ilt.\dll\().\actual
|
||||
.previous
|
||||
.section ".idata.ro.hnt.\dll\().2.\actual","a",@progbits
|
||||
"\dll\().\actual":
|
||||
.short 0 // hint
|
||||
.section .idata.ro.hnt.\dll\().2.\actual,"a",@progbits
|
||||
\dll\().\actual:
|
||||
.ifnb \hint # hint i.e. guess function ordinal
|
||||
.short \hint
|
||||
.else
|
||||
.short 0
|
||||
.endif
|
||||
.asciz "\actual"
|
||||
.align 2 // documented requirement
|
||||
.globl "\dll\().\actual"
|
||||
.hidden "\dll\().\actual"
|
||||
.type "\dll\().\actual",@object
|
||||
.size "\dll\().\actual",.-"\dll\().\actual"
|
||||
.align 2 # documented requirement
|
||||
.globl \dll\().\actual
|
||||
.hidden \dll\().\actual
|
||||
.type \dll\().\actual,@object
|
||||
.size \dll\().\actual,.-\dll\().\actual
|
||||
.previous
|
||||
#else
|
||||
.section ".data.nt.\actual","aw",@progbits
|
||||
.globl "\fn"
|
||||
.balign 8
|
||||
.weak "\actual"
|
||||
"\fn": .quad "\actual"
|
||||
#endif
|
||||
.endm
|
||||
|
||||
// Defines DLL import.
|
||||
// @note this is an implementation detail of .imp
|
||||
.macro .dll name:req
|
||||
.section ".idata.ro.idt.2.\name","aG",@progbits,"\name",comdat
|
||||
.equ ".Lidata.idt.\name",.
|
||||
.long RVA("idata.ilt.\name") // ImportLookupTable
|
||||
.long 0 // TimeDateStamp
|
||||
.long 0 // ForwarderChain
|
||||
.long RVA(".Lidata.str.\name") // DllNameRva
|
||||
.long RVA("idata.iat.\name") // ImportAddressTable
|
||||
.type ".Lidata.idt.\name",@object
|
||||
.size ".Lidata.idt.\name",.-".Lidata.idt.\name"
|
||||
.section .idata.ro.idt.2.\name,"aG",@progbits,\name,comdat
|
||||
.equ .Lidata.idt.\name,.
|
||||
.long RVA(idata.ilt.\name) # ImportLookupTable
|
||||
.long 0 # TimeDateStamp
|
||||
.long 0 # ForwarderChain
|
||||
.long RVA(.Lidata.str.\name) # DllNameRva
|
||||
.long RVA(idata.iat.\name) # ImportAddressTable
|
||||
.type .Lidata.idt.\name,@object
|
||||
.size .Lidata.idt.\name,.-.Lidata.idt.\name
|
||||
.previous
|
||||
.section ".idata.ro.ilt.\name\().1","aG",@progbits,"\name",comdat
|
||||
.balign __SIZEOF_POINTER__
|
||||
.type "idata.ilt.\name",@object
|
||||
"idata.ilt.\name":
|
||||
.section .idata.ro.ilt.\name\().1,"aG",@progbits,\name,comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.ilt.\name,@object
|
||||
idata.ilt.\name:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section ".idata.ro.ilt.\name\().3","aG",@progbits,"\name",comdat
|
||||
*/.section .idata.ro.ilt.\name\().3,"aG",@progbits,\name,comdat
|
||||
.quad 0
|
||||
.previous
|
||||
.section ".idata.ro.hnt.\name\().1","aG",@progbits,"\name",comdat
|
||||
.balign __SIZEOF_POINTER__
|
||||
.type "idata.hnt.\name",@object
|
||||
.equ "idata.hnt.\name",.
|
||||
.section .idata.ro.hnt.\name\().1,"aG",@progbits,\name,comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.hnt.\name,@object
|
||||
.equ idata.hnt.\name,.
|
||||
.previous
|
||||
.section ".piro.data.sort.iat.2.\name\().1","awG",@progbits,"\name",comdat
|
||||
.balign __SIZEOF_POINTER__
|
||||
.type "idata.iat.\name",@object
|
||||
"idata.iat.\name":
|
||||
.section .piro.data.sort.iat.2.\name\().1,"awG",@progbits,\name,comdat
|
||||
.align __SIZEOF_POINTER__
|
||||
.type idata.iat.\name,@object
|
||||
idata.iat.\name:
|
||||
.previous/*
|
||||
...
|
||||
decentralized content
|
||||
...
|
||||
*/.section ".piro.data.sort.iat.2.\name\().3","awG",@progbits,"\name",comdat
|
||||
*/.section .piro.data.sort.iat.2.\name\().3,"awG",@progbits,\name,comdat
|
||||
.quad 0
|
||||
.previous
|
||||
.section .rodata.str1.1,"aSM",@progbits,1
|
||||
".Lidata.str.\name":
|
||||
.Lidata.str.\name:
|
||||
.asciz "\name\().dll"
|
||||
.previous
|
||||
.endm
|
||||
|
|
90
ape/launch.S
90
ape/launch.S
|
@ -1,90 +0,0 @@
|
|||
/*-*- 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 │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
// Calls _start() function of loaded program.
|
||||
//
|
||||
// When the program entrypoint is called, all registers shall be
|
||||
// cleared, with the exception of (1) %rdi will be equal to %rsp
|
||||
// on FreeBSD and (2) %cl will contain the detected host OS code
|
||||
//
|
||||
// We clear all the general registers we can to have some wiggle
|
||||
// room, to extend the behavior of this loader in the future. We
|
||||
// don't need to clear the XMM registers because your APE loader
|
||||
// should be compiled using gcc/clang's -mgeneral-regs-only flag
|
||||
//
|
||||
// @param rdi is passed through as-is
|
||||
// @param rsi is address of entrypoint (becomes zero)
|
||||
// @param rdx is passed through as-is
|
||||
// @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 x1,0
|
||||
mov x4,0
|
||||
mov x5,0
|
||||
mov x6,0
|
||||
mov x7,0
|
||||
mov x8,0
|
||||
mov x9,0
|
||||
mov x10,0
|
||||
mov x11,0
|
||||
mov x12,0
|
||||
mov x13,0
|
||||
mov x14,0
|
||||
mov x15,0
|
||||
mov x17,0
|
||||
mov x19,0
|
||||
mov x20,0
|
||||
mov x21,0
|
||||
mov x22,0
|
||||
mov x23,0
|
||||
mov x24,0
|
||||
mov x25,0
|
||||
mov x26,0
|
||||
mov x27,0
|
||||
mov x28,0
|
||||
mov x29,0
|
||||
mov x30,0
|
||||
br x16
|
||||
|
||||
#else
|
||||
|
||||
mov %r8,%rsp
|
||||
xor %r8d,%r8d
|
||||
xor %r9d,%r9d
|
||||
xor %r10d,%r10d
|
||||
xor %r11d,%r11d
|
||||
xor %r12d,%r12d
|
||||
xor %r13d,%r13d
|
||||
xor %r14d,%r14d
|
||||
xor %r15d,%r15d
|
||||
push %rsi
|
||||
xor %esi,%esi
|
||||
xor %ebp,%ebp
|
||||
xor %ebx,%ebx
|
||||
xor %eax,%eax
|
||||
ret
|
||||
|
||||
#endif
|
||||
.endfn Launch,globl
|
249
ape/loader-elf.S
Normal file
249
ape/loader-elf.S
Normal file
|
@ -0,0 +1,249 @@
|
|||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/elf/def.h"
|
||||
#include "libc/sysv/consts/prot.h"
|
||||
#include "libc/macho.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/macros.internal.h"
|
||||
|
||||
// APE Loader Executable Structure
|
||||
// Linux, FreeBSD, NetBSD, OpenBSD
|
||||
|
||||
.align 8
|
||||
ehdr: .ascii "\177ELF"
|
||||
.byte ELFCLASS64
|
||||
.byte ELFDATA2LSB
|
||||
.byte 1
|
||||
.byte ELFOSABI_FREEBSD
|
||||
.quad 0
|
||||
.word ET_EXEC # e_type
|
||||
.word EM_NEXGEN32E # e_machine
|
||||
.long 1 # e_version
|
||||
.quad _start # e_entry
|
||||
.quad phdrs - ehdr # e_phoff
|
||||
.quad 0 # e_shoff
|
||||
.long 0 # e_flags
|
||||
.word 64 # e_ehsize
|
||||
.word 56 # e_phentsize
|
||||
.word 4 # e_phnum
|
||||
.word 0 # e_shentsize
|
||||
.word 0 # e_shnum
|
||||
.word 0 # e_shstrndx
|
||||
.endobj ehdr,globl
|
||||
|
||||
.align 8
|
||||
phdrs: .long PT_LOAD # p_type
|
||||
.long PF_R|PF_X # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad ehdr # p_vaddr
|
||||
.quad ehdr # p_paddr
|
||||
.quad filesz # p_filesz
|
||||
.quad filesz # p_memsz
|
||||
.quad PAGESIZE # p_align
|
||||
|
||||
.long PT_LOAD # p_type
|
||||
.long PF_R|PF_W # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad bss # p_vaddr
|
||||
.quad bss # p_paddr
|
||||
.quad 0 # p_filesz
|
||||
.quad bsssize # p_memsz
|
||||
.quad PAGESIZE # p_align
|
||||
|
||||
.long PT_GNU_STACK # p_type
|
||||
.long PF_R|PF_W # p_flags
|
||||
.quad 0 # p_offset
|
||||
.quad 0 # p_vaddr
|
||||
.quad 0 # p_paddr
|
||||
.quad 0 # p_filesz
|
||||
.quad 0 # p_memsz
|
||||
.quad 16 # p_align
|
||||
|
||||
.long PT_NOTE # p_type
|
||||
.long PF_R # p_flags
|
||||
.quad note - ehdr # p_offset
|
||||
.quad note # p_vaddr
|
||||
.quad note # p_paddr
|
||||
.quad notesize # p_filesz
|
||||
.quad notesize # p_memsz
|
||||
.quad 8 # p_align
|
||||
.endobj phdrs
|
||||
|
||||
note: .long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "OpenBSD"
|
||||
2: .align 4
|
||||
3: .long 0
|
||||
4: .long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "NetBSD"
|
||||
2: .align 4
|
||||
3: .long 901000000
|
||||
4: .endobj note
|
||||
notesize = . - note
|
||||
|
||||
.align 64,0 # for ape.S dd
|
||||
.org 0x180 # for ape.S dd
|
||||
|
||||
// APE Loader XNU Header
|
||||
//
|
||||
// This header is dd'd backwards by the APE shell script when
|
||||
// running on Mac OS X.
|
||||
//
|
||||
// @see ape/ape.S
|
||||
macho: .long 0xFEEDFACE+1
|
||||
.long MAC_CPU_NEXGEN32E
|
||||
.long MAC_CPU_NEXGEN32E_ALL
|
||||
.long MAC_EXECUTE
|
||||
.long 5 # number of load commands
|
||||
.long 60f-10f # size of all load commands
|
||||
.long MAC_NOUNDEFS # flags
|
||||
.long 0 # reserved
|
||||
10: .long MAC_LC_SEGMENT_64
|
||||
.long 20f-10b # unmaps first page dir
|
||||
.ascin "__PAGEZERO",16 # consistent with linux
|
||||
.quad 0,0x200000,0,0 # which forbids mem <2m
|
||||
.long 0,0,0,0
|
||||
20: .long MAC_LC_SEGMENT_64
|
||||
.long 30f-20b
|
||||
.ascin "__TEXT",16
|
||||
.quad ehdr # vaddr
|
||||
.quad 4096 # memsz
|
||||
.quad 0 # file offset
|
||||
.quad filesz # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_EXEC|PROT_READ # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
210: .ascin "__text",16 # section name (.text)
|
||||
.ascin "__TEXT",16
|
||||
.quad _start # vaddr
|
||||
.quad textsz # memsz
|
||||
.long textoff # offset
|
||||
.long 6 # align 2**6 = 64
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ATTR_SOME_INSTRUCTIONS # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
30: .long MAC_LC_SEGMENT_64
|
||||
.long 40f-30b
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.quad 0 # offset
|
||||
.quad 0 # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_READ|PROT_WRITE # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
310: .ascin "__bss",16 # section name (.bss)
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.long 0 # offset
|
||||
.long 12 # align 2**12 = 4096
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ZEROFILL # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
40: .long MAC_LC_UUID
|
||||
.long 50f-40b
|
||||
.quad 0x3fb29ee4ac6c87aa # uuid1
|
||||
.quad 0xdd2c9bb866d9eef8 # uuid2
|
||||
50: .long MAC_LC_UNIXTHREAD
|
||||
.long 60f-50b # cmdsize
|
||||
.long MAC_THREAD_NEXGEN32E # flavaflav
|
||||
.long (520f-510f)/4 # count
|
||||
510: .quad 0 # rax
|
||||
.quad 0 # rbx
|
||||
.quad 0 # rcx
|
||||
.quad XNU # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
.quad 0 # rbp
|
||||
.quad 0 # rsp
|
||||
.quad 0 # r8
|
||||
.quad 0 # r9
|
||||
.quad 0 # r10
|
||||
.quad 0 # r11
|
||||
.quad 0 # r12
|
||||
.quad 0 # r13
|
||||
.quad 0 # r14
|
||||
.quad 0 # r15
|
||||
.quad _start # rip
|
||||
.quad 0 # rflags
|
||||
.quad 0 # cs
|
||||
.quad 0 # fs
|
||||
.quad 0 # gs
|
||||
520:
|
||||
60:
|
||||
.endobj macho
|
||||
|
||||
.align 64,0 # for ape.S dd
|
||||
.org 0x400 # for ape.S dd
|
||||
|
||||
// Ape Loader Entrpoint
|
||||
//
|
||||
// This is normally called by the operating system. However it may
|
||||
// be called by the Actually Portable Executables themselves, when
|
||||
// re-executing a program. Just do this:
|
||||
//
|
||||
// memcpy(0x200000, loader)
|
||||
// lea handoff(%rip),%rcx
|
||||
// lea argblock(%rip),%rsp
|
||||
// jmp 0x200400
|
||||
//
|
||||
// @see APE_LOADER_ENTRY
|
||||
// @see ape/loader.h
|
||||
_start:
|
||||
|
||||
// Hack for detecting M1 Rosetta environment.
|
||||
// https://github.com/jart/cosmopolitan/issues/429#issuecomment-1166704377
|
||||
cmp $-1,%ebx
|
||||
jne 0f
|
||||
cmp $+1,%edx
|
||||
jne 0f
|
||||
mov $XNU,%dl
|
||||
xor %ecx,%ecx
|
||||
|
||||
0: mov %rsp,%rsi
|
||||
jmp ApeLoader
|
||||
.endfn _start,globl
|
||||
|
||||
// System Call Entrpoint
|
||||
//
|
||||
// This function is used by the APE loader to make system calls.
|
||||
// We also pass a reference to this function to the APE binary's
|
||||
// _start() function. It's needed because on OpenBSD, msyscall()
|
||||
// restricts which pages can issue system calls, and it can only
|
||||
// be called once. Therefore if we want to be load and re-load a
|
||||
// binary multiple times without calling the system execve(), we
|
||||
// need to be able to handover the SYSCALL function. We hardcode
|
||||
// this to a fixed address, but that shouldn't be used, since we
|
||||
// would ideally want to move it to a random page in the future.
|
||||
__syscall_loader:
|
||||
clc
|
||||
syscall
|
||||
jc 1f
|
||||
ret
|
||||
1: neg %rax
|
||||
ret
|
||||
.endfn __syscall_loader,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 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
|
@ -16,80 +16,123 @@
|
|||
│ 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
|
||||
// There must exist a MAC_LC_SEGMENT_64 for every PT_LOAD
|
||||
// APE Loader Executable Structure for XNU
|
||||
|
||||
.section .macho,"a",@progbits
|
||||
.balign 64
|
||||
.long 0xFEEDFACE+1
|
||||
.align 4096
|
||||
macho: .long 0xFEEDFACE+1
|
||||
.long MAC_CPU_NEXGEN32E
|
||||
.long MAC_CPU_NEXGEN32E_ALL
|
||||
.long MAC_EXECUTE
|
||||
.long 5 // number of load commands
|
||||
.long 60f-10f // size of all load commands
|
||||
.long MAC_NOUNDEFS|MAC_SPLIT_SEGS // flags
|
||||
.long 0 // reserved
|
||||
.long 5 # number of load commands
|
||||
.long 60f-10f # size of all load commands
|
||||
.long MAC_NOUNDEFS # flags
|
||||
.long 0 # reserved
|
||||
10: .long MAC_LC_SEGMENT_64
|
||||
.long 20f-10b // unmaps first page dir
|
||||
.ascin "__PAGEZERO",16 // consistent with linux
|
||||
.quad 0,0x200000,0,0 // which forbids mem <2m
|
||||
.long 20f-10b # unmaps first page dir
|
||||
.ascin "__PAGEZERO",16 # consistent with linux
|
||||
.quad 0,0x200000,0,0 # which forbids mem <2m
|
||||
.long 0,0,0,0
|
||||
20: .long MAC_LC_SEGMENT_64
|
||||
.long 30f-20b
|
||||
.ascin "__TEXT",16
|
||||
.quad 0 // vaddr
|
||||
.quad 0 // memsz
|
||||
.quad 0 // file offset
|
||||
.quad 0 // file size
|
||||
.long 0 // maxprot
|
||||
.long 0 // initprot
|
||||
.long 0 // segment section count
|
||||
.long 0 // flags
|
||||
.quad macho # vaddr
|
||||
.quad 4096 # memsz
|
||||
.quad 0 # file offset
|
||||
.quad filesz # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_EXEC|PROT_READ # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
210: .ascin "__text",16 # section name (.text)
|
||||
.ascin "__TEXT",16
|
||||
.quad _start # vaddr
|
||||
.quad textsz # memsz
|
||||
.long textoff # offset
|
||||
.long 6 # align 2**3 = 64
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ATTR_SOME_INSTRUCTIONS # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
30: .long MAC_LC_SEGMENT_64
|
||||
.long 40f-30b
|
||||
.ascin "__RODATA",16
|
||||
.quad 0 // vaddr
|
||||
.quad 0 // memsz
|
||||
.quad 0 // file offset
|
||||
.quad 0 // file size
|
||||
.long 0 // maxprot
|
||||
.long 0 // initprot
|
||||
.long 0 // segment section count
|
||||
.long 0 // flags
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.quad 0 # offset
|
||||
.quad 0 # file size
|
||||
.long PROT_EXEC|PROT_READ|PROT_WRITE # maxprot
|
||||
.long PROT_READ|PROT_WRITE # initprot
|
||||
.long 1 # segment section count
|
||||
.long 0 # flags
|
||||
310: .ascin "__bss",16 # section name (.bss)
|
||||
.ascin "__DATA",16
|
||||
.quad bss # vaddr
|
||||
.quad bsssize # memsz
|
||||
.long 0 # offset
|
||||
.long 12 # align 2**12 = 4096
|
||||
.long 0 # reloc table offset
|
||||
.long 0 # relocation count
|
||||
.long MAC_S_ZEROFILL # section type & attributes
|
||||
.long 0,0,0 # reserved
|
||||
40: .long MAC_LC_UUID
|
||||
.long 50f-40b
|
||||
.quad 0x4527148ba7a513ef // uuid1
|
||||
.quad 0x56fa865940665e8f // uuid2
|
||||
.quad 0x3fb29ee4ac6c87aa # uuid1
|
||||
.quad 0xdd2c9bb866d9eef8 # uuid2
|
||||
50: .long MAC_LC_UNIXTHREAD
|
||||
.long 60f-50b // cmdsize
|
||||
.long MAC_THREAD_NEXGEN32E // flavaflav
|
||||
.long (520f-510f)/4 // count
|
||||
510: .quad 0 // rax
|
||||
.quad 0 // rbx
|
||||
.quad 0 // rcx
|
||||
.quad 0 // rdx
|
||||
.quad 0 // rdi
|
||||
.quad 0 // rsi
|
||||
.quad 0 // rbp
|
||||
.quad 0 // rsp
|
||||
.quad 0 // r8
|
||||
.quad 0 // r9
|
||||
.quad 0 // r10
|
||||
.quad 0 // r11
|
||||
.quad 0 // r12
|
||||
.quad 0 // r13
|
||||
.quad 0 // r14
|
||||
.quad 0 // r15
|
||||
.quad XnuEntrypoint // rip
|
||||
.quad 0 // rflags
|
||||
.quad 0 // cs
|
||||
.quad 0 // fs
|
||||
.quad 0 // gs
|
||||
.long 60f-50b # cmdsize
|
||||
.long MAC_THREAD_NEXGEN32E # flavaflav
|
||||
.long (520f-510f)/4 # count
|
||||
510: .quad 0 # rax
|
||||
.quad 0 # rbx
|
||||
.quad 0 # rcx
|
||||
.quad XNU # rdx
|
||||
.quad 0 # rdi
|
||||
.quad 0 # rsi
|
||||
.quad 0 # rbp
|
||||
.quad 0 # rsp
|
||||
.quad 0 # r8
|
||||
.quad 0 # r9
|
||||
.quad 0 # r10
|
||||
.quad 0 # r11
|
||||
.quad 0 # r12
|
||||
.quad 0 # r13
|
||||
.quad 0 # r14
|
||||
.quad 0 # r15
|
||||
.quad _start # rip
|
||||
.quad 0 # rflags
|
||||
.quad 0 # cs
|
||||
.quad 0 # fs
|
||||
.quad 0 # gs
|
||||
520:
|
||||
60:
|
||||
.endobj macho,globl
|
||||
|
||||
.align 64
|
||||
_start:
|
||||
|
||||
// Hack for detecting M1 Rosetta environment.
|
||||
// https://github.com/jart/cosmopolitan/issues/429#issuecomment-1166704377
|
||||
cmp $-1,%ebx
|
||||
jne 0f
|
||||
cmp $+1,%edx
|
||||
jne 0f
|
||||
mov $XNU,%dl
|
||||
xor %ecx,%ecx
|
||||
|
||||
0: mov %rsp,%rsi
|
||||
jmp ApeLoader
|
||||
.endfn _start,globl
|
||||
|
||||
__syscall_loader:
|
||||
clc
|
||||
syscall
|
||||
jc 1f
|
||||
ret
|
||||
1: neg %rax
|
||||
ret
|
||||
.endfn __syscall_loader,globl
|
||||
|
|
42
ape/loader-macho.lds
Normal file
42
ape/loader-macho.lds
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
. = 0x200000;
|
||||
.text : {
|
||||
*(.text)
|
||||
*(.rodata .rodata.*)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
filesz = . - macho;
|
||||
textsz = . - _start;
|
||||
.bss ALIGN(4096) : {
|
||||
bss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
memsz = . - macho;
|
||||
/DISCARD/ : {
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
bsssize = SIZEOF(.bss);
|
||||
textoff = _start - macho;
|
1278
ape/loader.c
1278
ape/loader.c
File diff suppressed because it is too large
Load diff
20
ape/loader.h
Normal file
20
ape/loader.h
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef COSMOPOLITAN_APE_LOADER_H_
|
||||
#define COSMOPOLITAN_APE_LOADER_H_
|
||||
|
||||
#define APE_LOADER_BASE 0x200000
|
||||
#define APE_LOADER_SIZE 0x200000
|
||||
#define APE_LOADER_ENTRY 0x200400
|
||||
#define APE_LOADER_BSS (PAGESIZE * 2)
|
||||
#define APE_LOADER_STACK 0x7f0000000000
|
||||
#define APE_BLOCK_BASE 0x7e0000000000
|
||||
#define APE_BLOCK_SIZE 0x000200000000
|
||||
|
||||
struct ApeLoader {
|
||||
int fd;
|
||||
int os;
|
||||
char *prog;
|
||||
char *page;
|
||||
void *syscall;
|
||||
};
|
||||
|
||||
#endif /* COSMOPOLITAN_APE_LOADER_H_ */
|
|
@ -1,7 +1,7 @@
|
|||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
||||
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
|
@ -16,80 +16,28 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
|
||||
ENTRY(ElfEntrypoint)
|
||||
|
||||
PHDRS {
|
||||
text PT_LOAD FLAGS(1) FILEHDR PHDRS; /* PF_X */
|
||||
rodata PT_LOAD FLAGS(4); /* PF_R */
|
||||
stack PT_GNU_STACK FLAGS(6); /* PF_W|PF_R */
|
||||
note PT_NOTE FLAGS(4); /* PF_R */
|
||||
}
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS {
|
||||
|
||||
. = SEGMENT_START("text-segment", 0x7f000000);
|
||||
__executable_start = .;
|
||||
. += SIZEOF_HEADERS;
|
||||
|
||||
.macho : {
|
||||
KEEP(*(.macho))
|
||||
} :text
|
||||
|
||||
.note : {
|
||||
KEEP(*(.note))
|
||||
} :text :note
|
||||
|
||||
. = 0x200000;
|
||||
.text : {
|
||||
*(.text .text.* .gnu.linkonce.t.*)
|
||||
} :text
|
||||
|
||||
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
||||
*(.rodata .rodata.* .gnu.linkonce.r.*)
|
||||
} :rodata
|
||||
|
||||
.stack : {
|
||||
*(.stack)
|
||||
} :stack
|
||||
|
||||
*(.text)
|
||||
*(.rodata .rodata.*)
|
||||
. = ALIGN(64);
|
||||
}
|
||||
filesz = . - ehdr;
|
||||
textsz = . - _start;
|
||||
.bss ALIGN(4096) : {
|
||||
bss = .;
|
||||
*(.bss)
|
||||
. = ALIGN(4096);
|
||||
}
|
||||
_end = .;
|
||||
|
||||
.stab 0 : { *(.stab) }
|
||||
.stabstr 0 : { *(.stabstr) }
|
||||
.stab.excl 0 : { *(.stab.excl) }
|
||||
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||
.stab.index 0 : { *(.stab.index) }
|
||||
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||
.debug 0 : { *(.debug) }
|
||||
.line 0 : { *(.line) }
|
||||
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||
.debug_aranges 0 : { *(.debug_aranges) }
|
||||
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||
.debug_frame 0 : { *(.debug_frame) }
|
||||
.debug_str 0 : { *(.debug_str) }
|
||||
.debug_loc 0 : { *(.debug_loc) }
|
||||
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||
.debug_typenames 0 : { *(.debug_typenames) }
|
||||
.debug_varnames 0 : { *(.debug_varnames) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.debug_ranges 0 : { *(.debug_ranges) }
|
||||
.debug_macro 0 : { *(.debug_macro) }
|
||||
.debug_addr 0 : { *(.debug_addr) }
|
||||
.debug_loclists 0 : { *(.debug_loclists) }
|
||||
.debug_rnglists 0 : { *(.debug_rnglists) }
|
||||
.debug_line_str 0 : { *(.debug_line_str) }
|
||||
.debug_extra 0 : { *(.debug_line_str) }
|
||||
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||
|
||||
memsz = _end - ehdr;
|
||||
/DISCARD/ : {
|
||||
*(.*)
|
||||
}
|
||||
}
|
||||
|
||||
bsssize = SIZEOF(.bss);
|
||||
textoff = _start - ehdr;
|
||||
|
|
|
@ -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
|
||||
|
@ -67,27 +180,12 @@
|
|||
.stub \name\()_bcs\n,long
|
||||
.endm
|
||||
|
||||
// Task State Segment Descriptor Entries.
|
||||
.macro .tssdescstub name:req
|
||||
.ifndef \name
|
||||
.weak \name
|
||||
.set \name,0
|
||||
.endif
|
||||
.ifndef \name\()_end
|
||||
.weak \name\()_end
|
||||
.set \name\()_end,0
|
||||
.endif
|
||||
.stub \name\()_desc_ent0,quad
|
||||
.stub \name\()_desc_ent1,quad
|
||||
.endm
|
||||
|
||||
/* 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 +197,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); \
|
||||
|
@ -123,47 +221,44 @@
|
|||
/**
|
||||
* Binary coded decimal support.
|
||||
*
|
||||
* <p>This allows linker scripts to generate dd commands, e.g. ape.lds.
|
||||
* There are a few ways to pad each number to the necessary 8 bytes.
|
||||
* Spaces cannot be prepended because busybox refuses to parse them.
|
||||
* Zeros cannot be prepended because Mac will take numbers as octal.
|
||||
* That leaves appending spaces. The user's shell ought to treat any
|
||||
* unquoted run of spaces as if there was only one, so this is safe.
|
||||
* <p>This allows linker scripts to generate dd commands. Leading spaces
|
||||
* need to be inserted so Mac doesn't consider them octal; therefore,
|
||||
* parameters must be quoted; and eight digits should be good enough.
|
||||
*/
|
||||
#define SHSTUB2(SYM, X) \
|
||||
HIDDEN(SYM##_bcs0 = BCD_LEFT(X)); \
|
||||
HIDDEN(SYM##_bcs1 = BCD_RIGHT(X))
|
||||
#define BCD_SMEAR(X) ((X) + (X) * 10000)
|
||||
#define BCD_LEFT(X) \
|
||||
(((X)) < 10000 ? BCD_RIGHT(BCD_SMEAR(X)) | 0x10 \
|
||||
: (X) < 100000 ? BCD_RIGHT(BCD_SMEAR((X) / 10)) \
|
||||
: (X) < 1000000 ? BCD_RIGHT(BCD_SMEAR((X) / 100)) \
|
||||
: (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)
|
||||
|
||||
/**
|
||||
* Laying out the GDT entries for a TSS for bare metal operation.
|
||||
*/
|
||||
#define TSSDESCSTUB2(SYM, BASE, LIM) \
|
||||
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 | \
|
||||
((BASE) >> 24 << 56 & 0xff00000000000000))
|
||||
#define TSSDESC_ENT1(BASE) ((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
||||
#define SHSTUB2(SYM, X) \
|
||||
HIDDEN(SYM##_bcs0 = BCD10K(X)); \
|
||||
HIDDEN(SYM##_bcs1 = BCD(X))
|
||||
#define BCD(X) \
|
||||
((X) == 0 \
|
||||
? 0x20202030 \
|
||||
: (X) < 10 ? 0x30202020 + (((X) % 10) << 24) \
|
||||
: (X) < 100 ? 0x30302020 + (((X) % 10) << 24) + \
|
||||
(((X) / 10 % 10) << 16) \
|
||||
: (X) < 1000 ? 0x30303020 + (((X) % 10) << 24) + \
|
||||
(((X) / 10 % 10) << 16) + \
|
||||
(((X) / 100 % 10) << 8) \
|
||||
: 0x30303030 + (((X) % 10) << 24) + \
|
||||
(((X) / 10 % 10) << 16) + \
|
||||
(((X) / 100 % 10) << 8) + \
|
||||
(((X) / 1000 % 10) << 0))
|
||||
#define BCD10K(X) \
|
||||
((X) < 10000 \
|
||||
? 0x20202020 \
|
||||
: (X) < 100000 \
|
||||
? 0x30202020 + (((X) / 10000 % 10) << 24) \
|
||||
: (X) < 1000000 \
|
||||
? 0x30302020 + (((X) / 10000 % 10) << 24) + \
|
||||
(((X) / 100000 % 10) << 16) \
|
||||
: (X) < 10000000 \
|
||||
? 0x30303020 + (((X) / 10000 % 10) << 24) + \
|
||||
(((X) / 100000 % 10) << 16) + \
|
||||
(((X) / 1000000 % 10) << 8) \
|
||||
: (X) < 100000000 \
|
||||
? 0x30303030 + (((X) / 10000 % 10) << 24) + \
|
||||
(((X) / 100000 % 10) << 16) + \
|
||||
(((X) / 1000000 % 10) << 8) + \
|
||||
(((X) / 10000000 % 10) << 0) \
|
||||
: 0xffffffffffffffff)
|
||||
|
||||
#endif /* __ASSEMBLER__ */
|
||||
#endif /* APE_MACROS_H_ */
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
#include "ape/ape.lds"
|
|
@ -36,8 +36,8 @@
|
|||
*/
|
||||
#define REAL(x) ((x) - (IMAGE_BASE_VIRTUAL - IMAGE_BASE_REAL))
|
||||
|
||||
#if IMAGE_BASE_VIRTUAL % 0x1000 != 0
|
||||
#error "IMAGE_BASE_VIRTUAL must be 4kb aligned"
|
||||
#if IMAGE_BASE_VIRTUAL % 0x200000 != 0
|
||||
#error "IMAGE_BASE_VIRTUAL must be 2mb aligned"
|
||||
#endif
|
||||
#if IMAGE_BASE_PHYSICAL % 0x1000 != 0
|
||||
#error "IMAGE_BASE_PHYSICAL must be 4kb aligned"
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
#ifndef COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||
COSMOPOLITAN_C_START_
|
||||
|
||||
extern const char __notices[] __attribute__((__weak__));
|
||||
extern unsigned char __executable_start[] __attribute__((__weak__));
|
||||
extern unsigned char __privileged_start[] __attribute__((__weak__));
|
||||
extern unsigned char _ehead[] __attribute__((__weak__));
|
||||
extern unsigned char _etext[] __attribute__((__weak__));
|
||||
extern unsigned char _edata[] __attribute__((__weak__));
|
||||
extern unsigned char _ezip[] __attribute__((__weak__));
|
||||
extern unsigned char _end[] __attribute__((__weak__));
|
||||
extern unsigned char _ereal[] __attribute__((__weak__));
|
||||
extern unsigned char _tdata_start[] __attribute__((__weak__));
|
||||
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__));
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#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.
|
74
ape/start.S
74
ape/start.S
|
@ -1,74 +0,0 @@
|
|||
/*-*- 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 │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/dce.h"
|
||||
#include "ape/ape.h"
|
||||
#include "libc/macros.h"
|
||||
|
||||
#ifdef __aarch64__
|
||||
|
||||
_start: mov x1,sp
|
||||
and sp,x1,#-16
|
||||
mov x29,0
|
||||
bl ApeLoader
|
||||
.endfn _start,globl
|
||||
|
||||
#else
|
||||
|
||||
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
|
||||
|
||||
.section .note,"a",@progbits
|
||||
.balign 4
|
||||
openbsd.ident:
|
||||
.long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "OpenBSD"
|
||||
2: .balign 4
|
||||
3: .long 0
|
||||
4: .size openbsd.ident,.-openbsd.ident
|
||||
.type openbsd.ident,@object
|
||||
.balign 4
|
||||
netbsd.ident:
|
||||
.long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "NetBSD"
|
||||
2: .balign 4
|
||||
3: .long 901000000
|
||||
4: .size netbsd.ident,.-netbsd.ident
|
||||
.type netbsd.ident,@object
|
||||
.balign 4
|
||||
ape.ident:
|
||||
.long 2f-1f
|
||||
.long 4f-3f
|
||||
.long 1
|
||||
1: .asciz "APE"
|
||||
2: .balign 4
|
||||
3: .long APE_VERSION_NOTE
|
||||
4: .size ape.ident,.-ape.ident
|
||||
.type ape.ident,@object
|
||||
|
||||
#endif
|
|
@ -1,49 +0,0 @@
|
|||
/*-*- 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 │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/macros.h"
|
||||
|
||||
// Invokes system call.
|
||||
//
|
||||
// This function has eight parameters. The first seven are for
|
||||
// arguments passed along to the system call. The eight is for
|
||||
// the magic number that indicates which system call is called
|
||||
//
|
||||
// The return value follows the Linux kernel convention, where
|
||||
// errors are returned as `-errno`. BSD systems are normalized
|
||||
// to follow this convention automatically.
|
||||
SystemCall:
|
||||
#ifdef __aarch64__
|
||||
mov x8,x7
|
||||
mov x9,0
|
||||
adds x9,x9,0
|
||||
svc 0
|
||||
bcs 1f
|
||||
ret
|
||||
1: neg x0,x0
|
||||
ret
|
||||
#else
|
||||
mov %rcx,%r10
|
||||
mov 16(%rsp),%eax
|
||||
clc
|
||||
syscall
|
||||
jnc 1f
|
||||
neg %rax
|
||||
1: ret
|
||||
#endif
|
||||
.endfn SystemCall,globl
|
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.
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/package.com
Executable file
BIN
build/bootstrap/package.com
Executable file
Binary file not shown.
BIN
build/bootstrap/pwd.com
Executable file
BIN
build/bootstrap/pwd.com
Executable file
Binary file not shown.
BIN
build/bootstrap/rm.com
Executable file
BIN
build/bootstrap/rm.com
Executable file
Binary file not shown.
BIN
build/bootstrap/touch.com
Executable file
BIN
build/bootstrap/touch.com
Executable file
Binary file not shown.
BIN
build/bootstrap/unbundle.com
Executable file
BIN
build/bootstrap/unbundle.com
Executable file
Binary file not shown.
BIN
build/bootstrap/zipobj.com
Executable file
BIN
build/bootstrap/zipobj.com
Executable file
Binary file not shown.
386
build/config.mk
386
build/config.mk
|
@ -1,68 +1,23 @@
|
|||
#-*-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───────────────────────┘
|
||||
|
||||
# Default Mode
|
||||
#
|
||||
# - `make`
|
||||
# - Optimized
|
||||
# - Backtraces
|
||||
# - Syscall tracing
|
||||
# - Function tracing
|
||||
#
|
||||
# - Reasonably small
|
||||
# - Reasonably optimized
|
||||
# - Reasonably debuggable
|
||||
ifeq ($(MODE),)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
ifeq ($(MODE), x86_64)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
ifeq ($(MODE), aarch64)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
|
||||
# Zero Optimization Mode
|
||||
#
|
||||
# - Goes 2x slower
|
||||
# - Supports --strace
|
||||
# - Unsupports --ftrace
|
||||
# - Better GDB debugging
|
||||
#
|
||||
ifeq ($(MODE), zero)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
OVERRIDE_CFLAGS += -O0
|
||||
OVERRIDE_CXXFLAGS += -O0
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
ifeq ($(MODE), aarch64-zero)
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
OVERRIDE_CFLAGS += -O0 -fdce
|
||||
OVERRIDE_CXXFLAGS += -O0 -fdce
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||
endif
|
||||
|
||||
# Fast Build Mode
|
||||
#
|
||||
# - `make MODE=fastbuild`
|
||||
# - No debugging
|
||||
# - Syscall tracing
|
||||
# - Function tracing
|
||||
# - Some optimizations
|
||||
# - Limited Backtraces
|
||||
#
|
||||
ifeq ($(MODE), fastbuild)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DDWARFLESS
|
||||
CONFIG_LDFLAGS += -S
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-DSYSDEBUG \
|
||||
-O2
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
# Optimized Mode
|
||||
|
@ -76,17 +31,22 @@ endif
|
|||
# - No memory corruption detection
|
||||
# - assert() / CHECK_xx() may leak code into binary for debuggability
|
||||
# - GCC 8+ hoists check fails into .text.cold, thus minimizing impact
|
||||
#
|
||||
ifeq ($(MODE), opt)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O3 -fmerge-all-constants
|
||||
CONFIG_TARGET_ARCH ?= -march=native
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG \
|
||||
-msse2avx \
|
||||
-Wa,-msse2avx
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-DSYSDEBUG \
|
||||
-O3 \
|
||||
-fmerge-all-constants
|
||||
TARGET_ARCH ?= \
|
||||
-march=native
|
||||
endif
|
||||
|
||||
# Optimized Linux Mode
|
||||
# The Fastest Mode of All
|
||||
#
|
||||
# - `make MODE=optlinux`
|
||||
# - Turns on red zone
|
||||
|
@ -94,26 +54,18 @@ endif
|
|||
# - Turns off function tracing
|
||||
# - Turns off support for older cpu models
|
||||
# - Turns off support for other operating systems
|
||||
#
|
||||
ifeq ($(MODE), optlinux)
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
|
||||
CONFIG_COPTS += -mred-zone
|
||||
CONFIG_TARGET_ARCH ?= -march=native
|
||||
endif
|
||||
ifeq ($(MODE), x86_64-optlinux)
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
|
||||
CONFIG_COPTS += -mred-zone
|
||||
CONFIG_TARGET_ARCH ?= -march=native
|
||||
endif
|
||||
ifeq ($(MODE), aarch64-optlinux)
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
|
||||
CONFIG_COPTS += -mred-zone
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG \
|
||||
-msse2avx \
|
||||
-Wa,-msse2avx \
|
||||
-DSUPPORT_VECTOR=1
|
||||
CONFIG_CCFLAGS += \
|
||||
-O3 -fmerge-all-constants
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
TARGET_ARCH ?= \
|
||||
-march=native
|
||||
endif
|
||||
|
||||
# Release Mode
|
||||
|
@ -124,76 +76,68 @@ endif
|
|||
# - More optimized
|
||||
# - Reasonably small
|
||||
# - Numeric backtraces
|
||||
# - No DWARF data bloat
|
||||
# - Toilsome debuggability
|
||||
# - assert() statements removed
|
||||
# - DCHECK_xx() statements removed
|
||||
# - No memory corruption detection
|
||||
# - CHECK_xx() won't leak strings into binary
|
||||
#
|
||||
ifeq ($(MODE), rel)
|
||||
CONFIG_CPPFLAGS += -DNDEBUG -DDWARFLESS
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||
PYFLAGS += -O1
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DNDEBUG
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O2
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
PYFLAGS += \
|
||||
-O1
|
||||
endif
|
||||
|
||||
# Asan Mode
|
||||
#
|
||||
# Safer binaries good for backend production serving.
|
||||
#
|
||||
# - `make MODE=asan`
|
||||
# - Memory safety
|
||||
# - Production worthy
|
||||
# - Backtraces
|
||||
# - Debuggability
|
||||
# - Larger binaries
|
||||
ifeq ($(MODE), asan)
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
-O2
|
||||
CONFIG_COPTS += \
|
||||
-fsanitize=address
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
# Debug Mode
|
||||
#
|
||||
# - `make MODE=dbg`
|
||||
# - Backtraces
|
||||
# - Enables ubsan
|
||||
# - Enables asan
|
||||
# - Enables ubsan (TODO)
|
||||
# - Stack canaries
|
||||
# - No optimization
|
||||
# - No optimization (TODO)
|
||||
# - Enormous binaries
|
||||
#
|
||||
ifeq ($(MODE), dbg)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
OVERRIDE_CFLAGS += -O0
|
||||
OVERRIDE_CXXFLAGS += -O0
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__ -Wno-unused-variable -Wno-unused-but-set-variable
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG
|
||||
CONFIG_COPTS += -fsanitize=undefined
|
||||
OVERRIDE_CCFLAGS += -fno-pie
|
||||
QUOTA ?= -C64 -L300
|
||||
endif
|
||||
ifeq ($(MODE), x86_64-dbg)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
OVERRIDE_CFLAGS += -O0
|
||||
OVERRIDE_CXXFLAGS += -O0
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__ -Wno-unused-variable -Wno-unused-but-set-variable
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG
|
||||
CONFIG_COPTS += -fsanitize=undefined
|
||||
OVERRIDE_CCFLAGS += -fno-pie
|
||||
QUOTA ?= -C64 -L300
|
||||
endif
|
||||
ifeq ($(MODE), aarch64-dbg)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
OVERRIDE_CFLAGS += -O0 -fdce
|
||||
OVERRIDE_CXXFLAGS += -O0 -fdce
|
||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__ -Wno-unused-variable -Wno-unused-but-set-variable
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG
|
||||
CONFIG_COPTS += -fsanitize=undefined
|
||||
QUOTA ?= -C64 -L300
|
||||
endif
|
||||
|
||||
# System Five Mode
|
||||
#
|
||||
# - `make MODE=sysv`
|
||||
# - Optimized
|
||||
# - Backtraces
|
||||
# - Debuggable
|
||||
# - Syscall tracing
|
||||
# - Function tracing
|
||||
# - No Windows bloat!
|
||||
#
|
||||
ifeq ($(MODE), sysv)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_OFLAGS ?= -g -ggdb
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DMODE_DBG
|
||||
CONFIG_CCFLAGS += \
|
||||
$(BACKTRACES) \
|
||||
$(FTRACE) \
|
||||
-DSYSDEBUG \
|
||||
-O2 \
|
||||
-fno-inline
|
||||
CONFIG_COPTS += \
|
||||
-fsanitize=address \
|
||||
-fsanitize=undefined
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
OVERRIDE_CCFLAGS += \
|
||||
-fno-pie
|
||||
endif
|
||||
|
||||
# Tiny Mode
|
||||
|
@ -207,7 +151,6 @@ endif
|
|||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
#
|
||||
ifeq ($(MODE), tiny)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
|
@ -220,48 +163,11 @@ CONFIG_CCFLAGS += \
|
|||
-fno-align-labels \
|
||||
-fno-align-loops \
|
||||
-fschedule-insns2 \
|
||||
-fomit-frame-pointer \
|
||||
-momit-leaf-frame-pointer \
|
||||
-foptimize-sibling-calls \
|
||||
-DDWARFLESS
|
||||
PYFLAGS += \
|
||||
-O2 \
|
||||
-B
|
||||
endif
|
||||
ifeq ($(MODE), x86_64-tiny)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops \
|
||||
-fschedule-insns2 \
|
||||
-momit-leaf-frame-pointer \
|
||||
-foptimize-sibling-calls \
|
||||
-DDWARFLESS
|
||||
PYFLAGS += \
|
||||
-O2 \
|
||||
-B
|
||||
endif
|
||||
ifeq ($(MODE), aarch64-tiny)
|
||||
# TODO(jart): -mcmodel=tiny
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops \
|
||||
-fschedule-insns2 \
|
||||
-momit-leaf-frame-pointer \
|
||||
-foptimize-sibling-calls \
|
||||
-DDWARFLESS
|
||||
-foptimize-sibling-calls
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
PYFLAGS += \
|
||||
-O2 \
|
||||
-B
|
||||
|
@ -279,20 +185,22 @@ endif
|
|||
# - No portability
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
#
|
||||
ifeq ($(MODE), tinylinux)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=1 \
|
||||
-DDWARFLESS
|
||||
-DSUPPORT_VECTOR=1
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
# Linux+BSD Tiny Mode
|
||||
|
@ -308,20 +216,22 @@ endif
|
|||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
#
|
||||
ifeq ($(MODE), tinylinuxbsd)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=113 \
|
||||
-DDWARFLESS
|
||||
-DSUPPORT_VECTOR=113
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
# Unix Tiny Mode
|
||||
|
@ -336,20 +246,22 @@ endif
|
|||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
#
|
||||
ifeq ($(MODE), tinysysv)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=121 \
|
||||
-DDWARFLESS
|
||||
-DSUPPORT_VECTOR=121
|
||||
DEFAULT_COPTS += \
|
||||
-mred-zone
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
# Tiny Metallic Unix Mode
|
||||
|
@ -364,54 +276,26 @@ endif
|
|||
# - No backtraces
|
||||
# - No algorithmics
|
||||
# - YOLO
|
||||
#
|
||||
ifeq ($(MODE), tinynowin)
|
||||
CONFIG_CPPFLAGS += \
|
||||
-DTINY \
|
||||
-DNDEBUG \
|
||||
-DTRUSTWORTHY \
|
||||
-DSUPPORT_VECTOR=251 \
|
||||
-DDWARFLESS
|
||||
-DSUPPORT_VECTOR=251
|
||||
CONFIG_CCFLAGS += \
|
||||
-Os \
|
||||
-fno-align-functions \
|
||||
-fno-align-jumps \
|
||||
-fno-align-labels \
|
||||
-fno-align-loops
|
||||
endif
|
||||
|
||||
# no x87 instructions mode
|
||||
#
|
||||
# export MODE=nox87
|
||||
# make -j8 toolchain
|
||||
# cosmocc -o /tmp/hello.com hello.c
|
||||
#
|
||||
# lets you shave ~23kb off blink
|
||||
#
|
||||
# git clone https://github.com/jart/blink
|
||||
# cd blink
|
||||
# ./configure --disable-x87
|
||||
# make -j8
|
||||
# o//blink/blink /tmp/hello.com
|
||||
#
|
||||
ifeq ($(MODE), nox87)
|
||||
ENABLE_FTRACE = 1
|
||||
CONFIG_COPTS += -mlong-double-64
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DNOX87
|
||||
TARGET_ARCH ?= \
|
||||
-msse3
|
||||
endif
|
||||
|
||||
# LLVM Mode
|
||||
#
|
||||
# We aim to support:
|
||||
#
|
||||
# make -j8 m=llvm o/llvm/libc
|
||||
#
|
||||
# The rest of the monorepo may not work with llvm.
|
||||
#
|
||||
ifeq ($(MODE), llvm)
|
||||
.STRICT = 0
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O2
|
||||
TARGET_ARCH ?= -msse3
|
||||
CONFIG_CCFLAGS += $(BACKTRACES) $(FTRACE) -DSYSDEBUG -O2
|
||||
AS = clang
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
|
@ -449,66 +333,12 @@ endif
|
|||
# such as MSVC or XCode. You can run your binary objects through a tool
|
||||
# like objconv to convert them to COFF or MachO. Then use ANSI mode to
|
||||
# rollup one header file that'll enable linkage with minimal issues.
|
||||
|
||||
ifeq ($(MODE), ansi)
|
||||
|
||||
CONFIG_CFLAGS += -std=c11
|
||||
#CONFIG_CPPFLAGS += -ansi
|
||||
CONFIG_CXXFLAGS += -std=c++11
|
||||
endif
|
||||
TARGET_ARCH ?= -msse3
|
||||
|
||||
ifneq ($(ENABLE_FTRACE),)
|
||||
CONFIG_CPPFLAGS += -DFTRACE
|
||||
FTRACE_CCFLAGS = -fno-inline-functions-called-once
|
||||
OVERRIDE_CFLAGS += $(FTRACE_CCFLAGS)
|
||||
OVERRIDE_CXXFLAGS += $(FTRACE_CCFLAGS)
|
||||
# function prologue nops for --ftrace
|
||||
ifeq ($(ARCH), x86_64)
|
||||
# this flag causes gcc to generate functions like this
|
||||
#
|
||||
# nop nop nop nop nop nop nop nop nop
|
||||
# func:
|
||||
# nop nop
|
||||
# ...
|
||||
#
|
||||
# which tool/build/fixupobj.c improves at build time like this
|
||||
#
|
||||
# nop nop nop nop nop nop nop nop nop
|
||||
# func:
|
||||
# xchg %ax,%ax
|
||||
# ...
|
||||
#
|
||||
# which --ftrace morphs at runtime like this
|
||||
#
|
||||
# ud2 # 2 bytes
|
||||
# call ftrace_hook # 5 bytes
|
||||
# jmp +2 # 2 bytes
|
||||
# func:
|
||||
# jmp -7 # 2 bytes
|
||||
# ...
|
||||
#
|
||||
CONFIG_CCFLAGS += -fpatchable-function-entry=18,16
|
||||
endif
|
||||
ifeq ($(ARCH), aarch64)
|
||||
# this flag causes gcc to generate functions like this
|
||||
#
|
||||
# nop nop nop nop nop nop
|
||||
# func:
|
||||
# nop
|
||||
# ...
|
||||
#
|
||||
# which --ftrace morphs at runtime like this
|
||||
#
|
||||
# brk #31337
|
||||
# stp x29,x30,[sp,#-16]!
|
||||
# mov x29,sp
|
||||
# bl ftrace_hook
|
||||
# ldp x29,x30,[sp],#16
|
||||
# b +1
|
||||
# func:
|
||||
# b -5
|
||||
# ...
|
||||
#
|
||||
CONFIG_CCFLAGS += -fpatchable-function-entry=7,6
|
||||
endif
|
||||
endif
|
||||
|
||||
TARGET_ARCH ?= $(CONFIG_TARGET_ARCH)
|
||||
|
|
|
@ -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
|
||||
#
|
||||
|
@ -33,43 +33,98 @@
|
|||
#
|
||||
# VARIABLES
|
||||
#
|
||||
# Our configuration variables, ordered by increasing preference:
|
||||
#
|
||||
# CCFLAGS frontend flags (.i, .c, .cc, .f, .S, .lds, etc.)
|
||||
# OFLAGS objectify flags (precludes -S and -E)
|
||||
# CCFLAGS gcc frontend flags (.i, .c, .cc, .f, .S, .lds, etc.)
|
||||
# CPPFLAGS preprocessor flags (.h, .c, .cc, .S, .inc, .lds, etc.)
|
||||
# TARGET_ARCH microarchitecture flags (e.g. -march=native)
|
||||
# COPTS c/c++ flags (.c, .cc)
|
||||
# CFLAGS c flags (.c only)
|
||||
# CXXFLAGS c++ flags (.cc only)
|
||||
# COPTS c/c++ flags (.c, .cc)
|
||||
# LDFLAGS linker flags (don't use -Wl, frontend prefix)
|
||||
# ASFLAGS assembler flags (don't use -Wa, frontend prefix)
|
||||
#
|
||||
# For each FOO above, there exists (by increasing preference)
|
||||
#
|
||||
# DEFAULT_FOO see build/definitions.mk
|
||||
# CONFIG_FOO see build/config.mk
|
||||
# FOO set ~/.cosmo.mk and target-specific
|
||||
# OVERRIDE_FOO set ~/.cosmo.mk and target-specific (use rarely)
|
||||
#
|
||||
# TARGET_ARCH microarchitecture flags (e.g. -march=native)
|
||||
|
||||
ifeq ($(LANDLOCKMAKE_VERSION),)
|
||||
TMPSAFE = $(join $(TMPDIR)/,$(subst /,_,$@)).tmp
|
||||
LC_ALL = C
|
||||
SOURCE_DATE_EPOCH = 0
|
||||
|
||||
TAGS ?= /usr/bin/ctags # emacs source builds or something breaks it
|
||||
ARFLAGS = rcsD
|
||||
ZFLAGS ?=
|
||||
XARGS ?= xargs -P4 -rs8000
|
||||
DOT ?= dot
|
||||
CLANG = clang
|
||||
FC = gfortran #/opt/cross9f/bin/x86_64-linux-musl-gfortran
|
||||
TMPDIR = o/tmp
|
||||
|
||||
AR = build/bootstrap/ar.com
|
||||
CP = build/bootstrap/cp.com
|
||||
RM = build/bootstrap/rm.com -f
|
||||
ECHO = build/bootstrap/echo.com
|
||||
TOUCH = build/bootstrap/touch.com
|
||||
PKG = build/bootstrap/package.com
|
||||
MKDEPS = build/bootstrap/mkdeps.com
|
||||
ZIPOBJ = build/bootstrap/zipobj.com
|
||||
FIXUPOBJ = build/bootstrap/fixupobj.com
|
||||
MKDIR = build/bootstrap/mkdir.com -p
|
||||
COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
|
||||
SYMTAB = $(TMPDIR)/$(subst /,_,$@).symtab
|
||||
|
||||
COMMA := ,
|
||||
PWD := $(shell build/bootstrap/pwd.com)
|
||||
IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||
|
||||
IGNORE := $(shell $(ECHO) -2 ♥cosmo)
|
||||
IGNORE := $(shell $(MKDIR) o/tmp)
|
||||
|
||||
ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-pc-linux-gnu-as.exe)","")
|
||||
AS = o/third_party/gcc/bin/x86_64-pc-linux-gnu-as.exe
|
||||
CC = o/third_party/gcc/bin/x86_64-pc-linux-gnu-gcc.exe
|
||||
CXX = o/third_party/gcc/bin/x86_64-pc-linux-gnu-g++.exe
|
||||
CXXFILT = o/third_party/gcc/bin/x86_64-pc-linux-gnu-c++filt.exe
|
||||
LD = o/third_party/gcc/bin/x86_64-pc-linux-gnu-ld.bfd.exe
|
||||
NM = o/third_party/gcc/bin/x86_64-pc-linux-gnu-nm.exe
|
||||
GCC = o/third_party/gcc/bin/x86_64-pc-linux-gnu-gcc.exe
|
||||
STRIP = o/third_party/gcc/bin/x86_64-pc-linux-gnu-strip.exe
|
||||
OBJCOPY = o/third_party/gcc/bin/x86_64-pc-linux-gnu-objcopy.exe
|
||||
OBJDUMP = o/third_party/gcc/bin/x86_64-pc-linux-gnu-objdump.exe
|
||||
ADDR2LINE = $(PWD)/o/third_party/gcc/bin/x86_64-pc-linux-gnu-addr2line.exe
|
||||
else
|
||||
TMPSAFE = $(TMPDIR)/
|
||||
IGNORE := $(shell build/bootstrap/unbundle.com)
|
||||
AS = o/third_party/gcc/bin/x86_64-linux-musl-as
|
||||
CC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
|
||||
CXX = o/third_party/gcc/bin/x86_64-linux-musl-g++
|
||||
CXXFILT = o/third_party/gcc/bin/x86_64-linux-musl-c++filt
|
||||
LD = o/third_party/gcc/bin/x86_64-linux-musl-ld.bfd
|
||||
NM = o/third_party/gcc/bin/x86_64-linux-musl-nm
|
||||
GCC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
|
||||
STRIP = o/third_party/gcc/bin/x86_64-linux-musl-strip
|
||||
OBJCOPY = o/third_party/gcc/bin/x86_64-linux-musl-objcopy
|
||||
OBJDUMP = o/third_party/gcc/bin/x86_64-linux-musl-objdump
|
||||
ADDR2LINE = $(PWD)/o/third_party/gcc/bin/x86_64-linux-musl-addr2line
|
||||
endif
|
||||
|
||||
export ADDR2LINE
|
||||
export LC_ALL
|
||||
export MKDIR
|
||||
export MODE
|
||||
export SOURCE_DATE_EPOCH
|
||||
export TMPDIR
|
||||
|
||||
FTRACE = \
|
||||
-pg
|
||||
|
||||
BACKTRACES = \
|
||||
-fno-schedule-insns2 \
|
||||
-fno-omit-frame-pointer \
|
||||
-fno-optimize-sibling-calls \
|
||||
-mno-omit-leaf-frame-pointer
|
||||
|
||||
SANITIZER = \
|
||||
-fsanitize=address
|
||||
|
||||
NO_MAGIC = \
|
||||
-ffreestanding \
|
||||
-mno-fentry \
|
||||
-fno-stack-protector \
|
||||
-fwrapv \
|
||||
-fno-sanitize=all \
|
||||
-fpatchable-function-entry=0,0
|
||||
-fno-sanitize=all
|
||||
|
||||
OLD_CODE = \
|
||||
-fno-strict-aliasing \
|
||||
|
@ -80,99 +135,77 @@ TRADITIONAL = \
|
|||
-Wno-return-type \
|
||||
-Wno-pointer-sign
|
||||
|
||||
DEFAULT_CCFLAGS += \
|
||||
DEFAULT_CCFLAGS = \
|
||||
-Wall \
|
||||
-Werror \
|
||||
-fno-omit-frame-pointer \
|
||||
-fdebug-prefix-map='$(PWD)'= \
|
||||
-frecord-gcc-switches
|
||||
|
||||
DEFAULT_COPTS ?= \
|
||||
DEFAULT_OFLAGS = \
|
||||
-g \
|
||||
-gdescribe-dies
|
||||
|
||||
DEFAULT_COPTS = \
|
||||
-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
|
||||
|
||||
ifeq ($(ARCH), x86_64)
|
||||
# Microsoft says "[a]ny memory below the stack beyond the red zone
|
||||
# [note: Windows defines the x64 red zone size as 0] is considered
|
||||
# volatile and may be modified by the operating system at any time."
|
||||
# https://devblogs.microsoft.com/oldnewthing/20190111-00/?p=100685
|
||||
DEFAULT_COPTS += \
|
||||
-mno-red-zone \
|
||||
-fno-semantic-interposition \
|
||||
-mno-tls-direct-seg-refs
|
||||
endif
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
#
|
||||
# - Apple says in "Writing ARM64 code for Apple platforms" that we're
|
||||
# not allowed to use the x18 register.
|
||||
#
|
||||
# - Cosmopolitan Libc uses x28 for thread-local storage because Apple
|
||||
# forbids us from using tpidr_el0 too.
|
||||
#
|
||||
DEFAULT_COPTS += \
|
||||
-ffixed-x18 \
|
||||
-ffixed-x28 \
|
||||
-fsigned-char
|
||||
endif
|
||||
|
||||
MATHEMATICAL = \
|
||||
-O3 \
|
||||
-fwrapv
|
||||
|
||||
DEFAULT_CPPFLAGS += \
|
||||
-D_COSMO_SOURCE \
|
||||
DEFAULT_CPPFLAGS = \
|
||||
-DCOSMO \
|
||||
-DMODE='"$(MODE)"' \
|
||||
-Wno-prio-ctor-dtor \
|
||||
-Wno-unknown-pragmas \
|
||||
-DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) \
|
||||
-nostdinc \
|
||||
-iquote. \
|
||||
-isystem libc/isystem
|
||||
-iquote .
|
||||
|
||||
DEFAULT_CFLAGS = \
|
||||
-std=gnu23
|
||||
-std=gnu2x
|
||||
|
||||
DEFAULT_CXXFLAGS = \
|
||||
-std=gnu++23 \
|
||||
-fno-rtti \
|
||||
-fno-exceptions \
|
||||
-fuse-cxa-atexit \
|
||||
-fno-threadsafe-statics \
|
||||
-Wno-int-in-bool-context \
|
||||
-Wno-narrowing \
|
||||
-Wno-literal-suffix \
|
||||
-isystem third_party/libcxx
|
||||
-Wno-literal-suffix
|
||||
|
||||
DEFAULT_ASFLAGS = \
|
||||
-W \
|
||||
-I. \
|
||||
--noexecstack
|
||||
--noexecstack \
|
||||
--nocompress-debug-sections
|
||||
|
||||
DEFAULT_LDFLAGS = \
|
||||
-static \
|
||||
-nostdlib \
|
||||
-znorelro \
|
||||
-melf_x86_64 \
|
||||
--gc-sections \
|
||||
-z noexecstack \
|
||||
--build-id=none \
|
||||
--no-dynamic-linker
|
||||
--no-dynamic-linker \
|
||||
-zmax-page-size=0x1000 #--cref -Map=$@.map
|
||||
|
||||
# # generate linker report files
|
||||
# DEFAULT_LDFLAGS += --cref -Map=$@.map
|
||||
ZIPOBJ_FLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
ifeq ($(ARCH), aarch64)
|
||||
DEFAULT_LDFLAGS += \
|
||||
-zmax-page-size=0x4000 \
|
||||
-zcommon-page-size=0x4000 \
|
||||
-znorelro
|
||||
else
|
||||
DEFAULT_LDFLAGS += \
|
||||
-zmax-page-size=0x4000 \
|
||||
-zcommon-page-size=0x1000
|
||||
endif
|
||||
PYFLAGS = \
|
||||
-b$(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
ASONLYFLAGS = \
|
||||
-c \
|
||||
-g
|
||||
-g \
|
||||
--debug-prefix-map='$(PWD)'=
|
||||
|
||||
DEFAULT_LDLIBS =
|
||||
|
||||
|
@ -246,31 +279,40 @@ LD.libs = \
|
|||
$(CONFIG_LIBS) \
|
||||
$(LIBS)
|
||||
|
||||
COMPILE.c.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(c.flags)
|
||||
COMPILE.cxx.flags = $(cc.flags) $(copt.flags) $(cxx.flags) $(cpp.flags)
|
||||
COMPILE.c.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(c.flags)
|
||||
COMPILE.cxx.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(cxx.flags)
|
||||
COMPILE.f.flags = $(cc.flags) $(copt.flags) $(f.flags)
|
||||
COMPILE.F.flags = $(cc.flags) $(cpp.flags) $(copt.flags) $(f.flags)
|
||||
COMPILE.i.flags = $(cc.flags) $(copt.flags) $(c.flags)
|
||||
COMPILE.ii.flags = $(cc.flags) $(copt.flags) $(cxx.flags)
|
||||
LINK.flags = $(DEFAULT_LDFLAGS) $(CONFIG_LDFLAGS) $(LDFLAGS)
|
||||
OBJECTIFY.c.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(c.flags)
|
||||
OBJECTIFY.cxx.flags = $(cc.flags) $(o.flags) $(S.flags) $(cxx.flags) $(cpp.flags) $(copt.flags)
|
||||
OBJECTIFY.c.flags = $(OBJECTIFY.S.flags) $(copt.flags) $(c.flags)
|
||||
OBJECTIFY.cxx.flags = $(OBJECTIFY.S.flags) $(copt.flags) $(cxx.flags)
|
||||
OBJECTIFY.s.flags = $(ASONLYFLAGS) $(s.flags)
|
||||
OBJECTIFY.S.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags)
|
||||
OBJECTIFY.S.flags = $(copt.flags) $(cc.flags) $(o.flags) $(cpp.flags) $(S.flags)
|
||||
OBJECTIFY.f.flags = $(copt.flags) $(cc.flags) $(o.flags) $(copt.flags) $(S.flags) $(f.flags)
|
||||
OBJECTIFY.F.flags = $(OBJECTIFY.f.flags) $(cpp.flags)
|
||||
PREPROCESS.flags = -E $(copt.flags) $(cc.flags) $(cpp.flags)
|
||||
PREPROCESS.lds.flags = -D__LINKER__ $(filter-out -g%,$(PREPROCESS.flags)) -P -xc
|
||||
|
||||
COMPILE.c = $(CC) -S $(COMPILE.c.flags)
|
||||
COMPILE.cxx = $(CXX) -S $(COMPILE.cxx.flags)
|
||||
COMPILE.i = $(CC) -S $(COMPILE.i.flags)
|
||||
COMPILE.f = $(FC) -S $(COMPILE.f.flags)
|
||||
COMPILE.F = $(FC) -S $(COMPILE.F.flags)
|
||||
OBJECTIFY.s = $(AS) $(OBJECTIFY.s.flags)
|
||||
OBJECTIFY.S = $(CC) $(OBJECTIFY.S.flags) -c
|
||||
OBJECTIFY.f = $(FC) $(OBJECTIFY.f.flags) -c
|
||||
OBJECTIFY.F = $(FC) $(OBJECTIFY.F.flags) -c
|
||||
OBJECTIFY.c = $(CC) $(OBJECTIFY.c.flags) -c
|
||||
OBJECTIFY.cxx = $(CXX) $(OBJECTIFY.cxx.flags) -c
|
||||
PREPROCESS = $(CC) $(PREPROCESS.flags)
|
||||
PREPROCESS.lds = $(CC) $(PREPROCESS.lds.flags)
|
||||
LINK = $(LD) $(LINK.flags)
|
||||
ELF = o/libc/elf/elf.lds
|
||||
ELFLINK = $(COMPILE) -ALINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION) && $(COMPILE) -AFIXUP.ape -T$@ $(FIXUPOBJ) $@
|
||||
ELFLINK = $(COMPILE) -ALINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION)
|
||||
LINKARGS = $(patsubst %.lds,-T %.lds,$(call uniqr,$(LD.libs) $(filter-out %.pkg,$^)))
|
||||
LOLSAN = build/lolsan -b $(IMAGE_BASE_VIRTUAL)
|
||||
|
||||
# The compiler won't generate %xmm code for sources extensioned .greg.c,
|
||||
# which is needed for C modules wanting to run at the executive level or
|
||||
|
@ -285,9 +327,74 @@ OBJECTIFY.greg.c = \
|
|||
-fno-optimize-sibling-calls \
|
||||
-fno-sanitize=all \
|
||||
-ffreestanding \
|
||||
-mno-fentry \
|
||||
-fwrapv \
|
||||
-c
|
||||
|
||||
OBJECTIFY.ansi.c = $(CC) $(OBJECTIFY.c.flags) -ansi -Wextra -Werror -pedantic-errors -c
|
||||
OBJECTIFY.c99.c = $(CC) $(OBJECTIFY.c.flags) -std=c99 -Wextra -Werror -pedantic-errors -c
|
||||
OBJECTIFY.c11.c = $(CC) $(OBJECTIFY.c.flags) -std=c11 -Wextra -Werror -pedantic-errors -c
|
||||
OBJECTIFY.c2x.c = $(CC) $(OBJECTIFY.c.flags) -std=c2x -Wextra -Werror -pedantic-errors -c
|
||||
|
||||
OBJECTIFY.real.c = \
|
||||
$(GCC) \
|
||||
-x-no-pg \
|
||||
$(OBJECTIFY.c.flags) \
|
||||
-wrapper build/realify.sh \
|
||||
-D__REAL_MODE__ \
|
||||
-ffixed-r8 \
|
||||
-ffixed-r9 \
|
||||
-ffixed-r10 \
|
||||
-ffixed-r11 \
|
||||
-ffixed-r12 \
|
||||
-ffixed-r13 \
|
||||
-ffixed-r14 \
|
||||
-ffixed-r15 \
|
||||
-mno-red-zone \
|
||||
-fcall-used-rbx \
|
||||
-fno-jump-tables \
|
||||
-fno-shrink-wrap \
|
||||
-fno-schedule-insns2 \
|
||||
-flive-range-shrinkage \
|
||||
-fno-omit-frame-pointer \
|
||||
-momit-leaf-frame-pointer \
|
||||
-mpreferred-stack-boundary=3 \
|
||||
-fno-delete-null-pointer-checks \
|
||||
-c
|
||||
|
||||
OBJECTIFY.ncabi.c = \
|
||||
$(GCC) \
|
||||
$(OBJECTIFY.c.flags) \
|
||||
-mno-sse \
|
||||
-mfpmath=387 \
|
||||
-mno-fentry \
|
||||
-fno-stack-protector \
|
||||
-fno-instrument-functions \
|
||||
-fno-optimize-sibling-calls \
|
||||
-fno-sanitize=all \
|
||||
-fcall-saved-rcx \
|
||||
-fcall-saved-rdx \
|
||||
-fcall-saved-rdi \
|
||||
-fcall-saved-rsi \
|
||||
-fcall-saved-r8 \
|
||||
-fcall-saved-r9 \
|
||||
-fcall-saved-r10 \
|
||||
-fcall-saved-r11 \
|
||||
-c \
|
||||
-xc
|
||||
|
||||
OBJECTIFY.initabi.c = \
|
||||
$(GCC) \
|
||||
$(OBJECTIFY.c.flags) \
|
||||
-mno-fentry \
|
||||
-fno-stack-protector \
|
||||
-fno-instrument-functions \
|
||||
-fno-optimize-sibling-calls \
|
||||
-fno-sanitize=all \
|
||||
-fcall-saved-rdi \
|
||||
-fcall-saved-rsi \
|
||||
-c
|
||||
|
||||
TAGSFLAGS = \
|
||||
-e \
|
||||
-a \
|
||||
|
|
|
@ -1,106 +0,0 @@
|
|||
#!/bin/sh
|
||||
# cosmocc downloader script
|
||||
# https://justine.lol/cosmo3/#install
|
||||
# https://github.com/jart/cosmopolitan/blob/master/tool/cosmocc/README.md
|
||||
|
||||
# collect arguments
|
||||
OUTPUT_DIR=${1:?OUTPUT_DIR}
|
||||
COSMOCC_VERSION=${2:?COSMOCC_VERSION}
|
||||
COSMOCC_SHA256SUM=${3:?COSMOCC_SHA256SUM}
|
||||
URL1="https://github.com/jart/cosmopolitan/releases/download/${COSMOCC_VERSION}/cosmocc-${COSMOCC_VERSION}.zip"
|
||||
URL2="https://cosmo.zip/pub/cosmocc/cosmocc-${COSMOCC_VERSION}.zip"
|
||||
|
||||
# helper function
|
||||
abort() {
|
||||
printf '%s\n' "download terminated." >&2
|
||||
exit 1
|
||||
}
|
||||
|
||||
# exit if already downloaded
|
||||
# we need it because directory timestamps work wierdly
|
||||
OUTPUT_DIR=${OUTPUT_DIR%/}
|
||||
if [ -d "${OUTPUT_DIR}" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# find commands we need to securely download cosmocc
|
||||
if ! UNZIP=$(command -v unzip 2>/dev/null); then
|
||||
printf '%s\n' "$0: fatal error: you need the unzip command" >&2
|
||||
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/unzip and put it on the system path" >&2
|
||||
abort
|
||||
fi
|
||||
if command -v sha256sum >/dev/null 2>&1; then
|
||||
# can use system sha256sum
|
||||
true
|
||||
elif command -v shasum >/dev/null 2>&1; then
|
||||
sha256sum() {
|
||||
shasum -a 256 "$@"
|
||||
}
|
||||
else
|
||||
if [ ! -f build/sha256sum.c ]; then
|
||||
printf '%s\n' "$0: fatal error: you need to install sha256sum" >&2
|
||||
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/sha256sum and put it on the system path" >&2
|
||||
abort
|
||||
fi
|
||||
if ! SHA256SUM=$(command -v "$PWD/o/build/sha256sum" 2>/dev/null); then
|
||||
if ! CC=$(command -v "$CC" 2>/dev/null); then
|
||||
if ! CC=$(command -v cc 2>/dev/null); then
|
||||
if ! CC=$(command -v cosmocc 2>/dev/null); then
|
||||
printf '%s\n' "$0: fatal error: you need to install either sha256sum, cc, or cosmocc" >&2
|
||||
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/sha256sum and put it on the system path" >&2
|
||||
abort
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
mkdir -p o/build || abort
|
||||
SHA256SUM="$PWD/o/build/sha256sum"
|
||||
printf '%s\n' "${CC} -w -O2 -o ${SHA256SUM} build/sha256sum.c" >&2
|
||||
"${CC}" -w -O2 -o "${SHA256SUM}.$$" build/sha256sum.c || abort
|
||||
mv -f "${SHA256SUM}.$$" "${SHA256SUM}" || abort
|
||||
fi
|
||||
sha256sum() {
|
||||
"${SHA256SUM}" "$@"
|
||||
}
|
||||
fi
|
||||
if WGET=$(command -v wget 2>/dev/null); then
|
||||
DOWNLOAD=$WGET
|
||||
DOWNLOAD_ARGS=-O
|
||||
elif CURL=$(command -v curl 2>/dev/null); then
|
||||
DOWNLOAD=$CURL
|
||||
DOWNLOAD_ARGS=-fLo
|
||||
else
|
||||
printf '%s\n' "$0: fatal error: you need to install either wget or curl" >&2
|
||||
printf '%s\n' "please download https://cosmo.zip/pub/cosmos/bin/wget and put it on the system path" >&2
|
||||
abort
|
||||
fi
|
||||
|
||||
# create temporary output directory
|
||||
OLDPWD=$PWD
|
||||
OUTPUT_TMP="${OUTPUT_DIR}.tmp.$$/"
|
||||
mkdir -p "${OUTPUT_TMP}" || abort
|
||||
cd "${OUTPUT_TMP}"
|
||||
die() {
|
||||
cd "${OLDPWD}"
|
||||
rm -rf "${OUTPUT_TMP}"
|
||||
abort
|
||||
}
|
||||
|
||||
# download cosmocc toolchain
|
||||
# multiple urls avoids outages and national firewalls
|
||||
if ! "${DOWNLOAD}" ${DOWNLOAD_ARGS} cosmocc.zip "${URL1}"; then
|
||||
rm -f cosmocc.zip
|
||||
"${DOWNLOAD}" ${DOWNLOAD_ARGS} cosmocc.zip "${URL2}" || die
|
||||
fi
|
||||
printf '%s\n' "${COSMOCC_SHA256SUM} *cosmocc.zip" >cosmocc.zip.sha256sum
|
||||
sha256sum -c cosmocc.zip.sha256sum || die
|
||||
"${UNZIP}" cosmocc.zip || die
|
||||
rm -f cosmocc.zip cosmocc.zip.sha256sum
|
||||
|
||||
# commit output directory
|
||||
cd "${OLDPWD}" || die
|
||||
mv "${OUTPUT_TMP}" "${OUTPUT_DIR}" || die
|
||||
|
||||
# update current symlink
|
||||
BASE=$(basename "${OUTPUT_DIR}")
|
||||
DIR=$(dirname "${OUTPUT_DIR}")
|
||||
ln -sfn "$BASE" "$DIR/current"
|
|
@ -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
|
||||
#
|
||||
|
@ -12,9 +12,5 @@
|
|||
|
||||
tail = $(wordlist 2,$(words $1),$1)
|
||||
reverse = $(if $1,$(call reverse,$(call tail,$1)) $(firstword $1))
|
||||
uniqr = $(if $1,$(call uniqr,$(filter-out $(firstword $1),$1)) $(firstword $1))
|
||||
|
||||
# polyfill uniq native (landlock make 1.4)
|
||||
ifneq ($(call uniq,c b c a),c b a)
|
||||
uniq = $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1)))
|
||||
endif
|
||||
uniqr = $(if $1,$(call uniqr,$(filter-out $(firstword $1),$1)) $(firstword $1))
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
||||
#── vi: set et ft=sh ts=2 sts=2 fenc=utf-8 :vi ─────────────┘
|
||||
#───vi: set net ft=sh ts=2 sts=2 fenc=utf-8 :vi─────────────┘
|
||||
#
|
||||
# OVERVIEW
|
||||
#
|
||||
|
@ -43,9 +43,6 @@
|
|||
# '(progn
|
||||
# (add-hook 'c-mode-common-hook 'jart-c-mode-common-hook)))
|
||||
|
||||
TAGS="$1"
|
||||
shift
|
||||
|
||||
# ctags doesn't understand atomics, e.g.
|
||||
# extern char **environ;
|
||||
set -- --regex-c='/_Atomic(\([^)]*\))/\1/b' "$@"
|
||||
|
@ -55,7 +52,7 @@ set -- --regex-c='/_Atomic(\([^)]*\))/\1/b' "$@"
|
|||
set -- --regex-c='/^\(\(hidden\|extern\|const\) \)*[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)/\4/b' "$@"
|
||||
|
||||
# ctags doesn't understand function prototypes, e.g.
|
||||
# bool isheap(void *p) dontthrow dontcallback;
|
||||
# bool isheap(void *p) dontthrow nocallback;
|
||||
set -- --regex-c='/^[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)(.*/\2/b' "$@"
|
||||
|
||||
# ctags doesn't understand function pointers, e.g.
|
||||
|
@ -66,7 +63,7 @@ set -- --regex-c='/^extern [^(]*(\*const \([^)]*\))(/\1/b' "$@"
|
|||
# struct WorstSoftwareEver;
|
||||
set -- --regex-c='/^struct.*;$/uehocruehcroue/b' "$@"
|
||||
|
||||
build/run $TAGS \
|
||||
exec ${TAGS:-ctags} \
|
||||
-e \
|
||||
--langmap=c:.c.h \
|
||||
--exclude=libc/nt/struct/imagefileheader.internal.h \
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
#!/bin/sh
|
||||
COSMO=${COSMO:-/opt/cosmo}
|
||||
|
||||
if [ -n "$OBJDUMP" ]; then
|
||||
exec "$OBJDUMP" "$@"
|
||||
fi
|
||||
|
||||
find_objdump() {
|
||||
if [ -x .cosmocc/3.9.2/bin/$1-linux-cosmo-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.9.2/bin/$1-linux-cosmo-objdump
|
||||
elif [ -x .cosmocc/3.9.2/bin/$1-linux-musl-objdump ]; then
|
||||
OBJDUMP=.cosmocc/3.9.2/bin/$1-linux-musl-objdump
|
||||
elif [ -x "$COSMO/.cosmocc/3.9.2/bin/$1-linux-cosmo-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.9.2/bin/$1-linux-cosmo-objdump"
|
||||
elif [ -x "$COSMO/.cosmocc/3.9.2/bin/$1-linux-musl-objdump" ]; then
|
||||
OBJDUMP="$COSMO/.cosmocc/3.9.2/bin/$1-linux-musl-objdump"
|
||||
else
|
||||
echo "error: toolchain not found (try running 'cosmocc --update' or 'make' in the cosmo monorepo)" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then
|
||||
find_objdump aarch64
|
||||
exec "$OBJDUMP" "$@"
|
||||
else
|
||||
find_objdump x86_64
|
||||
exec "$OBJDUMP" "$@"
|
||||
fi
|
|
@ -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
|
||||
#
|
||||
|
@ -22,14 +22,10 @@
|
|||
# - tool/build/runit.c
|
||||
# - tool/build/runitd.c
|
||||
|
||||
.PRECIOUS: o/$(MODE)/%.ok
|
||||
o/$(MODE)/%.ok: private .PLEDGE = stdio rpath wpath cpath proc fattr inet dns
|
||||
o/$(MODE)/%.ok: private .UNVEIL += r:/etc/resolv.conf
|
||||
o/$(MODE)/%.ok: \
|
||||
o/$(MODE)/tool/build/runit \
|
||||
o/$(MODE)/tool/build/runitd \
|
||||
o/$(MODE)/%
|
||||
.PRECIOUS: o/$(MODE)/%.com.ok
|
||||
o/$(MODE)/%.com.ok: .PLEDGE = stdio rpath wpath cpath proc fattr inet
|
||||
o/$(MODE)/%.com.ok: \
|
||||
o/$(MODE)/tool/build/runit.com \
|
||||
o/$(MODE)/tool/build/runitd.com \
|
||||
o/$(MODE)/%.com
|
||||
@$(COMPILE) -wATEST -tT$@ $^ $(HOSTS)
|
||||
|
||||
.PHONY:
|
||||
o/tiny/tool/build/runit:
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
#-*-mode:sed;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||
#── vi: et ft=sed ts=8 sw=8 fenc=utf-8 :vi ────────────────┘
|
||||
#───vi: et ft=sed ts=8 tw=8 fenc=utf-8 :vi─────────────────┘
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
|
|
212
build/rules.mk
212
build/rules.mk
|
@ -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
|
||||
#
|
||||
|
@ -16,15 +16,49 @@
|
|||
|
||||
MAKEFLAGS += --no-builtin-rules
|
||||
|
||||
MAKE_ZIPCOPY = $(COMPILE) -AZIPCOPY -wT$@ $(ZIPCOPY) $< $@
|
||||
ifneq ($(ARCH), aarch64)
|
||||
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@ && $(MAKE_ZIPCOPY)
|
||||
else
|
||||
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S $< $@ && $(MAKE_ZIPCOPY)
|
||||
endif
|
||||
o/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/%.o: o/%.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/%.s: %.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/%.s: o/%.S ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) $<
|
||||
o/%.o: %.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/%.o: o/%.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
|
||||
o/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/%.zip.o: o/% ; @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%: o/$(MODE)/%.dbg
|
||||
@$(MAKE_OBJCOPY)
|
||||
o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S -O binary $< $@
|
||||
o/$(MODE)/%.o: %.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.f ; @$(COMPILE) -AOBJECTIFY.f $(OBJECTIFY.f) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.F ; @$(COMPILE) -AOBJECTIFY.F $(OBJECTIFY.F) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.h: %.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
||||
o/$(MODE)/%.h: o/$(MODE)/%.c ; @$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
||||
o/$(MODE)/%.o: %.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.greg.o: %.greg.c ; @$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.initabi.o: %.initabi.c ; @$(COMPILE) -AOBJECTIFY.init $(OBJECTIFY.initabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.ncabi.o: %.ncabi.c ; @$(COMPILE) -AOBJECTIFY.nc $(OBJECTIFY.ncabi.c) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.real.o: %.c ; @$(COMPILE) -AOBJECTIFY.real $(OBJECTIFY.real.c) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.runs: o/$(MODE)/% ; @$(COMPILE) -ACHECK -wtT$@ $< $(TESTARGS)
|
||||
o/$(MODE)/%.zip.o: % ; @$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-gcc.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-gcc.asm: %.cc ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: %.c ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: %.cc ; @$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
|
||||
o/%.o: %.cc
|
||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/%.o: o/%.cc
|
||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/$(MODE)/%.o: %.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||
|
@ -34,144 +68,51 @@ o/$(MODE)/%.o: o/$(MODE)/%.c
|
|||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/$(MODE)/%.h: %.c
|
||||
@$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
||||
|
||||
o/$(MODE)/%.o: %.cc
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.cc
|
||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/$(MODE)/%.o: %.cpp
|
||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.lds: %.lds
|
||||
@$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||
|
||||
ifneq ($(ARCH), aarch64)
|
||||
o/$(MODE)/%.o: %.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.S
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||
else
|
||||
o/$(MODE)/%.o: %.S libc/empty.s
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.s) $(OUTPUT_OPTION) libc/empty.s
|
||||
o/$(MODE)/%.o: o/$(MODE)/%.S libc/empty.s
|
||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.s) $(OUTPUT_OPTION) libc/empty.s
|
||||
endif
|
||||
|
||||
o/$(MODE)/%.o: %.greg.c
|
||||
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/$(MODE)/%.greg.o: %.greg.c
|
||||
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||
|
||||
o/%.a:
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),$^)
|
||||
@$(COMPILE) -AARCHIVE -wT$@ $(AR) $(ARFLAGS) $@ @$(TMPDIR)/$(subst /,_,$@)
|
||||
|
||||
o/%.pkg:
|
||||
$(file >$(TMPSAFE).args,$(filter %.o,$^))
|
||||
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@).args,$(filter %.o,$^))
|
||||
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPDIR)/$(subst /,_,$@)
|
||||
|
||||
o/$(MODE)/%.pkg:
|
||||
$(file >$(TMPSAFE).args,$(filter %.o,$^))
|
||||
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
|
||||
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter %.o,$^))
|
||||
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPDIR)/$(subst /,_,$@)
|
||||
|
||||
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj
|
||||
@$(COMPILE) -wAPYOBJ o/$(MODE)/third_party/python/pyobj $(PYFLAGS) -o $@ $<
|
||||
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com
|
||||
@$(COMPILE) -wAPYOBJ o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<
|
||||
|
||||
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp
|
||||
@$(COMPILE) -wAPYCOMP o/$(MODE)/third_party/python/pycomp $(PYCFLAGS) -o $@ $<
|
||||
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp.com
|
||||
@$(COMPILE) -wAPYCOMP o/$(MODE)/third_party/python/pycomp.com $(PYCFLAGS) -o $@ $<
|
||||
|
||||
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac
|
||||
@$(COMPILE) -wALUAC o/$(MODE)/third_party/lua/luac -s -o $@ $<
|
||||
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com
|
||||
@$(COMPILE) -wALUAC o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||
|
||||
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean
|
||||
@$(COMPILE) -wALUA -tT$@ o/$(MODE)/tool/net/redbean $(LUAFLAGS) -i $<
|
||||
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean.com
|
||||
@$(COMPILE) -wALUA -tT$@ o/$(MODE)/tool/net/redbean.com $(LUAFLAGS) -i $<
|
||||
|
||||
o/$(MODE)/%: o/$(MODE)/%.com o/$(MODE)/tool/build/cp.com o/$(MODE)/tool/build/assimilate.com
|
||||
@$(COMPILE) -wACP -T$@ o/$(MODE)/tool/build/cp.com $< $@
|
||||
@$(COMPILE) -wAASSIMILATE -T$@ o/$(MODE)/tool/build/assimilate.com $@
|
||||
|
||||
################################################################################
|
||||
# LOCAL UNIT TESTS
|
||||
#
|
||||
# We always run unit tests as part of the normal `make` invocation. you
|
||||
# may override the $(TESTARGS) variable to do things such as enable the
|
||||
# benchmarking feature. For example:
|
||||
#
|
||||
# TESTARGS = -b
|
||||
#
|
||||
# May be specified in your ~/.cosmo.mk file. You can also use this to
|
||||
# enable things like function tracing. For example:
|
||||
#
|
||||
# TESTARGS = ----ftrace
|
||||
# .PLEDGE += prot_exec
|
||||
#
|
||||
# You could then run a command like:
|
||||
#
|
||||
# make -j8 o//test/libc/calls/openbsd_test.runs
|
||||
#
|
||||
# You need PROT_EXEC permission since ftrace morphs the binary. It's
|
||||
# also worth mentioning that the pledge command can simulate what
|
||||
# Landlock Make does:
|
||||
#
|
||||
# o//tool/build/pledge \
|
||||
# -v. -p 'stdio rpath wpath cpath tty prot_exec' \
|
||||
# o//test/libc/calls/openbsd_test \
|
||||
# ----ftrace
|
||||
#
|
||||
# This is useful in the event a test binary should run by itself, but
|
||||
# fails to run beneath Landlock Make. It's also useful sometimes to
|
||||
# override the verbosity when running tests:
|
||||
#
|
||||
# make V=5 TESTARGS=-b o//test/libc/calls/openbsd_test.runs
|
||||
#
|
||||
# This way, if for some reason a test should fail but calls exit(0),
|
||||
# then the stdout/stderr output, which would normally be suppressed,
|
||||
# will actually be displayed.
|
||||
# strict header checking
|
||||
# these rules are unsandboxed since they're kind of a sandboxing test themselves
|
||||
|
||||
o/$(MODE)/%.runs: o/$(MODE)/%
|
||||
@$(COMPILE) -ACHECK -wtT$@ $< $(TESTARGS)
|
||||
|
||||
################################################################################
|
||||
# ELF ZIP FILES
|
||||
#
|
||||
# zipobj lets us do fast incremental linking of compressed data.
|
||||
# it's nice because if we link a hundred binaries that use the time zone
|
||||
# database, then that database only needs to be DEFLATE'd once.
|
||||
|
||||
o/%.zip.o: o/%
|
||||
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.zip.o: %
|
||||
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%.zip.o: %
|
||||
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
# an issue with sandboxing arises when creating directory entries in the
|
||||
# zip file. we need the trailing slash (e.g. o//foo/.zip.o) but Landlock
|
||||
# Make avoids sandboxing directory names that have a trailing slash (so
|
||||
# they can be used to watch for deleted files, without creating overly
|
||||
# broad unveiling). such rules need to be written more explicitly.
|
||||
o/$(MODE)%/.zip.o: %
|
||||
@$(COMPILE) -wAZIPOBJ $(ZIPOBJ) $(ZIPOBJ_FLAGS) $(OUTPUT_OPTION) $<
|
||||
|
||||
################################################################################
|
||||
# STRICT HEADER CHECKING
|
||||
#
|
||||
# these rules are unsandboxed since they're already a sandboxing test,
|
||||
# and it would be too costly in terms of make latency to have every
|
||||
# header file depend on $(HDRS) and $(INCS).
|
||||
|
||||
o/%.h.ok: private .UNSANDBOXED = 1
|
||||
o/%.h.ok: .UNSANDBOXED = 1
|
||||
o/%.h.ok: %.h
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
|
||||
|
||||
o/$(MODE)/%.h.ok: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.h.ok: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.h.ok: %.h
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.c) -xc -g0 -o $@ $<
|
||||
|
||||
o/$(MODE)/%.hh.ok: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.hh.ok: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.hh.ok: %.hh
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
|
||||
|
@ -179,27 +120,6 @@ o/%.okk: .UNSANDBOXED = 1
|
|||
o/%.okk: %
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
|
||||
o/$(MODE)/%.okk: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.okk: .UNSANDBOXED = 1
|
||||
o/$(MODE)/%.okk: %
|
||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||
|
||||
################################################################################
|
||||
# EMACS ASSEMBLY GENERATION
|
||||
|
||||
o/$(MODE)/%-gcc.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-gcc.asm: %.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%-gcc.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-gcc.asm: %.cc
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
|
||||
|
||||
o/$(MODE)/%-clang.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-clang.asm: %.c
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) -S -g0 $(OUTPUT_OPTION) $<
|
||||
|
||||
# TODO(jart): Make intrinsics support Clang.
|
||||
o/$(MODE)/%-clang.asm: CC = $(CLANG)
|
||||
o/$(MODE)/%-clang.asm: private .UNSANDBOXED = 1
|
||||
o/$(MODE)/%-clang.asm: %.cc
|
||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.cxx) -S -g0 $(OUTPUT_OPTION) $<
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
#!/bin/sh
|
||||
UNAMEM=$(uname -m)
|
||||
UNAMES=$(uname -s)
|
||||
if [ x"$UNAMES" = x"Darwin" ] && [ x"$UNAMEM" = x"arm64" ]; then
|
||||
exec ape "$@"
|
||||
else
|
||||
exec rusage "$@"
|
||||
fi
|
|
@ -31,7 +31,7 @@ if [ ! -f /proc/sys/fs/binfmt_misc/status ]; then
|
|||
exit 0
|
||||
fi
|
||||
|
||||
if ! build/bootstrap/echo -n; then
|
||||
if ! build/bootstrap/echo.com -n; then
|
||||
cat <<'EOF' >&2
|
||||
|
||||
ERROR
|
||||
|
|
|
@ -1,455 +0,0 @@
|
|||
/*-*- 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 │
|
||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||
│ Copyright 2022 Justine Alexandra Roberts Tunney │
|
||||
│ │
|
||||
│ Permission to use, copy, modify, and/or distribute this software for │
|
||||
│ any purpose with or without fee is hereby granted, provided that the │
|
||||
│ above copyright notice and this permission notice appear in all copies. │
|
||||
│ │
|
||||
│ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL │
|
||||
│ WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED │
|
||||
│ WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE │
|
||||
│ AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL │
|
||||
│ DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR │
|
||||
│ PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER │
|
||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
// this file should not have dependencies, because everything will be
|
||||
// re-downloaded if the o/tool/sha256sum artifact becomes invalidated
|
||||
|
||||
#define PROG "sha256sum"
|
||||
#define USAGE \
|
||||
"\
|
||||
Usage: " PROG " [-?hbctw] [PATH...]\n\
|
||||
-h help\n\
|
||||
-c check mode\n\
|
||||
-b binary mode\n\
|
||||
-t textual mode\n\
|
||||
-w warning mode\n"
|
||||
|
||||
#define ROTR(a, b) (((a) >> (b)) | ((a) << (32 - (b))))
|
||||
#define CH(x, y, z) (((x) & (y)) ^ (~(x) & (z)))
|
||||
#define MAJ(x, y, z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z)))
|
||||
#define EP0(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
|
||||
#define EP1(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
|
||||
#define SIG0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ ((x) >> 3))
|
||||
#define SIG1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ ((x) >> 10))
|
||||
|
||||
struct Sha256Ctx {
|
||||
uint8_t data[64];
|
||||
uint32_t datalen;
|
||||
uint64_t bitlen;
|
||||
uint32_t state[8];
|
||||
};
|
||||
|
||||
static const uint32_t kSha256Tab[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, //
|
||||
0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, //
|
||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, //
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, //
|
||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, //
|
||||
0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, //
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, //
|
||||
0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, //
|
||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, //
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, //
|
||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, //
|
||||
0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, //
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, //
|
||||
0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, //
|
||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, //
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, //
|
||||
};
|
||||
|
||||
static bool g_warn;
|
||||
static char g_mode;
|
||||
static bool g_check;
|
||||
static int g_mismatches;
|
||||
|
||||
static void Sha256Transform(uint32_t state[8], const uint8_t data[64]) {
|
||||
unsigned i;
|
||||
uint32_t a, b, c, d, e, f, g, h, t1, t2, m[64];
|
||||
for (i = 0; i < 16; ++i, data += 4) {
|
||||
m[i] = (uint32_t)data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
|
||||
}
|
||||
for (; i < 64; ++i) {
|
||||
m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16];
|
||||
}
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
f = state[5];
|
||||
g = state[6];
|
||||
h = state[7];
|
||||
for (i = 0; i < 64; ++i) {
|
||||
t1 = h + EP1(e) + CH(e, f, g) + kSha256Tab[i] + m[i];
|
||||
t2 = EP0(a) + MAJ(a, b, c);
|
||||
h = g;
|
||||
g = f;
|
||||
f = e;
|
||||
e = d + t1;
|
||||
d = c;
|
||||
c = b;
|
||||
b = a;
|
||||
a = t1 + t2;
|
||||
}
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
state[5] += f;
|
||||
state[6] += g;
|
||||
state[7] += h;
|
||||
}
|
||||
|
||||
static void Sha256Init(struct Sha256Ctx *ctx) {
|
||||
ctx->datalen = 0;
|
||||
ctx->bitlen = 0;
|
||||
ctx->state[0] = 0x6a09e667;
|
||||
ctx->state[1] = 0xbb67ae85;
|
||||
ctx->state[2] = 0x3c6ef372;
|
||||
ctx->state[3] = 0xa54ff53a;
|
||||
ctx->state[4] = 0x510e527f;
|
||||
ctx->state[5] = 0x9b05688c;
|
||||
ctx->state[6] = 0x1f83d9ab;
|
||||
ctx->state[7] = 0x5be0cd19;
|
||||
}
|
||||
|
||||
static void Sha256Update(struct Sha256Ctx *ctx, const uint8_t *data,
|
||||
long size) {
|
||||
long i;
|
||||
for (i = 0; i < size; ++i) {
|
||||
ctx->data[ctx->datalen] = data[i];
|
||||
ctx->datalen++;
|
||||
if (ctx->datalen == 64) {
|
||||
Sha256Transform(ctx->state, ctx->data);
|
||||
ctx->bitlen += 512;
|
||||
ctx->datalen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Sha256Final(struct Sha256Ctx *ctx, uint8_t *hash) {
|
||||
long i;
|
||||
i = ctx->datalen;
|
||||
ctx->data[i++] = 0x80;
|
||||
if (ctx->datalen < 56) {
|
||||
memset(ctx->data + i, 0, 56 - i);
|
||||
} else {
|
||||
memset(ctx->data + i, 0, 64 - i);
|
||||
Sha256Transform(ctx->state, ctx->data);
|
||||
memset(ctx->data, 0, 56);
|
||||
}
|
||||
ctx->bitlen += ctx->datalen * 8;
|
||||
ctx->data[63] = ctx->bitlen;
|
||||
ctx->data[62] = ctx->bitlen >> 8;
|
||||
ctx->data[61] = ctx->bitlen >> 16;
|
||||
ctx->data[60] = ctx->bitlen >> 24;
|
||||
ctx->data[59] = ctx->bitlen >> 32;
|
||||
ctx->data[58] = ctx->bitlen >> 40;
|
||||
ctx->data[57] = ctx->bitlen >> 48;
|
||||
ctx->data[56] = ctx->bitlen >> 56;
|
||||
Sha256Transform(ctx->state, ctx->data);
|
||||
for (i = 0; i < 4; ++i) {
|
||||
hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0xff;
|
||||
hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0xff;
|
||||
hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0xff;
|
||||
hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0xff;
|
||||
hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0xff;
|
||||
hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0xff;
|
||||
hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0xff;
|
||||
hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
static char *FormatUint32(char *p, uint32_t x) {
|
||||
char t;
|
||||
size_t i, a, b;
|
||||
i = 0;
|
||||
do {
|
||||
p[i++] = x % 10 + '0';
|
||||
x = x / 10;
|
||||
} while (x > 0);
|
||||
p[i] = '\0';
|
||||
if (i) {
|
||||
for (a = 0, b = i - 1; a < b; ++a, --b) {
|
||||
t = p[a];
|
||||
p[a] = p[b];
|
||||
p[b] = t;
|
||||
}
|
||||
}
|
||||
return p + i;
|
||||
}
|
||||
|
||||
static char *FormatInt32(char *p, int32_t x) {
|
||||
if (x < 0)
|
||||
*p++ = '-', x = -(uint32_t)x;
|
||||
return FormatUint32(p, x);
|
||||
}
|
||||
|
||||
static size_t StrCat(char *dst, const char *src, size_t dsize) {
|
||||
size_t m, n = dsize;
|
||||
const char *p = dst;
|
||||
const char *q = src;
|
||||
while (n-- != 0 && *dst != '\0')
|
||||
dst++;
|
||||
m = dst - p;
|
||||
n = dsize - m;
|
||||
if (n-- == 0) {
|
||||
return m + strlen(src);
|
||||
}
|
||||
while (*src != '\0') {
|
||||
if (n != 0) {
|
||||
*dst++ = *src;
|
||||
n--;
|
||||
}
|
||||
src++;
|
||||
}
|
||||
*dst = '\0';
|
||||
return m + (src - q);
|
||||
}
|
||||
|
||||
static void GetOpts(int argc, char *argv[]) {
|
||||
int opt;
|
||||
g_mode = ' ';
|
||||
while ((opt = getopt(argc, argv, "?hbctw")) != -1) {
|
||||
switch (opt) {
|
||||
case 'w':
|
||||
g_warn = true;
|
||||
break;
|
||||
case 'c':
|
||||
g_check = true;
|
||||
break;
|
||||
case 't':
|
||||
g_mode = ' ';
|
||||
break;
|
||||
case 'b':
|
||||
g_mode = '*';
|
||||
break;
|
||||
case 'h':
|
||||
case '?':
|
||||
(void)write(1, USAGE, sizeof(USAGE) - 1);
|
||||
exit(0);
|
||||
default:
|
||||
(void)write(2, USAGE, sizeof(USAGE) - 1);
|
||||
exit(64);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Write(int fd, const char *s, ...) {
|
||||
va_list va;
|
||||
char buf[512];
|
||||
buf[0] = 0;
|
||||
va_start(va, s);
|
||||
do {
|
||||
StrCat(buf, s, sizeof(buf));
|
||||
} while ((s = va_arg(va, const char *)));
|
||||
va_end(va);
|
||||
(void)write(fd, buf, strlen(buf));
|
||||
}
|
||||
|
||||
static bool IsModeCharacter(char c) {
|
||||
switch (c) {
|
||||
case ' ':
|
||||
case '*':
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static bool IsSupportedPath(const char *path) {
|
||||
size_t i;
|
||||
for (i = 0;; ++i) {
|
||||
switch (path[i]) {
|
||||
case 0:
|
||||
if (i)
|
||||
return true;
|
||||
// fallthrough
|
||||
case '\r':
|
||||
case '\n':
|
||||
case '\\':
|
||||
Write(2, PROG, ": ", path, ": unsupported path\n", NULL);
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool GetDigest(const char *path, FILE *f, uint8_t digest[32]) {
|
||||
size_t got;
|
||||
uint8_t buf[512];
|
||||
struct Sha256Ctx ctx;
|
||||
Sha256Init(&ctx);
|
||||
while ((got = fread(buf, 1, sizeof(buf), f))) {
|
||||
Sha256Update(&ctx, buf, got);
|
||||
}
|
||||
if (ferror(f)) {
|
||||
Write(2, PROG, ": ", path, ": ", strerror(errno), "\n", NULL);
|
||||
return false;
|
||||
}
|
||||
Sha256Final(&ctx, digest);
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *CopyHex(char *s, const void *p, size_t n) {
|
||||
const char *d, *e;
|
||||
for (d = (const char *)p, e = d + n; d < e; ++d) {
|
||||
*s++ = "0123456789abcdef"[(*d >> 4) & 15];
|
||||
*s++ = "0123456789abcdef"[(*d >> 0) & 15];
|
||||
}
|
||||
*s = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
static bool ProduceDigest(const char *path, FILE *f) {
|
||||
char hexdigest[65];
|
||||
char mode[2] = {g_mode};
|
||||
unsigned char digest[32];
|
||||
if (!IsSupportedPath(path))
|
||||
return false;
|
||||
if (!GetDigest(path, f, digest))
|
||||
return false;
|
||||
CopyHex(hexdigest, digest, 32);
|
||||
Write(1, hexdigest, " ", mode, path, "\n", NULL);
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *Chomp(char *line) {
|
||||
size_t i;
|
||||
if (line) {
|
||||
for (i = strlen(line); i--;) {
|
||||
if (line[i] == '\r' || line[i] == '\n') {
|
||||
line[i] = '\0';
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
static int HexToInt(int c) {
|
||||
if ('0' <= c && c <= '9') {
|
||||
return c - '0';
|
||||
} else if ('a' <= c && c <= 'f') {
|
||||
return c - 'a' + 10;
|
||||
} else if ('A' <= c && c <= 'F') {
|
||||
return c - 'A' + 10;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
static bool CheckDigests(const char *path, FILE *f) {
|
||||
FILE *f2;
|
||||
bool k = true;
|
||||
int a, b, i, line;
|
||||
const char *path2, *status;
|
||||
uint8_t wantdigest[32], gotdigest[32];
|
||||
char buf[64 + 2 + PATH_MAX + 1 + 1], *p;
|
||||
for (line = 0; fgets(buf, sizeof(buf), f); ++line) {
|
||||
if (!*Chomp(buf))
|
||||
continue;
|
||||
for (p = buf, i = 0; i < 32; ++i) {
|
||||
if ((a = HexToInt(*p++ & 255)) == -1)
|
||||
goto InvalidLine;
|
||||
if ((b = HexToInt(*p++ & 255)) == -1)
|
||||
goto InvalidLine;
|
||||
wantdigest[i] = a << 4 | b;
|
||||
}
|
||||
if (*p++ != ' ')
|
||||
goto InvalidLine;
|
||||
if (!IsModeCharacter(*p++))
|
||||
goto InvalidLine;
|
||||
path2 = p;
|
||||
if (!*path2)
|
||||
goto InvalidLine;
|
||||
if (!IsSupportedPath(path2))
|
||||
continue;
|
||||
if ((f2 = fopen(path2, "rb"))) {
|
||||
if (GetDigest(path2, f2, gotdigest)) {
|
||||
if (!memcmp(wantdigest, gotdigest, 32)) {
|
||||
status = "OK";
|
||||
} else {
|
||||
status = "FAILED";
|
||||
++g_mismatches;
|
||||
k = false;
|
||||
}
|
||||
Write(1, path2, ": ", status, "\n", NULL);
|
||||
} else {
|
||||
k = false;
|
||||
}
|
||||
fclose(f2);
|
||||
} else {
|
||||
Write(2, PROG, ": ", path2, ": ", strerror(errno), "\n", NULL);
|
||||
k = false;
|
||||
}
|
||||
continue;
|
||||
InvalidLine:
|
||||
if (g_warn) {
|
||||
char linestr[12];
|
||||
FormatInt32(linestr, line + 1);
|
||||
Write(2, PROG, ": ", path, ":", linestr, ": ",
|
||||
"improperly formatted checksum line", "\n", NULL);
|
||||
}
|
||||
}
|
||||
if (ferror(f)) {
|
||||
Write(2, PROG, ": ", path, ": ", strerror(errno), "\n", NULL);
|
||||
k = false;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
|
||||
static bool Process(const char *path, FILE *f) {
|
||||
if (g_check) {
|
||||
return CheckDigests(path, f);
|
||||
} else {
|
||||
return ProduceDigest(path, f);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
int i;
|
||||
FILE *f;
|
||||
bool k = true;
|
||||
GetOpts(argc, argv);
|
||||
if (optind == argc) {
|
||||
f = stdin;
|
||||
k &= Process("-", f);
|
||||
} else {
|
||||
for (i = optind; i < argc; ++i) {
|
||||
if ((f = fopen(argv[i], "rb"))) {
|
||||
k &= Process(argv[i], f);
|
||||
fclose(f);
|
||||
} else {
|
||||
Write(2, PROG, ": ", argv[i], ": ", strerror(errno), "\n", NULL);
|
||||
k = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g_mismatches) {
|
||||
char ibuf[12];
|
||||
FormatInt32(ibuf, g_mismatches);
|
||||
Write(2, PROG, ": WARNING: ", ibuf, " computed checksum did NOT match\n",
|
||||
NULL);
|
||||
}
|
||||
return !k;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
---
|
||||
BasedOnStyle: Mozilla
|
||||
IndentWidth: 4
|
||||
ColumnLimit: 80
|
||||
---
|
||||
Language: Cpp
|
||||
AllowShortFunctionsOnASingleLine: false
|
||||
AlignTrailingComments: false
|
||||
AlignEscapedNewlines: DontAlign
|
||||
AlwaysBreakTemplateDeclarations: true
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
FixNamespaceComments: true
|
||||
---
|
55
ctl/BUILD.mk
55
ctl/BUILD.mk
|
@ -1,55 +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 ────────────────────┘
|
||||
|
||||
PKGS += CTL
|
||||
|
||||
CTL_ARTIFACTS += CTL_A
|
||||
CTL = $(CTL_A_DEPS) $(CTL_A)
|
||||
CTL_A = o/$(MODE)/ctl/ctl.a
|
||||
CTL_A_FILES := $(wildcard ctl/*)
|
||||
CTL_A_HDRS = $(filter %.h,$(CTL_A_FILES))
|
||||
CTL_A_SRCS = $(filter %.cc,$(CTL_A_FILES))
|
||||
CTL_A_OBJS = $(CTL_A_SRCS:%.cc=o/$(MODE)/%.o)
|
||||
|
||||
CTL_A_CHECKS = \
|
||||
$(CTL_A).pkg \
|
||||
$(CTL_A_HDRS:%=o/$(MODE)/%.okk) \
|
||||
|
||||
CTL_A_DIRECTDEPS = \
|
||||
LIBC_INTRIN \
|
||||
LIBC_MEM \
|
||||
LIBC_NEXGEN32E \
|
||||
LIBC_STDIO \
|
||||
LIBC_STR \
|
||||
THIRD_PARTY_DOUBLECONVERSION \
|
||||
THIRD_PARTY_GDTOA \
|
||||
THIRD_PARTY_LIBCXXABI \
|
||||
THIRD_PARTY_LIBUNWIND \
|
||||
|
||||
CTL_A_DEPS := $(call uniq,$(foreach x,$(CTL_A_DIRECTDEPS),$($(x))))
|
||||
|
||||
$(CTL_A): ctl/ \
|
||||
$(CTL_A).pkg \
|
||||
$(CTL_A_OBJS)
|
||||
|
||||
$(CTL_A).pkg: \
|
||||
$(CTL_A_OBJS) \
|
||||
$(foreach x,$(CTL_A_DIRECTDEPS),$($(x)_A).pkg)
|
||||
|
||||
$(CTL_A_OBJS): private \
|
||||
OVERRIDE_CXXFLAGS += \
|
||||
-Wframe-larger-than=4096 \
|
||||
-Walloca-larger-than=4096 \
|
||||
-ffunction-sections \
|
||||
-fdata-sections \
|
||||
-fexceptions \
|
||||
|
||||
CTL_LIBS = $(foreach x,$(CTL_ARTIFACTS),$($(x)))
|
||||
CTL_SRCS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_SRCS))
|
||||
CTL_HDRS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_HDRS))
|
||||
CTL_CHECKS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_CHECKS))
|
||||
CTL_OBJS = $(foreach x,$(CTL_ARTIFACTS),$($(x)_OBJS))
|
||||
$(CTL_OBJS): $(BUILD_FILES) ctl/BUILD.mk
|
||||
|
||||
.PHONY: o/$(MODE)/ctl
|
||||
o/$(MODE)/ctl: $(CTL_CHECKS)
|
5015
ctl/README.md
5015
ctl/README.md
File diff suppressed because it is too large
Load diff
|
@ -1,28 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ACCUMULATE_H_
|
||||
#define CTL_ACCUMULATE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class T>
|
||||
constexpr T
|
||||
accumulate(InputIt first, InputIt last, T init)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
init = init + *first;
|
||||
return init;
|
||||
}
|
||||
|
||||
template<class InputIt, class T, class BinaryOperation>
|
||||
constexpr T
|
||||
accumulate(InputIt first, InputIt last, T init, BinaryOperation op)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
init = op(init, *first);
|
||||
return init;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ACCUMULATE_H_
|
|
@ -1,55 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADD_LVALUE_REFERENCE_H_
|
||||
#define CTL_ADD_LVALUE_REFERENCE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct add_lvalue_reference
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct add_lvalue_reference<T&>
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct add_lvalue_reference<T&&>
|
||||
{
|
||||
typedef T& type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_lvalue_reference<void>
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_lvalue_reference<const void>
|
||||
{
|
||||
typedef const void type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_lvalue_reference<volatile void>
|
||||
{
|
||||
typedef volatile void type;
|
||||
};
|
||||
|
||||
template<>
|
||||
struct add_lvalue_reference<const volatile void>
|
||||
{
|
||||
typedef const volatile void type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using add_lvalue_reference_t = typename add_lvalue_reference<T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADD_LVALUE_REFERENCE_H_
|
|
@ -1,43 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADD_POINTER_H_
|
||||
#define CTL_ADD_POINTER_H_
|
||||
#include "remove_reference.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
// Primary template
|
||||
template<typename T>
|
||||
struct add_pointer
|
||||
{
|
||||
typedef typename remove_reference<T>::type* type;
|
||||
};
|
||||
|
||||
// Specialization for functions
|
||||
template<typename R, typename... Args>
|
||||
struct add_pointer<R(Args...)>
|
||||
{
|
||||
typedef R (*type)(Args...);
|
||||
};
|
||||
|
||||
// Specialization for function references
|
||||
template<typename R, typename... Args>
|
||||
struct add_pointer<R (&)(Args...)>
|
||||
{
|
||||
typedef R (*type)(Args...);
|
||||
};
|
||||
|
||||
// Specialization for rvalue references to functions
|
||||
template<typename R, typename... Args>
|
||||
struct add_pointer<R (&&)(Args...)>
|
||||
{
|
||||
typedef R (*type)(Args...);
|
||||
};
|
||||
|
||||
// Helper alias template (C++14 and later)
|
||||
template<typename T>
|
||||
using add_pointer_t = typename add_pointer<T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADD_POINTER_H_
|
|
@ -1,29 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADDRESSOF_H_
|
||||
#define CTL_ADDRESSOF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
T*
|
||||
addressof(T& arg) noexcept
|
||||
{
|
||||
return reinterpret_cast<T*>(
|
||||
&const_cast<char&>(reinterpret_cast<const volatile char&>(arg)));
|
||||
}
|
||||
|
||||
template<typename R, typename... Args>
|
||||
R (*addressof(R (*&arg)(Args...)) noexcept)
|
||||
(Args...)
|
||||
{
|
||||
return arg;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T*
|
||||
addressof(T&&) = delete;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADDRESSOF_H_
|
|
@ -1,24 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ADVANCE_H_
|
||||
#define CTL_ADVANCE_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class Distance>
|
||||
constexpr void
|
||||
advance(InputIt& it, Distance n)
|
||||
{
|
||||
while (n > 0) {
|
||||
--n;
|
||||
++it;
|
||||
}
|
||||
while (n < 0) {
|
||||
++n;
|
||||
--it;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ADVANCE_H_
|
20
ctl/all_of.h
20
ctl/all_of.h
|
@ -1,20 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ALL_OF_H_
|
||||
#define CTL_ALL_OF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class UnaryPredicate>
|
||||
constexpr bool
|
||||
all_of(InputIt first, InputIt last, UnaryPredicate p)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
if (!p(*first))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ALL_OF_H_
|
|
@ -1,94 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ALLOCATOR_H_
|
||||
#define CTL_ALLOCATOR_H_
|
||||
#include "bad_alloc.h"
|
||||
#include "integral_constant.h"
|
||||
#include "new.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
class allocator
|
||||
{
|
||||
public:
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using propagate_on_container_move_assignment = ctl::true_type;
|
||||
using is_always_equal = ctl::true_type;
|
||||
using pointer = T*;
|
||||
using const_pointer = const T*;
|
||||
using reference = T&;
|
||||
using const_reference = const T&;
|
||||
|
||||
constexpr allocator() noexcept = default;
|
||||
|
||||
constexpr allocator(const allocator&) noexcept = default;
|
||||
|
||||
template<class U>
|
||||
constexpr allocator(const allocator<U>&) noexcept
|
||||
{
|
||||
}
|
||||
|
||||
constexpr ~allocator() = default;
|
||||
|
||||
[[nodiscard]] T* allocate(size_type n)
|
||||
{
|
||||
if (n > __SIZE_MAX__ / sizeof(T))
|
||||
throw ctl::bad_alloc();
|
||||
if (auto p = static_cast<T*>(::operator new(
|
||||
n * sizeof(T), ctl::align_val_t(alignof(T)), ctl::nothrow)))
|
||||
return p;
|
||||
throw ctl::bad_alloc();
|
||||
}
|
||||
|
||||
void deallocate(T* p, size_type n) noexcept
|
||||
{
|
||||
::operator delete(p, n * sizeof(T), ctl::align_val_t(alignof(T)));
|
||||
}
|
||||
|
||||
template<typename U, typename... Args>
|
||||
void construct(U* p, Args&&... args)
|
||||
{
|
||||
::new (static_cast<void*>(p)) U(ctl::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename U>
|
||||
void destroy(U* p)
|
||||
{
|
||||
p->~U();
|
||||
}
|
||||
|
||||
size_type max_size() const noexcept
|
||||
{
|
||||
return __SIZE_MAX__ / sizeof(T);
|
||||
}
|
||||
|
||||
allocator& operator=(const allocator&) = default;
|
||||
|
||||
template<typename U>
|
||||
struct rebind
|
||||
{
|
||||
using other = allocator<U>;
|
||||
};
|
||||
};
|
||||
|
||||
template<class T, class U>
|
||||
bool
|
||||
operator==(const allocator<T>&, const allocator<U>&) noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class T, class U>
|
||||
bool
|
||||
operator!=(const allocator<T>&, const allocator<U>&) noexcept
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ALLOCATOR_H_
|
|
@ -1,70 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ALLOCATOR_TRAITS_H_
|
||||
#define CTL_ALLOCATOR_TRAITS_H_
|
||||
#include "integral_constant.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename Alloc>
|
||||
struct allocator_traits
|
||||
{
|
||||
using allocator_type = Alloc;
|
||||
using value_type = typename Alloc::value_type;
|
||||
using pointer = typename Alloc::value_type*;
|
||||
using const_pointer = const typename Alloc::value_type*;
|
||||
using void_pointer = void*;
|
||||
using const_void_pointer = const void*;
|
||||
using difference_type = ptrdiff_t;
|
||||
using size_type = size_t;
|
||||
|
||||
using propagate_on_container_copy_assignment = ctl::false_type;
|
||||
using propagate_on_container_move_assignment = ctl::true_type;
|
||||
using propagate_on_container_swap = ctl::false_type;
|
||||
using is_always_equal = ctl::true_type;
|
||||
|
||||
template<typename T>
|
||||
struct rebind_alloc
|
||||
{
|
||||
using other = typename Alloc::template rebind<T>::other;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using rebind_traits = allocator_traits<typename rebind_alloc<T>::other>;
|
||||
|
||||
static pointer allocate(Alloc& a, size_type n)
|
||||
{
|
||||
return a.allocate(n);
|
||||
}
|
||||
|
||||
static void deallocate(Alloc& a, pointer p, size_type n)
|
||||
{
|
||||
a.deallocate(p, n);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static void construct(Alloc& a, T* p, Args&&... args)
|
||||
{
|
||||
::new ((void*)p) T(static_cast<Args&&>(args)...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static void destroy(Alloc& a, T* p)
|
||||
{
|
||||
p->~T();
|
||||
}
|
||||
|
||||
static size_type max_size(const Alloc& a) noexcept
|
||||
{
|
||||
return a.max_size();
|
||||
}
|
||||
|
||||
static Alloc select_on_container_copy_construction(const Alloc& a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ALLOCATOR_TRAITS_H_
|
20
ctl/any_of.h
20
ctl/any_of.h
|
@ -1,20 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ANY_OF_H_
|
||||
#define CTL_ANY_OF_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class UnaryPredicate>
|
||||
constexpr bool
|
||||
any_of(InputIt first, InputIt last, UnaryPredicate p)
|
||||
{
|
||||
for (; first != last; ++first)
|
||||
if (p(*first))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ANY_OF_H_
|
248
ctl/array.h
248
ctl/array.h
|
@ -1,248 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_ARRAY_H_
|
||||
#define CTL_ARRAY_H_
|
||||
#include "initializer_list.h"
|
||||
#include "out_of_range.h"
|
||||
#include "reverse_iterator.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T, size_t N>
|
||||
struct array
|
||||
{
|
||||
using value_type = T;
|
||||
using size_type = size_t;
|
||||
using difference_type = ptrdiff_t;
|
||||
using reference = value_type&;
|
||||
using const_reference = const value_type&;
|
||||
using pointer = value_type*;
|
||||
using const_pointer = const value_type*;
|
||||
using iterator = value_type*;
|
||||
using const_iterator = const value_type*;
|
||||
using reverse_iterator = ctl::reverse_iterator<iterator>;
|
||||
using const_reverse_iterator = ctl::reverse_iterator<const_iterator>;
|
||||
|
||||
T elems[N];
|
||||
|
||||
constexpr array() = default;
|
||||
|
||||
constexpr array(std::initializer_list<T> init)
|
||||
{
|
||||
auto it = init.begin();
|
||||
for (size_t i = 0; i < N && it != init.end(); ++i, ++it)
|
||||
elems[i] = *it;
|
||||
}
|
||||
|
||||
constexpr reference at(size_type pos)
|
||||
{
|
||||
if (pos >= N)
|
||||
throw ctl::out_of_range();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr const_reference at(size_type pos) const
|
||||
{
|
||||
if (pos >= N)
|
||||
throw ctl::out_of_range();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr reference operator[](size_type pos)
|
||||
{
|
||||
if (pos >= N)
|
||||
__builtin_trap();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr const_reference operator[](size_type pos) const
|
||||
{
|
||||
if (pos >= N)
|
||||
__builtin_trap();
|
||||
return elems[pos];
|
||||
}
|
||||
|
||||
constexpr reference front()
|
||||
{
|
||||
return elems[0];
|
||||
}
|
||||
|
||||
constexpr const_reference front() const
|
||||
{
|
||||
return elems[0];
|
||||
}
|
||||
|
||||
constexpr reference back()
|
||||
{
|
||||
return elems[N - 1];
|
||||
}
|
||||
|
||||
constexpr const_reference back() const
|
||||
{
|
||||
return elems[N - 1];
|
||||
}
|
||||
|
||||
constexpr T* data() noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr const T* data() const noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr iterator begin() noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr const_iterator begin() const noexcept
|
||||
{
|
||||
return elems;
|
||||
}
|
||||
|
||||
constexpr iterator end() noexcept
|
||||
{
|
||||
return elems + N;
|
||||
}
|
||||
|
||||
constexpr const_iterator end() const noexcept
|
||||
{
|
||||
return elems + N;
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rbegin() noexcept
|
||||
{
|
||||
return reverse_iterator(end());
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator rbegin() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(end());
|
||||
}
|
||||
|
||||
constexpr reverse_iterator rend() noexcept
|
||||
{
|
||||
return reverse_iterator(begin());
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator rend() const noexcept
|
||||
{
|
||||
return const_reverse_iterator(begin());
|
||||
}
|
||||
|
||||
constexpr const_iterator cbegin() const noexcept
|
||||
{
|
||||
return begin();
|
||||
}
|
||||
|
||||
constexpr const_iterator cend() const noexcept
|
||||
{
|
||||
return end();
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crbegin() const noexcept
|
||||
{
|
||||
return rbegin();
|
||||
}
|
||||
|
||||
constexpr const_reverse_iterator crend() const noexcept
|
||||
{
|
||||
return rend();
|
||||
}
|
||||
|
||||
constexpr bool empty() const noexcept
|
||||
{
|
||||
return N == 0;
|
||||
}
|
||||
|
||||
constexpr size_type size() const noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
constexpr size_type max_size() const noexcept
|
||||
{
|
||||
return N;
|
||||
}
|
||||
|
||||
void fill(const T& value)
|
||||
{
|
||||
for (size_type i = 0; i < N; ++i) {
|
||||
elems[i] = value;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(array& other) noexcept
|
||||
{
|
||||
for (size_type i = 0; i < N; ++i) {
|
||||
T temp = elems[i];
|
||||
elems[i] = other.elems[i];
|
||||
other.elems[i] = temp;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator==(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (!(lhs[i] == rhs[i]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator!=(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator<(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i) {
|
||||
if (lhs[i] < rhs[i])
|
||||
return true;
|
||||
if (rhs[i] < lhs[i])
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator<=(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return !(rhs < lhs);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator>(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return rhs < lhs;
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
bool
|
||||
operator>=(const array<T, N>& lhs, const array<T, N>& rhs)
|
||||
{
|
||||
return !(lhs < rhs);
|
||||
}
|
||||
|
||||
template<typename T, size_t N>
|
||||
void
|
||||
swap(array<T, N>& lhs, array<T, N>& rhs) noexcept
|
||||
{
|
||||
lhs.swap(rhs);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_ARRAY_H_
|
|
@ -1,64 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_BACK_INSERTER_H_
|
||||
#define CTL_BACK_INSERTER_H_
|
||||
#include "iterator.h"
|
||||
#include "utility.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class Container>
|
||||
class back_insert_iterator
|
||||
{
|
||||
protected:
|
||||
Container* container;
|
||||
|
||||
public:
|
||||
using iterator_category = ctl::output_iterator_tag;
|
||||
using value_type = void;
|
||||
using difference_type = void;
|
||||
using pointer = void;
|
||||
using reference = void;
|
||||
|
||||
explicit back_insert_iterator(Container& c) : container(&c)
|
||||
{
|
||||
}
|
||||
|
||||
back_insert_iterator& operator=(const typename Container::value_type& value)
|
||||
{
|
||||
container->push_back(value);
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator& operator=(typename Container::value_type&& value)
|
||||
{
|
||||
container->push_back(ctl::move(value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator& operator*()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator& operator++()
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
|
||||
back_insert_iterator operator++(int)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<class Container>
|
||||
back_insert_iterator<Container>
|
||||
back_inserter(Container& c)
|
||||
{
|
||||
return back_insert_iterator<Container>(c);
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_BACK_INSERTER_H_
|
|
@ -1,23 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_BAD_ALLOC_H_
|
||||
#define CTL_BAD_ALLOC_H_
|
||||
#include "exception.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
class bad_alloc : public ctl::exception
|
||||
{
|
||||
public:
|
||||
bad_alloc() noexcept = default;
|
||||
~bad_alloc() override = default;
|
||||
|
||||
const char* what() const noexcept override
|
||||
{
|
||||
return "ctl::bad_alloc";
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_BAD_ALLOC_H_
|
|
@ -1,25 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_CONDITIONAL_H_
|
||||
#define CTL_CONDITIONAL_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<bool B, class T, class F>
|
||||
struct conditional
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template<class T, class F>
|
||||
struct conditional<false, T, F>
|
||||
{
|
||||
typedef F type;
|
||||
};
|
||||
|
||||
template<bool B, typename T, typename F>
|
||||
using conditional_t = typename conditional<B, T, F>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_CONDITIONAL_H_
|
22
ctl/copy.h
22
ctl/copy.h
|
@ -1,22 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_COPY_H_
|
||||
#define CTL_COPY_H_
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<class InputIt, class OutputIt>
|
||||
OutputIt
|
||||
copy(InputIt first, InputIt last, OutputIt d_first)
|
||||
{
|
||||
while (first != last) {
|
||||
*d_first = *first;
|
||||
++d_first;
|
||||
++first;
|
||||
}
|
||||
return d_first;
|
||||
}
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_COPY_H_
|
36
ctl/decay.h
36
ctl/decay.h
|
@ -1,36 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_DECAY_H_
|
||||
#define CTL_DECAY_H_
|
||||
#include "add_pointer.h"
|
||||
#include "conditional.h"
|
||||
#include "is_array.h"
|
||||
#include "is_function.h"
|
||||
#include "remove_cv.h"
|
||||
#include "remove_extent.h"
|
||||
#include "remove_reference.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct decay
|
||||
{
|
||||
private:
|
||||
typedef typename ctl::remove_reference<T>::type U;
|
||||
|
||||
public:
|
||||
typedef typename ctl::conditional<
|
||||
ctl::is_array<U>::value,
|
||||
typename ctl::remove_extent<U>::type*,
|
||||
typename ctl::conditional<ctl::is_function<U>::value,
|
||||
typename ctl::add_pointer<U>::type,
|
||||
typename ctl::remove_cv<U>::type>::type>::type
|
||||
type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
using decay_t = typename decay<T>::type;
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_DECAY_H_
|
|
@ -1,44 +0,0 @@
|
|||
// -*-mode:c++;indent-tabs-mode:nil;c-basic-offset:4;tab-width:8;coding:utf-8-*-
|
||||
// vi: set et ft=cpp ts=4 sts=4 sw=4 fenc=utf-8 :vi
|
||||
#ifndef CTL_DEFAULT_DELETE_H_
|
||||
#define CTL_DEFAULT_DELETE_H_
|
||||
#include "enable_if.h"
|
||||
#include "is_convertible.h"
|
||||
|
||||
namespace ctl {
|
||||
|
||||
template<typename T>
|
||||
struct default_delete
|
||||
{
|
||||
constexpr default_delete() noexcept = default;
|
||||
template<typename U,
|
||||
typename = typename ctl::enable_if<
|
||||
ctl::is_convertible<U*, T*>::value>::type>
|
||||
constexpr default_delete(const default_delete<U>&) noexcept
|
||||
{
|
||||
}
|
||||
constexpr void operator()(T* const p) const noexcept
|
||||
{
|
||||
delete p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct default_delete<T[]>
|
||||
{
|
||||
constexpr default_delete() noexcept = default;
|
||||
template<typename U,
|
||||
typename = typename ctl::enable_if<
|
||||
ctl::is_convertible<U (*)[], T (*)[]>::value>::type>
|
||||
constexpr default_delete(const default_delete<U[]>&) noexcept
|
||||
{
|
||||
}
|
||||
constexpr void operator()(T* const p) const noexcept
|
||||
{
|
||||
delete[] p;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace ctl
|
||||
|
||||
#endif // CTL_DEFAULT_DELETE_H_
|
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