diff --git a/llvm/include/llvm/Object/SymbolSize.h b/llvm/include/llvm/Object/SymbolSize.h new file mode 100644 index 000000000000..4d95ec15e8c9 --- /dev/null +++ b/llvm/include/llvm/Object/SymbolSize.h @@ -0,0 +1,26 @@ +//===- SymbolSize.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Declares the writeArchive function for writing an archive file. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_SYMBOLSIZE_H +#define LLVM_OBJECT_SYMBOLSIZE_H + +#include "llvm/Object/ObjectFile.h" + +namespace llvm { +namespace object { +ErrorOr>> +computeSymbolSizes(const ObjectFile &O); +} +} // namespace llvm + +#endif diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt index 232fc42ab282..06e5b66a6cae 100644 --- a/llvm/lib/Object/CMakeLists.txt +++ b/llvm/lib/Object/CMakeLists.txt @@ -16,6 +16,7 @@ add_llvm_library(LLVMObject ObjectFile.cpp RecordStreamer.cpp SymbolicFile.cpp + SymbolSize.cpp ADDITIONAL_HEADER_DIRS ${LLVM_MAIN_INCLUDE_DIR}/llvm/Object diff --git a/llvm/lib/Object/SymbolSize.cpp b/llvm/lib/Object/SymbolSize.cpp new file mode 100644 index 000000000000..d133266e713b --- /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>> +llvm::object::computeSymbolSizes(const ObjectFile &O) { + std::vector> Ret; + + if (isa(&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 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; +} diff --git a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp index f857b2ef9735..5bc18d3bfbec 100644 --- a/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp +++ b/llvm/tools/llvm-rtdyld/llvm-rtdyld.cpp @@ -25,6 +25,7 @@ #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Object/MachO.h" +#include "llvm/Object/SymbolSize.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DynamicLibrary.h" #include "llvm/Support/ManagedStatic.h" @@ -252,38 +253,14 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) { std::unique_ptr Context( new DWARFContextInMemory(*SymbolObj,LoadedObjInfo.get())); - // FIXME: This is generally useful. Figure out a place in lib/Object to - // put utility functions. - std::map> FuncAddresses; - if (!isa(SymbolObj)) { - for (object::SymbolRef Sym : SymbolObj->symbols()) { - object::SymbolRef::Type SymType; - if (Sym.getType(SymType)) - continue; - if (SymType != object::SymbolRef::ST_Function) - continue; - uint64_t Addr; - if (Sym.getAddress(Addr)) - continue; - object::section_iterator Sec = SymbolObj->section_end(); - if (Sym.getSection(Sec)) - continue; - std::vector &Addrs = FuncAddresses[*Sec]; - if (Addrs.empty()) { - uint64_t SecAddr = Sec->getAddress(); - uint64_t SecSize = Sec->getSize(); - Addrs.push_back(SecAddr + SecSize); - } - Addrs.push_back(Addr); - } - for (auto &Pair : FuncAddresses) { - std::vector &Addrs = Pair.second; - array_pod_sort(Addrs.begin(), Addrs.end()); - } - } + ErrorOr>> SymAddrOrErr = + object::computeSymbolSizes(*SymbolObj); + if (std::error_code EC = SymAddrOrErr.getError()) + return Error(EC.message()); // Use symbol info to iterate functions in the object. - for (object::SymbolRef Sym : SymbolObj->symbols()) { + for (const auto &P : *SymAddrOrErr) { + object::SymbolRef Sym = P.first; object::SymbolRef::Type SymType; if (Sym.getType(SymType)) continue; @@ -295,20 +272,7 @@ static int printLineInfoForInput(bool LoadObjects, bool UseDebugObj) { if (Sym.getAddress(Addr)) continue; - uint64_t Size; - if (isa(SymbolObj)) { - Size = Sym.getSize(); - } else { - object::section_iterator Sec = SymbolObj->section_end(); - if (Sym.getSection(Sec)) - continue; - const std::vector &Addrs = FuncAddresses[*Sec]; - auto AddrI = std::find(Addrs.begin(), Addrs.end(), Addr); - assert(AddrI != Addrs.end() && (AddrI + 1) != Addrs.end()); - assert(*AddrI == Addr); - Size = *(AddrI + 1) - Addr; - } - + uint64_t Size = P.second; // If we're not using the debug object, compute the address of the // symbol in memory (rather than that in the unrelocated object file) // and use that to query the DWARFContext.