Merge branch 'merge-ld-libc' into 'master'
feat(ld.so): merge with libc.so Closes #284 See merge request redox-os/relibc!1547
This commit is contained in:
Generated
+15
-15
@@ -16,9 +16,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "arrayvec"
|
||||
version = "0.7.6"
|
||||
version = "0.7.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
|
||||
checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56"
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
@@ -289,9 +289,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.32"
|
||||
version = "0.4.33"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "953f07c43838f8e6f9758cab68bf5bed85465e7587ebe0b823f1bcd81978ad3a"
|
||||
checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad"
|
||||
|
||||
[[package]]
|
||||
name = "md-5"
|
||||
@@ -305,9 +305,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.8.1"
|
||||
version = "2.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6b947ae49db0d222b1dbc6b113ce7248a3fc3a6ca21b696717bfc000ba4484d8"
|
||||
checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98"
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
@@ -321,7 +321,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
source = "git+https://gitlab.redox-os.org/andypython/object#7270e3f0d06e5ef4c2b80abc6166d31f4ddf4fea"
|
||||
source = "git+https://gitlab.redox-os.org/andypython/object?branch=new#da781336d847df0deb897ed1162785f6c2057c56"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
@@ -389,18 +389,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.45"
|
||||
version = "1.0.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
|
||||
checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.10.1"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2e8e8bcc7961af1fdac401278c6a831614941f6164ee3bf4ce61b7edb162207"
|
||||
checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80"
|
||||
dependencies = [
|
||||
"rand_core 0.10.1",
|
||||
]
|
||||
@@ -615,9 +615,9 @@ checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
version = "0.9.8"
|
||||
version = "0.9.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
|
||||
checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
]
|
||||
@@ -630,9 +630,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.117"
|
||||
version = "2.0.119"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
|
||||
checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
@@ -117,6 +117,7 @@ features = ["c_api"]
|
||||
[dependencies.object]
|
||||
version = "0.36.7"
|
||||
git = "https://gitlab.redox-os.org/andypython/object"
|
||||
branch = "new"
|
||||
default-features = false
|
||||
features = ["elf", "read_core"]
|
||||
|
||||
|
||||
@@ -51,13 +51,13 @@ 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"; \
|
||||
printf "\033[0;36;49mWriting Header $$header\033[0m\n"; \
|
||||
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"; \
|
||||
fi \
|
||||
done; echo -e "\033[0;36;49mAll headers written\033[0m";
|
||||
done; printf "\033[0;36;49mAll headers written\033[0m\n";
|
||||
|
||||
clean:
|
||||
$(CARGO) clean
|
||||
@@ -147,8 +147,12 @@ $(BUILD)/$(PROFILE)/libc.so: $(BUILD)/$(PROFILE)/libc.a
|
||||
-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 $@
|
||||
# Specifying a dynamic list makes all non-local `STV_DEFAULT`
|
||||
# definitions non-preemptible, except for the symbols listed in
|
||||
# `dynlst.txt`. So, the symbols defined in `dynlst.txt` may be
|
||||
# interposed by other definitions at runtime (either from the
|
||||
# executable or some shared library).
|
||||
$(LD) --shared --whole-archive --dynamic-list=dynlst.txt $^ -o $@
|
||||
|
||||
$(BUILD)/$(PROFILE)/libc.a: $(BUILD)/$(PROFILE)/librelibc.a $(BUILD)/openlibm/libopenlibm.a
|
||||
echo "create $@" > "$@.mri"
|
||||
@@ -221,7 +225,7 @@ $(BUILD)/openlibm: openlibm
|
||||
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/"
|
||||
./renamesyms.sh "$@" "$(BUILD)/$(PROFILE)/deps/"
|
||||
else
|
||||
$(BUILD)/openlibm/libopenlibm.a:
|
||||
mkdir -p "$(BUILD)/openlibm"
|
||||
|
||||
+1
-1
Submodule dlmalloc-rs updated: 3b0ee3b467...40c10f6182
+27
@@ -0,0 +1,27 @@
|
||||
{
|
||||
environ;
|
||||
|
||||
stdin;
|
||||
stdout;
|
||||
stderr;
|
||||
|
||||
timezone;
|
||||
daylight;
|
||||
tzname;
|
||||
__timezone;
|
||||
__daylight;
|
||||
__tzname;
|
||||
|
||||
signgam;
|
||||
__signgam;
|
||||
|
||||
optarg;
|
||||
optind;
|
||||
opterr;
|
||||
optreset;
|
||||
__optreset;
|
||||
|
||||
getdate_err;
|
||||
|
||||
__stack_chk_guard;
|
||||
};
|
||||
@@ -1,263 +0,0 @@
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
./aarch64-unknown-linux-gnu.ld
|
||||
@@ -1,255 +0,0 @@
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
@@ -1,256 +0,0 @@
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
@@ -1,247 +0,0 @@
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
@@ -1,259 +0,0 @@
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
./x86_64-unknown-linux-gnu.ld
|
||||
@@ -1,256 +0,0 @@
|
||||
/* 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)
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -112,7 +112,7 @@ global_asm!(
|
||||
.globl _start
|
||||
_start:
|
||||
mv a0, sp
|
||||
jal relibc_ld_so_start
|
||||
call relibc_ld_so_start
|
||||
unimp
|
||||
"
|
||||
);
|
||||
|
||||
+13
-15
@@ -11,10 +11,13 @@ use core::{
|
||||
sync::atomic::{AtomicUsize, Ordering},
|
||||
};
|
||||
|
||||
use alloc::sync::Arc;
|
||||
|
||||
use crate::{
|
||||
c_str::CStr,
|
||||
ld_so::{
|
||||
linker::{DlError, ObjectHandle, Resolve, ScopeKind},
|
||||
dso::DSO,
|
||||
linker::{DlError, Resolve, ScopeKind},
|
||||
tcb::Tcb,
|
||||
},
|
||||
platform::types::{c_char, c_int, c_void},
|
||||
@@ -123,11 +126,8 @@ pub unsafe extern "C" fn dlopen(cfilename: *const c_char, flags: c_int) -> *mut
|
||||
|
||||
let mut linker = unsafe { (*tcb.linker_ptr).lock() };
|
||||
|
||||
let cbs_c = linker.cbs.clone();
|
||||
let cbs = cbs_c.borrow();
|
||||
|
||||
match (cbs.load_library)(&mut linker, filename, resolve, scope, noload) {
|
||||
Ok(handle) => handle.as_ptr().cast_mut(),
|
||||
match linker.load_library(filename, resolve, scope, noload) {
|
||||
Ok(handle) => Arc::into_raw(handle).cast::<c_void>().cast_mut(),
|
||||
Err(error) => {
|
||||
set_last_error(error);
|
||||
ptr::null_mut()
|
||||
@@ -138,7 +138,7 @@ pub unsafe extern "C" fn dlopen(cfilename: *const c_char, flags: c_int) -> *mut
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/dlsym.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void {
|
||||
let handle = ObjectHandle::from_ptr(handle);
|
||||
let handle = unsafe { handle.cast::<DSO>().as_ref() };
|
||||
|
||||
if symbol.is_null() {
|
||||
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
|
||||
@@ -161,9 +161,8 @@ pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *m
|
||||
}
|
||||
|
||||
let linker = unsafe { (*tcb.linker_ptr).lock() };
|
||||
let cbs_c = linker.cbs.clone();
|
||||
let cbs = cbs_c.borrow();
|
||||
match (cbs.get_sym)(&linker, handle, symbol_str) {
|
||||
|
||||
match linker.get_sym(handle, symbol_str) {
|
||||
Some(sym) => sym,
|
||||
_ => {
|
||||
ERROR.store(ERROR_NOT_SUPPORTED.as_ptr() as usize, Ordering::SeqCst);
|
||||
@@ -185,15 +184,14 @@ pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
|
||||
return -1;
|
||||
};
|
||||
|
||||
let Some(handle) = ObjectHandle::from_ptr(handle) else {
|
||||
if handle.is_null() {
|
||||
set_last_error(DlError::InvalidHandle);
|
||||
return -1;
|
||||
};
|
||||
}
|
||||
|
||||
let mut linker = unsafe { (*tcb.linker_ptr).lock() };
|
||||
let cbs_c = linker.cbs.clone();
|
||||
let cbs = cbs_c.borrow();
|
||||
(cbs.unload)(&mut linker, handle);
|
||||
let obj = unsafe { Arc::from_raw(handle.cast::<DSO>()) };
|
||||
linker.unload(obj);
|
||||
0
|
||||
}
|
||||
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
use super::linker::{Linker, ObjectHandle, Resolve, Result, ScopeKind};
|
||||
use crate::platform::types::c_void;
|
||||
use alloc::boxed::Box;
|
||||
|
||||
pub struct LinkerCallbacks {
|
||||
pub unload: Box<dyn Fn(&mut Linker, ObjectHandle)>,
|
||||
pub load_library:
|
||||
Box<dyn Fn(&mut Linker, Option<&str>, Resolve, ScopeKind, bool) -> Result<ObjectHandle>>,
|
||||
pub get_sym: Box<dyn Fn(&Linker, Option<ObjectHandle>, &str) -> Option<*mut c_void>>,
|
||||
}
|
||||
|
||||
impl LinkerCallbacks {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub fn new() -> LinkerCallbacks {
|
||||
LinkerCallbacks {
|
||||
unload: Box::new(unload),
|
||||
load_library: Box::new(load_library),
|
||||
get_sym: Box::new(get_sym),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn unload(linker: &mut Linker, handle: ObjectHandle) {
|
||||
linker.unload(handle)
|
||||
}
|
||||
|
||||
fn load_library(
|
||||
linker: &mut Linker,
|
||||
name: Option<&str>,
|
||||
resolve: Resolve,
|
||||
scope: ScopeKind,
|
||||
noload: bool,
|
||||
) -> Result<ObjectHandle> {
|
||||
linker.load_library(name, resolve, scope, noload)
|
||||
}
|
||||
|
||||
fn get_sym(linker: &Linker, handle: Option<ObjectHandle>, name: &str) -> Option<*mut c_void> {
|
||||
linker.get_sym(handle, name)
|
||||
}
|
||||
+215
-67
@@ -3,7 +3,7 @@
|
||||
//! * <https://www.akkadia.org/drepper/dsohowto.pdf>
|
||||
|
||||
use object::{
|
||||
NativeEndian, Object, StringTable, SymbolIndex, elf,
|
||||
NativeEndian, Object, StringTable, SymbolIndex, U32, elf,
|
||||
read::elf::{
|
||||
Dyn as _, GnuHashTable, HashTable as SysVHashTable, ProgramHeader as _, Rel as _,
|
||||
Rela as _, Sym as _, Version, VersionTable,
|
||||
@@ -42,25 +42,29 @@ pub type Relr = usize;
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
mod shim {
|
||||
use object::{NativeEndian, elf::*, read::elf::ElfFile32};
|
||||
pub type Dyn = Dyn32<NativeEndian>;
|
||||
pub type Rel = Rel32<NativeEndian>;
|
||||
pub type Rela = Rela32<NativeEndian>;
|
||||
pub type Sym = Sym32<NativeEndian>;
|
||||
pub type FileHeader = FileHeader32<NativeEndian>;
|
||||
pub type ProgramHeader = ProgramHeader32<NativeEndian>;
|
||||
use object::{NativeEndian, elf, read::elf::ElfFile32};
|
||||
pub type Dyn = elf::Dyn32<NativeEndian>;
|
||||
pub type Rel = elf::Rel32<NativeEndian>;
|
||||
pub type Rela = elf::Rela32<NativeEndian>;
|
||||
pub type Sym = elf::Sym32<NativeEndian>;
|
||||
pub type FileHeader = elf::FileHeader32<NativeEndian>;
|
||||
pub type ProgramHeader = elf::ProgramHeader32<NativeEndian>;
|
||||
pub type GnuHashHeader = elf::GnuHashHeader<NativeEndian>;
|
||||
pub type SysVHashHeader = elf::HashHeader<NativeEndian>;
|
||||
pub type ElfFile<'a> = ElfFile32<'a, NativeEndian>;
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
mod shim {
|
||||
use object::{NativeEndian, elf::*, read::elf::ElfFile64};
|
||||
pub type Dyn = Dyn64<NativeEndian>;
|
||||
pub type Rel = Rel64<NativeEndian>;
|
||||
pub type Rela = Rela64<NativeEndian>;
|
||||
pub type Sym = Sym64<NativeEndian>;
|
||||
pub type FileHeader = FileHeader64<NativeEndian>;
|
||||
pub type ProgramHeader = ProgramHeader64<NativeEndian>;
|
||||
use object::{NativeEndian, elf, read::elf::ElfFile64};
|
||||
pub type Dyn = elf::Dyn64<NativeEndian>;
|
||||
pub type Rel = elf::Rel64<NativeEndian>;
|
||||
pub type Rela = elf::Rela64<NativeEndian>;
|
||||
pub type Sym = elf::Sym64<NativeEndian>;
|
||||
pub type FileHeader = elf::FileHeader64<NativeEndian>;
|
||||
pub type ProgramHeader = elf::ProgramHeader64<NativeEndian>;
|
||||
pub type GnuHashHeader = elf::GnuHashHeader<NativeEndian>;
|
||||
pub type SysVHashHeader = elf::HashHeader<NativeEndian>;
|
||||
pub type ElfFile<'a> = ElfFile64<'a, NativeEndian>;
|
||||
}
|
||||
|
||||
@@ -176,7 +180,7 @@ impl<'data> Dynamic<'data> {
|
||||
unsafe impl Send for Dynamic<'_> {}
|
||||
unsafe impl Sync for Dynamic<'_> {}
|
||||
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(super) struct Relocation {
|
||||
pub(super) offset: usize,
|
||||
pub(super) addend: Option<usize>,
|
||||
@@ -331,14 +335,35 @@ impl SymbolBinding {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct MemoryMapHandle {
|
||||
ptr: *const u8,
|
||||
size: usize,
|
||||
}
|
||||
|
||||
impl MemoryMapHandle {
|
||||
pub fn as_ptr(&self) -> *const u8 {
|
||||
self.ptr
|
||||
}
|
||||
|
||||
pub fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for MemoryMapHandle {
|
||||
fn drop(&mut self) {
|
||||
unsafe { Sys::munmap(self.ptr as *mut c_void, self.size).unwrap() };
|
||||
}
|
||||
}
|
||||
|
||||
/// Use to represent a library as well as all the symbols that is loaded withen it.
|
||||
pub struct DSO {
|
||||
pub name: String,
|
||||
pub id: usize,
|
||||
pub dlopened: bool,
|
||||
pub entry_point: usize,
|
||||
/// Loaded library in-memory data
|
||||
pub mmap: &'static [u8],
|
||||
pub base: *const u8,
|
||||
pub mmap: Option<MemoryMapHandle>,
|
||||
pub tls_module_id: usize,
|
||||
pub tls_offset: usize,
|
||||
|
||||
@@ -350,9 +375,55 @@ pub struct DSO {
|
||||
|
||||
/// Whether this DSO *and* its dependencies have been successfully loaded.
|
||||
is_ready: AtomicBool,
|
||||
|
||||
/// Is this DSO for ld.so?
|
||||
is_me: bool,
|
||||
}
|
||||
|
||||
impl DSO {
|
||||
pub fn from_raw(
|
||||
base: *const u8,
|
||||
dyns: &[Dyn],
|
||||
phdrs: &[ProgramHeader],
|
||||
id: usize,
|
||||
tls_module_id: usize,
|
||||
tls_offset: usize,
|
||||
) -> (Self, Master) {
|
||||
// FIXME: What should `path` be set to?
|
||||
// FIXME: this function and `parse_dynamic` should be unsafe.
|
||||
let (dynamic, _debug) = Self::parse_dynamic("", base, true, dyns).unwrap();
|
||||
|
||||
let tcb_master = phdrs
|
||||
.iter()
|
||||
.find(|ph| ph.p_type(NativeEndian) == elf::PT_TLS)
|
||||
.map(|ph| Master {
|
||||
ptr: unsafe { base.byte_add(ph.p_vaddr(NativeEndian) as usize) },
|
||||
image_size: ph.p_filesz(NativeEndian) as usize,
|
||||
segment_size: ph.p_memsz(NativeEndian) as usize,
|
||||
offset: tls_offset + ph.p_memsz(NativeEndian) as usize,
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
(
|
||||
Self {
|
||||
name: String::from("libc.so.6"),
|
||||
id,
|
||||
tls_offset: tcb_master.offset,
|
||||
tls_module_id,
|
||||
dlopened: false,
|
||||
entry_point: 0,
|
||||
base,
|
||||
mmap: None,
|
||||
dynamic,
|
||||
scope: spin::Once::new(),
|
||||
pie: true,
|
||||
is_ready: AtomicBool::new(false),
|
||||
is_me: true,
|
||||
},
|
||||
tcb_master,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn new(
|
||||
path: &str,
|
||||
data: &[u8],
|
||||
@@ -385,7 +456,10 @@ impl DSO {
|
||||
id,
|
||||
dlopened,
|
||||
entry_point,
|
||||
mmap,
|
||||
|
||||
base: mmap.as_ptr(),
|
||||
mmap: Some(mmap),
|
||||
|
||||
tls_module_id: if tcb_master.is_some() {
|
||||
tls_module_id
|
||||
} else {
|
||||
@@ -397,13 +471,14 @@ impl DSO {
|
||||
dynamic,
|
||||
scope: spin::Once::new(),
|
||||
is_ready: AtomicBool::new(false),
|
||||
is_me: false,
|
||||
};
|
||||
|
||||
Ok((dso, tcb_master, elf.elf_program_headers().to_vec()))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mark_ready(&self) {
|
||||
pub unsafe fn mark_ready(&self) {
|
||||
self.is_ready.store(true, Ordering::SeqCst);
|
||||
}
|
||||
|
||||
@@ -444,11 +519,7 @@ impl DSO {
|
||||
Some((
|
||||
Symbol {
|
||||
name,
|
||||
base: if self.pie {
|
||||
self.mmap.as_ptr() as usize
|
||||
} else {
|
||||
0
|
||||
},
|
||||
base: if self.pie { self.base as usize } else { 0 },
|
||||
value: sym.st_value(NativeEndian) as usize,
|
||||
size: sym.st_size(NativeEndian) as usize,
|
||||
sym_type: sym.st_type(),
|
||||
@@ -468,7 +539,7 @@ impl DSO {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn run_fini(&self) {
|
||||
pub unsafe fn run_fini(&self) {
|
||||
for f in self.dynamic.fini_array.iter().rev() {
|
||||
unsafe { f() }
|
||||
}
|
||||
@@ -480,7 +551,7 @@ impl DSO {
|
||||
data: &'a [u8],
|
||||
base_addr: Option<usize>,
|
||||
tls_offset: usize,
|
||||
) -> Result<(&'static [u8], Option<Master>, Dynamic<'static>), String> {
|
||||
) -> Result<(MemoryMapHandle, Option<Master>, Dynamic<'static>), String> {
|
||||
let endian = elf.endian();
|
||||
log::trace!("# {}", path);
|
||||
// data for struct LinkMap
|
||||
@@ -640,8 +711,9 @@ impl DSO {
|
||||
|
||||
let dynamic = dynamic.ok_or_else(|| "Unable to find PT_DYNAMIC section".to_string())?;
|
||||
|
||||
let (parsed_dynamic, debug) = Self::parse_dynamic(path, mmap, is_pie_enabled(elf), dynamic)
|
||||
.map_err(|e| e.to_string())?;
|
||||
let (parsed_dynamic, debug) =
|
||||
Self::parse_dynamic(path, mmap.as_ptr(), is_pie_enabled(elf), dynamic.1)
|
||||
.map_err(|e| e.to_string())?;
|
||||
|
||||
if let Some(i) = debug {
|
||||
// FIXME: cleanup
|
||||
@@ -664,14 +736,21 @@ impl DSO {
|
||||
}
|
||||
}
|
||||
|
||||
Ok((mmap, tcb_master, parsed_dynamic))
|
||||
Ok((
|
||||
MemoryMapHandle {
|
||||
ptr: mmap.as_ptr(),
|
||||
size: mmap.len(),
|
||||
},
|
||||
tcb_master,
|
||||
parsed_dynamic,
|
||||
))
|
||||
}
|
||||
|
||||
fn parse_dynamic<'a>(
|
||||
path: &str,
|
||||
mmap: &'a [u8],
|
||||
mmap: *const u8,
|
||||
is_pie: bool,
|
||||
(_, entries): (&ProgramHeader, &[Dyn]),
|
||||
entries: &[Dyn],
|
||||
) -> object::Result<(Dynamic<'a>, Option<usize>)> {
|
||||
let mut runpath = None;
|
||||
let mut got = None;
|
||||
@@ -692,28 +771,79 @@ impl DSO {
|
||||
|
||||
for (i, entry) in entries.iter().enumerate() {
|
||||
let val = entry.d_val(NativeEndian);
|
||||
let relative_idx = val as usize - if is_pie { 0 } else { mmap.as_ptr() as usize };
|
||||
let ptr = (val as usize + if is_pie { mmap.as_ptr() as usize } else { 0 }) as *const u8;
|
||||
let relative_idx = val as usize - if is_pie { 0 } else { mmap as usize };
|
||||
let ptr = (val as usize + if is_pie { mmap as usize } else { 0 }) as *const u8;
|
||||
let tag = entry.d_tag(NativeEndian) as u32;
|
||||
|
||||
match tag {
|
||||
elf::DT_DEBUG => debug = Some(i),
|
||||
|
||||
// {Gnu,SysV}HashTable::parse()
|
||||
//
|
||||
// > The header does not contain a length field, and so all of
|
||||
// > `data` will be used as the hash table values. It does not
|
||||
// > matter if this is longer than needed...
|
||||
elf::DT_GNU_HASH => {
|
||||
let value = GnuHashTable::parse(NativeEndian, &mmap[relative_idx..])?;
|
||||
hash_table = Some(HashTable::Gnu(value));
|
||||
let header = unsafe { ptr.cast::<GnuHashHeader>().as_ref() }.unwrap();
|
||||
let bloom_count = header.bloom_count.get(NativeEndian) as usize;
|
||||
let bucket_count = header.bucket_count.get(NativeEndian) as usize;
|
||||
let symbol_base = header.symbol_base.get(NativeEndian);
|
||||
|
||||
let bloom_size = bloom_count * size_of::<usize>();
|
||||
let mut ptr = unsafe { ptr.byte_add(size_of::<GnuHashHeader>()) };
|
||||
|
||||
let bloom_filters = unsafe { slice::from_raw_parts(ptr, bloom_size) };
|
||||
unsafe { ptr = ptr.byte_add(bloom_size) };
|
||||
|
||||
let buckets = unsafe {
|
||||
slice::from_raw_parts(ptr.cast::<U32<NativeEndian>>(), bucket_count)
|
||||
};
|
||||
unsafe { ptr = ptr.byte_add(bucket_count * size_of::<u32>()) };
|
||||
|
||||
let mut max_symbol = 0;
|
||||
for bucket in buckets {
|
||||
let bucket = bucket.get(NativeEndian);
|
||||
if max_symbol < bucket {
|
||||
max_symbol = bucket;
|
||||
}
|
||||
}
|
||||
|
||||
assert_ne!(max_symbol, 0);
|
||||
let chains_ptr = ptr.cast::<u32>();
|
||||
let mut i = max_symbol - symbol_base;
|
||||
|
||||
while unsafe { chains_ptr.add(i as usize).read() & 1 == 0 } {
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let values = unsafe {
|
||||
slice::from_raw_parts(ptr.cast::<U32<NativeEndian>>(), i as usize + 1)
|
||||
};
|
||||
|
||||
let table = GnuHashTable {
|
||||
symbol_base,
|
||||
bloom_shift: header.bloom_shift.get(NativeEndian),
|
||||
bloom_filters,
|
||||
buckets,
|
||||
values,
|
||||
};
|
||||
|
||||
hash_table = Some(HashTable::Gnu(table));
|
||||
}
|
||||
|
||||
// XXX: Both GNU_HASH and HASH may be present, we give priority
|
||||
// to GNU_HASH as it is significantly faster.
|
||||
elf::DT_HASH if hash_table.is_none() => {
|
||||
let value = SysVHashTable::parse(NativeEndian, &mmap[relative_idx..])?;
|
||||
hash_table = Some(HashTable::Sysv(value));
|
||||
let header = unsafe { ptr.cast::<SysVHashHeader>().as_ref() }.unwrap();
|
||||
let bucket_count = header.bucket_count.get(NativeEndian) as usize;
|
||||
let chain_count = header.chain_count.get(NativeEndian) as usize;
|
||||
|
||||
let mut ptr = unsafe {
|
||||
ptr.byte_add(size_of::<SysVHashHeader>())
|
||||
.cast::<U32<NativeEndian>>()
|
||||
};
|
||||
|
||||
let buckets = unsafe { slice::from_raw_parts(ptr, bucket_count) };
|
||||
unsafe { ptr = ptr.add(bucket_count) };
|
||||
let chains = unsafe { slice::from_raw_parts(ptr, chain_count) };
|
||||
|
||||
let table = SysVHashTable { buckets, chains };
|
||||
hash_table = Some(HashTable::Sysv(table));
|
||||
}
|
||||
|
||||
elf::DT_PLTGOT => {
|
||||
@@ -771,14 +901,16 @@ impl DSO {
|
||||
}
|
||||
}
|
||||
|
||||
let strtab_offset = strtab_offset.expect("mandatory DT_STRTAB not present");
|
||||
let strtab_size = strtab_size.expect("mandatory DT_STRSZ not present");
|
||||
let hash_table = hash_table.expect("either DT_GNU_HASH and/or DT_HASH mut be present");
|
||||
|
||||
let strtab_offset = strtab_offset.expect("DT_STRTAB must be present");
|
||||
let strtab_size = strtab_size.expect("DT_STRSZ must be present");
|
||||
|
||||
#[expect(clippy::unnecessary_cast, reason = "needed on i586")]
|
||||
let dynstrtab = StringTable::new(
|
||||
mmap,
|
||||
strtab_offset as u64,
|
||||
strtab_offset as u64 + strtab_size as u64,
|
||||
unsafe { slice::from_raw_parts(mmap.byte_add(strtab_offset), strtab_size as usize) },
|
||||
0,
|
||||
strtab_size as u64,
|
||||
);
|
||||
|
||||
let get_str = |entry: &Dyn| {
|
||||
@@ -812,7 +944,6 @@ impl DSO {
|
||||
let soname = soname.map(get_str).transpose()?;
|
||||
|
||||
let jmprel = jmprel.unwrap_or_default();
|
||||
let hash_table = hash_table.expect("either DT_GNU_HASH and/or DT_HASH mut be present");
|
||||
|
||||
let init_array = unsafe { get_array(init_array_ptr, init_array_len) };
|
||||
let fini_array = unsafe { get_array(fini_array_ptr, fini_array_len) };
|
||||
@@ -889,8 +1020,6 @@ impl DSO {
|
||||
}
|
||||
|
||||
fn static_relocate(&self, global_scope: &Scope, reloc: Relocation) -> object::Result<()> {
|
||||
let b = self.mmap.as_ptr() as usize;
|
||||
|
||||
let (sym, my_sym) = if reloc.sym != STN_UNDEF {
|
||||
let name = self.dynamic.symbol_name(reloc.sym).unwrap();
|
||||
|
||||
@@ -923,7 +1052,7 @@ impl DSO {
|
||||
.unwrap_or((0, self));
|
||||
|
||||
let ptr = if self.pie {
|
||||
(b + reloc.offset) as *mut u8
|
||||
unsafe { self.base.byte_add(reloc.offset).cast_mut() }
|
||||
} else {
|
||||
reloc.offset as *mut u8
|
||||
};
|
||||
@@ -956,7 +1085,7 @@ impl DSO {
|
||||
}
|
||||
RelocationKind::GOT => set_usize(s),
|
||||
RelocationKind::OFFSET => set_usize((s + a).wrapping_sub(p)),
|
||||
RelocationKind::RELATIVE => set_usize(b + a),
|
||||
RelocationKind::RELATIVE => set_usize(self.base as usize + a),
|
||||
RelocationKind::SYMBOLIC => set_usize(s + a),
|
||||
RelocationKind::TPOFF => {
|
||||
assert!(
|
||||
@@ -974,7 +1103,8 @@ impl DSO {
|
||||
}
|
||||
}
|
||||
RelocationKind::IRELATIVE => unsafe {
|
||||
let f: unsafe extern "C" fn() -> usize = core::mem::transmute(b + a);
|
||||
let f: unsafe extern "C" fn() -> usize =
|
||||
core::mem::transmute(self.base as usize + a);
|
||||
set_usize(f());
|
||||
},
|
||||
RelocationKind::COPY => unsafe {
|
||||
@@ -1007,7 +1137,6 @@ impl DSO {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let object_base_addr = self.mmap.as_ptr() as usize;
|
||||
let jmprel = self.dynamic.jmprel;
|
||||
let pltrelsz = self.dynamic.pltrelsz;
|
||||
|
||||
@@ -1031,14 +1160,14 @@ impl DSO {
|
||||
};
|
||||
|
||||
let ptr = if self.pie {
|
||||
(object_base_addr + reloc.offset) as *mut usize
|
||||
(self.base as usize + reloc.offset) as *mut usize
|
||||
} else {
|
||||
reloc.offset as *mut usize
|
||||
};
|
||||
|
||||
match (reloc.kind, resolve) {
|
||||
(RelocationKind::PLT, Resolve::Lazy) if self.pie => unsafe {
|
||||
*ptr += object_base_addr;
|
||||
*ptr += self.base as usize;
|
||||
},
|
||||
|
||||
(RelocationKind::PLT, Resolve::Lazy) => {
|
||||
@@ -1082,20 +1211,31 @@ impl DSO {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn relocate(&self, ph: &[ProgramHeader], resolve: Resolve) -> object::Result<()> {
|
||||
pub fn relocate(&self, ph: Option<&[ProgramHeader]>, resolve: Resolve) -> object::Result<()> {
|
||||
let global_scope = GLOBAL_SCOPE.read();
|
||||
let base = self.mmap.as_ptr();
|
||||
|
||||
unsafe {
|
||||
apply_relr(base, self.dynamic.relr);
|
||||
if !self.is_me {
|
||||
unsafe {
|
||||
apply_relr(self.base, self.dynamic.relr);
|
||||
}
|
||||
}
|
||||
|
||||
self.dynamic
|
||||
.static_relocations()
|
||||
.try_for_each(|reloc| self.static_relocate(&global_scope, reloc))?;
|
||||
for reloc in self.dynamic.static_relocations() {
|
||||
if reloc.kind == RelocationKind::RELATIVE && self.is_me {
|
||||
continue;
|
||||
}
|
||||
self.static_relocate(&global_scope, reloc)?;
|
||||
}
|
||||
|
||||
if self.is_me {
|
||||
// TODO: assert that ld.so have no lazy relocations.
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
self.lazy_relocate(&global_scope, resolve)?;
|
||||
|
||||
let ph = ph.unwrap();
|
||||
|
||||
// Protect pages
|
||||
for ph in ph
|
||||
.iter()
|
||||
@@ -1120,7 +1260,7 @@ impl DSO {
|
||||
|
||||
unsafe {
|
||||
let ptr = if self.pie {
|
||||
self.mmap.as_ptr().add(vaddr)
|
||||
self.base.add(vaddr)
|
||||
} else {
|
||||
vaddr as *const u8
|
||||
};
|
||||
@@ -1135,12 +1275,16 @@ impl DSO {
|
||||
|
||||
impl Drop for DSO {
|
||||
fn drop(&mut self) {
|
||||
if self.is_me {
|
||||
return;
|
||||
}
|
||||
if self.is_ready.load(Ordering::SeqCst) {
|
||||
// `run_fini` should not be called if we are being prematurely
|
||||
// dropped (e.g. failed to satisfy dependencies).
|
||||
self.run_fini();
|
||||
unsafe {
|
||||
self.run_fini();
|
||||
}
|
||||
}
|
||||
unsafe { Sys::munmap(self.mmap.as_ptr() as *mut c_void, self.mmap.len()).unwrap() };
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1309,3 +1453,7 @@ pub unsafe fn apply_relr(base: *const u8, relr: &[Relr]) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Add safety comment.
|
||||
unsafe impl Send for DSO {}
|
||||
unsafe impl Sync for DSO {}
|
||||
|
||||
+83
-72
@@ -1,6 +1,5 @@
|
||||
use alloc::{
|
||||
collections::BTreeMap,
|
||||
rc::Rc,
|
||||
string::{String, ToString},
|
||||
sync::{Arc, Weak},
|
||||
vec::Vec,
|
||||
@@ -12,13 +11,9 @@ use object::{
|
||||
read::elf::{Rela as _, Sym},
|
||||
};
|
||||
|
||||
use core::{
|
||||
cell::RefCell,
|
||||
ptr::{self, NonNull},
|
||||
};
|
||||
use core::ptr;
|
||||
|
||||
use crate::{
|
||||
ALLOCATOR,
|
||||
c_str::{CStr, CString},
|
||||
error::Errno,
|
||||
header::{
|
||||
@@ -26,7 +21,7 @@ use crate::{
|
||||
fcntl, sys_mman,
|
||||
unistd::F_OK,
|
||||
},
|
||||
ld_so::dso::SymbolBinding,
|
||||
ld_so::dso::{Dyn, SymbolBinding},
|
||||
out::Out,
|
||||
platform::{
|
||||
Pal, Sys,
|
||||
@@ -43,7 +38,6 @@ use super::dso::Rela;
|
||||
use super::{
|
||||
PATH_SEP,
|
||||
access::accessible,
|
||||
callbacks::LinkerCallbacks,
|
||||
debug::{_dl_debug_state, _r_debug, RTLDState},
|
||||
dso::{DSO, ProgramHeader},
|
||||
tcb::{Master, Tcb},
|
||||
@@ -328,41 +322,6 @@ impl Scope {
|
||||
}
|
||||
}
|
||||
|
||||
// Used by dlfcn.h
|
||||
//
|
||||
// We need this as the handle must be created and destroyed with the dynamic
|
||||
// linker's allocator.
|
||||
pub struct ObjectHandle(*const DSO);
|
||||
|
||||
impl ObjectHandle {
|
||||
#[inline]
|
||||
fn new(obj: Arc<DSO>) -> Self {
|
||||
Self(Arc::into_raw(obj))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn into_inner(self) -> Arc<DSO> {
|
||||
unsafe { Arc::from_raw(self.0) }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn as_ptr(&self) -> *const c_void {
|
||||
self.0.cast()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn from_ptr(ptr: *const c_void) -> Option<Self> {
|
||||
NonNull::new(ptr as *mut DSO).map(|ptr| Self(ptr.as_ptr()))
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<DSO> for ObjectHandle {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &DSO {
|
||||
unsafe { &*self.0 }
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DebugFlags: u32 {
|
||||
@@ -417,29 +376,36 @@ impl Config {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Me {
|
||||
pub base: *const u8,
|
||||
pub phdrs: &'static [ProgramHeader],
|
||||
pub dyns: &'static [Dyn],
|
||||
}
|
||||
|
||||
pub struct Linker {
|
||||
config: Config,
|
||||
|
||||
me: Me,
|
||||
|
||||
next_object_id: usize,
|
||||
next_tls_module_id: usize,
|
||||
tls_size: usize,
|
||||
objects: BTreeMap<usize, Arc<DSO>>,
|
||||
name_to_object_id_map: BTreeMap<String, usize>,
|
||||
pub cbs: Rc<RefCell<LinkerCallbacks>>,
|
||||
}
|
||||
|
||||
const ROOT_ID: usize = 1;
|
||||
|
||||
impl Linker {
|
||||
pub fn new(config: Config) -> Self {
|
||||
pub fn new(me: Me, config: Config) -> Self {
|
||||
Self {
|
||||
me,
|
||||
config,
|
||||
next_object_id: ROOT_ID,
|
||||
next_tls_module_id: 1,
|
||||
tls_size: 0,
|
||||
objects: BTreeMap::new(),
|
||||
name_to_object_id_map: BTreeMap::new(),
|
||||
cbs: Rc::new(RefCell::new(LinkerCallbacks::new())),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,7 +431,7 @@ impl Linker {
|
||||
resolve: Resolve,
|
||||
scope: ScopeKind,
|
||||
noload: bool,
|
||||
) -> Result<ObjectHandle> {
|
||||
) -> Result<Arc<DSO>> {
|
||||
log::trace!(
|
||||
"[ld.so] load_library(name={:?}, resolve={:#?}, scope={:#?}, noload={})",
|
||||
name,
|
||||
@@ -500,14 +466,14 @@ impl Linker {
|
||||
self.scope_debug();
|
||||
}
|
||||
|
||||
Ok(ObjectHandle::new(obj.clone()))
|
||||
Ok(obj.clone())
|
||||
} else if !noload {
|
||||
let parent_runpath = &self
|
||||
.objects
|
||||
.get(&ROOT_ID)
|
||||
.and_then(|parent| parent.runpath().cloned());
|
||||
|
||||
Ok(ObjectHandle::new(self.load_object(
|
||||
Ok(self.load_object(
|
||||
name,
|
||||
parent_runpath,
|
||||
None,
|
||||
@@ -518,29 +484,24 @@ impl Linker {
|
||||
resolve
|
||||
},
|
||||
scope,
|
||||
)?))
|
||||
)?)
|
||||
} else {
|
||||
// FIXME: LoadError?
|
||||
// Err(Error::Malformed(format!(
|
||||
// "object '{}' has not yet been loaded",
|
||||
// name
|
||||
// )))
|
||||
Ok(ObjectHandle(ptr::null()))
|
||||
Err(DlError::NotFound)
|
||||
}
|
||||
}
|
||||
|
||||
None => match self.objects.get(&ROOT_ID) {
|
||||
Some(obj) => Ok(ObjectHandle::new(obj.clone())),
|
||||
Some(obj) => Ok(obj.clone()),
|
||||
None => Err(DlError::NotFound),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_sym(&self, handle: Option<ObjectHandle>, name: &str) -> Option<*mut c_void> {
|
||||
pub fn get_sym(&self, handle: Option<&DSO>, name: &str) -> Option<*mut c_void> {
|
||||
let guard;
|
||||
|
||||
if let Some(handle) = handle.as_ref() {
|
||||
handle.as_ref().scope()
|
||||
if let Some(handle) = handle {
|
||||
handle.scope()
|
||||
} else {
|
||||
guard = GLOBAL_SCOPE.read();
|
||||
&guard
|
||||
@@ -560,8 +521,7 @@ impl Linker {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn unload(&mut self, handle: ObjectHandle) {
|
||||
let obj = handle.into_inner();
|
||||
pub fn unload(&mut self, obj: Arc<DSO>) {
|
||||
if !obj.dlopened {
|
||||
return;
|
||||
}
|
||||
@@ -590,7 +550,7 @@ impl Linker {
|
||||
if let Some(name) = self.name_to_object_id_map.get(*dep)
|
||||
&& let Some(object_name) = self.objects.get(name)
|
||||
{
|
||||
self.unload(ObjectHandle::new(object_name.clone()));
|
||||
self.unload(object_name.clone());
|
||||
}
|
||||
}
|
||||
self.name_to_object_id_map.remove(&obj.name);
|
||||
@@ -603,7 +563,9 @@ impl Linker {
|
||||
|
||||
pub fn fini(&self) {
|
||||
for obj in self.objects.values() {
|
||||
obj.run_fini();
|
||||
unsafe {
|
||||
obj.run_fini();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -642,7 +604,11 @@ impl Linker {
|
||||
)?;
|
||||
|
||||
for (i, obj) in new_objects.iter().enumerate() {
|
||||
obj.relocate(&objects_data[i], resolve).unwrap();
|
||||
obj.relocate(
|
||||
objects_data[i].as_ref().map(|phdrs| phdrs.as_slice()),
|
||||
resolve,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
unsafe {
|
||||
@@ -735,7 +701,6 @@ impl Linker {
|
||||
#[cfg(target_os = "redox")]
|
||||
Some(thr_fd),
|
||||
);
|
||||
tcb.mspace = ALLOCATOR.get();
|
||||
|
||||
#[cfg(target_os = "redox")]
|
||||
{
|
||||
@@ -751,7 +716,10 @@ impl Linker {
|
||||
}
|
||||
|
||||
for obj in new_objects.into_iter() {
|
||||
obj.mark_ready();
|
||||
// SAFETY: `obj` and its dependencies have been successfuly loaded.
|
||||
unsafe {
|
||||
obj.mark_ready();
|
||||
}
|
||||
self.run_init(&obj);
|
||||
self.register_object(obj);
|
||||
}
|
||||
@@ -788,7 +756,7 @@ impl Linker {
|
||||
base_addr: Option<usize>,
|
||||
dlopened: bool,
|
||||
new_objects: &mut Vec<Arc<DSO>>,
|
||||
objects_data: &mut Vec<Vec<ProgramHeader>>,
|
||||
objects_data: &mut Vec<Option<Vec<ProgramHeader>>>,
|
||||
tcb_masters: &mut Vec<Master>,
|
||||
// Scope of the object that caused this object to be loaded.
|
||||
dependent_scope: Option<&mut Scope>,
|
||||
@@ -821,6 +789,49 @@ impl Linker {
|
||||
|
||||
let debug = self.config.debug_flags.contains(DebugFlags::LOAD);
|
||||
|
||||
if name == "libc.so.6" || name == "libc.so" {
|
||||
if debug {
|
||||
println!(
|
||||
"[ld.so]: loading libc.so.6 (aka. ld.so) at {:#?}",
|
||||
self.me.base
|
||||
);
|
||||
}
|
||||
|
||||
let (me, master) = DSO::from_raw(
|
||||
self.me.base,
|
||||
self.me.dyns,
|
||||
self.me.phdrs,
|
||||
self.next_object_id,
|
||||
self.next_tls_module_id,
|
||||
self.tls_size.next_multiple_of(16),
|
||||
);
|
||||
|
||||
self.tls_size = master.offset;
|
||||
self.next_tls_module_id += 1;
|
||||
self.next_object_id += 1;
|
||||
|
||||
let obj = Arc::new(me);
|
||||
|
||||
tcb_masters.push(master);
|
||||
objects_data.push(None);
|
||||
new_objects.push(obj.clone());
|
||||
|
||||
if let Some(dependent_scope) = dependent_scope {
|
||||
match scope_kind {
|
||||
ScopeKind::Local => dependent_scope.add(&obj),
|
||||
ScopeKind::Global => GLOBAL_SCOPE.write().add(&obj),
|
||||
}
|
||||
} else if let ScopeKind::Global = scope_kind {
|
||||
GLOBAL_SCOPE.write().add(&obj);
|
||||
}
|
||||
|
||||
let mut scope = Scope::local();
|
||||
scope.set_owner(Arc::downgrade(&obj));
|
||||
obj.scope.call_once(|| scope);
|
||||
|
||||
return Ok(obj);
|
||||
}
|
||||
|
||||
let path = self.search_object(name, parent_runpath)?;
|
||||
let file = self.read_file(&path)?;
|
||||
let data = file.data();
|
||||
@@ -846,8 +857,8 @@ impl Linker {
|
||||
eprintln!(
|
||||
"[ld.so]: loading object: {} at {:#x}:{:#x} (pie: {})",
|
||||
name,
|
||||
obj.mmap.as_ptr() as usize,
|
||||
obj.mmap.as_ptr() as usize + obj.mmap.len(),
|
||||
obj.mmap.as_ref().unwrap().as_ptr() as usize,
|
||||
obj.mmap.as_ref().unwrap().as_ptr() as usize + obj.mmap.as_ref().unwrap().size(),
|
||||
obj.pie,
|
||||
);
|
||||
}
|
||||
@@ -896,7 +907,7 @@ impl Linker {
|
||||
)?;
|
||||
}
|
||||
|
||||
objects_data.push(elf);
|
||||
objects_data.push(Some(elf));
|
||||
new_objects.push(obj.clone());
|
||||
|
||||
scope.set_owner(Arc::downgrade(&obj));
|
||||
@@ -1011,7 +1022,7 @@ impl Linker {
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
extern "C" fn __plt_resolve_inner(obj: *const DSO, relocation_index: c_uint) -> *mut c_void {
|
||||
let obj = unsafe { &*obj };
|
||||
let obj_base = obj.mmap.as_ptr() as usize;
|
||||
let obj_base = obj.base as usize;
|
||||
let jmprel = obj.dynamic.jmprel;
|
||||
|
||||
let rela = unsafe { &*(jmprel as *const Rela).add(relocation_index as usize) };
|
||||
|
||||
+1
-2
@@ -21,9 +21,8 @@ use crate::{
|
||||
pub const PATH_SEP: char = ':';
|
||||
|
||||
mod access;
|
||||
pub mod callbacks;
|
||||
pub mod debug;
|
||||
mod dso;
|
||||
pub mod dso;
|
||||
pub mod linker;
|
||||
pub mod start;
|
||||
pub mod tcb;
|
||||
|
||||
+45
-20
@@ -1,6 +1,6 @@
|
||||
// Start code adapted from https://gitlab.redox-os.org/redox-os/relibc/blob/master/src/start.rs
|
||||
|
||||
use core::slice;
|
||||
use core::{slice, str::FromStr};
|
||||
|
||||
use alloc::{
|
||||
borrow::ToOwned,
|
||||
@@ -9,10 +9,11 @@ use alloc::{
|
||||
string::{String, ToString},
|
||||
vec::Vec,
|
||||
};
|
||||
use log::LevelFilter;
|
||||
use object::{
|
||||
NativeEndian,
|
||||
elf::{self, PT_DYNAMIC, PT_PHDR},
|
||||
read::elf::{Dyn as _, ProgramHeader as _},
|
||||
read::elf::{Dyn as _, FileHeader as _, ProgramHeader as _},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@@ -23,12 +24,12 @@ use crate::{
|
||||
},
|
||||
ld_so::{
|
||||
dso::{
|
||||
DT_RELR, DT_RELRENT, DT_RELRSZ, Dyn, ProgramHeader, Rel, Rela, Relocation,
|
||||
DT_RELR, DT_RELRENT, DT_RELRSZ, Dyn, FileHeader, ProgramHeader, Rel, Rela, Relocation,
|
||||
RelocationKind, Relr, apply_relr,
|
||||
},
|
||||
linker::DebugFlags,
|
||||
linker::{DebugFlags, Me},
|
||||
},
|
||||
platform::{auxv_iter, get_auxvs, types::c_char},
|
||||
platform::{auxv_iter, get_auxvs, logger::RELIBC_LOG_ENV_VAR, types::c_char},
|
||||
start::Stack,
|
||||
sync::mutex::Mutex,
|
||||
};
|
||||
@@ -41,12 +42,6 @@ use super::{
|
||||
tcb::Tcb,
|
||||
};
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub const SIZEOF_EHDR: usize = 52;
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub const SIZEOF_EHDR: usize = 64;
|
||||
|
||||
unsafe fn get_argv(mut ptr: *const usize) -> (Vec<String>, *const usize) {
|
||||
//traverse the stack and collect argument vector
|
||||
let mut argv = Vec::new();
|
||||
@@ -211,7 +206,7 @@ pub unsafe extern "C" fn relibc_ld_so_start(
|
||||
|
||||
let is_manual = at_entry == ld_entry; // Whether the dynamic linker was invoked as a command.
|
||||
|
||||
let mut i = dynamic;
|
||||
let mut i = 0;
|
||||
let mut rela_ptr = None;
|
||||
let mut rela_len = None;
|
||||
let mut relr_ptr = None;
|
||||
@@ -219,7 +214,7 @@ pub unsafe extern "C" fn relibc_ld_so_start(
|
||||
let mut rel_ptr = None;
|
||||
let mut rel_len = None;
|
||||
loop {
|
||||
let entry = unsafe { &*i };
|
||||
let entry = unsafe { &*dynamic.add(i) };
|
||||
let val = entry.d_val(NativeEndian);
|
||||
let ptr = val as *const u8;
|
||||
match entry.d_tag(NativeEndian) as u32 {
|
||||
@@ -241,9 +236,11 @@ pub unsafe extern "C" fn relibc_ld_so_start(
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
i = unsafe { i.add(1) };
|
||||
i += 1;
|
||||
}
|
||||
|
||||
let dyns = unsafe { slice::from_raw_parts(dynamic, i) };
|
||||
|
||||
unsafe fn get_array<'a, T>(
|
||||
ptr: Option<*const T>,
|
||||
len: Option<usize>,
|
||||
@@ -251,7 +248,7 @@ pub unsafe extern "C" fn relibc_ld_so_start(
|
||||
) -> &'a [T] {
|
||||
if let Some(ptr) = ptr {
|
||||
let len = len.expect("dynamic entry was present without it's corresponding size");
|
||||
unsafe { core::slice::from_raw_parts(ptr.byte_add(base_addr), len) }
|
||||
unsafe { slice::from_raw_parts(ptr.byte_add(base_addr), len) }
|
||||
} else {
|
||||
&[]
|
||||
}
|
||||
@@ -298,7 +295,23 @@ pub unsafe extern "C" fn relibc_ld_so_start(
|
||||
}
|
||||
}
|
||||
|
||||
stage2(sp, self_base, is_manual, base_addr)
|
||||
unsafe extern "C" {
|
||||
safe static __ehdr_start: FileHeader;
|
||||
}
|
||||
|
||||
let ph_off = __ehdr_start.e_phoff(NativeEndian) as usize;
|
||||
let ph_num = __ehdr_start.e_phnum(NativeEndian) as usize;
|
||||
|
||||
let my_phdrs = unsafe {
|
||||
slice::from_raw_parts(
|
||||
core::ptr::addr_of!(__ehdr_start)
|
||||
.byte_add(ph_off)
|
||||
.cast::<ProgramHeader>(),
|
||||
ph_num,
|
||||
)
|
||||
};
|
||||
|
||||
stage2(sp, self_base, is_manual, base_addr, dyns, my_phdrs)
|
||||
}
|
||||
|
||||
fn stage2(
|
||||
@@ -306,6 +319,8 @@ fn stage2(
|
||||
self_base: usize,
|
||||
is_manual: bool,
|
||||
base_addr: Option<usize>,
|
||||
my_dyns: &'static [Dyn],
|
||||
my_phdrs: &'static [ProgramHeader],
|
||||
) -> usize {
|
||||
// Setup TCB for ourselves.
|
||||
unsafe {
|
||||
@@ -392,9 +407,12 @@ fn stage2(
|
||||
.collect::<Vec<_>>(),
|
||||
);
|
||||
|
||||
crate::platform::environ = crate::platform::OUR_ENVIRON.unsafe_mut().as_mut_ptr();
|
||||
|
||||
crate::platform::logger::init();
|
||||
if let Some(env) = envs.get(RELIBC_LOG_ENV_VAR.to_str().unwrap())
|
||||
&& let Ok(level) = LevelFilter::from_str(env)
|
||||
&& let Err(_) = crate::platform::logger::init(level)
|
||||
{
|
||||
log::error!("Logger has already been initialised");
|
||||
}
|
||||
}
|
||||
|
||||
// we might need global lock for this kind of stuff
|
||||
@@ -435,7 +453,14 @@ fn stage2(
|
||||
}
|
||||
}
|
||||
|
||||
let mut linker = Linker::new(config);
|
||||
let mut linker = Linker::new(
|
||||
Me {
|
||||
base: self_base as *const u8,
|
||||
phdrs: my_phdrs,
|
||||
dyns: my_dyns,
|
||||
},
|
||||
config,
|
||||
);
|
||||
let entry = match linker.load_program(&path, base_addr) {
|
||||
Ok(entry) => entry,
|
||||
Err(err) => {
|
||||
|
||||
+1
-4
@@ -11,7 +11,7 @@ use generic_rt::GenericTcb;
|
||||
use crate::{
|
||||
header::sys_mman,
|
||||
ld_so::linker::Linker,
|
||||
platform::{Dlmalloc, Pal, Sys},
|
||||
platform::{Pal, Sys},
|
||||
pthread::{OsTid, Pthread},
|
||||
sync::{mutex::Mutex, waitval::Waitval},
|
||||
};
|
||||
@@ -56,8 +56,6 @@ pub struct Tcb {
|
||||
pub num_copied_masters: usize,
|
||||
/// Pointer to dynamic linker
|
||||
pub linker_ptr: *const Mutex<Linker>,
|
||||
/// pointer to rust memory allocator structure
|
||||
pub mspace: *const Mutex<Dlmalloc>,
|
||||
/// Underlying pthread_t struct, pthread_self() returns &self.pthread
|
||||
pub pthread: Pthread,
|
||||
|
||||
@@ -98,7 +96,6 @@ impl Tcb {
|
||||
masters_len: 0,
|
||||
num_copied_masters: 0,
|
||||
linker_ptr: ptr::null(),
|
||||
mspace: ptr::null(),
|
||||
pthread: Pthread {
|
||||
waitval: Waitval::new(),
|
||||
flags: Default::default(),
|
||||
|
||||
@@ -3,8 +3,7 @@ use core::{
|
||||
cell::SyncUnsafeCell,
|
||||
cmp,
|
||||
mem::align_of,
|
||||
ptr::{self, copy_nonoverlapping, write_bytes},
|
||||
sync::atomic::{AtomicPtr, Ordering},
|
||||
ptr::{copy_nonoverlapping, write_bytes},
|
||||
};
|
||||
|
||||
mod sys;
|
||||
@@ -17,31 +16,18 @@ pub type Dlmalloc = DlmallocCApi<sys::System>;
|
||||
#[allow(clippy::declare_interior_mutable_const)]
|
||||
pub const NEWALLOCATOR: Allocator = Allocator::new();
|
||||
|
||||
pub struct Allocator {
|
||||
inner: SyncUnsafeCell<Mutex<Dlmalloc>>,
|
||||
pub ptr: AtomicPtr<Mutex<Dlmalloc>>,
|
||||
}
|
||||
pub struct Allocator(SyncUnsafeCell<Mutex<Dlmalloc>>);
|
||||
|
||||
impl Allocator {
|
||||
#[allow(clippy::new_without_default)]
|
||||
pub const fn new() -> Self {
|
||||
Allocator {
|
||||
inner: SyncUnsafeCell::new(Mutex::new(Dlmalloc::new(sys::System::new()))),
|
||||
ptr: AtomicPtr::new(ptr::null_mut()),
|
||||
}
|
||||
Self(SyncUnsafeCell::new(Mutex::new(Dlmalloc::new(
|
||||
sys::System::new(),
|
||||
))))
|
||||
}
|
||||
|
||||
pub fn get(&self) -> *const Mutex<Dlmalloc> {
|
||||
let ptr = self.ptr.load(Ordering::Acquire);
|
||||
if !ptr.is_null() {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
self.inner.get()
|
||||
}
|
||||
|
||||
pub fn set(&self, mspace: *const Mutex<Dlmalloc>) {
|
||||
self.ptr.store(mspace.cast_mut(), Ordering::Release);
|
||||
self.0.get()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-16
@@ -1,36 +1,33 @@
|
||||
use core::{fmt, str::FromStr};
|
||||
use core::fmt;
|
||||
|
||||
use crate::{c_str::CStr, io::prelude::*, sync::Mutex};
|
||||
|
||||
use alloc::string::{String, ToString};
|
||||
use log::{Metadata, Record};
|
||||
use log::{LevelFilter, Metadata, Record, SetLoggerError};
|
||||
|
||||
const DEFAULT_LOG_LEVEL: log::LevelFilter = log::LevelFilter::Info;
|
||||
|
||||
pub unsafe fn init() {
|
||||
pub const RELIBC_LOG_ENV_VAR: &'static core::ffi::CStr = c"RELIBC_LOG_LEVEL";
|
||||
|
||||
pub unsafe fn init(level: LevelFilter) -> Result<(), SetLoggerError> {
|
||||
let mut logger = RedoxLogger::new();
|
||||
let log_env = c"RELIBC_LOG_LEVEL".as_ptr();
|
||||
#[cfg(feature = "no_trace")]
|
||||
let mut trace_warn = false;
|
||||
unsafe {
|
||||
if let Some(env) = CStr::from_nullable_ptr(crate::header::stdlib::getenv(log_env))
|
||||
&& let Ok(level) = log::LevelFilter::from_str(env.to_str().unwrap_or(""))
|
||||
{
|
||||
#[cfg(feature = "no_trace")]
|
||||
if level == log::LevelFilter::Trace {
|
||||
trace_warn = true;
|
||||
}
|
||||
|
||||
logger = logger.with_output(OutputBuilder::stderr().with_filter(level).build());
|
||||
#[cfg(feature = "no_trace")]
|
||||
if level == log::LevelFilter::Trace {
|
||||
trace_warn = true;
|
||||
}
|
||||
|
||||
logger = logger.with_output(OutputBuilder::stderr().with_filter(level).build());
|
||||
|
||||
if let Some(name) = CStr::from_nullable_ptr(crate::platform::program_invocation_short_name)
|
||||
{
|
||||
logger = logger.with_process_name(name.to_str().unwrap_or("").to_string());
|
||||
}
|
||||
}
|
||||
if logger.enable().is_err() {
|
||||
log::error!("Logger already initialized");
|
||||
}
|
||||
|
||||
logger.enable()?;
|
||||
|
||||
#[cfg(feature = "no_trace")]
|
||||
if trace_warn {
|
||||
@@ -38,6 +35,8 @@ pub unsafe fn init() {
|
||||
"The 'no_trace' feature is enabled but RELIBC_LOG_LEVEL=TRACE, there will be no trace logs"
|
||||
);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Copied from redox_log crate with some modifications, in future we might use it instead?
|
||||
|
||||
@@ -172,7 +172,6 @@ pub(crate) unsafe fn create(
|
||||
new_tcb.masters_ptr = current_tcb.masters_ptr;
|
||||
new_tcb.masters_len = current_tcb.masters_len;
|
||||
new_tcb.linker_ptr = current_tcb.linker_ptr;
|
||||
new_tcb.mspace = current_tcb.mspace;
|
||||
|
||||
let stack_end = unsafe { stack_base.add(stack_size) };
|
||||
let mut stack = stack_end.cast::<usize>();
|
||||
|
||||
+28
-47
@@ -1,14 +1,13 @@
|
||||
//! Startup code.
|
||||
|
||||
use alloc::{boxed::Box, vec::Vec};
|
||||
use core::{intrinsics, ptr};
|
||||
use alloc::vec::Vec;
|
||||
use core::{intrinsics, ptr, str::FromStr};
|
||||
|
||||
use crate::{
|
||||
ALLOCATOR,
|
||||
c_str::CStr,
|
||||
header::{libgen, stdio, stdlib},
|
||||
ld_so::{self, linker::Linker},
|
||||
platform::{self, Pal, Sys, get_auxvs, types::*},
|
||||
sync::mutex::Mutex,
|
||||
ld_so::{self},
|
||||
platform::{self, Pal, Sys, get_auxvs, logger::RELIBC_LOG_ENV_VAR, types::*},
|
||||
};
|
||||
|
||||
#[repr(C)]
|
||||
@@ -89,26 +88,9 @@ static mut INIT_COMPLETE: bool = false;
|
||||
#[unsafe(no_mangle)]
|
||||
static mut __relibc_init_environ: *mut *mut c_char = ptr::null_mut();
|
||||
|
||||
fn alloc_init() {
|
||||
unsafe {
|
||||
if INIT_COMPLETE {
|
||||
return;
|
||||
}
|
||||
}
|
||||
unsafe {
|
||||
if let Some(tcb) = ld_so::tcb::Tcb::current()
|
||||
&& !tcb.mspace.is_null()
|
||||
{
|
||||
ALLOCATOR.set(tcb.mspace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" fn init_array() {
|
||||
// The thing is that we cannot guarantee if
|
||||
// init_array runs first or if relibc_start runs first
|
||||
// Still whoever gets to run first must initialize rust
|
||||
// memory allocator before doing anything else.
|
||||
|
||||
unsafe {
|
||||
if INIT_COMPLETE {
|
||||
@@ -116,15 +98,14 @@ extern "C" fn init_array() {
|
||||
}
|
||||
}
|
||||
|
||||
alloc_init();
|
||||
io_init();
|
||||
|
||||
unsafe {
|
||||
if platform::environ.is_null() {
|
||||
platform::environ = __relibc_init_environ;
|
||||
}
|
||||
}
|
||||
|
||||
io_init();
|
||||
|
||||
unsafe {
|
||||
crate::pthread::init();
|
||||
INIT_COMPLETE = true
|
||||
@@ -203,26 +184,14 @@ pub unsafe extern "C" fn relibc_start_v1(
|
||||
redox_rt::TLS_ACTIVATED.store(true, core::sync::atomic::Ordering::Relaxed);
|
||||
}
|
||||
|
||||
// Set up the right allocator...
|
||||
// if any memory rust based memory allocation happen before this step .. we are doomed.
|
||||
alloc_init();
|
||||
|
||||
if let Some(tcb) = unsafe { ld_so::tcb::Tcb::current() } {
|
||||
// Update TCB mspace
|
||||
if tcb.mspace.is_null() {
|
||||
tcb.mspace = ALLOCATOR.get();
|
||||
}
|
||||
|
||||
// Set linker pointer if necessary
|
||||
if tcb.linker_ptr.is_null() {
|
||||
//TODO: get ld path
|
||||
let linker = Linker::new(ld_so::linker::Config::default());
|
||||
//TODO: load root object
|
||||
tcb.linker_ptr = Box::into_raw(Box::new(Mutex::new(linker)));
|
||||
}
|
||||
let is_dynamically_linked = if let Some(tcb) = unsafe { ld_so::tcb::Tcb::current() } {
|
||||
#[cfg(target_os = "redox")]
|
||||
redox_rt::signal::setup_sighandler(&tcb.os_specific, true);
|
||||
}
|
||||
|
||||
!tcb.linker_ptr.is_null()
|
||||
} else {
|
||||
false
|
||||
};
|
||||
|
||||
// Set up argc and argv
|
||||
let argc = sp.argc;
|
||||
@@ -249,9 +218,21 @@ pub unsafe extern "C" fn relibc_start_v1(
|
||||
}
|
||||
|
||||
let auxvs = unsafe { get_auxvs(sp.auxv().cast()) };
|
||||
unsafe { crate::platform::init(auxvs) };
|
||||
init_array();
|
||||
unsafe { crate::platform::logger::init() };
|
||||
if !is_dynamically_linked {
|
||||
unsafe { crate::platform::init(auxvs) };
|
||||
init_array();
|
||||
}
|
||||
|
||||
if let Some(env) = unsafe {
|
||||
CStr::from_nullable_ptr(crate::header::stdlib::getenv(RELIBC_LOG_ENV_VAR.as_ptr()))
|
||||
} && let Ok(level) = log::LevelFilter::from_str(env.to_str().unwrap_or(""))
|
||||
{
|
||||
if let Err(_) = unsafe { crate::platform::logger::init(level) }
|
||||
&& !is_dynamically_linked
|
||||
{
|
||||
log::error!("Logger has already been initialised");
|
||||
}
|
||||
}
|
||||
|
||||
// Run preinit array
|
||||
{
|
||||
|
||||
+2
-1
@@ -44,7 +44,8 @@ run-once: $(BUILD)/bins_verify/relibc-tests $(BUILD)/$(TESTBIN) support_build
|
||||
$(BUILD)/bins_verify/relibc-tests: src/main.rs
|
||||
mkdir -p $(BUILD)/bins_verify
|
||||
RUSTFLAGS="-C target-feature=-crt-static" $(CARGO_TEST) build --release --bin relibc-tests \
|
||||
--artifact-dir $(BUILD)/bins_verify --target-dir $(BUILD)/target -Z unstable-options
|
||||
--artifact-dir $(BUILD)/bins_verify --target-dir $(BUILD)/target -Z unstable-options \
|
||||
--target $(TARGET)
|
||||
rm -rf $(BUILD)/target
|
||||
|
||||
$(BUILD)/Makefile: Makefile.run.mk
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
#include <assert.h>
|
||||
#include <signal.h>
|
||||
#include <setjmp.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include "test_helpers.h"
|
||||
#include <assert.h>
|
||||
#include <setjmp.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static sigjmp_buf jmpenv;
|
||||
|
||||
@@ -15,6 +15,7 @@ void alarm_handler(int sig) {
|
||||
int main() {
|
||||
struct sigaction sa;
|
||||
|
||||
sa.sa_flags = 0;
|
||||
sa.sa_handler = alarm_handler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
@@ -27,7 +28,7 @@ int main() {
|
||||
}
|
||||
|
||||
alarm(1);
|
||||
sleep(5);
|
||||
sleep(5);
|
||||
|
||||
assert(0); // unreachable
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user