1 //===- SymbolSize.cpp -----------------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "llvm/Object/SymbolSize.h" 11 #include "llvm/ADT/STLExtras.h" 12 #include "llvm/Object/ELFObjectFile.h" 13 14 using namespace llvm; 15 using namespace object; 16 17 namespace { 18 struct SymEntry { 19 symbol_iterator I; 20 uint64_t Address; 21 unsigned Number; 22 SectionRef Section; 23 }; 24 } 25 26 static int compareAddress(const SymEntry *A, const SymEntry *B) { 27 if (A->Section == B->Section) 28 return A->Address - B->Address; 29 if (A->Section < B->Section) 30 return -1; 31 return 1; 32 } 33 34 static int compareNumber(const SymEntry *A, const SymEntry *B) { 35 return A->Number - B->Number; 36 } 37 38 ErrorOr<std::vector<std::pair<SymbolRef, uint64_t>>> 39 llvm::object::computeSymbolSizes(const ObjectFile &O) { 40 std::vector<std::pair<SymbolRef, uint64_t>> Ret; 41 42 if (isa<ELFObjectFileBase>(&O)) { 43 for (SymbolRef Sym : O.symbols()) { 44 Ret.push_back({Sym, Sym.getSize()}); 45 } 46 return Ret; 47 } 48 49 // Collect sorted symbol addresses. Include dummy addresses for the end 50 // of each section. 51 std::vector<SymEntry> Addresses; 52 unsigned SymNum = 0; 53 for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) { 54 SymbolRef Sym = *I; 55 uint64_t Address; 56 if (std::error_code EC = Sym.getAddress(Address)) 57 return EC; 58 section_iterator SecI = O.section_end(); 59 if (std::error_code EC = Sym.getSection(SecI)) 60 return EC; 61 Addresses.push_back({I, Address, SymNum, *SecI}); 62 ++SymNum; 63 } 64 for (const SectionRef Sec : O.sections()) { 65 uint64_t Address = Sec.getAddress(); 66 uint64_t Size = Sec.getSize(); 67 Addresses.push_back({O.symbol_end(), Address + Size, 0, Sec}); 68 } 69 array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress); 70 71 // Compute the size as the gap to the next symbol 72 for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) { 73 auto &P = Addresses[I]; 74 if (P.I == O.symbol_end()) 75 continue; 76 uint64_t Size = Addresses[I + 1].Address - P.Address; 77 P.Address = Size; 78 } 79 80 // Put back in the original order and copy the result 81 array_pod_sort(Addresses.begin(), Addresses.end(), compareNumber); 82 for (SymEntry &P : Addresses) { 83 if (P.I == O.symbol_end()) 84 continue; 85 Ret.push_back({*P.I, P.Address}); 86 } 87 return Ret; 88 } 89