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

381 assert(isa(&Bin) &&

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.