summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Object/SymbolSize.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2015-06-23 02:08:48 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2015-06-23 02:08:48 +0000
commitb109c032bd44068e1fd8275117513bba172a9886 (patch)
tree3c7bc93c06c4956b493db8f2b9ed1fc28b7abd12 /llvm/lib/Object/SymbolSize.cpp
parent0b554ed364981a0b5172a0202ee183ef6fc5ae85 (diff)
downloadbcm5719-llvm-b109c032bd44068e1fd8275117513bba172a9886.tar.gz
bcm5719-llvm-b109c032bd44068e1fd8275117513bba172a9886.zip
Extract an utility for computing symbol sizes on MachO and COFF.
I will add a second user in the next commit. llvm-svn: 240366
Diffstat (limited to 'llvm/lib/Object/SymbolSize.cpp')
-rw-r--r--llvm/lib/Object/SymbolSize.cpp88
1 files changed, 88 insertions, 0 deletions
diff --git a/llvm/lib/Object/SymbolSize.cpp b/llvm/lib/Object/SymbolSize.cpp
new file mode 100644
index 00000000000..d133266e713
--- /dev/null
+++ b/llvm/lib/Object/SymbolSize.cpp
@@ -0,0 +1,88 @@
+//===- SymbolSize.cpp -----------------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/SymbolSize.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/ELFObjectFile.h"
+
+using namespace llvm;
+using namespace object;
+
+namespace {
+struct SymEntry {
+ symbol_iterator I;
+ uint64_t Address;
+ unsigned Number;
+ SectionRef Section;
+};
+}
+
+static int compareAddress(const SymEntry *A, const SymEntry *B) {
+ if (A->Section == B->Section)
+ return A->Address - B->Address;
+ if (A->Section < B->Section)
+ return -1;
+ return 1;
+}
+
+static int compareNumber(const SymEntry *A, const SymEntry *B) {
+ return A->Number - B->Number;
+}
+
+ErrorOr<std::vector<std::pair<SymbolRef, uint64_t>>>
+llvm::object::computeSymbolSizes(const ObjectFile &O) {
+ std::vector<std::pair<SymbolRef, uint64_t>> Ret;
+
+ if (isa<ELFObjectFileBase>(&O)) {
+ for (SymbolRef Sym : O.symbols()) {
+ Ret.push_back({Sym, Sym.getSize()});
+ }
+ return Ret;
+ }
+
+ // Collect sorted symbol addresses. Include dummy addresses for the end
+ // of each section.
+ std::vector<SymEntry> Addresses;
+ unsigned SymNum = 0;
+ for (symbol_iterator I = O.symbol_begin(), E = O.symbol_end(); I != E; ++I) {
+ SymbolRef Sym = *I;
+ uint64_t Address;
+ if (std::error_code EC = Sym.getAddress(Address))
+ return EC;
+ section_iterator SecI = O.section_end();
+ if (std::error_code EC = Sym.getSection(SecI))
+ return EC;
+ Addresses.push_back({I, Address, SymNum, *SecI});
+ ++SymNum;
+ }
+ for (const SectionRef Sec : O.sections()) {
+ uint64_t Address = Sec.getAddress();
+ uint64_t Size = Sec.getSize();
+ Addresses.push_back({O.symbol_end(), Address + Size, 0, Sec});
+ }
+ array_pod_sort(Addresses.begin(), Addresses.end(), compareAddress);
+
+ // Compute the size as the gap to the next symbol
+ for (unsigned I = 0, N = Addresses.size() - 1; I < N; ++I) {
+ auto &P = Addresses[I];
+ if (P.I == O.symbol_end())
+ continue;
+ uint64_t Size = Addresses[I + 1].Address - P.Address;
+ P.Address = Size;
+ }
+
+ // Put back in the original order and copy the result
+ array_pod_sort(Addresses.begin(), Addresses.end(), compareNumber);
+ for (SymEntry &P : Addresses) {
+ if (P.I == O.symbol_end())
+ continue;
+ Ret.push_back({*P.I, P.Address});
+ }
+ return Ret;
+}
OpenPOWER on IntegriCloud