diff options
author | H.J. Lu <hjl.tools@gmail.com> | 2012-05-10 10:05:40 -0700 |
---|---|---|
committer | H.J. Lu <hjl.tools@gmail.com> | 2012-05-10 10:05:40 -0700 |
commit | c8c59454eac603f75e8e037d290e595abeda2af5 (patch) | |
tree | f60350c1498dd1251d7f7ad85b51ee002bcef53a /sysdeps/x86_64 | |
parent | 6f27cd16593d0c095bb1b90787bee70910d3a609 (diff) | |
download | glibc-c8c59454eac603f75e8e037d290e595abeda2af5.tar.gz glibc-c8c59454eac603f75e8e037d290e595abeda2af5.tar.xz glibc-c8c59454eac603f75e8e037d290e595abeda2af5.zip |
Sign extend R_X86_64_DTPOFF64/R_X86_64_TPOFF64
Diffstat (limited to 'sysdeps/x86_64')
-rw-r--r-- | sysdeps/x86_64/dl-machine.h | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h index d1906a4b66..cf49d42925 100644 --- a/sysdeps/x86_64/dl-machine.h +++ b/sysdeps/x86_64/dl-machine.h @@ -328,7 +328,19 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, /* During relocation all TLS symbols are defined and used. Therefore the offset is already correct. */ if (sym != NULL) - *reloc_addr = sym->st_value + reloc->r_addend; + { + value = sym->st_value + reloc->r_addend; +# ifdef __ILP32__ + /* This relocation type computes a signed offset that is + usually negative. The symbol and addend values are 32 + bits but the GOT entry is 64 bits wide and the whole + 64-bit entry is used as a signed quantity, so we need + to sign-extend the computed value to 64 bits. */ + *(Elf64_Sxword *) reloc_addr = (Elf64_Sxword) (Elf32_Sxword) value; +# else + *reloc_addr = value; +# endif + } # endif break; case R_X86_64_TLSDESC: @@ -378,8 +390,17 @@ elf_machine_rela (struct link_map *map, const ElfW(Rela) *reloc, /* We know the offset of the object the symbol is contained in. It is a negative value which will be added to the thread pointer. */ - *reloc_addr = (sym->st_value + reloc->r_addend - - sym_map->l_tls_offset); + value = (sym->st_value + reloc->r_addend + - sym_map->l_tls_offset); +# ifdef __ILP32__ + /* The symbol and addend values are 32 bits but the GOT + entry is 64 bits wide and the whole 64-bit entry is used + as a signed quantity, so we need to sign-extend the + computed value to 64 bits. */ + *(Elf64_Sxword *) reloc_addr = (Elf64_Sxword) (Elf32_Sword) value; +# else + *reloc_addr = value; +# endif } break; # endif |