Server-side workaround to handle overlapping modules.
This change is resolving an issue that was caused by the combination of: - Android system libraries being relro packed in N+. - Breakpad dealing with relro packed libraries in a hack way. This is a fix for http://crbug/611824. I also found an use-after-free issue (bug in Minidump::SeekToStreamType). I disallowed the MinidumpStreamInfo copy and assign constructors and the compiler detected another similar issue in Minidump::Print. Then I disabled the copy and assign constructors for most classes in minidump.h (just in case). There are a couple of classes where I couldn't disallow them (since assign is used). This will require a small refactor so I left it out of this CL. R=mark@chromium.org Review URL: https://codereview.chromium.org/2060663002 .
This commit is contained in:
parent
67f738b7ad
commit
24f5931c5e
18 changed files with 239 additions and 39 deletions
|
@ -169,6 +169,7 @@ TEST(MinidumpWriterTest, MappingInfo) {
|
||||||
info.start_addr = kMemoryAddress;
|
info.start_addr = kMemoryAddress;
|
||||||
info.size = memory_size;
|
info.size = memory_size;
|
||||||
info.offset = 0;
|
info.offset = 0;
|
||||||
|
info.exec = false;
|
||||||
strcpy(info.name, kMemoryName);
|
strcpy(info.name, kMemoryName);
|
||||||
|
|
||||||
MappingList mappings;
|
MappingList mappings;
|
||||||
|
@ -323,6 +324,7 @@ TEST(MinidumpWriterTest, MappingInfoContained) {
|
||||||
info.start_addr = kMemoryAddress - memory_size;
|
info.start_addr = kMemoryAddress - memory_size;
|
||||||
info.size = memory_size * 3;
|
info.size = memory_size * 3;
|
||||||
info.offset = 0;
|
info.offset = 0;
|
||||||
|
info.exec = false;
|
||||||
strcpy(info.name, kMemoryName);
|
strcpy(info.name, kMemoryName);
|
||||||
|
|
||||||
MappingList mappings;
|
MappingList mappings;
|
||||||
|
|
|
@ -86,7 +86,14 @@ class CodeModule {
|
||||||
// ownership of. The new CodeModule may be of a different concrete class
|
// ownership of. The new CodeModule may be of a different concrete class
|
||||||
// than the CodeModule being copied, but will behave identically to the
|
// than the CodeModule being copied, but will behave identically to the
|
||||||
// copied CodeModule as far as the CodeModule interface is concerned.
|
// copied CodeModule as far as the CodeModule interface is concerned.
|
||||||
virtual const CodeModule* Copy() const = 0;
|
virtual CodeModule* Copy() const = 0;
|
||||||
|
|
||||||
|
// Getter and setter for shrink_down_delta. This is used when the address
|
||||||
|
// range for a module is shrunk down due to address range conflicts with
|
||||||
|
// other modules. The base_address and size fields are not updated and they
|
||||||
|
// should always reflect the original values (reported in the minidump).
|
||||||
|
virtual uint64_t shrink_down_delta() const = 0;
|
||||||
|
virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
|
@ -35,7 +35,12 @@
|
||||||
#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
|
#ifndef GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
|
||||||
#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
|
#define GOOGLE_BREAKPAD_PROCESSOR_CODE_MODULES_H__
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "google_breakpad/common/breakpad_types.h"
|
#include "google_breakpad/common/breakpad_types.h"
|
||||||
|
#include "processor/linked_ptr.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
@ -91,6 +96,14 @@ class CodeModules {
|
||||||
// returns objects in may differ between a copy and the original CodeModules
|
// returns objects in may differ between a copy and the original CodeModules
|
||||||
// object.
|
// object.
|
||||||
virtual const CodeModules* Copy() const = 0;
|
virtual const CodeModules* Copy() const = 0;
|
||||||
|
|
||||||
|
// Returns a vector of all modules which address ranges needed to be shrunk
|
||||||
|
// down due to address range conflicts with other modules.
|
||||||
|
virtual std::vector<linked_ptr<const CodeModule> >
|
||||||
|
GetShrunkRangeModules() const = 0;
|
||||||
|
|
||||||
|
// Returns true, if module address range shrink is enabled.
|
||||||
|
virtual bool IsModuleShrinkEnabled() const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
|
@ -58,6 +58,9 @@ class MicrodumpModules : public BasicCodeModules {
|
||||||
public:
|
public:
|
||||||
// Takes over ownership of |module|.
|
// Takes over ownership of |module|.
|
||||||
void Add(const CodeModule* module);
|
void Add(const CodeModule* module);
|
||||||
|
|
||||||
|
// Enables/disables module address range shrink.
|
||||||
|
void SetEnableModuleShrink(bool is_enabled);
|
||||||
};
|
};
|
||||||
|
|
||||||
// MicrodumpContext carries a CPU-specific context.
|
// MicrodumpContext carries a CPU-specific context.
|
||||||
|
|
|
@ -151,6 +151,8 @@ class MinidumpStream : public MinidumpObject {
|
||||||
// that implements MinidumpStream can compare expected_size to a
|
// that implements MinidumpStream can compare expected_size to a
|
||||||
// known size as an integrity check.
|
// known size as an integrity check.
|
||||||
virtual bool Read(uint32_t expected_size) = 0;
|
virtual bool Read(uint32_t expected_size) = 0;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpStream);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -191,6 +193,8 @@ class MinidumpContext : public DumpContext {
|
||||||
// for access to data about the minidump file itself, such as whether
|
// for access to data about the minidump file itself, such as whether
|
||||||
// it should be byte-swapped.
|
// it should be byte-swapped.
|
||||||
Minidump* minidump_;
|
Minidump* minidump_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpContext);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -358,6 +362,8 @@ class MinidumpThreadList : public MinidumpStream {
|
||||||
// The list of threads.
|
// The list of threads.
|
||||||
MinidumpThreads* threads_;
|
MinidumpThreads* threads_;
|
||||||
uint32_t thread_count_;
|
uint32_t thread_count_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpThreadList);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -392,7 +398,14 @@ class MinidumpModule : public MinidumpObject,
|
||||||
virtual string debug_file() const;
|
virtual string debug_file() const;
|
||||||
virtual string debug_identifier() const;
|
virtual string debug_identifier() const;
|
||||||
virtual string version() const;
|
virtual string version() const;
|
||||||
virtual const CodeModule* Copy() const;
|
virtual CodeModule* Copy() const;
|
||||||
|
|
||||||
|
// Getter and setter for shrink_down_delta. This is used when the address
|
||||||
|
// range for a module is shrunk down due to address range conflicts with
|
||||||
|
// other modules. The base_address and size fields are not updated and they
|
||||||
|
// should always reflect the original values (reported in the minidump).
|
||||||
|
virtual uint64_t shrink_down_delta() const;
|
||||||
|
virtual void SetShrinkDownDelta(uint64_t shrink_down_delta);
|
||||||
|
|
||||||
// The CodeView record, which contains information to locate the module's
|
// The CodeView record, which contains information to locate the module's
|
||||||
// debugging information (pdb). This is returned as uint8_t* because
|
// debugging information (pdb). This is returned as uint8_t* because
|
||||||
|
@ -501,6 +514,13 @@ class MinidumpModuleList : public MinidumpStream,
|
||||||
virtual const MinidumpModule* GetModuleAtIndex(unsigned int index) const;
|
virtual const MinidumpModule* GetModuleAtIndex(unsigned int index) const;
|
||||||
virtual const CodeModules* Copy() const;
|
virtual const CodeModules* Copy() const;
|
||||||
|
|
||||||
|
// Returns a vector of all modules which address ranges needed to be shrunk
|
||||||
|
// down due to address range conflicts with other modules.
|
||||||
|
virtual vector<linked_ptr<const CodeModule> > GetShrunkRangeModules() const;
|
||||||
|
|
||||||
|
// Returns true, if module address range shrink is enabled.
|
||||||
|
virtual bool IsModuleShrinkEnabled() const;
|
||||||
|
|
||||||
// Print a human-readable representation of the object to stdout.
|
// Print a human-readable representation of the object to stdout.
|
||||||
void Print();
|
void Print();
|
||||||
|
|
||||||
|
@ -525,6 +545,8 @@ class MinidumpModuleList : public MinidumpStream,
|
||||||
|
|
||||||
MinidumpModules *modules_;
|
MinidumpModules *modules_;
|
||||||
uint32_t module_count_;
|
uint32_t module_count_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpModuleList);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -587,6 +609,8 @@ class MinidumpMemoryList : public MinidumpStream {
|
||||||
// The list of regions.
|
// The list of regions.
|
||||||
MemoryRegions *regions_;
|
MemoryRegions *regions_;
|
||||||
uint32_t region_count_;
|
uint32_t region_count_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryList);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -626,6 +650,8 @@ class MinidumpException : public MinidumpStream {
|
||||||
|
|
||||||
MDRawExceptionStream exception_;
|
MDRawExceptionStream exception_;
|
||||||
MinidumpContext* context_;
|
MinidumpContext* context_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpException);
|
||||||
};
|
};
|
||||||
|
|
||||||
// MinidumpAssertion wraps MDRawAssertionInfo, which contains information
|
// MinidumpAssertion wraps MDRawAssertionInfo, which contains information
|
||||||
|
@ -666,6 +692,8 @@ class MinidumpAssertion : public MinidumpStream {
|
||||||
string expression_;
|
string expression_;
|
||||||
string function_;
|
string function_;
|
||||||
string file_;
|
string file_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpAssertion);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -719,6 +747,8 @@ class MinidumpSystemInfo : public MinidumpStream {
|
||||||
|
|
||||||
// A string identifying the CPU vendor, if known.
|
// A string identifying the CPU vendor, if known.
|
||||||
const string* cpu_vendor_;
|
const string* cpu_vendor_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpSystemInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -752,6 +782,8 @@ class MinidumpMiscInfo : public MinidumpStream {
|
||||||
string daylight_name_;
|
string daylight_name_;
|
||||||
string build_string_;
|
string build_string_;
|
||||||
string dbg_bld_str_;
|
string dbg_bld_str_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpMiscInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -784,6 +816,8 @@ class MinidumpBreakpadInfo : public MinidumpStream {
|
||||||
bool Read(uint32_t expected_size_);
|
bool Read(uint32_t expected_size_);
|
||||||
|
|
||||||
MDRawBreakpadInfo breakpad_info_;
|
MDRawBreakpadInfo breakpad_info_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpBreakpadInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
// MinidumpMemoryInfo wraps MDRawMemoryInfo, which provides information
|
// MinidumpMemoryInfo wraps MDRawMemoryInfo, which provides information
|
||||||
|
@ -854,6 +888,8 @@ class MinidumpMemoryInfoList : public MinidumpStream {
|
||||||
|
|
||||||
MinidumpMemoryInfos* infos_;
|
MinidumpMemoryInfos* infos_;
|
||||||
uint32_t info_count_;
|
uint32_t info_count_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpMemoryInfoList);
|
||||||
};
|
};
|
||||||
|
|
||||||
// MinidumpLinuxMaps wraps information about a single mapped memory region
|
// MinidumpLinuxMaps wraps information about a single mapped memory region
|
||||||
|
@ -1061,6 +1097,9 @@ class Minidump {
|
||||||
// Print a human-readable representation of the object to stdout.
|
// Print a human-readable representation of the object to stdout.
|
||||||
void Print();
|
void Print();
|
||||||
|
|
||||||
|
// Is the OS Android.
|
||||||
|
bool IsAndroid();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// MinidumpStreamInfo is used in the MinidumpStreamMap. It lets
|
// MinidumpStreamInfo is used in the MinidumpStreamMap. It lets
|
||||||
// the Minidump object locate interesting streams quickly, and
|
// the Minidump object locate interesting streams quickly, and
|
||||||
|
@ -1074,6 +1113,9 @@ class Minidump {
|
||||||
|
|
||||||
// Pointer to the stream if cached, or NULL if not yet populated
|
// Pointer to the stream if cached, or NULL if not yet populated
|
||||||
MinidumpStream* stream;
|
MinidumpStream* stream;
|
||||||
|
|
||||||
|
private:
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(MinidumpStreamInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef vector<MDRawDirectory> MinidumpDirectoryEntries;
|
typedef vector<MDRawDirectory> MinidumpDirectoryEntries;
|
||||||
|
@ -1121,6 +1163,8 @@ class Minidump {
|
||||||
// construction or after a failed Read(); true following a successful
|
// construction or after a failed Read(); true following a successful
|
||||||
// Read().
|
// Read().
|
||||||
bool valid_;
|
bool valid_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(Minidump);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,10 @@
|
||||||
|
|
||||||
#include "common/using_std_string.h"
|
#include "common/using_std_string.h"
|
||||||
#include "google_breakpad/common/breakpad_types.h"
|
#include "google_breakpad/common/breakpad_types.h"
|
||||||
#include "google_breakpad/processor/system_info.h"
|
#include "google_breakpad/processor/code_modules.h"
|
||||||
#include "google_breakpad/processor/minidump.h"
|
#include "google_breakpad/processor/minidump.h"
|
||||||
|
#include "google_breakpad/processor/system_info.h"
|
||||||
|
#include "processor/linked_ptr.h"
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
@ -109,6 +111,9 @@ class ProcessState {
|
||||||
}
|
}
|
||||||
const SystemInfo* system_info() const { return &system_info_; }
|
const SystemInfo* system_info() const { return &system_info_; }
|
||||||
const CodeModules* modules() const { return modules_; }
|
const CodeModules* modules() const { return modules_; }
|
||||||
|
const vector<linked_ptr<const CodeModule> >* shrunk_range_modules() const {
|
||||||
|
return &shrunk_range_modules_;
|
||||||
|
}
|
||||||
const vector<const CodeModule*>* modules_without_symbols() const {
|
const vector<const CodeModule*>* modules_without_symbols() const {
|
||||||
return &modules_without_symbols_;
|
return &modules_without_symbols_;
|
||||||
}
|
}
|
||||||
|
@ -172,6 +177,10 @@ class ProcessState {
|
||||||
// ProcessState.
|
// ProcessState.
|
||||||
const CodeModules *modules_;
|
const CodeModules *modules_;
|
||||||
|
|
||||||
|
// The modules which virtual address ranges were shrunk down due to
|
||||||
|
// virtual address conflicts.
|
||||||
|
vector<linked_ptr<const CodeModule> > shrunk_range_modules_;
|
||||||
|
|
||||||
// The modules that didn't have symbols when the report was processed.
|
// The modules that didn't have symbols when the report was processed.
|
||||||
vector<const CodeModule*> modules_without_symbols_;
|
vector<const CodeModule*> modules_without_symbols_;
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,7 @@ class BasicCodeModule : public CodeModule {
|
||||||
explicit BasicCodeModule(const CodeModule *that)
|
explicit BasicCodeModule(const CodeModule *that)
|
||||||
: base_address_(that->base_address()),
|
: base_address_(that->base_address()),
|
||||||
size_(that->size()),
|
size_(that->size()),
|
||||||
|
shrink_down_delta_(that->shrink_down_delta()),
|
||||||
code_file_(that->code_file()),
|
code_file_(that->code_file()),
|
||||||
code_identifier_(that->code_identifier()),
|
code_identifier_(that->code_identifier()),
|
||||||
debug_file_(that->debug_file()),
|
debug_file_(that->debug_file()),
|
||||||
|
@ -71,6 +72,7 @@ class BasicCodeModule : public CodeModule {
|
||||||
const string &version)
|
const string &version)
|
||||||
: base_address_(base_address),
|
: base_address_(base_address),
|
||||||
size_(size),
|
size_(size),
|
||||||
|
shrink_down_delta_(0),
|
||||||
code_file_(code_file),
|
code_file_(code_file),
|
||||||
code_identifier_(code_identifier),
|
code_identifier_(code_identifier),
|
||||||
debug_file_(debug_file),
|
debug_file_(debug_file),
|
||||||
|
@ -83,16 +85,21 @@ class BasicCodeModule : public CodeModule {
|
||||||
// members.
|
// members.
|
||||||
virtual uint64_t base_address() const { return base_address_; }
|
virtual uint64_t base_address() const { return base_address_; }
|
||||||
virtual uint64_t size() const { return size_; }
|
virtual uint64_t size() const { return size_; }
|
||||||
|
virtual uint64_t shrink_down_delta() const { return shrink_down_delta_; }
|
||||||
|
virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {
|
||||||
|
shrink_down_delta_ = shrink_down_delta;
|
||||||
|
}
|
||||||
virtual string code_file() const { return code_file_; }
|
virtual string code_file() const { return code_file_; }
|
||||||
virtual string code_identifier() const { return code_identifier_; }
|
virtual string code_identifier() const { return code_identifier_; }
|
||||||
virtual string debug_file() const { return debug_file_; }
|
virtual string debug_file() const { return debug_file_; }
|
||||||
virtual string debug_identifier() const { return debug_identifier_; }
|
virtual string debug_identifier() const { return debug_identifier_; }
|
||||||
virtual string version() const { return version_; }
|
virtual string version() const { return version_; }
|
||||||
virtual const CodeModule* Copy() const { return new BasicCodeModule(this); }
|
virtual CodeModule* Copy() const { return new BasicCodeModule(this); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t base_address_;
|
uint64_t base_address_;
|
||||||
uint64_t size_;
|
uint64_t size_;
|
||||||
|
uint64_t shrink_down_delta_;
|
||||||
string code_file_;
|
string code_file_;
|
||||||
string code_identifier_;
|
string code_identifier_;
|
||||||
string debug_file_;
|
string debug_file_;
|
||||||
|
|
|
@ -38,6 +38,8 @@
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "google_breakpad/processor/code_module.h"
|
#include "google_breakpad/processor/code_module.h"
|
||||||
#include "processor/linked_ptr.h"
|
#include "processor/linked_ptr.h"
|
||||||
#include "processor/logging.h"
|
#include "processor/logging.h"
|
||||||
|
@ -45,31 +47,50 @@
|
||||||
|
|
||||||
namespace google_breakpad {
|
namespace google_breakpad {
|
||||||
|
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
BasicCodeModules::BasicCodeModules(const CodeModules *that)
|
BasicCodeModules::BasicCodeModules(const CodeModules *that)
|
||||||
: main_address_(0), map_() {
|
: main_address_(0), map_() {
|
||||||
BPLOG_IF(ERROR, !that) << "BasicCodeModules::BasicCodeModules requires "
|
BPLOG_IF(ERROR, !that) << "BasicCodeModules::BasicCodeModules requires "
|
||||||
"|that|";
|
"|that|";
|
||||||
assert(that);
|
assert(that);
|
||||||
|
|
||||||
|
map_.SetEnableShrinkDown(that->IsModuleShrinkEnabled());
|
||||||
|
|
||||||
const CodeModule *main_module = that->GetMainModule();
|
const CodeModule *main_module = that->GetMainModule();
|
||||||
if (main_module)
|
if (main_module)
|
||||||
main_address_ = main_module->base_address();
|
main_address_ = main_module->base_address();
|
||||||
|
|
||||||
unsigned int count = that->module_count();
|
unsigned int count = that->module_count();
|
||||||
for (unsigned int module_sequence = 0;
|
for (unsigned int i = 0; i < count; ++i) {
|
||||||
module_sequence < count;
|
|
||||||
++module_sequence) {
|
|
||||||
// Make a copy of the module and insert it into the map. Use
|
// Make a copy of the module and insert it into the map. Use
|
||||||
// GetModuleAtIndex because ordering is unimportant when slurping the
|
// GetModuleAtIndex because ordering is unimportant when slurping the
|
||||||
// entire list, and GetModuleAtIndex may be faster than
|
// entire list, and GetModuleAtIndex may be faster than
|
||||||
// GetModuleAtSequence.
|
// GetModuleAtSequence.
|
||||||
linked_ptr<const CodeModule> module(
|
linked_ptr<const CodeModule> module(that->GetModuleAtIndex(i)->Copy());
|
||||||
that->GetModuleAtIndex(module_sequence)->Copy());
|
|
||||||
if (!map_.StoreRange(module->base_address(), module->size(), module)) {
|
if (!map_.StoreRange(module->base_address(), module->size(), module)) {
|
||||||
BPLOG(ERROR) << "Module " << module->code_file() <<
|
BPLOG(ERROR) << "Module " << module->code_file()
|
||||||
" could not be stored";
|
<< " could not be stored";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Report modules with shrunk ranges.
|
||||||
|
for (unsigned int i = 0; i < count; ++i) {
|
||||||
|
linked_ptr<const CodeModule> module(that->GetModuleAtIndex(i)->Copy());
|
||||||
|
uint64_t delta = 0;
|
||||||
|
if (map_.RetrieveRange(module->base_address() + module->size() - 1,
|
||||||
|
&module, NULL /* base */, &delta, NULL /* size */) &&
|
||||||
|
delta > 0) {
|
||||||
|
BPLOG(INFO) << "The range for module " << module->code_file()
|
||||||
|
<< " was shrunk down by " << HexString(delta) << " bytes.";
|
||||||
|
linked_ptr<CodeModule> shrunk_range_module(module->Copy());
|
||||||
|
shrunk_range_module->SetShrinkDownDelta(delta);
|
||||||
|
shrunk_range_modules_.push_back(shrunk_range_module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(ivanpe): Report modules with conflicting ranges. The list of such
|
||||||
|
// modules should be copied from |that|.
|
||||||
}
|
}
|
||||||
|
|
||||||
BasicCodeModules::BasicCodeModules() : main_address_(0), map_() { }
|
BasicCodeModules::BasicCodeModules() : main_address_(0), map_() { }
|
||||||
|
@ -122,4 +143,13 @@ const CodeModules* BasicCodeModules::Copy() const {
|
||||||
return new BasicCodeModules(this);
|
return new BasicCodeModules(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<linked_ptr<const CodeModule> >
|
||||||
|
BasicCodeModules::GetShrunkRangeModules() const {
|
||||||
|
return shrunk_range_modules_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool BasicCodeModules::IsModuleShrinkEnabled() const {
|
||||||
|
return map_.IsShrinkDownEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace google_breakpad
|
} // namespace google_breakpad
|
||||||
|
|
|
@ -43,6 +43,8 @@
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "google_breakpad/processor/code_modules.h"
|
#include "google_breakpad/processor/code_modules.h"
|
||||||
#include "processor/linked_ptr.h"
|
#include "processor/linked_ptr.h"
|
||||||
#include "processor/range_map.h"
|
#include "processor/range_map.h"
|
||||||
|
@ -67,6 +69,9 @@ class BasicCodeModules : public CodeModules {
|
||||||
virtual const CodeModule* GetModuleAtSequence(unsigned int sequence) const;
|
virtual const CodeModule* GetModuleAtSequence(unsigned int sequence) const;
|
||||||
virtual const CodeModule* GetModuleAtIndex(unsigned int index) const;
|
virtual const CodeModule* GetModuleAtIndex(unsigned int index) const;
|
||||||
virtual const CodeModules* Copy() const;
|
virtual const CodeModules* Copy() const;
|
||||||
|
virtual std::vector<linked_ptr<const CodeModule> >
|
||||||
|
GetShrunkRangeModules() const;
|
||||||
|
virtual bool IsModuleShrinkEnabled() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
BasicCodeModules();
|
BasicCodeModules();
|
||||||
|
@ -78,6 +83,10 @@ class BasicCodeModules : public CodeModules {
|
||||||
// address range.
|
// address range.
|
||||||
RangeMap<uint64_t, linked_ptr<const CodeModule> > map_;
|
RangeMap<uint64_t, linked_ptr<const CodeModule> > map_;
|
||||||
|
|
||||||
|
// A vector of all CodeModules that were shrunk downs due to
|
||||||
|
// address range conflicts.
|
||||||
|
std::vector<linked_ptr<const CodeModule> > shrunk_range_modules_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Disallow copy constructor and assignment operator.
|
// Disallow copy constructor and assignment operator.
|
||||||
BasicCodeModules(const BasicCodeModules &that);
|
BasicCodeModules(const BasicCodeModules &that);
|
||||||
|
|
|
@ -68,9 +68,11 @@ class TestCodeModule : public CodeModule {
|
||||||
virtual string debug_file() const { return ""; }
|
virtual string debug_file() const { return ""; }
|
||||||
virtual string debug_identifier() const { return ""; }
|
virtual string debug_identifier() const { return ""; }
|
||||||
virtual string version() const { return ""; }
|
virtual string version() const { return ""; }
|
||||||
virtual const CodeModule* Copy() const {
|
virtual CodeModule* Copy() const {
|
||||||
return new TestCodeModule(code_file_);
|
return new TestCodeModule(code_file_);
|
||||||
}
|
}
|
||||||
|
virtual uint64_t shrink_down_delta() const { return 0; }
|
||||||
|
virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string code_file_;
|
string code_file_;
|
||||||
|
|
|
@ -79,9 +79,11 @@ class TestCodeModule : public CodeModule {
|
||||||
virtual string debug_file() const { return ""; }
|
virtual string debug_file() const { return ""; }
|
||||||
virtual string debug_identifier() const { return ""; }
|
virtual string debug_identifier() const { return ""; }
|
||||||
virtual string version() const { return ""; }
|
virtual string version() const { return ""; }
|
||||||
virtual const CodeModule* Copy() const {
|
virtual CodeModule* Copy() const {
|
||||||
return new TestCodeModule(code_file_);
|
return new TestCodeModule(code_file_);
|
||||||
}
|
}
|
||||||
|
virtual uint64_t shrink_down_delta() const { return 0; }
|
||||||
|
virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
string code_file_;
|
string code_file_;
|
||||||
|
|
|
@ -110,6 +110,9 @@ void MicrodumpModules::Add(const CodeModule* module) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MicrodumpModules::SetEnableModuleShrink(bool is_enabled) {
|
||||||
|
map_.SetEnableShrinkDown(is_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// MicrodumpContext
|
// MicrodumpContext
|
||||||
|
@ -262,6 +265,7 @@ Microdump::Microdump(const string& contents)
|
||||||
} else if (os_id == "A") {
|
} else if (os_id == "A") {
|
||||||
system_info_->os = "Android";
|
system_info_->os = "Android";
|
||||||
system_info_->os_short = "android";
|
system_info_->os_short = "android";
|
||||||
|
modules_->SetEnableModuleShrink(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
// OS line also contains release and version for future use.
|
// OS line also contains release and version for future use.
|
||||||
|
|
|
@ -201,7 +201,7 @@ TEST_F(MicrodumpProcessorTest, TestProcessX86) {
|
||||||
AnalyzeDump("microdump-x86.dmp", false /* omit_symbols */,
|
AnalyzeDump("microdump-x86.dmp", false /* omit_symbols */,
|
||||||
4 /* expected_cpu_count */, &state);
|
4 /* expected_cpu_count */, &state);
|
||||||
|
|
||||||
ASSERT_EQ(105U, state.modules()->module_count());
|
ASSERT_EQ(124U, state.modules()->module_count());
|
||||||
ASSERT_EQ("x86", state.system_info()->cpu);
|
ASSERT_EQ("x86", state.system_info()->cpu);
|
||||||
ASSERT_EQ("asus/WW_Z00A/Z00A:5.0/LRX21V/2.19.40.22_20150627_5104_user:user/"
|
ASSERT_EQ("asus/WW_Z00A/Z00A:5.0/LRX21V/2.19.40.22_20150627_5104_user:user/"
|
||||||
"release-keys", state.system_info()->os_version);
|
"release-keys", state.system_info()->os_version);
|
||||||
|
@ -216,11 +216,11 @@ TEST_F(MicrodumpProcessorTest, TestProcessMultiple) {
|
||||||
ProcessState state;
|
ProcessState state;
|
||||||
AnalyzeDump("microdump-multiple.dmp", false /* omit_symbols */,
|
AnalyzeDump("microdump-multiple.dmp", false /* omit_symbols */,
|
||||||
6 /* expected_cpu_count */, &state);
|
6 /* expected_cpu_count */, &state);
|
||||||
ASSERT_EQ(133U, state.modules()->module_count());
|
ASSERT_EQ(156U, state.modules()->module_count());
|
||||||
ASSERT_EQ("arm", state.system_info()->cpu);
|
ASSERT_EQ("arm", state.system_info()->cpu);
|
||||||
ASSERT_EQ("lge/p1_tmo_us/p1:6.0/MRA58K/1603210524c8d:user/release-keys",
|
ASSERT_EQ("lge/p1_tmo_us/p1:6.0/MRA58K/1603210524c8d:user/release-keys",
|
||||||
state.system_info()->os_version);
|
state.system_info()->os_version);
|
||||||
ASSERT_EQ(2U, state.threads()->at(0)->frames()->size());
|
ASSERT_EQ(5U, state.threads()->at(0)->frames()->size());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(MicrodumpProcessorTest, TestProcessMips) {
|
TEST_F(MicrodumpProcessorTest, TestProcessMips) {
|
||||||
|
@ -249,7 +249,7 @@ TEST_F(MicrodumpProcessorTest, TestProcessMips64) {
|
||||||
AnalyzeDump("microdump-mips64.dmp", false /* omit_symbols */,
|
AnalyzeDump("microdump-mips64.dmp", false /* omit_symbols */,
|
||||||
1 /* expected_cpu_count */, &state);
|
1 /* expected_cpu_count */, &state);
|
||||||
|
|
||||||
ASSERT_EQ(7U, state.modules()->module_count());
|
ASSERT_EQ(8U, state.modules()->module_count());
|
||||||
ASSERT_EQ("mips64", state.system_info()->cpu);
|
ASSERT_EQ("mips64", state.system_info()->cpu);
|
||||||
ASSERT_EQ("3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015",
|
ASSERT_EQ("3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015",
|
||||||
state.system_info()->os_version);
|
state.system_info()->os_version);
|
||||||
|
|
|
@ -2109,11 +2109,21 @@ string MinidumpModule::version() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const CodeModule* MinidumpModule::Copy() const {
|
CodeModule* MinidumpModule::Copy() const {
|
||||||
return new BasicCodeModule(this);
|
return new BasicCodeModule(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t MinidumpModule::shrink_down_delta() const {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinidumpModule::SetShrinkDownDelta(uint64_t shrink_down_delta) {
|
||||||
|
// Not implemented
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) {
|
const uint8_t* MinidumpModule::GetCVRecord(uint32_t* size) {
|
||||||
if (!module_valid_) {
|
if (!module_valid_) {
|
||||||
BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
|
BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord";
|
||||||
|
@ -2497,6 +2507,7 @@ MinidumpModuleList::MinidumpModuleList(Minidump* minidump)
|
||||||
range_map_(new RangeMap<uint64_t, unsigned int>()),
|
range_map_(new RangeMap<uint64_t, unsigned int>()),
|
||||||
modules_(NULL),
|
modules_(NULL),
|
||||||
module_count_(0) {
|
module_count_(0) {
|
||||||
|
range_map_->SetEnableShrinkDown(minidump_->IsAndroid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2741,6 +2752,14 @@ const CodeModules* MinidumpModuleList::Copy() const {
|
||||||
return new BasicCodeModules(this);
|
return new BasicCodeModules(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
vector<linked_ptr<const CodeModule> >
|
||||||
|
MinidumpModuleList::GetShrunkRangeModules() const {
|
||||||
|
return vector<linked_ptr<const CodeModule> >();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MinidumpModuleList::IsModuleShrinkEnabled() const {
|
||||||
|
return range_map_->IsShrinkDownEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
void MinidumpModuleList::Print() {
|
void MinidumpModuleList::Print() {
|
||||||
if (!valid_) {
|
if (!valid_) {
|
||||||
|
@ -4532,6 +4551,24 @@ MinidumpLinuxMapsList *Minidump::GetLinuxMapsList() {
|
||||||
return GetStream(&linux_maps_list);
|
return GetStream(&linux_maps_list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Minidump::IsAndroid() {
|
||||||
|
// Save the current stream position
|
||||||
|
off_t saved_position = Tell();
|
||||||
|
if (saved_position == -1) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const MDRawSystemInfo* system_info =
|
||||||
|
GetSystemInfo() ? GetSystemInfo()->system_info() : NULL;
|
||||||
|
|
||||||
|
// Restore position and return
|
||||||
|
if (!SeekSet(saved_position)) {
|
||||||
|
BPLOG(ERROR) << "Couldn't seek back to saved position";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return system_info && system_info->platform_id == MD_OS_ANDROID;
|
||||||
|
}
|
||||||
|
|
||||||
static const char* get_stream_name(uint32_t stream_type) {
|
static const char* get_stream_name(uint32_t stream_type) {
|
||||||
switch (stream_type) {
|
switch (stream_type) {
|
||||||
case MD_UNUSED_STREAM:
|
case MD_UNUSED_STREAM:
|
||||||
|
@ -4645,7 +4682,7 @@ void Minidump::Print() {
|
||||||
iterator != stream_map_->end();
|
iterator != stream_map_->end();
|
||||||
++iterator) {
|
++iterator) {
|
||||||
uint32_t stream_type = iterator->first;
|
uint32_t stream_type = iterator->first;
|
||||||
MinidumpStreamInfo info = iterator->second;
|
const MinidumpStreamInfo& info = iterator->second;
|
||||||
printf(" stream type 0x%x (%s) at index %d\n", stream_type,
|
printf(" stream type 0x%x (%s) at index %d\n", stream_type,
|
||||||
get_stream_name(stream_type),
|
get_stream_name(stream_type),
|
||||||
info.stream_index);
|
info.stream_index);
|
||||||
|
@ -4802,7 +4839,7 @@ bool Minidump::SeekToStreamType(uint32_t stream_type,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
MinidumpStreamInfo info = iterator->second;
|
const MinidumpStreamInfo& info = iterator->second;
|
||||||
if (info.stream_index >= header_.stream_count) {
|
if (info.stream_index >= header_.stream_count) {
|
||||||
BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
|
BPLOG(ERROR) << "SeekToStreamType: type " << stream_type <<
|
||||||
" out of range: " <<
|
" out of range: " <<
|
||||||
|
|
|
@ -126,8 +126,20 @@ ProcessResult MinidumpProcessor::Process(
|
||||||
// Put a copy of the module list into ProcessState object. This is not
|
// Put a copy of the module list into ProcessState object. This is not
|
||||||
// necessarily a MinidumpModuleList, but it adheres to the CodeModules
|
// necessarily a MinidumpModuleList, but it adheres to the CodeModules
|
||||||
// interface, which is all that ProcessState needs to expose.
|
// interface, which is all that ProcessState needs to expose.
|
||||||
if (module_list)
|
if (module_list) {
|
||||||
process_state->modules_ = module_list->Copy();
|
process_state->modules_ = module_list->Copy();
|
||||||
|
process_state->shrunk_range_modules_ =
|
||||||
|
process_state->modules_->GetShrunkRangeModules();
|
||||||
|
for (unsigned int i = 0;
|
||||||
|
i < process_state->shrunk_range_modules_.size();
|
||||||
|
i++) {
|
||||||
|
linked_ptr<const CodeModule> module =
|
||||||
|
process_state->shrunk_range_modules_[i];
|
||||||
|
BPLOG(INFO) << "The range for module " << module->code_file()
|
||||||
|
<< " was shrunk down by " << HexString(
|
||||||
|
module->shrink_down_delta()) << " bytes. ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MinidumpMemoryList *memory_list = dump->GetMemoryList();
|
MinidumpMemoryList *memory_list = dump->GetMemoryList();
|
||||||
if (memory_list) {
|
if (memory_list) {
|
||||||
|
|
|
@ -52,6 +52,11 @@ void RangeMap<AddressType, EntryType>::SetEnableShrinkDown(
|
||||||
enable_shrink_down_ = enable_shrink_down;
|
enable_shrink_down_ = enable_shrink_down;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename AddressType, typename EntryType>
|
||||||
|
bool RangeMap<AddressType, EntryType>::IsShrinkDownEnabled() const {
|
||||||
|
return enable_shrink_down_;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename AddressType, typename EntryType>
|
template<typename AddressType, typename EntryType>
|
||||||
bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
|
bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base,
|
||||||
const AddressType &size,
|
const AddressType &size,
|
||||||
|
|
|
@ -60,6 +60,7 @@ class RangeMap {
|
||||||
// will be shrunk down by moving its start position to a higher address so
|
// will be shrunk down by moving its start position to a higher address so
|
||||||
// that it does not overlap anymore.
|
// that it does not overlap anymore.
|
||||||
void SetEnableShrinkDown(bool enable_shrink_down);
|
void SetEnableShrinkDown(bool enable_shrink_down);
|
||||||
|
bool IsShrinkDownEnabled() const;
|
||||||
|
|
||||||
// Inserts a range into the map. Returns false for a parameter error,
|
// Inserts a range into the map. Returns false for a parameter error,
|
||||||
// or if the location of the range would conflict with a range already
|
// or if the location of the range would conflict with a range already
|
||||||
|
|
|
@ -48,6 +48,7 @@
|
||||||
#include "google_breakpad/processor/memory_region.h"
|
#include "google_breakpad/processor/memory_region.h"
|
||||||
#include "google_breakpad/processor/symbol_supplier.h"
|
#include "google_breakpad/processor/symbol_supplier.h"
|
||||||
#include "google_breakpad/processor/system_info.h"
|
#include "google_breakpad/processor/system_info.h"
|
||||||
|
#include "processor/linked_ptr.h"
|
||||||
|
|
||||||
class MockMemoryRegion: public google_breakpad::MemoryRegion {
|
class MockMemoryRegion: public google_breakpad::MemoryRegion {
|
||||||
public:
|
public:
|
||||||
|
@ -114,9 +115,11 @@ class MockCodeModule: public google_breakpad::CodeModule {
|
||||||
string debug_file() const { return code_file_; }
|
string debug_file() const { return code_file_; }
|
||||||
string debug_identifier() const { return code_file_; }
|
string debug_identifier() const { return code_file_; }
|
||||||
string version() const { return version_; }
|
string version() const { return version_; }
|
||||||
const google_breakpad::CodeModule *Copy() const {
|
google_breakpad::CodeModule *Copy() const {
|
||||||
abort(); // Tests won't use this.
|
abort(); // Tests won't use this.
|
||||||
}
|
}
|
||||||
|
virtual uint64_t shrink_down_delta() const { return 0; }
|
||||||
|
virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
uint64_t base_address_;
|
uint64_t base_address_;
|
||||||
|
@ -157,7 +160,17 @@ class MockCodeModules: public google_breakpad::CodeModules {
|
||||||
return modules_.at(index);
|
return modules_.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CodeModules *Copy() const { abort(); } // Tests won't use this.
|
CodeModules *Copy() const { abort(); } // Tests won't use this
|
||||||
|
|
||||||
|
virtual std::vector<google_breakpad::linked_ptr<const CodeModule> >
|
||||||
|
GetShrunkRangeModules() const {
|
||||||
|
return std::vector<google_breakpad::linked_ptr<const CodeModule> >();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns true, if module address range shrink is enabled.
|
||||||
|
bool IsModuleShrinkEnabled() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
typedef std::vector<const MockCodeModule *> ModuleVector;
|
typedef std::vector<const MockCodeModule *> ModuleVector;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue