-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[X86][LLD] Handle R_X86_64_CODE_6_GOTTPOFF relocation type #117675
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
b9cfa55
8d56798
451a507
3f4aeab
6204ae1
23176d9
43d3c1b
78e0327
279cae2
645ecde
7e5beeb
9c9470e
c30d72b
c5f27c3
6e584af
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -401,6 +401,7 @@ RelExpr X86_64::getRelExpr(RelType type, const Symbol &s, | |
case R_X86_64_CODE_4_GOTPCRELX: | ||
case R_X86_64_GOTTPOFF: | ||
case R_X86_64_CODE_4_GOTTPOFF: | ||
case R_X86_64_CODE_6_GOTTPOFF: | ||
return R_GOT_PC; | ||
case R_X86_64_GOTOFF64: | ||
return R_GOTPLTREL; | ||
|
@@ -562,8 +563,9 @@ void X86_64::relaxTlsGdToIe(uint8_t *loc, const Relocation &rel, | |
} | ||
} | ||
|
||
// In some conditions, R_X86_64_GOTTPOFF/R_X86_64_CODE_4_GOTTPOFF relocation can | ||
// be optimized to R_X86_64_TPOFF32 so that it does not use GOT. | ||
// In some conditions, | ||
// R_X86_64_GOTTPOFF/R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_6_GOTTPOFF | ||
// relocation can be optimized to R_X86_64_TPOFF32 so that it does not use GOT. | ||
void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, | ||
uint64_t val) const { | ||
uint8_t *inst = loc - 3; | ||
|
@@ -605,7 +607,7 @@ void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, | |
} else if (rel.type == R_X86_64_CODE_4_GOTTPOFF) { | ||
if (loc[-4] != 0xd5) { | ||
Err(ctx) << getErrorLoc(ctx, loc - 4) | ||
<< "Invalid prefix with R_X86_64_CODE_4_GOTTPOFF!"; | ||
<< "invalid prefix with R_X86_64_CODE_4_GOTTPOFF!"; | ||
return; | ||
} | ||
const uint8_t rex = loc[-3]; | ||
|
@@ -623,6 +625,41 @@ void X86_64::relaxTlsIeToLe(uint8_t *loc, const Relocation &rel, | |
<< "R_X86_64_CODE_4_GOTTPOFF must be used in MOVQ or ADDQ " | ||
"instructions only"; | ||
} | ||
} else if (rel.type == R_X86_64_CODE_6_GOTTPOFF) { | ||
if (loc[-6] != 0x62) { | ||
Err(ctx) << getErrorLoc(ctx, loc - 6) | ||
<< "invalid prefix with R_X86_64_CODE_6_GOTTPOFF!"; | ||
return; | ||
} | ||
// Check bits are satisfied: | ||
// loc[-5]: X==1 (inverted polarity), (loc[-5] & 0x7) == 0x4 | ||
// loc[-4]: W==1, X2==1 (inverted polarity), pp==0b00(NP) | ||
// loc[-3]: NF==1 or ND==1 | ||
// loc[-2]: opcode==0x1 or opcode==0x3 | ||
// loc[-1]: Mod==0b00, RM==0b101 | ||
if (((loc[-5] & 0x47) == 0x44) && ((loc[-4] & 0x87) == 0x84) && | ||
((loc[-3] & 0x14) != 0) && (loc[-2] == 0x1 || loc[-2] == 0x3) && | ||
((loc[-1] & 0xc7) == 0x5)) { | ||
// "addq %reg1, foo@GOTTPOFF(%rip), %reg2" -> "addq $foo, %reg1, %reg2" | ||
// "addq foo@GOTTPOFF(%rip), %reg1, %reg2" -> "addq $foo, %reg1, %reg2" | ||
// "{nf} addq %reg1, foo@GOTTPOFF(%rip), %reg2" | ||
// -> "{nf} addq $foo, %reg1, %reg2" | ||
// "{nf} addq name@GOTTPOFF(%rip), %reg1, %reg2" | ||
// -> "{nf} addq $foo, %reg1, %reg2" | ||
// "{nf} addq name@GOTTPOFF(%rip), %reg" -> "{nf} addq $foo, %reg" | ||
loc[-2] = 0x81; | ||
// Move R bits to B bits in EVEX payloads and ModRM byte. | ||
const uint8_t evexPayload0 = loc[-5]; | ||
if ((evexPayload0 & (1 << 7)) == 0) | ||
loc[-5] = (evexPayload0 | (1 << 7)) & ~(1 << 5); | ||
if ((evexPayload0 & (1 << 4)) == 0) | ||
loc[-5] = evexPayload0 | (1 << 4) | (1 << 3); | ||
*regSlot = 0xc0 | reg; | ||
} else { | ||
Err(ctx) << getErrorLoc(ctx, loc - 6) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. new error messages must be tested There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. |
||
<< "R_X86_64_CODE_6_GOTTPOFF must be used in ADDQ instructions " | ||
"with NDD/NF/NDD+NF only"; | ||
} | ||
} else { | ||
llvm_unreachable("Unsupported relocation type!"); | ||
} | ||
|
@@ -782,6 +819,7 @@ int64_t X86_64::getImplicitAddend(const uint8_t *buf, RelType type) const { | |
case R_X86_64_PC32: | ||
case R_X86_64_GOTTPOFF: | ||
case R_X86_64_CODE_4_GOTTPOFF: | ||
case R_X86_64_CODE_6_GOTTPOFF: | ||
case R_X86_64_PLT32: | ||
case R_X86_64_TLSGD: | ||
case R_X86_64_TLSLD: | ||
|
@@ -893,6 +931,7 @@ void X86_64::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { | |
break; | ||
case R_X86_64_GOTTPOFF: | ||
case R_X86_64_CODE_4_GOTTPOFF: | ||
case R_X86_64_CODE_6_GOTTPOFF: | ||
if (rel.expr == R_RELAX_TLS_IE_TO_LE) { | ||
relaxTlsIeToLe(loc, rel, val); | ||
} else { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,15 @@ | ||
# REQUIRES: x86 | ||
|
||
# RUN: yaml2obj %s -o %t.o | ||
# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s | ||
# RUN: yaml2obj --docnum=1 %s -o %t1.o | ||
# RUN: not ld.lld %t1.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s | ||
# ERR: R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only | ||
# ERR: R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only | ||
|
||
## YAML below contains 2 relocations of type R_X86_64_GOTTPOFF, and a .text | ||
## with fake content filled by 0xFF. That means instructions for relaxation are | ||
## "broken", so they does not match any known valid relaxations. We also generate | ||
## .tls section because we need it for correct processing of STT_TLS symbol. | ||
!ELF | ||
--- !ELF | ||
FileHeader: | ||
Class: ELFCLASS64 | ||
Data: ELFDATA2LSB | ||
|
@@ -44,4 +44,132 @@ Symbols: | |
Value: 0x12345 | ||
Size: 4 | ||
Binding: STB_GLOBAL | ||
|
||
|
||
|
||
# RUN: yaml2obj --docnum=2 %s -o %t2.o | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for adding negative tests but YAML is not very readable. You can use assembly tests with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added one more assembly test. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is the new assembly test okay? |
||
# RUN: not ld.lld %t2.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR2 %s | ||
# ERR2: invalid prefix with R_X86_64_CODE_4_GOTTPOFF! | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We always test error: in error messages. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated. |
||
# ERR2: invalid prefix with R_X86_64_CODE_6_GOTTPOFF! | ||
|
||
## YAML below contains 2 relocations of | ||
## R_X86_64_CODE_4_GOTTPOFF/R_X86_64_CODE_6_GOTTPOFF type, and a .text with | ||
## fake content filled by 0xFF. It's expected to get "invalid prefix" error | ||
## message as above. | ||
--- !ELF | ||
FileHeader: | ||
Class: ELFCLASS64 | ||
Data: ELFDATA2LSB | ||
OSABI: ELFOSABI_FREEBSD | ||
Type: ET_REL | ||
Machine: EM_X86_64 | ||
Sections: | ||
- Type: SHT_PROGBITS | ||
Name: .text | ||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | ||
AddressAlign: 0x04 | ||
Content: "FFFFFFFFFFFFFFFFFFFF" | ||
- Type: SHT_PROGBITS | ||
Name: .tls | ||
Flags: [ SHF_ALLOC, SHF_TLS ] | ||
- Type: SHT_REL | ||
Name: .rel.text | ||
Link: .symtab | ||
Info: .text | ||
AddressAlign: 0x04 | ||
Relocations: | ||
- Offset: 4 | ||
Symbol: foo | ||
Type: R_X86_64_CODE_4_GOTTPOFF | ||
- Offset: 6 | ||
Symbol: foo | ||
Type: R_X86_64_CODE_6_GOTTPOFF | ||
Symbols: | ||
- Name: foo | ||
Type: STT_TLS | ||
Section: .text | ||
Value: 0x12345 | ||
Size: 4 | ||
Binding: STB_GLOBAL | ||
|
||
|
||
# RUN: yaml2obj --docnum=3 %s -o %t3.o | ||
# RUN: not ld.lld %t3.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR3 %s | ||
# ERR3: R_X86_64_CODE_4_GOTTPOFF must be used in MOVQ or ADDQ instructions only | ||
|
||
## YAML below contains R_X86_64_CODE_4_GOTTPOFF relocation type, and a .text | ||
## with fake content filled by 0xd5, 0xFF, ... and 0xFF. It's expected to get | ||
## the error message as above. | ||
--- !ELF | ||
FileHeader: | ||
Class: ELFCLASS64 | ||
Data: ELFDATA2LSB | ||
OSABI: ELFOSABI_FREEBSD | ||
Type: ET_REL | ||
Machine: EM_X86_64 | ||
Sections: | ||
- Type: SHT_PROGBITS | ||
Name: .text | ||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | ||
AddressAlign: 0x04 | ||
Content: "d5FFFFFFFFFFFFFFFFFF" | ||
- Type: SHT_PROGBITS | ||
Name: .tls | ||
Flags: [ SHF_ALLOC, SHF_TLS ] | ||
- Type: SHT_REL | ||
Name: .rel.text | ||
Link: .symtab | ||
Info: .text | ||
AddressAlign: 0x04 | ||
Relocations: | ||
- Offset: 4 | ||
Symbol: foo | ||
Type: R_X86_64_CODE_4_GOTTPOFF | ||
Symbols: | ||
- Name: foo | ||
Type: STT_TLS | ||
Section: .text | ||
Value: 0x12345 | ||
Size: 4 | ||
Binding: STB_GLOBAL | ||
|
||
|
||
# RUN: yaml2obj --docnum=4 %s -o %t4.o | ||
# RUN: not ld.lld %t4.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR4 %s | ||
# ERR4: R_X86_64_CODE_6_GOTTPOFF must be used in ADDQ instructions with NDD/NF/NDD+NF only | ||
|
||
## YAML below contains R_X86_64_CODE_6_GOTTPOFF relocation type, and a .text | ||
## with fake content filled by 0x62, 0xFF, ... and 0xFF. It's expected to get | ||
## the error message as above. | ||
--- !ELF | ||
FileHeader: | ||
Class: ELFCLASS64 | ||
Data: ELFDATA2LSB | ||
OSABI: ELFOSABI_FREEBSD | ||
Type: ET_REL | ||
Machine: EM_X86_64 | ||
Sections: | ||
- Type: SHT_PROGBITS | ||
Name: .text | ||
Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | ||
AddressAlign: 0x04 | ||
Content: "62FFFFFFFFFFFFFFFFFF" | ||
- Type: SHT_PROGBITS | ||
Name: .tls | ||
Flags: [ SHF_ALLOC, SHF_TLS ] | ||
- Type: SHT_REL | ||
Name: .rel.text | ||
Link: .symtab | ||
Info: .text | ||
AddressAlign: 0x04 | ||
Relocations: | ||
- Offset: 6 | ||
Symbol: foo | ||
Type: R_X86_64_CODE_6_GOTTPOFF | ||
Symbols: | ||
- Name: foo | ||
Type: STT_TLS | ||
Section: .text | ||
Value: 0x12345 | ||
Size: 4 | ||
Binding: STB_GLOBAL | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
BTW, there is a problem with the newly added relocation optimization. Unlike the relocation w/ REX prefix, we don't check the bits strictly. For example, we don't check if the W, X, pp and zero bits in EVEX payload2. This brings an potential issue that the linker hides the bug of assembler.
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can easily edit the binary in obj file to produce an invalid encoding with R_X86_64_CODE_6_GOTTPOFF relocation, e.g. set the zero bits in payload2 to ones. And then feed the modified the obj to linker, it would error nothing with this implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean it's better to check the bits strictly as for REX2 prefix? Since we may not use EGPR in instructions with NDD/NF, so it's not necessary to check X bits. I've added check for W bits. Seemed it's complicated to check pp bits. I'll take a look and will add later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated. Please help review. Thanks.