static void relaxTlsGdToLe(uint8_t *loc, const Relocation &rel, uint64_t val) {
if (rel.type == R_386_TLS_GD) {
- // Convert
+ // Convert (loc[-2] == 0x04)
// leal x@tlsgd(, %ebx, 1), %eax
- // call __tls_get_addr@plt
+ // call ___tls_get_addr@plt
+ // or
+ // leal x@tlsgd(%reg), %eax
+ // call *___tls_get_addr@got(%reg)
// to
- // movl %gs:0, %eax
- // subl $x@tpoff, %eax
const uint8_t inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
- 0x81, 0xe8, 0, 0, 0, 0, // subl val(%ebx), %eax
+ 0x81, 0xe8, 0, 0, 0, 0, // subl x@ntpoff(%ebx), %eax
};
- memcpy(loc - 3, inst, sizeof(inst));
- write32le(loc + 5, val);
+ uint8_t *w = loc[-2] == 0x04 ? loc - 3 : loc - 2;
+ memcpy(w, inst, sizeof(inst));
+ write32le(w + 8, val);
} else if (rel.type == R_386_TLS_GOTDESC) {
// Convert leal x@tlsdesc(%ebx), %eax to leal x@ntpoff, %eax.
//
static void relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, uint64_t val) {
if (rel.type == R_386_TLS_GD) {
- // Convert
+ // Convert (loc[-2] == 0x04)
// leal x@tlsgd(, %ebx, 1), %eax
- // call __tls_get_addr@plt
- // to
- // movl %gs:0, %eax
- // addl x@gotntpoff(%ebx), %eax
+ // call ___tls_get_addr@plt
+ // or
+ // leal x@tlsgd(%reg), %eax
+ // call *___tls_get_addr@got(%reg)
const uint8_t inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
- 0x03, 0x83, 0, 0, 0, 0, // addl val(%ebx), %eax
+ 0x03, 0x83, 0, 0, 0, 0, // addl x@gottpoff(%ebx), %eax
};
- memcpy(loc - 3, inst, sizeof(inst));
- write32le(loc + 5, val);
+ uint8_t *w = loc[-2] == 0x04 ? loc - 3 : loc - 2;
+ memcpy(w, inst, sizeof(inst));
+ write32le(w + 8, val);
} else if (rel.type == R_386_TLS_GOTDESC) {
// Convert leal x@tlsdesc(%ebx), %eax to movl x@gotntpoff(%ebx), %eax.
if (memcmp(loc - 2, "\x8d\x83", 2)) {
return;
}
+ if (loc[4] == 0xe8) {
+ // Convert
+ // leal x(%reg),%eax
+ // call ___tls_get_addr@plt
+ // to
+ const uint8_t inst[] = {
+ 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
+ 0x90, // nop
+ 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi
+ };
+ memcpy(loc - 2, inst, sizeof(inst));
+ return;
+ }
+
// Convert
- // leal foo(%reg),%eax
- // call ___tls_get_addr
+ // leal x(%reg),%eax
+ // call *___tls_get_addr@got(%reg)
// to
- // movl %gs:0,%eax
- // nop
- // leal 0(%esi,1),%esi
const uint8_t inst[] = {
0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
- 0x90, // nop
- 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi
+ 0x8d, 0xb6, 0x00, 0x00, 0x00, 0x00, // leal (%esi),%esi
};
memcpy(loc - 2, inst, sizeof(inst));
}
// NORELOC: Relocations [
// NORELOC-NEXT: Section ({{.*}}) .rel.dyn {
-// NORELOC-NEXT: 0x402258 R_386_TLS_TPOFF tlsshared0
-// NORELOC-NEXT: 0x40225C R_386_TLS_TPOFF tlsshared1
+// NORELOC-NEXT: 0x402270 R_386_TLS_TPOFF tlsshared0
+// NORELOC-NEXT: 0x402274 R_386_TLS_TPOFF tlsshared1
// NORELOC-NEXT: }
// NORELOC-NEXT: ]
// DISASM-NEXT: subl $8, %eax
// DISASM-NEXT: movl %gs:0, %eax
// DISASM-NEXT: subl $4, %eax
+// DISASM-NEXT: movl %gs:0, %eax
+// DISASM-NEXT: addl -4100(%ebx), %eax
+// DISASM-NEXT: movl %gs:0, %eax
+// DISASM-NEXT: subl $4, %eax
.type tlsexe1,@object
.section .tbss,"awT",@nobits
call ___tls_get_addr@plt
leal tlsexe2@tlsgd(,%ebx,1),%eax
call ___tls_get_addr@plt
+
+// -fno-plt GD->IE and GD->LE
+leal tlsshared1@tlsgd(%edx),%eax
+call *___tls_get_addr@GOT(%edx)
+leal tlsexe2@tlsgd(%edx),%eax
+call *___tls_get_addr@GOT(%edx)