mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-26 14:19:19 +00:00
parent
8738673625
commit
5a821d4c92
97
repos/base/include/base/shared_object.h
Normal file
97
repos/base/include/base/shared_object.h
Normal file
@ -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 <base/exception.h>
|
||||
#include <base/stdint.h>
|
||||
|
||||
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<typename T = void *> T lookup(const char *symbol) const
|
||||
{
|
||||
return static_cast<T>(_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_ */
|
6
repos/base/lib/mk/arm/ld.mk
Normal file
6
repos/base/lib/mk/arm/ld.mk
Normal file
@ -0,0 +1,6 @@
|
||||
REQUIRES = arm
|
||||
|
||||
include $(REP_DIR)/lib/mk/ldso.inc
|
||||
|
||||
INC_DIR += $(DIR)/arm
|
||||
vpath %.s $(DIR)/arm
|
22
repos/base/lib/mk/ldso.inc
Normal file
22
repos/base/lib/mk/ldso.inc
Normal file
@ -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
|
||||
|
6
repos/base/lib/mk/x86_32/ld.mk
Normal file
6
repos/base/lib/mk/x86_32/ld.mk
Normal file
@ -0,0 +1,6 @@
|
||||
REQUIRES = x86 32bit
|
||||
|
||||
include $(REP_DIR)/lib/mk/ldso.inc
|
||||
|
||||
INC_DIR += $(DIR)/x86_32
|
||||
vpath %.s $(DIR)/x86_32
|
6
repos/base/lib/mk/x86_64/ld.mk
Normal file
6
repos/base/lib/mk/x86_64/ld.mk
Normal file
@ -0,0 +1,6 @@
|
||||
REQUIRES = x86 64bit
|
||||
|
||||
include $(REP_DIR)/lib/mk/ldso.inc
|
||||
|
||||
INC_DIR += $(DIR)/x86_64
|
||||
vpath %.s $(DIR)/x86_64
|
@ -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
|
||||
|
@ -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 '<config>' 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:
|
||||
|
||||
!<!-- bind immediately, no library informations -->
|
||||
!<start name="dynamic_binary">
|
||||
! <resource name="RAM" quantum="1M" />
|
||||
! <config ld_bind_now="yes" ld_verbose="no">
|
||||
! </config>
|
||||
!</start>
|
||||
|
||||
Debugging dynamic binaries with GDB stubs
|
||||
-----------------------------------------
|
||||
|
||||
! # go to directory containing the binaries
|
||||
! cd <build/dir>/bin
|
||||
!
|
||||
! # start GDB with binary to debug
|
||||
! gdb <path to binary>
|
||||
! gdb <binary name>
|
||||
!
|
||||
! # 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
|
39
repos/base/src/lib/ldso/arm/jmp_slot.s
Normal file
39
repos/base/src/lib/ldso/arm/jmp_slot.s
Normal file
@ -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 */
|
118
repos/base/src/lib/ldso/arm/relocation.h
Normal file
118
repos/base/src/lib/ldso/arm/relocation.h
Normal file
@ -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 <relocation_generic.h>
|
||||
|
||||
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<Elf::Rel, DT_REL, R_JMPSLOT> Reloc_plt;
|
||||
typedef Reloc_jmpslot_generic<Elf::Rel, DT_REL, false> Reloc_jmpslot;
|
||||
typedef Reloc_bind_now_generic<Elf::Rel, DT_REL> 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<Elf::Rel>(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_ */
|
307
repos/base/src/lib/ldso/file.cc
Normal file
307
repos/base/src/lib/ldso/file.cc
Normal file
@ -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 <linker.h>
|
||||
|
||||
#include <base/allocator_avl.h>
|
||||
#include <os/attached_rom_dataspace.h>
|
||||
#include <rm_session/connection.h>
|
||||
#include <util/construct_at.h>
|
||||
|
||||
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<Rm_area>(placeholder, base);
|
||||
constructed = 1;
|
||||
}
|
||||
return reinterpret_cast<Rm_area *>(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;
|
||||
}
|
||||
|
458
repos/base/src/lib/ldso/include/elf.h
Normal file
458
repos/base/src/lib/ldso/include/elf.h
Normal file
@ -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 <base/stdint.h>
|
||||
|
||||
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_ */
|
230
repos/base/src/lib/ldso/include/linker.h
Normal file
230
repos/base/src/lib/ldso/include/linker.h
Normal file
@ -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 <base/exception.h>
|
||||
#include <base/env.h>
|
||||
#include <util/fifo.h>
|
||||
#include <util/misc_math.h>
|
||||
#include <util/string.h>
|
||||
#include <elf.h>
|
||||
#include <trace.h>
|
||||
|
||||
/**
|
||||
* 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 <typename T>
|
||||
static inline T trunc_page(T addr) {
|
||||
return addr & Genode::_align_mask((T)12); }
|
||||
|
||||
template <typename T>
|
||||
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<Object>::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 *>(_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<Dag>::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<Dag> * const dag,
|
||||
unsigned flags = 0);
|
||||
~Dag();
|
||||
|
||||
void load_needed(Genode::Fifo<Dag> * const dag, unsigned flags = 0);
|
||||
bool in_dag(char const *file, Genode::Fifo<Dag> *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_ */
|
176
repos/base/src/lib/ldso/include/relocation_generic.h
Normal file
176
repos/base/src/lib/ldso/include/relocation_generic.h
Normal file
@ -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 <linker.h>
|
||||
|
||||
namespace Linker
|
||||
{
|
||||
struct Plt_got;
|
||||
template <typename REL, unsigned TYPE, bool DIV> class Reloc_jmpslot_generic;
|
||||
template <typename REL, unsigned TYPE, unsigned JMPSLOT> struct Reloc_plt_generic;
|
||||
template <typename REL, unsigned TYPE> 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<typename REL, unsigned TYPE, unsigned JMPSLOT>
|
||||
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 <typename REL>
|
||||
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 <typename REL, unsigned TYPE, bool DIV>
|
||||
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 <typename REL, unsigned TYPE>
|
||||
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<REL, TYPE, false> reloc(dag, TYPE, pltrel, index);
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* _INCLUDE__RELOCATION_GENERIC_H_ */
|
38
repos/base/src/lib/ldso/include/trace.h
Normal file
38
repos/base/src/lib/ldso/include/trace.h
Normal file
@ -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 <l4/sys/ktrace.h>
|
||||
}
|
||||
#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_ */
|
@ -13,6 +13,6 @@
|
||||
SECTIONS
|
||||
{
|
||||
/* set ldso memory location */
|
||||
. = 0x30000 - SIZEOF_HEADERS;
|
||||
. = 0x30000;
|
||||
}
|
||||
|
1193
repos/base/src/lib/ldso/main.cc
Normal file
1193
repos/base/src/lib/ldso/main.cc
Normal file
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
* \brief Our implementation of __gnu_Unwind_Find_exidx
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \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
|
@ -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_*;
|
35
repos/base/src/lib/ldso/x86_32/jmp_slot.s
Normal file
35
repos/base/src/lib/ldso/x86_32/jmp_slot.s
Normal file
@ -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 */
|
98
repos/base/src/lib/ldso/x86_32/relocation.h
Normal file
98
repos/base/src/lib/ldso/x86_32/relocation.h
Normal file
@ -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 <relocation_generic.h>
|
||||
|
||||
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<Elf::Rel, DT_REL, R_JMPSLOT> Reloc_plt;
|
||||
typedef Reloc_jmpslot_generic<Elf::Rel, DT_REL, true> Reloc_jmpslot;
|
||||
typedef Reloc_bind_now_generic<Elf::Rel, DT_REL> 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<Elf::Rel>(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_ */
|
52
repos/base/src/lib/ldso/x86_64/jmp_slot.s
Normal file
52
repos/base/src/lib/ldso/x86_64/jmp_slot.s
Normal file
@ -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
|
104
repos/base/src/lib/ldso/x86_64/relocation.h
Normal file
104
repos/base/src/lib/ldso/x86_64/relocation.h
Normal file
@ -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 <relocation_generic.h>
|
||||
|
||||
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<Elf::Rela, DT_RELA, R_JMPSLOT> Reloc_plt;
|
||||
typedef Reloc_jmpslot_generic<Elf::Rela, DT_RELA, false> Reloc_jmpslot;
|
||||
typedef Reloc_bind_now_generic<Elf::Rela, DT_RELA> 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<Elf::Rela>(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_ */
|
@ -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) }
|
@ -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
|
||||
|
||||
|
5
repos/libports/lib/mk/test-ldso_lib_dl.mk
Normal file
5
repos/libports/lib/mk/test-ldso_lib_dl.mk
Normal file
@ -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
|
@ -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 {
|
||||
</default-route>
|
||||
<start name="test-ldso">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<config>
|
||||
<config ld_bind_now="no" ld_verbose="no">
|
||||
<libc stdout="/dev/log">
|
||||
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||
</libc>
|
||||
@ -27,7 +27,13 @@ install_config {
|
||||
</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] <warning: unsupported format string argument>
|
||||
[init -> test-ldso] <warning: unsupported format string argument>
|
||||
[init -> test-ldso] <warning: unsupported format string argument>
|
||||
[init -> test-ldso] <warning: unsupported format string argument>
|
||||
[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
|
||||
}
|
||||
|
120
repos/libports/src/lib/libc/dynamic_linker.cc
Normal file
120
repos/libports/src/lib/libc/dynamic_linker.cc
Normal file
@ -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 <base/env.h>
|
||||
#include <base/printf.h>
|
||||
#include <base/shared_object.h>
|
||||
#include <base/snprintf.h>
|
||||
|
||||
extern "C" {
|
||||
#include <dlfcn.h>
|
||||
}
|
||||
|
||||
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<Shared_object *>(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;
|
||||
}
|
1
repos/libports/src/test/ldso/dl/target.mk
Normal file
1
repos/libports/src/test/ldso/dl/target.mk
Normal file
@ -0,0 +1 @@
|
||||
LIBS = test-ldso_lib_dl
|
@ -16,6 +16,7 @@
|
||||
#define _TEST_LDSO_H_
|
||||
|
||||
void lib_1_test();
|
||||
void lib_1_good();
|
||||
void lib_1_exception();
|
||||
void lib_2_exception();
|
||||
|
||||
|
9
repos/libports/src/test/ldso/lib_dl.cc
Normal file
9
repos/libports/src/test/ldso/lib_dl.cc
Normal file
@ -0,0 +1,9 @@
|
||||
#include <base/printf.h>
|
||||
#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();
|
||||
}
|
@ -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<Object *>(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;
|
||||
}
|
||||
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -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
|
@ -1,22 +0,0 @@
|
||||
/*
|
||||
* \brief Retrieve progam name from dataspace (Linux specific)
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \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 <ldso/arch.h>
|
||||
|
||||
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;
|
||||
}
|
@ -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; }
|
||||
|
||||
|
@ -1,25 +0,0 @@
|
||||
/*
|
||||
* \brief Retrieve progam name from dataspace (Linux specific)
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \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 <ldso/arch.h>
|
||||
#include <linux_dataspace/client.h>
|
||||
|
||||
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;
|
||||
}
|
@ -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 <ldso/arch.h>
|
||||
|
||||
void Genode::set_parent_cap_arch(void *ptr)
|
||||
{
|
||||
}
|
@ -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 <ldso/arch.h>
|
||||
|
||||
void Genode::set_parent_cap_arch(void *ptr)
|
||||
{
|
||||
/* Not required, determinig parent cap is done not using any exported
|
||||
* symbols
|
||||
*/
|
||||
}
|
@ -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 <base/child.h>
|
||||
#include <ldso/arch.h>
|
||||
#include <util/string.h>
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
void Genode::set_parent_cap_arch(void *ptr)
|
||||
{
|
||||
Genode::Parent_capability cap = parent_cap();
|
||||
memcpy(ptr, &cap, sizeof(cap));
|
||||
}
|
@ -1,122 +0,0 @@
|
||||
/*
|
||||
* \brief Special handling for the ARM architecture
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \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 <fcntl.h>
|
||||
#include <machine/elf.h>
|
||||
#include <sys/param.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
}
|
||||
|
@ -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 <typename Func_ptr>
|
||||
static Func * func(Func_ptr ptr)
|
||||
{
|
||||
return reinterpret_cast<Func *>(const_cast<void **>(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>(main_func);
|
||||
return main(genode_argc, genode_argv, genode_envp);
|
||||
}
|
@ -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 <jdp@polstra.com>.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -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 <sys/types.h>
|
||||
#include <machine/atomic.h>
|
||||
|
||||
#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
|
@ -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
|
@ -1,398 +0,0 @@
|
||||
/* $NetBSD: mdreloc.c,v 1.23 2003/07/26 15:04:38 mrg Exp $ */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD: src/libexec/rtld-elf/arm/reloc.c,v 1.4.8.1 2009/04/15 03:14:26 kensmith Exp $");
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#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;
|
||||
}
|
@ -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 <sys/types.h>
|
||||
#include <machine/atomic.h>
|
||||
|
||||
#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
|
@ -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 <machine/asm.h>
|
||||
__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 */
|
||||
|
@ -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 <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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 <sys/cdefs.h>
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
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 */
|
@ -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 <jdp@polstra.com>.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <machine/segments.h>
|
||||
#include <machine/sysarch.h>
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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);
|
||||
}
|
@ -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 <sys/types.h>
|
||||
#include <machine/atomic.h>
|
||||
|
||||
#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
|
@ -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
|
@ -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 <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/queue.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#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;
|
||||
}
|
@ -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
|
@ -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 <sys/types.h>
|
||||
#include <err.h>
|
||||
#include <paths.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#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 <stdio.h>
|
||||
#endif
|
||||
|
||||
#if defined(MALLOC_DEBUG) || defined(RCHECK)
|
||||
#define ASSERT(p) if (!(p)) botch("p")
|
||||
#include <stdio.h>
|
||||
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);
|
||||
}
|
@ -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 <sys/param.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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 <machine/elf.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <elf-hints.h>
|
||||
#include <link.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#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 /* } */
|
@ -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 <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#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]);
|
||||
}
|
@ -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
|
@ -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
|
@ -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 <err.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
@ -1,30 +0,0 @@
|
||||
/*
|
||||
* \brief Unoffical dlfnc.h extensions
|
||||
* \author Sebastian.Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \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_ */
|
@ -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;
|
@ -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 <err.h>
|
||||
#include <base/env.h>
|
||||
#include <base/printf.h>
|
||||
|
||||
|
||||
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) ;
|
||||
}
|
@ -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 <base/allocator_avl.h>
|
||||
#include <base/printf.h>
|
||||
#include <ldso/arch.h>
|
||||
#include <rom_session/connection.h>
|
||||
#include <rm_session/connection.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/param.h>
|
||||
#include <util/list.h>
|
||||
#include <util/construct_at.h>
|
||||
|
||||
#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<Rm_area>(placeholder, base);
|
||||
constructed = 1;
|
||||
}
|
||||
return reinterpret_cast<Rm_area *>(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<Fd_handle>::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<Fd_handle> *file_list()
|
||||
{
|
||||
static List<Fd_handle> _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();
|
||||
}
|
||||
|
@ -1,39 +0,0 @@
|
||||
/*
|
||||
* \brief Meta-information for Genode on Linux
|
||||
* \author Sebastian Sumpf <Sebastian.Sumpf@genode-labs.com>
|
||||
* \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 <machine/elf.h>
|
||||
|
||||
#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_ */
|
@ -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 <sys/_types.h>
|
||||
|
||||
/*
|
||||
* 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_ */
|
@ -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_ */
|
@ -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 <sys/elf_generic.h> */
|
||||
#endif
|
||||
#include <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
|
||||
#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */
|
||||
#include <sys/elf_generic.h>
|
||||
|
||||
#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_ */
|
@ -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 <sys/cdefs.h>
|
||||
|
||||
#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_ */
|
@ -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 <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
|
||||
|
||||
#define __ELF_WORD_SIZE 32 /* Used by <sys/elf_generic.h> */
|
||||
#include <sys/elf_generic.h>
|
||||
|
||||
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_ */
|
@ -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 <sys/elf32.h> /* Definitions common to all 32 bit architectures. */
|
||||
#if defined(__ELF_WORD_SIZE) && __ELF_WORD_SIZE == 64
|
||||
#include <sys/elf64.h> /* Definitions common to all 64 bit architectures. */
|
||||
#endif
|
||||
|
||||
#ifndef __ELF_WORD_SIZE
|
||||
#define __ELF_WORD_SIZE 32 /* Used by <sys/elf_generic.h> */
|
||||
#endif
|
||||
|
||||
#include <sys/elf_generic.h>
|
||||
|
||||
#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_ */
|
@ -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 <stddef.h>, <sys/queue.h>, and <sys/types.h>
|
||||
* 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 <size_t> \
|
||||
(&reinterpret_cast <const volatile char &> \
|
||||
(static_cast<type *> (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 <sys/_posix.h>, 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_ */
|
@ -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 <sys/types.h>
|
||||
#include <machine/elf.h>
|
||||
#include <sys/elf32.h>
|
||||
#include <sys/elf64.h>
|
||||
|
||||
#endif /* !_SYS_ELF_H_ */
|
@ -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 <sys/elf_common.h>
|
||||
|
||||
/*
|
||||
* 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_ */
|
@ -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 <sys/elf_common.h>
|
||||
|
||||
/*
|
||||
* 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_ */
|
@ -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_ */
|
@ -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 <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* 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_ */
|
@ -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 <sys/elf.h>
|
||||
|
||||
/*
|
||||
* Flags that describe the origin of the entries in Dl_serinfo.
|
||||
* SunOS has these in <sys/link.h>, 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_ */
|
@ -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 <sys/cdefs.h>
|
||||
|
||||
/*
|
||||
* 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_ */
|
@ -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
|
@ -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.
|
||||
*/
|
@ -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_
|
@ -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 <stddef.h>
|
||||
#include <base/fixed_stdint.h>
|
||||
|
||||
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_
|
||||
|
||||
|
@ -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 <sys/link_elf.h>
|
@ -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.
|
||||
*/
|
||||
|
@ -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.
|
||||
*/
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user