aboutsummaryrefslogtreecommitdiff
path: root/externals/breakpad/src/common/mac/dump_syms.cc
diff options
context:
space:
mode:
Diffstat (limited to 'externals/breakpad/src/common/mac/dump_syms.cc')
-rw-r--r--externals/breakpad/src/common/mac/dump_syms.cc726
1 files changed, 0 insertions, 726 deletions
diff --git a/externals/breakpad/src/common/mac/dump_syms.cc b/externals/breakpad/src/common/mac/dump_syms.cc
deleted file mode 100644
index c06945e483..0000000000
--- a/externals/breakpad/src/common/mac/dump_syms.cc
+++ /dev/null
@@ -1,726 +0,0 @@
-// -*- mode: c++ -*-
-
-// Copyright 2011 Google LLC
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-// * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-// * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-// * Neither the name of Google LLC nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// Author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com>
-
-// 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>
-#include <dirent.h>
-#include <errno.h>
-#include <mach-o/arch.h>
-#include <mach-o/fat.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <ostream>
-#include <string>
-#include <vector>
-
-#include "common/dwarf/bytereader-inl.h"
-#include "common/dwarf/dwarf2reader.h"
-#include "common/dwarf_cfi_to_module.h"
-#include "common/dwarf_cu_to_module.h"
-#include "common/dwarf_line_to_module.h"
-#include "common/dwarf_range_list_handler.h"
-#include "common/mac/file_id.h"
-#include "common/mac/arch_utilities.h"
-#include "common/mac/macho_reader.h"
-#include "common/module.h"
-#include "common/path_helper.h"
-#include "common/scoped_ptr.h"
-#include "common/stabs_reader.h"
-#include "common/stabs_to_module.h"
-#include "common/symbol_data.h"
-
-#ifndef CPU_TYPE_ARM
-#define CPU_TYPE_ARM (static_cast<cpu_type_t>(12))
-#endif // CPU_TYPE_ARM
-
-#ifndef CPU_TYPE_ARM64
-#define CPU_TYPE_ARM64 (static_cast<cpu_type_t>(16777228))
-#endif // CPU_TYPE_ARM64
-
-using google_breakpad::ByteReader;
-using google_breakpad::DwarfCUToModule;
-using google_breakpad::DwarfLineToModule;
-using google_breakpad::DwarfRangeListHandler;
-using google_breakpad::mach_o::FatReader;
-using google_breakpad::mach_o::FileID;
-using google_breakpad::mach_o::Section;
-using google_breakpad::mach_o::Segment;
-using google_breakpad::Module;
-using google_breakpad::StabsReader;
-using google_breakpad::StabsToModule;
-using google_breakpad::scoped_ptr;
-using std::make_pair;
-using std::pair;
-using std::string;
-using std::vector;
-
-namespace {
-// Return a vector<string> with absolute paths to all the entries
-// in directory (excluding . and ..).
-vector<string> list_directory(const string& directory) {
- vector<string> entries;
- DIR* dir = opendir(directory.c_str());
- if (!dir) {
- return entries;
- }
-
- string path = directory;
- if (path[path.length() - 1] != '/') {
- path += '/';
- }
-
- struct dirent* entry = NULL;
- while ((entry = readdir(dir))) {
- if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0) {
- entries.push_back(path + entry->d_name);
- }
- }
-
- closedir(dir);
- return entries;
-}
-}
-
-namespace google_breakpad {
-
-bool DumpSymbols::Read(const string& filename) {
- selected_object_file_ = nullptr;
- struct stat st;
- if (stat(filename.c_str(), &st) == -1) {
- fprintf(stderr, "Could not access object file %s: %s\n",
- filename.c_str(), strerror(errno));
- return false;
- }
-
- from_disk_ = true;
-
- // Does this filename refer to a dSYM bundle?
- string contents_path = filename + "/Contents/Resources/DWARF";
- string object_filename;
- if (S_ISDIR(st.st_mode) &&
- access(contents_path.c_str(), F_OK) == 0) {
- // If there's one file under Contents/Resources/DWARF then use that,
- // otherwise bail out.
- const vector<string> entries = list_directory(contents_path);
- if (entries.size() == 0) {
- fprintf(stderr, "Unable to find DWARF-bearing file in bundle: %s\n",
- filename.c_str());
- return false;
- }
- if (entries.size() > 1) {
- fprintf(stderr, "Too many DWARF files in bundle: %s\n",
- filename.c_str());
- return false;
- }
-
- object_filename = entries[0];
- } else {
- object_filename = filename;
- }
-
- // Read the file's contents into memory.
- bool read_ok = true;
- string error;
- scoped_array<uint8_t> contents;
- off_t total = 0;
- if (stat(object_filename.c_str(), &st) != -1) {
- FILE* f = fopen(object_filename.c_str(), "rb");
- if (f) {
- contents.reset(new uint8_t[st.st_size]);
- while (total < st.st_size && !feof(f)) {
- size_t read = fread(&contents[0] + total, 1, st.st_size - total, f);
- if (read == 0) {
- if (ferror(f)) {
- read_ok = false;
- error = strerror(errno);
- }
- break;
- }
- total += read;
- }
- fclose(f);
- } else {
- error = strerror(errno);
- }
- }
-
- if (!read_ok) {
- fprintf(stderr, "Error reading object file: %s: %s\n",
- object_filename.c_str(), error.c_str());
- return false;
- }
- return ReadData(contents.release(), total, object_filename);
-}
-
-bool DumpSymbols::ReadData(uint8_t* contents, size_t size,
- const std::string& filename) {
- contents_.reset(contents);
- size_ = size;
- object_filename_ = filename;
-
- // Get the list of object files present in the file.
- FatReader::Reporter fat_reporter(object_filename_);
- FatReader fat_reader(&fat_reporter);
- if (!fat_reader.Read(contents_.get(), size)) {
- return false;
- }
-
- // Get our own copy of fat_reader's object file list.
- size_t object_files_count;
- const SuperFatArch* object_files =
- fat_reader.object_files(&object_files_count);
- if (object_files_count == 0) {
- fprintf(stderr, "Fat binary file contains *no* architectures: %s\n",
- object_filename_.c_str());
- return false;
- }
- object_files_.resize(object_files_count);
- memcpy(&object_files_[0], object_files,
- sizeof(SuperFatArch) * object_files_count);
-
- return true;
-}
-
-bool DumpSymbols::SetArchitecture(const ArchInfo& info) {
- // Find the best match for the architecture the user requested.
- const SuperFatArch* best_match =
- FindBestMatchForArchitecture(info.cputype, info.cpusubtype);
- if (!best_match) return false;
-
- // Record the selected object file.
- selected_object_file_ = best_match;
- return true;
-}
-
-
-SuperFatArch* DumpSymbols::FindBestMatchForArchitecture(
- 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;
- }
- }
- }
- // No exact match found.
- 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 nullptr;
-}
-
-string DumpSymbols::Identifier() {
- scoped_ptr<FileID> file_id;
-
- if (from_disk_) {
- file_id.reset(new FileID(object_filename_.c_str()));
- } else {
- file_id.reset(new FileID(contents_.get(), size_));
- }
- unsigned char identifier_bytes[16];
- scoped_ptr<Module> module;
- if (!selected_object_file_) {
- if (!CreateEmptyModule(module))
- return string();
- }
- cpu_type_t cpu_type = selected_object_file_->cputype;
- cpu_subtype_t cpu_subtype = selected_object_file_->cpusubtype;
- if (!file_id->MachoIdentifier(cpu_type, cpu_subtype, identifier_bytes)) {
- fprintf(stderr, "Unable to calculate UUID of mach-o binary %s!\n",
- object_filename_.c_str());
- return "";
- }
-
- char identifier_string[40];
- FileID::ConvertIdentifierToString(identifier_bytes, identifier_string,
- sizeof(identifier_string));
-
- string compacted(identifier_string);
- for(size_t i = compacted.find('-'); i != string::npos;
- i = compacted.find('-', i))
- compacted.erase(i, 1);
-
- // The pdb for these IDs has an extra byte, so to make everything uniform put
- // a 0 on the end of mac IDs.
- compacted += "0";
-
- return compacted;
-}
-
-// A range handler that accepts rangelist data parsed by
-// RangeListReader and populates a range vector (typically
-// owned by a function) with the results.
-class DumpSymbols::DumperRangesHandler:
- public DwarfCUToModule::RangesHandler {
- public:
- DumperRangesHandler(ByteReader* reader) :
- reader_(reader) { }
-
- bool ReadRanges(
- enum DwarfForm form, uint64_t data,
- RangeListReader::CURangesInfo* cu_info,
- vector<Module::Range>* ranges) {
- DwarfRangeListHandler handler(ranges);
- RangeListReader range_list_reader(reader_, cu_info,
- &handler);
- return range_list_reader.ReadRanges(form, data);
- }
-
- private:
- ByteReader* reader_;
-};
-
-// A line-to-module loader that accepts line number info parsed by
-// LineInfo and populates a Module and a line vector
-// with the results.
-class DumpSymbols::DumperLineToModule:
- public DwarfCUToModule::LineToModuleHandler {
- public:
- // Create a line-to-module converter using BYTE_READER.
- DumperLineToModule(ByteReader* byte_reader)
- : byte_reader_(byte_reader) { }
-
- void StartCompilationUnit(const string& compilation_dir) {
- compilation_dir_ = compilation_dir;
- }
-
- void ReadProgram(const uint8_t* program,
- uint64_t length,
- const uint8_t* string_section,
- uint64_t string_section_length,
- const uint8_t* line_string_section,
- uint64_t line_string_section_length,
- Module* module,
- vector<Module::Line>* lines,
- std::map<uint32_t, Module::File*>* files) {
- DwarfLineToModule handler(module, compilation_dir_, lines, files);
- LineInfo parser(program, length, byte_reader_, nullptr, 0,
- nullptr, 0, &handler);
- parser.Start();
- }
- private:
- string compilation_dir_;
- ByteReader* byte_reader_; // WEAK
-};
-
-bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) {
- // Select an object file, if SetArchitecture hasn't been called to set one
- // explicitly.
- if (!selected_object_file_) {
- // If there's only one architecture, that's the one.
- if (object_files_.size() == 1)
- selected_object_file_ = &object_files_[0];
- else {
- // Look for an object file whose architecture matches our own.
- 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"
- " with '-a ARCH' to resolve the ambiguity\n",
- object_filename_.c_str());
- return false;
- }
- }
- }
-
- assert(selected_object_file_);
-
- // Find the name of the selected file's architecture, to appear in
- // the MODULE record and in error messages.
- 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_name == kUnknownArchName) {
- return false;
- }
-
- if (strcmp(selected_arch_name, "i386") == 0)
- selected_arch_name = "x86";
-
- // Produce a name to use in error messages that includes the
- // filename, and the architecture, if there is more than one.
- selected_object_name_ = object_filename_;
- if (object_files_.size() > 1) {
- selected_object_name_ += ", architecture ";
- selected_object_name_ + selected_arch_name;
- }
-
- // Compute a module name, to appear in the MODULE record.
- 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();
- if (identifier.empty())
- return false;
-
- // Create a module to hold the debugging information.
- module.reset(new Module(module_name, "mac", selected_arch_name, identifier,
- "", 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.
- 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_,
- module,
- handle_inter_cu_refs);
-
- // Build a SectionMap from our mach_o::SectionMap.
- for (mach_o::SectionMap::const_iterator it = dwarf_sections.begin();
- it != dwarf_sections.end(); ++it) {
- file_context.AddSectionToSectionMap(
- it->first,
- it->second.contents.start,
- it->second.contents.Size());
- }
-
- // Find the __debug_info section.
- SectionMap::const_iterator debug_info_entry =
- file_context.section_map().find("__debug_info");
- // There had better be a __debug_info section!
- if (debug_info_entry == file_context.section_map().end()) {
- fprintf(stderr, "%s: __DWARF segment of file has no __debug_info section\n",
- selected_object_name_.c_str());
- return;
- }
- const std::pair<const uint8_t*, uint64_t>& debug_info_section =
- debug_info_entry->second;
-
- // Build a line-to-module loader for the root handler to use.
- DumperLineToModule line_to_module(&byte_reader);
-
- // .debug_ranges and .debug_rngslists reader
- DumperRangesHandler ranges_handler(&byte_reader);
-
- // 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, handle_inline);
- // Make a Dwarf2Handler that drives our DIEHandler.
- DIEDispatcher die_dispatcher(&root_handler);
- // Make a DWARF parser for the compilation unit at OFFSET.
- CompilationUnit dwarf_reader(selected_object_name_,
- file_context.section_map(),
- offset,
- &byte_reader,
- &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);
- }
- }
-}
-
-bool DumpSymbols::ReadCFI(google_breakpad::Module* module,
- const mach_o::Reader& macho_reader,
- const mach_o::Section& section,
- bool eh_frame) const {
- // Find the appropriate set of register names for this file's
- // architecture.
- vector<string> register_names;
- switch (macho_reader.cpu_type()) {
- case CPU_TYPE_X86:
- register_names = DwarfCFIToModule::RegisterNames::I386();
- break;
- case CPU_TYPE_X86_64:
- register_names = DwarfCFIToModule::RegisterNames::X86_64();
- break;
- case CPU_TYPE_ARM:
- register_names = DwarfCFIToModule::RegisterNames::ARM();
- break;
- case CPU_TYPE_ARM64:
- register_names = DwarfCFIToModule::RegisterNames::ARM64();
- break;
- default: {
- 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;
- }
- }
-
- // Find the call frame information and its size.
- const uint8_t* cfi = section.contents.start;
- size_t cfi_size = section.contents.Size();
-
- // Plug together the parser, handler, and their entourages.
- DwarfCFIToModule::Reporter module_reporter(selected_object_name_,
- section.section_name);
- DwarfCFIToModule handler(module, register_names, &module_reporter);
- ByteReader byte_reader(macho_reader.big_endian() ?
- ENDIANNESS_BIG :
- ENDIANNESS_LITTLE);
- byte_reader.SetAddressSize(macho_reader.bits_64() ? 8 : 4);
- // At the moment, according to folks at Apple and some cursory
- // investigation, Mac OS X only uses DW_EH_PE_pcrel-based pointers, so
- // this is the only base address the CFI parser will need.
- byte_reader.SetCFIDataBase(section.address, cfi);
-
- CallFrameInfo::Reporter dwarf_reporter(selected_object_name_,
- section.section_name);
- CallFrameInfo parser(cfi, cfi_size,
- &byte_reader, &handler, &dwarf_reporter,
- eh_frame);
- parser.Start();
- return true;
-}
-
-// A LoadCommandHandler that loads whatever debugging data it finds into a
-// Module.
-class DumpSymbols::LoadCommandDumper:
- public mach_o::Reader::LoadCommandHandler {
- public:
- // Create a load command dumper handling load commands from READER's
- // file, and adding data to MODULE.
- LoadCommandDumper(const DumpSymbols& dumper,
- google_breakpad::Module* module,
- const mach_o::Reader& reader,
- SymbolData symbol_data,
- bool handle_inter_cu_refs)
- : dumper_(dumper),
- module_(module),
- reader_(reader),
- symbol_data_(symbol_data),
- handle_inter_cu_refs_(handle_inter_cu_refs) { }
-
- bool SegmentCommand(const mach_o::Segment& segment);
- bool SymtabCommand(const ByteBuffer& entries, const ByteBuffer& strings);
-
- private:
- const DumpSymbols& dumper_;
- google_breakpad::Module* module_; // WEAK
- const mach_o::Reader& reader_;
- const SymbolData symbol_data_;
- const bool handle_inter_cu_refs_;
-};
-
-bool DumpSymbols::LoadCommandDumper::SegmentCommand(const Segment& segment) {
- mach_o::SectionMap section_map;
- if (!reader_.MapSegmentSections(segment, &section_map))
- return false;
-
- if (segment.name == "__TEXT") {
- module_->SetLoadAddress(segment.vmaddr);
- if (symbol_data_ & CFI) {
- mach_o::SectionMap::const_iterator eh_frame =
- section_map.find("__eh_frame");
- if (eh_frame != section_map.end()) {
- // If there is a problem reading this, don't treat it as a fatal error.
- dumper_.ReadCFI(module_, reader_, eh_frame->second, true);
- }
- }
- return true;
- }
-
- if (segment.name == "__DWARF") {
- if ((symbol_data_ & SYMBOLS_AND_FILES) || (symbol_data_ & INLINES)) {
- dumper_.ReadDwarf(module_, reader_, section_map, handle_inter_cu_refs_);
- }
- if (symbol_data_ & CFI) {
- mach_o::SectionMap::const_iterator debug_frame
- = section_map.find("__debug_frame");
- if (debug_frame != section_map.end()) {
- // If there is a problem reading this, don't treat it as a fatal error.
- dumper_.ReadCFI(module_, reader_, debug_frame->second, false);
- }
- }
- }
-
- return true;
-}
-
-bool DumpSymbols::LoadCommandDumper::SymtabCommand(const ByteBuffer& entries,
- const ByteBuffer& strings) {
- StabsToModule stabs_to_module(module_);
- // Mac OS X STABS are never "unitized", and the size of the 'value' field
- // matches the address size of the executable.
- StabsReader stabs_reader(entries.start, entries.Size(),
- strings.start, strings.Size(),
- reader_.big_endian(),
- reader_.bits_64() ? 8 : 4,
- true,
- &stabs_to_module);
- if (!stabs_reader.Process())
- return false;
- stabs_to_module.Finalize();
- return true;
-}
-
-bool DumpSymbols::ReadSymbolData(Module** out_module) {
- scoped_ptr<Module> module;
- if (!CreateEmptyModule(module))
- return false;
-
- // Parse the selected object file.
- mach_o::Reader::Reporter reporter(selected_object_name_);
- mach_o::Reader reader(&reporter);
- if (!reader.Read(&contents_[0]
- + selected_object_file_->offset,
- selected_object_file_->size,
- selected_object_file_->cputype,
- selected_object_file_->cpusubtype))
- return false;
-
- // Walk its load commands, and deal with whatever is there.
- LoadCommandDumper load_command_dumper(*this, module.get(), reader,
- symbol_data_, handle_inter_cu_refs_);
- if (!reader.WalkLoadCommands(&load_command_dumper))
- return false;
-
- *out_module = module.release();
-
- return true;
-}
-
-// Read the selected object file's debugging information, and write out the
-// header only to |stream|. Return true on success; if an error occurs, report
-// it and return false.
-bool DumpSymbols::WriteSymbolFileHeader(std::ostream& stream) {
- scoped_ptr<Module> module;
- if (!CreateEmptyModule(module))
- return false;
-
- return module->Write(stream, symbol_data_);
-}
-
-} // namespace google_breakpad