diff options
-rw-r--r-- | libexec/rtld-elf/powerpc/reloc.c | 68 | ||||
-rw-r--r-- | libexec/rtld-elf/powerpc/rtld_machdep.h | 8 | ||||
-rw-r--r-- | sys/powerpc/include/elf.h | 28 |
3 files changed, 101 insertions, 3 deletions
diff --git a/libexec/rtld-elf/powerpc/reloc.c b/libexec/rtld-elf/powerpc/reloc.c index 1f9f05a..b65e026 100644 --- a/libexec/rtld-elf/powerpc/reloc.c +++ b/libexec/rtld-elf/powerpc/reloc.c @@ -206,6 +206,58 @@ reloc_nonplt_object(Obj_Entry *obj_rtld, Obj_Entry *obj, const Elf_Rela *rela, */ break; + case R_PPC_DTPMOD32: + def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, + false, cache); + + if (def == NULL) + return (-1); + + *where = (Elf_Addr) defobj->tlsindex; + + break; + + case R_PPC_TPREL32: + def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, + false, cache); + + if (def == NULL) + return (-1); + + /* + * We lazily allocate offsets for static TLS as we + * see the first relocation that references the + * TLS block. This allows us to support (small + * amounts of) static TLS in dynamically loaded + * modules. If we run out of space, we generate an + * error. + */ + if (!defobj->tls_done) { + if (!allocate_tls_offset((Obj_Entry*) defobj)) { + _rtld_error("%s: No space available for static " + "Thread Local Storage", obj->path); + return (-1); + } + } + + *(Elf_Addr **)where = *where * sizeof(Elf_Addr) + + (Elf_Addr *)(def->st_value + rela->r_addend + + defobj->tlsoffset - TLS_TP_OFFSET - TLS_TCB_SIZE); + + break; + + case R_PPC_DTPREL32: + def = find_symdef(ELF_R_SYM(rela->r_info), obj, &defobj, + false, cache); + + if (def == NULL) + return (-1); + + *where += (Elf_Addr)(def->st_value + rela->r_addend + - TLS_DTV_OFFSET); + + break; + default: _rtld_error("%s: Unsupported relocation type %d" " in non-PLT relocations\n", obj->path, @@ -494,6 +546,7 @@ void allocate_initial_tls(Obj_Entry *list) { register Elf_Addr **tp __asm__("r2"); + Elf_Addr **_tp; /* * Fix the size of the static TLS block by using the maximum @@ -503,7 +556,14 @@ allocate_initial_tls(Obj_Entry *list) tls_static_space = tls_last_offset + tls_last_size + RTLD_STATIC_TLS_EXTRA; - tp = (Elf_Addr **) ((char *) allocate_tls(list, 0, 8, 8) + 0x7008); + _tp = (Elf_Addr **) ((char *) allocate_tls(list, 0, 8, 8) + + TLS_TP_OFFSET + TLS_TCB_SIZE); + + /* + * XXX gcc seems to ignore 'tp = _tp;' + */ + + __asm __volatile("mr %0,%1" : "=r"(tp) : "r"(_tp)); } void* @@ -512,6 +572,8 @@ __tls_get_addr(tls_index* ti) register Elf_Addr **tp __asm__("r2"); char *p; - p = tls_get_addr_common(tp, ti->ti_module, ti->ti_offset); - return p + 0x8000; + p = tls_get_addr_common((Elf_Addr**)((Elf_Addr)tp - TLS_TP_OFFSET + - TLS_TCB_SIZE), ti->ti_module, ti->ti_offset); + + return (p + TLS_DTV_OFFSET); } diff --git a/libexec/rtld-elf/powerpc/rtld_machdep.h b/libexec/rtld-elf/powerpc/rtld_machdep.h index 534882b..38e105d 100644 --- a/libexec/rtld-elf/powerpc/rtld_machdep.h +++ b/libexec/rtld-elf/powerpc/rtld_machdep.h @@ -62,6 +62,14 @@ void _rtld_bind_start(void); void _rtld_powerpc_pltresolve(void); void _rtld_powerpc_pltcall(void); +/* + * TLS + */ + +#define TLS_TP_OFFSET 0x7000 +#define TLS_DTV_OFFSET 0x8000 +#define TLS_TCB_SIZE 8 + #define round(size, align) \ (((size) + (align) - 1) & ~((align) - 1)) #define calculate_first_tls_offset(size, align) \ diff --git a/sys/powerpc/include/elf.h b/sys/powerpc/include/elf.h index 7fc1b36..4c64472 100644 --- a/sys/powerpc/include/elf.h +++ b/sys/powerpc/include/elf.h @@ -128,6 +128,34 @@ __ElfType(Auxinfo); #define R_PPC_COUNT 37 /* Count of defined relocation types. */ /* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* * The remaining relocs are from the Embedded ELF ABI, and are not in the * SVR4 ELF ABI. */ |