forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			134 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			134 lines
		
	
	
		
			4.5 KiB
		
	
	
	
		
			C++
		
	
	
	
//===- MapFile.cpp --------------------------------------------------------===//
 | 
						|
//
 | 
						|
//                             The LLVM Linker
 | 
						|
//
 | 
						|
// This file is distributed under the University of Illinois Open Source
 | 
						|
// License. See LICENSE.TXT for details.
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
//
 | 
						|
// This file implements the -Map option. It shows lists in order and
 | 
						|
// hierarchically the output sections, input sections, input files and
 | 
						|
// symbol:
 | 
						|
//
 | 
						|
// Address  Size     Align Out     In      File    Symbol
 | 
						|
// =================================================================
 | 
						|
// 00201000 00000015     4 .text
 | 
						|
// 00201000 0000000e     4         .text
 | 
						|
// 00201000 0000000e     4                 test.o
 | 
						|
// 0020100e 00000000     0                         local
 | 
						|
// 00201005 00000000     0                         f(int)
 | 
						|
//
 | 
						|
//===----------------------------------------------------------------------===//
 | 
						|
 | 
						|
#include "MapFile.h"
 | 
						|
#include "InputFiles.h"
 | 
						|
#include "Strings.h"
 | 
						|
 | 
						|
#include "llvm/Support/raw_ostream.h"
 | 
						|
 | 
						|
using namespace llvm;
 | 
						|
using namespace llvm::object;
 | 
						|
 | 
						|
using namespace lld;
 | 
						|
using namespace lld::elf;
 | 
						|
 | 
						|
static void writeOutSecLine(raw_fd_ostream &OS, int Width, uint64_t Address,
 | 
						|
                            uint64_t Size, uint64_t Align, StringRef Name) {
 | 
						|
  OS << format("%0*llx %0*llx %5llx ", Width, Address, Width, Size, Align)
 | 
						|
     << left_justify(Name, 7);
 | 
						|
}
 | 
						|
 | 
						|
static void writeInSecLine(raw_fd_ostream &OS, int Width, uint64_t Address,
 | 
						|
                           uint64_t Size, uint64_t Align, StringRef Name) {
 | 
						|
  // Pass an empty name to align the text to the correct column.
 | 
						|
  writeOutSecLine(OS, Width, Address, Size, Align, "");
 | 
						|
  OS << ' ' << left_justify(Name, 7);
 | 
						|
}
 | 
						|
 | 
						|
static void writeFileLine(raw_fd_ostream &OS, int Width, uint64_t Address,
 | 
						|
                          uint64_t Size, uint64_t Align, StringRef Name) {
 | 
						|
  // Pass an empty name to align the text to the correct column.
 | 
						|
  writeInSecLine(OS, Width, Address, Size, Align, "");
 | 
						|
  OS << ' ' << left_justify(Name, 7);
 | 
						|
}
 | 
						|
 | 
						|
static void writeSymbolLine(raw_fd_ostream &OS, int Width, uint64_t Address,
 | 
						|
                            uint64_t Size, StringRef Name) {
 | 
						|
  // Pass an empty name to align the text to the correct column.
 | 
						|
  writeFileLine(OS, Width, Address, Size, 0, "");
 | 
						|
  OS << ' ' << left_justify(Name, 7);
 | 
						|
}
 | 
						|
 | 
						|
template <class ELFT>
 | 
						|
static void writeInputSection(raw_fd_ostream &OS, const InputSection<ELFT> *IS,
 | 
						|
                              StringRef &PrevName) {
 | 
						|
  int Width = ELFT::Is64Bits ? 16 : 8;
 | 
						|
  StringRef Name = IS->Name;
 | 
						|
  if (Name != PrevName) {
 | 
						|
    writeInSecLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(),
 | 
						|
                   IS->Alignment, Name);
 | 
						|
    OS << '\n';
 | 
						|
    PrevName = Name;
 | 
						|
  }
 | 
						|
 | 
						|
  elf::ObjectFile<ELFT> *File = IS->getFile();
 | 
						|
  if (!File)
 | 
						|
    return;
 | 
						|
  writeFileLine(OS, Width, IS->OutSec->Addr + IS->OutSecOff, IS->getSize(),
 | 
						|
                IS->Alignment, toString(File));
 | 
						|
  OS << '\n';
 | 
						|
 | 
						|
  for (SymbolBody *Sym : File->getSymbols()) {
 | 
						|
    auto *DR = dyn_cast<DefinedRegular<ELFT>>(Sym);
 | 
						|
    if (!DR)
 | 
						|
      continue;
 | 
						|
    if (DR->Section != IS)
 | 
						|
      continue;
 | 
						|
    if (DR->isSection())
 | 
						|
      continue;
 | 
						|
    writeSymbolLine(OS, Width, Sym->getVA<ELFT>(), Sym->getSize<ELFT>(),
 | 
						|
                    toString(*Sym));
 | 
						|
    OS << '\n';
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
template <class ELFT>
 | 
						|
static void writeMapFile2(raw_fd_ostream &OS,
 | 
						|
                          ArrayRef<OutputSectionBase *> OutputSections) {
 | 
						|
  int Width = ELFT::Is64Bits ? 16 : 8;
 | 
						|
 | 
						|
  OS << left_justify("Address", Width) << ' ' << left_justify("Size", Width)
 | 
						|
     << " Align Out     In      File    Symbol\n";
 | 
						|
 | 
						|
  for (OutputSectionBase *Sec : OutputSections) {
 | 
						|
    writeOutSecLine(OS, Width, Sec->Addr, Sec->Size, Sec->Addralign,
 | 
						|
                    Sec->getName());
 | 
						|
    OS << '\n';
 | 
						|
 | 
						|
    StringRef PrevName = "";
 | 
						|
    Sec->forEachInputSection([&](InputSectionData *S) {
 | 
						|
      if (const auto *IS = dyn_cast<InputSection<ELFT>>(S))
 | 
						|
        writeInputSection(OS, IS, PrevName);
 | 
						|
    });
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
template <class ELFT>
 | 
						|
void elf::writeMapFile(ArrayRef<OutputSectionBase *> OutputSections) {
 | 
						|
  if (Config->MapFile.empty())
 | 
						|
    return;
 | 
						|
 | 
						|
  std::error_code EC;
 | 
						|
  raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None);
 | 
						|
  if (EC)
 | 
						|
    error("cannot open " + Config->MapFile + ": " + EC.message());
 | 
						|
  else
 | 
						|
    writeMapFile2<ELFT>(OS, OutputSections);
 | 
						|
}
 | 
						|
 | 
						|
template void elf::writeMapFile<ELF32LE>(ArrayRef<OutputSectionBase *>);
 | 
						|
template void elf::writeMapFile<ELF32BE>(ArrayRef<OutputSectionBase *>);
 | 
						|
template void elf::writeMapFile<ELF64LE>(ArrayRef<OutputSectionBase *>);
 | 
						|
template void elf::writeMapFile<ELF64BE>(ArrayRef<OutputSectionBase *>);
 |