diff options
author | benchan@chromium.org <benchan@chromium.org> | 2015-02-02 23:27:27 +0000 |
---|---|---|
committer | benchan@chromium.org <benchan@chromium.org> | 2015-02-02 23:27:27 +0000 |
commit | 4c01a9c389ffcfb29bb1c2a4239804019eddc3d6 (patch) | |
tree | 6e529f8734a13e431b537dc9499a29e79beeece7 /src/client/linux/minidump_writer/minidump_writer.cc | |
parent | Replace uses of hash_map with unordered_map (diff) | |
download | breakpad-4c01a9c389ffcfb29bb1c2a4239804019eddc3d6.tar.xz |
Handle failures of copying process data from a core file.
When LinuxCoreDumper fails to copy process data from a core file, it
fills the return buffer with a repeated sequence of a special marker.
However, MinidumpWriter doesn't know about that and may incorrectly
interpret the data. In many cases, MinidumpWriter simply copies the
gibberish data to the minidump, which isn't too bad. However, the
gibberish data may cause MinidumpWriter to behave badly in some other
cases. For example, when MinidumpWriter tries to iterate through the
linked list of all loaded DSOs via the r_map field of a r_debug struct,
if the linked list is filed with the special marker, the code keeps
iterating through the same address.
This CL addresses the issue by having LinuxCoreDumper::CopyFromProcess()
returns a Boolean value to indicate if the expected data is found from
the core file. MinidumpWriter can then decide how to handle that.
BUG=chromium:453484
TEST=Run core2md with the test data attached to chromium:453484.
R=mark@chromium.org
Review URL: https://breakpad.appspot.com/4724002
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1420 4c0a9323-5329-0410-9bdc-e9ce6186880e
Diffstat (limited to 'src/client/linux/minidump_writer/minidump_writer.cc')
-rw-r--r-- | src/client/linux/minidump_writer/minidump_writer.cc | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/src/client/linux/minidump_writer/minidump_writer.cc b/src/client/linux/minidump_writer/minidump_writer.cc index 91610c03..edc7e47d 100644 --- a/src/client/linux/minidump_writer/minidump_writer.cc +++ b/src/client/linux/minidump_writer/minidump_writer.cc @@ -658,7 +658,9 @@ class MinidumpWriter { ElfW(Addr) dyn_addr = 0; for (; phnum >= 0; phnum--, phdr++) { ElfW(Phdr) ph; - dumper_->CopyFromProcess(&ph, GetCrashThread(), phdr, sizeof(ph)); + if (!dumper_->CopyFromProcess(&ph, GetCrashThread(), phdr, sizeof(ph))) + return false; + // Adjust base address with the virtual address of the PT_LOAD segment // corresponding to offset 0 if (ph.p_type == PT_LOAD && ph.p_offset == 0) { @@ -679,11 +681,14 @@ class MinidumpWriter { struct r_debug* r_debug = NULL; uint32_t dynamic_length = 0; - for (int i = 0;;) { + for (int i = 0; ; ++i) { ElfW(Dyn) dyn; dynamic_length += sizeof(dyn); - dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic+i++, - sizeof(dyn)); + if (!dumper_->CopyFromProcess(&dyn, GetCrashThread(), dynamic + i, + sizeof(dyn))) { + return false; + } + if (dyn.d_tag == DT_DEBUG) { r_debug = reinterpret_cast<struct r_debug*>(dyn.d_un.d_ptr); continue; @@ -703,11 +708,15 @@ class MinidumpWriter { // Count the number of loaded DSOs int dso_count = 0; struct r_debug debug_entry; - dumper_->CopyFromProcess(&debug_entry, GetCrashThread(), r_debug, - sizeof(debug_entry)); + if (!dumper_->CopyFromProcess(&debug_entry, GetCrashThread(), r_debug, + sizeof(debug_entry))) { + return false; + } for (struct link_map* ptr = debug_entry.r_map; ptr; ) { struct link_map map; - dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map)); + if (!dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map))) + return false; + ptr = map.l_next; dso_count++; } @@ -725,7 +734,9 @@ class MinidumpWriter { // Iterate over DSOs and write their information to mini dump for (struct link_map* ptr = debug_entry.r_map; ptr; ) { struct link_map map; - dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map)); + if (!dumper_->CopyFromProcess(&map, GetCrashThread(), ptr, sizeof(map))) + return false; + ptr = map.l_next; char filename[257] = { 0 }; if (map.l_name) { |