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 Value = Sym.getValue(); 57 section_iterator SecI = O.section_end(); 58 if (std::error_code EC = Sym.getSection(SecI)) 59 return EC; 60 Addresses.push_back({I, Value, SymNum, *SecI}); 61 ++SymNum; 62 } 63 for (const SectionRef Sec : O.sections()) { 64 uint64_t Address = Sec.getAddress(); 65 uint64_t Size = Sec.getSize(); 66 Addresses.push_back({O.symbol_end(), Address + Size, 0, Sec}); 67 } 68 array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress); 69 70 // Compute the size as the gap to the next symbol 71 for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) { 72 auto &P = Addresses[I]; 73 if (P.I == O.symbol_end()) 74 continue; 75 76 // If multiple symbol have the same address, give both the same size. 77 unsigned NextI = I + 1; 78 while (NextI < N && Addresses[NextI].Address == P.Address) 79 ++NextI; 80 81 uint64_t Size = Addresses[NextI].Address - P.Address; 82 P.Address = Size; 83 } 84 85 // Put back in the original order and copy the result 86 array_pod_sort(Addresses.begin(), Addresses.end(), compareNumber); 87 for (SymEntry &P : Addresses) { 88 if (P.I == O.symbol_end()) 89 continue; 90 Ret.push_back({*P.I, P.Address}); 91 } 92 return Ret; 93 } 94