summaryrefslogtreecommitdiffstats
path: root/llvm/lib/MC
diff options
context:
space:
mode:
authorKeno Fischer <kfischer@college.harvard.edu>2016-12-08 01:40:21 +0000
committerKeno Fischer <kfischer@college.harvard.edu>2016-12-08 01:40:21 +0000
commit460218fb7d13132e4ea3def3b75eb43aa505b2db (patch)
tree0527e1c2d2e68010380ffda91cbb5c08bd3d8231 /llvm/lib/MC
parent4574a890511d8bf7b9e7e3d59d9ad368ab79f843 (diff)
downloadbcm5719-llvm-460218fb7d13132e4ea3def3b75eb43aa505b2db.tar.gz
bcm5719-llvm-460218fb7d13132e4ea3def3b75eb43aa505b2db.zip
[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
Diffstat (limited to 'llvm/lib/MC')
-rw-r--r--llvm/lib/MC/MCAsmStreamer.cpp6
-rw-r--r--llvm/lib/MC/MCCodeView.cpp2
-rw-r--r--llvm/lib/MC/MCParser/COFFAsmParser.cpp15
-rw-r--r--llvm/lib/MC/MCStreamer.cpp5
-rw-r--r--llvm/lib/MC/WinCOFFStreamer.cpp15
5 files changed, 33 insertions, 10 deletions
diff --git a/llvm/lib/MC/MCAsmStreamer.cpp b/llvm/lib/MC/MCAsmStreamer.cpp
index e36903e1fae..7cff7b9b272 100644
--- a/llvm/lib/MC/MCAsmStreamer.cpp
+++ b/llvm/lib/MC/MCAsmStreamer.cpp
@@ -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();
}
diff --git a/llvm/lib/MC/MCCodeView.cpp b/llvm/lib/MC/MCCodeView.cpp
index ac1acc08b0c..ae0e50a37d7 100644
--- a/llvm/lib/MC/MCCodeView.cpp
+++ b/llvm/lib/MC/MCCodeView.cpp
@@ -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.
diff --git a/llvm/lib/MC/MCParser/COFFAsmParser.cpp b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
index 2c9f9eb0cda..f4114795a92 100644
--- a/llvm/lib/MC/MCParser/COFFAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/COFFAsmParser.cpp
@@ -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;
}
diff --git a/llvm/lib/MC/MCStreamer.cpp b/llvm/lib/MC/MCStreamer.cpp
index ebbf8116fa3..96fb566aa3a 100644
--- a/llvm/lib/MC/MCStreamer.cpp
+++ b/llvm/lib/MC/MCStreamer.cpp
@@ -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
diff --git a/llvm/lib/MC/WinCOFFStreamer.cpp b/llvm/lib/MC/WinCOFFStreamer.cpp
index 5c6407ef1e5..6383d879403 100644
--- a/llvm/lib/MC/WinCOFFStreamer.cpp
+++ b/llvm/lib/MC/WinCOFFStreamer.cpp
@@ -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);
}
OpenPOWER on IntegriCloud