Add ld_so executable
This commit is contained in:
Generated
+96
@@ -93,6 +93,16 @@ name = "fuchsia-cprng"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "goblin"
|
||||
version = "0.0.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.3"
|
||||
@@ -106,6 +116,10 @@ dependencies = [
|
||||
"spin 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ld_so"
|
||||
version = "0.1.0"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.51"
|
||||
@@ -132,6 +146,11 @@ name = "num-traits"
|
||||
version = "0.2.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "plain"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "posix-regex"
|
||||
version = "0.1.0"
|
||||
@@ -144,11 +163,27 @@ dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "0.4.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.3.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "0.6.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ralloc"
|
||||
version = "1.0.0"
|
||||
@@ -226,6 +261,7 @@ dependencies = [
|
||||
"cbitset 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"core_io 0.1.20181107",
|
||||
"goblin 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"posix-regex 0.1.0",
|
||||
"ralloc 1.0.0",
|
||||
@@ -252,6 +288,14 @@ dependencies = [
|
||||
"semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "0.2.7"
|
||||
@@ -262,11 +306,43 @@ name = "sc"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "scroll"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scroll_derive"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.1.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "0.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver-parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.90"
|
||||
@@ -342,6 +418,16 @@ dependencies = [
|
||||
"unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "0.15.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "synom"
|
||||
version = "0.11.3"
|
||||
@@ -452,14 +538,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4"
|
||||
"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
|
||||
"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba"
|
||||
"checksum goblin 0.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6a4013e9182f2345c6b7829b9ef6e670bce0dfca12c6f974457ed2160c2c7fe9"
|
||||
"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
|
||||
"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1"
|
||||
"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917"
|
||||
"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b"
|
||||
"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6"
|
||||
"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
|
||||
"checksum plain 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6"
|
||||
"checksum proc-macro2 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cd07deb3c6d1d9ff827999c7f9b04cdfd66b1b17ae508e14fe47b620f2282ae0"
|
||||
"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
|
||||
"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293"
|
||||
"checksum rand 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c618c47cd3ebd209790115ab837de41425723956ad3ce2e6a7f09890947cacb9"
|
||||
"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b"
|
||||
@@ -469,9 +559,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76"
|
||||
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
|
||||
"checksum rustc_version 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c5f5376ea5e30ce23c03eb77cbe4962b988deead10910c372b226388b594c084"
|
||||
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
|
||||
"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
|
||||
"checksum sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4ebbb026ba4a707c25caec2db5ef59ad8b41f7ad77cad06257e06229c891f376"
|
||||
"checksum scroll 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2f84d114ef17fd144153d608fba7c446b0145d038985e7a8cc5d08bb0ce20383"
|
||||
"checksum scroll_derive 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1aa96c45e7f5a91cb7fabe7b279f02fea7126239fc40b732316e8b6a2d0fcb"
|
||||
"checksum semver 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "d4f410fedcf71af0345d7607d246e7ad15faaadd49d240ee3b24e5dc21a820ac"
|
||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||
"checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4"
|
||||
"checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788"
|
||||
"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab"
|
||||
@@ -481,6 +576,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum standalone-syn 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "115808f5187c07c23cb93eee49d542fae54c6e8285d3a24c6ff683fcde9243db"
|
||||
"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
|
||||
"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad"
|
||||
"checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2"
|
||||
"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6"
|
||||
"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8"
|
||||
"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
|
||||
|
||||
+6
-1
@@ -8,7 +8,7 @@ name = "relibc"
|
||||
crate-type = ["staticlib"]
|
||||
|
||||
[workspace]
|
||||
members = ["src/crt0", "src/crti", "src/crtn", "cbindgen"]
|
||||
members = ["src/crt0", "src/crti", "src/crtn", "src/ld_so", "cbindgen"]
|
||||
exclude = ["core_io", "ralloc"]
|
||||
|
||||
[build-dependencies]
|
||||
@@ -22,6 +22,11 @@ posix-regex = { path = "posix-regex", features = ["no_std"] }
|
||||
rand = { version = "0.5.5", default-features = false }
|
||||
va_list = { path = "va_list", features = ["no_std"] }
|
||||
|
||||
[dependencies.goblin]
|
||||
version = "0.0.21"
|
||||
default-features = false
|
||||
features = ["elf32", "elf64", "endian_fd"]
|
||||
|
||||
[dependencies.ralloc]
|
||||
path = "ralloc"
|
||||
default-features = false
|
||||
|
||||
@@ -79,7 +79,9 @@ sysroot: all
|
||||
test: sysroot
|
||||
$(MAKE) -C tests run
|
||||
|
||||
$(BUILD)/release/libc.a: $(BUILD)/release/librelibc.a $(BUILD)/pthreads-emb/libpthread.a $(BUILD)/openlibm/libopenlibm.a
|
||||
# Debug targets
|
||||
|
||||
$(BUILD)/debug/libc.a: $(BUILD)/debug/librelibc.a $(BUILD)/pthreads-emb/libpthread.a $(BUILD)/openlibm/libopenlibm.a
|
||||
echo "create $@" > "$@.mri"
|
||||
for lib in $^; do\
|
||||
echo "addlib $$lib" >> "$@.mri"; \
|
||||
@@ -88,13 +90,18 @@ $(BUILD)/release/libc.a: $(BUILD)/release/librelibc.a $(BUILD)/pthreads-emb/libp
|
||||
echo "end" >> "$@.mri"
|
||||
ar -M < "$@.mri"
|
||||
|
||||
$(BUILD)/release/libc.so: $(BUILD)/release/librelibc.patched.a $(BUILD)/pthreads-emb/libpthread.a $(BUILD)/openlibm/libopenlibm.a
|
||||
$(BUILD)/debug/libc.so: $(BUILD)/debug/librelibc.patched.a $(BUILD)/pthreads-emb/libpthread.a $(BUILD)/openlibm/libopenlibm.a
|
||||
$(CC) -nostdlib -shared -Wl,--whole-archive $^ -Wl,--no-whole-archive -o $@
|
||||
|
||||
$(BUILD)/debug/librelibc.a: $(SRC)
|
||||
$(CARGO) rustc $(CARGOFLAGS) -- --emit link=$@ $(RUSTCFLAGS)
|
||||
touch $@
|
||||
|
||||
$(BUILD)/debug/librelibc.patched.a: $(BUILD)/debug/librelibc.a
|
||||
# Patch out clzsi2.o from libgcc
|
||||
cp $< $@
|
||||
ar d $@ clzsi2.o
|
||||
|
||||
$(BUILD)/debug/crt0.o: $(SRC)
|
||||
CARGO_INCREMENTAL=0 $(CARGO) rustc --manifest-path src/crt0/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||
touch $@
|
||||
@@ -107,6 +114,27 @@ $(BUILD)/debug/crtn.o: $(SRC)
|
||||
CARGO_INCREMENTAL=0 $(CARGO) rustc --manifest-path src/crtn/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||
touch $@
|
||||
|
||||
$(BUILD)/debug/ld_so.o: $(SRC)
|
||||
CARGO_INCREMENTAL=0 $(CARGO) rustc --manifest-path src/ld_so/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||
touch $@
|
||||
|
||||
$(BUILD)/debug/ld_so: $(BUILD)/debug/ld_so.o $(BUILD)/debug/crti.o $(BUILD)/debug/libc.a $(BUILD)/debug/crtn.o
|
||||
$(LD) $^ -o $@
|
||||
|
||||
# Release targets
|
||||
|
||||
$(BUILD)/release/libc.a: $(BUILD)/release/librelibc.a $(BUILD)/pthreads-emb/libpthread.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"
|
||||
|
||||
$(BUILD)/release/libc.so: $(BUILD)/release/librelibc.patched.a $(BUILD)/pthreads-emb/libpthread.a $(BUILD)/openlibm/libopenlibm.a
|
||||
$(CC) -nostdlib -shared -Wl,--whole-archive $^ -Wl,--no-whole-archive -o $@
|
||||
|
||||
$(BUILD)/release/librelibc.a: $(SRC)
|
||||
$(CARGO) rustc --release $(CARGOFLAGS) -- --emit link=$@ $(RUSTCFLAGS)
|
||||
touch $@
|
||||
@@ -128,6 +156,15 @@ $(BUILD)/release/crtn.o: $(SRC)
|
||||
CARGO_INCREMENTAL=0 $(CARGO) rustc --release --manifest-path src/crtn/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||
touch $@
|
||||
|
||||
$(BUILD)/release/ld_so.o: $(SRC)
|
||||
CARGO_INCREMENTAL=0 $(CARGO) rustc --release --manifest-path src/ld_so/Cargo.toml $(CARGOFLAGS) -- --emit obj=$@ -C panic=abort $(RUSTCFLAGS)
|
||||
touch $@
|
||||
|
||||
$(BUILD)/release/ld_so: $(BUILD)/release/ld_so.o $(BUILD)/release/crti.o $(BUILD)/release/libc.a $(BUILD)/release/crtn.o
|
||||
$(LD) $^ -o $@
|
||||
|
||||
# Other targets
|
||||
|
||||
$(BUILD)/include: $(SRC)
|
||||
rm -rf $@ $@.partial
|
||||
mkdir -p $@.partial
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//! sys/auxv.h implementation
|
||||
|
||||
use platform::types::*;
|
||||
use platform::{Pal, Sys};
|
||||
|
||||
pub const AT_HWCAP: usize = 16;
|
||||
|
||||
|
||||
@@ -679,8 +679,6 @@ pub extern "C" fn vfork() -> pid_t {
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn write(fildes: c_int, buf: *const c_void, nbyte: size_t) -> ssize_t {
|
||||
use core::slice;
|
||||
|
||||
let buf = unsafe { slice::from_raw_parts(buf as *const u8, nbyte as usize) };
|
||||
Sys::write(fildes, buf)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
[package]
|
||||
name = "ld_so"
|
||||
version = "0.1.0"
|
||||
authors = ["Jeremy Soller <jackpot51@gmail.com>"]
|
||||
|
||||
[lib]
|
||||
name = "ld_so"
|
||||
crate-type = ["staticlib"]
|
||||
@@ -0,0 +1,355 @@
|
||||
use alloc::boxed::Box;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec::Vec;
|
||||
use core::{ptr, slice};
|
||||
use goblin::elf::{Elf, program_header, reloc, sym};
|
||||
use goblin::error::{Error, Result};
|
||||
|
||||
use c_str::CString;
|
||||
use fs::File;
|
||||
use header::{fcntl, sys_mman, unistd};
|
||||
use io::Read;
|
||||
use platform::types::c_void;
|
||||
|
||||
const PAGE_SIZE: usize = 4096;
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
const PATH_SEP: char = ';';
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
const PATH_SEP: char = ':';
|
||||
|
||||
pub struct Linker {
|
||||
library_path: String,
|
||||
objects: BTreeMap<String, Box<[u8]>>
|
||||
}
|
||||
|
||||
impl Linker {
|
||||
pub fn new(library_path: &str) -> Self {
|
||||
Self {
|
||||
library_path: library_path.to_string(),
|
||||
objects: BTreeMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn load(&mut self, name: &str, path: &str) -> Result<()> {
|
||||
println!("load {}: {}", name, path);
|
||||
|
||||
let mut data = Vec::new();
|
||||
|
||||
let path_c = CString::new(path).map_err(|err| Error::Malformed(
|
||||
format!("invalid path '{}': {}", path, err)
|
||||
))?;
|
||||
|
||||
{
|
||||
let flags = fcntl::O_RDONLY | fcntl::O_CLOEXEC;
|
||||
let mut file = File::open(&path_c, flags).map_err(|err| Error::Malformed(
|
||||
format!("failed to open '{}': {}", path, err)
|
||||
))?;
|
||||
|
||||
file.read_to_end(&mut data).map_err(|err| Error::Malformed(
|
||||
format!("failed to read '{}': {}", path, err)
|
||||
))?;
|
||||
}
|
||||
|
||||
self.load_data(name, data.into_boxed_slice())
|
||||
}
|
||||
|
||||
pub fn load_data(&mut self, name: &str, data: Box<[u8]>) -> Result<()> {
|
||||
//TODO: Prevent failures due to recursion
|
||||
{
|
||||
let elf = Elf::parse(&data)?;
|
||||
//println!("{:#?}", elf);
|
||||
|
||||
for library in elf.libraries.iter() {
|
||||
if ! self.objects.contains_key(&library.to_string()) {
|
||||
self.load_library(library)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.objects.insert(name.to_string(), data);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn load_library(&mut self, name: &str) -> Result<()> {
|
||||
if name.contains('/') {
|
||||
self.load(name, name)
|
||||
} else {
|
||||
let library_path = self.library_path.clone();
|
||||
for part in library_path.split(PATH_SEP) {
|
||||
let path = if part.is_empty() {
|
||||
format!("./{}", name)
|
||||
} else {
|
||||
format!("{}/{}", part, name)
|
||||
};
|
||||
|
||||
println!("check {}", path);
|
||||
|
||||
let access = unsafe {
|
||||
let path_c = CString::new(path.as_bytes()).map_err(|err| Error::Malformed(
|
||||
format!("invalid path '{}': {}", path, err)
|
||||
))?;
|
||||
|
||||
// TODO: Use R_OK | X_OK
|
||||
unistd::access(path_c.as_ptr(), unistd::F_OK) == 0
|
||||
};
|
||||
|
||||
if access {
|
||||
self.load(name, &path)?;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::Malformed(
|
||||
format!("failed to locate '{}'", name)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn link(&mut self, primary: &str) -> Result<usize> {
|
||||
let elfs = {
|
||||
let mut elfs = BTreeMap::new();
|
||||
for (name, data) in self.objects.iter() {
|
||||
elfs.insert(name.as_str(), Elf::parse(&data)?);
|
||||
}
|
||||
elfs
|
||||
};
|
||||
|
||||
// Load all ELF files into memory and find all globals
|
||||
let mut mmaps = BTreeMap::new();
|
||||
let mut globals = BTreeMap::new();
|
||||
for (elf_name, elf) in elfs.iter() {
|
||||
println!("load {}", elf_name);
|
||||
|
||||
let object = match self.objects.get(*elf_name) {
|
||||
Some(some) => some,
|
||||
None => continue,
|
||||
};
|
||||
|
||||
// Calculate virtual memory bounds
|
||||
let bounds = {
|
||||
let mut bounds_opt: Option<(usize, usize)> = None;
|
||||
for ph in elf.program_headers.iter() {
|
||||
match ph.p_type {
|
||||
program_header::PT_LOAD => {
|
||||
let voff = ph.p_vaddr as usize % PAGE_SIZE;
|
||||
let vaddr = ph.p_vaddr as usize - voff;
|
||||
let vsize = ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
|
||||
|
||||
println!(" load {:#x}, {:#x}: {:x?}", vaddr, vsize, ph);
|
||||
|
||||
if let Some(ref mut bounds) = bounds_opt {
|
||||
if vaddr < bounds.0 {
|
||||
bounds.0 = vaddr;
|
||||
}
|
||||
if vaddr + vsize > bounds.1 {
|
||||
bounds.1 = vaddr + vsize;
|
||||
}
|
||||
} else {
|
||||
bounds_opt = Some((vaddr, vaddr + vsize));
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
match bounds_opt {
|
||||
Some(some) => some,
|
||||
None => continue,
|
||||
}
|
||||
};
|
||||
println!(" bounds {:#x}, {:#x}", bounds.0, bounds.1);
|
||||
|
||||
// Allocate memory
|
||||
let mmap = unsafe {
|
||||
let size = bounds.1 /* - bounds.0 */;
|
||||
let ptr = sys_mman::mmap(
|
||||
ptr::null_mut(),
|
||||
size,
|
||||
//TODO: Make it possible to not specify PROT_EXEC on Redox
|
||||
sys_mman::PROT_READ | sys_mman::PROT_WRITE,
|
||||
sys_mman::MAP_ANONYMOUS | sys_mman::MAP_PRIVATE,
|
||||
-1,
|
||||
0
|
||||
);
|
||||
if ptr as usize == !0 /* MAP_FAILED */ {
|
||||
return Err(Error::Malformed(
|
||||
format!("failed to map {}", elf_name)
|
||||
));
|
||||
}
|
||||
slice::from_raw_parts_mut(ptr as *mut u8, size)
|
||||
};
|
||||
println!(" mmap {:p}, {:#x}", mmap.as_mut_ptr(), mmap.len());
|
||||
|
||||
// Locate all globals
|
||||
for sym in elf.dynsyms.iter() {
|
||||
if sym.st_bind() == sym::STB_GLOBAL && sym.st_value != 0 {
|
||||
if let Some(name_res) = elf.dynstrtab.get(sym.st_name) {
|
||||
let name = name_res?;
|
||||
let value = mmap.as_ptr() as usize + sym.st_value as usize;
|
||||
println!(" global {}: {:x?} = {:#x}", name, sym, value);
|
||||
globals.insert(name, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copy data
|
||||
for ph in elf.program_headers.iter() {
|
||||
match ph.p_type {
|
||||
program_header::PT_LOAD => {
|
||||
let voff = ph.p_vaddr as usize % PAGE_SIZE;
|
||||
let vaddr = ph.p_vaddr as usize - voff;
|
||||
let vsize = ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
|
||||
|
||||
// Copy data
|
||||
let obj_data = {
|
||||
let range = ph.file_range();
|
||||
match object.get(range.clone()) {
|
||||
Some(some) => some,
|
||||
None => return Err(Error::Malformed(
|
||||
format!("failed to read {:?}", range)
|
||||
)),
|
||||
}
|
||||
};
|
||||
|
||||
let mmap_data = {
|
||||
let range = ph.p_vaddr as usize..ph.p_vaddr as usize + obj_data.len();
|
||||
match mmap.get_mut(range.clone()) {
|
||||
Some(some) => some,
|
||||
None => return Err(Error::Malformed(
|
||||
format!("failed to write {:?}", range)
|
||||
)),
|
||||
}
|
||||
};
|
||||
|
||||
println!(" copy {:#x}, {:#x}: {:#x}, {:#x}", vaddr, vsize, voff, obj_data.len());
|
||||
|
||||
mmap_data.copy_from_slice(obj_data);
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
|
||||
mmaps.insert(elf_name, mmap);
|
||||
}
|
||||
|
||||
// Perform relocations and protect pages
|
||||
let mut entry_opt = None;
|
||||
for (elf_name, elf) in elfs.iter() {
|
||||
let mmap = match mmaps.get_mut(elf_name) {
|
||||
Some(some) => some,
|
||||
None => continue
|
||||
};
|
||||
|
||||
println!("link {}", elf_name);
|
||||
|
||||
if *elf_name == primary {
|
||||
entry_opt = Some(mmap.as_mut_ptr() as usize + elf.header.e_entry as usize);
|
||||
}
|
||||
|
||||
// Relocate
|
||||
for rel in elf.dynrelas.iter().chain(elf.dynrels.iter()).chain(elf.pltrelocs.iter()) {
|
||||
println!(" rel {}: {:x?}",
|
||||
reloc::r_to_str(rel.r_type, elf.header.e_machine),
|
||||
rel
|
||||
);
|
||||
|
||||
let a = rel.r_addend.unwrap_or(0) as usize;
|
||||
|
||||
let b = mmap.as_ptr() as usize;
|
||||
|
||||
let s = if rel.r_sym > 0 {
|
||||
let sym = elf.dynsyms.get(rel.r_sym).ok_or(Error::Malformed(
|
||||
format!("missing symbol for relocation {:?}", rel)
|
||||
))?;
|
||||
|
||||
let name = elf.dynstrtab.get(sym.st_name).ok_or(Error::Malformed(
|
||||
format!("missing name for symbol {:?}", sym)
|
||||
))??;
|
||||
|
||||
if let Some(value) = globals.get(name) {
|
||||
println!(" sym {}: {:x?} = {:#x}", name, sym, value);
|
||||
*value
|
||||
} else {
|
||||
println!(" sym {}: {:x?} = undefined", name, sym);
|
||||
0
|
||||
}
|
||||
} else {
|
||||
0
|
||||
};
|
||||
|
||||
let ptr = unsafe {
|
||||
mmap.as_mut_ptr().add(rel.r_offset as usize)
|
||||
};
|
||||
|
||||
let set_u64 = |value| {
|
||||
println!(" set_u64 {:#x}", value);
|
||||
unsafe { *(ptr as *mut u64) = value; }
|
||||
};
|
||||
|
||||
match rel.r_type {
|
||||
reloc::R_X86_64_64 => {
|
||||
set_u64((s + a) as u64);
|
||||
},
|
||||
reloc::R_X86_64_GLOB_DAT | reloc::R_X86_64_JUMP_SLOT => {
|
||||
set_u64(s as u64);
|
||||
},
|
||||
reloc::R_X86_64_RELATIVE => {
|
||||
set_u64((b + a) as u64);
|
||||
},
|
||||
_ => {
|
||||
println!(" unsupported");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Protect pages
|
||||
for ph in elf.program_headers.iter() {
|
||||
match ph.p_type {
|
||||
program_header::PT_LOAD => {
|
||||
let voff = ph.p_vaddr as usize % PAGE_SIZE;
|
||||
let vaddr = ph.p_vaddr as usize - voff;
|
||||
let vsize = ((ph.p_memsz as usize + voff + PAGE_SIZE - 1) / PAGE_SIZE) * PAGE_SIZE;
|
||||
|
||||
let mut prot = 0;
|
||||
|
||||
if ph.p_flags & program_header::PF_R == program_header::PF_R {
|
||||
prot |= sys_mman::PROT_READ;
|
||||
}
|
||||
|
||||
// W ^ X. If it is executable, do not allow it to be writable, even if requested
|
||||
if ph.p_flags & program_header::PF_X == program_header::PF_X {
|
||||
prot |= sys_mman::PROT_EXEC;
|
||||
} else if ph.p_flags & program_header::PF_W == program_header::PF_W {
|
||||
prot |= sys_mman::PROT_WRITE;
|
||||
}
|
||||
|
||||
let res = unsafe {
|
||||
let ptr = mmap.as_mut_ptr().add(vaddr);
|
||||
println!(" prot {:#x}, {:#x}: {:p}, {:#x}", vaddr, vsize, ptr, prot);
|
||||
|
||||
sys_mman::mprotect(
|
||||
ptr as *mut c_void,
|
||||
vsize,
|
||||
prot
|
||||
)
|
||||
};
|
||||
|
||||
if res < 0 {
|
||||
return Err(Error::Malformed(
|
||||
format!("failed to mprotect {}", elf_name)
|
||||
));
|
||||
}
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entry_opt.ok_or(Error::Malformed(
|
||||
format!("missing entry for {}", primary)
|
||||
))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod linker;
|
||||
pub mod start;
|
||||
@@ -0,0 +1,64 @@
|
||||
#![no_std]
|
||||
#![feature(asm)]
|
||||
#![feature(linkage)]
|
||||
#![feature(naked_functions)]
|
||||
|
||||
#[naked]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn _start() {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
asm!("
|
||||
# Save original stack and align stack to 16 bytes
|
||||
mov rbp, rsp
|
||||
and rsp, 0xFFFFFFFFFFFFFFF0
|
||||
|
||||
# Call ld_so_start(stack)
|
||||
mov rdi, rbp
|
||||
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
|
||||
jmp rax
|
||||
"
|
||||
:
|
||||
:
|
||||
:
|
||||
: "intel", "volatile"
|
||||
);
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
asm!("
|
||||
mov x0, sp
|
||||
bl ld_so_start
|
||||
TODO
|
||||
"
|
||||
:
|
||||
:
|
||||
:
|
||||
: "volatile"
|
||||
);
|
||||
}
|
||||
|
||||
#[naked]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn main(argc: isize, argv: *const *const i8) -> usize {
|
||||
// LD
|
||||
0x1D
|
||||
}
|
||||
|
||||
#[panic_handler]
|
||||
#[linkage = "weak"]
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn rust_begin_unwind(pi: &::core::panic::PanicInfo) -> ! {
|
||||
extern "C" {
|
||||
fn relibc_panic(pi: &::core::panic::PanicInfo) -> !;
|
||||
}
|
||||
relibc_panic(pi)
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
// Start code adapted from https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/start.rs
|
||||
|
||||
use c_str::CStr;
|
||||
use header::unistd;
|
||||
use platform::types::c_char;
|
||||
|
||||
use super::linker::Linker;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct Stack {
|
||||
argc: isize,
|
||||
argv0: *const c_char,
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn relibc_ld_so_start(sp: &'static mut Stack) -> usize {
|
||||
if sp.argc < 2 {
|
||||
eprintln!("ld.so [executable] [arguments...]");
|
||||
unistd::_exit(1);
|
||||
loop {}
|
||||
}
|
||||
|
||||
// Pop the first argument (path to ld_so), and get the path of the program
|
||||
// TODO: Also retrieve LD_LIBRARY_PATH this way
|
||||
let path_c = unsafe {
|
||||
let mut argv = &mut sp.argv0 as *mut *const c_char;
|
||||
loop {
|
||||
let next_argv = argv.add(1);
|
||||
let arg = *next_argv;
|
||||
*argv = arg;
|
||||
argv = next_argv;
|
||||
if arg.is_null() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
sp.argc -= 1;
|
||||
|
||||
CStr::from_ptr(sp.argv0)
|
||||
};
|
||||
|
||||
let path = match path_c.to_str() {
|
||||
Ok(ok) => ok,
|
||||
Err(err) => {
|
||||
eprintln!("ld.so: failed to parse path: {}", err);
|
||||
unistd::_exit(1);
|
||||
loop {}
|
||||
}
|
||||
};
|
||||
|
||||
let mut linker = Linker::new("/usr/local/lib:/lib/x86_64-linux-gnu");
|
||||
match linker.load(&path, &path) {
|
||||
Ok(()) => (),
|
||||
Err(err) => {
|
||||
eprintln!("ld.so: failed to load '{}': {}", path, err);
|
||||
unistd::_exit(1);
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
|
||||
match linker.link(&path) {
|
||||
Ok(entry) => entry,
|
||||
Err(err) => {
|
||||
eprintln!("ld.so: failed to link '{}': {}", path, err);
|
||||
unistd::_exit(1);
|
||||
loop {}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,6 +26,7 @@
|
||||
extern crate alloc;
|
||||
extern crate cbitset;
|
||||
extern crate core_io;
|
||||
extern crate goblin;
|
||||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
extern crate posix_regex;
|
||||
@@ -50,6 +51,7 @@ pub mod db;
|
||||
pub mod fs;
|
||||
pub mod header;
|
||||
pub mod io;
|
||||
pub mod ld_so;
|
||||
pub mod mutex;
|
||||
pub mod platform;
|
||||
pub mod start;
|
||||
|
||||
Reference in New Issue
Block a user