xref: /llvm-project-15.0.7/lld/ELF/MapFile.cpp (revision 774ea7d0)
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) {
38eb1ad400SRui Ueyama   OS << format("%0*llx %0*llx %5lld ", 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>
64*774ea7d0SRafael Espindola static void writeInputSection(raw_fd_ostream &OS, const InputSection *IS,
65db540ff0SRui Ueyama                               StringRef &PrevName) {
661ebfc59cSRafael Espindola   int Width = ELFT::Is64Bits ? 16 : 8;
671ebfc59cSRafael Espindola   StringRef Name = IS->Name;
681ebfc59cSRafael Espindola   if (Name != PrevName) {
69b4c9b81aSRafael Espindola     writeInSecLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff,
70b4c9b81aSRafael Espindola                    IS->template getSize<ELFT>(), IS->Alignment, Name);
711ebfc59cSRafael Espindola     OS << '\n';
721ebfc59cSRafael Espindola     PrevName = Name;
731ebfc59cSRafael Espindola   }
74db540ff0SRui Ueyama 
75b4c9b81aSRafael Espindola   elf::ObjectFile<ELFT> *File = IS->template getFile<ELFT>();
761ebfc59cSRafael Espindola   if (!File)
771ebfc59cSRafael Espindola     return;
78b4c9b81aSRafael Espindola   writeFileLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff,
79b4c9b81aSRafael Espindola                 IS->template getSize<ELFT>(), 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)
102483ffa33SRui 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 = "";
110c404d50dSRafael Espindola     Sec->forEachInputSection([&](InputSectionBase *S) {
111*774ea7d0SRafael Espindola       if (const auto *IS = dyn_cast<InputSection>(S))
112*774ea7d0SRafael Espindola         writeInputSection<ELFT>(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)
125c9807c33SRui Ueyama     error("cannot open " + Config->MapFile + ": " + EC.message());
126c9807c33SRui Ueyama   else
127543731f9SRui Ueyama     writeMapFile2<ELFT>(OS, OutputSections);
1281ebfc59cSRafael Espindola }
1291ebfc59cSRafael Espindola 
1301ebfc59cSRafael Espindola template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionBase *>);
1311ebfc59cSRafael Espindola template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionBase *>);
1321ebfc59cSRafael Espindola template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionBase *>);
1331ebfc59cSRafael Espindola template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionBase *>);
134