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 |
@@ -0,0 +1,7 @@
|
|||||||
|
[**.c]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
|
|
||||||
|
[**.yml]
|
||||||
|
indent_size = 4
|
||||||
|
indent_style = space
|
||||||
+11
-1
@@ -1 +1,11 @@
|
|||||||
/target/
|
.idea/
|
||||||
|
prefix/
|
||||||
|
sysroot/
|
||||||
|
**/target/
|
||||||
|
.gdb_history
|
||||||
|
*.patch
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
/.vim
|
||||||
|
.vscode/
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
image: "redoxos/redoxer:latest"
|
||||||
|
|
||||||
|
variables:
|
||||||
|
GIT_SUBMODULE_STRATEGY: recursive
|
||||||
|
|
||||||
|
workflow:
|
||||||
|
rules:
|
||||||
|
- if: '$CI_COMMIT_BRANCH == "master" && $CI_PROJECT_NAMESPACE == "redox-os"'
|
||||||
|
- if: '$CI_MERGE_REQUEST_TARGET_BRANCH_NAME == "master"'
|
||||||
|
|
||||||
|
stages:
|
||||||
|
- build
|
||||||
|
- cross-build
|
||||||
|
- test
|
||||||
|
before_script:
|
||||||
|
cargo install cbindgen
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
stage: build
|
||||||
|
needs: []
|
||||||
|
script:
|
||||||
|
- rustup component add rustfmt-preview
|
||||||
|
- ./fmt.sh -- --check
|
||||||
|
|
||||||
|
linux:
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- ./check.sh --host
|
||||||
|
|
||||||
|
x86_64:
|
||||||
|
stage: build
|
||||||
|
script:
|
||||||
|
- ./check.sh --arch=x86_64
|
||||||
|
|
||||||
|
i586:
|
||||||
|
stage: cross-build
|
||||||
|
script:
|
||||||
|
- ./check.sh --arch=i586
|
||||||
|
|
||||||
|
aarch64:
|
||||||
|
stage: cross-build
|
||||||
|
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
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[submodule "openlibm"]
|
||||||
|
path = openlibm
|
||||||
|
url = https://gitlab.redox-os.org/redox-os/openlibm.git
|
||||||
|
branch = master
|
||||||
|
[submodule "src/dlmalloc-rs"]
|
||||||
|
path = dlmalloc-rs
|
||||||
|
url = https://gitlab.redox-os.org/redox-os/dlmalloc-rs.git
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
language: rust
|
|
||||||
rust:
|
|
||||||
- nightly
|
|
||||||
sudo: false
|
|
||||||
notifications:
|
|
||||||
email: false
|
|
||||||
+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
+481
-394
File diff suppressed because it is too large
Load Diff
+133
-61
@@ -1,76 +1,148 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "userutils"
|
name = "relibc"
|
||||||
version = "0.1.0"
|
version = "0.2.5"
|
||||||
|
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[[bin]]
|
[lib]
|
||||||
name = "id"
|
name = "relibc"
|
||||||
path = "src/bin/id.rs"
|
crate-type = ["staticlib"]
|
||||||
|
|
||||||
[[bin]]
|
[workspace]
|
||||||
name = "getty"
|
members = [
|
||||||
path = "src/bin/getty.rs"
|
"src/crt0",
|
||||||
|
"src/crti",
|
||||||
|
"src/crtn",
|
||||||
|
"redox-rt",
|
||||||
|
"ld_so",
|
||||||
|
"generic-rt",
|
||||||
|
]
|
||||||
|
exclude = ["tests", "dlmalloc-rs"]
|
||||||
|
|
||||||
[[bin]]
|
[workspace.lints.clippy]
|
||||||
name = "groupadd"
|
borrow_as_ptr = "deny"
|
||||||
path = "src/bin/groupadd.rs"
|
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
|
||||||
|
|
||||||
[[bin]]
|
[workspace.lints.rust]
|
||||||
name = "groupdel"
|
dangling_pointers_from_temporaries = "deny"
|
||||||
path = "src/bin/groupdel.rs"
|
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)
|
||||||
|
|
||||||
[[bin]]
|
[lints]
|
||||||
name = "groupmod"
|
workspace = true
|
||||||
path = "src/bin/groupmod.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
[workspace.dependencies]
|
||||||
name = "login"
|
bitflags = "2"
|
||||||
path = "src/bin/login.rs"
|
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"
|
||||||
|
|
||||||
[[bin]]
|
[build-dependencies]
|
||||||
name = "passwd"
|
cc = "1"
|
||||||
path = "src/bin/passwd.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "su"
|
|
||||||
path = "src/bin/su.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "sudo"
|
|
||||||
path = "src/bin/sudo.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "useradd"
|
|
||||||
path = "src/bin/useradd.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "userdel"
|
|
||||||
path = "src/bin/userdel.rs"
|
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "usermod"
|
|
||||||
path = "src/bin/usermod.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = "2.33.0"
|
bitflags.workspace = true
|
||||||
extra = { git = "https://gitlab.redox-os.org/redox-os/libextra.git" }
|
cbitset = "0.2"
|
||||||
orbclient = "0.3.47"
|
posix-regex = { version = "0.1.4", features = ["no_std"] }
|
||||||
plain = "0.2.3"
|
|
||||||
redox_liner = "0.5.2"
|
rand = { version = "0.10", default-features = false }
|
||||||
libredox = { version = "0.1.12", features = ["mkns"] }
|
rand_xorshift = "0.5"
|
||||||
redox_termios = "0.1.3"
|
rand_jitter = "0.6"
|
||||||
redox_event = "0.4.3"
|
|
||||||
redox-scheme = "0.9.0"
|
memchr = { version = "2.2.0", default-features = false }
|
||||||
redox_syscall = "0.7.0"
|
plain.workspace = true
|
||||||
redox_users = "0.4.6"
|
unicode-width = "0.1"
|
||||||
termion = "4"
|
__libc_only_for_layout_checks = { package = "libc", version = "0.2.149", optional = true }
|
||||||
libc = "0.2"
|
md5-crypto = { package = "md-5", version = "0.10.6", default-features = false }
|
||||||
serde = { version = "1.0.203", features = ["derive"] }
|
sha-crypt = { version = "0.5", default-features = false }
|
||||||
toml = "0.8.11"
|
base64ct = { version = "1.6", default-features = false, features = ["alloc"] }
|
||||||
ioslice = "0.6"
|
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]
|
||||||
|
version = "0.36.7"
|
||||||
|
git = "https://gitlab.redox-os.org/andypython/object"
|
||||||
|
default-features = false
|
||||||
|
features = ["elf", "read_core"]
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
|
sc = "0.2.7"
|
||||||
|
|
||||||
[target.'cfg(target_os = "redox")'.dependencies]
|
[target.'cfg(target_os = "redox")'.dependencies]
|
||||||
redox-rt = { git = "https://gitlab.redox-os.org/redox-os/relibc", default-features = false }
|
redox_syscall.workspace = true
|
||||||
|
redox-rt = { path = "redox-rt" }
|
||||||
|
redox-path.workspace = true
|
||||||
|
redox_event = { version = "0.4.6", default-features = false, features = [
|
||||||
|
"redox_syscall",
|
||||||
|
] }
|
||||||
|
ioslice.workspace = true
|
||||||
|
redox-ioctl = { path = "redox-ioctl" }
|
||||||
|
redox_protocols.workspace = true
|
||||||
|
|
||||||
|
[features]
|
||||||
|
# to enable trace level, take out this `no_trace`
|
||||||
|
default = ["check_against_libc_crate", "ld_so_cache", "no_trace"]
|
||||||
|
check_against_libc_crate = ["__libc_only_for_layout_checks"]
|
||||||
|
ld_so_cache = []
|
||||||
|
math_libm = []
|
||||||
|
no_trace = ["log/release_max_level_debug"]
|
||||||
|
# for very verbose activity beyond trace level
|
||||||
|
trace_tls = []
|
||||||
|
|
||||||
|
[profile.dev]
|
||||||
|
panic = "abort"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
panic = "abort"
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
cc-11 = { git = "https://github.com/tea/cc-rs", branch = "riscv-abi-arch-fix", package = "cc" }
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
The MIT License (MIT)
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2016 The Redox developers
|
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
|
||||||
|
|||||||
@@ -0,0 +1,226 @@
|
|||||||
|
include config.mk
|
||||||
|
|
||||||
|
CARGO?=cargo
|
||||||
|
CARGO_TEST?=$(CARGO)
|
||||||
|
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
|
||||||
|
|
||||||
|
export CARGO_TARGET_DIR?=$(shell pwd)/target
|
||||||
|
BUILD?=$(CARGO_TARGET_DIR)/$(TARGET)
|
||||||
|
CARGOFLAGS+=--target=$(TARGET)
|
||||||
|
EXCEPT_MATH=-not -name "math"
|
||||||
|
FEATURE_MATH=
|
||||||
|
ifneq ($(USE_RUST_LIBM),)
|
||||||
|
FEATURE_MATH=--features math_libm
|
||||||
|
EXCEPT_MATH=
|
||||||
|
endif
|
||||||
|
|
||||||
|
TARGET_HEADERS?=$(BUILD)/include
|
||||||
|
export CFLAGS=-I$(TARGET_HEADERS)
|
||||||
|
|
||||||
|
PROFILE?=release
|
||||||
|
|
||||||
|
HEADERS_UNPARSED=$(shell find src/header -mindepth 1 -maxdepth 1 -type d -not -name "_*" $(EXCEPT_MATH) -printf "%f\n")
|
||||||
|
HEADERS_DEPS=$(shell find src/header -type f \( -name "cbindgen.toml" -o -name "*.rs" \))
|
||||||
|
#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
|
||||||
|
@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:
|
||||||
|
$(CARGO) clean
|
||||||
|
$(MAKE) -C tests clean
|
||||||
|
rm -rf sysroot
|
||||||
|
|
||||||
|
check:
|
||||||
|
$(CARGO) check
|
||||||
|
|
||||||
|
fmt:
|
||||||
|
./fmt.sh
|
||||||
|
|
||||||
|
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,24 +1,173 @@
|
|||||||
# Redox OS user and group utilities.
|
# Redox C Library (relibc)
|
||||||
|
|
||||||
The `userutils` crate contains the utilities for dealing with users and groups in Redox OS.
|
relibc is a portable C standard library written in Rust and is under heavy development, this library contain the following items:
|
||||||
They are heavily influenced by UNIX and are, when needed, tailored to specific Redox use cases.
|
|
||||||
|
|
||||||
These implementations strive to be as simple as possible drawing particular
|
- C, Linux, BSD functions and extensions
|
||||||
inspiration by BSD systems. They are indeed small, by choice.
|
- POSIX compatibility layer
|
||||||
|
- Interfaces for system components
|
||||||
|
|
||||||
[](https://travis-ci.org/redox-os/userutils)
|
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.
|
||||||
|
|
||||||
**Currently included:**
|
Currently Redox and Linux are supported.
|
||||||
|
|
||||||
- `getty`: Used by `init(8)` to open and initialize the TTY line, read a login name and invoke `login(1)`.
|
## `redox-rt`
|
||||||
- `id`: Displays user identity.
|
|
||||||
- `login`: Allows users to login into the system
|
`redox-rt` is a runtime library that provides much of the code that enables POSIX on Redox, like `fork`, `exec`, signal handling, etc.
|
||||||
- `passwd`: Allows users to modify their passwords.
|
Relibc uses it as backend in `src/platform/redox`, and it's intended to eventually be usable independently, without relibc.
|
||||||
- `su`: Allows users to substitute identity.
|
|
||||||
- `sudo`: Enables users to execute a command as another user.
|
## Repository Layout
|
||||||
- `useradd`: Add a user
|
|
||||||
- `usermod`: Modify user information
|
- `include` - Header files (mostly macros and variadic functions `cbindgen` can't generate)
|
||||||
- `userdel`: Delete a user
|
- `src` - Source files
|
||||||
- `groupadd`: Add a user group
|
- `src/c` - C code
|
||||||
- `groupmod`: Modify group information
|
- `src/crt0` - Runtime code
|
||||||
- `groupdel`: Remove a user group
|
- `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
|
||||||
|
git clone --recursive https://gitlab.redox-os.org/redox-os/relibc
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build Instructions
|
||||||
|
|
||||||
|
To build relibc out of the Redox build system, do the following steps:
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
- Install `cbindgen`
|
||||||
|
|
||||||
|
```sh
|
||||||
|
cargo install cbindgen
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Install the `expect` tool
|
||||||
|
|
||||||
|
- Debian, Ubuntu and PopOS:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo apt install expect
|
||||||
|
```
|
||||||
|
|
||||||
|
- Fedora:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo dnf install expect
|
||||||
|
```
|
||||||
|
|
||||||
|
- Arch Linux:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
sudo pacman -S expect
|
||||||
|
```
|
||||||
|
|
||||||
|
### Build Relibc
|
||||||
|
|
||||||
|
To build the relibc library objects, run the following command:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make all
|
||||||
|
```
|
||||||
|
|
||||||
|
- Clean old library objects and tests
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make clean
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build relibc inside the Redox build system
|
||||||
|
|
||||||
|
Inside of your Redox build system, run:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
make prefix
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to rebuild `relibc` for testing a Cookbook recipe, run:
|
||||||
|
|
||||||
|
```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_
|
||||||
|
|
||||||
|
This project is funded through [NGI Zero Core](https://nlnet.nl/core), a fund established by [NLnet](https://nlnet.nl) with financial support from the European Commission's [Next Generation Internet](https://ngi.eu) program. Learn more at the [NLnet project page](https://nlnet.nl/project/RedoxOS-Signals).
|
||||||
|
|
||||||
|
[<img src="https://nlnet.nl/logo/banner.png" alt="NLnet foundation logo" width="20%" />](https://nlnet.nl)
|
||||||
|
[<img src="https://nlnet.nl/image/logos/NGI0_tag.svg" alt="NGI Zero Logo" width="20%" />](https://nlnet.nl/core)
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
extern crate cc;
|
||||||
|
|
||||||
|
use std::{env, fs};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let _crate_dir = env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set");
|
||||||
|
let target = env::var("TARGET").unwrap();
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=src/c");
|
||||||
|
|
||||||
|
let mut cc_builder = &mut cc::Build::new();
|
||||||
|
|
||||||
|
cc_builder = cc_builder.flag("-nostdinc").flag("-nostdlib");
|
||||||
|
|
||||||
|
if target.starts_with("aarch64") {
|
||||||
|
cc_builder = cc_builder.flag("-mno-outline-atomics")
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
@@ -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
|
||||||
+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)
|
||||||
|
}
|
||||||
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
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
/*
|
||||||
|
* Based on the i387 version written by J.T. Conklin <jtc@netbsd.org>.
|
||||||
|
* Public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amd64/bsd_asm.h>
|
||||||
|
|
||||||
|
ENTRY(fmodf)
|
||||||
|
movss %xmm0,-4(%rsp)
|
||||||
|
movss %xmm1,-8(%rsp)
|
||||||
|
flds -8(%rsp)
|
||||||
|
flds -4(%rsp)
|
||||||
|
1: fprem
|
||||||
|
fstsw %ax
|
||||||
|
testw $0x400,%ax
|
||||||
|
jne 1b
|
||||||
|
fstps -4(%rsp)
|
||||||
|
movss -4(%rsp),%xmm0
|
||||||
|
fstp %st
|
||||||
|
ret
|
||||||
|
END(fmodf)
|
||||||
|
|
||||||
|
/* Enable stack protection */
|
||||||
|
#if defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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(fmodl)
|
||||||
|
fldt 24(%rsp)
|
||||||
|
fldt 8(%rsp)
|
||||||
|
1: fprem
|
||||||
|
fstsw %ax
|
||||||
|
testw $0x400,%ax
|
||||||
|
jne 1b
|
||||||
|
fstp %st(1)
|
||||||
|
ret
|
||||||
|
END(fmodl)
|
||||||
|
|
||||||
|
/* Enable stack protection */
|
||||||
|
#if defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Based on the i387 version written by:
|
||||||
|
* J.T. Conklin (jtc@netbsd.org)
|
||||||
|
* Public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amd64/bsd_asm.h>
|
||||||
|
|
||||||
|
//RCSID("from: FreeBSD: src/lib/msun/i387/e_remainder.S,v 1.8 2005/02/04 14:08:32 das Exp")
|
||||||
|
//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_remainder.S,v 1.2 2011/01/07 16:13:12 kib Exp $")
|
||||||
|
|
||||||
|
ENTRY(remainder)
|
||||||
|
movsd %xmm0,-8(%rsp)
|
||||||
|
movsd %xmm1,-16(%rsp)
|
||||||
|
fldl -16(%rsp)
|
||||||
|
fldl -8(%rsp)
|
||||||
|
1: fprem1
|
||||||
|
fstsw %ax
|
||||||
|
testw $0x400,%ax
|
||||||
|
jne 1b
|
||||||
|
fstpl -8(%rsp)
|
||||||
|
movsd -8(%rsp),%xmm0
|
||||||
|
fstp %st
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
/* Enable stack protection */
|
||||||
|
#if defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Based on the i387 version written by J.T. Conklin <jtc@netbsd.org>.
|
||||||
|
* Public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amd64/bsd_asm.h>
|
||||||
|
|
||||||
|
//RCSID("from: $NetBSD: e_remainderf.S,v 1.2 1995/05/08 23:49:47 jtc Exp $")
|
||||||
|
//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_remainderf.S,v 1.2 2011/01/07 16:13:12 kib Exp $")
|
||||||
|
|
||||||
|
ENTRY(remainderf)
|
||||||
|
movss %xmm0,-4(%rsp)
|
||||||
|
movss %xmm1,-8(%rsp)
|
||||||
|
flds -8(%rsp)
|
||||||
|
flds -4(%rsp)
|
||||||
|
1: fprem1
|
||||||
|
fstsw %ax
|
||||||
|
testw $0x400,%ax
|
||||||
|
jne 1b
|
||||||
|
fstps -4(%rsp)
|
||||||
|
movss -4(%rsp),%xmm0
|
||||||
|
fstp %st
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
/* Enable stack protection */
|
||||||
|
#if defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Based on the i387 version written by:
|
||||||
|
* J.T. Conklin (jtc@netbsd.org)
|
||||||
|
* Public domain.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amd64/bsd_asm.h>
|
||||||
|
|
||||||
|
//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_remainderl.S,v 1.2 2011/01/07 16:13:12 kib Exp $")
|
||||||
|
|
||||||
|
ENTRY(remainderl)
|
||||||
|
#ifndef _WIN64
|
||||||
|
fldt 24(%rsp)
|
||||||
|
fldt 8(%rsp)
|
||||||
|
#else
|
||||||
|
fldt (%r8)
|
||||||
|
fldt (%rdx)
|
||||||
|
#endif
|
||||||
|
1: fprem1
|
||||||
|
fstsw %ax
|
||||||
|
testw $0x400,%ax
|
||||||
|
jne 1b
|
||||||
|
fstp %st(1)
|
||||||
|
#ifdef _WIN64
|
||||||
|
mov %rcx,%rax
|
||||||
|
movq $0x0,0x8(%rcx)
|
||||||
|
fstpt (%rcx)
|
||||||
|
#endif
|
||||||
|
ret
|
||||||
|
|
||||||
|
|
||||||
|
/* Enable stack protection */
|
||||||
|
#if defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2005 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amd64/bsd_asm.h>
|
||||||
|
//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_sqrt.S,v 1.4 2011/01/07 16:13:12 kib Exp $")
|
||||||
|
|
||||||
|
ENTRY(sqrt)
|
||||||
|
sqrtsd %xmm0, %xmm0
|
||||||
|
ret
|
||||||
|
END(sqrt)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Enable stack protection */
|
||||||
|
#if defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2005 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amd64/bsd_asm.h>
|
||||||
|
//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_sqrtf.S,v 1.3 2011/01/07 16:13:12 kib Exp $")
|
||||||
|
|
||||||
|
ENTRY(sqrtf)
|
||||||
|
sqrtss %xmm0, %xmm0
|
||||||
|
ret
|
||||||
|
END(sqrtf)
|
||||||
|
|
||||||
|
|
||||||
|
/* Enable stack protection */
|
||||||
|
#if defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2008 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <amd64/bsd_asm.h>
|
||||||
|
//__FBSDID("$FreeBSD: src/lib/msun/amd64/e_sqrtl.S,v 1.2 2011/01/07 16:13:12 kib Exp $")
|
||||||
|
|
||||||
|
ENTRY(sqrtl)
|
||||||
|
#ifndef _WIN64
|
||||||
|
fldt 8(%rsp)
|
||||||
|
fsqrt
|
||||||
|
#else
|
||||||
|
fldt (%rdx)
|
||||||
|
fsqrt
|
||||||
|
mov %rcx,%rax
|
||||||
|
movq $0x0,0x8(%rcx)
|
||||||
|
fstpt (%rcx)
|
||||||
|
#endif
|
||||||
|
ret
|
||||||
|
|
||||||
|
/* Enable stack protection */
|
||||||
|
#if defined(__ELF__)
|
||||||
|
.section .note.GNU-stack,"",%progbits
|
||||||
|
#endif
|
||||||
@@ -0,0 +1,162 @@
|
|||||||
|
/*-
|
||||||
|
* Copyright (c) 2004-2005 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/amd64/fenv.c,v 1.8 2011/10/21 06:25:31 das Exp $
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "bsd_fpu.h"
|
||||||
|
#include "math_private.h"
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
#define __fenv_static OLM_DLLEXPORT
|
||||||
|
#endif
|
||||||
|
#include <openlibm_fenv.h>
|
||||||
|
|
||||||
|
#ifdef __GNUC_GNU_INLINE__
|
||||||
|
#error "This file must be compiled with C99 'inline' semantics"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
const fenv_t __fe_dfl_env = {
|
||||||
|
{ 0xffff0000 | __INITIAL_FPUCW__,
|
||||||
|
0xffff0000,
|
||||||
|
0xffffffff,
|
||||||
|
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }
|
||||||
|
},
|
||||||
|
__INITIAL_MXCSR__
|
||||||
|
};
|
||||||
|
|
||||||
|
extern inline OLM_DLLEXPORT int feclearexcept(int __excepts);
|
||||||
|
extern inline OLM_DLLEXPORT int fegetexceptflag(fexcept_t *__flagp, int __excepts);
|
||||||
|
|
||||||
|
OLM_DLLEXPORT int
|
||||||
|
fesetexceptflag(const fexcept_t *flagp, int excepts)
|
||||||
|
{
|
||||||
|
fenv_t env;
|
||||||
|
|
||||||
|
__fnstenv(&env.__x87);
|
||||||
|
env.__x87.__status &= ~excepts;
|
||||||
|
env.__x87.__status |= *flagp & excepts;
|
||||||
|
__fldenv(env.__x87);
|
||||||
|
|
||||||
|
__stmxcsr(&env.__mxcsr);
|
||||||
|
env.__mxcsr &= ~excepts;
|
||||||
|
env.__mxcsr |= *flagp & excepts;
|
||||||
|
__ldmxcsr(env.__mxcsr);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
OLM_DLLEXPORT int
|
||||||
|
feraiseexcept(int excepts)
|
||||||
|
{
|
||||||
|
fexcept_t ex = excepts;
|
||||||
|
|
||||||
|
fesetexceptflag(&ex, excepts);
|
||||||
|
__fwait();
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline OLM_DLLEXPORT int fetestexcept(int __excepts);
|
||||||
|
extern inline OLM_DLLEXPORT int fegetround(void);
|
||||||
|
extern inline OLM_DLLEXPORT int fesetround(int __round);
|
||||||
|
|
||||||
|
OLM_DLLEXPORT int
|
||||||
|
fegetenv(fenv_t *envp)
|
||||||
|
{
|
||||||
|
|
||||||
|
__fnstenv(&envp->__x87);
|
||||||
|
__stmxcsr(&envp->__mxcsr);
|
||||||
|
/*
|
||||||
|
* fnstenv masks all exceptions, so we need to restore the
|
||||||
|
* control word to avoid this side effect.
|
||||||
|
*/
|
||||||
|
__fldcw(envp->__x87.__control);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
OLM_DLLEXPORT int
|
||||||
|
feholdexcept(fenv_t *envp)
|
||||||
|
{
|
||||||
|
uint32_t mxcsr;
|
||||||
|
|
||||||
|
__stmxcsr(&mxcsr);
|
||||||
|
__fnstenv(&envp->__x87);
|
||||||
|
__fnclex();
|
||||||
|
envp->__mxcsr = mxcsr;
|
||||||
|
mxcsr &= ~FE_ALL_EXCEPT;
|
||||||
|
mxcsr |= FE_ALL_EXCEPT << _SSE_EMASK_SHIFT;
|
||||||
|
__ldmxcsr(mxcsr);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern inline OLM_DLLEXPORT int fesetenv(const fenv_t *__envp);
|
||||||
|
|
||||||
|
OLM_DLLEXPORT int
|
||||||
|
feupdateenv(const fenv_t *envp)
|
||||||
|
{
|
||||||
|
uint32_t mxcsr;
|
||||||
|
uint16_t status;
|
||||||
|
|
||||||
|
__fnstsw(&status);
|
||||||
|
__stmxcsr(&mxcsr);
|
||||||
|
fesetenv(envp);
|
||||||
|
feraiseexcept((mxcsr | status) & FE_ALL_EXCEPT);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
feenableexcept(int mask)
|
||||||
|
{
|
||||||
|
uint32_t mxcsr, omask;
|
||||||
|
uint16_t control;
|
||||||
|
|
||||||
|
mask &= FE_ALL_EXCEPT;
|
||||||
|
__fnstcw(&control);
|
||||||
|
__stmxcsr(&mxcsr);
|
||||||
|
omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
|
||||||
|
control &= ~mask;
|
||||||
|
__fldcw(control);
|
||||||
|
mxcsr &= ~(mask << _SSE_EMASK_SHIFT);
|
||||||
|
__ldmxcsr(mxcsr);
|
||||||
|
return (omask);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
fedisableexcept(int mask)
|
||||||
|
{
|
||||||
|
uint32_t mxcsr, omask;
|
||||||
|
uint16_t control;
|
||||||
|
|
||||||
|
mask &= FE_ALL_EXCEPT;
|
||||||
|
__fnstcw(&control);
|
||||||
|
__stmxcsr(&mxcsr);
|
||||||
|
omask = ~(control | mxcsr >> _SSE_EMASK_SHIFT) & FE_ALL_EXCEPT;
|
||||||
|
control |= mask;
|
||||||
|
__fldcw(control);
|
||||||
|
mxcsr |= mask << _SSE_EMASK_SHIFT;
|
||||||
|
__ldmxcsr(mxcsr);
|
||||||
|
return (omask);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user