[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
This commit is contained in:
George Rimar 2018-04-05 11:25:58 +00:00
parent ee01b1d390
commit e88b76a989
6 changed files with 71 additions and 42 deletions

View File

@ -1049,7 +1049,9 @@ void LinkerScript::assignAddresses() {
for (BaseCommand *Base : SectionCommands) {
if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {
Cmd->Addr = Dot;
assignSymbol(Cmd, false);
Cmd->Size = Dot - Cmd->Addr;
continue;
}

View File

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

View File

@ -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<SymbolAssignment>(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<OutputSection>(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<SymbolAssignment>(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';

View File

@ -267,8 +267,7 @@ void ScriptParser::readDefsym(StringRef Name) {
Expr E = readExpr();
if (!atEOF())
setError("EOF expected, but got " + next());
SymbolAssignment *Cmd = make<SymbolAssignment>(Name, E, getCurrentLocation(),
"" /*CommandString*/);
SymbolAssignment *Cmd = make<SymbolAssignment>(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<SymbolAssignment>(Name, E, getCurrentLocation(), CommandString);
return make<SymbolAssignment>(Name, E, getCurrentLocation());
}
// This is an operator-precedence parser to parse a linker

View File

@ -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 <internal>:(.comment)
# CHECK-NEXT: 0 0 48 8 .symtab
# CHECK-NEXT: 0 0 48 8 <internal>:(.symtab)
# CHECK-NEXT: 0 0 2f 1 .shstrtab
# CHECK-NEXT: 0 0 2f 1 <internal>:(.shstrtab)
# CHECK-NEXT: 0 0 9 1 .strtab
# CHECK-NEXT: 0 0 9 1 <internal>:(.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 <internal>:(.comment)
# CHECK-NEXT: 0 0 c0 8 .symtab
# CHECK-NEXT: 0 0 c0 8 <internal>:(.symtab)
# CHECK-NEXT: 0 0 2f 1 .shstrtab
# CHECK-NEXT: 0 0 2f 1 <internal>:(.shstrtab)
# CHECK-NEXT: 0 0 22 1 .strtab
# CHECK-NEXT: 0 0 22 1 <internal>:(.strtab)

View File

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