diff options
author | Bernd Schmidt <bernds@codesourcery.com> | 2011-04-11 13:21:23 +0200 |
---|---|---|
committer | Bernd Schmidt <bernds@codesourcery.com> | 2011-04-11 13:27:03 +0200 |
commit | feb7ce46ef24f74ebf0235f10127bd49f0c7e675 (patch) | |
tree | 3369d611fd697300b39b9f9b6f0cea4f06bd8ae7 | |
parent | eff2d0ba5890b517ef5bc9d0269d6149556c12c8 (diff) |
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>
-rw-r--r-- | ldso/ldso/c6x/elfinterp.c | 6 | ||||
-rw-r--r-- | 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 7c79171ce..f5d3ad41e 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 91e8a97ca..7b5d75146 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) { |