Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 89a4aa8a05 | |||
| 26595f1624 | |||
| 9774052fd1 | |||
| 620184ab6d | |||
| 9196d01417 | |||
| 36f95af890 | |||
| 86c27653ed | |||
| 5907c14c4e | |||
| 4b683014c9 | |||
| 3bc71a8161 | |||
| 72a916318b | |||
| f21d523529 | |||
| 1232fb742a | |||
| 11569da01e | |||
| 1268238ac0 | |||
| 9e625ef20f | |||
| 3399e18693 | |||
| dfd687e3cf | |||
| d00a02c791 | |||
| 83a5c11e21 | |||
| 6caad3a538 | |||
| a725e6ac8c | |||
| a31138efe9 | |||
| 4eabdf2016 | |||
| 826a984fdb | |||
| 08cf1e6e0a | |||
| 2f320c1ea0 | |||
| bae5afa1b4 | |||
| ae99d15bfa | |||
| e25fd20708 | |||
| 0c5f21d297 | |||
| 2ae6ef9a67 | |||
| ba2e6555af | |||
| c1b8c3b4cf | |||
| 4e40dc538c | |||
| fc8f0ec4fd | |||
| f00e969b82 | |||
| 3cb57fbc7f | |||
| a500cd9e6c | |||
| 32e402087f | |||
| 2cd334a1f9 | |||
| ae6549251b | |||
| 31ee8b3bf9 | |||
| a2e4cd27fe | |||
| d28963d88e | |||
| 047e7c09da | |||
| 1b3e94a20d |
@@ -1,2 +0,0 @@
|
|||||||
[unstable]
|
|
||||||
json-target-spec = true
|
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[**.c]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[**.yml]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
+11
-6
@@ -1,6 +1,11 @@
|
|||||||
target
|
.idea/
|
||||||
/config.toml
|
prefix/
|
||||||
.gitlab-ci-local/
|
sysroot/
|
||||||
kernel
|
**/target/
|
||||||
kernel.all
|
.gdb_history
|
||||||
kernel.sym
|
*.patch
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
/.vim
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
|||||||
+58
-75
@@ -5,86 +5,69 @@ variables:
|
|||||||
|
|
||||||
workflow:
|
workflow:
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_PROJECT_NAMESPACE == "redox-os"'
|
- if: '$CI_COMMIT_BRANCH == "master" && $CI_PROJECT_NAMESPACE == "redox-os"'
|
||||||
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
|
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
|
||||||
|
|
||||||
stages:
|
stages:
|
||||||
- build
|
- build
|
||||||
- cross-build
|
- cross-build
|
||||||
- test
|
- test
|
||||||
- other-features
|
before_script:
|
||||||
# TODO: benchmarks and profiling (maybe manually enabled for relevant MRs)?
|
cargo install cbindgen
|
||||||
|
|
||||||
x86_64:
|
|
||||||
stage: build
|
|
||||||
script:
|
|
||||||
- mkdir -p target/${ARCH}
|
|
||||||
- redoxer env make BUILD=target/${ARCH}
|
|
||||||
variables:
|
|
||||||
ARCH: "x86_64"
|
|
||||||
|
|
||||||
aarch64:
|
|
||||||
stage: cross-build
|
|
||||||
image: "redoxos/redoxer:aarch64"
|
|
||||||
script:
|
|
||||||
- mkdir -p target/${ARCH}
|
|
||||||
- redoxer env make BUILD=target/${ARCH}
|
|
||||||
variables:
|
|
||||||
ARCH: "aarch64"
|
|
||||||
|
|
||||||
i586:
|
|
||||||
stage: cross-build
|
|
||||||
script:
|
|
||||||
- mkdir -p target/${ARCH}
|
|
||||||
- TARGET=${ARCH}-unknown-redox redoxer env make BUILD=target/${ARCH}
|
|
||||||
variables:
|
|
||||||
ARCH: "i586"
|
|
||||||
|
|
||||||
riscv64gc:
|
|
||||||
stage: cross-build
|
|
||||||
script:
|
|
||||||
- mkdir -p target/${ARCH}
|
|
||||||
- TARGET=${ARCH}-unknown-redox redoxer env make BUILD=target/${ARCH}
|
|
||||||
variables:
|
|
||||||
ARCH: "riscv64gc"
|
|
||||||
|
|
||||||
fmt:
|
fmt:
|
||||||
stage: build
|
stage: build
|
||||||
script:
|
needs: []
|
||||||
- rustup component add rustfmt
|
script:
|
||||||
- rustfmt --check
|
- rustup component add rustfmt-preview
|
||||||
|
- ./fmt.sh -- --check
|
||||||
|
|
||||||
x86_64:boot:
|
linux:
|
||||||
stage: test
|
stage: build
|
||||||
needs: [x86_64]
|
script:
|
||||||
script:
|
- ./check.sh --host
|
||||||
- mkdir -p target/${ARCH}
|
|
||||||
- export COOKBOOK_SOURCE_IDENT=$CI_COMMIT_SHA
|
|
||||||
- redoxer env make BUILD=target/${ARCH}
|
|
||||||
- timeout -s KILL 9m redoxer exec --folder target/${ARCH}/:/usr/lib/boot uname -a
|
|
||||||
variables:
|
|
||||||
ARCH: "x86_64"
|
|
||||||
|
|
||||||
x86_64:relibc:
|
x86_64:
|
||||||
stage: test
|
stage: build
|
||||||
needs: [x86_64]
|
script:
|
||||||
script:
|
- ./check.sh --arch=x86_64
|
||||||
- redoxer pkg relibc-tests-bins
|
|
||||||
- export COOKBOOK_SOURCE_IDENT=$CI_COMMIT_SHA
|
|
||||||
- mkdir -p target/${TARGET}/sysroot/{usr/lib/boot,root} target/${TARGET}/root
|
|
||||||
- redoxer env make BUILD=target/${TARGET}/sysroot/usr/lib/boot
|
|
||||||
- (cd target/${TARGET}/sysroot && mv home/user/relibc-tests/* root/)
|
|
||||||
- timeout -s KILL 9m redoxer exec --folder target/${TARGET}/sysroot/:/ make run
|
|
||||||
# It is fine if failing sometimes
|
|
||||||
allow_failure: true
|
|
||||||
variables:
|
|
||||||
TARGET: "x86_64-unknown-redox"
|
|
||||||
|
|
||||||
profiling-compile:
|
i586:
|
||||||
stage: other-features
|
stage: cross-build
|
||||||
allow_failure: true
|
script:
|
||||||
script:
|
- ./check.sh --arch=i586
|
||||||
make check
|
|
||||||
variables:
|
aarch64:
|
||||||
ARCH: "x86_64"
|
stage: cross-build
|
||||||
KERNEL_CHECK_FEATURES: profiling
|
image: "redoxos/redoxer:aarch64"
|
||||||
|
script:
|
||||||
|
- ./check.sh --arch=aarch64
|
||||||
|
|
||||||
|
riscv64gc:
|
||||||
|
stage: cross-build
|
||||||
|
script:
|
||||||
|
- ./check.sh --arch=riscv64gc
|
||||||
|
|
||||||
|
test:linux:
|
||||||
|
stage: test
|
||||||
|
needs: [linux]
|
||||||
|
script:
|
||||||
|
- ./check.sh --host --test
|
||||||
|
|
||||||
|
test:x86_64:
|
||||||
|
stage: test
|
||||||
|
needs: [x86_64]
|
||||||
|
script:
|
||||||
|
# timeout: https://gitlab.redox-os.org/redox-os/relibc/-/issues/238
|
||||||
|
- timeout -s KILL 9m ./check.sh --arch=x86_64 --test
|
||||||
|
|
||||||
|
test:aarch64:
|
||||||
|
stage: test
|
||||||
|
needs: [aarch64]
|
||||||
|
image: "redoxos/redoxer:aarch64"
|
||||||
|
# many issues that not exist in x86_64, and lack of interest to fix so far
|
||||||
|
allow_failure: true
|
||||||
|
script:
|
||||||
|
- timeout -s KILL 9m ./check.sh --arch=aarch64 --test
|
||||||
|
|
||||||
|
#TODO: Enable more arch once dynamic linker working
|
||||||
|
|||||||
+7
-4
@@ -1,4 +1,7 @@
|
|||||||
[submodule "redox-path"]
|
[submodule "openlibm"]
|
||||||
path = redox-path
|
path = openlibm
|
||||||
url = https://gitlab.redox-os.org/redox-os/redox-path.git
|
url = https://gitlab.redox-os.org/redox-os/openlibm.git
|
||||||
branch = main
|
branch = master
|
||||||
|
[submodule "src/dlmalloc-rs"]
|
||||||
|
path = dlmalloc-rs
|
||||||
|
url = https://gitlab.redox-os.org/redox-os/dlmalloc-rs.git
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
[editor]
|
|
||||||
auto-format = false
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
[[language]]
|
|
||||||
name = "rust"
|
|
||||||
|
|
||||||
[[language-server.rust-analyzer.config.cargo]]
|
|
||||||
extraEnv = ["RUST_TARGET_PATH=targets"]
|
|
||||||
# Select one of targets to make lsp work for your confguration
|
|
||||||
# Do not commit this change
|
|
||||||
# TODO: find a better way to do this
|
|
||||||
# target = "aarch64-unknown-kernel"
|
|
||||||
|
|
||||||
[[language-server.rust-analyzer.config.check]]
|
|
||||||
targets = ["x86_64-unknown-kernel", "i686-unknown-kernel", "aarch64-unknown-kernel"]
|
|
||||||
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
# Porting the core Redox kernel to arm AArch64: An outline
|
|
||||||
|
|
||||||
## Intro
|
|
||||||
|
|
||||||
This document is [my](https://github.com/raw-bin) attempt at:
|
|
||||||
|
|
||||||
* Capturing thinking on the work needed for a core Redox kernel port
|
|
||||||
* Sharing progress with the community as things evolve
|
|
||||||
* Creating a template that can be used for ports to other architectures
|
|
||||||
|
|
||||||
Core Redox kernel means everything needed to get to a non-graphical console-only multi-user shell.
|
|
||||||
|
|
||||||
Only the 64-bit execution state (AArch64) with the 64-bit instruction set architecture (A64) shall be supported for the moment. For more background/context read [this](https://developer.arm.com/products/architecture/a-profile/docs/den0024/latest/introduction).
|
|
||||||
|
|
||||||
This document is intended to be kept *live*. It will be updated to reflect the current state of work and any feedback received.
|
|
||||||
|
|
||||||
It is hard~futile to come up with a strict sequence of work for such ports but this document is a reasonable template to follow.
|
|
||||||
|
|
||||||
## Intended target platform
|
|
||||||
|
|
||||||
The primary focus is on [qemu's virt machine platform emulation for the AArch64 architecture](https://github.com/qemu/qemu/blob/master/hw/arm/virt.c#L127).
|
|
||||||
|
|
||||||
Targeting a virtual platform is a convenient way to bring up the mechanics of architectural support and makes the jump to silicon easier. The preferred boot chain for AArch64 (explained later) is well supported on this platform and boot-over-tftp from localhost makes the debug cycle very efficient.
|
|
||||||
|
|
||||||
Once the core kernel port is complete a similar follow on document will be created that is dedicated to silicon bring-up.
|
|
||||||
|
|
||||||
## Boot protocol elements
|
|
||||||
|
|
||||||
| Item | Notes |
|
|
||||||
|------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| [Linux kernel boot protocol for AArch64](https://www.kernel.org/doc/Documentation/arm64/booting.txt) | The linked document describes assumptions made from the bootloader which are field tested and worthwhile to have for Redox an AArch64. <br/> The intent is to consider most of the document except anything tied to the Linux kernel itself. |
|
|
||||||
| [Flattened Device Tree](https://elinux.org/Device_Tree_Reference) | FDT binary blobs supplied by the bootloader shall provide the Redox kernel with misc platform \{memory, interrupt, devicemem} maps. Qemu's virt machine platform synthetically creates an FDT blob at a specific address which is very handy. |
|
|
||||||
|
|
||||||
## Boot flow elements
|
|
||||||
|
|
||||||
The following table lists the boot flow in order.
|
|
||||||
|
|
||||||
| Item | Notes |
|
|
||||||
|-------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| [ARM Trusted Firmware (TF-A)](https://github.com/ARM-software/arm-trusted-firmware) | TF-A is a de-facto standard reference firmware implementation and proven in the field. <br/> TF-A runs post power-on on Armv8-A implementations and eventually hands off to further stages of the boot flow.<br />For qemu's virt machine platform, it is essentially absent but I mean to rely on it heavily for silicon bring up hence mentioning it here. |
|
|
||||||
| [u-boot](https://www.denx.de/wiki/U-Boot) | u-boot will handle early console access, media access for fetching redox kernel images from non-volatile storage/misc disk subsystems/off the network. <br /> u-boot supports loading EFI applications. If EFI support to AArch64 Redox is added in the future that should essentially work out of the box. <br /> u-boot will load redox and FDT binary blobs into RAM and jump to the redox kernel. |
|
|
||||||
| Redox early-init stub | For AArch64, the redox kernel will contain an A64 assembly stub that will setup the MMU from scratch. This is akin to the [x86_64 redox bootloader](https://github.com/redox-os/bootloader/blob/master/x86_64/startup-x86_64.asm). <br /> This stub sets up identity maps for MMU initialization, maps the kernel image itself as well as the device memory for the UART console. At present this stub shall be a part of the kernel itself for simplicity. |
|
|
||||||
| Redox kstart entry | The early init stub hands off here. kstart will then re-init the MMU more comprehensively. |
|
|
||||||
|
|
||||||
## Supported devices
|
|
||||||
|
|
||||||
The following devices shall be supported. All necessary information specific to these devices will be provided to the redox kernel by the platform specific FDT binary blob.
|
|
||||||
|
|
||||||
| Device | Notes |
|
|
||||||
|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
||||||
| [Generic Interrupt Controller v2](https://developer.arm.com/products/architecture/a-profile/docs/ihi0048/b/arm-generic-interrupt-controller-architecture-version-20-architecture-specification) | The GIC is an Arm-v8A architectural element and is supported by all architecturally compliant processor implementations. GICv2 is supported by qemu's virt machine emulation and most subsequent GIC implementations are backward compatible to GICv2. |
|
|
||||||
| [Generic Timer](http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0500d/BGBBIJCB.html) | The Generic Timer Architecture is an Arm-v8A architectural element and is implemented by all compliant processor implementations. It is supported by qemu. |
|
|
||||||
| [PrimeCell UART PL011](http://infocenter.arm.com/help/topic/com.arm.doc.ddi0183f/DDI0183.pdf) | The PL011 UART is supported by qemu and most ARM systems. |
|
|
||||||
|
|
||||||
## Intended development sequence and status
|
|
||||||
|
|
||||||
| Item | Description | Status | Notes |
|
|
||||||
|--------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------|-------------------------------------------------------------------------------|
|
|
||||||
| Redox AArch64 toolchain | Create an usable redox AArch64 toolchain specification | Done | Using this JSON spec in isolated tests produces valid AArch64 soft float code |
|
|
||||||
| Stubbed kernel image | Stub out AArch64 kernel support using the existing x86_64 arch code as a template <br /> Modify redox kernel build glue and work iteratively to get a linkable (non-functional) image | Not done yet | |
|
|
||||||
| Boot flow | Create a self hosted u-boot -> redox kernel workflow <br /> Should obtain the stubbed image from a local TFTP server, load it into RAM and jump to it | Not done yet | |
|
|
||||||
| GDB Debug flow | Create a debug workflow centered around qemu's GDB stub <br /> This should allow connecting to qemu's GDB stub and debug u-boot/redox stub via a GDB client and single stepping through code | Not done yet | |
|
|
||||||
| Verify Redox entry | Verify that control reaches the redox kernel from u-boot | Not done yet | |
|
|
||||||
| AArch64 early init stub | Add support for raw asm code for early AArch64 init in the redox kernel <br /> Verify that this code is located appropriately in the link map and that control reaches this code from u-boot | Not done yet | |
|
|
||||||
| Basic DTB support | Integrate the [device_tree crate](https://mbr.github.io/device_tree-rs/device_tree/) <br /> Use the crate to access the qemu supplied DTB image and extract the memory map | Not done yet | |
|
|
||||||
| Basic UART support | Use the device_tree crate to get the UART address from the DTB image and set up the initial console <br /> This is a polling mode only setup | Not done yet | |
|
|
||||||
| Initial MMU support | Implement initial MMU support in the early init stub <br /> This forces the MMU into a clean state overriding any bootloader specific setup <br /> Create an identity map for MMU init <br /> Create a mapping for the kernel image <br /> Create a mapping for any devices needed at this stage (UART) | Not done yet | |
|
|
||||||
| kmain entry | Verify that kmain entry works post early MMU init | Not done yet | |
|
|
||||||
| Basic Redox MMU support | Get Redox to create a final set of mappings for everything <br /> Verify that this works as expected | Not done yet | |
|
|
||||||
| Basic libc support | Flesh out a basic set of libc calls as required for simple user-land apps | Not done yet | |
|
|
||||||
| userspace_init entry | Verify user-space entry and /sbin/init invocation | Not done yet | |
|
|
||||||
| Basic Interrupt controller support | Add a GIC driver <br /> Verify functionality | Not done yet | |
|
|
||||||
| Basic Timer support | Add a Generic Timer driver <br /> Verify functionality | Not done yet | |
|
|
||||||
| UART interrupt support | Add support for UART interrupts | Not done yet | |
|
|
||||||
| Task context switch support | Add context switching support <br /> Verify functionality | Not done yet | |
|
|
||||||
| Login shell | Iteratively add and verify multi-user login shell support | Not done yet | |
|
|
||||||
| Publish development branch on github | Work with the community to post work done after employer approval | Not done yet | |
|
|
||||||
| Break out the Bubbly | Drink copious quantities of alcohol to celebrate | Not done yet | |
|
|
||||||
| Silicon bring-up | Plan silicon bring-up | Not done yet | |
|
|
||||||
+123
@@ -0,0 +1,123 @@
|
|||||||
|
# Contributing
|
||||||
|
|
||||||
|
## Table of contents
|
||||||
|
1. [What to do](#what-to-do)
|
||||||
|
2. [Code style](#code-style)
|
||||||
|
3. [Sending merge requests](#sending-merge-requests)
|
||||||
|
4. [Writing tests](#writing-tests)
|
||||||
|
5. [Running tests](#running-tests)
|
||||||
|
|
||||||
|
Maintaining a libc is tough work, and we'd love some help!
|
||||||
|
|
||||||
|
## What to do
|
||||||
|
|
||||||
|
For now, we are still trying to get full libc compatibility before we move on to
|
||||||
|
any optimisation.
|
||||||
|
|
||||||
|
- We currently have a number of unimplemented functions. Search for
|
||||||
|
`unimplemented!()` and hop right in!
|
||||||
|
- If you notice any missing functionality, feel free to add it in
|
||||||
|
|
||||||
|
## Code style
|
||||||
|
|
||||||
|
We have a `rustfmt.toml` in the root directory of relibc. Please run `./fmt.sh`
|
||||||
|
before sending in any merge requests as it will automatically format your code.
|
||||||
|
|
||||||
|
With regards to general style:
|
||||||
|
|
||||||
|
### Where applicable, prefer using references to raw pointers
|
||||||
|
|
||||||
|
This is most obvious when looking at `stdio` functions. If raw pointers were
|
||||||
|
used instead of references, then the resulting code would be significantly
|
||||||
|
uglier. Instead try to check for pointer being valid with `pointer::as_ref()`
|
||||||
|
and `pointer::as_mut()` and then immediately use those references instead.
|
||||||
|
|
||||||
|
Internal functions should always take references.
|
||||||
|
|
||||||
|
### Use the c types exposed in our platform module instead of Rust's inbuilt integer types
|
||||||
|
|
||||||
|
This is so we can guarantee that everything works across platforms. While it is
|
||||||
|
generally accepted these days that an `int` has 32 bits (which matches against
|
||||||
|
an `i32`), some platforms have `int` as having 16 bits, and others have long as
|
||||||
|
being 32 bits instead of 64. If you use the types in platform, then we can
|
||||||
|
guarantee that your code will "just work" should we port relibc to a different
|
||||||
|
architecture.
|
||||||
|
|
||||||
|
### Use our internal functions
|
||||||
|
|
||||||
|
If you need to use a C string, don't reinvent the wheel. We have functions in
|
||||||
|
the platform module that convert C strings to Rust slices.
|
||||||
|
|
||||||
|
We also have structures that wrap files, wrap writable strings, and wrap various
|
||||||
|
other commonly used things that you should use instead of rolling your own.
|
||||||
|
|
||||||
|
## Sending merge requests
|
||||||
|
|
||||||
|
If you have sent us a merge request, first of all, thanks for taking your time
|
||||||
|
to help us!
|
||||||
|
|
||||||
|
The first thing to note is that we do most of our development on our
|
||||||
|
[GitLab server](https://gitlab.redox-os.org/redox-os/relibc), and as such it is
|
||||||
|
possible that none of the maintainers will see your merge request if it is
|
||||||
|
opened on GitHub.
|
||||||
|
|
||||||
|
In your merge request, please put in the description:
|
||||||
|
- What functions (if any) have been implemented or changed
|
||||||
|
- The rationale behind your merge request (e.g. why you thought this change was
|
||||||
|
required. If you are just implementing some functions, you can ignore this)
|
||||||
|
- Any issues that are related to the merge request
|
||||||
|
|
||||||
|
We have CI attached to our GitLab instance, so all merge requests are checked to
|
||||||
|
make sure that they are tested before they are merged. Please write tests for
|
||||||
|
the functions that you add/change and test locally on your own machine
|
||||||
|
***before*** submitting a merge request.
|
||||||
|
|
||||||
|
## Writing tests
|
||||||
|
|
||||||
|
Every function that gets written needs to have a test in C in order to make sure
|
||||||
|
it works as intended. Here are a few guidelines for writing good tests.
|
||||||
|
|
||||||
|
### Ensure that any literals you have are mapped to variables instead of being directly passed to a function.
|
||||||
|
|
||||||
|
Sometimes compilers take literals put into libc functions and run them
|
||||||
|
internally during compilation, which can cause some false positives. All tests
|
||||||
|
are compiled with `-fno-builtin`, which theoretically solves this issue, but
|
||||||
|
just in case, it'd be a good idea to map inputs to variables.
|
||||||
|
|
||||||
|
```c
|
||||||
|
#include "string.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
// Don't do this
|
||||||
|
printf("%d\n", strcspn("Hello", "Hi"));
|
||||||
|
|
||||||
|
// Do this
|
||||||
|
char *first = "Hello";
|
||||||
|
char *second = "Hi";
|
||||||
|
printf("%d\n", strcspn(first, second));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Ensure your tests cover every section of code.
|
||||||
|
|
||||||
|
What happens if a string in `strcmp()` is shorter than the other string? What
|
||||||
|
happens if the first argument to `strcspn()` is longer than the second string?
|
||||||
|
In order to make sure that all functions work as expected, we ask that any tests
|
||||||
|
cover as much of the code that you have written as possible.
|
||||||
|
|
||||||
|
## Running tests
|
||||||
|
|
||||||
|
Running tests is an important part in trying to find bugs. Before opening a
|
||||||
|
merge request, we ask that you test on your own machine to make sure there are
|
||||||
|
no regressions.
|
||||||
|
|
||||||
|
You can run tests with `make test` in the root directory of relibc to compile
|
||||||
|
relibc, compile the tests and run them. This *will* print a lot of output to
|
||||||
|
stdout, so be warned!
|
||||||
|
|
||||||
|
You can test against verified correct output with `make verify` in the tests
|
||||||
|
directory. You will need to manually create the correct output and put it in the
|
||||||
|
tests/expected directory. Running any `make` commands in the tests directory
|
||||||
|
will ***not*** rebuild relibc, so you'll need to go back to the root directory
|
||||||
|
if you need to rebuild relibc.
|
||||||
Generated
+551
-222
@@ -3,54 +3,94 @@
|
|||||||
version = 4
|
version = 4
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ahash"
|
name = "argon2"
|
||||||
version = "0.8.12"
|
version = "0.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75"
|
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"base64ct",
|
||||||
"once_cell",
|
"blake2",
|
||||||
"version_check",
|
"cpufeatures",
|
||||||
"zerocopy",
|
"password-hash",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arrayvec"
|
name = "autocfg"
|
||||||
version = "0.7.6"
|
version = "1.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bit_field"
|
name = "base64ct"
|
||||||
version = "0.10.3"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6"
|
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitfield"
|
name = "bcrypt-pbkdf"
|
||||||
version = "0.13.2"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "46afbd2983a5d5a7bd740ccb198caf5b82f45c40c09c0eed36052d91cb92e719"
|
checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2"
|
||||||
|
dependencies = [
|
||||||
|
"blowfish",
|
||||||
|
"pbkdf2",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "1.3.2"
|
version = "2.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "blake2"
|
||||||
version = "2.11.1"
|
version = "0.10.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c4512299f36f043ab09a583e57bceb5a5aab7a73db1805848e8fef3c9e8c78b3"
|
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "block-buffer"
|
||||||
|
version = "0.10.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blowfish"
|
||||||
|
version = "0.9.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e412e2cd0f2b2d93e02543ceae7917b3c70331573df19ee046bcbc35e45e87d7"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"cipher",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cbitset"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29b6ad25ae296159fb0da12b970b2fe179b234584d7cd294c891e2bbb284466b"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.60"
|
version = "1.1.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://github.com/tea/cc-rs?branch=riscv-abi-arch-fix#588ceacb084af41415690c57688e338a32a1f1b4"
|
||||||
checksum = "43c5703da9466b66a946814e1adf53ea2c90f10063b86290cc9eb67ce3478a20"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"find-msvc-tools",
|
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -61,80 +101,176 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "equivalent"
|
name = "chrono"
|
||||||
version = "1.0.2"
|
version = "0.4.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
|
checksum = "145052bdd345b87320e369255277e3fb5152762ad123a901ef5c262dd38fe8d2"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "fdt"
|
|
||||||
version = "0.2.0-alpha1"
|
|
||||||
source = "git+https://github.com/repnop/fdt.git?rev=2fb1409edd1877c714a0aa36b6a7c5351004be54#2fb1409edd1877c714a0aa36b6a7c5351004be54"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "find-msvc-tools"
|
|
||||||
version = "0.1.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hashbrown"
|
|
||||||
version = "0.14.5"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ahash",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hashbrown"
|
name = "chrono-tz"
|
||||||
version = "0.17.0"
|
version = "0.10.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51"
|
checksum = "a6139a8597ed92cf816dfb33f5dd6cf0bb93a6adc938f11039f371bc5bcd26c3"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "indexmap"
|
|
||||||
version = "2.14.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"equivalent",
|
"chrono",
|
||||||
"hashbrown 0.17.0",
|
"phf",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kernel"
|
name = "cipher"
|
||||||
version = "0.5.12"
|
version = "0.4.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"arrayvec",
|
"crypto-common",
|
||||||
"bitfield",
|
"inout",
|
||||||
"bitflags 2.11.1",
|
]
|
||||||
"cc",
|
|
||||||
"fdt",
|
[[package]]
|
||||||
"hashbrown 0.14.5",
|
name = "cpufeatures"
|
||||||
"linked_list_allocator",
|
version = "0.2.17"
|
||||||
"object",
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
"raw-cpuid",
|
checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
|
||||||
"redox-path",
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crt0"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crti"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crtn"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crypto-common"
|
||||||
|
version = "0.1.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
"typenum",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "digest"
|
||||||
|
version = "0.10.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||||
|
dependencies = [
|
||||||
|
"block-buffer",
|
||||||
|
"crypto-common",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dlmalloc"
|
||||||
|
version = "0.2.8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"windows-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "drm-sys"
|
||||||
|
version = "0.8.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bafb66c8dbc944d69e15cfcc661df7e703beffbaec8bd63151368b06c5f9858c"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"linux-raw-sys",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-array"
|
||||||
|
version = "0.14.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||||
|
dependencies = [
|
||||||
|
"typenum",
|
||||||
|
"version_check",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "generic-rt"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "goblin"
|
||||||
|
version = "0.10.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "983a6aafb3b12d4c41ea78d39e189af4298ce747353945ff5105b54a056e5cd9"
|
||||||
|
dependencies = [
|
||||||
|
"log",
|
||||||
|
"plain",
|
||||||
|
"scroll",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hmac"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inout"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||||
|
dependencies = [
|
||||||
|
"generic-array",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ioslice"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5e571352c8a3b89074d12e3ee5173ffe162159105352aaaf1fc5764da747e31b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ld_so"
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.177"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libm"
|
||||||
|
version = "0.2.15"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.1.16"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e02f3bb43d335493c96bf3fd3a321600bf6bd07ed34bc64118e9293bdffea46c"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"libc",
|
||||||
|
"plain",
|
||||||
"redox_syscall",
|
"redox_syscall",
|
||||||
"rmm",
|
|
||||||
"rustc-demangle",
|
|
||||||
"sbi-rt",
|
|
||||||
"slab",
|
|
||||||
"smallvec",
|
|
||||||
"spin",
|
|
||||||
"toml",
|
|
||||||
"x86",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linked_list_allocator"
|
name = "linux-raw-sys"
|
||||||
version = "0.9.1"
|
version = "0.6.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "549ce1740e46b291953c4340adcd74c59bcf4308f4cac050fd33ba91b7168f4a"
|
checksum = "2a385b1be4e5c3e362ad2ffa73c392e53f031eaa5b7d648e64cd87f27f6063d7"
|
||||||
dependencies = [
|
|
||||||
"spinning_top",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@@ -146,93 +282,258 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "memchr"
|
name = "log"
|
||||||
version = "2.8.0"
|
version = "0.4.29"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79"
|
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "md-5"
|
||||||
|
version = "0.10.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"digest",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memchr"
|
||||||
|
version = "2.7.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "object"
|
name = "object"
|
||||||
version = "0.37.3"
|
version = "0.36.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "git+https://gitlab.redox-os.org/andypython/object#7270e3f0d06e5ef4c2b80abc6166d31f4ddf4fea"
|
||||||
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "once_cell"
|
name = "password-hash"
|
||||||
version = "1.21.4"
|
version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
|
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"subtle",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pbkdf2"
|
||||||
|
version = "0.12.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
|
||||||
|
dependencies = [
|
||||||
|
"digest",
|
||||||
|
"hmac",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
|
||||||
|
dependencies = [
|
||||||
|
"phf_shared",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "phf_shared"
|
||||||
|
version = "0.12.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
|
||||||
|
dependencies = [
|
||||||
|
"siphasher",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "plain"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "posix-regex"
|
||||||
|
version = "0.1.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "66df580334caab2f744839ab1be85493d7ec731a92d6cf928008ab0b212bf3bc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.106"
|
version = "1.0.103"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
|
checksum = "5ee95bc4ef87b8d5ba32e8b7714ccc834865276eab0aed5c9958d00ec45f49e8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.45"
|
version = "1.0.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
checksum = "a338cc41d27e6cc6dce6cefc13a0729dfbb81c262b1f519331575dd80ef3067f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "raw-cpuid"
|
name = "rand"
|
||||||
version = "10.7.0"
|
version = "0.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332"
|
checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"rand_core 0.10.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.6.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_core"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_jitter"
|
||||||
|
version = "0.6.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a02dd27aa28665e46e60168c8f355240c73b8a344d2557a92318849441ffda33"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"rand_core 0.10.0",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rand_xorshift"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60aa6af80be32871323012e02e6e65f8a7cc7890931ae421d217ad8fe0df2ccf"
|
||||||
|
dependencies = [
|
||||||
|
"rand_core 0.10.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox-ioctl"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"drm-sys",
|
||||||
|
"redox_syscall",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox-path"
|
name = "redox-path"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "64072665120942deff5fd5425d6c1811b854f4939e7f1c01ce755f64432bbea7"
|
checksum = "436d45c2b6a5b159d43da708e62b25be3a4a3d5550d654b72216ade4c4bfd717"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox-rt"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"generic-rt",
|
||||||
|
"goblin",
|
||||||
|
"ioslice",
|
||||||
|
"libredox",
|
||||||
|
"plain",
|
||||||
|
"redox-path",
|
||||||
|
"redox_syscall",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_event"
|
||||||
|
version = "0.4.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4ea3e412d205440c7b0218af26247226f979ed1201674cda7a33cc70609084b5"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"libredox",
|
||||||
|
"redox_syscall",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.8.1"
|
version = "0.7.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f450ad9c3b1da563fb6948a8e0fb0fb9269711c9c73d9ea1de5058c79c8d643a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.11.1",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rmm"
|
name = "relibc"
|
||||||
version = "0.1.0"
|
version = "0.2.5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.11.1",
|
"argon2",
|
||||||
|
"base64ct",
|
||||||
|
"bcrypt-pbkdf",
|
||||||
|
"bitflags",
|
||||||
|
"cbitset",
|
||||||
|
"cc",
|
||||||
|
"chrono",
|
||||||
|
"chrono-tz",
|
||||||
|
"dlmalloc",
|
||||||
|
"generic-rt",
|
||||||
|
"ioslice",
|
||||||
|
"libc",
|
||||||
|
"libm",
|
||||||
|
"libredox",
|
||||||
|
"log",
|
||||||
|
"md-5",
|
||||||
|
"memchr",
|
||||||
|
"object",
|
||||||
|
"pbkdf2",
|
||||||
|
"plain",
|
||||||
|
"posix-regex",
|
||||||
|
"rand",
|
||||||
|
"rand_jitter",
|
||||||
|
"rand_xorshift",
|
||||||
|
"redox-ioctl",
|
||||||
|
"redox-path",
|
||||||
|
"redox-rt",
|
||||||
|
"redox_event",
|
||||||
|
"redox_syscall",
|
||||||
|
"sc",
|
||||||
|
"scrypt",
|
||||||
|
"sha-crypt",
|
||||||
|
"sha2",
|
||||||
|
"spin",
|
||||||
|
"unicode-width",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "salsa20"
|
||||||
version = "0.1.27"
|
version = "0.10.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
|
checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "sbi-rt"
|
|
||||||
version = "0.0.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7fbaa69be1eedc61c426e6d489b2260482e928b465360576900d52d496a58bd0"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"sbi-spec",
|
"cipher",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sbi-spec"
|
name = "sc"
|
||||||
version = "0.0.7"
|
version = "0.2.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e36312fb5ddc10d08ecdc65187402baba4ac34585cb9d1b78522ae2358d890"
|
checksum = "010e18bd3bfd1d45a7e666b236c78720df0d9a7698ebaa9c1c559961eb60a38b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
@@ -241,28 +542,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "scroll"
|
||||||
version = "1.0.228"
|
version = "0.13.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e"
|
checksum = "c1257cd4248b4132760d6524d6dda4e053bc648c9070b960929bf50cfb1e7add"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_core",
|
"scroll_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_core"
|
name = "scroll_derive"
|
||||||
version = "1.0.228"
|
version = "0.13.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad"
|
checksum = "ed76efe62313ab6610570951494bdaa81568026e0318eaa55f167de70eeea67d"
|
||||||
dependencies = [
|
|
||||||
"serde_derive",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "serde_derive"
|
|
||||||
version = "1.0.228"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79"
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -270,12 +562,36 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_spanned"
|
name = "scrypt"
|
||||||
version = "0.6.9"
|
version = "0.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3"
|
checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"password-hash",
|
||||||
|
"pbkdf2",
|
||||||
|
"salsa20",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha-crypt"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "88e79009728d8311d42d754f2f319a975f9e38f156fd5e422d2451486c78b286"
|
||||||
|
dependencies = [
|
||||||
|
"base64ct",
|
||||||
|
"sha2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha2"
|
||||||
|
version = "0.10.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"cpufeatures",
|
||||||
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -285,16 +601,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slab"
|
name = "siphasher"
|
||||||
version = "0.4.12"
|
version = "1.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
|
checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "smallvec"
|
|
||||||
version = "1.15.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
@@ -306,19 +616,16 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spinning_top"
|
name = "subtle"
|
||||||
version = "0.2.5"
|
version = "2.6.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5b9eb1a2f4c41445a3a0ff9abc5221c5fcd28e1f13cd7c0397706f9ac938ddb0"
|
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||||
dependencies = [
|
|
||||||
"lock_api",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "syn"
|
||||||
version = "2.0.117"
|
version = "2.0.110"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
checksum = "a99801b5bd34ede4cf3fc688c5919368fea4e4814a4664359503e6015b280aea"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -326,51 +633,22 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "typenum"
|
||||||
version = "0.8.23"
|
version = "1.19.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dc1beb996b9d83529a9e75c17a1686767d148d70663143c7854d8b4a09ced362"
|
checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb"
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
"serde_spanned",
|
|
||||||
"toml_datetime",
|
|
||||||
"toml_edit",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml_datetime"
|
|
||||||
version = "0.6.11"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
|
|
||||||
dependencies = [
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml_edit"
|
|
||||||
version = "0.22.27"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
|
|
||||||
dependencies = [
|
|
||||||
"indexmap",
|
|
||||||
"serde",
|
|
||||||
"serde_spanned",
|
|
||||||
"toml_datetime",
|
|
||||||
"toml_write",
|
|
||||||
"winnow",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "toml_write"
|
|
||||||
version = "0.1.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "5d99f8c9a7727884afe522e9bd5edbfc91a3312b36a77b5fb8926e4c31a41801"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.24"
|
version = "1.0.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
|
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-width"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "version_check"
|
name = "version_check"
|
||||||
@@ -379,45 +657,96 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winapi"
|
||||||
version = "0.7.15"
|
version = "0.3.9"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
|
checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"memchr",
|
"winapi-i686-pc-windows-gnu",
|
||||||
|
"winapi-x86_64-pc-windows-gnu",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x86"
|
name = "winapi-i686-pc-windows-gnu"
|
||||||
version = "0.47.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "55b5be8cc34d017d8aabec95bc45a43d0f20e8b2a31a453cabc804fe996f8dca"
|
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-x86_64-pc-windows-gnu"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-sys"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bit_field",
|
"windows-targets",
|
||||||
"bitflags 1.3.2",
|
|
||||||
"raw-cpuid",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy"
|
name = "windows-targets"
|
||||||
version = "0.8.48"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9"
|
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"zerocopy-derive",
|
"windows_aarch64_gnullvm",
|
||||||
|
"windows_aarch64_msvc",
|
||||||
|
"windows_i686_gnu",
|
||||||
|
"windows_i686_gnullvm",
|
||||||
|
"windows_i686_msvc",
|
||||||
|
"windows_x86_64_gnu",
|
||||||
|
"windows_x86_64_gnullvm",
|
||||||
|
"windows_x86_64_msvc",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zerocopy-derive"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.8.48"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[patch.unused]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.1.18"
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.52.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|||||||
+127
-127
@@ -1,148 +1,148 @@
|
|||||||
[workspace]
|
|
||||||
resolver = "3"
|
|
||||||
members = [".", "rmm"]
|
|
||||||
|
|
||||||
[package]
|
[package]
|
||||||
name = "kernel"
|
name = "relibc"
|
||||||
version = "0.5.12"
|
version = "0.2.5"
|
||||||
build = "build.rs"
|
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "relibc"
|
||||||
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = [
|
||||||
|
"src/crt0",
|
||||||
|
"src/crti",
|
||||||
|
"src/crtn",
|
||||||
|
"redox-rt",
|
||||||
|
"ld_so",
|
||||||
|
"generic-rt",
|
||||||
|
]
|
||||||
|
exclude = ["tests", "dlmalloc-rs"]
|
||||||
|
|
||||||
|
[workspace.lints.clippy]
|
||||||
|
borrow_as_ptr = "deny"
|
||||||
|
cast_lossless = "warn" # TODO review occurrences
|
||||||
|
cast_possible_truncation = "allow" # TODO review occurrences
|
||||||
|
cast_possible_wrap = "allow" # TODO review occurrences
|
||||||
|
cast_precision_loss = "allow" # TODO review occurrences
|
||||||
|
cast_ptr_alignment = "allow" # TODO review occurrences
|
||||||
|
cast_sign_loss = "allow" # TODO review occurrences
|
||||||
|
missing_errors_doc = "allow" # TODO review occurrences
|
||||||
|
missing_panics_doc = "allow" # TODO review occurrences
|
||||||
|
missing_safety_doc = "allow" # TODO review occurrences
|
||||||
|
mut_from_ref = "warn" # TODO review occurrences
|
||||||
|
precedence = "deny"
|
||||||
|
ptr_as_ptr = "warn" # TODO review occurrences
|
||||||
|
ptr_cast_constness = "warn" # TODO review occurrences
|
||||||
|
ref_as_ptr = "warn" # TODO review occurrences
|
||||||
|
upper_case_acronyms = "allow" # TODO review occurrences
|
||||||
|
zero_ptr = "warn" # must allow on public constants due to cbindgen issue
|
||||||
|
|
||||||
|
[workspace.lints.rust]
|
||||||
|
dangling_pointers_from_temporaries = "deny"
|
||||||
|
dead_code = "allow" # TODO review occuurences
|
||||||
|
deprecated = "deny"
|
||||||
|
improper_ctypes_definitions = "deny"
|
||||||
|
internal_features = "allow" # core_intrinsics and lang_items
|
||||||
|
irrefutable_let_patterns = "deny"
|
||||||
|
mismatched_lifetime_syntaxes = "deny"
|
||||||
|
non_camel_case_types = "allow" # needed for most POSIX type names
|
||||||
|
non_snake_case = "allow" # TODO review occuurences
|
||||||
|
non_upper_case_globals = "allow" # TODO review occuurences
|
||||||
|
unexpected_cfgs = "deny"
|
||||||
|
unpredictable_function_pointer_comparisons = "deny"
|
||||||
|
unreachable_code = "allow" # TODO review occuurences
|
||||||
|
unsafe_op_in_unsafe_fn = "deny"
|
||||||
|
unused_imports = "deny"
|
||||||
|
unused_must_use = "deny"
|
||||||
|
unused_mut = "deny"
|
||||||
|
unused_unsafe = "deny"
|
||||||
|
unused_variables = "allow" # TODO review occurrences (too many for now)
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
bitflags = "2"
|
||||||
|
ioslice = { version = "0.6", default-features = false }
|
||||||
|
plain = "0.2"
|
||||||
|
redox-path = "0.3"
|
||||||
|
redox_protocols = { package = "libredox", version = "0.1.16", default-features = false, features = ["protocol"] }
|
||||||
|
redox_syscall = "0.7.4"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = "1.0"
|
cc = "1"
|
||||||
toml = "0.8"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
arrayvec = { version = "0.7.4", default-features = false }
|
bitflags.workspace = true
|
||||||
bitfield = "0.13.2"
|
cbitset = "0.2"
|
||||||
bitflags = "2"
|
posix-regex = { version = "0.1.4", features = ["no_std"] }
|
||||||
fdt = { git = "https://github.com/repnop/fdt.git", rev = "2fb1409edd1877c714a0aa36b6a7c5351004be54" }
|
|
||||||
hashbrown = { version = "0.14.3", default-features = false, features = ["ahash", "inline-more"] }
|
rand = { version = "0.10", default-features = false }
|
||||||
linked_list_allocator = "0.9.0"
|
rand_xorshift = "0.5"
|
||||||
redox-path = "0.2.0"
|
rand_jitter = "0.6"
|
||||||
redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git", default-features = false }
|
|
||||||
rmm = { path = "rmm", default-features = false }
|
memchr = { version = "2.2.0", default-features = false }
|
||||||
slab = { version = "0.4", default-features = false }
|
plain.workspace = true
|
||||||
smallvec = { version = "1.15.1", default-features = false }
|
unicode-width = "0.1"
|
||||||
spin = { version = "0.9.8" }
|
__libc_only_for_layout_checks = { package = "libc", version = "0.2.149", optional = true }
|
||||||
|
md5-crypto = { package = "md-5", version = "0.10.6", default-features = false }
|
||||||
|
sha-crypt = { version = "0.5", default-features = false }
|
||||||
|
base64ct = { version = "1.6", default-features = false, features = ["alloc"] }
|
||||||
|
bcrypt-pbkdf = { version = "0.10", default-features = false, features = [
|
||||||
|
"alloc",
|
||||||
|
] }
|
||||||
|
scrypt = { version = "0.11", default-features = false, features = ["simple"] }
|
||||||
|
pbkdf2 = { version = "0.12", features = ["sha2"] }
|
||||||
|
sha2 = { version = "0.10", default-features = false }
|
||||||
|
generic-rt = { path = "generic-rt" }
|
||||||
|
chrono-tz = { version = "0.10", default-features = false }
|
||||||
|
chrono = { version = "0.4", default-features = false, features = ["alloc"] }
|
||||||
|
libm = "0.2"
|
||||||
|
log = "0.4"
|
||||||
|
spin = "0.9.8"
|
||||||
|
argon2 = "0.5.3"
|
||||||
|
|
||||||
|
[dependencies.dlmalloc]
|
||||||
|
path = "dlmalloc-rs"
|
||||||
|
default-features = false
|
||||||
|
features = ["c_api"]
|
||||||
|
|
||||||
[dependencies.object]
|
[dependencies.object]
|
||||||
version = "0.37.1"
|
version = "0.36.7"
|
||||||
|
git = "https://gitlab.redox-os.org/andypython/object"
|
||||||
default-features = false
|
default-features = false
|
||||||
features = ["read_core", "elf"]
|
features = ["elf", "read_core"]
|
||||||
|
|
||||||
[dependencies.rustc-demangle]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
version = "0.1.16"
|
sc = "0.2.7"
|
||||||
default-features = false
|
|
||||||
|
|
||||||
[lints.clippy]
|
[target.'cfg(target_os = "redox")'.dependencies]
|
||||||
# Overflows are very, very bad in kernel code as it may provide an attack vector for
|
redox_syscall.workspace = true
|
||||||
# userspace applications, and it is only checked in debug builds
|
redox-rt = { path = "redox-rt" }
|
||||||
# TODO: address occurrences and then deny
|
redox-path.workspace = true
|
||||||
arithmetic_side_effects = "warn"
|
redox_event = { version = "0.4.6", default-features = false, features = [
|
||||||
cast_ptr_alignment = "warn" # TODO: address occurrences and then deny
|
"redox_syscall",
|
||||||
identity_op = "allow" # Used to allow stuff like 1 << 0 and 1 * 1024 * 1024
|
] }
|
||||||
if_same_then_else = "allow" # Useful for adding comments about different branches
|
ioslice.workspace = true
|
||||||
# Indexing a slice can cause panics and that is something we always want to avoid
|
redox-ioctl = { path = "redox-ioctl" }
|
||||||
# in kernel code. Use .get and return an error instead
|
redox_protocols.workspace = true
|
||||||
# TODO: address occurrences and then deny
|
|
||||||
indexing_slicing = "warn"
|
|
||||||
many_single_char_names = "allow" # Useful in the syscall function
|
|
||||||
module_inception = "allow" # Used for context::context
|
|
||||||
# Not implementing default is sometimes useful in the case something has significant cost
|
|
||||||
# to allocate. If you implement default, it can be allocated without evidence using the
|
|
||||||
# ..Default::default() syntax. Not fun in kernel space
|
|
||||||
new_without_default = "allow"
|
|
||||||
not_unsafe_ptr_arg_deref = "deny"
|
|
||||||
or_fun_call = "allow" # Used to make it nicer to return errors, for example, .ok_or(Error::new(ESRCH))
|
|
||||||
precedence = "deny"
|
|
||||||
ptr_cast_constness = "deny"
|
|
||||||
too_many_arguments = "allow" # This is needed in some cases, like for syscall
|
|
||||||
# Avoid panicking in the kernel without information about the panic. Use expect
|
|
||||||
# TODO: address occurrences and then deny
|
|
||||||
unwrap_used = "warn"
|
|
||||||
|
|
||||||
[lints.rust]
|
|
||||||
static_mut_refs = "warn" # FIXME deny once all occurrences are fixed
|
|
||||||
# This is usually a serious issue - a missing import of a define where it is interpreted
|
|
||||||
# as a catch-all variable in a match, for example
|
|
||||||
unreachable_patterns = "deny"
|
|
||||||
unused_must_use = "deny" # Ensure that all must_use results are used
|
|
||||||
|
|
||||||
[target.'cfg(any(target_arch = "x86", target_arch = "x86_64"))'.dependencies]
|
|
||||||
raw-cpuid = "10.2.0"
|
|
||||||
x86 = { version = "0.47.0", default-features = false }
|
|
||||||
|
|
||||||
[target.'cfg(any(target_arch = "riscv64", target_arch = "riscv32"))'.dependencies]
|
|
||||||
sbi-rt = "0.0.3"
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = [
|
# to enable trace level, take out this `no_trace`
|
||||||
"acpi",
|
default = ["check_against_libc_crate", "ld_so_cache", "no_trace"]
|
||||||
#"debugger",
|
check_against_libc_crate = ["__libc_only_for_layout_checks"]
|
||||||
"multi_core",
|
ld_so_cache = []
|
||||||
"serial_debug",
|
math_libm = []
|
||||||
"self_modifying",
|
no_trace = ["log/release_max_level_debug"]
|
||||||
"x86_kvm_pv",
|
# for very verbose activity beyond trace level
|
||||||
#"busy_panic",
|
trace_tls = []
|
||||||
#"drop_panic",
|
|
||||||
#"syscall_debug"
|
|
||||||
]
|
|
||||||
|
|
||||||
# Activates some limited code-overwriting optimizations, based on CPU features.
|
|
||||||
self_modifying = []
|
|
||||||
|
|
||||||
acpi = []
|
|
||||||
lpss_debug = []
|
|
||||||
multi_core = ["acpi"]
|
|
||||||
profiling = []
|
|
||||||
#TODO: remove when threading issues are fixed
|
|
||||||
pti = []
|
|
||||||
drop_panic = []
|
|
||||||
busy_panic = []
|
|
||||||
qemu_debug = []
|
|
||||||
serial_debug = []
|
|
||||||
system76_ec_debug = []
|
|
||||||
x86_kvm_pv = []
|
|
||||||
|
|
||||||
debugger = ["syscall_debug"]
|
|
||||||
syscall_debug = []
|
|
||||||
|
|
||||||
sys_fdstat = []
|
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
# Avoids having to define the eh_personality lang item and reduces kernel size
|
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
# Avoids having to define the eh_personality lang item and reduces kernel size
|
|
||||||
panic = "abort"
|
panic = "abort"
|
||||||
#lto = true
|
|
||||||
debug = "full"
|
|
||||||
|
|
||||||
# Red Bear OS Phase J: see local/sources/base/Cargo.toml for
|
|
||||||
# the rationale. Both the kernel and the base workspace need
|
|
||||||
# the libredox override so that the libredox::error::Error
|
|
||||||
# type is the same compile-time type as syscall::Error. With
|
|
||||||
# the local libredox fork at local/sources/libredox/ using
|
|
||||||
# the local syscall fork at local/sources/syscall/, the
|
|
||||||
# libredox::error::Error (re-exported from the local syscall)
|
|
||||||
# and syscall::Error (also the local syscall) are now the
|
|
||||||
# same type, so `?` conversions in scheme-utils / daemon
|
|
||||||
# compile cleanly.
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
# Phase J: override libredox 0.1.17 to use the local
|
cc-11 = { git = "https://github.com/tea/cc-rs", branch = "riscv-abi-arch-fix", package = "cc" }
|
||||||
# fork at ../libredox/ (which itself uses the local syscall
|
|
||||||
# fork). This breaks the libredox::error::Error <->
|
|
||||||
# syscall::Error type-identity barrier that previously
|
|
||||||
# caused E0277 errors in scheme-utils and daemon.
|
|
||||||
libredox = { path = "../libredox" }
|
|
||||||
# Phase J: the kernel's redox_syscall dep is a git URL
|
|
||||||
# (not crates.io), so [patch.crates-io] doesn't apply.
|
|
||||||
# Use a [patch."<URL>"] section to match the dep source.
|
|
||||||
# The local fork at ../syscall adds the EnterS2Idle /
|
|
||||||
# ExitS2Idle AcpiVerb variants — the kernel's direct use
|
|
||||||
# of AcpiVerb in src/scheme/acpi.rs's kcall handler
|
|
||||||
# needs the fork to see these variants.
|
|
||||||
[patch."https://gitlab.redox-os.org/redox-os/syscall.git"]
|
|
||||||
redox_syscall = { path = "../syscall" }
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2017 Jeremy Soller
|
Copyright (c) 2018 Redox OS
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
@@ -1,66 +1,226 @@
|
|||||||
.PHONY: all check
|
include config.mk
|
||||||
|
|
||||||
SOURCE:=$(dir $(realpath $(lastword $(MAKEFILE_LIST))))
|
CARGO?=cargo
|
||||||
BUILD?=$(CURDIR)
|
CARGO_TEST?=$(CARGO)
|
||||||
export RUST_TARGET_PATH=$(SOURCE)/targets
|
CARGO_COMMON_FLAGS=-Z build-std=core,alloc,compiler_builtins
|
||||||
|
CARGOFLAGS?=$(CARGO_COMMON_FLAGS)
|
||||||
|
CC_WRAPPER?=
|
||||||
|
RUSTCFLAGS?=
|
||||||
|
LINKFLAGS?=-lgcc
|
||||||
|
USE_RUST_LIBM?=
|
||||||
|
TESTBIN?=
|
||||||
|
export OBJCOPY?=objcopy
|
||||||
|
|
||||||
ifeq ($(TARGET),)
|
export CARGO_TARGET_DIR?=$(shell pwd)/target
|
||||||
ARCH?=$(shell uname -m)
|
BUILD?=$(CARGO_TARGET_DIR)/$(TARGET)
|
||||||
else
|
CARGOFLAGS+=--target=$(TARGET)
|
||||||
ARCH?=$(shell echo "$(TARGET)" | cut -d - -f1)
|
EXCEPT_MATH=-not -name "math"
|
||||||
|
FEATURE_MATH=
|
||||||
|
ifneq ($(USE_RUST_LIBM),)
|
||||||
|
FEATURE_MATH=--features math_libm
|
||||||
|
EXCEPT_MATH=
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(ARCH),riscv64gc)
|
TARGET_HEADERS?=$(BUILD)/include
|
||||||
override ARCH:=riscv64
|
export CFLAGS=-I$(TARGET_HEADERS)
|
||||||
GNU_TARGET=riscv64-unknown-redox
|
|
||||||
else ifeq ($(ARCH),i686)
|
PROFILE?=release
|
||||||
override ARCH:=i586
|
|
||||||
GNU_TARGET=i686-unknown-redox
|
HEADERS_UNPARSED=$(shell find src/header -mindepth 1 -maxdepth 1 -type d -not -name "_*" $(EXCEPT_MATH) -printf "%f\n")
|
||||||
else
|
HEADERS_DEPS=$(shell find src/header -type f \( -name "cbindgen.toml" -o -name "*.rs" \))
|
||||||
GNU_TARGET=$(ARCH)-unknown-redox
|
#HEADERS=$(patsubst %,%.h,$(subst _,/,$(HEADERS_UNPARSED)))
|
||||||
|
|
||||||
|
SRC=\
|
||||||
|
Cargo.* \
|
||||||
|
$(shell find src/ redox-rt/src/ ld_so/src/ redox-ioctl/src/ include/ -type f)
|
||||||
|
|
||||||
|
BUILTINS_VERSION=0.1.70
|
||||||
|
|
||||||
|
.PHONY: all clean fmt install install-libs install-headers install-tests libs headers submodules test
|
||||||
|
|
||||||
|
all: | headers libs
|
||||||
|
|
||||||
|
headers: $(HEADERS_DEPS)
|
||||||
|
rm -rf $(TARGET_HEADERS)
|
||||||
|
mkdir -p $(TARGET_HEADERS)
|
||||||
|
cp -r include/* $(TARGET_HEADERS)
|
||||||
|
ifeq ($(USE_RUST_LIBM),)
|
||||||
|
cp "openlibm/include"/*.h $(TARGET_HEADERS)
|
||||||
|
cp "openlibm/src"/*.h $(TARGET_HEADERS)
|
||||||
endif
|
endif
|
||||||
|
@set -e ; \
|
||||||
|
for header in $(HEADERS_UNPARSED); do \
|
||||||
|
if test -f "src/header/$$header/cbindgen.toml"; then \
|
||||||
|
echo -e "\033[0;36;49mWriting Header $$header\033[0m"; \
|
||||||
|
out=`echo "$$header" | sed 's/_/\//g'`; \
|
||||||
|
out="$(TARGET_HEADERS)/$$out.h"; \
|
||||||
|
cat "src/header/$$header/cbindgen.toml" cbindgen.globdefs.toml \
|
||||||
|
| cbindgen "src/header/$$header/mod.rs" --config=/dev/stdin --output "$$out" 2>/dev/null; \
|
||||||
|
fi \
|
||||||
|
done; echo -e "\033[0;36;49mAll headers written\033[0m";
|
||||||
|
|
||||||
|
clean:
|
||||||
all: $(BUILD)/kernel $(BUILD)/kernel.sym
|
$(CARGO) clean
|
||||||
|
$(MAKE) -C tests clean
|
||||||
LD_SCRIPT=$(SOURCE)/linkers/$(ARCH).ld
|
rm -rf sysroot
|
||||||
LOCKFILE=$(SOURCE)/Cargo.lock
|
|
||||||
MANIFEST=$(SOURCE)/Cargo.toml
|
|
||||||
TARGET_SPEC=$(RUST_TARGET_PATH)/$(ARCH)-unknown-kernel.json
|
|
||||||
|
|
||||||
KERNEL_CARGO_FEATURES?=
|
|
||||||
|
|
||||||
$(BUILD)/kernel.all: $(LD_SCRIPT) $(LOCKFILE) $(MANIFEST) $(TARGET_SPEC) $(shell find $(SOURCE) -name "*.rs" -type f)
|
|
||||||
cd $(SOURCE) && RUSTUP_TOOLCHAIN=nightly-2026-04-11 RUSTFLAGS="-Zunstable-options" cargo rustc \
|
|
||||||
-Z json-target-spec -Z build-std=core,alloc -Zbuild-std-features=compiler-builtins-mem \
|
|
||||||
--bin kernel \
|
|
||||||
--manifest-path "$(MANIFEST)" \
|
|
||||||
--target "$(TARGET_SPEC)" \
|
|
||||||
--release \
|
|
||||||
--features=$(KERNEL_CARGO_FEATURES) \
|
|
||||||
-- \
|
|
||||||
-C link-arg=-T -Clink-arg="$(LD_SCRIPT)" \
|
|
||||||
-C link-arg=-z -Clink-arg=max-page-size=0x1000 \
|
|
||||||
--emit link="$(BUILD)/kernel.all"
|
|
||||||
|
|
||||||
$(BUILD)/kernel.sym: $(BUILD)/kernel.all
|
|
||||||
$(GNU_TARGET)-objcopy \
|
|
||||||
--only-keep-debug \
|
|
||||||
"$(BUILD)/kernel.all" \
|
|
||||||
"$(BUILD)/kernel.sym"
|
|
||||||
|
|
||||||
$(BUILD)/kernel: $(BUILD)/kernel.all
|
|
||||||
$(GNU_TARGET)-objcopy \
|
|
||||||
--strip-debug \
|
|
||||||
"$(BUILD)/kernel.all" \
|
|
||||||
"$(BUILD)/kernel"
|
|
||||||
|
|
||||||
KERNEL_CHECK_FEATURES?=
|
|
||||||
|
|
||||||
check:
|
check:
|
||||||
cargo check \
|
$(CARGO) check
|
||||||
--bin kernel \
|
|
||||||
--manifest-path "$(MANIFEST)" \
|
fmt:
|
||||||
--target "$(TARGET_SPEC)" \
|
./fmt.sh
|
||||||
-Z build-std=core,alloc -Zbuild-std-features=compiler-builtins-mem -Z target-spec-json \
|
|
||||||
--features=$(KERNEL_CHECK_FEATURES)
|
install-headers: headers libs
|
||||||
|
mkdir -pv "$(DESTDIR)/include"
|
||||||
|
cp -rv "$(TARGET_HEADERS)"/* "$(DESTDIR)/include"
|
||||||
|
|
||||||
|
libs: \
|
||||||
|
$(BUILD)/$(PROFILE)/libc.a \
|
||||||
|
$(BUILD)/$(PROFILE)/libc.so \
|
||||||
|
$(BUILD)/$(PROFILE)/crt0.o \
|
||||||
|
$(BUILD)/$(PROFILE)/crti.o \
|
||||||
|
$(BUILD)/$(PROFILE)/crtn.o \
|
||||||
|
$(BUILD)/$(PROFILE)/ld.so
|
||||||
|
|
||||||
|
install-libs: headers libs
|
||||||
|
mkdir -pv "$(DESTDIR)/lib"
|
||||||
|
cp -v "$(BUILD)/$(PROFILE)/libc.a" "$(DESTDIR)/lib"
|
||||||
|
cp -v "$(BUILD)/$(PROFILE)/libc.so" "$(DESTDIR)/lib"
|
||||||
|
ln -vnfs libc.so "$(DESTDIR)/lib/libc.so.6"
|
||||||
|
cp -v "$(BUILD)/$(PROFILE)/crt0.o" "$(DESTDIR)/lib"
|
||||||
|
ln -vnfs crt0.o "$(DESTDIR)/lib/crt1.o"
|
||||||
|
cp -v "$(BUILD)/$(PROFILE)/crti.o" "$(DESTDIR)/lib"
|
||||||
|
cp -v "$(BUILD)/$(PROFILE)/crtn.o" "$(DESTDIR)/lib"
|
||||||
|
cp -v "$(BUILD)/$(PROFILE)/ld.so" "$(DESTDIR)/$(LD_SO_PATH)"
|
||||||
|
ifeq ($(USE_RUST_LIBM),)
|
||||||
|
cp -v "$(BUILD)/openlibm/libopenlibm.a" "$(DESTDIR)/lib/libm.a"
|
||||||
|
endif
|
||||||
|
# Empty libraries for dl, pthread, and rt
|
||||||
|
$(AR) -rcs "$(DESTDIR)/lib/libdl.a"
|
||||||
|
$(AR) -rcs "$(DESTDIR)/lib/libpthread.a"
|
||||||
|
$(AR) -rcs "$(DESTDIR)/lib/librt.a"
|
||||||
|
|
||||||
|
install-tests: tests
|
||||||
|
$(MAKE) -C tests
|
||||||
|
mkdir -p "$(DESTDIR)/relibc-tests"
|
||||||
|
cp -vr tests/build_$(TARGET)/* "$(DESTDIR)/relibc-tests/"
|
||||||
|
|
||||||
|
install: install-headers install-libs
|
||||||
|
|
||||||
|
submodules:
|
||||||
|
git submodule sync
|
||||||
|
git submodule update --init --recursive
|
||||||
|
|
||||||
|
sysroot:
|
||||||
|
@mkdir -p $@
|
||||||
|
|
||||||
|
.PHONY: sysroot/$(TARGET)
|
||||||
|
sysroot/$(TARGET): | sysroot
|
||||||
|
rm -rf $@
|
||||||
|
rm -rf $@.partial
|
||||||
|
mkdir -p $@.partial
|
||||||
|
$(MAKE) install DESTDIR=$(shell pwd)/$@.partial
|
||||||
|
mv $@.partial $@
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
test: sysroot/$(TARGET)
|
||||||
|
# TODO: Fix SIGILL when running cargo test
|
||||||
|
# $(CARGO_TEST) test
|
||||||
|
$(MAKE) -C tests run
|
||||||
|
|
||||||
|
test-once: sysroot/$(TARGET)
|
||||||
|
$(MAKE) -C tests run-once TESTBIN=$(TESTBIN)
|
||||||
|
|
||||||
|
|
||||||
|
$(BUILD)/$(PROFILE)/libc.so: $(BUILD)/$(PROFILE)/libc.a
|
||||||
|
$(CC) -nostdlib \
|
||||||
|
-shared \
|
||||||
|
-Wl,--gc-sections \
|
||||||
|
-Wl,-z,pack-relative-relocs \
|
||||||
|
-Wl,--sort-common \
|
||||||
|
-Wl,--whole-archive $^ -Wl,--no-whole-archive \
|
||||||
|
-Wl,-soname,libc.so.6 \
|
||||||
|
$(LINKFLAGS) \
|
||||||
|
-o $@
|
||||||
|
|
||||||
|
$(BUILD)/$(PROFILE)/ld.so: $(BUILD)/$(PROFILE)/ld_so.o $(BUILD)/$(PROFILE)/libc.a
|
||||||
|
# TODO: merge ld.so with libc.so: --dynamic-list=dynamic-list-file
|
||||||
|
$(LD) --shared -Bsymbolic --no-relax -T ld_so/ld_script/$(TARGET).ld --gc-sections $^ -o $@
|
||||||
|
|
||||||
|
$(BUILD)/$(PROFILE)/libc.a: $(BUILD)/$(PROFILE)/librelibc.a $(BUILD)/openlibm/libopenlibm.a
|
||||||
|
echo "create $@" > "$@.mri"
|
||||||
|
for lib in $^; do\
|
||||||
|
echo "addlib $$lib" >> "$@.mri"; \
|
||||||
|
done
|
||||||
|
echo "save" >> "$@.mri"
|
||||||
|
echo "end" >> "$@.mri"
|
||||||
|
$(AR) -M < "$@.mri"
|
||||||
|
|
||||||
|
# Debug targets
|
||||||
|
|
||||||
|
$(BUILD)/debug/librelibc.a: $(SRC)
|
||||||
|
$(CARGO) rustc $(CARGOFLAGS) $(FEATURE_MATH) -- --emit link=$@ -g -C debug-assertions=no $(RUSTCFLAGS)
|
||||||
|
./renamesyms.sh "$@" "$(BUILD)/debug/deps/"
|
||||||
|
./stripcore.sh "$@"
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
$(BUILD)/debug/crt0.o: $(SRC)
|
||||||
|
$(CARGO) rustc --manifest-path src/crt0/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
$(BUILD)/debug/crti.o: $(SRC)
|
||||||
|
$(CARGO) rustc --manifest-path src/crti/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
$(BUILD)/debug/crtn.o: $(SRC)
|
||||||
|
$(CARGO) rustc --manifest-path src/crtn/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
$(BUILD)/debug/ld_so.o: $(SRC)
|
||||||
|
$(CARGO) rustc --manifest-path ld_so/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort -g -C debug-assertions=no $(RUSTCFLAGS)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
# Release targets
|
||||||
|
|
||||||
|
$(BUILD)/release/librelibc.a: $(SRC)
|
||||||
|
$(CARGO) rustc --release $(CARGOFLAGS) -- --emit link=$@ $(RUSTCFLAGS)
|
||||||
|
@# TODO: Better to only allow a certain whitelisted set of symbols? Perhaps
|
||||||
|
@# use some cbindgen hook, specify them manually, or grep for #[unsafe(no_mangle)].
|
||||||
|
./renamesyms.sh "$@" "$(BUILD)/release/deps/"
|
||||||
|
./stripcore.sh "$@"
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
$(BUILD)/release/crt0.o: $(SRC)
|
||||||
|
$(CARGO) rustc --release --manifest-path src/crt0/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
$(BUILD)/release/crti.o: $(SRC)
|
||||||
|
$(CARGO) rustc --release --manifest-path src/crti/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
$(BUILD)/release/crtn.o: $(SRC)
|
||||||
|
$(CARGO) rustc --release --manifest-path src/crtn/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
$(BUILD)/release/ld_so.o: $(SRC)
|
||||||
|
$(CARGO) rustc --release --manifest-path ld_so/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
# Other targets
|
||||||
|
|
||||||
|
$(BUILD)/openlibm: openlibm
|
||||||
|
rm -rf $@ $@.partial
|
||||||
|
mkdir -p $(BUILD)
|
||||||
|
cp -r $< $@.partial
|
||||||
|
mv $@.partial $@
|
||||||
|
touch $@
|
||||||
|
|
||||||
|
ifeq ($(USE_RUST_LIBM),)
|
||||||
|
$(BUILD)/openlibm/libopenlibm.a: $(BUILD)/openlibm $(BUILD)/$(PROFILE)/librelibc.a
|
||||||
|
$(MAKE) -s AR=$(AR) CC="$(CC_WRAPPER) $(CC)" LD=$(LD) CPPFLAGS="$(CPPFLAGS) -fno-stack-protector -I$(shell pwd)/include -I$(TARGET_HEADERS)" -C $< libopenlibm.a
|
||||||
|
./renamesyms.sh "$@" "$(BUILD)/release/deps/"
|
||||||
|
else
|
||||||
|
$(BUILD)/openlibm/libopenlibm.a:
|
||||||
|
mkdir -p "$(BUILD)/openlibm"
|
||||||
|
$(AR) -rcs "$(BUILD)/openlibm/libopenlibm.a"
|
||||||
|
endif
|
||||||
|
|||||||
@@ -1,77 +1,169 @@
|
|||||||
# Kernel
|
# Redox C Library (relibc)
|
||||||
|
|
||||||
Redox OS Microkernel
|
relibc is a portable C standard library written in Rust and is under heavy development, this library contain the following items:
|
||||||
|
|
||||||
[](https://docs.rs/redox_syscall/latest/syscall/)
|
- C, Linux, BSD functions and extensions
|
||||||
[](https://github.com/XAMPPRocky/tokei)
|
- POSIX compatibility layer
|
||||||
[](./LICENSE)
|
- Interfaces for system components
|
||||||
|
|
||||||
## Requirements
|
The motivation for this project is twofold: Reduce issues that the Redox developers were having with [newlib](https://sourceware.org/newlib/), and create a more stable and safe alternative to C standard libraries written in C. It is mainly designed to be used under Redox, as an alternative to newlib, but it also supports Linux via the [sc](https://crates.io/crates/sc) crate.
|
||||||
|
|
||||||
* [`nasm`](https://nasm.us/) needs to be available on the PATH at build time.
|
Currently Redox and Linux are supported.
|
||||||
|
|
||||||
## Building The Documentation
|
## `redox-rt`
|
||||||
|
|
||||||
Use this command:
|
`redox-rt` is a runtime library that provides much of the code that enables POSIX on Redox, like `fork`, `exec`, signal handling, etc.
|
||||||
|
Relibc uses it as backend in `src/platform/redox`, and it's intended to eventually be usable independently, without relibc.
|
||||||
|
|
||||||
|
## Repository Layout
|
||||||
|
|
||||||
|
- `include` - Header files (mostly macros and variadic functions `cbindgen` can't generate)
|
||||||
|
- `src` - Source files
|
||||||
|
- `src/c` - C code
|
||||||
|
- `src/crt0` - Runtime code
|
||||||
|
- `src/crti` - Runtime code
|
||||||
|
- `src/crtn` - Runtime code
|
||||||
|
- `src/header` - Header files implementation
|
||||||
|
- `src/header/*` - Each folder has a `cbindgen.toml` file, it generates a C-to-Rust interface and header files
|
||||||
|
- `src/ld_so` - Dynamic loader code
|
||||||
|
- `src/platform` - Platform-specific and common code
|
||||||
|
- `src/platform/redox` - Redox-specific code
|
||||||
|
- `src/platform/linux` - Linux-specific code
|
||||||
|
- `src/pthread` - pthread implementation
|
||||||
|
- `src/sync` - Synchronization primitives
|
||||||
|
- `tests` - C tests (each MR needs to give success in all of them)
|
||||||
|
|
||||||
|
## Download the sources
|
||||||
|
|
||||||
|
To download the relibc sources run the following command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
cargo doc --open --target x86_64-unknown-none
|
git clone --recursive https://gitlab.redox-os.org/redox-os/relibc
|
||||||
```
|
```
|
||||||
|
|
||||||
## Debugging
|
## Build Instructions
|
||||||
|
|
||||||
### QEMU
|
To build relibc out of the Redox build system, do the following steps:
|
||||||
|
|
||||||
Running [QEMU](https://www.qemu.org) with the `-s` flag will set up QEMU to listen on port `1234` for a GDB client to connect to it. To debug the redox kernel run.
|
### Dependencies
|
||||||
|
|
||||||
|
- Install `cbindgen`
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
make qemu gdb=yes
|
cargo install cbindgen
|
||||||
```
|
```
|
||||||
|
|
||||||
This will start a virtual machine with and listen on port `1234` for a GDB or LLDB client.
|
#### Install the `expect` tool
|
||||||
|
|
||||||
### GDB
|
- Debian, Ubuntu and PopOS:
|
||||||
|
|
||||||
If you are going to use [GDB](https://www.gnu.org/software/gdb/), run these commands to load debug symbols and connect to your running kernel:
|
```sh
|
||||||
|
sudo apt install expect
|
||||||
```
|
|
||||||
(gdb) symbol-file build/kernel.sym
|
|
||||||
(gdb) target remote localhost:1234
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### LLDB
|
- Fedora:
|
||||||
|
|
||||||
If you are going to use [LLDB](https://lldb.llvm.org/), run these commands to start debugging:
|
```sh
|
||||||
|
sudo dnf install expect
|
||||||
```
|
|
||||||
(lldb) target create -s build/kernel.sym build/kernel
|
|
||||||
(lldb) gdb-remote localhost:1234
|
|
||||||
```
|
```
|
||||||
|
|
||||||
After connecting to your kernel you can set some interesting breakpoints and `continue`
|
- Arch Linux:
|
||||||
the process. See your debuggers man page for more information on useful commands to run.
|
|
||||||
|
|
||||||
## Notes
|
```sh
|
||||||
|
sudo pacman -S expect
|
||||||
|
```
|
||||||
|
|
||||||
- Always use `foo.get(n)` instead of `foo[n]` and try to cover for the possibility of `Option::None`. Doing the regular way may work fine for applications, but never in the kernel. No possible panics should ever exist in kernel space, because then the whole OS would just stop working.
|
### Build Relibc
|
||||||
|
|
||||||
- If you receive a kernel panic in QEMU, use `pkill qemu-system` to kill the frozen QEMU process.
|
To build the relibc library objects, run the following command:
|
||||||
|
|
||||||
## How To Contribute
|
```sh
|
||||||
|
make all
|
||||||
|
```
|
||||||
|
|
||||||
To learn how to contribute to this system component you need to read the following document:
|
- Clean old library objects and tests
|
||||||
|
|
||||||
- [CONTRIBUTING.md](https://gitlab.redox-os.org/redox-os/redox/-/blob/master/CONTRIBUTING.md)
|
```sh
|
||||||
|
make clean
|
||||||
|
```
|
||||||
|
|
||||||
## Development
|
## Build relibc inside the Redox build system
|
||||||
|
|
||||||
To learn how to do development with this system component inside the Redox build system you need to read the [Build System](https://doc.redox-os.org/book/build-system-reference.html) and [Coding and Building](https://doc.redox-os.org/book/coding-and-building.html) pages.
|
Inside of your Redox build system, run:
|
||||||
|
|
||||||
### How To Build
|
```sh
|
||||||
|
make prefix
|
||||||
|
```
|
||||||
|
|
||||||
To build this system component you need to download the Redox build system, you can learn how to do it on the [Building Redox](https://doc.redox-os.org/book/podman-build.html) page.
|
If you need to rebuild `relibc` for testing a Cookbook recipe, run:
|
||||||
|
|
||||||
This is necessary because they only work with cross-compilation to a Redox virtual machine, but you can do some testing from Linux.
|
```sh
|
||||||
|
touch relibc
|
||||||
|
make prefix r.recipe-name
|
||||||
|
```
|
||||||
|
|
||||||
|
Touching (changing the "last modified time" of) the `relibc` folder is needed to trigger recompilation for `make prefix`. Replace `recipe-name` with your desired recipe name.
|
||||||
|
|
||||||
|
Note: Do not edit `relibc` inside `prefix` folder! Do your work on `relibc` folder directly inside your Redox build system instead.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
Relibc has a test suite that also runs every time a new commit get pushed. You can see `.gitlab-ci.yml` to see how it's being executed. That being said, `./check.sh` is the recommended way to run tests. Here's few examples:
|
||||||
|
|
||||||
|
+ `./check.sh` - Run build, without running the test
|
||||||
|
+ `./check.sh --test` - Run all tests in x86_64 Redox using Redoxer
|
||||||
|
+ `./check.sh --test --host` - Run all tests in host (Linux)
|
||||||
|
+ `./check.sh --test --arch=aarch64` - Run all tests in specified arch
|
||||||
|
- Arch can be `x86_64`, `aarch64`, `i586`, or `riscv64gc`
|
||||||
|
+ `./check.sh --test=stdio/printf` - Run a single test
|
||||||
|
- Can be combined with `--host` or `--arch`
|
||||||
|
- Will run statically linked test in Linux, dynamically linked in Redox
|
||||||
|
|
||||||
|
Couple of notes:
|
||||||
|
|
||||||
|
- Relibc and its tests will rebuild if files changed, however switching between arch or host requires you to run `make clean`
|
||||||
|
- Redoxer is needed to run tests for Redox without `--host`. You can install it using `cargo install redoxer`
|
||||||
|
- Tests can hangs, the test runner can anticipate this, assuming the kernel doesn't hang too.
|
||||||
|
|
||||||
|
## Issues
|
||||||
|
|
||||||
|
#### I'm building for my own platform which I run, and am getting `x86_64-linux-gnu-ar: command not found` (or similar)
|
||||||
|
|
||||||
|
The Makefile expects GNU compiler tools prefixed with the platform specifier, as would be present when you installed a cross compiler. Since you are building for your own platform, some Linux distributions (like Manjaro) don't install/symlink the prefixed executables.
|
||||||
|
|
||||||
|
An easy fix would be to replace the corresponding lines in `config.mk`, e.g.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
ifeq ($(TARGET),x86_64-unknown-linux-gnu)
|
||||||
|
- export CC=x86_64-linux-gnu-gcc
|
||||||
|
- export LD=x86_64-linux-gnu-ld
|
||||||
|
- export AR=x86_64-linux-gnu-ar
|
||||||
|
- export NM=x86_64-linux-gnu-nm
|
||||||
|
+ export CC=gcc
|
||||||
|
+ export LD=ld
|
||||||
|
+ export AR=ar
|
||||||
|
+ export NM=nm
|
||||||
|
export OBJCOPY=objcopy
|
||||||
|
export CPPFLAGS=
|
||||||
|
LD_SO_PATH=lib/ld64.so.1
|
||||||
|
endif
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Before starting to contribute, read [this](CONTRIBUTING.md) document.
|
||||||
|
|
||||||
|
## Supported OSes
|
||||||
|
|
||||||
|
- Redox OS
|
||||||
|
- Linux
|
||||||
|
|
||||||
|
## Supported architectures
|
||||||
|
|
||||||
|
- i586 (Intel/AMD)
|
||||||
|
- x86_64 (Intel/AMD)
|
||||||
|
- aarch64 (ARM64)
|
||||||
|
- riscv64gc (RISC-V)
|
||||||
|
|
||||||
## Funding - _Unix-style Signals and Process Management_
|
## Funding - _Unix-style Signals and Process Management_
|
||||||
|
|
||||||
|
|||||||
@@ -1,100 +1,30 @@
|
|||||||
#![allow(clippy::unwrap_used)] // the build script can panic
|
extern crate cc;
|
||||||
|
|
||||||
use std::{env, path::Path, process::Command};
|
use std::{env, fs};
|
||||||
use toml::Table;
|
|
||||||
|
|
||||||
fn parse_kconfig(arch: &str) -> Option<()> {
|
|
||||||
println!("cargo:rerun-if-changed=config.toml");
|
|
||||||
|
|
||||||
assert!(Path::new("config.toml.example").try_exists().unwrap());
|
|
||||||
if !Path::new("config.toml").try_exists().unwrap() {
|
|
||||||
std::fs::copy("config.toml.example", "config.toml").unwrap();
|
|
||||||
}
|
|
||||||
let config_str = std::fs::read_to_string("config.toml").unwrap();
|
|
||||||
let root: Table = toml::from_str(&config_str).unwrap();
|
|
||||||
|
|
||||||
let altfeatures = root
|
|
||||||
.get("arch")?
|
|
||||||
.as_table()
|
|
||||||
.unwrap()
|
|
||||||
.get(arch)?
|
|
||||||
.as_table()
|
|
||||||
.unwrap()
|
|
||||||
.get("features")?
|
|
||||||
.as_table()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
#[expect(clippy::format_collect)] // TODO: remove once version is bumped
|
|
||||||
let features_list = altfeatures
|
|
||||||
.keys()
|
|
||||||
.map(|feat| format!(", {feat:?}"))
|
|
||||||
.collect::<String>();
|
|
||||||
println!("cargo::rustc-check-cfg=cfg(cpu_feature_always, values(\"\"{features_list}))");
|
|
||||||
println!("cargo::rustc-check-cfg=cfg(cpu_feature_auto, values(\"\"{features_list}))");
|
|
||||||
println!("cargo::rustc-check-cfg=cfg(cpu_feature_never, values(\"\"{features_list}))");
|
|
||||||
|
|
||||||
let self_modifying = env::var("CARGO_FEATURE_SELF_MODIFYING").is_ok();
|
|
||||||
|
|
||||||
for (name, value) in altfeatures {
|
|
||||||
let mut choice = value.as_str().unwrap();
|
|
||||||
assert!(matches!(choice, "always" | "never" | "auto"));
|
|
||||||
|
|
||||||
if !self_modifying && choice == "auto" {
|
|
||||||
choice = "never";
|
|
||||||
}
|
|
||||||
|
|
||||||
println!("cargo:rustc-cfg=cpu_feature_{choice}=\"{name}\"");
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
println!("cargo::rustc-env=TARGET={}", env::var("TARGET").unwrap());
|
let _crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
|
||||||
println!("cargo::rustc-check-cfg=cfg(dtb)");
|
let target = env::var("TARGET").unwrap();
|
||||||
|
|
||||||
let out_dir = env::var("OUT_DIR").unwrap();
|
println!("cargo:rerun-if-changed=src/c");
|
||||||
let arch_str = env::var("CARGO_CFG_TARGET_ARCH").unwrap();
|
|
||||||
|
|
||||||
match &*arch_str {
|
let mut cc_builder = &mut cc::Build::new();
|
||||||
"aarch64" => {
|
|
||||||
println!("cargo::rustc-cfg=dtb");
|
|
||||||
}
|
|
||||||
"x86" => {
|
|
||||||
println!("cargo::rerun-if-changed=src/asm/x86/trampoline.asm");
|
|
||||||
|
|
||||||
let status = Command::new("nasm")
|
cc_builder = cc_builder.flag("-nostdinc").flag("-nostdlib");
|
||||||
.arg("-f")
|
|
||||||
.arg("bin")
|
|
||||||
.arg("-o")
|
|
||||||
.arg(format!("{}/trampoline", out_dir))
|
|
||||||
.arg("src/asm/x86/trampoline.asm")
|
|
||||||
.status()
|
|
||||||
.expect("failed to run nasm");
|
|
||||||
if !status.success() {
|
|
||||||
panic!("nasm failed with exit status {}", status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"x86_64" => {
|
|
||||||
println!("cargo::rerun-if-changed=src/asm/x86_64/trampoline.asm");
|
|
||||||
|
|
||||||
let status = Command::new("nasm")
|
if target.starts_with("aarch64") {
|
||||||
.arg("-f")
|
cc_builder = cc_builder.flag("-mno-outline-atomics")
|
||||||
.arg("bin")
|
|
||||||
.arg("-o")
|
|
||||||
.arg(format!("{}/trampoline", out_dir))
|
|
||||||
.arg("src/asm/x86_64/trampoline.asm")
|
|
||||||
.status()
|
|
||||||
.expect("failed to run nasm");
|
|
||||||
if !status.success() {
|
|
||||||
panic!("nasm failed with exit status {}", status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"riscv64" => {
|
|
||||||
println!("cargo::rustc-cfg=dtb");
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let _ = parse_kconfig(&arch_str);
|
cc_builder
|
||||||
|
.flag("-fno-stack-protector")
|
||||||
|
.flag("-Wno-expansion-to-defined")
|
||||||
|
.files(
|
||||||
|
fs::read_dir("src/c")
|
||||||
|
.expect("src/c directory missing")
|
||||||
|
.map(|res| res.expect("read_dir error").path()),
|
||||||
|
)
|
||||||
|
.compile("relibc_c");
|
||||||
|
|
||||||
|
println!("cargo:rustc-link-lib=static=relibc_c");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
|
||||||
|
# needs a leading newline
|
||||||
|
[defines]
|
||||||
|
"target_os=redox" = "__redox__"
|
||||||
|
"target_os=linux" = "__linux__"
|
||||||
|
"target_pointer_width=64" = "__LP64__"
|
||||||
|
"target_pointer_width=32" = "__ILP32__"
|
||||||
|
"target_arch=x86" = "__i386__"
|
||||||
|
"target_arch=x86_64" = "__x86_64__"
|
||||||
|
"target_arch=aarch64" = "__aarch64__"
|
||||||
|
# This is not exact. It should be `defined(__riscv) && defined(__LP64__)`, or `defined(__riscv) && __riscv_xlen==64`
|
||||||
|
# This will do however, as long as we only support riscv64 and not riscv32
|
||||||
|
"target_arch=riscv64" = "__riscv"
|
||||||
|
|
||||||
|
# XXX: silences a warning
|
||||||
|
"feature = no_std" = "__relibc__"
|
||||||
|
|
||||||
|
# Ensure attributes are passed down from Rust
|
||||||
|
# <features.h> must be included where attributes are used in relibc
|
||||||
|
[fn]
|
||||||
|
must_use = "__nodiscard"
|
||||||
|
deprecated = "__deprecated"
|
||||||
|
deprecated_with_note = "__deprecatedNote({})"
|
||||||
|
no_return = "__noreturn"
|
||||||
@@ -0,0 +1,168 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
RED='\033[1;38;5;196m'
|
||||||
|
GREEN='\033[1;38;5;46m'
|
||||||
|
NC='\033[0m'
|
||||||
|
|
||||||
|
show_help() {
|
||||||
|
echo "Usage: $(basename "$0") [OPTIONS]"
|
||||||
|
echo ""
|
||||||
|
echo "Description:"
|
||||||
|
echo " Wrapper for Makefile / Cargo to run checks or tests on Redox OS targets."
|
||||||
|
echo ""
|
||||||
|
echo "Options:"
|
||||||
|
echo " --test Run 'make test' instead of 'make all'"
|
||||||
|
echo " --test= Run single 'make test'"
|
||||||
|
echo " --cargo Run 'cargo check' / 'cargo test' instead"
|
||||||
|
echo " (note: cargo test is currently not maintained for relibc)"
|
||||||
|
echo " --host Run the command on host (linux) target"
|
||||||
|
echo " --all-target Run the command on all supported Redox architectures"
|
||||||
|
echo " --target=<target> Override the target architecture (e.g., i586-unknown-redox)"
|
||||||
|
echo " --arch=<arch> Override the target architecture using arch (e.g., i586)"
|
||||||
|
echo " --help Show this help message"
|
||||||
|
echo ""
|
||||||
|
echo "Supported Targets:"
|
||||||
|
for t in "${SUPPORTED_TARGETS[@]}"; do
|
||||||
|
echo " - $t"
|
||||||
|
done
|
||||||
|
echo " - $(uname -m)-unknown-linux-gnu"
|
||||||
|
echo ""
|
||||||
|
echo "Environment:"
|
||||||
|
echo " TARGET Sets the default target (overridden by --target)"
|
||||||
|
}
|
||||||
|
|
||||||
|
if ! command -v cbindgen &> /dev/null; then
|
||||||
|
echo "Error: 'cbindgen' CLI not found."
|
||||||
|
echo "Please install it: cargo install cbindgen"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
SUPPORTED_TARGETS=(
|
||||||
|
"x86_64-unknown-redox"
|
||||||
|
"i586-unknown-redox"
|
||||||
|
"aarch64-unknown-redox"
|
||||||
|
"riscv64gc-unknown-redox"
|
||||||
|
)
|
||||||
|
|
||||||
|
CURRENT_TARGET="${TARGET:-x86_64-unknown-redox}"
|
||||||
|
CHECK_ALL=false
|
||||||
|
CMD_ACTION="make"
|
||||||
|
CARGO_ACTION="check"
|
||||||
|
MAKE_ACTION="all"
|
||||||
|
TEST_BIN=""
|
||||||
|
IS_HOST=0
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
--all-target)
|
||||||
|
CHECK_ALL=true
|
||||||
|
;;
|
||||||
|
--test)
|
||||||
|
MAKE_ACTION="test"
|
||||||
|
CARGO_ACTION="test"
|
||||||
|
;;
|
||||||
|
--test=*)
|
||||||
|
TEST_BIN="${1#*=}"
|
||||||
|
MAKE_ACTION="test-once"
|
||||||
|
;;
|
||||||
|
--cargo)
|
||||||
|
CMD_ACTION="cargo"
|
||||||
|
;;
|
||||||
|
--host)
|
||||||
|
CURRENT_TARGET="$(uname -m)-unknown-linux-gnu"
|
||||||
|
IS_HOST=1
|
||||||
|
;;
|
||||||
|
--target=*)
|
||||||
|
CURRENT_TARGET="${1#*=}"
|
||||||
|
;;
|
||||||
|
--arch=*)
|
||||||
|
CURRENT_TARGET="${1#*=}-unknown-redox"
|
||||||
|
;;
|
||||||
|
--help)
|
||||||
|
show_help
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo -e "${RED}Error: Unknown option '$1'${NC}"
|
||||||
|
show_help
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
shift
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$IS_HOST" -eq 0 ]; then
|
||||||
|
if ! command -v redoxer &> /dev/null; then
|
||||||
|
echo "Error: 'redoxer' CLI not found."
|
||||||
|
echo "Please install it: cargo install redoxer"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
run_redoxer() {
|
||||||
|
export TARGET=$1
|
||||||
|
REDOXER_ENV="redoxer env"
|
||||||
|
if [ "$IS_HOST" -eq 0 ]; then
|
||||||
|
redoxer toolchain || { echo -e "${RED}Fail: redoxer toolchain for: $target.${NC}" && exit 1; }
|
||||||
|
export CARGO_TEST="redoxer"
|
||||||
|
export TEST_RUNNER="redoxer exec --folder ../../sysroot/$TARGET/:/usr --folder . --"
|
||||||
|
# TODO: Identify hang issue with pthread/barrier and pthread/once tests in multi core to get rid of this limit
|
||||||
|
export REDOXER_QEMU_ARGS="-smp 1"
|
||||||
|
|
||||||
|
MAKE_ACTION="$MAKE_ACTION IS_REDOX=1"
|
||||||
|
else
|
||||||
|
REDOXER_ENV=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$TEST_BIN" != "" ]; then
|
||||||
|
if [ "$IS_HOST" -eq 0 ]; then
|
||||||
|
MAKE_ACTION="$MAKE_ACTION TESTBIN=bins_dynamic/$TEST_BIN"
|
||||||
|
else
|
||||||
|
MAKE_ACTION="$MAKE_ACTION TESTBIN=bins_static/$TEST_BIN"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$CMD_ACTION" == "make" ]; then
|
||||||
|
CMD_OPT="-j $(nproc) $MAKE_ACTION"
|
||||||
|
else
|
||||||
|
CMD_OPT="$CARGO_ACTION"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "----------------------------------------"
|
||||||
|
echo "Running $REDOXER_ENV $CMD_ACTION $CMD_OPT for: $TARGET"
|
||||||
|
|
||||||
|
if $REDOXER_ENV $CMD_ACTION $CMD_OPT; then
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
echo -e "${RED}Fail: $CMD_ACTION $CMD_OPT for $TARGET failed.${NC}"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ "$CHECK_ALL" = true ]; then
|
||||||
|
echo "Running $CMD_ACTION for all supported Redox targets..."
|
||||||
|
|
||||||
|
has_error=false
|
||||||
|
|
||||||
|
for target in "${SUPPORTED_TARGETS[@]}"; do
|
||||||
|
if ! run_redoxer "$target"; then
|
||||||
|
has_error=true
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "----------------------------------------"
|
||||||
|
if [ "$has_error" = true ]; then
|
||||||
|
echo -e "${RED}Summary: One or more targets failed.${NC}"
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
echo -e "${GREEN}Summary: All targets passed!${NC}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if run_redoxer "$CURRENT_TARGET"; then
|
||||||
|
echo -e "${GREEN}Success: $CARGO_ACTION for $CURRENT_TARGET passed.${NC}"
|
||||||
|
exit 0
|
||||||
|
else
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
export RUST_TARGET_PATH="${PWD}/targets"
|
|
||||||
export RUSTFLAGS="-C debuginfo=2"
|
|
||||||
cargo clippy --lib --release --target x86_64-unknown-none "$@"
|
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
ifndef TARGET
|
||||||
|
export TARGET:=$(shell rustc -Z unstable-options --print target-spec-json | grep llvm-target | cut -d '"' -f4)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET),aarch64-unknown-linux-gnu)
|
||||||
|
export CC=aarch64-linux-gnu-gcc
|
||||||
|
export LD=aarch64-linux-gnu-ld
|
||||||
|
export AR=aarch64-linux-gnu-ar
|
||||||
|
export NM=aarch64-linux-gnu-nm
|
||||||
|
export OBJCOPY=aarch64-linux-gnu-objcopy
|
||||||
|
export CPPFLAGS=
|
||||||
|
LD_SO_PATH=lib/ld.so.1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET),aarch64-unknown-redox)
|
||||||
|
export CC=aarch64-unknown-redox-gcc
|
||||||
|
export LD=aarch64-unknown-redox-ld
|
||||||
|
export AR=aarch64-unknown-redox-ar
|
||||||
|
export NM=aarch64-unknown-redox-nm
|
||||||
|
export OBJCOPY=aarch64-unknown-redox-objcopy
|
||||||
|
export CPPFLAGS=
|
||||||
|
LD_SO_PATH=lib/ld.so.1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET),i586-unknown-redox)
|
||||||
|
export CC=i586-unknown-redox-gcc
|
||||||
|
export LD=i586-unknown-redox-ld
|
||||||
|
export AR=i586-unknown-redox-ar
|
||||||
|
export NM=i586-unknown-redox-nm
|
||||||
|
export OBJCOPY=i586-unknown-redox-objcopy
|
||||||
|
export CPPFLAGS=
|
||||||
|
LD_SO_PATH=lib/libc.so.1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET),i686-unknown-redox)
|
||||||
|
export CC=i686-unknown-redox-gcc
|
||||||
|
export LD=i686-unknown-redox-ld
|
||||||
|
export AR=i686-unknown-redox-ar
|
||||||
|
export NM=i686-unknown-redox-nm
|
||||||
|
export OBJCOPY=i686-unknown-redox-objcopy
|
||||||
|
export CPPFLAGS=
|
||||||
|
LD_SO_PATH=lib/libc.so.1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET),x86_64-unknown-linux-gnu)
|
||||||
|
export CC=x86_64-linux-gnu-gcc
|
||||||
|
export LD=x86_64-linux-gnu-ld
|
||||||
|
export AR=x86_64-linux-gnu-ar
|
||||||
|
export NM=x86_64-linux-gnu-nm
|
||||||
|
export OBJCOPY=objcopy
|
||||||
|
export CPPFLAGS=
|
||||||
|
LD_SO_PATH=lib/ld64.so.1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET),x86_64-unknown-redox)
|
||||||
|
export CC=x86_64-unknown-redox-gcc
|
||||||
|
export LD=x86_64-unknown-redox-ld
|
||||||
|
export AR=x86_64-unknown-redox-ar
|
||||||
|
export NM=x86_64-unknown-redox-nm
|
||||||
|
export OBJCOPY=x86_64-unknown-redox-objcopy
|
||||||
|
export CPPFLAGS=
|
||||||
|
LD_SO_PATH=lib/ld64.so.1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(TARGET),riscv64gc-unknown-redox)
|
||||||
|
export CC=riscv64-unknown-redox-gcc
|
||||||
|
export LD=riscv64-unknown-redox-ld
|
||||||
|
export AR=riscv64-unknown-redox-ar
|
||||||
|
export NM=riscv64-unknown-redox-nm
|
||||||
|
export OBJCOPY=riscv64-unknown-redox-objcopy
|
||||||
|
export CPPFLAGS=-march=rv64gc -mabi=lp64d
|
||||||
|
LD_SO_PATH=lib/ld.so.1
|
||||||
|
endif
|
||||||
@@ -1,7 +0,0 @@
|
|||||||
[arch.x86_64.features]
|
|
||||||
smap = "auto"
|
|
||||||
fsgsbase = "auto"
|
|
||||||
xsave = "auto"
|
|
||||||
xsaveopt = "auto"
|
|
||||||
|
|
||||||
# vim: ft=toml
|
|
||||||
+117
@@ -0,0 +1,117 @@
|
|||||||
|
name: CI
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
name: Test
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: ubuntu-latest
|
||||||
|
rust: stable
|
||||||
|
- os: ubuntu-latest
|
||||||
|
rust: beta
|
||||||
|
- os: ubuntu-latest
|
||||||
|
rust: nightly
|
||||||
|
- os: macos-latest
|
||||||
|
rust: stable
|
||||||
|
- os: windows-latest
|
||||||
|
rust: stable
|
||||||
|
- os: ubuntu-latest
|
||||||
|
rust: stable
|
||||||
|
target: wasm32-wasip1
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- run: rustup update ${{ matrix.rust }} --no-self-update && rustup default ${{ matrix.rust }}
|
||||||
|
shell: bash
|
||||||
|
|
||||||
|
# Configure cross-builds by adding the rustup target and configuring future
|
||||||
|
# cargo invocations.
|
||||||
|
- run: |
|
||||||
|
rustup target add ${{ matrix.target }}
|
||||||
|
echo CARGO_BUILD_TARGET=${{ matrix.target }} >> $GITHUB_ENV
|
||||||
|
if: matrix.target != ''
|
||||||
|
|
||||||
|
# For wasm install wasmtime as a test runner and configure it with Cargo.
|
||||||
|
- name: Setup `wasmtime`
|
||||||
|
uses: bytecodealliance/actions/wasmtime/setup@v1
|
||||||
|
if: matrix.target == 'wasm32-wasip1'
|
||||||
|
- run: echo CARGO_TARGET_WASM32_WASIP1_RUNNER=wasmtime >> $GITHUB_ENV
|
||||||
|
if: matrix.target == 'wasm32-wasip1'
|
||||||
|
|
||||||
|
- run: cargo test
|
||||||
|
- run: cargo test --features debug
|
||||||
|
- run: cargo test --features global
|
||||||
|
- run: cargo test --release
|
||||||
|
env:
|
||||||
|
CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS: true
|
||||||
|
- run: cargo test --release
|
||||||
|
env:
|
||||||
|
CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS: false
|
||||||
|
- run: cargo test --features debug --release
|
||||||
|
env:
|
||||||
|
CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS: true
|
||||||
|
- run: RUSTFLAGS='--cfg test_lots' cargo test --release
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS: true
|
||||||
|
- run: RUSTFLAGS='--cfg test_lots' cargo test --release --features debug
|
||||||
|
shell: bash
|
||||||
|
env:
|
||||||
|
CARGO_PROFILE_RELEASE_DEBUG_ASSERTIONS: true
|
||||||
|
|
||||||
|
rustfmt:
|
||||||
|
name: Rustfmt
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install Rust
|
||||||
|
run: rustup update stable && rustup default stable && rustup component add rustfmt
|
||||||
|
- run: cargo fmt -- --check
|
||||||
|
|
||||||
|
wasm:
|
||||||
|
name: WebAssembly
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install Rust
|
||||||
|
run: rustup update stable && rustup default stable && rustup target add wasm32-unknown-unknown
|
||||||
|
- run: cargo build --target wasm32-unknown-unknown
|
||||||
|
- run: cargo build --target wasm32-unknown-unknown --release
|
||||||
|
|
||||||
|
external-platform:
|
||||||
|
name: external-platform
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install Rust
|
||||||
|
run: rustup update stable && rustup default stable && rustup target add x86_64-fortanix-unknown-sgx
|
||||||
|
- run: cargo build --target x86_64-fortanix-unknown-sgx
|
||||||
|
|
||||||
|
fuzz:
|
||||||
|
name: Build Fuzzers
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install Rust
|
||||||
|
run: rustup update nightly && rustup default nightly
|
||||||
|
- run: cargo install cargo-fuzz
|
||||||
|
- run: cargo fuzz build --dev
|
||||||
|
|
||||||
|
miri:
|
||||||
|
name: Miri
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Install Miri
|
||||||
|
run: |
|
||||||
|
rustup toolchain install nightly --component miri
|
||||||
|
rustup override set nightly
|
||||||
|
cargo miri setup
|
||||||
|
- name: Test with Miri Stack Borrows
|
||||||
|
run: cargo miri test
|
||||||
|
- name: Test with Miri Tree Borrows
|
||||||
|
run: cargo miri test
|
||||||
|
env:
|
||||||
|
MIRIFLAGS: -Zmiri-tree-borrows
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
/target/
|
||||||
|
**/*.rs.bk
|
||||||
|
Cargo.lock
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
[package]
|
||||||
|
name = "dlmalloc"
|
||||||
|
version = "0.2.8"
|
||||||
|
authors = ["Alex Crichton <alex@alexcrichton.com>"]
|
||||||
|
license = "MIT/Apache-2.0"
|
||||||
|
readme = "README.md"
|
||||||
|
repository = "https://github.com/alexcrichton/dlmalloc-rs"
|
||||||
|
homepage = "https://github.com/alexcrichton/dlmalloc-rs"
|
||||||
|
documentation = "https://docs.rs/dlmalloc"
|
||||||
|
description = """
|
||||||
|
A Rust port of the dlmalloc allocator
|
||||||
|
"""
|
||||||
|
edition.workspace = true
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
members = ['fuzz']
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
edition = '2021'
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
features = ['global']
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
doctest = false
|
||||||
|
|
||||||
|
[target.'cfg(all(unix, not(target_arch = "wasm32")))'.dependencies]
|
||||||
|
libc = { version = "0.2", default-features = false, optional = true }
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
# For more information on these dependencies see rust-lang/rust's
|
||||||
|
# `src/tools/rustc-std-workspace` folder
|
||||||
|
core = { version = '1.0.0', optional = true, package = 'rustc-std-workspace-core' }
|
||||||
|
compiler_builtins = { version = '0.1.0', optional = true }
|
||||||
|
cfg-if = "1.0"
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "windows")'.dependencies.windows-sys]
|
||||||
|
version = ">=0.52.0, <=0.59.*"
|
||||||
|
features = [
|
||||||
|
"Win32_Foundation",
|
||||||
|
"Win32_System_Memory",
|
||||||
|
"Win32_System_Threading",
|
||||||
|
"Win32_System_SystemInformation",
|
||||||
|
]
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
arbitrary = "1.3.2"
|
||||||
|
rand = { version = "0.8", features = ['small_rng'] }
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug-assertions = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# Enable implementations of the `GlobalAlloc` standard library API, exporting a
|
||||||
|
# new `GlobalDlmalloc` as well which implements this trait.
|
||||||
|
global = ["system", "rust_api"]
|
||||||
|
|
||||||
|
# Enable very expensive debug checks in this crate
|
||||||
|
debug = []
|
||||||
|
|
||||||
|
# Enables OS APIs based on the current target, can be implemented manually
|
||||||
|
# otherwise.
|
||||||
|
system = ["libc"]
|
||||||
|
|
||||||
|
rustc-dep-of-std = ['core', 'compiler_builtins/rustc-dep-of-std']
|
||||||
|
|
||||||
|
c_api = []
|
||||||
|
rust_api = []
|
||||||
|
|
||||||
|
default = ["global", "rust_api"]
|
||||||
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [yyyy] [name of copyright owner]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
Copyright (c) 2014 Alex Crichton
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any
|
||||||
|
person obtaining a copy of this software and associated
|
||||||
|
documentation files (the "Software"), to deal in the
|
||||||
|
Software without restriction, including without
|
||||||
|
limitation the rights to use, copy, modify, merge,
|
||||||
|
publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software
|
||||||
|
is furnished to do so, subject to the following
|
||||||
|
conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice
|
||||||
|
shall be included in all copies or substantial portions
|
||||||
|
of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||||
|
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||||
|
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||||
|
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||||
|
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
# dlmalloc-rs
|
||||||
|
|
||||||
|
A port of [dlmalloc] to Rust.
|
||||||
|
|
||||||
|
[Documentation](https://docs.rs/dlmalloc)
|
||||||
|
|
||||||
|
[dlmalloc]: https://gee.cs.oswego.edu/dl/html/malloc.html
|
||||||
|
|
||||||
|
## Why dlmalloc?
|
||||||
|
|
||||||
|
This crate is a port of [dlmalloc] to Rust, and doesn't rely on C. The primary
|
||||||
|
purpose of this crate is to serve as the default allocator for Rust on the
|
||||||
|
`wasm32-unknown-unknown` target. At the time this was written the wasm target
|
||||||
|
didn't support C code, so it was required to have a Rust-only solution.
|
||||||
|
|
||||||
|
This allocator is not the most performant by a longshot. It is primarily, I
|
||||||
|
think, intended for being easy to port and easy to learn. I didn't dive too deep
|
||||||
|
into the implementation when writing it, it's just a straight port of the C
|
||||||
|
version.
|
||||||
|
|
||||||
|
It's unlikely that Rust code needs to worry/interact with this allocator in
|
||||||
|
general. Most of the time you'll be manually switching to a different allocator
|
||||||
|
:)
|
||||||
|
|
||||||
|
# License
|
||||||
|
|
||||||
|
This project is licensed under either of
|
||||||
|
|
||||||
|
* Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
* MIT license ([LICENSE-MIT](LICENSE-MIT) or
|
||||||
|
http://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
at your option.
|
||||||
|
|
||||||
|
### Contribution
|
||||||
|
|
||||||
|
Unless you explicitly state otherwise, any contribution intentionally submitted
|
||||||
|
for inclusion in this project by you, as defined in the Apache-2.0 license,
|
||||||
|
shall be dual licensed as above, without any additional terms or conditions.
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
corpus
|
||||||
|
artifacts
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
[package]
|
||||||
|
name = "dlmalloc-fuzz"
|
||||||
|
version = "0.0.1"
|
||||||
|
publish = false
|
||||||
|
edition.workspace = true
|
||||||
|
|
||||||
|
[package.metadata]
|
||||||
|
cargo-fuzz = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
arbitrary = "1.3.2"
|
||||||
|
dlmalloc = { path = '..' }
|
||||||
|
libfuzzer-sys = "0.4.7"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "alloc"
|
||||||
|
path = "fuzz_targets/alloc.rs"
|
||||||
|
test = false
|
||||||
|
bench = false
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
#![no_main]
|
||||||
|
|
||||||
|
use arbitrary::Unstructured;
|
||||||
|
use libfuzzer_sys::fuzz_target;
|
||||||
|
|
||||||
|
fuzz_target!(|bytes: &[u8]| {
|
||||||
|
let _ = dlmalloc_fuzz::run(&mut Unstructured::new(bytes));
|
||||||
|
});
|
||||||
@@ -0,0 +1,108 @@
|
|||||||
|
use arbitrary::{Result, Unstructured};
|
||||||
|
use dlmalloc::Dlmalloc;
|
||||||
|
use std::cmp;
|
||||||
|
|
||||||
|
const MAX_ALLOCATED: usize = 100 << 20; // 100 MB
|
||||||
|
|
||||||
|
pub fn run(u: &mut Unstructured<'_>) -> Result<()> {
|
||||||
|
let mut a = Dlmalloc::new();
|
||||||
|
let mut ptrs = Vec::new();
|
||||||
|
let mut allocated = 0;
|
||||||
|
unsafe {
|
||||||
|
while u.arbitrary()? {
|
||||||
|
// If there are pointers to free then have a chance of deallocating
|
||||||
|
// a pointer. Try not to deallocate things until there's a "large"
|
||||||
|
// working set but afterwards give it a 50/50 chance of allocating
|
||||||
|
// or deallocating.
|
||||||
|
let free = match ptrs.len() {
|
||||||
|
0 => false,
|
||||||
|
0..=10_000 => u.ratio(1, 3)?,
|
||||||
|
_ => u.arbitrary()?,
|
||||||
|
};
|
||||||
|
if free {
|
||||||
|
let idx = u.choose_index(ptrs.len())?;
|
||||||
|
let (ptr, size, align) = ptrs.swap_remove(idx);
|
||||||
|
allocated -= size;
|
||||||
|
a.free(ptr, size, align);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1/100 chance of reallocating a pointer to a different size.
|
||||||
|
if ptrs.len() > 0 && u.ratio(1, 100)? {
|
||||||
|
let idx = u.choose_index(ptrs.len())?;
|
||||||
|
let (ptr, size, align) = ptrs.swap_remove(idx);
|
||||||
|
|
||||||
|
// Arbitrarily choose whether to make this allocation either
|
||||||
|
// twice as large or half as small.
|
||||||
|
let new_size = if u.arbitrary()? {
|
||||||
|
u.int_in_range(size..=size * 2)?
|
||||||
|
} else if size > 10 {
|
||||||
|
u.int_in_range(size / 2..=size)?
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
if allocated + new_size - size > MAX_ALLOCATED {
|
||||||
|
ptrs.push((ptr, size, align));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
allocated -= size;
|
||||||
|
allocated += new_size;
|
||||||
|
|
||||||
|
// Perform the `realloc` and assert that all bytes were copied.
|
||||||
|
let mut tmp = Vec::new();
|
||||||
|
for i in 0..cmp::min(size, new_size) {
|
||||||
|
tmp.push(*ptr.offset(i as isize));
|
||||||
|
}
|
||||||
|
let ptr = a.realloc(ptr, size, align, new_size);
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
for (i, byte) in tmp.iter().enumerate() {
|
||||||
|
assert_eq!(*byte, *ptr.offset(i as isize));
|
||||||
|
}
|
||||||
|
ptrs.push((ptr, new_size, align));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aribtrarily choose a size to allocate as well as an alignment.
|
||||||
|
// Enable small sizes with standard alignment happening a fair bit.
|
||||||
|
let size = if u.arbitrary()? {
|
||||||
|
u.int_in_range(1..=128)?
|
||||||
|
} else {
|
||||||
|
u.int_in_range(1..=128 * 1024)?
|
||||||
|
};
|
||||||
|
let align = if u.ratio(1, 10)? {
|
||||||
|
1 << u.int_in_range(3..=8)?
|
||||||
|
} else {
|
||||||
|
8
|
||||||
|
};
|
||||||
|
|
||||||
|
if size + allocated > MAX_ALLOCATED {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
allocated += size;
|
||||||
|
|
||||||
|
// Choose arbitrarily between a zero-allocated chunk and a normal
|
||||||
|
// allocated chunk.
|
||||||
|
let zero = u.ratio(1, 50)?;
|
||||||
|
let ptr = if zero {
|
||||||
|
a.calloc(size, align)
|
||||||
|
} else {
|
||||||
|
a.malloc(size, align)
|
||||||
|
};
|
||||||
|
for i in 0..size {
|
||||||
|
if zero {
|
||||||
|
assert_eq!(*ptr.offset(i as isize), 0);
|
||||||
|
}
|
||||||
|
*ptr.offset(i as isize) = 0xce;
|
||||||
|
}
|
||||||
|
ptrs.push((ptr, size, align));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deallocate everythign when we're done.
|
||||||
|
for (ptr, size, align) in ptrs {
|
||||||
|
a.free(ptr, size, align);
|
||||||
|
}
|
||||||
|
|
||||||
|
a.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,42 @@
|
|||||||
|
use crate::Allocator;
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
|
pub struct System {
|
||||||
|
_priv: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl System {
|
||||||
|
pub const fn new() -> System {
|
||||||
|
System { _priv: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Allocator for System {
|
||||||
|
fn alloc(&self, _size: usize) -> (*mut u8, usize, u32) {
|
||||||
|
(ptr::null_mut(), 0, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 {
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_part(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free(&self, _ptr: *mut u8, _size: usize) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_release_part(&self, _flags: u32) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocates_zeros(&self) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn page_size(&self) -> usize {
|
||||||
|
1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
use crate::Dlmalloc;
|
||||||
|
use core::alloc::{GlobalAlloc, Layout};
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
|
pub use crate::sys::enable_alloc_after_fork;
|
||||||
|
|
||||||
|
/// An instance of a "global allocator" backed by `Dlmalloc`
|
||||||
|
///
|
||||||
|
/// This API requires the `global` feature is activated, and this type
|
||||||
|
/// implements the `GlobalAlloc` trait in the standard library.
|
||||||
|
pub struct GlobalDlmalloc;
|
||||||
|
|
||||||
|
static mut DLMALLOC: Dlmalloc = Dlmalloc::new();
|
||||||
|
|
||||||
|
unsafe impl GlobalAlloc for GlobalDlmalloc {
|
||||||
|
#[inline]
|
||||||
|
unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
|
||||||
|
let _guard = lock();
|
||||||
|
let dlmalloc = ptr::addr_of_mut!(DLMALLOC);
|
||||||
|
(*dlmalloc).malloc(layout.size(), layout.align())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
|
||||||
|
let _guard = lock();
|
||||||
|
let dlmalloc = ptr::addr_of_mut!(DLMALLOC);
|
||||||
|
(*dlmalloc).free(ptr, layout.size(), layout.align())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
|
||||||
|
let _guard = lock();
|
||||||
|
let dlmalloc = ptr::addr_of_mut!(DLMALLOC);
|
||||||
|
(*dlmalloc).calloc(layout.size(), layout.align())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
|
||||||
|
let _guard = lock();
|
||||||
|
let dlmalloc = ptr::addr_of_mut!(DLMALLOC);
|
||||||
|
(*dlmalloc).realloc(ptr, layout.size(), layout.align(), new_size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn lock() -> impl Drop {
|
||||||
|
crate::sys::acquire_global_lock();
|
||||||
|
|
||||||
|
struct Guard;
|
||||||
|
impl Drop for Guard {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
crate::sys::release_global_lock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Guard
|
||||||
|
}
|
||||||
@@ -0,0 +1,230 @@
|
|||||||
|
//! A Rust port of the `dlmalloc` allocator.
|
||||||
|
//!
|
||||||
|
//! The `dlmalloc` allocator is described at
|
||||||
|
//! <https://gee.cs.oswego.edu/dl/html/malloc.html> and this Rust crate is a straight
|
||||||
|
//! port of the C code for the allocator into Rust. The implementation is
|
||||||
|
//! wrapped up in a `Dlmalloc` type and has support for Linux, OSX, and Wasm
|
||||||
|
//! currently.
|
||||||
|
//!
|
||||||
|
//! The primary purpose of this crate is that it serves as the default memory
|
||||||
|
//! allocator for the `wasm32-unknown-unknown` target in the standard library.
|
||||||
|
//! Support for other platforms is largely untested and unused, but is used when
|
||||||
|
//! testing this crate.
|
||||||
|
|
||||||
|
#![allow(dead_code)]
|
||||||
|
#![no_std]
|
||||||
|
#![deny(missing_docs)]
|
||||||
|
|
||||||
|
#[cfg(feature = "rust_api")]
|
||||||
|
use core::{cmp, ptr};
|
||||||
|
|
||||||
|
#[cfg(feature = "system")]
|
||||||
|
use sys::System;
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub use self::global::{enable_alloc_after_fork, GlobalDlmalloc};
|
||||||
|
|
||||||
|
mod dlmalloc;
|
||||||
|
|
||||||
|
#[cfg(feature = "c_api")]
|
||||||
|
pub use dlmalloc::Dlmalloc as DlmallocCApi;
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
mod global;
|
||||||
|
|
||||||
|
/// In order for this crate to efficiently manage memory, it needs a way to communicate with the
|
||||||
|
/// underlying platform. This `Allocator` trait provides an interface for this communication.
|
||||||
|
pub unsafe trait Allocator: Send {
|
||||||
|
/// Allocates system memory region of at least `size` bytes
|
||||||
|
/// Returns a triple of `(base, size, flags)` where `base` is a pointer to the beginning of the
|
||||||
|
/// allocated memory region. `size` is the actual size of the region while `flags` specifies
|
||||||
|
/// properties of the allocated region. If `EXTERN_BIT` (bit 0) set in flags, then we did not
|
||||||
|
/// allocate this segment and so should not try to deallocate or merge with others.
|
||||||
|
/// This function can return a `std::ptr::null_mut()` when allocation fails (other values of
|
||||||
|
/// the triple will be ignored).
|
||||||
|
fn alloc(&self, size: usize) -> (*mut u8, usize, u32);
|
||||||
|
|
||||||
|
/// Remaps system memory region at `ptr` with size `oldsize` to a potential new location with
|
||||||
|
/// size `newsize`. `can_move` indicates if the location is allowed to move to a completely new
|
||||||
|
/// location, or that it is only allowed to change in size. Returns a pointer to the new
|
||||||
|
/// location in memory.
|
||||||
|
/// This function can return a `std::ptr::null_mut()` to signal an error.
|
||||||
|
fn remap(&self, ptr: *mut u8, oldsize: usize, newsize: usize, can_move: bool) -> *mut u8;
|
||||||
|
|
||||||
|
/// Frees a part of a memory chunk. The original memory chunk starts at `ptr` with size `oldsize`
|
||||||
|
/// and is turned into a memory region starting at the same address but with `newsize` bytes.
|
||||||
|
/// Returns `true` iff the access memory region could be freed.
|
||||||
|
fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool;
|
||||||
|
|
||||||
|
/// Frees an entire memory region. Returns `true` iff the operation succeeded. When `false` is
|
||||||
|
/// returned, the `dlmalloc` may re-use the location on future allocation requests
|
||||||
|
fn free(&self, ptr: *mut u8, size: usize) -> bool;
|
||||||
|
|
||||||
|
/// Indicates if the system can release a part of memory. For the `flags` argument, see
|
||||||
|
/// `Allocator::alloc`
|
||||||
|
fn can_release_part(&self, flags: u32) -> bool;
|
||||||
|
|
||||||
|
/// Indicates whether newly allocated regions contain zeros.
|
||||||
|
fn allocates_zeros(&self) -> bool;
|
||||||
|
|
||||||
|
/// Returns the page size. Must be a power of two
|
||||||
|
fn page_size(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An allocator instance
|
||||||
|
///
|
||||||
|
/// Instances of this type are used to allocate blocks of memory. For best
|
||||||
|
/// results only use one of these. Currently doesn't implement `Drop` to release
|
||||||
|
/// lingering memory back to the OS. That may happen eventually though!
|
||||||
|
#[cfg(feature = "rust_api")]
|
||||||
|
pub struct Dlmalloc<
|
||||||
|
#[cfg(feature = "system")]
|
||||||
|
A = System,
|
||||||
|
#[cfg(not(feature = "system"))]
|
||||||
|
A,
|
||||||
|
>(dlmalloc::Dlmalloc<A>);
|
||||||
|
|
||||||
|
cfg_if::cfg_if! {
|
||||||
|
if #[cfg(all(feature = "system", target_family = "wasm"))] {
|
||||||
|
#[path = "wasm.rs"]
|
||||||
|
mod sys;
|
||||||
|
} else if #[cfg(all(feature = "system", target_os = "windows"))] {
|
||||||
|
#[path = "windows.rs"]
|
||||||
|
mod sys;
|
||||||
|
} else if #[cfg(all(feature = "system", target_os = "xous"))] {
|
||||||
|
#[path = "xous.rs"]
|
||||||
|
mod sys;
|
||||||
|
} else if #[cfg(all(feature = "system", any(target_os = "linux", target_os = "macos", target_os = "redox")))] {
|
||||||
|
#[path = "unix.rs"]
|
||||||
|
mod sys;
|
||||||
|
} else {
|
||||||
|
#[path = "dummy.rs"]
|
||||||
|
mod sys;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "system")]
|
||||||
|
#[cfg(feature = "rust_api")]
|
||||||
|
impl Dlmalloc<System> {
|
||||||
|
/// Creates a new instance of an allocator
|
||||||
|
pub const fn new() -> Dlmalloc<System> {
|
||||||
|
Dlmalloc(dlmalloc::Dlmalloc::new(System::new()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust_api")]
|
||||||
|
impl<A> Dlmalloc<A> {
|
||||||
|
/// Creates a new instance of an allocator
|
||||||
|
pub const fn new_with_allocator(sys_allocator: A) -> Dlmalloc<A> {
|
||||||
|
Dlmalloc(dlmalloc::Dlmalloc::new(sys_allocator))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "rust_api")]
|
||||||
|
impl<A: Allocator> Dlmalloc<A> {
|
||||||
|
/// Allocates `size` bytes with `align` align.
|
||||||
|
///
|
||||||
|
/// Returns a null pointer if allocation fails. Returns a valid pointer
|
||||||
|
/// otherwise.
|
||||||
|
///
|
||||||
|
/// Safety and contracts are largely governed by the `GlobalAlloc::alloc`
|
||||||
|
/// method contracts.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn malloc(&mut self, size: usize, align: usize) -> *mut u8 {
|
||||||
|
if align <= self.0.malloc_alignment() {
|
||||||
|
self.0.malloc(size)
|
||||||
|
} else {
|
||||||
|
self.0.memalign(align, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as `malloc`, except if the allocation succeeds it's guaranteed to
|
||||||
|
/// point to `size` bytes of zeros.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn calloc(&mut self, size: usize, align: usize) -> *mut u8 {
|
||||||
|
let ptr = self.malloc(size, align);
|
||||||
|
if !ptr.is_null() && self.0.calloc_must_clear(ptr) {
|
||||||
|
ptr::write_bytes(ptr, 0, size);
|
||||||
|
}
|
||||||
|
ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deallocates a `ptr` with `size` and `align` as the previous request used
|
||||||
|
/// to allocate it.
|
||||||
|
///
|
||||||
|
/// Safety and contracts are largely governed by the `GlobalAlloc::dealloc`
|
||||||
|
/// method contracts.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn free(&mut self, ptr: *mut u8, size: usize, align: usize) {
|
||||||
|
let _ = align;
|
||||||
|
self.0.validate_size(ptr, size);
|
||||||
|
self.0.free(ptr)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Reallocates `ptr`, a previous allocation with `old_size` and
|
||||||
|
/// `old_align`, to have `new_size` and the same alignment as before.
|
||||||
|
///
|
||||||
|
/// Returns a null pointer if the memory couldn't be reallocated, but `ptr`
|
||||||
|
/// is still valid. Returns a valid pointer and frees `ptr` if the request
|
||||||
|
/// is satisfied.
|
||||||
|
///
|
||||||
|
/// Safety and contracts are largely governed by the `GlobalAlloc::realloc`
|
||||||
|
/// method contracts.
|
||||||
|
#[inline]
|
||||||
|
pub unsafe fn realloc(
|
||||||
|
&mut self,
|
||||||
|
ptr: *mut u8,
|
||||||
|
old_size: usize,
|
||||||
|
old_align: usize,
|
||||||
|
new_size: usize,
|
||||||
|
) -> *mut u8 {
|
||||||
|
self.0.validate_size(ptr, old_size);
|
||||||
|
|
||||||
|
if old_align <= self.0.malloc_alignment() {
|
||||||
|
self.0.realloc(ptr, new_size)
|
||||||
|
} else {
|
||||||
|
let res = self.malloc(new_size, old_align);
|
||||||
|
if !res.is_null() {
|
||||||
|
let size = cmp::min(old_size, new_size);
|
||||||
|
ptr::copy_nonoverlapping(ptr, res, size);
|
||||||
|
self.free(ptr, old_size, old_align);
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// If possible, gives memory back to the system if there is unused memory
|
||||||
|
/// at the high end of the malloc pool or in unused segments.
|
||||||
|
///
|
||||||
|
/// You can call this after freeing large blocks of memory to potentially
|
||||||
|
/// reduce the system-level memory requirements of a program. However, it
|
||||||
|
/// cannot guarantee to reduce memory. Under some allocation patterns, some
|
||||||
|
/// large free blocks of memory will be locked between two used chunks, so
|
||||||
|
/// they cannot be given back to the system.
|
||||||
|
///
|
||||||
|
/// The `pad` argument represents the amount of free trailing space to
|
||||||
|
/// leave untrimmed. If this argument is zero, only the minimum amount of
|
||||||
|
/// memory to maintain internal data structures will be left. Non-zero
|
||||||
|
/// arguments can be supplied to maintain enough trailing space to service
|
||||||
|
/// future expected allocations without having to re-obtain memory from the
|
||||||
|
/// system.
|
||||||
|
///
|
||||||
|
/// Returns `true` if it actually released any memory, else `false`.
|
||||||
|
pub unsafe fn trim(&mut self, pad: usize) -> bool {
|
||||||
|
self.0.trim(pad)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Releases all allocations in this allocator back to the system,
|
||||||
|
/// consuming self and preventing further use.
|
||||||
|
///
|
||||||
|
/// Returns the number of bytes released to the system.
|
||||||
|
pub unsafe fn destroy(self) -> usize {
|
||||||
|
self.0.destroy()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get a reference the underlying [`Allocator`] that this `Dlmalloc` was
|
||||||
|
/// constructed with.
|
||||||
|
pub fn allocator(&self) -> &A {
|
||||||
|
self.0.allocator()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
use crate::Allocator;
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
|
/// System setting for Linux
|
||||||
|
pub struct System {
|
||||||
|
_priv: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl System {
|
||||||
|
pub const fn new() -> System {
|
||||||
|
System { _priv: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
static mut LOCK: libc::pthread_mutex_t = libc::PTHREAD_MUTEX_INITIALIZER;
|
||||||
|
|
||||||
|
unsafe impl Allocator for System {
|
||||||
|
fn alloc(&self, size: usize) -> (*mut u8, usize, u32) {
|
||||||
|
let addr = unsafe {
|
||||||
|
libc::mmap(
|
||||||
|
ptr::null_mut(),
|
||||||
|
size,
|
||||||
|
libc::PROT_WRITE | libc::PROT_READ,
|
||||||
|
libc::MAP_ANON | libc::MAP_PRIVATE,
|
||||||
|
-1,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
if addr == libc::MAP_FAILED {
|
||||||
|
(ptr::null_mut(), 0, 0)
|
||||||
|
} else {
|
||||||
|
(addr.cast(), size, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn remap(&self, ptr: *mut u8, oldsize: usize, newsize: usize, can_move: bool) -> *mut u8 {
|
||||||
|
let flags = if can_move { libc::MREMAP_MAYMOVE } else { 0 };
|
||||||
|
let ptr = unsafe { libc::mremap(ptr.cast(), oldsize, newsize, flags) };
|
||||||
|
if ptr == libc::MAP_FAILED {
|
||||||
|
ptr::null_mut()
|
||||||
|
} else {
|
||||||
|
ptr.cast()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "redox", target_os = "macos"))]
|
||||||
|
fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 {
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool {
|
||||||
|
unsafe {
|
||||||
|
let rc = libc::mremap(ptr.cast(), oldsize, newsize, 0);
|
||||||
|
if rc != libc::MAP_FAILED {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
libc::munmap(ptr.add(newsize).cast(), oldsize - newsize) == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(any(target_os = "redox", target_os = "macos"))]
|
||||||
|
fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool {
|
||||||
|
unsafe { libc::munmap(ptr.add(newsize).cast(), oldsize - newsize) == 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free(&self, ptr: *mut u8, size: usize) -> bool {
|
||||||
|
unsafe { libc::munmap(ptr.cast(), size) == 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_release_part(&self, _flags: u32) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocates_zeros(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn page_size(&self) -> usize {
|
||||||
|
4096
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub fn acquire_global_lock() {
|
||||||
|
unsafe { assert_eq!(libc::pthread_mutex_lock(ptr::addr_of_mut!(LOCK)), 0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub fn release_global_lock() {
|
||||||
|
unsafe { assert_eq!(libc::pthread_mutex_unlock(ptr::addr_of_mut!(LOCK)), 0) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
/// allows the allocator to remain unsable in the child process,
|
||||||
|
/// after a call to `fork(2)`
|
||||||
|
///
|
||||||
|
/// #Safety
|
||||||
|
///
|
||||||
|
/// if used, this function must be called,
|
||||||
|
/// before any allocations are made with the global allocator.
|
||||||
|
pub unsafe fn enable_alloc_after_fork() {
|
||||||
|
// atfork must only be called once, to avoid a deadlock,
|
||||||
|
// where the handler attempts to acquire the global lock twice
|
||||||
|
static mut FORK_PROTECTED: bool = false;
|
||||||
|
|
||||||
|
unsafe extern "C" fn _acquire_global_lock() {
|
||||||
|
acquire_global_lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn _release_global_lock() {
|
||||||
|
release_global_lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
acquire_global_lock();
|
||||||
|
// if a process forks,
|
||||||
|
// it will acquire the lock before any other thread,
|
||||||
|
// protecting it from deadlock,
|
||||||
|
// due to the child being created with only the calling thread.
|
||||||
|
if !FORK_PROTECTED {
|
||||||
|
libc::pthread_atfork(
|
||||||
|
Some(_acquire_global_lock),
|
||||||
|
Some(_release_global_lock),
|
||||||
|
Some(_release_global_lock),
|
||||||
|
);
|
||||||
|
FORK_PROTECTED = true;
|
||||||
|
}
|
||||||
|
release_global_lock();
|
||||||
|
}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
use crate::Allocator;
|
||||||
|
#[cfg(target_arch = "wasm32")]
|
||||||
|
use core::arch::wasm32 as wasm;
|
||||||
|
#[cfg(target_arch = "wasm64")]
|
||||||
|
use core::arch::wasm64 as wasm;
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
|
/// System setting for Wasm
|
||||||
|
pub struct System {
|
||||||
|
_priv: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl System {
|
||||||
|
pub const fn new() -> System {
|
||||||
|
System { _priv: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Allocator for System {
|
||||||
|
fn alloc(&self, size: usize) -> (*mut u8, usize, u32) {
|
||||||
|
let pages = size / self.page_size();
|
||||||
|
let prev = wasm::memory_grow(0, pages);
|
||||||
|
if prev == usize::max_value() {
|
||||||
|
return (ptr::null_mut(), 0, 0);
|
||||||
|
}
|
||||||
|
(
|
||||||
|
(prev * self.page_size()) as *mut u8,
|
||||||
|
pages * self.page_size(),
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 {
|
||||||
|
// TODO: I think this can be implemented near the end?
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_part(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free(&self, _ptr: *mut u8, _size: usize) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_release_part(&self, _flags: u32) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocates_zeros(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn page_size(&self) -> usize {
|
||||||
|
64 * 1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub fn acquire_global_lock() {
|
||||||
|
// single threaded, no need!
|
||||||
|
assert!(!cfg!(target_feature = "atomics"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub fn release_global_lock() {
|
||||||
|
// single threaded, no need!
|
||||||
|
assert!(!cfg!(target_feature = "atomics"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub unsafe fn enable_alloc_after_fork() {
|
||||||
|
// single threaded, no need!
|
||||||
|
assert!(!cfg!(target_feature = "atomics"));
|
||||||
|
}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
use crate::Allocator;
|
||||||
|
use core::mem::MaybeUninit;
|
||||||
|
use core::ptr;
|
||||||
|
use windows_sys::Win32::System::Memory::*;
|
||||||
|
use windows_sys::Win32::System::SystemInformation::*;
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
use windows_sys::Win32::System::Threading::*;
|
||||||
|
|
||||||
|
pub struct System {
|
||||||
|
_priv: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl System {
|
||||||
|
pub const fn new() -> System {
|
||||||
|
System { _priv: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Allocator for System {
|
||||||
|
fn alloc(&self, size: usize) -> (*mut u8, usize, u32) {
|
||||||
|
let addr = unsafe {
|
||||||
|
VirtualAlloc(
|
||||||
|
ptr::null_mut(),
|
||||||
|
size,
|
||||||
|
MEM_RESERVE | MEM_COMMIT,
|
||||||
|
PAGE_READWRITE,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
if addr.is_null() {
|
||||||
|
(ptr::null_mut(), 0, 0)
|
||||||
|
} else {
|
||||||
|
(addr.cast(), size, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 {
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_part(&self, ptr: *mut u8, oldsize: usize, newsize: usize) -> bool {
|
||||||
|
unsafe { VirtualFree(ptr.add(newsize).cast(), oldsize - newsize, MEM_DECOMMIT) != 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free(&self, ptr: *mut u8, _size: usize) -> bool {
|
||||||
|
unsafe { VirtualFree(ptr.cast(), 0, MEM_DECOMMIT) != 0 }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_release_part(&self, _flags: u32) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocates_zeros(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn page_size(&self) -> usize {
|
||||||
|
unsafe {
|
||||||
|
let mut info = MaybeUninit::uninit();
|
||||||
|
GetSystemInfo(info.as_mut_ptr());
|
||||||
|
info.assume_init_ref().dwPageSize as usize
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NB: `SRWLOCK_INIT` doesn't appear to be in `windows-sys`
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
static mut LOCK: SRWLOCK = SRWLOCK {
|
||||||
|
Ptr: ptr::null_mut(),
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub fn acquire_global_lock() {
|
||||||
|
unsafe {
|
||||||
|
AcquireSRWLockExclusive(ptr::addr_of_mut!(LOCK));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub fn release_global_lock() {
|
||||||
|
unsafe {
|
||||||
|
ReleaseSRWLockExclusive(ptr::addr_of_mut!(LOCK));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Not needed on Windows
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub unsafe fn enable_alloc_after_fork() {}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
use crate::Allocator;
|
||||||
|
use core::ptr;
|
||||||
|
|
||||||
|
pub struct System {
|
||||||
|
_priv: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl System {
|
||||||
|
pub const fn new() -> System {
|
||||||
|
System { _priv: () }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv32")]
|
||||||
|
mod sys {
|
||||||
|
use core::arch::asm;
|
||||||
|
|
||||||
|
pub fn increase_heap(length: usize) -> Result<(usize, usize), ()> {
|
||||||
|
let syscall_no_increase_heap = 10usize;
|
||||||
|
let memory_flags_read_write = 2usize | 4usize;
|
||||||
|
|
||||||
|
let mut a0 = syscall_no_increase_heap;
|
||||||
|
let mut a1 = length;
|
||||||
|
let mut a2 = memory_flags_read_write;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
asm!(
|
||||||
|
"ecall",
|
||||||
|
inlateout("a0") a0,
|
||||||
|
inlateout("a1") a1,
|
||||||
|
inlateout("a2") a2,
|
||||||
|
out("a3") _,
|
||||||
|
out("a4") _,
|
||||||
|
out("a5") _,
|
||||||
|
out("a6") _,
|
||||||
|
out("a7") _,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let result = a0;
|
||||||
|
let address = a1;
|
||||||
|
let length = a2;
|
||||||
|
|
||||||
|
// 3 is the "MemoryRange" type, and the result is only valid
|
||||||
|
// if we get nonzero address and length.
|
||||||
|
if result == 3 && address != 0 && length != 0 {
|
||||||
|
Ok((address, length))
|
||||||
|
} else {
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Allocator for System {
|
||||||
|
/// Allocate an additional `size` bytes on the heap, and return a new
|
||||||
|
/// chunk of memory, as well as the size of the allocation and some
|
||||||
|
/// flags. Since flags are unused on this platform, they will always
|
||||||
|
/// be `0`.
|
||||||
|
fn alloc(&self, size: usize) -> (*mut u8, usize, u32) {
|
||||||
|
let size = if size == 0 {
|
||||||
|
4096
|
||||||
|
} else if size & 4095 == 0 {
|
||||||
|
size
|
||||||
|
} else {
|
||||||
|
size + (4096 - (size & 4095))
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Ok((address, length)) = sys::increase_heap(size) {
|
||||||
|
let start = address - size + length;
|
||||||
|
(start as *mut u8, size, 0)
|
||||||
|
} else {
|
||||||
|
(ptr::null_mut(), 0, 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remap(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize, _can_move: bool) -> *mut u8 {
|
||||||
|
// TODO
|
||||||
|
ptr::null_mut()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free_part(&self, _ptr: *mut u8, _oldsize: usize, _newsize: usize) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn free(&self, _ptr: *mut u8, _size: usize) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn can_release_part(&self, _flags: u32) -> bool {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn allocates_zeros(&self) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn page_size(&self) -> usize {
|
||||||
|
4 * 1024
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub fn acquire_global_lock() {
|
||||||
|
// global feature should not be enabled
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub fn release_global_lock() {
|
||||||
|
// global feature should not be enabled
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
pub unsafe fn enable_alloc_after_fork() {
|
||||||
|
// platform does not support `fork()` call
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
extern crate dlmalloc;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
use std::thread;
|
||||||
|
|
||||||
|
#[global_allocator]
|
||||||
|
#[cfg(feature = "global")]
|
||||||
|
static A: dlmalloc::GlobalDlmalloc = dlmalloc::GlobalDlmalloc;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn foo() {
|
||||||
|
println!("hello");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn map() {
|
||||||
|
let mut m = HashMap::new();
|
||||||
|
m.insert(1, 2);
|
||||||
|
m.insert(5, 3);
|
||||||
|
drop(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn strings() {
|
||||||
|
format!("foo, bar, {}", "baz");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(not(target_family = "wasm"))]
|
||||||
|
fn threads() {
|
||||||
|
assert!(thread::spawn(|| panic!()).join().is_err());
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
use arbitrary::Unstructured;
|
||||||
|
use dlmalloc::Dlmalloc;
|
||||||
|
use rand::{rngs::SmallRng, RngCore, SeedableRng};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn smoke() {
|
||||||
|
let mut a = Dlmalloc::new();
|
||||||
|
unsafe {
|
||||||
|
let ptr = a.malloc(1, 1);
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
*ptr = 9;
|
||||||
|
assert_eq!(*ptr, 9);
|
||||||
|
a.free(ptr, 1, 1);
|
||||||
|
|
||||||
|
let ptr = a.malloc(1, 1);
|
||||||
|
assert!(!ptr.is_null());
|
||||||
|
*ptr = 10;
|
||||||
|
assert_eq!(*ptr, 10);
|
||||||
|
a.free(ptr, 1, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[path = "../fuzz/src/lib.rs"]
|
||||||
|
mod fuzz;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn stress() {
|
||||||
|
let mut rng = SmallRng::seed_from_u64(0);
|
||||||
|
let mut buf = vec![0; 4096];
|
||||||
|
let iters = if cfg!(miri) { 5 } else { 2000 };
|
||||||
|
for _ in 0..iters {
|
||||||
|
rng.fill_bytes(&mut buf);
|
||||||
|
let mut u = Unstructured::new(&buf);
|
||||||
|
let _ = fuzz::run(&mut u);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
cargo fmt --package relibc --package crt0 --package redox-rt "$@"
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[package]
|
||||||
|
name = "generic-rt"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![allow(internal_features)]
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
|
use core::{
|
||||||
|
arch::asm,
|
||||||
|
mem::{self, offset_of},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct GenericTcb<Os> {
|
||||||
|
/// Pointer to the end of static TLS. Must be the first member
|
||||||
|
pub tls_end: *mut u8,
|
||||||
|
/// Size of the memory allocated for the static TLS in bytes (multiple of page size)
|
||||||
|
pub tls_len: usize,
|
||||||
|
/// Pointer to this structure
|
||||||
|
pub tcb_ptr: *mut Self,
|
||||||
|
/// Size of the memory allocated for this structure in bytes (should be same as page size)
|
||||||
|
pub tcb_len: usize,
|
||||||
|
pub os_specific: Os,
|
||||||
|
}
|
||||||
|
impl<Os> GenericTcb<Os> {
|
||||||
|
/// Architecture specific code to read a usize from the TCB - aarch64
|
||||||
|
#[allow(unsafe_op_in_unsafe_fn)]
|
||||||
|
#[inline(always)]
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
pub unsafe fn arch_read(offset: usize) -> usize {
|
||||||
|
let abi_ptr: usize;
|
||||||
|
asm!(
|
||||||
|
"mrs {}, tpidr_el0",
|
||||||
|
out(reg) abi_ptr,
|
||||||
|
);
|
||||||
|
|
||||||
|
let tcb_ptr = *(abi_ptr as *const usize);
|
||||||
|
*((tcb_ptr + offset) as *const usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Architecture specific code to read a usize from the TCB - x86
|
||||||
|
#[allow(unsafe_op_in_unsafe_fn)]
|
||||||
|
#[inline(always)]
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
pub unsafe fn arch_read(offset: usize) -> usize {
|
||||||
|
let value;
|
||||||
|
asm!(
|
||||||
|
"
|
||||||
|
mov {}, gs:[{}]
|
||||||
|
",
|
||||||
|
out(reg) value,
|
||||||
|
in(reg) offset,
|
||||||
|
);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Architecture specific code to read a usize from the TCB - x86_64
|
||||||
|
#[allow(unsafe_op_in_unsafe_fn)]
|
||||||
|
#[inline(always)]
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
pub unsafe fn arch_read(offset: usize) -> usize {
|
||||||
|
let value;
|
||||||
|
asm!(
|
||||||
|
"
|
||||||
|
mov {}, fs:[{}]
|
||||||
|
",
|
||||||
|
out(reg) value,
|
||||||
|
in(reg) offset,
|
||||||
|
);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Architecture specific code to read a usize from the TCB - riscv64
|
||||||
|
#[allow(unsafe_op_in_unsafe_fn)]
|
||||||
|
#[inline(always)]
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
unsafe fn arch_read(offset: usize) -> usize {
|
||||||
|
let value;
|
||||||
|
asm!(
|
||||||
|
"ld {value}, -8(tp)", // TCB
|
||||||
|
"add {value}, {value}, {offset}",
|
||||||
|
"ld {value}, 0({value})",
|
||||||
|
value = out(reg) value,
|
||||||
|
offset = in(reg) offset,
|
||||||
|
);
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
pub unsafe fn current_ptr() -> Option<*mut Self> {
|
||||||
|
let tcb_ptr = unsafe { Self::arch_read(offset_of!(Self, tcb_ptr)) as *mut Self };
|
||||||
|
let tcb_len = unsafe { Self::arch_read(offset_of!(Self, tcb_len)) };
|
||||||
|
if tcb_ptr.is_null() || tcb_len < mem::size_of::<Self>() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(tcb_ptr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub unsafe fn current() -> Option<&'static mut Self> {
|
||||||
|
unsafe { Some(&mut *Self::current_ptr()?) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pub fn panic_notls(_msg: impl core::fmt::Display) -> ! {
|
||||||
|
// TODO: actually print _msg, perhaps by having panic_notls take a `T: DebugBackend` that can
|
||||||
|
// propagate until called by e.g. relibc start
|
||||||
|
core::intrinsics::abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ExpectTlsFree {
|
||||||
|
type Unwrapped;
|
||||||
|
|
||||||
|
fn expect_notls(self, msg: &str) -> Self::Unwrapped;
|
||||||
|
}
|
||||||
|
impl<T, E: core::fmt::Debug> ExpectTlsFree for Result<T, E> {
|
||||||
|
type Unwrapped = T;
|
||||||
|
|
||||||
|
fn expect_notls(self, msg: &str) -> T {
|
||||||
|
match self {
|
||||||
|
Ok(t) => t,
|
||||||
|
Err(err) => panic_notls(format_args!(
|
||||||
|
"{msg}: expect failed for Result with err: {err:?}",
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T> ExpectTlsFree for Option<T> {
|
||||||
|
type Unwrapped = T;
|
||||||
|
|
||||||
|
fn expect_notls(self, msg: &str) -> T {
|
||||||
|
match self {
|
||||||
|
Some(t) => t,
|
||||||
|
None => panic_notls(format_args!("{msg}: expect failed for Option")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _ALLOCA_H
|
||||||
|
#define _ALLOCA_H
|
||||||
|
|
||||||
|
#define alloca(size) __builtin_alloca (size)
|
||||||
|
|
||||||
|
#endif /* _ALLOCA_H */
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#include <openlibm_complex.h>
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
/*
|
||||||
|
* MIT License
|
||||||
|
* Copyright (c) 2020 Rich Felker musl-libc
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _FEATURES_H__RELIBC
|
||||||
|
#define _FEATURES_H__RELIBC
|
||||||
|
|
||||||
|
// Version metadata for feature gating
|
||||||
|
// This is useful for divergent implementation specific behavior
|
||||||
|
// glibc, ulibc, and likely others define a similar macro
|
||||||
|
// musl does not define an equivalent macro
|
||||||
|
#define __RELIBC__ 1
|
||||||
|
#define __RELIBC__MAJOR 0
|
||||||
|
#define __RELIBC__MINOR 2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sources:
|
||||||
|
* https://en.cppreference.com/w/c/language/attributes
|
||||||
|
* https://clang.llvm.org/docs/LanguageExtensions.html
|
||||||
|
* https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005fc_005fattribute.html
|
||||||
|
* https://gcc.gnu.org/onlinedocs/cpp/Standard-Predefined-Macros.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Clang doesn't define __has_cpp_attribute if compiling C code
|
||||||
|
#if !defined(__has_cpp_attribute)
|
||||||
|
#define __has_cpp_attribute(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Clang doesn't define __has_c_attribute if compiling C++ code
|
||||||
|
#if !defined(__has_c_attribute)
|
||||||
|
#define __has_c_attribute(x) 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Check if C23+ attributes are available
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
// HACK: GCC backports C++ attributes to C++98 but doesn't accept attributes
|
||||||
|
// placed before the function like cbindgen emits.
|
||||||
|
// Let's just disable attributes for C++98 by checking if a random C++11
|
||||||
|
// feature is available.
|
||||||
|
#define __HAS_ATTRIBUTE(x) __cpp_variable_templates &&__has_cpp_attribute(x)
|
||||||
|
#else
|
||||||
|
#define __HAS_ATTRIBUTE(x) \
|
||||||
|
(__has_c_attribute(x) || __STDC_VERSION__ >= 202311L || \
|
||||||
|
__has_cpp_attribute(x))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO: Not emitted with cbindgen
|
||||||
|
#if __STDC_VERSION__ >= 199901L
|
||||||
|
#define __restrict restrict
|
||||||
|
#elif !defined(__GNUC__)
|
||||||
|
#define __restrict
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// TODO: Not emitted with cbindgen
|
||||||
|
#if __STDC_VERSION__ >= 199901L || defined(__cplusplus)
|
||||||
|
#define __inline inline
|
||||||
|
#elif !defined(__GNUC__)
|
||||||
|
#define __inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Analogous to Rust's Never type
|
||||||
|
//TODO: clang fails to compile C with [[noreturn]]
|
||||||
|
#if defined(__cplusplus) && __HAS_ATTRIBUTE(noreturn) && !(__clang__)
|
||||||
|
#define __noreturn [[noreturn]]
|
||||||
|
// #elif __STDC_VERSION__ >= 201112L
|
||||||
|
// FIXME: cbindgen incorrectly places _Noreturn
|
||||||
|
// #define __noreturn _Noreturn
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define __noreturn __attribute__((__noreturn__))
|
||||||
|
#else
|
||||||
|
#define __noreturn
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Analogous to Rust's #[must_use]
|
||||||
|
// C23 only
|
||||||
|
#if __HAS_ATTRIBUTE(nodiscard)
|
||||||
|
#define __nodiscard [[nodiscard]]
|
||||||
|
#define __nodiscardNote(x) [[nodiscard(x)]]
|
||||||
|
#else
|
||||||
|
#define __nodiscard
|
||||||
|
#define __nodiscardNote(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Analogous to Rust's #[deprecated]
|
||||||
|
// C23 only
|
||||||
|
#if __HAS_ATTRIBUTE(deprecated)
|
||||||
|
#define __deprecated [[deprecated]]
|
||||||
|
#define __deprecatedNote(x) [[deprecated(x)]]
|
||||||
|
#else
|
||||||
|
#define __deprecated
|
||||||
|
#define __deprecatedNote(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
#include <openlibm_fenv.h>
|
||||||
|
#undef complex
|
||||||
|
#undef I
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// Copied from musl
|
||||||
|
|
||||||
|
#ifndef _ISO646_H
|
||||||
|
#define _ISO646_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#define and &&
|
||||||
|
#define and_eq &=
|
||||||
|
#define bitand &
|
||||||
|
#define bitor |
|
||||||
|
#define compl ~
|
||||||
|
#define not !
|
||||||
|
#define not_eq !=
|
||||||
|
#define or ||
|
||||||
|
#define or_eq |=
|
||||||
|
#define xor ^
|
||||||
|
#define xor_eq ^=
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
#ifndef __MACHINE_ENDIAN_H__
|
||||||
|
|
||||||
|
/* TODO: Forcing little endian, if you need a big endian system, fix this { */
|
||||||
|
#ifndef BIG_ENDIAN
|
||||||
|
#define BIG_ENDIAN 4321
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LITTLE_ENDIAN
|
||||||
|
#define LITTLE_ENDIAN 1234
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef BYTE_ORDER
|
||||||
|
#define BYTE_ORDER LITTLE_ENDIAN
|
||||||
|
#endif
|
||||||
|
/* } */
|
||||||
|
|
||||||
|
#endif /* __MACHINE_ENDIAN_H__ */
|
||||||
+113
@@ -0,0 +1,113 @@
|
|||||||
|
#include <openlibm_math.h>
|
||||||
|
|
||||||
|
// Missing typedefs
|
||||||
|
typedef float float_t;
|
||||||
|
typedef double double_t;
|
||||||
|
|
||||||
|
/* double */
|
||||||
|
|
||||||
|
#ifndef M_PI
|
||||||
|
#define M_PI 3.14159265358979323846 /* pi */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_PI_2
|
||||||
|
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_PI_4
|
||||||
|
#define M_PI_4 0.78539816339744830962 /* pi/4 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_2_PI
|
||||||
|
#define M_2_PI 0.63661977236758134308 /* 2/pi */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_E
|
||||||
|
#define M_E 2.7182818284590452354 /* e */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LOG2E
|
||||||
|
#define M_LOG2E 1.4426950408889634074 /* log_2 e */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LOG10E
|
||||||
|
#define M_LOG10E 0.43429448190325182765 /* log_10 e */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LN2
|
||||||
|
#define M_LN2 0.69314718055994530942 /* log_e 2 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LN10
|
||||||
|
#define M_LN10 2.30258509299404568402 /* log_e 10 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_1_PI
|
||||||
|
#define M_1_PI 0.31830988618379067154 /* 1/pi */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_2_SQRTPI
|
||||||
|
#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_SQRT2
|
||||||
|
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_SQRT1_2
|
||||||
|
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* long double */
|
||||||
|
|
||||||
|
#ifndef M_El
|
||||||
|
#define M_El 2.718281828459045235360287471352662498L /* e */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LOG2El
|
||||||
|
#define M_LOG2El 1.442695040888963407359924681001892137L /* log_2 e */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LOG10El
|
||||||
|
#define M_LOG10El 0.434294481903251827651128918916605082L /* log_10 e */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LN2l
|
||||||
|
#define M_LN2l 0.693147180559945309417232121458176568L /* log_e 2 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_LN10l
|
||||||
|
#define M_LN10l 2.302585092994045684017991454684364208L /* log_e 10 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_PIl
|
||||||
|
#define M_PIl 3.141592653589793238462643383279502884L /* pi */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_PI_2l
|
||||||
|
#define M_PI_2l 1.570796326794896619231321691639751442L /* pi/2 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_PI_4l
|
||||||
|
#define M_PI_4l 0.785398163397448309615660845819875721L /* pi/4 */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_1_PIl
|
||||||
|
#define M_1_PIl 0.318309886183790671537767526745028724L /* 1/pi */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_2_PIl
|
||||||
|
#define M_2_PIl 0.636619772367581343075535053490057448L /* 2/pi */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_2_SQRTPIl
|
||||||
|
#define M_2_SQRTPIl 1.128379167095512573896158903121545172L /* 2/sqrt(pi) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_SQRT2l
|
||||||
|
#define M_SQRT2l 1.414213562373095048801688724209698079L /* sqrt(2) */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef M_SQRT1_2l
|
||||||
|
#define M_SQRT1_2l 0.707106781186547524400844362104849039L /* 1/sqrt(2) */
|
||||||
|
#endif
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#include <string.h>
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _NETINET_IN_SYSTM_H
|
||||||
|
#define _NETINET_IN_SYSTM_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef uint16_t n_short;
|
||||||
|
typedef uint32_t n_long;
|
||||||
|
typedef uint32_t n_time;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
#ifndef _RELIBC_PATHS_H
|
||||||
|
#define _RELIBC_PATHS_H
|
||||||
|
|
||||||
|
#define _PATH_BSHELL "/bin/sh"
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
#ifndef _SETJMP_H
|
||||||
|
#define _SETJMP_H
|
||||||
|
|
||||||
|
#ifdef __aarch64__
|
||||||
|
typedef unsigned long jmp_buf[22];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __arm__
|
||||||
|
typedef unsigned long long jmp_buf[32];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
typedef unsigned long jmp_buf[6];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __m68k__
|
||||||
|
typedef unsigned long jmp_buf[39];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __microblaze__
|
||||||
|
typedef unsigned long jmp_buf[18];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __mips__
|
||||||
|
typedef unsigned long long jmp_buf[13];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __mips64__
|
||||||
|
typedef unsigned long long jmp_buf[23];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __mipsn32__
|
||||||
|
typedef unsigned long long jmp_buf[23];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __or1k__
|
||||||
|
typedef unsigned long jmp_buf[13];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __powerpc__
|
||||||
|
typedef unsigned long long jmp_buf[56];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __powerpc64__
|
||||||
|
typedef uint128_t jmp_buf[32];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __s390x__
|
||||||
|
typedef unsigned long jmp_buf[18];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __sh__
|
||||||
|
typedef unsigned long jmp_buf[15];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __x32__
|
||||||
|
typedef unsigned long long jmp_buf[8];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __x86_64__
|
||||||
|
typedef unsigned long jmp_buf[16];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __riscv
|
||||||
|
typedef unsigned long jmp_buf[26];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef jmp_buf sigjmp_buf;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int setjmp(jmp_buf buf);
|
||||||
|
void longjmp(jmp_buf buf, int value);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SETJMP_H */
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
#ifndef _STDARG_H
|
||||||
|
#define _STDARG_H
|
||||||
|
|
||||||
|
typedef __builtin_va_list va_list;
|
||||||
|
#define va_start(v,l) __builtin_va_start(v,l)
|
||||||
|
#define va_end(v) __builtin_va_end(v)
|
||||||
|
#define va_arg(v,l) __builtin_va_arg(v,l)
|
||||||
|
#define va_copy(d,s) __builtin_va_copy(d,s)
|
||||||
|
|
||||||
|
#endif /* _STDARG_H */
|
||||||
@@ -0,0 +1,243 @@
|
|||||||
|
/* Copyright (C) 2013-2022 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/* ISO C11 Standard: 7.17 Atomics <stdatomic.h>. */
|
||||||
|
|
||||||
|
#ifndef _STDATOMIC_H
|
||||||
|
#define _STDATOMIC_H
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
memory_order_relaxed = __ATOMIC_RELAXED,
|
||||||
|
memory_order_consume = __ATOMIC_CONSUME,
|
||||||
|
memory_order_acquire = __ATOMIC_ACQUIRE,
|
||||||
|
memory_order_release = __ATOMIC_RELEASE,
|
||||||
|
memory_order_acq_rel = __ATOMIC_ACQ_REL,
|
||||||
|
memory_order_seq_cst = __ATOMIC_SEQ_CST
|
||||||
|
} memory_order;
|
||||||
|
|
||||||
|
|
||||||
|
typedef _Atomic _Bool atomic_bool;
|
||||||
|
typedef _Atomic char atomic_char;
|
||||||
|
typedef _Atomic signed char atomic_schar;
|
||||||
|
typedef _Atomic unsigned char atomic_uchar;
|
||||||
|
typedef _Atomic short atomic_short;
|
||||||
|
typedef _Atomic unsigned short atomic_ushort;
|
||||||
|
typedef _Atomic int atomic_int;
|
||||||
|
typedef _Atomic unsigned int atomic_uint;
|
||||||
|
typedef _Atomic long atomic_long;
|
||||||
|
typedef _Atomic unsigned long atomic_ulong;
|
||||||
|
typedef _Atomic long long atomic_llong;
|
||||||
|
typedef _Atomic unsigned long long atomic_ullong;
|
||||||
|
typedef _Atomic __CHAR16_TYPE__ atomic_char16_t;
|
||||||
|
typedef _Atomic __CHAR32_TYPE__ atomic_char32_t;
|
||||||
|
typedef _Atomic __WCHAR_TYPE__ atomic_wchar_t;
|
||||||
|
typedef _Atomic __INT_LEAST8_TYPE__ atomic_int_least8_t;
|
||||||
|
typedef _Atomic __UINT_LEAST8_TYPE__ atomic_uint_least8_t;
|
||||||
|
typedef _Atomic __INT_LEAST16_TYPE__ atomic_int_least16_t;
|
||||||
|
typedef _Atomic __UINT_LEAST16_TYPE__ atomic_uint_least16_t;
|
||||||
|
typedef _Atomic __INT_LEAST32_TYPE__ atomic_int_least32_t;
|
||||||
|
typedef _Atomic __UINT_LEAST32_TYPE__ atomic_uint_least32_t;
|
||||||
|
typedef _Atomic __INT_LEAST64_TYPE__ atomic_int_least64_t;
|
||||||
|
typedef _Atomic __UINT_LEAST64_TYPE__ atomic_uint_least64_t;
|
||||||
|
typedef _Atomic __INT_FAST8_TYPE__ atomic_int_fast8_t;
|
||||||
|
typedef _Atomic __UINT_FAST8_TYPE__ atomic_uint_fast8_t;
|
||||||
|
typedef _Atomic __INT_FAST16_TYPE__ atomic_int_fast16_t;
|
||||||
|
typedef _Atomic __UINT_FAST16_TYPE__ atomic_uint_fast16_t;
|
||||||
|
typedef _Atomic __INT_FAST32_TYPE__ atomic_int_fast32_t;
|
||||||
|
typedef _Atomic __UINT_FAST32_TYPE__ atomic_uint_fast32_t;
|
||||||
|
typedef _Atomic __INT_FAST64_TYPE__ atomic_int_fast64_t;
|
||||||
|
typedef _Atomic __UINT_FAST64_TYPE__ atomic_uint_fast64_t;
|
||||||
|
typedef _Atomic __INTPTR_TYPE__ atomic_intptr_t;
|
||||||
|
typedef _Atomic __UINTPTR_TYPE__ atomic_uintptr_t;
|
||||||
|
typedef _Atomic __SIZE_TYPE__ atomic_size_t;
|
||||||
|
typedef _Atomic __PTRDIFF_TYPE__ atomic_ptrdiff_t;
|
||||||
|
typedef _Atomic __INTMAX_TYPE__ atomic_intmax_t;
|
||||||
|
typedef _Atomic __UINTMAX_TYPE__ atomic_uintmax_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define ATOMIC_VAR_INIT(VALUE) (VALUE)
|
||||||
|
|
||||||
|
/* Initialize an atomic object pointed to by PTR with VAL. */
|
||||||
|
#define atomic_init(PTR, VAL) \
|
||||||
|
atomic_store_explicit (PTR, VAL, __ATOMIC_RELAXED)
|
||||||
|
|
||||||
|
#define kill_dependency(Y) \
|
||||||
|
__extension__ \
|
||||||
|
({ \
|
||||||
|
__auto_type __kill_dependency_tmp = (Y); \
|
||||||
|
__kill_dependency_tmp; \
|
||||||
|
})
|
||||||
|
|
||||||
|
extern void atomic_thread_fence (memory_order);
|
||||||
|
#define atomic_thread_fence(MO) __atomic_thread_fence (MO)
|
||||||
|
extern void atomic_signal_fence (memory_order);
|
||||||
|
#define atomic_signal_fence(MO) __atomic_signal_fence (MO)
|
||||||
|
#define atomic_is_lock_free(OBJ) __atomic_is_lock_free (sizeof (*(OBJ)), (OBJ))
|
||||||
|
|
||||||
|
#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE
|
||||||
|
#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE
|
||||||
|
#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE
|
||||||
|
#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE
|
||||||
|
#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE
|
||||||
|
#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE
|
||||||
|
#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE
|
||||||
|
#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE
|
||||||
|
#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE
|
||||||
|
#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE
|
||||||
|
|
||||||
|
|
||||||
|
/* Note that these macros require __auto_type to remove
|
||||||
|
_Atomic qualifiers (and const qualifiers, if those are valid on
|
||||||
|
macro operands).
|
||||||
|
|
||||||
|
Also note that the header file uses the generic form of __atomic
|
||||||
|
builtins, which requires the address to be taken of the value
|
||||||
|
parameter, and then we pass that value on. This allows the macros
|
||||||
|
to work for any type, and the compiler is smart enough to convert
|
||||||
|
these to lock-free _N variants if possible, and throw away the
|
||||||
|
temps. */
|
||||||
|
|
||||||
|
#define atomic_store_explicit(PTR, VAL, MO) \
|
||||||
|
__extension__ \
|
||||||
|
({ \
|
||||||
|
__auto_type __atomic_store_ptr = (PTR); \
|
||||||
|
__typeof__ ((void)0, *__atomic_store_ptr) __atomic_store_tmp = (VAL); \
|
||||||
|
__atomic_store (__atomic_store_ptr, &__atomic_store_tmp, (MO)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define atomic_store(PTR, VAL) \
|
||||||
|
atomic_store_explicit (PTR, VAL, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
|
|
||||||
|
#define atomic_load_explicit(PTR, MO) \
|
||||||
|
__extension__ \
|
||||||
|
({ \
|
||||||
|
__auto_type __atomic_load_ptr = (PTR); \
|
||||||
|
__typeof__ ((void)0, *__atomic_load_ptr) __atomic_load_tmp; \
|
||||||
|
__atomic_load (__atomic_load_ptr, &__atomic_load_tmp, (MO)); \
|
||||||
|
__atomic_load_tmp; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define atomic_load(PTR) atomic_load_explicit (PTR, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
|
|
||||||
|
#define atomic_exchange_explicit(PTR, VAL, MO) \
|
||||||
|
__extension__ \
|
||||||
|
({ \
|
||||||
|
__auto_type __atomic_exchange_ptr = (PTR); \
|
||||||
|
__typeof__ ((void)0, *__atomic_exchange_ptr) __atomic_exchange_val = (VAL); \
|
||||||
|
__typeof__ ((void)0, *__atomic_exchange_ptr) __atomic_exchange_tmp; \
|
||||||
|
__atomic_exchange (__atomic_exchange_ptr, &__atomic_exchange_val, \
|
||||||
|
&__atomic_exchange_tmp, (MO)); \
|
||||||
|
__atomic_exchange_tmp; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define atomic_exchange(PTR, VAL) \
|
||||||
|
atomic_exchange_explicit (PTR, VAL, __ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
|
|
||||||
|
#define atomic_compare_exchange_strong_explicit(PTR, VAL, DES, SUC, FAIL) \
|
||||||
|
__extension__ \
|
||||||
|
({ \
|
||||||
|
__auto_type __atomic_compare_exchange_ptr = (PTR); \
|
||||||
|
__typeof__ ((void)0, *__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \
|
||||||
|
= (DES); \
|
||||||
|
__atomic_compare_exchange (__atomic_compare_exchange_ptr, (VAL), \
|
||||||
|
&__atomic_compare_exchange_tmp, 0, \
|
||||||
|
(SUC), (FAIL)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define atomic_compare_exchange_strong(PTR, VAL, DES) \
|
||||||
|
atomic_compare_exchange_strong_explicit (PTR, VAL, DES, __ATOMIC_SEQ_CST, \
|
||||||
|
__ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
|
#define atomic_compare_exchange_weak_explicit(PTR, VAL, DES, SUC, FAIL) \
|
||||||
|
__extension__ \
|
||||||
|
({ \
|
||||||
|
__auto_type __atomic_compare_exchange_ptr = (PTR); \
|
||||||
|
__typeof__ ((void)0, *__atomic_compare_exchange_ptr) __atomic_compare_exchange_tmp \
|
||||||
|
= (DES); \
|
||||||
|
__atomic_compare_exchange (__atomic_compare_exchange_ptr, (VAL), \
|
||||||
|
&__atomic_compare_exchange_tmp, 1, \
|
||||||
|
(SUC), (FAIL)); \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define atomic_compare_exchange_weak(PTR, VAL, DES) \
|
||||||
|
atomic_compare_exchange_weak_explicit (PTR, VAL, DES, __ATOMIC_SEQ_CST, \
|
||||||
|
__ATOMIC_SEQ_CST)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define atomic_fetch_add(PTR, VAL) __atomic_fetch_add ((PTR), (VAL), \
|
||||||
|
__ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_add_explicit(PTR, VAL, MO) \
|
||||||
|
__atomic_fetch_add ((PTR), (VAL), (MO))
|
||||||
|
|
||||||
|
#define atomic_fetch_sub(PTR, VAL) __atomic_fetch_sub ((PTR), (VAL), \
|
||||||
|
__ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_sub_explicit(PTR, VAL, MO) \
|
||||||
|
__atomic_fetch_sub ((PTR), (VAL), (MO))
|
||||||
|
|
||||||
|
#define atomic_fetch_or(PTR, VAL) __atomic_fetch_or ((PTR), (VAL), \
|
||||||
|
__ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_or_explicit(PTR, VAL, MO) \
|
||||||
|
__atomic_fetch_or ((PTR), (VAL), (MO))
|
||||||
|
|
||||||
|
#define atomic_fetch_xor(PTR, VAL) __atomic_fetch_xor ((PTR), (VAL), \
|
||||||
|
__ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_xor_explicit(PTR, VAL, MO) \
|
||||||
|
__atomic_fetch_xor ((PTR), (VAL), (MO))
|
||||||
|
|
||||||
|
#define atomic_fetch_and(PTR, VAL) __atomic_fetch_and ((PTR), (VAL), \
|
||||||
|
__ATOMIC_SEQ_CST)
|
||||||
|
#define atomic_fetch_and_explicit(PTR, VAL, MO) \
|
||||||
|
__atomic_fetch_and ((PTR), (VAL), (MO))
|
||||||
|
|
||||||
|
|
||||||
|
typedef _Atomic struct
|
||||||
|
{
|
||||||
|
#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1
|
||||||
|
_Bool __val;
|
||||||
|
#else
|
||||||
|
unsigned char __val;
|
||||||
|
#endif
|
||||||
|
} atomic_flag;
|
||||||
|
|
||||||
|
#define ATOMIC_FLAG_INIT { 0 }
|
||||||
|
|
||||||
|
|
||||||
|
extern _Bool atomic_flag_test_and_set (volatile atomic_flag *);
|
||||||
|
#define atomic_flag_test_and_set(PTR) \
|
||||||
|
__atomic_test_and_set ((PTR), __ATOMIC_SEQ_CST)
|
||||||
|
extern _Bool atomic_flag_test_and_set_explicit (volatile atomic_flag *,
|
||||||
|
memory_order);
|
||||||
|
#define atomic_flag_test_and_set_explicit(PTR, MO) \
|
||||||
|
__atomic_test_and_set ((PTR), (MO))
|
||||||
|
|
||||||
|
extern void atomic_flag_clear (volatile atomic_flag *);
|
||||||
|
#define atomic_flag_clear(PTR) __atomic_clear ((PTR), __ATOMIC_SEQ_CST)
|
||||||
|
extern void atomic_flag_clear_explicit (volatile atomic_flag *, memory_order);
|
||||||
|
#define atomic_flag_clear_explicit(PTR, MO) __atomic_clear ((PTR), (MO))
|
||||||
|
|
||||||
|
#endif /* _STDATOMIC_H */
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
#ifndef _STDBOOL_H
|
||||||
|
#define _STDBOOL_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
#define bool _Bool
|
||||||
|
#define true 1
|
||||||
|
#define false 0
|
||||||
|
#else /* __cplusplus */
|
||||||
|
#if __cplusplus < 201103L
|
||||||
|
#define bool bool
|
||||||
|
#define false false
|
||||||
|
#define true true
|
||||||
|
#endif /*__cplusplus < 201103L*/
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
#define __bool_true_false_are_defined 1
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _STDBOOL_H */
|
||||||
@@ -0,0 +1,377 @@
|
|||||||
|
/* Copyright (C) 2008-2018 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This file is part of GCC.
|
||||||
|
|
||||||
|
GCC is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3, or (at your option)
|
||||||
|
any later version.
|
||||||
|
|
||||||
|
GCC is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
Under Section 7 of GPL version 3, you are granted additional
|
||||||
|
permissions described in the GCC Runtime Library Exception, version
|
||||||
|
3.1, as published by the Free Software Foundation.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License and
|
||||||
|
a copy of the GCC Runtime Library Exception along with this program;
|
||||||
|
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ISO C Standard: 7.18 Integer types <stdint.h>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _STDINT_H
|
||||||
|
#define _STDINT_H
|
||||||
|
|
||||||
|
/* 7.8.1.1 Exact-width integer types */
|
||||||
|
|
||||||
|
#ifdef __INT8_TYPE__
|
||||||
|
typedef __INT8_TYPE__ int8_t;
|
||||||
|
#endif
|
||||||
|
#ifdef __INT16_TYPE__
|
||||||
|
typedef __INT16_TYPE__ int16_t;
|
||||||
|
#endif
|
||||||
|
#ifdef __INT32_TYPE__
|
||||||
|
typedef __INT32_TYPE__ int32_t;
|
||||||
|
#endif
|
||||||
|
#ifdef __INT64_TYPE__
|
||||||
|
typedef __INT64_TYPE__ int64_t;
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT8_TYPE__
|
||||||
|
typedef __UINT8_TYPE__ uint8_t;
|
||||||
|
typedef __UINT8_TYPE__ u_int8_t;
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT16_TYPE__
|
||||||
|
typedef __UINT16_TYPE__ uint16_t;
|
||||||
|
typedef __UINT16_TYPE__ u_int16_t;
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT32_TYPE__
|
||||||
|
typedef __UINT32_TYPE__ uint32_t;
|
||||||
|
typedef __UINT32_TYPE__ u_int32_t;
|
||||||
|
// Required by openlibm
|
||||||
|
typedef __UINT32_TYPE__ __uint32_t;
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT64_TYPE__
|
||||||
|
typedef __UINT64_TYPE__ uint64_t;
|
||||||
|
typedef __UINT64_TYPE__ u_int64_t;
|
||||||
|
// Required by openlibm
|
||||||
|
typedef __UINT64_TYPE__ __uint64_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 7.8.1.2 Minimum-width integer types */
|
||||||
|
|
||||||
|
typedef __INT_LEAST8_TYPE__ int_least8_t;
|
||||||
|
typedef __INT_LEAST16_TYPE__ int_least16_t;
|
||||||
|
typedef __INT_LEAST32_TYPE__ int_least32_t;
|
||||||
|
typedef __INT_LEAST64_TYPE__ int_least64_t;
|
||||||
|
typedef __UINT_LEAST8_TYPE__ uint_least8_t;
|
||||||
|
typedef __UINT_LEAST16_TYPE__ uint_least16_t;
|
||||||
|
typedef __UINT_LEAST32_TYPE__ uint_least32_t;
|
||||||
|
typedef __UINT_LEAST64_TYPE__ uint_least64_t;
|
||||||
|
|
||||||
|
/* 7.8.1.3 Fastest minimum-width integer types */
|
||||||
|
|
||||||
|
typedef __INT_FAST8_TYPE__ int_fast8_t;
|
||||||
|
typedef __INT_FAST16_TYPE__ int_fast16_t;
|
||||||
|
typedef __INT_FAST32_TYPE__ int_fast32_t;
|
||||||
|
typedef __INT_FAST64_TYPE__ int_fast64_t;
|
||||||
|
typedef __UINT_FAST8_TYPE__ uint_fast8_t;
|
||||||
|
typedef __UINT_FAST16_TYPE__ uint_fast16_t;
|
||||||
|
typedef __UINT_FAST32_TYPE__ uint_fast32_t;
|
||||||
|
typedef __UINT_FAST64_TYPE__ uint_fast64_t;
|
||||||
|
|
||||||
|
/* 7.8.1.4 Integer types capable of holding object pointers */
|
||||||
|
|
||||||
|
#ifdef __INTPTR_TYPE__
|
||||||
|
typedef __INTPTR_TYPE__ intptr_t;
|
||||||
|
#endif
|
||||||
|
#ifdef __UINTPTR_TYPE__
|
||||||
|
typedef __UINTPTR_TYPE__ uintptr_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* 7.8.1.5 Greatest-width integer types */
|
||||||
|
|
||||||
|
typedef __INTMAX_TYPE__ intmax_t;
|
||||||
|
typedef __UINTMAX_TYPE__ uintmax_t;
|
||||||
|
|
||||||
|
#if (!defined __cplusplus || __cplusplus >= 201103L \
|
||||||
|
|| defined __STDC_LIMIT_MACROS)
|
||||||
|
|
||||||
|
/* 7.18.2 Limits of specified-width integer types */
|
||||||
|
|
||||||
|
#ifdef __INT8_MAX__
|
||||||
|
# undef INT8_MAX
|
||||||
|
# define INT8_MAX __INT8_MAX__
|
||||||
|
# undef INT8_MIN
|
||||||
|
# define INT8_MIN (-INT8_MAX - 1)
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT8_MAX__
|
||||||
|
# undef UINT8_MAX
|
||||||
|
# define UINT8_MAX __UINT8_MAX__
|
||||||
|
#endif
|
||||||
|
#ifdef __INT16_MAX__
|
||||||
|
# undef INT16_MAX
|
||||||
|
# define INT16_MAX __INT16_MAX__
|
||||||
|
# undef INT16_MIN
|
||||||
|
# define INT16_MIN (-INT16_MAX - 1)
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT16_MAX__
|
||||||
|
# undef UINT16_MAX
|
||||||
|
# define UINT16_MAX __UINT16_MAX__
|
||||||
|
#endif
|
||||||
|
#ifdef __INT32_MAX__
|
||||||
|
# undef INT32_MAX
|
||||||
|
# define INT32_MAX __INT32_MAX__
|
||||||
|
# undef INT32_MIN
|
||||||
|
# define INT32_MIN (-INT32_MAX - 1)
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT32_MAX__
|
||||||
|
# undef UINT32_MAX
|
||||||
|
# define UINT32_MAX __UINT32_MAX__
|
||||||
|
#endif
|
||||||
|
#ifdef __INT64_MAX__
|
||||||
|
# undef INT64_MAX
|
||||||
|
# define INT64_MAX __INT64_MAX__
|
||||||
|
# undef INT64_MIN
|
||||||
|
# define INT64_MIN (-INT64_MAX - 1)
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT64_MAX__
|
||||||
|
# undef UINT64_MAX
|
||||||
|
# define UINT64_MAX __UINT64_MAX__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef INT_LEAST8_MAX
|
||||||
|
#define INT_LEAST8_MAX __INT_LEAST8_MAX__
|
||||||
|
#undef INT_LEAST8_MIN
|
||||||
|
#define INT_LEAST8_MIN (-INT_LEAST8_MAX - 1)
|
||||||
|
#undef UINT_LEAST8_MAX
|
||||||
|
#define UINT_LEAST8_MAX __UINT_LEAST8_MAX__
|
||||||
|
#undef INT_LEAST16_MAX
|
||||||
|
#define INT_LEAST16_MAX __INT_LEAST16_MAX__
|
||||||
|
#undef INT_LEAST16_MIN
|
||||||
|
#define INT_LEAST16_MIN (-INT_LEAST16_MAX - 1)
|
||||||
|
#undef UINT_LEAST16_MAX
|
||||||
|
#define UINT_LEAST16_MAX __UINT_LEAST16_MAX__
|
||||||
|
#undef INT_LEAST32_MAX
|
||||||
|
#define INT_LEAST32_MAX __INT_LEAST32_MAX__
|
||||||
|
#undef INT_LEAST32_MIN
|
||||||
|
#define INT_LEAST32_MIN (-INT_LEAST32_MAX - 1)
|
||||||
|
#undef UINT_LEAST32_MAX
|
||||||
|
#define UINT_LEAST32_MAX __UINT_LEAST32_MAX__
|
||||||
|
#undef INT_LEAST64_MAX
|
||||||
|
#define INT_LEAST64_MAX __INT_LEAST64_MAX__
|
||||||
|
#undef INT_LEAST64_MIN
|
||||||
|
#define INT_LEAST64_MIN (-INT_LEAST64_MAX - 1)
|
||||||
|
#undef UINT_LEAST64_MAX
|
||||||
|
#define UINT_LEAST64_MAX __UINT_LEAST64_MAX__
|
||||||
|
|
||||||
|
#undef INT_FAST8_MAX
|
||||||
|
#define INT_FAST8_MAX __INT_FAST8_MAX__
|
||||||
|
#undef INT_FAST8_MIN
|
||||||
|
#define INT_FAST8_MIN (-INT_FAST8_MAX - 1)
|
||||||
|
#undef UINT_FAST8_MAX
|
||||||
|
#define UINT_FAST8_MAX __UINT_FAST8_MAX__
|
||||||
|
#undef INT_FAST16_MAX
|
||||||
|
#define INT_FAST16_MAX __INT_FAST16_MAX__
|
||||||
|
#undef INT_FAST16_MIN
|
||||||
|
#define INT_FAST16_MIN (-INT_FAST16_MAX - 1)
|
||||||
|
#undef UINT_FAST16_MAX
|
||||||
|
#define UINT_FAST16_MAX __UINT_FAST16_MAX__
|
||||||
|
#undef INT_FAST32_MAX
|
||||||
|
#define INT_FAST32_MAX __INT_FAST32_MAX__
|
||||||
|
#undef INT_FAST32_MIN
|
||||||
|
#define INT_FAST32_MIN (-INT_FAST32_MAX - 1)
|
||||||
|
#undef UINT_FAST32_MAX
|
||||||
|
#define UINT_FAST32_MAX __UINT_FAST32_MAX__
|
||||||
|
#undef INT_FAST64_MAX
|
||||||
|
#define INT_FAST64_MAX __INT_FAST64_MAX__
|
||||||
|
#undef INT_FAST64_MIN
|
||||||
|
#define INT_FAST64_MIN (-INT_FAST64_MAX - 1)
|
||||||
|
#undef UINT_FAST64_MAX
|
||||||
|
#define UINT_FAST64_MAX __UINT_FAST64_MAX__
|
||||||
|
|
||||||
|
#ifdef __INTPTR_MAX__
|
||||||
|
# undef INTPTR_MAX
|
||||||
|
# define INTPTR_MAX __INTPTR_MAX__
|
||||||
|
# undef INTPTR_MIN
|
||||||
|
# define INTPTR_MIN (-INTPTR_MAX - 1)
|
||||||
|
#endif
|
||||||
|
#ifdef __UINTPTR_MAX__
|
||||||
|
# undef UINTPTR_MAX
|
||||||
|
# define UINTPTR_MAX __UINTPTR_MAX__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef INTMAX_MAX
|
||||||
|
#define INTMAX_MAX __INTMAX_MAX__
|
||||||
|
#undef INTMAX_MIN
|
||||||
|
#define INTMAX_MIN (-INTMAX_MAX - 1)
|
||||||
|
#undef UINTMAX_MAX
|
||||||
|
#define UINTMAX_MAX __UINTMAX_MAX__
|
||||||
|
|
||||||
|
/* 7.18.3 Limits of other integer types */
|
||||||
|
|
||||||
|
#undef PTRDIFF_MAX
|
||||||
|
#define PTRDIFF_MAX __PTRDIFF_MAX__
|
||||||
|
#undef PTRDIFF_MIN
|
||||||
|
#define PTRDIFF_MIN (-PTRDIFF_MAX - 1)
|
||||||
|
|
||||||
|
#undef SIG_ATOMIC_MAX
|
||||||
|
#define SIG_ATOMIC_MAX __SIG_ATOMIC_MAX__
|
||||||
|
#undef SIG_ATOMIC_MIN
|
||||||
|
#define SIG_ATOMIC_MIN __SIG_ATOMIC_MIN__
|
||||||
|
|
||||||
|
#undef SIZE_MAX
|
||||||
|
#define SIZE_MAX __SIZE_MAX__
|
||||||
|
|
||||||
|
#undef WCHAR_MAX
|
||||||
|
#define WCHAR_MAX __WCHAR_MAX__
|
||||||
|
#undef WCHAR_MIN
|
||||||
|
#define WCHAR_MIN __WCHAR_MIN__
|
||||||
|
|
||||||
|
#undef WINT_MAX
|
||||||
|
#define WINT_MAX __WINT_MAX__
|
||||||
|
#undef WINT_MIN
|
||||||
|
#define WINT_MIN __WINT_MIN__
|
||||||
|
|
||||||
|
#endif /* (!defined __cplusplus || __cplusplus >= 201103L
|
||||||
|
|| defined __STDC_LIMIT_MACROS) */
|
||||||
|
|
||||||
|
#if (!defined __cplusplus || __cplusplus >= 201103L \
|
||||||
|
|| defined __STDC_CONSTANT_MACROS)
|
||||||
|
|
||||||
|
#undef INT8_C
|
||||||
|
#define INT8_C(c) __INT8_C(c)
|
||||||
|
#undef INT16_C
|
||||||
|
#define INT16_C(c) __INT16_C(c)
|
||||||
|
#undef INT32_C
|
||||||
|
#define INT32_C(c) __INT32_C(c)
|
||||||
|
#undef INT64_C
|
||||||
|
#define INT64_C(c) __INT64_C(c)
|
||||||
|
#undef UINT8_C
|
||||||
|
#define UINT8_C(c) __UINT8_C(c)
|
||||||
|
#undef UINT16_C
|
||||||
|
#define UINT16_C(c) __UINT16_C(c)
|
||||||
|
#undef UINT32_C
|
||||||
|
#define UINT32_C(c) __UINT32_C(c)
|
||||||
|
#undef UINT64_C
|
||||||
|
#define UINT64_C(c) __UINT64_C(c)
|
||||||
|
#undef INTMAX_C
|
||||||
|
#define INTMAX_C(c) __INTMAX_C(c)
|
||||||
|
#undef UINTMAX_C
|
||||||
|
#define UINTMAX_C(c) __UINTMAX_C(c)
|
||||||
|
|
||||||
|
#endif /* (!defined __cplusplus || __cplusplus >= 201103L
|
||||||
|
|| defined __STDC_CONSTANT_MACROS) */
|
||||||
|
|
||||||
|
#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
|
||||||
|
/* TS 18661-1 widths of integer types. */
|
||||||
|
|
||||||
|
#ifdef __INT8_TYPE__
|
||||||
|
# undef INT8_WIDTH
|
||||||
|
# define INT8_WIDTH 8
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT8_TYPE__
|
||||||
|
# undef UINT8_WIDTH
|
||||||
|
# define UINT8_WIDTH 8
|
||||||
|
#endif
|
||||||
|
#ifdef __INT16_TYPE__
|
||||||
|
# undef INT16_WIDTH
|
||||||
|
# define INT16_WIDTH 16
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT16_TYPE__
|
||||||
|
# undef UINT16_WIDTH
|
||||||
|
# define UINT16_WIDTH 16
|
||||||
|
#endif
|
||||||
|
#ifdef __INT32_TYPE__
|
||||||
|
# undef INT32_WIDTH
|
||||||
|
# define INT32_WIDTH 32
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT32_TYPE__
|
||||||
|
# undef UINT32_WIDTH
|
||||||
|
# define UINT32_WIDTH 32
|
||||||
|
#endif
|
||||||
|
#ifdef __INT64_TYPE__
|
||||||
|
# undef INT64_WIDTH
|
||||||
|
# define INT64_WIDTH 64
|
||||||
|
#endif
|
||||||
|
#ifdef __UINT64_TYPE__
|
||||||
|
# undef UINT64_WIDTH
|
||||||
|
# define UINT64_WIDTH 64
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef INT_LEAST8_WIDTH
|
||||||
|
#define INT_LEAST8_WIDTH __INT_LEAST8_WIDTH__
|
||||||
|
#undef UINT_LEAST8_WIDTH
|
||||||
|
#define UINT_LEAST8_WIDTH __INT_LEAST8_WIDTH__
|
||||||
|
#undef INT_LEAST16_WIDTH
|
||||||
|
#define INT_LEAST16_WIDTH __INT_LEAST16_WIDTH__
|
||||||
|
#undef UINT_LEAST16_WIDTH
|
||||||
|
#define UINT_LEAST16_WIDTH __INT_LEAST16_WIDTH__
|
||||||
|
#undef INT_LEAST32_WIDTH
|
||||||
|
#define INT_LEAST32_WIDTH __INT_LEAST32_WIDTH__
|
||||||
|
#undef UINT_LEAST32_WIDTH
|
||||||
|
#define UINT_LEAST32_WIDTH __INT_LEAST32_WIDTH__
|
||||||
|
#undef INT_LEAST64_WIDTH
|
||||||
|
#define INT_LEAST64_WIDTH __INT_LEAST64_WIDTH__
|
||||||
|
#undef UINT_LEAST64_WIDTH
|
||||||
|
#define UINT_LEAST64_WIDTH __INT_LEAST64_WIDTH__
|
||||||
|
|
||||||
|
#undef INT_FAST8_WIDTH
|
||||||
|
#define INT_FAST8_WIDTH __INT_FAST8_WIDTH__
|
||||||
|
#undef UINT_FAST8_WIDTH
|
||||||
|
#define UINT_FAST8_WIDTH __INT_FAST8_WIDTH__
|
||||||
|
#undef INT_FAST16_WIDTH
|
||||||
|
#define INT_FAST16_WIDTH __INT_FAST16_WIDTH__
|
||||||
|
#undef UINT_FAST16_WIDTH
|
||||||
|
#define UINT_FAST16_WIDTH __INT_FAST16_WIDTH__
|
||||||
|
#undef INT_FAST32_WIDTH
|
||||||
|
#define INT_FAST32_WIDTH __INT_FAST32_WIDTH__
|
||||||
|
#undef UINT_FAST32_WIDTH
|
||||||
|
#define UINT_FAST32_WIDTH __INT_FAST32_WIDTH__
|
||||||
|
#undef INT_FAST64_WIDTH
|
||||||
|
#define INT_FAST64_WIDTH __INT_FAST64_WIDTH__
|
||||||
|
#undef UINT_FAST64_WIDTH
|
||||||
|
#define UINT_FAST64_WIDTH __INT_FAST64_WIDTH__
|
||||||
|
|
||||||
|
#ifdef __INTPTR_TYPE__
|
||||||
|
# undef INTPTR_WIDTH
|
||||||
|
# define INTPTR_WIDTH __INTPTR_WIDTH__
|
||||||
|
#endif
|
||||||
|
#ifdef __UINTPTR_TYPE__
|
||||||
|
# undef UINTPTR_WIDTH
|
||||||
|
# define UINTPTR_WIDTH __INTPTR_WIDTH__
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#undef INTMAX_WIDTH
|
||||||
|
#define INTMAX_WIDTH __INTMAX_WIDTH__
|
||||||
|
#undef UINTMAX_WIDTH
|
||||||
|
#define UINTMAX_WIDTH __INTMAX_WIDTH__
|
||||||
|
|
||||||
|
#undef PTRDIFF_WIDTH
|
||||||
|
#define PTRDIFF_WIDTH __PTRDIFF_WIDTH__
|
||||||
|
|
||||||
|
#undef SIG_ATOMIC_WIDTH
|
||||||
|
#define SIG_ATOMIC_WIDTH __SIG_ATOMIC_WIDTH__
|
||||||
|
|
||||||
|
#undef SIZE_WIDTH
|
||||||
|
#define SIZE_WIDTH __SIZE_WIDTH__
|
||||||
|
|
||||||
|
#undef WCHAR_WIDTH
|
||||||
|
#define WCHAR_WIDTH __WCHAR_WIDTH__
|
||||||
|
|
||||||
|
#undef WINT_WIDTH
|
||||||
|
#define WINT_WIDTH __WINT_WIDTH__
|
||||||
|
|
||||||
|
#ifdef __ILP32__
|
||||||
|
#define SIZE_MAX UINT32_MAX
|
||||||
|
#else
|
||||||
|
#define SIZE_MAX UINT64_MAX
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _GCC_STDINT_H */
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _STDIO_EXT_H
|
||||||
|
#define _STDIO_EXT_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
size_t __freadahead(FILE *stream);
|
||||||
|
size_t __fpending(FILE *stream);
|
||||||
|
int __freadable(FILE *stream);
|
||||||
|
int __freading(FILE *stream);
|
||||||
|
void __fseterr(FILE *stream);
|
||||||
|
int __fwritable(FILE *stream);
|
||||||
|
int __fwriting(FILE *stream);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _STDIO_EXT_H */
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
/* Spec:
|
||||||
|
* The <stdnoreturn.h> header shall define the macro noreturn which shall
|
||||||
|
* expand to _Noreturn */
|
||||||
|
|
||||||
|
#ifndef _STDNORETURN_H
|
||||||
|
#define _STDNORETURN_H
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
/* Borrowed from musl */
|
||||||
|
#if __STDC_VERSION__ >= 201112L
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define _Noreturn __attribute__((__noreturn__))
|
||||||
|
#else
|
||||||
|
#define _Noreturn
|
||||||
|
#endif
|
||||||
|
#define noreturn _Noreturn
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#ifndef _SYS_PARAM_H
|
||||||
|
#define _SYS_PARAM_H
|
||||||
|
|
||||||
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
|
||||||
|
#define __bitop(array, index, op) ((array)[(index) / 8] op (1 << (index) % 8))
|
||||||
|
#define setbit(array, index) __bitop(array, index, |=)
|
||||||
|
#define clrbit(array, index) __bitop(array, index, &= ~)
|
||||||
|
#define isset(array, index) __bitop(array, index, &)
|
||||||
|
#define isclr(array, index) !isset(array, index)
|
||||||
|
|
||||||
|
#define howmany(bits, size) (((bits) + (size) - 1) / (size))
|
||||||
|
#define roundup(bits, size) (howmany(bits, size) * (size))
|
||||||
|
#define powerof2(n) !(((n) - 1) & (n))
|
||||||
|
|
||||||
|
// Shamelessly copied from musl.
|
||||||
|
// Tweak as needed.
|
||||||
|
#define MAXSYMLINKS 20
|
||||||
|
#define MAXHOSTNAMELEN 64
|
||||||
|
#define MAXNAMLEN 255
|
||||||
|
#define MAXPATHLEN 4096
|
||||||
|
#define NBBY 8
|
||||||
|
#define NGROUPS 32
|
||||||
|
#define CANBSIZ 255
|
||||||
|
#define NOFILE 256
|
||||||
|
#define NCARGS 131072
|
||||||
|
#define DEV_BSIZE 512
|
||||||
|
#define NOGROUP (-1)
|
||||||
|
|
||||||
|
#include <sys/resource.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <machine/endian.h>
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#include <poll.h>
|
||||||
@@ -0,0 +1,846 @@
|
|||||||
|
/* $NetBSD: queue.h,v 1.70 2015/11/02 15:21:23 christos Exp $ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (c) 1991, 1993
|
||||||
|
* The Regents of the University of California. All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* @(#)queue.h 8.5 (Berkeley) 8/20/94
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SYS_QUEUE_H_
|
||||||
|
#define _SYS_QUEUE_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file defines five types of data structures: singly-linked lists,
|
||||||
|
* lists, simple queues, tail queues, and circular queues.
|
||||||
|
*
|
||||||
|
* A singly-linked list is headed by a single forward pointer. The
|
||||||
|
* elements are singly linked for minimum space and pointer manipulation
|
||||||
|
* overhead at the expense of O(n) removal for arbitrary elements. New
|
||||||
|
* elements can be added to the list after an existing element or at the
|
||||||
|
* head of the list. Elements being removed from the head of the list
|
||||||
|
* should use the explicit macro for this purpose for optimum
|
||||||
|
* efficiency. A singly-linked list may only be traversed in the forward
|
||||||
|
* direction. Singly-linked lists are ideal for applications with large
|
||||||
|
* datasets and few or no removals or for implementing a LIFO queue.
|
||||||
|
*
|
||||||
|
* A list is headed by a single forward pointer (or an array of forward
|
||||||
|
* pointers for a hash table header). The elements are doubly linked
|
||||||
|
* so that an arbitrary element can be removed without a need to
|
||||||
|
* traverse the list. New elements can be added to the list before
|
||||||
|
* or after an existing element or at the head of the list. A list
|
||||||
|
* may only be traversed in the forward direction.
|
||||||
|
*
|
||||||
|
* A simple queue is headed by a pair of pointers, one the head of the
|
||||||
|
* list and the other to the tail of the list. The elements are singly
|
||||||
|
* linked to save space, so elements can only be removed from the
|
||||||
|
* head of the list. New elements can be added to the list after
|
||||||
|
* an existing element, at the head of the list, or at the end of the
|
||||||
|
* list. A simple queue may only be traversed in the forward direction.
|
||||||
|
*
|
||||||
|
* A tail queue is headed by a pair of pointers, one to the head of the
|
||||||
|
* list and the other to the tail of the list. The elements are doubly
|
||||||
|
* linked so that an arbitrary element can be removed without a need to
|
||||||
|
* traverse the list. New elements can be added to the list before or
|
||||||
|
* after an existing element, at the head of the list, or at the end of
|
||||||
|
* the list. A tail queue may be traversed in either direction.
|
||||||
|
*
|
||||||
|
* A circle queue is headed by a pair of pointers, one to the head of the
|
||||||
|
* list and the other to the tail of the list. The elements are doubly
|
||||||
|
* linked so that an arbitrary element can be removed without a need to
|
||||||
|
* traverse the list. New elements can be added to the list before or after
|
||||||
|
* an existing element, at the head of the list, or at the end of the list.
|
||||||
|
* A circle queue may be traversed in either direction, but has a more
|
||||||
|
* complex end of list detection.
|
||||||
|
*
|
||||||
|
* For details on the use of these macros, see the queue(3) manual page.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Include the definition of NULL only on NetBSD because sys/null.h
|
||||||
|
* is not available elsewhere. This conditional makes the header
|
||||||
|
* portable and it can simply be dropped verbatim into any system.
|
||||||
|
* The caveat is that on other systems some other header
|
||||||
|
* must provide NULL before the macros can be used.
|
||||||
|
*/
|
||||||
|
#ifdef __NetBSD__
|
||||||
|
#include <sys/null.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(QUEUEDEBUG)
|
||||||
|
# if defined(_KERNEL)
|
||||||
|
# define QUEUEDEBUG_ABORT(...) panic(__VA_ARGS__)
|
||||||
|
# else
|
||||||
|
# include <err.h>
|
||||||
|
# define QUEUEDEBUG_ABORT(...) err(1, __VA_ARGS__)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked List definitions.
|
||||||
|
*/
|
||||||
|
#define SLIST_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *slh_first; /* first element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SLIST_HEAD_INITIALIZER(head) \
|
||||||
|
{ NULL }
|
||||||
|
|
||||||
|
#define SLIST_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *sle_next; /* next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked List access methods.
|
||||||
|
*/
|
||||||
|
#define SLIST_FIRST(head) ((head)->slh_first)
|
||||||
|
#define SLIST_END(head) NULL
|
||||||
|
#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
|
||||||
|
#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
|
||||||
|
|
||||||
|
#define SLIST_FOREACH(var, head, field) \
|
||||||
|
for((var) = (head)->slh_first; \
|
||||||
|
(var) != SLIST_END(head); \
|
||||||
|
(var) = (var)->field.sle_next)
|
||||||
|
|
||||||
|
#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
|
for ((var) = SLIST_FIRST((head)); \
|
||||||
|
(var) != SLIST_END(head) && \
|
||||||
|
((tvar) = SLIST_NEXT((var), field), 1); \
|
||||||
|
(var) = (tvar))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked List functions.
|
||||||
|
*/
|
||||||
|
#define SLIST_INIT(head) do { \
|
||||||
|
(head)->slh_first = SLIST_END(head); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
|
||||||
|
(elm)->field.sle_next = (slistelm)->field.sle_next; \
|
||||||
|
(slistelm)->field.sle_next = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SLIST_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
(elm)->field.sle_next = (head)->slh_first; \
|
||||||
|
(head)->slh_first = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SLIST_REMOVE_AFTER(slistelm, field) do { \
|
||||||
|
(slistelm)->field.sle_next = \
|
||||||
|
SLIST_NEXT(SLIST_NEXT((slistelm), field), field); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SLIST_REMOVE_HEAD(head, field) do { \
|
||||||
|
(head)->slh_first = (head)->slh_first->field.sle_next; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SLIST_REMOVE(head, elm, type, field) do { \
|
||||||
|
if ((head)->slh_first == (elm)) { \
|
||||||
|
SLIST_REMOVE_HEAD((head), field); \
|
||||||
|
} \
|
||||||
|
else { \
|
||||||
|
struct type *curelm = (head)->slh_first; \
|
||||||
|
while(curelm->field.sle_next != (elm)) \
|
||||||
|
curelm = curelm->field.sle_next; \
|
||||||
|
curelm->field.sle_next = \
|
||||||
|
curelm->field.sle_next->field.sle_next; \
|
||||||
|
} \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List definitions.
|
||||||
|
*/
|
||||||
|
#define LIST_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *lh_first; /* first element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define LIST_HEAD_INITIALIZER(head) \
|
||||||
|
{ NULL }
|
||||||
|
|
||||||
|
#define LIST_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *le_next; /* next element */ \
|
||||||
|
struct type **le_prev; /* address of previous next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List access methods.
|
||||||
|
*/
|
||||||
|
#define LIST_FIRST(head) ((head)->lh_first)
|
||||||
|
#define LIST_END(head) NULL
|
||||||
|
#define LIST_EMPTY(head) ((head)->lh_first == LIST_END(head))
|
||||||
|
#define LIST_NEXT(elm, field) ((elm)->field.le_next)
|
||||||
|
|
||||||
|
#define LIST_FOREACH(var, head, field) \
|
||||||
|
for ((var) = ((head)->lh_first); \
|
||||||
|
(var) != LIST_END(head); \
|
||||||
|
(var) = ((var)->field.le_next))
|
||||||
|
|
||||||
|
#define LIST_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
|
for ((var) = LIST_FIRST((head)); \
|
||||||
|
(var) != LIST_END(head) && \
|
||||||
|
((tvar) = LIST_NEXT((var), field), 1); \
|
||||||
|
(var) = (tvar))
|
||||||
|
|
||||||
|
#define LIST_MOVE(head1, head2) do { \
|
||||||
|
LIST_INIT((head2)); \
|
||||||
|
if (!LIST_EMPTY((head1))) { \
|
||||||
|
(head2)->lh_first = (head1)->lh_first; \
|
||||||
|
LIST_INIT((head1)); \
|
||||||
|
} \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* List functions.
|
||||||
|
*/
|
||||||
|
#if defined(QUEUEDEBUG)
|
||||||
|
#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field) \
|
||||||
|
if ((head)->lh_first && \
|
||||||
|
(head)->lh_first->field.le_prev != &(head)->lh_first) \
|
||||||
|
QUEUEDEBUG_ABORT("LIST_INSERT_HEAD %p %s:%d", (head), \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
#define QUEUEDEBUG_LIST_OP(elm, field) \
|
||||||
|
if ((elm)->field.le_next && \
|
||||||
|
(elm)->field.le_next->field.le_prev != \
|
||||||
|
&(elm)->field.le_next) \
|
||||||
|
QUEUEDEBUG_ABORT("LIST_* forw %p %s:%d", (elm), \
|
||||||
|
__FILE__, __LINE__); \
|
||||||
|
if (*(elm)->field.le_prev != (elm)) \
|
||||||
|
QUEUEDEBUG_ABORT("LIST_* back %p %s:%d", (elm), \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field) \
|
||||||
|
(elm)->field.le_next = (void *)1L; \
|
||||||
|
(elm)->field.le_prev = (void *)1L;
|
||||||
|
#else
|
||||||
|
#define QUEUEDEBUG_LIST_INSERT_HEAD(head, elm, field)
|
||||||
|
#define QUEUEDEBUG_LIST_OP(elm, field)
|
||||||
|
#define QUEUEDEBUG_LIST_POSTREMOVE(elm, field)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define LIST_INIT(head) do { \
|
||||||
|
(head)->lh_first = LIST_END(head); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define LIST_INSERT_AFTER(listelm, elm, field) do { \
|
||||||
|
QUEUEDEBUG_LIST_OP((listelm), field) \
|
||||||
|
if (((elm)->field.le_next = (listelm)->field.le_next) != \
|
||||||
|
LIST_END(head)) \
|
||||||
|
(listelm)->field.le_next->field.le_prev = \
|
||||||
|
&(elm)->field.le_next; \
|
||||||
|
(listelm)->field.le_next = (elm); \
|
||||||
|
(elm)->field.le_prev = &(listelm)->field.le_next; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
|
||||||
|
QUEUEDEBUG_LIST_OP((listelm), field) \
|
||||||
|
(elm)->field.le_prev = (listelm)->field.le_prev; \
|
||||||
|
(elm)->field.le_next = (listelm); \
|
||||||
|
*(listelm)->field.le_prev = (elm); \
|
||||||
|
(listelm)->field.le_prev = &(elm)->field.le_next; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define LIST_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
QUEUEDEBUG_LIST_INSERT_HEAD((head), (elm), field) \
|
||||||
|
if (((elm)->field.le_next = (head)->lh_first) != LIST_END(head))\
|
||||||
|
(head)->lh_first->field.le_prev = &(elm)->field.le_next;\
|
||||||
|
(head)->lh_first = (elm); \
|
||||||
|
(elm)->field.le_prev = &(head)->lh_first; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define LIST_REMOVE(elm, field) do { \
|
||||||
|
QUEUEDEBUG_LIST_OP((elm), field) \
|
||||||
|
if ((elm)->field.le_next != NULL) \
|
||||||
|
(elm)->field.le_next->field.le_prev = \
|
||||||
|
(elm)->field.le_prev; \
|
||||||
|
*(elm)->field.le_prev = (elm)->field.le_next; \
|
||||||
|
QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define LIST_REPLACE(elm, elm2, field) do { \
|
||||||
|
if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
|
||||||
|
(elm2)->field.le_next->field.le_prev = \
|
||||||
|
&(elm2)->field.le_next; \
|
||||||
|
(elm2)->field.le_prev = (elm)->field.le_prev; \
|
||||||
|
*(elm2)->field.le_prev = (elm2); \
|
||||||
|
QUEUEDEBUG_LIST_POSTREMOVE((elm), field) \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple queue definitions.
|
||||||
|
*/
|
||||||
|
#define SIMPLEQ_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *sqh_first; /* first element */ \
|
||||||
|
struct type **sqh_last; /* addr of last next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SIMPLEQ_HEAD_INITIALIZER(head) \
|
||||||
|
{ NULL, &(head).sqh_first }
|
||||||
|
|
||||||
|
#define SIMPLEQ_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *sqe_next; /* next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple queue access methods.
|
||||||
|
*/
|
||||||
|
#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
|
||||||
|
#define SIMPLEQ_END(head) NULL
|
||||||
|
#define SIMPLEQ_EMPTY(head) ((head)->sqh_first == SIMPLEQ_END(head))
|
||||||
|
#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
|
||||||
|
|
||||||
|
#define SIMPLEQ_FOREACH(var, head, field) \
|
||||||
|
for ((var) = ((head)->sqh_first); \
|
||||||
|
(var) != SIMPLEQ_END(head); \
|
||||||
|
(var) = ((var)->field.sqe_next))
|
||||||
|
|
||||||
|
#define SIMPLEQ_FOREACH_SAFE(var, head, field, next) \
|
||||||
|
for ((var) = ((head)->sqh_first); \
|
||||||
|
(var) != SIMPLEQ_END(head) && \
|
||||||
|
((next = ((var)->field.sqe_next)), 1); \
|
||||||
|
(var) = (next))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Simple queue functions.
|
||||||
|
*/
|
||||||
|
#define SIMPLEQ_INIT(head) do { \
|
||||||
|
(head)->sqh_first = NULL; \
|
||||||
|
(head)->sqh_last = &(head)->sqh_first; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
|
||||||
|
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||||
|
(head)->sqh_first = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||||
|
(elm)->field.sqe_next = NULL; \
|
||||||
|
*(head)->sqh_last = (elm); \
|
||||||
|
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||||
|
if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
|
||||||
|
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||||
|
(listelm)->field.sqe_next = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SIMPLEQ_REMOVE_HEAD(head, field) do { \
|
||||||
|
if (((head)->sqh_first = (head)->sqh_first->field.sqe_next) == NULL) \
|
||||||
|
(head)->sqh_last = &(head)->sqh_first; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SIMPLEQ_REMOVE_AFTER(head, elm, field) do { \
|
||||||
|
if (((elm)->field.sqe_next = (elm)->field.sqe_next->field.sqe_next) \
|
||||||
|
== NULL) \
|
||||||
|
(head)->sqh_last = &(elm)->field.sqe_next; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SIMPLEQ_REMOVE(head, elm, type, field) do { \
|
||||||
|
if ((head)->sqh_first == (elm)) { \
|
||||||
|
SIMPLEQ_REMOVE_HEAD((head), field); \
|
||||||
|
} else { \
|
||||||
|
struct type *curelm = (head)->sqh_first; \
|
||||||
|
while (curelm->field.sqe_next != (elm)) \
|
||||||
|
curelm = curelm->field.sqe_next; \
|
||||||
|
if ((curelm->field.sqe_next = \
|
||||||
|
curelm->field.sqe_next->field.sqe_next) == NULL) \
|
||||||
|
(head)->sqh_last = &(curelm)->field.sqe_next; \
|
||||||
|
} \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SIMPLEQ_CONCAT(head1, head2) do { \
|
||||||
|
if (!SIMPLEQ_EMPTY((head2))) { \
|
||||||
|
*(head1)->sqh_last = (head2)->sqh_first; \
|
||||||
|
(head1)->sqh_last = (head2)->sqh_last; \
|
||||||
|
SIMPLEQ_INIT((head2)); \
|
||||||
|
} \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define SIMPLEQ_LAST(head, type, field) \
|
||||||
|
(SIMPLEQ_EMPTY((head)) ? \
|
||||||
|
NULL : \
|
||||||
|
((struct type *)(void *) \
|
||||||
|
((char *)((head)->sqh_last) - offsetof(struct type, field))))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tail queue definitions.
|
||||||
|
*/
|
||||||
|
#define _TAILQ_HEAD(name, type, qual) \
|
||||||
|
struct name { \
|
||||||
|
qual type *tqh_first; /* first element */ \
|
||||||
|
qual type *qual *tqh_last; /* addr of last next element */ \
|
||||||
|
}
|
||||||
|
#define TAILQ_HEAD(name, type) _TAILQ_HEAD(name, struct type,)
|
||||||
|
|
||||||
|
#define TAILQ_HEAD_INITIALIZER(head) \
|
||||||
|
{ TAILQ_END(head), &(head).tqh_first }
|
||||||
|
|
||||||
|
#define _TAILQ_ENTRY(type, qual) \
|
||||||
|
struct { \
|
||||||
|
qual type *tqe_next; /* next element */ \
|
||||||
|
qual type *qual *tqe_prev; /* address of previous next element */\
|
||||||
|
}
|
||||||
|
#define TAILQ_ENTRY(type) _TAILQ_ENTRY(struct type,)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tail queue access methods.
|
||||||
|
*/
|
||||||
|
#define TAILQ_FIRST(head) ((head)->tqh_first)
|
||||||
|
#define TAILQ_END(head) (NULL)
|
||||||
|
#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
|
||||||
|
#define TAILQ_LAST(head, headname) \
|
||||||
|
(*(((struct headname *)(void *)((head)->tqh_last))->tqh_last))
|
||||||
|
#define TAILQ_PREV(elm, headname, field) \
|
||||||
|
(*(((struct headname *)(void *)((elm)->field.tqe_prev))->tqh_last))
|
||||||
|
#define TAILQ_EMPTY(head) (TAILQ_FIRST(head) == TAILQ_END(head))
|
||||||
|
|
||||||
|
|
||||||
|
#define TAILQ_FOREACH(var, head, field) \
|
||||||
|
for ((var) = ((head)->tqh_first); \
|
||||||
|
(var) != TAILQ_END(head); \
|
||||||
|
(var) = ((var)->field.tqe_next))
|
||||||
|
|
||||||
|
#define TAILQ_FOREACH_SAFE(var, head, field, next) \
|
||||||
|
for ((var) = ((head)->tqh_first); \
|
||||||
|
(var) != TAILQ_END(head) && \
|
||||||
|
((next) = TAILQ_NEXT(var, field), 1); (var) = (next))
|
||||||
|
|
||||||
|
#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
|
||||||
|
for ((var) = TAILQ_LAST((head), headname); \
|
||||||
|
(var) != TAILQ_END(head); \
|
||||||
|
(var) = TAILQ_PREV((var), headname, field))
|
||||||
|
|
||||||
|
#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, prev) \
|
||||||
|
for ((var) = TAILQ_LAST((head), headname); \
|
||||||
|
(var) != TAILQ_END(head) && \
|
||||||
|
((prev) = TAILQ_PREV((var), headname, field), 1); (var) = (prev))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Tail queue functions.
|
||||||
|
*/
|
||||||
|
#if defined(QUEUEDEBUG)
|
||||||
|
#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field) \
|
||||||
|
if ((head)->tqh_first && \
|
||||||
|
(head)->tqh_first->field.tqe_prev != &(head)->tqh_first) \
|
||||||
|
QUEUEDEBUG_ABORT("TAILQ_INSERT_HEAD %p %s:%d", (head), \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field) \
|
||||||
|
if (*(head)->tqh_last != NULL) \
|
||||||
|
QUEUEDEBUG_ABORT("TAILQ_INSERT_TAIL %p %s:%d", (head), \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
#define QUEUEDEBUG_TAILQ_OP(elm, field) \
|
||||||
|
if ((elm)->field.tqe_next && \
|
||||||
|
(elm)->field.tqe_next->field.tqe_prev != \
|
||||||
|
&(elm)->field.tqe_next) \
|
||||||
|
QUEUEDEBUG_ABORT("TAILQ_* forw %p %s:%d", (elm), \
|
||||||
|
__FILE__, __LINE__); \
|
||||||
|
if (*(elm)->field.tqe_prev != (elm)) \
|
||||||
|
QUEUEDEBUG_ABORT("TAILQ_* back %p %s:%d", (elm), \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field) \
|
||||||
|
if ((elm)->field.tqe_next == NULL && \
|
||||||
|
(head)->tqh_last != &(elm)->field.tqe_next) \
|
||||||
|
QUEUEDEBUG_ABORT("TAILQ_PREREMOVE head %p elm %p %s:%d",\
|
||||||
|
(head), (elm), __FILE__, __LINE__);
|
||||||
|
#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field) \
|
||||||
|
(elm)->field.tqe_next = (void *)1L; \
|
||||||
|
(elm)->field.tqe_prev = (void *)1L;
|
||||||
|
#else
|
||||||
|
#define QUEUEDEBUG_TAILQ_INSERT_HEAD(head, elm, field)
|
||||||
|
#define QUEUEDEBUG_TAILQ_INSERT_TAIL(head, elm, field)
|
||||||
|
#define QUEUEDEBUG_TAILQ_OP(elm, field)
|
||||||
|
#define QUEUEDEBUG_TAILQ_PREREMOVE(head, elm, field)
|
||||||
|
#define QUEUEDEBUG_TAILQ_POSTREMOVE(elm, field)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TAILQ_INIT(head) do { \
|
||||||
|
(head)->tqh_first = TAILQ_END(head); \
|
||||||
|
(head)->tqh_last = &(head)->tqh_first; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define TAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
QUEUEDEBUG_TAILQ_INSERT_HEAD((head), (elm), field) \
|
||||||
|
if (((elm)->field.tqe_next = (head)->tqh_first) != TAILQ_END(head))\
|
||||||
|
(head)->tqh_first->field.tqe_prev = \
|
||||||
|
&(elm)->field.tqe_next; \
|
||||||
|
else \
|
||||||
|
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||||
|
(head)->tqh_first = (elm); \
|
||||||
|
(elm)->field.tqe_prev = &(head)->tqh_first; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define TAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||||
|
QUEUEDEBUG_TAILQ_INSERT_TAIL((head), (elm), field) \
|
||||||
|
(elm)->field.tqe_next = TAILQ_END(head); \
|
||||||
|
(elm)->field.tqe_prev = (head)->tqh_last; \
|
||||||
|
*(head)->tqh_last = (elm); \
|
||||||
|
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||||
|
QUEUEDEBUG_TAILQ_OP((listelm), field) \
|
||||||
|
if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != \
|
||||||
|
TAILQ_END(head)) \
|
||||||
|
(elm)->field.tqe_next->field.tqe_prev = \
|
||||||
|
&(elm)->field.tqe_next; \
|
||||||
|
else \
|
||||||
|
(head)->tqh_last = &(elm)->field.tqe_next; \
|
||||||
|
(listelm)->field.tqe_next = (elm); \
|
||||||
|
(elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
|
||||||
|
QUEUEDEBUG_TAILQ_OP((listelm), field) \
|
||||||
|
(elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
|
||||||
|
(elm)->field.tqe_next = (listelm); \
|
||||||
|
*(listelm)->field.tqe_prev = (elm); \
|
||||||
|
(listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define TAILQ_REMOVE(head, elm, field) do { \
|
||||||
|
QUEUEDEBUG_TAILQ_PREREMOVE((head), (elm), field) \
|
||||||
|
QUEUEDEBUG_TAILQ_OP((elm), field) \
|
||||||
|
if (((elm)->field.tqe_next) != TAILQ_END(head)) \
|
||||||
|
(elm)->field.tqe_next->field.tqe_prev = \
|
||||||
|
(elm)->field.tqe_prev; \
|
||||||
|
else \
|
||||||
|
(head)->tqh_last = (elm)->field.tqe_prev; \
|
||||||
|
*(elm)->field.tqe_prev = (elm)->field.tqe_next; \
|
||||||
|
QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define TAILQ_REPLACE(head, elm, elm2, field) do { \
|
||||||
|
if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != \
|
||||||
|
TAILQ_END(head)) \
|
||||||
|
(elm2)->field.tqe_next->field.tqe_prev = \
|
||||||
|
&(elm2)->field.tqe_next; \
|
||||||
|
else \
|
||||||
|
(head)->tqh_last = &(elm2)->field.tqe_next; \
|
||||||
|
(elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
|
||||||
|
*(elm2)->field.tqe_prev = (elm2); \
|
||||||
|
QUEUEDEBUG_TAILQ_POSTREMOVE((elm), field); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define TAILQ_CONCAT(head1, head2, field) do { \
|
||||||
|
if (!TAILQ_EMPTY(head2)) { \
|
||||||
|
*(head1)->tqh_last = (head2)->tqh_first; \
|
||||||
|
(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
|
||||||
|
(head1)->tqh_last = (head2)->tqh_last; \
|
||||||
|
TAILQ_INIT((head2)); \
|
||||||
|
} \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked Tail queue declarations.
|
||||||
|
*/
|
||||||
|
#define STAILQ_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *stqh_first; /* first element */ \
|
||||||
|
struct type **stqh_last; /* addr of last next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define STAILQ_HEAD_INITIALIZER(head) \
|
||||||
|
{ NULL, &(head).stqh_first }
|
||||||
|
|
||||||
|
#define STAILQ_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *stqe_next; /* next element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked Tail queue access methods.
|
||||||
|
*/
|
||||||
|
#define STAILQ_FIRST(head) ((head)->stqh_first)
|
||||||
|
#define STAILQ_END(head) NULL
|
||||||
|
#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
|
||||||
|
#define STAILQ_EMPTY(head) (STAILQ_FIRST(head) == STAILQ_END(head))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Singly-linked Tail queue functions.
|
||||||
|
*/
|
||||||
|
#define STAILQ_INIT(head) do { \
|
||||||
|
(head)->stqh_first = NULL; \
|
||||||
|
(head)->stqh_last = &(head)->stqh_first; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define STAILQ_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
if (((elm)->field.stqe_next = (head)->stqh_first) == NULL) \
|
||||||
|
(head)->stqh_last = &(elm)->field.stqe_next; \
|
||||||
|
(head)->stqh_first = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define STAILQ_INSERT_TAIL(head, elm, field) do { \
|
||||||
|
(elm)->field.stqe_next = NULL; \
|
||||||
|
*(head)->stqh_last = (elm); \
|
||||||
|
(head)->stqh_last = &(elm)->field.stqe_next; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define STAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||||
|
if (((elm)->field.stqe_next = (listelm)->field.stqe_next) == NULL)\
|
||||||
|
(head)->stqh_last = &(elm)->field.stqe_next; \
|
||||||
|
(listelm)->field.stqe_next = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define STAILQ_REMOVE_HEAD(head, field) do { \
|
||||||
|
if (((head)->stqh_first = (head)->stqh_first->field.stqe_next) == NULL) \
|
||||||
|
(head)->stqh_last = &(head)->stqh_first; \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define STAILQ_REMOVE(head, elm, type, field) do { \
|
||||||
|
if ((head)->stqh_first == (elm)) { \
|
||||||
|
STAILQ_REMOVE_HEAD((head), field); \
|
||||||
|
} else { \
|
||||||
|
struct type *curelm = (head)->stqh_first; \
|
||||||
|
while (curelm->field.stqe_next != (elm)) \
|
||||||
|
curelm = curelm->field.stqe_next; \
|
||||||
|
if ((curelm->field.stqe_next = \
|
||||||
|
curelm->field.stqe_next->field.stqe_next) == NULL) \
|
||||||
|
(head)->stqh_last = &(curelm)->field.stqe_next; \
|
||||||
|
} \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define STAILQ_FOREACH(var, head, field) \
|
||||||
|
for ((var) = ((head)->stqh_first); \
|
||||||
|
(var); \
|
||||||
|
(var) = ((var)->field.stqe_next))
|
||||||
|
|
||||||
|
#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
|
||||||
|
for ((var) = STAILQ_FIRST((head)); \
|
||||||
|
(var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
|
||||||
|
(var) = (tvar))
|
||||||
|
|
||||||
|
#define STAILQ_CONCAT(head1, head2) do { \
|
||||||
|
if (!STAILQ_EMPTY((head2))) { \
|
||||||
|
*(head1)->stqh_last = (head2)->stqh_first; \
|
||||||
|
(head1)->stqh_last = (head2)->stqh_last; \
|
||||||
|
STAILQ_INIT((head2)); \
|
||||||
|
} \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define STAILQ_LAST(head, type, field) \
|
||||||
|
(STAILQ_EMPTY((head)) ? \
|
||||||
|
NULL : \
|
||||||
|
((struct type *)(void *) \
|
||||||
|
((char *)((head)->stqh_last) - offsetof(struct type, field))))
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _KERNEL
|
||||||
|
/*
|
||||||
|
* Circular queue definitions. Do not use. We still keep the macros
|
||||||
|
* for compatibility but because of pointer aliasing issues their use
|
||||||
|
* is discouraged!
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* __launder_type(): We use this ugly hack to work around the the compiler
|
||||||
|
* noticing that two types may not alias each other and elide tests in code.
|
||||||
|
* We hit this in the CIRCLEQ macros when comparing 'struct name *' and
|
||||||
|
* 'struct type *' (see CIRCLEQ_HEAD()). Modern compilers (such as GCC
|
||||||
|
* 4.8) declare these comparisons as always false, causing the code to
|
||||||
|
* not run as designed.
|
||||||
|
*
|
||||||
|
* This hack is only to be used for comparisons and thus can be fully const.
|
||||||
|
* Do not use for assignment.
|
||||||
|
*
|
||||||
|
* If we ever choose to change the ABI of the CIRCLEQ macros, we could fix
|
||||||
|
* this by changing the head/tail sentinal values, but see the note above
|
||||||
|
* this one.
|
||||||
|
*/
|
||||||
|
static __inline const void * __launder_type(const void *);
|
||||||
|
static __inline const void *
|
||||||
|
__launder_type(const void *__x)
|
||||||
|
{
|
||||||
|
__asm __volatile("" : "+r" (__x));
|
||||||
|
return __x;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if defined(QUEUEDEBUG)
|
||||||
|
#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field) \
|
||||||
|
if ((head)->cqh_first != CIRCLEQ_ENDC(head) && \
|
||||||
|
(head)->cqh_first->field.cqe_prev != CIRCLEQ_ENDC(head)) \
|
||||||
|
QUEUEDEBUG_ABORT("CIRCLEQ head forw %p %s:%d", (head), \
|
||||||
|
__FILE__, __LINE__); \
|
||||||
|
if ((head)->cqh_last != CIRCLEQ_ENDC(head) && \
|
||||||
|
(head)->cqh_last->field.cqe_next != CIRCLEQ_ENDC(head)) \
|
||||||
|
QUEUEDEBUG_ABORT("CIRCLEQ head back %p %s:%d", (head), \
|
||||||
|
__FILE__, __LINE__);
|
||||||
|
#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field) \
|
||||||
|
if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) { \
|
||||||
|
if ((head)->cqh_last != (elm)) \
|
||||||
|
QUEUEDEBUG_ABORT("CIRCLEQ elm last %p %s:%d", \
|
||||||
|
(elm), __FILE__, __LINE__); \
|
||||||
|
} else { \
|
||||||
|
if ((elm)->field.cqe_next->field.cqe_prev != (elm)) \
|
||||||
|
QUEUEDEBUG_ABORT("CIRCLEQ elm forw %p %s:%d", \
|
||||||
|
(elm), __FILE__, __LINE__); \
|
||||||
|
} \
|
||||||
|
if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) { \
|
||||||
|
if ((head)->cqh_first != (elm)) \
|
||||||
|
QUEUEDEBUG_ABORT("CIRCLEQ elm first %p %s:%d", \
|
||||||
|
(elm), __FILE__, __LINE__); \
|
||||||
|
} else { \
|
||||||
|
if ((elm)->field.cqe_prev->field.cqe_next != (elm)) \
|
||||||
|
QUEUEDEBUG_ABORT("CIRCLEQ elm prev %p %s:%d", \
|
||||||
|
(elm), __FILE__, __LINE__); \
|
||||||
|
}
|
||||||
|
#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field) \
|
||||||
|
(elm)->field.cqe_next = (void *)1L; \
|
||||||
|
(elm)->field.cqe_prev = (void *)1L;
|
||||||
|
#else
|
||||||
|
#define QUEUEDEBUG_CIRCLEQ_HEAD(head, field)
|
||||||
|
#define QUEUEDEBUG_CIRCLEQ_ELM(head, elm, field)
|
||||||
|
#define QUEUEDEBUG_CIRCLEQ_POSTREMOVE(elm, field)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define CIRCLEQ_HEAD(name, type) \
|
||||||
|
struct name { \
|
||||||
|
struct type *cqh_first; /* first element */ \
|
||||||
|
struct type *cqh_last; /* last element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define CIRCLEQ_HEAD_INITIALIZER(head) \
|
||||||
|
{ CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
|
||||||
|
|
||||||
|
#define CIRCLEQ_ENTRY(type) \
|
||||||
|
struct { \
|
||||||
|
struct type *cqe_next; /* next element */ \
|
||||||
|
struct type *cqe_prev; /* previous element */ \
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Circular queue functions.
|
||||||
|
*/
|
||||||
|
#define CIRCLEQ_INIT(head) do { \
|
||||||
|
(head)->cqh_first = CIRCLEQ_END(head); \
|
||||||
|
(head)->cqh_last = CIRCLEQ_END(head); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
|
||||||
|
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
|
||||||
|
QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
|
||||||
|
(elm)->field.cqe_next = (listelm)->field.cqe_next; \
|
||||||
|
(elm)->field.cqe_prev = (listelm); \
|
||||||
|
if ((listelm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
|
||||||
|
(head)->cqh_last = (elm); \
|
||||||
|
else \
|
||||||
|
(listelm)->field.cqe_next->field.cqe_prev = (elm); \
|
||||||
|
(listelm)->field.cqe_next = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
|
||||||
|
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
|
||||||
|
QUEUEDEBUG_CIRCLEQ_ELM((head), (listelm), field) \
|
||||||
|
(elm)->field.cqe_next = (listelm); \
|
||||||
|
(elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
|
||||||
|
if ((listelm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
|
||||||
|
(head)->cqh_first = (elm); \
|
||||||
|
else \
|
||||||
|
(listelm)->field.cqe_prev->field.cqe_next = (elm); \
|
||||||
|
(listelm)->field.cqe_prev = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
|
||||||
|
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
|
||||||
|
(elm)->field.cqe_next = (head)->cqh_first; \
|
||||||
|
(elm)->field.cqe_prev = CIRCLEQ_END(head); \
|
||||||
|
if ((head)->cqh_last == CIRCLEQ_ENDC(head)) \
|
||||||
|
(head)->cqh_last = (elm); \
|
||||||
|
else \
|
||||||
|
(head)->cqh_first->field.cqe_prev = (elm); \
|
||||||
|
(head)->cqh_first = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
|
||||||
|
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
|
||||||
|
(elm)->field.cqe_next = CIRCLEQ_END(head); \
|
||||||
|
(elm)->field.cqe_prev = (head)->cqh_last; \
|
||||||
|
if ((head)->cqh_first == CIRCLEQ_ENDC(head)) \
|
||||||
|
(head)->cqh_first = (elm); \
|
||||||
|
else \
|
||||||
|
(head)->cqh_last->field.cqe_next = (elm); \
|
||||||
|
(head)->cqh_last = (elm); \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define CIRCLEQ_REMOVE(head, elm, field) do { \
|
||||||
|
QUEUEDEBUG_CIRCLEQ_HEAD((head), field) \
|
||||||
|
QUEUEDEBUG_CIRCLEQ_ELM((head), (elm), field) \
|
||||||
|
if ((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
|
||||||
|
(head)->cqh_last = (elm)->field.cqe_prev; \
|
||||||
|
else \
|
||||||
|
(elm)->field.cqe_next->field.cqe_prev = \
|
||||||
|
(elm)->field.cqe_prev; \
|
||||||
|
if ((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
|
||||||
|
(head)->cqh_first = (elm)->field.cqe_next; \
|
||||||
|
else \
|
||||||
|
(elm)->field.cqe_prev->field.cqe_next = \
|
||||||
|
(elm)->field.cqe_next; \
|
||||||
|
QUEUEDEBUG_CIRCLEQ_POSTREMOVE((elm), field) \
|
||||||
|
} while (/*CONSTCOND*/0)
|
||||||
|
|
||||||
|
#define CIRCLEQ_FOREACH(var, head, field) \
|
||||||
|
for ((var) = ((head)->cqh_first); \
|
||||||
|
(var) != CIRCLEQ_ENDC(head); \
|
||||||
|
(var) = ((var)->field.cqe_next))
|
||||||
|
|
||||||
|
#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
|
||||||
|
for ((var) = ((head)->cqh_last); \
|
||||||
|
(var) != CIRCLEQ_ENDC(head); \
|
||||||
|
(var) = ((var)->field.cqe_prev))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Circular queue access methods.
|
||||||
|
*/
|
||||||
|
#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
|
||||||
|
#define CIRCLEQ_LAST(head) ((head)->cqh_last)
|
||||||
|
/* For comparisons */
|
||||||
|
#define CIRCLEQ_ENDC(head) (__launder_type(head))
|
||||||
|
/* For assignments */
|
||||||
|
#define CIRCLEQ_END(head) ((void *)(head))
|
||||||
|
#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
|
||||||
|
#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
|
||||||
|
#define CIRCLEQ_EMPTY(head) \
|
||||||
|
(CIRCLEQ_FIRST(head) == CIRCLEQ_ENDC(head))
|
||||||
|
|
||||||
|
#define CIRCLEQ_LOOP_NEXT(head, elm, field) \
|
||||||
|
(((elm)->field.cqe_next == CIRCLEQ_ENDC(head)) \
|
||||||
|
? ((head)->cqh_first) \
|
||||||
|
: (elm->field.cqe_next))
|
||||||
|
#define CIRCLEQ_LOOP_PREV(head, elm, field) \
|
||||||
|
(((elm)->field.cqe_prev == CIRCLEQ_ENDC(head)) \
|
||||||
|
? ((head)->cqh_last) \
|
||||||
|
: (elm->field.cqe_prev))
|
||||||
|
#endif /* !_KERNEL */
|
||||||
|
|
||||||
|
#endif /* !_SYS_QUEUE_H_ */
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
#ifndef _SYS_REDOX_H
|
||||||
|
#define _SYS_REDOX_H
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __redox__
|
||||||
|
|
||||||
|
ssize_t redox_fpath(int fd, void * buf, size_t count);
|
||||||
|
void * redox_physalloc(size_t size);
|
||||||
|
int redox_physfree(void * physical_address, size_t size);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// From musl, license MIT
|
||||||
|
#ifndef _SYS_SYSMACROS_H
|
||||||
|
#define _SYS_SYSMACROS_H
|
||||||
|
|
||||||
|
#define major(x) \
|
||||||
|
((unsigned)( (((x)>>31>>1) & 0xfffff000) | (((x)>>8) & 0x00000fff) ))
|
||||||
|
#define minor(x) \
|
||||||
|
((unsigned)( (((x)>>12) & 0xffffff00) | ((x) & 0x000000ff) ))
|
||||||
|
|
||||||
|
#define makedev(x,y) ( \
|
||||||
|
(((x)&0xfffff000ULL) << 32) | \
|
||||||
|
(((x)&0x00000fffULL) << 8) | \
|
||||||
|
(((y)&0xffffff00ULL) << 12) | \
|
||||||
|
(((y)&0x000000ffULL)) )
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
#ifndef _SYS_USER_H
|
||||||
|
#define _SYS_USER_H
|
||||||
|
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_AMD64)
|
||||||
|
#include <arch/x64/user.h>
|
||||||
|
#elif defined(__aarch64__)
|
||||||
|
#include <arch/aarch64/user.h>
|
||||||
|
#elif defined(__riscv) && __riscv_xlen==64
|
||||||
|
#include <arch/riscv64/user.h>
|
||||||
|
#else
|
||||||
|
#error "Unknown architecture"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
#ifndef _SYSEXITS_H
|
||||||
|
#define _SYSEXITS_H
|
||||||
|
|
||||||
|
#define EX_OK 0
|
||||||
|
#define EX_USAGE 64
|
||||||
|
#define EX_DATAERR 65
|
||||||
|
#define EX_NOINPUT 66
|
||||||
|
#define EX_NOUSER 67
|
||||||
|
#define EX_NOHOST 68
|
||||||
|
#define EX_UNAVAILABLE 69
|
||||||
|
#define EX_SOFTWARE 70
|
||||||
|
#define EX_OSERR 71
|
||||||
|
#define EX_OSFILE 72
|
||||||
|
#define EX_CANTCREAT 73
|
||||||
|
#define EX_IOERR 74
|
||||||
|
#define EX_TEMPFAIL 75
|
||||||
|
#define EX_PROTOCOL 76
|
||||||
|
#define EX_NOPERM 77
|
||||||
|
#define EX_CONFIG 78
|
||||||
|
|
||||||
|
#endif /* _SYSEXITS_H */
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
#include <sys/syslog.h>
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "ld_so"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
name = "ld_so"
|
||||||
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
|
[lints]
|
||||||
|
workspace = true
|
||||||
@@ -0,0 +1,263 @@
|
|||||||
|
/* Script for -z combreloc */
|
||||||
|
/* Copyright (C) 2014-2025 Free Software Foundation, Inc.
|
||||||
|
Copying and distribution of this script, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. */
|
||||||
|
OUTPUT_FORMAT("elf64-littleaarch64", "elf64-bigaarch64", "elf64-littleaarch64")
|
||||||
|
OUTPUT_ARCH(aarch64)
|
||||||
|
ENTRY(_start)
|
||||||
|
SEARCH_DIR("=/usr/aarch64-linux-gnu/lib64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/aarch64-linux-gnu/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib");
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000));
|
||||||
|
. = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
|
||||||
|
/* Place the build-id as close to the ELF headers as possible. This
|
||||||
|
maximises the chance the build-id will be present in core files,
|
||||||
|
which GDB can then use to locate the associated debuginfo file. */
|
||||||
|
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||||
|
.interp : { *(.interp) }
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.gnu.hash : { *(.gnu.hash) }
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.gnu.version : { *(.gnu.version) }
|
||||||
|
.gnu.version_d : { *(.gnu.version_d) }
|
||||||
|
.gnu.version_r : { *(.gnu.version_r) }
|
||||||
|
.rela.dyn :
|
||||||
|
{
|
||||||
|
*(.rela.init)
|
||||||
|
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||||
|
*(.rela.fini)
|
||||||
|
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||||
|
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||||
|
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||||
|
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||||
|
*(.rela.ctors)
|
||||||
|
*(.rela.dtors)
|
||||||
|
*(.rela.got)
|
||||||
|
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||||
|
*(.rela.ifunc)
|
||||||
|
}
|
||||||
|
.rela.plt :
|
||||||
|
{
|
||||||
|
*(.rela.plt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||||
|
*(.rela.iplt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||||
|
}
|
||||||
|
.relr.dyn : { *(.relr.dyn) }
|
||||||
|
/* Start of the executable code region. */
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.init)))
|
||||||
|
} =0x1f2003d5
|
||||||
|
.plt : ALIGN(16) { *(.plt) *(.iplt) }
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(SORT(.text.sorted.*))
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
} =0x1f2003d5
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.fini)))
|
||||||
|
} =0x1f2003d5
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
/* Start of the Read Only Data region. */
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.sframe : ONLY_IF_RO { *(.sframe) *(.sframe.*) }
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||||
|
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||||
|
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||||
|
/* Various note sections. Placed here so that they are always included
|
||||||
|
in the read-only segment and not treated as orphan sections. The
|
||||||
|
current orphan handling algorithm does place note sections after R/O
|
||||||
|
data, but this is not guaranteed to always be the case. */
|
||||||
|
.note.build-id : { *(.note.build-id) }
|
||||||
|
.note.GNU-stack : { *(.note.GNU-stack) }
|
||||||
|
.note.gnu-property : { *(.note.gnu-property) }
|
||||||
|
.note.ABI-tag : { *(.note.ABI-tag) }
|
||||||
|
.note.package : { *(.note.package) }
|
||||||
|
.note.dlopen : { *(.note.dlopen) }
|
||||||
|
.note.netbsd.ident : { *(.note.netbsd.ident) }
|
||||||
|
.note.openbsd.ident : { *(.note.openbsd.ident) }
|
||||||
|
/* Start of the Read Write Data region. */
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||||
|
/* Exception handling. */
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.sframe : ONLY_IF_RW { *(.sframe) *(.sframe.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||||
|
/* Thread Local Storage sections. */
|
||||||
|
/* .tdata :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__tdata_start = .);
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
}
|
||||||
|
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
/* .init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
} */
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*crtbegin?.o(.ctors))
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
}
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*crtbegin?.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
}
|
||||||
|
.jcr : { KEEP (*(.jcr)) }
|
||||||
|
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
.got : { *(.got) *(.igot) }
|
||||||
|
. = DATA_SEGMENT_RELRO_END (24, .);
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
PROVIDE (__data_start = .);
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
_edata = .;
|
||||||
|
PROVIDE (edata = .);
|
||||||
|
. = ALIGN(ALIGNOF(NEXT_SECTION));
|
||||||
|
__bss_start = .;
|
||||||
|
__bss_start__ = .;
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
/* Align here to ensure that in the common case of there only being one
|
||||||
|
type of .bss section, the section occupies space up to _end.
|
||||||
|
Align after .bss to ensure correct alignment even if the
|
||||||
|
.bss section disappears because there are no input sections.
|
||||||
|
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||||
|
pad the .data section. */
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
_bss_end__ = .; __bss_end__ = .;
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
/* Start of the Large Data region. */
|
||||||
|
. = SEGMENT_START("ldata-segment", .);
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
__end__ = .;
|
||||||
|
_end = .;
|
||||||
|
PROVIDE (end = .);
|
||||||
|
. = DATA_SEGMENT_END (.);
|
||||||
|
/* Start of the Tiny Data region. */
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 (INFO) : { *(.comment); LINKER_VERSION; }
|
||||||
|
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1. */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions. */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2. */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2. */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions. */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* DWARF 3. */
|
||||||
|
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
/* DWARF 5. */
|
||||||
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
|
.debug_line_str 0 : { *(.debug_line_str) }
|
||||||
|
.debug_loclists 0 : { *(.debug_loclists) }
|
||||||
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
|
.debug_names 0 : { *(.debug_names) }
|
||||||
|
.debug_rnglists 0 : { *(.debug_rnglists) }
|
||||||
|
.debug_str_offsets 0 : { *(.debug_str_offsets) }
|
||||||
|
.debug_sup 0 : { *(.debug_sup) }
|
||||||
|
.ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }
|
||||||
|
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||||
|
/*
|
||||||
|
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||||
|
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||||
|
* that may reference use thread local storage.
|
||||||
|
*
|
||||||
|
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||||
|
*/
|
||||||
|
*(.gnu.linkonce.tb.*) *(.tcommon)
|
||||||
|
*(.init_array)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,255 @@
|
|||||||
|
/* Script for -z combreloc */
|
||||||
|
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||||
|
Copying and distribution of this script, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. */
|
||||||
|
OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64",
|
||||||
|
"elf64-littleaarch64")
|
||||||
|
OUTPUT_ARCH(aarch64)
|
||||||
|
ENTRY(_start)
|
||||||
|
SEARCH_DIR("/aarch64-unknown-redox/lib");
|
||||||
|
SEARCH_DIR("/usr/local/lib64");
|
||||||
|
SEARCH_DIR("/lib64");
|
||||||
|
SEARCH_DIR("/usr/lib64");
|
||||||
|
SEARCH_DIR("/usr/local/lib");
|
||||||
|
SEARCH_DIR("/lib");
|
||||||
|
SEARCH_DIR("/usr/lib");
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
|
||||||
|
.interp : { *(.interp) }
|
||||||
|
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.gnu.hash : { *(.gnu.hash) }
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.gnu.version : { *(.gnu.version) }
|
||||||
|
.gnu.version_d : { *(.gnu.version_d) }
|
||||||
|
.gnu.version_r : { *(.gnu.version_r) }
|
||||||
|
.rela.dyn :
|
||||||
|
{
|
||||||
|
*(.rela.init)
|
||||||
|
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||||
|
*(.rela.fini)
|
||||||
|
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||||
|
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||||
|
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||||
|
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||||
|
*(.rela.ctors)
|
||||||
|
*(.rela.dtors)
|
||||||
|
*(.rela.got)
|
||||||
|
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||||
|
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
|
||||||
|
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
|
||||||
|
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
|
||||||
|
*(.rela.ifunc)
|
||||||
|
}
|
||||||
|
.rela.plt :
|
||||||
|
{
|
||||||
|
*(.rela.plt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||||
|
*(.rela.iplt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||||
|
}
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.init)))
|
||||||
|
}
|
||||||
|
.plt : { *(.plt) *(.iplt) }
|
||||||
|
.plt.got : { *(.plt.got) }
|
||||||
|
.plt.sec : { *(.plt.sec) }
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
}
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.fini)))
|
||||||
|
}
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
/* Adjust the address for the rodata segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||||
|
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||||
|
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||||
|
/* Exception handling */
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||||
|
/* Thread Local Storage sections */
|
||||||
|
/* .tdata :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__tdata_start = .);
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
}
|
||||||
|
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
.init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
}
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*crtbegin?.o(.ctors))
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
}
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*crtbegin?.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
}
|
||||||
|
.jcr : { KEEP (*(.jcr)) }
|
||||||
|
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
.got : { *(.got) *(.igot) }
|
||||||
|
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
_edata = .; PROVIDE (edata = .);
|
||||||
|
. = .;
|
||||||
|
__bss_start = .;
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
/* Align here to ensure that the .bss section occupies space up to
|
||||||
|
_end. Align after .bss to ensure correct alignment even if the
|
||||||
|
.bss section disappears because there are no input sections.
|
||||||
|
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||||
|
pad the .data section. */
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
.lbss :
|
||||||
|
{
|
||||||
|
*(.dynlbss)
|
||||||
|
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||||
|
*(LARGE_COMMON)
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
. = SEGMENT_START("ldata-segment", .);
|
||||||
|
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||||
|
}
|
||||||
|
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
_end = .; PROVIDE (end = .);
|
||||||
|
. = DATA_SEGMENT_END (.);
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* DWARF 3 */
|
||||||
|
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
/* DWARF Extension. */
|
||||||
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
|
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||||
|
/*
|
||||||
|
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||||
|
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||||
|
* that may reference use thread local storage.
|
||||||
|
*
|
||||||
|
* .init_array need to be not discarded unlike x86_64 linker variant
|
||||||
|
*/
|
||||||
|
*(.gnu.linkonce.tb.*) *(.tcommon)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
/* Script for -z combreloc */
|
||||||
|
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||||
|
Copying and distribution of this script, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. */
|
||||||
|
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
|
||||||
|
"elf32-i386")
|
||||||
|
OUTPUT_ARCH(i386)
|
||||||
|
ENTRY(_start)
|
||||||
|
SEARCH_DIR("/i686-unknown-redox/lib");
|
||||||
|
SEARCH_DIR("/usr/local/lib32");
|
||||||
|
SEARCH_DIR("/lib32");
|
||||||
|
SEARCH_DIR("/usr/lib32");
|
||||||
|
SEARCH_DIR("/usr/local/lib");
|
||||||
|
SEARCH_DIR("/lib");
|
||||||
|
SEARCH_DIR("/usr/lib");
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
|
||||||
|
.interp : { *(.interp) }
|
||||||
|
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.gnu.hash : { *(.gnu.hash) }
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.gnu.version : { *(.gnu.version) }
|
||||||
|
.gnu.version_d : { *(.gnu.version_d) }
|
||||||
|
.gnu.version_r : { *(.gnu.version_r) }
|
||||||
|
.rela.dyn :
|
||||||
|
{
|
||||||
|
*(.rela.init)
|
||||||
|
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||||
|
*(.rela.fini)
|
||||||
|
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||||
|
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||||
|
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||||
|
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||||
|
*(.rela.ctors)
|
||||||
|
*(.rela.dtors)
|
||||||
|
*(.rela.got)
|
||||||
|
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||||
|
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
|
||||||
|
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
|
||||||
|
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
|
||||||
|
*(.rela.ifunc)
|
||||||
|
}
|
||||||
|
.rela.plt :
|
||||||
|
{
|
||||||
|
*(.rela.plt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||||
|
*(.rela.iplt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||||
|
}
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.init)))
|
||||||
|
}
|
||||||
|
.plt : { *(.plt) *(.iplt) }
|
||||||
|
.plt.got : { *(.plt.got) }
|
||||||
|
.plt.sec : { *(.plt.sec) }
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
}
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.fini)))
|
||||||
|
}
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
/* Adjust the address for the rodata segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||||
|
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||||
|
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||||
|
/* Exception handling */
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||||
|
/* Thread Local Storage sections */
|
||||||
|
/* .tdata :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__tdata_start = .);
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
}
|
||||||
|
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
/* .init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
} */
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*crtbegin?.o(.ctors))
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
}
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*crtbegin?.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
}
|
||||||
|
.jcr : { KEEP (*(.jcr)) }
|
||||||
|
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
.got : { *(.got) *(.igot) }
|
||||||
|
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
_edata = .; PROVIDE (edata = .);
|
||||||
|
. = .;
|
||||||
|
__bss_start = .;
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
/* Align here to ensure that the .bss section occupies space up to
|
||||||
|
_end. Align after .bss to ensure correct alignment even if the
|
||||||
|
.bss section disappears because there are no input sections.
|
||||||
|
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||||
|
pad the .data section. */
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
.lbss :
|
||||||
|
{
|
||||||
|
*(.dynlbss)
|
||||||
|
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||||
|
*(LARGE_COMMON)
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
. = SEGMENT_START("ldata-segment", .);
|
||||||
|
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||||
|
}
|
||||||
|
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
_end = .; PROVIDE (end = .);
|
||||||
|
. = DATA_SEGMENT_END (.);
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* DWARF 3 */
|
||||||
|
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
/* DWARF Extension. */
|
||||||
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
|
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||||
|
/*
|
||||||
|
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||||
|
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||||
|
* that may reference use thread local storage.
|
||||||
|
*
|
||||||
|
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||||
|
*/
|
||||||
|
*(.gnu.linkonce.tb.*) *(.tcommon)
|
||||||
|
*(.init_array)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
/* Script for -z combreloc */
|
||||||
|
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||||
|
Copying and distribution of this script, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. */
|
||||||
|
OUTPUT_FORMAT("elf32-i386", "elf32-i386",
|
||||||
|
"elf32-i386")
|
||||||
|
OUTPUT_ARCH(i386)
|
||||||
|
ENTRY(_start)
|
||||||
|
SEARCH_DIR("/i686-unknown-redox/lib");
|
||||||
|
SEARCH_DIR("/usr/local/lib32");
|
||||||
|
SEARCH_DIR("/lib32");
|
||||||
|
SEARCH_DIR("/usr/lib32");
|
||||||
|
SEARCH_DIR("/usr/local/lib");
|
||||||
|
SEARCH_DIR("/lib");
|
||||||
|
SEARCH_DIR("/usr/lib");
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
|
||||||
|
.interp : { *(.interp) }
|
||||||
|
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.gnu.hash : { *(.gnu.hash) }
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.gnu.version : { *(.gnu.version) }
|
||||||
|
.gnu.version_d : { *(.gnu.version_d) }
|
||||||
|
.gnu.version_r : { *(.gnu.version_r) }
|
||||||
|
.rela.dyn :
|
||||||
|
{
|
||||||
|
*(.rela.init)
|
||||||
|
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||||
|
*(.rela.fini)
|
||||||
|
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||||
|
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||||
|
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||||
|
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||||
|
*(.rela.ctors)
|
||||||
|
*(.rela.dtors)
|
||||||
|
*(.rela.got)
|
||||||
|
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||||
|
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
|
||||||
|
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
|
||||||
|
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
|
||||||
|
*(.rela.ifunc)
|
||||||
|
}
|
||||||
|
.rela.plt :
|
||||||
|
{
|
||||||
|
*(.rela.plt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||||
|
*(.rela.iplt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||||
|
}
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.init)))
|
||||||
|
}
|
||||||
|
.plt : { *(.plt) *(.iplt) }
|
||||||
|
.plt.got : { *(.plt.got) }
|
||||||
|
.plt.sec : { *(.plt.sec) }
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
}
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.fini)))
|
||||||
|
}
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
/* Adjust the address for the rodata segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||||
|
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||||
|
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||||
|
/* Exception handling */
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||||
|
/* Thread Local Storage sections */
|
||||||
|
/* .tdata :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__tdata_start = .);
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
}
|
||||||
|
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
/* .init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
} */
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*crtbegin?.o(.ctors))
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
}
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*crtbegin?.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
}
|
||||||
|
.jcr : { KEEP (*(.jcr)) }
|
||||||
|
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
.got : { *(.got) *(.igot) }
|
||||||
|
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
_edata = .; PROVIDE (edata = .);
|
||||||
|
. = .;
|
||||||
|
__bss_start = .;
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
/* Align here to ensure that the .bss section occupies space up to
|
||||||
|
_end. Align after .bss to ensure correct alignment even if the
|
||||||
|
.bss section disappears because there are no input sections.
|
||||||
|
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||||
|
pad the .data section. */
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
.lbss :
|
||||||
|
{
|
||||||
|
*(.dynlbss)
|
||||||
|
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||||
|
*(LARGE_COMMON)
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
. = SEGMENT_START("ldata-segment", .);
|
||||||
|
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||||
|
}
|
||||||
|
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
_end = .; PROVIDE (end = .);
|
||||||
|
. = DATA_SEGMENT_END (.);
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* DWARF 3 */
|
||||||
|
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
/* DWARF Extension. */
|
||||||
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
|
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||||
|
/*
|
||||||
|
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||||
|
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||||
|
* that may reference use thread local storage.
|
||||||
|
*
|
||||||
|
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||||
|
*/
|
||||||
|
*(.gnu.linkonce.tb.*) *(.tcommon)
|
||||||
|
*(.init_array)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,247 @@
|
|||||||
|
/* Script for -z combreloc */
|
||||||
|
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||||
|
Copying and distribution of this script, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. */
|
||||||
|
OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv" )
|
||||||
|
OUTPUT_ARCH(riscv)
|
||||||
|
ENTRY(_start)
|
||||||
|
SEARCH_DIR("/riscv64-unknown-redox/lib");
|
||||||
|
SEARCH_DIR("/usr/local/lib64");
|
||||||
|
SEARCH_DIR("/lib64");
|
||||||
|
SEARCH_DIR("/usr/lib64");
|
||||||
|
SEARCH_DIR("/usr/local/lib");
|
||||||
|
SEARCH_DIR("/lib");
|
||||||
|
SEARCH_DIR("/usr/lib");
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
|
||||||
|
.interp : { *(.interp) }
|
||||||
|
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.gnu.hash : { *(.gnu.hash) }
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.gnu.version : { *(.gnu.version) }
|
||||||
|
.gnu.version_d : { *(.gnu.version_d) }
|
||||||
|
.gnu.version_r : { *(.gnu.version_r) }
|
||||||
|
.rela.dyn :
|
||||||
|
{
|
||||||
|
*(.rela.init)
|
||||||
|
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||||
|
*(.rela.fini)
|
||||||
|
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||||
|
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||||
|
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||||
|
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||||
|
*(.rela.ctors)
|
||||||
|
*(.rela.dtors)
|
||||||
|
*(.rela.got)
|
||||||
|
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||||
|
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
|
||||||
|
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
|
||||||
|
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
|
||||||
|
*(.rela.ifunc)
|
||||||
|
}
|
||||||
|
.rela.plt :
|
||||||
|
{
|
||||||
|
*(.rela.plt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||||
|
*(.rela.iplt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||||
|
}
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
.plt : { *(.plt) *(.iplt) }
|
||||||
|
.plt.got : { *(.plt.got) }
|
||||||
|
.plt.sec : { *(.plt.sec) }
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
}
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
/* Adjust the address for the rodata segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||||
|
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||||
|
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||||
|
/* Exception handling */
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||||
|
/* Thread Local Storage sections */
|
||||||
|
/* .tdata :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__tdata_start = .);
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
}
|
||||||
|
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
/* .init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
} */
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*crtbegin?.o(.ctors))
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
}
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*crtbegin?.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
}
|
||||||
|
.jcr : { KEEP (*(.jcr)) }
|
||||||
|
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
.got : { *(.got) *(.igot) }
|
||||||
|
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
_edata = .; PROVIDE (edata = .);
|
||||||
|
. = .;
|
||||||
|
__bss_start = .;
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
/* Align here to ensure that the .bss section occupies space up to
|
||||||
|
_end. Align after .bss to ensure correct alignment even if the
|
||||||
|
.bss section disappears because there are no input sections.
|
||||||
|
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||||
|
pad the .data section. */
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
.lbss :
|
||||||
|
{
|
||||||
|
*(.dynlbss)
|
||||||
|
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||||
|
*(LARGE_COMMON)
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
. = SEGMENT_START("ldata-segment", .);
|
||||||
|
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||||
|
}
|
||||||
|
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
_end = .; PROVIDE (end = .);
|
||||||
|
. = DATA_SEGMENT_END (.);
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* DWARF 3 */
|
||||||
|
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
/* DWARF Extension. */
|
||||||
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
|
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||||
|
/*
|
||||||
|
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||||
|
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||||
|
* that may reference use thread local storage.
|
||||||
|
*
|
||||||
|
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||||
|
*/
|
||||||
|
*(.gnu.linkonce.tb.*) *(.tcommon)
|
||||||
|
*(.init_array)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
/* Script for -z combreloc */
|
||||||
|
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||||
|
Copying and distribution of this script, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. */
|
||||||
|
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
|
||||||
|
"elf64-x86-64")
|
||||||
|
OUTPUT_ARCH(i386:x86-64)
|
||||||
|
ENTRY(_start)
|
||||||
|
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib64");
|
||||||
|
SEARCH_DIR("/usr/lib64/binutils/x86_64-pc-linux-gnu/2.33.164");
|
||||||
|
SEARCH_DIR("/usr/local/lib64");
|
||||||
|
SEARCH_DIR("/lib64");
|
||||||
|
SEARCH_DIR("/usr/lib64");
|
||||||
|
SEARCH_DIR("/usr/x86_64-pc-linux-gnu/lib");
|
||||||
|
SEARCH_DIR("/usr/lib64/binutils/x86_64-pc-linux-gnu/2.33.1");
|
||||||
|
SEARCH_DIR("/usr/local/lib");
|
||||||
|
SEARCH_DIR("/lib");
|
||||||
|
SEARCH_DIR("/usr/lib");
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
|
||||||
|
.interp : { *(.interp) }
|
||||||
|
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.gnu.hash : { *(.gnu.hash) }
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.gnu.version : { *(.gnu.version) }
|
||||||
|
.gnu.version_d : { *(.gnu.version_d) }
|
||||||
|
.gnu.version_r : { *(.gnu.version_r) }
|
||||||
|
.rela.dyn :
|
||||||
|
{
|
||||||
|
*(.rela.init)
|
||||||
|
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||||
|
*(.rela.fini)
|
||||||
|
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||||
|
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||||
|
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||||
|
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||||
|
*(.rela.ctors)
|
||||||
|
*(.rela.dtors)
|
||||||
|
*(.rela.got)
|
||||||
|
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||||
|
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
|
||||||
|
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
|
||||||
|
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
|
||||||
|
*(.rela.ifunc)
|
||||||
|
}
|
||||||
|
.rela.plt :
|
||||||
|
{
|
||||||
|
*(.rela.plt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||||
|
*(.rela.iplt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||||
|
}
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.init)))
|
||||||
|
}
|
||||||
|
.plt : { *(.plt) *(.iplt) }
|
||||||
|
.plt.got : { *(.plt.got) }
|
||||||
|
.plt.sec : { *(.plt.sec) }
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
}
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.fini)))
|
||||||
|
}
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
/* Adjust the address for the rodata segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||||
|
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||||
|
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||||
|
/* Exception handling */
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||||
|
/* Thread Local Storage sections */
|
||||||
|
/* .tdata : ALIGN(4K)
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__tdata_start = .);
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
}
|
||||||
|
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
/* .init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
} */
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*crtbegin?.o(.ctors))
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
}
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*crtbegin?.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
}
|
||||||
|
.jcr : { KEEP (*(.jcr)) }
|
||||||
|
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
.got : { *(.got) *(.igot) }
|
||||||
|
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
_edata = .; PROVIDE (edata = .);
|
||||||
|
. = .;
|
||||||
|
__bss_start = .;
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
/* Align here to ensure that the .bss section occupies space up to
|
||||||
|
_end. Align after .bss to ensure correct alignment even if the
|
||||||
|
.bss section disappears because there are no input sections.
|
||||||
|
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||||
|
pad the .data section. */
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
.lbss :
|
||||||
|
{
|
||||||
|
*(.dynlbss)
|
||||||
|
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||||
|
*(LARGE_COMMON)
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
. = SEGMENT_START("ldata-segment", .);
|
||||||
|
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||||
|
}
|
||||||
|
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
_end = .; PROVIDE (end = .);
|
||||||
|
. = DATA_SEGMENT_END (.);
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* DWARF 3 */
|
||||||
|
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
/* DWARF Extension. */
|
||||||
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
|
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||||
|
/*
|
||||||
|
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||||
|
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||||
|
* that may reference use thread local storage.
|
||||||
|
*
|
||||||
|
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||||
|
*/
|
||||||
|
*(.gnu.linkonce.tb.*) *(.tcommon)
|
||||||
|
*(.init_array)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
/* Script for -z combreloc */
|
||||||
|
/* Copyright (C) 2014-2020 Free Software Foundation, Inc.
|
||||||
|
Copying and distribution of this script, with or without modification,
|
||||||
|
are permitted in any medium without royalty provided the copyright
|
||||||
|
notice and this notice are preserved. */
|
||||||
|
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64",
|
||||||
|
"elf64-x86-64")
|
||||||
|
OUTPUT_ARCH(i386:x86-64)
|
||||||
|
ENTRY(_start)
|
||||||
|
SEARCH_DIR("/x86_64-unknown-redox/lib");
|
||||||
|
SEARCH_DIR("/usr/local/lib64");
|
||||||
|
SEARCH_DIR("/lib64");
|
||||||
|
SEARCH_DIR("/usr/lib64");
|
||||||
|
SEARCH_DIR("/usr/local/lib");
|
||||||
|
SEARCH_DIR("/lib");
|
||||||
|
SEARCH_DIR("/usr/lib");
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/* Read-only sections, merged into text segment: */
|
||||||
|
PROVIDE (__executable_start = SEGMENT_START("text-segment", 0x400000)); . = SEGMENT_START("text-segment", 0x20000000) + SIZEOF_HEADERS;
|
||||||
|
.interp : { *(.interp) }
|
||||||
|
.note.gnu.build-id : { *(.note.gnu.build-id) }
|
||||||
|
.hash : { *(.hash) }
|
||||||
|
.gnu.hash : { *(.gnu.hash) }
|
||||||
|
.dynsym : { *(.dynsym) }
|
||||||
|
.dynstr : { *(.dynstr) }
|
||||||
|
.gnu.version : { *(.gnu.version) }
|
||||||
|
.gnu.version_d : { *(.gnu.version_d) }
|
||||||
|
.gnu.version_r : { *(.gnu.version_r) }
|
||||||
|
.rela.dyn :
|
||||||
|
{
|
||||||
|
*(.rela.init)
|
||||||
|
*(.rela.text .rela.text.* .rela.gnu.linkonce.t.*)
|
||||||
|
*(.rela.fini)
|
||||||
|
*(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*)
|
||||||
|
*(.rela.data .rela.data.* .rela.gnu.linkonce.d.*)
|
||||||
|
*(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*)
|
||||||
|
*(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*)
|
||||||
|
*(.rela.ctors)
|
||||||
|
*(.rela.dtors)
|
||||||
|
*(.rela.got)
|
||||||
|
*(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*)
|
||||||
|
*(.rela.ldata .rela.ldata.* .rela.gnu.linkonce.l.*)
|
||||||
|
*(.rela.lbss .rela.lbss.* .rela.gnu.linkonce.lb.*)
|
||||||
|
*(.rela.lrodata .rela.lrodata.* .rela.gnu.linkonce.lr.*)
|
||||||
|
*(.rela.ifunc)
|
||||||
|
}
|
||||||
|
.rela.plt :
|
||||||
|
{
|
||||||
|
*(.rela.plt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_start = .);
|
||||||
|
*(.rela.iplt)
|
||||||
|
PROVIDE_HIDDEN (__rela_iplt_end = .);
|
||||||
|
}
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.init)))
|
||||||
|
}
|
||||||
|
.plt : { *(.plt) *(.iplt) }
|
||||||
|
.plt.got : { *(.plt.got) }
|
||||||
|
.plt.sec : { *(.plt.sec) }
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
|
||||||
|
*(.text.exit .text.exit.*)
|
||||||
|
*(.text.startup .text.startup.*)
|
||||||
|
*(.text.hot .text.hot.*)
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
/* .gnu.warning sections are handled specially by elf.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
}
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(SORT_NONE(.fini)))
|
||||||
|
}
|
||||||
|
PROVIDE (__etext = .);
|
||||||
|
PROVIDE (_etext = .);
|
||||||
|
PROVIDE (etext = .);
|
||||||
|
. = ALIGN(CONSTANT (MAXPAGESIZE));
|
||||||
|
/* Adjust the address for the rodata segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = SEGMENT_START("rodata-segment", ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)));
|
||||||
|
.rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) }
|
||||||
|
.rodata1 : { *(.rodata1) }
|
||||||
|
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) }
|
||||||
|
.eh_frame : ONLY_IF_RO { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gcc_except_table : ONLY_IF_RO { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RO { *(.gnu_extab*) }
|
||||||
|
/* These sections are generated by the Sun/Oracle C++ compiler. */
|
||||||
|
.exception_ranges : ONLY_IF_RO { *(.exception_ranges*) }
|
||||||
|
/* Adjust the address for the data segment. We want to adjust up to
|
||||||
|
the same address within the page on the next page up. */
|
||||||
|
. = DATA_SEGMENT_ALIGN (CONSTANT (MAXPAGESIZE), CONSTANT (COMMONPAGESIZE));
|
||||||
|
/* Exception handling */
|
||||||
|
.eh_frame : ONLY_IF_RW { KEEP (*(.eh_frame)) *(.eh_frame.*) }
|
||||||
|
.gnu_extab : ONLY_IF_RW { *(.gnu_extab) }
|
||||||
|
.gcc_except_table : ONLY_IF_RW { *(.gcc_except_table .gcc_except_table.*) }
|
||||||
|
.exception_ranges : ONLY_IF_RW { *(.exception_ranges*) }
|
||||||
|
/* Thread Local Storage sections */
|
||||||
|
/* .tdata : ALIGN(4K)
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__tdata_start = .);
|
||||||
|
*(.tdata .tdata.* .gnu.linkonce.td.*)
|
||||||
|
}
|
||||||
|
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } */
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
/* .init_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
} */
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
|
||||||
|
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
|
||||||
|
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of
|
||||||
|
the constructors, so we make sure it is
|
||||||
|
first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not
|
||||||
|
actually link against crtbegin.o; the
|
||||||
|
linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it
|
||||||
|
doesn't matter which directory crtbegin.o
|
||||||
|
is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*crtbegin?.o(.ctors))
|
||||||
|
/* We don't want to include the .ctor section from
|
||||||
|
the crtend.o file until after the sorted ctors.
|
||||||
|
The .ctor section from the crtend file contains the
|
||||||
|
end of ctors marker and it must be last */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
}
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*crtbegin?.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o *crtend?.o ) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
}
|
||||||
|
.jcr : { KEEP (*(.jcr)) }
|
||||||
|
.data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) *(.data.rel.ro .data.rel.ro.* .gnu.linkonce.d.rel.ro.*) }
|
||||||
|
.dynamic : { *(.dynamic) }
|
||||||
|
.got : { *(.got) *(.igot) }
|
||||||
|
. = DATA_SEGMENT_RELRO_END (SIZEOF (.got.plt) >= 24 ? 24 : 0, .);
|
||||||
|
.got.plt : { *(.got.plt) *(.igot.plt) }
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data .data.* .gnu.linkonce.d.*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
}
|
||||||
|
.data1 : { *(.data1) }
|
||||||
|
_edata = .; PROVIDE (edata = .);
|
||||||
|
. = .;
|
||||||
|
__bss_start = .;
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss .bss.* .gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
/* Align here to ensure that the .bss section occupies space up to
|
||||||
|
_end. Align after .bss to ensure correct alignment even if the
|
||||||
|
.bss section disappears because there are no input sections.
|
||||||
|
FIXME: Why do we need it? When there is no .bss section, we do not
|
||||||
|
pad the .data section. */
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
.lbss :
|
||||||
|
{
|
||||||
|
*(.dynlbss)
|
||||||
|
*(.lbss .lbss.* .gnu.linkonce.lb.*)
|
||||||
|
*(LARGE_COMMON)
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
. = SEGMENT_START("ldata-segment", .);
|
||||||
|
.lrodata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.lrodata .lrodata.* .gnu.linkonce.lr.*)
|
||||||
|
}
|
||||||
|
.ldata ALIGN(CONSTANT (MAXPAGESIZE)) + (. & (CONSTANT (MAXPAGESIZE) - 1)) :
|
||||||
|
{
|
||||||
|
*(.ldata .ldata.* .gnu.linkonce.l.*)
|
||||||
|
. = ALIGN(. != 0 ? 64 / 8 : 1);
|
||||||
|
}
|
||||||
|
. = ALIGN(64 / 8);
|
||||||
|
_end = .; PROVIDE (end = .);
|
||||||
|
. = DATA_SEGMENT_END (.);
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
.gnu.build.attributes : { *(.gnu.build.attributes .gnu.build.attributes.*) }
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
/* SGI/MIPS DWARF 2 extensions */
|
||||||
|
.debug_weaknames 0 : { *(.debug_weaknames) }
|
||||||
|
.debug_funcnames 0 : { *(.debug_funcnames) }
|
||||||
|
.debug_typenames 0 : { *(.debug_typenames) }
|
||||||
|
.debug_varnames 0 : { *(.debug_varnames) }
|
||||||
|
/* DWARF 3 */
|
||||||
|
.debug_pubtypes 0 : { *(.debug_pubtypes) }
|
||||||
|
.debug_ranges 0 : { *(.debug_ranges) }
|
||||||
|
/* DWARF Extension. */
|
||||||
|
.debug_macro 0 : { *(.debug_macro) }
|
||||||
|
.debug_addr 0 : { *(.debug_addr) }
|
||||||
|
.gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||||
|
/DISCARD/ : {
|
||||||
|
*(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*)
|
||||||
|
/*
|
||||||
|
* XXX: As of now, ld.so links with relibc which has the main functionality. In the next refactor,
|
||||||
|
* ld.so will be moved out of relibc. So, till that time, we have to discard any sections
|
||||||
|
* that may reference use thread local storage.
|
||||||
|
*
|
||||||
|
* .init_array also depends on TLS and is discarded as we don't need it.
|
||||||
|
*/
|
||||||
|
*(.gnu.linkonce.tb.*) *(.tcommon)
|
||||||
|
*(.init_array)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,136 @@
|
|||||||
|
#![no_std]
|
||||||
|
#![feature(linkage)]
|
||||||
|
#![deny(unsafe_op_in_unsafe_fn)]
|
||||||
|
|
||||||
|
use core::arch::global_asm;
|
||||||
|
|
||||||
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
global_asm!(
|
||||||
|
"
|
||||||
|
.weak _DYNAMIC
|
||||||
|
.hidden _DYNAMIC
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
_start:
|
||||||
|
mov x28, sp
|
||||||
|
// align stack to 16 bytes
|
||||||
|
and sp, x28, #0xfffffffffffffff0
|
||||||
|
adr x1, _start
|
||||||
|
mov x0, x28
|
||||||
|
adrp x2, _DYNAMIC
|
||||||
|
add x2, x2, #:lo12:_DYNAMIC
|
||||||
|
// ld_so_start(stack=x0, ld_entry=x1, dynamic=x2)
|
||||||
|
bl relibc_ld_so_start
|
||||||
|
// restore original stack, clear registers, and jump to the new start function
|
||||||
|
mov sp, x28
|
||||||
|
mov x1, xzr
|
||||||
|
mov x2, xzr
|
||||||
|
mov x3, xzr
|
||||||
|
mov x4, xzr
|
||||||
|
mov x5, xzr
|
||||||
|
mov x6, xzr
|
||||||
|
mov x7, xzr
|
||||||
|
mov x8, xzr
|
||||||
|
mov x9, xzr
|
||||||
|
mov x10, xzr
|
||||||
|
mov x11, xzr
|
||||||
|
mov x12, xzr
|
||||||
|
mov x13, xzr
|
||||||
|
mov x14, xzr
|
||||||
|
mov x15, xzr
|
||||||
|
mov x16, xzr
|
||||||
|
mov x17, xzr
|
||||||
|
mov x18, xzr
|
||||||
|
mov x19, xzr
|
||||||
|
mov x20, xzr
|
||||||
|
mov x21, xzr
|
||||||
|
mov x22, xzr
|
||||||
|
mov x23, xzr
|
||||||
|
mov x24, xzr
|
||||||
|
mov x25, xzr
|
||||||
|
mov x26, xzr
|
||||||
|
mov x27, xzr
|
||||||
|
mov x28, xzr
|
||||||
|
mov x29, xzr
|
||||||
|
mov x30, xzr
|
||||||
|
br x0
|
||||||
|
udf #0
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86")]
|
||||||
|
global_asm!(
|
||||||
|
"
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
push esp
|
||||||
|
call relibc_ld_so_start
|
||||||
|
pop esp
|
||||||
|
# TODO: x86
|
||||||
|
ud2
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(target_arch = "x86_64")]
|
||||||
|
global_asm!(
|
||||||
|
"
|
||||||
|
.weak _DYNAMIC
|
||||||
|
.hidden _DYNAMIC
|
||||||
|
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
lea rsi, [rip + _start]
|
||||||
|
|
||||||
|
# Save original stack and align stack to 16 bytes
|
||||||
|
mov rbp, rsp
|
||||||
|
and rsp, 0xfffffffffffffff0
|
||||||
|
|
||||||
|
# Call ld_so_start(stack=rdi, ld_entry=rsi, dynamic=rdx)
|
||||||
|
mov rdi, rbp
|
||||||
|
lea rdx, [rip + _DYNAMIC]
|
||||||
|
call relibc_ld_so_start
|
||||||
|
|
||||||
|
# Restore original stack, clear registers, and jump to new start function
|
||||||
|
mov rsp, rbp
|
||||||
|
xor rcx, rcx
|
||||||
|
xor rdx, rdx
|
||||||
|
xor rdi, rdi
|
||||||
|
xor rsi, rsi
|
||||||
|
xor r8, r8
|
||||||
|
xor r9, r9
|
||||||
|
xor r10, r10
|
||||||
|
xor r11, r11
|
||||||
|
fninit
|
||||||
|
jmp rax
|
||||||
|
ud2
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(target_arch = "riscv64")]
|
||||||
|
global_asm!(
|
||||||
|
"
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
mv a0, sp
|
||||||
|
jal relibc_ld_so_start
|
||||||
|
unimp
|
||||||
|
"
|
||||||
|
);
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub unsafe extern "C" fn main(_argc: isize, _argv: *const *const i8) -> usize {
|
||||||
|
// LD
|
||||||
|
0x1D
|
||||||
|
}
|
||||||
|
|
||||||
|
#[linkage = "weak"]
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
extern "C" fn relibc_panic(_pi: &::core::panic::PanicInfo) -> ! {
|
||||||
|
loop {}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[panic_handler]
|
||||||
|
#[linkage = "weak"]
|
||||||
|
pub unsafe fn rust_begin_unwind(pi: &::core::panic::PanicInfo) -> ! {
|
||||||
|
relibc_panic(pi)
|
||||||
|
}
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
ENTRY(kstart)
|
|
||||||
OUTPUT_FORMAT("elf64-littleaarch64", "elf64-littleaarch64", "elf64-littleaarch64")
|
|
||||||
|
|
||||||
KERNEL_OFFSET = 0xFFFFFF0000000000;
|
|
||||||
|
|
||||||
SECTIONS {
|
|
||||||
. = KERNEL_OFFSET;
|
|
||||||
|
|
||||||
. += SIZEOF_HEADERS;
|
|
||||||
|
|
||||||
/* Force the zero page to be part of a segment by creating a
|
|
||||||
* dummy section in the zero page.
|
|
||||||
* Limine will map the segment with the lowest vaddr value at
|
|
||||||
* 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
|
|
||||||
* As such without the zero page being part of a segment, the
|
|
||||||
* kernel would be loaded at an offset from the expected
|
|
||||||
* location. As the redox kernel is not currently relocatable,
|
|
||||||
* this would result in a crash. A similar issue likely exists
|
|
||||||
* with multiboot/multiboot2 and the paddr of the segment.
|
|
||||||
*/
|
|
||||||
.dummy ALIGN(8) : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
|
|
||||||
|
|
||||||
. = ALIGN(4096);
|
|
||||||
|
|
||||||
.text : AT(ADDR(.text) - KERNEL_OFFSET) {
|
|
||||||
__text_start = .;
|
|
||||||
*(.text*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
__text_end = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) {
|
|
||||||
__rodata_start = .;
|
|
||||||
*(.rodata*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
__rodata_end = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data : AT(ADDR(.data) - KERNEL_OFFSET) {
|
|
||||||
*(.data*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
*(.bss*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
}
|
|
||||||
|
|
||||||
__end = .;
|
|
||||||
|
|
||||||
/DISCARD/ : {
|
|
||||||
*(.comment*)
|
|
||||||
*(.eh_frame*)
|
|
||||||
*(.gcc_except_table*)
|
|
||||||
*(.note*)
|
|
||||||
*(.rel.eh_frame*)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
ENTRY(kstart)
|
|
||||||
OUTPUT_FORMAT(elf32-i386)
|
|
||||||
|
|
||||||
KERNEL_OFFSET = 0xC0000000;
|
|
||||||
|
|
||||||
SECTIONS {
|
|
||||||
. = KERNEL_OFFSET;
|
|
||||||
|
|
||||||
. += SIZEOF_HEADERS;
|
|
||||||
|
|
||||||
/* Force the zero page to be part of a segment by creating a
|
|
||||||
* dummy section in the zero page.
|
|
||||||
* Limine will map the segment with the lowest vaddr value at
|
|
||||||
* 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
|
|
||||||
* As such without the zero page being part of a segment, the
|
|
||||||
* kernel would be loaded at an offset from the expected
|
|
||||||
* location. As the redox kernel is not currently relocatable,
|
|
||||||
* this would result in a crash. A similar issue likely exists
|
|
||||||
* with multiboot/multiboot2 and the paddr of the segment.
|
|
||||||
*/
|
|
||||||
.dummy : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
|
|
||||||
|
|
||||||
.text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET) {
|
|
||||||
__text_start = .;
|
|
||||||
*(.text*)
|
|
||||||
}
|
|
||||||
|
|
||||||
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET) {
|
|
||||||
__text_end = .;
|
|
||||||
__rodata_start = .;
|
|
||||||
*(.rodata*)
|
|
||||||
}
|
|
||||||
|
|
||||||
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET) {
|
|
||||||
__rodata_end = .;
|
|
||||||
*(.data*)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
*(.bss*)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
}
|
|
||||||
|
|
||||||
__end = .;
|
|
||||||
|
|
||||||
/DISCARD/ : {
|
|
||||||
*(.comment*)
|
|
||||||
*(.eh_frame*)
|
|
||||||
*(.gcc_except_table*)
|
|
||||||
*(.note*)
|
|
||||||
*(.rel.eh_frame*)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
ENTRY(kstart)
|
|
||||||
OUTPUT_FORMAT("elf64-littleriscv", "elf64-littleriscv", "elf64-littleriscv" )
|
|
||||||
|
|
||||||
KERNEL_OFFSET = 0xFFFFFFFF80000000;
|
|
||||||
|
|
||||||
SECTIONS {
|
|
||||||
. = KERNEL_OFFSET;
|
|
||||||
|
|
||||||
. += SIZEOF_HEADERS;
|
|
||||||
|
|
||||||
/* Force the zero page to be part of a segment by creating a
|
|
||||||
* dummy section in the zero page.
|
|
||||||
* Linker will map the segment with the lowest vaddr value at
|
|
||||||
* 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
|
|
||||||
* As such without the zero page being part of a segment, the
|
|
||||||
* kernel would be loaded at an offset from the expected
|
|
||||||
* location. As the redox kernel is not currently relocatable,
|
|
||||||
* this would result in a crash. A similar issue likely exists
|
|
||||||
* with multiboot/multiboot2 and the paddr of the segment.
|
|
||||||
*/
|
|
||||||
.dummy ALIGN(8) : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
|
|
||||||
|
|
||||||
. = ALIGN(4096);
|
|
||||||
|
|
||||||
.text : AT(ADDR(.text) - KERNEL_OFFSET) {
|
|
||||||
__text_start = .;
|
|
||||||
*(.early_init.text*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
*(.text*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
__text_end = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.rodata : AT(ADDR(.rodata) - KERNEL_OFFSET) {
|
|
||||||
__rodata_start = .;
|
|
||||||
*(.rodata*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
__rodata_end = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data : AT(ADDR(.data) - KERNEL_OFFSET) {
|
|
||||||
*(.data*)
|
|
||||||
*(.sdata*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
*(.got*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
*(.bss*)
|
|
||||||
*(.sbss*)
|
|
||||||
. = ALIGN(4096);
|
|
||||||
}
|
|
||||||
|
|
||||||
__end = .;
|
|
||||||
|
|
||||||
/DISCARD/ : {
|
|
||||||
*(.comment*)
|
|
||||||
*(.eh_frame*)
|
|
||||||
*(.gcc_except_table*)
|
|
||||||
*(.note*)
|
|
||||||
*(.rel.eh_frame*)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
ENTRY(kstart)
|
|
||||||
OUTPUT_FORMAT(elf64-x86-64)
|
|
||||||
|
|
||||||
KERNEL_OFFSET = 0xFFFFFFFF80000000;
|
|
||||||
|
|
||||||
SECTIONS {
|
|
||||||
. = KERNEL_OFFSET;
|
|
||||||
|
|
||||||
. += SIZEOF_HEADERS;
|
|
||||||
|
|
||||||
/* Force the zero page to be part of a segment by creating a
|
|
||||||
* dummy section in the zero page.
|
|
||||||
* Limine will map the segment with the lowest vaddr value at
|
|
||||||
* 0xFFFFFFFF80000000 even if the segment has a higher vaddr.
|
|
||||||
* As such without the zero page being part of a segment, the
|
|
||||||
* kernel would be loaded at an offset from the expected
|
|
||||||
* location. As the redox kernel is not currently relocatable,
|
|
||||||
* this would result in a crash. A similar issue likely exists
|
|
||||||
* with multiboot/multiboot2 and the paddr of the segment.
|
|
||||||
*/
|
|
||||||
.dummy : AT(ADDR(.dummy) - KERNEL_OFFSET) {}
|
|
||||||
|
|
||||||
.text ALIGN(4K) : AT(ADDR(.text) - KERNEL_OFFSET) {
|
|
||||||
__text_start = .;
|
|
||||||
*(.text*)
|
|
||||||
}
|
|
||||||
|
|
||||||
.rodata ALIGN(4K) : AT(ADDR(.rodata) - KERNEL_OFFSET) {
|
|
||||||
__text_end = .;
|
|
||||||
__rodata_start = .;
|
|
||||||
*(.rodata*)
|
|
||||||
__altcode_start = .;
|
|
||||||
KEEP(*(.altcode*))
|
|
||||||
__altcode_end = .;
|
|
||||||
. = ALIGN(8);
|
|
||||||
__altrelocs_start = .;
|
|
||||||
KEEP(*(.altrelocs*))
|
|
||||||
__altrelocs_end = .;
|
|
||||||
__altfeatures_start = .;
|
|
||||||
KEEP(*(.altfeatures*))
|
|
||||||
__altfeatures_end = .;
|
|
||||||
}
|
|
||||||
|
|
||||||
.data ALIGN(4K) : AT(ADDR(.data) - KERNEL_OFFSET) {
|
|
||||||
__rodata_end = .;
|
|
||||||
*(.data*)
|
|
||||||
. = ALIGN(4K);
|
|
||||||
*(.bss*)
|
|
||||||
}
|
|
||||||
|
|
||||||
__end = .;
|
|
||||||
|
|
||||||
/DISCARD/ : {
|
|
||||||
*(.comment*)
|
|
||||||
*(.eh_frame*)
|
|
||||||
*(.gcc_except_table*)
|
|
||||||
*(.note*)
|
|
||||||
*(.rel.eh_frame*)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
+7
@@ -0,0 +1,7 @@
|
|||||||
|
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/" # Location of package manifests
|
||||||
|
schedule:
|
||||||
|
interval: "monthly"
|
||||||
Vendored
+93
@@ -0,0 +1,93 @@
|
|||||||
|
name: CI
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags: '*'
|
||||||
|
jobs:
|
||||||
|
test-unix:
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
os:
|
||||||
|
- ubuntu-latest
|
||||||
|
- macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- run: make
|
||||||
|
- run: make test
|
||||||
|
windows:
|
||||||
|
runs-on: windows-latest
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- { sys: mingw64, env: x86_64 }
|
||||||
|
- { sys: mingw32, env: i686 }
|
||||||
|
- { sys: ucrt64, env: ucrt-x86_64 } # Experimental!
|
||||||
|
- { sys: clang64, env: clang-x86_64 } # Experimental!
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
shell: msys2 {0}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- name: Set up the desired MSYS2 environment
|
||||||
|
uses: msys2/setup-msys2@v2
|
||||||
|
with:
|
||||||
|
msystem: ${{matrix.sys}}
|
||||||
|
install: base-devel mingw-w64-${{matrix.env}}-toolchain
|
||||||
|
- run: make
|
||||||
|
- run: make test
|
||||||
|
code-coverage-old:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- name: Setup LCOV
|
||||||
|
uses: hrishikesh-kadam/setup-lcov@v1
|
||||||
|
- name: Build and Run tests
|
||||||
|
run: make coverage -j
|
||||||
|
# - name: Upload coverage to Codecov
|
||||||
|
# uses: codecov/codecov-action@v5
|
||||||
|
# with:
|
||||||
|
# files: ./cov-html/libopenlibm.info
|
||||||
|
# token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: code-coverage-report-old
|
||||||
|
path: ./cov-html/
|
||||||
|
code-coverage:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout Openlibm
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
- name: Checkout Openlibm-test
|
||||||
|
uses: actions/checkout@v5
|
||||||
|
with:
|
||||||
|
repository: 'JuliaMath/openlibm-test'
|
||||||
|
path: 'openlibm-test'
|
||||||
|
- name: Setup LCOV
|
||||||
|
uses: hrishikesh-kadam/setup-lcov@v1
|
||||||
|
- name: Build Openlibm
|
||||||
|
run: make -j`nproc` CODE_COVERAGE=1
|
||||||
|
- name: Run Test
|
||||||
|
run: |
|
||||||
|
make -j`nproc` -C openlibm-test \
|
||||||
|
USE_OPENLIBM=1 OPENLIBM_HOME="$(pwd)" \
|
||||||
|
SKIP_FP_EXCEPT_TEST=1 \
|
||||||
|
- name: Show Test Result
|
||||||
|
run: cat openlibm-test/src/REPORT
|
||||||
|
- name: Gen Coverage Report
|
||||||
|
run: make gen-cov-report
|
||||||
|
- name: Upload coverage to Codecov
|
||||||
|
uses: codecov/codecov-action@v5
|
||||||
|
with:
|
||||||
|
files: ./cov-html/libopenlibm.info
|
||||||
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
|
- uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: code-coverage-report
|
||||||
|
path: ./cov-html/
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
# merge this file into cross.yml
|
||||||
|
# when we can `sudo apt install gcc-loongarch64-linux-gnu` on ubuntu
|
||||||
|
name: Cross
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags: '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-cross-qemu:
|
||||||
|
# TODO: We need Ubuntu 24.04 to use newer version of qemu,
|
||||||
|
# switch to ubuntu-latest when `ubuntu-latest >= 24.04`
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
name: build-cross-qemu-${{ matrix.config.arch }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
config:
|
||||||
|
- { arch: loongarch64, triple: loongarch64-linux-gnu }
|
||||||
|
env:
|
||||||
|
ARCH: ${{ matrix.config.arch }}
|
||||||
|
TRIPLE: ${{ matrix.config.triple }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- name: Install qemu
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install -y qemu-user qemu-user-binfmt
|
||||||
|
- name: Install gcc-${{ matrix.config.triple }}
|
||||||
|
# package gcc-loongarch64-linux-gnu seems not exist
|
||||||
|
# https://packages.debian.org/sid/amd64/gcc-loongarch64-linux-gnu
|
||||||
|
run: sudo apt install -y gcc-14-loongarch64-linux-gnu
|
||||||
|
- name: Build with ${{ matrix.config.triple }}-gcc
|
||||||
|
run: |
|
||||||
|
make ARCH=$ARCH TOOLPREFIX=$TRIPLE- \
|
||||||
|
CC='loongarch64-linux-gnu-gcc-14' \
|
||||||
|
AR='loongarch64-linux-gnu-gcc-ar-14' \
|
||||||
|
- name: Build tests
|
||||||
|
run: |
|
||||||
|
make -C test ARCH=$ARCH TOOLPREFIX=$TRIPLE- \
|
||||||
|
CC='loongarch64-linux-gnu-gcc-14' \
|
||||||
|
AR='loongarch64-linux-gnu-gcc-ar-14' \
|
||||||
|
- name: Run Tests
|
||||||
|
env:
|
||||||
|
QEMU_EXEC: qemu-${{ matrix.config.arch }}
|
||||||
|
CROSS_LIB: /usr/${{ matrix.config.triple }}
|
||||||
|
run: |
|
||||||
|
$QEMU_EXEC -L . -L $CROSS_LIB/ test/test-float
|
||||||
|
$QEMU_EXEC -L . -L $CROSS_LIB/ test/test-double
|
||||||
Vendored
+53
@@ -0,0 +1,53 @@
|
|||||||
|
name: Cross
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
tags: '*'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-cross-qemu:
|
||||||
|
# TODO: We need Ubuntu 24.04 to use newer version of qemu,
|
||||||
|
# switch to ubuntu-latest when `ubuntu-latest >= 24.04`
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
name: build-cross-qemu-${{ matrix.config.arch }}
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
config:
|
||||||
|
- { arch: arm, triple: arm-linux-gnueabihf }
|
||||||
|
- { arch: aarch64, triple: aarch64-linux-gnu }
|
||||||
|
- { arch: ppc, triple: powerpc-linux-gnu }
|
||||||
|
- { arch: ppc64, triple: powerpc64-linux-gnu }
|
||||||
|
- { arch: ppc64le, triple: powerpc64le-linux-gnu }
|
||||||
|
- { arch: mips, triple: mips-linux-gnu }
|
||||||
|
- { arch: mipsel, triple: mipsel-linux-gnu }
|
||||||
|
# Builds successfully, but tests fail.
|
||||||
|
# - { arch: mips64, triple: mips64-linux-gnuabi64 }
|
||||||
|
# - { arch: mips64el, triple: mips64el-linux-gnuabi64 }
|
||||||
|
- { arch: riscv64, triple: riscv64-linux-gnu }
|
||||||
|
- { arch: s390x, triple: s390x-linux-gnu }
|
||||||
|
env:
|
||||||
|
ARCH: ${{ matrix.config.arch }}
|
||||||
|
TRIPLE: ${{ matrix.config.triple }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v5
|
||||||
|
- name: Install qemu and toolchain gcc-${{ matrix.config.triple }}
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install qemu-user qemu-user-binfmt gcc-$TRIPLE -y
|
||||||
|
- name: Build with ${{ matrix.config.triple }}-gcc
|
||||||
|
run: make ARCH=$ARCH TOOLPREFIX=$TRIPLE-
|
||||||
|
- name: Build tests
|
||||||
|
run: make -C test ARCH=$ARCH TOOLPREFIX=$TRIPLE-
|
||||||
|
- name: Run Tests
|
||||||
|
env:
|
||||||
|
QEMU_EXEC: qemu-${{ matrix.config.arch }}
|
||||||
|
CROSS_LIB: /usr/${{ matrix.config.triple }}
|
||||||
|
run: |
|
||||||
|
$QEMU_EXEC -L . -L $CROSS_LIB/ test/test-float
|
||||||
|
$QEMU_EXEC -L . -L $CROSS_LIB/ test/test-double
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
*.o
|
||||||
|
*~
|
||||||
|
*.a
|
||||||
|
*.dll*
|
||||||
|
*.so*
|
||||||
|
*.dylib*
|
||||||
|
*.pc
|
||||||
|
|
||||||
|
# code coverage
|
||||||
|
openlibm-test
|
||||||
|
cov-html/
|
||||||
|
*.gcda
|
||||||
|
*.gcno
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
JuliaLang <julia-dev@googlegroups.com> <julia-dev@googlegroups.com>
|
||||||
|
JuliaLang <julia-dev@googlegroups.com> <julia-math@googlegroups.com>
|
||||||
|
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <jeff.bezanson@gmail.com>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@beagle.darwinproject.mit.edu>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@caspian.caspian.mit.edu>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@evolution.local>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@mathstation045.mit.edu>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@mathstation049.mit.edu>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@mathstation186.mit.edu>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@post.harvard.edu>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@scooby-doo.csail.mit.edu>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <bezanson@shaggy.csail.mit.edu>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <jeff@lagann.(none)>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <julia@beowulf1.csail.mit.edu>
|
||||||
|
Jeff Bezanson <jeff.bezanson@gmail.com> <vcloud@julia02.domain.local>
|
||||||
|
|
||||||
|
Stefan Karpinski <stefan@karpinski.org> <stefan@karpinski.org>
|
||||||
|
Stefan Karpinski <stefan@karpinski.org> <stefan.karpinski@gmail.com>
|
||||||
|
Stefan Karpinski <stefan@karpinski.org> <stefan.karpinski@post.harvard.edu>
|
||||||
|
|
||||||
|
Viral B. Shah <viral@mayin.org> <viral@mayin.org>
|
||||||
|
Viral B. Shah <viral@mayin.org> <viral@beowulf1.csail.mit.edu>
|
||||||
|
Viral B. Shah <viral@mayin.org> <viral@neumann.cs.ucsb.edu>
|
||||||
|
Viral B. Shah <viral@mayin.org> <viral@ubuntu-VirtualBox.(none)>
|
||||||
|
|
||||||
|
George Xing <gxing@mit.edu> <gxing@mit.edu>
|
||||||
|
George Xing <gxing@mit.edu> <noobiecubie@gmail.com>
|
||||||
|
|
||||||
|
Stephan Boyer <boyers@mit.edu> <boyers@mit.edu>
|
||||||
|
Stephan Boyer <boyers@mit.edu> <stephan@julialang.xvm.mit.edu>
|
||||||
|
Stephan Boyer <boyers@mit.edu> <stephan@ubuntu.(none)>
|
||||||
|
Stephan Boyer <boyers@mit.edu> <stephan@ubuntu.ubuntu-domain>
|
||||||
|
|
||||||
|
Giuseppe Zingales <giuseppe.pet.zingales@gmail.com> <giuseppe.pet.zingales@gmail.com>
|
||||||
|
Giuseppe Zingales <giuseppe.pet.zingales@gmail.com> <g3@ubuntu.ubuntu-domain>
|
||||||
|
|
||||||
|
Jameson Nash <jameson@mit.edu> <jameson@mit.edu>
|
||||||
|
Jameson Nash <jameson@mit.edu> <vtjnash@comcast.net>
|
||||||
|
Jameson Nash <jameson@mit.edu> <vtjnash@gmail.com>
|
||||||
|
|
||||||
|
Alan Edelman <mit.edelman@gmail.com> <mit.edelman@gmail.com>
|
||||||
|
|
||||||
|
PlayMyCode <joe@playmycode.com> <joe@playmycode.com>
|
||||||
|
PlayMyCode <joe@playmycode.com> <hello@playmycode.com>
|
||||||
|
|
||||||
|
Corey M. Hoffstein <corey@hoffstein.com> <corey@hoffstein.com>
|
||||||
|
Corey M. Hoffstein <corey@hoffstein.com> <corey@newfoundresearch.com>
|
||||||
|
|
||||||
|
Stefan Kroboth <stefan.kroboth@gmail.com> <stefan.kroboth@gmail.com>
|
||||||
|
|
||||||
|
Tim Holy <tim.holy@gmail.com> <tim.holy@gmail.com>
|
||||||
|
Tim Holy <tim.holy@gmail.com> <holy@wustl.edu>
|
||||||
|
|
||||||
|
Patrick O'Leary <patrick.oleary@gmail.com> <patrick.oleary@gmail.com>
|
||||||
|
|
||||||
|
Ivan Mantova <horphus@gmail.com> <horphus@gmail.com>
|
||||||
|
|
||||||
|
Keno Fischer <kfischer@college.harvard.edu> <kfischer@college.harvard.edu>
|
||||||
|
Keno Fischer <kfischer@college.harvard.edu> <kfischer+github@college.harvard.edu>
|
||||||
|
Keno Fischer <kfischer@college.harvard.edu> <kenof@stanford.edu>
|
||||||
Executable
+576
@@ -0,0 +1,576 @@
|
|||||||
|
cmake_minimum_required(VERSION 3.25)
|
||||||
|
|
||||||
|
# Get version string from Make.inc
|
||||||
|
file(READ "${CMAKE_CURRENT_LIST_DIR}/Make.inc" MAKE_FILE)
|
||||||
|
string(REGEX MATCH "VERSION = ([0-9\.]+)" _ ${MAKE_FILE})
|
||||||
|
|
||||||
|
project(openlibm
|
||||||
|
VERSION ${CMAKE_MATCH_1}
|
||||||
|
LANGUAGES C ASM)
|
||||||
|
|
||||||
|
option(BUILD_SHARED_LIBS "Build using shared libraries" ON)
|
||||||
|
|
||||||
|
add_library("${PROJECT_NAME}")
|
||||||
|
|
||||||
|
# Find the relevant folder depending on the architecture
|
||||||
|
set(OPENLIBM_ARCH_FOLDER ${CMAKE_SYSTEM_PROCESSOR})
|
||||||
|
string(TOLOWER "${OPENLIBM_ARCH_FOLDER}" OPENLIBM_ARCH_FOLDER)
|
||||||
|
|
||||||
|
if(${OPENLIBM_ARCH_FOLDER} STREQUAL "amd64" OR ${OPENLIBM_ARCH_FOLDER} STREQUAL "x86_64")
|
||||||
|
set(OPENLIBM_ARCH_FOLDER "amd64")
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "arm64" OR ${OPENLIBM_ARCH_FOLDER} STREQUAL "aarch64")
|
||||||
|
set(OPENLIBM_ARCH_FOLDER "aarch64")
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "armv7-a")
|
||||||
|
set(OPENLIBM_ARCH_FOLDER "arm")
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "x86" OR ${OPENLIBM_ARCH_FOLDER} STREQUAL "i686")
|
||||||
|
set(OPENLIBM_ARCH_FOLDER "i387")
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "powerpc")
|
||||||
|
set(OPENLIBM_ARCH_FOLDER "powerpc")
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "riscv64")
|
||||||
|
set(OPENLIBM_ARCH_FOLDER "riscv64")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "${PROJECT_NAME} not set up for detected architecture: ${OPENLIBM_ARCH_FOLDER}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Compile flags
|
||||||
|
list(APPEND C_ASM_COMPILE_FLAGS "-ffp-contract=off" "-fno-fast-math" "-fno-rounding-math" "-fno-math-errno")
|
||||||
|
list(APPEND C_ASM_COMPILE_FLAGS "-fPIC" "-std=c99" "-fno-builtin")
|
||||||
|
list(APPEND C_ASM_COMPILE_FLAGS "-Wall" "-Wno-implicit-function-declaration")
|
||||||
|
list(APPEND C_ASM_COMPILE_FLAGS "-DASSEMBLER" "-D__BSD_VISIBLE" "-O3")
|
||||||
|
|
||||||
|
# Compiler-specific compile flags
|
||||||
|
if("${CMAKE_C_COMPILER_ID}" MATCHES "Clang")
|
||||||
|
list(APPEND C_ASM_COMPILE_FLAGS "-fno-strict-aliasing" "-ffp-exception-behavior=strict")
|
||||||
|
elseif("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
|
||||||
|
list(APPEND C_ASM_COMPILE_FLAGS "-fno-gnu89-inline")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "${PROJECT_NAME} not set up to be compiled with ${CMAKE_C_COMPILER_ID}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Architecture-specific compile flags - take advantage of sse on x86
|
||||||
|
if(${OPENLIBM_ARCH_FOLDER} STREQUAL "i387")
|
||||||
|
list(APPEND C_ASM_COMPILE_FLAGS "-march=i686" "-m32" "-msse2" "-mfpmath=sse")
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "amd64")
|
||||||
|
list(APPEND C_ASM_COMPILE_FLAGS "-m64" "-msse2" "-mfpmath=sse")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Suppress warnings if requested
|
||||||
|
if(OPENLIBM_SUPPRESS_WARNINGS)
|
||||||
|
list(APPEND C_ASM_COMPILE_FLAGS "-w")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Add compile flags
|
||||||
|
target_compile_options("${PROJECT_NAME}" PUBLIC ${C_ASM_COMPILE_FLAGS})
|
||||||
|
|
||||||
|
# Project Source
|
||||||
|
set(PROJECT_SRC "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||||
|
|
||||||
|
# Common
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
# src
|
||||||
|
"${PROJECT_SRC}/src/common.c"
|
||||||
|
"${PROJECT_SRC}/src/e_acos.c"
|
||||||
|
"${PROJECT_SRC}/src/e_acosf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_acosh.c"
|
||||||
|
"${PROJECT_SRC}/src/e_acoshf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_asin.c"
|
||||||
|
"${PROJECT_SRC}/src/e_asinf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_atan2.c"
|
||||||
|
"${PROJECT_SRC}/src/e_atan2f.c"
|
||||||
|
"${PROJECT_SRC}/src/e_atanh.c"
|
||||||
|
"${PROJECT_SRC}/src/e_atanhf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_cosh.c"
|
||||||
|
"${PROJECT_SRC}/src/e_coshf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_exp.c"
|
||||||
|
"${PROJECT_SRC}/src/e_expf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_fmod.c"
|
||||||
|
"${PROJECT_SRC}/src/e_fmodf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_hypot.c"
|
||||||
|
"${PROJECT_SRC}/src/e_hypotf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_j0.c"
|
||||||
|
"${PROJECT_SRC}/src/e_j0f.c"
|
||||||
|
"${PROJECT_SRC}/src/e_j1.c"
|
||||||
|
"${PROJECT_SRC}/src/e_j1f.c"
|
||||||
|
"${PROJECT_SRC}/src/e_jn.c"
|
||||||
|
"${PROJECT_SRC}/src/e_jnf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_lgamma.c"
|
||||||
|
"${PROJECT_SRC}/src/e_lgamma_r.c"
|
||||||
|
"${PROJECT_SRC}/src/e_lgammaf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_lgammaf_r.c"
|
||||||
|
"${PROJECT_SRC}/src/e_log.c"
|
||||||
|
"${PROJECT_SRC}/src/e_log10.c"
|
||||||
|
"${PROJECT_SRC}/src/e_log10f.c"
|
||||||
|
"${PROJECT_SRC}/src/e_log2.c"
|
||||||
|
"${PROJECT_SRC}/src/e_log2f.c"
|
||||||
|
"${PROJECT_SRC}/src/e_logf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_pow.c"
|
||||||
|
"${PROJECT_SRC}/src/e_powf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_remainder.c"
|
||||||
|
"${PROJECT_SRC}/src/e_remainderf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_rem_pio2.c"
|
||||||
|
"${PROJECT_SRC}/src/e_rem_pio2f.c"
|
||||||
|
"${PROJECT_SRC}/src/e_sinh.c"
|
||||||
|
"${PROJECT_SRC}/src/e_sinhf.c"
|
||||||
|
"${PROJECT_SRC}/src/e_sqrt.c"
|
||||||
|
"${PROJECT_SRC}/src/e_sqrtf.c"
|
||||||
|
"${PROJECT_SRC}/src/k_cos.c"
|
||||||
|
"${PROJECT_SRC}/src/k_exp.c"
|
||||||
|
"${PROJECT_SRC}/src/k_expf.c"
|
||||||
|
"${PROJECT_SRC}/src/k_rem_pio2.c"
|
||||||
|
"${PROJECT_SRC}/src/k_sin.c"
|
||||||
|
"${PROJECT_SRC}/src/k_tan.c"
|
||||||
|
"${PROJECT_SRC}/src/k_cosf.c"
|
||||||
|
"${PROJECT_SRC}/src/k_sinf.c"
|
||||||
|
"${PROJECT_SRC}/src/k_tanf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_asinh.c"
|
||||||
|
"${PROJECT_SRC}/src/s_asinhf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_atan.c"
|
||||||
|
"${PROJECT_SRC}/src/s_atanf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_carg.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cargf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cbrt.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cbrtf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ceil.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ceilf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_copysign.c"
|
||||||
|
"${PROJECT_SRC}/src/s_copysignf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cos.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cosf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_csqrt.c"
|
||||||
|
"${PROJECT_SRC}/src/s_csqrtf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_erf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_erff.c"
|
||||||
|
"${PROJECT_SRC}/src/s_exp2.c"
|
||||||
|
"${PROJECT_SRC}/src/s_exp2f.c"
|
||||||
|
"${PROJECT_SRC}/src/s_expm1.c"
|
||||||
|
"${PROJECT_SRC}/src/s_expm1f.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fabs.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fabsf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fdim.c"
|
||||||
|
"${PROJECT_SRC}/src/s_floor.c"
|
||||||
|
"${PROJECT_SRC}/src/s_floorf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fmax.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fmaxf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fmin.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fminf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fpclassify.c"
|
||||||
|
"${PROJECT_SRC}/src/s_frexp.c"
|
||||||
|
"${PROJECT_SRC}/src/s_frexpf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ilogb.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ilogbf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_isinf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_isfinite.c"
|
||||||
|
"${PROJECT_SRC}/src/s_isnormal.c"
|
||||||
|
"${PROJECT_SRC}/src/s_isnan.c"
|
||||||
|
"${PROJECT_SRC}/src/s_log1p.c"
|
||||||
|
"${PROJECT_SRC}/src/s_log1pf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_logb.c"
|
||||||
|
"${PROJECT_SRC}/src/s_logbf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_modf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_modff.c"
|
||||||
|
"${PROJECT_SRC}/src/s_nextafter.c"
|
||||||
|
"${PROJECT_SRC}/src/s_nextafterf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_nexttowardf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_remquo.c"
|
||||||
|
"${PROJECT_SRC}/src/s_remquof.c"
|
||||||
|
"${PROJECT_SRC}/src/s_rint.c"
|
||||||
|
"${PROJECT_SRC}/src/s_rintf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_round.c"
|
||||||
|
"${PROJECT_SRC}/src/s_roundf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_scalbln.c"
|
||||||
|
"${PROJECT_SRC}/src/s_scalbn.c"
|
||||||
|
"${PROJECT_SRC}/src/s_scalbnf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_signbit.c"
|
||||||
|
"${PROJECT_SRC}/src/s_signgam.c"
|
||||||
|
"${PROJECT_SRC}/src/s_sin.c"
|
||||||
|
"${PROJECT_SRC}/src/s_sincos.c"
|
||||||
|
"${PROJECT_SRC}/src/s_sinf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_sincosf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_tan.c"
|
||||||
|
"${PROJECT_SRC}/src/s_tanf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_tanh.c"
|
||||||
|
"${PROJECT_SRC}/src/s_tanhf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_tgammaf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_trunc.c"
|
||||||
|
"${PROJECT_SRC}/src/s_truncf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cpow.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cpowf.c"
|
||||||
|
"${PROJECT_SRC}/src/w_cabs.c"
|
||||||
|
"${PROJECT_SRC}/src/w_cabsf.c"
|
||||||
|
|
||||||
|
"${PROJECT_SRC}/src/s_fma.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fmaf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_lrint.c"
|
||||||
|
"${PROJECT_SRC}/src/s_lrintf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_lround.c"
|
||||||
|
"${PROJECT_SRC}/src/s_lroundf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_llrint.c"
|
||||||
|
"${PROJECT_SRC}/src/s_llrintf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_llround.c"
|
||||||
|
"${PROJECT_SRC}/src/s_llroundf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_nearbyint.c"
|
||||||
|
|
||||||
|
# C99 complex functions
|
||||||
|
"${PROJECT_SRC}/src/s_ccosh.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ccoshf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cexp.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cexpf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cimag.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cimagf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_conj.c"
|
||||||
|
"${PROJECT_SRC}/src/s_conjf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cproj.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cprojf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_creal.c"
|
||||||
|
"${PROJECT_SRC}/src/s_crealf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_csinh.c"
|
||||||
|
"${PROJECT_SRC}/src/s_csinhf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ctanh.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ctanhf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cacos.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cacosf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cacosh.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cacoshf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_casin.c"
|
||||||
|
"${PROJECT_SRC}/src/s_casinf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_casinh.c"
|
||||||
|
"${PROJECT_SRC}/src/s_casinhf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_catan.c"
|
||||||
|
"${PROJECT_SRC}/src/s_catanf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_catanh.c"
|
||||||
|
"${PROJECT_SRC}/src/s_catanhf.c"
|
||||||
|
"${PROJECT_SRC}/src/s_clog.c"
|
||||||
|
"${PROJECT_SRC}/src/s_clogf.c"
|
||||||
|
|
||||||
|
# bsdsrc
|
||||||
|
"${PROJECT_SRC}/bsdsrc/b_exp.c"
|
||||||
|
"${PROJECT_SRC}/bsdsrc/b_log.c"
|
||||||
|
"${PROJECT_SRC}/bsdsrc/b_tgamma.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/src/s_nan.c"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine if long double and double are the same size
|
||||||
|
include(CheckCSourceCompiles)
|
||||||
|
check_c_source_compiles("
|
||||||
|
#include <float.h>
|
||||||
|
#if (LDBL_MANT_DIG == DBL_MANT_DIG)
|
||||||
|
#error \"long double and double are the same size\"
|
||||||
|
#endif
|
||||||
|
int main(void ) { return 0; }
|
||||||
|
" LONG_DOUBLE_NOT_DOUBLE)
|
||||||
|
|
||||||
|
# Add in long double functions for x86, x64 and aarch64
|
||||||
|
if(LONG_DOUBLE_NOT_DOUBLE)
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/src/s_copysignl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fabsl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_llrintl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_lrintl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_modfl.c"
|
||||||
|
|
||||||
|
"${PROJECT_SRC}/src/e_acosl.c"
|
||||||
|
"${PROJECT_SRC}/src/e_asinl.c"
|
||||||
|
"${PROJECT_SRC}/src/e_atan2l.c"
|
||||||
|
"${PROJECT_SRC}/src/e_fmodl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fmaxl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fminl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ilogbl.c"
|
||||||
|
"${PROJECT_SRC}/src/e_hypotl.c"
|
||||||
|
"${PROJECT_SRC}/src/e_lgammal.c"
|
||||||
|
"${PROJECT_SRC}/src/e_remainderl.c"
|
||||||
|
"${PROJECT_SRC}/src/e_sqrtl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_atanl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ceill.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cosl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cprojl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_csqrtl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_floorl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_fmal.c"
|
||||||
|
"${PROJECT_SRC}/src/s_frexpl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_logbl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_nexttoward.c"
|
||||||
|
"${PROJECT_SRC}/src/s_remquol.c"
|
||||||
|
"${PROJECT_SRC}/src/s_roundl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_lroundl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_llroundl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cpowl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cargl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_sinl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_sincosl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_tanl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_truncl.c"
|
||||||
|
"${PROJECT_SRC}/src/w_cabsl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_nextafterl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_rintl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_scalbnl.c"
|
||||||
|
"${PROJECT_SRC}/src/polevll.c"
|
||||||
|
"${PROJECT_SRC}/src/s_casinl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ctanl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cimagl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_conjl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_creall.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cacoshl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_catanhl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_casinhl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_catanl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_csinl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cacosl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cexpl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_csinhl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ccoshl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_clogl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ctanhl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_ccosl.c"
|
||||||
|
"${PROJECT_SRC}/src/s_cbrtl.c"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (LONG_DOUBLE_NOT_DOUBLE)
|
||||||
|
if (${OPENLIBM_ARCH_FOLDER} STREQUAL "i387" OR ${OPENLIBM_ARCH_FOLDER} STREQUAL "amd64")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
# ld80
|
||||||
|
"${PROJECT_SRC}/ld80/invtrig.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_acoshl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_powl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/k_tanl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/s_exp2l.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_atanhl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_lgammal_r.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_sinhl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/s_asinhl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/s_expm1l.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_coshl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_log10l.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_tgammal.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_expl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_log2l.c"
|
||||||
|
"${PROJECT_SRC}/ld80/k_cosl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/s_log1pl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/s_tanhl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/e_logl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/k_sinl.c"
|
||||||
|
"${PROJECT_SRC}/ld80/s_erfl.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/ld80/s_nanl.c"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(${OPENLIBM_ARCH_FOLDER} STREQUAL "aarch64")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
# ld128
|
||||||
|
"${PROJECT_SRC}/ld128/invtrig.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_acoshl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_powl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/k_tanl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/s_exp2l.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_atanhl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_lgammal_r.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_sinhl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/s_asinhl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/s_expm1l.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_coshl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_log10l.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_tgammal.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_expl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_log2l.c"
|
||||||
|
"${PROJECT_SRC}/ld128/k_cosl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/s_log1pl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/s_tanhl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/e_logl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/k_sinl.c"
|
||||||
|
"${PROJECT_SRC}/ld128/s_erfl.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/ld128/s_nanl.c"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Architecture-specific sources
|
||||||
|
if (${OPENLIBM_ARCH_FOLDER} STREQUAL "amd64")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/amd64/fenv.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND OPENLIBM_ASM_SOURCE
|
||||||
|
"${PROJECT_SRC}/amd64/e_remainder.S"
|
||||||
|
"${PROJECT_SRC}/amd64/e_remainderf.S"
|
||||||
|
"${PROJECT_SRC}/amd64/e_remainderl.S"
|
||||||
|
"${PROJECT_SRC}/amd64/e_sqrt.S"
|
||||||
|
"${PROJECT_SRC}/amd64/e_sqrtf.S"
|
||||||
|
"${PROJECT_SRC}/amd64/e_sqrtl.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_llrint.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_llrintf.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_llrintl.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_logbl.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_lrint.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_lrintf.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_lrintl.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_remquo.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_remquof.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_remquol.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_rintl.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_scalbn.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_scalbnf.S"
|
||||||
|
"${PROJECT_SRC}/amd64/s_scalbnl.S"
|
||||||
|
"${PROJECT_SRC}/amd64/e_fmod.S"
|
||||||
|
"${PROJECT_SRC}/amd64/e_fmodf.S"
|
||||||
|
"${PROJECT_SRC}/amd64/e_fmodl.S"
|
||||||
|
)
|
||||||
|
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "aarch64")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/aarch64/fenv.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "arm")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/${OPENLIBM_ARCH_FOLDER}/fenv.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "i387")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/i387/fenv.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
list(APPEND OPENLIBM_ASM_SOURCE
|
||||||
|
"${PROJECT_SRC}/i387/e_exp.S"
|
||||||
|
"${PROJECT_SRC}/i387/e_fmod.S"
|
||||||
|
"${PROJECT_SRC}/i387/e_log.S"
|
||||||
|
"${PROJECT_SRC}/i387/e_log10.S"
|
||||||
|
"${PROJECT_SRC}/i387/e_remainder.S"
|
||||||
|
"${PROJECT_SRC}/i387/e_sqrt.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_ceil.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_copysign.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_floor.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_llrint.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_logb.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_lrint.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_remquo.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_rint.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_tan.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_trunc.S"
|
||||||
|
|
||||||
|
# float counterparts
|
||||||
|
"${PROJECT_SRC}/i387/e_log10f.S"
|
||||||
|
"${PROJECT_SRC}/i387/e_logf.S"
|
||||||
|
"${PROJECT_SRC}/i387/e_remainderf.S"
|
||||||
|
"${PROJECT_SRC}/i387/e_sqrtf.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_ceilf.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_copysignf.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_floorf.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_llrintf.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_logbf.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_lrintf.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_remquof.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_rintf.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_truncf.S"
|
||||||
|
|
||||||
|
# long double counterparts
|
||||||
|
"${PROJECT_SRC}/i387/e_remainderl.S"
|
||||||
|
"${PROJECT_SRC}/i387/e_sqrtl.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_ceill.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_copysignl.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_floorl.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_llrintl.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_logbl.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_lrintl.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_remquol.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_rintl.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_truncl.S"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT ${CMAKE_SYSTEM_NAME} STREQUAL "Windows")
|
||||||
|
list(APPEND OPENLIBM_ASM_SOURCE
|
||||||
|
"${PROJECT_SRC}/i387/s_scalbn.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_scalbnf.S"
|
||||||
|
"${PROJECT_SRC}/i387/s_scalbnl.S"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "powerpc")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/powerpc/fenv.c"
|
||||||
|
)
|
||||||
|
elseif(${OPENLIBM_ARCH_FOLDER} STREQUAL "riscv64")
|
||||||
|
list(APPEND OPENLIBM_C_SOURCE
|
||||||
|
"${PROJECT_SRC}/riscv64/fenv.c")
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "${PROJECT_NAME} CMake build is not set up for ${OPENLIBM_ARCH_FOLDER}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
# Filter out C implementation from compilation list if a native implementation exists
|
||||||
|
foreach(FILE_TO_REMOVE ${OPENLIBM_ASM_SOURCE})
|
||||||
|
# Get filename and strip out extension
|
||||||
|
cmake_path(GET FILE_TO_REMOVE FILENAME FILENAME_TO_REMOVE)
|
||||||
|
cmake_path(REMOVE_EXTENSION FILENAME_TO_REMOVE OUTPUT_VARIABLE FILENAME_TO_REMOVE)
|
||||||
|
message(DEBUG "Filename to remove: ${FILENAME_TO_REMOVE}")
|
||||||
|
|
||||||
|
# Go through files and remove one with the same name
|
||||||
|
foreach(CUR_FILE ${OPENLIBM_C_SOURCE})
|
||||||
|
cmake_path(GET CUR_FILE FILENAME CUR_FILENAME)
|
||||||
|
cmake_path(REMOVE_EXTENSION CUR_FILENAME OUTPUT_VARIABLE CUR_FILENAME)
|
||||||
|
|
||||||
|
if(${CUR_FILENAME} STREQUAL ${FILENAME_TO_REMOVE})
|
||||||
|
list(REMOVE_ITEM OPENLIBM_C_SOURCE ${CUR_FILE})
|
||||||
|
message(DEBUG "Removed source file from compilation list: ${CUR_FILE}")
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
|
||||||
|
# Add sources
|
||||||
|
target_sources("${PROJECT_NAME}" PRIVATE ${OPENLIBM_C_SOURCE}
|
||||||
|
${OPENLIBM_ASM_SOURCE}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Include directories
|
||||||
|
list(APPEND OPENLIBM_INCLUDE_DIRS
|
||||||
|
"${PROJECT_SRC}"
|
||||||
|
"${PROJECT_SRC}/include"
|
||||||
|
"${PROJECT_SRC}/${OPENLIBM_ARCH_FOLDER}"
|
||||||
|
"${PROJECT_SRC}/src"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(${OPENLIBM_ARCH_FOLDER} STREQUAL "i387" OR ${OPENLIBM_ARCH_FOLDER} STREQUAL "amd64" OR ${OPENLIBM_ARCH_FOLDER} STREQUAL "powerpc")
|
||||||
|
list(APPEND OPENLIBM_INCLUDE_DIRS "${PROJECT_SRC}/ld80")
|
||||||
|
else()
|
||||||
|
if(${OPENLIBM_ARCH_FOLDER} STREQUAL "aarch64" OR ${OPENLIBM_ARCH_FOLDER} STREQUAL "riscv64")
|
||||||
|
list(APPEND OPENLIBM_INCLUDE_DIRS "${PROJECT_SRC}/ld128")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories("${PROJECT_NAME}" PUBLIC ${OPENLIBM_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
file(GLOB PUBLIC_HEADERS "*.h" "include/*.h" "${OPENLIBM_ARCH_FOLDER}/*.h" "src/*.h")
|
||||||
|
set_target_properties("${PROJECT_NAME}" PROPERTIES PUBLIC_HEADER "${PUBLIC_HEADERS}")
|
||||||
|
install (TARGETS "${PROJECT_NAME}")
|
||||||
|
|
||||||
|
# Can't use configure_file because openlibm.pc.in uses $var instead of CMake configure @var's
|
||||||
|
# Would rather string replace variables here instead of editing .pc.in, because editing .pc.in
|
||||||
|
# might build break autotools build.
|
||||||
|
file(READ "${PROJECT_SRC}/openlibm.pc.in" PC_FILE)
|
||||||
|
string(REPLACE "\${version}" "${CMAKE_PROJECT_VERSION}" PC_FILE ${PC_FILE})
|
||||||
|
string(PREPEND PC_FILE "prefix=${CMAKE_INSTALL_PREFIX}
|
||||||
|
includedir=\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
libdir=\${prefix}/${CMAKE_INSTALL_LIBDIR}\n
|
||||||
|
")
|
||||||
|
file(WRITE "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc" ${PC_FILE})
|
||||||
|
install(FILES "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc"
|
||||||
|
DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
|
||||||
@@ -0,0 +1,115 @@
|
|||||||
|
## OpenLibm
|
||||||
|
|
||||||
|
OpenLibm contains code that is covered by various licenses.
|
||||||
|
|
||||||
|
The OpenLibm code derives from the FreeBSD msun and OpenBSD libm
|
||||||
|
implementations, which in turn derives from FDLIBM 5.3. As a result, it
|
||||||
|
has a number of fixes and updates that have accumulated over the years
|
||||||
|
in msun, and also optimized assembly versions of many functions. These
|
||||||
|
improvements are provided under the BSD and ISC licenses. The msun
|
||||||
|
library also includes work placed under the public domain, which is
|
||||||
|
noted in the individual files. Further work on making a standalone
|
||||||
|
OpenLibm library from msun, as part of the Julia project is covered
|
||||||
|
under the MIT license. The test files, test-double.c and test-float.c
|
||||||
|
are under the LGPL.
|
||||||
|
|
||||||
|
## Parts copyrighted by the Julia project (MIT License)
|
||||||
|
|
||||||
|
> Copyright (c) 2011-14 The Julia Project.
|
||||||
|
> https://github.com/JuliaMath/openlibm/graphs/contributors
|
||||||
|
>
|
||||||
|
> Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
> a copy of this software and associated documentation files (the
|
||||||
|
> "Software"), to deal in the Software without restriction, including
|
||||||
|
> without limitation the rights to use, copy, modify, merge, publish,
|
||||||
|
> distribute, sublicense, and/or sell copies of the Software, and to
|
||||||
|
> permit persons to whom the Software is furnished to do so, subject to
|
||||||
|
> the following conditions:
|
||||||
|
>
|
||||||
|
> The above copyright notice and this permission notice shall be
|
||||||
|
> included in all copies or substantial portions of the Software.
|
||||||
|
>
|
||||||
|
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||||
|
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||||
|
> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||||
|
> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||||
|
> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||||
|
> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
|
|
||||||
|
## Parts copyrighted by Stephen L. Moshier (ISC License)
|
||||||
|
|
||||||
|
> Copyright (c) 2008 Stephen L. Moshier <steve@moshier.net>
|
||||||
|
>
|
||||||
|
> Permission to use, copy, modify, and 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.
|
||||||
|
|
||||||
|
## FREEBSD MSUN (FreeBSD/2-clause BSD/Simplified BSD License)
|
||||||
|
|
||||||
|
> Copyright 1992-2011 The FreeBSD Project. All rights reserved.
|
||||||
|
>
|
||||||
|
> Redistribution and use in source and binary forms, with or without
|
||||||
|
> modification, are permitted provided that the following conditions are
|
||||||
|
> met:
|
||||||
|
>
|
||||||
|
> 1. Redistributions of source code must retain the above copyright
|
||||||
|
> notice, this list of conditions and the following disclaimer.
|
||||||
|
>
|
||||||
|
> 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
> notice, this list of conditions and the following disclaimer in the
|
||||||
|
> documentation and/or other materials provided with the distribution.
|
||||||
|
> THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY
|
||||||
|
> EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
> IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
> PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR
|
||||||
|
> CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||||
|
> EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
> PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||||
|
> PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||||
|
> LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||||
|
> NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
> SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
>
|
||||||
|
> The views and conclusions contained in the software and documentation
|
||||||
|
> are those of the authors and should not be interpreted as representing
|
||||||
|
> official policies, either expressed or implied, of the FreeBSD
|
||||||
|
> Project.
|
||||||
|
|
||||||
|
## FDLIBM
|
||||||
|
|
||||||
|
> Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
|
||||||
|
>
|
||||||
|
> Developed at SunPro, a Sun Microsystems, Inc. business.
|
||||||
|
> Permission to use, copy, modify, and distribute this
|
||||||
|
> software is freely granted, provided that this notice
|
||||||
|
> is preserved.
|
||||||
|
|
||||||
|
## Tests
|
||||||
|
|
||||||
|
> Copyright (C) 1997, 1999 Free Software Foundation, Inc.
|
||||||
|
> This file is part of the GNU C Library.
|
||||||
|
> Contributed by Andreas Jaeger <aj@suse.de>, 1997.
|
||||||
|
>
|
||||||
|
> The GNU C Library is free software; you can redistribute it and/or
|
||||||
|
> modify it under the terms of the GNU Lesser General Public
|
||||||
|
> License as published by the Free Software Foundation; either
|
||||||
|
> version 2.1 of the License, or (at your option) any later version.
|
||||||
|
>
|
||||||
|
> The GNU C Library is distributed in the hope that it will be useful,
|
||||||
|
> but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
> Lesser General Public License for more details.
|
||||||
|
>
|
||||||
|
> You should have received a copy of the GNU Lesser General Public
|
||||||
|
> License along with the GNU C Library; if not, write to the Free
|
||||||
|
> Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||||
|
> 02111-1307 USA.
|
||||||
@@ -0,0 +1,197 @@
|
|||||||
|
# -*- mode: makefile-gmake -*-
|
||||||
|
# vi:ft=make
|
||||||
|
|
||||||
|
# Default build rule for any Makefile in this project: all
|
||||||
|
default: all
|
||||||
|
|
||||||
|
OS := $(shell uname)
|
||||||
|
# Do not forget to bump SOMINOR when changing VERSION,
|
||||||
|
# and SOMAJOR when breaking ABI in a backward-incompatible way
|
||||||
|
VERSION = 0.8.0
|
||||||
|
SOMAJOR = 4
|
||||||
|
SOMINOR = 0
|
||||||
|
DESTDIR =
|
||||||
|
prefix ?= /usr/local
|
||||||
|
bindir ?= $(prefix)/bin
|
||||||
|
libdir ?= $(prefix)/lib
|
||||||
|
includedir ?= $(prefix)/include
|
||||||
|
|
||||||
|
ifeq ($(OS), FreeBSD)
|
||||||
|
pkgconfigdir ?= $(prefix)/libdata/pkgconfig
|
||||||
|
else
|
||||||
|
pkgconfigdir ?= $(libdir)/pkgconfig
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Build with Code Coverage
|
||||||
|
# Only test with Ubuntu + gcc + lcov, may not work for other platform.
|
||||||
|
# deps: https://github.com/linux-test-project/lcov
|
||||||
|
# You don't need to set this flag manually, `make coverage` will do it for you.
|
||||||
|
# Just Run: make clean && make coverage -j
|
||||||
|
CODE_COVERAGE ?= 0
|
||||||
|
|
||||||
|
ifneq (,$(findstring $(OS),Darwin FreeBSD OpenBSD))
|
||||||
|
USEGCC ?= 0
|
||||||
|
USECLANG ?= 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(findstring CLANG,$(MSYSTEM)))
|
||||||
|
# In MSYS2
|
||||||
|
USEGCC = 0
|
||||||
|
USECLANG = 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ARCH),wasm32)
|
||||||
|
USECLANG = 1
|
||||||
|
USEGCC = 0
|
||||||
|
TOOLPREFIX = llvm-
|
||||||
|
endif
|
||||||
|
|
||||||
|
USEGCC ?= 1
|
||||||
|
USECLANG ?= 0
|
||||||
|
TOOLPREFIX ?=
|
||||||
|
|
||||||
|
AR := $(TOOLPREFIX)ar
|
||||||
|
|
||||||
|
ifeq ($(USECLANG),1)
|
||||||
|
USEGCC = 0
|
||||||
|
CC = clang
|
||||||
|
CFLAGS_add += -fno-builtin -fno-strict-aliasing
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(USEGCC),1)
|
||||||
|
CC := $(TOOLPREFIX)gcc
|
||||||
|
CFLAGS_add += -fno-gnu89-inline -fno-builtin
|
||||||
|
endif
|
||||||
|
|
||||||
|
ARCH ?= $(shell $(CC) -dumpmachine | sed "s/\([^-]*\).*$$/\1/")
|
||||||
|
|
||||||
|
ifeq ($(ARCH),mingw32)
|
||||||
|
$(error "the mingw32 compiler you are using fails the openblas testsuite. please see the Julia README.windows.md document for a replacement")
|
||||||
|
endif
|
||||||
|
|
||||||
|
# OS-specific stuff
|
||||||
|
ifeq ($(ARCH),arm64)
|
||||||
|
override ARCH := aarch64
|
||||||
|
endif
|
||||||
|
ifeq ($(findstring arm,$(ARCH)),arm)
|
||||||
|
override ARCH := arm
|
||||||
|
MARCH ?= armv7-a+fp
|
||||||
|
CFLAGS_add += -mhard-float
|
||||||
|
endif
|
||||||
|
ifeq ($(findstring powerpc,$(ARCH)),powerpc)
|
||||||
|
override ARCH := powerpc
|
||||||
|
endif
|
||||||
|
ifeq ($(findstring ppc,$(ARCH)),ppc)
|
||||||
|
override ARCH := powerpc
|
||||||
|
endif
|
||||||
|
ifeq ($(findstring s390,$(ARCH)),s390)
|
||||||
|
override ARCH := s390
|
||||||
|
endif
|
||||||
|
ifneq ($(filter $(ARCH),i386 i486 i586 i686 i387 i487 i587 i687),)
|
||||||
|
override ARCH := i387
|
||||||
|
MARCH ?= i686
|
||||||
|
endif
|
||||||
|
ifeq ($(ARCH),x86_64)
|
||||||
|
override ARCH := amd64
|
||||||
|
endif
|
||||||
|
ifeq ($(findstring mips,$(ARCH)),mips)
|
||||||
|
override ARCH := mips
|
||||||
|
endif
|
||||||
|
ifeq ($(findstring riscv64,$(ARCH)),riscv64)
|
||||||
|
override ARCH := riscv64
|
||||||
|
endif
|
||||||
|
ifeq ($(findstring loongarch64,$(ARCH)),loongarch64)
|
||||||
|
override ARCH := loongarch64
|
||||||
|
endif
|
||||||
|
|
||||||
|
# If CFLAGS does not contain a -O optimization flag, default to -O3
|
||||||
|
ifeq ($(findstring -O,$(CFLAGS)),)
|
||||||
|
CFLAGS_add += -O3
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(findstring MINGW,$(OS)))
|
||||||
|
override OS=WINNT
|
||||||
|
endif
|
||||||
|
|
||||||
|
#keep these if statements separate
|
||||||
|
ifeq ($(OS), WINNT)
|
||||||
|
SHLIB_EXT = dll
|
||||||
|
SONAME_FLAG =
|
||||||
|
shlibdir = $(bindir)
|
||||||
|
else
|
||||||
|
ifeq ($(OS), Darwin)
|
||||||
|
SHLIB_EXT = dylib
|
||||||
|
SONAME_FLAG = -install_name
|
||||||
|
else
|
||||||
|
SHLIB_EXT = so
|
||||||
|
SONAME_FLAG = -soname
|
||||||
|
endif
|
||||||
|
CFLAGS_add += -fPIC
|
||||||
|
shlibdir = $(libdir)
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Add `-march` to our CFLAGS if it's defined
|
||||||
|
ifneq ($(MARCH),)
|
||||||
|
CFLAGS_arch += -march=$(MARCH)
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ARCH),i387)
|
||||||
|
CFLAGS_arch += -m32
|
||||||
|
SFLAGS_arch += -m32
|
||||||
|
LDFLAGS_arch += -m32
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ARCH),amd64)
|
||||||
|
CFLAGS_arch += -m64
|
||||||
|
SFLAGS_arch += -m64
|
||||||
|
LDFLAGS_arch += -m64
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(ARCH),wasm32)
|
||||||
|
CFLAGS_arch += -ffreestanding -nostdlib -nostdinc --target=wasm32-unknown-unknown
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Add our "arch"-related FLAGS in. We separate arch-related flags out so that
|
||||||
|
# we can conveniently get at them for targets that don't want the rest of
|
||||||
|
# *FLAGS_add, such as the testing Makefile targets
|
||||||
|
CFLAGS_add += $(CFLAGS_arch)
|
||||||
|
SFLAGS_add += $(SFLAGS_arch)
|
||||||
|
LDFLAGS_add += $(LDFLAGS_arch)
|
||||||
|
|
||||||
|
CFLAGS_add += -std=c99 -Wall -I$(OPENLIBM_HOME) -I$(OPENLIBM_HOME)/include -I$(OPENLIBM_HOME)/$(ARCH) -I$(OPENLIBM_HOME)/src -DASSEMBLER -D__BSD_VISIBLE -Wno-implicit-function-declaration
|
||||||
|
ifneq ($(filter $(ARCH),i387 amd64 powerpc),)
|
||||||
|
CFLAGS_add += -I$(OPENLIBM_HOME)/ld80
|
||||||
|
else
|
||||||
|
ifneq ($(filter $(ARCH),aarch64 riscv64),)
|
||||||
|
CFLAGS_add += -I$(OPENLIBM_HOME)/ld128
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifneq ($(filter $(ARCH),i387 amd64),)
|
||||||
|
# Determines whether `long double` is the same as `double` on this arch.
|
||||||
|
# linux x86_64, for instance, `long double` is 80 bits wide, whereas on macOS aarch64,
|
||||||
|
# `long double` is the same as `double`.
|
||||||
|
LONG_DOUBLE_NOT_DOUBLE := 1
|
||||||
|
else ifeq ($(ARCH), aarch64)
|
||||||
|
ifeq ($(filter $(OS),Darwin WINNT),)
|
||||||
|
LONG_DOUBLE_NOT_DOUBLE := 1
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(CODE_COVERAGE),1)
|
||||||
|
CFLAGS_add += -g -O0 --coverage
|
||||||
|
LDFLAGS_add += --coverage
|
||||||
|
endif # CODE_COVERAGE==1
|
||||||
|
|
||||||
|
|
||||||
|
%.c.o: %.c
|
||||||
|
$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_add) -c $< -o $@
|
||||||
|
|
||||||
|
%.S.o: %.S
|
||||||
|
$(CC) $(CPPFLAGS) $(SFLAGS) $(SFLAGS_add) $(filter -m% -B% -I% -D%,$(CFLAGS_add)) -c $< -o $@
|
||||||
|
|
||||||
|
|
||||||
|
# Makefile debugging trick:
|
||||||
|
# call print-VARIABLE to see the runtime value of any variable
|
||||||
|
print-%:
|
||||||
|
@echo '$*=$($*)'
|
||||||
@@ -0,0 +1,140 @@
|
|||||||
|
OPENLIBM_HOME=$(abspath .)
|
||||||
|
include ./Make.inc
|
||||||
|
|
||||||
|
SUBDIRS = src $(ARCH) bsdsrc
|
||||||
|
ifeq ($(LONG_DOUBLE_NOT_DOUBLE),1)
|
||||||
|
# Add ld80 directory on x86 and x64
|
||||||
|
ifneq ($(filter $(ARCH),i387 amd64),)
|
||||||
|
SUBDIRS += ld80
|
||||||
|
else
|
||||||
|
ifneq ($(filter $(ARCH),aarch64),)
|
||||||
|
SUBDIRS += ld128
|
||||||
|
else
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
define INC_template
|
||||||
|
TEST=test
|
||||||
|
override CUR_SRCS = $(1)_SRCS
|
||||||
|
include $(1)/Make.files
|
||||||
|
SRCS += $$(addprefix $(1)/,$$($(1)_SRCS))
|
||||||
|
endef
|
||||||
|
|
||||||
|
DIR=test
|
||||||
|
|
||||||
|
$(foreach dir,$(SUBDIRS),$(eval $(call INC_template,$(dir))))
|
||||||
|
|
||||||
|
DUPLICATE_NAMES = $(filter $(patsubst %.S,%,$($(ARCH)_SRCS)),$(patsubst %.c,%,$(src_SRCS)))
|
||||||
|
DUPLICATE_SRCS = $(addsuffix .c,$(DUPLICATE_NAMES))
|
||||||
|
|
||||||
|
OBJS = $(patsubst %.f,%.f.o,\
|
||||||
|
$(patsubst %.S,%.S.o,\
|
||||||
|
$(patsubst %.c,%.c.o,$(filter-out $(addprefix src/,$(DUPLICATE_SRCS)),$(SRCS)))))
|
||||||
|
|
||||||
|
# If we're on windows, don't do versioned shared libraries. Also, generate an import library
|
||||||
|
# for the DLL. If we're on OSX, put the version number before the .dylib. Otherwise,
|
||||||
|
# put it after.
|
||||||
|
ifeq ($(OS), WINNT)
|
||||||
|
OLM_MAJOR_MINOR_SHLIB_EXT := $(SHLIB_EXT)
|
||||||
|
LDFLAGS_add += -Wl,--out-implib,libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT).a
|
||||||
|
else
|
||||||
|
ifeq ($(OS), Darwin)
|
||||||
|
OLM_MAJOR_MINOR_SHLIB_EXT := $(SOMAJOR).$(SOMINOR).$(SHLIB_EXT)
|
||||||
|
OLM_MAJOR_SHLIB_EXT := $(SOMAJOR).$(SHLIB_EXT)
|
||||||
|
else
|
||||||
|
OLM_MAJOR_MINOR_SHLIB_EXT := $(SHLIB_EXT).$(SOMAJOR).$(SOMINOR)
|
||||||
|
OLM_MAJOR_SHLIB_EXT := $(SHLIB_EXT).$(SOMAJOR)
|
||||||
|
endif
|
||||||
|
LDFLAGS_add += -Wl,$(SONAME_FLAG),libopenlibm.$(OLM_MAJOR_SHLIB_EXT)
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: all check test clean distclean \
|
||||||
|
install install-static install-shared install-pkgconfig install-headers
|
||||||
|
|
||||||
|
|
||||||
|
OLM_LIBS := libopenlibm.a
|
||||||
|
ifneq ($(ARCH), wasm32)
|
||||||
|
OLM_LIBS += libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT)
|
||||||
|
endif
|
||||||
|
|
||||||
|
all : $(OLM_LIBS)
|
||||||
|
|
||||||
|
check test: test/test-double test/test-float
|
||||||
|
test/test-double
|
||||||
|
test/test-float
|
||||||
|
|
||||||
|
libopenlibm.a: $(OBJS)
|
||||||
|
$(AR) -rcs libopenlibm.a $(OBJS)
|
||||||
|
|
||||||
|
libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT): $(OBJS)
|
||||||
|
$(CC) -shared $(OBJS) $(LDFLAGS) $(LDFLAGS_add) -o $@
|
||||||
|
ifneq ($(OS),WINNT)
|
||||||
|
ln -sf $@ libopenlibm.$(OLM_MAJOR_SHLIB_EXT)
|
||||||
|
ln -sf $@ libopenlibm.$(SHLIB_EXT)
|
||||||
|
endif
|
||||||
|
|
||||||
|
test/test-double: libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT)
|
||||||
|
$(MAKE) -C test test-double
|
||||||
|
|
||||||
|
test/test-float: libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT)
|
||||||
|
$(MAKE) -C test test-float
|
||||||
|
|
||||||
|
COVERAGE_DIR:=cov-html
|
||||||
|
COVERAGE_FILE:=$(COVERAGE_DIR)/libopenlibm.info
|
||||||
|
# Gen cov report with: make clean && make coverage -j
|
||||||
|
coverage: clean-coverage
|
||||||
|
$(MAKE) test CODE_COVERAGE=1
|
||||||
|
$(MAKE) gen-cov-report
|
||||||
|
|
||||||
|
gen-cov-report:
|
||||||
|
-mkdir $(COVERAGE_DIR)
|
||||||
|
lcov -d amd64 -d bsdsrc -d ld80 -d src \
|
||||||
|
--rc lcov_branch_coverage=1 --capture --output-file $(COVERAGE_FILE)
|
||||||
|
genhtml --legend --branch-coverage \
|
||||||
|
--title "Openlibm commit `git rev-parse HEAD`" \
|
||||||
|
--output-directory $(COVERAGE_DIR)/ \
|
||||||
|
$(COVERAGE_FILE)
|
||||||
|
|
||||||
|
# Zero coverage statistics and Delete report
|
||||||
|
clean-coverage:
|
||||||
|
-lcov -d amd64 -d bsdsrc -d ld80 -d src --zerocounters
|
||||||
|
rm -f ./*/*.gcda
|
||||||
|
rm -rf $(COVERAGE_DIR)/
|
||||||
|
|
||||||
|
clean: clean-coverage
|
||||||
|
rm -f aarch64/*.o amd64/*.o arm/*.o bsdsrc/*.o i387/*.o loongarch64/*.o ld80/*.o ld128/*.o src/*.o powerpc/*.o mips/*.o s390/*.o riscv64/*.o
|
||||||
|
rm -f libopenlibm.a libopenlibm.*$(SHLIB_EXT)*
|
||||||
|
rm -f ./*/*.gcno
|
||||||
|
$(MAKE) -C test clean
|
||||||
|
|
||||||
|
openlibm.pc: openlibm.pc.in Make.inc Makefile
|
||||||
|
echo "version=${VERSION}" > openlibm.pc
|
||||||
|
echo "libdir=$(DESTDIR)$(libdir)" >> openlibm.pc
|
||||||
|
echo "includedir=$(DESTDIR)$(includedir)/openlibm" >> openlibm.pc
|
||||||
|
cat openlibm.pc.in >> openlibm.pc
|
||||||
|
|
||||||
|
install-static: libopenlibm.a
|
||||||
|
mkdir -p $(DESTDIR)$(libdir)
|
||||||
|
cp -RpP -f libopenlibm.a $(DESTDIR)$(libdir)/
|
||||||
|
|
||||||
|
install-shared: libopenlibm.$(OLM_MAJOR_MINOR_SHLIB_EXT)
|
||||||
|
mkdir -p $(DESTDIR)$(shlibdir)
|
||||||
|
ifeq ($(OS), WINNT)
|
||||||
|
mkdir -p $(DESTDIR)$(libdir)
|
||||||
|
cp -RpP -f libopenlibm.*$(SHLIB_EXT) $(DESTDIR)$(shlibdir)/
|
||||||
|
cp -RpP -f libopenlibm.*$(SHLIB_EXT).a $(DESTDIR)$(libdir)/
|
||||||
|
else
|
||||||
|
cp -RpP -f libopenlibm.*$(SHLIB_EXT)* $(DESTDIR)$(shlibdir)/
|
||||||
|
endif
|
||||||
|
|
||||||
|
install-pkgconfig: openlibm.pc
|
||||||
|
mkdir -p $(DESTDIR)$(pkgconfigdir)
|
||||||
|
cp -RpP -f openlibm.pc $(DESTDIR)$(pkgconfigdir)/
|
||||||
|
|
||||||
|
install-headers:
|
||||||
|
mkdir -p $(DESTDIR)$(includedir)/openlibm
|
||||||
|
cp -RpP -f include/*.h $(DESTDIR)$(includedir)/openlibm
|
||||||
|
cp -RpP -f src/*.h $(DESTDIR)$(includedir)/openlibm
|
||||||
|
|
||||||
|
install: install-static install-shared install-pkgconfig install-headers
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
# OpenLibm
|
||||||
|
|
||||||
|
[](https://codecov.io/gh/JuliaMath/openlibm)
|
||||||
|
|
||||||
|
[OpenLibm](https://openlibm.org/) is an effort to have a high quality, portable, standalone
|
||||||
|
C mathematical library ([`libm`](http://en.wikipedia.org/wiki/libm)).
|
||||||
|
It can be used standalone in applications and programming language
|
||||||
|
implementations.
|
||||||
|
|
||||||
|
The project was born out of a need to have a good `libm` for the
|
||||||
|
[Julia programming language](http://www.julialang.org) that worked
|
||||||
|
consistently across compilers and operating systems, and in 32-bit and
|
||||||
|
64-bit environments.
|
||||||
|
|
||||||
|
## Platform support
|
||||||
|
|
||||||
|
OpenLibm builds on Linux, macOS, Windows, FreeBSD, OpenBSD, NetBSD, and
|
||||||
|
DragonFly BSD. It builds with both GCC and clang. Although largely
|
||||||
|
tested and widely used on the x86 and x86-64 architectures, OpenLibm
|
||||||
|
also supports arm, aarch64, ppc64le, mips, wasm32, riscv, s390(x) and
|
||||||
|
loongarch64.
|
||||||
|
|
||||||
|
## Build instructions
|
||||||
|
|
||||||
|
### GNU Make
|
||||||
|
|
||||||
|
1. Use GNU Make to build OpenLibm. This is `make` on most systems, but `gmake` on BSDs.
|
||||||
|
2. Use `make USEGCC=1` to build with GCC. This is the default on
|
||||||
|
Linux and Windows.
|
||||||
|
3. Use `make USECLANG=1` to build with clang. This is the default on OS X, FreeBSD,
|
||||||
|
and OpenBSD.
|
||||||
|
4. Use `make ARCH=wasm32` to build the wasm32 library with clang.
|
||||||
|
5. Architectures are auto-detected. Use `make ARCH=i386` to force a
|
||||||
|
build for i386. Other supported architectures are i486, i586, and
|
||||||
|
i686. GCC 4.8 is the minimum requirement for correct codegen on
|
||||||
|
older 32-bit architectures.
|
||||||
|
|
||||||
|
|
||||||
|
**Cross Build**
|
||||||
|
Take `riscv64` as example:
|
||||||
|
1. install `qemu-riscv64-static`, `gcc-riscv64-linux-gnu`
|
||||||
|
2. Cross build:
|
||||||
|
```sh
|
||||||
|
ARCH=riscv64
|
||||||
|
TRIPLE=$ARCH-linux-gnu
|
||||||
|
make ARCH=$ARCH TOOLPREFIX=$TRIPLE- -j
|
||||||
|
make -C test ARCH=$ARCH TOOLPREFIX=$TRIPLE- -j
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Run test with qemu:
|
||||||
|
```sh
|
||||||
|
qemu-$ARCH-static -L . -L /usr/$TRIPLE/ test/test-float
|
||||||
|
qemu-$ARCH-static -L . -L /usr/$TRIPLE/ test/test-double
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### CMake
|
||||||
|
|
||||||
|
1. Create build directory with `mkdir build` and navigate into it with `cd build`.
|
||||||
|
2. Run CMake to configure project and generate native build system with `cmake /path/to/openlibm/`
|
||||||
|
or generate project with build system of choice e.g. `cmake /path/to/openlib/ -G "MinGW Makefiles"`.
|
||||||
|
3. Build with the build system with `cmake --build .`.
|
||||||
|
|
||||||
|
Default CMake configuration builds a shared library, this can easily be configured using
|
||||||
|
[BUILD_SHARED_LIBS](https://cmake.org/cmake/help/latest/variable/BUILD_SHARED_LIBS.html)
|
||||||
|
configuration option.
|
||||||
|
|
||||||
|
|
||||||
|
## Acknowledgements
|
||||||
|
|
||||||
|
PowerPC support for openlibm was graciously sponsored by IBM.
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
$(CUR_SRCS) = fenv.c
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $FreeBSD: src/lib/msun/arm/fenv.c,v 1.3 2011/10/16 05:37:56 das Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <openlibm_fenv.h>
|
||||||
|
|
||||||
|
#ifdef __GNUC_GNU_INLINE__
|
||||||
|
#error "This file must be compiled with C99 'inline' semantics"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hopefully the system ID byte is immutable, so it's valid to use
|
||||||
|
* this as a default environment.
|
||||||
|
*/
|
||||||
|
const fenv_t __fe_dfl_env = {0};
|
||||||
|
|
||||||
|
extern inline int feclearexcept(int __excepts);
|
||||||
|
extern inline int fegetexceptflag(fexcept_t *__flagp, int __excepts);
|
||||||
|
extern inline int fesetexceptflag(const fexcept_t *__flagp, int __excepts);
|
||||||
|
extern inline int feraiseexcept(int __excepts);
|
||||||
|
extern inline int fetestexcept(int __excepts);
|
||||||
|
extern inline int fegetround(void);
|
||||||
|
extern inline int fesetround(int __round);
|
||||||
|
extern inline int fegetenv(fenv_t *__envp);
|
||||||
|
extern inline int feholdexcept(fenv_t *__envp);
|
||||||
|
extern inline int fesetenv(const fenv_t *__envp);
|
||||||
|
extern inline int feupdateenv(const fenv_t *__envp);
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
$(CUR_SRCS) = fenv.c e_remainder.S e_remainderf.S e_remainderl.S \
|
||||||
|
e_sqrt.S e_sqrtf.S e_sqrtl.S \
|
||||||
|
s_llrint.S s_llrintf.S s_llrintl.S \
|
||||||
|
s_logbl.S s_lrint.S s_lrintf.S s_lrintl.S \
|
||||||
|
s_remquo.S s_remquof.S s_remquol.S \
|
||||||
|
s_rintl.S s_scalbn.S s_scalbnf.S s_scalbnl.S \
|
||||||
|
e_fmod.S e_fmodf.S e_fmodl.S
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1990 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* William Jolitz.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* from: @(#)DEFS.h 5.1 (Berkeley) 4/23/90
|
||||||
|
* $FreeBSD: src/sys/amd64/include/asm.h,v 1.18 2007/08/22 04:26:07 jkoshy Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BSD_ASM_H_
|
||||||
|
#define _BSD_ASM_H_
|
||||||
|
|
||||||
|
#ifdef __APPLE__
|
||||||
|
#include "../i387/osx_asm.h"
|
||||||
|
#define CNAME(x) EXT(x)
|
||||||
|
#else
|
||||||
|
#include "bsd_cdefs.h"
|
||||||
|
|
||||||
|
#ifdef PIC
|
||||||
|
#define PIC_PLT(x) x@PLT
|
||||||
|
#define PIC_GOT(x) x@GOTPCREL(%rip)
|
||||||
|
#else
|
||||||
|
#define PIC_PLT(x) x
|
||||||
|
#define PIC_GOT(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* CNAME and HIDENAME manage the relationship between symbol names in C
|
||||||
|
* and the equivalent assembly language names. CNAME is given a name as
|
||||||
|
* it would be used in a C program. It expands to the equivalent assembly
|
||||||
|
* language name. HIDENAME is given an assembly-language name, and expands
|
||||||
|
* to a possibly-modified form that will be invisible to C programs.
|
||||||
|
*/
|
||||||
|
#define CNAME(csym) csym
|
||||||
|
#define HIDENAME(asmsym) .asmsym
|
||||||
|
|
||||||
|
#define _START_ENTRY .p2align 4,0x90
|
||||||
|
|
||||||
|
#if defined(__ELF__)
|
||||||
|
#define _ENTRY(x) .text; _START_ENTRY; \
|
||||||
|
.globl CNAME(x); .type CNAME(x),@function; CNAME(x):
|
||||||
|
#define END(x) .size x, . - x
|
||||||
|
|
||||||
|
#elif defined(_WIN32)
|
||||||
|
#ifndef _MSC_VER
|
||||||
|
#define END(x) .end
|
||||||
|
#define _START_ENTRY_WIN .text; _START_ENTRY
|
||||||
|
#else
|
||||||
|
#define END(x) end
|
||||||
|
#define _START_ENTRY_WIN .code; _START_ENTRY
|
||||||
|
#endif
|
||||||
|
#define _ENTRY(x) _START_ENTRY_WIN; \
|
||||||
|
.globl CNAME(x); .section .drectve; .ascii " -export:", #x; \
|
||||||
|
.section .text; .def CNAME(x); .scl 2; .type 32; .endef; CNAME(x):
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PROF
|
||||||
|
#define ALTENTRY(x) _ENTRY(x); \
|
||||||
|
pushq %rbp; movq %rsp,%rbp; \
|
||||||
|
call PIC_PLT(HIDENAME(mcount)); \
|
||||||
|
popq %rbp; \
|
||||||
|
jmp 9f
|
||||||
|
#define ENTRY(x) _ENTRY(x); \
|
||||||
|
pushq %rbp; movq %rsp,%rbp; \
|
||||||
|
call PIC_PLT(HIDENAME(mcount)); \
|
||||||
|
popq %rbp; \
|
||||||
|
9:
|
||||||
|
#else
|
||||||
|
#define ALTENTRY(x) _ENTRY(x)
|
||||||
|
#define ENTRY(x) _ENTRY(x)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#define RCSID(x) .text; .asciz x
|
||||||
|
|
||||||
|
#undef __FBSDID
|
||||||
|
#if !defined(lint) && !defined(STRIP_FBSDID)
|
||||||
|
#define __FBSDID(s) .ident s
|
||||||
|
#else
|
||||||
|
#define __FBSDID(s) /* nothing */
|
||||||
|
#endif /* not lint and not STRIP_FBSDID */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif /* !_BSD_ASM_H_ */
|
||||||
@@ -0,0 +1,218 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 1990 The Regents of the University of California.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This code is derived from software contributed to Berkeley by
|
||||||
|
* William Jolitz.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 4. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* from: @(#)npx.h 5.3 (Berkeley) 1/18/91
|
||||||
|
* $FreeBSD: src/sys/x86/include/fpu.h,v 1.1 2012/03/16 20:24:30 tijl Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Floating Point Data Structures and Constants
|
||||||
|
* W. Jolitz 1/90
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BSD_FPU_H_
|
||||||
|
#define _BSD_FPU_H_
|
||||||
|
|
||||||
|
#include "types-compat.h"
|
||||||
|
|
||||||
|
/* Environment information of floating point unit. */
|
||||||
|
struct env87 {
|
||||||
|
int32_t en_cw; /* control word (16bits) */
|
||||||
|
int32_t en_sw; /* status word (16bits) */
|
||||||
|
int32_t en_tw; /* tag word (16bits) */
|
||||||
|
int32_t en_fip; /* fp instruction pointer */
|
||||||
|
uint16_t en_fcs; /* fp code segment selector */
|
||||||
|
uint16_t en_opcode; /* opcode last executed (11 bits) */
|
||||||
|
int32_t en_foo; /* fp operand offset */
|
||||||
|
int32_t en_fos; /* fp operand segment selector */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Contents of each x87 floating point accumulator. */
|
||||||
|
struct fpacc87 {
|
||||||
|
uint8_t fp_bytes[10];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Floating point context. (i386 fnsave/frstor) */
|
||||||
|
struct save87 {
|
||||||
|
struct env87 sv_env; /* floating point control/status */
|
||||||
|
struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */
|
||||||
|
uint8_t sv_pad0[4]; /* saved status word (now unused) */
|
||||||
|
/*
|
||||||
|
* Bogus padding for emulators. Emulators should use their own
|
||||||
|
* struct and arrange to store into this struct (ending here)
|
||||||
|
* before it is inspected for ptracing or for core dumps. Some
|
||||||
|
* emulators overwrite the whole struct. We have no good way of
|
||||||
|
* knowing how much padding to leave. Leave just enough for the
|
||||||
|
* GPL emulator's i387_union (176 bytes total).
|
||||||
|
*/
|
||||||
|
uint8_t sv_pad[64]; /* padding; used by emulators */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Contents of each SSE extended accumulator. */
|
||||||
|
struct xmmacc {
|
||||||
|
uint8_t xmm_bytes[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Contents of the upper 16 bytes of each AVX extended accumulator. */
|
||||||
|
struct ymmacc {
|
||||||
|
uint8_t ymm_bytes[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Rename structs below depending on machine architecture. */
|
||||||
|
#ifdef __i386__
|
||||||
|
#define __envxmm32 envxmm
|
||||||
|
#else
|
||||||
|
#define __envxmm32 envxmm32
|
||||||
|
#define __envxmm64 envxmm
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct __envxmm32 {
|
||||||
|
uint16_t en_cw; /* control word (16bits) */
|
||||||
|
uint16_t en_sw; /* status word (16bits) */
|
||||||
|
uint16_t en_tw; /* tag word (16bits) */
|
||||||
|
uint16_t en_opcode; /* opcode last executed (11 bits) */
|
||||||
|
uint32_t en_fip; /* fp instruction pointer */
|
||||||
|
uint16_t en_fcs; /* fp code segment selector */
|
||||||
|
uint16_t en_pad0; /* padding */
|
||||||
|
uint32_t en_foo; /* fp operand offset */
|
||||||
|
uint16_t en_fos; /* fp operand segment selector */
|
||||||
|
uint16_t en_pad1; /* padding */
|
||||||
|
uint32_t en_mxcsr; /* SSE control/status register */
|
||||||
|
uint32_t en_mxcsr_mask; /* valid bits in mxcsr */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct __envxmm64 {
|
||||||
|
uint16_t en_cw; /* control word (16bits) */
|
||||||
|
uint16_t en_sw; /* status word (16bits) */
|
||||||
|
uint8_t en_tw; /* tag word (8bits) */
|
||||||
|
uint8_t en_zero;
|
||||||
|
uint16_t en_opcode; /* opcode last executed (11 bits ) */
|
||||||
|
uint64_t en_rip; /* fp instruction pointer */
|
||||||
|
uint64_t en_rdp; /* fp operand pointer */
|
||||||
|
uint32_t en_mxcsr; /* SSE control/status register */
|
||||||
|
uint32_t en_mxcsr_mask; /* valid bits in mxcsr */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Floating point context. (i386 fxsave/fxrstor) */
|
||||||
|
struct savexmm {
|
||||||
|
struct __envxmm32 sv_env;
|
||||||
|
struct {
|
||||||
|
struct fpacc87 fp_acc;
|
||||||
|
uint8_t fp_pad[6]; /* padding */
|
||||||
|
} sv_fp[8];
|
||||||
|
struct xmmacc sv_xmm[8];
|
||||||
|
uint8_t sv_pad[224];
|
||||||
|
} __attribute__ ((aligned(16)));
|
||||||
|
|
||||||
|
#ifdef __i386__
|
||||||
|
union savefpu {
|
||||||
|
struct save87 sv_87;
|
||||||
|
struct savexmm sv_xmm;
|
||||||
|
};
|
||||||
|
#else
|
||||||
|
/* Floating point context. (amd64 fxsave/fxrstor) */
|
||||||
|
struct savefpu {
|
||||||
|
struct __envxmm64 sv_env;
|
||||||
|
struct {
|
||||||
|
struct fpacc87 fp_acc;
|
||||||
|
uint8_t fp_pad[6]; /* padding */
|
||||||
|
} sv_fp[8];
|
||||||
|
struct xmmacc sv_xmm[16];
|
||||||
|
uint8_t sv_pad[96];
|
||||||
|
} __attribute__ ((aligned(16)));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct xstate_hdr {
|
||||||
|
uint64_t xstate_bv;
|
||||||
|
uint8_t xstate_rsrv0[16];
|
||||||
|
uint8_t xstate_rsrv[40];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct savexmm_xstate {
|
||||||
|
struct xstate_hdr sx_hd;
|
||||||
|
struct ymmacc sx_ymm[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct savexmm_ymm {
|
||||||
|
struct __envxmm32 sv_env;
|
||||||
|
struct {
|
||||||
|
struct fpacc87 fp_acc;
|
||||||
|
int8_t fp_pad[6]; /* padding */
|
||||||
|
} sv_fp[8];
|
||||||
|
struct xmmacc sv_xmm[16];
|
||||||
|
uint8_t sv_pad[96];
|
||||||
|
struct savexmm_xstate sv_xstate;
|
||||||
|
} __attribute__ ((aligned(16)));
|
||||||
|
|
||||||
|
struct savefpu_xstate {
|
||||||
|
struct xstate_hdr sx_hd;
|
||||||
|
struct ymmacc sx_ymm[16];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct savefpu_ymm {
|
||||||
|
struct __envxmm64 sv_env;
|
||||||
|
struct {
|
||||||
|
struct fpacc87 fp_acc;
|
||||||
|
int8_t fp_pad[6]; /* padding */
|
||||||
|
} sv_fp[8];
|
||||||
|
struct xmmacc sv_xmm[16];
|
||||||
|
uint8_t sv_pad[96];
|
||||||
|
struct savefpu_xstate sv_xstate;
|
||||||
|
} __attribute__ ((aligned(64)));
|
||||||
|
|
||||||
|
#undef __envxmm32
|
||||||
|
#undef __envxmm64
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The hardware default control word for i387's and later coprocessors is
|
||||||
|
* 0x37F, giving:
|
||||||
|
*
|
||||||
|
* round to nearest
|
||||||
|
* 64-bit precision
|
||||||
|
* all exceptions masked.
|
||||||
|
*
|
||||||
|
* FreeBSD/i386 uses 53 bit precision for things like fadd/fsub/fsqrt etc
|
||||||
|
* because of the difference between memory and fpu register stack arguments.
|
||||||
|
* If its using an intermediate fpu register, it has 80/64 bits to work
|
||||||
|
* with. If it uses memory, it has 64/53 bits to work with. However,
|
||||||
|
* gcc is aware of this and goes to a fair bit of trouble to make the
|
||||||
|
* best use of it.
|
||||||
|
*
|
||||||
|
* This is mostly academic for AMD64, because the ABI prefers the use
|
||||||
|
* SSE2 based math. For FreeBSD/amd64, we go with the default settings.
|
||||||
|
*/
|
||||||
|
#define __INITIAL_FPUCW__ 0x037F
|
||||||
|
#define __INITIAL_FPUCW_I386__ 0x127F
|
||||||
|
#define __INITIAL_NPXCW__ __INITIAL_FPUCW_I386__
|
||||||
|
#define __INITIAL_MXCSR__ 0x1F80
|
||||||
|
#define __INITIAL_MXCSR_MASK__ 0xFFBF
|
||||||
|
|
||||||
|
#endif /* !_BSD_FPU_H_ */
|
||||||
@@ -0,0 +1,272 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2003 Peter Wemm.
|
||||||
|
* Copyright (c) 1990 Andrew Moore, Talke Studio
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. Neither the name of the University nor the names of its contributors
|
||||||
|
* may be used to endorse or promote products derived from this software
|
||||||
|
* without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
|
||||||
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||||
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||||
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||||
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||||
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* from: @(#) ieeefp.h 1.0 (Berkeley) 9/23/93
|
||||||
|
* $FreeBSD: src/sys/amd64/include/ieeefp.h,v 1.14 2005/04/12 23:12:00 jhb Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IEEE floating point type and constant definitions.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _BSD_IEEEFP_H_
|
||||||
|
#define _BSD_IEEEFP_H_
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FP rounding modes
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
FP_RN=0, /* round to nearest */
|
||||||
|
FP_RM, /* round down to minus infinity */
|
||||||
|
FP_RP, /* round up to plus infinity */
|
||||||
|
FP_RZ /* truncate */
|
||||||
|
} fp_rnd_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FP precision modes
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
FP_PS=0, /* 24 bit (single-precision) */
|
||||||
|
FP_PRS, /* reserved */
|
||||||
|
FP_PD, /* 53 bit (double-precision) */
|
||||||
|
FP_PE /* 64 bit (extended-precision) */
|
||||||
|
} fp_prec_t;
|
||||||
|
|
||||||
|
#define fp_except_t int
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FP exception masks
|
||||||
|
*/
|
||||||
|
#define FP_X_INV 0x01 /* invalid operation */
|
||||||
|
#define FP_X_DNML 0x02 /* denormal */
|
||||||
|
#define FP_X_DZ 0x04 /* zero divide */
|
||||||
|
#define FP_X_OFL 0x08 /* overflow */
|
||||||
|
#define FP_X_UFL 0x10 /* underflow */
|
||||||
|
#define FP_X_IMP 0x20 /* (im)precision */
|
||||||
|
#define FP_X_STK 0x40 /* stack fault */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FP registers
|
||||||
|
*/
|
||||||
|
#define FP_MSKS_REG 0 /* exception masks */
|
||||||
|
#define FP_PRC_REG 0 /* precision */
|
||||||
|
#define FP_RND_REG 0 /* direction */
|
||||||
|
#define FP_STKY_REG 1 /* sticky flags */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FP register bit field masks
|
||||||
|
*/
|
||||||
|
#define FP_MSKS_FLD 0x3f /* exception masks field */
|
||||||
|
#define FP_PRC_FLD 0x300 /* precision control field */
|
||||||
|
#define FP_RND_FLD 0xc00 /* round control field */
|
||||||
|
#define FP_STKY_FLD 0x3f /* sticky flags field */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SSE mxcsr register bit field masks
|
||||||
|
*/
|
||||||
|
#define SSE_STKY_FLD 0x3f /* exception flags */
|
||||||
|
#define SSE_DAZ_FLD 0x40 /* Denormals are zero */
|
||||||
|
#define SSE_MSKS_FLD 0x1f80 /* exception masks field */
|
||||||
|
#define SSE_RND_FLD 0x6000 /* rounding control */
|
||||||
|
#define SSE_FZ_FLD 0x8000 /* flush to zero on underflow */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FP register bit field offsets
|
||||||
|
*/
|
||||||
|
#define FP_MSKS_OFF 0 /* exception masks offset */
|
||||||
|
#define FP_PRC_OFF 8 /* precision control offset */
|
||||||
|
#define FP_RND_OFF 10 /* round control offset */
|
||||||
|
#define FP_STKY_OFF 0 /* sticky flags offset */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SSE mxcsr register bit field offsets
|
||||||
|
*/
|
||||||
|
#define SSE_STKY_OFF 0 /* exception flags offset */
|
||||||
|
#define SSE_DAZ_OFF 6 /* DAZ exception mask offset */
|
||||||
|
#define SSE_MSKS_OFF 7 /* other exception masks offset */
|
||||||
|
#define SSE_RND_OFF 13 /* rounding control offset */
|
||||||
|
#define SSE_FZ_OFF 15 /* flush to zero offset */
|
||||||
|
|
||||||
|
#if (defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE__)) || defined(_WIN32) \
|
||||||
|
&& !defined(__cplusplus)
|
||||||
|
|
||||||
|
#define __fldenv(addr) __asm __volatile("fldenv %0" : : "m" (*(addr)))
|
||||||
|
#define __fnstenv(addr) __asm __volatile("fnstenv %0" : "=m" (*(addr)))
|
||||||
|
#define __fldcw(addr) __asm __volatile("fldcw %0" : : "m" (*(addr)))
|
||||||
|
#define __fnstcw(addr) __asm __volatile("fnstcw %0" : "=m" (*(addr)))
|
||||||
|
#define __fnstsw(addr) __asm __volatile("fnstsw %0" : "=m" (*(addr)))
|
||||||
|
#define __ldmxcsr(addr) __asm __volatile("ldmxcsr %0" : : "m" (*(addr)))
|
||||||
|
#define __stmxcsr(addr) __asm __volatile("stmxcsr %0" : "=m" (*(addr)))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* General notes about conflicting SSE vs FP status bits.
|
||||||
|
* This code assumes that software will not fiddle with the control
|
||||||
|
* bits of the SSE and x87 in such a way to get them out of sync and
|
||||||
|
* still expect this to work. Break this at your peril.
|
||||||
|
* Because I based this on the i386 port, the x87 state is used for
|
||||||
|
* the fpget*() functions, and is shadowed into the SSE state for
|
||||||
|
* the fpset*() functions. For dual source fpget*() functions, I
|
||||||
|
* merge the two together. I think.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Set rounding control */
|
||||||
|
static __inline__ fp_rnd_t
|
||||||
|
__fpgetround(void)
|
||||||
|
{
|
||||||
|
unsigned short _cw;
|
||||||
|
|
||||||
|
__fnstcw(&_cw);
|
||||||
|
return ((_cw & FP_RND_FLD) >> FP_RND_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ fp_rnd_t
|
||||||
|
__fpsetround(fp_rnd_t _m)
|
||||||
|
{
|
||||||
|
unsigned short _cw;
|
||||||
|
unsigned int _mxcsr;
|
||||||
|
fp_rnd_t _p;
|
||||||
|
|
||||||
|
__fnstcw(&_cw);
|
||||||
|
_p = (_cw & FP_RND_FLD) >> FP_RND_OFF;
|
||||||
|
_cw &= ~FP_RND_FLD;
|
||||||
|
_cw |= (_m << FP_RND_OFF) & FP_RND_FLD;
|
||||||
|
__fldcw(&_cw);
|
||||||
|
__stmxcsr(&_mxcsr);
|
||||||
|
_mxcsr &= ~SSE_RND_FLD;
|
||||||
|
_mxcsr |= (_m << SSE_RND_OFF) & SSE_RND_FLD;
|
||||||
|
__ldmxcsr(&_mxcsr);
|
||||||
|
return (_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set precision for fadd/fsub/fsqrt etc x87 instructions
|
||||||
|
* There is no equivalent SSE mode or control.
|
||||||
|
*/
|
||||||
|
static __inline__ fp_prec_t
|
||||||
|
__fpgetprec(void)
|
||||||
|
{
|
||||||
|
unsigned short _cw;
|
||||||
|
|
||||||
|
__fnstcw(&_cw);
|
||||||
|
return ((_cw & FP_PRC_FLD) >> FP_PRC_OFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ fp_prec_t
|
||||||
|
__fpsetprec(fp_rnd_t _m)
|
||||||
|
{
|
||||||
|
unsigned short _cw;
|
||||||
|
fp_prec_t _p;
|
||||||
|
|
||||||
|
__fnstcw(&_cw);
|
||||||
|
_p = (_cw & FP_PRC_FLD) >> FP_PRC_OFF;
|
||||||
|
_cw &= ~FP_PRC_FLD;
|
||||||
|
_cw |= (_m << FP_PRC_OFF) & FP_PRC_FLD;
|
||||||
|
__fldcw(&_cw);
|
||||||
|
return (_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Look at the exception masks
|
||||||
|
* Note that x87 masks are inverse of the fp*() functions
|
||||||
|
* API. ie: mask = 1 means disable for x87 and SSE, but
|
||||||
|
* for the fp*() api, mask = 1 means enabled.
|
||||||
|
*/
|
||||||
|
static __inline__ fp_except_t
|
||||||
|
__fpgetmask(void)
|
||||||
|
{
|
||||||
|
unsigned short _cw;
|
||||||
|
|
||||||
|
__fnstcw(&_cw);
|
||||||
|
return ((~_cw) & FP_MSKS_FLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
static __inline__ fp_except_t
|
||||||
|
__fpsetmask(fp_except_t _m)
|
||||||
|
{
|
||||||
|
unsigned short _cw;
|
||||||
|
unsigned int _mxcsr;
|
||||||
|
fp_except_t _p;
|
||||||
|
|
||||||
|
__fnstcw(&_cw);
|
||||||
|
_p = (~_cw) & FP_MSKS_FLD;
|
||||||
|
_cw &= ~FP_MSKS_FLD;
|
||||||
|
_cw |= (~_m) & FP_MSKS_FLD;
|
||||||
|
__fldcw(&_cw);
|
||||||
|
__stmxcsr(&_mxcsr);
|
||||||
|
/* XXX should we clear non-ieee SSE_DAZ_FLD and SSE_FZ_FLD ? */
|
||||||
|
_mxcsr &= ~SSE_MSKS_FLD;
|
||||||
|
_mxcsr |= ((~_m) << SSE_MSKS_OFF) & SSE_MSKS_FLD;
|
||||||
|
__ldmxcsr(&_mxcsr);
|
||||||
|
return (_p);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* See which sticky exceptions are pending, and reset them */
|
||||||
|
static __inline__ fp_except_t
|
||||||
|
__fpgetsticky(void)
|
||||||
|
{
|
||||||
|
unsigned short _sw;
|
||||||
|
unsigned int _mxcsr;
|
||||||
|
fp_except_t _ex;
|
||||||
|
|
||||||
|
__fnstsw(&_sw);
|
||||||
|
_ex = _sw & FP_STKY_FLD;
|
||||||
|
__stmxcsr(&_mxcsr);
|
||||||
|
_ex |= _mxcsr & SSE_STKY_FLD;
|
||||||
|
return (_ex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE__ && !__cplusplus */
|
||||||
|
|
||||||
|
#if !defined(__IEEEFP_NOINLINES__) && !defined(__cplusplus) \
|
||||||
|
&& defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE__)
|
||||||
|
|
||||||
|
#define fpgetround() __fpgetround()
|
||||||
|
#define fpsetround(_m) __fpsetround(_m)
|
||||||
|
#define fpgetprec() __fpgetprec()
|
||||||
|
#define fpsetprec(_m) __fpsetprec(_m)
|
||||||
|
#define fpgetmask() __fpgetmask()
|
||||||
|
#define fpsetmask(_m) __fpsetmask(_m)
|
||||||
|
#define fpgetsticky() __fpgetsticky()
|
||||||
|
|
||||||
|
/* Suppress prototypes in the MI header. */
|
||||||
|
#define _IEEEFP_INLINED_ 1
|
||||||
|
|
||||||
|
#else /* !__IEEEFP_NOINLINES__ && !__cplusplus && __GNUCLIKE_ASM
|
||||||
|
&& __CC_SUPPORTS___INLINE__ */
|
||||||
|
|
||||||
|
/* Augment the userland declarations */
|
||||||
|
__BEGIN_DECLS
|
||||||
|
extern fp_prec_t fpgetprec(void);
|
||||||
|
extern fp_prec_t fpsetprec(fp_prec_t);
|
||||||
|
__END_DECLS
|
||||||
|
|
||||||
|
#endif /* !__IEEEFP_NOINLINES__ && !__cplusplus && __GNUCLIKE_ASM
|
||||||
|
&& __CC_SUPPORTS___INLINE__ */
|
||||||
|
|
||||||
|
#endif /* !_BSD_IEEEFP_H_ */
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 1993,94 Winning Strategies, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* 3. All advertising materials mentioning features or use of this software
|
||||||
|
* must display the following acknowledgement:
|
||||||
|
* This product includes software developed by Winning Strategies, Inc.
|
||||||
|
* 4. The name of the author may not be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||||
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||||
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||||
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||||
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||||
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Based on the i387 version written by:
|
||||||
|
* J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amd64/bsd_asm.h>
|
||||||
|
|
||||||
|
ENTRY(fmod)
|
||||||
|
movsd %xmm0,-8(%rsp)
|
||||||
|
movsd %xmm1,-16(%rsp)
|
||||||
|
fldl -16(%rsp)
|
||||||
|
fldl -8(%rsp)
|
||||||
|
1: fprem
|
||||||
|
fstsw %ax
|
||||||
|
testw $0x400,%ax
|
||||||
|
jne 1b
|
||||||
|
fstpl -8(%rsp)
|
||||||
|
movsd -8(%rsp),%xmm0
|
||||||
|
fstp %st
|
||||||
|
ret
|
||||||
|
END(fmod)
|
||||||
|
|
||||||
|
/* Enable stack protection */
|
||||||
|
#if defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user