Browse Source

Support dynamic assignment of DSBT_INDEX

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@codesourcery.com>
Bernd Schmidt 14 years ago
parent
commit
feb7ce46ef
2 changed files with 34 additions and 6 deletions
  1. 5 1
      ldso/ldso/c6x/elfinterp.c
  2. 29 5
      ldso/ldso/dl-elf.c

+ 5 - 1
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) */
 	}

+ 29 - 5
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) {