mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-08-04 08:50:27 +00:00
Compare commits
No commits in common. "master" and "nesemu1-1.2" have entirely different histories.
master
...
nesemu1-1.
14484 changed files with 459400 additions and 1143218 deletions
|
@ -6,8 +6,6 @@ AlignConsecutiveMacros: true
|
||||||
AlignConsecutiveDeclarations: false
|
AlignConsecutiveDeclarations: false
|
||||||
AlwaysBreakBeforeMultilineStrings: false
|
AlwaysBreakBeforeMultilineStrings: false
|
||||||
AllowShortFunctionsOnASingleLine: false
|
AllowShortFunctionsOnASingleLine: false
|
||||||
AllowShortLoopsOnASingleLine: false
|
|
||||||
AllowShortIfStatementsOnASingleLine: false
|
|
||||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
IncludeBlocks: Merge
|
IncludeBlocks: Merge
|
||||||
|
|
|
@ -1,31 +0,0 @@
|
||||||
# Run this command to always ignore formatting commits in git blame
|
|
||||||
# git config blame.ignoreRevsFile .git-blame-ignore-revs
|
|
||||||
|
|
||||||
# Upgraded clang-format to 19.0.0git
|
|
||||||
89fc95fefd40413706ff1bdaac2e8d98b328dbf1
|
|
||||||
# vim c++ filetype in modelines
|
|
||||||
04c6bc478e082263d67c41bedbd033dde2d429eb
|
|
||||||
# Ran clang-format
|
|
||||||
f032b5570b4cd87c6bb4abb54c0b98e69c939955
|
|
||||||
# Applied clang-format update to repo
|
|
||||||
6e6fc38935054db0534d5af4fb99c6193305b946
|
|
||||||
# revert retabbing
|
|
||||||
2b315626f3af765cdfbc61114647412cdb798b3a
|
|
||||||
# more modeline errata
|
|
||||||
3a8e01a77a7c97af0b16fb1651b230cee7f7d4c6
|
|
||||||
# fix more vi modelines
|
|
||||||
2fc507c98f53a76718f61f9a36602f86b5ac0cc9
|
|
||||||
# flip et/noet in modelines
|
|
||||||
e16a7d8f3b8f906c3ef76e79f57f3adfc7f25186
|
|
||||||
# fix vi modelines
|
|
||||||
394d998315f613a888cc6b6c051d4163bdf5cd6f
|
|
||||||
# clang-format
|
|
||||||
c0eacf2eb1e1c0b3bd4f71f12fef258f5b249c3f
|
|
||||||
# ape-m1 formatting cleanup
|
|
||||||
da8baf2aa5ce93b958aca90a0ae69f537806324b
|
|
||||||
# Run clang-format on most sources
|
|
||||||
369f9740de4534c28d0e81ab2afc99decbb9a3e6
|
|
||||||
# Get rid of .internal.h convention in LIBC_INTRIN
|
|
||||||
86d884cce24d773e298a2714c1e3d91ecab9be45
|
|
||||||
# Remove .internal from more header filenames
|
|
||||||
31194165d2afca36c2315a6e7ca2f0797dde09e3
|
|
9
.gitattributes
vendored
9
.gitattributes
vendored
|
@ -1,10 +1,5 @@
|
||||||
# -*- conf -*-
|
# -*- conf -*-
|
||||||
*.gz binary
|
*.gz binary
|
||||||
*.so binary
|
/build/bootstrap/*.com binary
|
||||||
*.dll binary
|
/build/bootstrap/*.com binary
|
||||||
*.dylib binary
|
|
||||||
/build/bootstrap/* binary
|
|
||||||
/usr/share/terminfo/* binary
|
|
||||||
/usr/share/terminfo/*/* binary
|
|
||||||
/usr/share/zoneinfo/* binary
|
/usr/share/zoneinfo/* binary
|
||||||
/usr/share/zoneinfo/*/* binary
|
|
||||||
|
|
59
.github/ISSUE_TEMPLATE/01-bug-low.yml
vendored
59
.github/ISSUE_TEMPLATE/01-bug-low.yml
vendored
|
@ -1,59 +0,0 @@
|
||||||
name: Low Severity Bugs
|
|
||||||
description: Used to report low severity bugs in cosmopolitan (e.g. cosmetic issues, non critical UI glitches)
|
|
||||||
title: "Bug: "
|
|
||||||
labels: ["bug", "low severity"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
Please include information about your system, the steps to reproduce the bug,
|
|
||||||
and the version of cosmopolitan that you are using.
|
|
||||||
If possible, please provide a minimal code example that reproduces the bug.
|
|
||||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
|
||||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
|
||||||
- type: input
|
|
||||||
id: contact
|
|
||||||
attributes:
|
|
||||||
label: Contact Details
|
|
||||||
description: How can we get in touch with you if we need more info?
|
|
||||||
placeholder: ex. email@example.com
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: what-happened
|
|
||||||
attributes:
|
|
||||||
label: What happened?
|
|
||||||
description: Also tell us, what did you expect to happen?
|
|
||||||
placeholder: Tell us what you see!
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: What version of our software are you running? (use `--version` to get a version string)
|
|
||||||
placeholder: "cosmocc (GCC) 12.3.0"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: operating-system
|
|
||||||
attributes:
|
|
||||||
label: What operating system are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Linux
|
|
||||||
- Mac
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
59
.github/ISSUE_TEMPLATE/02-bug-medium.yml
vendored
59
.github/ISSUE_TEMPLATE/02-bug-medium.yml
vendored
|
@ -1,59 +0,0 @@
|
||||||
name: Medium Severity Bug
|
|
||||||
description: Used to report medium severity bugs in cosmopolitan (e.g. Malfunctioning Features but generally still useable)
|
|
||||||
title: "Bug: "
|
|
||||||
labels: ["bug", "medium severity"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
Please include information about your system, the steps to reproduce the bug,
|
|
||||||
and the version of cosmopolitan that you are using.
|
|
||||||
If possible, please provide a minimal code example that reproduces the bug.
|
|
||||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
|
||||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
|
||||||
- type: input
|
|
||||||
id: contact
|
|
||||||
attributes:
|
|
||||||
label: Contact Details
|
|
||||||
description: How can we get in touch with you if we need more info?
|
|
||||||
placeholder: ex. email@example.com
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: what-happened
|
|
||||||
attributes:
|
|
||||||
label: What happened?
|
|
||||||
description: Also tell us, what did you expect to happen?
|
|
||||||
placeholder: Tell us what you see!
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: What version of our software are you running? (use `--version` to get a version string)
|
|
||||||
placeholder: "cosmocc (GCC) 12.3.0"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: operating-system
|
|
||||||
attributes:
|
|
||||||
label: What operating system are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Linux
|
|
||||||
- Mac
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
59
.github/ISSUE_TEMPLATE/03-bug-high.yml
vendored
59
.github/ISSUE_TEMPLATE/03-bug-high.yml
vendored
|
@ -1,59 +0,0 @@
|
||||||
name: High Severity Bug
|
|
||||||
description: Used to report high severity bugs in cosmopolitan (e.g. Malfunctioning features hindering important common workflow)
|
|
||||||
title: "Bug: "
|
|
||||||
labels: ["bug", "high severity"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
Please include information about your system, the steps to reproduce the bug,
|
|
||||||
and the version of cosmopolitan that you are using.
|
|
||||||
If possible, please provide a minimal code example that reproduces the bug.
|
|
||||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
|
||||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
|
||||||
- type: input
|
|
||||||
id: contact
|
|
||||||
attributes:
|
|
||||||
label: Contact Details
|
|
||||||
description: How can we get in touch with you if we need more info?
|
|
||||||
placeholder: ex. email@example.com
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: what-happened
|
|
||||||
attributes:
|
|
||||||
label: What happened?
|
|
||||||
description: Also tell us, what did you expect to happen?
|
|
||||||
placeholder: Tell us what you see!
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: What version of our software are you running? (use `--version` to get a version string)
|
|
||||||
placeholder: "cosmocc (GCC) 12.3.0"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: operating-system
|
|
||||||
attributes:
|
|
||||||
label: What operating system are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Linux
|
|
||||||
- Mac
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
59
.github/ISSUE_TEMPLATE/04-bug-critical.yml
vendored
59
.github/ISSUE_TEMPLATE/04-bug-critical.yml
vendored
|
@ -1,59 +0,0 @@
|
||||||
name: Critical Severity Bug
|
|
||||||
description: Used to report critical severity bugs in cosmopolitan (e.g. Crashing, Corrupted, Dataloss)
|
|
||||||
title: "Bug: "
|
|
||||||
labels: ["bug", "critical severity"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Thanks for taking the time to fill out this bug report!
|
|
||||||
Please include information about your system, the steps to reproduce the bug,
|
|
||||||
and the version of cosmopolitan that you are using.
|
|
||||||
If possible, please provide a minimal code example that reproduces the bug.
|
|
||||||
You may also consider using function call tracing `--ftrace` or the lighter system call tracing `--strace`
|
|
||||||
for additional technical logging that may allow us to narrow down where the fault occurred.
|
|
||||||
- type: input
|
|
||||||
id: contact
|
|
||||||
attributes:
|
|
||||||
label: Contact Details
|
|
||||||
description: How can we get in touch with you if we need more info?
|
|
||||||
placeholder: ex. email@example.com
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: what-happened
|
|
||||||
attributes:
|
|
||||||
label: What happened?
|
|
||||||
description: Also tell us, what did you expect to happen?
|
|
||||||
placeholder: Tell us what you see!
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: Version
|
|
||||||
description: What version of our software are you running? (use `--version` to get a version string)
|
|
||||||
placeholder: "cosmocc (GCC) 12.3.0"
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: dropdown
|
|
||||||
id: operating-system
|
|
||||||
attributes:
|
|
||||||
label: What operating system are you seeing the problem on?
|
|
||||||
multiple: true
|
|
||||||
options:
|
|
||||||
- Linux
|
|
||||||
- Mac
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
validations:
|
|
||||||
required: false
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
51
.github/ISSUE_TEMPLATE/05-enhancement.yml
vendored
51
.github/ISSUE_TEMPLATE/05-enhancement.yml
vendored
|
@ -1,51 +0,0 @@
|
||||||
name: Enhancement template
|
|
||||||
description: Used to request enhancements for cosmopolitan
|
|
||||||
title: "Feature Request: "
|
|
||||||
labels: ["enhancement"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
[Please post your idea first in Discussion if there is not yet a consensus for this enhancement request. This will help to keep this issue tracker focused on enhancements that the community has agreed needs to be implemented.](https://github.com/jart/cosmopolitan/discussions/categories/ideas)
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: prerequisites
|
|
||||||
attributes:
|
|
||||||
label: Prerequisites
|
|
||||||
description: Please confirm the following before submitting your enhancement request.
|
|
||||||
options:
|
|
||||||
- label: I am running the latest code. Mention the version if possible as well.
|
|
||||||
required: true
|
|
||||||
- label: I carefully followed the [README.md](https://github.com/jart/cosmopolitan/blob/master/README.md).
|
|
||||||
required: true
|
|
||||||
- label: I searched using keywords relevant to my issue to make sure that I am creating a new issue that is not already open (or closed).
|
|
||||||
required: true
|
|
||||||
- label: I reviewed the [Discussions](https://github.com/jart/cosmopolitan/discussions), and have a new and useful enhancement to share.
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: feature-description
|
|
||||||
attributes:
|
|
||||||
label: Feature Description
|
|
||||||
description: Please provide a detailed written description of what you were trying to do, and what you expected `cosmopolitan` to do as an enhancement.
|
|
||||||
placeholder: Detailed description of the enhancement
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: motivation
|
|
||||||
attributes:
|
|
||||||
label: Motivation
|
|
||||||
description: Please provide a detailed written description of reasons why this feature is necessary and how it is useful to `cosmopolitan` users.
|
|
||||||
placeholder: Explanation of why this feature is needed and its benefits
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: possible-implementation
|
|
||||||
attributes:
|
|
||||||
label: Possible Implementation
|
|
||||||
description: If you have an idea as to how it can be implemented, please write a detailed description. Feel free to give links to external sources or share visuals that might be helpful to understand the details better.
|
|
||||||
placeholder: Detailed description of potential implementation
|
|
||||||
validations:
|
|
||||||
required: false
|
|
52
.github/ISSUE_TEMPLATE/06-research.yml
vendored
52
.github/ISSUE_TEMPLATE/06-research.yml
vendored
|
@ -1,52 +0,0 @@
|
||||||
name: Research
|
|
||||||
description: Track new technical research area
|
|
||||||
title: "Research: "
|
|
||||||
labels: ["research"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Don't forget to check for any [duplicate research issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3A%22research+%F0%9F%94%AC%22)
|
|
||||||
|
|
||||||
- type: checkboxes
|
|
||||||
id: research-stage
|
|
||||||
attributes:
|
|
||||||
label: Research Stage
|
|
||||||
description: Track general state of this research ticket
|
|
||||||
options:
|
|
||||||
- label: Background Research (Let's try to avoid reinventing the wheel)
|
|
||||||
- label: Hypothesis Formed (How do you think this will work and it's effect?)
|
|
||||||
- label: Strategy / Implementation Forming
|
|
||||||
- label: Analysis of results
|
|
||||||
- label: Debrief / Documentation (So people in the future can learn from us)
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: background
|
|
||||||
attributes:
|
|
||||||
label: Previous existing literature and research
|
|
||||||
description: Whats the current state of the art and whats the motivation for this research?
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: hypothesis
|
|
||||||
attributes:
|
|
||||||
label: Hypothesis
|
|
||||||
description: How do you think this will work and it's effect?
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: implementation
|
|
||||||
attributes:
|
|
||||||
label: Implementation
|
|
||||||
description: Got an approach? e.g. a PR ready to go?
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: analysis
|
|
||||||
attributes:
|
|
||||||
label: Analysis
|
|
||||||
description: How does the proposed implementation behave?
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: logs
|
|
||||||
attributes:
|
|
||||||
label: Relevant log output
|
|
||||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
|
||||||
render: shell
|
|
28
.github/ISSUE_TEMPLATE/07-refactor.yml
vendored
28
.github/ISSUE_TEMPLATE/07-refactor.yml
vendored
|
@ -1,28 +0,0 @@
|
||||||
name: Refactor (Maintainers)
|
|
||||||
description: Used to track refactoring opportunities
|
|
||||||
title: "Refactor: "
|
|
||||||
labels: ["refactor"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
Don't forget to [check for existing refactor issue tickets](https://github.com/jart/cosmopolitan/issues?q=is%3Aopen+is%3Aissue+label%3Arefactoring) in case it's already covered.
|
|
||||||
Also you may want to check [Pull request refactor label as well](https://github.com/jart/cosmopolitan/pulls?q=is%3Aopen+is%3Apr+label%3Arefactoring) for duplicates too.
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: background-description
|
|
||||||
attributes:
|
|
||||||
label: Background Description
|
|
||||||
description: Please provide a detailed written description of the pain points you are trying to solve.
|
|
||||||
placeholder: Detailed description behind your motivation to request refactor
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: possible-approaches
|
|
||||||
attributes:
|
|
||||||
label: Possible Refactor Approaches
|
|
||||||
description: If you have some idea of possible approaches to solve this problem. You may want to make it a todo list.
|
|
||||||
placeholder: Your idea of possible refactoring opportunity/approaches
|
|
||||||
validations:
|
|
||||||
required: false
|
|
15
.github/ISSUE_TEMPLATE/config.yml
vendored
15
.github/ISSUE_TEMPLATE/config.yml
vendored
|
@ -1,15 +0,0 @@
|
||||||
blank_issues_enabled: true
|
|
||||||
contact_links:
|
|
||||||
- name: FAQ
|
|
||||||
url: https://github.com/jart/cosmopolitan/wiki/FAQ
|
|
||||||
about: Is your question a common one? You may want to check here first.
|
|
||||||
- name: Got an idea?
|
|
||||||
url: https://github.com/jart/cosmopolitan/discussions/categories/ideas
|
|
||||||
about: Pop it there. It may then become an enhancement ticket.
|
|
||||||
- name: Got a question?
|
|
||||||
url: https://github.com/jart/cosmopolitan/discussions/categories/q-a
|
|
||||||
about: Ask a question there!
|
|
||||||
- name: Want to contribute?
|
|
||||||
url: https://github.com/jart/cosmopolitan/wiki/contribute
|
|
||||||
about: Head to the contribution guide page of the wiki for areas you can help with
|
|
||||||
|
|
49
.github/labeler.yml
vendored
49
.github/labeler.yml
vendored
|
@ -1,49 +0,0 @@
|
||||||
# https://github.com/actions/labeler
|
|
||||||
|
|
||||||
documentation:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- README.md
|
|
||||||
- LICENSE
|
|
||||||
- CONTRIBUTING.md
|
|
||||||
- libc/README.md
|
|
||||||
- tool/cosmocc/README.md
|
|
||||||
- third_party/getopt/README.txt
|
|
||||||
build:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- build/**
|
|
||||||
- Makefile
|
|
||||||
- '*/*.mk'
|
|
||||||
examples:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file: examples/**
|
|
||||||
devops:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- .github/**
|
|
||||||
- .clang-format
|
|
||||||
dsp:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- dsp/**
|
|
||||||
ape:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- ape/**
|
|
||||||
libc:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- libc/**
|
|
||||||
net:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- net/**
|
|
||||||
third_party:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- third_party/**
|
|
||||||
tool:
|
|
||||||
- changed-files:
|
|
||||||
- any-glob-to-any-file:
|
|
||||||
- tool/**
|
|
42
.github/workflows/build.yml
vendored
42
.github/workflows/build.yml
vendored
|
@ -1,8 +1,5 @@
|
||||||
name: build
|
name: build
|
||||||
|
|
||||||
env:
|
|
||||||
COSMOCC_VERSION: 3.9.2
|
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
|
@ -22,48 +19,13 @@ jobs:
|
||||||
matrix:
|
matrix:
|
||||||
mode: ["", tiny, rel, tinylinux, optlinux]
|
mode: ["", tiny, rel, tinylinux, optlinux]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v3
|
||||||
with:
|
|
||||||
# Full checkout needed for git-restore-mtime-bare.
|
|
||||||
fetch-depth: 0
|
|
||||||
|
|
||||||
# TODO(jart): fork this action.
|
|
||||||
- uses: chetan/git-restore-mtime-action@v2
|
|
||||||
|
|
||||||
- uses: actions/cache/restore@v4
|
|
||||||
id: cache
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
.cosmocc
|
|
||||||
o
|
|
||||||
key: ${{ env.COSMOCC_VERSION }}-${{ matrix.mode }}-${{ github.sha }}
|
|
||||||
restore-keys: |
|
|
||||||
${{ env.COSMOCC_VERSION }}-${{ matrix.mode }}-
|
|
||||||
${{ env.COSMOCC_VERSION }}-
|
|
||||||
|
|
||||||
- name: Restore mtimes
|
|
||||||
if: steps.cache.outputs.cache-hit == 'true'
|
|
||||||
run: |
|
|
||||||
while read mtime file; do
|
|
||||||
[ -f "$file" ] && touch -d "@$mtime" "$file"
|
|
||||||
done < o/.mtimes
|
|
||||||
|
|
||||||
- name: support ape bins 1
|
- name: support ape bins 1
|
||||||
run: sudo cp -a build/bootstrap/ape.elf /usr/bin/ape
|
run: sudo cp build/bootstrap/ape.elf /usr/bin/ape
|
||||||
|
|
||||||
- name: support ape bins 2
|
- name: support ape bins 2
|
||||||
run: sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
run: sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
||||||
|
|
||||||
- name: make matrix
|
- name: make matrix
|
||||||
run: V=0 make -j2 MODE=${{ matrix.mode }}
|
run: V=0 make -j2 MODE=${{ matrix.mode }}
|
||||||
|
|
||||||
- name: Save mtimes
|
|
||||||
run: |
|
|
||||||
find o -type f -exec stat -c "%Y %n" {} \; > o/.mtimes
|
|
||||||
|
|
||||||
- uses: actions/cache/save@v4
|
|
||||||
with:
|
|
||||||
path: |
|
|
||||||
.cosmocc
|
|
||||||
o
|
|
||||||
key: ${{ env.COSMOCC_VERSION }}-${{ matrix.mode }}-${{ github.sha }}
|
|
||||||
|
|
17
.github/workflows/labeler.yml
vendored
17
.github/workflows/labeler.yml
vendored
|
@ -1,17 +0,0 @@
|
||||||
name: "Pull Request Labeler"
|
|
||||||
on:
|
|
||||||
- pull_request_target
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
labeler:
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
pull-requests: write
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
repository: "jart/cosmopolitan"
|
|
||||||
- uses: actions/labeler@v5
|
|
||||||
with:
|
|
||||||
configuration-path: '.github/labeler.yml'
|
|
24
.github/workflows/nightly-cosmocc.yml
vendored
24
.github/workflows/nightly-cosmocc.yml
vendored
|
@ -1,24 +0,0 @@
|
||||||
name: Nightly cosmocc
|
|
||||||
on:
|
|
||||||
schedule:
|
|
||||||
# https://crontab.guru/#37_4_*_*_*
|
|
||||||
- cron: "37 4 * * *"
|
|
||||||
workflow_dispatch:
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
jobs:
|
|
||||||
build-cosmocc:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- run: |
|
|
||||||
sudo cp build/bootstrap/ape.elf /usr/bin/ape
|
|
||||||
sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
|
||||||
- run: tool/cosmocc/package.sh
|
|
||||||
# https://github.com/actions/upload-artifact/issues/590
|
|
||||||
- uses: actions/upload-artifact@v4.3.5
|
|
||||||
with:
|
|
||||||
name: cosmocc
|
|
||||||
path: cosmocc
|
|
||||||
compression-level: 9
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,8 +1,7 @@
|
||||||
# -*- conf -*-
|
# -*- conf -*-
|
||||||
|
|
||||||
/o
|
/o
|
||||||
/cosmocc
|
/.prompt.jtlp
|
||||||
/.cosmocc
|
|
||||||
|
|
||||||
# TODO: Find some way to have Python write to o/
|
# TODO: Find some way to have Python write to o/
|
||||||
__pycache__
|
__pycache__
|
||||||
|
@ -15,4 +14,3 @@ __pycache__
|
||||||
/tool/emacs/*.elc
|
/tool/emacs/*.elc
|
||||||
/perf.data
|
/perf.data
|
||||||
/perf.data.old
|
/perf.data.old
|
||||||
/qemu*core
|
|
||||||
|
|
111
.vscode/c_cpp_properties.json
vendored
Normal file
111
.vscode/c_cpp_properties.json
vendored
Normal file
|
@ -0,0 +1,111 @@
|
||||||
|
{
|
||||||
|
"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=",
|
||||||
|
"dontinstrument=",
|
||||||
|
"nodebuginfo=",
|
||||||
|
"interruptfn=",
|
||||||
|
"optimizespeed=",
|
||||||
|
"forcealignargpointer=",
|
||||||
|
"dontasan=",
|
||||||
|
"dontubsan=",
|
||||||
|
"donothing=",
|
||||||
|
"nosideeffect=",
|
||||||
|
"unreachable=",,
|
||||||
|
"notpossible=",
|
||||||
|
"thatispacked=",
|
||||||
|
"dontthrow=",
|
||||||
|
"nocallback=",
|
||||||
|
"relegated=",
|
||||||
|
"hidden=",
|
||||||
|
"textstartup=",
|
||||||
|
"initarray=",
|
||||||
|
"returnsnonnull=",
|
||||||
|
"returnspointerwithnoaliases=",
|
||||||
|
"printfesque(x)=",
|
||||||
|
"attributeallocsize(x)=",
|
||||||
|
"returnsaligned(x)=",
|
||||||
|
"attributeallocalign(x)=",
|
||||||
|
"nullterminated(x)="
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}"
|
||||||
|
],
|
||||||
|
"cStandard": "gnu17",
|
||||||
|
"compilerPath": "${workspaceFolder}/o/third_party/gcc/bin/x86_64-linux-musl-gcc",
|
||||||
|
"compilerArgs": [
|
||||||
|
"-Wall",
|
||||||
|
"-Werror",
|
||||||
|
"-fdebug-prefix-map=${workspaceFolder}=",
|
||||||
|
"-frecord-gcc-switches",
|
||||||
|
"-Wa,-W",
|
||||||
|
"-Wa,-I.",
|
||||||
|
"-Wa,--noexecstack",
|
||||||
|
"-Og",
|
||||||
|
"-g",
|
||||||
|
"-gdescribe-dies",
|
||||||
|
"-msse3",
|
||||||
|
"-mno-red-zone",
|
||||||
|
"-fno-math-errno",
|
||||||
|
"-fno-trapping-math",
|
||||||
|
"-fno-fp-int-builtin-inexact",
|
||||||
|
"-fno-ident",
|
||||||
|
"-fno-common",
|
||||||
|
"-fno-gnu-unique",
|
||||||
|
"-fstrict-aliasing",
|
||||||
|
"-fstrict-overflow",
|
||||||
|
"-fno-semantic-interposition",
|
||||||
|
"-mno-omit-leaf-frame-pointer",
|
||||||
|
"-fno-jump-tables",
|
||||||
|
"-nostdinc",
|
||||||
|
"-iquote."
|
||||||
|
],
|
||||||
|
"forcedInclude": [
|
||||||
|
"libc/integral/normalize.inc"
|
||||||
|
],
|
||||||
|
"defines": [
|
||||||
|
"COSMO",
|
||||||
|
"MODE=",
|
||||||
|
"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.
|
We'd love to accept your patches! Please read this guide first.
|
||||||
|
|
||||||
## Identity Disclosure
|
|
||||||
|
|
||||||
This project does not accept anonymous contributions. Justine Tunney
|
|
||||||
won't merge pull requests from strangers. In order to change the Cosmo
|
|
||||||
codebase, and have your changes be upstreamed, she has to know who you
|
|
||||||
are. You're encouraged to disclose your full name and email address to
|
|
||||||
the public too, by including them in your git commit messages; however
|
|
||||||
that's not a requirement; as we're happy to respect the wishes of
|
|
||||||
contributors who prefer to remain anonymous to the public.
|
|
||||||
|
|
||||||
## Copyright Assignment
|
## Copyright Assignment
|
||||||
|
|
||||||
The first time you send a pull request, you need to send an email to
|
Please send an email to Justine Tunney <jtunney@gmail.com> stating that
|
||||||
Justine Tunney <jtunney@gmail.com> stating that you intend to assign her
|
you intend to assign her the copyright to the changes you contribute to
|
||||||
the copyright to the changes you contribute to Cosmopolitan. It only
|
Cosmopolitan. Please use the same email address you use for git commits
|
||||||
needs to happen once. This only applies to the code you *choose* to
|
which should only contain original source code from you or other people
|
||||||
contribute. The email should be sent from an email address associated
|
who are also assigning copyright. Please note that, if you're employed,
|
||||||
with your identity. Your email should link to your pull request.
|
you may need to get your employer's approval beforehand. If you can not
|
||||||
|
assign copyright due to local laws, then you may alternatively consider
|
||||||
|
disclaiming it using the language in [Unlicense](https://unlicense.org)
|
||||||
|
or [CC-0](http://creativecommons.org/share-your-work/public-domain/cc0)
|
||||||
|
|
||||||
To make things easy, here's an example of a good email you can use:
|
This is important because we can't produce 12kb single-file executables
|
||||||
|
that comply with license requirements if we have to embed lots of them.
|
||||||
> **From**: YOUR NAME (yname@gmail.com)
|
Although that's less of an issue depending on the purpose of the files.
|
||||||
> **To**: Justine Tunney (jtunney@gmail.com)
|
For example, ownership is much less of a concern in the unit test files
|
||||||
> **Subject**: Cosmopolitan Copyright Assignment for YOUR NAME
|
so you're encouraged to put your copyright on those, provided it's ISC.
|
||||||
>
|
|
||||||
> Hi Justine,
|
|
||||||
>
|
|
||||||
> I made my first contribution to Cosmopolitan in
|
|
||||||
> https://github.com/jart/cosmopolitan/pull/XXXX could you please take a
|
|
||||||
> look? I intend to assign you the copyright to the changes I contribute
|
|
||||||
> to Cosmopolitan.
|
|
||||||
>
|
|
||||||
> Thanks!
|
|
||||||
|
|
||||||
Please note that in order to give Justine the copyright, it has to be
|
|
||||||
yours to give in the first place. If you're employed, then you should
|
|
||||||
get your employer's approval to do this beforehand. Even with big
|
|
||||||
companies like Google, this process is quick and painless. Usually we
|
|
||||||
see employers granting authorization in less than one day.
|
|
||||||
|
|
||||||
If you live in a country that doesn't recognize one's ability to assign
|
|
||||||
copyright, then you may alternatively consider disclaiming it using the
|
|
||||||
language in [Unlicense](https://unlicense.org) or
|
|
||||||
[CC-0](http://creativecommons.org/share-your-work/public-domain/cc0).
|
|
||||||
|
|
||||||
If you're checking-in third party code, then you need to have headers at
|
|
||||||
the top of each source file (but never header files) documenting its
|
|
||||||
owners and the code should go in the `third_party/` folder. Every third
|
|
||||||
party project should have a `README.cosmo` file that documents its
|
|
||||||
provenance as well as any local changes you've made.
|
|
||||||
|
|
||||||
## Copyright Policy Exceptions
|
|
||||||
|
|
||||||
### Tests
|
|
||||||
|
|
||||||
You're encoraged to claim ownership of your test code. If you add a new
|
|
||||||
file under the `test/` directory, then you should put your name in the
|
|
||||||
ISC license header at the top of the file. If you add new test cases to
|
|
||||||
an existing unit test file, then you're encouraged to append a line with
|
|
||||||
your name to the existing copyright header of that file.
|
|
||||||
|
|
||||||
### Exceptional Features
|
|
||||||
|
|
||||||
Let's say you discovered a faster better way to implement `log10()` and
|
|
||||||
you want to give it to Cosmopolitan. In cases like this, it really isn't
|
|
||||||
appropriate for Justine to own your code. What you could do instead, is
|
|
||||||
write your own new and improved `log10.c` from scratch, put your name on
|
|
||||||
the top with the ISC license, and then add a `__notice()` directive so
|
|
||||||
that your name will be embedded inside every executable that links the
|
|
||||||
`log10()` function. This will help you get your name out there. Please
|
|
||||||
note you need get approval from Justine each time you want to do this.
|
|
||||||
|
|
||||||
## Style Guide
|
## Style Guide
|
||||||
|
|
||||||
|
@ -83,4 +29,34 @@ clang-format -i -style=file tool/net/redbean.c
|
||||||
```
|
```
|
||||||
|
|
||||||
If you use Emacs this can be automated on save for Cosmopolitan using
|
If you use Emacs this can be automated on save for Cosmopolitan using
|
||||||
[tool/emacs/cosmo-format.el](tool/emacs/cosmo-format.el).
|
[tool/emacs/cosmo-format.el]([tool/emacs/cosmo-format.el]).
|
||||||
|
|
||||||
|
### Source Files
|
||||||
|
|
||||||
|
- Must use include paths relative to the root of the repository
|
||||||
|
- Must have comment at top of file documenting copyright and license
|
||||||
|
- Must have notice embedding if not owned by Justine (exception: tests)
|
||||||
|
- May use language extensions that are supported by both GCC and Clang
|
||||||
|
- Should use Google indentation (otherwise use `/* clang-format off */`)
|
||||||
|
- Should use asm() instead of compiler APIs (exception: ctz, clz, memcpy)
|
||||||
|
|
||||||
|
### Header Files
|
||||||
|
|
||||||
|
- Must not have copyright or license comments
|
||||||
|
- Must have once guards (otherwise change `.h` to `.inc`)
|
||||||
|
- Must be ANSI C89 compatible to be included in the amalgamation header
|
||||||
|
- Must include its dependencies (exception: libc/integral/normalize.inc)
|
||||||
|
- Must not define objects (i.e. `cc -c -xc foo.h` will produce empty `.o`)
|
||||||
|
- Should not use typedefs
|
||||||
|
- Should not use forward declarations
|
||||||
|
- Should not include documentation comments
|
||||||
|
- Should not include parameter names in prototypes
|
||||||
|
- Should not pose problems if included by C++ or Assembly sources
|
||||||
|
- Should not declare non-ANSI code, at all, when the user requests ANSI
|
||||||
|
|
||||||
|
### Build Config
|
||||||
|
|
||||||
|
- Must not write files outside `o/`
|
||||||
|
- Must not communicate with Internet
|
||||||
|
- Must not depend on system libraries
|
||||||
|
- Must not depend on system commands (exception: sh, make, gzip, zip)
|
||||||
|
|
639
Makefile
639
Makefile
|
@ -1,5 +1,5 @@
|
||||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
|
@ -21,23 +21,23 @@
|
||||||
# make -j8 -O MODE=tiny
|
# make -j8 -O MODE=tiny
|
||||||
#
|
#
|
||||||
# # build individual target
|
# # build individual target
|
||||||
# make -j8 -O o//examples/hello
|
# make -j8 -O o//examples/hello.com
|
||||||
# o//examples/hello
|
# o//examples/hello.com
|
||||||
#
|
#
|
||||||
# # view source
|
# # view source
|
||||||
# less examples/hello.c
|
# less examples/hello.c
|
||||||
#
|
#
|
||||||
# # view binary
|
# # view binary
|
||||||
# o//tool/viz/bing o//examples/hello |
|
# o//tool/viz/bing.com o//examples/hello.com |
|
||||||
# o//tool/viz/fold
|
# o//tool/viz/fold.com
|
||||||
#
|
#
|
||||||
# # view transitive closure of legalese
|
# # view transitive closure of legalese
|
||||||
# o//tool/viz/bing -n o//examples/hello |
|
# o//tool/viz/bing.com -n o//examples/hello.com |
|
||||||
# o//tool/viz/fold
|
# o//tool/viz/fold.com
|
||||||
#
|
#
|
||||||
# # basic debugging
|
# # basic debugging
|
||||||
# make -j8 -O MODE=dbg o/dbg/examples/crashreport
|
# make -j8 -O MODE=dbg o/dbg/examples/crashreport.com
|
||||||
# o/examples/crashreport
|
# o/examples/crashreport.com
|
||||||
# less examples/crashreport.c
|
# less examples/crashreport.c
|
||||||
#
|
#
|
||||||
# # extremely tiny binaries
|
# # extremely tiny binaries
|
||||||
|
@ -51,7 +51,7 @@
|
||||||
#
|
#
|
||||||
# TROUBLESHOOTING
|
# TROUBLESHOOTING
|
||||||
#
|
#
|
||||||
# make -j8 -O V=1 o//examples/hello
|
# make -j8 -O V=1 o//examples/hello.com
|
||||||
# make o//examples/life.elf -pn |& less
|
# make o//examples/life.elf -pn |& less
|
||||||
# etc.
|
# etc.
|
||||||
#
|
#
|
||||||
|
@ -59,7 +59,7 @@
|
||||||
#
|
#
|
||||||
# build/config.mk
|
# build/config.mk
|
||||||
|
|
||||||
SHELL = build/bootstrap/cocmd
|
SHELL = build/bootstrap/cocmd.com
|
||||||
MAKEFLAGS += --no-builtin-rules
|
MAKEFLAGS += --no-builtin-rules
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
|
@ -73,110 +73,11 @@ MODE := $(m)
|
||||||
endif
|
endif
|
||||||
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
|
all: o
|
||||||
o: o/$(MODE)
|
o: o/$(MODE)
|
||||||
|
|
||||||
o/$(MODE): \
|
o/$(MODE): \
|
||||||
o/$(MODE)/ape \
|
o/$(MODE)/ape \
|
||||||
o/$(MODE)/ctl \
|
|
||||||
o/$(MODE)/dsp \
|
o/$(MODE)/dsp \
|
||||||
o/$(MODE)/net \
|
o/$(MODE)/net \
|
||||||
o/$(MODE)/libc \
|
o/$(MODE)/libc \
|
||||||
|
@ -185,33 +86,23 @@ o/$(MODE): \
|
||||||
o/$(MODE)/examples \
|
o/$(MODE)/examples \
|
||||||
o/$(MODE)/third_party
|
o/$(MODE)/third_party
|
||||||
|
|
||||||
# TODO(jart): Make Emacs `C-c C-c` shortcut not need this.
|
|
||||||
.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),)
|
ifneq ($(LANDLOCKMAKE_VERSION),)
|
||||||
ifeq ($(UNAME_S),Linux)
|
|
||||||
ifeq ($(wildcard /usr/bin/ape),)
|
ifeq ($(wildcard /usr/bin/ape),)
|
||||||
$(warning please run ape/apeinstall.sh if you intend to use landlock make)
|
$(warning please run ape/apeinstall.sh if you intend to use landlock make)
|
||||||
$(shell sleep .5)
|
$(shell sleep .5)
|
||||||
endif
|
endif
|
||||||
endif
|
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
|
||||||
ifneq ($(TOOLCHAIN),)
|
|
||||||
.STRICT = 1
|
.STRICT = 1
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PLEDGE += stdio rpath wpath cpath fattr proc
|
.PLEDGE = stdio rpath wpath cpath fattr proc
|
||||||
.UNVEIL += \
|
.UNVEIL = \
|
||||||
libc/integral \
|
libc/integral \
|
||||||
libc/stdbool.h \
|
libc/disclaimer.inc \
|
||||||
rwc:/dev/shm \
|
rwc:/dev/shm \
|
||||||
rx:.cosmocc \
|
|
||||||
rx:build/bootstrap \
|
rx:build/bootstrap \
|
||||||
|
rx:o/third_party/gcc \
|
||||||
r:build/portcosmo.h \
|
r:build/portcosmo.h \
|
||||||
/proc/stat \
|
/proc/stat \
|
||||||
rw:/dev/null \
|
rw:/dev/null \
|
||||||
|
@ -220,8 +111,6 @@ endif
|
||||||
/etc/hosts \
|
/etc/hosts \
|
||||||
~/.runit.psk \
|
~/.runit.psk \
|
||||||
/proc/self/status \
|
/proc/self/status \
|
||||||
rx:/usr/bin/qemu-aarch64 \
|
|
||||||
rx:o/third_party/qemu/qemu-aarch64 \
|
|
||||||
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
|
||||||
|
|
||||||
PKGS =
|
PKGS =
|
||||||
|
@ -232,163 +121,149 @@ include build/definitions.mk # ├──META
|
||||||
include build/config.mk # │ You can build
|
include build/config.mk # │ You can build
|
||||||
include build/rules.mk # │ You can topologically order
|
include build/rules.mk # │ You can topologically order
|
||||||
include build/online.mk #─┘
|
include build/online.mk #─┘
|
||||||
include libc/nexgen32e/BUILD.mk #─┐
|
include libc/nexgen32e/nexgen32e.mk #─┐
|
||||||
include libc/sysv/BUILD.mk # ├──SYSTEM SUPPORT
|
include libc/sysv/sysv.mk # ├──SYSTEM SUPPORT
|
||||||
include libc/nt/BUILD.mk # │ You can do math
|
include libc/nt/nt.mk # │ You can do math
|
||||||
include libc/intrin/BUILD.mk # │ You can use the stack
|
include libc/intrin/intrin.mk # │ You can use the stack
|
||||||
include third_party/compiler_rt/BUILD.mk # │ You can manipulate arrays
|
include third_party/compiler_rt/compiler_rt.mk # │ You can manipulate arrays
|
||||||
include libc/tinymath/BUILD.mk # │ You can issue raw system calls
|
include libc/tinymath/tinymath.mk # │ You can issue raw system calls
|
||||||
include libc/str/BUILD.mk # │
|
include libc/str/str.mk # │
|
||||||
include third_party/xed/BUILD.mk # │
|
include third_party/xed/xed.mk # │
|
||||||
include third_party/puff/BUILD.mk # │
|
include third_party/puff/puff.mk # │
|
||||||
include libc/elf/BUILD.mk # │
|
include third_party/zlib/zlib.mk # │
|
||||||
include ape/BUILD.mk # │
|
include third_party/double-conversion/dc.mk # │
|
||||||
include libc/fmt/BUILD.mk # │
|
include libc/elf/elf.mk # │
|
||||||
include libc/vga/BUILD.mk # │
|
include ape/ape.mk # │
|
||||||
include libc/irq/BUILD.mk #─┘
|
include libc/fmt/fmt.mk # │
|
||||||
include libc/calls/BUILD.mk #─┐
|
include libc/vga/vga.mk #─┘
|
||||||
include libc/irq/BUILD.mk # ├──SYSTEMS RUNTIME
|
include libc/calls/calls.mk #─┐
|
||||||
include third_party/nsync/BUILD.mk # │ You can issue system calls
|
include libc/runtime/runtime.mk # ├──SYSTEMS RUNTIME
|
||||||
include libc/runtime/BUILD.mk # │
|
include libc/crt/crt.mk # │ You can issue system calls
|
||||||
include libc/crt/BUILD.mk # │
|
include tool/hello/hello.mk # │
|
||||||
include third_party/dlmalloc/BUILD.mk #─┘
|
include third_party/nsync/nsync.mk # │
|
||||||
include libc/mem/BUILD.mk #─┐
|
include third_party/dlmalloc/dlmalloc.mk #─┘
|
||||||
include third_party/gdtoa/BUILD.mk # ├──DYNAMIC RUNTIME
|
include libc/mem/mem.mk #─┐
|
||||||
include third_party/nsync/mem/BUILD.mk # │ You can now use stdio
|
include third_party/gdtoa/gdtoa.mk # ├──DYNAMIC RUNTIME
|
||||||
include libc/proc/BUILD.mk # │ You can now use threads
|
include third_party/nsync/mem/mem.mk # │ You can now use stdio
|
||||||
include libc/dlopen/BUILD.mk # │ You can now use processes
|
include libc/thread/thread.mk # │ You can finally call malloc()
|
||||||
include libc/thread/BUILD.mk # │ You can finally call malloc()
|
include libc/zipos/zipos.mk # │
|
||||||
include third_party/zlib/BUILD.mk # │
|
include libc/stdio/stdio.mk # │
|
||||||
include libc/stdio/BUILD.mk # │
|
include libc/time/time.mk # │
|
||||||
include tool/hello/BUILD.mk # │
|
include net/net.mk # │
|
||||||
include third_party/tz/BUILD.mk # │
|
include third_party/vqsort/vqsort.mk # │
|
||||||
include net/BUILD.mk # │
|
include libc/log/log.mk # │
|
||||||
include third_party/vqsort/BUILD.mk # │
|
include third_party/getopt/getopt.mk # │
|
||||||
include libc/log/BUILD.mk # │
|
include third_party/bzip2/bzip2.mk # │
|
||||||
include third_party/getopt/BUILD.mk # │
|
include dsp/core/core.mk # │
|
||||||
include third_party/bzip2/BUILD.mk # │
|
include third_party/musl/musl.mk # │
|
||||||
include dsp/core/BUILD.mk # │
|
include libc/x/x.mk # │
|
||||||
include third_party/zlib/gz/BUILD.mk # │
|
include third_party/stb/stb.mk # │
|
||||||
include third_party/intel/BUILD.mk # │
|
include dsp/scale/scale.mk # │
|
||||||
include third_party/aarch64/BUILD.mk # │
|
include dsp/mpeg/mpeg.mk # │
|
||||||
include libc/BUILD.mk #─┘
|
include dsp/dsp.mk # │
|
||||||
include libc/sock/BUILD.mk #─┐
|
include third_party/zlib/gz/gz.mk # │
|
||||||
include net/http/BUILD.mk # ├──ONLINE RUNTIME
|
include third_party/intel/intel.mk # │
|
||||||
include third_party/musl/BUILD.mk # │ You can communicate with the network
|
include third_party/aarch64/aarch64.mk # │
|
||||||
include third_party/regex/BUILD.mk # │
|
include libc/libc.mk #─┘
|
||||||
include third_party/tr/BUILD.mk # │
|
include libc/sock/sock.mk #─┐
|
||||||
include third_party/sed/BUILD.mk # │
|
include dsp/tty/tty.mk # ├──ONLINE RUNTIME
|
||||||
include libc/system/BUILD.mk # │
|
include libc/dns/dns.mk # │ You can communicate with the network
|
||||||
include libc/x/BUILD.mk # │
|
include net/http/http.mk # │
|
||||||
include dsp/scale/BUILD.mk # │
|
include third_party/mbedtls/mbedtls.mk # │
|
||||||
include dsp/mpeg/BUILD.mk # │
|
include third_party/libcxx/libcxx.mk # │
|
||||||
include dsp/tty/BUILD.mk # │
|
include third_party/ggml/ggml.mk # │
|
||||||
include dsp/audio/BUILD.mk # │
|
include third_party/radpajama/radpajama.mk # │
|
||||||
include dsp/prog/BUILD.mk # │
|
include net/https/https.mk # │
|
||||||
include dsp/BUILD.mk # │
|
include third_party/regex/regex.mk #─┘
|
||||||
include third_party/stb/BUILD.mk # │
|
include third_party/tidy/tidy.mk
|
||||||
include third_party/mbedtls/BUILD.mk # │
|
include third_party/third_party.mk
|
||||||
include third_party/ncurses/BUILD.mk # │
|
include third_party/nsync/testing/testing.mk
|
||||||
include third_party/readline/BUILD.mk # │
|
include libc/testlib/testlib.mk
|
||||||
include third_party/libunwind/BUILD.mk # |
|
include tool/viz/lib/vizlib.mk
|
||||||
include third_party/libcxxabi/BUILD.mk # |
|
include tool/args/args.mk
|
||||||
include third_party/double-conversion/BUILD.mk # │
|
include test/tool/args/test.mk
|
||||||
include ctl/BUILD.mk # │
|
include third_party/linenoise/linenoise.mk
|
||||||
include third_party/libcxx/BUILD.mk # │
|
include third_party/maxmind/maxmind.mk
|
||||||
include third_party/openmp/BUILD.mk # │
|
include net/finger/finger.mk
|
||||||
include third_party/pcre/BUILD.mk # │
|
include third_party/double-conversion/test/test.mk
|
||||||
include third_party/less/BUILD.mk # │
|
include third_party/lua/lua.mk
|
||||||
include net/https/BUILD.mk #─┘
|
include third_party/zstd/zstd.mk
|
||||||
include third_party/tidy/BUILD.mk
|
include third_party/tr/tr.mk
|
||||||
include third_party/BUILD.mk
|
include third_party/sed/sed.mk
|
||||||
include third_party/nsync/testing/BUILD.mk
|
include third_party/awk/awk.mk
|
||||||
include libc/testlib/BUILD.mk
|
include third_party/hiredis/hiredis.mk
|
||||||
include tool/viz/lib/BUILD.mk
|
include third_party/make/make.mk
|
||||||
include tool/args/BUILD.mk
|
include third_party/ctags/ctags.mk
|
||||||
include test/math/BUILD.mk
|
include third_party/finger/finger.mk
|
||||||
include test/posix/BUILD.mk
|
include third_party/argon2/argon2.mk
|
||||||
include test/ctl/BUILD.mk
|
include third_party/smallz4/smallz4.mk
|
||||||
include test/libcxx/BUILD.mk
|
include third_party/sqlite3/sqlite3.mk
|
||||||
include test/tool/args/BUILD.mk
|
include third_party/mbedtls/test/test.mk
|
||||||
include third_party/linenoise/BUILD.mk
|
include third_party/quickjs/quickjs.mk
|
||||||
include third_party/maxmind/BUILD.mk
|
include third_party/lz4cli/lz4cli.mk
|
||||||
include net/finger/BUILD.mk
|
include third_party/zip/zip.mk
|
||||||
include third_party/double-conversion/test/BUILD.mk
|
include third_party/xxhash/xxhash.mk
|
||||||
include third_party/lua/BUILD.mk
|
include third_party/unzip/unzip.mk
|
||||||
include third_party/tree/BUILD.mk
|
include tool/build/lib/buildlib.mk
|
||||||
include third_party/zstd/BUILD.mk
|
include third_party/chibicc/chibicc.mk
|
||||||
include third_party/awk/BUILD.mk
|
include third_party/chibicc/test/test.mk
|
||||||
include third_party/hiredis/BUILD.mk
|
include third_party/python/python.mk
|
||||||
include third_party/make/BUILD.mk
|
include tool/build/build.mk
|
||||||
include third_party/ctags/BUILD.mk
|
include tool/curl/curl.mk
|
||||||
include third_party/finger/BUILD.mk
|
include tool/ape/ape.mk
|
||||||
include third_party/argon2/BUILD.mk
|
include third_party/qemu/qemu.mk
|
||||||
include third_party/smallz4/BUILD.mk
|
include examples/examples.mk
|
||||||
include third_party/sqlite3/BUILD.mk
|
include examples/pyapp/pyapp.mk
|
||||||
include third_party/mbedtls/test/BUILD.mk
|
include examples/pylife/pylife.mk
|
||||||
include third_party/lz4cli/BUILD.mk
|
include tool/decode/lib/decodelib.mk
|
||||||
include third_party/zip/BUILD.mk
|
include tool/decode/decode.mk
|
||||||
include third_party/xxhash/BUILD.mk
|
include tool/lambda/lib/lib.mk
|
||||||
include third_party/unzip/BUILD.mk
|
include tool/lambda/lambda.mk
|
||||||
include tool/build/lib/BUILD.mk
|
include tool/plinko/lib/lib.mk
|
||||||
include third_party/chibicc/BUILD.mk
|
include tool/plinko/plinko.mk
|
||||||
include third_party/chibicc/test/BUILD.mk
|
include test/tool/plinko/test.mk
|
||||||
include third_party/python/BUILD.mk
|
include tool/net/net.mk
|
||||||
include tool/build/BUILD.mk
|
include tool/viz/viz.mk
|
||||||
include tool/curl/BUILD.mk
|
include tool/tool.mk
|
||||||
include third_party/qemu/BUILD.mk
|
include net/turfwar/turfwar.mk
|
||||||
include third_party/libcxxabi/test/BUILD.mk
|
include test/libc/tinymath/test.mk
|
||||||
include examples/BUILD.mk
|
include test/libc/intrin/test.mk
|
||||||
include examples/pyapp/BUILD.mk
|
include test/libc/mem/test.mk
|
||||||
include examples/pylife/BUILD.mk
|
include test/libc/nexgen32e/test.mk
|
||||||
include tool/decode/lib/BUILD.mk
|
include test/libc/runtime/test.mk
|
||||||
include tool/decode/BUILD.mk
|
include test/libc/thread/test.mk
|
||||||
include tool/lambda/lib/BUILD.mk
|
include test/libc/sock/test.mk
|
||||||
include tool/lambda/BUILD.mk
|
include test/libc/str/test.mk
|
||||||
include tool/plinko/lib/BUILD.mk
|
include test/libc/log/test.mk
|
||||||
include tool/plinko/BUILD.mk
|
include test/libc/str/test.mk
|
||||||
include test/tool/plinko/BUILD.mk
|
include test/libc/calls/test.mk
|
||||||
include tool/net/BUILD.mk
|
include test/libc/x/test.mk
|
||||||
include tool/viz/BUILD.mk
|
include test/libc/xed/test.mk
|
||||||
include tool/BUILD.mk
|
include test/libc/fmt/test.mk
|
||||||
include net/turfwar/BUILD.mk
|
include test/libc/dns/test.mk
|
||||||
include test/libc/tinymath/BUILD.mk
|
include test/libc/time/test.mk
|
||||||
include test/libc/intrin/BUILD.mk
|
include test/libc/stdio/test.mk
|
||||||
include test/libc/mem/BUILD.mk
|
include test/libc/zipos/test.mk
|
||||||
include test/libc/nexgen32e/BUILD.mk
|
include test/libc/release/test.mk
|
||||||
include test/libc/runtime/BUILD.mk
|
include test/libc/test.mk
|
||||||
include test/libc/thread/BUILD.mk
|
include test/net/http/test.mk
|
||||||
include test/libc/sock/BUILD.mk
|
include test/net/https/test.mk
|
||||||
include test/libc/str/BUILD.mk
|
include test/net/finger/test.mk
|
||||||
include test/libc/log/BUILD.mk
|
include test/net/test.mk
|
||||||
include test/libc/str/BUILD.mk
|
include test/tool/build/lib/test.mk
|
||||||
include test/libc/calls/BUILD.mk
|
include test/tool/build/test.mk
|
||||||
include test/libc/x/BUILD.mk
|
include test/tool/viz/lib/test.mk
|
||||||
include test/libc/xed/BUILD.mk
|
include test/tool/viz/test.mk
|
||||||
include test/libc/fmt/BUILD.mk
|
include test/tool/net/test.mk
|
||||||
include test/libc/time/BUILD.mk
|
include test/tool/test.mk
|
||||||
include test/libc/proc/BUILD.mk
|
include test/dsp/core/test.mk
|
||||||
include test/libc/stdio/BUILD.mk
|
include test/dsp/scale/test.mk
|
||||||
include test/libc/system/BUILD.mk
|
include test/dsp/tty/test.mk
|
||||||
include test/libc/BUILD.mk
|
include test/dsp/test.mk
|
||||||
include test/net/http/BUILD.mk
|
include examples/package/lib/build.mk
|
||||||
include test/net/https/BUILD.mk
|
include examples/package/build.mk
|
||||||
include test/net/finger/BUILD.mk
|
|
||||||
include test/net/BUILD.mk
|
|
||||||
include test/tool/build/lib/BUILD.mk
|
|
||||||
include test/tool/build/BUILD.mk
|
|
||||||
include test/tool/viz/lib/BUILD.mk
|
|
||||||
include test/tool/viz/BUILD.mk
|
|
||||||
include test/tool/net/BUILD.mk
|
|
||||||
include test/tool/BUILD.mk
|
|
||||||
include test/dsp/core/BUILD.mk
|
|
||||||
include test/dsp/scale/BUILD.mk
|
|
||||||
include test/dsp/tty/BUILD.mk
|
|
||||||
include test/dsp/BUILD.mk
|
|
||||||
include examples/package/lib/BUILD.mk
|
|
||||||
include examples/package/BUILD.mk
|
|
||||||
#-φ-examples/package/new.sh
|
#-φ-examples/package/new.sh
|
||||||
include test/BUILD.mk
|
include test/test.mk
|
||||||
|
|
||||||
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
|
OBJS = $(foreach x,$(PKGS),$($(x)_OBJS))
|
||||||
SRCS := $(foreach x,$(PKGS),$($(x)_SRCS))
|
SRCS := $(foreach x,$(PKGS),$($(x)_SRCS))
|
||||||
|
@ -414,7 +289,7 @@ o/$(MODE)/hdrs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS) $(
|
||||||
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x)))) $(INCS) $(INCS)
|
o/$(MODE)/incs.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(INCS) $(INCS),$(dir $(x)))) $(INCS) $(INCS)
|
||||||
$(file >$@,$(INCS))
|
$(file >$@,$(INCS))
|
||||||
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS)
|
o/$(MODE)/depend: o/$(MODE)/.x o/$(MODE)/srcs.txt o/$(MODE)/hdrs.txt o/$(MODE)/incs.txt $(SRCS) $(HDRS) $(INCS)
|
||||||
$(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -s -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt
|
$(COMPILE) -AMKDEPS -L320 $(MKDEPS) -o $@ -r o/$(MODE)/ @o/$(MODE)/srcs.txt @o/$(MODE)/hdrs.txt @o/$(MODE)/incs.txt
|
||||||
|
|
||||||
o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
o/$(MODE)/srcs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(SRCS),$(dir $(x))))
|
||||||
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
$(file >$@) $(foreach x,$(SRCS),$(file >>$@,$(x)))
|
||||||
|
@ -422,87 +297,76 @@ o/$(MODE)/hdrs-old.txt: o/$(MODE)/.x $(MAKEFILES) $(call uniq,$(foreach x,$(HDRS
|
||||||
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
$(file >$@) $(foreach x,$(HDRS) $(INCS),$(file >>$@,$(x)))
|
||||||
|
|
||||||
TAGS: private .UNSANDBOXED = 1
|
TAGS: private .UNSANDBOXED = 1
|
||||||
TAGS: o/$(MODE)/srcs-old.txt $(SRCS) #o/$(MODE)/third_party/ctags/ctags
|
TAGS: o/$(MODE)/srcs-old.txt $(SRCS) #o/$(MODE)/third_party/ctags/ctags.com
|
||||||
@$(RM) $@
|
@$(RM) $@
|
||||||
@o/$(MODE)/third_party/ctags/ctags $(TAGSFLAGS) -L $< -o $@
|
@o/$(MODE)/third_party/ctags/ctags.com $(TAGSFLAGS) -L $< -o $@
|
||||||
|
|
||||||
HTAGS: private .UNSANDBOXED = 1
|
HTAGS: private .UNSANDBOXED = 1
|
||||||
HTAGS: o/$(MODE)/hdrs-old.txt $(filter-out third_party/libcxx/%,$(HDRS)) #o/$(MODE)/third_party/ctags/ctags
|
HTAGS: o/$(MODE)/hdrs-old.txt $(filter-out third_party/libcxx/%,$(HDRS)) #o/$(MODE)/third_party/ctags/ctags.com
|
||||||
@$(RM) $@
|
@$(RM) $@
|
||||||
@build/htags o/$(MODE)/third_party/ctags/ctags -L $< -o $@
|
@build/htags o/$(MODE)/third_party/ctags/ctags.com -L $< -o $@
|
||||||
|
|
||||||
loc: private .UNSANDBOXED = 1
|
loc: private .UNSANDBOXED = 1
|
||||||
loc: o/$(MODE)/tool/build/summy
|
loc: o/$(MODE)/tool/build/summy.com
|
||||||
find -name \*.h -or -name \*.hpp -or -name \*.c -or -name \*.cc -or -name \*.cpp -or -name \*.S -or -name \*.mk | \
|
find -name \*.h -or -name \*.c -or -name \*.S | \
|
||||||
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
|
$(XARGS) wc -l | grep total | awk '{print $$1}' | $<
|
||||||
|
|
||||||
COSMOPOLITAN = \
|
# PLEASE: MAINTAIN TOPOLOGICAL ORDER
|
||||||
CTL \
|
# FROM HIGHEST LEVEL TO LOWEST LEVEL
|
||||||
DSP_AUDIO \
|
COSMOPOLITAN_OBJECTS = \
|
||||||
LIBC_CALLS \
|
|
||||||
LIBC_DLOPEN \
|
|
||||||
LIBC_ELF \
|
|
||||||
LIBC_FMT \
|
|
||||||
LIBC_INTRIN \
|
|
||||||
LIBC_IRQ \
|
|
||||||
LIBC_LOG \
|
|
||||||
LIBC_MEM \
|
|
||||||
LIBC_NEXGEN32E \
|
|
||||||
LIBC_NT_ADVAPI32 \
|
|
||||||
LIBC_NT_BCRYPTPRIMITIVES \
|
|
||||||
LIBC_NT_COMDLG32 \
|
|
||||||
LIBC_NT_GDI32 \
|
|
||||||
LIBC_NT_IPHLPAPI \
|
|
||||||
LIBC_NT_KERNEL32 \
|
|
||||||
LIBC_NT_NTDLL \
|
|
||||||
LIBC_NT_PDH \
|
|
||||||
LIBC_NT_POWRPROF \
|
|
||||||
LIBC_NT_PSAPI \
|
|
||||||
LIBC_NT_REALTIME \
|
|
||||||
LIBC_NT_SHELL32 \
|
|
||||||
LIBC_NT_SYNCHRONIZATION \
|
|
||||||
LIBC_NT_USER32 \
|
|
||||||
LIBC_NT_WS2_32 \
|
|
||||||
LIBC_PROC \
|
|
||||||
LIBC_RUNTIME \
|
|
||||||
LIBC_SOCK \
|
|
||||||
LIBC_STDIO \
|
|
||||||
LIBC_STR \
|
|
||||||
LIBC_SYSTEM \
|
|
||||||
LIBC_SYSV \
|
|
||||||
LIBC_SYSV_CALLS \
|
|
||||||
LIBC_THREAD \
|
|
||||||
LIBC_TINYMATH \
|
|
||||||
LIBC_VGA \
|
|
||||||
LIBC_X \
|
|
||||||
NET_HTTP \
|
|
||||||
THIRD_PARTY_COMPILER_RT \
|
|
||||||
THIRD_PARTY_DLMALLOC \
|
|
||||||
THIRD_PARTY_DOUBLECONVERSION \
|
|
||||||
THIRD_PARTY_GDTOA \
|
|
||||||
THIRD_PARTY_GETOPT \
|
|
||||||
THIRD_PARTY_LIBCXXABI \
|
|
||||||
THIRD_PARTY_LIBUNWIND \
|
|
||||||
THIRD_PARTY_MUSL \
|
|
||||||
THIRD_PARTY_NSYNC \
|
|
||||||
THIRD_PARTY_NSYNC_MEM \
|
|
||||||
THIRD_PARTY_OPENMP \
|
|
||||||
THIRD_PARTY_PUFF \
|
|
||||||
THIRD_PARTY_REGEX \
|
|
||||||
THIRD_PARTY_TZ \
|
|
||||||
THIRD_PARTY_XED \
|
|
||||||
THIRD_PARTY_ZLIB \
|
|
||||||
THIRD_PARTY_ZLIB_GZ \
|
|
||||||
TOOL_ARGS \
|
TOOL_ARGS \
|
||||||
|
NET_HTTP \
|
||||||
|
LIBC_DNS \
|
||||||
|
LIBC_SOCK \
|
||||||
|
LIBC_NT_WS2_32 \
|
||||||
|
LIBC_NT_IPHLPAPI \
|
||||||
|
LIBC_NT_MSWSOCK \
|
||||||
|
LIBC_X \
|
||||||
|
THIRD_PARTY_GETOPT \
|
||||||
|
LIBC_LOG \
|
||||||
|
LIBC_TIME \
|
||||||
|
LIBC_ZIPOS \
|
||||||
|
THIRD_PARTY_MUSL \
|
||||||
|
LIBC_STDIO \
|
||||||
|
THIRD_PARTY_GDTOA \
|
||||||
|
THIRD_PARTY_REGEX \
|
||||||
|
LIBC_THREAD \
|
||||||
|
THIRD_PARTY_NSYNC_MEM \
|
||||||
|
LIBC_MEM \
|
||||||
|
THIRD_PARTY_DLMALLOC \
|
||||||
|
LIBC_RUNTIME \
|
||||||
|
THIRD_PARTY_NSYNC \
|
||||||
|
LIBC_ELF \
|
||||||
|
LIBC_CALLS \
|
||||||
|
LIBC_SYSV_CALLS \
|
||||||
|
LIBC_VGA \
|
||||||
|
LIBC_NT_PSAPI \
|
||||||
|
LIBC_NT_POWRPROF \
|
||||||
|
LIBC_NT_PDH \
|
||||||
|
LIBC_NT_GDI32 \
|
||||||
|
LIBC_NT_COMDLG32 \
|
||||||
|
LIBC_NT_USER32 \
|
||||||
|
LIBC_NT_NTDLL \
|
||||||
|
LIBC_NT_ADVAPI32 \
|
||||||
|
LIBC_NT_SYNCHRONIZATION \
|
||||||
|
LIBC_FMT \
|
||||||
|
THIRD_PARTY_PUFF \
|
||||||
|
THIRD_PARTY_COMPILER_RT \
|
||||||
|
LIBC_TINYMATH \
|
||||||
|
THIRD_PARTY_XED \
|
||||||
|
LIBC_STR \
|
||||||
|
LIBC_SYSV \
|
||||||
|
LIBC_INTRIN \
|
||||||
|
LIBC_NT_KERNEL32 \
|
||||||
|
LIBC_NEXGEN32E
|
||||||
|
|
||||||
COSMOPOLITAN_H_PKGS = \
|
COSMOPOLITAN_HEADERS = \
|
||||||
APE \
|
APE \
|
||||||
DSP_AUDIO \
|
|
||||||
LIBC \
|
LIBC \
|
||||||
LIBC_CALLS \
|
LIBC_CALLS \
|
||||||
|
LIBC_DNS \
|
||||||
LIBC_ELF \
|
LIBC_ELF \
|
||||||
LIBC_FMT \
|
LIBC_FMT \
|
||||||
LIBC_DLOPEN \
|
|
||||||
LIBC_INTRIN \
|
LIBC_INTRIN \
|
||||||
LIBC_LOG \
|
LIBC_LOG \
|
||||||
LIBC_MEM \
|
LIBC_MEM \
|
||||||
|
@ -511,14 +375,15 @@ COSMOPOLITAN_H_PKGS = \
|
||||||
LIBC_RUNTIME \
|
LIBC_RUNTIME \
|
||||||
LIBC_SOCK \
|
LIBC_SOCK \
|
||||||
LIBC_STDIO \
|
LIBC_STDIO \
|
||||||
LIBC_PROC \
|
|
||||||
THIRD_PARTY_NSYNC \
|
THIRD_PARTY_NSYNC \
|
||||||
THIRD_PARTY_XED \
|
THIRD_PARTY_XED \
|
||||||
LIBC_STR \
|
LIBC_STR \
|
||||||
LIBC_SYSV \
|
LIBC_SYSV \
|
||||||
LIBC_THREAD \
|
LIBC_THREAD \
|
||||||
|
LIBC_TIME \
|
||||||
LIBC_TINYMATH \
|
LIBC_TINYMATH \
|
||||||
LIBC_X \
|
LIBC_X \
|
||||||
|
LIBC_ZIPOS \
|
||||||
LIBC_VGA \
|
LIBC_VGA \
|
||||||
NET_HTTP \
|
NET_HTTP \
|
||||||
TOOL_ARGS \
|
TOOL_ARGS \
|
||||||
|
@ -526,43 +391,28 @@ COSMOPOLITAN_H_PKGS = \
|
||||||
THIRD_PARTY_GDTOA \
|
THIRD_PARTY_GDTOA \
|
||||||
THIRD_PARTY_GETOPT \
|
THIRD_PARTY_GETOPT \
|
||||||
THIRD_PARTY_MUSL \
|
THIRD_PARTY_MUSL \
|
||||||
THIRD_PARTY_ZLIB \
|
|
||||||
THIRD_PARTY_ZLIB_GZ \
|
|
||||||
THIRD_PARTY_REGEX
|
THIRD_PARTY_REGEX
|
||||||
|
|
||||||
COSMOCC_PKGS = \
|
|
||||||
$(COSMOPOLITAN_H_PKGS) \
|
|
||||||
CTL \
|
|
||||||
THIRD_PARTY_AARCH64 \
|
|
||||||
THIRD_PARTY_LIBCXX \
|
|
||||||
THIRD_PARTY_LIBCXXABI \
|
|
||||||
THIRD_PARTY_LIBUNWIND \
|
|
||||||
THIRD_PARTY_OPENMP \
|
|
||||||
THIRD_PARTY_INTEL
|
|
||||||
|
|
||||||
o/$(MODE)/cosmopolitan.a: \
|
o/$(MODE)/cosmopolitan.a: \
|
||||||
$(call reverse,$(call uniq,$(foreach x,$(COSMOPOLITAN),$($(x)))))
|
$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_A_OBJS))
|
||||||
|
|
||||||
COSMOCC_HDRS = \
|
o/cosmopolitan.h: \
|
||||||
$(wildcard libc/integral/*) \
|
o/$(MODE)/tool/build/rollup.com \
|
||||||
$(foreach x,$(COSMOCC_PKGS),$($(x)_HDRS)) \
|
|
||||||
$(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 \
|
libc/integral/normalize.inc \
|
||||||
$(foreach x,$(COSMOPOLITAN_H_PKGS),$($(x)_HDRS))
|
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)) \
|
||||||
|
$(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_INCS))
|
||||||
|
$(file >$(TMPDIR)/$(subst /,_,$@),libc/integral/normalize.inc $(foreach x,$(COSMOPOLITAN_HEADERS),$($(x)_HDRS)))
|
||||||
|
@$(ECHO) '#define COSMO' >$@
|
||||||
|
@$(COMPILE) -AROLLUP -T$@ o/$(MODE)/tool/build/rollup.com @$(TMPDIR)/$(subst /,_,$@) >>$@
|
||||||
|
|
||||||
o/cosmopolitan.html: private .UNSANDBOXED = 1
|
o/cosmopolitan.html: private .UNSANDBOXED = 1
|
||||||
o/cosmopolitan.html: \
|
o/cosmopolitan.html: \
|
||||||
o/$(MODE)/third_party/chibicc/chibicc.dbg \
|
o/$(MODE)/third_party/chibicc/chibicc.com.dbg \
|
||||||
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \
|
$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))) \
|
||||||
$(filter-out %.cpp,$(filter-out %.cc,$(SRCS))) \
|
$(SRCS) \
|
||||||
$(HDRS)
|
$(HDRS)
|
||||||
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.cpp,$(filter-out %.cc,$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))))
|
$(file >$(TMPDIR)/$(subst /,_,$@),$(filter-out %.s,$(foreach x,$(COSMOPOLITAN_OBJECTS),$($(x)_SRCS))))
|
||||||
o/$(MODE)/third_party/chibicc/chibicc.dbg -J \
|
o/$(MODE)/third_party/chibicc/chibicc.com.dbg -J \
|
||||||
-fno-common -include libc/integral/normalize.inc -o $@ \
|
-fno-common -include libc/integral/normalize.inc -o $@ \
|
||||||
-DCOSMO @$(TMPDIR)/$(subst /,_,$@)
|
-DCOSMO @$(TMPDIR)/$(subst /,_,$@)
|
||||||
|
|
||||||
|
@ -574,42 +424,27 @@ $(SRCS): \
|
||||||
libc/integral/lp64arg.inc \
|
libc/integral/lp64arg.inc \
|
||||||
libc/integral/lp64.inc
|
libc/integral/lp64.inc
|
||||||
|
|
||||||
|
.PHONY: toolchain
|
||||||
ifeq ($(ARCH), x86_64)
|
ifeq ($(ARCH), x86_64)
|
||||||
TOOLCHAIN_ARTIFACTS = \
|
toolchain: o/cosmopolitan.h \
|
||||||
o/$(MODE)/ape/ape.lds \
|
o/$(MODE)/ape/public/ape.lds \
|
||||||
o/$(MODE)/libc/crt/crt.o \
|
o/$(MODE)/libc/crt/crt.o \
|
||||||
o/$(MODE)/ape/ape.elf \
|
|
||||||
o/$(MODE)/ape/ape.o \
|
o/$(MODE)/ape/ape.o \
|
||||||
o/$(MODE)/ape/ape-copy-self.o \
|
o/$(MODE)/ape/ape-copy-self.o \
|
||||||
o/$(MODE)/ape/ape-no-modify-self.o \
|
o/$(MODE)/ape/ape-no-modify-self.o \
|
||||||
o/$(MODE)/cosmopolitan.a \
|
o/$(MODE)/cosmopolitan.a \
|
||||||
o/$(MODE)/third_party/libcxx/libcxx.a \
|
o/$(MODE)/third_party/libcxx/libcxx.a \
|
||||||
o/$(MODE)/tool/build/march-native \
|
o/$(MODE)/tool/build/fixupobj.com \
|
||||||
o/$(MODE)/tool/build/ar \
|
o/$(MODE)/tool/build/zipcopy.com
|
||||||
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
|
else
|
||||||
TOOLCHAIN_ARTIFACTS = \
|
toolchain: o/$(MODE)/ape/aarch64.lds \
|
||||||
o/$(MODE)/ape/ape.elf \
|
|
||||||
o/$(MODE)/ape/aarch64.lds \
|
|
||||||
o/$(MODE)/libc/crt/crt.o \
|
o/$(MODE)/libc/crt/crt.o \
|
||||||
o/$(MODE)/cosmopolitan.a \
|
o/$(MODE)/cosmopolitan.a \
|
||||||
o/$(MODE)/third_party/libcxx/libcxx.a \
|
o/$(MODE)/third_party/libcxx/libcxx.a \
|
||||||
o/$(MODE)/tool/build/march-native \
|
o/$(MODE)/tool/build/fixupobj.com \
|
||||||
o/$(MODE)/tool/build/fixupobj \
|
o/$(MODE)/tool/build/zipcopy.com
|
||||||
o/$(MODE)/tool/build/zipcopy
|
|
||||||
endif
|
endif
|
||||||
|
|
||||||
.PHONY: toolchain
|
|
||||||
toolchain: $(TOOLCHAIN_ARTIFACTS)
|
|
||||||
|
|
||||||
.PHONY: clean_toolchain
|
|
||||||
clean_toolchain:
|
|
||||||
$(RM) $(TOOLCHAIN_ARTIFACTS)
|
|
||||||
|
|
||||||
aarch64: private .INTERNET = true
|
aarch64: private .INTERNET = true
|
||||||
aarch64: private .UNSANDBOXED = true
|
aarch64: private .UNSANDBOXED = true
|
||||||
aarch64:
|
aarch64:
|
||||||
|
|
408
README.md
408
README.md
|
@ -3,49 +3,75 @@
|
||||||
[](https://github.com/jart/cosmopolitan/actions/workflows/build.yml)
|
[](https://github.com/jart/cosmopolitan/actions/workflows/build.yml)
|
||||||
# Cosmopolitan
|
# Cosmopolitan
|
||||||
|
|
||||||
[Cosmopolitan Libc](https://justine.lol/cosmopolitan/index.html) makes C/C++
|
[Cosmopolitan Libc](https://justine.lol/cosmopolitan/index.html) makes C
|
||||||
a build-once run-anywhere language, like Java, except it doesn't need an
|
a build-once run-anywhere language, like Java, except it doesn't need an
|
||||||
interpreter or virtual machine. Instead, it reconfigures stock GCC and
|
interpreter or virtual machine. Instead, it reconfigures stock GCC and
|
||||||
Clang to output a POSIX-approved polyglot format that runs natively on
|
Clang to output a POSIX-approved polyglot format that runs natively on
|
||||||
Linux + Mac + Windows + FreeBSD + OpenBSD 7.3 + NetBSD + BIOS with the
|
Linux + Mac + Windows + FreeBSD + OpenBSD + NetBSD + BIOS with the best
|
||||||
best possible performance and the tiniest footprint imaginable.
|
possible performance and the tiniest footprint imaginable.
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
For an introduction to this project, please read the [actually portable
|
For an introduction to this project, please read the [αcτµαlly pδrταblε
|
||||||
executable](https://justine.lol/ape.html) blog post and [cosmopolitan
|
εxεcµταblε](https://justine.lol/ape.html) blog post and [cosmopolitan
|
||||||
libc](https://justine.lol/cosmopolitan/index.html) website. We also have
|
libc](https://justine.lol/cosmopolitan/index.html) website. We also have
|
||||||
[API
|
[API documentation](https://justine.lol/cosmopolitan/documentation.html).
|
||||||
documentation](https://justine.lol/cosmopolitan/documentation.html).
|
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
You can start by obtaining a release of our `cosmocc` compiler from
|
It's recommended that Cosmopolitan be installed to `/opt/cosmo` and
|
||||||
<https://cosmo.zip/pub/cosmocc/>.
|
`/opt/cosmos` on your computer. The first has the monorepo. The second
|
||||||
|
contains your non-monorepo artifacts.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
mkdir -p cosmocc
|
sudo mkdir -p /opt
|
||||||
cd cosmocc
|
sudo chmod 1777 /opt
|
||||||
wget https://cosmo.zip/pub/cosmocc/cosmocc.zip
|
git clone https://github.com/jart/cosmopolitan /opt/cosmo
|
||||||
unzip cosmocc.zip
|
cd /opt/cosmo
|
||||||
|
make -j8 toolchain
|
||||||
|
ape/apeinstall.sh # optional
|
||||||
|
mkdir -p /opt/cosmos/bin
|
||||||
|
export PATH="/opt/cosmos/bin:$PATH"
|
||||||
|
echo 'PATH="/opt/cosmos/bin:$PATH"' >>~/.profile
|
||||||
|
sudo ln -sf /opt/cosmo/tool/scripts/cosmocc /opt/cosmos/bin/cosmocc
|
||||||
|
sudo ln -sf /opt/cosmo/tool/scripts/cosmoc++ /opt/cosmos/bin/cosmoc++
|
||||||
```
|
```
|
||||||
|
|
||||||
Here's an example program we can write:
|
You've now successfully installed your very own cosmos. Now let's build
|
||||||
|
an example program, which demonstrates the crash reporting feature:
|
||||||
|
|
||||||
```c
|
```c
|
||||||
// hello.c
|
// hello.c
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <cosmo.h>
|
||||||
|
|
||||||
int main() {
|
int main() {
|
||||||
|
ShowCrashReports();
|
||||||
printf("hello world\n");
|
printf("hello world\n");
|
||||||
|
__builtin_trap();
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
It can be compiled as follows:
|
To compile the program, you can run the `cosmocc` command. It's
|
||||||
|
important to give it an output path that ends with `.com` so the output
|
||||||
|
format will be Actually Portable Executable. When this happens, a
|
||||||
|
concomitant debug binary is created automatically too.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cosmocc -o hello hello.c
|
cosmocc -o hello.com hello.c
|
||||||
./hello
|
./hello.com
|
||||||
|
./hello.com.dbg
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use the `cosmocc` toolchain to build conventional open source
|
||||||
|
projects which use autotools. This strategy normally works:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export CC=cosmocc
|
||||||
|
export CXX=cosmoc++
|
||||||
|
./configure --prefix=/opt/cosmos
|
||||||
|
make -j
|
||||||
|
make install
|
||||||
```
|
```
|
||||||
|
|
||||||
The Cosmopolitan Libc runtime links some heavyweight troubleshooting
|
The Cosmopolitan Libc runtime links some heavyweight troubleshooting
|
||||||
|
@ -53,115 +79,275 @@ features by default, which are very useful for developers and admins.
|
||||||
Here's how you can log system calls:
|
Here's how you can log system calls:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./hello --strace
|
./hello.com --strace
|
||||||
```
|
```
|
||||||
|
|
||||||
Here's how you can get a much more verbose log of function calls:
|
Here's how you can get a much more verbose log of function calls:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
./hello --ftrace
|
./hello.com --ftrace
|
||||||
```
|
```
|
||||||
|
|
||||||
You can use the Cosmopolitan's toolchain to build conventional open
|
If you want to cut out the bloat and instead make your executables as
|
||||||
source projects which use autotools. This strategy normally works:
|
tiny as possible, then the monorepo supports numerous build modes. You
|
||||||
|
can select one of the predefined ones by looking at
|
||||||
|
[build/config.mk](build/config.mk). One of the most popular modes is
|
||||||
|
`MODE=tiny`. It can be used with the `cosmocc` toolchain as follows:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
export CC=x86_64-unknown-cosmo-cc
|
cd /opt/cosmo
|
||||||
export CXX=x86_64-unknown-cosmo-c++
|
make -j8 MODE=tiny toolchain
|
||||||
./configure --prefix=/opt/cosmos/x86_64
|
|
||||||
make -j
|
|
||||||
make install
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Cosmopolitan Source Builds
|
Now that we have our toolchain, let's write a program that links less
|
||||||
|
surface area than the program above. The executable that this program
|
||||||
|
produces will run on platforms like Linux, Windows, MacOS, etc., even
|
||||||
|
though it's directly using POSIX APIs, which Cosmopolitan polyfills.
|
||||||
|
|
||||||
Cosmopolitan can be compiled from source on any of our supported
|
```c
|
||||||
platforms. The Makefile will download cosmocc automatically.
|
// hello2.c
|
||||||
|
#include <unistd.h>
|
||||||
|
int main() {
|
||||||
|
write(1, "hello world\n", 12);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
It's recommended that you install a systemwide APE Loader. This command
|
Now let's compile our tiny actually portable executable, which should be
|
||||||
requires `sudo` access to copy the `ape` command to a system folder and
|
on the order of 20kb in size.
|
||||||
register with binfmt_misc on Linux, for even more performance.
|
|
||||||
|
```sh
|
||||||
|
export MODE=tiny
|
||||||
|
cosmocc -Os -o hello2.com hello2.c
|
||||||
|
./hello2.com
|
||||||
|
```
|
||||||
|
|
||||||
|
Let's say you only care about Linux and would rather have simpler tinier
|
||||||
|
binaries, similar to what Musl Libc would produce. In that case, try
|
||||||
|
using the `MODE=tinylinux` build mode, which can produce binaries more
|
||||||
|
on the order of 4kb.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export MODE=tinylinux
|
||||||
|
(cd /opt/cosmo; make -j8 toolchain)
|
||||||
|
cosmocc -Os -o hello2.com hello2.c
|
||||||
|
./hello2.com # <-- actually an ELF executable
|
||||||
|
```
|
||||||
|
|
||||||
|
## ARM
|
||||||
|
|
||||||
|
Cosmo supports cross-compiling binaries for machines with ARM
|
||||||
|
microprocessors. There are two options available for doing this.
|
||||||
|
|
||||||
|
The first option is to embed the [blink virtual
|
||||||
|
machine](https://github.com/jart/blink) by adding the following to the
|
||||||
|
top of your main.c file:
|
||||||
|
|
||||||
|
```c
|
||||||
|
__static_yoink("blink_linux_aarch64"); // for raspberry pi
|
||||||
|
__static_yoink("blink_xnu_aarch64"); // is apple silicon
|
||||||
|
```
|
||||||
|
|
||||||
|
The benefit is you'll have single file executables that'll run on both
|
||||||
|
x86_64 and arm64 platforms. The tradeoff is Blink's JIT is slower than
|
||||||
|
running natively, but tends to go fast enough, unless you're doing
|
||||||
|
scientific computing (e.g. running LLMs with
|
||||||
|
`o//third_party/ggml/llama.com`).
|
||||||
|
|
||||||
|
Therefore, the second option is to cross compile aarch64 executables,
|
||||||
|
by using build modes like the following:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make -j8 m=aarch64 o/aarch64/third_party/ggml/llama.com
|
||||||
|
make -j8 m=aarch64-tiny o/aarch64-tiny/third_party/ggml/llama.com
|
||||||
|
```
|
||||||
|
|
||||||
|
That'll produce ELF executables that run natively on two operating
|
||||||
|
systems: Linux Arm64 (e.g. Raspberry Pi) and MacOS Arm64 (i.e. Apple
|
||||||
|
Silicon), thus giving you full performance. The catch is you have to
|
||||||
|
compile these executables on an x86_64-linux machine. The second catch
|
||||||
|
is that MacOS needs a little bit of help understanding the ELF format.
|
||||||
|
To solve that, we provide a tiny APE loader you can use on M1 machines.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
scp ape/ape-m1.c macintosh:
|
||||||
|
scp o/aarch64/third_party/ggml/llama.com macintosh:
|
||||||
|
ssh macintosh
|
||||||
|
xcode-install
|
||||||
|
cc -o ape ape-m1.c
|
||||||
|
sudo cp ape /usr/local/bin/ape
|
||||||
|
```
|
||||||
|
|
||||||
|
You can run your ELF AARCH64 executable on Apple Silicon as follows:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ape ./llama.com
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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
|
||||||
|
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
|
```sh
|
||||||
ape/apeinstall.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
|
Since the Cosmopolitan repository is very large, you might only want to
|
||||||
build one particular thing. Here's an example of a target that can be
|
build a particular thing. Cosmopolitan's build config does a good job at
|
||||||
compiled relatively quickly, which is a simple POSIX test that only
|
having minimal deterministic builds. For example, if you wanted to build
|
||||||
depends on core LIBC packages.
|
only hello.com then you could do that as follows:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
rm -rf o//libc o//test
|
build/bootstrap/make.com o//examples/hello.com
|
||||||
.cosmocc/current/bin/make o//test/posix/signal_test
|
|
||||||
o//test/posix/signal_test
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Sometimes it's desirable to build a subset of targets, without having to
|
Sometimes it's desirable to build a subset of targets, without having to
|
||||||
list out each individual one. For example if you wanted to build and run
|
list out each individual one. You can do that by asking make to build a
|
||||||
all the unit tests in the `TEST_POSIX` package, you could say:
|
directory name. For example, if you wanted to build only the targets and
|
||||||
|
subtargets of the chibicc package including its tests, you would say:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
.cosmocc/current/bin/make o//test/posix
|
build/bootstrap/make.com o//third_party/chibicc
|
||||||
|
o//third_party/chibicc/chibicc.com --help
|
||||||
```
|
```
|
||||||
|
|
||||||
Cosmopolitan provides a variety of build modes. For example, if you want
|
Cosmopolitan provides a variety of build modes. For example, if you want
|
||||||
really tiny binaries (as small as 12kb in size) then you'd say:
|
really tiny binaries (as small as 12kb in size) then you'd say:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
.cosmocc/current/bin/make m=tiny
|
build/bootstrap/make.com m=tiny
|
||||||
```
|
```
|
||||||
|
|
||||||
You can furthermore cut out the bloat of other operating systems, and
|
Here's some other build modes you can try:
|
||||||
have Cosmopolitan become much more similar to Musl Libc.
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
.cosmocc/current/bin/make m=tinylinux
|
build/bootstrap/make.com m=dbg # asan + ubsan + debug
|
||||||
|
build/bootstrap/make.com m=asan # production memory safety
|
||||||
|
build/bootstrap/make.com m=opt # -march=native optimizations
|
||||||
|
build/bootstrap/make.com m=rel # traditional release binaries
|
||||||
|
build/bootstrap/make.com m=optlinux # optimal linux-only performance
|
||||||
|
build/bootstrap/make.com m=fastbuild # build 28% faster w/o debugging
|
||||||
|
build/bootstrap/make.com m=tinylinux # tiniest linux-only 4kb binaries
|
||||||
```
|
```
|
||||||
|
|
||||||
For further details, see [//build/config.mk](build/config.mk).
|
For further details, see [//build/config.mk](build/config.mk).
|
||||||
|
|
||||||
## Debugging
|
## Cosmopolitan Amalgamation
|
||||||
|
|
||||||
To print a log of system calls to stderr:
|
Another way to use Cosmopolitan is via our amalgamated release, where
|
||||||
|
we've combined everything into a single static archive and a single
|
||||||
|
header file. If you're doing your development work on Linux or BSD then
|
||||||
|
you need just five files to get started. Here's what you do on Linux:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cosmocc -o hello hello.c
|
wget https://justine.lol/cosmopolitan/cosmopolitan-amalgamation-2.2.zip
|
||||||
./hello --strace
|
unzip cosmopolitan-amalgamation-2.2.zip
|
||||||
|
printf 'main() { printf("hello world\\n"); }\n' >hello.c
|
||||||
|
gcc -g -Os -static -nostdlib -nostdinc -fno-pie -no-pie -mno-red-zone \
|
||||||
|
-fno-omit-frame-pointer -pg -mnop-mcount -mno-tls-direct-seg-refs -gdwarf-4 \
|
||||||
|
-o hello.com.dbg hello.c -fuse-ld=bfd -Wl,-T,ape.lds -Wl,--gc-sections \
|
||||||
|
-Wl,-z,common-page-size=0x1000 -Wl,-z,max-page-size=0x1000 \
|
||||||
|
-include cosmopolitan.h crt.o ape-no-modify-self.o cosmopolitan.a
|
||||||
|
objcopy -S -O binary hello.com.dbg hello.com
|
||||||
```
|
```
|
||||||
|
|
||||||
To print a log of function calls to stderr:
|
You now have a portable program.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cosmocc -o hello hello.c
|
./hello.com
|
||||||
./hello --ftrace
|
bash -c './hello.com' # zsh/fish workaround (we patched them in 2021)
|
||||||
```
|
```
|
||||||
|
|
||||||
Both strace and ftrace use the unbreakable kprintf() facility, which is
|
If `./hello.com` executed on Linux throws an error about not finding an
|
||||||
able to be sent to a file by setting an environment variable.
|
interpreter, it should be fixed by running the following command (although
|
||||||
|
note that it may not survive a system restart):
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
export KPRINTF_LOG=log
|
sudo sh -c "echo ':APE:M::MZqFpD::/bin/sh:' >/proc/sys/fs/binfmt_misc/register"
|
||||||
./hello --strace
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If the same command produces puzzling errors on WSL or WINE when using
|
||||||
|
Redbean 2.x, they may be fixed by disabling binfmt_misc:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo sh -c 'echo -1 >/proc/sys/fs/binfmt_misc/status'
|
||||||
|
```
|
||||||
|
|
||||||
|
Since we used the `ape-no-modify-self.o` bootloader (rather than
|
||||||
|
`ape.o`) your executable will not modify itself when it's run. What
|
||||||
|
it'll instead do, is extract a 4kb program (the [APE loader](https://justine.lol/apeloader/))
|
||||||
|
to `${TMPDIR:-${HOME:-.}}` that maps your program into memory without
|
||||||
|
needing to copy it. The APE loader must be in an executable location
|
||||||
|
(e.g. not stored on a `noexec` mount) for it to run. See below for
|
||||||
|
alternatives:
|
||||||
|
|
||||||
|
It's possible to install the APE loader systemwide as follows.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# System-Wide APE Install
|
||||||
|
# for Linux, Darwin, and BSDs
|
||||||
|
# 1. Copies APE Loader to /usr/bin/ape
|
||||||
|
# 2. Registers w/ binfmt_misc too if Linux
|
||||||
|
ape/apeinstall.sh
|
||||||
|
|
||||||
|
# System-Wide APE Uninstall
|
||||||
|
# for Linux, Darwin, and BSDs
|
||||||
|
ape/apeuninstall.sh
|
||||||
|
```
|
||||||
|
|
||||||
|
It's also possible to convert APE binaries into the system-local format
|
||||||
|
by using the `--assimilate` flag. Please note that if binfmt_misc is in
|
||||||
|
play, you'll need to unregister it temporarily before doing this, since
|
||||||
|
the assimilate feature is part of the shell script header.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
$ file hello.com
|
||||||
|
hello.com: DOS/MBR boot sector
|
||||||
|
./hello.com --assimilate
|
||||||
|
$ file hello.com
|
||||||
|
hello.com: ELF 64-bit LSB executable
|
||||||
|
```
|
||||||
|
|
||||||
|
Now that you're up and running with Cosmopolitan Libc and APE, here's
|
||||||
|
some of the most important troubleshooting tools APE offers that you
|
||||||
|
should know, in case you encounter any issues:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./hello.com --strace # log system calls to stderr
|
||||||
|
./hello.com --ftrace # log function calls to stderr
|
||||||
|
```
|
||||||
|
|
||||||
|
Do you love tiny binaries? If so, you may not be happy with Cosmo adding
|
||||||
|
heavyweight features like tracing to your binaries by default. In that
|
||||||
|
case, you may want to consider using our build system:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make m=tiny
|
||||||
|
```
|
||||||
|
|
||||||
|
Which will cause programs such as `hello.com` and `life.com` to shrink
|
||||||
|
from 60kb in size to about 16kb. There's also a prebuilt amalgamation
|
||||||
|
online <https://justine.lol/cosmopolitan/cosmopolitan-tiny.zip> hosted
|
||||||
|
on our download page <https://justine.lol/cosmopolitan/download.html>.
|
||||||
|
|
||||||
## GDB
|
## GDB
|
||||||
|
|
||||||
Here's the recommended `~/.gdbinit` config:
|
Here's the recommended `~/.gdbinit` config:
|
||||||
|
@ -186,60 +372,46 @@ end
|
||||||
src
|
src
|
||||||
```
|
```
|
||||||
|
|
||||||
You normally run the `.dbg` file under gdb. If you need to debug the
|
You normally run the `.com.dbg` file under gdb. If you need to debug the
|
||||||
`` file itself, then you can load the debug symbols independently as
|
`.com` file itself, then you can load the debug symbols independently as
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
gdb foo -ex 'add-symbol-file foo.dbg 0x401000'
|
gdb foo.com -ex 'add-symbol-file foo.com.dbg 0x401000'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Platform Notes
|
## Alternative Development Environments
|
||||||
|
|
||||||
### Shells
|
### MacOS
|
||||||
|
|
||||||
If you use zsh and have trouble running APE programs try `sh -c ./prog`
|
If you're developing on MacOS you can install the GNU compiler
|
||||||
or simply upgrade to zsh 5.9+ (since we patched it two years ago). The
|
collection for x86_64-elf via homebrew:
|
||||||
same is the case for Python `subprocess`, old versions of fish, etc.
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
|
|
||||||
Some Linux systems are configured to launch MZ executables under WINE.
|
|
||||||
Other distros configure their stock installs so that APE programs will
|
|
||||||
print "run-detectors: unable to find an interpreter". For example:
|
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
jart@ubuntu:~$ wget https://cosmo.zip/pub/cosmos/bin/dash
|
brew install x86_64-elf-gcc
|
||||||
jart@ubuntu:~$ chmod +x dash
|
|
||||||
jart@ubuntu:~$ ./dash
|
|
||||||
run-detectors: unable to find an interpreter for ./dash
|
|
||||||
```
|
```
|
||||||
|
|
||||||
You can fix that by registering APE with `binfmt_misc`:
|
Then in the above scripts just replace `gcc` and `objcopy` with
|
||||||
|
`x86_64-elf-gcc` and `x86_64-elf-objcopy` to compile your APE binary.
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
If you're developing on Windows then you need to download an
|
||||||
|
x86_64-pc-linux-gnu toolchain beforehand. See the [Compiling on
|
||||||
|
Windows](https://justine.lol/cosmopolitan/windows-compiling.html)
|
||||||
|
tutorial. It's needed because the ELF object format is what makes
|
||||||
|
universal binaries possible.
|
||||||
|
|
||||||
|
Cosmopolitan officially only builds on Linux. However, one highly
|
||||||
|
experimental (and currently broken) thing you could try, is building the
|
||||||
|
entire cosmo repository from source using the cross9 toolchain.
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
sudo wget -O /usr/bin/ape https://cosmo.zip/pub/cosmos/bin/ape-$(uname -m).elf
|
mkdir -p o/third_party
|
||||||
sudo chmod +x /usr/bin/ape
|
rm -rf o/third_party/gcc
|
||||||
sudo sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
wget https://justine.lol/linux-compiler-on-windows/cross9.zip
|
||||||
sudo sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register"
|
unzip cross9.zip
|
||||||
```
|
mv cross9 o/third_party/gcc
|
||||||
|
build/bootstrap/make.com
|
||||||
You should be good now. APE will not only work, it'll launch executables
|
|
||||||
400µs faster now too. However if things still didn't work out, it's also
|
|
||||||
possible to disable `binfmt_misc` as follows:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/cli' # remove Ubuntu's MZ interpreter
|
|
||||||
sudo sh -c 'echo -1 > /proc/sys/fs/binfmt_misc/status' # remove ALL binfmt_misc entries
|
|
||||||
```
|
|
||||||
|
|
||||||
### WSL
|
|
||||||
|
|
||||||
It's normally unsafe to use APE in a WSL environment, because it tries
|
|
||||||
to run MZ executables as WIN32 binaries within the WSL environment. In
|
|
||||||
order to make it safe to use Cosmopolitan software on WSL, run this:
|
|
||||||
|
|
||||||
```sh
|
|
||||||
sudo sh -c "echo -1 > /proc/sys/fs/binfmt_misc/WSLInterop"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Discord Chatroom
|
## Discord Chatroom
|
||||||
|
@ -251,12 +423,12 @@ server. You're welcome to join us! <https://discord.gg/FwAVVu7eJ4>
|
||||||
|
|
||||||
| Platform | Min Version | Circa |
|
| Platform | Min Version | Circa |
|
||||||
| :--- | ---: | ---: |
|
| :--- | ---: | ---: |
|
||||||
| AMD | K8 | 2003 |
|
| AMD | K8 Venus | 2005 |
|
||||||
| Intel | Core | 2006 |
|
| Intel | Core | 2006 |
|
||||||
| Linux | 2.6.18 | 2007 |
|
| Linux | 2.6.18 | 2007 |
|
||||||
| Windows | 8 [1] | 2012 |
|
| Windows | 8 [1] | 2012 |
|
||||||
| Darwin (macOS) | 23.1.0+ | 2023 |
|
| Mac OS X | 15.6 | 2018 |
|
||||||
| OpenBSD | 7.3 or earlier | 2023 |
|
| OpenBSD | 7 | 2021 |
|
||||||
| FreeBSD | 13 | 2020 |
|
| FreeBSD | 13 | 2020 |
|
||||||
| NetBSD | 9.2 | 2021 |
|
| NetBSD | 9.2 | 2021 |
|
||||||
|
|
||||||
|
|
287
ape/BUILD.mk
287
ape/BUILD.mk
|
@ -1,287 +0,0 @@
|
||||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
|
||||||
#── vi: set noet ft=make ts=8 sw=8 fenc=utf-8 :vi ────────────────────┘
|
|
||||||
#
|
|
||||||
# OVERVIEW
|
|
||||||
#
|
|
||||||
# αcτµαlly pδrταblε εxεcµταblε
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# This file defines the libraries, runtimes, and build rules needed to
|
|
||||||
# create executables from your Linux workstation that'll run anywhere.
|
|
||||||
# Loading this package will make certain systemic modifications to the
|
|
||||||
# build like turning off the System V "Red Zone" optimization, because
|
|
||||||
# αcτµαlly pδrταblε εxεcµταblεs need to be able to run in kernelspace.
|
|
||||||
|
|
||||||
PKGS += APE
|
|
||||||
|
|
||||||
APE_FILES := $(wildcard ape/*.*)
|
|
||||||
APE_HDRS = $(filter %.h,$(APE_FILES))
|
|
||||||
APE_INCS = $(filter %.inc,$(APE_FILES))
|
|
||||||
|
|
||||||
ifeq ($(ARCH), aarch64)
|
|
||||||
|
|
||||||
APE = o/$(MODE)/ape/aarch64.lds
|
|
||||||
|
|
||||||
APELINK = \
|
|
||||||
$(COMPILE) \
|
|
||||||
-ALINK.ape \
|
|
||||||
$(LINK) \
|
|
||||||
$(LINKARGS) \
|
|
||||||
$(OUTPUT_OPTION) && \
|
|
||||||
$(COMPILE) \
|
|
||||||
-AFIXUP.ape \
|
|
||||||
-wT$@ \
|
|
||||||
$(FIXUPOBJ) \
|
|
||||||
$@
|
|
||||||
|
|
||||||
APE_SRCS = ape/ape.S ape/start.S ape/launch.S ape/systemcall.S
|
|
||||||
APE_OBJS = o/$(MODE)/ape/ape.o
|
|
||||||
APE_NO_MODIFY_SELF = $(APE)
|
|
||||||
APE_COPY_SELF = $(APE)
|
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/ape
|
|
||||||
o/$(MODE)/ape: $(APE)
|
|
||||||
|
|
||||||
o/$(MODE)/ape/aarch64.lds: \
|
|
||||||
ape/aarch64.lds \
|
|
||||||
libc/zip.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
libc/calls/struct/timespec.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/str/str.h
|
|
||||||
|
|
||||||
APE_LOADER_LDFLAGS = \
|
|
||||||
-pie \
|
|
||||||
-static \
|
|
||||||
-nostdlib \
|
|
||||||
--no-dynamic-linker \
|
|
||||||
-z norelro \
|
|
||||||
-z common-page-size=0x4000 \
|
|
||||||
-z max-page-size=0x4000
|
|
||||||
|
|
||||||
APE_LOADER_FLAGS = \
|
|
||||||
-DNDEBUG \
|
|
||||||
-iquote. \
|
|
||||||
-Wall \
|
|
||||||
-Wextra \
|
|
||||||
-fpie \
|
|
||||||
-Os \
|
|
||||||
-ffreestanding \
|
|
||||||
-mgeneral-regs-only \
|
|
||||||
-fno-asynchronous-unwind-tables \
|
|
||||||
-fno-stack-protector \
|
|
||||||
-fno-ident \
|
|
||||||
-fno-gnu-unique \
|
|
||||||
-c \
|
|
||||||
$(OUTPUT_OPTION) \
|
|
||||||
$<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
|
||||||
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
|
|
||||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.elf.dbg: \
|
|
||||||
o/$(MODE)/ape/start.o \
|
|
||||||
o/$(MODE)/ape/loader.o \
|
|
||||||
o/$(MODE)/ape/launch.o \
|
|
||||||
o/$(MODE)/ape/systemcall.o
|
|
||||||
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
|
||||||
|
|
||||||
o/$(MODE)/ape/loader.o: ape/loader.c ape/ape.h
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=33 -g $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/start.o: ape/start.S
|
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
|
||||||
o/$(MODE)/ape/launch.o: ape/launch.S
|
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
|
||||||
o/$(MODE)/ape/systemcall.o: ape/systemcall.S
|
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/ape
|
|
||||||
o/$(MODE)/ape: o/$(MODE)/ape/ape.elf
|
|
||||||
|
|
||||||
else
|
|
||||||
|
|
||||||
APE = o/$(MODE)/ape/ape.o \
|
|
||||||
o/$(MODE)/ape/ape.lds
|
|
||||||
|
|
||||||
APELINK = \
|
|
||||||
$(COMPILE) \
|
|
||||||
-ALINK.ape \
|
|
||||||
$(LINK) \
|
|
||||||
$(LINKARGS) \
|
|
||||||
$(OUTPUT_OPTION) && \
|
|
||||||
$(COMPILE) \
|
|
||||||
-AFIXUP.ape \
|
|
||||||
-wT$@ \
|
|
||||||
$(FIXUPOBJ) \
|
|
||||||
$@
|
|
||||||
|
|
||||||
APE_NO_MODIFY_SELF = \
|
|
||||||
o/$(MODE)/ape/ape.lds \
|
|
||||||
o/$(MODE)/ape/ape-no-modify-self.o
|
|
||||||
|
|
||||||
APE_COPY_SELF = \
|
|
||||||
o/$(MODE)/ape/ape.lds \
|
|
||||||
o/$(MODE)/ape/ape-copy-self.o
|
|
||||||
|
|
||||||
APE_LOADER_FLAGS = \
|
|
||||||
-DNDEBUG \
|
|
||||||
-iquote. \
|
|
||||||
-Wall \
|
|
||||||
-Wextra \
|
|
||||||
-Werror \
|
|
||||||
-pedantic-errors \
|
|
||||||
-fpie \
|
|
||||||
-Os \
|
|
||||||
-ffreestanding \
|
|
||||||
-mgeneral-regs-only \
|
|
||||||
-fno-stack-protector \
|
|
||||||
-fno-ident \
|
|
||||||
-fno-gnu-unique \
|
|
||||||
-c \
|
|
||||||
$(OUTPUT_OPTION) \
|
|
||||||
$<
|
|
||||||
|
|
||||||
APE_SRCS_C = ape/loader.c
|
|
||||||
APE_SRCS_S = $(filter %.S,$(APE_FILES))
|
|
||||||
APE_SRCS = $(APE_SRCS_C) $(APE_SRCS_S)
|
|
||||||
APE_OBJS = $(APE_SRCS_S:%.S=o/$(MODE)/%.o)
|
|
||||||
APE_CHECKS = $(APE_HDRS:%=o/%.ok)
|
|
||||||
|
|
||||||
o/ape/idata.inc: \
|
|
||||||
ape/idata.internal.h \
|
|
||||||
ape/relocations.h
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape-no-modify-self.o: \
|
|
||||||
ape/ape.S \
|
|
||||||
ape/ape.h \
|
|
||||||
ape/macros.internal.h \
|
|
||||||
ape/relocations.h \
|
|
||||||
ape/ape.internal.h \
|
|
||||||
libc/dce.h \
|
|
||||||
libc/elf/def.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
libc/macho.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/nexgen32e/uart.internal.h \
|
|
||||||
libc/calls/metalfile.internal.h \
|
|
||||||
libc/nt/pedef.internal.h \
|
|
||||||
libc/runtime/e820.internal.h \
|
|
||||||
libc/runtime/mman.internal.h \
|
|
||||||
libc/runtime/pc.internal.h \
|
|
||||||
libc/sysv/consts/prot.h \
|
|
||||||
o/$(MODE)/ape/ape.elf
|
|
||||||
@$(COMPILE) \
|
|
||||||
-AOBJECTIFY.S \
|
|
||||||
$(OBJECTIFY.S) \
|
|
||||||
$(OUTPUT_OPTION) \
|
|
||||||
-DAPE_NO_MODIFY_SELF \
|
|
||||||
-DAPE_LOADER='"o/$(MODE)/ape/ape.elf"' $<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape-copy-self.o: \
|
|
||||||
ape/ape.S \
|
|
||||||
ape/ape.h \
|
|
||||||
ape/macros.internal.h \
|
|
||||||
ape/relocations.h \
|
|
||||||
ape/ape.internal.h \
|
|
||||||
libc/dce.h \
|
|
||||||
libc/elf/def.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
libc/macho.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/nexgen32e/uart.internal.h \
|
|
||||||
libc/calls/metalfile.internal.h \
|
|
||||||
libc/nt/pedef.internal.h \
|
|
||||||
libc/runtime/e820.internal.h \
|
|
||||||
libc/runtime/mman.internal.h \
|
|
||||||
libc/runtime/pc.internal.h \
|
|
||||||
libc/sysv/consts/prot.h
|
|
||||||
@$(COMPILE) \
|
|
||||||
-AOBJECTIFY.S \
|
|
||||||
$(OBJECTIFY.S) \
|
|
||||||
$(OUTPUT_OPTION) \
|
|
||||||
-DAPE_NO_MODIFY_SELF $<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/loader.o: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -g $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/loader-gcc.asm: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/loader-clang.asm: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
|
||||||
|
|
||||||
o/$(MODE)/ape/loader-xnu.o: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -g $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/loader-xnu-gcc.asm: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
|
||||||
o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
|
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
|
||||||
@$(COMPILE) -AOBJBINCOPY -w $(OBJBINCOPY) -f -o $@ $<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.elf.dbg
|
|
||||||
@$(COMPILE) -AOBJBINCOPY -w $(OBJBINCOPY) -fm -o $@ $<
|
|
||||||
|
|
||||||
APE_LOADER_LDFLAGS = \
|
|
||||||
-static \
|
|
||||||
-nostdlib \
|
|
||||||
--no-dynamic-linker \
|
|
||||||
-z separate-code \
|
|
||||||
-z common-page-size=0x1000 \
|
|
||||||
-z max-page-size=0x10000
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.elf.dbg: \
|
|
||||||
o/$(MODE)/ape/loader-macho.o \
|
|
||||||
o/$(MODE)/ape/start.o \
|
|
||||||
o/$(MODE)/ape/loader.o \
|
|
||||||
o/$(MODE)/ape/launch.o \
|
|
||||||
o/$(MODE)/ape/systemcall.o \
|
|
||||||
ape/loader.lds
|
|
||||||
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
|
||||||
|
|
||||||
.PHONY: o/$(MODE)/ape
|
|
||||||
o/$(MODE)/ape: $(APE_CHECKS) \
|
|
||||||
o/$(MODE)/ape/ape.o \
|
|
||||||
o/$(MODE)/ape/ape.lds \
|
|
||||||
o/$(MODE)/ape/ape.elf \
|
|
||||||
o/$(MODE)/ape/ape.macho \
|
|
||||||
|
|
||||||
endif
|
|
||||||
|
|
||||||
# these assembly files are safe to build on aarch64
|
|
||||||
o/$(MODE)/ape/ape.o: \
|
|
||||||
ape/ape.S \
|
|
||||||
ape/ape.h \
|
|
||||||
libc/dce.h \
|
|
||||||
libc/elf/def.h \
|
|
||||||
ape/relocations.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
ape/ape.internal.h \
|
|
||||||
ape/macros.internal.h \
|
|
||||||
libc/macho.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/sysv/consts/prot.h \
|
|
||||||
libc/nt/pedef.internal.h \
|
|
||||||
libc/runtime/pc.internal.h \
|
|
||||||
libc/runtime/e820.internal.h \
|
|
||||||
libc/runtime/mman.internal.h \
|
|
||||||
libc/nexgen32e/uart.internal.h \
|
|
||||||
libc/calls/metalfile.internal.h
|
|
||||||
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
|
||||||
|
|
||||||
o/$(MODE)/ape/ape.lds: \
|
|
||||||
ape/ape.lds \
|
|
||||||
ape/macros.internal.h \
|
|
||||||
ape/relocations.h \
|
|
||||||
ape/ape.internal.h \
|
|
||||||
libc/thread/tls.h \
|
|
||||||
libc/calls/struct/timespec.h \
|
|
||||||
libc/thread/thread.h \
|
|
||||||
libc/dce.h \
|
|
||||||
libc/elf/def.h \
|
|
||||||
libc/elf/pf2prot.internal.h \
|
|
||||||
libc/macros.h \
|
|
||||||
libc/nt/pedef.internal.h \
|
|
||||||
libc/str/str.h \
|
|
||||||
libc/zip.h
|
|
|
@ -1,7 +1,6 @@
|
||||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/sysv/consts/prot.h"
|
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
|
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
@ -12,7 +11,7 @@ OUTPUT_FORMAT("elf64-littleaarch64",
|
||||||
|
|
||||||
SECTIONS {
|
SECTIONS {
|
||||||
|
|
||||||
. = SEGMENT_START("text-segment", 0x000800000000);
|
. = SEGMENT_START("text-segment", IMAGE_BASE_VIRTUAL);
|
||||||
__executable_start = .;
|
__executable_start = .;
|
||||||
. += SIZEOF_HEADERS;
|
. += SIZEOF_HEADERS;
|
||||||
|
|
||||||
|
@ -90,12 +89,10 @@ SECTIONS {
|
||||||
*(.ubsan.data)
|
*(.ubsan.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
.notice : {
|
.comment : {
|
||||||
__notices = .;
|
__comment_start = .;
|
||||||
KEEP(*(.notice))
|
KEEP(*(.comment))
|
||||||
BYTE(0);
|
BYTE(0);
|
||||||
BYTE(10);
|
|
||||||
BYTE(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.eh_frame_hdr : {
|
.eh_frame_hdr : {
|
||||||
|
@ -103,8 +100,10 @@ SECTIONS {
|
||||||
*(.eh_frame_entry .eh_frame_entry.*)
|
*(.eh_frame_entry .eh_frame_entry.*)
|
||||||
}
|
}
|
||||||
|
|
||||||
__eh_frame_hdr_start = SIZEOF(.eh_frame_hdr) > 0 ? ADDR(.eh_frame_hdr) : 0;
|
.eh_frame : ONLY_IF_RO {
|
||||||
__eh_frame_hdr_end = SIZEOF(.eh_frame_hdr) > 0 ? . : 0;
|
KEEP(*(.eh_frame))
|
||||||
|
*(.eh_frame.*)
|
||||||
|
}
|
||||||
|
|
||||||
.gcc_except_table : ONLY_IF_RO {
|
.gcc_except_table : ONLY_IF_RO {
|
||||||
*(.gcc_except_table .gcc_except_table.*)
|
*(.gcc_except_table .gcc_except_table.*)
|
||||||
|
@ -125,11 +124,9 @@ SECTIONS {
|
||||||
. += CONSTANT(MAXPAGESIZE);
|
. += CONSTANT(MAXPAGESIZE);
|
||||||
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
. = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
||||||
|
|
||||||
.eh_frame : {
|
.eh_frame : ONLY_IF_RW {
|
||||||
__eh_frame_start = .;
|
|
||||||
KEEP(*(.eh_frame))
|
KEEP(*(.eh_frame))
|
||||||
*(.eh_frame.*)
|
*(.eh_frame.*)
|
||||||
__eh_frame_end = .;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.gnu_extab : ONLY_IF_RW {
|
.gnu_extab : ONLY_IF_RW {
|
||||||
|
@ -160,11 +157,8 @@ SECTIONS {
|
||||||
|
|
||||||
.init_array : {
|
.init_array : {
|
||||||
__init_array_start = .;
|
__init_array_start = .;
|
||||||
KEEP(*(.preinit_array))
|
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
KEEP(*(.init_array EXCLUDE_FILE(*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
|
||||||
KEEP(*(.init_array))
|
|
||||||
KEEP(*(.ctors))
|
|
||||||
__init_array_end = .;
|
__init_array_end = .;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,9 +253,6 @@ SECTIONS {
|
||||||
.debug_ranges 0 : { *(.debug_ranges) }
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
.debug_macro 0 : { *(.debug_macro) }
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
.debug_addr 0 : { *(.debug_addr) }
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
.debug_names 0 : { *(.debug_names) }
|
|
||||||
.debug_loclists 0 : { *(.debug_loclists) }
|
|
||||||
.debug_str_offsets 0 : { *(.debug_str_offsets) }
|
|
||||||
.ARM.attributes 0 : { KEEP(*(.ARM.attributes)) KEEP(*(.gnu.attributes)) }
|
.ARM.attributes 0 : { KEEP(*(.ARM.attributes)) KEEP(*(.gnu.attributes)) }
|
||||||
.note.gnu.arm.ident 0 : { KEEP(*(.note.gnu.arm.ident)) }
|
.note.gnu.arm.ident 0 : { KEEP(*(.note.gnu.arm.ident)) }
|
||||||
|
|
||||||
|
@ -282,20 +273,18 @@ SECTIONS {
|
||||||
*(.gnu.lto_*)
|
*(.gnu.lto_*)
|
||||||
*(.eh_frame)
|
*(.eh_frame)
|
||||||
*(.idata.*)
|
*(.idata.*)
|
||||||
*(.yoink)
|
|
||||||
*(.head)
|
*(.head)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : APE_STACKSIZE;
|
||||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 8 * 1024 * 1024;
|
ape_stack_memsz2 = ape_stack_memsz * 2;
|
||||||
ape_stack_prot = PROT_READ | PROT_WRITE;
|
|
||||||
|
|
||||||
_tls_size = _tbss_end - _tdata_start;
|
_tls_size = _tbss_end - _tdata_start;
|
||||||
_tdata_size = _tdata_end - _tdata_start;
|
_tdata_size = _tdata_end - _tdata_start;
|
||||||
_tbss_size = _tbss_end - _tbss_start;
|
_tbss_size = _tbss_end - _tbss_start;
|
||||||
_tbss_offset = _tbss_start - _tdata_start;
|
_tbss_offset = _tbss_start - _tdata_start;
|
||||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||||
_tdata_align = ALIGNOF(.tdata);
|
_tls_align = MAX(ALIGNOF(.tdata), ALIGNOF(.tbss));
|
||||||
_tbss_align = ALIGNOF(.tbss);
|
|
||||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||||
|
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||||
|
|
849
ape/ape-m1.c
849
ape/ape-m1.c
File diff suppressed because it is too large
Load diff
184
ape/ape.S
184
ape/ape.S
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 nofixeol :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -33,17 +33,17 @@
|
||||||
│ αcτµαlly pδrταblε εxεcµταblε § program header │
|
│ αcτµαlly pδrταblε εxεcµταblε § program header │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "ape/macros.internal.h"
|
#include "ape/macros.internal.h"
|
||||||
|
#include "ape/notice.inc"
|
||||||
#include "ape/relocations.h"
|
#include "ape/relocations.h"
|
||||||
#include "libc/calls/metalfile.internal.h"
|
#include "libc/calls/metalfile.internal.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/elf/def.h"
|
#include "libc/elf/def.h"
|
||||||
#include "libc/macho.h"
|
#include "libc/macho.internal.h"
|
||||||
#include "libc/nexgen32e/uart.internal.h"
|
#include "libc/nexgen32e/uart.internal.h"
|
||||||
#include "libc/nt/pedef.internal.h"
|
#include "libc/nt/pedef.internal.h"
|
||||||
#include "libc/runtime/pc.internal.h"
|
#include "libc/runtime/pc.internal.h"
|
||||||
#include "ape/ape.internal.h"
|
#include "ape/ape.internal.h"
|
||||||
#include "libc/thread/tls.h"
|
#include "libc/thread/tls.h"
|
||||||
#include "ape/ape.h"
|
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
|
|
||||||
#define USE_SYMBOL_HACK 1
|
#define USE_SYMBOL_HACK 1
|
||||||
|
@ -196,7 +196,7 @@ ape_mz:
|
||||||
.quad ape_elf_entry // 18: e_entry
|
.quad ape_elf_entry // 18: e_entry
|
||||||
.quad ape_elf_phoff // 20: e_phoff
|
.quad ape_elf_phoff // 20: e_phoff
|
||||||
.quad ape_elf_shoff // 28: e_shoff
|
.quad ape_elf_shoff // 28: e_shoff
|
||||||
.long 0x101ca75 // 30: ape e_flags
|
.long 0 // 30: e_flags
|
||||||
.short 64 // 34: e_ehsize
|
.short 64 // 34: e_ehsize
|
||||||
.short 56 // 36: e_phentsize
|
.short 56 // 36: e_phentsize
|
||||||
.short ape_elf_phnum // 38: e_phnum
|
.short ape_elf_phnum // 38: e_phnum
|
||||||
|
@ -591,7 +591,7 @@ ape_disk:
|
||||||
|
|
||||||
#ifdef APE_IS_SHELL_SCRIPT
|
#ifdef APE_IS_SHELL_SCRIPT
|
||||||
apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
||||||
.ascii "m=$(uname -m 2>/dev/null) || m=x86_64\n"
|
.ascii "m=\"$(uname -m)\"\n"
|
||||||
|
|
||||||
.ascii "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n"
|
.ascii "if [ \"$m\" = x86_64 ] || [ \"$m\" = amd64 ]; then\n"
|
||||||
// Until all operating systems can be updated to support APE,
|
// Until all operating systems can be updated to support APE,
|
||||||
|
@ -610,9 +610,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
||||||
// extract the loader into a temp folder, and use it to
|
// extract the loader into a temp folder, and use it to
|
||||||
// load the APE without modifying it.
|
// load the APE without modifying it.
|
||||||
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
.ascii "[ x\"$1\" != x--assimilate ] && {\n"
|
||||||
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-"
|
.ascii "t=\"${TMPDIR:-${HOME:-.}}/.ape-1.5\"\n"
|
||||||
.ascii APE_VERSION_STR
|
|
||||||
.ascii "\"\n"
|
|
||||||
.ascii "[ -x \"$t\" ] || {\n"
|
.ascii "[ -x \"$t\" ] || {\n"
|
||||||
.ascii "mkdir -p \"${t%/*}\" &&\n"
|
.ascii "mkdir -p \"${t%/*}\" &&\n"
|
||||||
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
|
.ascii "dd if=\"$o\" of=\"$t.$$\" skip="
|
||||||
|
@ -669,7 +667,7 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
||||||
.shstub ape_elf_entry,8 // 18: e_entry
|
.shstub ape_elf_entry,8 // 18: e_entry
|
||||||
.shstub ape_elf_phoff,8 // 20: e_phoff
|
.shstub ape_elf_phoff,8 // 20: e_phoff
|
||||||
.shstub ape_elf_shoff,8 // 28: e_shoff
|
.shstub ape_elf_shoff,8 // 28: e_shoff
|
||||||
.ascii "\\165\\312\\1\\1" // 30: ape e_flags
|
.ascii "\\0\\0\\0\\0" // 30: e_flags
|
||||||
.ascii "\\100\\0" // 34: e_ehsize
|
.ascii "\\100\\0" // 34: e_ehsize
|
||||||
.ascii "\\070\\0" // 36: e_phentsize
|
.ascii "\\070\\0" // 36: e_phentsize
|
||||||
.shstub ape_elf_phnum,2 // 38: e_phnum
|
.shstub ape_elf_phnum,2 // 38: e_phnum
|
||||||
|
@ -699,10 +697,37 @@ apesh: .ascii "\n@\n#'\"\n" // sixth edition shebang
|
||||||
#endif /* APE_NO_MODIFY_SELF */
|
#endif /* APE_NO_MODIFY_SELF */
|
||||||
.ascii "exit $?\n"
|
.ascii "exit $?\n"
|
||||||
.ascii "fi\n" // x86_64
|
.ascii "fi\n" // x86_64
|
||||||
.ascii "echo error: this ape binary only supports x86_64 >&2\n"
|
// ...
|
||||||
.ascii "exit 1\n"
|
// decentralized section (.apesh)
|
||||||
|
// ...
|
||||||
|
.ascii "PHDRS='' <<'@'\n"
|
||||||
.endobj apesh
|
.endobj apesh
|
||||||
|
|
||||||
|
// elf program headers get inserted here
|
||||||
|
// because they need to be in the first 4096 bytes
|
||||||
|
.section .emushprologue,"a",@progbits
|
||||||
|
emush: .ascii "\n@\n#'\"\n"
|
||||||
|
.ascii "s=\"$(uname -s)\"\n"
|
||||||
|
// our script is running on a non-x86_64 architecture
|
||||||
|
// 1. `dd` out the appropriate blink vm blob
|
||||||
|
// 2. gunzip the blink virtual machine executable
|
||||||
|
// 3. relaunch this program inside the blink vm
|
||||||
|
.ascii "o=\"$(command -v \"$0\")\"\n"
|
||||||
|
.ascii "e=\"${TMPDIR:-${HOME:-.}}/.ape-blink-1.0.0\"\n"
|
||||||
|
.previous
|
||||||
|
// ...
|
||||||
|
// decentralized section (.emush)
|
||||||
|
// - __static_yoink("blink_linux_aarch64"); // for raspberry pi
|
||||||
|
// - __static_yoink("blink_xnu_aarch64"); // is apple silicon
|
||||||
|
// ...
|
||||||
|
.section .emushepilogue,"a",@progbits
|
||||||
|
.ascii "echo \"$0: this ape binary lacks $m support\" >&2\n"
|
||||||
|
.rept 16
|
||||||
|
.ascii "exit 127\n"
|
||||||
|
.endr
|
||||||
|
.ascii "exit 1\n"
|
||||||
|
.previous
|
||||||
|
|
||||||
#ifdef APE_LOADER
|
#ifdef APE_LOADER
|
||||||
.section .ape.loader,"a",@progbits
|
.section .ape.loader,"a",@progbits
|
||||||
.balign 64
|
.balign 64
|
||||||
|
@ -720,8 +745,6 @@ ape_loader_end:
|
||||||
#if SupportsSystemv() || SupportsMetal()
|
#if SupportsSystemv() || SupportsMetal()
|
||||||
.section .elf.phdrs,"a",@progbits
|
.section .elf.phdrs,"a",@progbits
|
||||||
|
|
||||||
.globl ape_phdrs
|
|
||||||
ape_phdrs:
|
|
||||||
.long PT_LOAD
|
.long PT_LOAD
|
||||||
.long PF_R|PF_X
|
.long PF_R|PF_X
|
||||||
.stub ape_cod_offset,quad
|
.stub ape_cod_offset,quad
|
||||||
|
@ -749,19 +772,30 @@ ape_phdrs:
|
||||||
.stub ape_ram_memsz,quad
|
.stub ape_ram_memsz,quad
|
||||||
.stub ape_ram_align,quad
|
.stub ape_ram_align,quad
|
||||||
|
|
||||||
// These values are left empty because some UNIX OSes give p_filesz
|
// APE Stack Configuration
|
||||||
// priority over `ulimit -s` a.k.a. RLIMIT_STACK which is preferred
|
//
|
||||||
// because we use an 8mb stack by default so that decadent software
|
// We actually respect this when allocating a deterministically
|
||||||
// doesn't unexpectedly crash, but putting that here meant NetBSD's
|
// addressed stack on Windows and other operating systems. However
|
||||||
// rusage accounting (which is the best) always reported 6mb of RSS
|
// there's a few caveats:
|
||||||
|
//
|
||||||
|
// - If ape_stack_pf has PF_X then OpenBSD probably won't work
|
||||||
|
// - We don't bother creating a deterministic stack in MODE=tiny
|
||||||
|
//
|
||||||
|
// With that said, here's some examples of configuration:
|
||||||
|
//
|
||||||
|
// STATIC_SYMBOL("ape_stack_pf", "7"); // RWX
|
||||||
|
// STATIC_STACK_ADDR(0x6fffffff0000);
|
||||||
|
// STATIC_STACK_SIZE(65536);
|
||||||
|
//
|
||||||
|
// @see ape.lds for defaults
|
||||||
.long PT_GNU_STACK
|
.long PT_GNU_STACK
|
||||||
.stub ape_stack_pf,long
|
.stub ape_stack_pf,long // override w/ PF_X for execstack
|
||||||
.quad 0
|
.stub ape_stack_offset,quad // ignored
|
||||||
.quad 0
|
.stub ape_stack_vaddr,quad // is mmap()'d with MAP_FIXED
|
||||||
.quad 0
|
.stub ape_stack_paddr,quad // ignored
|
||||||
.quad 0
|
.stub ape_stack_filesz,quad // ignored
|
||||||
.quad 0
|
.stub ape_stack_memsz2,quad // is mmap(size) argument
|
||||||
.quad 16
|
.stub ape_stack_align,quad // must be 16+
|
||||||
|
|
||||||
#if SupportsOpenbsd() || SupportsNetbsd()
|
#if SupportsOpenbsd() || SupportsNetbsd()
|
||||||
.long PT_NOTE
|
.long PT_NOTE
|
||||||
|
@ -784,7 +818,7 @@ ape.ident:
|
||||||
.long 1
|
.long 1
|
||||||
1: .asciz "APE"
|
1: .asciz "APE"
|
||||||
2: .balign 4
|
2: .balign 4
|
||||||
3: .long APE_VERSION_NOTE
|
3: .long 105000000
|
||||||
4: .size ape.ident,.-ape.ident
|
4: .size ape.ident,.-ape.ident
|
||||||
.type ape.ident,@object
|
.type ape.ident,@object
|
||||||
.previous
|
.previous
|
||||||
|
@ -1010,8 +1044,7 @@ DLLEXE = DLLSTD
|
||||||
// ││││││││ │ │┌6:Contains Initialized Data
|
// ││││││││ │ │┌6:Contains Initialized Data
|
||||||
// ││││││││ o │ ││┌5:Contains Code
|
// ││││││││ o │ ││┌5:Contains Code
|
||||||
// ││││││││┌┴─┐rrrr│ ooror│││rorrr
|
// ││││││││┌┴─┐rrrr│ ooror│││rorrr
|
||||||
PETEXT = 0b01100000000000000000000000100000
|
PETEXT = 0b01100000000000000000000001100000
|
||||||
PERDAT = 0b01000000000000000000000001000000
|
|
||||||
PEDATA = 0b11000000000000000000000011000000
|
PEDATA = 0b11000000000000000000000011000000
|
||||||
PEIMPS = 0b11000000000000000000000001000000
|
PEIMPS = 0b11000000000000000000000001000000
|
||||||
|
|
||||||
|
@ -1019,11 +1052,11 @@ PEIMPS = 0b11000000000000000000000001000000
|
||||||
.balign __SIZEOF_POINTER__
|
.balign __SIZEOF_POINTER__
|
||||||
ape_pe: .ascin "PE",4
|
ape_pe: .ascin "PE",4
|
||||||
.short kNtImageFileMachineNexgen32e
|
.short kNtImageFileMachineNexgen32e
|
||||||
.short ape_pe_shnum // NumberOfSections
|
.stub ape_pe_shnum,short // NumberOfSections
|
||||||
.long 0x5c64126b // TimeDateStamp
|
.long 0x5c64126b // TimeDateStamp
|
||||||
.long 0 // PointerToSymbolTable
|
.long 0 // PointerToSymbolTable
|
||||||
.long 0 // NumberOfSymbols
|
.long 0 // NumberOfSymbols
|
||||||
.short ape_pe_optsz // SizeOfOptionalHeader
|
.stub ape_pe_optsz,short // SizeOfOptionalHeader
|
||||||
.short PEEXE // Characteristics
|
.short PEEXE // Characteristics
|
||||||
.short kNtPe64bit // Optional Header Magic
|
.short kNtPe64bit // Optional Header Magic
|
||||||
.byte 14 // MajorLinkerVersion
|
.byte 14 // MajorLinkerVersion
|
||||||
|
@ -1036,7 +1069,7 @@ ape_pe: .ascin "PE",4
|
||||||
.quad ape_pe_base // ImageBase
|
.quad ape_pe_base // ImageBase
|
||||||
.long ape_pe_sectionalignment // SectionAlignment
|
.long ape_pe_sectionalignment // SectionAlignment
|
||||||
.long ape_pe_filealignment // FileAlignment
|
.long ape_pe_filealignment // FileAlignment
|
||||||
.short 10 // MajorOperatingSystemVersion
|
.short v_ntversion // MajorOperatingSystemVersion
|
||||||
.short 0 // MinorOperatingSystemVersion
|
.short 0 // MinorOperatingSystemVersion
|
||||||
.short 0 // MajorImageVersion
|
.short 0 // MajorImageVersion
|
||||||
.short 0 // MinorImageVersion
|
.short 0 // MinorImageVersion
|
||||||
|
@ -1047,25 +1080,25 @@ ape_pe: .ascin "PE",4
|
||||||
.long ape_pe_sizeofheaders // SizeOfHeaders
|
.long ape_pe_sizeofheaders // SizeOfHeaders
|
||||||
.long 0 // Checksum
|
.long 0 // Checksum
|
||||||
.short v_ntsubsystem // Subsystem: 0=Neutral,2=GUI,3=Console
|
.short v_ntsubsystem // Subsystem: 0=Neutral,2=GUI,3=Console
|
||||||
.short v_ntdllchar // DllCharacteristics
|
.stub v_ntdllchar,short // DllCharacteristics
|
||||||
.quad 0x10000 // StackReserve
|
.quad 0x0000000000100000 // StackReserve
|
||||||
.quad 0x1000 // StackCommit
|
.quad 0x00000000000fc000 // StackCommit
|
||||||
.quad 0 // HeapReserve
|
.quad 0 // HeapReserve
|
||||||
.quad 0 // HeapCommit
|
.quad 0 // HeapCommit
|
||||||
.long 0 // LoaderFlags
|
.long 0 // LoaderFlags
|
||||||
.long 2 // NumberOfDirectoryEntries
|
.long 2 // NumberOfDirectoryEntries
|
||||||
.long 0,0 // ExportsDirectory
|
.long 0,0 // ExportsDirectory
|
||||||
.long ape_idata // ImportsDirectory
|
.stub ape_idata,long // ImportsDirectory
|
||||||
.long ape_idata_idtsize // ImportsDirectorySize
|
.stub ape_idata_idtsize,long // ImportsDirectorySize
|
||||||
.endobj ape_pe,globl
|
.endobj ape_pe,globl
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.section .pe.sections,"a",@progbits
|
.section .pe.sections,"a",@progbits
|
||||||
.ascin ".text",8 // Section Name
|
.ascin ".text",8 // Section Name
|
||||||
.long ape_text_memsz // Virtual Size or Physical Address
|
.stub ape_text_memsz,long // Virtual Size or Physical Address
|
||||||
.long ape_text_rva // Relative Virtual Address
|
.stub ape_text_rva,long // Relative Virtual Address
|
||||||
.long ape_text_filesz // Physical Size
|
.stub ape_text_filesz,long // Physical Size
|
||||||
.long ape_text_offset // Physical Offset
|
.stub ape_text_offset,long // Physical Offset
|
||||||
.long 0 // Relocation Table Offset
|
.long 0 // Relocation Table Offset
|
||||||
.long 0 // Line Number Table Offset
|
.long 0 // Line Number Table Offset
|
||||||
.short 0 // Relocation Count
|
.short 0 // Relocation Count
|
||||||
|
@ -1073,25 +1106,12 @@ ape_pe: .ascin "PE",4
|
||||||
.long PETEXT // Flags
|
.long PETEXT // Flags
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.section .pe.sections,"a",@progbits
|
|
||||||
.ascin ".rdata",8 // Section Name
|
|
||||||
.long ape_rom_memsz // Virtual Size or Physical Address
|
|
||||||
.long ape_rom_rva // Relative Virtual Address
|
|
||||||
.long ape_rom_filesz // Physical Size
|
|
||||||
.long ape_rom_offset // Physical Offset
|
|
||||||
.long 0 // Relocation Table Offset
|
|
||||||
.long 0 // Line Number Table Offset
|
|
||||||
.short 0 // Relocation Count
|
|
||||||
.short 0 // Line Number Count
|
|
||||||
.long PERDAT // Flags
|
|
||||||
.previous
|
|
||||||
|
|
||||||
.section .pe.sections,"a",@progbits
|
.section .pe.sections,"a",@progbits
|
||||||
.ascin ".data",8 // Section Name
|
.ascin ".data",8 // Section Name
|
||||||
.long ape_ram_memsz // Virtual Size or Physical Address
|
.stub ape_ram_memsz,long // Virtual Size or Physical Address
|
||||||
.long ape_ram_rva // Relative Virtual Address
|
.stub ape_ram_rva,long // Relative Virtual Address
|
||||||
.long ape_ram_filesz // Physical Size
|
.stub ape_ram_filesz,long // Physical Size
|
||||||
.long ape_ram_offset // Physical Offset
|
.stub ape_ram_offset,long // Physical Offset
|
||||||
.long 0 // Relocation Table Offset
|
.long 0 // Relocation Table Offset
|
||||||
.long 0 // Line Number Table Offset
|
.long 0 // Line Number Table Offset
|
||||||
.short 0 // Relocation Count
|
.short 0 // Relocation Count
|
||||||
|
@ -1108,7 +1128,6 @@ ape_pe: .ascin "PE",4
|
||||||
.type ape_idata_idt,@object
|
.type ape_idata_idt,@object
|
||||||
.globl ape_idata_idt,ape_idata_idtend
|
.globl ape_idata_idt,ape_idata_idtend
|
||||||
.hidden ape_idata_idt,ape_idata_idtend
|
.hidden ape_idata_idt,ape_idata_idtend
|
||||||
.balign 4
|
|
||||||
ape_idata_idt:
|
ape_idata_idt:
|
||||||
.previous/*
|
.previous/*
|
||||||
...
|
...
|
||||||
|
@ -1117,7 +1136,6 @@ ape_idata_idt:
|
||||||
*/.section .idata.ro.idt.3,"a",@progbits
|
*/.section .idata.ro.idt.3,"a",@progbits
|
||||||
.long 0,0,0,0,0
|
.long 0,0,0,0,0
|
||||||
ape_idata_idtend:
|
ape_idata_idtend:
|
||||||
.byte 0
|
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
.section .piro.data.sort.iat.1,"aw",@progbits
|
.section .piro.data.sort.iat.1,"aw",@progbits
|
||||||
|
@ -1125,16 +1143,13 @@ ape_idata_idtend:
|
||||||
.type ape_idata_iat,@object
|
.type ape_idata_iat,@object
|
||||||
.globl ape_idata_iat,ape_idata_iatend
|
.globl ape_idata_iat,ape_idata_iatend
|
||||||
.hidden ape_idata_iat,ape_idata_iatend
|
.hidden ape_idata_iat,ape_idata_iatend
|
||||||
.balign 8
|
|
||||||
ape_idata_iat:
|
ape_idata_iat:
|
||||||
.previous/*
|
.previous/*
|
||||||
...
|
...
|
||||||
decentralized content
|
decentralized content
|
||||||
...
|
...
|
||||||
*/.section .piro.data.sort.iat.3,"aw",@progbits
|
*/.section .piro.data.sort.iat.3,"aw",@progbits
|
||||||
.quad 0
|
|
||||||
ape_idata_iatend:
|
ape_idata_iatend:
|
||||||
.byte 0
|
|
||||||
.previous
|
.previous
|
||||||
|
|
||||||
#endif /* SupportsWindows() */
|
#endif /* SupportsWindows() */
|
||||||
|
@ -1244,6 +1259,8 @@ realmodeloader:
|
||||||
call lhinit
|
call lhinit
|
||||||
call rlinit
|
call rlinit
|
||||||
call sinit4
|
call sinit4
|
||||||
|
.optfn _start16
|
||||||
|
call _start16
|
||||||
call longmodeloader
|
call longmodeloader
|
||||||
.endfn realmodeloader
|
.endfn realmodeloader
|
||||||
|
|
||||||
|
@ -1701,7 +1718,7 @@ ape_grub_entry:
|
||||||
│ αcτµαlly pδrταblε εxεcµταblε § cosmopolitan libc runtime runtime ─╬─│┼
|
│ αcτµαlly pδrταblε εxεcµταblε § cosmopolitan libc runtime runtime ─╬─│┼
|
||||||
╚────────────────────────────────────────────────────────────────────────────│*/
|
╚────────────────────────────────────────────────────────────────────────────│*/
|
||||||
kernel: movabs $ape_stack_vaddr,%rsp
|
kernel: movabs $ape_stack_vaddr,%rsp
|
||||||
add $ape_stack_memsz,%rsp
|
add $ape_stack_memsz2,%rsp
|
||||||
movl $0,0x7b000 // unmap null 2mb
|
movl $0,0x7b000 // unmap null 2mb
|
||||||
#if USE_SYMBOL_HACK
|
#if USE_SYMBOL_HACK
|
||||||
.byte 0x0f,0x1f,0207 // nop rdi binbase
|
.byte 0x0f,0x1f,0207 // nop rdi binbase
|
||||||
|
@ -1771,31 +1788,49 @@ kernel: movabs $ape_stack_vaddr,%rsp
|
||||||
.type ape_text_nops,@object
|
.type ape_text_nops,@object
|
||||||
.type __test_end,@object
|
.type __test_end,@object
|
||||||
|
|
||||||
|
.section .commentprologue,"a",@progbits
|
||||||
|
.globl __comment_start
|
||||||
|
.type __comment_start,@object
|
||||||
|
.hidden __comment_start
|
||||||
|
__comment_start:/*
|
||||||
|
...
|
||||||
|
decentralized content
|
||||||
|
...
|
||||||
|
*/.previous
|
||||||
|
.section .commentepilogue,"a",@progbits
|
||||||
|
.byte 0
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .ape.pad.head,"a",@progbits
|
.section .ape.pad.head,"a",@progbits
|
||||||
.type ape_pad_head,@object
|
.type ape_pad_head,@object
|
||||||
.hidden ape_pad_head
|
.hidden ape_pad_head
|
||||||
ape_pad_head:
|
ape_pad_head:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .ape.pad.text,"a",@progbits
|
.section .ape.pad.text,"a",@progbits
|
||||||
.type ape_pad_text,@object
|
.type ape_pad_text,@object
|
||||||
.hidden ape_pad_text
|
.hidden ape_pad_text
|
||||||
ape_pad_text:
|
ape_pad_text:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .ape.pad.privileged,"a",@progbits
|
.section .ape.pad.privileged,"a",@progbits
|
||||||
.type ape_pad_privileged,@object
|
.type ape_pad_privileged,@object
|
||||||
.hidden ape_pad_privileged
|
.hidden ape_pad_privileged
|
||||||
ape_pad_privileged:
|
ape_pad_privileged:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .ape.pad.data,"a",@progbits
|
.section .ape.pad.data,"a",@progbits
|
||||||
.type ape_pad_data,@object
|
.type ape_pad_data,@object
|
||||||
.hidden ape_pad_data
|
.hidden ape_pad_data
|
||||||
ape_pad_data:
|
ape_pad_data:
|
||||||
|
.previous
|
||||||
|
|
||||||
#if SupportsWindows()
|
#if SupportsWindows()
|
||||||
.section .idata.ro,"a",@progbits
|
.section .idata.ro,"a",@progbits
|
||||||
.type ape_idata_ro,@object
|
.type ape_idata_ro,@object
|
||||||
.hidden ape_idata_ro
|
.hidden ape_idata_ro
|
||||||
ape_idata_ro:
|
ape_idata_ro:
|
||||||
|
.previous
|
||||||
#endif /* SupportsWindows() */
|
#endif /* SupportsWindows() */
|
||||||
|
|
||||||
.section .dataprologue,"aw",@progbits
|
.section .dataprologue,"aw",@progbits
|
||||||
|
@ -1803,45 +1838,32 @@ ape_idata_ro:
|
||||||
.globl __data_start
|
.globl __data_start
|
||||||
.hidden __data_start
|
.hidden __data_start
|
||||||
__data_start:
|
__data_start:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .dataepilogue,"aw",@progbits
|
.section .dataepilogue,"aw",@progbits
|
||||||
.type __data_end,@object
|
.type __data_end,@object
|
||||||
.globl __data_end
|
.globl __data_end
|
||||||
.hidden __data_end
|
.hidden __data_end
|
||||||
__data_end:
|
__data_end:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .bssprologue,"aw",@nobits
|
.section .bssprologue,"aw",@nobits
|
||||||
.type __bss_start,@object
|
.type __bss_start,@object
|
||||||
.globl __bss_start
|
.globl __bss_start
|
||||||
.hidden __bss_start
|
.hidden __bss_start
|
||||||
__bss_start:
|
__bss_start:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .bssepilogue,"aw",@nobits
|
.section .bssepilogue,"aw",@nobits
|
||||||
.type __bss_end,@object
|
.type __bss_end,@object
|
||||||
.globl __bss_end
|
.globl __bss_end
|
||||||
.hidden __bss_end
|
.hidden __bss_end
|
||||||
__bss_end:
|
__bss_end:
|
||||||
|
.previous
|
||||||
|
|
||||||
.section .fstls,"awT",@nobits
|
.section .fstls,"awT",@nobits
|
||||||
.align TLS_ALIGNMENT
|
.align TLS_ALIGNMENT
|
||||||
|
.previous
|
||||||
.section .notice,"aR",@progbits
|
|
||||||
.asciz "\n\n\
|
|
||||||
Cosmopolitan\n\
|
|
||||||
Copyright 2024 Justine Alexandra Roberts Tunney\n\
|
|
||||||
\n\
|
|
||||||
Permission to use, copy, modify, and/or distribute this software for\n\
|
|
||||||
any purpose with or without fee is hereby granted, provided that the\n\
|
|
||||||
above copyright notice and this permission notice appear in all copies.\n\
|
|
||||||
\n\
|
|
||||||
THE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL\n\
|
|
||||||
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED\n\
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE\n\
|
|
||||||
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL\n\
|
|
||||||
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR\n\
|
|
||||||
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER\n\
|
|
||||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\n\
|
|
||||||
PERFORMANCE OF THIS SOFTWARE."
|
|
||||||
|
|
||||||
.end
|
.end
|
||||||
|
|
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_ */
|
|
193
ape/ape.lds
193
ape/ape.lds
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -198,10 +198,6 @@
|
||||||
#define SKEW 0
|
#define SKEW 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef IMAGE_BASE_VIRTUAL
|
|
||||||
#define IMAGE_BASE_VIRTUAL 0x400000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if IMAGE_BASE_VIRTUAL > 0xffffffff
|
#if IMAGE_BASE_VIRTUAL > 0xffffffff
|
||||||
#error "please use 32-bit addresses for image data"
|
#error "please use 32-bit addresses for image data"
|
||||||
#endif
|
#endif
|
||||||
|
@ -229,16 +225,21 @@ SECTIONS {
|
||||||
|
|
||||||
/* Real Mode */
|
/* Real Mode */
|
||||||
KEEP(*(.head))
|
KEEP(*(.head))
|
||||||
|
KEEP(*(.apesh))
|
||||||
KEEP(*(.text.head))
|
KEEP(*(.text.head))
|
||||||
|
|
||||||
/* Executable & Linkable Format */
|
/* Executable & Linkable Format */
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
ape_phdrs = .;
|
ape_phdrs = .;
|
||||||
KEEP(*(.elf.phdrs))
|
KEEP(*(.elf.phdrs))
|
||||||
ape_phdrs_end = .;
|
ape_phdrs_end = .;
|
||||||
|
|
||||||
|
KEEP(*(.emushprologue))
|
||||||
|
KEEP(*(.emush))
|
||||||
|
KEEP(*(.emushepilogue))
|
||||||
|
|
||||||
/* OpenBSD */
|
/* OpenBSD */
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
ape_note = .;
|
ape_note = .;
|
||||||
KEEP(*(.note.openbsd.ident))
|
KEEP(*(.note.openbsd.ident))
|
||||||
KEEP(*(.note.netbsd.ident))
|
KEEP(*(.note.netbsd.ident))
|
||||||
|
@ -252,15 +253,15 @@ SECTIONS {
|
||||||
|
|
||||||
/* Mach-O */
|
/* Mach-O */
|
||||||
KEEP(*(.macho))
|
KEEP(*(.macho))
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
ape_macho_end = .;
|
ape_macho_end = .;
|
||||||
|
|
||||||
/* APE loader */
|
/* APE loader */
|
||||||
KEEP(*(.ape.loader))
|
KEEP(*(.ape.loader))
|
||||||
. = ALIGN(. != 0 ? CODE_GRANULE : 0);
|
. = ALIGN(CODE_GRANULE);
|
||||||
|
|
||||||
KEEP(*(.ape.pad.head))
|
KEEP(*(.ape.pad.head))
|
||||||
. = ALIGN(. != 0 ? (SupportsWindows() || SupportsMetal() ? CONSTANT(COMMONPAGESIZE) : 16) : 0);
|
. = ALIGN(SupportsWindows() || SupportsMetal() ? CONSTANT(COMMONPAGESIZE) : 16);
|
||||||
_ehead = .;
|
_ehead = .;
|
||||||
} :Head
|
} :Head
|
||||||
|
|
||||||
|
@ -282,9 +283,12 @@ SECTIONS {
|
||||||
KEEP(*(SORT_BY_NAME(.init.*)))
|
KEEP(*(SORT_BY_NAME(.init.*)))
|
||||||
KEEP(*(.init))
|
KEEP(*(.init))
|
||||||
KEEP(*(.initepilogue))
|
KEEP(*(.initepilogue))
|
||||||
|
KEEP(*(.pltprologue))
|
||||||
*(.plt)
|
*(.plt)
|
||||||
|
KEEP(*(.pltepilogue))
|
||||||
|
KEEP(*(.pltgotprologue))
|
||||||
*(.plt.got)
|
*(.plt.got)
|
||||||
*(.iplt)
|
KEEP(*(.pltgotepilogue))
|
||||||
*(.text.startup .text.startup.*)
|
*(.text.startup .text.startup.*)
|
||||||
*(.text.exit .text.exit.*)
|
*(.text.exit .text.exit.*)
|
||||||
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
@ -293,6 +297,7 @@ SECTIONS {
|
||||||
KEEP(*(.textwindowsprologue))
|
KEEP(*(.textwindowsprologue))
|
||||||
*(.text.windows)
|
*(.text.windows)
|
||||||
KEEP(*(.textwindowsepilogue))
|
KEEP(*(.textwindowsepilogue))
|
||||||
|
KEEP(*(.blink))
|
||||||
*(SORT_BY_ALIGNMENT(.text.modernity))
|
*(SORT_BY_ALIGNMENT(.text.modernity))
|
||||||
*(SORT_BY_ALIGNMENT(.text.modernity.*))
|
*(SORT_BY_ALIGNMENT(.text.modernity.*))
|
||||||
*(SORT_BY_ALIGNMENT(.text.hot))
|
*(SORT_BY_ALIGNMENT(.text.hot))
|
||||||
|
@ -307,20 +312,20 @@ SECTIONS {
|
||||||
|
|
||||||
/* Privileged code invulnerable to magic */
|
/* Privileged code invulnerable to magic */
|
||||||
KEEP(*(.ape.pad.privileged));
|
KEEP(*(.ape.pad.privileged));
|
||||||
. = ALIGN(__privileged_end > __privileged_start ? CONSTANT(COMMONPAGESIZE) : 0);
|
. = ALIGN(__privileged_end > __privileged_start ? CONSTANT(COMMONPAGESIZE) : 1);
|
||||||
/*END: morphable code */
|
/*END: morphable code */
|
||||||
__privileged_start = .;
|
__privileged_start = .;
|
||||||
*(.privileged .privileged.*)
|
*(.privileged)
|
||||||
__privileged_end = .;
|
__privileged_end = .;
|
||||||
|
|
||||||
KEEP(*(.ape.pad.text))
|
KEEP(*(.ape.pad.text))
|
||||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||||
/*END: Read Only Data (only needed for initialization) */
|
/*END: Read Only Data (only needed for initialization) */
|
||||||
} :Cod
|
} :Cod
|
||||||
|
|
||||||
/*BEGIN: Read Only Data */
|
/*BEGIN: Read Only Data */
|
||||||
|
|
||||||
.rodata ALIGN(CONSTANT(COMMONPAGESIZE)) : {
|
.rodata . : {
|
||||||
KEEP(*(.rodata.pytab.0));
|
KEEP(*(.rodata.pytab.0));
|
||||||
KEEP(*(.rodata.pytab.1));
|
KEEP(*(.rodata.pytab.1));
|
||||||
KEEP(*(.rodata.pytab.2));
|
KEEP(*(.rodata.pytab.2));
|
||||||
|
@ -329,16 +334,12 @@ SECTIONS {
|
||||||
*(.ubsan.types)
|
*(.ubsan.types)
|
||||||
*(.ubsan.data)
|
*(.ubsan.data)
|
||||||
|
|
||||||
__eh_frame_hdr_start_actual = .;
|
|
||||||
*(.eh_frame_hdr)
|
|
||||||
__eh_frame_hdr_end_actual = .;
|
|
||||||
|
|
||||||
/* Legal Notices */
|
/* Legal Notices */
|
||||||
__notices = .;
|
#if !defined(IM_FEELING_NAUGHTY) || defined(EMBED_NOTICES)
|
||||||
KEEP(*(.notice))
|
KEEP(*(.commentprologue))
|
||||||
BYTE(0);
|
KEEP(*(.comment))
|
||||||
BYTE(10);
|
KEEP(*(.commentepilogue))
|
||||||
BYTE(10);
|
#endif
|
||||||
|
|
||||||
/*BEGIN: read-only data that's only needed for initialization */
|
/*BEGIN: read-only data that's only needed for initialization */
|
||||||
|
|
||||||
|
@ -348,12 +349,28 @@ SECTIONS {
|
||||||
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
|
KEEP(*(SORT_BY_NAME(.idata.ro.*)))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
|
__init_array_start = .;
|
||||||
|
KEEP(*(SORT_BY_INIT_PRIORITY(.init_array.*)
|
||||||
|
SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP(*(.ctors))
|
||||||
|
KEEP(*(.init_array))
|
||||||
|
KEEP(*(.preinit_array))
|
||||||
|
__init_array_end = .;
|
||||||
|
|
||||||
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
|
__fini_array_start = .;
|
||||||
|
KEEP(*(SORT_BY_INIT_PRIORITY(.fini_array.*)
|
||||||
|
SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP(*(.fini_array))
|
||||||
|
KEEP(*(.dtors))
|
||||||
|
__fini_array_end = .;
|
||||||
|
|
||||||
/* Encoded Data Structures w/ Linear Initialization Order */
|
/* Encoded Data Structures w/ Linear Initialization Order */
|
||||||
KEEP(*(.initroprologue))
|
KEEP(*(.initroprologue))
|
||||||
KEEP(*(SORT_BY_NAME(.initro.*)))
|
KEEP(*(SORT_BY_NAME(.initro.*)))
|
||||||
KEEP(*(.initroepilogue))
|
KEEP(*(.initroepilogue))
|
||||||
KEEP(*(SORT_BY_NAME(.sort.rodata.*)))
|
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 */
|
/*END: read-only data that's only needed for initialization */
|
||||||
|
|
||||||
|
@ -367,13 +384,14 @@ SECTIONS {
|
||||||
*(SORT_BY_ALIGNMENT(.tdata.*))
|
*(SORT_BY_ALIGNMENT(.tdata.*))
|
||||||
_tdata_end = .;
|
_tdata_end = .;
|
||||||
KEEP(*(.ape.pad.rodata))
|
KEEP(*(.ape.pad.rodata))
|
||||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||||
_etext = .;
|
_etext = .;
|
||||||
PROVIDE(etext = .);
|
PROVIDE(etext = .);
|
||||||
} :Tls :Rom
|
} :Tls :Rom
|
||||||
/*END: Read Only Data */
|
/*END: Read Only Data */
|
||||||
|
|
||||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
. = DATA_SEGMENT_ALIGN(CONSTANT(COMMONPAGESIZE), CONSTANT(COMMONPAGESIZE));
|
||||||
|
. = DATA_SEGMENT_RELRO_END(0, .);
|
||||||
|
|
||||||
/* this only tells the linker about the layout of uninitialized */
|
/* this only tells the linker about the layout of uninitialized */
|
||||||
/* TLS data, and does not advance the linker's location counter */
|
/* TLS data, and does not advance the linker's location counter */
|
||||||
|
@ -386,13 +404,6 @@ SECTIONS {
|
||||||
_tbss_end = .;
|
_tbss_end = .;
|
||||||
} :Tls
|
} :Tls
|
||||||
|
|
||||||
.eh_frame : {
|
|
||||||
__eh_frame_start = .;
|
|
||||||
KEEP(*(.eh_frame))
|
|
||||||
*(.eh_frame.*)
|
|
||||||
__eh_frame_end = .;
|
|
||||||
} :Ram
|
|
||||||
|
|
||||||
.data . : {
|
.data . : {
|
||||||
/*BEGIN: Read/Write Data */
|
/*BEGIN: Read/Write Data */
|
||||||
#if SupportsWindows()
|
#if SupportsWindows()
|
||||||
|
@ -401,55 +412,33 @@ SECTIONS {
|
||||||
/*BEGIN: NT FORK COPYING */
|
/*BEGIN: NT FORK COPYING */
|
||||||
KEEP(*(.dataprologue))
|
KEEP(*(.dataprologue))
|
||||||
*(.data .data.*)
|
*(.data .data.*)
|
||||||
*(.gnu_extab)
|
|
||||||
*(.gcc_except_table .gcc_except_table.*)
|
|
||||||
*(.exception_ranges*)
|
|
||||||
*(.PyRuntime) /* for python */
|
*(.PyRuntime) /* for python */
|
||||||
*(.subrs) /* for emacs */
|
*(.subrs) /* for emacs */
|
||||||
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
KEEP(*(SORT_BY_NAME(.sort.data.*)))
|
||||||
. += . > 0 ? CODE_GRANULE : 0;
|
. += . > 0 ? CODE_GRANULE : 0;
|
||||||
|
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
KEEP(*(.gotprologue))
|
||||||
__got_start = .;
|
|
||||||
*(.got)
|
*(.got)
|
||||||
__got_end = .;
|
KEEP(*(.gotepilogue))
|
||||||
|
|
||||||
|
KEEP(*(.gotpltprologue))
|
||||||
*(.got.plt)
|
*(.got.plt)
|
||||||
|
KEEP(*(.gotpltepilogue))
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
|
||||||
__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 */
|
/*BEGIN: Post-Initialization Read-Only */
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
KEEP(*(SORT_BY_NAME(.piro.relo.sort.*)))
|
||||||
. = ALIGN(. != 0 ? __SIZEOF_POINTER__ : 0);
|
. = ALIGN(__SIZEOF_POINTER__);
|
||||||
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
KEEP(*(SORT_BY_NAME(.piro.data.sort.*)))
|
||||||
KEEP(*(.piro.pad.data))
|
KEEP(*(.piro.pad.data))
|
||||||
*(.igot.plt)
|
|
||||||
KEEP(*(.dataepilogue))
|
KEEP(*(.dataepilogue))
|
||||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
. = ALIGN(512);
|
||||||
/*END: NT FORK COPYING */
|
/*END: NT FORK COPYING */
|
||||||
_edata = .;
|
_edata = .;
|
||||||
PROVIDE(edata = .);
|
PROVIDE(edata = .);
|
||||||
_ezip = .; /* <-- very deprecated */
|
_ezip = .; /* <-- very deprecated */
|
||||||
} :Ram
|
} :Ram
|
||||||
|
|
||||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
|
||||||
|
|
||||||
/*END: file content that's loaded by o/s */
|
/*END: file content that's loaded by o/s */
|
||||||
/*END: file content */
|
/*END: file content */
|
||||||
/*BEGIN: bss memory that's addressable */
|
/*BEGIN: bss memory that's addressable */
|
||||||
|
@ -473,14 +462,14 @@ SECTIONS {
|
||||||
|
|
||||||
KEEP(*(.bssepilogue))
|
KEEP(*(.bssepilogue))
|
||||||
|
|
||||||
. = ALIGN(. != 0 ? CONSTANT(COMMONPAGESIZE) : 0);
|
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
||||||
|
|
||||||
/*END: NT FORK COPYING */
|
/*END: NT FORK COPYING */
|
||||||
} :Ram
|
|
||||||
|
|
||||||
. = ALIGN(CONSTANT(COMMONPAGESIZE));
|
|
||||||
_end = .;
|
_end = .;
|
||||||
PROVIDE(end = .);
|
PROVIDE(end = .);
|
||||||
|
} :Ram
|
||||||
|
|
||||||
|
. = DATA_SEGMENT_END(.);
|
||||||
|
|
||||||
/*END: nt addressability guarantee */
|
/*END: nt addressability guarantee */
|
||||||
/*END: bsd addressability guarantee */
|
/*END: bsd addressability guarantee */
|
||||||
|
@ -520,9 +509,6 @@ SECTIONS {
|
||||||
.debug_rnglists 0 : { *(.debug_rnglists) }
|
.debug_rnglists 0 : { *(.debug_rnglists) }
|
||||||
.debug_macro 0 : { *(.debug_macro) }
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
.debug_addr 0 : { *(.debug_addr) }
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
.debug_names 0 : { *(.debug_names) }
|
|
||||||
.debug_loclists 0 : { *(.debug_loclists) }
|
|
||||||
.debug_str_offsets 0 : { *(.debug_str_offsets) }
|
|
||||||
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
.gnu.attributes 0 : { KEEP(*(.gnu.attributes)) }
|
||||||
.GCC.command.line 0 : { *(.GCC.command.line) }
|
.GCC.command.line 0 : { *(.GCC.command.line) }
|
||||||
|
|
||||||
|
@ -541,9 +527,7 @@ SECTIONS {
|
||||||
*(.piro.data.sort.iat.*)
|
*(.piro.data.sort.iat.*)
|
||||||
#endif
|
#endif
|
||||||
*(__patchable_function_entries)
|
*(__patchable_function_entries)
|
||||||
*(.note.gnu.property)
|
|
||||||
*(__mcount_loc)
|
*(__mcount_loc)
|
||||||
*(.rela.dyn)
|
|
||||||
*(.discard)
|
*(.discard)
|
||||||
*(.yoink)
|
*(.yoink)
|
||||||
}
|
}
|
||||||
|
@ -566,31 +550,29 @@ _tdata_size = _tdata_end - _tdata_start;
|
||||||
_tbss_size = _tbss_end - _tbss_start;
|
_tbss_size = _tbss_end - _tbss_start;
|
||||||
_tbss_offset = _tbss_start - _tdata_start;
|
_tbss_offset = _tbss_start - _tdata_start;
|
||||||
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
_tls_content = (_tdata_end - _tdata_start) + (_tbss_end - _tbss_start);
|
||||||
_tdata_align = ALIGNOF(.tdata);
|
_tls_align = 1;
|
||||||
_tbss_align = ALIGNOF(.tbss);
|
|
||||||
_tls_align = MAX(TLS_ALIGNMENT, MAX(ALIGNOF(.tdata), ALIGNOF(.tbss)));
|
|
||||||
|
|
||||||
ape_cod_offset = 0;
|
ape_cod_offset = 0;
|
||||||
ape_cod_vaddr = ADDR(.head);
|
ape_cod_vaddr = ADDR(.head);
|
||||||
ape_cod_paddr = LOADADDR(.head);
|
ape_cod_paddr = LOADADDR(.head);
|
||||||
ape_cod_filesz = ADDR(.rodata) - ADDR(.head);
|
ape_cod_filesz = SIZEOF(.head) + SIZEOF(.text);
|
||||||
ape_cod_memsz = ape_cod_filesz;
|
ape_cod_memsz = ape_cod_filesz;
|
||||||
ape_cod_align = CONSTANT(COMMONPAGESIZE);
|
ape_cod_align = CONSTANT(COMMONPAGESIZE);
|
||||||
ape_cod_rva = RVA(ape_cod_vaddr);
|
ape_cod_rva = RVA(ape_cod_vaddr);
|
||||||
|
|
||||||
|
ape_rom_offset = ape_cod_offset + ape_cod_filesz;
|
||||||
ape_rom_vaddr = ADDR(.rodata);
|
ape_rom_vaddr = ADDR(.rodata);
|
||||||
ape_rom_offset = ape_rom_vaddr - __executable_start;
|
|
||||||
ape_rom_paddr = LOADADDR(.rodata);
|
ape_rom_paddr = LOADADDR(.rodata);
|
||||||
ape_rom_filesz = ADDR(.tbss) - ADDR(.rodata);
|
ape_rom_filesz = SIZEOF(.rodata) + SIZEOF(.tdata);
|
||||||
ape_rom_memsz = ape_rom_filesz;
|
ape_rom_memsz = ape_rom_filesz;
|
||||||
ape_rom_align = CONSTANT(COMMONPAGESIZE);
|
ape_rom_align = CONSTANT(COMMONPAGESIZE);
|
||||||
ape_rom_rva = RVA(ape_rom_vaddr);
|
ape_rom_rva = RVA(ape_rom_vaddr);
|
||||||
|
|
||||||
ape_ram_vaddr = ADDR(.eh_frame);
|
ape_ram_offset = ape_rom_offset + ape_rom_filesz;
|
||||||
ape_ram_offset = ape_ram_vaddr - __executable_start;
|
ape_ram_vaddr = ADDR(.data);
|
||||||
ape_ram_paddr = LOADADDR(.eh_frame);
|
ape_ram_paddr = LOADADDR(.data);
|
||||||
ape_ram_filesz = ADDR(.bss) - ADDR(.eh_frame);
|
ape_ram_filesz = SIZEOF(.data);
|
||||||
ape_ram_memsz = _end - ADDR(.eh_frame);
|
ape_ram_memsz = SIZEOF(.data) + SIZEOF(.bss);
|
||||||
ape_ram_align = CONSTANT(COMMONPAGESIZE);
|
ape_ram_align = CONSTANT(COMMONPAGESIZE);
|
||||||
ape_ram_rva = RVA(ape_ram_vaddr);
|
ape_ram_rva = RVA(ape_ram_vaddr);
|
||||||
|
|
||||||
|
@ -600,23 +582,22 @@ ape_stack_offset = 0;
|
||||||
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
ape_stack_vaddr = DEFINED(ape_stack_vaddr) ? ape_stack_vaddr : 0x700000000000;
|
||||||
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
|
ape_stack_paddr = ape_ram_paddr + ape_ram_filesz;
|
||||||
ape_stack_filesz = 0;
|
ape_stack_filesz = 0;
|
||||||
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : 4 * 1024 * 1024;
|
ape_stack_memsz = DEFINED(ape_stack_memsz) ? ape_stack_memsz : APE_STACKSIZE;
|
||||||
|
ape_stack_memsz2 = ape_stack_memsz * 2;
|
||||||
|
ape_stack_align = 16;
|
||||||
|
|
||||||
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
|
ape_note_offset = ape_cod_offset + (ape_note - ape_cod_vaddr);
|
||||||
ape_note_filesz = ape_note_end - ape_note;
|
ape_note_filesz = ape_note_end - ape_note;
|
||||||
ape_note_memsz = ape_note_filesz;
|
ape_note_memsz = ape_note_filesz;
|
||||||
|
|
||||||
ape_text_vaddr = ADDR(.text);
|
ape_text_offset = ape_cod_offset + LOADADDR(.text) - ape_cod_paddr;
|
||||||
ape_text_offset = ape_text_vaddr - __executable_start;
|
|
||||||
ape_text_paddr = LOADADDR(.text);
|
ape_text_paddr = LOADADDR(.text);
|
||||||
ape_text_filesz = ADDR(.rodata) - ADDR(.text);
|
ape_text_vaddr = ADDR(.text);
|
||||||
|
ape_text_filesz = SIZEOF(.text) + SIZEOF(.rodata) + SIZEOF(.tdata);
|
||||||
ape_text_memsz = ape_text_filesz;
|
ape_text_memsz = ape_text_filesz;
|
||||||
ape_text_align = CONSTANT(COMMONPAGESIZE);
|
ape_text_align = CONSTANT(COMMONPAGESIZE);
|
||||||
ape_text_rva = RVA(ape_text_vaddr);
|
ape_text_rva = RVA(ape_text_vaddr);
|
||||||
|
|
||||||
__eh_frame_hdr_start = __eh_frame_hdr_end_actual > __eh_frame_hdr_start_actual ? __eh_frame_hdr_start_actual : 0;
|
|
||||||
__eh_frame_hdr_end = __eh_frame_hdr_end_actual > __eh_frame_hdr_start_actual ? __eh_frame_hdr_end_actual : 0;
|
|
||||||
|
|
||||||
/* we roundup here because xnu wants the file load segments page-aligned */
|
/* we roundup here because xnu wants the file load segments page-aligned */
|
||||||
/* but we don't want to add the nop padding to the ape program, so we'll */
|
/* but we don't want to add the nop padding to the ape program, so we'll */
|
||||||
/* let ape.S dd read past the end of the file into the wrapping binaries */
|
/* let ape.S dd read past the end of the file into the wrapping binaries */
|
||||||
|
@ -626,6 +607,29 @@ SHSTUB2(ape_loader_dd_count,
|
||||||
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
|
? ROUNDUP(ape_loader_end - ape_loader, CONSTANT(COMMONPAGESIZE)) / 64
|
||||||
: 0);
|
: 0);
|
||||||
|
|
||||||
|
#if defined(APE_IS_SHELL_SCRIPT) && !IsTiny()
|
||||||
|
|
||||||
|
#define IDENTITY(X) X
|
||||||
|
|
||||||
|
#define APE_DECLARE_FIXED_DECIMAL(F, X) \
|
||||||
|
X##_quad = DEFINED(X) ? ((F(X) < 1000000000 ? 32 : F(X) / 1000000000 % 10 + 48) << 000 | \
|
||||||
|
(F(X) < 100000000 ? 32 : F(X) / 100000000 % 10 + 48) << 010 | \
|
||||||
|
(F(X) < 10000000 ? 32 : F(X) / 10000000 % 10 + 48) << 020 | \
|
||||||
|
(F(X) < 1000000 ? 32 : F(X) / 1000000 % 10 + 48) << 030 | \
|
||||||
|
(F(X) < 100000 ? 32 : F(X) / 100000 % 10 + 48) << 040 | \
|
||||||
|
(F(X) < 10000 ? 32 : F(X) / 10000 % 10 + 48) << 050 | \
|
||||||
|
(F(X) < 1000 ? 32 : F(X) / 1000 % 10 + 48) << 060 | \
|
||||||
|
(F(X) < 100 ? 32 : F(X) / 100 % 10 + 48) << 070) : 0; \
|
||||||
|
X##_short = DEFINED(X) ? ((F(X) < 10 ? 32 : F(X) / 10 % 10 + 48) << 000 | \
|
||||||
|
(F(X) % 10 + 48) << 010) : 0
|
||||||
|
|
||||||
|
APE_DECLARE_FIXED_DECIMAL(RVA, blink_linux_aarch64);
|
||||||
|
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_linux_aarch64_size);
|
||||||
|
APE_DECLARE_FIXED_DECIMAL(RVA, blink_xnu_aarch64);
|
||||||
|
APE_DECLARE_FIXED_DECIMAL(IDENTITY, blink_xnu_aarch64_size);
|
||||||
|
|
||||||
|
#endif /* APE_IS_SHELL_SCRIPT */
|
||||||
|
|
||||||
#if SupportsMetal()
|
#if SupportsMetal()
|
||||||
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
|
v_ape_realsectors = MIN(0x70000 - IMAGE_BASE_REAL, ROUNDUP(RVA(_ezip), 512)) / 512;
|
||||||
v_ape_realbytes = v_ape_realsectors * 512;
|
v_ape_realbytes = v_ape_realsectors * 512;
|
||||||
|
@ -729,6 +733,7 @@ ape_idataz = LINK_WINDOWS ? RVA(ape_idata_iat) : 0;
|
||||||
ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0;
|
ape_idata_iatsize = LINK_WINDOWS ? ape_idata_iatend - ape_idata_iat : 0;
|
||||||
ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0;
|
ape_idata = LINK_WINDOWS ? RVA(ape_idata_idt) : 0;
|
||||||
ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0;
|
ape_idata_idtsize = LINK_WINDOWS ? ape_idata_idtend - ape_idata_idt : 0;
|
||||||
|
v_ntversion = LINK_WINDOWS ? 6 : 1;
|
||||||
v_ntdllchar = LINK_WINDOWS ? 288 : 0;
|
v_ntdllchar = LINK_WINDOWS ? 288 : 0;
|
||||||
v_ntsubversion = LINK_WINDOWS ? 6 : 5;
|
v_ntsubversion = LINK_WINDOWS ? 6 : 5;
|
||||||
v_ntsubsystem = (LINK_WINDOWS
|
v_ntsubsystem = (LINK_WINDOWS
|
||||||
|
@ -754,6 +759,12 @@ ASSERT(((DEFINED(__init_rodata_end) ? __init_rodata_end : 0) %
|
||||||
ASSERT((!DEFINED(ape_grub) ? 1 : RVA(ape_grub) < 8192),
|
ASSERT((!DEFINED(ape_grub) ? 1 : RVA(ape_grub) < 8192),
|
||||||
"grub stub needs to be in first 8kb of image");
|
"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),
|
ASSERT(IS2POW(ape_stack_memsz),
|
||||||
"ape_stack_memsz must be a two power");
|
"ape_stack_memsz must be a two power");
|
||||||
|
|
||||||
|
@ -763,8 +774,6 @@ ASSERT(ape_stack_vaddr % ape_stack_memsz == 0,
|
||||||
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
ASSERT(ALIGNOF(.tdata) <= TLS_ALIGNMENT && ALIGNOF(.tbss) <= TLS_ALIGNMENT,
|
||||||
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
"_Thread_local _Alignof can't exceed TLS_ALIGNMENT");
|
||||||
|
|
||||||
ASSERT(DEFINED(main), "main() function not defined");
|
|
||||||
|
|
||||||
/* Let's not be like Knight Capital. */
|
/* Let's not be like Knight Capital. */
|
||||||
/* NOCROSSREFS_TO(.test .text) */
|
/* NOCROSSREFS_TO(.test .text) */
|
||||||
|
|
||||||
|
|
303
ape/ape.mk
Normal file
303
ape/ape.mk
Normal file
|
@ -0,0 +1,303 @@
|
||||||
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
|
#
|
||||||
|
# OVERVIEW
|
||||||
|
#
|
||||||
|
# αcτµαlly pδrταblε εxεcµταblε
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# This file defines the libraries, runtimes, and build rules needed to
|
||||||
|
# create executables from your Linux workstation that'll run anywhere.
|
||||||
|
# Loading this package will make certain systemic modifications to the
|
||||||
|
# build like turning off the System V "Red Zone" optimization, because
|
||||||
|
# αcτµαlly pδrταblε εxεcµταblεs need to be able to run in kernelspace.
|
||||||
|
|
||||||
|
PKGS += APE
|
||||||
|
|
||||||
|
APE_FILES := $(wildcard ape/*.*)
|
||||||
|
APE_HDRS = $(filter %.h,$(APE_FILES))
|
||||||
|
APE_INCS = $(filter %.inc,$(APE_FILES))
|
||||||
|
|
||||||
|
ifeq ($(ARCH), aarch64)
|
||||||
|
|
||||||
|
APE = o/$(MODE)/ape/aarch64.lds
|
||||||
|
|
||||||
|
APELINK = \
|
||||||
|
$(COMPILE) \
|
||||||
|
-ALINK.ape \
|
||||||
|
$(LINK) \
|
||||||
|
$(LINKARGS) \
|
||||||
|
$(OUTPUT_OPTION) && \
|
||||||
|
$(COMPILE) \
|
||||||
|
-AFIXUP.ape \
|
||||||
|
-wT$@ \
|
||||||
|
$(FIXUPOBJ) \
|
||||||
|
$@
|
||||||
|
|
||||||
|
APE_SRCS = ape/ape.S ape/start.S ape/launch.S ape/systemcall.S
|
||||||
|
APE_OBJS = o/$(MODE)/ape/ape.o
|
||||||
|
APE_NO_MODIFY_SELF = $(APE)
|
||||||
|
APE_COPY_SELF = $(APE)
|
||||||
|
|
||||||
|
.PHONY: o/$(MODE)/ape
|
||||||
|
o/$(MODE)/ape: $(APE)
|
||||||
|
|
||||||
|
o/$(MODE)/ape/aarch64.lds: \
|
||||||
|
ape/aarch64.lds \
|
||||||
|
libc/zip.internal.h \
|
||||||
|
libc/intrin/bits.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
|
libc/calls/struct/timespec.h \
|
||||||
|
libc/macros.internal.h \
|
||||||
|
libc/str/str.h
|
||||||
|
|
||||||
|
APE_LOADER_LDFLAGS = \
|
||||||
|
-pie \
|
||||||
|
-static \
|
||||||
|
-nostdlib \
|
||||||
|
--no-dynamic-linker \
|
||||||
|
-z norelro \
|
||||||
|
-z common-page-size=0x4000 \
|
||||||
|
-z max-page-size=0x4000
|
||||||
|
|
||||||
|
APE_LOADER_FLAGS = \
|
||||||
|
-DNDEBUG \
|
||||||
|
-iquote. \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-fpie \
|
||||||
|
-Os \
|
||||||
|
-ffreestanding \
|
||||||
|
-mgeneral-regs-only \
|
||||||
|
-fno-asynchronous-unwind-tables \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-ident \
|
||||||
|
-fno-gnu-unique \
|
||||||
|
-c \
|
||||||
|
$(OUTPUT_OPTION) \
|
||||||
|
$<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||||
|
$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.elf.dbg: \
|
||||||
|
o/$(MODE)/ape/start.o \
|
||||||
|
o/$(MODE)/ape/loader.o \
|
||||||
|
o/$(MODE)/ape/launch.o \
|
||||||
|
o/$(MODE)/ape/systemcall.o
|
||||||
|
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
||||||
|
|
||||||
|
o/$(MODE)/ape/loader.o: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/start.o: ape/start.S
|
||||||
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
o/$(MODE)/ape/launch.o: ape/launch.S
|
||||||
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
o/$(MODE)/ape/systemcall.o: ape/systemcall.S
|
||||||
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
|
||||||
|
.PHONY: o/$(MODE)/ape
|
||||||
|
o/$(MODE)/ape: o/$(MODE)/ape/ape.elf
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
APE = o/$(MODE)/ape/ape.o \
|
||||||
|
o/$(MODE)/ape/ape.lds
|
||||||
|
|
||||||
|
APELINK = \
|
||||||
|
$(COMPILE) \
|
||||||
|
-ALINK.ape \
|
||||||
|
$(LINK) \
|
||||||
|
$(LINKARGS) \
|
||||||
|
$(OUTPUT_OPTION) && \
|
||||||
|
$(COMPILE) \
|
||||||
|
-AFIXUP.ape \
|
||||||
|
-wT$@ \
|
||||||
|
$(FIXUPOBJ) \
|
||||||
|
$@
|
||||||
|
|
||||||
|
APE_NO_MODIFY_SELF = \
|
||||||
|
o/$(MODE)/ape/ape.lds \
|
||||||
|
o/$(MODE)/ape/ape-no-modify-self.o
|
||||||
|
|
||||||
|
APE_COPY_SELF = \
|
||||||
|
o/$(MODE)/ape/ape.lds \
|
||||||
|
o/$(MODE)/ape/ape-copy-self.o
|
||||||
|
|
||||||
|
APE_LOADER_FLAGS = \
|
||||||
|
-DNDEBUG \
|
||||||
|
-iquote. \
|
||||||
|
-Wall \
|
||||||
|
-Wextra \
|
||||||
|
-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/$(MODE)/ape/public/ape.lds: CPPFLAGS += -UCOSMO
|
||||||
|
o/$(MODE)/ape/public/ape.lds: \
|
||||||
|
ape/public/ape.lds \
|
||||||
|
ape/ape.lds \
|
||||||
|
ape/ape.internal.h \
|
||||||
|
ape/macros.internal.h \
|
||||||
|
ape/relocations.h \
|
||||||
|
libc/intrin/bits.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
|
libc/calls/struct/timespec.h \
|
||||||
|
libc/thread/thread.h \
|
||||||
|
libc/dce.h \
|
||||||
|
libc/elf/def.h \
|
||||||
|
libc/elf/pf2prot.internal.h \
|
||||||
|
libc/macros.internal.h \
|
||||||
|
libc/nt/pedef.internal.h \
|
||||||
|
libc/str/str.h \
|
||||||
|
libc/zip.internal.h
|
||||||
|
|
||||||
|
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 \
|
||||||
|
ape/ape.internal.h \
|
||||||
|
libc/dce.h \
|
||||||
|
libc/elf/def.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
|
libc/intrin/asancodes.h \
|
||||||
|
libc/macho.internal.h \
|
||||||
|
libc/macros.internal.h \
|
||||||
|
libc/nexgen32e/uart.internal.h \
|
||||||
|
libc/calls/metalfile.internal.h \
|
||||||
|
libc/nexgen32e/vidya.internal.h \
|
||||||
|
libc/nt/pedef.internal.h \
|
||||||
|
libc/runtime/e820.internal.h \
|
||||||
|
libc/runtime/mman.internal.h \
|
||||||
|
libc/runtime/pc.internal.h \
|
||||||
|
libc/sysv/consts/prot.h \
|
||||||
|
ape/blink-linux-aarch64.gz \
|
||||||
|
ape/blink-xnu-aarch64.gz \
|
||||||
|
o/$(MODE)/ape/ape.elf
|
||||||
|
@$(COMPILE) \
|
||||||
|
-AOBJECTIFY.S \
|
||||||
|
$(OBJECTIFY.S) \
|
||||||
|
$(OUTPUT_OPTION) \
|
||||||
|
-DAPE_NO_MODIFY_SELF \
|
||||||
|
-DAPE_LOADER='"o/$(MODE)/ape/ape.elf"' $<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape-copy-self.o: \
|
||||||
|
ape/ape.S \
|
||||||
|
ape/macros.internal.h \
|
||||||
|
ape/notice.inc \
|
||||||
|
ape/relocations.h \
|
||||||
|
ape/ape.internal.h \
|
||||||
|
libc/dce.h \
|
||||||
|
libc/elf/def.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
|
libc/intrin/asancodes.h \
|
||||||
|
libc/macho.internal.h \
|
||||||
|
libc/macros.internal.h \
|
||||||
|
libc/nexgen32e/uart.internal.h \
|
||||||
|
libc/calls/metalfile.internal.h \
|
||||||
|
libc/nexgen32e/vidya.internal.h \
|
||||||
|
libc/nt/pedef.internal.h \
|
||||||
|
libc/runtime/e820.internal.h \
|
||||||
|
libc/runtime/mman.internal.h \
|
||||||
|
libc/runtime/pc.internal.h \
|
||||||
|
libc/sysv/consts/prot.h \
|
||||||
|
ape/blink-linux-aarch64.gz \
|
||||||
|
ape/blink-xnu-aarch64.gz
|
||||||
|
@$(COMPILE) \
|
||||||
|
-AOBJECTIFY.S \
|
||||||
|
$(OBJECTIFY.S) \
|
||||||
|
$(OUTPUT_OPTION) \
|
||||||
|
-DAPE_NO_MODIFY_SELF $<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/loader.o: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -g $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/loader-gcc.asm: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/loader-clang.asm: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=121 -S -g0 $(APE_LOADER_FLAGS)
|
||||||
|
|
||||||
|
o/$(MODE)/ape/loader-xnu.o: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -g $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/loader-xnu-gcc.asm: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
||||||
|
o/$(MODE)/ape/loader-xnu-clang.asm: ape/loader.c
|
||||||
|
@$(COMPILE) -AOBJECTIFY.c $(CLANG) -DSUPPORT_VECTOR=8 -S -g0 $(APE_LOADER_FLAGS)
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
|
||||||
|
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy.com -f -o $@ $<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.macho: o/$(MODE)/ape/ape.elf.dbg
|
||||||
|
@$(COMPILE) -AOBJBINCOPY -w build/bootstrap/objbincopy.com -fm -o $@ $<
|
||||||
|
|
||||||
|
APE_LOADER_LDFLAGS = \
|
||||||
|
-static \
|
||||||
|
-nostdlib \
|
||||||
|
--no-dynamic-linker \
|
||||||
|
-z separate-code \
|
||||||
|
-z common-page-size=0x1000 \
|
||||||
|
-z max-page-size=0x10000
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.elf.dbg: \
|
||||||
|
o/$(MODE)/ape/loader-macho.o \
|
||||||
|
o/$(MODE)/ape/start.o \
|
||||||
|
o/$(MODE)/ape/loader.o \
|
||||||
|
o/$(MODE)/ape/launch.o \
|
||||||
|
o/$(MODE)/ape/systemcall.o \
|
||||||
|
ape/loader.lds
|
||||||
|
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)
|
||||||
|
|
||||||
|
.PHONY: o/$(MODE)/ape
|
||||||
|
o/$(MODE)/ape: $(APE_CHECKS) \
|
||||||
|
o/$(MODE)/ape/ape.o \
|
||||||
|
o/$(MODE)/ape/ape.lds \
|
||||||
|
o/$(MODE)/ape/public/ape.lds \
|
||||||
|
o/$(MODE)/ape/ape.elf \
|
||||||
|
o/$(MODE)/ape/ape.macho \
|
||||||
|
o/$(MODE)/ape/ape-copy-self.o \
|
||||||
|
o/$(MODE)/ape/ape-no-modify-self.o
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
# these assembly files are safe to build on aarch64
|
||||||
|
o/$(MODE)/ape/ape.o: ape/ape.S
|
||||||
|
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.o: \
|
||||||
|
ape/blink-linux-aarch64.gz \
|
||||||
|
ape/blink-xnu-aarch64.gz
|
||||||
|
|
||||||
|
o/$(MODE)/ape/ape.lds: \
|
||||||
|
ape/ape.lds \
|
||||||
|
ape/macros.internal.h \
|
||||||
|
ape/relocations.h \
|
||||||
|
ape/ape.internal.h \
|
||||||
|
libc/intrin/bits.h \
|
||||||
|
libc/thread/tls.h \
|
||||||
|
libc/calls/struct/timespec.h \
|
||||||
|
libc/thread/thread.h \
|
||||||
|
libc/dce.h \
|
||||||
|
libc/elf/def.h \
|
||||||
|
libc/elf/pf2prot.internal.h \
|
||||||
|
libc/macros.internal.h \
|
||||||
|
libc/nt/pedef.internal.h \
|
||||||
|
libc/str/str.h \
|
||||||
|
libc/zip.internal.h
|
|
@ -1,108 +1,58 @@
|
||||||
#!/bin/sh
|
#!/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 [ "$(id -u)" -eq 0 ]; then
|
||||||
SUDO=
|
SUDO=
|
||||||
elif command -v sudo >/dev/null 2>&1; then
|
else
|
||||||
SUDO=sudo
|
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
|
fi
|
||||||
|
|
||||||
echo "Actually Portable Executable (APE) Installer" >&2
|
echo "Actually Portable Executable (APE) Installer" >&2
|
||||||
echo "Author: Justine Tunney <jtunney@gmail.com>" >&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
|
# INSTALL APE LOADER SYSTEMWIDE
|
||||||
|
|
||||||
if [ -f o/$MODE/depend ] && $MAKE -j8 o/$MODE/ape; then
|
if [ -f o/depend ] && make -j8 o//ape; then
|
||||||
echo "successfully recompiled ape loader" >&2
|
echo "successfully recompiled ape loader" >&2
|
||||||
elif [ -x o/$MODE/ape/ape.$EXT ]; then
|
|
||||||
echo "using ape loader you compiled earlier" >&2
|
|
||||||
elif [ -d build/bootstrap ]; then
|
elif [ -d build/bootstrap ]; then
|
||||||
# if make isn't being used then it's unlikely the user changed the sources
|
# 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
|
# in that case the prebuilt binaries should be completely up-to-date
|
||||||
echo "using prebuilt ape loader from cosmo repo" >&2
|
echo "using prebuilt ape loader from cosmo repo" >&2
|
||||||
mkdir -p o/$MODE/ape || exit
|
mkdir -p o//ape || exit
|
||||||
cp -af build/bootstrap/ape.$BEXT o/$MODE/ape/ape.$EXT || exit
|
cp -af build/bootstrap/ape.elf o//ape/ape.elf || exit
|
||||||
|
cp -af build/bootstrap/ape.macho o//ape/ape.macho || exit
|
||||||
else
|
else
|
||||||
echo "no cosmopolitan libc repository here" >&2
|
echo "no cosmopolitan libc repository here" >&2
|
||||||
echo "fetching ape loader from justine.lol" >&2
|
echo "fetching ape loader from justine.lol" >&2
|
||||||
mkdir -p o/$MODE/ape || exit
|
mkdir -p o//ape || exit
|
||||||
if command -v wget >/dev/null 2>&1; then
|
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
|
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
|
fi
|
||||||
chmod +x o/$MODE/ape/ape.$EXT || exit
|
chmod +x o//ape/ape.elf || exit
|
||||||
|
chmod +x o//ape/ape.macho || exit
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! [ /usr/bin/ape -nt o/$MODE/ape/ape.$EXT ]; then
|
if [ "$(uname -s)" = "Darwin" ]; then
|
||||||
|
if ! [ /usr/bin/ape -nt o//ape/ape.macho ]; then
|
||||||
echo >&2
|
echo >&2
|
||||||
echo "installing o/$MODE/ape/ape.$EXT to /usr/bin/ape" >&2
|
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
|
||||||
echo "$SUDO $INSTALL o/$MODE/ape/ape.$EXT /usr/bin/ape" >&2
|
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
|
||||||
$SUDO $INSTALL o/$MODE/ape/ape.$EXT /usr/bin/ape || exit
|
$SUDO cp -f o//ape/ape.macho /usr/bin/ape || exit
|
||||||
echo "done" >&2
|
echo "done" >&2
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
if ! [ /usr/bin/ape -nt o//ape/ape.elf ]; then
|
||||||
|
echo >&2
|
||||||
|
echo "installing o//ape/ape.elf to /usr/bin/ape" >&2
|
||||||
|
echo "$SUDO mv -f o//ape/ape.elf /usr/bin/ape" >&2
|
||||||
|
$SUDO cp -f o//ape/ape.elf /usr/bin/ape || exit
|
||||||
|
echo "done" >&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# REGISTER APE LOADER WITH BINFMT_MISC TOO (LINUX-ONLY)
|
# REGISTER APE LOADER WITH BINFMT_MISC TOO (LINUX-ONLY)
|
||||||
|
@ -137,20 +87,13 @@ if [ x"$(uname -s)" = xLinux ]; then
|
||||||
echo done >&2
|
echo done >&2
|
||||||
fi
|
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 >&2
|
||||||
echo registering APE with binfmt_misc >&2
|
echo registering APE with binfmt_misc >&2
|
||||||
echo you may need to edit configs to persist across reboot >&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
|
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:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
$SUDO sh -c "echo ':APE:M::MZqFpD::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||||
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"$FLAGS'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
echo '$SUDO sh -c "echo '"'"':APE-jart:M::jartsr::/usr/bin/ape:'"'"' >/proc/sys/fs/binfmt_misc/register"' >&2
|
||||||
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:$FLAGS' >/proc/sys/fs/binfmt_misc/register" || exit
|
$SUDO sh -c "echo ':APE-jart:M::jartsr::/usr/bin/ape:' >/proc/sys/fs/binfmt_misc/register" || exit
|
||||||
echo done >&2
|
echo done >&2
|
||||||
|
|
||||||
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
if [ x"$(cat /proc/sys/fs/binfmt_misc/status)" = xdisabled ]; then
|
||||||
|
|
|
@ -1,23 +1,9 @@
|
||||||
#!/bin/sh
|
#!/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
|
if [ "$UID" = "0" ]; then
|
||||||
SUDO=
|
SUDO=
|
||||||
elif command -v sudo >/dev/null 2>&1; then
|
|
||||||
SUDO=sudo
|
|
||||||
elif command -v doas >/dev/null 2>&1; then
|
|
||||||
SUDO=doas
|
|
||||||
else
|
else
|
||||||
echo "need root or sudo" >&2
|
SUDO=sudo
|
||||||
exit
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -42,9 +28,6 @@ done
|
||||||
if [ -f /usr/bin/ape ]; then
|
if [ -f /usr/bin/ape ]; then
|
||||||
$SUDO rm -f /usr/bin/ape
|
$SUDO rm -f /usr/bin/ape
|
||||||
fi
|
fi
|
||||||
if [ -f /usr/local/bin/ape ]; then
|
|
||||||
$SUDO rm -f /usr/local/bin/ape
|
|
||||||
fi
|
|
||||||
|
|
||||||
# legacy installations
|
# legacy installations
|
||||||
rm -f o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape"
|
rm -f o/tmp/ape /tmp/ape "${TMPDIR:-/tmp}/ape"
|
||||||
|
@ -55,11 +38,8 @@ for x in .ape \
|
||||||
.ape-1.3 \
|
.ape-1.3 \
|
||||||
.ape-1.4 \
|
.ape-1.4 \
|
||||||
.ape-1.5 \
|
.ape-1.5 \
|
||||||
.ape-1.6 \
|
.ape-blink-0.9.2 \
|
||||||
.ape-1.7 \
|
.ape-blink-1.0.0; do
|
||||||
.ape-1.8 \
|
|
||||||
.ape-1.9 \
|
|
||||||
.ape-1.10; do
|
|
||||||
rm -f \
|
rm -f \
|
||||||
~/$x \
|
~/$x \
|
||||||
/tmp/$x \
|
/tmp/$x \
|
||||||
|
|
BIN
ape/blink-linux-aarch64.gz
Normal file
BIN
ape/blink-linux-aarch64.gz
Normal file
Binary file not shown.
BIN
ape/blink-xnu-aarch64.gz
Executable file
BIN
ape/blink-xnu-aarch64.gz
Executable file
Binary file not shown.
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -43,10 +43,10 @@
|
||||||
.hidden \fn
|
.hidden \fn
|
||||||
.previous
|
.previous
|
||||||
.section ".idata.ro.ilt.\dll\().2.\actual","a",@progbits
|
.section ".idata.ro.ilt.\dll\().2.\actual","a",@progbits
|
||||||
"idata.ilt.\dll\().\actual":
|
".Lidata.ilt.\dll\().\actual":
|
||||||
.quad RVA("\dll\().\actual")
|
.quad RVA("\dll\().\actual")
|
||||||
.type "idata.ilt.\dll\().\actual",@object
|
.type ".Lidata.ilt.\dll\().\actual",@object
|
||||||
.size "idata.ilt.\dll\().\actual",.-"idata.ilt.\dll\().\actual"
|
.size ".Lidata.ilt.\dll\().\actual",.-".Lidata.ilt.\dll\().\actual"
|
||||||
.previous
|
.previous
|
||||||
.section ".idata.ro.hnt.\dll\().2.\actual","a",@progbits
|
.section ".idata.ro.hnt.\dll\().2.\actual","a",@progbits
|
||||||
"\dll\().\actual":
|
"\dll\().\actual":
|
||||||
|
@ -81,7 +81,7 @@
|
||||||
.size ".Lidata.idt.\name",.-".Lidata.idt.\name"
|
.size ".Lidata.idt.\name",.-".Lidata.idt.\name"
|
||||||
.previous
|
.previous
|
||||||
.section ".idata.ro.ilt.\name\().1","aG",@progbits,"\name",comdat
|
.section ".idata.ro.ilt.\name\().1","aG",@progbits,"\name",comdat
|
||||||
.balign __SIZEOF_POINTER__
|
.align __SIZEOF_POINTER__
|
||||||
.type "idata.ilt.\name",@object
|
.type "idata.ilt.\name",@object
|
||||||
"idata.ilt.\name":
|
"idata.ilt.\name":
|
||||||
.previous/*
|
.previous/*
|
||||||
|
@ -92,12 +92,12 @@
|
||||||
.quad 0
|
.quad 0
|
||||||
.previous
|
.previous
|
||||||
.section ".idata.ro.hnt.\name\().1","aG",@progbits,"\name",comdat
|
.section ".idata.ro.hnt.\name\().1","aG",@progbits,"\name",comdat
|
||||||
.balign __SIZEOF_POINTER__
|
.align __SIZEOF_POINTER__
|
||||||
.type "idata.hnt.\name",@object
|
.type "idata.hnt.\name",@object
|
||||||
.equ "idata.hnt.\name",.
|
.equ "idata.hnt.\name",.
|
||||||
.previous
|
.previous
|
||||||
.section ".piro.data.sort.iat.2.\name\().1","awG",@progbits,"\name",comdat
|
.section ".piro.data.sort.iat.2.\name\().1","awG",@progbits,"\name",comdat
|
||||||
.balign __SIZEOF_POINTER__
|
.align __SIZEOF_POINTER__
|
||||||
.type "idata.iat.\name",@object
|
.type "idata.iat.\name",@object
|
||||||
"idata.iat.\name":
|
"idata.iat.\name":
|
||||||
.previous/*
|
.previous/*
|
||||||
|
|
14
ape/launch.S
14
ape/launch.S
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
// Calls _start() function of loaded program.
|
// Calls _start() function of loaded program.
|
||||||
//
|
//
|
||||||
|
@ -31,16 +31,17 @@
|
||||||
//
|
//
|
||||||
// @param rdi is passed through as-is
|
// @param rdi is passed through as-is
|
||||||
// @param rsi is address of entrypoint (becomes zero)
|
// @param rsi is address of entrypoint (becomes zero)
|
||||||
// @param rdx is passed through as-is
|
// @param rdx is stack pointer (becomes zero)
|
||||||
// @param rcx is passed through as-is
|
// @param rcx is passed through as-is
|
||||||
// @param r8 is stack pointer (becomes zero)
|
|
||||||
// @noreturn
|
// @noreturn
|
||||||
Launch:
|
Launch:
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
|
|
||||||
mov x16,x1
|
mov x16,x1
|
||||||
mov sp,x4
|
mov sp,x2
|
||||||
mov x1,0
|
mov x1,0
|
||||||
|
mov x2,0
|
||||||
|
mov x3,0
|
||||||
mov x4,0
|
mov x4,0
|
||||||
mov x5,0
|
mov x5,0
|
||||||
mov x6,0
|
mov x6,0
|
||||||
|
@ -70,7 +71,6 @@ Launch:
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
mov %r8,%rsp
|
|
||||||
xor %r8d,%r8d
|
xor %r8d,%r8d
|
||||||
xor %r9d,%r9d
|
xor %r9d,%r9d
|
||||||
xor %r10d,%r10d
|
xor %r10d,%r10d
|
||||||
|
@ -79,6 +79,8 @@ Launch:
|
||||||
xor %r13d,%r13d
|
xor %r13d,%r13d
|
||||||
xor %r14d,%r14d
|
xor %r14d,%r14d
|
||||||
xor %r15d,%r15d
|
xor %r15d,%r15d
|
||||||
|
mov %rdx,%rsp
|
||||||
|
xor %edx,%edx
|
||||||
push %rsi
|
push %rsi
|
||||||
xor %esi,%esi
|
xor %esi,%esi
|
||||||
xor %ebp,%ebp
|
xor %ebp,%ebp
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -16,13 +16,13 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macho.h"
|
#include "libc/macho.internal.h"
|
||||||
#include "libc/sysv/consts/prot.h"
|
#include "libc/sysv/consts/prot.h"
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
// Apple Mach-O Executable Headers
|
// Apple Mach-O Executable Headers
|
||||||
// Fixups are applied by objbincopy
|
// Fixups are applied by objbincopy.com
|
||||||
// There must exist a MAC_LC_SEGMENT_64 for every PT_LOAD
|
// There must exist a MAC_LC_SEGMENT_64 for every PT_LOAD
|
||||||
|
|
||||||
.section .macho,"a",@progbits
|
.section .macho,"a",@progbits
|
||||||
|
|
441
ape/loader.c
441
ape/loader.c
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
|
||||||
│ vi: set et ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi │
|
│vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
│ Copyright 2021 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -16,7 +16,6 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "ape/ape.h"
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @fileoverview APE Loader for GNU/Systemd/XNU/FreeBSD/NetBSD/OpenBSD
|
* @fileoverview APE Loader for GNU/Systemd/XNU/FreeBSD/NetBSD/OpenBSD
|
||||||
|
@ -87,8 +86,6 @@
|
||||||
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
|
||||||
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))
|
||||||
|
|
||||||
#define PATH_MAX 1024 /* XXX verify */
|
|
||||||
|
|
||||||
#define SupportsLinux() (SUPPORT_VECTOR & LINUX)
|
#define SupportsLinux() (SUPPORT_VECTOR & LINUX)
|
||||||
#define SupportsXnu() (SUPPORT_VECTOR & XNU)
|
#define SupportsXnu() (SUPPORT_VECTOR & XNU)
|
||||||
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
|
#define SupportsFreebsd() (SUPPORT_VECTOR & FREEBSD)
|
||||||
|
@ -107,12 +104,6 @@
|
||||||
#define IsAarch64() 0
|
#define IsAarch64() 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
#define EXTERN_C extern "C"
|
|
||||||
#else
|
|
||||||
#define EXTERN_C
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define O_RDONLY 0
|
#define O_RDONLY 0
|
||||||
#define PROT_NONE 0
|
#define PROT_NONE 0
|
||||||
#define PROT_READ 1
|
#define PROT_READ 1
|
||||||
|
@ -141,9 +132,6 @@
|
||||||
#define AT_PHENT 4
|
#define AT_PHENT 4
|
||||||
#define AT_PHNUM 5
|
#define AT_PHNUM 5
|
||||||
#define AT_PAGESZ 6
|
#define AT_PAGESZ 6
|
||||||
#define AT_FLAGS 8
|
|
||||||
#define AT_FLAGS_PRESERVE_ARGV0_BIT 0
|
|
||||||
#define AT_FLAGS_PRESERVE_ARGV0 (1 << AT_FLAGS_PRESERVE_ARGV0_BIT)
|
|
||||||
#define AT_EXECFN_LINUX 31
|
#define AT_EXECFN_LINUX 31
|
||||||
#define AT_EXECFN_NETBSD 2014
|
#define AT_EXECFN_NETBSD 2014
|
||||||
#define X_OK 1
|
#define X_OK 1
|
||||||
|
@ -152,9 +140,6 @@
|
||||||
#define PR_SET_MM 35
|
#define PR_SET_MM 35
|
||||||
#define PR_SET_MM_EXE_FILE 13
|
#define PR_SET_MM_EXE_FILE 13
|
||||||
|
|
||||||
#define EF_APE_MODERN 0x101ca75
|
|
||||||
#define EF_APE_MODERN_MASK 0x1ffffff
|
|
||||||
|
|
||||||
#define READ32(S) \
|
#define READ32(S) \
|
||||||
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
((unsigned)(255 & (S)[3]) << 030 | (unsigned)(255 & (S)[2]) << 020 | \
|
||||||
(unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000)
|
(unsigned)(255 & (S)[1]) << 010 | (unsigned)(255 & (S)[0]) << 000)
|
||||||
|
@ -169,6 +154,13 @@
|
||||||
(unsigned long)(255 & (S)[1]) << 010 | \
|
(unsigned long)(255 & (S)[1]) << 010 | \
|
||||||
(unsigned long)(255 & (S)[0]) << 000)
|
(unsigned long)(255 & (S)[0]) << 000)
|
||||||
|
|
||||||
|
#define DEBUG(VAR) \
|
||||||
|
{ \
|
||||||
|
char ibuf[19] = {0}; \
|
||||||
|
Utox(ibuf, VAR); \
|
||||||
|
Print(os, 2, #VAR " ", ibuf, "\n", 0l); \
|
||||||
|
}
|
||||||
|
|
||||||
struct ElfEhdr {
|
struct ElfEhdr {
|
||||||
unsigned char e_ident[16];
|
unsigned char e_ident[16];
|
||||||
unsigned short e_type;
|
unsigned short e_type;
|
||||||
|
@ -204,52 +196,52 @@ union ElfEhdrBuf {
|
||||||
|
|
||||||
union ElfPhdrBuf {
|
union ElfPhdrBuf {
|
||||||
struct ElfPhdr phdr;
|
struct ElfPhdr phdr;
|
||||||
char buf[1024];
|
char buf[4096];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PathSearcher {
|
struct PathSearcher {
|
||||||
int os;
|
int os;
|
||||||
int literally;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *syspath;
|
const char *syspath;
|
||||||
unsigned long namelen;
|
unsigned long namelen;
|
||||||
char path[PATH_MAX];
|
char path[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ApeLoader {
|
struct ApeLoader {
|
||||||
|
union ElfEhdrBuf ehdr;
|
||||||
union ElfPhdrBuf phdr;
|
union ElfPhdrBuf phdr;
|
||||||
struct PathSearcher ps;
|
struct PathSearcher ps;
|
||||||
char path[PATH_MAX];
|
char path[1024];
|
||||||
};
|
};
|
||||||
|
|
||||||
EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
|
long SystemCall(long, long, long, long, long, long, long, int);
|
||||||
EXTERN_C void Launch(void *, long, void *, int, void *)
|
void Launch(void *, long, void *, int) __attribute__((__noreturn__));
|
||||||
__attribute__((__noreturn__));
|
|
||||||
|
|
||||||
extern char __executable_start[];
|
extern char __executable_start[];
|
||||||
extern char _end[];
|
extern char _end[];
|
||||||
|
|
||||||
|
static int ToLower(int c) {
|
||||||
|
return 'A' <= c && c <= 'Z' ? c + ('a' - 'A') : c;
|
||||||
|
}
|
||||||
|
|
||||||
static unsigned long StrLen(const char *s) {
|
static unsigned long StrLen(const char *s) {
|
||||||
unsigned long n = 0;
|
unsigned long n = 0;
|
||||||
while (*s++)
|
while (*s++) ++n;
|
||||||
++n;
|
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int StrCmp(const char *l, const char *r) {
|
static int StrCmp(const char *l, const char *r) {
|
||||||
unsigned long i = 0;
|
unsigned long i = 0;
|
||||||
while (l[i] == r[i] && r[i])
|
while (l[i] == r[i] && r[i]) ++i;
|
||||||
++i;
|
|
||||||
return (l[i] & 255) - (r[i] & 255);
|
return (l[i] & 255) - (r[i] & 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
static const char *BaseName(const char *s) {
|
||||||
|
int c;
|
||||||
static const char *StrRChr(const char *s, int c) {
|
const char *b = "";
|
||||||
const char *b = 0;
|
|
||||||
if (s) {
|
if (s) {
|
||||||
for (; *s; ++s) {
|
while ((c = *s++)) {
|
||||||
if (*s == c) {
|
if (c == '/') {
|
||||||
b = s;
|
b = s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -257,13 +249,6 @@ static const char *StrRChr(const char *s, int c) {
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *BaseName(const char *s) {
|
|
||||||
const char *b = StrRChr(s, '/');
|
|
||||||
return b ? b + 1 : s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static void Bzero(void *a, unsigned long n) {
|
static void Bzero(void *a, unsigned long n) {
|
||||||
long z;
|
long z;
|
||||||
char *p, *e;
|
char *p, *e;
|
||||||
|
@ -338,7 +323,24 @@ static char *GetEnv(char **p, const char *s) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *Utoa(char p[20], unsigned long x) {
|
static char *Utox(char p[19], unsigned long x) {
|
||||||
|
int i;
|
||||||
|
if (x) {
|
||||||
|
*p++ = '0';
|
||||||
|
*p++ = 'x';
|
||||||
|
i = (__builtin_clzl(x) ^ (sizeof(long) * 8 - 1)) + 1;
|
||||||
|
i = (i + 3) & -4;
|
||||||
|
do {
|
||||||
|
*p++ = "0123456789abcdef"[(x >> (i -= 4)) & 15];
|
||||||
|
} while (i);
|
||||||
|
} else {
|
||||||
|
*p++ = '0';
|
||||||
|
}
|
||||||
|
*p = 0;
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *Utoa(char p[21], unsigned long x) {
|
||||||
char t;
|
char t;
|
||||||
unsigned long i, a, b;
|
unsigned long i, a, b;
|
||||||
i = 0;
|
i = 0;
|
||||||
|
@ -358,8 +360,7 @@ static char *Utoa(char p[20], unsigned long x) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *Itoa(char p[21], long x) {
|
static char *Itoa(char p[21], long x) {
|
||||||
if (x < 0)
|
if (x < 0) *p++ = '-', x = -(unsigned long)x;
|
||||||
*p++ = '-', x = -(unsigned long)x;
|
|
||||||
return Utoa(p, x);
|
return Utoa(p, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,8 +369,7 @@ __attribute__((__noinline__)) static long CallSystem(long arg1, long arg2,
|
||||||
long arg5, long arg6,
|
long arg5, long arg6,
|
||||||
long arg7, int numba,
|
long arg7, int numba,
|
||||||
char os) {
|
char os) {
|
||||||
if (IsXnu())
|
if (IsXnu()) numba |= 0x2000000;
|
||||||
numba |= 0x2000000;
|
|
||||||
return SystemCall(arg1, arg2, arg3, arg4, arg5, arg6, arg7, numba);
|
return SystemCall(arg1, arg2, arg3, arg4, arg5, arg6, arg7, numba);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -517,62 +517,10 @@ static long Print(int os, int fd, const char *s, ...) {
|
||||||
return Write(fd, b, n, os);
|
return Write(fd, b, n, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
static long Printf(int os, int fd, const char *fmt, ...) {
|
|
||||||
int i;
|
|
||||||
char c;
|
|
||||||
int k = 0;
|
|
||||||
unsigned u;
|
|
||||||
char b[512];
|
|
||||||
const char *s;
|
|
||||||
unsigned long d;
|
|
||||||
__builtin_va_list va;
|
|
||||||
__builtin_va_start(va, fmt);
|
|
||||||
for (;;) {
|
|
||||||
switch ((c = *fmt++)) {
|
|
||||||
case '\0':
|
|
||||||
__builtin_va_end(va);
|
|
||||||
return Write(fd, b, k, os);
|
|
||||||
case '%':
|
|
||||||
switch ((c = *fmt++)) {
|
|
||||||
case 's':
|
|
||||||
for (s = __builtin_va_arg(va, const char *); s && *s; ++s) {
|
|
||||||
if (k < 512)
|
|
||||||
b[k++] = *s;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
d = __builtin_va_arg(va, unsigned long);
|
|
||||||
for (i = 16; i--;) {
|
|
||||||
u = (d >> (i * 4)) & 15;
|
|
||||||
if (u < 10) {
|
|
||||||
c = '0' + u;
|
|
||||||
} else {
|
|
||||||
u -= 10;
|
|
||||||
c = 'a' + u;
|
|
||||||
}
|
|
||||||
if (k < 512)
|
|
||||||
b[k++] = c;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (k < 512)
|
|
||||||
b[k++] = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (k < 512)
|
|
||||||
b[k++] = c;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Perror(int os, const char *thing, long rc, const char *reason) {
|
static void Perror(int os, const char *thing, long rc, const char *reason) {
|
||||||
char ibuf[21];
|
char ibuf[21];
|
||||||
ibuf[0] = 0;
|
ibuf[0] = 0;
|
||||||
if (rc)
|
if (rc) Itoa(ibuf, -rc);
|
||||||
Itoa(ibuf, -rc);
|
|
||||||
Print(os, 2, "ape error: ", thing, ": ", reason,
|
Print(os, 2, "ape error: ", thing, ": ", reason,
|
||||||
rc ? " failed w/ errno " : "", ibuf, "\n", 0l);
|
rc ? " failed w/ errno " : "", ibuf, "\n", 0l);
|
||||||
}
|
}
|
||||||
|
@ -583,17 +531,38 @@ __attribute__((__noreturn__)) static void Pexit(int os, const char *c, int rc,
|
||||||
Exit(127, os);
|
Exit(127, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char AccessCommand(struct PathSearcher *ps, unsigned long pathlen) {
|
static char EndsWithIgnoreCase(const char *p, unsigned long n, const char *s) {
|
||||||
if (pathlen + 1 + ps->namelen + 1 > sizeof(ps->path))
|
unsigned long i, m;
|
||||||
|
if (n >= (m = StrLen(s))) {
|
||||||
|
for (i = n - m; i < n; ++i) {
|
||||||
|
if (ToLower(p[i]) != *s++) {
|
||||||
return 0;
|
return 0;
|
||||||
if (pathlen && ps->path[pathlen - 1] != '/')
|
}
|
||||||
ps->path[pathlen++] = '/';
|
}
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static char IsComPath(struct PathSearcher *ps) {
|
||||||
|
return EndsWithIgnoreCase(ps->name, ps->namelen, ".com") ||
|
||||||
|
EndsWithIgnoreCase(ps->name, ps->namelen, ".exe") ||
|
||||||
|
EndsWithIgnoreCase(ps->name, ps->namelen, ".com.dbg");
|
||||||
|
}
|
||||||
|
|
||||||
|
static char AccessCommand(struct PathSearcher *ps, const char *suffix,
|
||||||
|
unsigned long pathlen) {
|
||||||
|
unsigned long suffixlen;
|
||||||
|
suffixlen = StrLen(suffix);
|
||||||
|
if (pathlen + 1 + ps->namelen + suffixlen + 1 > sizeof(ps->path)) return 0;
|
||||||
|
if (pathlen && ps->path[pathlen - 1] != '/') ps->path[pathlen++] = '/';
|
||||||
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
MemMove(ps->path + pathlen, ps->name, ps->namelen);
|
||||||
ps->path[pathlen + ps->namelen] = 0;
|
MemMove(ps->path + pathlen + ps->namelen, suffix, suffixlen + 1);
|
||||||
return !Access(ps->path, X_OK, ps->os);
|
return !Access(ps->path, X_OK, ps->os);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char SearchPath(struct PathSearcher *ps) {
|
static char SearchPath(struct PathSearcher *ps, const char *suffix) {
|
||||||
const char *p;
|
const char *p;
|
||||||
unsigned long i;
|
unsigned long i;
|
||||||
for (p = ps->syspath;;) {
|
for (p = ps->syspath;;) {
|
||||||
|
@ -602,7 +571,7 @@ static char SearchPath(struct PathSearcher *ps) {
|
||||||
ps->path[i] = p[i];
|
ps->path[i] = p[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (AccessCommand(ps, i)) {
|
if (AccessCommand(ps, suffix, i)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (p[i] == ':') {
|
} else if (p[i] == ':') {
|
||||||
p += i + 1;
|
p += i + 1;
|
||||||
|
@ -612,25 +581,28 @@ static char SearchPath(struct PathSearcher *ps) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *Commandv(struct PathSearcher *ps, int os, char *name,
|
static char FindCommand(struct PathSearcher *ps, const char *suffix) {
|
||||||
|
if (MemChr(ps->name, '/', ps->namelen)) {
|
||||||
|
ps->path[0] = 0;
|
||||||
|
return AccessCommand(ps, suffix, 0);
|
||||||
|
}
|
||||||
|
return SearchPath(ps, suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *Commandv(struct PathSearcher *ps, int os, const char *name,
|
||||||
const char *syspath) {
|
const char *syspath) {
|
||||||
if (!(ps->namelen = StrLen((ps->name = name))))
|
|
||||||
return 0;
|
|
||||||
if (ps->literally || MemChr(ps->name, '/', ps->namelen))
|
|
||||||
return name;
|
|
||||||
ps->os = os;
|
ps->os = os;
|
||||||
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
|
ps->syspath = syspath ? syspath : "/bin:/usr/local/bin:/usr/bin";
|
||||||
if (ps->namelen + 1 > sizeof(ps->path))
|
if (!(ps->namelen = StrLen((ps->name = name)))) return 0;
|
||||||
return 0;
|
if (ps->namelen + 1 > sizeof(ps->path)) return 0;
|
||||||
ps->path[0] = 0;
|
if (FindCommand(ps, "") || (!IsComPath(ps) && FindCommand(ps, ".com"))) {
|
||||||
if (SearchPath(ps)) {
|
|
||||||
return ps->path;
|
return ps->path;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
__attribute__((__noreturn__)) static void Spawn(int os, const char *exe, int fd,
|
||||||
long *sp, unsigned long pagesz,
|
long *sp, unsigned long pagesz,
|
||||||
struct ElfEhdr *e,
|
struct ElfEhdr *e,
|
||||||
struct ElfPhdr *p) {
|
struct ElfPhdr *p) {
|
||||||
|
@ -650,6 +622,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
found_code = 0;
|
found_code = 0;
|
||||||
found_entry = 0;
|
found_entry = 0;
|
||||||
virtmin = virtmax = 0;
|
virtmin = virtmax = 0;
|
||||||
|
if (!pagesz) pagesz = 4096;
|
||||||
if (pagesz & (pagesz - 1)) {
|
if (pagesz & (pagesz - 1)) {
|
||||||
Pexit(os, exe, 0, "AT_PAGESZ isn't two power");
|
Pexit(os, exe, 0, "AT_PAGESZ isn't two power");
|
||||||
}
|
}
|
||||||
|
@ -678,8 +651,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
Pexit(os, exe, 0, "ELF segments overlap your APE loader");
|
Pexit(os, exe, 0, "ELF segments overlap your APE loader");
|
||||||
}
|
}
|
||||||
for (j = i + 1; j < e->e_phnum; ++j) {
|
for (j = i + 1; j < e->e_phnum; ++j) {
|
||||||
if (p[j].p_type != PT_LOAD)
|
if (p[j].p_type != PT_LOAD) continue;
|
||||||
continue;
|
|
||||||
c = p[j].p_vaddr & -pagesz;
|
c = p[j].p_vaddr & -pagesz;
|
||||||
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
|
d = (p[j].p_vaddr + p[j].p_memsz + (pagesz - 1)) & -pagesz;
|
||||||
if (MAX(a, c) < MIN(b, d)) {
|
if (MAX(a, c) < MIN(b, d)) {
|
||||||
|
@ -712,8 +684,7 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
if (e->e_type == ET_DYN) {
|
if (e->e_type == ET_DYN) {
|
||||||
rc = Mmap(0, virtmax - virtmin, PROT_NONE,
|
rc = Mmap(0, virtmax - virtmin, PROT_NONE,
|
||||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0, os);
|
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0, os);
|
||||||
if (rc < 0)
|
if (rc < 0) Pexit(os, exe, rc, "pie mmap");
|
||||||
Pexit(os, exe, rc, "pie mmap");
|
|
||||||
dynbase = rc;
|
dynbase = rc;
|
||||||
if (dynbase & (pagesz - 1)) {
|
if (dynbase & (pagesz - 1)) {
|
||||||
Pexit(os, exe, 0, "OS mmap incongruent w/ AT_PAGESZ");
|
Pexit(os, exe, 0, "OS mmap incongruent w/ AT_PAGESZ");
|
||||||
|
@ -727,70 +698,48 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
|
|
||||||
/* load elf */
|
/* load elf */
|
||||||
for (i = 0; i < e->e_phnum; ++i) {
|
for (i = 0; i < e->e_phnum; ++i) {
|
||||||
void *addr;
|
if (p[i].p_type != PT_LOAD) continue;
|
||||||
unsigned long size;
|
|
||||||
if (p[i].p_type != PT_LOAD)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
/* configure mapping */
|
/* configure mapping */
|
||||||
prot = 0;
|
prot = 0;
|
||||||
flags = MAP_FIXED | MAP_PRIVATE;
|
flags = MAP_FIXED | MAP_PRIVATE;
|
||||||
if (p[i].p_flags & PF_R)
|
if (p[i].p_flags & PF_R) prot |= PROT_READ;
|
||||||
prot |= PROT_READ;
|
if (p[i].p_flags & PF_W) prot |= PROT_WRITE;
|
||||||
if (p[i].p_flags & PF_W)
|
if (p[i].p_flags & PF_X) prot |= PROT_EXEC;
|
||||||
prot |= PROT_WRITE;
|
|
||||||
if (p[i].p_flags & PF_X)
|
|
||||||
prot |= PROT_EXEC;
|
|
||||||
|
|
||||||
if (p[i].p_filesz) {
|
|
||||||
/* load from file */
|
/* load from file */
|
||||||
|
if (p[i].p_filesz) {
|
||||||
|
void *addr;
|
||||||
int prot1, prot2;
|
int prot1, prot2;
|
||||||
unsigned long wipe;
|
unsigned long size;
|
||||||
prot1 = prot;
|
prot1 = prot;
|
||||||
prot2 = prot;
|
prot2 = prot;
|
||||||
/* when we ask the system to map the interval [vaddr,vaddr+filesz)
|
|
||||||
it might schlep extra file content into memory on both the left
|
|
||||||
and the righthand side. that's because elf doesn't require that
|
|
||||||
either side of the interval be aligned on the system page size.
|
|
||||||
normally we can get away with ignoring these junk bytes. but if
|
|
||||||
the segment defines bss memory (i.e. memsz > filesz) then we'll
|
|
||||||
need to clear the extra bytes in the page, if they exist. since
|
|
||||||
we can't do that if we're mapping a read-only page, we can just
|
|
||||||
map it with write permissions and call mprotect on it afterward */
|
|
||||||
a = p[i].p_vaddr + p[i].p_filesz; /* end of file content */
|
a = p[i].p_vaddr + p[i].p_filesz; /* end of file content */
|
||||||
b = (a + (pagesz - 1)) & -pagesz; /* first pure bss page */
|
b = (a + (pagesz - 1)) & -pagesz; /* first pure bss page */
|
||||||
c = p[i].p_vaddr + p[i].p_memsz; /* end of segment data */
|
c = p[i].p_vaddr + p[i].p_memsz; /* end of segment data */
|
||||||
wipe = MIN(b - a, c - a);
|
if (b > c) b = c;
|
||||||
if (wipe && (~prot1 & PROT_WRITE)) {
|
if (c > b && (~prot1 & PROT_WRITE)) {
|
||||||
prot1 = PROT_READ | PROT_WRITE;
|
prot1 = PROT_READ | PROT_WRITE;
|
||||||
}
|
}
|
||||||
addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz));
|
addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz));
|
||||||
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz;
|
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_filesz;
|
||||||
rc = Mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz, os);
|
rc = Mmap(addr, size, prot1, flags, fd, p[i].p_offset & -pagesz, os);
|
||||||
if (rc < 0)
|
if (rc < 0) Pexit(os, exe, rc, "prog mmap");
|
||||||
Pexit(os, exe, rc, "prog mmap");
|
if (c > b) Bzero((void *)(dynbase + a), b - a);
|
||||||
if (wipe)
|
|
||||||
Bzero((void *)(dynbase + a), wipe);
|
|
||||||
if (prot2 != prot1) {
|
if (prot2 != prot1) {
|
||||||
rc = Mprotect(addr, size, prot2, os);
|
rc = Mprotect(addr, size, prot2, os);
|
||||||
if (rc < 0)
|
if (rc < 0) Pexit(os, exe, rc, "prog mprotect");
|
||||||
Pexit(os, exe, rc, "prog mprotect");
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* allocate extra bss */
|
/* allocate extra bss */
|
||||||
if (c > b) {
|
a = p[i].p_vaddr + p[i].p_filesz;
|
||||||
|
a = (a + (pagesz - 1)) & -pagesz;
|
||||||
|
b = p[i].p_vaddr + p[i].p_memsz;
|
||||||
|
if (b > a) {
|
||||||
flags |= MAP_ANONYMOUS;
|
flags |= MAP_ANONYMOUS;
|
||||||
rc = Mmap((void *)(dynbase + b), c - b, prot, flags, -1, 0, os);
|
rc = Mmap((void *)(dynbase + a), b - a, prot, flags, -1, 0, os);
|
||||||
if (rc < 0)
|
if (rc < 0) Pexit(os, exe, rc, "bss mmap");
|
||||||
Pexit(os, exe, rc, "extra bss mmap");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/* allocate pure bss */
|
|
||||||
addr = (void *)(dynbase + (p[i].p_vaddr & -pagesz));
|
|
||||||
size = (p[i].p_vaddr & (pagesz - 1)) + p[i].p_memsz;
|
|
||||||
flags |= MAP_ANONYMOUS;
|
|
||||||
rc = Mmap(addr, size, prot, flags, -1, 0, os);
|
|
||||||
if (rc < 0)
|
|
||||||
Pexit(os, exe, rc, "bss mmap");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -799,27 +748,25 @@ __attribute__((__noreturn__)) static void Spawn(int os, char *exe, int fd,
|
||||||
Msyscall(dynbase + code, codesize, os);
|
Msyscall(dynbase + code, codesize, os);
|
||||||
|
|
||||||
/* call program entrypoint */
|
/* call program entrypoint */
|
||||||
Launch(IsFreebsd() ? sp : 0, dynbase + e->e_entry, exe, os, sp);
|
Launch(IsFreebsd() ? sp : 0, dynbase + e->e_entry, sp, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
static const char *TryElf(struct ApeLoader *M, const char *exe, int fd,
|
||||||
char *exe, int fd, long *sp, long *auxv,
|
long *sp, long *auxv, unsigned long pagesz, int os) {
|
||||||
unsigned long pagesz, int os) {
|
|
||||||
long i, rc;
|
long i, rc;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
struct ElfEhdr *e;
|
struct ElfEhdr *e;
|
||||||
struct ElfPhdr *p;
|
struct ElfPhdr *p;
|
||||||
|
|
||||||
/* validate page size */
|
/* validate page size */
|
||||||
if (!pagesz)
|
if (!pagesz) pagesz = 4096;
|
||||||
pagesz = 4096;
|
|
||||||
if (pagesz & (pagesz - 1)) {
|
if (pagesz & (pagesz - 1)) {
|
||||||
Pexit(os, exe, 0, "AT_PAGESZ isn't two power");
|
Pexit(os, exe, 0, "AT_PAGESZ isn't two power");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* validate elf header */
|
/* validate elf header */
|
||||||
e = &ebuf->ehdr;
|
e = &M->ehdr.ehdr;
|
||||||
if (READ32(ebuf->buf) != READ32("\177ELF")) {
|
if (READ32(M->ehdr.buf) != READ32("\177ELF")) {
|
||||||
return "didn't embed ELF magic";
|
return "didn't embed ELF magic";
|
||||||
}
|
}
|
||||||
if (e->e_ident[EI_CLASS] == ELFCLASS32) {
|
if (e->e_ident[EI_CLASS] == ELFCLASS32) {
|
||||||
|
@ -837,10 +784,6 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
||||||
return "couldn't find ELF header with x86-64 machine type";
|
return "couldn't find ELF header with x86-64 machine type";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if ((e->e_flags & EF_APE_MODERN_MASK) != EF_APE_MODERN && sp[0] > 0) {
|
|
||||||
/* change argv[0] to resolved path for older binaries */
|
|
||||||
((char **)(sp + 1))[0] = exe;
|
|
||||||
}
|
|
||||||
if (e->e_phentsize != sizeof(struct ElfPhdr)) {
|
if (e->e_phentsize != sizeof(struct ElfPhdr)) {
|
||||||
Pexit(os, exe, 0, "e_phentsize is wrong");
|
Pexit(os, exe, 0, "e_phentsize is wrong");
|
||||||
}
|
}
|
||||||
|
@ -851,10 +794,8 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
||||||
|
|
||||||
/* read program headers */
|
/* read program headers */
|
||||||
rc = Pread(fd, M->phdr.buf, size, e->e_phoff, os);
|
rc = Pread(fd, M->phdr.buf, size, e->e_phoff, os);
|
||||||
if (rc < 0)
|
if (rc < 0) return "failed to read ELF program headers";
|
||||||
return "failed to read ELF program headers";
|
if (rc != size) return "truncated read of ELF program headers";
|
||||||
if (rc != size)
|
|
||||||
return "truncated read of ELF program headers";
|
|
||||||
|
|
||||||
/* bail on recoverable program header errors */
|
/* bail on recoverable program header errors */
|
||||||
p = &M->phdr.phdr;
|
p = &M->phdr.phdr;
|
||||||
|
@ -929,37 +870,39 @@ static const char *TryElf(struct ApeLoader *M, union ElfEhdrBuf *ebuf,
|
||||||
Spawn(os, exe, fd, sp, pagesz, e, p);
|
Spawn(os, exe, fd, sp, pagesz, e, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
__attribute__((__noreturn__)) static void ShowUsage(int os, int fd, int rc) {
|
static __attribute__((__noreturn__)) void ShowUsage(int os, int fd, int rc) {
|
||||||
Print(os, fd,
|
Print(os, fd,
|
||||||
"NAME\n"
|
"NAME\n"
|
||||||
"\n"
|
"\n"
|
||||||
" actually portable executable loader version " APE_VERSION_STR "\n"
|
" actually portable executable loader version 1.5\n"
|
||||||
" copyrights 2024 justine alexandra roberts tunney\n"
|
" copyright 2023 justine alexandra roberts tunney\n"
|
||||||
" https://justine.lol/ape.html\n"
|
" https://justine.lol/ape.html\n"
|
||||||
"\n"
|
"\n"
|
||||||
"USAGE\n"
|
"USAGE\n"
|
||||||
"\n"
|
"\n"
|
||||||
" ape PROG [ARGV1,ARGV2,...]\n"
|
" ape [FLAGS] PROG [ARGV1,ARGV2,...]\n"
|
||||||
" ape - PROG [ARGV0,ARGV1,...]\n"
|
" ape [FLAGS] - PROG [ARGV0,ARGV1,...]\n"
|
||||||
|
"\n"
|
||||||
|
"FLAGS\n"
|
||||||
|
"\n"
|
||||||
|
" -h show this help\n"
|
||||||
|
" -f force loading of program (do not use execve)\n"
|
||||||
"\n",
|
"\n",
|
||||||
0l);
|
0l);
|
||||||
Exit(rc, os);
|
Exit(rc, os);
|
||||||
}
|
}
|
||||||
|
|
||||||
EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
__attribute__((__noreturn__)) //
|
||||||
char dl) {
|
void ApeLoader(long di, long *sp, char dl) {
|
||||||
int rc, n;
|
int rc;
|
||||||
unsigned i;
|
unsigned i, n;
|
||||||
const char *ape;
|
|
||||||
int c, fd, os, argc;
|
int c, fd, os, argc;
|
||||||
struct ApeLoader *M;
|
struct ApeLoader *M;
|
||||||
char arg0, literally;
|
|
||||||
unsigned long pagesz;
|
unsigned long pagesz;
|
||||||
union ElfEhdrBuf *ebuf;
|
long *auxv, *ap, *ew;
|
||||||
long *auxv, *ap, *endp, *sp2;
|
char *p, *pe, *exe, *ape, *prog, **argv, **envp;
|
||||||
char *p, *pe, *exe, *prog, **argv, **envp;
|
|
||||||
|
|
||||||
(void)Printf;
|
(void)Utox;
|
||||||
|
|
||||||
/* detect freebsd */
|
/* detect freebsd */
|
||||||
if (SupportsXnu() && dl == XNU) {
|
if (SupportsXnu() && dl == XNU) {
|
||||||
|
@ -975,7 +918,7 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
argc = *sp;
|
argc = *sp;
|
||||||
argv = (char **)(sp + 1);
|
argv = (char **)(sp + 1);
|
||||||
envp = (char **)(sp + 1 + argc + 1);
|
envp = (char **)(sp + 1 + argc + 1);
|
||||||
auxv = sp + 1 + argc + 1;
|
auxv = (long *)(sp + 1 + argc + 1);
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (!*auxv++) {
|
if (!*auxv++) {
|
||||||
break;
|
break;
|
||||||
|
@ -984,49 +927,51 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
|
|
||||||
/* determine ape loader program name */
|
/* determine ape loader program name */
|
||||||
ape = argv[0];
|
ape = argv[0];
|
||||||
if (!ape)
|
if (!ape) ape = "ape";
|
||||||
ape = "ape";
|
|
||||||
|
|
||||||
/* detect openbsd */
|
/* detect openbsd */
|
||||||
if (SupportsOpenbsd() && !os && !auxv[0]) {
|
if (SupportsOpenbsd() && !os && !auxv[0]) {
|
||||||
os = OPENBSD;
|
os = OPENBSD;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* xnu passes auxv as an array of strings */
|
|
||||||
if (os == XNU) {
|
|
||||||
*auxv = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* detect netbsd and find end of words */
|
/* detect netbsd and find end of words */
|
||||||
pagesz = 0;
|
pagesz = 0;
|
||||||
arg0 = 0;
|
|
||||||
for (ap = auxv; ap[0]; ap += 2) {
|
for (ap = auxv; ap[0]; ap += 2) {
|
||||||
if (ap[0] == AT_PAGESZ) {
|
if (ap[0] == AT_PAGESZ) {
|
||||||
pagesz = ap[1];
|
pagesz = ap[1];
|
||||||
} else if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) {
|
} else if (SupportsNetbsd() && !os && ap[0] == AT_EXECFN_NETBSD) {
|
||||||
os = NETBSD;
|
os = NETBSD;
|
||||||
} else if (SupportsLinux() && ap[0] == AT_FLAGS) {
|
|
||||||
// TODO(mrdomino): maybe set/insert this when we are called as "ape -".
|
|
||||||
arg0 = !!(ap[1] & AT_FLAGS_PRESERVE_ARGV0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!pagesz) {
|
ew = ap + 1;
|
||||||
pagesz = 4096;
|
|
||||||
}
|
|
||||||
endp = ap + 1;
|
|
||||||
|
|
||||||
/* the default operating system */
|
/* allocate loader memory */
|
||||||
|
n = sizeof(*M) / sizeof(long);
|
||||||
|
MemMove(sp - n, sp, (char *)ew - (char *)sp);
|
||||||
|
sp -= n, argv -= n, envp -= n, auxv -= n;
|
||||||
|
M = (struct ApeLoader *)(ew - n);
|
||||||
|
|
||||||
|
/* default operating system */
|
||||||
if (!os) {
|
if (!os) {
|
||||||
os = LINUX;
|
os = LINUX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* parse flags */
|
||||||
|
while (argc > 1) {
|
||||||
|
if (argv[1][0] != '-') break; /* normal argument */
|
||||||
|
if (!argv[1][1]) break; /* hyphen argument */
|
||||||
|
if (!StrCmp(argv[1], "-h") || !StrCmp(argv[1], "--help")) {
|
||||||
|
ShowUsage(os, 1, 0);
|
||||||
|
} else {
|
||||||
|
Print(os, 2, ape, ": invalid flag (pass -h for help)\n", 0l);
|
||||||
|
Exit(1, os);
|
||||||
|
}
|
||||||
|
*++sp = --argc;
|
||||||
|
++argv;
|
||||||
|
}
|
||||||
|
|
||||||
/* we can load via shell, shebang, or binfmt_misc */
|
/* we can load via shell, shebang, or binfmt_misc */
|
||||||
if (arg0) {
|
if (argc >= 3 && !StrCmp(argv[1], "-")) {
|
||||||
literally = 1;
|
|
||||||
prog = (char *)sp[2];
|
|
||||||
argc = sp[2] = sp[0] - 2;
|
|
||||||
argv = (char **)((sp += 2) + 1);
|
|
||||||
} else if ((literally = argc >= 3 && !StrCmp(argv[1], "-"))) {
|
|
||||||
/* if the first argument is a hyphen then we give the user the
|
/* if the first argument is a hyphen then we give the user the
|
||||||
power to change argv[0] or omit it entirely. most operating
|
power to change argv[0] or omit it entirely. most operating
|
||||||
systems don't permit the omission of argv[0] but we do, b/c
|
systems don't permit the omission of argv[0] but we do, b/c
|
||||||
|
@ -1035,67 +980,41 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
argc = sp[3] = sp[0] - 3;
|
argc = sp[3] = sp[0] - 3;
|
||||||
argv = (char **)((sp += 3) + 1);
|
argv = (char **)((sp += 3) + 1);
|
||||||
} else if (argc < 2) {
|
} else if (argc < 2) {
|
||||||
ShowUsage(os, 2, 1);
|
Print(os, 2, ape, ": missing command name (pass -h for help)\n", 0l);
|
||||||
|
Exit(1, os);
|
||||||
} else {
|
} else {
|
||||||
if (argv[1][0] == '-') {
|
|
||||||
rc = !((argv[1][1] == 'h' && !argv[1][2]) ||
|
|
||||||
!StrCmp(argv[1] + 1, "-help"));
|
|
||||||
ShowUsage(os, 1 + rc, rc);
|
|
||||||
}
|
|
||||||
prog = (char *)sp[2];
|
prog = (char *)sp[2];
|
||||||
argc = sp[1] = sp[0] - 1;
|
argc = sp[1] = sp[0] - 1;
|
||||||
argv = (char **)((sp += 1) + 1);
|
argv = (char **)((sp += 1) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* allocate loader memory in program's arg block */
|
|
||||||
n = sizeof(struct ApeLoader);
|
|
||||||
M = (struct ApeLoader *)__builtin_alloca(n);
|
|
||||||
M->ps.literally = literally;
|
|
||||||
|
|
||||||
/* create new bottom of stack for spawned program
|
|
||||||
system v abi aligns this on a 16-byte boundary
|
|
||||||
grows down the alloc by poking the guard pages */
|
|
||||||
n = (endp - sp + 1) * sizeof(long);
|
|
||||||
sp2 = (long *)__builtin_alloca(n);
|
|
||||||
if ((long)sp2 & 15)
|
|
||||||
++sp2;
|
|
||||||
for (; n > 0; n -= pagesz) {
|
|
||||||
((char *)sp2)[n - 1] = 0;
|
|
||||||
}
|
|
||||||
MemMove(sp2, sp, (endp - sp) * sizeof(long));
|
|
||||||
argv = (char **)(sp2 + 1);
|
|
||||||
envp = (char **)(sp2 + 1 + argc + 1);
|
|
||||||
auxv = sp2 + (auxv - sp);
|
|
||||||
sp = sp2;
|
|
||||||
|
|
||||||
/* allocate ephemeral memory for reading file */
|
|
||||||
n = sizeof(union ElfEhdrBuf);
|
|
||||||
ebuf = (union ElfEhdrBuf *)__builtin_alloca(n);
|
|
||||||
for (; n > 0; n -= pagesz) {
|
|
||||||
((char *)ebuf)[n - 1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* resolve path of executable and read its first page */
|
/* resolve path of executable and read its first page */
|
||||||
if (!(exe = Commandv(&M->ps, os, prog, GetEnv(envp, "PATH")))) {
|
if (!(exe = Commandv(&M->ps, os, prog, GetEnv(envp, "PATH")))) {
|
||||||
Pexit(os, prog, 0, "not found (maybe chmod +x or ./ needed)");
|
Pexit(os, prog, 0, "not found (maybe chmod +x or ./ needed)");
|
||||||
} else if ((fd = Open(exe, O_RDONLY, 0, os)) < 0) {
|
} else if ((fd = Open(exe, O_RDONLY, 0, os)) < 0) {
|
||||||
Pexit(os, exe, fd, "open");
|
Pexit(os, exe, fd, "open");
|
||||||
} else if ((rc = Pread(fd, ebuf->buf, sizeof(ebuf->buf), 0, os)) < 0) {
|
} else if ((rc = Pread(fd, M->ehdr.buf, sizeof(M->ehdr.buf), 0, os)) < 0) {
|
||||||
Pexit(os, exe, rc, "read");
|
Pexit(os, exe, rc, "read");
|
||||||
} else if ((unsigned long)rc < sizeof(ebuf->ehdr)) {
|
} else if ((unsigned long)rc < sizeof(M->ehdr.ehdr)) {
|
||||||
Pexit(os, exe, 0, "too small");
|
Pexit(os, exe, 0, "too small");
|
||||||
}
|
}
|
||||||
pe = ebuf->buf + rc;
|
pe = M->ehdr.buf + rc;
|
||||||
|
|
||||||
|
/* change argv[0] to resolved path if it's ambiguous */
|
||||||
|
if ((argc > 0 && *prog != '/' && *exe == '/' && !StrCmp(prog, argv[0])) ||
|
||||||
|
!StrCmp(BaseName(prog), argv[0])) {
|
||||||
|
argv[0] = exe;
|
||||||
|
}
|
||||||
|
|
||||||
/* ape intended behavior
|
/* ape intended behavior
|
||||||
1. if ape, will scan shell script for elf printf statements
|
1. if ape, will scan shell script for elf printf statements
|
||||||
2. shell script may have multiple lines producing elf headers
|
2. shell script may have multiple lines producing elf headers
|
||||||
3. all elf printf lines must exist in the first 8192 bytes of file
|
3. all elf printf lines must exist in the first 8192 bytes of file
|
||||||
4. elf program headers may appear anywhere in the binary */
|
4. elf program headers may appear anywhere in the binary */
|
||||||
if (READ64(ebuf->buf) == READ64("MZqFpD='") ||
|
if (READ64(M->ehdr.buf) == READ64("MZqFpD='") ||
|
||||||
READ64(ebuf->buf) == READ64("jartsr='") ||
|
READ64(M->ehdr.buf) == READ64("jartsr='") ||
|
||||||
READ64(ebuf->buf) == READ64("APEDBG='")) {
|
READ64(M->ehdr.buf) == READ64("APEDBG='")) {
|
||||||
for (p = ebuf->buf; p < pe; ++p) {
|
for (p = M->ehdr.buf; p < pe; ++p) {
|
||||||
if (READ64(p) != READ64("printf '")) {
|
if (READ64(p) != READ64("printf '")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1113,15 +1032,15 @@ EXTERN_C __attribute__((__noreturn__)) void ApeLoader(long di, long *sp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ebuf->buf[i++] = c;
|
M->ehdr.buf[i++] = c;
|
||||||
if (i >= sizeof(ebuf->buf)) {
|
if (i >= sizeof(M->ehdr.buf)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (i >= sizeof(ebuf->ehdr)) {
|
if (i >= sizeof(M->ehdr.ehdr)) {
|
||||||
TryElf(M, ebuf, exe, fd, sp, auxv, pagesz, os);
|
TryElf(M, exe, fd, sp, auxv, pagesz, os);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Pexit(os, exe, 0, TryElf(M, ebuf, exe, fd, sp, auxv, pagesz, os));
|
Pexit(os, exe, 0, TryElf(M, exe, fd, sp, auxv, pagesz, os));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
/*-*- mode: ld-script; indent-tabs-mode: nil; tab-width: 2; coding: utf-8 -*-│
|
||||||
│ vi: set et sts=2 sw=2 fenc=utf-8 :vi │
|
│vi: set et sts=2 tw=2 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 sw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
│ Copyright 2020 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -18,10 +18,123 @@
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#ifndef APE_MACROS_H_
|
#ifndef APE_MACROS_H_
|
||||||
#define APE_MACROS_H_
|
#define APE_MACROS_H_
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.internal.h"
|
||||||
#ifdef __ASSEMBLER__
|
#ifdef __ASSEMBLER__
|
||||||
/* clang-format off */
|
/* clang-format off */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @fileoverview Macros relevant to αcτµαlly pδrταblε εxεcµταblε.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Calls near (i.e. pc+pcrel<64kB) FUNCTION.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
// @cost 9 bytes overhead
|
||||||
|
.macro rlcall function:req
|
||||||
|
.byte 0x50 # push %[er]ax
|
||||||
|
.byte 0xb8,0,0 # mov $?,%[e]ax
|
||||||
|
jmp 911f
|
||||||
|
.byte 0x58 # pop %[er]ax
|
||||||
|
.byte 0xe8 # call Jvds
|
||||||
|
.long \function\()-.-4
|
||||||
|
jmp 912f
|
||||||
|
911: .byte 0x58 # pop %[er]ax
|
||||||
|
.byte 0xe8 # call Jvds
|
||||||
|
.short \function\()-.-2
|
||||||
|
912:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Loads far (i.e. <1mb) abs constexpr ADDRESS into ES:DI+EDX+RDX.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro movesdi address:req
|
||||||
|
.byte 0xbf # mov $0x????xxxx,%[e]di
|
||||||
|
.short \address>>4
|
||||||
|
.byte 0x8e,0xc7 # mov %di,%es
|
||||||
|
.byte 0xbf # mov $0x????xxxx,%[e]di
|
||||||
|
.short \address&0xf
|
||||||
|
jmp 297f
|
||||||
|
.byte 0xbf # mov $0x????xxxx,%edi
|
||||||
|
.long \address
|
||||||
|
297:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Loads 16-bit CONSTEXPR into Qw-register w/ optional zero-extend.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbmov constexpr:req abcd abcd.hi:req abcd.lo:req
|
||||||
|
.ifnb \abcd
|
||||||
|
.if (\constexpr)<128 && (\constexpr)>=0
|
||||||
|
pushpop \constexpr,\abcd
|
||||||
|
.exitm
|
||||||
|
.endif
|
||||||
|
.endif
|
||||||
|
movb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
movb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Compares 16-bit CONSTEXPR with Qw-register.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbcmp constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
cmpb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
jnz 387f
|
||||||
|
cmpb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
387:
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Adds 16-bit CONSTEXPR to Qw-register.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbadd constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
addb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.if (\constexpr) != 0
|
||||||
|
adcb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Subtracts 16-bit CONSTEXPR from Qw-register.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbsub constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
subb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.if (\constexpr) != 0
|
||||||
|
sbbb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Ands Qw-register with 16-bit CONSTEXPR.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bband constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
.if ((\constexpr)&0xff) != 0xff || ((\constexpr)>>8&0xff) == 0xff
|
||||||
|
andb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.endif
|
||||||
|
.if ((\constexpr)>>8&0xff) != 0xff
|
||||||
|
andb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Ors Qw-register with 16-bit CONSTEXPR.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro bbor constexpr:req abcd.hi:req abcd.lo:req
|
||||||
|
.if ((\constexpr)&0xff) != 0 || ((\constexpr)>>8&0xff) != 0
|
||||||
|
orb $(\constexpr)&0xff,\abcd.lo
|
||||||
|
.endif
|
||||||
|
.if ((\constexpr)>>8&0xff) != 0
|
||||||
|
orb $(\constexpr)>>8&0xff,\abcd.hi
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// Performs ACTION only if in real mode.
|
||||||
|
// @mode long,legacy,real
|
||||||
|
.macro rlo clobber:req action:vararg
|
||||||
|
990: mov $0,\clobber
|
||||||
|
.if .-990b!=3
|
||||||
|
.error "bad clobber or assembler mode"
|
||||||
|
.endif
|
||||||
|
991: \action
|
||||||
|
.rept 2-(.-991b)
|
||||||
|
nop
|
||||||
|
.endr
|
||||||
|
.if .-991b!=2
|
||||||
|
.error "ACTION must be 1-2 bytes"
|
||||||
|
.endif
|
||||||
|
.endm
|
||||||
|
|
||||||
// Initializes real mode stack.
|
// Initializes real mode stack.
|
||||||
// The most holiest of holy code.
|
// The most holiest of holy code.
|
||||||
// @mode real
|
// @mode real
|
||||||
|
@ -84,8 +197,7 @@
|
||||||
/* clang-format on */
|
/* clang-format on */
|
||||||
#elif defined(__LINKER__)
|
#elif defined(__LINKER__)
|
||||||
|
|
||||||
#define BCX_NIBBLE(X) \
|
#define BCX_NIBBLE(X) ((((X)&0xf) > 0x9) ? ((X)&0xf) + 0x37 : ((X)&0xf) + 0x30)
|
||||||
((((X) & 0xf) > 0x9) ? ((X) & 0xf) + 0x37 : ((X) & 0xf) + 0x30)
|
|
||||||
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
#define BCX_OCTET(X) ((BCX_NIBBLE((X) >> 4) << 8) | (BCX_NIBBLE((X) >> 0) << 0))
|
||||||
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
#define BCX_INT16(X) ((BCX_OCTET((X) >> 8) << 16) | (BCX_OCTET((X) >> 0) << 0))
|
||||||
#define BCXSTUB(SYM, X) \
|
#define BCXSTUB(SYM, X) \
|
||||||
|
@ -143,13 +255,20 @@
|
||||||
: 0xffffffffffffffff)
|
: 0xffffffffffffffff)
|
||||||
#define BCD_RIGHT(X) \
|
#define BCD_RIGHT(X) \
|
||||||
(((X)) < 10000 ? 0x20202020 \
|
(((X)) < 10000 ? 0x20202020 \
|
||||||
: (X) < 100000 ? 0x20202030 + (X) % 10 \
|
: (X) < 100000 ? 0x20202030 + \
|
||||||
: (X) < 1000000 ? 0x20203030 + ((X) / 10) % 10 + (X) % 10 * 0x100 \
|
(X) % 10 \
|
||||||
: (X) < 10000000 ? 0x20303030 + ((X) / 100) % 10 + \
|
: (X) < 1000000 ? 0x20203030 + \
|
||||||
((X) / 10) % 10 * 0x100 + (X) % 10 * 0x10000 \
|
((X) / 10) % 10 + \
|
||||||
: (X) < 100000000 \
|
(X) % 10 * 0x100 \
|
||||||
? 0x30303030 + ((X) / 1000) % 10 + ((X) / 100) % 10 * 0x100 + \
|
: (X) < 10000000 ? 0x20303030 + \
|
||||||
((X) / 10) % 10 * 0x10000 + (X) % 10 * 0x1000000 \
|
((X) / 100) % 10 + \
|
||||||
|
((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)
|
: 0xffffffffffffffff)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -160,10 +279,14 @@
|
||||||
HIDDEN(SYM##_desc_ent1 = TSSDESC_ENT1(BASE)); \
|
HIDDEN(SYM##_desc_ent1 = TSSDESC_ENT1(BASE)); \
|
||||||
ASSERT((LIM) >= 0 && (LIM) <= 0xffff, "bare metal TSS is suspiciously fat")
|
ASSERT((LIM) >= 0 && (LIM) <= 0xffff, "bare metal TSS is suspiciously fat")
|
||||||
#define TSSDESC_ENT0(BASE, LIM) \
|
#define TSSDESC_ENT0(BASE, LIM) \
|
||||||
(((LIM) << 0 & 0x000000000000ffff) | ((BASE) << 16 & 0x000000ffffff0000) | \
|
(((LIM) << 0 & 0x000000000000ffff) | \
|
||||||
0x89 << 40 | ((LIM) >> 16 << 48 & 0x000f000000000000) | 0x2 << 52 | \
|
((BASE) << 16 & 0x000000ffffff0000) | \
|
||||||
|
0x89 << 40 | \
|
||||||
|
((LIM) >> 16 << 48 & 0x000f000000000000) | \
|
||||||
|
0x2 << 52 | \
|
||||||
((BASE) >> 24 << 56 & 0xff00000000000000))
|
((BASE) >> 24 << 56 & 0xff00000000000000))
|
||||||
#define TSSDESC_ENT1(BASE) ((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
#define TSSDESC_ENT1(BASE) \
|
||||||
|
((BASE) >> 32 << 0 & 0x00000000ffffffff)
|
||||||
|
|
||||||
#endif /* __ASSEMBLER__ */
|
#endif /* __ASSEMBLER__ */
|
||||||
#endif /* APE_MACROS_H_ */
|
#endif /* APE_MACROS_H_ */
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
#ifndef COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
#ifndef COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||||
#define COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
#define COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_
|
||||||
|
#if !(__ASSEMBLER__ + __LINKER__ + 0)
|
||||||
COSMOPOLITAN_C_START_
|
COSMOPOLITAN_C_START_
|
||||||
|
|
||||||
extern const char __notices[] __attribute__((__weak__));
|
extern const char __comment_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __executable_start[] __attribute__((__weak__));
|
extern unsigned char __executable_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __privileged_start[] __attribute__((__weak__));
|
extern unsigned char __privileged_start[] __attribute__((__weak__));
|
||||||
extern unsigned char _ehead[] __attribute__((__weak__));
|
extern unsigned char _ehead[] __attribute__((__weak__));
|
||||||
|
@ -16,17 +17,13 @@ extern unsigned char _tdata_end[] __attribute__((__weak__));
|
||||||
extern unsigned char _tbss_start[] __attribute__((__weak__));
|
extern unsigned char _tbss_start[] __attribute__((__weak__));
|
||||||
extern unsigned char _tbss_end[] __attribute__((__weak__));
|
extern unsigned char _tbss_end[] __attribute__((__weak__));
|
||||||
extern unsigned char _tls_align[] __attribute__((__weak__));
|
extern unsigned char _tls_align[] __attribute__((__weak__));
|
||||||
extern unsigned char _tdata_align[] __attribute__((__weak__));
|
|
||||||
extern unsigned char _tbss_align[] __attribute__((__weak__));
|
|
||||||
extern unsigned char __test_start[] __attribute__((__weak__));
|
extern unsigned char __test_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __ro[] __attribute__((__weak__));
|
extern unsigned char __ro[] __attribute__((__weak__));
|
||||||
extern unsigned char __data_start[] __attribute__((__weak__));
|
extern uint8_t __data_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __data_end[] __attribute__((__weak__));
|
extern uint8_t __data_end[] __attribute__((__weak__));
|
||||||
extern unsigned char __bss_start[] __attribute__((__weak__));
|
extern uint8_t __bss_start[] __attribute__((__weak__));
|
||||||
extern unsigned char __bss_end[] __attribute__((__weak__));
|
extern uint8_t __bss_end[] __attribute__((__weak__));
|
||||||
extern unsigned long __got_start[] __attribute__((__weak__));
|
|
||||||
extern unsigned long __got_end[] __attribute__((__weak__));
|
|
||||||
extern unsigned char ape_phdrs[] __attribute__((__weak__));
|
|
||||||
|
|
||||||
COSMOPOLITAN_C_END_
|
COSMOPOLITAN_C_END_
|
||||||
|
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
|
||||||
#endif /* COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_ */
|
#endif /* COSMOPOLITAN_APE_SECTIONS_INTERNAL_H_ */
|
||||||
|
|
|
@ -1,703 +0,0 @@
|
||||||
# Actually Portable Executable Specification v0.1
|
|
||||||
|
|
||||||
Actually Portable Executable (APE) is an executable file format that
|
|
||||||
polyglots the Windows Portable Executable (PE) format with a UNIX Sixth
|
|
||||||
Edition style shell script that doesn't have a shebang. This makes it
|
|
||||||
possible to produce a single file binary that executes on the stock
|
|
||||||
installations of the many OSes and architectures.
|
|
||||||
|
|
||||||
## Supported OSes and Architectures
|
|
||||||
|
|
||||||
- AMD64
|
|
||||||
- Linux
|
|
||||||
- MacOS
|
|
||||||
- Windows
|
|
||||||
- FreeBSD
|
|
||||||
- OpenBSD
|
|
||||||
- NetBSD
|
|
||||||
- BIOS
|
|
||||||
|
|
||||||
- ARM64
|
|
||||||
- Linux
|
|
||||||
- MacOS
|
|
||||||
- FreeBSD
|
|
||||||
- Windows (non-native)
|
|
||||||
|
|
||||||
## File Header
|
|
||||||
|
|
||||||
APE defines three separate file magics, all of which are 8 characters
|
|
||||||
long. Any file that starts with one of these magic values can be
|
|
||||||
considered an APE program.
|
|
||||||
|
|
||||||
### (1) APE MZ Magic
|
|
||||||
|
|
||||||
- ASCII: `MZqFpD='`
|
|
||||||
- Hex: 4d 5a 71 46 70 44 3d 27
|
|
||||||
|
|
||||||
This is the canonical magic used by almost all APE programs. It enables
|
|
||||||
maximum portability between OSes. When interpreted as a shell script, it
|
|
||||||
is assigning a single quoted string to an unused variable. The shell
|
|
||||||
will then ignore subsequent binary content that's placed inside the
|
|
||||||
string.
|
|
||||||
|
|
||||||
It is strongly recommended that this magic value be immediately followed
|
|
||||||
by a newline (\n or hex 0a) character. Some shells, e.g. FreeBSD SH and
|
|
||||||
Zsh impose a binary safety check before handing off files that don't
|
|
||||||
have a shebang to `/bin/sh`. That check applies to the first line, which
|
|
||||||
can't contain NUL characters.
|
|
||||||
|
|
||||||
The letters were carefully chosen so as to be valid x86 instructions in
|
|
||||||
all operating modes. This makes it possible to store a BIOS bootloader
|
|
||||||
disk image inside an APE binary. For example, simple CLI programs built
|
|
||||||
with Cosmopolitan Libc will boot from BIOS into long mode if they're
|
|
||||||
treated as a floppy disk image.
|
|
||||||
|
|
||||||
The letters also allow for the possibility of being treated on x86-64 as
|
|
||||||
a flat executable, where the PE / ELF / Mach-O executable structures are
|
|
||||||
ignored, and execution simply begins at the beginning of the file,
|
|
||||||
similar to how MS-DOS .COM binaries work.
|
|
||||||
|
|
||||||
The 0x4a relative offset of the magic causes execution to jump into the
|
|
||||||
MS-DOS stub defined by Portable Executable. APE binaries built by Cosmo
|
|
||||||
Libc use tricks in the MS-DOS stub to check the operating mode and then
|
|
||||||
jump to the appropriate entrypoint, e.g. `_start()`.
|
|
||||||
|
|
||||||
#### Decoded as i8086
|
|
||||||
|
|
||||||
```asm
|
|
||||||
dec %bp
|
|
||||||
pop %dx
|
|
||||||
jno 0x4a
|
|
||||||
jo 0x4a
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Decoded as i386
|
|
||||||
|
|
||||||
```asm
|
|
||||||
push %ebp
|
|
||||||
pop %edx
|
|
||||||
jno 0x4a
|
|
||||||
jo 0x4a
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Decoded as x86-64
|
|
||||||
|
|
||||||
```asm
|
|
||||||
rex.WRB
|
|
||||||
pop %r10
|
|
||||||
jno 0x4a
|
|
||||||
jo 0x4a
|
|
||||||
```
|
|
||||||
|
|
||||||
### (2) APE UNIX-Only Magic
|
|
||||||
|
|
||||||
- ASCII: `jartsr='`
|
|
||||||
- Hex: 6a 61 72 74 73 72 3d 27
|
|
||||||
|
|
||||||
Being a novel executable format that was first published in 2020, the
|
|
||||||
APE file format is less understood by industry tools compared to the PE,
|
|
||||||
ELF, and Mach-O executable file formats, which have been around for
|
|
||||||
decades. For this reason, APE programs that use the MZ magic above can
|
|
||||||
attract attention from Windows AV software, which may be unwanted by
|
|
||||||
developers who aren't interested in targeting the Windows platform.
|
|
||||||
Therefore the `jartsr='` magic is defined which enables the creation of
|
|
||||||
APE binaries that can safely target all non-Windows platforms. Even
|
|
||||||
though this magic is less common, APE interpreters and binfmt-misc
|
|
||||||
installations MUST support this.
|
|
||||||
|
|
||||||
It is strongly recommended that this magic value be immediately followed
|
|
||||||
by a newline (\n or hex 0a) character. Some shells, e.g. FreeBSD SH and
|
|
||||||
Zsh impose a binary safety check before handing off files that don't
|
|
||||||
have a shebang to `/bin/sh`. That check applies to the first line, which
|
|
||||||
can't contain NUL characters.
|
|
||||||
|
|
||||||
The letters were carefully chosen so as to be valid x86 instructions in
|
|
||||||
all operating modes. This makes it possible to store a BIOS bootloader
|
|
||||||
disk image inside an APE binary. For example, simple CLI programs built
|
|
||||||
with Cosmopolitan Libc will boot from BIOS into long mode if they're
|
|
||||||
treated as a floppy disk image.
|
|
||||||
|
|
||||||
The letters also allow for the possibility of being treated on x86-64 as
|
|
||||||
a flat executable, where the PE / ELF / Mach-O executable structures are
|
|
||||||
ignored, and execution simply begins at the beginning of the file,
|
|
||||||
similar to how MS-DOS .COM binaries work.
|
|
||||||
|
|
||||||
The 0x78 relative offset of the magic causes execution to jump into the
|
|
||||||
MS-DOS stub defined by Portable Executable. APE binaries built by Cosmo
|
|
||||||
Libc use tricks in the MS-DOS stub to check the operating mode and then
|
|
||||||
jump to the appropriate entrypoint, e.g. `_start()`.
|
|
||||||
|
|
||||||
#### Decoded as i8086 / i386 / x86-64
|
|
||||||
|
|
||||||
```asm
|
|
||||||
push $0x61
|
|
||||||
jb 0x78
|
|
||||||
jae 0x78
|
|
||||||
```
|
|
||||||
|
|
||||||
### (3) APE Debug Magic
|
|
||||||
|
|
||||||
- ASCII: `APEDBG='`
|
|
||||||
- Hex: 41 50 45 44 42 47 3d 27
|
|
||||||
|
|
||||||
While APE files must be valid shell scripts, in practice, UNIX systems
|
|
||||||
will oftentimes be configured to provide a faster safer alternative to
|
|
||||||
loading an APE binary through `/bin/sh`. The Linux Kernel can be patched
|
|
||||||
to have execve() recognize the APE format and directly load its embedded
|
|
||||||
ELF header. Linux systems can also use binfmt-misc to recognize APE's MZ
|
|
||||||
and jartsr magic, and pass them to a userspace program named `ape` that
|
|
||||||
acts as an interpreter. In such environments, the need sometimes arises
|
|
||||||
to be able to test that the `/bin/sh` is working correctly, in which
|
|
||||||
case the `APEDBG='` magic is RECOMMENDED.
|
|
||||||
|
|
||||||
APE interpreters, execve() implementations, and binfmt-misc installs
|
|
||||||
MUST ignore this magic. If necessary, steps can be taken to help files
|
|
||||||
with this magic be passed to `/bin/sh` like a normal shebang-less shell
|
|
||||||
script for execution.
|
|
||||||
|
|
||||||
## Embedded ELF Header
|
|
||||||
|
|
||||||
APE binaries MAY embed an ELF header inside them. Unlike conventional
|
|
||||||
executable file formats, this header is not stored at a fixed offset.
|
|
||||||
It's instead encoded as octal escape codes in a shell script `printf`
|
|
||||||
statement. For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
printf '\177ELF\2\1\1\011\0\0\0\0\0\0\0\0\2\0\076\0\1\0\0\0\166\105\100\000\000\000\000\000\060\013\000\000\000\000\000\000\000\000\000\000\000\000\000\000\165\312\1\1\100\0\070\0\005\000\0\0\000\000\000\000'
|
|
||||||
```
|
|
||||||
|
|
||||||
This `printf` statement MUST appear in the first 8192 bytes of the APE
|
|
||||||
executable, so as to limit how much of the initial portion of a file an
|
|
||||||
interpreter must load.
|
|
||||||
|
|
||||||
Multiple such `printf` statements MAY appear in the first 8192 bytes, in
|
|
||||||
order to specify multiple architectures. For example, fat binaries built
|
|
||||||
by the `apelink` program (provided by Cosmo Libc) will have two encoded
|
|
||||||
ELF headers, for AMD64 and ARM64, each of which point into the proper
|
|
||||||
file offsets for their respective native code. Therefore, kernels and
|
|
||||||
interpreters which load the APE format directly MUST check the
|
|
||||||
`e_machine` field of the `Elf64_Ehdr` that's decoded from the octal
|
|
||||||
codes, before accepting a `printf` shell statement as valid.
|
|
||||||
|
|
||||||
These printf statements MUST always use only unescaped ASCII characters
|
|
||||||
or octal escape codes. These printf statements MUST NOT use space saving
|
|
||||||
escape codes such as `\n`. For example, rather than saying `\n` it would
|
|
||||||
be valid to say `\012` instead. It's also valid to say `\12` but only if
|
|
||||||
the encoded characters that follow aren't an octal digit.
|
|
||||||
|
|
||||||
For example, the following algorithm may be used for parsing octal:
|
|
||||||
|
|
||||||
```c
|
|
||||||
static int ape_parse_octal(const unsigned char page[8192], int i, int *pc)
|
|
||||||
{
|
|
||||||
int c;
|
|
||||||
if ('0' <= page[i] && page[i] <= '7') {
|
|
||||||
c = page[i++] - '0';
|
|
||||||
if ('0' <= page[i] && page[i] <= '7') {
|
|
||||||
c *= 8;
|
|
||||||
c += page[i++] - '0';
|
|
||||||
if ('0' <= page[i] && page[i] <= '7') {
|
|
||||||
c *= 8;
|
|
||||||
c += page[i++] - '0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*pc = c;
|
|
||||||
}
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
APE aware interpreters SHOULD only take `e_machine` into consideration.
|
|
||||||
It is the responsibility of the `_start()` function to detect the OS.
|
|
||||||
Therefore, multiple `printf` statements are only embedded in the shell
|
|
||||||
script for different CPU architectures.
|
|
||||||
|
|
||||||
The OS ABI field of an APE embedded `Elf64_Ehdr` SHOULD be set to
|
|
||||||
`ELFOSABI_FREEBSD`, since it's the only UNIX OS APE supports that
|
|
||||||
actually checks the field. However different values MAY be chosen for
|
|
||||||
binaries that don't intend to have FreeBSD in their support vector.
|
|
||||||
|
|
||||||
Counter-intuitively, the ARM64 ELF header is used on the MacOS ARM64
|
|
||||||
platform when loading from fat binaries.
|
|
||||||
|
|
||||||
## Embedded Mach-O Header (x86-64 only)
|
|
||||||
|
|
||||||
APE shell scripts that support MacOS on AMD64 must use the `dd` command
|
|
||||||
in a very specific way to specify how the embedded binary Macho-O header
|
|
||||||
is copied backward to the start of the file. For example:
|
|
||||||
|
|
||||||
```
|
|
||||||
dd if="$o" of="$o" bs=8 skip=433 count=66 conv=notrunc
|
|
||||||
```
|
|
||||||
|
|
||||||
These `dd` statements have traditionally been generated by the GNU as
|
|
||||||
and ld.bfd programs by encoding ASCII into 64-bit linker relocations,
|
|
||||||
which necessitated a fixed width for integer values. It took several
|
|
||||||
iterations over APE's history before we eventually got it right:
|
|
||||||
|
|
||||||
- `arg=" 9293"` is how we originally had ape do it
|
|
||||||
- `arg=$(( 9293))` b/c busybox sh disliked quoted space
|
|
||||||
- `arg=9293 ` is generated by modern apelink program
|
|
||||||
|
|
||||||
Software that parses the APE file format, which needs to extract the
|
|
||||||
Macho-O x86-64 header SHOULD support the old binaries that use the
|
|
||||||
previous encodings. To make backwards compatibility simple the following
|
|
||||||
regular expression may be used, which generalizes to all defined
|
|
||||||
formats:
|
|
||||||
|
|
||||||
```c
|
|
||||||
regcomp(&rx,
|
|
||||||
"bs=" // dd block size arg
|
|
||||||
"(['\"] *)?" // #1 optional quote w/ space
|
|
||||||
"(\\$\\(\\( *)?" // #2 optional math w/ space
|
|
||||||
"([[:digit:]]+)" // #3
|
|
||||||
"( *\\)\\))?" // #4 optional math w/ space
|
|
||||||
"( *['\"])?" // #5 optional quote w/ space
|
|
||||||
" +" //
|
|
||||||
"skip=" // dd skip arg
|
|
||||||
"(['\"] *)?" // #6 optional quote w/ space
|
|
||||||
"(\\$\\(\\( *)?" // #7 optional math w/ space
|
|
||||||
"([[:digit:]]+)" // #8
|
|
||||||
"( *\\)\\))?" // #9 optional math w/ space
|
|
||||||
"( *['\"])?" // #10 optional quote w/ space
|
|
||||||
" +" //
|
|
||||||
"count=" // dd count arg
|
|
||||||
"(['\"] *)?" // #11 optional quote w/ space
|
|
||||||
"(\\$\\(\\( *)?" // #12 optional math w/ space
|
|
||||||
"([[:digit:]]+)", // #13
|
|
||||||
REG_EXTENDED);
|
|
||||||
```
|
|
||||||
|
|
||||||
For further details, see the canonical implementation in
|
|
||||||
`cosmopolitan/tool/build/assimilate.c`.
|
|
||||||
|
|
||||||
## Static Linking
|
|
||||||
|
|
||||||
Actually Portable Executables are always statically linked. This
|
|
||||||
revision of the specification does not define any facility for storing
|
|
||||||
code in dynamic shared objects.
|
|
||||||
|
|
||||||
Cosmopolitan Libc provides a solution that enables APE binaries have
|
|
||||||
limited access to dlopen(). By manually loading a platform-specific
|
|
||||||
executable and asking the OS-specific libc's dlopen() to load
|
|
||||||
OS-specific libraries, it becomes possible to use GPUs and GUIs. This
|
|
||||||
has worked great for AI projects like llamafile.
|
|
||||||
|
|
||||||
There is no way for an Actually Portable Executable to interact with
|
|
||||||
OS-specific dynamic shared object extension modules to programming
|
|
||||||
languages. For example, a Lua interpreter compiled as an Actually
|
|
||||||
Portable Executable would have no way of linking extension libraries
|
|
||||||
downloaded from the Lua Rocks package manager. This is primarily because
|
|
||||||
different OSes define incompatible ABIs.
|
|
||||||
|
|
||||||
While it was possible to polyglot PE+ELF+MachO to create multi-OS
|
|
||||||
executables, it simply isn't possible to do that same thing for
|
|
||||||
DLL+DYLIB+SO. Therefore, in order to have DSOs, APE would need to either
|
|
||||||
choose one of the existing formats or invent one of its own, and then
|
|
||||||
develop its own parallel ecosystem of extension software. In the future,
|
|
||||||
the APE specification may expand to encompass this. However the focus to
|
|
||||||
date has been exclusively on executables with limited dlopen() support.
|
|
||||||
|
|
||||||
## Application Binary Interface (ABI)
|
|
||||||
|
|
||||||
APE binaries use the System V ABI, as defined by:
|
|
||||||
|
|
||||||
- [System V ABI - AMD64 Architecture Processor Supplement](https://gitlab.com/x86-psABIs/x86-64-ABI)
|
|
||||||
- AARCH64 has a uniform consensus defined by ARM Limited
|
|
||||||
|
|
||||||
There are however a few changes we've had to make.
|
|
||||||
|
|
||||||
### No Red Zone
|
|
||||||
|
|
||||||
Actually Portable Executables that have Windows and/or bare metal in
|
|
||||||
their support vector MUST be compiled using `-mno-red-zone`. This is
|
|
||||||
because, on Windows, DLLs and other software lurking in the va-space
|
|
||||||
might use tricks like SetThreadContext() to take control of a thread
|
|
||||||
whereas on bare metal, it's also generally accepted that kernel-mode
|
|
||||||
code cannot assume a red zone either due to hardware interrupts that
|
|
||||||
pull the exact same kinds of stunts.
|
|
||||||
|
|
||||||
APE software that only has truly System V ABI conformant OSes (e.g.
|
|
||||||
Linux) in their support vector MAY use the red zone optimization.
|
|
||||||
|
|
||||||
### Thread Local Storage
|
|
||||||
|
|
||||||
#### aarch64
|
|
||||||
|
|
||||||
Here's the TLS memory layout on aarch64:
|
|
||||||
|
|
||||||
```
|
|
||||||
x28
|
|
||||||
%tpidr_el0
|
|
||||||
│
|
|
||||||
│ _Thread_local
|
|
||||||
┌───┼───┬──────────┬──────────┐
|
|
||||||
│tib│dtv│ .tdata │ .tbss │
|
|
||||||
├───┴───┴──────────┴──────────┘
|
|
||||||
│
|
|
||||||
__get_tls()
|
|
||||||
```
|
|
||||||
|
|
||||||
The ARM64 code in actually portable executables use the `x28` register
|
|
||||||
to store the address of the thread information block. All aarch64 code
|
|
||||||
linked into these executables SHOULD be compiled with `-ffixed-x28`
|
|
||||||
which is supported by both Clang and GCC.
|
|
||||||
|
|
||||||
The runtime library for an actually portable executables MAY choose to
|
|
||||||
use `tpidr_el0` instead, if OSes like MacOS aren't being targeted. For
|
|
||||||
example, if the goal is to create a Linux-only fat binary linker program
|
|
||||||
for Musl Libc, then choosing to use the existing `tpidr_el0` convention
|
|
||||||
would be friction-free alternative.
|
|
||||||
|
|
||||||
It's not possible for an APE runtime that targets the full range of OSes
|
|
||||||
to use the `tpidr_el0` register for TLS because Apple won't allow it. On
|
|
||||||
MacOS ARM64 systems, this register can only be used by a runtime to
|
|
||||||
implement the `sched_getcpu()` system call. It's reserved by MacOS.
|
|
||||||
|
|
||||||
#### x86-64
|
|
||||||
|
|
||||||
Here's the TLS memory layout on x86_64:
|
|
||||||
|
|
||||||
```
|
|
||||||
__get_tls()
|
|
||||||
│
|
|
||||||
%fs OpenBSD/NetBSD
|
|
||||||
_Thread_local │
|
|
||||||
┌───┬──────────┬──────────┼───┐
|
|
||||||
│pad│ .tdata │ .tbss │tib│
|
|
||||||
└───┴──────────┴──────────┼───┘
|
|
||||||
│
|
|
||||||
Linux/FreeBSD/Windows/Mac %gs
|
|
||||||
```
|
|
||||||
|
|
||||||
Quite possibly the greatest challenge in Actually Portable Executable
|
|
||||||
working, has been overcoming the incompatibilities between OSes in how
|
|
||||||
thread-local storage works on x86-64. The AMD64 architecture defines two
|
|
||||||
special segment registers. Every OS uses one of these segment registers
|
|
||||||
to implement TLS support. However not all OSes agree on which register
|
|
||||||
to use. Some OSes grant userspace the power to define either of these
|
|
||||||
registers to hold any value that is desired. Some OSes only effectively
|
|
||||||
allow a single one of them to be changed. Lastly, some OSes, e.g.
|
|
||||||
Windows, claim ownership of the memory layout these registers point
|
|
||||||
towards too.
|
|
||||||
|
|
||||||
Here's a breakdown on how much power is granted to userspace runtimes by
|
|
||||||
each OS when it comes to changing amd64 segment registers.
|
|
||||||
|
|
||||||
| | %fs | %gs |
|
|
||||||
|---------|--------------|--------------|
|
|
||||||
| Linux | unrestricted | unrestricted |
|
|
||||||
| MacOS | inaccessible | unrestricted |
|
|
||||||
| Windows | inaccessible | restricted |
|
|
||||||
| FreeBSD | unrestricted | unrestricted |
|
|
||||||
| NetBSD | unrestricted | broken |
|
|
||||||
| OpenBSD | unrestricted | inaccessible |
|
|
||||||
|
|
||||||
Therefore, regardless of which register one we choose, some OSes are
|
|
||||||
going to be incompatible.
|
|
||||||
|
|
||||||
APE binaries are always built with a Linux compiler. So another issue
|
|
||||||
arises in the fact that our Linux-flavored GCC and Clang toolchains
|
|
||||||
(which are used to produce cross-OS binaries) are also only capable of
|
|
||||||
producing TLS instructions that use the %fs convention.
|
|
||||||
|
|
||||||
To solve these challenges, the `cosmocc` compiler will rewrite binary
|
|
||||||
objects after they've been compiled by GCC, so that the `%gs` register
|
|
||||||
is used, rather than `%fs`. Morphing x86-64 binaries after they've been
|
|
||||||
compiled is normally difficult, due to the complexity of the machine
|
|
||||||
instruction language. However GCC provides `-mno-tls-direct-seg-refs`
|
|
||||||
which greatly reduces the complexity of this task. This flag forgoes
|
|
||||||
some optimizations to make the generated code simpler. Rather than doing
|
|
||||||
clever arithmetic with `%fs` prefixes, the compiler will always generate
|
|
||||||
the thread information block address load as a separate instruction.
|
|
||||||
|
|
||||||
```c
|
|
||||||
// Change AMD code to use %gs:0x30 instead of %fs:0
|
|
||||||
// We assume -mno-tls-direct-seg-refs has been used
|
|
||||||
static void ChangeTlsFsToGs(unsigned char *p, size_t n) {
|
|
||||||
unsigned char *e = p + n - 9;
|
|
||||||
while (p <= e) {
|
|
||||||
// we're checking for the following expression:
|
|
||||||
// 0144 == p[0] && // %fs
|
|
||||||
// 0110 == (p[1] & 0373) && // rex.w (and ignore rex.r)
|
|
||||||
// (0213 == p[2] || // mov reg/mem → reg (word-sized)
|
|
||||||
// 0003 == p[2]) && // add reg/mem → reg (word-sized)
|
|
||||||
// 0004 == (p[3] & 0307) && // mod/rm (4,reg,0) means sib → reg
|
|
||||||
// 0045 == p[4] && // sib (5,4,0) → (rbp,rsp,0) → disp32
|
|
||||||
// 0000 == p[5] && // displacement (von Neumann endian)
|
|
||||||
// 0000 == p[6] && // displacement
|
|
||||||
// 0000 == p[7] && // displacement
|
|
||||||
// 0000 == p[8] // displacement
|
|
||||||
uint64_t w = READ64LE(p) & READ64LE("\377\373\377\307\377\377\377\377");
|
|
||||||
if ((w == READ64LE("\144\110\213\004\045\000\000\000") ||
|
|
||||||
w == READ64LE("\144\110\003\004\045\000\000\000")) &&
|
|
||||||
!p[8]) {
|
|
||||||
p[0] = 0145; // change %fs to %gs
|
|
||||||
p[5] = 0x30; // change 0 to 0x30
|
|
||||||
p += 9;
|
|
||||||
} else {
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
By favoring `%gs` we've now ensured friction-free compatibility for the
|
|
||||||
APE runtime on MacOS, Linux, and FreeBSD which are all able to conform
|
|
||||||
easily to this convention. However additional work needs to be done at
|
|
||||||
runtime when an APE program is started on Windows, OpenBSD, and NetBSD.
|
|
||||||
On these platforms, all executable pages must be faulted and morphed to
|
|
||||||
fixup the TLS instructions.
|
|
||||||
|
|
||||||
On OpenBSD and NetBSD, this is as simple as undoing the example
|
|
||||||
operation above. Earlier at compile-time we turned `%fs` into `%gs`.
|
|
||||||
Now, at runtime, `%gs` must be turned back into `%fs`. Since the
|
|
||||||
executable is morphing itself, this is easier said than done.
|
|
||||||
|
|
||||||
OpenBSD for example enforces a `W^X` invariant. Code that's executing
|
|
||||||
can't modify itself at the same time. The way Cosmopolitan solves this
|
|
||||||
is by defining a special part of the binary called `.text.privileged`.
|
|
||||||
This section is aligned to page boundaries. A GNU ld linker script is
|
|
||||||
used to ensure that code which morphs code is placed into this section,
|
|
||||||
through the use of a header-defined cosmo-specific keyword `privileged`.
|
|
||||||
Additionally, the `fixupobj` program is used by the Cosmo build system
|
|
||||||
to ensure that compiled objects don't contain privileged functions that
|
|
||||||
call non-privileged functions. Needless to say, `mprotect()` needs to be
|
|
||||||
a privileged function, so that it can be used to disable the execute bit
|
|
||||||
on all other parts of the executable except for the privileged section,
|
|
||||||
thereby making it writable. Once this has been done, code can change.
|
|
||||||
|
|
||||||
On Windows the displacement bytes of the TLS instruction are changed to
|
|
||||||
use the `%gs:0x1480+i*8` ABI where `i` is a number assigned by the WIN32
|
|
||||||
`TlsAlloc()` API. This avoids the need to call `TlsGetValue()` which is
|
|
||||||
implemented this exact same way under the hood. Even though 0x1480 isn't
|
|
||||||
explicitly documented by MSDN, this ABI is believed to be stable because
|
|
||||||
MSVC generates binaries that use this offset directly. The only caveat
|
|
||||||
is that `TlsAlloc()` must be called as early in the runtime init as
|
|
||||||
possible, to ensure an index less than 64 is returned.
|
|
||||||
|
|
||||||
### Thread Information Block (TIB)
|
|
||||||
|
|
||||||
The Actually Portable Executable Thread Information Block (TIB) is
|
|
||||||
defined by this version of the specification as follows:
|
|
||||||
|
|
||||||
- The 64-bit TIB self-pointer is stored at offset 0x00.
|
|
||||||
- The 64-bit TIB self-pointer is also stored at offset 0x30.
|
|
||||||
- The 32-bit `errno` value is stored at offset 0x3c.
|
|
||||||
|
|
||||||
All other parts of the thread information block should be considered
|
|
||||||
unspecified and therefore reserved for future specifications.
|
|
||||||
|
|
||||||
The APE thread information block is aligned on a 64-byte boundary.
|
|
||||||
|
|
||||||
Cosmopolitan Libc v3.5.8 (c. 2024-07-21) currently implements a thread
|
|
||||||
information block that's 512 bytes in size.
|
|
||||||
|
|
||||||
### Foreign Function Calls
|
|
||||||
|
|
||||||
Even though APE programs always use the System V ABI, there arises the
|
|
||||||
occasional need to interface with foreign functions, e.g. WIN32. The
|
|
||||||
`__attribute__((__ms_abi__))` annotation introduced by GCC v6 is used
|
|
||||||
for this purpose.
|
|
||||||
|
|
||||||
The ability to change a function's ABI on a case-by-case basis is
|
|
||||||
surprisingly enough supported by GCC, Clang, NVCC, and even the AMD HIP
|
|
||||||
compilers for both UNIX systems and Windows. All of these compilers
|
|
||||||
support both the System V ABI and the Microsoft x64 ABI.
|
|
||||||
|
|
||||||
APE binaries will actually favor the Microsoft ABI even when running on
|
|
||||||
UNIX OSes for certain dlopen() use-cases. For example, if we control the
|
|
||||||
code to a CUDA module, which we compile on each OS separately from our
|
|
||||||
main APE binary, then any function that's inside the APE binary whose
|
|
||||||
pointer may be passed into a foreign module SHOULD be compiled to use
|
|
||||||
the Microsoft ABI. This is because in practice the OS-specific module
|
|
||||||
may need to be compiled by MSVC, where MS ABI is the *only* ABI, which
|
|
||||||
forces our UNIX programs to partially conform. Thankfully, all UNIX
|
|
||||||
compilers support doing it on a case-by-case basis.
|
|
||||||
|
|
||||||
### Char Signedness
|
|
||||||
|
|
||||||
Actually Portable Executable defines `char` as signed.
|
|
||||||
|
|
||||||
Therefore conformant APE software MUST use `-fsigned-char` when building
|
|
||||||
code for aarch64, as well as any other architecture that (unlike x86-64)
|
|
||||||
would otherwise define `char` as being `unsigned char` by default.
|
|
||||||
|
|
||||||
This decision was one of the cases where it made sense to offer a more
|
|
||||||
consistent runtime experience for fat multi-arch binaries. However you
|
|
||||||
SHOULD still write code to assume `char` can go either way. But if all
|
|
||||||
you care about is using APE, then you CAN assume `char` is signed.
|
|
||||||
|
|
||||||
### Long Double
|
|
||||||
|
|
||||||
On AMD64 platforms, APE binaries define `long double` as 80-bit.
|
|
||||||
|
|
||||||
On ARM64 platforms, APE binaries define `long double` as 128-bit.
|
|
||||||
|
|
||||||
We accept inconsistency in this case, because hardware acceleration is
|
|
||||||
far more valuable than stylistic consistency in the case of mathematics.
|
|
||||||
|
|
||||||
One challenge arises on AMD64 for supporting `long double` across OSes.
|
|
||||||
Unlike UNIX systems, the Windows Executive on x86-64 initializes the x87
|
|
||||||
FPU to have double (64-bit) precision rather than 80-bit. That's because
|
|
||||||
code compiled by MSVC treats `long double` as though it were `double` to
|
|
||||||
prefer always using the more modern SSE instructions. However System V
|
|
||||||
requires genuine 80-bit `long double` support on AMD64.
|
|
||||||
|
|
||||||
Therefore, if an APE program detects that it's been started on a Windows
|
|
||||||
x86-64 system, then it SHOULD use the following assembly to initialize
|
|
||||||
the x87 FPU in System V ABI mode.
|
|
||||||
|
|
||||||
```asm
|
|
||||||
fldcw 1f(%rip)
|
|
||||||
.rodata
|
|
||||||
.balign 2
|
|
||||||
// 8087 FPU Control Word
|
|
||||||
// IM: Invalid Operation ───────────────┐
|
|
||||||
// DM: Denormal Operand ───────────────┐│
|
|
||||||
// ZM: Zero Divide ───────────────────┐││
|
|
||||||
// OM: Overflow ─────────────────────┐│││
|
|
||||||
// UM: Underflow ───────────────────┐││││
|
|
||||||
// PM: Precision ──────────────────┐│││││
|
|
||||||
// PC: Precision Control ───────┐ ││││││
|
|
||||||
// {float,∅,double,long double}│ ││││││
|
|
||||||
// RC: Rounding Control ──────┐ │ ││││││
|
|
||||||
// {even, →-∞, →+∞, →0} │┌┤ ││││││
|
|
||||||
// ┌┤││ ││││││
|
|
||||||
// d││││rr││││││
|
|
||||||
1: .short 0b00000000000000000001101111111
|
|
||||||
.previous
|
|
||||||
```
|
|
||||||
|
|
||||||
## Executable File Alignment
|
|
||||||
|
|
||||||
Actually Portable Executable is a statically-linked flat executable file
|
|
||||||
format that is, as a thing in itself, agnostic to file alignments. For
|
|
||||||
example, the shell script payload at the beginning of the file and its
|
|
||||||
statements have no such requirements. Alignment requirements are however
|
|
||||||
imposed by the executable formats that APE wraps.
|
|
||||||
|
|
||||||
1. ELF requires that file offsets be congruent with virtual addresses
|
|
||||||
modulo the CPU page size. So when we add a shell script to the start
|
|
||||||
of an executable, we need to round up to the page size in order to
|
|
||||||
maintain ELF's invariant. Although no such roundup is required on the
|
|
||||||
program segments once the invariant is restored. ELF loaders will
|
|
||||||
happily map program headers from arbitrary file intervals (which may
|
|
||||||
overlap) onto arbitrarily virtual intervals (which don't need to be
|
|
||||||
contiguous). In order to do that, the loaders will generally use
|
|
||||||
UNIX's mmap() function which is more restrictive and only accepts
|
|
||||||
addresses and offsets that are page aligned. To make it possible to
|
|
||||||
map an unaligned ELF program header that could potentially start and
|
|
||||||
stop at any byte, ELF loaders round-out the intervals, which means
|
|
||||||
adjacent unrelated data might also get mapped, which may need to be
|
|
||||||
explicitly zero'd. Thanks to the cleverness of ELF, it's possible to
|
|
||||||
have an executable file be very tiny, without needing any alignment
|
|
||||||
bytes, and it'll be loaded into a properly aligned virtual space
|
|
||||||
where segments can be as sparse as we want them to be.
|
|
||||||
|
|
||||||
2. PE doesn't care about congruence and instead defines two separate
|
|
||||||
kinds of alignment. First, PE requires that the layout of segment
|
|
||||||
memory inside the file be aligned on at minimum the classic 512 byte
|
|
||||||
MS-DOS page size. This means that, unlike ELF, some alignment padding
|
|
||||||
may need to be encoded into the file, making it slightly larger. Next
|
|
||||||
PE imposes an alignment restriction on segments once they've been
|
|
||||||
mapped into the virtual address space, which must be rounded to the
|
|
||||||
system page size. Like ELF, PE segments need to be properly ordered
|
|
||||||
but they're allowed to drift apart once mapped in a non-contiguous
|
|
||||||
sparsely mapped way. When inserting shell script content at the start
|
|
||||||
of a PE file, the most problematic thing is the need to round up to
|
|
||||||
the 64kb system granularity, which results in a lot of needless bytes
|
|
||||||
of padding being inserted by a naive second-pass linker.
|
|
||||||
|
|
||||||
3. Apple's Mach-O format is the strictest of them all. While both ELF
|
|
||||||
and PE are defined in such a way that invites great creativity, XNU
|
|
||||||
will simply refuse to an executable that does anything creative with
|
|
||||||
alignment. All loaded segments need to both start and end on a page
|
|
||||||
aligned address. XNU also wants segments to be contiguous similar to
|
|
||||||
portable executable, except it applies to both the file and virtual
|
|
||||||
spaces, which must follow the same structure.
|
|
||||||
|
|
||||||
Actually Portable Executables must conform to the strictest requirements
|
|
||||||
demanded by the support vector. Therefore an APE binary that has headers
|
|
||||||
for all three of the above executable formats MUST conform to the Apple
|
|
||||||
way of doing things. GNU ld linker scripts aren't very good at producing
|
|
||||||
ELF binaries that rigidly conform to this simple naive layout. There are
|
|
||||||
so many ways things can go wrong, where third party code might slip its
|
|
||||||
own custom section name in-between the linker script sections that are
|
|
||||||
explicitly defined, thereby causing ELF's powerful features to manifest
|
|
||||||
and the resulting content overlapping. The best `ld` flag that helps is
|
|
||||||
`--orphan-handling=error` which can help with explaining such mysteries.
|
|
||||||
|
|
||||||
While Cosmopolitan was originally defined to just use stock GNU tools,
|
|
||||||
this proved intractable over time, and the project has been evolving in
|
|
||||||
the direction of building its own. Inventing the `apelink` program was
|
|
||||||
what enabled the project to achieve multi-architecture binaries whereas
|
|
||||||
previously it was only possible to do multi-OS binaries. In the future,
|
|
||||||
our hope is that a fast power linker like Mold can be adapted to produce
|
|
||||||
fat APE binaries directly from object files in one pass.
|
|
||||||
|
|
||||||
## Position Independent Code
|
|
||||||
|
|
||||||
APE doesn't currently support position independent executable formats.
|
|
||||||
This is because APE was originally written for the GNU linker, where PIC
|
|
||||||
and PIE were after-thoughts and never fully incorporated with the older
|
|
||||||
more powerful linker script techniques upon which APE relies. Future
|
|
||||||
iterations of this specification are intended to converge on modern
|
|
||||||
standards, as our tooling becomes developed enough to support it.
|
|
||||||
|
|
||||||
However this only applies to the wrapped executable formats themselves.
|
|
||||||
While our convention to date has been to always load ELF programs at the
|
|
||||||
4mb mark, this is not guaranteed across OSes and architectures. Programs
|
|
||||||
should have no expectations that a program will be loaded to any given
|
|
||||||
address. For example, Cosmo currently implements APE on AARCH64 as
|
|
||||||
loading executables to a starting address of 0x000800000000. This
|
|
||||||
address occupies a sweet spot of requirements.
|
|
||||||
|
|
||||||
## Address Space
|
|
||||||
|
|
||||||
In order to create a single binary that supports as many platforms as
|
|
||||||
possible without needing to be recompiled, there's a very narrow range
|
|
||||||
of addresses that can be used. That range is somewhere between 32 bits
|
|
||||||
and 39 bits.
|
|
||||||
|
|
||||||
- Embedded devices that claim to be 64-bit will oftentimes only support
|
|
||||||
a virtual address space that's 39 bits in size.
|
|
||||||
|
|
||||||
- We can't load executable images on AARCH64 beneath 0x100000000 (4gb)
|
|
||||||
because Apple forbids doing that, possibly in an effort to enforce a
|
|
||||||
best practice for spotting 32-bit to 64-bit transition bugs. Please
|
|
||||||
note that this restriction only applies to Apple ARM64 systems. The
|
|
||||||
x86-64 version of XNU will happily load APE binaries to 0x00400000.
|
|
||||||
|
|
||||||
- The AMD64 architecture on desktops and servers can usually be counted
|
|
||||||
upon to provide a 47-bit address space. The Linux Kernel for instance
|
|
||||||
grants each userspace program full dominion over addresses 0x00200000
|
|
||||||
through 0x00007fffffffffff provided the hardware supports this. On
|
|
||||||
modern workstations supporting Intel and AMD's new PML5T feature which
|
|
||||||
virtualizes memory using a radix trie that's five layers deep, Linux
|
|
||||||
is able to offer userspace its choice of fixed addresses from
|
|
||||||
0x00200000 through 0x00ffffffffffffff. The only exception to this rule
|
|
||||||
we've encountered so far is that Windows 7 and Windows Vista behaved
|
|
||||||
similar to embedded devices in reducing the number of va bits.
|
|
||||||
|
|
||||||
## Page Size
|
|
||||||
|
|
||||||
APE software MUST be page size agnostic. For many years the industry had
|
|
||||||
converged on a strong consensus of having a page size that's 4096 bytes.
|
|
||||||
However this convention was never guaranteed. New computers have become
|
|
||||||
extremely popular, such as Apple Silicon, that use a 16kb page size.
|
|
||||||
|
|
||||||
By convention, Cosmopolitan Libc currently generates ELF headers for
|
|
||||||
x86-64 that are strictly aligned on a 4096-byte page size. On ARM64
|
|
||||||
Cosmopolitan is currently implemented to always generate ELF headers
|
|
||||||
aligned on a 16kb page size.
|
|
||||||
|
|
||||||
In addition to being page size agnostic, APE software that cares about
|
|
||||||
working correctly on Windows needs to be aware of the concept of
|
|
||||||
allocation granularity. While the page size on Windows is generally 4kb
|
|
||||||
in size, memory mappings can only be created on addresses that aligned
|
|
||||||
to the system allocation granularity, which is generally 64kb. If you
|
|
||||||
use a function like mmap() with Cosmopolitan Libc, then the `addr` and
|
|
||||||
`offset` parameters need to be aligned to `sysconf(_SC_GRANSIZE)` or
|
|
||||||
else your software won't work on Windows. Windows has other limitations
|
|
||||||
too, such as lacking the ability to carve or punch holes in mappings.
|
|
10
ape/start.S
10
ape/start.S
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -17,13 +17,11 @@
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/dce.h"
|
#include "libc/dce.h"
|
||||||
#include "ape/ape.h"
|
#include "libc/macros.internal.h"
|
||||||
#include "libc/macros.h"
|
|
||||||
|
|
||||||
#ifdef __aarch64__
|
#ifdef __aarch64__
|
||||||
|
|
||||||
_start: mov x1,sp
|
_start: mov x1,sp
|
||||||
and sp,x1,#-16
|
|
||||||
mov x29,0
|
mov x29,0
|
||||||
bl ApeLoader
|
bl ApeLoader
|
||||||
.endfn _start,globl
|
.endfn _start,globl
|
||||||
|
@ -34,7 +32,7 @@ XnuEntrypoint:
|
||||||
mov $_HOSTXNU,%dl // xnu's not unix!
|
mov $_HOSTXNU,%dl // xnu's not unix!
|
||||||
ElfEntrypoint:
|
ElfEntrypoint:
|
||||||
mov %rsp,%rsi // save real stack
|
mov %rsp,%rsi // save real stack
|
||||||
andq $-16,%rsp // force SSE alignment
|
sub $1024*1024,%rsp // room for allocs
|
||||||
call ApeLoader
|
call ApeLoader
|
||||||
.endfn ElfEntrypoint,globl
|
.endfn ElfEntrypoint,globl
|
||||||
.endfn XnuEntrypoint,globl
|
.endfn XnuEntrypoint,globl
|
||||||
|
@ -67,7 +65,7 @@ ape.ident:
|
||||||
.long 1
|
.long 1
|
||||||
1: .asciz "APE"
|
1: .asciz "APE"
|
||||||
2: .balign 4
|
2: .balign 4
|
||||||
3: .long APE_VERSION_NOTE
|
3: .long 105000000
|
||||||
4: .size ape.ident,.-ape.ident
|
4: .size ape.ident,.-ape.ident
|
||||||
.type ape.ident,@object
|
.type ape.ident,@object
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
/*-*- mode:unix-assembly; indent-tabs-mode:t; tab-width:8; coding:utf-8 -*-│
|
||||||
│ vi: set noet ft=asm ts=8 sw=8 fenc=utf-8 :vi │
|
│vi: set et ft=asm ts=8 tw=8 fenc=utf-8 :vi│
|
||||||
╞══════════════════════════════════════════════════════════════════════════════╡
|
╞══════════════════════════════════════════════════════════════════════════════╡
|
||||||
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
│ Copyright 2023 Justine Alexandra Roberts Tunney │
|
||||||
│ │
|
│ │
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||||
#include "libc/macros.h"
|
#include "libc/macros.internal.h"
|
||||||
|
|
||||||
// Invokes system call.
|
// Invokes system call.
|
||||||
//
|
//
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
build/bootstrap/ape.silicon
Executable file
BIN
build/bootstrap/ape.silicon
Executable file
Binary file not shown.
BIN
build/bootstrap/ar.com
Executable file
BIN
build/bootstrap/ar.com
Executable file
Binary file not shown.
BIN
build/bootstrap/chmod.com
Executable file
BIN
build/bootstrap/chmod.com
Executable file
Binary file not shown.
Binary file not shown.
BIN
build/bootstrap/cocmd.com
Executable file
BIN
build/bootstrap/cocmd.com
Executable file
Binary file not shown.
BIN
build/bootstrap/compile.com
Executable file
BIN
build/bootstrap/compile.com
Executable file
Binary file not shown.
BIN
build/bootstrap/cp.com
Executable file
BIN
build/bootstrap/cp.com
Executable file
Binary file not shown.
BIN
build/bootstrap/echo.com
Executable file
BIN
build/bootstrap/echo.com
Executable file
Binary file not shown.
BIN
build/bootstrap/fixupobj.com
Executable file
BIN
build/bootstrap/fixupobj.com
Executable file
Binary file not shown.
|
@ -1,58 +0,0 @@
|
||||||
--nocompress-debug-sections
|
|
||||||
--noexecstack
|
|
||||||
-Wa,--nocompress-debug-sections
|
|
||||||
-Wa,--noexecstack
|
|
||||||
-Wa,-msse2avx
|
|
||||||
-Werror=maybe-uninitialized
|
|
||||||
-Wno-literal-suffix
|
|
||||||
-Wno-unused-but-set-variable
|
|
||||||
-Wunsafe-loop-optimizations
|
|
||||||
-fbranch-target-load-optimize
|
|
||||||
-fcx-limited-range
|
|
||||||
-fdelete-dead-exceptions
|
|
||||||
-femit-struct-debug-baseonly
|
|
||||||
-ffp-int-builtin-inexact
|
|
||||||
-finline-functions-called-once
|
|
||||||
-fipa-pta
|
|
||||||
-fivopts
|
|
||||||
-flimit-function-alignment
|
|
||||||
-fmerge-constants
|
|
||||||
-fmodulo-sched
|
|
||||||
-fmodulo-sched-allow-regmoves
|
|
||||||
-fno-align-jumps
|
|
||||||
-fno-align-labels
|
|
||||||
-fno-align-loops
|
|
||||||
-fno-code-hoisting
|
|
||||||
-fno-cx-limited-range
|
|
||||||
-fno-fp-int-builtin-inexact
|
|
||||||
-fno-gnu-unique
|
|
||||||
-fno-inline-functions-called-once
|
|
||||||
-fno-instrument-functions
|
|
||||||
-fno-schedule-insns2
|
|
||||||
-fno-whole-program
|
|
||||||
-fopt-info-vec
|
|
||||||
-fopt-info-vec-missed
|
|
||||||
-freg-struct-return
|
|
||||||
-freschedule-modulo-scheduled-loops
|
|
||||||
-frounding-math
|
|
||||||
-fsched2-use-superblocks
|
|
||||||
-fschedule-insns
|
|
||||||
-fschedule-insns2
|
|
||||||
-fshrink-wrap
|
|
||||||
-fshrink-wrap-separate
|
|
||||||
-fsignaling-nans
|
|
||||||
-fstack-clash-protection
|
|
||||||
-ftracer
|
|
||||||
-ftrapv
|
|
||||||
-ftree-loop-im
|
|
||||||
-ftree-loop-vectorize
|
|
||||||
-funsafe-loop-optimizations
|
|
||||||
-fversion-loops-for-strides
|
|
||||||
-fwhole-program
|
|
||||||
-gdescribe-dies
|
|
||||||
-gstabs
|
|
||||||
-mcall-ms2sysv-xlogues
|
|
||||||
-mdispatch-scheduler
|
|
||||||
-mfpmath=sse+387
|
|
||||||
-mmitigate-rop
|
|
||||||
-mno-fentry
|
|
BIN
build/bootstrap/gzip.com
Executable file
BIN
build/bootstrap/gzip.com
Executable file
Binary file not shown.
BIN
build/bootstrap/make.com
Executable file
BIN
build/bootstrap/make.com
Executable file
Binary file not shown.
BIN
build/bootstrap/mkdeps.com
Executable file
BIN
build/bootstrap/mkdeps.com
Executable file
Binary file not shown.
BIN
build/bootstrap/mkdir.com
Executable file
BIN
build/bootstrap/mkdir.com
Executable file
Binary file not shown.
BIN
build/bootstrap/objbincopy.com
Executable file
BIN
build/bootstrap/objbincopy.com
Executable file
Binary file not shown.
BIN
build/bootstrap/package.com
Executable file
BIN
build/bootstrap/package.com
Executable file
Binary file not shown.
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/zipcopy.com
Executable file
BIN
build/bootstrap/zipcopy.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.
133
build/config.mk
133
build/config.mk
|
@ -1,5 +1,5 @@
|
||||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
|
|
||||||
# Default Mode
|
# Default Mode
|
||||||
#
|
#
|
||||||
|
@ -11,19 +11,14 @@
|
||||||
#
|
#
|
||||||
ifeq ($(MODE),)
|
ifeq ($(MODE),)
|
||||||
ENABLE_FTRACE = 1
|
ENABLE_FTRACE = 1
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
CONFIG_OFLAGS ?= -g
|
||||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
|
||||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
|
||||||
endif
|
|
||||||
ifeq ($(MODE), x86_64)
|
|
||||||
ENABLE_FTRACE = 1
|
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
|
||||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||||
|
TARGET_ARCH ?= -msse3
|
||||||
endif
|
endif
|
||||||
ifeq ($(MODE), aarch64)
|
ifeq ($(MODE), aarch64)
|
||||||
ENABLE_FTRACE = 1
|
ENABLE_FTRACE = 1
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
CONFIG_OFLAGS ?= -g
|
||||||
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
CONFIG_CCFLAGS += -O2 $(BACKTRACES)
|
||||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||||
endif
|
endif
|
||||||
|
@ -37,15 +32,15 @@ endif
|
||||||
#
|
#
|
||||||
ifeq ($(MODE), zero)
|
ifeq ($(MODE), zero)
|
||||||
ENABLE_FTRACE = 1
|
ENABLE_FTRACE = 1
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
CONFIG_OFLAGS ?= -g
|
||||||
OVERRIDE_CFLAGS += -O0
|
OVERRIDE_CFLAGS += -O0
|
||||||
OVERRIDE_CXXFLAGS += -O0
|
OVERRIDE_CXXFLAGS += -O0
|
||||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||||
endif
|
endif
|
||||||
ifeq ($(MODE), aarch64-zero)
|
ifeq ($(MODE), aarch64-zero)
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
CONFIG_OFLAGS ?= -g
|
||||||
OVERRIDE_CFLAGS += -O0 -fdce
|
OVERRIDE_CFLAGS += -O0
|
||||||
OVERRIDE_CXXFLAGS += -O0 -fdce
|
OVERRIDE_CXXFLAGS += -O0
|
||||||
CONFIG_CPPFLAGS += -DSYSDEBUG
|
CONFIG_CPPFLAGS += -DSYSDEBUG
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -63,6 +58,7 @@ ENABLE_FTRACE = 1
|
||||||
CONFIG_CCFLAGS += $(BACKTRACES) -O
|
CONFIG_CCFLAGS += $(BACKTRACES) -O
|
||||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DDWARFLESS
|
CONFIG_CPPFLAGS += -DSYSDEBUG -DDWARFLESS
|
||||||
CONFIG_LDFLAGS += -S
|
CONFIG_LDFLAGS += -S
|
||||||
|
TARGET_ARCH ?= -msse3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Optimized Mode
|
# Optimized Mode
|
||||||
|
@ -79,10 +75,10 @@ endif
|
||||||
#
|
#
|
||||||
ifeq ($(MODE), opt)
|
ifeq ($(MODE), opt)
|
||||||
ENABLE_FTRACE = 1
|
ENABLE_FTRACE = 1
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
CONFIG_OFLAGS ?= -g
|
||||||
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
|
CONFIG_CPPFLAGS += -DNDEBUG -DSYSDEBUG
|
||||||
CONFIG_CCFLAGS += $(BACKTRACES) -O3 -fmerge-all-constants
|
CONFIG_CCFLAGS += $(BACKTRACES) -O3 -fmerge-all-constants
|
||||||
CONFIG_TARGET_ARCH ?= -march=native
|
TARGET_ARCH ?= -march=native
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Optimized Linux Mode
|
# Optimized Linux Mode
|
||||||
|
@ -96,24 +92,11 @@ endif
|
||||||
# - Turns off support for other operating systems
|
# - Turns off support for other operating systems
|
||||||
#
|
#
|
||||||
ifeq ($(MODE), optlinux)
|
ifeq ($(MODE), optlinux)
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
CONFIG_OFLAGS ?= -g
|
||||||
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_CPPFLAGS += -DNDEBUG -DSYSDEBUG -DSUPPORT_VECTOR=1
|
||||||
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
|
CONFIG_CCFLAGS += -O3 -fmerge-all-constants
|
||||||
CONFIG_COPTS += -mred-zone
|
CONFIG_COPTS += -mred-zone
|
||||||
|
TARGET_ARCH ?= -march=native
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Release Mode
|
# Release Mode
|
||||||
|
@ -134,13 +117,36 @@ endif
|
||||||
ifeq ($(MODE), rel)
|
ifeq ($(MODE), rel)
|
||||||
CONFIG_CPPFLAGS += -DNDEBUG -DDWARFLESS
|
CONFIG_CPPFLAGS += -DNDEBUG -DDWARFLESS
|
||||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||||
|
TARGET_ARCH ?= -msse3
|
||||||
PYFLAGS += -O1
|
PYFLAGS += -O1
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
# Asan Mode
|
||||||
|
#
|
||||||
|
# Safer binaries good for backend production serving.
|
||||||
|
#
|
||||||
|
# - `make MODE=asan`
|
||||||
|
# - Memory safety
|
||||||
|
# - Production worthy
|
||||||
|
# - Backtraces
|
||||||
|
# - Debuggability
|
||||||
|
# - Larger binaries
|
||||||
|
#
|
||||||
|
ifeq ($(MODE), asan)
|
||||||
|
ENABLE_FTRACE = 1
|
||||||
|
CONFIG_OFLAGS ?= -g
|
||||||
|
CONFIG_CPPFLAGS += -D__SANITIZE_ADDRESS__
|
||||||
|
CONFIG_CCFLAGS += $(BACKTRACES) -O2 -DSYSDEBUG
|
||||||
|
CONFIG_COPTS += -fsanitize=address
|
||||||
|
TARGET_ARCH ?= -msse3
|
||||||
|
QUOTA ?= -C64 -L300
|
||||||
|
endif
|
||||||
|
|
||||||
# Debug Mode
|
# Debug Mode
|
||||||
#
|
#
|
||||||
# - `make MODE=dbg`
|
# - `make MODE=dbg`
|
||||||
# - Backtraces
|
# - Backtraces
|
||||||
|
# - Enables asan
|
||||||
# - Enables ubsan
|
# - Enables ubsan
|
||||||
# - Stack canaries
|
# - Stack canaries
|
||||||
# - No optimization
|
# - No optimization
|
||||||
|
@ -148,33 +154,19 @@ endif
|
||||||
#
|
#
|
||||||
ifeq ($(MODE), dbg)
|
ifeq ($(MODE), dbg)
|
||||||
ENABLE_FTRACE = 1
|
ENABLE_FTRACE = 1
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
CONFIG_OFLAGS ?= -g
|
||||||
OVERRIDE_CFLAGS += -O0
|
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_ADDRESS__ -D__SANITIZE_UNDEFINED__
|
||||||
OVERRIDE_CXXFLAGS += -O0
|
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
|
||||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__ -Wno-unused-variable -Wno-unused-but-set-variable
|
CONFIG_COPTS += -fsanitize=address -fsanitize=undefined
|
||||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG
|
TARGET_ARCH ?= -msse3
|
||||||
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
|
OVERRIDE_CCFLAGS += -fno-pie
|
||||||
QUOTA ?= -C64 -L300
|
QUOTA ?= -C64 -L300
|
||||||
endif
|
endif
|
||||||
ifeq ($(MODE), aarch64-dbg)
|
ifeq ($(MODE), aarch64-dbg)
|
||||||
ENABLE_FTRACE = 1
|
ENABLE_FTRACE = 1
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
CONFIG_OFLAGS ?= -g
|
||||||
OVERRIDE_CFLAGS += -O0 -fdce
|
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__
|
||||||
OVERRIDE_CXXFLAGS += -O0 -fdce
|
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O0 -fno-inline
|
||||||
CONFIG_CPPFLAGS += -DMODE_DBG -D__SANITIZE_UNDEFINED__ -Wno-unused-variable -Wno-unused-but-set-variable
|
|
||||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG
|
|
||||||
CONFIG_COPTS += -fsanitize=undefined
|
CONFIG_COPTS += -fsanitize=undefined
|
||||||
QUOTA ?= -C64 -L300
|
QUOTA ?= -C64 -L300
|
||||||
endif
|
endif
|
||||||
|
@ -191,9 +183,10 @@ endif
|
||||||
#
|
#
|
||||||
ifeq ($(MODE), sysv)
|
ifeq ($(MODE), sysv)
|
||||||
ENABLE_FTRACE = 1
|
ENABLE_FTRACE = 1
|
||||||
CONFIG_OFLAGS ?= -g -ggdb
|
CONFIG_OFLAGS ?= -g
|
||||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
|
CONFIG_CPPFLAGS += -DSYSDEBUG -DSUPPORT_VECTOR=121
|
||||||
|
TARGET_ARCH ?= -msse3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Tiny Mode
|
# Tiny Mode
|
||||||
|
@ -223,25 +216,8 @@ CONFIG_CCFLAGS += \
|
||||||
-momit-leaf-frame-pointer \
|
-momit-leaf-frame-pointer \
|
||||||
-foptimize-sibling-calls \
|
-foptimize-sibling-calls \
|
||||||
-DDWARFLESS
|
-DDWARFLESS
|
||||||
PYFLAGS += \
|
TARGET_ARCH ?= \
|
||||||
-O2 \
|
-msse3
|
||||||
-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 += \
|
PYFLAGS += \
|
||||||
-O2 \
|
-O2 \
|
||||||
-B
|
-B
|
||||||
|
@ -293,6 +269,8 @@ CONFIG_CCFLAGS += \
|
||||||
-fno-align-jumps \
|
-fno-align-jumps \
|
||||||
-fno-align-labels \
|
-fno-align-labels \
|
||||||
-fno-align-loops
|
-fno-align-loops
|
||||||
|
TARGET_ARCH ?= \
|
||||||
|
-msse3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Linux+BSD Tiny Mode
|
# Linux+BSD Tiny Mode
|
||||||
|
@ -322,6 +300,8 @@ CONFIG_CCFLAGS += \
|
||||||
-fno-align-jumps \
|
-fno-align-jumps \
|
||||||
-fno-align-labels \
|
-fno-align-labels \
|
||||||
-fno-align-loops
|
-fno-align-loops
|
||||||
|
TARGET_ARCH ?= \
|
||||||
|
-msse3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Unix Tiny Mode
|
# Unix Tiny Mode
|
||||||
|
@ -350,6 +330,8 @@ CONFIG_CCFLAGS += \
|
||||||
-fno-align-jumps \
|
-fno-align-jumps \
|
||||||
-fno-align-labels \
|
-fno-align-labels \
|
||||||
-fno-align-loops
|
-fno-align-loops
|
||||||
|
TARGET_ARCH ?= \
|
||||||
|
-msse3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# Tiny Metallic Unix Mode
|
# Tiny Metallic Unix Mode
|
||||||
|
@ -378,6 +360,8 @@ CONFIG_CCFLAGS += \
|
||||||
-fno-align-jumps \
|
-fno-align-jumps \
|
||||||
-fno-align-labels \
|
-fno-align-labels \
|
||||||
-fno-align-loops
|
-fno-align-loops
|
||||||
|
TARGET_ARCH ?= \
|
||||||
|
-msse3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# no x87 instructions mode
|
# no x87 instructions mode
|
||||||
|
@ -399,6 +383,7 @@ ENABLE_FTRACE = 1
|
||||||
CONFIG_COPTS += -mlong-double-64
|
CONFIG_COPTS += -mlong-double-64
|
||||||
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
CONFIG_CCFLAGS += $(BACKTRACES) -O2
|
||||||
CONFIG_CPPFLAGS += -DSYSDEBUG -DNOX87
|
CONFIG_CPPFLAGS += -DSYSDEBUG -DNOX87
|
||||||
|
TARGET_ARCH ?= -msse3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# LLVM Mode
|
# LLVM Mode
|
||||||
|
@ -411,6 +396,7 @@ endif
|
||||||
#
|
#
|
||||||
ifeq ($(MODE), llvm)
|
ifeq ($(MODE), llvm)
|
||||||
.STRICT = 0
|
.STRICT = 0
|
||||||
|
TARGET_ARCH ?= -msse3
|
||||||
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O2
|
CONFIG_CCFLAGS += $(BACKTRACES) -DSYSDEBUG -O2
|
||||||
AS = clang
|
AS = clang
|
||||||
CC = clang
|
CC = clang
|
||||||
|
@ -453,6 +439,7 @@ ifeq ($(MODE), ansi)
|
||||||
CONFIG_CFLAGS += -std=c11
|
CONFIG_CFLAGS += -std=c11
|
||||||
#CONFIG_CPPFLAGS += -ansi
|
#CONFIG_CPPFLAGS += -ansi
|
||||||
CONFIG_CXXFLAGS += -std=c++11
|
CONFIG_CXXFLAGS += -std=c++11
|
||||||
|
TARGET_ARCH ?= -msse3
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifneq ($(ENABLE_FTRACE),)
|
ifneq ($(ENABLE_FTRACE),)
|
||||||
|
@ -510,5 +497,3 @@ ifeq ($(ARCH), aarch64)
|
||||||
CONFIG_CCFLAGS += -fpatchable-function-entry=7,6
|
CONFIG_CCFLAGS += -fpatchable-function-entry=7,6
|
||||||
endif
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
TARGET_ARCH ?= $(CONFIG_TARGET_ARCH)
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
|
@ -53,23 +53,111 @@
|
||||||
# OVERRIDE_FOO set ~/.cosmo.mk and target-specific (use rarely)
|
# OVERRIDE_FOO set ~/.cosmo.mk and target-specific (use rarely)
|
||||||
#
|
#
|
||||||
|
|
||||||
|
LC_ALL = C
|
||||||
|
SOURCE_DATE_EPOCH = 0
|
||||||
|
|
||||||
|
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
|
||||||
|
GZIP = build/bootstrap/gzip.com
|
||||||
|
ECHO = build/bootstrap/echo.com
|
||||||
|
CHMOD = build/bootstrap/chmod.com
|
||||||
|
TOUCH = build/bootstrap/touch.com
|
||||||
|
PKG = build/bootstrap/package.com
|
||||||
|
MKDEPS = build/bootstrap/mkdeps.com
|
||||||
|
ZIPOBJ = build/bootstrap/zipobj.com
|
||||||
|
ZIPCOPY = build/bootstrap/zipcopy.com
|
||||||
|
FIXUPOBJ = build/bootstrap/fixupobj.com
|
||||||
|
MKDIR = build/bootstrap/mkdir.com -p
|
||||||
|
COMPILE = build/bootstrap/compile.com -V9 -P4096 $(QUOTA)
|
||||||
|
|
||||||
|
COMMA := ,
|
||||||
|
PWD := $(shell build/bootstrap/pwd.com)
|
||||||
|
|
||||||
|
IGNORE := $(shell $(ECHO) -2 ♥cosmo)
|
||||||
|
IGNORE := $(shell $(MKDIR) $(TMPDIR))
|
||||||
|
|
||||||
|
ifneq ($(findstring aarch64,$(MODE)),)
|
||||||
|
ARCH = aarch64
|
||||||
|
VM = o/third_party/qemu/qemu-aarch64
|
||||||
|
HOSTS ?= pi silicon
|
||||||
|
else
|
||||||
|
ARCH = x86_64
|
||||||
|
HOSTS ?= freebsd openbsd openbsd73 netbsd rhel7 rhel5 xnu win10
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(PREFIX),)
|
||||||
|
ifeq ($(USE_SYSTEM_TOOLCHAIN),)
|
||||||
|
ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-pc-linux-gnu-*)","")
|
||||||
|
PREFIX = o/third_party/gcc/bin/x86_64-pc-linux-gnu-
|
||||||
|
else
|
||||||
|
IGNORE := $(shell build/bootstrap/unbundle.com)
|
||||||
|
PREFIX = o/third_party/gcc/bin/x86_64-linux-musl-
|
||||||
|
endif
|
||||||
|
ifeq ($(ARCH), aarch64)
|
||||||
|
PREFIX = o/third_party/gcc/bin/aarch64-linux-musl-
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
AS = $(PREFIX)as
|
||||||
|
CC = $(PREFIX)gcc
|
||||||
|
CXX = $(PREFIX)g++
|
||||||
|
CXXFILT = $(PREFIX)c++filt
|
||||||
|
LD = $(PREFIX)ld.bfd
|
||||||
|
NM = $(PREFIX)nm
|
||||||
|
GCC = $(PREFIX)gcc
|
||||||
|
STRIP = $(PREFIX)strip
|
||||||
|
OBJCOPY = $(PREFIX)objcopy
|
||||||
|
OBJDUMP = $(PREFIX)objdump
|
||||||
|
ifneq ($(wildcard $(PWD)/$(PREFIX)addr2line), )
|
||||||
|
ADDR2LINE = $(PWD)/$(PREFIX)addr2line
|
||||||
|
else
|
||||||
|
ADDR2LINE = $(PREFIX)addr2line
|
||||||
|
endif
|
||||||
|
|
||||||
|
export ADDR2LINE
|
||||||
|
export LC_ALL
|
||||||
|
export MKDIR
|
||||||
|
export MODE
|
||||||
|
export SOURCE_DATE_EPOCH
|
||||||
|
export TMPDIR
|
||||||
|
|
||||||
ifeq ($(LANDLOCKMAKE_VERSION),)
|
ifeq ($(LANDLOCKMAKE_VERSION),)
|
||||||
TMPSAFE = $(join $(TMPDIR)/,$(subst /,_,$@)).tmp
|
TMPSAFE = $(join $(TMPDIR),$(subst /,_,$@)).tmp
|
||||||
else
|
else
|
||||||
TMPSAFE = $(TMPDIR)/
|
TMPSAFE = $(TMPDIR)/
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ARCH), aarch64)
|
||||||
|
IMAGE_BASE_VIRTUAL ?= 0x010000000000
|
||||||
|
else
|
||||||
|
IMAGE_BASE_VIRTUAL ?= 0x400000
|
||||||
|
endif
|
||||||
|
|
||||||
BACKTRACES = \
|
BACKTRACES = \
|
||||||
-fno-schedule-insns2 \
|
|
||||||
-fno-optimize-sibling-calls \
|
-fno-optimize-sibling-calls \
|
||||||
-mno-omit-leaf-frame-pointer
|
-mno-omit-leaf-frame-pointer
|
||||||
|
|
||||||
|
ifneq ($(ARCH), aarch64)
|
||||||
|
BACKTRACES += -fno-schedule-insns2
|
||||||
|
endif
|
||||||
|
|
||||||
|
SANITIZER = \
|
||||||
|
-fsanitize=address
|
||||||
|
|
||||||
NO_MAGIC = \
|
NO_MAGIC = \
|
||||||
-ffreestanding \
|
|
||||||
-fno-stack-protector \
|
-fno-stack-protector \
|
||||||
-fwrapv \
|
-fwrapv \
|
||||||
-fno-sanitize=all \
|
-fno-sanitize=all
|
||||||
-fpatchable-function-entry=0,0
|
|
||||||
|
|
||||||
OLD_CODE = \
|
OLD_CODE = \
|
||||||
-fno-strict-aliasing \
|
-fno-strict-aliasing \
|
||||||
|
@ -87,18 +175,18 @@ DEFAULT_CCFLAGS += \
|
||||||
-frecord-gcc-switches
|
-frecord-gcc-switches
|
||||||
|
|
||||||
DEFAULT_COPTS ?= \
|
DEFAULT_COPTS ?= \
|
||||||
|
-fno-math-errno \
|
||||||
-fno-ident \
|
-fno-ident \
|
||||||
-fno-common \
|
-fno-common \
|
||||||
-fno-gnu-unique \
|
-fno-gnu-unique \
|
||||||
-fstrict-aliasing \
|
-fstrict-aliasing \
|
||||||
-fstrict-overflow \
|
-fstrict-overflow \
|
||||||
-fno-semantic-interposition
|
-fno-semantic-interposition \
|
||||||
|
-fno-dwarf2-cfi-asm \
|
||||||
|
-fno-unwind-tables \
|
||||||
|
-fno-asynchronous-unwind-tables
|
||||||
|
|
||||||
ifeq ($(ARCH), x86_64)
|
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 += \
|
DEFAULT_COPTS += \
|
||||||
-mno-red-zone \
|
-mno-red-zone \
|
||||||
-mno-tls-direct-seg-refs
|
-mno-tls-direct-seg-refs
|
||||||
|
@ -115,7 +203,7 @@ ifeq ($(ARCH), aarch64)
|
||||||
DEFAULT_COPTS += \
|
DEFAULT_COPTS += \
|
||||||
-ffixed-x18 \
|
-ffixed-x18 \
|
||||||
-ffixed-x28 \
|
-ffixed-x28 \
|
||||||
-fsigned-char
|
-mno-outline-atomics
|
||||||
endif
|
endif
|
||||||
|
|
||||||
MATHEMATICAL = \
|
MATHEMATICAL = \
|
||||||
|
@ -123,24 +211,23 @@ MATHEMATICAL = \
|
||||||
-fwrapv
|
-fwrapv
|
||||||
|
|
||||||
DEFAULT_CPPFLAGS += \
|
DEFAULT_CPPFLAGS += \
|
||||||
-D_COSMO_SOURCE \
|
-DCOSMO \
|
||||||
-DMODE='"$(MODE)"' \
|
-DMODE='"$(MODE)"' \
|
||||||
-Wno-prio-ctor-dtor \
|
-DIMAGE_BASE_VIRTUAL=$(IMAGE_BASE_VIRTUAL) \
|
||||||
-Wno-unknown-pragmas \
|
|
||||||
-nostdinc \
|
-nostdinc \
|
||||||
-iquote. \
|
-iquote .
|
||||||
-isystem libc/isystem
|
|
||||||
|
|
||||||
DEFAULT_CFLAGS = \
|
DEFAULT_CFLAGS = \
|
||||||
-std=gnu23
|
-std=gnu2x
|
||||||
|
|
||||||
DEFAULT_CXXFLAGS = \
|
DEFAULT_CXXFLAGS = \
|
||||||
-std=gnu++23 \
|
-fno-rtti \
|
||||||
|
-fno-exceptions \
|
||||||
-fuse-cxa-atexit \
|
-fuse-cxa-atexit \
|
||||||
|
-fno-threadsafe-statics \
|
||||||
-Wno-int-in-bool-context \
|
-Wno-int-in-bool-context \
|
||||||
-Wno-narrowing \
|
-Wno-narrowing \
|
||||||
-Wno-literal-suffix \
|
-Wno-literal-suffix
|
||||||
-isystem third_party/libcxx
|
|
||||||
|
|
||||||
DEFAULT_ASFLAGS = \
|
DEFAULT_ASFLAGS = \
|
||||||
-W \
|
-W \
|
||||||
|
@ -152,7 +239,6 @@ DEFAULT_LDFLAGS = \
|
||||||
-nostdlib \
|
-nostdlib \
|
||||||
-znorelro \
|
-znorelro \
|
||||||
--gc-sections \
|
--gc-sections \
|
||||||
-z noexecstack \
|
|
||||||
--build-id=none \
|
--build-id=none \
|
||||||
--no-dynamic-linker
|
--no-dynamic-linker
|
||||||
|
|
||||||
|
@ -166,7 +252,7 @@ DEFAULT_LDFLAGS += \
|
||||||
-znorelro
|
-znorelro
|
||||||
else
|
else
|
||||||
DEFAULT_LDFLAGS += \
|
DEFAULT_LDFLAGS += \
|
||||||
-zmax-page-size=0x4000 \
|
-zmax-page-size=0x10000 \
|
||||||
-zcommon-page-size=0x1000
|
-zcommon-page-size=0x1000
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
@ -247,22 +333,30 @@ LD.libs = \
|
||||||
$(LIBS)
|
$(LIBS)
|
||||||
|
|
||||||
COMPILE.c.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(c.flags)
|
COMPILE.c.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(c.flags)
|
||||||
COMPILE.cxx.flags = $(cc.flags) $(copt.flags) $(cxx.flags) $(cpp.flags)
|
COMPILE.cxx.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(cxx.flags)
|
||||||
|
COMPILE.f.flags = $(cc.flags) $(copt.flags) $(f.flags)
|
||||||
|
COMPILE.F.flags = $(cc.flags) $(copt.flags) $(cpp.flags) $(f.flags)
|
||||||
COMPILE.i.flags = $(cc.flags) $(copt.flags) $(c.flags)
|
COMPILE.i.flags = $(cc.flags) $(copt.flags) $(c.flags)
|
||||||
COMPILE.ii.flags = $(cc.flags) $(copt.flags) $(cxx.flags)
|
COMPILE.ii.flags = $(cc.flags) $(copt.flags) $(cxx.flags)
|
||||||
LINK.flags = $(DEFAULT_LDFLAGS) $(CONFIG_LDFLAGS) $(LDFLAGS)
|
LINK.flags = $(DEFAULT_LDFLAGS) $(CONFIG_LDFLAGS) $(LDFLAGS)
|
||||||
OBJECTIFY.c.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(c.flags)
|
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.cxx.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(cxx.flags)
|
||||||
OBJECTIFY.s.flags = $(ASONLYFLAGS) $(s.flags)
|
OBJECTIFY.s.flags = $(ASONLYFLAGS) $(s.flags)
|
||||||
OBJECTIFY.S.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags)
|
OBJECTIFY.S.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags)
|
||||||
|
OBJECTIFY.f.flags = $(cc.flags) $(o.flags) $(S.flags) $(f.flags)
|
||||||
|
OBJECTIFY.F.flags = $(cc.flags) $(o.flags) $(S.flags) $(cpp.flags) $(copt.flags) $(f.flags)
|
||||||
PREPROCESS.flags = -E $(copt.flags) $(cc.flags) $(cpp.flags)
|
PREPROCESS.flags = -E $(copt.flags) $(cc.flags) $(cpp.flags)
|
||||||
PREPROCESS.lds.flags = -D__LINKER__ $(filter-out -g%,$(PREPROCESS.flags)) -P -xc
|
PREPROCESS.lds.flags = -D__LINKER__ $(filter-out -g%,$(PREPROCESS.flags)) -P -xc
|
||||||
|
|
||||||
COMPILE.c = $(CC) -S $(COMPILE.c.flags)
|
COMPILE.c = $(CC) -S $(COMPILE.c.flags)
|
||||||
COMPILE.cxx = $(CXX) -S $(COMPILE.cxx.flags)
|
COMPILE.cxx = $(CXX) -S $(COMPILE.cxx.flags)
|
||||||
COMPILE.i = $(CC) -S $(COMPILE.i.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 = $(AS) $(OBJECTIFY.s.flags)
|
||||||
OBJECTIFY.S = $(CC) $(OBJECTIFY.S.flags) -c
|
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.c = $(CC) $(OBJECTIFY.c.flags) -c
|
||||||
OBJECTIFY.cxx = $(CXX) $(OBJECTIFY.cxx.flags) -c
|
OBJECTIFY.cxx = $(CXX) $(OBJECTIFY.cxx.flags) -c
|
||||||
PREPROCESS = $(CC) $(PREPROCESS.flags)
|
PREPROCESS = $(CC) $(PREPROCESS.flags)
|
||||||
|
@ -271,6 +365,7 @@ LINK = $(LD) $(LINK.flags)
|
||||||
ELF = o/libc/elf/elf.lds
|
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) && $(COMPILE) -AFIXUP.ape -T$@ $(FIXUPOBJ) $@
|
||||||
LINKARGS = $(patsubst %.lds,-T %.lds,$(call uniqr,$(LD.libs) $(filter-out %.pkg,$^)))
|
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,
|
# 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
|
# which is needed for C modules wanting to run at the executive level or
|
||||||
|
@ -288,6 +383,68 @@ OBJECTIFY.greg.c = \
|
||||||
-fwrapv \
|
-fwrapv \
|
||||||
-c
|
-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 \
|
||||||
|
-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) \
|
||||||
|
-fno-stack-protector \
|
||||||
|
-fno-instrument-functions \
|
||||||
|
-fno-optimize-sibling-calls \
|
||||||
|
-fno-sanitize=all \
|
||||||
|
-fcall-saved-rdi \
|
||||||
|
-fcall-saved-rsi \
|
||||||
|
-c
|
||||||
|
|
||||||
TAGSFLAGS = \
|
TAGSFLAGS = \
|
||||||
-e \
|
-e \
|
||||||
-a \
|
-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-*-┐
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
#-*-mode:sh;indent-tabs-mode:nil;tab-width:2;coding:utf-8-*-┐
|
#-*-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
|
# OVERVIEW
|
||||||
#
|
#
|
||||||
|
@ -55,7 +55,7 @@ set -- --regex-c='/_Atomic(\([^)]*\))/\1/b' "$@"
|
||||||
set -- --regex-c='/^\(\(hidden\|extern\|const\) \)*[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)/\4/b' "$@"
|
set -- --regex-c='/^\(\(hidden\|extern\|const\) \)*[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)/\4/b' "$@"
|
||||||
|
|
||||||
# ctags doesn't understand function prototypes, e.g.
|
# 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' "$@"
|
set -- --regex-c='/^[_[:alpha:]][_[:alnum:]]*[ *][ *]*\([_[:alpha:]][_[:alnum:]]*[ *][ *]*\)*\([_[:alpha:]][_$[:alnum:]]*\)(.*/\2/b' "$@"
|
||||||
|
|
||||||
# ctags doesn't understand function pointers, e.g.
|
# ctags doesn't understand function pointers, e.g.
|
||||||
|
@ -66,7 +66,7 @@ set -- --regex-c='/^extern [^(]*(\*const \([^)]*\))(/\1/b' "$@"
|
||||||
# struct WorstSoftwareEver;
|
# struct WorstSoftwareEver;
|
||||||
set -- --regex-c='/^struct.*;$/uehocruehcroue/b' "$@"
|
set -- --regex-c='/^struct.*;$/uehocruehcroue/b' "$@"
|
||||||
|
|
||||||
build/run $TAGS \
|
exec $TAGS \
|
||||||
-e \
|
-e \
|
||||||
--langmap=c:.c.h \
|
--langmap=c:.c.h \
|
||||||
--exclude=libc/nt/struct/imagefileheader.internal.h \
|
--exclude=libc/nt/struct/imagefileheader.internal.h \
|
||||||
|
|
|
@ -1,29 +1,6 @@
|
||||||
#!/bin/sh
|
#!/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
|
if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then
|
||||||
find_objdump aarch64
|
exec o/third_party/gcc/bin/aarch64-linux-musl-objdump "$@"
|
||||||
exec "$OBJDUMP" "$@"
|
|
||||||
else
|
else
|
||||||
find_objdump x86_64
|
exec o/third_party/gcc/bin/x86_64-linux-musl-objdump "$@"
|
||||||
exec "$OBJDUMP" "$@"
|
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
|
@ -22,14 +22,10 @@
|
||||||
# - tool/build/runit.c
|
# - tool/build/runit.c
|
||||||
# - tool/build/runitd.c
|
# - tool/build/runitd.c
|
||||||
|
|
||||||
.PRECIOUS: o/$(MODE)/%.ok
|
.PRECIOUS: o/$(MODE)/%.com.ok
|
||||||
o/$(MODE)/%.ok: private .PLEDGE = stdio rpath wpath cpath proc fattr inet dns
|
o/$(MODE)/%.com.ok: private .PLEDGE = stdio rpath wpath cpath proc fattr inet
|
||||||
o/$(MODE)/%.ok: private .UNVEIL += r:/etc/resolv.conf
|
o/$(MODE)/%.com.ok: \
|
||||||
o/$(MODE)/%.ok: \
|
o//tool/build/runit.com \
|
||||||
o/$(MODE)/tool/build/runit \
|
o//tool/build/runitd.com \
|
||||||
o/$(MODE)/tool/build/runitd \
|
o/$(MODE)/%.com
|
||||||
o/$(MODE)/%
|
|
||||||
@$(COMPILE) -wATEST -tT$@ $^ $(HOSTS)
|
@$(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-*-┐
|
#-*-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
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
|
|
124
build/rules.mk
124
build/rules.mk
|
@ -1,5 +1,5 @@
|
||||||
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
#-*-mode:makefile-gmake;indent-tabs-mode:t;tab-width:8;coding:utf-8-*-┐
|
||||||
#── vi: set et ft=make ts=8 sw=8 fenc=utf-8 :vi ──────────────────────┘
|
#───vi: set et ft=make ts=8 tw=8 fenc=utf-8 :vi───────────────────────┘
|
||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
|
@ -23,8 +23,50 @@ else
|
||||||
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S $< $@ && $(MAKE_ZIPCOPY)
|
MAKE_OBJCOPY = $(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -S $< $@ && $(MAKE_ZIPCOPY)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
o/$(MODE)/%: o/$(MODE)/%.dbg
|
o/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(OUTPUT_OPTION) $<
|
||||||
@$(MAKE_OBJCOPY)
|
o/%.inc: %.h ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) -D__ASSEMBLER__ -P $<
|
||||||
|
o/$(MODE)/%: o/$(MODE)/%.dbg ; @$(MAKE_OBJCOPY)
|
||||||
|
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: %.cc ; @$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||||
|
o/$(MODE)/%.lds: %.lds ; @$(COMPILE) -APREPROCESS $(PREPROCESS.lds) $(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) $<
|
||||||
|
|
||||||
|
ifneq ($(ARCH), aarch64)
|
||||||
|
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/$(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: %.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||||
|
o/$(MODE)/%.o: o/$(MODE)/%.S ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) $<
|
||||||
|
else
|
||||||
|
o/%.o: %.s libc/empty.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) libc/empty.s
|
||||||
|
o/%.o: o/%.s libc/empty.s ; @$(COMPILE) -AOBJECTIFY.s $(OBJECTIFY.s) $(OUTPUT_OPTION) libc/empty.s
|
||||||
|
o/%.s: %.S libc/empty.s ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) libc/empty.s
|
||||||
|
o/%.s: o/%.S libc/empty.s ; @$(COMPILE) -APREPROCESS $(PREPROCESS) $(OUTPUT_OPTION) libc/empty.s
|
||||||
|
o/%.o: %.S libc/empty.s ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.s) $(OUTPUT_OPTION) libc/empty.s
|
||||||
|
o/%.o: o/%.S libc/empty.s ; @$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.s) $(OUTPUT_OPTION) libc/empty.s
|
||||||
|
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
|
||||||
|
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/%.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
|
o/$(MODE)/%.o: %.c
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||||
|
@ -34,30 +76,13 @@ o/$(MODE)/%.o: o/$(MODE)/%.c
|
||||||
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
@$(COMPILE) -AOBJECTIFY.c $(OBJECTIFY.c) $(OUTPUT_OPTION) $<
|
||||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||||
|
|
||||||
o/$(MODE)/%.h: %.c
|
o/$(MODE)/%.o: o/$(MODE)/%.cc
|
||||||
@$(COMPILE) -AAMALGAMATE $(PREPROCESS) $(OUTPUT_OPTION) -fdirectives-only -P $<
|
|
||||||
|
|
||||||
o/$(MODE)/%.o: %.cc
|
|
||||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
||||||
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||||
|
|
||||||
o/$(MODE)/%.o: %.cpp
|
o/%.greg.o: %.greg.c
|
||||||
@$(COMPILE) -AOBJECTIFY.cxx $(OBJECTIFY.cxx) $(OUTPUT_OPTION) $<
|
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||||
|
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@
|
||||||
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
|
o/$(MODE)/%.o: %.greg.c
|
||||||
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
@$(COMPILE) -AOBJECTIFY.greg $(OBJECTIFY.greg.c) $(OUTPUT_OPTION) $<
|
||||||
|
@ -79,17 +104,17 @@ o/$(MODE)/%.pkg:
|
||||||
$(file >$(TMPSAFE).args,$(filter %.o,$^))
|
$(file >$(TMPSAFE).args,$(filter %.o,$^))
|
||||||
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
|
@$(COMPILE) -APACKAGE -wT$@ $(PKG) $(OUTPUT_OPTION) $(addprefix -d,$(filter %.pkg,$^)) @$(TMPSAFE).args
|
||||||
|
|
||||||
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj
|
o/$(MODE)/%.o: %.py o/$(MODE)/third_party/python/pyobj.com $(VM)
|
||||||
@$(COMPILE) -wAPYOBJ o/$(MODE)/third_party/python/pyobj $(PYFLAGS) -o $@ $<
|
@$(COMPILE) -wAPYOBJ $(VM) o/$(MODE)/third_party/python/pyobj.com $(PYFLAGS) -o $@ $<
|
||||||
|
|
||||||
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp
|
o/$(MODE)/%.pyc: %.py o/$(MODE)/third_party/python/pycomp.com $(VM)
|
||||||
@$(COMPILE) -wAPYCOMP o/$(MODE)/third_party/python/pycomp $(PYCFLAGS) -o $@ $<
|
@$(COMPILE) -wAPYCOMP $(VM) o/$(MODE)/third_party/python/pycomp.com $(PYCFLAGS) -o $@ $<
|
||||||
|
|
||||||
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac
|
o/$(MODE)/%.lua: %.lua o/$(MODE)/third_party/lua/luac.com $(VM)
|
||||||
@$(COMPILE) -wALUAC o/$(MODE)/third_party/lua/luac -s -o $@ $<
|
@$(COMPILE) -wALUAC $(VM) o/$(MODE)/third_party/lua/luac.com -s -o $@ $<
|
||||||
|
|
||||||
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean
|
o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean.com $(VM)
|
||||||
@$(COMPILE) -wALUA -tT$@ o/$(MODE)/tool/net/redbean $(LUAFLAGS) -i $<
|
@$(COMPILE) -wALUA -tT$@ $(VM) o/$(MODE)/tool/net/redbean.com $(LUAFLAGS) -i $<
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# LOCAL UNIT TESTS
|
# LOCAL UNIT TESTS
|
||||||
|
@ -108,34 +133,34 @@ o/$(MODE)/%.lua.runs: %.lua o/$(MODE)/tool/net/redbean
|
||||||
#
|
#
|
||||||
# You could then run a command like:
|
# You could then run a command like:
|
||||||
#
|
#
|
||||||
# make -j8 o//test/libc/calls/openbsd_test.runs
|
# make -j8 o//test/libc/calls/openbsd_test.com.runs
|
||||||
#
|
#
|
||||||
# You need PROT_EXEC permission since ftrace morphs the binary. It's
|
# You need PROT_EXEC permission since ftrace morphs the binary. It's
|
||||||
# also worth mentioning that the pledge command can simulate what
|
# also worth mentioning that the pledge.com command can simulate what
|
||||||
# Landlock Make does:
|
# Landlock Make does:
|
||||||
#
|
#
|
||||||
# o//tool/build/pledge \
|
# o//tool/build/pledge.com \
|
||||||
# -v. -p 'stdio rpath wpath cpath tty prot_exec' \
|
# -v. -p 'stdio rpath wpath cpath tty prot_exec' \
|
||||||
# o//test/libc/calls/openbsd_test \
|
# o//test/libc/calls/openbsd_test.com \
|
||||||
# ----ftrace
|
# ----ftrace
|
||||||
#
|
#
|
||||||
# This is useful in the event a test binary should run by itself, but
|
# 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
|
# fails to run beneath Landlock Make. It's also useful sometimes to
|
||||||
# override the verbosity when running tests:
|
# override the verbosity when running tests:
|
||||||
#
|
#
|
||||||
# make V=5 TESTARGS=-b o//test/libc/calls/openbsd_test.runs
|
# make V=5 TESTARGS=-b o//test/libc/calls/openbsd_test.com.runs
|
||||||
#
|
#
|
||||||
# This way, if for some reason a test should fail but calls exit(0),
|
# This way, if for some reason a test should fail but calls exit(0),
|
||||||
# then the stdout/stderr output, which would normally be suppressed,
|
# then the stdout/stderr output, which would normally be suppressed,
|
||||||
# will actually be displayed.
|
# will actually be displayed.
|
||||||
|
|
||||||
o/$(MODE)/%.runs: o/$(MODE)/%
|
o/$(MODE)/%.runs: o/$(MODE)/% $(VM)
|
||||||
@$(COMPILE) -ACHECK -wtT$@ $< $(TESTARGS)
|
@$(COMPILE) -ACHECK -wtT$@ $(VM) $< $(TESTARGS)
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# ELF ZIP FILES
|
# ELF ZIP FILES
|
||||||
#
|
#
|
||||||
# zipobj lets us do fast incremental linking of compressed data.
|
# zipobj.com lets us do fast incremental linking of compressed data.
|
||||||
# it's nice because if we link a hundred binaries that use the time zone
|
# 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.
|
# database, then that database only needs to be DEFLATE'd once.
|
||||||
|
|
||||||
|
@ -183,6 +208,25 @@ o/$(MODE)/%.okk: private .UNSANDBOXED = 1
|
||||||
o/$(MODE)/%.okk: %
|
o/$(MODE)/%.okk: %
|
||||||
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
@$(COMPILE) -ACHECK.h $(COMPILE.cxx) -xc++ -g0 -o $@ $<
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# EXECUTABLE HELPERS
|
||||||
|
|
||||||
|
MAKE_SYMTAB_CREATE = \
|
||||||
|
$(COMPILE) -wASYMTAB \
|
||||||
|
$(VM) \
|
||||||
|
o/$(MODE)/tool/build/symtab.com \
|
||||||
|
-o $(TMPSAFE)/.symtab \
|
||||||
|
$<
|
||||||
|
|
||||||
|
MAKE_SYMTAB_ZIP = \
|
||||||
|
$(COMPILE) -AZIP -T$@ \
|
||||||
|
$(VM) \
|
||||||
|
o/$(MODE)/third_party/zip/zip.com \
|
||||||
|
-b$(TMPDIR) \
|
||||||
|
-9qj \
|
||||||
|
$@ \
|
||||||
|
$(TMPSAFE)/.symtab
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# EMACS ASSEMBLY GENERATION
|
# EMACS ASSEMBLY GENERATION
|
||||||
|
|
||||||
|
|
13
build/run
13
build/run
|
@ -1,8 +1,9 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
UNAMEM=$(uname -m)
|
if printf '%s\n' "$*" | grep aarch64 >/dev/null 2>&1; then
|
||||||
UNAMES=$(uname -s)
|
if [ ! -f o/third_party/qemu/qemu-aarch64 ]; then
|
||||||
if [ x"$UNAMES" = x"Darwin" ] && [ x"$UNAMEM" = x"arm64" ]; then
|
make -j8 o/third_party/qemu/qemu-aarch64
|
||||||
exec ape "$@"
|
fi
|
||||||
else
|
exec o/third_party/qemu/qemu-aarch64 "$@"
|
||||||
exec rusage "$@"
|
else
|
||||||
|
exec "$@"
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -31,7 +31,7 @@ if [ ! -f /proc/sys/fs/binfmt_misc/status ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! build/bootstrap/echo -n; then
|
if ! build/bootstrap/echo.com -n; then
|
||||||
cat <<'EOF' >&2
|
cat <<'EOF' >&2
|
||||||
|
|
||||||
ERROR
|
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_
|
|
|
@ -1,39 +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_DISTANCE_H_
|
|
||||||
#define CTL_DISTANCE_H_
|
|
||||||
#include "iterator.h"
|
|
||||||
#include "iterator_traits.h"
|
|
||||||
|
|
||||||
namespace ctl {
|
|
||||||
|
|
||||||
template<class InputIter>
|
|
||||||
constexpr typename ctl::iterator_traits<InputIter>::difference_type
|
|
||||||
distance_impl(InputIter first, InputIter last, input_iterator_tag)
|
|
||||||
{
|
|
||||||
typename ctl::iterator_traits<InputIter>::difference_type res(0);
|
|
||||||
for (; first != last; ++first)
|
|
||||||
++res;
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class RandIter>
|
|
||||||
constexpr typename ctl::iterator_traits<RandIter>::difference_type
|
|
||||||
distance_impl(RandIter first, RandIter last, random_access_iterator_tag)
|
|
||||||
{
|
|
||||||
return last - first;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class InputIter>
|
|
||||||
constexpr typename ctl::iterator_traits<InputIter>::difference_type
|
|
||||||
distance(InputIter first, InputIter last)
|
|
||||||
{
|
|
||||||
return distance_impl(
|
|
||||||
first,
|
|
||||||
last,
|
|
||||||
typename ctl::iterator_traits<InputIter>::iterator_category());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace ctl
|
|
||||||
|
|
||||||
#endif // CTL_DISTANCE_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