runtime_loader: support linking TLS symbols from any DSO

Previously TLS_DTPMOD relocation blindly returned ID of the current DSO.
This patch does proper symbol lookup if there is a symbol assigned to the
relocation and uses ID of the DSO in which the symbol is defined.
This commit is contained in:
Pawel Dziepak
2014-05-04 12:21:26 +02:00
parent 0427af0c09
commit df58e6a9f4
4 changed files with 23 additions and 25 deletions
@@ -31,29 +31,22 @@ relocate_rel(image_t *rootImage, image_t *image, struct Elf32_Rel *rel,
for (i = 0; i * (int)sizeof(struct Elf32_Rel) < rel_len; i++) {
unsigned type = ELF32_R_TYPE(rel[i].r_info);
unsigned symbolIndex = ELF32_R_SYM(rel[i].r_info);
switch (type) {
case R_386_32:
case R_386_PC32:
case R_386_GLOB_DAT:
case R_386_JMP_SLOT:
case R_386_GOTOFF:
case R_386_TLS_DTPOFF32:
{
struct Elf32_Sym *sym;
status_t status;
sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
status = resolve_symbol(rootImage, image, sym, cache, &S);
if (status < B_OK) {
TRACE(("resolve symbol \"%s\" returned: %ld\n",
SYMNAME(image, sym), status));
printf("resolve symbol \"%s\" returned: %ld\n",
SYMNAME(image, sym), status);
return status;
}
image_t* symbolImage = NULL;
if (symbolIndex != 0) {
Elf32_Sym* sym = SYMBOL(image, symbolIndex);
status_t status = resolve_symbol(rootImage, image, sym, cache, &S,
&symbolImage);
if (status < B_OK) {
TRACE(("resolve symbol \"%s\" returned: %ld\n",
SYMNAME(image, sym), status));
printf("resolve symbol \"%s\" returned: %ld\n",
SYMNAME(image, sym), status);
return status;
}
}
switch (type) {
case R_386_NONE:
continue;
@@ -92,7 +85,8 @@ relocate_rel(image_t *rootImage, image_t *image, struct Elf32_Rel *rel,
break;
#endif
case R_386_TLS_DTPMOD32:
final_val = image->dso_tls_id;
final_val = symbolImage == NULL
? image->dso_tls_id : symbolImage->dso_tls_id;
break;
case R_386_TLS_DTPOFF32:
final_val = S;
@@ -21,13 +21,14 @@ relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel,
int type = ELF64_R_TYPE(rel[i].r_info);
int symIndex = ELF64_R_SYM(rel[i].r_info);
Elf64_Addr symAddr = 0;
image_t* symbolImage = NULL;
// Resolve the symbol, if any.
if (symIndex != 0) {
Elf64_Sym* sym = SYMBOL(image, symIndex);
status_t status = resolve_symbol(rootImage, image, sym, cache,
&symAddr);
&symAddr, &symbolImage);
if (status != B_OK) {
TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
SYMNAME(image, sym), status));
@@ -57,7 +58,8 @@ relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel,
relocValue = image->regions[0].delta + rel[i].r_addend;
break;
case R_X86_64_DTPMOD64:
relocValue = image->dso_tls_id;
relocValue = symbolImage == NULL
? image->dso_tls_id : symbolImage->dso_tls_id;
break;
case R_X86_64_DTPOFF32:
case R_X86_64_DTPOFF64:
@@ -474,7 +474,7 @@ find_undefined_symbol_add_on(image_t* rootImage, image_t* image,
int
resolve_symbol(image_t* rootImage, image_t* image, elf_sym* sym,
SymbolLookupCache* cache, addr_t* symAddress)
SymbolLookupCache* cache, addr_t* symAddress, image_t** symbolImage)
{
uint32 index = sym - image->syms;
@@ -581,6 +581,8 @@ resolve_symbol(image_t* rootImage, image_t* image, elf_sym* sym,
cache->SetSymbolValueAt(index, (addr_t)location);
if (symbolImage)
*symbolImage = sharedImage;
*symAddress = (addr_t)location;
return B_OK;
}
@@ -76,7 +76,7 @@ status_t get_library_symbol(void* handle, void* caller, const char* symbolName,
status_t get_next_image_dependency(image_id id, uint32* cookie,
const char** _name);
int resolve_symbol(image_t* rootImage, image_t* image, elf_sym* sym,
SymbolLookupCache* cache, addr_t* sym_addr);
SymbolLookupCache* cache, addr_t* sym_addr, image_t** symbolImage = NULL);
status_t elf_verify_header(void* header, size_t length);