1 //===- 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 /lldmap 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 "Error.h" 26 #include "Symbols.h" 27 #include "Writer.h" 28 29 #include "llvm/Support/raw_ostream.h" 30 31 using namespace llvm; 32 using namespace llvm::object; 33 34 using namespace lld; 35 using namespace lld::coff; 36 37 static void writeOutSecLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size, 38 uint64_t Align, StringRef Name) { 39 OS << format("%08llx %08llx %5lld ", Address, Size, Align) 40 << left_justify(Name, 7); 41 } 42 43 static void writeInSecLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size, 44 uint64_t Align, StringRef Name) { 45 // Pass an empty name to align the text to the correct column. 46 writeOutSecLine(OS, Address, Size, Align, ""); 47 OS << ' ' << left_justify(Name, 7); 48 } 49 50 static void writeFileLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size, 51 uint64_t Align, StringRef Name) { 52 // Pass an empty name to align the text to the correct column. 53 writeInSecLine(OS, Address, Size, Align, ""); 54 OS << ' ' << left_justify(Name, 7); 55 } 56 57 static void writeSymbolLine(raw_fd_ostream &OS, uint64_t Address, uint64_t Size, 58 StringRef Name) { 59 // Pass an empty name to align the text to the correct column. 60 writeFileLine(OS, Address, Size, 0, ""); 61 OS << ' ' << left_justify(Name, 7); 62 } 63 64 static void writeSectionChunk(raw_fd_ostream &OS, const SectionChunk *SC, 65 StringRef &PrevName) { 66 StringRef Name = SC->getSectionName(); 67 if (Name != PrevName) { 68 writeInSecLine(OS, SC->getRVA(), SC->getSize(), SC->getAlign(), Name); 69 OS << '\n'; 70 PrevName = Name; 71 } 72 coff::ObjectFile *File = SC->File; 73 if (!File) 74 return; 75 writeFileLine(OS, SC->getRVA(), SC->getSize(), SC->getAlign(), 76 toString(File)); 77 OS << '\n'; 78 ArrayRef<SymbolBody *> Syms = File->getSymbols(); 79 for (SymbolBody *Sym : Syms) { 80 auto *DR = dyn_cast<DefinedRegular>(Sym); 81 if (!DR || DR->getChunk() != SC || 82 DR->getCOFFSymbol().isSectionDefinition()) 83 continue; 84 writeSymbolLine(OS, DR->getRVA(), SC->getSize(), toString(*Sym)); 85 OS << '\n'; 86 } 87 } 88 89 static void writeMapFile2(raw_fd_ostream &OS, 90 ArrayRef<OutputSection *> OutputSections) { 91 OS << "Address Size Align Out In File Symbol\n"; 92 93 for (OutputSection *Sec : OutputSections) { 94 uint32_t VA = Sec->getRVA(); 95 writeOutSecLine(OS, VA, Sec->getVirtualSize(), /*Align=*/PageSize, 96 Sec->getName()); 97 OS << '\n'; 98 StringRef PrevName = ""; 99 for (Chunk *C : Sec->getChunks()) 100 if (const auto *SC = dyn_cast<SectionChunk>(C)) 101 writeSectionChunk(OS, SC, PrevName); 102 } 103 } 104 105 void coff::writeMapFile(ArrayRef<OutputSection *> OutputSections) { 106 if (Config->MapFile.empty()) 107 return; 108 109 std::error_code EC; 110 raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); 111 if (EC) 112 fatal("cannot open " + Config->MapFile + ": " + EC.message()); 113 writeMapFile2(OS, OutputSections); 114 } 115