summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Salter <msalter@redhat.com>2012-05-22 10:53:29 -0400
committerBernhard Reutner-Fischer <rep.dot.nop@gmail.com>2012-06-06 09:06:10 +0200
commit8554fb21bb34329201b38c2ae4387fb6f00645cc (patch)
tree462975e36aee3b3ff726e3300ead039e4da1fb3c
parent80c9bfc4668e2370b3434a801dc266f336265832 (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>
-rw-r--r--ldso/include/dl-elf.h5
-rw-r--r--ldso/include/dl-hash.h6
-rw-r--r--ldso/include/ldso.h3
-rw-r--r--ldso/ldso/dl-elf.c70
-rw-r--r--ldso/ldso/dl-hash.c9
-rw-r--r--ldso/ldso/ldso.c14
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)