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 -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 28 #include "llvm/Support/raw_ostream.h" 29 30 using namespace llvm; 31 using namespace llvm::object; 32 33 using namespace lld; 34 using namespace lld::elf; 35 36 static void writeOutSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, 37 uint64_t Size, uint64_t Align, StringRef Name) { 38 OS << format("%0*llx %0*llx %5lld ", Width, Address, Width, Size, Align) 39 << left_justify(Name, 7); 40 } 41 42 static 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 49 static 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 56 static 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 63 template <class ELFT> 64 static void writeInputSection(raw_fd_ostream &OS, const InputSection *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, 70 IS->template getSize<ELFT>(), IS->Alignment, Name); 71 OS << '\n'; 72 PrevName = Name; 73 } 74 75 elf::ObjectFile<ELFT> *File = IS->template getFile<ELFT>(); 76 if (!File) 77 return; 78 writeFileLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, 79 IS->template getSize<ELFT>(), IS->Alignment, toString(File)); 80 OS << '\n'; 81 82 for (SymbolBody *Sym : File->getSymbols()) { 83 auto *DR = dyn_cast<DefinedRegular>(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 96 template <class ELFT> 97 static void writeMapFile2(raw_fd_ostream &OS, 98 ArrayRef<OutputSection *> OutputSections) { 99 int Width = ELFT::Is64Bits ? 16 : 8; 100 101 OS << left_justify("Address", Width) << ' ' << left_justify("Size", Width) 102 << " Align Out In File Symbol\n"; 103 104 for (OutputSection *Sec : OutputSections) { 105 writeOutSecLine(OS, Width, Sec->Addr, Sec->Size, Sec->Addralign, Sec->Name); 106 OS << '\n'; 107 108 StringRef PrevName = ""; 109 for (InputSection *IS : Sec->Sections) { 110 writeInputSection<ELFT>(OS, IS, PrevName); 111 } 112 } 113 } 114 115 template <class ELFT> 116 void elf::writeMapFile(ArrayRef<OutputSection *> OutputSections) { 117 if (Config->MapFile.empty()) 118 return; 119 120 std::error_code EC; 121 raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); 122 if (EC) 123 error("cannot open " + Config->MapFile + ": " + EC.message()); 124 else 125 writeMapFile2<ELFT>(OS, OutputSections); 126 } 127 128 template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSection *>); 129 template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSection *>); 130 template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSection *>); 131 template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSection *>); 132