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++) {
|
for (i = 0; i * (int)sizeof(struct Elf32_Rel) < rel_len; i++) {
|
||||||
unsigned type = ELF32_R_TYPE(rel[i].r_info);
|
unsigned type = ELF32_R_TYPE(rel[i].r_info);
|
||||||
|
unsigned symbolIndex = ELF32_R_SYM(rel[i].r_info);
|
||||||
|
|
||||||
switch (type) {
|
image_t* symbolImage = NULL;
|
||||||
case R_386_32:
|
if (symbolIndex != 0) {
|
||||||
case R_386_PC32:
|
Elf32_Sym* sym = SYMBOL(image, symbolIndex);
|
||||||
case R_386_GLOB_DAT:
|
status_t status = resolve_symbol(rootImage, image, sym, cache, &S,
|
||||||
case R_386_JMP_SLOT:
|
&symbolImage);
|
||||||
case R_386_GOTOFF:
|
if (status < B_OK) {
|
||||||
case R_386_TLS_DTPOFF32:
|
TRACE(("resolve symbol \"%s\" returned: %ld\n",
|
||||||
{
|
SYMNAME(image, sym), status));
|
||||||
struct Elf32_Sym *sym;
|
printf("resolve symbol \"%s\" returned: %ld\n",
|
||||||
status_t status;
|
SYMNAME(image, sym), status);
|
||||||
sym = SYMBOL(image, ELF32_R_SYM(rel[i].r_info));
|
return status;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case R_386_NONE:
|
case R_386_NONE:
|
||||||
continue;
|
continue;
|
||||||
@@ -92,7 +85,8 @@ relocate_rel(image_t *rootImage, image_t *image, struct Elf32_Rel *rel,
|
|||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
case R_386_TLS_DTPMOD32:
|
case R_386_TLS_DTPMOD32:
|
||||||
final_val = image->dso_tls_id;
|
final_val = symbolImage == NULL
|
||||||
|
? image->dso_tls_id : symbolImage->dso_tls_id;
|
||||||
break;
|
break;
|
||||||
case R_386_TLS_DTPOFF32:
|
case R_386_TLS_DTPOFF32:
|
||||||
final_val = S;
|
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 type = ELF64_R_TYPE(rel[i].r_info);
|
||||||
int symIndex = ELF64_R_SYM(rel[i].r_info);
|
int symIndex = ELF64_R_SYM(rel[i].r_info);
|
||||||
Elf64_Addr symAddr = 0;
|
Elf64_Addr symAddr = 0;
|
||||||
|
image_t* symbolImage = NULL;
|
||||||
|
|
||||||
// Resolve the symbol, if any.
|
// Resolve the symbol, if any.
|
||||||
if (symIndex != 0) {
|
if (symIndex != 0) {
|
||||||
Elf64_Sym* sym = SYMBOL(image, symIndex);
|
Elf64_Sym* sym = SYMBOL(image, symIndex);
|
||||||
|
|
||||||
status_t status = resolve_symbol(rootImage, image, sym, cache,
|
status_t status = resolve_symbol(rootImage, image, sym, cache,
|
||||||
&symAddr);
|
&symAddr, &symbolImage);
|
||||||
if (status != B_OK) {
|
if (status != B_OK) {
|
||||||
TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
|
TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
|
||||||
SYMNAME(image, sym), status));
|
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;
|
relocValue = image->regions[0].delta + rel[i].r_addend;
|
||||||
break;
|
break;
|
||||||
case R_X86_64_DTPMOD64:
|
case R_X86_64_DTPMOD64:
|
||||||
relocValue = image->dso_tls_id;
|
relocValue = symbolImage == NULL
|
||||||
|
? image->dso_tls_id : symbolImage->dso_tls_id;
|
||||||
break;
|
break;
|
||||||
case R_X86_64_DTPOFF32:
|
case R_X86_64_DTPOFF32:
|
||||||
case R_X86_64_DTPOFF64:
|
case R_X86_64_DTPOFF64:
|
||||||
|
|||||||
@@ -474,7 +474,7 @@ find_undefined_symbol_add_on(image_t* rootImage, image_t* image,
|
|||||||
|
|
||||||
int
|
int
|
||||||
resolve_symbol(image_t* rootImage, image_t* image, elf_sym* sym,
|
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;
|
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);
|
cache->SetSymbolValueAt(index, (addr_t)location);
|
||||||
|
|
||||||
|
if (symbolImage)
|
||||||
|
*symbolImage = sharedImage;
|
||||||
*symAddress = (addr_t)location;
|
*symAddress = (addr_t)location;
|
||||||
return B_OK;
|
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,
|
status_t get_next_image_dependency(image_id id, uint32* cookie,
|
||||||
const char** _name);
|
const char** _name);
|
||||||
int resolve_symbol(image_t* rootImage, image_t* image, elf_sym* sym,
|
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);
|
status_t elf_verify_header(void* header, size_t length);
|
||||||
|
|||||||
Reference in New Issue
Block a user