22 #include "absl/strings/str_join.h"
23 #include "absl/strings/string_view.h"
24 #include "absl/strings/substitute.h"
44 THROW(
"Malformed Mach-O file");
53 if (
sizeof(
T) >
data.size()) {
54 THROW(
"Premature EOF reading Mach-O data.");
56 return reinterpret_cast<const T*
>(
data.data());
61 const T*
ret = GetStructPointer<T>(*
data);
79 template <
class Struct>
85 template <
class Struct,
class Func>
87 Func&& loadcmd_func) {
102 THROW(
"Mach-O load command had zero size.");
106 data.is64bit = Is64Bit<Struct>();
109 data.file_data = macho_data;
110 std::forward<Func>(loadcmd_func)(
data);
117 template <
class Func>
119 Func&& loadcmd_func) {
130 ParseMachOHeaderImpl<mach_header>(macho_file, overhead_sink,
131 std::forward<Func>(loadcmd_func));
134 ParseMachOHeaderImpl<mach_header_64>(
135 macho_file, overhead_sink, std::forward<Func>(loadcmd_func));
151 THROW(
"We don't support cross-endian Mach-O files.");
153 THROW(
"Corrupt Mach-O file");
157 template <
class Func>
159 Func&& loadcmd_func) {
171 std::forward<Func>(loadcmd_func));
175 template <
class Func>
177 Func&& loadcmd_func) {
185 std::forward<Func>(loadcmd_func));
189 std::forward<Func>(loadcmd_func));
194 template <
class Segment,
class Section>
197 auto segment = GetStructPointerAndAdvance<Segment>(&command_data);
206 for (
uint32_t j = 0; j < nsects; j++) {
207 auto section = GetStructPointerAndAdvance<Section>(&command_data);
229 segment->vmaddr, segment->vmsize,
233 template <
class Segment,
class Section>
235 auto segment = GetStructPointerAndAdvance<Segment>(&
cmd.command_data);
251 "macho_segment", segname,
255 "macho_segment", segname, segment->vmaddr, segment->vmsize,
260 for (
uint32_t j = 0; j < nsects; j++) {
261 auto section = GetStructPointerAndAdvance<Section>(&
cmd.command_data);
279 "macho_section",
label,
292 auto info = GetStructPointer<dyld_info_command>(
cmd.command_data);
295 "macho_dyld",
"Rebase Info",
298 "macho_dyld",
"Binding Info",
301 "macho_dyld",
"Weak Binding Info",
302 StrictSubstr(
cmd.file_data, info->weak_bind_off, info->weak_bind_size));
304 "macho_dyld",
"Lazy Binding Info",
305 StrictSubstr(
cmd.file_data, info->lazy_bind_off, info->lazy_bind_size));
307 "macho_dyld",
"Export Info",
312 auto symtab = GetStructPointer<symtab_command>(
cmd.command_data);
316 "macho_symtab",
"Symbol Table",
319 "macho_symtab",
"String Table",
324 auto dysymtab = GetStructPointer<dysymtab_command>(
cmd.command_data);
327 "macho_dynsymtab",
"Table of Contents",
330 sink->AddFileRange(
"macho_dynsymtab",
"Module Table",
334 "macho_dynsymtab",
"Referenced Symbol Table",
337 sink->AddFileRange(
"macho_dynsymtab",
"Indirect Symbol Table",
339 dysymtab->nindirectsyms *
sizeof(
uint32_t)));
340 sink->AddFileRange(
"macho_dynsymtab",
"External Relocation Entries",
344 "macho_dynsymtab",
"Local Relocation Entries",
351 auto linkedit = GetStructPointer<linkedit_data_command>(
cmd.command_data);
353 "macho_linkedit",
label,
360 ParseSegment<segment_command_64, section_64>(
cmd,
sink);
363 ParseSegment<segment_command, section>(
cmd,
sink);
402 template <
class NList>
405 auto symtab_cmd = GetStructPointer<symtab_command>(
cmd.command_data);
408 symtab_cmd->nsyms *
sizeof(NList));
414 auto sym = GetStructPointerAndAdvance<NList>(&
symtab);
415 string_view sym_range(
reinterpret_cast<const char*
>(sym),
sizeof(NList));
417 if (sym->n_type &
N_STAB || sym->n_value == 0) {
430 table->insert(std::make_pair(
436 sink->AddFileRangeForVMAddr(
"macho_symtab_name", sym->n_value,
name);
437 sink->AddFileRangeForVMAddr(
"macho_symtab_sym", sym->n_value, sym_range);
448 ParseSymbolsFromSymbolTable<nlist_64>(cmd, symtab, sink);
450 ParseSymbolsFromSymbolTable<struct nlist>(cmd, symtab, sink);
466 AddSegmentAsFallback<segment_command_64, section_64>(
467 cmd.command_data, cmd.file_data, sink);
470 AddSegmentAsFallback<segment_command, section>(cmd.command_data,
471 cmd.file_data, sink);
475 sink->AddFileRange(
"macho_fallback",
"[Unmapped]",
sink->input_file().data());
478 template <
class Segment,
class Section>
481 auto segment = GetStructPointerAndAdvance<Segment>(&
cmd.command_data);
484 if (segname !=
"__DWARF") {
489 for (
uint32_t j = 0; j < nsects; j++) {
490 auto section = GetStructPointerAndAdvance<Section>(&
cmd.command_data);
508 if (sectname.
find(
"__debug_") == 0) {
511 }
else if (sectname.
find(
"__zdebug_") == 0) {
517 auto uncompressed_size = ReadBigEndian<uint64_t>(&
contents);
529 ReadDebugSectionsFromSegment<segment_command_64, section_64>(
533 ReadDebugSectionsFromSegment<segment_command, section>(cmd, dwarf,
551 GetStructPointerAndAdvance<uuid_command>(&cmd.command_data);
552 if (!cmd.command_data.empty()) {
553 THROWF(
"Unexpected excess uuid data: $0", cmd.command_data.size());
555 id.resize(
sizeof(uuid_cmd->uuid));
556 memcpy(&
id[0], &uuid_cmd->uuid[0],
sizeof(uuid_cmd->uuid));
563 void ProcessFile(
const std::vector<RangeSink*>& sinks)
const override {
564 for (
auto sink : sinks) {
565 switch (
sink->data_source()) {
566 case DataSource::kSegments:
567 case DataSource::kSections:
570 case DataSource::kSymbols:
571 case DataSource::kRawSymbols:
572 case DataSource::kShortSymbols:
573 case DataSource::kFullSymbols:
576 case DataSource::kCompileUnits: {
581 DataSource::kRawSymbols,
582 &sinks[0]->MapAtIndex(0),
nullptr);
583 symbol_sink.
AddOutput(&symbol_map, &empty_munger);
591 case DataSource::kArchiveMembers:
592 case DataSource::kInlines:
594 THROW(
"Mach-O doesn't support this data source");
603 WARN(
"Mach-O files do not support disassembly yet");
617 return std::unique_ptr<ObjectFile>(