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:
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user