Use Symbol::getValue to simplify object::computeSymbolSizes. NFC.
[oota-llvm.git] / lib / Object / SymbolSize.cpp
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 }