mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[mips] Do not include offset into %got
expression for global symbols
Now pseudo instruction `la $6, symbol+8($6)` is expanding into the following chain of commands: ``` lw $1, %got(symbol+8)($gp) addiu $1, $1, 8 addu $6, $1, $6 ``` This is incorrect. When a linker handles the `R_MIPS_GOT16` relocation, it does not expect to get any addend and breaks on assertion. Otherwise it has to create new GOT entry for each unique "sym + offset" pair. Offset for a global symbol should be added to result of loading GOT entry by a separate `add` command. The patch fixes the problem by stripping off an offset from the expression passed to the `%got`. That's interesting that even current code inserts a separate `add` command. Differential Revision: https://reviews.llvm.org/D66552 llvm-svn: 369755
This commit is contained in:
parent
29a5b2fd9c
commit
493b163f5d
@ -2884,16 +2884,18 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsLocalSym =
|
||||||
|
Res.getSymA()->getSymbol().isInSection() ||
|
||||||
|
Res.getSymA()->getSymbol().isTemporary() ||
|
||||||
|
(Res.getSymA()->getSymbol().isELF() &&
|
||||||
|
cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
|
||||||
|
ELF::STB_LOCAL);
|
||||||
|
|
||||||
// The case where the result register is $25 is somewhat special. If the
|
// The case where the result register is $25 is somewhat special. If the
|
||||||
// symbol in the final relocation is external and not modified with a
|
// symbol in the final relocation is external and not modified with a
|
||||||
// constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
|
// constant then we must use R_MIPS_CALL16 instead of R_MIPS_GOT16.
|
||||||
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
|
if ((DstReg == Mips::T9 || DstReg == Mips::T9_64) && !UseSrcReg &&
|
||||||
Res.getConstant() == 0 &&
|
Res.getConstant() == 0 && !IsLocalSym) {
|
||||||
!(Res.getSymA()->getSymbol().isInSection() ||
|
|
||||||
Res.getSymA()->getSymbol().isTemporary() ||
|
|
||||||
(Res.getSymA()->getSymbol().isELF() &&
|
|
||||||
cast<MCSymbolELF>(Res.getSymA()->getSymbol()).getBinding() ==
|
|
||||||
ELF::STB_LOCAL))) {
|
|
||||||
const MCExpr *CallExpr =
|
const MCExpr *CallExpr =
|
||||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
|
MipsMCExpr::create(MipsMCExpr::MEK_GOT_CALL, SymExpr, getContext());
|
||||||
TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr),
|
TOut.emitRRX(Mips::LW, DstReg, GPReg, MCOperand::createExpr(CallExpr),
|
||||||
@ -2902,8 +2904,8 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// The remaining cases are:
|
// The remaining cases are:
|
||||||
// External GOT: lw $tmp, %got(symbol+offset)($gp)
|
// External GOT: lw $tmp, %got(symbol)($gp)
|
||||||
// >addiu $tmp, $tmp, %lo(offset)
|
// >addiu $tmp, $tmp, offset
|
||||||
// >addiu $rd, $tmp, $rs
|
// >addiu $rd, $tmp, $rs
|
||||||
// Local GOT: lw $tmp, %got(symbol+offset)($gp)
|
// Local GOT: lw $tmp, %got(symbol+offset)($gp)
|
||||||
// addiu $tmp, $tmp, %lo(symbol+offset)($gp)
|
// addiu $tmp, $tmp, %lo(symbol+offset)($gp)
|
||||||
@ -2911,17 +2913,19 @@ bool MipsAsmParser::loadAndAddSymbolAddress(const MCExpr *SymExpr,
|
|||||||
// The addiu's marked with a '>' may be omitted if they are redundant. If
|
// The addiu's marked with a '>' may be omitted if they are redundant. If
|
||||||
// this happens then the last instruction must use $rd as the result
|
// this happens then the last instruction must use $rd as the result
|
||||||
// register.
|
// register.
|
||||||
const MipsMCExpr *GotExpr =
|
const MipsMCExpr *GotExpr = nullptr;
|
||||||
MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
|
|
||||||
const MCExpr *LoExpr = nullptr;
|
const MCExpr *LoExpr = nullptr;
|
||||||
if (Res.getSymA()->getSymbol().isInSection() ||
|
if (IsLocalSym) {
|
||||||
Res.getSymA()->getSymbol().isTemporary())
|
GotExpr = MipsMCExpr::create(MipsMCExpr::MEK_GOT, SymExpr, getContext());
|
||||||
LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
|
LoExpr = MipsMCExpr::create(MipsMCExpr::MEK_LO, SymExpr, getContext());
|
||||||
else if (Res.getConstant() != 0) {
|
} else {
|
||||||
// External symbols fully resolve the symbol with just the %got(symbol)
|
// External symbols fully resolve the symbol with just the %got(symbol)
|
||||||
// but we must still account for any offset to the symbol for expressions
|
// but we must still account for any offset to the symbol for expressions
|
||||||
// like symbol+8.
|
// like symbol+8.
|
||||||
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
|
GotExpr =
|
||||||
|
MipsMCExpr::create(MipsMCExpr::MEK_GOT, Res.getSymA(), getContext());
|
||||||
|
if (Res.getConstant() != 0)
|
||||||
|
LoExpr = MCConstantExpr::create(Res.getConstant(), getContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned TmpReg = DstReg;
|
unsigned TmpReg = DstReg;
|
||||||
|
@ -14,13 +14,15 @@ la $5, symbol($6) # CHECK: lw $5, %got(symbol)($gp) # encoding: [0x8f,0x8
|
|||||||
la $6, symbol($6) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A]
|
la $6, symbol($6) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A]
|
||||||
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
# CHECK: addu $6, $1, $6 # encoding: [0x00,0x26,0x30,0x21]
|
# CHECK: addu $6, $1, $6 # encoding: [0x00,0x26,0x30,0x21]
|
||||||
la $5, symbol+8 # CHECK: lw $5, %got(symbol+8)($gp) # encoding: [0x8f,0x85,A,A]
|
la $5, symbol+8 # CHECK: lw $5, %got(symbol)($gp) # encoding: [0x8f,0x85,A,A]
|
||||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
la $5, symbol+8($6) # CHECK: lw $5, %got(symbol+8)($gp) # encoding: [0x8f,0x85,A,A]
|
# CHECK: addiu $5, $5, 8 # encoding: [0x24,0xa5,0x00,0x08]
|
||||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
la $5, symbol+8($6) # CHECK: lw $5, %got(symbol)($gp) # encoding: [0x8f,0x85,A,A]
|
||||||
|
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
|
# CHECK: addiu $5, $5, 8 # encoding: [0x24,0xa5,0x00,0x08]
|
||||||
# CHECK: addu $5, $5, $6 # encoding: [0x00,0xa6,0x28,0x21]
|
# CHECK: addu $5, $5, $6 # encoding: [0x00,0xa6,0x28,0x21]
|
||||||
la $6, symbol+8($6) # CHECK: lw $1, %got(symbol+8)($gp) # encoding: [0x8f,0x81,A,A]
|
la $6, symbol+8($6) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A]
|
||||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
# CHECK: addiu $1, $1, 8 # encoding: [0x24,0x21,0x00,0x08]
|
# CHECK: addiu $1, $1, 8 # encoding: [0x24,0x21,0x00,0x08]
|
||||||
# CHECK: addu $6, $1, $6 # encoding: [0x00,0x26,0x30,0x21]
|
# CHECK: addu $6, $1, $6 # encoding: [0x00,0x26,0x30,0x21]
|
||||||
la $5, 1f # CHECK: lw $5, %got($tmp0)($gp) # encoding: [0x8f,0x85,A,A]
|
la $5, 1f # CHECK: lw $5, %got($tmp0)($gp) # encoding: [0x8f,0x85,A,A]
|
||||||
@ -38,13 +40,15 @@ la $25, symbol($6) # CHECK: lw $25, %got(symbol)($gp) # encoding: [0x8f,0x
|
|||||||
la $25, symbol($25) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A]
|
la $25, symbol($25) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A]
|
||||||
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
# CHECK: addu $25, $1, $25 # encoding: [0x00,0x39,0xc8,0x21]
|
# CHECK: addu $25, $1, $25 # encoding: [0x00,0x39,0xc8,0x21]
|
||||||
la $25, symbol+8 # CHECK: lw $25, %got(symbol+8)($gp) # encoding: [0x8f,0x99,A,A]
|
la $25, symbol+8 # CHECK: lw $25, %got(symbol)($gp) # encoding: [0x8f,0x99,A,A]
|
||||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
la $25, symbol+8($6) # CHECK: lw $25, %got(symbol+8)($gp) # encoding: [0x8f,0x99,A,A]
|
# CHECK: addiu $25, $25, 8 # encoding: [0x27,0x39,0x00,0x08]
|
||||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
la $25, symbol+8($6) # CHECK: lw $25, %got(symbol)($gp) # encoding: [0x8f,0x99,A,A]
|
||||||
|
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
|
# CHECK: addiu $25, $25, 8 # encoding: [0x27,0x39,0x00,0x08]
|
||||||
# CHECK: addu $25, $25, $6 # encoding: [0x03,0x26,0xc8,0x21]
|
# CHECK: addu $25, $25, $6 # encoding: [0x03,0x26,0xc8,0x21]
|
||||||
la $25, symbol+8($25) # CHECK: lw $1, %got(symbol+8)($gp) # encoding: [0x8f,0x81,A,A]
|
la $25, symbol+8($25) # CHECK: lw $1, %got(symbol)($gp) # encoding: [0x8f,0x81,A,A]
|
||||||
# CHECK: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
# CHECK: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
# CHECK: addiu $1, $1, 8 # encoding: [0x24,0x21,0x00,0x08]
|
# CHECK: addiu $1, $1, 8 # encoding: [0x24,0x21,0x00,0x08]
|
||||||
# CHECK: addu $25, $1, $25 # encoding: [0x00,0x39,0xc8,0x21]
|
# CHECK: addu $25, $1, $25 # encoding: [0x00,0x39,0xc8,0x21]
|
||||||
la $25, 1f # CHECK: lw $25, %got($tmp1)($gp) # encoding: [0x8f,0x99,A,A]
|
la $25, 1f # CHECK: lw $25, %got($tmp1)($gp) # encoding: [0x8f,0x99,A,A]
|
||||||
|
@ -144,13 +144,13 @@
|
|||||||
# CHECK-LE: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac]
|
# CHECK-LE: sw $10, -7616($1) # encoding: [0x40,0xe2,0x2a,0xac]
|
||||||
|
|
||||||
lw $8, symbol+8
|
lw $8, symbol+8
|
||||||
# CHECK-LE: lw $8, %got(symbol+8)($gp) # encoding: [A,A,0x88,0x8f]
|
# CHECK-LE: lw $8, %got(symbol)($gp) # encoding: [A,A,0x88,0x8f]
|
||||||
# CHECK-LE: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
# CHECK-LE: addiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x25]
|
# CHECK-LE: addiu $8, $8, 8 # encoding: [0x08,0x00,0x08,0x25]
|
||||||
# CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d]
|
# CHECK-LE: lw $8, 0($8) # encoding: [0x00,0x00,0x08,0x8d]
|
||||||
sw $8, symbol+8
|
sw $8, symbol+8
|
||||||
# CHECK-LE: lw $1, %got(symbol+8)($gp) # encoding: [A,A,0x81,0x8f]
|
# CHECK-LE: lw $1, %got(symbol)($gp) # encoding: [A,A,0x81,0x8f]
|
||||||
# CHECK-LE: # fixup A - offset: 0, value: %got(symbol+8), kind: fixup_Mips_GOT
|
# CHECK-LE: # fixup A - offset: 0, value: %got(symbol), kind: fixup_Mips_GOT
|
||||||
# CHECK-LE: addiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x24]
|
# CHECK-LE: addiu $1, $1, 8 # encoding: [0x08,0x00,0x21,0x24]
|
||||||
# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac]
|
# CHECK-LE: sw $8, 0($1) # encoding: [0x00,0x00,0x28,0xac]
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user