Index: ELF/Arch/PPC64.cpp =================================================================== --- ELF/Arch/PPC64.cpp +++ ELF/Arch/PPC64.cpp @@ -156,6 +156,11 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S, const uint8_t *Loc) const { switch (Type) { + case R_PPC64_DTPREL16: + case R_PPC64_DTPREL16_HA: + case R_PPC64_DTPREL16_LO: + case R_PPC64_DTPREL16_LO_DS: + return R_ABS; case R_PPC64_TOC16: case R_PPC64_TOC16_DS: case R_PPC64_TOC16_HA: @@ -232,8 +237,13 @@ } static std::pair toAddr16Rel(RelType Type, uint64_t Val) { + // For R_PPC64_DTPREL16* relocations, DTV pointer points 0x8000 bytes past the + // start of each TLS block. We also subtract 0x8000 (which equals to + // PPC64TocOffset) from Val to calculate the offset and thus can use the same + // formula. uint64_t V = Val - PPC64TocOffset; switch (Type) { + case R_PPC64_DTPREL16: case R_PPC64_GOT_TLSGD16: case R_PPC64_GOT_TLSLD16: case R_PPC64_TOC16: @@ -241,20 +251,24 @@ case R_PPC64_TOC16_DS: case R_PPC64_GOT_TPREL16_DS: return {R_PPC64_ADDR16_DS, V}; + case R_PPC64_DTPREL16_HA: case R_PPC64_GOT_TLSGD16_HA: case R_PPC64_GOT_TLSLD16_HA: case R_PPC64_GOT_TPREL16_HA: case R_PPC64_TOC16_HA: return {R_PPC64_ADDR16_HA, V}; + case R_PPC64_DTPREL16_HI: case R_PPC64_GOT_TLSGD16_HI: case R_PPC64_GOT_TLSLD16_HI: case R_PPC64_GOT_TPREL16_HI: case R_PPC64_TOC16_HI: return {R_PPC64_ADDR16_HI, V}; + case R_PPC64_DTPREL16_LO: case R_PPC64_GOT_TLSGD16_LO: case R_PPC64_GOT_TLSLD16_LO: case R_PPC64_TOC16_LO: return {R_PPC64_ADDR16_LO, V}; + case R_PPC64_DTPREL16_LO_DS: case R_PPC64_TOC16_LO_DS: case R_PPC64_GOT_TPREL16_LO_DS: return {R_PPC64_ADDR16_LO_DS, V}; Index: test/ELF/ppc64-local-dynamic.s =================================================================== --- test/ELF/ppc64-local-dynamic.s +++ test/ELF/ppc64-local-dynamic.s @@ -32,6 +32,9 @@ addi 3, 3, i@got@tlsld@l bl __tls_get_addr(i@tlsld) nop + addi 4, 3, i@dtprel + addis 4, 3, j@dtprel@ha + addi 4, 4, j@dtprel@l ld 0, 16(1) mtlr 0 blr @@ -76,6 +79,9 @@ // InputRelocs: R_PPC64_GOT_TLSLD16_HA 0000000000000000 i + 0 // InputRelocs: R_PPC64_GOT_TLSLD16_LO 0000000000000000 i + 0 // InputRelocs: R_PPC64_TLSLD 0000000000000000 i + 0 +// InputRelocs: R_PPC64_DTPREL16 0000000000000000 i + 0 +// InputRelocs: R_PPC64_DTPREL16_HA 0000000000000000 j + 0 +// InputRelocs: R_PPC64_DTPREL16_LO 0000000000000000 j + 0 // InputRelocs: R_PPC64_GOT_TLSLD16_HI 0000000000000000 j + 0 // InputRelocs: R_PPC64_GOT_TLSLD16 0000000000000008 k + 0 @@ -99,9 +105,15 @@ // #ha(i@got@tlsld) --> (0x20108 - 0x28100 + 0x8000) >> 16 = 0 // #lo(i@got@tlsld) --> (0x20108 - 0x28100) = -7ff8 = -32760 +// i@dtprel --> (0x0 - 0x8000) = -32768 +// #ha(j@dtprel) --> (0x10 - 0x8000 + 0x8000) >> 16 = 0 +// #lo(j@dtprel) --> (0x10 - 0x8000) & 0xffff = -32752 // Dis: test: // Dis: addis 3, 2, 0 // Dis-NEXT: addi 3, 3, -32760 +// Dis: addi 4, 3, -32768 +// Dis-NEXT: addis 4, 3, 0 +// Dis-NEXT: addi 4, 4, -32752 // #hi(j@got@tlsld) --> (0x20108 - 0x28100 ) > 16 = -1 // Dis: test_hi: