blob: 8986b9f78f7a5ca0a5e4ea545ebfba8ac090eea8 [file] [log] [blame]
Rafael Espindola1ebfc592017-01-13 21:05:46 +00001//===- MapFile.cpp --------------------------------------------------------===//
2//
3// The LLVM Linker
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the -Map option. It shows lists in order and
11// hierarchically the output sections, input sections, input files and
12// symbol:
13//
14// Address Size Align Out In File Symbol
15// =================================================================
16// 00201000 00000015 4 .text
17// 00201000 0000000e 4 .text
18// 00201000 0000000e 4 test.o
19// 0020100e 00000000 0 local
20// 00201005 00000000 0 f(int)
21//
22//===----------------------------------------------------------------------===//
23
24#include "MapFile.h"
25#include "InputFiles.h"
26#include "Strings.h"
27
Rui Ueyama543731f2017-01-15 00:41:21 +000028#include "llvm/Support/raw_ostream.h"
Rafael Espindola1ebfc592017-01-13 21:05:46 +000029
30using namespace llvm;
31using namespace llvm::object;
32
33using namespace lld;
34using namespace lld::elf;
35
36static void writeOutSecLine(raw_fd_ostream &OS, int Width, uint64_t Address,
37 uint64_t Size, uint64_t Align, StringRef Name) {
Rui Ueyama483ffa32017-01-15 01:11:47 +000038 OS << format("%0*x %0*x %5x ", Width, Address, Width, Size, Align)
Rafael Espindola1ebfc592017-01-13 21:05:46 +000039 << left_justify(Name, 7);
40}
41
42static void writeInSecLine(raw_fd_ostream &OS, int Width, uint64_t Address,
43 uint64_t Size, uint64_t Align, StringRef Name) {
44 // Pass an empty name to align the text to the correct column.
45 writeOutSecLine(OS, Width, Address, Size, Align, "");
46 OS << ' ' << left_justify(Name, 7);
47}
48
49static void writeFileLine(raw_fd_ostream &OS, int Width, uint64_t Address,
50 uint64_t Size, uint64_t Align, StringRef Name) {
51 // Pass an empty name to align the text to the correct column.
52 writeInSecLine(OS, Width, Address, Size, Align, "");
53 OS << ' ' << left_justify(Name, 7);
54}
55
56static void writeSymbolLine(raw_fd_ostream &OS, int Width, uint64_t Address,
57 uint64_t Size, StringRef Name) {
58 // Pass an empty name to align the text to the correct column.
59 writeFileLine(OS, Width, Address, Size, 0, "");
60 OS << ' ' << left_justify(Name, 7);
61}
62
63template <class ELFT>
Rui Ueyamadb540ff2017-01-14 00:37:28 +000064static void writeInputSection(raw_fd_ostream &OS, const InputSection<ELFT> *IS,
65 StringRef &PrevName) {
66 int Width = ELFT::Is64Bits ? 16 : 8;
67 StringRef Name = IS->Name;
68 if (Name != PrevName) {
69 writeInSecLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(),
70 IS->Alignment, Name);
71 OS << '\n';
72 PrevName = Name;
73 }
74
75 elf::ObjectFile<ELFT> *File = IS->getFile();
76 if (!File)
77 return;
78 writeFileLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(),
79 IS->Alignment, toString(File));
80 OS << '\n';
81
82 for (SymbolBody *Sym : File->getSymbols()) {
83 auto *DR = dyn_cast<DefinedRegular<ELFT>>(Sym);
84 if (!DR)
85 continue;
86 if (DR->Section != IS)
87 continue;
88 if (DR->isSection())
89 continue;
90 writeSymbolLine(OS, Width, Sym->getVA<ELFT>(), Sym->getSize<ELFT>(),
91 toString(*Sym));
92 OS << '\n';
93 }
94}
95
96template <class ELFT>
Rui Ueyama543731f2017-01-15 00:41:21 +000097static void writeMapFile2(raw_fd_ostream &OS,
Rafael Espindola1ebfc592017-01-13 21:05:46 +000098 ArrayRef<OutputSectionBase *> OutputSections) {
Rafael Espindola1ebfc592017-01-13 21:05:46 +000099 int Width = ELFT::Is64Bits ? 16 : 8;
Rui Ueyamadb540ff2017-01-14 00:37:28 +0000100
Rafael Espindola1ebfc592017-01-13 21:05:46 +0000101 OS << left_justify("Address", Width) << ' ' << left_justify("Size", Width)
Rui Ueyama483ffa32017-01-15 01:11:47 +0000102 << " Align Out In File Symbol\n";
Rui Ueyamadb540ff2017-01-14 00:37:28 +0000103
Rafael Espindola1ebfc592017-01-13 21:05:46 +0000104 for (OutputSectionBase *Sec : OutputSections) {
Rui Ueyamadb540ff2017-01-14 00:37:28 +0000105 writeOutSecLine(OS, Width, Sec->Addr, Sec->Size, Sec->Addralign,
106 Sec->getName());
Rafael Espindola1ebfc592017-01-13 21:05:46 +0000107 OS << '\n';
Rui Ueyamadb540ff2017-01-14 00:37:28 +0000108
Rafael Espindola1ebfc592017-01-13 21:05:46 +0000109 StringRef PrevName = "";
110 Sec->forEachInputSection([&](InputSectionData *S) {
Rui Ueyamadb540ff2017-01-14 00:37:28 +0000111 if (const auto *IS = dyn_cast<InputSection<ELFT>>(S))
112 writeInputSection(OS, IS, PrevName);
Rafael Espindola1ebfc592017-01-13 21:05:46 +0000113 });
114 }
115}
116
117template <class ELFT>
118void elf::writeMapFile(ArrayRef<OutputSectionBase *> OutputSections) {
Rui Ueyama543731f2017-01-15 00:41:21 +0000119 if (Config->MapFile.empty())
Rafael Espindola1ebfc592017-01-13 21:05:46 +0000120 return;
121
Rui Ueyama543731f2017-01-15 00:41:21 +0000122 std::error_code EC;
123 raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None);
Rafael Espindola1ebfc592017-01-13 21:05:46 +0000124 if (EC)
Rui Ueyamac9807c32017-01-16 01:07:19 +0000125 error("cannot open " + Config->MapFile + ": " + EC.message());
126 else
127 writeMapFile2<ELFT>(OS, OutputSections);
Rafael Espindola1ebfc592017-01-13 21:05:46 +0000128}
129
130template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionBase *>);
131template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionBase *>);
132template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionBase *>);
133template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionBase *>);