SymbolSize.cpp revision 314564
1139826Simp//===- SymbolSize.cpp -----------------------------------------------------===//
253541Sshin//
353541Sshin//                     The LLVM Compiler Infrastructure
453541Sshin//
553541Sshin// This file is distributed under the University of Illinois Open Source
653541Sshin// License. See LICENSE.TXT for details.
753541Sshin//
853541Sshin//===----------------------------------------------------------------------===//
953541Sshin
1053541Sshin#include "llvm/Object/SymbolSize.h"
1153541Sshin#include "llvm/ADT/STLExtras.h"
1253541Sshin#include "llvm/Object/COFF.h"
1353541Sshin#include "llvm/Object/ELFObjectFile.h"
1453541Sshin#include "llvm/Object/MachO.h"
1553541Sshin
1653541Sshinusing namespace llvm;
1753541Sshinusing namespace object;
1853541Sshin
1953541Sshin// Orders increasingly by (SectionID, Address).
2053541Sshinint llvm::object::compareAddress(const SymEntry *A, const SymEntry *B) {
2153541Sshin  if (A->SectionID != B->SectionID)
2253541Sshin    return A->SectionID < B->SectionID ? -1 : 1;
2353541Sshin  if (A->Address != B->Address)
2453541Sshin    return A->Address < B->Address ? -1 : 1;
2553541Sshin  return 0;
2653541Sshin}
2753541Sshin
28174510Sobrienstatic unsigned getSectionID(const ObjectFile &O, SectionRef Sec) {
29174510Sobrien  if (auto *M = dyn_cast<MachOObjectFile>(&O))
3053541Sshin    return M->getSectionID(Sec);
3153541Sshin  return cast<COFFObjectFile>(O).getSectionID(Sec);
32174510Sobrien}
33174510Sobrien
34174510Sobrienstatic unsigned getSymbolSectionID(const ObjectFile &O, SymbolRef Sym) {
3562587Sitojun  if (auto *M = dyn_cast<MachOObjectFile>(&O))
3662587Sitojun    return M->getSymbolSectionID(Sym);
37225044Sbz  return cast<COFFObjectFile>(O).getSymbolSectionID(Sym);
3855009Sshin}
39148921Ssuz
4053541Sshinstd::vector<std::pair<SymbolRef, uint64_t>>
4153541Sshinllvm::object::computeSymbolSizes(const ObjectFile &O) {
4253541Sshin  std::vector<std::pair<SymbolRef, uint64_t>> Ret;
4378064Sume
4453541Sshin  if (const auto *E = dyn_cast<ELFObjectFileBase>(&O)) {
4553541Sshin    auto Syms = E->symbols();
4653541Sshin    if (Syms.begin() == Syms.end())
4753541Sshin      Syms = E->getDynamicSymbolIterators();
4853541Sshin    for (ELFSymbolRef Sym : Syms)
4953541Sshin      Ret.push_back({Sym, Sym.getSize()});
5078064Sume    return Ret;
5153541Sshin  }
5253541Sshin
5353541Sshin  // Collect sorted symbol addresses. Include dummy addresses for the end
54225044Sbz  // of each section.
5553541Sshin  std::vector<SymEntry> Addresses;
5684994Sdarrenr  unsigned SymNum = 0;
5753541Sshin  for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) {
5853541Sshin    SymbolRef Sym = *I;
5953541Sshin    uint64_t Value = Sym.getValue();
6078064Sume    Addresses.push_back({I, Value, SymNum, getSymbolSectionID(O, Sym)});
6178064Sume    ++SymNum;
6262587Sitojun  }
6378064Sume  for (SectionRef Sec : O.sections()) {
6462587Sitojun    uint64_t Address = Sec.getAddress();
6553541Sshin    uint64_t Size = Sec.getSize();
66148385Sume    Addresses.push_back(
6762587Sitojun        {O.symbol_end(), Address + Size, 0, getSectionID(O, Sec)});
6853541Sshin  }
6953541Sshin  array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress);
7078064Sume
7178064Sume  // Compute the size as the gap to the next symbol
72171167Sgnn  for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) {
73105199Ssam    auto &P = Addresses[I];
74105199Ssam    if (P.I == O.symbol_end())
75105199Ssam      continue;
76171167Sgnn
77105199Ssam    // If multiple symbol have the same address, give both the same size.
7884994Sdarrenr    unsigned NextI = I + 1;
7984994Sdarrenr    while (NextI < N && Addresses[NextI].Address == P.Address)
8053541Sshin      ++NextI;
8153541Sshin
8253541Sshin    uint64_t Size = Addresses[NextI].Address - P.Address;
8353541Sshin    P.Address = Size;
8453541Sshin  }
8553541Sshin
8653541Sshin  // Assign the sorted symbols in the original order.
8753541Sshin  Ret.resize(SymNum);
8853541Sshin  for (SymEntry &P : Addresses) {
8953541Sshin    if (P.I == O.symbol_end())
9053541Sshin      continue;
9153541Sshin    Ret[P.Number] = {*P.I, P.Address};
9253541Sshin  }
93171259Sdelphij  return Ret;
9453541Sshin}
9553541Sshin