mirror of
https://github.com/RPCSX/llvm.git
synced 2024-11-25 04:39:44 +00:00
Handle _GLOBAL_OFFSET_TABLE_ correctly.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@116932 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
9f608b1919
commit
64e6719ee8
@ -18,6 +18,7 @@
|
||||
#include "llvm/MC/MCCodeEmitter.h"
|
||||
#include "llvm/MC/MCExpr.h"
|
||||
#include "llvm/MC/MCInst.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
using namespace llvm;
|
||||
|
||||
@ -193,6 +194,25 @@ static bool Is32BitMemOperand(const MCInst &MI, unsigned Op) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// StartsWithGlobalOffsetTable - Return true for the simple cases where this
|
||||
/// expression starts with _GLOBAL_OFFSET_TABLE_. This is a needed to support
|
||||
/// PIC on ELF i386 as that symbol is magic. We check only simple case that
|
||||
/// are know to be used: _GLOBAL_OFFSET_TABLE_ by itself or at the start
|
||||
/// of a binary expression.
|
||||
static bool StartsWithGlobalOffsetTable(const MCExpr *Expr) {
|
||||
if (Expr->getKind() == MCExpr::Binary) {
|
||||
const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Expr);
|
||||
Expr = BE->getLHS();
|
||||
}
|
||||
|
||||
if (Expr->getKind() != MCExpr::SymbolRef)
|
||||
return false;
|
||||
|
||||
const MCSymbolRefExpr *Ref = static_cast<const MCSymbolRefExpr*>(Expr);
|
||||
const MCSymbol &S = Ref->getSymbol();
|
||||
return S.getName() == "_GLOBAL_OFFSET_TABLE_";
|
||||
}
|
||||
|
||||
void X86MCCodeEmitter::
|
||||
EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
|
||||
unsigned &CurByte, raw_ostream &OS,
|
||||
@ -209,6 +229,13 @@ EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
|
||||
// If we have an immoffset, add it to the expression.
|
||||
const MCExpr *Expr = DispOp.getExpr();
|
||||
|
||||
if (StartsWithGlobalOffsetTable(Expr)) {
|
||||
// FIXME: We should probably change the FixupKind to a special one so that
|
||||
// other parts of MC don't have to check the symbol name.
|
||||
assert(ImmOffset == 0);
|
||||
ImmOffset = CurByte;
|
||||
}
|
||||
|
||||
// If the fixup is pc-relative, we need to bias the value to be relative to
|
||||
// the start of the field, not the end of the field.
|
||||
if (FixupKind == MCFixupKind(X86::reloc_pcrel_4byte) ||
|
||||
|
18
test/MC/ELF/global-offset.s
Normal file
18
test/MC/ELF/global-offset.s
Normal file
@ -0,0 +1,18 @@
|
||||
// RUN: llvm-mc -filetype=obj -triple i386-pc-linux-gnu %s -o - | elf-dump --dump-section-data | FileCheck %s
|
||||
|
||||
// We test that _GLOBAL_OFFSET_TABLE_ will account for the two bytes at the
|
||||
// start of the addl.
|
||||
|
||||
addl $_GLOBAL_OFFSET_TABLE_, %ebx
|
||||
|
||||
// CHECK: ('sh_name', 0x00000001) # '.text'
|
||||
// CHECK-NEXT: ('sh_type',
|
||||
// CHECK-NEXT: ('sh_flags',
|
||||
// CHECK-NEXT: ('sh_addr',
|
||||
// CHECK-NEXT: ('sh_offset',
|
||||
// CHECK-NEXT: ('sh_size',
|
||||
// CHECK-NEXT: ('sh_link',
|
||||
// CHECK-NEXT: ('sh_info',
|
||||
// CHECK-NEXT: ('sh_addralign',
|
||||
// CHECK-NEXT: ('sh_entsize',
|
||||
// CHECK-NEXT: ('_section_data', '81c30200 0000')
|
Loading…
Reference in New Issue
Block a user