Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/bloaty.cc
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ struct DataSourceDefinition {

constexpr DataSourceDefinition data_sources[] = {
{DataSource::kArchiveMembers, "armembers", "the .o files in a .a file"},
{DataSource::kArchs, "archs", "architecture slices in universal binaries"},
{DataSource::kCompileUnits, "compileunits",
"source file for the .o file (translation unit). requires debug info."},
{DataSource::kInputFiles, "inputfiles",
Expand Down
1 change: 1 addition & 0 deletions src/bloaty.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ enum class DataSource {
kRawRanges,
kSections,
kSegments,
kArchs,

// We always set this to one of the concrete symbol types below before
// setting it on a sink.
Expand Down
2 changes: 2 additions & 0 deletions src/elf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,8 @@ class ElfObjectFile : public ObjectFile {
DoReadELFSections(sink, kReportByEscapedSectionName);
break;
}
case DataSource::kArchs:
THROW("ELF files do not support 'archs' data source");
default:
THROW("unknown data source");
}
Expand Down
84 changes: 84 additions & 0 deletions src/macho.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <string_view>

#include "absl/strings/str_join.h"
#include "absl/strings/str_format.h"
#include "absl/strings/substitute.h"
#include "third_party/darwin_xnu_macho/mach-o/loader.h"
#include "third_party/darwin_xnu_macho/mach-o/fat.h"
Expand Down Expand Up @@ -69,6 +70,57 @@ void MaybeAddOverhead(RangeSink* sink, const char* label, string_view data) {
}
}

// ARM64E capability field constants
static constexpr uint32_t ARM64E_SUBTYPE_MASK = 0x00FFFFFF; // Low 24 bits: subtype proper

static bool IsArm64eSubtype(uint32_t cpusubtype) {
uint32_t subtype_proper = cpusubtype & ARM64E_SUBTYPE_MASK;
return subtype_proper == CPU_SUBTYPE_ARM64E;
}

std::string CpuTypeToString(uint32_t cputype, uint32_t cpusubtype) {
switch (cputype) {
case CPU_TYPE_X86_64:
switch (cpusubtype) {
case CPU_SUBTYPE_X86_64_H:
return "x86_64h";
default:
return "x86_64";
}
case CPU_TYPE_ARM64:
if (IsArm64eSubtype(cpusubtype)) {
return "arm64e";
}
switch (cpusubtype) {
case CPU_SUBTYPE_ARM64_V8:
return "arm64v8";
default:
return "arm64";
}
case CPU_TYPE_X86:
return "i386";
case CPU_TYPE_ARM:
switch (cpusubtype) {
case CPU_SUBTYPE_ARM_V6:
return "armv6";
case CPU_SUBTYPE_ARM_V7:
return "armv7";
case CPU_SUBTYPE_ARM_V7F:
return "armv7f";
case CPU_SUBTYPE_ARM_V7S:
return "armv7s";
case CPU_SUBTYPE_ARM_V7K:
return "armv7k";
case CPU_SUBTYPE_ARM_V8:
return "armv8";
default:
return "arm";
}
default:
return absl::StrFormat("cpu_%d", cputype);
}
}

struct LoadCommand {
bool is64bit;
uint32_t cmd;
Expand Down Expand Up @@ -619,6 +671,10 @@ class MachOObjectFile : public ObjectFile {
ReadDWARFInlines(dwarf, sink, true);
break;
}
case DataSource::kArchs: {
ProcessArchitectures(sink);
break;
}
case DataSource::kArchiveMembers:
default:
THROW("Mach-O doesn't support this data source");
Expand All @@ -627,6 +683,34 @@ class MachOObjectFile : public ObjectFile {
}
}

void ProcessArchitectures(RangeSink* sink) const {
uint32_t magic = ReadMagic(file_data().data());

if (magic == FAT_CIGAM) {
string_view header_data = file_data().data();
auto header = GetStructPointerAndAdvance<fat_header>(&header_data);
uint32_t nfat_arch = ByteSwap(header->nfat_arch);

for (uint32_t i = 0; i < nfat_arch; i++) {
auto arch = GetStructPointerAndAdvance<fat_arch>(&header_data);
uint32_t cputype = ByteSwap(arch->cputype);
uint32_t cpusubtype = ByteSwap(arch->cpusubtype);
uint32_t offset = ByteSwap(arch->offset);
uint32_t size = ByteSwap(arch->size);

std::string arch_name = CpuTypeToString(cputype, cpusubtype);
string_view slice_data = StrictSubstr(file_data().data(), offset, size);

sink->AddFileRange("archs", arch_name, slice_data);
}
} else {
auto header = GetStructPointer<mach_header>(file_data().data());
std::string arch_name = CpuTypeToString(header->cputype, header->cpusubtype);

sink->AddFileRange("archs", arch_name, file_data().data());
}
}

bool GetDisassemblyInfo(std::string_view /*symbol*/,
DataSource /*symbol_source*/,
DisassemblyInfo* /*info*/) const override {
Expand Down
Loading