macho.cc
Go to the documentation of this file.
1 // Copyright 2016 Google Inc. All Rights Reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include <iostream>
16 #include "string.h"
17 #include "bloaty.h"
18 #include "util.h"
19 
20 #include <cassert>
21 
22 #include "absl/strings/str_join.h"
23 #include "absl/strings/string_view.h"
24 #include "absl/strings/substitute.h"
29 
30 using absl::string_view;
31 
32 namespace bloaty {
33 namespace macho {
34 
35 // segname (& sectname) may NOT be NULL-terminated,
36 // i.e. can use up all 16 chars, e.g. '__gcc_except_tab' (no '\0'!)
37 // hence specifying size when constructing std::string
38 static string_view ArrayToStr(const char* s, size_t maxlen) {
39  return string_view(s, strnlen(s, maxlen));
40 }
41 
43  if (data.size() < sizeof(uint32_t)) {
44  THROW("Malformed Mach-O file");
45  }
47  memcpy(&magic, data.data(), sizeof(magic));
48  return magic;
49 }
50 
51 template <class T>
53  if (sizeof(T) > data.size()) {
54  THROW("Premature EOF reading Mach-O data.");
55  }
56  return reinterpret_cast<const T*>(data.data());
57 }
58 
59 template <class T>
61  const T* ret = GetStructPointer<T>(*data);
62  *data = data->substr(sizeof(T));
63  return ret;
64 }
65 
67  if (sink) {
68  sink->AddFileRange("macho_overhead", label, data);
69  }
70 }
71 
72 struct LoadCommand {
73  bool is64bit;
77 };
78 
79 template <class Struct>
80 bool Is64Bit() { return false; }
81 
82 template <>
83 bool Is64Bit<mach_header_64>() { return true; }
84 
85 template <class Struct, class Func>
86 void ParseMachOHeaderImpl(string_view macho_data, RangeSink* overhead_sink,
87  Func&& loadcmd_func) {
88  string_view header_data = macho_data;
89  auto header = GetStructPointerAndAdvance<Struct>(&header_data);
90  MaybeAddOverhead(overhead_sink,
91  "[Mach-O Headers]",
92  macho_data.substr(0, sizeof(Struct)));
93  uint32_t ncmds = header->ncmds;
94 
95  for (uint32_t i = 0; i < ncmds; i++) {
96  auto command = GetStructPointer<load_command>(header_data);
97 
98  // We test for this because otherwise a large ncmds can make bloaty hang for
99  // a while, even on a small file. Hopefully there are no real cases where a
100  // zero-size loadcmd exists.
101  if (command->cmdsize == 0) {
102  THROW("Mach-O load command had zero size.");
103  }
104 
106  data.is64bit = Is64Bit<Struct>();
107  data.cmd = command->cmd;
108  data.command_data = StrictSubstr(header_data, 0, command->cmdsize);
109  data.file_data = macho_data;
110  std::forward<Func>(loadcmd_func)(data);
111 
112  MaybeAddOverhead(overhead_sink, "[Mach-O Headers]", data.command_data);
113  header_data = header_data.substr(command->cmdsize);
114  }
115 }
116 
117 template <class Func>
118 void ParseMachOHeader(string_view macho_file, RangeSink* overhead_sink,
119  Func&& loadcmd_func) {
120  uint32_t magic = ReadMagic(macho_file);
121  switch (magic) {
122  case MH_MAGIC:
123  // We don't expect to see many 32-bit binaries out in the wild.
124  // Apple is aggressively phasing out support for 32-bit binaries:
125  // https://www.macrumors.com/2017/06/06/apple-to-phase-out-32-bit-mac-apps/
126  //
127  // Still, you can build 32-bit binaries as of this writing, and
128  // there are existing 32-bit binaries floating around, so we might
129  // as well support them.
130  ParseMachOHeaderImpl<mach_header>(macho_file, overhead_sink,
131  std::forward<Func>(loadcmd_func));
132  break;
133  case MH_MAGIC_64:
134  ParseMachOHeaderImpl<mach_header_64>(
135  macho_file, overhead_sink, std::forward<Func>(loadcmd_func));
136  break;
137  case MH_CIGAM:
138  case MH_CIGAM_64:
139  // OS X and Darwin currently only run on x86/x86-64 (little-endian
140  // platforms), so we expect basically all Mach-O files to be
141  // little-endian. Additionally, pretty much all CPU architectures
142  // are little-endian these days. ARM has the option to be
143  // big-endian, but I can't find any OS that is actually compiled to
144  // use big-endian mode. debian-mips is the only big-endian OS I can
145  // find (and maybe SPARC).
146  //
147  // All of this is to say, this case should only happen if you are
148  // running Bloaty on debian-mips. I consider that uncommon enough
149  // (and hard enough to test) that we don't support this until there
150  // is a demonstrated need.
151  THROW("We don't support cross-endian Mach-O files.");
152  default:
153  THROW("Corrupt Mach-O file");
154  }
155 }
156 
157 template <class Func>
158 void ParseFatHeader(string_view fat_file, RangeSink* overhead_sink,
159  Func&& loadcmd_func) {
160  string_view header_data = fat_file;
161  auto header = GetStructPointerAndAdvance<fat_header>(&header_data);
162  MaybeAddOverhead(overhead_sink, "[Mach-O Headers]",
163  fat_file.substr(0, sizeof(fat_header)));
164  assert(ByteSwap(header->magic) == FAT_MAGIC);
165  uint32_t nfat_arch = ByteSwap(header->nfat_arch);
166  for (uint32_t i = 0; i < nfat_arch; i++) {
167  auto arch = GetStructPointerAndAdvance<fat_arch>(&header_data);
168  string_view macho_data = StrictSubstr(
169  fat_file, ByteSwap(arch->offset), ByteSwap(arch->size));
170  ParseMachOHeader(macho_data, overhead_sink,
171  std::forward<Func>(loadcmd_func));
172  }
173 }
174 
175 template <class Func>
176 void ForEachLoadCommand(string_view maybe_fat_file, RangeSink* overhead_sink,
177  Func&& loadcmd_func) {
178  uint32_t magic = ReadMagic(maybe_fat_file);
179  switch (magic) {
180  case MH_MAGIC:
181  case MH_MAGIC_64:
182  case MH_CIGAM:
183  case MH_CIGAM_64:
184  ParseMachOHeader(maybe_fat_file, overhead_sink,
185  std::forward<Func>(loadcmd_func));
186  break;
187  case FAT_CIGAM:
188  ParseFatHeader(maybe_fat_file, overhead_sink,
189  std::forward<Func>(loadcmd_func));
190  break;
191  }
192 }
193 
194 template <class Segment, class Section>
196  RangeSink* sink) {
197  auto segment = GetStructPointerAndAdvance<Segment>(&command_data);
198 
199  if (segment->maxprot == VM_PROT_NONE) {
200  return;
201  }
202 
203  string_view segname = ArrayToStr(segment->segname, 16);
204 
205  uint32_t nsects = segment->nsects;
206  for (uint32_t j = 0; j < nsects; j++) {
207  auto section = GetStructPointerAndAdvance<Section>(&command_data);
208 
209  // filesize equals vmsize unless the section is zerofill
210  uint64_t filesize = section->size;
211  switch (section->flags & SECTION_TYPE) {
212  case S_ZEROFILL:
213  case S_GB_ZEROFILL:
215  filesize = 0;
216  break;
217  default:
218  break;
219  }
220 
222  std::make_tuple(segname, ArrayToStr(section->sectname, 16)), ",");
223  label = "[" + label + "]";
224  sink->AddRange("macho_fallback", label, section->addr, section->size,
225  StrictSubstr(file_data, section->offset, filesize));
226  }
227 
228  sink->AddRange("macho_fallback", "[" + std::string(segname) + "]",
229  segment->vmaddr, segment->vmsize,
230  StrictSubstr(file_data, segment->fileoff, segment->filesize));
231 }
232 
233 template <class Segment, class Section>
235  auto segment = GetStructPointerAndAdvance<Segment>(&cmd.command_data);
236  string_view segname = ArrayToStr(segment->segname, 16);
237 
238  // For unknown reasons, some load commands will have maxprot = NONE
239  // indicating they are not accessible, but will also contain a vmaddr
240  // and vmsize. In practice the vmaddr/vmsize of a section sometimes
241  // fall within the segment, but sometimes exceed it, leading to an
242  // error about exceeding the base map.
243  //
244  // Since such segments should not be mapped, we simply ignore the
245  // vmaddr/vmsize of such segments.
246  bool unmapped = segment->maxprot == VM_PROT_NONE;
247 
248  if (sink->data_source() == DataSource::kSegments) {
249  if (unmapped) {
250  sink->AddFileRange(
251  "macho_segment", segname,
252  StrictSubstr(cmd.file_data, segment->fileoff, segment->filesize));
253  } else {
254  sink->AddRange(
255  "macho_segment", segname, segment->vmaddr, segment->vmsize,
256  StrictSubstr(cmd.file_data, segment->fileoff, segment->filesize));
257  }
258  } else if (sink->data_source() == DataSource::kSections) {
259  uint32_t nsects = segment->nsects;
260  for (uint32_t j = 0; j < nsects; j++) {
261  auto section = GetStructPointerAndAdvance<Section>(&cmd.command_data);
262 
263  // filesize equals vmsize unless the section is zerofill
264  uint64_t filesize = section->size;
265  switch (section->flags & SECTION_TYPE) {
266  case S_ZEROFILL:
267  case S_GB_ZEROFILL:
269  filesize = 0;
270  break;
271  default:
272  break;
273  }
274 
276  std::make_tuple(segname, ArrayToStr(section->sectname, 16)), ",");
277  if (unmapped) {
278  sink->AddFileRange(
279  "macho_section", label,
280  StrictSubstr(cmd.file_data, section->offset, filesize));
281  } else {
282  sink->AddRange("macho_section", label, section->addr, section->size,
283  StrictSubstr(cmd.file_data, section->offset, filesize));
284  }
285  }
286  } else {
288  }
289 }
290 
291 static void ParseDyldInfo(const LoadCommand& cmd, RangeSink* sink) {
292  auto info = GetStructPointer<dyld_info_command>(cmd.command_data);
293 
294  sink->AddFileRange(
295  "macho_dyld", "Rebase Info",
296  StrictSubstr(cmd.file_data, info->rebase_off, info->rebase_size));
297  sink->AddFileRange(
298  "macho_dyld", "Binding Info",
299  StrictSubstr(cmd.file_data, info->bind_off, info->bind_size));
300  sink->AddFileRange(
301  "macho_dyld", "Weak Binding Info",
302  StrictSubstr(cmd.file_data, info->weak_bind_off, info->weak_bind_size));
303  sink->AddFileRange(
304  "macho_dyld", "Lazy Binding Info",
305  StrictSubstr(cmd.file_data, info->lazy_bind_off, info->lazy_bind_size));
306  sink->AddFileRange(
307  "macho_dyld", "Export Info",
308  StrictSubstr(cmd.file_data, info->export_off, info->export_size));
309 }
310 
312  auto symtab = GetStructPointer<symtab_command>(cmd.command_data);
313 
314  size_t size = cmd.is64bit ? sizeof(nlist_64) : sizeof(struct nlist);
315  sink->AddFileRange(
316  "macho_symtab", "Symbol Table",
317  StrictSubstr(cmd.file_data, symtab->symoff, symtab->nsyms * size));
318  sink->AddFileRange(
319  "macho_symtab", "String Table",
320  StrictSubstr(cmd.file_data, symtab->stroff, symtab->strsize));
321 }
322 
324  auto dysymtab = GetStructPointer<dysymtab_command>(cmd.command_data);
325 
326  sink->AddFileRange(
327  "macho_dynsymtab", "Table of Contents",
328  StrictSubstr(cmd.file_data, dysymtab->tocoff,
329  dysymtab->ntoc * sizeof(dylib_table_of_contents)));
330  sink->AddFileRange("macho_dynsymtab", "Module Table",
331  StrictSubstr(cmd.file_data, dysymtab->modtaboff,
332  dysymtab->nmodtab * sizeof(dylib_module_64)));
333  sink->AddFileRange(
334  "macho_dynsymtab", "Referenced Symbol Table",
335  StrictSubstr(cmd.file_data, dysymtab->extrefsymoff,
336  dysymtab->nextrefsyms * sizeof(dylib_reference)));
337  sink->AddFileRange("macho_dynsymtab", "Indirect Symbol Table",
338  StrictSubstr(cmd.file_data, dysymtab->indirectsymoff,
339  dysymtab->nindirectsyms * sizeof(uint32_t)));
340  sink->AddFileRange("macho_dynsymtab", "External Relocation Entries",
341  StrictSubstr(cmd.file_data, dysymtab->extreloff,
342  dysymtab->nextrel * sizeof(relocation_info)));
343  sink->AddFileRange(
344  "macho_dynsymtab", "Local Relocation Entries",
345  StrictSubstr(cmd.file_data, dysymtab->locreloff,
346  dysymtab->nlocrel * sizeof(struct relocation_info)));
347 }
348 
350  RangeSink* sink) {
351  auto linkedit = GetStructPointer<linkedit_data_command>(cmd.command_data);
352  sink->AddFileRange(
353  "macho_linkedit", label,
354  StrictSubstr(cmd.file_data, linkedit->dataoff, linkedit->datasize));
355 }
356 
358  switch (cmd.cmd) {
359  case LC_SEGMENT_64:
360  ParseSegment<segment_command_64, section_64>(cmd, sink);
361  break;
362  case LC_SEGMENT:
363  ParseSegment<segment_command, section>(cmd, sink);
364  break;
365  case LC_DYLD_INFO:
366  case LC_DYLD_INFO_ONLY:
368  break;
369  case LC_SYMTAB:
371  break;
372  case LC_DYSYMTAB:
374  break;
375  case LC_CODE_SIGNATURE:
376  ParseLinkeditCommand("Code Signature", cmd, sink);
377  break;
379  ParseLinkeditCommand("Segment Split Info", cmd, sink);
380  break;
381  case LC_FUNCTION_STARTS:
382  ParseLinkeditCommand("Function Start Addresses", cmd, sink);
383  break;
384  case LC_DATA_IN_CODE:
385  ParseLinkeditCommand("Table of Non-instructions", cmd, sink);
386  break;
388  ParseLinkeditCommand("Code Signing DRs", cmd, sink);
389  break;
391  ParseLinkeditCommand("Optimization Hints", cmd, sink);
392  break;
393  }
394 }
395 
398  sink->input_file().data(), sink,
399  [sink](const LoadCommand& cmd) { ParseLoadCommand(cmd, sink); });
400 }
401 
402 template <class NList>
404  RangeSink* sink) {
405  auto symtab_cmd = GetStructPointer<symtab_command>(cmd.command_data);
406 
407  string_view symtab = StrictSubstr(cmd.file_data, symtab_cmd->symoff,
408  symtab_cmd->nsyms * sizeof(NList));
409  string_view strtab =
410  StrictSubstr(cmd.file_data, symtab_cmd->stroff, symtab_cmd->strsize);
411 
412  uint32_t nsyms = symtab_cmd->nsyms;
413  for (uint32_t i = 0; i < nsyms; i++) {
414  auto sym = GetStructPointerAndAdvance<NList>(&symtab);
415  string_view sym_range(reinterpret_cast<const char*>(sym), sizeof(NList));
416 
417  if (sym->n_type & N_STAB || sym->n_value == 0) {
418  continue;
419  }
420 
421  string_view name_region = StrictSubstr(strtab, sym->n_un.n_strx);
422  string_view name = ReadNullTerminated(&name_region);
423 
424  if (sink->data_source() >= DataSource::kSymbols) {
425  sink->AddVMRange("macho_symbols", sym->n_value, RangeSink::kUnknownSize,
426  ItaniumDemangle(name, sink->data_source()));
427  }
428 
429  if (table) {
430  table->insert(std::make_pair(
431  name, std::make_pair(sym->n_value, RangeSink::kUnknownSize)));
432  }
433 
434  // Capture the trailing NULL.
435  name = string_view(name.data(), name.size() + 1);
436  sink->AddFileRangeForVMAddr("macho_symtab_name", sym->n_value, name);
437  sink->AddFileRangeForVMAddr("macho_symtab_sym", sym->n_value, sym_range);
438  }
439 }
440 
443  file_data, sink,
444  [symtab, sink](const LoadCommand& cmd) {
445  switch (cmd.cmd) {
446  case LC_SYMTAB:
447  if (cmd.is64bit) {
448  ParseSymbolsFromSymbolTable<nlist_64>(cmd, symtab, sink);
449  } else {
450  ParseSymbolsFromSymbolTable<struct nlist>(cmd, symtab, sink);
451  }
452  break;
453  case LC_DYSYMTAB:
454  //ParseSymbolsFromDynamicSymbolTable(command_data, file_data, sink);
455  break;
456  }
457  });
458 }
459 
462  sink->input_file().data(), sink,
463  [sink](const LoadCommand& cmd) {
464  switch (cmd.cmd) {
465  case LC_SEGMENT_64:
466  AddSegmentAsFallback<segment_command_64, section_64>(
467  cmd.command_data, cmd.file_data, sink);
468  break;
469  case LC_SEGMENT:
470  AddSegmentAsFallback<segment_command, section>(cmd.command_data,
471  cmd.file_data, sink);
472  break;
473  }
474  });
475  sink->AddFileRange("macho_fallback", "[Unmapped]", sink->input_file().data());
476 }
477 
478 template <class Segment, class Section>
480  RangeSink *sink) {
481  auto segment = GetStructPointerAndAdvance<Segment>(&cmd.command_data);
482  string_view segname = ArrayToStr(segment->segname, 16);
483 
484  if (segname != "__DWARF") {
485  return;
486  }
487 
488  uint32_t nsects = segment->nsects;
489  for (uint32_t j = 0; j < nsects; j++) {
490  auto section = GetStructPointerAndAdvance<Section>(&cmd.command_data);
491  string_view sectname = ArrayToStr(section->sectname, 16);
492 
493  // filesize equals vmsize unless the section is zerofill
494  uint64_t filesize = section->size;
495  switch (section->flags & SECTION_TYPE) {
496  case S_ZEROFILL:
497  case S_GB_ZEROFILL:
499  filesize = 0;
500  break;
501  default:
502  break;
503  }
504 
506  StrictSubstr(cmd.file_data, section->offset, filesize);
507 
508  if (sectname.find("__debug_") == 0) {
509  sectname.remove_prefix(string_view("__debug_").size());
510  dwarf->SetFieldByName(sectname, contents);
511  } else if (sectname.find("__zdebug_") == 0) {
512  sectname.remove_prefix(string_view("__zdebug_").size());
513  string_view *member = dwarf->GetFieldByName(sectname);
514  if (!member || ReadBytes(4, &contents) != "ZLIB") {
515  continue;
516  }
517  auto uncompressed_size = ReadBigEndian<uint64_t>(&contents);
518  *member = sink->ZlibDecompress(contents, uncompressed_size);
519  }
520  }
521 }
522 
524  dwarf::File *dwarf, RangeSink *sink) {
526  file.data(), nullptr, [dwarf, sink](const LoadCommand &cmd) {
527  switch (cmd.cmd) {
528  case LC_SEGMENT_64:
529  ReadDebugSectionsFromSegment<segment_command_64, section_64>(
530  cmd, dwarf, sink);
531  break;
532  case LC_SEGMENT:
533  ReadDebugSectionsFromSegment<segment_command, section>(cmd, dwarf,
534  sink);
535  break;
536  }
537  });
538 }
539 
540 class MachOObjectFile : public ObjectFile {
541  public:
542  MachOObjectFile(std::unique_ptr<InputFile> file_data)
543  : ObjectFile(std::move(file_data)) {}
544 
545  std::string GetBuildId() const override {
546  std::string id;
547 
548  ForEachLoadCommand(file_data().data(), nullptr, [&id](LoadCommand cmd) {
549  if (cmd.cmd == LC_UUID) {
550  auto uuid_cmd =
551  GetStructPointerAndAdvance<uuid_command>(&cmd.command_data);
552  if (!cmd.command_data.empty()) {
553  THROWF("Unexpected excess uuid data: $0", cmd.command_data.size());
554  }
555  id.resize(sizeof(uuid_cmd->uuid));
556  memcpy(&id[0], &uuid_cmd->uuid[0], sizeof(uuid_cmd->uuid));
557  }
558  });
559 
560  return id;
561  }
562 
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:
569  break;
570  case DataSource::kSymbols:
571  case DataSource::kRawSymbols:
572  case DataSource::kShortSymbols:
573  case DataSource::kFullSymbols:
574  ParseSymbols(debug_file().file_data().data(), nullptr, sink);
575  break;
576  case DataSource::kCompileUnits: {
578  DualMap symbol_map;
579  NameMunger empty_munger;
580  RangeSink symbol_sink(&debug_file().file_data(), sink->options(),
581  DataSource::kRawSymbols,
582  &sinks[0]->MapAtIndex(0), nullptr);
583  symbol_sink.AddOutput(&symbol_map, &empty_munger);
584  ParseSymbols(debug_file().file_data().data(), &symtab, &symbol_sink);
585  dwarf::File dwarf;
586  ReadDebugSectionsFromMachO(debug_file().file_data(), &dwarf, sink);
587  ReadDWARFCompileUnits(dwarf, symbol_map, sink);
588  ParseSymbols(sink->input_file().data(), nullptr, sink);
589  break;
590  }
591  case DataSource::kArchiveMembers:
592  case DataSource::kInlines:
593  default:
594  THROW("Mach-O doesn't support this data source");
595  }
597  }
598  }
599 
601  DataSource /*symbol_source*/,
602  DisassemblyInfo* /*info*/) const override {
603  WARN("Mach-O files do not support disassembly yet");
604  return false;
605  }
606 };
607 
608 } // namespace macho
609 
610 std::unique_ptr<ObjectFile> TryOpenMachOFile(std::unique_ptr<InputFile> &file) {
611  uint32_t magic = macho::ReadMagic(file->data());
612 
613  // We only support little-endian host and little endian binaries (see
614  // ParseMachOHeader() for more rationale). Fat headers are always on disk as
615  // big-endian.
616  if (magic == MH_MAGIC || magic == MH_MAGIC_64 || magic == FAT_CIGAM) {
617  return std::unique_ptr<ObjectFile>(
619  }
620 
621  return nullptr;
622 }
623 
624 } // namespace bloaty
LC_CODE_SIGNATURE
#define LC_CODE_SIGNATURE
Definition: loader.h:219
bloaty::macho::Is64Bit< mach_header_64 >
bool Is64Bit< mach_header_64 >()
Definition: macho.cc:83
section::addr
uint32_t addr
Definition: loader.h:340
bloaty
Definition: bloaty.cc:69
bloaty::macho::MachOObjectFile::ProcessFile
void ProcessFile(const std::vector< RangeSink * > &sinks) const override
Definition: macho.cc:563
dylib_module_64
Definition: loader.h:946
LC_SEGMENT_64
#define LC_SEGMENT_64
Definition: loader.h:215
dylib_table_of_contents
Definition: loader.h:911
S_GB_ZEROFILL
#define S_GB_ZEROFILL
Definition: loader.h:401
S_ZEROFILL
#define S_ZEROFILL
Definition: loader.h:377
bloaty::macho::ParseFatHeader
void ParseFatHeader(string_view fat_file, RangeSink *overhead_sink, Func &&loadcmd_func)
Definition: macho.cc:158
magic
uintptr_t magic
Definition: abseil-cpp/absl/base/internal/low_level_alloc.cc:83
bloaty::macho::AddMachOFallback
static void AddMachOFallback(RangeSink *sink)
Definition: macho.cc:460
bloaty::dwarf::File::SetFieldByName
void SetFieldByName(absl::string_view name, absl::string_view contents)
Definition: debug_info.h:80
bloaty::macho::ParseLinkeditCommand
static void ParseLinkeditCommand(string_view label, const LoadCommand &cmd, RangeSink *sink)
Definition: macho.cc:349
std::tr1::make_tuple
tuple make_tuple()
Definition: cares/cares/test/gmock-1.8.0/gtest/gtest.h:1619
bloaty::macho::GetStructPointer
const T * GetStructPointer(string_view data)
Definition: macho.cc:52
LC_DYSYMTAB
#define LC_DYSYMTAB
Definition: loader.h:194
SECTION_TYPE
#define SECTION_TYPE
Definition: loader.h:372
absl::string_view::find
size_type find(string_view s, size_type pos=0) const noexcept
Definition: abseil-cpp/absl/strings/string_view.cc:81
MH_MAGIC_64
#define MH_MAGIC_64
Definition: loader.h:77
bloaty::ObjectFile
Definition: bloaty.h:257
bloaty::macho::ParseSymbolTable
static void ParseSymbolTable(const LoadCommand &cmd, RangeSink *sink)
Definition: macho.cc:311
string.h
absl::string_view
Definition: abseil-cpp/absl/strings/string_view.h:167
bloaty.h
testing::internal::string
::std::string string
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/include/gtest/internal/gtest-port.h:881
LC_LINKER_OPTIMIZATION_HINT
#define LC_LINKER_OPTIMIZATION_HINT
Definition: loader.h:237
section::flags
uint32_t flags
Definition: loader.h:346
file
Definition: bloaty/third_party/zlib/examples/gzappend.c:170
setup.name
name
Definition: setup.py:542
bloaty::macho::LoadCommand::cmd
uint32_t cmd
Definition: macho.cc:74
bloaty::macho::MachOObjectFile
Definition: macho.cc:540
dylib_reference
Definition: loader.h:980
section::sectname
char sectname[16]
Definition: loader.h:338
LC_DYLIB_CODE_SIGN_DRS
#define LC_DYLIB_CODE_SIGN_DRS
Definition: loader.h:234
bloaty::macho::MachOObjectFile::GetBuildId
std::string GetBuildId() const override
Definition: macho.cc:545
bloaty::DataSource::kSegments
@ kSegments
bloaty::macho::ParseSegment
void ParseSegment(LoadCommand cmd, RangeSink *sink)
Definition: macho.cc:234
LC_DYLD_INFO_ONLY
#define LC_DYLD_INFO_ONLY
Definition: loader.h:225
bloaty::macho::ReadDebugSectionsFromSegment
void ReadDebugSectionsFromSegment(LoadCommand cmd, dwarf::File *dwarf, RangeSink *sink)
Definition: macho.cc:479
T
#define T(upbtypeconst, upbtype, ctype, default_value)
versiongenerate.file_data
string file_data
Definition: bloaty/third_party/protobuf/third_party/googletest/googletest/xcode/Scripts/versiongenerate.py:84
uint32_t
unsigned int uint32_t
Definition: stdint-msvc2008.h:80
section::size
uint32_t size
Definition: loader.h:341
FAT_CIGAM
#define FAT_CIGAM
Definition: fat.h:48
memcpy
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
bloaty::ItaniumDemangle
std::string ItaniumDemangle(string_view symbol, DataSource source)
Definition: bloaty.cc:169
bloaty::macho::AddSegmentAsFallback
void AddSegmentAsFallback(string_view command_data, string_view file_data, RangeSink *sink)
Definition: macho.cc:195
MH_MAGIC
#define MH_MAGIC
Definition: loader.h:58
absl::move
constexpr absl::remove_reference_t< T > && move(T &&t) noexcept
Definition: abseil-cpp/absl/utility/utility.h:221
bloaty::RangeSink::kUnknownSize
static constexpr uint64_t kUnknownSize
Definition: bloaty.h:211
absl::StrJoin
std::string StrJoin(Iterator start, Iterator end, absl::string_view sep, Formatter &&fmt)
Definition: abseil-cpp/absl/strings/str_join.h:239
gen_synthetic_protos.label
label
Definition: gen_synthetic_protos.py:102
THROW
#define THROW(msg)
Definition: bloaty/src/util.h:45
nlist_64
Definition: nlist.h:92
bloaty::macho::ForEachLoadCommand
void ForEachLoadCommand(string_view maybe_fat_file, RangeSink *overhead_sink, Func &&loadcmd_func)
Definition: macho.cc:176
absl::random_internal_nanobenchmark::Func
FuncOutput(*)(const void *, FuncInput) Func
Definition: abseil-cpp/absl/random/internal/nanobenchmark.h:68
reloc.h
bloaty::macho::ArrayToStr
static string_view ArrayToStr(const char *s, size_t maxlen)
Definition: macho.cc:38
bloaty::macho::MaybeAddOverhead
void MaybeAddOverhead(RangeSink *sink, const char *label, string_view data)
Definition: macho.cc:66
member
int member
Definition: abseil-cpp/absl/base/invoke_test.cc:87
bloaty::NameMunger
Definition: bloaty.h:236
uint64_t
unsigned __int64 uint64_t
Definition: stdint-msvc2008.h:90
nlist.h
header
struct absl::base_internal::@2940::AllocList::Header header
regen-readme.cmd
cmd
Definition: regen-readme.py:21
bloaty::macho::ParseMachOHeaderImpl
void ParseMachOHeaderImpl(string_view macho_data, RangeSink *overhead_sink, Func &&loadcmd_func)
Definition: macho.cc:86
LC_FUNCTION_STARTS
#define LC_FUNCTION_STARTS
Definition: loader.h:229
fat_header
Definition: fat.h:50
bloaty::RangeSink
Definition: bloaty.h:110
VM_PROT_NONE
#define VM_PROT_NONE
Definition: vm_prot.h:81
bloaty::macho::ReadDebugSectionsFromMachO
static void ReadDebugSectionsFromMachO(const InputFile &file, dwarf::File *dwarf, RangeSink *sink)
Definition: macho.cc:523
data
char data[kBufferLength]
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:1006
LC_SEGMENT_SPLIT_INFO
#define LC_SEGMENT_SPLIT_INFO
Definition: loader.h:220
bloaty::DataSource
DataSource
Definition: bloaty.h:52
bloaty::macho::Is64Bit
bool Is64Bit()
Definition: macho.cc:80
bloaty::macho::ParseSymbols
void ParseSymbols(string_view file_data, SymbolTable *symtab, RangeSink *sink)
Definition: macho.cc:441
arch
cs_arch arch
Definition: cstool.c:13
bloaty::dwarf::File::GetFieldByName
absl::string_view * GetFieldByName(absl::string_view name)
Definition: dwarf.cc:196
bloaty::DualMap
Definition: bloaty.h:312
nlist
Definition: nlist.h:76
section
Definition: loader.h:337
N_STAB
#define N_STAB
Definition: nlist.h:117
symtab
upb_symtab * symtab
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:774
LC_UUID
#define LC_UUID
Definition: loader.h:217
contents
string_view contents
Definition: elf.cc:597
bloaty::macho::ParseDyldInfo
static void ParseDyldInfo(const LoadCommand &cmd, RangeSink *sink)
Definition: macho.cc:291
bloaty::DataSource::kSymbols
@ kSymbols
BLOATY_UNREACHABLE
#define BLOATY_UNREACHABLE()
Definition: bloaty/src/util.h:53
Struct
struct Struct Struct
Definition: bloaty/third_party/protobuf/php/ext/google/protobuf/protobuf.h:670
S_THREAD_LOCAL_ZEROFILL
#define S_THREAD_LOCAL_ZEROFILL
Definition: loader.h:410
sink
FormatSinkImpl * sink
Definition: abseil-cpp/absl/strings/internal/str_format/float_conversion.cc:450
absl::string_view::remove_prefix
ABSL_INTERNAL_STRING_VIEW_CXX14_CONSTEXPR void remove_prefix(size_type n)
Definition: abseil-cpp/absl/strings/string_view.h:344
ret
UniquePtr< SSL_SESSION > ret
Definition: ssl_x509.cc:1029
nsyms
static int nsyms(symset s)
Definition: gen_hpack_tables.cc:68
std
Definition: grpcpp/impl/codegen/async_unary_call.h:407
string_view
absl::string_view string_view
Definition: attr.cc:22
bloaty::ReadNullTerminated
absl::string_view ReadNullTerminated(absl::string_view *data)
Definition: third_party/bloaty/src/util.cc:26
bloaty::DisassemblyInfo
Definition: bloaty.h:317
bloaty::macho::LoadCommand::command_data
string_view command_data
Definition: macho.cc:75
bloaty::macho::ParseMachOHeader
void ParseMachOHeader(string_view macho_file, RangeSink *overhead_sink, Func &&loadcmd_func)
Definition: macho.cc:118
bloaty::TryOpenMachOFile
std::unique_ptr< ObjectFile > TryOpenMachOFile(std::unique_ptr< InputFile > &file)
Definition: macho.cc:610
FAT_MAGIC
#define FAT_MAGIC
Definition: fat.h:47
bloaty::macho::ParseLoadCommand
void ParseLoadCommand(const LoadCommand &cmd, RangeSink *sink)
Definition: macho.cc:357
bloaty::SymbolTable
std::map< absl::string_view, std::pair< uint64_t, uint64_t > > SymbolTable
Definition: bloaty.h:253
relocation_info
Definition: reloc.h:64
loader.h
LC_DYLD_INFO
#define LC_DYLD_INFO
Definition: loader.h:224
fat.h
table
uint8_t table[256]
Definition: hpack_parser.cc:456
util.h
MH_CIGAM
#define MH_CIGAM
Definition: loader.h:59
section::offset
uint32_t offset
Definition: loader.h:342
strnlen
size_t strnlen(const char *str, size_t maxlen)
Definition: os390-syscalls.c:554
WARN
#define WARN(...)
Definition: bloaty/src/util.h:47
bloaty::macho::LoadCommand
Definition: macho.cc:72
MH_CIGAM_64
#define MH_CIGAM_64
Definition: loader.h:78
header_data
std::string header_data
Definition: rls.cc:253
bloaty::macho::MachOObjectFile::MachOObjectFile
MachOObjectFile(std::unique_ptr< InputFile > file_data)
Definition: macho.cc:542
size
voidpf void uLong size
Definition: bloaty/third_party/zlib/contrib/minizip/ioapi.h:136
bloaty::macho::LoadCommand::file_data
string_view file_data
Definition: macho.cc:76
LC_SYMTAB
#define LC_SYMTAB
Definition: loader.h:185
bloaty::macho::ParseLoadCommands
void ParseLoadCommands(RangeSink *sink)
Definition: macho.cc:396
bloaty::macho::ParseDynamicSymbolTable
static void ParseDynamicSymbolTable(const LoadCommand &cmd, RangeSink *sink)
Definition: macho.cc:323
LC_DATA_IN_CODE
#define LC_DATA_IN_CODE
Definition: loader.h:232
bloaty::macho::GetStructPointerAndAdvance
const T * GetStructPointerAndAdvance(string_view *data)
Definition: macho.cc:60
bloaty::StrictSubstr
absl::string_view StrictSubstr(absl::string_view data, size_t off, size_t n)
Definition: bloaty/src/util.h:89
bloaty::macho::MachOObjectFile::GetDisassemblyInfo
bool GetDisassemblyInfo(absl::string_view, DataSource, DisassemblyInfo *) const override
Definition: macho.cc:600
bloaty::ReadBytes
absl::string_view ReadBytes(size_t bytes, absl::string_view *data)
Definition: bloaty/src/util.h:165
bloaty::dwarf::File
Definition: debug_info.h:64
absl::string_view::substr
constexpr string_view substr(size_type pos=0, size_type n=npos) const
Definition: abseil-cpp/absl/strings/string_view.h:399
LC_SEGMENT
#define LC_SEGMENT
Definition: loader.h:184
bloaty::InputFile
Definition: bloaty.h:70
bloaty::macho::ParseSymbolsFromSymbolTable
void ParseSymbolsFromSymbolTable(const LoadCommand &cmd, SymbolTable *table, RangeSink *sink)
Definition: macho.cc:403
command
const char * command
Definition: grpc_tool.cc:247
bloaty::RangeSink::AddOutput
void AddOutput(DualMap *map, const NameMunger *munger)
Definition: bloaty.cc:1084
i
uint64_t i
Definition: abseil-cpp/absl/container/btree_benchmark.cc:230
bloaty::macho::LoadCommand::is64bit
bool is64bit
Definition: macho.cc:73
bloaty::ReadDWARFCompileUnits
void ReadDWARFCompileUnits(const dwarf::File &file, const DualMap &map, RangeSink *sink)
Definition: dwarf.cc:630
id
uint32_t id
Definition: flow_control_fuzzer.cc:70
bloaty::macho::ReadMagic
uint32_t ReadMagic(string_view data)
Definition: macho.cc:42
bloaty::DataSource::kSections
@ kSections
bloaty::ByteSwap
constexpr T ByteSwap(T val)
Definition: bloaty/src/util.h:133


grpc
Author(s):
autogenerated on Fri May 16 2025 02:59:17