Mac dump_syms: accept __DWARF segment without __debug_info section

A .dSYM may validly contain a __DWARF segment without any __debug_info
section. This can occur for Chromium Framework in a component build of
Chromium, because in that case, all of the code is in other libraries
that Chromium Framework depends on.

This was previously tested by an assertion, but the assertion did not
trigger in NDEBUG (release) builds. In NDEBUG builds, this condition
would lead to an out-of-bounds read, detected by AddressSanitizer.

Instead of an assertion, the check is now always done at runtime.
Instead of being fatal, it's now just a warning, because it's been
established that __DWARF without __debug_info can occur.

(In the Chromium case, it remains pointless to run dump_syms via the
"chrome_dump_syms" target on a component build, as it'll only attempt to
symbolize Chromium Framework, and not any of the libraries that Chromium
Framework depends on that actually contain the code.)

Bug: chromium:991206
Change-Id: I6c9c75f0be7901813e3eaae54aff38c1afe73ca9
Reviewed-on: https://chromium-review.googlesource.com/c/breakpad/breakpad/+/1741610
Reviewed-by: Robert Sesek <rsesek@chromium.org>
This commit is contained in:
Mark Mentovai 2019-08-07 12:42:38 -04:00
parent ef04c9c028
commit 01dfa81f1b
2 changed files with 8 additions and 15 deletions

View file

@ -413,7 +413,7 @@ bool DumpSymbols::CreateEmptyModule(scoped_ptr<Module>& module) {
return true; return true;
} }
bool DumpSymbols::ReadDwarf(google_breakpad::Module *module, void DumpSymbols::ReadDwarf(google_breakpad::Module *module,
const mach_o::Reader &macho_reader, const mach_o::Reader &macho_reader,
const mach_o::SectionMap &dwarf_sections, const mach_o::SectionMap &dwarf_sections,
bool handle_inter_cu_refs) const { bool handle_inter_cu_refs) const {
@ -439,15 +439,14 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
// Find the __debug_info section. // Find the __debug_info section.
dwarf2reader::SectionMap::const_iterator debug_info_entry = dwarf2reader::SectionMap::const_iterator debug_info_entry =
file_context.section_map().find("__debug_info"); file_context.section_map().find("__debug_info");
assert(debug_info_entry != file_context.section_map().end());
const std::pair<const uint8_t *, uint64>& debug_info_section =
debug_info_entry->second;
// There had better be a __debug_info section! // There had better be a __debug_info section!
if (!debug_info_section.first) { if (debug_info_entry == file_context.section_map().end()) {
fprintf(stderr, "%s: __DWARF segment of file has no __debug_info section\n", 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; return;
} }
const std::pair<const uint8_t*, uint64>& debug_info_section =
debug_info_entry->second;
// Build a line-to-module loader for the root handler to use. // Build a line-to-module loader for the root handler to use.
DumperLineToModule line_to_module(&byte_reader); DumperLineToModule line_to_module(&byte_reader);
@ -484,8 +483,6 @@ bool DumpSymbols::ReadDwarf(google_breakpad::Module *module,
// Process the entire compilation unit; get the offset of the next. // Process the entire compilation unit; get the offset of the next.
offset += dwarf_reader.Start(); offset += dwarf_reader.Start();
} }
return true;
} }
bool DumpSymbols::ReadCFI(google_breakpad::Module *module, bool DumpSymbols::ReadCFI(google_breakpad::Module *module,
@ -598,10 +595,7 @@ bool DumpSymbols::LoadCommandDumper::SegmentCommand(const Segment &segment) {
if (segment.name == "__DWARF") { if (segment.name == "__DWARF") {
if (symbol_data_ != ONLY_CFI) { if (symbol_data_ != ONLY_CFI) {
if (!dumper_.ReadDwarf(module_, reader_, section_map, dumper_.ReadDwarf(module_, reader_, section_map, handle_inter_cu_refs_);
handle_inter_cu_refs_)) {
return false;
}
} }
if (symbol_data_ != NO_CFI) { if (symbol_data_ != NO_CFI) {
mach_o::SectionMap::const_iterator debug_frame mach_o::SectionMap::const_iterator debug_frame

View file

@ -141,9 +141,8 @@ class DumpSymbols {
bool CreateEmptyModule(scoped_ptr<Module>& module); bool CreateEmptyModule(scoped_ptr<Module>& module);
// Read debugging information from |dwarf_sections|, which was taken from // Read debugging information from |dwarf_sections|, which was taken from
// |macho_reader|, and add it to |module|. On success, return true; // |macho_reader|, and add it to |module|.
// on failure, report the problem and return false. void ReadDwarf(google_breakpad::Module *module,
bool ReadDwarf(google_breakpad::Module *module,
const mach_o::Reader &macho_reader, const mach_o::Reader &macho_reader,
const mach_o::SectionMap &dwarf_sections, const mach_o::SectionMap &dwarf_sections,
bool handle_inter_cu_refs) const; bool handle_inter_cu_refs) const;