riscv64 TLS support.
Signed-off-by: Mao Han <han_mao@linux.alibaba.com> Signed-off-by: Xia Lifang <lifang_xia@linux.alibaba.com> Signed-off-by: Chen Guoyin <chenguoyin.cgy@linux.alibaba.com> Signed-off-by: Wang Chen <wangchen20@iscas.ac.cn> Signed-off-by: Lu Xufan <luxufan@iscas.ac.cn> Test: treehugger Change-Id: I14efb4a03a3dc2ec736d7e47a3f8859c886eb9d6
This commit is contained in:
parent
c6bddf4516
commit
43462707a1
|
@ -137,6 +137,15 @@ size_t StaticTlsLayout::reserve_exe_segment_and_tcb(const TlsSegment* exe_segmen
|
||||||
offset_bionic_tcb_ = reserve(sizeof(bionic_tcb), max_align);
|
offset_bionic_tcb_ = reserve(sizeof(bionic_tcb), max_align);
|
||||||
return offset_bionic_tcb_ - exe_size;
|
return offset_bionic_tcb_ - exe_size;
|
||||||
|
|
||||||
|
#elif defined(__riscv)
|
||||||
|
|
||||||
|
// First reserve enough space for the TCB before the executable segment.
|
||||||
|
offset_bionic_tcb_ = reserve(sizeof(bionic_tcb), 1);
|
||||||
|
|
||||||
|
// Then reserve the segment itself.
|
||||||
|
const size_t exe_size = round_up_with_overflow_check(exe_segment->size, exe_segment->alignment);
|
||||||
|
return reserve(exe_size, 1);
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#error "Unrecognized architecture"
|
#error "Unrecognized architecture"
|
||||||
#endif
|
#endif
|
||||||
|
@ -312,7 +321,7 @@ __attribute__((noinline)) static void* tls_get_addr_slow_path(const TlsIndex* ti
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return static_cast<char*>(mod_ptr) + ti->offset;
|
return static_cast<char*>(mod_ptr) + ti->offset + TLS_DTV_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns the address of a thread's TLS memory given a module ID and an offset
|
// Returns the address of a thread's TLS memory given a module ID and an offset
|
||||||
|
@ -332,7 +341,7 @@ extern "C" void* TLS_GET_ADDR(const TlsIndex* ti) TLS_GET_ADDR_CCONV {
|
||||||
if (__predict_true(generation == dtv->generation)) {
|
if (__predict_true(generation == dtv->generation)) {
|
||||||
void* mod_ptr = dtv->modules[__tls_module_id_to_idx(ti->module_id)];
|
void* mod_ptr = dtv->modules[__tls_module_id_to_idx(ti->module_id)];
|
||||||
if (__predict_true(mod_ptr != nullptr)) {
|
if (__predict_true(mod_ptr != nullptr)) {
|
||||||
return static_cast<char*>(mod_ptr) + ti->offset;
|
return static_cast<char*>(mod_ptr) + ti->offset + TLS_DTV_OFFSET;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -114,6 +114,28 @@
|
||||||
#define TLS_SLOT_BIONIC_TLS 9
|
#define TLS_SLOT_BIONIC_TLS 9
|
||||||
#define MAX_TLS_SLOT 9 // update this value when reserving a slot
|
#define MAX_TLS_SLOT 9 // update this value when reserving a slot
|
||||||
|
|
||||||
|
#elif defined(__riscv)
|
||||||
|
|
||||||
|
// RISC-V ELF Specification[1] specifies that RISC-V uses Variant I as described
|
||||||
|
// by the ELF TLS specification, with tp containing the address one past the end
|
||||||
|
// of the TCB.
|
||||||
|
//
|
||||||
|
// [1]: RISC-V ELF Specification. Section: Thread Local Storage
|
||||||
|
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#thread-local-storage
|
||||||
|
|
||||||
|
#define MIN_TLS_SLOT (-9) // update this value when reserving a slot
|
||||||
|
|
||||||
|
#define TLS_SLOT_BIONIC_TLS (-9)
|
||||||
|
#define TLS_SLOT_DTV (-8)
|
||||||
|
#define TLS_SLOT_THREAD_ID (-7)
|
||||||
|
#define TLS_SLOT_APP (-6)
|
||||||
|
#define TLS_SLOT_OPENGL (-5)
|
||||||
|
#define TLS_SLOT_OPENGL_API (-4)
|
||||||
|
#define TLS_SLOT_STACK_GUARD (-3)
|
||||||
|
#define TLS_SLOT_SANITIZER (-2)
|
||||||
|
#define TLS_SLOT_ART_THREAD_SELF (-1)
|
||||||
|
#define MAX_TLS_SLOT (-1)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define BIONIC_TLS_SLOTS (MAX_TLS_SLOT - MIN_TLS_SLOT + 1)
|
#define BIONIC_TLS_SLOTS (MAX_TLS_SLOT - MIN_TLS_SLOT + 1)
|
||||||
|
|
|
@ -201,3 +201,18 @@ extern "C" void* TLS_GET_ADDR(const TlsIndex* ti) TLS_GET_ADDR_CCONV;
|
||||||
struct bionic_tcb;
|
struct bionic_tcb;
|
||||||
void __free_dynamic_tls(bionic_tcb* tcb);
|
void __free_dynamic_tls(bionic_tcb* tcb);
|
||||||
void __notify_thread_exit_callbacks();
|
void __notify_thread_exit_callbacks();
|
||||||
|
|
||||||
|
#if defined(__riscv)
|
||||||
|
// TLS_DTV_OFFSET is a constant used in relocation fields, defined in RISC-V ELF Specification[1]
|
||||||
|
// The front of the TCB contains a pointer to the DTV, and each pointer in DTV
|
||||||
|
// points to 0x800 past the start of a TLS block to make full use of the range
|
||||||
|
// of load/store instructions, refer to [2].
|
||||||
|
//
|
||||||
|
// [1]: RISC-V ELF Specification.
|
||||||
|
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#constants
|
||||||
|
// [2]: Documentation of TLS data structures
|
||||||
|
// https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/53
|
||||||
|
#define TLS_DTV_OFFSET 0x800
|
||||||
|
#else
|
||||||
|
#define TLS_DTV_OFFSET 0
|
||||||
|
#endif
|
||||||
|
|
|
@ -371,7 +371,7 @@ static inline void* get_tls_block_for_this_thread(const soinfo_tls* si_tls, bool
|
||||||
char* static_tls = reinterpret_cast<char*>(__get_bionic_tcb()) - layout.offset_bionic_tcb();
|
char* static_tls = reinterpret_cast<char*>(__get_bionic_tcb()) - layout.offset_bionic_tcb();
|
||||||
return static_tls + tls_mod.static_offset;
|
return static_tls + tls_mod.static_offset;
|
||||||
} else if (should_alloc) {
|
} else if (should_alloc) {
|
||||||
const TlsIndex ti { si_tls->module_id, 0 };
|
const TlsIndex ti { si_tls->module_id, static_cast<size_t>(0 - TLS_DTV_OFFSET) };
|
||||||
return TLS_GET_ADDR(&ti);
|
return TLS_GET_ADDR(&ti);
|
||||||
} else {
|
} else {
|
||||||
TlsDtv* dtv = __get_tcb_dtv(__get_bionic_tcb());
|
TlsDtv* dtv = __get_tcb_dtv(__get_bionic_tcb());
|
||||||
|
|
|
@ -51,6 +51,8 @@ static int GetTargetElfMachine() {
|
||||||
return EM_AARCH64;
|
return EM_AARCH64;
|
||||||
#elif defined(__i386__)
|
#elif defined(__i386__)
|
||||||
return EM_386;
|
return EM_386;
|
||||||
|
#elif defined(__riscv)
|
||||||
|
return EM_RISCV;
|
||||||
#elif defined(__x86_64__)
|
#elif defined(__x86_64__)
|
||||||
return EM_X86_64;
|
return EM_X86_64;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -49,7 +49,9 @@ static bool is_tls_reloc(ElfW(Word) type) {
|
||||||
case R_GENERIC_TLS_DTPMOD:
|
case R_GENERIC_TLS_DTPMOD:
|
||||||
case R_GENERIC_TLS_DTPREL:
|
case R_GENERIC_TLS_DTPREL:
|
||||||
case R_GENERIC_TLS_TPREL:
|
case R_GENERIC_TLS_TPREL:
|
||||||
|
#if defined(R_GENERIC_TLSDESC)
|
||||||
case R_GENERIC_TLSDESC:
|
case R_GENERIC_TLSDESC:
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
|
@ -426,7 +428,7 @@ static bool process_relocation_impl(Relocator& relocator, const rel_t& reloc) {
|
||||||
case R_GENERIC_TLS_DTPREL:
|
case R_GENERIC_TLS_DTPREL:
|
||||||
count_relocation_if<IsGeneral>(kRelocRelative);
|
count_relocation_if<IsGeneral>(kRelocRelative);
|
||||||
{
|
{
|
||||||
const ElfW(Addr) result = sym_addr + get_addend_rel();
|
const ElfW(Addr) result = sym_addr + get_addend_rel() - TLS_DTV_OFFSET;
|
||||||
trace_reloc("RELO TLS_DTPREL %16p <- %16p %s",
|
trace_reloc("RELO TLS_DTPREL %16p <- %16p %s",
|
||||||
rel_target, reinterpret_cast<void*>(result), sym_name);
|
rel_target, reinterpret_cast<void*>(result), sym_name);
|
||||||
*static_cast<ElfW(Addr)*>(rel_target) = result;
|
*static_cast<ElfW(Addr)*>(rel_target) = result;
|
||||||
|
|
|
@ -73,6 +73,20 @@
|
||||||
#define R_GENERIC_TLS_TPREL R_386_TLS_TPOFF
|
#define R_GENERIC_TLS_TPREL R_386_TLS_TPOFF
|
||||||
#define R_GENERIC_TLSDESC R_386_TLS_DESC
|
#define R_GENERIC_TLSDESC R_386_TLS_DESC
|
||||||
|
|
||||||
|
#elif defined (__riscv)
|
||||||
|
|
||||||
|
#define R_GENERIC_JUMP_SLOT R_RISCV_JUMP_SLOT
|
||||||
|
#define R_GENERIC_ABSOLUTE R_RISCV_64
|
||||||
|
#define R_GENERIC_GLOB_DAT R_RISCV_64
|
||||||
|
#define R_GENERIC_RELATIVE R_RISCV_RELATIVE
|
||||||
|
#define R_GENERIC_IRELATIVE R_RISCV_IRELATIVE
|
||||||
|
#define R_GENERIC_COPY R_RISCV_COPY
|
||||||
|
#define R_GENERIC_TLS_DTPMOD R_RISCV_TLS_DTPMOD64
|
||||||
|
#define R_GENERIC_TLS_DTPREL R_RISCV_TLS_DTPREL64
|
||||||
|
#define R_GENERIC_TLS_TPREL R_RISCV_TLS_TPREL64
|
||||||
|
// TODO: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/issues/94
|
||||||
|
// #define R_GENERIC_TLSDESC R_RISCV_TLS_DESC
|
||||||
|
|
||||||
#elif defined (__x86_64__)
|
#elif defined (__x86_64__)
|
||||||
|
|
||||||
#define R_GENERIC_JUMP_SLOT R_X86_64_JUMP_SLOT
|
#define R_GENERIC_JUMP_SLOT R_X86_64_JUMP_SLOT
|
||||||
|
|
Loading…
Reference in New Issue