mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
[CodeGen] Fix invalid DWARF info on Win64
The relocations for `DIEEntry::EmitValue` were wrong for Win64 (emitting FK_Data_4 instead of FK_SecRel_4). This corrects that oversight so that the DWARF data is correct in Win64 COFF files. Fixes PR15393. Patch by Jameson Nash <jameson@juliacomputing.com> based on a patch by David Majnemer. Differential Revision: https://reviews.llvm.org/D21731 llvm-svn: 289013
This commit is contained in:
parent
34f25a2606
commit
7c7d74df6a
@ -67,7 +67,7 @@ the target. It corresponds to the COFF relocation types
|
||||
.long 4
|
||||
.long 242
|
||||
.long 40
|
||||
.secrel32 _function_name
|
||||
.secrel32 _function_name + 0
|
||||
.secidx _function_name
|
||||
...
|
||||
|
||||
|
@ -471,7 +471,7 @@ public:
|
||||
/// \brief Emits a COFF section relative relocation.
|
||||
///
|
||||
/// \param Symbol - Symbol the section relative relocation should point to.
|
||||
virtual void EmitCOFFSecRel32(MCSymbol const *Symbol);
|
||||
virtual void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset);
|
||||
|
||||
/// \brief Emit an ELF .size directive.
|
||||
///
|
||||
|
@ -52,7 +52,7 @@ public:
|
||||
void EndCOFFSymbolDef() override;
|
||||
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
|
||||
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
|
||||
void EmitCOFFSecRel32(MCSymbol const *Symbol) override;
|
||||
void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
|
||||
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||
unsigned ByteAlignment) override;
|
||||
void EmitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||
|
@ -1688,7 +1688,7 @@ void AsmPrinter::EmitLabelPlusOffset(const MCSymbol *Label, uint64_t Offset,
|
||||
unsigned Size,
|
||||
bool IsSectionRelative) const {
|
||||
if (MAI->needsDwarfSectionOffsetDirective() && IsSectionRelative) {
|
||||
OutStreamer->EmitCOFFSecRel32(Label);
|
||||
OutStreamer->EmitCOFFSecRel32(Label, Offset);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ void AsmPrinter::emitDwarfSymbolReference(const MCSymbol *Label,
|
||||
if (!ForceOffset) {
|
||||
// On COFF targets, we have to emit the special .secrel32 directive.
|
||||
if (MAI->needsDwarfSectionOffsetDirective()) {
|
||||
OutStreamer->EmitCOFFSecRel32(Label);
|
||||
OutStreamer->EmitCOFFSecRel32(Label, /*Offset=*/0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -801,7 +801,7 @@ void CodeViewDebug::emitDebugInfoForFunction(const Function *GV,
|
||||
OS.AddComment("Function type index");
|
||||
OS.EmitIntValue(getFuncIdForSubprogram(GV->getSubprogram()).getIndex(), 4);
|
||||
OS.AddComment("Function section relative address");
|
||||
OS.EmitCOFFSecRel32(Fn);
|
||||
OS.EmitCOFFSecRel32(Fn, /*Offset=*/0);
|
||||
OS.AddComment("Function section index");
|
||||
OS.EmitCOFFSectionIndex(Fn);
|
||||
OS.AddComment("Flags");
|
||||
@ -2271,7 +2271,7 @@ void CodeViewDebug::emitDebugInfoForGlobal(const DIGlobalVariable *DIGV,
|
||||
OS.AddComment("Type");
|
||||
OS.EmitIntValue(getCompleteTypeIndex(DIGV->getType()).getIndex(), 4);
|
||||
OS.AddComment("DataOffset");
|
||||
OS.EmitCOFFSecRel32(GVSym);
|
||||
OS.EmitCOFFSecRel32(GVSym, /*Offset=*/0);
|
||||
OS.AddComment("Segment");
|
||||
OS.EmitCOFFSectionIndex(GVSym);
|
||||
OS.AddComment("Name");
|
||||
|
@ -642,7 +642,7 @@ void DIEEntry::EmitValue(const AsmPrinter *AP, dwarf::Form Form) const {
|
||||
MCSection *Section = Unit->getSection();
|
||||
if (Section) {
|
||||
const MCSymbol *SectionSym = Section->getBeginSymbol();
|
||||
AP->EmitLabelPlusOffset(SectionSym, Addr, SizeOf(AP, Form));
|
||||
AP->EmitLabelPlusOffset(SectionSym, Addr, SizeOf(AP, Form), true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ public:
|
||||
void EndCOFFSymbolDef() override;
|
||||
void EmitCOFFSafeSEH(MCSymbol const *Symbol) override;
|
||||
void EmitCOFFSectionIndex(MCSymbol const *Symbol) override;
|
||||
void EmitCOFFSecRel32(MCSymbol const *Symbol) override;
|
||||
void EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) override;
|
||||
void emitELFSize(MCSymbol *Symbol, const MCExpr *Value) override;
|
||||
void EmitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
|
||||
unsigned ByteAlignment) override;
|
||||
@ -614,9 +614,11 @@ void MCAsmStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
|
||||
EmitEOL();
|
||||
}
|
||||
|
||||
void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
|
||||
void MCAsmStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {
|
||||
OS << "\t.secrel32\t";
|
||||
Symbol->print(OS, MAI);
|
||||
if (Offset != 0)
|
||||
OS << '+' << Offset;
|
||||
EmitEOL();
|
||||
}
|
||||
|
||||
|
@ -200,7 +200,7 @@ void CodeViewContext::emitLineTableForFunction(MCObjectStreamer &OS,
|
||||
OS.EmitIntValue(unsigned(ModuleSubstreamKind::Lines), 4);
|
||||
OS.emitAbsoluteSymbolDiff(LineEnd, LineBegin, 4);
|
||||
OS.EmitLabel(LineBegin);
|
||||
OS.EmitCOFFSecRel32(FuncBegin);
|
||||
OS.EmitCOFFSecRel32(FuncBegin, /*Offset=*/0);
|
||||
OS.EmitCOFFSectionIndex(FuncBegin);
|
||||
|
||||
// Actual line info.
|
||||
|
@ -455,13 +455,26 @@ bool COFFAsmParser::ParseDirectiveSecRel32(StringRef, SMLoc) {
|
||||
if (getParser().parseIdentifier(SymbolID))
|
||||
return TokError("expected identifier in directive");
|
||||
|
||||
int64_t Offset = 0;
|
||||
SMLoc OffsetLoc;
|
||||
if (getLexer().is(AsmToken::Plus)) {
|
||||
OffsetLoc = getLexer().getLoc();
|
||||
if (getParser().parseAbsoluteExpression(Offset))
|
||||
return true;
|
||||
}
|
||||
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement))
|
||||
return TokError("unexpected token in directive");
|
||||
|
||||
if (Offset < 0 || Offset > UINT32_MAX)
|
||||
return Error(OffsetLoc,
|
||||
"invalid '.secrel32' directive offset, can't be less "
|
||||
"than zero or greater than UINT32_MAX");
|
||||
|
||||
MCSymbol *Symbol = getContext().getOrCreateSymbol(SymbolID);
|
||||
|
||||
Lex();
|
||||
getStreamer().EmitCOFFSecRel32(Symbol);
|
||||
getStreamer().EmitCOFFSecRel32(Symbol, Offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -125,7 +125,7 @@ void MCStreamer::EmitSymbolValue(const MCSymbol *Sym, unsigned Size,
|
||||
if (!IsSectionRelative)
|
||||
EmitValueImpl(MCSymbolRefExpr::create(Sym, getContext()), Size);
|
||||
else
|
||||
EmitCOFFSecRel32(Sym);
|
||||
EmitCOFFSecRel32(Sym, /*Offset=*/0);
|
||||
}
|
||||
|
||||
void MCStreamer::EmitDTPRel64Value(const MCExpr *Value) {
|
||||
@ -689,8 +689,7 @@ void MCStreamer::EmitCOFFSafeSEH(MCSymbol const *Symbol) {
|
||||
void MCStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
|
||||
}
|
||||
|
||||
void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
|
||||
}
|
||||
void MCStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol, uint64_t Offset) {}
|
||||
|
||||
/// EmitRawText - If this file is backed by an assembly streamer, this dumps
|
||||
/// the specified string in the output .s file. This capability is
|
||||
|
@ -195,11 +195,20 @@ void MCWinCOFFStreamer::EmitCOFFSectionIndex(MCSymbol const *Symbol) {
|
||||
DF->getContents().resize(DF->getContents().size() + 2, 0);
|
||||
}
|
||||
|
||||
void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol) {
|
||||
void MCWinCOFFStreamer::EmitCOFFSecRel32(MCSymbol const *Symbol,
|
||||
uint64_t Offset) {
|
||||
MCDataFragment *DF = getOrCreateDataFragment();
|
||||
const MCSymbolRefExpr *SRE = MCSymbolRefExpr::create(Symbol, getContext());
|
||||
MCFixup Fixup = MCFixup::create(DF->getContents().size(), SRE, FK_SecRel_4);
|
||||
// Create Symbol A for the relocation relative reference.
|
||||
const MCExpr *MCE = MCSymbolRefExpr::create(Symbol, getContext());
|
||||
// Add the constant offset, if given.
|
||||
if (Offset)
|
||||
MCE = MCBinaryExpr::createAdd(
|
||||
MCE, MCConstantExpr::create(Offset, getContext()), getContext());
|
||||
// Build the secrel32 relocation.
|
||||
MCFixup Fixup = MCFixup::create(DF->getContents().size(), MCE, FK_SecRel_4);
|
||||
// Record the relocation.
|
||||
DF->getFixups().push_back(Fixup);
|
||||
// Emit 4 bytes (zeros) to the object file.
|
||||
DF->getContents().resize(DF->getContents().size() + 4, 0);
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,22 @@
|
||||
; RUN: llc -filetype=asm -O0 -mtriple=x86_64-linux-gnu < %s | FileCheck %s
|
||||
; RUN: llc -filetype=obj -O0 %s -mtriple=x86_64-linux-gnu -o %t
|
||||
; RUN: llvm-dwarfdump %t | FileCheck %s -check-prefix=CHECK-DWARF
|
||||
; RUN: llc -filetype=asm -O0 -mtriple=x86_64-linux-gnu < %s -dwarf-version 2 | FileCheck -check-prefixes=CHECK,ELF-ASM %s
|
||||
; RUN: llc -filetype=obj -O0 %s -mtriple=x86_64-linux-gnu -o %t-2 -dwarf-version 2
|
||||
; RUN: llvm-dwarfdump %t-2 | FileCheck %s -check-prefix=CHECK-DWARF
|
||||
; RUN: llc -filetype=obj -O0 %s -mtriple=x86_64-linux-gnu -o %t-4 -dwarf-version 2
|
||||
; RUN: llvm-dwarfdump %t-4 | FileCheck %s -check-prefix=CHECK-DWARF
|
||||
|
||||
; RUN: llc -filetype=asm -O0 -mtriple=x86_64-apple-darwin < %s | FileCheck --check-prefix=DARWIN-ASM %s
|
||||
; RUN: llc -filetype=obj %s -mtriple=x86_64-apple-darwin -o %t2
|
||||
; RUN: llvm-dwarfdump %t2 | FileCheck %s -check-prefix=DARWIN-DWARF
|
||||
; RUN: llc -filetype=asm -O0 -mtriple=x86_64-apple-darwin < %s -dwarf-version 2 | FileCheck -check-prefixes=CHECK,DARWIN-ASM2 %s
|
||||
; RUN: llc -filetype=asm -O0 -mtriple=x86_64-apple-darwin < %s -dwarf-version 4 | FileCheck -check-prefixes=CHECK,DARWIN-ASM4 %s
|
||||
; RUN: llc -filetype=obj %s -mtriple=x86_64-apple-darwin -o %t2-2 -dwarf-version 2
|
||||
; RUN: llvm-dwarfdump %t2-2 | FileCheck %s -check-prefix=CHECK-DWARF
|
||||
; RUN: llc -filetype=obj %s -mtriple=x86_64-apple-darwin -o %t2-4 -dwarf-version 4
|
||||
; RUN: llvm-dwarfdump %t2-4 | FileCheck %s -check-prefix=CHECK-DWARF
|
||||
|
||||
; RUN: llc -filetype=asm -O0 -mtriple=x86_64-pc-win32 < %s -dwarf-version 2 | FileCheck -check-prefixes=CHECK,COFF-ASM %s
|
||||
; RUN: llc -filetype=asm -O0 -mtriple=x86_64-pc-win32 < %s -dwarf-version 4 | FileCheck -check-prefixes=CHECK,COFF-ASM %s
|
||||
; RUN: llc -filetype=obj -O0 %s -mtriple=x86_64-pc-win32 -o %t3-2 -dwarf-version 2
|
||||
; RUN: llvm-dwarfdump %t3-2 | FileCheck %s -check-prefix=CHECK-DWARF2
|
||||
; RUN: llc -filetype=obj -O0 %s -mtriple=x86_64-pc-win32 -o %t3-4 -dwarf-version 4
|
||||
; RUN: llvm-dwarfdump %t3-4 | FileCheck %s -check-prefix=CHECK-DWARF
|
||||
|
||||
; Testing case generated from:
|
||||
; clang++ tu1.cpp tu2.cpp -g -emit-llvm -c
|
||||
@ -22,7 +34,10 @@
|
||||
; Make sure we use relocation for ref_addr on non-darwin platforms.
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
; CHECK: DW_TAG_variable
|
||||
; CHECK: .long [[TYPE:.*]] # DW_AT_type
|
||||
; ELF-ASM: .long [[TYPE:.*]] # DW_AT_type
|
||||
; DARWIN-ASM2: .long [[TYPE:.*]] ## DW_AT_type
|
||||
; DARWIN-ASM4: .long [[TYPE:.*]] ## DW_AT_type
|
||||
; COFF-ASM: .long [[TYPE:.*]] # DW_AT_type
|
||||
; CHECK: DW_TAG_structure_type
|
||||
; CHECK: cu_begin1
|
||||
; CHECK: DW_TAG_compile_unit
|
||||
@ -30,25 +45,24 @@
|
||||
; This variable's type is in the 1st CU.
|
||||
; CHECK: DW_TAG_variable
|
||||
; Make sure this is relocatable.
|
||||
; CHECK: .quad .Lsection_info+[[TYPE]] # DW_AT_type
|
||||
; and test that we don't create the labels to emit a correct COFF relocation
|
||||
; ELF-ASM: .quad .Lsection_info+[[TYPE]] # DW_AT_type
|
||||
; COFF-ASM: .secrel32 .Lsection_info+[[TYPE]] # DW_AT_type
|
||||
; DARWIN-ASM2: .quad [[TYPE]] ## DW_AT_type
|
||||
; DARWIN-ASM4: .long [[TYPE]] ## DW_AT_type
|
||||
; CHECK-NOT: DW_TAG_structure_type
|
||||
; CHECK: .section
|
||||
|
||||
; test that we don't create useless labels
|
||||
; DARWIN-ASM: .long [[TYPE:.*]] ## DW_AT_type
|
||||
; DARWIN-ASM: .quad [[TYPE]] ## DW_AT_type
|
||||
|
||||
; CHECK-DWARF: DW_TAG_compile_unit
|
||||
; CHECK-DWARF: 0x[[ADDR:.*]]: DW_TAG_structure_type
|
||||
; CHECK-DWARF: DW_TAG_compile_unit
|
||||
; CHECK-DWARF: DW_TAG_variable
|
||||
; CHECK-DWARF: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[ADDR]])
|
||||
|
||||
; DARWIN-DWARF: DW_TAG_compile_unit
|
||||
; DARWIN-DWARF: 0x[[ADDR:.*]]: DW_TAG_structure_type
|
||||
; DARWIN-DWARF: DW_TAG_compile_unit
|
||||
; DARWIN-DWARF: DW_TAG_variable
|
||||
; DARWIN-DWARF: DW_AT_type [DW_FORM_ref_addr] {{.*}}[[ADDR]])
|
||||
; CHECK-DWARF2: DW_TAG_compile_unit
|
||||
; CHECK-DWARF2: DW_TAG_variable
|
||||
; CHECK-DWARF2: DW_AT_type [DW_FORM_ref4] {{.*}} => {[[ADDR:.*]]})
|
||||
; CHECK-DWARF2: [[ADDR]]: DW_TAG_structure_type
|
||||
|
||||
%struct.foo = type { i8 }
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user