diff options
author | Mark Salter <msalter@redhat.com> | 2012-05-22 10:53:29 -0400 |
---|---|---|
committer | Bernhard Reutner-Fischer <rep.dot.nop@gmail.com> | 2012-06-06 09:06:10 +0200 |
commit | 8554fb21bb34329201b38c2ae4387fb6f00645cc (patch) | |
tree | 462975e36aee3b3ff726e3300ead039e4da1fb3c /ldso | |
parent | 80c9bfc4668e2370b3434a801dc266f336265832 (diff) |
Clean up DSBT support
The existing DSBT support relies on the kernel to provide DSBT info
as part of the load maps passed to user space. The problem with this
approach is that the DSBT info is in the dynamic section, so the
kernel must access a userspace mapping of the dynamic section (or
separately read a copy for the kernel) in order to retrieve the
information needed by userspace.
This patch reworks the DSBT support to remove the reliance on DSBT
info coming from the kernel. Instead, ldso reads the info itself from
the dynamic section. One other benefit of this is that it allows the
existing kernel FDPIC loader to also load DSBT binaries.
Signed-off-by: Mark Salter <msalter@redhat.com>
Signed-off-by: Bernhard Reutner-Fischer <rep.dot.nop@gmail.com>
Diffstat (limited to 'ldso')
-rw-r--r-- | ldso/include/dl-elf.h | 5 | ||||
-rw-r--r-- | ldso/include/dl-hash.h | 6 | ||||
-rw-r--r-- | ldso/include/ldso.h | 3 | ||||
-rw-r--r-- | ldso/ldso/dl-elf.c | 70 | ||||
-rw-r--r-- | ldso/ldso/dl-hash.c | 9 | ||||
-rw-r--r-- | ldso/ldso/ldso.c | 14 |
6 files changed, 66 insertions, 41 deletions
diff --git a/ldso/include/dl-elf.h b/ldso/include/dl-elf.h index 29d1a007f..060ee3dfb 100644 --- a/ldso/include/dl-elf.h +++ b/ldso/include/dl-elf.h @@ -222,11 +222,6 @@ unsigned int __dl_parse_dynamic_info(ElfW(Dyn) *dpnt, unsigned long dynamic_info #ifdef __DSBT__ /* Get the mapped address of the DSBT base. */ ADJUST_DYN_INFO(DT_DSBT_BASE_IDX, load_off); - - /* Initialize loadmap dsbt info. */ - load_off.map->dsbt_table = (void *)dynamic_info[DT_DSBT_BASE_IDX]; - load_off.map->dsbt_size = dynamic_info[DT_DSBT_SIZE_IDX]; - load_off.map->dsbt_index = dynamic_info[DT_DSBT_INDEX_IDX]; #endif #undef ADJUST_DYN_INFO return rtld_flags; diff --git a/ldso/include/dl-hash.h b/ldso/include/dl-hash.h index c7effc588..7bccdca96 100644 --- a/ldso/include/dl-hash.h +++ b/ldso/include/dl-hash.h @@ -139,6 +139,12 @@ struct elf_resolve { memory when the module is dlclose()d. */ struct funcdesc_ht *funcdesc_ht; #endif +#ifdef __DSBT__ + /* Information for DSBT */ + void **dsbt_table; + unsigned long dsbt_size; + unsigned long dsbt_index; +#endif }; #define RELOCS_DONE 0x000001 diff --git a/ldso/include/ldso.h b/ldso/include/ldso.h index 6f3b728c3..cb7b12218 100644 --- a/ldso/include/ldso.h +++ b/ldso/include/ldso.h @@ -84,6 +84,9 @@ extern struct elf_resolve *_dl_trace_prelink_map; /* Library map for prelinking #else #define _dl_trace_prelink 0 #endif +#ifdef __DSBT__ +extern void **_dl_ldso_dsbt; +#endif #if defined(USE_TLS) && USE_TLS extern void _dl_add_to_slotinfo (struct link_map *l); diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index 9e2a12ce7..31ba11ffa 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -851,10 +851,15 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags, /* Handle DSBT initialization */ { struct elf_resolve *t, *ref; - int idx = tpnt->loadaddr.map->dsbt_index; - unsigned *dsbt = tpnt->loadaddr.map->dsbt_table; + int idx = tpnt->dsbt_index; + void **dsbt = tpnt->dsbt_table; - if (idx == 0) { + /* + * It is okay (required actually) to have zero idx for an executable. + * This is the case when running ldso standalone and the program + * is being mapped in via _dl_load_shared_library(). + */ + if (idx == 0 && tpnt->libtype != elf_executable) { if (!dynamic_info[DT_TEXTREL]) { /* This DSO has not been assigned an index. */ _dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n", @@ -869,9 +874,9 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags, break; } } - idx = tpnt->loadaddr.map->dsbt_size; + idx = tpnt->dsbt_size; while (idx-- > 0) - if (!ref || ref->loadaddr.map->dsbt_table[idx] == NULL) + if (!ref || ref->dsbt_table[idx] == NULL) break; if (idx <= 0) { _dl_dprintf(2, "%s: '%s' caused DSBT table overflow!\n", @@ -880,43 +885,36 @@ struct elf_resolve *_dl_load_elf_shared_library(unsigned rflags, } _dl_if_debug_dprint("\n\tfile='%s'; assigned index %d\n", libname, idx); - tpnt->loadaddr.map->dsbt_index = idx; + tpnt->dsbt_index = idx; + } + /* make sure index is not already used */ + if (_dl_ldso_dsbt[idx]) { + struct elf_resolve *dup; + const char *dup_name; + + for (dup = _dl_loaded_modules; dup; dup = dup->next) + if (dup != tpnt && dup->dsbt_index == idx) + break; + if (dup) + dup_name = dup->libname; + else if (idx == 1) + dup_name = "runtime linker"; + else + dup_name = "unknown library"; + _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n", + _dl_progname, libname, idx, dup_name); + _dl_exit(1); } /* * Setup dsbt slot for this module in dsbt of all modules. */ - ref = NULL; - for (t = _dl_loaded_modules; t; t = t->next) { - /* find a dsbt table from another module */ - if (ref == NULL && t != tpnt) { - ref = t; - - /* make sure index is not already used */ - if (t->loadaddr.map->dsbt_table[idx]) { - struct elf_resolve *dup; - char *dup_name; - - for (dup = _dl_loaded_modules; dup; dup = dup->next) - if (dup != tpnt && dup->loadaddr.map->dsbt_index == idx) - break; - if (dup) - dup_name = dup->libname; - else if (idx == 1) - dup_name = "runtime linker"; - else - dup_name = "unknown library"; - _dl_dprintf(2, "%s: '%s' dsbt index %d already used by %s!\n", - _dl_progname, libname, idx, dup_name); - _dl_exit(1); - } - } - t->loadaddr.map->dsbt_table[idx] = (unsigned)dsbt; - } - if (ref) - _dl_memcpy(dsbt, ref->loadaddr.map->dsbt_table, - tpnt->loadaddr.map->dsbt_size * sizeof(unsigned *)); + for (t = _dl_loaded_modules; t; t = t->next) + t->dsbt_table[idx] = dsbt; + _dl_ldso_dsbt[idx] = dsbt; + _dl_memcpy(dsbt, _dl_ldso_dsbt, + tpnt->dsbt_size * sizeof(tpnt->dsbt_table[0])); } #endif _dl_if_debug_dprint("\n\tfile='%s'; generating link map\n", libname); diff --git a/ldso/ldso/dl-hash.c b/ldso/ldso/dl-hash.c index 36ebec684..2c659dc58 100644 --- a/ldso/ldso/dl-hash.c +++ b/ldso/ldso/dl-hash.c @@ -115,6 +115,15 @@ struct elf_resolve *_dl_add_elf_hash_table(const char *libname, tpnt->dynamic_addr = (ElfW(Dyn) *)dynamic_addr; tpnt->libtype = loaded_file; +#ifdef __DSBT__ + if (dynamic_info[DT_DSBT_BASE_IDX] != 0) + tpnt->dsbt_table = (void *)dynamic_info[DT_DSBT_BASE_IDX]; + if (dynamic_info[DT_DSBT_SIZE_IDX] != 0) + tpnt->dsbt_size = dynamic_info[DT_DSBT_SIZE_IDX]; + if (dynamic_info[DT_DSBT_INDEX_IDX] != 0) + tpnt->dsbt_index = dynamic_info[DT_DSBT_INDEX_IDX]; +#endif /* __DSBT__ */ + #ifdef __LDSO_GNU_HASH_SUPPORT__ if (dynamic_info[DT_GNU_HASH_IDX] != 0) { Elf32_Word *hash32 = (Elf_Symndx*)dynamic_info[DT_GNU_HASH_IDX]; diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c index 8cfb03f9a..f2ba628b3 100644 --- a/ldso/ldso/ldso.c +++ b/ldso/ldso/ldso.c @@ -77,6 +77,10 @@ char *_dl_debug_bindings = NULL; int _dl_debug_file = 2; #endif +#ifdef __DSBT__ +void **_dl_ldso_dsbt = NULL; +#endif + unsigned long attribute_hidden _dl_skip_args = 0; const char *_dl_progname = UCLIBC_LDSO; /* The name of the executable being run */ @@ -454,6 +458,11 @@ void *_dl_get_ready_to_run(struct elf_resolve *tpnt, DL_LOADADDR_TYPE load_addr, _dl_progname = argv[0]; } +#ifdef __DSBT__ + _dl_ldso_dsbt = (void *)tpnt->dynamic_info[DT_DSBT_BASE_IDX]; + _dl_ldso_dsbt[tpnt->dynamic_info[DT_DSBT_INDEX_IDX]] = _dl_ldso_dsbt; +#endif + #ifndef __LDSO_STANDALONE_SUPPORT__ if (_start == (void *) auxvt[AT_ENTRY].a_un.a_val) { _dl_dprintf(_dl_debug_file, "Standalone execution is not enabled\n"); @@ -688,6 +697,11 @@ of this helper program; chances are you did not intend to run this program.\n\ app_tpnt->mapaddr = app_mapaddr; app_tpnt->rtld_flags = unlazy | RTLD_GLOBAL; app_tpnt->usage_count++; +#ifdef __DSBT__ + _dl_ldso_dsbt[0] = app_tpnt->dsbt_table; + _dl_memcpy(app_tpnt->dsbt_table, _dl_ldso_dsbt, + app_tpnt->dsbt_size * sizeof(tpnt->dsbt_table[0])); +#endif lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]); #ifdef ALLOW_ZERO_PLTGOT if (lpnt) |