LLVM: lib/TextAPI/BinaryReader/DylibReader.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
24#include
25#include
26#include
27#include
28#include
29
30using namespace llvm;
34
38 return std::forward_as_tuple(CT.getArch(), CT.getOS(),
40 std::forward_as_tuple(T.getArch(), T.getOS(), T.getEnvironment());
41 });
42
43 if (I != Container.end() && *I == T)
44 return I;
45 return Container.emplace(I, T);
46}
47
50 auto getOSVersionStr = [](uint32_t V) {
52 std::string Vers;
54 VStream << OSVersion;
55 return VStream.str();
56 };
59 return getOSVersionStr(Vers.version);
60 };
61
65
67 std::string OSVersion;
68 switch (cmd.C.cmd) {
69 case MachO::LC_VERSION_MIN_MACOSX:
70 OSVersion = getOSVersion(cmd);
71 emplace(Triples, {Arch, "apple", "macos" + OSVersion});
72 break;
73 case MachO::LC_VERSION_MIN_IPHONEOS:
74 OSVersion = getOSVersion(cmd);
75 if (IsIntel)
76 emplace(Triples, {Arch, "apple", "ios" + OSVersion, "simulator"});
77 else
78 emplace(Triples, {Arch, "apple", "ios" + OSVersion});
79 break;
80 case MachO::LC_VERSION_MIN_TVOS:
81 OSVersion = getOSVersion(cmd);
82 if (IsIntel)
83 emplace(Triples, {Arch, "apple", "tvos" + OSVersion, "simulator"});
84 else
85 emplace(Triples, {Arch, "apple", "tvos" + OSVersion});
86 break;
87 case MachO::LC_VERSION_MIN_WATCHOS:
88 OSVersion = getOSVersion(cmd);
89 if (IsIntel)
90 emplace(Triples, {Arch, "apple", "watchos" + OSVersion, "simulator"});
91 else
92 emplace(Triples, {Arch, "apple", "watchos" + OSVersion});
93 break;
94 case MachO::LC_BUILD_VERSION: {
97 case MachO::PLATFORM_MACOS:
98 emplace(Triples, {Arch, "apple", "macos" + OSVersion});
99 break;
100 case MachO::PLATFORM_IOS:
101 emplace(Triples, {Arch, "apple", "ios" + OSVersion});
102 break;
103 case MachO::PLATFORM_TVOS:
104 emplace(Triples, {Arch, "apple", "tvos" + OSVersion});
105 break;
106 case MachO::PLATFORM_WATCHOS:
107 emplace(Triples, {Arch, "apple", "watchos" + OSVersion});
108 break;
109 case MachO::PLATFORM_BRIDGEOS:
110 emplace(Triples, {Arch, "apple", "bridgeos" + OSVersion});
111 break;
112 case MachO::PLATFORM_MACCATALYST:
113 emplace(Triples, {Arch, "apple", "ios" + OSVersion, "macabi"});
114 break;
115 case MachO::PLATFORM_IOSSIMULATOR:
116 emplace(Triples, {Arch, "apple", "ios" + OSVersion, "simulator"});
117 break;
118 case MachO::PLATFORM_TVOSSIMULATOR:
119 emplace(Triples, {Arch, "apple", "tvos" + OSVersion, "simulator"});
120 break;
121 case MachO::PLATFORM_WATCHOSSIMULATOR:
122 emplace(Triples, {Arch, "apple", "watchos" + OSVersion, "simulator"});
123 break;
124 case MachO::PLATFORM_DRIVERKIT:
125 emplace(Triples, {Arch, "apple", "driverkit" + OSVersion});
126 break;
127 default:
128 break;
129 }
130 break;
131 }
132 default:
133 break;
134 }
135 }
136
137
138
139 if (Triples.empty())
140 emplace(Triples, {Arch, "apple", "unknown"});
141
142 return Triples;
143}
144
147 auto &BA = Slice.getBinaryAttrs();
148
149 switch (H.filetype) {
150 default:
153 BA.File = FileType::MachO_DynamicLibrary;
154 break;
156 BA.File = FileType::MachO_DynamicLibrary_Stub;
157 break;
159 BA.File = FileType::MachO_Bundle;
160 break;
161 }
162
164 BA.TwoLevelNamespace = true;
166 BA.AppExtensionSafe = true;
167
169 switch (LCI.C.cmd) {
170 case MachO::LC_ID_DYLIB: {
172 BA.InstallName = Slice.copyString(LCI.Ptr + DLLC.dylib.name);
173 BA.CurrentVersion = DLLC.dylib.current_version;
174 BA.CompatVersion = DLLC.dylib.compatibility_version;
175 break;
176 }
177 case MachO::LC_REEXPORT_DYLIB: {
179 BA.RexportedLibraries.emplace_back(
180 Slice.copyString(LCI.Ptr + DLLC.dylib.name));
181 break;
182 }
183 case MachO::LC_SUB_FRAMEWORK: {
185 BA.ParentUmbrella = Slice.copyString(LCI.Ptr + SFC.umbrella);
186 break;
187 }
188 case MachO::LC_SUB_CLIENT: {
190 BA.AllowableClients.emplace_back(Slice.copyString(LCI.Ptr + SCLC.client));
191 break;
192 }
193 case MachO::LC_UUID: {
195 std::stringstream Stream;
196 for (unsigned I = 0; I < 16; ++I) {
197 if (I == 4 || I == 6 || I == 8 || I == 10)
198 Stream << '-';
199 Stream << std::setfill('0') << std::setw(2) << std::uppercase
200 << std::hex << static_cast(UUIDLC.uuid[I]);
201 }
202 BA.UUID = Slice.copyString(Stream.str());
203 break;
204 }
205 case MachO::LC_RPATH: {
207 BA.RPaths.emplace_back(Slice.copyString(LCI.Ptr + RPLC.path));
208 break;
209 }
210 case MachO::LC_SEGMENT_SPLIT_INFO: {
212 if (SSILC.datasize == 0)
213 BA.OSLibNotForSharedCache = true;
214 break;
215 }
216 default:
217 break;
218 }
219 }
220
221 for (auto &Sect : Obj->sections()) {
222 auto SectName = Sect.getName();
223 if (!SectName)
224 return SectName.takeError();
225 if (*SectName != "__objc_imageinfo" && *SectName != "__image_info")
226 continue;
227
228 auto Content = Sect.getContents();
230 return Content.takeError();
231
232 if ((Content->size() >= 8) && (Content->front() == 0)) {
235 auto *p =
237 Flags = *p;
238 } else {
239 auto *p =
241 Flags = *p;
242 }
243 BA.SwiftABI = (Flags >> 8) & 0xFF;
244 }
245 }
247}
248
251
252 auto parseExport = [](const auto ExportFlags,
253 auto Addr) -> std::tuple<SymbolFlags, RecordLinkage> {
258 Flags |= SymbolFlags::WeakDefined;
259 break;
261 Flags |= SymbolFlags::ThreadLocalValue;
262 break;
263 }
264
266 ? RecordLinkage::Rexported
267 : RecordLinkage::Exported;
268 return {Flags, Linkage};
269 };
270
272
274
275
276
277 for (auto &Sym : Obj->exports(Err)) {
278 auto [Flags, Linkage] = parseExport(Sym.flags(), Sym.address());
279 Slice.addRecord(Sym.name(), Flags, GlobalRecord::Kind::Unknown, Linkage);
280 Exports[Sym.name()] = {Flags, Linkage};
281 }
282
283 for (const auto &Sym : Obj->symbols()) {
285 if (!FlagsOrErr)
286 return FlagsOrErr.takeError();
287 auto Flags = *FlagsOrErr;
288
290 if (!NameOrErr)
291 return NameOrErr.takeError();
292 auto Name = *NameOrErr;
293
295 SymbolFlags RecordFlags = SymbolFlags::None;
296
297 if (Flags & SymbolRef::SF_Undefined) {
299 Linkage = RecordLinkage::Undefined;
300 else
301 continue;
302 if (Flags & SymbolRef::SF_Weak)
303 RecordFlags |= SymbolFlags::WeakReferenced;
304 } else if (Flags & SymbolRef::SF_Exported) {
305 auto Exp = Exports.find(Name);
306
307
308
309 if (Exp != Exports.end())
310 std::tie(RecordFlags, Linkage) = Exp->second;
311 else
312 Linkage = RecordLinkage::Exported;
313 } else if (Flags & SymbolRef::SF_Hidden) {
314 Linkage = RecordLinkage::Internal;
315 } else
316 continue;
317
318 auto TypeOrErr = Sym.getType();
319 if (!TypeOrErr)
320 return TypeOrErr.takeError();
321 auto Type = *TypeOrErr;
322
324 ? GlobalRecord::Kind::Function
325 : GlobalRecord::Kind::Variable;
326
327 if (GV == GlobalRecord::Kind::Function)
328 RecordFlags |= SymbolFlags::Text;
329 else
330 RecordFlags |= SymbolFlags::Data;
331
332 Slice.addRecord(Name, RecordFlags, GV, Linkage);
333 }
334 return Err;
335}
336
340 return make_error(TextAPIErrorCode::UnsupportedTarget);
341
344 return Err;
345
348 return Err;
349
351}
352
356
358 if (!BinOrErr)
359 return BinOrErr.takeError();
360
362 if (auto *Obj = dyn_cast(&Bin)) {
364 Obj->getHeader().cpusubtype);
366 return make_error(TextAPIErrorCode::NoSuchArchitecture);
367
369 for (const auto &T : Triples) {
371 return make_error(TextAPIErrorCode::UnsupportedTarget);
374 return std::move(Err);
376 }
378 }
379
380
382 "Expected a MachO universal binary.");
383 auto *UB = cast(&Bin);
384
385 for (auto OI = UB->begin_objects(), OE = UB->end_objects(); OI != OE; ++OI) {
386
387 auto Arch =
390 continue;
391
392
394 continue;
395
396
397 auto ObjOrErr = OI->getAsObjectFile();
398
399
400 if (!ObjOrErr) {
402 continue;
403 }
404
405 auto &Obj = *ObjOrErr.get();
406 switch (Obj.getHeader().filetype) {
407 default:
408 break;
415 return std::move(Err);
417 }
418 break;
419 }
420 }
421
423 return make_error(TextAPIErrorCode::EmptyResults);
425}
426
431 if (!SlicesOrErr)
432 return SlicesOrErr.takeError();
433
435}
436
438
441 const std::unique_ptr &DiCtx) {
445 if (!FlagsOrErr) {
447 continue;
448 }
449
450 if (!(*FlagsOrErr & SymbolRef::SF_Exported))
451 continue;
452
454 if (!AddressOrErr) {
456 continue;
457 }
459
460 auto TypeOrErr = Symbol.getType();
461 if (!TypeOrErr) {
463 continue;
464 }
466
467 auto *DWARFCU = IsCode ? DiCtx->getCompileUnitForCodeAddress(Address)
468 : DiCtx->getCompileUnitForDataAddress(Address);
469 if (!DWARFCU)
470 continue;
471
472 const DWARFDie &DIE = IsCode ? DWARFCU->getSubroutineForAddress(Address)
473 : DWARFCU->getVariableForAddress(Address);
474 const std::string File = DIE.getDeclFile(
475 llvm::DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath);
477
479 if (!NameOrErr) {
481 continue;
482 }
483 auto Name = *NameOrErr;
485
486 if (!File.empty() && Line != 0)
488 }
489
491}
492
496
498 if (!DSYMsOrErr) {
501 }
502 if (DSYMsOrErr->empty())
504
505 const StringRef Path = DSYMsOrErr->front();
507 if (auto Err = BufOrErr.getError())
509
510 auto BinOrErr = createBinary(*BufOrErr.get());
511 if (!BinOrErr) {
514 }
515
516 if (auto *Single = dyn_cast(BinOrErr->get())) {
518 *Single, DWARFContext::ProcessDebugRelocations::Process, nullptr, "",
520
522 }
523
524 if (auto *Fat = dyn_cast(BinOrErr->get())) {
526 if (!ObjForArch) {
529 }
530 auto MachOOrErr = ObjForArch->getAsObjectFile();
531 if (!MachOOrErr) {
534 }
535 auto &Obj = **MachOOrErr;
537 Obj, DWARFContext::ProcessDebugRelocations::Process, nullptr, "",
539
541 }
543}
AMDGPU Mark last scratch load
Function Alias Analysis Results
static TripleVec::iterator emplace(TripleVec &Container, Triple &&T)
static SymbolToSourceLocMap accumulateLocs(MachOObjectFile &Obj, const std::unique_ptr< DWARFContext > &DiCtx)
static Error readSymbols(MachOObjectFile *Obj, RecordsSlice &Slice, const ParseOption &Opt)
static Error readMachOHeader(MachOObjectFile *Obj, RecordsSlice &Slice)
static TripleVec constructTriples(MachOObjectFile *Obj, const Architecture ArchT)
std::vector< Triple > TripleVec
static void DWARFErrorHandler(Error Err)
IntervalMap< SlotIndex, DbgVariableValue, 4 > LocMap
Map of where a user value is live to that value.
Implements the TAPI Record Collection Type.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
Define TAPI specific error codes.
A structured debug information entry.
static std::unique_ptr< DWARFContext > create(const object::ObjectFile &Obj, ProcessDebugRelocations RelocAction=ProcessDebugRelocations::Process, const LoadedObjectInfo *L=nullptr, std::string DWPName="", std::function< void(Error)> RecoverableErrorHandler=WithColor::defaultErrorHandler, std::function< void(Error)> WarningHandler=WithColor::defaultWarningHandler, bool ThreadSafe=false)
Utility class that carries the DWARF compile/type unit and the debug info entry in an object.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
Error takeError()
Take ownership of the stored error.
const BasicBlock & back() const
void insert(KeyT a, KeyT b, ValT y)
insert - Add a mapping of [a;b] to y, coalesce with adjacent intervals.
bool has(Architecture Arch) const
SymbolFlags getFlags() const
StringRef getName() const
StringRef getBufferIdentifier() const
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
iterator find(StringRef Key)
StringRef - Represent a constant reference to a string, i.e.
Triple - Helper class for working with autoconf configuration names.
OSType getOS() const
Get the parsed operating system type of this triple.
ArchType getArch() const
Get the parsed architecture type of this triple.
EnvironmentType getEnvironment() const
Get the parsed environment type of this triple.
The instances of the Type class are immutable: once they are created, they are never changed.
bool isLittleEndian() const
MachO::sub_client_command getSubClientCommand(const LoadCommandInfo &L) const
iterator_range< export_iterator > exports(Error &Err) const
For use iterating over all exported symbols.
MachO::build_version_command getBuildVersionLoadCommand(const LoadCommandInfo &L) const
static Expected< std::vector< std::string > > findDsymObjectMembers(StringRef Path)
If the input path is a .dSYM bundle (as created by the dsymutil tool), return the paths to the object...
MachO::rpath_command getRpathCommand(const LoadCommandInfo &L) const
MachO::sub_framework_command getSubFrameworkCommand(const LoadCommandInfo &L) const
const MachO::mach_header & getHeader() const
iterator_range< load_command_iterator > load_commands() const
MachO::uuid_command getUuidCommand(const LoadCommandInfo &L) const
MachO::version_min_command getVersionMinLoadCommand(const LoadCommandInfo &L) const
MachO::linkedit_data_command getLinkeditDataLoadCommand(const LoadCommandInfo &L) const
MachO::dylib_command getDylibIDLoadCommand(const LoadCommandInfo &L) const
section_iterator_range sections() const
symbol_iterator_range symbols() const
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Defines the MachO Dynamic Library Reader.
Expected< Records > readFile(MemoryBufferRef Buffer, const ParseOption &Opt)
Parse Mach-O dynamic libraries to extract TAPI attributes.
SymbolToSourceLocMap accumulateSourceLocFromDSYM(const StringRef DSYM, const Target &T)
Get the source location for each symbol from dylib.
llvm::StringMap< RecordLoc > SymbolToSourceLocMap
Expected< std::unique_ptr< InterfaceFile > > get(MemoryBufferRef Buffer)
Get TAPI file representation of binary dylib.
@ EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL
@ EXPORT_SYMBOL_FLAGS_KIND_REGULAR
StringRef getArchitectureName(Architecture Arch)
Convert an architecture slice to a string.
Architecture
Defines the architecture slices that are supported by Text-based Stub files.
PlatformType mapToPlatformType(PlatformType Platform, bool WantSim)
@ EXPORT_SYMBOL_FLAGS_REEXPORT
@ EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION
@ EXPORT_SYMBOL_FLAGS_KIND_MASK
std::unique_ptr< InterfaceFile > convertToInterfaceFile(const Records &Slices)
SimpleSymbol parseSymbol(StringRef SymName)
Get symbol classification by parsing the name of a symbol.
Architecture getArchitectureFromCpuType(uint32_t CPUType, uint32_t CPUSubType)
Convert a CPU Type and Subtype pair to an architecture slice.
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr, bool InitContent=true)
Create a Binary from Source, autodetecting the file type.
This is an optimization pass for GlobalISel generic memory operations.
auto partition_point(R &&Range, Predicate P)
Binary search for the first iterator in a range where a predicate is false.
void consumeError(Error Err)
Consume a Error without doing anything.
bool Undefineds
Capture undefined symbols too.
bool MachOHeader
Capture Mach-O header from binary, primarily load commands.
bool SymbolTable
Capture defined symbols out of export trie and n-list.
ArchitectureSet Archs
Determines arch slice to parse.