aboutsummaryrefslogtreecommitdiff
path: root/src/google_breakpad
diff options
context:
space:
mode:
authorJoshua Peraza <jperaza@chromium.org>2016-12-16 12:10:33 -0800
committerJoshua Peraza <jperaza@chromium.org>2016-12-16 20:15:04 +0000
commitc2d969cb1050803961a53cfdbbcff5c69e579ebb (patch)
treed820694a130c38d7ab4898e26db38b13d606434b /src/google_breakpad
parentFix unit tests expecting no output when a microdump is suppressed. (diff)
downloadbreakpad-c2d969cb1050803961a53cfdbbcff5c69e579ebb.tar.xz
Added classes to support reading unloaded module lists in minidumps.
The implementations of Module/UnloadedModule and ModuleList/UnloadedModuleList are very similar. They have been made separate classes because they operate on different structs, complicating factoring code into a base class and have sufficiently different implementation that templates would not be suitable. When unloaded modules have partially overlapping ranges, the module shrink down feature is used to move the start of the higher range to the end of the lower range. If two unloaded modules overlap identically, the second module will not be added to the range map and the failure ignored. Places where MinidumpUnloadedModule differs from MinidumpModule: code_identifier: the android/linux case is deleted since cv_records never exist. debug_file/debug_identifier/version: always return empty strings. Read: an expected size is provided as opposed to MD_MODULE_SIZE. A seek is used if there are extra, unused bytes. Places where MinidumpUnloadedModuleList differs from MinidumpModuleList: Read: entry and header size is provided in the header in addition to count. This changes the checks and handling of padding. Failures from StoreRange are ignored. GetMainModule: always returns NULL. BUG= Change-Id: I52e93d3ccc38483f50a6418fede8b506ec879aaa Reviewed-on: https://chromium-review.googlesource.com/421566 Reviewed-by: Joshua Peraza <jperaza@chromium.org>
Diffstat (limited to 'src/google_breakpad')
-rw-r--r--src/google_breakpad/common/minidump_format.h14
-rw-r--r--src/google_breakpad/processor/minidump.h113
2 files changed, 127 insertions, 0 deletions
diff --git a/src/google_breakpad/common/minidump_format.h b/src/google_breakpad/common/minidump_format.h
index 251e503d..b99c8f7c 100644
--- a/src/google_breakpad/common/minidump_format.h
+++ b/src/google_breakpad/common/minidump_format.h
@@ -677,6 +677,20 @@ typedef enum {
} MDOSPlatform;
typedef struct {
+ uint64_t base_of_image;
+ uint32_t size_of_image;
+ uint32_t checksum;
+ uint32_t time_date_stamp;
+ MDRVA module_name_rva;
+} MDRawUnloadedModule;
+
+typedef struct {
+ uint32_t size_of_header;
+ uint32_t size_of_entry;
+ uint32_t number_of_entries;
+} MDRawUnloadedModuleList; /* MINIDUMP_UNLOADED_MODULE_LIST */
+
+typedef struct {
uint16_t year;
uint16_t month;
uint16_t day_of_week;
diff --git a/src/google_breakpad/processor/minidump.h b/src/google_breakpad/processor/minidump.h
index c8c3cd48..1bfc7d9e 100644
--- a/src/google_breakpad/processor/minidump.h
+++ b/src/google_breakpad/processor/minidump.h
@@ -752,6 +752,118 @@ class MinidumpSystemInfo : public MinidumpStream {
};
+// MinidumpUnloadedModule wraps MDRawUnloadedModule
+class MinidumpUnloadedModule : public MinidumpObject,
+ public CodeModule {
+ public:
+ ~MinidumpUnloadedModule() override;
+
+ const MDRawUnloadedModule* module() const {
+ return valid_ ? &unloaded_module_ : NULL;
+ }
+
+ // CodeModule implementation
+ uint64_t base_address() const override {
+ return valid_ ? unloaded_module_.base_of_image : 0;
+ }
+ uint64_t size() const override {
+ return valid_ ? unloaded_module_.size_of_image : 0;
+ }
+ string code_file() const override;
+ string code_identifier() const override;
+ string debug_file() const override;
+ string debug_identifier() const override;
+ string version() const override;
+ CodeModule* Copy() const override;
+ uint64_t shrink_down_delta() const override;
+ void SetShrinkDownDelta(uint64_t shrink_down_delta) override;
+
+ protected:
+ explicit MinidumpUnloadedModule(Minidump* minidump);
+
+ private:
+ // These objects are managed by MinidumpUnloadedModuleList
+ friend class MinidumpUnloadedModuleList;
+
+ // This works like MinidumpStream::Read, but is driven by
+ // MinidumpUnloadedModuleList.
+ bool Read(uint32_t expected_size);
+
+ // Reads the module name. This is done separately from Read to
+ // allow contiguous reading of code modules by MinidumpUnloadedModuleList.
+ bool ReadAuxiliaryData();
+
+ // True after a successful Read. This is different from valid_, which
+ // is not set true until ReadAuxiliaryData also completes successfully.
+ // module_valid_ is only used by ReadAuxiliaryData and the functions it
+ // calls to determine whether the object is ready for auxiliary data to
+ // be read.
+ bool module_valid_;
+
+ MDRawUnloadedModule unloaded_module_;
+
+ // Cached module name
+ const string* name_;
+};
+
+
+// MinidumpUnloadedModuleList contains all the unloaded code modules for a
+// process in the form of MinidumpUnloadedModules. It maintains a map of
+// these modules so that it may easily provide a code module corresponding
+// to a specific address. If multiple modules in the list have identical
+// ranges, only the first module encountered is recorded in the range map.
+class MinidumpUnloadedModuleList : public MinidumpStream,
+ public CodeModules {
+ public:
+ ~MinidumpUnloadedModuleList() override;
+
+ static void set_max_modules(uint32_t max_modules) {
+ max_modules_ = max_modules;
+ }
+ static uint32_t max_modules() { return max_modules_; }
+
+ // CodeModules implementation.
+ unsigned int module_count() const override {
+ return valid_ ? module_count_ : 0;
+ }
+ const MinidumpUnloadedModule*
+ GetModuleForAddress(uint64_t address) const override;
+ const MinidumpUnloadedModule* GetMainModule() const override;
+ const MinidumpUnloadedModule*
+ GetModuleAtSequence(unsigned int sequence) const override;
+ const MinidumpUnloadedModule*
+ GetModuleAtIndex(unsigned int index) const override;
+ const CodeModules* Copy() const override;
+ vector<linked_ptr<const CodeModule>> GetShrunkRangeModules() const override;
+ bool IsModuleShrinkEnabled() const override;
+
+ protected:
+ explicit MinidumpUnloadedModuleList(Minidump* minidump_);
+
+ private:
+ friend class Minidump;
+
+ typedef vector<MinidumpUnloadedModule> MinidumpUnloadedModules;
+
+ static const uint32_t kStreamType = MD_UNLOADED_MODULE_LIST_STREAM;
+
+
+ bool Read(uint32_t expected_size_);
+
+ // The largest number of modules that will be read from a minidump. The
+ // default is 1024.
+ static uint32_t max_modules_;
+
+ // Access to module indices using addresses as the key.
+ RangeMap<uint64_t, unsigned int> *range_map_;
+
+ MinidumpUnloadedModules *unloaded_modules_;
+ uint32_t module_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(MinidumpUnloadedModuleList);
+};
+
+
// MinidumpMiscInfo wraps MDRawMiscInfo and provides information about
// the process that generated the minidump, and optionally additional system
// information. See also MinidumpSystemInfo.
@@ -1041,6 +1153,7 @@ class Minidump {
virtual MinidumpException* GetException();
virtual MinidumpAssertion* GetAssertion();
virtual MinidumpSystemInfo* GetSystemInfo();
+ virtual MinidumpUnloadedModuleList* GetUnloadedModuleList();
virtual MinidumpMiscInfo* GetMiscInfo();
virtual MinidumpBreakpadInfo* GetBreakpadInfo();
virtual MinidumpMemoryInfoList* GetMemoryInfoList();