1285163Sdim//===- SymbolSize.cpp -----------------------------------------------------===// 2285163Sdim// 3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4353358Sdim// See https://llvm.org/LICENSE.txt for license information. 5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6285163Sdim// 7285163Sdim//===----------------------------------------------------------------------===// 8285163Sdim 9285163Sdim#include "llvm/Object/SymbolSize.h" 10285163Sdim#include "llvm/ADT/STLExtras.h" 11285163Sdim#include "llvm/Object/COFF.h" 12285163Sdim#include "llvm/Object/ELFObjectFile.h" 13285163Sdim#include "llvm/Object/MachO.h" 14285163Sdim 15285163Sdimusing namespace llvm; 16285163Sdimusing namespace object; 17285163Sdim 18314564Sdim// Orders increasingly by (SectionID, Address). 19314564Sdimint llvm::object::compareAddress(const SymEntry *A, const SymEntry *B) { 20285163Sdim if (A->SectionID != B->SectionID) 21314564Sdim return A->SectionID < B->SectionID ? -1 : 1; 22314564Sdim if (A->Address != B->Address) 23314564Sdim return A->Address < B->Address ? -1 : 1; 24314564Sdim return 0; 25285163Sdim} 26285163Sdim 27285163Sdimstatic unsigned getSectionID(const ObjectFile &O, SectionRef Sec) { 28285163Sdim if (auto *M = dyn_cast<MachOObjectFile>(&O)) 29285163Sdim return M->getSectionID(Sec); 30285163Sdim return cast<COFFObjectFile>(O).getSectionID(Sec); 31285163Sdim} 32285163Sdim 33285163Sdimstatic unsigned getSymbolSectionID(const ObjectFile &O, SymbolRef Sym) { 34285163Sdim if (auto *M = dyn_cast<MachOObjectFile>(&O)) 35285163Sdim return M->getSymbolSectionID(Sym); 36285163Sdim return cast<COFFObjectFile>(O).getSymbolSectionID(Sym); 37285163Sdim} 38285163Sdim 39285163Sdimstd::vector<std::pair<SymbolRef, uint64_t>> 40285163Sdimllvm::object::computeSymbolSizes(const ObjectFile &O) { 41285163Sdim std::vector<std::pair<SymbolRef, uint64_t>> Ret; 42285163Sdim 43285163Sdim if (const auto *E = dyn_cast<ELFObjectFileBase>(&O)) { 44285163Sdim auto Syms = E->symbols(); 45285163Sdim if (Syms.begin() == Syms.end()) 46285163Sdim Syms = E->getDynamicSymbolIterators(); 47285163Sdim for (ELFSymbolRef Sym : Syms) 48285163Sdim Ret.push_back({Sym, Sym.getSize()}); 49285163Sdim return Ret; 50285163Sdim } 51285163Sdim 52285163Sdim // Collect sorted symbol addresses. Include dummy addresses for the end 53285163Sdim // of each section. 54285163Sdim std::vector<SymEntry> Addresses; 55285163Sdim unsigned SymNum = 0; 56285163Sdim for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) { 57285163Sdim SymbolRef Sym = *I; 58285163Sdim uint64_t Value = Sym.getValue(); 59285163Sdim Addresses.push_back({I, Value, SymNum, getSymbolSectionID(O, Sym)}); 60285163Sdim ++SymNum; 61285163Sdim } 62285163Sdim for (SectionRef Sec : O.sections()) { 63285163Sdim uint64_t Address = Sec.getAddress(); 64285163Sdim uint64_t Size = Sec.getSize(); 65285163Sdim Addresses.push_back( 66285163Sdim {O.symbol_end(), Address + Size, 0, getSectionID(O, Sec)}); 67285163Sdim } 68341825Sdim 69341825Sdim if (Addresses.empty()) 70341825Sdim return Ret; 71341825Sdim 72285163Sdim array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress); 73285163Sdim 74285163Sdim // Compute the size as the gap to the next symbol 75285163Sdim for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) { 76285163Sdim auto &P = Addresses[I]; 77285163Sdim if (P.I == O.symbol_end()) 78285163Sdim continue; 79285163Sdim 80285163Sdim // If multiple symbol have the same address, give both the same size. 81285163Sdim unsigned NextI = I + 1; 82285163Sdim while (NextI < N && Addresses[NextI].Address == P.Address) 83285163Sdim ++NextI; 84285163Sdim 85285163Sdim uint64_t Size = Addresses[NextI].Address - P.Address; 86285163Sdim P.Address = Size; 87285163Sdim } 88285163Sdim 89285163Sdim // Assign the sorted symbols in the original order. 90285163Sdim Ret.resize(SymNum); 91285163Sdim for (SymEntry &P : Addresses) { 92285163Sdim if (P.I == O.symbol_end()) 93285163Sdim continue; 94285163Sdim Ret[P.Number] = {*P.I, P.Address}; 95285163Sdim } 96285163Sdim return Ret; 97285163Sdim} 98