summaryrefslogtreecommitdiff
path: root/ldso
diff options
context:
space:
mode:
authorJoakim Tjernlund <joakim.tjernlund@transmode.se>2004-11-02 08:14:49 +0000
committerJoakim Tjernlund <joakim.tjernlund@transmode.se>2004-11-02 08:14:49 +0000
commitdc0f822bfed430e5b4f87f27c2e63171fa5fba28 (patch)
tree01eda5fa3c42d0c8b114f76622b4794a7735aa41 /ldso
parentf8f7b102217864ea382a46bb9ad173b3493e5cae (diff)
- Remove dynamic_size from struct elf_resolve.
- Replace all open coded dynamic handling with a function. Reduces size. - Fold special MIPS dynamic code into the dynamic_info item. - Add RELRO support. - Support linking with "-z now". - prepare for DT_RELACOUNT/DT_RELCOUNT optimization. - Add -z now to ld.so linking, this is what ld.so does anyway so let the linker know that.
Diffstat (limited to 'ldso')
-rw-r--r--ldso/include/dl-elf.h49
-rw-r--r--ldso/include/dl-hash.h11
-rw-r--r--ldso/ldso/Makefile2
-rw-r--r--ldso/ldso/dl-elf.c80
-rw-r--r--ldso/ldso/dl-hash.c18
-rw-r--r--ldso/ldso/dl-startup.c25
-rw-r--r--ldso/ldso/ldso.c87
-rw-r--r--ldso/ldso/mips/dl-startup.h14
-rw-r--r--ldso/ldso/mips/dl-sysdep.h18
-rw-r--r--ldso/ldso/mips/elfinterp.c16
-rw-r--r--ldso/libdl/libdl.c10
11 files changed, 172 insertions, 158 deletions
diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h
index d70d84ae4..a1237b09f 100644
--- a/ldso/include/dl-elf.h
+++ b/ldso/include/dl-elf.h
@@ -33,7 +33,7 @@ extern struct elf_resolve *_dl_check_if_named_library_is_loaded(const char *full
int trace_loaded_objects);
extern int _dl_linux_resolve(void);
extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
-
+extern void _dl_protect_relro (struct elf_resolve *l);
/*
* Datatype of a relocation on this platform
@@ -42,16 +42,63 @@ extern int _dl_fixup(struct dyn_elf *rpnt, int flag);
# define ELF_RELOC ElfW(Rela)
# define DT_RELOC_TABLE_ADDR DT_RELA
# define DT_RELOC_TABLE_SIZE DT_RELASZ
+# define DT_RELOCCOUNT DT_RELACOUNT
# define UNSUPPORTED_RELOC_TYPE DT_REL
# define UNSUPPORTED_RELOC_STR "REL"
#else
# define ELF_RELOC ElfW(Rel)
# define DT_RELOC_TABLE_ADDR DT_REL
# define DT_RELOC_TABLE_SIZE DT_RELSZ
+# define DT_RELOCCOUNT DT_RELCOUNT
# define UNSUPPORTED_RELOC_TYPE DT_RELA
# define UNSUPPORTED_RELOC_STR "RELA"
#endif
+/* OS and/or GNU dynamic extensions */
+#define OS_NUM 1
+#define DT_RELCONT_IDX DT_NUM
+
+#ifndef ARCH_DYNAMIC_INFO
+ /* define in arch specific code, if needed */
+# define ARCH_NUM 0
+#endif
+
+#define DYNAMIC_SIZE (DT_NUM+OS_NUM+ARCH_NUM)
+
+extern void _dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr);
+
+static inline __attribute__((always_inline))
+void __dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr)
+{
+ for (; dpnt->d_tag; dpnt++) {
+ if (dpnt->d_tag < DT_NUM) {
+ dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
+#ifndef __mips__
+ if (dpnt->d_tag == DT_DEBUG)
+ dpnt->d_un.d_val = (unsigned long)debug_addr;
+#endif
+ if (dpnt->d_tag == DT_BIND_NOW)
+ dynamic_info[DT_BIND_NOW] = 1;
+ if (dpnt->d_tag == DT_FLAGS &&
+ (dpnt->d_un.d_val & DF_BIND_NOW))
+ dynamic_info[DT_BIND_NOW] = 1;
+ if (dpnt->d_tag == DT_TEXTREL)
+ dynamic_info[DT_TEXTREL] = 1;
+ } else if (dpnt->d_tag < DT_LOPROC) {
+ if (dpnt->d_tag == DT_RELOCCOUNT)
+ dynamic_info[DT_RELCONT_IDX] = dpnt->d_un.d_val;
+ if (dpnt->d_tag == DT_FLAGS_1 &&
+ (dpnt->d_un.d_val & DF_1_NOW))
+ dynamic_info[DT_BIND_NOW] = 1;
+ }
+#ifdef ARCH_DYNAMIC_INFO
+ else {
+ ARCH_DYNAMIC_INFO(dpnt, dynamic_info, debug_addr);
+ }
+#endif
+ }
+}
+
/* Reloc type classes as returned by elf_machine_type_class().
ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h
index 67484d260..60fdd2856 100644
--- a/ldso/include/dl-hash.h
+++ b/ldso/include/dl-hash.h
@@ -41,18 +41,13 @@ struct elf_resolve{
*/
unsigned long nchain;
unsigned long * chains;
- unsigned long dynamic_info[24];
+ unsigned long dynamic_info[DYNAMIC_SIZE];
- unsigned long dynamic_size;
unsigned long n_phent;
Elf32_Phdr * ppnt;
-#if defined(__mips__)
- /* Needed for MIPS relocation */
- unsigned long mips_gotsym;
- unsigned long mips_local_gotno;
- unsigned long mips_symtabno;
-#endif
+ ElfW(Addr) relro_addr;
+ size_t relro_size;
#ifdef __powerpc__
/* this is used to store the address of relocation data words, so
diff --git a/ldso/ldso/Makefile b/ldso/ldso/Makefile
index 1f6476d2e..f58c3e857 100644
--- a/ldso/ldso/Makefile
+++ b/ldso/ldso/Makefile
@@ -40,7 +40,7 @@ XXFLAGS+= $(XARCH_CFLAGS) $(CPU_CFLAGS) $(PICFLAG) \
XXFLAGS :=$(XXFLAGS:-O0=-O1)
XXFLAGS+=$(shell $(CC) -print-search-dirs | sed -ne "s/install: *\(.*\)/-I\1include/gp")
-LDFLAGS=$(CPU_LDFLAGS-y) -Bsymbolic -shared --warn-common --export-dynamic --sort-common \
+LDFLAGS=$(CPU_LDFLAGS-y) -z now -Bsymbolic -shared --warn-common --export-dynamic --sort-common \
-z combreloc --discard-locals --discard-all --no-undefined
CSRC= ldso.c
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 3e4e3482c..d0144077d 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -114,6 +114,25 @@ int _dl_unmap_cache(void)
}
#endif
+
+void
+_dl_protect_relro (struct elf_resolve *l)
+{
+ ElfW(Addr) start = ((l->loadaddr + l->relro_addr)
+ & ~(_dl_pagesize - 1));
+ ElfW(Addr) end = ((l->loadaddr + l->relro_addr + l->relro_size)
+ & ~(_dl_pagesize - 1));
+#if defined (__SUPPORT_LD_DEBUG__)
+ if (_dl_debug)
+ _dl_dprintf(2, "RELRO protecting %s: start:%x, end:%x\n", l->libname, start, end);
+#endif
+ if (start != end &&
+ _dl_mprotect ((void *) start, end - start, PROT_READ) < 0) {
+ _dl_dprintf(2, "%s: cannot apply additional memory protection after relocation", l->libname);
+ _dl_exit(0);
+ }
+}
+
/* This function's behavior must exactly match that
* in uClibc/ldso/util/ldd.c */
static struct elf_resolve *
@@ -390,16 +409,17 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
{
ElfW(Ehdr) *epnt;
unsigned long dynamic_addr = 0;
- unsigned long dynamic_size = 0;
Elf32_Dyn *dpnt;
struct elf_resolve *tpnt;
ElfW(Phdr) *ppnt;
char *status, *header;
- unsigned long dynamic_info[24];
+ unsigned long dynamic_info[DYNAMIC_SIZE];
unsigned long *lpnt;
unsigned long libaddr;
unsigned long minvma = 0xffffffff, maxvma = 0;
int i, flags, piclib, infile;
+ ElfW(Addr) relro_addr = 0;
+ size_t relro_size = 0;
/* If this file is already loaded, skip this step */
tpnt = _dl_check_hashed_files(libname);
@@ -493,7 +513,6 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
_dl_dprintf(2, "%s: '%s' has more than one dynamic section\n",
_dl_progname, libname);
dynamic_addr = ppnt->p_vaddr;
- dynamic_size = ppnt->p_filesz;
};
if (ppnt->p_type == PT_LOAD) {
@@ -535,6 +554,10 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
ppnt = (ElfW(Phdr) *)(intptr_t) & header[epnt->e_phoff];
for (i = 0; i < epnt->e_phnum; i++) {
+ if (ppnt->p_type == PT_GNU_RELRO) {
+ relro_addr = ppnt->p_vaddr;
+ relro_size = ppnt->p_memsz;
+ }
if (ppnt->p_type == PT_LOAD) {
/* See if this is a PIC library. */
@@ -627,40 +650,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
}
dpnt = (Elf32_Dyn *) dynamic_addr;
-
- dynamic_size = dynamic_size / sizeof(Elf32_Dyn);
_dl_memset(dynamic_info, 0, sizeof(dynamic_info));
-
-#if defined(__mips__)
- {
-
- int indx = 1;
- Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
-
- while(dpnt->d_tag) {
- dpnt++;
- indx++;
- }
- dynamic_size = indx;
- }
-#endif
-
- {
- unsigned long indx;
-
- for (indx = 0; indx < dynamic_size; indx++)
- {
- if (dpnt->d_tag > DT_JMPREL) {
- dpnt++;
- continue;
- }
- dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
- if (dpnt->d_tag == DT_TEXTREL)
- dynamic_info[DT_TEXTREL] = 1;
- dpnt++;
- };
- }
-
+ _dl_parse_dynamic_info(dpnt, dynamic_info, NULL);
/* If the TEXTREL is set, this means that we need to make the pages
writable before we perform relocations. Do this now. They get set
back again later. */
@@ -682,8 +673,9 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
}
tpnt = _dl_add_elf_hash_table(libname, (char *) libaddr, dynamic_info,
- dynamic_addr, dynamic_size);
-
+ dynamic_addr, 0);
+ tpnt->relro_addr = relro_addr;
+ tpnt->relro_size = relro_size;
tpnt->ppnt = (ElfW(Phdr) *)(intptr_t) (tpnt->loadaddr + epnt->e_phoff);
tpnt->n_phent = epnt->e_phnum;
@@ -718,8 +710,8 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
#if defined (__SUPPORT_LD_DEBUG__)
if(_dl_debug) {
_dl_dprintf(2, "\n\tfile='%s'; generating link map\n", libname);
- _dl_dprintf(2, "\t\tdynamic: %x base: %x size: %x\n",
- dynamic_addr, libaddr, dynamic_size);
+ _dl_dprintf(2, "\t\tdynamic: %x base: %x\n",
+ dynamic_addr, libaddr);
_dl_dprintf(2, "\t\t entry: %x phdr: %x phnum: %x\n\n",
epnt->e_entry + libaddr, tpnt->ppnt, tpnt->n_phent);
@@ -769,6 +761,8 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
tpnt->dynamic_info[DT_RELOC_TABLE_ADDR],
reloc_size);
}
+ if (tpnt->dynamic_info[DT_BIND_NOW])
+ now_flag = RTLD_NOW;
if (tpnt->dynamic_info[DT_JMPREL] &&
(!(tpnt->init_flag & JMP_RELOCS_DONE) ||
(now_flag && !(tpnt->rtld_flags & now_flag)))) {
@@ -784,7 +778,6 @@ int _dl_fixup(struct dyn_elf *rpnt, int now_flag)
tpnt->dynamic_info[DT_PLTRELSZ]);
}
}
-
return goof;
}
@@ -880,6 +873,11 @@ char *_dl_strdup(const char *string)
_dl_strcpy(retval, string);
return retval;
}
+
+void _dl_parse_dynamic_info(Elf32_Dyn *dpnt, unsigned long dynamic_info[], void *debug_addr)
+{
+ __dl_parse_dynamic_info(dpnt, dynamic_info, debug_addr);
+}
#ifdef __USE_GNU
#if ! defined LIBDL || (! defined PIC && ! defined __PIC__)
int
diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c
index bac4a506a..a119e77f9 100644
--- a/ldso/ldso/dl-hash.c
+++ b/ldso/ldso/dl-hash.c
@@ -116,7 +116,6 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
tpnt->init_flag = 0;
tpnt->libname = _dl_strdup(libname);
tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr;
- tpnt->dynamic_size = dynamic_size;
tpnt->libtype = loaded_file;
if (dynamic_info[DT_HASH] != 0) {
@@ -128,23 +127,8 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname,
tpnt->chains = hash_addr;
}
tpnt->loadaddr = (ElfW(Addr))loadaddr;
- for (i = 0; i < 24; i++)
+ for (i = 0; i < DYNAMIC_SIZE; i++)
tpnt->dynamic_info[i] = dynamic_info[i];
-#ifdef __mips__
- {
- Elf32_Dyn *dpnt = (Elf32_Dyn *) dynamic_addr;
-
- while(dpnt->d_tag) {
- if (dpnt->d_tag == DT_MIPS_GOTSYM)
- tpnt->mips_gotsym = dpnt->d_un.d_val;
- if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
- tpnt->mips_local_gotno = dpnt->d_un.d_val;
- if (dpnt->d_tag == DT_MIPS_SYMTABNO)
- tpnt->mips_symtabno = dpnt->d_un.d_val;
- dpnt++;
- }
- }
-#endif
return tpnt;
}
diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c
index 0055435d2..91c41e730 100644
--- a/ldso/ldso/dl-startup.c
+++ b/ldso/ldso/dl-startup.c
@@ -281,23 +281,14 @@ found_got:
#ifdef __SUPPORT_LD_DEBUG_EARLY__
SEND_STDERR("scanning DYNAMIC section\n");
#endif
- while (dpnt->d_tag) {
-#if defined(__mips__)
- if (dpnt->d_tag == DT_MIPS_GOTSYM)
- tpnt->mips_gotsym = (unsigned long) dpnt->d_un.d_val;
- if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
- tpnt->mips_local_gotno = (unsigned long) dpnt->d_un.d_val;
- if (dpnt->d_tag == DT_MIPS_SYMTABNO)
- tpnt->mips_symtabno = (unsigned long) dpnt->d_un.d_val;
+ tpnt->dynamic_addr = dpnt;
+#ifdef __mips__
+ /* MIPS cannot call functions here, must inline */
+ __dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL);
+#else
+ _dl_parse_dynamic_info(dpnt, tpnt->dynamic_info, NULL);
#endif
- if (dpnt->d_tag < 24) {
- tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
- if (dpnt->d_tag == DT_TEXTREL) {
- tpnt->dynamic_info[DT_TEXTREL] = 1;
- }
- }
- dpnt++;
- }
+
#ifdef __SUPPORT_LD_DEBUG_EARLY__
SEND_STDERR("done scanning DYNAMIC section\n");
#endif
@@ -335,7 +326,7 @@ found_got:
SEND_STDERR("About to do MIPS specific GOT bootstrap\n");
#endif
/* For MIPS we have to do stuff to the GOT before we do relocations. */
- PERFORM_BOOTSTRAP_GOT(got);
+ PERFORM_BOOTSTRAP_GOT(got, tpnt);
#endif
/* OK, now do the relocations. We do not do a lazy binding here, so
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 46b59a3b2..d231969f8 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -97,9 +97,11 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
struct elf_resolve app_tpnt_tmp;
struct elf_resolve *app_tpnt = &app_tpnt_tmp;
struct r_debug *debug_addr;
- unsigned long brk_addr, *lpnt;
+ unsigned long *lpnt;
int (*_dl_atexit) (void *);
unsigned long *_dl_envp; /* The environment address */
+ ElfW(Addr) relro_addr = 0;
+ size_t relro_size = 0;
#if defined (__SUPPORT_LD_DEBUG__)
int (*_dl_on_exit) (void (*FUNCTION)(int STATUS, void *ARG),void*);
#endif
@@ -132,23 +134,6 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
* go from there. Eventually we will run across ourself, and we
* will need to properly deal with that as well.
*/
- {
- ElfW(Ehdr) *epnt;
- ElfW(Phdr) *myppnt;
- int j;
-
- epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
- tpnt->n_phent = epnt->e_phnum;
- tpnt->ppnt = myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
- for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
- if (myppnt->p_type == PT_DYNAMIC) {
- tpnt->dynamic_addr = (ElfW(Dyn) *)(myppnt->p_vaddr + load_addr);
- tpnt->dynamic_size = myppnt->p_filesz;
- }
- }
- }
-
- brk_addr = 0;
rpnt = NULL;
if (_dl_getenv("LD_BIND_NOW", envp))
unlazy = RTLD_NOW;
@@ -189,46 +174,13 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_ptr;
for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
- if (ppnt->p_type == PT_LOAD) {
- if (ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz > brk_addr)
- brk_addr = ppnt->p_vaddr + app_tpnt->loadaddr + ppnt->p_memsz;
+ if (ppnt->p_type == PT_GNU_RELRO) {
+ relro_addr = ppnt->p_vaddr;
+ relro_size = ppnt->p_memsz;
}
if (ppnt->p_type == PT_DYNAMIC) {
dpnt = (Elf32_Dyn *) (ppnt->p_vaddr + app_tpnt->loadaddr);
- while (dpnt->d_tag) {
-#if defined(__mips__)
- if (dpnt->d_tag == DT_MIPS_GOTSYM)
- app_tpnt->mips_gotsym =
- (unsigned long) dpnt->d_un.d_val;
- if (dpnt->d_tag == DT_MIPS_LOCAL_GOTNO)
- app_tpnt->mips_local_gotno =
- (unsigned long) dpnt->d_un.d_val;
- if (dpnt->d_tag == DT_MIPS_SYMTABNO)
- app_tpnt->mips_symtabno =
- (unsigned long) dpnt->d_un.d_val;
- /* Remember... DT_MIPS_RLD_MAP > DT_JMPREL. */
- if (dpnt->d_tag == DT_MIPS_RLD_MAP) {
- *(ElfW(Addr) *)(dpnt->d_un.d_ptr) = (ElfW(Addr)) debug_addr;
- }
- if (dpnt->d_tag > DT_JMPREL) {
- dpnt++;
- continue;
- }
- app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
-#else
- if (dpnt->d_tag > DT_JMPREL) {
- dpnt++;
- continue;
- }
- app_tpnt->dynamic_info[dpnt->d_tag] = dpnt->d_un.d_val;
- if (dpnt->d_tag == DT_DEBUG) {
- dpnt->d_un.d_val = (unsigned long) debug_addr;
- }
-#endif
- if (dpnt->d_tag == DT_TEXTREL)
- app_tpnt->dynamic_info[DT_TEXTREL] = 1;
- dpnt++;
- }
+ _dl_parse_dynamic_info(dpnt, app_tpnt->dynamic_info, debug_addr);
#ifndef __FORCE_SHAREABLE_TEXT_SEGMENTS__
/* Ugly, ugly. We need to call mprotect to change the
* protection of the text pages so that we can do the
@@ -315,6 +267,8 @@ void _dl_get_ready_to_run(struct elf_resolve *tpnt, unsigned long load_addr,
#endif
}
}
+ app_tpnt->relro_addr = relro_addr;
+ app_tpnt->relro_size = relro_size;
/* Now we need to figure out what kind of options are selected.
* Note that for SUID programs we ignore the settings in
@@ -728,10 +682,24 @@ next_lib2:
* again once all libs are loaded.
*/
if (tpnt) {
+ ElfW(Ehdr) *epnt = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_ptr;
+ ElfW(Phdr) *myppnt = (ElfW(Phdr) *) (load_addr + epnt->e_phoff);
+ int j;
+
tpnt = _dl_add_elf_hash_table(tpnt->libname, (char *)load_addr,
tpnt->dynamic_info,
(unsigned long)tpnt->dynamic_addr,
- tpnt->dynamic_size);
+ 0);
+
+ tpnt->n_phent = epnt->e_phnum;
+ tpnt->ppnt = myppnt;
+ for (j = 0; j < epnt->e_phnum; j++, myppnt++) {
+ if (myppnt->p_type == PT_GNU_RELRO) {
+ tpnt->relro_addr = myppnt->p_vaddr;
+ tpnt->relro_size = myppnt->p_memsz;
+ break;
+ }
+ }
tpnt->libtype = program_interpreter;
tpnt->usage_count++;
tpnt->symbol_scope = _dl_symbol_tables;
@@ -791,6 +759,13 @@ next_lib2:
if (_dl_symbol_tables)
goof += _dl_fixup(_dl_symbol_tables, unlazy);
+ for (tpnt = _dl_loaded_modules; tpnt; tpnt = tpnt->next) {
+ if (tpnt->relro_size)
+ _dl_protect_relro (tpnt);
+ }
+
+
+
/* OK, at this point things are pretty much ready to run. Now we need
* to touch up a few items that are required, and then we can let the
diff --git a/ldso/ldso/mips/dl-startup.h b/ldso/ldso/mips/dl-startup.h
index 3d9b829c3..0dd92b5ba 100644
--- a/ldso/ldso/mips/dl-startup.h
+++ b/ldso/ldso/mips/dl-startup.h
@@ -48,21 +48,21 @@ asm("" \
* Here is a macro to perform the GOT relocation. This is only
* used when bootstrapping the dynamic loader.
*/
-#define PERFORM_BOOTSTRAP_GOT(got) \
+#define PERFORM_BOOTSTRAP_GOT(got, tpnt) \
do { \
Elf32_Sym *sym; \
unsigned long i; \
\
/* Add load address displacement to all local GOT entries */ \
i = 2; \
- while (i < tpnt->mips_local_gotno) \
+ while (i < tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
got[i++] += load_addr; \
\
/* Handle global GOT entries */ \
- got += tpnt->mips_local_gotno; \
+ got += tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]; \
sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + \
- load_addr) + tpnt->mips_gotsym; \
- i = tpnt->mips_symtabno - tpnt->mips_gotsym; \
+ load_addr) + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]; \
+ i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];\
\
while (i--) { \
if (sym->st_shndx == SHN_UNDEF || \
@@ -91,8 +91,8 @@ do { \
#define PERFORM_BOOTSTRAP_RELOC(RELP,REL,SYMBOL,LOAD,SYMTAB) \
switch(ELF32_R_TYPE((RELP)->r_info)) { \
case R_MIPS_REL32: \
- if (symtab_index) { \
- if (symtab_index < tpnt->mips_gotsym) \
+ if (SYMTAB) { \
+ if (symtab_index<tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])\
*REL += SYMBOL; \
} \
else { \
diff --git a/ldso/ldso/mips/dl-sysdep.h b/ldso/ldso/mips/dl-sysdep.h
index 45a1f2e4e..8f5a56185 100644
--- a/ldso/ldso/mips/dl-sysdep.h
+++ b/ldso/ldso/mips/dl-sysdep.h
@@ -8,6 +8,22 @@
/* Define this if the system uses RELOCA. */
#undef ELF_USES_RELOCA
+#define ARCH_NUM 3
+#define DT_MIPS_GOTSYM_IDX (DT_NUM + OS_NUM)
+#define DT_MIPS_LOCAL_GOTNO_IDX (DT_NUM + OS_NUM +1)
+#define DT_MIPS_SYMTABNO_IDX (DT_NUM + OS_NUM +2)
+
+#define ARCH_DYNAMIC_INFO(dpnt, dynamic, debug_addr) \
+do { \
+if (dpnt->d_tag == DT_MIPS_GOTSYM) \
+ dynamic[DT_MIPS_GOTSYM_IDX] = dpnt->d_un.d_val; \
+else if(dpnt->d_tag == DT_MIPS_LOCAL_GOTNO) \
+ dynamic[DT_MIPS_LOCAL_GOTNO_IDX] = dpnt->d_un.d_val; \
+else if(dpnt->d_tag == DT_MIPS_SYMTABNO) \
+ dynamic[DT_MIPS_SYMTABNO_IDX] = dpnt->d_un.d_val; \
+else if (dpnt->d_tag == DT_MIPS_RLD_MAP) \
+ *(Elf32_Addr *)(dpnt->d_un.d_ptr) = (Elf32_Addr) debug_addr; \
+} while (0)
/* Initialization sequence for the application/library GOT. */
#define INIT_GOT(GOT_BASE,MODULE) \
@@ -24,7 +40,7 @@ do { \
\
/* Add load address displacement to all local GOT entries */ \
i = 2; \
- while (i < MODULE->mips_local_gotno) \
+ while (i < MODULE->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX]) \
GOT_BASE[i++] += (unsigned long) MODULE->loadaddr; \
\
} while (0)
diff --git a/ldso/ldso/mips/elfinterp.c b/ldso/ldso/mips/elfinterp.c
index 37ef6a86c..74521823e 100644
--- a/ldso/ldso/mips/elfinterp.c
+++ b/ldso/ldso/mips/elfinterp.c
@@ -121,8 +121,8 @@ unsigned long _dl_linux_resolver(unsigned long sym_index,
char **got_addr;
char *symname;
- gotsym = tpnt->mips_gotsym;
- local_gotno = tpnt->mips_local_gotno;
+ gotsym = tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];
+ local_gotno = tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX];
sym = ((Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + tpnt->loadaddr)) + sym_index;
strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + tpnt->loadaddr);
@@ -213,13 +213,13 @@ int _dl_parse_relocation_information(struct dyn_elf *xpnt,
switch (reloc_type) {
case R_MIPS_REL32:
if (symtab_index) {
- if (symtab_index < tpnt->mips_gotsym)
+ if (symtab_index < tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX])
*reloc_addr +=
symtab[symtab_index].st_value +
(unsigned long) tpnt->loadaddr;
else {
- *reloc_addr += got[symtab_index + tpnt->mips_local_gotno -
- tpnt->mips_gotsym];
+ *reloc_addr += got[symtab_index + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX] -
+ tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX]];
}
}
else {
@@ -270,12 +270,12 @@ void _dl_perform_mips_global_got_relocations(struct elf_resolve *tpnt)
/* Setup the loop variables */
got_entry = (unsigned long *) (tpnt->loadaddr +
- tpnt->dynamic_info[DT_PLTGOT]) + tpnt->mips_local_gotno;
+ tpnt->dynamic_info[DT_PLTGOT]) + tpnt->dynamic_info[DT_MIPS_LOCAL_GOTNO_IDX];
sym = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] +
- (unsigned long) tpnt->loadaddr) + tpnt->mips_gotsym;
+ (unsigned long) tpnt->loadaddr) + tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];
strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] +
(unsigned long) tpnt->loadaddr);
- i = tpnt->mips_symtabno - tpnt->mips_gotsym;
+ i = tpnt->dynamic_info[DT_MIPS_SYMTABNO_IDX] - tpnt->dynamic_info[DT_MIPS_GOTSYM_IDX];
#if defined (__SUPPORT_LD_DEBUG__)
if(_dl_debug_reloc)
diff --git a/ldso/libdl/libdl.c b/ldso/libdl/libdl.c
index 21dbd86ce..1bb68bdc8 100644
--- a/ldso/libdl/libdl.c
+++ b/ldso/libdl/libdl.c
@@ -47,6 +47,8 @@ extern struct elf_resolve * _dl_check_if_named_library_is_loaded(const char *, i
__attribute__ ((__weak__));
extern int _dl_fixup(struct dyn_elf *rpnt, int lazy)
__attribute__ ((__weak__));
+extern void _dl_protect_relro(struct elf_resolve * tpnt)
+ __attribute__ ((__weak__));
extern int _dl_errno __attribute__ ((__weak__));
extern struct dyn_elf *_dl_symbol_tables __attribute__ ((__weak__));
extern struct dyn_elf *_dl_handles __attribute__ ((__weak__));
@@ -128,7 +130,7 @@ void __attribute__ ((destructor)) dl_cleanup(void)
void *dlopen(const char *libname, int flag)
{
struct elf_resolve *tpnt, *tfrom, *tcurr;
- struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr;
+ struct dyn_elf *dyn_chain, *rpnt = NULL, *dyn_ptr, *relro_ptr;
struct dyn_elf *dpnt;
ElfW(Addr) from;
struct elf_resolve *tpnt1;
@@ -168,6 +170,8 @@ void *dlopen(const char *libname, int flag)
tfrom = tpnt;
}
for(rpnt = _dl_symbol_tables; rpnt->next; rpnt=rpnt->next);
+
+ relro_ptr = rpnt;
/* Try to load the specified library */
#ifdef __SUPPORT_LD_DEBUG__
if(_dl_debug)
@@ -311,6 +315,10 @@ void *dlopen(const char *libname, int flag)
if (_dl_fixup(dyn_chain, now_flag))
goto oops;
+ for (rpnt = relro_ptr->next; rpnt; rpnt = rpnt->next) {
+ if (rpnt->dyn->relro_size)
+ _dl_protect_relro(rpnt->dyn);
+ }
/* TODO: Should we set the protections of all pages back to R/O now ? */