aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthestig@chromium.org <thestig@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-09-14 01:02:55 +0000
committerthestig@chromium.org <thestig@chromium.org@4c0a9323-5329-0410-9bdc-e9ce6186880e>2011-09-14 01:02:55 +0000
commit8d54c7509234e9a4918046c12dcb138489f06990 (patch)
tree3da356f2f0b5d4b281cb6394a8064fbee5fdd756
parentRemove javascript_engine GYP variable. (diff)
downloadbreakpad-8d54c7509234e9a4918046c12dcb138489f06990.tar.xz
Linux/Mac: Add option to omit the CFI section in dump_syms.
Review URL: http://breakpad.appspot.com/304001 git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@835 4c0a9323-5329-0410-9bdc-e9ce6186880e
-rw-r--r--src/common/linux/dump_symbols.cc8
-rw-r--r--src/common/linux/dump_symbols.h4
-rw-r--r--src/common/linux/dump_symbols_unittest.cc26
-rw-r--r--src/common/mac/dump_syms.h24
-rw-r--r--src/common/mac/dump_syms.mm48
-rw-r--r--src/common/module.cc86
-rw-r--r--src/common/module.h13
-rw-r--r--src/common/module_unittest.cc68
-rw-r--r--src/tools/linux/dump_syms/dump_syms.cc42
-rw-r--r--src/tools/mac/dump_syms/dump_syms_tool.mm21
10 files changed, 213 insertions, 127 deletions
diff --git a/src/common/linux/dump_symbols.cc b/src/common/linux/dump_symbols.cc
index fc312983..cd059ba8 100644
--- a/src/common/linux/dump_symbols.cc
+++ b/src/common/linux/dump_symbols.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 Google Inc.
+// Copyright (c) 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -728,6 +728,7 @@ namespace google_breakpad {
bool WriteSymbolFileInternal(uint8_t* obj_file,
const std::string &obj_filename,
const std::string &debug_dir,
+ bool cfi,
std::ostream &sym_stream) {
ElfW(Ehdr) *elf_header = reinterpret_cast<ElfW(Ehdr) *>(obj_file);
@@ -803,7 +804,7 @@ bool WriteSymbolFileInternal(uint8_t* obj_file,
return false;
}
}
- if (!module.Write(sym_stream))
+ if (!module.Write(sym_stream, cfi))
return false;
return true;
@@ -811,6 +812,7 @@ bool WriteSymbolFileInternal(uint8_t* obj_file,
bool WriteSymbolFile(const std::string &obj_file,
const std::string &debug_dir,
+ bool cfi,
std::ostream &sym_stream) {
MmapWrapper map_wrapper;
ElfW(Ehdr) *elf_header = NULL;
@@ -818,7 +820,7 @@ bool WriteSymbolFile(const std::string &obj_file,
return false;
return WriteSymbolFileInternal(reinterpret_cast<uint8_t*>(elf_header),
- obj_file, debug_dir, sym_stream);
+ obj_file, debug_dir, cfi, sym_stream);
}
} // namespace google_breakpad
diff --git a/src/common/linux/dump_symbols.h b/src/common/linux/dump_symbols.h
index 3749d1f6..9bf54d37 100644
--- a/src/common/linux/dump_symbols.h
+++ b/src/common/linux/dump_symbols.h
@@ -1,6 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2010, Google Inc.
+// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -45,8 +45,10 @@ namespace google_breakpad {
// file format.
// If OBJ_FILE has been stripped but contains a .gnu_debuglink section,
// then look for the debug file in DEBUG_DIR.
+// If CFI is set to false, then omit the CFI section.
bool WriteSymbolFile(const std::string &obj_file,
const std::string &debug_dir,
+ bool cfi,
std::ostream &sym_stream);
} // namespace google_breakpad
diff --git a/src/common/linux/dump_symbols_unittest.cc b/src/common/linux/dump_symbols_unittest.cc
index 06263076..c6d4d2d3 100644
--- a/src/common/linux/dump_symbols_unittest.cc
+++ b/src/common/linux/dump_symbols_unittest.cc
@@ -47,6 +47,7 @@ namespace google_breakpad {
bool WriteSymbolFileInternal(uint8_t* obj_file,
const std::string &obj_filename,
const std::string &debug_dir,
+ bool cfi,
std::ostream &sym_stream);
}
@@ -62,7 +63,7 @@ using std::vector;
using ::testing::Test;
class DumpSymbols : public Test {
-public:
+ public:
void GetElfContents(ELF& elf) {
string contents;
ASSERT_TRUE(elf.GetContents(&contents));
@@ -84,6 +85,7 @@ TEST_F(DumpSymbols, Invalid) {
EXPECT_FALSE(WriteSymbolFileInternal(reinterpret_cast<uint8_t*>(&header),
"foo",
"",
+ true,
s));
}
@@ -105,11 +107,11 @@ TEST_F(DumpSymbols, SimplePublic32) {
SHN_UNDEF + 1);
int index = elf.AddSection(".dynstr", table, SHT_STRTAB);
elf.AddSection(".dynsym", syms,
- SHT_DYNSYM, // type
- SHF_ALLOC, // flags
- 0, // addr
- index, // link
- sizeof(Elf32_Sym)); // entsize
+ SHT_DYNSYM, // type
+ SHF_ALLOC, // flags
+ 0, // addr
+ index, // link
+ sizeof(Elf32_Sym)); // entsize
elf.Finish();
GetElfContents(elf);
@@ -118,6 +120,7 @@ TEST_F(DumpSymbols, SimplePublic32) {
ASSERT_TRUE(WriteSymbolFileInternal(elfdata,
"foo",
"",
+ true,
s));
EXPECT_EQ("MODULE Linux x86 000000000000000000000000000000000 foo\n"
"PUBLIC 1000 0 superfunc\n",
@@ -141,11 +144,11 @@ TEST_F(DumpSymbols, SimplePublic64) {
SHN_UNDEF + 1);
int index = elf.AddSection(".dynstr", table, SHT_STRTAB);
elf.AddSection(".dynsym", syms,
- SHT_DYNSYM, // type
- SHF_ALLOC, // flags
- 0, // addr
- index, // link
- sizeof(Elf64_Sym)); // entsize
+ SHT_DYNSYM, // type
+ SHF_ALLOC, // flags
+ 0, // addr
+ index, // link
+ sizeof(Elf64_Sym)); // entsize
elf.Finish();
GetElfContents(elf);
@@ -154,6 +157,7 @@ TEST_F(DumpSymbols, SimplePublic64) {
ASSERT_TRUE(WriteSymbolFileInternal(elfdata,
"foo",
"",
+ true,
s));
EXPECT_EQ("MODULE Linux x86_64 000000000000000000000000000000000 foo\n"
"PUBLIC 1000 0 superfunc\n",
diff --git a/src/common/mac/dump_syms.h b/src/common/mac/dump_syms.h
index f197ca28..0e2f464d 100644
--- a/src/common/mac/dump_syms.h
+++ b/src/common/mac/dump_syms.h
@@ -1,6 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2010, Google Inc.
+// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -52,9 +52,9 @@ namespace google_breakpad {
class DumpSymbols {
public:
- DumpSymbols()
+ DumpSymbols()
: input_pathname_(),
- object_filename_(),
+ object_filename_(),
contents_(),
selected_object_file_(),
selected_object_name_() { }
@@ -84,9 +84,9 @@ class DumpSymbols {
// 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,
+
+ // 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.
//
// By default, if this dumper's file contains only one object file, then
@@ -94,7 +94,7 @@ class DumpSymbols {
// 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);
-
+
// Return a pointer to an array of 'struct fat_arch' structures,
// describing the object files contained in this dumper's file. Set
// *|count| to the number of elements in the array. The returned array is
@@ -109,10 +109,10 @@ class DumpSymbols {
return NULL;
}
- // Read the selected object file's debugging information, and write it
- // out to |stream|. Return true on success; if an error occurs, report it
- // and return false.
- bool WriteSymbolFile(std::ostream &stream);
+ // Read the selected object file's debugging information, and write it out to
+ // |stream|. Write the CFI section if |cfi| is true. Return true on success;
+ // if an error occurs, report it and return false.
+ bool WriteSymbolFile(std::ostream &stream, bool cfi);
private:
// Used internally.
@@ -158,7 +158,7 @@ class DumpSymbols {
// has exactly one element.
vector<struct fat_arch> object_files_;
- // The object file in object_files_ selected to dump, or NULL if
+ // The object file in object_files_ selected to dump, or NULL if
// SetArchitecture hasn't been called yet.
const struct fat_arch *selected_object_file_;
diff --git a/src/common/mac/dump_syms.mm b/src/common/mac/dump_syms.mm
index 5fd614f2..9783514f 100644
--- a/src/common/mac/dump_syms.mm
+++ b/src/common/mac/dump_syms.mm
@@ -1,6 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2010, Google Inc.
+// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -79,7 +79,7 @@ namespace google_breakpad {
bool DumpSymbols::Read(NSString *filename) {
if (![[NSFileManager defaultManager] fileExistsAtPath:filename]) {
fprintf(stderr, "Object file does not exist: %s\n",
- [filename fileSystemRepresentation]);
+ [filename fileSystemRepresentation]);
return false;
}
@@ -101,15 +101,15 @@ bool DumpSymbols::Read(NSString *filename) {
// pathForResource:ofType:inDirectory likes.
NSString *base_name = [input_pathname_ lastPathComponent];
NSString *dwarf_resource;
-
+
do {
NSString *new_base_name = [base_name stringByDeletingPathExtension];
// If stringByDeletingPathExtension returned the name unchanged, then
// there's nothing more for us to strip off --- lose.
if ([new_base_name isEqualToString:base_name]) {
- fprintf(stderr, "Unable to find DWARF-bearing file in bundle: %s\n",
- [input_pathname_ fileSystemRepresentation]);
+ fprintf(stderr, "Unable to find DWARF-bearing file in bundle: %s\n",
+ [input_pathname_ fileSystemRepresentation]);
return false;
}
@@ -141,12 +141,12 @@ bool DumpSymbols::Read(NSString *filename) {
// file don't affect memory and vice versa).
NSError *error;
contents_ = [NSData dataWithContentsOfFile:object_filename_
- options:0
- error:&error];
+ options:0
+ error:&error];
if (!contents_) {
fprintf(stderr, "Error reading object file: %s: %s\n",
- [object_filename_ fileSystemRepresentation],
- [[error localizedDescription] UTF8String]);
+ [object_filename_ fileSystemRepresentation],
+ [[error localizedDescription] UTF8String]);
return false;
}
[contents_ retain];
@@ -166,7 +166,7 @@ bool DumpSymbols::Read(NSString *filename) {
fat_reader.object_files(&object_files_count);
if (object_files_count == 0) {
fprintf(stderr, "Fat binary file contains *no* architectures: %s\n",
- [object_filename_ fileSystemRepresentation]);
+ [object_filename_ fileSystemRepresentation]);
return false;
}
object_files_.resize(object_files_count);
@@ -197,14 +197,14 @@ bool DumpSymbols::SetArchitecture(const std::string &arch_name) {
}
return arch_set;
}
-
+
string DumpSymbols::Identifier() {
FileID file_id([object_filename_ fileSystemRepresentation]);
unsigned char identifier_bytes[16];
cpu_type_t cpu_type = selected_object_file_->cputype;
if (!file_id.MachoIdentifier(cpu_type, identifier_bytes)) {
fprintf(stderr, "Unable to calculate UUID of mach-o binary %s!\n",
- [object_filename_ fileSystemRepresentation]);
+ [object_filename_ fileSystemRepresentation]);
return "";
}
@@ -243,7 +243,7 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
const mach_o::Reader &macho_reader,
const mach_o::SectionMap &dwarf_sections) const {
// Build a byte reader of the appropriate endianness.
- ByteReader byte_reader(macho_reader.big_endian()
+ ByteReader byte_reader(macho_reader.big_endian()
? dwarf2reader::ENDIANNESS_BIG
: dwarf2reader::ENDIANNESS_LITTLE);
@@ -265,10 +265,10 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
// There had better be a __debug_info section!
if (!debug_info_section.first) {
fprintf(stderr, "%s: __DWARF segment of file has no __debug_info section\n",
- selected_object_name_.c_str());
+ selected_object_name_.c_str());
return false;
}
-
+
// Build a line-to-module loader for the root handler to use.
DumperLineToModule line_to_module(&byte_reader);
@@ -343,7 +343,7 @@ bool DumpSymbols::ReadCFI(google_breakpad::Module *module,
// 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);
-
+
dwarf2reader::CallFrameInfo::Reporter dwarf_reporter(selected_object_name_,
section.section_name);
dwarf2reader::CallFrameInfo parser(cfi, cfi_size,
@@ -421,7 +421,7 @@ bool DumpSymbols::LoadCommandDumper::SymtabCommand(const ByteBuffer &entries,
return true;
}
-bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
+bool DumpSymbols::WriteSymbolFile(std::ostream &stream, bool cfi) {
// Select an object file, if SetArchitecture hasn't been called to set one
// explicitly.
if (!selected_object_file_) {
@@ -433,10 +433,10 @@ bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
const NXArchInfo *local_arch = NXGetLocalArchInfo();
if (!SetArchitecture(local_arch->cputype, local_arch->cpusubtype)) {
fprintf(stderr, "%s: object file contains more than one"
- " architecture, none of which match the current"
+ " architecture, none of which match the current"
" architecture; specify an architecture explicitly"
- " with '-a ARCH' to resolve the ambiguity\n",
- [object_filename_ fileSystemRepresentation]);
+ " with '-a ARCH' to resolve the ambiguity\n",
+ [object_filename_ fileSystemRepresentation]);
return false;
}
}
@@ -472,7 +472,7 @@ bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
identifier += "0";
// Create a module to hold the debugging information.
- Module module([module_name UTF8String], "mac", selected_arch_name,
+ Module module([module_name UTF8String], "mac", selected_arch_name,
identifier);
// Parse the selected object file.
@@ -481,8 +481,8 @@ bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
if (!reader.Read(reinterpret_cast<const uint8_t *>([contents_ bytes])
+ selected_object_file_->offset,
selected_object_file_->size,
- selected_object_file_->cputype,
- selected_object_file_->cpusubtype))
+ selected_object_file_->cputype,
+ selected_object_file_->cpusubtype))
return false;
// Walk its load commands, and deal with whatever is there.
@@ -490,7 +490,7 @@ bool DumpSymbols::WriteSymbolFile(std::ostream &stream) {
if (!reader.WalkLoadCommands(&load_command_dumper))
return false;
- return module.Write(stream);
+ return module.Write(stream, cfi);
}
} // namespace google_breakpad
diff --git a/src/common/module.cc b/src/common/module.cc
index f02b26ea..4e257d1d 100644
--- a/src/common/module.cc
+++ b/src/common/module.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010 Google Inc.
+// Copyright (c) 2011 Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -39,6 +39,7 @@
#include <string.h>
#include <iostream>
+#include <utility>
namespace google_breakpad {
@@ -56,16 +57,17 @@ Module::Module(const string &name, const string &os,
load_address_(0) { }
Module::~Module() {
- for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); it++)
+ for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
delete it->second;
for (FunctionSet::iterator it = functions_.begin();
- it != functions_.end(); it++)
+ it != functions_.end(); ++it) {
delete *it;
+ }
for (vector<StackFrameEntry *>::iterator it = stack_frame_entries_.begin();
- it != stack_frame_entries_.end(); it++)
+ it != stack_frame_entries_.end(); ++it) {
delete *it;
- for (ExternSet::iterator it = externs_.begin();
- it != externs_.end(); it++)
+ }
+ for (ExternSet::iterator it = externs_.begin(); it != externs_.end(); ++it)
delete *it;
}
@@ -87,7 +89,7 @@ void Module::AddFunction(Function *function) {
void Module::AddFunctions(vector<Function *>::iterator begin,
vector<Function *>::iterator end) {
- for (vector<Function *>::iterator it = begin; it != end; it++)
+ for (vector<Function *>::iterator it = begin; it != end; ++it)
AddFunction(*it);
}
@@ -149,7 +151,7 @@ Module::File *Module::FindExistingFile(const string &name) {
void Module::GetFiles(vector<File *> *vec) {
vec->clear();
- for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); it++)
+ for (FileByNameMap::iterator it = files_.begin(); it != files_.end(); ++it)
vec->push_back(it->second);
}
@@ -160,16 +162,17 @@ void Module::GetStackFrameEntries(vector<StackFrameEntry *> *vec) {
void Module::AssignSourceIds() {
// First, give every source file an id of -1.
for (FileByNameMap::iterator file_it = files_.begin();
- file_it != files_.end(); file_it++)
+ file_it != files_.end(); ++file_it) {
file_it->second->source_id = -1;
+ }
// Next, mark all files actually cited by our functions' line number
// info, by setting each one's source id to zero.
for (FunctionSet::const_iterator func_it = functions_.begin();
- func_it != functions_.end(); func_it++) {
+ func_it != functions_.end(); ++func_it) {
Function *func = *func_it;
for (vector<Line>::iterator line_it = func->lines.begin();
- line_it != func->lines.end(); line_it++)
+ line_it != func->lines.end(); ++line_it)
line_it->file->source_id = 0;
}
@@ -179,9 +182,10 @@ void Module::AssignSourceIds() {
// lexicographical order by name, which is neat.
int next_source_id = 0;
for (FileByNameMap::iterator file_it = files_.begin();
- file_it != files_.end(); file_it++)
+ file_it != files_.end(); ++file_it) {
if (!file_it->second->source_id)
file_it->second->source_id = next_source_id++;
+ }
}
bool Module::ReportError() {
@@ -192,7 +196,7 @@ bool Module::ReportError() {
bool Module::WriteRuleMap(const RuleMap &rule_map, std::ostream &stream) {
for (RuleMap::const_iterator it = rule_map.begin();
- it != rule_map.end(); it++) {
+ it != rule_map.end(); ++it) {
if (it != rule_map.begin())
stream << ' ';
stream << it->first << ": " << it->second;
@@ -200,7 +204,7 @@ bool Module::WriteRuleMap(const RuleMap &rule_map, std::ostream &stream) {
return stream.good();
}
-bool Module::Write(std::ostream &stream) {
+bool Module::Write(std::ostream &stream, bool cfi) {
stream << "MODULE " << os_ << " " << architecture_ << " "
<< id_ << " " << name_ << endl;
if (!stream.good())
@@ -210,7 +214,7 @@ bool Module::Write(std::ostream &stream) {
// Write out files.
for (FileByNameMap::iterator file_it = files_.begin();
- file_it != files_.end(); file_it++) {
+ file_it != files_.end(); ++file_it) {
File *file = file_it->second;
if (file->source_id >= 0) {
stream << "FILE " << file->source_id << " " << file->name << endl;
@@ -221,18 +225,18 @@ bool Module::Write(std::ostream &stream) {
// Write out functions and their lines.
for (FunctionSet::const_iterator func_it = functions_.begin();
- func_it != functions_.end(); func_it++) {
+ func_it != functions_.end(); ++func_it) {
Function *func = *func_it;
stream << "FUNC " << hex
<< (func->address - load_address_) << " "
<< func->size << " "
<< func->parameter_size << " "
<< func->name << dec << endl;
-
+
if (!stream.good())
return ReportError();
for (vector<Line>::iterator line_it = func->lines.begin();
- line_it != func->lines.end(); line_it++) {
+ line_it != func->lines.end(); ++line_it) {
stream << hex
<< (line_it->address - load_address_) << " "
<< line_it->size << " "
@@ -246,7 +250,7 @@ bool Module::Write(std::ostream &stream) {
// Write out 'PUBLIC' records.
for (ExternSet::const_iterator extern_it = externs_.begin();
- extern_it != externs_.end(); extern_it++) {
+ extern_it != externs_.end(); ++extern_it) {
Extern *ext = *extern_it;
stream << "PUBLIC " << hex
<< (ext->address - load_address_) << " 0 "
@@ -255,34 +259,36 @@ bool Module::Write(std::ostream &stream) {
return ReportError();
}
- // Write out 'STACK CFI INIT' and 'STACK CFI' records.
- vector<StackFrameEntry *>::const_iterator frame_it;
- for (frame_it = stack_frame_entries_.begin();
- frame_it != stack_frame_entries_.end(); frame_it++) {
- StackFrameEntry *entry = *frame_it;
- stream << "STACK CFI INIT " << hex
- << (entry->address - load_address_) << " "
- << entry->size << " " << dec;
- if (!stream.good()
- || !WriteRuleMap(entry->initial_rules, stream))
- return ReportError();
-
- stream << endl;
-
- // Write out this entry's delta rules as 'STACK CFI' records.
- for (RuleChangeMap::const_iterator delta_it = entry->rule_changes.begin();
- delta_it != entry->rule_changes.end(); delta_it++) {
- stream << "STACK CFI " << hex
- << (delta_it->first - load_address_) << " " << dec;
+ if (cfi) {
+ // Write out 'STACK CFI INIT' and 'STACK CFI' records.
+ vector<StackFrameEntry *>::const_iterator frame_it;
+ for (frame_it = stack_frame_entries_.begin();
+ frame_it != stack_frame_entries_.end(); ++frame_it) {
+ StackFrameEntry *entry = *frame_it;
+ stream << "STACK CFI INIT " << hex
+ << (entry->address - load_address_) << " "
+ << entry->size << " " << dec;
if (!stream.good()
- || !WriteRuleMap(delta_it->second, stream))
+ || !WriteRuleMap(entry->initial_rules, stream))
return ReportError();
stream << endl;
+
+ // Write out this entry's delta rules as 'STACK CFI' records.
+ for (RuleChangeMap::const_iterator delta_it = entry->rule_changes.begin();
+ delta_it != entry->rule_changes.end(); ++delta_it) {
+ stream << "STACK CFI " << hex
+ << (delta_it->first - load_address_) << " " << dec;
+ if (!stream.good()
+ || !WriteRuleMap(delta_it->second, stream))
+ return ReportError();
+
+ stream << endl;
+ }
}
}
return true;
}
-} // namespace google_breakpad
+} // namespace google_breakpad
diff --git a/src/common/module.h b/src/common/module.h
index 55f260f1..734a1afc 100644
--- a/src/common/module.h
+++ b/src/common/module.h
@@ -259,14 +259,15 @@ class Module {
// breakpad symbol format. Return true if all goes well, or false if
// an error occurs. This method writes out:
// - a header based on the values given to the constructor,
- // - the source files added via FindFile, and finally
- // - the functions added via AddFunctions, each with its lines.
+ // - the source files added via FindFile,
+ // - the functions added via AddFunctions, each with its lines,
+ // - all public records,
+ // - and if CFI is true, all CFI records.
// Addresses in the output are all relative to the load address
// established by SetLoadAddress.
- bool Write(std::ostream &stream);
+ bool Write(std::ostream &stream, bool cfi);
private:
-
// Report an error that has occurred writing the symbol file, using
// errno to find the appropriate cause. Return false.
static bool ReportError();
@@ -287,7 +288,7 @@ class Module {
// Relation for maps whose keys are strings shared with some other
// structure.
struct CompareStringPtrs {
- bool operator()(const string *x, const string *y) { return *x < *y; };
+ bool operator()(const string *x, const string *y) { return *x < *y; }
};
// A map from filenames to File structures. The map's keys are
@@ -315,6 +316,6 @@ class Module {
ExternSet externs_;
};
-} // namespace google_breakpad
+} // namespace google_breakpad
#endif // COMMON_LINUX_MODULE_H__
diff --git a/src/common/module_unittest.cc b/src/common/module_unittest.cc
index 4972bbe8..85c3b1c6 100644
--- a/src/common/module_unittest.cc
+++ b/src/common/module_unittest.cc
@@ -70,7 +70,7 @@ static Module::Function *generate_duplicate_function(const string &name) {
TEST(Write, Header) {
stringstream s;
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n",
contents.c_str());
@@ -91,7 +91,7 @@ TEST(Write, OneLineFunc) {
function->lines.push_back(line);
m.AddFunction(function);
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
"FILE 0 file_name.cc\n"
@@ -141,7 +141,7 @@ TEST(Write, RelativeLoadAddress) {
// the module must work fine.
m.SetLoadAddress(0x2ab698b0b6407073LL);
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
"FILE 0 filename-a.cc\n"
@@ -164,7 +164,7 @@ TEST(Write, OmitUnusedFiles) {
// Create some source files.
Module::File *file1 = m.FindFile("filename1");
- m.FindFile("filename2"); // not used by any line
+ m.FindFile("filename2"); // not used by any line
Module::File *file3 = m.FindFile("filename3");
// Create a function.
@@ -197,7 +197,7 @@ TEST(Write, OmitUnusedFiles) {
EXPECT_NE(-1, vec[2]->source_id);
stringstream s;
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
"FILE 0 filename1\n"
@@ -209,6 +209,52 @@ TEST(Write, OmitUnusedFiles) {
contents.c_str());
}
+TEST(Write, NoCFI) {
+ stringstream s;
+ Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
+
+ // Some source files. We will expect to see them in lexicographic order.
+ Module::File *file1 = m.FindFile("filename.cc");
+
+ // A function.
+ Module::Function *function = new(Module::Function);
+ function->name = "A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)";
+ function->address = 0xbec774ea5dd935f3LL;
+ function->size = 0x2922088f98d3f6fcLL;
+ function->parameter_size = 0xe5e9aa008bd5f0d0LL;
+
+ // Some source lines. The module should not sort these.
+ Module::Line line1 = { 0xbec774ea5dd935f3LL, 0x1c2be6d6c5af2611LL,
+ file1, 41676901 };
+ function->lines.push_back(line1);
+
+ m.AddFunction(function);
+
+ // Some stack information.
+ Module::StackFrameEntry *entry = new Module::StackFrameEntry();
+ entry->address = 0x30f9e5c83323973dULL;
+ entry->size = 0x49fc9ca7c7c13dc2ULL;
+ entry->initial_rules[".cfa"] = "he was a handsome man";
+ entry->initial_rules["and"] = "what i want to know is";
+ entry->rule_changes[0x30f9e5c83323973eULL]["how"] =
+ "do you like your blueeyed boy";
+ entry->rule_changes[0x30f9e5c83323973eULL]["Mister"] = "Death";
+ m.AddStackFrameEntry(entry);
+
+ // Set the load address. Doing this after adding all the data to
+ // the module must work fine.
+ m.SetLoadAddress(0x2ab698b0b6407073LL);
+
+ m.Write(s, false);
+ string contents = s.str();
+ EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
+ "FILE 0 filename.cc\n"
+ "FUNC 9410dc39a798c580 2922088f98d3f6fc e5e9aa008bd5f0d0"
+ " A_FLIBBERTIJIBBET::a_will_o_the_wisp(a clown)\n"
+ "9410dc39a798c580 1c2be6d6c5af2611 41676901 0\n",
+ contents.c_str());
+}
+
TEST(Construct, AddFunctions) {
stringstream s;
Module m(MODULE_NAME, MODULE_OS, MODULE_ARCH, MODULE_ID);
@@ -233,7 +279,7 @@ TEST(Construct, AddFunctions) {
m.AddFunctions(vec.begin(), vec.end());
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
"FUNC 2987743d0b35b13f b369db048deb3010 938e556cb5a79988"
@@ -285,7 +331,7 @@ TEST(Construct, AddFrames) {
m.AddStackFrameEntry(entry3);
// Check that Write writes STACK CFI records properly.
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
"STACK CFI INIT ddb5f41285aa7757 1486493370dc5073 \n"
@@ -361,7 +407,7 @@ TEST(Construct, DuplicateFunctions) {
m.AddFunction(function1);
m.AddFunction(function2);
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
"FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
@@ -380,7 +426,7 @@ TEST(Construct, FunctionsWithSameAddress) {
m.AddFunction(function1);
m.AddFunction(function2);
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE os-name architecture id-string name with spaces\n"
"FUNC d35402aac7a7ad5c 200b26e605f99071 f14ac4fed48c4a99"
@@ -407,7 +453,7 @@ TEST(Construct, Externs) {
m.AddExtern(extern1);
m.AddExtern(extern2);
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
@@ -434,7 +480,7 @@ TEST(Construct, DuplicateExterns) {
m.AddExtern(extern1);
m.AddExtern(extern2);
- m.Write(s);
+ m.Write(s, true);
string contents = s.str();
EXPECT_STREQ("MODULE " MODULE_OS " " MODULE_ARCH " "
diff --git a/src/tools/linux/dump_syms/dump_syms.cc b/src/tools/linux/dump_syms/dump_syms.cc
index f4c05cfc..adac216c 100644
--- a/src/tools/linux/dump_syms/dump_syms.cc
+++ b/src/tools/linux/dump_syms/dump_syms.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2010, Google Inc.
+// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -27,27 +27,47 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include <iostream>
#include <stdio.h>
+
+#include <cstring>
+#include <iostream>
#include <string>
#include "common/linux/dump_symbols.h"
using google_breakpad::WriteSymbolFile;
+int usage(const char* self) {
+ fprintf(stderr, "Usage: %s [OPTION] <binary-with-debugging-info> "
+ "[directory-for-debug-file]\n\n", self);
+ fprintf(stderr, "Options:\n");
+ fprintf(stderr, " -c Do not generate CFI section\n");
+ return 1;
+}
+
int main(int argc, char **argv) {
- if (argc < 2 || argc > 3) {
- fprintf(stderr, "Usage: %s <binary-with-debugging-info> "
- "[directory-for-debug-file]\n", argv[0]);
- return 1;
- }
+ if (argc < 2 || argc > 4)
+ return usage(argv[0]);
- const char *binary = argv[1];
+ bool cfi = true;
+ if (strcmp("-c", argv[1]) == 0)
+ cfi = false;
+ if (!cfi && argc == 2)
+ return usage(argv[0]);
+
+ const char *binary;
std::string debug_dir;
- if (argc == 3)
- debug_dir = argv[2];
+ if (cfi) {
+ binary = argv[1];
+ if (argc == 3)
+ debug_dir = argv[2];
+ } else {
+ binary = argv[2];
+ if (argc == 4)
+ debug_dir = argv[3];
+ }
- if (!WriteSymbolFile(binary, debug_dir, std::cout)) {
+ if (!WriteSymbolFile(binary, debug_dir, cfi, std::cout)) {
fprintf(stderr, "Failed to write symbol file.\n");
return 1;
}
diff --git a/src/tools/mac/dump_syms/dump_syms_tool.mm b/src/tools/mac/dump_syms/dump_syms_tool.mm
index 3f1f03b6..92ebf211 100644
--- a/src/tools/mac/dump_syms/dump_syms_tool.mm
+++ b/src/tools/mac/dump_syms/dump_syms_tool.mm
@@ -1,6 +1,6 @@
// -*- mode: c++ -*-
-// Copyright (c) 2006, Google Inc.
+// Copyright (c) 2011, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
@@ -45,9 +45,10 @@ using google_breakpad::DumpSymbols;
using std::vector;
struct Options {
- Options() : srcPath(), arch() { }
+ Options() : srcPath(), arch(), cfi(true) { }
NSString *srcPath;
const NXArchInfo *arch;
+ bool cfi;
};
//=============================================================================
@@ -82,17 +83,18 @@ static bool Start(const Options &options) {
return false;
}
}
-
- return dump_symbols.WriteSymbolFile(std::cout);
+
+ return dump_symbols.WriteSymbolFile(std::cout, options.cfi);
}
//=============================================================================
static void Usage(int argc, const char *argv[]) {
fprintf(stderr, "Output a Breakpad symbol file from a Mach-o file.\n");
- fprintf(stderr, "Usage: %s [-a ARCHITECTURE] <Mach-o file>\n",
+ fprintf(stderr, "Usage: %s [-a ARCHITECTURE] [-c] <Mach-o file>\n",
argv[0]);
fprintf(stderr, "\t-a: Architecture type [default: native, or whatever is\n");
fprintf(stderr, "\t in the file, if it contains only one architecture]\n");
+ fprintf(stderr, "\t-c: Do not generate CFI section\n");
fprintf(stderr, "\t-h: Usage\n");
fprintf(stderr, "\t-?: Usage\n");
}
@@ -102,7 +104,7 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
extern int optind;
signed char ch;
- while ((ch = getopt(argc, (char * const *)argv, "a:h?")) != -1) {
+ while ((ch = getopt(argc, (char * const *)argv, "a:ch?")) != -1) {
switch (ch) {
case 'a': {
const NXArchInfo *arch_info = NXGetArchInfoFromName(optarg);
@@ -114,6 +116,9 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
options->arch = arch_info;
break;
}
+ case 'c':
+ options->cfi = false;
+ break;
case '?':
case 'h':
Usage(argc, argv);
@@ -121,7 +126,7 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
break;
}
}
-
+
if ((argc - optind) != 1) {
fprintf(stderr, "Must specify Mach-o file\n");
Usage(argc, argv);
@@ -137,7 +142,7 @@ static void SetupOptions(int argc, const char *argv[], Options *options) {
int main (int argc, const char * argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Options options;
- bool result;
+ bool result;
SetupOptions(argc, argv, &options);
result = Start(options);