146b69c69SDimitry Andric //===- MapFile.cpp --------------------------------------------------------===// 246b69c69SDimitry Andric // 346b69c69SDimitry Andric // The LLVM Linker 446b69c69SDimitry Andric // 546b69c69SDimitry Andric // This file is distributed under the University of Illinois Open Source 646b69c69SDimitry Andric // License. See LICENSE.TXT for details. 746b69c69SDimitry Andric // 846b69c69SDimitry Andric //===----------------------------------------------------------------------===// 946b69c69SDimitry Andric // 1046b69c69SDimitry Andric // This file implements the -Map option. It shows lists in order and 1146b69c69SDimitry Andric // hierarchically the output sections, input sections, input files and 1246b69c69SDimitry Andric // symbol: 1346b69c69SDimitry Andric // 1446b69c69SDimitry Andric // Address Size Align Out In File Symbol 1546b69c69SDimitry Andric // ================================================================= 1646b69c69SDimitry Andric // 00201000 00000015 4 .text 1746b69c69SDimitry Andric // 00201000 0000000e 4 .text 1846b69c69SDimitry Andric // 00201000 0000000e 4 test.o 1946b69c69SDimitry Andric // 0020100e 00000000 0 local 2046b69c69SDimitry Andric // 00201005 00000000 0 f(int) 2146b69c69SDimitry Andric // 2246b69c69SDimitry Andric //===----------------------------------------------------------------------===// 2346b69c69SDimitry Andric 2446b69c69SDimitry Andric #include "MapFile.h" 2546b69c69SDimitry Andric #include "InputFiles.h" 2646b69c69SDimitry Andric #include "Strings.h" 2746b69c69SDimitry Andric 2846b69c69SDimitry Andric #include "llvm/Support/raw_ostream.h" 2946b69c69SDimitry Andric 3046b69c69SDimitry Andric using namespace llvm; 3146b69c69SDimitry Andric using namespace llvm::object; 3246b69c69SDimitry Andric 3346b69c69SDimitry Andric using namespace lld; 3446b69c69SDimitry Andric using namespace lld::elf; 3546b69c69SDimitry Andric 3646b69c69SDimitry Andric static void writeOutSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, 3746b69c69SDimitry Andric uint64_t Size, uint64_t Align, StringRef Name) { 3846b69c69SDimitry Andric OS << format("%0*llx %0*llx %5lld ", Width, Address, Width, Size, Align) 3946b69c69SDimitry Andric << left_justify(Name, 7); 4046b69c69SDimitry Andric } 4146b69c69SDimitry Andric 4246b69c69SDimitry Andric static void writeInSecLine(raw_fd_ostream &OS, int Width, uint64_t Address, 4346b69c69SDimitry Andric uint64_t Size, uint64_t Align, StringRef Name) { 4446b69c69SDimitry Andric // Pass an empty name to align the text to the correct column. 4546b69c69SDimitry Andric writeOutSecLine(OS, Width, Address, Size, Align, ""); 4646b69c69SDimitry Andric OS << ' ' << left_justify(Name, 7); 4746b69c69SDimitry Andric } 4846b69c69SDimitry Andric 4946b69c69SDimitry Andric static void writeFileLine(raw_fd_ostream &OS, int Width, uint64_t Address, 5046b69c69SDimitry Andric uint64_t Size, uint64_t Align, StringRef Name) { 5146b69c69SDimitry Andric // Pass an empty name to align the text to the correct column. 5246b69c69SDimitry Andric writeInSecLine(OS, Width, Address, Size, Align, ""); 5346b69c69SDimitry Andric OS << ' ' << left_justify(Name, 7); 5446b69c69SDimitry Andric } 5546b69c69SDimitry Andric 5646b69c69SDimitry Andric static void writeSymbolLine(raw_fd_ostream &OS, int Width, uint64_t Address, 5746b69c69SDimitry Andric uint64_t Size, StringRef Name) { 5846b69c69SDimitry Andric // Pass an empty name to align the text to the correct column. 5946b69c69SDimitry Andric writeFileLine(OS, Width, Address, Size, 0, ""); 6046b69c69SDimitry Andric OS << ' ' << left_justify(Name, 7); 6146b69c69SDimitry Andric } 6246b69c69SDimitry Andric 6346b69c69SDimitry Andric template <class ELFT> 6446b69c69SDimitry Andric static void writeInputSection(raw_fd_ostream &OS, const InputSection *IS, 6546b69c69SDimitry Andric StringRef &PrevName) { 6646b69c69SDimitry Andric int Width = ELFT::Is64Bits ? 16 : 8; 6746b69c69SDimitry Andric StringRef Name = IS->Name; 6846b69c69SDimitry Andric if (Name != PrevName) { 6946b69c69SDimitry Andric writeInSecLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), 7046b69c69SDimitry Andric IS->Alignment, Name); 7146b69c69SDimitry Andric OS << '\n'; 7246b69c69SDimitry Andric PrevName = Name; 7346b69c69SDimitry Andric } 7446b69c69SDimitry Andric 7546b69c69SDimitry Andric elf::ObjectFile<ELFT> *File = IS->template getFile<ELFT>(); 7646b69c69SDimitry Andric if (!File) 7746b69c69SDimitry Andric return; 7846b69c69SDimitry Andric writeFileLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(), 7946b69c69SDimitry Andric IS->Alignment, toString(File)); 8046b69c69SDimitry Andric OS << '\n'; 8146b69c69SDimitry Andric 8246b69c69SDimitry Andric for (SymbolBody *Sym : File->getSymbols()) { 8346b69c69SDimitry Andric auto *DR = dyn_cast<DefinedRegular>(Sym); 8446b69c69SDimitry Andric if (!DR) 8546b69c69SDimitry Andric continue; 8646b69c69SDimitry Andric if (DR->Section != IS) 8746b69c69SDimitry Andric continue; 8846b69c69SDimitry Andric if (DR->isSection()) 8946b69c69SDimitry Andric continue; 9046b69c69SDimitry Andric writeSymbolLine(OS, Width, Sym->getVA(), Sym->getSize<ELFT>(), 9146b69c69SDimitry Andric toString(*Sym)); 9246b69c69SDimitry Andric OS << '\n'; 9346b69c69SDimitry Andric } 9446b69c69SDimitry Andric } 9546b69c69SDimitry Andric 9646b69c69SDimitry Andric template <class ELFT> 9746b69c69SDimitry Andric static void writeMapFile2(raw_fd_ostream &OS, 9846b69c69SDimitry Andric ArrayRef<OutputSection *> OutputSections) { 9946b69c69SDimitry Andric int Width = ELFT::Is64Bits ? 16 : 8; 10046b69c69SDimitry Andric 10146b69c69SDimitry Andric OS << left_justify("Address", Width) << ' ' << left_justify("Size", Width) 10246b69c69SDimitry Andric << " Align Out In File Symbol\n"; 10346b69c69SDimitry Andric 10446b69c69SDimitry Andric for (OutputSection *Sec : OutputSections) { 10546b69c69SDimitry Andric writeOutSecLine(OS, Width, Sec->Addr, Sec->Size, Sec->Alignment, Sec->Name); 10646b69c69SDimitry Andric OS << '\n'; 10746b69c69SDimitry Andric 10846b69c69SDimitry Andric StringRef PrevName = ""; 10946b69c69SDimitry Andric for (InputSection *IS : Sec->Sections) { 11046b69c69SDimitry Andric writeInputSection<ELFT>(OS, IS, PrevName); 11146b69c69SDimitry Andric } 11246b69c69SDimitry Andric } 11346b69c69SDimitry Andric } 11446b69c69SDimitry Andric 11546b69c69SDimitry Andric template <class ELFT> 11646b69c69SDimitry Andric void elf::writeMapFile(ArrayRef<OutputSection *> OutputSections) { 11746b69c69SDimitry Andric if (Config->MapFile.empty()) 11846b69c69SDimitry Andric return; 11946b69c69SDimitry Andric 12046b69c69SDimitry Andric std::error_code EC; 12146b69c69SDimitry Andric raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None); 12246b69c69SDimitry Andric if (EC) 12346b69c69SDimitry Andric error("cannot open " + Config->MapFile + ": " + EC.message()); 12446b69c69SDimitry Andric else 12546b69c69SDimitry Andric writeMapFile2<ELFT>(OS, OutputSections); 12646b69c69SDimitry Andric } 12746b69c69SDimitry Andric 12846b69c69SDimitry Andric template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSection *>); 12946b69c69SDimitry Andric template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSection *>); 13046b69c69SDimitry Andric template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSection *>); 13146b69c69SDimitry Andric template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSection *>); 132