diff --git a/repos/base/include/base/shared_object.h b/repos/base/include/base/shared_object.h new file mode 100644 index 000000000..68ff4ba94 --- /dev/null +++ b/repos/base/include/base/shared_object.h @@ -0,0 +1,97 @@ +/** + * \brief Dynamic linker interface + * \author Sebastian Sumpf + * \date 2014-10-09 + */ + +#ifndef _INCLUDE__BASE__SHARED_OBJECT_H_ +#define _INCLUDE__BASE__SHARED_OBJECT_H_ + +#include +#include + +namespace Genode { + class Shared_object; + struct Address_info; +}; + +class Genode::Shared_object +{ + private: + + void *_handle = nullptr; + + void *_lookup(const char *symbol) const; + + public: + + class Invalid_file : public Genode::Exception { }; + class Invalid_symbol : public Genode::Exception { }; + + enum open_flags { + NOW = 0x1, + LAZY = 0x2, + KEEP = 0x4, /* do not unload on destruction */ + }; + + /** + * Load shared object and dependencies + * + * \param file Shared object to load + * \param flags LAZY for lazy function binding, NOW for immediate binding + * + * \throw Invalid_file + */ + Shared_object(char const *file = nullptr, unsigned flags = LAZY); + + /** + * Close and unload shared object + */ + ~Shared_object(); + + /** + * Lookup a symbol in shared object and it's dependencies + * + * \param symbol Symbol name + * + * \throw Invalid_symbol + * + * \return Symbol address + */ + template T lookup(const char *symbol) const + { + return static_cast(_lookup(symbol)); + } + + /** + * Link information + */ + struct Link_map + { + Genode::addr_t addr; /* load address */ + char const *path; /* object path */ + void const *dynamic; /* pointer to DYNAMIC section */ + Link_map *next; + Link_map *prev; + }; + + /** + * Return link map of shared object + */ + Link_map const * link_map() const; +}; + + +struct Genode::Address_info +{ + char const *path; /* path of shared object */ + Genode::addr_t base; /* base of shared object */ + char const *name; /* name of symbol */ + Genode::addr_t addr; /* address of symbol */ + + class Invalid_address : public Genode::Exception { }; + + Address_info(Genode::addr_t addr); +}; + +#endif /* _INCLUDE__BASE__SHARED_OBJECT_H_ */ diff --git a/repos/base/lib/mk/arm/ld.mk b/repos/base/lib/mk/arm/ld.mk new file mode 100644 index 000000000..e189f7d5d --- /dev/null +++ b/repos/base/lib/mk/arm/ld.mk @@ -0,0 +1,6 @@ +REQUIRES = arm + +include $(REP_DIR)/lib/mk/ldso.inc + +INC_DIR += $(DIR)/arm +vpath %.s $(DIR)/arm diff --git a/repos/os/lib/mk/arm/ldso-startup.mk b/repos/base/lib/mk/arm/ldso-startup.mk similarity index 100% rename from repos/os/lib/mk/arm/ldso-startup.mk rename to repos/base/lib/mk/arm/ldso-startup.mk diff --git a/repos/os/lib/mk/ldso-startup.mk b/repos/base/lib/mk/ldso-startup.mk similarity index 100% rename from repos/os/lib/mk/ldso-startup.mk rename to repos/base/lib/mk/ldso-startup.mk diff --git a/repos/base/lib/mk/ldso.inc b/repos/base/lib/mk/ldso.inc new file mode 100644 index 000000000..ab0c2fa9a --- /dev/null +++ b/repos/base/lib/mk/ldso.inc @@ -0,0 +1,22 @@ +SHARED_LIB = yes +DIR = $(REP_DIR)/src/lib/ldso + +include $(BASE_DIR)/mk/base-libs.mk + +LIBS = $(BASE_LIBS) +SRC_CC = main.cc test.cc file.cc +SRC_S = jmp_slot.s +INC_DIR += $(DIR)/include +LD_OPT += -Bsymbolic-functions --version-script=$(DIR)/symbol.map +ENTRY_POINT = _start + +ifneq ($(filter linux, $(SPECS)),) +LD_OPT += -T$(call select_from_repositories,src/platform/context_area.nostdlib.ld) +else +LD_OPT += -T$(DIR)/linker.ld +endif + +vpath %.cc $(DIR) + +# vi:ft=make + diff --git a/repos/base/lib/mk/x86_32/ld.mk b/repos/base/lib/mk/x86_32/ld.mk new file mode 100644 index 000000000..4c99f61e2 --- /dev/null +++ b/repos/base/lib/mk/x86_32/ld.mk @@ -0,0 +1,6 @@ +REQUIRES = x86 32bit + +include $(REP_DIR)/lib/mk/ldso.inc + +INC_DIR += $(DIR)/x86_32 +vpath %.s $(DIR)/x86_32 diff --git a/repos/base/lib/mk/x86_64/ld.mk b/repos/base/lib/mk/x86_64/ld.mk new file mode 100644 index 000000000..e11a925b7 --- /dev/null +++ b/repos/base/lib/mk/x86_64/ld.mk @@ -0,0 +1,6 @@ +REQUIRES = x86 64bit + +include $(REP_DIR)/lib/mk/ldso.inc + +INC_DIR += $(DIR)/x86_64 +vpath %.s $(DIR)/x86_64 diff --git a/repos/base/mk/lib.mk b/repos/base/mk/lib.mk index d51d7a175..1683d34ff 100644 --- a/repos/base/mk/lib.mk +++ b/repos/base/mk/lib.mk @@ -139,7 +139,7 @@ $(LIB_A): $(OBJECTS) # Don't link base libraries against shared libraries except for ld.lib.so # ifdef SHARED_LIB -ifneq ($(LIB),ld) +ifneq ($(LIB),$(DYNAMIC_LINKER)) override DEPS := $(filter-out $(BASE_LIBS:=.lib),$(DEPS)) endif endif @@ -173,7 +173,7 @@ USED_SO_FILES := $(foreach s,$(USED_SHARED_LIBS),$(LIB_CACHE_DIR)/$s/$s.lib.s # # Don't link ld libary against shared objects # -USED_SO_FILES := $(filter-out %ld.lib.so,$(USED_SO_FILES)) +USED_SO_FILES := $(filter-out %$(DYNAMIC_LINKER).lib.so,$(USED_SO_FILES)) # # Default entry point of shared libraries diff --git a/repos/os/src/lib/ldso/README b/repos/base/src/lib/ldso/README similarity index 54% rename from repos/os/src/lib/ldso/README rename to repos/base/src/lib/ldso/README index 10afb4688..73b47adaf 100644 --- a/repos/os/src/lib/ldso/README +++ b/repos/base/src/lib/ldso/README @@ -1,4 +1,4 @@ -This directory contains the port of the dynamic linker (ldso) from FreeBSD. +This directory contains Genode's dynamic linker (ldso) Usage @@ -11,14 +11,32 @@ declare 'SHARED_LIB = yes' in the library-description file. When doing so, a library, no special precautions are needed. The build system will automatically detect the use of shared libraries, concludes that the binary must be dynamically linked, and will use the correct linker script. When loading a -dynamically linked program, the dynamic linker 'lsdo' and all used shared +dynamically linked program, the dynamic linker 'ldso.lib.so' and all used shared objects must be loaded as well. +The linker can be configured through the '' node when loading a dynamic +binary. Currently there are to configurations options, 'ld_bind_now="yes"' +causes the linker to resolve all symbol references on program loading. +'ld_verbose="yes"' outputs library load informations before starting the +program. + +Configuration snippet: + +! +! +! +! +! +! + Debugging dynamic binaries with GDB stubs ----------------------------------------- +! # go to directory containing the binaries +! cd /bin +! ! # start GDB with binary to debug -! gdb +! gdb ! ! # break in main routine ! b main @@ -26,7 +44,7 @@ Debugging dynamic binaries with GDB stubs ! # inspect loaded shared libraries ! info sharedlibrary ! -! # load shared symbols of shared libaries +! # load shared symbols of shared libraries (if not already loaded) ! share ! ! # from here you can debug within libraries diff --git a/repos/base/src/lib/ldso/arm/jmp_slot.s b/repos/base/src/lib/ldso/arm/jmp_slot.s new file mode 100644 index 000000000..833e4e535 --- /dev/null +++ b/repos/base/src/lib/ldso/arm/jmp_slot.s @@ -0,0 +1,39 @@ +/** + * \brief Jump slot entry code for ARM platforms + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +.text +.globl _jmp_slot +.type _jmp_slot,%function +/* + * stack[0] = RA + * ip = &GOT[n+3] + * lr = &GOT[2] + */ +_jmp_slot: + + stmdb sp!,{r0-r4,sl,fp} + + /* retrieve relocation index */ + sub r1, ip, lr /* r1 = 4 * (n + 1) */ + sub r1, r1, #4 /* r1 = 4 * n */ + lsr r1, r1, #2 /* r1 = n */ + + ldr r0, [lr, #-4] /* obj pointer from PLOTGOT[1] */ + mov r4, ip /* safe got location */ + + bl jmp_slot /* call linker(obj, index) */ + + str r0, [r4] /* save symbol value in GOT */ + mov ip, r0 + ldmia sp!,{r0-r4,sl,fp,lr} /* restore the stack */ + mov pc, ip /* jump to symbol address */ diff --git a/repos/base/src/lib/ldso/arm/relocation.h b/repos/base/src/lib/ldso/arm/relocation.h new file mode 100644 index 000000000..fba36fb42 --- /dev/null +++ b/repos/base/src/lib/ldso/arm/relocation.h @@ -0,0 +1,118 @@ +/** + * \brief ARM specific relocations + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__ARM__RELOCATION_H_ +#define _INCLUDE__ARM__RELOCATION_H_ + +#include + +namespace Linker { + enum Reloc_types { + R_ABS32 = 2, + R_REL32 = 3, + R_COPY = 20, + R_GLOB_DAT = 21, + R_JMPSLOT = 22, + R_RELATIVE = 23, + }; + + class Reloc_non_plt; + + typedef Reloc_plt_generic Reloc_plt; + typedef Reloc_jmpslot_generic Reloc_jmpslot; + typedef Reloc_bind_now_generic Reloc_bind_now; +}; + + +class Linker::Reloc_non_plt : public Reloc_non_plt_generic +{ + private: + + void _rel32(Elf::Rel const *rel, Elf::Addr *addr) + { + Elf::Addr reloc_base; + Elf::Sym const *sym; + + if (!(sym = locate_symbol(rel->sym(), _dag, &reloc_base))) + return; + + /* S + A - P */ + *addr = reloc_base + sym->st_value - (Elf::Addr)addr + *addr; + trace("REL32", (unsigned long)addr, *addr, 0); + } + + void _glob_dat(Elf::Rel const *rel, Elf::Addr *addr, bool no_addend) + { + Elf::Addr reloc_base; + Elf::Sym const *sym; + + if (!(sym = locate_symbol(rel->sym(), _dag, &reloc_base))) + return; + + Elf::Addr addend = no_addend ? 0 : *addr; + + /* S + A */ + *addr = addend + reloc_base + sym->st_value; + trace("GLOB_DAT", (unsigned long)addr, *addr, 0); + } + + void _relative(Elf::Addr *addr) + { + /* + * This ommits the linker and the binary, the linker has relative + * relocations within its text-segment (e.g., 'initial_sp' and friends), which + * we cannot write to from here). + */ + if (_dag->obj->reloc_base()) + *addr += _dag->obj->reloc_base(); + } + + public: + + Reloc_non_plt(Dag const *dag, Elf::Rela const *, unsigned long) + : Reloc_non_plt_generic(dag) + { + PERR("LD: DT_RELA not supported"); + throw Incompatible(); + } + + Reloc_non_plt(Dag const *dag, Elf::Rel const *rel, unsigned long size, bool second_pass) + : Reloc_non_plt_generic(dag) + { + Elf::Rel const *end = rel + (size / sizeof(Elf::Rel)); + for (; rel < end; rel++) { + Elf::Addr *addr = (Elf::Addr *)(_dag->obj->reloc_base() + rel->offset); + + if (second_pass && rel->type() != R_GLOB_DAT) + continue; + + switch (rel->type()) { + + case R_REL32 : _rel32(rel, addr); break; + case R_COPY : _copy(rel, addr); break; + case R_ABS32 : + case R_GLOB_DAT: _glob_dat(rel, addr, second_pass); break; + case R_RELATIVE: _relative(addr); break; + default: + trace("UNKREL", rel->type(), 0, 0); + if (_dag->root) { + PWRN("LD: Unkown relocation %u", rel->type()); + throw Incompatible(); + } + break; + } + } + } +}; + +#endif /* _INCLUDE__ARM__RELOCATION_H_ */ diff --git a/repos/base/src/lib/ldso/file.cc b/repos/base/src/lib/ldso/file.cc new file mode 100644 index 000000000..8a523581e --- /dev/null +++ b/repos/base/src/lib/ldso/file.cc @@ -0,0 +1,307 @@ +/** + * \brief ELF loading/unloading support + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#include + +#include +#include +#include +#include + +char const *Linker::ELFMAG = "\177ELF"; + +using namespace Linker; +using namespace Genode; + +namespace Linker +{ + class Rm_area; + struct Elf_file; +} + +/** + * Managed dataspace for ELF files (singelton) + */ +class Linker::Rm_area : public Rm_connection +{ + private: + + /* size of dataspace */ + enum { RESERVATION = 160 * 1024 * 1024 }; + + addr_t _base; /* base address of dataspace */ + Allocator_avl _range; /* VM range allocator */ + + protected: + + Rm_area(addr_t base) + : Rm_connection(0, RESERVATION), _range(env()->heap()) + { + on_destruction(KEEP_OPEN); + + _base = (addr_t) env()->rm_session()->attach_at(dataspace(), base); + _range.add_range(base, RESERVATION); + } + + public: + + static Rm_area *r(addr_t base = 0) + { + /* + * The capabilities in this class become invalid when doing a + * fork in the noux environment. Hence avoid destruction of + * the singleton object as the destructor would try to access + * the capabilities also in the forked process. + */ + static bool constructed = 0; + static char placeholder[sizeof(Rm_area)]; + if (!constructed) { + construct_at(placeholder, base); + constructed = 1; + } + return reinterpret_cast(placeholder); + } + + /** + * Reserve VM region of 'size' at 'vaddr'. Allocate any free region if + * 'vaddr' is zero + */ + addr_t alloc_region(size_t size, addr_t vaddr = 0) + { + addr_t addr = vaddr; + + if (addr && (_range.alloc_addr(size, addr).is_error())) + throw Region_conflict(); + else if (!addr && _range.alloc_aligned(size, (void **)&addr, 12).is_error()) + throw Region_conflict(); + + return addr; + } + + void free_region(addr_t vaddr) { _range.free((void *)vaddr); } + + /** + * Overwritten from 'Rm_connection' + */ + Local_addr attach_at(Dataspace_capability ds, addr_t local_addr, + size_t size = 0, off_t offset = 0) { + return Rm_connection::attach_at(ds, local_addr - _base, size, offset); } + + /** + * Overwritten from 'Rm_connection' + */ + Local_addr attach_executable(Dataspace_capability ds, addr_t local_addr, + size_t size = 0, off_t offset = 0) { + return Rm_connection::attach_executable(ds, local_addr - _base, size, offset); } + + void detach(Local_addr local_addr) { + Rm_connection::detach((addr_t)local_addr - _base); } +}; + + +/** + * Map ELF files + */ +struct Linker::Elf_file : File +{ + Rom_connection rom; + Ram_dataspace_capability ram_cap[Phdr::MAX_PHDR]; + bool loaded; + Elf_file(char const *name, bool load = true) + : + rom(name), loaded(load) + { + load_phdr(); + + if (load) + load_segments(); + } + + virtual ~Elf_file() + { + if (loaded) + unload_segments(); + } + + /** + * Check if ELF is sane + */ + bool check_compat(Elf::Ehdr const *ehdr) + { + if (memcmp(ehdr, ELFMAG, SELFMAG) != 0) { + PERR("LD: binary is not an ELF"); + return false; + } + + if (ehdr->e_ident[EI_CLASS] != ELFCLASS) { + PERR("LD: support for 32/64-bit objects only"); + return false;; + } + + return true; + } + + /** + * Copy program headers and read entry point + */ + void load_phdr() + { + Elf::Ehdr *ehdr = (Elf::Ehdr *)env()->rm_session()->attach(rom.dataspace(), 0x1000); + + if (!check_compat(ehdr)) + throw Incompatible(); + + /* set entry point and program header information */ + phdr.count = ehdr->e_phnum; + entry = (Entry)ehdr->e_entry; + + /* copy program headers */ + addr_t header = (addr_t)ehdr + ehdr->e_phoff; + for (unsigned i = 0; i < phdr.count; i++, header += ehdr->e_phentsize) + memcpy(&phdr.phdr[i], (void *)header, ehdr->e_phentsize); + + env()->rm_session()->detach(ehdr); + + Phdr p; + loadable_segments(p); + /* start vaddr */ + start = trunc_page(p.phdr[0].p_vaddr); + Elf::Phdr *ph = &p.phdr[p.count - 1]; + /* size of lodable segments */ + size = round_page(ph->p_vaddr + ph->p_memsz) - start; + } + + /** + * Find PT_LOAD segemnts + */ + void loadable_segments(Phdr &result) + { + for (unsigned i = 0; i < phdr.count; i++) { + Elf::Phdr *ph = &phdr.phdr[i]; + + if (ph->p_type != PT_LOAD) + continue; + + if (ph->p_align & (0x1000 - 1)) { + PERR("LD: Unsupported alignment %p", (void *)ph->p_align); + throw Incompatible(); + } + + result.phdr[result.count++] = *ph; + } + } + + bool is_rx(Elf::Phdr const &ph) { + return ((ph.p_flags & PF_MASK) == (PF_R | PF_X)); } + + bool is_rw(Elf::Phdr const &ph) { + return ((ph.p_flags & PF_MASK) == (PF_R | PF_W)); } + + /** + * Load PT_LOAD segments + */ + void load_segments() + { + Phdr p; + + /* search for PT_LOAD */ + loadable_segments(p); + + /* allocate region */ + reloc_base = Rm_area::r(start)->alloc_region(size, start); + reloc_base = (start == reloc_base) ? 0 : reloc_base; + + if (verbose_loading) + PDBG("reloc_base: " EFMT " start: " EFMT " end: " EFMT, + reloc_base, start, reloc_base + start + size); + + for (unsigned i = 0; i < p.count; i++) { + Elf::Phdr *ph = &p.phdr[i]; + + if (is_rx(*ph)) + load_segment_rx(*ph); + + else if (is_rw(*ph)) + load_segment_rw(*ph, i); + + else { + PERR("LD: Non-RW/RX segment"); + throw Invalid_file(); + } + } + } + + /** + * Map read-only segment + */ + void load_segment_rx(Elf::Phdr const &p) + { + Rm_area::r()->attach_executable(rom.dataspace(), + trunc_page(p.p_vaddr) + reloc_base, + round_page(p.p_memsz), + trunc_page(p.p_offset)); + } + + /** + * Copy read-write segment + */ + void load_segment_rw(Elf::Phdr const &p, int nr) + { + void *src = env()->rm_session()->attach(rom.dataspace(), 0, p.p_offset); + addr_t dst = p.p_vaddr + reloc_base; + + ram_cap[nr] = env()->ram_session()->alloc(p.p_memsz); + Rm_area::r()->attach_at(ram_cap[nr], dst); + + memcpy((void*)dst, src, p.p_filesz); + + /* clear if file size < memory size */ + if (p.p_filesz < p.p_memsz) + memset((void *)(dst + p.p_filesz), 0, p.p_memsz - p.p_filesz); + + env()->rm_session()->detach(src); + } + + /** + * Unmap segements, RM regions, and free allocated dataspaces + */ + void unload_segments() + { + Phdr p; + loadable_segments(p); + + /* detach from RM area */ + for (unsigned i = 0; i < p.count; i++) + Rm_area::r()->detach(trunc_page(p.phdr[i].p_vaddr) + reloc_base); + + /* free region from RM area */ + Rm_area::r()->free_region(trunc_page(p.phdr[0].p_vaddr) + reloc_base); + + /* free ram of RW segments */ + for (unsigned i = 0; i < Phdr::MAX_PHDR; i++) + if (ram_cap[i].valid()) { + env()->ram_session()->free(ram_cap[i]); + } + } +}; + + +File const *Linker::load(char const *path, bool load) +{ + if (verbose_loading) + PDBG("loading: %s (PHDRS only: %s)", path, load ? "no" : "yes"); + + Elf_file *file = new(env()->heap()) Elf_file(Linker::file(path), load); + return file; +} + diff --git a/repos/base/src/lib/ldso/include/elf.h b/repos/base/src/lib/ldso/include/elf.h new file mode 100644 index 000000000..8df92968b --- /dev/null +++ b/repos/base/src/lib/ldso/include/elf.h @@ -0,0 +1,458 @@ +/** + * \brief ELF binary definitions + * \author Christian Helmuth + * \author Sebastian Sumpf + * \date 2014-05-16 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__ELF_H_ +#define _INCLUDE__ELF_H_ + + +#include + +namespace Linker { + + /* standard ELF types. */ + + /* type for a 16-bit quantity. */ + typedef genode_uint16_t Elf32_Half; + typedef genode_uint16_t Elf64_Half; + + /* types for signed and unsigned 32-bit quantities */ + typedef genode_uint32_t Elf32_Word; + typedef genode_int32_t Elf32_Sword; + typedef genode_uint32_t Elf64_Word; + typedef genode_int32_t Elf64_Sword; + + /* types for signed and unsigned 64-bit quantities */ + typedef genode_uint64_t Elf32_Xword; + typedef genode_int64_t Elf32_Sxword; + typedef genode_uint64_t Elf64_Xword; + typedef genode_int64_t Elf64_Sxword; + + /* type of addresses */ + typedef genode_uint32_t Elf32_Addr; + typedef genode_uint64_t Elf64_Addr; + + /* type of file offsets */ + typedef genode_uint32_t Elf32_Off; + typedef genode_uint64_t Elf64_Off; + + /* type for section indices, which are 16-bit quantities */ + typedef genode_uint16_t Elf32_Section; + typedef genode_uint16_t Elf64_Section; + + /* type for version symbol information */ + typedef Elf32_Half Elf32_Versym; + typedef Elf64_Half Elf64_Versym; + + /** + * Fields in the e_ident array of ELF file header The EI_* macros are indices + * into the array. The macros under each EI_* macro are the values the byte + * may have. + */ + enum { + EI_NIDENT = 16, /* size of e_ident array in ELF header */ + + EI_MAG0 = 0, /* file identification byte 0 index */ + ELFMAG0 = 0x7f, /* magic number byte 0 */ + + EI_MAG1 = 1, /* file identification byte 1 index */ + ELFMAG1 = 'E', /* magic number byte 1 */ + + EI_MAG2 = 2, /* file identification byte 2 index */ + ELFMAG2 = 'L', /* magic number byte 2 */ + + EI_MAG3 = 3, /* file identification byte 3 index */ + ELFMAG3 = 'F', /* magic number byte 3 */ + }; + + /** + * Conglomeration of the identification bytes, for easy testing as a word + */ + extern const char *ELFMAG; + + enum { + SELFMAG = 4, + + EI_CLASS = 4, /* file class byte index */ + ELFCLASSNONE = 0, /* invalid class */ + ELFCLASS32 = 1, /* 32-bit objects */ + ELFCLASS64 = 2, /* 64-bit objects */ + ELFCLASSNUM = 3, + + EI_DATA = 5, /* data encoding byte index */ + ELFDATANONE = 0, /* invalid data encoding */ + ELFDATA2LSB = 1, /* 2's complement, little endian */ + ELFDATA2MSB = 2, /* 2's complement, big endian */ + ELFDATANUM = 3, + + EI_ABIVERSION = 8, /* ABI version */ + + EI_PAD = 9, /* byte index of padding bytes */ + }; + + /** + * Legal values for e_type (object file type) + */ + enum { + ET_NONE = 0, /* no file type */ + ET_EXEC = 2, /* executable file */ + ET_DYN = 3, /* shared object file */ + }; + + /** + * Legal values for e_machine (architecture) + */ + enum { + EM_NONE = 0, /* no machine */ + EM_386 = 3, /* intel 80386 */ + }; + + /** + * Legal values for e_version (version) + */ + enum { + EV_NONE = 0, /* invalid ELF version */ + EV_CURRENT = 1, /* current version */ + EV_NUM = 2, + }; + + /** + * Legal values for p_type (segment type) + */ + enum { + PT_NULL = 0, /* program header table entry unused */ + PT_LOAD = 1, /* loadable program segment */ + PT_DYNAMIC = 2, /* dynamic linking information */ + PT_INTERP = 3, /* program interpreter */ + PT_NOTE = 4, /* auxiliary information */ + PT_SHLIB = 5, /* reserved */ + PT_PHDR = 6, /* entry for header table itself */ + PT_TLS = 7, /* thread-local storage segment */ + PT_NUM = 8, /* number of defined types */ + PT_LOOS = 0x60000000, /* start of OS-specific */ + PT_GNU_EH_FRAME = 0x6474e550, /* gcc .eh_frame_hdr segment */ + PT_GNU_STACK = 0x6474e551, /* indicates stack executability */ + PT_GNU_RELRO = 0x6474e552, /* read-only after relocation */ + PT_LOPROC = 0x70000000, /* first processor-specific type */ + PT_ARM_EXIDX = 0x70000001, /* location of exception tables */ + PT_HIPROC = 0x7fffffff, /* last processor-specific type */ + }; + + /** + * Legal values for p_flags (segment flags) + */ + enum { + PF_X = (1 << 0), /* segment is executable */ + PF_W = (1 << 1), /* segment is writable */ + PF_R = (1 << 2), /* segment is readable */ + PF_MASK = 0x7, + }; + + /** + * Tag value for Elf::Dyn + */ + enum D_tag + { + DT_NULL = 0, + DT_NEEDED = 1, /* dependend libraries */ + DT_PLTRELSZ = 2, /* size of PLT relocations */ + DT_PLTGOT = 3, /* processor dependent address */ + DT_HASH = 4, /* address of symbol hash table */ + DT_STRTAB = 5, /* string table */ + DT_SYMTAB = 6, /* address of symbol table */ + DT_RELA = 7, /* ELF relocation with addend */ + DT_RELASZ = 8, /* total size of RELA reolcations */ + DT_STRSZ = 10, /* size of string table */ + DT_INIT = 12, /* ctors */ + DT_REL = 17, /* address of Elf::Rel relocations */ + DT_RELSZ = 18, /* sizof Elf::Rel relocation */ + DT_PLTREL = 20, /* PLT relcation */ + DT_DEBUG = 21, /* debug structure location */ + DT_JMPREL = 23, /* address of PLT relocation */ + }; + + + /** + * Symbol table + */ + enum Symbol_table { + /* Termination symbol for hash chains */ + STN_UNDEF = 0, + + /* Bindings */ + STB_LOCAL = 0, /* local symbol */ + STB_WEAK = 2, /* weak symbol */ + + /* Types */ + STT_NOTYPE = 0, /* type unspecified */ + STT_OBJECT = 1, /* data */ + STT_FUNC = 2, /* function */ + + /* Section table index */ + SHN_UNDEF = 0, /* undefined */ + SHN_COMMON = 0xfff2, /* common data */ +}; + + +/******************************** + ** 32-Bit non-POD definitions ** + ********************************/ + + namespace Elf32 { + + typedef Elf32_Addr Addr; + typedef Elf32_Word Hashelt; + typedef Elf32_Word Size; + typedef Elf32_Half Half; + + /** + * The ELF file header + */ + struct Ehdr + { + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ + }; + + + /** + * Program segment header + */ + struct Phdr + { + Elf32_Word p_type; /* segment type */ + Elf32_Off p_offset; /* segment file offset */ + Elf32_Addr p_vaddr; /* segment virtual address */ + Elf32_Addr p_paddr; /* segment physical address */ + Elf32_Word p_filesz; /* segment size in file */ + Elf32_Word p_memsz; /* segment size in memory */ + Elf32_Word p_flags; /* segment flags */ + Elf32_Word p_align; /* segment alignment */ + }; + + /** + * Dynamic structure (section .dynamic) + */ + struct Dyn + { + Elf32_Sword tag; /* entry type */ + union { + Elf32_Word val; /* integer value */ + Elf32_Addr ptr; /* address value */ + } un; + }; + + /** + * Relocation + */ + struct Rel + { + Elf32_Addr offset; /* location to be relocated */ + Elf32_Word info; /* relocation type and symbol index */ + + /** + * Relocation type + */ + int type() const { return info & 0xff; } + + /** + * Symbol table index + */ + unsigned sym() const { return info >> 8; } + }; + + /** + * Relocations that need an addend field + */ + struct Rela + { + Elf32_Addr r_offset; /* location to be relocated */ + Elf32_Word r_info; /* relocation type and symbol index */ + Elf32_Sword r_addend; /* addend */ + }; + + /** + * Symbol table entry + */ + struct Sym + { + Elf32_Word st_name; /* string table index of name */ + Elf32_Addr st_value; /* symbol value */ + Elf32_Word st_size; /* size of associated object */ + unsigned char st_info; /* type and binding information */ + unsigned char st_other; /* reserved (not used) */ + Elf32_Half st_shndx; /* section index of symbol */ + + /** + * Binding information + */ + unsigned char bind() const { return st_info >> 4; } + + /** + * Type information + */ + unsigned char type() const { return st_info & 0xf; } + + /** + * Check for weak symbol + */ + bool weak() const { return bind() == STB_WEAK; } + }; + } + + +/******************************** + ** 64-Bit non-POD definitions ** + ********************************/ + + namespace Elf64 { + + typedef Elf64_Addr Addr; + typedef Elf64_Word Hashelt; + typedef Elf64_Xword Size; + typedef Elf64_Half Half; + + /** + * ELF header + */ + struct Ehdr + { + unsigned char e_ident[EI_NIDENT]; /* magic number and other info */ + Elf64_Half e_type; /* object file type */ + Elf64_Half e_machine; /* architecture */ + Elf64_Word e_version; /* object file version */ + Elf64_Addr e_entry; /* entry point virtual address */ + Elf64_Off e_phoff; /* program header table file offset */ + Elf64_Off e_shoff; /* section header table file offset */ + Elf64_Word e_flags; /* processor-specific flags */ + Elf64_Half e_ehsize; /* eLF header size in bytes */ + Elf64_Half e_phentsize; /* program header table entry size */ + Elf64_Half e_phnum; /* program header table entry count */ + Elf64_Half e_shentsize; /* section header table entry size */ + Elf64_Half e_shnum; /* section header table entry count */ + Elf64_Half e_shstrndx; /* section header string table index */ + }; + + /** + * Program header + */ + struct Phdr + { + Elf64_Word p_type; /* segment type */ + Elf64_Word p_flags; /* segment flags */ + Elf64_Off p_offset; /* segment file offset */ + Elf64_Addr p_vaddr; /* segment virtual address */ + Elf64_Addr p_paddr; /* segment physical address */ + Elf64_Xword p_filesz; /* segment size in file */ + Elf64_Xword p_memsz; /* segment size in memory */ + Elf64_Xword p_align; /* segment alignment */ + }; + + /** + * Dynamic structure (section .dynamic) + */ + struct Dyn + { + Elf64_Sxword tag; /* entry type. */ + union + { + Elf64_Xword val; /* integer value. */ + Elf64_Addr ptr; /* address value. */ + } un; + }; + + /** + * Relocation + */ + struct Rel + { + Elf64_Addr r_offset; /* location to be relocated. */ + Elf64_Xword r_info; /* relocation type and symbol index. */ + }; + + /** + * Relocations that need an addend field + */ + struct Rela + { + Elf64_Addr offset; /* location to be relocated */ + Elf64_Xword info; /* relocation type and symbol index */ + Elf64_Sxword addend; /* addend */ + + /** + * Relocation type + */ + int type() const { return info & 0xffffffffL; } + + /** + * Symbol table index + */ + unsigned sym() const { return (info >> 16) >> 16; } + }; + + /** + * Symbol table entry + */ + struct Sym + { + Elf64_Word st_name; /* string table index of name */ + unsigned char st_info; /* type and binding information */ + unsigned char st_other; /* reserved (not used) */ + Elf64_Half st_shndx; /* section index of symbol */ + Elf64_Addr st_value; /* symbol value */ + Elf64_Xword st_size; /* size of associated object */ + + /** + * Binding information + */ + unsigned char bind() const { return st_info >> 4; } + + /** + * Type information + */ + unsigned char type() const { return st_info & 0xf; } + + /** + * Check for weak symbol + */ + bool weak() const { return bind() == STB_WEAK; } + }; + } /* namespace Elf64 */ +} /* namespace Linker" */ + +/** + * Define bit-width independent types + */ +#ifdef __x86_64__ +namespace Elf = Linker::Elf64; +#define ELFCLASS ELFCLASS64 +#define EFMT "%llx" +#else +namespace Elf = Linker::Elf32; +#define ELFCLASS ELFCLASS32 +#define EFMT "%x" +#endif /* _LP64 */ + +#endif /* _INCLUDE__ELF_H_ */ diff --git a/repos/base/src/lib/ldso/include/linker.h b/repos/base/src/lib/ldso/include/linker.h new file mode 100644 index 000000000..bf378e076 --- /dev/null +++ b/repos/base/src/lib/ldso/include/linker.h @@ -0,0 +1,230 @@ +/** + * \brief Generic linker definitions + * \author Sebastian Sumpf + * \date 2014-10-24 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__LINKER_H_ +#define _INCLUDE__LINKER_H_ + +#include +#include +#include +#include +#include +#include +#include + +/** + * Debugging + */ +constexpr bool verbose_lookup = false; +constexpr bool verbose_link_map = false; +constexpr bool verbose_relocation = false; +constexpr bool verbose_exception = false; +constexpr bool verbose_shared = false; +constexpr bool verbose_loading = false; + +/** + * Forward declartions and helpers + */ +namespace Linker +{ + class Object; + struct Phdr; + struct File; + struct Root_object; + struct Dag; + struct Elf_object; + + /** + * Find symbol via index + * + * \param sym_index Symbol index within object + * \param dag Directed acyclic graph of object + * \param base Returned address of symbol + * \param undef True, return undefined symbol; False return defined + * symbols only + * \param other True, search for symbol in other objects; False, search + * for symbol in given object as well. + * + * \throw Not_found Symbol not found + * + * \return Symbol information + */ + Elf::Sym const *locate_symbol(unsigned sym_index, Dag const *, Elf::Addr *base, + bool undef = false, bool other = false); + + + /** + * Find symbol via name + * + * \param name Symbol name + * \param dag Directed acyclic graph of object + * \param base Returned address of symbol + * \param undef True, return undefined symbol; False return defined + * symbols only + * \param other True, search for symbol in other objects; False, search + * for symbol in given object as well. + * + * \throw Not_found Symbol not found + * + * \return Symbol information + */ + Elf::Sym const *search_symbol(char const *name, Dag const *dag, Elf::Addr *base, + bool undef = false, bool other = false); + + /** + * Load object + * + * \param path Path of object + * \param load True, load binary; False, load ELF header only + * + * \throw Invalid_file Segment is neither read-only/executable or read/write + * \throw Region_conflict There is already something at the given address + * \throw Incompatible Not an ELF + * + * \return File descriptor + */ + File const *load(char const *path, bool load = true); + + /** + * Exceptions + */ + class Incompatible : Genode::Exception { }; + class Invalid_file : Genode::Exception { }; + class Not_found : Genode::Exception { }; + + /** + * Page handling + */ + template + static inline T trunc_page(T addr) { + return addr & Genode::_align_mask((T)12); } + + template + static inline T round_page(T addr) { + return Genode::align_addr(addr, (T)12); } + + /** + * Extract file name from path + */ + inline char const *file(char const *path) + { + /* strip directories */ + char const *f, *r = path; + for (f = r; *f; f++) + if (*f == '/') + r = f + 1; + return r; + } + + /** + * Invariants + */ + constexpr char const *binary_name() { return "binary"; } + constexpr char const *linker_name() { return "ld.lib.so"; } +} + + +struct Linker::Phdr +{ + enum { MAX_PHDR = 10 }; + + Elf::Phdr phdr[MAX_PHDR]; + unsigned count = 0; +}; + + +struct Linker::File +{ + typedef void (*Entry)(void); + + Phdr phdr; + Entry entry; + Elf::Addr reloc_base = 0; + Elf::Addr start = 0; + Elf::Size size = 0; + + virtual ~File() { } + + Elf::Phdr const *elf_phdr(unsigned index) const + { + if (index < phdr.count) + return &phdr.phdr[index]; + + return 0; + } + + unsigned elf_phdr_count() const { return phdr.count; } + +}; + + +class Linker::Object : public Genode::Fifo::Element +{ + protected: + + enum { MAX_PATH = 128 }; + + char _name[MAX_PATH]; + File const *_file = nullptr; + + public: + + Object() { } + Object(char const *path, File const *file) + : _file(file) + { + Genode::strncpy(_name, Linker::file(path), MAX_PATH); + } + + virtual ~Object() + { + if (_file) + destroy(Genode::env()->heap(), const_cast(_file)); + } + + Elf::Addr reloc_base() const { return _file ? _file->reloc_base : 0; } + char const *name() const { return _name; } + + File const *file() { return _file; } + + virtual bool is_linker() const = 0; + virtual bool is_binary() const = 0; + + Elf::Size const size() const { return _file ? _file->size : 0; } +}; + + +struct Linker::Dag : Genode::Fifo::Element +{ + Object *obj = nullptr; + Root_object *root = nullptr; + + Dag(Object *obj, Root_object *root) : obj(obj), root(root) { } + + Dag(char const *path, Root_object *root, Genode::Fifo * const dag, + unsigned flags = 0); + ~Dag(); + + void load_needed(Genode::Fifo * const dag, unsigned flags = 0); + bool in_dag(char const *file, Genode::Fifo *const dag); +}; + + +static inline bool verbose_reloc(Linker::Dag const *d) +{ + return d->root && verbose_relocation; +} + +extern "C" void _jmp_slot(void); + +#endif /* _INCLUDE__LINKER_H_ */ diff --git a/repos/base/src/lib/ldso/include/relocation_generic.h b/repos/base/src/lib/ldso/include/relocation_generic.h new file mode 100644 index 000000000..b5853ebbe --- /dev/null +++ b/repos/base/src/lib/ldso/include/relocation_generic.h @@ -0,0 +1,176 @@ +/** + * \brief Generic relocation classes + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__RELOCATION_GENERIC_H_ +#define _INCLUDE__RELOCATION_GENERIC_H_ + +#include + +namespace Linker +{ + struct Plt_got; + template class Reloc_jmpslot_generic; + template struct Reloc_plt_generic; + template struct Reloc_bind_now_generic; + class Reloc_non_plt_generic; +} + + +/** + * Set 2nd and 3rd GOT entry (see: SYSTEM V APPLICATION BINARY INTERFACE + * Intel386 Architecture Processor Supplement - 5.9 + */ +struct Linker::Plt_got +{ + Plt_got(Dag const *dag, Elf::Addr *pltgot) + { + if (verbose_relocation) + PDBG("OBJ: %s (%p)", dag->obj->name(), dag); + + pltgot[1] = (Elf::Addr) dag; /* ELF object */ + pltgot[2] = (Elf::Addr) &_jmp_slot; /* Linker entry */ + } +}; + + +/** + * PLT relocations + */ +template +struct Linker::Reloc_plt_generic +{ + Reloc_plt_generic(Object const *obj, D_tag const type, + Elf::Rel const *start, unsigned long size) + { + if (type != TYPE) { + PERR("LD: Unsupported PLT relocation type: %u", type); + throw Incompatible(); + } + + REL const *rel = (REL const *)start; + REL const *end = rel + (size / sizeof(REL)); + for (; rel < end; rel++) { + + if (rel->type() != JMPSLOT) { + PERR("LD: Unsupported PLT relocation %u", rel->type()); + throw Incompatible(); + } + + /* find relocation address and add relocation base */ + Elf::Addr *addr = (Elf::Addr *)(obj->reloc_base() + rel->offset); + *addr += obj->reloc_base(); + } + } +}; + + +class Linker::Reloc_non_plt_generic +{ + protected: + + Dag const *_dag; + + /** + * Copy relocations, these are just for the main program, we can do them + * safely here since all other DSO are loaded, relocated, and constructed at + * this point + */ + template + void _copy(REL const *rel, Elf::Addr *addr) + { + if (!_dag->obj->is_binary()) { + PERR("LD: Copy relocation in DSO (%s at %p)", _dag->obj->name(), addr); + throw Incompatible(); + } + + Elf::Sym const *sym; + Elf::Addr reloc_base; + + /* search symbol in other objects, do not return undefined symbols */ + if (!(sym = locate_symbol(rel->sym(), _dag, &reloc_base, false, true))) { + PWRN("LD: Symbol not found"); + return; + } + + Elf::Addr src = reloc_base + sym->st_value; + Genode::memcpy(addr, (void *)src, sym->st_size); + + if (verbose_relocation) + PDBG("Copy relocation: " EFMT " -> %p (0x" EFMT " bytes) val: " EFMT "\n", + src, addr, sym->st_size, sym->st_value); + } + + public: + + Reloc_non_plt_generic(Dag const *dag) : _dag(dag) { } +}; + + +/** + * Generic jmp slot handling + */ +template +class Linker::Reloc_jmpslot_generic +{ + Elf::Addr *_addr = 0; + + public: + + Reloc_jmpslot_generic(Dag const *dag, unsigned const type, Elf::Rel const* pltrel, + Elf::Size const index) + { + if (type != TYPE) { + PERR("LD: Unsupported JMP relocation type: %u", type); + throw Incompatible(); + } + + REL const *rel = &((REL *)pltrel)[index / (DIV ? sizeof(REL) : 1)]; + Elf::Sym const *sym; + Elf::Addr reloc_base; + + if (!(sym = locate_symbol(rel->sym(), dag, &reloc_base))) { + PWRN("LD: Symbol not found"); + return; + } + + /* write address of symbol to jump slot */ + _addr = (Elf::Addr *)(dag->obj->reloc_base() + rel->offset); + *_addr = reloc_base + sym->st_value; + + + if (verbose_relocation) { + PDBG("jmp: rbase " EFMT " s: %p sval: " EFMT, reloc_base, sym, sym->st_value); + PDBG("jmp_slot at %p -> " EFMT, _addr, *_addr); + } + } + + Elf::Addr target_addr() const { return *_addr; } +}; + + +/** + * Relocate jump slots immediately + */ +template +struct Linker::Reloc_bind_now_generic +{ + Reloc_bind_now_generic(Dag const *dag, Elf::Rel const *pltrel, unsigned long const size) + { + Elf::Size last_index = size / sizeof(REL); + + for (Elf::Size index = 0; index < last_index; index++) + Reloc_jmpslot_generic reloc(dag, TYPE, pltrel, index); + } +}; + +#endif /* _INCLUDE__RELOCATION_GENERIC_H_ */ diff --git a/repos/base/src/lib/ldso/include/trace.h b/repos/base/src/lib/ldso/include/trace.h new file mode 100644 index 000000000..c350b9bb0 --- /dev/null +++ b/repos/base/src/lib/ldso/include/trace.h @@ -0,0 +1,38 @@ +/** + * \brief Trace support for linker intialization + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__TRACE_H_ +#define _INCLUDE__TRACE_H_ + +#if 0 +typedef Genode::addr_t l4_umword_t; +typedef Genode::addr_t l4_addr_t; + +namespace Fiasco { + #include +} +#else +namespace Fiasco { + inline void fiasco_tbuf_log_3val(char const *,unsigned, unsigned, unsigned) { } +} +extern "C" void wait_for_continue(); +#endif + +namespace Linker { + inline void trace(char const *str, unsigned v1, unsigned v2, unsigned v3) + { + Fiasco::fiasco_tbuf_log_3val(str, v1, v2, v3); + } +} + +#endif /* _INCLUDE__TRACE_H_ */ diff --git a/repos/os/src/lib/ldso/ldso.ld b/repos/base/src/lib/ldso/linker.ld similarity index 92% rename from repos/os/src/lib/ldso/ldso.ld rename to repos/base/src/lib/ldso/linker.ld index 1f9c4ef54..ee5eef7b1 100644 --- a/repos/os/src/lib/ldso/ldso.ld +++ b/repos/base/src/lib/ldso/linker.ld @@ -13,6 +13,6 @@ SECTIONS { /* set ldso memory location */ - . = 0x30000 - SIZEOF_HEADERS; + . = 0x30000; } diff --git a/repos/base/src/lib/ldso/main.cc b/repos/base/src/lib/ldso/main.cc new file mode 100644 index 000000000..416cf135b --- /dev/null +++ b/repos/base/src/lib/ldso/main.cc @@ -0,0 +1,1193 @@ +/** + * \brief Genode's dynamic linker + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#include +#include +#include +#include +#include +#include + +#include + +using namespace Linker; + + +/** + * Offset of dynamic section of this ELF is filled out during linkage + */ +extern Genode::addr_t _DYNAMIC; + +/** + * Genode args to the 'main' function + */ +extern char **genode_argv; +extern int genode_argc; +extern char **genode_envp; + + +namespace Linker { + struct Dynamic; + struct Hash_table; + struct Ld; + struct Ld_vtable; + struct Binary; + struct Link_map; + struct Debug; + + typedef void (*Func)(void); +}; + +static bool bind_now = false; +static Binary *binary = 0; + +/** + * Registers dtors + */ +int genode_atexit(Linker::Func); + +/** + * LIBC debug support + */ +extern "C" void brk(Debug *, Link_map *) { } + +struct Linker::Debug +{ + /* + * This state value describes the mapping change taking place when + * the brk address is called. + */ + enum State { + CONSISTENT, /* mapping change is complete */ + ADD, /* beginning to add a new object */ + DELETE /* beginning to remove an object mapping */ + }; + + Debug() : Brk(brk) { } + + int version = 1; /* unused */ + struct Link_map *map = nullptr;; /* start of link map */ + + /* + * This is the address of a function internal to the run-time linker, that + * will always be called when the linker begins to map in a library or unmap + * it, and again when the mapping change is complete. The debugger can set a + * breakpoint at this address if it wants to notice shared object mapping + * changes. + */ + void (*Brk)(Debug *, Link_map *); + State state = CONSISTENT; + + static void state_change(State s, Link_map *m) + { + d()->state = s; + d()->Brk(d(), m); + } + + static Debug *d() + { + static Debug _d; + return &_d; + } +}; + + +/** + * Link map + */ +struct Linker::Link_map +{ + Elf::Addr addr; /* base address of library */ + char const *path; /* path */ + void const *dynamic; /* DYNAMIC section */ + + Link_map *next = nullptr; + Link_map *prev = nullptr; + + static Link_map *first; + + static void add(Link_map *map) + { + map->next = nullptr;; + if (!first) { + first = map; + Debug::d()->map = map; + return; + } + + Link_map *m; + for (m = first; m->next; m = m->next) ; + + m->next = map; + map->prev = m; + } + + static void remove(Link_map *map) + { + if (map->prev) + map->prev->next = map->next; + + if (map->next) + map->next->prev = map->prev; + + if (map == first) + first = map->next; + } + + static void dump() + { + if (!verbose_link_map) + return; + + for (Link_map *m = first; m; m = m->next) + PINF("MAP: addr: " EFMT " dynamic: %p %s m: %p p: %p n: %p", + m->addr, m->dynamic, m->path, m, m->prev, m->next); + } +}; + +Link_map *Link_map::first; + + +/** + * ELF hash table and hash function + */ +struct Linker::Hash_table +{ + unsigned long nbuckets() const { return *((Elf::Hashelt *)this); } + unsigned long nchains() const { return *(((Elf::Hashelt *)this) + 1); } + + Elf::Hashelt const *buckets() { return ((Elf::Hashelt *)this + 2); } + Elf::Hashelt const *chains() { return buckets() + nbuckets(); } + + /** + * ELF hash function Figure 5.12 of the 'System V ABI' + */ + static unsigned long hash(char const *name) + { + unsigned const char *p = (unsigned char const *)name; + unsigned long h = 0, g; + + while (*p) { + h = (h << 4) + *p++; + if ((g = h & 0xf0000000) != 0) + h ^= g >> 24; + h &= ~g; + } + return h; + } +}; + + +/** + * .dynamic section entries + */ +struct Linker::Dynamic +{ + struct Needed : Genode::Fifo::Element + { + Genode::off_t offset; + + Needed(Genode::off_t offset) : offset(offset) { } + + char const *path(char const *strtab) + { + return ((char const *)(strtab + offset)); + } + + char const *name(char const *strtab) + { + return file(path(strtab)); + } + }; + + Dag const *dag; + Object const *obj; + Elf::Dyn const *dynamic; + + Hash_table *hash_table = nullptr; + + Elf::Rela *reloca = nullptr; + unsigned long reloca_size = 0; + + Elf::Sym *symtab = nullptr; + char *strtab = nullptr; + unsigned long strtab_size = 0; + + Elf::Addr *pltgot = nullptr; + + Elf::Rel *pltrel = nullptr; + unsigned long pltrel_size = 0; + D_tag pltrel_type = DT_NULL; + + Func init_function = nullptr; + + Elf::Rel *rel = nullptr; + unsigned long rel_size = 0; + + Genode::Fifo needed; + + Dynamic(Dag const *dag) + : + dag(dag), obj(dag->obj), dynamic((Elf::Dyn *)(obj->reloc_base() + &_DYNAMIC)) + { + init(); + } + + Dynamic(Dag const *dag, Object const *obj, Linker::Phdr const *phdr) + : + dag(dag), obj(obj), dynamic(find_dynamic(phdr)) + { + init(); + } + + ~Dynamic() + { + Needed *n; + while ((n = needed.dequeue())) + destroy(Genode::env()->heap(), n); + } + + Elf::Dyn const *find_dynamic(Linker::Phdr const *p) + { + for (unsigned i = 0; i < p->count; i++) + if (p->phdr[i].p_type == PT_DYNAMIC) + return reinterpret_cast(p->phdr[i].p_vaddr + obj->reloc_base()); + + return 0; + } + + void section_dt_needed(Elf::Dyn const *d) + { + Needed *n = new(Genode::env()->heap()) Needed(d->un.ptr); + needed.enqueue(n); + } + + template + void section(T *member, Elf::Dyn const *d) + { + *member = (T)(obj->reloc_base() + d->un.ptr); + } + + void section_dt_debug(Elf::Dyn const *d) + { + Elf::Dyn *_d = const_cast(d); + _d->un.ptr = (Elf::Addr)Debug::d(); + } + + void init() + { + for (Elf::Dyn const *d = dynamic; d->tag != DT_NULL; d++) { + switch (d->tag) { + + case DT_NEEDED : section_dt_needed(d); break; + case DT_PLTRELSZ: pltrel_size = d->un.val; break; + case DT_PLTGOT : section(&pltgot, d); break; + case DT_HASH : section(&hash_table, d); break; + case DT_RELA : section(&reloca, d); break; + case DT_RELASZ : reloca_size = d->un.val; break; + case DT_SYMTAB : section(&symtab, d); break; + case DT_STRTAB : section(&strtab, d); break; + case DT_STRSZ : strtab_size = d->un.val; break; + case DT_INIT : section(&init_function, d); break; + case DT_PLTREL : pltrel_type = (D_tag)d->un.val; break; + case DT_JMPREL : section(&pltrel, d); break; + case DT_REL : section(&rel, d); break; + case DT_RELSZ : rel_size = d->un.val; break; + case DT_DEBUG : section_dt_debug(d); break; + default: + trace("DT", d->tag, 0, 0); + break; + } + } + } + + void relocate() + { + plt_setup(); + + if (pltrel_size) { + switch (pltrel_type) { + + case DT_RELA: + case DT_REL: + Reloc_plt(obj, pltrel_type, pltrel, pltrel_size); + break; + default: + PERR("LD: Invalid PLT relocation %u", pltrel_type); + throw Incompatible(); + } + } + + relocate_non_plt(); + } + + void plt_setup() + { + if (pltgot) + Plt_got r(dag, pltgot); + } + + void relocate_non_plt(bool second_pass = false) + { + if (reloca) + Reloc_non_plt r(dag, reloca, reloca_size); + + if (rel) + Reloc_non_plt r(dag, rel, rel_size, second_pass); + + if (bind_now) + Reloc_bind_now r(dag, pltrel, pltrel_size); + } +}; + + +static void register_initializer(Elf_object *elf); + +/** + * The actual ELF object, one per file + */ +struct Linker::Elf_object : Object, Genode::List::Element, + Genode::Fifo::Element +{ + Dynamic dynamic; + Link_map map; + unsigned ref_count = 1; + unsigned flags = 0; + + Elf_object(Dag const *dag) : dynamic(dag) + { } + + Elf_object(char const *path, Dag const *dag, unsigned flags = 0) + : + Object(path, Linker::load(Linker::file(path))), dynamic(dag, this, &_file->phdr), + flags(flags) + { + /* register for static construction and relocation */ + register_initializer(this); + obj_list()->enqueue(this); + + /* add to link map */ + Debug::state_change(Debug::ADD, nullptr); + setup_link_map(); + Debug::state_change(Debug::CONSISTENT, &map); + } + + virtual ~Elf_object() + { + if (!_file) + return; + + if (verbose_loading) + PDBG("destroy: %s", name()); + + /* remove from link map */ + Debug::state_change(Debug::DELETE, &map); + Link_map::remove(&map); + Debug::state_change(Debug::CONSISTENT, nullptr); + + /* remove from loaded objects list */ + obj_list()->remove(this); + } + + void setup_link_map() + { + map.addr = _file ? _file->start + reloc_base() : reloc_base(); + map.path = name(); + map.dynamic = (void *)dynamic.dynamic; + + Link_map::add(&map); + }; + + virtual void relocate() { dynamic.relocate(); } + + /** + * Return symbol of given number from ELF + */ + Elf::Sym const * symbol(unsigned sym_index) const + { + if (sym_index > dynamic.hash_table->nchains()) + return 0; + + return dynamic.symtab + sym_index; + } + + /** + * Return name of given symbol + */ + char const *symbol_name(Elf::Sym const *sym) const + { + return dynamic.strtab + sym->st_name; + } + + /** + * Lookup symbol name in this ELF + */ + Elf::Sym const * lookup_symbol(char const *name, unsigned long hash) const + { + Hash_table *h = dynamic.hash_table; + + if (!h->buckets()) + return 0; + + unsigned long sym_index = h->buckets()[hash % h->nbuckets()]; + + /* traverse hash chain */ + for (; sym_index != STN_UNDEF; sym_index = h->chains()[sym_index]) + { + /* bad object */ + if (sym_index > h->nchains()) + return 0; + + Elf::Sym const *sym = symbol(sym_index); + char const *sym_name = symbol_name(sym); + + /* this omitts everything but 'NOTYPE', 'OBJECT', and 'FUNC' */ + if (sym->type() > STT_FUNC) + continue; + + if (sym->st_value == 0) + continue; + + /* check for symbol name */ + if (name[0] != sym_name[0] || Genode::strcmp(name, sym_name)) + continue; + + return sym; + } + + return 0; + } + + /** + * Search for symbol at addr + */ + void info(Genode::addr_t addr, Genode::Address_info &info) const + { + info.path = name(); + info.base = map.addr; + info.addr = 0; + + Hash_table *h = dynamic.hash_table; + + for (unsigned long sym_index = 0; sym_index < h->nchains(); sym_index++) + { + Elf::Sym const *sym = symbol(sym_index); + + /* skip */ + if (sym->st_shndx == SHN_UNDEF || sym->st_shndx == SHN_COMMON) + continue; + + Genode::addr_t sym_addr = reloc_base() + sym->st_value; + if (sym_addr > addr || sym_addr < info.addr) + continue; + + info.addr = sym_addr; + info.name = symbol_name(sym); + + if (info.addr == addr) + break; + } + + if (!info.addr) + throw Genode::Address_info::Invalid_address(); + } + + Elf_object *init_next() const + { + return Genode::List::Element::next(); + } + + + Elf_object *obj_next() const + { + return Genode::Fifo::Element::next(); + } + + static Genode::Fifo *obj_list() + { + static Genode::Fifo _list; + return &_list; + } + + static Elf_object *find_obj(Genode::addr_t addr) + { + for (Elf_object *e = obj_list()->head(); e; e = e->obj_next()) + if (addr >= e->map.addr && addr < e->map.addr + e->size()) + return e; + + throw Genode::Address_info::Invalid_address(); + } + + static Elf_object *load(char const *path, Dag *dag, unsigned flags = 0) + { + for (Elf_object *e = obj_list()->head(); e; e = e->obj_next()) { + + if (verbose_loading) + PDBG("LOAD: %s == %s", Linker::file(path), e->name()); + + if (!Genode::strcmp(Linker::file(path), e->name())) { + e->ref_count++; + return e; + } + } + + Elf_object *e = new (Genode::env()->heap()) Elf_object(path, dag, flags); + dag->obj = e; + return e; + } + + bool unload() { return !(--ref_count) && !(flags & Genode::Shared_object::KEEP); } + + static Genode::Lock & lock() + { + static Genode::Lock _lock; + return _lock; + } + + + Elf::Phdr const *phdr_exidx() const + { + for (unsigned i = 0; i < _file->elf_phdr_count(); i++) { + Elf::Phdr const *ph = _file->elf_phdr(i); + + if (ph->p_type == PT_ARM_EXIDX) + return ph; + } + + return 0; + } + + bool is_linker() const override { return false; } + bool is_binary() const override { return false; } +}; + + +/** + * Handle static construction and relocation of ELF files + */ +struct Init : Genode::List +{ + static Init *list() + { + static Init _list; + return &_list; + } + + Elf_object *contains(char const *file) + { + for (Elf_object *e = first(); e; e = e->init_next()) + if (!Genode::strcmp(file, e->name())) + return e; + + return nullptr; + } + + void reorder(Elf_object const *elf) + { + /* put in front of initializer list */ + remove(elf); + insert(elf); + + /* re-order dependencies */ + for (Dynamic::Needed *n = elf->dynamic.needed.head(); n; n = n->next()) { + char const *path = n->path(elf->dynamic.strtab); + Elf_object *e; + + if ((e = contains(Linker::file(path)))) + reorder(e); + } + } + + void initialize() + { + Elf_object *obj = first(); + + /* relocate */ + for (; obj; obj = obj->init_next()) { + if (verbose_relocation) + PDBG("Relocate %s", obj->name()); + obj->relocate(); + } + + /* call static constructors */ + obj = first(); + while (obj) { + + if (obj->dynamic.init_function) { + + if (verbose_relocation) + PDBG("%s init func %p", obj->name(), obj->dynamic.init_function); + + obj->dynamic.init_function(); + } + + Elf_object *next = obj->init_next(); + remove(obj); + obj = next; + } + } +}; + + +void register_initializer(Elf_object *elf) +{ + Init::list()->insert(elf); +} + + +/** + * Dag node + */ +Linker::Dag::Dag(char const *path, Root_object *root, Genode::Fifo * const dag, unsigned flags) + : obj(Elf_object::load(path, this, flags)), root(root) +{ + dag->enqueue(this); + load_needed(dag, flags); +} + + +Linker::Dag::~Dag() +{ + if ((static_cast(obj))->unload()) { + + if (verbose_loading) + PDBG("Destroy: %s\n", obj->name()); + + destroy(Genode::env()->heap(), obj); + } +} + + +bool Linker::Dag::in_dag(char const *file, Genode::Fifo * const dag) +{ + for (Dag *d = dag->head(); d; d = d->next()) + if (!Genode::strcmp(file, d->obj->name())) + return true; + + return false; +} + + +void Linker::Dag::load_needed(Genode::Fifo * const dag, unsigned flags) +{ + Elf_object *elf = static_cast(obj); + + for (Dynamic::Needed *n = elf->dynamic.needed.head(); n; n = n->next()) { + char const *path = n->path(elf->dynamic.strtab); + Elf_object *e; + + if (!in_dag(Linker::file(path), dag)) + new (Genode::env()->heap()) Dag(path, root, dag, flags); + + /* re-order initializer list, if needed object has been already added */ + else if ((e = Init::list()->contains(Linker::file(path)))) + Init::list()->reorder(e); + } +} + + +/** + * The dynamic linker has its own ELF ojbect type + */ +struct Linker::Ld : Dag, Elf_object +{ + Ld() : Dag(this, nullptr), Elf_object(this) + { + Genode::strncpy(_name, linker_name(), Object::MAX_PATH); + + trace("LD", 0, 0, 0); + } + + void setup_link_map() + { + Elf_object::setup_link_map(); + + /** + * Use DT_HASH table address for linker, assuming that it will always be at + * the beginning of the file + */ + map.addr = trunc_page((Elf::Addr)dynamic.hash_table); + } + + void load_phdr() + { + _file = Linker::load(name(), false); + } + + void relocate_global() { dynamic.relocate_non_plt(true); } + void update_dag(Dag const *dag) { dynamic.dag = dag; } + + static Ld *linker(); + + bool is_linker() const override { return true; } + + /** + * Entry point for jump relocations, it is called from assembly + */ + static Elf::Addr jmp_slot(Dag const *dag, Elf::Size offset) asm("jmp_slot"); +}; + + +/** + * Ld object with different vtable typeinfo + */ +struct Linker::Ld_vtable : Ld +{ + Ld_vtable() + { + Elf_object::obj_list()->enqueue(this); + } +}; + + +Linker::Ld *Linker::Ld::linker() +{ + static Ld_vtable _linker; + return &_linker; +} + + +Elf::Addr Ld::jmp_slot(Dag const *dag, Elf::Size index) +{ + Elf_object const *obj = static_cast(dag->obj); + + Genode::Lock::Guard guard(Elf_object::lock()); + + if (verbose_relocation) + PDBG("SLOT %p " EFMT, obj, index); + + try { + Reloc_jmpslot slot(dag, obj->dynamic.pltrel_type, obj->dynamic.pltrel, index); + return slot.target_addr(); + } catch (...) { PERR("LD: Jump slot relocation failed. FATAL!"); } + + return 0; +} + + +struct Linker::Root_object +{ + Genode::Fifo dag; + + /* main root */ + Root_object() { }; + + /* runtime loaded root components */ + Root_object(char const *path, unsigned flags = 0) + { + new (Genode::env()->heap()) Dag(path, this, &dag, flags); + + /* provide Genode base library access */ + new (Genode::env()->heap()) Dag(linker_name(), this, &dag);; + + /* relocate and call constructors */ + Init::list()->initialize(); + } + + ~Root_object() + { + Dag *d; + while ((d = dag.dequeue())) + destroy(Genode::env()->heap(), d); + } + + Link_map const *link_map() const + { + Elf_object const *obj = static_cast(dag.head()->obj); + return obj ? &obj->map : 0; + } +}; + + +/** + * The program to load has its own ELF object type + */ +struct Linker::Binary : Root_object, Elf_object +{ + Binary() + : Elf_object(binary_name(), new (Genode::env()->heap()) Dag(this, this)) + { + /* create dag for binary and linker */ + Dag *binary = const_cast(dynamic.dag); + dag.enqueue(binary); + Dag *linker = new (Genode::env()->heap()) Dag(Ld::linker(), this); + dag.enqueue(linker); + + /* update linker dag */ + Ld::linker()->update_dag(linker); + + /* place linker on second place in link map as well */ + Ld::linker()->setup_link_map(); + + /* load dependencies */ + binary->load_needed(&dag); + + /* relocate and call constructors */ + Init::list()->initialize(); + } + + Elf::Addr lookup_symbol(char const *name) + { + Elf::Sym const *symbol = 0; + + if ((symbol = Elf_object::lookup_symbol(name, Hash_table::hash(name)))) + return reloc_base() + symbol->st_value; + + return 0; + } + + int call_entry_point() + { + /* call static construtors and register destructors */ + Func * const ctors_start = (Func *)lookup_symbol("_ctors_start"); + Func * const ctors_end = (Func *)lookup_symbol("_ctors_end"); + for (Func * ctor = ctors_end; ctor != ctors_start; (*--ctor)()); + + Func * const dtors_start = (Func *)lookup_symbol("_dtors_start"); + Func * const dtors_end = (Func *)lookup_symbol("_dtors_end"); + for (Func * dtor = dtors_start; dtor != dtors_end; genode_atexit(*dtor++)); + + /* call main function of the program */ + typedef int (*Main)(int, char **, char **); + Main const main = reinterpret_cast
(_file->entry); + + return main(genode_argc, genode_argv, genode_envp); + } + + void relocate() override + { + /* relocate ourselves */ + Elf_object::relocate(); + + /* + * After having loaded the main program, we relocate the linker's + * symbols again such that, for example type informations, which are + * also present within the main program, become relocated to the correct + * positions + */ + Ld::linker()->relocate_global(); + } + + bool is_binary() const override { return true; } +}; + + +/** + * This is called mostly from the relocation code + * XXX: 'undef' needs to be true for dlsym + */ +Elf::Sym const *Linker::locate_symbol(unsigned sym_index, Dag const *dag, Elf::Addr *base, bool undef, bool other) +{ + Elf_object const *e = static_cast(dag->obj); + Elf::Sym const *symbol = e->symbol(sym_index); + + if (!symbol) { + PWRN("LD: Unkown symbol index %x", sym_index); + return 0; + } + + if (symbol->bind() == STB_LOCAL) { + trace("NONLOCAL", symbol->bind(), 0, 0); + *base = dag->obj->reloc_base(); + return symbol; + } + + return search_symbol(e->symbol_name(symbol), dag, base, undef, other); +} + + +Elf::Sym const *Linker::search_symbol(char const *name, Dag const *dag, Elf::Addr *base, bool undef, bool other) +{ + Dag const *curr = dag->root ? dag->root->dag.head() : dag; + unsigned long hash = Hash_table::hash(name); + Elf::Sym const *weak_symbol = 0; + Elf::Addr weak_base = 0; + Elf::Sym const *symbol = 0; + + //TODO: handle vertab and search in object list + for (;curr; curr = curr->next()) { + + if (other && curr == dag) + continue; + + Elf_object const *elf = static_cast(curr->obj); + + if ((symbol = elf->lookup_symbol(name, hash)) && (symbol->st_value || undef)) { + + if (dag->root && verbose_lookup) + PINF("Lookup %s obj_src %s st %p info %x weak: %u", name, elf->name(), symbol, symbol->st_info, symbol->weak()); + + if (!undef && symbol->st_shndx == SHN_UNDEF) + continue; + + if (!symbol->weak() && symbol->st_shndx != SHN_UNDEF) { + *base = elf->reloc_base(); + return symbol; + } + + if (!weak_symbol) { + weak_symbol = symbol; + weak_base = elf->reloc_base(); + } + } + } + + /* try searching binary's DAG */ + if (!weak_symbol && dag->root && dag != binary->dag.head()) + return search_symbol(name, binary->dag.head(), base, undef, other); + + if (dag->root && verbose_lookup) + PDBG("Return %p", weak_symbol); + + if (!weak_symbol) + throw Not_found(); + + *base = weak_base; + return weak_symbol; +} + + +/** + * Called before anything else, even '_main', we cannot access any global data + * here, we have to relocate our own ELF first + */ +extern "C" void init_rtld() +{ + trace("init_rtld", 0, 0, 0); + + /* + * Allocate on stack, since the linker has not been relocated yet, the vtable + * type relocation might prdouce a wrong vtable pointer (at least on ARM), do + * not call any virtual funtions of this object + */ + Ld linker_stack; + linker_stack.relocate(); + + /* make sure this does not get destroyed the usual way */ + linker_stack.ref_count++; + + trace("init_rtld finished", 0, 0, 0); + + /* + * Create actual linker object with different vtable type and set PLT to new + * DAG. + */ + Ld::linker()->dynamic.plt_setup(); +} + + +/** + * "Walk through shared objects" support, see man page of 'dl_iterate_phdr' + */ +struct Phdr_info +{ + Elf::Addr addr; /* module relocation base */ + char const *name; /* module name */ + Elf::Phdr const *phdr; /* pointer to module's phdr */ + Elf::Half phnum; /* number of entries in phdr */ +}; + + +extern "C" int dl_iterate_phdr(int (*callback) (Phdr_info *info, Genode::size_t size, void *data), void *data) +{ + int err = 0; + Phdr_info info; + + Genode::Lock::Guard guard(Elf_object::lock()); + + Elf_object *e = Elf_object::obj_list()->head(); + for (;e; e = e->obj_next()) { + + info.addr = e->reloc_base(); + info.name = e->name(); + info.phdr = e->file()->phdr.phdr; + info.phnum = e->file()->phdr.count; + + if (verbose_exception) + PDBG("%s reloc " EFMT, e->name(), e->reloc_base()); + + if ((err = callback(&info, sizeof(Phdr_info), data))) + break; + } + + return err; +} + + +/** + * Find ELF and exceptions table segment that that is located under 'pc', + * address of excption table and number of entries 'pcount' + */ +extern "C" unsigned long dl_unwind_find_exidx(unsigned long pc, int *pcount) +{ + /* size of exception table entries */ + enum { EXIDX_ENTRY_SIZE = 8 }; + *pcount = 0; + + /* + * Since this function may be called before the main function, load linker's + * program header now + */ + if (!Ld::linker()->file()) + Ld::linker()->load_phdr(); + + Elf_object *e = Elf_object::obj_list()->head(); + for (; e; e = e->obj_next()) + { + /* address of first PT_LOAD header */ + Genode::addr_t base = e->reloc_base() + e->file()->start; + + /* is the 'pc' somewhere within this ELF image */ + if ((pc < base) || (pc >= base + e->file()->size)) + continue; + + /* retrieve PHDR of exception-table segment */ + Elf::Phdr const *exidx = e->phdr_exidx(); + if (!exidx) + continue; + + *pcount = exidx->p_memsz / EXIDX_ENTRY_SIZE; + return exidx->p_vaddr + e->reloc_base(); + } + + return 0; +} + + +/***************************** + ** Shared object interface ** + *****************************/ + +static Root_object *to_root(void *h) +{ + return static_cast(h); +} + + +Genode::Shared_object::Shared_object(char const *file, unsigned flags) +{ + using namespace Linker; + + if (verbose_shared) + PDBG("open '%s'", file ? file : "binary"); + + try { + Genode::Lock::Guard guard(Elf_object::lock()); + + /* update bind now variable */ + bind_now = (flags & Shared_object::NOW) ? true : false; + + _handle = (Root_object *)new (Genode::env()->heap()) Root_object(file ? file : binary_name(), flags); + } catch (...) { throw Invalid_file(); } +} + + +void *Genode::Shared_object::_lookup(const char *name) const +{ + using namespace Linker; + + if (verbose_shared) + PDBG("lookup '%s'", name); + + try { + Genode::Lock::Guard guard(Elf_object::lock()); + + Elf::Addr base; + Root_object *root = to_root(_handle); + Elf::Sym const *symbol = search_symbol(name, root->dag.head(), &base, true); + + return (void *)(base + symbol->st_value); + } catch (...) { throw Shared_object::Invalid_symbol(); } +} + + +Genode::Shared_object::Link_map const * Genode::Shared_object::link_map() const +{ + return (Link_map const *)to_root(_handle)->link_map(); +} + + +Genode::Shared_object::~Shared_object() +{ + using namespace Linker; + + if (verbose_shared) + PDBG("close"); + + Genode::Lock::Guard guard(Elf_object::lock()); + destroy(Genode::env()->heap(), to_root(_handle)); +} + + +Genode::Address_info::Address_info(Genode::addr_t address) +{ + using namespace Genode; + + if (verbose_shared) + PDBG("request: %lx", address); + + Elf_object *e = Elf_object::find_obj(address); + e->info(address, *this); + + if (verbose_shared) + PDBG("Found: obj: %s sym: %s addr: %lx", path, name, addr); +} + + +static void dump_loaded() +{ + Elf_object *o = Elf_object::obj_list()->head(); + for(; o; o = o->obj_next()) { + + if (o->is_binary()) + continue; + + Elf_object *e = static_cast(o); + Genode::printf(" " EFMT " .. " EFMT ": %s\n", + e->map.addr, e->map.addr + e->size() - 1, e->name()); + } +} + + +int main() +{ + /* load program headers of linker now */ + if (!Ld::linker()->file()) + Ld::linker()->load_phdr(); + + /* read configuration */ + try { + /* bind immediately */ + bind_now = Genode::config()->xml_node().attribute("ld_bind_now").has_value("yes"); + } catch (...) { } + + /* load binary and all dependencies */ + try { + binary = new(Genode::env()->heap()) Binary(); + } catch (...) { + PERR("LD: Failed to load program"); + return -1; + } + + /* print loaded object information */ + try { + if (Genode::config()->xml_node().attribute("ld_verbose").has_value("yes")) + dump_loaded(); + } catch (...) { } + + Link_map::dump(); + + /* start binary */ + return binary->call_entry_point(); +} + diff --git a/repos/os/src/lib/ldso/startup/startup.cc b/repos/base/src/lib/ldso/startup/startup.cc similarity index 100% rename from repos/os/src/lib/ldso/startup/startup.cc rename to repos/base/src/lib/ldso/startup/startup.cc diff --git a/repos/os/src/lib/ldso/startup/unwind_exidx.cc b/repos/base/src/lib/ldso/startup/unwind_exidx.cc similarity index 99% rename from repos/os/src/lib/ldso/startup/unwind_exidx.cc rename to repos/base/src/lib/ldso/startup/unwind_exidx.cc index 81b1bbc9c..d90a465bf 100644 --- a/repos/os/src/lib/ldso/startup/unwind_exidx.cc +++ b/repos/base/src/lib/ldso/startup/unwind_exidx.cc @@ -2,7 +2,7 @@ * \brief Our implementation of __gnu_Unwind_Find_exidx * \author Sebastian Sumpf * \date 2010-07-05 - * + * * This file is used for ARM-EABI dynamic linking, only. The ARM cross-compiler * uses this hook to locate a 'ARM.exidx' section within a shared object. For * this to work 'dl_unwind_find_exidx' is excuted by 'ldso', which returns the diff --git a/repos/os/src/lib/ldso/symbol.map b/repos/base/src/lib/ldso/symbol.map similarity index 89% rename from repos/os/src/lib/ldso/symbol.map rename to repos/base/src/lib/ldso/symbol.map index 1293e2316..578bcd3ef 100644 --- a/repos/os/src/lib/ldso/symbol.map +++ b/repos/base/src/lib/ldso/symbol.map @@ -23,19 +23,6 @@ }; __dynamic_cast; - /* - * Standard dl interface - */ - dlclose; - dlerror; - dlopen; - dlsym; - dlvsym; - dladdr; - dllockinit; - dlinfo; - dl_iterate_phdr; - /* * Debugging */ @@ -49,10 +36,6 @@ __ldso_raise_exception*; }; - /* - * Exceptions symbols - */ - /* GNU verbose terminate handler */ extern "C++" { __gnu_cxx::__verbose_terminate_handler*; }; @@ -67,6 +50,7 @@ _Unwind_DeleteException; _Unwind_Resume; __gxx_personality_v0; + dl_iterate_phdr; /* ARM */ __aeabi_*; diff --git a/repos/os/src/lib/ldso/test.cc b/repos/base/src/lib/ldso/test.cc similarity index 100% rename from repos/os/src/lib/ldso/test.cc rename to repos/base/src/lib/ldso/test.cc diff --git a/repos/base/src/lib/ldso/x86_32/jmp_slot.s b/repos/base/src/lib/ldso/x86_32/jmp_slot.s new file mode 100644 index 000000000..589a84e1a --- /dev/null +++ b/repos/base/src/lib/ldso/x86_32/jmp_slot.s @@ -0,0 +1,35 @@ +/** + * \brief Jump slot entry code for x86_32 + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +.text +.align 4 +.globl _jmp_slot +.type _jmp_slot,@function +_jmp_slot: + pushf + pushl %eax + pushl %edx + pushl %ecx + pushl 0x14(%esp) /* relocation index */ + pushl 0x14(%esp) /* obj pointer */ + + call jmp_slot@PLT + + addl $8, %esp /* remove arguments from call */ + movl %eax, 0x14(%esp) /* store synmbol value in obj pointer position */ + popl %ecx + popl %edx + popl %eax + popf + leal 0x4(%esp), %esp /* remove relocation index */ + ret /* return to symbol value */ diff --git a/repos/base/src/lib/ldso/x86_32/relocation.h b/repos/base/src/lib/ldso/x86_32/relocation.h new file mode 100644 index 000000000..251addcd9 --- /dev/null +++ b/repos/base/src/lib/ldso/x86_32/relocation.h @@ -0,0 +1,98 @@ +/** + * \brief x86_32 specific relocations + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _X86_32__RELOCATION_H_ +#define _X86_32__RELOCATION_H_ + +#include + +namespace Linker { + + enum Reloc_types { + R_32 = 1, + R_COPY = 5, + R_GLOB_DAT = 6, + R_JMPSLOT = 7, + R_RELATIVE = 8, + }; + + class Reloc_non_plt; + + typedef Reloc_plt_generic Reloc_plt; + typedef Reloc_jmpslot_generic Reloc_jmpslot; + typedef Reloc_bind_now_generic Reloc_bind_now; +} + + +class Linker::Reloc_non_plt : public Reloc_non_plt_generic +{ + private: + + void _glob_dat(Elf::Rel const *rel, Elf::Addr *addr, bool addend = false) + { + Elf::Addr reloc_base; + Elf::Sym const *sym; + + if (!(sym = locate_symbol(rel->sym(), _dag, &reloc_base))) + return; + + *addr = (addend ? *addr : 0) + reloc_base + sym->st_value; + trace("REL32", (unsigned long)addr, *addr, 0); + } + + void _relative(Elf::Rel const *rel, Elf::Addr *addr) + { + if (_dag->obj->reloc_base()) + *addr += _dag->obj->reloc_base(); + } + + public: + + Reloc_non_plt(Dag const *dag, Elf::Rela const *, unsigned long) + : Reloc_non_plt_generic(dag) + { + PERR("LD: DT_RELA not supported"); + trace("Non_plt", 0, 0, 0); + throw Incompatible(); + } + + Reloc_non_plt(Dag const *dag, Elf::Rel const *rel, unsigned long size, bool second_pass) + : Reloc_non_plt_generic(dag) + { + Elf::Rel const *end = rel + (size / sizeof(Elf::Rel)); + + for (; rel < end; rel++) { + Elf::Addr *addr = (Elf::Addr *)(_dag->obj->reloc_base() + rel->offset); + + if (second_pass && rel->type() != R_GLOB_DAT) + continue; + + switch (rel->type()) { + + case R_32 : _glob_dat(rel, addr, true); break; + case R_GLOB_DAT: _glob_dat(rel, addr); break; + case R_COPY : _copy(rel, addr); break; + case R_RELATIVE: _relative(rel, addr); break; + default: + trace("UNKREL", rel->type(), 0, 0); + if (_dag->root) { + PWRN("LD: Unkown relocation %u", rel->type()); + throw Incompatible(); + } + break; + } + } + } +}; + +#endif /* _X86_32__RELOCATION_H_ */ diff --git a/repos/base/src/lib/ldso/x86_64/jmp_slot.s b/repos/base/src/lib/ldso/x86_64/jmp_slot.s new file mode 100644 index 000000000..25ffb1fba --- /dev/null +++ b/repos/base/src/lib/ldso/x86_64/jmp_slot.s @@ -0,0 +1,52 @@ +/** + * \brief Jump slot entry code for x86_64 + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +.text +.align 4 +.globl _jmp_slot +.type _jmp_slot,@function +_jmp_slot: + subq $8, %rsp + pushfq + pushq %rax + pushq %rdx + pushq %rcx + pushq %rsi + pushq %rdi + pushq %r8 + pushq %r9 + pushq %r10 + pushq %r11 + + /* obj pointer */ + movq 0x58(%rsp), %rdi + /* relocation index */ + movq 0x60(%rsp), %rsi + + call jmp_slot@PLT + /* rax now contains target symbol address */ + movq %rax, 0x60(%rsp) + + popq %r11 + popq %r10 + popq %r9 + popq %r8 + popq %rdi + popq %rsi + popq %rcx + popq %rdx + popq %rax + popfq + leaq 16(%rsp), %rsp + + ret diff --git a/repos/base/src/lib/ldso/x86_64/relocation.h b/repos/base/src/lib/ldso/x86_64/relocation.h new file mode 100644 index 000000000..1b611888f --- /dev/null +++ b/repos/base/src/lib/ldso/x86_64/relocation.h @@ -0,0 +1,104 @@ +/** + * \brief x86_64 specific relocations + * \author Sebastian Sumpf + * \date 2014-10-26 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _INCLUDE__X86_64__RELOCATION_H_ +#define _INCLUDE__X86_64__RELOCATION_H_ + +#include + +namespace Linker { + +/** + * Relocation types + */ + enum Reloc_types { + R_64 = 1, /* add 64 bit symbol value. */ + R_COPY = 5, + R_GLOB_DAT = 6, /* GOT entry to data address */ + R_JMPSLOT = 7, /* jump slot */ + R_RELATIVE = 8, /* add load addr of shared object */ + }; + + class Reloc_non_plt; + + typedef Reloc_plt_generic Reloc_plt; + typedef Reloc_jmpslot_generic Reloc_jmpslot; + typedef Reloc_bind_now_generic Reloc_bind_now; +}; + +class Linker::Reloc_non_plt : public Reloc_non_plt_generic +{ + private: + /** + * Relative relocation (reloc base + addend) + */ + void _relative(Elf::Rela const *rel, Elf::Addr *addr) + { + trace("64", _dag->obj->reloc_base(), rel->addend, 0); + *addr = _dag->obj->reloc_base() + rel->addend; + } + + /** + * GOT entry to data address or 64 bit symbol (addend = true), + * (reloc base of containing ojbect + symbol value (+ addend) + */ + void _glob_dat_64(Elf::Rela const *rel, Elf::Addr *addr, bool addend) + { + Elf::Addr reloc_base; + Elf::Sym const *sym; + + if (!(sym = locate_symbol(rel->sym(), _dag, &reloc_base))) + return; + + *addr = reloc_base + sym->st_value + (addend ? rel->addend : 0); + if (verbose_reloc(_dag)) + PDBG("GLOB DAT %p -> %llx r %llx v %llx", addr, *addr, reloc_base, + sym->st_value); + } + + public: + + Reloc_non_plt(Dag const *dag, Elf::Rela const *rel, unsigned long size) + : Reloc_non_plt_generic(dag) + { + Elf::Rela const *end = rel + (size / sizeof(Elf::Rela)); + + for (; rel < end; rel++) { + Elf::Addr *addr = (Elf::Addr *)(_dag->obj->reloc_base() + rel->offset); + + switch(rel->type()) { + case R_64: _glob_dat_64(rel, addr, true); break; + case R_GLOB_DAT: _glob_dat_64(rel, addr, false); break; + case R_COPY: _copy(rel, addr); break; + case R_RELATIVE: _relative(rel, addr); break; + + default: + trace("UNKRELA", rel->type(), 0, 0); + if (!_dag->obj->is_linker()) { + PWRN("LD: Unkown relocation %u", rel->type()); + throw Incompatible(); + } + break; + } + } + } + + Reloc_non_plt(Dag const *dag, Elf::Rel const *, unsigned long, bool) + : Reloc_non_plt_generic(dag) + { + PERR("LD: DT_REL not supported"); + throw Incompatible(); + } +}; + +#endif /* _INCLUDE__X86_64__RELOCATION_H_ */ diff --git a/repos/os/src/platform/genode_dyn.dl b/repos/base/src/platform/genode_dyn.dl similarity index 100% rename from repos/os/src/platform/genode_dyn.dl rename to repos/base/src/platform/genode_dyn.dl diff --git a/repos/os/src/platform/genode_dyn.ld b/repos/base/src/platform/genode_dyn.ld similarity index 100% rename from repos/os/src/platform/genode_dyn.ld rename to repos/base/src/platform/genode_dyn.ld diff --git a/repos/os/src/platform/genode_rel.ld b/repos/base/src/platform/genode_rel.ld similarity index 99% rename from repos/os/src/platform/genode_rel.ld rename to repos/base/src/platform/genode_rel.ld index fb5f8b8ad..7400a3776 100644 --- a/repos/os/src/platform/genode_rel.ld +++ b/repos/base/src/platform/genode_rel.ld @@ -24,7 +24,6 @@ PHDRS SECTIONS { /* Read-only sections, merged into text segment: */ - . += SIZEOF_HEADERS; .note.gnu.build-id : { *(.note.gnu.build-id) } : ro .hash : { *(.hash) } .gnu.hash : { *(.gnu.hash) } diff --git a/repos/libports/lib/mk/libc.mk b/repos/libports/lib/mk/libc.mk index 961df7e54..e6fcd6f7c 100644 --- a/repos/libports/lib/mk/libc.mk +++ b/repos/libports/lib/mk/libc.mk @@ -14,7 +14,7 @@ SRC_CC = atexit.cc dummies.cc rlimit.cc sysctl.cc \ gettimeofday.cc malloc.cc progname.cc fd_alloc.cc file_operations.cc \ plugin.cc plugin_registry.cc select.cc exit.cc environ.cc nanosleep.cc \ libc_mem_alloc.cc pread_pwrite.cc readv_writev.cc poll.cc \ - libc_pdbg.cc vfs_plugin.cc rtc.cc + libc_pdbg.cc vfs_plugin.cc rtc.cc dynamic_linker.cc INC_DIR += $(REP_DIR)/src/lib/libc diff --git a/repos/libports/lib/mk/test-ldso_lib_dl.mk b/repos/libports/lib/mk/test-ldso_lib_dl.mk new file mode 100644 index 000000000..fcefb2420 --- /dev/null +++ b/repos/libports/lib/mk/test-ldso_lib_dl.mk @@ -0,0 +1,5 @@ +SRC_CC = lib_dl.cc +SHARED_LIB = yes +LIBS = test-ldso_lib_1 +INC_DIR += $(REP_DIR)/src/test/ldso/include +vpath % $(REP_DIR)/src/test/ldso diff --git a/repos/os/run/ldso.run b/repos/libports/run/ldso.run similarity index 89% rename from repos/os/run/ldso.run rename to repos/libports/run/ldso.run index 6e4bdc1bc..eabba888f 100644 --- a/repos/os/run/ldso.run +++ b/repos/libports/run/ldso.run @@ -2,7 +2,7 @@ if {[have_spec always_hybrid]} { puts "Run script does not support hybrid Linux/Genode."; exit 0 } -build "core init test/ldso" +build "core init test/ldso test/ldso/dl" create_boot_directory @@ -18,7 +18,7 @@ install_config { - + @@ -27,7 +27,13 @@ install_config { } -build_boot_image "core init test-ldso test-ldso_lib_1.lib.so test-ldso_lib_2.lib.so libc.lib.so libm.lib.so ld.lib.so" +set boot_modules { + core init test-ldso test-ldso_lib_1.lib.so + test-ldso_lib_2.lib.so test-ldso_lib_dl.lib.so + ld.lib.so libc.lib.so libm.lib.so +} + +build_boot_image $boot_modules append qemu_args "-nographic -m 64" @@ -103,13 +109,19 @@ compare_output_to { [init -> test-ldso] exception in lib: caught [init -> test-ldso] exception in another shared lib: caught [init -> test-ldso] -[init -> test-ldso] test stack alignment +[init -> test-ldso] Test stack alignment [init -> test-ldso] -------------------- [init -> test-ldso] [init -> test-ldso] [init -> test-ldso] [init -> test-ldso] [init -> test-ldso] +[init -> test-ldso] Dynamic cast +[init -> test-ldso] ------------ +[init -> test-ldso] 'Object' called: good +[init -> test-ldso] +[init -> test-ldso] Destruction +[init -> test-ldso] ----------- [init -> test-ldso] ~Lib_2_local 55667785 [init -> test-ldso] ~Lib_1_local_2 1020303d [init -> test-ldso] ~Lib_1_local_1 5060707d @@ -124,4 +136,3 @@ compare_output_to { [init -> test-ldso] ~Lib_1_global_1 5060705 [init -> test-ldso] ~Lib_2_global 11223340 } - diff --git a/repos/libports/src/lib/libc/dynamic_linker.cc b/repos/libports/src/lib/libc/dynamic_linker.cc new file mode 100644 index 000000000..48dc698c9 --- /dev/null +++ b/repos/libports/src/lib/libc/dynamic_linker.cc @@ -0,0 +1,120 @@ +/** + * \brief DL interface bindings + * \author Sebastian Sumpf + * \date 2014-10-24 + * + * Wrap Genode's shared library interface onto libc semantics. + */ + +#include +#include +#include +#include + +extern "C" { +#include +} + +using namespace Genode; + +enum { MAX_ERR = 128 }; +static char err_str[MAX_ERR]; + +char *dlerror(void) +{ + return err_str; +} + + +static Shared_object *to_object(void *handle) +{ + return static_cast(handle); +} + + +void *dlopen(const char *name, int mode) +{ + int supported = RTLD_LAZY | RTLD_NOW | RTLD_LOCAL | RTLD_NODELETE; + + /* error on unsupported mode values */ + if (mode & ~supported) { + snprintf(err_str, MAX_ERR, "Unsupported mode 0x%x\n", mode & ~supported); + PERR("dlopen: %s", err_str); + return nullptr; + } + + Shared_object *obj = 0; + unsigned flags = mode & RTLD_NOW ? Shared_object::NOW : Shared_object::LAZY; + flags |= mode & RTLD_NODELETE ? Shared_object::KEEP : 0; + + try { + obj = new (env()->heap()) Shared_object(name, flags); + } catch (...) { + snprintf(err_str, MAX_ERR, "Unable to open file %s\n", name); + } + + return (void *)obj; +} + + +void *dlsym(void *handle, const char *name) +{ + if (handle == nullptr || handle == RTLD_NEXT || handle == RTLD_DEFAULT || + handle == RTLD_SELF) { + snprintf(err_str, MAX_ERR, "Unsupported handle %p\n", handle); + return nullptr; + } + + try { + return to_object(handle)->lookup(name); + } catch (...) { + snprintf(err_str, MAX_ERR, "Symbol '%s' not found\n", name); + } + + return nullptr; +} + + +int dladdr(const void *addr, Dl_info *dlip) +{ + try { + Address_info info((addr_t)addr); + dlip->dli_fname = info.path; + dlip->dli_fbase = (void *)info.base; + dlip->dli_sname = info.name; + dlip->dli_saddr = (void *)info.addr; + } catch (...) { + snprintf(err_str, MAX_ERR, "Symbol %p at not found", addr); + return 0; + } + + return 1; +} + + +int dlclose(void *handle) +{ + destroy(env()->heap(), to_object(handle)); + return 0; +} + + +int dlinfo(void *handle, int request, void *p) +{ + PERR("%s not implemented", __func__); + return 0; +} + + +dlfunc_t dlfunc(void *handle, const char *name) +{ + PERR("%s not implemented", __func__); + return 0; +} + + +void *dlvsym(void *handle, const char *name, const char *version) +{ + PERR("%s not implemented", __func__); + return nullptr; +} diff --git a/repos/libports/src/test/ldso/dl/target.mk b/repos/libports/src/test/ldso/dl/target.mk new file mode 100644 index 000000000..4d709a586 --- /dev/null +++ b/repos/libports/src/test/ldso/dl/target.mk @@ -0,0 +1 @@ +LIBS = test-ldso_lib_dl diff --git a/repos/libports/src/test/ldso/include/test-ldso.h b/repos/libports/src/test/ldso/include/test-ldso.h index d3ae81d38..b3e527236 100644 --- a/repos/libports/src/test/ldso/include/test-ldso.h +++ b/repos/libports/src/test/ldso/include/test-ldso.h @@ -16,6 +16,7 @@ #define _TEST_LDSO_H_ void lib_1_test(); +void lib_1_good(); void lib_1_exception(); void lib_2_exception(); diff --git a/repos/libports/src/test/ldso/lib_dl.cc b/repos/libports/src/test/ldso/lib_dl.cc new file mode 100644 index 000000000..04fbbced2 --- /dev/null +++ b/repos/libports/src/test/ldso/lib_dl.cc @@ -0,0 +1,9 @@ +#include +#include "test-ldso.h" + +extern "C" void lib_dl_symbol() +{ + Genode::printf("called (from '%s')\n", __func__); + Genode::printf("Call 'lib_1_good': "); + lib_1_good(); +} diff --git a/repos/libports/src/test/ldso/main.cc b/repos/libports/src/test/ldso/main.cc index a922e7eea..8d8b4f28d 100644 --- a/repos/libports/src/test/ldso/main.cc +++ b/repos/libports/src/test/ldso/main.cc @@ -132,6 +132,34 @@ struct Test_stack_align_thread : Thread<0x2000> void entry() { test_stack_align("%f\n%g\n", 3.142, 2.718); } }; + +/****************** + ** Dynamic cast ** + ******************/ + +struct Object_base +{ + virtual void func() { printf("'Object_base' called: failed\n"); } +}; + +struct Object : Object_base +{ + void func() { printf("'Object' called: good\n"); } +}; + +void test_dynamic_cast_call(Object_base *o) +{ + Object *b = dynamic_cast(o); + b->func(); +} + +static void test_dynamic_cast() +{ + Object *o = new (Genode::env()->heap()) Object; + test_dynamic_cast_call(o); +} + + /** * Main function of LDSO test */ @@ -188,7 +216,7 @@ int main(int argc, char **argv) lib_1_test(); - printf("test stack alignment\n"); + printf("Test stack alignment\n"); printf("--------------------\n"); test_stack_align("%f\n%g\n", 3.142, 2.718); Test_stack_align_thread t; @@ -196,6 +224,15 @@ int main(int argc, char **argv) t.join(); printf("\n"); + printf("Dynamic cast\n"); + printf("------------\n"); + test_dynamic_cast(); + printf("\n"); + + + printf("Destruction\n"); + printf("-----------\n"); + /* test if return value is propagated correctly by dynamic linker */ return 123; } diff --git a/repos/os/lib/mk/arm/ld.mk b/repos/os/lib/mk/arm/ld.mk deleted file mode 100644 index 731d4c396..000000000 --- a/repos/os/lib/mk/arm/ld.mk +++ /dev/null @@ -1,12 +0,0 @@ -REQUIRES = arm -SHARED_LIB = yes -DIR = $(REP_DIR)/src/lib/ldso - -INC_DIR += $(DIR)/contrib/arm \ - $(DIR)/include/libc/libc-arm \ - $(DIR)/include/arm - -vpath platform.c $(DIR)/arm -vpath % $(DIR)/contrib/arm - -include $(DIR)/target.inc diff --git a/repos/os/lib/mk/codezero/ldso-arch.mk b/repos/os/lib/mk/codezero/ldso-arch.mk deleted file mode 100644 index a805b3d31..000000000 --- a/repos/os/lib/mk/codezero/ldso-arch.mk +++ /dev/null @@ -1,7 +0,0 @@ -SRC_CC = parent_cap.cc binary_name.cc -SRC_C = dummy.c -LIBS = syscall - -vpath parent_cap.cc $(REP_DIR)/src/lib/ldso/arch -vpath binary_name.cc $(REP_DIR)/src/lib/ldso/arch -vpath dummy.c $(REP_DIR)/src/lib/ldso/arch/codezero diff --git a/repos/os/lib/mk/ldso-arch.mk b/repos/os/lib/mk/ldso-arch.mk deleted file mode 100644 index 217ff2423..000000000 --- a/repos/os/lib/mk/ldso-arch.mk +++ /dev/null @@ -1,4 +0,0 @@ -SRC_CC = parent_cap.cc binary_name.cc - -vpath parent_cap.cc $(REP_DIR)/src/lib/ldso/arch -vpath binary_name.cc $(REP_DIR)/src/lib/ldso/arch diff --git a/repos/os/lib/mk/linux/ldso-arch.mk b/repos/os/lib/mk/linux/ldso-arch.mk deleted file mode 100644 index 223dea4ab..000000000 --- a/repos/os/lib/mk/linux/ldso-arch.mk +++ /dev/null @@ -1,4 +0,0 @@ -SRC_CC = parent_cap.cc binary_name.cc - -vpath parent_cap.cc $(REP_DIR)/src/lib/ldso/arch/linux -vpath binary_name.cc $(REP_DIR)/src/lib/ldso/arch/linux diff --git a/repos/os/lib/mk/nova/ldso-arch.mk b/repos/os/lib/mk/nova/ldso-arch.mk deleted file mode 100644 index f452b270d..000000000 --- a/repos/os/lib/mk/nova/ldso-arch.mk +++ /dev/null @@ -1,4 +0,0 @@ -SRC_CC = parent_cap.cc binary_name.cc - -vpath parent_cap.cc $(REP_DIR)/src/lib/ldso/arch/nova -vpath binary_name.cc $(REP_DIR)/src/lib/ldso/arch diff --git a/repos/os/lib/mk/pistachio/ldso-arch.mk b/repos/os/lib/mk/pistachio/ldso-arch.mk deleted file mode 100644 index 2e9b9f0c1..000000000 --- a/repos/os/lib/mk/pistachio/ldso-arch.mk +++ /dev/null @@ -1,5 +0,0 @@ -SRC_CC = parent_cap.cc binary_name.cc -LIBS = l4 - -vpath parent_cap.cc $(REP_DIR)/src/lib/ldso/arch -vpath binary_name.cc $(REP_DIR)/src/lib/ldso/arch diff --git a/repos/os/lib/mk/x86_32/ld.mk b/repos/os/lib/mk/x86_32/ld.mk deleted file mode 100644 index 0eacb46c6..000000000 --- a/repos/os/lib/mk/x86_32/ld.mk +++ /dev/null @@ -1,12 +0,0 @@ -REQUIRES = x86 32bit -SHARED_LIB = yes -DIR = $(REP_DIR)/src/lib/ldso - -INC_DIR += $(DIR)/contrib/i386 \ - $(DIR)/include/libc/libc-i386 \ - $(DIR)/include/x86_32 - -vpath % $(DIR)/contrib/i386 -vpath % $(DIR)/x86_32 - -include $(DIR)/target.inc diff --git a/repos/os/lib/mk/x86_64/ld.mk b/repos/os/lib/mk/x86_64/ld.mk deleted file mode 100644 index 5c1eeec39..000000000 --- a/repos/os/lib/mk/x86_64/ld.mk +++ /dev/null @@ -1,14 +0,0 @@ -REQUIRES = x86 64bit -SHARED_LIB = yes -DIR = $(REP_DIR)/src/lib/ldso - -INC_DIR += $(DIR)/contrib/amd64 \ - $(DIR)/include/libc/libc-amd64 \ - $(DIR)/include/x86_64 - -D_OPTS = __ELF_WORD_SIZE=64 - - -vpath % $(DIR)/contrib/amd64 - -include $(DIR)/target.inc diff --git a/repos/os/src/lib/ldso/arch/binary_name.cc b/repos/os/src/lib/ldso/arch/binary_name.cc deleted file mode 100644 index efe5fcb62..000000000 --- a/repos/os/src/lib/ldso/arch/binary_name.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief Retrieve progam name from dataspace (Linux specific) - * \author Sebastian Sumpf - * \date 2010-01-04 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ -#include - -using namespace Genode; -/* - * Function is implemented for Linux/GDB only - */ -int Genode::binary_name(Dataspace_capability ds_cap, char *buf, size_t buf_size) -{ - return -1; -} diff --git a/repos/os/src/lib/ldso/arch/codezero/dummy.c b/repos/os/src/lib/ldso/arch/codezero/dummy.c deleted file mode 100644 index d06ac5aa7..000000000 --- a/repos/os/src/lib/ldso/arch/codezero/dummy.c +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief Dummies for Codezeros libmem (used by libl4) - * \author Sebastian Sumpf - * \date 2011-05-10 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -void *mem_cache_zalloc(void *cache){ return 0; } -void *mem_cache_alloc(void *cache){ return 0; } -void *mem_cache_init(void *start, int cache_size, int struct_size, - unsigned int alignment) { return 0; } -int mem_cache_free(void *cache, void *addr) { return 0; } - -void *kmalloc(int size) { return 0; } - - diff --git a/repos/os/src/lib/ldso/arch/linux/binary_name.cc b/repos/os/src/lib/ldso/arch/linux/binary_name.cc deleted file mode 100644 index f15f0d227..000000000 --- a/repos/os/src/lib/ldso/arch/linux/binary_name.cc +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \brief Retrieve progam name from dataspace (Linux specific) - * \author Sebastian Sumpf - * \date 2010-01-04 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ -#include -#include - -using namespace Genode; - -int Genode::binary_name(Dataspace_capability ds_cap, char *buf, size_t buf_size) -{ - /* determine name of binary to start */ - Linux_dataspace_client ds_client(ds_cap); - Linux_dataspace::Filename filename = ds_client.fname(); - strncpy(buf, filename.buf, buf_size); - return 0; -} diff --git a/repos/os/src/lib/ldso/arch/linux/parent_cap.cc b/repos/os/src/lib/ldso/arch/linux/parent_cap.cc deleted file mode 100644 index 6fc7fe773..000000000 --- a/repos/os/src/lib/ldso/arch/linux/parent_cap.cc +++ /dev/null @@ -1,18 +0,0 @@ -/* - * \brief Parent capability manipulation - * \author Sebastian Sumpf - * \date 2009-11-05 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include - -void Genode::set_parent_cap_arch(void *ptr) -{ -} diff --git a/repos/os/src/lib/ldso/arch/nova/parent_cap.cc b/repos/os/src/lib/ldso/arch/nova/parent_cap.cc deleted file mode 100644 index d10218654..000000000 --- a/repos/os/src/lib/ldso/arch/nova/parent_cap.cc +++ /dev/null @@ -1,21 +0,0 @@ -/* - * \brief Parent capability manipulation - * \author Alexander Boettcher - * \date 2012-08-13 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include - -void Genode::set_parent_cap_arch(void *ptr) -{ - /* Not required, determinig parent cap is done not using any exported - * symbols - */ -} diff --git a/repos/os/src/lib/ldso/arch/parent_cap.cc b/repos/os/src/lib/ldso/arch/parent_cap.cc deleted file mode 100644 index 9ae99d45d..000000000 --- a/repos/os/src/lib/ldso/arch/parent_cap.cc +++ /dev/null @@ -1,24 +0,0 @@ -/* - * \brief Parent capability manipulation - * \author Sebastian Sumpf - * \date 2009-11-05 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include - -using namespace Genode; - -void Genode::set_parent_cap_arch(void *ptr) -{ - Genode::Parent_capability cap = parent_cap(); - memcpy(ptr, &cap, sizeof(cap)); -} diff --git a/repos/os/src/lib/ldso/arm/platform.c b/repos/os/src/lib/ldso/arm/platform.c deleted file mode 100644 index bd3ed56a4..000000000 --- a/repos/os/src/lib/ldso/arm/platform.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * \brief Special handling for the ARM architecture - * \author Sebastian Sumpf - * \date 2010-07-05 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ -#include "rtld.h" -#include -#include -#include -#include -#include "dl_extensions.h" - -/* - * cbass: Added EHABI exception table section type - * - */ -#ifndef PT_ARM_EXIDX -#define PT_ARM_EXIDX 0x70000001 -#endif - -extern Obj_Entry *obj_list; - -typedef struct exidx_t { - unsigned long base; - int count; -} exidx_t; - - -/* - * Scan for exception index section and parse information - */ -static void platform_section(Elf_Phdr *phdr, void **priv) -{ - exidx_t *exidx; - switch (phdr->p_type) { - - case PT_ARM_EXIDX: - exidx = (exidx_t *)xmalloc(sizeof(exidx_t)); - exidx->base = phdr->p_vaddr; - /* Each exception table entry is 8 Byte */ - exidx->count = phdr->p_memsz / 8; - *priv = (void *)exidx; - return; - } -} - - -/* - * Read program header and setup exception information - */ -static void find_exidx(Obj_Entry *obj) -{ - char *phdr = file_phdr(obj->path, (void *)obj->mapbase); - - Elf_Ehdr *ehdr = (Elf_Ehdr *)phdr; - Elf_Phdr *ph_table = (Elf_Phdr *)(phdr + ehdr->e_phoff); - - unsigned i; - size_t start = ~0; - size_t end = ~0; - - for (i = 0; i < ehdr->e_phnum; i++) { - platform_section(&ph_table[i], &obj->priv); - - /* determine map size */ - if (ph_table[i].p_type == PT_LOAD) { - - if (start == ~0) - start = trunc_page(ph_table[i].p_vaddr); - - end = round_page(ph_table[i].p_vaddr + ph_table[i].p_memsz); - } - } - - /* since linker is not setup by map_object map info is not set correctly */ - if (obj->rtld) { - obj->vaddrbase = (Elf_Addr)obj->mapbase; - obj->mapsize = end - start; - } -} - - -/* - * Find exceptions index that matches given IP (PC) - */ -unsigned long dl_unwind_find_exidx(unsigned long pc, int *pcount) -{ - Obj_Entry *obj; - extern Obj_Entry obj_rtld; - caddr_t addr = (caddr_t)pc; - - /* - * Used during startup before ldso's main function is called and therefore - * obj_list has not been initialized - */ - Obj_Entry *list = obj_list; - if (!list) - list = &obj_rtld; - - for (obj = list; obj != NULL; obj = obj->next) { - - /* initialize exceptions for object */ - if (!obj->priv) - find_exidx(obj); - - if (addr >= obj->mapbase && addr < obj->mapbase + obj->mapsize && obj->priv) { - *pcount = ((exidx_t *)obj->priv)->count; - return (unsigned long)(((exidx_t *)obj->priv)->base + obj->mapbase - obj->vaddrbase); - } - } - - *pcount = 0; - return 0; -} - diff --git a/repos/os/src/lib/ldso/call_program_main.cc b/repos/os/src/lib/ldso/call_program_main.cc deleted file mode 100644 index 5dee701f6..000000000 --- a/repos/os/src/lib/ldso/call_program_main.cc +++ /dev/null @@ -1,58 +0,0 @@ -/* - * \brief Call the main function of the dynamic program - * \author Martin Stein - * \date 2013-12-14 - */ - -/* - * Copyright (C) 2014 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -typedef void (*Func)(void); - -int genode_atexit(Func); - -extern "C" { void const ** get_program_var_addr(char const * name); } - -extern char ** genode_argv; -extern int genode_argc; -extern char ** genode_envp; - -/** - * Cast a given function pointer into a 'void (*)()' function pointer - * - * \param ptr source function pointer - */ -template -static Func * func(Func_ptr ptr) -{ - return reinterpret_cast(const_cast(ptr)); -} - -/** - * Call the main function of the dynamic program - * - * \param main_ptr raw pointer of program main-function - * - * \return return value of the program main-function - */ -extern "C" int call_program_main(Func main_func) -{ - /* call constructors of global objects of the program */ - Func * const _ctors_end = func(get_program_var_addr("_ctors_end")); - Func * const _ctors_start = func(get_program_var_addr("_ctors_start")); - for (Func * ctor = _ctors_end; ctor != _ctors_start; (*--ctor)()); - - /* register global-object destructors of program at LDSO atexit-array */ - Func * const _dtors_end = func(get_program_var_addr("_dtors_end")); - Func * const _dtors_start = func(get_program_var_addr("_dtors_start")); - for (Func * dtor = _dtors_start; dtor != _dtors_end; genode_atexit(*dtor++)); - - /* call main function of the program */ - typedef int (*Main)(int, char **, char **); - Main const main = reinterpret_cast
(main_func); - return main(genode_argc, genode_argv, genode_envp); -} diff --git a/repos/os/src/lib/ldso/contrib/amd64/reloc.c b/repos/os/src/lib/ldso/contrib/amd64/reloc.c deleted file mode 100644 index 97976f06a..000000000 --- a/repos/os/src/lib/ldso/contrib/amd64/reloc.c +++ /dev/null @@ -1,407 +0,0 @@ -/*- - * Copyright 1996, 1997, 1998, 1999 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/amd64/reloc.c,v 1.18.8.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -/* - * Dynamic linker for ELF. - * - * John Polstra . - */ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "rtld.h" - -/* - * Process the special R_X86_64_COPY relocations in the main program. These - * copy data from a shared object into a region in the main program's BSS - * segment. - * - * Returns 0 on success, -1 on failure. - */ -int -do_copy_relocations(Obj_Entry *dstobj) -{ - const Elf_Rela *relalim; - const Elf_Rela *rela; - - assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ - - relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize); - for (rela = dstobj->rela; rela < relalim; rela++) { - if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) { - void *dstaddr; - const Elf_Sym *dstsym; - const char *name; - unsigned long hash; - size_t size; - const void *srcaddr; - const Elf_Sym *srcsym; - Obj_Entry *srcobj; - const Ver_Entry *ve; - - dstaddr = (void *) (dstobj->relocbase + rela->r_offset); - dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info); - name = dstobj->strtab + dstsym->st_name; - hash = elf_hash(name); - size = dstsym->st_size; - ve = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info)); - - for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) - if ((srcsym = symlook_obj(name, hash, srcobj, ve, 0)) != NULL) - break; - - if (srcobj == NULL) { - _rtld_error("Undefined symbol \"%s\" referenced from COPY" - " relocation in %s", name, dstobj->path); - return -1; - } - - srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value); - memcpy(dstaddr, srcaddr, size); - } - } - - return 0; -} - -/* Initialize the special GOT entries. */ -void -init_pltgot(Obj_Entry *obj) -{ - if (obj->pltgot != NULL) { - obj->pltgot[1] = (Elf_Addr) obj; - obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; - } -} - -/* Process the non-PLT relocations. */ -int -reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) -{ - const Elf_Rela *relalim; - const Elf_Rela *rela; - SymCache *cache; - int bytes = obj->nchains * sizeof(SymCache); - int r = -1; - - /* - * The dynamic loader may be called from a thread, we have - * limited amounts of stack available so we cannot use alloca(). - */ - int flags = obj->rtld_init ? MAP_LDSO : 0; - cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON|flags, -1, 0); - if (cache == MAP_FAILED) - cache = NULL; - - relalim = (const Elf_Rela *) ((caddr_t) obj->rela + obj->relasize); - for (rela = obj->rela; rela < relalim; rela++) { - Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rela->r_offset); - Elf32_Addr *where32 = (Elf32_Addr *)where; - - switch (ELF_R_TYPE(rela->r_info)) { - - case R_X86_64_NONE: - break; - - case R_X86_64_64: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - *where = (Elf_Addr) (defobj->relocbase + def->st_value + rela->r_addend); - } - break; - - case R_X86_64_PC32: - /* - * I don't think the dynamic linker should ever see this - * type of relocation. But the binutils-2.6 tools sometimes - * generate it. - */ - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - *where32 = (Elf32_Addr) (unsigned long) (defobj->relocbase + - def->st_value + rela->r_addend - (Elf_Addr) where); - } - break; - /* missing: R_X86_64_GOT32 R_X86_64_PLT32 */ - - case R_X86_64_COPY: - /* - * These are deferred until all other relocations have - * been done. All we do here is make sure that the COPY - * relocation is not in a shared library. They are allowed - * only in executable files. - */ - if (!obj->mainprog) { - _rtld_error("%s: Unexpected R_X86_64_COPY relocation" - " in shared library", obj->path); - goto done; - } - break; - - case R_X86_64_GLOB_DAT: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); - - /* cbass: Skip undefined symbols */ - if (def == NULL || defobj == NULL) - continue; - - *where = (Elf_Addr) (defobj->relocbase + def->st_value); - } - break; - - case R_X86_64_TPOFF64: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - /* - * We lazily allocate offsets for static TLS as we - * see the first relocation that references the - * TLS block. This allows us to support (small - * amounts of) static TLS in dynamically loaded - * modules. If we run out of space, we generate an - * error. - */ - if (!defobj->tls_done) { - if (!allocate_tls_offset((Obj_Entry*) defobj)) { - _rtld_error("%s: No space available for static " - "Thread Local Storage", obj->path); - goto done; - } - } - - *where = (Elf_Addr) (def->st_value - defobj->tlsoffset + - rela->r_addend); - } - break; - - case R_X86_64_TPOFF32: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - /* - * We lazily allocate offsets for static TLS as we - * see the first relocation that references the - * TLS block. This allows us to support (small - * amounts of) static TLS in dynamically loaded - * modules. If we run out of space, we generate an - * error. - */ - if (!defobj->tls_done) { - if (!allocate_tls_offset((Obj_Entry*) defobj)) { - _rtld_error("%s: No space available for static " - "Thread Local Storage", obj->path); - goto done; - } - } - - *where32 = (Elf32_Addr) (def->st_value - - defobj->tlsoffset + - rela->r_addend); - } - break; - - case R_X86_64_DTPMOD64: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - *where += (Elf_Addr) defobj->tlsindex; - } - break; - - case R_X86_64_DTPOFF64: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - *where += (Elf_Addr) (def->st_value + rela->r_addend); - } - break; - - case R_X86_64_DTPOFF32: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - *where32 += (Elf32_Addr) (def->st_value + rela->r_addend); - } - break; - - case R_X86_64_RELATIVE: - *where = (Elf_Addr)(obj->relocbase + rela->r_addend); - break; - - /* missing: R_X86_64_GOTPCREL, R_X86_64_32, R_X86_64_32S, R_X86_64_16, R_X86_64_PC16, R_X86_64_8, R_X86_64_PC8 */ - - default: - _rtld_error("%s: Unsupported relocation type %u" - " in non-PLT relocations\n", obj->path, - (unsigned int)ELF_R_TYPE(rela->r_info)); - goto done; - } - } - r = 0; -done: - - /* - * Do not unmap if LDSO is in initialization, since some ctors might not - * be called, yet. - */ - if (cache && !(obj->rtld_init)) - munmap(cache, bytes); - return(r); -} - -/* Process the PLT relocations. */ -int -reloc_plt(Obj_Entry *obj) -{ - const Elf_Rela *relalim; - const Elf_Rela *rela; - - relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); - for (rela = obj->pltrela; rela < relalim; rela++) { - Elf_Addr *where; - - assert(ELF_R_TYPE(rela->r_info) == R_X86_64_JMP_SLOT); - - /* Relocate the GOT slot pointing into the PLT. */ - where = (Elf_Addr *)(obj->relocbase + rela->r_offset); - *where += (Elf_Addr)obj->relocbase; - } - return 0; -} - -/* Relocate the jump slots in an object. */ -int -reloc_jmpslots(Obj_Entry *obj) -{ - const Elf_Rela *relalim; - const Elf_Rela *rela; - - if (obj->jmpslots_done) - return 0; - relalim = (const Elf_Rela *)((char *)obj->pltrela + obj->pltrelasize); - for (rela = obj->pltrela; rela < relalim; rela++) { - Elf_Addr *where, target; - const Elf_Sym *def; - const Obj_Entry *defobj; - - assert(ELF_R_TYPE(rela->r_info) == R_X86_64_JMP_SLOT); - where = (Elf_Addr *)(obj->relocbase + rela->r_offset); - def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, true, NULL); - if (def == NULL) - return -1; - target = (Elf_Addr)(defobj->relocbase + def->st_value + rela->r_addend); - reloc_jmpslot(where, target, defobj, obj, (const Elf_Rel *)rela); - } - obj->jmpslots_done = true; - return 0; -} - -void -allocate_initial_tls(Obj_Entry *objs) -{ - /* - * Fix the size of the static TLS block by using the maximum - * offset allocated so far and adding a bit for dynamic modules to - * use. - */ - tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA; - amd64_set_fsbase(allocate_tls(objs, 0, - 3*sizeof(Elf_Addr), sizeof(Elf_Addr))); -} - -void *__tls_get_addr(tls_index *ti) -{ - Elf_Addr** segbase; - Elf_Addr* dtv; - - __asm __volatile("movq %%fs:0, %0" : "=r" (segbase)); - dtv = segbase[1]; - - return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset); -} diff --git a/repos/os/src/lib/ldso/contrib/amd64/rtld_machdep.h b/repos/os/src/lib/ldso/contrib/amd64/rtld_machdep.h deleted file mode 100644 index 6287750eb..000000000 --- a/repos/os/src/lib/ldso/contrib/amd64/rtld_machdep.h +++ /dev/null @@ -1,78 +0,0 @@ -/*- - * Copyright (c) 1999, 2000 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/amd64/rtld_machdep.h,v 1.13.8.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -#ifndef RTLD_MACHDEP_H -#define RTLD_MACHDEP_H 1 - -#include -#include - -#define CACHE_LINE_SIZE 64 - -struct Struct_Obj_Entry; - -/* Return the address of the .dynamic section in the dynamic linker. */ -#define rtld_dynamic(obj) \ - ((const Elf_Dyn *)((obj)->relocbase + (Elf_Addr)&_DYNAMIC)) - -/* Fixup the jump slot at "where" to transfer control to "target". */ -static inline Elf_Addr -reloc_jmpslot(Elf_Addr *where, Elf_Addr target, - const struct Struct_Obj_Entry *obj, - const struct Struct_Obj_Entry *refobj, const Elf_Rel *rel) -{ -#ifdef dbg - dbg("reloc_jmpslot: *%p = %p", (void *)(where), - (void *)(target)); -#endif - (*(Elf_Addr *)(where) = (Elf_Addr)(target)); - return target; -} - -#define make_function_pointer(def, defobj) \ - ((defobj)->relocbase + (def)->st_value) - -#define call_initfini_pointer(obj, target) \ - (((InitFunc)(target))()) - -#define round(size, align) \ - (((size) + (align) - 1) & ~((align) - 1)) -#define calculate_first_tls_offset(size, align) \ - round(size, align) -#define calculate_tls_offset(prev_offset, prev_size, size, align) \ - round((prev_offset) + (size), align) -#define calculate_tls_end(off, size) (off) - -typedef struct { - unsigned long ti_module; - unsigned long ti_offset; -} tls_index; - -extern void *__tls_get_addr(tls_index *ti); - -#endif diff --git a/repos/os/src/lib/ldso/contrib/amd64/rtld_start.S b/repos/os/src/lib/ldso/contrib/amd64/rtld_start.S deleted file mode 100644 index 535e29dac..000000000 --- a/repos/os/src/lib/ldso/contrib/amd64/rtld_start.S +++ /dev/null @@ -1,114 +0,0 @@ -/*- - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/amd64/rtld_start.S,v 1.5.28.1 2009/04/15 03:14:26 kensmith Exp $ - */ - - .text - .align 4 - .globl .rtld_start - .type .rtld_start,@function -.rtld_start: - xorq %rbp,%rbp # Clear frame pointer for good form - subq $24,%rsp # A place to store exit procedure addr - movq %rdi,%r12 - movq %rsp,%rsi # save address of exit proc - movq %rsp,%rdx # construct address of obj_main - addq $8,%rdx - call _rtld@PLT # Call rtld(sp); returns entry point - popq %rsi # Get exit procedure address - movq %r12,%rdi # *ap -/* - * At this point, %rax contains the entry point of the main program, and - * %rdx contains a pointer to a termination function that should be - * registered with atexit(). (crt1.o registers it.) - */ -.globl .rtld_goto_main -.rtld_goto_main: # This symbol exists just to make debugging easier. - jmp *%rax # Enter main program - - -/* - * Binder entry point. Control is transferred to here by code in the PLT. - * On entry, there are two arguments on the stack. In ascending address - * order, they are (1) "obj", a pointer to the calling object's Obj_Entry, - * and (2) "reloff", the byte offset of the appropriate relocation entry - * in the PLT relocation table. - * - * We are careful to preserve all registers, even the the caller-save - * registers. That is because this code may be invoked by low-level - * assembly-language code that is not ABI-compliant. - * - * Stack map: - * reloff 0x60 - * obj 0x58 - * spare 0x50 - * rflags 0x48 - * rax 0x40 - * rdx 0x38 - * rcx 0x30 - * rsi 0x28 - * rdi 0x20 - * r8 0x18 - * r9 0x10 - * r10 0x8 - * r11 0x0 - */ - .align 4 - .globl _rtld_bind_start - .type _rtld_bind_start,@function -_rtld_bind_start: - subq $8,%rsp - pushfq # Save rflags - pushq %rax # Save %rax - pushq %rdx # Save %rdx - pushq %rcx # Save %rcx - pushq %rsi # Save %rsi - pushq %rdi # Save %rdi - pushq %r8 # Save %r8 - pushq %r9 # Save %r9 - pushq %r10 # Save %r10 - pushq %r11 # Save %r11 - - movq 0x58(%rsp),%rdi # Fetch obj argument - movq 0x60(%rsp),%rsi # Fetch reloff argument - leaq (%rsi,%rsi,2),%rsi # multiply by 3 - leaq (,%rsi,8),%rsi # now 8, for 24 (sizeof Elf_Rela) - - call _rtld_bind@PLT # Transfer control to the binder - /* Now %rax contains the entry point of the function being called. */ - - movq %rax,0x60(%rsp) # Store target over reloff argument - popq %r11 # Restore %r11 - popq %r10 # Restore %r10 - popq %r9 # Restore %r9 - popq %r8 # Restore %r8 - popq %rdi # Restore %rdi - popq %rsi # Restore %rsi - popq %rcx # Restore %rcx - popq %rdx # Restore %rdx - popq %rax # Restore %rax - popfq # Restore rflags - leaq 16(%rsp),%rsp # Discard spare, obj, do not change rflags - ret # "Return" to target address diff --git a/repos/os/src/lib/ldso/contrib/arm/reloc.c b/repos/os/src/lib/ldso/contrib/arm/reloc.c deleted file mode 100644 index 52261eb85..000000000 --- a/repos/os/src/lib/ldso/contrib/arm/reloc.c +++ /dev/null @@ -1,398 +0,0 @@ -/* $NetBSD: mdreloc.c,v 1.23 2003/07/26 15:04:38 mrg Exp $ */ - -#include -__FBSDID("$FreeBSD: src/libexec/rtld-elf/arm/reloc.c,v 1.4.8.1 2009/04/15 03:14:26 kensmith Exp $"); -#include -#include - -#include -#include -#include -#include -#include -#include "debug.h" -#include "rtld.h" - -void -init_pltgot(Obj_Entry *obj) -{ - if (obj->pltgot != NULL) { - obj->pltgot[1] = (Elf_Addr) obj; - obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; - } -} - -int -do_copy_relocations(Obj_Entry *dstobj) -{ - const Elf_Rel *rellim; - const Elf_Rel *rel; - - assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ - - rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize); - for (rel = dstobj->rel; rel < rellim; rel++) { - if (ELF_R_TYPE(rel->r_info) == R_ARM_COPY) { - void *dstaddr; - const Elf_Sym *dstsym; - const char *name; - unsigned long hash; - size_t size; - const void *srcaddr; - const Elf_Sym *srcsym; - Obj_Entry *srcobj; - const Ver_Entry *ve; - - dstaddr = (void *) (dstobj->relocbase + rel->r_offset); - dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info); - name = dstobj->strtab + dstsym->st_name; - hash = elf_hash(name); - size = dstsym->st_size; - ve = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info)); - - for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) - if ((srcsym = symlook_obj(name, hash, srcobj, ve, 0)) != NULL) - break; - - if (srcobj == NULL) { - _rtld_error("Undefined symbol \"%s\" referenced from COPY" - " relocation in %s", name, dstobj->path); - return -1; - } - - srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value); - memcpy(dstaddr, srcaddr, size); - } - } - return 0; -} - -void _rtld_bind_start(void); -void _rtld_relocate_nonplt_self(Elf_Dyn *, Elf_Addr); - -int open(); -int _open(); -void -_rtld_relocate_nonplt_self(Elf_Dyn *dynp, Elf_Addr relocbase) -{ - const Elf_Rel *rel = 0, *rellim; - Elf_Addr relsz = 0; - Elf_Addr *where; - - for (; dynp->d_tag != DT_NULL; dynp++) { - switch (dynp->d_tag) { - case DT_REL: - rel = (const Elf_Rel *)(relocbase + dynp->d_un.d_ptr); - break; - case DT_RELSZ: - relsz = dynp->d_un.d_val; - break; - } - } - rellim = (const Elf_Rel *)((caddr_t)rel + relsz); - for (; rel < rellim; rel++) { - where = (Elf_Addr *)(relocbase + rel->r_offset); - - *where += (Elf_Addr)relocbase; - } -} -/* - * It is possible for the compiler to emit relocations for unaligned data. - * We handle this situation with these inlines. - */ -#define RELOC_ALIGNED_P(x) \ - (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) - -static __inline Elf_Addr -load_ptr(void *where) -{ - Elf_Addr res; - - memcpy(&res, where, sizeof(res)); - - return (res); -} - -static __inline void -store_ptr(void *where, Elf_Addr val) -{ - - memcpy(where, &val, sizeof(val)); -} - -static int -reloc_nonplt_object(Obj_Entry *obj, const Elf_Rel *rel, SymCache *cache) -{ - Elf_Addr *where; - const Elf_Sym *def; - const Obj_Entry *defobj; - Elf_Addr tmp; - unsigned long symnum; - - where = (Elf_Addr *)(obj->relocbase + rel->r_offset); - symnum = ELF_R_SYM(rel->r_info); - - /* - * cbass: - * This is the second relocation run for LDSO, relocate global - * symbols only, in order to resolve e.g. type informations in - * binary - */ - if (obj->rtld && !(obj->rtld_init)) { - switch (ELF_R_TYPE(rel->r_info)) { - - case R_ARM_GLOB_DAT: /* word32 B + S */ - def = find_symdef(symnum, obj, &defobj, false, cache); - if (def == NULL || defobj==NULL) - return 0; - *where = (Elf_Addr)defobj->relocbase + - def->st_value; - default: - return 0; - } - } - - switch (ELF_R_TYPE(rel->r_info)) { - case R_ARM_NONE: - /* XXX cbass: Ignore TLS relocations */ - case R_ARM_TLS_DTPMOD32: - break; - -#if 1 /* XXX should not occur */ - case R_ARM_PC24: { /* word32 S - P + A */ - Elf32_Sword addend; - - /* - * Extract addend and sign-extend if needed. - */ - addend = *where; - if (addend & 0x00800000) - addend |= 0xff000000; - - def = find_symdef(symnum, obj, &defobj, false, cache); - if (def == NULL) - return -1; - tmp = (Elf_Addr)obj->relocbase + def->st_value - - (Elf_Addr)where + (addend << 2); - if ((tmp & 0xfe000000) != 0xfe000000 && - (tmp & 0xfe000000) != 0) { - _rtld_error( - "%s: R_ARM_PC24 relocation @ %p to %s failed " - "(displacement %ld (%#lx) out of range)", - obj->path, where, - obj->strtab + obj->symtab[symnum].st_name, - (long) tmp, (long) tmp); - return -1; - } - tmp >>= 2; - *where = (*where & 0xff000000) | (tmp & 0x00ffffff); - dbg("PC24 %s in %s --> %p @ %p in %s", - obj->strtab + obj->symtab[symnum].st_name, - obj->path, (void *)*where, where, defobj->path); - break; - } -#endif - - case R_ARM_REL32: /* word32 S - P + A */ - def = find_symdef(symnum, obj, &defobj, false, cache); - if (def == NULL) - return -1; - - *where = (Elf_Addr)defobj->relocbase + def->st_value - (Elf_Addr)where - + *where; - break; - - case R_ARM_ABS32: /* word32 B + S + A */ - case R_ARM_GLOB_DAT: /* word32 B + S */ - def = find_symdef(symnum, obj, &defobj, false, cache); - /* cbass: Skip undefined symbols */ - if (def == NULL || defobj==NULL) - return 0; - if (__predict_true(RELOC_ALIGNED_P(where))) { - tmp = *where + (Elf_Addr)defobj->relocbase + - def->st_value; - *where = tmp; - } else { - tmp = load_ptr(where) + - (Elf_Addr)defobj->relocbase + - def->st_value; - store_ptr(where, tmp); - } - dbg("ABS32/GLOB_DAT %s in %s --> %p @ %p in %s", - obj->strtab + obj->symtab[symnum].st_name, - obj->path, (void *)tmp, where, defobj->path); - break; - - case R_ARM_RELATIVE: /* word32 B + A */ - if (__predict_true(RELOC_ALIGNED_P(where))) { - tmp = *where + (Elf_Addr)obj->relocbase; - - if (obj->relocbase) - *where = tmp; - } else { - tmp = load_ptr(where) + - (Elf_Addr)obj->relocbase; - store_ptr(where, tmp); - } - dbg("RELATIVE in %s --> %p", obj->path, - (void *)tmp); - break; - - case R_ARM_COPY: - /* - * These are deferred until all other relocations have - * been done. All we do here is make sure that the - * COPY relocation is not in a shared library. They - * are allowed only in executable files. - */ - if (!obj->mainprog) { - _rtld_error( - "%s: Unexpected R_COPY relocation in shared library", - obj->path); - return -1; - } - dbg("COPY (avoid in main)"); - break; - - default: - dbg("sym = %lu, type = %lu, offset = %p, " - "contents = %p, symbol = %s", - symnum, (u_long)ELF_R_TYPE(rel->r_info), - (void *)rel->r_offset, (void *)load_ptr(where), - obj->strtab + obj->symtab[symnum].st_name); - _rtld_error("%s: Unsupported relocation type %ld " - "in non-PLT relocations\n", - obj->path, (u_long) ELF_R_TYPE(rel->r_info)); - return -1; - } - return 0; -} - -/* - * * Process non-PLT relocations - * */ -int -reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) -{ - const Elf_Rel *rellim; - const Elf_Rel *rel; - SymCache *cache; - int bytes = obj->nchains * sizeof(SymCache); - int r = -1; - - /* - * The dynamic loader may be called from a thread, we have - * limited amounts of stack available so we cannot use alloca(). - */ - int flags = obj->rtld_init ? MAP_LDSO : 0; - cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON|flags, -1, 0); - if (cache == MAP_FAILED) - cache = NULL; - - rellim = (const Elf_Rel *)((caddr_t)obj->rel + obj->relsize); - for (rel = obj->rel; rel < rellim; rel++) { - if (reloc_nonplt_object(obj, rel, cache) < 0) - goto done; - } - r = 0; -done: - - /* - * Do not unmap if LDSO is in initialization, since some ctors might not - * be called, yet. - */ - if (cache && !(obj->rtld_init)) { - munmap(cache, bytes); - } - return (r); -} - -/* - * * Process the PLT relocations. - * */ -int -reloc_plt(Obj_Entry *obj) -{ - const Elf_Rel *rellim; - const Elf_Rel *rel; - - rellim = (const Elf_Rel *)((char *)obj->pltrel + - obj->pltrelsize); - for (rel = obj->pltrel; rel < rellim; rel++) { - Elf_Addr *where; - - assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT); - - where = (Elf_Addr *)(obj->relocbase + rel->r_offset); - *where += (Elf_Addr )obj->relocbase; - } - - return (0); -} - -/* - * * LD_BIND_NOW was set - force relocation for all jump slots - * */ -int -reloc_jmpslots(Obj_Entry *obj) -{ - const Obj_Entry *defobj; - const Elf_Rel *rellim; - const Elf_Rel *rel; - const Elf_Sym *def; - Elf_Addr *where; - Elf_Addr target; - - rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize); - for (rel = obj->pltrel; rel < rellim; rel++) { - assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT); - where = (Elf_Addr *)(obj->relocbase + rel->r_offset); - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - true, NULL); - if (def == NULL) { - dbg("reloc_jmpslots: sym not found"); - return (-1); - } - - /* skip undefined symbols in linker */ - if (defobj == NULL && obj->rtld) - continue; - - target = (Elf_Addr)(defobj->relocbase + def->st_value); - reloc_jmpslot(where, target, defobj, obj, - (const Elf_Rel *) rel); - } - - obj->jmpslots_done = true; - - return (0); -} - -Elf_Addr -reloc_jmpslot(Elf_Addr *where, Elf_Addr target, const Obj_Entry *defobj, - const Obj_Entry *obj, const Elf_Rel *rel) -{ - - assert(ELF_R_TYPE(rel->r_info) == R_ARM_JUMP_SLOT); - - if (*where != target) - *where = target; - - return target; -} - -void -allocate_initial_tls(Obj_Entry *objs) -{ - -} - -void * -__tls_get_addr(tls_index* ti) -{ - /* XXX cbass: We don't support tls, but some compilers use TLS. Just for the - * sake of it: Provide some memory ... and best wishes! - */ - static char _tls[64]; - return _tls; -} diff --git a/repos/os/src/lib/ldso/contrib/arm/rtld_machdep.h b/repos/os/src/lib/ldso/contrib/arm/rtld_machdep.h deleted file mode 100644 index bd70b935d..000000000 --- a/repos/os/src/lib/ldso/contrib/arm/rtld_machdep.h +++ /dev/null @@ -1,74 +0,0 @@ -/*- - * Copyright (c) 1999, 2000 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/arm/rtld_machdep.h,v 1.5.20.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -#ifndef RTLD_MACHDEP_H -#define RTLD_MACHDEP_H 1 - -#include -#include - -#define CACHE_LINE_SIZE 32 - -struct Struct_Obj_Entry; - -/* Return the address of the .dynamic section in the dynamic linker. */ -#define rtld_dynamic(obj) (&_DYNAMIC) - -Elf_Addr reloc_jmpslot(Elf_Addr *where, Elf_Addr target, - const struct Struct_Obj_Entry *defobj, - const struct Struct_Obj_Entry *obj, - const Elf_Rel *rel); - -#define make_function_pointer(def, defobj) \ - ((defobj)->relocbase + (def)->st_value) - -#define call_initfini_pointer(obj, target) \ - (((InitFunc)(target))()) - -typedef struct { - unsigned long ti_module; - unsigned long ti_offset; -} tls_index; - -#define round(size, align) \ - (((size) + (align) - 1) & ~((align) - 1)) -#define calculate_first_tls_offset(size, align) \ - round(size, align) -#define calculate_tls_offset(prev_offset, prev_size, size, align) \ - round(prev_offset + prev_size, align) -#define calculate_tls_end(off, size) ((off) + (size)) - - -/* - * Lazy binding entry point, called via PLT. - */ -void _rtld_bind_start(void); - -extern void *__tls_get_addr(tls_index *ti); - -#endif diff --git a/repos/os/src/lib/ldso/contrib/arm/rtld_start.S b/repos/os/src/lib/ldso/contrib/arm/rtld_start.S deleted file mode 100644 index 8be73688d..000000000 --- a/repos/os/src/lib/ldso/contrib/arm/rtld_start.S +++ /dev/null @@ -1,101 +0,0 @@ -/* $NetBSD: rtld_start.S,v 1.7 2002/09/12 17:18:38 mycroft Exp $ */ - -/*- - * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Matt Thomas and by Charles M. Hannum. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the NetBSD - * Foundation, Inc. and its contributors. - * 4. Neither the name of The NetBSD Foundation nor the names of its - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include -__FBSDID("$FreeBSD: src/libexec/rtld-elf/arm/rtld_start.S,v 1.3.20.1 2009/04/15 03:14:26 kensmith Exp $"); - - .text - .align 0 - .globl .rtld_start - .type .rtld_start,%function -.rtld_start: - sub sp, sp, #8 /* make room for obj_main & exit proc */ - mov r4, r0 /* save ps_strings */ - ldr sl, .L2 - ldr r5, .L2+4 - ldr r0, .L2+8 -.L1: - add sl, pc, sl - ldr r5, [sl, r5] - ldr r0, [sl, r0] - - sub r1, sl, r5 /* relocbase */ - add r0, r1, r0 /* &_DYNAMIC */ - bl _rtld_relocate_nonplt_self - mov r1, sp - add r2, sp, #4 - add r0, sp, #8 - bl _rtld /* call the shared loader */ - mov r3, r0 /* save entry point */ - - ldr r2, [sp, #0] /* r2 = cleanup */ - ldr r1, [sp, #4] /* r1 = obj_main */ - add sp, sp, #8 /* restore stack */ - mov r0, r4 /* restore ps_strings */ - mov pc, r3 /* jump to the entry point */ -.L2: - .word _GLOBAL_OFFSET_TABLE_ - (.L1+8) - .word _GLOBAL_OFFSET_TABLE_(GOT) - .word _DYNAMIC(GOT) - - .align 0 - .globl _rtld_bind_start - .type _rtld_bind_start,%function -/* - * stack[0] = RA - * ip = &GOT[n+3] - * lr = &GOT[2] - */ -_rtld_bind_start: - stmdb sp!,{r0-r4,sl,fp} - - sub r1, ip, lr /* r1 = 4 * (n + 1) */ - sub r1, r1, #4 /* r1 = 4 * n */ - add r1, r1, r1 /* r1 = 8 * n */ - - ldr r0, [lr, #-4] /* get obj ptr from GOT[1] */ - mov r4, ip /* save GOT location */ - - bl _rtld_bind /* Call the binder */ - - str r0, [r4] /* save address in GOT */ - mov ip, r0 /* save new address */ - - ldmia sp!,{r0-r4,sl,fp,lr} /* restore the stack */ - mov pc, ip /* jump to the new address */ - diff --git a/repos/os/src/lib/ldso/contrib/debug.c b/repos/os/src/lib/ldso/contrib/debug.c deleted file mode 100644 index 453aa53ac..000000000 --- a/repos/os/src/lib/ldso/contrib/debug.c +++ /dev/null @@ -1,143 +0,0 @@ -/*- - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/debug.c,v 1.4.30.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -/* - * Support for printing debugging messages. - */ - -#include -#include - -#include "debug.h" -#include "rtld.h" - -static const char rel_header[] = - " symbol name r_info r_offset st_value st_size address value\n" - " ------------------------------------------------------------------------------\n"; -static const char rel_format[] = " %-25s %6lx %08lx %08lx %7d %10p %08lx\n"; - -int debug = 0; - -void -debug_printf(const char *format, ...) -{ - if (debug) { - va_list ap; - va_start(ap, format); - - fflush(stdout); - vfprintf(stderr, format, ap); - putc('\n', stderr); - - va_end(ap); - } -} - -void -dump_relocations (Obj_Entry *obj0) -{ - Obj_Entry *obj; - - for (obj = obj0; obj != NULL; obj = obj->next) { - dump_obj_relocations(obj); - } -} - -void -dump_obj_relocations (Obj_Entry *obj) -{ - - printf("Object \"%s\", relocbase %p\n", obj->path, obj->relocbase); - - if (obj->relsize) { - printf("Non-PLT Relocations: %ld\n", - (obj->relsize / sizeof(Elf_Rel))); - dump_Elf_Rel(obj, obj->rel, obj->relsize); - } - - if (obj->relasize) { - printf("Non-PLT Relocations with Addend: %ld\n", - (obj->relasize / sizeof(Elf_Rela))); - dump_Elf_Rela(obj, obj->rela, obj->relasize); - } - - if (obj->pltrelsize) { - printf("PLT Relocations: %ld\n", - (obj->pltrelsize / sizeof(Elf_Rel))); - dump_Elf_Rel(obj, obj->pltrel, obj->pltrelsize); - } - - if (obj->pltrelasize) { - printf("PLT Relocations with Addend: %ld\n", - (obj->pltrelasize / sizeof(Elf_Rela))); - dump_Elf_Rela(obj, obj->pltrela, obj->pltrelasize); - } -} - -void -dump_Elf_Rel (Obj_Entry *obj, const Elf_Rel *rel0, u_long relsize) -{ - const Elf_Rel *rel; - const Elf_Rel *rellim; - const Elf_Sym *sym; - Elf_Addr *dstaddr; - - printf("%s", rel_header); - rellim = (const Elf_Rel *)((const char *)rel0 + relsize); - for (rel = rel0; rel < rellim; rel++) { - dstaddr = (Elf_Addr *)(obj->relocbase + rel->r_offset); - sym = obj->symtab + ELF_R_SYM(rel->r_info); - printf(rel_format, - obj->strtab + sym->st_name, - (u_long)rel->r_info, (u_long)rel->r_offset, - (u_long)sym->st_value, (int)sym->st_size, - dstaddr, (u_long)*dstaddr); - } - return; -} - -void -dump_Elf_Rela (Obj_Entry *obj, const Elf_Rela *rela0, u_long relasize) -{ - const Elf_Rela *rela; - const Elf_Rela *relalim; - const Elf_Sym *sym; - Elf_Addr *dstaddr; - - printf("%s", rel_header); - relalim = (const Elf_Rela *)((const char *)rela0 + relasize); - for (rela = rela0; rela < relalim; rela++) { - dstaddr = (Elf_Addr *)(obj->relocbase + rela->r_offset); - sym = obj->symtab + ELF_R_SYM(rela->r_info); - printf(rel_format, - obj->strtab + sym->st_name, - (u_long)rela->r_info, (u_long)rela->r_offset, - (u_long)sym->st_value, (int)sym->st_size, - dstaddr, (u_long)*dstaddr); - } - return; -} diff --git a/repos/os/src/lib/ldso/contrib/debug.h b/repos/os/src/lib/ldso/contrib/debug.h deleted file mode 100644 index e9ccc6df1..000000000 --- a/repos/os/src/lib/ldso/contrib/debug.h +++ /dev/null @@ -1,66 +0,0 @@ -/*- - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/debug.h,v 1.7.8.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -/* - * Support for printing debugging messages. - */ - -#ifndef DEBUG_H -#define DEBUG_H 1 - -#ifndef __GNUC__ -#error "This file must be compiled with GCC" -#endif - -#include - -#include -#include - -extern void debug_printf(const char *, ...) __printflike(1, 2); -extern int debug; - -#ifdef DEBUG -#define dbg(...) debug_printf(__VA_ARGS__) -#else -#define dbg(...) ((void) 0) -#endif - -#ifndef COMPAT_32BIT -#define _MYNAME "ld-elf.so.1" -#else -#define _MYNAME "ld-elf32.so.1" -#endif - -#define assert(cond) ((cond) ? (void) 0 : \ - (msg(_MYNAME ": assert failed: " __FILE__ ":" \ - __XSTRING(__LINE__) "\n"), abort())) -#define msg(s) write(STDOUT_FILENO, s, strlen(s)) -#define trace() msg(_MYNAME ": " __XSTRING(__LINE__) "\n") - - -#endif /* DEBUG_H */ diff --git a/repos/os/src/lib/ldso/contrib/i386/reloc.c b/repos/os/src/lib/ldso/contrib/i386/reloc.c deleted file mode 100644 index 0a02e5c4d..000000000 --- a/repos/os/src/lib/ldso/contrib/i386/reloc.c +++ /dev/null @@ -1,387 +0,0 @@ -/*- - * Copyright 1996, 1997, 1998, 1999 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/i386/reloc.c,v 1.20.8.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -/* - * Dynamic linker for ELF. - * - * John Polstra . - */ - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "rtld.h" - -/* - * Process the special R_386_COPY relocations in the main program. These - * copy data from a shared object into a region in the main program's BSS - * segment. - * - * Returns 0 on success, -1 on failure. - */ -int -do_copy_relocations(Obj_Entry *dstobj) -{ - const Elf_Rel *rellim; - const Elf_Rel *rel; - - assert(dstobj->mainprog); /* COPY relocations are invalid elsewhere */ - - rellim = (const Elf_Rel *) ((caddr_t) dstobj->rel + dstobj->relsize); - for (rel = dstobj->rel; rel < rellim; rel++) { - if (ELF_R_TYPE(rel->r_info) == R_386_COPY) { - void *dstaddr; - const Elf_Sym *dstsym; - const char *name; - unsigned long hash; - size_t size; - const void *srcaddr; - const Elf_Sym *srcsym; - const Ver_Entry *ve; - Obj_Entry *srcobj; - - dstaddr = (void *) (dstobj->relocbase + rel->r_offset); - dstsym = dstobj->symtab + ELF_R_SYM(rel->r_info); - name = dstobj->strtab + dstsym->st_name; - hash = elf_hash(name); - size = dstsym->st_size; - ve = fetch_ventry(dstobj, ELF_R_SYM(rel->r_info)); - - for (srcobj = dstobj->next; srcobj != NULL; srcobj = srcobj->next) - if ((srcsym = symlook_obj(name, hash, srcobj, ve, 0)) != NULL) - break; - - if (srcobj == NULL) { - _rtld_error("Undefined symbol \"%s\" referenced from COPY" - " relocation in %s", name, dstobj->path); - return -1; - } - - srcaddr = (const void *) (srcobj->relocbase + srcsym->st_value); - memcpy(dstaddr, srcaddr, size); - } - } - - return 0; -} - -/* Initialize the special GOT entries. */ -void -init_pltgot(Obj_Entry *obj) -{ - if (obj->pltgot != NULL) { - obj->pltgot[1] = (Elf_Addr) obj; - obj->pltgot[2] = (Elf_Addr) &_rtld_bind_start; - } -} - -/* Process the non-PLT relocations. */ -int -reloc_non_plt(Obj_Entry *obj, Obj_Entry *obj_rtld) -{ - const Elf_Rel *rellim; - const Elf_Rel *rel; - SymCache *cache; - int bytes = obj->nchains * sizeof(SymCache); - int r = -1; - /* - * The dynamic loader may be called from a thread, we have - * limited amounts of stack available so we cannot use alloca(). - */ - int flags = obj->rtld_init ? MAP_LDSO : 0; - cache = mmap(NULL, bytes, PROT_READ|PROT_WRITE, MAP_ANON|flags, -1, 0); - if (cache == MAP_FAILED) - cache = NULL; - - rellim = (const Elf_Rel *) ((caddr_t) obj->rel + obj->relsize); - for (rel = obj->rel; rel < rellim; rel++) { - Elf_Addr *where = (Elf_Addr *) (obj->relocbase + rel->r_offset); - - /* - * cbass: - * This is the second relocation run for LDSO, relocate global - * symbols only, in order to resolve e.g. type informations in - * binary - */ - if (obj->rtld && !obj->rtld_init) { - switch (ELF_R_TYPE(rel->r_info)) { - - case R_386_GLOB_DAT: - break; - default: - continue; - } - } - - switch (ELF_R_TYPE(rel->r_info)) { - - case R_386_NONE: - break; - - case R_386_32: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - *where += (Elf_Addr) (defobj->relocbase + def->st_value); - } - break; - - case R_386_PC32: - /* - * I don't think the dynamic linker should ever see this - * type of relocation. But the binutils-2.6 tools sometimes - * generate it. - */ - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - *where += - (Elf_Addr) (defobj->relocbase + def->st_value) - - (Elf_Addr) where; - } - break; - - case R_386_COPY: - /* - * These are deferred until all other relocations have - * been done. All we do here is make sure that the COPY - * relocation is not in a shared library. They are allowed - * only in executable files. - */ - if (!obj->mainprog) { - _rtld_error("%s: Unexpected R_386_COPY relocation" - " in shared library", obj->path); - goto done; - } - break; - - case R_386_GLOB_DAT: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); - /* cbass: Skip undefined symbols */ - if (def == NULL || defobj == NULL) - continue; - - *where = (Elf_Addr) (defobj->relocbase + def->st_value); - } - break; - - case R_386_RELATIVE: - /* skip text relocations for ld.lib.so, since relocbase is 0 - * here */ - if (!obj->rtld) - *where += (Elf_Addr) obj->relocbase; - break; - - case R_386_TLS_TPOFF: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - /* - * We lazily allocate offsets for static TLS as we - * see the first relocation that references the - * TLS block. This allows us to support (small - * amounts of) static TLS in dynamically loaded - * modules. If we run out of space, we generate an - * error. - */ - if (!defobj->tls_done) { - if (!allocate_tls_offset((Obj_Entry*) defobj)) { - _rtld_error("%s: No space available for static " - "Thread Local Storage", obj->path); - goto done; - } - } - - *where += (Elf_Addr) (def->st_value - defobj->tlsoffset); - } - break; - - case R_386_TLS_DTPMOD32: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - *where += (Elf_Addr) defobj->tlsindex; - } - break; - - case R_386_TLS_DTPOFF32: - { - const Elf_Sym *def; - const Obj_Entry *defobj; - - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, - false, cache); - if (def == NULL) - goto done; - - *where += (Elf_Addr) def->st_value; - } - break; - - default: - _rtld_error("%s: Unsupported relocation type %d" - " in non-PLT relocations\n", obj->path, - ELF_R_TYPE(rel->r_info)); - goto done; - } - } - r = 0; -done: - - /* - * Do not unmap if LDSO is in initialization, since some ctors might not - * be called, yet. - */ - if (cache && !(obj->rtld_init)) - munmap(cache, bytes); - return(r); -} - -/* Process the PLT relocations. */ -int -reloc_plt(Obj_Entry *obj) -{ - const Elf_Rel *rellim; - const Elf_Rel *rel; - - rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize); - for (rel = obj->pltrel; rel < rellim; rel++) { - Elf_Addr *where; - - assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT); - - /* Relocate the GOT slot pointing into the PLT. */ - where = (Elf_Addr *)(obj->relocbase + rel->r_offset); - *where += (Elf_Addr)obj->relocbase; - } - return 0; -} - -/* Relocate the jump slots in an object. */ -int -reloc_jmpslots(Obj_Entry *obj) -{ - const Elf_Rel *rellim; - const Elf_Rel *rel; - - if (obj->jmpslots_done) - return 0; - rellim = (const Elf_Rel *)((char *)obj->pltrel + obj->pltrelsize); - for (rel = obj->pltrel; rel < rellim; rel++) { - Elf_Addr *where, target; - const Elf_Sym *def; - const Obj_Entry *defobj; - - assert(ELF_R_TYPE(rel->r_info) == R_386_JMP_SLOT); - where = (Elf_Addr *)(obj->relocbase + rel->r_offset); - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL); - if (def == NULL) - return -1; - target = (Elf_Addr)(defobj->relocbase + def->st_value); - reloc_jmpslot(where, target, defobj, obj, rel); - } - obj->jmpslots_done = true; - return 0; -} - -void -allocate_initial_tls(Obj_Entry *objs) -{ - void* tls; - - /* - * Fix the size of the static TLS block by using the maximum - * offset allocated so far and adding a bit for dynamic modules to - * use. - */ - tls_static_space = tls_last_offset + RTLD_STATIC_TLS_EXTRA; - tls = allocate_tls(objs, NULL, 3*sizeof(Elf_Addr), sizeof(Elf_Addr)); - i386_set_gsbase(tls); -} - -/* GNU ABI */ -__attribute__((__regparm__(1))) -void *___tls_get_addr(tls_index *ti) -{ - Elf_Addr** segbase; - - __asm __volatile("movl %%gs:0, %0" : "=r" (segbase)); - - return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset); -} - -/* Sun ABI */ -void *__tls_get_addr(tls_index *ti) -{ - Elf_Addr** segbase; - - __asm __volatile("movl %%gs:0, %0" : "=r" (segbase)); - - return tls_get_addr_common(&segbase[1], ti->ti_module, ti->ti_offset); -} diff --git a/repos/os/src/lib/ldso/contrib/i386/rtld_machdep.h b/repos/os/src/lib/ldso/contrib/i386/rtld_machdep.h deleted file mode 100644 index df3c326d5..000000000 --- a/repos/os/src/lib/ldso/contrib/i386/rtld_machdep.h +++ /dev/null @@ -1,79 +0,0 @@ -/*- - * Copyright (c) 1999, 2000 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/i386/rtld_machdep.h,v 1.11.8.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -#ifndef RTLD_MACHDEP_H -#define RTLD_MACHDEP_H 1 - -#include -#include - -#define CACHE_LINE_SIZE 32 - -struct Struct_Obj_Entry; - -/* Return the address of the .dynamic section in the dynamic linker. */ -#define rtld_dynamic(obj) \ - ((const Elf_Dyn *)((obj)->relocbase + (Elf_Addr)&_DYNAMIC)) - -/* Fixup the jump slot at "where" to transfer control to "target". */ -static inline Elf_Addr -reloc_jmpslot(Elf_Addr *where, Elf_Addr target, - const struct Struct_Obj_Entry *obj, - const struct Struct_Obj_Entry *refobj, const Elf_Rel *rel) -{ -#ifdef dbg - dbg("reloc_jmpslot: *%p = %p", (void *)(where), - (void *)(target)); -#endif - (*(Elf_Addr *)(where) = (Elf_Addr)(target)); - return target; -} - -#define make_function_pointer(def, defobj) \ - ((defobj)->relocbase + (def)->st_value) - -#define call_initfini_pointer(obj, target) \ - (((InitFunc)(target))()) - -#define round(size, align) \ - (((size) + (align) - 1) & ~((align) - 1)) -#define calculate_first_tls_offset(size, align) \ - round(size, align) -#define calculate_tls_offset(prev_offset, prev_size, size, align) \ - round((prev_offset) + (size), align) -#define calculate_tls_end(off, size) (off) - -typedef struct { - unsigned long ti_module; - unsigned long ti_offset; -} tls_index; - -extern void *___tls_get_addr(tls_index *ti) __attribute__((__regparm__(1))); -extern void *__tls_get_addr(tls_index *ti); - -#endif diff --git a/repos/os/src/lib/ldso/contrib/i386/rtld_start.S b/repos/os/src/lib/ldso/contrib/i386/rtld_start.S deleted file mode 100644 index cd8cadc0b..000000000 --- a/repos/os/src/lib/ldso/contrib/i386/rtld_start.S +++ /dev/null @@ -1,91 +0,0 @@ -/*- - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/i386/rtld_start.S,v 1.4.20.1 2009/04/15 03:14:26 kensmith Exp $ - */ - - .text - .align 4 - .globl .rtld_start - .type .rtld_start,@function -.rtld_start: - xorl %ebp,%ebp # Clear frame pointer for good form - movl %esp,%eax # Save initial stack pointer - movl %esp,%esi # Save initial stack pointer - andl $0xfffffff0,%esp # Align stack pointer - subl $16,%esp # A place to store exit procedure addr - movl %esp,%ebx # save address of exit proc - movl %esp,%ecx # construct address of obj_main - addl $4,%ecx - subl $4,%esp # Keep stack aligned - pushl %ecx # Pass address of obj_main - pushl %ebx # Pass address of exit proc - pushl %eax # Pass initial stack pointer to rtld - call _rtld@PLT # Call rtld(sp); returns entry point - addl $16,%esp # Remove arguments from stack - popl %edx # Get exit procedure address - movl %esi,%esp # Ignore obj_main -/* - * At this point, %eax contains the entry point of the main program, and - * %edx contains a pointer to a termination function that should be - * registered with atexit(). (crt1.o registers it.) - */ -.globl .rtld_goto_main -.rtld_goto_main: # This symbol exists just to make debugging easier. - jmp *%eax # Enter main program - - -/* - * Binder entry point. Control is transferred to here by code in the PLT. - * On entry, there are two arguments on the stack. In ascending address - * order, they are (1) "obj", a pointer to the calling object's Obj_Entry, - * and (2) "reloff", the byte offset of the appropriate relocation entry - * in the PLT relocation table. - * - * We are careful to preserve all registers, even the the caller-save - * registers. That is because this code may be invoked by low-level - * assembly-language code that is not ABI-compliant. - */ - .align 4 - .globl _rtld_bind_start - .type _rtld_bind_start,@function -_rtld_bind_start: - pushf # Save eflags - pushl %eax # Save %eax - pushl %edx # Save %edx - pushl %ecx # Save %ecx - pushl 20(%esp) # Copy reloff argument - pushl 20(%esp) # Copy obj argument - - call _rtld_bind@PLT # Transfer control to the binder - /* Now %eax contains the entry point of the function being called. */ - - addl $8,%esp # Discard binder arguments - movl %eax,20(%esp) # Store target over obj argument - popl %ecx # Restore %ecx - popl %edx # Restore %edx - popl %eax # Restore %eax - popf # Restore eflags - leal 4(%esp),%esp # Discard reloff, do not change eflags - ret # "Return" to target address diff --git a/repos/os/src/lib/ldso/contrib/libmap.c b/repos/os/src/lib/ldso/contrib/libmap.c deleted file mode 100644 index a20ab7013..000000000 --- a/repos/os/src/lib/ldso/contrib/libmap.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * $FreeBSD: src/libexec/rtld-elf/libmap.c,v 1.15.8.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "rtld.h" -#include "libmap.h" - -#ifndef _PATH_LIBMAP_CONF -#define _PATH_LIBMAP_CONF "/etc/libmap.conf" -#endif - -#ifdef COMPAT_32BIT -#undef _PATH_LIBMAP_CONF -#define _PATH_LIBMAP_CONF "/etc/libmap32.conf" -#endif - -TAILQ_HEAD(lm_list, lm); -struct lm { - char *f; - char *t; - - TAILQ_ENTRY(lm) lm_link; -}; - -TAILQ_HEAD(lmp_list, lmp) lmp_head = TAILQ_HEAD_INITIALIZER(lmp_head); -struct lmp { - char *p; - enum { T_EXACT=0, T_BASENAME, T_DIRECTORY } type; - struct lm_list lml; - TAILQ_ENTRY(lmp) lmp_link; -}; - -static int lm_count; - -static void lmc_parse (FILE *); -static void lm_add (const char *, const char *, const char *); -static void lm_free (struct lm_list *); -static char * lml_find (struct lm_list *, const char *); -static struct lm_list * lmp_find (const char *); -static struct lm_list * lmp_init (char *); -static const char * quickbasename (const char *); -static int readstrfn (void * cookie, char *buf, int len); -static int closestrfn (void * cookie); - -#define iseol(c) (((c) == '#') || ((c) == '\0') || \ - ((c) == '\n') || ((c) == '\r')) - -int -lm_init (char *libmap_override) -{ - FILE *fp; - - dbg("%s(\"%s\")", __func__, libmap_override); - - TAILQ_INIT(&lmp_head); - - fp = fopen(_PATH_LIBMAP_CONF, "r"); - if (fp) { - lmc_parse(fp); - fclose(fp); - } - - if (libmap_override) { - char *p; - /* do some character replacement to make $LIBMAP look like a - text file, then "open" it with funopen */ - libmap_override = xstrdup(libmap_override); - - for (p = libmap_override; *p; p++) { - switch (*p) { - case '=': - *p = ' '; break; - case ',': - *p = '\n'; break; - } - } - fp = funopen(libmap_override, readstrfn, NULL, NULL, closestrfn); - if (fp) { - lmc_parse(fp); - fclose(fp); - } - } - - return (lm_count == 0); -} - -static void -lmc_parse (FILE *fp) -{ - char *cp; - char *f, *t, *c, *p; - char prog[MAXPATHLEN]; - char line[MAXPATHLEN + 2]; - - dbg("%s(%p)", __func__, fp); - - p = NULL; - while ((cp = fgets(line, MAXPATHLEN + 1, fp)) != NULL) { - t = f = c = NULL; - - /* Skip over leading space */ - while (isspace(*cp)) cp++; - - /* Found a comment or EOL */ - if (iseol(*cp)) continue; - - /* Found a constraint selector */ - if (*cp == '[') { - cp++; - - /* Skip leading space */ - while (isspace(*cp)) cp++; - - /* Found comment, EOL or end of selector */ - if (iseol(*cp) || *cp == ']') - continue; - - c = cp++; - /* Skip to end of word */ - while (!isspace(*cp) && !iseol(*cp) && *cp != ']') - cp++; - - /* Skip and zero out trailing space */ - while (isspace(*cp)) *cp++ = '\0'; - - /* Check if there is a closing brace */ - if (*cp != ']') continue; - - /* Terminate string if there was no trailing space */ - *cp++ = '\0'; - - /* - * There should be nothing except whitespace or comment - from this point to the end of the line. - */ - while(isspace(*cp)) cp++; - if (!iseol(*cp)) continue; - - strcpy(prog, c); - p = prog; - continue; - } - - /* Parse the 'from' candidate. */ - f = cp++; - while (!isspace(*cp) && !iseol(*cp)) cp++; - - /* Skip and zero out the trailing whitespace */ - while (isspace(*cp)) *cp++ = '\0'; - - /* Found a comment or EOL */ - if (iseol(*cp)) continue; - - /* Parse 'to' mapping */ - t = cp++; - while (!isspace(*cp) && !iseol(*cp)) cp++; - - /* Skip and zero out the trailing whitespace */ - while (isspace(*cp)) *cp++ = '\0'; - - /* Should be no extra tokens at this point */ - if (!iseol(*cp)) continue; - - *cp = '\0'; - lm_add(p, f, t); - } -} - -static void -lm_free (struct lm_list *lml) -{ - struct lm *lm; - - dbg("%s(%p)", __func__, lml); - - while (!TAILQ_EMPTY(lml)) { - lm = TAILQ_FIRST(lml); - TAILQ_REMOVE(lml, lm, lm_link); - free(lm->f); - free(lm->t); - free(lm); - } - return; -} - -void -lm_fini (void) -{ - struct lmp *lmp; - - dbg("%s()", __func__); - - while (!TAILQ_EMPTY(&lmp_head)) { - lmp = TAILQ_FIRST(&lmp_head); - TAILQ_REMOVE(&lmp_head, lmp, lmp_link); - free(lmp->p); - lm_free(&lmp->lml); - free(lmp); - } - return; -} - -static void -lm_add (const char *p, const char *f, const char *t) -{ - struct lm_list *lml; - struct lm *lm; - - if (p == NULL) - p = "$DEFAULT$"; - - dbg("%s(\"%s\", \"%s\", \"%s\")", __func__, p, f, t); - - if ((lml = lmp_find(p)) == NULL) - lml = lmp_init(xstrdup(p)); - - lm = xmalloc(sizeof(struct lm)); - lm->f = xstrdup(f); - lm->t = xstrdup(t); - TAILQ_INSERT_HEAD(lml, lm, lm_link); - lm_count++; -} - -char * -lm_find (const char *p, const char *f) -{ - struct lm_list *lml; - char *t; - - dbg("%s(\"%s\", \"%s\")", __func__, p, f); - - if (p != NULL && (lml = lmp_find(p)) != NULL) { - t = lml_find(lml, f); - if (t != NULL) { - /* - * Add a global mapping if we have - * a successful constrained match. - */ - lm_add(NULL, f, t); - return (t); - } - } - lml = lmp_find("$DEFAULT$"); - if (lml != NULL) - return (lml_find(lml, f)); - else - return (NULL); -} - -/* Given a libmap translation list and a library name, return the - replacement library, or NULL */ -#ifdef COMPAT_32BIT -char * -lm_findn (const char *p, const char *f, const int n) -{ - char pathbuf[64], *s, *t; - - if (n < sizeof(pathbuf) - 1) - s = pathbuf; - else - s = xmalloc(n + 1); - memcpy(s, f, n); - s[n] = '\0'; - t = lm_find(p, s); - if (s != pathbuf) - free(s); - return (t); -} -#endif - -static char * -lml_find (struct lm_list *lmh, const char *f) -{ - struct lm *lm; - - dbg("%s(%p, \"%s\")", __func__, lmh, f); - - TAILQ_FOREACH(lm, lmh, lm_link) - if (strcmp(f, lm->f) == 0) - return (lm->t); - return (NULL); -} - -/* Given an executable name, return a pointer to the translation list or - NULL if no matches */ -static struct lm_list * -lmp_find (const char *n) -{ - struct lmp *lmp; - - dbg("%s(\"%s\")", __func__, n); - - TAILQ_FOREACH(lmp, &lmp_head, lmp_link) - if ((lmp->type == T_EXACT && strcmp(n, lmp->p) == 0) || - (lmp->type == T_DIRECTORY && strncmp(n, lmp->p, strlen(lmp->p)) == 0) || - (lmp->type == T_BASENAME && strcmp(quickbasename(n), lmp->p) == 0)) - return (&lmp->lml); - return (NULL); -} - -static struct lm_list * -lmp_init (char *n) -{ - struct lmp *lmp; - - dbg("%s(\"%s\")", __func__, n); - - lmp = xmalloc(sizeof(struct lmp)); - lmp->p = n; - if (n[strlen(n)-1] == '/') - lmp->type = T_DIRECTORY; - else if (strchr(n,'/') == NULL) - lmp->type = T_BASENAME; - else - lmp->type = T_EXACT; - TAILQ_INIT(&lmp->lml); - TAILQ_INSERT_HEAD(&lmp_head, lmp, lmp_link); - - return (&lmp->lml); -} - -/* libc basename is overkill. Return a pointer to the character after the - last /, or the original string if there are no slashes. */ -static const char * -quickbasename (const char *path) -{ - const char *p = path; - for (; *path; path++) { - if (*path == '/') - p = path+1; - } - return (p); -} - -static int -readstrfn(void * cookie, char *buf, int len) -{ - static char *current; - static int left; - int copied; - - copied = 0; - if (!current) { - current = cookie; - left = strlen(cookie); - } - while (*current && left && len) { - *buf++ = *current++; - left--; - len--; - copied++; - } - return copied; -} - -static int -closestrfn(void * cookie) -{ - free(cookie); - return 0; -} diff --git a/repos/os/src/lib/ldso/contrib/libmap.h b/repos/os/src/lib/ldso/contrib/libmap.h deleted file mode 100644 index d0cbe5659..000000000 --- a/repos/os/src/lib/ldso/contrib/libmap.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * $FreeBSD: src/libexec/rtld-elf/libmap.h,v 1.4.20.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -int lm_init (char *); -void lm_fini (void); -char * lm_find (const char *, const char *); -#ifdef COMPAT_32BIT -char * lm_findn (const char *, const char *, const int); -#endif diff --git a/repos/os/src/lib/ldso/contrib/malloc.c b/repos/os/src/lib/ldso/contrib/malloc.c deleted file mode 100644 index cff52b6e1..000000000 --- a/repos/os/src/lib/ldso/contrib/malloc.c +++ /dev/null @@ -1,518 +0,0 @@ -/*- - * Copyright (c) 1983 Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)malloc.c 5.11 (Berkeley) 2/23/91";*/ -static char *rcsid = "$FreeBSD: src/libexec/rtld-elf/malloc.c,v 1.11.8.1 2009/04/15 03:14:26 kensmith Exp $"; -#endif /* LIBC_SCCS and not lint */ - -/* - * malloc.c (Caltech) 2/21/82 - * Chris Kingsley, kingsley@cit-20. - * - * This is a very fast storage allocator. It allocates blocks of a small - * number of different sizes, and keeps free lists of each size. Blocks that - * don't exactly fit are passed up to the next larger size. In this - * implementation, the available sizes are 2^n-4 (or 2^n-10) bytes long. - * This is designed for use in a virtual memory environment. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifndef BSD -#define MAP_COPY MAP_PRIVATE -#define MAP_FILE 0 -//#define MAP_ANON 0 -#endif - -#ifndef BSD /* Need do better than this */ -#define NEED_DEV_ZERO 1 -#endif - -static void morecore(); -static int findbucket(); - -/* - * Pre-allocate mmap'ed pages - */ -#define NPOOLPAGES (32*1024/pagesz) -static caddr_t pagepool_start, pagepool_end; -static int morepages(); - -/* - * The overhead on a block is at least 4 bytes. When free, this space - * contains a pointer to the next free block, and the bottom two bits must - * be zero. When in use, the first byte is set to MAGIC, and the second - * byte is the size index. The remaining bytes are for alignment. - * If range checking is enabled then a second word holds the size of the - * requested block, less 1, rounded up to a multiple of sizeof(RMAGIC). - * The order of elements is critical: ov_magic must overlay the low order - * bits of ov_next, and ov_magic can not be a valid ov_next bit pattern. - */ -union overhead { - union overhead *ov_next; /* when free */ - struct { - u_char ovu_magic; /* magic number */ - u_char ovu_index; /* bucket # */ -#ifdef RCHECK - u_short ovu_rmagic; /* range magic number */ - u_int ovu_size; /* actual block size */ -#endif - } ovu; -#define ov_magic ovu.ovu_magic -#define ov_index ovu.ovu_index -#define ov_rmagic ovu.ovu_rmagic -#define ov_size ovu.ovu_size -}; - -#define MAGIC 0xef /* magic # on accounting info */ -#define RMAGIC 0x5555 /* magic # on range info */ - -#ifdef RCHECK -#define RSLOP sizeof (u_short) -#else -#define RSLOP 0 -#endif - -/* - * nextf[i] is the pointer to the next free block of size 2^(i+3). The - * smallest allocatable block is 8 bytes. The overhead information - * precedes the data area returned to the user. - */ -#define NBUCKETS 30 -static union overhead *nextf[NBUCKETS]; - -static int pagesz; /* page size */ -static int pagebucket; /* page size bucket */ - -#ifdef MSTATS -/* - * nmalloc[i] is the difference between the number of mallocs and frees - * for a given block size. - */ -static u_int nmalloc[NBUCKETS]; -#include -#endif - -#if defined(MALLOC_DEBUG) || defined(RCHECK) -#define ASSERT(p) if (!(p)) botch("p") -#include -static void -botch(s) - char *s; -{ - fprintf(stderr, "\r\nassertion botched: %s\r\n", s); - (void) fflush(stderr); /* just in case user buffered it */ - abort(); -} -#else -#define ASSERT(p) -#endif - -/* Debugging stuff */ -static void xprintf(const char *, ...); -#define TRACE() xprintf("TRACE %s:%d\n", __FILE__, __LINE__) - -void * -malloc(nbytes) - size_t nbytes; -{ - register union overhead *op; - register int bucket; - register long n; - register unsigned amt; - - /* - * First time malloc is called, setup page size and - * align break pointer so all data will be page aligned. - */ - if (pagesz == 0) { - pagesz = n = getpagesize(); - if (morepages(NPOOLPAGES) == 0) - return NULL; - op = (union overhead *)(pagepool_start); - n = n - sizeof (*op) - ((long)op & (n - 1)); - if (n < 0) - n += pagesz; - if (n) { - pagepool_start += n; - } - bucket = 0; - amt = 8; - while ((unsigned)pagesz > amt) { - amt <<= 1; - bucket++; - } - pagebucket = bucket; - } - /* - * Convert amount of memory requested into closest block size - * stored in hash buckets which satisfies request. - * Account for space used per block for accounting. - */ - if (nbytes <= (unsigned long)(n = pagesz - sizeof (*op) - RSLOP)) { -#ifndef RCHECK - amt = 8; /* size of first bucket */ - bucket = 0; -#else - amt = 16; /* size of first bucket */ - bucket = 1; -#endif - n = -(sizeof (*op) + RSLOP); - } else { - amt = pagesz; - bucket = pagebucket; - } - while (nbytes > amt + n) { - amt <<= 1; - if (amt == 0) - return (NULL); - bucket++; - } - /* - * If nothing in hash bucket right now, - * request more memory from the system. - */ - if ((op = nextf[bucket]) == NULL) { - morecore(bucket); - if ((op = nextf[bucket]) == NULL) - return (NULL); - } - /* remove from linked list */ - nextf[bucket] = op->ov_next; - op->ov_magic = MAGIC; - op->ov_index = bucket; -#ifdef MSTATS - nmalloc[bucket]++; -#endif -#ifdef RCHECK - /* - * Record allocated size of block and - * bound space with magic numbers. - */ - op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); - op->ov_rmagic = RMAGIC; - *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; -#endif - return ((char *)(op + 1)); -} - -void * -calloc(size_t num, size_t size) -{ - void *ret; - - if (size != 0 && (num * size) / size != num) { - /* size_t overflow. */ - return (NULL); - } - - if ((ret = malloc(num * size)) != NULL) - memset(ret, 0, num * size); - - return (ret); -} - -/* - * Allocate more memory to the indicated bucket. - */ -static void -morecore(bucket) - int bucket; -{ - register union overhead *op; - register int sz; /* size of desired block */ - int amt; /* amount to allocate */ - int nblks; /* how many blocks we get */ - - /* - * sbrk_size <= 0 only for big, FLUFFY, requests (about - * 2^30 bytes on a VAX, I think) or for a negative arg. - */ - sz = 1 << (bucket + 3); -#ifdef MALLOC_DEBUG - ASSERT(sz > 0); -#else - if (sz <= 0) - return; -#endif - if (sz < pagesz) { - amt = pagesz; - nblks = amt / sz; - } else { - amt = sz + pagesz; - nblks = 1; - } - if (amt > pagepool_end - pagepool_start) - if (morepages(amt/pagesz + NPOOLPAGES) == 0) - return; - op = (union overhead *)pagepool_start; - pagepool_start += amt; - - /* - * Add new memory allocated to that on - * free list for this hash bucket. - */ - nextf[bucket] = op; - while (--nblks > 0) { - op->ov_next = (union overhead *)((caddr_t)op + sz); - op = (union overhead *)((caddr_t)op + sz); - } -} - -void -free(cp) - void *cp; -{ - register int size; - register union overhead *op; - - if (cp == NULL) - return; - op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); -#ifdef MALLOC_DEBUG - ASSERT(op->ov_magic == MAGIC); /* make sure it was in use */ -#else - if (op->ov_magic != MAGIC) - return; /* sanity */ -#endif -#ifdef RCHECK - ASSERT(op->ov_rmagic == RMAGIC); - ASSERT(*(u_short *)((caddr_t)(op + 1) + op->ov_size) == RMAGIC); -#endif - size = op->ov_index; - ASSERT(size < NBUCKETS); - op->ov_next = nextf[size]; /* also clobbers ov_magic */ - nextf[size] = op; -#ifdef MSTATS - nmalloc[size]--; -#endif -} - -/* - * When a program attempts "storage compaction" as mentioned in the - * old malloc man page, it realloc's an already freed block. Usually - * this is the last block it freed; occasionally it might be farther - * back. We have to search all the free lists for the block in order - * to determine its bucket: 1st we make one pass thru the lists - * checking only the first block in each; if that fails we search - * ``realloc_srchlen'' blocks in each list for a match (the variable - * is extern so the caller can modify it). If that fails we just copy - * however many bytes was given to realloc() and hope it's not huge. - */ -int realloc_srchlen = 4; /* 4 should be plenty, -1 =>'s whole list */ - -void * -realloc(cp, nbytes) - void *cp; - size_t nbytes; -{ - register u_int onb; - register int i; - union overhead *op; - char *res; - int was_alloced = 0; - - if (cp == NULL) - return (malloc(nbytes)); - op = (union overhead *)((caddr_t)cp - sizeof (union overhead)); - if (op->ov_magic == MAGIC) { - was_alloced++; - i = op->ov_index; - } else { - /* - * Already free, doing "compaction". - * - * Search for the old block of memory on the - * free list. First, check the most common - * case (last element free'd), then (this failing) - * the last ``realloc_srchlen'' items free'd. - * If all lookups fail, then assume the size of - * the memory block being realloc'd is the - * largest possible (so that all "nbytes" of new - * memory are copied into). Note that this could cause - * a memory fault if the old area was tiny, and the moon - * is gibbous. However, that is very unlikely. - */ - if ((i = findbucket(op, 1)) < 0 && - (i = findbucket(op, realloc_srchlen)) < 0) - i = NBUCKETS; - } - onb = 1 << (i + 3); - if (onb < (u_int)pagesz) - onb -= sizeof (*op) + RSLOP; - else - onb += pagesz - sizeof (*op) - RSLOP; - /* avoid the copy if same size block */ - if (was_alloced) { - if (i) { - i = 1 << (i + 2); - if (i < pagesz) - i -= sizeof (*op) + RSLOP; - else - i += pagesz - sizeof (*op) - RSLOP; - } - if (nbytes <= onb && nbytes > (size_t)i) { -#ifdef RCHECK - op->ov_size = (nbytes + RSLOP - 1) & ~(RSLOP - 1); - *(u_short *)((caddr_t)(op + 1) + op->ov_size) = RMAGIC; -#endif - return(cp); - } else - free(cp); - } - if ((res = malloc(nbytes)) == NULL) - return (NULL); - if (cp != res) /* common optimization if "compacting" */ - bcopy(cp, res, (nbytes < onb) ? nbytes : onb); - return (res); -} - -/* - * Search ``srchlen'' elements of each free list for a block whose - * header starts at ``freep''. If srchlen is -1 search the whole list. - * Return bucket number, or -1 if not found. - */ -static int -findbucket(freep, srchlen) - union overhead *freep; - int srchlen; -{ - register union overhead *p; - register int i, j; - - for (i = 0; i < NBUCKETS; i++) { - j = 0; - for (p = nextf[i]; p && j != srchlen; p = p->ov_next) { - if (p == freep) - return (i); - j++; - } - } - return (-1); -} - -#ifdef MSTATS -/* - * mstats - print out statistics about malloc - * - * Prints two lines of numbers, one showing the length of the free list - * for each size category, the second showing the number of mallocs - - * frees for each size category. - */ -mstats(s) - char *s; -{ - register int i, j; - register union overhead *p; - int totfree = 0, - totused = 0; - - fprintf(stderr, "Memory allocation statistics %s\nfree:\t", s); - for (i = 0; i < NBUCKETS; i++) { - for (j = 0, p = nextf[i]; p; p = p->ov_next, j++) - ; - fprintf(stderr, " %d", j); - totfree += j * (1 << (i + 3)); - } - fprintf(stderr, "\nused:\t"); - for (i = 0; i < NBUCKETS; i++) { - fprintf(stderr, " %d", nmalloc[i]); - totused += nmalloc[i] * (1 << (i + 3)); - } - fprintf(stderr, "\n\tTotal in use: %d, total free: %d\n", - totused, totfree); -} -#endif - - -static int -morepages(n) -int n; -{ - int fd = -1; - int offset; - -#ifdef NEED_DEV_ZERO - fd = open(_PATH_DEVZERO, O_RDWR, 0); - if (fd == -1) - perror(_PATH_DEVZERO); -#endif - - if (pagepool_end - pagepool_start > pagesz) { - caddr_t addr = (caddr_t) - (((long)pagepool_start + pagesz - 1) & ~(pagesz - 1)); - if (munmap(addr, pagepool_end - addr) != 0) - warn("morepages: munmap %p", addr); - } - - offset = (long)pagepool_start - ((long)pagepool_start & ~(pagesz - 1)); - - if ((pagepool_start = mmap(0, n * pagesz, - PROT_READ|PROT_WRITE, - MAP_ANON|MAP_COPY, fd, 0)) == (caddr_t)-1) { - xprintf("Cannot map anonymous memory"); - return 0; - } - pagepool_end = pagepool_start + n * pagesz; - pagepool_start += offset; - -#ifdef NEED_DEV_ZERO - close(fd); -#endif - return n; -} - -/* - * Non-mallocing printf, for use by malloc itself. - */ -static void -xprintf(const char *fmt, ...) -{ - char buf[256]; - va_list ap; - - va_start(ap, fmt); - vsprintf(buf, fmt, ap); - (void)write(STDOUT_FILENO, buf, strlen(buf)); - va_end(ap); -} diff --git a/repos/os/src/lib/ldso/contrib/map_object.c b/repos/os/src/lib/ldso/contrib/map_object.c deleted file mode 100644 index 6beec5a19..000000000 --- a/repos/os/src/lib/ldso/contrib/map_object.c +++ /dev/null @@ -1,283 +0,0 @@ -/*- - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/map_object.c,v 1.18.8.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "debug.h" -#include "file.h" -#include "rtld.h" - -static Elf_Ehdr *get_elf_header (int, const char *); - -/* - * Map a shared object into memory. The "fd" argument is a file descriptor, - * which must be open on the object and positioned at its beginning. - * The "path" argument is a pathname that is used only for error messages. - * - * The return value is a pointer to a newly-allocated Obj_Entry structure - * for the shared object. Returns NULL on failure. - */ -Obj_Entry * -map_object(int fd, const char *path, const struct stat *sb) -{ - Obj_Entry *obj; - Elf_Ehdr *hdr; - Elf_Phdr *phdr; - Elf_Phdr *phlimit; - Elf_Phdr **segs; - int nsegs; - Elf_Phdr *phdyn; - Elf_Phdr *phinterp; - Elf_Phdr *phtls; - caddr_t mapbase; - size_t mapsize; - Elf_Addr base_vaddr; - Elf_Addr base_vlimit; - size_t phsize; - - hdr = get_elf_header(fd, path); - if (hdr == NULL) - return (NULL); - - /* - * Scan the program header entries, and save key information. - * - * We rely on there being exactly two load segments, text and data, - * in that order. - */ - phdr = (Elf_Phdr *) ((char *)hdr + hdr->e_phoff); - phsize = hdr->e_phnum * sizeof (phdr[0]); - phlimit = phdr + hdr->e_phnum; - nsegs = -1; - phdyn = phinterp = phtls = NULL; - segs = alloca(sizeof(segs[0]) * hdr->e_phnum); - while (phdr < phlimit) { - switch (phdr->p_type) { - - case PT_INTERP: - phinterp = phdr; - break; - - case PT_LOAD: - segs[++nsegs] = phdr; - if ((segs[nsegs]->p_align & (PAGE_SIZE - 1)) != 0) { - _rtld_error("%s: PT_LOAD segment %d not page-aligned", - path, nsegs); - return NULL; - } - break; - - case PT_PHDR: - phsize = phdr->p_memsz; - break; - - case PT_DYNAMIC: - phdyn = phdr; - break; - - case PT_TLS: - phtls = phdr; - break; - } - - ++phdr; - } - if (phdyn == NULL) { - _rtld_error("%s: object is not dynamically-linked", path); - return NULL; - } - - if (nsegs < 0) { - _rtld_error("%s: too few PT_LOAD segments", path); - return NULL; - } - - /* - * Map the entire address space of the object, to stake out our - * contiguous region, and to establish the base address for relocation. - */ - base_vaddr = trunc_page(segs[0]->p_vaddr); - base_vlimit = round_page(segs[nsegs]->p_vaddr + segs[nsegs]->p_memsz); - mapsize = base_vlimit - base_vaddr; - - mapbase = genode_map(fd, segs); - - obj = obj_new(); - if (sb != NULL) { - obj->dev = sb->st_dev; - obj->ino = sb->st_ino; - } - obj->mapbase = mapbase; - obj->mapsize = mapsize; - obj->textsize = round_page(segs[0]->p_vaddr + segs[0]->p_memsz) - - base_vaddr; - obj->vaddrbase = base_vaddr; - obj->relocbase = mapbase - base_vaddr; - obj->dynamic = (const Elf_Dyn *) (obj->relocbase + phdyn->p_vaddr); - if (hdr->e_entry != 0) - obj->entry = (caddr_t) (obj->relocbase + hdr->e_entry); - - /* cbass: copy program header */ - obj->phdr = malloc(phsize); - if (obj->phdr == NULL) { - obj_free(obj); - _rtld_error("%s: cannot allocate program header", path); - return NULL; - } - memcpy((char *)obj->phdr, (char *)hdr + hdr->e_phoff, phsize); - obj->phdr_alloc = true; - obj->phsize = phsize; - - if (phinterp != NULL) - obj->interp = (const char *) (obj->relocbase + phinterp->p_vaddr); - if (phtls != NULL) { - tls_dtv_generation++; - obj->tlsindex = ++tls_max_index; - obj->tlssize = phtls->p_memsz; - obj->tlsalign = phtls->p_align; - obj->tlsinitsize = phtls->p_filesz; - obj->tlsinit = mapbase + phtls->p_vaddr; - } - return obj; -} - -static Elf_Ehdr * -get_elf_header (int fd, const char *path) -{ - static union { - Elf_Ehdr hdr; - char buf[PAGE_SIZE]; - } u; - ssize_t nbytes; - - if ((nbytes = read(fd, u.buf, PAGE_SIZE)) == -1) { - _rtld_error("%s: read error: %s", path, strerror(errno)); - return NULL; - } - - /* Make sure the file is valid */ - if (nbytes < (ssize_t)sizeof(Elf_Ehdr) || !IS_ELF(u.hdr)) { - _rtld_error("%s: invalid file format", path); - return NULL; - } - if (u.hdr.e_ident[EI_CLASS] != ELF_TARG_CLASS - || u.hdr.e_ident[EI_DATA] != ELF_TARG_DATA) { - _rtld_error("%s: unsupported file layout", path); - return NULL; - } - if (u.hdr.e_ident[EI_VERSION] != EV_CURRENT - || u.hdr.e_version != EV_CURRENT) { - _rtld_error("%s: unsupported file version", path); - return NULL; - } - if (u.hdr.e_type != ET_EXEC && u.hdr.e_type != ET_DYN) { - _rtld_error("%s: unsupported file type", path); - return NULL; - } - if (u.hdr.e_machine != ELF_TARG_MACH) { - _rtld_error("%s: unsupported machine", path); - return NULL; - } - - /* - * We rely on the program header being in the first page. This is - * not strictly required by the ABI specification, but it seems to - * always true in practice. And, it simplifies things considerably. - */ - if (u.hdr.e_phentsize != sizeof(Elf_Phdr)) { - _rtld_error( - "%s: invalid shared object: e_phentsize != sizeof(Elf_Phdr)", path); - return NULL; - } - if (u.hdr.e_phoff + u.hdr.e_phnum * sizeof(Elf_Phdr) > (size_t)nbytes) { - _rtld_error("%s: program header too large", path); - return NULL; - } - - return (&u.hdr); -} - -void -obj_free(Obj_Entry *obj) -{ - Objlist_Entry *elm; - - if (obj->tls_done) - free_tls_offset(obj); - while (obj->needed != NULL) { - Needed_Entry *needed = obj->needed; - obj->needed = needed->next; - free(needed); - } - while (!STAILQ_EMPTY(&obj->names)) { - Name_Entry *entry = STAILQ_FIRST(&obj->names); - STAILQ_REMOVE_HEAD(&obj->names, link); - free(entry); - } - while (!STAILQ_EMPTY(&obj->dldags)) { - elm = STAILQ_FIRST(&obj->dldags); - STAILQ_REMOVE_HEAD(&obj->dldags, link); - free(elm); - } - while (!STAILQ_EMPTY(&obj->dagmembers)) { - elm = STAILQ_FIRST(&obj->dagmembers); - STAILQ_REMOVE_HEAD(&obj->dagmembers, link); - free(elm); - } - if (obj->vertab) - free(obj->vertab); - if (obj->origin_path) - free(obj->origin_path); - if (obj->priv) - free(obj->priv); - if (obj->path) - free(obj->path); - if (obj->phdr_alloc) - free((void *)obj->phdr); - free(obj); -} - -Obj_Entry * -obj_new(void) -{ - Obj_Entry *obj; - - obj = CNEW(Obj_Entry); - STAILQ_INIT(&obj->dldags); - STAILQ_INIT(&obj->dagmembers); - STAILQ_INIT(&obj->names); - return obj; -} - diff --git a/repos/os/src/lib/ldso/contrib/rtld.c b/repos/os/src/lib/ldso/contrib/rtld.c deleted file mode 100644 index 54b3aea59..000000000 --- a/repos/os/src/lib/ldso/contrib/rtld.c +++ /dev/null @@ -1,3476 +0,0 @@ -/*- - * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. - * Copyright 2003 Alexander Kabaev . - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/rtld.c,v 1.124.2.4.2.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -/* - * Dynamic linker for ELF. - * - * John Polstra . - */ - -#ifndef __GNUC__ -#error "GCC is needed to compile this file" -#endif - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "debug.h" -#include "rtld.h" -#include "libmap.h" -#include "rtld_tls.h" -#include "file.h" -#include "dl_extensions.h" - -#ifndef COMPAT_32BIT -#define PATH_RTLD "/libexec/ld-elf.so.1" -#else -#define PATH_RTLD "/libexec/ld-elf32.so.1" -#endif - -static char *path_rtld = "ld.lib.so"; - -/* Types. */ -typedef void (*func_ptr_type)(); -typedef void * (*path_enum_proc) (const char *path, size_t len, void *arg); - -/* - * This structure provides a reentrant way to keep a list of objects and - * check which ones have already been processed in some way. - */ -typedef struct Struct_DoneList { - const Obj_Entry **objs; /* Array of object pointers */ - unsigned int num_alloc; /* Allocated size of the array */ - unsigned int num_used; /* Number of array slots used */ -} DoneList; - -/* - * Function declarations. - */ -static const char *basename(const char *); -static void die(void) __dead2; -static void digest_dynamic(Obj_Entry *, int); -static Obj_Entry *digest_phdr(const Elf_Phdr *, int, caddr_t, const char *); -static Obj_Entry *dlcheck(void *); -static Obj_Entry *do_load_object(int, const char *, char *, struct stat *); -static int do_search_info(const Obj_Entry *obj, int, struct dl_serinfo *); -static bool donelist_check(DoneList *, const Obj_Entry *); -static void errmsg_restore(char *); -static char *errmsg_save(void); -static void *fill_search_info(const char *, size_t, void *); -static char *find_library(const char *, const Obj_Entry *); -static const char *gethints(void); -static void init_dag(Obj_Entry *); -static void init_dag1(Obj_Entry *, Obj_Entry *, DoneList *); -void init_rtld(caddr_t); -static void initlist_add_neededs(Needed_Entry *, Objlist *); -static void initlist_add_objects(Obj_Entry *, Obj_Entry **, Objlist *); -static bool is_exported(const Elf_Sym *); -static void linkmap_add(Obj_Entry *); -static void linkmap_delete(Obj_Entry *); -static int load_needed_objects(Obj_Entry *); -static int load_preload_objects(void); -static Obj_Entry *load_object(const char *, const Obj_Entry *); -static Obj_Entry *obj_from_addr(const void *); -static void objlist_call_fini(Objlist *, int *lockstate); -static void objlist_call_init(Objlist *, int *lockstate); -static void objlist_clear(Objlist *); -static Objlist_Entry *objlist_find(Objlist *, const Obj_Entry *); -static void objlist_init(Objlist *); -static void objlist_push_head(Objlist *, Obj_Entry *); -static void objlist_push_tail(Objlist *, Obj_Entry *); -static void objlist_remove(Objlist *, Obj_Entry *); -static void objlist_remove_unref(Objlist *); -static void *path_enumerate(const char *, path_enum_proc, void *); -static int relocate_objects(Obj_Entry *, bool, Obj_Entry *); -static int rtld_dirname(const char *, char *); -static void rtld_exit(void); -static char *search_library_path(const char *, const char *); -const void **get_program_var_addr(const char *); -static const Elf_Sym *symlook_default(const char *, unsigned long, - const Obj_Entry *, const Obj_Entry **, const Ver_Entry *, int); -static const Elf_Sym *symlook_list(const char *, unsigned long, const Objlist *, - const Obj_Entry **, const Ver_Entry *, int, DoneList *); -static const Elf_Sym *symlook_needed(const char *, unsigned long, - const Needed_Entry *, const Obj_Entry **, const Ver_Entry *, - int, DoneList *); -static void trace_loaded_objects(Obj_Entry *); -static void unlink_object(Obj_Entry *); -static void unload_object(Obj_Entry *); -static void unref_dag(Obj_Entry *); -static void ref_dag(Obj_Entry *); -static int rtld_verify_versions(const Objlist *); -static int rtld_verify_object_versions(Obj_Entry *); -static void object_add_name(Obj_Entry *, const char *); -static int object_match_name(const Obj_Entry *, const char *); -static void ld_utrace_log(int, void *, void *, size_t, int, const char *); - -void r_debug_state(struct r_debug *, struct link_map *); - -/* - * Data declarations. - */ -static char *error_message; /* Message for dlerror(), or NULL */ -struct r_debug r_debug; /* for GDB; */ -static bool libmap_disable; /* Disable libmap */ -static char *libmap_override; /* Maps to use in addition to libmap.conf */ -static bool trust; /* False for setuid and setgid programs */ -static bool dangerous_ld_env; /* True if environment variables have been - used to affect the libraries loaded */ -static char *ld_bind_now; /* Environment variable for immediate binding */ -static char *ld_debug; /* Environment variable for debugging */ -static char *ld_library_path; /* Environment variable for search path */ -static char *ld_preload; /* Environment variable for libraries to - load first */ -static char *ld_tracing; /* Called from ldd to print libs */ -static char *ld_utrace; /* Use utrace() to log events. */ -Obj_Entry *obj_list; /* Head of linked list of shared objects */ -static Obj_Entry **obj_tail; /* Link field of last object in list */ -static Obj_Entry *obj_main; /* The main program shared object */ -Obj_Entry obj_rtld; /* The dynamic linker shared object */ -static unsigned int obj_count; /* Number of objects in obj_list */ -static unsigned int obj_loads; /* Number of objects in obj_list */ - -static Objlist list_global = /* Objects dlopened with RTLD_GLOBAL */ - STAILQ_HEAD_INITIALIZER(list_global); -static Objlist list_main = /* Objects loaded at program startup */ - STAILQ_HEAD_INITIALIZER(list_main); -static Objlist list_fini = /* Objects needing fini() calls */ - STAILQ_HEAD_INITIALIZER(list_fini); - -static Elf_Sym sym_zero; /* For resolving undefined weak refs. */ - -#define GDB_STATE(s,m) r_debug.r_state = s; r_debug_state(&r_debug,m); - -extern Elf_Dyn _DYNAMIC; -#pragma weak _DYNAMIC -#ifndef RTLD_IS_DYNAMIC -#define RTLD_IS_DYNAMIC() (&_DYNAMIC != NULL) -#endif - -/* - * These are the functions the dynamic linker exports to application - * programs. They are the only symbols the dynamic linker is willing - * to export from itself. - */ -static func_ptr_type exports[] = { - (func_ptr_type) &_rtld_error, - (func_ptr_type) &dlclose, - (func_ptr_type) &dlerror, - (func_ptr_type) &dlopen, - (func_ptr_type) &dlsym, - (func_ptr_type) &dlvsym, - (func_ptr_type) &dladdr, - (func_ptr_type) &dllockinit, - (func_ptr_type) &dlinfo, - (func_ptr_type) &_rtld_thread_init, -#ifdef __i386__ - (func_ptr_type) &___tls_get_addr, -#endif - (func_ptr_type) &__tls_get_addr, - (func_ptr_type) &_rtld_allocate_tls, - (func_ptr_type) &_rtld_free_tls, - (func_ptr_type) &dl_iterate_phdr, - (func_ptr_type) &_rtld_atfork_pre, - (func_ptr_type) &_rtld_atfork_post, -#ifdef ARM_EABI - (func_ptr_type) &dl_unwind_find_exidx, -#endif - NULL -}; - -/* - * Global declarations normally provided by crt1. The dynamic linker is - * not built with crt1, so we have to provide them ourselves. - */ -char *__progname; -char **environ; - -/* - * Globals to control TLS allocation. - */ -size_t tls_last_offset; /* Static TLS offset of last module */ -size_t tls_last_size; /* Static TLS size of last module */ -size_t tls_static_space; /* Static TLS space allocated */ -int tls_dtv_generation = 1; /* Used to detect when dtv size changes */ -int tls_max_index = 1; /* Largest module index allocated */ - -/* - * Fill in a DoneList with an allocation large enough to hold all of - * the currently-loaded objects. Keep this as a macro since it calls - * alloca and we want that to occur within the scope of the caller. - */ -#define donelist_init(dlp) \ - ((dlp)->objs = alloca(obj_count * sizeof (dlp)->objs[0]), \ - assert((dlp)->objs != NULL), \ - (dlp)->num_alloc = obj_count, \ - (dlp)->num_used = 0) - -#define UTRACE_DLOPEN_START 1 -#define UTRACE_DLOPEN_STOP 2 -#define UTRACE_DLCLOSE_START 3 -#define UTRACE_DLCLOSE_STOP 4 -#define UTRACE_LOAD_OBJECT 5 -#define UTRACE_UNLOAD_OBJECT 6 -#define UTRACE_ADD_RUNDEP 7 -#define UTRACE_PRELOAD_FINISHED 8 -#define UTRACE_INIT_CALL 9 -#define UTRACE_FINI_CALL 10 - -struct utrace_rtld { - char sig[4]; /* 'RTLD' */ - int event; - void *handle; - void *mapbase; /* Used for 'parent' and 'init/fini' */ - size_t mapsize; - int refcnt; /* Used for 'mode' */ - char name[MAXPATHLEN]; -}; - -#define LD_UTRACE(e, h, mb, ms, r, n) do { \ - if (ld_utrace != NULL) \ - ld_utrace_log(e, h, mb, ms, r, n); \ -} while (0) - -static void -ld_utrace_log(int event, void *handle, void *mapbase, size_t mapsize, - int refcnt, const char *name) -{ - struct utrace_rtld ut; - - ut.sig[0] = 'R'; - ut.sig[1] = 'T'; - ut.sig[2] = 'L'; - ut.sig[3] = 'D'; - ut.event = event; - ut.handle = handle; - ut.mapbase = mapbase; - ut.mapsize = mapsize; - ut.refcnt = refcnt; - bzero(ut.name, sizeof(ut.name)); - if (name) - strlcpy(ut.name, name, sizeof(ut.name)); - utrace(&ut, sizeof(ut)); -} - -/** - * cbass: Set full linker path from binary dependency (Note: We always link ldso - * to binaries in Genode - */ -static -void set_rtld_path(Obj_Entry *obj) -{ - Needed_Entry *needed; - const char *name; - - for (needed = obj->needed; needed != NULL; needed = needed->next) { - name = obj->strtab + needed->name; - if (object_match_name(&obj_rtld, name)) - obj_rtld.path = xstrdup(name); - } -} - -/* - * Main entry point for dynamic linking. The first argument is the - * stack pointer. The stack is expected to be laid out as described - * in the SVR4 ABI specification, Intel 386 Processor Supplement. - * Specifically, the stack pointer points to a word containing - * ARGC. Following that in the stack is a null-terminated sequence - * of pointers to argument strings. Then comes a null-terminated - * sequence of pointers to environment strings. Finally, there is a - * sequence of "auxiliary vector" entries. - * - * The second argument points to a place to store the dynamic linker's - * exit procedure pointer and the third to a place to store the main - * program's object. - * - * The return value is the main program's entry point. - */ -func_ptr_type -_rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp) -{ - Elf_Auxinfo *aux_info[AT_COUNT]; - int i; - int argc; - char **argv; - char **env; - Elf_Auxinfo *aux; - Elf_Auxinfo *auxp; - const char *argv0; - Objlist_Entry *entry; - Obj_Entry *obj; - Obj_Entry **preload_tail; - Objlist initlist; - int lockstate; - - /* - * On entry, the dynamic linker itself has not been relocated yet. - * Be very careful not to reference any global data until after - * init_rtld has returned. It is OK to reference file-scope statics - * and string constants, and to call static and global functions. - */ - - /* Find the auxiliary vector on the stack. */ - argc = *sp++; - argv = (char **) sp; - sp += argc + 1; /* Skip over arguments and NULL terminator */ - env = (char **) sp; - while (*sp++ != 0) /* Skip over environment, and NULL terminator */ - ; - aux = (Elf_Auxinfo *) sp; - - /* Digest the auxiliary vector. */ - for (i = 0; i < AT_COUNT; i++) - aux_info[i] = NULL; - for (auxp = aux; auxp->a_type != AT_NULL; auxp++) { - if (auxp->a_type < AT_COUNT) - aux_info[auxp->a_type] = auxp; - } - - /* Initialize and relocate ourselves. */ - assert(aux_info[AT_BASE] != NULL); - - __progname = obj_rtld.path; - argv0 = argv[0] != NULL ? argv[0] : "(null)"; - environ = env; - - trust = !issetugid(); - - ld_bind_now = getenv(LD_ "BIND_NOW"); - /* - * If the process is tainted, then we un-set the dangerous environment - * variables. The process will be marked as tainted until setuid(2) - * is called. If any child process calls setuid(2) we do not want any - * future processes to honor the potentially un-safe variables. - */ - if (!trust) { - unsetenv(LD_ "PRELOAD"); - unsetenv(LD_ "LIBMAP"); - unsetenv(LD_ "LIBRARY_PATH"); - unsetenv(LD_ "LIBMAP_DISABLE"); - unsetenv(LD_ "DEBUG"); - } - ld_debug = getenv(LD_ "DEBUG"); - libmap_disable = getenv(LD_ "LIBMAP_DISABLE") != NULL; - libmap_override = getenv(LD_ "LIBMAP"); - ld_library_path = getenv(LD_ "LIBRARY_PATH"); - ld_preload = getenv(LD_ "PRELOAD"); - dangerous_ld_env = libmap_disable || (libmap_override != NULL) || - (ld_library_path != NULL) || (ld_preload != NULL); - ld_tracing = getenv(LD_ "TRACE_LOADED_OBJECTS"); - ld_utrace = getenv(LD_ "UTRACE"); - - if (ld_debug != NULL && *ld_debug != '\0') - debug = 1; - dbg("%s is initialized, base address = %p", __progname, - (caddr_t) aux_info[AT_BASE]->a_un.a_ptr); - dbg("RTLD dynamic = %p", obj_rtld.dynamic); - dbg("RTLD pltgot = %p", obj_rtld.pltgot); - - /* - * Load the main program, or process its program header if it is - * already loaded. - */ - if (aux_info[AT_EXECFD] != NULL) { /* Load the main program. */ - int fd = aux_info[AT_EXECFD]->a_un.a_val; - dbg("loading main program"); - obj_main = map_object(fd, argv0, NULL); - close(fd); - if (obj_main == NULL) - die(); - } else { /* Main program already loaded. */ - const Elf_Phdr *phdr; - int phnum; - caddr_t entry; - - dbg("processing main program's program header"); - assert(aux_info[AT_PHDR] != NULL); - phdr = (const Elf_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr; - assert(aux_info[AT_PHNUM] != NULL); - phnum = aux_info[AT_PHNUM]->a_un.a_val; - assert(aux_info[AT_PHENT] != NULL); - assert(aux_info[AT_PHENT]->a_un.a_val == sizeof(Elf_Phdr)); - assert(aux_info[AT_ENTRY] != NULL); - entry = (caddr_t) aux_info[AT_ENTRY]->a_un.a_ptr; - if ((obj_main = digest_phdr(phdr, phnum, entry, argv0)) == NULL) - die(); - } - - obj_main->path = xstrdup(argv0); - obj_main->mainprog = true; - - /* - * Get the actual dynamic linker pathname from the executable if - * possible. (It should always be possible.) That ensures that - * gdb will find the right dynamic linker even if a non-standard - * one is being used. - */ - if (obj_main->interp != NULL && - strcmp(obj_main->interp, obj_rtld.path) != 0) { - free(obj_rtld.path); - obj_rtld.path = xstrdup(obj_main->interp); - __progname = obj_rtld.path; - } - - digest_dynamic(obj_main, 0); - - linkmap_add(obj_main); - - /* Link the main program into the list of objects. */ - *obj_tail = obj_main; - obj_tail = &obj_main->next; - obj_count++; - obj_loads++; - *obj_tail = &obj_rtld; - obj_tail = &obj_rtld.next; - obj_count++; - obj_loads++; - STAILQ_INIT(&obj_rtld.names); - object_add_name(&obj_rtld, obj_rtld.path); - /* Make sure we don't call the main program's init and fini functions. */ - obj_main->init = obj_main->fini = (Elf_Addr)NULL; - - /* Initialize a fake symbol for resolving undefined weak references. */ - sym_zero.st_info = ELF_ST_INFO(STB_GLOBAL, STT_NOTYPE); - sym_zero.st_shndx = SHN_UNDEF; - - if (!libmap_disable) - libmap_disable = (bool)lm_init(libmap_override); - - dbg("loading LD_PRELOAD libraries"); - if (load_preload_objects() == -1) - die(); - preload_tail = obj_tail; - - dbg("loading needed objects"); - if (load_needed_objects(obj_main) == -1) - die(); - - /* Make a list of all objects loaded at startup. */ - for (obj = obj_list; obj != NULL; obj = obj->next) { - objlist_push_tail(&list_main, obj); - obj->refcount++; - } - - dbg("checking for required versions"); - if (rtld_verify_versions(&list_main) == -1 && !ld_tracing) - die(); - - if (ld_tracing) { /* We're done */ - trace_loaded_objects(obj_main); - exit(0); - } - - if (getenv(LD_ "DUMP_REL_PRE") != NULL) { - dump_relocations(obj_main); - exit (0); - } - - /* setup TLS for main thread */ - dbg("initializing initial thread local storage"); - STAILQ_FOREACH(entry, &list_main, link) { - /* - * Allocate all the initial objects out of the static TLS - * block even if they didn't ask for it. - */ - allocate_tls_offset(entry->obj); - } - allocate_initial_tls(obj_list); - - if (relocate_objects(obj_main, - ld_bind_now != NULL && *ld_bind_now != '\0', &obj_rtld) == -1) - die(); - - dbg("doing copy relocations"); - if (do_copy_relocations(obj_main) == -1) - die(); - - if (getenv(LD_ "DUMP_REL_POST") != NULL) { - dump_relocations(obj_main); - exit (0); - } - - /* - * cbass: After having loaded the main program, we relocate LDSO's global - * symbols again such that for example type informations, which are also - * present within the main program, become relocated to the correct - * positions - */ - reloc_non_plt(&obj_rtld, &obj_rtld); - - /* cbass: find out full rtld path */ - set_rtld_path(obj_main); - linkmap_add(&obj_rtld); - - dbg("initializing key program variables"); - set_program_var("__progname", argv[0] != NULL ? basename(argv[0]) : ""); - set_program_var("environ", env); - - dbg("initializing thread locks"); - lockdflt_init(); - - /* Make a list of init functions to call. */ - objlist_init(&initlist); - initlist_add_objects(obj_list, preload_tail, &initlist); - - r_debug_state(NULL, &obj_rtld.linkmap); /* say hello to gdb! */ - - lockstate = wlock_acquire(rtld_bind_lock); - objlist_call_init(&initlist, &lockstate); - objlist_clear(&initlist); - wlock_release(rtld_bind_lock, lockstate); - - dbg("transferring control to program entry point = %p", obj_main->entry); - - /* Return the exit procedure and the program entry point. */ - *exit_proc = rtld_exit; - *objp = obj_main; - return (func_ptr_type) obj_main->entry; -} - -Elf_Addr -_rtld_bind(Obj_Entry *obj, Elf_Size reloff) -{ - const Elf_Rel *rel; - const Elf_Sym *def; - const Obj_Entry *defobj; - Elf_Addr *where; - Elf_Addr target; - int lockstate; - - lockstate = rlock_acquire(rtld_bind_lock); - if (obj->pltrel) - rel = (const Elf_Rel *) ((caddr_t) obj->pltrel + reloff); - else - rel = (const Elf_Rel *) ((caddr_t) obj->pltrela + reloff); - - where = (Elf_Addr *) (obj->relocbase + rel->r_offset); - def = find_symdef(ELF_R_SYM(rel->r_info), obj, &defobj, true, NULL); - if (def == NULL) - die(); - - target = (Elf_Addr)(defobj->relocbase + def->st_value); - - dbg("\"%s\" in \"%s\" ==> %p in \"%s\"", - defobj->strtab + def->st_name, basename(obj->path), - (void *)target, basename(defobj->path)); - - /* - * Write the new contents for the jmpslot. Note that depending on - * architecture, the value which we need to return back to the - * lazy binding trampoline may or may not be the target - * address. The value returned from reloc_jmpslot() is the value - * that the trampoline needs. - */ - target = reloc_jmpslot(where, target, defobj, obj, rel); - rlock_release(rtld_bind_lock, lockstate); - return target; -} - -/* - * Error reporting function. Use it like printf. If formats the message - * into a buffer, and sets things up so that the next call to dlerror() - * will return the message. - */ -void -_rtld_error(const char *fmt, ...) -{ - static char buf[512]; - va_list ap; - - va_start(ap, fmt); - vsnprintf(buf, sizeof buf, fmt, ap); - error_message = buf; - va_end(ap); -} - -/* - * Return a dynamically-allocated copy of the current error message, if any. - */ -static char * -errmsg_save(void) -{ - return error_message == NULL ? NULL : xstrdup(error_message); -} - -/* - * Restore the current error message from a copy which was previously saved - * by errmsg_save(). The copy is freed. - */ -static void -errmsg_restore(char *saved_msg) -{ - if (saved_msg == NULL) - error_message = NULL; - else { - _rtld_error("%s", saved_msg); - free(saved_msg); - } -} - -static const char * -basename(const char *name) -{ - const char *p = strrchr(name, '/'); - return p != NULL ? p + 1 : name; -} - -static void -die(void) -{ - const char *msg = dlerror(); - - if (msg == NULL) - msg = "Fatal error"; - errx(1, "%s", msg); -} - -/* - * Process a shared object's DYNAMIC section, and save the important - * information in its Obj_Entry structure. - */ -static void -digest_dynamic(Obj_Entry *obj, int early) -{ - const Elf_Dyn *dynp; - Needed_Entry **needed_tail = &obj->needed; - const Elf_Dyn *dyn_rpath = NULL; - const Elf_Dyn *dyn_soname = NULL; - int plttype = DT_REL; - - obj->bind_now = false; - for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; dynp++) { - switch (dynp->d_tag) { - - case DT_REL: - obj->rel = (const Elf_Rel *) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_RELSZ: - obj->relsize = dynp->d_un.d_val; - break; - - case DT_RELENT: - assert(dynp->d_un.d_val == sizeof(Elf_Rel)); - break; - - case DT_JMPREL: - obj->pltrel = (const Elf_Rel *) - (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_PLTRELSZ: - obj->pltrelsize = dynp->d_un.d_val; - break; - - case DT_RELA: - obj->rela = (const Elf_Rela *) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_RELASZ: - obj->relasize = dynp->d_un.d_val; - break; - - case DT_RELAENT: - assert(dynp->d_un.d_val == sizeof(Elf_Rela)); - break; - - case DT_PLTREL: - plttype = dynp->d_un.d_val; - assert(dynp->d_un.d_val == DT_REL || plttype == DT_RELA); - break; - - case DT_SYMTAB: - obj->symtab = (const Elf_Sym *) - (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_SYMENT: - assert(dynp->d_un.d_val == sizeof(Elf_Sym)); - break; - - case DT_STRTAB: - obj->strtab = (const char *) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_STRSZ: - obj->strsize = dynp->d_un.d_val; - break; - - case DT_VERNEED: - obj->verneed = (const Elf_Verneed *) (obj->relocbase + - dynp->d_un.d_val); - break; - - case DT_VERNEEDNUM: - obj->verneednum = dynp->d_un.d_val; - break; - - case DT_VERDEF: - obj->verdef = (const Elf_Verdef *) (obj->relocbase + - dynp->d_un.d_val); - break; - - case DT_VERDEFNUM: - obj->verdefnum = dynp->d_un.d_val; - break; - - case DT_VERSYM: - obj->versyms = (const Elf_Versym *)(obj->relocbase + - dynp->d_un.d_val); - break; - - case DT_HASH: - { - const Elf_Hashelt *hashtab = (const Elf_Hashelt *) - (obj->relocbase + dynp->d_un.d_ptr); - obj->nbuckets = hashtab[0]; - obj->nchains = hashtab[1]; - obj->buckets = hashtab + 2; - obj->chains = obj->buckets + obj->nbuckets; - } - break; - - case DT_NEEDED: - if (!obj->rtld) { - Needed_Entry *nep = NEW(Needed_Entry); - nep->name = dynp->d_un.d_val; - nep->obj = NULL; - nep->next = NULL; - - *needed_tail = nep; - needed_tail = &nep->next; - } - break; - - case DT_PLTGOT: - obj->pltgot = (Elf_Addr *) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_TEXTREL: - /* Note: ld.lib.so has exactly one text-relocation in order to be - * able to initialize it's GOT without a stack pointer */ - if (!obj->rtld) - obj->textrel = true; - break; - - case DT_SYMBOLIC: - obj->symbolic = true; - break; - - case DT_RPATH: - case DT_RUNPATH: /* XXX: process separately */ - /* - * We have to wait until later to process this, because we - * might not have gotten the address of the string table yet. - */ - dyn_rpath = dynp; - break; - - case DT_SONAME: - dyn_soname = dynp; - break; - - case DT_INIT: - obj->init = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_FINI: - obj->fini = (Elf_Addr) (obj->relocbase + dynp->d_un.d_ptr); - break; - - case DT_DEBUG: - /* XXX - not implemented yet */ - if (!early) - dbg("Filling in DT_DEBUG entry"); - ((Elf_Dyn*)dynp)->d_un.d_ptr = (Elf_Addr) &r_debug; - break; - - case DT_FLAGS: - if (dynp->d_un.d_val & DF_ORIGIN) { - obj->origin_path = xmalloc(PATH_MAX); - if (rtld_dirname(obj->path, obj->origin_path) == -1) - die(); - } - if (dynp->d_un.d_val & DF_SYMBOLIC) - obj->symbolic = true; - if (dynp->d_un.d_val & DF_TEXTREL) - obj->textrel = true; - if (dynp->d_un.d_val & DF_BIND_NOW) - obj->bind_now = true; - if (dynp->d_un.d_val & DF_STATIC_TLS) - ; - break; - - default: - if (!early) { - dbg("Ignoring d_tag %ld = %#lx", (long)dynp->d_tag, - (long)dynp->d_tag); - } - break; - } - } - - obj->traced = false; - - if (plttype == DT_RELA) { - obj->pltrela = (const Elf_Rela *) obj->pltrel; - obj->pltrel = NULL; - obj->pltrelasize = obj->pltrelsize; - obj->pltrelsize = 0; - } - - if (dyn_rpath != NULL) - obj->rpath = obj->strtab + dyn_rpath->d_un.d_val; - - if (dyn_soname != NULL) - object_add_name(obj, obj->strtab + dyn_soname->d_un.d_val); -} - -/* - * Process a shared object's program header. This is used only for the - * main program, when the kernel has already loaded the main program - * into memory before calling the dynamic linker. It creates and - * returns an Obj_Entry structure. - */ -static Obj_Entry * -digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry, const char *path) -{ - Obj_Entry *obj; - const Elf_Phdr *phlimit = phdr + phnum; - const Elf_Phdr *ph; - int nsegs = 0; - - obj = obj_new(); - for (ph = phdr; ph < phlimit; ph++) { - switch (ph->p_type) { - - case PT_PHDR: - if ((const Elf_Phdr *)ph->p_vaddr != phdr) { - _rtld_error("%s: invalid PT_PHDR", path); - return NULL; - } - obj->phdr = (const Elf_Phdr *) ph->p_vaddr; - obj->phsize = ph->p_memsz; - break; - - case PT_INTERP: - obj->interp = (const char *) ph->p_vaddr; - break; - - case PT_LOAD: - if (nsegs == 0) { /* First load segment */ - obj->vaddrbase = trunc_page(ph->p_vaddr); - obj->mapbase = (caddr_t) obj->vaddrbase; - obj->relocbase = obj->mapbase - obj->vaddrbase; - obj->textsize = round_page(ph->p_vaddr + ph->p_memsz) - - obj->vaddrbase; - } else { /* Last load segment */ - obj->mapsize = round_page(ph->p_vaddr + ph->p_memsz) - - obj->vaddrbase; - } - nsegs++; - break; - - case PT_DYNAMIC: - obj->dynamic = (const Elf_Dyn *) ph->p_vaddr; - break; - - case PT_TLS: - obj->tlsindex = 1; - obj->tlssize = ph->p_memsz; - obj->tlsalign = ph->p_align; - obj->tlsinitsize = ph->p_filesz; - obj->tlsinit = (void*) ph->p_vaddr; - break; - } - } - if (nsegs < 1) { - _rtld_error("%s: too few PT_LOAD segments", path); - return NULL; - } - - obj->entry = entry; - return obj; -} - -static Obj_Entry * -dlcheck(void *handle) -{ - Obj_Entry *obj; - - for (obj = obj_list; obj != NULL; obj = obj->next) - if (obj == (Obj_Entry *) handle) - break; - - if (obj == NULL || obj->refcount == 0 || obj->dl_refcount == 0) { - _rtld_error("Invalid shared object handle %p", handle); - return NULL; - } - return obj; -} - -/* - * If the given object is already in the donelist, return true. Otherwise - * add the object to the list and return false. - */ -static bool -donelist_check(DoneList *dlp, const Obj_Entry *obj) -{ - unsigned int i; - - for (i = 0; i < dlp->num_used; i++) - if (dlp->objs[i] == obj) - return true; - /* - * Our donelist allocation should always be sufficient. But if - * our threads locking isn't working properly, more shared objects - * could have been loaded since we allocated the list. That should - * never happen, but we'll handle it properly just in case it does. - */ - if (dlp->num_used < dlp->num_alloc) - dlp->objs[dlp->num_used++] = obj; - return false; -} - -/* - * Hash function for symbol table lookup. Don't even think about changing - * this. It is specified by the System V ABI. - */ -unsigned long -elf_hash(const char *name) -{ - const unsigned char *p = (const unsigned char *) name; - unsigned long h = 0; - unsigned long g; - - while (*p != '\0') { - h = (h << 4) + *p++; - if ((g = h & 0xf0000000) != 0) - h ^= g >> 24; - h &= ~g; - } - return h; -} - -/* - * Find the library with the given name, and return its full pathname. - * The returned string is dynamically allocated. Generates an error - * message and returns NULL if the library cannot be found. - * - * If the second argument is non-NULL, then it refers to an already- - * loaded shared object, whose library search path will be searched. - * - * The search order is: - * LD_LIBRARY_PATH - * rpath in the referencing file - * ldconfig hints - * /lib:/usr/lib - */ -static char * -find_library(const char *xname, const Obj_Entry *refobj) -{ - char *pathname; - char *name; - - if (strchr(xname, '/') != NULL) { /* Hard coded pathname */ - if (xname[0] != '/' && !trust) { - _rtld_error("Absolute pathname required for shared object \"%s\"", - xname); - return NULL; - } - return xstrdup(xname); - } - - if (libmap_disable || (refobj == NULL) || - (name = lm_find(refobj->path, xname)) == NULL) - name = (char *)xname; - - dbg(" Searching for \"%s\"", name); - - if ((pathname = search_library_path(name, ld_library_path)) != NULL || - (refobj != NULL && - (pathname = search_library_path(name, refobj->rpath)) != NULL) || - (pathname = search_library_path(name, gethints())) != NULL || - (pathname = search_library_path(name, STANDARD_LIBRARY_PATH)) != NULL) - return pathname; - - if(refobj != NULL && refobj->path != NULL) { - _rtld_error("Shared object \"%s\" not found, required by \"%s\"", - name, basename(refobj->path)); - } else { - _rtld_error("Shared object \"%s\" not found", name); - } - return NULL; -} - -/* - * Given a symbol number in a referencing object, find the corresponding - * definition of the symbol. Returns a pointer to the symbol, or NULL if - * no definition was found. Returns a pointer to the Obj_Entry of the - * defining object via the reference parameter DEFOBJ_OUT. - */ -const Elf_Sym * -find_symdef(unsigned long symnum, const Obj_Entry *refobj, - const Obj_Entry **defobj_out, int flags, SymCache *cache) -{ - const Elf_Sym *ref; - const Elf_Sym *def; - const Obj_Entry *defobj; - const Ver_Entry *ventry; - const char *name; - unsigned long hash; - - /* - * If we have already found this symbol, get the information from - * the cache. - */ - if (symnum >= refobj->nchains) - return NULL; /* Bad object */ - if (cache != NULL && cache[symnum].sym != NULL) { - *defobj_out = cache[symnum].obj; - return cache[symnum].sym; - } - - ref = refobj->symtab + symnum; - name = refobj->strtab + ref->st_name; - defobj = NULL; - - /* - * We don't have to do a full scale lookup if the symbol is local. - * We know it will bind to the instance in this load module; to - * which we already have a pointer (ie ref). By not doing a lookup, - * we not only improve performance, but it also avoids unresolvable - * symbols when local symbols are not in the hash table. This has - * been seen with the ia64 toolchain. - */ - if (ELF_ST_BIND(ref->st_info) != STB_LOCAL) { - if (ELF_ST_TYPE(ref->st_info) == STT_SECTION) { - _rtld_error("%s: Bogus symbol table entry %lu", refobj->path, - symnum); - } - ventry = fetch_ventry(refobj, symnum); - hash = elf_hash(name); - def = symlook_default(name, hash, refobj, &defobj, ventry, flags); - } else { - def = ref; - defobj = refobj; - } - - /* - * If we found no definition and the reference is weak, treat the - * symbol as having the value zero. - */ - if (def == NULL && ELF_ST_BIND(ref->st_info) == STB_WEAK) { - def = &sym_zero; - defobj = obj_main; - } - - if (def != NULL) { - *defobj_out = defobj; - /* Record the information in the cache to avoid subsequent lookups. */ - /* cbass: Don't cache LDSO data during initialization */ - if (cache != NULL && !(refobj->rtld_init)) { - cache[symnum].sym = def; - cache[symnum].obj = defobj; - } - } else { - if (refobj != &obj_rtld && !(refobj->rtld_init)) - _rtld_error("%s: Undefined symbol \"%s\"", refobj->path, name); - } - return def; -} - -/* - * Return the search path from the ldconfig hints file, reading it if - * necessary. Returns NULL if there are problems with the hints file, - * or if the search path there is empty. - */ -static const char * -gethints(void) -{ - static char *hints; - - if (hints == NULL) { - int fd; - struct elfhints_hdr hdr; - char *p; - - /* Keep from trying again in case the hints file is bad. */ - hints = ""; - - if ((fd = open(_PATH_ELF_HINTS, O_RDONLY)) == -1) - return NULL; - if (read(fd, &hdr, sizeof hdr) != sizeof hdr || - hdr.magic != ELFHINTS_MAGIC || - hdr.version != 1) { - close(fd); - return NULL; - } - p = xmalloc(hdr.dirlistlen + 1); - if (lseek(fd, hdr.strtab + hdr.dirlist, SEEK_SET) == -1 || - read(fd, p, hdr.dirlistlen + 1) != (ssize_t)hdr.dirlistlen + 1) { - free(p); - close(fd); - return NULL; - } - hints = p; - close(fd); - } - return hints[0] != '\0' ? hints : NULL; -} - -static void -init_dag(Obj_Entry *root) -{ - DoneList donelist; - - donelist_init(&donelist); - init_dag1(root, root, &donelist); -} - -static void -init_dag1(Obj_Entry *root, Obj_Entry *obj, DoneList *dlp) -{ - const Needed_Entry *needed; - - if (donelist_check(dlp, obj)) - return; - - obj->refcount++; - objlist_push_tail(&obj->dldags, root); - objlist_push_tail(&root->dagmembers, obj); - for (needed = obj->needed; needed != NULL; needed = needed->next) - if (needed->obj != NULL) - init_dag1(root, needed->obj, dlp); -} - -/* - * Initialize the dynamic linker. The argument is the address at which - * the dynamic linker has been mapped into memory. The primary task of - * this function is to relocate the dynamic linker. - */ -void -init_rtld(caddr_t _mapbase) -{ - /* mapbase is set at compile time */ - caddr_t mapbase = (caddr_t)LINK_ADDRESS; - - Obj_Entry objtmp; /* Temporary rtld object */ - - /* - * Conjure up an Obj_Entry structure for the dynamic linker. - * - * The "path" member can't be initialized yet because string constatns - * cannot yet be acessed. Below we will set it correctly. - */ - memset(&objtmp, 0, sizeof(objtmp)); - objtmp.path = NULL; - objtmp.rtld = true; - /* cbass: Mark ldso initialization */ - objtmp.rtld_init = true; - objtmp.mapbase = mapbase; -#ifdef PIC - objtmp.relocbase = mapbase; -#endif - if (RTLD_IS_DYNAMIC()) { - objtmp.dynamic = rtld_dynamic(&objtmp); - digest_dynamic(&objtmp, 1); - assert(objtmp.needed == NULL); - assert(!objtmp.textrel); - - /* - * Temporarily put the dynamic linker entry into the object list, so - * that symbols can be found. - */ - - relocate_objects(&objtmp, true, &objtmp); - } - - /* Initialize the object list. */ - obj_tail = &obj_list; - /* Now that non-local variables can be accesses, copy out obj_rtld. */ - memcpy(&obj_rtld, &objtmp, sizeof(obj_rtld)); - - /* Replace the path with a dynamically allocated copy. */ - obj_rtld.path = path_rtld; - obj_rtld.rtld_init = false; - - r_debug.r_brk = r_debug_state; - r_debug.r_state = RT_CONSISTENT; -} - -/* - * Add the init functions from a needed object list (and its recursive - * needed objects) to "list". This is not used directly; it is a helper - * function for initlist_add_objects(). The write lock must be held - * when this function is called. - */ -static void -initlist_add_neededs(Needed_Entry *needed, Objlist *list) -{ - /* Recursively process the successor needed objects. */ - if (needed->next != NULL) - initlist_add_neededs(needed->next, list); - - /* Process the current needed object. */ - if (needed->obj != NULL) - initlist_add_objects(needed->obj, &needed->obj->next, list); -} - -/* - * Scan all of the DAGs rooted in the range of objects from "obj" to - * "tail" and add their init functions to "list". This recurses over - * the DAGs and ensure the proper init ordering such that each object's - * needed libraries are initialized before the object itself. At the - * same time, this function adds the objects to the global finalization - * list "list_fini" in the opposite order. The write lock must be - * held when this function is called. - */ -static void -initlist_add_objects(Obj_Entry *obj, Obj_Entry **tail, Objlist *list) -{ - if (obj->init_done) - return; - obj->init_done = true; - - /* Recursively process the successor objects. */ - if (&obj->next != tail) - initlist_add_objects(obj->next, tail, list); - - /* Recursively process the needed objects. */ - if (obj->needed != NULL) - initlist_add_neededs(obj->needed, list); - - /* Add the object to the init list. */ - if (obj->init != (Elf_Addr)NULL) - objlist_push_tail(list, obj); - - /* Add the object to the global fini list in the reverse order. */ - if (obj->fini != (Elf_Addr)NULL) - objlist_push_head(&list_fini, obj); -} - -#ifndef FPTR_TARGET -#define FPTR_TARGET(f) ((Elf_Addr) (f)) -#endif - -static bool -is_exported(const Elf_Sym *def) -{ - Elf_Addr value; - const func_ptr_type *p; - - value = (Elf_Addr)(obj_rtld.relocbase + def->st_value); - for (p = exports; *p != NULL; p++) - if (FPTR_TARGET(*p) == value) - return true; - return false; -} - -/* - * Given a shared object, traverse its list of needed objects, and load - * each of them. Returns 0 on success. Generates an error message and - * returns -1 on failure. - */ -static int -load_needed_objects(Obj_Entry *first) -{ - Obj_Entry *obj; - - for (obj = first; obj != NULL; obj = obj->next) { - Needed_Entry *needed; - - for (needed = obj->needed; needed != NULL; needed = needed->next) { - needed->obj = load_object(obj->strtab + needed->name, obj); - if (needed->obj == NULL && !ld_tracing) - return -1; - } - } - - return 0; -} - -static int -load_preload_objects(void) -{ - char *p = ld_preload; - static const char delim[] = " \t:;"; - - if (p == NULL) - return 0; - - p += strspn(p, delim); - while (*p != '\0') { - size_t len = strcspn(p, delim); - char savech; - - savech = p[len]; - p[len] = '\0'; - if (load_object(p, NULL) == NULL) - return -1; /* XXX - cleanup */ - p[len] = savech; - p += len; - p += strspn(p, delim); - } - LD_UTRACE(UTRACE_PRELOAD_FINISHED, NULL, NULL, 0, 0, NULL); - return 0; -} - -/* - * Load a shared object into memory, if it is not already loaded. - * - * Returns a pointer to the Obj_Entry for the object. Returns NULL - * on failure. - */ -static Obj_Entry * -load_object(const char *name, const Obj_Entry *refobj) -{ - Obj_Entry *obj; - int fd = -1; - struct stat sb; - char *path; - - for (obj = obj_list->next; obj != NULL; obj = obj->next) - if (object_match_name(obj, name)) - return obj; - - path = find_library(name, refobj); - if (path == NULL) - return NULL; - - /* - * If we didn't find a match by pathname, open the file and check - * again by device and inode. This avoids false mismatches caused - * by multiple links or ".." in pathnames. - * - * To avoid a race, we open the file and use fstat() rather than - * using stat(). - */ - if ((fd = open(path, O_RDONLY)) == -1) { - _rtld_error("Cannot open \"%s\"", path); - free(path); - return NULL; - } - if (fstat(fd, &sb) == -1) { - _rtld_error("Cannot fstat \"%s\"", path); - close(fd); - free(path); - return NULL; - } - for (obj = obj_list->next; obj != NULL; obj = obj->next) { - if (obj->ino == sb.st_ino && obj->dev == sb.st_dev) { - close(fd); - break; - } - } - if (obj != NULL) { - object_add_name(obj, name); - free(path); - close(fd); - return obj; - } - - /* First use of this object, so we must map it in */ - obj = do_load_object(fd, name, path, &sb); - if (obj == NULL) - free(path); - close(fd); - - return obj; -} - -static Obj_Entry * -do_load_object(int fd, const char *name, char *path, struct stat *sbp) -{ - Obj_Entry *obj; - struct statfs fs; - - /* - * but first, make sure that environment variables haven't been - * used to circumvent the noexec flag on a filesystem. - */ - if (dangerous_ld_env) { - if (fstatfs(fd, &fs) != 0) { - _rtld_error("Cannot fstatfs \"%s\"", path); - return NULL; - } - if (fs.f_flags & MNT_NOEXEC) { - _rtld_error("Cannot execute objects on %s\n", fs.f_mntonname); - return NULL; - } - } - dbg("loading \"%s\"", path); - obj = map_object(fd, path, sbp); - if (obj == NULL) - return NULL; - - object_add_name(obj, name); - obj->path = path; - digest_dynamic(obj, 0); - - *obj_tail = obj; - obj_tail = &obj->next; - obj_count++; - obj_loads++; - linkmap_add(obj); /* for GDB & dlinfo() */ - - dbg(" %p .. %p: %s", obj->mapbase, - obj->mapbase + obj->mapsize - 1, obj->path); - if (obj->textrel) - dbg(" WARNING: %s has impure text", obj->path); - LD_UTRACE(UTRACE_LOAD_OBJECT, obj, obj->mapbase, obj->mapsize, 0, - obj->path); - - return obj; -} - -static Obj_Entry * -obj_from_addr(const void *addr) -{ - Obj_Entry *obj; - - for (obj = obj_list; obj != NULL; obj = obj->next) { - if (addr < (void *) obj->mapbase) - continue; - if (addr < (void *) (obj->mapbase + obj->mapsize)) - return obj; - } - return NULL; -} - -/* - * Call the finalization functions for each of the objects in "list" - * which are unreferenced. All of the objects are expected to have - * non-NULL fini functions. - */ -static void -objlist_call_fini(Objlist *list, int *lockstate) -{ - Objlist_Entry *elm; - char *saved_msg; - - /* - * Preserve the current error message since a fini function might - * call into the dynamic linker and overwrite it. - */ - saved_msg = errmsg_save(); - wlock_release(rtld_bind_lock, *lockstate); - STAILQ_FOREACH(elm, list, link) { - if (elm->obj->refcount == 0) { - dbg("calling fini function for %s at %p", elm->obj->path, - (void *)elm->obj->fini); - LD_UTRACE(UTRACE_FINI_CALL, elm->obj, (void *)elm->obj->fini, 0, 0, - elm->obj->path); - call_initfini_pointer(elm->obj, elm->obj->fini); - } - } - *lockstate = wlock_acquire(rtld_bind_lock); - errmsg_restore(saved_msg); -} - -/* - * Call the initialization functions for each of the objects in - * "list". All of the objects are expected to have non-NULL init - * functions. - */ -static void -objlist_call_init(Objlist *list, int *lockstate) -{ - Objlist_Entry *elm; - char *saved_msg; - - /* - * Preserve the current error message since an init function might - * call into the dynamic linker and overwrite it. - */ - saved_msg = errmsg_save(); - wlock_release(rtld_bind_lock, *lockstate); - STAILQ_FOREACH(elm, list, link) { - dbg("calling init function for %s at %p", elm->obj->path, - (void *)elm->obj->init); - LD_UTRACE(UTRACE_INIT_CALL, elm->obj, (void *)elm->obj->init, 0, 0, - elm->obj->path); - call_initfini_pointer(elm->obj, elm->obj->init); - } - *lockstate = wlock_acquire(rtld_bind_lock); - errmsg_restore(saved_msg); -} - -static void -objlist_clear(Objlist *list) -{ - Objlist_Entry *elm; - - while (!STAILQ_EMPTY(list)) { - elm = STAILQ_FIRST(list); - STAILQ_REMOVE_HEAD(list, link); - free(elm); - } -} - -static Objlist_Entry * -objlist_find(Objlist *list, const Obj_Entry *obj) -{ - Objlist_Entry *elm; - - STAILQ_FOREACH(elm, list, link) - if (elm->obj == obj) - return elm; - return NULL; -} - -static void -objlist_init(Objlist *list) -{ - STAILQ_INIT(list); -} - -static void -objlist_push_head(Objlist *list, Obj_Entry *obj) -{ - Objlist_Entry *elm; - - elm = NEW(Objlist_Entry); - elm->obj = obj; - STAILQ_INSERT_HEAD(list, elm, link); -} - -static void -objlist_push_tail(Objlist *list, Obj_Entry *obj) -{ - Objlist_Entry *elm; - - elm = NEW(Objlist_Entry); - elm->obj = obj; - STAILQ_INSERT_TAIL(list, elm, link); -} - -static void -objlist_remove(Objlist *list, Obj_Entry *obj) -{ - Objlist_Entry *elm; - - if ((elm = objlist_find(list, obj)) != NULL) { - STAILQ_REMOVE(list, elm, Struct_Objlist_Entry, link); - free(elm); - } -} - -/* - * Remove all of the unreferenced objects from "list". - */ -static void -objlist_remove_unref(Objlist *list) -{ - Objlist newlist; - Objlist_Entry *elm; - - STAILQ_INIT(&newlist); - while (!STAILQ_EMPTY(list)) { - elm = STAILQ_FIRST(list); - STAILQ_REMOVE_HEAD(list, link); - if (elm->obj->refcount == 0) - free(elm); - else - STAILQ_INSERT_TAIL(&newlist, elm, link); - } - *list = newlist; -} - -/* - * Relocate newly-loaded shared objects. The argument is a pointer to - * the Obj_Entry for the first such object. All objects from the first - * to the end of the list of objects are relocated. Returns 0 on success, - * or -1 on failure. - */ -static int -relocate_objects(Obj_Entry *first, bool bind_now, Obj_Entry *rtldobj) -{ - Obj_Entry *obj; - - for (obj = first; obj != NULL; obj = obj->next) { - if (obj != rtldobj) - dbg("relocating \"%s\"", obj->path); - - /* rtld has already been relocated */ - if (first != rtldobj && obj == rtldobj) - continue; - - if (obj->nbuckets == 0 || obj->nchains == 0 || obj->buckets == NULL || - obj->symtab == NULL || obj->strtab == NULL) { - _rtld_error("%s: Shared object has no run-time symbol table", - obj->path); - return -1; - } - - if (obj->textrel) { - /* There are relocations to the write-protected text segment. */ - if (mprotect(obj->mapbase, obj->textsize, - PROT_READ|PROT_WRITE|PROT_EXEC) == -1) { - _rtld_error("%s: Cannot write-enable text segment: %s", - obj->path, strerror(errno)); - return -1; - } - } - - /* Process the non-PLT relocations. */ - if (reloc_non_plt(obj, rtldobj)) - return -1; - - if (obj->textrel) { /* Re-protected the text segment. */ - if (mprotect(obj->mapbase, obj->textsize, - PROT_READ|PROT_EXEC) == -1) { - _rtld_error("%s: Cannot write-protect text segment: %s", - obj->path, strerror(errno)); - return -1; - } - } - - /* Process the PLT relocations. */ - if (reloc_plt(obj) == -1) - return -1; - /* Relocate the jump slots if we are doing immediate binding. */ - if (obj->bind_now || bind_now) - if (reloc_jmpslots(obj) == -1) - return -1; - - - /* - * Set up the magic number and version in the Obj_Entry. These - * were checked in the crt1.o from the original ElfKit, so we - * set them for backward compatibility. - */ - obj->magic = RTLD_MAGIC; - obj->version = RTLD_VERSION; - - /* Set the special PLT or GOT entries. */ - init_pltgot(obj); - } - - return 0; -} - -/* - * Cleanup procedure. It will be called (by the atexit mechanism) just - * before the process exits. - */ -static void -rtld_exit(void) -{ - Obj_Entry *obj; - int lockstate; - - lockstate = wlock_acquire(rtld_bind_lock); - dbg("rtld_exit()"); - /* Clear all the reference counts so the fini functions will be called. */ - for (obj = obj_list; obj != NULL; obj = obj->next) - obj->refcount = 0; - objlist_call_fini(&list_fini, &lockstate); - /* No need to remove the items from the list, since we are exiting. */ - if (!libmap_disable) - lm_fini(); - wlock_release(rtld_bind_lock, lockstate); -} - -static void * -path_enumerate(const char *path, path_enum_proc callback, void *arg) -{ -#ifdef COMPAT_32BIT - const char *trans; -#endif - if (path == NULL) - return (NULL); - - path += strspn(path, ":;"); - while (*path != '\0') { - size_t len; - char *res; - - len = strcspn(path, ":;"); -#ifdef COMPAT_32BIT - trans = lm_findn(NULL, path, len); - if (trans) - res = callback(trans, strlen(trans), arg); - else -#endif - res = callback(path, len, arg); - - if (res != NULL) - return (res); - - path += len; - path += strspn(path, ":;"); - } - - return (NULL); -} - -struct try_library_args { - const char *name; - size_t namelen; - char *buffer; - size_t buflen; -}; - -static void * -try_library_path(const char *dir, size_t dirlen, void *param) -{ - struct try_library_args *arg; - - arg = param; - if (*dir == '/' || trust) { - char *pathname; - - if (dirlen + 1 + arg->namelen + 1 > arg->buflen) - return (NULL); - - pathname = arg->buffer; - strncpy(pathname, dir, dirlen); - pathname[dirlen] = '/'; - strcpy(pathname + dirlen + 1, arg->name); - - dbg(" Trying \"%s\"", pathname); - if (access(pathname, F_OK) == 0) { /* We found it */ - pathname = xmalloc(dirlen + 1 + arg->namelen + 1); - strcpy(pathname, arg->buffer); - return (pathname); - } - } - return (NULL); -} - -static char * -search_library_path(const char *name, const char *path) -{ - char *p; - struct try_library_args arg; - - if (path == NULL) - return NULL; - - arg.name = name; - arg.namelen = strlen(name); - arg.buffer = xmalloc(PATH_MAX); - arg.buflen = PATH_MAX; - - p = path_enumerate(path, try_library_path, &arg); - - free(arg.buffer); - - return (p); -} - -int -dlclose(void *handle) -{ - Obj_Entry *root; - int lockstate; - - lockstate = wlock_acquire(rtld_bind_lock); - root = dlcheck(handle); - if (root == NULL) { - wlock_release(rtld_bind_lock, lockstate); - return -1; - } - LD_UTRACE(UTRACE_DLCLOSE_START, handle, NULL, 0, root->dl_refcount, - root->path); - - /* Unreference the object and its dependencies. */ - root->dl_refcount--; - - unref_dag(root); - - if (root->refcount == 0) { - /* - * The object is no longer referenced, so we must unload it. - * First, call the fini functions. - */ - objlist_call_fini(&list_fini, &lockstate); - objlist_remove_unref(&list_fini); - - /* Finish cleaning up the newly-unreferenced objects. */ - GDB_STATE(RT_DELETE,&root->linkmap); - unload_object(root); - GDB_STATE(RT_CONSISTENT,NULL); - } - LD_UTRACE(UTRACE_DLCLOSE_STOP, handle, NULL, 0, 0, NULL); - wlock_release(rtld_bind_lock, lockstate); - return 0; -} - -const char * -dlerror(void) -{ - char *msg = error_message; - error_message = NULL; - return msg; -} - -/* - * This function is deprecated and has no effect. - */ -void -dllockinit(void *context, - void *(*lock_create)(void *context), - void (*rlock_acquire)(void *lock), - void (*wlock_acquire)(void *lock), - void (*lock_release)(void *lock), - void (*lock_destroy)(void *lock), - void (*context_destroy)(void *context)) -{ - static void *cur_context; - static void (*cur_context_destroy)(void *); - - /* Just destroy the context from the previous call, if necessary. */ - if (cur_context_destroy != NULL) - cur_context_destroy(cur_context); - cur_context = context; - cur_context_destroy = context_destroy; -} - -void * -dlopen(const char *name, int mode) -{ - Obj_Entry **old_obj_tail; - Obj_Entry *obj; - Objlist initlist; - int result, lockstate; - - LD_UTRACE(UTRACE_DLOPEN_START, NULL, NULL, 0, mode, name); - ld_tracing = (mode & RTLD_TRACE) == 0 ? NULL : "1"; - if (ld_tracing != NULL) - environ = (char **)*get_program_var_addr("environ"); - - objlist_init(&initlist); - - lockstate = wlock_acquire(rtld_bind_lock); - GDB_STATE(RT_ADD,NULL); - - old_obj_tail = obj_tail; - obj = NULL; - if (name == NULL) { - obj = obj_main; - obj->refcount++; - } else { - obj = load_object(name, obj_main); - } - - if (obj) { - obj->dl_refcount++; - if (mode & RTLD_GLOBAL && objlist_find(&list_global, obj) == NULL) - objlist_push_tail(&list_global, obj); - mode &= RTLD_MODEMASK; - if (*old_obj_tail != NULL) { /* We loaded something new. */ - assert(*old_obj_tail == obj); - result = load_needed_objects(obj); - init_dag(obj); - if (result != -1) - result = rtld_verify_versions(&obj->dagmembers); - if (result != -1 && ld_tracing) - goto trace; - if (result == -1 || - (relocate_objects(obj, mode == RTLD_NOW, &obj_rtld)) == -1) { - obj->dl_refcount--; - unref_dag(obj); - if (obj->refcount == 0) - unload_object(obj); - obj = NULL; - } else { - /* Make list of init functions to call. */ - initlist_add_objects(obj, &obj->next, &initlist); - } - } else { - - /* Bump the reference counts for objects on this DAG. */ - ref_dag(obj); - - if (ld_tracing) - goto trace; - } - } - - LD_UTRACE(UTRACE_DLOPEN_STOP, obj, NULL, 0, obj ? obj->dl_refcount : 0, - name); - GDB_STATE(RT_CONSISTENT,obj ? &obj->linkmap : NULL); - - /* Call the init functions. */ - objlist_call_init(&initlist, &lockstate); - objlist_clear(&initlist); - wlock_release(rtld_bind_lock, lockstate); - return obj; -trace: - trace_loaded_objects(obj); - wlock_release(rtld_bind_lock, lockstate); - exit(0); -} - -static void * -do_dlsym(void *handle, const char *name, void *retaddr, const Ver_Entry *ve, - int flags) -{ - DoneList donelist; - const Obj_Entry *obj, *defobj; - const Elf_Sym *def, *symp; - unsigned long hash; - int lockstate; - - hash = elf_hash(name); - def = NULL; - defobj = NULL; - flags |= SYMLOOK_IN_PLT; - - lockstate = rlock_acquire(rtld_bind_lock); - if (handle == NULL || handle == RTLD_NEXT || - handle == RTLD_DEFAULT || handle == RTLD_SELF) { - - if ((obj = obj_from_addr(retaddr)) == NULL) { - _rtld_error("Cannot determine caller's shared object"); - rlock_release(rtld_bind_lock, lockstate); - return NULL; - } - if (handle == NULL) { /* Just the caller's shared object. */ - def = symlook_obj(name, hash, obj, ve, flags); - defobj = obj; - } else if (handle == RTLD_NEXT || /* Objects after caller's */ - handle == RTLD_SELF) { /* ... caller included */ - if (handle == RTLD_NEXT) - obj = obj->next; - for (; obj != NULL; obj = obj->next) { - if ((symp = symlook_obj(name, hash, obj, ve, flags)) != NULL) { - if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) { - def = symp; - defobj = obj; - if (ELF_ST_BIND(def->st_info) != STB_WEAK) - break; - } - } - } - /* - * Search the dynamic linker itself, and possibly resolve the - * symbol from there. This is how the application links to - * dynamic linker services such as dlopen. Only the values listed - * in the "exports" array can be resolved from the dynamic linker. - */ - if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { - symp = symlook_obj(name, hash, &obj_rtld, ve, flags); - if (symp != NULL && is_exported(symp)) { - def = symp; - defobj = &obj_rtld; - } - } - } else { - assert(handle == RTLD_DEFAULT); - def = symlook_default(name, hash, obj, &defobj, ve, flags); - } - } else { - if ((obj = dlcheck(handle)) == NULL) { - rlock_release(rtld_bind_lock, lockstate); - return NULL; - } - - donelist_init(&donelist); - if (obj->mainprog) { - /* Search main program and all libraries loaded by it. */ - def = symlook_list(name, hash, &list_main, &defobj, ve, flags, - &donelist); - } else { - Needed_Entry fake; - - /* Search the whole DAG rooted at the given object. */ - fake.next = NULL; - fake.obj = (Obj_Entry *)obj; - fake.name = 0; - def = symlook_needed(name, hash, &fake, &defobj, ve, flags, - &donelist); - } - } - - if (def != NULL) { - rlock_release(rtld_bind_lock, lockstate); - - /* - * The value required by the caller is derived from the value - * of the symbol. For the ia64 architecture, we need to - * construct a function descriptor which the caller can use to - * call the function with the right 'gp' value. For other - * architectures and for non-functions, the value is simply - * the relocated value of the symbol. - */ - if (ELF_ST_TYPE(def->st_info) == STT_FUNC) - return make_function_pointer(def, defobj); - else - return defobj->relocbase + def->st_value; - } - - _rtld_error("Undefined symbol \"%s\"", name); - rlock_release(rtld_bind_lock, lockstate); - return NULL; -} - -void * -dlsym(void *handle, const char *name) -{ - return do_dlsym(handle, name, __builtin_return_address(0), NULL, - SYMLOOK_DLSYM); -} - -void * -dlvsym(void *handle, const char *name, const char *version) -{ - Ver_Entry ventry; - - ventry.name = version; - ventry.file = NULL; - ventry.hash = elf_hash(version); - ventry.flags= 0; - return do_dlsym(handle, name, __builtin_return_address(0), &ventry, - SYMLOOK_DLSYM); -} - -int -dladdr(const void *addr, Dl_info *info) -{ - const Obj_Entry *obj; - const Elf_Sym *def; - void *symbol_addr; - unsigned long symoffset; - int lockstate; - - lockstate = rlock_acquire(rtld_bind_lock); - obj = obj_from_addr(addr); - if (obj == NULL) { - _rtld_error("No shared object contains address"); - rlock_release(rtld_bind_lock, lockstate); - return 0; - } - info->dli_fname = obj->path; - info->dli_fbase = obj->mapbase; - info->dli_saddr = (void *)0; - info->dli_sname = NULL; - - /* - * Walk the symbol list looking for the symbol whose address is - * closest to the address sent in. - */ - for (symoffset = 0; symoffset < obj->nchains; symoffset++) { - def = obj->symtab + symoffset; - - /* - * For skip the symbol if st_shndx is either SHN_UNDEF or - * SHN_COMMON. - */ - if (def->st_shndx == SHN_UNDEF || def->st_shndx == SHN_COMMON) - continue; - - /* - * If the symbol is greater than the specified address, or if it - * is further away from addr than the current nearest symbol, - * then reject it. - */ - symbol_addr = obj->relocbase + def->st_value; - if (symbol_addr > addr || symbol_addr < info->dli_saddr) - continue; - - /* Update our idea of the nearest symbol. */ - info->dli_sname = obj->strtab + def->st_name; - info->dli_saddr = symbol_addr; - - /* Exact match? */ - if (info->dli_saddr == addr) - break; - } - rlock_release(rtld_bind_lock, lockstate); - return 1; -} - -int -dlinfo(void *handle, int request, void *p) -{ - const Obj_Entry *obj; - int error, lockstate; - - lockstate = rlock_acquire(rtld_bind_lock); - - if (handle == NULL || handle == RTLD_SELF) { - void *retaddr; - - retaddr = __builtin_return_address(0); /* __GNUC__ only */ - if ((obj = obj_from_addr(retaddr)) == NULL) - _rtld_error("Cannot determine caller's shared object"); - } else - obj = dlcheck(handle); - - if (obj == NULL) { - rlock_release(rtld_bind_lock, lockstate); - return (-1); - } - - error = 0; - switch (request) { - case RTLD_DI_LINKMAP: - *((struct link_map const **)p) = &obj->linkmap; - break; - case RTLD_DI_ORIGIN: - error = rtld_dirname(obj->path, p); - break; - - case RTLD_DI_SERINFOSIZE: - case RTLD_DI_SERINFO: - error = do_search_info(obj, request, (struct dl_serinfo *)p); - break; - - default: - _rtld_error("Invalid request %d passed to dlinfo()", request); - error = -1; - } - - rlock_release(rtld_bind_lock, lockstate); - - return (error); -} - -int -dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param) -{ - struct dl_phdr_info phdr_info; - const Obj_Entry *obj; - int error, bind_lockstate, phdr_lockstate; - - phdr_lockstate = wlock_acquire(rtld_phdr_lock); - bind_lockstate = rlock_acquire(rtld_bind_lock); - - error = 0; - - for (obj = obj_list; obj != NULL; obj = obj->next) { - phdr_info.dlpi_addr = (Elf_Addr)obj->relocbase; - phdr_info.dlpi_name = STAILQ_FIRST(&obj->names) ? - STAILQ_FIRST(&obj->names)->name : obj->path; - phdr_info.dlpi_phdr = obj->phdr; - phdr_info.dlpi_phnum = obj->phsize / sizeof(obj->phdr[0]); - phdr_info.dlpi_tls_modid = obj->tlsindex; - phdr_info.dlpi_tls_data = obj->tlsinit; - phdr_info.dlpi_adds = obj_loads; - phdr_info.dlpi_subs = obj_loads - obj_count; - - if ((error = callback(&phdr_info, sizeof phdr_info, param)) != 0) - break; - - } - rlock_release(rtld_bind_lock, bind_lockstate); - wlock_release(rtld_phdr_lock, phdr_lockstate); - - return (error); -} - -struct fill_search_info_args { - int request; - unsigned int flags; - Dl_serinfo *serinfo; - Dl_serpath *serpath; - char *strspace; -}; - -static void * -fill_search_info(const char *dir, size_t dirlen, void *param) -{ - struct fill_search_info_args *arg; - - arg = param; - - if (arg->request == RTLD_DI_SERINFOSIZE) { - arg->serinfo->dls_cnt ++; - arg->serinfo->dls_size += sizeof(Dl_serpath) + dirlen + 1; - } else { - struct dl_serpath *s_entry; - - s_entry = arg->serpath; - s_entry->dls_name = arg->strspace; - s_entry->dls_flags = arg->flags; - - strncpy(arg->strspace, dir, dirlen); - arg->strspace[dirlen] = '\0'; - - arg->strspace += dirlen + 1; - arg->serpath++; - } - - return (NULL); -} - -static int -do_search_info(const Obj_Entry *obj, int request, struct dl_serinfo *info) -{ - struct dl_serinfo _info; - struct fill_search_info_args args; - - args.request = RTLD_DI_SERINFOSIZE; - args.serinfo = &_info; - - _info.dls_size = __offsetof(struct dl_serinfo, dls_serpath); - _info.dls_cnt = 0; - - path_enumerate(ld_library_path, fill_search_info, &args); - path_enumerate(obj->rpath, fill_search_info, &args); - path_enumerate(gethints(), fill_search_info, &args); - path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args); - - - if (request == RTLD_DI_SERINFOSIZE) { - info->dls_size = _info.dls_size; - info->dls_cnt = _info.dls_cnt; - return (0); - } - - if (info->dls_cnt != _info.dls_cnt || info->dls_size != _info.dls_size) { - _rtld_error("Uninitialized Dl_serinfo struct passed to dlinfo()"); - return (-1); - } - - args.request = RTLD_DI_SERINFO; - args.serinfo = info; - args.serpath = &info->dls_serpath[0]; - args.strspace = (char *)&info->dls_serpath[_info.dls_cnt]; - - args.flags = LA_SER_LIBPATH; - if (path_enumerate(ld_library_path, fill_search_info, &args) != NULL) - return (-1); - - args.flags = LA_SER_RUNPATH; - if (path_enumerate(obj->rpath, fill_search_info, &args) != NULL) - return (-1); - - args.flags = LA_SER_CONFIG; - if (path_enumerate(gethints(), fill_search_info, &args) != NULL) - return (-1); - - args.flags = LA_SER_DEFAULT; - if (path_enumerate(STANDARD_LIBRARY_PATH, fill_search_info, &args) != NULL) - return (-1); - return (0); -} - -static int -rtld_dirname(const char *path, char *bname) -{ - const char *endp; - - /* Empty or NULL string gets treated as "." */ - if (path == NULL || *path == '\0') { - bname[0] = '.'; - bname[1] = '\0'; - return (0); - } - - /* Strip trailing slashes */ - endp = path + strlen(path) - 1; - while (endp > path && *endp == '/') - endp--; - - /* Find the start of the dir */ - while (endp > path && *endp != '/') - endp--; - - /* Either the dir is "/" or there are no slashes */ - if (endp == path) { - bname[0] = *endp == '/' ? '/' : '.'; - bname[1] = '\0'; - return (0); - } else { - do { - endp--; - } while (endp > path && *endp == '/'); - } - - if (endp - path + 2 > PATH_MAX) - { - _rtld_error("Filename is too long: %s", path); - return(-1); - } - - strncpy(bname, path, endp - path + 1); - bname[endp - path + 1] = '\0'; - return (0); -} - -static void -linkmap_add(Obj_Entry *obj) -{ - struct link_map *l = &obj->linkmap; - struct link_map *prev; - - obj->linkmap.l_name = obj->path; - obj->linkmap.l_addr = obj->mapbase; - obj->linkmap.l_ld = obj->dynamic; -#ifdef __mips__ - /* GDB needs load offset on MIPS to use the symbols */ - obj->linkmap.l_offs = obj->relocbase; -#endif - - if (r_debug.r_map == NULL) { - r_debug.r_map = l; - return; - } - - /* - * Scan to the end of the list, but not past the entry for the - * dynamic linker, which we want to keep at the very end. - */ - for (prev = r_debug.r_map; - prev->l_next != NULL && prev->l_next != &obj_rtld.linkmap; - prev = prev->l_next) - ; - - /* Link in the new entry. */ - l->l_prev = prev; - l->l_next = prev->l_next; - if (l->l_next != NULL) - l->l_next->l_prev = l; - prev->l_next = l; -} - -static void -linkmap_delete(Obj_Entry *obj) -{ - struct link_map *l = &obj->linkmap; - - if (l->l_prev == NULL) { - if ((r_debug.r_map = l->l_next) != NULL) - l->l_next->l_prev = NULL; - return; - } - - if ((l->l_prev->l_next = l->l_next) != NULL) - l->l_next->l_prev = l->l_prev; -} - -/* - * Function for the debugger to set a breakpoint on to gain control. - * - * The two parameters allow the debugger to easily find and determine - * what the runtime loader is doing and to whom it is doing it. - * - * When the loadhook trap is hit (r_debug_state, set at program - * initialization), the arguments can be found on the stack: - * - * +8 struct link_map *m - * +4 struct r_debug *rd - * +0 RetAddr - */ -void -r_debug_state(struct r_debug* rd, struct link_map *m) -{ -} - -/* - * Get address of the pointer variable in the main program. - */ -const void ** -get_program_var_addr(const char *name) -{ - const Obj_Entry *obj; - unsigned long hash; - - hash = elf_hash(name); - for (obj = obj_main; obj != NULL; obj = obj->next) { - const Elf_Sym *def; - - if ((def = symlook_obj(name, hash, obj, NULL, 0)) != NULL) { - const void **addr; - - addr = (const void **)(obj->relocbase + def->st_value); - return addr; - } - } - return NULL; -} - -/* - * Set a pointer variable in the main program to the given value. This - * is used to set key variables such as "environ" before any of the - * init functions are called. - */ -void -set_program_var(const char *name, const void *value) -{ - const void **addr; - - if ((addr = get_program_var_addr(name)) != NULL) { - dbg("\"%s\": *%p <-- %p", name, addr, value); - *addr = value; - } -} - -/* - * Given a symbol name in a referencing object, find the corresponding - * definition of the symbol. Returns a pointer to the symbol, or NULL if - * no definition was found. Returns a pointer to the Obj_Entry of the - * defining object via the reference parameter DEFOBJ_OUT. - */ -static const Elf_Sym * -symlook_default(const char *name, unsigned long hash, const Obj_Entry *refobj, - const Obj_Entry **defobj_out, const Ver_Entry *ventry, int flags) -{ - DoneList donelist; - const Elf_Sym *def; - const Elf_Sym *symp; - const Obj_Entry *obj; - const Obj_Entry *defobj; - const Objlist_Entry *elm; - def = NULL; - defobj = NULL; - donelist_init(&donelist); - - /* - * Look first in the referencing object if linked symbolically. - * cbass: Treat LDSO as if linked with '-Bsymbolic' during initialization - */ - if ((refobj->rtld_init || refobj->symbolic) && !donelist_check(&donelist, refobj)) { - symp = symlook_obj(name, hash, refobj, ventry, flags); - if (symp != NULL) { - def = symp; - defobj = refobj; - } - - /* cbass: Don't use any further lookup logic during initialization */ - if (def && refobj->rtld_init) { - *defobj_out = defobj; - return def; - } - } - - /* Search all objects loaded at program start up. */ - if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { - symp = symlook_list(name, hash, &list_main, &obj, ventry, flags, - &donelist); - if (symp != NULL && - (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { - def = symp; - defobj = obj; - } - } - - /* Search all DAGs whose roots are RTLD_GLOBAL objects. */ - STAILQ_FOREACH(elm, &list_global, link) { - if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) - break; - symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, ventry, - flags, &donelist); - if (symp != NULL && - (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { - def = symp; - defobj = obj; - } - } - - /* Search all dlopened DAGs containing the referencing object. */ - STAILQ_FOREACH(elm, &refobj->dldags, link) { - if (def != NULL && ELF_ST_BIND(def->st_info) != STB_WEAK) - break; - symp = symlook_list(name, hash, &elm->obj->dagmembers, &obj, ventry, - flags, &donelist); - if (symp != NULL && - (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK)) { - def = symp; - defobj = obj; - } - } - - /* - * Search the dynamic linker itself, and possibly resolve the - * symbol from there. This is how the application links to - * dynamic linker services such as dlopen. Only the values listed - * in the "exports" array can be resolved from the dynamic linker. - */ - if (def == NULL || ELF_ST_BIND(def->st_info) == STB_WEAK) { - symp = symlook_obj(name, hash, &obj_rtld, ventry, flags); - if (symp != NULL && is_exported(symp)) { - def = symp; - defobj = &obj_rtld; - } - } - - if (def != NULL) - *defobj_out = defobj; - return def; -} - -static const Elf_Sym * -symlook_list(const char *name, unsigned long hash, const Objlist *objlist, - const Obj_Entry **defobj_out, const Ver_Entry *ventry, int flags, - DoneList *dlp) -{ - const Elf_Sym *symp; - const Elf_Sym *def; - const Obj_Entry *defobj; - const Objlist_Entry *elm; - - def = NULL; - defobj = NULL; - STAILQ_FOREACH(elm, objlist, link) { - if (donelist_check(dlp, elm->obj)) - continue; - if ((symp = symlook_obj(name, hash, elm->obj, ventry, flags)) != NULL) { - if (def == NULL || ELF_ST_BIND(symp->st_info) != STB_WEAK) { - def = symp; - defobj = elm->obj; - if (ELF_ST_BIND(def->st_info) != STB_WEAK) - break; - } - } - } - if (def != NULL) - *defobj_out = defobj; - return def; -} - -/* - * Search the symbol table of a shared object and all objects needed - * by it for a symbol of the given name. Search order is - * breadth-first. Returns a pointer to the symbol, or NULL if no - * definition was found. - */ -static const Elf_Sym * -symlook_needed(const char *name, unsigned long hash, const Needed_Entry *needed, - const Obj_Entry **defobj_out, const Ver_Entry *ventry, int flags, - DoneList *dlp) -{ - const Elf_Sym *def, *def_w; - const Needed_Entry *n; - const Obj_Entry *obj, *defobj, *defobj1; - - def = def_w = NULL; - defobj = NULL; - for (n = needed; n != NULL; n = n->next) { - if ((obj = n->obj) == NULL || - donelist_check(dlp, obj) || - (def = symlook_obj(name, hash, obj, ventry, flags)) == NULL) - continue; - defobj = obj; - if (ELF_ST_BIND(def->st_info) != STB_WEAK) { - *defobj_out = defobj; - return (def); - } - } - /* - * There we come when either symbol definition is not found in - * directly needed objects, or found symbol is weak. - */ - for (n = needed; n != NULL; n = n->next) { - if ((obj = n->obj) == NULL) - continue; - def_w = symlook_needed(name, hash, obj->needed, &defobj1, - ventry, flags, dlp); - if (def_w == NULL) - continue; - if (def == NULL || ELF_ST_BIND(def_w->st_info) != STB_WEAK) { - def = def_w; - defobj = defobj1; - } - if (ELF_ST_BIND(def_w->st_info) != STB_WEAK) - break; - } - if (def != NULL) - *defobj_out = defobj; - return (def); -} - -/* - * Search the symbol table of a single shared object for a symbol of - * the given name and version, if requested. Returns a pointer to the - * symbol, or NULL if no definition was found. - * - * The symbol's hash value is passed in for efficiency reasons; that - * eliminates many recomputations of the hash value. - */ -const Elf_Sym * -symlook_obj(const char *name, unsigned long hash, const Obj_Entry *obj, - const Ver_Entry *ventry, int flags) -{ - unsigned long symnum; - const Elf_Sym *vsymp; - Elf_Versym verndx; - int vcount; - - if (obj->buckets == NULL) - return NULL; - - vsymp = NULL; - vcount = 0; - symnum = obj->buckets[hash % obj->nbuckets]; - - for (; symnum != STN_UNDEF; symnum = obj->chains[symnum]) { - const Elf_Sym *symp; - const char *strp; - - if (symnum >= obj->nchains) - return NULL; /* Bad object */ - - symp = obj->symtab + symnum; - strp = obj->strtab + symp->st_name; - - switch (ELF_ST_TYPE(symp->st_info)) { - case STT_FUNC: - case STT_NOTYPE: - case STT_OBJECT: - if (symp->st_value == 0) - continue; - /* fallthrough */ - case STT_TLS: - if (symp->st_shndx != SHN_UNDEF || - ((flags & SYMLOOK_IN_PLT) == 0 && - ELF_ST_TYPE(symp->st_info) == STT_FUNC)) - break; - /* fallthrough */ - default: - continue; - } - if (name[0] != strp[0] || strcmp(name, strp) != 0) - continue; - - if (ventry == NULL) { - if (obj->versyms != NULL) { - verndx = VER_NDX(obj->versyms[symnum]); - if (verndx > obj->vernum) { - _rtld_error("%s: symbol %s references wrong version %d", - obj->path, obj->strtab + symnum, verndx); - continue; - } - /* - * If we are not called from dlsym (i.e. this is a normal - * relocation from unversioned binary, accept the symbol - * immediately if it happens to have first version after - * this shared object became versioned. Otherwise, if - * symbol is versioned and not hidden, remember it. If it - * is the only symbol with this name exported by the - * shared object, it will be returned as a match at the - * end of the function. If symbol is global (verndx < 2) - * accept it unconditionally. - */ - if ((flags & SYMLOOK_DLSYM) == 0 && verndx == VER_NDX_GIVEN) - return symp; - else if (verndx >= VER_NDX_GIVEN) { - if ((obj->versyms[symnum] & VER_NDX_HIDDEN) == 0) { - if (vsymp == NULL) - vsymp = symp; - vcount ++; - } - continue; - } - } - return symp; - } else { - if (obj->versyms == NULL) { - if (object_match_name(obj, ventry->name)) { - _rtld_error("%s: object %s should provide version %s for " - "symbol %s", obj_rtld.path, obj->path, ventry->name, - obj->strtab + symnum); - continue; - } - } else { - verndx = VER_NDX(obj->versyms[symnum]); - if (verndx > obj->vernum) { - _rtld_error("%s: symbol %s references wrong version %d", - obj->path, obj->strtab + symnum, verndx); - continue; - } - if (obj->vertab[verndx].hash != ventry->hash || - strcmp(obj->vertab[verndx].name, ventry->name)) { - /* - * Version does not match. Look if this is a global symbol - * and if it is not hidden. If global symbol (verndx < 2) - * is available, use it. Do not return symbol if we are - * called by dlvsym, because dlvsym looks for a specific - * version and default one is not what dlvsym wants. - */ - if ((flags & SYMLOOK_DLSYM) || - (obj->versyms[symnum] & VER_NDX_HIDDEN) || - (verndx >= VER_NDX_GIVEN)) - continue; - } - } - return symp; - } - } - return (vcount == 1) ? vsymp : NULL; -} - -static void -trace_loaded_objects(Obj_Entry *obj) -{ - char *fmt1, *fmt2, *fmt, *main_local, *list_containers; - int c; - - if ((main_local = getenv(LD_ "TRACE_LOADED_OBJECTS_PROGNAME")) == NULL) - main_local = ""; - - if ((fmt1 = getenv(LD_ "TRACE_LOADED_OBJECTS_FMT1")) == NULL) - fmt1 = "\t%o => %p (%x)\n"; - - if ((fmt2 = getenv(LD_ "TRACE_LOADED_OBJECTS_FMT2")) == NULL) - fmt2 = "\t%o (%x)\n"; - - list_containers = getenv(LD_ "TRACE_LOADED_OBJECTS_ALL"); - - for (; obj; obj = obj->next) { - Needed_Entry *needed; - char *name, *path; - bool is_lib; - - if (list_containers && obj->needed != NULL) - printf("%s:\n", obj->path); - for (needed = obj->needed; needed; needed = needed->next) { - if (needed->obj != NULL) { - if (needed->obj->traced && !list_containers) - continue; - needed->obj->traced = true; - path = needed->obj->path; - } else - path = "not found"; - - name = (char *)obj->strtab + needed->name; - is_lib = strncmp(name, "lib", 3) == 0; /* XXX - bogus */ - - fmt = is_lib ? fmt1 : fmt2; - while ((c = *fmt++) != '\0') { - switch (c) { - default: - putchar(c); - continue; - case '\\': - switch (c = *fmt) { - case '\0': - continue; - case 'n': - putchar('\n'); - break; - case 't': - putchar('\t'); - break; - } - break; - case '%': - switch (c = *fmt) { - case '\0': - continue; - case '%': - default: - putchar(c); - break; - case 'A': - printf("%s", main_local); - break; - case 'a': - printf("%s", obj_main->path); - break; - case 'o': - printf("%s", name); - break; -#if 0 - case 'm': - printf("%d", sodp->sod_major); - break; - case 'n': - printf("%d", sodp->sod_minor); - break; -#endif - case 'p': - printf("%s", path); - break; - case 'x': - printf("%p", needed->obj ? needed->obj->mapbase : 0); - break; - } - break; - } - ++fmt; - } - } - } -} - -/* - * Unload a dlopened object and its dependencies from memory and from - * our data structures. It is assumed that the DAG rooted in the - * object has already been unreferenced, and that the object has a - * reference count of 0. - */ -static void -unload_object(Obj_Entry *root) -{ - Obj_Entry *obj; - Obj_Entry **linkp; - - assert(root->refcount == 0); - - /* - * Pass over the DAG removing unreferenced objects from - * appropriate lists. - */ - unlink_object(root); - - /* Unmap all objects that are no longer referenced. */ - linkp = &obj_list->next; - while ((obj = *linkp) != NULL) { - if (obj->refcount == 0) { - LD_UTRACE(UTRACE_UNLOAD_OBJECT, obj, obj->mapbase, obj->mapsize, 0, - obj->path); - dbg("unloading \"%s\"", obj->path); - munmap(obj->mapbase, obj->mapsize); - linkmap_delete(obj); - *linkp = obj->next; - obj_count--; - obj_free(obj); - } else - linkp = &obj->next; - } - obj_tail = linkp; -} - -static void -unlink_object(Obj_Entry *root) -{ - Objlist_Entry *elm; - - if (root->refcount == 0) { - /* Remove the object from the RTLD_GLOBAL list. */ - objlist_remove(&list_global, root); - - /* Remove the object from all objects' DAG lists. */ - STAILQ_FOREACH(elm, &root->dagmembers, link) { - objlist_remove(&elm->obj->dldags, root); - if (elm->obj != root) - unlink_object(elm->obj); - } - } -} - -static void -ref_dag(Obj_Entry *root) -{ - Objlist_Entry *elm; - - STAILQ_FOREACH(elm, &root->dagmembers, link) - elm->obj->refcount++; -} - -static void -unref_dag(Obj_Entry *root) -{ - Objlist_Entry *elm; - - STAILQ_FOREACH(elm, &root->dagmembers, link) - elm->obj->refcount--; -} - -/* - * Common code for MD __tls_get_addr(). - */ -void * -tls_get_addr_common(Elf_Addr** dtvp, int index, size_t offset) -{ - Elf_Addr* dtv = *dtvp; - int lockstate; - - /* Check dtv generation in case new modules have arrived */ - if (dtv[0] != tls_dtv_generation) { - Elf_Addr* newdtv; - int to_copy; - - lockstate = wlock_acquire(rtld_bind_lock); - newdtv = calloc(1, (tls_max_index + 2) * sizeof(Elf_Addr)); - to_copy = dtv[1]; - if (to_copy > tls_max_index) - to_copy = tls_max_index; - memcpy(&newdtv[2], &dtv[2], to_copy * sizeof(Elf_Addr)); - newdtv[0] = tls_dtv_generation; - newdtv[1] = tls_max_index; - free(dtv); - wlock_release(rtld_bind_lock, lockstate); - *dtvp = newdtv; - } - - /* Dynamically allocate module TLS if necessary */ - if (!dtv[index + 1]) { - /* Signal safe, wlock will block out signals. */ - lockstate = wlock_acquire(rtld_bind_lock); - if (!dtv[index + 1]) - dtv[index + 1] = (Elf_Addr)allocate_module_tls(index); - wlock_release(rtld_bind_lock, lockstate); - } - return (void*) (dtv[index + 1] + offset); -} - -/* XXX not sure what variants to use for arm. */ - -#if defined(__ia64__) || defined(__powerpc__) - -/* - * Allocate Static TLS using the Variant I method. - */ -void * -allocate_tls(Obj_Entry *objs, void *oldtcb, size_t tcbsize, size_t tcbalign) -{ - Obj_Entry *obj; - char *tcb; - Elf_Addr **tls; - Elf_Addr *dtv; - Elf_Addr addr; - int i; - - if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE) - return (oldtcb); - - assert(tcbsize >= TLS_TCB_SIZE); - tcb = calloc(1, tls_static_space - TLS_TCB_SIZE + tcbsize); - tls = (Elf_Addr **)(tcb + tcbsize - TLS_TCB_SIZE); - - if (oldtcb != NULL) { - memcpy(tls, oldtcb, tls_static_space); - free(oldtcb); - - /* Adjust the DTV. */ - dtv = tls[0]; - for (i = 0; i < dtv[1]; i++) { - if (dtv[i+2] >= (Elf_Addr)oldtcb && - dtv[i+2] < (Elf_Addr)oldtcb + tls_static_space) { - dtv[i+2] = dtv[i+2] - (Elf_Addr)oldtcb + (Elf_Addr)tls; - } - } - } else { - dtv = calloc(tls_max_index + 2, sizeof(Elf_Addr)); - tls[0] = dtv; - dtv[0] = tls_dtv_generation; - dtv[1] = tls_max_index; - - for (obj = objs; obj; obj = obj->next) { - if (obj->tlsoffset) { - addr = (Elf_Addr)tls + obj->tlsoffset; - memset((void*) (addr + obj->tlsinitsize), - 0, obj->tlssize - obj->tlsinitsize); - if (obj->tlsinit) - memcpy((void*) addr, obj->tlsinit, - obj->tlsinitsize); - dtv[obj->tlsindex + 1] = addr; - } - } - } - - return (tcb); -} - -void -free_tls(void *tcb, size_t tcbsize, size_t tcbalign) -{ - Elf_Addr *dtv; - Elf_Addr tlsstart, tlsend; - int dtvsize, i; - - assert(tcbsize >= TLS_TCB_SIZE); - - tlsstart = (Elf_Addr)tcb + tcbsize - TLS_TCB_SIZE; - tlsend = tlsstart + tls_static_space; - - dtv = *(Elf_Addr **)tlsstart; - dtvsize = dtv[1]; - for (i = 0; i < dtvsize; i++) { - if (dtv[i+2] && (dtv[i+2] < tlsstart || dtv[i+2] >= tlsend)) { - free((void*)dtv[i+2]); - } - } - free(dtv); - free(tcb); -} - -#endif - -#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \ - defined(__arm__) - -/* - * Allocate Static TLS using the Variant II method. - */ -void * -allocate_tls(Obj_Entry *objs, void *oldtls, size_t tcbsize, size_t tcbalign) -{ - Obj_Entry *obj; - size_t size; - char *tls; - Elf_Addr *dtv, *olddtv; - Elf_Addr segbase, oldsegbase, addr; - int i; - - size = round(tls_static_space, tcbalign); - - assert(tcbsize >= 2*sizeof(Elf_Addr)); - tls = calloc(1, size + tcbsize); - dtv = calloc(1, (tls_max_index + 2) * sizeof(Elf_Addr)); - - segbase = (Elf_Addr)(tls + size); - ((Elf_Addr*)segbase)[0] = segbase; - ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv; - - dtv[0] = tls_dtv_generation; - dtv[1] = tls_max_index; - - if (oldtls) { - /* - * Copy the static TLS block over whole. - */ - oldsegbase = (Elf_Addr) oldtls; - memcpy((void *)(segbase - tls_static_space), - (const void *)(oldsegbase - tls_static_space), - tls_static_space); - - /* - * If any dynamic TLS blocks have been created tls_get_addr(), - * move them over. - */ - olddtv = ((Elf_Addr**)oldsegbase)[1]; - for (i = 0; i < olddtv[1]; i++) { - if (olddtv[i+2] < oldsegbase - size || olddtv[i+2] > oldsegbase) { - dtv[i+2] = olddtv[i+2]; - olddtv[i+2] = 0; - } - } - - /* - * We assume that this block was the one we created with - * allocate_initial_tls(). - */ - free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr)); - } else { - for (obj = objs; obj; obj = obj->next) { - if (obj->tlsoffset) { - addr = segbase - obj->tlsoffset; - memset((void*) (addr + obj->tlsinitsize), - 0, obj->tlssize - obj->tlsinitsize); - if (obj->tlsinit) - memcpy((void*) addr, obj->tlsinit, obj->tlsinitsize); - dtv[obj->tlsindex + 1] = addr; - } - } - } - - return (void*) segbase; -} - -void -free_tls(void *tls, size_t tcbsize, size_t tcbalign) -{ - size_t size; - Elf_Addr* dtv; - int dtvsize, i; - Elf_Addr tlsstart, tlsend; - - /* - * Figure out the size of the initial TLS block so that we can - * find stuff which ___tls_get_addr() allocated dynamically. - */ - size = round(tls_static_space, tcbalign); - - dtv = ((Elf_Addr**)tls)[1]; - dtvsize = dtv[1]; - tlsend = (Elf_Addr) tls; - tlsstart = tlsend - size; - for (i = 0; i < dtvsize; i++) { - if (dtv[i+2] && (dtv[i+2] < tlsstart || dtv[i+2] > tlsend)) { - free((void*) dtv[i+2]); - } - } - - free((void*) tlsstart); - free((void*) dtv); -} - -#endif - -/* - * Allocate TLS block for module with given index. - */ -void * -allocate_module_tls(int index) -{ - Obj_Entry* obj; - char* p; - - for (obj = obj_list; obj; obj = obj->next) { - if (obj->tlsindex == index) - break; - } - if (!obj) { - _rtld_error("Can't find module with TLS index %d", index); - die(); - } - - p = malloc(obj->tlssize); - memcpy(p, obj->tlsinit, obj->tlsinitsize); - memset(p + obj->tlsinitsize, 0, obj->tlssize - obj->tlsinitsize); - - return p; -} - -bool -allocate_tls_offset(Obj_Entry *obj) -{ - size_t off; - - if (obj->tls_done) - return true; - - if (obj->tlssize == 0) { - obj->tls_done = true; - return true; - } - - if (obj->tlsindex == 1) - off = calculate_first_tls_offset(obj->tlssize, obj->tlsalign); - else - off = calculate_tls_offset(tls_last_offset, tls_last_size, - obj->tlssize, obj->tlsalign); - - /* - * If we have already fixed the size of the static TLS block, we - * must stay within that size. When allocating the static TLS, we - * leave a small amount of space spare to be used for dynamically - * loading modules which use static TLS. - */ - if (tls_static_space) { - if (calculate_tls_end(off, obj->tlssize) > tls_static_space) - return false; - } - - tls_last_offset = obj->tlsoffset = off; - tls_last_size = obj->tlssize; - obj->tls_done = true; - - return true; -} - -void -free_tls_offset(Obj_Entry *obj) -{ -#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__) || \ - defined(__arm__) - /* - * If we were the last thing to allocate out of the static TLS - * block, we give our space back to the 'allocator'. This is a - * simplistic workaround to allow libGL.so.1 to be loaded and - * unloaded multiple times. We only handle the Variant II - * mechanism for now - this really needs a proper allocator. - */ - if (calculate_tls_end(obj->tlsoffset, obj->tlssize) - == calculate_tls_end(tls_last_offset, tls_last_size)) { - tls_last_offset -= obj->tlssize; - tls_last_size = 0; - } -#endif -} - -void * -_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign) -{ - void *ret; - int lockstate; - - lockstate = wlock_acquire(rtld_bind_lock); - ret = allocate_tls(obj_list, oldtls, tcbsize, tcbalign); - wlock_release(rtld_bind_lock, lockstate); - return (ret); -} - -void -_rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign) -{ - int lockstate; - - lockstate = wlock_acquire(rtld_bind_lock); - free_tls(tcb, tcbsize, tcbalign); - wlock_release(rtld_bind_lock, lockstate); -} - -static void -object_add_name(Obj_Entry *obj, const char *name) -{ - Name_Entry *entry; - size_t len; - - len = strlen(name); - entry = malloc(sizeof(Name_Entry) + len); - - if (entry != NULL) { - strcpy(entry->name, name); - STAILQ_INSERT_TAIL(&obj->names, entry, link); - } -} - -static const char * -shorten(const char *name) -{ - const char *shortname = name; - for (; *name; name++) - if (*name == '/') - shortname = name + 1; - - return shortname; -} - -static int -object_match_name(const Obj_Entry *obj, const char *name) -{ - Name_Entry *entry; - const char *shortname = shorten(name); - - STAILQ_FOREACH(entry, &obj->names, link) { - if (strcmp(name, entry->name) == 0) - return (1); - const char *entry_name = shorten(entry->name); - if (strcmp(shortname, entry_name) == 0) - return (1); - } - - return (0); -} - -static Obj_Entry * -locate_dependency(const Obj_Entry *obj, const char *name) -{ - const Objlist_Entry *entry; - const Needed_Entry *needed; - - STAILQ_FOREACH(entry, &list_main, link) { - if (object_match_name(entry->obj, name)) - return entry->obj; - } - - for (needed = obj->needed; needed != NULL; needed = needed->next) { - if (needed->obj == NULL) - continue; - if (object_match_name(needed->obj, name)) - return needed->obj; - } - _rtld_error("%s: Unexpected inconsistency: dependency %s not found", - obj->path, name); - die(); -} - -static int -check_object_provided_version(Obj_Entry *refobj, const Obj_Entry *depobj, - const Elf_Vernaux *vna) -{ - const Elf_Verdef *vd; - const char *vername; - - vername = refobj->strtab + vna->vna_name; - vd = depobj->verdef; - if (vd == NULL) { - _rtld_error("%s: version %s required by %s not defined", - depobj->path, vername, refobj->path); - return (-1); - } - for (;;) { - if (vd->vd_version != VER_DEF_CURRENT) { - _rtld_error("%s: Unsupported version %d of Elf_Verdef entry", - depobj->path, vd->vd_version); - return (-1); - } - if (vna->vna_hash == vd->vd_hash) { - const Elf_Verdaux *aux = (const Elf_Verdaux *) - ((char *)vd + vd->vd_aux); - if (strcmp(vername, depobj->strtab + aux->vda_name) == 0) - return (0); - } - if (vd->vd_next == 0) - break; - vd = (const Elf_Verdef *) ((char *)vd + vd->vd_next); - } - if (vna->vna_flags & VER_FLG_WEAK) - return (0); - _rtld_error("%s: version %s required by %s not found", - depobj->path, vername, refobj->path); - return (-1); -} - -static int -rtld_verify_object_versions(Obj_Entry *obj) -{ - const Elf_Verneed *vn; - const Elf_Verdef *vd; - const Elf_Verdaux *vda; - const Elf_Vernaux *vna; - const Obj_Entry *depobj; - int maxvernum, vernum; - - maxvernum = 0; - /* - * Walk over defined and required version records and figure out - * max index used by any of them. Do very basic sanity checking - * while there. - */ - vn = obj->verneed; - while (vn != NULL) { - if (vn->vn_version != VER_NEED_CURRENT) { - _rtld_error("%s: Unsupported version %d of Elf_Verneed entry", - obj->path, vn->vn_version); - return (-1); - } - vna = (const Elf_Vernaux *) ((char *)vn + vn->vn_aux); - for (;;) { - vernum = VER_NEED_IDX(vna->vna_other); - if (vernum > maxvernum) - maxvernum = vernum; - if (vna->vna_next == 0) - break; - vna = (const Elf_Vernaux *) ((char *)vna + vna->vna_next); - } - if (vn->vn_next == 0) - break; - vn = (const Elf_Verneed *) ((char *)vn + vn->vn_next); - } - - vd = obj->verdef; - while (vd != NULL) { - if (vd->vd_version != VER_DEF_CURRENT) { - _rtld_error("%s: Unsupported version %d of Elf_Verdef entry", - obj->path, vd->vd_version); - return (-1); - } - vernum = VER_DEF_IDX(vd->vd_ndx); - if (vernum > maxvernum) - maxvernum = vernum; - if (vd->vd_next == 0) - break; - vd = (const Elf_Verdef *) ((char *)vd + vd->vd_next); - } - - if (maxvernum == 0) - return (0); - - /* - * Store version information in array indexable by version index. - * Verify that object version requirements are satisfied along the - * way. - */ - obj->vernum = maxvernum + 1; - obj->vertab = calloc(obj->vernum, sizeof(Ver_Entry)); - - vd = obj->verdef; - while (vd != NULL) { - if ((vd->vd_flags & VER_FLG_BASE) == 0) { - vernum = VER_DEF_IDX(vd->vd_ndx); - assert(vernum <= maxvernum); - vda = (const Elf_Verdaux *)((char *)vd + vd->vd_aux); - obj->vertab[vernum].hash = vd->vd_hash; - obj->vertab[vernum].name = obj->strtab + vda->vda_name; - obj->vertab[vernum].file = NULL; - obj->vertab[vernum].flags = 0; - } - if (vd->vd_next == 0) - break; - vd = (const Elf_Verdef *) ((char *)vd + vd->vd_next); - } - - vn = obj->verneed; - while (vn != NULL) { - depobj = locate_dependency(obj, obj->strtab + vn->vn_file); - vna = (const Elf_Vernaux *) ((char *)vn + vn->vn_aux); - for (;;) { - if (check_object_provided_version(obj, depobj, vna)) - return (-1); - vernum = VER_NEED_IDX(vna->vna_other); - assert(vernum <= maxvernum); - obj->vertab[vernum].hash = vna->vna_hash; - obj->vertab[vernum].name = obj->strtab + vna->vna_name; - obj->vertab[vernum].file = obj->strtab + vn->vn_file; - obj->vertab[vernum].flags = (vna->vna_other & VER_NEED_HIDDEN) ? - VER_INFO_HIDDEN : 0; - if (vna->vna_next == 0) - break; - vna = (const Elf_Vernaux *) ((char *)vna + vna->vna_next); - } - if (vn->vn_next == 0) - break; - vn = (const Elf_Verneed *) ((char *)vn + vn->vn_next); - } - return 0; -} - -static int -rtld_verify_versions(const Objlist *objlist) -{ - Objlist_Entry *entry; - int rc; - - rc = 0; - STAILQ_FOREACH(entry, objlist, link) { - /* - * Skip dummy objects or objects that have their version requirements - * already checked. - */ - if (entry->obj->strtab == NULL || entry->obj->vertab != NULL) - continue; - if (rtld_verify_object_versions(entry->obj) == -1) { - rc = -1; - if (ld_tracing == NULL) - break; - } - } - if (rc == 0 || ld_tracing != NULL) - rc = rtld_verify_object_versions(&obj_rtld); - return rc; -} - -const Ver_Entry * -fetch_ventry(const Obj_Entry *obj, unsigned long symnum) -{ - Elf_Versym vernum; - - if (obj->vertab) { - vernum = VER_NDX(obj->versyms[symnum]); - if (vernum >= obj->vernum) { - _rtld_error("%s: symbol %s has wrong verneed value %d", - obj->path, obj->strtab + symnum, vernum); - } else if (obj->vertab[vernum].hash != 0) { - return &obj->vertab[vernum]; - } - } - return NULL; -} diff --git a/repos/os/src/lib/ldso/contrib/rtld.h b/repos/os/src/lib/ldso/contrib/rtld.h deleted file mode 100644 index 75bb258a4..000000000 --- a/repos/os/src/lib/ldso/contrib/rtld.h +++ /dev/null @@ -1,286 +0,0 @@ -/*- - * Copyright 1996, 1997, 1998, 1999, 2000 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/rtld.h,v 1.38.8.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -#ifndef RTLD_H /* { */ -#define RTLD_H 1 - -#include -#include -#include - -#include -#include -#include - -#include "rtld_lock.h" -#include "rtld_machdep.h" - -#ifdef COMPAT_32BIT -#undef STANDARD_LIBRARY_PATH -#undef _PATH_ELF_HINTS -#define _PATH_ELF_HINTS "/var/run/ld-elf32.so.hints" -/* For running 32 bit binaries */ -#define STANDARD_LIBRARY_PATH "/lib32:/usr/lib32" -#define LD_ "LD_32_" -#endif - -#ifndef STANDARD_LIBRARY_PATH -#define STANDARD_LIBRARY_PATH "/lib:/usr/lib" -#endif -#ifndef LD_ -#define LD_ "LD_" -#endif - -#define NEW(type) ((type *) xmalloc(sizeof(type))) -#define CNEW(type) ((type *) xcalloc(sizeof(type))) - -/* We might as well do booleans like C++. */ -typedef unsigned char bool; -#define false 0 -#define true 1 - -extern size_t tls_last_offset; -extern size_t tls_last_size; -extern size_t tls_static_space; -extern int tls_dtv_generation; -extern int tls_max_index; - -struct stat; -struct Struct_Obj_Entry; - -/* Lists of shared objects */ -typedef struct Struct_Objlist_Entry { - STAILQ_ENTRY(Struct_Objlist_Entry) link; - struct Struct_Obj_Entry *obj; -} Objlist_Entry; - -typedef STAILQ_HEAD(Struct_Objlist, Struct_Objlist_Entry) Objlist; - -/* Types of init and fini functions */ -typedef void (*InitFunc)(void); - -/* Lists of shared object dependencies */ -typedef struct Struct_Needed_Entry { - struct Struct_Needed_Entry *next; - struct Struct_Obj_Entry *obj; - unsigned long name; /* Offset of name in string table */ -} Needed_Entry; - -typedef struct Struct_Name_Entry { - STAILQ_ENTRY(Struct_Name_Entry) link; - char name[1]; -} Name_Entry; - -/* Lock object */ -typedef struct Struct_LockInfo { - void *context; /* Client context for creating locks */ - void *thelock; /* The one big lock */ - /* Debugging aids. */ - volatile int rcount; /* Number of readers holding lock */ - volatile int wcount; /* Number of writers holding lock */ - /* Methods */ - void *(*lock_create)(void *context); - void (*rlock_acquire)(void *lock); - void (*wlock_acquire)(void *lock); - void (*rlock_release)(void *lock); - void (*wlock_release)(void *lock); - void (*lock_destroy)(void *lock); - void (*context_destroy)(void *context); -} LockInfo; - -typedef struct Struct_Ver_Entry { - Elf_Word hash; - unsigned int flags; - const char *name; - const char *file; -} Ver_Entry; - -#define VER_INFO_HIDDEN 0x01 - -/* - * Shared object descriptor. - * - * Items marked with "(%)" are dynamically allocated, and must be freed - * when the structure is destroyed. - * - * CAUTION: It appears that the JDK port peeks into these structures. - * It looks at "next" and "mapbase" at least. Don't add new members - * near the front, until this can be straightened out. - */ -typedef struct Struct_Obj_Entry { - /* - * These two items have to be set right for compatibility with the - * original ElfKit crt1.o. - */ - Elf_Size magic; /* Magic number (sanity check) */ - Elf_Size version; /* Version number of struct format */ - - struct Struct_Obj_Entry *next; - char *path; /* Pathname of underlying file (%) */ - char *origin_path; /* Directory path of origin file */ - int refcount; - int dl_refcount; /* Number of times loaded by dlopen */ - - /* These items are computed by map_object() or by digest_phdr(). */ - caddr_t mapbase; /* Base address of mapped region */ - size_t mapsize; /* Size of mapped region in bytes */ - size_t textsize; /* Size of text segment in bytes */ - Elf_Addr vaddrbase; /* Base address in shared object file */ - caddr_t relocbase; /* Relocation constant = mapbase - vaddrbase */ - const Elf_Dyn *dynamic; /* Dynamic section */ - caddr_t entry; /* Entry point */ - const Elf_Phdr *phdr; /* Program header if it is mapped, else NULL */ - size_t phsize; /* Size of program header in bytes */ - const char *interp; /* Pathname of the interpreter, if any */ - - /* TLS information */ - int tlsindex; /* Index in DTV for this module */ - void *tlsinit; /* Base address of TLS init block */ - size_t tlsinitsize; /* Size of TLS init block for this module */ - size_t tlssize; /* Size of TLS block for this module */ - size_t tlsoffset; /* Offset of static TLS block for this module */ - size_t tlsalign; /* Alignment of static TLS block */ - - /* Items from the dynamic section. */ - Elf_Addr *pltgot; /* PLT or GOT, depending on architecture */ - const Elf_Rel *rel; /* Relocation entries */ - unsigned long relsize; /* Size in bytes of relocation info */ - const Elf_Rela *rela; /* Relocation entries with addend */ - unsigned long relasize; /* Size in bytes of addend relocation info */ - const Elf_Rel *pltrel; /* PLT relocation entries */ - unsigned long pltrelsize; /* Size in bytes of PLT relocation info */ - const Elf_Rela *pltrela; /* PLT relocation entries with addend */ - unsigned long pltrelasize; /* Size in bytes of PLT addend reloc info */ - const Elf_Sym *symtab; /* Symbol table */ - const char *strtab; /* String table */ - unsigned long strsize; /* Size in bytes of string table */ - - const Elf_Verneed *verneed; /* Required versions. */ - Elf_Word verneednum; /* Number of entries in verneed table */ - const Elf_Verdef *verdef; /* Provided versions. */ - Elf_Word verdefnum; /* Number of entries in verdef table */ - const Elf_Versym *versyms; /* Symbol versions table */ - - const Elf_Hashelt *buckets; /* Hash table buckets array */ - unsigned long nbuckets; /* Number of buckets */ - const Elf_Hashelt *chains; /* Hash table chain array */ - unsigned long nchains; /* Number of chains */ - - const char *rpath; /* Search path specified in object */ - Needed_Entry *needed; /* Shared objects needed by this one (%) */ - - STAILQ_HEAD(, Struct_Name_Entry) names; /* List of names for this object we - know about. */ - Ver_Entry *vertab; /* Versions required /defined by this object */ - int vernum; /* Number of entries in vertab */ - - Elf_Addr init; /* Initialization function to call */ - Elf_Addr fini; /* Termination function to call */ - - bool mainprog : 1; /* True if this is the main program */ - bool rtld : 1; /* True if this is the dynamic linker */ - bool rtld_init : 1; /* True during rtld initialization */ - bool textrel : 1; /* True if there are relocations to text seg */ - bool symbolic : 1; /* True if generated with "-Bsymbolic" */ - bool bind_now : 1; /* True if all relocations should be made first */ - bool traced : 1; /* Already printed in ldd trace output */ - bool jmpslots_done : 1; /* Already have relocated the jump slots */ - bool init_done : 1; /* Already have added object to init list */ - bool tls_done : 1; /* Already allocated offset for static TLS */ - bool phdr_alloc : 1; /* Phdr is allocated and needs to be freed. */ - - struct link_map linkmap; /* for GDB and dlinfo() */ - Objlist dldags; /* Object belongs to these dlopened DAGs (%) */ - Objlist dagmembers; /* DAG has these members (%) */ - dev_t dev; /* Object's filesystem's device */ - ino_t ino; /* Object's inode number */ - void *priv; /* Platform-dependant */ -} Obj_Entry; - -#define RTLD_MAGIC 0xd550b87a -#define RTLD_VERSION 1 - -#define RTLD_STATIC_TLS_EXTRA 64 - -/* Flags to be passed into symlook_ family of functions. */ -#define SYMLOOK_IN_PLT 0x01 /* Lookup for PLT symbol */ -#define SYMLOOK_DLSYM 0x02 /* Return newes versioned symbol. Used by - dlsym. */ - -/* - * Symbol cache entry used during relocation to avoid multiple lookups - * of the same symbol. - */ -typedef struct Struct_SymCache { - const Elf_Sym *sym; /* Symbol table entry */ - const Obj_Entry *obj; /* Shared object which defines it */ -} SymCache; - -extern void _rtld_error(const char *, ...) __printflike(1, 2); -extern Obj_Entry *map_object(int, const char *, const struct stat *); -extern void *xcalloc(size_t); -extern void *xmalloc(size_t); -extern char *xstrdup(const char *); -extern Elf_Addr _GLOBAL_OFFSET_TABLE_[]; - -extern void dump_relocations (Obj_Entry *); -extern void dump_obj_relocations (Obj_Entry *); -extern void dump_Elf_Rel (Obj_Entry *, const Elf_Rel *, u_long); -extern void dump_Elf_Rela (Obj_Entry *, const Elf_Rela *, u_long); - -/* - * Function declarations. - */ -unsigned long elf_hash(const char *); -const Elf_Sym *find_symdef(unsigned long, const Obj_Entry *, - const Obj_Entry **, int, SymCache *); -void init_pltgot(Obj_Entry *); -void lockdflt_init(void); -void obj_free(Obj_Entry *); -Obj_Entry *obj_new(void); -void _rtld_bind_start(void); -const Elf_Sym *symlook_obj(const char *, unsigned long, const Obj_Entry *, - const Ver_Entry *, int); -void *tls_get_addr_common(Elf_Addr** dtvp, int index, size_t offset); -void *allocate_tls(Obj_Entry *, void *, size_t, size_t); -void free_tls(void *, size_t, size_t); -void *allocate_module_tls(int index); -bool allocate_tls_offset(Obj_Entry *obj); -void free_tls_offset(Obj_Entry *obj); -const Ver_Entry *fetch_ventry(const Obj_Entry *obj, unsigned long); -void set_program_var(const char *name, const void *value); - -/* - * MD function declarations. - */ -int do_copy_relocations(Obj_Entry *); -int reloc_non_plt(Obj_Entry *, Obj_Entry *); -int reloc_plt(Obj_Entry *); -int reloc_jmpslots(Obj_Entry *); -void allocate_initial_tls(Obj_Entry *); - -#endif /* } */ diff --git a/repos/os/src/lib/ldso/contrib/rtld_lock.c b/repos/os/src/lib/ldso/contrib/rtld_lock.c deleted file mode 100644 index b4b43214f..000000000 --- a/repos/os/src/lib/ldso/contrib/rtld_lock.c +++ /dev/null @@ -1,334 +0,0 @@ -/*- - * Copyright 1999, 2000 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * from: FreeBSD: src/libexec/rtld-elf/sparc64/lockdflt.c,v 1.3 2002/10/09 - * $FreeBSD: src/libexec/rtld-elf/rtld_lock.c,v 1.4.2.3.2.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -/* - * Thread locking implementation for the dynamic linker. - * - * We use the "simple, non-scalable reader-preference lock" from: - * - * J. M. Mellor-Crummey and M. L. Scott. "Scalable Reader-Writer - * Synchronization for Shared-Memory Multiprocessors." 3rd ACM Symp. on - * Principles and Practice of Parallel Programming, April 1991. - * - * In this algorithm the lock is a single word. Its low-order bit is - * set when a writer holds the lock. The remaining high-order bits - * contain a count of readers desiring the lock. The algorithm requires - * atomic "compare_and_store" and "add" operations, which we implement - * using assembly language sequences in "rtld_start.S". - */ - -#include -#include -#include - -#include "debug.h" -#include "rtld.h" -#include "rtld_machdep.h" - -#define WAFLAG 0x1 /* A writer holds the lock */ -#define RC_INCR 0x2 /* Adjusts count of readers desiring lock */ - -typedef struct Struct_Lock { - volatile u_int lock; - void *base; -} Lock; - -static sigset_t fullsigmask, oldsigmask; -static int thread_flag; - -static void * -def_lock_create() -{ - void *base; - char *p; - uintptr_t r; - Lock *l; - - /* - * Arrange for the lock to occupy its own cache line. First, we - * optimistically allocate just a cache line, hoping that malloc - * will give us a well-aligned block of memory. If that doesn't - * work, we allocate a larger block and take a well-aligned cache - * line from it. - */ - base = xmalloc(CACHE_LINE_SIZE); - p = (char *)base; - if ((uintptr_t)p % CACHE_LINE_SIZE != 0) { - free(base); - base = xmalloc(2 * CACHE_LINE_SIZE); - p = (char *)base; - if ((r = (uintptr_t)p % CACHE_LINE_SIZE) != 0) - p += CACHE_LINE_SIZE - r; - } - l = (Lock *)p; - l->base = base; - l->lock = 0; - return l; -} - -static void -def_lock_destroy(void *lock) -{ - Lock *l = (Lock *)lock; - - free(l->base); -} - -static void -def_rlock_acquire(void *lock) -{ - Lock *l = (Lock *)lock; - - atomic_add_acq_int(&l->lock, RC_INCR); - while (l->lock & WAFLAG) - ; /* Spin */ -} - -static void -def_wlock_acquire(void *lock) -{ - Lock *l = (Lock *)lock; - sigset_t tmp_oldsigmask; - - for ( ; ; ) { - sigprocmask(SIG_BLOCK, &fullsigmask, &tmp_oldsigmask); - if (atomic_cmpset_acq_int(&l->lock, 0, WAFLAG)) - break; - sigprocmask(SIG_SETMASK, &tmp_oldsigmask, NULL); - } - oldsigmask = tmp_oldsigmask; -} - -static void -def_lock_release(void *lock) -{ - Lock *l = (Lock *)lock; - - if ((l->lock & WAFLAG) == 0) - atomic_add_rel_int(&l->lock, -RC_INCR); - else { - atomic_add_rel_int(&l->lock, -WAFLAG); - sigprocmask(SIG_SETMASK, &oldsigmask, NULL); - } -} - -static int -def_thread_set_flag(int mask) -{ - int old_val = thread_flag; - thread_flag |= mask; - return (old_val); -} - -static int -def_thread_clr_flag(int mask) -{ - int old_val = thread_flag; - thread_flag &= ~mask; - return (old_val); -} - -/* - * Public interface exposed to the rest of the dynamic linker. - */ -static struct RtldLockInfo lockinfo; -static struct RtldLockInfo deflockinfo; - -static __inline int -thread_mask_set(int mask) -{ - return lockinfo.thread_set_flag(mask); -} - -static __inline void -thread_mask_clear(int mask) -{ - lockinfo.thread_clr_flag(mask); -} - -#define RTLD_LOCK_CNT 3 -struct rtld_lock { - void *handle; - int mask; -} rtld_locks[RTLD_LOCK_CNT]; - -rtld_lock_t rtld_bind_lock = &rtld_locks[0]; -rtld_lock_t rtld_libc_lock = &rtld_locks[1]; -rtld_lock_t rtld_phdr_lock = &rtld_locks[2]; - -int -rlock_acquire(rtld_lock_t lock) -{ - if (thread_mask_set(lock->mask) & lock->mask) { - dbg("rlock_acquire: recursed"); - return (0); - } - lockinfo.rlock_acquire(lock->handle); - return (1); -} - -int -wlock_acquire(rtld_lock_t lock) -{ - if (thread_mask_set(lock->mask) & lock->mask) { - dbg("wlock_acquire: recursed"); - return (0); - } - lockinfo.wlock_acquire(lock->handle); - return (1); -} - -void -rlock_release(rtld_lock_t lock, int locked) -{ - if (locked == 0) - return; - thread_mask_clear(lock->mask); - lockinfo.lock_release(lock->handle); -} - -void -wlock_release(rtld_lock_t lock, int locked) -{ - if (locked == 0) - return; - thread_mask_clear(lock->mask); - lockinfo.lock_release(lock->handle); -} - -void -lockdflt_init() -{ - int i; - - deflockinfo.rtli_version = RTLI_VERSION; - deflockinfo.lock_create = def_lock_create; - deflockinfo.lock_destroy = def_lock_destroy; - deflockinfo.rlock_acquire = def_rlock_acquire; - deflockinfo.wlock_acquire = def_wlock_acquire; - deflockinfo.lock_release = def_lock_release; - deflockinfo.thread_set_flag = def_thread_set_flag; - deflockinfo.thread_clr_flag = def_thread_clr_flag; - deflockinfo.at_fork = NULL; - - for (i = 0; i < RTLD_LOCK_CNT; i++) { - rtld_locks[i].mask = (1 << i); - rtld_locks[i].handle = NULL; - } - - memcpy(&lockinfo, &deflockinfo, sizeof(lockinfo)); - _rtld_thread_init(NULL); - /* - * Construct a mask to block all signals except traps which might - * conceivably be generated within the dynamic linker itself. - */ - sigfillset(&fullsigmask); - sigdelset(&fullsigmask, SIGILL); - sigdelset(&fullsigmask, SIGTRAP); - sigdelset(&fullsigmask, SIGABRT); - sigdelset(&fullsigmask, SIGEMT); - sigdelset(&fullsigmask, SIGFPE); - sigdelset(&fullsigmask, SIGBUS); - sigdelset(&fullsigmask, SIGSEGV); - sigdelset(&fullsigmask, SIGSYS); -} - -/* - * Callback function to allow threads implementation to - * register their own locking primitives if the default - * one is not suitable. - * The current context should be the only context - * executing at the invocation time. - */ -void -_rtld_thread_init(struct RtldLockInfo *pli) -{ - int flags, i; - void *locks[RTLD_LOCK_CNT]; - - /* disable all locking while this function is running */ - flags = thread_mask_set(~0); - - if (pli == NULL) - pli = &deflockinfo; - - - for (i = 0; i < RTLD_LOCK_CNT; i++) - if ((locks[i] = pli->lock_create()) == NULL) - break; - - if (i < RTLD_LOCK_CNT) { - while (--i >= 0) - pli->lock_destroy(locks[i]); - abort(); - } - - for (i = 0; i < RTLD_LOCK_CNT; i++) { - if (rtld_locks[i].handle == NULL) - continue; - if (flags & rtld_locks[i].mask) - lockinfo.lock_release(rtld_locks[i].handle); - lockinfo.lock_destroy(rtld_locks[i].handle); - } - - for (i = 0; i < RTLD_LOCK_CNT; i++) { - rtld_locks[i].handle = locks[i]; - if (flags & rtld_locks[i].mask) - pli->wlock_acquire(rtld_locks[i].handle); - } - - lockinfo.lock_create = pli->lock_create; - lockinfo.lock_destroy = pli->lock_destroy; - lockinfo.rlock_acquire = pli->rlock_acquire; - lockinfo.wlock_acquire = pli->wlock_acquire; - lockinfo.lock_release = pli->lock_release; - lockinfo.thread_set_flag = pli->thread_set_flag; - lockinfo.thread_clr_flag = pli->thread_clr_flag; - lockinfo.at_fork = pli->at_fork; - - /* restore thread locking state, this time with new locks */ - thread_mask_clear(~0); - thread_mask_set(flags); - dbg("_rtld_thread_init: done"); -} - -void -_rtld_atfork_pre(int *locks) -{ - - locks[2] = wlock_acquire(rtld_phdr_lock); - locks[0] = rlock_acquire(rtld_bind_lock); -} - -void -_rtld_atfork_post(int *locks) -{ - - rlock_release(rtld_bind_lock, locks[0]); - wlock_release(rtld_phdr_lock, locks[2]); -} diff --git a/repos/os/src/lib/ldso/contrib/rtld_lock.h b/repos/os/src/lib/ldso/contrib/rtld_lock.h deleted file mode 100644 index c62967027..000000000 --- a/repos/os/src/lib/ldso/contrib/rtld_lock.h +++ /dev/null @@ -1,73 +0,0 @@ -/*- - * Copyright 2003 Alexander Kabaev. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/rtld_lock.h,v 1.2.20.2.2.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -#ifndef _RTLD_LOCK_H_ -#define _RTLD_LOCK_H_ - -#define RTLI_VERSION 0x01 -#define MAX_RTLD_LOCKS 8 - -struct RtldLockInfo -{ - unsigned int rtli_version; - void *(*lock_create)(void); - void (*lock_destroy)(void *); - void (*rlock_acquire)(void *); - void (*wlock_acquire)(void *); - void (*lock_release)(void *); - int (*thread_set_flag)(int); - int (*thread_clr_flag)(int); - void (*at_fork)(void); -}; - -extern void _rtld_thread_init(struct RtldLockInfo *); -extern void _rtld_atfork_pre(int *); -extern void _rtld_atfork_post(int *); - -#ifdef IN_RTLD - -struct rtld_lock; -typedef struct rtld_lock *rtld_lock_t; - -extern rtld_lock_t rtld_bind_lock; -extern rtld_lock_t rtld_libc_lock; -extern rtld_lock_t rtld_phdr_lock; - -#ifdef __cplusplus -extern "C" { -#endif -int rlock_acquire(rtld_lock_t); -int wlock_acquire(rtld_lock_t); -void rlock_release(rtld_lock_t, int); -void wlock_release(rtld_lock_t, int); -#ifdef __cplusplus -} -#endif - -#endif /* IN_RTLD */ - -#endif diff --git a/repos/os/src/lib/ldso/contrib/rtld_tls.h b/repos/os/src/lib/ldso/contrib/rtld_tls.h deleted file mode 100644 index 7f554bead..000000000 --- a/repos/os/src/lib/ldso/contrib/rtld_tls.h +++ /dev/null @@ -1,69 +0,0 @@ -/*- - * Copyright (c) 2004 Doug Rabson - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/rtld_tls.h,v 1.1.28.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -/* - * Semi-public interface from thread libraries to rtld for managing - * TLS. - */ - -#ifndef _RTLD_TLS_H_ -#define _RTLD_TLS_H_ - -/* - * Allocate a TLS block for a new thread. The memory allocated will - * include 'tcbsize' bytes aligned to a 'tcbalign' boundary (in bytes) - * for the thread library's private purposes. The location of the TCB - * block is returned by this function. For architectures using - * 'Variant I' TLS, the thread local storage follows the TCB, and for - * 'Variant II', the thread local storage precedes it. For - * architectures using the 'Variant II' model (e.g. i386, amd64, - * sparc64), the TCB must begin with two pointer fields which are used - * by rtld for its TLS implementation. For the 'Variant I' model, the - * TCB must begin with a single pointer field for rtld's - * implementation. - * - * If the value of 'oldtls' is non-NULL, the new TLS block will be - * initialised using the values contained in 'oldtls' and 'oldtls' - * will be freed. This is typically used when initialising a thread - * library to migrate from using the initial bootstrap TLS block - * created by rtld to one which contains suitable thread library - * private data. - * - * The value returned from this function is suitable for installing - * directly into the thread pointer register. - */ -extern void *_rtld_allocate_tls(void* oldtls, size_t tcbsize, size_t tcbalign); - -/* - * Free a TLS block allocated using _rtld_allocate_tls(). The tcbsize - * and tcbalign parameters must be the same as those used to allocate - * the block. - */ -extern void _rtld_free_tls(void *tcb, size_t tcbsize, size_t tcbalign); - -#endif diff --git a/repos/os/src/lib/ldso/contrib/xmalloc.c b/repos/os/src/lib/ldso/contrib/xmalloc.c deleted file mode 100644 index 448856bf2..000000000 --- a/repos/os/src/lib/ldso/contrib/xmalloc.c +++ /dev/null @@ -1,59 +0,0 @@ -/*- - * Copyright 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/libexec/rtld-elf/xmalloc.c,v 1.3.30.1 2009/04/15 03:14:26 kensmith Exp $ - */ - -#include -#include -#include -#include - -void *xcalloc(size_t); -void *xmalloc(size_t); -char *xstrdup(const char *); - -void * -xcalloc(size_t size) -{ - return memset(xmalloc(size), 0, size); -} - -void * -xmalloc(size_t size) -{ - void *p = malloc(size); - if (p == NULL) - err(1, "Out of memory"); - return p; -} - -char * -xstrdup(const char *s) -{ - char *p = strdup(s); - if (p == NULL) - err(1, "Out of memory"); - return p; -} diff --git a/repos/os/src/lib/ldso/dl_extensions.h b/repos/os/src/lib/ldso/dl_extensions.h deleted file mode 100644 index 258cc4d4b..000000000 --- a/repos/os/src/lib/ldso/dl_extensions.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * \brief Unoffical dlfnc.h extensions - * \author Sebastian.Sumpf - * \date 2010-07-05 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _DL_EXTENSIONS_ -#define _DL_EXTENSIONS_ - -/* For a given PC, find the .so that it belongs to. - * Returns the base address of the .ARM.exidx section - * for that .so, and the number of 8-byte entries - * in that section (via *pcount). - * Intended to be called by libc's __gnu_Unwind_Find_exidx(). - * - * 'Quoted from Android' - */ - -#ifdef __ARM_EABI__ -unsigned long dl_unwind_find_exidx(unsigned long pc, int *pcount); -#endif - -#endif /* _DL_EXTENSIONS_ */ diff --git a/repos/os/src/lib/ldso/environ.cc b/repos/os/src/lib/ldso/environ.cc deleted file mode 100644 index bf811ed29..000000000 --- a/repos/os/src/lib/ldso/environ.cc +++ /dev/null @@ -1,22 +0,0 @@ -/* - * \brief Dummy 'lx_environ' used on on-Linux platforms - * \author Norman Feske - * \date 2011-08-23 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -/* - * The 'lx_environ' pointer is supposed to be initialized by the startup code - * on Linux. It is specially treated in 'main.c'. On platforms w/o 'lx_environ', - * we resolve the symbol by the weak symbol defined here. On Linux, the - * weak symbol is overridden by the version in the startup library. - * - * XXX: We should better remove the Linux-specific code from ldso's 'main.c'. - */ -__attribute__((weak)) char **lx_environ = (char **)0; diff --git a/repos/os/src/lib/ldso/err.cc b/repos/os/src/lib/ldso/err.cc deleted file mode 100644 index ccc1da28a..000000000 --- a/repos/os/src/lib/ldso/err.cc +++ /dev/null @@ -1,29 +0,0 @@ -/* - * \brief Error message handling - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ -#include -#include -#include - - -extern "C" void errx(int eval, const char *fmt, ...) -{ - using namespace Genode; - va_list args; - - va_start(args, fmt); - vprintf(fmt, args); - va_end(args); - printf("\n"); - env()->parent()->exit(eval); - while(1) ; -} diff --git a/repos/os/src/lib/ldso/file.cc b/repos/os/src/lib/ldso/file.cc deleted file mode 100644 index 68b8d19a0..000000000 --- a/repos/os/src/lib/ldso/file.cc +++ /dev/null @@ -1,415 +0,0 @@ -/* - * \brief libc file handling function emulation (open/read/write/mmap) - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "file.h" - -extern int debug; - -namespace Genode { - - /** - * Managed dataspace for ELF files (singelton) - */ - class Rm_area : public Rm_connection - { - private: - - /* size of dataspace */ - enum { RESERVATION = 160 * 1024 * 1024 }; - - addr_t _base; /* base address of dataspace */ - Allocator_avl _range; /* VM range allocator */ - - protected: - - Rm_area(addr_t base) - : Rm_connection(0, RESERVATION), _range(env()->heap()) - { - on_destruction(KEEP_OPEN); - - _base = (addr_t) env()->rm_session()->attach_at(dataspace(), base); - _range.add_range(base, RESERVATION); - } - - public: - - static Rm_area *r(addr_t base = 0) - { - /* - * The capabilities in this class become invalid when doing a - * fork in the noux environment. Hence avoid destruction of - * the singleton object as the destructor would try to access - * the capabilities also in the forked process. - */ - static bool constructed = 0; - static char placeholder[sizeof(Rm_area)]; - if (!constructed) { - construct_at(placeholder, base); - constructed = 1; - } - return reinterpret_cast(placeholder); - } - - /** - * Reserve VM region of 'size' at 'vaddr'. Allocate any free region if - * 'vaddr' is zero - */ - addr_t alloc_region(size_t size, addr_t vaddr = 0) - { - addr_t addr = vaddr; - - if (addr && (_range.alloc_addr(size, addr).is_error())) - throw Region_conflict(); - else if (!addr && _range.alloc_aligned(size, (void **)&addr, 12).is_error()) - throw Region_conflict(); - - return addr; - } - - void free_region(addr_t vaddr) { _range.free((void *)vaddr); } - - /** - * Overwritten from 'Rm_connection' - */ - Local_addr attach_at(Dataspace_capability ds, addr_t local_addr, - size_t size = 0, off_t offset = 0) { - return Rm_connection::attach_at(ds, local_addr - _base, size, offset); } - - /** - * Overwritten from 'Rm_connection' - */ - Local_addr attach_executable(Dataspace_capability ds, addr_t local_addr, - size_t size = 0, off_t offset = 0) { - return Rm_connection::attach_executable(ds, local_addr - _base, size, offset); } - - void detach(Local_addr local_addr) { - Rm_connection::detach((addr_t)local_addr - _base); } - }; - - - class Fd_handle : public List::Element - { - private: - - addr_t _phdr; - addr_t _vaddr; /* image start */ - addr_t _daddr; /* data start */ - Rom_dataspace_capability _ds_rom; /* image ds */ - Ram_dataspace_capability _ds_ram; /* data ds */ - int _fd; /* file handle */ - Session_capability _rom_cap; - - public: - - Fd_handle(int fd, Rom_dataspace_capability ds_rom, Session_capability rom_cap) - : _vaddr(~0UL), _ds_rom(ds_rom), _fd(fd), _rom_cap(rom_cap) - { - _phdr = (addr_t)env()->rm_session()->attach(_ds_rom, PAGE_SIZE); - } - - addr_t vaddr() { return _vaddr; } - void vaddr(addr_t vaddr) { _vaddr = vaddr; } - Rom_dataspace_capability dataspace() { return _ds_rom; } - addr_t phdr() { return _phdr; } - - void setup_data(addr_t vaddr, addr_t vlimit, addr_t flimit, off_t offset) - { - /* allocate data segment */ - _ds_ram = env()->ram_session()->alloc(vlimit - vaddr); - Rm_area::r()->attach_at(_ds_ram, vaddr); - - /* map rom data segment */ - void *rom_data = env()->rm_session()->attach(_ds_rom, 0, offset); - - /* copy data */ - memcpy((void *)vaddr, rom_data, flimit - vaddr); - env()->rm_session()->detach(rom_data); - - /* set parent cap (arch.lib.a) */ - set_parent_cap_arch((void *)vaddr); - - _daddr = vaddr; - } - - void setup_text(addr_t vaddr, size_t size, off_t offset) - { - _vaddr = vaddr; - Rm_area::r()->attach_executable(_ds_rom, vaddr, size, offset); - } - - addr_t alloc_region(addr_t vaddr, addr_t vlimit) - { - Rm_area *a = Rm_area::r(vaddr); - return a->alloc_region(vlimit - vaddr, vaddr); - } - - static List *file_list() - { - static List _file_list; - return &_file_list; - } - - static Fd_handle *find_handle(int fd, addr_t vaddr = 0) - { - Fd_handle *h = file_list()->first(); - - while (h) { - - if (vaddr && vaddr == h->_vaddr) - return h; - if (h->_fd == fd) - return h; - h = h->next(); - } - - return 0; - } - - static void free(void *addr) - { - addr_t vaddr = (addr_t) addr; - - Fd_handle *h = file_list()->first(); - - while (h) { - - if (h->_vaddr != vaddr) { - h = h->next(); - continue; - } - - destroy(env()->heap(), h); - return; - } - } - - ~Fd_handle() - { - file_list()->remove(this); - - if (_vaddr != ~0UL) { - Rm_area::r()->detach(_vaddr); - Rm_area::r()->detach(_daddr); - Rm_area::r()->free_region(_vaddr); - env()->ram_session()->free(_ds_ram); - env()->rm_session()->detach(_phdr); - } - - if (_rom_cap.valid()) - env()->parent()->close(_rom_cap); - } - }; -} - - -extern "C" int open(const char *pathname, int flags) -{ - using namespace Genode; - static int fd = -1; - static int i = 0; - i++; - - /* skip directory part from pathname, leaving only the plain filename */ - const char *filename = pathname; - for (; *pathname; pathname++) - if (*pathname == '/') - filename = pathname + 1; - - try { - /* open the file dataspace and attach it */ - Rom_connection rom(filename); - rom.on_destruction(Rom_connection::KEEP_OPEN); - - Fd_handle::file_list()->insert(new(env()->heap()) - Fd_handle(++fd, rom.dataspace(), rom.cap())); - - Fd_handle *h; - if (!(h = Fd_handle::find_handle(fd))) { - PERR("Could not open %s\n", filename); - return -1; - } - } catch (...) { - PERR("Rom connection failed for %s", filename); - return -1; - } - - return fd; -} - - -extern "C" void *file_phdr(const char *pathname, void *vaddr) -{ - using namespace Genode; - - Fd_handle *h = 0; - if (!(h = Fd_handle::find_handle(-1, (addr_t)vaddr))) { - int fd = open(pathname, 0); - h = Fd_handle::find_handle(fd); - h->vaddr((addr_t)vaddr); - } - - return (void *)h->phdr(); -} - - -extern "C" int find_binary_name(int fd, char *buf, size_t buf_size) -{ - using namespace Genode; - - Fd_handle *h; - if (!(h = Fd_handle::find_handle(fd))) { - PERR("handle not found\n"); - return -1; - } - - return binary_name(h->dataspace(), buf, buf_size); -} - - -extern "C" ssize_t read(int fd, void *buf, size_t count) -{ - using namespace Genode; - - Fd_handle *h; - - if (!(h = Fd_handle::find_handle(fd))) { - PERR("handle not found\n"); - return -1; - } - - try { - void *base = env()->rm_session()->attach(h->dataspace(), count); - memcpy(buf, base, count); - env()->rm_session()->detach(base); - } - catch (...) { - return -1; - } - - return count; -} - - -extern "C" ssize_t write(int fd, const void *buf, size_t count) -{ - Genode::printf("%p", buf); - return count; -} - - -extern "C" int munmap(void *addr, size_t /* length */) -{ - using namespace Genode; - Fd_handle::free(addr); - return 0; -} - - -extern "C" void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) -{ - using namespace Genode; - - if(!(flags & MAP_ANON)) { - PERR("No MAP_ANON"); - return MAP_FAILED; - } - - /* called during ldso relocation */ - if (flags & MAP_LDSO) { - enum { MEM_SIZE = 128 * 1024 }; - static char _mem[MEM_SIZE]; - - /* generate fault on allocation */ - if (length > MEM_SIZE) { - int *fault = (int *)0xa110ce88; - *fault = 1; - } - return _mem; - } - /* memory allocation */ - else { - void *base; - - try { - Ram_dataspace_capability ds_cap = env()->ram_session()->alloc(round_page(length)); - base = env()->rm_session()->attach(ds_cap, length, 0, - (addr) ? true : false, (addr_t)addr); - } - catch(...) { - PERR("Anonmymous mmap failed\n"); - return MAP_FAILED; - } - - if (debug) - PDBG("base %p", base); - - return base; - } - - return MAP_FAILED; -} - - -extern "C" void *genode_map(int fd, Elf_Phdr **segs) -{ - using namespace Genode; - - if (1 > 1) { - PERR("More than two segments in ELF"); - return MAP_FAILED; - } - - Fd_handle *h; - if (!(h = Fd_handle::find_handle(fd))) { - PERR("handle not found\n"); - return MAP_FAILED; - } - - addr_t base_vaddr = trunc_page(segs[0]->p_vaddr); - addr_t base_offset = trunc_page(segs[0]->p_offset); - addr_t base_msize = round_page(segs[1]->p_vaddr - base_vaddr); - addr_t base_vlimit = round_page(segs[1]->p_vaddr + segs[1]->p_memsz); - /* is this a fixed address */ - bool fixed = base_vaddr ? true : false; - - try { - base_vaddr = h->alloc_region(base_vaddr, base_vlimit); - } catch (...) { - PERR("Region allocation failed: %lx-%lx", base_vaddr, base_vlimit); - return MAP_FAILED; - } - - /* map text segment */ - h->setup_text(base_vaddr, base_msize, base_offset); - - addr_t offset = fixed ? 0 : base_vaddr; - base_vlimit += offset; - addr_t base_flimit = offset + segs[1]->p_vaddr + segs[1]->p_filesz; - base_vaddr = offset + trunc_page(segs[1]->p_vaddr); - base_offset = trunc_page(segs[1]->p_offset); - - /* copy data segment */ - h->setup_data(base_vaddr, base_vlimit, base_flimit, base_offset); - - return (void *)h->vaddr(); -} - diff --git a/repos/os/src/lib/ldso/file.h b/repos/os/src/lib/ldso/file.h deleted file mode 100644 index 7006e5c67..000000000 --- a/repos/os/src/lib/ldso/file.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * \brief Meta-information for Genode on Linux - * \author Sebastian Sumpf - * \date 2010-01-04 - */ - -/* - * Copyright (C) 2010-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _FILE_H_ -#define _FILE_H_ - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -int find_binary_name(int fd, char *buf, size_t buf_size); - -/** - * Map file into address space - * - * \param fd File handle - * \param segs Elf segment descriptors (must currently be two) - * - * \return Address on success; MAP_FAILED otherwise - */ -void *genode_map(int fd, Elf_Phdr **segs); - -#ifdef __cplusplus -} -#endif - -#endif /* _FILE_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/dlfcn.h b/repos/os/src/lib/ldso/include/libc/dlfcn.h deleted file mode 100644 index 9ac91492f..000000000 --- a/repos/os/src/lib/ldso/include/libc/dlfcn.h +++ /dev/null @@ -1,139 +0,0 @@ -/*- - * Copyright (c) 1994 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/include/dlfcn.h,v 1.20 2005/12/18 19:43:31 kan Exp $ - */ - -#ifndef _DLFCN_H_ -#define _DLFCN_H_ - -#include - -/* - * Modes and flags for dlopen(). - */ -#define RTLD_LAZY 1 /* Bind function calls lazily. */ -#define RTLD_NOW 2 /* Bind function calls immediately. */ -#define RTLD_MODEMASK 0x3 -#define RTLD_GLOBAL 0x100 /* Make symbols globally available. */ -#define RTLD_LOCAL 0 /* Opposite of RTLD_GLOBAL, and the default. */ -#define RTLD_TRACE 0x200 /* Trace loaded objects and exit. */ - -/* - * Request arguments for dlinfo(). - */ -#define RTLD_DI_LINKMAP 2 /* Obtain link map. */ -#define RTLD_DI_SERINFO 4 /* Obtain search path info. */ -#define RTLD_DI_SERINFOSIZE 5 /* ... query for required space. */ -#define RTLD_DI_ORIGIN 6 /* Obtain object origin */ -#define RTLD_DI_MAX RTLD_DI_ORIGIN - -/* - * Special handle arguments for dlsym()/dlinfo(). - */ -#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ -#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ -#define RTLD_SELF ((void *) -3) /* Search the caller itself. */ - -#if __BSD_VISIBLE - -#ifndef _SIZE_T_DECLARED -typedef __size_t size_t; -#define _SIZE_T_DECLARED -#endif - -/* - * Structure filled in by dladdr(). - */ -typedef struct dl_info { - const char *dli_fname; /* Pathname of shared object. */ - void *dli_fbase; /* Base address of shared object. */ - const char *dli_sname; /* Name of nearest symbol. */ - void *dli_saddr; /* Address of nearest symbol. */ -} Dl_info; - -/*- - * The actual type declared by this typedef is immaterial, provided that - * it is a function pointer. Its purpose is to provide a return type for - * dlfunc() which can be cast to a function pointer type without depending - * on behavior undefined by the C standard, which might trigger a compiler - * diagnostic. We intentionally declare a unique type signature to force - * a diagnostic should the application not cast the return value of dlfunc() - * appropriately. - */ -struct __dlfunc_arg { - int __dlfunc_dummy; -}; - -typedef void (*dlfunc_t)(struct __dlfunc_arg); - -/* - * Structures, returned by the RTLD_DI_SERINFO dlinfo() request. - */ -typedef struct dl_serpath { - char * dls_name; /* single search path entry */ - unsigned int dls_flags; /* path information */ -} Dl_serpath; - -typedef struct dl_serinfo { - size_t dls_size; /* total buffer size */ - unsigned int dls_cnt; /* number of path entries */ - Dl_serpath dls_serpath[1]; /* there may be more than one */ -} Dl_serinfo; - -#endif /* __BSD_VISIBLE */ - -__BEGIN_DECLS -/* XSI functions first. */ -int dlclose(void *); -const char * - dlerror(void); -void *dlopen(const char *, int); -void *dlsym(void * __restrict, const char * __restrict); - -#if __BSD_VISIBLE -int dladdr(const void * __restrict, Dl_info * __restrict); -dlfunc_t dlfunc(void * __restrict, const char * __restrict); -int dlinfo(void * __restrict, int, void * __restrict); -void dllockinit(void *_context, - void *(*_lock_create)(void *_context), - void (*_rlock_acquire)(void *_lock), - void (*_wlock_acquire)(void *_lock), - void (*_lock_release)(void *_lock), - void (*_lock_destroy)(void *_lock), - void (*_context_destroy)(void *_context)); -void *dlvsym(void * __restrict, const char * __restrict, - const char * __restrict); -#endif /* __BSD_VISIBLE */ -__END_DECLS - -#endif /* !_DLFCN_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/elf-hints.h b/repos/os/src/lib/ldso/include/libc/elf-hints.h deleted file mode 100644 index d572a4f14..000000000 --- a/repos/os/src/lib/ldso/include/libc/elf-hints.h +++ /dev/null @@ -1,50 +0,0 @@ -/*- - * Copyright (c) 1997 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/include/elf-hints.h,v 1.4 2001/05/02 23:56:17 obrien Exp $ - */ - -#ifndef _ELF_HINTS_H_ -#define _ELF_HINTS_H_ - -/* - * Hints file produced by ldconfig. - */ -struct elfhints_hdr { - u_int32_t magic; /* Magic number */ - u_int32_t version; /* File version (1) */ - u_int32_t strtab; /* Offset of string table in file */ - u_int32_t strsize; /* Size of string table */ - u_int32_t dirlist; /* Offset of directory list in - string table */ - u_int32_t dirlistlen; /* strlen(dirlist) */ - u_int32_t spare[26]; /* Room for expansion */ -}; - -#define ELFHINTS_MAGIC 0x746e6845 - -#define _PATH_ELF_HINTS "/var/run/ld-elf.so.hints" - -#endif /* !_ELF_HINTS_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/libc-amd64/machine/elf.h b/repos/os/src/lib/ldso/include/libc/libc-amd64/machine/elf.h deleted file mode 100644 index ce89edf42..000000000 --- a/repos/os/src/lib/ldso/include/libc/libc-amd64/machine/elf.h +++ /dev/null @@ -1,123 +0,0 @@ -/*- - * Copyright (c) 1996-1997 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/amd64/include/elf.h,v 1.19 2006/10/04 21:37:09 jb Exp $ - */ - -#ifndef _MACHINE_ELF_H_ -#define _MACHINE_ELF_H_ 1 - -/* - * ELF definitions for the AMD64 architecture. - */ - - -#ifndef __ELF_WORD_SIZE -#define __ELF_WORD_SIZE 64 /* Used by */ -#endif -#include /* Definitions common to all 32 bit architectures. */ -#include /* Definitions common to all 64 bit architectures. */ -#include - -#define ELF_ARCH EM_X86_64 - -#define ELF_MACHINE_OK(x) ((x) == EM_X86_64) - -/* - * Auxiliary vector entries for passing information to the interpreter. - * - * The i386 supplement to the SVR4 ABI specification names this "auxv_t", - * but POSIX lays claim to all symbols ending with "_t". - */ -typedef struct { /* Auxiliary vector entry on initial stack */ - int a_type; /* Entry type. */ - union { - int a_val; /* Integer value. */ - } a_un; -} Elf32_Auxinfo; - - -typedef struct { /* Auxiliary vector entry on initial stack */ - long a_type; /* Entry type. */ - union { - long a_val; /* Integer value. */ - void *a_ptr; /* Address. */ - void (*a_fcn)(void); /* Function pointer (not used). */ - } a_un; -} Elf64_Auxinfo; - -__ElfType(Auxinfo); - -/* Values for a_type. */ -#define AT_NULL 0 /* Terminates the vector. */ -#define AT_IGNORE 1 /* Ignored entry. */ -#define AT_EXECFD 2 /* File descriptor of program to load. */ -#define AT_PHDR 3 /* Program header of program already loaded. */ -#define AT_PHENT 4 /* Size of each program header entry. */ -#define AT_PHNUM 5 /* Number of program header entries. */ -#define AT_PAGESZ 6 /* Page size in bytes. */ -#define AT_BASE 7 /* Interpreter's base address. */ -#define AT_FLAGS 8 /* Flags (unused for i386). */ -#define AT_ENTRY 9 /* Where interpreter should transfer control. */ - -/* - * The following non-standard values are used for passing information - * from John Polstra's testbed program to the dynamic linker. These - * are expected to go away soon. - * - * Unfortunately, these overlap the Linux non-standard values, so they - * must not be used in the same context. - */ -#define AT_BRK 10 /* Starting point for sbrk and brk. */ -#define AT_DEBUG 11 /* Debugging level. */ - -/* - * The following non-standard values are used in Linux ELF binaries. - */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ - -#define AT_COUNT 15 /* Count of defined aux entry types. */ - -/* - * Relocation types. - */ - -#define R_X86_64_COUNT 24 /* Count of defined relocation types. */ - -/* Define "machine" characteristics */ -#if __ELF_WORD_SIZE == 32 -#define ELF_TARG_CLASS ELFCLASS32 -#else -#define ELF_TARG_CLASS ELFCLASS64 -#endif -#define ELF_TARG_DATA ELFDATA2LSB -#define ELF_TARG_MACH EM_X86_64 -#define ELF_TARG_VER 1 - -#endif /* !_MACHINE_ELF_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/libc-arm/machine/asm.h b/repos/os/src/lib/ldso/include/libc/libc-arm/machine/asm.h deleted file mode 100644 index eb3a47d15..000000000 --- a/repos/os/src/lib/ldso/include/libc/libc-arm/machine/asm.h +++ /dev/null @@ -1,174 +0,0 @@ -/* $NetBSD: asm.h,v 1.5 2003/08/07 16:26:53 agc Exp $ */ - -/*- - * Copyright (c) 1990 The Regents of the University of California. - * All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * from: @(#)asm.h 5.5 (Berkeley) 5/7/91 - * - * $FreeBSD: src/sys/arm/include/asm.h,v 1.7 2007/10/13 12:04:10 cognet Exp $ - */ - -#ifndef _MACHINE_ASM_H_ -#define _MACHINE_ASM_H_ -#include - -#ifdef __ELF__ -# define _C_LABEL(x) x -#else -# ifdef __STDC__ -# define _C_LABEL(x) _ ## x -# else -# define _C_LABEL(x) _/**/x -# endif -#endif -#define _ASM_LABEL(x) x - -#ifndef _JB_MAGIC__SETJMP -#define _JB_MAGIC__SETJMP 0x4278f500 -#define _JB_MAGIC_SETJMP 0x4278f501 -#endif - -#define I32_bit (1 << 7) /* IRQ disable */ -#define F32_bit (1 << 6) /* FIQ disable */ - -#define CPU_CONTROL_32BP_ENABLE 0x00000010 /* P: 32-bit exception handlers */ -#define CPU_CONTROL_32BD_ENABLE 0x00000020 /* D: 32-bit addressing */ - -#ifndef _ALIGN_TEXT -# define _ALIGN_TEXT .align 0 -#endif - -/* - * gas/arm uses @ as a single comment character and thus cannot be used here - * Instead it recognised the # instead of an @ symbols in .type directives - * We define a couple of macros so that assembly code will not be dependant - * on one or the other. - */ -#define _ASM_TYPE_FUNCTION #function -#define _ASM_TYPE_OBJECT #object -#define GLOBAL(X) .globl x -#define _ENTRY(x) \ - .text; _ALIGN_TEXT; .globl x; .type x,_ASM_TYPE_FUNCTION; x: - -#ifdef GPROF -# define _PROF_PROLOGUE \ - mov ip, lr; bl __mcount -#else -# define _PROF_PROLOGUE -#endif - -#define ENTRY(y) _ENTRY(_C_LABEL(y)); _PROF_PROLOGUE -#define ENTRY_NP(y) _ENTRY(_C_LABEL(y)) -#define ASENTRY(y) _ENTRY(_ASM_LABEL(y)); _PROF_PROLOGUE -#define ASENTRY_NP(y) _ENTRY(_ASM_LABEL(y)) - -#define ASMSTR .asciz - -#if defined(__ELF__) && defined(PIC) -#ifdef __STDC__ -#define PIC_SYM(x,y) x ## ( ## y ## ) -#else -#define PIC_SYM(x,y) x/**/(/**/y/**/) -#endif -#else -#define PIC_SYM(x,y) x -#endif - -#undef __FBSDID -#if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) .ident s -#else -#define __FBSDID(s) /* nothing */ -#endif - - -#ifdef __ELF__ -#define WEAK_ALIAS(alias,sym) \ - .weak alias; \ - alias = sym -#endif - -#ifdef __STDC__ -#define WARN_REFERENCES(sym,msg) \ - .stabs msg ## ,30,0,0,0 ; \ - .stabs __STRING(_C_LABEL(sym)) ## ,1,0,0,0 -#elif defined(__ELF__) -#define WARN_REFERENCES(sym,msg) \ - .stabs msg,30,0,0,0 ; \ - .stabs __STRING(sym),1,0,0,0 -#else -#define WARN_REFERENCES(sym,msg) \ - .stabs msg,30,0,0,0 ; \ - .stabs __STRING(_/**/sym),1,0,0,0 -#endif /* __STDC__ */ - - -#if defined (__ARM_ARCH_6__) || defined (__ARM_ARCH_6J__) -#define _ARM_ARCH_6 -#endif - -#if defined (_ARM_ARCH_6) || defined (__ARM_ARCH_5__) || \ - defined (__ARM_ARCH_5T__) || defined (__ARM_ARCH_5TE__) || \ - defined (__ARM_ARCH_5TEJ__) || defined (__ARM_ARCH_5E__) -#define _ARM_ARCH_5 -#endif - -#if defined (_ARM_ARCH_6) || defined(__ARM_ARCH_5TE__) || \ - defined(__ARM_ARCH_5TEJ__) || defined(__ARM_ARCH_5E__) -#define _ARM_ARCH_5E -#endif - -#if defined (_ARM_ARCH_5) || defined (__ARM_ARCH_4T__) -#define _ARM_ARCH_4T -#endif - - -#if defined (_ARM_ARCH_4T) -# define RET bx lr -# define RETeq bxeq lr -# define RETne bxne lr -# ifdef __STDC__ -# define RETc(c) bx##c lr -# else -# define RETc(c) bx/**/c lr -# endif -#else -# define RET mov pc, lr -# define RETeq moveq pc, lr -# define RETne movne pc, lr -# ifdef __STDC__ -# define RETc(c) mov##c pc, lr -# else -# define RETc(c) mov/**/c pc, lr -# endif -#endif - -#endif /* !_MACHINE_ASM_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/libc-arm/machine/elf.h b/repos/os/src/lib/ldso/include/libc/libc-arm/machine/elf.h deleted file mode 100644 index bdd1c016e..000000000 --- a/repos/os/src/lib/ldso/include/libc/libc-arm/machine/elf.h +++ /dev/null @@ -1,103 +0,0 @@ -/*- - * Copyright (c) 2001 David E. O'Brien - * Copyright (c) 1996-1997 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/arm/include/elf.h,v 1.11 2009/10/10 15:31:24 kib Exp $ - */ - -#ifndef _MACHINE_ELF_H_ -#define _MACHINE_ELF_H_ 1 - -/* - * EABI ELF definitions for the StrongARM architecture. - * See "ARM ELF", document no. `SWS ESPC 0003 A-08' for details. - */ - -#include /* Definitions common to all 32 bit architectures. */ - -#define __ELF_WORD_SIZE 32 /* Used by */ -#include - -typedef struct { /* Auxiliary vector entry on initial stack */ - int a_type; /* Entry type. */ - union { - long a_val; /* Integer value. */ - void *a_ptr; /* Address. */ - void (*a_fcn)(void); /* Function pointer (not used). */ - } a_un; -} Elf32_Auxinfo; - -__ElfType(Auxinfo); - -#define ELF_ARCH EM_ARM - -#define ELF_MACHINE_OK(x) ((x) == EM_ARM) - -/* - * Relocation types. - */ - -/* Values for a_type. */ -#define AT_NULL 0 /* Terminates the vector. */ -#define AT_IGNORE 1 /* Ignored entry. */ -#define AT_EXECFD 2 /* File descriptor of program to load. */ -#define AT_PHDR 3 /* Program header of program already loaded. */ -#define AT_PHENT 4 /* Size of each program header entry. */ -#define AT_PHNUM 5 /* Number of program header entries. */ -#define AT_PAGESZ 6 /* Page size in bytes. */ -#define AT_BASE 7 /* Interpreter's base address. */ -#define AT_FLAGS 8 /* Flags (unused). */ -#define AT_ENTRY 9 /* Where interpreter should transfer control. */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ -#define AT_EXECPATH 15 /* Path to the executable. */ - -#define AT_COUNT 16 /* Count of defined aux entry types. */ - -#define R_ARM_COUNT 33 /* Count of defined relocation types. */ - - -/* Define "machine" characteristics */ -#define ELF_TARG_CLASS ELFCLASS32 -#ifdef __ARMEB__ -#define ELF_TARG_DATA ELFDATA2MSB -#else -#define ELF_TARG_DATA ELFDATA2LSB -#endif -#define ELF_TARG_MACH EM_ARM -#define ELF_TARG_VER 1 - -/* - * Magic number for the elf trampoline, chosen wisely to be an immediate - * value. - */ -#define MAGIC_TRAMP_NUMBER 0x5c000003 - -#define ET_DYN_LOAD_ADDR 0x12000 - -#endif /* !_MACHINE_ELF_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/libc-i386/machine/elf.h b/repos/os/src/lib/ldso/include/libc/libc-i386/machine/elf.h deleted file mode 100644 index 450847c14..000000000 --- a/repos/os/src/lib/ldso/include/libc/libc-i386/machine/elf.h +++ /dev/null @@ -1,122 +0,0 @@ -/*- - * Copyright (c) 1996-1997 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/i386/include/elf.h,v 1.17 2006/10/04 21:37:09 jb Exp $ - */ - -#ifndef _MACHINE_ELF_H_ -#define _MACHINE_ELF_H_ 1 - -/* - * ELF definitions for the i386 architecture. - */ - -#include /* Definitions common to all 32 bit architectures. */ -#if defined(__ELF_WORD_SIZE) && __ELF_WORD_SIZE == 64 -#include /* Definitions common to all 64 bit architectures. */ -#endif - -#ifndef __ELF_WORD_SIZE -#define __ELF_WORD_SIZE 32 /* Used by */ -#endif - -#include - -#define ELF_ARCH EM_386 - -#define ELF_MACHINE_OK(x) ((x) == EM_386 || (x) == EM_486) - -/* - * Auxiliary vector entries for passing information to the interpreter. - * - * The i386 supplement to the SVR4 ABI specification names this "auxv_t", - * but POSIX lays claim to all symbols ending with "_t". - */ - -typedef struct { /* Auxiliary vector entry on initial stack */ - int a_type; /* Entry type. */ - union { - long a_val; /* Integer value. */ - void *a_ptr; /* Address. */ - void (*a_fcn)(void); /* Function pointer (not used). */ - } a_un; -} Elf32_Auxinfo; - -#if __ELF_WORD_SIZE == 64 -/* Fake for amd64 loader support */ -typedef struct { - int fake; -} Elf64_Auxinfo; -#endif - -__ElfType(Auxinfo); - -/* Values for a_type. */ -#define AT_NULL 0 /* Terminates the vector. */ -#define AT_IGNORE 1 /* Ignored entry. */ -#define AT_EXECFD 2 /* File descriptor of program to load. */ -#define AT_PHDR 3 /* Program header of program already loaded. */ -#define AT_PHENT 4 /* Size of each program header entry. */ -#define AT_PHNUM 5 /* Number of program header entries. */ -#define AT_PAGESZ 6 /* Page size in bytes. */ -#define AT_BASE 7 /* Interpreter's base address. */ -#define AT_FLAGS 8 /* Flags (unused for i386). */ -#define AT_ENTRY 9 /* Where interpreter should transfer control. */ - -/* - * The following non-standard values are used for passing information - * from John Polstra's testbed program to the dynamic linker. These - * are expected to go away soon. - * - * Unfortunately, these overlap the Linux non-standard values, so they - * must not be used in the same context. - */ -#define AT_BRK 10 /* Starting point for sbrk and brk. */ -#define AT_DEBUG 11 /* Debugging level. */ - -/* - * The following non-standard values are used in Linux ELF binaries. - */ -#define AT_NOTELF 10 /* Program is not ELF ?? */ -#define AT_UID 11 /* Real uid. */ -#define AT_EUID 12 /* Effective uid. */ -#define AT_GID 13 /* Real gid. */ -#define AT_EGID 14 /* Effective gid. */ - -#define AT_COUNT 15 /* Count of defined aux entry types. */ - -/* - * Relocation types. - */ - -#define R_386_COUNT 38 /* Count of defined relocation types. */ - -/* Define "machine" characteristics */ -#define ELF_TARG_CLASS ELFCLASS32 -#define ELF_TARG_DATA ELFDATA2LSB -#define ELF_TARG_MACH EM_386 -#define ELF_TARG_VER 1 - -#endif /* !_MACHINE_ELF_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/sys/cdefs.h b/repos/os/src/lib/ldso/include/libc/sys/cdefs.h deleted file mode 100644 index 0324789c4..000000000 --- a/repos/os/src/lib/ldso/include/libc/sys/cdefs.h +++ /dev/null @@ -1,564 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * This code is derived from software contributed to Berkeley by - * Berkeley Software Design, Inc. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)cdefs.h 8.8 (Berkeley) 1/9/95 - * $FreeBSD: src/sys/sys/cdefs.h,v 1.96 2008/10/21 16:46:50 rdivacky Exp $ - */ - -#ifndef _SYS_CDEFS_H_ -#define _SYS_CDEFS_H_ - -#if defined(__cplusplus) -#define __BEGIN_DECLS extern "C" { -#define __END_DECLS } -#else -#define __BEGIN_DECLS -#define __END_DECLS -#endif - -/* - * This code has been put in place to help reduce the addition of - * compiler specific defines in FreeBSD code. It helps to aid in - * having a compiler-agnostic source tree. - */ - -#if defined(__GNUC__) || defined(__INTEL_COMPILER) - -#if __GNUC__ >= 3 || defined(__INTEL_COMPILER) -#define __GNUCLIKE_ASM 3 -#define __GNUCLIKE_MATH_BUILTIN_CONSTANTS -#else -#define __GNUCLIKE_ASM 2 -#endif -#define __GNUCLIKE___TYPEOF 1 -#define __GNUCLIKE___OFFSETOF 1 -#define __GNUCLIKE___SECTION 1 - -#define __GNUCLIKE_ATTRIBUTE_MODE_DI 1 - -#ifndef __INTEL_COMPILER -# define __GNUCLIKE_CTOR_SECTION_HANDLING 1 -#endif - -#define __GNUCLIKE_BUILTIN_CONSTANT_P 1 -# if defined(__INTEL_COMPILER) && defined(__cplusplus) \ - && __INTEL_COMPILER < 800 -# undef __GNUCLIKE_BUILTIN_CONSTANT_P -# endif - -#if (__GNUC_MINOR__ > 95 || __GNUC__ >= 3) && !defined(__INTEL_COMPILER) -# define __GNUCLIKE_BUILTIN_VARARGS 1 -# define __GNUCLIKE_BUILTIN_STDARG 1 -# define __GNUCLIKE_BUILTIN_VAALIST 1 -#endif - -#if defined(__GNUC__) -# define __GNUC_VA_LIST_COMPATIBILITY 1 -#endif - -#ifndef __INTEL_COMPILER -# define __GNUCLIKE_BUILTIN_NEXT_ARG 1 -# define __GNUCLIKE_MATH_BUILTIN_RELOPS -#endif - -#define __GNUCLIKE_BUILTIN_MEMCPY 1 - -/* XXX: if __GNUC__ >= 2: not tested everywhere originally, where replaced */ -#define __CC_SUPPORTS_INLINE 1 -#define __CC_SUPPORTS___INLINE 1 -#define __CC_SUPPORTS___INLINE__ 1 - -#define __CC_SUPPORTS___FUNC__ 1 -#define __CC_SUPPORTS_WARNING 1 - -#define __CC_SUPPORTS_VARADIC_XXX 1 /* see varargs.h */ - -#define __CC_SUPPORTS_DYNAMIC_ARRAY_INIT 1 - -#endif /* __GNUC__ || __INTEL_COMPILER */ - -/* - * Macro to test if we're using a specific version of gcc or later. - */ -#if defined(__GNUC__) && !defined(__INTEL_COMPILER) -#define __GNUC_PREREQ__(ma, mi) \ - (__GNUC__ > (ma) || __GNUC__ == (ma) && __GNUC_MINOR__ >= (mi)) -#else -#define __GNUC_PREREQ__(ma, mi) 0 -#endif - -/* - * The __CONCAT macro is used to concatenate parts of symbol names, e.g. - * with "#define OLD(foo) __CONCAT(old,foo)", OLD(foo) produces oldfoo. - * The __CONCAT macro is a bit tricky to use if it must work in non-ANSI - * mode -- there must be no spaces between its arguments, and for nested - * __CONCAT's, all the __CONCAT's must be at the left. __CONCAT can also - * concatenate double-quoted strings produced by the __STRING macro, but - * this only works with ANSI C. - * - * __XSTRING is like __STRING, but it expands any macros in its argument - * first. It is only available with ANSI C. - */ -#if defined(__STDC__) || defined(__cplusplus) -#define __P(protos) protos /* full-blown ANSI C */ -#define __CONCAT1(x,y) x ## y -#define __CONCAT(x,y) __CONCAT1(x,y) -#define __STRING(x) #x /* stringify without expanding x */ -#define __XSTRING(x) __STRING(x) /* expand x, then stringify */ - -#define __const const /* define reserved names to standard */ -#define __signed signed -#define __volatile volatile -#if defined(__cplusplus) -#define __inline inline /* convert to C++ keyword */ -#else -#if !(defined(__CC_SUPPORTS___INLINE)) -#define __inline /* delete GCC keyword */ -#endif /* ! __CC_SUPPORTS___INLINE */ -#endif /* !__cplusplus */ - -#else /* !(__STDC__ || __cplusplus) */ -#define __P(protos) () /* traditional C preprocessor */ -#define __CONCAT(x,y) x/**/y -#define __STRING(x) "x" - -#if !defined(__CC_SUPPORTS___INLINE) -#define __const /* delete pseudo-ANSI C keywords */ -#define __inline -#define __signed -#define __volatile -/* - * In non-ANSI C environments, new programs will want ANSI-only C keywords - * deleted from the program and old programs will want them left alone. - * When using a compiler other than gcc, programs using the ANSI C keywords - * const, inline etc. as normal identifiers should define -DNO_ANSI_KEYWORDS. - * When using "gcc -traditional", we assume that this is the intent; if - * __GNUC__ is defined but __STDC__ is not, we leave the new keywords alone. - */ -#ifndef NO_ANSI_KEYWORDS -#define const /* delete ANSI C keywords */ -#define inline -#define signed -#define volatile -#endif /* !NO_ANSI_KEYWORDS */ -#endif /* !__CC_SUPPORTS___INLINE */ -#endif /* !(__STDC__ || __cplusplus) */ - -/* - * Compiler-dependent macros to help declare dead (non-returning) and - * pure (no side effects) functions, and unused variables. They are - * null except for versions of gcc that are known to support the features - * properly (old versions of gcc-2 supported the dead and pure features - * in a different (wrong) way). If we do not provide an implementation - * for a given compiler, let the compile fail if it is told to use - * a feature that we cannot live without. - */ -#ifdef lint -#define __dead2 -#define __pure2 -#define __unused -#define __packed -#define __aligned(x) -#define __section(x) -#else -#if !__GNUC_PREREQ__(2, 5) && !defined(__INTEL_COMPILER) -#define __dead2 -#define __pure2 -#define __unused -#endif -#if __GNUC__ == 2 && __GNUC_MINOR__ >= 5 && __GNUC_MINOR__ < 7 && !defined(__INTEL_COMPILER) -#define __dead2 __attribute__((__noreturn__)) -#define __pure2 __attribute__((__const__)) -#define __unused -/* XXX Find out what to do for __packed, __aligned and __section */ -#endif -#if __GNUC_PREREQ__(2, 7) -#define __dead2 __attribute__((__noreturn__)) -#define __pure2 __attribute__((__const__)) -#define __unused __attribute__((__unused__)) -#define __used __attribute__((__used__)) -#define __packed __attribute__((__packed__)) -#define __aligned(x) __attribute__((__aligned__(x))) -#define __section(x) __attribute__((__section__(x))) -#endif -#if defined(__INTEL_COMPILER) -#define __dead2 __attribute__((__noreturn__)) -#define __pure2 __attribute__((__const__)) -#define __unused __attribute__((__unused__)) -#define __used __attribute__((__used__)) -#define __packed __attribute__((__packed__)) -#define __aligned(x) __attribute__((__aligned__(x))) -#define __section(x) __attribute__((__section__(x))) -#endif -#endif - -#if __GNUC_PREREQ__(2, 96) -#define __pure __attribute__((__pure__)) -#else -#define __pure -#endif - -#if __GNUC_PREREQ__(3, 1) || (defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 800) -#define __always_inline __attribute__((__always_inline__)) -#else -#define __always_inline -#endif - -#if __GNUC_PREREQ__(4, 2) /* actually 4.1.3 */ -#define __gnu89_inline __attribute__((__gnu_inline__)) __inline -#else -#define __gnu89_inline -#endif - -#if __GNUC_PREREQ__(3, 1) -#define __noinline __attribute__ ((__noinline__)) -#else -#define __noinline -#endif - -#if __GNUC_PREREQ__(3, 3) -#define __nonnull(x) __attribute__((__nonnull__(x))) -#else -#define __nonnull(x) -#endif - -/* XXX: should use `#if __STDC_VERSION__ < 199901'. */ -#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER) -#define __func__ NULL -#endif - -#if (defined(__INTEL_COMPILER) || (defined(__GNUC__) && __GNUC__ >= 2)) && !defined(__STRICT_ANSI__) || __STDC_VERSION__ >= 199901 -#define __LONG_LONG_SUPPORTED -#endif - -/* - * GCC 2.95 provides `__restrict' as an extension to C90 to support the - * C99-specific `restrict' type qualifier. We happen to use `__restrict' as - * a way to define the `restrict' type qualifier without disturbing older - * software that is unaware of C99 keywords. - */ -#if !(__GNUC__ == 2 && __GNUC_MINOR__ == 95) -#if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 199901 -#define __restrict -#else -#define __restrict restrict -#endif -#endif - -/* - * GNU C version 2.96 adds explicit branch prediction so that - * the CPU back-end can hint the processor and also so that - * code blocks can be reordered such that the predicted path - * sees a more linear flow, thus improving cache behavior, etc. - * - * The following two macros provide us with a way to utilize this - * compiler feature. Use __predict_true() if you expect the expression - * to evaluate to true, and __predict_false() if you expect the - * expression to evaluate to false. - * - * A few notes about usage: - * - * * Generally, __predict_false() error condition checks (unless - * you have some _strong_ reason to do otherwise, in which case - * document it), and/or __predict_true() `no-error' condition - * checks, assuming you want to optimize for the no-error case. - * - * * Other than that, if you don't know the likelihood of a test - * succeeding from empirical or other `hard' evidence, don't - * make predictions. - * - * * These are meant to be used in places that are run `a lot'. - * It is wasteful to make predictions in code that is run - * seldomly (e.g. at subsystem initialization time) as the - * basic block reordering that this affects can often generate - * larger code. - */ -#if __GNUC_PREREQ__(2, 96) -#define __predict_true(exp) __builtin_expect((exp), 1) -#define __predict_false(exp) __builtin_expect((exp), 0) -#else -#define __predict_true(exp) (exp) -#define __predict_false(exp) (exp) -#endif - -/* - * We define this here since , , and - * require it. - */ -#if __GNUC_PREREQ__(4, 1) -#define __offsetof(type, field) __builtin_offsetof(type, field) -#else -#ifndef __cplusplus -#define __offsetof(type, field) ((size_t)(&((type *)0)->field)) -#else -#define __offsetof(type, field) \ - (__offsetof__ (reinterpret_cast \ - (&reinterpret_cast \ - (static_cast (0)->field)))) -#endif -#endif -#define __rangeof(type, start, end) \ - (__offsetof(type, end) - __offsetof(type, start)) - -/* - * Compiler-dependent macros to declare that functions take printf-like - * or scanf-like arguments. They are null except for versions of gcc - * that are known to support the features properly (old versions of gcc-2 - * didn't permit keeping the keywords out of the application namespace). - */ -#if !__GNUC_PREREQ__(2, 7) && !defined(__INTEL_COMPILER) -#define __printflike(fmtarg, firstvararg) -#define __scanflike(fmtarg, firstvararg) -#define __format_arg(fmtarg) -#else -#define __printflike(fmtarg, firstvararg) \ - __attribute__((__format__ (__printf__, fmtarg, firstvararg))) -#define __scanflike(fmtarg, firstvararg) \ - __attribute__((__format__ (__scanf__, fmtarg, firstvararg))) -#define __format_arg(fmtarg) __attribute__((__format_arg__ (fmtarg))) -#endif - -/* Compiler-dependent macros that rely on FreeBSD-specific extensions. */ -#if __FreeBSD_cc_version >= 300001 && defined(__GNUC__) && !defined(__INTEL_COMPILER) -#define __printf0like(fmtarg, firstvararg) \ - __attribute__((__format__ (__printf0__, fmtarg, firstvararg))) -#else -#define __printf0like(fmtarg, firstvararg) -#endif - -#if defined(__GNUC__) || defined(__INTEL_COMPILER) -#ifndef __INTEL_COMPILER -#define __strong_reference(sym,aliassym) \ - extern __typeof (sym) aliassym __attribute__ ((__alias__ (#sym))) -#endif -#ifdef __STDC__ -#define __weak_reference(sym,alias) \ - __asm__(".weak " #alias); \ - __asm__(".equ " #alias ", " #sym) -#define __warn_references(sym,msg) \ - __asm__(".section .gnu.warning." #sym); \ - __asm__(".asciz \"" msg "\""); \ - __asm__(".previous") -#define __sym_compat(sym,impl,verid) \ - __asm__(".symver " #impl ", " #sym "@" #verid) -#define __sym_default(sym,impl,verid) \ - __asm__(".symver " #impl ", " #sym "@@" #verid) -#else -#define __weak_reference(sym,alias) \ - __asm__(".weak alias"); \ - __asm__(".equ alias, sym") -#define __warn_references(sym,msg) \ - __asm__(".section .gnu.warning.sym"); \ - __asm__(".asciz \"msg\""); \ - __asm__(".previous") -#define __sym_compat(sym,impl,verid) \ - __asm__(".symver impl, sym@verid") -#define __sym_default(impl,sym,verid) \ - __asm__(".symver impl, sym@@verid") -#endif /* __STDC__ */ -#endif /* __GNUC__ || __INTEL_COMPILER */ - -#if defined(__GNUC__) || defined(__INTEL_COMPILER) -#define __IDSTRING(name,string) __asm__(".ident\t\"" string "\"") -#else -/* - * The following definition might not work well if used in header files, - * but it should be better than nothing. If you want a "do nothing" - * version, then it should generate some harmless declaration, such as: - * #define __IDSTRING(name,string) struct __hack - */ -#define __IDSTRING(name,string) static const char name[] __unused = string -#endif - -/* - * Embed the rcs id of a source file in the resulting library. Note that in - * more recent ELF binutils, we use .ident allowing the ID to be stripped. - * Usage: - * __FBSDID("$FreeBSD: src/sys/sys/cdefs.h,v 1.96 2008/10/21 16:46:50 rdivacky Exp $"); - */ -#ifndef __FBSDID -#if !defined(lint) && !defined(STRIP_FBSDID) -#define __FBSDID(s) __IDSTRING(__CONCAT(__rcsid_,__LINE__),s) -#else -#define __FBSDID(s) struct __hack -#endif -#endif - -#ifndef __RCSID -#ifndef NO__RCSID -#define __RCSID(s) __IDSTRING(__CONCAT(__rcsid_,__LINE__),s) -#else -#define __RCSID(s) struct __hack -#endif -#endif - -#ifndef __RCSID_SOURCE -#ifndef NO__RCSID_SOURCE -#define __RCSID_SOURCE(s) __IDSTRING(__CONCAT(__rcsid_source_,__LINE__),s) -#else -#define __RCSID_SOURCE(s) struct __hack -#endif -#endif - -#ifndef __SCCSID -#ifndef NO__SCCSID -#define __SCCSID(s) __IDSTRING(__CONCAT(__sccsid_,__LINE__),s) -#else -#define __SCCSID(s) struct __hack -#endif -#endif - -#ifndef __COPYRIGHT -#ifndef NO__COPYRIGHT -#define __COPYRIGHT(s) __IDSTRING(__CONCAT(__copyright_,__LINE__),s) -#else -#define __COPYRIGHT(s) struct __hack -#endif -#endif - -#ifndef __DECONST -#define __DECONST(type, var) ((type)(uintptr_t)(const void *)(var)) -#endif - -#ifndef __DEVOLATILE -#define __DEVOLATILE(type, var) ((type)(uintptr_t)(volatile void *)(var)) -#endif - -#ifndef __DEQUALIFY -#define __DEQUALIFY(type, var) ((type)(uintptr_t)(const volatile void *)(var)) -#endif - -/*- - * The following definitions are an extension of the behavior originally - * implemented in , but with a different level of granularity. - * POSIX.1 requires that the macros we test be defined before any standard - * header file is included. - * - * Here's a quick run-down of the versions: - * defined(_POSIX_SOURCE) 1003.1-1988 - * _POSIX_C_SOURCE == 1 1003.1-1990 - * _POSIX_C_SOURCE == 2 1003.2-1992 C Language Binding Option - * _POSIX_C_SOURCE == 199309 1003.1b-1993 - * _POSIX_C_SOURCE == 199506 1003.1c-1995, 1003.1i-1995, - * and the omnibus ISO/IEC 9945-1: 1996 - * _POSIX_C_SOURCE == 200112 1003.1-2001 - * - * In addition, the X/Open Portability Guide, which is now the Single UNIX - * Specification, defines a feature-test macro which indicates the version of - * that specification, and which subsumes _POSIX_C_SOURCE. - * - * Our macros begin with two underscores to avoid namespace screwage. - */ - -/* Deal with IEEE Std. 1003.1-1990, in which _POSIX_C_SOURCE == 1. */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 1 -#undef _POSIX_C_SOURCE /* Probably illegal, but beyond caring now. */ -#define _POSIX_C_SOURCE 199009 -#endif - -/* Deal with IEEE Std. 1003.2-1992, in which _POSIX_C_SOURCE == 2. */ -#if defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE == 2 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199209 -#endif - -/* Deal with various X/Open Portability Guides and Single UNIX Spec. */ -#ifdef _XOPEN_SOURCE -#if _XOPEN_SOURCE - 0 >= 600 -#define __XSI_VISIBLE 600 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 200112 -#elif _XOPEN_SOURCE - 0 >= 500 -#define __XSI_VISIBLE 500 -#undef _POSIX_C_SOURCE -#define _POSIX_C_SOURCE 199506 -#endif -#endif - -/* - * Deal with all versions of POSIX. The ordering relative to the tests above is - * important. - */ -#if defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) -#define _POSIX_C_SOURCE 198808 -#endif -#ifdef _POSIX_C_SOURCE -#if _POSIX_C_SOURCE >= 200112 -#define __POSIX_VISIBLE 200112 -#define __ISO_C_VISIBLE 1999 -#elif _POSIX_C_SOURCE >= 199506 -#define __POSIX_VISIBLE 199506 -#define __ISO_C_VISIBLE 1990 -#elif _POSIX_C_SOURCE >= 199309 -#define __POSIX_VISIBLE 199309 -#define __ISO_C_VISIBLE 1990 -#elif _POSIX_C_SOURCE >= 199209 -#define __POSIX_VISIBLE 199209 -#define __ISO_C_VISIBLE 1990 -#elif _POSIX_C_SOURCE >= 199009 -#define __POSIX_VISIBLE 199009 -#define __ISO_C_VISIBLE 1990 -#else -#define __POSIX_VISIBLE 198808 -#define __ISO_C_VISIBLE 0 -#endif /* _POSIX_C_SOURCE */ -#else -/*- - * Deal with _ANSI_SOURCE: - * If it is defined, and no other compilation environment is explicitly - * requested, then define our internal feature-test macros to zero. This - * makes no difference to the preprocessor (undefined symbols in preprocessing - * expressions are defined to have value zero), but makes it more convenient for - * a test program to print out the values. - * - * If a program mistakenly defines _ANSI_SOURCE and some other macro such as - * _POSIX_C_SOURCE, we will assume that it wants the broader compilation - * environment (and in fact we will never get here). - */ -#if defined(_ANSI_SOURCE) /* Hide almost everything. */ -#define __POSIX_VISIBLE 0 -#define __XSI_VISIBLE 0 -#define __BSD_VISIBLE 0 -#define __ISO_C_VISIBLE 1990 -#elif defined(_C99_SOURCE) /* Localism to specify strict C99 env. */ -#define __POSIX_VISIBLE 0 -#define __XSI_VISIBLE 0 -#define __BSD_VISIBLE 0 -#define __ISO_C_VISIBLE 1999 -#else /* Default environment: show everything. */ -#define __POSIX_VISIBLE 200112 -#define __XSI_VISIBLE 600 -#define __BSD_VISIBLE 1 -#define __ISO_C_VISIBLE 1999 -#endif -#endif - -#endif /* !_SYS_CDEFS_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/sys/elf.h b/repos/os/src/lib/ldso/include/libc/sys/elf.h deleted file mode 100644 index 02e22e370..000000000 --- a/repos/os/src/lib/ldso/include/libc/sys/elf.h +++ /dev/null @@ -1,41 +0,0 @@ -/*- - * Copyright (c) 2001 David E. O'Brien. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/elf.h,v 1.2 2007/11/28 21:54:46 jb Exp $ - */ - -/* - * This is a Solaris compatibility header - */ - -#ifndef _SYS_ELF_H_ -#define _SYS_ELF_H_ - -#include -#include -#include -#include - -#endif /* !_SYS_ELF_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/sys/elf32.h b/repos/os/src/lib/ldso/include/libc/sys/elf32.h deleted file mode 100644 index 676736bf1..000000000 --- a/repos/os/src/lib/ldso/include/libc/sys/elf32.h +++ /dev/null @@ -1,245 +0,0 @@ -/*- - * Copyright (c) 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/elf32.h,v 1.13 2006/10/17 05:43:30 jkoshy Exp $ - */ - -#ifndef _SYS_ELF32_H_ -#define _SYS_ELF32_H_ 1 - -#include - -/* - * ELF definitions common to all 32-bit architectures. - */ - -typedef uint32_t Elf32_Addr; -typedef uint16_t Elf32_Half; -typedef uint32_t Elf32_Off; -typedef int32_t Elf32_Sword; -typedef uint32_t Elf32_Word; -typedef uint64_t Elf32_Lword; - -typedef Elf32_Word Elf32_Hashelt; - -/* Non-standard class-dependent datatype used for abstraction. */ -typedef Elf32_Word Elf32_Size; -typedef Elf32_Sword Elf32_Ssize; - -/* - * ELF header. - */ - -typedef struct { - unsigned char e_ident[EI_NIDENT]; /* File identification. */ - Elf32_Half e_type; /* File type. */ - Elf32_Half e_machine; /* Machine architecture. */ - Elf32_Word e_version; /* ELF format version. */ - Elf32_Addr e_entry; /* Entry point. */ - Elf32_Off e_phoff; /* Program header file offset. */ - Elf32_Off e_shoff; /* Section header file offset. */ - Elf32_Word e_flags; /* Architecture-specific flags. */ - Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ - Elf32_Half e_phentsize; /* Size of program header entry. */ - Elf32_Half e_phnum; /* Number of program header entries. */ - Elf32_Half e_shentsize; /* Size of section header entry. */ - Elf32_Half e_shnum; /* Number of section header entries. */ - Elf32_Half e_shstrndx; /* Section name strings section. */ -} Elf32_Ehdr; - -/* - * Section header. - */ - -typedef struct { - Elf32_Word sh_name; /* Section name (index into the - section header string table). */ - Elf32_Word sh_type; /* Section type. */ - Elf32_Word sh_flags; /* Section flags. */ - Elf32_Addr sh_addr; /* Address in memory image. */ - Elf32_Off sh_offset; /* Offset in file. */ - Elf32_Word sh_size; /* Size in bytes. */ - Elf32_Word sh_link; /* Index of a related section. */ - Elf32_Word sh_info; /* Depends on section type. */ - Elf32_Word sh_addralign; /* Alignment in bytes. */ - Elf32_Word sh_entsize; /* Size of each entry in section. */ -} Elf32_Shdr; - -/* - * Program header. - */ - -typedef struct { - Elf32_Word p_type; /* Entry type. */ - Elf32_Off p_offset; /* File offset of contents. */ - Elf32_Addr p_vaddr; /* Virtual address in memory image. */ - Elf32_Addr p_paddr; /* Physical address (not used). */ - Elf32_Word p_filesz; /* Size of contents in file. */ - Elf32_Word p_memsz; /* Size of contents in memory. */ - Elf32_Word p_flags; /* Access permission flags. */ - Elf32_Word p_align; /* Alignment in memory and file. */ -} Elf32_Phdr; - -/* - * Dynamic structure. The ".dynamic" section contains an array of them. - */ - -typedef struct { - Elf32_Sword d_tag; /* Entry type. */ - union { - Elf32_Word d_val; /* Integer value. */ - Elf32_Addr d_ptr; /* Address value. */ - } d_un; -} Elf32_Dyn; - -/* - * Relocation entries. - */ - -/* Relocations that don't need an addend field. */ -typedef struct { - Elf32_Addr r_offset; /* Location to be relocated. */ - Elf32_Word r_info; /* Relocation type and symbol index. */ -} Elf32_Rel; - -/* Relocations that need an addend field. */ -typedef struct { - Elf32_Addr r_offset; /* Location to be relocated. */ - Elf32_Word r_info; /* Relocation type and symbol index. */ - Elf32_Sword r_addend; /* Addend. */ -} Elf32_Rela; - -/* Macros for accessing the fields of r_info. */ -#define ELF32_R_SYM(info) ((info) >> 8) -#define ELF32_R_TYPE(info) ((unsigned char)(info)) - -/* Macro for constructing r_info from field values. */ -#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) - -/* - * Note entry header - */ -typedef Elf_Note Elf32_Nhdr; - -/* - * Move entry - */ -typedef struct { - Elf32_Lword m_value; /* symbol value */ - Elf32_Word m_info; /* size + index */ - Elf32_Word m_poffset; /* symbol offset */ - Elf32_Half m_repeat; /* repeat count */ - Elf32_Half m_stride; /* stride info */ -} Elf32_Move; - -/* - * The macros compose and decompose values for Move.r_info - * - * sym = ELF32_M_SYM(M.m_info) - * size = ELF32_M_SIZE(M.m_info) - * M.m_info = ELF32_M_INFO(sym, size) - */ -#define ELF32_M_SYM(info) ((info)>>8) -#define ELF32_M_SIZE(info) ((unsigned char)(info)) -#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) - -/* - * Hardware/Software capabilities entry - */ -typedef struct { - Elf32_Word c_tag; /* how to interpret value */ - union { - Elf32_Word c_val; - Elf32_Addr c_ptr; - } c_un; -} Elf32_Cap; - -/* - * Symbol table entries. - */ - -typedef struct { - Elf32_Word st_name; /* String table index of name. */ - Elf32_Addr st_value; /* Symbol value. */ - Elf32_Word st_size; /* Size of associated object. */ - unsigned char st_info; /* Type and binding information. */ - unsigned char st_other; /* Reserved (not used). */ - Elf32_Half st_shndx; /* Section index of symbol. */ -} Elf32_Sym; - -/* Macros for accessing the fields of st_info. */ -#define ELF32_ST_BIND(info) ((info) >> 4) -#define ELF32_ST_TYPE(info) ((info) & 0xf) - -/* Macro for constructing st_info from field values. */ -#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -/* Macro for accessing the fields of st_other. */ -#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) - -/* Structures used by Sun & GNU symbol versioning. */ -typedef struct -{ - Elf32_Half vd_version; - Elf32_Half vd_flags; - Elf32_Half vd_ndx; - Elf32_Half vd_cnt; - Elf32_Word vd_hash; - Elf32_Word vd_aux; - Elf32_Word vd_next; -} Elf32_Verdef; - -typedef struct -{ - Elf32_Word vda_name; - Elf32_Word vda_next; -} Elf32_Verdaux; - -typedef struct -{ - Elf32_Half vn_version; - Elf32_Half vn_cnt; - Elf32_Word vn_file; - Elf32_Word vn_aux; - Elf32_Word vn_next; -} Elf32_Verneed; - -typedef struct -{ - Elf32_Word vna_hash; - Elf32_Half vna_flags; - Elf32_Half vna_other; - Elf32_Word vna_name; - Elf32_Word vna_next; -} Elf32_Vernaux; - -typedef Elf32_Half Elf32_Versym; - -typedef struct { - Elf32_Half si_boundto; /* direct bindings - symbol bound to */ - Elf32_Half si_flags; /* per symbol flags */ -} Elf32_Syminfo; - -#endif /* !_SYS_ELF32_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/sys/elf64.h b/repos/os/src/lib/ldso/include/libc/sys/elf64.h deleted file mode 100644 index de348ae39..000000000 --- a/repos/os/src/lib/ldso/include/libc/sys/elf64.h +++ /dev/null @@ -1,248 +0,0 @@ -/*- - * Copyright (c) 1996-1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/elf64.h,v 1.17 2006/10/17 05:43:30 jkoshy Exp $ - */ - -#ifndef _SYS_ELF64_H_ -#define _SYS_ELF64_H_ 1 - -#include - -/* - * ELF definitions common to all 64-bit architectures. - */ - -typedef uint64_t Elf64_Addr; -typedef uint16_t Elf64_Half; -typedef uint64_t Elf64_Off; -typedef int32_t Elf64_Sword; -typedef int64_t Elf64_Sxword; -typedef uint32_t Elf64_Word; -typedef uint64_t Elf64_Lword; -typedef uint64_t Elf64_Xword; - -/* - * Types of dynamic symbol hash table bucket and chain elements. - * - * This is inconsistent among 64 bit architectures, so a machine dependent - * typedef is required. - */ - -typedef Elf64_Word Elf64_Hashelt; - -/* Non-standard class-dependent datatype used for abstraction. */ -typedef Elf64_Xword Elf64_Size; -typedef Elf64_Sxword Elf64_Ssize; - -/* - * ELF header. - */ - -typedef struct { - unsigned char e_ident[EI_NIDENT]; /* File identification. */ - Elf64_Half e_type; /* File type. */ - Elf64_Half e_machine; /* Machine architecture. */ - Elf64_Word e_version; /* ELF format version. */ - Elf64_Addr e_entry; /* Entry point. */ - Elf64_Off e_phoff; /* Program header file offset. */ - Elf64_Off e_shoff; /* Section header file offset. */ - Elf64_Word e_flags; /* Architecture-specific flags. */ - Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ - Elf64_Half e_phentsize; /* Size of program header entry. */ - Elf64_Half e_phnum; /* Number of program header entries. */ - Elf64_Half e_shentsize; /* Size of section header entry. */ - Elf64_Half e_shnum; /* Number of section header entries. */ - Elf64_Half e_shstrndx; /* Section name strings section. */ -} Elf64_Ehdr; - -/* - * Section header. - */ - -typedef struct { - Elf64_Word sh_name; /* Section name (index into the - section header string table). */ - Elf64_Word sh_type; /* Section type. */ - Elf64_Xword sh_flags; /* Section flags. */ - Elf64_Addr sh_addr; /* Address in memory image. */ - Elf64_Off sh_offset; /* Offset in file. */ - Elf64_Xword sh_size; /* Size in bytes. */ - Elf64_Word sh_link; /* Index of a related section. */ - Elf64_Word sh_info; /* Depends on section type. */ - Elf64_Xword sh_addralign; /* Alignment in bytes. */ - Elf64_Xword sh_entsize; /* Size of each entry in section. */ -} Elf64_Shdr; - -/* - * Program header. - */ - -typedef struct { - Elf64_Word p_type; /* Entry type. */ - Elf64_Word p_flags; /* Access permission flags. */ - Elf64_Off p_offset; /* File offset of contents. */ - Elf64_Addr p_vaddr; /* Virtual address in memory image. */ - Elf64_Addr p_paddr; /* Physical address (not used). */ - Elf64_Xword p_filesz; /* Size of contents in file. */ - Elf64_Xword p_memsz; /* Size of contents in memory. */ - Elf64_Xword p_align; /* Alignment in memory and file. */ -} Elf64_Phdr; - -/* - * Dynamic structure. The ".dynamic" section contains an array of them. - */ - -typedef struct { - Elf64_Sxword d_tag; /* Entry type. */ - union { - Elf64_Xword d_val; /* Integer value. */ - Elf64_Addr d_ptr; /* Address value. */ - } d_un; -} Elf64_Dyn; - -/* - * Relocation entries. - */ - -/* Relocations that don't need an addend field. */ -typedef struct { - Elf64_Addr r_offset; /* Location to be relocated. */ - Elf64_Xword r_info; /* Relocation type and symbol index. */ -} Elf64_Rel; - -/* Relocations that need an addend field. */ -typedef struct { - Elf64_Addr r_offset; /* Location to be relocated. */ - Elf64_Xword r_info; /* Relocation type and symbol index. */ - Elf64_Sxword r_addend; /* Addend. */ -} Elf64_Rela; - -/* Macros for accessing the fields of r_info. */ -#define ELF64_R_SYM(info) ((info) >> 32) -#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) - -/* Macro for constructing r_info from field values. */ -#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) - -#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) -#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) -#define ELF64_R_TYPE_INFO(data, type) \ - (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) - -/* - * Note entry header - */ -typedef Elf_Note Elf64_Nhdr; - -/* - * Move entry - */ -typedef struct { - Elf64_Lword m_value; /* symbol value */ - Elf64_Xword m_info; /* size + index */ - Elf64_Xword m_poffset; /* symbol offset */ - Elf64_Half m_repeat; /* repeat count */ - Elf64_Half m_stride; /* stride info */ -} Elf64_Move; - -#define ELF64_M_SYM(info) ((info)>>8) -#define ELF64_M_SIZE(info) ((unsigned char)(info)) -#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) - -/* - * Hardware/Software capabilities entry - */ -typedef struct { - Elf64_Xword c_tag; /* how to interpret value */ - union { - Elf64_Xword c_val; - Elf64_Addr c_ptr; - } c_un; -} Elf64_Cap; - -/* - * Symbol table entries. - */ - -typedef struct { - Elf64_Word st_name; /* String table index of name. */ - unsigned char st_info; /* Type and binding information. */ - unsigned char st_other; /* Reserved (not used). */ - Elf64_Half st_shndx; /* Section index of symbol. */ - Elf64_Addr st_value; /* Symbol value. */ - Elf64_Xword st_size; /* Size of associated object. */ -} Elf64_Sym; - -/* Macros for accessing the fields of st_info. */ -#define ELF64_ST_BIND(info) ((info) >> 4) -#define ELF64_ST_TYPE(info) ((info) & 0xf) - -/* Macro for constructing st_info from field values. */ -#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) - -/* Macro for accessing the fields of st_other. */ -#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) - -/* Structures used by Sun & GNU-style symbol versioning. */ -typedef struct { - Elf64_Half vd_version; - Elf64_Half vd_flags; - Elf64_Half vd_ndx; - Elf64_Half vd_cnt; - Elf64_Word vd_hash; - Elf64_Word vd_aux; - Elf64_Word vd_next; -} Elf64_Verdef; - -typedef struct { - Elf64_Word vda_name; - Elf64_Word vda_next; -} Elf64_Verdaux; - -typedef struct { - Elf64_Half vn_version; - Elf64_Half vn_cnt; - Elf64_Word vn_file; - Elf64_Word vn_aux; - Elf64_Word vn_next; -} Elf64_Verneed; - -typedef struct { - Elf64_Word vna_hash; - Elf64_Half vna_flags; - Elf64_Half vna_other; - Elf64_Word vna_name; - Elf64_Word vna_next; -} Elf64_Vernaux; - -typedef Elf64_Half Elf64_Versym; - -typedef struct { - Elf64_Half si_boundto; /* direct bindings - symbol bound to */ - Elf64_Half si_flags; /* per symbol flags */ -} Elf64_Syminfo; - -#endif /* !_SYS_ELF64_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/sys/elf_common.h b/repos/os/src/lib/ldso/include/libc/sys/elf_common.h deleted file mode 100644 index 0ffbffa24..000000000 --- a/repos/os/src/lib/ldso/include/libc/sys/elf_common.h +++ /dev/null @@ -1,865 +0,0 @@ -/*- - * Copyright (c) 1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/elf_common.h,v 1.24 2008/08/02 01:20:10 imp Exp $ - */ - -#ifndef _SYS_ELF_COMMON_H_ -#define _SYS_ELF_COMMON_H_ 1 - -/* - * ELF definitions that are independent of architecture or word size. - */ - -/* - * Note header. The ".note" section contains an array of notes. Each - * begins with this header, aligned to a word boundary. Immediately - * following the note header is n_namesz bytes of name, padded to the - * next word boundary. Then comes n_descsz bytes of descriptor, again - * padded to a word boundary. The values of n_namesz and n_descsz do - * not include the padding. - */ - -typedef struct { - u_int32_t n_namesz; /* Length of name. */ - u_int32_t n_descsz; /* Length of descriptor. */ - u_int32_t n_type; /* Type of this note. */ -} Elf_Note; - -/* Indexes into the e_ident array. Keep synced with - http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ -#define EI_MAG0 0 /* Magic number, byte 0. */ -#define EI_MAG1 1 /* Magic number, byte 1. */ -#define EI_MAG2 2 /* Magic number, byte 2. */ -#define EI_MAG3 3 /* Magic number, byte 3. */ -#define EI_CLASS 4 /* Class of machine. */ -#define EI_DATA 5 /* Data format. */ -#define EI_VERSION 6 /* ELF format version. */ -#define EI_OSABI 7 /* Operating system / ABI identification */ -#define EI_ABIVERSION 8 /* ABI version */ -#define OLD_EI_BRAND 8 /* Start of architecture identification. */ -#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ -#define EI_NIDENT 16 /* Size of e_ident array. */ - -/* Values for the magic number bytes. */ -#define ELFMAG0 0x7f -#define ELFMAG1 'E' -#define ELFMAG2 'L' -#define ELFMAG3 'F' -#define ELFMAG "\177ELF" /* magic string */ -#define SELFMAG 4 /* magic string size */ - -/* Values for e_ident[EI_VERSION] and e_version. */ -#define EV_NONE 0 -#define EV_CURRENT 1 - -/* Values for e_ident[EI_CLASS]. */ -#define ELFCLASSNONE 0 /* Unknown class. */ -#define ELFCLASS32 1 /* 32-bit architecture. */ -#define ELFCLASS64 2 /* 64-bit architecture. */ - -/* Values for e_ident[EI_DATA]. */ -#define ELFDATANONE 0 /* Unknown data format. */ -#define ELFDATA2LSB 1 /* 2's complement little-endian. */ -#define ELFDATA2MSB 2 /* 2's complement big-endian. */ - -/* Values for e_ident[EI_OSABI]. */ -#define ELFOSABI_NONE 0 /* UNIX System V ABI */ -#define ELFOSABI_HPUX 1 /* HP-UX operating system */ -#define ELFOSABI_NETBSD 2 /* NetBSD */ -#define ELFOSABI_LINUX 3 /* GNU/Linux */ -#define ELFOSABI_HURD 4 /* GNU/Hurd */ -#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ -#define ELFOSABI_SOLARIS 6 /* Solaris */ -#define ELFOSABI_AIX 7 /* AIX */ -#define ELFOSABI_IRIX 8 /* IRIX */ -#define ELFOSABI_FREEBSD 9 /* FreeBSD */ -#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ -#define ELFOSABI_MODESTO 11 /* Novell Modesto */ -#define ELFOSABI_OPENBSD 12 /* OpenBSD */ -#define ELFOSABI_OPENVMS 13 /* Open VMS */ -#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ -#define ELFOSABI_ARM 97 /* ARM */ -#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ - -#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ -#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ - -/* e_ident */ -#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ - (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ - (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ - (ehdr).e_ident[EI_MAG3] == ELFMAG3) - -/* Values for e_type. */ -#define ET_NONE 0 /* Unknown type. */ -#define ET_REL 1 /* Relocatable. */ -#define ET_EXEC 2 /* Executable. */ -#define ET_DYN 3 /* Shared object. */ -#define ET_CORE 4 /* Core file. */ -#define ET_LOOS 0xfe00 /* First operating system specific. */ -#define ET_HIOS 0xfeff /* Last operating system-specific. */ -#define ET_LOPROC 0xff00 /* First processor-specific. */ -#define ET_HIPROC 0xffff /* Last processor-specific. */ - -/* Values for e_machine. */ -#define EM_NONE 0 /* Unknown machine. */ -#define EM_M32 1 /* AT&T WE32100. */ -#define EM_SPARC 2 /* Sun SPARC. */ -#define EM_386 3 /* Intel i386. */ -#define EM_68K 4 /* Motorola 68000. */ -#define EM_88K 5 /* Motorola 88000. */ -#define EM_860 7 /* Intel i860. */ -#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ -#define EM_S370 9 /* IBM System/370. */ -#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ -#define EM_PARISC 15 /* HP PA-RISC. */ -#define EM_VPP500 17 /* Fujitsu VPP500. */ -#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ -#define EM_960 19 /* Intel 80960. */ -#define EM_PPC 20 /* PowerPC 32-bit. */ -#define EM_PPC64 21 /* PowerPC 64-bit. */ -#define EM_S390 22 /* IBM System/390. */ -#define EM_V800 36 /* NEC V800. */ -#define EM_FR20 37 /* Fujitsu FR20. */ -#define EM_RH32 38 /* TRW RH-32. */ -#define EM_RCE 39 /* Motorola RCE. */ -#define EM_ARM 40 /* ARM. */ -#define EM_SH 42 /* Hitachi SH. */ -#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ -#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ -#define EM_ARC 45 /* Argonaut RISC Core. */ -#define EM_H8_300 46 /* Hitachi H8/300. */ -#define EM_H8_300H 47 /* Hitachi H8/300H. */ -#define EM_H8S 48 /* Hitachi H8S. */ -#define EM_H8_500 49 /* Hitachi H8/500. */ -#define EM_IA_64 50 /* Intel IA-64 Processor. */ -#define EM_MIPS_X 51 /* Stanford MIPS-X. */ -#define EM_COLDFIRE 52 /* Motorola ColdFire. */ -#define EM_68HC12 53 /* Motorola M68HC12. */ -#define EM_MMA 54 /* Fujitsu MMA. */ -#define EM_PCP 55 /* Siemens PCP. */ -#define EM_NCPU 56 /* Sony nCPU. */ -#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ -#define EM_STARCORE 58 /* Motorola Star*Core processor. */ -#define EM_ME16 59 /* Toyota ME16 processor. */ -#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ -#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ -#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ -#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ - -/* Non-standard or deprecated. */ -#define EM_486 6 /* Intel i486. */ -#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ -#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ -#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ - -/* Special section indexes. */ -#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ -#define SHN_LORESERVE 0xff00 /* First of reserved range. */ -#define SHN_LOPROC 0xff00 /* First processor-specific. */ -#define SHN_HIPROC 0xff1f /* Last processor-specific. */ -#define SHN_LOOS 0xff20 /* First operating system-specific. */ -#define SHN_HIOS 0xff3f /* Last operating system-specific. */ -#define SHN_ABS 0xfff1 /* Absolute values. */ -#define SHN_COMMON 0xfff2 /* Common data. */ -#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ -#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ - -/* sh_type */ -#define SHT_NULL 0 /* inactive */ -#define SHT_PROGBITS 1 /* program defined information */ -#define SHT_SYMTAB 2 /* symbol table section */ -#define SHT_STRTAB 3 /* string table section */ -#define SHT_RELA 4 /* relocation section with addends */ -#define SHT_HASH 5 /* symbol hash table section */ -#define SHT_DYNAMIC 6 /* dynamic section */ -#define SHT_NOTE 7 /* note section */ -#define SHT_NOBITS 8 /* no space section */ -#define SHT_REL 9 /* relocation section - no addends */ -#define SHT_SHLIB 10 /* reserved - purpose unknown */ -#define SHT_DYNSYM 11 /* dynamic symbol table section */ -#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ -#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ -#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ -#define SHT_GROUP 17 /* Section group. */ -#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ -#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ -#define SHT_LOSUNW 0x6ffffff4 -#define SHT_SUNW_dof 0x6ffffff4 -#define SHT_SUNW_cap 0x6ffffff5 -#define SHT_SUNW_SIGNATURE 0x6ffffff6 -#define SHT_SUNW_ANNOTATE 0x6ffffff7 -#define SHT_SUNW_DEBUGSTR 0x6ffffff8 -#define SHT_SUNW_DEBUG 0x6ffffff9 -#define SHT_SUNW_move 0x6ffffffa -#define SHT_SUNW_COMDAT 0x6ffffffb -#define SHT_SUNW_syminfo 0x6ffffffc -#define SHT_SUNW_verdef 0x6ffffffd -#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ -#define SHT_SUNW_verneed 0x6ffffffe -#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ -#define SHT_SUNW_versym 0x6fffffff -#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ -#define SHT_HISUNW 0x6fffffff -#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ -#define SHT_LOPROC 0x70000000 /* reserved range for processor */ -#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ -#define SHT_HIPROC 0x7fffffff /* specific section header types */ -#define SHT_LOUSER 0x80000000 /* reserved range for application */ -#define SHT_HIUSER 0xffffffff /* specific indexes */ - -/* Flags for sh_flags. */ -#define SHF_WRITE 0x1 /* Section contains writable data. */ -#define SHF_ALLOC 0x2 /* Section occupies memory. */ -#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ -#define SHF_MERGE 0x10 /* Section may be merged. */ -#define SHF_STRINGS 0x20 /* Section contains strings. */ -#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ -#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ -#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ -#define SHF_GROUP 0x200 /* Member of section group. */ -#define SHF_TLS 0x400 /* Section contains TLS data. */ -#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ -#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ - -/* Values for p_type. */ -#define PT_NULL 0 /* Unused entry. */ -#define PT_LOAD 1 /* Loadable segment. */ -#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ -#define PT_INTERP 3 /* Pathname of interpreter. */ -#define PT_NOTE 4 /* Auxiliary information. */ -#define PT_SHLIB 5 /* Reserved (not used). */ -#define PT_PHDR 6 /* Location of program header itself. */ -#define PT_TLS 7 /* Thread local storage segment */ -#define PT_LOOS 0x60000000 /* First OS-specific. */ -#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ -#define PT_GNU_EH_FRAME 0x6474e550 -#define PT_LOSUNW 0x6ffffffa -#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ -#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ -#define PT_SUNWDTRACE 0x6ffffffc /* private */ -#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ -#define PT_HISUNW 0x6fffffff -#define PT_HIOS 0x6fffffff /* Last OS-specific. */ -#define PT_LOPROC 0x70000000 /* First processor-specific type. */ -#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ - -/* Values for p_flags. */ -#define PF_X 0x1 /* Executable. */ -#define PF_W 0x2 /* Writable. */ -#define PF_R 0x4 /* Readable. */ -#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ -#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ - -/* Extended program header index. */ -#define PN_XNUM 0xffff - -/* Values for d_tag. */ -#define DT_NULL 0 /* Terminating entry. */ -#define DT_NEEDED 1 /* String table offset of a needed shared - library. */ -#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ -#define DT_PLTGOT 3 /* Processor-dependent address. */ -#define DT_HASH 4 /* Address of symbol hash table. */ -#define DT_STRTAB 5 /* Address of string table. */ -#define DT_SYMTAB 6 /* Address of symbol table. */ -#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ -#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ -#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ -#define DT_STRSZ 10 /* Size of string table. */ -#define DT_SYMENT 11 /* Size of each symbol table entry. */ -#define DT_INIT 12 /* Address of initialization function. */ -#define DT_FINI 13 /* Address of finalization function. */ -#define DT_SONAME 14 /* String table offset of shared object - name. */ -#define DT_RPATH 15 /* String table offset of library path. [sup] */ -#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ -#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ -#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ -#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ -#define DT_PLTREL 20 /* Type of relocation used for PLT. */ -#define DT_DEBUG 21 /* Reserved (not used). */ -#define DT_TEXTREL 22 /* Indicates there may be relocations in - non-writable segments. [sup] */ -#define DT_JMPREL 23 /* Address of PLT relocations. */ -#define DT_BIND_NOW 24 /* [sup] */ -#define DT_INIT_ARRAY 25 /* Address of the array of pointers to - initialization functions */ -#define DT_FINI_ARRAY 26 /* Address of the array of pointers to - termination functions */ -#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of - initialization functions. */ -#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of - terminationfunctions. */ -#define DT_RUNPATH 29 /* String table offset of a null-terminated - library search path string. */ -#define DT_FLAGS 30 /* Object specific flag values. */ -#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING - and less than DT_LOOS follow the rules for - the interpretation of the d_un union - as follows: even == 'd_ptr', even == 'd_val' - or none */ -#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to - pre-initialization functions. */ -#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of - pre-initialization functions. */ -#define DT_MAXPOSTAGS 34 /* number of positive tags */ -#define DT_LOOS 0x6000000d /* First OS-specific */ -#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ -#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ -#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ -#define DT_SUNW_CAP 0x60000010 /* hardware/software */ -#define DT_HIOS 0x6ffff000 /* Last OS-specific */ - -/* - * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the - * Dyn.d_un.d_val field of the Elf*_Dyn structure. - */ -#define DT_VALRNGLO 0x6ffffd00 -#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ -#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ -#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ -#define DT_MOVESZ 0x6ffffdfb /* move table size */ -#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ -#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ - /* the following DT_* entry. */ - /* See DF_P1_* definitions */ -#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ -#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ -#define DT_VALRNGHI 0x6ffffdff - -/* - * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the - * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. - * - * If any adjustment is made to the ELF object after it has been - * built, these entries will need to be adjusted. - */ -#define DT_ADDRRNGLO 0x6ffffe00 -#define DT_CONFIG 0x6ffffefa /* configuration information */ -#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ -#define DT_AUDIT 0x6ffffefc /* object auditing */ -#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ -#define DT_MOVETAB 0x6ffffefe /* move table */ -#define DT_SYMINFO 0x6ffffeff /* syminfo table */ -#define DT_ADDRRNGHI 0x6ffffeff - -#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ -#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ -#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ -#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ -#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ -#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ -#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ -#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ - -#define DT_LOPROC 0x70000000 /* First processor-specific type. */ -#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 -#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ -#define DT_USED 0x7ffffffe /* ignored - same as needed */ -#define DT_FILTER 0x7fffffff /* shared library filter name */ -#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ - -/* Values for DT_FLAGS */ -#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may - make reference to the $ORIGIN substitution - string */ -#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ -#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in - non-writable segments. */ -#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should - process all relocations for the object - containing this entry before transferring - control to the program. */ -#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or - executable contains code using a static - thread-local storage scheme. */ - -/* Values for n_type. Used in core files. */ -#define NT_PRSTATUS 1 /* Process status. */ -#define NT_FPREGSET 2 /* Floating point registers. */ -#define NT_PRPSINFO 3 /* Process state info. */ - -/* Symbol Binding - ELFNN_ST_BIND - st_info */ -#define STB_LOCAL 0 /* Local symbol */ -#define STB_GLOBAL 1 /* Global symbol */ -#define STB_WEAK 2 /* like global - lower precedence */ -#define STB_LOOS 10 /* Reserved range for operating system */ -#define STB_HIOS 12 /* specific semantics. */ -#define STB_LOPROC 13 /* reserved range for processor */ -#define STB_HIPROC 15 /* specific semantics. */ - -/* Symbol type - ELFNN_ST_TYPE - st_info */ -#define STT_NOTYPE 0 /* Unspecified type. */ -#define STT_OBJECT 1 /* Data object. */ -#define STT_FUNC 2 /* Function. */ -#define STT_SECTION 3 /* Section. */ -#define STT_FILE 4 /* Source file. */ -#define STT_COMMON 5 /* Uninitialized common block. */ -#define STT_TLS 6 /* TLS object. */ -#define STT_NUM 7 -#define STT_LOOS 10 /* Reserved range for operating system */ -#define STT_HIOS 12 /* specific semantics. */ -#define STT_LOPROC 13 /* reserved range for processor */ -#define STT_HIPROC 15 /* specific semantics. */ - -/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ -#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ -#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ -#define STV_HIDDEN 0x2 /* Not visible. */ -#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ -#define STV_EXPORTED 0x4 -#define STV_SINGLETON 0x5 -#define STV_ELIMINATE 0x6 - -/* Special symbol table indexes. */ -#define STN_UNDEF 0 /* Undefined symbol index. */ - -/* Symbol versioning flags. */ -#define VER_DEF_CURRENT 1 -#define VER_DEF_IDX(x) VER_NDX(x) - -#define VER_FLG_BASE 0x01 -#define VER_FLG_WEAK 0x02 - -#define VER_NEED_CURRENT 1 -#define VER_NEED_WEAK (1u << 15) -#define VER_NEED_HIDDEN VER_NDX_HIDDEN -#define VER_NEED_IDX(x) VER_NDX(x) - -#define VER_NDX_LOCAL 0 -#define VER_NDX_GLOBAL 1 -#define VER_NDX_GIVEN 2 - -#define VER_NDX_HIDDEN (1u << 15) -#define VER_NDX(x) ((x) & ~(1u << 15)) - -#define CA_SUNW_NULL 0 -#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ -#define CA_SUNW_SF_1 2 /* first software capabilities entry */ - -/* - * Syminfo flag values - */ -#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ - /* to object containing defn. */ -#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ -#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ -#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ - /* lazily-loaded */ -#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ - /* object containing defn. */ -#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ - /* directly bind to this symbol */ -#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ -#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ - -/* - * Syminfo.si_boundto values. - */ -#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ -#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ -#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ -#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ -#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ - -/* - * Syminfo version values. - */ -#define SYMINFO_NONE 0 /* Syminfo version */ -#define SYMINFO_CURRENT 1 -#define SYMINFO_NUM 2 - -/* - * Relocation types. - * - * All machine architectures are defined here to allow tools on one to - * handle others. - */ - -#define R_386_NONE 0 /* No relocation. */ -#define R_386_32 1 /* Add symbol value. */ -#define R_386_PC32 2 /* Add PC-relative symbol value. */ -#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ -#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ -#define R_386_COPY 5 /* Copy data from shared object. */ -#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ -#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ -#define R_386_RELATIVE 8 /* Add load address of shared object. */ -#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ -#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ -#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ -#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ -#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ -#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ -#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ -#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ -#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ -#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ -#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ -#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ -#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ -#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ -#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ -#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ -#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ -#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ -#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ -#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ -#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ -#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ - -#define R_ARM_NONE 0 /* No relocation. */ -#define R_ARM_PC24 1 -#define R_ARM_ABS32 2 -#define R_ARM_REL32 3 -#define R_ARM_PC13 4 -#define R_ARM_ABS16 5 -#define R_ARM_ABS12 6 -#define R_ARM_THM_ABS5 7 -#define R_ARM_ABS8 8 -#define R_ARM_SBREL32 9 -#define R_ARM_THM_PC22 10 -#define R_ARM_THM_PC8 11 -#define R_ARM_AMP_VCALL9 12 -#define R_ARM_SWI24 13 -#define R_ARM_THM_SWI8 14 -#define R_ARM_XPC25 15 -#define R_ARM_THM_XPC22 16 -#define R_ARM_TLS_DTPMOD32 17 -#define R_ARM_COPY 20 /* Copy data from shared object. */ -#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ -#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ -#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ -#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ -#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ -#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ -#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ -#define R_ARM_GNU_VTENTRY 100 -#define R_ARM_GNU_VTINHERIT 101 -#define R_ARM_RSBREL32 250 -#define R_ARM_THM_RPC22 251 -#define R_ARM_RREL32 252 -#define R_ARM_RABS32 253 -#define R_ARM_RPC24 254 -#define R_ARM_RBASE 255 - -/* Name Value Field Calculation */ -#define R_IA_64_NONE 0 /* None */ -#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ -#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ -#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ -#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ -#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ -#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ -#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ -#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ -#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ -#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ -#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ -#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ -#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ -#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ -#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ -#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ -#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ -#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ -#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ -#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ -#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ -#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ -#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ -#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ -#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ -#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ -#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ -#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ -#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ -#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ -#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ -#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ -#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ -#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ -#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ -#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ -#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ -#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ -#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ -#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ -#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ -#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ -#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ -#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ -#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ -#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ -#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ -#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ -#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ -#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ -#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ -#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ -#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ -#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ -#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ -#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ -#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ -#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ -#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ -#define R_IA_64_SUB 0x85 /* immediate64 A - S */ -#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ -#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ -#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ -#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ -#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ -#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ -#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ -#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ -#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ -#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ -#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ -#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ -#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ -#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ -#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ -#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ -#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ -#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ -#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ - -#define R_MIPS_NONE 0 /* No reloc */ -#define R_MIPS_16 1 /* Direct 16 bit */ -#define R_MIPS_32 2 /* Direct 32 bit */ -#define R_MIPS_REL32 3 /* PC relative 32 bit */ -#define R_MIPS_26 4 /* Direct 26 bit shifted */ -#define R_MIPS_HI16 5 /* High 16 bit */ -#define R_MIPS_LO16 6 /* Low 16 bit */ -#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ -#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ -#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ -#define R_MIPS_PC16 10 /* PC relative 16 bit */ -#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ -#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ -#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */ -#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */ -#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ -#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ - -#define R_PPC_NONE 0 /* No relocation. */ -#define R_PPC_ADDR32 1 -#define R_PPC_ADDR24 2 -#define R_PPC_ADDR16 3 -#define R_PPC_ADDR16_LO 4 -#define R_PPC_ADDR16_HI 5 -#define R_PPC_ADDR16_HA 6 -#define R_PPC_ADDR14 7 -#define R_PPC_ADDR14_BRTAKEN 8 -#define R_PPC_ADDR14_BRNTAKEN 9 -#define R_PPC_REL24 10 -#define R_PPC_REL14 11 -#define R_PPC_REL14_BRTAKEN 12 -#define R_PPC_REL14_BRNTAKEN 13 -#define R_PPC_GOT16 14 -#define R_PPC_GOT16_LO 15 -#define R_PPC_GOT16_HI 16 -#define R_PPC_GOT16_HA 17 -#define R_PPC_PLTREL24 18 -#define R_PPC_COPY 19 -#define R_PPC_GLOB_DAT 20 -#define R_PPC_JMP_SLOT 21 -#define R_PPC_RELATIVE 22 -#define R_PPC_LOCAL24PC 23 -#define R_PPC_UADDR32 24 -#define R_PPC_UADDR16 25 -#define R_PPC_REL32 26 -#define R_PPC_PLT32 27 -#define R_PPC_PLTREL32 28 -#define R_PPC_PLT16_LO 29 -#define R_PPC_PLT16_HI 30 -#define R_PPC_PLT16_HA 31 -#define R_PPC_SDAREL16 32 -#define R_PPC_SECTOFF 33 -#define R_PPC_SECTOFF_LO 34 -#define R_PPC_SECTOFF_HI 35 -#define R_PPC_SECTOFF_HA 36 - -/* - * TLS relocations - */ -#define R_PPC_TLS 67 -#define R_PPC_DTPMOD32 68 -#define R_PPC_TPREL16 69 -#define R_PPC_TPREL16_LO 70 -#define R_PPC_TPREL16_HI 71 -#define R_PPC_TPREL16_HA 72 -#define R_PPC_TPREL32 73 -#define R_PPC_DTPREL16 74 -#define R_PPC_DTPREL16_LO 75 -#define R_PPC_DTPREL16_HI 76 -#define R_PPC_DTPREL16_HA 77 -#define R_PPC_DTPREL32 78 -#define R_PPC_GOT_TLSGD16 79 -#define R_PPC_GOT_TLSGD16_LO 80 -#define R_PPC_GOT_TLSGD16_HI 81 -#define R_PPC_GOT_TLSGD16_HA 82 -#define R_PPC_GOT_TLSLD16 83 -#define R_PPC_GOT_TLSLD16_LO 84 -#define R_PPC_GOT_TLSLD16_HI 85 -#define R_PPC_GOT_TLSLD16_HA 86 -#define R_PPC_GOT_TPREL16 87 -#define R_PPC_GOT_TPREL16_LO 88 -#define R_PPC_GOT_TPREL16_HI 89 -#define R_PPC_GOT_TPREL16_HA 90 - -/* - * The remaining relocs are from the Embedded ELF ABI, and are not in the - * SVR4 ELF ABI. - */ - -#define R_PPC_EMB_NADDR32 101 -#define R_PPC_EMB_NADDR16 102 -#define R_PPC_EMB_NADDR16_LO 103 -#define R_PPC_EMB_NADDR16_HI 104 -#define R_PPC_EMB_NADDR16_HA 105 -#define R_PPC_EMB_SDAI16 106 -#define R_PPC_EMB_SDA2I16 107 -#define R_PPC_EMB_SDA2REL 108 -#define R_PPC_EMB_SDA21 109 -#define R_PPC_EMB_MRKREF 110 -#define R_PPC_EMB_RELSEC16 111 -#define R_PPC_EMB_RELST_LO 112 -#define R_PPC_EMB_RELST_HI 113 -#define R_PPC_EMB_RELST_HA 114 -#define R_PPC_EMB_BIT_FLD 115 -#define R_PPC_EMB_RELSDA 116 - -#define R_SPARC_NONE 0 -#define R_SPARC_8 1 -#define R_SPARC_16 2 -#define R_SPARC_32 3 -#define R_SPARC_DISP8 4 -#define R_SPARC_DISP16 5 -#define R_SPARC_DISP32 6 -#define R_SPARC_WDISP30 7 -#define R_SPARC_WDISP22 8 -#define R_SPARC_HI22 9 -#define R_SPARC_22 10 -#define R_SPARC_13 11 -#define R_SPARC_LO10 12 -#define R_SPARC_GOT10 13 -#define R_SPARC_GOT13 14 -#define R_SPARC_GOT22 15 -#define R_SPARC_PC10 16 -#define R_SPARC_PC22 17 -#define R_SPARC_WPLT30 18 -#define R_SPARC_COPY 19 -#define R_SPARC_GLOB_DAT 20 -#define R_SPARC_JMP_SLOT 21 -#define R_SPARC_RELATIVE 22 -#define R_SPARC_UA32 23 -#define R_SPARC_PLT32 24 -#define R_SPARC_HIPLT22 25 -#define R_SPARC_LOPLT10 26 -#define R_SPARC_PCPLT32 27 -#define R_SPARC_PCPLT22 28 -#define R_SPARC_PCPLT10 29 -#define R_SPARC_10 30 -#define R_SPARC_11 31 -#define R_SPARC_64 32 -#define R_SPARC_OLO10 33 -#define R_SPARC_HH22 34 -#define R_SPARC_HM10 35 -#define R_SPARC_LM22 36 -#define R_SPARC_PC_HH22 37 -#define R_SPARC_PC_HM10 38 -#define R_SPARC_PC_LM22 39 -#define R_SPARC_WDISP16 40 -#define R_SPARC_WDISP19 41 -#define R_SPARC_GLOB_JMP 42 -#define R_SPARC_7 43 -#define R_SPARC_5 44 -#define R_SPARC_6 45 -#define R_SPARC_DISP64 46 -#define R_SPARC_PLT64 47 -#define R_SPARC_HIX22 48 -#define R_SPARC_LOX10 49 -#define R_SPARC_H44 50 -#define R_SPARC_M44 51 -#define R_SPARC_L44 52 -#define R_SPARC_REGISTER 53 -#define R_SPARC_UA64 54 -#define R_SPARC_UA16 55 -#define R_SPARC_TLS_GD_HI22 56 -#define R_SPARC_TLS_GD_LO10 57 -#define R_SPARC_TLS_GD_ADD 58 -#define R_SPARC_TLS_GD_CALL 59 -#define R_SPARC_TLS_LDM_HI22 60 -#define R_SPARC_TLS_LDM_LO10 61 -#define R_SPARC_TLS_LDM_ADD 62 -#define R_SPARC_TLS_LDM_CALL 63 -#define R_SPARC_TLS_LDO_HIX22 64 -#define R_SPARC_TLS_LDO_LOX10 65 -#define R_SPARC_TLS_LDO_ADD 66 -#define R_SPARC_TLS_IE_HI22 67 -#define R_SPARC_TLS_IE_LO10 68 -#define R_SPARC_TLS_IE_LD 69 -#define R_SPARC_TLS_IE_LDX 70 -#define R_SPARC_TLS_IE_ADD 71 -#define R_SPARC_TLS_LE_HIX22 72 -#define R_SPARC_TLS_LE_LOX10 73 -#define R_SPARC_TLS_DTPMOD32 74 -#define R_SPARC_TLS_DTPMOD64 75 -#define R_SPARC_TLS_DTPOFF32 76 -#define R_SPARC_TLS_DTPOFF64 77 -#define R_SPARC_TLS_TPOFF32 78 -#define R_SPARC_TLS_TPOFF64 79 - -#define R_X86_64_NONE 0 /* No relocation. */ -#define R_X86_64_64 1 /* Add 64 bit symbol value. */ -#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ -#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ -#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ -#define R_X86_64_COPY 5 /* Copy data from shared object. */ -#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ -#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ -#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ -#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ -#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ -#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ -#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ -#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ -#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ -#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ -#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ -#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ -#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ -#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ -#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ -#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ -#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ -#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ - - -#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/sys/elf_generic.h b/repos/os/src/lib/ldso/include/libc/sys/elf_generic.h deleted file mode 100644 index 9d540733a..000000000 --- a/repos/os/src/lib/ldso/include/libc/sys/elf_generic.h +++ /dev/null @@ -1,88 +0,0 @@ -/*- - * Copyright (c) 1998 John D. Polstra. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/elf_generic.h,v 1.8 2005/12/18 19:43:33 kan Exp $ - */ - -#ifndef _SYS_ELF_GENERIC_H_ -#define _SYS_ELF_GENERIC_H_ 1 - -#include - -/* - * Definitions of generic ELF names which relieve applications from - * needing to know the word size. - */ - -#if __ELF_WORD_SIZE != 32 && __ELF_WORD_SIZE != 64 -#error "__ELF_WORD_SIZE must be defined as 32 or 64" -#endif - -#define ELF_CLASS __CONCAT(ELFCLASS,__ELF_WORD_SIZE) - -#if BYTE_ORDER == LITTLE_ENDIAN -#define ELF_DATA ELFDATA2LSB -#elif BYTE_ORDER == BIG_ENDIAN -#define ELF_DATA ELFDATA2MSB -#else -#error "Unknown byte order" -#endif - -#define __elfN(x) __CONCAT(__CONCAT(__CONCAT(elf,__ELF_WORD_SIZE),_),x) -#define __ElfN(x) __CONCAT(__CONCAT(__CONCAT(Elf,__ELF_WORD_SIZE),_),x) -#define __ELFN(x) __CONCAT(__CONCAT(__CONCAT(ELF,__ELF_WORD_SIZE),_),x) -#define __ElfType(x) typedef __ElfN(x) __CONCAT(Elf_,x) - -__ElfType(Addr); -__ElfType(Half); -__ElfType(Off); -__ElfType(Sword); -__ElfType(Word); -__ElfType(Ehdr); -__ElfType(Shdr); -__ElfType(Phdr); -__ElfType(Dyn); -__ElfType(Rel); -__ElfType(Rela); -__ElfType(Sym); -__ElfType(Verdef); -__ElfType(Verdaux); -__ElfType(Verneed); -__ElfType(Vernaux); -__ElfType(Versym); - -/* Non-standard ELF types. */ -__ElfType(Hashelt); -__ElfType(Size); -__ElfType(Ssize); - -#define ELF_R_SYM __ELFN(R_SYM) -#define ELF_R_TYPE __ELFN(R_TYPE) -#define ELF_R_INFO __ELFN(R_INFO) -#define ELF_ST_BIND __ELFN(ST_BIND) -#define ELF_ST_TYPE __ELFN(ST_TYPE) -#define ELF_ST_INFO __ELFN(ST_INFO) - -#endif /* !_SYS_ELF_GENERIC_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/sys/link_elf.h b/repos/os/src/lib/ldso/include/libc/sys/link_elf.h deleted file mode 100644 index f3fb2e0f9..000000000 --- a/repos/os/src/lib/ldso/include/libc/sys/link_elf.h +++ /dev/null @@ -1,99 +0,0 @@ -/*- - * Copyright (c) 1993 Paul Kranenburg - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Paul Kranenburg. - * 4. The name of the author may not be used to endorse or promote products - * derived from this software without specific prior written permission - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * $FreeBSD: src/sys/sys/link_elf.h,v 1.29 2008/07/11 01:10:40 obrien Exp $ - */ - -/* - * RRS section definitions. - * - * The layout of some data structures defined in this header file is - * such that we can provide compatibility with the SunOS 4.x shared - * library scheme. - */ - -#ifndef _SYS_LINK_ELF_H_ -#define _SYS_LINK_ELF_H_ - -#include - -/* - * Flags that describe the origin of the entries in Dl_serinfo. - * SunOS has these in , we follow the suit. - */ -#define LA_SER_ORIG 0x01 /* original (needed) name */ -#define LA_SER_LIBPATH 0x02 /* LD_LIBRARY_PATH entry prepended */ -#define LA_SER_RUNPATH 0x04 /* runpath entry prepended */ -#define LA_SER_CONFIG 0x08 /* configuration entry prepended */ -#define LA_SER_DEFAULT 0x40 /* default path prepended */ -#define LA_SER_SECURE 0x80 /* default (secure) path prepended */ - -typedef struct link_map { - caddr_t l_addr; /* Base Address of library */ -#ifdef __mips__ - caddr_t l_offs; /* Load Offset of library */ -#endif - const char *l_name; /* Absolute Path to Library */ - const void *l_ld; /* Pointer to .dynamic in memory */ - struct link_map *l_next, *l_prev; /* linked list of of mapped libs */ -} Link_map; - -struct r_debug { - int r_version; /* not used */ - struct link_map *r_map; /* list of loaded images */ - void (*r_brk)(struct r_debug *, struct link_map *); - /* pointer to break point */ - enum { - RT_CONSISTENT, /* things are stable */ - RT_ADD, /* adding a shared library */ - RT_DELETE /* removing a shared library */ - } r_state; -}; - -struct dl_phdr_info -{ - Elf_Addr dlpi_addr; /* module relocation base */ - const char *dlpi_name; /* module name */ - const Elf_Phdr *dlpi_phdr; /* pointer to module's phdr */ - Elf_Half dlpi_phnum; /* number of entries in phdr */ - unsigned long long int dlpi_adds; /* total # of loads */ - unsigned long long int dlpi_subs; /* total # of unloads */ - size_t dlpi_tls_modid; - void *dlpi_tls_data; -}; - -__BEGIN_DECLS - -typedef int (*__dl_iterate_hdr_callback)(struct dl_phdr_info *, size_t, - void *); -extern int dl_iterate_phdr(__dl_iterate_hdr_callback, void *); - -__END_DECLS - -#endif /* _SYS_LINK_ELF_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc/sys/queue.h b/repos/os/src/lib/ldso/include/libc/sys/queue.h deleted file mode 100644 index 74cafacf1..000000000 --- a/repos/os/src/lib/ldso/include/libc/sys/queue.h +++ /dev/null @@ -1,627 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)queue.h 8.5 (Berkeley) 8/20/94 - * $FreeBSD: src/sys/sys/queue.h,v 1.69 2008/05/22 14:40:03 ed Exp $ - */ - -#ifndef _SYS_QUEUE_H_ -#define _SYS_QUEUE_H_ - -#include - -/* - * This file defines four types of data structures: singly-linked lists, - * singly-linked tail queues, lists and tail queues. - * - * A singly-linked list is headed by a single forward pointer. The elements - * are singly linked for minimum space and pointer manipulation overhead at - * the expense of O(n) removal for arbitrary elements. New elements can be - * added to the list after an existing element or at the head of the list. - * Elements being removed from the head of the list should use the explicit - * macro for this purpose for optimum efficiency. A singly-linked list may - * only be traversed in the forward direction. Singly-linked lists are ideal - * for applications with large datasets and few or no removals or for - * implementing a LIFO queue. - * - * A singly-linked tail queue is headed by a pair of pointers, one to the - * head of the list and the other to the tail of the list. The elements are - * singly linked for minimum space and pointer manipulation overhead at the - * expense of O(n) removal for arbitrary elements. New elements can be added - * to the list after an existing element, at the head of the list, or at the - * end of the list. Elements being removed from the head of the tail queue - * should use the explicit macro for this purpose for optimum efficiency. - * A singly-linked tail queue may only be traversed in the forward direction. - * Singly-linked tail queues are ideal for applications with large datasets - * and few or no removals or for implementing a FIFO queue. - * - * A list is headed by a single forward pointer (or an array of forward - * pointers for a hash table header). The elements are doubly linked - * so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before - * or after an existing element or at the head of the list. A list - * may only be traversed in the forward direction. - * - * A tail queue is headed by a pair of pointers, one to the head of the - * list and the other to the tail of the list. The elements are doubly - * linked so that an arbitrary element can be removed without a need to - * traverse the list. New elements can be added to the list before or - * after an existing element, at the head of the list, or at the end of - * the list. A tail queue may be traversed in either direction. - * - * For details on the use of these macros, see the queue(3) manual page. - * - * - * SLIST LIST STAILQ TAILQ - * _HEAD + + + + - * _HEAD_INITIALIZER + + + + - * _ENTRY + + + + - * _INIT + + + + - * _EMPTY + + + + - * _FIRST + + + + - * _NEXT + + + + - * _PREV - - - + - * _LAST - - + + - * _FOREACH + + + + - * _FOREACH_SAFE + + + + - * _FOREACH_REVERSE - - - + - * _FOREACH_REVERSE_SAFE - - - + - * _INSERT_HEAD + + + + - * _INSERT_BEFORE - + - + - * _INSERT_AFTER + + + + - * _INSERT_TAIL - - + + - * _CONCAT - - + + - * _REMOVE_HEAD + - + - - * _REMOVE_NEXT + - + - - * _REMOVE + + + + - * - */ -#ifdef QUEUE_MACRO_DEBUG -/* Store the last 2 places the queue element or head was altered */ -struct qm_trace { - char * lastfile; - int lastline; - char * prevfile; - int prevline; -}; - -#define TRACEBUF struct qm_trace trace; -#define TRASHIT(x) do {(x) = (void *)-1;} while (0) - -#define QMD_TRACE_HEAD(head) do { \ - (head)->trace.prevline = (head)->trace.lastline; \ - (head)->trace.prevfile = (head)->trace.lastfile; \ - (head)->trace.lastline = __LINE__; \ - (head)->trace.lastfile = __FILE__; \ -} while (0) - -#define QMD_TRACE_ELEM(elem) do { \ - (elem)->trace.prevline = (elem)->trace.lastline; \ - (elem)->trace.prevfile = (elem)->trace.lastfile; \ - (elem)->trace.lastline = __LINE__; \ - (elem)->trace.lastfile = __FILE__; \ -} while (0) - -#else -#define QMD_TRACE_ELEM(elem) -#define QMD_TRACE_HEAD(head) -#define TRACEBUF -#define TRASHIT(x) -#endif /* QUEUE_MACRO_DEBUG */ - -/* - * Singly-linked List declarations. - */ -#define SLIST_HEAD(name, type) \ -struct name { \ - struct type *slh_first; /* first element */ \ -} - -#define SLIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define SLIST_ENTRY(type) \ -struct { \ - struct type *sle_next; /* next element */ \ -} - -/* - * Singly-linked List functions. - */ -#define SLIST_EMPTY(head) ((head)->slh_first == NULL) - -#define SLIST_FIRST(head) ((head)->slh_first) - -#define SLIST_FOREACH(var, head, field) \ - for ((var) = SLIST_FIRST((head)); \ - (var); \ - (var) = SLIST_NEXT((var), field)) - -#define SLIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = SLIST_FIRST((head)); \ - (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ - for ((varp) = &SLIST_FIRST((head)); \ - ((var) = *(varp)) != NULL; \ - (varp) = &SLIST_NEXT((var), field)) - -#define SLIST_INIT(head) do { \ - SLIST_FIRST((head)) = NULL; \ -} while (0) - -#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ - SLIST_NEXT((slistelm), field) = (elm); \ -} while (0) - -#define SLIST_INSERT_HEAD(head, elm, field) do { \ - SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ - SLIST_FIRST((head)) = (elm); \ -} while (0) - -#define SLIST_NEXT(elm, field) ((elm)->field.sle_next) - -#define SLIST_REMOVE(head, elm, type, field) do { \ - if (SLIST_FIRST((head)) == (elm)) { \ - SLIST_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = SLIST_FIRST((head)); \ - while (SLIST_NEXT(curelm, field) != (elm)) \ - curelm = SLIST_NEXT(curelm, field); \ - SLIST_REMOVE_NEXT(head, curelm, field); \ - } \ - TRASHIT((elm)->field.sle_next); \ -} while (0) - -#define SLIST_REMOVE_NEXT(head, elm, field) do { \ - SLIST_NEXT(elm, field) = \ - SLIST_NEXT(SLIST_NEXT(elm, field), field); \ -} while (0) - -#define SLIST_REMOVE_HEAD(head, field) do { \ - SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ -} while (0) - -/* - * Singly-linked Tail queue declarations. - */ -#define STAILQ_HEAD(name, type) \ -struct name { \ - struct type *stqh_first;/* first element */ \ - struct type **stqh_last;/* addr of last next element */ \ -} - -#define STAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).stqh_first } - -#define STAILQ_ENTRY(type) \ -struct { \ - struct type *stqe_next; /* next element */ \ -} - -/* - * Singly-linked Tail queue functions. - */ -#define STAILQ_CONCAT(head1, head2) do { \ - if (!STAILQ_EMPTY((head2))) { \ - *(head1)->stqh_last = (head2)->stqh_first; \ - (head1)->stqh_last = (head2)->stqh_last; \ - STAILQ_INIT((head2)); \ - } \ -} while (0) - -#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) - -#define STAILQ_FIRST(head) ((head)->stqh_first) - -#define STAILQ_FOREACH(var, head, field) \ - for((var) = STAILQ_FIRST((head)); \ - (var); \ - (var) = STAILQ_NEXT((var), field)) - - -#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = STAILQ_FIRST((head)); \ - (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define STAILQ_INIT(head) do { \ - STAILQ_FIRST((head)) = NULL; \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_NEXT((tqelm), field) = (elm); \ -} while (0) - -#define STAILQ_INSERT_HEAD(head, elm, field) do { \ - if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ - STAILQ_FIRST((head)) = (elm); \ -} while (0) - -#define STAILQ_INSERT_TAIL(head, elm, field) do { \ - STAILQ_NEXT((elm), field) = NULL; \ - *(head)->stqh_last = (elm); \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -#define STAILQ_LAST(head, type, field) \ - (STAILQ_EMPTY((head)) ? \ - NULL : \ - ((struct type *)(void *) \ - ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) - -#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) - -#define STAILQ_REMOVE(head, elm, type, field) do { \ - if (STAILQ_FIRST((head)) == (elm)) { \ - STAILQ_REMOVE_HEAD((head), field); \ - } \ - else { \ - struct type *curelm = STAILQ_FIRST((head)); \ - while (STAILQ_NEXT(curelm, field) != (elm)) \ - curelm = STAILQ_NEXT(curelm, field); \ - STAILQ_REMOVE_NEXT(head, curelm, field); \ - } \ - TRASHIT((elm)->field.stqe_next); \ -} while (0) - -#define STAILQ_REMOVE_HEAD(head, field) do { \ - if ((STAILQ_FIRST((head)) = \ - STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ - (head)->stqh_last = &STAILQ_FIRST((head)); \ -} while (0) - -#define STAILQ_REMOVE_NEXT(head, elm, field) do { \ - if ((STAILQ_NEXT(elm, field) = \ - STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ - (head)->stqh_last = &STAILQ_NEXT((elm), field); \ -} while (0) - -/* - * List declarations. - */ -#define LIST_HEAD(name, type) \ -struct name { \ - struct type *lh_first; /* first element */ \ -} - -#define LIST_HEAD_INITIALIZER(head) \ - { NULL } - -#define LIST_ENTRY(type) \ -struct { \ - struct type *le_next; /* next element */ \ - struct type **le_prev; /* address of previous next element */ \ -} - -/* - * List functions. - */ - -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_LIST_CHECK_HEAD(head, field) do { \ - if (LIST_FIRST((head)) != NULL && \ - LIST_FIRST((head))->field.le_prev != \ - &LIST_FIRST((head))) \ - panic("Bad list head %p first->prev != head", (head)); \ -} while (0) - -#define QMD_LIST_CHECK_NEXT(elm, field) do { \ - if (LIST_NEXT((elm), field) != NULL && \ - LIST_NEXT((elm), field)->field.le_prev != \ - &((elm)->field.le_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -#define QMD_LIST_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.le_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_LIST_CHECK_HEAD(head, field) -#define QMD_LIST_CHECK_NEXT(elm, field) -#define QMD_LIST_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define LIST_EMPTY(head) ((head)->lh_first == NULL) - -#define LIST_FIRST(head) ((head)->lh_first) - -#define LIST_FOREACH(var, head, field) \ - for ((var) = LIST_FIRST((head)); \ - (var); \ - (var) = LIST_NEXT((var), field)) - -#define LIST_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = LIST_FIRST((head)); \ - (var) && ((tvar) = LIST_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define LIST_INIT(head) do { \ - LIST_FIRST((head)) = NULL; \ -} while (0) - -#define LIST_INSERT_AFTER(listelm, elm, field) do { \ - QMD_LIST_CHECK_NEXT(listelm, field); \ - if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ - LIST_NEXT((listelm), field)->field.le_prev = \ - &LIST_NEXT((elm), field); \ - LIST_NEXT((listelm), field) = (elm); \ - (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ -} while (0) - -#define LIST_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_LIST_CHECK_PREV(listelm, field); \ - (elm)->field.le_prev = (listelm)->field.le_prev; \ - LIST_NEXT((elm), field) = (listelm); \ - *(listelm)->field.le_prev = (elm); \ - (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ -} while (0) - -#define LIST_INSERT_HEAD(head, elm, field) do { \ - QMD_LIST_CHECK_HEAD((head), field); \ - if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ - LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ - LIST_FIRST((head)) = (elm); \ - (elm)->field.le_prev = &LIST_FIRST((head)); \ -} while (0) - -#define LIST_NEXT(elm, field) ((elm)->field.le_next) - -#define LIST_REMOVE(elm, field) do { \ - QMD_LIST_CHECK_NEXT(elm, field); \ - QMD_LIST_CHECK_PREV(elm, field); \ - if (LIST_NEXT((elm), field) != NULL) \ - LIST_NEXT((elm), field)->field.le_prev = \ - (elm)->field.le_prev; \ - *(elm)->field.le_prev = LIST_NEXT((elm), field); \ - TRASHIT((elm)->field.le_next); \ - TRASHIT((elm)->field.le_prev); \ -} while (0) - -/* - * Tail queue declarations. - */ -#define TAILQ_HEAD(name, type) \ -struct name { \ - struct type *tqh_first; /* first element */ \ - struct type **tqh_last; /* addr of last next element */ \ - TRACEBUF \ -} - -#define TAILQ_HEAD_INITIALIZER(head) \ - { NULL, &(head).tqh_first } - -#define TAILQ_ENTRY(type) \ -struct { \ - struct type *tqe_next; /* next element */ \ - struct type **tqe_prev; /* address of previous next element */ \ - TRACEBUF \ -} - -/* - * Tail queue functions. - */ -#if (defined(_KERNEL) && defined(INVARIANTS)) -#define QMD_TAILQ_CHECK_HEAD(head, field) do { \ - if (!TAILQ_EMPTY(head) && \ - TAILQ_FIRST((head))->field.tqe_prev != \ - &TAILQ_FIRST((head))) \ - panic("Bad tailq head %p first->prev != head", (head)); \ -} while (0) - -#define QMD_TAILQ_CHECK_TAIL(head, field) do { \ - if (*(head)->tqh_last != NULL) \ - panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ -} while (0) - -#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ - if (TAILQ_NEXT((elm), field) != NULL && \ - TAILQ_NEXT((elm), field)->field.tqe_prev != \ - &((elm)->field.tqe_next)) \ - panic("Bad link elm %p next->prev != elm", (elm)); \ -} while (0) - -#define QMD_TAILQ_CHECK_PREV(elm, field) do { \ - if (*(elm)->field.tqe_prev != (elm)) \ - panic("Bad link elm %p prev->next != elm", (elm)); \ -} while (0) -#else -#define QMD_TAILQ_CHECK_HEAD(head, field) -#define QMD_TAILQ_CHECK_TAIL(head, headname) -#define QMD_TAILQ_CHECK_NEXT(elm, field) -#define QMD_TAILQ_CHECK_PREV(elm, field) -#endif /* (_KERNEL && INVARIANTS) */ - -#define TAILQ_CONCAT(head1, head2, field) do { \ - if (!TAILQ_EMPTY(head2)) { \ - *(head1)->tqh_last = (head2)->tqh_first; \ - (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ - (head1)->tqh_last = (head2)->tqh_last; \ - TAILQ_INIT((head2)); \ - QMD_TRACE_HEAD(head1); \ - QMD_TRACE_HEAD(head2); \ - } \ -} while (0) - -#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) - -#define TAILQ_FIRST(head) ((head)->tqh_first) - -#define TAILQ_FOREACH(var, head, field) \ - for ((var) = TAILQ_FIRST((head)); \ - (var); \ - (var) = TAILQ_NEXT((var), field)) - -#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ - for ((var) = TAILQ_FIRST((head)); \ - (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ - (var) = (tvar)) - -#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var); \ - (var) = TAILQ_PREV((var), headname, field)) - -#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ - for ((var) = TAILQ_LAST((head), headname); \ - (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ - (var) = (tvar)) - -#define TAILQ_INIT(head) do { \ - TAILQ_FIRST((head)) = NULL; \ - (head)->tqh_last = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ -} while (0) - -#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ - QMD_TAILQ_CHECK_NEXT(listelm, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else { \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - } \ - TAILQ_NEXT((listelm), field) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ - QMD_TAILQ_CHECK_PREV(listelm, field); \ - (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ - TAILQ_NEXT((elm), field) = (listelm); \ - *(listelm)->field.tqe_prev = (elm); \ - (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_ELEM(&(elm)->field); \ - QMD_TRACE_ELEM(&listelm->field); \ -} while (0) - -#define TAILQ_INSERT_HEAD(head, elm, field) do { \ - QMD_TAILQ_CHECK_HEAD(head, field); \ - if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ - TAILQ_FIRST((head))->field.tqe_prev = \ - &TAILQ_NEXT((elm), field); \ - else \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - TAILQ_FIRST((head)) = (elm); \ - (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_INSERT_TAIL(head, elm, field) do { \ - QMD_TAILQ_CHECK_TAIL(head, field); \ - TAILQ_NEXT((elm), field) = NULL; \ - (elm)->field.tqe_prev = (head)->tqh_last; \ - *(head)->tqh_last = (elm); \ - (head)->tqh_last = &TAILQ_NEXT((elm), field); \ - QMD_TRACE_HEAD(head); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - -#define TAILQ_LAST(head, headname) \ - (*(((struct headname *)((head)->tqh_last))->tqh_last)) - -#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) - -#define TAILQ_PREV(elm, headname, field) \ - (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) - -#define TAILQ_REMOVE(head, elm, field) do { \ - QMD_TAILQ_CHECK_NEXT(elm, field); \ - QMD_TAILQ_CHECK_PREV(elm, field); \ - if ((TAILQ_NEXT((elm), field)) != NULL) \ - TAILQ_NEXT((elm), field)->field.tqe_prev = \ - (elm)->field.tqe_prev; \ - else { \ - (head)->tqh_last = (elm)->field.tqe_prev; \ - QMD_TRACE_HEAD(head); \ - } \ - *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ - TRASHIT((elm)->field.tqe_next); \ - TRASHIT((elm)->field.tqe_prev); \ - QMD_TRACE_ELEM(&(elm)->field); \ -} while (0) - - -#ifdef _KERNEL - -/* - * XXX insque() and remque() are an old way of handling certain queues. - * They bogusly assumes that all queue heads look alike. - */ - -struct quehead { - struct quehead *qh_link; - struct quehead *qh_rlink; -}; - -#ifdef __CC_SUPPORTS___INLINE - -static __inline void -insque(void *a, void *b) -{ - struct quehead *element = (struct quehead *)a, - *head = (struct quehead *)b; - - element->qh_link = head->qh_link; - element->qh_rlink = head; - head->qh_link = element; - element->qh_link->qh_rlink = element; -} - -static __inline void -remque(void *a) -{ - struct quehead *element = (struct quehead *)a; - - element->qh_link->qh_rlink = element->qh_rlink; - element->qh_rlink->qh_link = element->qh_link; - element->qh_rlink = 0; -} - -#else /* !__CC_SUPPORTS___INLINE */ - -void insque(void *a, void *b); -void remque(void *a); - -#endif /* __CC_SUPPORTS___INLINE */ - -#endif /* _KERNEL */ - -#endif /* !_SYS_QUEUE_H_ */ diff --git a/repos/os/src/lib/ldso/include/libc_emu/err.h b/repos/os/src/lib/ldso/include/libc_emu/err.h deleted file mode 100644 index 51dc9995d..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/err.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * \brief err.h prototypes required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _ERR_H_ -#define _ERR_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - -#define err errx -void errx(int eval, const char *fmt, ...) __attribute__((noreturn)); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/repos/os/src/lib/ldso/include/libc_emu/errno.h b/repos/os/src/lib/ldso/include/libc_emu/errno.h deleted file mode 100644 index 489c21b96..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/errno.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * \brief Dummy file - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ diff --git a/repos/os/src/lib/ldso/include/libc_emu/fcntl.h b/repos/os/src/lib/ldso/include/libc_emu/fcntl.h deleted file mode 100644 index 046bde62f..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/fcntl.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * \brief fcntl.h prototypes/definitions required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _FCNTL_H_ -#define _FCNTL_H_ - -enum flags { - O_RDONLY = 0x0 -}; - -int open(const char *pathname, int flags); - -#endif //_FCNTL_H_ diff --git a/repos/os/src/lib/ldso/include/libc_emu/ldso_types.h b/repos/os/src/lib/ldso/include/libc_emu/ldso_types.h deleted file mode 100644 index 4cf893e87..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/ldso_types.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * \brief ldso type definitions - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _LDSO_TYPES_H_ -#define _LDSO_TYPES_H_ - -#ifndef __ASSEMBLY__ -//from gcc (defines size_t) -#include -#include - -typedef genode_uint16_t uint16_t; -typedef genode_uint32_t uint32_t; -typedef genode_uint64_t uint64_t; - -typedef genode_int32_t int32_t; -typedef genode_int64_t int64_t; - -typedef uint32_t u_int32_t; -typedef unsigned long u_long; - -typedef char * caddr_t; -typedef uint32_t dev_t; -typedef uint32_t ino_t; -typedef int64_t off_t; -typedef int64_t ssize_t; - -typedef int FILE; - -typedef unsigned long uintptr_t; //ARM reloc.c, only -extern int *stdout, *stdin, *stderr, errno; - -struct stat { - dev_t st_dev; - ino_t st_ino; -}; - -enum statfs_flags { - MNT_NOEXEC = 0x4 -}; - -struct statfs { - uint32_t f_flags; - char f_mntonname[1]; -}; - -enum { - STDOUT_FILENO, -}; -#endif //__ASSEMBLY__ -#endif //_LDSO_TYPES_H_ - - diff --git a/repos/os/src/lib/ldso/include/libc_emu/link.h b/repos/os/src/lib/ldso/include/libc_emu/link.h deleted file mode 100644 index 085b93560..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/link.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * \brief link.h prototypes/definitions required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include diff --git a/repos/os/src/lib/ldso/include/libc_emu/machine/atomic.h b/repos/os/src/lib/ldso/include/libc_emu/machine/atomic.h deleted file mode 100644 index 114be2b87..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/machine/atomic.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * \brief Dummy file - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - diff --git a/repos/os/src/lib/ldso/include/libc_emu/machine/segments.h b/repos/os/src/lib/ldso/include/libc_emu/machine/segments.h deleted file mode 100644 index 489c21b96..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/machine/segments.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * \brief Dummy file - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ diff --git a/repos/os/src/lib/ldso/include/libc_emu/machine/sysarch.h b/repos/os/src/lib/ldso/include/libc_emu/machine/sysarch.h deleted file mode 100644 index 87edbc5f3..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/machine/sysarch.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * \brief sysarch.h dummies required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _MACHINE_SYSARCH_H_ -#define _MACHINE_SYSARCH_H_ - -static inline -int i386_set_gsbase(void *addr) { return 0; } - -inline void amd64_set_fsbase(void *p) -{} -#endif //_MACHINE_SYSARCH_H_ - diff --git a/repos/os/src/lib/ldso/include/libc_emu/stdio.h b/repos/os/src/lib/ldso/include/libc_emu/stdio.h deleted file mode 100644 index 924695ea9..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/stdio.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * \brief stdio.h prototypes/definitions required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef STDIO_H -#define STDIO_H - -#include -#include - -//implementations -#ifdef __cplusplus -extern "C" { -#endif -int printf(const char *format, ...); -int vprintf(const char *format, va_list ap); -int vsnprintf(char *str, size_t size, const char *format, va_list ap); -int putc(int c, int *stream); -int putchar(int c); -int vfprintf(int *stream, const char *format, va_list ap); -#ifdef __cplusplus -} -#endif - -//dummies -static inline int fflush(int *stream) {(void)stream; return 0;} -static inline void exit(int status) __attribute__((noreturn)); - -static inline void exit(int status) -{ - while(1) ; -} - -#endif //STDIO_H - diff --git a/repos/os/src/lib/ldso/include/libc_emu/stdlib.h b/repos/os/src/lib/ldso/include/libc_emu/stdlib.h deleted file mode 100644 index 9c404e669..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/stdlib.h +++ /dev/null @@ -1,43 +0,0 @@ -/* - * \brief stdlib.h prototypes/definitions required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef STDLIB_H -#define STDLIB_H - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -void *malloc(size_t size); -void free(void *ptr); -void *calloc(size_t nmemb, size_t size); -char *getenv(const char *); - -#ifdef __cplusplus -} -#endif - -// gcc built-in -void *alloca(size_t size); - -static inline -void abort(void) {} - -static inline -int unsetenv(const char *name) -{ - return 0; -} -#endif //STDLIB_H diff --git a/repos/os/src/lib/ldso/include/libc_emu/string.h b/repos/os/src/lib/ldso/include/libc_emu/string.h deleted file mode 100644 index 3a47dd7b1..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/string.h +++ /dev/null @@ -1,142 +0,0 @@ -/* - * \brief string.h prototypes/definitions required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _STRING_H_ -#define _STRING_H_ - -#include -#include -#include - -#define alloca(size) __builtin_alloca ((size)) - -/* - * prototypes - */ -#ifdef __cplusplus -extern "C" { -#endif -void bzero(void *s, size_t n); - -void *memcpy(void *dest, const void *src, size_t n); -void *memset(void *s, int c, size_t n); - -int strcmp(const char *s1, const char *s2); -int strncmp(const char *s1, const char *s2, size_t n); - -char *strncpy(char *dst, const char *src, size_t n); -size_t strlen(const char *s); -#ifdef __cplusplus -} -#endif - - -/* - * dummies - */ -static inline -const char *strerror(int errnum) { (void)errnum; return ""; } - - -static inline -size_t strspn(const char *s, const char *accept) -{ - extern int debug; - if (debug) - printf("Warning: %s called\n", __func__); - return 0; -} - -static inline -size_t strcspn(const char *s, const char *reject) -{ - extern int debug; - if (debug) - printf("Warning: %s called\n", __func__); - return 0; -} - -static inline -char *strchr(const char *s, int c) -{ - extern int debug; - if (debug) - printf("Warning: %s called\n", __func__); - return NULL; -} - -static inline -char *strrchr(const char *s, int c) -{ - extern int debug; - if (debug) - printf("Warning: %s called\n", __func__); - return NULL; -} - - -/* - * inlines - */ -static inline -char * -strcpy(char *to, const char *from) -{ - char *save = to; - - for (; (*to = *from); ++from, ++to); - return(save); -} - -static inline -char * -strdup(const char *str) -{ - size_t len; - char *copy; - - len = strlen(str) + 1; - if ((copy = (char*)malloc(len)) == NULL) - return (NULL); - memcpy(copy, str, len); - return (copy); -} - -static inline -size_t -strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0) { - while (--n != 0) { - if ((*d++ = *s++) == '\0') - break; - } - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ -} - -#endif // _STRING_H_ diff --git a/repos/os/src/lib/ldso/include/libc_emu/sys/_types.h b/repos/os/src/lib/ldso/include/libc_emu/sys/_types.h deleted file mode 100644 index 26de39fe2..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/sys/_types.h +++ /dev/null @@ -1,25 +0,0 @@ -/* - * \brief C/C++ prototype macros - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SYS_TYPES_H_ -#define _SYS_TYPES_H_ - -#if defined(__cplusplus) -#define __BEGIN_DECLS extern "C" { -#define __END_DECLS } -#else -#define __BEGIN_DECLS -#define __END_DECLS -#endif - -#endif //_SYS_TYPES_H_ diff --git a/repos/os/src/lib/ldso/include/libc_emu/sys/ktrace.h b/repos/os/src/lib/ldso/include/libc_emu/sys/ktrace.h deleted file mode 100644 index a463eb674..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/sys/ktrace.h +++ /dev/null @@ -1,20 +0,0 @@ -/* - * \brief kctrace.h dummies required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _SYS_KTRACE_H_ -#define _SYS_KTRACE_H_ - -static inline -int utrace(const void *addr, size_t len) { return 0;} - -#endif //_SYS_KTRACE_H_ diff --git a/repos/os/src/lib/ldso/include/libc_emu/sys/mman.h b/repos/os/src/lib/ldso/include/libc_emu/sys/mman.h deleted file mode 100644 index 8294a26e0..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/sys/mman.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * \brief mman.h prototypes/definitions required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef MMAN_H -#define MMAN_H - -#include - -enum prot { - PROT_NONE, - PROT_READ, - PROT_WRITE, - PROT_EXEC = 0x4, -}; - -enum map { - MAP_PRIVATE = 0x2, - MAP_FIXED = 0x10, - MAP_ANON = 0x1000, - MAP_NOCORE = 0x20000, - MAP_LDSO = 0x80000000, /* special flag if LDSO has not been relocated, yet */ -}; - -#define MAP_FAILED ((void *)-1) - -#ifdef __cplusplus -extern "C" { -#endif - -void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); -int munmap(void *addr, size_t length); - -#ifdef __cplusplus -} -#endif - - -//dummies - -static inline -int mprotect(const void *addr, size_t len, int prot) { return 0; } - -#endif //MMAN_H diff --git a/repos/os/src/lib/ldso/include/libc_emu/sys/mount.h b/repos/os/src/lib/ldso/include/libc_emu/sys/mount.h deleted file mode 100644 index 489c21b96..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/sys/mount.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * \brief Dummy file - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ diff --git a/repos/os/src/lib/ldso/include/libc_emu/sys/param.h b/repos/os/src/lib/ldso/include/libc_emu/sys/param.h deleted file mode 100644 index 4d99324f0..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/sys/param.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * \brief param.h prototypes/definitions required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef PARAM_H -#define PARAM_H - -//XXX cbass: hard code for now -#define PAGE_SIZE 0x1000 -#define PAGE_MASK ~(PAGE_SIZE - 1) -#define PATH_MAX 1024 -#define MAXPATHLEN PATH_MAX - -static inline -unsigned long round_page(unsigned long page) -{ - return ((page + PAGE_SIZE - 1) & PAGE_MASK); -} - -static inline -unsigned long trunc_page(unsigned long page) -{ - return (page & PAGE_MASK); -} - -#endif //PARAM_H diff --git a/repos/os/src/lib/ldso/include/libc_emu/sys/queue.h b/repos/os/src/lib/ldso/include/libc_emu/sys/queue.h deleted file mode 100644 index 489c21b96..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/sys/queue.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * \brief Dummy file - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ diff --git a/repos/os/src/lib/ldso/include/libc_emu/sys/stat.h b/repos/os/src/lib/ldso/include/libc_emu/sys/stat.h deleted file mode 100644 index 20edca662..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/sys/stat.h +++ /dev/null @@ -1,6 +0,0 @@ - -/* - * \brief Dummy file - * \author Sebastian Sumpf - * \date 2009-10-26 - */ diff --git a/repos/os/src/lib/ldso/include/libc_emu/sys/types.h b/repos/os/src/lib/ldso/include/libc_emu/sys/types.h deleted file mode 100644 index 114be2b87..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/sys/types.h +++ /dev/null @@ -1,13 +0,0 @@ -/* - * \brief Dummy file - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - diff --git a/repos/os/src/lib/ldso/include/libc_emu/sys/uio.h b/repos/os/src/lib/ldso/include/libc_emu/sys/uio.h deleted file mode 100644 index 489c21b96..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/sys/uio.h +++ /dev/null @@ -1,12 +0,0 @@ -/* - * \brief Dummy file - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ diff --git a/repos/os/src/lib/ldso/include/libc_emu/unistd.h b/repos/os/src/lib/ldso/include/libc_emu/unistd.h deleted file mode 100644 index 9b7e0e401..000000000 --- a/repos/os/src/lib/ldso/include/libc_emu/unistd.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * \brief unistd.h prototypes/definitions required by ldso - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#ifndef _UNISTD_H_ -#define _UNISTD_H_ - -#ifdef __cplusplus -extern "C" { -#endif - -ssize_t read(int fd, void *buf, size_t count); -ssize_t write(int fd, const void *buf, size_t count); - -#ifdef __cplusplus -} -#endif - -static inline -int issetugid(void) { return 1; } - -static inline -int close(int fd) { return 0; } - -void *file_phdr(const char *, void *); - -enum whence { - SEEK_SET -}; - -static inline -off_t lseek(int fd, off_t offset, int whence) { return 0; } - -static inline -int fstat(int fd, struct stat *buf) -{ - buf->st_dev = fd + 1; - buf->st_ino = fd + 1; - return 0; -} - -static inline -int fstatfs(int fd, struct statfs *buf) -{ - buf->f_flags = 0; - buf->f_mntonname[0] = '\0'; - return 0; -} - -enum access_mode { - F_OK -}; - -static inline -int access(const char *pathname, int mode) -{ - return 0; -} - -#endif //_UNISTD_H_ diff --git a/repos/os/src/lib/ldso/ldso_types.c b/repos/os/src/lib/ldso/ldso_types.c deleted file mode 100644 index b320d2cf1..000000000 --- a/repos/os/src/lib/ldso/ldso_types.c +++ /dev/null @@ -1,17 +0,0 @@ -/* - * \brief libc stdandard file handles - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -int *stdin = 0; -int *stdout = 0; -int *stderr = 0; -int errno = 0; diff --git a/repos/os/src/lib/ldso/lock.cc b/repos/os/src/lib/ldso/lock.cc deleted file mode 100644 index 817e2edd1..000000000 --- a/repos/os/src/lib/ldso/lock.cc +++ /dev/null @@ -1,82 +0,0 @@ -/* - * \brief Map rtld lock implementation to Genode primitives - * \author Sebastian Sumpf - * \date 2011-05-17 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include "rtld_lock.h" -#include -#include -#include -/** - * Simple read/write lock implementation - */ -struct rtld_lock { - - Genode::Lock *_lock; - Genode::Lock _inc; - - int _read; - - rtld_lock(Genode::Lock *lock) : _lock(lock), _read(0) {} - - void read_lock() - { - Genode::Lock::Guard guard(_inc); - if(++_read == 1) - lock(); - } - - void read_unlock() - { - Genode::Lock::Guard guard(_inc); - if (--_read == 0) - unlock(); - } - - void lock() { _lock->lock(); } - void unlock() { _lock->unlock(); } -}; - -static Genode::Lock _gbind_lock; -static Genode::Lock _gphdr_lock; - -static rtld_lock _bind_lock(&_gbind_lock); -static rtld_lock _phdr_lock(&_gphdr_lock); - -/* the two locks used within rtld */ -rtld_lock_t rtld_bind_lock = &_bind_lock; -rtld_lock_t rtld_phdr_lock = &_phdr_lock; - - -extern "C" int rlock_acquire(rtld_lock_t lock) -{ - lock->read_lock(); - return 1; -} - - -extern "C" int wlock_acquire(rtld_lock_t lock) -{ - lock->lock(); - return 1; -} - - -extern "C" void rlock_release(rtld_lock_t lock, int locked) -{ - lock->read_unlock(); -} - - -extern "C" void wlock_release(rtld_lock_t lock, int locked) -{ - lock->unlock(); -} diff --git a/repos/os/src/lib/ldso/main.c b/repos/os/src/lib/ldso/main.c deleted file mode 100644 index fe4450fe5..000000000 --- a/repos/os/src/lib/ldso/main.c +++ /dev/null @@ -1,94 +0,0 @@ -/* - * \brief libc startup code - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "file.h" - -typedef void (*func_ptr_type)(); - -func_ptr_type -_rtld(Elf_Addr *sp, func_ptr_type *exit_proc, Obj_Entry **objp); - -extern char **lx_environ; - -int call_program_main(void (*main_func)(void)); - - -static void *setup_stack(const char *name, long fd) -{ - char **p; - int env_count = 0; - char *env_end = '\0'; - - if (!lx_environ) { - lx_environ = &env_end; - } - - for (p = lx_environ; *p; p++, env_count++) ; - env_count++; - - long sp_argc = 1; - const char *sp_argv[] = { name, '\0' }; - char *sp_at[] = { - (char*)AT_BASE, //map base of ldso - (char*)LINK_ADDRESS, - (char*)AT_EXECFD, //file handle of program to load - (char*)fd, - (char*)AT_NULL, //AT terminator - }; - - void *sp = malloc(sizeof(sp_argc) + sizeof(sp_argv) + (env_count * sizeof(long)) - + sizeof(sp_at)); - void *sp_tmp = sp; - - //build dummy stack - memcpy(sp_tmp, &sp_argc, sizeof(sp_argc)); //argc - sp_tmp += sizeof(sp_argc); - memcpy(sp_tmp, sp_argv, sizeof(sp_argv)); //argv - sp_tmp += sizeof(sp_argv); - memcpy(sp_tmp, lx_environ, env_count * sizeof(long)); //environ - sp_tmp += env_count * sizeof(long); - memcpy(sp_tmp, sp_at, sizeof(sp_at)); //auxiliary vector - - return sp; -} - - -int main(int argc, char **argv) -{ - char *binary = "binary"; - char binary_buf[64]; - - Obj_Entry *objp; - func_ptr_type exit_proc; - - int fd = open(binary, O_RDONLY); - - /* find file name of file descriptor */ - if (!find_binary_name(fd, binary_buf, sizeof(binary_buf))) - binary = binary_buf; - - /* build dummy stack */ - void *sp = setup_stack(binary, (long)fd); - func_ptr_type const program_main = _rtld(sp, &exit_proc, &objp); - - /* call main function of dynamic program */ - return call_program_main(program_main); -} diff --git a/repos/os/src/lib/ldso/platform.c b/repos/os/src/lib/ldso/platform.c deleted file mode 100644 index 13d52d4a0..000000000 --- a/repos/os/src/lib/ldso/platform.c +++ /dev/null @@ -1,13 +0,0 @@ -/* - * \brief Dummy for architectures that don't have platform specific - * implementations - * \author Sebastian Sumpf - * \date 2011-07-29 - */ - -/* - * Copyright (C) 2011-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ diff --git a/repos/os/src/lib/ldso/rtld_dummies.c b/repos/os/src/lib/ldso/rtld_dummies.c deleted file mode 100644 index 07a42b38a..000000000 --- a/repos/os/src/lib/ldso/rtld_dummies.c +++ /dev/null @@ -1,54 +0,0 @@ -/* - * \brief ldso dummy function implementations - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include "rtld.h" -#include "rtld_machdep.h" - -inline int -lm_init (char *libmap_override) -{ - return 0; -} - -inline void -lm_fini (void) -{ -} - -inline char * -lm_find (const char *p, const char *f) -{ - return NULL; -} - - -inline void -_rtld_thread_init(struct RtldLockInfo *pli) -{ -} - -inline void -_rtld_atfork_pre(int *locks) -{ -} - -inline void -_rtld_atfork_post(int *locks) -{ -} - -inline void -lockdflt_init() -{ -} - diff --git a/repos/os/src/lib/ldso/stdio.cc b/repos/os/src/lib/ldso/stdio.cc deleted file mode 100644 index 22b65866e..000000000 --- a/repos/os/src/lib/ldso/stdio.cc +++ /dev/null @@ -1,63 +0,0 @@ -/* - * \brief libc I/O functions - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include - -extern "C" int printf(char const *format, ...) -{ - va_list args; - - va_start(args, format); - Genode::vprintf(format, args); - va_end(args); - - return 0; -} - -extern "C" inline -int vprintf(const char *format, va_list ap) -{ - Genode::vprintf(format, ap); - return 0; -} - -extern "C" -int vsnprintf(char *str, size_t size, const char *format, va_list ap) -{ - Genode::String_console sc(str, size); - sc.vprintf(format, ap); - return sc.len(); -} - -extern "C" -int vfprintf(int *stream, const char *format, va_list ap) -{ - (void)stream; - return vprintf(format, ap); -} - -extern "C" -int putchar(int c) { - printf("%c", c); - return c; -} - -extern "C" -int putc(int c, int *stream) -{ - (void)stream; - printf("%c", c); - return c; -} diff --git a/repos/os/src/lib/ldso/stdlib.cc b/repos/os/src/lib/ldso/stdlib.cc deleted file mode 100644 index a1d8532ea..000000000 --- a/repos/os/src/lib/ldso/stdlib.cc +++ /dev/null @@ -1,71 +0,0 @@ -/* - * \brief libc standard library calls - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include -#include - -typedef unsigned long Block_header; - -extern "C" void *malloc(size_t size) -{ - /* enforce size to be a multiple of 4 bytes */ - size = (size + 3) & ~3; - - /* - * We store the size of the allocation at the very - * beginning of the allocated block and return - * the subsequent address. This way, we can retrieve - * the size information when freeing the block. - */ - unsigned long real_size = size + sizeof(Block_header); - void *addr = 0; - if (!Genode::env()->heap()->alloc(real_size, &addr)) - return 0; - - *(Block_header *)addr = real_size; - return (Block_header *)addr + 1; -} - -extern "C" void *calloc(size_t nmemb, size_t size) -{ - void *ptr = malloc(size * nmemb); - - if (ptr) - Genode::memset(ptr, 0, size * nmemb); - - return ptr; -} - -extern "C" void free(void *ptr) -{ - if (!ptr) return; - - unsigned long *addr = ((unsigned long *)ptr) - 1; - Genode::env()->heap()->free(addr, *addr); -} - -/* - * We use getenv to configure ldso - */ -extern "C" char *getenv(const char *name) -{ -#ifdef DEBUG - if (!Genode::strcmp("LD_DEBUG", name)) - return (char*)"1"; -#endif - - if (!Genode::strcmp("LD_LIBRARY_PATH", name)) - return (char*)"/"; - return NULL; -} diff --git a/repos/os/src/lib/ldso/string.cc b/repos/os/src/lib/ldso/string.cc deleted file mode 100644 index 0f65d9bd1..000000000 --- a/repos/os/src/lib/ldso/string.cc +++ /dev/null @@ -1,57 +0,0 @@ -/* - * \brief libc string manipulation - * \author Sebastian Sumpf - * \date 2009-10-26 - */ - -/* - * Copyright (C) 2009-2013 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU General Public License version 2. - */ - -#include -#include - -extern "C" -void bzero(void *s, size_t n) -{ - Genode::memset(s, 0, n); -} - -extern "C" -int strcmp(const char *s1, const char *s2) -{ - return Genode::strcmp(s1, s2); -} - -extern "C" -int strncmp(const char *s1, const char *s2, size_t n) -{ - return Genode::strcmp(s1, s2, n); -} -extern "C" -size_t strlen(const char *s) -{ - return Genode::strlen(s); -} - -extern "C" -char *strncpy(char *dst, const char *src, size_t n) -{ - return Genode::strncpy(dst, src, n); -} - -extern "C" -void *memcpy(void *dest, const void *src, size_t n) -{ - return Genode::memcpy(dest, src, n); -} - -extern "C" -void *memset(void *s, int c, size_t n) -{ - void *r = Genode::memset(s, c, n); - return r; -} diff --git a/repos/os/src/lib/ldso/target.inc b/repos/os/src/lib/ldso/target.inc deleted file mode 100644 index e4fd6e138..000000000 --- a/repos/os/src/lib/ldso/target.inc +++ /dev/null @@ -1,63 +0,0 @@ -#note: leave empty to disable debugging output -DEBUG = - -include $(BASE_DIR)/mk/base-libs.mk -LIBS = $(BASE_LIBS) ldso-arch - -SRC_S = rtld_start.S -SRC_C = reloc.c rtld.c map_object.c xmalloc.c debug.c main.c \ - ldso_types.c rtld_dummies.c platform.c -SRC_CC = stdio.cc stdlib.cc file.cc err.cc string.cc lock.cc \ - test.cc environ.cc call_program_main.cc - -INC_DIR += $(DIR)/ \ - $(DIR)/contrib \ - $(DIR)/include/libc \ - $(DIR)/include/libc_emu - -# -# Change link address -# -# When LINK_ADDRESS does not match the memory address of ld.lib.so at runtime, -# GDB shows the following message when attaching to a dynamically linked Genode -# process (for example test-lwip_httpsrv): -# -# "warning: .dynamic section for ".../libcache/ld/ld.lib.so" is not at the -# expected address (wrong library or version mismatch?)" -# -# In this case, backtraces show no symbol names or source lines. -# -ifneq ($(filter linux, $(SPECS)),) -LINK_ADDRESS = 0x50000000 -else -LINK_ADDRESS = 0x30000 -endif - -ENTRY_POINT = _start - -D_OPTS += IN_RTLD __BSD_VISIBLE=1 LINK_ADDRESS=$(LINK_ADDRESS) $(RENAME_FUNCS) -D_OPTS += $(if $(DEBUG),DEBUG,) -D_OPTS := $(addprefix -D,$(D_OPTS)) - -CC_DEF += $(D_OPTS) -fno-builtin -CXX_DEF += $(D_OPTS) -AS_OPT += $(D_OPTS) - -CC_DEF += -Iinclude -include $(DIR)/include/libc_emu/ldso_types.h -LD_OPT += -Bsymbolic-functions -T$(DIR)/ldso.ld --version-script=$(DIR)/symbol.map - -CC_OPT += -Wno-unused-but-set-variable - -# -# Add context area script to Linux version of linker -# -ifneq ($(filter linux, $(SPECS)),) -LD_OPT += -T$(call select_from_repositories,src/platform/context_area.nostdlib.ld) -endif - -vpath %.cc $(DIR) -vpath %.c $(DIR)/contrib -vpath %.c $(DIR) - - -# vim:set ft=make: