Path: blob/main/contrib/llvm-project/llvm/lib/Object/SymbolSize.cpp
35232 views
//===- SymbolSize.cpp -----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "llvm/Object/SymbolSize.h"9#include "llvm/ADT/STLExtras.h"10#include "llvm/Object/COFF.h"11#include "llvm/Object/ELFObjectFile.h"12#include "llvm/Object/MachO.h"13#include "llvm/Object/Wasm.h"14#include "llvm/Object/XCOFFObjectFile.h"1516using namespace llvm;17using namespace object;1819// Orders increasingly by (SectionID, Address).20int llvm::object::compareAddress(const SymEntry *A, const SymEntry *B) {21if (A->SectionID != B->SectionID)22return A->SectionID < B->SectionID ? -1 : 1;23if (A->Address != B->Address)24return A->Address < B->Address ? -1 : 1;25return 0;26}2728static unsigned getSectionID(const ObjectFile &O, SectionRef Sec) {29if (auto *M = dyn_cast<MachOObjectFile>(&O))30return M->getSectionID(Sec);31if (isa<WasmObjectFile>(&O))32return Sec.getIndex();33if (isa<XCOFFObjectFile>(&O))34return Sec.getIndex();35return cast<COFFObjectFile>(O).getSectionID(Sec);36}3738static unsigned getSymbolSectionID(const ObjectFile &O, SymbolRef Sym) {39if (auto *M = dyn_cast<MachOObjectFile>(&O))40return M->getSymbolSectionID(Sym);41if (const auto *M = dyn_cast<WasmObjectFile>(&O))42return M->getSymbolSectionId(Sym);43if (const auto *M = dyn_cast<XCOFFObjectFile>(&O))44return M->getSymbolSectionID(Sym);45return cast<COFFObjectFile>(O).getSymbolSectionID(Sym);46}4748std::vector<std::pair<SymbolRef, uint64_t>>49llvm::object::computeSymbolSizes(const ObjectFile &O) {50std::vector<std::pair<SymbolRef, uint64_t>> Ret;5152if (const auto *E = dyn_cast<ELFObjectFileBase>(&O)) {53auto Syms = E->symbols();54if (Syms.empty())55Syms = E->getDynamicSymbolIterators();56for (ELFSymbolRef Sym : Syms)57Ret.push_back({Sym, Sym.getSize()});58return Ret;59}6061if (const auto *E = dyn_cast<XCOFFObjectFile>(&O)) {62for (XCOFFSymbolRef Sym : E->symbols())63Ret.push_back({Sym, Sym.getSize()});64return Ret;65}6667if (const auto *E = dyn_cast<WasmObjectFile>(&O)) {68for (SymbolRef Sym : E->symbols()) {69Ret.push_back({Sym, E->getSymbolSize(Sym)});70}71return Ret;72}7374// Collect sorted symbol addresses. Include dummy addresses for the end75// of each section.76std::vector<SymEntry> Addresses;77unsigned SymNum = 0;78for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) {79SymbolRef Sym = *I;80Expected<uint64_t> ValueOrErr = Sym.getValue();81if (!ValueOrErr)82// TODO: Actually report errors helpfully.83report_fatal_error(ValueOrErr.takeError());84Addresses.push_back({I, *ValueOrErr, SymNum, getSymbolSectionID(O, Sym)});85++SymNum;86}87for (SectionRef Sec : O.sections()) {88uint64_t Address = Sec.getAddress();89uint64_t Size = Sec.getSize();90Addresses.push_back(91{O.symbol_end(), Address + Size, 0, getSectionID(O, Sec)});92}9394if (Addresses.empty())95return Ret;9697array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress);9899// Compute the size as the gap to the next symbol. If multiple symbols have100// the same address, give both the same size. Because Addresses is sorted,101// use two pointers to keep track of the current symbol vs. the next symbol102// that doesn't have the same address for size computation.103for (unsigned I = 0, NextI = 0, N = Addresses.size() - 1; I < N; ++I) {104auto &P = Addresses[I];105if (P.I == O.symbol_end())106continue;107108// If the next pointer is behind, update it to the next symbol.109if (NextI <= I) {110NextI = I + 1;111while (NextI < N && Addresses[NextI].Address == P.Address)112++NextI;113}114115uint64_t Size = Addresses[NextI].Address - P.Address;116P.Address = Size;117}118119// Assign the sorted symbols in the original order.120Ret.resize(SymNum);121for (SymEntry &P : Addresses) {122if (P.I == O.symbol_end())123continue;124Ret[P.Number] = {*P.I, P.Address};125}126return Ret;127}128129130