aboutsummaryrefslogtreecommitdiff
path: root/src/common/mac
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/mac')
-rw-r--r--src/common/mac/arch_utilities.cc256
-rw-r--r--src/common/mac/arch_utilities.h26
-rw-r--r--src/common/mac/bootstrap_compat.cc4
-rw-r--r--src/common/mac/dump_syms.cc201
-rw-r--r--src/common/mac/dump_syms.h56
-rw-r--r--src/common/mac/file_id.cc4
-rw-r--r--src/common/mac/launch_reporter.cc4
-rw-r--r--src/common/mac/macho_id.cc4
-rw-r--r--src/common/mac/macho_reader.cc4
-rw-r--r--src/common/mac/macho_reader_unittest.cc4
-rw-r--r--src/common/mac/macho_utilities.cc4
-rw-r--r--src/common/mac/macho_walker.cc13
-rw-r--r--src/common/mac/string_utilities.cc4
13 files changed, 285 insertions, 299 deletions
diff --git a/src/common/mac/arch_utilities.cc b/src/common/mac/arch_utilities.cc
index 392efe78..96340d54 100644
--- a/src/common/mac/arch_utilities.cc
+++ b/src/common/mac/arch_utilities.cc
@@ -26,113 +26,22 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/mac/arch_utilities.h"
+#include <mach/machine.h>
#include <mach-o/arch.h>
#include <mach-o/fat.h>
#include <stdio.h>
#include <string.h>
-#ifndef CPU_SUBTYPE_ARM_V7S
-#define CPU_SUBTYPE_ARM_V7S (static_cast<cpu_subtype_t>(11))
-#endif // CPU_SUBTYPE_ARM_V7S
-
-#ifndef CPU_TYPE_ARM64
-#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
-#endif // CPU_TYPE_ARM64
-
-#ifndef CPU_SUBTYPE_ARM64_ALL
-#define CPU_SUBTYPE_ARM64_ALL (static_cast<cpu_subtype_t>(0))
-#endif // CPU_SUBTYPE_ARM64_ALL
-
-#ifndef CPU_SUBTYPE_ARM64_E
-#define CPU_SUBTYPE_ARM64_E (static_cast<cpu_subtype_t>(2))
-#endif // CPU_SUBTYPE_ARM64_E
-
-namespace {
-
-const NXArchInfo* ArchInfo_arm64(cpu_subtype_t cpu_subtype) {
- const char* name = NULL;
- switch (cpu_subtype) {
- case CPU_SUBTYPE_ARM64_ALL:
- name = "arm64";
- break;
- case CPU_SUBTYPE_ARM64_E:
- name = "arm64e";
- break;
- default:
- return NULL;
- }
-
- NXArchInfo* arm64 = new NXArchInfo;
- *arm64 = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM,
- CPU_SUBTYPE_ARM_V7);
- arm64->name = name;
- arm64->cputype = CPU_TYPE_ARM64;
- arm64->cpusubtype = cpu_subtype;
- arm64->description = "arm 64";
- return arm64;
-}
-
-const NXArchInfo* ArchInfo_armv7s() {
- NXArchInfo* armv7s = new NXArchInfo;
- *armv7s = *NXGetArchInfoFromCpuType(CPU_TYPE_ARM,
- CPU_SUBTYPE_ARM_V7);
- armv7s->name = "armv7s";
- armv7s->cpusubtype = CPU_SUBTYPE_ARM_V7S;
- armv7s->description = "arm v7s";
- return armv7s;
-}
-
-} // namespace
-
-namespace google_breakpad {
-
-const NXArchInfo* BreakpadGetArchInfoFromName(const char* arch_name) {
- // TODO: Remove this when the OS knows about arm64.
- if (!strcmp("arm64", arch_name))
- return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM64,
- CPU_SUBTYPE_ARM64_ALL);
-
- if (!strcmp("arm64e", arch_name))
- return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM64,
- CPU_SUBTYPE_ARM64_E);
-
- // TODO: Remove this when the OS knows about armv7s.
- if (!strcmp("armv7s", arch_name))
- return BreakpadGetArchInfoFromCpuType(CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S);
-
- return NXGetArchInfoFromName(arch_name);
-}
-
-const NXArchInfo* BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype) {
- // TODO: Remove this when the OS knows about arm64.
- if (cpu_type == CPU_TYPE_ARM64 && cpu_subtype == CPU_SUBTYPE_ARM64_ALL) {
- static const NXArchInfo* arm64 = ArchInfo_arm64(cpu_subtype);
- return arm64;
- }
-
- if (cpu_type == CPU_TYPE_ARM64 && cpu_subtype == CPU_SUBTYPE_ARM64_E) {
- static const NXArchInfo* arm64e = ArchInfo_arm64(cpu_subtype);
- return arm64e;
- }
-
- // TODO: Remove this when the OS knows about armv7s.
- if (cpu_type == CPU_TYPE_ARM && cpu_subtype == CPU_SUBTYPE_ARM_V7S) {
- static const NXArchInfo* armv7s = ArchInfo_armv7s();
- return armv7s;
- }
-
- return NXGetArchInfoFromCpuType(cpu_type, cpu_subtype);
-}
-
-} // namespace google_breakpad
+#ifdef __APPLE__
+#include <mach-o/utils.h>
+#endif
-// TODO(crbug.com/1242776): The "#ifndef __APPLE__" should be here, but the
-// system version of NXGetLocalArchInfo returns incorrect information on
-// x86_64 machines (treating them as just x86), so use the Breakpad version
-// all the time for now.
namespace {
enum Architecture {
@@ -147,69 +56,31 @@ enum Architecture {
kNumArchitectures
};
+struct NamedArchInfo {
+ const char* name;
+ ArchInfo info;
+};
+
// enum Architecture above and kKnownArchitectures below
// must be kept in sync.
-const NXArchInfo kKnownArchitectures[] = {
- {
- "i386",
- CPU_TYPE_I386,
- CPU_SUBTYPE_I386_ALL,
- NX_LittleEndian,
- "Intel 80x86"
- },
- {
- "x86_64",
- CPU_TYPE_X86_64,
- CPU_SUBTYPE_X86_64_ALL,
- NX_LittleEndian,
- "Intel x86-64"
- },
- {
- "x86_64h",
- CPU_TYPE_X86_64,
- CPU_SUBTYPE_X86_64_H,
- NX_LittleEndian,
- "Intel x86-64h Haswell"
- },
- {
- "arm",
- CPU_TYPE_ARM,
- CPU_SUBTYPE_ARM_ALL,
- NX_LittleEndian,
- "ARM"
- },
- {
- "arm64",
- CPU_TYPE_ARM64,
- CPU_SUBTYPE_ARM64_ALL,
- NX_LittleEndian,
- "ARM64"
- },
- {
- "arm64e",
- CPU_TYPE_ARM64,
- CPU_SUBTYPE_ARM64_E,
- NX_LittleEndian,
- "ARM64e"
- },
- {
- "ppc",
- CPU_TYPE_POWERPC,
- CPU_SUBTYPE_POWERPC_ALL,
- NX_BigEndian,
- "PowerPC"
- }
-};
+constexpr NamedArchInfo kKnownArchitectures[] = {
+ {"i386", {CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL}},
+ {"x86_64", {CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL}},
+ {"x86_64h", {CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_H}},
+ {"arm", {CPU_TYPE_ARM, CPU_SUBTYPE_ARM_ALL}},
+ {"arm64", {CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL}},
+ {"arm64e", {CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E}},
+ {"ppc", {CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL}}};
} // namespace
-const NXArchInfo *NXGetLocalArchInfo(void) {
+ArchInfo GetLocalArchInfo(void) {
Architecture arch;
#if defined(__i386__)
arch = kArch_i386;
#elif defined(__x86_64__)
arch = kArch_x86_64;
-#elif defined(__arm64)
+#elif defined(__arm64__) || defined(__aarch64__)
arch = kArch_arm64;
#elif defined(__arm__)
arch = kArch_arm;
@@ -218,51 +89,72 @@ const NXArchInfo *NXGetLocalArchInfo(void) {
#else
#error "Unsupported CPU architecture"
#endif
- return &kKnownArchitectures[arch];
+ return kKnownArchitectures[arch].info;
}
-#ifndef __APPLE__
+#ifdef __APPLE__
-const NXArchInfo *NXGetArchInfoFromName(const char *name) {
- for (int arch = 0; arch < kNumArchitectures; ++arch) {
- if (!strcmp(name, kKnownArchitectures[arch].name)) {
- return &kKnownArchitectures[arch];
+std::optional<ArchInfo> GetArchInfoFromName(const char* arch_name) {
+ if (__builtin_available(macOS 13.0, iOS 16.0, *)) {
+ cpu_type_t type;
+ cpu_subtype_t subtype;
+ if (macho_cpu_type_for_arch_name(arch_name, &type, &subtype)) {
+ return ArchInfo{type, subtype};
+ }
+ } else {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ const NXArchInfo* info = NXGetArchInfoFromName(arch_name);
+#pragma clang diagnostic pop
+ if (info) {
+ return ArchInfo{info->cputype, info->cpusubtype};
}
}
- return NULL;
+ return std::nullopt;
}
-const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype,
- cpu_subtype_t cpusubtype) {
- const NXArchInfo *candidate = NULL;
+const char* GetNameFromCPUType(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
+ if (__builtin_available(macOS 13.0, iOS 16.0, *)) {
+ const char* name = macho_arch_name_for_cpu_type(cpu_type, cpu_subtype);
+ if (name) {
+ return name;
+ }
+ } else {
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+ const NXArchInfo* info = NXGetArchInfoFromCpuType(cpu_type, cpu_subtype);
+#pragma clang diagnostic pop
+ if (info) {
+ return info->name;
+ }
+ }
+
+ return kUnknownArchName;
+}
+
+#else
+
+std::optional<ArchInfo> GetArchInfoFromName(const char* arch_name) {
for (int arch = 0; arch < kNumArchitectures; ++arch) {
- if (kKnownArchitectures[arch].cputype == cputype) {
- if (kKnownArchitectures[arch].cpusubtype == cpusubtype) {
- return &kKnownArchitectures[arch];
- }
- if (!candidate) {
- candidate = &kKnownArchitectures[arch];
- }
+ if (!strcmp(arch_name, kKnownArchitectures[arch].name)) {
+ return kKnownArchitectures[arch].info;
}
}
- return candidate;
+ return std::nullopt;
}
-struct fat_arch *NXFindBestFatArch(cpu_type_t cputype,
- cpu_subtype_t cpusubtype,
- struct fat_arch *fat_archs,
- uint32_t nfat_archs) {
- struct fat_arch *candidate = NULL;
- for (uint32_t f = 0; f < nfat_archs; ++f) {
- if (fat_archs[f].cputype == cputype) {
- if (fat_archs[f].cpusubtype == cpusubtype) {
- return &fat_archs[f];
+const char* GetNameFromCPUType(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
+ const char* candidate = kUnknownArchName;
+ for (int arch = 0; arch < kNumArchitectures; ++arch) {
+ if (kKnownArchitectures[arch].info.cputype == cpu_type) {
+ if (kKnownArchitectures[arch].info.cpusubtype == cpu_subtype) {
+ return kKnownArchitectures[arch].name;
}
- if (!candidate) {
- candidate = &fat_archs[f];
+ if (!strcmp(candidate, kUnknownArchName)) {
+ candidate = kKnownArchitectures[arch].name;
}
}
}
return candidate;
}
-#endif // !__APPLE__
+#endif // __APPLE__
diff --git a/src/common/mac/arch_utilities.h b/src/common/mac/arch_utilities.h
index d267c43b..3b036738 100644
--- a/src/common/mac/arch_utilities.h
+++ b/src/common/mac/arch_utilities.h
@@ -31,16 +31,26 @@
#ifndef COMMON_MAC_ARCH_UTILITIES_H__
#define COMMON_MAC_ARCH_UTILITIES_H__
-#include <mach-o/arch.h>
+#include <mach/machine.h>
-namespace google_breakpad {
+#include <optional>
-// Custom implementation of |NXGetArchInfoFromName| and
-// |NXGetArchInfoFromCpuType| that handle newer CPU on older OSes.
-const NXArchInfo* BreakpadGetArchInfoFromName(const char* arch_name);
-const NXArchInfo* BreakpadGetArchInfoFromCpuType(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype);
+static constexpr const char* kUnknownArchName = "<Unknown architecture>";
-} // namespace google_breakpad
+struct ArchInfo {
+ cpu_type_t cputype;
+ cpu_subtype_t cpusubtype;
+};
+
+// Returns architecture info if `arch_name` corresponds to a valid, known
+// architecture, and std::nullopt otherwise.
+std::optional<ArchInfo> GetArchInfoFromName(const char* arch_name);
+
+// Returns the name of the architecture specified by `cpu_type` and
+// `cpu_subtype`, or `kUnknownArchName` if it's unknown or invalid.
+const char* GetNameFromCPUType(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);
+
+// Returns the architecture of the machine this code is running on.
+ArchInfo GetLocalArchInfo();
#endif // COMMON_MAC_ARCH_UTILITIES_H__
diff --git a/src/common/mac/bootstrap_compat.cc b/src/common/mac/bootstrap_compat.cc
index 6647bae3..408589ba 100644
--- a/src/common/mac/bootstrap_compat.cc
+++ b/src/common/mac/bootstrap_compat.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/mac/bootstrap_compat.h"
namespace breakpad {
diff --git a/src/common/mac/dump_syms.cc b/src/common/mac/dump_syms.cc
index 9658b2c6..c06945e4 100644
--- a/src/common/mac/dump_syms.cc
+++ b/src/common/mac/dump_syms.cc
@@ -32,6 +32,10 @@
// dump_syms.cc: Create a symbol file for use with minidumps
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/mac/dump_syms.h"
#include <assert.h>
@@ -217,11 +221,10 @@ bool DumpSymbols::ReadData(uint8_t* contents, size_t size,
return true;
}
-bool DumpSymbols::SetArchitecture(cpu_type_t cpu_type,
- cpu_subtype_t cpu_subtype) {
+bool DumpSymbols::SetArchitecture(const ArchInfo& info) {
// Find the best match for the architecture the user requested.
- const SuperFatArch* best_match = FindBestMatchForArchitecture(
- cpu_type, cpu_subtype);
+ const SuperFatArch* best_match =
+ FindBestMatchForArchitecture(info.cputype, info.cpusubtype);
if (!best_match) return false;
// Record the selected object file.
@@ -229,70 +232,37 @@ bool DumpSymbols::SetArchitecture(cpu_type_t cpu_type,
return true;
}
-bool DumpSymbols::SetArchitecture(const std::string& arch_name) {
- bool arch_set = false;
- const NXArchInfo* arch_info =
- google_breakpad::BreakpadGetArchInfoFromName(arch_name.c_str());
- if (arch_info) {
- arch_set = SetArchitecture(arch_info->cputype, arch_info->cpusubtype);
- }
- return arch_set;
-}
SuperFatArch* DumpSymbols::FindBestMatchForArchitecture(
- cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
- // Check if all the object files can be converted to struct fat_arch.
- bool can_convert_to_fat_arch = true;
- vector<struct fat_arch> fat_arch_vector;
- for (vector<SuperFatArch>::const_iterator it = object_files_.begin();
- it != object_files_.end();
- ++it) {
- struct fat_arch arch;
- bool success = it->ConvertToFatArch(&arch);
- if (!success) {
- can_convert_to_fat_arch = false;
- break;
- }
- fat_arch_vector.push_back(arch);
- }
-
- // If all the object files can be converted to struct fat_arch, use
- // NXFindBestFatArch.
- if (can_convert_to_fat_arch) {
- const struct fat_arch* best_match
- = NXFindBestFatArch(cpu_type, cpu_subtype, &fat_arch_vector[0],
- static_cast<uint32_t>(fat_arch_vector.size()));
-
- for (size_t i = 0; i < fat_arch_vector.size(); ++i) {
- if (best_match == &fat_arch_vector[i])
- return &object_files_[i];
+ cpu_type_t cpu_type,
+ cpu_subtype_t cpu_subtype) {
+ SuperFatArch* closest_match = nullptr;
+ for (auto& object_file : object_files_) {
+ if (static_cast<cpu_type_t>(object_file.cputype) == cpu_type) {
+ // If there's an exact match, return it directly.
+ if ((static_cast<cpu_subtype_t>(object_file.cpusubtype) &
+ ~CPU_SUBTYPE_MASK) == (cpu_subtype & ~CPU_SUBTYPE_MASK)) {
+ return &object_file;
+ }
+ // Otherwise, hold on to this as the closest match since at least the CPU
+ // type matches.
+ if (!closest_match) {
+ closest_match = &object_file;
+ }
}
- assert(best_match == NULL);
- // Fall through since NXFindBestFatArch can't find arm slices on x86_64
- // macOS 13. See FB11955188.
}
-
- // Check for an exact match with cpu_type and cpu_subtype.
- for (vector<SuperFatArch>::iterator it = object_files_.begin();
- it != object_files_.end();
- ++it) {
- if (static_cast<cpu_type_t>(it->cputype) == cpu_type &&
- (static_cast<cpu_subtype_t>(it->cpusubtype) & ~CPU_SUBTYPE_MASK) ==
- (cpu_subtype & ~CPU_SUBTYPE_MASK))
- return &*it;
- }
-
// No exact match found.
- // TODO(erikchen): If it becomes necessary, we can copy the implementation of
- // NXFindBestFatArch, located at
- // http://web.mit.edu/darwin/src/modules/cctools/libmacho/arch.c.
- fprintf(stderr, "Failed to find an exact match for an object file with cpu "
- "type: %d and cpu subtype: %d.\n", cpu_type, cpu_subtype);
- if (!can_convert_to_fat_arch) {
- fprintf(stderr, "Furthermore, at least one object file is larger "
- "than 2**32.\n");
+ fprintf(stderr,
+ "Failed to find an exact match for an object file with cpu "
+ "type: %d and cpu subtype: %d.\n",
+ cpu_type, cpu_subtype);
+ if (closest_match) {
+ fprintf(stderr, "Using %s as the closest match.\n",
+ GetNameFromCPUType(closest_match->cputype,
+ closest_match->cpusubtype));
+ return closest_match;
}
- return NULL;
+ return nullptr;
}
string DumpSymbols::Identifier() {
@@ -398,8 +368,8 @@ bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) {
selected_object_file_ = &object_files_[0];
else {
// Look for an object file whose architecture matches our own.
- const NXArchInfo* local_arch = NXGetLocalArchInfo();
- if (!SetArchitecture(local_arch->cputype, local_arch->cpusubtype)) {
+ ArchInfo local_arch = GetLocalArchInfo();
+ if (!SetArchitecture(local_arch)) {
fprintf(stderr, "%s: object file contains more than one"
" architecture, none of which match the current"
" architecture; specify an architecture explicitly"
@@ -414,18 +384,16 @@ bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) {
// Find the name of the selected file's architecture, to appear in
// the MODULE record and in error messages.
- const NXArchInfo* selected_arch_info =
- google_breakpad::BreakpadGetArchInfoFromCpuType(
- selected_object_file_->cputype, selected_object_file_->cpusubtype);
+ const char* selected_arch_name = GetNameFromCPUType(
+ selected_object_file_->cputype, selected_object_file_->cpusubtype);
// In certain cases, it is possible that architecture info can't be reliably
// determined, e.g. new architectures that breakpad is unware of. In that
// case, avoid crashing and return false instead.
- if (selected_arch_info == NULL) {
+ if (selected_arch_name == kUnknownArchName) {
return false;
}
- const char* selected_arch_name = selected_arch_info->name;
if (strcmp(selected_arch_name, "i386") == 0)
selected_arch_name = "x86";
@@ -438,7 +406,12 @@ bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) {
}
// Compute a module name, to appear in the MODULE record.
- string module_name = google_breakpad::BaseName(object_filename_);
+ string module_name;
+ if (!module_name_.empty()) {
+ module_name = module_name_;
+ } else {
+ module_name = google_breakpad::BaseName(object_filename_);
+ }
// Choose an identifier string, to appear in the MODULE record.
string identifier = Identifier();
@@ -447,18 +420,71 @@ bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) {
// Create a module to hold the debugging information.
module.reset(new Module(module_name, "mac", selected_arch_name, identifier,
- "", enable_multiple_));
+ "", enable_multiple_, prefer_extern_name_));
return true;
}
+void DumpSymbols::StartProcessSplitDwarf(
+ google_breakpad::CompilationUnit* reader,
+ Module* module,
+ google_breakpad::Endianness endianness,
+ bool handle_inter_cu_refs,
+ bool handle_inline) const {
+ std::string split_file;
+ google_breakpad::SectionMap split_sections;
+ google_breakpad::ByteReader split_byte_reader(endianness);
+ uint64_t cu_offset = 0;
+ if (reader->ProcessSplitDwarf(split_file, split_sections, split_byte_reader,
+ cu_offset))
+ return;
+ DwarfCUToModule::FileContext file_context(split_file, module,
+ handle_inter_cu_refs);
+ for (auto section : split_sections)
+ file_context.AddSectionToSectionMap(section.first, section.second.first,
+ section.second.second);
+ // Because DWP/DWO file doesn't have .debug_addr/.debug_line/.debug_line_str,
+ // its debug info will refer to .debug_addr/.debug_line in the main binary.
+ if (file_context.section_map().find(".debug_addr") ==
+ file_context.section_map().end())
+ file_context.AddSectionToSectionMap(".debug_addr", reader->GetAddrBuffer(),
+ reader->GetAddrBufferLen());
+ if (file_context.section_map().find(".debug_line") ==
+ file_context.section_map().end())
+ file_context.AddSectionToSectionMap(".debug_line", reader->GetLineBuffer(),
+ reader->GetLineBufferLen());
+ if (file_context.section_map().find(".debug_line_str") ==
+ file_context.section_map().end())
+ file_context.AddSectionToSectionMap(".debug_line_str",
+ reader->GetLineStrBuffer(),
+ reader->GetLineStrBufferLen());
+ DumperRangesHandler ranges_handler(&split_byte_reader);
+ DumperLineToModule line_to_module(&split_byte_reader);
+ DwarfCUToModule::WarningReporter reporter(split_file, cu_offset);
+ DwarfCUToModule root_handler(
+ &file_context, &line_to_module, &ranges_handler, &reporter, handle_inline,
+ reader->GetLowPC(), reader->GetAddrBase(), reader->HasSourceLineInfo(),
+ reader->GetSourceLineOffset());
+ google_breakpad::DIEDispatcher die_dispatcher(&root_handler);
+ google_breakpad::CompilationUnit split_reader(
+ split_file, file_context.section_map(), cu_offset, &split_byte_reader,
+ &die_dispatcher);
+ split_reader.SetSplitDwarf(reader->GetAddrBase(), reader->GetDWOID());
+ split_reader.Start();
+ // Normally, it won't happen unless we have transitive reference.
+ if (split_reader.ShouldProcessSplitDwarf()) {
+ StartProcessSplitDwarf(&split_reader, module, endianness,
+ handle_inter_cu_refs, handle_inline);
+ }
+}
+
void DumpSymbols::ReadDwarf(google_breakpad::Module* module,
const mach_o::Reader& macho_reader,
const mach_o::SectionMap& dwarf_sections,
bool handle_inter_cu_refs) const {
// Build a byte reader of the appropriate endianness.
- ByteReader byte_reader(macho_reader.big_endian()
- ? ENDIANNESS_BIG
- : ENDIANNESS_LITTLE);
+ google_breakpad::Endianness endianness =
+ macho_reader.big_endian() ? ENDIANNESS_BIG : ENDIANNESS_LITTLE;
+ ByteReader byte_reader(endianness);
// Construct a context for this file.
DwarfCUToModule::FileContext file_context(selected_object_name_,
@@ -494,14 +520,14 @@ void DumpSymbols::ReadDwarf(google_breakpad::Module* module,
// Walk the __debug_info section, one compilation unit at a time.
uint64_t debug_info_length = debug_info_section.second;
+ bool handle_inline = symbol_data_ & INLINES;
for (uint64_t offset = 0; offset < debug_info_length;) {
// Make a handler for the root DIE that populates MODULE with the
// debug info.
DwarfCUToModule::WarningReporter reporter(selected_object_name_,
offset);
DwarfCUToModule root_handler(&file_context, &line_to_module,
- &ranges_handler, &reporter,
- symbol_data_ & INLINES);
+ &ranges_handler, &reporter, handle_inline);
// Make a Dwarf2Handler that drives our DIEHandler.
DIEDispatcher die_dispatcher(&root_handler);
// Make a DWARF parser for the compilation unit at OFFSET.
@@ -512,6 +538,11 @@ void DumpSymbols::ReadDwarf(google_breakpad::Module* module,
&die_dispatcher);
// Process the entire compilation unit; get the offset of the next.
offset += dwarf_reader.Start();
+ // Start to process split dwarf file.
+ if (dwarf_reader.ShouldProcessSplitDwarf()) {
+ StartProcessSplitDwarf(&dwarf_reader, module, endianness,
+ handle_inter_cu_refs, handle_inline);
+ }
}
}
@@ -536,16 +567,14 @@ bool DumpSymbols::ReadCFI(google_breakpad::Module* module,
register_names = DwarfCFIToModule::RegisterNames::ARM64();
break;
default: {
- const NXArchInfo* arch = google_breakpad::BreakpadGetArchInfoFromCpuType(
- macho_reader.cpu_type(), macho_reader.cpu_subtype());
- fprintf(stderr, "%s: cannot convert DWARF call frame information for ",
- selected_object_name_.c_str());
- if (arch)
- fprintf(stderr, "architecture '%s'", arch->name);
- else
- fprintf(stderr, "architecture %d,%d",
- macho_reader.cpu_type(), macho_reader.cpu_subtype());
- fprintf(stderr, " to Breakpad symbol file: no register name table\n");
+ const char* arch_name = GetNameFromCPUType(macho_reader.cpu_type(),
+ macho_reader.cpu_subtype());
+ fprintf(
+ stderr,
+ "%s: cannot convert DWARF call frame information for architecture "
+ "'%s' (%d, %d) to Breakpad symbol file: no register name table\n",
+ selected_object_name_.c_str(), arch_name, macho_reader.cpu_type(),
+ macho_reader.cpu_subtype());
return false;
}
}
diff --git a/src/common/mac/dump_syms.h b/src/common/mac/dump_syms.h
index c2e1b40b..5ccf49e3 100644
--- a/src/common/mac/dump_syms.h
+++ b/src/common/mac/dump_syms.h
@@ -43,6 +43,8 @@
#include <vector>
#include "common/byte_cursor.h"
+#include "common/dwarf/dwarf2reader.h"
+#include "common/mac/arch_utilities.h"
#include "common/mac/macho_reader.h"
#include "common/mac/super_fat_arch.h"
#include "common/module.h"
@@ -55,7 +57,9 @@ class DumpSymbols {
public:
DumpSymbols(SymbolData symbol_data,
bool handle_inter_cu_refs,
- bool enable_multiple = false)
+ bool enable_multiple = false,
+ const std::string& module_name = "",
+ bool prefer_extern_name = false)
: symbol_data_(symbol_data),
handle_inter_cu_refs_(handle_inter_cu_refs),
object_filename_(),
@@ -65,12 +69,19 @@ class DumpSymbols {
object_files_(),
selected_object_file_(),
selected_object_name_(),
- enable_multiple_(enable_multiple) {}
+ enable_multiple_(enable_multiple),
+ module_name_(module_name),
+ prefer_extern_name_(prefer_extern_name) {}
~DumpSymbols() = default;
// Prepare to read debugging information from |filename|. |filename| may be
// the name of a fat file, a Mach-O file, or a dSYM bundle containing either
- // of the above. On success, return true; if there is a problem reading
+ // of the above.
+ //
+ // If |module_name_| is empty, uses the basename of |filename| as the module
+ // name. Otherwise, uses |module_name_| as the module name.
+ //
+ // On success, return true; if there is a problem reading
// |filename|, report it and return false.
bool Read(const std::string& filename);
@@ -82,26 +93,15 @@ class DumpSymbols {
// problem reading |contents|, report it and return false.
bool ReadData(uint8_t* contents, size_t size, const std::string& filename);
- // If this dumper's file includes an object file for |cpu_type| and
- // |cpu_subtype|, then select that object file for dumping, and return
- // true. Otherwise, return false, and leave this dumper's selected
- // architecture unchanged.
- //
- // By default, if this dumper's file contains only one object file, then
- // the dumper will dump those symbols; and if it contains more than one
- // object file, then the dumper will dump the object file whose
- // architecture matches that of this dumper program.
- bool SetArchitecture(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype);
-
- // If this dumper's file includes an object file for |arch_name|, then select
- // that object file for dumping, and return true. Otherwise, return false,
- // and leave this dumper's selected architecture unchanged.
+ // If this dumper's file includes an object file for `info`, then select that
+ // object file for dumping, and return true. Otherwise, return false, and
+ // leave this dumper's selected architecture unchanged.
//
// By default, if this dumper's file contains only one object file, then
// the dumper will dump those symbols; and if it contains more than one
// object file, then the dumper will dump the object file whose
// architecture matches that of this dumper program.
- bool SetArchitecture(const std::string& arch_name);
+ bool SetArchitecture(const ArchInfo& info);
// Return a pointer to an array of SuperFatArch structures describing the
// object files contained in this dumper's file. Set *|count| to the number
@@ -144,6 +144,13 @@ class DumpSymbols {
// Creates an empty module object.
bool CreateEmptyModule(scoped_ptr<Module>& module);
+ // Process the split dwarf file referenced by reader.
+ void StartProcessSplitDwarf(google_breakpad::CompilationUnit* reader,
+ Module* module,
+ google_breakpad::Endianness endianness,
+ bool handle_inter_cu_refs,
+ bool handle_inline) const;
+
// Read debugging information from |dwarf_sections|, which was taken from
// |macho_reader|, and add it to |module|.
void ReadDwarf(google_breakpad::Module* module,
@@ -204,6 +211,19 @@ class DumpSymbols {
// See: https://crbug.com/google-breakpad/751 and docs at
// docs/symbol_files.md#records-3
bool enable_multiple_;
+
+ // If non-empty, used as the module name. Otherwise, the basename of
+ // |object_filename_| is used as the module name.
+ const std::string module_name_;
+
+ // If a Function and an Extern share the same address but have a different
+ // name, prefer the name of the Extern.
+ //
+ // Use this when dumping Mach-O .dSYMs built with -gmlt (Minimum Line Tables),
+ // as the Function's fully-qualified name will only be present in the STABS
+ // (which are placed in the Extern), not in the DWARF symbols (which are
+ // placed in the Function).
+ bool prefer_extern_name_;
};
} // namespace google_breakpad
diff --git a/src/common/mac/file_id.cc b/src/common/mac/file_id.cc
index a6c1d26f..ee4a66bb 100644
--- a/src/common/mac/file_id.cc
+++ b/src/common/mac/file_id.cc
@@ -32,6 +32,10 @@
//
// Author: Dan Waylonis
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/mac/file_id.h"
#include <fcntl.h>
diff --git a/src/common/mac/launch_reporter.cc b/src/common/mac/launch_reporter.cc
index de554ee3..f6b8aed1 100644
--- a/src/common/mac/launch_reporter.cc
+++ b/src/common/mac/launch_reporter.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
diff --git a/src/common/mac/macho_id.cc b/src/common/mac/macho_id.cc
index e67ccddb..bb0058ce 100644
--- a/src/common/mac/macho_id.cc
+++ b/src/common/mac/macho_id.cc
@@ -33,6 +33,10 @@
// Author: Dan Waylonis
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <fcntl.h>
#include <mach-o/loader.h>
#include <stdio.h>
diff --git a/src/common/mac/macho_reader.cc b/src/common/mac/macho_reader.cc
index 23c809c4..0324be14 100644
--- a/src/common/mac/macho_reader.cc
+++ b/src/common/mac/macho_reader.cc
@@ -31,6 +31,10 @@
// macho_reader.cc: Implementation of google_breakpad::Mach_O::FatReader and
// google_breakpad::Mach_O::Reader. See macho_reader.h for details.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/mac/macho_reader.h"
#include <assert.h>
diff --git a/src/common/mac/macho_reader_unittest.cc b/src/common/mac/macho_reader_unittest.cc
index 3beec341..4b5ac6ca 100644
--- a/src/common/mac/macho_reader_unittest.cc
+++ b/src/common/mac/macho_reader_unittest.cc
@@ -31,6 +31,10 @@
// macho_reader_unittest.cc: Unit tests for google_breakpad::Mach_O::FatReader
// and google_breakpad::Mach_O::Reader.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <map>
#include <string>
#include <vector>
diff --git a/src/common/mac/macho_utilities.cc b/src/common/mac/macho_utilities.cc
index 16e430df..113e8d3f 100644
--- a/src/common/mac/macho_utilities.cc
+++ b/src/common/mac/macho_utilities.cc
@@ -30,6 +30,10 @@
//
// Author: Dave Camp
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/mac/byteswap.h"
#include "common/mac/macho_utilities.h"
diff --git a/src/common/mac/macho_walker.cc b/src/common/mac/macho_walker.cc
index 505a4df1..4b9f56c2 100644
--- a/src/common/mac/macho_walker.cc
+++ b/src/common/mac/macho_walker.cc
@@ -32,17 +32,21 @@
//
// Author: Dan Waylonis
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include <assert.h>
#include <fcntl.h>
-#include <mach-o/arch.h>
#include <mach-o/fat.h>
#include <mach-o/loader.h>
#include <string.h>
#include <unistd.h>
+#include "common/mac/arch_utilities.h"
#include "common/mac/byteswap.h"
-#include "common/mac/macho_walker.h"
#include "common/mac/macho_utilities.h"
+#include "common/mac/macho_walker.h"
namespace MacFileUtilities {
@@ -81,9 +85,8 @@ bool MachoWalker::WalkHeader(cpu_type_t cpu_type, cpu_subtype_t cpu_subtype) {
cpu_subtype_t valid_cpu_subtype = cpu_subtype;
// if |cpu_type| is 0, use the native cpu type.
if (cpu_type == 0) {
- const NXArchInfo* arch = NXGetLocalArchInfo();
- assert(arch);
- valid_cpu_type = arch->cputype;
+ ArchInfo arch = GetLocalArchInfo();
+ valid_cpu_type = arch.cputype;
valid_cpu_subtype = CPU_SUBTYPE_MULTIPLE;
}
off_t offset;
diff --git a/src/common/mac/string_utilities.cc b/src/common/mac/string_utilities.cc
index 861029d4..3b83351f 100644
--- a/src/common/mac/string_utilities.cc
+++ b/src/common/mac/string_utilities.cc
@@ -26,6 +26,10 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#ifdef HAVE_CONFIG_H
+#include <config.h> // Must come first
+#endif
+
#include "common/scoped_ptr.h"
#include "common/mac/string_utilities.h"