From e88b76a98995c08806b1fdc7a6b43b96fa709c60 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Thu, 5 Apr 2018 11:25:58 +0000 Subject: [PATCH] [ELF] - Reveal more information in -Map file about assignments. Currently, LLD print symbol assignment commands to the map file, but it does not do that for assignments that are outside of the section descriptions. Such assignments can affect the layout though. The patch implements the following: * Teaches LLD to print symbol assignments outside of section declaration. * Teaches LLD to print PROVIDE/HIDDEN/PROVIDE hidden commands. In case when symbol is not provided, nothing will be printed. Differential revision: https://reviews.llvm.org/D44894 llvm-svn: 329272 --- lld/ELF/LinkerScript.cpp | 2 + lld/ELF/LinkerScript.h | 6 +-- lld/ELF/MapFile.cpp | 18 +++++++- lld/ELF/ScriptParser.cpp | 27 ++++++----- lld/test/ELF/linkerscript/map-file.test | 59 +++++++++++++++--------- lld/test/ELF/linkerscript/map-file2.test | 1 + 6 files changed, 71 insertions(+), 42 deletions(-) diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index cc8623e488c8..15751b876e0f 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -1049,7 +1049,9 @@ void LinkerScript::assignAddresses() { for (BaseCommand *Base : SectionCommands) { if (auto *Cmd = dyn_cast(Base)) { + Cmd->Addr = Dot; assignSymbol(Cmd, false); + Cmd->Size = Dot - Cmd->Addr; continue; } diff --git a/lld/ELF/LinkerScript.h b/lld/ELF/LinkerScript.h index e3074f9877e6..4dd95867ab54 100644 --- a/lld/ELF/LinkerScript.h +++ b/lld/ELF/LinkerScript.h @@ -86,10 +86,8 @@ struct BaseCommand { // This represents ". = " or " = ". struct SymbolAssignment : BaseCommand { - SymbolAssignment(StringRef Name, Expr E, std::string Loc, - std::string CommandString) - : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc), - CommandString(CommandString) {} + SymbolAssignment(StringRef Name, Expr E, std::string Loc) + : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc) {} static bool classof(const BaseCommand *C) { return C->Kind == AssignmentKind; diff --git a/lld/ELF/MapFile.cpp b/lld/ELF/MapFile.cpp index 4de228fb2026..55597adf7b94 100644 --- a/lld/ELF/MapFile.cpp +++ b/lld/ELF/MapFile.cpp @@ -175,8 +175,20 @@ void elf::writeMapFile() { OS << right_justify("VMA", W) << ' ' << right_justify("LMA", 9) << ' ' << right_justify("Size", W) << " Align Out In Symbol\n"; - // Print out file contents. - for (OutputSection *OSec : OutputSections) { + for (BaseCommand *Base : Script->SectionCommands) { + if (auto *Cmd = dyn_cast(Base)) { + if (Cmd->Provide && !Cmd->Sym) + continue; + //FIXME: calculate and print LMA. + writeHeader(OS, Cmd->Addr, 0, Cmd->Size, 1); + OS << Cmd->CommandString << '\n'; + continue; + } + + auto *OSec = dyn_cast(Base); + if (!OSec) + continue; + writeHeader(OS, OSec->Addr, OSec->getLMA(), OSec->Size, OSec->Alignment); OS << OSec->Name << '\n'; @@ -206,6 +218,8 @@ void elf::writeMapFile() { } if (auto *Cmd = dyn_cast(Base)) { + if (Cmd->Provide && !Cmd->Sym) + continue; writeHeader(OS, Cmd->Addr, OSec->getLMA() + Cmd->Addr - OSec->getVA(0), Cmd->Size, 1); OS << Indent8 << Cmd->CommandString << '\n'; diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index ff650d8ef875..372bdc30ead3 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -267,8 +267,7 @@ void ScriptParser::readDefsym(StringRef Name) { Expr E = readExpr(); if (!atEOF()) setError("EOF expected, but got " + next()); - SymbolAssignment *Cmd = make(Name, E, getCurrentLocation(), - "" /*CommandString*/); + SymbolAssignment *Cmd = make(Name, E, getCurrentLocation()); Script->SectionCommands.push_back(Cmd); } @@ -773,27 +772,31 @@ SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) { Cmd->Provide = Provide; Cmd->Hidden = Hidden; expect(")"); - expect(";"); return Cmd; } SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) { + size_t OldPos = Pos; SymbolAssignment *Cmd = nullptr; - if (peek() == "=" || peek() == "+=") { + if (peek() == "=" || peek() == "+=") Cmd = readAssignment(Tok); - expect(";"); - } else if (Tok == "PROVIDE") { + else if (Tok == "PROVIDE") Cmd = readProvideHidden(true, false); - } else if (Tok == "HIDDEN") { + else if (Tok == "HIDDEN") Cmd = readProvideHidden(false, true); - } else if (Tok == "PROVIDE_HIDDEN") { + else if (Tok == "PROVIDE_HIDDEN") Cmd = readProvideHidden(true, true); + + if (Cmd) { + Cmd->CommandString = + Tok.str() + " " + + llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " "); + expect(";"); } return Cmd; } SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { - size_t OldPos = Pos; StringRef Op = next(); assert(Op == "=" || Op == "+="); Expr E = readExpr(); @@ -801,11 +804,7 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { std::string Loc = getCurrentLocation(); E = [=] { return add(Script->getSymbolValue(Name, Loc), E()); }; } - - std::string CommandString = - Name.str() + " " + - llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " "); - return make(Name, E, getCurrentLocation(), CommandString); + return make(Name, E, getCurrentLocation()); } // This is an operator-precedence parser to parse a linker diff --git a/lld/test/ELF/linkerscript/map-file.test b/lld/test/ELF/linkerscript/map-file.test index f930ae7fa6d2..00bcc7d26307 100644 --- a/lld/test/ELF/linkerscript/map-file.test +++ b/lld/test/ELF/linkerscript/map-file.test @@ -1,6 +1,6 @@ # REQUIRES: x86 -# RUN: echo '.section .foo.1, "a"; .quad 1' > %t.s +# RUN: echo '.quad sym3; .quad sym4; .section .foo.1, "a"; .quad 1' > %t.s # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o # RUN: ld.lld -o %t %t.o -Map=%t.map --script %s @@ -13,33 +13,48 @@ SECTIONS { SHORT(0x1122) LONG(0x11223344) QUAD(0x1122334455667788) + PROVIDE_HIDDEN(sym4 = .); . += 0x1000; *(.foo.1) + PROVIDE(unused1 = 0xff); + HIDDEN(sym6 = .); . += 0x123 * (1 + 1); foo = .; bar = 0x42 - 0x26; } + sym1 = .; + . += 0x500; + sym2 = .; + PROVIDE(unused2 = 0xff); + PROVIDE(sym3 = 42); } -# CHECK: VMA LMA Size Align Out In Symbol -# CHECK-NEXT: 1000 1000 125d 1 .foo -# CHECK-NEXT: 1000 1000 1 1 BYTE ( 0x11 ) -# CHECK-NEXT: 1001 1001 2 1 SHORT ( 0x1122 ) -# CHECK-NEXT: 1003 1003 4 1 LONG ( 0x11223344 ) -# CHECK-NEXT: 1007 1007 8 1 QUAD ( 0x1122334455667788 ) -# CHECK-NEXT: 100f 100f 1000 1 . += 0x1000 -# CHECK-NEXT: 200f 200f 8 1 {{.*}}{{/|\\}}map-file.test.tmp.o:(.foo.1) -# CHECK-NEXT: 2017 2017 246 1 . += 0x123 * ( 1 + 1 ) -# CHECK-NEXT: 225d 225d 0 1 foo = . -# CHECK-NEXT: 225d 225d 0 1 bar = 0x42 - 0x26 -# CHECK-NEXT: 2260 2260 0 4 .text -# CHECK-NEXT: 2260 2260 0 4 {{.*}}{{/|\\}}map-file.test.tmp.o:(.text) -# CHECK-NEXT: 0 0 8 1 .comment -# CHECK-NEXT: 0 0 8 1 :(.comment) -# CHECK-NEXT: 0 0 48 8 .symtab -# CHECK-NEXT: 0 0 48 8 :(.symtab) -# CHECK-NEXT: 0 0 2f 1 .shstrtab -# CHECK-NEXT: 0 0 2f 1 :(.shstrtab) -# CHECK-NEXT: 0 0 9 1 .strtab -# CHECK-NEXT: 0 0 9 1 :(.strtab) +# CHECK: VMA LMA Size Align Out In Symbol +# CHECK-NEXT: 0 0 1000 1 . = 0x1000 +# CHECK-NEXT: 1000 1000 125d 1 .foo +# CHECK-NEXT: 1000 1000 1 1 BYTE ( 0x11 ) +# CHECK-NEXT: 1001 1001 2 1 SHORT ( 0x1122 ) +# CHECK-NEXT: 1003 1003 4 1 LONG ( 0x11223344 ) +# CHECK-NEXT: 1007 1007 8 1 QUAD ( 0x1122334455667788 ) +# CHECK-NEXT: 100f 100f 0 1 PROVIDE_HIDDEN ( sym4 = . ) +# CHECK-NEXT: 100f 100f 1000 1 . += 0x1000 +# CHECK-NEXT: 200f 200f 8 1 {{.*}}{{/|\\}}map-file.test.tmp.o:(.foo.1) +# CHECK-NEXT: 2017 2017 0 1 HIDDEN ( sym6 = . ) +# CHECK-NEXT: 2017 2017 246 1 . += 0x123 * ( 1 + 1 ) +# CHECK-NEXT: 225d 225d 0 1 foo = . +# CHECK-NEXT: 225d 225d 0 1 bar = 0x42 - 0x26 +# CHECK-NEXT: 225d 0 0 1 sym1 = . +# CHECK-NEXT: 225d 0 500 1 . += 0x500 +# CHECK-NEXT: 275d 0 0 1 sym2 = . +# CHECK-NEXT: 275d 0 0 1 PROVIDE ( sym3 = 42 ) +# CHECK-NEXT: 2760 2760 10 4 .text +# CHECK-NEXT: 2760 2760 10 4 {{.*}}{{/|\\}}map-file.test.tmp.o:(.text) +# CHECK-NEXT: 0 0 8 1 .comment +# CHECK-NEXT: 0 0 8 1 :(.comment) +# CHECK-NEXT: 0 0 c0 8 .symtab +# CHECK-NEXT: 0 0 c0 8 :(.symtab) +# CHECK-NEXT: 0 0 2f 1 .shstrtab +# CHECK-NEXT: 0 0 2f 1 :(.shstrtab) +# CHECK-NEXT: 0 0 22 1 .strtab +# CHECK-NEXT: 0 0 22 1 :(.strtab) diff --git a/lld/test/ELF/linkerscript/map-file2.test b/lld/test/ELF/linkerscript/map-file2.test index 3ff764330f66..3cfaad62349a 100644 --- a/lld/test/ELF/linkerscript/map-file2.test +++ b/lld/test/ELF/linkerscript/map-file2.test @@ -17,6 +17,7 @@ SECTIONS { } # CHECK: VMA LMA Size Align Out In Symbol +# CHECK-NEXT: 0 0 1000 1 . = 0x1000 # CHECK-NEXT: 1000 1000 8 1 .aaa # CHECK-NEXT: 1000 1000 8 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.aaa) # CHECK-NEXT: 1008 2000 8 1 .bbb