SymbolSize.cpp revision 314564
1139826Simp//===- SymbolSize.cpp -----------------------------------------------------===// 253541Sshin// 353541Sshin// The LLVM Compiler Infrastructure 453541Sshin// 553541Sshin// This file is distributed under the University of Illinois Open Source 653541Sshin// License. See LICENSE.TXT for details. 753541Sshin// 853541Sshin//===----------------------------------------------------------------------===// 953541Sshin 1053541Sshin#include "llvm/Object/SymbolSize.h" 1153541Sshin#include "llvm/ADT/STLExtras.h" 1253541Sshin#include "llvm/Object/COFF.h" 1353541Sshin#include "llvm/Object/ELFObjectFile.h" 1453541Sshin#include "llvm/Object/MachO.h" 1553541Sshin 1653541Sshinusing namespace llvm; 1753541Sshinusing namespace object; 1853541Sshin 1953541Sshin// Orders increasingly by (SectionID, Address). 2053541Sshinint llvm::object::compareAddress(const SymEntry *A, const SymEntry *B) { 2153541Sshin if (A->SectionID != B->SectionID) 2253541Sshin return A->SectionID < B->SectionID ? -1 : 1; 2353541Sshin if (A->Address != B->Address) 2453541Sshin return A->Address < B->Address ? -1 : 1; 2553541Sshin return 0; 2653541Sshin} 2753541Sshin 28174510Sobrienstatic unsigned getSectionID(const ObjectFile &O, SectionRef Sec) { 29174510Sobrien if (auto *M = dyn_cast<MachOObjectFile>(&O)) 3053541Sshin return M->getSectionID(Sec); 3153541Sshin return cast<COFFObjectFile>(O).getSectionID(Sec); 32174510Sobrien} 33174510Sobrien 34174510Sobrienstatic unsigned getSymbolSectionID(const ObjectFile &O, SymbolRef Sym) { 3562587Sitojun if (auto *M = dyn_cast<MachOObjectFile>(&O)) 3662587Sitojun return M->getSymbolSectionID(Sym); 37225044Sbz return cast<COFFObjectFile>(O).getSymbolSectionID(Sym); 3855009Sshin} 39148921Ssuz 4053541Sshinstd::vector<std::pair<SymbolRef, uint64_t>> 4153541Sshinllvm::object::computeSymbolSizes(const ObjectFile &O) { 4253541Sshin std::vector<std::pair<SymbolRef, uint64_t>> Ret; 4378064Sume 4453541Sshin if (const auto *E = dyn_cast<ELFObjectFileBase>(&O)) { 4553541Sshin auto Syms = E->symbols(); 4653541Sshin if (Syms.begin() == Syms.end()) 4753541Sshin Syms = E->getDynamicSymbolIterators(); 4853541Sshin for (ELFSymbolRef Sym : Syms) 4953541Sshin Ret.push_back({Sym, Sym.getSize()}); 5078064Sume return Ret; 5153541Sshin } 5253541Sshin 5353541Sshin // Collect sorted symbol addresses. Include dummy addresses for the end 54225044Sbz // of each section. 5553541Sshin std::vector<SymEntry> Addresses; 5684994Sdarrenr unsigned SymNum = 0; 5753541Sshin for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) { 5853541Sshin SymbolRef Sym = *I; 5953541Sshin uint64_t Value = Sym.getValue(); 6078064Sume Addresses.push_back({I, Value, SymNum, getSymbolSectionID(O, Sym)}); 6178064Sume ++SymNum; 6262587Sitojun } 6378064Sume for (SectionRef Sec : O.sections()) { 6462587Sitojun uint64_t Address = Sec.getAddress(); 6553541Sshin uint64_t Size = Sec.getSize(); 66148385Sume Addresses.push_back( 6762587Sitojun {O.symbol_end(), Address + Size, 0, getSectionID(O, Sec)}); 6853541Sshin } 6953541Sshin array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress); 7078064Sume 7178064Sume // Compute the size as the gap to the next symbol 72171167Sgnn for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) { 73105199Ssam auto &P = Addresses[I]; 74105199Ssam if (P.I == O.symbol_end()) 75105199Ssam continue; 76171167Sgnn 77105199Ssam // If multiple symbol have the same address, give both the same size. 7884994Sdarrenr unsigned NextI = I + 1; 7984994Sdarrenr while (NextI < N && Addresses[NextI].Address == P.Address) 8053541Sshin ++NextI; 8153541Sshin 8253541Sshin uint64_t Size = Addresses[NextI].Address - P.Address; 8353541Sshin P.Address = Size; 8453541Sshin } 8553541Sshin 8653541Sshin // Assign the sorted symbols in the original order. 8753541Sshin Ret.resize(SymNum); 8853541Sshin for (SymEntry &P : Addresses) { 8953541Sshin if (P.I == O.symbol_end()) 9053541Sshin continue; 9153541Sshin Ret[P.Number] = {*P.I, P.Address}; 9253541Sshin } 93171259Sdelphij return Ret; 9453541Sshin} 9553541Sshin