Implement TLS_DTPMOD and TLS_DTPREL relocations
Generalize the omitted symbol and missing-TLS-segment behaviors to all TLS relocations. R_GENERIC_TLS_DTPMOD is a module ID, which starts at 1 for the executable. R_GENERIC_TLS_DTPREL is an offset from the start of a module to a specific TLS symbol. binutils currently disagrees with Bionic about the values of R_AARCH64_TLS_DTPMOD64 and R_AARCH64_TLS_DTPREL64, so disable DTPMOD/DTPREL for now on arm64. Bug: http://b/78026329 Test: bionic unit tests (Tests for dynamic TLS will be added later) Change-Id: I05c28d6a1036bdd6127f605036679b7475689445
This commit is contained in:
parent
ea41ab0548
commit
3b463cf7f4
1 changed files with 42 additions and 12 deletions
|
@ -2722,7 +2722,11 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
|||
soinfo* lsi = nullptr;
|
||||
|
||||
if (sym == 0) {
|
||||
// Do nothing.
|
||||
// By convention in ld.bfd and lld, an omitted symbol on a TLS relocation
|
||||
// is a reference to the current module.
|
||||
if (is_tls_reloc(type)) {
|
||||
lsi = this;
|
||||
}
|
||||
} else if (ELF_ST_BIND(symtab_[sym].st_info) == STB_LOCAL && is_tls_reloc(type)) {
|
||||
// In certain situations, the Gold linker accesses a TLS symbol using a
|
||||
// relocation to an STB_LOCAL symbol in .dynsym of either STT_SECTION or
|
||||
|
@ -2830,6 +2834,11 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
|||
sym_name, get_realpath());
|
||||
return false;
|
||||
}
|
||||
if (lsi->get_tls() == nullptr) {
|
||||
DL_ERR("TLS relocation refers to symbol \"%s\" in solib \"%s\" with no TLS segment",
|
||||
sym_name, lsi->get_realpath());
|
||||
return false;
|
||||
}
|
||||
sym_addr = s->st_value;
|
||||
} else {
|
||||
if (ELF_ST_TYPE(s->st_info) == STT_TLS) {
|
||||
|
@ -2916,16 +2925,12 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
|||
MARK(rel->r_offset);
|
||||
{
|
||||
ElfW(Addr) tpoff = 0;
|
||||
if (sym == 0) {
|
||||
// By convention in ld.bfd and lld, an omitted symbol
|
||||
// (ELFW(R_SYM) == 0) refers to the local module.
|
||||
lsi = this;
|
||||
}
|
||||
if (lsi == nullptr) {
|
||||
// Unresolved weak relocation. Leave tpoff at 0 to resolve
|
||||
// &weak_tls_symbol to __get_tls().
|
||||
} else if (soinfo_tls* lsi_tls = lsi->get_tls()) {
|
||||
const TlsModule& mod = get_tls_module(lsi_tls->module_id);
|
||||
} else {
|
||||
CHECK(lsi->get_tls() != nullptr); // We rejected a missing TLS segment above.
|
||||
const TlsModule& mod = get_tls_module(lsi->get_tls()->module_id);
|
||||
if (mod.static_offset != SIZE_MAX) {
|
||||
tpoff += mod.static_offset - tls_tp_base;
|
||||
} else {
|
||||
|
@ -2933,10 +2938,6 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
|||
sym_name, lsi->get_realpath(), get_realpath());
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
DL_ERR("TLS relocation refers to symbol \"%s\" in solib \"%s\" with no TLS segment",
|
||||
sym_name, lsi->get_realpath());
|
||||
return false;
|
||||
}
|
||||
tpoff += sym_addr + addend;
|
||||
TRACE_TYPE(RELO, "RELO TLS_TPREL %16p <- %16p %s\n",
|
||||
|
@ -2946,6 +2947,35 @@ bool soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& r
|
|||
}
|
||||
break;
|
||||
|
||||
#if !defined(__aarch64__)
|
||||
// Omit support for DTPMOD/DTPREL on arm64, at least until
|
||||
// http://b/123385182 is fixed. arm64 uses TLSDESC instead.
|
||||
case R_GENERIC_TLS_DTPMOD:
|
||||
count_relocation(kRelocRelative);
|
||||
MARK(rel->r_offset);
|
||||
{
|
||||
size_t module_id = 0;
|
||||
if (lsi == nullptr) {
|
||||
// Unresolved weak relocation. Evaluate the module ID to 0.
|
||||
} else {
|
||||
CHECK(lsi->get_tls() != nullptr); // We rejected a missing TLS segment above.
|
||||
module_id = lsi->get_tls()->module_id;
|
||||
}
|
||||
TRACE_TYPE(RELO, "RELO TLS_DTPMOD %16p <- %zu %s\n",
|
||||
reinterpret_cast<void*>(reloc), module_id, sym_name);
|
||||
*reinterpret_cast<ElfW(Addr)*>(reloc) = module_id;
|
||||
}
|
||||
break;
|
||||
case R_GENERIC_TLS_DTPREL:
|
||||
count_relocation(kRelocRelative);
|
||||
MARK(rel->r_offset);
|
||||
TRACE_TYPE(RELO, "RELO TLS_DTPREL %16p <- %16p %s\n",
|
||||
reinterpret_cast<void*>(reloc),
|
||||
reinterpret_cast<void*>(sym_addr + addend), sym_name);
|
||||
*reinterpret_cast<ElfW(Addr)*>(reloc) = sym_addr + addend;
|
||||
break;
|
||||
#endif // !defined(__aarch64__)
|
||||
|
||||
#if defined(__aarch64__)
|
||||
case R_AARCH64_ABS64:
|
||||
count_relocation(kRelocAbsolute);
|
||||
|
|
Loading…
Reference in a new issue