[Patch v2 1/2] Clean up DSBT support

Mark Salter msalter at redhat.com
Tue May 22 14:53:29 UTC 2012


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 at redhat.com>
---
 ldso/include/dl-elf.h  |    5 ---
 ldso/include/dl-hash.h |    6 ++++
 ldso/include/ldso.h    |    3 ++
 ldso/ldso/dl-elf.c     |   70 +++++++++++++++++++++++------------------------
 ldso/ldso/dl-hash.c    |    9 ++++++
 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 29d1a00..060ee3d 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 c7effc5..7bccdca 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 6f3b728..cb7b122 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 9e2a12c..31ba11f 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 36ebec6..2c659dc 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 8cfb03f..f2ba628 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)
-- 
1.7.9.1



More information about the uClibc mailing list