[git commit prelink] Support dynamic assignment of DSBT_INDEX

Bernd Schmidt bernds at codesourcery.com
Wed May 4 06:33:44 UTC 2011


commit: http://git.uclibc.org/uClibc/commit/?id=feb7ce46ef24f74ebf0235f10127bd49f0c7e675
branch: http://git.uclibc.org/uClibc/commit/?id=refs/heads/prelink

For DSBT targets (C6X only at this point), we'd like to support the case
where the user did not specify --dsbt-index at link time when building a
shared library. The dynamic linker can still assign an index at runtime
and fix up the DSBT_INDEX relocs, at the cost of startup time and memory
space.

Signed-off-by: Bernd Schmidt <bernds at codesourcery.com>
---
 ldso/ldso/c6x/elfinterp.c |    6 +++++-
 ldso/ldso/dl-elf.c        |   34 +++++++++++++++++++++++++++++-----
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/ldso/ldso/c6x/elfinterp.c b/ldso/ldso/c6x/elfinterp.c
index 7c79171..f5d3ad4 100644
--- a/ldso/ldso/c6x/elfinterp.c
+++ b/ldso/ldso/c6x/elfinterp.c
@@ -198,6 +198,10 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 		new_val = sym_val;
 		*reloc_addr = sym_val;
 		break;
+	case R_C6000_DSBT_INDEX:
+		new_val = (old_val & ~0x007fff00) | ((tpnt->loadaddr.map->dsbt_index & 0x7fff) << 8);
+		*reloc_addr = new_val;
+		break;
 	case R_C6000_ABS_L16:
 		new_val = (old_val & ~0x007fff80) | ((sym_val & 0xffff) << 7);
 		*reloc_addr = new_val;
@@ -224,7 +228,7 @@ _dl_do_reloc (struct elf_resolve *tpnt,struct dyn_elf *scope,
 				   (char *)symbol_addr,
 				   symtab[symtab_index].st_size);
 		}
-		break;
+		return 0;
 	default:
 		return -1; /*call _dl_exit(1) */
 	}
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c
index 91e8a97..7b5d751 100644
--- a/ldso/ldso/dl-elf.c
+++ b/ldso/ldso/dl-elf.c
@@ -811,20 +811,44 @@ struct elf_resolve *_dl_load_elf_shared_library(int secure,
 #ifdef __DSBT__
 	/* Handle DSBT initialization */
 	{
-		struct elf_resolve *t, *ref = NULL;
+		struct elf_resolve *t, *ref;
 		int idx = tpnt->loadaddr.map->dsbt_index;
 		unsigned *dsbt = tpnt->loadaddr.map->dsbt_table;
 
 		if (idx == 0) {
-			/* This DSO has not been assigned an index */
-			_dl_dprintf(2, "%s: '%s' is missing a dsbt index assignment!\n",
-				    _dl_progname, libname);
-			_dl_exit(1);
+			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",
+					    _dl_progname, libname);
+				_dl_exit(1);
+			}
+			/* Find a dsbt table from another module. */
+			ref = NULL;
+			for (t = _dl_loaded_modules; t; t = t->next) {
+				if (ref == NULL && t != tpnt) {
+					ref = t;
+					break;
+				}
+			}
+			idx = tpnt->loadaddr.map->dsbt_size;
+			while (idx-- > 0)
+				if (!ref || ref->loadaddr.map->dsbt_table[idx] == NULL)
+					break;
+			if (idx <= 0) {
+				_dl_dprintf(2, "%s: '%s' caused DSBT table overflow!\n",
+					    _dl_progname, libname);
+				_dl_exit(1);
+			}
+			_dl_if_debug_dprint("\n\tfile='%s';  assigned index %d\n",
+					    libname, idx);
+			tpnt->loadaddr.map->dsbt_index = idx;
+
 		}
 
 		/*
 		 * 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) {
-- 
1.7.3.4



More information about the uClibc-cvs mailing list