mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
Fix COFF x86-64 relocations. PR7960.
Multiple symbol reloc handling part of the patch by Cameron Esfahani. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@111963 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
3e242f86eb
commit
82c84fdd23
@ -125,6 +125,7 @@ public:
|
|||||||
typedef DenseMap<MCSectionData const *, COFFSection *> section_map;
|
typedef DenseMap<MCSectionData const *, COFFSection *> section_map;
|
||||||
|
|
||||||
// Root level file contents.
|
// Root level file contents.
|
||||||
|
bool Is64Bit;
|
||||||
COFF::header Header;
|
COFF::header Header;
|
||||||
sections Sections;
|
sections Sections;
|
||||||
symbols Symbols;
|
symbols Symbols;
|
||||||
@ -274,10 +275,11 @@ size_t StringTable::insert(llvm::StringRef String) {
|
|||||||
// WinCOFFObjectWriter class implementation
|
// WinCOFFObjectWriter class implementation
|
||||||
|
|
||||||
WinCOFFObjectWriter::WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit)
|
WinCOFFObjectWriter::WinCOFFObjectWriter(raw_ostream &OS, bool is64Bit)
|
||||||
: MCObjectWriter(OS, true) {
|
: MCObjectWriter(OS, true)
|
||||||
|
, Is64Bit(is64Bit) {
|
||||||
memset(&Header, 0, sizeof(Header));
|
memset(&Header, 0, sizeof(Header));
|
||||||
|
|
||||||
is64Bit ? Header.Machine = COFF::IMAGE_FILE_MACHINE_AMD64
|
Is64Bit ? Header.Machine = COFF::IMAGE_FILE_MACHINE_AMD64
|
||||||
: Header.Machine = COFF::IMAGE_FILE_MACHINE_I386;
|
: Header.Machine = COFF::IMAGE_FILE_MACHINE_I386;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -565,22 +567,34 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
|
|||||||
MCValue Target,
|
MCValue Target,
|
||||||
uint64_t &FixedValue) {
|
uint64_t &FixedValue) {
|
||||||
assert(Target.getSymA() != NULL && "Relocation must reference a symbol!");
|
assert(Target.getSymA() != NULL && "Relocation must reference a symbol!");
|
||||||
assert(Target.getSymB() == NULL &&
|
|
||||||
"Relocation must reference only one symbol!");
|
const MCSymbol *A = &Target.getSymA()->getSymbol();
|
||||||
|
MCSymbolData &A_SD = Asm.getSymbolData(*A);
|
||||||
|
|
||||||
MCSectionData const *SectionData = Fragment->getParent();
|
MCSectionData const *SectionData = Fragment->getParent();
|
||||||
MCSymbolData const *SymbolData =
|
|
||||||
&Asm.getSymbolData(Target.getSymA()->getSymbol());
|
|
||||||
|
|
||||||
|
// Mark this symbol as requiring an entry in the symbol table.
|
||||||
assert(SectionMap.find(SectionData) != SectionMap.end() &&
|
assert(SectionMap.find(SectionData) != SectionMap.end() &&
|
||||||
"Section must already have been defined in ExecutePostLayoutBinding!");
|
"Section must already have been defined in ExecutePostLayoutBinding!");
|
||||||
assert(SymbolMap.find(SymbolData) != SymbolMap.end() &&
|
assert(SymbolMap.find(&A_SD) != SymbolMap.end() &&
|
||||||
"Symbol must already have been defined in ExecutePostLayoutBinding!");
|
"Symbol must already have been defined in ExecutePostLayoutBinding!");
|
||||||
|
|
||||||
COFFSection *coff_section = SectionMap[SectionData];
|
COFFSection *coff_section = SectionMap[SectionData];
|
||||||
COFFSymbol *coff_symbol = SymbolMap[SymbolData];
|
COFFSymbol *coff_symbol = SymbolMap[&A_SD];
|
||||||
|
|
||||||
FixedValue = Target.getConstant();
|
if (Target.getSymB()) {
|
||||||
|
const MCSymbol *B = &Target.getSymB()->getSymbol();
|
||||||
|
MCSymbolData &B_SD = Asm.getSymbolData(*B);
|
||||||
|
|
||||||
|
FixedValue = Layout.getSymbolAddress(&A_SD) - Layout.getSymbolAddress(&B_SD);
|
||||||
|
|
||||||
|
// In the case where we have SymbA and SymB, we just need to store the delta
|
||||||
|
// between the two symbols. Update FixedValue to account for the delta, and
|
||||||
|
// skip recording the relocation.
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
FixedValue = Target.getConstant();
|
||||||
|
}
|
||||||
|
|
||||||
COFFRelocation Reloc;
|
COFFRelocation Reloc;
|
||||||
|
|
||||||
@ -590,40 +604,29 @@ void WinCOFFObjectWriter::RecordRelocation(const MCAssembler &Asm,
|
|||||||
|
|
||||||
Reloc.Data.VirtualAddress += Fixup.getOffset();
|
Reloc.Data.VirtualAddress += Fixup.getOffset();
|
||||||
|
|
||||||
COFF::RelocationTypeX86 Type;
|
switch (Fixup.getKind()) {
|
||||||
|
case X86::reloc_pcrel_4byte:
|
||||||
if (Header.Machine == COFF::IMAGE_FILE_MACHINE_I386) {
|
case X86::reloc_riprel_4byte:
|
||||||
switch (Fixup.getKind()) {
|
case X86::reloc_riprel_4byte_movq_load:
|
||||||
case X86::reloc_pcrel_4byte:
|
Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_REL32
|
||||||
Type = COFF::IMAGE_REL_I386_REL32;
|
: COFF::IMAGE_REL_I386_REL32;
|
||||||
FixedValue += 4;
|
// FIXME: Can anyone explain what this does other than adjust for the size
|
||||||
break;
|
// of the offset?
|
||||||
case FK_Data_4:
|
FixedValue += 4;
|
||||||
Type = COFF::IMAGE_REL_I386_DIR32;
|
break;
|
||||||
break;
|
case FK_Data_4:
|
||||||
default:
|
Reloc.Data.Type = Is64Bit ? COFF::IMAGE_REL_AMD64_ADDR32
|
||||||
|
: COFF::IMAGE_REL_I386_DIR32;
|
||||||
|
break;
|
||||||
|
case FK_Data_8:
|
||||||
|
if (Is64Bit)
|
||||||
|
Reloc.Data.Type = COFF::IMAGE_REL_AMD64_ADDR64;
|
||||||
|
else
|
||||||
llvm_unreachable("unsupported relocation type");
|
llvm_unreachable("unsupported relocation type");
|
||||||
}
|
break;
|
||||||
} else if (Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64) {
|
default:
|
||||||
switch (Fixup.getKind()) {
|
llvm_unreachable("unsupported relocation type");
|
||||||
case FK_Data_8:
|
}
|
||||||
Type = COFF::IMAGE_REL_AMD64_ADDR64;
|
|
||||||
break;
|
|
||||||
case X86::reloc_pcrel_4byte:
|
|
||||||
case X86::reloc_riprel_4byte:
|
|
||||||
Type = COFF::IMAGE_REL_AMD64_REL32;
|
|
||||||
FixedValue += 4;
|
|
||||||
break;
|
|
||||||
case FK_Data_4:
|
|
||||||
Type = COFF::IMAGE_REL_AMD64_ADDR32;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
llvm_unreachable("unsupported relocation type");
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
llvm_unreachable("unknown target architecture");
|
|
||||||
|
|
||||||
Reloc.Data.Type = Type;
|
|
||||||
|
|
||||||
coff_section->Relocations.push_back(Reloc);
|
coff_section->Relocations.push_back(Reloc);
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
; RUN: llc -filetype=obj %s -o %t
|
; This test checks that the COFF object emitter works for the most basic
|
||||||
; RUN: coff-dump.py %abs_tmp | FileCheck %s
|
; programs.
|
||||||
|
|
||||||
; ModuleID = '-'
|
; RUN: llc -filetype=obj -mtriple i686-pc-win32 %s -o %t
|
||||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
|
; RUN: coff-dump.py %abs_tmp | FileCheck %s
|
||||||
target triple = "i686-pc-win32"
|
; RUN: llc -filetype=obj -mtriple x86_64-pc-win32 %s -o %t
|
||||||
|
|
||||||
@.str = private constant [12 x i8] c"Hello World\00" ; <[12 x i8]*> [#uses=1]
|
@.str = private constant [12 x i8] c"Hello World\00" ; <[12 x i8]*> [#uses=1]
|
||||||
|
|
||||||
|
34
test/MC/COFF/switch-relocations.ll
Normal file
34
test/MC/COFF/switch-relocations.ll
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
; The purpose of this test is to see if the COFF object writer can properly
|
||||||
|
; relax the fixups that are created for jump tables on x86-64. See PR7960.
|
||||||
|
|
||||||
|
; This test case was reduced from Lua/lapi.c.
|
||||||
|
|
||||||
|
; RUN: llc -filetype=obj -mtriple i686-pc-win32 %s -o %t
|
||||||
|
; RUN: llc -filetype=obj -mtriple x86_64-pc-win32 %s -o %t
|
||||||
|
|
||||||
|
define void @lua_gc(i32 %what) nounwind {
|
||||||
|
entry:
|
||||||
|
switch i32 %what, label %sw.epilog [
|
||||||
|
i32 0, label %sw.bb
|
||||||
|
i32 1, label %sw.bb
|
||||||
|
i32 2, label %sw.bb
|
||||||
|
i32 3, label %sw.bb14
|
||||||
|
i32 4, label %sw.bb18
|
||||||
|
i32 6, label %sw.bb57
|
||||||
|
]
|
||||||
|
|
||||||
|
sw.bb: ; preds = %entry, %entry, %entry
|
||||||
|
ret void
|
||||||
|
|
||||||
|
sw.bb14: ; preds = %entry
|
||||||
|
ret void
|
||||||
|
|
||||||
|
sw.bb18: ; preds = %entry
|
||||||
|
ret void
|
||||||
|
|
||||||
|
sw.bb57: ; preds = %entry
|
||||||
|
ret void
|
||||||
|
|
||||||
|
sw.epilog: ; preds = %entry
|
||||||
|
ret void
|
||||||
|
}
|
@ -1,9 +1,9 @@
|
|||||||
; RUN: llc -filetype=obj %s -o %t
|
; The purpose of this test is to see if the COFF object writer is emitting the
|
||||||
; RUN: coff-dump.py %abs_tmp | FileCheck %s
|
; proper relocations for multiple pieces of data in a single data fragment.
|
||||||
|
|
||||||
; ModuleID = 'coff-fragment-test.c'
|
; RUN: llc -filetype=obj -mtriple i686-pc-win32 %s -o %t
|
||||||
target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-f80:128:128-v64:64:64-v128:128:128-a0:0:64-f80:32:32-n8:16:32"
|
; RUN: coff-dump.py %abs_tmp | FileCheck %s
|
||||||
target triple = "i686-pc-win32"
|
; RUN: llc -filetype=obj -mtriple x86_64-pc-win32 %s -o %t
|
||||||
|
|
||||||
@.str = private constant [7 x i8] c"Hello \00" ; <[7 x i8]*> [#uses=1]
|
@.str = private constant [7 x i8] c"Hello \00" ; <[7 x i8]*> [#uses=1]
|
||||||
@str = internal constant [7 x i8] c"World!\00" ; <[7 x i8]*> [#uses=1]
|
@str = internal constant [7 x i8] c"World!\00" ; <[7 x i8]*> [#uses=1]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user