summaryrefslogtreecommitdiff
path: root/ldso/include
diff options
context:
space:
mode:
authorMike Frysinger <vapier@gentoo.org>2006-06-30 02:55:57 +0000
committerMike Frysinger <vapier@gentoo.org>2006-06-30 02:55:57 +0000
commit1ba3a7b727b49d61b4868a06f1258a54db4dc9e0 (patch)
tree3958d8fe8647427ecaacf38922a128d8d5c51c1a /ldso/include
parent1d6903684a1f73d72fb913c62491693f35f02d62 (diff)
Bernd Schmidt writes: abstract away addresses so we can support FDPIC ELFs
Diffstat (limited to 'ldso/include')
-rw-r--r--ldso/include/dl-defs.h66
-rw-r--r--ldso/include/dl-elf.h9
-rw-r--r--ldso/include/dl-hash.h4
-rw-r--r--ldso/include/ldso.h2
4 files changed, 75 insertions, 6 deletions
diff --git a/ldso/include/dl-defs.h b/ldso/include/dl-defs.h
index 878ebc3b8..dc6531d19 100644
--- a/ldso/include/dl-defs.h
+++ b/ldso/include/dl-defs.h
@@ -66,4 +66,70 @@ typedef struct {
#endif
+/* Machines in which different sections may be relocated by different
+ amounts should define this and LD_RELOC_ADDR. If you change this,
+ make sure you change struct link_map in include/link.h accordingly
+ such that it matches a prefix of struct elf_resolve. */
+#ifndef DL_LOADADDR_TYPE
+# define DL_LOADADDR_TYPE ElfW(Addr)
+#endif
+
+/* When DL_LOADADDR_TYPE is not a scalar value, or some different
+ computation is needed to relocate an address, define this. */
+#ifndef DL_RELOC_ADDR
+# define DL_RELOC_ADDR(ADDR, LOADADDR) \
+ ((void*)((intptr_t)(ADDR) + (intptr_t)(LOADADDR)))
+#endif
+
+/* Define if any declarations/definitions of local variables are
+ needed in a function that calls DT_INIT_LOADADDR or
+ DL_INIT_LOADADDR_HDR. Declarations must be properly terminated
+ with a semicolon, and non-declaration statements are forbidden. */
+#ifndef DL_INIT_LOADADDR_EXTRA_DECLS
+# define DL_INIT_LOADADDR_EXTRA_DECLS /* int i; */
+#endif
+
+/* Prepare a DL_LOADADDR_TYPE data structure for incremental
+ initialization with DL_INIT_LOADADDR_HDR, given pointers to a base
+ load address and to program headers. */
+#ifndef DL_INIT_LOADADDR
+# define DL_INIT_LOADADDR(LOADADDR, BASEADDR, PHDR, PHDRCNT) \
+ ((LOADADDR) = (BASEADDR))
+#endif
+
+/* Convert a DL_LOADADDR_TYPE to an identifying pointer. Used mostly
+ for debugging. */
+#ifndef DL_LOADADDR_BASE
+# define DL_LOADADDR_BASE(LOADADDR) (LOADADDR)
+#endif
+
+/* Initialize a LOADADDR representing the loader itself. It's only
+ called from DL_BOOT, so additional arguments passed to it may be
+ referenced. */
+#ifndef DL_INIT_LOADADDR_BOOT
+# define DL_INIT_LOADADDR_BOOT(LOADADDR, BASEADDR) \
+ ((LOADADDR) = (BASEADDR))
+#endif
+
+/* Initialize a LOADADDR representing the program. It's called from
+ DL_BOOT only. */
+#ifndef DL_INIT_LOADADDR_PROG
+# define DL_INIT_LOADADDR_PROG(LOADADDR, BASEADDR) \
+ ((LOADADDR) = (BASEADDR))
+#endif
+
+/* Test whether a given ADDR is more likely to be within the memory
+ region mapped to TPNT (a struct elf_resolve *) than to TFROM.
+ Everywhere that this is used, TFROM is initially NULL, and whenever
+ a potential match is found, it's updated. One might want to walk
+ the chain of elf_resolve to locate the best match and return false
+ whenever TFROM is non-NULL, or use an exact-matching algorithm
+ using additional information encoded in DL_LOADADDR_TYPE to test
+ for exact containment. */
+#ifndef DL_ADDR_IN_LOADADDR
+# define DL_ADDR_IN_LOADADDR(ADDR, TPNT, TFROM) \
+ ((void*)(TPNT)->loadaddr < (void*)(ADDR) \
+ && (! (TFROM) || (TFROM)->loadaddr < (TPNT)->loadaddr))
+#endif
+
#endif /* _LD_DEFS_H */
diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h
index de404aec1..9e364d680 100644
--- a/ldso/include/dl-elf.h
+++ b/ldso/include/dl-elf.h
@@ -94,10 +94,12 @@ extern void _dl_protect_relro (struct elf_resolve *l);
#define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
-extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off);
+extern void _dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr,
+ DL_LOADADDR_TYPE load_off);
static __always_inline
-void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr, ElfW(Addr) load_off)
+void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void *debug_addr,
+ DL_LOADADDR_TYPE load_off)
{
for (; dpnt->d_tag; dpnt++) {
if (dpnt->d_tag < DT_NUM) {
@@ -139,7 +141,8 @@ void __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info[], void
#define ADJUST_DYN_INFO(tag, load_off) \
do { \
if (dynamic_info[tag]) \
- dynamic_info[tag] += load_off; \
+ dynamic_info[tag] = (unsigned long)DL_RELOC_ADDR (dynamic_info[tag], \
+ load_off); \
} while(0)
ADJUST_DYN_INFO(DT_HASH, load_off);
ADJUST_DYN_INFO(DT_PLTGOT, load_off);
diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h
index b12b36f3b..26fb334fe 100644
--- a/ldso/include/dl-hash.h
+++ b/ldso/include/dl-hash.h
@@ -28,7 +28,7 @@ struct dyn_elf{
struct elf_resolve{
/* These entries must be in this order to be compatible with the interface used
by gdb to obtain the list of symbols. */
- ElfW(Addr) loadaddr; /* Base address shared object is loaded at. */
+ DL_LOADADDR_TYPE loadaddr; /* Base address shared object is loaded at. */
char *libname; /* Absolute file name object was found in. */
ElfW(Dyn) *dynamic_addr; /* Dynamic section of the shared object. */
struct elf_resolve * next;
@@ -77,7 +77,7 @@ extern struct elf_resolve * _dl_loaded_modules;
extern struct dyn_elf * _dl_handles;
extern struct elf_resolve * _dl_add_elf_hash_table(const char * libname,
- char * loadaddr, unsigned long * dynamic_info,
+ DL_LOADADDR_TYPE loadaddr, unsigned long * dynamic_info,
unsigned long dynamic_addr, unsigned long dynamic_size);
extern char * _dl_find_hash(const char * name, struct dyn_elf * rpnt1,
diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h
index 0a3f70691..573652e61 100644
--- a/ldso/include/ldso.h
+++ b/ldso/include/ldso.h
@@ -88,7 +88,7 @@ extern void _dl_unsetenv(const char *symbol, char **envp);
extern char *_dl_strdup(const char *string);
extern void _dl_dprintf(int, const char *, ...);
-extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
+extern void _dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr,
ElfW(auxv_t) auxvt[AT_EGID + 1], char **envp, char **argv);
#endif /* _LDSO_H_ */