LLVM  13.0.0git
ObjectFileTransformer.cpp
Go to the documentation of this file.
1 //===- ObjectFileTransformer.cpp --------------------------------*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include <unordered_set>
10 
13 #include "llvm/Object/ObjectFile.h"
16 
19 
20 using namespace llvm;
21 using namespace gsym;
22 
23 constexpr uint32_t NT_GNU_BUILD_ID_TAG = 0x03;
24 
25 static std::vector<uint8_t> getUUID(const object::ObjectFile &Obj) {
26  // Extract the UUID from the object file
27  std::vector<uint8_t> UUID;
28  if (auto *MachO = dyn_cast<object::MachOObjectFile>(&Obj)) {
29  const ArrayRef<uint8_t> MachUUID = MachO->getUuid();
30  if (!MachUUID.empty())
31  UUID.assign(MachUUID.data(), MachUUID.data() + MachUUID.size());
32  } else if (isa<object::ELFObjectFileBase>(&Obj)) {
33  const StringRef GNUBuildID(".note.gnu.build-id");
34  for (const object::SectionRef &Sect : Obj.sections()) {
35  Expected<StringRef> SectNameOrErr = Sect.getName();
36  if (!SectNameOrErr) {
37  consumeError(SectNameOrErr.takeError());
38  continue;
39  }
40  StringRef SectName(*SectNameOrErr);
41  if (SectName != GNUBuildID)
42  continue;
43  StringRef BuildIDData;
44  Expected<StringRef> E = Sect.getContents();
45  if (E)
46  BuildIDData = *E;
47  else {
48  consumeError(E.takeError());
49  continue;
50  }
51  DataExtractor Decoder(BuildIDData, Obj.makeTriple().isLittleEndian(), 8);
52  uint64_t Offset = 0;
53  const uint32_t NameSize = Decoder.getU32(&Offset);
54  const uint32_t PayloadSize = Decoder.getU32(&Offset);
55  const uint32_t PayloadType = Decoder.getU32(&Offset);
57  if (Name == "GNU" && PayloadType == NT_GNU_BUILD_ID_TAG) {
58  Offset = alignTo(Offset, 4);
59  StringRef UUIDBytes(Decoder.getBytes(&Offset, PayloadSize));
60  if (!UUIDBytes.empty()) {
61  auto Ptr = reinterpret_cast<const uint8_t *>(UUIDBytes.data());
62  UUID.assign(Ptr, Ptr + UUIDBytes.size());
63  }
64  }
65  }
66  }
67  return UUID;
68 }
69 
71  raw_ostream &Log,
72  GsymCreator &Gsym) {
73  using namespace llvm::object;
74 
75  const bool IsMachO = isa<MachOObjectFile>(&Obj);
76  const bool IsELF = isa<ELFObjectFileBase>(&Obj);
77 
78  // Read build ID.
79  Gsym.setUUID(getUUID(Obj));
80 
81  // Parse the symbol table.
82  size_t NumBefore = Gsym.getNumFunctionInfos();
83  for (const object::SymbolRef &Sym : Obj.symbols()) {
84  Expected<SymbolRef::Type> SymType = Sym.getType();
85  if (!SymType) {
86  consumeError(SymType.takeError());
87  continue;
88  }
89  Expected<uint64_t> AddrOrErr = Sym.getValue();
90  if (!AddrOrErr)
91  // TODO: Test this error.
92  return AddrOrErr.takeError();
93 
94  if (SymType.get() != SymbolRef::Type::ST_Function ||
95  !Gsym.IsValidTextAddress(*AddrOrErr) ||
96  Gsym.hasFunctionInfoForAddress(*AddrOrErr))
97  continue;
98  // Function size for MachO files will be 0
99  constexpr bool NoCopy = false;
100  const uint64_t size = IsELF ? ELFSymbolRef(Sym).getSize() : 0;
101  Expected<StringRef> Name = Sym.getName();
102  if (!Name) {
103  logAllUnhandledErrors(Name.takeError(), Log, "ObjectFileTransformer: ");
104  continue;
105  }
106  // Remove the leading '_' character in any symbol names if there is one
107  // for mach-o files.
108  if (IsMachO)
109  Name->consume_front("_");
110  Gsym.addFunctionInfo(
111  FunctionInfo(*AddrOrErr, size, Gsym.insertString(*Name, NoCopy)));
112  }
113  size_t FunctionsAddedCount = Gsym.getNumFunctionInfos() - NumBefore;
114  Log << "Loaded " << FunctionsAddedCount << " functions from symbol table.\n";
115  return Error::success();
116 }
llvm::alignTo
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:158
llvm
This class represents lattice values for constants.
Definition: AllocatorList.h:23
llvm::StringRef::empty
LLVM_NODISCARD bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:156
llvm::gsym::GsymCreator
GsymCreator is used to emit GSYM data to a stand alone file or section within a file.
Definition: GsymCreator.h:134
llvm::COFF::NameSize
@ NameSize
Definition: COFF.h:58
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
ObjectFileTransformer.h
NT_GNU_BUILD_ID_TAG
constexpr uint32_t NT_GNU_BUILD_ID_TAG
Definition: ObjectFileTransformer.cpp:23
llvm::gsym::GsymCreator::IsValidTextAddress
bool IsValidTextAddress(uint64_t Addr) const
Check if an address is a valid code address.
Definition: GsymCreator.cpp:311
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
llvm::consumeError
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1006
llvm::ArrayRef::empty
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:158
llvm::ArrayRef::data
const T * data() const
Definition: ArrayRef.h:160
llvm::object::ObjectFile::symbols
symbol_iterator_range symbols() const
Definition: ObjectFile.h:311
llvm::object::ELFSymbolRef::getSize
uint64_t getSize() const
Definition: ELFObjectFile.h:149
llvm::Triple::isLittleEndian
bool isLittleEndian() const
Tests whether the target triple is little endian.
Definition: Triple.cpp:1562
llvm::DataExtractor::getBytes
StringRef getBytes(uint64_t *OffsetPtr, uint64_t Length, Error *Err=nullptr) const
Extract a fixed number of bytes from the specified offset.
Definition: DataExtractor.cpp:181
llvm::object
Definition: ObjectFileTransformer.h:18
llvm::DataExtractor::getFixedLengthString
StringRef getFixedLengthString(uint64_t *OffsetPtr, uint64_t Length, StringRef TrimChars={"\0", 1}) const
Extract a fixed length string from *OffsetPtr and consume Length bytes.
Definition: DataExtractor.cpp:174
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
MachOUniversal.h
llvm::gsym::GsymCreator::hasFunctionInfoForAddress
bool hasFunctionInfoForAddress(uint64_t Addr) const
Check if an address has already been added as a function info.
Definition: GsymCreator.cpp:317
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:50
llvm::gsym::FunctionInfo
Function information in GSYM files encodes information for one contiguous address range.
Definition: FunctionInfo.h:89
llvm::object::SectionRef
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:80
llvm::object::ELFSymbolRef
Definition: ELFObjectFile.h:139
getUUID
static std::vector< uint8_t > getUUID(const object::ObjectFile &Obj)
Definition: ObjectFileTransformer.cpp:25
ObjectFile.h
UUID
std::pair< llvm::MachO::Target, std::string > UUID
Definition: TextStubCommon.h:23
llvm::object::ObjectFile::makeTriple
Triple makeTriple() const
Create a triple from the data in this object file.
Definition: ObjectFile.cpp:106
llvm::size
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
Definition: STLExtras.h:1479
llvm::DataExtractor::getU32
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
Definition: DataExtractor.cpp:108
llvm::gsym::GsymCreator::getNumFunctionInfos
size_t getNumFunctionInfos() const
Get the current number of FunctionInfo objects contained in this object.
Definition: GsymCreator.cpp:306
llvm::ArrayRef< uint8_t >
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
llvm::object::ObjectFile
This class is the base class for all object file types.
Definition: ObjectFile.h:225
llvm::gsym::GsymCreator::addFunctionInfo
void addFunctionInfo(FunctionInfo &&FI)
Add a function info to this GSYM creator.
Definition: GsymCreator.cpp:282
llvm::Expected::get
reference get()
Returns a reference to the stored T value.
Definition: Error.h:537
uint32_t
llvm::gsym::GsymCreator::insertString
uint32_t insertString(StringRef S, bool Copy=true)
Insert a string into the GSYM string table.
Definition: GsymCreator.cpp:264
ELFObjectFile.h
llvm::logAllUnhandledErrors
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition: Error.cpp:61
llvm::GraphProgram::Name
Name
Definition: GraphWriter.h:52
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
DataExtractor.h
llvm::gsym::ObjectFileTransformer::convert
static llvm::Error convert(const object::ObjectFile &Obj, raw_ostream &Log, GsymCreator &Gsym)
Extract any object file data that is needed by the GsymCreator.
Definition: ObjectFileTransformer.cpp:70
llvm::Expected::takeError
Error takeError()
Take ownership of the stored error.
Definition: Error.h:557
llvm::DataExtractor
Definition: DataExtractor.h:41
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
llvm::object::ObjectFile::sections
section_iterator_range sections() const
Definition: ObjectFile.h:319
llvm::StringRef::data
const LLVM_NODISCARD char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:152
llvm::object::SymbolRef
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: ObjectFile.h:164
raw_ostream.h
llvm::StringRef::size
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:160
GsymCreator.h
llvm::gsym::GsymCreator::setUUID
void setUUID(llvm::ArrayRef< uint8_t > UUIDBytes)
Set the UUID value.
Definition: GsymCreator.h:214