Index: lld/trunk/ELF/LinkerScript.h =================================================================== --- lld/trunk/ELF/LinkerScript.h +++ lld/trunk/ELF/LinkerScript.h @@ -86,8 +86,10 @@ // This represents ". = " or " = ". struct SymbolAssignment : BaseCommand { - SymbolAssignment(StringRef Name, Expr E, std::string Loc) - : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc) {} + SymbolAssignment(StringRef Name, Expr E, std::string Loc, + std::string CommandString) + : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc), + CommandString(CommandString) {} static bool classof(const BaseCommand *C) { return C->Kind == AssignmentKind; @@ -106,6 +108,16 @@ // Holds file name and line number for error reporting. std::string Location; + + // A string representation of this command. We use this for -Map. + std::string CommandString; + + // This is just an offset of this assignment command in the output section. + unsigned Offset; + + // Size of this assignment command. This is usually 0, but if you move '.' + // or use a BYTE()-family command, this may be greater than 0." + unsigned Size; }; // Linker scripts allow additional constraints to be put on ouput sections. @@ -178,11 +190,15 @@ // Represents BYTE(), SHORT(), LONG(), or QUAD(). struct ByteCommand : BaseCommand { - ByteCommand(Expr E, unsigned Size) - : BaseCommand(ByteKind), Expression(E), Size(Size) {} + ByteCommand(Expr E, unsigned Size, std::string CommandString) + : BaseCommand(ByteKind), Expression(E), Size(Size), + CommandString(CommandString) {} static bool classof(const BaseCommand *C) { return C->Kind == ByteKind; } + // Keeps string representing the command. Used for -Map" is perhaps better. + std::string CommandString; + Expr Expression; unsigned Offset; unsigned Size; Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -767,7 +767,9 @@ for (BaseCommand *Base : Sec->SectionCommands) { // This handles the assignments to symbol or to the dot. if (auto *Cmd = dyn_cast(Base)) { + Cmd->Offset = Dot - Ctx->OutSec->Addr; assignSymbol(Cmd, true); + Cmd->Size = Dot - Ctx->OutSec->Addr - Cmd->Offset; continue; } Index: lld/trunk/ELF/MapFile.cpp =================================================================== --- lld/trunk/ELF/MapFile.cpp +++ lld/trunk/ELF/MapFile.cpp @@ -177,16 +177,34 @@ OS << OSec->Name << '\n'; // Dump symbols for each input section. - for (InputSection *IS : getInputSections(OSec)) { - if (IS == InX::EhFrame) { - printEhFrame(OS, OSec); + for (BaseCommand *Base : OSec->SectionCommands) { + if (auto *ISD = dyn_cast(Base)) { + for (InputSection *IS : ISD->Sections) { + if (IS == InX::EhFrame) { + printEhFrame(OS, OSec); + continue; + } + + writeHeader(OS, OSec->Addr + IS->OutSecOff, IS->getSize(), + IS->Alignment); + OS << Indent8 << toString(IS) << '\n'; + for (Symbol *Sym : SectionSyms[IS]) + OS << SymStr[Sym] << '\n'; + } continue; } - writeHeader(OS, OSec->Addr + IS->OutSecOff, IS->getSize(), IS->Alignment); - OS << Indent8 << toString(IS) << '\n'; - for (Symbol *Sym : SectionSyms[IS]) - OS << SymStr[Sym] << '\n'; + if (auto *Cmd = dyn_cast(Base)) { + writeHeader(OS, OSec->Addr + Cmd->Offset, Cmd->Size, 1); + OS << Indent8 << Cmd->CommandString << '\n'; + continue; + } + + if (auto *Cmd = dyn_cast(Base)) { + writeHeader(OS, OSec->Addr + Cmd->Offset, Cmd->Size, 1); + OS << Indent8 << Cmd->CommandString << '\n'; + continue; + } } } } Index: lld/trunk/ELF/ScriptParser.cpp =================================================================== --- lld/trunk/ELF/ScriptParser.cpp +++ lld/trunk/ELF/ScriptParser.cpp @@ -267,7 +267,8 @@ Expr E = readExpr(); if (!atEOF()) setError("EOF expected, but got " + next()); - SymbolAssignment *Cmd = make(Name, E, getCurrentLocation()); + SymbolAssignment *Cmd = make(Name, E, getCurrentLocation(), + "" /*CommandString*/); Script->SectionCommands.push_back(Cmd); } @@ -791,6 +792,7 @@ } SymbolAssignment *ScriptParser::readAssignment(StringRef Name) { + size_t OldPos = Pos; StringRef Op = next(); assert(Op == "=" || Op == "+="); Expr E = readExpr(); @@ -798,7 +800,11 @@ std::string Loc = getCurrentLocation(); E = [=] { return add(Script->getSymbolValue(Name, Loc), E()); }; } - return make(Name, E, getCurrentLocation()); + + std::string CommandString = + Name.str() + " " + + llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " "); + return make(Name, E, getCurrentLocation(), CommandString); } // This is an operator-precedence parser to parse a linker @@ -952,7 +958,13 @@ .Default(-1); if (Size == -1) return nullptr; - return make(readParenExpr(), Size); + + size_t OldPos = Pos; + Expr E = readParenExpr(); + std::string CommandString = + Tok.str() + " " + + llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " "); + return make(E, Size, CommandString); } StringRef ScriptParser::readParenLiteral() { Index: lld/trunk/test/ELF/linkerscript/map-file.test =================================================================== --- lld/trunk/test/ELF/linkerscript/map-file.test +++ lld/trunk/test/ELF/linkerscript/map-file.test @@ -0,0 +1,38 @@ +# REQUIRES: x86 + +# RUN: echo ".section .foo.1,\"a\"" > %t.s +# RUN: echo ".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 +# RUN: FileCheck -strict-whitespace %s < %t.map + +SECTIONS { + . = 0x1000; + .foo : { + BYTE(0x11) + SHORT(0x1122) + LONG(0x11223344) + QUAD(0x1122334455667788) + . += 0x1000; + *(.foo.1) + . += 0x123 * + (1 + 1); + foo = .; + bar = 0x42 - 0x26; + } +} + +# CHECK: Address Size Align Out In Symbol +# CHECK-NEXT: 0000000000001000 000000000000125d 1 .foo +# CHECK-NEXT: 0000000000001000 0000000000000001 1 BYTE ( 0x11 ) +# CHECK-NEXT: 0000000000001001 0000000000000002 1 SHORT ( 0x1122 ) +# CHECK-NEXT: 0000000000001003 0000000000000004 1 LONG ( 0x11223344 ) +# CHECK-NEXT: 0000000000001007 0000000000000008 1 QUAD ( 0x1122334455667788 ) +# CHECK-NEXT: 000000000000100f 0000000000001000 1 . += 0x1000 +# CHECK-NEXT: 000000000000200f 0000000000000008 1 {{.*}}{{/|\\}}map-file.test.tmp.o:(.foo.1) +# CHECK-NEXT: 0000000000002017 0000000000000246 1 . += 0x123 * ( 1 + 1 ) +# CHECK-NEXT: 000000000000225d 0000000000000000 1 foo = . +# CHECK-NEXT: 000000000000225d 0000000000000000 1 bar = 0x42 - 0x26 +# CHECK-NEXT: 0000000000002260 0000000000000000 4 .text +# CHECK-NEXT: 0000000000002260 0000000000000000 4 {{.*}}{{/|\\}}map-file.test.tmp.o:(.text)