[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:
parent
3662da80de
commit
84bcabcb86
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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)
|
Loading…
Reference in New Issue