xref: /llvm-project-15.0.7/lld/ELF/MapFile.cpp (revision db540ff0)
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