11ebfc59cSRafael Espindola //===- MapFile.cpp --------------------------------------------------------===// 21ebfc59cSRafael Espindola // 31ebfc59cSRafael Espindola // The LLVM Linker 41ebfc59cSRafael Espindola // 51ebfc59cSRafael Espindola // This file is distributed under the University of Illinois Open Source 61ebfc59cSRafael Espindola // License. See LICENSE.TXT for details. 71ebfc59cSRafael Espindola // 81ebfc59cSRafael Espindola //===----------------------------------------------------------------------===// 91ebfc59cSRafael Espindola // 101ebfc59cSRafael Espindola // This file implements the -Map option. It shows lists in order and 111ebfc59cSRafael Espindola // hierarchically the output sections, input sections, input files and 121ebfc59cSRafael Espindola // symbol: 131ebfc59cSRafael Espindola // 141ebfc59cSRafael Espindola // Address Size Align Out In File Symbol 151ebfc59cSRafael Espindola // ================================================================= 161ebfc59cSRafael Espindola // 00201000 00000015 4 .text 171ebfc59cSRafael Espindola // 00201000 0000000e 4 .text 181ebfc59cSRafael Espindola // 00201000 0000000e 4 test.o 191ebfc59cSRafael Espindola // 0020100e 00000000 0 local 201ebfc59cSRafael Espindola // 00201005 00000000 0 f(int) 211ebfc59cSRafael Espindola // 221ebfc59cSRafael Espindola //===----------------------------------------------------------------------===// 231ebfc59cSRafael Espindola 241ebfc59cSRafael Espindola #include "MapFile.h" 251ebfc59cSRafael Espindola #include "InputFiles.h" 261ebfc59cSRafael Espindola #include "Strings.h" 271ebfc59cSRafael Espindola 28543731f9SRui Ueyama #include "llvm/Support/raw_ostream.h" 291ebfc59cSRafael Espindola 301ebfc59cSRafael Espindola using namespace llvm; 311ebfc59cSRafael Espindola using namespace llvm::object; 321ebfc59cSRafael Espindola 331ebfc59cSRafael Espindola using namespace lld; 341ebfc59cSRafael Espindola using namespace lld::elf; 351ebfc59cSRafael Espindola 361ebfc59cSRafael Espindola static void writeOutSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, 371ebfc59cSRafael Espindola uint64_t Size, uint64_t Align, StringRef Name) { 38*483ffa33SRui Ueyama OS << format("%0*x %0*x %5x ", Width, Address, Width, Size, Align) 391ebfc59cSRafael Espindola << left_justify(Name, 7); 401ebfc59cSRafael Espindola } 411ebfc59cSRafael Espindola 421ebfc59cSRafael Espindola static void writeInSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, 431ebfc59cSRafael Espindola uint64_t Size, uint64_t Align, StringRef Name) { 441ebfc59cSRafael Espindola // Pass an empty name to align the text to the correct column. 451ebfc59cSRafael Espindola writeOutSecLine(OS, Width, Address, Size, Align, ""); 461ebfc59cSRafael Espindola OS << ' ' << left_justify(Name, 7); 471ebfc59cSRafael Espindola } 481ebfc59cSRafael Espindola 491ebfc59cSRafael Espindola static void writeFileLine(raw_fd_ostream &OS, int Width, uint64_t Address, 501ebfc59cSRafael Espindola uint64_t Size, uint64_t Align, StringRef Name) { 511ebfc59cSRafael Espindola // Pass an empty name to align the text to the correct column. 521ebfc59cSRafael Espindola writeInSecLine(OS, Width, Address, Size, Align, ""); 531ebfc59cSRafael Espindola OS << ' ' << left_justify(Name, 7); 541ebfc59cSRafael Espindola } 551ebfc59cSRafael Espindola 561ebfc59cSRafael Espindola static void writeSymbolLine(raw_fd_ostream &OS, int Width, uint64_t Address, 571ebfc59cSRafael Espindola uint64_t Size, StringRef Name) { 581ebfc59cSRafael Espindola // Pass an empty name to align the text to the correct column. 591ebfc59cSRafael Espindola writeFileLine(OS, Width, Address, Size, 0, ""); 601ebfc59cSRafael Espindola OS << ' ' << left_justify(Name, 7); 611ebfc59cSRafael Espindola } 621ebfc59cSRafael Espindola 631ebfc59cSRafael Espindola template <class ELFT> 64db540ff0SRui Ueyama static void writeInputSection(raw_fd_ostream &OS, const InputSection<ELFT> *IS, 65db540ff0SRui Ueyama StringRef &PrevName) { 661ebfc59cSRafael Espindola int Width = ELFT::Is64Bits ? 16 : 8; 671ebfc59cSRafael Espindola StringRef Name = IS->Name; 681ebfc59cSRafael Espindola if (Name != PrevName) { 69db540ff0SRui Ueyama writeInSecLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), 701ebfc59cSRafael Espindola IS->Alignment, Name); 711ebfc59cSRafael Espindola OS << '\n'; 721ebfc59cSRafael Espindola PrevName = Name; 731ebfc59cSRafael Espindola } 74db540ff0SRui Ueyama 751ebfc59cSRafael Espindola elf::ObjectFile<ELFT> *File = IS->getFile(); 761ebfc59cSRafael Espindola if (!File) 771ebfc59cSRafael Espindola return; 78db540ff0SRui Ueyama writeFileLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), 79db540ff0SRui Ueyama IS->Alignment, toString(File)); 801ebfc59cSRafael Espindola OS << '\n'; 81db540ff0SRui Ueyama 82db540ff0SRui Ueyama for (SymbolBody *Sym : File->getSymbols()) { 831ebfc59cSRafael Espindola auto *DR = dyn_cast<DefinedRegular<ELFT>>(Sym); 841ebfc59cSRafael Espindola if (!DR) 851ebfc59cSRafael Espindola continue; 861ebfc59cSRafael Espindola if (DR->Section != IS) 871ebfc59cSRafael Espindola continue; 881ebfc59cSRafael Espindola if (DR->isSection()) 891ebfc59cSRafael Espindola continue; 901ebfc59cSRafael Espindola writeSymbolLine(OS, Width, Sym->getVA<ELFT>(), Sym->getSize<ELFT>(), 911ebfc59cSRafael Espindola toString(*Sym)); 921ebfc59cSRafael Espindola OS << '\n'; 931ebfc59cSRafael Espindola } 94db540ff0SRui Ueyama } 95db540ff0SRui Ueyama 96db540ff0SRui Ueyama template <class ELFT> 97543731f9SRui Ueyama static void writeMapFile2(raw_fd_ostream &OS, 98db540ff0SRui Ueyama ArrayRef<OutputSectionBase *> OutputSections) { 99db540ff0SRui Ueyama int Width = ELFT::Is64Bits ? 16 : 8; 100db540ff0SRui Ueyama 101db540ff0SRui Ueyama OS << left_justify("Address", Width) << ' ' << left_justify("Size", Width) 102*483ffa33SRui Ueyama << " Align Out In File Symbol\n"; 103db540ff0SRui Ueyama 104db540ff0SRui Ueyama for (OutputSectionBase *Sec : OutputSections) { 105db540ff0SRui Ueyama writeOutSecLine(OS, Width, Sec->Addr, Sec->Size, Sec->Addralign, 106db540ff0SRui Ueyama Sec->getName()); 107db540ff0SRui Ueyama OS << '\n'; 108db540ff0SRui Ueyama 109db540ff0SRui Ueyama StringRef PrevName = ""; 110db540ff0SRui Ueyama Sec->forEachInputSection([&](InputSectionData *S) { 111db540ff0SRui Ueyama if (const auto *IS = dyn_cast<InputSection<ELFT>>(S)) 112db540ff0SRui Ueyama writeInputSection(OS, IS, PrevName); 1131ebfc59cSRafael Espindola }); 1141ebfc59cSRafael Espindola } 1151ebfc59cSRafael Espindola } 1161ebfc59cSRafael Espindola 1171ebfc59cSRafael Espindola template <class ELFT> 1181ebfc59cSRafael Espindola void elf::writeMapFile(ArrayRef<OutputSectionBase *> OutputSections) { 119543731f9SRui Ueyama if (Config->MapFile.empty()) 1201ebfc59cSRafael Espindola return; 1211ebfc59cSRafael Espindola 122543731f9SRui Ueyama std::error_code EC; 123543731f9SRui Ueyama raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); 1241ebfc59cSRafael Espindola if (EC) 125543731f9SRui Ueyama fatal("cannot open " + Config->MapFile + ": " + EC.message()); 126543731f9SRui Ueyama writeMapFile2<ELFT>(OS, OutputSections); 1271ebfc59cSRafael Espindola } 1281ebfc59cSRafael Espindola 1291ebfc59cSRafael Espindola template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionBase *>); 1301ebfc59cSRafael Espindola template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionBase *>); 1311ebfc59cSRafael Espindola template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionBase *>); 1321ebfc59cSRafael Espindola template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionBase *>); 133