diff options
Diffstat (limited to 'externals/breakpad/src/common/mac/dump_syms.cc')
| -rw-r--r-- | externals/breakpad/src/common/mac/dump_syms.cc | 726 |
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, §ion_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 |
