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 281ebfc59cSRafael Espindola #include "llvm/Support/FileUtilities.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) { 381ebfc59cSRafael Espindola OS << format_hex_no_prefix(Address, Width) << ' ' 391ebfc59cSRafael Espindola << format_hex_no_prefix(Size, Width) << ' ' << format("%5x ", Align) 401ebfc59cSRafael Espindola << left_justify(Name, 7); 411ebfc59cSRafael Espindola } 421ebfc59cSRafael Espindola 431ebfc59cSRafael Espindola static void writeInSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, 441ebfc59cSRafael Espindola uint64_t Size, uint64_t Align, StringRef Name) { 451ebfc59cSRafael Espindola // Pass an empty name to align the text to the correct column. 461ebfc59cSRafael Espindola writeOutSecLine(OS, Width, Address, Size, Align, ""); 471ebfc59cSRafael Espindola OS << ' ' << left_justify(Name, 7); 481ebfc59cSRafael Espindola } 491ebfc59cSRafael Espindola 501ebfc59cSRafael Espindola static void writeFileLine(raw_fd_ostream &OS, int Width, uint64_t Address, 511ebfc59cSRafael Espindola uint64_t Size, uint64_t Align, StringRef Name) { 521ebfc59cSRafael Espindola // Pass an empty name to align the text to the correct column. 531ebfc59cSRafael Espindola writeInSecLine(OS, Width, Address, Size, Align, ""); 541ebfc59cSRafael Espindola OS << ' ' << left_justify(Name, 7); 551ebfc59cSRafael Espindola } 561ebfc59cSRafael Espindola 571ebfc59cSRafael Espindola static void writeSymbolLine(raw_fd_ostream &OS, int Width, uint64_t Address, 581ebfc59cSRafael Espindola uint64_t Size, StringRef Name) { 591ebfc59cSRafael Espindola // Pass an empty name to align the text to the correct column. 601ebfc59cSRafael Espindola writeFileLine(OS, Width, Address, Size, 0, ""); 611ebfc59cSRafael Espindola OS << ' ' << left_justify(Name, 7); 621ebfc59cSRafael Espindola } 631ebfc59cSRafael Espindola 641ebfc59cSRafael Espindola template <class ELFT> 65*db540ff0SRui Ueyama static void writeInputSection(raw_fd_ostream &OS, const InputSection<ELFT> *IS, 66*db540ff0SRui Ueyama StringRef &PrevName) { 671ebfc59cSRafael Espindola int Width = ELFT::Is64Bits ? 16 : 8; 681ebfc59cSRafael Espindola StringRef Name = IS->Name; 691ebfc59cSRafael Espindola if (Name != PrevName) { 70*db540ff0SRui Ueyama writeInSecLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), 711ebfc59cSRafael Espindola IS->Alignment, Name); 721ebfc59cSRafael Espindola OS << '\n'; 731ebfc59cSRafael Espindola PrevName = Name; 741ebfc59cSRafael Espindola } 75*db540ff0SRui Ueyama 761ebfc59cSRafael Espindola elf::ObjectFile<ELFT> *File = IS->getFile(); 771ebfc59cSRafael Espindola if (!File) 781ebfc59cSRafael Espindola return; 79*db540ff0SRui Ueyama writeFileLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), 80*db540ff0SRui Ueyama IS->Alignment, toString(File)); 811ebfc59cSRafael Espindola OS << '\n'; 82*db540ff0SRui Ueyama 83*db540ff0SRui Ueyama for (SymbolBody *Sym : File->getSymbols()) { 841ebfc59cSRafael Espindola auto *DR = dyn_cast<DefinedRegular<ELFT>>(Sym); 851ebfc59cSRafael Espindola if (!DR) 861ebfc59cSRafael Espindola continue; 871ebfc59cSRafael Espindola if (DR->Section != IS) 881ebfc59cSRafael Espindola continue; 891ebfc59cSRafael Espindola if (DR->isSection()) 901ebfc59cSRafael Espindola continue; 911ebfc59cSRafael Espindola writeSymbolLine(OS, Width, Sym->getVA<ELFT>(), Sym->getSize<ELFT>(), 921ebfc59cSRafael Espindola toString(*Sym)); 931ebfc59cSRafael Espindola OS << '\n'; 941ebfc59cSRafael Espindola } 95*db540ff0SRui Ueyama } 96*db540ff0SRui Ueyama 97*db540ff0SRui Ueyama template <class ELFT> 98*db540ff0SRui Ueyama static void writeMapFile2(int FD, 99*db540ff0SRui Ueyama ArrayRef<OutputSectionBase *> OutputSections) { 100*db540ff0SRui Ueyama raw_fd_ostream OS(FD, true); 101*db540ff0SRui Ueyama int Width = ELFT::Is64Bits ? 16 : 8; 102*db540ff0SRui Ueyama 103*db540ff0SRui Ueyama OS << left_justify("Address", Width) << ' ' << left_justify("Size", Width) 104*db540ff0SRui Ueyama << ' ' << left_justify("Align", 5) << ' ' << left_justify("Out", 7) << ' ' 105*db540ff0SRui Ueyama << left_justify("In", 7) << ' ' << left_justify("File", 7) << " Symbol\n"; 106*db540ff0SRui Ueyama 107*db540ff0SRui Ueyama for (OutputSectionBase *Sec : OutputSections) { 108*db540ff0SRui Ueyama writeOutSecLine(OS, Width, Sec->Addr, Sec->Size, Sec->Addralign, 109*db540ff0SRui Ueyama Sec->getName()); 110*db540ff0SRui Ueyama OS << '\n'; 111*db540ff0SRui Ueyama 112*db540ff0SRui Ueyama StringRef PrevName = ""; 113*db540ff0SRui Ueyama Sec->forEachInputSection([&](InputSectionData *S) { 114*db540ff0SRui Ueyama if (const auto *IS = dyn_cast<InputSection<ELFT>>(S)) 115*db540ff0SRui Ueyama writeInputSection(OS, IS, PrevName); 1161ebfc59cSRafael Espindola }); 1171ebfc59cSRafael Espindola } 1181ebfc59cSRafael Espindola } 1191ebfc59cSRafael Espindola 1201ebfc59cSRafael Espindola template <class ELFT> 1211ebfc59cSRafael Espindola void elf::writeMapFile(ArrayRef<OutputSectionBase *> OutputSections) { 1221ebfc59cSRafael Espindola StringRef MapFile = Config->MapFile; 1231ebfc59cSRafael Espindola if (MapFile.empty()) 1241ebfc59cSRafael Espindola return; 1251ebfc59cSRafael Espindola 1261ebfc59cSRafael Espindola // Create new file in same directory but with random name. 1271ebfc59cSRafael Espindola SmallString<128> TempPath; 1281ebfc59cSRafael Espindola int FD; 1291ebfc59cSRafael Espindola std::error_code EC = 1301ebfc59cSRafael Espindola sys::fs::createUniqueFile(Twine(MapFile) + ".tmp%%%%%%%", FD, TempPath); 1311ebfc59cSRafael Espindola if (EC) 1321ebfc59cSRafael Espindola fatal(EC.message()); 1331ebfc59cSRafael Espindola FileRemover RAII(TempPath); 1341ebfc59cSRafael Espindola writeMapFile2<ELFT>(FD, OutputSections); 1351ebfc59cSRafael Espindola EC = sys::fs::rename(TempPath, MapFile); 1361ebfc59cSRafael Espindola if (EC) 1371ebfc59cSRafael Espindola fatal(EC.message()); 1381ebfc59cSRafael Espindola } 1391ebfc59cSRafael Espindola 1401ebfc59cSRafael Espindola template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionBase *>); 1411ebfc59cSRafael Espindola template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionBase *>); 1421ebfc59cSRafael Espindola template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionBase *>); 1431ebfc59cSRafael Espindola template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionBase *>); 144