LLVM 18.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
16
19
20using namespace llvm;
21using namespace gsym;
22
24
25static 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 continue;
97 // Function size for MachO files will be 0
98 constexpr bool NoCopy = false;
99 const uint64_t size = IsELF ? ELFSymbolRef(Sym).getSize() : 0;
100 Expected<StringRef> Name = Sym.getName();
101 if (!Name) {
102 if (Log)
103 logAllUnhandledErrors(Name.takeError(), *Log,
104 "ObjectFileTransformer: ");
105 else
106 consumeError(Name.takeError());
107 continue;
108 }
109 // Remove the leading '_' character in any symbol names if there is one
110 // for mach-o files.
111 if (IsMachO)
112 Name->consume_front("_");
113 Gsym.addFunctionInfo(
114 FunctionInfo(*AddrOrErr, size, Gsym.insertString(*Name, NoCopy)));
115 }
116 size_t FunctionsAddedCount = Gsym.getNumFunctionInfos() - NumBefore;
117 if (Log)
118 *Log << "Loaded " << FunctionsAddedCount
119 << " functions from symbol table.\n";
120 return Error::success();
121}
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
std::string Name
Symbol * Sym
Definition: ELF_riscv.cpp:468
static std::vector< uint8_t > getUUID(const object::ObjectFile &Obj)
constexpr uint32_t NT_GNU_BUILD_ID_TAG
std::pair< llvm::MachO::Target, std::string > UUID
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
const T * data() const
Definition: ArrayRef.h:162
StringRef getFixedLengthString(uint64_t *OffsetPtr, uint64_t Length, StringRef TrimChars={"\0", 1}) const
Extract a fixed length string from *OffsetPtr and consume Length bytes.
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
StringRef getBytes(uint64_t *OffsetPtr, uint64_t Length, Error *Err=nullptr) const
Extract a fixed number of bytes from the specified offset.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:160
static ErrorSuccess success()
Create a success value.
Definition: Error.h:334
Tagged union holding either a T or a Error.
Definition: Error.h:474
Error takeError()
Take ownership of the stored error.
Definition: Error.h:601
reference get()
Returns a reference to the stored T value.
Definition: Error.h:571
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
constexpr bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:134
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
bool isLittleEndian() const
Tests whether the target triple is little endian.
Definition: Triple.cpp:1744
GsymCreator is used to emit GSYM data to a stand alone file or section within a file.
Definition: GsymCreator.h:133
void addFunctionInfo(FunctionInfo &&FI)
Add a function info to this GSYM creator.
uint32_t insertString(StringRef S, bool Copy=true)
Insert a string into the GSYM string table.
void setUUID(llvm::ArrayRef< uint8_t > UUIDBytes)
Set the UUID value.
Definition: GsymCreator.h:369
size_t getNumFunctionInfos() const
Get the current number of FunctionInfo objects contained in this object.
bool IsValidTextAddress(uint64_t Addr) const
Check if an address is a valid code address.
static llvm::Error convert(const object::ObjectFile &Obj, raw_ostream *Log, GsymCreator &Gsym)
Extract any object file data that is needed by the GsymCreator.
uint64_t getSize() const
This class is the base class for all object file types.
Definition: ObjectFile.h:229
Triple makeTriple() const
Create a triple from the data in this object file.
Definition: ObjectFile.cpp:109
section_iterator_range sections() const
Definition: ObjectFile.h:328
symbol_iterator_range symbols() const
Definition: ObjectFile.h:320
This is a value type class that represents a single section in the list of sections in the object fil...
Definition: ObjectFile.h:81
This is a value type class that represents a single symbol in the list of symbols in the object file.
Definition: ObjectFile.h:168
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
constexpr size_t NameSize
Definition: XCOFF.h:29
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition: Error.cpp:65
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:1685
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
void consumeError(Error Err)
Consume a Error without doing anything.
Definition: Error.h:1041
Function information in GSYM files encodes information for one contiguous address range.
Definition: FunctionInfo.h:89