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 if (A->Section == B->Section) 32 return 0; 33 return 1; 34 } 35 36 static int compareNumber(const SymEntry *A, const SymEntry *B) { 37 return A->Number - B->Number; 38 } 39 40 ErrorOr<std::vector<std::pair<SymbolRef, uint64_t>>> 41 llvm::object::computeSymbolSizes(const ObjectFile &O) { 42 std::vector<std::pair<SymbolRef, uint64_t>> Ret; 43 44 if (const auto *E = dyn_cast<ELFObjectFileBase>(&O)) { 45 for (SymbolRef Sym : E->symbols()) 46 Ret.push_back({Sym, E->getSymbolSize(Sym)}); 47 return Ret; 48 } 49 50 // Collect sorted symbol addresses. Include dummy addresses for the end 51 // of each section. 52 std::vector<SymEntry> Addresses; 53 unsigned SymNum = 0; 54 for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) { 55 SymbolRef Sym = *I; 56 uint64_t Address; 57 if (std::error_code EC = Sym.getAddress(Address)) 58 return EC; 59 section_iterator SecI = O.section_end(); 60 if (std::error_code EC = Sym.getSection(SecI)) 61 return EC; 62 Addresses.push_back({I, Address, SymNum, *SecI}); 63 ++SymNum; 64 } 65 for (const SectionRef Sec : O.sections()) { 66 uint64_t Address = Sec.getAddress(); 67 uint64_t Size = Sec.getSize(); 68 Addresses.push_back({O.symbol_end(), Address + Size, 0, Sec}); 69 } 70 array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress); 71 72 // Compute the size as the gap to the next symbol 73 for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) { 74 auto &P = Addresses[I]; 75 if (P.I == O.symbol_end()) 76 continue; 77 78 // If multiple symbol have the same address, give both the same size. 79 unsigned NextI = I + 1; 80 while (NextI < N && Addresses[NextI].Address == P.Address) 81 ++NextI; 82 83 uint64_t Size = Addresses[NextI].Address - P.Address; 84 P.Address = Size; 85 } 86 87 // Put back in the original order and copy the result 88 array_pod_sort(Addresses.begin(), Addresses.end(), compareNumber); 89 for (SymEntry &P : Addresses) { 90 if (P.I == O.symbol_end()) 91 continue; 92 Ret.push_back({*P.I, P.Address}); 93 } 94 return Ret; 95 } 96