[ELF] - Show data and assignment commands in the map file.

Patch teaches LLD to print BYTE/SHORT/LONG/QUAD and
location move commands to the map file.

Differential revision: https://reviews.llvm.org/D44004

llvm-svn: 327612
This commit is contained in:
George Rimar 2018-03-15 09:16:40 +00:00
parent 3662da80de
commit 84bcabcb86
5 changed files with 100 additions and 14 deletions

View File

@ -767,7 +767,9 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {
for (BaseCommand *Base : Sec->SectionCommands) {
// This handles the assignments to symbol or to the dot.
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
Cmd->Offset = Dot - Ctx->OutSec->Addr;
assignSymbol(Cmd, true);
Cmd->Size = Dot - Ctx->OutSec->Addr - Cmd->Offset;
continue;
}

View File

@ -86,8 +86,10 @@ struct BaseCommand {
// This represents ". = <expr>" or "<symbol> = <expr>".
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 @@ struct SymbolAssignment : BaseCommand {
// 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 @@ struct AssertCommand : BaseCommand {
// 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;

View File

@ -177,16 +177,34 @@ void elf::writeMapFile() {
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<InputSectionDescription>(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<ByteCommand>(Base)) {
writeHeader(OS, OSec->Addr + Cmd->Offset, Cmd->Size, 1);
OS << Indent8 << Cmd->CommandString << '\n';
continue;
}
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
writeHeader(OS, OSec->Addr + Cmd->Offset, Cmd->Size, 1);
OS << Indent8 << Cmd->CommandString << '\n';
continue;
}
}
}
}

View File

@ -267,7 +267,8 @@ void ScriptParser::readDefsym(StringRef Name) {
Expr E = readExpr();
if (!atEOF())
setError("EOF expected, but got " + next());
SymbolAssignment *Cmd = make<SymbolAssignment>(Name, E, getCurrentLocation());
SymbolAssignment *Cmd = make<SymbolAssignment>(Name, E, getCurrentLocation(),
"" /*CommandString*/);
Script->SectionCommands.push_back(Cmd);
}
@ -791,6 +792,7 @@ SymbolAssignment *ScriptParser::readProvideOrAssignment(StringRef Tok) {
}
SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
size_t OldPos = Pos;
StringRef Op = next();
assert(Op == "=" || Op == "+=");
Expr E = readExpr();
@ -798,7 +800,11 @@ SymbolAssignment *ScriptParser::readAssignment(StringRef Name) {
std::string Loc = getCurrentLocation();
E = [=] { return add(Script->getSymbolValue(Name, Loc), E()); };
}
return make<SymbolAssignment>(Name, E, getCurrentLocation());
std::string CommandString =
Name.str() + " " +
llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " ");
return make<SymbolAssignment>(Name, E, getCurrentLocation(), CommandString);
}
// This is an operator-precedence parser to parse a linker
@ -952,7 +958,13 @@ ByteCommand *ScriptParser::readByteCommand(StringRef Tok) {
.Default(-1);
if (Size == -1)
return nullptr;
return make<ByteCommand>(readParenExpr(), Size);
size_t OldPos = Pos;
Expr E = readParenExpr();
std::string CommandString =
Tok.str() + " " +
llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " ");
return make<ByteCommand>(E, Size, CommandString);
}
StringRef ScriptParser::readParenLiteral() {

View File

@ -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)