diff options
author | Matt A. Tobin <email@mattatobin.com> | 2019-04-01 13:55:00 -0400 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2019-04-01 13:55:00 -0400 |
commit | ce3979c721ba378a448bfbe3671c99d993cbc801 (patch) | |
tree | e200d5225bcecef5f974b946a58277fddd24e89c /toolkit/crashreporter/google-breakpad/src/processor | |
parent | f6c16cff36048c583ca0e1d019b622336ca861a0 (diff) | |
parent | ff2f287f82630ab3887d7d5c1e64e5b888ea0beb (diff) | |
download | UXP-ce3979c721ba378a448bfbe3671c99d993cbc801.tar UXP-ce3979c721ba378a448bfbe3671c99d993cbc801.tar.gz UXP-ce3979c721ba378a448bfbe3671c99d993cbc801.tar.lz UXP-ce3979c721ba378a448bfbe3671c99d993cbc801.tar.xz UXP-ce3979c721ba378a448bfbe3671c99d993cbc801.zip |
Merge branch 'master' into Sync-weave
Diffstat (limited to 'toolkit/crashreporter/google-breakpad/src/processor')
137 files changed, 0 insertions, 47048 deletions
diff --git a/toolkit/crashreporter/google-breakpad/src/processor/address_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/address_map-inl.h deleted file mode 100644 index 251c44781..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/address_map-inl.h +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// address_map-inl.h: Address map implementation. -// -// See address_map.h for documentation. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_ADDRESS_MAP_INL_H__ -#define PROCESSOR_ADDRESS_MAP_INL_H__ - -#include "processor/address_map.h" - -#include <assert.h> - -#include "processor/logging.h" - -namespace google_breakpad { - -template<typename AddressType, typename EntryType> -bool AddressMap<AddressType, EntryType>::Store(const AddressType &address, - const EntryType &entry) { - // Ensure that the specified address doesn't conflict with something already - // in the map. - if (map_.find(address) != map_.end()) { - BPLOG(INFO) << "Store failed, address " << HexString(address) << - " is already present"; - return false; - } - - map_.insert(MapValue(address, entry)); - return true; -} - -template<typename AddressType, typename EntryType> -bool AddressMap<AddressType, EntryType>::Retrieve( - const AddressType &address, - EntryType *entry, AddressType *entry_address) const { - BPLOG_IF(ERROR, !entry) << "AddressMap::Retrieve requires |entry|"; - assert(entry); - - // upper_bound gives the first element whose key is greater than address, - // but we want the first element whose key is less than or equal to address. - // Decrement the iterator to get there, but not if the upper_bound already - // points to the beginning of the map - in that case, address is lower than - // the lowest stored key, so return false. - MapConstIterator iterator = map_.upper_bound(address); - if (iterator == map_.begin()) - return false; - --iterator; - - *entry = iterator->second; - if (entry_address) - *entry_address = iterator->first; - - return true; -} - -template<typename AddressType, typename EntryType> -void AddressMap<AddressType, EntryType>::Clear() { - map_.clear(); -} - -} // namespace google_breakpad - -#endif // PROCESSOR_ADDRESS_MAP_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/address_map.h b/toolkit/crashreporter/google-breakpad/src/processor/address_map.h deleted file mode 100644 index 2972cbb9f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/address_map.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// address_map.h: Address maps. -// -// An address map contains a set of objects keyed by address. Objects are -// retrieved from the map by returning the object with the highest key less -// than or equal to the lookup key. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_ADDRESS_MAP_H__ -#define PROCESSOR_ADDRESS_MAP_H__ - -#include <map> - -namespace google_breakpad { - -// Forward declarations (for later friend declarations). -template<class, class> class AddressMapSerializer; - -template<typename AddressType, typename EntryType> -class AddressMap { - public: - AddressMap() : map_() {} - - // Inserts an entry into the map. Returns false without storing the entry - // if an entry is already stored in the map at the same address as specified - // by the address argument. - bool Store(const AddressType &address, const EntryType &entry); - - // Locates the entry stored at the highest address less than or equal to - // the address argument. If there is no such range, returns false. The - // entry is returned in entry, which is a required argument. If - // entry_address is not NULL, it will be set to the address that the entry - // was stored at. - bool Retrieve(const AddressType &address, - EntryType *entry, AddressType *entry_address) const; - - // Empties the address map, restoring it to the same state as when it was - // initially created. - void Clear(); - - private: - friend class AddressMapSerializer<AddressType, EntryType>; - friend class ModuleComparer; - - // Convenience types. - typedef std::map<AddressType, EntryType> AddressToEntryMap; - typedef typename AddressToEntryMap::const_iterator MapConstIterator; - typedef typename AddressToEntryMap::value_type MapValue; - - // Maps the address of each entry to an EntryType. - AddressToEntryMap map_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_ADDRESS_MAP_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/address_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/address_map_unittest.cc deleted file mode 100644 index 9b4095b16..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/address_map_unittest.cc +++ /dev/null @@ -1,196 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// address_map_unittest.cc: Unit tests for AddressMap. -// -// Author: Mark Mentovai - -#include <limits.h> -#include <stdio.h> - -#include "processor/address_map-inl.h" -#include "processor/linked_ptr.h" -#include "processor/logging.h" - -#define ASSERT_TRUE(condition) \ - if (!(condition)) { \ - fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \ - return false; \ - } - -#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition)) - -#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) - -namespace { - -using google_breakpad::AddressMap; -using google_breakpad::linked_ptr; - -// A CountedObject holds an int. A global (not thread safe!) count of -// allocated CountedObjects is maintained to help test memory management. -class CountedObject { - public: - explicit CountedObject(int id) : id_(id) { ++count_; } - ~CountedObject() { --count_; } - - static int count() { return count_; } - int id() const { return id_; } - - private: - static int count_; - int id_; -}; - -int CountedObject::count_; - -typedef int AddressType; -typedef AddressMap< AddressType, linked_ptr<CountedObject> > TestMap; - -static bool DoAddressMapTest() { - ASSERT_EQ(CountedObject::count(), 0); - - TestMap test_map; - linked_ptr<CountedObject> entry; - AddressType address; - - // Check that a new map is truly empty. - ASSERT_FALSE(test_map.Retrieve(0, &entry, &address)); - ASSERT_FALSE(test_map.Retrieve(INT_MIN, &entry, &address)); - ASSERT_FALSE(test_map.Retrieve(INT_MAX, &entry, &address)); - - // Check that Clear clears the map without leaking. - ASSERT_EQ(CountedObject::count(), 0); - ASSERT_TRUE(test_map.Store(1, - linked_ptr<CountedObject>(new CountedObject(0)))); - ASSERT_TRUE(test_map.Retrieve(1, &entry, &address)); - ASSERT_EQ(CountedObject::count(), 1); - test_map.Clear(); - ASSERT_EQ(CountedObject::count(), 1); // still holding entry in this scope - - // Check that a cleared map is truly empty. - ASSERT_FALSE(test_map.Retrieve(0, &entry, &address)); - ASSERT_FALSE(test_map.Retrieve(INT_MIN, &entry, &address)); - ASSERT_FALSE(test_map.Retrieve(INT_MAX, &entry, &address)); - - // Check a single-element map. - ASSERT_TRUE(test_map.Store(10, - linked_ptr<CountedObject>(new CountedObject(1)))); - ASSERT_FALSE(test_map.Retrieve(9, &entry, &address)); - ASSERT_TRUE(test_map.Retrieve(10, &entry, &address)); - ASSERT_EQ(CountedObject::count(), 1); - ASSERT_EQ(entry->id(), 1); - ASSERT_EQ(address, 10); - ASSERT_TRUE(test_map.Retrieve(11, &entry, &address)); - ASSERT_TRUE(test_map.Retrieve(11, &entry, NULL)); // NULL ok here - - // Add some more elements. - ASSERT_TRUE(test_map.Store(5, - linked_ptr<CountedObject>(new CountedObject(2)))); - ASSERT_EQ(CountedObject::count(), 2); - ASSERT_TRUE(test_map.Store(20, - linked_ptr<CountedObject>(new CountedObject(3)))); - ASSERT_TRUE(test_map.Store(15, - linked_ptr<CountedObject>(new CountedObject(4)))); - ASSERT_FALSE(test_map.Store(10, - linked_ptr<CountedObject>(new CountedObject(5)))); // already in map - ASSERT_TRUE(test_map.Store(16, - linked_ptr<CountedObject>(new CountedObject(6)))); - ASSERT_TRUE(test_map.Store(14, - linked_ptr<CountedObject>(new CountedObject(7)))); - - // Nothing was stored with a key under 5. Don't use ASSERT inside loops - // because it won't show exactly which key/entry/address failed. - for (AddressType key = 0; key < 5; ++key) { - if (test_map.Retrieve(key, &entry, &address)) { - fprintf(stderr, - "FAIL: retrieve %d expected false observed true @ %s:%d\n", - key, __FILE__, __LINE__); - return false; - } - } - - // Check everything that was stored. - const int id_verify[] = { 0, 0, 0, 0, 0, // unused - 2, 2, 2, 2, 2, // 5 - 9 - 1, 1, 1, 1, 7, // 10 - 14 - 4, 6, 6, 6, 6, // 15 - 19 - 3, 3, 3, 3, 3, // 20 - 24 - 3, 3, 3, 3, 3 }; // 25 - 29 - const AddressType address_verify[] = { 0, 0, 0, 0, 0, // unused - 5, 5, 5, 5, 5, // 5 - 9 - 10, 10, 10, 10, 14, // 10 - 14 - 15, 16, 16, 16, 16, // 15 - 19 - 20, 20, 20, 20, 20, // 20 - 24 - 20, 20, 20, 20, 20 }; // 25 - 29 - - for (AddressType key = 5; key < 30; ++key) { - if (!test_map.Retrieve(key, &entry, &address)) { - fprintf(stderr, - "FAIL: retrieve %d expected true observed false @ %s:%d\n", - key, __FILE__, __LINE__); - return false; - } - if (entry->id() != id_verify[key]) { - fprintf(stderr, - "FAIL: retrieve %d expected entry %d observed %d @ %s:%d\n", - key, id_verify[key], entry->id(), __FILE__, __LINE__); - return false; - } - if (address != address_verify[key]) { - fprintf(stderr, - "FAIL: retrieve %d expected address %d observed %d @ %s:%d\n", - key, address_verify[key], address, __FILE__, __LINE__); - return false; - } - } - - // The stored objects should still be in the map. - ASSERT_EQ(CountedObject::count(), 6); - - return true; -} - -static bool RunTests() { - if (!DoAddressMapTest()) - return false; - - // Leak check. - ASSERT_EQ(CountedObject::count(), 0); - - return true; -} - -} // namespace - -int main(int argc, char **argv) { - BPLOG_INIT(&argc, &argv); - - return RunTests() ? 0 : 1; -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_code_module.h b/toolkit/crashreporter/google-breakpad/src/processor/basic_code_module.h deleted file mode 100644 index 0f7b3e431..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/basic_code_module.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// basic_code_module.h: Carries information about code modules that are loaded -// into a process. -// -// This is a basic concrete implementation of CodeModule. It cannot be -// instantiated directly, only based on other objects that implement -// the CodeModule interface. It exists to provide a CodeModule implementation -// a place to store information when the life of the original object (such as -// a MinidumpModule) cannot be guaranteed. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_BASIC_CODE_MODULE_H__ -#define PROCESSOR_BASIC_CODE_MODULE_H__ - -#include <string> - -#include "common/using_std_string.h" -#include "google_breakpad/processor/code_module.h" - -namespace google_breakpad { - -class BasicCodeModule : public CodeModule { - public: - // Creates a new BasicCodeModule given any existing CodeModule - // implementation. This is useful to make a copy of the data relevant to - // the CodeModule interface without requiring all of the resources that - // other CodeModule implementations may require. - explicit BasicCodeModule(const CodeModule *that) - : base_address_(that->base_address()), - size_(that->size()), - shrink_down_delta_(that->shrink_down_delta()), - code_file_(that->code_file()), - code_identifier_(that->code_identifier()), - debug_file_(that->debug_file()), - debug_identifier_(that->debug_identifier()), - version_(that->version()) {} - - BasicCodeModule(uint64_t base_address, uint64_t size, - const string &code_file, - const string &code_identifier, - const string &debug_file, - const string &debug_identifier, - const string &version) - : base_address_(base_address), - size_(size), - shrink_down_delta_(0), - code_file_(code_file), - code_identifier_(code_identifier), - debug_file_(debug_file), - debug_identifier_(debug_identifier), - version_(version) - {} - virtual ~BasicCodeModule() {} - - // See code_module.h for descriptions of these methods and the associated - // members. - virtual uint64_t base_address() const { return base_address_; } - 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_identifier() const { return code_identifier_; } - virtual string debug_file() const { return debug_file_; } - virtual string debug_identifier() const { return debug_identifier_; } - virtual string version() const { return version_; } - virtual CodeModule* Copy() const { return new BasicCodeModule(this); } - - private: - uint64_t base_address_; - uint64_t size_; - uint64_t shrink_down_delta_; - string code_file_; - string code_identifier_; - string debug_file_; - string debug_identifier_; - string version_; - - // Disallow copy constructor and assignment operator. - BasicCodeModule(const BasicCodeModule &that); - void operator=(const BasicCodeModule &that); -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_BASIC_CODE_MODULE_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.cc b/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.cc deleted file mode 100644 index 48d971677..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.cc +++ /dev/null @@ -1,155 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// basic_code_modules.cc: Contains all of the CodeModule objects that -// were loaded into a single process. -// -// See basic_code_modules.h for documentation. -// -// Author: Mark Mentovai - -#include "processor/basic_code_modules.h" - -#include <assert.h> - -#include <vector> - -#include "google_breakpad/processor/code_module.h" -#include "processor/linked_ptr.h" -#include "processor/logging.h" -#include "processor/range_map-inl.h" - -namespace google_breakpad { - -using std::vector; - -BasicCodeModules::BasicCodeModules(const CodeModules *that) - : main_address_(0), map_() { - BPLOG_IF(ERROR, !that) << "BasicCodeModules::BasicCodeModules requires " - "|that|"; - assert(that); - - map_.SetEnableShrinkDown(that->IsModuleShrinkEnabled()); - - const CodeModule *main_module = that->GetMainModule(); - if (main_module) - main_address_ = main_module->base_address(); - - unsigned int count = that->module_count(); - for (unsigned int i = 0; i < count; ++i) { - // Make a copy of the module and insert it into the map. Use - // GetModuleAtIndex because ordering is unimportant when slurping the - // entire list, and GetModuleAtIndex may be faster than - // GetModuleAtSequence. - linked_ptr<const CodeModule> module(that->GetModuleAtIndex(i)->Copy()); - if (!map_.StoreRange(module->base_address(), module->size(), module)) { - BPLOG(ERROR) << "Module " << module->code_file() - << " 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() { -} - -unsigned int BasicCodeModules::module_count() const { - return map_.GetCount(); -} - -const CodeModule* BasicCodeModules::GetModuleForAddress( - uint64_t address) const { - linked_ptr<const CodeModule> module; - if (!map_.RetrieveRange(address, &module, NULL /* base */, NULL /* delta */, - NULL /* size */)) { - BPLOG(INFO) << "No module at " << HexString(address); - return NULL; - } - - return module.get(); -} - -const CodeModule* BasicCodeModules::GetMainModule() const { - return GetModuleForAddress(main_address_); -} - -const CodeModule* BasicCodeModules::GetModuleAtSequence( - unsigned int sequence) const { - linked_ptr<const CodeModule> module; - if (!map_.RetrieveRangeAtIndex(sequence, &module, NULL /* base */, - NULL /* delta */, NULL /* size */)) { - BPLOG(ERROR) << "RetrieveRangeAtIndex failed for sequence " << sequence; - return NULL; - } - - return module.get(); -} - -const CodeModule* BasicCodeModules::GetModuleAtIndex( - unsigned int index) const { - // This class stores everything in a RangeMap, without any more-efficient - // way to walk the list of CodeModule objects. Implement GetModuleAtIndex - // using GetModuleAtSequence, which meets all of the requirements, and - // in addition, guarantees ordering. - return GetModuleAtSequence(index); -} - -const CodeModules* BasicCodeModules::Copy() const { - 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 diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.h b/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.h deleted file mode 100644 index 50f8a03d8..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/basic_code_modules.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// basic_code_modules.h: Contains all of the CodeModule objects that -// were loaded into a single process. -// -// This is a basic concrete implementation of CodeModules. It cannot be -// instantiated directly, only based on other objects that implement -// the CodeModules interface. It exists to provide a CodeModules -// implementation a place to store information when the life of the original -// object (such as a MinidumpModuleList) cannot be guaranteed. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_BASIC_CODE_MODULES_H__ -#define PROCESSOR_BASIC_CODE_MODULES_H__ - -#include <stddef.h> - -#include <vector> - -#include "google_breakpad/processor/code_modules.h" -#include "processor/linked_ptr.h" -#include "processor/range_map.h" - -namespace google_breakpad { - -class BasicCodeModules : public CodeModules { - public: - // Creates a new BasicCodeModules object given any existing CodeModules - // implementation. This is useful to make a copy of the data relevant to - // the CodeModules and CodeModule interfaces without requiring all of the - // resources that other implementations may require. A copy will be - // made of each contained CodeModule using CodeModule::Copy. - explicit BasicCodeModules(const CodeModules *that); - - virtual ~BasicCodeModules(); - - // See code_modules.h for descriptions of these methods. - virtual unsigned int module_count() const; - virtual const CodeModule* GetModuleForAddress(uint64_t address) const; - virtual const CodeModule* GetMainModule() const; - virtual const CodeModule* GetModuleAtSequence(unsigned int sequence) const; - virtual const CodeModule* GetModuleAtIndex(unsigned int index) const; - virtual const CodeModules* Copy() const; - virtual std::vector<linked_ptr<const CodeModule> > - GetShrunkRangeModules() const; - virtual bool IsModuleShrinkEnabled() const; - - protected: - BasicCodeModules(); - - // The base address of the main module. - uint64_t main_address_; - - // The map used to contain each CodeModule, keyed by each CodeModule's - // address range. - 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: - // Disallow copy constructor and assignment operator. - BasicCodeModules(const BasicCodeModules &that); - void operator=(const BasicCodeModules &that); -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_BASIC_CODE_MODULES_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc deleted file mode 100644 index aa66e1599..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver.cc +++ /dev/null @@ -1,612 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// basic_source_line_resolver.cc: BasicSourceLineResolver implementation. -// -// See basic_source_line_resolver.h and basic_source_line_resolver_types.h -// for documentation. - -#include <assert.h> -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <limits> -#include <map> -#include <utility> -#include <vector> - -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "processor/basic_source_line_resolver_types.h" -#include "processor/module_factory.h" - -#include "processor/tokenize.h" - -using std::map; -using std::vector; -using std::make_pair; - -namespace google_breakpad { - -#ifdef _WIN32 -#ifdef _MSC_VER -#define strtok_r strtok_s -#endif -#define strtoull _strtoui64 -#endif - -static const char *kWhitespace = " \r\n"; -static const int kMaxErrorsPrinted = 5; -static const int kMaxErrorsBeforeBailing = 100; - -BasicSourceLineResolver::BasicSourceLineResolver() : - SourceLineResolverBase(new BasicModuleFactory) { } - -// static -void BasicSourceLineResolver::Module::LogParseError( - const string &message, - int line_number, - int *num_errors) { - if (++(*num_errors) <= kMaxErrorsPrinted) { - if (line_number > 0) { - BPLOG(ERROR) << "Line " << line_number << ": " << message; - } else { - BPLOG(ERROR) << message; - } - } -} - -bool BasicSourceLineResolver::Module::LoadMapFromMemory( - char *memory_buffer, - size_t memory_buffer_size) { - linked_ptr<Function> cur_func; - int line_number = 0; - int num_errors = 0; - char *save_ptr; - - // If the length is 0, we can still pretend we have a symbol file. This is - // for scenarios that want to test symbol lookup, but don't necessarily care - // if certain modules do not have any information, like system libraries. - if (memory_buffer_size == 0) { - return true; - } - - // Make sure the last character is null terminator. - size_t last_null_terminator = memory_buffer_size - 1; - if (memory_buffer[last_null_terminator] != '\0') { - memory_buffer[last_null_terminator] = '\0'; - } - - // Skip any null terminators at the end of the memory buffer, and make sure - // there are no other null terminators in the middle of the memory buffer. - bool has_null_terminator_in_the_middle = false; - while (last_null_terminator > 0 && - memory_buffer[last_null_terminator - 1] == '\0') { - last_null_terminator--; - } - for (size_t i = 0; i < last_null_terminator; i++) { - if (memory_buffer[i] == '\0') { - memory_buffer[i] = '_'; - has_null_terminator_in_the_middle = true; - } - } - if (has_null_terminator_in_the_middle) { - LogParseError( - "Null terminator is not expected in the middle of the symbol data", - line_number, - &num_errors); - } - - char *buffer; - buffer = strtok_r(memory_buffer, "\r\n", &save_ptr); - - while (buffer != NULL) { - ++line_number; - - if (strncmp(buffer, "FILE ", 5) == 0) { - if (!ParseFile(buffer)) { - LogParseError("ParseFile on buffer failed", line_number, &num_errors); - } - } else if (strncmp(buffer, "STACK ", 6) == 0) { - if (!ParseStackInfo(buffer)) { - LogParseError("ParseStackInfo failed", line_number, &num_errors); - } - } else if (strncmp(buffer, "FUNC ", 5) == 0) { - cur_func.reset(ParseFunction(buffer)); - if (!cur_func.get()) { - LogParseError("ParseFunction failed", line_number, &num_errors); - } else { - // StoreRange will fail if the function has an invalid address or size. - // We'll silently ignore this, the function and any corresponding lines - // will be destroyed when cur_func is released. - functions_.StoreRange(cur_func->address, cur_func->size, cur_func); - } - } else if (strncmp(buffer, "PUBLIC ", 7) == 0) { - // Clear cur_func: public symbols don't contain line number information. - cur_func.reset(); - - if (!ParsePublicSymbol(buffer)) { - LogParseError("ParsePublicSymbol failed", line_number, &num_errors); - } - } else if (strncmp(buffer, "MODULE ", 7) == 0) { - // Ignore these. They're not of any use to BasicSourceLineResolver, - // which is fed modules by a SymbolSupplier. These lines are present to - // aid other tools in properly placing symbol files so that they can - // be accessed by a SymbolSupplier. - // - // MODULE <guid> <age> <filename> - } else if (strncmp(buffer, "INFO ", 5) == 0) { - // Ignore these as well, they're similarly just for housekeeping. - // - // INFO CODE_ID <code id> <filename> - } else { - if (!cur_func.get()) { - LogParseError("Found source line data without a function", - line_number, &num_errors); - } else { - Line *line = ParseLine(buffer); - if (!line) { - LogParseError("ParseLine failed", line_number, &num_errors); - } else { - cur_func->lines.StoreRange(line->address, line->size, - linked_ptr<Line>(line)); - } - } - } - if (num_errors > kMaxErrorsBeforeBailing) { - break; - } - buffer = strtok_r(NULL, "\r\n", &save_ptr); - } - is_corrupt_ = num_errors > 0; - return true; -} - -void BasicSourceLineResolver::Module::LookupAddress(StackFrame *frame) const { - MemAddr address = frame->instruction - frame->module->base_address(); - - // First, look for a FUNC record that covers address. Use - // RetrieveNearestRange instead of RetrieveRange so that, if there - // is no such function, we can use the next function to bound the - // extent of the PUBLIC symbol we find, below. This does mean we - // need to check that address indeed falls within the function we - // find; do the range comparison in an overflow-friendly way. - linked_ptr<Function> func; - linked_ptr<PublicSymbol> public_symbol; - MemAddr function_base; - MemAddr function_size; - MemAddr public_address; - if (functions_.RetrieveNearestRange(address, &func, &function_base, - NULL /* delta */, &function_size) && - address >= function_base && address - function_base < function_size) { - frame->function_name = func->name; - frame->function_base = frame->module->base_address() + function_base; - - linked_ptr<Line> line; - MemAddr line_base; - if (func->lines.RetrieveRange(address, &line, &line_base, NULL /* delta */, - NULL /* size */)) { - FileMap::const_iterator it = files_.find(line->source_file_id); - if (it != files_.end()) { - frame->source_file_name = files_.find(line->source_file_id)->second; - } - frame->source_line = line->line; - frame->source_line_base = frame->module->base_address() + line_base; - } - } else if (public_symbols_.Retrieve(address, - &public_symbol, &public_address) && - (!func.get() || public_address > function_base)) { - frame->function_name = public_symbol->name; - frame->function_base = frame->module->base_address() + public_address; - } -} - -WindowsFrameInfo *BasicSourceLineResolver::Module::FindWindowsFrameInfo( - const StackFrame *frame) const { - MemAddr address = frame->instruction - frame->module->base_address(); - scoped_ptr<WindowsFrameInfo> result(new WindowsFrameInfo()); - - // We only know about WindowsFrameInfo::STACK_INFO_FRAME_DATA and - // WindowsFrameInfo::STACK_INFO_FPO. Prefer them in this order. - // WindowsFrameInfo::STACK_INFO_FRAME_DATA is the newer type that - // includes its own program string. - // WindowsFrameInfo::STACK_INFO_FPO is the older type - // corresponding to the FPO_DATA struct. See stackwalker_x86.cc. - linked_ptr<WindowsFrameInfo> frame_info; - if ((windows_frame_info_[WindowsFrameInfo::STACK_INFO_FRAME_DATA] - .RetrieveRange(address, &frame_info)) - || (windows_frame_info_[WindowsFrameInfo::STACK_INFO_FPO] - .RetrieveRange(address, &frame_info))) { - result->CopyFrom(*frame_info.get()); - return result.release(); - } - - // Even without a relevant STACK line, many functions contain - // information about how much space their parameters consume on the - // stack. Use RetrieveNearestRange instead of RetrieveRange, so that - // we can use the function to bound the extent of the PUBLIC symbol, - // below. However, this does mean we need to check that ADDRESS - // falls within the retrieved function's range; do the range - // comparison in an overflow-friendly way. - linked_ptr<Function> function; - MemAddr function_base, function_size; - if (functions_.RetrieveNearestRange(address, &function, &function_base, - NULL /* delta */, &function_size) && - address >= function_base && address - function_base < function_size) { - result->parameter_size = function->parameter_size; - result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE; - return result.release(); - } - - // PUBLIC symbols might have a parameter size. Use the function we - // found above to limit the range the public symbol covers. - linked_ptr<PublicSymbol> public_symbol; - MemAddr public_address; - if (public_symbols_.Retrieve(address, &public_symbol, &public_address) && - (!function.get() || public_address > function_base)) { - result->parameter_size = public_symbol->parameter_size; - } - - return NULL; -} - -CFIFrameInfo *BasicSourceLineResolver::Module::FindCFIFrameInfo( - const StackFrame *frame) const { - MemAddr address = frame->instruction - frame->module->base_address(); - MemAddr initial_base, initial_size; - string initial_rules; - - // Find the initial rule whose range covers this address. That - // provides an initial set of register recovery rules. Then, walk - // forward from the initial rule's starting address to frame's - // instruction address, applying delta rules. - if (!cfi_initial_rules_.RetrieveRange(address, &initial_rules, &initial_base, - NULL /* delta */, &initial_size)) { - return NULL; - } - - // Create a frame info structure, and populate it with the rules from - // the STACK CFI INIT record. - scoped_ptr<CFIFrameInfo> rules(new CFIFrameInfo()); - if (!ParseCFIRuleSet(initial_rules, rules.get())) - return NULL; - - // Find the first delta rule that falls within the initial rule's range. - map<MemAddr, string>::const_iterator delta = - cfi_delta_rules_.lower_bound(initial_base); - - // Apply delta rules up to and including the frame's address. - while (delta != cfi_delta_rules_.end() && delta->first <= address) { - ParseCFIRuleSet(delta->second, rules.get()); - delta++; - } - - return rules.release(); -} - -bool BasicSourceLineResolver::Module::ParseFile(char *file_line) { - long index; - char *filename; - if (SymbolParseHelper::ParseFile(file_line, &index, &filename)) { - files_.insert(make_pair(index, string(filename))); - return true; - } - return false; -} - -BasicSourceLineResolver::Function* -BasicSourceLineResolver::Module::ParseFunction(char *function_line) { - uint64_t address; - uint64_t size; - long stack_param_size; - char *name; - if (SymbolParseHelper::ParseFunction(function_line, &address, &size, - &stack_param_size, &name)) { - return new Function(name, address, size, stack_param_size); - } - return NULL; -} - -BasicSourceLineResolver::Line* BasicSourceLineResolver::Module::ParseLine( - char *line_line) { - uint64_t address; - uint64_t size; - long line_number; - long source_file; - - if (SymbolParseHelper::ParseLine(line_line, &address, &size, &line_number, - &source_file)) { - return new Line(address, size, source_file, line_number); - } - return NULL; -} - -bool BasicSourceLineResolver::Module::ParsePublicSymbol(char *public_line) { - uint64_t address; - long stack_param_size; - char *name; - - if (SymbolParseHelper::ParsePublicSymbol(public_line, &address, - &stack_param_size, &name)) { - // A few public symbols show up with an address of 0. This has been seen - // in the dumped output of ntdll.pdb for symbols such as _CIlog, _CIpow, - // RtlDescribeChunkLZNT1, and RtlReserveChunkLZNT1. They would conflict - // with one another if they were allowed into the public_symbols_ map, - // but since the address is obviously invalid, gracefully accept them - // as input without putting them into the map. - if (address == 0) { - return true; - } - - linked_ptr<PublicSymbol> symbol(new PublicSymbol(name, address, - stack_param_size)); - return public_symbols_.Store(address, symbol); - } - return false; -} - -bool BasicSourceLineResolver::Module::ParseStackInfo(char *stack_info_line) { - // Skip "STACK " prefix. - stack_info_line += 6; - - // Find the token indicating what sort of stack frame walking - // information this is. - while (*stack_info_line == ' ') - stack_info_line++; - const char *platform = stack_info_line; - while (!strchr(kWhitespace, *stack_info_line)) - stack_info_line++; - *stack_info_line++ = '\0'; - - // MSVC stack frame info. - if (strcmp(platform, "WIN") == 0) { - int type = 0; - uint64_t rva, code_size; - linked_ptr<WindowsFrameInfo> - stack_frame_info(WindowsFrameInfo::ParseFromString(stack_info_line, - type, - rva, - code_size)); - if (stack_frame_info == NULL) - return false; - - // TODO(mmentovai): I wanted to use StoreRange's return value as this - // method's return value, but MSVC infrequently outputs stack info that - // violates the containment rules. This happens with a section of code - // in strncpy_s in test_app.cc (testdata/minidump2). There, problem looks - // like this: - // STACK WIN 4 4242 1a a 0 ... (STACK WIN 4 base size prolog 0 ...) - // STACK WIN 4 4243 2e 9 0 ... - // ContainedRangeMap treats these two blocks as conflicting. In reality, - // when the prolog lengths are taken into account, the actual code of - // these blocks doesn't conflict. However, we can't take the prolog lengths - // into account directly here because we'd wind up with a different set - // of range conflicts when MSVC outputs stack info like this: - // STACK WIN 4 1040 73 33 0 ... - // STACK WIN 4 105a 59 19 0 ... - // because in both of these entries, the beginning of the code after the - // prolog is at 0x1073, and the last byte of contained code is at 0x10b2. - // Perhaps we could get away with storing ranges by rva + prolog_size - // if ContainedRangeMap were modified to allow replacement of - // already-stored values. - - windows_frame_info_[type].StoreRange(rva, code_size, stack_frame_info); - return true; - } else if (strcmp(platform, "CFI") == 0) { - // DWARF CFI stack frame info - return ParseCFIFrameInfo(stack_info_line); - } else { - // Something unrecognized. - return false; - } -} - -bool BasicSourceLineResolver::Module::ParseCFIFrameInfo( - char *stack_info_line) { - char *cursor; - - // Is this an INIT record or a delta record? - char *init_or_address = strtok_r(stack_info_line, " \r\n", &cursor); - if (!init_or_address) - return false; - - if (strcmp(init_or_address, "INIT") == 0) { - // This record has the form "STACK INIT <address> <size> <rules...>". - char *address_field = strtok_r(NULL, " \r\n", &cursor); - if (!address_field) return false; - - char *size_field = strtok_r(NULL, " \r\n", &cursor); - if (!size_field) return false; - - char *initial_rules = strtok_r(NULL, "\r\n", &cursor); - if (!initial_rules) return false; - - MemAddr address = strtoul(address_field, NULL, 16); - MemAddr size = strtoul(size_field, NULL, 16); - cfi_initial_rules_.StoreRange(address, size, initial_rules); - return true; - } - - // This record has the form "STACK <address> <rules...>". - char *address_field = init_or_address; - char *delta_rules = strtok_r(NULL, "\r\n", &cursor); - if (!delta_rules) return false; - MemAddr address = strtoul(address_field, NULL, 16); - cfi_delta_rules_[address] = delta_rules; - return true; -} - -// static -bool SymbolParseHelper::ParseFile(char *file_line, long *index, - char **filename) { - // FILE <id> <filename> - assert(strncmp(file_line, "FILE ", 5) == 0); - file_line += 5; // skip prefix - - vector<char*> tokens; - if (!Tokenize(file_line, kWhitespace, 2, &tokens)) { - return false; - } - - char *after_number; - *index = strtol(tokens[0], &after_number, 10); - if (!IsValidAfterNumber(after_number) || *index < 0 || - *index == std::numeric_limits<long>::max()) { - return false; - } - - *filename = tokens[1]; - if (!*filename) { - return false; - } - - return true; -} - -// static -bool SymbolParseHelper::ParseFunction(char *function_line, uint64_t *address, - uint64_t *size, long *stack_param_size, - char **name) { - // FUNC <address> <size> <stack_param_size> <name> - assert(strncmp(function_line, "FUNC ", 5) == 0); - function_line += 5; // skip prefix - - vector<char*> tokens; - if (!Tokenize(function_line, kWhitespace, 4, &tokens)) { - return false; - } - - char *after_number; - *address = strtoull(tokens[0], &after_number, 16); - if (!IsValidAfterNumber(after_number) || - *address == std::numeric_limits<unsigned long long>::max()) { - return false; - } - *size = strtoull(tokens[1], &after_number, 16); - if (!IsValidAfterNumber(after_number) || - *size == std::numeric_limits<unsigned long long>::max()) { - return false; - } - *stack_param_size = strtol(tokens[2], &after_number, 16); - if (!IsValidAfterNumber(after_number) || - *stack_param_size == std::numeric_limits<long>::max() || - *stack_param_size < 0) { - return false; - } - *name = tokens[3]; - - return true; -} - -// static -bool SymbolParseHelper::ParseLine(char *line_line, uint64_t *address, - uint64_t *size, long *line_number, - long *source_file) { - // <address> <size> <line number> <source file id> - vector<char*> tokens; - if (!Tokenize(line_line, kWhitespace, 4, &tokens)) { - return false; - } - - char *after_number; - *address = strtoull(tokens[0], &after_number, 16); - if (!IsValidAfterNumber(after_number) || - *address == std::numeric_limits<unsigned long long>::max()) { - return false; - } - *size = strtoull(tokens[1], &after_number, 16); - if (!IsValidAfterNumber(after_number) || - *size == std::numeric_limits<unsigned long long>::max()) { - return false; - } - *line_number = strtol(tokens[2], &after_number, 10); - if (!IsValidAfterNumber(after_number) || - *line_number == std::numeric_limits<long>::max()) { - return false; - } - *source_file = strtol(tokens[3], &after_number, 10); - if (!IsValidAfterNumber(after_number) || *source_file < 0 || - *source_file == std::numeric_limits<long>::max()) { - return false; - } - - // Valid line numbers normally start from 1, however there are functions that - // are associated with a source file but not associated with any line number - // (block helper function) and for such functions the symbol file contains 0 - // for the line numbers. Hence, 0 should be treated as a valid line number. - // For more information on block helper functions, please, take a look at: - // http://clang.llvm.org/docs/Block-ABI-Apple.html - if (*line_number < 0) { - return false; - } - - return true; -} - -// static -bool SymbolParseHelper::ParsePublicSymbol(char *public_line, - uint64_t *address, - long *stack_param_size, - char **name) { - // PUBLIC <address> <stack_param_size> <name> - assert(strncmp(public_line, "PUBLIC ", 7) == 0); - public_line += 7; // skip prefix - - vector<char*> tokens; - if (!Tokenize(public_line, kWhitespace, 3, &tokens)) { - return false; - } - - char *after_number; - *address = strtoull(tokens[0], &after_number, 16); - if (!IsValidAfterNumber(after_number) || - *address == std::numeric_limits<unsigned long long>::max()) { - return false; - } - *stack_param_size = strtol(tokens[1], &after_number, 16); - if (!IsValidAfterNumber(after_number) || - *stack_param_size == std::numeric_limits<long>::max() || - *stack_param_size < 0) { - return false; - } - *name = tokens[2]; - - return true; -} - -// static -bool SymbolParseHelper::IsValidAfterNumber(char *after_number) { - if (after_number != NULL && strchr(kWhitespace, *after_number) != NULL) { - return true; - } - return false; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_types.h b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_types.h deleted file mode 100644 index a022bc0db..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_types.h +++ /dev/null @@ -1,177 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// basic_source_line_types.h: definition of nested classes/structs in -// BasicSourceLineResolver. It moves the definitions out of -// basic_source_line_resolver.cc, so that other classes could have access -// to these private nested types without including basic_source_line_resolver.cc -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__ -#define PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__ - -#include <map> -#include <string> - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "processor/source_line_resolver_base_types.h" - -#include "processor/address_map-inl.h" -#include "processor/range_map-inl.h" -#include "processor/contained_range_map-inl.h" - -#include "processor/linked_ptr.h" -#include "google_breakpad/processor/stack_frame.h" -#include "processor/cfi_frame_info.h" -#include "processor/windows_frame_info.h" - -namespace google_breakpad { - -struct -BasicSourceLineResolver::Function : public SourceLineResolverBase::Function { - Function(const string &function_name, - MemAddr function_address, - MemAddr code_size, - int set_parameter_size) : Base(function_name, - function_address, - code_size, - set_parameter_size), - lines() { } - RangeMap< MemAddr, linked_ptr<Line> > lines; - private: - typedef SourceLineResolverBase::Function Base; -}; - - -class BasicSourceLineResolver::Module : public SourceLineResolverBase::Module { - public: - explicit Module(const string &name) : name_(name), is_corrupt_(false) { } - virtual ~Module() { } - - // Loads a map from the given buffer in char* type. - // Does NOT have ownership of memory_buffer. - // The passed in |memory buffer| is of size |memory_buffer_size|. If it is - // not null terminated, LoadMapFromMemory() will null terminate it by - // modifying the passed in buffer. - virtual bool LoadMapFromMemory(char *memory_buffer, - size_t memory_buffer_size); - - // Tells whether the loaded symbol data is corrupt. Return value is - // undefined, if the symbol data hasn't been loaded yet. - virtual bool IsCorrupt() const { return is_corrupt_; } - - // Looks up the given relative address, and fills the StackFrame struct - // with the result. - virtual void LookupAddress(StackFrame *frame) const; - - // If Windows stack walking information is available covering ADDRESS, - // return a WindowsFrameInfo structure describing it. If the information - // is not available, returns NULL. A NULL return value does not indicate - // an error. The caller takes ownership of any returned WindowsFrameInfo - // object. - virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) const; - - // If CFI stack walking information is available covering ADDRESS, - // return a CFIFrameInfo structure describing it. If the information - // is not available, return NULL. The caller takes ownership of any - // returned CFIFrameInfo object. - virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const; - - private: - // Friend declarations. - friend class BasicSourceLineResolver; - friend class ModuleComparer; - friend class ModuleSerializer; - - typedef std::map<int, string> FileMap; - - // Logs parse errors. |*num_errors| is increased every time LogParseError is - // called. - static void LogParseError( - const string &message, - int line_number, - int *num_errors); - - // Parses a file declaration - bool ParseFile(char *file_line); - - // Parses a function declaration, returning a new Function object. - Function* ParseFunction(char *function_line); - - // Parses a line declaration, returning a new Line object. - Line* ParseLine(char *line_line); - - // Parses a PUBLIC symbol declaration, storing it in public_symbols_. - // Returns false if an error occurs. - bool ParsePublicSymbol(char *public_line); - - // Parses a STACK WIN or STACK CFI frame info declaration, storing - // it in the appropriate table. - bool ParseStackInfo(char *stack_info_line); - - // Parses a STACK CFI record, storing it in cfi_frame_info_. - bool ParseCFIFrameInfo(char *stack_info_line); - - string name_; - FileMap files_; - RangeMap< MemAddr, linked_ptr<Function> > functions_; - AddressMap< MemAddr, linked_ptr<PublicSymbol> > public_symbols_; - bool is_corrupt_; - - // Each element in the array is a ContainedRangeMap for a type - // listed in WindowsFrameInfoTypes. These are split by type because - // there may be overlaps between maps of different types, but some - // information is only available as certain types. - ContainedRangeMap< MemAddr, linked_ptr<WindowsFrameInfo> > - windows_frame_info_[WindowsFrameInfo::STACK_INFO_LAST]; - - // DWARF CFI stack walking data. The Module stores the initial rule sets - // and rule deltas as strings, just as they appear in the symbol file: - // although the file may contain hundreds of thousands of STACK CFI - // records, walking a stack will only ever use a few of them, so it's - // best to delay parsing a record until it's actually needed. - - // STACK CFI INIT records: for each range, an initial set of register - // recovery rules. The RangeMap's itself gives the starting and ending - // addresses. - RangeMap<MemAddr, string> cfi_initial_rules_; - - // STACK CFI records: at a given address, the changes to the register - // recovery rules that take effect at that address. The map key is the - // starting address; the ending address is the key of the next entry in - // this map, or the end of the range as given by the cfi_initial_rules_ - // entry (which FindCFIFrameInfo looks up first). - std::map<MemAddr, string> cfi_delta_rules_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_BASIC_SOURCE_LINE_RESOLVER_TYPES_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc deleted file mode 100644 index a75044c74..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/basic_source_line_resolver_unittest.cc +++ /dev/null @@ -1,682 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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 <assert.h> -#include <stdio.h> - -#include <string> - -#include "breakpad_googletest_includes.h" -#include "common/scoped_ptr.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/stack_frame.h" -#include "google_breakpad/processor/memory_region.h" -#include "processor/linked_ptr.h" -#include "processor/logging.h" -#include "processor/windows_frame_info.h" -#include "processor/cfi_frame_info.h" - -namespace { - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::CFIFrameInfo; -using google_breakpad::CodeModule; -using google_breakpad::MemoryRegion; -using google_breakpad::StackFrame; -using google_breakpad::WindowsFrameInfo; -using google_breakpad::linked_ptr; -using google_breakpad::scoped_ptr; -using google_breakpad::SymbolParseHelper; - -class TestCodeModule : public CodeModule { - public: - TestCodeModule(string code_file) : code_file_(code_file) {} - virtual ~TestCodeModule() {} - - virtual uint64_t base_address() const { return 0; } - virtual uint64_t size() const { return 0xb000; } - virtual string code_file() const { return code_file_; } - virtual string code_identifier() const { return ""; } - virtual string debug_file() const { return ""; } - virtual string debug_identifier() const { return ""; } - virtual string version() const { return ""; } - virtual CodeModule* Copy() const { - return new TestCodeModule(code_file_); - } - virtual uint64_t shrink_down_delta() const { return 0; } - virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {} - - private: - string code_file_; -}; - -// A mock memory region object, for use by the STACK CFI tests. -class MockMemoryRegion: public MemoryRegion { - uint64_t GetBase() const { return 0x10000; } - uint32_t GetSize() const { return 0x01000; } - bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const { - *value = address & 0xff; - return true; - } - bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const { - *value = address & 0xffff; - return true; - } - bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const { - switch (address) { - case 0x10008: *value = 0x98ecadc3; break; // saved %ebx - case 0x1000c: *value = 0x878f7524; break; // saved %esi - case 0x10010: *value = 0x6312f9a5; break; // saved %edi - case 0x10014: *value = 0x10038; break; // caller's %ebp - case 0x10018: *value = 0xf6438648; break; // return address - default: *value = 0xdeadbeef; break; // junk - } - return true; - } - bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const { - *value = address; - return true; - } - void Print() const { - assert(false); - } -}; - -// Verify that, for every association in ACTUAL, EXPECTED has the same -// association. (That is, ACTUAL's associations should be a subset of -// EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and -// ".cfa". -static bool VerifyRegisters( - const char *file, int line, - const CFIFrameInfo::RegisterValueMap<uint32_t> &expected, - const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) { - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a; - a = actual.find(".cfa"); - if (a == actual.end()) - return false; - a = actual.find(".ra"); - if (a == actual.end()) - return false; - for (a = actual.begin(); a != actual.end(); a++) { - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e = - expected.find(a->first); - if (e == expected.end()) { - fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n", - file, line, a->first.c_str(), a->second); - return false; - } - if (e->second != a->second) { - fprintf(stderr, - "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n", - file, line, a->first.c_str(), a->second, e->second); - return false; - } - // Don't complain if this doesn't recover all registers. Although - // the DWARF spec says that unmentioned registers are undefined, - // GCC uses omission to mean that they are unchanged. - } - return true; -} - - -static bool VerifyEmpty(const StackFrame &frame) { - if (frame.function_name.empty() && - frame.source_file_name.empty() && - frame.source_line == 0) - return true; - return false; -} - -static void ClearSourceLineInfo(StackFrame *frame) { - frame->function_name.clear(); - frame->module = NULL; - frame->source_file_name.clear(); - frame->source_line = 0; -} - -class TestBasicSourceLineResolver : public ::testing::Test { -public: - void SetUp() { - testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") + - "/src/processor/testdata"; - } - - BasicSourceLineResolver resolver; - string testdata_dir; -}; - -TEST_F(TestBasicSourceLineResolver, TestLoadAndResolve) -{ - TestCodeModule module1("module1"); - ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out")); - ASSERT_TRUE(resolver.HasModule(&module1)); - TestCodeModule module2("module2"); - ASSERT_TRUE(resolver.LoadModule(&module2, testdata_dir + "/module2.out")); - ASSERT_TRUE(resolver.HasModule(&module2)); - - - StackFrame frame; - scoped_ptr<WindowsFrameInfo> windows_frame_info; - scoped_ptr<CFIFrameInfo> cfi_frame_info; - frame.instruction = 0x1000; - frame.module = NULL; - resolver.FillSourceLineInfo(&frame); - ASSERT_FALSE(frame.module); - ASSERT_TRUE(frame.function_name.empty()); - ASSERT_EQ(frame.function_base, 0U); - ASSERT_TRUE(frame.source_file_name.empty()); - ASSERT_EQ(frame.source_line, 0); - ASSERT_EQ(frame.source_line_base, 0U); - - frame.module = &module1; - resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Function1_1"); - ASSERT_TRUE(frame.module); - ASSERT_EQ(frame.module->code_file(), "module1"); - ASSERT_EQ(frame.function_base, 0x1000U); - ASSERT_EQ(frame.source_file_name, "file1_1.cc"); - ASSERT_EQ(frame.source_line, 44); - ASSERT_EQ(frame.source_line_base, 0x1000U); - windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); - ASSERT_TRUE(windows_frame_info.get()); - ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); - ASSERT_FALSE(windows_frame_info->allocates_base_pointer); - ASSERT_EQ(windows_frame_info->program_string, - "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ ="); - - ClearSourceLineInfo(&frame); - frame.instruction = 0x800; - frame.module = &module1; - resolver.FillSourceLineInfo(&frame); - ASSERT_TRUE(VerifyEmpty(frame)); - windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); - ASSERT_FALSE(windows_frame_info.get()); - - frame.instruction = 0x1280; - resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Function1_3"); - ASSERT_TRUE(frame.source_file_name.empty()); - ASSERT_EQ(frame.source_line, 0); - windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); - ASSERT_TRUE(windows_frame_info.get()); - ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN); - ASSERT_FALSE(windows_frame_info->allocates_base_pointer); - ASSERT_TRUE(windows_frame_info->program_string.empty()); - - frame.instruction = 0x1380; - resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Function1_4"); - ASSERT_TRUE(frame.source_file_name.empty()); - ASSERT_EQ(frame.source_line, 0); - windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); - ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); - ASSERT_TRUE(windows_frame_info.get()); - ASSERT_FALSE(windows_frame_info->allocates_base_pointer); - ASSERT_FALSE(windows_frame_info->program_string.empty()); - - frame.instruction = 0x2000; - windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); - ASSERT_FALSE(windows_frame_info.get()); - - // module1 has STACK CFI records covering 3d40..3def; - // module2 has STACK CFI records covering 3df0..3e9f; - // check that FindCFIFrameInfo doesn't claim to find any outside those ranges. - frame.instruction = 0x3d3f; - frame.module = &module1; - cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); - ASSERT_FALSE(cfi_frame_info.get()); - - frame.instruction = 0x3e9f; - frame.module = &module1; - cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); - ASSERT_FALSE(cfi_frame_info.get()); - - CFIFrameInfo::RegisterValueMap<uint32_t> current_registers; - CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; - CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers; - MockMemoryRegion memory; - - // Regardless of which instruction evaluation takes place at, it - // should produce the same values for the caller's registers. - expected_caller_registers[".cfa"] = 0x1001c; - expected_caller_registers[".ra"] = 0xf6438648; - expected_caller_registers["$ebp"] = 0x10038; - expected_caller_registers["$ebx"] = 0x98ecadc3; - expected_caller_registers["$esi"] = 0x878f7524; - expected_caller_registers["$edi"] = 0x6312f9a5; - - frame.instruction = 0x3d40; - frame.module = &module1; - current_registers.clear(); - current_registers["$esp"] = 0x10018; - current_registers["$ebp"] = 0x10038; - current_registers["$ebx"] = 0x98ecadc3; - current_registers["$esi"] = 0x878f7524; - current_registers["$edi"] = 0x6312f9a5; - cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers)); - - frame.instruction = 0x3d41; - current_registers["$esp"] = 0x10014; - cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers)); - - frame.instruction = 0x3d43; - current_registers["$ebp"] = 0x10014; - cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers); - - frame.instruction = 0x3d54; - current_registers["$ebx"] = 0x6864f054U; - cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers); - - frame.instruction = 0x3d5a; - current_registers["$esi"] = 0x6285f79aU; - cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers); - - frame.instruction = 0x3d84; - current_registers["$edi"] = 0x64061449U; - cfi_frame_info.reset(resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers); - - frame.instruction = 0x2900; - frame.module = &module1; - resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, string("PublicSymbol")); - - frame.instruction = 0x4000; - frame.module = &module1; - resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, string("LargeFunction")); - - frame.instruction = 0x2181; - frame.module = &module2; - resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Function2_2"); - ASSERT_EQ(frame.function_base, 0x2170U); - ASSERT_TRUE(frame.module); - ASSERT_EQ(frame.module->code_file(), "module2"); - ASSERT_EQ(frame.source_file_name, "file2_2.cc"); - ASSERT_EQ(frame.source_line, 21); - ASSERT_EQ(frame.source_line_base, 0x2180U); - windows_frame_info.reset(resolver.FindWindowsFrameInfo(&frame)); - ASSERT_TRUE(windows_frame_info.get()); - ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); - ASSERT_EQ(windows_frame_info->prolog_size, 1U); - - frame.instruction = 0x216f; - resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Public2_1"); - - ClearSourceLineInfo(&frame); - frame.instruction = 0x219f; - frame.module = &module2; - resolver.FillSourceLineInfo(&frame); - ASSERT_TRUE(frame.function_name.empty()); - - frame.instruction = 0x21a0; - frame.module = &module2; - resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Public2_2"); -} - -TEST_F(TestBasicSourceLineResolver, TestInvalidLoads) -{ - TestCodeModule module3("module3"); - ASSERT_TRUE(resolver.LoadModule(&module3, - testdata_dir + "/module3_bad.out")); - ASSERT_TRUE(resolver.HasModule(&module3)); - ASSERT_TRUE(resolver.IsModuleCorrupt(&module3)); - TestCodeModule module4("module4"); - ASSERT_TRUE(resolver.LoadModule(&module4, - testdata_dir + "/module4_bad.out")); - ASSERT_TRUE(resolver.HasModule(&module4)); - ASSERT_TRUE(resolver.IsModuleCorrupt(&module4)); - TestCodeModule module5("module5"); - ASSERT_FALSE(resolver.LoadModule(&module5, - testdata_dir + "/invalid-filename")); - ASSERT_FALSE(resolver.HasModule(&module5)); - TestCodeModule invalidmodule("invalid-module"); - ASSERT_FALSE(resolver.HasModule(&invalidmodule)); -} - -TEST_F(TestBasicSourceLineResolver, TestUnload) -{ - TestCodeModule module1("module1"); - ASSERT_FALSE(resolver.HasModule(&module1)); - ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out")); - ASSERT_TRUE(resolver.HasModule(&module1)); - resolver.UnloadModule(&module1); - ASSERT_FALSE(resolver.HasModule(&module1)); - ASSERT_TRUE(resolver.LoadModule(&module1, testdata_dir + "/module1.out")); - ASSERT_TRUE(resolver.HasModule(&module1)); -} - -// Test parsing of valid FILE lines. The format is: -// FILE <id> <filename> -TEST(SymbolParseHelper, ParseFileValid) { - long index; - char *filename; - - char kTestLine[] = "FILE 1 file name"; - ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename)); - EXPECT_EQ(1, index); - EXPECT_EQ("file name", string(filename)); - - // 0 is a valid index. - char kTestLine1[] = "FILE 0 file name"; - ASSERT_TRUE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename)); - EXPECT_EQ(0, index); - EXPECT_EQ("file name", string(filename)); -} - -// Test parsing of invalid FILE lines. The format is: -// FILE <id> <filename> -TEST(SymbolParseHelper, ParseFileInvalid) { - long index; - char *filename; - - // Test missing file name. - char kTestLine[] = "FILE 1 "; - ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine, &index, &filename)); - - // Test bad index. - char kTestLine1[] = "FILE x1 file name"; - ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine1, &index, &filename)); - - // Test large index. - char kTestLine2[] = "FILE 123123123123123123123123 file name"; - ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine2, &index, &filename)); - - // Test negative index. - char kTestLine3[] = "FILE -2 file name"; - ASSERT_FALSE(SymbolParseHelper::ParseFile(kTestLine3, &index, &filename)); -} - -// Test parsing of valid FUNC lines. The format is: -// FUNC <address> <size> <stack_param_size> <name> -TEST(SymbolParseHelper, ParseFunctionValid) { - uint64_t address; - uint64_t size; - long stack_param_size; - char *name; - - char kTestLine[] = "FUNC 1 2 3 function name"; - ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine, &address, &size, - &stack_param_size, &name)); - EXPECT_EQ(1ULL, address); - EXPECT_EQ(2ULL, size); - EXPECT_EQ(3, stack_param_size); - EXPECT_EQ("function name", string(name)); - - // Test hex address, size, and param size. - char kTestLine1[] = "FUNC a1 a2 a3 function name"; - ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine1, &address, &size, - &stack_param_size, &name)); - EXPECT_EQ(0xa1ULL, address); - EXPECT_EQ(0xa2ULL, size); - EXPECT_EQ(0xa3, stack_param_size); - EXPECT_EQ("function name", string(name)); - - char kTestLine2[] = "FUNC 0 0 0 function name"; - ASSERT_TRUE(SymbolParseHelper::ParseFunction(kTestLine2, &address, &size, - &stack_param_size, &name)); - EXPECT_EQ(0ULL, address); - EXPECT_EQ(0ULL, size); - EXPECT_EQ(0, stack_param_size); - EXPECT_EQ("function name", string(name)); -} - -// Test parsing of invalid FUNC lines. The format is: -// FUNC <address> <size> <stack_param_size> <name> -TEST(SymbolParseHelper, ParseFunctionInvalid) { - uint64_t address; - uint64_t size; - long stack_param_size; - char *name; - - // Test missing function name. - char kTestLine[] = "FUNC 1 2 3 "; - ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine, &address, &size, - &stack_param_size, &name)); - // Test bad address. - char kTestLine1[] = "FUNC 1z 2 3 function name"; - ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine1, &address, &size, - &stack_param_size, &name)); - // Test large address. - char kTestLine2[] = "FUNC 123123123123123123123123123 2 3 function name"; - ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine2, &address, &size, - &stack_param_size, &name)); - // Test bad size. - char kTestLine3[] = "FUNC 1 z2 3 function name"; - ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine3, &address, &size, - &stack_param_size, &name)); - // Test large size. - char kTestLine4[] = "FUNC 1 231231231231231231231231232 3 function name"; - ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine4, &address, &size, - &stack_param_size, &name)); - // Test bad param size. - char kTestLine5[] = "FUNC 1 2 3z function name"; - ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine5, &address, &size, - &stack_param_size, &name)); - // Test large param size. - char kTestLine6[] = "FUNC 1 2 312312312312312312312312323 function name"; - ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine6, &address, &size, - &stack_param_size, &name)); - // Negative param size. - char kTestLine7[] = "FUNC 1 2 -5 function name"; - ASSERT_FALSE(SymbolParseHelper::ParseFunction(kTestLine7, &address, &size, - &stack_param_size, &name)); -} - -// Test parsing of valid lines. The format is: -// <address> <size> <line number> <source file id> -TEST(SymbolParseHelper, ParseLineValid) { - uint64_t address; - uint64_t size; - long line_number; - long source_file; - - char kTestLine[] = "1 2 3 4"; - ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine, &address, &size, - &line_number, &source_file)); - EXPECT_EQ(1ULL, address); - EXPECT_EQ(2ULL, size); - EXPECT_EQ(3, line_number); - EXPECT_EQ(4, source_file); - - // Test hex size and address. - char kTestLine1[] = "a1 a2 3 4 // some comment"; - ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size, - &line_number, &source_file)); - EXPECT_EQ(0xa1ULL, address); - EXPECT_EQ(0xa2ULL, size); - EXPECT_EQ(3, line_number); - EXPECT_EQ(4, source_file); - - // 0 is a valid line number. - char kTestLine2[] = "a1 a2 0 4 // some comment"; - ASSERT_TRUE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size, - &line_number, &source_file)); - EXPECT_EQ(0xa1ULL, address); - EXPECT_EQ(0xa2ULL, size); - EXPECT_EQ(0, line_number); - EXPECT_EQ(4, source_file); -} - -// Test parsing of invalid lines. The format is: -// <address> <size> <line number> <source file id> -TEST(SymbolParseHelper, ParseLineInvalid) { - uint64_t address; - uint64_t size; - long line_number; - long source_file; - - // Test missing source file id. - char kTestLine[] = "1 2 3"; - ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine, &address, &size, - &line_number, &source_file)); - // Test bad address. - char kTestLine1[] = "1z 2 3 4"; - ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine1, &address, &size, - &line_number, &source_file)); - // Test large address. - char kTestLine2[] = "123123123123123123123123 2 3 4"; - ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine2, &address, &size, - &line_number, &source_file)); - // Test bad size. - char kTestLine3[] = "1 z2 3 4"; - ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine3, &address, &size, - &line_number, &source_file)); - // Test large size. - char kTestLine4[] = "1 123123123123123123123123 3 4"; - ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine4, &address, &size, - &line_number, &source_file)); - // Test bad line number. - char kTestLine5[] = "1 2 z3 4"; - ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine5, &address, &size, - &line_number, &source_file)); - // Test negative line number. - char kTestLine6[] = "1 2 -1 4"; - ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine6, &address, &size, - &line_number, &source_file)); - // Test large line number. - char kTestLine7[] = "1 2 123123123123123123123 4"; - ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine7, &address, &size, - &line_number, &source_file)); - // Test bad source file id. - char kTestLine8[] = "1 2 3 f"; - ASSERT_FALSE(SymbolParseHelper::ParseLine(kTestLine8, &address, &size, - &line_number, &source_file)); -} - -// Test parsing of valid PUBLIC lines. The format is: -// PUBLIC <address> <stack_param_size> <name> -TEST(SymbolParseHelper, ParsePublicSymbolValid) { - uint64_t address; - long stack_param_size; - char *name; - - char kTestLine[] = "PUBLIC 1 2 3"; - ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &address, - &stack_param_size, &name)); - EXPECT_EQ(1ULL, address); - EXPECT_EQ(2, stack_param_size); - EXPECT_EQ("3", string(name)); - - // Test hex size and address. - char kTestLine1[] = "PUBLIC a1 a2 function name"; - ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &address, - &stack_param_size, &name)); - EXPECT_EQ(0xa1ULL, address); - EXPECT_EQ(0xa2, stack_param_size); - EXPECT_EQ("function name", string(name)); - - // Test 0 is a valid address. - char kTestLine2[] = "PUBLIC 0 a2 function name"; - ASSERT_TRUE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &address, - &stack_param_size, &name)); - EXPECT_EQ(0ULL, address); - EXPECT_EQ(0xa2, stack_param_size); - EXPECT_EQ("function name", string(name)); -} - -// Test parsing of invalid PUBLIC lines. The format is: -// PUBLIC <address> <stack_param_size> <name> -TEST(SymbolParseHelper, ParsePublicSymbolInvalid) { - uint64_t address; - long stack_param_size; - char *name; - - // Test missing source function name. - char kTestLine[] = "PUBLIC 1 2 "; - ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine, &address, - &stack_param_size, &name)); - // Test bad address. - char kTestLine1[] = "PUBLIC 1z 2 3"; - ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine1, &address, - &stack_param_size, &name)); - // Test large address. - char kTestLine2[] = "PUBLIC 123123123123123123123123 2 3"; - ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine2, &address, - &stack_param_size, &name)); - // Test bad param stack size. - char kTestLine3[] = "PUBLIC 1 z2 3"; - ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine3, &address, - &stack_param_size, &name)); - // Test large param stack size. - char kTestLine4[] = "PUBLIC 1 123123123123123123123123123 3"; - ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine4, &address, - &stack_param_size, &name)); - // Test negative param stack size. - char kTestLine5[] = "PUBLIC 1 -5 3"; - ASSERT_FALSE(SymbolParseHelper::ParsePublicSymbol(kTestLine5, &address, - &stack_param_size, &name)); -} - -} // namespace - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/call_stack.cc b/toolkit/crashreporter/google-breakpad/src/processor/call_stack.cc deleted file mode 100644 index 925f08469..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/call_stack.cc +++ /dev/null @@ -1,54 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// call_stack.cc: A call stack comprised of stack frames. -// -// See call_stack.h for documentation. -// -// Author: Mark Mentovai - -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/stack_frame.h" - -namespace google_breakpad { - -CallStack::~CallStack() { - Clear(); -} - -void CallStack::Clear() { - for (vector<StackFrame *>::const_iterator iterator = frames_.begin(); - iterator != frames_.end(); - ++iterator) { - delete *iterator; - } - tid_ = 0; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info-inl.h deleted file mode 100644 index 7e7af0af9..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info-inl.h +++ /dev/null @@ -1,119 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// cfi_frame_info-inl.h: Definitions for cfi_frame_info.h inlined functions. - -#ifndef PROCESSOR_CFI_FRAME_INFO_INL_H_ -#define PROCESSOR_CFI_FRAME_INFO_INL_H_ - -#include <string.h> - -namespace google_breakpad { - -template <typename RegisterType, class RawContextType> -bool SimpleCFIWalker<RegisterType, RawContextType>::FindCallerRegisters( - const MemoryRegion &memory, - const CFIFrameInfo &cfi_frame_info, - const RawContextType &callee_context, - int callee_validity, - RawContextType *caller_context, - int *caller_validity) const { - typedef CFIFrameInfo::RegisterValueMap<RegisterType> ValueMap; - ValueMap callee_registers; - ValueMap caller_registers; - // Just for brevity. - typename ValueMap::const_iterator caller_none = caller_registers.end(); - - // Populate callee_registers with register values from callee_context. - for (size_t i = 0; i < map_size_; i++) { - const RegisterSet &r = register_map_[i]; - if (callee_validity & r.validity_flag) - callee_registers[r.name] = callee_context.*r.context_member; - } - - // Apply the rules, and see what register values they yield. - if (!cfi_frame_info.FindCallerRegs<RegisterType>(callee_registers, memory, - &caller_registers)) - return false; - - // Populate *caller_context with the values the rules placed in - // caller_registers. - memset(caller_context, 0xda, sizeof(*caller_context)); - *caller_validity = 0; - for (size_t i = 0; i < map_size_; i++) { - const RegisterSet &r = register_map_[i]; - typename ValueMap::const_iterator caller_entry; - - // Did the rules provide a value for this register by its name? - caller_entry = caller_registers.find(r.name); - if (caller_entry != caller_none) { - caller_context->*r.context_member = caller_entry->second; - *caller_validity |= r.validity_flag; - continue; - } - - // Did the rules provide a value for this register under its - // alternate name? - if (r.alternate_name) { - caller_entry = caller_registers.find(r.alternate_name); - if (caller_entry != caller_none) { - caller_context->*r.context_member = caller_entry->second; - *caller_validity |= r.validity_flag; - continue; - } - } - - // Is this a callee-saves register? The walker assumes that these - // still hold the caller's value if the CFI doesn't mention them. - // - // Note that other frame walkers may fail to recover callee-saves - // registers; for example, the x86 "traditional" strategy only - // recovers %eip, %esp, and %ebp, even though %ebx, %esi, and %edi - // are callee-saves, too. It is not correct to blindly set the - // valid bit for all callee-saves registers, without first - // checking its validity bit in the callee. - if (r.callee_saves && (callee_validity & r.validity_flag) != 0) { - caller_context->*r.context_member = callee_context.*r.context_member; - *caller_validity |= r.validity_flag; - continue; - } - - // Otherwise, the register's value is unknown. - } - - return true; -} - -} // namespace google_breakpad - -#endif // PROCESSOR_CFI_FRAME_INFO_INL_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc deleted file mode 100644 index 0c4af7ba8..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.cc +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// cfi_frame_info.cc: Implementation of CFIFrameInfo class. -// See cfi_frame_info.h for details. - -#include "processor/cfi_frame_info.h" - -#include <string.h> - -#include <sstream> - -#include "common/scoped_ptr.h" -#include "processor/postfix_evaluator-inl.h" - -namespace google_breakpad { - -#ifdef _MSC_VER -#define strtok_r strtok_s -#endif - -template<typename V> -bool CFIFrameInfo::FindCallerRegs(const RegisterValueMap<V> ®isters, - const MemoryRegion &memory, - RegisterValueMap<V> *caller_registers) const { - // If there are not rules for both .ra and .cfa in effect at this address, - // don't use this CFI data for stack walking. - if (cfa_rule_.empty() || ra_rule_.empty()) - return false; - - RegisterValueMap<V> working; - PostfixEvaluator<V> evaluator(&working, &memory); - - caller_registers->clear(); - - // First, compute the CFA. - V cfa; - working = registers; - if (!evaluator.EvaluateForValue(cfa_rule_, &cfa)) - return false; - - // Then, compute the return address. - V ra; - working = registers; - working[".cfa"] = cfa; - if (!evaluator.EvaluateForValue(ra_rule_, &ra)) - return false; - - // Now, compute values for all the registers register_rules_ mentions. - for (RuleMap::const_iterator it = register_rules_.begin(); - it != register_rules_.end(); it++) { - V value; - working = registers; - working[".cfa"] = cfa; - if (!evaluator.EvaluateForValue(it->second, &value)) - return false; - (*caller_registers)[it->first] = value; - } - - (*caller_registers)[".ra"] = ra; - (*caller_registers)[".cfa"] = cfa; - - return true; -} - -// Explicit instantiations for 32-bit and 64-bit architectures. -template bool CFIFrameInfo::FindCallerRegs<uint32_t>( - const RegisterValueMap<uint32_t> ®isters, - const MemoryRegion &memory, - RegisterValueMap<uint32_t> *caller_registers) const; -template bool CFIFrameInfo::FindCallerRegs<uint64_t>( - const RegisterValueMap<uint64_t> ®isters, - const MemoryRegion &memory, - RegisterValueMap<uint64_t> *caller_registers) const; - -string CFIFrameInfo::Serialize() const { - std::ostringstream stream; - - if (!cfa_rule_.empty()) { - stream << ".cfa: " << cfa_rule_; - } - if (!ra_rule_.empty()) { - if (static_cast<std::streamoff>(stream.tellp()) != 0) - stream << " "; - stream << ".ra: " << ra_rule_; - } - for (RuleMap::const_iterator iter = register_rules_.begin(); - iter != register_rules_.end(); - ++iter) { - if (static_cast<std::streamoff>(stream.tellp()) != 0) - stream << " "; - stream << iter->first << ": " << iter->second; - } - - return stream.str(); -} - -bool CFIRuleParser::Parse(const string &rule_set) { - size_t rule_set_len = rule_set.size(); - scoped_array<char> working_copy(new char[rule_set_len + 1]); - memcpy(working_copy.get(), rule_set.data(), rule_set_len); - working_copy[rule_set_len] = '\0'; - - name_.clear(); - expression_.clear(); - - char *cursor; - static const char token_breaks[] = " \t\r\n"; - char *token = strtok_r(working_copy.get(), token_breaks, &cursor); - - for (;;) { - // End of rule set? - if (!token) return Report(); - - // Register/pseudoregister name? - size_t token_len = strlen(token); - if (token_len >= 1 && token[token_len - 1] == ':') { - // Names can't be empty. - if (token_len < 2) return false; - // If there is any pending content, report it. - if (!name_.empty() || !expression_.empty()) { - if (!Report()) return false; - } - name_.assign(token, token_len - 1); - expression_.clear(); - } else { - // Another expression component. - assert(token_len > 0); // strtok_r guarantees this, I think. - if (!expression_.empty()) - expression_ += ' '; - expression_ += token; - } - token = strtok_r(NULL, token_breaks, &cursor); - } -} - -bool CFIRuleParser::Report() { - if (name_.empty() || expression_.empty()) return false; - if (name_ == ".cfa") handler_->CFARule(expression_); - else if (name_ == ".ra") handler_->RARule(expression_); - else handler_->RegisterRule(name_, expression_); - return true; -} - -void CFIFrameInfoParseHandler::CFARule(const string &expression) { - frame_info_->SetCFARule(expression); -} - -void CFIFrameInfoParseHandler::RARule(const string &expression) { - frame_info_->SetRARule(expression); -} - -void CFIFrameInfoParseHandler::RegisterRule(const string &name, - const string &expression) { - frame_info_->SetRegisterRule(name, expression); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.h b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.h deleted file mode 100644 index 90a1b3d74..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info.h +++ /dev/null @@ -1,275 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// cfi_frame_info.h: Define the CFIFrameInfo class, which holds the -// set of 'STACK CFI'-derived register recovery rules that apply at a -// given instruction. - -#ifndef PROCESSOR_CFI_FRAME_INFO_H_ -#define PROCESSOR_CFI_FRAME_INFO_H_ - -#include <map> -#include <string> - -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" - -namespace google_breakpad { - -using std::map; - -class MemoryRegion; - -// A set of rules for recovering the calling frame's registers' -// values, when the PC is at a given address in the current frame's -// function. See the description of 'STACK CFI' records at: -// -// https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md -// -// To prepare an instance of CFIFrameInfo for use at a given -// instruction, first populate it with the rules from the 'STACK CFI -// INIT' record that covers that instruction, and then apply the -// changes given by the 'STACK CFI' records up to our instruction's -// address. Then, use the FindCallerRegs member function to apply the -// rules to the callee frame's register values, yielding the caller -// frame's register values. -class CFIFrameInfo { - public: - // A map from register names onto values. - template<typename ValueType> class RegisterValueMap: - public map<string, ValueType> { }; - - // Set the expression for computing a call frame address, return - // address, or register's value. At least the CFA rule and the RA - // rule must be set before calling FindCallerRegs. - void SetCFARule(const string &expression) { cfa_rule_ = expression; } - void SetRARule(const string &expression) { ra_rule_ = expression; } - void SetRegisterRule(const string ®ister_name, const string &expression) { - register_rules_[register_name] = expression; - } - - // Compute the values of the calling frame's registers, according to - // this rule set. Use ValueType in expression evaluation; this - // should be uint32_t on machines with 32-bit addresses, or - // uint64_t on machines with 64-bit addresses. - // - // Return true on success, false otherwise. - // - // MEMORY provides access to the contents of the stack. REGISTERS is - // a dictionary mapping the names of registers whose values are - // known in the current frame to their values. CALLER_REGISTERS is - // populated with the values of the recoverable registers in the - // frame that called the current frame. - // - // In addition, CALLER_REGISTERS[".ra"] will be the return address, - // and CALLER_REGISTERS[".cfa"] will be the call frame address. - // These may be helpful in computing the caller's PC and stack - // pointer, if their values are not explicitly specified. - template<typename ValueType> - bool FindCallerRegs(const RegisterValueMap<ValueType> ®isters, - const MemoryRegion &memory, - RegisterValueMap<ValueType> *caller_registers) const; - - // Serialize the rules in this object into a string in the format - // of STACK CFI records. - string Serialize() const; - - private: - - // A map from register names onto evaluation rules. - typedef map<string, string> RuleMap; - - // In this type, a "postfix expression" is an expression of the sort - // interpreted by google_breakpad::PostfixEvaluator. - - // A postfix expression for computing the current frame's CFA (call - // frame address). The CFA is a reference address for the frame that - // remains unchanged throughout the frame's lifetime. You should - // evaluate this expression with a dictionary initially populated - // with the values of the current frame's known registers. - string cfa_rule_; - - // The following expressions should be evaluated with a dictionary - // initially populated with the values of the current frame's known - // registers, and with ".cfa" set to the result of evaluating the - // cfa_rule expression, above. - - // A postfix expression for computing the current frame's return - // address. - string ra_rule_; - - // For a register named REG, rules[REG] is a postfix expression - // which leaves the value of REG in the calling frame on the top of - // the stack. You should evaluate this expression - RuleMap register_rules_; -}; - -// A parser for STACK CFI-style rule sets. -// This may seem bureaucratic: there's no legitimate run-time reason -// to use a parser/handler pattern for this, as it's not a likely -// reuse boundary. But doing so makes finer-grained unit testing -// possible. -class CFIRuleParser { - public: - - class Handler { - public: - Handler() { } - virtual ~Handler() { } - - // The input specifies EXPRESSION as the CFA/RA computation rule. - virtual void CFARule(const string &expression) = 0; - virtual void RARule(const string &expression) = 0; - - // The input specifies EXPRESSION as the recovery rule for register NAME. - virtual void RegisterRule(const string &name, const string &expression) = 0; - }; - - // Construct a parser which feeds its results to HANDLER. - CFIRuleParser(Handler *handler) : handler_(handler) { } - - // Parse RULE_SET as a set of CFA computation and RA/register - // recovery rules, as appearing in STACK CFI records. Report the - // results of parsing by making the appropriate calls to handler_. - // Return true if parsing was successful, false otherwise. - bool Parse(const string &rule_set); - - private: - // Report any accumulated rule to handler_ - bool Report(); - - // The handler to which the parser reports its findings. - Handler *handler_; - - // Working data. - string name_, expression_; -}; - -// A handler for rule set parsing that populates a CFIFrameInfo with -// the results. -class CFIFrameInfoParseHandler: public CFIRuleParser::Handler { - public: - // Populate FRAME_INFO with the results of parsing. - CFIFrameInfoParseHandler(CFIFrameInfo *frame_info) - : frame_info_(frame_info) { } - - void CFARule(const string &expression); - void RARule(const string &expression); - void RegisterRule(const string &name, const string &expression); - - private: - CFIFrameInfo *frame_info_; -}; - -// A utility class template for simple 'STACK CFI'-driven stack walkers. -// Given a CFIFrameInfo instance, a table describing the architecture's -// register set, and a context holding the last frame's registers, an -// instance of this class can populate a new context with the caller's -// registers. -// -// This class template doesn't use any internal knowledge of CFIFrameInfo -// or the other stack walking structures; it just uses the public interface -// of CFIFrameInfo to do the usual things. But the logic it handles should -// be common to many different architectures' stack walkers, so wrapping it -// up in a class should allow the walkers to share code. -// -// RegisterType should be the type of this architecture's registers, either -// uint32_t or uint64_t. RawContextType should be the raw context -// structure type for this architecture. -template <typename RegisterType, class RawContextType> -class SimpleCFIWalker { - public: - // A structure describing one architecture register. - struct RegisterSet { - // The register name, as it appears in STACK CFI rules. - const char *name; - - // An alternate name that the register's value might be found - // under in a register value dictionary, or NULL. When generating - // names, prefer NAME to this value. It's common to list ".cfa" as - // an alternative name for the stack pointer, and ".ra" as an - // alternative name for the instruction pointer. - const char *alternate_name; - - // True if the callee is expected to preserve the value of this - // register. If this flag is true for some register R, and the STACK - // CFI records provide no rule to recover R, then SimpleCFIWalker - // assumes that the callee has not changed R's value, and the caller's - // value for R is that currently in the callee's context. - bool callee_saves; - - // The ContextValidity flag representing the register's presence. - int validity_flag; - - // A pointer to the RawContextType member that holds the - // register's value. - RegisterType RawContextType::*context_member; - }; - - // Create a simple CFI-based frame walker, given a description of the - // architecture's register set. REGISTER_MAP is an array of - // RegisterSet structures; MAP_SIZE is the number of elements in the - // array. - SimpleCFIWalker(const RegisterSet *register_map, size_t map_size) - : register_map_(register_map), map_size_(map_size) { } - - // Compute the calling frame's raw context given the callee's raw - // context. - // - // Given: - // - // - MEMORY, holding the stack's contents, - // - CFI_FRAME_INFO, describing the called function, - // - CALLEE_CONTEXT, holding the called frame's registers, and - // - CALLEE_VALIDITY, indicating which registers in CALLEE_CONTEXT are valid, - // - // fill in CALLER_CONTEXT with the caller's register values, and set - // CALLER_VALIDITY to indicate which registers are valid in - // CALLER_CONTEXT. Return true on success, or false on failure. - bool FindCallerRegisters(const MemoryRegion &memory, - const CFIFrameInfo &cfi_frame_info, - const RawContextType &callee_context, - int callee_validity, - RawContextType *caller_context, - int *caller_validity) const; - - private: - const RegisterSet *register_map_; - size_t map_size_; -}; - -} // namespace google_breakpad - -#include "cfi_frame_info-inl.h" - -#endif // PROCESSOR_CFI_FRAME_INFO_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info_unittest.cc deleted file mode 100644 index 542b28492..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/cfi_frame_info_unittest.cc +++ /dev/null @@ -1,546 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// cfi_frame_info_unittest.cc: Unit tests for CFIFrameInfo, -// CFIRuleParser, CFIFrameInfoParseHandler, and SimpleCFIWalker. - -#include <string.h> - -#include "breakpad_googletest_includes.h" -#include "common/using_std_string.h" -#include "processor/cfi_frame_info.h" -#include "google_breakpad/processor/memory_region.h" - -using google_breakpad::CFIFrameInfo; -using google_breakpad::CFIFrameInfoParseHandler; -using google_breakpad::CFIRuleParser; -using google_breakpad::MemoryRegion; -using google_breakpad::SimpleCFIWalker; -using testing::_; -using testing::A; -using testing::AtMost; -using testing::DoAll; -using testing::Return; -using testing::SetArgumentPointee; -using testing::Test; - -class MockMemoryRegion: public MemoryRegion { - public: - MOCK_CONST_METHOD0(GetBase, uint64_t()); - MOCK_CONST_METHOD0(GetSize, uint32_t()); - MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint8_t *)); - MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint16_t *)); - MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint32_t *)); - MOCK_CONST_METHOD2(GetMemoryAtAddress, bool(uint64_t, uint64_t *)); - MOCK_CONST_METHOD0(Print, void()); -}; - -// Handy definitions for all tests. -struct CFIFixture { - - // Set up the mock memory object to expect no references. - void ExpectNoMemoryReferences() { - EXPECT_CALL(memory, GetBase()).Times(0); - EXPECT_CALL(memory, GetSize()).Times(0); - EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint8_t *>())).Times(0); - EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint16_t *>())).Times(0); - EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint32_t *>())).Times(0); - EXPECT_CALL(memory, GetMemoryAtAddress(_, A<uint64_t *>())).Times(0); - } - - CFIFrameInfo cfi; - MockMemoryRegion memory; - CFIFrameInfo::RegisterValueMap<uint64_t> registers, caller_registers; -}; - -class Simple: public CFIFixture, public Test { }; - -// FindCallerRegs should fail if no .cfa rule is provided. -TEST_F(Simple, NoCFA) { - ExpectNoMemoryReferences(); - - cfi.SetRARule("0"); - ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(".ra: 0", cfi.Serialize()); -} - -// FindCallerRegs should fail if no .ra rule is provided. -TEST_F(Simple, NoRA) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule("0"); - ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(".cfa: 0", cfi.Serialize()); -} - -TEST_F(Simple, SetCFAAndRARule) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule("330903416631436410"); - cfi.SetRARule("5870666104170902211"); - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(2U, caller_registers.size()); - ASSERT_EQ(330903416631436410ULL, caller_registers[".cfa"]); - ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]); - - ASSERT_EQ(".cfa: 330903416631436410 .ra: 5870666104170902211", - cfi.Serialize()); -} - -TEST_F(Simple, SetManyRules) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule("$temp1 68737028 = $temp2 61072337 = $temp1 $temp2 -"); - cfi.SetRARule(".cfa 99804755 +"); - cfi.SetRegisterRule("register1", ".cfa 54370437 *"); - cfi.SetRegisterRule("vodkathumbscrewingly", "24076308 .cfa +"); - cfi.SetRegisterRule("pubvexingfjordschmaltzy", ".cfa 29801007 -"); - cfi.SetRegisterRule("uncopyrightables", "92642917 .cfa /"); - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(6U, caller_registers.size()); - ASSERT_EQ(7664691U, caller_registers[".cfa"]); - ASSERT_EQ(107469446U, caller_registers[".ra"]); - ASSERT_EQ(416732599139967ULL, caller_registers["register1"]); - ASSERT_EQ(31740999U, caller_registers["vodkathumbscrewingly"]); - ASSERT_EQ(-22136316ULL, caller_registers["pubvexingfjordschmaltzy"]); - ASSERT_EQ(12U, caller_registers["uncopyrightables"]); - ASSERT_EQ(".cfa: $temp1 68737028 = $temp2 61072337 = $temp1 $temp2 - " - ".ra: .cfa 99804755 + " - "pubvexingfjordschmaltzy: .cfa 29801007 - " - "register1: .cfa 54370437 * " - "uncopyrightables: 92642917 .cfa / " - "vodkathumbscrewingly: 24076308 .cfa +", - cfi.Serialize()); -} - -TEST_F(Simple, RulesOverride) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule("330903416631436410"); - cfi.SetRARule("5870666104170902211"); - cfi.SetCFARule("2828089117179001"); - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(2U, caller_registers.size()); - ASSERT_EQ(2828089117179001ULL, caller_registers[".cfa"]); - ASSERT_EQ(5870666104170902211ULL, caller_registers[".ra"]); - ASSERT_EQ(".cfa: 2828089117179001 .ra: 5870666104170902211", - cfi.Serialize()); -} - -class Scope: public CFIFixture, public Test { }; - -// There should be no value for .cfa in scope when evaluating the CFA rule. -TEST_F(Scope, CFALacksCFA) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule(".cfa"); - cfi.SetRARule("0"); - ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); -} - -// There should be no value for .ra in scope when evaluating the CFA rule. -TEST_F(Scope, CFALacksRA) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule(".ra"); - cfi.SetRARule("0"); - ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); -} - -// The current frame's registers should be in scope when evaluating -// the CFA rule. -TEST_F(Scope, CFASeesCurrentRegs) { - ExpectNoMemoryReferences(); - - registers[".baraminology"] = 0x06a7bc63e4f13893ULL; - registers[".ornithorhynchus"] = 0x5e0bf850bafce9d2ULL; - cfi.SetCFARule(".baraminology .ornithorhynchus +"); - cfi.SetRARule("0"); - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(2U, caller_registers.size()); - ASSERT_EQ(0x06a7bc63e4f13893ULL + 0x5e0bf850bafce9d2ULL, - caller_registers[".cfa"]); -} - -// .cfa should be in scope in the return address expression. -TEST_F(Scope, RASeesCFA) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule("48364076"); - cfi.SetRARule(".cfa"); - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(2U, caller_registers.size()); - ASSERT_EQ(48364076U, caller_registers[".ra"]); -} - -// There should be no value for .ra in scope when evaluating the CFA rule. -TEST_F(Scope, RALacksRA) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule("0"); - cfi.SetRARule(".ra"); - ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); -} - -// The current frame's registers should be in scope in the return -// address expression. -TEST_F(Scope, RASeesCurrentRegs) { - ExpectNoMemoryReferences(); - - registers["noachian"] = 0x54dc4a5d8e5eb503ULL; - cfi.SetCFARule("10359370"); - cfi.SetRARule("noachian"); - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(2U, caller_registers.size()); - ASSERT_EQ(0x54dc4a5d8e5eb503ULL, caller_registers[".ra"]); -} - -// .cfa should be in scope for register rules. -TEST_F(Scope, RegistersSeeCFA) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule("6515179"); - cfi.SetRARule(".cfa"); - cfi.SetRegisterRule("rogerian", ".cfa"); - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(3U, caller_registers.size()); - ASSERT_EQ(6515179U, caller_registers["rogerian"]); -} - -// The return address should not be in scope for register rules. -TEST_F(Scope, RegsLackRA) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule("42740329"); - cfi.SetRARule("27045204"); - cfi.SetRegisterRule("$r1", ".ra"); - ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); -} - -// Register rules can see the current frame's register values. -TEST_F(Scope, RegsSeeRegs) { - ExpectNoMemoryReferences(); - - registers["$r1"] = 0x6ed3582c4bedb9adULL; - registers["$r2"] = 0xd27d9e742b8df6d0ULL; - cfi.SetCFARule("88239303"); - cfi.SetRARule("30503835"); - cfi.SetRegisterRule("$r1", "$r1 42175211 = $r2"); - cfi.SetRegisterRule("$r2", "$r2 21357221 = $r1"); - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(4U, caller_registers.size()); - ASSERT_EQ(0xd27d9e742b8df6d0ULL, caller_registers["$r1"]); - ASSERT_EQ(0x6ed3582c4bedb9adULL, caller_registers["$r2"]); -} - -// Each rule's temporaries are separate. -TEST_F(Scope, SeparateTempsRA) { - ExpectNoMemoryReferences(); - - cfi.SetCFARule("$temp1 76569129 = $temp1"); - cfi.SetRARule("0"); - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - - cfi.SetCFARule("$temp1 76569129 = $temp1"); - cfi.SetRARule("$temp1"); - ASSERT_FALSE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); -} - -class MockCFIRuleParserHandler: public CFIRuleParser::Handler { - public: - MOCK_METHOD1(CFARule, void(const string &)); - MOCK_METHOD1(RARule, void(const string &)); - MOCK_METHOD2(RegisterRule, void(const string &, const string &)); -}; - -// A fixture class for testing CFIRuleParser. -class CFIParserFixture { - public: - CFIParserFixture() : parser(&mock_handler) { - // Expect no parsing results to be reported to mock_handler. Individual - // tests can override this. - EXPECT_CALL(mock_handler, CFARule(_)).Times(0); - EXPECT_CALL(mock_handler, RARule(_)).Times(0); - EXPECT_CALL(mock_handler, RegisterRule(_, _)).Times(0); - } - - MockCFIRuleParserHandler mock_handler; - CFIRuleParser parser; -}; - -class Parser: public CFIParserFixture, public Test { }; - -TEST_F(Parser, Empty) { - EXPECT_FALSE(parser.Parse("")); -} - -TEST_F(Parser, LoneColon) { - EXPECT_FALSE(parser.Parse(":")); -} - -TEST_F(Parser, CFANoExpr) { - EXPECT_FALSE(parser.Parse(".cfa:")); -} - -TEST_F(Parser, CFANoColonNoExpr) { - EXPECT_FALSE(parser.Parse(".cfa")); -} - -TEST_F(Parser, RANoExpr) { - EXPECT_FALSE(parser.Parse(".ra:")); -} - -TEST_F(Parser, RANoColonNoExpr) { - EXPECT_FALSE(parser.Parse(".ra")); -} - -TEST_F(Parser, RegNoExpr) { - EXPECT_FALSE(parser.Parse("reg:")); -} - -TEST_F(Parser, NoName) { - EXPECT_FALSE(parser.Parse("expr")); -} - -TEST_F(Parser, NoNameTwo) { - EXPECT_FALSE(parser.Parse("expr1 expr2")); -} - -TEST_F(Parser, StartsWithExpr) { - EXPECT_FALSE(parser.Parse("expr1 reg: expr2")); -} - -TEST_F(Parser, CFA) { - EXPECT_CALL(mock_handler, CFARule("spleen")).WillOnce(Return()); - EXPECT_TRUE(parser.Parse(".cfa: spleen")); -} - -TEST_F(Parser, RA) { - EXPECT_CALL(mock_handler, RARule("notoriety")).WillOnce(Return()); - EXPECT_TRUE(parser.Parse(".ra: notoriety")); -} - -TEST_F(Parser, Reg) { - EXPECT_CALL(mock_handler, RegisterRule("nemo", "mellifluous")) - .WillOnce(Return()); - EXPECT_TRUE(parser.Parse("nemo: mellifluous")); -} - -TEST_F(Parser, CFARARegs) { - EXPECT_CALL(mock_handler, CFARule("cfa expression")).WillOnce(Return()); - EXPECT_CALL(mock_handler, RARule("ra expression")).WillOnce(Return()); - EXPECT_CALL(mock_handler, RegisterRule("galba", "praetorian")) - .WillOnce(Return()); - EXPECT_CALL(mock_handler, RegisterRule("otho", "vitellius")) - .WillOnce(Return()); - EXPECT_TRUE(parser.Parse(".cfa: cfa expression .ra: ra expression " - "galba: praetorian otho: vitellius")); -} - -TEST_F(Parser, Whitespace) { - EXPECT_CALL(mock_handler, RegisterRule("r1", "r1 expression")) - .WillOnce(Return()); - EXPECT_CALL(mock_handler, RegisterRule("r2", "r2 expression")) - .WillOnce(Return()); - EXPECT_TRUE(parser.Parse(" r1:\tr1\nexpression \tr2:\t\rr2\r\n " - "expression \n")); -} - -TEST_F(Parser, WhitespaceLoneColon) { - EXPECT_FALSE(parser.Parse(" \n:\t ")); -} - -TEST_F(Parser, EmptyName) { - EXPECT_CALL(mock_handler, RegisterRule("reg", _)) - .Times(AtMost(1)) - .WillRepeatedly(Return()); - EXPECT_FALSE(parser.Parse("reg: expr1 : expr2")); -} - -TEST_F(Parser, RuleLoneColon) { - EXPECT_CALL(mock_handler, RegisterRule("r1", "expr")) - .Times(AtMost(1)) - .WillRepeatedly(Return()); - EXPECT_FALSE(parser.Parse(" r1: expr :")); -} - -TEST_F(Parser, RegNoExprRule) { - EXPECT_CALL(mock_handler, RegisterRule("r1", "expr")) - .Times(AtMost(1)) - .WillRepeatedly(Return()); - EXPECT_FALSE(parser.Parse("r0: r1: expr")); -} - -class ParseHandlerFixture: public CFIFixture { - public: - ParseHandlerFixture() : CFIFixture(), handler(&cfi) { } - CFIFrameInfoParseHandler handler; -}; - -class ParseHandler: public ParseHandlerFixture, public Test { }; - -TEST_F(ParseHandler, CFARARule) { - handler.CFARule("reg-for-cfa"); - handler.RARule("reg-for-ra"); - registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL; - registers["reg-for-ra"] = 0x6301b475b8b91c02ULL; - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]); - ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]); -} - -TEST_F(ParseHandler, RegisterRules) { - handler.CFARule("reg-for-cfa"); - handler.RARule("reg-for-ra"); - handler.RegisterRule("reg1", "reg-for-reg1"); - handler.RegisterRule("reg2", "reg-for-reg2"); - registers["reg-for-cfa"] = 0x268a9a4a3821a797ULL; - registers["reg-for-ra"] = 0x6301b475b8b91c02ULL; - registers["reg-for-reg1"] = 0x06cde8e2ff062481ULL; - registers["reg-for-reg2"] = 0xff0c4f76403173e2ULL; - ASSERT_TRUE(cfi.FindCallerRegs<uint64_t>(registers, memory, - &caller_registers)); - ASSERT_EQ(0x268a9a4a3821a797ULL, caller_registers[".cfa"]); - ASSERT_EQ(0x6301b475b8b91c02ULL, caller_registers[".ra"]); - ASSERT_EQ(0x06cde8e2ff062481ULL, caller_registers["reg1"]); - ASSERT_EQ(0xff0c4f76403173e2ULL, caller_registers["reg2"]); -} - -struct SimpleCFIWalkerFixture { - struct RawContext { - uint64_t r0, r1, r2, r3, r4, sp, pc; - }; - enum Validity { - R0_VALID = 0x01, - R1_VALID = 0x02, - R2_VALID = 0x04, - R3_VALID = 0x08, - R4_VALID = 0x10, - SP_VALID = 0x20, - PC_VALID = 0x40 - }; - typedef SimpleCFIWalker<uint64_t, RawContext> CFIWalker; - - SimpleCFIWalkerFixture() - : walker(register_map, - sizeof(register_map) / sizeof(register_map[0])) { } - - static CFIWalker::RegisterSet register_map[7]; - CFIFrameInfo call_frame_info; - CFIWalker walker; - MockMemoryRegion memory; - RawContext callee_context, caller_context; -}; - -SimpleCFIWalkerFixture::CFIWalker::RegisterSet -SimpleCFIWalkerFixture::register_map[7] = { - { "r0", NULL, true, R0_VALID, &RawContext::r0 }, - { "r1", NULL, true, R1_VALID, &RawContext::r1 }, - { "r2", NULL, false, R2_VALID, &RawContext::r2 }, - { "r3", NULL, false, R3_VALID, &RawContext::r3 }, - { "r4", NULL, true, R4_VALID, &RawContext::r4 }, - { "sp", ".cfa", true, SP_VALID, &RawContext::sp }, - { "pc", ".ra", true, PC_VALID, &RawContext::pc }, -}; - -class SimpleWalker: public SimpleCFIWalkerFixture, public Test { }; - -TEST_F(SimpleWalker, Walk) { - // Stack_top is the current stack pointer, pointing to the lowest - // address of a frame that looks like this (all 64-bit words): - // - // sp -> saved r0 - // garbage - // return address - // cfa -> - // - // r0 has been saved on the stack. - // r1 has been saved in r2. - // r2 and r3 are not recoverable. - // r4 is not recoverable, even though it is a callee-saves register. - // Some earlier frame's unwinder must have failed to recover it. - - uint64_t stack_top = 0x83254944b20d5512ULL; - - // Saved r0. - EXPECT_CALL(memory, - GetMemoryAtAddress(stack_top, A<uint64_t *>())) - .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xdc1975eba8602302ULL), - Return(true))); - // Saved return address. - EXPECT_CALL(memory, - GetMemoryAtAddress(stack_top + 16, A<uint64_t *>())) - .WillRepeatedly(DoAll(SetArgumentPointee<1>(0xba5ad6d9acce28deULL), - Return(true))); - - call_frame_info.SetCFARule("sp 24 +"); - call_frame_info.SetRARule(".cfa 8 - ^"); - call_frame_info.SetRegisterRule("r0", ".cfa 24 - ^"); - call_frame_info.SetRegisterRule("r1", "r2"); - - callee_context.r0 = 0x94e030ca79edd119ULL; - callee_context.r1 = 0x937b4d7e95ce52d9ULL; - callee_context.r2 = 0x5fe0027416b8b62aULL; // caller's r1 - // callee_context.r3 is not valid in callee. - // callee_context.r4 is not valid in callee. - callee_context.sp = stack_top; - callee_context.pc = 0x25b21b224311d280ULL; - int callee_validity = R0_VALID | R1_VALID | R2_VALID | SP_VALID | PC_VALID; - - memset(&caller_context, 0, sizeof(caller_context)); - - int caller_validity; - EXPECT_TRUE(walker.FindCallerRegisters(memory, call_frame_info, - callee_context, callee_validity, - &caller_context, &caller_validity)); - EXPECT_EQ(R0_VALID | R1_VALID | SP_VALID | PC_VALID, caller_validity); - EXPECT_EQ(0xdc1975eba8602302ULL, caller_context.r0); - EXPECT_EQ(0x5fe0027416b8b62aULL, caller_context.r1); - EXPECT_EQ(stack_top + 24, caller_context.sp); - EXPECT_EQ(0xba5ad6d9acce28deULL, caller_context.pc); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h deleted file mode 100644 index 4c0ad41f9..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map-inl.h +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// contained_range_map-inl.h: Hierarchically-organized range map implementation. -// -// See contained_range_map.h for documentation. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_CONTAINED_RANGE_MAP_INL_H__ -#define PROCESSOR_CONTAINED_RANGE_MAP_INL_H__ - -#include "processor/contained_range_map.h" - -#include <assert.h> - -#include "processor/logging.h" - - -namespace google_breakpad { - - -template<typename AddressType, typename EntryType> -ContainedRangeMap<AddressType, EntryType>::~ContainedRangeMap() { - // Clear frees the children pointed to by the map, and frees the map itself. - Clear(); -} - - -template<typename AddressType, typename EntryType> -bool ContainedRangeMap<AddressType, EntryType>::StoreRange( - const AddressType &base, const AddressType &size, const EntryType &entry) { - AddressType high = base + size - 1; - - // Check for undersize or overflow. - if (size <= 0 || high < base) { - //TODO(nealsid) We are commenting this out in order to prevent - // excessive logging. We plan to move to better logging as this - // failure happens quite often and is expected(see comment in - // basic_source_line_resolver.cc:671). - // BPLOG(INFO) << "StoreRange failed, " << HexString(base) << "+" - // << HexString(size) << ", " << HexString(high); - return false; - } - - if (!map_) - map_ = new AddressToRangeMap(); - - MapIterator iterator_base = map_->lower_bound(base); - MapIterator iterator_high = map_->lower_bound(high); - MapIterator iterator_end = map_->end(); - - if (iterator_base == iterator_high && iterator_base != iterator_end && - base >= iterator_base->second->base_) { - // The new range is entirely within an existing child range. - - // If the new range's geometry is exactly equal to an existing child - // range's, it violates the containment rules, and an attempt to store - // it must fail. iterator_base->first contains the key, which was the - // containing child's high address. - if (iterator_base->second->base_ == base && iterator_base->first == high) { - // TODO(nealsid): See the TODO above on why this is commented out. -// BPLOG(INFO) << "StoreRange failed, identical range is already " -// "present: " << HexString(base) << "+" << HexString(size); - return false; - } - - // Pass the new range on to the child to attempt to store. - return iterator_base->second->StoreRange(base, size, entry); - } - - // iterator_high might refer to an irrelevant range: one whose base address - // is higher than the new range's high address. Set contains_high to true - // only if iterator_high refers to a range that is at least partially - // within the new range. - bool contains_high = iterator_high != iterator_end && - high >= iterator_high->second->base_; - - // If the new range encompasses any existing child ranges, it must do so - // fully. Partial containment isn't allowed. - if ((iterator_base != iterator_end && base > iterator_base->second->base_) || - (contains_high && high < iterator_high->first)) { - // TODO(mmentovai): Some symbol files will trip this check frequently - // on STACK lines. Too many messages will be produced. These are more - // suitable for a DEBUG channel than an INFO channel. - // BPLOG(INFO) << "StoreRange failed, new range partially contains " - // "existing range: " << HexString(base) << "+" << - // HexString(size); - return false; - } - - // When copying and erasing contained ranges, the "end" iterator needs to - // point one past the last item of the range to copy. If contains_high is - // false, the iterator's already in the right place; the increment is safe - // because contains_high can't be true if iterator_high == iterator_end. - if (contains_high) - ++iterator_high; - - // Optimization: if the iterators are equal, no child ranges would be - // moved. Create the new child range with a NULL map to conserve space - // in leaf nodes, of which there will be many. - AddressToRangeMap *child_map = NULL; - - if (iterator_base != iterator_high) { - // The children of this range that are contained by the new range must - // be transferred over to the new range. Create the new child range map - // and copy the pointers to range maps it should contain into it. - child_map = new AddressToRangeMap(iterator_base, iterator_high); - - // Remove the copied child pointers from this range's map of children. - map_->erase(iterator_base, iterator_high); - } - - // Store the new range in the map by its high address. Any children that - // the new child range contains were formerly children of this range but - // are now this range's grandchildren. Ownership of these is transferred - // to the new child range. - map_->insert(MapValue(high, - new ContainedRangeMap(base, entry, child_map))); - return true; -} - - -template<typename AddressType, typename EntryType> -bool ContainedRangeMap<AddressType, EntryType>::RetrieveRange( - const AddressType &address, EntryType *entry) const { - BPLOG_IF(ERROR, !entry) << "ContainedRangeMap::RetrieveRange requires " - "|entry|"; - assert(entry); - - // If nothing was ever stored, then there's nothing to retrieve. - if (!map_) - return false; - - // Get an iterator to the child range whose high address is equal to or - // greater than the supplied address. If the supplied address is higher - // than all of the high addresses in the range, then this range does not - // contain a child at address, so return false. If the supplied address - // is lower than the base address of the child range, then it is not within - // the child range, so return false. - MapConstIterator iterator = map_->lower_bound(address); - if (iterator == map_->end() || address < iterator->second->base_) - return false; - - // The child in iterator->second contains the specified address. Find out - // if it has a more-specific descendant that also contains it. If it does, - // it will set |entry| appropriately. If not, set |entry| to the child. - if (!iterator->second->RetrieveRange(address, entry)) - *entry = iterator->second->entry_; - - return true; -} - - -template<typename AddressType, typename EntryType> -void ContainedRangeMap<AddressType, EntryType>::Clear() { - if (map_) { - MapConstIterator end = map_->end(); - for (MapConstIterator child = map_->begin(); child != end; ++child) - delete child->second; - - delete map_; - map_ = NULL; - } -} - - -} // namespace google_breakpad - - -#endif // PROCESSOR_CONTAINED_RANGE_MAP_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map.h b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map.h deleted file mode 100644 index 1015ae8cf..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map.h +++ /dev/null @@ -1,150 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// contained_range_map.h: Hierarchically-organized range maps. -// -// A contained range map is similar to a standard range map, except it allows -// objects to be organized hierarchically. A contained range map allows -// objects to contain other objects. It is not sensitive to the order that -// objects are added to the map: larger, more general, containing objects -// may be added either before or after smaller, more specific, contained -// ones. -// -// Contained range maps guarantee that each object may only contain smaller -// objects than itself, and that a parent object may only contain child -// objects located entirely within the parent's address space. Attempts -// to introduce objects (via StoreRange) that violate these rules will fail. -// Retrieval (via RetrieveRange) always returns the most specific (smallest) -// object that contains the address being queried. Note that while it is -// not possible to insert two objects into a map that have exactly the same -// geometry (base address and size), it is possible to completely mask a -// larger object by inserting smaller objects that entirely fill the larger -// object's address space. -// -// Internally, contained range maps are implemented as a tree. Each tree -// node except for the root node describes an object in the map. Each node -// maintains its list of children in a map similar to a standard range map, -// keyed by the highest address that each child occupies. Each node's -// children occupy address ranges entirely within the node. The root node -// is the only node directly accessible to the user, and represents the -// entire address space. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_CONTAINED_RANGE_MAP_H__ -#define PROCESSOR_CONTAINED_RANGE_MAP_H__ - - -#include <map> - - -namespace google_breakpad { - -// Forward declarations (for later friend declarations of specialized template). -template<class, class> class ContainedRangeMapSerializer; - -template<typename AddressType, typename EntryType> -class ContainedRangeMap { - public: - // The default constructor creates a ContainedRangeMap with no geometry - // and no entry, and as such is only suitable for the root node of a - // ContainedRangeMap tree. - ContainedRangeMap() : base_(), entry_(), map_(NULL) {} - - ~ContainedRangeMap(); - - // Inserts a range into the map. If the new range is encompassed by - // an existing child range, the new range is passed into the child range's - // StoreRange method. If the new range encompasses any existing child - // ranges, those child ranges are moved to the new range, becoming - // grandchildren of this ContainedRangeMap. Returns false for a - // parameter error, or if the ContainedRangeMap hierarchy guarantees - // would be violated. - bool StoreRange(const AddressType &base, - const AddressType &size, - const EntryType &entry); - - // Retrieves the most specific (smallest) descendant range encompassing - // the specified address. This method will only return entries held by - // child ranges, and not the entry contained by |this|. This is necessary - // to support a sparsely-populated root range. If no descendant range - // encompasses the address, returns false. - bool RetrieveRange(const AddressType &address, EntryType *entry) const; - - // Removes all children. Note that Clear only removes descendants, - // leaving the node on which it is called intact. Because the only - // meaningful things contained by a root node are descendants, this - // is sufficient to restore an entire ContainedRangeMap to its initial - // empty state when called on the root node. - void Clear(); - - private: - friend class ContainedRangeMapSerializer<AddressType, EntryType>; - friend class ModuleComparer; - - // AddressToRangeMap stores pointers. This makes reparenting simpler in - // StoreRange, because it doesn't need to copy entire objects. - typedef std::map<AddressType, ContainedRangeMap *> AddressToRangeMap; - typedef typename AddressToRangeMap::const_iterator MapConstIterator; - typedef typename AddressToRangeMap::iterator MapIterator; - typedef typename AddressToRangeMap::value_type MapValue; - - // Creates a new ContainedRangeMap with the specified base address, entry, - // and initial child map, which may be NULL. This is only used internally - // by ContainedRangeMap when it creates a new child. - ContainedRangeMap(const AddressType &base, const EntryType &entry, - AddressToRangeMap *map) - : base_(base), entry_(entry), map_(map) {} - - // The base address of this range. The high address does not need to - // be stored, because it is used as the key to an object in its parent's - // map, and all ContainedRangeMaps except for the root range are contained - // within maps. The root range does not actually contain an entry, so its - // base_ field is meaningless, and the fact that it has no parent and thus - // no key is unimportant. For this reason, the base_ field should only be - // is accessed on child ContainedRangeMap objects, and never on |this|. - const AddressType base_; - - // The entry corresponding to this range. The root range does not - // actually contain an entry, so its entry_ field is meaningless. For - // this reason, the entry_ field should only be accessed on child - // ContainedRangeMap objects, and never on |this|. - const EntryType entry_; - - // The map containing child ranges, keyed by each child range's high - // address. This is a pointer to avoid allocating map structures for - // leaf nodes, where they are not needed. - AddressToRangeMap *map_; -}; - - -} // namespace google_breakpad - - -#endif // PROCESSOR_CONTAINED_RANGE_MAP_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map_unittest.cc deleted file mode 100644 index e5910da0d..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/contained_range_map_unittest.cc +++ /dev/null @@ -1,263 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// contained_range_map_unittest.cc: Unit tests for ContainedRangeMap -// -// Author: Mark Mentovai - -#include <stdio.h> - -#include "processor/contained_range_map-inl.h" - -#include "processor/logging.h" - - -#define ASSERT_TRUE(condition) \ - if (!(condition)) { \ - fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \ - return false; \ - } - -#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition)) - - -namespace { - - -using google_breakpad::ContainedRangeMap; - - -static bool RunTests() { - ContainedRangeMap<unsigned int, int> crm; - - // First, do the StoreRange tests. This validates the containment - // rules. - ASSERT_TRUE (crm.StoreRange(10, 10, 1)); - ASSERT_FALSE(crm.StoreRange(10, 10, 2)); // exactly equal to 1 - ASSERT_FALSE(crm.StoreRange(11, 10, 3)); // begins inside 1 and extends up - ASSERT_FALSE(crm.StoreRange( 9, 10, 4)); // begins below 1 and ends inside - ASSERT_TRUE (crm.StoreRange(11, 9, 5)); // contained by existing - ASSERT_TRUE (crm.StoreRange(12, 7, 6)); - ASSERT_TRUE (crm.StoreRange( 9, 12, 7)); // contains existing - ASSERT_TRUE (crm.StoreRange( 9, 13, 8)); - ASSERT_TRUE (crm.StoreRange( 8, 14, 9)); - ASSERT_TRUE (crm.StoreRange(30, 3, 10)); - ASSERT_TRUE (crm.StoreRange(33, 3, 11)); - ASSERT_TRUE (crm.StoreRange(30, 6, 12)); // storable but totally masked - ASSERT_TRUE (crm.StoreRange(40, 8, 13)); // will be totally masked - ASSERT_TRUE (crm.StoreRange(40, 4, 14)); - ASSERT_TRUE (crm.StoreRange(44, 4, 15)); - ASSERT_FALSE(crm.StoreRange(32, 10, 16)); // begins in #10, ends in #14 - ASSERT_FALSE(crm.StoreRange(50, 0, 17)); // zero length - ASSERT_TRUE (crm.StoreRange(50, 10, 18)); - ASSERT_TRUE (crm.StoreRange(50, 1, 19)); - ASSERT_TRUE (crm.StoreRange(59, 1, 20)); - ASSERT_TRUE (crm.StoreRange(60, 1, 21)); - ASSERT_TRUE (crm.StoreRange(69, 1, 22)); - ASSERT_TRUE (crm.StoreRange(60, 10, 23)); - ASSERT_TRUE (crm.StoreRange(68, 1, 24)); - ASSERT_TRUE (crm.StoreRange(61, 1, 25)); - ASSERT_TRUE (crm.StoreRange(61, 8, 26)); - ASSERT_FALSE(crm.StoreRange(59, 9, 27)); - ASSERT_FALSE(crm.StoreRange(59, 10, 28)); - ASSERT_FALSE(crm.StoreRange(59, 11, 29)); - ASSERT_TRUE (crm.StoreRange(70, 10, 30)); - ASSERT_TRUE (crm.StoreRange(74, 2, 31)); - ASSERT_TRUE (crm.StoreRange(77, 2, 32)); - ASSERT_FALSE(crm.StoreRange(72, 6, 33)); - ASSERT_TRUE (crm.StoreRange(80, 3, 34)); - ASSERT_TRUE (crm.StoreRange(81, 1, 35)); - ASSERT_TRUE (crm.StoreRange(82, 1, 36)); - ASSERT_TRUE (crm.StoreRange(83, 3, 37)); - ASSERT_TRUE (crm.StoreRange(84, 1, 38)); - ASSERT_TRUE (crm.StoreRange(83, 1, 39)); - ASSERT_TRUE (crm.StoreRange(86, 5, 40)); - ASSERT_TRUE (crm.StoreRange(88, 1, 41)); - ASSERT_TRUE (crm.StoreRange(90, 1, 42)); - ASSERT_TRUE (crm.StoreRange(86, 1, 43)); - ASSERT_TRUE (crm.StoreRange(87, 1, 44)); - ASSERT_TRUE (crm.StoreRange(89, 1, 45)); - ASSERT_TRUE (crm.StoreRange(87, 4, 46)); - ASSERT_TRUE (crm.StoreRange(87, 3, 47)); - ASSERT_FALSE(crm.StoreRange(86, 2, 48)); - - // Each element in test_data contains the expected result when calling - // RetrieveRange on an address. - const int test_data[] = { - 0, // 0 - 0, // 1 - 0, // 2 - 0, // 3 - 0, // 4 - 0, // 5 - 0, // 6 - 0, // 7 - 9, // 8 - 7, // 9 - 1, // 10 - 5, // 11 - 6, // 12 - 6, // 13 - 6, // 14 - 6, // 15 - 6, // 16 - 6, // 17 - 6, // 18 - 5, // 19 - 7, // 20 - 8, // 21 - 0, // 22 - 0, // 23 - 0, // 24 - 0, // 25 - 0, // 26 - 0, // 27 - 0, // 28 - 0, // 29 - 10, // 30 - 10, // 31 - 10, // 32 - 11, // 33 - 11, // 34 - 11, // 35 - 0, // 36 - 0, // 37 - 0, // 38 - 0, // 39 - 14, // 40 - 14, // 41 - 14, // 42 - 14, // 43 - 15, // 44 - 15, // 45 - 15, // 46 - 15, // 47 - 0, // 48 - 0, // 49 - 19, // 50 - 18, // 51 - 18, // 52 - 18, // 53 - 18, // 54 - 18, // 55 - 18, // 56 - 18, // 57 - 18, // 58 - 20, // 59 - 21, // 60 - 25, // 61 - 26, // 62 - 26, // 63 - 26, // 64 - 26, // 65 - 26, // 66 - 26, // 67 - 24, // 68 - 22, // 69 - 30, // 70 - 30, // 71 - 30, // 72 - 30, // 73 - 31, // 74 - 31, // 75 - 30, // 76 - 32, // 77 - 32, // 78 - 30, // 79 - 34, // 80 - 35, // 81 - 36, // 82 - 39, // 83 - 38, // 84 - 37, // 85 - 43, // 86 - 44, // 87 - 41, // 88 - 45, // 89 - 42, // 90 - 0, // 91 - 0, // 92 - 0, // 93 - 0, // 94 - 0, // 95 - 0, // 96 - 0, // 97 - 0, // 98 - 0 // 99 - }; - unsigned int test_high = sizeof(test_data) / sizeof(int); - - // Now, do the RetrieveRange tests. This further validates that the - // objects were stored properly and that retrieval returns the correct - // object. - // If GENERATE_TEST_DATA is defined, instead of the retrieval tests, a - // new test_data array will be printed. Exercise caution when doing this. - // Be sure to verify the results manually! -#ifdef GENERATE_TEST_DATA - printf(" const int test_data[] = {\n"); -#endif // GENERATE_TEST_DATA - - for (unsigned int address = 0; address < test_high; ++address) { - int value; - if (!crm.RetrieveRange(address, &value)) - value = 0; - -#ifndef GENERATE_TEST_DATA - // Don't use ASSERT inside the loop because it won't show the failed - // |address|, and the line number will always be the same. That makes - // it difficult to figure out which test failed. - if (value != test_data[address]) { - fprintf(stderr, "FAIL: retrieve %d expected %d observed %d @ %s:%d\n", - address, test_data[address], value, __FILE__, __LINE__); - return false; - } -#else // !GENERATE_TEST_DATA - printf(" %d%c%s // %d\n", value, - address == test_high - 1 ? ' ' : ',', - value < 10 ? " " : "", - address); -#endif // !GENERATE_TEST_DATA - } - -#ifdef GENERATE_TEST_DATA - printf(" };\n"); -#endif // GENERATE_TEST_DATA - - return true; -} - - -} // namespace - - -int main(int argc, char **argv) { - BPLOG_INIT(&argc, &argv); - - return RunTests() ? 0 : 1; -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc deleted file mode 100644 index 559022404..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.cc +++ /dev/null @@ -1,240 +0,0 @@ -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// disassembler_x86.cc: simple x86 disassembler. -// -// Provides single step disassembly of x86 bytecode and flags instructions -// that utilize known bad register values. -// -// Author: Cris Neckar - -#include "processor/disassembler_x86.h" - -#include <string.h> - -namespace google_breakpad { - -DisassemblerX86::DisassemblerX86(const uint8_t *bytecode, - uint32_t size, - uint32_t virtual_address) : - bytecode_(bytecode), - size_(size), - virtual_address_(virtual_address), - current_byte_offset_(0), - current_inst_offset_(0), - instr_valid_(false), - register_valid_(false), - pushed_bad_value_(false), - end_of_block_(false), - flags_(0) { - libdis::x86_init(libdis::opt_none, NULL, NULL); -} - -DisassemblerX86::~DisassemblerX86() { - if (instr_valid_) - libdis::x86_oplist_free(¤t_instr_); - - libdis::x86_cleanup(); -} - -uint32_t DisassemblerX86::NextInstruction() { - if (instr_valid_) - libdis::x86_oplist_free(¤t_instr_); - - if (current_byte_offset_ >= size_) { - instr_valid_ = false; - return 0; - } - uint32_t instr_size = 0; - instr_size = libdis::x86_disasm((unsigned char *)bytecode_, size_, - virtual_address_, current_byte_offset_, - ¤t_instr_); - if (instr_size == 0) { - instr_valid_ = false; - return 0; - } - - current_byte_offset_ += instr_size; - current_inst_offset_++; - instr_valid_ = libdis::x86_insn_is_valid(¤t_instr_); - if (!instr_valid_) - return 0; - - if (current_instr_.type == libdis::insn_return) - end_of_block_ = true; - libdis::x86_op_t *src = libdis::x86_get_src_operand(¤t_instr_); - libdis::x86_op_t *dest = libdis::x86_get_dest_operand(¤t_instr_); - - if (register_valid_) { - switch (current_instr_.group) { - // Flag branches based off of bad registers and calls that occur - // after pushing bad values. - case libdis::insn_controlflow: - switch (current_instr_.type) { - case libdis::insn_jmp: - case libdis::insn_jcc: - case libdis::insn_call: - case libdis::insn_callcc: - if (dest) { - switch (dest->type) { - case libdis::op_expression: - if (dest->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_BRANCH_TARGET; - break; - case libdis::op_register: - if (dest->data.reg.id == bad_register_.id) - flags_ |= DISX86_BAD_BRANCH_TARGET; - break; - default: - if (pushed_bad_value_ && - (current_instr_.type == libdis::insn_call || - current_instr_.type == libdis::insn_callcc)) - flags_ |= DISX86_BAD_ARGUMENT_PASSED; - break; - } - } - break; - default: - break; - } - break; - - // Flag block data operations that use bad registers for src or dest. - case libdis::insn_string: - if (dest && dest->type == libdis::op_expression && - dest->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_BLOCK_WRITE; - if (src && src->type == libdis::op_expression && - src->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_BLOCK_READ; - break; - - // Flag comparisons based on bad data. - case libdis::insn_comparison: - if ((dest && dest->type == libdis::op_expression && - dest->data.expression.base.id == bad_register_.id) || - (src && src->type == libdis::op_expression && - src->data.expression.base.id == bad_register_.id) || - (dest && dest->type == libdis::op_register && - dest->data.reg.id == bad_register_.id) || - (src && src->type == libdis::op_register && - src->data.reg.id == bad_register_.id)) - flags_ |= DISX86_BAD_COMPARISON; - break; - - // Flag any other instruction which derefs a bad register for - // src or dest. - default: - if (dest && dest->type == libdis::op_expression && - dest->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_WRITE; - if (src && src->type == libdis::op_expression && - src->data.expression.base.id == bad_register_.id) - flags_ |= DISX86_BAD_READ; - break; - } - } - - // When a register is marked as tainted check if it is pushed. - // TODO(cdn): may also want to check for MOVs into EBP offsets. - if (register_valid_ && dest && current_instr_.type == libdis::insn_push) { - switch (dest->type) { - case libdis::op_expression: - if (dest->data.expression.base.id == bad_register_.id || - dest->data.expression.index.id == bad_register_.id) - pushed_bad_value_ = true; - break; - case libdis::op_register: - if (dest->data.reg.id == bad_register_.id) - pushed_bad_value_ = true; - break; - default: - break; - } - } - - // Check if a tainted register value is clobbered. - // For conditional MOVs and XCHGs assume that - // there is a hit. - if (register_valid_) { - switch (current_instr_.type) { - case libdis::insn_xor: - if (src && src->type == libdis::op_register && - dest && dest->type == libdis::op_register && - src->data.reg.id == bad_register_.id && - src->data.reg.id == dest->data.reg.id) - register_valid_ = false; - break; - case libdis::insn_pop: - case libdis::insn_mov: - case libdis::insn_movcc: - if (dest && dest->type == libdis::op_register && - dest->data.reg.id == bad_register_.id) - register_valid_ = false; - break; - case libdis::insn_popregs: - register_valid_ = false; - break; - case libdis::insn_xchg: - case libdis::insn_xchgcc: - if (dest && dest->type == libdis::op_register && - src && src->type == libdis::op_register) { - if (dest->data.reg.id == bad_register_.id) - memcpy(&bad_register_, &src->data.reg, sizeof(libdis::x86_reg_t)); - else if (src->data.reg.id == bad_register_.id) - memcpy(&bad_register_, &dest->data.reg, sizeof(libdis::x86_reg_t)); - } - break; - default: - break; - } - } - - return instr_size; -} - -bool DisassemblerX86::setBadRead() { - if (!instr_valid_) - return false; - - libdis::x86_op_t *operand = libdis::x86_get_src_operand(¤t_instr_); - if (!operand || operand->type != libdis::op_expression) - return false; - - memcpy(&bad_register_, &operand->data.expression.base, - sizeof(libdis::x86_reg_t)); - register_valid_ = true; - return true; -} - -bool DisassemblerX86::setBadWrite() { - if (!instr_valid_) - return false; - - libdis::x86_op_t *operand = libdis::x86_get_dest_operand(¤t_instr_); - if (!operand || operand->type != libdis::op_expression) - return false; - - memcpy(&bad_register_, &operand->data.expression.base, - sizeof(libdis::x86_reg_t)); - register_valid_ = true; - return true; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.h b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.h deleted file mode 100644 index 710694107..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86.h +++ /dev/null @@ -1,127 +0,0 @@ -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// disassembler_x86.h: Basic x86 bytecode disassembler -// -// Provides a simple disassembler which wraps libdisasm. This allows simple -// tests to be run against bytecode to test for various properties. -// -// Author: Cris Neckar - -#ifndef GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ -#define GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ - -#include <stddef.h> -#include <sys/types.h> - -#include "google_breakpad/common/breakpad_types.h" - -namespace libdis { -#include "third_party/libdisasm/libdis.h" -} - -namespace google_breakpad { - -enum { - DISX86_NONE = 0x0, - DISX86_BAD_BRANCH_TARGET = 0x1, - DISX86_BAD_ARGUMENT_PASSED = 0x2, - DISX86_BAD_WRITE = 0x4, - DISX86_BAD_BLOCK_WRITE = 0x8, - DISX86_BAD_READ = 0x10, - DISX86_BAD_BLOCK_READ = 0x20, - DISX86_BAD_COMPARISON = 0x40 -}; - -class DisassemblerX86 { - public: - // TODO(cdn): Modify this class to take a MemoryRegion instead of just - // a raw buffer. This will make it easier to use this on arbitrary - // minidumps without first copying out the code segment. - DisassemblerX86(const uint8_t *bytecode, uint32_t, uint32_t); - ~DisassemblerX86(); - - // This walks to the next instruction in the memory region and - // sets flags based on the type of instruction and previous state - // including any registers marked as bad through setBadRead() - // or setBadWrite(). This method can be called in a loop to - // disassemble until the end of a region. - uint32_t NextInstruction(); - - // Indicates whether the current disassembled instruction was valid. - bool currentInstructionValid() { return instr_valid_; } - - // Returns the current instruction as defined in libdis.h, - // or NULL if the current instruction is not valid. - const libdis::x86_insn_t* currentInstruction() { - return instr_valid_ ? ¤t_instr_ : NULL; - } - - // Returns the type of the current instruction as defined in libdis.h. - libdis::x86_insn_group currentInstructionGroup() { - return current_instr_.group; - } - - // Indicates whether a return instruction has been encountered. - bool endOfBlock() { return end_of_block_; } - - // The flags set so far for the disassembly. - uint16_t flags() { return flags_; } - - // This sets an indicator that the register used to determine - // src or dest for the current instruction is tainted. These can - // be used after examining the current instruction to indicate, - // for example that a bad read or write occurred and the pointer - // stored in the register is currently invalid. - bool setBadRead(); - bool setBadWrite(); - - protected: - const uint8_t *bytecode_; - uint32_t size_; - uint32_t virtual_address_; - uint32_t current_byte_offset_; - uint32_t current_inst_offset_; - - bool instr_valid_; - libdis::x86_insn_t current_instr_; - - // TODO(cdn): Maybe also track an expression's index register. - // ex: mov eax, [ebx + ecx]; ebx is base, ecx is index. - bool register_valid_; - libdis::x86_reg_t bad_register_; - - bool pushed_bad_value_; - bool end_of_block_; - - uint16_t flags_; -}; - -} // namespace google_breakpad - -#endif // GOOGLE_BREAKPAD_PROCESSOR_DISASSEMBLER_X86_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86_unittest.cc deleted file mode 100644 index 352905f20..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/disassembler_x86_unittest.cc +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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 <unistd.h> - -#include "breakpad_googletest_includes.h" -#include "processor/disassembler_x86.h" -#include "third_party/libdisasm/libdis.h" - -namespace { - -using google_breakpad::DisassemblerX86; - -unsigned char just_return[] = "\xc3"; // retn - -unsigned char invalid_instruction[] = "\x00"; // invalid - -unsigned char read_eax_jmp_eax[] = - "\x8b\x18" // mov ebx, [eax]; - "\x33\xc9" // xor ebx, ebx; - "\xff\x20" // jmp eax; - "\xc3"; // retn; - -unsigned char write_eax_arg_to_call[] = - "\x89\xa8\x00\x02\x00\x00" // mov [eax+200], ebp; - "\xc1\xeb\x02" // shr ebx, 2; - "\x50" // push eax; - "\xe8\xd1\x24\x77\x88" // call something; - "\xc3"; // retn; - -unsigned char read_edi_stosb[] = - "\x8b\x07" // mov eax, [edi]; - "\x8b\xc8" // mov ecx, eax; - "\xf3\xaa" // rep stosb; - "\xc3"; // retn; - -unsigned char read_clobber_write[] = - "\x03\x18" // add ebx, [eax]; - "\x8b\xc1" // mov eax, ecx; - "\x89\x10" // mov [eax], edx; - "\xc3"; // retn; - -unsigned char read_xchg_write[] = - "\x03\x18" // add ebx, [eax]; - "\x91" // xchg eax, ecx; - "\x89\x18" // mov [eax], ebx; - "\x89\x11" // mov [ecx], edx; - "\xc3"; // retn; - -unsigned char read_cmp[] = - "\x03\x18" // add ebx, [eax]; - "\x83\xf8\x00" // cmp eax, 0; - "\x74\x04" // je +4; - "\xc3"; // retn; - -TEST(DisassemblerX86Test, SimpleReturnInstruction) { - DisassemblerX86 dis(just_return, sizeof(just_return)-1, 0); - EXPECT_EQ(1U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_TRUE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup()); - const libdis::x86_insn_t* instruction = dis.currentInstruction(); - EXPECT_EQ(libdis::insn_controlflow, instruction->group); - EXPECT_EQ(libdis::insn_return, instruction->type); - EXPECT_EQ(0U, dis.NextInstruction()); - EXPECT_FALSE(dis.currentInstructionValid()); - EXPECT_EQ(NULL, dis.currentInstruction()); -} - -TEST(DisassemblerX86Test, SimpleInvalidInstruction) { - DisassemblerX86 dis(invalid_instruction, sizeof(invalid_instruction)-1, 0); - EXPECT_EQ(0U, dis.NextInstruction()); - EXPECT_FALSE(dis.currentInstructionValid()); -} - -TEST(DisassemblerX86Test, BadReadLeadsToBranch) { - DisassemblerX86 dis(read_eax_jmp_eax, sizeof(read_eax_jmp_eax)-1, 0); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); - EXPECT_TRUE(dis.setBadRead()); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_logic, dis.currentInstructionGroup()); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(google_breakpad::DISX86_BAD_BRANCH_TARGET, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup()); -} - -TEST(DisassemblerX86Test, BadWriteLeadsToPushedArg) { - DisassemblerX86 dis(write_eax_arg_to_call, - sizeof(write_eax_arg_to_call)-1, 0); - EXPECT_EQ(6U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); - EXPECT_TRUE(dis.setBadWrite()); - EXPECT_EQ(3U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup()); - EXPECT_EQ(1U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(5U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(google_breakpad::DISX86_BAD_ARGUMENT_PASSED, dis.flags()); - EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup()); - EXPECT_FALSE(dis.endOfBlock()); -} - - -TEST(DisassemblerX86Test, BadReadLeadsToBlockWrite) { - DisassemblerX86 dis(read_edi_stosb, sizeof(read_edi_stosb)-1, 0); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); - EXPECT_TRUE(dis.setBadRead()); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(google_breakpad::DISX86_BAD_BLOCK_WRITE, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_string, dis.currentInstructionGroup()); -} - -TEST(DisassemblerX86Test, BadReadClobberThenWrite) { - DisassemblerX86 dis(read_clobber_write, sizeof(read_clobber_write)-1, 0); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup()); - EXPECT_TRUE(dis.setBadRead()); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); -} - -TEST(DisassemblerX86Test, BadReadXCHGThenWrite) { - DisassemblerX86 dis(read_xchg_write, sizeof(read_xchg_write)-1, 0); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup()); - EXPECT_TRUE(dis.setBadRead()); - EXPECT_EQ(1U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(google_breakpad::DISX86_BAD_WRITE, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_move, dis.currentInstructionGroup()); -} - -TEST(DisassemblerX86Test, BadReadThenCMP) { - DisassemblerX86 dis(read_cmp, sizeof(read_cmp)-1, 0); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(0U, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_arithmetic, dis.currentInstructionGroup()); - EXPECT_TRUE(dis.setBadRead()); - EXPECT_EQ(3U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(google_breakpad::DISX86_BAD_COMPARISON, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_comparison, dis.currentInstructionGroup()); - EXPECT_EQ(2U, dis.NextInstruction()); - EXPECT_TRUE(dis.currentInstructionValid()); - EXPECT_EQ(google_breakpad::DISX86_BAD_COMPARISON, dis.flags()); - EXPECT_FALSE(dis.endOfBlock()); - EXPECT_EQ(libdis::insn_controlflow, dis.currentInstructionGroup()); -} -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/dump_context.cc b/toolkit/crashreporter/google-breakpad/src/processor/dump_context.cc deleted file mode 100644 index 762d4fe21..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/dump_context.cc +++ /dev/null @@ -1,659 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// dump_context.cc: A (mini/micro)dump context. -// -// See dump_context.h for documentation. - -#include "google_breakpad/processor/dump_context.h" - -#include <assert.h> - -#ifdef _WIN32 -#include <io.h> -#else // _WIN32 -#include <unistd.h> -#endif // _WIN32 - -#include "common/stdio_wrapper.h" -#include "processor/logging.h" - -namespace google_breakpad { - -DumpContext::DumpContext() : context_(), - context_flags_(0) { } - -DumpContext::~DumpContext() { - FreeContext(); -} - -uint32_t DumpContext::GetContextCPU() const { - if (!valid_) { - // Don't log a message, GetContextCPU can be legitimately called with - // valid_ false by FreeContext, which is called by Read. - return 0; - } - - return context_flags_ & MD_CONTEXT_CPU_MASK; -} - -uint32_t DumpContext::GetContextFlags() const { - return context_flags_; -} - -const MDRawContextX86* DumpContext::GetContextX86() const { - if (GetContextCPU() != MD_CONTEXT_X86) { - BPLOG(ERROR) << "DumpContext cannot get x86 context"; - return NULL; - } - - return context_.x86; -} - -const MDRawContextPPC* DumpContext::GetContextPPC() const { - if (GetContextCPU() != MD_CONTEXT_PPC) { - BPLOG(ERROR) << "DumpContext cannot get ppc context"; - return NULL; - } - - return context_.ppc; -} - -const MDRawContextPPC64* DumpContext::GetContextPPC64() const { - if (GetContextCPU() != MD_CONTEXT_PPC64) { - BPLOG(ERROR) << "DumpContext cannot get ppc64 context"; - return NULL; - } - - return context_.ppc64; -} - -const MDRawContextAMD64* DumpContext::GetContextAMD64() const { - if (GetContextCPU() != MD_CONTEXT_AMD64) { - BPLOG(ERROR) << "DumpContext cannot get amd64 context"; - return NULL; - } - - return context_.amd64; -} - -const MDRawContextSPARC* DumpContext::GetContextSPARC() const { - if (GetContextCPU() != MD_CONTEXT_SPARC) { - BPLOG(ERROR) << "DumpContext cannot get sparc context"; - return NULL; - } - - return context_.ctx_sparc; -} - -const MDRawContextARM* DumpContext::GetContextARM() const { - if (GetContextCPU() != MD_CONTEXT_ARM) { - BPLOG(ERROR) << "DumpContext cannot get arm context"; - return NULL; - } - - return context_.arm; -} - -const MDRawContextARM64* DumpContext::GetContextARM64() const { - if (GetContextCPU() != MD_CONTEXT_ARM64) { - BPLOG(ERROR) << "DumpContext cannot get arm64 context"; - return NULL; - } - - return context_.arm64; -} - -const MDRawContextMIPS* DumpContext::GetContextMIPS() const { - if ((GetContextCPU() != MD_CONTEXT_MIPS) && - (GetContextCPU() != MD_CONTEXT_MIPS64)) { - BPLOG(ERROR) << "DumpContext cannot get MIPS context"; - return NULL; - } - - return context_.ctx_mips; -} - -bool DumpContext::GetInstructionPointer(uint64_t* ip) const { - BPLOG_IF(ERROR, !ip) << "DumpContext::GetInstructionPointer requires |ip|"; - assert(ip); - *ip = 0; - - if (!valid_) { - BPLOG(ERROR) << "Invalid DumpContext for GetInstructionPointer"; - return false; - } - - switch (GetContextCPU()) { - case MD_CONTEXT_AMD64: - *ip = GetContextAMD64()->rip; - break; - case MD_CONTEXT_ARM: - *ip = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_PC]; - break; - case MD_CONTEXT_ARM64: - *ip = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_PC]; - break; - case MD_CONTEXT_PPC: - *ip = GetContextPPC()->srr0; - break; - case MD_CONTEXT_PPC64: - *ip = GetContextPPC64()->srr0; - break; - case MD_CONTEXT_SPARC: - *ip = GetContextSPARC()->pc; - break; - case MD_CONTEXT_X86: - *ip = GetContextX86()->eip; - break; - case MD_CONTEXT_MIPS: - case MD_CONTEXT_MIPS64: - *ip = GetContextMIPS()->epc; - break; - default: - // This should never happen. - BPLOG(ERROR) << "Unknown CPU architecture in GetInstructionPointer"; - return false; - } - return true; -} - -bool DumpContext::GetStackPointer(uint64_t* sp) const { - BPLOG_IF(ERROR, !sp) << "DumpContext::GetStackPointer requires |sp|"; - assert(sp); - *sp = 0; - - if (!valid_) { - BPLOG(ERROR) << "Invalid DumpContext for GetStackPointer"; - return false; - } - - switch (GetContextCPU()) { - case MD_CONTEXT_AMD64: - *sp = GetContextAMD64()->rsp; - break; - case MD_CONTEXT_ARM: - *sp = GetContextARM()->iregs[MD_CONTEXT_ARM_REG_SP]; - break; - case MD_CONTEXT_ARM64: - *sp = GetContextARM64()->iregs[MD_CONTEXT_ARM64_REG_SP]; - break; - case MD_CONTEXT_PPC: - *sp = GetContextPPC()->gpr[MD_CONTEXT_PPC_REG_SP]; - break; - case MD_CONTEXT_PPC64: - *sp = GetContextPPC64()->gpr[MD_CONTEXT_PPC64_REG_SP]; - break; - case MD_CONTEXT_SPARC: - *sp = GetContextSPARC()->g_r[MD_CONTEXT_SPARC_REG_SP]; - break; - case MD_CONTEXT_X86: - *sp = GetContextX86()->esp; - break; - case MD_CONTEXT_MIPS: - case MD_CONTEXT_MIPS64: - *sp = GetContextMIPS()->iregs[MD_CONTEXT_MIPS_REG_SP]; - break; - default: - // This should never happen. - BPLOG(ERROR) << "Unknown CPU architecture in GetStackPointer"; - return false; - } - return true; -} - -void DumpContext::SetContextFlags(uint32_t context_flags) { - context_flags_ = context_flags; -} - -void DumpContext::SetContextX86(MDRawContextX86* x86) { - context_.x86 = x86; -} - -void DumpContext::SetContextPPC(MDRawContextPPC* ppc) { - context_.ppc = ppc; -} - -void DumpContext::SetContextPPC64(MDRawContextPPC64* ppc64) { - context_.ppc64 = ppc64; -} - -void DumpContext::SetContextAMD64(MDRawContextAMD64* amd64) { - context_.amd64 = amd64; -} - -void DumpContext::SetContextSPARC(MDRawContextSPARC* ctx_sparc) { - context_.ctx_sparc = ctx_sparc; -} - -void DumpContext::SetContextARM(MDRawContextARM* arm) { - context_.arm = arm; -} - -void DumpContext::SetContextARM64(MDRawContextARM64* arm64) { - context_.arm64 = arm64; -} - -void DumpContext::SetContextMIPS(MDRawContextMIPS* ctx_mips) { - context_.ctx_mips = ctx_mips; -} - -void DumpContext::FreeContext() { - switch (GetContextCPU()) { - case MD_CONTEXT_X86: - delete context_.x86; - break; - - case MD_CONTEXT_PPC: - delete context_.ppc; - break; - - case MD_CONTEXT_PPC64: - delete context_.ppc64; - break; - - case MD_CONTEXT_AMD64: - delete context_.amd64; - break; - - case MD_CONTEXT_SPARC: - delete context_.ctx_sparc; - break; - - case MD_CONTEXT_ARM: - delete context_.arm; - break; - - case MD_CONTEXT_ARM64: - delete context_.arm64; - break; - - case MD_CONTEXT_MIPS: - case MD_CONTEXT_MIPS64: - delete context_.ctx_mips; - break; - - default: - // There is no context record (valid_ is false) or there's a - // context record for an unknown CPU (shouldn't happen, only known - // records are stored by Read). - break; - } - - context_flags_ = 0; - context_.base = NULL; -} - -void DumpContext::Print() { - if (!valid_) { - BPLOG(ERROR) << "DumpContext cannot print invalid data"; - return; - } - - switch (GetContextCPU()) { - case MD_CONTEXT_X86: { - const MDRawContextX86* context_x86 = GetContextX86(); - printf("MDRawContextX86\n"); - printf(" context_flags = 0x%x\n", - context_x86->context_flags); - printf(" dr0 = 0x%x\n", context_x86->dr0); - printf(" dr1 = 0x%x\n", context_x86->dr1); - printf(" dr2 = 0x%x\n", context_x86->dr2); - printf(" dr3 = 0x%x\n", context_x86->dr3); - printf(" dr6 = 0x%x\n", context_x86->dr6); - printf(" dr7 = 0x%x\n", context_x86->dr7); - printf(" float_save.control_word = 0x%x\n", - context_x86->float_save.control_word); - printf(" float_save.status_word = 0x%x\n", - context_x86->float_save.status_word); - printf(" float_save.tag_word = 0x%x\n", - context_x86->float_save.tag_word); - printf(" float_save.error_offset = 0x%x\n", - context_x86->float_save.error_offset); - printf(" float_save.error_selector = 0x%x\n", - context_x86->float_save.error_selector); - printf(" float_save.data_offset = 0x%x\n", - context_x86->float_save.data_offset); - printf(" float_save.data_selector = 0x%x\n", - context_x86->float_save.data_selector); - printf(" float_save.register_area[%2d] = 0x", - MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE); - for (unsigned int register_index = 0; - register_index < MD_FLOATINGSAVEAREA_X86_REGISTERAREA_SIZE; - ++register_index) { - printf("%02x", context_x86->float_save.register_area[register_index]); - } - printf("\n"); - printf(" float_save.cr0_npx_state = 0x%x\n", - context_x86->float_save.cr0_npx_state); - printf(" gs = 0x%x\n", context_x86->gs); - printf(" fs = 0x%x\n", context_x86->fs); - printf(" es = 0x%x\n", context_x86->es); - printf(" ds = 0x%x\n", context_x86->ds); - printf(" edi = 0x%x\n", context_x86->edi); - printf(" esi = 0x%x\n", context_x86->esi); - printf(" ebx = 0x%x\n", context_x86->ebx); - printf(" edx = 0x%x\n", context_x86->edx); - printf(" ecx = 0x%x\n", context_x86->ecx); - printf(" eax = 0x%x\n", context_x86->eax); - printf(" ebp = 0x%x\n", context_x86->ebp); - printf(" eip = 0x%x\n", context_x86->eip); - printf(" cs = 0x%x\n", context_x86->cs); - printf(" eflags = 0x%x\n", context_x86->eflags); - printf(" esp = 0x%x\n", context_x86->esp); - printf(" ss = 0x%x\n", context_x86->ss); - printf(" extended_registers[%3d] = 0x", - MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE); - for (unsigned int register_index = 0; - register_index < MD_CONTEXT_X86_EXTENDED_REGISTERS_SIZE; - ++register_index) { - printf("%02x", context_x86->extended_registers[register_index]); - } - printf("\n\n"); - - break; - } - - case MD_CONTEXT_PPC: { - const MDRawContextPPC* context_ppc = GetContextPPC(); - printf("MDRawContextPPC\n"); - printf(" context_flags = 0x%x\n", - context_ppc->context_flags); - printf(" srr0 = 0x%x\n", context_ppc->srr0); - printf(" srr1 = 0x%x\n", context_ppc->srr1); - for (unsigned int gpr_index = 0; - gpr_index < MD_CONTEXT_PPC_GPR_COUNT; - ++gpr_index) { - printf(" gpr[%2d] = 0x%x\n", - gpr_index, context_ppc->gpr[gpr_index]); - } - printf(" cr = 0x%x\n", context_ppc->cr); - printf(" xer = 0x%x\n", context_ppc->xer); - printf(" lr = 0x%x\n", context_ppc->lr); - printf(" ctr = 0x%x\n", context_ppc->ctr); - printf(" mq = 0x%x\n", context_ppc->mq); - printf(" vrsave = 0x%x\n", context_ppc->vrsave); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; - ++fpr_index) { - printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_ppc->float_save.fpregs[fpr_index]); - } - printf(" float_save.fpscr = 0x%x\n", - context_ppc->float_save.fpscr); - // TODO(mmentovai): print the 128-bit quantities in - // context_ppc->vector_save. This isn't done yet because printf - // doesn't support 128-bit quantities, and printing them using - // PRIx64 as two 64-bit quantities requires knowledge of the CPU's - // byte ordering. - printf(" vector_save.save_vrvalid = 0x%x\n", - context_ppc->vector_save.save_vrvalid); - printf("\n"); - - break; - } - - case MD_CONTEXT_PPC64: { - const MDRawContextPPC64* context_ppc64 = GetContextPPC64(); - printf("MDRawContextPPC64\n"); - printf(" context_flags = 0x%" PRIx64 "\n", - context_ppc64->context_flags); - printf(" srr0 = 0x%" PRIx64 "\n", - context_ppc64->srr0); - printf(" srr1 = 0x%" PRIx64 "\n", - context_ppc64->srr1); - for (unsigned int gpr_index = 0; - gpr_index < MD_CONTEXT_PPC64_GPR_COUNT; - ++gpr_index) { - printf(" gpr[%2d] = 0x%" PRIx64 "\n", - gpr_index, context_ppc64->gpr[gpr_index]); - } - printf(" cr = 0x%" PRIx64 "\n", context_ppc64->cr); - printf(" xer = 0x%" PRIx64 "\n", - context_ppc64->xer); - printf(" lr = 0x%" PRIx64 "\n", context_ppc64->lr); - printf(" ctr = 0x%" PRIx64 "\n", - context_ppc64->ctr); - printf(" vrsave = 0x%" PRIx64 "\n", - context_ppc64->vrsave); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; - ++fpr_index) { - printf(" float_save.fpregs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_ppc64->float_save.fpregs[fpr_index]); - } - printf(" float_save.fpscr = 0x%x\n", - context_ppc64->float_save.fpscr); - // TODO(mmentovai): print the 128-bit quantities in - // context_ppc64->vector_save. This isn't done yet because printf - // doesn't support 128-bit quantities, and printing them using - // PRIx64 as two 64-bit quantities requires knowledge of the CPU's - // byte ordering. - printf(" vector_save.save_vrvalid = 0x%x\n", - context_ppc64->vector_save.save_vrvalid); - printf("\n"); - - break; - } - - case MD_CONTEXT_AMD64: { - const MDRawContextAMD64* context_amd64 = GetContextAMD64(); - printf("MDRawContextAMD64\n"); - printf(" p1_home = 0x%" PRIx64 "\n", - context_amd64->p1_home); - printf(" p2_home = 0x%" PRIx64 "\n", - context_amd64->p2_home); - printf(" p3_home = 0x%" PRIx64 "\n", - context_amd64->p3_home); - printf(" p4_home = 0x%" PRIx64 "\n", - context_amd64->p4_home); - printf(" p5_home = 0x%" PRIx64 "\n", - context_amd64->p5_home); - printf(" p6_home = 0x%" PRIx64 "\n", - context_amd64->p6_home); - printf(" context_flags = 0x%x\n", - context_amd64->context_flags); - printf(" mx_csr = 0x%x\n", - context_amd64->mx_csr); - printf(" cs = 0x%x\n", context_amd64->cs); - printf(" ds = 0x%x\n", context_amd64->ds); - printf(" es = 0x%x\n", context_amd64->es); - printf(" fs = 0x%x\n", context_amd64->fs); - printf(" gs = 0x%x\n", context_amd64->gs); - printf(" ss = 0x%x\n", context_amd64->ss); - printf(" eflags = 0x%x\n", context_amd64->eflags); - printf(" dr0 = 0x%" PRIx64 "\n", context_amd64->dr0); - printf(" dr1 = 0x%" PRIx64 "\n", context_amd64->dr1); - printf(" dr2 = 0x%" PRIx64 "\n", context_amd64->dr2); - printf(" dr3 = 0x%" PRIx64 "\n", context_amd64->dr3); - printf(" dr6 = 0x%" PRIx64 "\n", context_amd64->dr6); - printf(" dr7 = 0x%" PRIx64 "\n", context_amd64->dr7); - printf(" rax = 0x%" PRIx64 "\n", context_amd64->rax); - printf(" rcx = 0x%" PRIx64 "\n", context_amd64->rcx); - printf(" rdx = 0x%" PRIx64 "\n", context_amd64->rdx); - printf(" rbx = 0x%" PRIx64 "\n", context_amd64->rbx); - printf(" rsp = 0x%" PRIx64 "\n", context_amd64->rsp); - printf(" rbp = 0x%" PRIx64 "\n", context_amd64->rbp); - printf(" rsi = 0x%" PRIx64 "\n", context_amd64->rsi); - printf(" rdi = 0x%" PRIx64 "\n", context_amd64->rdi); - printf(" r8 = 0x%" PRIx64 "\n", context_amd64->r8); - printf(" r9 = 0x%" PRIx64 "\n", context_amd64->r9); - printf(" r10 = 0x%" PRIx64 "\n", context_amd64->r10); - printf(" r11 = 0x%" PRIx64 "\n", context_amd64->r11); - printf(" r12 = 0x%" PRIx64 "\n", context_amd64->r12); - printf(" r13 = 0x%" PRIx64 "\n", context_amd64->r13); - printf(" r14 = 0x%" PRIx64 "\n", context_amd64->r14); - printf(" r15 = 0x%" PRIx64 "\n", context_amd64->r15); - printf(" rip = 0x%" PRIx64 "\n", context_amd64->rip); - // TODO: print xmm, vector, debug registers - printf("\n"); - break; - } - - case MD_CONTEXT_SPARC: { - const MDRawContextSPARC* context_sparc = GetContextSPARC(); - printf("MDRawContextSPARC\n"); - printf(" context_flags = 0x%x\n", - context_sparc->context_flags); - for (unsigned int g_r_index = 0; - g_r_index < MD_CONTEXT_SPARC_GPR_COUNT; - ++g_r_index) { - printf(" g_r[%2d] = 0x%" PRIx64 "\n", - g_r_index, context_sparc->g_r[g_r_index]); - } - printf(" ccr = 0x%" PRIx64 "\n", context_sparc->ccr); - printf(" pc = 0x%" PRIx64 "\n", context_sparc->pc); - printf(" npc = 0x%" PRIx64 "\n", context_sparc->npc); - printf(" y = 0x%" PRIx64 "\n", context_sparc->y); - printf(" asi = 0x%" PRIx64 "\n", context_sparc->asi); - printf(" fprs = 0x%" PRIx64 "\n", context_sparc->fprs); - - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; - ++fpr_index) { - printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_sparc->float_save.regs[fpr_index]); - } - printf(" float_save.filler = 0x%" PRIx64 "\n", - context_sparc->float_save.filler); - printf(" float_save.fsr = 0x%" PRIx64 "\n", - context_sparc->float_save.fsr); - break; - } - - case MD_CONTEXT_ARM: { - const MDRawContextARM* context_arm = GetContextARM(); - printf("MDRawContextARM\n"); - printf(" context_flags = 0x%x\n", - context_arm->context_flags); - for (unsigned int ireg_index = 0; - ireg_index < MD_CONTEXT_ARM_GPR_COUNT; - ++ireg_index) { - printf(" iregs[%2d] = 0x%x\n", - ireg_index, context_arm->iregs[ireg_index]); - } - printf(" cpsr = 0x%x\n", context_arm->cpsr); - printf(" float_save.fpscr = 0x%" PRIx64 "\n", - context_arm->float_save.fpscr); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; - ++fpr_index) { - printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_arm->float_save.regs[fpr_index]); - } - for (unsigned int fpe_index = 0; - fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; - ++fpe_index) { - printf(" float_save.extra[%2d] = 0x%" PRIx32 "\n", - fpe_index, context_arm->float_save.extra[fpe_index]); - } - - break; - } - - case MD_CONTEXT_ARM64: { - const MDRawContextARM64* context_arm64 = GetContextARM64(); - printf("MDRawContextARM64\n"); - printf(" context_flags = 0x%" PRIx64 "\n", - context_arm64->context_flags); - for (unsigned int ireg_index = 0; - ireg_index < MD_CONTEXT_ARM64_GPR_COUNT; - ++ireg_index) { - printf(" iregs[%2d] = 0x%" PRIx64 "\n", - ireg_index, context_arm64->iregs[ireg_index]); - } - printf(" cpsr = 0x%x\n", context_arm64->cpsr); - printf(" float_save.fpsr = 0x%x\n", context_arm64->float_save.fpsr); - printf(" float_save.fpcr = 0x%x\n", context_arm64->float_save.fpcr); - - for (unsigned int freg_index = 0; - freg_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; - ++freg_index) { - uint128_struct fp_value = context_arm64->float_save.regs[freg_index]; - printf(" float_save.regs[%2d] = 0x%" PRIx64 "%" PRIx64 "\n", - freg_index, fp_value.high, fp_value.low); - } - break; - } - - case MD_CONTEXT_MIPS: - case MD_CONTEXT_MIPS64: { - const MDRawContextMIPS* context_mips = GetContextMIPS(); - printf("MDRawContextMIPS\n"); - printf(" context_flags = 0x%x\n", - context_mips->context_flags); - for (int ireg_index = 0; - ireg_index < MD_CONTEXT_MIPS_GPR_COUNT; - ++ireg_index) { - printf(" iregs[%2d] = 0x%" PRIx64 "\n", - ireg_index, context_mips->iregs[ireg_index]); - } - printf(" mdhi = 0x%" PRIx64 "\n", - context_mips->mdhi); - printf(" mdlo = 0x%" PRIx64 "\n", - context_mips->mdhi); - for (int dsp_index = 0; - dsp_index < MD_CONTEXT_MIPS_DSP_COUNT; - ++dsp_index) { - printf(" hi[%1d] = 0x%" PRIx32 "\n", - dsp_index, context_mips->hi[dsp_index]); - printf(" lo[%1d] = 0x%" PRIx32 "\n", - dsp_index, context_mips->lo[dsp_index]); - } - printf(" dsp_control = 0x%" PRIx32 "\n", - context_mips->dsp_control); - printf(" epc = 0x%" PRIx64 "\n", - context_mips->epc); - printf(" badvaddr = 0x%" PRIx64 "\n", - context_mips->badvaddr); - printf(" status = 0x%" PRIx32 "\n", - context_mips->status); - printf(" cause = 0x%" PRIx32 "\n", - context_mips->cause); - - for (int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; - ++fpr_index) { - printf(" float_save.regs[%2d] = 0x%" PRIx64 "\n", - fpr_index, context_mips->float_save.regs[fpr_index]); - } - printf(" float_save.fpcsr = 0x%" PRIx32 "\n", - context_mips->float_save.fpcsr); - printf(" float_save.fir = 0x%" PRIx32 "\n", - context_mips->float_save.fir); - break; - } - - default: { - break; - } - } -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/dump_object.cc b/toolkit/crashreporter/google-breakpad/src/processor/dump_object.cc deleted file mode 100644 index 2c82b200b..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/dump_object.cc +++ /dev/null @@ -1,39 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// dump_object.cc: A base class for all mini/micro dump object. - -#include "google_breakpad/processor/dump_object.h" - -namespace google_breakpad { - -DumpObject::DumpObject() : valid_(false) { -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability.cc b/toolkit/crashreporter/google-breakpad/src/processor/exploitability.cc deleted file mode 100644 index 6ee1e9622..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/exploitability.cc +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// exploitability_engine.cc: Generic exploitability engine. -// -// See exploitable_engine.h for documentation. -// -// Author: Cris Neckar - - -#include <cassert> - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/exploitability.h" -#include "google_breakpad/processor/minidump.h" -#include "google_breakpad/processor/process_state.h" -#include "processor/exploitability_linux.h" -#include "processor/exploitability_win.h" -#include "processor/logging.h" - -namespace google_breakpad { - -Exploitability::Exploitability(Minidump *dump, - ProcessState *process_state) - : dump_(dump), - process_state_(process_state) {} - -ExploitabilityRating Exploitability::CheckExploitability() { - return CheckPlatformExploitability(); -} - -Exploitability *Exploitability::ExploitabilityForPlatform( - Minidump *dump, - ProcessState *process_state) { - return ExploitabilityForPlatform(dump, process_state, false); -} - -Exploitability *Exploitability::ExploitabilityForPlatform( - Minidump *dump, - ProcessState *process_state, - bool enable_objdump) { - Exploitability *platform_exploitability = NULL; - MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo(); - if (!minidump_system_info) - return NULL; - - const MDRawSystemInfo *raw_system_info = - minidump_system_info->system_info(); - if (!raw_system_info) - return NULL; - - switch (raw_system_info->platform_id) { - case MD_OS_WIN32_NT: - case MD_OS_WIN32_WINDOWS: { - platform_exploitability = new ExploitabilityWin(dump, process_state); - break; - } - case MD_OS_LINUX: { - platform_exploitability = new ExploitabilityLinux(dump, - process_state, - enable_objdump); - break; - } - case MD_OS_MAC_OS_X: - case MD_OS_IOS: - case MD_OS_UNIX: - case MD_OS_SOLARIS: - case MD_OS_ANDROID: - case MD_OS_PS3: - default: { - platform_exploitability = NULL; - break; - } - } - - BPLOG_IF(ERROR, !platform_exploitability) << - "No Exploitability module for platform: " << - process_state->system_info()->os; - return platform_exploitability; -} - -bool Exploitability::AddressIsAscii(uint64_t address) { - for (int i = 0; i < 8; i++) { - uint8_t byte = (address >> (8*i)) & 0xff; - if ((byte >= ' ' && byte <= '~') || byte == 0) - continue; - return false; - } - return true; -} - -} // namespace google_breakpad - diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.cc b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.cc deleted file mode 100644 index 63056c438..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.cc +++ /dev/null @@ -1,625 +0,0 @@ -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// exploitability_linux.cc: Linux specific exploitability engine. -// -// Provides a guess at the exploitability of the crash for the Linux -// platform given a minidump and process_state. -// -// Author: Matthew Riley - -#include "processor/exploitability_linux.h" - -#ifndef _WIN32 -#include <regex.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> - -#include <sstream> -#include <iterator> -#endif // _WIN32 - -#include "google_breakpad/common/minidump_exception_linux.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/stack_frame.h" -#include "processor/logging.h" - -namespace { - -// Prefixes for memory mapping names. -constexpr char kHeapPrefix[] = "[heap"; -constexpr char kStackPrefix[] = "[stack"; - -// This function in libc is called if the program was compiled with -// -fstack-protector and a function's stack canary changes. -constexpr char kStackCheckFailureFunction[] = "__stack_chk_fail"; - -// This function in libc is called if the program was compiled with -// -D_FORTIFY_SOURCE=2, a function like strcpy() is called, and the runtime -// can determine that the call would overflow the target buffer. -constexpr char kBoundsCheckFailureFunction[] = "__chk_fail"; - -#ifndef _WIN32 -const unsigned int MAX_INSTRUCTION_LEN = 15; -const unsigned int MAX_OBJDUMP_BUFFER_LEN = 4096; -#endif // _WIN32 - -} // namespace - -namespace google_breakpad { - -ExploitabilityLinux::ExploitabilityLinux(Minidump *dump, - ProcessState *process_state) - : Exploitability(dump, process_state), - enable_objdump_(false) { } - -ExploitabilityLinux::ExploitabilityLinux(Minidump *dump, - ProcessState *process_state, - bool enable_objdump) - : Exploitability(dump, process_state), - enable_objdump_(enable_objdump) { } - - -ExploitabilityRating ExploitabilityLinux::CheckPlatformExploitability() { - // Check the crashing thread for functions suggesting a buffer overflow or - // stack smash. - if (process_state_->requesting_thread() != -1) { - CallStack* crashing_thread = - process_state_->threads()->at(process_state_->requesting_thread()); - const vector<StackFrame*>& crashing_thread_frames = - *crashing_thread->frames(); - for (size_t i = 0; i < crashing_thread_frames.size(); ++i) { - if (crashing_thread_frames[i]->function_name == - kStackCheckFailureFunction) { - return EXPLOITABILITY_HIGH; - } - - if (crashing_thread_frames[i]->function_name == - kBoundsCheckFailureFunction) { - return EXPLOITABILITY_HIGH; - } - } - } - - // Getting exception data. (It should exist for all minidumps.) - MinidumpException *exception = dump_->GetException(); - if (exception == NULL) { - BPLOG(INFO) << "No exception record."; - return EXPLOITABILITY_ERR_PROCESSING; - } - const MDRawExceptionStream *raw_exception_stream = exception->exception(); - if (raw_exception_stream == NULL) { - BPLOG(INFO) << "No raw exception stream."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Checking for benign exceptions that caused the crash. - if (this->BenignCrashTrigger(raw_exception_stream)) { - return EXPLOITABILITY_NONE; - } - - // Check if the instruction pointer is in a valid instruction region - // by finding if it maps to an executable part of memory. - uint64_t instruction_ptr = 0; - uint64_t stack_ptr = 0; - - const MinidumpContext *context = exception->GetContext(); - if (context == NULL) { - BPLOG(INFO) << "No exception context."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Getting the instruction pointer. - if (!context->GetInstructionPointer(&instruction_ptr)) { - BPLOG(INFO) << "Failed to retrieve instruction pointer."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Getting the stack pointer. - if (!context->GetStackPointer(&stack_ptr)) { - BPLOG(INFO) << "Failed to retrieve stack pointer."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Checking for the instruction pointer in a valid instruction region, - // a misplaced stack pointer, and an executable stack or heap. - if (!this->InstructionPointerInCode(instruction_ptr) || - this->StackPointerOffStack(stack_ptr) || - this->ExecutableStackOrHeap()) { - return EXPLOITABILITY_HIGH; - } - - // Check for write to read only memory or invalid memory, shelling out - // to objdump is enabled. - if (enable_objdump_ && this->EndedOnIllegalWrite(instruction_ptr)) { - return EXPLOITABILITY_HIGH; - } - - // There was no strong evidence suggesting exploitability, but the minidump - // does not appear totally benign either. - return EXPLOITABILITY_INTERESTING; -} - -bool ExploitabilityLinux::EndedOnIllegalWrite(uint64_t instruction_ptr) { -#ifdef _WIN32 - BPLOG(INFO) << "MinGW does not support fork and exec. Terminating method."; -#else - // Get memory region containing instruction pointer. - MinidumpMemoryList *memory_list = dump_->GetMemoryList(); - MinidumpMemoryRegion *memory_region = - memory_list ? - memory_list->GetMemoryRegionForAddress(instruction_ptr) : NULL; - if (!memory_region) { - BPLOG(INFO) << "No memory region around instruction pointer."; - return false; - } - - // Get exception data to find architecture. - string architecture = ""; - MinidumpException *exception = dump_->GetException(); - // This should never evaluate to true, since this should not be reachable - // without checking for exception data earlier. - if (!exception) { - BPLOG(INFO) << "No exception data."; - return false; - } - const MDRawExceptionStream *raw_exception_stream = exception->exception(); - const MinidumpContext *context = exception->GetContext(); - // This should not evaluate to true, for the same reason mentioned above. - if (!raw_exception_stream || !context) { - BPLOG(INFO) << "No exception or architecture data."; - return false; - } - // Check architecture and set architecture variable to corresponding flag - // in objdump. - switch (context->GetContextCPU()) { - case MD_CONTEXT_X86: - architecture = "i386"; - break; - case MD_CONTEXT_AMD64: - architecture = "i386:x86-64"; - break; - default: - // Unsupported architecture. Note that ARM architectures are not - // supported because objdump does not support ARM. - return false; - break; - } - - // Get memory region around instruction pointer and the number of bytes - // before and after the instruction pointer in the memory region. - const uint8_t *raw_memory = memory_region->GetMemory(); - const uint64_t base = memory_region->GetBase(); - if (base > instruction_ptr) { - BPLOG(ERROR) << "Memory region base value exceeds instruction pointer."; - return false; - } - const uint64_t offset = instruction_ptr - base; - if (memory_region->GetSize() < MAX_INSTRUCTION_LEN + offset) { - BPLOG(INFO) << "Not enough bytes left to guarantee complete instruction."; - return false; - } - - // Convert bytes into objdump output. - char objdump_output_buffer[MAX_OBJDUMP_BUFFER_LEN] = {0}; - DisassembleBytes(architecture, - raw_memory + offset, - MAX_OBJDUMP_BUFFER_LEN, - objdump_output_buffer); - - string line; - if (!GetObjdumpInstructionLine(objdump_output_buffer, &line)) { - return false; - } - - // Convert objdump instruction line into the operation and operands. - string instruction = ""; - string dest = ""; - string src = ""; - TokenizeObjdumpInstruction(line, &instruction, &dest, &src); - - // Check if the operation is a write to memory. First, the instruction - // must one that can write to memory. Second, the write destination - // must be a spot in memory rather than a register. Since there are no - // symbols from objdump, the destination will be enclosed by brackets. - if (dest.size() > 2 && dest.at(0) == '[' && dest.at(dest.size() - 1) == ']' && - (!instruction.compare("mov") || !instruction.compare("inc") || - !instruction.compare("dec") || !instruction.compare("and") || - !instruction.compare("or") || !instruction.compare("xor") || - !instruction.compare("not") || !instruction.compare("neg") || - !instruction.compare("add") || !instruction.compare("sub") || - !instruction.compare("shl") || !instruction.compare("shr"))) { - // Strip away enclosing brackets from the destination address. - dest = dest.substr(1, dest.size() - 2); - uint64_t write_address = 0; - CalculateAddress(dest, *context, &write_address); - - // If the program crashed as a result of a write, the destination of - // the write must have been an address that did not permit writing. - // However, if the address is under 4k, due to program protections, - // the crash does not suggest exploitability for writes with such a - // low target address. - return write_address > 4096; - } -#endif // _WIN32 - return false; -} - -#ifndef _WIN32 -bool ExploitabilityLinux::CalculateAddress(const string &address_expression, - const DumpContext &context, - uint64_t *write_address) { - // The destination should be the format reg+a or reg-a, where reg - // is a register and a is a hexadecimal constant. Although more complex - // expressions can make valid instructions, objdump's disassembly outputs - // it in this simpler format. - // TODO(liuandrew): Handle more complex formats, should they arise. - - if (!write_address) { - BPLOG(ERROR) << "Null parameter."; - return false; - } - - // Clone parameter into a non-const string. - string expression = address_expression; - - // Parse out the constant that is added to the address (if it exists). - size_t delim = expression.find('+'); - bool positive_add_constant = true; - // Check if constant is subtracted instead of added. - if (delim == string::npos) { - positive_add_constant = false; - delim = expression.find('-'); - } - uint32_t add_constant = 0; - // Save constant and remove it from the expression. - if (delim != string::npos) { - if (!sscanf(expression.substr(delim + 1).c_str(), "%x", &add_constant)) { - BPLOG(ERROR) << "Failed to scan constant."; - return false; - } - expression = expression.substr(0, delim); - } - - // Set the the write address to the corresponding register. - // TODO(liuandrew): Add support for partial registers, such as - // the rax/eax/ax/ah/al chain. - switch (context.GetContextCPU()) { - case MD_CONTEXT_X86: - if (!expression.compare("eax")) { - *write_address = context.GetContextX86()->eax; - } else if (!expression.compare("ebx")) { - *write_address = context.GetContextX86()->ebx; - } else if (!expression.compare("ecx")) { - *write_address = context.GetContextX86()->ecx; - } else if (!expression.compare("edx")) { - *write_address = context.GetContextX86()->edx; - } else if (!expression.compare("edi")) { - *write_address = context.GetContextX86()->edi; - } else if (!expression.compare("esi")) { - *write_address = context.GetContextX86()->esi; - } else if (!expression.compare("ebp")) { - *write_address = context.GetContextX86()->ebp; - } else if (!expression.compare("esp")) { - *write_address = context.GetContextX86()->esp; - } else if (!expression.compare("eip")) { - *write_address = context.GetContextX86()->eip; - } else { - BPLOG(ERROR) << "Unsupported register"; - return false; - } - break; - case MD_CONTEXT_AMD64: - if (!expression.compare("rax")) { - *write_address = context.GetContextAMD64()->rax; - } else if (!expression.compare("rbx")) { - *write_address = context.GetContextAMD64()->rbx; - } else if (!expression.compare("rcx")) { - *write_address = context.GetContextAMD64()->rcx; - } else if (!expression.compare("rdx")) { - *write_address = context.GetContextAMD64()->rdx; - } else if (!expression.compare("rdi")) { - *write_address = context.GetContextAMD64()->rdi; - } else if (!expression.compare("rsi")) { - *write_address = context.GetContextAMD64()->rsi; - } else if (!expression.compare("rbp")) { - *write_address = context.GetContextAMD64()->rbp; - } else if (!expression.compare("rsp")) { - *write_address = context.GetContextAMD64()->rsp; - } else if (!expression.compare("rip")) { - *write_address = context.GetContextAMD64()->rip; - } else if (!expression.compare("r8")) { - *write_address = context.GetContextAMD64()->r8; - } else if (!expression.compare("r9")) { - *write_address = context.GetContextAMD64()->r9; - } else if (!expression.compare("r10")) { - *write_address = context.GetContextAMD64()->r10; - } else if (!expression.compare("r11")) { - *write_address = context.GetContextAMD64()->r11; - } else if (!expression.compare("r12")) { - *write_address = context.GetContextAMD64()->r12; - } else if (!expression.compare("r13")) { - *write_address = context.GetContextAMD64()->r13; - } else if (!expression.compare("r14")) { - *write_address = context.GetContextAMD64()->r14; - } else if (!expression.compare("r15")) { - *write_address = context.GetContextAMD64()->r15; - } else { - BPLOG(ERROR) << "Unsupported register"; - return false; - } - break; - default: - // This should not occur since the same switch condition - // should have terminated this method. - return false; - break; - } - - // Add or subtract constant from write address (if applicable). - *write_address = - positive_add_constant ? - *write_address + add_constant : *write_address - add_constant; - - return true; -} - -// static -bool ExploitabilityLinux::GetObjdumpInstructionLine( - const char *objdump_output_buffer, - string *instruction_line) { - // Put buffer data into stream to output line-by-line. - std::stringstream objdump_stream; - objdump_stream.str(string(objdump_output_buffer)); - - // Pipe each output line into the string until the string contains the first - // instruction from objdump. All lines before the "<.data>:" section are - // skipped. Loop until the line shows the first instruction or there are no - // lines left. - bool data_section_seen = false; - do { - if (!getline(objdump_stream, *instruction_line)) { - BPLOG(INFO) << "Objdump instructions not found"; - return false; - } - if (instruction_line->find("<.data>:") != string::npos) { - data_section_seen = true; - } - } while (!data_section_seen || instruction_line->find("0:") == string::npos); - // This first instruction contains the above substring. - - return true; -} - -bool ExploitabilityLinux::TokenizeObjdumpInstruction(const string &line, - string *operation, - string *dest, - string *src) { - if (!operation || !dest || !src) { - BPLOG(ERROR) << "Null parameters passed."; - return false; - } - - // Set all pointer values to empty strings. - *operation = ""; - *dest = ""; - *src = ""; - - // Tokenize the objdump line. - vector<string> tokens; - std::istringstream line_stream(line); - copy(std::istream_iterator<string>(line_stream), - std::istream_iterator<string>(), - std::back_inserter(tokens)); - - // Regex for the data in hex form. Each byte is two hex digits. - regex_t regex; - regcomp(®ex, "^[[:xdigit:]]{2}$", REG_EXTENDED | REG_NOSUB); - - // Find and set the location of the operator. The operator appears - // directly after the chain of bytes that define the instruction. The - // operands will be the last token, given that the instruction has operands. - // If not, the operator is the last token. The loop skips the first token - // because the first token is the instruction number (namely "0:"). - string operands = ""; - for (size_t i = 1; i < tokens.size(); i++) { - // Check if current token no longer is in byte format. - if (regexec(®ex, tokens[i].c_str(), 0, NULL, 0)) { - // instruction = tokens[i]; - *operation = tokens[i]; - // If the operator is the last token, there are no operands. - if (i != tokens.size() - 1) { - operands = tokens[tokens.size() - 1]; - } - break; - } - } - regfree(®ex); - - if (operation->empty()) { - BPLOG(ERROR) << "Failed to parse out operation from objdump instruction."; - return false; - } - - // Split operands into source and destination (if applicable). - if (!operands.empty()) { - size_t delim = operands.find(','); - if (delim == string::npos) { - *dest = operands; - } else { - *dest = operands.substr(0, delim); - *src = operands.substr(delim + 1); - } - } - return true; -} - -bool ExploitabilityLinux::DisassembleBytes(const string &architecture, - const uint8_t *raw_bytes, - const unsigned int buffer_len, - char *objdump_output_buffer) { - if (!raw_bytes || !objdump_output_buffer) { - BPLOG(ERROR) << "Bad input parameters."; - return false; - } - - // Write raw bytes around instruction pointer to a temporary file to - // pass as an argument to objdump. - char raw_bytes_tmpfile[] = "/tmp/breakpad_mem_region-raw_bytes-XXXXXX"; - int raw_bytes_fd = mkstemp(raw_bytes_tmpfile); - if (raw_bytes_fd < 0) { - BPLOG(ERROR) << "Failed to create tempfile."; - unlink(raw_bytes_tmpfile); - return false; - } - if (write(raw_bytes_fd, raw_bytes, MAX_INSTRUCTION_LEN) - != MAX_INSTRUCTION_LEN) { - BPLOG(ERROR) << "Writing of raw bytes failed."; - unlink(raw_bytes_tmpfile); - return false; - } - - char cmd[1024] = {0}; - snprintf(cmd, - 1024, - "objdump -D -b binary -M intel -m %s %s", - architecture.c_str(), - raw_bytes_tmpfile); - FILE *objdump_fp = popen(cmd, "r"); - if (!objdump_fp) { - fclose(objdump_fp); - unlink(raw_bytes_tmpfile); - BPLOG(ERROR) << "Failed to call objdump."; - return false; - } - if (fread(objdump_output_buffer, 1, buffer_len, objdump_fp) <= 0) { - fclose(objdump_fp); - unlink(raw_bytes_tmpfile); - BPLOG(ERROR) << "Failed to read objdump output."; - return false; - } - fclose(objdump_fp); - unlink(raw_bytes_tmpfile); - return true; -} -#endif // _WIN32 - -bool ExploitabilityLinux::StackPointerOffStack(uint64_t stack_ptr) { - MinidumpLinuxMapsList *linux_maps_list = dump_->GetLinuxMapsList(); - // Inconclusive if there are no mappings available. - if (!linux_maps_list) { - return false; - } - const MinidumpLinuxMaps *linux_maps = - linux_maps_list->GetLinuxMapsForAddress(stack_ptr); - // Checks if the stack pointer maps to a valid mapping and if the mapping - // is not the stack. If the mapping has no name, it is inconclusive whether - // it is off the stack. - return !linux_maps || (linux_maps->GetPathname().compare("") && - linux_maps->GetPathname().compare( - 0, strlen(kStackPrefix), kStackPrefix)); -} - -bool ExploitabilityLinux::ExecutableStackOrHeap() { - MinidumpLinuxMapsList *linux_maps_list = dump_->GetLinuxMapsList(); - if (linux_maps_list) { - for (size_t i = 0; i < linux_maps_list->get_maps_count(); i++) { - const MinidumpLinuxMaps *linux_maps = - linux_maps_list->GetLinuxMapsAtIndex(i); - // Check for executable stack or heap for each mapping. - if (linux_maps && (!linux_maps->GetPathname().compare( - 0, strlen(kStackPrefix), kStackPrefix) || - !linux_maps->GetPathname().compare( - 0, strlen(kHeapPrefix), kHeapPrefix)) && - linux_maps->IsExecutable()) { - return true; - } - } - } - return false; -} - -bool ExploitabilityLinux::InstructionPointerInCode(uint64_t instruction_ptr) { - // Get Linux memory mapping from /proc/self/maps. Checking whether the - // region the instruction pointer is in has executable permission can tell - // whether it is in a valid code region. If there is no mapping for the - // instruction pointer, it is indicative that the instruction pointer is - // not within a module, which implies that it is outside a valid area. - MinidumpLinuxMapsList *linux_maps_list = dump_->GetLinuxMapsList(); - const MinidumpLinuxMaps *linux_maps = - linux_maps_list ? - linux_maps_list->GetLinuxMapsForAddress(instruction_ptr) : NULL; - return linux_maps ? linux_maps->IsExecutable() : false; -} - -bool ExploitabilityLinux::BenignCrashTrigger(const MDRawExceptionStream - *raw_exception_stream) { - // Check the cause of crash. - // If the exception of the crash is a benign exception, - // it is probably not exploitable. - switch (raw_exception_stream->exception_record.exception_code) { - case MD_EXCEPTION_CODE_LIN_SIGHUP: - case MD_EXCEPTION_CODE_LIN_SIGINT: - case MD_EXCEPTION_CODE_LIN_SIGQUIT: - case MD_EXCEPTION_CODE_LIN_SIGTRAP: - case MD_EXCEPTION_CODE_LIN_SIGABRT: - case MD_EXCEPTION_CODE_LIN_SIGFPE: - case MD_EXCEPTION_CODE_LIN_SIGKILL: - case MD_EXCEPTION_CODE_LIN_SIGUSR1: - case MD_EXCEPTION_CODE_LIN_SIGUSR2: - case MD_EXCEPTION_CODE_LIN_SIGPIPE: - case MD_EXCEPTION_CODE_LIN_SIGALRM: - case MD_EXCEPTION_CODE_LIN_SIGTERM: - case MD_EXCEPTION_CODE_LIN_SIGCHLD: - case MD_EXCEPTION_CODE_LIN_SIGCONT: - case MD_EXCEPTION_CODE_LIN_SIGSTOP: - case MD_EXCEPTION_CODE_LIN_SIGTSTP: - case MD_EXCEPTION_CODE_LIN_SIGTTIN: - case MD_EXCEPTION_CODE_LIN_SIGTTOU: - case MD_EXCEPTION_CODE_LIN_SIGURG: - case MD_EXCEPTION_CODE_LIN_SIGXCPU: - case MD_EXCEPTION_CODE_LIN_SIGXFSZ: - case MD_EXCEPTION_CODE_LIN_SIGVTALRM: - case MD_EXCEPTION_CODE_LIN_SIGPROF: - case MD_EXCEPTION_CODE_LIN_SIGWINCH: - case MD_EXCEPTION_CODE_LIN_SIGIO: - case MD_EXCEPTION_CODE_LIN_SIGPWR: - case MD_EXCEPTION_CODE_LIN_SIGSYS: - case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED: - return true; - break; - default: - return false; - break; - } -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.h b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.h deleted file mode 100644 index e3ff13b6e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_linux.h +++ /dev/null @@ -1,129 +0,0 @@ -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// exploitability_linux.h: Linux specific exploitability engine. -// -// Provides a guess at the exploitability of the crash for the Linux -// platform given a minidump and process_state. -// -// Author: Matthew Riley - -#ifndef GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_LINUX_H_ -#define GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_LINUX_H_ - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/processor/exploitability.h" - -namespace google_breakpad { - -class ExploitabilityLinux : public Exploitability { - public: - ExploitabilityLinux(Minidump *dump, - ProcessState *process_state); - - // Parameters are the minidump to analyze, the object representing process - // state, and whether to enable objdump disassembly. - // Enabling objdump will allow exploitability analysis to call out to - // objdump for diassembly. It is used to check the identity of the - // instruction that caused the program to crash. If there are any - // portability concerns, this should not be enabled. - ExploitabilityLinux(Minidump *dump, - ProcessState *process_state, - bool enable_objdump); - - virtual ExploitabilityRating CheckPlatformExploitability(); - - private: - friend class ExploitabilityLinuxTest; - - // Takes the address of the instruction pointer and returns - // whether the instruction pointer lies in a valid instruction region. - bool InstructionPointerInCode(uint64_t instruction_ptr); - - // Checks the exception that triggered the creation of the - // minidump and reports whether the exception suggests no exploitability. - bool BenignCrashTrigger(const MDRawExceptionStream *raw_exception_stream); - - // This method checks if the crash occurred during a write to read-only or - // invalid memory. It does so by checking if the instruction at the - // instruction pointer is a write instruction, and if the target of the - // instruction is at a spot in memory that prohibits writes. - bool EndedOnIllegalWrite(uint64_t instruction_ptr); - -#ifndef _WIN32 - // Disassembles raw bytes via objdump and pipes the output into the provided - // buffer, given the desired architecture, the file from which objdump will - // read, and the buffer length. The method returns whether the disassembly - // was a success, and the caller owns all pointers. - static bool DisassembleBytes(const string &architecture, - const uint8_t *raw_bytes, - const unsigned int MAX_OBJDUMP_BUFFER_LEN, - char *objdump_output_buffer); - - // Parses the objdump output given in |objdump_output_buffer| and extracts - // the line of the first instruction into |instruction_line|. Returns true - // when the instruction line is successfully extracted. - static bool GetObjdumpInstructionLine( - const char *objdump_output_buffer, - string *instruction_line); - - // Tokenizes out the operation and operands from a line of instruction - // disassembled by objdump. This method modifies the pointers to match the - // tokens of the instruction, and returns if the tokenizing was a success. - // The caller owns all pointers. - static bool TokenizeObjdumpInstruction(const string &line, - string *operation, - string *dest, - string *src); - - // Calculates the effective address of an expression in the form reg+a or - // reg-a, where 'reg' is a register and 'a' is a constant, and writes the - // result in the pointer. The method returns whether the calculation was - // a success. The caller owns the pointer. - static bool CalculateAddress(const string &address_expression, - const DumpContext &context, - uint64_t *write_address); -#endif // _WIN32 - - // Checks if the stack pointer points to a memory mapping that is not - // labelled as the stack. - bool StackPointerOffStack(uint64_t stack_ptr); - - // Checks if the stack or heap are marked executable according - // to the memory mappings. - bool ExecutableStackOrHeap(); - - // Whether this exploitability engine is permitted to shell out to objdump - // to disassemble raw bytes. - bool enable_objdump_; -}; - -} // namespace google_breakpad - -#endif // GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_LINUX_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_unittest.cc deleted file mode 100644 index 528ee5f21..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_unittest.cc +++ /dev/null @@ -1,306 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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 <stdlib.h> -#include <unistd.h> - -#include <string> - -#include "breakpad_googletest_includes.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/minidump_processor.h" -#include "google_breakpad/processor/process_state.h" -#ifndef _WIN32 -#include "processor/exploitability_linux.h" -#endif // _WIN32 -#include "processor/simple_symbol_supplier.h" - -#ifndef _WIN32 -namespace google_breakpad { - -class ExploitabilityLinuxTest : public ExploitabilityLinux { - public: - using ExploitabilityLinux::CalculateAddress; - using ExploitabilityLinux::DisassembleBytes; - using ExploitabilityLinux::GetObjdumpInstructionLine; - using ExploitabilityLinux::TokenizeObjdumpInstruction; -}; - -class ExploitabilityLinuxTestMinidumpContext : public MinidumpContext { - public: - explicit ExploitabilityLinuxTestMinidumpContext( - const MDRawContextAMD64& context) : MinidumpContext(NULL) { - valid_ = true; - SetContextAMD64(new MDRawContextAMD64(context)); - SetContextFlags(MD_CONTEXT_AMD64); - } -}; - -} // namespace google_breakpad -#endif // _WIN32 - -namespace { - -using google_breakpad::BasicSourceLineResolver; -#ifndef _WIN32 -using google_breakpad::ExploitabilityLinuxTest; -using google_breakpad::ExploitabilityLinuxTestMinidumpContext; -#endif // _WIN32 -using google_breakpad::MinidumpProcessor; -using google_breakpad::ProcessState; -using google_breakpad::SimpleSymbolSupplier; - -string TestDataDir() { - return string(getenv("srcdir") ? getenv("srcdir") : ".") + - "/src/processor/testdata"; -} - -// Find the given dump file in <srcdir>/src/processor/testdata, process it, -// and get the exploitability rating. Returns EXPLOITABILITY_ERR_PROCESSING -// if the crash dump can't be processed. -google_breakpad::ExploitabilityRating -ExploitabilityFor(const string& filename) { - SimpleSymbolSupplier supplier(TestDataDir() + "/symbols"); - BasicSourceLineResolver resolver; - MinidumpProcessor processor(&supplier, &resolver, true); - processor.set_enable_objdump(true); - ProcessState state; - - string minidump_file = TestDataDir() + "/" + filename; - - if (processor.Process(minidump_file, &state) != - google_breakpad::PROCESS_OK) { - return google_breakpad::EXPLOITABILITY_ERR_PROCESSING; - } - - return state.exploitability(); -} - -TEST(ExploitabilityTest, TestWindowsEngine) { - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("ascii_read_av.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("ascii_read_av_block_write.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("ascii_read_av_clobber_write.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("ascii_read_av_conditional.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("ascii_read_av_then_jmp.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("ascii_read_av_xchg_write.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("ascii_write_av.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("ascii_write_av_arg_to_call.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE, - ExploitabilityFor("null_read_av.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE, - ExploitabilityFor("null_write_av.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE, - ExploitabilityFor("stack_exhaustion.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("exec_av_on_stack.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_MEDIUM, - ExploitabilityFor("write_av_non_null.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW, - ExploitabilityFor("read_av_non_null.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW, - ExploitabilityFor("read_av_clobber_write.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_LOW, - ExploitabilityFor("read_av_conditional.dmp")); -} - -TEST(ExploitabilityTest, TestLinuxEngine) { - ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING, - ExploitabilityFor("linux_null_read_av.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_overflow.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_stacksmash.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE, - ExploitabilityFor("linux_divide_by_zero.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING, - ExploitabilityFor("linux_null_dereference.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_jmp_to_0.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_outside_module.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_NONE, - ExploitabilityFor("linux_raise_sigabrt.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING, - ExploitabilityFor("linux_inside_module_exe_region1.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING, - ExploitabilityFor("linux_inside_module_exe_region2.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING, - ExploitabilityFor("linux_stack_pointer_in_stack.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING, - ExploitabilityFor("linux_stack_pointer_in_stack_alt_name.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_stack_pointer_in_module.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_executable_stack.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_executable_heap.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_jmp_to_module_not_exe_region.dmp")); -#ifndef _WIN32 - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_write_to_nonwritable_module.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_write_to_nonwritable_region_math.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_write_to_outside_module.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_HIGH, - ExploitabilityFor("linux_write_to_outside_module_via_math.dmp")); - ASSERT_EQ(google_breakpad::EXPLOITABILITY_INTERESTING, - ExploitabilityFor("linux_write_to_under_4k.dmp")); -#endif // _WIN32 -} - -#ifndef _WIN32 -TEST(ExploitabilityLinuxUtilsTest, DisassembleBytesTest) { - ASSERT_FALSE(ExploitabilityLinuxTest::DisassembleBytes("", NULL, 5, NULL)); - uint8_t bytes[6] = {0xc7, 0x0, 0x5, 0x0, 0x0, 0x0}; - char buffer[1024] = {0}; - ASSERT_TRUE(ExploitabilityLinuxTest::DisassembleBytes("i386:x86-64", - bytes, - 1024, - buffer)); - std::stringstream objdump_stream; - objdump_stream.str(string(buffer)); - string line = ""; - while (line.find("<.data>") == string::npos) - getline(objdump_stream, line); - getline(objdump_stream, line); - ASSERT_EQ(line, " 0:\tc7 00 05 00 00 00 \tmov DWORD PTR [rax],0x5"); -} - -TEST(ExploitabilityLinuxUtilsTest, GetObjdumpInstructionLine) { - string disassebly = - "\n" - "/tmp/breakpad_mem_region-raw_bytes-tMmMo0: file format binary\n" - "// Trying to confuse the parser 0:\n" - "\n" - "Disassembly of section .data:\n" - "\n" - "0000000000000000 <.data>:\n" - " 0:\tc7 00 01 00 00 00 \tmov DWORD PTR [rax],0x1\n" - " 6:\t5d \tpop rbp\n" - " 7:\tc3 \tret \n" - " 8:\t55 \tpush rbp\n" - " 9:\t48 89 e5 \tmov rbp,rsp\n" - " c:\t53 \tpush rbx\n" - " d:\t48 \trex.W\n" - " e:\t81 \t.byte 0x81\n"; - string line; - EXPECT_TRUE(ExploitabilityLinuxTest::GetObjdumpInstructionLine( - disassebly.c_str(), &line)); - EXPECT_EQ(" 0:\tc7 00 01 00 00 00 \tmov DWORD PTR [rax],0x1", line); - - // There is no "0:" after "<.data>:". Expected to return false. - disassebly = - "\n" - "/tmp/breakpad_mem_region-raw_bytes-tMmMo0: file format binary\n" - "// Trying to confuse the parser 0:\n" - "\n" - "Disassembly of section .data:\n" - "\n" - " 0:\tc7 00 01 00 00 00 \tmov DWORD PTR [rax],0x1\n" - " 6:\t5d \tpop rbp\n" - " 7:\tc3 \tret \n" - " 8:\t55 \tpush rbp\n" - " 9:\t48 89 e5 \tmov rbp,rsp\n" - " d:\t48 \trex.W\n" - "0000000000000000 <.data>:\n" - " c:\t53 \tpush rbx\n"; - EXPECT_FALSE(ExploitabilityLinuxTest::GetObjdumpInstructionLine( - disassebly.c_str(), &line)); -} - -TEST(ExploitabilityLinuxUtilsTest, TokenizeObjdumpInstructionTest) { - ASSERT_FALSE(ExploitabilityLinuxTest::TokenizeObjdumpInstruction("", - NULL, - NULL, - NULL)); - string line = "0: c7 00 05 00 00 00 mov DWORD PTR [rax],0x5"; - string operation = ""; - string dest = ""; - string src = ""; - ASSERT_TRUE(ExploitabilityLinuxTest::TokenizeObjdumpInstruction(line, - &operation, - &dest, - &src)); - ASSERT_EQ(operation, "mov"); - ASSERT_EQ(dest, "[rax]"); - ASSERT_EQ(src, "0x5"); - line = "0: c3 ret"; - ASSERT_TRUE(ExploitabilityLinuxTest::TokenizeObjdumpInstruction(line, - &operation, - &dest, - &src)); - ASSERT_EQ(operation, "ret"); - ASSERT_EQ(dest, ""); - ASSERT_EQ(src, ""); - line = "0: 5f pop rdi"; - ASSERT_TRUE(ExploitabilityLinuxTest::TokenizeObjdumpInstruction(line, - &operation, - &dest, - &src)); - ASSERT_EQ(operation, "pop"); - ASSERT_EQ(dest, "rdi"); - ASSERT_EQ(src, ""); -} - -TEST(ExploitabilityLinuxUtilsTest, CalculateAddressTest) { - MDRawContextAMD64 raw_context; - raw_context.rdx = 12345; - ExploitabilityLinuxTestMinidumpContext context(raw_context); - ASSERT_EQ(context.GetContextAMD64()->rdx, 12345U); - ASSERT_FALSE(ExploitabilityLinuxTest::CalculateAddress("", context, NULL)); - uint64_t write_address = 0; - ASSERT_TRUE(ExploitabilityLinuxTest::CalculateAddress("rdx-0x4D2", - context, - &write_address)); - ASSERT_EQ(write_address, 11111U); - ASSERT_TRUE(ExploitabilityLinuxTest::CalculateAddress("rdx+0x4D2", - context, - &write_address)); - ASSERT_EQ(write_address, 13579U); - ASSERT_FALSE(ExploitabilityLinuxTest::CalculateAddress("rdx+rax", - context, - &write_address)); - ASSERT_FALSE(ExploitabilityLinuxTest::CalculateAddress("0x3482+0x4D2", - context, - &write_address)); -} -#endif // _WIN32 - -} // namespace diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.cc b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.cc deleted file mode 100644 index a1f8703a6..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.cc +++ /dev/null @@ -1,283 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// exploitability_win.cc: Windows specific exploitability engine. -// -// Provides a guess at the exploitability of the crash for the Windows -// platform given a minidump and process_state. -// -// Author: Cris Neckar - -#include <vector> - -#include "processor/exploitability_win.h" - -#include "common/scoped_ptr.h" -#include "google_breakpad/common/minidump_exception_win32.h" -#include "google_breakpad/processor/minidump.h" -#include "processor/disassembler_x86.h" -#include "processor/logging.h" - -#include "third_party/libdisasm/libdis.h" - -namespace google_breakpad { - -// The cutoff that we use to judge if and address is likely an offset -// from various interesting addresses. -static const uint64_t kProbableNullOffset = 4096; -static const uint64_t kProbableStackOffset = 8192; - -// The various cutoffs for the different ratings. -static const size_t kHighCutoff = 100; -static const size_t kMediumCutoff = 80; -static const size_t kLowCutoff = 50; -static const size_t kInterestingCutoff = 25; - -// Predefined incremental values for conditional weighting. -static const size_t kTinyBump = 5; -static const size_t kSmallBump = 20; -static const size_t kMediumBump = 50; -static const size_t kLargeBump = 70; -static const size_t kHugeBump = 90; - -// The maximum number of bytes to disassemble past the program counter. -static const size_t kDisassembleBytesBeyondPC = 2048; - -ExploitabilityWin::ExploitabilityWin(Minidump *dump, - ProcessState *process_state) - : Exploitability(dump, process_state) { } - -ExploitabilityRating ExploitabilityWin::CheckPlatformExploitability() { - MinidumpException *exception = dump_->GetException(); - if (!exception) { - BPLOG(INFO) << "Minidump does not have exception record."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - const MDRawExceptionStream *raw_exception = exception->exception(); - if (!raw_exception) { - BPLOG(INFO) << "Could not obtain raw exception info."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - const MinidumpContext *context = exception->GetContext(); - if (!context) { - BPLOG(INFO) << "Could not obtain exception context."; - return EXPLOITABILITY_ERR_PROCESSING; - } - - MinidumpMemoryList *memory_list = dump_->GetMemoryList(); - bool memory_available = true; - if (!memory_list) { - BPLOG(INFO) << "Minidump memory segments not available."; - memory_available = false; - } - uint64_t address = process_state_->crash_address(); - uint32_t exception_code = raw_exception->exception_record.exception_code; - - uint32_t exploitability_weight = 0; - - uint64_t stack_ptr = 0; - uint64_t instruction_ptr = 0; - - // Getting the instruction pointer. - if (!context->GetInstructionPointer(&instruction_ptr)) { - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Getting the stack pointer. - if (!context->GetStackPointer(&stack_ptr)) { - return EXPLOITABILITY_ERR_PROCESSING; - } - - // Check if we are executing on the stack. - if (instruction_ptr <= (stack_ptr + kProbableStackOffset) && - instruction_ptr >= (stack_ptr - kProbableStackOffset)) - exploitability_weight += kHugeBump; - - switch (exception_code) { - // This is almost certainly recursion. - case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW: - exploitability_weight += kTinyBump; - break; - - // These exceptions tend to be benign and we can generally ignore them. - case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO: - case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW: - case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO: - case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT: - case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW: - case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW: - case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR: - exploitability_weight += kTinyBump; - break; - - // These exceptions will typically mean that we have jumped where we - // shouldn't. - case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION: - case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION: - case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION: - exploitability_weight += kLargeBump; - break; - - // These represent bugs in exception handlers. - case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION: - case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION: - exploitability_weight += kSmallBump; - break; - - case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION: - case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN: - exploitability_weight += kHugeBump; - break; - - case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION: - exploitability_weight += kLargeBump; - break; - - case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION: - bool near_null = (address <= kProbableNullOffset); - bool bad_read = false; - bool bad_write = false; - if (raw_exception->exception_record.number_parameters >= 1) { - MDAccessViolationTypeWin av_type = - static_cast<MDAccessViolationTypeWin> - (raw_exception->exception_record.exception_information[0]); - switch (av_type) { - case MD_ACCESS_VIOLATION_WIN_READ: - bad_read = true; - if (near_null) - exploitability_weight += kSmallBump; - else - exploitability_weight += kMediumBump; - break; - case MD_ACCESS_VIOLATION_WIN_WRITE: - bad_write = true; - if (near_null) - exploitability_weight += kSmallBump; - else - exploitability_weight += kHugeBump; - break; - case MD_ACCESS_VIOLATION_WIN_EXEC: - if (near_null) - exploitability_weight += kSmallBump; - else - exploitability_weight += kHugeBump; - break; - default: - BPLOG(INFO) << "Unrecognized access violation type."; - return EXPLOITABILITY_ERR_PROCESSING; - break; - } - MinidumpMemoryRegion *instruction_region = 0; - if (memory_available) { - instruction_region = - memory_list->GetMemoryRegionForAddress(instruction_ptr); - } - if (!near_null && instruction_region && - context->GetContextCPU() == MD_CONTEXT_X86 && - (bad_read || bad_write)) { - // Perform checks related to memory around instruction pointer. - uint32_t memory_offset = - instruction_ptr - instruction_region->GetBase(); - uint32_t available_memory = - instruction_region->GetSize() - memory_offset; - available_memory = available_memory > kDisassembleBytesBeyondPC ? - kDisassembleBytesBeyondPC : available_memory; - if (available_memory) { - const uint8_t *raw_memory = - instruction_region->GetMemory() + memory_offset; - DisassemblerX86 disassembler(raw_memory, - available_memory, - instruction_ptr); - disassembler.NextInstruction(); - if (bad_read) - disassembler.setBadRead(); - else - disassembler.setBadWrite(); - if (disassembler.currentInstructionValid()) { - // Check if the faulting instruction falls into one of - // several interesting groups. - switch (disassembler.currentInstructionGroup()) { - case libdis::insn_controlflow: - exploitability_weight += kLargeBump; - break; - case libdis::insn_string: - exploitability_weight += kHugeBump; - break; - default: - break; - } - // Loop the disassembler through the code and check if it - // IDed any interesting conditions in the near future. - // Multiple flags may be set so treat each equally. - while (disassembler.NextInstruction() && - disassembler.currentInstructionValid() && - !disassembler.endOfBlock()) - continue; - if (disassembler.flags() & DISX86_BAD_BRANCH_TARGET) - exploitability_weight += kLargeBump; - if (disassembler.flags() & DISX86_BAD_ARGUMENT_PASSED) - exploitability_weight += kTinyBump; - if (disassembler.flags() & DISX86_BAD_WRITE) - exploitability_weight += kMediumBump; - if (disassembler.flags() & DISX86_BAD_BLOCK_WRITE) - exploitability_weight += kMediumBump; - if (disassembler.flags() & DISX86_BAD_READ) - exploitability_weight += kTinyBump; - if (disassembler.flags() & DISX86_BAD_BLOCK_READ) - exploitability_weight += kTinyBump; - if (disassembler.flags() & DISX86_BAD_COMPARISON) - exploitability_weight += kTinyBump; - } - } - } - if (!near_null && AddressIsAscii(address)) - exploitability_weight += kMediumBump; - } else { - BPLOG(INFO) << "Access violation type parameter missing."; - return EXPLOITABILITY_ERR_PROCESSING; - } - } - - // Based on the calculated weight we return a simplified classification. - BPLOG(INFO) << "Calculated exploitability weight: " << exploitability_weight; - if (exploitability_weight >= kHighCutoff) - return EXPLOITABILITY_HIGH; - if (exploitability_weight >= kMediumCutoff) - return EXPLOITABLITY_MEDIUM; - if (exploitability_weight >= kLowCutoff) - return EXPLOITABILITY_LOW; - if (exploitability_weight >= kInterestingCutoff) - return EXPLOITABILITY_INTERESTING; - - return EXPLOITABILITY_NONE; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.h b/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.h deleted file mode 100644 index 4e08aef03..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/exploitability_win.h +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// exploitability_win.h: Windows specific exploitability engine. -// -// Provides a guess at the exploitability of the crash for the Windows -// platform given a minidump and process_state. -// -// Author: Cris Neckar - -#ifndef GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_WIN_H_ -#define GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_WIN_H_ - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/processor/exploitability.h" - -namespace google_breakpad { - -class ExploitabilityWin : public Exploitability { - public: - ExploitabilityWin(Minidump *dump, - ProcessState *process_state); - - virtual ExploitabilityRating CheckPlatformExploitability(); -}; - -} // namespace google_breakpad - -#endif // GOOGLE_BREAKPAD_PROCESSOR_EXPLOITABILITY_WIN_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver.cc b/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver.cc deleted file mode 100644 index 4a3d00071..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver.cc +++ /dev/null @@ -1,275 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// fast_source_line_resolver.cc: FastSourceLineResolver is a concrete class that -// implements SourceLineResolverInterface. Both FastSourceLineResolver and -// BasicSourceLineResolver inherit from SourceLineResolverBase class to reduce -// code redundancy. -// -// See fast_source_line_resolver.h and fast_source_line_resolver_types.h -// for more documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include "google_breakpad/processor/fast_source_line_resolver.h" -#include "processor/fast_source_line_resolver_types.h" - -#include <map> -#include <string> -#include <utility> - -#include "common/scoped_ptr.h" -#include "common/using_std_string.h" -#include "processor/module_factory.h" -#include "processor/simple_serializer-inl.h" - -using std::map; -using std::make_pair; - -namespace google_breakpad { - -FastSourceLineResolver::FastSourceLineResolver() - : SourceLineResolverBase(new FastModuleFactory) { } - -bool FastSourceLineResolver::ShouldDeleteMemoryBufferAfterLoadModule() { - return false; -} - -void FastSourceLineResolver::Module::LookupAddress(StackFrame *frame) const { - MemAddr address = frame->instruction - frame->module->base_address(); - - // First, look for a FUNC record that covers address. Use - // RetrieveNearestRange instead of RetrieveRange so that, if there - // is no such function, we can use the next function to bound the - // extent of the PUBLIC symbol we find, below. This does mean we - // need to check that address indeed falls within the function we - // find; do the range comparison in an overflow-friendly way. - scoped_ptr<Function> func(new Function); - const Function* func_ptr = 0; - scoped_ptr<PublicSymbol> public_symbol(new PublicSymbol); - const PublicSymbol* public_symbol_ptr = 0; - MemAddr function_base; - MemAddr function_size; - MemAddr public_address; - - if (functions_.RetrieveNearestRange(address, func_ptr, - &function_base, &function_size) && - address >= function_base && address - function_base < function_size) { - func.get()->CopyFrom(func_ptr); - frame->function_name = func->name; - frame->function_base = frame->module->base_address() + function_base; - - scoped_ptr<Line> line(new Line); - const Line* line_ptr = 0; - MemAddr line_base; - if (func->lines.RetrieveRange(address, line_ptr, &line_base, NULL)) { - line.get()->CopyFrom(line_ptr); - FileMap::iterator it = files_.find(line->source_file_id); - if (it != files_.end()) { - frame->source_file_name = - files_.find(line->source_file_id).GetValuePtr(); - } - frame->source_line = line->line; - frame->source_line_base = frame->module->base_address() + line_base; - } - } else if (public_symbols_.Retrieve(address, - public_symbol_ptr, &public_address) && - (!func_ptr || public_address > function_base)) { - public_symbol.get()->CopyFrom(public_symbol_ptr); - frame->function_name = public_symbol->name; - frame->function_base = frame->module->base_address() + public_address; - } -} - -// WFI: WindowsFrameInfo. -// Returns a WFI object reading from a raw memory chunk of data -WindowsFrameInfo FastSourceLineResolver::CopyWFI(const char *raw) { - const WindowsFrameInfo::StackInfoTypes type = - static_cast<const WindowsFrameInfo::StackInfoTypes>( - *reinterpret_cast<const int32_t*>(raw)); - - // The first 8 bytes of int data are unused. - // They correspond to "StackInfoTypes type_;" and "int valid;" - // data member of WFI. - const uint32_t *para_uint32 = reinterpret_cast<const uint32_t*>( - raw + 2 * sizeof(int32_t)); - - uint32_t prolog_size = para_uint32[0];; - uint32_t epilog_size = para_uint32[1]; - uint32_t parameter_size = para_uint32[2]; - uint32_t saved_register_size = para_uint32[3]; - uint32_t local_size = para_uint32[4]; - uint32_t max_stack_size = para_uint32[5]; - const char *boolean = reinterpret_cast<const char*>(para_uint32 + 6); - bool allocates_base_pointer = (*boolean != 0); - string program_string = boolean + 1; - - return WindowsFrameInfo(type, - prolog_size, - epilog_size, - parameter_size, - saved_register_size, - local_size, - max_stack_size, - allocates_base_pointer, - program_string); -} - -// Loads a map from the given buffer in char* type. -// Does NOT take ownership of mem_buffer. -// In addition, treat mem_buffer as const char*. -bool FastSourceLineResolver::Module::LoadMapFromMemory( - char *memory_buffer, - size_t memory_buffer_size) { - if (!memory_buffer) return false; - - // Read the "is_corrupt" flag. - const char *mem_buffer = memory_buffer; - mem_buffer = SimpleSerializer<bool>::Read(mem_buffer, &is_corrupt_); - - const uint32_t *map_sizes = reinterpret_cast<const uint32_t*>(mem_buffer); - - unsigned int header_size = kNumberMaps_ * sizeof(unsigned int); - - // offsets[]: an array of offset addresses (with respect to mem_buffer), - // for each "Static***Map" component of Module. - // "Static***Map": static version of std::map or map wrapper, i.e., StaticMap, - // StaticAddressMap, StaticContainedRangeMap, and StaticRangeMap. - unsigned int offsets[kNumberMaps_]; - offsets[0] = header_size; - for (int i = 1; i < kNumberMaps_; ++i) { - offsets[i] = offsets[i - 1] + map_sizes[i - 1]; - } - - // Use pointers to construct Static*Map data members in Module: - int map_id = 0; - files_ = StaticMap<int, char>(mem_buffer + offsets[map_id++]); - functions_ = - StaticRangeMap<MemAddr, Function>(mem_buffer + offsets[map_id++]); - public_symbols_ = - StaticAddressMap<MemAddr, PublicSymbol>(mem_buffer + offsets[map_id++]); - for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) - windows_frame_info_[i] = - StaticContainedRangeMap<MemAddr, char>(mem_buffer + offsets[map_id++]); - - cfi_initial_rules_ = - StaticRangeMap<MemAddr, char>(mem_buffer + offsets[map_id++]); - cfi_delta_rules_ = StaticMap<MemAddr, char>(mem_buffer + offsets[map_id++]); - - return true; -} - -WindowsFrameInfo *FastSourceLineResolver::Module::FindWindowsFrameInfo( - const StackFrame *frame) const { - MemAddr address = frame->instruction - frame->module->base_address(); - scoped_ptr<WindowsFrameInfo> result(new WindowsFrameInfo()); - - // We only know about WindowsFrameInfo::STACK_INFO_FRAME_DATA and - // WindowsFrameInfo::STACK_INFO_FPO. Prefer them in this order. - // WindowsFrameInfo::STACK_INFO_FRAME_DATA is the newer type that - // includes its own program string. - // WindowsFrameInfo::STACK_INFO_FPO is the older type - // corresponding to the FPO_DATA struct. See stackwalker_x86.cc. - const char* frame_info_ptr; - if ((windows_frame_info_[WindowsFrameInfo::STACK_INFO_FRAME_DATA] - .RetrieveRange(address, frame_info_ptr)) - || (windows_frame_info_[WindowsFrameInfo::STACK_INFO_FPO] - .RetrieveRange(address, frame_info_ptr))) { - result->CopyFrom(CopyWFI(frame_info_ptr)); - return result.release(); - } - - // Even without a relevant STACK line, many functions contain - // information about how much space their parameters consume on the - // stack. Use RetrieveNearestRange instead of RetrieveRange, so that - // we can use the function to bound the extent of the PUBLIC symbol, - // below. However, this does mean we need to check that ADDRESS - // falls within the retrieved function's range; do the range - // comparison in an overflow-friendly way. - scoped_ptr<Function> function(new Function); - const Function* function_ptr = 0; - MemAddr function_base, function_size; - if (functions_.RetrieveNearestRange(address, function_ptr, - &function_base, &function_size) && - address >= function_base && address - function_base < function_size) { - function.get()->CopyFrom(function_ptr); - result->parameter_size = function->parameter_size; - result->valid |= WindowsFrameInfo::VALID_PARAMETER_SIZE; - return result.release(); - } - - // PUBLIC symbols might have a parameter size. Use the function we - // found above to limit the range the public symbol covers. - scoped_ptr<PublicSymbol> public_symbol(new PublicSymbol); - const PublicSymbol* public_symbol_ptr = 0; - MemAddr public_address; - if (public_symbols_.Retrieve(address, public_symbol_ptr, &public_address) && - (!function_ptr || public_address > function_base)) { - public_symbol.get()->CopyFrom(public_symbol_ptr); - result->parameter_size = public_symbol->parameter_size; - } - - return NULL; -} - -CFIFrameInfo *FastSourceLineResolver::Module::FindCFIFrameInfo( - const StackFrame *frame) const { - MemAddr address = frame->instruction - frame->module->base_address(); - MemAddr initial_base, initial_size; - const char* initial_rules = NULL; - - // Find the initial rule whose range covers this address. That - // provides an initial set of register recovery rules. Then, walk - // forward from the initial rule's starting address to frame's - // instruction address, applying delta rules. - if (!cfi_initial_rules_.RetrieveRange(address, initial_rules, - &initial_base, &initial_size)) { - return NULL; - } - - // Create a frame info structure, and populate it with the rules from - // the STACK CFI INIT record. - scoped_ptr<CFIFrameInfo> rules(new CFIFrameInfo()); - if (!ParseCFIRuleSet(initial_rules, rules.get())) - return NULL; - - // Find the first delta rule that falls within the initial rule's range. - StaticMap<MemAddr, char>::iterator delta = - cfi_delta_rules_.lower_bound(initial_base); - - // Apply delta rules up to and including the frame's address. - while (delta != cfi_delta_rules_.end() && delta.GetKey() <= address) { - ParseCFIRuleSet(delta.GetValuePtr(), rules.get()); - delta++; - } - - return rules.release(); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_types.h b/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_types.h deleted file mode 100644 index 2c010470f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_types.h +++ /dev/null @@ -1,185 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// fast_source_line_resolver_types.h: definition of nested classes/structs in -// FastSourceLineResolver. It moves the definitions out of -// fast_source_line_resolver.cc, so that other classes could have access -// to these private nested types without including fast_source_line_resolver.cc -// -// Author: lambxsy@google.com (Siyang Xie) - -#ifndef PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__ -#define PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__ - -#include "google_breakpad/processor/fast_source_line_resolver.h" -#include "processor/source_line_resolver_base_types.h" - -#include <map> -#include <string> - -#include "google_breakpad/processor/stack_frame.h" -#include "processor/cfi_frame_info.h" -#include "processor/static_address_map-inl.h" -#include "processor/static_contained_range_map-inl.h" -#include "processor/static_map.h" -#include "processor/static_range_map-inl.h" -#include "processor/windows_frame_info.h" - -namespace google_breakpad { - -struct FastSourceLineResolver::Line : public SourceLineResolverBase::Line { - void CopyFrom(const Line *line_ptr) { - const char *raw = reinterpret_cast<const char*>(line_ptr); - CopyFrom(raw); - } - - // De-serialize the memory data of a Line. - void CopyFrom(const char *raw) { - address = *(reinterpret_cast<const MemAddr*>(raw)); - size = *(reinterpret_cast<const MemAddr*>(raw + sizeof(address))); - source_file_id = *(reinterpret_cast<const int32_t *>( - raw + 2 * sizeof(address))); - line = *(reinterpret_cast<const int32_t*>( - raw + 2 * sizeof(address) + sizeof(source_file_id))); - } -}; - -struct FastSourceLineResolver::Function : -public SourceLineResolverBase::Function { - void CopyFrom(const Function *func_ptr) { - const char *raw = reinterpret_cast<const char*>(func_ptr); - CopyFrom(raw); - } - - // De-serialize the memory data of a Function. - void CopyFrom(const char *raw) { - size_t name_size = strlen(raw) + 1; - name = raw; - address = *(reinterpret_cast<const MemAddr*>(raw + name_size)); - size = *(reinterpret_cast<const MemAddr*>( - raw + name_size + sizeof(MemAddr))); - parameter_size = *(reinterpret_cast<const int32_t*>( - raw + name_size + 2 * sizeof(MemAddr))); - lines = StaticRangeMap<MemAddr, Line>( - raw + name_size + 2 * sizeof(MemAddr) + sizeof(int32_t)); - } - - StaticRangeMap<MemAddr, Line> lines; -}; - -struct FastSourceLineResolver::PublicSymbol : -public SourceLineResolverBase::PublicSymbol { - void CopyFrom(const PublicSymbol *public_symbol_ptr) { - const char *raw = reinterpret_cast<const char*>(public_symbol_ptr); - CopyFrom(raw); - } - - // De-serialize the memory data of a PublicSymbol. - void CopyFrom(const char *raw) { - size_t name_size = strlen(raw) + 1; - name = raw; - address = *(reinterpret_cast<const MemAddr*>(raw + name_size)); - parameter_size = *(reinterpret_cast<const int32_t*>( - raw + name_size + sizeof(MemAddr))); - } -}; - -class FastSourceLineResolver::Module: public SourceLineResolverBase::Module { - public: - explicit Module(const string &name) : name_(name), is_corrupt_(false) { } - virtual ~Module() { } - - // Looks up the given relative address, and fills the StackFrame struct - // with the result. - virtual void LookupAddress(StackFrame *frame) const; - - // Loads a map from the given buffer in char* type. - virtual bool LoadMapFromMemory(char *memory_buffer, - size_t memory_buffer_size); - - // Tells whether the loaded symbol data is corrupt. Return value is - // undefined, if the symbol data hasn't been loaded yet. - virtual bool IsCorrupt() const { return is_corrupt_; } - - // If Windows stack walking information is available covering ADDRESS, - // return a WindowsFrameInfo structure describing it. If the information - // is not available, returns NULL. A NULL return value does not indicate - // an error. The caller takes ownership of any returned WindowsFrameInfo - // object. - virtual WindowsFrameInfo *FindWindowsFrameInfo(const StackFrame *frame) const; - - // If CFI stack walking information is available covering ADDRESS, - // return a CFIFrameInfo structure describing it. If the information - // is not available, return NULL. The caller takes ownership of any - // returned CFIFrameInfo object. - virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const; - - // Number of serialized map components of Module. - static const int kNumberMaps_ = 5 + WindowsFrameInfo::STACK_INFO_LAST; - - private: - friend class FastSourceLineResolver; - friend class ModuleComparer; - typedef StaticMap<int, char> FileMap; - - string name_; - StaticMap<int, char> files_; - StaticRangeMap<MemAddr, Function> functions_; - StaticAddressMap<MemAddr, PublicSymbol> public_symbols_; - bool is_corrupt_; - - // Each element in the array is a ContainedRangeMap for a type - // listed in WindowsFrameInfoTypes. These are split by type because - // there may be overlaps between maps of different types, but some - // information is only available as certain types. - StaticContainedRangeMap<MemAddr, char> - windows_frame_info_[WindowsFrameInfo::STACK_INFO_LAST]; - - // DWARF CFI stack walking data. The Module stores the initial rule sets - // and rule deltas as strings, just as they appear in the symbol file: - // although the file may contain hundreds of thousands of STACK CFI - // records, walking a stack will only ever use a few of them, so it's - // best to delay parsing a record until it's actually needed. - // - // STACK CFI INIT records: for each range, an initial set of register - // recovery rules. The RangeMap's itself gives the starting and ending - // addresses. - StaticRangeMap<MemAddr, char> cfi_initial_rules_; - - // STACK CFI records: at a given address, the changes to the register - // recovery rules that take effect at that address. The map key is the - // starting address; the ending address is the key of the next entry in - // this map, or the end of the range as given by the cfi_initial_rules_ - // entry (which FindCFIFrameInfo looks up first). - StaticMap<MemAddr, char> cfi_delta_rules_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_FAST_SOURCE_LINE_RESOLVER_TYPES_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_unittest.cc deleted file mode 100644 index c7215228e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/fast_source_line_resolver_unittest.cc +++ /dev/null @@ -1,491 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// fast_source_line_resolver_unittest.cc: Unit tests for FastSourceLineResolver. -// Two different approaches for testing fast source line resolver: -// First, use the same unit test data for basic source line resolver. -// Second, read data from symbol files, load them as basic modules, and then -// serialize them and load the serialized data as fast modules. Then compare -// modules to assure the fast module contains exactly the same data as -// basic module. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include <assert.h> -#include <stdio.h> - -#include <sstream> -#include <string> - -#include "breakpad_googletest_includes.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/stack_frame.h" -#include "google_breakpad/processor/memory_region.h" -#include "processor/logging.h" -#include "processor/module_serializer.h" -#include "processor/module_comparer.h" - -namespace { - -using google_breakpad::SourceLineResolverBase; -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::FastSourceLineResolver; -using google_breakpad::ModuleSerializer; -using google_breakpad::ModuleComparer; -using google_breakpad::CFIFrameInfo; -using google_breakpad::CodeModule; -using google_breakpad::MemoryRegion; -using google_breakpad::StackFrame; -using google_breakpad::WindowsFrameInfo; -using google_breakpad::linked_ptr; -using google_breakpad::scoped_ptr; - -class TestCodeModule : public CodeModule { - public: - explicit TestCodeModule(string code_file) : code_file_(code_file) {} - virtual ~TestCodeModule() {} - - virtual uint64_t base_address() const { return 0; } - virtual uint64_t size() const { return 0xb000; } - virtual string code_file() const { return code_file_; } - virtual string code_identifier() const { return ""; } - virtual string debug_file() const { return ""; } - virtual string debug_identifier() const { return ""; } - virtual string version() const { return ""; } - virtual CodeModule* Copy() const { - return new TestCodeModule(code_file_); - } - virtual uint64_t shrink_down_delta() const { return 0; } - virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {} - - private: - string code_file_; -}; - -// A mock memory region object, for use by the STACK CFI tests. -class MockMemoryRegion: public MemoryRegion { - uint64_t GetBase() const { return 0x10000; } - uint32_t GetSize() const { return 0x01000; } - bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const { - *value = address & 0xff; - return true; - } - bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const { - *value = address & 0xffff; - return true; - } - bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const { - switch (address) { - case 0x10008: *value = 0x98ecadc3; break; // saved %ebx - case 0x1000c: *value = 0x878f7524; break; // saved %esi - case 0x10010: *value = 0x6312f9a5; break; // saved %edi - case 0x10014: *value = 0x10038; break; // caller's %ebp - case 0x10018: *value = 0xf6438648; break; // return address - default: *value = 0xdeadbeef; break; // junk - } - return true; - } - bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const { - *value = address; - return true; - } - void Print() const { - assert(false); - } -}; - -// Verify that, for every association in ACTUAL, EXPECTED has the same -// association. (That is, ACTUAL's associations should be a subset of -// EXPECTED's.) Also verify that ACTUAL has associations for ".ra" and -// ".cfa". -static bool VerifyRegisters( - const char *file, int line, - const CFIFrameInfo::RegisterValueMap<uint32_t> &expected, - const CFIFrameInfo::RegisterValueMap<uint32_t> &actual) { - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator a; - a = actual.find(".cfa"); - if (a == actual.end()) - return false; - a = actual.find(".ra"); - if (a == actual.end()) - return false; - for (a = actual.begin(); a != actual.end(); a++) { - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator e = - expected.find(a->first); - if (e == expected.end()) { - fprintf(stderr, "%s:%d: unexpected register '%s' recovered, value 0x%x\n", - file, line, a->first.c_str(), a->second); - return false; - } - if (e->second != a->second) { - fprintf(stderr, - "%s:%d: register '%s' recovered value was 0x%x, expected 0x%x\n", - file, line, a->first.c_str(), a->second, e->second); - return false; - } - // Don't complain if this doesn't recover all registers. Although - // the DWARF spec says that unmentioned registers are undefined, - // GCC uses omission to mean that they are unchanged. - } - return true; -} - -static bool VerifyEmpty(const StackFrame &frame) { - if (frame.function_name.empty() && - frame.source_file_name.empty() && - frame.source_line == 0) - return true; - return false; -} - -static void ClearSourceLineInfo(StackFrame *frame) { - frame->function_name.clear(); - frame->module = NULL; - frame->source_file_name.clear(); - frame->source_line = 0; -} - -class TestFastSourceLineResolver : public ::testing::Test { - public: - void SetUp() { - testdata_dir = string(getenv("srcdir") ? getenv("srcdir") : ".") + - "/src/processor/testdata"; - } - - string symbol_file(int file_index) { - std::stringstream ss; - ss << testdata_dir << "/module" << file_index << ".out"; - return ss.str(); - } - - ModuleSerializer serializer; - BasicSourceLineResolver basic_resolver; - FastSourceLineResolver fast_resolver; - ModuleComparer module_comparer; - - string testdata_dir; -}; - -// Test adapted from basic_source_line_resolver_unittest. -TEST_F(TestFastSourceLineResolver, TestLoadAndResolve) { - TestCodeModule module1("module1"); - ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1))); - ASSERT_TRUE(basic_resolver.HasModule(&module1)); - // Convert module1 to fast_module: - ASSERT_TRUE(serializer.ConvertOneModule( - module1.code_file(), &basic_resolver, &fast_resolver)); - ASSERT_TRUE(fast_resolver.HasModule(&module1)); - - TestCodeModule module2("module2"); - ASSERT_TRUE(basic_resolver.LoadModule(&module2, symbol_file(2))); - ASSERT_TRUE(basic_resolver.HasModule(&module2)); - // Convert module2 to fast_module: - ASSERT_TRUE(serializer.ConvertOneModule( - module2.code_file(), &basic_resolver, &fast_resolver)); - ASSERT_TRUE(fast_resolver.HasModule(&module2)); - - StackFrame frame; - scoped_ptr<WindowsFrameInfo> windows_frame_info; - scoped_ptr<CFIFrameInfo> cfi_frame_info; - frame.instruction = 0x1000; - frame.module = NULL; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_FALSE(frame.module); - ASSERT_TRUE(frame.function_name.empty()); - ASSERT_EQ(frame.function_base, 0U); - ASSERT_TRUE(frame.source_file_name.empty()); - ASSERT_EQ(frame.source_line, 0); - ASSERT_EQ(frame.source_line_base, 0U); - - frame.module = &module1; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Function1_1"); - ASSERT_TRUE(frame.module); - ASSERT_EQ(frame.module->code_file(), "module1"); - ASSERT_EQ(frame.function_base, 0x1000U); - ASSERT_EQ(frame.source_file_name, "file1_1.cc"); - ASSERT_EQ(frame.source_line, 44); - ASSERT_EQ(frame.source_line_base, 0x1000U); - windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); - ASSERT_TRUE(windows_frame_info.get()); - ASSERT_FALSE(windows_frame_info->allocates_base_pointer); - ASSERT_EQ(windows_frame_info->program_string, - "$eip 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ ="); - - ClearSourceLineInfo(&frame); - frame.instruction = 0x800; - frame.module = &module1; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_TRUE(VerifyEmpty(frame)); - windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); - ASSERT_FALSE(windows_frame_info.get()); - - frame.instruction = 0x1280; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Function1_3"); - ASSERT_TRUE(frame.source_file_name.empty()); - ASSERT_EQ(frame.source_line, 0); - windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); - ASSERT_TRUE(windows_frame_info.get()); - ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_UNKNOWN); - ASSERT_FALSE(windows_frame_info->allocates_base_pointer); - ASSERT_TRUE(windows_frame_info->program_string.empty()); - - frame.instruction = 0x1380; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Function1_4"); - ASSERT_TRUE(frame.source_file_name.empty()); - ASSERT_EQ(frame.source_line, 0); - windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); - ASSERT_TRUE(windows_frame_info.get()); - ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); - ASSERT_FALSE(windows_frame_info->allocates_base_pointer); - ASSERT_FALSE(windows_frame_info->program_string.empty()); - - frame.instruction = 0x2000; - windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); - ASSERT_FALSE(windows_frame_info.get()); - - // module1 has STACK CFI records covering 3d40..3def; - // module2 has STACK CFI records covering 3df0..3e9f; - // check that FindCFIFrameInfo doesn't claim to find any outside those ranges. - frame.instruction = 0x3d3f; - frame.module = &module1; - cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); - ASSERT_FALSE(cfi_frame_info.get()); - - frame.instruction = 0x3e9f; - frame.module = &module1; - cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); - ASSERT_FALSE(cfi_frame_info.get()); - - CFIFrameInfo::RegisterValueMap<uint32_t> current_registers; - CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; - CFIFrameInfo::RegisterValueMap<uint32_t> expected_caller_registers; - MockMemoryRegion memory; - - // Regardless of which instruction evaluation takes place at, it - // should produce the same values for the caller's registers. - expected_caller_registers[".cfa"] = 0x1001c; - expected_caller_registers[".ra"] = 0xf6438648; - expected_caller_registers["$ebp"] = 0x10038; - expected_caller_registers["$ebx"] = 0x98ecadc3; - expected_caller_registers["$esi"] = 0x878f7524; - expected_caller_registers["$edi"] = 0x6312f9a5; - - frame.instruction = 0x3d40; - frame.module = &module1; - current_registers.clear(); - current_registers["$esp"] = 0x10018; - current_registers["$ebp"] = 0x10038; - current_registers["$ebx"] = 0x98ecadc3; - current_registers["$esi"] = 0x878f7524; - current_registers["$edi"] = 0x6312f9a5; - cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers)); - - frame.instruction = 0x3d41; - current_registers["$esp"] = 0x10014; - cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - ASSERT_TRUE(VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers)); - - frame.instruction = 0x3d43; - current_registers["$ebp"] = 0x10014; - cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers); - - frame.instruction = 0x3d54; - current_registers["$ebx"] = 0x6864f054U; - cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers); - - frame.instruction = 0x3d5a; - current_registers["$esi"] = 0x6285f79aU; - cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers); - - frame.instruction = 0x3d84; - current_registers["$edi"] = 0x64061449U; - cfi_frame_info.reset(fast_resolver.FindCFIFrameInfo(&frame)); - ASSERT_TRUE(cfi_frame_info.get()); - ASSERT_TRUE(cfi_frame_info.get() - ->FindCallerRegs<uint32_t>(current_registers, memory, - &caller_registers)); - VerifyRegisters(__FILE__, __LINE__, - expected_caller_registers, caller_registers); - - frame.instruction = 0x2900; - frame.module = &module1; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, string("PublicSymbol")); - - frame.instruction = 0x4000; - frame.module = &module1; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, string("LargeFunction")); - - frame.instruction = 0x2181; - frame.module = &module2; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Function2_2"); - ASSERT_EQ(frame.function_base, 0x2170U); - ASSERT_TRUE(frame.module); - ASSERT_EQ(frame.module->code_file(), "module2"); - ASSERT_EQ(frame.source_file_name, "file2_2.cc"); - ASSERT_EQ(frame.source_line, 21); - ASSERT_EQ(frame.source_line_base, 0x2180U); - windows_frame_info.reset(fast_resolver.FindWindowsFrameInfo(&frame)); - ASSERT_TRUE(windows_frame_info.get()); - ASSERT_EQ(windows_frame_info->type_, WindowsFrameInfo::STACK_INFO_FRAME_DATA); - ASSERT_EQ(windows_frame_info->prolog_size, 1U); - - frame.instruction = 0x216f; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Public2_1"); - - ClearSourceLineInfo(&frame); - frame.instruction = 0x219f; - frame.module = &module2; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_TRUE(frame.function_name.empty()); - - frame.instruction = 0x21a0; - frame.module = &module2; - fast_resolver.FillSourceLineInfo(&frame); - ASSERT_EQ(frame.function_name, "Public2_2"); -} - -TEST_F(TestFastSourceLineResolver, TestInvalidLoads) { - TestCodeModule module3("module3"); - ASSERT_TRUE(basic_resolver.LoadModule(&module3, - testdata_dir + "/module3_bad.out")); - ASSERT_TRUE(basic_resolver.HasModule(&module3)); - ASSERT_TRUE(basic_resolver.IsModuleCorrupt(&module3)); - // Convert module3 to fast_module: - ASSERT_TRUE(serializer.ConvertOneModule(module3.code_file(), - &basic_resolver, - &fast_resolver)); - ASSERT_TRUE(fast_resolver.HasModule(&module3)); - ASSERT_TRUE(fast_resolver.IsModuleCorrupt(&module3)); - - TestCodeModule module4("module4"); - ASSERT_TRUE(basic_resolver.LoadModule(&module4, - testdata_dir + "/module4_bad.out")); - ASSERT_TRUE(basic_resolver.HasModule(&module4)); - ASSERT_TRUE(basic_resolver.IsModuleCorrupt(&module4)); - // Convert module4 to fast_module: - ASSERT_TRUE(serializer.ConvertOneModule(module4.code_file(), - &basic_resolver, - &fast_resolver)); - ASSERT_TRUE(fast_resolver.HasModule(&module4)); - ASSERT_TRUE(fast_resolver.IsModuleCorrupt(&module4)); - - TestCodeModule module5("module5"); - ASSERT_FALSE(fast_resolver.LoadModule(&module5, - testdata_dir + "/invalid-filename")); - ASSERT_FALSE(fast_resolver.HasModule(&module5)); - - TestCodeModule invalidmodule("invalid-module"); - ASSERT_FALSE(fast_resolver.HasModule(&invalidmodule)); -} - -TEST_F(TestFastSourceLineResolver, TestUnload) { - TestCodeModule module1("module1"); - ASSERT_FALSE(basic_resolver.HasModule(&module1)); - - ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1))); - ASSERT_TRUE(basic_resolver.HasModule(&module1)); - // Convert module1 to fast_module. - ASSERT_TRUE(serializer.ConvertOneModule(module1.code_file(), - &basic_resolver, - &fast_resolver)); - ASSERT_TRUE(fast_resolver.HasModule(&module1)); - basic_resolver.UnloadModule(&module1); - fast_resolver.UnloadModule(&module1); - ASSERT_FALSE(fast_resolver.HasModule(&module1)); - - ASSERT_TRUE(basic_resolver.LoadModule(&module1, symbol_file(1))); - ASSERT_TRUE(basic_resolver.HasModule(&module1)); - // Convert module1 to fast_module. - ASSERT_TRUE(serializer.ConvertOneModule(module1.code_file(), - &basic_resolver, - &fast_resolver)); - ASSERT_TRUE(fast_resolver.HasModule(&module1)); -} - -TEST_F(TestFastSourceLineResolver, CompareModule) { - char *symbol_data; - size_t symbol_data_size; - string symbol_data_string; - string filename; - - for (int module_index = 0; module_index < 3; ++module_index) { - std::stringstream ss; - ss << testdata_dir << "/module" << module_index << ".out"; - filename = ss.str(); - ASSERT_TRUE(SourceLineResolverBase::ReadSymbolFile( - symbol_file(module_index), &symbol_data, &symbol_data_size)); - symbol_data_string.assign(symbol_data, symbol_data_size); - delete [] symbol_data; - ASSERT_TRUE(module_comparer.Compare(symbol_data_string)); - } -} - -} // namespace - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/linked_ptr.h b/toolkit/crashreporter/google-breakpad/src/processor/linked_ptr.h deleted file mode 100644 index 72fbba84a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/linked_ptr.h +++ /dev/null @@ -1,193 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// A "smart" pointer type with reference tracking. Every pointer to a -// particular object is kept on a circular linked list. When the last pointer -// to an object is destroyed or reassigned, the object is deleted. -// -// Used properly, this deletes the object when the last reference goes away. -// There are several caveats: -// - Like all reference counting schemes, cycles lead to leaks. -// - Each smart pointer is actually two pointers (8 bytes instead of 4). -// - Every time a pointer is assigned, the entire list of pointers to that -// object is traversed. This class is therefore NOT SUITABLE when there -// will often be more than two or three pointers to a particular object. -// - References are only tracked as long as linked_ptr<> objects are copied. -// If a linked_ptr<> is converted to a raw pointer and back, BAD THINGS -// will happen (double deletion). -// -// A good use of this class is storing object references in STL containers. -// You can safely put linked_ptr<> in a vector<>. -// Other uses may not be as good. -// -// Note: If you use an incomplete type with linked_ptr<>, the class -// *containing* linked_ptr<> must have a constructor and destructor (even -// if they do nothing!). - -#ifndef PROCESSOR_LINKED_PTR_H__ -#define PROCESSOR_LINKED_PTR_H__ - -namespace google_breakpad { - -// This is used internally by all instances of linked_ptr<>. It needs to be -// a non-template class because different types of linked_ptr<> can refer to -// the same object (linked_ptr<Superclass>(obj) vs linked_ptr<Subclass>(obj)). -// So, it needs to be possible for different types of linked_ptr to participate -// in the same circular linked list, so we need a single class type here. -// -// DO NOT USE THIS CLASS DIRECTLY YOURSELF. Use linked_ptr<T>. -class linked_ptr_internal { - public: - // Create a new circle that includes only this instance. - void join_new() { - next_ = this; - } - - // Join an existing circle. - void join(linked_ptr_internal const* ptr) { - linked_ptr_internal const* p = ptr; - while (p->next_ != ptr) p = p->next_; - p->next_ = this; - next_ = ptr; - } - - // Leave whatever circle we're part of. Returns true iff we were the - // last member of the circle. Once this is done, you can join() another. - bool depart() { - if (next_ == this) return true; - linked_ptr_internal const* p = next_; - while (p->next_ != this) p = p->next_; - p->next_ = next_; - return false; - } - - private: - mutable linked_ptr_internal const* next_; -}; - -template <typename T> -class linked_ptr { - public: - typedef T element_type; - - // Take over ownership of a raw pointer. This should happen as soon as - // possible after the object is created. - explicit linked_ptr(T* ptr = NULL) { capture(ptr); } - ~linked_ptr() { depart(); } - - // Copy an existing linked_ptr<>, adding ourselves to the list of references. - template <typename U> linked_ptr(linked_ptr<U> const& ptr) { copy(&ptr); } - linked_ptr(linked_ptr const& ptr) { copy(&ptr); } - - // Assignment releases the old value and acquires the new. - template <typename U> linked_ptr& operator=(linked_ptr<U> const& ptr) { - depart(); - copy(&ptr); - return *this; - } - - linked_ptr& operator=(linked_ptr const& ptr) { - if (&ptr != this) { - depart(); - copy(&ptr); - } - return *this; - } - - // Smart pointer members. - void reset(T* ptr = NULL) { depart(); capture(ptr); } - T* get() const { return value_; } - T* operator->() const { return value_; } - T& operator*() const { return *value_; } - // Release ownership of the pointed object and returns it. - // Sole ownership by this linked_ptr object is required. - T* release() { - link_.depart(); - T* v = value_; - value_ = NULL; - return v; - } - - bool operator==(T* p) const { return value_ == p; } - bool operator!=(T* p) const { return value_ != p; } - template <typename U> - bool operator==(linked_ptr<U> const& ptr) const { - return value_ == ptr.get(); - } - template <typename U> - bool operator!=(linked_ptr<U> const& ptr) const { - return value_ != ptr.get(); - } - - private: - template <typename U> - friend class linked_ptr; - - T* value_; - linked_ptr_internal link_; - - void depart() { - if (link_.depart()) delete value_; - } - - void capture(T* ptr) { - value_ = ptr; - link_.join_new(); - } - - template <typename U> void copy(linked_ptr<U> const* ptr) { - value_ = ptr->get(); - if (value_) - link_.join(&ptr->link_); - else - link_.join_new(); - } -}; - -template<typename T> inline -bool operator==(T* ptr, const linked_ptr<T>& x) { - return ptr == x.get(); -} - -template<typename T> inline -bool operator!=(T* ptr, const linked_ptr<T>& x) { - return ptr != x.get(); -} - -// A function to convert T* into linked_ptr<T> -// Doing e.g. make_linked_ptr(new FooBarBaz<type>(arg)) is a shorter notation -// for linked_ptr<FooBarBaz<type> >(new FooBarBaz<type>(arg)) -template <typename T> -linked_ptr<T> make_linked_ptr(T* ptr) { - return linked_ptr<T>(ptr); -} - -} // namespace google_breakpad - -#endif // PROCESSOR_LINKED_PTR_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/logging.cc b/toolkit/crashreporter/google-breakpad/src/processor/logging.cc deleted file mode 100644 index c1eebbc22..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/logging.cc +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// logging.cc: Breakpad logging -// -// See logging.h for documentation. -// -// Author: Mark Mentovai - -#include <assert.h> -#include <errno.h> -#include <string.h> -#include <time.h> - -#include <string> - -#include "common/stdio_wrapper.h" -#include "common/using_std_string.h" -#include "processor/logging.h" -#include "processor/pathname_stripper.h" - -namespace google_breakpad { - -LogStream::LogStream(std::ostream &stream, Severity severity, - const char *file, int line) - : stream_(stream) { - time_t clock; - time(&clock); - struct tm tm_struct; -#ifdef _WIN32 - localtime_s(&tm_struct, &clock); -#else - localtime_r(&clock, &tm_struct); -#endif - char time_string[20]; - strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", &tm_struct); - - const char *severity_string = "UNKNOWN_SEVERITY"; - switch (severity) { - case SEVERITY_INFO: - severity_string = "INFO"; - break; - case SEVERITY_ERROR: - severity_string = "ERROR"; - break; - } - - stream_ << time_string << ": " << PathnameStripper::File(file) << ":" << - line << ": " << severity_string << ": "; -} - -LogStream::~LogStream() { - stream_ << std::endl; -} - -string HexString(uint32_t number) { - char buffer[11]; - snprintf(buffer, sizeof(buffer), "0x%x", number); - return string(buffer); -} - -string HexString(uint64_t number) { - char buffer[19]; - snprintf(buffer, sizeof(buffer), "0x%" PRIx64, number); - return string(buffer); -} - -string HexString(int number) { - char buffer[19]; - snprintf(buffer, sizeof(buffer), "0x%x", number); - return string(buffer); -} - -int ErrnoString(string *error_string) { - assert(error_string); - - // strerror isn't necessarily thread-safe. strerror_r would be preferrable, - // but GNU libc uses a nonstandard strerror_r by default, which returns a - // char* (rather than an int success indicator) and doesn't necessarily - // use the supplied buffer. - error_string->assign(strerror(errno)); - return errno; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/logging.h b/toolkit/crashreporter/google-breakpad/src/processor/logging.h deleted file mode 100644 index 406fb67cf..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/logging.h +++ /dev/null @@ -1,186 +0,0 @@ -// Copyright (c) 2007, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// logging.h: Breakpad logging -// -// Breakpad itself uses Breakpad logging with statements of the form: -// BPLOG(severity) << "message"; -// severity may be INFO, ERROR, or other values defined in this file. -// -// BPLOG is an overridable macro so that users can customize Breakpad's -// logging. Left at the default, logging messages are sent to stderr along -// with a timestamp and the source code location that produced a message. -// The streams may be changed by redefining BPLOG_*_STREAM, the logging -// behavior may be changed by redefining BPLOG_*, and the entire logging -// system may be overridden by redefining BPLOG(severity). These -// redefinitions may be passed to the preprocessor as a command-line flag -// (-D). -// -// If an additional header is required to override Breakpad logging, it can -// be specified by the BP_LOGGING_INCLUDE macro. If defined, this header -// will #include the header specified by that macro. -// -// If any initialization is needed before logging, it can be performed by -// a function called through the BPLOG_INIT macro. Each main function of -// an executable program in the Breakpad processor library calls -// BPLOG_INIT(&argc, &argv); before any logging can be performed; define -// BPLOG_INIT appropriately if initialization is required. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_LOGGING_H__ -#define PROCESSOR_LOGGING_H__ - -#include <iostream> -#include <string> - -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" - -#ifdef BP_LOGGING_INCLUDE -#include BP_LOGGING_INCLUDE -#endif // BP_LOGGING_INCLUDE - -#ifndef THIRD_PARTY_BREAKPAD_GOOGLE_GLUE_LOGGING_H_ -namespace base_logging { - -// The open-source copy of logging.h has diverged from Google's internal copy -// (temporarily, at least). To support the transition to structured logging -// a definition for base_logging::LogMessage is needed, which is a ostream- -// like object for streaming arguments to construct a log message. -typedef std::ostream LogMessage; - -} // namespace base_logging -#endif // THIRD_PARTY_BREAKPAD_GOOGLE_GLUE_LOGGING_H_ - -namespace google_breakpad { - -// These are defined in Microsoft headers. -#ifdef SEVERITY_ERROR -#undef SEVERITY_ERROR -#endif - -#ifdef ERROR -#undef ERROR -#endif - -class LogStream { - public: - enum Severity { - SEVERITY_INFO, - SEVERITY_ERROR - }; - - // Begin logging a message to the stream identified by |stream|, at the - // indicated severity. The file and line parameters should be set so as to - // identify the line of source code that is producing a message. - LogStream(std::ostream &stream, Severity severity, - const char *file, int line); - - // Finish logging by printing a newline and flushing the output stream. - ~LogStream(); - - template<typename T> std::ostream& operator<<(const T &t) { - return stream_ << t; - } - - private: - std::ostream &stream_; - - // Disallow copy constructor and assignment operator - explicit LogStream(const LogStream &that); - void operator=(const LogStream &that); -}; - -// This class is used to explicitly ignore values in the conditional logging -// macros. This avoids compiler warnings like "value computed is not used" -// and "statement has no effect". -class LogMessageVoidify { - public: - LogMessageVoidify() {} - - // This has to be an operator with a precedence lower than << but higher - // than ?: - void operator&(base_logging::LogMessage &) {} -}; - -// Returns number formatted as a hexadecimal string, such as "0x7b". -string HexString(uint32_t number); -string HexString(uint64_t number); -string HexString(int number); - -// Returns the error code as set in the global errno variable, and sets -// error_string, a required argument, to a string describing that error -// code. -int ErrnoString(string *error_string); - -} // namespace google_breakpad - -#ifndef BPLOG_INIT -#define BPLOG_INIT(pargc, pargv) -#endif // BPLOG_INIT - -#define BPLOG_LAZY_STREAM(stream, condition) \ - !(condition) ? (void) 0 : \ - google_breakpad::LogMessageVoidify() & (BPLOG_ ## stream) - -#ifndef BPLOG_MINIMUM_SEVERITY -#define BPLOG_MINIMUM_SEVERITY SEVERITY_INFO -#endif - -#define BPLOG_LOG_IS_ON(severity) \ - ((google_breakpad::LogStream::SEVERITY_ ## severity) >= \ - (google_breakpad::LogStream::BPLOG_MINIMUM_SEVERITY)) - -#ifndef BPLOG -#define BPLOG(severity) BPLOG_LAZY_STREAM(severity, BPLOG_LOG_IS_ON(severity)) -#endif // BPLOG - -#ifndef BPLOG_INFO -#ifndef BPLOG_INFO_STREAM -#define BPLOG_INFO_STREAM std::clog -#endif // BPLOG_INFO_STREAM -#define BPLOG_INFO google_breakpad::LogStream(BPLOG_INFO_STREAM, \ - google_breakpad::LogStream::SEVERITY_INFO, \ - __FILE__, __LINE__) -#endif // BPLOG_INFO - -#ifndef BPLOG_ERROR -#ifndef BPLOG_ERROR_STREAM -#define BPLOG_ERROR_STREAM std::cerr -#endif // BPLOG_ERROR_STREAM -#define BPLOG_ERROR google_breakpad::LogStream(BPLOG_ERROR_STREAM, \ - google_breakpad::LogStream::SEVERITY_ERROR, \ - __FILE__, __LINE__) -#endif // BPLOG_ERROR - -#define BPLOG_IF(severity, condition) \ - BPLOG_LAZY_STREAM(severity, ((condition) && BPLOG_LOG_IS_ON(severity))) - -#endif // PROCESSOR_LOGGING_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/map_serializers-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/map_serializers-inl.h deleted file mode 100644 index 61c7bbd7c..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/map_serializers-inl.h +++ /dev/null @@ -1,266 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// map_serializers_inl.h: implementation for serializing std::map and its -// wrapper classes. -// -// See map_serializers.h for documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_MAP_SERIALIZERS_INL_H__ -#define PROCESSOR_MAP_SERIALIZERS_INL_H__ - -#include <map> -#include <string> - -#include "processor/map_serializers.h" -#include "processor/simple_serializer.h" - -#include "processor/address_map-inl.h" -#include "processor/range_map-inl.h" -#include "processor/contained_range_map-inl.h" - -#include "processor/logging.h" - -namespace google_breakpad { - -template<typename Key, typename Value> -size_t StdMapSerializer<Key, Value>::SizeOf( - const std::map<Key, Value> &m) const { - size_t size = 0; - size_t header_size = (1 + m.size()) * sizeof(uint32_t); - size += header_size; - - typename std::map<Key, Value>::const_iterator iter; - for (iter = m.begin(); iter != m.end(); ++iter) { - size += key_serializer_.SizeOf(iter->first); - size += value_serializer_.SizeOf(iter->second); - } - return size; -} - -template<typename Key, typename Value> -char *StdMapSerializer<Key, Value>::Write(const std::map<Key, Value> &m, - char *dest) const { - if (!dest) { - BPLOG(ERROR) << "StdMapSerializer failed: write to NULL address."; - return NULL; - } - char *start_address = dest; - - // Write header: - // Number of nodes. - dest = SimpleSerializer<uint32_t>::Write(m.size(), dest); - // Nodes offsets. - uint32_t *offsets = reinterpret_cast<uint32_t*>(dest); - dest += sizeof(uint32_t) * m.size(); - - char *key_address = dest; - dest += sizeof(Key) * m.size(); - - // Traverse map. - typename std::map<Key, Value>::const_iterator iter; - int index = 0; - for (iter = m.begin(); iter != m.end(); ++iter, ++index) { - offsets[index] = static_cast<uint32_t>(dest - start_address); - key_address = key_serializer_.Write(iter->first, key_address); - dest = value_serializer_.Write(iter->second, dest); - } - return dest; -} - -template<typename Key, typename Value> -char *StdMapSerializer<Key, Value>::Serialize( - const std::map<Key, Value> &m, unsigned int *size) const { - // Compute size of memory to be allocated. - unsigned int size_to_alloc = SizeOf(m); - // Allocate memory. - char *serialized_data = new char[size_to_alloc]; - if (!serialized_data) { - BPLOG(INFO) << "StdMapSerializer memory allocation failed."; - if (size) *size = 0; - return NULL; - } - // Write serialized data into memory. - Write(m, serialized_data); - - if (size) *size = size_to_alloc; - return serialized_data; -} - -template<typename Address, typename Entry> -size_t RangeMapSerializer<Address, Entry>::SizeOf( - const RangeMap<Address, Entry> &m) const { - size_t size = 0; - size_t header_size = (1 + m.map_.size()) * sizeof(uint32_t); - size += header_size; - - typename std::map<Address, Range>::const_iterator iter; - for (iter = m.map_.begin(); iter != m.map_.end(); ++iter) { - // Size of key (high address). - size += address_serializer_.SizeOf(iter->first); - // Size of base (low address). - size += address_serializer_.SizeOf(iter->second.base()); - // Size of entry. - size += entry_serializer_.SizeOf(iter->second.entry()); - } - return size; -} - -template<typename Address, typename Entry> -char *RangeMapSerializer<Address, Entry>::Write( - const RangeMap<Address, Entry> &m, char *dest) const { - if (!dest) { - BPLOG(ERROR) << "RangeMapSerializer failed: write to NULL address."; - return NULL; - } - char *start_address = dest; - - // Write header: - // Number of nodes. - dest = SimpleSerializer<uint32_t>::Write(m.map_.size(), dest); - // Nodes offsets. - uint32_t *offsets = reinterpret_cast<uint32_t*>(dest); - dest += sizeof(uint32_t) * m.map_.size(); - - char *key_address = dest; - dest += sizeof(Address) * m.map_.size(); - - // Traverse map. - typename std::map<Address, Range>::const_iterator iter; - int index = 0; - for (iter = m.map_.begin(); iter != m.map_.end(); ++iter, ++index) { - offsets[index] = static_cast<uint32_t>(dest - start_address); - key_address = address_serializer_.Write(iter->first, key_address); - dest = address_serializer_.Write(iter->second.base(), dest); - dest = entry_serializer_.Write(iter->second.entry(), dest); - } - return dest; -} - -template<typename Address, typename Entry> -char *RangeMapSerializer<Address, Entry>::Serialize( - const RangeMap<Address, Entry> &m, unsigned int *size) const { - // Compute size of memory to be allocated. - unsigned int size_to_alloc = SizeOf(m); - // Allocate memory. - char *serialized_data = new char[size_to_alloc]; - if (!serialized_data) { - BPLOG(INFO) << "RangeMapSerializer memory allocation failed."; - if (size) *size = 0; - return NULL; - } - - // Write serialized data into memory. - Write(m, serialized_data); - - if (size) *size = size_to_alloc; - return serialized_data; -} - - -template<class AddrType, class EntryType> -size_t ContainedRangeMapSerializer<AddrType, EntryType>::SizeOf( - const ContainedRangeMap<AddrType, EntryType> *m) const { - size_t size = 0; - size_t header_size = addr_serializer_.SizeOf(m->base_) - + entry_serializer_.SizeOf(m->entry_) - + sizeof(uint32_t); - size += header_size; - // In case m.map_ == NULL, we treat it as an empty map: - size += sizeof(uint32_t); - if (m->map_) { - size += m->map_->size() * sizeof(uint32_t); - typename Map::const_iterator iter; - for (iter = m->map_->begin(); iter != m->map_->end(); ++iter) { - size += addr_serializer_.SizeOf(iter->first); - // Recursive calculation of size: - size += SizeOf(iter->second); - } - } - return size; -} - -template<class AddrType, class EntryType> -char *ContainedRangeMapSerializer<AddrType, EntryType>::Write( - const ContainedRangeMap<AddrType, EntryType> *m, char *dest) const { - if (!dest) { - BPLOG(ERROR) << "StdMapSerializer failed: write to NULL address."; - return NULL; - } - dest = addr_serializer_.Write(m->base_, dest); - dest = SimpleSerializer<uint32_t>::Write(entry_serializer_.SizeOf(m->entry_), - dest); - dest = entry_serializer_.Write(m->entry_, dest); - - // Write map<<AddrType, ContainedRangeMap*>: - char *map_address = dest; - if (m->map_ == NULL) { - dest = SimpleSerializer<uint32_t>::Write(0, dest); - } else { - dest = SimpleSerializer<uint32_t>::Write(m->map_->size(), dest); - uint32_t *offsets = reinterpret_cast<uint32_t*>(dest); - dest += sizeof(uint32_t) * m->map_->size(); - - char *key_address = dest; - dest += sizeof(AddrType) * m->map_->size(); - - // Traverse map. - typename Map::const_iterator iter; - int index = 0; - for (iter = m->map_->begin(); iter != m->map_->end(); ++iter, ++index) { - offsets[index] = static_cast<uint32_t>(dest - map_address); - key_address = addr_serializer_.Write(iter->first, key_address); - // Recursively write. - dest = Write(iter->second, dest); - } - } - return dest; -} - -template<class AddrType, class EntryType> -char *ContainedRangeMapSerializer<AddrType, EntryType>::Serialize( - const ContainedRangeMap<AddrType, EntryType> *m, unsigned int *size) const { - unsigned int size_to_alloc = SizeOf(m); - // Allocating memory. - char *serialized_data = new char[size_to_alloc]; - if (!serialized_data) { - BPLOG(INFO) << "ContainedRangeMapSerializer memory allocation failed."; - if (size) *size = 0; - return NULL; - } - Write(m, serialized_data); - if (size) *size = size_to_alloc; - return serialized_data; -} - -} // namespace google_breakpad - -#endif // PROCESSOR_MAP_SERIALIZERS_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/map_serializers.h b/toolkit/crashreporter/google-breakpad/src/processor/map_serializers.h deleted file mode 100644 index a0b9d3fd6..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/map_serializers.h +++ /dev/null @@ -1,168 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// map_serializers.h: defines templates for serializing std::map and its -// wrappers: AddressMap, RangeMap, and ContainedRangeMap. -// -// Author: Siyang Xie (lambxsy@google.com) - - -#ifndef PROCESSOR_MAP_SERIALIZERS_H__ -#define PROCESSOR_MAP_SERIALIZERS_H__ - -#include <map> -#include <string> - -#include "processor/simple_serializer.h" - -#include "processor/address_map-inl.h" -#include "processor/range_map-inl.h" -#include "processor/contained_range_map-inl.h" - -namespace google_breakpad { - -// StdMapSerializer allocates memory and serializes an std::map instance into a -// chunk of memory data. -template<typename Key, typename Value> -class StdMapSerializer { - public: - // Calculate the memory size of serialized data. - size_t SizeOf(const std::map<Key, Value> &m) const; - - // Writes the serialized data to memory with start address = dest, - // and returns the "end" of data, i.e., return the address follow the final - // byte of data. - // NOTE: caller has to allocate enough memory before invoke Write() method. - char* Write(const std::map<Key, Value> &m, char* dest) const; - - // Serializes a std::map object into a chunk of memory data with format - // described in "StaticMap.h" comment. - // Returns a pointer to the serialized data. If size != NULL, *size is set - // to the size of serialized data, i.e., SizeOf(m). - // Caller has the ownership of memory allocated as "new char[]". - char* Serialize(const std::map<Key, Value> &m, unsigned int *size) const; - - private: - SimpleSerializer<Key> key_serializer_; - SimpleSerializer<Value> value_serializer_; -}; - -// AddressMapSerializer allocates memory and serializes an AddressMap into a -// chunk of memory data. -template<typename Addr, typename Entry> -class AddressMapSerializer { - public: - // Calculate the memory size of serialized data. - size_t SizeOf(const AddressMap<Addr, Entry> &m) const { - return std_map_serializer_.SizeOf(m.map_); - } - - // Write the serialized data to specified memory location. Return the "end" - // of data, i.e., return the address after the final byte of data. - // NOTE: caller has to allocate enough memory before invoke Write() method. - char* Write(const AddressMap<Addr, Entry> &m, char *dest) const { - return std_map_serializer_.Write(m.map_, dest); - } - - // Serializes an AddressMap object into a chunk of memory data. - // Returns a pointer to the serialized data. If size != NULL, *size is set - // to the size of serialized data, i.e., SizeOf(m). - // Caller has the ownership of memory allocated as "new char[]". - char* Serialize(const AddressMap<Addr, Entry> &m, unsigned int *size) const { - return std_map_serializer_.Serialize(m.map_, size); - } - - private: - // AddressMapSerializer is a simple wrapper of StdMapSerializer, just as - // AddressMap is a simple wrapper of std::map. - StdMapSerializer<Addr, Entry> std_map_serializer_; -}; - -// RangeMapSerializer allocates memory and serializes a RangeMap instance into a -// chunk of memory data. -template<typename Address, typename Entry> -class RangeMapSerializer { - public: - // Calculate the memory size of serialized data. - size_t SizeOf(const RangeMap<Address, Entry> &m) const; - - // Write the serialized data to specified memory location. Return the "end" - // of data, i.e., return the address after the final byte of data. - // NOTE: caller has to allocate enough memory before invoke Write() method. - char* Write(const RangeMap<Address, Entry> &m, char* dest) const; - - // Serializes a RangeMap object into a chunk of memory data. - // Returns a pointer to the serialized data. If size != NULL, *size is set - // to the size of serialized data, i.e., SizeOf(m). - // Caller has the ownership of memory allocated as "new char[]". - char* Serialize(const RangeMap<Address, Entry> &m, unsigned int *size) const; - - private: - // Convenient type name for Range. - typedef typename RangeMap<Address, Entry>::Range Range; - - // Serializer for RangeMap's key and Range::base_. - SimpleSerializer<Address> address_serializer_; - // Serializer for RangeMap::Range::entry_. - SimpleSerializer<Entry> entry_serializer_; -}; - -// ContainedRangeMapSerializer allocates memory and serializes a -// ContainedRangeMap instance into a chunk of memory data. -template<class AddrType, class EntryType> -class ContainedRangeMapSerializer { - public: - // Calculate the memory size of serialized data. - size_t SizeOf(const ContainedRangeMap<AddrType, EntryType> *m) const; - - // Write the serialized data to specified memory location. Return the "end" - // of data, i.e., return the address after the final byte of data. - // NOTE: caller has to allocate enough memory before invoke Write() method. - char* Write(const ContainedRangeMap<AddrType, EntryType> *m, - char* dest) const; - - // Serializes a ContainedRangeMap object into a chunk of memory data. - // Returns a pointer to the serialized data. If size != NULL, *size is set - // to the size of serialized data, i.e., SizeOf(m). - // Caller has the ownership of memory allocated as "new char[]". - char* Serialize(const ContainedRangeMap<AddrType, EntryType> *m, - unsigned int *size) const; - - private: - // Convenient type name for the underlying map type. - typedef std::map<AddrType, ContainedRangeMap<AddrType, EntryType>*> Map; - - // Serializer for addresses and entries stored in ContainedRangeMap. - SimpleSerializer<AddrType> addr_serializer_; - SimpleSerializer<EntryType> entry_serializer_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_MAP_SERIALIZERS_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/map_serializers_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/map_serializers_unittest.cc deleted file mode 100644 index 0d872ec2e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/map_serializers_unittest.cc +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// map_serializers_unittest.cc: Unit tests for std::map serializer and -// std::map wrapper serializers. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include <climits> -#include <map> -#include <string> -#include <utility> -#include <iostream> -#include <sstream> - -#include "breakpad_googletest_includes.h" -#include "map_serializers-inl.h" - -#include "processor/address_map-inl.h" -#include "processor/range_map-inl.h" -#include "processor/contained_range_map-inl.h" - -typedef int32_t AddrType; -typedef int32_t EntryType; - -class TestStdMapSerializer : public ::testing::Test { - protected: - void SetUp() { - serialized_size_ = 0; - serialized_data_ = NULL; - } - - void TearDown() { - delete [] serialized_data_; - } - - std::map<AddrType, EntryType> std_map_; - google_breakpad::StdMapSerializer<AddrType, EntryType> serializer_; - uint32_t serialized_size_; - char *serialized_data_; -}; - -TEST_F(TestStdMapSerializer, EmptyMapTestCase) { - const int32_t correct_data[] = { 0 }; - uint32_t correct_size = sizeof(correct_data); - - // std_map_ is empty. - serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - -TEST_F(TestStdMapSerializer, MapWithTwoElementsTestCase) { - const int32_t correct_data[] = { - // # of nodes - 2, - // Offsets - 20, 24, - // Keys - 1, 3, - // Values - 2, 6 - }; - uint32_t correct_size = sizeof(correct_data); - - std_map_.insert(std::make_pair(1, 2)); - std_map_.insert(std::make_pair(3, 6)); - - serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - -TEST_F(TestStdMapSerializer, MapWithFiveElementsTestCase) { - const int32_t correct_data[] = { - // # of nodes - 5, - // Offsets - 44, 48, 52, 56, 60, - // Keys - 1, 2, 3, 4, 5, - // Values - 11, 12, 13, 14, 15 - }; - uint32_t correct_size = sizeof(correct_data); - - for (int i = 1; i < 6; ++i) - std_map_.insert(std::make_pair(i, 10 + i)); - - serialized_data_ = serializer_.Serialize(std_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - -class TestAddressMapSerializer : public ::testing::Test { - protected: - void SetUp() { - serialized_size_ = 0; - serialized_data_ = 0; - } - - void TearDown() { - delete [] serialized_data_; - } - - google_breakpad::AddressMap<AddrType, EntryType> address_map_; - google_breakpad::AddressMapSerializer<AddrType, EntryType> serializer_; - uint32_t serialized_size_; - char *serialized_data_; -}; - -TEST_F(TestAddressMapSerializer, EmptyMapTestCase) { - const int32_t correct_data[] = { 0 }; - uint32_t correct_size = sizeof(correct_data); - - // std_map_ is empty. - serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - -TEST_F(TestAddressMapSerializer, MapWithTwoElementsTestCase) { - const int32_t correct_data[] = { - // # of nodes - 2, - // Offsets - 20, 24, - // Keys - 1, 3, - // Values - 2, 6 - }; - uint32_t correct_size = sizeof(correct_data); - - address_map_.Store(1, 2); - address_map_.Store(3, 6); - - serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - -TEST_F(TestAddressMapSerializer, MapWithFourElementsTestCase) { - const int32_t correct_data[] = { - // # of nodes - 4, - // Offsets - 36, 40, 44, 48, - // Keys - -6, -4, 8, 123, - // Values - 2, 3, 5, 8 - }; - uint32_t correct_size = sizeof(correct_data); - - address_map_.Store(-6, 2); - address_map_.Store(-4, 3); - address_map_.Store(8, 5); - address_map_.Store(123, 8); - - serialized_data_ = serializer_.Serialize(address_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - - -class TestRangeMapSerializer : public ::testing::Test { - protected: - void SetUp() { - serialized_size_ = 0; - serialized_data_ = 0; - } - - void TearDown() { - delete [] serialized_data_; - } - - google_breakpad::RangeMap<AddrType, EntryType> range_map_; - google_breakpad::RangeMapSerializer<AddrType, EntryType> serializer_; - uint32_t serialized_size_; - char *serialized_data_; -}; - -TEST_F(TestRangeMapSerializer, EmptyMapTestCase) { - const int32_t correct_data[] = { 0 }; - uint32_t correct_size = sizeof(correct_data); - - // range_map_ is empty. - serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - -TEST_F(TestRangeMapSerializer, MapWithOneRangeTestCase) { - const int32_t correct_data[] = { - // # of nodes - 1, - // Offsets - 12, - // Keys: high address - 10, - // Values: (low address, entry) pairs - 1, 6 - }; - uint32_t correct_size = sizeof(correct_data); - - range_map_.StoreRange(1, 10, 6); - - serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - -TEST_F(TestRangeMapSerializer, MapWithThreeRangesTestCase) { - const int32_t correct_data[] = { - // # of nodes - 3, - // Offsets - 28, 36, 44, - // Keys: high address - 5, 9, 20, - // Values: (low address, entry) pairs - 2, 1, 6, 2, 10, 3 - }; - uint32_t correct_size = sizeof(correct_data); - - ASSERT_TRUE(range_map_.StoreRange(2, 4, 1)); - ASSERT_TRUE(range_map_.StoreRange(6, 4, 2)); - ASSERT_TRUE(range_map_.StoreRange(10, 11, 3)); - - serialized_data_ = serializer_.Serialize(range_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - - -class TestContainedRangeMapSerializer : public ::testing::Test { - protected: - void SetUp() { - serialized_size_ = 0; - serialized_data_ = 0; - } - - void TearDown() { - delete [] serialized_data_; - } - - google_breakpad::ContainedRangeMap<AddrType, EntryType> crm_map_; - google_breakpad::ContainedRangeMapSerializer<AddrType, EntryType> serializer_; - uint32_t serialized_size_; - char *serialized_data_; -}; - -TEST_F(TestContainedRangeMapSerializer, EmptyMapTestCase) { - const int32_t correct_data[] = { - 0, // base address of root - 4, // size of entry - 0, // entry stored at root - 0 // empty map stored at root - }; - uint32_t correct_size = sizeof(correct_data); - - // crm_map_ is empty. - serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - -TEST_F(TestContainedRangeMapSerializer, MapWithOneRangeTestCase) { - const int32_t correct_data[] = { - 0, // base address of root - 4, // size of entry - 0, // entry stored at root - // Map stored at root node: - 1, // # of nodes - 12, // offset - 9, // key - // value: a child ContainedRangeMap - 3, // base address of child CRM - 4, // size of entry - -1, // entry stored in child CRM - 0 // empty sub-map stored in child CRM - }; - uint32_t correct_size = sizeof(correct_data); - - crm_map_.StoreRange(3, 7, -1); - - serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - -TEST_F(TestContainedRangeMapSerializer, MapWithTwoLevelsTestCase) { - // Tree structure of ranges: - // root level 0 - // | - // map - // / \ level 1: child1, child2 - // 2~8 10~20 - // | | - // map map - // / \ | - // 3~4 6~7 16-20 level 2: grandchild1, grandchild2, grandchild3 - - const int32_t correct_data[] = { - // root: base, entry_size, entry - 0, 4, 0, - // root's map: # of nodes, offset1, offset2, key1, key2 - 2, 20, 84, 8, 20, - // child1: base, entry_size, entry: - 2, 4, -1, - // child1's map: # of nodes, offset1, offset2, key1, key2 - 2, 20, 36, 4, 7, - // grandchild1: base, entry_size, entry, empty_map - 3, 4, -1, 0, - // grandchild2: base, entry_size, entry, empty_map - 6, 4, -1, 0, - // child2: base, entry_size, entry: - 10, 4, -1, - // child2's map: # of nodes, offset1, key1 - 1, 12, 20, - // grandchild3: base, entry_size, entry, empty_map - 16, 4, -1, 0 - }; - uint32_t correct_size = sizeof(correct_data); - - // Store child1. - ASSERT_TRUE(crm_map_.StoreRange(2, 7, -1)); - // Store child2. - ASSERT_TRUE(crm_map_.StoreRange(10, 11, -1)); - // Store grandchild1. - ASSERT_TRUE(crm_map_.StoreRange(3, 2, -1)); - // Store grandchild2. - ASSERT_TRUE(crm_map_.StoreRange(6, 2, -1)); - // Store grandchild3. - ASSERT_TRUE(crm_map_.StoreRange(16, 5, -1)); - - serialized_data_ = serializer_.Serialize(&crm_map_, &serialized_size_); - - EXPECT_EQ(correct_size, serialized_size_); - EXPECT_EQ(memcmp(correct_data, serialized_data_, correct_size), 0); -} - - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump.cc b/toolkit/crashreporter/google-breakpad/src/processor/microdump.cc deleted file mode 100644 index 4af62f56f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/microdump.cc +++ /dev/null @@ -1,385 +0,0 @@ -// Copyright (c) 2014 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// microdump.cc: A microdump reader. -// -// See microdump.h for documentation. - -#include "google_breakpad/processor/microdump.h" - -#include <stdio.h> -#include <string.h> - -#include <memory> -#include <sstream> -#include <string> -#include <vector> - -#include "google_breakpad/common/minidump_cpu_arm.h" -#include "google_breakpad/processor/code_module.h" -#include "processor/basic_code_module.h" -#include "processor/linked_ptr.h" -#include "processor/logging.h" -#include "processor/range_map-inl.h" - -namespace { -static const char kGoogleBreakpadKey[] = "google-breakpad"; -static const char kMicrodumpBegin[] = "-----BEGIN BREAKPAD MICRODUMP-----"; -static const char kMicrodumpEnd[] = "-----END BREAKPAD MICRODUMP-----"; -static const char kOsKey[] = ": O "; -static const char kCpuKey[] = ": C "; -static const char kGpuKey[] = ": G "; -static const char kMmapKey[] = ": M "; -static const char kStackKey[] = ": S "; -static const char kStackFirstLineKey[] = ": S 0 "; -static const char kArmArchitecture[] = "arm"; -static const char kArm64Architecture[] = "arm64"; -static const char kX86Architecture[] = "x86"; -static const char kMipsArchitecture[] = "mips"; -static const char kMips64Architecture[] = "mips64"; -static const char kGpuUnknown[] = "UNKNOWN"; - -template<typename T> -T HexStrToL(const string& str) { - uint64_t res = 0; - std::istringstream ss(str); - ss >> std::hex >> res; - return static_cast<T>(res); -} - -std::vector<uint8_t> ParseHexBuf(const string& str) { - std::vector<uint8_t> buf; - for (size_t i = 0; i < str.length(); i += 2) { - buf.push_back(HexStrToL<uint8_t>(str.substr(i, 2))); - } - return buf; -} - -bool GetLine(std::istringstream* istream, string* str) { - if (std::getline(*istream, *str)) { - // Trim any trailing newline from the end of the line. Allows us - // to seamlessly handle both Windows/DOS and Unix formatted input. The - // adb tool generally writes logcat dumps in Windows/DOS format. - if (!str->empty() && str->at(str->size() - 1) == '\r') { - str->erase(str->size() - 1); - } - return true; - } - return false; -} - -} // namespace - -namespace google_breakpad { - -// -// MicrodumpModules -// - -void MicrodumpModules::Add(const CodeModule* module) { - linked_ptr<const CodeModule> module_ptr(module); - if (!map_.StoreRange(module->base_address(), module->size(), module_ptr)) { - BPLOG(ERROR) << "Module " << module->code_file() << - " could not be stored"; - } -} - -void MicrodumpModules::SetEnableModuleShrink(bool is_enabled) { - map_.SetEnableShrinkDown(is_enabled); -} - -// -// MicrodumpContext -// - -void MicrodumpContext::SetContextARM(MDRawContextARM* arm) { - DumpContext::SetContextFlags(MD_CONTEXT_ARM); - DumpContext::SetContextARM(arm); - valid_ = true; -} - -void MicrodumpContext::SetContextARM64(MDRawContextARM64* arm64) { - DumpContext::SetContextFlags(MD_CONTEXT_ARM64); - DumpContext::SetContextARM64(arm64); - valid_ = true; -} - -void MicrodumpContext::SetContextX86(MDRawContextX86* x86) { - DumpContext::SetContextFlags(MD_CONTEXT_X86); - DumpContext::SetContextX86(x86); - valid_ = true; -} - -void MicrodumpContext::SetContextMIPS(MDRawContextMIPS* mips32) { - DumpContext::SetContextFlags(MD_CONTEXT_MIPS); - DumpContext::SetContextMIPS(mips32); - valid_ = true; -} - -void MicrodumpContext::SetContextMIPS64(MDRawContextMIPS* mips64) { - DumpContext::SetContextFlags(MD_CONTEXT_MIPS64); - DumpContext::SetContextMIPS(mips64); - valid_ = true; -} - - -// -// MicrodumpMemoryRegion -// - -MicrodumpMemoryRegion::MicrodumpMemoryRegion() : base_address_(0) { } - -void MicrodumpMemoryRegion::Init(uint64_t base_address, - const std::vector<uint8_t>& contents) { - base_address_ = base_address; - contents_ = contents; -} - -uint64_t MicrodumpMemoryRegion::GetBase() const { return base_address_; } - -uint32_t MicrodumpMemoryRegion::GetSize() const { return contents_.size(); } - -bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address, - uint8_t* value) const { - return GetMemoryLittleEndian(address, value); -} - -bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address, - uint16_t* value) const { - return GetMemoryLittleEndian(address, value); -} - -bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address, - uint32_t* value) const { - return GetMemoryLittleEndian(address, value); -} - -bool MicrodumpMemoryRegion::GetMemoryAtAddress(uint64_t address, - uint64_t* value) const { - return GetMemoryLittleEndian(address, value); -} - -template<typename ValueType> -bool MicrodumpMemoryRegion::GetMemoryLittleEndian(uint64_t address, - ValueType* value) const { - if (address < base_address_ || - address - base_address_ + sizeof(ValueType) > contents_.size()) - return false; - ValueType v = 0; - uint64_t start = address - base_address_; - // The loop condition is odd, but it's correct for size_t. - for (size_t i = sizeof(ValueType) - 1; i < sizeof(ValueType); i--) - v = (v << 8) | static_cast<uint8_t>(contents_[start + i]); - *value = v; - return true; -} - -void MicrodumpMemoryRegion::Print() const { - // Not reached, just needed to honor the base class contract. - assert(false); -} - -// -// Microdump -// -Microdump::Microdump(const string& contents) - : context_(new MicrodumpContext()), - stack_region_(new MicrodumpMemoryRegion()), - modules_(new MicrodumpModules()), - system_info_(new SystemInfo()) { - assert(!contents.empty()); - - bool in_microdump = false; - string line; - uint64_t stack_start = 0; - std::vector<uint8_t> stack_content; - string arch; - - std::istringstream stream(contents); - while (GetLine(&stream, &line)) { - if (line.find(kGoogleBreakpadKey) == string::npos) { - continue; - } - if (line.find(kMicrodumpBegin) != string::npos) { - in_microdump = true; - continue; - } - if (!in_microdump) { - continue; - } - if (line.find(kMicrodumpEnd) != string::npos) { - break; - } - - size_t pos; - if ((pos = line.find(kOsKey)) != string::npos) { - string os_str(line, pos + strlen(kOsKey)); - std::istringstream os_tokens(os_str); - string os_id; - string num_cpus; - string os_version; - // This reflect the actual HW arch and might not match the arch emulated - // for the execution (e.g., running a 32-bit binary on a 64-bit cpu). - string hw_arch; - - os_tokens >> os_id; - os_tokens >> arch; - os_tokens >> num_cpus; - os_tokens >> hw_arch; - GetLine(&os_tokens, &os_version); - os_version.erase(0, 1); // remove leading space. - - system_info_->cpu = arch; - system_info_->cpu_count = HexStrToL<uint8_t>(num_cpus); - system_info_->os_version = os_version; - - if (os_id == "L") { - system_info_->os = "Linux"; - system_info_->os_short = "linux"; - } else if (os_id == "A") { - system_info_->os = "Android"; - system_info_->os_short = "android"; - modules_->SetEnableModuleShrink(true); - } - - // OS line also contains release and version for future use. - } else if ((pos = line.find(kStackKey)) != string::npos) { - if (line.find(kStackFirstLineKey) != string::npos) { - // The first line of the stack (S 0 stack header) provides the value of - // the stack pointer, the start address of the stack being dumped and - // the length of the stack. We could use it in future to double check - // that we received all the stack as expected. - continue; - } - string stack_str(line, pos + strlen(kStackKey)); - std::istringstream stack_tokens(stack_str); - string start_addr_str; - string raw_content; - stack_tokens >> start_addr_str; - stack_tokens >> raw_content; - uint64_t start_addr = HexStrToL<uint64_t>(start_addr_str); - - if (stack_start != 0) { - // Verify that the stack chunks in the microdump are contiguous. - assert(start_addr == stack_start + stack_content.size()); - } else { - stack_start = start_addr; - } - std::vector<uint8_t> chunk = ParseHexBuf(raw_content); - stack_content.insert(stack_content.end(), chunk.begin(), chunk.end()); - - } else if ((pos = line.find(kCpuKey)) != string::npos) { - string cpu_state_str(line, pos + strlen(kCpuKey)); - std::vector<uint8_t> cpu_state_raw = ParseHexBuf(cpu_state_str); - if (strcmp(arch.c_str(), kArmArchitecture) == 0) { - if (cpu_state_raw.size() != sizeof(MDRawContextARM)) { - std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() - << " bytes instead of " << sizeof(MDRawContextARM) - << std::endl; - continue; - } - MDRawContextARM* arm = new MDRawContextARM(); - memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size()); - context_->SetContextARM(arm); - } else if (strcmp(arch.c_str(), kArm64Architecture) == 0) { - if (cpu_state_raw.size() != sizeof(MDRawContextARM64)) { - std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() - << " bytes instead of " << sizeof(MDRawContextARM64) - << std::endl; - continue; - } - MDRawContextARM64* arm = new MDRawContextARM64(); - memcpy(arm, &cpu_state_raw[0], cpu_state_raw.size()); - context_->SetContextARM64(arm); - } else if (strcmp(arch.c_str(), kX86Architecture) == 0) { - if (cpu_state_raw.size() != sizeof(MDRawContextX86)) { - std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() - << " bytes instead of " << sizeof(MDRawContextX86) - << std::endl; - continue; - } - MDRawContextX86* x86 = new MDRawContextX86(); - memcpy(x86, &cpu_state_raw[0], cpu_state_raw.size()); - context_->SetContextX86(x86); - } else if (strcmp(arch.c_str(), kMipsArchitecture) == 0) { - if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) { - std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() - << " bytes instead of " << sizeof(MDRawContextMIPS) - << std::endl; - continue; - } - MDRawContextMIPS* mips32 = new MDRawContextMIPS(); - memcpy(mips32, &cpu_state_raw[0], cpu_state_raw.size()); - context_->SetContextMIPS(mips32); - } else if (strcmp(arch.c_str(), kMips64Architecture) == 0) { - if (cpu_state_raw.size() != sizeof(MDRawContextMIPS)) { - std::cerr << "Malformed CPU context. Got " << cpu_state_raw.size() - << " bytes instead of " << sizeof(MDRawContextMIPS) - << std::endl; - continue; - } - MDRawContextMIPS* mips64 = new MDRawContextMIPS(); - memcpy(mips64, &cpu_state_raw[0], cpu_state_raw.size()); - context_->SetContextMIPS64(mips64); - } else { - std::cerr << "Unsupported architecture: " << arch << std::endl; - } - } else if ((pos = line.find(kGpuKey)) != string::npos) { - string gpu_str(line, pos + strlen(kGpuKey)); - if (strcmp(gpu_str.c_str(), kGpuUnknown) != 0) { - std::istringstream gpu_tokens(gpu_str); - std::getline(gpu_tokens, system_info_->gl_version, '|'); - std::getline(gpu_tokens, system_info_->gl_vendor, '|'); - std::getline(gpu_tokens, system_info_->gl_renderer, '|'); - } - } else if ((pos = line.find(kMmapKey)) != string::npos) { - string mmap_line(line, pos + strlen(kMmapKey)); - std::istringstream mmap_tokens(mmap_line); - string addr, offset, size, identifier, filename; - mmap_tokens >> addr; - mmap_tokens >> offset; - mmap_tokens >> size; - mmap_tokens >> identifier; - mmap_tokens >> filename; - - modules_->Add(new BasicCodeModule( - HexStrToL<uint64_t>(addr), // base_address - HexStrToL<uint64_t>(size), // size - filename, // code_file - identifier, // code_identifier - filename, // debug_file - identifier, // debug_identifier - "")); // version - } - } - stack_region_->Init(stack_start, stack_content); -} - -} // namespace google_breakpad - diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor.cc b/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor.cc deleted file mode 100644 index 366e3f30a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor.cc +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) 2014, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// microdump_processor.cc: A microdump processor. -// -// See microdump_processor.h for documentation. - -#include "google_breakpad/processor/microdump_processor.h" - -#include <assert.h> - -#include <string> - -#include "common/using_std_string.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/microdump.h" -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/stackwalker.h" -#include "google_breakpad/processor/stack_frame_symbolizer.h" -#include "processor/logging.h" - -namespace google_breakpad { - -MicrodumpProcessor::MicrodumpProcessor(StackFrameSymbolizer* frame_symbolizer) - : frame_symbolizer_(frame_symbolizer) { - assert(frame_symbolizer); -} - -MicrodumpProcessor::~MicrodumpProcessor() {} - -ProcessResult MicrodumpProcessor::Process(const string µdump_contents, - ProcessState* process_state) { - assert(process_state); - - process_state->Clear(); - - if (microdump_contents.empty()) { - BPLOG(ERROR) << "Microdump is empty."; - return PROCESS_ERROR_MINIDUMP_NOT_FOUND; - } - - Microdump microdump(microdump_contents); - process_state->modules_ = microdump.GetModules()->Copy(); - scoped_ptr<Stackwalker> stackwalker( - Stackwalker::StackwalkerForCPU( - &process_state->system_info_, - microdump.GetContext(), - microdump.GetMemory(), - process_state->modules_, - frame_symbolizer_)); - - scoped_ptr<CallStack> stack(new CallStack()); - if (stackwalker.get()) { - if (!stackwalker->Walk(stack.get(), - &process_state->modules_without_symbols_, - &process_state->modules_with_corrupt_symbols_)) { - BPLOG(INFO) << "Processing was interrupted."; - return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED; - } - } else { - BPLOG(ERROR) << "No stackwalker found for microdump."; - return PROCESS_ERROR_NO_THREAD_LIST; - } - - process_state->threads_.push_back(stack.release()); - process_state->thread_memory_regions_.push_back(microdump.GetMemory()); - process_state->crashed_ = true; - process_state->requesting_thread_ = 0; - process_state->system_info_ = *microdump.GetSystemInfo(); - - return PROCESS_OK; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor_unittest.cc deleted file mode 100644 index af897f7da..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/microdump_processor_unittest.cc +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright (c) 2014, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Unit test for MicrodumpProcessor. - -#include <fstream> -#include <iostream> -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/microdump_processor.h" -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/stack_frame.h" -#include "google_breakpad/processor/stack_frame_symbolizer.h" -#include "processor/simple_symbol_supplier.h" -#include "processor/stackwalker_unittest_utils.h" - -namespace { - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::MicrodumpProcessor; -using google_breakpad::ProcessState; -using google_breakpad::SimpleSymbolSupplier; -using google_breakpad::StackFrameSymbolizer; - -class MicrodumpProcessorTest : public ::testing::Test { - public: - MicrodumpProcessorTest() - : files_path_(string(getenv("srcdir") ? getenv("srcdir") : ".") + - "/src/processor/testdata/") { - } - - void ReadFile(const string& file_name, string* file_contents) { - assert(file_contents); - std::ifstream file_stream(file_name.c_str(), std::ios::in); - ASSERT_TRUE(file_stream.good()); - std::vector<char> bytes; - file_stream.seekg(0, std::ios_base::end); - ASSERT_TRUE(file_stream.good()); - bytes.resize(file_stream.tellg()); - file_stream.seekg(0, std::ios_base::beg); - ASSERT_TRUE(file_stream.good()); - file_stream.read(&bytes[0], bytes.size()); - ASSERT_TRUE(file_stream.good()); - *file_contents = string(&bytes[0], bytes.size()); - } - - google_breakpad::ProcessResult ProcessMicrodump( - const string& symbols_file, - const string& microdump_contents, - ProcessState* state) { - SimpleSymbolSupplier supplier(symbols_file); - BasicSourceLineResolver resolver; - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - MicrodumpProcessor processor(&frame_symbolizer); - - return processor.Process(microdump_contents, state); - } - - void AnalyzeDump(const string& microdump_file_name, bool omit_symbols, - int expected_cpu_count, ProcessState* state) { - string symbols_file = omit_symbols ? "" : files_path_ + "symbols/microdump"; - string microdump_file_path = files_path_ + microdump_file_name; - string microdump_contents; - ReadFile(microdump_file_path, µdump_contents); - - google_breakpad::ProcessResult result = - ProcessMicrodump(symbols_file, microdump_contents, state); - - ASSERT_EQ(google_breakpad::PROCESS_OK, result); - ASSERT_TRUE(state->crashed()); - ASSERT_EQ(0, state->requesting_thread()); - ASSERT_EQ(1U, state->threads()->size()); - - ASSERT_EQ(expected_cpu_count, state->system_info()->cpu_count); - ASSERT_EQ("android", state->system_info()->os_short); - ASSERT_EQ("Android", state->system_info()->os); - } - - string files_path_; -}; - -TEST_F(MicrodumpProcessorTest, TestProcess_Empty) { - ProcessState state; - google_breakpad::ProcessResult result = - ProcessMicrodump("", "", &state); - ASSERT_EQ(google_breakpad::PROCESS_ERROR_MINIDUMP_NOT_FOUND, result); -} - -TEST_F(MicrodumpProcessorTest, TestProcess_Invalid) { - ProcessState state; - google_breakpad::ProcessResult result = - ProcessMicrodump("", "This is not a valid microdump", &state); - ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result); -} - -TEST_F(MicrodumpProcessorTest, TestProcess_MissingSymbols) { - ProcessState state; - AnalyzeDump("microdump-arm64.dmp", true /* omit_symbols */, - 2 /* expected_cpu_count */, &state); - - ASSERT_EQ(8U, state.modules()->module_count()); - ASSERT_EQ("arm64", state.system_info()->cpu); - ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version); - ASSERT_EQ(1U, state.threads()->size()); - ASSERT_EQ(12U, state.threads()->at(0)->frames()->size()); - - ASSERT_EQ("", - state.threads()->at(0)->frames()->at(0)->function_name); - ASSERT_EQ("", - state.threads()->at(0)->frames()->at(3)->function_name); -} - -TEST_F(MicrodumpProcessorTest, TestProcess_UnsupportedArch) { - string microdump_contents = - "W/google-breakpad(26491): -----BEGIN BREAKPAD MICRODUMP-----\n" - "W/google-breakpad(26491): O A \"unsupported-arch\"\n" - "W/google-breakpad(26491): S 0 A48BD840 A48BD000 00002000\n"; - - ProcessState state; - - google_breakpad::ProcessResult result = - ProcessMicrodump("", microdump_contents, &state); - - ASSERT_EQ(google_breakpad::PROCESS_ERROR_NO_THREAD_LIST, result); -} - -TEST_F(MicrodumpProcessorTest, TestProcessArm) { - ProcessState state; - AnalyzeDump("microdump-arm.dmp", false /* omit_symbols */, - 2 /* expected_cpu_count*/, &state); - - ASSERT_EQ(6U, state.modules()->module_count()); - ASSERT_EQ("arm", state.system_info()->cpu); - ASSERT_EQ("OpenGL ES 3.0 V@104.0 AU@ (GIT@Id3510ff6dc)", - state.system_info()->gl_version); - ASSERT_EQ("Qualcomm", state.system_info()->gl_vendor); - ASSERT_EQ("Adreno (TM) 330", state.system_info()->gl_renderer); - ASSERT_EQ("OS VERSION INFO", state.system_info()->os_version); - ASSERT_EQ(8U, state.threads()->at(0)->frames()->size()); - ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody", - state.threads()->at(0)->frames()->at(0)->function_name); - ASSERT_EQ("testing::Test::Run", - state.threads()->at(0)->frames()->at(1)->function_name); - ASSERT_EQ("main", - state.threads()->at(0)->frames()->at(6)->function_name); - ASSERT_EQ("breakpad_unittests", - state.threads()->at(0)->frames()->at(6)->module->code_file()); -} - -TEST_F(MicrodumpProcessorTest, TestProcessArm64) { - ProcessState state; - AnalyzeDump("microdump-arm64.dmp", false /* omit_symbols */, - 2 /* expected_cpu_count*/, &state); - - ASSERT_EQ(8U, state.modules()->module_count()); - ASSERT_EQ("arm64", state.system_info()->cpu); - ASSERT_EQ("OS 64 VERSION INFO", state.system_info()->os_version); - ASSERT_EQ(9U, state.threads()->at(0)->frames()->size()); - ASSERT_EQ("MicrodumpWriterTest_Setup_Test::TestBody", - state.threads()->at(0)->frames()->at(0)->function_name); - ASSERT_EQ("testing::Test::Run", - state.threads()->at(0)->frames()->at(2)->function_name); - ASSERT_EQ("main", - state.threads()->at(0)->frames()->at(7)->function_name); - ASSERT_EQ("breakpad_unittests", - state.threads()->at(0)->frames()->at(7)->module->code_file()); -} - -TEST_F(MicrodumpProcessorTest, TestProcessX86) { - ProcessState state; - AnalyzeDump("microdump-x86.dmp", false /* omit_symbols */, - 4 /* expected_cpu_count */, &state); - - ASSERT_EQ(124U, state.modules()->module_count()); - ASSERT_EQ("x86", state.system_info()->cpu); - ASSERT_EQ("asus/WW_Z00A/Z00A:5.0/LRX21V/2.19.40.22_20150627_5104_user:user/" - "release-keys", state.system_info()->os_version); - ASSERT_EQ(56U, state.threads()->at(0)->frames()->size()); - ASSERT_EQ("libc.so", - state.threads()->at(0)->frames()->at(0)->module->debug_file()); - // TODO(mmandlis): Get symbols for the test X86 microdump and test function - // names. -} - -TEST_F(MicrodumpProcessorTest, TestProcessMultiple) { - ProcessState state; - AnalyzeDump("microdump-multiple.dmp", false /* omit_symbols */, - 6 /* expected_cpu_count */, &state); - ASSERT_EQ(156U, state.modules()->module_count()); - ASSERT_EQ("arm", state.system_info()->cpu); - ASSERT_EQ("lge/p1_tmo_us/p1:6.0/MRA58K/1603210524c8d:user/release-keys", - state.system_info()->os_version); - ASSERT_EQ(5U, state.threads()->at(0)->frames()->size()); -} - -TEST_F(MicrodumpProcessorTest, TestProcessMips) { - ProcessState state; - AnalyzeDump("microdump-mips32.dmp", false /* omit_symbols */, - 2 /* expected_cpu_count */, &state); - - ASSERT_EQ(7U, state.modules()->module_count()); - ASSERT_EQ("mips", state.system_info()->cpu); - ASSERT_EQ("3.0.8-g893bf16 #7 SMP PREEMPT Fri Jul 10 15:20:59 PDT 2015", - state.system_info()->os_version); - ASSERT_EQ(4U, state.threads()->at(0)->frames()->size()); - - ASSERT_EQ("blaTest", - state.threads()->at(0)->frames()->at(0)->function_name); - ASSERT_EQ("Crash", - state.threads()->at(0)->frames()->at(1)->function_name); - ASSERT_EQ("main", - state.threads()->at(0)->frames()->at(2)->function_name); - ASSERT_EQ("crash_example", - state.threads()->at(0)->frames()->at(0)->module->debug_file()); -} - -TEST_F(MicrodumpProcessorTest, TestProcessMips64) { - ProcessState state; - AnalyzeDump("microdump-mips64.dmp", false /* omit_symbols */, - 1 /* expected_cpu_count */, &state); - - ASSERT_EQ(8U, state.modules()->module_count()); - ASSERT_EQ("mips64", state.system_info()->cpu); - ASSERT_EQ("3.10.0-gf185e20 #112 PREEMPT Mon Oct 5 11:12:49 PDT 2015", - state.system_info()->os_version); - ASSERT_EQ(4U, state.threads()->at(0)->frames()->size()); - - ASSERT_EQ("blaTest", - state.threads()->at(0)->frames()->at(0)->function_name); - ASSERT_EQ("Crash", - state.threads()->at(0)->frames()->at(1)->function_name); - ASSERT_EQ("main", - state.threads()->at(0)->frames()->at(2)->function_name); - ASSERT_EQ("crash_example", - state.threads()->at(0)->frames()->at(0)->module->debug_file()); -} - -} // namespace - -int main(int argc, char* argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk.cc b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk.cc deleted file mode 100644 index 7ea80495a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk.cc +++ /dev/null @@ -1,151 +0,0 @@ -// Copyright (c) 2014 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// microdump_stackwalk.cc: Process a microdump with MicrodumpProcessor, printing -// the results, including stack traces. - -#include <stdio.h> -#include <string.h> - -#include <fstream> -#include <string> -#include <vector> - -#include "common/scoped_ptr.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/microdump_processor.h" -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/stack_frame_symbolizer.h" -#include "processor/logging.h" -#include "processor/simple_symbol_supplier.h" -#include "processor/stackwalk_common.h" - - -namespace { - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::MicrodumpProcessor; -using google_breakpad::ProcessResult; -using google_breakpad::ProcessState; -using google_breakpad::scoped_ptr; -using google_breakpad::SimpleSymbolSupplier; -using google_breakpad::StackFrameSymbolizer; - -// Processes |microdump_file| using MicrodumpProcessor. |symbol_path|, if -// non-empty, is the base directory of a symbol storage area, laid out in -// the format required by SimpleSymbolSupplier. If such a storage area -// is specified, it is made available for use by the MicrodumpProcessor. -// -// Returns the value of MicrodumpProcessor::Process. If processing succeeds, -// prints identifying OS and CPU information from the microdump, crash -// information and call stacks for the crashing thread. -// All information is printed to stdout. -int PrintMicrodumpProcess(const char* microdump_file, - const std::vector<string>& symbol_paths, - bool machine_readable) { - std::ifstream file_stream(microdump_file); - std::vector<char> bytes; - file_stream.seekg(0, std::ios_base::end); - bytes.resize(file_stream.tellg()); - file_stream.seekg(0, std::ios_base::beg); - file_stream.read(&bytes[0], bytes.size()); - string microdump_content(&bytes[0], bytes.size()); - - scoped_ptr<SimpleSymbolSupplier> symbol_supplier; - if (!symbol_paths.empty()) { - symbol_supplier.reset(new SimpleSymbolSupplier(symbol_paths)); - } - - BasicSourceLineResolver resolver; - StackFrameSymbolizer frame_symbolizer(symbol_supplier.get(), &resolver); - ProcessState process_state; - MicrodumpProcessor microdump_processor(&frame_symbolizer); - ProcessResult res = microdump_processor.Process(microdump_content, - &process_state); - - if (res == google_breakpad::PROCESS_OK) { - if (machine_readable) { - PrintProcessStateMachineReadable(process_state); - } else { - PrintProcessState(process_state, false, &resolver); - } - return 0; - } - - BPLOG(ERROR) << "MicrodumpProcessor::Process failed (code = " << res << ")"; - return 1; -} - -void usage(const char *program_name) { - fprintf(stderr, "usage: %s [-m] <microdump-file> [symbol-path ...]\n" - " -m : Output in machine-readable format\n", - program_name); -} - -} // namespace - -int main(int argc, char** argv) { - BPLOG_INIT(&argc, &argv); - - if (argc < 2) { - usage(argv[0]); - return 1; - } - - const char* microdump_file; - bool machine_readable; - int symbol_path_arg; - - if (strcmp(argv[1], "-m") == 0) { - if (argc < 3) { - usage(argv[0]); - return 1; - } - - machine_readable = true; - microdump_file = argv[2]; - symbol_path_arg = 3; - } else { - machine_readable = false; - microdump_file = argv[1]; - symbol_path_arg = 2; - } - - // extra arguments are symbol paths - std::vector<string> symbol_paths; - if (argc > symbol_path_arg) { - for (int argi = symbol_path_arg; argi < argc; ++argi) - symbol_paths.push_back(argv[argi]); - } - - return PrintMicrodumpProcess(microdump_file, - symbol_paths, - machine_readable); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_machine_readable_test b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_machine_readable_test deleted file mode 100755 index fadec2645..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_machine_readable_test +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2014, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -source "${0%/*}/microdump_stackwalk_test_vars" # for MICRODUMP_SUPPORTED_ARCHS. -testdata_dir=$srcdir/src/processor/testdata - -set -e # Bail out with an error if any of the commands below fails. -for ARCH in $MICRODUMP_SUPPORTED_ARCHS; do - echo "Testing microdump_stackwalk -m for arch $ARCH" - ./src/processor/microdump_stackwalk -m $testdata_dir/microdump-${ARCH}.dmp \ - $testdata_dir/symbols/microdump | \ - tr -d '\015' | \ - diff -u $testdata_dir/microdump.stackwalk.machine_readable-${ARCH}.out - -done -exit 0 diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test deleted file mode 100755 index 5a1f3d59f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2014, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -source "${0%/*}/microdump_stackwalk_test_vars" # for MICRODUMP_SUPPORTED_ARCHS. -testdata_dir=$srcdir/src/processor/testdata - -set -e # Bail out with an error if any of the commands below fails. -for ARCH in $MICRODUMP_SUPPORTED_ARCHS; do - echo "Testing microdump_stackwalk for arch $ARCH" - ./src/processor/microdump_stackwalk $testdata_dir/microdump-${ARCH}.dmp \ - $testdata_dir/symbols/microdump | \ - tr -d '\015' | \ - diff -u $testdata_dir/microdump.stackwalk-${ARCH}.out - -done -exit 0 diff --git a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test_vars b/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test_vars deleted file mode 100644 index a8b0e0df5..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/microdump_stackwalk_test_vars +++ /dev/null @@ -1 +0,0 @@ -MICRODUMP_SUPPORTED_ARCHS="arm arm64" diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc deleted file mode 100644 index 1e1d386df..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump.cc +++ /dev/null @@ -1,4989 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// minidump.cc: A minidump reader. -// -// See minidump.h for documentation. -// -// Author: Mark Mentovai - -#include "google_breakpad/processor/minidump.h" - -#include <assert.h> -#include <fcntl.h> -#include <stddef.h> -#include <string.h> -#include <time.h> - -#ifdef _WIN32 -#include <io.h> -#else // _WIN32 -#include <unistd.h> -#endif // _WIN32 - -#include <algorithm> -#include <fstream> -#include <iostream> -#include <limits> -#include <map> -#include <vector> - -#include "processor/range_map-inl.h" - -#include "common/scoped_ptr.h" -#include "common/stdio_wrapper.h" -#include "google_breakpad/processor/dump_context.h" -#include "processor/basic_code_module.h" -#include "processor/basic_code_modules.h" -#include "processor/logging.h" - -namespace google_breakpad { - - -using std::istream; -using std::ifstream; -using std::numeric_limits; -using std::vector; - -// Returns true iff |context_size| matches exactly one of the sizes of the -// various MDRawContext* types. -// TODO(blundell): This function can be removed once -// http://code.google.com/p/google-breakpad/issues/detail?id=550 is fixed. -static bool IsContextSizeUnique(uint32_t context_size) { - int num_matching_contexts = 0; - if (context_size == sizeof(MDRawContextX86)) - num_matching_contexts++; - if (context_size == sizeof(MDRawContextPPC)) - num_matching_contexts++; - if (context_size == sizeof(MDRawContextPPC64)) - num_matching_contexts++; - if (context_size == sizeof(MDRawContextAMD64)) - num_matching_contexts++; - if (context_size == sizeof(MDRawContextSPARC)) - num_matching_contexts++; - if (context_size == sizeof(MDRawContextARM)) - num_matching_contexts++; - if (context_size == sizeof(MDRawContextARM64)) - num_matching_contexts++; - if (context_size == sizeof(MDRawContextMIPS)) - num_matching_contexts++; - return num_matching_contexts == 1; -} - -// -// Swapping routines -// -// Inlining these doesn't increase code size significantly, and it saves -// a whole lot of unnecessary jumping back and forth. -// - - -// Swapping an 8-bit quantity is a no-op. This function is only provided -// to account for certain templatized operations that require swapping for -// wider types but handle uint8_t too -// (MinidumpMemoryRegion::GetMemoryAtAddressInternal). -static inline void Swap(uint8_t* value) { -} - - -// Optimization: don't need to AND the furthest right shift, because we're -// shifting an unsigned quantity. The standard requires zero-filling in this -// case. If the quantities were signed, a bitmask whould be needed for this -// right shift to avoid an arithmetic shift (which retains the sign bit). -// The furthest left shift never needs to be ANDed bitmask. - - -static inline void Swap(uint16_t* value) { - *value = (*value >> 8) | - (*value << 8); -} - - -static inline void Swap(uint32_t* value) { - *value = (*value >> 24) | - ((*value >> 8) & 0x0000ff00) | - ((*value << 8) & 0x00ff0000) | - (*value << 24); -} - - -static inline void Swap(uint64_t* value) { - uint32_t* value32 = reinterpret_cast<uint32_t*>(value); - Swap(&value32[0]); - Swap(&value32[1]); - uint32_t temp = value32[0]; - value32[0] = value32[1]; - value32[1] = temp; -} - - -// Given a pointer to a 128-bit int in the minidump data, set the "low" -// and "high" fields appropriately. -static void Normalize128(uint128_struct* value, bool is_big_endian) { - // The struct format is [high, low], so if the format is big-endian, - // the most significant bytes will already be in the high field. - if (!is_big_endian) { - uint64_t temp = value->low; - value->low = value->high; - value->high = temp; - } -} - -// This just swaps each int64 half of the 128-bit value. -// The value should also be normalized by calling Normalize128(). -static void Swap(uint128_struct* value) { - Swap(&value->low); - Swap(&value->high); -} - -// Swapping signed integers -static inline void Swap(int32_t* value) { - Swap(reinterpret_cast<uint32_t*>(value)); -} - -static inline void Swap(MDLocationDescriptor* location_descriptor) { - Swap(&location_descriptor->data_size); - Swap(&location_descriptor->rva); -} - - -static inline void Swap(MDMemoryDescriptor* memory_descriptor) { - Swap(&memory_descriptor->start_of_memory_range); - Swap(&memory_descriptor->memory); -} - - -static inline void Swap(MDGUID* guid) { - Swap(&guid->data1); - Swap(&guid->data2); - Swap(&guid->data3); - // Don't swap guid->data4[] because it contains 8-bit quantities. -} - -static inline void Swap(MDSystemTime* system_time) { - Swap(&system_time->year); - Swap(&system_time->month); - Swap(&system_time->day_of_week); - Swap(&system_time->day); - Swap(&system_time->hour); - Swap(&system_time->minute); - Swap(&system_time->second); - Swap(&system_time->milliseconds); -} - -static inline void Swap(MDXStateFeature* xstate_feature) { - Swap(&xstate_feature->offset); - Swap(&xstate_feature->size); -} - -static inline void Swap(MDXStateConfigFeatureMscInfo* xstate_feature_info) { - Swap(&xstate_feature_info->size_of_info); - Swap(&xstate_feature_info->context_size); - Swap(&xstate_feature_info->enabled_features); - - for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES; i++) { - Swap(&xstate_feature_info->features[i]); - } -} - -static inline void Swap(uint16_t* data, size_t size_in_bytes) { - size_t data_length = size_in_bytes / sizeof(data[0]); - for (size_t i = 0; i < data_length; i++) { - Swap(&data[i]); - } -} - -// -// Character conversion routines -// - - -// Standard wide-character conversion routines depend on the system's own -// idea of what width a wide character should be: some use 16 bits, and -// some use 32 bits. For the purposes of a minidump, wide strings are -// always represented with 16-bit UTF-16 chracters. iconv isn't available -// everywhere, and its interface varies where it is available. iconv also -// deals purely with char* pointers, so in addition to considering the swap -// parameter, a converter that uses iconv would also need to take the host -// CPU's endianness into consideration. It doesn't seems worth the trouble -// of making it a dependency when we don't care about anything but UTF-16. -static string* UTF16ToUTF8(const vector<uint16_t>& in, - bool swap) { - scoped_ptr<string> out(new string()); - - // Set the string's initial capacity to the number of UTF-16 characters, - // because the UTF-8 representation will always be at least this long. - // If the UTF-8 representation is longer, the string will grow dynamically. - out->reserve(in.size()); - - for (vector<uint16_t>::const_iterator iterator = in.begin(); - iterator != in.end(); - ++iterator) { - // Get a 16-bit value from the input - uint16_t in_word = *iterator; - if (swap) - Swap(&in_word); - - // Convert the input value (in_word) into a Unicode code point (unichar). - uint32_t unichar; - if (in_word >= 0xdc00 && in_word <= 0xdcff) { - BPLOG(ERROR) << "UTF16ToUTF8 found low surrogate " << - HexString(in_word) << " without high"; - return NULL; - } else if (in_word >= 0xd800 && in_word <= 0xdbff) { - // High surrogate. - unichar = (in_word - 0xd7c0) << 10; - if (++iterator == in.end()) { - BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " << - HexString(in_word) << " at end of string"; - return NULL; - } - uint32_t high_word = in_word; - in_word = *iterator; - if (in_word < 0xdc00 || in_word > 0xdcff) { - BPLOG(ERROR) << "UTF16ToUTF8 found high surrogate " << - HexString(high_word) << " without low " << - HexString(in_word); - return NULL; - } - unichar |= in_word & 0x03ff; - } else { - // The ordinary case, a single non-surrogate Unicode character encoded - // as a single 16-bit value. - unichar = in_word; - } - - // Convert the Unicode code point (unichar) into its UTF-8 representation, - // appending it to the out string. - if (unichar < 0x80) { - (*out) += static_cast<char>(unichar); - } else if (unichar < 0x800) { - (*out) += 0xc0 | static_cast<char>(unichar >> 6); - (*out) += 0x80 | static_cast<char>(unichar & 0x3f); - } else if (unichar < 0x10000) { - (*out) += 0xe0 | static_cast<char>(unichar >> 12); - (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f); - (*out) += 0x80 | static_cast<char>(unichar & 0x3f); - } else if (unichar < 0x200000) { - (*out) += 0xf0 | static_cast<char>(unichar >> 18); - (*out) += 0x80 | static_cast<char>((unichar >> 12) & 0x3f); - (*out) += 0x80 | static_cast<char>((unichar >> 6) & 0x3f); - (*out) += 0x80 | static_cast<char>(unichar & 0x3f); - } else { - BPLOG(ERROR) << "UTF16ToUTF8 cannot represent high value " << - HexString(unichar) << " in UTF-8"; - return NULL; - } - } - - return out.release(); -} - -// Return the smaller of the number of code units in the UTF-16 string, -// not including the terminating null word, or maxlen. -static size_t UTF16codeunits(const uint16_t *string, size_t maxlen) { - size_t count = 0; - while (count < maxlen && string[count] != 0) - count++; - return count; -} - -static inline void Swap(MDTimeZoneInformation* time_zone) { - Swap(&time_zone->bias); - // Skip time_zone->standard_name. No need to swap UTF-16 fields. - // The swap will be done as part of the conversion to UTF-8. - Swap(&time_zone->standard_date); - Swap(&time_zone->standard_bias); - // Skip time_zone->daylight_name. No need to swap UTF-16 fields. - // The swap will be done as part of the conversion to UTF-8. - Swap(&time_zone->daylight_date); - Swap(&time_zone->daylight_bias); -} - -static void ConvertUTF16BufferToUTF8String(const uint16_t* utf16_data, - size_t max_length_in_bytes, - string* utf8_result, - bool swap) { - // Since there is no explicit byte length for each string, use - // UTF16codeunits to calculate word length, then derive byte - // length from that. - size_t max_word_length = max_length_in_bytes / sizeof(utf16_data[0]); - size_t word_length = UTF16codeunits(utf16_data, max_word_length); - if (word_length > 0) { - size_t byte_length = word_length * sizeof(utf16_data[0]); - vector<uint16_t> utf16_vector(word_length); - memcpy(&utf16_vector[0], &utf16_data[0], byte_length); - scoped_ptr<string> temp(UTF16ToUTF8(utf16_vector, swap)); - if (temp.get()) { - utf8_result->assign(*temp); - } - } else { - utf8_result->clear(); - } -} - - -// For fields that may or may not be valid, PrintValueOrInvalid will print the -// string "(invalid)" if the field is not valid, and will print the value if -// the field is valid. The value is printed as hexadecimal or decimal. - -enum NumberFormat { - kNumberFormatDecimal, - kNumberFormatHexadecimal, -}; - -static void PrintValueOrInvalid(bool valid, - NumberFormat number_format, - uint32_t value) { - if (!valid) { - printf("(invalid)\n"); - } else if (number_format == kNumberFormatDecimal) { - printf("%d\n", value); - } else { - printf("0x%x\n", value); - } -} - -// Converts a time_t to a string showing the time in UTC. -string TimeTToUTCString(time_t tt) { - struct tm timestruct; -#ifdef _WIN32 - gmtime_s(×truct, &tt); -#else - gmtime_r(&tt, ×truct); -#endif - - char timestr[20]; - int rv = strftime(timestr, 20, "%Y-%m-%d %H:%M:%S", ×truct); - if (rv == 0) { - return string(); - } - - return string(timestr); -} - - -// -// MinidumpObject -// - - -MinidumpObject::MinidumpObject(Minidump* minidump) - : DumpObject(), - minidump_(minidump) { -} - - -// -// MinidumpStream -// - - -MinidumpStream::MinidumpStream(Minidump* minidump) - : MinidumpObject(minidump) { -} - - -// -// MinidumpContext -// - - -MinidumpContext::MinidumpContext(Minidump* minidump) - : DumpContext(), - minidump_(minidump) { -} - -MinidumpContext::~MinidumpContext() { -} - -bool MinidumpContext::Read(uint32_t expected_size) { - valid_ = false; - - // Certain raw context types are currently assumed to have unique sizes. - if (!IsContextSizeUnique(sizeof(MDRawContextAMD64))) { - BPLOG(ERROR) << "sizeof(MDRawContextAMD64) cannot match the size of any " - << "other raw context"; - return false; - } - if (!IsContextSizeUnique(sizeof(MDRawContextPPC64))) { - BPLOG(ERROR) << "sizeof(MDRawContextPPC64) cannot match the size of any " - << "other raw context"; - return false; - } - if (!IsContextSizeUnique(sizeof(MDRawContextARM64))) { - BPLOG(ERROR) << "sizeof(MDRawContextARM64) cannot match the size of any " - << "other raw context"; - return false; - } - - FreeContext(); - - // First, figure out what type of CPU this context structure is for. - // For some reason, the AMD64 Context doesn't have context_flags - // at the beginning of the structure, so special case it here. - if (expected_size == sizeof(MDRawContextAMD64)) { - BPLOG(INFO) << "MinidumpContext: looks like AMD64 context"; - - scoped_ptr<MDRawContextAMD64> context_amd64(new MDRawContextAMD64()); - if (!minidump_->ReadBytes(context_amd64.get(), - sizeof(MDRawContextAMD64))) { - BPLOG(ERROR) << "MinidumpContext could not read amd64 context"; - return false; - } - - if (minidump_->swap()) - Swap(&context_amd64->context_flags); - - uint32_t cpu_type = context_amd64->context_flags & MD_CONTEXT_CPU_MASK; - if (cpu_type == 0) { - if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { - context_amd64->context_flags |= cpu_type; - } else { - BPLOG(ERROR) << "Failed to preserve the current stream position"; - return false; - } - } - - if (cpu_type != MD_CONTEXT_AMD64) { - // TODO: Fall through to switch below. - // http://code.google.com/p/google-breakpad/issues/detail?id=550 - BPLOG(ERROR) << "MinidumpContext not actually amd64 context"; - return false; - } - - // Do this after reading the entire MDRawContext structure because - // GetSystemInfo may seek minidump to a new position. - if (!CheckAgainstSystemInfo(cpu_type)) { - BPLOG(ERROR) << "MinidumpContext amd64 does not match system info"; - return false; - } - - // Normalize the 128-bit types in the dump. - // Since this is AMD64, by definition, the values are little-endian. - for (unsigned int vr_index = 0; - vr_index < MD_CONTEXT_AMD64_VR_COUNT; - ++vr_index) - Normalize128(&context_amd64->vector_register[vr_index], false); - - if (minidump_->swap()) { - Swap(&context_amd64->p1_home); - Swap(&context_amd64->p2_home); - Swap(&context_amd64->p3_home); - Swap(&context_amd64->p4_home); - Swap(&context_amd64->p5_home); - Swap(&context_amd64->p6_home); - // context_flags is already swapped - Swap(&context_amd64->mx_csr); - Swap(&context_amd64->cs); - Swap(&context_amd64->ds); - Swap(&context_amd64->es); - Swap(&context_amd64->fs); - Swap(&context_amd64->ss); - Swap(&context_amd64->eflags); - Swap(&context_amd64->dr0); - Swap(&context_amd64->dr1); - Swap(&context_amd64->dr2); - Swap(&context_amd64->dr3); - Swap(&context_amd64->dr6); - Swap(&context_amd64->dr7); - Swap(&context_amd64->rax); - Swap(&context_amd64->rcx); - Swap(&context_amd64->rdx); - Swap(&context_amd64->rbx); - Swap(&context_amd64->rsp); - Swap(&context_amd64->rbp); - Swap(&context_amd64->rsi); - Swap(&context_amd64->rdi); - Swap(&context_amd64->r8); - Swap(&context_amd64->r9); - Swap(&context_amd64->r10); - Swap(&context_amd64->r11); - Swap(&context_amd64->r12); - Swap(&context_amd64->r13); - Swap(&context_amd64->r14); - Swap(&context_amd64->r15); - Swap(&context_amd64->rip); - // FIXME: I'm not sure what actually determines - // which member of the union {flt_save, sse_registers} - // is valid. We're not currently using either, - // but it would be good to have them swapped properly. - - for (unsigned int vr_index = 0; - vr_index < MD_CONTEXT_AMD64_VR_COUNT; - ++vr_index) - Swap(&context_amd64->vector_register[vr_index]); - Swap(&context_amd64->vector_control); - Swap(&context_amd64->debug_control); - Swap(&context_amd64->last_branch_to_rip); - Swap(&context_amd64->last_branch_from_rip); - Swap(&context_amd64->last_exception_to_rip); - Swap(&context_amd64->last_exception_from_rip); - } - - SetContextFlags(context_amd64->context_flags); - - SetContextAMD64(context_amd64.release()); - } else if (expected_size == sizeof(MDRawContextPPC64)) { - // |context_flags| of MDRawContextPPC64 is 64 bits, but other MDRawContext - // in the else case have 32 bits |context_flags|, so special case it here. - uint64_t context_flags; - if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { - BPLOG(ERROR) << "MinidumpContext could not read context flags"; - return false; - } - if (minidump_->swap()) - Swap(&context_flags); - - uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK; - scoped_ptr<MDRawContextPPC64> context_ppc64(new MDRawContextPPC64()); - - if (cpu_type == 0) { - if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { - context_ppc64->context_flags |= cpu_type; - } else { - BPLOG(ERROR) << "Failed to preserve the current stream position"; - return false; - } - } - - if (cpu_type != MD_CONTEXT_PPC64) { - // TODO: Fall through to switch below. - // http://code.google.com/p/google-breakpad/issues/detail?id=550 - BPLOG(ERROR) << "MinidumpContext not actually ppc64 context"; - return false; - } - - // Set the context_flags member, which has already been read, and - // read the rest of the structure beginning with the first member - // after context_flags. - context_ppc64->context_flags = context_flags; - - size_t flags_size = sizeof(context_ppc64->context_flags); - uint8_t* context_after_flags = - reinterpret_cast<uint8_t*>(context_ppc64.get()) + flags_size; - if (!minidump_->ReadBytes(context_after_flags, - sizeof(MDRawContextPPC64) - flags_size)) { - BPLOG(ERROR) << "MinidumpContext could not read ppc64 context"; - return false; - } - - // Do this after reading the entire MDRawContext structure because - // GetSystemInfo may seek minidump to a new position. - if (!CheckAgainstSystemInfo(cpu_type)) { - BPLOG(ERROR) << "MinidumpContext ppc64 does not match system info"; - return false; - } - if (minidump_->swap()) { - // context_ppc64->context_flags was already swapped. - Swap(&context_ppc64->srr0); - Swap(&context_ppc64->srr1); - for (unsigned int gpr_index = 0; - gpr_index < MD_CONTEXT_PPC64_GPR_COUNT; - ++gpr_index) { - Swap(&context_ppc64->gpr[gpr_index]); - } - Swap(&context_ppc64->cr); - Swap(&context_ppc64->xer); - Swap(&context_ppc64->lr); - Swap(&context_ppc64->ctr); - Swap(&context_ppc64->vrsave); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; - ++fpr_index) { - Swap(&context_ppc64->float_save.fpregs[fpr_index]); - } - // Don't swap context_ppc64->float_save.fpscr_pad because it is only - // used for padding. - Swap(&context_ppc64->float_save.fpscr); - for (unsigned int vr_index = 0; - vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT; - ++vr_index) { - Normalize128(&context_ppc64->vector_save.save_vr[vr_index], true); - Swap(&context_ppc64->vector_save.save_vr[vr_index]); - } - Swap(&context_ppc64->vector_save.save_vscr); - // Don't swap the padding fields in vector_save. - Swap(&context_ppc64->vector_save.save_vrvalid); - } - - SetContextFlags(static_cast<uint32_t>(context_ppc64->context_flags)); - - // Check for data loss when converting context flags from uint64_t into - // uint32_t - if (static_cast<uint64_t>(GetContextFlags()) != - context_ppc64->context_flags) { - BPLOG(ERROR) << "Data loss detected when converting PPC64 context_flags"; - return false; - } - - SetContextPPC64(context_ppc64.release()); - } else if (expected_size == sizeof(MDRawContextARM64)) { - // |context_flags| of MDRawContextARM64 is 64 bits, but other MDRawContext - // in the else case have 32 bits |context_flags|, so special case it here. - uint64_t context_flags; - - BPLOG(INFO) << "MinidumpContext: looks like ARM64 context"; - - if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { - BPLOG(ERROR) << "MinidumpContext could not read context flags"; - return false; - } - if (minidump_->swap()) - Swap(&context_flags); - - scoped_ptr<MDRawContextARM64> context_arm64(new MDRawContextARM64()); - - uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK; - if (cpu_type == 0) { - if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { - context_arm64->context_flags |= cpu_type; - } else { - BPLOG(ERROR) << "Failed to preserve the current stream position"; - return false; - } - } - - if (cpu_type != MD_CONTEXT_ARM64) { - // TODO: Fall through to switch below. - // http://code.google.com/p/google-breakpad/issues/detail?id=550 - BPLOG(ERROR) << "MinidumpContext not actually arm64 context"; - return false; - } - - // Set the context_flags member, which has already been read, and - // read the rest of the structure beginning with the first member - // after context_flags. - context_arm64->context_flags = context_flags; - - size_t flags_size = sizeof(context_arm64->context_flags); - uint8_t* context_after_flags = - reinterpret_cast<uint8_t*>(context_arm64.get()) + flags_size; - if (!minidump_->ReadBytes(context_after_flags, - sizeof(MDRawContextARM64) - flags_size)) { - BPLOG(ERROR) << "MinidumpContext could not read arm64 context"; - return false; - } - - // Do this after reading the entire MDRawContext structure because - // GetSystemInfo may seek minidump to a new position. - if (!CheckAgainstSystemInfo(cpu_type)) { - BPLOG(ERROR) << "MinidumpContext arm64 does not match system info"; - return false; - } - - if (minidump_->swap()) { - // context_arm64->context_flags was already swapped. - for (unsigned int ireg_index = 0; - ireg_index < MD_CONTEXT_ARM64_GPR_COUNT; - ++ireg_index) { - Swap(&context_arm64->iregs[ireg_index]); - } - Swap(&context_arm64->cpsr); - Swap(&context_arm64->float_save.fpsr); - Swap(&context_arm64->float_save.fpcr); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_ARM64_FPR_COUNT; - ++fpr_index) { - // While ARM64 is bi-endian, iOS (currently the only platform - // for which ARM64 support has been brought up) uses ARM64 exclusively - // in little-endian mode. - Normalize128(&context_arm64->float_save.regs[fpr_index], false); - Swap(&context_arm64->float_save.regs[fpr_index]); - } - } - SetContextFlags(static_cast<uint32_t>(context_arm64->context_flags)); - - // Check for data loss when converting context flags from uint64_t into - // uint32_t - if (static_cast<uint64_t>(GetContextFlags()) != - context_arm64->context_flags) { - BPLOG(ERROR) << "Data loss detected when converting ARM64 context_flags"; - return false; - } - - SetContextARM64(context_arm64.release()); - } else { - uint32_t context_flags; - if (!minidump_->ReadBytes(&context_flags, sizeof(context_flags))) { - BPLOG(ERROR) << "MinidumpContext could not read context flags"; - return false; - } - if (minidump_->swap()) - Swap(&context_flags); - - uint32_t cpu_type = context_flags & MD_CONTEXT_CPU_MASK; - if (cpu_type == 0) { - // Unfortunately the flag for MD_CONTEXT_ARM that was taken - // from a Windows CE SDK header conflicts in practice with - // the CONTEXT_XSTATE flag. MD_CONTEXT_ARM has been renumbered, - // but handle dumps with the legacy value gracefully here. - if (context_flags & MD_CONTEXT_ARM_OLD) { - context_flags |= MD_CONTEXT_ARM; - context_flags &= ~MD_CONTEXT_ARM_OLD; - cpu_type = MD_CONTEXT_ARM; - } - } - - if (cpu_type == 0) { - if (minidump_->GetContextCPUFlagsFromSystemInfo(&cpu_type)) { - context_flags |= cpu_type; - } else { - BPLOG(ERROR) << "Failed to preserve the current stream position"; - return false; - } - } - - // Allocate the context structure for the correct CPU and fill it. The - // casts are slightly unorthodox, but it seems better to do that than to - // maintain a separate pointer for each type of CPU context structure - // when only one of them will be used. - switch (cpu_type) { - case MD_CONTEXT_X86: { - if (expected_size != sizeof(MDRawContextX86)) { - BPLOG(ERROR) << "MinidumpContext x86 size mismatch, " << - expected_size << " != " << sizeof(MDRawContextX86); - return false; - } - - scoped_ptr<MDRawContextX86> context_x86(new MDRawContextX86()); - - // Set the context_flags member, which has already been read, and - // read the rest of the structure beginning with the first member - // after context_flags. - context_x86->context_flags = context_flags; - - size_t flags_size = sizeof(context_x86->context_flags); - uint8_t* context_after_flags = - reinterpret_cast<uint8_t*>(context_x86.get()) + flags_size; - if (!minidump_->ReadBytes(context_after_flags, - sizeof(MDRawContextX86) - flags_size)) { - BPLOG(ERROR) << "MinidumpContext could not read x86 context"; - return false; - } - - // Do this after reading the entire MDRawContext structure because - // GetSystemInfo may seek minidump to a new position. - if (!CheckAgainstSystemInfo(cpu_type)) { - BPLOG(ERROR) << "MinidumpContext x86 does not match system info"; - return false; - } - - if (minidump_->swap()) { - // context_x86->context_flags was already swapped. - Swap(&context_x86->dr0); - Swap(&context_x86->dr1); - Swap(&context_x86->dr2); - Swap(&context_x86->dr3); - Swap(&context_x86->dr6); - Swap(&context_x86->dr7); - Swap(&context_x86->float_save.control_word); - Swap(&context_x86->float_save.status_word); - Swap(&context_x86->float_save.tag_word); - Swap(&context_x86->float_save.error_offset); - Swap(&context_x86->float_save.error_selector); - Swap(&context_x86->float_save.data_offset); - Swap(&context_x86->float_save.data_selector); - // context_x86->float_save.register_area[] contains 8-bit quantities - // and does not need to be swapped. - Swap(&context_x86->float_save.cr0_npx_state); - Swap(&context_x86->gs); - Swap(&context_x86->fs); - Swap(&context_x86->es); - Swap(&context_x86->ds); - Swap(&context_x86->edi); - Swap(&context_x86->esi); - Swap(&context_x86->ebx); - Swap(&context_x86->edx); - Swap(&context_x86->ecx); - Swap(&context_x86->eax); - Swap(&context_x86->ebp); - Swap(&context_x86->eip); - Swap(&context_x86->cs); - Swap(&context_x86->eflags); - Swap(&context_x86->esp); - Swap(&context_x86->ss); - // context_x86->extended_registers[] contains 8-bit quantities and - // does not need to be swapped. - } - - SetContextX86(context_x86.release()); - - break; - } - - case MD_CONTEXT_PPC: { - if (expected_size != sizeof(MDRawContextPPC)) { - BPLOG(ERROR) << "MinidumpContext ppc size mismatch, " << - expected_size << " != " << sizeof(MDRawContextPPC); - return false; - } - - scoped_ptr<MDRawContextPPC> context_ppc(new MDRawContextPPC()); - - // Set the context_flags member, which has already been read, and - // read the rest of the structure beginning with the first member - // after context_flags. - context_ppc->context_flags = context_flags; - - size_t flags_size = sizeof(context_ppc->context_flags); - uint8_t* context_after_flags = - reinterpret_cast<uint8_t*>(context_ppc.get()) + flags_size; - if (!minidump_->ReadBytes(context_after_flags, - sizeof(MDRawContextPPC) - flags_size)) { - BPLOG(ERROR) << "MinidumpContext could not read ppc context"; - return false; - } - - // Do this after reading the entire MDRawContext structure because - // GetSystemInfo may seek minidump to a new position. - if (!CheckAgainstSystemInfo(cpu_type)) { - BPLOG(ERROR) << "MinidumpContext ppc does not match system info"; - return false; - } - - // Normalize the 128-bit types in the dump. - // Since this is PowerPC, by definition, the values are big-endian. - for (unsigned int vr_index = 0; - vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT; - ++vr_index) { - Normalize128(&context_ppc->vector_save.save_vr[vr_index], true); - } - - if (minidump_->swap()) { - // context_ppc->context_flags was already swapped. - Swap(&context_ppc->srr0); - Swap(&context_ppc->srr1); - for (unsigned int gpr_index = 0; - gpr_index < MD_CONTEXT_PPC_GPR_COUNT; - ++gpr_index) { - Swap(&context_ppc->gpr[gpr_index]); - } - Swap(&context_ppc->cr); - Swap(&context_ppc->xer); - Swap(&context_ppc->lr); - Swap(&context_ppc->ctr); - Swap(&context_ppc->mq); - Swap(&context_ppc->vrsave); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_PPC_FPR_COUNT; - ++fpr_index) { - Swap(&context_ppc->float_save.fpregs[fpr_index]); - } - // Don't swap context_ppc->float_save.fpscr_pad because it is only - // used for padding. - Swap(&context_ppc->float_save.fpscr); - for (unsigned int vr_index = 0; - vr_index < MD_VECTORSAVEAREA_PPC_VR_COUNT; - ++vr_index) { - Swap(&context_ppc->vector_save.save_vr[vr_index]); - } - Swap(&context_ppc->vector_save.save_vscr); - // Don't swap the padding fields in vector_save. - Swap(&context_ppc->vector_save.save_vrvalid); - } - - SetContextPPC(context_ppc.release()); - - break; - } - - case MD_CONTEXT_SPARC: { - if (expected_size != sizeof(MDRawContextSPARC)) { - BPLOG(ERROR) << "MinidumpContext sparc size mismatch, " << - expected_size << " != " << sizeof(MDRawContextSPARC); - return false; - } - - scoped_ptr<MDRawContextSPARC> context_sparc(new MDRawContextSPARC()); - - // Set the context_flags member, which has already been read, and - // read the rest of the structure beginning with the first member - // after context_flags. - context_sparc->context_flags = context_flags; - - size_t flags_size = sizeof(context_sparc->context_flags); - uint8_t* context_after_flags = - reinterpret_cast<uint8_t*>(context_sparc.get()) + flags_size; - if (!minidump_->ReadBytes(context_after_flags, - sizeof(MDRawContextSPARC) - flags_size)) { - BPLOG(ERROR) << "MinidumpContext could not read sparc context"; - return false; - } - - // Do this after reading the entire MDRawContext structure because - // GetSystemInfo may seek minidump to a new position. - if (!CheckAgainstSystemInfo(cpu_type)) { - BPLOG(ERROR) << "MinidumpContext sparc does not match system info"; - return false; - } - - if (minidump_->swap()) { - // context_sparc->context_flags was already swapped. - for (unsigned int gpr_index = 0; - gpr_index < MD_CONTEXT_SPARC_GPR_COUNT; - ++gpr_index) { - Swap(&context_sparc->g_r[gpr_index]); - } - Swap(&context_sparc->ccr); - Swap(&context_sparc->pc); - Swap(&context_sparc->npc); - Swap(&context_sparc->y); - Swap(&context_sparc->asi); - Swap(&context_sparc->fprs); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_SPARC_FPR_COUNT; - ++fpr_index) { - Swap(&context_sparc->float_save.regs[fpr_index]); - } - Swap(&context_sparc->float_save.filler); - Swap(&context_sparc->float_save.fsr); - } - SetContextSPARC(context_sparc.release()); - - break; - } - - case MD_CONTEXT_ARM: { - if (expected_size != sizeof(MDRawContextARM)) { - BPLOG(ERROR) << "MinidumpContext arm size mismatch, " << - expected_size << " != " << sizeof(MDRawContextARM); - return false; - } - - scoped_ptr<MDRawContextARM> context_arm(new MDRawContextARM()); - - // Set the context_flags member, which has already been read, and - // read the rest of the structure beginning with the first member - // after context_flags. - context_arm->context_flags = context_flags; - - size_t flags_size = sizeof(context_arm->context_flags); - uint8_t* context_after_flags = - reinterpret_cast<uint8_t*>(context_arm.get()) + flags_size; - if (!minidump_->ReadBytes(context_after_flags, - sizeof(MDRawContextARM) - flags_size)) { - BPLOG(ERROR) << "MinidumpContext could not read arm context"; - return false; - } - - // Do this after reading the entire MDRawContext structure because - // GetSystemInfo may seek minidump to a new position. - if (!CheckAgainstSystemInfo(cpu_type)) { - BPLOG(ERROR) << "MinidumpContext arm does not match system info"; - return false; - } - - if (minidump_->swap()) { - // context_arm->context_flags was already swapped. - for (unsigned int ireg_index = 0; - ireg_index < MD_CONTEXT_ARM_GPR_COUNT; - ++ireg_index) { - Swap(&context_arm->iregs[ireg_index]); - } - Swap(&context_arm->cpsr); - Swap(&context_arm->float_save.fpscr); - for (unsigned int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; - ++fpr_index) { - Swap(&context_arm->float_save.regs[fpr_index]); - } - for (unsigned int fpe_index = 0; - fpe_index < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; - ++fpe_index) { - Swap(&context_arm->float_save.extra[fpe_index]); - } - } - SetContextARM(context_arm.release()); - - break; - } - - case MD_CONTEXT_MIPS: - case MD_CONTEXT_MIPS64: { - if (expected_size != sizeof(MDRawContextMIPS)) { - BPLOG(ERROR) << "MinidumpContext MIPS size mismatch, " - << expected_size - << " != " - << sizeof(MDRawContextMIPS); - return false; - } - - scoped_ptr<MDRawContextMIPS> context_mips(new MDRawContextMIPS()); - - // Set the context_flags member, which has already been read, and - // read the rest of the structure beginning with the first member - // after context_flags. - context_mips->context_flags = context_flags; - - size_t flags_size = sizeof(context_mips->context_flags); - uint8_t* context_after_flags = - reinterpret_cast<uint8_t*>(context_mips.get()) + flags_size; - if (!minidump_->ReadBytes(context_after_flags, - sizeof(MDRawContextMIPS) - flags_size)) { - BPLOG(ERROR) << "MinidumpContext could not read MIPS context"; - return false; - } - - // Do this after reading the entire MDRawContext structure because - // GetSystemInfo may seek minidump to a new position. - if (!CheckAgainstSystemInfo(cpu_type)) { - BPLOG(ERROR) << "MinidumpContext MIPS does not match system info"; - return false; - } - - if (minidump_->swap()) { - // context_mips->context_flags was already swapped. - for (int ireg_index = 0; - ireg_index < MD_CONTEXT_MIPS_GPR_COUNT; - ++ireg_index) { - Swap(&context_mips->iregs[ireg_index]); - } - Swap(&context_mips->mdhi); - Swap(&context_mips->mdlo); - for (int dsp_index = 0; - dsp_index < MD_CONTEXT_MIPS_DSP_COUNT; - ++dsp_index) { - Swap(&context_mips->hi[dsp_index]); - Swap(&context_mips->lo[dsp_index]); - } - Swap(&context_mips->dsp_control); - Swap(&context_mips->epc); - Swap(&context_mips->badvaddr); - Swap(&context_mips->status); - Swap(&context_mips->cause); - for (int fpr_index = 0; - fpr_index < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; - ++fpr_index) { - Swap(&context_mips->float_save.regs[fpr_index]); - } - Swap(&context_mips->float_save.fpcsr); - Swap(&context_mips->float_save.fir); - } - SetContextMIPS(context_mips.release()); - - break; - } - - default: { - // Unknown context type - Don't log as an error yet. Let the - // caller work that out. - BPLOG(INFO) << "MinidumpContext unknown context type " << - HexString(cpu_type); - return false; - break; - } - } - SetContextFlags(context_flags); - } - - valid_ = true; - return true; -} - -bool MinidumpContext::CheckAgainstSystemInfo(uint32_t context_cpu_type) { - // It's OK if the minidump doesn't contain an MD_SYSTEM_INFO_STREAM, - // as this function just implements a sanity check. - MinidumpSystemInfo* system_info = minidump_->GetSystemInfo(); - if (!system_info) { - BPLOG(INFO) << "MinidumpContext could not be compared against " - "MinidumpSystemInfo"; - return true; - } - - // If there is an MD_SYSTEM_INFO_STREAM, it should contain valid system info. - const MDRawSystemInfo* raw_system_info = system_info->system_info(); - if (!raw_system_info) { - BPLOG(INFO) << "MinidumpContext could not be compared against " - "MDRawSystemInfo"; - return false; - } - - MDCPUArchitecture system_info_cpu_type = static_cast<MDCPUArchitecture>( - raw_system_info->processor_architecture); - - // Compare the CPU type of the context record to the CPU type in the - // minidump's system info stream. - bool return_value = false; - switch (context_cpu_type) { - case MD_CONTEXT_X86: - if (system_info_cpu_type == MD_CPU_ARCHITECTURE_X86 || - system_info_cpu_type == MD_CPU_ARCHITECTURE_X86_WIN64 || - system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) { - return_value = true; - } - break; - - case MD_CONTEXT_PPC: - if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC) - return_value = true; - break; - - case MD_CONTEXT_PPC64: - if (system_info_cpu_type == MD_CPU_ARCHITECTURE_PPC64) - return_value = true; - break; - - case MD_CONTEXT_AMD64: - if (system_info_cpu_type == MD_CPU_ARCHITECTURE_AMD64) - return_value = true; - break; - - case MD_CONTEXT_SPARC: - if (system_info_cpu_type == MD_CPU_ARCHITECTURE_SPARC) - return_value = true; - break; - - case MD_CONTEXT_ARM: - if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM) - return_value = true; - break; - - case MD_CONTEXT_ARM64: - if (system_info_cpu_type == MD_CPU_ARCHITECTURE_ARM64) - return_value = true; - break; - - case MD_CONTEXT_MIPS: - if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS) - return_value = true; - break; - - case MD_CONTEXT_MIPS64: - if (system_info_cpu_type == MD_CPU_ARCHITECTURE_MIPS64) - return_value = true; - break; - } - - BPLOG_IF(ERROR, !return_value) << "MinidumpContext CPU " << - HexString(context_cpu_type) << - " wrong for MinidumpSystemInfo CPU " << - HexString(system_info_cpu_type); - - return return_value; -} - - -// -// MinidumpMemoryRegion -// - - -uint32_t MinidumpMemoryRegion::max_bytes_ = 2 * 1024 * 1024; // 2MB - - -MinidumpMemoryRegion::MinidumpMemoryRegion(Minidump* minidump) - : MinidumpObject(minidump), - descriptor_(NULL), - memory_(NULL) { -} - - -MinidumpMemoryRegion::~MinidumpMemoryRegion() { - delete memory_; -} - - -void MinidumpMemoryRegion::SetDescriptor(MDMemoryDescriptor* descriptor) { - descriptor_ = descriptor; - valid_ = descriptor && - descriptor_->memory.data_size <= - numeric_limits<uint64_t>::max() - - descriptor_->start_of_memory_range; -} - - -const uint8_t* MinidumpMemoryRegion::GetMemory() const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetMemory"; - return NULL; - } - - if (!memory_) { - if (descriptor_->memory.data_size == 0) { - BPLOG(ERROR) << "MinidumpMemoryRegion is empty"; - return NULL; - } - - if (!minidump_->SeekSet(descriptor_->memory.rva)) { - BPLOG(ERROR) << "MinidumpMemoryRegion could not seek to memory region"; - return NULL; - } - - if (descriptor_->memory.data_size > max_bytes_) { - BPLOG(ERROR) << "MinidumpMemoryRegion size " << - descriptor_->memory.data_size << " exceeds maximum " << - max_bytes_; - return NULL; - } - - scoped_ptr< vector<uint8_t> > memory( - new vector<uint8_t>(descriptor_->memory.data_size)); - - if (!minidump_->ReadBytes(&(*memory)[0], descriptor_->memory.data_size)) { - BPLOG(ERROR) << "MinidumpMemoryRegion could not read memory region"; - return NULL; - } - - memory_ = memory.release(); - } - - return &(*memory_)[0]; -} - - -uint64_t MinidumpMemoryRegion::GetBase() const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetBase"; - return static_cast<uint64_t>(-1); - } - - return descriptor_->start_of_memory_range; -} - - -uint32_t MinidumpMemoryRegion::GetSize() const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for GetSize"; - return 0; - } - - return descriptor_->memory.data_size; -} - - -void MinidumpMemoryRegion::FreeMemory() { - delete memory_; - memory_ = NULL; -} - - -template<typename T> -bool MinidumpMemoryRegion::GetMemoryAtAddressInternal(uint64_t address, - T* value) const { - BPLOG_IF(ERROR, !value) << "MinidumpMemoryRegion::GetMemoryAtAddressInternal " - "requires |value|"; - assert(value); - *value = 0; - - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpMemoryRegion for " - "GetMemoryAtAddressInternal"; - return false; - } - - // Common failure case - if (address < descriptor_->start_of_memory_range || - sizeof(T) > numeric_limits<uint64_t>::max() - address || - address + sizeof(T) > descriptor_->start_of_memory_range + - descriptor_->memory.data_size) { - BPLOG(INFO) << "MinidumpMemoryRegion request out of range: " << - HexString(address) << "+" << sizeof(T) << "/" << - HexString(descriptor_->start_of_memory_range) << "+" << - HexString(descriptor_->memory.data_size); - return false; - } - - const uint8_t* memory = GetMemory(); - if (!memory) { - // GetMemory already logged a perfectly good message. - return false; - } - - // If the CPU requires memory accesses to be aligned, this can crash. - // x86 and ppc are able to cope, though. - *value = *reinterpret_cast<const T*>( - &memory[address - descriptor_->start_of_memory_range]); - - if (minidump_->swap()) - Swap(value); - - return true; -} - - -bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, - uint8_t* value) const { - return GetMemoryAtAddressInternal(address, value); -} - - -bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, - uint16_t* value) const { - return GetMemoryAtAddressInternal(address, value); -} - - -bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, - uint32_t* value) const { - return GetMemoryAtAddressInternal(address, value); -} - - -bool MinidumpMemoryRegion::GetMemoryAtAddress(uint64_t address, - uint64_t* value) const { - return GetMemoryAtAddressInternal(address, value); -} - - -void MinidumpMemoryRegion::Print() const { - if (!valid_) { - BPLOG(ERROR) << "MinidumpMemoryRegion cannot print invalid data"; - return; - } - - const uint8_t* memory = GetMemory(); - if (memory) { - printf("0x"); - for (unsigned int byte_index = 0; - byte_index < descriptor_->memory.data_size; - byte_index++) { - printf("%02x", memory[byte_index]); - } - printf("\n"); - } else { - printf("No memory\n"); - } -} - - -// -// MinidumpThread -// - - -MinidumpThread::MinidumpThread(Minidump* minidump) - : MinidumpObject(minidump), - thread_(), - memory_(NULL), - context_(NULL) { -} - - -MinidumpThread::~MinidumpThread() { - delete memory_; - delete context_; -} - - -bool MinidumpThread::Read() { - // Invalidate cached data. - delete memory_; - memory_ = NULL; - delete context_; - context_ = NULL; - - valid_ = false; - - if (!minidump_->ReadBytes(&thread_, sizeof(thread_))) { - BPLOG(ERROR) << "MinidumpThread cannot read thread"; - return false; - } - - if (minidump_->swap()) { - Swap(&thread_.thread_id); - Swap(&thread_.suspend_count); - Swap(&thread_.priority_class); - Swap(&thread_.priority); - Swap(&thread_.teb); - Swap(&thread_.stack); - Swap(&thread_.thread_context); - } - - // Check for base + size overflow or undersize. - if (thread_.stack.memory.rva == 0 || - thread_.stack.memory.data_size == 0 || - thread_.stack.memory.data_size > numeric_limits<uint64_t>::max() - - thread_.stack.start_of_memory_range) { - // This is ok, but log an error anyway. - BPLOG(ERROR) << "MinidumpThread has a memory region problem, " << - HexString(thread_.stack.start_of_memory_range) << "+" << - HexString(thread_.stack.memory.data_size) << - ", RVA 0x" << HexString(thread_.stack.memory.rva); - } else { - memory_ = new MinidumpMemoryRegion(minidump_); - memory_->SetDescriptor(&thread_.stack); - } - - valid_ = true; - return true; -} - -uint64_t MinidumpThread::GetStartOfStackMemoryRange() const { - if (!valid_) { - BPLOG(ERROR) << "GetStartOfStackMemoryRange: Invalid MinidumpThread"; - return 0; - } - - return thread_.stack.start_of_memory_range; -} - -MinidumpMemoryRegion* MinidumpThread::GetMemory() { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpThread for GetMemory"; - return NULL; - } - - return memory_; -} - - -MinidumpContext* MinidumpThread::GetContext() { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpThread for GetContext"; - return NULL; - } - - if (!context_) { - if (!minidump_->SeekSet(thread_.thread_context.rva)) { - BPLOG(ERROR) << "MinidumpThread cannot seek to context"; - return NULL; - } - - scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_)); - - if (!context->Read(thread_.thread_context.data_size)) { - BPLOG(ERROR) << "MinidumpThread cannot read context"; - return NULL; - } - - context_ = context.release(); - } - - return context_; -} - - -bool MinidumpThread::GetThreadID(uint32_t *thread_id) const { - BPLOG_IF(ERROR, !thread_id) << "MinidumpThread::GetThreadID requires " - "|thread_id|"; - assert(thread_id); - *thread_id = 0; - - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpThread for GetThreadID"; - return false; - } - - *thread_id = thread_.thread_id; - return true; -} - - -void MinidumpThread::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpThread cannot print invalid data"; - return; - } - - printf("MDRawThread\n"); - printf(" thread_id = 0x%x\n", thread_.thread_id); - printf(" suspend_count = %d\n", thread_.suspend_count); - printf(" priority_class = 0x%x\n", thread_.priority_class); - printf(" priority = 0x%x\n", thread_.priority); - printf(" teb = 0x%" PRIx64 "\n", thread_.teb); - printf(" stack.start_of_memory_range = 0x%" PRIx64 "\n", - thread_.stack.start_of_memory_range); - printf(" stack.memory.data_size = 0x%x\n", - thread_.stack.memory.data_size); - printf(" stack.memory.rva = 0x%x\n", thread_.stack.memory.rva); - printf(" thread_context.data_size = 0x%x\n", - thread_.thread_context.data_size); - printf(" thread_context.rva = 0x%x\n", - thread_.thread_context.rva); - - MinidumpContext* context = GetContext(); - if (context) { - printf("\n"); - context->Print(); - } else { - printf(" (no context)\n"); - printf("\n"); - } - - MinidumpMemoryRegion* memory = GetMemory(); - if (memory) { - printf("Stack\n"); - memory->Print(); - } else { - printf("No stack\n"); - } - printf("\n"); -} - - -// -// MinidumpThreadList -// - - -uint32_t MinidumpThreadList::max_threads_ = 4096; - - -MinidumpThreadList::MinidumpThreadList(Minidump* minidump) - : MinidumpStream(minidump), - id_to_thread_map_(), - threads_(NULL), - thread_count_(0) { -} - - -MinidumpThreadList::~MinidumpThreadList() { - delete threads_; -} - - -bool MinidumpThreadList::Read(uint32_t expected_size) { - // Invalidate cached data. - id_to_thread_map_.clear(); - delete threads_; - threads_ = NULL; - thread_count_ = 0; - - valid_ = false; - - uint32_t thread_count; - if (expected_size < sizeof(thread_count)) { - BPLOG(ERROR) << "MinidumpThreadList count size mismatch, " << - expected_size << " < " << sizeof(thread_count); - return false; - } - if (!minidump_->ReadBytes(&thread_count, sizeof(thread_count))) { - BPLOG(ERROR) << "MinidumpThreadList cannot read thread count"; - return false; - } - - if (minidump_->swap()) - Swap(&thread_count); - - if (thread_count > numeric_limits<uint32_t>::max() / sizeof(MDRawThread)) { - BPLOG(ERROR) << "MinidumpThreadList thread count " << thread_count << - " would cause multiplication overflow"; - return false; - } - - if (expected_size != sizeof(thread_count) + - thread_count * sizeof(MDRawThread)) { - // may be padded with 4 bytes on 64bit ABIs for alignment - if (expected_size == sizeof(thread_count) + 4 + - thread_count * sizeof(MDRawThread)) { - uint32_t useless; - if (!minidump_->ReadBytes(&useless, 4)) { - BPLOG(ERROR) << "MinidumpThreadList cannot read threadlist padded " - "bytes"; - return false; - } - } else { - BPLOG(ERROR) << "MinidumpThreadList size mismatch, " << expected_size << - " != " << sizeof(thread_count) + - thread_count * sizeof(MDRawThread); - return false; - } - } - - - if (thread_count > max_threads_) { - BPLOG(ERROR) << "MinidumpThreadList count " << thread_count << - " exceeds maximum " << max_threads_; - return false; - } - - if (thread_count != 0) { - scoped_ptr<MinidumpThreads> threads( - new MinidumpThreads(thread_count, MinidumpThread(minidump_))); - - for (unsigned int thread_index = 0; - thread_index < thread_count; - ++thread_index) { - MinidumpThread* thread = &(*threads)[thread_index]; - - // Assume that the file offset is correct after the last read. - if (!thread->Read()) { - BPLOG(ERROR) << "MinidumpThreadList cannot read thread " << - thread_index << "/" << thread_count; - return false; - } - - uint32_t thread_id; - if (!thread->GetThreadID(&thread_id)) { - BPLOG(ERROR) << "MinidumpThreadList cannot get thread ID for thread " << - thread_index << "/" << thread_count; - return false; - } - - if (GetThreadByID(thread_id)) { - // Another thread with this ID is already in the list. Data error. - BPLOG(ERROR) << "MinidumpThreadList found multiple threads with ID " << - HexString(thread_id) << " at thread " << - thread_index << "/" << thread_count; - return false; - } - id_to_thread_map_[thread_id] = thread; - } - - threads_ = threads.release(); - } - - thread_count_ = thread_count; - - valid_ = true; - return true; -} - - -MinidumpThread* MinidumpThreadList::GetThreadAtIndex(unsigned int index) - const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpThreadList for GetThreadAtIndex"; - return NULL; - } - - if (index >= thread_count_) { - BPLOG(ERROR) << "MinidumpThreadList index out of range: " << - index << "/" << thread_count_; - return NULL; - } - - return &(*threads_)[index]; -} - - -MinidumpThread* MinidumpThreadList::GetThreadByID(uint32_t thread_id) { - // Don't check valid_. Read calls this method before everything is - // validated. It is safe to not check valid_ here. - return id_to_thread_map_[thread_id]; -} - - -void MinidumpThreadList::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpThreadList cannot print invalid data"; - return; - } - - printf("MinidumpThreadList\n"); - printf(" thread_count = %d\n", thread_count_); - printf("\n"); - - for (unsigned int thread_index = 0; - thread_index < thread_count_; - ++thread_index) { - printf("thread[%d]\n", thread_index); - - (*threads_)[thread_index].Print(); - } -} - - -// -// MinidumpModule -// - - -uint32_t MinidumpModule::max_cv_bytes_ = 32768; -uint32_t MinidumpModule::max_misc_bytes_ = 32768; - - -MinidumpModule::MinidumpModule(Minidump* minidump) - : MinidumpObject(minidump), - module_valid_(false), - has_debug_info_(false), - module_(), - name_(NULL), - cv_record_(NULL), - cv_record_signature_(MD_CVINFOUNKNOWN_SIGNATURE), - misc_record_(NULL) { -} - - -MinidumpModule::~MinidumpModule() { - delete name_; - delete cv_record_; - delete misc_record_; -} - - -bool MinidumpModule::Read() { - // Invalidate cached data. - delete name_; - name_ = NULL; - delete cv_record_; - cv_record_ = NULL; - cv_record_signature_ = MD_CVINFOUNKNOWN_SIGNATURE; - delete misc_record_; - misc_record_ = NULL; - - module_valid_ = false; - has_debug_info_ = false; - valid_ = false; - - if (!minidump_->ReadBytes(&module_, MD_MODULE_SIZE)) { - BPLOG(ERROR) << "MinidumpModule cannot read module"; - return false; - } - - if (minidump_->swap()) { - Swap(&module_.base_of_image); - Swap(&module_.size_of_image); - Swap(&module_.checksum); - Swap(&module_.time_date_stamp); - Swap(&module_.module_name_rva); - Swap(&module_.version_info.signature); - Swap(&module_.version_info.struct_version); - Swap(&module_.version_info.file_version_hi); - Swap(&module_.version_info.file_version_lo); - Swap(&module_.version_info.product_version_hi); - Swap(&module_.version_info.product_version_lo); - Swap(&module_.version_info.file_flags_mask); - Swap(&module_.version_info.file_flags); - Swap(&module_.version_info.file_os); - Swap(&module_.version_info.file_type); - Swap(&module_.version_info.file_subtype); - Swap(&module_.version_info.file_date_hi); - Swap(&module_.version_info.file_date_lo); - Swap(&module_.cv_record); - Swap(&module_.misc_record); - // Don't swap reserved fields because their contents are unknown (as - // are their proper widths). - } - - // Check for base + size overflow or undersize. - if (module_.size_of_image == 0 || - module_.size_of_image > - numeric_limits<uint64_t>::max() - module_.base_of_image) { - BPLOG(ERROR) << "MinidumpModule has a module problem, " << - HexString(module_.base_of_image) << "+" << - HexString(module_.size_of_image); - return false; - } - - module_valid_ = true; - return true; -} - - -bool MinidumpModule::ReadAuxiliaryData() { - if (!module_valid_) { - BPLOG(ERROR) << "Invalid MinidumpModule for ReadAuxiliaryData"; - return false; - } - - // Each module must have a name. - name_ = minidump_->ReadString(module_.module_name_rva); - if (!name_) { - BPLOG(ERROR) << "MinidumpModule could not read name"; - return false; - } - - // At this point, we have enough info for the module to be valid. - valid_ = true; - - // CodeView and miscellaneous debug records are only required if the - // module indicates that they exist. - if (module_.cv_record.data_size && !GetCVRecord(NULL)) { - BPLOG(ERROR) << "MinidumpModule has no CodeView record, " - "but one was expected"; - return false; - } - - if (module_.misc_record.data_size && !GetMiscRecord(NULL)) { - BPLOG(ERROR) << "MinidumpModule has no miscellaneous debug record, " - "but one was expected"; - return false; - } - - has_debug_info_ = true; - return true; -} - - -string MinidumpModule::code_file() const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpModule for code_file"; - return ""; - } - - return *name_; -} - - -string MinidumpModule::code_identifier() const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpModule for code_identifier"; - return ""; - } - - if (!has_debug_info_) - return ""; - - MinidumpSystemInfo *minidump_system_info = minidump_->GetSystemInfo(); - if (!minidump_system_info) { - BPLOG(ERROR) << "MinidumpModule code_identifier requires " - "MinidumpSystemInfo"; - return ""; - } - - const MDRawSystemInfo *raw_system_info = minidump_system_info->system_info(); - if (!raw_system_info) { - BPLOG(ERROR) << "MinidumpModule code_identifier requires MDRawSystemInfo"; - return ""; - } - - string identifier; - - switch (raw_system_info->platform_id) { - case MD_OS_WIN32_NT: - case MD_OS_WIN32_WINDOWS: { - // Use the same format that the MS symbol server uses in filesystem - // hierarchies. - char identifier_string[17]; - snprintf(identifier_string, sizeof(identifier_string), "%08X%x", - module_.time_date_stamp, module_.size_of_image); - identifier = identifier_string; - break; - } - - case MD_OS_ANDROID: - case MD_OS_LINUX: { - // If ELF CodeView data is present, return the debug id. - if (cv_record_ && cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { - const MDCVInfoELF* cv_record_elf = - reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]); - assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); - - for (unsigned int build_id_index = 0; - build_id_index < (cv_record_->size() - MDCVInfoELF_minsize); - ++build_id_index) { - char hexbyte[3]; - snprintf(hexbyte, sizeof(hexbyte), "%02x", - cv_record_elf->build_id[build_id_index]); - identifier += hexbyte; - } - break; - } - // Otherwise fall through to the case below. - } - - case MD_OS_MAC_OS_X: - case MD_OS_IOS: - case MD_OS_SOLARIS: - case MD_OS_NACL: - case MD_OS_PS3: { - // TODO(mmentovai): support uuid extension if present, otherwise fall - // back to version (from LC_ID_DYLIB?), otherwise fall back to something - // else. - identifier = "id"; - break; - } - - default: { - // Without knowing what OS generated the dump, we can't generate a good - // identifier. Return an empty string, signalling failure. - BPLOG(ERROR) << "MinidumpModule code_identifier requires known platform, " - "found " << HexString(raw_system_info->platform_id); - break; - } - } - - return identifier; -} - - -string MinidumpModule::debug_file() const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpModule for debug_file"; - return ""; - } - - if (!has_debug_info_) - return ""; - - string file; - // Prefer the CodeView record if present. - if (cv_record_) { - if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { - // It's actually an MDCVInfoPDB70 structure. - const MDCVInfoPDB70* cv_record_70 = - reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]); - assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); - - // GetCVRecord guarantees pdb_file_name is null-terminated. - file = reinterpret_cast<const char*>(cv_record_70->pdb_file_name); - } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { - // It's actually an MDCVInfoPDB20 structure. - const MDCVInfoPDB20* cv_record_20 = - reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); - assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); - - // GetCVRecord guarantees pdb_file_name is null-terminated. - file = reinterpret_cast<const char*>(cv_record_20->pdb_file_name); - } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { - // It's actually an MDCVInfoELF structure. - assert(reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0])-> - cv_signature == MD_CVINFOELF_SIGNATURE); - - // For MDCVInfoELF, the debug file is the code file. - file = *name_; - } - - // If there's a CodeView record but it doesn't match a known signature, - // try the miscellaneous record. - } - - if (file.empty()) { - // No usable CodeView record. Try the miscellaneous debug record. - if (misc_record_) { - const MDImageDebugMisc* misc_record = - reinterpret_cast<const MDImageDebugMisc *>(&(*misc_record_)[0]); - if (!misc_record->unicode) { - // If it's not Unicode, just stuff it into the string. It's unclear - // if misc_record->data is 0-terminated, so use an explicit size. - file = string( - reinterpret_cast<const char*>(misc_record->data), - module_.misc_record.data_size - MDImageDebugMisc_minsize); - } else { - // There's a misc_record but it encodes the debug filename in UTF-16. - // (Actually, because miscellaneous records are so old, it's probably - // UCS-2.) Convert it to UTF-8 for congruity with the other strings - // that this method (and all other methods in the Minidump family) - // return. - - unsigned int bytes = - module_.misc_record.data_size - MDImageDebugMisc_minsize; - if (bytes % 2 == 0) { - unsigned int utf16_words = bytes / 2; - - // UTF16ToUTF8 expects a vector<uint16_t>, so create a temporary one - // and copy the UTF-16 data into it. - vector<uint16_t> string_utf16(utf16_words); - if (utf16_words) - memcpy(&string_utf16[0], &misc_record->data, bytes); - - // GetMiscRecord already byte-swapped the data[] field if it contains - // UTF-16, so pass false as the swap argument. - scoped_ptr<string> new_file(UTF16ToUTF8(string_utf16, false)); - file = *new_file; - } - } - } - } - - // Relatively common case - BPLOG_IF(INFO, file.empty()) << "MinidumpModule could not determine " - "debug_file for " << *name_; - - return file; -} - -static string guid_and_age_to_debug_id(const MDGUID& guid, - uint32_t age) { - char identifier_string[41]; - snprintf(identifier_string, sizeof(identifier_string), - "%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%x", - guid.data1, - guid.data2, - guid.data3, - guid.data4[0], - guid.data4[1], - guid.data4[2], - guid.data4[3], - guid.data4[4], - guid.data4[5], - guid.data4[6], - guid.data4[7], - age); - return identifier_string; -} - -string MinidumpModule::debug_identifier() const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpModule for debug_identifier"; - return ""; - } - - if (!has_debug_info_) - return ""; - - string identifier; - - // Use the CodeView record if present. - if (cv_record_) { - if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { - // It's actually an MDCVInfoPDB70 structure. - const MDCVInfoPDB70* cv_record_70 = - reinterpret_cast<const MDCVInfoPDB70*>(&(*cv_record_)[0]); - assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); - - // Use the same format that the MS symbol server uses in filesystem - // hierarchies. - identifier = guid_and_age_to_debug_id(cv_record_70->signature, - cv_record_70->age); - } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { - // It's actually an MDCVInfoPDB20 structure. - const MDCVInfoPDB20* cv_record_20 = - reinterpret_cast<const MDCVInfoPDB20*>(&(*cv_record_)[0]); - assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); - - // Use the same format that the MS symbol server uses in filesystem - // hierarchies. - char identifier_string[17]; - snprintf(identifier_string, sizeof(identifier_string), - "%08X%x", cv_record_20->signature, cv_record_20->age); - identifier = identifier_string; - } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { - // It's actually an MDCVInfoELF structure. - const MDCVInfoELF* cv_record_elf = - reinterpret_cast<const MDCVInfoELF*>(&(*cv_record_)[0]); - assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); - - // For backwards-compatibility, stuff as many bytes as will fit into - // a MDGUID and use the MS symbol server format as MDCVInfoPDB70 does - // with age = 0. Historically Breakpad would do this during dump - // writing to fit the build id data into a MDCVInfoPDB70 struct. - // The full build id is available by calling code_identifier. - MDGUID guid = {0}; - memcpy(&guid, &cv_record_elf->build_id, - std::min(cv_record_->size() - MDCVInfoELF_minsize, - sizeof(MDGUID))); - identifier = guid_and_age_to_debug_id(guid, 0); - } - } - - // TODO(mmentovai): if there's no usable CodeView record, there might be a - // miscellaneous debug record. It only carries a filename, though, and no - // identifier. I'm not sure what the right thing to do for the identifier - // is in that case, but I don't expect to find many modules without a - // CodeView record (or some other Breakpad extension structure in place of - // a CodeView record). Treat it as an error (empty identifier) for now. - - // TODO(mmentovai): on the Mac, provide fallbacks as in code_identifier(). - - // Relatively common case - BPLOG_IF(INFO, identifier.empty()) << "MinidumpModule could not determine " - "debug_identifier for " << *name_; - - return identifier; -} - - -string MinidumpModule::version() const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpModule for version"; - return ""; - } - - string version; - - if (module_.version_info.signature == MD_VSFIXEDFILEINFO_SIGNATURE && - module_.version_info.struct_version & MD_VSFIXEDFILEINFO_VERSION) { - char version_string[24]; - snprintf(version_string, sizeof(version_string), "%u.%u.%u.%u", - module_.version_info.file_version_hi >> 16, - module_.version_info.file_version_hi & 0xffff, - module_.version_info.file_version_lo >> 16, - module_.version_info.file_version_lo & 0xffff); - version = version_string; - } - - // TODO(mmentovai): possibly support other struct types in place of - // the one used with MD_VSFIXEDFILEINFO_SIGNATURE. We can possibly use - // a different structure that better represents versioning facilities on - // Mac OS X and Linux, instead of forcing them to adhere to the dotted - // quad of 16-bit ints that Windows uses. - - BPLOG_IF(INFO, version.empty()) << "MinidumpModule could not determine " - "version for " << *name_; - - return version; -} - - -CodeModule* MinidumpModule::Copy() const { - 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) { - if (!module_valid_) { - BPLOG(ERROR) << "Invalid MinidumpModule for GetCVRecord"; - return NULL; - } - - if (!cv_record_) { - // This just guards against 0-sized CodeView records; more specific checks - // are used when the signature is checked against various structure types. - if (module_.cv_record.data_size == 0) { - return NULL; - } - - if (!minidump_->SeekSet(module_.cv_record.rva)) { - BPLOG(ERROR) << "MinidumpModule could not seek to CodeView record"; - return NULL; - } - - if (module_.cv_record.data_size > max_cv_bytes_) { - BPLOG(ERROR) << "MinidumpModule CodeView record size " << - module_.cv_record.data_size << " exceeds maximum " << - max_cv_bytes_; - return NULL; - } - - // Allocating something that will be accessed as MDCVInfoPDB70 or - // MDCVInfoPDB20 but is allocated as uint8_t[] can cause alignment - // problems. x86 and ppc are able to cope, though. This allocation - // style is needed because the MDCVInfoPDB70 or MDCVInfoPDB20 are - // variable-sized due to their pdb_file_name fields; these structures - // are not MDCVInfoPDB70_minsize or MDCVInfoPDB20_minsize and treating - // them as such would result in incomplete structures or overruns. - scoped_ptr< vector<uint8_t> > cv_record( - new vector<uint8_t>(module_.cv_record.data_size)); - - if (!minidump_->ReadBytes(&(*cv_record)[0], module_.cv_record.data_size)) { - BPLOG(ERROR) << "MinidumpModule could not read CodeView record"; - return NULL; - } - - uint32_t signature = MD_CVINFOUNKNOWN_SIGNATURE; - if (module_.cv_record.data_size > sizeof(signature)) { - MDCVInfoPDB70* cv_record_signature = - reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]); - signature = cv_record_signature->cv_signature; - if (minidump_->swap()) - Swap(&signature); - } - - if (signature == MD_CVINFOPDB70_SIGNATURE) { - // Now that the structure type is known, recheck the size. - if (MDCVInfoPDB70_minsize > module_.cv_record.data_size) { - BPLOG(ERROR) << "MinidumpModule CodeView7 record size mismatch, " << - MDCVInfoPDB70_minsize << " > " << - module_.cv_record.data_size; - return NULL; - } - - if (minidump_->swap()) { - MDCVInfoPDB70* cv_record_70 = - reinterpret_cast<MDCVInfoPDB70*>(&(*cv_record)[0]); - Swap(&cv_record_70->cv_signature); - Swap(&cv_record_70->signature); - Swap(&cv_record_70->age); - // Don't swap cv_record_70.pdb_file_name because it's an array of 8-bit - // quantities. (It's a path, is it UTF-8?) - } - - // The last field of either structure is null-terminated 8-bit character - // data. Ensure that it's null-terminated. - if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { - BPLOG(ERROR) << "MinidumpModule CodeView7 record string is not " - "0-terminated"; - return NULL; - } - } else if (signature == MD_CVINFOPDB20_SIGNATURE) { - // Now that the structure type is known, recheck the size. - if (MDCVInfoPDB20_minsize > module_.cv_record.data_size) { - BPLOG(ERROR) << "MinidumpModule CodeView2 record size mismatch, " << - MDCVInfoPDB20_minsize << " > " << - module_.cv_record.data_size; - return NULL; - } - if (minidump_->swap()) { - MDCVInfoPDB20* cv_record_20 = - reinterpret_cast<MDCVInfoPDB20*>(&(*cv_record)[0]); - Swap(&cv_record_20->cv_header.signature); - Swap(&cv_record_20->cv_header.offset); - Swap(&cv_record_20->signature); - Swap(&cv_record_20->age); - // Don't swap cv_record_20.pdb_file_name because it's an array of 8-bit - // quantities. (It's a path, is it UTF-8?) - } - - // The last field of either structure is null-terminated 8-bit character - // data. Ensure that it's null-terminated. - if ((*cv_record)[module_.cv_record.data_size - 1] != '\0') { - BPLOG(ERROR) << "MindumpModule CodeView2 record string is not " - "0-terminated"; - return NULL; - } - } else if (signature == MD_CVINFOELF_SIGNATURE) { - // Now that the structure type is known, recheck the size. - if (MDCVInfoELF_minsize > module_.cv_record.data_size) { - BPLOG(ERROR) << "MinidumpModule CodeViewELF record size mismatch, " << - MDCVInfoELF_minsize << " > " << - module_.cv_record.data_size; - return NULL; - } - // There's nothing to swap in CVInfoELF, it's just raw bytes. - } - - // If the signature doesn't match something above, it's not something - // that Breakpad can presently handle directly. Because some modules in - // the wild contain such CodeView records as MD_CVINFOCV50_SIGNATURE, - // don't bail out here - allow the data to be returned to the user, - // although byte-swapping can't be done. - - // Store the vector type because that's how storage was allocated, but - // return it casted to uint8_t*. - cv_record_ = cv_record.release(); - cv_record_signature_ = signature; - } - - if (size) - *size = module_.cv_record.data_size; - - return &(*cv_record_)[0]; -} - - -const MDImageDebugMisc* MinidumpModule::GetMiscRecord(uint32_t* size) { - if (!module_valid_) { - BPLOG(ERROR) << "Invalid MinidumpModule for GetMiscRecord"; - return NULL; - } - - if (!misc_record_) { - if (module_.misc_record.data_size == 0) { - return NULL; - } - - if (MDImageDebugMisc_minsize > module_.misc_record.data_size) { - BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record " - "size mismatch, " << MDImageDebugMisc_minsize << " > " << - module_.misc_record.data_size; - return NULL; - } - - if (!minidump_->SeekSet(module_.misc_record.rva)) { - BPLOG(ERROR) << "MinidumpModule could not seek to miscellaneous " - "debugging record"; - return NULL; - } - - if (module_.misc_record.data_size > max_misc_bytes_) { - BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record size " << - module_.misc_record.data_size << " exceeds maximum " << - max_misc_bytes_; - return NULL; - } - - // Allocating something that will be accessed as MDImageDebugMisc but - // is allocated as uint8_t[] can cause alignment problems. x86 and - // ppc are able to cope, though. This allocation style is needed - // because the MDImageDebugMisc is variable-sized due to its data field; - // this structure is not MDImageDebugMisc_minsize and treating it as such - // would result in an incomplete structure or an overrun. - scoped_ptr< vector<uint8_t> > misc_record_mem( - new vector<uint8_t>(module_.misc_record.data_size)); - MDImageDebugMisc* misc_record = - reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_mem)[0]); - - if (!minidump_->ReadBytes(misc_record, module_.misc_record.data_size)) { - BPLOG(ERROR) << "MinidumpModule could not read miscellaneous debugging " - "record"; - return NULL; - } - - if (minidump_->swap()) { - Swap(&misc_record->data_type); - Swap(&misc_record->length); - // Don't swap misc_record.unicode because it's an 8-bit quantity. - // Don't swap the reserved fields for the same reason, and because - // they don't contain any valid data. - if (misc_record->unicode) { - // There is a potential alignment problem, but shouldn't be a problem - // in practice due to the layout of MDImageDebugMisc. - uint16_t* data16 = reinterpret_cast<uint16_t*>(&(misc_record->data)); - unsigned int dataBytes = module_.misc_record.data_size - - MDImageDebugMisc_minsize; - Swap(data16, dataBytes); - } - } - - if (module_.misc_record.data_size != misc_record->length) { - BPLOG(ERROR) << "MinidumpModule miscellaneous debugging record data " - "size mismatch, " << module_.misc_record.data_size << - " != " << misc_record->length; - return NULL; - } - - // Store the vector type because that's how storage was allocated, but - // return it casted to MDImageDebugMisc*. - misc_record_ = misc_record_mem.release(); - } - - if (size) - *size = module_.misc_record.data_size; - - return reinterpret_cast<MDImageDebugMisc*>(&(*misc_record_)[0]); -} - - -void MinidumpModule::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpModule cannot print invalid data"; - return; - } - - printf("MDRawModule\n"); - printf(" base_of_image = 0x%" PRIx64 "\n", - module_.base_of_image); - printf(" size_of_image = 0x%x\n", - module_.size_of_image); - printf(" checksum = 0x%x\n", - module_.checksum); - printf(" time_date_stamp = 0x%x %s\n", - module_.time_date_stamp, - TimeTToUTCString(module_.time_date_stamp).c_str()); - printf(" module_name_rva = 0x%x\n", - module_.module_name_rva); - printf(" version_info.signature = 0x%x\n", - module_.version_info.signature); - printf(" version_info.struct_version = 0x%x\n", - module_.version_info.struct_version); - printf(" version_info.file_version = 0x%x:0x%x\n", - module_.version_info.file_version_hi, - module_.version_info.file_version_lo); - printf(" version_info.product_version = 0x%x:0x%x\n", - module_.version_info.product_version_hi, - module_.version_info.product_version_lo); - printf(" version_info.file_flags_mask = 0x%x\n", - module_.version_info.file_flags_mask); - printf(" version_info.file_flags = 0x%x\n", - module_.version_info.file_flags); - printf(" version_info.file_os = 0x%x\n", - module_.version_info.file_os); - printf(" version_info.file_type = 0x%x\n", - module_.version_info.file_type); - printf(" version_info.file_subtype = 0x%x\n", - module_.version_info.file_subtype); - printf(" version_info.file_date = 0x%x:0x%x\n", - module_.version_info.file_date_hi, - module_.version_info.file_date_lo); - printf(" cv_record.data_size = %d\n", - module_.cv_record.data_size); - printf(" cv_record.rva = 0x%x\n", - module_.cv_record.rva); - printf(" misc_record.data_size = %d\n", - module_.misc_record.data_size); - printf(" misc_record.rva = 0x%x\n", - module_.misc_record.rva); - - printf(" (code_file) = \"%s\"\n", code_file().c_str()); - printf(" (code_identifier) = \"%s\"\n", - code_identifier().c_str()); - - uint32_t cv_record_size; - const uint8_t *cv_record = GetCVRecord(&cv_record_size); - if (cv_record) { - if (cv_record_signature_ == MD_CVINFOPDB70_SIGNATURE) { - const MDCVInfoPDB70* cv_record_70 = - reinterpret_cast<const MDCVInfoPDB70*>(cv_record); - assert(cv_record_70->cv_signature == MD_CVINFOPDB70_SIGNATURE); - - printf(" (cv_record).cv_signature = 0x%x\n", - cv_record_70->cv_signature); - printf(" (cv_record).signature = %08x-%04x-%04x-%02x%02x-", - cv_record_70->signature.data1, - cv_record_70->signature.data2, - cv_record_70->signature.data3, - cv_record_70->signature.data4[0], - cv_record_70->signature.data4[1]); - for (unsigned int guidIndex = 2; - guidIndex < 8; - ++guidIndex) { - printf("%02x", cv_record_70->signature.data4[guidIndex]); - } - printf("\n"); - printf(" (cv_record).age = %d\n", - cv_record_70->age); - printf(" (cv_record).pdb_file_name = \"%s\"\n", - cv_record_70->pdb_file_name); - } else if (cv_record_signature_ == MD_CVINFOPDB20_SIGNATURE) { - const MDCVInfoPDB20* cv_record_20 = - reinterpret_cast<const MDCVInfoPDB20*>(cv_record); - assert(cv_record_20->cv_header.signature == MD_CVINFOPDB20_SIGNATURE); - - printf(" (cv_record).cv_header.signature = 0x%x\n", - cv_record_20->cv_header.signature); - printf(" (cv_record).cv_header.offset = 0x%x\n", - cv_record_20->cv_header.offset); - printf(" (cv_record).signature = 0x%x %s\n", - cv_record_20->signature, - TimeTToUTCString(cv_record_20->signature).c_str()); - printf(" (cv_record).age = %d\n", - cv_record_20->age); - printf(" (cv_record).pdb_file_name = \"%s\"\n", - cv_record_20->pdb_file_name); - } else if (cv_record_signature_ == MD_CVINFOELF_SIGNATURE) { - const MDCVInfoELF* cv_record_elf = - reinterpret_cast<const MDCVInfoELF*>(cv_record); - assert(cv_record_elf->cv_signature == MD_CVINFOELF_SIGNATURE); - - printf(" (cv_record).cv_signature = 0x%x\n", - cv_record_elf->cv_signature); - printf(" (cv_record).build_id = "); - for (unsigned int build_id_index = 0; - build_id_index < (cv_record_size - MDCVInfoELF_minsize); - ++build_id_index) { - printf("%02x", cv_record_elf->build_id[build_id_index]); - } - printf("\n"); - } else { - printf(" (cv_record) = "); - for (unsigned int cv_byte_index = 0; - cv_byte_index < cv_record_size; - ++cv_byte_index) { - printf("%02x", cv_record[cv_byte_index]); - } - printf("\n"); - } - } else { - printf(" (cv_record) = (null)\n"); - } - - const MDImageDebugMisc* misc_record = GetMiscRecord(NULL); - if (misc_record) { - printf(" (misc_record).data_type = 0x%x\n", - misc_record->data_type); - printf(" (misc_record).length = 0x%x\n", - misc_record->length); - printf(" (misc_record).unicode = %d\n", - misc_record->unicode); - if (misc_record->unicode) { - string misc_record_data_utf8; - ConvertUTF16BufferToUTF8String( - reinterpret_cast<const uint16_t*>(misc_record->data), - misc_record->length - offsetof(MDImageDebugMisc, data), - &misc_record_data_utf8, - false); // already swapped - printf(" (misc_record).data = \"%s\"\n", - misc_record_data_utf8.c_str()); - } else { - printf(" (misc_record).data = \"%s\"\n", - misc_record->data); - } - } else { - printf(" (misc_record) = (null)\n"); - } - - printf(" (debug_file) = \"%s\"\n", debug_file().c_str()); - printf(" (debug_identifier) = \"%s\"\n", - debug_identifier().c_str()); - printf(" (version) = \"%s\"\n", version().c_str()); - printf("\n"); -} - - -// -// MinidumpModuleList -// - - -uint32_t MinidumpModuleList::max_modules_ = 1024; - - -MinidumpModuleList::MinidumpModuleList(Minidump* minidump) - : MinidumpStream(minidump), - range_map_(new RangeMap<uint64_t, unsigned int>()), - modules_(NULL), - module_count_(0) { - range_map_->SetEnableShrinkDown(minidump_->IsAndroid()); -} - - -MinidumpModuleList::~MinidumpModuleList() { - delete range_map_; - delete modules_; -} - - -bool MinidumpModuleList::Read(uint32_t expected_size) { - // Invalidate cached data. - range_map_->Clear(); - delete modules_; - modules_ = NULL; - module_count_ = 0; - - valid_ = false; - - uint32_t module_count; - if (expected_size < sizeof(module_count)) { - BPLOG(ERROR) << "MinidumpModuleList count size mismatch, " << - expected_size << " < " << sizeof(module_count); - return false; - } - if (!minidump_->ReadBytes(&module_count, sizeof(module_count))) { - BPLOG(ERROR) << "MinidumpModuleList could not read module count"; - return false; - } - - if (minidump_->swap()) - Swap(&module_count); - - if (module_count > numeric_limits<uint32_t>::max() / MD_MODULE_SIZE) { - BPLOG(ERROR) << "MinidumpModuleList module count " << module_count << - " would cause multiplication overflow"; - return false; - } - - if (expected_size != sizeof(module_count) + - module_count * MD_MODULE_SIZE) { - // may be padded with 4 bytes on 64bit ABIs for alignment - if (expected_size == sizeof(module_count) + 4 + - module_count * MD_MODULE_SIZE) { - uint32_t useless; - if (!minidump_->ReadBytes(&useless, 4)) { - BPLOG(ERROR) << "MinidumpModuleList cannot read modulelist padded " - "bytes"; - return false; - } - } else { - BPLOG(ERROR) << "MinidumpModuleList size mismatch, " << expected_size << - " != " << sizeof(module_count) + - module_count * MD_MODULE_SIZE; - return false; - } - } - - if (module_count > max_modules_) { - BPLOG(ERROR) << "MinidumpModuleList count " << module_count_ << - " exceeds maximum " << max_modules_; - return false; - } - - if (module_count != 0) { - scoped_ptr<MinidumpModules> modules( - new MinidumpModules(module_count, MinidumpModule(minidump_))); - - for (unsigned int module_index = 0; - module_index < module_count; - ++module_index) { - MinidumpModule* module = &(*modules)[module_index]; - - // Assume that the file offset is correct after the last read. - if (!module->Read()) { - BPLOG(ERROR) << "MinidumpModuleList could not read module " << - module_index << "/" << module_count; - return false; - } - } - - // Loop through the module list once more to read additional data and - // build the range map. This is done in a second pass because - // MinidumpModule::ReadAuxiliaryData seeks around, and if it were - // included in the loop above, additional seeks would be needed where - // none are now to read contiguous data. - uint64_t last_end_address = 0; - for (unsigned int module_index = 0; - module_index < module_count; - ++module_index) { - MinidumpModule* module = &(*modules)[module_index]; - - // ReadAuxiliaryData fails if any data that the module indicates should - // exist is missing, but we treat some such cases as valid anyway. See - // issue #222: if a debugging record is of a format that's too large to - // handle, it shouldn't render the entire dump invalid. Check module - // validity before giving up. - if (!module->ReadAuxiliaryData() && !module->valid()) { - BPLOG(ERROR) << "MinidumpModuleList could not read required module " - "auxiliary data for module " << - module_index << "/" << module_count; - return false; - } - - // It is safe to use module->code_file() after successfully calling - // module->ReadAuxiliaryData or noting that the module is valid. - - uint64_t base_address = module->base_address(); - uint64_t module_size = module->size(); - if (base_address == static_cast<uint64_t>(-1)) { - BPLOG(ERROR) << "MinidumpModuleList found bad base address " - "for module " << module_index << "/" << module_count << - ", " << module->code_file(); - return false; - } - - if (!range_map_->StoreRange(base_address, module_size, module_index)) { - // Android's shared memory implementation /dev/ashmem can contain - // duplicate entries for JITted code, so ignore these. - // TODO(wfh): Remove this code when Android is fixed. - // See https://crbug.com/439531 - const string kDevAshmem("/dev/ashmem/"); - if (module->code_file().compare( - 0, kDevAshmem.length(), kDevAshmem) != 0) { - if (base_address < last_end_address) { - // If failed due to apparent range overlap the cause may be - // the client correction applied for Android packed relocations. - // If this is the case, back out the client correction and retry. - module_size -= last_end_address - base_address; - base_address = last_end_address; - if (!range_map_->StoreRange(base_address, - module_size, module_index)) { - BPLOG(ERROR) << "MinidumpModuleList could not store module " << - module_index << "/" << module_count << ", " << - module->code_file() << ", " << - HexString(base_address) << "+" << - HexString(module_size) << ", after adjusting"; - return false; - } - } else { - BPLOG(ERROR) << "MinidumpModuleList could not store module " << - module_index << "/" << module_count << ", " << - module->code_file() << ", " << - HexString(base_address) << "+" << - HexString(module_size); - return false; - } - } else { - BPLOG(INFO) << "MinidumpModuleList ignoring overlapping module " << - module_index << "/" << module_count << ", " << - module->code_file() << ", " << - HexString(base_address) << "+" << - HexString(module_size); - } - } - last_end_address = base_address + module_size; - } - - modules_ = modules.release(); - } - - module_count_ = module_count; - - valid_ = true; - return true; -} - - -const MinidumpModule* MinidumpModuleList::GetModuleForAddress( - uint64_t address) const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleForAddress"; - return NULL; - } - - unsigned int module_index; - if (!range_map_->RetrieveRange(address, &module_index, NULL /* base */, - NULL /* delta */, NULL /* size */)) { - BPLOG(INFO) << "MinidumpModuleList has no module at " << - HexString(address); - return NULL; - } - - return GetModuleAtIndex(module_index); -} - - -const MinidumpModule* MinidumpModuleList::GetMainModule() const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpModuleList for GetMainModule"; - return NULL; - } - - // The main code module is the first one present in a minidump file's - // MDRawModuleList. - return GetModuleAtIndex(0); -} - - -const MinidumpModule* MinidumpModuleList::GetModuleAtSequence( - unsigned int sequence) const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtSequence"; - return NULL; - } - - if (sequence >= module_count_) { - BPLOG(ERROR) << "MinidumpModuleList sequence out of range: " << - sequence << "/" << module_count_; - return NULL; - } - - unsigned int module_index; - if (!range_map_->RetrieveRangeAtIndex(sequence, &module_index, - NULL /* base */, NULL /* delta */, - NULL /* size */)) { - BPLOG(ERROR) << "MinidumpModuleList has no module at sequence " << sequence; - return NULL; - } - - return GetModuleAtIndex(module_index); -} - - -const MinidumpModule* MinidumpModuleList::GetModuleAtIndex( - unsigned int index) const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpModuleList for GetModuleAtIndex"; - return NULL; - } - - if (index >= module_count_) { - BPLOG(ERROR) << "MinidumpModuleList index out of range: " << - index << "/" << module_count_; - return NULL; - } - - return &(*modules_)[index]; -} - - -const CodeModules* MinidumpModuleList::Copy() const { - 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() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpModuleList cannot print invalid data"; - return; - } - - printf("MinidumpModuleList\n"); - printf(" module_count = %d\n", module_count_); - printf("\n"); - - for (unsigned int module_index = 0; - module_index < module_count_; - ++module_index) { - printf("module[%d]\n", module_index); - - (*modules_)[module_index].Print(); - } -} - - -// -// MinidumpMemoryList -// - - -uint32_t MinidumpMemoryList::max_regions_ = 4096; - - -MinidumpMemoryList::MinidumpMemoryList(Minidump* minidump) - : MinidumpStream(minidump), - range_map_(new RangeMap<uint64_t, unsigned int>()), - descriptors_(NULL), - regions_(NULL), - region_count_(0) { -} - - -MinidumpMemoryList::~MinidumpMemoryList() { - delete range_map_; - delete descriptors_; - delete regions_; -} - - -bool MinidumpMemoryList::Read(uint32_t expected_size) { - // Invalidate cached data. - delete descriptors_; - descriptors_ = NULL; - delete regions_; - regions_ = NULL; - range_map_->Clear(); - region_count_ = 0; - - valid_ = false; - - uint32_t region_count; - if (expected_size < sizeof(region_count)) { - BPLOG(ERROR) << "MinidumpMemoryList count size mismatch, " << - expected_size << " < " << sizeof(region_count); - return false; - } - if (!minidump_->ReadBytes(®ion_count, sizeof(region_count))) { - BPLOG(ERROR) << "MinidumpMemoryList could not read memory region count"; - return false; - } - - if (minidump_->swap()) - Swap(®ion_count); - - if (region_count > - numeric_limits<uint32_t>::max() / sizeof(MDMemoryDescriptor)) { - BPLOG(ERROR) << "MinidumpMemoryList region count " << region_count << - " would cause multiplication overflow"; - return false; - } - - if (expected_size != sizeof(region_count) + - region_count * sizeof(MDMemoryDescriptor)) { - // may be padded with 4 bytes on 64bit ABIs for alignment - if (expected_size == sizeof(region_count) + 4 + - region_count * sizeof(MDMemoryDescriptor)) { - uint32_t useless; - if (!minidump_->ReadBytes(&useless, 4)) { - BPLOG(ERROR) << "MinidumpMemoryList cannot read memorylist padded " - "bytes"; - return false; - } - } else { - BPLOG(ERROR) << "MinidumpMemoryList size mismatch, " << expected_size << - " != " << sizeof(region_count) + - region_count * sizeof(MDMemoryDescriptor); - return false; - } - } - - if (region_count > max_regions_) { - BPLOG(ERROR) << "MinidumpMemoryList count " << region_count << - " exceeds maximum " << max_regions_; - return false; - } - - if (region_count != 0) { - scoped_ptr<MemoryDescriptors> descriptors( - new MemoryDescriptors(region_count)); - - // Read the entire array in one fell swoop, instead of reading one entry - // at a time in the loop. - if (!minidump_->ReadBytes(&(*descriptors)[0], - sizeof(MDMemoryDescriptor) * region_count)) { - BPLOG(ERROR) << "MinidumpMemoryList could not read memory region list"; - return false; - } - - scoped_ptr<MemoryRegions> regions( - new MemoryRegions(region_count, MinidumpMemoryRegion(minidump_))); - - for (unsigned int region_index = 0; - region_index < region_count; - ++region_index) { - MDMemoryDescriptor* descriptor = &(*descriptors)[region_index]; - - if (minidump_->swap()) - Swap(descriptor); - - uint64_t base_address = descriptor->start_of_memory_range; - uint32_t region_size = descriptor->memory.data_size; - - // Check for base + size overflow or undersize. - if (region_size == 0 || - region_size > numeric_limits<uint64_t>::max() - base_address) { - BPLOG(ERROR) << "MinidumpMemoryList has a memory region problem, " << - " region " << region_index << "/" << region_count << - ", " << HexString(base_address) << "+" << - HexString(region_size); - return false; - } - - if (!range_map_->StoreRange(base_address, region_size, region_index)) { - BPLOG(ERROR) << "MinidumpMemoryList could not store memory region " << - region_index << "/" << region_count << ", " << - HexString(base_address) << "+" << - HexString(region_size); - return false; - } - - (*regions)[region_index].SetDescriptor(descriptor); - } - - descriptors_ = descriptors.release(); - regions_ = regions.release(); - } - - region_count_ = region_count; - - valid_ = true; - return true; -} - - -MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionAtIndex( - unsigned int index) { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionAtIndex"; - return NULL; - } - - if (index >= region_count_) { - BPLOG(ERROR) << "MinidumpMemoryList index out of range: " << - index << "/" << region_count_; - return NULL; - } - - return &(*regions_)[index]; -} - - -MinidumpMemoryRegion* MinidumpMemoryList::GetMemoryRegionForAddress( - uint64_t address) { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpMemoryList for GetMemoryRegionForAddress"; - return NULL; - } - - unsigned int region_index; - if (!range_map_->RetrieveRange(address, ®ion_index, NULL /* base */, - NULL /* delta */, NULL /* size */)) { - BPLOG(INFO) << "MinidumpMemoryList has no memory region at " << - HexString(address); - return NULL; - } - - return GetMemoryRegionAtIndex(region_index); -} - - -void MinidumpMemoryList::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpMemoryList cannot print invalid data"; - return; - } - - printf("MinidumpMemoryList\n"); - printf(" region_count = %d\n", region_count_); - printf("\n"); - - for (unsigned int region_index = 0; - region_index < region_count_; - ++region_index) { - MDMemoryDescriptor* descriptor = &(*descriptors_)[region_index]; - printf("region[%d]\n", region_index); - printf("MDMemoryDescriptor\n"); - printf(" start_of_memory_range = 0x%" PRIx64 "\n", - descriptor->start_of_memory_range); - printf(" memory.data_size = 0x%x\n", descriptor->memory.data_size); - printf(" memory.rva = 0x%x\n", descriptor->memory.rva); - MinidumpMemoryRegion* region = GetMemoryRegionAtIndex(region_index); - if (region) { - printf("Memory\n"); - region->Print(); - } else { - printf("No memory\n"); - } - printf("\n"); - } -} - - -// -// MinidumpException -// - - -MinidumpException::MinidumpException(Minidump* minidump) - : MinidumpStream(minidump), - exception_(), - context_(NULL) { -} - - -MinidumpException::~MinidumpException() { - delete context_; -} - - -bool MinidumpException::Read(uint32_t expected_size) { - // Invalidate cached data. - delete context_; - context_ = NULL; - - valid_ = false; - - if (expected_size != sizeof(exception_)) { - BPLOG(ERROR) << "MinidumpException size mismatch, " << expected_size << - " != " << sizeof(exception_); - return false; - } - - if (!minidump_->ReadBytes(&exception_, sizeof(exception_))) { - BPLOG(ERROR) << "MinidumpException cannot read exception"; - return false; - } - - if (minidump_->swap()) { - Swap(&exception_.thread_id); - // exception_.__align is for alignment only and does not need to be - // swapped. - Swap(&exception_.exception_record.exception_code); - Swap(&exception_.exception_record.exception_flags); - Swap(&exception_.exception_record.exception_record); - Swap(&exception_.exception_record.exception_address); - Swap(&exception_.exception_record.number_parameters); - // exception_.exception_record.__align is for alignment only and does not - // need to be swapped. - for (unsigned int parameter_index = 0; - parameter_index < MD_EXCEPTION_MAXIMUM_PARAMETERS; - ++parameter_index) { - Swap(&exception_.exception_record.exception_information[parameter_index]); - } - Swap(&exception_.thread_context); - } - - valid_ = true; - return true; -} - - -bool MinidumpException::GetThreadID(uint32_t *thread_id) const { - BPLOG_IF(ERROR, !thread_id) << "MinidumpException::GetThreadID requires " - "|thread_id|"; - assert(thread_id); - *thread_id = 0; - - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpException for GetThreadID"; - return false; - } - - *thread_id = exception_.thread_id; - return true; -} - - -MinidumpContext* MinidumpException::GetContext() { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpException for GetContext"; - return NULL; - } - - if (!context_) { - if (!minidump_->SeekSet(exception_.thread_context.rva)) { - BPLOG(ERROR) << "MinidumpException cannot seek to context"; - return NULL; - } - - scoped_ptr<MinidumpContext> context(new MinidumpContext(minidump_)); - - // Don't log as an error if we can still fall back on the thread's context - // (which must be possible if we got this far.) - if (!context->Read(exception_.thread_context.data_size)) { - BPLOG(INFO) << "MinidumpException cannot read context"; - return NULL; - } - - context_ = context.release(); - } - - return context_; -} - - -void MinidumpException::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpException cannot print invalid data"; - return; - } - - printf("MDException\n"); - printf(" thread_id = 0x%x\n", - exception_.thread_id); - printf(" exception_record.exception_code = 0x%x\n", - exception_.exception_record.exception_code); - printf(" exception_record.exception_flags = 0x%x\n", - exception_.exception_record.exception_flags); - printf(" exception_record.exception_record = 0x%" PRIx64 "\n", - exception_.exception_record.exception_record); - printf(" exception_record.exception_address = 0x%" PRIx64 "\n", - exception_.exception_record.exception_address); - printf(" exception_record.number_parameters = %d\n", - exception_.exception_record.number_parameters); - for (unsigned int parameterIndex = 0; - parameterIndex < exception_.exception_record.number_parameters; - ++parameterIndex) { - printf(" exception_record.exception_information[%2d] = 0x%" PRIx64 "\n", - parameterIndex, - exception_.exception_record.exception_information[parameterIndex]); - } - printf(" thread_context.data_size = %d\n", - exception_.thread_context.data_size); - printf(" thread_context.rva = 0x%x\n", - exception_.thread_context.rva); - MinidumpContext* context = GetContext(); - if (context) { - printf("\n"); - context->Print(); - } else { - printf(" (no context)\n"); - printf("\n"); - } -} - -// -// MinidumpAssertion -// - - -MinidumpAssertion::MinidumpAssertion(Minidump* minidump) - : MinidumpStream(minidump), - assertion_(), - expression_(), - function_(), - file_() { -} - - -MinidumpAssertion::~MinidumpAssertion() { -} - - -bool MinidumpAssertion::Read(uint32_t expected_size) { - // Invalidate cached data. - valid_ = false; - - if (expected_size != sizeof(assertion_)) { - BPLOG(ERROR) << "MinidumpAssertion size mismatch, " << expected_size << - " != " << sizeof(assertion_); - return false; - } - - if (!minidump_->ReadBytes(&assertion_, sizeof(assertion_))) { - BPLOG(ERROR) << "MinidumpAssertion cannot read assertion"; - return false; - } - - // Each of {expression, function, file} is a UTF-16 string, - // we'll convert them to UTF-8 for ease of use. - ConvertUTF16BufferToUTF8String(assertion_.expression, - sizeof(assertion_.expression), &expression_, - minidump_->swap()); - ConvertUTF16BufferToUTF8String(assertion_.function, - sizeof(assertion_.function), &function_, - minidump_->swap()); - ConvertUTF16BufferToUTF8String(assertion_.file, sizeof(assertion_.file), - &file_, minidump_->swap()); - - if (minidump_->swap()) { - Swap(&assertion_.line); - Swap(&assertion_.type); - } - - valid_ = true; - return true; -} - -void MinidumpAssertion::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpAssertion cannot print invalid data"; - return; - } - - printf("MDAssertion\n"); - printf(" expression = %s\n", - expression_.c_str()); - printf(" function = %s\n", - function_.c_str()); - printf(" file = %s\n", - file_.c_str()); - printf(" line = %u\n", - assertion_.line); - printf(" type = %u\n", - assertion_.type); - printf("\n"); -} - -// -// MinidumpSystemInfo -// - - -MinidumpSystemInfo::MinidumpSystemInfo(Minidump* minidump) - : MinidumpStream(minidump), - system_info_(), - csd_version_(NULL), - cpu_vendor_(NULL) { -} - - -MinidumpSystemInfo::~MinidumpSystemInfo() { - delete csd_version_; - delete cpu_vendor_; -} - - -bool MinidumpSystemInfo::Read(uint32_t expected_size) { - // Invalidate cached data. - delete csd_version_; - csd_version_ = NULL; - delete cpu_vendor_; - cpu_vendor_ = NULL; - - valid_ = false; - - if (expected_size != sizeof(system_info_)) { - BPLOG(ERROR) << "MinidumpSystemInfo size mismatch, " << expected_size << - " != " << sizeof(system_info_); - return false; - } - - if (!minidump_->ReadBytes(&system_info_, sizeof(system_info_))) { - BPLOG(ERROR) << "MinidumpSystemInfo cannot read system info"; - return false; - } - - if (minidump_->swap()) { - Swap(&system_info_.processor_architecture); - Swap(&system_info_.processor_level); - Swap(&system_info_.processor_revision); - // number_of_processors and product_type are 8-bit quantities and need no - // swapping. - Swap(&system_info_.major_version); - Swap(&system_info_.minor_version); - Swap(&system_info_.build_number); - Swap(&system_info_.platform_id); - Swap(&system_info_.csd_version_rva); - Swap(&system_info_.suite_mask); - // Don't swap the reserved2 field because its contents are unknown. - - if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || - system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) { - for (unsigned int i = 0; i < 3; ++i) - Swap(&system_info_.cpu.x86_cpu_info.vendor_id[i]); - Swap(&system_info_.cpu.x86_cpu_info.version_information); - Swap(&system_info_.cpu.x86_cpu_info.feature_information); - Swap(&system_info_.cpu.x86_cpu_info.amd_extended_cpu_features); - } else { - for (unsigned int i = 0; i < 2; ++i) - Swap(&system_info_.cpu.other_cpu_info.processor_features[i]); - } - } - - valid_ = true; - return true; -} - - -string MinidumpSystemInfo::GetOS() { - string os; - - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetOS"; - return os; - } - - switch (system_info_.platform_id) { - case MD_OS_WIN32_NT: - case MD_OS_WIN32_WINDOWS: - os = "windows"; - break; - - case MD_OS_MAC_OS_X: - os = "mac"; - break; - - case MD_OS_IOS: - os = "ios"; - break; - - case MD_OS_LINUX: - os = "linux"; - break; - - case MD_OS_SOLARIS: - os = "solaris"; - break; - - case MD_OS_ANDROID: - os = "android"; - break; - - case MD_OS_PS3: - os = "ps3"; - break; - - case MD_OS_NACL: - os = "nacl"; - break; - - default: - BPLOG(ERROR) << "MinidumpSystemInfo unknown OS for platform " << - HexString(system_info_.platform_id); - break; - } - - return os; -} - - -string MinidumpSystemInfo::GetCPU() { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPU"; - return ""; - } - - string cpu; - - switch (system_info_.processor_architecture) { - case MD_CPU_ARCHITECTURE_X86: - case MD_CPU_ARCHITECTURE_X86_WIN64: - cpu = "x86"; - break; - - case MD_CPU_ARCHITECTURE_AMD64: - cpu = "x86-64"; - break; - - case MD_CPU_ARCHITECTURE_PPC: - cpu = "ppc"; - break; - - case MD_CPU_ARCHITECTURE_PPC64: - cpu = "ppc64"; - break; - - case MD_CPU_ARCHITECTURE_SPARC: - cpu = "sparc"; - break; - - case MD_CPU_ARCHITECTURE_ARM: - cpu = "arm"; - break; - - case MD_CPU_ARCHITECTURE_ARM64: - cpu = "arm64"; - break; - - default: - BPLOG(ERROR) << "MinidumpSystemInfo unknown CPU for architecture " << - HexString(system_info_.processor_architecture); - break; - } - - return cpu; -} - - -const string* MinidumpSystemInfo::GetCSDVersion() { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCSDVersion"; - return NULL; - } - - if (!csd_version_) - csd_version_ = minidump_->ReadString(system_info_.csd_version_rva); - - BPLOG_IF(ERROR, !csd_version_) << "MinidumpSystemInfo could not read " - "CSD version"; - - return csd_version_; -} - - -const string* MinidumpSystemInfo::GetCPUVendor() { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpSystemInfo for GetCPUVendor"; - return NULL; - } - - // CPU vendor information can only be determined from x86 minidumps. - if (!cpu_vendor_ && - (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || - system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64)) { - char cpu_vendor_string[13]; - snprintf(cpu_vendor_string, sizeof(cpu_vendor_string), - "%c%c%c%c%c%c%c%c%c%c%c%c", - system_info_.cpu.x86_cpu_info.vendor_id[0] & 0xff, - (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 8) & 0xff, - (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 16) & 0xff, - (system_info_.cpu.x86_cpu_info.vendor_id[0] >> 24) & 0xff, - system_info_.cpu.x86_cpu_info.vendor_id[1] & 0xff, - (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 8) & 0xff, - (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 16) & 0xff, - (system_info_.cpu.x86_cpu_info.vendor_id[1] >> 24) & 0xff, - system_info_.cpu.x86_cpu_info.vendor_id[2] & 0xff, - (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 8) & 0xff, - (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 16) & 0xff, - (system_info_.cpu.x86_cpu_info.vendor_id[2] >> 24) & 0xff); - cpu_vendor_ = new string(cpu_vendor_string); - } - - return cpu_vendor_; -} - - -void MinidumpSystemInfo::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpSystemInfo cannot print invalid data"; - return; - } - - printf("MDRawSystemInfo\n"); - printf(" processor_architecture = 0x%x\n", - system_info_.processor_architecture); - printf(" processor_level = %d\n", - system_info_.processor_level); - printf(" processor_revision = 0x%x\n", - system_info_.processor_revision); - printf(" number_of_processors = %d\n", - system_info_.number_of_processors); - printf(" product_type = %d\n", - system_info_.product_type); - printf(" major_version = %d\n", - system_info_.major_version); - printf(" minor_version = %d\n", - system_info_.minor_version); - printf(" build_number = %d\n", - system_info_.build_number); - printf(" platform_id = 0x%x\n", - system_info_.platform_id); - printf(" csd_version_rva = 0x%x\n", - system_info_.csd_version_rva); - printf(" suite_mask = 0x%x\n", - system_info_.suite_mask); - if (system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86 || - system_info_.processor_architecture == MD_CPU_ARCHITECTURE_X86_WIN64) { - printf(" cpu.x86_cpu_info (valid):\n"); - } else { - printf(" cpu.x86_cpu_info (invalid):\n"); - } - for (unsigned int i = 0; i < 3; ++i) { - printf(" cpu.x86_cpu_info.vendor_id[%d] = 0x%x\n", - i, system_info_.cpu.x86_cpu_info.vendor_id[i]); - } - printf(" cpu.x86_cpu_info.version_information = 0x%x\n", - system_info_.cpu.x86_cpu_info.version_information); - printf(" cpu.x86_cpu_info.feature_information = 0x%x\n", - system_info_.cpu.x86_cpu_info.feature_information); - printf(" cpu.x86_cpu_info.amd_extended_cpu_features = 0x%x\n", - system_info_.cpu.x86_cpu_info.amd_extended_cpu_features); - if (system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86 && - system_info_.processor_architecture != MD_CPU_ARCHITECTURE_X86_WIN64) { - printf(" cpu.other_cpu_info (valid):\n"); - for (unsigned int i = 0; i < 2; ++i) { - printf(" cpu.other_cpu_info.processor_features[%d] = 0x%" PRIx64 "\n", - i, system_info_.cpu.other_cpu_info.processor_features[i]); - } - } - const string* csd_version = GetCSDVersion(); - if (csd_version) { - printf(" (csd_version) = \"%s\"\n", - csd_version->c_str()); - } else { - printf(" (csd_version) = (null)\n"); - } - const string* cpu_vendor = GetCPUVendor(); - if (cpu_vendor) { - printf(" (cpu_vendor) = \"%s\"\n", - cpu_vendor->c_str()); - } else { - printf(" (cpu_vendor) = (null)\n"); - } - printf("\n"); -} - - -// -// MinidumpMiscInfo -// - - -MinidumpMiscInfo::MinidumpMiscInfo(Minidump* minidump) - : MinidumpStream(minidump), - misc_info_() { -} - - -bool MinidumpMiscInfo::Read(uint32_t expected_size) { - valid_ = false; - - size_t padding = 0; - if (expected_size != MD_MISCINFO_SIZE && - expected_size != MD_MISCINFO2_SIZE && - expected_size != MD_MISCINFO3_SIZE && - expected_size != MD_MISCINFO4_SIZE && - expected_size != MD_MISCINFO5_SIZE) { - if (expected_size > MD_MISCINFO5_SIZE) { - // Only read the part of the misc info structure we know how to handle - BPLOG(INFO) << "MinidumpMiscInfo size larger than expected " - << expected_size << ", skipping over the unknown part"; - padding = expected_size - MD_MISCINFO5_SIZE; - expected_size = MD_MISCINFO5_SIZE; - } else { - BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << expected_size - << " != " << MD_MISCINFO_SIZE << ", " << MD_MISCINFO2_SIZE - << ", " << MD_MISCINFO3_SIZE << ", " << MD_MISCINFO4_SIZE - << ", " << MD_MISCINFO5_SIZE << ")"; - return false; - } - } - - if (!minidump_->ReadBytes(&misc_info_, expected_size)) { - BPLOG(ERROR) << "MinidumpMiscInfo cannot read miscellaneous info"; - return false; - } - - if (padding != 0) { - off_t saved_position = minidump_->Tell(); - if (saved_position == -1) { - BPLOG(ERROR) << "MinidumpMiscInfo could not tell the current position"; - return false; - } - - if (!minidump_->SeekSet(saved_position + padding)) { - BPLOG(ERROR) << "MinidumpMiscInfo could not seek past the miscellaneous " - << "info structure"; - return false; - } - } - - if (minidump_->swap()) { - // Swap version 1 fields - Swap(&misc_info_.size_of_info); - Swap(&misc_info_.flags1); - Swap(&misc_info_.process_id); - Swap(&misc_info_.process_create_time); - Swap(&misc_info_.process_user_time); - Swap(&misc_info_.process_kernel_time); - if (misc_info_.size_of_info > MD_MISCINFO_SIZE) { - // Swap version 2 fields - Swap(&misc_info_.processor_max_mhz); - Swap(&misc_info_.processor_current_mhz); - Swap(&misc_info_.processor_mhz_limit); - Swap(&misc_info_.processor_max_idle_state); - Swap(&misc_info_.processor_current_idle_state); - } - if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) { - // Swap version 3 fields - Swap(&misc_info_.process_integrity_level); - Swap(&misc_info_.process_execute_flags); - Swap(&misc_info_.protected_process); - Swap(&misc_info_.time_zone_id); - Swap(&misc_info_.time_zone); - } - if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) { - // Swap version 4 fields. - // Do not swap UTF-16 strings. The swap is done as part of the - // conversion to UTF-8 (code follows below). - } - if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) { - // Swap version 5 fields - Swap(&misc_info_.xstate_data); - Swap(&misc_info_.process_cookie); - } - } - - if (expected_size + padding != misc_info_.size_of_info) { - BPLOG(ERROR) << "MinidumpMiscInfo size mismatch, " << - expected_size << " != " << misc_info_.size_of_info; - return false; - } - - // Convert UTF-16 strings - if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) { - // Convert UTF-16 strings in version 3 fields - ConvertUTF16BufferToUTF8String(misc_info_.time_zone.standard_name, - sizeof(misc_info_.time_zone.standard_name), - &standard_name_, minidump_->swap()); - ConvertUTF16BufferToUTF8String(misc_info_.time_zone.daylight_name, - sizeof(misc_info_.time_zone.daylight_name), - &daylight_name_, minidump_->swap()); - } - if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) { - // Convert UTF-16 strings in version 4 fields - ConvertUTF16BufferToUTF8String(misc_info_.build_string, - sizeof(misc_info_.build_string), - &build_string_, minidump_->swap()); - ConvertUTF16BufferToUTF8String(misc_info_.dbg_bld_str, - sizeof(misc_info_.dbg_bld_str), - &dbg_bld_str_, minidump_->swap()); - } - - valid_ = true; - return true; -} - - -void MinidumpMiscInfo::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpMiscInfo cannot print invalid data"; - return; - } - - printf("MDRawMiscInfo\n"); - // Print version 1 fields - printf(" size_of_info = %d\n", misc_info_.size_of_info); - printf(" flags1 = 0x%x\n", misc_info_.flags1); - printf(" process_id = "); - PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_ID, - kNumberFormatDecimal, misc_info_.process_id); - if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES) { - printf(" process_create_time = 0x%x %s\n", - misc_info_.process_create_time, - TimeTToUTCString(misc_info_.process_create_time).c_str()); - } else { - printf(" process_create_time = (invalid)\n"); - } - printf(" process_user_time = "); - PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES, - kNumberFormatDecimal, misc_info_.process_user_time); - printf(" process_kernel_time = "); - PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES, - kNumberFormatDecimal, misc_info_.process_kernel_time); - if (misc_info_.size_of_info > MD_MISCINFO_SIZE) { - // Print version 2 fields - printf(" processor_max_mhz = "); - PrintValueOrInvalid(misc_info_.flags1 & - MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, - kNumberFormatDecimal, misc_info_.processor_max_mhz); - printf(" processor_current_mhz = "); - PrintValueOrInvalid(misc_info_.flags1 & - MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, - kNumberFormatDecimal, misc_info_.processor_current_mhz); - printf(" processor_mhz_limit = "); - PrintValueOrInvalid(misc_info_.flags1 & - MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, - kNumberFormatDecimal, misc_info_.processor_mhz_limit); - printf(" processor_max_idle_state = "); - PrintValueOrInvalid(misc_info_.flags1 & - MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, - kNumberFormatDecimal, - misc_info_.processor_max_idle_state); - printf(" processor_current_idle_state = "); - PrintValueOrInvalid(misc_info_.flags1 & - MD_MISCINFO_FLAGS1_PROCESSOR_POWER_INFO, - kNumberFormatDecimal, - misc_info_.processor_current_idle_state); - } - if (misc_info_.size_of_info > MD_MISCINFO2_SIZE) { - // Print version 3 fields - printf(" process_integrity_level = "); - PrintValueOrInvalid(misc_info_.flags1 & - MD_MISCINFO_FLAGS1_PROCESS_INTEGRITY, - kNumberFormatHexadecimal, - misc_info_.process_integrity_level); - printf(" process_execute_flags = "); - PrintValueOrInvalid(misc_info_.flags1 & - MD_MISCINFO_FLAGS1_PROCESS_EXECUTE_FLAGS, - kNumberFormatHexadecimal, - misc_info_.process_execute_flags); - printf(" protected_process = "); - PrintValueOrInvalid(misc_info_.flags1 & - MD_MISCINFO_FLAGS1_PROTECTED_PROCESS, - kNumberFormatDecimal, misc_info_.protected_process); - printf(" time_zone_id = "); - PrintValueOrInvalid(misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE, - kNumberFormatDecimal, misc_info_.time_zone_id); - if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_TIMEZONE) { - printf(" time_zone.bias = %d\n", - misc_info_.time_zone.bias); - printf(" time_zone.standard_name = %s\n", standard_name_.c_str()); - printf(" time_zone.standard_date = " - "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n", - misc_info_.time_zone.standard_date.year, - misc_info_.time_zone.standard_date.month, - misc_info_.time_zone.standard_date.day, - misc_info_.time_zone.standard_date.day_of_week, - misc_info_.time_zone.standard_date.hour, - misc_info_.time_zone.standard_date.minute, - misc_info_.time_zone.standard_date.second, - misc_info_.time_zone.standard_date.milliseconds); - printf(" time_zone.standard_bias = %d\n", - misc_info_.time_zone.standard_bias); - printf(" time_zone.daylight_name = %s\n", daylight_name_.c_str()); - printf(" time_zone.daylight_date = " - "%04d-%02d-%02d (%d) %02d:%02d:%02d.%03d\n", - misc_info_.time_zone.daylight_date.year, - misc_info_.time_zone.daylight_date.month, - misc_info_.time_zone.daylight_date.day, - misc_info_.time_zone.daylight_date.day_of_week, - misc_info_.time_zone.daylight_date.hour, - misc_info_.time_zone.daylight_date.minute, - misc_info_.time_zone.daylight_date.second, - misc_info_.time_zone.daylight_date.milliseconds); - printf(" time_zone.daylight_bias = %d\n", - misc_info_.time_zone.daylight_bias); - } else { - printf(" time_zone.bias = (invalid)\n"); - printf(" time_zone.standard_name = (invalid)\n"); - printf(" time_zone.standard_date = (invalid)\n"); - printf(" time_zone.standard_bias = (invalid)\n"); - printf(" time_zone.daylight_name = (invalid)\n"); - printf(" time_zone.daylight_date = (invalid)\n"); - printf(" time_zone.daylight_bias = (invalid)\n"); - } - } - if (misc_info_.size_of_info > MD_MISCINFO3_SIZE) { - // Print version 4 fields - if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_BUILDSTRING) { - printf(" build_string = %s\n", build_string_.c_str()); - printf(" dbg_bld_str = %s\n", dbg_bld_str_.c_str()); - } else { - printf(" build_string = (invalid)\n"); - printf(" dbg_bld_str = (invalid)\n"); - } - } - if (misc_info_.size_of_info > MD_MISCINFO4_SIZE) { - // Print version 5 fields - if (misc_info_.flags1 & MD_MISCINFO_FLAGS1_PROCESS_COOKIE) { - printf(" xstate_data.size_of_info = %d\n", - misc_info_.xstate_data.size_of_info); - printf(" xstate_data.context_size = %d\n", - misc_info_.xstate_data.context_size); - printf(" xstate_data.enabled_features = 0x%" PRIx64 "\n", - misc_info_.xstate_data.enabled_features); - for (size_t i = 0; i < MD_MAXIMUM_XSTATE_FEATURES; i++) { - if (misc_info_.xstate_data.enabled_features & (1 << i)) { - printf(" xstate_data.features[%02zu] = { %d, %d }\n", i, - misc_info_.xstate_data.features[i].offset, - misc_info_.xstate_data.features[i].size); - } - } - if (misc_info_.xstate_data.enabled_features == 0) { - printf(" xstate_data.features[] = (empty)\n"); - } - printf(" process_cookie = %d\n", - misc_info_.process_cookie); - } else { - printf(" xstate_data.size_of_info = (invalid)\n"); - printf(" xstate_data.context_size = (invalid)\n"); - printf(" xstate_data.enabled_features = (invalid)\n"); - printf(" xstate_data.features[] = (invalid)\n"); - printf(" process_cookie = (invalid)\n"); - } - } - printf("\n"); -} - - -// -// MinidumpBreakpadInfo -// - - -MinidumpBreakpadInfo::MinidumpBreakpadInfo(Minidump* minidump) - : MinidumpStream(minidump), - breakpad_info_() { -} - - -bool MinidumpBreakpadInfo::Read(uint32_t expected_size) { - valid_ = false; - - if (expected_size != sizeof(breakpad_info_)) { - BPLOG(ERROR) << "MinidumpBreakpadInfo size mismatch, " << expected_size << - " != " << sizeof(breakpad_info_); - return false; - } - - if (!minidump_->ReadBytes(&breakpad_info_, sizeof(breakpad_info_))) { - BPLOG(ERROR) << "MinidumpBreakpadInfo cannot read Breakpad info"; - return false; - } - - if (minidump_->swap()) { - Swap(&breakpad_info_.validity); - Swap(&breakpad_info_.dump_thread_id); - Swap(&breakpad_info_.requesting_thread_id); - } - - valid_ = true; - return true; -} - - -bool MinidumpBreakpadInfo::GetDumpThreadID(uint32_t *thread_id) const { - BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetDumpThreadID " - "requires |thread_id|"; - assert(thread_id); - *thread_id = 0; - - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetDumpThreadID"; - return false; - } - - if (!(breakpad_info_.validity & MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID)) { - BPLOG(INFO) << "MinidumpBreakpadInfo has no dump thread"; - return false; - } - - *thread_id = breakpad_info_.dump_thread_id; - return true; -} - - -bool MinidumpBreakpadInfo::GetRequestingThreadID(uint32_t *thread_id) - const { - BPLOG_IF(ERROR, !thread_id) << "MinidumpBreakpadInfo::GetRequestingThreadID " - "requires |thread_id|"; - assert(thread_id); - *thread_id = 0; - - if (!thread_id || !valid_) { - BPLOG(ERROR) << "Invalid MinidumpBreakpadInfo for GetRequestingThreadID"; - return false; - } - - if (!(breakpad_info_.validity & - MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID)) { - BPLOG(INFO) << "MinidumpBreakpadInfo has no requesting thread"; - return false; - } - - *thread_id = breakpad_info_.requesting_thread_id; - return true; -} - - -void MinidumpBreakpadInfo::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpBreakpadInfo cannot print invalid data"; - return; - } - - printf("MDRawBreakpadInfo\n"); - printf(" validity = 0x%x\n", breakpad_info_.validity); - printf(" dump_thread_id = "); - PrintValueOrInvalid(breakpad_info_.validity & - MD_BREAKPAD_INFO_VALID_DUMP_THREAD_ID, - kNumberFormatHexadecimal, breakpad_info_.dump_thread_id); - printf(" requesting_thread_id = "); - PrintValueOrInvalid(breakpad_info_.validity & - MD_BREAKPAD_INFO_VALID_REQUESTING_THREAD_ID, - kNumberFormatHexadecimal, - breakpad_info_.requesting_thread_id); - - printf("\n"); -} - - -// -// MinidumpMemoryInfo -// - - -MinidumpMemoryInfo::MinidumpMemoryInfo(Minidump* minidump) - : MinidumpObject(minidump), - memory_info_() { -} - - -bool MinidumpMemoryInfo::IsExecutable() const { - uint32_t protection = - memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK; - return protection == MD_MEMORY_PROTECT_EXECUTE || - protection == MD_MEMORY_PROTECT_EXECUTE_READ || - protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE; -} - - -bool MinidumpMemoryInfo::IsWritable() const { - uint32_t protection = - memory_info_.protection & MD_MEMORY_PROTECTION_ACCESS_MASK; - return protection == MD_MEMORY_PROTECT_READWRITE || - protection == MD_MEMORY_PROTECT_WRITECOPY || - protection == MD_MEMORY_PROTECT_EXECUTE_READWRITE || - protection == MD_MEMORY_PROTECT_EXECUTE_WRITECOPY; -} - - -bool MinidumpMemoryInfo::Read() { - valid_ = false; - - if (!minidump_->ReadBytes(&memory_info_, sizeof(memory_info_))) { - BPLOG(ERROR) << "MinidumpMemoryInfo cannot read memory info"; - return false; - } - - if (minidump_->swap()) { - Swap(&memory_info_.base_address); - Swap(&memory_info_.allocation_base); - Swap(&memory_info_.allocation_protection); - Swap(&memory_info_.region_size); - Swap(&memory_info_.state); - Swap(&memory_info_.protection); - Swap(&memory_info_.type); - } - - // Check for base + size overflow or undersize. - if (memory_info_.region_size == 0 || - memory_info_.region_size > numeric_limits<uint64_t>::max() - - memory_info_.base_address) { - BPLOG(ERROR) << "MinidumpMemoryInfo has a memory region problem, " << - HexString(memory_info_.base_address) << "+" << - HexString(memory_info_.region_size); - return false; - } - - valid_ = true; - return true; -} - - -void MinidumpMemoryInfo::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpMemoryInfo cannot print invalid data"; - return; - } - - printf("MDRawMemoryInfo\n"); - printf(" base_address = 0x%" PRIx64 "\n", - memory_info_.base_address); - printf(" allocation_base = 0x%" PRIx64 "\n", - memory_info_.allocation_base); - printf(" allocation_protection = 0x%x\n", - memory_info_.allocation_protection); - printf(" region_size = 0x%" PRIx64 "\n", memory_info_.region_size); - printf(" state = 0x%x\n", memory_info_.state); - printf(" protection = 0x%x\n", memory_info_.protection); - printf(" type = 0x%x\n", memory_info_.type); -} - - -// -// MinidumpMemoryInfoList -// - - -MinidumpMemoryInfoList::MinidumpMemoryInfoList(Minidump* minidump) - : MinidumpStream(minidump), - range_map_(new RangeMap<uint64_t, unsigned int>()), - infos_(NULL), - info_count_(0) { -} - - -MinidumpMemoryInfoList::~MinidumpMemoryInfoList() { - delete range_map_; - delete infos_; -} - - -bool MinidumpMemoryInfoList::Read(uint32_t expected_size) { - // Invalidate cached data. - delete infos_; - infos_ = NULL; - range_map_->Clear(); - info_count_ = 0; - - valid_ = false; - - MDRawMemoryInfoList header; - if (expected_size < sizeof(MDRawMemoryInfoList)) { - BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " << - expected_size << " < " << sizeof(MDRawMemoryInfoList); - return false; - } - if (!minidump_->ReadBytes(&header, sizeof(header))) { - BPLOG(ERROR) << "MinidumpMemoryInfoList could not read header"; - return false; - } - - if (minidump_->swap()) { - Swap(&header.size_of_header); - Swap(&header.size_of_entry); - Swap(&header.number_of_entries); - } - - // Sanity check that the header is the expected size. - // TODO(ted): could possibly handle this more gracefully, assuming - // that future versions of the structs would be backwards-compatible. - if (header.size_of_header != sizeof(MDRawMemoryInfoList)) { - BPLOG(ERROR) << "MinidumpMemoryInfoList header size mismatch, " << - header.size_of_header << " != " << - sizeof(MDRawMemoryInfoList); - return false; - } - - // Sanity check that the entries are the expected size. - if (header.size_of_entry != sizeof(MDRawMemoryInfo)) { - BPLOG(ERROR) << "MinidumpMemoryInfoList entry size mismatch, " << - header.size_of_entry << " != " << - sizeof(MDRawMemoryInfo); - return false; - } - - if (header.number_of_entries > - numeric_limits<uint32_t>::max() / sizeof(MDRawMemoryInfo)) { - BPLOG(ERROR) << "MinidumpMemoryInfoList info count " << - header.number_of_entries << - " would cause multiplication overflow"; - return false; - } - - if (expected_size != sizeof(MDRawMemoryInfoList) + - header.number_of_entries * sizeof(MDRawMemoryInfo)) { - BPLOG(ERROR) << "MinidumpMemoryInfoList size mismatch, " << expected_size << - " != " << sizeof(MDRawMemoryInfoList) + - header.number_of_entries * sizeof(MDRawMemoryInfo); - return false; - } - - // Check for data loss when converting header.number_of_entries from - // uint64_t into MinidumpMemoryInfos::size_type (uint32_t) - MinidumpMemoryInfos::size_type header_number_of_entries = - static_cast<unsigned int>(header.number_of_entries); - if (static_cast<uint64_t>(header_number_of_entries) != - header.number_of_entries) { - BPLOG(ERROR) << "Data loss detected when converting " - "the header's number_of_entries"; - return false; - } - - if (header.number_of_entries != 0) { - scoped_ptr<MinidumpMemoryInfos> infos( - new MinidumpMemoryInfos(header_number_of_entries, - MinidumpMemoryInfo(minidump_))); - - for (unsigned int index = 0; - index < header.number_of_entries; - ++index) { - MinidumpMemoryInfo* info = &(*infos)[index]; - - // Assume that the file offset is correct after the last read. - if (!info->Read()) { - BPLOG(ERROR) << "MinidumpMemoryInfoList cannot read info " << - index << "/" << header.number_of_entries; - return false; - } - - uint64_t base_address = info->GetBase(); - uint64_t region_size = info->GetSize(); - - if (!range_map_->StoreRange(base_address, region_size, index)) { - BPLOG(ERROR) << "MinidumpMemoryInfoList could not store" - " memory region " << - index << "/" << header.number_of_entries << ", " << - HexString(base_address) << "+" << - HexString(region_size); - return false; - } - } - - infos_ = infos.release(); - } - - info_count_ = header_number_of_entries; - - valid_ = true; - return true; -} - - -const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoAtIndex( - unsigned int index) const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for GetMemoryInfoAtIndex"; - return NULL; - } - - if (index >= info_count_) { - BPLOG(ERROR) << "MinidumpMemoryInfoList index out of range: " << - index << "/" << info_count_; - return NULL; - } - - return &(*infos_)[index]; -} - - -const MinidumpMemoryInfo* MinidumpMemoryInfoList::GetMemoryInfoForAddress( - uint64_t address) const { - if (!valid_) { - BPLOG(ERROR) << "Invalid MinidumpMemoryInfoList for" - " GetMemoryInfoForAddress"; - return NULL; - } - - unsigned int info_index; - if (!range_map_->RetrieveRange(address, &info_index, NULL /* base */, - NULL /* delta */, NULL /* size */)) { - BPLOG(INFO) << "MinidumpMemoryInfoList has no memory info at " << - HexString(address); - return NULL; - } - - return GetMemoryInfoAtIndex(info_index); -} - - -void MinidumpMemoryInfoList::Print() { - if (!valid_) { - BPLOG(ERROR) << "MinidumpMemoryInfoList cannot print invalid data"; - return; - } - - printf("MinidumpMemoryInfoList\n"); - printf(" info_count = %d\n", info_count_); - printf("\n"); - - for (unsigned int info_index = 0; - info_index < info_count_; - ++info_index) { - printf("info[%d]\n", info_index); - (*infos_)[info_index].Print(); - printf("\n"); - } -} - -// -// MinidumpLinuxMaps -// - -MinidumpLinuxMaps::MinidumpLinuxMaps(Minidump *minidump) - : MinidumpObject(minidump) { -} - -void MinidumpLinuxMaps::Print() const { - if (!valid_) { - BPLOG(ERROR) << "MinidumpLinuxMaps cannot print invalid data"; - return; - } - std::cout << region_.line << std::endl; -} - -// -// MinidumpLinuxMapsList -// - -MinidumpLinuxMapsList::MinidumpLinuxMapsList(Minidump *minidump) - : MinidumpStream(minidump), - maps_(NULL), - maps_count_(0) { -} - -MinidumpLinuxMapsList::~MinidumpLinuxMapsList() { - if (maps_) { - for (unsigned int i = 0; i < maps_->size(); i++) { - delete (*maps_)[i]; - } - delete maps_; - } -} - -const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsForAddress( - uint64_t address) const { - if (!valid_ || (maps_ == NULL)) { - BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsForAddress"; - return NULL; - } - - // Search every memory mapping. - for (unsigned int index = 0; index < maps_count_; index++) { - // Check if address is within bounds of the current memory region. - if ((*maps_)[index]->GetBase() <= address && - (*maps_)[index]->GetBase() + (*maps_)[index]->GetSize() > address) { - return (*maps_)[index]; - } - } - - // No mapping encloses the memory address. - BPLOG(ERROR) << "MinidumpLinuxMapsList has no mapping at " - << HexString(address); - return NULL; -} - -const MinidumpLinuxMaps *MinidumpLinuxMapsList::GetLinuxMapsAtIndex( - unsigned int index) const { - if (!valid_ || (maps_ == NULL)) { - BPLOG(ERROR) << "Invalid MinidumpLinuxMapsList for GetLinuxMapsAtIndex"; - return NULL; - } - - // Index out of bounds. - if (index >= maps_count_ || (maps_ == NULL)) { - BPLOG(ERROR) << "MinidumpLinuxMapsList index of out range: " - << index - << "/" - << maps_count_; - return NULL; - } - return (*maps_)[index]; -} - -bool MinidumpLinuxMapsList::Read(uint32_t expected_size) { - // Invalidate cached data. - if (maps_) { - for (unsigned int i = 0; i < maps_->size(); i++) { - delete (*maps_)[i]; - } - delete maps_; - } - maps_ = NULL; - maps_count_ = 0; - - valid_ = false; - - // Load and check expected stream length. - uint32_t length = 0; - if (!minidump_->SeekToStreamType(MD_LINUX_MAPS, &length)) { - BPLOG(ERROR) << "MinidumpLinuxMapsList stream type not found"; - return false; - } - if (expected_size != length) { - BPLOG(ERROR) << "MinidumpLinuxMapsList size mismatch: " - << expected_size - << " != " - << length; - return false; - } - - // Create a vector to read stream data. The vector needs to have - // at least enough capacity to read all the data. - vector<char> mapping_bytes(length); - if (!minidump_->ReadBytes(&mapping_bytes[0], length)) { - BPLOG(ERROR) << "MinidumpLinuxMapsList failed to read bytes"; - return false; - } - string map_string(mapping_bytes.begin(), mapping_bytes.end()); - vector<MappedMemoryRegion> all_regions; - - // Parse string into mapping data. - if (!ParseProcMaps(map_string, &all_regions)) { - return false; - } - - scoped_ptr<MinidumpLinuxMappings> maps(new MinidumpLinuxMappings()); - - // Push mapping data into wrapper classes. - for (size_t i = 0; i < all_regions.size(); i++) { - scoped_ptr<MinidumpLinuxMaps> ele(new MinidumpLinuxMaps(minidump_)); - ele->region_ = all_regions[i]; - ele->valid_ = true; - maps->push_back(ele.release()); - } - - // Set instance variables. - maps_ = maps.release(); - maps_count_ = maps_->size(); - valid_ = true; - return true; -} - -void MinidumpLinuxMapsList::Print() const { - if (!valid_ || (maps_ == NULL)) { - BPLOG(ERROR) << "MinidumpLinuxMapsList cannot print valid data"; - return; - } - for (size_t i = 0; i < maps_->size(); i++) { - (*maps_)[i]->Print(); - } -} - -// -// Minidump -// - - -uint32_t Minidump::max_streams_ = 128; -unsigned int Minidump::max_string_length_ = 1024; - - -Minidump::Minidump(const string& path) - : header_(), - directory_(NULL), - stream_map_(new MinidumpStreamMap()), - path_(path), - stream_(NULL), - swap_(false), - valid_(false) { -} - -Minidump::Minidump(istream& stream) - : header_(), - directory_(NULL), - stream_map_(new MinidumpStreamMap()), - path_(), - stream_(&stream), - swap_(false), - valid_(false) { -} - -Minidump::~Minidump() { - if (stream_) { - BPLOG(INFO) << "Minidump closing minidump"; - } - if (!path_.empty()) { - delete stream_; - } - delete directory_; - delete stream_map_; -} - - -bool Minidump::Open() { - if (stream_ != NULL) { - BPLOG(INFO) << "Minidump reopening minidump " << path_; - - // The file is already open. Seek to the beginning, which is the position - // the file would be at if it were opened anew. - return SeekSet(0); - } - - stream_ = new ifstream(path_.c_str(), std::ios::in | std::ios::binary); - if (!stream_ || !stream_->good()) { - string error_string; - int error_code = ErrnoString(&error_string); - BPLOG(ERROR) << "Minidump could not open minidump " << path_ << - ", error " << error_code << ": " << error_string; - return false; - } - - BPLOG(INFO) << "Minidump opened minidump " << path_; - return true; -} - -bool Minidump::GetContextCPUFlagsFromSystemInfo(uint32_t *context_cpu_flags) { - // Initialize output parameters - *context_cpu_flags = 0; - - // Save the current stream position - off_t saved_position = Tell(); - if (saved_position == -1) { - // Failed to save the current stream position. - // Returns true because the current position of the stream is preserved. - return true; - } - - const MDRawSystemInfo* system_info = - GetSystemInfo() ? GetSystemInfo()->system_info() : NULL; - - if (system_info != NULL) { - switch (system_info->processor_architecture) { - case MD_CPU_ARCHITECTURE_X86: - *context_cpu_flags = MD_CONTEXT_X86; - break; - case MD_CPU_ARCHITECTURE_MIPS: - *context_cpu_flags = MD_CONTEXT_MIPS; - break; - case MD_CPU_ARCHITECTURE_MIPS64: - *context_cpu_flags = MD_CONTEXT_MIPS64; - break; - case MD_CPU_ARCHITECTURE_ALPHA: - *context_cpu_flags = MD_CONTEXT_ALPHA; - break; - case MD_CPU_ARCHITECTURE_PPC: - *context_cpu_flags = MD_CONTEXT_PPC; - break; - case MD_CPU_ARCHITECTURE_PPC64: - *context_cpu_flags = MD_CONTEXT_PPC64; - break; - case MD_CPU_ARCHITECTURE_SHX: - *context_cpu_flags = MD_CONTEXT_SHX; - break; - case MD_CPU_ARCHITECTURE_ARM: - *context_cpu_flags = MD_CONTEXT_ARM; - break; - case MD_CPU_ARCHITECTURE_ARM64: - *context_cpu_flags = MD_CONTEXT_ARM64; - break; - case MD_CPU_ARCHITECTURE_IA64: - *context_cpu_flags = MD_CONTEXT_IA64; - break; - case MD_CPU_ARCHITECTURE_ALPHA64: - *context_cpu_flags = 0; - break; - case MD_CPU_ARCHITECTURE_MSIL: - *context_cpu_flags = 0; - break; - case MD_CPU_ARCHITECTURE_AMD64: - *context_cpu_flags = MD_CONTEXT_AMD64; - break; - case MD_CPU_ARCHITECTURE_X86_WIN64: - *context_cpu_flags = 0; - break; - case MD_CPU_ARCHITECTURE_SPARC: - *context_cpu_flags = MD_CONTEXT_SPARC; - break; - case MD_CPU_ARCHITECTURE_UNKNOWN: - *context_cpu_flags = 0; - break; - default: - *context_cpu_flags = 0; - break; - } - } - - // Restore position and return - return SeekSet(saved_position); -} - - -bool Minidump::Read() { - // Invalidate cached data. - delete directory_; - directory_ = NULL; - stream_map_->clear(); - - valid_ = false; - - if (!Open()) { - BPLOG(ERROR) << "Minidump cannot open minidump"; - return false; - } - - if (!ReadBytes(&header_, sizeof(MDRawHeader))) { - BPLOG(ERROR) << "Minidump cannot read header"; - return false; - } - - if (header_.signature != MD_HEADER_SIGNATURE) { - // The file may be byte-swapped. Under the present architecture, these - // classes don't know or need to know what CPU (or endianness) the - // minidump was produced on in order to parse it. Use the signature as - // a byte order marker. - uint32_t signature_swapped = header_.signature; - Swap(&signature_swapped); - if (signature_swapped != MD_HEADER_SIGNATURE) { - // This isn't a minidump or a byte-swapped minidump. - BPLOG(ERROR) << "Minidump header signature mismatch: (" << - HexString(header_.signature) << ", " << - HexString(signature_swapped) << ") != " << - HexString(MD_HEADER_SIGNATURE); - return false; - } - swap_ = true; - } else { - // The file is not byte-swapped. Set swap_ false (it may have been true - // if the object is being reused?) - swap_ = false; - } - - BPLOG(INFO) << "Minidump " << (swap_ ? "" : "not ") << - "byte-swapping minidump"; - - if (swap_) { - Swap(&header_.signature); - Swap(&header_.version); - Swap(&header_.stream_count); - Swap(&header_.stream_directory_rva); - Swap(&header_.checksum); - Swap(&header_.time_date_stamp); - Swap(&header_.flags); - } - - // Version check. The high 16 bits of header_.version contain something - // else "implementation specific." - if ((header_.version & 0x0000ffff) != MD_HEADER_VERSION) { - BPLOG(ERROR) << "Minidump version mismatch: " << - HexString(header_.version & 0x0000ffff) << " != " << - HexString(MD_HEADER_VERSION); - return false; - } - - if (!SeekSet(header_.stream_directory_rva)) { - BPLOG(ERROR) << "Minidump cannot seek to stream directory"; - return false; - } - - if (header_.stream_count > max_streams_) { - BPLOG(ERROR) << "Minidump stream count " << header_.stream_count << - " exceeds maximum " << max_streams_; - return false; - } - - if (header_.stream_count != 0) { - scoped_ptr<MinidumpDirectoryEntries> directory( - new MinidumpDirectoryEntries(header_.stream_count)); - - // Read the entire array in one fell swoop, instead of reading one entry - // at a time in the loop. - if (!ReadBytes(&(*directory)[0], - sizeof(MDRawDirectory) * header_.stream_count)) { - BPLOG(ERROR) << "Minidump cannot read stream directory"; - return false; - } - - for (unsigned int stream_index = 0; - stream_index < header_.stream_count; - ++stream_index) { - MDRawDirectory* directory_entry = &(*directory)[stream_index]; - - if (swap_) { - Swap(&directory_entry->stream_type); - Swap(&directory_entry->location); - } - - // Initialize the stream_map_ map, which speeds locating a stream by - // type. - unsigned int stream_type = directory_entry->stream_type; - switch (stream_type) { - case MD_THREAD_LIST_STREAM: - case MD_MODULE_LIST_STREAM: - case MD_MEMORY_LIST_STREAM: - case MD_EXCEPTION_STREAM: - case MD_SYSTEM_INFO_STREAM: - case MD_MISC_INFO_STREAM: - case MD_BREAKPAD_INFO_STREAM: { - if (stream_map_->find(stream_type) != stream_map_->end()) { - // Another stream with this type was already found. A minidump - // file should contain at most one of each of these stream types. - BPLOG(ERROR) << "Minidump found multiple streams of type " << - stream_type << ", but can only deal with one"; - return false; - } - // Fall through to default - } - - default: { - // Overwrites for stream types other than those above, but it's - // expected to be the user's burden in that case. - (*stream_map_)[stream_type].stream_index = stream_index; - } - } - } - - directory_ = directory.release(); - } - - valid_ = true; - return true; -} - - -MinidumpThreadList* Minidump::GetThreadList() { - MinidumpThreadList* thread_list; - return GetStream(&thread_list); -} - - -MinidumpModuleList* Minidump::GetModuleList() { - MinidumpModuleList* module_list; - return GetStream(&module_list); -} - - -MinidumpMemoryList* Minidump::GetMemoryList() { - MinidumpMemoryList* memory_list; - return GetStream(&memory_list); -} - - -MinidumpException* Minidump::GetException() { - MinidumpException* exception; - return GetStream(&exception); -} - -MinidumpAssertion* Minidump::GetAssertion() { - MinidumpAssertion* assertion; - return GetStream(&assertion); -} - - -MinidumpSystemInfo* Minidump::GetSystemInfo() { - MinidumpSystemInfo* system_info; - return GetStream(&system_info); -} - - -MinidumpMiscInfo* Minidump::GetMiscInfo() { - MinidumpMiscInfo* misc_info; - return GetStream(&misc_info); -} - - -MinidumpBreakpadInfo* Minidump::GetBreakpadInfo() { - MinidumpBreakpadInfo* breakpad_info; - return GetStream(&breakpad_info); -} - -MinidumpMemoryInfoList* Minidump::GetMemoryInfoList() { - MinidumpMemoryInfoList* memory_info_list; - return GetStream(&memory_info_list); -} - -MinidumpLinuxMapsList *Minidump::GetLinuxMapsList() { - MinidumpLinuxMapsList *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) { - switch (stream_type) { - case MD_UNUSED_STREAM: - return "MD_UNUSED_STREAM"; - case MD_RESERVED_STREAM_0: - return "MD_RESERVED_STREAM_0"; - case MD_RESERVED_STREAM_1: - return "MD_RESERVED_STREAM_1"; - case MD_THREAD_LIST_STREAM: - return "MD_THREAD_LIST_STREAM"; - case MD_MODULE_LIST_STREAM: - return "MD_MODULE_LIST_STREAM"; - case MD_MEMORY_LIST_STREAM: - return "MD_MEMORY_LIST_STREAM"; - case MD_EXCEPTION_STREAM: - return "MD_EXCEPTION_STREAM"; - case MD_SYSTEM_INFO_STREAM: - return "MD_SYSTEM_INFO_STREAM"; - case MD_THREAD_EX_LIST_STREAM: - return "MD_THREAD_EX_LIST_STREAM"; - case MD_MEMORY_64_LIST_STREAM: - return "MD_MEMORY_64_LIST_STREAM"; - case MD_COMMENT_STREAM_A: - return "MD_COMMENT_STREAM_A"; - case MD_COMMENT_STREAM_W: - return "MD_COMMENT_STREAM_W"; - case MD_HANDLE_DATA_STREAM: - return "MD_HANDLE_DATA_STREAM"; - case MD_FUNCTION_TABLE_STREAM: - return "MD_FUNCTION_TABLE_STREAM"; - case MD_UNLOADED_MODULE_LIST_STREAM: - return "MD_UNLOADED_MODULE_LIST_STREAM"; - case MD_MISC_INFO_STREAM: - return "MD_MISC_INFO_STREAM"; - case MD_MEMORY_INFO_LIST_STREAM: - return "MD_MEMORY_INFO_LIST_STREAM"; - case MD_THREAD_INFO_LIST_STREAM: - return "MD_THREAD_INFO_LIST_STREAM"; - case MD_HANDLE_OPERATION_LIST_STREAM: - return "MD_HANDLE_OPERATION_LIST_STREAM"; - case MD_TOKEN_STREAM: - return "MD_TOKEN_STREAM"; - case MD_JAVASCRIPT_DATA_STREAM: - return "MD_JAVASCRIPT_DATA_STREAM"; - case MD_SYSTEM_MEMORY_INFO_STREAM: - return "MD_SYSTEM_MEMORY_INFO_STREAM"; - case MD_PROCESS_VM_COUNTERS_STREAM: - return "MD_PROCESS_VM_COUNTERS_STREAM"; - case MD_LAST_RESERVED_STREAM: - return "MD_LAST_RESERVED_STREAM"; - case MD_BREAKPAD_INFO_STREAM: - return "MD_BREAKPAD_INFO_STREAM"; - case MD_ASSERTION_INFO_STREAM: - return "MD_ASSERTION_INFO_STREAM"; - case MD_LINUX_CPU_INFO: - return "MD_LINUX_CPU_INFO"; - case MD_LINUX_PROC_STATUS: - return "MD_LINUX_PROC_STATUS"; - case MD_LINUX_LSB_RELEASE: - return "MD_LINUX_LSB_RELEASE"; - case MD_LINUX_CMD_LINE: - return "MD_LINUX_CMD_LINE"; - case MD_LINUX_ENVIRON: - return "MD_LINUX_ENVIRON"; - case MD_LINUX_AUXV: - return "MD_LINUX_AUXV"; - case MD_LINUX_MAPS: - return "MD_LINUX_MAPS"; - case MD_LINUX_DSO_DEBUG: - return "MD_LINUX_DSO_DEBUG"; - default: - return "unknown"; - } -} - -void Minidump::Print() { - if (!valid_) { - BPLOG(ERROR) << "Minidump cannot print invalid data"; - return; - } - - printf("MDRawHeader\n"); - printf(" signature = 0x%x\n", header_.signature); - printf(" version = 0x%x\n", header_.version); - printf(" stream_count = %d\n", header_.stream_count); - printf(" stream_directory_rva = 0x%x\n", header_.stream_directory_rva); - printf(" checksum = 0x%x\n", header_.checksum); - printf(" time_date_stamp = 0x%x %s\n", - header_.time_date_stamp, - TimeTToUTCString(header_.time_date_stamp).c_str()); - printf(" flags = 0x%" PRIx64 "\n", header_.flags); - printf("\n"); - - for (unsigned int stream_index = 0; - stream_index < header_.stream_count; - ++stream_index) { - MDRawDirectory* directory_entry = &(*directory_)[stream_index]; - - printf("mDirectory[%d]\n", stream_index); - printf("MDRawDirectory\n"); - printf(" stream_type = 0x%x (%s)\n", directory_entry->stream_type, - get_stream_name(directory_entry->stream_type)); - printf(" location.data_size = %d\n", - directory_entry->location.data_size); - printf(" location.rva = 0x%x\n", directory_entry->location.rva); - printf("\n"); - } - - printf("Streams:\n"); - for (MinidumpStreamMap::const_iterator iterator = stream_map_->begin(); - iterator != stream_map_->end(); - ++iterator) { - uint32_t stream_type = iterator->first; - const MinidumpStreamInfo& info = iterator->second; - printf(" stream type 0x%x (%s) at index %d\n", stream_type, - get_stream_name(stream_type), - info.stream_index); - } - printf("\n"); -} - - -const MDRawDirectory* Minidump::GetDirectoryEntryAtIndex(unsigned int index) - const { - if (!valid_) { - BPLOG(ERROR) << "Invalid Minidump for GetDirectoryEntryAtIndex"; - return NULL; - } - - if (index >= header_.stream_count) { - BPLOG(ERROR) << "Minidump stream directory index out of range: " << - index << "/" << header_.stream_count; - return NULL; - } - - return &(*directory_)[index]; -} - - -bool Minidump::ReadBytes(void* bytes, size_t count) { - // Can't check valid_ because Read needs to call this method before - // validity can be determined. - if (!stream_) { - return false; - } - stream_->read(static_cast<char*>(bytes), count); - std::streamsize bytes_read = stream_->gcount(); - if (bytes_read == -1) { - string error_string; - int error_code = ErrnoString(&error_string); - BPLOG(ERROR) << "ReadBytes: error " << error_code << ": " << error_string; - return false; - } - - // Convert to size_t and check for data loss - size_t bytes_read_converted = static_cast<size_t>(bytes_read); - if (static_cast<std::streamsize>(bytes_read_converted) != bytes_read) { - BPLOG(ERROR) << "ReadBytes: conversion data loss detected when converting " - << bytes_read << " to " << bytes_read_converted; - return false; - } - - if (bytes_read_converted != count) { - BPLOG(ERROR) << "ReadBytes: read " << bytes_read_converted << "/" << count; - return false; - } - - return true; -} - - -bool Minidump::SeekSet(off_t offset) { - // Can't check valid_ because Read needs to call this method before - // validity can be determined. - if (!stream_) { - return false; - } - stream_->seekg(offset, std::ios_base::beg); - if (!stream_->good()) { - string error_string; - int error_code = ErrnoString(&error_string); - BPLOG(ERROR) << "SeekSet: error " << error_code << ": " << error_string; - return false; - } - return true; -} - -off_t Minidump::Tell() { - if (!valid_ || !stream_) { - return (off_t)-1; - } - - // Check for conversion data loss - std::streamoff std_streamoff = stream_->tellg(); - off_t rv = static_cast<off_t>(std_streamoff); - if (static_cast<std::streamoff>(rv) == std_streamoff) { - return rv; - } else { - BPLOG(ERROR) << "Data loss detected"; - return (off_t)-1; - } -} - - -string* Minidump::ReadString(off_t offset) { - if (!valid_) { - BPLOG(ERROR) << "Invalid Minidump for ReadString"; - return NULL; - } - if (!SeekSet(offset)) { - BPLOG(ERROR) << "ReadString could not seek to string at offset " << offset; - return NULL; - } - - uint32_t bytes; - if (!ReadBytes(&bytes, sizeof(bytes))) { - BPLOG(ERROR) << "ReadString could not read string size at offset " << - offset; - return NULL; - } - if (swap_) - Swap(&bytes); - - if (bytes % 2 != 0) { - BPLOG(ERROR) << "ReadString found odd-sized " << bytes << - "-byte string at offset " << offset; - return NULL; - } - unsigned int utf16_words = bytes / 2; - - if (utf16_words > max_string_length_) { - BPLOG(ERROR) << "ReadString string length " << utf16_words << - " exceeds maximum " << max_string_length_ << - " at offset " << offset; - return NULL; - } - - vector<uint16_t> string_utf16(utf16_words); - - if (utf16_words) { - if (!ReadBytes(&string_utf16[0], bytes)) { - BPLOG(ERROR) << "ReadString could not read " << bytes << - "-byte string at offset " << offset; - return NULL; - } - } - - return UTF16ToUTF8(string_utf16, swap_); -} - - -bool Minidump::SeekToStreamType(uint32_t stream_type, - uint32_t* stream_length) { - BPLOG_IF(ERROR, !stream_length) << "Minidump::SeekToStreamType requires " - "|stream_length|"; - assert(stream_length); - *stream_length = 0; - - if (!valid_) { - BPLOG(ERROR) << "Invalid Mindump for SeekToStreamType"; - return false; - } - - MinidumpStreamMap::const_iterator iterator = stream_map_->find(stream_type); - if (iterator == stream_map_->end()) { - // This stream type didn't exist in the directory. - BPLOG(INFO) << "SeekToStreamType: type " << stream_type << " not present"; - return false; - } - - const MinidumpStreamInfo& info = iterator->second; - if (info.stream_index >= header_.stream_count) { - BPLOG(ERROR) << "SeekToStreamType: type " << stream_type << - " out of range: " << - info.stream_index << "/" << header_.stream_count; - return false; - } - - MDRawDirectory* directory_entry = &(*directory_)[info.stream_index]; - if (!SeekSet(directory_entry->location.rva)) { - BPLOG(ERROR) << "SeekToStreamType could not seek to stream type " << - stream_type; - return false; - } - - *stream_length = directory_entry->location.data_size; - - return true; -} - - -template<typename T> -T* Minidump::GetStream(T** stream) { - // stream is a garbage parameter that's present only to account for C++'s - // inability to overload a method based solely on its return type. - - const uint32_t stream_type = T::kStreamType; - - BPLOG_IF(ERROR, !stream) << "Minidump::GetStream type " << stream_type << - " requires |stream|"; - assert(stream); - *stream = NULL; - - if (!valid_) { - BPLOG(ERROR) << "Invalid Minidump for GetStream type " << stream_type; - return NULL; - } - - MinidumpStreamMap::iterator iterator = stream_map_->find(stream_type); - if (iterator == stream_map_->end()) { - // This stream type didn't exist in the directory. - BPLOG(INFO) << "GetStream: type " << stream_type << " not present"; - return NULL; - } - - // Get a pointer so that the stored stream field can be altered. - MinidumpStreamInfo* info = &iterator->second; - - if (info->stream) { - // This cast is safe because info.stream is only populated by this - // method, and there is a direct correlation between T and stream_type. - *stream = static_cast<T*>(info->stream); - return *stream; - } - - uint32_t stream_length; - if (!SeekToStreamType(stream_type, &stream_length)) { - BPLOG(ERROR) << "GetStream could not seek to stream type " << stream_type; - return NULL; - } - - scoped_ptr<T> new_stream(new T(this)); - - if (!new_stream->Read(stream_length)) { - BPLOG(ERROR) << "GetStream could not read stream type " << stream_type; - return NULL; - } - - *stream = new_stream.release(); - info->stream = *stream; - return *stream; -} - - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc deleted file mode 100644 index 343f04428..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump.cc +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// minidump_dump.cc: Print the contents of a minidump file in somewhat -// readable text. -// -// Author: Mark Mentovai - -#include <stdio.h> -#include <string.h> - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/minidump.h" -#include "processor/logging.h" - -namespace { - -using google_breakpad::Minidump; -using google_breakpad::MinidumpThreadList; -using google_breakpad::MinidumpModuleList; -using google_breakpad::MinidumpMemoryInfoList; -using google_breakpad::MinidumpMemoryList; -using google_breakpad::MinidumpException; -using google_breakpad::MinidumpAssertion; -using google_breakpad::MinidumpSystemInfo; -using google_breakpad::MinidumpMiscInfo; -using google_breakpad::MinidumpBreakpadInfo; - -static void DumpRawStream(Minidump *minidump, - uint32_t stream_type, - const char *stream_name, - int *errors) { - uint32_t length = 0; - if (!minidump->SeekToStreamType(stream_type, &length)) { - return; - } - - printf("Stream %s:\n", stream_name); - - if (length == 0) { - printf("\n"); - return; - } - std::vector<char> contents(length); - if (!minidump->ReadBytes(&contents[0], length)) { - ++*errors; - BPLOG(ERROR) << "minidump.ReadBytes failed"; - return; - } - size_t current_offset = 0; - while (current_offset < length) { - size_t remaining = length - current_offset; - // Printf requires an int and direct casting from size_t results - // in compatibility warnings. - uint32_t int_remaining = remaining; - printf("%.*s", int_remaining, &contents[current_offset]); - char *next_null = reinterpret_cast<char *>( - memchr(&contents[current_offset], 0, remaining)); - if (next_null == NULL) - break; - printf("\\0\n"); - size_t null_offset = next_null - &contents[0]; - current_offset = null_offset + 1; - } - printf("\n\n"); -} - -static bool PrintMinidumpDump(const char *minidump_file) { - Minidump minidump(minidump_file); - if (!minidump.Read()) { - BPLOG(ERROR) << "minidump.Read() failed"; - return false; - } - minidump.Print(); - - int errors = 0; - - MinidumpThreadList *thread_list = minidump.GetThreadList(); - if (!thread_list) { - ++errors; - BPLOG(ERROR) << "minidump.GetThreadList() failed"; - } else { - thread_list->Print(); - } - - MinidumpModuleList *module_list = minidump.GetModuleList(); - if (!module_list) { - ++errors; - BPLOG(ERROR) << "minidump.GetModuleList() failed"; - } else { - module_list->Print(); - } - - MinidumpMemoryList *memory_list = minidump.GetMemoryList(); - if (!memory_list) { - ++errors; - BPLOG(ERROR) << "minidump.GetMemoryList() failed"; - } else { - memory_list->Print(); - } - - MinidumpException *exception = minidump.GetException(); - if (!exception) { - BPLOG(INFO) << "minidump.GetException() failed"; - } else { - exception->Print(); - } - - MinidumpAssertion *assertion = minidump.GetAssertion(); - if (!assertion) { - BPLOG(INFO) << "minidump.GetAssertion() failed"; - } else { - assertion->Print(); - } - - MinidumpSystemInfo *system_info = minidump.GetSystemInfo(); - if (!system_info) { - ++errors; - BPLOG(ERROR) << "minidump.GetSystemInfo() failed"; - } else { - system_info->Print(); - } - - MinidumpMiscInfo *misc_info = minidump.GetMiscInfo(); - if (!misc_info) { - ++errors; - BPLOG(ERROR) << "minidump.GetMiscInfo() failed"; - } else { - misc_info->Print(); - } - - MinidumpBreakpadInfo *breakpad_info = minidump.GetBreakpadInfo(); - if (!breakpad_info) { - // Breakpad info is optional, so don't treat this as an error. - BPLOG(INFO) << "minidump.GetBreakpadInfo() failed"; - } else { - breakpad_info->Print(); - } - - MinidumpMemoryInfoList *memory_info_list = minidump.GetMemoryInfoList(); - if (!memory_info_list) { - ++errors; - BPLOG(ERROR) << "minidump.GetMemoryInfoList() failed"; - } else { - memory_info_list->Print(); - } - - DumpRawStream(&minidump, - MD_LINUX_CMD_LINE, - "MD_LINUX_CMD_LINE", - &errors); - DumpRawStream(&minidump, - MD_LINUX_ENVIRON, - "MD_LINUX_ENVIRON", - &errors); - DumpRawStream(&minidump, - MD_LINUX_LSB_RELEASE, - "MD_LINUX_LSB_RELEASE", - &errors); - DumpRawStream(&minidump, - MD_LINUX_PROC_STATUS, - "MD_LINUX_PROC_STATUS", - &errors); - DumpRawStream(&minidump, - MD_LINUX_CPU_INFO, - "MD_LINUX_CPU_INFO", - &errors); - DumpRawStream(&minidump, - MD_LINUX_MAPS, - "MD_LINUX_MAPS", - &errors); - - return errors == 0; -} - -} // namespace - -int main(int argc, char **argv) { - BPLOG_INIT(&argc, &argv); - - if (argc != 2) { - fprintf(stderr, "usage: %s <file>\n", argv[0]); - return 1; - } - - return PrintMinidumpDump(argv[1]) ? 0 : 1; -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump_test b/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump_test deleted file mode 100755 index fb62ace73..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_dump_test +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2006, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -testdata_dir=$srcdir/src/processor/testdata -./src/processor/minidump_dump $testdata_dir/minidump2.dmp | \ - tr -d '\015' | \ - diff -u $testdata_dir/minidump2.dump.out - -exit $? diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc deleted file mode 100644 index 33b4a1284..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor.cc +++ /dev/null @@ -1,1577 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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 "google_breakpad/processor/minidump_processor.h" - -#include <assert.h> - -#include <string> - -#include "common/scoped_ptr.h" -#include "common/stdio_wrapper.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/minidump.h" -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/exploitability.h" -#include "google_breakpad/processor/stack_frame_symbolizer.h" -#include "processor/logging.h" -#include "processor/stackwalker_x86.h" -#include "processor/symbolic_constants_win.h" - -namespace google_breakpad { - -MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, - SourceLineResolverInterface *resolver) - : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), - own_frame_symbolizer_(true), - enable_exploitability_(false), - enable_objdump_(false) { -} - -MinidumpProcessor::MinidumpProcessor(SymbolSupplier *supplier, - SourceLineResolverInterface *resolver, - bool enable_exploitability) - : frame_symbolizer_(new StackFrameSymbolizer(supplier, resolver)), - own_frame_symbolizer_(true), - enable_exploitability_(enable_exploitability), - enable_objdump_(false) { -} - -MinidumpProcessor::MinidumpProcessor(StackFrameSymbolizer *frame_symbolizer, - bool enable_exploitability) - : frame_symbolizer_(frame_symbolizer), - own_frame_symbolizer_(false), - enable_exploitability_(enable_exploitability), - enable_objdump_(false) { - assert(frame_symbolizer_); -} - -MinidumpProcessor::~MinidumpProcessor() { - if (own_frame_symbolizer_) delete frame_symbolizer_; -} - -ProcessResult MinidumpProcessor::Process( - Minidump *dump, ProcessState *process_state) { - assert(dump); - assert(process_state); - - process_state->Clear(); - - const MDRawHeader *header = dump->header(); - if (!header) { - BPLOG(ERROR) << "Minidump " << dump->path() << " has no header"; - return PROCESS_ERROR_NO_MINIDUMP_HEADER; - } - process_state->time_date_stamp_ = header->time_date_stamp; - - bool has_process_create_time = - GetProcessCreateTime(dump, &process_state->process_create_time_); - - bool has_cpu_info = GetCPUInfo(dump, &process_state->system_info_); - bool has_os_info = GetOSInfo(dump, &process_state->system_info_); - - uint32_t dump_thread_id = 0; - bool has_dump_thread = false; - uint32_t requesting_thread_id = 0; - bool has_requesting_thread = false; - - MinidumpBreakpadInfo *breakpad_info = dump->GetBreakpadInfo(); - if (breakpad_info) { - has_dump_thread = breakpad_info->GetDumpThreadID(&dump_thread_id); - has_requesting_thread = - breakpad_info->GetRequestingThreadID(&requesting_thread_id); - } - - MinidumpException *exception = dump->GetException(); - if (exception) { - process_state->crashed_ = true; - has_requesting_thread = exception->GetThreadID(&requesting_thread_id); - - process_state->crash_reason_ = GetCrashReason( - dump, &process_state->crash_address_); - } - - // This will just return an empty string if it doesn't exist. - process_state->assertion_ = GetAssertion(dump); - - MinidumpModuleList *module_list = dump->GetModuleList(); - - // Put a copy of the module list into ProcessState object. This is not - // necessarily a MinidumpModuleList, but it adheres to the CodeModules - // interface, which is all that ProcessState needs to expose. - if (module_list) { - 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(); - if (memory_list) { - BPLOG(INFO) << "Found " << memory_list->region_count() - << " memory regions."; - } - - MinidumpThreadList *threads = dump->GetThreadList(); - if (!threads) { - BPLOG(ERROR) << "Minidump " << dump->path() << " has no thread list"; - return PROCESS_ERROR_NO_THREAD_LIST; - } - - BPLOG(INFO) << "Minidump " << dump->path() << " has " << - (has_cpu_info ? "" : "no ") << "CPU info, " << - (has_os_info ? "" : "no ") << "OS info, " << - (breakpad_info != NULL ? "" : "no ") << "Breakpad info, " << - (exception != NULL ? "" : "no ") << "exception, " << - (module_list != NULL ? "" : "no ") << "module list, " << - (threads != NULL ? "" : "no ") << "thread list, " << - (has_dump_thread ? "" : "no ") << "dump thread, " << - (has_requesting_thread ? "" : "no ") << "requesting thread, and " << - (has_process_create_time ? "" : "no ") << "process create time"; - - bool interrupted = false; - bool found_requesting_thread = false; - unsigned int thread_count = threads->thread_count(); - - // Reset frame_symbolizer_ at the beginning of stackwalk for each minidump. - frame_symbolizer_->Reset(); - - for (unsigned int thread_index = 0; - thread_index < thread_count; - ++thread_index) { - char thread_string_buffer[64]; - snprintf(thread_string_buffer, sizeof(thread_string_buffer), "%d/%d", - thread_index, thread_count); - string thread_string = dump->path() + ":" + thread_string_buffer; - - MinidumpThread *thread = threads->GetThreadAtIndex(thread_index); - if (!thread) { - BPLOG(ERROR) << "Could not get thread for " << thread_string; - return PROCESS_ERROR_GETTING_THREAD; - } - - uint32_t thread_id; - if (!thread->GetThreadID(&thread_id)) { - BPLOG(ERROR) << "Could not get thread ID for " << thread_string; - return PROCESS_ERROR_GETTING_THREAD_ID; - } - - thread_string += " id " + HexString(thread_id); - BPLOG(INFO) << "Looking at thread " << thread_string; - - // If this thread is the thread that produced the minidump, don't process - // it. Because of the problems associated with a thread producing a - // dump of itself (when both its context and its stack are in flux), - // processing that stack wouldn't provide much useful data. - if (has_dump_thread && thread_id == dump_thread_id) { - continue; - } - - MinidumpContext *context = thread->GetContext(); - - if (has_requesting_thread && thread_id == requesting_thread_id) { - if (found_requesting_thread) { - // There can't be more than one requesting thread. - BPLOG(ERROR) << "Duplicate requesting thread: " << thread_string; - return PROCESS_ERROR_DUPLICATE_REQUESTING_THREADS; - } - - // Use processed_state->threads_.size() instead of thread_index. - // thread_index points to the thread index in the minidump, which - // might be greater than the thread index in the threads vector if - // any of the minidump's threads are skipped and not placed into the - // processed threads vector. The thread vector's current size will - // be the index of the current thread when it's pushed into the - // vector. - process_state->requesting_thread_ = process_state->threads_.size(); - - found_requesting_thread = true; - - if (process_state->crashed_) { - // Use the exception record's context for the crashed thread, instead - // of the thread's own context. For the crashed thread, the thread's - // own context is the state inside the exception handler. Using it - // would not result in the expected stack trace from the time of the - // crash. If the exception context is invalid, however, we fall back - // on the thread context. - MinidumpContext *ctx = exception->GetContext(); - context = ctx ? ctx : thread->GetContext(); - } - } - - // If the memory region for the stack cannot be read using the RVA stored - // in the memory descriptor inside MINIDUMP_THREAD, try to locate and use - // a memory region (containing the stack) from the minidump memory list. - MinidumpMemoryRegion *thread_memory = thread->GetMemory(); - if (!thread_memory && memory_list) { - uint64_t start_stack_memory_range = thread->GetStartOfStackMemoryRange(); - if (start_stack_memory_range) { - thread_memory = memory_list->GetMemoryRegionForAddress( - start_stack_memory_range); - } - } - if (!thread_memory) { - BPLOG(ERROR) << "No memory region for " << thread_string; - } - - // Use process_state->modules_ instead of module_list, because the - // |modules| argument will be used to populate the |module| fields in - // the returned StackFrame objects, which will be placed into the - // returned ProcessState object. module_list's lifetime is only as - // long as the Minidump object: it will be deleted when this function - // returns. process_state->modules_ is owned by the ProcessState object - // (just like the StackFrame objects), and is much more suitable for this - // task. - scoped_ptr<Stackwalker> stackwalker( - Stackwalker::StackwalkerForCPU(process_state->system_info(), - context, - thread_memory, - process_state->modules_, - frame_symbolizer_)); - - scoped_ptr<CallStack> stack(new CallStack()); - if (stackwalker.get()) { - if (!stackwalker->Walk(stack.get(), - &process_state->modules_without_symbols_, - &process_state->modules_with_corrupt_symbols_)) { - BPLOG(INFO) << "Stackwalker interrupt (missing symbols?) at " - << thread_string; - interrupted = true; - } - } else { - // Threads with missing CPU contexts will hit this, but - // don't abort processing the rest of the dump just for - // one bad thread. - BPLOG(ERROR) << "No stackwalker for " << thread_string; - } - stack->set_tid(thread_id); - process_state->threads_.push_back(stack.release()); - process_state->thread_memory_regions_.push_back(thread_memory); - } - - if (interrupted) { - BPLOG(INFO) << "Processing interrupted for " << dump->path(); - return PROCESS_SYMBOL_SUPPLIER_INTERRUPTED; - } - - // If a requesting thread was indicated, it must be present. - if (has_requesting_thread && !found_requesting_thread) { - // Don't mark as an error, but invalidate the requesting thread - BPLOG(ERROR) << "Minidump indicated requesting thread " << - HexString(requesting_thread_id) << ", not found in " << - dump->path(); - process_state->requesting_thread_ = -1; - } - - // Exploitability defaults to EXPLOITABILITY_NOT_ANALYZED - process_state->exploitability_ = EXPLOITABILITY_NOT_ANALYZED; - - // If an exploitability run was requested we perform the platform specific - // rating. - if (enable_exploitability_) { - scoped_ptr<Exploitability> exploitability( - Exploitability::ExploitabilityForPlatform(dump, - process_state, - enable_objdump_)); - // The engine will be null if the platform is not supported - if (exploitability != NULL) { - process_state->exploitability_ = exploitability->CheckExploitability(); - } else { - process_state->exploitability_ = EXPLOITABILITY_ERR_NOENGINE; - } - } - - BPLOG(INFO) << "Processed " << dump->path(); - return PROCESS_OK; -} - -ProcessResult MinidumpProcessor::Process( - const string &minidump_file, ProcessState *process_state) { - BPLOG(INFO) << "Processing minidump in file " << minidump_file; - - Minidump dump(minidump_file); - if (!dump.Read()) { - BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read"; - return PROCESS_ERROR_MINIDUMP_NOT_FOUND; - } - - return Process(&dump, process_state); -} - -// Returns the MDRawSystemInfo from a minidump, or NULL if system info is -// not available from the minidump. If system_info is non-NULL, it is used -// to pass back the MinidumpSystemInfo object. -static const MDRawSystemInfo* GetSystemInfo(Minidump *dump, - MinidumpSystemInfo **system_info) { - MinidumpSystemInfo *minidump_system_info = dump->GetSystemInfo(); - if (!minidump_system_info) - return NULL; - - if (system_info) - *system_info = minidump_system_info; - - return minidump_system_info->system_info(); -} - -// Extract CPU info string from ARM-specific MDRawSystemInfo structure. -// raw_info: pointer to source MDRawSystemInfo. -// cpu_info: address of target string, cpu info text will be appended to it. -static void GetARMCpuInfo(const MDRawSystemInfo* raw_info, - string* cpu_info) { - assert(raw_info != NULL && cpu_info != NULL); - - // Write ARM architecture version. - char cpu_string[32]; - snprintf(cpu_string, sizeof(cpu_string), "ARMv%d", - raw_info->processor_level); - cpu_info->append(cpu_string); - - // There is no good list of implementer id values, but the following - // pages provide some help: - // http://comments.gmane.org/gmane.linux.linaro.devel/6903 - // http://forum.xda-developers.com/archive/index.php/t-480226.html - const struct { - uint32_t id; - const char* name; - } vendors[] = { - { 0x41, "ARM" }, - { 0x51, "Qualcomm" }, - { 0x56, "Marvell" }, - { 0x69, "Intel/Marvell" }, - }; - const struct { - uint32_t id; - const char* name; - } parts[] = { - { 0x4100c050, "Cortex-A5" }, - { 0x4100c080, "Cortex-A8" }, - { 0x4100c090, "Cortex-A9" }, - { 0x4100c0f0, "Cortex-A15" }, - { 0x4100c140, "Cortex-R4" }, - { 0x4100c150, "Cortex-R5" }, - { 0x4100b360, "ARM1136" }, - { 0x4100b560, "ARM1156" }, - { 0x4100b760, "ARM1176" }, - { 0x4100b020, "ARM11-MPCore" }, - { 0x41009260, "ARM926" }, - { 0x41009460, "ARM946" }, - { 0x41009660, "ARM966" }, - { 0x510006f0, "Krait" }, - { 0x510000f0, "Scorpion" }, - }; - - const struct { - uint32_t hwcap; - const char* name; - } features[] = { - { MD_CPU_ARM_ELF_HWCAP_SWP, "swp" }, - { MD_CPU_ARM_ELF_HWCAP_HALF, "half" }, - { MD_CPU_ARM_ELF_HWCAP_THUMB, "thumb" }, - { MD_CPU_ARM_ELF_HWCAP_26BIT, "26bit" }, - { MD_CPU_ARM_ELF_HWCAP_FAST_MULT, "fastmult" }, - { MD_CPU_ARM_ELF_HWCAP_FPA, "fpa" }, - { MD_CPU_ARM_ELF_HWCAP_VFP, "vfpv2" }, - { MD_CPU_ARM_ELF_HWCAP_EDSP, "edsp" }, - { MD_CPU_ARM_ELF_HWCAP_JAVA, "java" }, - { MD_CPU_ARM_ELF_HWCAP_IWMMXT, "iwmmxt" }, - { MD_CPU_ARM_ELF_HWCAP_CRUNCH, "crunch" }, - { MD_CPU_ARM_ELF_HWCAP_THUMBEE, "thumbee" }, - { MD_CPU_ARM_ELF_HWCAP_NEON, "neon" }, - { MD_CPU_ARM_ELF_HWCAP_VFPv3, "vfpv3" }, - { MD_CPU_ARM_ELF_HWCAP_VFPv3D16, "vfpv3d16" }, - { MD_CPU_ARM_ELF_HWCAP_TLS, "tls" }, - { MD_CPU_ARM_ELF_HWCAP_VFPv4, "vfpv4" }, - { MD_CPU_ARM_ELF_HWCAP_IDIVA, "idiva" }, - { MD_CPU_ARM_ELF_HWCAP_IDIVT, "idivt" }, - }; - - uint32_t cpuid = raw_info->cpu.arm_cpu_info.cpuid; - if (cpuid != 0) { - // Extract vendor name from CPUID - const char* vendor = NULL; - uint32_t vendor_id = (cpuid >> 24) & 0xff; - for (size_t i = 0; i < sizeof(vendors)/sizeof(vendors[0]); ++i) { - if (vendors[i].id == vendor_id) { - vendor = vendors[i].name; - break; - } - } - cpu_info->append(" "); - if (vendor) { - cpu_info->append(vendor); - } else { - snprintf(cpu_string, sizeof(cpu_string), "vendor(0x%x)", vendor_id); - cpu_info->append(cpu_string); - } - - // Extract part name from CPUID - uint32_t part_id = (cpuid & 0xff00fff0); - const char* part = NULL; - for (size_t i = 0; i < sizeof(parts)/sizeof(parts[0]); ++i) { - if (parts[i].id == part_id) { - part = parts[i].name; - break; - } - } - cpu_info->append(" "); - if (part != NULL) { - cpu_info->append(part); - } else { - snprintf(cpu_string, sizeof(cpu_string), "part(0x%x)", part_id); - cpu_info->append(cpu_string); - } - } - uint32_t elf_hwcaps = raw_info->cpu.arm_cpu_info.elf_hwcaps; - if (elf_hwcaps != 0) { - cpu_info->append(" features: "); - const char* comma = ""; - for (size_t i = 0; i < sizeof(features)/sizeof(features[0]); ++i) { - if (elf_hwcaps & features[i].hwcap) { - cpu_info->append(comma); - cpu_info->append(features[i].name); - comma = ","; - } - } - } -} - -// static -bool MinidumpProcessor::GetCPUInfo(Minidump *dump, SystemInfo *info) { - assert(dump); - assert(info); - - info->cpu.clear(); - info->cpu_info.clear(); - - MinidumpSystemInfo *system_info; - const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); - if (!raw_system_info) - return false; - - switch (raw_system_info->processor_architecture) { - case MD_CPU_ARCHITECTURE_X86: - case MD_CPU_ARCHITECTURE_AMD64: { - if (raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_X86) - info->cpu = "x86"; - else - info->cpu = "amd64"; - - const string *cpu_vendor = system_info->GetCPUVendor(); - if (cpu_vendor) { - info->cpu_info = *cpu_vendor; - info->cpu_info.append(" "); - } - - char x86_info[36]; - snprintf(x86_info, sizeof(x86_info), "family %u model %u stepping %u", - raw_system_info->processor_level, - raw_system_info->processor_revision >> 8, - raw_system_info->processor_revision & 0xff); - info->cpu_info.append(x86_info); - break; - } - - case MD_CPU_ARCHITECTURE_PPC: { - info->cpu = "ppc"; - break; - } - - case MD_CPU_ARCHITECTURE_PPC64: { - info->cpu = "ppc64"; - break; - } - - case MD_CPU_ARCHITECTURE_SPARC: { - info->cpu = "sparc"; - break; - } - - case MD_CPU_ARCHITECTURE_ARM: { - info->cpu = "arm"; - GetARMCpuInfo(raw_system_info, &info->cpu_info); - break; - } - - case MD_CPU_ARCHITECTURE_ARM64: { - info->cpu = "arm64"; - break; - } - - case MD_CPU_ARCHITECTURE_MIPS: { - info->cpu = "mips"; - break; - } - case MD_CPU_ARCHITECTURE_MIPS64: { - info->cpu = "mips64"; - break; - } - - default: { - // Assign the numeric architecture ID into the CPU string. - char cpu_string[7]; - snprintf(cpu_string, sizeof(cpu_string), "0x%04x", - raw_system_info->processor_architecture); - info->cpu = cpu_string; - break; - } - } - - info->cpu_count = raw_system_info->number_of_processors; - - return true; -} - -// static -bool MinidumpProcessor::GetOSInfo(Minidump *dump, SystemInfo *info) { - assert(dump); - assert(info); - - info->os.clear(); - info->os_short.clear(); - info->os_version.clear(); - - MinidumpSystemInfo *system_info; - const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, &system_info); - if (!raw_system_info) - return false; - - info->os_short = system_info->GetOS(); - - switch (raw_system_info->platform_id) { - case MD_OS_WIN32_NT: { - info->os = "Windows NT"; - break; - } - - case MD_OS_WIN32_WINDOWS: { - info->os = "Windows"; - break; - } - - case MD_OS_MAC_OS_X: { - info->os = "Mac OS X"; - break; - } - - case MD_OS_IOS: { - info->os = "iOS"; - break; - } - - case MD_OS_LINUX: { - info->os = "Linux"; - break; - } - - case MD_OS_SOLARIS: { - info->os = "Solaris"; - break; - } - - case MD_OS_ANDROID: { - info->os = "Android"; - break; - } - - case MD_OS_PS3: { - info->os = "PS3"; - break; - } - - case MD_OS_NACL: { - info->os = "NaCl"; - break; - } - - default: { - // Assign the numeric platform ID into the OS string. - char os_string[11]; - snprintf(os_string, sizeof(os_string), "0x%08x", - raw_system_info->platform_id); - info->os = os_string; - break; - } - } - - char os_version_string[33]; - snprintf(os_version_string, sizeof(os_version_string), "%u.%u.%u", - raw_system_info->major_version, - raw_system_info->minor_version, - raw_system_info->build_number); - info->os_version = os_version_string; - - const string *csd_version = system_info->GetCSDVersion(); - if (csd_version) { - info->os_version.append(" "); - info->os_version.append(*csd_version); - } - - return true; -} - -// static -bool MinidumpProcessor::GetProcessCreateTime(Minidump* dump, - uint32_t* process_create_time) { - assert(dump); - assert(process_create_time); - - *process_create_time = 0; - - MinidumpMiscInfo* minidump_misc_info = dump->GetMiscInfo(); - if (!minidump_misc_info) { - return false; - } - - const MDRawMiscInfo* md_raw_misc_info = minidump_misc_info->misc_info(); - if (!md_raw_misc_info) { - return false; - } - - if (!(md_raw_misc_info->flags1 & MD_MISCINFO_FLAGS1_PROCESS_TIMES)) { - return false; - } - - *process_create_time = md_raw_misc_info->process_create_time; - return true; -} - -// static -string MinidumpProcessor::GetCrashReason(Minidump *dump, uint64_t *address) { - MinidumpException *exception = dump->GetException(); - if (!exception) - return ""; - - const MDRawExceptionStream *raw_exception = exception->exception(); - if (!raw_exception) - return ""; - - if (address) - *address = raw_exception->exception_record.exception_address; - - // The reason value is OS-specific and possibly CPU-specific. Set up - // sensible numeric defaults for the reason string in case we can't - // map the codes to a string (because there's no system info, or because - // it's an unrecognized platform, or because it's an unrecognized code.) - char reason_string[24]; - uint32_t exception_code = raw_exception->exception_record.exception_code; - uint32_t exception_flags = raw_exception->exception_record.exception_flags; - snprintf(reason_string, sizeof(reason_string), "0x%08x / 0x%08x", - exception_code, exception_flags); - string reason = reason_string; - - const MDRawSystemInfo *raw_system_info = GetSystemInfo(dump, NULL); - if (!raw_system_info) - return reason; - - switch (raw_system_info->platform_id) { - case MD_OS_MAC_OS_X: - case MD_OS_IOS: { - char flags_string[11]; - snprintf(flags_string, sizeof(flags_string), "0x%08x", exception_flags); - switch (exception_code) { - case MD_EXCEPTION_MAC_BAD_ACCESS: - reason = "EXC_BAD_ACCESS / "; - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_INVALID_ADDRESS: - reason.append("KERN_INVALID_ADDRESS"); - break; - case MD_EXCEPTION_CODE_MAC_PROTECTION_FAILURE: - reason.append("KERN_PROTECTION_FAILURE"); - break; - case MD_EXCEPTION_CODE_MAC_NO_ACCESS: - reason.append("KERN_NO_ACCESS"); - break; - case MD_EXCEPTION_CODE_MAC_MEMORY_FAILURE: - reason.append("KERN_MEMORY_FAILURE"); - break; - case MD_EXCEPTION_CODE_MAC_MEMORY_ERROR: - reason.append("KERN_MEMORY_ERROR"); - break; - default: - // arm and ppc overlap - if (raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_ARM || - raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_ARM64) { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN: - reason.append("EXC_ARM_DA_ALIGN"); - break; - case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG: - reason.append("EXC_ARM_DA_DEBUG"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - } else if (raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_PPC) { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_PPC_VM_PROT_READ: - reason.append("EXC_PPC_VM_PROT_READ"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_BADSPACE: - reason.append("EXC_PPC_BADSPACE"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_UNALIGNED: - reason.append("EXC_PPC_UNALIGNED"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - } else if (raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_X86 || - raw_system_info->processor_architecture == - MD_CPU_ARCHITECTURE_AMD64) { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT: - reason.append("EXC_I386_GPFLT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - } else { - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - } - break; - } - break; - case MD_EXCEPTION_MAC_BAD_INSTRUCTION: - reason = "EXC_BAD_INSTRUCTION / "; - switch (raw_system_info->processor_architecture) { - case MD_CPU_ARCHITECTURE_ARM: - case MD_CPU_ARCHITECTURE_ARM64: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_ARM_UNDEFINED: - reason.append("EXC_ARM_UNDEFINED"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_PPC: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_PPC_INVALID_SYSCALL: - reason.append("EXC_PPC_INVALID_SYSCALL"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_UNIMPLEMENTED_INSTRUCTION: - reason.append("EXC_PPC_UNIPL_INST"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_INSTRUCTION: - reason.append("EXC_PPC_PRIVINST"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_PRIVILEGED_REGISTER: - reason.append("EXC_PPC_PRIVREG"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_TRACE: - reason.append("EXC_PPC_TRACE"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_PERFORMANCE_MONITOR: - reason.append("EXC_PPC_PERFMON"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_AMD64: - case MD_CPU_ARCHITECTURE_X86: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_X86_INVALID_OPERATION: - reason.append("EXC_I386_INVOP"); - break; - case MD_EXCEPTION_CODE_MAC_X86_INVALID_TASK_STATE_SEGMENT: - reason.append("EXC_I386_INVTSSFLT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_SEGMENT_NOT_PRESENT: - reason.append("EXC_I386_SEGNPFLT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_STACK_FAULT: - reason.append("EXC_I386_STKFLT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_GENERAL_PROTECTION_FAULT: - reason.append("EXC_I386_GPFLT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_ALIGNMENT_FAULT: - reason.append("EXC_I386_ALIGNFLT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - case MD_EXCEPTION_MAC_ARITHMETIC: - reason = "EXC_ARITHMETIC / "; - switch (raw_system_info->processor_architecture) { - case MD_CPU_ARCHITECTURE_PPC: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_PPC_OVERFLOW: - reason.append("EXC_PPC_OVERFLOW"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_ZERO_DIVIDE: - reason.append("EXC_PPC_ZERO_DIVIDE"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_INEXACT: - reason.append("EXC_FLT_INEXACT"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_ZERO_DIVIDE: - reason.append("EXC_PPC_FLT_ZERO_DIVIDE"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_UNDERFLOW: - reason.append("EXC_PPC_FLT_UNDERFLOW"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_OVERFLOW: - reason.append("EXC_PPC_FLT_OVERFLOW"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_FLOAT_NOT_A_NUMBER: - reason.append("EXC_PPC_FLT_NOT_A_NUMBER"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_NO_EMULATION: - reason.append("EXC_PPC_NOEMULATION"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_ALTIVEC_ASSIST: - reason.append("EXC_PPC_ALTIVECASSIST"); - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_AMD64: - case MD_CPU_ARCHITECTURE_X86: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_X86_DIV: - reason.append("EXC_I386_DIV"); - break; - case MD_EXCEPTION_CODE_MAC_X86_INTO: - reason.append("EXC_I386_INTO"); - break; - case MD_EXCEPTION_CODE_MAC_X86_NOEXT: - reason.append("EXC_I386_NOEXT"); - break; - case MD_EXCEPTION_CODE_MAC_X86_EXTOVR: - reason.append("EXC_I386_EXTOVR"); - break; - case MD_EXCEPTION_CODE_MAC_X86_EXTERR: - reason.append("EXC_I386_EXTERR"); - break; - case MD_EXCEPTION_CODE_MAC_X86_EMERR: - reason.append("EXC_I386_EMERR"); - break; - case MD_EXCEPTION_CODE_MAC_X86_BOUND: - reason.append("EXC_I386_BOUND"); - break; - case MD_EXCEPTION_CODE_MAC_X86_SSEEXTERR: - reason.append("EXC_I386_SSEEXTERR"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - case MD_EXCEPTION_MAC_EMULATION: - reason = "EXC_EMULATION / "; - reason.append(flags_string); - break; - case MD_EXCEPTION_MAC_SOFTWARE: - reason = "EXC_SOFTWARE / "; - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_ABORT: - reason.append("SIGABRT"); - break; - case MD_EXCEPTION_CODE_MAC_NS_EXCEPTION: - reason.append("UNCAUGHT_NS_EXCEPTION"); - break; - // These are ppc only but shouldn't be a problem as they're - // unused on x86 - case MD_EXCEPTION_CODE_MAC_PPC_TRAP: - reason.append("EXC_PPC_TRAP"); - break; - case MD_EXCEPTION_CODE_MAC_PPC_MIGRATE: - reason.append("EXC_PPC_MIGRATE"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - case MD_EXCEPTION_MAC_BREAKPOINT: - reason = "EXC_BREAKPOINT / "; - switch (raw_system_info->processor_architecture) { - case MD_CPU_ARCHITECTURE_ARM: - case MD_CPU_ARCHITECTURE_ARM64: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_ARM_DA_ALIGN: - reason.append("EXC_ARM_DA_ALIGN"); - break; - case MD_EXCEPTION_CODE_MAC_ARM_DA_DEBUG: - reason.append("EXC_ARM_DA_DEBUG"); - break; - case MD_EXCEPTION_CODE_MAC_ARM_BREAKPOINT: - reason.append("EXC_ARM_BREAKPOINT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_PPC: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_PPC_BREAKPOINT: - reason.append("EXC_PPC_BREAKPOINT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - case MD_CPU_ARCHITECTURE_AMD64: - case MD_CPU_ARCHITECTURE_X86: { - switch (exception_flags) { - case MD_EXCEPTION_CODE_MAC_X86_SGL: - reason.append("EXC_I386_SGL"); - break; - case MD_EXCEPTION_CODE_MAC_X86_BPT: - reason.append("EXC_I386_BPT"); - break; - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - default: - reason.append(flags_string); - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - case MD_EXCEPTION_MAC_SYSCALL: - reason = "EXC_SYSCALL / "; - reason.append(flags_string); - break; - case MD_EXCEPTION_MAC_MACH_SYSCALL: - reason = "EXC_MACH_SYSCALL / "; - reason.append(flags_string); - break; - case MD_EXCEPTION_MAC_RPC_ALERT: - reason = "EXC_RPC_ALERT / "; - reason.append(flags_string); - break; - } - break; - } - - case MD_OS_WIN32_NT: - case MD_OS_WIN32_WINDOWS: { - switch (exception_code) { - case MD_EXCEPTION_CODE_WIN_CONTROL_C: - reason = "DBG_CONTROL_C"; - break; - case MD_EXCEPTION_CODE_WIN_GUARD_PAGE_VIOLATION: - reason = "EXCEPTION_GUARD_PAGE"; - break; - case MD_EXCEPTION_CODE_WIN_DATATYPE_MISALIGNMENT: - reason = "EXCEPTION_DATATYPE_MISALIGNMENT"; - break; - case MD_EXCEPTION_CODE_WIN_BREAKPOINT: - reason = "EXCEPTION_BREAKPOINT"; - break; - case MD_EXCEPTION_CODE_WIN_SINGLE_STEP: - reason = "EXCEPTION_SINGLE_STEP"; - break; - case MD_EXCEPTION_CODE_WIN_ACCESS_VIOLATION: - // For EXCEPTION_ACCESS_VIOLATION, Windows puts the address that - // caused the fault in exception_information[1]. - // exception_information[0] is 0 if the violation was caused by - // an attempt to read data, 1 if it was an attempt to write data, - // and 8 if this was a data execution violation. - // This information is useful in addition to the code address, which - // will be present in the crash thread's instruction field anyway. - if (raw_exception->exception_record.number_parameters >= 1) { - MDAccessViolationTypeWin av_type = - static_cast<MDAccessViolationTypeWin> - (raw_exception->exception_record.exception_information[0]); - switch (av_type) { - case MD_ACCESS_VIOLATION_WIN_READ: - reason = "EXCEPTION_ACCESS_VIOLATION_READ"; - break; - case MD_ACCESS_VIOLATION_WIN_WRITE: - reason = "EXCEPTION_ACCESS_VIOLATION_WRITE"; - break; - case MD_ACCESS_VIOLATION_WIN_EXEC: - reason = "EXCEPTION_ACCESS_VIOLATION_EXEC"; - break; - default: - reason = "EXCEPTION_ACCESS_VIOLATION"; - break; - } - } else { - reason = "EXCEPTION_ACCESS_VIOLATION"; - } - if (address && - raw_exception->exception_record.number_parameters >= 2) { - *address = - raw_exception->exception_record.exception_information[1]; - } - break; - case MD_EXCEPTION_CODE_WIN_IN_PAGE_ERROR: - // For EXCEPTION_IN_PAGE_ERROR, Windows puts the address that - // caused the fault in exception_information[1]. - // exception_information[0] is 0 if the violation was caused by - // an attempt to read data, 1 if it was an attempt to write data, - // and 8 if this was a data execution violation. - // exception_information[2] contains the underlying NTSTATUS code, - // which is the explanation for why this error occured. - // This information is useful in addition to the code address, which - // will be present in the crash thread's instruction field anyway. - if (raw_exception->exception_record.number_parameters >= 1) { - MDInPageErrorTypeWin av_type = - static_cast<MDInPageErrorTypeWin> - (raw_exception->exception_record.exception_information[0]); - switch (av_type) { - case MD_IN_PAGE_ERROR_WIN_READ: - reason = "EXCEPTION_IN_PAGE_ERROR_READ"; - break; - case MD_IN_PAGE_ERROR_WIN_WRITE: - reason = "EXCEPTION_IN_PAGE_ERROR_WRITE"; - break; - case MD_IN_PAGE_ERROR_WIN_EXEC: - reason = "EXCEPTION_IN_PAGE_ERROR_EXEC"; - break; - default: - reason = "EXCEPTION_IN_PAGE_ERROR"; - break; - } - } else { - reason = "EXCEPTION_IN_PAGE_ERROR"; - } - if (address && - raw_exception->exception_record.number_parameters >= 2) { - *address = - raw_exception->exception_record.exception_information[1]; - } - if (raw_exception->exception_record.number_parameters >= 3) { - uint32_t ntstatus = - static_cast<uint32_t> - (raw_exception->exception_record.exception_information[2]); - reason.append(" / "); - reason.append(NTStatusToString(ntstatus)); - } - break; - case MD_EXCEPTION_CODE_WIN_INVALID_HANDLE: - reason = "EXCEPTION_INVALID_HANDLE"; - break; - case MD_EXCEPTION_CODE_WIN_ILLEGAL_INSTRUCTION: - reason = "EXCEPTION_ILLEGAL_INSTRUCTION"; - break; - case MD_EXCEPTION_CODE_WIN_NONCONTINUABLE_EXCEPTION: - reason = "EXCEPTION_NONCONTINUABLE_EXCEPTION"; - break; - case MD_EXCEPTION_CODE_WIN_INVALID_DISPOSITION: - reason = "EXCEPTION_INVALID_DISPOSITION"; - break; - case MD_EXCEPTION_CODE_WIN_ARRAY_BOUNDS_EXCEEDED: - reason = "EXCEPTION_BOUNDS_EXCEEDED"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_DENORMAL_OPERAND: - reason = "EXCEPTION_FLT_DENORMAL_OPERAND"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_DIVIDE_BY_ZERO: - reason = "EXCEPTION_FLT_DIVIDE_BY_ZERO"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_INEXACT_RESULT: - reason = "EXCEPTION_FLT_INEXACT_RESULT"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_INVALID_OPERATION: - reason = "EXCEPTION_FLT_INVALID_OPERATION"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_OVERFLOW: - reason = "EXCEPTION_FLT_OVERFLOW"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_STACK_CHECK: - reason = "EXCEPTION_FLT_STACK_CHECK"; - break; - case MD_EXCEPTION_CODE_WIN_FLOAT_UNDERFLOW: - reason = "EXCEPTION_FLT_UNDERFLOW"; - break; - case MD_EXCEPTION_CODE_WIN_INTEGER_DIVIDE_BY_ZERO: - reason = "EXCEPTION_INT_DIVIDE_BY_ZERO"; - break; - case MD_EXCEPTION_CODE_WIN_INTEGER_OVERFLOW: - reason = "EXCEPTION_INT_OVERFLOW"; - break; - case MD_EXCEPTION_CODE_WIN_PRIVILEGED_INSTRUCTION: - reason = "EXCEPTION_PRIV_INSTRUCTION"; - break; - case MD_EXCEPTION_CODE_WIN_STACK_OVERFLOW: - reason = "EXCEPTION_STACK_OVERFLOW"; - break; - case MD_EXCEPTION_CODE_WIN_POSSIBLE_DEADLOCK: - reason = "EXCEPTION_POSSIBLE_DEADLOCK"; - break; - case MD_EXCEPTION_CODE_WIN_STACK_BUFFER_OVERRUN: - reason = "EXCEPTION_STACK_BUFFER_OVERRUN"; - break; - case MD_EXCEPTION_CODE_WIN_HEAP_CORRUPTION: - reason = "EXCEPTION_HEAP_CORRUPTION"; - break; - case MD_EXCEPTION_OUT_OF_MEMORY: - reason = "Out of Memory"; - break; - case MD_EXCEPTION_CODE_WIN_UNHANDLED_CPP_EXCEPTION: - reason = "Unhandled C++ Exception"; - break; - default: - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - - case MD_OS_ANDROID: - case MD_OS_LINUX: { - switch (exception_code) { - case MD_EXCEPTION_CODE_LIN_SIGHUP: - reason = "SIGHUP"; - break; - case MD_EXCEPTION_CODE_LIN_SIGINT: - reason = "SIGINT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGQUIT: - reason = "SIGQUIT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGILL: - reason = "SIGILL"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTRAP: - reason = "SIGTRAP"; - break; - case MD_EXCEPTION_CODE_LIN_SIGABRT: - reason = "SIGABRT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGBUS: - reason = "SIGBUS"; - break; - case MD_EXCEPTION_CODE_LIN_SIGFPE: - reason = "SIGFPE"; - break; - case MD_EXCEPTION_CODE_LIN_SIGKILL: - reason = "SIGKILL"; - break; - case MD_EXCEPTION_CODE_LIN_SIGUSR1: - reason = "SIGUSR1"; - break; - case MD_EXCEPTION_CODE_LIN_SIGSEGV: - reason = "SIGSEGV"; - break; - case MD_EXCEPTION_CODE_LIN_SIGUSR2: - reason = "SIGUSR2"; - break; - case MD_EXCEPTION_CODE_LIN_SIGPIPE: - reason = "SIGPIPE"; - break; - case MD_EXCEPTION_CODE_LIN_SIGALRM: - reason = "SIGALRM"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTERM: - reason = "SIGTERM"; - break; - case MD_EXCEPTION_CODE_LIN_SIGSTKFLT: - reason = "SIGSTKFLT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGCHLD: - reason = "SIGCHLD"; - break; - case MD_EXCEPTION_CODE_LIN_SIGCONT: - reason = "SIGCONT"; - break; - case MD_EXCEPTION_CODE_LIN_SIGSTOP: - reason = "SIGSTOP"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTSTP: - reason = "SIGTSTP"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTTIN: - reason = "SIGTTIN"; - break; - case MD_EXCEPTION_CODE_LIN_SIGTTOU: - reason = "SIGTTOU"; - break; - case MD_EXCEPTION_CODE_LIN_SIGURG: - reason = "SIGURG"; - break; - case MD_EXCEPTION_CODE_LIN_SIGXCPU: - reason = "SIGXCPU"; - break; - case MD_EXCEPTION_CODE_LIN_SIGXFSZ: - reason = "SIGXFSZ"; - break; - case MD_EXCEPTION_CODE_LIN_SIGVTALRM: - reason = "SIGVTALRM"; - break; - case MD_EXCEPTION_CODE_LIN_SIGPROF: - reason = "SIGPROF"; - break; - case MD_EXCEPTION_CODE_LIN_SIGWINCH: - reason = "SIGWINCH"; - break; - case MD_EXCEPTION_CODE_LIN_SIGIO: - reason = "SIGIO"; - break; - case MD_EXCEPTION_CODE_LIN_SIGPWR: - reason = "SIGPWR"; - break; - case MD_EXCEPTION_CODE_LIN_SIGSYS: - reason = "SIGSYS"; - break; - case MD_EXCEPTION_CODE_LIN_DUMP_REQUESTED: - reason = "DUMP_REQUESTED"; - break; - default: - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - - case MD_OS_SOLARIS: { - switch (exception_code) { - case MD_EXCEPTION_CODE_SOL_SIGHUP: - reason = "SIGHUP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGINT: - reason = "SIGINT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGQUIT: - reason = "SIGQUIT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGILL: - reason = "SIGILL"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTRAP: - reason = "SIGTRAP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGIOT: - reason = "SIGIOT | SIGABRT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGEMT: - reason = "SIGEMT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGFPE: - reason = "SIGFPE"; - break; - case MD_EXCEPTION_CODE_SOL_SIGKILL: - reason = "SIGKILL"; - break; - case MD_EXCEPTION_CODE_SOL_SIGBUS: - reason = "SIGBUS"; - break; - case MD_EXCEPTION_CODE_SOL_SIGSEGV: - reason = "SIGSEGV"; - break; - case MD_EXCEPTION_CODE_SOL_SIGSYS: - reason = "SIGSYS"; - break; - case MD_EXCEPTION_CODE_SOL_SIGPIPE: - reason = "SIGPIPE"; - break; - case MD_EXCEPTION_CODE_SOL_SIGALRM: - reason = "SIGALRM"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTERM: - reason = "SIGTERM"; - break; - case MD_EXCEPTION_CODE_SOL_SIGUSR1: - reason = "SIGUSR1"; - break; - case MD_EXCEPTION_CODE_SOL_SIGUSR2: - reason = "SIGUSR2"; - break; - case MD_EXCEPTION_CODE_SOL_SIGCLD: - reason = "SIGCLD | SIGCHLD"; - break; - case MD_EXCEPTION_CODE_SOL_SIGPWR: - reason = "SIGPWR"; - break; - case MD_EXCEPTION_CODE_SOL_SIGWINCH: - reason = "SIGWINCH"; - break; - case MD_EXCEPTION_CODE_SOL_SIGURG: - reason = "SIGURG"; - break; - case MD_EXCEPTION_CODE_SOL_SIGPOLL: - reason = "SIGPOLL | SIGIO"; - break; - case MD_EXCEPTION_CODE_SOL_SIGSTOP: - reason = "SIGSTOP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTSTP: - reason = "SIGTSTP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGCONT: - reason = "SIGCONT"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTTIN: - reason = "SIGTTIN"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTTOU: - reason = "SIGTTOU"; - break; - case MD_EXCEPTION_CODE_SOL_SIGVTALRM: - reason = "SIGVTALRM"; - break; - case MD_EXCEPTION_CODE_SOL_SIGPROF: - reason = "SIGPROF"; - break; - case MD_EXCEPTION_CODE_SOL_SIGXCPU: - reason = "SIGXCPU"; - break; - case MD_EXCEPTION_CODE_SOL_SIGXFSZ: - reason = "SIGXFSZ"; - break; - case MD_EXCEPTION_CODE_SOL_SIGWAITING: - reason = "SIGWAITING"; - break; - case MD_EXCEPTION_CODE_SOL_SIGLWP: - reason = "SIGLWP"; - break; - case MD_EXCEPTION_CODE_SOL_SIGFREEZE: - reason = "SIGFREEZE"; - break; - case MD_EXCEPTION_CODE_SOL_SIGTHAW: - reason = "SIGTHAW"; - break; - case MD_EXCEPTION_CODE_SOL_SIGCANCEL: - reason = "SIGCANCEL"; - break; - case MD_EXCEPTION_CODE_SOL_SIGLOST: - reason = "SIGLOST"; - break; - case MD_EXCEPTION_CODE_SOL_SIGXRES: - reason = "SIGXRES"; - break; - case MD_EXCEPTION_CODE_SOL_SIGJVM1: - reason = "SIGJVM1"; - break; - case MD_EXCEPTION_CODE_SOL_SIGJVM2: - reason = "SIGJVM2"; - break; - default: - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - break; - } - - case MD_OS_PS3: { - switch (exception_code) { - case MD_EXCEPTION_CODE_PS3_UNKNOWN: - reason = "UNKNOWN"; - break; - case MD_EXCEPTION_CODE_PS3_TRAP_EXCEP: - reason = "TRAP_EXCEP"; - break; - case MD_EXCEPTION_CODE_PS3_PRIV_INSTR: - reason = "PRIV_INSTR"; - break; - case MD_EXCEPTION_CODE_PS3_ILLEGAL_INSTR: - reason = "ILLEGAL_INSTR"; - break; - case MD_EXCEPTION_CODE_PS3_INSTR_STORAGE: - reason = "INSTR_STORAGE"; - break; - case MD_EXCEPTION_CODE_PS3_INSTR_SEGMENT: - reason = "INSTR_SEGMENT"; - break; - case MD_EXCEPTION_CODE_PS3_DATA_STORAGE: - reason = "DATA_STORAGE"; - break; - case MD_EXCEPTION_CODE_PS3_DATA_SEGMENT: - reason = "DATA_SEGMENT"; - break; - case MD_EXCEPTION_CODE_PS3_FLOAT_POINT: - reason = "FLOAT_POINT"; - break; - case MD_EXCEPTION_CODE_PS3_DABR_MATCH: - reason = "DABR_MATCH"; - break; - case MD_EXCEPTION_CODE_PS3_ALIGN_EXCEP: - reason = "ALIGN_EXCEP"; - break; - case MD_EXCEPTION_CODE_PS3_MEMORY_ACCESS: - reason = "MEMORY_ACCESS"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_ALIGN: - reason = "COPRO_ALIGN"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_INVALID_COM: - reason = "COPRO_INVALID_COM"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_ERR: - reason = "COPRO_ERR"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_FIR: - reason = "COPRO_FIR"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_DATA_SEGMENT: - reason = "COPRO_DATA_SEGMENT"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_DATA_STORAGE: - reason = "COPRO_DATA_STORAGE"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_STOP_INSTR: - reason = "COPRO_STOP_INSTR"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_HALT_INSTR: - reason = "COPRO_HALT_INSTR"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_HALTINST_UNKNOWN: - reason = "COPRO_HALTINSTR_UNKNOWN"; - break; - case MD_EXCEPTION_CODE_PS3_COPRO_MEMORY_ACCESS: - reason = "COPRO_MEMORY_ACCESS"; - break; - case MD_EXCEPTION_CODE_PS3_GRAPHIC: - reason = "GRAPHIC"; - break; - default: - BPLOG(INFO) << "Unknown exception reason "<< reason; - break; - } - break; - } - - default: { - BPLOG(INFO) << "Unknown exception reason " << reason; - break; - } - } - - return reason; -} - -// static -string MinidumpProcessor::GetAssertion(Minidump *dump) { - MinidumpAssertion *assertion = dump->GetAssertion(); - if (!assertion) - return ""; - - const MDRawAssertionInfo *raw_assertion = assertion->assertion(); - if (!raw_assertion) - return ""; - - string assertion_string; - switch (raw_assertion->type) { - case MD_ASSERTION_INFO_TYPE_INVALID_PARAMETER: - assertion_string = "Invalid parameter passed to library function"; - break; - case MD_ASSERTION_INFO_TYPE_PURE_VIRTUAL_CALL: - assertion_string = "Pure virtual function called"; - break; - default: { - char assertion_type[32]; - snprintf(assertion_type, sizeof(assertion_type), - "0x%08x", raw_assertion->type); - assertion_string = "Unknown assertion type "; - assertion_string += assertion_type; - break; - } - } - - string expression = assertion->expression(); - if (!expression.empty()) { - assertion_string.append(" " + expression); - } - - string function = assertion->function(); - if (!function.empty()) { - assertion_string.append(" in function " + function); - } - - string file = assertion->file(); - if (!file.empty()) { - assertion_string.append(", in file " + file); - } - - if (raw_assertion->line != 0) { - char assertion_line[32]; - snprintf(assertion_line, sizeof(assertion_line), "%u", raw_assertion->line); - assertion_string.append(" at line "); - assertion_string.append(assertion_line); - } - - return assertion_string; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc deleted file mode 100644 index d43c1fc97..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_processor_unittest.cc +++ /dev/null @@ -1,645 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Unit test for MinidumpProcessor. Uses a pre-generated minidump and -// corresponding symbol file, and checks the stack frames for correctness. - -#include <stdlib.h> - -#include <string> -#include <iostream> -#include <fstream> -#include <map> -#include <utility> - -#include "breakpad_googletest_includes.h" -#include "common/scoped_ptr.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/code_modules.h" -#include "google_breakpad/processor/minidump.h" -#include "google_breakpad/processor/minidump_processor.h" -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/stack_frame.h" -#include "google_breakpad/processor/symbol_supplier.h" -#include "processor/logging.h" -#include "processor/stackwalker_unittest_utils.h" - -using std::map; - -namespace google_breakpad { -class MockMinidump : public Minidump { - public: - MockMinidump() : Minidump("") { - } - - MOCK_METHOD0(Read, bool()); - MOCK_CONST_METHOD0(path, string()); - MOCK_CONST_METHOD0(header, const MDRawHeader*()); - MOCK_METHOD0(GetThreadList, MinidumpThreadList*()); - MOCK_METHOD0(GetSystemInfo, MinidumpSystemInfo*()); - MOCK_METHOD0(GetMiscInfo, MinidumpMiscInfo*()); - MOCK_METHOD0(GetBreakpadInfo, MinidumpBreakpadInfo*()); - MOCK_METHOD0(GetException, MinidumpException*()); - MOCK_METHOD0(GetAssertion, MinidumpAssertion*()); - MOCK_METHOD0(GetModuleList, MinidumpModuleList*()); - MOCK_METHOD0(GetMemoryList, MinidumpMemoryList*()); -}; - -class MockMinidumpThreadList : public MinidumpThreadList { - public: - MockMinidumpThreadList() : MinidumpThreadList(NULL) {} - - MOCK_CONST_METHOD0(thread_count, unsigned int()); - MOCK_CONST_METHOD1(GetThreadAtIndex, MinidumpThread*(unsigned int)); -}; - -class MockMinidumpMemoryList : public MinidumpMemoryList { - public: - MockMinidumpMemoryList() : MinidumpMemoryList(NULL) {} - - MOCK_METHOD1(GetMemoryRegionForAddress, MinidumpMemoryRegion*(uint64_t)); -}; - -class MockMinidumpThread : public MinidumpThread { - public: - MockMinidumpThread() : MinidumpThread(NULL) {} - - MOCK_CONST_METHOD1(GetThreadID, bool(uint32_t*)); - MOCK_METHOD0(GetContext, MinidumpContext*()); - MOCK_METHOD0(GetMemory, MinidumpMemoryRegion*()); - MOCK_CONST_METHOD0(GetStartOfStackMemoryRange, uint64_t()); -}; - -// This is crappy, but MinidumpProcessor really does want a -// MinidumpMemoryRegion. -class MockMinidumpMemoryRegion : public MinidumpMemoryRegion { - public: - MockMinidumpMemoryRegion(uint64_t base, const string& contents) : - MinidumpMemoryRegion(NULL) { - region_.Init(base, contents); - } - - uint64_t GetBase() const { return region_.GetBase(); } - uint32_t GetSize() const { return region_.GetSize(); } - - bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const { - return region_.GetMemoryAtAddress(address, value); - } - bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const { - return region_.GetMemoryAtAddress(address, value); - } - bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const { - return region_.GetMemoryAtAddress(address, value); - } - bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const { - return region_.GetMemoryAtAddress(address, value); - } - - MockMemoryRegion region_; -}; - -// A test miscelaneous info stream, just returns values from the -// MDRawMiscInfo fed to it. -class TestMinidumpMiscInfo : public MinidumpMiscInfo { - public: - explicit TestMinidumpMiscInfo(const MDRawMiscInfo& misc_info) : - MinidumpMiscInfo(NULL) { - valid_ = true; - misc_info_ = misc_info; - } -}; - -} // namespace google_breakpad - -namespace { - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::CallStack; -using google_breakpad::CodeModule; -using google_breakpad::MinidumpContext; -using google_breakpad::MinidumpMemoryRegion; -using google_breakpad::MinidumpMiscInfo; -using google_breakpad::MinidumpProcessor; -using google_breakpad::MinidumpSystemInfo; -using google_breakpad::MinidumpThreadList; -using google_breakpad::MinidumpThread; -using google_breakpad::MockMinidump; -using google_breakpad::MockMinidumpMemoryList; -using google_breakpad::MockMinidumpMemoryRegion; -using google_breakpad::MockMinidumpThread; -using google_breakpad::MockMinidumpThreadList; -using google_breakpad::ProcessState; -using google_breakpad::scoped_ptr; -using google_breakpad::SymbolSupplier; -using google_breakpad::SystemInfo; -using ::testing::_; -using ::testing::AnyNumber; -using ::testing::DoAll; -using ::testing::Mock; -using ::testing::Ne; -using ::testing::Property; -using ::testing::Return; -using ::testing::SetArgumentPointee; - -static const char *kSystemInfoOS = "Windows NT"; -static const char *kSystemInfoOSShort = "windows"; -static const char *kSystemInfoOSVersion = "5.1.2600 Service Pack 2"; -static const char *kSystemInfoCPU = "x86"; -static const char *kSystemInfoCPUInfo = - "GenuineIntel family 6 model 13 stepping 8"; - -#define ASSERT_TRUE_ABORT(cond) \ - if (!(cond)) { \ - fprintf(stderr, "FAILED: %s at %s:%d\n", #cond, __FILE__, __LINE__); \ - abort(); \ - } - -#define ASSERT_EQ_ABORT(e1, e2) ASSERT_TRUE_ABORT((e1) == (e2)) - -class TestSymbolSupplier : public SymbolSupplier { - public: - TestSymbolSupplier() : interrupt_(false) {} - - virtual SymbolResult GetSymbolFile(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file); - - virtual SymbolResult GetSymbolFile(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - string *symbol_data); - - virtual SymbolResult GetCStringSymbolData(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - char **symbol_data, - size_t *symbol_data_size); - - virtual void FreeSymbolData(const CodeModule *module); - - // When set to true, causes the SymbolSupplier to return INTERRUPT - void set_interrupt(bool interrupt) { interrupt_ = interrupt; } - - private: - bool interrupt_; - map<string, char *> memory_buffers_; -}; - -SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile( - const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file) { - ASSERT_TRUE_ABORT(module); - ASSERT_TRUE_ABORT(system_info); - ASSERT_EQ_ABORT(system_info->cpu, kSystemInfoCPU); - ASSERT_EQ_ABORT(system_info->cpu_info, kSystemInfoCPUInfo); - ASSERT_EQ_ABORT(system_info->os, kSystemInfoOS); - ASSERT_EQ_ABORT(system_info->os_short, kSystemInfoOSShort); - ASSERT_EQ_ABORT(system_info->os_version, kSystemInfoOSVersion); - - if (interrupt_) { - return INTERRUPT; - } - - if (module && module->code_file() == "c:\\test_app.exe") { - *symbol_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + - "/src/processor/testdata/symbols/test_app.pdb/" + - module->debug_identifier() + - "/test_app.sym"; - return FOUND; - } - - return NOT_FOUND; -} - -SymbolSupplier::SymbolResult TestSymbolSupplier::GetSymbolFile( - const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - string *symbol_data) { - SymbolSupplier::SymbolResult s = GetSymbolFile(module, system_info, - symbol_file); - if (s == FOUND) { - std::ifstream in(symbol_file->c_str()); - std::getline(in, *symbol_data, string::traits_type::to_char_type( - string::traits_type::eof())); - in.close(); - } - - return s; -} - -SymbolSupplier::SymbolResult TestSymbolSupplier::GetCStringSymbolData( - const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - char **symbol_data, - size_t *symbol_data_size) { - string symbol_data_string; - SymbolSupplier::SymbolResult s = GetSymbolFile(module, - system_info, - symbol_file, - &symbol_data_string); - if (s == FOUND) { - *symbol_data_size = symbol_data_string.size() + 1; - *symbol_data = new char[*symbol_data_size]; - if (*symbol_data == NULL) { - BPLOG(ERROR) << "Memory allocation failed for module: " - << module->code_file() << " size: " << *symbol_data_size; - return INTERRUPT; - } - memcpy(*symbol_data, symbol_data_string.c_str(), symbol_data_string.size()); - (*symbol_data)[symbol_data_string.size()] = '\0'; - memory_buffers_.insert(make_pair(module->code_file(), *symbol_data)); - } - - return s; -} - -void TestSymbolSupplier::FreeSymbolData(const CodeModule *module) { - map<string, char *>::iterator it = memory_buffers_.find(module->code_file()); - if (it != memory_buffers_.end()) { - delete [] it->second; - memory_buffers_.erase(it); - } -} - -// A test system info stream, just returns values from the -// MDRawSystemInfo fed to it. -class TestMinidumpSystemInfo : public MinidumpSystemInfo { - public: - explicit TestMinidumpSystemInfo(MDRawSystemInfo info) : - MinidumpSystemInfo(NULL) { - valid_ = true; - system_info_ = info; - csd_version_ = new string(""); - } -}; - -// A test minidump context, just returns the MDRawContextX86 -// fed to it. -class TestMinidumpContext : public MinidumpContext { - public: - explicit TestMinidumpContext(const MDRawContextX86& context) : - MinidumpContext(NULL) { - valid_ = true; - SetContextX86(new MDRawContextX86(context)); - SetContextFlags(MD_CONTEXT_X86); - } -}; - -class MinidumpProcessorTest : public ::testing::Test { -}; - -TEST_F(MinidumpProcessorTest, TestCorruptMinidumps) { - MockMinidump dump; - TestSymbolSupplier supplier; - BasicSourceLineResolver resolver; - MinidumpProcessor processor(&supplier, &resolver); - ProcessState state; - - EXPECT_EQ(processor.Process("nonexistent minidump", &state), - google_breakpad::PROCESS_ERROR_MINIDUMP_NOT_FOUND); - - EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump")); - EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true)); - - MDRawHeader fakeHeader; - fakeHeader.time_date_stamp = 0; - EXPECT_CALL(dump, header()). - WillOnce(Return(reinterpret_cast<MDRawHeader*>(NULL))). - WillRepeatedly(Return(&fakeHeader)); - - EXPECT_EQ(processor.Process(&dump, &state), - google_breakpad::PROCESS_ERROR_NO_MINIDUMP_HEADER); - - EXPECT_CALL(dump, GetThreadList()). - WillOnce(Return(reinterpret_cast<MinidumpThreadList*>(NULL))); - EXPECT_CALL(dump, GetSystemInfo()). - WillRepeatedly(Return(reinterpret_cast<MinidumpSystemInfo*>(NULL))); - - EXPECT_EQ(processor.Process(&dump, &state), - google_breakpad::PROCESS_ERROR_NO_THREAD_LIST); -} - -// This test case verifies that the symbol supplier is only consulted -// once per minidump per module. -TEST_F(MinidumpProcessorTest, TestSymbolSupplierLookupCounts) { - MockSymbolSupplier supplier; - BasicSourceLineResolver resolver; - MinidumpProcessor processor(&supplier, &resolver); - - string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + - "/src/processor/testdata/minidump2.dmp"; - ProcessState state; - EXPECT_CALL(supplier, GetCStringSymbolData( - Property(&google_breakpad::CodeModule::code_file, - "c:\\test_app.exe"), - _, _, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND)); - EXPECT_CALL(supplier, GetCStringSymbolData( - Property(&google_breakpad::CodeModule::code_file, - Ne("c:\\test_app.exe")), - _, _, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND)); - // Avoid GMOCK WARNING "Uninteresting mock function call - returning - // directly" for FreeSymbolData(). - EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); - ASSERT_EQ(processor.Process(minidump_file, &state), - google_breakpad::PROCESS_OK); - - ASSERT_TRUE(Mock::VerifyAndClearExpectations(&supplier)); - - // We need to verify that across minidumps, the processor will refetch - // symbol files, even with the same symbol supplier. - EXPECT_CALL(supplier, GetCStringSymbolData( - Property(&google_breakpad::CodeModule::code_file, - "c:\\test_app.exe"), - _, _, _, _)).WillOnce(Return(SymbolSupplier::NOT_FOUND)); - EXPECT_CALL(supplier, GetCStringSymbolData( - Property(&google_breakpad::CodeModule::code_file, - Ne("c:\\test_app.exe")), - _, _, _, _)).WillRepeatedly(Return(SymbolSupplier::NOT_FOUND)); - // Avoid GMOCK WARNING "Uninteresting mock function call - returning - // directly" for FreeSymbolData(). - EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); - ASSERT_EQ(processor.Process(minidump_file, &state), - google_breakpad::PROCESS_OK); -} - -TEST_F(MinidumpProcessorTest, TestBasicProcessing) { - TestSymbolSupplier supplier; - BasicSourceLineResolver resolver; - MinidumpProcessor processor(&supplier, &resolver); - - string minidump_file = string(getenv("srcdir") ? getenv("srcdir") : ".") + - "/src/processor/testdata/minidump2.dmp"; - - ProcessState state; - ASSERT_EQ(processor.Process(minidump_file, &state), - google_breakpad::PROCESS_OK); - ASSERT_EQ(state.system_info()->os, kSystemInfoOS); - ASSERT_EQ(state.system_info()->os_short, kSystemInfoOSShort); - ASSERT_EQ(state.system_info()->os_version, kSystemInfoOSVersion); - ASSERT_EQ(state.system_info()->cpu, kSystemInfoCPU); - ASSERT_EQ(state.system_info()->cpu_info, kSystemInfoCPUInfo); - ASSERT_TRUE(state.crashed()); - ASSERT_EQ(state.crash_reason(), "EXCEPTION_ACCESS_VIOLATION_WRITE"); - ASSERT_EQ(state.crash_address(), 0x45U); - ASSERT_EQ(state.threads()->size(), size_t(1)); - EXPECT_EQ((*state.threads())[0]->tid(), 3060U); - ASSERT_EQ(state.requesting_thread(), 0); - EXPECT_EQ(1171480435U, state.time_date_stamp()); - EXPECT_EQ(1171480435U, state.process_create_time()); - - CallStack *stack = state.threads()->at(0); - ASSERT_TRUE(stack); - ASSERT_EQ(stack->frames()->size(), 4U); - - ASSERT_TRUE(stack->frames()->at(0)->module); - ASSERT_EQ(stack->frames()->at(0)->module->base_address(), 0x400000U); - ASSERT_EQ(stack->frames()->at(0)->module->code_file(), "c:\\test_app.exe"); - ASSERT_EQ(stack->frames()->at(0)->function_name, - "`anonymous namespace'::CrashFunction"); - ASSERT_EQ(stack->frames()->at(0)->source_file_name, "c:\\test_app.cc"); - ASSERT_EQ(stack->frames()->at(0)->source_line, 58); - - ASSERT_TRUE(stack->frames()->at(1)->module); - ASSERT_EQ(stack->frames()->at(1)->module->base_address(), 0x400000U); - ASSERT_EQ(stack->frames()->at(1)->module->code_file(), "c:\\test_app.exe"); - ASSERT_EQ(stack->frames()->at(1)->function_name, "main"); - ASSERT_EQ(stack->frames()->at(1)->source_file_name, "c:\\test_app.cc"); - ASSERT_EQ(stack->frames()->at(1)->source_line, 65); - - // This comes from the CRT - ASSERT_TRUE(stack->frames()->at(2)->module); - ASSERT_EQ(stack->frames()->at(2)->module->base_address(), 0x400000U); - ASSERT_EQ(stack->frames()->at(2)->module->code_file(), "c:\\test_app.exe"); - ASSERT_EQ(stack->frames()->at(2)->function_name, "__tmainCRTStartup"); - ASSERT_EQ(stack->frames()->at(2)->source_file_name, - "f:\\sp\\vctools\\crt_bld\\self_x86\\crt\\src\\crt0.c"); - ASSERT_EQ(stack->frames()->at(2)->source_line, 327); - - // No debug info available for kernel32.dll - ASSERT_TRUE(stack->frames()->at(3)->module); - ASSERT_EQ(stack->frames()->at(3)->module->base_address(), 0x7c800000U); - ASSERT_EQ(stack->frames()->at(3)->module->code_file(), - "C:\\WINDOWS\\system32\\kernel32.dll"); - ASSERT_TRUE(stack->frames()->at(3)->function_name.empty()); - ASSERT_TRUE(stack->frames()->at(3)->source_file_name.empty()); - ASSERT_EQ(stack->frames()->at(3)->source_line, 0); - - ASSERT_EQ(state.modules()->module_count(), 13U); - ASSERT_TRUE(state.modules()->GetMainModule()); - ASSERT_EQ(state.modules()->GetMainModule()->code_file(), "c:\\test_app.exe"); - ASSERT_FALSE(state.modules()->GetModuleForAddress(0)); - ASSERT_EQ(state.modules()->GetMainModule(), - state.modules()->GetModuleForAddress(0x400000)); - ASSERT_EQ(state.modules()->GetModuleForAddress(0x7c801234)->debug_file(), - "kernel32.pdb"); - ASSERT_EQ(state.modules()->GetModuleForAddress(0x77d43210)->version(), - "5.1.2600.2622"); - - // Test that disabled exploitability engine defaults to - // EXPLOITABILITY_NOT_ANALYZED. - ASSERT_EQ(google_breakpad::EXPLOITABILITY_NOT_ANALYZED, - state.exploitability()); - - // Test that the symbol supplier can interrupt processing - state.Clear(); - supplier.set_interrupt(true); - ASSERT_EQ(processor.Process(minidump_file, &state), - google_breakpad::PROCESS_SYMBOL_SUPPLIER_INTERRUPTED); -} - -TEST_F(MinidumpProcessorTest, TestThreadMissingMemory) { - MockMinidump dump; - EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump")); - EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true)); - - MDRawHeader fake_header; - fake_header.time_date_stamp = 0; - EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header)); - - MDRawSystemInfo raw_system_info; - memset(&raw_system_info, 0, sizeof(raw_system_info)); - raw_system_info.processor_architecture = MD_CPU_ARCHITECTURE_X86; - raw_system_info.platform_id = MD_OS_WIN32_NT; - TestMinidumpSystemInfo dump_system_info(raw_system_info); - - EXPECT_CALL(dump, GetSystemInfo()). - WillRepeatedly(Return(&dump_system_info)); - - MockMinidumpThreadList thread_list; - EXPECT_CALL(dump, GetThreadList()). - WillOnce(Return(&thread_list)); - - MockMinidumpMemoryList memory_list; - EXPECT_CALL(dump, GetMemoryList()). - WillOnce(Return(&memory_list)); - - // Return a thread missing stack memory. - MockMinidumpThread no_memory_thread; - EXPECT_CALL(no_memory_thread, GetThreadID(_)). - WillRepeatedly(DoAll(SetArgumentPointee<0>(1), - Return(true))); - EXPECT_CALL(no_memory_thread, GetMemory()). - WillRepeatedly(Return(reinterpret_cast<MinidumpMemoryRegion*>(NULL))); - - const uint64_t kTestStartOfMemoryRange = 0x1234; - EXPECT_CALL(no_memory_thread, GetStartOfStackMemoryRange()). - WillRepeatedly(Return(kTestStartOfMemoryRange)); - EXPECT_CALL(memory_list, GetMemoryRegionForAddress(kTestStartOfMemoryRange)). - WillRepeatedly(Return(reinterpret_cast<MinidumpMemoryRegion*>(NULL))); - - MDRawContextX86 no_memory_thread_raw_context; - memset(&no_memory_thread_raw_context, 0, - sizeof(no_memory_thread_raw_context)); - no_memory_thread_raw_context.context_flags = MD_CONTEXT_X86_FULL; - const uint32_t kExpectedEIP = 0xabcd1234; - no_memory_thread_raw_context.eip = kExpectedEIP; - TestMinidumpContext no_memory_thread_context(no_memory_thread_raw_context); - EXPECT_CALL(no_memory_thread, GetContext()). - WillRepeatedly(Return(&no_memory_thread_context)); - - EXPECT_CALL(thread_list, thread_count()). - WillRepeatedly(Return(1)); - EXPECT_CALL(thread_list, GetThreadAtIndex(0)). - WillOnce(Return(&no_memory_thread)); - - MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL); - ProcessState state; - EXPECT_EQ(processor.Process(&dump, &state), - google_breakpad::PROCESS_OK); - - // Should have a single thread with a single frame in it. - ASSERT_EQ(1U, state.threads()->size()); - ASSERT_EQ(1U, state.threads()->at(0)->frames()->size()); - ASSERT_EQ(kExpectedEIP, state.threads()->at(0)->frames()->at(0)->instruction); -} - -TEST_F(MinidumpProcessorTest, GetProcessCreateTime) { - const uint32_t kProcessCreateTime = 2000; - const uint32_t kTimeDateStamp = 5000; - MockMinidump dump; - EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump")); - EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true)); - - // Set time of crash. - MDRawHeader fake_header; - fake_header.time_date_stamp = kTimeDateStamp; - EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header)); - - // Set process create time. - MDRawMiscInfo raw_misc_info; - memset(&raw_misc_info, 0, sizeof(raw_misc_info)); - raw_misc_info.process_create_time = kProcessCreateTime; - raw_misc_info.flags1 |= MD_MISCINFO_FLAGS1_PROCESS_TIMES; - google_breakpad::TestMinidumpMiscInfo dump_misc_info(raw_misc_info); - EXPECT_CALL(dump, GetMiscInfo()).WillRepeatedly(Return(&dump_misc_info)); - - // No threads - MockMinidumpThreadList thread_list; - EXPECT_CALL(dump, GetThreadList()).WillOnce(Return(&thread_list)); - EXPECT_CALL(thread_list, thread_count()).WillRepeatedly(Return(0)); - - MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL); - ProcessState state; - EXPECT_EQ(google_breakpad::PROCESS_OK, processor.Process(&dump, &state)); - - // Verify the time stamps. - ASSERT_EQ(kTimeDateStamp, state.time_date_stamp()); - ASSERT_EQ(kProcessCreateTime, state.process_create_time()); -} - -TEST_F(MinidumpProcessorTest, TestThreadMissingContext) { - MockMinidump dump; - EXPECT_CALL(dump, path()).WillRepeatedly(Return("mock minidump")); - EXPECT_CALL(dump, Read()).WillRepeatedly(Return(true)); - - MDRawHeader fake_header; - fake_header.time_date_stamp = 0; - EXPECT_CALL(dump, header()).WillRepeatedly(Return(&fake_header)); - - MDRawSystemInfo raw_system_info; - memset(&raw_system_info, 0, sizeof(raw_system_info)); - raw_system_info.processor_architecture = MD_CPU_ARCHITECTURE_X86; - raw_system_info.platform_id = MD_OS_WIN32_NT; - TestMinidumpSystemInfo dump_system_info(raw_system_info); - - EXPECT_CALL(dump, GetSystemInfo()). - WillRepeatedly(Return(&dump_system_info)); - - MockMinidumpThreadList thread_list; - EXPECT_CALL(dump, GetThreadList()). - WillOnce(Return(&thread_list)); - - MockMinidumpMemoryList memory_list; - EXPECT_CALL(dump, GetMemoryList()). - WillOnce(Return(&memory_list)); - - // Return a thread missing a thread context. - MockMinidumpThread no_context_thread; - EXPECT_CALL(no_context_thread, GetThreadID(_)). - WillRepeatedly(DoAll(SetArgumentPointee<0>(1), - Return(true))); - EXPECT_CALL(no_context_thread, GetContext()). - WillRepeatedly(Return(reinterpret_cast<MinidumpContext*>(NULL))); - - // The memory contents don't really matter here, since it won't be used. - MockMinidumpMemoryRegion no_context_thread_memory(0x1234, "xxx"); - EXPECT_CALL(no_context_thread, GetMemory()). - WillRepeatedly(Return(&no_context_thread_memory)); - EXPECT_CALL(no_context_thread, GetStartOfStackMemoryRange()). - Times(0); - EXPECT_CALL(memory_list, GetMemoryRegionForAddress(_)). - Times(0); - - EXPECT_CALL(thread_list, thread_count()). - WillRepeatedly(Return(1)); - EXPECT_CALL(thread_list, GetThreadAtIndex(0)). - WillOnce(Return(&no_context_thread)); - - MinidumpProcessor processor(reinterpret_cast<SymbolSupplier*>(NULL), NULL); - ProcessState state; - EXPECT_EQ(processor.Process(&dump, &state), - google_breakpad::PROCESS_OK); - - // Should have a single thread with zero frames. - ASSERT_EQ(1U, state.threads()->size()); - ASSERT_EQ(0U, state.threads()->at(0)->frames()->size()); -} - -} // namespace - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - return RUN_ALL_TESTS(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc deleted file mode 100644 index 8f83969fe..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk.cc +++ /dev/null @@ -1,162 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// minidump_stackwalk.cc: Process a minidump with MinidumpProcessor, printing -// the results, including stack traces. -// -// Author: Mark Mentovai - -#include <stdio.h> -#include <string.h> - -#include <string> -#include <vector> - -#include "common/scoped_ptr.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/minidump.h" -#include "google_breakpad/processor/minidump_processor.h" -#include "google_breakpad/processor/process_state.h" -#include "processor/logging.h" -#include "processor/simple_symbol_supplier.h" -#include "processor/stackwalk_common.h" - - -namespace { - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::Minidump; -using google_breakpad::MinidumpProcessor; -using google_breakpad::ProcessState; -using google_breakpad::SimpleSymbolSupplier; -using google_breakpad::scoped_ptr; - -// Processes |minidump_file| using MinidumpProcessor. |symbol_path|, if -// non-empty, is the base directory of a symbol storage area, laid out in -// the format required by SimpleSymbolSupplier. If such a storage area -// is specified, it is made available for use by the MinidumpProcessor. -// -// Returns the value of MinidumpProcessor::Process. If processing succeeds, -// prints identifying OS and CPU information from the minidump, crash -// information if the minidump was produced as a result of a crash, and -// call stacks for each thread contained in the minidump. All information -// is printed to stdout. -bool PrintMinidumpProcess(const string &minidump_file, - const std::vector<string> &symbol_paths, - bool machine_readable, - bool output_stack_contents) { - scoped_ptr<SimpleSymbolSupplier> symbol_supplier; - if (!symbol_paths.empty()) { - // TODO(mmentovai): check existence of symbol_path if specified? - symbol_supplier.reset(new SimpleSymbolSupplier(symbol_paths)); - } - - BasicSourceLineResolver resolver; - MinidumpProcessor minidump_processor(symbol_supplier.get(), &resolver); - - // Process the minidump. - Minidump dump(minidump_file); - if (!dump.Read()) { - BPLOG(ERROR) << "Minidump " << dump.path() << " could not be read"; - return false; - } - ProcessState process_state; - if (minidump_processor.Process(&dump, &process_state) != - google_breakpad::PROCESS_OK) { - BPLOG(ERROR) << "MinidumpProcessor::Process failed"; - return false; - } - - if (machine_readable) { - PrintProcessStateMachineReadable(process_state); - } else { - PrintProcessState(process_state, output_stack_contents, &resolver); - } - - return true; -} - -void usage(const char *program_name) { - fprintf(stderr, "usage: %s [-m|-s] <minidump-file> [symbol-path ...]\n" - " -m : Output in machine-readable format\n" - " -s : Output stack contents\n", - program_name); -} - -} // namespace - -int main(int argc, char **argv) { - BPLOG_INIT(&argc, &argv); - - if (argc < 2) { - usage(argv[0]); - return 1; - } - - const char *minidump_file; - bool machine_readable = false; - bool output_stack_contents = false; - int symbol_path_arg; - - if (strcmp(argv[1], "-m") == 0) { - if (argc < 3) { - usage(argv[0]); - return 1; - } - - machine_readable = true; - minidump_file = argv[2]; - symbol_path_arg = 3; - } else if (strcmp(argv[1], "-s") == 0) { - if (argc < 3) { - usage(argv[0]); - return 1; - } - - output_stack_contents = true; - minidump_file = argv[2]; - symbol_path_arg = 3; - } else { - minidump_file = argv[1]; - symbol_path_arg = 2; - } - - // extra arguments are symbol paths - std::vector<string> symbol_paths; - if (argc > symbol_path_arg) { - for (int argi = symbol_path_arg; argi < argc; ++argi) - symbol_paths.push_back(argv[argi]); - } - - return PrintMinidumpProcess(minidump_file, - symbol_paths, - machine_readable, - output_stack_contents) ? 0 : 1; -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_machine_readable_test b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_machine_readable_test deleted file mode 100755 index 2aadb2412..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_machine_readable_test +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2007, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -testdata_dir=$srcdir/src/processor/testdata -./src/processor/minidump_stackwalk -m $testdata_dir/minidump2.dmp \ - $testdata_dir/symbols | \ - tr -d '\015' | \ - diff -u $testdata_dir/minidump2.stackwalk.machine_readable.out - -exit $? diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_test b/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_test deleted file mode 100755 index f97902791..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_stackwalk_test +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2006, Google Inc. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -testdata_dir=$srcdir/src/processor/testdata -./src/processor/minidump_stackwalk $testdata_dir/minidump2.dmp \ - $testdata_dir/symbols | \ - tr -d '\015' | \ - diff -u $testdata_dir/minidump2.stackwalk.out - -exit $? diff --git a/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc deleted file mode 100644 index d29e9f4e5..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/minidump_unittest.cc +++ /dev/null @@ -1,1521 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Unit test for Minidump. Uses a pre-generated minidump and -// verifies that certain streams are correct. - -#include <iostream> -#include <fstream> -#include <sstream> -#include <stdlib.h> -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/minidump.h" -#include "processor/logging.h" -#include "processor/synth_minidump.h" - -namespace { - -using google_breakpad::Minidump; -using google_breakpad::MinidumpContext; -using google_breakpad::MinidumpException; -using google_breakpad::MinidumpMemoryInfo; -using google_breakpad::MinidumpMemoryInfoList; -using google_breakpad::MinidumpMemoryList; -using google_breakpad::MinidumpMemoryRegion; -using google_breakpad::MinidumpModule; -using google_breakpad::MinidumpModuleList; -using google_breakpad::MinidumpSystemInfo; -using google_breakpad::MinidumpThread; -using google_breakpad::MinidumpThreadList; -using google_breakpad::SynthMinidump::Context; -using google_breakpad::SynthMinidump::Dump; -using google_breakpad::SynthMinidump::Exception; -using google_breakpad::SynthMinidump::Memory; -using google_breakpad::SynthMinidump::Module; -using google_breakpad::SynthMinidump::Section; -using google_breakpad::SynthMinidump::Stream; -using google_breakpad::SynthMinidump::String; -using google_breakpad::SynthMinidump::SystemInfo; -using google_breakpad::SynthMinidump::Thread; -using google_breakpad::test_assembler::kBigEndian; -using google_breakpad::test_assembler::kLittleEndian; -using std::ifstream; -using std::istringstream; -using std::vector; -using ::testing::Return; - -class MinidumpTest : public ::testing::Test { -public: - void SetUp() { - minidump_file_ = string(getenv("srcdir") ? getenv("srcdir") : ".") + - "/src/processor/testdata/minidump2.dmp"; - } - string minidump_file_; -}; - -TEST_F(MinidumpTest, TestMinidumpFromFile) { - Minidump minidump(minidump_file_); - ASSERT_EQ(minidump.path(), minidump_file_); - ASSERT_TRUE(minidump.Read()); - const MDRawHeader* header = minidump.header(); - ASSERT_NE(header, (MDRawHeader*)NULL); - ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); - - MinidumpModuleList *md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); - const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); - ASSERT_EQ("c:\\test_app.exe", md_module->code_file()); - ASSERT_EQ("c:\\test_app.pdb", md_module->debug_file()); - ASSERT_EQ("45D35F6C2d000", md_module->code_identifier()); - ASSERT_EQ("5A9832E5287241C1838ED98914E9B7FF1", md_module->debug_identifier()); -} - -TEST_F(MinidumpTest, TestMinidumpFromStream) { - // read minidump contents into memory, construct a stringstream around them - ifstream file_stream(minidump_file_.c_str(), std::ios::in); - ASSERT_TRUE(file_stream.good()); - vector<char> bytes; - file_stream.seekg(0, std::ios_base::end); - ASSERT_TRUE(file_stream.good()); - bytes.resize(file_stream.tellg()); - file_stream.seekg(0, std::ios_base::beg); - ASSERT_TRUE(file_stream.good()); - file_stream.read(&bytes[0], bytes.size()); - ASSERT_TRUE(file_stream.good()); - string str(&bytes[0], bytes.size()); - istringstream stream(str); - ASSERT_TRUE(stream.good()); - - // now read minidump from stringstream - Minidump minidump(stream); - ASSERT_EQ(minidump.path(), ""); - ASSERT_TRUE(minidump.Read()); - const MDRawHeader* header = minidump.header(); - ASSERT_NE(header, (MDRawHeader*)NULL); - ASSERT_EQ(header->signature, uint32_t(MD_HEADER_SIGNATURE)); - //TODO: add more checks here -} - -TEST(Dump, ReadBackEmpty) { - Dump dump(0); - dump.Finish(); - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream stream(contents); - Minidump minidump(stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); -} - -TEST(Dump, ReadBackEmptyBigEndian) { - Dump big_minidump(0, kBigEndian); - big_minidump.Finish(); - string contents; - ASSERT_TRUE(big_minidump.GetContents(&contents)); - istringstream stream(contents); - Minidump minidump(stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(0U, minidump.GetDirectoryEntryCount()); -} - -TEST(Dump, OneStream) { - Dump dump(0, kBigEndian); - Stream stream(dump, 0xfbb7fa2bU); - stream.Append("stream contents"); - dump.Add(&stream); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); - ASSERT_TRUE(dir != NULL); - EXPECT_EQ(0xfbb7fa2bU, dir->stream_type); - - uint32_t stream_length; - ASSERT_TRUE(minidump.SeekToStreamType(0xfbb7fa2bU, &stream_length)); - ASSERT_EQ(15U, stream_length); - char stream_contents[15]; - ASSERT_TRUE(minidump.ReadBytes(stream_contents, sizeof(stream_contents))); - EXPECT_EQ(string("stream contents"), - string(stream_contents, sizeof(stream_contents))); - - EXPECT_FALSE(minidump.GetThreadList()); - EXPECT_FALSE(minidump.GetModuleList()); - EXPECT_FALSE(minidump.GetMemoryList()); - EXPECT_FALSE(minidump.GetException()); - EXPECT_FALSE(minidump.GetAssertion()); - EXPECT_FALSE(minidump.GetSystemInfo()); - EXPECT_FALSE(minidump.GetMiscInfo()); - EXPECT_FALSE(minidump.GetBreakpadInfo()); -} - -TEST(Dump, OneMemory) { - Dump dump(0, kBigEndian); - Memory memory(dump, 0x309d68010bd21b2cULL); - memory.Append("memory contents"); - dump.Add(&memory); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); - ASSERT_TRUE(dir != NULL); - EXPECT_EQ((uint32_t) MD_MEMORY_LIST_STREAM, dir->stream_type); - - MinidumpMemoryList *memory_list = minidump.GetMemoryList(); - ASSERT_TRUE(memory_list != NULL); - ASSERT_EQ(1U, memory_list->region_count()); - - MinidumpMemoryRegion *region1 = memory_list->GetMemoryRegionAtIndex(0); - ASSERT_EQ(0x309d68010bd21b2cULL, region1->GetBase()); - ASSERT_EQ(15U, region1->GetSize()); - const uint8_t *region1_bytes = region1->GetMemory(); - ASSERT_TRUE(memcmp("memory contents", region1_bytes, 15) == 0); -} - -// One thread --- and its requisite entourage. -TEST(Dump, OneThread) { - Dump dump(0, kLittleEndian); - Memory stack(dump, 0x2326a0fa); - stack.Append("stack for thread"); - - MDRawContextX86 raw_context; - const uint32_t kExpectedEIP = 0x6913f540; - raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; - raw_context.edi = 0x3ecba80d; - raw_context.esi = 0x382583b9; - raw_context.ebx = 0x7fccc03f; - raw_context.edx = 0xf62f8ec2; - raw_context.ecx = 0x46a6a6a8; - raw_context.eax = 0x6a5025e2; - raw_context.ebp = 0xd9fabb4a; - raw_context.eip = kExpectedEIP; - raw_context.cs = 0xbffe6eda; - raw_context.eflags = 0xb2ce1e2d; - raw_context.esp = 0x659caaa4; - raw_context.ss = 0x2e951ef7; - Context context(dump, raw_context); - - Thread thread(dump, 0xa898f11b, stack, context, - 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); - - dump.Add(&stack); - dump.Add(&context); - dump.Add(&thread); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); - - MinidumpMemoryList *md_memory_list = minidump.GetMemoryList(); - ASSERT_TRUE(md_memory_list != NULL); - ASSERT_EQ(1U, md_memory_list->region_count()); - - MinidumpMemoryRegion *md_region = md_memory_list->GetMemoryRegionAtIndex(0); - ASSERT_EQ(0x2326a0faU, md_region->GetBase()); - ASSERT_EQ(16U, md_region->GetSize()); - const uint8_t *region_bytes = md_region->GetMemory(); - ASSERT_TRUE(memcmp("stack for thread", region_bytes, 16) == 0); - - MinidumpThreadList *thread_list = minidump.GetThreadList(); - ASSERT_TRUE(thread_list != NULL); - ASSERT_EQ(1U, thread_list->thread_count()); - - MinidumpThread *md_thread = thread_list->GetThreadAtIndex(0); - ASSERT_TRUE(md_thread != NULL); - uint32_t thread_id; - ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); - ASSERT_EQ(0xa898f11bU, thread_id); - MinidumpMemoryRegion *md_stack = md_thread->GetMemory(); - ASSERT_TRUE(md_stack != NULL); - ASSERT_EQ(0x2326a0faU, md_stack->GetBase()); - ASSERT_EQ(16U, md_stack->GetSize()); - const uint8_t *md_stack_bytes = md_stack->GetMemory(); - ASSERT_TRUE(memcmp("stack for thread", md_stack_bytes, 16) == 0); - - MinidumpContext *md_context = md_thread->GetContext(); - ASSERT_TRUE(md_context != NULL); - ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); - - uint64_t eip; - ASSERT_TRUE(md_context->GetInstructionPointer(&eip)); - EXPECT_EQ(kExpectedEIP, eip); - - const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); - ASSERT_TRUE(md_raw_context != NULL); - ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), - (md_raw_context->context_flags - & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); - EXPECT_EQ(0x3ecba80dU, raw_context.edi); - EXPECT_EQ(0x382583b9U, raw_context.esi); - EXPECT_EQ(0x7fccc03fU, raw_context.ebx); - EXPECT_EQ(0xf62f8ec2U, raw_context.edx); - EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); - EXPECT_EQ(0x6a5025e2U, raw_context.eax); - EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); - EXPECT_EQ(kExpectedEIP, raw_context.eip); - EXPECT_EQ(0xbffe6edaU, raw_context.cs); - EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); - EXPECT_EQ(0x659caaa4U, raw_context.esp); - EXPECT_EQ(0x2e951ef7U, raw_context.ss); -} - -TEST(Dump, ThreadMissingMemory) { - Dump dump(0, kLittleEndian); - Memory stack(dump, 0x2326a0fa); - // Stack has no contents. - - MDRawContextX86 raw_context; - memset(&raw_context, 0, sizeof(raw_context)); - raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; - Context context(dump, raw_context); - - Thread thread(dump, 0xa898f11b, stack, context, - 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); - - dump.Add(&stack); - dump.Add(&context); - dump.Add(&thread); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); - - // This should succeed even though the thread has no stack memory. - MinidumpThreadList* thread_list = minidump.GetThreadList(); - ASSERT_TRUE(thread_list != NULL); - ASSERT_EQ(1U, thread_list->thread_count()); - - MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); - ASSERT_TRUE(md_thread != NULL); - - uint32_t thread_id; - ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); - ASSERT_EQ(0xa898f11bU, thread_id); - - MinidumpContext* md_context = md_thread->GetContext(); - ASSERT_NE(reinterpret_cast<MinidumpContext*>(NULL), md_context); - - MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); - ASSERT_EQ(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack); -} - -TEST(Dump, ThreadMissingContext) { - Dump dump(0, kLittleEndian); - Memory stack(dump, 0x2326a0fa); - stack.Append("stack for thread"); - - // Context is empty. - Context context(dump); - - Thread thread(dump, 0xa898f11b, stack, context, - 0x9e39439f, 0x4abfc15f, 0xe499898a, 0x0d43e939dcfd0372ULL); - - dump.Add(&stack); - dump.Add(&context); - dump.Add(&thread); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); - - // This should succeed even though the thread has no stack memory. - MinidumpThreadList* thread_list = minidump.GetThreadList(); - ASSERT_TRUE(thread_list != NULL); - ASSERT_EQ(1U, thread_list->thread_count()); - - MinidumpThread* md_thread = thread_list->GetThreadAtIndex(0); - ASSERT_TRUE(md_thread != NULL); - - uint32_t thread_id; - ASSERT_TRUE(md_thread->GetThreadID(&thread_id)); - ASSERT_EQ(0xa898f11bU, thread_id); - MinidumpMemoryRegion* md_stack = md_thread->GetMemory(); - ASSERT_NE(reinterpret_cast<MinidumpMemoryRegion*>(NULL), md_stack); - - MinidumpContext* md_context = md_thread->GetContext(); - ASSERT_EQ(reinterpret_cast<MinidumpContext*>(NULL), md_context); -} - -static const MDVSFixedFileInfo fixed_file_info = { - 0xb2fba33a, // signature - 0x33d7a728, // struct_version - 0x31afcb20, // file_version_hi - 0xe51cdab1, // file_version_lo - 0xd1ea6907, // product_version_hi - 0x03032857, // product_version_lo - 0x11bf71d7, // file_flags_mask - 0x5fb8cdbf, // file_flags - 0xe45d0d5d, // file_os - 0x107d9562, // file_type - 0x5a8844d4, // file_subtype - 0xa8d30b20, // file_date_hi - 0x651c3e4e // file_date_lo -}; - -TEST(Dump, OneModule) { - Dump dump(0, kBigEndian); - String module_name(dump, "single module"); - Section cv_info(dump); - cv_info - .D32(MD_CVINFOPDB70_SIGNATURE) // signature - // signature, a MDGUID - .D32(0xabcd1234) - .D16(0xf00d) - .D16(0xbeef) - .Append("\x01\x02\x03\x04\x05\x06\x07\x08") - .D32(1) // age - .AppendCString("c:\\foo\\file.pdb"); // pdb_file_name - - String csd_version(dump, "Windows 9000"); - SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); - - Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, - module_name, - 0xb1054d2a, - 0x34571371, - fixed_file_info, // from synth_minidump_unittest_data.h - &cv_info, nullptr); - - dump.Add(&module); - dump.Add(&module_name); - dump.Add(&cv_info); - dump.Add(&system_info); - dump.Add(&csd_version); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); - - const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(1); - ASSERT_TRUE(dir != NULL); - EXPECT_EQ((uint32_t) MD_MODULE_LIST_STREAM, dir->stream_type); - - MinidumpModuleList *md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); - ASSERT_EQ(1U, md_module_list->module_count()); - - const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); - ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); - ASSERT_EQ(0xada542bd, md_module->size()); - ASSERT_EQ("single module", md_module->code_file()); - ASSERT_EQ("c:\\foo\\file.pdb", md_module->debug_file()); - // time_date_stamp and size_of_image concatenated - ASSERT_EQ("B1054D2Aada542bd", md_module->code_identifier()); - ASSERT_EQ("ABCD1234F00DBEEF01020304050607081", md_module->debug_identifier()); - - const MDRawModule *md_raw_module = md_module->module(); - ASSERT_TRUE(md_raw_module != NULL); - ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); - ASSERT_EQ(0x34571371U, md_raw_module->checksum); - ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, - sizeof(fixed_file_info)) == 0); -} - -// Test that a module with a MDCVInfoELF CV record is handled properly. -TEST(Dump, OneModuleCVELF) { - Dump dump(0, kLittleEndian); - String module_name(dump, "elf module"); - Section cv_info(dump); - cv_info - .D32(MD_CVINFOELF_SIGNATURE) // signature - // build_id - .Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf" - "\x37\x38\xce\xa3\x4a\x87"); - - const MDRawSystemInfo linux_x86 = { - MD_CPU_ARCHITECTURE_X86, // processor_architecture - 6, // processor_level - 0xd08, // processor_revision - 1, // number_of_processors - 0, // product_type - 0, // major_version - 0, // minor_version - 0, // build_number - MD_OS_LINUX, // platform_id - 0xdeadbeef, // csd_version_rva - 0x100, // suite_mask - 0, // reserved2 - { // cpu - { // x86_cpu_info - { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id - 0x6d8, // version_information - 0xafe9fbff, // feature_information - 0xffffffff // amd_extended_cpu_features - } - } - }; - String csd_version(dump, "Literally Linux"); - SystemInfo system_info(dump, linux_x86, csd_version); - - Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, - module_name, - 0xb1054d2a, - 0x34571371, - fixed_file_info, // from synth_minidump_unittest_data.h - &cv_info, nullptr); - - dump.Add(&module); - dump.Add(&module_name); - dump.Add(&cv_info); - dump.Add(&system_info); - dump.Add(&csd_version); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - - MinidumpModuleList *md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); - ASSERT_EQ(1U, md_module_list->module_count()); - - const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); - ASSERT_EQ(0xa90206ca83eb2852ULL, md_module->base_address()); - ASSERT_EQ(0xada542bd, md_module->size()); - ASSERT_EQ("elf module", md_module->code_file()); - // debug_file == code_file - ASSERT_EQ("elf module", md_module->debug_file()); - // just the build_id, directly - ASSERT_EQ("5fa9cdb41053df1b86fab733b4df3738cea34a87", - md_module->code_identifier()); - // build_id truncted to GUID length and treated as such, with zero - // age appended - ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier()); - - const MDRawModule *md_raw_module = md_module->module(); - ASSERT_TRUE(md_raw_module != NULL); - ASSERT_EQ(0xb1054d2aU, md_raw_module->time_date_stamp); - ASSERT_EQ(0x34571371U, md_raw_module->checksum); - ASSERT_TRUE(memcmp(&md_raw_module->version_info, &fixed_file_info, - sizeof(fixed_file_info)) == 0); -} - -// Test that a build_id that's shorter than a GUID is handled properly. -TEST(Dump, CVELFShort) { - Dump dump(0, kLittleEndian); - String module_name(dump, "elf module"); - Section cv_info(dump); - cv_info - .D32(MD_CVINFOELF_SIGNATURE) // signature - // build_id, shorter than a GUID - .Append("\x5f\xa9\xcd\xb4"); - - const MDRawSystemInfo linux_x86 = { - MD_CPU_ARCHITECTURE_X86, // processor_architecture - 6, // processor_level - 0xd08, // processor_revision - 1, // number_of_processors - 0, // product_type - 0, // major_version - 0, // minor_version - 0, // build_number - MD_OS_LINUX, // platform_id - 0xdeadbeef, // csd_version_rva - 0x100, // suite_mask - 0, // reserved2 - { // cpu - { // x86_cpu_info - { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id - 0x6d8, // version_information - 0xafe9fbff, // feature_information - 0xffffffff // amd_extended_cpu_features - } - } - }; - String csd_version(dump, "Literally Linux"); - SystemInfo system_info(dump, linux_x86, csd_version); - - Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, - module_name, - 0xb1054d2a, - 0x34571371, - fixed_file_info, // from synth_minidump_unittest_data.h - &cv_info, nullptr); - - dump.Add(&module); - dump.Add(&module_name); - dump.Add(&cv_info); - dump.Add(&system_info); - dump.Add(&csd_version); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); - - MinidumpModuleList *md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); - ASSERT_EQ(1U, md_module_list->module_count()); - - const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); - // just the build_id, directly - ASSERT_EQ("5fa9cdb4", md_module->code_identifier()); - // build_id expanded to GUID length and treated as such, with zero - // age appended - ASSERT_EQ("B4CDA95F0000000000000000000000000", md_module->debug_identifier()); -} - -// Test that a build_id that's very long is handled properly. -TEST(Dump, CVELFLong) { - Dump dump(0, kLittleEndian); - String module_name(dump, "elf module"); - Section cv_info(dump); - cv_info - .D32(MD_CVINFOELF_SIGNATURE) // signature - // build_id, lots of bytes - .Append("\x5f\xa9\xcd\xb4\x10\x53\xdf\x1b\x86\xfa\xb7\x33\xb4\xdf" - "\x37\x38\xce\xa3\x4a\x87\x01\x02\x03\x04\x05\x06\x07\x08" - "\x09\x0a\x0b\x0c\x0d\x0e\x0f"); - - - const MDRawSystemInfo linux_x86 = { - MD_CPU_ARCHITECTURE_X86, // processor_architecture - 6, // processor_level - 0xd08, // processor_revision - 1, // number_of_processors - 0, // product_type - 0, // major_version - 0, // minor_version - 0, // build_number - MD_OS_LINUX, // platform_id - 0xdeadbeef, // csd_version_rva - 0x100, // suite_mask - 0, // reserved2 - { // cpu - { // x86_cpu_info - { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id - 0x6d8, // version_information - 0xafe9fbff, // feature_information - 0xffffffff // amd_extended_cpu_features - } - } - }; - String csd_version(dump, "Literally Linux"); - SystemInfo system_info(dump, linux_x86, csd_version); - - Module module(dump, 0xa90206ca83eb2852ULL, 0xada542bd, - module_name, - 0xb1054d2a, - 0x34571371, - fixed_file_info, // from synth_minidump_unittest_data.h - &cv_info, nullptr); - - dump.Add(&module); - dump.Add(&module_name); - dump.Add(&cv_info); - dump.Add(&system_info); - dump.Add(&csd_version); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); - - MinidumpModuleList *md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); - ASSERT_EQ(1U, md_module_list->module_count()); - - const MinidumpModule *md_module = md_module_list->GetModuleAtIndex(0); - ASSERT_TRUE(md_module != NULL); - // just the build_id, directly - ASSERT_EQ( - "5fa9cdb41053df1b86fab733b4df3738cea34a870102030405060708090a0b0c0d0e0f", - md_module->code_identifier()); - // build_id truncated to GUID length and treated as such, with zero - // age appended. - ASSERT_EQ("B4CDA95F53101BDF86FAB733B4DF37380", md_module->debug_identifier()); -} - -TEST(Dump, OneSystemInfo) { - Dump dump(0, kLittleEndian); - String csd_version(dump, "Petulant Pierogi"); - SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); - - dump.Add(&system_info); - dump.Add(&csd_version); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); - ASSERT_TRUE(dir != NULL); - EXPECT_EQ((uint32_t) MD_SYSTEM_INFO_STREAM, dir->stream_type); - - MinidumpSystemInfo *md_system_info = minidump.GetSystemInfo(); - ASSERT_TRUE(md_system_info != NULL); - ASSERT_EQ("windows", md_system_info->GetOS()); - ASSERT_EQ("x86", md_system_info->GetCPU()); - ASSERT_EQ("Petulant Pierogi", *md_system_info->GetCSDVersion()); - ASSERT_EQ("GenuineIntel", *md_system_info->GetCPUVendor()); -} - -TEST(Dump, BigDump) { - Dump dump(0, kLittleEndian); - - // A SystemInfo stream. - String csd_version(dump, "Munificent Macaque"); - SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); - dump.Add(&csd_version); - dump.Add(&system_info); - - // Five threads! - Memory stack0(dump, 0x70b9ebfc); - stack0.Append("stack for thread zero"); - MDRawContextX86 raw_context0; - raw_context0.context_flags = MD_CONTEXT_X86_INTEGER; - raw_context0.eip = 0xaf0709e4; - Context context0(dump, raw_context0); - Thread thread0(dump, 0xbbef4432, stack0, context0, - 0xd0377e7b, 0xdb8eb0cf, 0xd73bc314, 0x09d357bac7f9a163ULL); - dump.Add(&stack0); - dump.Add(&context0); - dump.Add(&thread0); - - Memory stack1(dump, 0xf988cc45); - stack1.Append("stack for thread one"); - MDRawContextX86 raw_context1; - raw_context1.context_flags = MD_CONTEXT_X86_INTEGER; - raw_context1.eip = 0xe4f56f81; - Context context1(dump, raw_context1); - Thread thread1(dump, 0x657c3f58, stack1, context1, - 0xa68fa182, 0x6f3cf8dd, 0xe3a78ccf, 0x78cc84775e4534bbULL); - dump.Add(&stack1); - dump.Add(&context1); - dump.Add(&thread1); - - Memory stack2(dump, 0xc8a92e7c); - stack2.Append("stack for thread two"); - MDRawContextX86 raw_context2; - raw_context2.context_flags = MD_CONTEXT_X86_INTEGER; - raw_context2.eip = 0xb336a438; - Context context2(dump, raw_context2); - Thread thread2(dump, 0xdf4b8a71, stack2, context2, - 0x674c26b6, 0x445d7120, 0x7e700c56, 0xd89bf778e7793e17ULL); - dump.Add(&stack2); - dump.Add(&context2); - dump.Add(&thread2); - - Memory stack3(dump, 0x36d08e08); - stack3.Append("stack for thread three"); - MDRawContextX86 raw_context3; - raw_context3.context_flags = MD_CONTEXT_X86_INTEGER; - raw_context3.eip = 0xdf99a60c; - Context context3(dump, raw_context3); - Thread thread3(dump, 0x86e6c341, stack3, context3, - 0x32dc5c55, 0x17a2aba8, 0xe0cc75e7, 0xa46393994dae83aeULL); - dump.Add(&stack3); - dump.Add(&context3); - dump.Add(&thread3); - - Memory stack4(dump, 0x1e0ab4fa); - stack4.Append("stack for thread four"); - MDRawContextX86 raw_context4; - raw_context4.context_flags = MD_CONTEXT_X86_INTEGER; - raw_context4.eip = 0xaa646267; - Context context4(dump, raw_context4); - Thread thread4(dump, 0x261a28d4, stack4, context4, - 0x6ebd389e, 0xa0cd4759, 0x30168846, 0x164f650a0cf39d35ULL); - dump.Add(&stack4); - dump.Add(&context4); - dump.Add(&thread4); - - // Three modules! - String module1_name(dump, "module one"); - Module module1(dump, 0xeb77da57b5d4cbdaULL, 0x83cd5a37, module1_name); - dump.Add(&module1_name); - dump.Add(&module1); - - String module2_name(dump, "module two"); - Module module2(dump, 0x8675884adfe5ac90ULL, 0xb11e4ea3, module2_name); - dump.Add(&module2_name); - dump.Add(&module2); - - String module3_name(dump, "module three"); - Module module3(dump, 0x95fc1544da321b6cULL, 0x7c2bf081, module3_name); - dump.Add(&module3_name); - dump.Add(&module3); - - // Add one more memory region, on top of the five stacks. - Memory memory5(dump, 0x61979e828040e564ULL); - memory5.Append("contents of memory 5"); - dump.Add(&memory5); - - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(4U, minidump.GetDirectoryEntryCount()); - - // Check the threads. - MinidumpThreadList *thread_list = minidump.GetThreadList(); - ASSERT_TRUE(thread_list != NULL); - ASSERT_EQ(5U, thread_list->thread_count()); - uint32_t thread_id; - ASSERT_TRUE(thread_list->GetThreadAtIndex(0)->GetThreadID(&thread_id)); - ASSERT_EQ(0xbbef4432U, thread_id); - ASSERT_EQ(0x70b9ebfcU, - thread_list->GetThreadAtIndex(0)->GetMemory()->GetBase()); - ASSERT_EQ(0xaf0709e4U, - thread_list->GetThreadAtIndex(0)->GetContext()->GetContextX86() - ->eip); - - ASSERT_TRUE(thread_list->GetThreadAtIndex(1)->GetThreadID(&thread_id)); - ASSERT_EQ(0x657c3f58U, thread_id); - ASSERT_EQ(0xf988cc45U, - thread_list->GetThreadAtIndex(1)->GetMemory()->GetBase()); - ASSERT_EQ(0xe4f56f81U, - thread_list->GetThreadAtIndex(1)->GetContext()->GetContextX86() - ->eip); - - ASSERT_TRUE(thread_list->GetThreadAtIndex(2)->GetThreadID(&thread_id)); - ASSERT_EQ(0xdf4b8a71U, thread_id); - ASSERT_EQ(0xc8a92e7cU, - thread_list->GetThreadAtIndex(2)->GetMemory()->GetBase()); - ASSERT_EQ(0xb336a438U, - thread_list->GetThreadAtIndex(2)->GetContext()->GetContextX86() - ->eip); - - ASSERT_TRUE(thread_list->GetThreadAtIndex(3)->GetThreadID(&thread_id)); - ASSERT_EQ(0x86e6c341U, thread_id); - ASSERT_EQ(0x36d08e08U, - thread_list->GetThreadAtIndex(3)->GetMemory()->GetBase()); - ASSERT_EQ(0xdf99a60cU, - thread_list->GetThreadAtIndex(3)->GetContext()->GetContextX86() - ->eip); - - ASSERT_TRUE(thread_list->GetThreadAtIndex(4)->GetThreadID(&thread_id)); - ASSERT_EQ(0x261a28d4U, thread_id); - ASSERT_EQ(0x1e0ab4faU, - thread_list->GetThreadAtIndex(4)->GetMemory()->GetBase()); - ASSERT_EQ(0xaa646267U, - thread_list->GetThreadAtIndex(4)->GetContext()->GetContextX86() - ->eip); - - // Check the modules. - MinidumpModuleList *md_module_list = minidump.GetModuleList(); - ASSERT_TRUE(md_module_list != NULL); - ASSERT_EQ(3U, md_module_list->module_count()); - EXPECT_EQ(0xeb77da57b5d4cbdaULL, - md_module_list->GetModuleAtIndex(0)->base_address()); - EXPECT_EQ(0x8675884adfe5ac90ULL, - md_module_list->GetModuleAtIndex(1)->base_address()); - EXPECT_EQ(0x95fc1544da321b6cULL, - md_module_list->GetModuleAtIndex(2)->base_address()); -} - -TEST(Dump, OneMemoryInfo) { - Dump dump(0, kBigEndian); - Stream stream(dump, MD_MEMORY_INFO_LIST_STREAM); - - // Add the MDRawMemoryInfoList header. - const uint64_t kNumberOfEntries = 1; - stream.D32(sizeof(MDRawMemoryInfoList)) // size_of_header - .D32(sizeof(MDRawMemoryInfo)) // size_of_entry - .D64(kNumberOfEntries); // number_of_entries - - - // Now add a MDRawMemoryInfo entry. - const uint64_t kBaseAddress = 0x1000; - const uint64_t kRegionSize = 0x2000; - stream.D64(kBaseAddress) // base_address - .D64(kBaseAddress) // allocation_base - .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // allocation_protection - .D32(0) // __alignment1 - .D64(kRegionSize) // region_size - .D32(MD_MEMORY_STATE_COMMIT) // state - .D32(MD_MEMORY_PROTECT_EXECUTE_READWRITE) // protection - .D32(MD_MEMORY_TYPE_PRIVATE) // type - .D32(0); // __alignment2 - - dump.Add(&stream); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - const MDRawDirectory *dir = minidump.GetDirectoryEntryAtIndex(0); - ASSERT_TRUE(dir != NULL); - EXPECT_EQ((uint32_t) MD_MEMORY_INFO_LIST_STREAM, dir->stream_type); - - MinidumpMemoryInfoList *info_list = minidump.GetMemoryInfoList(); - ASSERT_TRUE(info_list != NULL); - ASSERT_EQ(1U, info_list->info_count()); - - const MinidumpMemoryInfo *info1 = info_list->GetMemoryInfoAtIndex(0); - ASSERT_EQ(kBaseAddress, info1->GetBase()); - ASSERT_EQ(kRegionSize, info1->GetSize()); - ASSERT_TRUE(info1->IsExecutable()); - ASSERT_TRUE(info1->IsWritable()); - - // Should get back the same memory region here. - const MinidumpMemoryInfo *info2 = - info_list->GetMemoryInfoForAddress(kBaseAddress + kRegionSize / 2); - ASSERT_EQ(kBaseAddress, info2->GetBase()); - ASSERT_EQ(kRegionSize, info2->GetSize()); -} - -TEST(Dump, OneExceptionX86) { - Dump dump(0, kLittleEndian); - - MDRawContextX86 raw_context; - raw_context.context_flags = MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL; - raw_context.edi = 0x3ecba80d; - raw_context.esi = 0x382583b9; - raw_context.ebx = 0x7fccc03f; - raw_context.edx = 0xf62f8ec2; - raw_context.ecx = 0x46a6a6a8; - raw_context.eax = 0x6a5025e2; - raw_context.ebp = 0xd9fabb4a; - raw_context.eip = 0x6913f540; - raw_context.cs = 0xbffe6eda; - raw_context.eflags = 0xb2ce1e2d; - raw_context.esp = 0x659caaa4; - raw_context.ss = 0x2e951ef7; - Context context(dump, raw_context); - - Exception exception(dump, context, - 0x1234abcd, // thread id - 0xdcba4321, // exception code - 0xf0e0d0c0, // exception flags - 0x0919a9b9c9d9e9f9ULL); // exception address - - dump.Add(&context); - dump.Add(&exception); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - MinidumpException *md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); - - uint32_t thread_id; - ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); - ASSERT_EQ(0x1234abcdU, thread_id); - - const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); - EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); - EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); - EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, - raw_exception->exception_record.exception_address); - - MinidumpContext *md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); - ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); - const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); - ASSERT_TRUE(md_raw_context != NULL); - ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), - (md_raw_context->context_flags - & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); - EXPECT_EQ(0x3ecba80dU, raw_context.edi); - EXPECT_EQ(0x382583b9U, raw_context.esi); - EXPECT_EQ(0x7fccc03fU, raw_context.ebx); - EXPECT_EQ(0xf62f8ec2U, raw_context.edx); - EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); - EXPECT_EQ(0x6a5025e2U, raw_context.eax); - EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); - EXPECT_EQ(0x6913f540U, raw_context.eip); - EXPECT_EQ(0xbffe6edaU, raw_context.cs); - EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); - EXPECT_EQ(0x659caaa4U, raw_context.esp); - EXPECT_EQ(0x2e951ef7U, raw_context.ss); -} - -TEST(Dump, OneExceptionX86XState) { - Dump dump(0, kLittleEndian); - - MDRawContextX86 raw_context; - raw_context.context_flags = MD_CONTEXT_X86_INTEGER | - MD_CONTEXT_X86_CONTROL | MD_CONTEXT_X86_XSTATE; - raw_context.edi = 0x3ecba80d; - raw_context.esi = 0x382583b9; - raw_context.ebx = 0x7fccc03f; - raw_context.edx = 0xf62f8ec2; - raw_context.ecx = 0x46a6a6a8; - raw_context.eax = 0x6a5025e2; - raw_context.ebp = 0xd9fabb4a; - raw_context.eip = 0x6913f540; - raw_context.cs = 0xbffe6eda; - raw_context.eflags = 0xb2ce1e2d; - raw_context.esp = 0x659caaa4; - raw_context.ss = 0x2e951ef7; - Context context(dump, raw_context); - - Exception exception(dump, context, - 0x1234abcd, // thread id - 0xdcba4321, // exception code - 0xf0e0d0c0, // exception flags - 0x0919a9b9c9d9e9f9ULL); // exception address - - dump.Add(&context); - dump.Add(&exception); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - MinidumpException *md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); - - uint32_t thread_id; - ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); - ASSERT_EQ(0x1234abcdU, thread_id); - - const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); - EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); - EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); - EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, - raw_exception->exception_record.exception_address); - - MinidumpContext *md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); - ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); - const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); - ASSERT_TRUE(md_raw_context != NULL); - ASSERT_EQ((uint32_t) (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL), - (md_raw_context->context_flags - & (MD_CONTEXT_X86_INTEGER | MD_CONTEXT_X86_CONTROL))); - EXPECT_EQ(0x3ecba80dU, raw_context.edi); - EXPECT_EQ(0x382583b9U, raw_context.esi); - EXPECT_EQ(0x7fccc03fU, raw_context.ebx); - EXPECT_EQ(0xf62f8ec2U, raw_context.edx); - EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); - EXPECT_EQ(0x6a5025e2U, raw_context.eax); - EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); - EXPECT_EQ(0x6913f540U, raw_context.eip); - EXPECT_EQ(0xbffe6edaU, raw_context.cs); - EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); - EXPECT_EQ(0x659caaa4U, raw_context.esp); - EXPECT_EQ(0x2e951ef7U, raw_context.ss); -} - -// Testing that the CPU type can be loaded from a system info stream when -// the CPU flags are missing from the context_flags of an exception record -TEST(Dump, OneExceptionX86NoCPUFlags) { - Dump dump(0, kLittleEndian); - - MDRawContextX86 raw_context; - // Intentionally not setting CPU type in the context_flags - raw_context.context_flags = 0; - raw_context.edi = 0x3ecba80d; - raw_context.esi = 0x382583b9; - raw_context.ebx = 0x7fccc03f; - raw_context.edx = 0xf62f8ec2; - raw_context.ecx = 0x46a6a6a8; - raw_context.eax = 0x6a5025e2; - raw_context.ebp = 0xd9fabb4a; - raw_context.eip = 0x6913f540; - raw_context.cs = 0xbffe6eda; - raw_context.eflags = 0xb2ce1e2d; - raw_context.esp = 0x659caaa4; - raw_context.ss = 0x2e951ef7; - Context context(dump, raw_context); - - Exception exception(dump, context, - 0x1234abcd, // thread id - 0xdcba4321, // exception code - 0xf0e0d0c0, // exception flags - 0x0919a9b9c9d9e9f9ULL); // exception address - - dump.Add(&context); - dump.Add(&exception); - - // Add system info. This is needed as an alternative source for CPU type - // information. Note, that the CPU flags were intentionally skipped from - // the context_flags and this alternative source is required. - String csd_version(dump, "Service Pack 2"); - SystemInfo system_info(dump, SystemInfo::windows_x86, csd_version); - dump.Add(&system_info); - dump.Add(&csd_version); - - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(2U, minidump.GetDirectoryEntryCount()); - - MinidumpException *md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); - - uint32_t thread_id; - ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); - ASSERT_EQ(0x1234abcdU, thread_id); - - const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); - EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); - EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); - EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, - raw_exception->exception_record.exception_address); - - MinidumpContext *md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); - - ASSERT_EQ((uint32_t) MD_CONTEXT_X86, md_context->GetContextCPU()); - const MDRawContextX86 *md_raw_context = md_context->GetContextX86(); - ASSERT_TRUE(md_raw_context != NULL); - - // Even though the CPU flags were missing from the context_flags, the - // GetContext call above is expected to load the missing CPU flags from the - // system info stream and set the CPU type bits in context_flags. - ASSERT_EQ((uint32_t) (MD_CONTEXT_X86), md_raw_context->context_flags); - - EXPECT_EQ(0x3ecba80dU, raw_context.edi); - EXPECT_EQ(0x382583b9U, raw_context.esi); - EXPECT_EQ(0x7fccc03fU, raw_context.ebx); - EXPECT_EQ(0xf62f8ec2U, raw_context.edx); - EXPECT_EQ(0x46a6a6a8U, raw_context.ecx); - EXPECT_EQ(0x6a5025e2U, raw_context.eax); - EXPECT_EQ(0xd9fabb4aU, raw_context.ebp); - EXPECT_EQ(0x6913f540U, raw_context.eip); - EXPECT_EQ(0xbffe6edaU, raw_context.cs); - EXPECT_EQ(0xb2ce1e2dU, raw_context.eflags); - EXPECT_EQ(0x659caaa4U, raw_context.esp); - EXPECT_EQ(0x2e951ef7U, raw_context.ss); -} - -// This test covers a scenario where a dump contains an exception but the -// context record of the exception is missing the CPU type information in its -// context_flags. The dump has no system info stream so it is imposible to -// deduce the CPU type, hence the context record is unusable. -TEST(Dump, OneExceptionX86NoCPUFlagsNoSystemInfo) { - Dump dump(0, kLittleEndian); - - MDRawContextX86 raw_context; - // Intentionally not setting CPU type in the context_flags - raw_context.context_flags = 0; - raw_context.edi = 0x3ecba80d; - raw_context.esi = 0x382583b9; - raw_context.ebx = 0x7fccc03f; - raw_context.edx = 0xf62f8ec2; - raw_context.ecx = 0x46a6a6a8; - raw_context.eax = 0x6a5025e2; - raw_context.ebp = 0xd9fabb4a; - raw_context.eip = 0x6913f540; - raw_context.cs = 0xbffe6eda; - raw_context.eflags = 0xb2ce1e2d; - raw_context.esp = 0x659caaa4; - raw_context.ss = 0x2e951ef7; - Context context(dump, raw_context); - - Exception exception(dump, context, - 0x1234abcd, // thread id - 0xdcba4321, // exception code - 0xf0e0d0c0, // exception flags - 0x0919a9b9c9d9e9f9ULL); // exception address - - dump.Add(&context); - dump.Add(&exception); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - MinidumpException *md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); - - uint32_t thread_id; - ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); - ASSERT_EQ(0x1234abcdU, thread_id); - - const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); - EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); - EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); - EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, - raw_exception->exception_record.exception_address); - - // The context record of the exception is unusable because the context_flags - // don't have CPU type information and at the same time the minidump lacks - // system info stream so it is impossible to deduce the CPU type. - MinidumpContext *md_context = md_exception->GetContext(); - ASSERT_EQ(NULL, md_context); -} - -TEST(Dump, OneExceptionARM) { - Dump dump(0, kLittleEndian); - - MDRawContextARM raw_context; - raw_context.context_flags = MD_CONTEXT_ARM_INTEGER; - raw_context.iregs[0] = 0x3ecba80d; - raw_context.iregs[1] = 0x382583b9; - raw_context.iregs[2] = 0x7fccc03f; - raw_context.iregs[3] = 0xf62f8ec2; - raw_context.iregs[4] = 0x46a6a6a8; - raw_context.iregs[5] = 0x6a5025e2; - raw_context.iregs[6] = 0xd9fabb4a; - raw_context.iregs[7] = 0x6913f540; - raw_context.iregs[8] = 0xbffe6eda; - raw_context.iregs[9] = 0xb2ce1e2d; - raw_context.iregs[10] = 0x659caaa4; - raw_context.iregs[11] = 0xf0e0d0c0; - raw_context.iregs[12] = 0xa9b8c7d6; - raw_context.iregs[13] = 0x12345678; - raw_context.iregs[14] = 0xabcd1234; - raw_context.iregs[15] = 0x10203040; - raw_context.cpsr = 0x2e951ef7; - Context context(dump, raw_context); - - Exception exception(dump, context, - 0x1234abcd, // thread id - 0xdcba4321, // exception code - 0xf0e0d0c0, // exception flags - 0x0919a9b9c9d9e9f9ULL); // exception address - - dump.Add(&context); - dump.Add(&exception); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - MinidumpException *md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); - - uint32_t thread_id; - ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); - ASSERT_EQ(0x1234abcdU, thread_id); - - const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); - EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); - EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); - EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, - raw_exception->exception_record.exception_address); - - MinidumpContext *md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); - ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU()); - const MDRawContextARM *md_raw_context = md_context->GetContextARM(); - ASSERT_TRUE(md_raw_context != NULL); - ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER, - (md_raw_context->context_flags - & MD_CONTEXT_ARM_INTEGER)); - EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]); - EXPECT_EQ(0x382583b9U, raw_context.iregs[1]); - EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]); - EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]); - EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]); - EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]); - EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]); - EXPECT_EQ(0x6913f540U, raw_context.iregs[7]); - EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]); - EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]); - EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]); - EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]); - EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]); - EXPECT_EQ(0x12345678U, raw_context.iregs[13]); - EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]); - EXPECT_EQ(0x10203040U, raw_context.iregs[15]); - EXPECT_EQ(0x2e951ef7U, raw_context.cpsr); -} - -TEST(Dump, OneExceptionARMOldFlags) { - Dump dump(0, kLittleEndian); - - MDRawContextARM raw_context; - // MD_CONTEXT_ARM_INTEGER, but with _OLD - raw_context.context_flags = MD_CONTEXT_ARM_OLD | 0x00000002; - raw_context.iregs[0] = 0x3ecba80d; - raw_context.iregs[1] = 0x382583b9; - raw_context.iregs[2] = 0x7fccc03f; - raw_context.iregs[3] = 0xf62f8ec2; - raw_context.iregs[4] = 0x46a6a6a8; - raw_context.iregs[5] = 0x6a5025e2; - raw_context.iregs[6] = 0xd9fabb4a; - raw_context.iregs[7] = 0x6913f540; - raw_context.iregs[8] = 0xbffe6eda; - raw_context.iregs[9] = 0xb2ce1e2d; - raw_context.iregs[10] = 0x659caaa4; - raw_context.iregs[11] = 0xf0e0d0c0; - raw_context.iregs[12] = 0xa9b8c7d6; - raw_context.iregs[13] = 0x12345678; - raw_context.iregs[14] = 0xabcd1234; - raw_context.iregs[15] = 0x10203040; - raw_context.cpsr = 0x2e951ef7; - Context context(dump, raw_context); - - Exception exception(dump, context, - 0x1234abcd, // thread id - 0xdcba4321, // exception code - 0xf0e0d0c0, // exception flags - 0x0919a9b9c9d9e9f9ULL); // exception address - - dump.Add(&context); - dump.Add(&exception); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - MinidumpException *md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); - - uint32_t thread_id; - ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); - ASSERT_EQ(0x1234abcdU, thread_id); - - const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); - EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); - EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); - EXPECT_EQ(0x0919a9b9c9d9e9f9ULL, - raw_exception->exception_record.exception_address); - - MinidumpContext *md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); - ASSERT_EQ((uint32_t) MD_CONTEXT_ARM, md_context->GetContextCPU()); - const MDRawContextARM *md_raw_context = md_context->GetContextARM(); - ASSERT_TRUE(md_raw_context != NULL); - ASSERT_EQ((uint32_t) MD_CONTEXT_ARM_INTEGER, - (md_raw_context->context_flags - & MD_CONTEXT_ARM_INTEGER)); - EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]); - EXPECT_EQ(0x382583b9U, raw_context.iregs[1]); - EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]); - EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]); - EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]); - EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]); - EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]); - EXPECT_EQ(0x6913f540U, raw_context.iregs[7]); - EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]); - EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]); - EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]); - EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]); - EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]); - EXPECT_EQ(0x12345678U, raw_context.iregs[13]); - EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]); - EXPECT_EQ(0x10203040U, raw_context.iregs[15]); - EXPECT_EQ(0x2e951ef7U, raw_context.cpsr); -} - -TEST(Dump, OneExceptionMIPS) { - Dump dump(0, kLittleEndian); - - MDRawContextMIPS raw_context; - raw_context.context_flags = MD_CONTEXT_MIPS_INTEGER; - raw_context.iregs[0] = 0x3ecba80d; - raw_context.iregs[1] = 0x382583b9; - raw_context.iregs[2] = 0x7fccc03f; - raw_context.iregs[3] = 0xf62f8ec2; - raw_context.iregs[4] = 0x46a6a6a8; - raw_context.iregs[5] = 0x6a5025e2; - raw_context.iregs[6] = 0xd9fabb4a; - raw_context.iregs[7] = 0x6913f540; - raw_context.iregs[8] = 0xbffe6eda; - raw_context.iregs[9] = 0xb2ce1e2d; - raw_context.iregs[10] = 0x659caaa4; - raw_context.iregs[11] = 0xf0e0d0c0; - raw_context.iregs[12] = 0xa9b8c7d6; - raw_context.iregs[13] = 0x12345678; - raw_context.iregs[14] = 0xabcd1234; - raw_context.iregs[15] = 0x10203040; - raw_context.iregs[16] = 0xa80d3ecb; - raw_context.iregs[17] = 0x83b93825; - raw_context.iregs[18] = 0xc03f7fcc; - raw_context.iregs[19] = 0x8ec2f62f; - raw_context.iregs[20] = 0xa6a846a6; - raw_context.iregs[21] = 0x25e26a50; - raw_context.iregs[22] = 0xbb4ad9fa; - raw_context.iregs[23] = 0xf5406913; - raw_context.iregs[24] = 0x6edabffe; - raw_context.iregs[25] = 0x1e2db2ce; - raw_context.iregs[26] = 0xaaa4659c; - raw_context.iregs[27] = 0xd0c0f0e0; - raw_context.iregs[28] = 0xc7d6a9b8; - raw_context.iregs[29] = 0x56781234; - raw_context.iregs[30] = 0x1234abcd; - raw_context.iregs[31] = 0x30401020; - - Context context(dump, raw_context); - - Exception exception(dump, context, - 0x1234abcd, // Thread id. - 0xdcba4321, // Exception code. - 0xf0e0d0c0, // Exception flags. - 0x0919a9b9); // Exception address. - - dump.Add(&context); - dump.Add(&exception); - dump.Finish(); - - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - - istringstream minidump_stream(contents); - Minidump minidump(minidump_stream); - ASSERT_TRUE(minidump.Read()); - ASSERT_EQ(1U, minidump.GetDirectoryEntryCount()); - - MinidumpException *md_exception = minidump.GetException(); - ASSERT_TRUE(md_exception != NULL); - - uint32_t thread_id; - ASSERT_TRUE(md_exception->GetThreadID(&thread_id)); - ASSERT_EQ(0x1234abcdU, thread_id); - - const MDRawExceptionStream* raw_exception = md_exception->exception(); - ASSERT_TRUE(raw_exception != NULL); - EXPECT_EQ(0xdcba4321, raw_exception->exception_record.exception_code); - EXPECT_EQ(0xf0e0d0c0, raw_exception->exception_record.exception_flags); - EXPECT_EQ(0x0919a9b9U, - raw_exception->exception_record.exception_address); - - MinidumpContext* md_context = md_exception->GetContext(); - ASSERT_TRUE(md_context != NULL); - ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS, md_context->GetContextCPU()); - const MDRawContextMIPS* md_raw_context = md_context->GetContextMIPS(); - ASSERT_TRUE(md_raw_context != NULL); - ASSERT_EQ((uint32_t) MD_CONTEXT_MIPS_INTEGER, - (md_raw_context->context_flags & MD_CONTEXT_MIPS_INTEGER)); - EXPECT_EQ(0x3ecba80dU, raw_context.iregs[0]); - EXPECT_EQ(0x382583b9U, raw_context.iregs[1]); - EXPECT_EQ(0x7fccc03fU, raw_context.iregs[2]); - EXPECT_EQ(0xf62f8ec2U, raw_context.iregs[3]); - EXPECT_EQ(0x46a6a6a8U, raw_context.iregs[4]); - EXPECT_EQ(0x6a5025e2U, raw_context.iregs[5]); - EXPECT_EQ(0xd9fabb4aU, raw_context.iregs[6]); - EXPECT_EQ(0x6913f540U, raw_context.iregs[7]); - EXPECT_EQ(0xbffe6edaU, raw_context.iregs[8]); - EXPECT_EQ(0xb2ce1e2dU, raw_context.iregs[9]); - EXPECT_EQ(0x659caaa4U, raw_context.iregs[10]); - EXPECT_EQ(0xf0e0d0c0U, raw_context.iregs[11]); - EXPECT_EQ(0xa9b8c7d6U, raw_context.iregs[12]); - EXPECT_EQ(0x12345678U, raw_context.iregs[13]); - EXPECT_EQ(0xabcd1234U, raw_context.iregs[14]); - EXPECT_EQ(0x10203040U, raw_context.iregs[15]); - EXPECT_EQ(0xa80d3ecbU, raw_context.iregs[16]); - EXPECT_EQ(0x83b93825U, raw_context.iregs[17]); - EXPECT_EQ(0xc03f7fccU, raw_context.iregs[18]); - EXPECT_EQ(0x8ec2f62fU, raw_context.iregs[19]); - EXPECT_EQ(0xa6a846a6U, raw_context.iregs[20]); - EXPECT_EQ(0x25e26a50U, raw_context.iregs[21]); - EXPECT_EQ(0xbb4ad9faU, raw_context.iregs[22]); - EXPECT_EQ(0xf5406913U, raw_context.iregs[23]); - EXPECT_EQ(0x6edabffeU, raw_context.iregs[24]); - EXPECT_EQ(0x1e2db2ceU, raw_context.iregs[25]); - EXPECT_EQ(0xaaa4659cU, raw_context.iregs[26]); - EXPECT_EQ(0xd0c0f0e0U, raw_context.iregs[27]); - EXPECT_EQ(0xc7d6a9b8U, raw_context.iregs[28]); - EXPECT_EQ(0x56781234U, raw_context.iregs[29]); - EXPECT_EQ(0x1234abcdU, raw_context.iregs[30]); - EXPECT_EQ(0x30401020U, raw_context.iregs[31]); -} - -} // namespace diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.cc b/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.cc deleted file mode 100644 index 025ab883a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.cc +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// module_comparer.cc: ModuleComparer implementation. -// See module_comparer.h for documentation. -// -// Author: lambxsy@google.com (Siyang Xie) - -#include "processor/module_comparer.h" - -#include <map> -#include <string> - -#include "common/scoped_ptr.h" -#include "processor/basic_code_module.h" -#include "processor/logging.h" - -#define ASSERT_TRUE(condition) \ - if (!(condition)) { \ - BPLOG(ERROR) << "FAIL: " << #condition << " @ " \ - << __FILE__ << ":" << __LINE__; \ - return false; \ - } - -#define ASSERT_FALSE(condition) ASSERT_TRUE(!(condition)) - -namespace google_breakpad { - -bool ModuleComparer::Compare(const string &symbol_data) { - scoped_ptr<BasicModule> basic_module(new BasicModule("test_module")); - scoped_ptr<FastModule> fast_module(new FastModule("test_module")); - - // Load symbol data into basic_module - scoped_array<char> buffer(new char[symbol_data.size() + 1]); - memcpy(buffer.get(), symbol_data.c_str(), symbol_data.size()); - buffer.get()[symbol_data.size()] = '\0'; - ASSERT_TRUE(basic_module->LoadMapFromMemory(buffer.get(), - symbol_data.size() + 1)); - buffer.reset(); - - // Serialize BasicSourceLineResolver::Module. - unsigned int serialized_size = 0; - scoped_array<char> serialized_data( - serializer_.Serialize(*(basic_module.get()), &serialized_size)); - ASSERT_TRUE(serialized_data.get()); - BPLOG(INFO) << "Serialized size = " << serialized_size << " Bytes"; - - // Load FastSourceLineResolver::Module using serialized data. - ASSERT_TRUE(fast_module->LoadMapFromMemory(serialized_data.get(), - serialized_size)); - ASSERT_TRUE(fast_module->IsCorrupt() == basic_module->IsCorrupt()); - - // Compare FastSourceLineResolver::Module with - // BasicSourceLineResolver::Module. - ASSERT_TRUE(CompareModule(basic_module.get(), fast_module.get())); - - return true; -} - -// Traversal the content of module and do comparison -bool ModuleComparer::CompareModule(const BasicModule *basic_module, - const FastModule *fast_module) const { - // Compare name_. - ASSERT_TRUE(basic_module->name_ == fast_module->name_); - - // Compare files_: - { - BasicModule::FileMap::const_iterator iter1 = basic_module->files_.begin(); - FastModule::FileMap::iterator iter2 = fast_module->files_.begin(); - while (iter1 != basic_module->files_.end() - && iter2 != fast_module->files_.end()) { - ASSERT_TRUE(iter1->first == iter2.GetKey()); - string tmp(iter2.GetValuePtr()); - ASSERT_TRUE(iter1->second == tmp); - ++iter1; - ++iter2; - } - ASSERT_TRUE(iter1 == basic_module->files_.end()); - ASSERT_TRUE(iter2 == fast_module->files_.end()); - } - - // Compare functions_: - { - RangeMap<MemAddr, linked_ptr<BasicFunc> >::MapConstIterator iter1; - StaticRangeMap<MemAddr, FastFunc>::MapConstIterator iter2; - iter1 = basic_module->functions_.map_.begin(); - iter2 = fast_module->functions_.map_.begin(); - while (iter1 != basic_module->functions_.map_.end() - && iter2 != fast_module->functions_.map_.end()) { - ASSERT_TRUE(iter1->first == iter2.GetKey()); - ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base()); - ASSERT_TRUE(CompareFunction( - iter1->second.entry().get(), iter2.GetValuePtr()->entryptr())); - ++iter1; - ++iter2; - } - ASSERT_TRUE(iter1 == basic_module->functions_.map_.end()); - ASSERT_TRUE(iter2 == fast_module->functions_.map_.end()); - } - - // Compare public_symbols_: - { - AddressMap<MemAddr, linked_ptr<BasicPubSymbol> >::MapConstIterator iter1; - StaticAddressMap<MemAddr, FastPubSymbol>::MapConstIterator iter2; - iter1 = basic_module->public_symbols_.map_.begin(); - iter2 = fast_module->public_symbols_.map_.begin(); - while (iter1 != basic_module->public_symbols_.map_.end() - && iter2 != fast_module->public_symbols_.map_.end()) { - ASSERT_TRUE(iter1->first == iter2.GetKey()); - ASSERT_TRUE(ComparePubSymbol( - iter1->second.get(), iter2.GetValuePtr())); - ++iter1; - ++iter2; - } - ASSERT_TRUE(iter1 == basic_module->public_symbols_.map_.end()); - ASSERT_TRUE(iter2 == fast_module->public_symbols_.map_.end()); - } - - // Compare windows_frame_info_[]: - for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) { - ASSERT_TRUE(CompareCRM(&(basic_module->windows_frame_info_[i]), - &(fast_module->windows_frame_info_[i]))); - } - - // Compare cfi_initial_rules_: - { - RangeMap<MemAddr, string>::MapConstIterator iter1; - StaticRangeMap<MemAddr, char>::MapConstIterator iter2; - iter1 = basic_module->cfi_initial_rules_.map_.begin(); - iter2 = fast_module->cfi_initial_rules_.map_.begin(); - while (iter1 != basic_module->cfi_initial_rules_.map_.end() - && iter2 != fast_module->cfi_initial_rules_.map_.end()) { - ASSERT_TRUE(iter1->first == iter2.GetKey()); - ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base()); - string tmp(iter2.GetValuePtr()->entryptr()); - ASSERT_TRUE(iter1->second.entry() == tmp); - ++iter1; - ++iter2; - } - ASSERT_TRUE(iter1 == basic_module->cfi_initial_rules_.map_.end()); - ASSERT_TRUE(iter2 == fast_module->cfi_initial_rules_.map_.end()); - } - - // Compare cfi_delta_rules_: - { - map<MemAddr, string>::const_iterator iter1; - StaticMap<MemAddr, char>::iterator iter2; - iter1 = basic_module->cfi_delta_rules_.begin(); - iter2 = fast_module->cfi_delta_rules_.begin(); - while (iter1 != basic_module->cfi_delta_rules_.end() - && iter2 != fast_module->cfi_delta_rules_.end()) { - ASSERT_TRUE(iter1->first == iter2.GetKey()); - string tmp(iter2.GetValuePtr()); - ASSERT_TRUE(iter1->second == tmp); - ++iter1; - ++iter2; - } - ASSERT_TRUE(iter1 == basic_module->cfi_delta_rules_.end()); - ASSERT_TRUE(iter2 == fast_module->cfi_delta_rules_.end()); - } - - return true; -} - -bool ModuleComparer::CompareFunction(const BasicFunc *basic_func, - const FastFunc *fast_func_raw) const { - FastFunc* fast_func = new FastFunc(); - fast_func->CopyFrom(fast_func_raw); - ASSERT_TRUE(basic_func->name == fast_func->name); - ASSERT_TRUE(basic_func->address == fast_func->address); - ASSERT_TRUE(basic_func->size == fast_func->size); - - // compare range map of lines: - RangeMap<MemAddr, linked_ptr<BasicLine> >::MapConstIterator iter1; - StaticRangeMap<MemAddr, FastLine>::MapConstIterator iter2; - iter1 = basic_func->lines.map_.begin(); - iter2 = fast_func->lines.map_.begin(); - while (iter1 != basic_func->lines.map_.end() - && iter2 != fast_func->lines.map_.end()) { - ASSERT_TRUE(iter1->first == iter2.GetKey()); - ASSERT_TRUE(iter1->second.base() == iter2.GetValuePtr()->base()); - ASSERT_TRUE(CompareLine(iter1->second.entry().get(), - iter2.GetValuePtr()->entryptr())); - ++iter1; - ++iter2; - } - ASSERT_TRUE(iter1 == basic_func->lines.map_.end()); - ASSERT_TRUE(iter2 == fast_func->lines.map_.end()); - - delete fast_func; - return true; -} - -bool ModuleComparer::CompareLine(const BasicLine *basic_line, - const FastLine *fast_line_raw) const { - FastLine *fast_line = new FastLine; - fast_line->CopyFrom(fast_line_raw); - - ASSERT_TRUE(basic_line->address == fast_line->address); - ASSERT_TRUE(basic_line->size == fast_line->size); - ASSERT_TRUE(basic_line->source_file_id == fast_line->source_file_id); - ASSERT_TRUE(basic_line->line == fast_line->line); - - delete fast_line; - return true; -} - -bool ModuleComparer::ComparePubSymbol(const BasicPubSymbol* basic_ps, - const FastPubSymbol* fastps_raw) const { - FastPubSymbol *fast_ps = new FastPubSymbol; - fast_ps->CopyFrom(fastps_raw); - ASSERT_TRUE(basic_ps->name == fast_ps->name); - ASSERT_TRUE(basic_ps->address == fast_ps->address); - ASSERT_TRUE(basic_ps->parameter_size == fast_ps->parameter_size); - delete fast_ps; - return true; -} - -bool ModuleComparer::CompareWFI(const WindowsFrameInfo& wfi1, - const WindowsFrameInfo& wfi2) const { - ASSERT_TRUE(wfi1.type_ == wfi2.type_); - ASSERT_TRUE(wfi1.valid == wfi2.valid); - ASSERT_TRUE(wfi1.prolog_size == wfi2.prolog_size); - ASSERT_TRUE(wfi1.epilog_size == wfi2.epilog_size); - ASSERT_TRUE(wfi1.parameter_size == wfi2.parameter_size); - ASSERT_TRUE(wfi1.saved_register_size == wfi2.saved_register_size); - ASSERT_TRUE(wfi1.local_size == wfi2.local_size); - ASSERT_TRUE(wfi1.max_stack_size == wfi2.max_stack_size); - ASSERT_TRUE(wfi1.allocates_base_pointer == wfi2.allocates_base_pointer); - ASSERT_TRUE(wfi1.program_string == wfi2.program_string); - return true; -} - -// Compare ContainedRangeMap -bool ModuleComparer::CompareCRM( - const ContainedRangeMap<MemAddr, linked_ptr<WFI> >* basic_crm, - const StaticContainedRangeMap<MemAddr, char>* fast_crm) const { - ASSERT_TRUE(basic_crm->base_ == fast_crm->base_); - - if (!basic_crm->entry_.get() || !fast_crm->entry_ptr_) { - // empty entry: - ASSERT_TRUE(!basic_crm->entry_.get() && !fast_crm->entry_ptr_); - } else { - WFI newwfi; - newwfi.CopyFrom(fast_resolver_->CopyWFI(fast_crm->entry_ptr_)); - ASSERT_TRUE(CompareWFI(*(basic_crm->entry_.get()), newwfi)); - } - - if ((!basic_crm->map_ || basic_crm->map_->empty()) - || fast_crm->map_.empty()) { - ASSERT_TRUE((!basic_crm->map_ || basic_crm->map_->empty()) - && fast_crm->map_.empty()); - } else { - ContainedRangeMap<MemAddr, linked_ptr<WFI> >::MapConstIterator iter1; - StaticContainedRangeMap<MemAddr, char>::MapConstIterator iter2; - iter1 = basic_crm->map_->begin(); - iter2 = fast_crm->map_.begin(); - while (iter1 != basic_crm->map_->end() - && iter2 != fast_crm->map_.end()) { - ASSERT_TRUE(iter1->first == iter2.GetKey()); - StaticContainedRangeMap<MemAddr, char> *child = - new StaticContainedRangeMap<MemAddr, char>( - reinterpret_cast<const char*>(iter2.GetValuePtr())); - ASSERT_TRUE(CompareCRM(iter1->second, child)); - delete child; - ++iter1; - ++iter2; - } - ASSERT_TRUE(iter1 == basic_crm->map_->end()); - ASSERT_TRUE(iter2 == fast_crm->map_.end()); - } - - return true; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.h b/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.h deleted file mode 100644 index fcbd51775..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/module_comparer.h +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// module_comparer.h: ModuleComparer reads a string format of symbol file, and -// loads the symbol into both BasicSourceLineResolver::Module and -// FastSourceLineResolve::Module. It then traverses both Modules and compare -// the content of data to verify the correctness of new fast module. -// ModuleCompare class is a tool to verify correctness of a loaded -// FastSourceLineResolver::Module instance, i.e., in-memory representation of -// parsed symbol. ModuleComparer class should be used for testing purpose only, -// e.g., in fast_source_line_resolver_unittest. -// -// Author: lambxsy@google.com (Siyang Xie) - -#ifndef PROCESSOR_MODULE_COMPARER_H__ -#define PROCESSOR_MODULE_COMPARER_H__ - -#include <string> - -#include "processor/basic_source_line_resolver_types.h" -#include "processor/fast_source_line_resolver_types.h" -#include "processor/module_serializer.h" -#include "processor/windows_frame_info.h" - -namespace google_breakpad { - -class ModuleComparer { - public: - ModuleComparer(): fast_resolver_(new FastSourceLineResolver), - basic_resolver_(new BasicSourceLineResolver) { } - ~ModuleComparer() { - delete fast_resolver_; - delete basic_resolver_; - } - - // BasicSourceLineResolver loads its module using the symbol data, - // ModuleSerializer serialize the loaded module into a memory chunk, - // FastSourceLineResolver loads its module using the serialized memory chunk, - // Then, traverse both modules together and compare underlying data - // return true if both modules contain exactly same data. - bool Compare(const string &symbol_data); - - private: - typedef BasicSourceLineResolver::Module BasicModule; - typedef FastSourceLineResolver::Module FastModule; - typedef BasicSourceLineResolver::Function BasicFunc; - typedef FastSourceLineResolver::Function FastFunc; - typedef BasicSourceLineResolver::Line BasicLine; - typedef FastSourceLineResolver::Line FastLine; - typedef BasicSourceLineResolver::PublicSymbol BasicPubSymbol; - typedef FastSourceLineResolver::PublicSymbol FastPubSymbol; - typedef WindowsFrameInfo WFI; - - bool CompareModule(const BasicModule *oldmodule, - const FastModule *newmodule) const; - bool CompareFunction(const BasicFunc *oldfunc, const FastFunc *newfunc) const; - bool CompareLine(const BasicLine *oldline, const FastLine *newline) const; - bool ComparePubSymbol(const BasicPubSymbol*, const FastPubSymbol*) const; - bool CompareWFI(const WindowsFrameInfo&, const WindowsFrameInfo&) const; - - // Compare ContainedRangeMap - bool CompareCRM(const ContainedRangeMap<MemAddr, linked_ptr<WFI> >*, - const StaticContainedRangeMap<MemAddr, char>*) const; - - FastSourceLineResolver *fast_resolver_; - BasicSourceLineResolver *basic_resolver_; - ModuleSerializer serializer_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_MODULE_COMPARER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_factory.h b/toolkit/crashreporter/google-breakpad/src/processor/module_factory.h deleted file mode 100644 index 7aa7caa59..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/module_factory.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// module_factory.h: ModuleFactory a factory that provides -// an interface for creating a Module and deferring instantiation to subclasses -// BasicModuleFactory and FastModuleFactory. - -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_MODULE_FACTORY_H__ -#define PROCESSOR_MODULE_FACTORY_H__ - -#include "processor/basic_source_line_resolver_types.h" -#include "processor/fast_source_line_resolver_types.h" -#include "processor/source_line_resolver_base_types.h" - -namespace google_breakpad { - -class ModuleFactory { - public: - virtual ~ModuleFactory() { }; - virtual SourceLineResolverBase::Module* CreateModule( - const string &name) const = 0; -}; - -class BasicModuleFactory : public ModuleFactory { - public: - virtual ~BasicModuleFactory() { } - virtual BasicSourceLineResolver::Module* CreateModule( - const string &name) const { - return new BasicSourceLineResolver::Module(name); - } -}; - -class FastModuleFactory : public ModuleFactory { - public: - virtual ~FastModuleFactory() { } - virtual FastSourceLineResolver::Module* CreateModule( - const string &name) const { - return new FastSourceLineResolver::Module(name); - } -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_MODULE_FACTORY_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.cc b/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.cc deleted file mode 100644 index 6ac60c1fc..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.cc +++ /dev/null @@ -1,207 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// module_serializer.cc: ModuleSerializer implementation. -// -// See module_serializer.h for documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include "processor/module_serializer.h" - -#include <map> -#include <string> - -#include "processor/basic_code_module.h" -#include "processor/logging.h" - -namespace google_breakpad { - -// Definition of static member variable in SimplerSerializer<Funcion>, which -// is declared in file "simple_serializer-inl.h" -RangeMapSerializer< MemAddr, linked_ptr<BasicSourceLineResolver::Line> > -SimpleSerializer<BasicSourceLineResolver::Function>::range_map_serializer_; - -size_t ModuleSerializer::SizeOf(const BasicSourceLineResolver::Module &module) { - size_t total_size_alloc_ = 0; - - // Size of the "is_corrupt" flag. - total_size_alloc_ += SimpleSerializer<bool>::SizeOf(module.is_corrupt_); - - // Compute memory size for each map component in Module class. - int map_index = 0; - map_sizes_[map_index++] = files_serializer_.SizeOf(module.files_); - map_sizes_[map_index++] = functions_serializer_.SizeOf(module.functions_); - map_sizes_[map_index++] = pubsym_serializer_.SizeOf(module.public_symbols_); - for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) - map_sizes_[map_index++] = - wfi_serializer_.SizeOf(&(module.windows_frame_info_[i])); - map_sizes_[map_index++] = cfi_init_rules_serializer_.SizeOf( - module.cfi_initial_rules_); - map_sizes_[map_index++] = cfi_delta_rules_serializer_.SizeOf( - module.cfi_delta_rules_); - - // Header size. - total_size_alloc_ += kNumberMaps_ * sizeof(uint32_t); - - for (int i = 0; i < kNumberMaps_; ++i) { - total_size_alloc_ += map_sizes_[i]; - } - - // Extra one byte for null terminator for C-string copy safety. - total_size_alloc_ += SimpleSerializer<char>::SizeOf(0); - - return total_size_alloc_; -} - -char *ModuleSerializer::Write(const BasicSourceLineResolver::Module &module, - char *dest) { - // Write the is_corrupt flag. - dest = SimpleSerializer<bool>::Write(module.is_corrupt_, dest); - // Write header. - memcpy(dest, map_sizes_, kNumberMaps_ * sizeof(uint32_t)); - dest += kNumberMaps_ * sizeof(uint32_t); - // Write each map. - dest = files_serializer_.Write(module.files_, dest); - dest = functions_serializer_.Write(module.functions_, dest); - dest = pubsym_serializer_.Write(module.public_symbols_, dest); - for (int i = 0; i < WindowsFrameInfo::STACK_INFO_LAST; ++i) - dest = wfi_serializer_.Write(&(module.windows_frame_info_[i]), dest); - dest = cfi_init_rules_serializer_.Write(module.cfi_initial_rules_, dest); - dest = cfi_delta_rules_serializer_.Write(module.cfi_delta_rules_, dest); - // Write a null terminator. - dest = SimpleSerializer<char>::Write(0, dest); - return dest; -} - -char* ModuleSerializer::Serialize( - const BasicSourceLineResolver::Module &module, unsigned int *size) { - // Compute size of memory to allocate. - unsigned int size_to_alloc = SizeOf(module); - - // Allocate memory for serialized data. - char *serialized_data = new char[size_to_alloc]; - if (!serialized_data) { - BPLOG(ERROR) << "ModuleSerializer: memory allocation failed, " - << "size to alloc: " << size_to_alloc; - if (size) *size = 0; - return NULL; - } - - // Write serialized data to allocated memory chunk. - char *end_address = Write(module, serialized_data); - // Verify the allocated memory size is equal to the size of data been written. - unsigned int size_written = - static_cast<unsigned int>(end_address - serialized_data); - if (size_to_alloc != size_written) { - BPLOG(ERROR) << "size_to_alloc differs from size_written: " - << size_to_alloc << " vs " << size_written; - } - - // Set size and return the start address of memory chunk. - if (size) - *size = size_to_alloc; - return serialized_data; -} - -bool ModuleSerializer::SerializeModuleAndLoadIntoFastResolver( - const BasicSourceLineResolver::ModuleMap::const_iterator &iter, - FastSourceLineResolver *fast_resolver) { - BPLOG(INFO) << "Converting symbol " << iter->first.c_str(); - - // Cast SourceLineResolverBase::Module* to BasicSourceLineResolver::Module*. - BasicSourceLineResolver::Module* basic_module = - dynamic_cast<BasicSourceLineResolver::Module*>(iter->second); - - unsigned int size = 0; - scoped_array<char> symbol_data(Serialize(*basic_module, &size)); - if (!symbol_data.get()) { - BPLOG(ERROR) << "Serialization failed for module: " << basic_module->name_; - return false; - } - BPLOG(INFO) << "Serialized Symbol Size " << size; - - // Copy the data into string. - // Must pass string to LoadModuleUsingMapBuffer(), instead of passing char* to - // LoadModuleUsingMemoryBuffer(), becaused of data ownership/lifetime issue. - string symbol_data_string(symbol_data.get(), size); - symbol_data.reset(); - - scoped_ptr<CodeModule> code_module( - new BasicCodeModule(0, 0, iter->first, "", "", "", "")); - - return fast_resolver->LoadModuleUsingMapBuffer(code_module.get(), - symbol_data_string); -} - -void ModuleSerializer::ConvertAllModules( - const BasicSourceLineResolver *basic_resolver, - FastSourceLineResolver *fast_resolver) { - // Check for NULL pointer. - if (!basic_resolver || !fast_resolver) - return; - - // Traverse module list in basic resolver. - BasicSourceLineResolver::ModuleMap::const_iterator iter; - iter = basic_resolver->modules_->begin(); - for (; iter != basic_resolver->modules_->end(); ++iter) - SerializeModuleAndLoadIntoFastResolver(iter, fast_resolver); -} - -bool ModuleSerializer::ConvertOneModule( - const string &moduleid, - const BasicSourceLineResolver *basic_resolver, - FastSourceLineResolver *fast_resolver) { - // Check for NULL pointer. - if (!basic_resolver || !fast_resolver) - return false; - - BasicSourceLineResolver::ModuleMap::const_iterator iter; - iter = basic_resolver->modules_->find(moduleid); - if (iter == basic_resolver->modules_->end()) - return false; - - return SerializeModuleAndLoadIntoFastResolver(iter, fast_resolver); -} - -char* ModuleSerializer::SerializeSymbolFileData( - const string &symbol_data, unsigned int *size) { - scoped_ptr<BasicSourceLineResolver::Module> module( - new BasicSourceLineResolver::Module("no name")); - scoped_array<char> buffer(new char[symbol_data.size() + 1]); - memcpy(buffer.get(), symbol_data.c_str(), symbol_data.size()); - buffer.get()[symbol_data.size()] = '\0'; - if (!module->LoadMapFromMemory(buffer.get(), symbol_data.size() + 1)) { - return NULL; - } - buffer.reset(NULL); - return Serialize(*(module.get()), size); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.h b/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.h deleted file mode 100644 index effb00916..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/module_serializer.h +++ /dev/null @@ -1,127 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// module_serializer.h: ModuleSerializer serializes a loaded symbol, -// i.e., a loaded BasicSouceLineResolver::Module instance, into a memory -// chunk of data. The serialized data can be read and loaded by -// FastSourceLineResolver without CPU & memory-intensive parsing. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_MODULE_SERIALIZER_H__ -#define PROCESSOR_MODULE_SERIALIZER_H__ - -#include <map> -#include <string> - -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/fast_source_line_resolver.h" -#include "processor/basic_source_line_resolver_types.h" -#include "processor/fast_source_line_resolver_types.h" -#include "processor/linked_ptr.h" -#include "processor/map_serializers-inl.h" -#include "processor/simple_serializer-inl.h" -#include "processor/windows_frame_info.h" - -namespace google_breakpad { - -// ModuleSerializer serializes a loaded BasicSourceLineResolver::Module into a -// chunk of memory data. ModuleSerializer also provides interface to compute -// memory size of the serialized data, write serialized data directly into -// memory, convert ASCII format symbol data into serialized binary data, and -// convert loaded BasicSourceLineResolver::Module into -// FastSourceLineResolver::Module. -class ModuleSerializer { - public: - // Compute the size of memory required to serialize a module. Return the - // total size needed for serialization. - size_t SizeOf(const BasicSourceLineResolver::Module &module); - - // Write a module into an allocated memory chunk with required size. - // Return the "end" of data, i.e., the address after the final byte of data. - char* Write(const BasicSourceLineResolver::Module &module, char *dest); - - // Serializes a loaded Module object into a chunk of memory data and returns - // the address of memory chunk. If size != NULL, *size is set to the memory - // size allocated for the serialized data. - // Caller takes the ownership of the memory chunk (allocated on heap), and - // owner should call delete [] to free the memory after use. - char* Serialize(const BasicSourceLineResolver::Module &module, - unsigned int *size = NULL); - - // Given the string format symbol_data, produces a chunk of serialized data. - // Caller takes ownership of the serialized data (on heap), and owner should - // call delete [] to free the memory after use. - char* SerializeSymbolFileData(const string &symbol_data, - unsigned int *size = NULL); - - // Serializes one loaded module with given moduleid in the basic source line - // resolver, and loads the serialized data into the fast source line resolver. - // Return false if the basic source line doesn't have a module with the given - // moduleid. - bool ConvertOneModule(const string &moduleid, - const BasicSourceLineResolver *basic_resolver, - FastSourceLineResolver *fast_resolver); - - // Serializes all the loaded modules in a basic source line resolver, and - // loads the serialized data into a fast source line resolver. - void ConvertAllModules(const BasicSourceLineResolver *basic_resolver, - FastSourceLineResolver *fast_resolver); - - private: - // Convenient type names. - typedef BasicSourceLineResolver::Line Line; - typedef BasicSourceLineResolver::Function Function; - typedef BasicSourceLineResolver::PublicSymbol PublicSymbol; - - // Internal implementation for ConvertOneModule and ConvertAllModules methods. - bool SerializeModuleAndLoadIntoFastResolver( - const BasicSourceLineResolver::ModuleMap::const_iterator &iter, - FastSourceLineResolver *fast_resolver); - - // Number of Maps that Module class contains. - static const int32_t kNumberMaps_ = - FastSourceLineResolver::Module::kNumberMaps_; - - // Memory sizes required to serialize map components in Module. - uint32_t map_sizes_[kNumberMaps_]; - - // Serializers for each individual map component in Module class. - StdMapSerializer<int, string> files_serializer_; - RangeMapSerializer<MemAddr, linked_ptr<Function> > functions_serializer_; - AddressMapSerializer<MemAddr, linked_ptr<PublicSymbol> > pubsym_serializer_; - ContainedRangeMapSerializer<MemAddr, - linked_ptr<WindowsFrameInfo> > wfi_serializer_; - RangeMapSerializer<MemAddr, string> cfi_init_rules_serializer_; - StdMapSerializer<MemAddr, string> cfi_delta_rules_serializer_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_MODULE_SERIALIZER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/moz.build b/toolkit/crashreporter/google-breakpad/src/processor/moz.build deleted file mode 100644 index 1a2fac39e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/moz.build +++ /dev/null @@ -1,66 +0,0 @@ -# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -# vim: set filetype=python: -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -SOURCES += [ - '../third_party/libdisasm/ia32_invariant.c', - 'disassembler_x86.cc', - 'exploitability_win.cc', -] - -UNIFIED_SOURCES += [ - '../third_party/libdisasm/ia32_implicit.c', - '../third_party/libdisasm/ia32_insn.c', - '../third_party/libdisasm/ia32_modrm.c', - '../third_party/libdisasm/ia32_opcode_tables.c', - '../third_party/libdisasm/ia32_operand.c', - '../third_party/libdisasm/ia32_reg.c', - '../third_party/libdisasm/ia32_settings.c', - '../third_party/libdisasm/x86_disasm.c', - '../third_party/libdisasm/x86_imm.c', - '../third_party/libdisasm/x86_insn.c', - '../third_party/libdisasm/x86_misc.c', - '../third_party/libdisasm/x86_operand_list.c', - 'basic_code_modules.cc', - 'basic_source_line_resolver.cc', - 'call_stack.cc', - 'cfi_frame_info.cc', - 'dump_context.cc', - 'dump_object.cc', - 'exploitability.cc', - 'exploitability_linux.cc', - 'logging.cc', - 'minidump.cc', - 'minidump_processor.cc', - 'pathname_stripper.cc', - 'proc_maps_linux.cc', - 'process_state.cc', - 'source_line_resolver_base.cc', - 'stack_frame_symbolizer.cc', - 'stackwalk_common.cc', - 'stackwalker.cc', - 'stackwalker_amd64.cc', - 'stackwalker_arm.cc', - 'stackwalker_arm64.cc', - 'stackwalker_mips.cc', - 'stackwalker_ppc.cc', - 'stackwalker_ppc64.cc', - 'stackwalker_sparc.cc', - 'stackwalker_x86.cc', - 'symbolic_constants_win.cc', - 'tokenize.cc', -] - -DEFINES['BPLOG_MINIMUM_SEVERITY'] = 'SEVERITY_ERROR' - -Library('breakpad_processor') - -# Don't use the STL wrappers in the crashreporter clients -DISABLE_STL_WRAPPING = True - -# We allow warnings for third-party code that can be updated from upstream. -ALLOW_COMPILER_WARNINGS = True - -include('/toolkit/crashreporter/crashreporter.mozbuild') diff --git a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.cc b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.cc deleted file mode 100644 index 839287bdb..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.cc +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// pathname_stripper.cc: Manipulates pathnames into their component parts. -// -// See pathname_stripper.h for documentation. -// -// Author: Mark Mentovai - -#include "processor/pathname_stripper.h" - -namespace google_breakpad { - -// static -string PathnameStripper::File(const string &path) { - string::size_type slash = path.rfind('/'); - string::size_type backslash = path.rfind('\\'); - - string::size_type file_start = 0; - if (slash != string::npos && - (backslash == string::npos || slash > backslash)) { - file_start = slash + 1; - } else if (backslash != string::npos) { - file_start = backslash + 1; - } - - return path.substr(file_start); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.h b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.h deleted file mode 100644 index 423ca0d05..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper.h +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// pathname_stripper.h: Manipulates pathnames into their component parts. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_PATHNAME_STRIPPER_H__ -#define PROCESSOR_PATHNAME_STRIPPER_H__ - -#include <string> - -#include "common/using_std_string.h" - -namespace google_breakpad { - -class PathnameStripper { - public: - // Given path, a pathname with components separated by slashes (/) or - // backslashes (\), returns the trailing component, without any separator. - // If path ends in a separator character, returns an empty string. - static string File(const string &path); -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_PATHNAME_STRIPPER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc deleted file mode 100644 index 1bff4cb01..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/pathname_stripper_unittest.cc +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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 <stdio.h> - -#include "processor/pathname_stripper.h" -#include "processor/logging.h" - -#define ASSERT_TRUE(condition) \ - if (!(condition)) { \ - fprintf(stderr, "FAIL: %s @ %s:%d\n", #condition, __FILE__, __LINE__); \ - return false; \ - } - -#define ASSERT_EQ(e1, e2) ASSERT_TRUE((e1) == (e2)) - -namespace { - -using google_breakpad::PathnameStripper; - -static bool RunTests() { - ASSERT_EQ(PathnameStripper::File("/dir/file"), "file"); - ASSERT_EQ(PathnameStripper::File("\\dir\\file"), "file"); - ASSERT_EQ(PathnameStripper::File("/dir\\file"), "file"); - ASSERT_EQ(PathnameStripper::File("\\dir/file"), "file"); - ASSERT_EQ(PathnameStripper::File("dir/file"), "file"); - ASSERT_EQ(PathnameStripper::File("dir\\file"), "file"); - ASSERT_EQ(PathnameStripper::File("dir/\\file"), "file"); - ASSERT_EQ(PathnameStripper::File("dir\\/file"), "file"); - ASSERT_EQ(PathnameStripper::File("file"), "file"); - ASSERT_EQ(PathnameStripper::File("dir/"), ""); - ASSERT_EQ(PathnameStripper::File("dir\\"), ""); - ASSERT_EQ(PathnameStripper::File("dir/dir/"), ""); - ASSERT_EQ(PathnameStripper::File("dir\\dir\\"), ""); - ASSERT_EQ(PathnameStripper::File("dir1/dir2/file"), "file"); - ASSERT_EQ(PathnameStripper::File("dir1\\dir2\\file"), "file"); - ASSERT_EQ(PathnameStripper::File("dir1/dir2\\file"), "file"); - ASSERT_EQ(PathnameStripper::File("dir1\\dir2/file"), "file"); - ASSERT_EQ(PathnameStripper::File(""), ""); - ASSERT_EQ(PathnameStripper::File("1"), "1"); - ASSERT_EQ(PathnameStripper::File("1/2"), "2"); - ASSERT_EQ(PathnameStripper::File("1\\2"), "2"); - ASSERT_EQ(PathnameStripper::File("/1/2"), "2"); - ASSERT_EQ(PathnameStripper::File("\\1\\2"), "2"); - ASSERT_EQ(PathnameStripper::File("dir//file"), "file"); - ASSERT_EQ(PathnameStripper::File("dir\\\\file"), "file"); - ASSERT_EQ(PathnameStripper::File("/dir//file"), "file"); - ASSERT_EQ(PathnameStripper::File("\\dir\\\\file"), "file"); - ASSERT_EQ(PathnameStripper::File("c:\\dir\\file"), "file"); - ASSERT_EQ(PathnameStripper::File("c:\\dir\\file.ext"), "file.ext"); - - return true; -} - -} // namespace - -int main(int argc, char **argv) { - BPLOG_INIT(&argc, &argv); - - return RunTests() ? 0 : 1; -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h deleted file mode 100644 index d7dbeac20..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator-inl.h +++ /dev/null @@ -1,363 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// postfix_evaluator-inl.h: Postfix (reverse Polish) notation expression -// evaluator. -// -// Documentation in postfix_evaluator.h. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_POSTFIX_EVALUATOR_INL_H__ -#define PROCESSOR_POSTFIX_EVALUATOR_INL_H__ - -#include "processor/postfix_evaluator.h" - -#include <stdio.h> - -#include <sstream> - -#include "google_breakpad/processor/memory_region.h" -#include "processor/logging.h" - -namespace google_breakpad { - -using std::istringstream; -using std::ostringstream; - - -// A small class used in Evaluate to make sure to clean up the stack -// before returning failure. -class AutoStackClearer { - public: - explicit AutoStackClearer(vector<string> *stack) : stack_(stack) {} - ~AutoStackClearer() { stack_->clear(); } - - private: - vector<string> *stack_; -}; - - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::EvaluateToken( - const string &token, - const string &expression, - DictionaryValidityType *assigned) { - // There are enough binary operations that do exactly the same thing - // (other than the specific operation, of course) that it makes sense - // to share as much code as possible. - enum BinaryOperation { - BINARY_OP_NONE = 0, - BINARY_OP_ADD, - BINARY_OP_SUBTRACT, - BINARY_OP_MULTIPLY, - BINARY_OP_DIVIDE_QUOTIENT, - BINARY_OP_DIVIDE_MODULUS, - BINARY_OP_ALIGN - }; - - BinaryOperation operation = BINARY_OP_NONE; - if (token == "+") - operation = BINARY_OP_ADD; - else if (token == "-") - operation = BINARY_OP_SUBTRACT; - else if (token == "*") - operation = BINARY_OP_MULTIPLY; - else if (token == "/") - operation = BINARY_OP_DIVIDE_QUOTIENT; - else if (token == "%") - operation = BINARY_OP_DIVIDE_MODULUS; - else if (token == "@") - operation = BINARY_OP_ALIGN; - - if (operation != BINARY_OP_NONE) { - // Get the operands. - ValueType operand1 = ValueType(); - ValueType operand2 = ValueType(); - if (!PopValues(&operand1, &operand2)) { - BPLOG(ERROR) << "Could not PopValues to get two values for binary " - "operation " << token << ": " << expression; - return false; - } - - // Perform the operation. - ValueType result; - switch (operation) { - case BINARY_OP_ADD: - result = operand1 + operand2; - break; - case BINARY_OP_SUBTRACT: - result = operand1 - operand2; - break; - case BINARY_OP_MULTIPLY: - result = operand1 * operand2; - break; - case BINARY_OP_DIVIDE_QUOTIENT: - result = operand1 / operand2; - break; - case BINARY_OP_DIVIDE_MODULUS: - result = operand1 % operand2; - break; - case BINARY_OP_ALIGN: - result = - operand1 & (static_cast<ValueType>(-1) ^ (operand2 - 1)); - break; - case BINARY_OP_NONE: - // This will not happen, but compilers will want a default or - // BINARY_OP_NONE case. - BPLOG(ERROR) << "Not reached!"; - return false; - break; - } - - // Save the result. - PushValue(result); - } else if (token == "^") { - // ^ for unary dereference. Can't dereference without memory. - if (!memory_) { - BPLOG(ERROR) << "Attempt to dereference without memory: " << - expression; - return false; - } - - ValueType address; - if (!PopValue(&address)) { - BPLOG(ERROR) << "Could not PopValue to get value to derefence: " << - expression; - return false; - } - - ValueType value; - if (!memory_->GetMemoryAtAddress(address, &value)) { - BPLOG(ERROR) << "Could not dereference memory at address " << - HexString(address) << ": " << expression; - return false; - } - - PushValue(value); - } else if (token == "=") { - // = for assignment. - ValueType value; - if (!PopValue(&value)) { - BPLOG(INFO) << "Could not PopValue to get value to assign: " << - expression; - return false; - } - - // Assignment is only meaningful when assigning into an identifier. - // The identifier must name a variable, not a constant. Variables - // begin with '$'. - string identifier; - if (PopValueOrIdentifier(NULL, &identifier) != POP_RESULT_IDENTIFIER) { - BPLOG(ERROR) << "PopValueOrIdentifier returned a value, but an " - "identifier is needed to assign " << - HexString(value) << ": " << expression; - return false; - } - if (identifier.empty() || identifier[0] != '$') { - BPLOG(ERROR) << "Can't assign " << HexString(value) << " to " << - identifier << ": " << expression; - return false; - } - - (*dictionary_)[identifier] = value; - if (assigned) - (*assigned)[identifier] = true; - } else { - // The token is not an operator, it's a literal value or an identifier. - // Push it onto the stack as-is. Use push_back instead of PushValue - // because PushValue pushes ValueType as a string, but token is already - // a string. - stack_.push_back(token); - } - return true; -} - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::EvaluateInternal( - const string &expression, - DictionaryValidityType *assigned) { - // Tokenize, splitting on whitespace. - istringstream stream(expression); - string token; - while (stream >> token) { - // Normally, tokens are whitespace-separated, but occasionally, the - // assignment operator is smashed up against the next token, i.e. - // $T0 $ebp 128 + =$eip $T0 4 + ^ =$ebp $T0 ^ = - // This has been observed in program strings produced by MSVS 2010 in LTO - // mode. - if (token.size() > 1 && token[0] == '=') { - if (!EvaluateToken("=", expression, assigned)) { - return false; - } - - if (!EvaluateToken(token.substr(1), expression, assigned)) { - return false; - } - } else if (!EvaluateToken(token, expression, assigned)) { - return false; - } - } - - return true; -} - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::Evaluate(const string &expression, - DictionaryValidityType *assigned) { - // Ensure that the stack is cleared before returning. - AutoStackClearer clearer(&stack_); - - if (!EvaluateInternal(expression, assigned)) - return false; - - // If there's anything left on the stack, it indicates incomplete execution. - // This is a failure case. If the stack is empty, evalution was complete - // and successful. - if (stack_.empty()) - return true; - - BPLOG(ERROR) << "Incomplete execution: " << expression; - return false; -} - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::EvaluateForValue(const string &expression, - ValueType *result) { - // Ensure that the stack is cleared before returning. - AutoStackClearer clearer(&stack_); - - if (!EvaluateInternal(expression, NULL)) - return false; - - // A successful execution should leave exactly one value on the stack. - if (stack_.size() != 1) { - BPLOG(ERROR) << "Expression yielded bad number of results: " - << "'" << expression << "'"; - return false; - } - - return PopValue(result); -} - -template<typename ValueType> -typename PostfixEvaluator<ValueType>::PopResult -PostfixEvaluator<ValueType>::PopValueOrIdentifier( - ValueType *value, string *identifier) { - // There needs to be at least one element on the stack to pop. - if (!stack_.size()) - return POP_RESULT_FAIL; - - string token = stack_.back(); - stack_.pop_back(); - - // First, try to treat the value as a literal. Literals may have leading - // '-' sign, and the entire remaining string must be parseable as - // ValueType. If this isn't possible, it can't be a literal, so treat it - // as an identifier instead. - // - // Some versions of the libstdc++, the GNU standard C++ library, have - // stream extractors for unsigned integer values that permit a leading - // '-' sign (6.0.13); others do not (6.0.9). Since we require it, we - // handle it explicitly here. - istringstream token_stream(token); - ValueType literal = ValueType(); - bool negative; - if (token_stream.peek() == '-') { - negative = true; - token_stream.get(); - } else { - negative = false; - } - if (token_stream >> literal && token_stream.peek() == EOF) { - if (value) { - *value = literal; - } - if (negative) - *value = -*value; - return POP_RESULT_VALUE; - } else { - if (identifier) { - *identifier = token; - } - return POP_RESULT_IDENTIFIER; - } -} - - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::PopValue(ValueType *value) { - ValueType literal = ValueType(); - string token; - PopResult result; - if ((result = PopValueOrIdentifier(&literal, &token)) == POP_RESULT_FAIL) { - return false; - } else if (result == POP_RESULT_VALUE) { - // This is the easy case. - *value = literal; - } else { // result == POP_RESULT_IDENTIFIER - // There was an identifier at the top of the stack. Resolve it to a - // value by looking it up in the dictionary. - typename DictionaryType::const_iterator iterator = - dictionary_->find(token); - if (iterator == dictionary_->end()) { - // The identifier wasn't found in the dictionary. Don't imply any - // default value, just fail. - BPLOG(INFO) << "Identifier " << token << " not in dictionary"; - return false; - } - - *value = iterator->second; - } - - return true; -} - - -template<typename ValueType> -bool PostfixEvaluator<ValueType>::PopValues(ValueType *value1, - ValueType *value2) { - return PopValue(value2) && PopValue(value1); -} - - -template<typename ValueType> -void PostfixEvaluator<ValueType>::PushValue(const ValueType &value) { - ostringstream token_stream; - token_stream << value; - stack_.push_back(token_stream.str()); -} - - -} // namespace google_breakpad - - -#endif // PROCESSOR_POSTFIX_EVALUATOR_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator.h b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator.h deleted file mode 100644 index 94b66190d..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator.h +++ /dev/null @@ -1,179 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// postfix_evaluator.h: Postfix (reverse Polish) notation expression evaluator. -// -// PostfixEvaluator evaluates an expression, using the expression itself -// in postfix (reverse Polish) notation and a dictionary mapping constants -// and variables to their values. The evaluator supports standard -// arithmetic operations, assignment into variables, and when an optional -// MemoryRange is provided, dereferencing. (Any unary key-to-value operation -// may be used with a MemoryRange implementation that returns the appropriate -// values, but PostfixEvaluator was written with dereferencing in mind.) -// -// The expression language is simple. Expressions are supplied as strings, -// with operands and operators delimited by whitespace. Operands may be -// either literal values suitable for ValueType, or constants or variables, -// which reference the dictionary. The supported binary operators are + -// (addition), - (subtraction), * (multiplication), / (quotient of division), -// % (modulus of division), and @ (data alignment). The alignment operator (@) -// accepts a value and an alignment size, and produces a result that is a -// multiple of the alignment size by truncating the input value. -// The unary ^ (dereference) operator is also provided. These operators -// allow any operand to be either a literal value, constant, or variable. -// Assignment (=) of any type of operand into a variable is also supported. -// -// The dictionary is provided as a map with string keys. Keys beginning -// with the '$' character are treated as variables. All other keys are -// treated as constants. Any results must be assigned into variables in the -// dictionary. These variables do not need to exist prior to calling -// Evaluate, unless used in an expression prior to being assigned to. The -// internal stack state is not made available after evaluation, and any -// values remaining on the stack are treated as evidence of incomplete -// execution and cause the evaluator to indicate failure. -// -// PostfixEvaluator is intended to support evaluation of "program strings" -// obtained from MSVC frame data debugging information in pdb files as -// returned by the DIA APIs. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_POSTFIX_EVALUATOR_H__ -#define PROCESSOR_POSTFIX_EVALUATOR_H__ - - -#include <map> -#include <string> -#include <vector> - -#include "common/using_std_string.h" - -namespace google_breakpad { - -using std::map; -using std::vector; - -class MemoryRegion; - -template<typename ValueType> -class PostfixEvaluator { - public: - typedef map<string, ValueType> DictionaryType; - typedef map<string, bool> DictionaryValidityType; - - // Create a PostfixEvaluator object that may be used (with Evaluate) on - // one or more expressions. PostfixEvaluator does not take ownership of - // either argument. |memory| may be NULL, in which case dereferencing - // (^) will not be supported. |dictionary| may be NULL, but evaluation - // will fail in that case unless set_dictionary is used before calling - // Evaluate. - PostfixEvaluator(DictionaryType *dictionary, const MemoryRegion *memory) - : dictionary_(dictionary), memory_(memory), stack_() {} - - // Evaluate the expression, starting with an empty stack. The results of - // execution will be stored in one (or more) variables in the dictionary. - // Returns false if any failures occur during execution, leaving - // variables in the dictionary in an indeterminate state. If assigned is - // non-NULL, any keys set in the dictionary as a result of evaluation - // will also be set to true in assigned, providing a way to determine if - // an expression modifies any of its input variables. - bool Evaluate(const string &expression, DictionaryValidityType *assigned); - - // Like Evaluate, but provides the value left on the stack to the - // caller. If evaluation succeeds and leaves exactly one value on - // the stack, pop that value, store it in *result, and return true. - // Otherwise, return false. - bool EvaluateForValue(const string &expression, ValueType *result); - - DictionaryType* dictionary() const { return dictionary_; } - - // Reset the dictionary. PostfixEvaluator does not take ownership. - void set_dictionary(DictionaryType *dictionary) {dictionary_ = dictionary; } - - private: - // Return values for PopValueOrIdentifier - enum PopResult { - POP_RESULT_FAIL = 0, - POP_RESULT_VALUE, - POP_RESULT_IDENTIFIER - }; - - // Retrieves the topmost literal value, constant, or variable from the - // stack. Returns POP_RESULT_VALUE if the topmost entry is a literal - // value, and sets |value| accordingly. Returns POP_RESULT_IDENTIFIER - // if the topmost entry is a constant or variable identifier, and sets - // |identifier| accordingly. Returns POP_RESULT_FAIL on failure, such - // as when the stack is empty. - PopResult PopValueOrIdentifier(ValueType *value, string *identifier); - - // Retrieves the topmost value on the stack. If the topmost entry is - // an identifier, the dictionary is queried for the identifier's value. - // Returns false on failure, such as when the stack is empty or when - // a nonexistent identifier is named. - bool PopValue(ValueType *value); - - // Retrieves the top two values on the stack, in the style of PopValue. - // value2 is popped before value1, so that value1 corresponds to the - // entry that was pushed prior to value2. Returns false on failure. - bool PopValues(ValueType *value1, ValueType *value2); - - // Pushes a new value onto the stack. - void PushValue(const ValueType &value); - - // Evaluate expression, updating *assigned if it is non-zero. Return - // true if evaluation completes successfully. Do not clear the stack - // upon successful evaluation. - bool EvaluateInternal(const string &expression, - DictionaryValidityType *assigned); - - bool EvaluateToken(const string &token, - const string &expression, - DictionaryValidityType *assigned); - - // The dictionary mapping constant and variable identifiers (strings) to - // values. Keys beginning with '$' are treated as variable names, and - // PostfixEvaluator is free to create and modify these keys. Weak pointer. - DictionaryType *dictionary_; - - // If non-NULL, the MemoryRegion used for dereference (^) operations. - // If NULL, dereferencing is unsupported and will fail. Weak pointer. - const MemoryRegion *memory_; - - // The stack contains state information as execution progresses. Values - // are pushed on to it as the expression string is read and as operations - // yield values; values are popped when used as operands to operators. - vector<string> stack_; -}; - -} // namespace google_breakpad - - -#endif // PROCESSOR_POSTFIX_EVALUATOR_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator_unittest.cc deleted file mode 100644 index f11898284..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/postfix_evaluator_unittest.cc +++ /dev/null @@ -1,403 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// postfix_evaluator_unittest.cc: Unit tests for PostfixEvaluator. -// -// Author: Mark Mentovai - -#include <assert.h> -#include <stdio.h> - -#include <map> -#include <string> - -#include "processor/postfix_evaluator-inl.h" - -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/processor/memory_region.h" -#include "processor/logging.h" - - -namespace { - - -using std::map; -using google_breakpad::MemoryRegion; -using google_breakpad::PostfixEvaluator; - - -// FakeMemoryRegion is used to test PostfixEvaluator's dereference (^) -// operator. The result of dereferencing a value is one greater than -// the value. -class FakeMemoryRegion : public MemoryRegion { - public: - virtual uint64_t GetBase() const { return 0; } - virtual uint32_t GetSize() const { return 0; } - virtual bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const { - *value = address + 1; - return true; - } - virtual bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const { - *value = address + 1; - return true; - } - virtual bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const { - *value = address + 1; - return true; - } - virtual bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const { - *value = address + 1; - return true; - } - virtual void Print() const { - assert(false); - } -}; - - -struct EvaluateTest { - // Expression passed to PostfixEvaluator::Evaluate. - const string expression; - - // True if the expression is expected to be evaluable, false if evaluation - // is expected to fail. - bool evaluable; -}; - - -struct EvaluateTestSet { - // The dictionary used for all tests in the set. - PostfixEvaluator<unsigned int>::DictionaryType *dictionary; - - // The list of tests. - const EvaluateTest *evaluate_tests; - - // The number of tests. - unsigned int evaluate_test_count; - - // Identifiers and their expected values upon completion of the Evaluate - // tests in the set. - map<string, unsigned int> *validate_data; -}; - - -struct EvaluateForValueTest { - // Expression passed to PostfixEvaluator::Evaluate. - const string expression; - - // True if the expression is expected to be evaluable, false if evaluation - // is expected to fail. - bool evaluable; - - // If evaluable, the value we expect it to yield. - unsigned int value; -}; - -static bool RunTests() { - // The first test set checks the basic operations and failure modes. - PostfixEvaluator<unsigned int>::DictionaryType dictionary_0; - const EvaluateTest evaluate_tests_0[] = { - { "$rAdd 2 2 + =", true }, // $rAdd = 2 + 2 = 4 - { "$rAdd $rAdd 2 + =", true }, // $rAdd = $rAdd + 2 = 6 - { "$rAdd 2 $rAdd + =", true }, // $rAdd = 2 + $rAdd = 8 - { "99", false }, // put some junk on the stack... - { "$rAdd2 2 2 + =", true }, // ...and make sure things still work - { "$rAdd2\t2\n2 + =", true }, // same but with different whitespace - { "$rAdd2 2 2 + = ", true }, // trailing whitespace - { " $rAdd2 2 2 + =", true }, // leading whitespace - { "$rAdd2 2 2 + =", true }, // extra whitespace - { "$T0 2 = +", false }, // too few operands for add - { "2 + =", false }, // too few operands for add - { "2 +", false }, // too few operands for add - { "+", false }, // too few operands for add - { "^", false }, // too few operands for dereference - { "=", false }, // too few operands for assignment - { "2 =", false }, // too few operands for assignment - { "2 2 + =", false }, // too few operands for assignment - { "2 2 =", false }, // can't assign into a literal - { "k 2 =", false }, // can't assign into a constant - { "2", false }, // leftover data on stack - { "2 2 +", false }, // leftover data on stack - { "$rAdd", false }, // leftover data on stack - { "0 $T1 0 0 + =", false }, // leftover data on stack - { "$T2 $T2 2 + =", false }, // can't operate on an undefined value - { "$rMul 9 6 * =", true }, // $rMul = 9 * 6 = 54 - { "$rSub 9 6 - =", true }, // $rSub = 9 - 6 = 3 - { "$rDivQ 9 6 / =", true }, // $rDivQ = 9 / 6 = 1 - { "$rDivM 9 6 % =", true }, // $rDivM = 9 % 6 = 3 - { "$rDeref 9 ^ =", true }, // $rDeref = ^9 = 10 (FakeMemoryRegion) - { "$rAlign 36 8 @ =", true }, // $rAlign = 36 @ 8 - { "$rAdd3 2 2 + =$rMul2 9 6 * =", true } // smashed-equals tokenization - }; - map<string, unsigned int> validate_data_0; - validate_data_0["$rAdd"] = 8; - validate_data_0["$rAdd2"] = 4; - validate_data_0["$rSub"] = 3; - validate_data_0["$rMul"] = 54; - validate_data_0["$rDivQ"] = 1; - validate_data_0["$rDivM"] = 3; - validate_data_0["$rDeref"] = 10; - validate_data_0["$rAlign"] = 32; - validate_data_0["$rAdd3"] = 4; - validate_data_0["$rMul2"] = 54; - - // The second test set simulates a couple of MSVC program strings. - // The data is fudged a little bit because the tests use FakeMemoryRegion - // instead of a real stack snapshot, but the program strings are real and - // the implementation doesn't know or care that the data is not real. - PostfixEvaluator<unsigned int>::DictionaryType dictionary_1; - dictionary_1["$ebp"] = 0xbfff0010; - dictionary_1["$eip"] = 0x10000000; - dictionary_1["$esp"] = 0xbfff0000; - dictionary_1[".cbSavedRegs"] = 4; - dictionary_1[".cbParams"] = 4; - dictionary_1[".raSearchStart"] = 0xbfff0020; - const EvaluateTest evaluate_tests_1[] = { - { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = " - "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", true }, - // Intermediate state: $T0 = 0xbfff0010, $eip = 0xbfff0015, - // $ebp = 0xbfff0011, $esp = 0xbfff0018, - // $L = 0xbfff000c, $P = 0xbfff001c - { "$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = " - "$L $T0 .cbSavedRegs - = $P $T0 8 + .cbParams + = $ebx $T0 28 - ^ =", - true }, - // Intermediate state: $T0 = 0xbfff0011, $eip = 0xbfff0016, - // $ebp = 0xbfff0012, $esp = 0xbfff0019, - // $L = 0xbfff000d, $P = 0xbfff001d, - // $ebx = 0xbffefff6 - { "$T0 $ebp = $T2 $esp = $T1 .raSearchStart = $eip $T1 ^ = $ebp $T0 = " - "$esp $T1 4 + = $L $T0 .cbSavedRegs - = $P $T1 4 + .cbParams + = " - "$ebx $T0 28 - ^ =", - true } - }; - map<string, unsigned int> validate_data_1; - validate_data_1["$T0"] = 0xbfff0012; - validate_data_1["$T1"] = 0xbfff0020; - validate_data_1["$T2"] = 0xbfff0019; - validate_data_1["$eip"] = 0xbfff0021; - validate_data_1["$ebp"] = 0xbfff0012; - validate_data_1["$esp"] = 0xbfff0024; - validate_data_1["$L"] = 0xbfff000e; - validate_data_1["$P"] = 0xbfff0028; - validate_data_1["$ebx"] = 0xbffefff7; - validate_data_1[".cbSavedRegs"] = 4; - validate_data_1[".cbParams"] = 4; - - EvaluateTestSet evaluate_test_sets[] = { - { &dictionary_0, evaluate_tests_0, - sizeof(evaluate_tests_0) / sizeof(EvaluateTest), &validate_data_0 }, - { &dictionary_1, evaluate_tests_1, - sizeof(evaluate_tests_1) / sizeof(EvaluateTest), &validate_data_1 }, - }; - - unsigned int evaluate_test_set_count = sizeof(evaluate_test_sets) / - sizeof(EvaluateTestSet); - - FakeMemoryRegion fake_memory; - PostfixEvaluator<unsigned int> postfix_evaluator = - PostfixEvaluator<unsigned int>(NULL, &fake_memory); - - for (unsigned int evaluate_test_set_index = 0; - evaluate_test_set_index < evaluate_test_set_count; - ++evaluate_test_set_index) { - EvaluateTestSet *evaluate_test_set = - &evaluate_test_sets[evaluate_test_set_index]; - const EvaluateTest *evaluate_tests = evaluate_test_set->evaluate_tests; - unsigned int evaluate_test_count = evaluate_test_set->evaluate_test_count; - - // The same dictionary will be used for each test in the set. Earlier - // tests can affect the state of the dictionary for later tests. - postfix_evaluator.set_dictionary(evaluate_test_set->dictionary); - - // Use a new validity dictionary for each test set. - PostfixEvaluator<unsigned int>::DictionaryValidityType assigned; - - for (unsigned int evaluate_test_index = 0; - evaluate_test_index < evaluate_test_count; - ++evaluate_test_index) { - const EvaluateTest *evaluate_test = &evaluate_tests[evaluate_test_index]; - - // Do the test. - bool result = postfix_evaluator.Evaluate(evaluate_test->expression, - &assigned); - if (result != evaluate_test->evaluable) { - fprintf(stderr, "FAIL: evaluate set %d/%d, test %d/%d, " - "expression \"%s\", expected %s, observed %s\n", - evaluate_test_set_index, evaluate_test_set_count, - evaluate_test_index, evaluate_test_count, - evaluate_test->expression.c_str(), - evaluate_test->evaluable ? "evaluable" : "not evaluable", - result ? "evaluted" : "not evaluated"); - return false; - } - } - - // Validate the results. - for (map<string, unsigned int>::const_iterator validate_iterator = - evaluate_test_set->validate_data->begin(); - validate_iterator != evaluate_test_set->validate_data->end(); - ++validate_iterator) { - const string identifier = validate_iterator->first; - unsigned int expected_value = validate_iterator->second; - - map<string, unsigned int>::const_iterator dictionary_iterator = - evaluate_test_set->dictionary->find(identifier); - - // The identifier must exist in the dictionary. - if (dictionary_iterator == evaluate_test_set->dictionary->end()) { - fprintf(stderr, "FAIL: evaluate test set %d/%d, " - "validate identifier \"%s\", " - "expected %d, observed not found\n", - evaluate_test_set_index, evaluate_test_set_count, - identifier.c_str(), expected_value); - return false; - } - - // The value in the dictionary must be the same as the expected value. - unsigned int observed_value = dictionary_iterator->second; - if (expected_value != observed_value) { - fprintf(stderr, "FAIL: evaluate test set %d/%d, " - "validate identifier \"%s\", " - "expected %d, observed %d\n", - evaluate_test_set_index, evaluate_test_set_count, - identifier.c_str(), expected_value, observed_value); - return false; - } - - // The value must be set in the "assigned" dictionary if it was a - // variable. It must not have been assigned if it was a constant. - bool expected_assigned = identifier[0] == '$'; - bool observed_assigned = false; - PostfixEvaluator<unsigned int>::DictionaryValidityType::const_iterator - iterator_assigned = assigned.find(identifier); - if (iterator_assigned != assigned.end()) { - observed_assigned = iterator_assigned->second; - } - if (expected_assigned != observed_assigned) { - fprintf(stderr, "FAIL: evaluate test set %d/%d, " - "validate assignment of \"%s\", " - "expected %d, observed %d\n", - evaluate_test_set_index, evaluate_test_set_count, - identifier.c_str(), expected_assigned, observed_assigned); - return false; - } - } - } - - // EvaluateForValue tests. - PostfixEvaluator<unsigned int>::DictionaryType dictionary_2; - dictionary_2["$ebp"] = 0xbfff0010; - dictionary_2["$eip"] = 0x10000000; - dictionary_2["$esp"] = 0xbfff0000; - dictionary_2[".cbSavedRegs"] = 4; - dictionary_2[".cbParams"] = 4; - dictionary_2[".raSearchStart"] = 0xbfff0020; - const EvaluateForValueTest evaluate_for_value_tests_2[] = { - { "28907223", true, 28907223 }, // simple constant - { "89854293 40010015 +", true, 89854293 + 40010015 }, // arithmetic - { "-870245 8769343 +", true, 7899098 }, // negative constants - { "$ebp $esp - $eip +", true, 0x10000010 }, // variable references - { "18929794 34015074", false, 0 }, // too many values - { "$ebp $ebp 4 - =", false, 0 }, // too few values - { "$new $eip = $new", true, 0x10000000 }, // make new variable - { "$new 4 +", true, 0x10000004 }, // see prior assignments - { ".cfa 42 = 10", false, 0 } // can't set constants - }; - const int evaluate_for_value_tests_2_size - = (sizeof (evaluate_for_value_tests_2) - / sizeof (evaluate_for_value_tests_2[0])); - map<string, unsigned int> validate_data_2; - validate_data_2["$eip"] = 0x10000000; - validate_data_2["$ebp"] = 0xbfff000c; - validate_data_2["$esp"] = 0xbfff0000; - validate_data_2["$new"] = 0x10000000; - validate_data_2[".cbSavedRegs"] = 4; - validate_data_2[".cbParams"] = 4; - validate_data_2[".raSearchStart"] = 0xbfff0020; - - postfix_evaluator.set_dictionary(&dictionary_2); - for (int i = 0; i < evaluate_for_value_tests_2_size; i++) { - const EvaluateForValueTest *test = &evaluate_for_value_tests_2[i]; - unsigned int result; - if (postfix_evaluator.EvaluateForValue(test->expression, &result) - != test->evaluable) { - fprintf(stderr, "FAIL: evaluate for value test %d, " - "expected evaluation to %s, but it %s\n", - i, test->evaluable ? "succeed" : "fail", - test->evaluable ? "failed" : "succeeded"); - return false; - } - if (test->evaluable && result != test->value) { - fprintf(stderr, "FAIL: evaluate for value test %d, " - "expected value to be 0x%x, but it was 0x%x\n", - i, test->value, result); - return false; - } - } - - for (map<string, unsigned int>::iterator v = validate_data_2.begin(); - v != validate_data_2.end(); v++) { - map<string, unsigned int>::iterator a = dictionary_2.find(v->first); - if (a == dictionary_2.end()) { - fprintf(stderr, "FAIL: evaluate for value dictionary check: " - "expected dict[\"%s\"] to be 0x%x, but it was unset\n", - v->first.c_str(), v->second); - return false; - } else if (a->second != v->second) { - fprintf(stderr, "FAIL: evaluate for value dictionary check: " - "expected dict[\"%s\"] to be 0x%x, but it was 0x%x\n", - v->first.c_str(), v->second, a->second); - return false; - } - dictionary_2.erase(a); - } - - map<string, unsigned int>::iterator remaining = dictionary_2.begin(); - if (remaining != dictionary_2.end()) { - fprintf(stderr, "FAIL: evaluation of test expressions put unexpected " - "values in dictionary:\n"); - for (; remaining != dictionary_2.end(); remaining++) - fprintf(stderr, " dict[\"%s\"] == 0x%x\n", - remaining->first.c_str(), remaining->second); - return false; - } - - return true; -} - - -} // namespace - - -int main(int argc, char **argv) { - BPLOG_INIT(&argc, &argv); - - return RunTests() ? 0 : 1; -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux.cc b/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux.cc deleted file mode 100644 index 3c0dea25d..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux.cc +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef __STDC_FORMAT_MACROS -#define __STDC_FORMAT_MACROS -#endif - -#include "google_breakpad/processor/proc_maps_linux.h" - -#include <fcntl.h> -#include <inttypes.h> -#include <stdio.h> - -#include "common/using_std_string.h" -#include "processor/logging.h" - -#if defined(OS_ANDROID) && !defined(__LP64__) -// In 32-bit mode, Bionic's inttypes.h defines PRI/SCNxPTR as an -// unsigned long int, which is incompatible with Bionic's stdint.h -// defining uintptr_t as an unsigned int: -// https://code.google.com/p/android/issues/detail?id=57218 -#undef SCNxPTR -#define SCNxPTR "x" -#endif - -namespace google_breakpad { - -bool ParseProcMaps(const string& input, - std::vector<MappedMemoryRegion>* regions_out) { - std::vector<MappedMemoryRegion> regions; - - // This isn't async safe nor terribly efficient, but it doesn't need to be at - // this point in time. - - // Split the string by newlines. - std::vector<string> lines; - string l = ""; - for (size_t i = 0; i < input.size(); i++) { - if (input[i] != '\n' && input[i] != '\r') { - l.push_back(input[i]); - } else if (l.size() > 0) { - lines.push_back(l); - l.clear(); - } - } - if (l.size() > 0) { - BPLOG(ERROR) << "Input doesn't end in newline"; - return false; - } - - for (size_t i = 0; i < lines.size(); ++i) { - MappedMemoryRegion region; - const char* line = lines[i].c_str(); - char permissions[5] = {'\0'}; // Ensure NUL-terminated string. - int path_index = 0; - - // Sample format from man 5 proc: - // - // address perms offset dev inode pathname - // 08048000-08056000 r-xp 00000000 03:0c 64593 /usr/sbin/gpm - // - // The final %n term captures the offset in the input string, which is used - // to determine the path name. It *does not* increment the return value. - // Refer to man 3 sscanf for details. - if (sscanf(line, "%" SCNx64 "-%" SCNx64 " %4c %" SCNx64" %hhx:%hhx %" - SCNd64 " %n", ®ion.start, ®ion.end, permissions, - ®ion.offset, ®ion.major_device, ®ion.minor_device, - ®ion.inode, &path_index) < 7) { - BPLOG(ERROR) << "sscanf failed for line: " << line; - return false; - } - - region.permissions = 0; - - if (permissions[0] == 'r') - region.permissions |= MappedMemoryRegion::READ; - else if (permissions[0] != '-') - return false; - - if (permissions[1] == 'w') - region.permissions |= MappedMemoryRegion::WRITE; - else if (permissions[1] != '-') - return false; - - if (permissions[2] == 'x') - region.permissions |= MappedMemoryRegion::EXECUTE; - else if (permissions[2] != '-') - return false; - - if (permissions[3] == 'p') - region.permissions |= MappedMemoryRegion::PRIVATE; - else if (permissions[3] != 's' && permissions[3] != 'S') // Shared memory. - return false; - - // Pushing then assigning saves us a string copy. - regions.push_back(region); - regions.back().path.assign(line + path_index); - regions.back().line.assign(line); - } - - regions_out->swap(regions); - return true; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux_unittest.cc deleted file mode 100644 index 466f23455..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/proc_maps_linux_unittest.cc +++ /dev/null @@ -1,251 +0,0 @@ -// Copyright (c) 2013 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "breakpad_googletest_includes.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/proc_maps_linux.h" - -namespace { - -TEST(ProcMapsTest, Empty) { - std::vector<google_breakpad::MappedMemoryRegion> regions; - EXPECT_TRUE(ParseProcMaps("", ®ions)); - EXPECT_EQ(0u, regions.size()); -} - -TEST(ProcMapsTest, NoSpaces) { - static const char kNoSpaces[] = - "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/cat\n"; - - std::vector<google_breakpad::MappedMemoryRegion> regions; - ASSERT_TRUE(ParseProcMaps(kNoSpaces, ®ions)); - ASSERT_EQ(1u, regions.size()); - - EXPECT_EQ(0x00400000u, regions[0].start); - EXPECT_EQ(0x0040b000u, regions[0].end); - EXPECT_EQ(0x00002200u, regions[0].offset); - EXPECT_EQ("/bin/cat", regions[0].path); -} - -TEST(ProcMapsTest, Spaces) { - static const char kSpaces[] = - "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/space cat\n"; - - std::vector<google_breakpad::MappedMemoryRegion> regions; - ASSERT_TRUE(ParseProcMaps(kSpaces, ®ions)); - ASSERT_EQ(1u, regions.size()); - - EXPECT_EQ(0x00400000u, regions[0].start); - EXPECT_EQ(0x0040b000u, regions[0].end); - EXPECT_EQ(0x00002200u, regions[0].offset); - EXPECT_EQ("/bin/space cat", regions[0].path); -} - -TEST(ProcMapsTest, NoNewline) { - static const char kNoSpaces[] = - "00400000-0040b000 r-xp 00002200 fc:00 794418 /bin/cat"; - - std::vector<google_breakpad::MappedMemoryRegion> regions; - ASSERT_FALSE(ParseProcMaps(kNoSpaces, ®ions)); -} - -TEST(ProcMapsTest, NoPath) { - static const char kNoPath[] = - "00400000-0040b000 rw-p 00000000 00:00 0 \n"; - - std::vector<google_breakpad::MappedMemoryRegion> regions; - ASSERT_TRUE(ParseProcMaps(kNoPath, ®ions)); - ASSERT_EQ(1u, regions.size()); - - EXPECT_EQ(0x00400000u, regions[0].start); - EXPECT_EQ(0x0040b000u, regions[0].end); - EXPECT_EQ(0x00000000u, regions[0].offset); - EXPECT_EQ("", regions[0].path); -} - -TEST(ProcMapsTest, Heap) { - static const char kHeap[] = - "022ac000-022cd000 rw-p 00000000 00:00 0 [heap]\n"; - - std::vector<google_breakpad::MappedMemoryRegion> regions; - ASSERT_TRUE(ParseProcMaps(kHeap, ®ions)); - ASSERT_EQ(1u, regions.size()); - - EXPECT_EQ(0x022ac000u, regions[0].start); - EXPECT_EQ(0x022cd000u, regions[0].end); - EXPECT_EQ(0x00000000u, regions[0].offset); - EXPECT_EQ("[heap]", regions[0].path); -} - -#if defined(ARCH_CPU_32_BITS) -TEST(ProcMapsTest, Stack32) { - static const char kStack[] = - "beb04000-beb25000 rw-p 00000000 00:00 0 [stack]\n"; - - std::vector<google_breakpad::MappedMemoryRegion> regions; - ASSERT_TRUE(ParseProcMaps(kStack, ®ions)); - ASSERT_EQ(1u, regions.size()); - - EXPECT_EQ(0xbeb04000u, regions[0].start); - EXPECT_EQ(0xbeb25000u, regions[0].end); - EXPECT_EQ(0x00000000u, regions[0].offset); - EXPECT_EQ("[stack]", regions[0].path); -} -#elif defined(ARCH_CPU_64_BITS) -TEST(ProcMapsTest, Stack64) { - static const char kStack[] = - "7fff69c5b000-7fff69c7d000 rw-p 00000000 00:00 0 [stack]\n"; - - std::vector<google_breakpad::MappedMemoryRegion> regions; - ASSERT_TRUE(ParseProcMaps(kStack, ®ions)); - ASSERT_EQ(1u, regions.size()); - - EXPECT_EQ(0x7fff69c5b000u, regions[0].start); - EXPECT_EQ(0x7fff69c7d000u, regions[0].end); - EXPECT_EQ(0x00000000u, regions[0].offset); - EXPECT_EQ("[stack]", regions[0].path); -} -#endif - -TEST(ProcMapsTest, Multiple) { - static const char kMultiple[] = - "00400000-0040b000 r-xp 00000000 fc:00 794418 /bin/cat\n" - "0060a000-0060b000 r--p 0000a000 fc:00 794418 /bin/cat\n" - "0060b000-0060c000 rw-p 0000b000 fc:00 794418 /bin/cat\n"; - - std::vector<google_breakpad::MappedMemoryRegion> regions; - ASSERT_TRUE(ParseProcMaps(kMultiple, ®ions)); - ASSERT_EQ(3u, regions.size()); - - EXPECT_EQ(0x00400000u, regions[0].start); - EXPECT_EQ(0x0040b000u, regions[0].end); - EXPECT_EQ(0x00000000u, regions[0].offset); - EXPECT_EQ("/bin/cat", regions[0].path); - - EXPECT_EQ(0x0060a000u, regions[1].start); - EXPECT_EQ(0x0060b000u, regions[1].end); - EXPECT_EQ(0x0000a000u, regions[1].offset); - EXPECT_EQ("/bin/cat", regions[1].path); - - EXPECT_EQ(0x0060b000u, regions[2].start); - EXPECT_EQ(0x0060c000u, regions[2].end); - EXPECT_EQ(0x0000b000u, regions[2].offset); - EXPECT_EQ("/bin/cat", regions[2].path); -} - -TEST(ProcMapsTest, Permissions) { - static struct { - const char* input; - uint8_t permissions; - } kTestCases[] = { - {"00400000-0040b000 ---s 00000000 fc:00 794418 /bin/cat\n", 0}, - {"00400000-0040b000 ---S 00000000 fc:00 794418 /bin/cat\n", 0}, - {"00400000-0040b000 r--s 00000000 fc:00 794418 /bin/cat\n", - google_breakpad::MappedMemoryRegion::READ}, - {"00400000-0040b000 -w-s 00000000 fc:00 794418 /bin/cat\n", - google_breakpad::MappedMemoryRegion::WRITE}, - {"00400000-0040b000 --xs 00000000 fc:00 794418 /bin/cat\n", - google_breakpad::MappedMemoryRegion::EXECUTE}, - {"00400000-0040b000 rwxs 00000000 fc:00 794418 /bin/cat\n", - google_breakpad::MappedMemoryRegion::READ - | google_breakpad::MappedMemoryRegion::WRITE - | google_breakpad::MappedMemoryRegion::EXECUTE}, - {"00400000-0040b000 ---p 00000000 fc:00 794418 /bin/cat\n", - google_breakpad::MappedMemoryRegion::PRIVATE}, - {"00400000-0040b000 r--p 00000000 fc:00 794418 /bin/cat\n", - google_breakpad::MappedMemoryRegion::READ - | google_breakpad::MappedMemoryRegion::PRIVATE}, - {"00400000-0040b000 -w-p 00000000 fc:00 794418 /bin/cat\n", - google_breakpad::MappedMemoryRegion::WRITE - | google_breakpad::MappedMemoryRegion::PRIVATE}, - {"00400000-0040b000 --xp 00000000 fc:00 794418 /bin/cat\n", - google_breakpad::MappedMemoryRegion::EXECUTE - | google_breakpad::MappedMemoryRegion::PRIVATE}, - {"00400000-0040b000 rwxp 00000000 fc:00 794418 /bin/cat\n", - google_breakpad::MappedMemoryRegion::READ - | google_breakpad::MappedMemoryRegion::WRITE - | google_breakpad::MappedMemoryRegion::EXECUTE - | google_breakpad::MappedMemoryRegion::PRIVATE}, - }; - - for (size_t i = 0; i < sizeof(kTestCases) / sizeof(kTestCases[0]); ++i) { - std::vector<google_breakpad::MappedMemoryRegion> regions; - EXPECT_TRUE(ParseProcMaps(kTestCases[i].input, ®ions)); - EXPECT_EQ(1u, regions.size()); - if (regions.empty()) - continue; - EXPECT_EQ(kTestCases[i].permissions, regions[0].permissions); - } -} - -TEST(ProcMapsTest, MissingFields) { - static const char* kTestCases[] = { - "00400000\n", // Missing end + beyond. - "00400000-0040b000\n", // Missing perms + beyond. - "00400000-0040b000 r-xp\n", // Missing offset + beyond. - "00400000-0040b000 r-xp 00000000\n", // Missing device + beyond. - "00400000-0040b000 r-xp 00000000 fc:00\n", // Missing inode + beyond. - "00400000-0040b000 00000000 fc:00 794418 /bin/cat\n", // Missing perms. - "00400000-0040b000 r-xp fc:00 794418 /bin/cat\n", // Missing offset. - "00400000-0040b000 r-xp 00000000 fc:00 /bin/cat\n", // Missing inode. - "00400000 r-xp 00000000 fc:00 794418 /bin/cat\n", // Missing end. - "-0040b000 r-xp 00000000 fc:00 794418 /bin/cat\n", // Missing start. - "00400000-0040b000 r-xp 00000000 794418 /bin/cat\n", // Missing device. - }; - - for (size_t i = 0; i < sizeof(kTestCases) / sizeof(kTestCases[0]); ++i) { - std::vector<google_breakpad::MappedMemoryRegion> regions; - EXPECT_FALSE(ParseProcMaps(kTestCases[i], ®ions)); - } -} - -TEST(ProcMapsTest, InvalidInput) { - static const char* kTestCases[] = { - "thisisal-0040b000 rwxp 00000000 fc:00 794418 /bin/cat\n", - "0040000d-linvalid rwxp 00000000 fc:00 794418 /bin/cat\n", - "00400000-0040b000 inpu 00000000 fc:00 794418 /bin/cat\n", - "00400000-0040b000 rwxp tforproc fc:00 794418 /bin/cat\n", - "00400000-0040b000 rwxp 00000000 ma:ps 794418 /bin/cat\n", - "00400000-0040b000 rwxp 00000000 fc:00 parse! /bin/cat\n", - }; - - for (size_t i = 0; i < sizeof(kTestCases) / sizeof(kTestCases[0]); ++i) { - std::vector<google_breakpad::MappedMemoryRegion> regions; - EXPECT_FALSE(ParseProcMaps(kTestCases[i], ®ions)); - } -} - -TEST(ProcMapsTest, ParseProcMapsEmptyString) { - std::vector<google_breakpad::MappedMemoryRegion> regions; - EXPECT_TRUE(ParseProcMaps("", ®ions)); - EXPECT_EQ(0ULL, regions.size()); -} - -// Testing a couple of remotely possible weird things in the input: -// - Line ending with \r\n or \n\r. -// - File name contains quotes. -// - File name has whitespaces. -TEST(ProcMapsTest, ParseProcMapsWeirdCorrectInput) { - std::vector<google_breakpad::MappedMemoryRegion> regions; - const string kContents = - "00400000-0040b000 r-xp 00000000 fc:00 2106562 " - " /bin/cat\r\n" - "7f53b7dad000-7f53b7f62000 r-xp 00000000 fc:00 263011 " - " /lib/x86_64-linux-gnu/libc-2.15.so\n\r" - "7f53b816d000-7f53b818f000 r-xp 00000000 fc:00 264284 " - " /lib/x86_64-linux-gnu/ld-2.15.so\n" - "7fff9c7ff000-7fff9c800000 r-xp 00000000 00:00 0 " - " \"vd so\"\n" - "ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 " - " [vsys call]\n"; - EXPECT_TRUE(ParseProcMaps(kContents, ®ions)); - EXPECT_EQ(5ULL, regions.size()); - EXPECT_EQ("/bin/cat", regions[0].path); - EXPECT_EQ("/lib/x86_64-linux-gnu/libc-2.15.so", regions[1].path); - EXPECT_EQ("/lib/x86_64-linux-gnu/ld-2.15.so", regions[2].path); - EXPECT_EQ("\"vd so\"", regions[3].path); - EXPECT_EQ("[vsys call]", regions[4].path); -} - -} // namespace diff --git a/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc b/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc deleted file mode 100644 index 5a5cd7f62..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/process_state.cc +++ /dev/null @@ -1,69 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// process_state.cc: A snapshot of a process, in a fully-digested state. -// -// See process_state.h for documentation. -// -// Author: Mark Mentovai - -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_modules.h" - -namespace google_breakpad { - -ProcessState::~ProcessState() { - Clear(); -} - -void ProcessState::Clear() { - time_date_stamp_ = 0; - process_create_time_ = 0; - crashed_ = false; - crash_reason_.clear(); - crash_address_ = 0; - assertion_.clear(); - requesting_thread_ = -1; - for (vector<CallStack *>::const_iterator iterator = threads_.begin(); - iterator != threads_.end(); - ++iterator) { - delete *iterator; - } - threads_.clear(); - system_info_.Clear(); - // modules_without_symbols_ and modules_with_corrupt_symbols_ DO NOT own - // the underlying CodeModule pointers. Just clear the vectors. - modules_without_symbols_.clear(); - modules_with_corrupt_symbols_.clear(); - delete modules_; - modules_ = NULL; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/processor.gyp b/toolkit/crashreporter/google-breakpad/src/processor/processor.gyp deleted file mode 100644 index 083a3237f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/processor.gyp +++ /dev/null @@ -1,184 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'includes': [ - '../build/common.gypi', - 'processor_tools.gypi', - ], - 'targets': [ - { - 'target_name': 'processor', - 'type': 'static_library', - 'sources': [ - 'address_map-inl.h', - 'address_map.h', - 'basic_code_module.h', - 'basic_code_modules.cc', - 'basic_code_modules.h', - 'basic_source_line_resolver.cc', - 'basic_source_line_resolver_types.h', - 'call_stack.cc', - 'cfi_frame_info-inl.h', - 'cfi_frame_info.cc', - 'cfi_frame_info.h', - 'contained_range_map-inl.h', - 'contained_range_map.h', - 'disassembler_x86.cc', - 'disassembler_x86.h', - 'dump_context.cc', - 'dump_object.cc', - 'exploitability.cc', - 'exploitability_linux.cc', - 'exploitability_linux.h', - 'exploitability_win.cc', - 'exploitability_win.h', - 'fast_source_line_resolver.cc', - 'fast_source_line_resolver_types.h', - 'linked_ptr.h', - 'logging.cc', - 'logging.h', - 'map_serializers-inl.h', - 'map_serializers.h', - 'microdump_processor.cc', - 'minidump.cc', - 'minidump_processor.cc', - 'module_comparer.cc', - 'module_comparer.h', - 'module_factory.h', - 'module_serializer.cc', - 'module_serializer.h', - 'pathname_stripper.cc', - 'pathname_stripper.h', - 'postfix_evaluator-inl.h', - 'postfix_evaluator.h', - 'proc_maps_linux.cc', - 'process_state.cc', - 'range_map-inl.h', - 'range_map.h', - 'simple_serializer-inl.h', - 'simple_serializer.h', - 'simple_symbol_supplier.cc', - 'simple_symbol_supplier.h', - 'source_line_resolver_base.cc', - 'source_line_resolver_base_types.h', - 'stack_frame_cpu.cc', - 'stack_frame_symbolizer.cc', - 'stackwalk_common.cc', - 'stackwalk_common.h', - 'stackwalker.cc', - 'stackwalker_address_list.cc', - 'stackwalker_address_list.h', - 'stackwalker_amd64.cc', - 'stackwalker_amd64.h', - 'stackwalker_arm.cc', - 'stackwalker_arm.h', - 'stackwalker_arm64.cc', - 'stackwalker_arm64.h', - 'stackwalker_mips.cc', - 'stackwalker_mips.h', - 'stackwalker_ppc.cc', - 'stackwalker_ppc.h', - 'stackwalker_ppc64.cc', - 'stackwalker_ppc64.h', - 'stackwalker_selftest.cc', - 'stackwalker_sparc.cc', - 'stackwalker_sparc.h', - 'stackwalker_x86.cc', - 'stackwalker_x86.h', - 'static_address_map-inl.h', - 'static_address_map.h', - 'static_contained_range_map-inl.h', - 'static_contained_range_map.h', - 'static_map-inl.h', - 'static_map.h', - 'static_map_iterator-inl.h', - 'static_map_iterator.h', - 'static_range_map-inl.h', - 'static_range_map.h', - 'symbolic_constants_win.cc', - 'symbolic_constants_win.h', - 'synth_minidump.cc', - 'synth_minidump.h', - 'tokenize.cc', - 'tokenize.h', - 'windows_frame_info.h', - ], - 'include_dirs': [ - '..', - ], - 'dependencies': [ - '../common/common.gyp:common', - '../third_party/libdisasm/libdisasm.gyp:libdisasm', - ], - }, - { - 'target_name': 'processor_unittests', - 'type': 'executable', - 'sources': [ - 'address_map_unittest.cc', - 'basic_source_line_resolver_unittest.cc', - 'cfi_frame_info_unittest.cc', - 'contained_range_map_unittest.cc', - 'disassembler_x86_unittest.cc', - 'exploitability_unittest.cc', - 'fast_source_line_resolver_unittest.cc', - 'map_serializers_unittest.cc', - 'microdump_processor_unittest.cc', - 'minidump_processor_unittest.cc', - 'minidump_unittest.cc', - 'pathname_stripper_unittest.cc', - 'postfix_evaluator_unittest.cc', - 'range_map_shrink_down_unittest.cc', - 'range_map_unittest.cc', - 'stackwalker_address_list_unittest.cc', - 'stackwalker_amd64_unittest.cc', - 'stackwalker_arm64_unittest.cc', - 'stackwalker_arm_unittest.cc', - 'stackwalker_mips_unittest.cc', - 'stackwalker_mips64_unittest.cc', - 'stackwalker_unittest_utils.h', - 'stackwalker_x86_unittest.cc', - 'static_address_map_unittest.cc', - 'static_contained_range_map_unittest.cc', - 'static_map_unittest.cc', - 'static_range_map_unittest.cc', - 'synth_minidump_unittest.cc', - 'synth_minidump_unittest_data.h', - ], - 'include_dirs': [ - '..', - ], - 'dependencies': [ - 'processor', - '../build/testing.gypi:gmock', - '../build/testing.gypi:gtest', - ], - }, - ], -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/processor_tools.gypi b/toolkit/crashreporter/google-breakpad/src/processor/processor_tools.gypi deleted file mode 100644 index ecb450d60..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/processor_tools.gypi +++ /dev/null @@ -1,57 +0,0 @@ -# Copyright 2014 Google Inc. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of Google Inc. nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -{ - 'target_defaults': { - 'include_dirs': [ - '..', - ], - }, - 'targets': [ - { - 'target_name': 'minidump_dump', - 'type': 'executable', - 'sources': [ - 'minidump_dump.cc', - ], - 'dependencies': [ - 'processor', - ], - }, - { - 'target_name': 'minidump_stackwalk', - 'type': 'executable', - 'sources': [ - 'minidump_stackwalk.cc', - ], - 'dependencies': [ - 'processor', - ], - }, - ], -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/proto/README b/toolkit/crashreporter/google-breakpad/src/processor/proto/README deleted file mode 100644 index df37b6f39..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/proto/README +++ /dev/null @@ -1,20 +0,0 @@ -If you wish to use these protobufs, you must generate their source files -using protoc from the protobuf project (http://code.google.com/p/protobuf/). - ------ -Troubleshooting for Protobuf: - -Install: -If you are getting permission errors install, make sure you are not trying to -install from an NFS. - - -Running protoc: -protoc: error while loading shared libraries: libprotobuf.so.0: cannot open -shared object file: No such file or directory - -The issue is that Ubuntu 8.04 doesn't include /usr/local/lib in -library paths. - -To fix it for your current terminal session, just type in -export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib diff --git a/toolkit/crashreporter/google-breakpad/src/processor/proto/process_state.proto b/toolkit/crashreporter/google-breakpad/src/processor/proto/process_state.proto deleted file mode 100644 index d3e02dc3f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/proto/process_state.proto +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// process_state_proto.proto: A client proto representation of a process, -// in a fully-digested state. -// -// Derived from earlier struct and class based models of a client-side -// processed minidump found under src/google_breakpad/processor. The -// file process_state.h holds the top level representation of this model, -// supported by additional classes. We've added a proto representation -// to ease serialization and parsing for server-side storage of crash -// reports processed on the client. -// -// Author: Jess Gray - -syntax = "proto2"; - -package google_breakpad; - -// A proto representation of a process, in a fully-digested state. -// See src/google_breakpad/processor/process_state.h -message ProcessStateProto { - // Next value: 14 - - // The time-date stamp of the original minidump (time_t format) - optional int64 time_date_stamp = 1; - - // The time-date stamp when the process was created (time_t format) - optional int64 process_create_time = 13; - - message Crash { - // The type of crash. OS- and possibly CPU- specific. For example, - // "EXCEPTION_ACCESS_VIOLATION" (Windows), "EXC_BAD_ACCESS / - // KERN_INVALID_ADDRESS" (Mac OS X), "SIGSEGV" (other Unix). - required string reason = 1; - - // If crash_reason implicates memory, the memory address that caused the - // crash. For data access errors, this will be the data address that - // caused the fault. For code errors, this will be the address of the - // instruction that caused the fault. - required int64 address = 2; - } - optional Crash crash = 2; - - - // If there was an assertion that was hit, a textual representation - // of that assertion, possibly including the file and line at which - // it occurred. - optional string assertion = 3; - - // The index of the thread that requested a dump be written in the - // threads vector. If a dump was produced as a result of a crash, this - // will point to the thread that crashed. If the dump was produced as - // by user code without crashing, and the dump contains extended Breakpad - // information, this will point to the thread that requested the dump. - optional int32 requesting_thread = 4; - - message Thread { - // Stack for the given thread - repeated StackFrame frames = 1; - } - - // Stacks for each thread (except possibly the exception handler - // thread) at the time of the crash. - repeated Thread threads = 5; - - // The modules that were loaded into the process represented by the - // ProcessState. - repeated CodeModule modules = 6; - - // System Info: OS and CPU - - // A string identifying the operating system, such as "Windows NT", - // "Mac OS X", or "Linux". If the information is present in the dump but - // its value is unknown, this field will contain a numeric value. If - // the information is not present in the dump, this field will be empty. - optional string os = 7; - - // A short form of the os string, using lowercase letters and no spaces, - // suitable for use in a filesystem. Possible values are "windows", - // "mac", and "linux". Empty if the information is not present in the dump - // or if the OS given by the dump is unknown. The values stored in this - // field should match those used by MinidumpSystemInfo::GetOS. - optional string os_short = 8; - - // A string identifying the version of the operating system, such as - // "5.1.2600 Service Pack 2" or "10.4.8 8L2127". If the dump does not - // contain this information, this field will be empty. - optional string os_version = 9; - - // A string identifying the basic CPU family, such as "x86" or "ppc". - // If this information is present in the dump but its value is unknown, - // this field will contain a numeric value. If the information is not - // present in the dump, this field will be empty. The values stored in - // this field should match those used by MinidumpSystemInfo::GetCPU. - optional string cpu = 10; - - // A string further identifying the specific CPU, such as - // "GenuineIntel level 6 model 13 stepping 8". If the information is not - // present in the dump, or additional identifying information is not - // defined for the CPU family, this field will be empty. - optional string cpu_info = 11; - - // The number of processors in the system. Will be greater than one for - // multi-core systems. - optional int32 cpu_count = 12; - - // Leave the ability to add the raw minidump to this representation -} - - -// Represents a single frame in a stack -// See src/google_breakpad/processor/code_module.h -message StackFrame { - // Next value: 8 - - // The program counter location as an absolute virtual address. For the - // innermost called frame in a stack, this will be an exact program counter - // or instruction pointer value. For all other frames, this will be within - // the instruction that caused execution to branch to a called function, - // but may not necessarily point to the exact beginning of that instruction. - required int64 instruction = 1; - - // The module in which the instruction resides. - optional CodeModule module = 2; - - // The function name, may be omitted if debug symbols are not available. - optional string function_name = 3; - - // The start address of the function, may be omitted if debug symbols - // are not available. - optional int64 function_base = 4; - - // The source file name, may be omitted if debug symbols are not available. - optional string source_file_name = 5; - - // The (1-based) source line number, may be omitted if debug symbols are - // not available. - optional int32 source_line = 6; - - // The start address of the source line, may be omitted if debug symbols - // are not available. - optional int64 source_line_base = 7; -} - - -// Carries information about code modules that are loaded into a process. -// See src/google_breakpad/processor/code_module.h -message CodeModule { - // Next value: 8 - - // The base address of this code module as it was loaded by the process. - optional int64 base_address = 1; - - // The size of the code module. - optional int64 size = 2; - - // The path or file name that the code module was loaded from. - optional string code_file = 3; - - // An identifying string used to discriminate between multiple versions and - // builds of the same code module. This may contain a uuid, timestamp, - // version number, or any combination of this or other information, in an - // implementation-defined format. - optional string code_identifier = 4; - - // The filename containing debugging information associated with the code - // module. If debugging information is stored in a file separate from the - // code module itself (as is the case when .pdb or .dSYM files are used), - // this will be different from code_file. If debugging information is - // stored in the code module itself (possibly prior to stripping), this - // will be the same as code_file. - optional string debug_file = 5; - - // An identifying string similar to code_identifier, but identifies a - // specific version and build of the associated debug file. This may be - // the same as code_identifier when the debug_file and code_file are - // identical or when the same identifier is used to identify distinct - // debug and code files. - optional string debug_identifier = 6; - - // A human-readable representation of the code module's version. - optional string version = 7; -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h deleted file mode 100644 index 9fe74c502..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/range_map-inl.h +++ /dev/null @@ -1,272 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// range_map-inl.h: Range map implementation. -// -// See range_map.h for documentation. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_RANGE_MAP_INL_H__ -#define PROCESSOR_RANGE_MAP_INL_H__ - - -#include <assert.h> - -#include "processor/range_map.h" -#include "processor/linked_ptr.h" -#include "processor/logging.h" - - -namespace google_breakpad { - -template<typename AddressType, typename EntryType> -void RangeMap<AddressType, EntryType>::SetEnableShrinkDown( - bool 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> -bool RangeMap<AddressType, EntryType>::StoreRange(const AddressType &base, - const AddressType &size, - const EntryType &entry) { - return StoreRangeInternal(base, 0 /* delta */, size, entry); -} - -template<typename AddressType, typename EntryType> -bool RangeMap<AddressType, EntryType>::StoreRangeInternal( - const AddressType &base, const AddressType &delta, - const AddressType &size, const EntryType &entry) { - AddressType high = base + (size - 1); - - // Check for undersize or overflow. - if (size <= 0 || high < base) { - // The processor will hit this case too frequently with common symbol - // files in the size == 0 case, which is more suited to a DEBUG channel. - // Filter those out since there's no DEBUG channel at the moment. - BPLOG_IF(INFO, size != 0) << "StoreRangeInternal failed, " - << HexString(base) << "+" << HexString(size) - << ", " << HexString(high) - << ", delta: " << HexString(delta); - return false; - } - - // Ensure that this range does not overlap with another one already in the - // map. - MapConstIterator iterator_base = map_.lower_bound(base); - MapConstIterator iterator_high = map_.lower_bound(high); - - if (iterator_base != iterator_high) { - // Some other range begins in the space used by this range. It may be - // contained within the space used by this range, or it may extend lower. - // If enable_shrink_down_ is true, shrink the current range down, otherwise - // this is an error. - if (enable_shrink_down_) { - AddressType additional_delta = iterator_base->first - base + 1; - return StoreRangeInternal(base + additional_delta, - delta + additional_delta, - size - additional_delta, entry); - } else { - // The processor hits this case too frequently with common symbol files. - // This is most appropriate for a DEBUG channel, but since none exists - // now simply comment out this logging. - // AddressType other_base = iterator_base->second.base(); - // AddressType other_size = iterator_base->first - other_base + 1; - // BPLOG(INFO) << "StoreRangeInternal failed, an existing range is " - // << "overlapping with the new range: new " - // << HexString(base) << "+" << HexString(size) - // << ", existing " << HexString(other_base) << "+" - // << HexString(other_size); - return false; - } - } - - if (iterator_high != map_.end()) { - if (iterator_high->second.base() <= high) { - // The range above this one overlaps with this one. It may fully - // contain this range, or it may begin within this range and extend - // higher. If enable_shrink_down_ is true, shrink the other range down, - // otherwise this is an error. - if (enable_shrink_down_ && iterator_high->first > high) { - // Shrink the other range down. - AddressType other_high = iterator_high->first; - AddressType additional_delta = - high - iterator_high->second.base() + 1; - EntryType other_entry; - AddressType other_base = AddressType(); - AddressType other_size = AddressType(); - AddressType other_delta = AddressType(); - RetrieveRange(other_high, &other_entry, &other_base, &other_delta, - &other_size); - map_.erase(iterator_high); - map_.insert(MapValue(other_high, - Range(other_base + additional_delta, - other_delta + additional_delta, - other_entry))); - // Retry to store this range. - return StoreRangeInternal(base, delta, size, entry); - } else { - // The processor hits this case too frequently with common symbol files. - // This is most appropriate for a DEBUG channel, but since none exists - // now simply comment out this logging. - // - // AddressType other_base = iterator_high->second.base(); - // AddressType other_size = iterator_high->first - other_base + 1; - // BPLOG(INFO) << "StoreRangeInternal failed, an existing range " - // << "contains or extends higher than the new range: new " - // << HexString(base) << "+" << HexString(size) - // << ", existing " << HexString(other_base) << "+" - // << HexString(other_size); - return false; - } - } - } - - // Store the range in the map by its high address, so that lower_bound can - // be used to quickly locate a range by address. - map_.insert(MapValue(high, Range(base, delta, entry))); - return true; -} - - -template<typename AddressType, typename EntryType> -bool RangeMap<AddressType, EntryType>::RetrieveRange( - const AddressType &address, EntryType *entry, AddressType *entry_base, - AddressType *entry_delta, AddressType *entry_size) const { - BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRange requires |entry|"; - assert(entry); - - MapConstIterator iterator = map_.lower_bound(address); - if (iterator == map_.end()) - return false; - - // The map is keyed by the high address of each range, so |address| is - // guaranteed to be lower than the range's high address. If |range| is - // not directly preceded by another range, it's possible for address to - // be below the range's low address, though. When that happens, address - // references something not within any range, so return false. - if (address < iterator->second.base()) - return false; - - *entry = iterator->second.entry(); - if (entry_base) - *entry_base = iterator->second.base(); - if (entry_delta) - *entry_delta = iterator->second.delta(); - if (entry_size) - *entry_size = iterator->first - iterator->second.base() + 1; - - return true; -} - - -template<typename AddressType, typename EntryType> -bool RangeMap<AddressType, EntryType>::RetrieveNearestRange( - const AddressType &address, EntryType *entry, AddressType *entry_base, - AddressType *entry_delta, AddressType *entry_size) const { - BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveNearestRange requires |entry|"; - assert(entry); - - // If address is within a range, RetrieveRange can handle it. - if (RetrieveRange(address, entry, entry_base, entry_delta, entry_size)) - return true; - - // upper_bound gives the first element whose key is greater than address, - // but we want the first element whose key is less than or equal to address. - // Decrement the iterator to get there, but not if the upper_bound already - // points to the beginning of the map - in that case, address is lower than - // the lowest stored key, so return false. - MapConstIterator iterator = map_.upper_bound(address); - if (iterator == map_.begin()) - return false; - --iterator; - - *entry = iterator->second.entry(); - if (entry_base) - *entry_base = iterator->second.base(); - if (entry_delta) - *entry_delta = iterator->second.delta(); - if (entry_size) - *entry_size = iterator->first - iterator->second.base() + 1; - - return true; -} - - -template<typename AddressType, typename EntryType> -bool RangeMap<AddressType, EntryType>::RetrieveRangeAtIndex( - int index, EntryType *entry, AddressType *entry_base, - AddressType *entry_delta, AddressType *entry_size) const { - BPLOG_IF(ERROR, !entry) << "RangeMap::RetrieveRangeAtIndex requires |entry|"; - assert(entry); - - if (index >= GetCount()) { - BPLOG(ERROR) << "Index out of range: " << index << "/" << GetCount(); - return false; - } - - // Walk through the map. Although it's ordered, it's not a vector, so it - // can't be addressed directly by index. - MapConstIterator iterator = map_.begin(); - for (int this_index = 0; this_index < index; ++this_index) - ++iterator; - - *entry = iterator->second.entry(); - if (entry_base) - *entry_base = iterator->second.base(); - if (entry_delta) - *entry_delta = iterator->second.delta(); - if (entry_size) - *entry_size = iterator->first - iterator->second.base() + 1; - - return true; -} - - -template<typename AddressType, typename EntryType> -int RangeMap<AddressType, EntryType>::GetCount() const { - return map_.size(); -} - - -template<typename AddressType, typename EntryType> -void RangeMap<AddressType, EntryType>::Clear() { - map_.clear(); -} - - -} // namespace google_breakpad - - -#endif // PROCESSOR_RANGE_MAP_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/range_map.h b/toolkit/crashreporter/google-breakpad/src/processor/range_map.h deleted file mode 100644 index d90a67327..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/range_map.h +++ /dev/null @@ -1,161 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// range_map.h: Range maps. -// -// A range map associates a range of addresses with a specific object. This -// is useful when certain objects of variable size are located within an -// address space. The range map makes it simple to determine which object is -// associated with a specific address, which may be any address within the -// range associated with an object. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_RANGE_MAP_H__ -#define PROCESSOR_RANGE_MAP_H__ - - -#include <map> - - -namespace google_breakpad { - -// Forward declarations (for later friend declarations of specialized template). -template<class, class> class RangeMapSerializer; - -template<typename AddressType, typename EntryType> -class RangeMap { - public: - RangeMap() : enable_shrink_down_(false), map_() {} - - // |enable_shrink_down| tells whether overlapping ranges can be shrunk down. - // If true, then adding a new range that overlaps with an existing one can - // be a successful operation. The range which ends at the higher address - // will be shrunk down by moving its start position to a higher address so - // that it does not overlap anymore. - void SetEnableShrinkDown(bool enable_shrink_down); - bool IsShrinkDownEnabled() const; - - // 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 - // stored in the map. If enable_shrink_down is true and there is an overlap - // between the current range and some other range (already in the map), - // shrink down the range which ends at a higher address. - bool StoreRange(const AddressType &base, const AddressType &size, - const EntryType &entry); - - // Locates the range encompassing the supplied address. If there is no such - // range, returns false. entry_base, entry_delta, and entry_size, if - // non-NULL, are set to the base, delta, and size of the entry's range. - // A positive entry delta (> 0) indicates that there was an overlap and the - // entry was shrunk down (original start address was increased by delta). - bool RetrieveRange(const AddressType &address, EntryType *entry, - AddressType *entry_base, AddressType *entry_delta, - AddressType *entry_size) const; - - // Locates the range encompassing the supplied address, if one exists. - // If no range encompasses the supplied address, locates the nearest range - // to the supplied address that is lower than the address. Returns false - // if no range meets these criteria. entry_base, entry_delta, and entry_size, - // if non-NULL, are set to the base, delta, and size of the entry's range. - // A positive entry delta (> 0) indicates that there was an overlap and the - // entry was shrunk down (original start address was increased by delta). - bool RetrieveNearestRange(const AddressType &address, EntryType *entry, - AddressType *entry_base, AddressType *entry_delta, - AddressType *entry_size) const; - - // Treating all ranges as a list ordered by the address spaces that they - // occupy, locates the range at the index specified by index. Returns - // false if index is larger than the number of ranges stored. entry_base, - // entry_delta, and entry_size, if non-NULL, are set to the base, delta, and - // size of the entry's range. - // A positive entry delta (> 0) indicates that there was an overlap and the - // entry was shrunk down (original start address was increased by delta). - // - // RetrieveRangeAtIndex is not optimized for speedy operation. - bool RetrieveRangeAtIndex(int index, EntryType *entry, - AddressType *entry_base, AddressType *entry_delta, - AddressType *entry_size) const; - - // Returns the number of ranges stored in the RangeMap. - int GetCount() const; - - // Empties the range map, restoring it to the state it was when it was - // initially created. - void Clear(); - - private: - // Friend declarations. - friend class ModuleComparer; - friend class RangeMapSerializer<AddressType, EntryType>; - - // Same a StoreRange() with the only exception that the |delta| can be - // passed in. - bool StoreRangeInternal(const AddressType &base, const AddressType &delta, - const AddressType &size, const EntryType &entry); - - class Range { - public: - Range(const AddressType &base, const AddressType &delta, - const EntryType &entry) - : base_(base), delta_(delta), entry_(entry) {} - - AddressType base() const { return base_; } - AddressType delta() const { return delta_; } - EntryType entry() const { return entry_; } - - private: - // The base address of the range. The high address does not need to - // be stored, because RangeMap uses it as the key to the map. - const AddressType base_; - - // The delta when the range is shrunk down. - const AddressType delta_; - - // The entry corresponding to a range. - const EntryType entry_; - }; - - // Convenience types. - typedef std::map<AddressType, Range> AddressToRangeMap; - typedef typename AddressToRangeMap::const_iterator MapConstIterator; - typedef typename AddressToRangeMap::value_type MapValue; - - // Whether overlapping ranges can be shrunk down. - bool enable_shrink_down_; - - // Maps the high address of each range to a EntryType. - AddressToRangeMap map_; -}; - - -} // namespace google_breakpad - - -#endif // PROCESSOR_RANGE_MAP_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/range_map_shrink_down_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/range_map_shrink_down_unittest.cc deleted file mode 100644 index 8dd0e709b..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/range_map_shrink_down_unittest.cc +++ /dev/null @@ -1,355 +0,0 @@ -// Copyright (c) 2016, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE - -// range_map_shrink_down_unittest.cc: Unit tests for RangeMap that specifically -// test shrink down when ranges overlap. -// -// Author: Ivan Penkov - -#include <limits.h> -#include <stdio.h> - -#include "processor/range_map-inl.h" - -#include "breakpad_googletest_includes.h" -#include "common/scoped_ptr.h" -#include "processor/linked_ptr.h" -#include "processor/logging.h" - -namespace { - -using google_breakpad::linked_ptr; -using google_breakpad::scoped_ptr; -using google_breakpad::RangeMap; - -// A CountedObject holds an int. A global (not thread safe!) count of -// allocated CountedObjects is maintained to help test memory management. -class CountedObject { - public: - explicit CountedObject(int id) : id_(id) { ++count_; } - ~CountedObject() { --count_; } - - static int count() { return count_; } - int id() const { return id_; } - - private: - static int count_; - int id_; -}; - -int CountedObject::count_; - -typedef int AddressType; -typedef RangeMap<AddressType, linked_ptr<CountedObject>> TestMap; - -// Same range cannot be stored wice. -TEST(RangeMap, TestShinkDown_SameRange) { - TestMap range_map; - range_map.SetEnableShrinkDown(true); - linked_ptr<CountedObject> object_1(new CountedObject(1)); - EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */, - object_1)); - - // Same range cannot be stored wice. - linked_ptr<CountedObject> object_2(new CountedObject(2)); - EXPECT_FALSE(range_map.StoreRange(0 /* base address */, 100 /* size */, - object_2)); -} - -// If a range is completely contained by another range, then the larger range -// should be shrinked down. -TEST(RangeMap, TestShinkDown_CompletelyContained) { - TestMap range_map; - range_map.SetEnableShrinkDown(true); - // Larger range is added first. - linked_ptr<CountedObject> object_1(new CountedObject(1)); - EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */, - object_1)); - // Smaller (contained) range is added second. - linked_ptr<CountedObject> object_2(new CountedObject(2)); - EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 80 /* size */, - object_2)); - linked_ptr<CountedObject> object; - AddressType retrieved_base = AddressType(); - AddressType retrieved_delta = AddressType(); - AddressType retrieved_size = AddressType(); - // The first range contains the second, so the first range should have been - // shrunk to [90, 99]. Range [0, 9] should be free. - EXPECT_FALSE(range_map.RetrieveRange(0, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_FALSE(range_map.RetrieveRange(9, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_TRUE(range_map.RetrieveRange(90, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(1, object->id()); - EXPECT_EQ(90, retrieved_base); - EXPECT_EQ(90, retrieved_delta); - EXPECT_EQ(10, retrieved_size); - // Validate the properties of the smaller range (should be untouched). - EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(2, object->id()); - EXPECT_EQ(10, retrieved_base); - EXPECT_EQ(0, retrieved_delta); - EXPECT_EQ(80, retrieved_size); -} - -// Same as the previous test, however the larger range is added second. -TEST(RangeMap, TestShinkDown_CompletelyContained_LargerAddedSecond) { - TestMap range_map; - range_map.SetEnableShrinkDown(true); - // Smaller (contained) range is added first. - linked_ptr<CountedObject> object_1(new CountedObject(1)); - EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 80 /* size */, - object_1)); - // Larger range is added second. - linked_ptr<CountedObject> object_2(new CountedObject(2)); - EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */, - object_2)); - linked_ptr<CountedObject> object; - AddressType retrieved_base = AddressType(); - AddressType retrieved_delta = AddressType(); - AddressType retrieved_size = AddressType(); - // The second range contains the first, so the second range should have been - // shrunk to [90, 99]. Range [0, 9] should be free. - EXPECT_FALSE(range_map.RetrieveRange(0, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_FALSE(range_map.RetrieveRange(9, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_TRUE(range_map.RetrieveRange(90, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(2, object->id()); - EXPECT_EQ(90, retrieved_base); - EXPECT_EQ(90, retrieved_delta); - EXPECT_EQ(10, retrieved_size); - // Validate the properties of the smaller range (should be untouched). - EXPECT_TRUE(range_map.RetrieveRange(10, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(1, object->id()); - EXPECT_EQ(10, retrieved_base); - EXPECT_EQ(0, retrieved_delta); - EXPECT_EQ(80, retrieved_size); -} - -TEST(RangeMap, TestShinkDown_PartialOverlap_AtBeginning) { - TestMap range_map; - range_map.SetEnableShrinkDown(true); - linked_ptr<CountedObject> object_1(new CountedObject(1)); - EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */, - object_1)); - - // Partial overlap at the beginning of the new range. - linked_ptr<CountedObject> object_2(new CountedObject(2)); - EXPECT_TRUE(range_map.StoreRange(90 /* base address */, 110 /* size */, - object_2)); - - linked_ptr<CountedObject> object; - AddressType retrieved_base = AddressType(); - AddressType retrieved_delta = AddressType(); - AddressType retrieved_size = AddressType(); - // The second range is supposed to be shrunk down so the following address - // should resize in the first range. - EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(1, object->id()); - EXPECT_EQ(0, retrieved_base); - EXPECT_EQ(0, retrieved_delta); - EXPECT_EQ(100, retrieved_size); - // Validate the properties of the shrunk down range. - EXPECT_TRUE(range_map.RetrieveRange(100, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(2, object->id()); - EXPECT_EQ(100, retrieved_base); - EXPECT_EQ(10, retrieved_delta); - EXPECT_EQ(100, retrieved_size); -} - -TEST(RangeMap, TestShinkDown_PartialOverlap_AtEnd) { - TestMap range_map; - range_map.SetEnableShrinkDown(true); - linked_ptr<CountedObject> object_1(new CountedObject(1)); - EXPECT_TRUE(range_map.StoreRange(50 /* base address */, 50 /* size */, - object_1)); - - // Partial overlap at the end of the new range. - linked_ptr<CountedObject> object_2(new CountedObject(2)); - EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 70 /* size */, - object_2)); - - linked_ptr<CountedObject> object; - AddressType retrieved_base = AddressType(); - AddressType retrieved_delta = AddressType(); - AddressType retrieved_size = AddressType(); - // The first range is supposed to be shrunk down so the following address - // should resize in the first range. - EXPECT_TRUE(range_map.RetrieveRange(69, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(2, object->id()); - EXPECT_EQ(0, retrieved_base); - EXPECT_EQ(0, retrieved_delta); - EXPECT_EQ(70, retrieved_size); - // Validate the properties of the shrunk down range. - EXPECT_TRUE(range_map.RetrieveRange(70, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(1, object->id()); - EXPECT_EQ(70, retrieved_base); - EXPECT_EQ(20, retrieved_delta); - EXPECT_EQ(30, retrieved_size); -} - -// A new range is overlapped at both ends. The new range and the range -// that overlaps at the end should be shrink. The range that overlaps at the -// beginning should be left untouched. -TEST(RangeMap, TestShinkDown_OverlapAtBothEnds) { - TestMap range_map; - range_map.SetEnableShrinkDown(true); - // This should overlap object_3 at the beginning. - linked_ptr<CountedObject> object_1(new CountedObject(1)); - EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 100 /* size */, - object_1)); - - // This should overlap object_3 at the end. - linked_ptr<CountedObject> object_2(new CountedObject(2)); - EXPECT_TRUE(range_map.StoreRange(100 /* base address */, 100 /* size */, - object_2)); - - // This should be overlapped on both ends by object_1 and object_2. - linked_ptr<CountedObject> object_3(new CountedObject(3)); - EXPECT_TRUE(range_map.StoreRange(50 /* base address */, 100 /* size */, - object_3)); - - linked_ptr<CountedObject> object; - AddressType retrieved_base = AddressType(); - AddressType retrieved_delta = AddressType(); - AddressType retrieved_size = AddressType(); - // The first range should be intact. - EXPECT_TRUE(range_map.RetrieveRange(0, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(1, object->id()); - EXPECT_EQ(0, retrieved_base); - EXPECT_EQ(0, retrieved_delta); - EXPECT_EQ(100, retrieved_size); - // The second range should be shrunk down by 50. - EXPECT_TRUE(range_map.RetrieveRange(150, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(2, object->id()); - EXPECT_EQ(150, retrieved_base); - EXPECT_EQ(50, retrieved_delta); - EXPECT_EQ(50, retrieved_size); - // The third range (in the middle) should be shrunk down by 50. - EXPECT_TRUE(range_map.RetrieveRange(100, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(3, object->id()); - EXPECT_EQ(100, retrieved_base); - EXPECT_EQ(50, retrieved_delta); - EXPECT_EQ(50, retrieved_size); -} - -TEST(RangeMap, TestShinkDown_MultipleConflicts) { - TestMap range_map; - range_map.SetEnableShrinkDown(true); - // This should overlap with object_3. - linked_ptr<CountedObject> object_1(new CountedObject(1)); - EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 90 /* size */, - object_1)); - - // This should also overlap with object_3 but after object_1. - linked_ptr<CountedObject> object_2(new CountedObject(2)); - EXPECT_TRUE(range_map.StoreRange(100 /* base address */, 100 /* size */, - object_2)); - - // This should be overlapped on both object_1 and object_2. Since - // object_3 ends with the higher address it must be shrunk. - linked_ptr<CountedObject> object_3(new CountedObject(3)); - EXPECT_TRUE(range_map.StoreRange(0 /* base address */, 300 /* size */, - object_3)); - - linked_ptr<CountedObject> object; - AddressType retrieved_base = AddressType(); - AddressType retrieved_delta = AddressType(); - AddressType retrieved_size = AddressType(); - // The first range should be intact. - EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(1, object->id()); - EXPECT_EQ(10, retrieved_base); - EXPECT_EQ(0, retrieved_delta); - EXPECT_EQ(90, retrieved_size); - // The second range should be intact. - EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(2, object->id()); - EXPECT_EQ(100, retrieved_base); - EXPECT_EQ(0, retrieved_delta); - EXPECT_EQ(100, retrieved_size); - // The third range should be shrunk down by 200. - EXPECT_TRUE(range_map.RetrieveRange(299, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(3, object->id()); - EXPECT_EQ(200, retrieved_base); - EXPECT_EQ(200, retrieved_delta); - EXPECT_EQ(100, retrieved_size); -} - -// Adding two ranges without overlap should succeed and the ranges should -// be left intact. -TEST(RangeMap, TestShinkDown_NoConflicts) { - TestMap range_map; - range_map.SetEnableShrinkDown(true); - // Adding range 1. - linked_ptr<CountedObject> object_1(new CountedObject(1)); - EXPECT_TRUE(range_map.StoreRange(10 /* base address */, 90 /* size */, - object_1)); - - // Adding range 2 - no overlap with range 1. - linked_ptr<CountedObject> object_2(new CountedObject(2)); - EXPECT_TRUE(range_map.StoreRange(110 /* base address */, 90 /* size */, - object_2)); - - linked_ptr<CountedObject> object; - AddressType retrieved_base = AddressType(); - AddressType retrieved_delta = AddressType(); - AddressType retrieved_size = AddressType(); - // The first range should be intact. - EXPECT_TRUE(range_map.RetrieveRange(99, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(1, object->id()); - EXPECT_EQ(10, retrieved_base); - EXPECT_EQ(0, retrieved_delta); - EXPECT_EQ(90, retrieved_size); - // The second range should be intact. - EXPECT_TRUE(range_map.RetrieveRange(199, &object, &retrieved_base, - &retrieved_delta, &retrieved_size)); - EXPECT_EQ(2, object->id()); - EXPECT_EQ(110, retrieved_base); - EXPECT_EQ(0, retrieved_delta); - EXPECT_EQ(90, retrieved_size); -} - -} // namespace diff --git a/toolkit/crashreporter/google-breakpad/src/processor/range_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/range_map_unittest.cc deleted file mode 100644 index 31b89e5de..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/range_map_unittest.cc +++ /dev/null @@ -1,559 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// range_map_unittest.cc: Unit tests for RangeMap -// -// Author: Mark Mentovai - - -#include <limits.h> -#include <stdio.h> - -#include "processor/range_map-inl.h" - -#include "common/scoped_ptr.h" -#include "processor/linked_ptr.h" -#include "processor/logging.h" - -namespace { - - -using google_breakpad::linked_ptr; -using google_breakpad::scoped_ptr; -using google_breakpad::RangeMap; - - -// A CountedObject holds an int. A global (not thread safe!) count of -// allocated CountedObjects is maintained to help test memory management. -class CountedObject { - public: - explicit CountedObject(int id) : id_(id) { ++count_; } - ~CountedObject() { --count_; } - - static int count() { return count_; } - int id() const { return id_; } - - private: - static int count_; - int id_; -}; - -int CountedObject::count_; - - -typedef int AddressType; -typedef RangeMap< AddressType, linked_ptr<CountedObject> > TestMap; - - -// RangeTest contains data to use for store and retrieve tests. See -// RunTests for descriptions of the tests. -struct RangeTest { - // Base address to use for test - AddressType address; - - // Size of range to use for test - AddressType size; - - // Unique ID of range - unstorable ranges must have unique IDs too - int id; - - // Whether this range is expected to be stored successfully or not - bool expect_storable; -}; - - -// A RangeTestSet encompasses multiple RangeTests, which are run in -// sequence on the same RangeMap. -struct RangeTestSet { - // An array of RangeTests - const RangeTest *range_tests; - - // The number of tests in the set - unsigned int range_test_count; -}; - - -// StoreTest uses the data in a RangeTest and calls StoreRange on the -// test RangeMap. It returns true if the expected result occurred, and -// false if something else happened. -static bool StoreTest(TestMap *range_map, const RangeTest *range_test) { - linked_ptr<CountedObject> object(new CountedObject(range_test->id)); - bool stored = range_map->StoreRange(range_test->address, - range_test->size, - object); - - if (stored != range_test->expect_storable) { - fprintf(stderr, "FAILED: " - "StoreRange id %d, expected %s, observed %s\n", - range_test->id, - range_test->expect_storable ? "storable" : "not storable", - stored ? "stored" : "not stored"); - return false; - } - - return true; -} - - -// RetrieveTest uses the data in RangeTest and calls RetrieveRange on the -// test RangeMap. If it retrieves the expected value (which can be no -// map entry at the specified range,) it returns true, otherwise, it returns -// false. RetrieveTest will check the values around the base address and -// the high address of a range to guard against off-by-one errors. -static bool RetrieveTest(TestMap *range_map, const RangeTest *range_test) { - for (unsigned int side = 0; side <= 1; ++side) { - // When side == 0, check the low side (base address) of each range. - // When side == 1, check the high side (base + size) of each range. - - // Check one-less and one-greater than the target address in addition - // to the target address itself. - - // If the size of the range is only 1, don't check one greater than - // the base or one less than the high - for a successfully stored - // range, these tests would erroneously fail because the range is too - // small. - AddressType low_offset = -1; - AddressType high_offset = 1; - if (range_test->size == 1) { - if (!side) // When checking the low side, - high_offset = 0; // don't check one over the target. - else // When checking the high side, - low_offset = 0; // don't check one under the target. - } - - for (AddressType offset = low_offset; offset <= high_offset; ++offset) { - AddressType address = - offset + - (!side ? range_test->address : - range_test->address + range_test->size - 1); - - bool expected_result = false; // This is correct for tests not stored. - if (range_test->expect_storable) { - if (offset == 0) // When checking the target address, - expected_result = true; // test should always succeed. - else if (offset == -1) // When checking one below the target, - expected_result = side; // should fail low and succeed high. - else // When checking one above the target, - expected_result = !side; // should succeed low and fail high. - } - - linked_ptr<CountedObject> object; - AddressType retrieved_base = AddressType(); - AddressType retrieved_size = AddressType(); - AddressType retrieved_delta = AddressType(); - bool retrieved = range_map->RetrieveRange(address, &object, - &retrieved_base, - &retrieved_delta, - &retrieved_size); - - bool observed_result = retrieved && object->id() == range_test->id; - - if (observed_result != expected_result) { - fprintf(stderr, "FAILED: " - "RetrieveRange id %d, side %d, offset %d, " - "expected %s, observed %s\n", - range_test->id, - side, - offset, - expected_result ? "true" : "false", - observed_result ? "true" : "false"); - return false; - } - - // If a range was successfully retrieved, check that the returned - // bounds match the range as stored. - if (observed_result == true && - (retrieved_base != range_test->address || - retrieved_size != range_test->size)) { - fprintf(stderr, "FAILED: " - "RetrieveRange id %d, side %d, offset %d, " - "expected base/size %d/%d, observed %d/%d\n", - range_test->id, - side, - offset, - range_test->address, range_test->size, - retrieved_base, retrieved_size); - return false; - } - - // Now, check RetrieveNearestRange. The nearest range is always - // expected to be different from the test range when checking one - // less than the low side. - bool expected_nearest = range_test->expect_storable; - if (!side && offset < 0) - expected_nearest = false; - - linked_ptr<CountedObject> nearest_object; - AddressType nearest_base = AddressType(); - AddressType nearest_delta = AddressType(); - AddressType nearest_size = AddressType(); - bool retrieved_nearest = range_map->RetrieveNearestRange(address, - &nearest_object, - &nearest_base, - &nearest_delta, - &nearest_size); - - // When checking one greater than the high side, RetrieveNearestRange - // should usually return the test range. When a different range begins - // at that address, though, then RetrieveNearestRange should return the - // range at the address instead of the test range. - if (side && offset > 0 && nearest_base == address) { - expected_nearest = false; - } - - bool observed_nearest = retrieved_nearest && - nearest_object->id() == range_test->id; - - if (observed_nearest != expected_nearest) { - fprintf(stderr, "FAILED: " - "RetrieveNearestRange id %d, side %d, offset %d, " - "expected %s, observed %s\n", - range_test->id, - side, - offset, - expected_nearest ? "true" : "false", - observed_nearest ? "true" : "false"); - return false; - } - - // If a range was successfully retrieved, check that the returned - // bounds match the range as stored. - if (expected_nearest && - (nearest_base != range_test->address || - nearest_size != range_test->size)) { - fprintf(stderr, "FAILED: " - "RetrieveNearestRange id %d, side %d, offset %d, " - "expected base/size %d/%d, observed %d/%d\n", - range_test->id, - side, - offset, - range_test->address, range_test->size, - nearest_base, nearest_size); - return false; - } - } - } - - return true; -} - - -// Test RetrieveRangeAtIndex, which is supposed to return objects in order -// according to their addresses. This test is performed by looping through -// the map, calling RetrieveRangeAtIndex for all possible indices in sequence, -// and verifying that each call returns a different object than the previous -// call, and that ranges are returned with increasing base addresses. Returns -// false if the test fails. -static bool RetrieveIndexTest(TestMap *range_map, int set) { - linked_ptr<CountedObject> object; - CountedObject *last_object = NULL; - AddressType last_base = 0; - - int object_count = range_map->GetCount(); - for (int object_index = 0; object_index < object_count; ++object_index) { - AddressType base; - if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base, - NULL /* delta */, NULL /* size */)) { - fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " - "expected success, observed failure\n", - set, object_index); - return false; - } - - if (!object.get()) { - fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " - "expected object, observed NULL\n", - set, object_index); - return false; - } - - // It's impossible to do these comparisons unless there's a previous - // object to compare against. - if (last_object) { - // The object must be different from the last one. - if (object->id() == last_object->id()) { - fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " - "expected different objects, observed same objects (%d)\n", - set, object_index, object->id()); - return false; - } - - // Each object must have a base greater than the previous object's base. - if (base <= last_base) { - fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d, " - "expected different bases, observed same bases (%d)\n", - set, object_index, base); - return false; - } - } - - last_object = object.get(); - last_base = base; - } - - // Make sure that RetrieveRangeAtIndex doesn't allow lookups at indices that - // are too high. - if (range_map->RetrieveRangeAtIndex(object_count, &object, NULL /* base */, - NULL /* delta */, NULL /* size */)) { - fprintf(stderr, "FAILED: RetrieveRangeAtIndex set %d index %d (too large), " - "expected failure, observed success\n", - set, object_count); - return false; - } - - return true; -} - -// Additional RetriveAtIndex test to expose the bug in RetrieveRangeAtIndex(). -// Bug info: RetrieveRangeAtIndex() previously retrieves the high address of -// entry, however, it is supposed to retrieve the base address of entry as -// stated in the comment in range_map.h. -static bool RetriveAtIndexTest2() { - scoped_ptr<TestMap> range_map(new TestMap()); - - // Store ranges with base address = 2 * object_id: - const int range_size = 2; - for (int object_id = 0; object_id < 100; ++object_id) { - linked_ptr<CountedObject> object(new CountedObject(object_id)); - int base_address = 2 * object_id; - range_map->StoreRange(base_address, range_size, object); - } - - linked_ptr<CountedObject> object; - int object_count = range_map->GetCount(); - for (int object_index = 0; object_index < object_count; ++object_index) { - AddressType base; - if (!range_map->RetrieveRangeAtIndex(object_index, &object, &base, - NULL /* delta */, NULL /* size */)) { - fprintf(stderr, "FAILED: RetrieveAtIndexTest2 index %d, " - "expected success, observed failure\n", object_index); - return false; - } - - int expected_base = 2 * object->id(); - if (base != expected_base) { - fprintf(stderr, "FAILED: RetriveAtIndexTest2 index %d, " - "expected base %d, observed base %d", - object_index, expected_base, base); - return false; - } - } - - return true; -} - - -// RunTests runs a series of test sets. -static bool RunTests() { - // These tests will be run sequentially. The first set of tests exercises - // most functions of RangeTest, and verifies all of the bounds-checking. - const RangeTest range_tests_0[] = { - { INT_MIN, 16, 1, true }, // lowest possible range - { -2, 5, 2, true }, // a range through zero - { INT_MAX - 9, 11, 3, false }, // tests anti-overflow - { INT_MAX - 9, 10, 4, true }, // highest possible range - { 5, 0, 5, false }, // tests anti-zero-size - { 5, 1, 6, true }, // smallest possible range - { -20, 15, 7, true }, // entirely negative - - { 10, 10, 10, true }, // causes the following tests to fail - { 9, 10, 11, false }, // one-less base, one-less high - { 9, 11, 12, false }, // one-less base, identical high - { 9, 12, 13, false }, // completely contains existing - { 10, 9, 14, false }, // identical base, one-less high - { 10, 10, 15, false }, // exactly identical to existing range - { 10, 11, 16, false }, // identical base, one-greater high - { 11, 8, 17, false }, // contained completely within - { 11, 9, 18, false }, // one-greater base, identical high - { 11, 10, 19, false }, // one-greater base, one-greater high - { 9, 2, 20, false }, // overlaps bottom by one - { 10, 1, 21, false }, // overlaps bottom by one, contained - { 19, 1, 22, false }, // overlaps top by one, contained - { 19, 2, 23, false }, // overlaps top by one - - { 9, 1, 24, true }, // directly below without overlap - { 20, 1, 25, true }, // directly above without overlap - - { 6, 3, 26, true }, // exactly between two ranges, gapless - { 7, 3, 27, false }, // tries to span two ranges - { 7, 5, 28, false }, // tries to span three ranges - { 4, 20, 29, false }, // tries to contain several ranges - - { 30, 50, 30, true }, - { 90, 25, 31, true }, - { 35, 65, 32, false }, // tries to span two noncontiguous - { 120, 10000, 33, true }, // > 8-bit - { 20000, 20000, 34, true }, // > 8-bit - { 0x10001, 0x10001, 35, true }, // > 16-bit - - { 27, -1, 36, false } // tests high < base - }; - - // Attempt to fill the entire space. The entire space must be filled with - // three stores because AddressType is signed for these tests, so RangeMap - // treats the size as signed and rejects sizes that appear to be negative. - // Even if these tests were run as unsigned, two stores would be needed - // to fill the space because the entire size of the space could only be - // described by using one more bit than would be present in AddressType. - const RangeTest range_tests_1[] = { - { INT_MIN, INT_MAX, 50, true }, // From INT_MIN to -2, inclusive - { -1, 2, 51, true }, // From -1 to 0, inclusive - { 1, INT_MAX, 52, true }, // From 1 to INT_MAX, inclusive - { INT_MIN, INT_MAX, 53, false }, // Can't fill the space twice - { -1, 2, 54, false }, - { 1, INT_MAX, 55, false }, - { -3, 6, 56, false }, // -3 to 2, inclusive - spans 3 ranges - }; - - // A light round of testing to verify that RetrieveRange does the right - // the right thing at the extremities of the range when nothing is stored - // there. Checks are forced without storing anything at the extremities - // by setting size = 0. - const RangeTest range_tests_2[] = { - { INT_MIN, 0, 100, false }, // makes RetrieveRange check low end - { -1, 3, 101, true }, - { INT_MAX, 0, 102, false }, // makes RetrieveRange check high end - }; - - // Similar to the previous test set, but with a couple of ranges closer - // to the extremities. - const RangeTest range_tests_3[] = { - { INT_MIN + 1, 1, 110, true }, - { INT_MAX - 1, 1, 111, true }, - { INT_MIN, 0, 112, false }, // makes RetrieveRange check low end - { INT_MAX, 0, 113, false } // makes RetrieveRange check high end - }; - - // The range map is cleared between sets of tests listed here. - const RangeTestSet range_test_sets[] = { - { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) }, - { range_tests_1, sizeof(range_tests_1) / sizeof(RangeTest) }, - { range_tests_2, sizeof(range_tests_2) / sizeof(RangeTest) }, - { range_tests_3, sizeof(range_tests_3) / sizeof(RangeTest) }, - { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) } // Run again - }; - - // Maintain the range map in a pointer so that deletion can be meaningfully - // tested. - scoped_ptr<TestMap> range_map(new TestMap()); - - // Run all of the test sets in sequence. - unsigned int range_test_set_count = sizeof(range_test_sets) / - sizeof(RangeTestSet); - for (unsigned int range_test_set_index = 0; - range_test_set_index < range_test_set_count; - ++range_test_set_index) { - const RangeTest *range_tests = - range_test_sets[range_test_set_index].range_tests; - unsigned int range_test_count = - range_test_sets[range_test_set_index].range_test_count; - - // Run the StoreRange test, which validates StoreRange and initializes - // the RangeMap with data for the RetrieveRange test. - int stored_count = 0; // The number of ranges successfully stored - for (unsigned int range_test_index = 0; - range_test_index < range_test_count; - ++range_test_index) { - const RangeTest *range_test = &range_tests[range_test_index]; - if (!StoreTest(range_map.get(), range_test)) - return false; - - if (range_test->expect_storable) - ++stored_count; - } - - // There should be exactly one CountedObject for everything successfully - // stored in the RangeMap. - if (CountedObject::count() != stored_count) { - fprintf(stderr, "FAILED: " - "stored object counts don't match, expected %d, observed %d\n", - stored_count, - CountedObject::count()); - - return false; - } - - // The RangeMap's own count of objects should also match. - if (range_map->GetCount() != stored_count) { - fprintf(stderr, "FAILED: stored object count doesn't match GetCount, " - "expected %d, observed %d\n", - stored_count, range_map->GetCount()); - - return false; - } - - // Run the RetrieveRange test - for (unsigned int range_test_index = 0; - range_test_index < range_test_count; - ++range_test_index) { - const RangeTest *range_test = &range_tests[range_test_index]; - if (!RetrieveTest(range_map.get(), range_test)) - return false; - } - - if (!RetrieveIndexTest(range_map.get(), range_test_set_index)) - return false; - - // Clear the map between test sets. If this is the final test set, - // delete the map instead to test destruction. - if (range_test_set_index < range_test_set_count - 1) - range_map->Clear(); - else - range_map.reset(); - - // Test that all stored objects are freed when the RangeMap is cleared - // or deleted. - if (CountedObject::count() != 0) { - fprintf(stderr, "FAILED: " - "did not free all objects after %s, %d still allocated\n", - range_test_set_index < range_test_set_count - 1 ? "clear" - : "delete", - CountedObject::count()); - - return false; - } - } - - if (!RetriveAtIndexTest2()) { - fprintf(stderr, "FAILED: did not pass RetrieveAtIndexTest2()\n"); - return false; - } - - return true; -} - - -} // namespace - - -int main(int argc, char **argv) { - BPLOG_INIT(&argc, &argv); - - return RunTests() ? 0 : 1; -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer-inl.h deleted file mode 100644 index 606bb3cea..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer-inl.h +++ /dev/null @@ -1,260 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// simple_serializer-inl.h: template specializations for following types: -// bool, const char *(C-string), string, -// Line, Function, PublicSymbol, WindowsFrameInfo and their linked pointers. -// -// See simple_serializer.h for moredocumentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_SIMPLE_SERIALIZER_INL_H__ -#define PROCESSOR_SIMPLE_SERIALIZER_INL_H__ - -#include <string> - -#include "processor/simple_serializer.h" -#include "map_serializers-inl.h" - -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "processor/basic_source_line_resolver_types.h" -#include "processor/linked_ptr.h" -#include "processor/windows_frame_info.h" - -namespace google_breakpad { - -// Specializations of SimpleSerializer: bool -template<> -class SimpleSerializer<bool> { - public: - static size_t SizeOf(bool boolean) { return 1; } - - static char *Write(bool boolean, char *dest) { - *dest = static_cast<char>(boolean? 255 : 0); - return ++dest; - } - - static const char *Read(const char *source, bool *value) { - *value = ((*source) == 0 ? false : true); - return ++source; - } -}; - -// Specializations of SimpleSerializer: string -template<> -class SimpleSerializer<string> { - public: - static size_t SizeOf(const string &str) { return str.size() + 1; } - - static char *Write(const string &str, char *dest) { - strcpy(dest, str.c_str()); - return dest + SizeOf(str); - } -}; - -// Specializations of SimpleSerializer: C-string -template<> -class SimpleSerializer<const char*> { - public: - static size_t SizeOf(const char *cstring) { - return strlen(cstring) + 1; - } - - static char *Write(const char *cstring, char *dest) { - strcpy(dest, cstring); - return dest + SizeOf(cstring); - } -}; - -// Specializations of SimpleSerializer: Line -template<> -class SimpleSerializer<BasicSourceLineResolver::Line> { - typedef BasicSourceLineResolver::Line Line; - public: - static size_t SizeOf(const Line &line) { - return SimpleSerializer<MemAddr>::SizeOf(line.address) - + SimpleSerializer<MemAddr>::SizeOf(line.size) - + SimpleSerializer<int32_t>::SizeOf(line.source_file_id) - + SimpleSerializer<int32_t>::SizeOf(line.line); - } - static char *Write(const Line &line, char *dest) { - dest = SimpleSerializer<MemAddr>::Write(line.address, dest); - dest = SimpleSerializer<MemAddr>::Write(line.size, dest); - dest = SimpleSerializer<int32_t>::Write(line.source_file_id, dest); - dest = SimpleSerializer<int32_t>::Write(line.line, dest); - return dest; - } -}; - -// Specializations of SimpleSerializer: PublicSymbol -template<> -class SimpleSerializer<BasicSourceLineResolver::PublicSymbol> { - typedef BasicSourceLineResolver::PublicSymbol PublicSymbol; - public: - static size_t SizeOf(const PublicSymbol &pubsymbol) { - return SimpleSerializer<string>::SizeOf(pubsymbol.name) - + SimpleSerializer<MemAddr>::SizeOf(pubsymbol.address) - + SimpleSerializer<int32_t>::SizeOf(pubsymbol.parameter_size); - } - static char *Write(const PublicSymbol &pubsymbol, char *dest) { - dest = SimpleSerializer<string>::Write(pubsymbol.name, dest); - dest = SimpleSerializer<MemAddr>::Write(pubsymbol.address, dest); - dest = SimpleSerializer<int32_t>::Write(pubsymbol.parameter_size, dest); - return dest; - } -}; - -// Specializations of SimpleSerializer: WindowsFrameInfo -template<> -class SimpleSerializer<WindowsFrameInfo> { - public: - static size_t SizeOf(const WindowsFrameInfo &wfi) { - unsigned int size = 0; - size += sizeof(int32_t); // wfi.type_ - size += SimpleSerializer<int32_t>::SizeOf(wfi.valid); - size += SimpleSerializer<uint32_t>::SizeOf(wfi.prolog_size); - size += SimpleSerializer<uint32_t>::SizeOf(wfi.epilog_size); - size += SimpleSerializer<uint32_t>::SizeOf(wfi.parameter_size); - size += SimpleSerializer<uint32_t>::SizeOf(wfi.saved_register_size); - size += SimpleSerializer<uint32_t>::SizeOf(wfi.local_size); - size += SimpleSerializer<uint32_t>::SizeOf(wfi.max_stack_size); - size += SimpleSerializer<bool>::SizeOf(wfi.allocates_base_pointer); - size += SimpleSerializer<string>::SizeOf(wfi.program_string); - return size; - } - static char *Write(const WindowsFrameInfo &wfi, char *dest) { - dest = SimpleSerializer<int32_t>::Write( - static_cast<const int32_t>(wfi.type_), dest); - dest = SimpleSerializer<int32_t>::Write(wfi.valid, dest); - dest = SimpleSerializer<uint32_t>::Write(wfi.prolog_size, dest); - dest = SimpleSerializer<uint32_t>::Write(wfi.epilog_size, dest); - dest = SimpleSerializer<uint32_t>::Write(wfi.parameter_size, dest); - dest = SimpleSerializer<uint32_t>::Write(wfi.saved_register_size, dest); - dest = SimpleSerializer<uint32_t>::Write(wfi.local_size, dest); - dest = SimpleSerializer<uint32_t>::Write(wfi.max_stack_size, dest); - dest = SimpleSerializer<bool>::Write(wfi.allocates_base_pointer, dest); - return SimpleSerializer<string>::Write(wfi.program_string, dest); - } -}; - -// Specializations of SimpleSerializer: Linked_ptr version of -// Line, Function, PublicSymbol, WindowsFrameInfo. -template<> -class SimpleSerializer< linked_ptr<BasicSourceLineResolver::Line> > { - typedef BasicSourceLineResolver::Line Line; - public: - static size_t SizeOf(const linked_ptr<Line> &lineptr) { - if (lineptr.get() == NULL) return 0; - return SimpleSerializer<Line>::SizeOf(*(lineptr.get())); - } - static char *Write(const linked_ptr<Line> &lineptr, char *dest) { - if (lineptr.get()) - dest = SimpleSerializer<Line>::Write(*(lineptr.get()), dest); - return dest; - } -}; - -template<> -class SimpleSerializer<BasicSourceLineResolver::Function> { - // Convenient type names. - typedef BasicSourceLineResolver::Function Function; - typedef BasicSourceLineResolver::Line Line; - public: - static size_t SizeOf(const Function &func) { - unsigned int size = 0; - size += SimpleSerializer<string>::SizeOf(func.name); - size += SimpleSerializer<MemAddr>::SizeOf(func.address); - size += SimpleSerializer<MemAddr>::SizeOf(func.size); - size += SimpleSerializer<int32_t>::SizeOf(func.parameter_size); - size += range_map_serializer_.SizeOf(func.lines); - return size; - } - - static char *Write(const Function &func, char *dest) { - dest = SimpleSerializer<string>::Write(func.name, dest); - dest = SimpleSerializer<MemAddr>::Write(func.address, dest); - dest = SimpleSerializer<MemAddr>::Write(func.size, dest); - dest = SimpleSerializer<int32_t>::Write(func.parameter_size, dest); - dest = range_map_serializer_.Write(func.lines, dest); - return dest; - } - private: - // This static member is defined in module_serializer.cc. - static RangeMapSerializer< MemAddr, linked_ptr<Line> > range_map_serializer_; -}; - -template<> -class SimpleSerializer< linked_ptr<BasicSourceLineResolver::Function> > { - typedef BasicSourceLineResolver::Function Function; - public: - static size_t SizeOf(const linked_ptr<Function> &func) { - if (!func.get()) return 0; - return SimpleSerializer<Function>::SizeOf(*(func.get())); - } - - static char *Write(const linked_ptr<Function> &func, char *dest) { - if (func.get()) - dest = SimpleSerializer<Function>::Write(*(func.get()), dest); - return dest; - } -}; - -template<> -class SimpleSerializer< linked_ptr<BasicSourceLineResolver::PublicSymbol> > { - typedef BasicSourceLineResolver::PublicSymbol PublicSymbol; - public: - static size_t SizeOf(const linked_ptr<PublicSymbol> &pubsymbol) { - if (pubsymbol.get() == NULL) return 0; - return SimpleSerializer<PublicSymbol>::SizeOf(*(pubsymbol.get())); - } - static char *Write(const linked_ptr<PublicSymbol> &pubsymbol, char *dest) { - if (pubsymbol.get()) - dest = SimpleSerializer<PublicSymbol>::Write(*(pubsymbol.get()), dest); - return dest; - } -}; - -template<> -class SimpleSerializer< linked_ptr<WindowsFrameInfo> > { - public: - static size_t SizeOf(const linked_ptr<WindowsFrameInfo> &wfi) { - if (wfi.get() == NULL) return 0; - return SimpleSerializer<WindowsFrameInfo>::SizeOf(*(wfi.get())); - } - static char *Write(const linked_ptr<WindowsFrameInfo> &wfi, char *dest) { - if (wfi.get()) - dest = SimpleSerializer<WindowsFrameInfo>::Write(*(wfi.get()), dest); - return dest; - } -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_SIMPLE_SERIALIZER_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer.h b/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer.h deleted file mode 100644 index 275f51ce3..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/simple_serializer.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// simple_serializer.h: SimpleSerializer is a template for calculating size and -// writing to specific memory location for objects of primitive types, C-style -// string, string, breakpad types/structs etc. -// All specializations of SimpleSerializer template are defined in the -// "simple_serializer-inl.h" file. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_SIMPLE_SERIALIZER_H__ -#define PROCESSOR_SIMPLE_SERIALIZER_H__ - -#include "google_breakpad/common/breakpad_types.h" - -namespace google_breakpad { - -typedef uint64_t MemAddr; - -// Default implementation of SimpleSerializer template. -// Specializations are defined in "simple_serializer-inl.h". -template<class Type> class SimpleSerializer { - public: - // Calculate and return the size of the 'item'. - static size_t SizeOf(const Type &item) { return sizeof(item); } - // Write 'item' to memory location 'dest', and return to the "end" address of - // data written, i.e., the address after the final byte written. - static char *Write(const Type &item, char *dest) { - new (dest) Type(item); - return dest + SizeOf(item); - } -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_SIMPLE_SERIALIZER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc deleted file mode 100644 index bc5ebb687..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.cc +++ /dev/null @@ -1,204 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// simple_symbol_supplier.cc: A simple SymbolSupplier implementation -// -// See simple_symbol_supplier.h for documentation. -// -// Author: Mark Mentovai - -#include "processor/simple_symbol_supplier.h" - -#include <assert.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> - -#include <algorithm> -#include <iostream> -#include <fstream> - -#include "common/using_std_string.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/system_info.h" -#include "processor/logging.h" -#include "processor/pathname_stripper.h" - -namespace google_breakpad { - -static bool file_exists(const string &file_name) { - struct stat sb; - return stat(file_name.c_str(), &sb) == 0; -} - -SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile( - const CodeModule *module, const SystemInfo *system_info, - string *symbol_file) { - BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFile " - "requires |symbol_file|"; - assert(symbol_file); - symbol_file->clear(); - - for (unsigned int path_index = 0; path_index < paths_.size(); ++path_index) { - SymbolResult result; - if ((result = GetSymbolFileAtPathFromRoot(module, system_info, - paths_[path_index], - symbol_file)) != NOT_FOUND) { - return result; - } - } - return NOT_FOUND; -} - -SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFile( - const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - string *symbol_data) { - assert(symbol_data); - symbol_data->clear(); - - SymbolSupplier::SymbolResult s = GetSymbolFile(module, system_info, - symbol_file); - if (s == FOUND) { - std::ifstream in(symbol_file->c_str()); - std::getline(in, *symbol_data, string::traits_type::to_char_type( - string::traits_type::eof())); - in.close(); - } - return s; -} - -SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetCStringSymbolData( - const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - char **symbol_data, - size_t *symbol_data_size) { - assert(symbol_data); - assert(symbol_data_size); - - string symbol_data_string; - SymbolSupplier::SymbolResult s = - GetSymbolFile(module, system_info, symbol_file, &symbol_data_string); - - if (s == FOUND) { - *symbol_data_size = symbol_data_string.size() + 1; - *symbol_data = new char[*symbol_data_size]; - if (*symbol_data == NULL) { - BPLOG(ERROR) << "Memory allocation for size " << *symbol_data_size - << " failed"; - return INTERRUPT; - } - memcpy(*symbol_data, symbol_data_string.c_str(), symbol_data_string.size()); - (*symbol_data)[symbol_data_string.size()] = '\0'; - memory_buffers_.insert(make_pair(module->code_file(), *symbol_data)); - } - return s; -} - -void SimpleSymbolSupplier::FreeSymbolData(const CodeModule *module) { - if (!module) { - BPLOG(INFO) << "Cannot free symbol data buffer for NULL module"; - return; - } - - map<string, char *>::iterator it = memory_buffers_.find(module->code_file()); - if (it == memory_buffers_.end()) { - BPLOG(INFO) << "Cannot find symbol data buffer for module " - << module->code_file(); - return; - } - delete [] it->second; - memory_buffers_.erase(it); -} - -SymbolSupplier::SymbolResult SimpleSymbolSupplier::GetSymbolFileAtPathFromRoot( - const CodeModule *module, const SystemInfo *system_info, - const string &root_path, string *symbol_file) { - BPLOG_IF(ERROR, !symbol_file) << "SimpleSymbolSupplier::GetSymbolFileAtPath " - "requires |symbol_file|"; - assert(symbol_file); - symbol_file->clear(); - - if (!module) - return NOT_FOUND; - - // Start with the base path. - string path = root_path; - - // Append the debug (pdb) file name as a directory name. - path.append("/"); - string debug_file_name = PathnameStripper::File(module->debug_file()); - if (debug_file_name.empty()) { - BPLOG(ERROR) << "Can't construct symbol file path without debug_file " - "(code_file = " << - PathnameStripper::File(module->code_file()) << ")"; - return NOT_FOUND; - } - path.append(debug_file_name); - - // Append the identifier as a directory name. - path.append("/"); - string identifier = module->debug_identifier(); - if (identifier.empty()) { - BPLOG(ERROR) << "Can't construct symbol file path without debug_identifier " - "(code_file = " << - PathnameStripper::File(module->code_file()) << - ", debug_file = " << debug_file_name << ")"; - return NOT_FOUND; - } - path.append(identifier); - - // Transform the debug file name into one ending in .sym. If the existing - // name ends in .pdb, strip the .pdb. Otherwise, add .sym to the non-.pdb - // name. - path.append("/"); - string debug_file_extension; - if (debug_file_name.size() > 4) - debug_file_extension = debug_file_name.substr(debug_file_name.size() - 4); - std::transform(debug_file_extension.begin(), debug_file_extension.end(), - debug_file_extension.begin(), tolower); - if (debug_file_extension == ".pdb") { - path.append(debug_file_name.substr(0, debug_file_name.size() - 4)); - } else { - path.append(debug_file_name); - } - path.append(".sym"); - - if (!file_exists(path)) { - BPLOG(INFO) << "No symbol file at " << path; - return NOT_FOUND; - } - - *symbol_file = path; - return FOUND; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h b/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h deleted file mode 100644 index 0cde85cdc..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/simple_symbol_supplier.h +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// simple_symbol_supplier.h: A simple SymbolSupplier implementation -// -// SimpleSymbolSupplier is a straightforward implementation of SymbolSupplier -// that stores symbol files in a filesystem tree. A SimpleSymbolSupplier is -// created with one or more base directories, which are the root paths for all -// symbol files. Each symbol file contained therein has a directory entry in -// the base directory with a name identical to the corresponding debugging -// file (pdb). Within each of these directories, there are subdirectories -// named for the debugging file's identifier. For recent pdb files, this is -// a concatenation of the pdb's uuid and age, presented in hexadecimal form, -// without any dashes or separators. The uuid is in uppercase hexadecimal -// and the age is in lowercase hexadecimal. Within that subdirectory, -// SimpleSymbolSupplier expects to find the symbol file, which is named -// identically to the debug file, but with a .sym extension. If the original -// debug file had a name ending in .pdb, the .pdb extension will be replaced -// with .sym. This sample hierarchy is rooted at the "symbols" base -// directory: -// -// symbols -// symbols/test_app.pdb -// symbols/test_app.pdb/63FE4780728D49379B9D7BB6460CB42A1 -// symbols/test_app.pdb/63FE4780728D49379B9D7BB6460CB42A1/test_app.sym -// symbols/kernel32.pdb -// symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542 -// symbols/kernel32.pdb/BCE8785C57B44245A669896B6A19B9542/kernel32.sym -// -// In this case, the uuid of test_app.pdb is -// 63fe4780-728d-4937-9b9d-7bb6460cb42a and its age is 1. -// -// This scheme was chosen to be roughly analogous to the way that -// symbol files may be accessed from Microsoft Symbol Server. A hierarchy -// used for Microsoft Symbol Server storage is usable as a hierarchy for -// SimpleSymbolServer, provided that the pdb files are transformed to dumped -// format using a tool such as dump_syms, and given a .sym extension. -// -// SimpleSymbolSupplier will iterate over all root paths searching for -// a symbol file existing in that path. -// -// SimpleSymbolSupplier supports any debugging file which can be identified -// by a CodeModule object's debug_file and debug_identifier accessors. The -// expected ultimate source of these CodeModule objects are MinidumpModule -// objects; it is this class that is responsible for assigning appropriate -// values for debug_file and debug_identifier. -// -// Author: Mark Mentovai - -#ifndef PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ -#define PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ - -#include <map> -#include <string> -#include <vector> - -#include "common/using_std_string.h" -#include "google_breakpad/processor/symbol_supplier.h" - -namespace google_breakpad { - -using std::map; -using std::vector; - -class CodeModule; - -class SimpleSymbolSupplier : public SymbolSupplier { - public: - // Creates a new SimpleSymbolSupplier, using path as the root path where - // symbols are stored. - explicit SimpleSymbolSupplier(const string &path) : paths_(1, path) {} - - // Creates a new SimpleSymbolSupplier, using paths as a list of root - // paths where symbols may be stored. - explicit SimpleSymbolSupplier(const vector<string> &paths) : paths_(paths) {} - - virtual ~SimpleSymbolSupplier() {} - - // Returns the path to the symbol file for the given module. See the - // description above. - virtual SymbolResult GetSymbolFile(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file); - - virtual SymbolResult GetSymbolFile(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - string *symbol_data); - - // Allocates data buffer on heap and writes symbol data into buffer. - // Symbol supplier ALWAYS takes ownership of the data buffer. - virtual SymbolResult GetCStringSymbolData(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - char **symbol_data, - size_t *symbol_data_size); - - // Free the data buffer allocated in the above GetCStringSymbolData(); - virtual void FreeSymbolData(const CodeModule *module); - - protected: - SymbolResult GetSymbolFileAtPathFromRoot(const CodeModule *module, - const SystemInfo *system_info, - const string &root_path, - string *symbol_file); - - private: - map<string, char *> memory_buffers_; - vector<string> paths_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_SIMPLE_SYMBOL_SUPPLIER_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base.cc b/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base.cc deleted file mode 100644 index 6eff1f991..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base.cc +++ /dev/null @@ -1,341 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// source_line_resolver_base.cc: Implementation of SourceLineResolverBase. -// -// See source_line_resolver_base.h and source_line_resolver_base_types.h for -// more documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> - -#include <map> -#include <utility> - -#include "google_breakpad/processor/source_line_resolver_base.h" -#include "processor/source_line_resolver_base_types.h" -#include "processor/module_factory.h" - -using std::map; -using std::make_pair; - -namespace google_breakpad { - -SourceLineResolverBase::SourceLineResolverBase( - ModuleFactory *module_factory) - : modules_(new ModuleMap), - corrupt_modules_(new ModuleSet), - memory_buffers_(new MemoryMap), - module_factory_(module_factory) { -} - -SourceLineResolverBase::~SourceLineResolverBase() { - ModuleMap::iterator it; - // Iterate through ModuleMap and delete all loaded modules. - for (it = modules_->begin(); it != modules_->end(); ++it) { - // Delete individual module. - delete it->second; - } - // Delete the map of modules. - delete modules_; - modules_ = NULL; - - // Delete the set of corrupt modules. - delete corrupt_modules_; - corrupt_modules_ = NULL; - - MemoryMap::iterator iter = memory_buffers_->begin(); - for (; iter != memory_buffers_->end(); ++iter) { - delete [] iter->second; - } - // Delete the map of memory buffers. - delete memory_buffers_; - memory_buffers_ = NULL; - - delete module_factory_; - module_factory_ = NULL; -} - -bool SourceLineResolverBase::ReadSymbolFile(const string &map_file, - char **symbol_data, - size_t *symbol_data_size) { - if (symbol_data == NULL || symbol_data_size == NULL) { - BPLOG(ERROR) << "Could not Read file into Null memory pointer"; - return false; - } - - struct stat buf; - int error_code = stat(map_file.c_str(), &buf); - if (error_code == -1) { - string error_string; - error_code = ErrnoString(&error_string); - BPLOG(ERROR) << "Could not open " << map_file << - ", error " << error_code << ": " << error_string; - return false; - } - - off_t file_size = buf.st_size; - - // Allocate memory for file contents, plus a null terminator - // since we may use strtok() on the contents. - *symbol_data_size = file_size + 1; - *symbol_data = new char[file_size + 1]; - - if (*symbol_data == NULL) { - BPLOG(ERROR) << "Could not allocate memory for " << map_file; - return false; - } - - BPLOG(INFO) << "Opening " << map_file; - - FILE *f = fopen(map_file.c_str(), "rt"); - if (!f) { - string error_string; - error_code = ErrnoString(&error_string); - BPLOG(ERROR) << "Could not open " << map_file << - ", error " << error_code << ": " << error_string; - delete [] (*symbol_data); - *symbol_data = NULL; - return false; - } - - AutoFileCloser closer(f); - - int items_read = 0; - - items_read = fread(*symbol_data, 1, file_size, f); - - if (items_read != file_size) { - string error_string; - error_code = ErrnoString(&error_string); - BPLOG(ERROR) << "Could not slurp " << map_file << - ", error " << error_code << ": " << error_string; - delete [] (*symbol_data); - *symbol_data = NULL; - return false; - } - - (*symbol_data)[file_size] = '\0'; - return true; -} - -bool SourceLineResolverBase::LoadModule(const CodeModule *module, - const string &map_file) { - if (module == NULL) - return false; - - // Make sure we don't already have a module with the given name. - if (modules_->find(module->code_file()) != modules_->end()) { - BPLOG(INFO) << "Symbols for module " << module->code_file() - << " already loaded"; - return false; - } - - BPLOG(INFO) << "Loading symbols for module " << module->code_file() - << " from " << map_file; - - char *memory_buffer; - size_t memory_buffer_size; - if (!ReadSymbolFile(map_file, &memory_buffer, &memory_buffer_size)) - return false; - - BPLOG(INFO) << "Read symbol file " << map_file << " succeeded"; - - bool load_result = LoadModuleUsingMemoryBuffer(module, memory_buffer, - memory_buffer_size); - - if (load_result && !ShouldDeleteMemoryBufferAfterLoadModule()) { - // memory_buffer has to stay alive as long as the module. - memory_buffers_->insert(make_pair(module->code_file(), memory_buffer)); - } else { - delete [] memory_buffer; - } - - return load_result; -} - -bool SourceLineResolverBase::LoadModuleUsingMapBuffer( - const CodeModule *module, const string &map_buffer) { - if (module == NULL) - return false; - - // Make sure we don't already have a module with the given name. - if (modules_->find(module->code_file()) != modules_->end()) { - BPLOG(INFO) << "Symbols for module " << module->code_file() - << " already loaded"; - return false; - } - - size_t memory_buffer_size = map_buffer.size() + 1; - char *memory_buffer = new char[memory_buffer_size]; - if (memory_buffer == NULL) { - BPLOG(ERROR) << "Could not allocate memory for " << module->code_file(); - return false; - } - - // Can't use strcpy, as the data may contain '\0's before the end. - memcpy(memory_buffer, map_buffer.c_str(), map_buffer.size()); - memory_buffer[map_buffer.size()] = '\0'; - - bool load_result = LoadModuleUsingMemoryBuffer(module, memory_buffer, - memory_buffer_size); - - if (load_result && !ShouldDeleteMemoryBufferAfterLoadModule()) { - // memory_buffer has to stay alive as long as the module. - memory_buffers_->insert(make_pair(module->code_file(), memory_buffer)); - } else { - delete [] memory_buffer; - } - - return load_result; -} - -bool SourceLineResolverBase::LoadModuleUsingMemoryBuffer( - const CodeModule *module, - char *memory_buffer, - size_t memory_buffer_size) { - if (!module) - return false; - - // Make sure we don't already have a module with the given name. - if (modules_->find(module->code_file()) != modules_->end()) { - BPLOG(INFO) << "Symbols for module " << module->code_file() - << " already loaded"; - return false; - } - - BPLOG(INFO) << "Loading symbols for module " << module->code_file() - << " from memory buffer"; - - Module *basic_module = module_factory_->CreateModule(module->code_file()); - - // Ownership of memory is NOT transfered to Module::LoadMapFromMemory(). - if (!basic_module->LoadMapFromMemory(memory_buffer, memory_buffer_size)) { - BPLOG(ERROR) << "Too many error while parsing symbol data for module " - << module->code_file(); - // Returning false from here would be an indication that the symbols for - // this module are missing which would be wrong. Intentionally fall through - // and add the module to both the modules_ and the corrupt_modules_ lists. - assert(basic_module->IsCorrupt()); - } - - modules_->insert(make_pair(module->code_file(), basic_module)); - if (basic_module->IsCorrupt()) { - corrupt_modules_->insert(module->code_file()); - } - return true; -} - -bool SourceLineResolverBase::ShouldDeleteMemoryBufferAfterLoadModule() { - return true; -} - -void SourceLineResolverBase::UnloadModule(const CodeModule *code_module) { - if (!code_module) - return; - - ModuleMap::iterator mod_iter = modules_->find(code_module->code_file()); - if (mod_iter != modules_->end()) { - Module *symbol_module = mod_iter->second; - delete symbol_module; - corrupt_modules_->erase(mod_iter->first); - modules_->erase(mod_iter); - } - - if (ShouldDeleteMemoryBufferAfterLoadModule()) { - // No-op. Because we never store any memory buffers. - } else { - // There may be a buffer stored locally, we need to find and delete it. - MemoryMap::iterator iter = memory_buffers_->find(code_module->code_file()); - if (iter != memory_buffers_->end()) { - delete [] iter->second; - memory_buffers_->erase(iter); - } - } -} - -bool SourceLineResolverBase::HasModule(const CodeModule *module) { - if (!module) - return false; - return modules_->find(module->code_file()) != modules_->end(); -} - -bool SourceLineResolverBase::IsModuleCorrupt(const CodeModule *module) { - if (!module) - return false; - return corrupt_modules_->find(module->code_file()) != corrupt_modules_->end(); -} - -void SourceLineResolverBase::FillSourceLineInfo(StackFrame *frame) { - if (frame->module) { - ModuleMap::const_iterator it = modules_->find(frame->module->code_file()); - if (it != modules_->end()) { - it->second->LookupAddress(frame); - } - } -} - -WindowsFrameInfo *SourceLineResolverBase::FindWindowsFrameInfo( - const StackFrame *frame) { - if (frame->module) { - ModuleMap::const_iterator it = modules_->find(frame->module->code_file()); - if (it != modules_->end()) { - return it->second->FindWindowsFrameInfo(frame); - } - } - return NULL; -} - -CFIFrameInfo *SourceLineResolverBase::FindCFIFrameInfo( - const StackFrame *frame) { - if (frame->module) { - ModuleMap::const_iterator it = modules_->find(frame->module->code_file()); - if (it != modules_->end()) { - return it->second->FindCFIFrameInfo(frame); - } - } - return NULL; -} - -bool SourceLineResolverBase::CompareString::operator()( - const string &s1, const string &s2) const { - return strcmp(s1.c_str(), s2.c_str()) < 0; -} - -bool SourceLineResolverBase::Module::ParseCFIRuleSet( - const string &rule_set, CFIFrameInfo *frame_info) const { - CFIFrameInfoParseHandler handler(frame_info); - CFIRuleParser parser(&handler); - return parser.Parse(rule_set); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base_types.h b/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base_types.h deleted file mode 100644 index 4a9dfb3ce..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/source_line_resolver_base_types.h +++ /dev/null @@ -1,158 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// source_line_resolver_base_types.h: definition of nested classes/structs in -// SourceLineResolverBase. It moves the definitions out of -// source_line_resolver_base.cc, so that other classes may have access -// to these private nested types without including source_line_resolver_base.cc -// In addition, Module is defined as a pure abstract class to be implemented by -// each concrete source line resolver class. -// -// See source_line_resolver_base.h for more documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include <stdio.h> - -#include <map> -#include <string> - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/processor/source_line_resolver_base.h" -#include "google_breakpad/processor/stack_frame.h" -#include "processor/cfi_frame_info.h" -#include "processor/windows_frame_info.h" - -#ifndef PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__ -#define PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__ - -namespace google_breakpad { - -class SourceLineResolverBase::AutoFileCloser { - public: - explicit AutoFileCloser(FILE *file) : file_(file) {} - ~AutoFileCloser() { - if (file_) - fclose(file_); - } - - private: - FILE *file_; -}; - -struct SourceLineResolverBase::Line { - Line() { } - Line(MemAddr addr, MemAddr code_size, int file_id, int source_line) - : address(addr) - , size(code_size) - , source_file_id(file_id) - , line(source_line) { } - - MemAddr address; - MemAddr size; - int32_t source_file_id; - int32_t line; -}; - -struct SourceLineResolverBase::Function { - Function() { } - Function(const string &function_name, - MemAddr function_address, - MemAddr code_size, - int set_parameter_size) - : name(function_name), address(function_address), size(code_size), - parameter_size(set_parameter_size) { } - - string name; - MemAddr address; - MemAddr size; - - // The size of parameters passed to this function on the stack. - int32_t parameter_size; -}; - -struct SourceLineResolverBase::PublicSymbol { - PublicSymbol() { } - PublicSymbol(const string& set_name, - MemAddr set_address, - int set_parameter_size) - : name(set_name), - address(set_address), - parameter_size(set_parameter_size) {} - - string name; - MemAddr address; - - // If the public symbol is used as a function entry point, parameter_size - // is set to the size of the parameters passed to the funciton on the - // stack, if known. - int32_t parameter_size; -}; - -class SourceLineResolverBase::Module { - public: - virtual ~Module() { }; - // Loads a map from the given buffer in char* type. - // Does NOT take ownership of memory_buffer (the caller, source line resolver, - // is the owner of memory_buffer). - // The passed in |memory buffer| is of size |memory_buffer_size|. If it is - // not null terminated, LoadMapFromMemory will null terminate it by modifying - // the passed in buffer. - virtual bool LoadMapFromMemory(char *memory_buffer, - size_t memory_buffer_size) = 0; - - // Tells whether the loaded symbol data is corrupt. Return value is - // undefined, if the symbol data hasn't been loaded yet. - virtual bool IsCorrupt() const = 0; - - // Looks up the given relative address, and fills the StackFrame struct - // with the result. - virtual void LookupAddress(StackFrame *frame) const = 0; - - // If Windows stack walking information is available covering ADDRESS, - // return a WindowsFrameInfo structure describing it. If the information - // is not available, returns NULL. A NULL return value does not indicate - // an error. The caller takes ownership of any returned WindowsFrameInfo - // object. - virtual WindowsFrameInfo * - FindWindowsFrameInfo(const StackFrame *frame) const = 0; - - // If CFI stack walking information is available covering ADDRESS, - // return a CFIFrameInfo structure describing it. If the information - // is not available, return NULL. The caller takes ownership of any - // returned CFIFrameInfo object. - virtual CFIFrameInfo *FindCFIFrameInfo(const StackFrame *frame) const = 0; - protected: - virtual bool ParseCFIRuleSet(const string &rule_set, - CFIFrameInfo *frame_info) const; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_SOURCE_LINE_RESOLVER_BASE_TYPES_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_cpu.cc b/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_cpu.cc deleted file mode 100644 index 6175dc7f2..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_cpu.cc +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stack_frame_cpu.h: CPU-specific StackFrame extensions. -// -// See google_breakpad/processor/stack_frame_cpu.h for documentation. -// -// Author: Colin Blundell - -#include "google_breakpad/processor/stack_frame_cpu.h" - -namespace google_breakpad { - -const uint64_t StackFrameARM64::CONTEXT_VALID_X0; -const uint64_t StackFrameARM64::CONTEXT_VALID_X1; -const uint64_t StackFrameARM64::CONTEXT_VALID_X2; -const uint64_t StackFrameARM64::CONTEXT_VALID_X3; -const uint64_t StackFrameARM64::CONTEXT_VALID_X4; -const uint64_t StackFrameARM64::CONTEXT_VALID_X5; -const uint64_t StackFrameARM64::CONTEXT_VALID_X6; -const uint64_t StackFrameARM64::CONTEXT_VALID_X7; -const uint64_t StackFrameARM64::CONTEXT_VALID_X8; -const uint64_t StackFrameARM64::CONTEXT_VALID_X9; -const uint64_t StackFrameARM64::CONTEXT_VALID_X10; -const uint64_t StackFrameARM64::CONTEXT_VALID_X11; -const uint64_t StackFrameARM64::CONTEXT_VALID_X12; -const uint64_t StackFrameARM64::CONTEXT_VALID_X13; -const uint64_t StackFrameARM64::CONTEXT_VALID_X14; -const uint64_t StackFrameARM64::CONTEXT_VALID_X15; -const uint64_t StackFrameARM64::CONTEXT_VALID_X16; -const uint64_t StackFrameARM64::CONTEXT_VALID_X17; -const uint64_t StackFrameARM64::CONTEXT_VALID_X18; -const uint64_t StackFrameARM64::CONTEXT_VALID_X19; -const uint64_t StackFrameARM64::CONTEXT_VALID_X20; -const uint64_t StackFrameARM64::CONTEXT_VALID_X21; -const uint64_t StackFrameARM64::CONTEXT_VALID_X22; -const uint64_t StackFrameARM64::CONTEXT_VALID_X23; -const uint64_t StackFrameARM64::CONTEXT_VALID_X24; -const uint64_t StackFrameARM64::CONTEXT_VALID_X25; -const uint64_t StackFrameARM64::CONTEXT_VALID_X26; -const uint64_t StackFrameARM64::CONTEXT_VALID_X27; -const uint64_t StackFrameARM64::CONTEXT_VALID_X28; -const uint64_t StackFrameARM64::CONTEXT_VALID_X29; -const uint64_t StackFrameARM64::CONTEXT_VALID_X30; -const uint64_t StackFrameARM64::CONTEXT_VALID_X31; -const uint64_t StackFrameARM64::CONTEXT_VALID_X32; -const uint64_t StackFrameARM64::CONTEXT_VALID_FP; -const uint64_t StackFrameARM64::CONTEXT_VALID_LR; -const uint64_t StackFrameARM64::CONTEXT_VALID_SP; -const uint64_t StackFrameARM64::CONTEXT_VALID_PC; -const uint64_t StackFrameARM64::CONTEXT_VALID_ALL; - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_symbolizer.cc b/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_symbolizer.cc deleted file mode 100644 index 5c8dbe5e1..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stack_frame_symbolizer.cc +++ /dev/null @@ -1,138 +0,0 @@ -// Copyright (c) 2012 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Implementation of StackFrameSymbolizer, which encapsulates the logic of how -// SourceLineResolverInterface interacts with SymbolSupplier to fill source -// line information in a stack frame, and also looks up WindowsFrameInfo or -// CFIFrameInfo for a stack frame. - -#include "google_breakpad/processor/stack_frame_symbolizer.h" - -#include <assert.h> - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/code_modules.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame.h" -#include "google_breakpad/processor/symbol_supplier.h" -#include "google_breakpad/processor/system_info.h" -#include "processor/linked_ptr.h" -#include "processor/logging.h" - -namespace google_breakpad { - -StackFrameSymbolizer::StackFrameSymbolizer( - SymbolSupplier* supplier, - SourceLineResolverInterface* resolver) : supplier_(supplier), - resolver_(resolver) { } - -StackFrameSymbolizer::SymbolizerResult StackFrameSymbolizer::FillSourceLineInfo( - const CodeModules* modules, - const SystemInfo* system_info, - StackFrame* frame) { - assert(frame); - - if (!modules) return kError; - const CodeModule* module = modules->GetModuleForAddress(frame->instruction); - if (!module) return kError; - frame->module = module; - - if (!resolver_) return kError; // no resolver. - // If module is known to have missing symbol file, return. - if (no_symbol_modules_.find(module->code_file()) != - no_symbol_modules_.end()) { - return kError; - } - - // If module is already loaded, go ahead to fill source line info and return. - if (resolver_->HasModule(frame->module)) { - resolver_->FillSourceLineInfo(frame); - return resolver_->IsModuleCorrupt(frame->module) ? - kWarningCorruptSymbols : kNoError; - } - - // Module needs to fetch symbol file. First check to see if supplier exists. - if (!supplier_) { - return kError; - } - - // Start fetching symbol from supplier. - string symbol_file; - char* symbol_data = NULL; - size_t symbol_data_size; - SymbolSupplier::SymbolResult symbol_result = supplier_->GetCStringSymbolData( - module, system_info, &symbol_file, &symbol_data, &symbol_data_size); - - switch (symbol_result) { - case SymbolSupplier::FOUND: { - bool load_success = resolver_->LoadModuleUsingMemoryBuffer( - frame->module, - symbol_data, - symbol_data_size); - if (resolver_->ShouldDeleteMemoryBufferAfterLoadModule()) { - supplier_->FreeSymbolData(module); - } - - if (load_success) { - resolver_->FillSourceLineInfo(frame); - return resolver_->IsModuleCorrupt(frame->module) ? - kWarningCorruptSymbols : kNoError; - } else { - BPLOG(ERROR) << "Failed to load symbol file in resolver."; - no_symbol_modules_.insert(module->code_file()); - return kError; - } - } - - case SymbolSupplier::NOT_FOUND: - no_symbol_modules_.insert(module->code_file()); - return kError; - - case SymbolSupplier::INTERRUPT: - return kInterrupt; - - default: - BPLOG(ERROR) << "Unknown SymbolResult enum: " << symbol_result; - return kError; - } - return kError; -} - -WindowsFrameInfo* StackFrameSymbolizer::FindWindowsFrameInfo( - const StackFrame* frame) { - return resolver_ ? resolver_->FindWindowsFrameInfo(frame) : NULL; -} - -CFIFrameInfo* StackFrameSymbolizer::FindCFIFrameInfo( - const StackFrame* frame) { - return resolver_ ? resolver_->FindCFIFrameInfo(frame) : NULL; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.cc deleted file mode 100644 index 704039f34..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.cc +++ /dev/null @@ -1,950 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalk_common.cc: Module shared by the {micro,mini}dump_stackwalck -// executables to print the content of dumps (w/ stack traces) on the console. -// -// Author: Mark Mentovai - -#include "processor/stackwalk_common.h" - -#include <assert.h> -#include <stdlib.h> -#include <string.h> - -#include <string> -#include <vector> - -#include "common/stdio_wrapper.h" -#include "common/using_std_string.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/code_modules.h" -#include "google_breakpad/processor/process_state.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/logging.h" -#include "processor/pathname_stripper.h" - -namespace google_breakpad { - -namespace { - -using std::vector; - -// Separator character for machine readable output. -static const char kOutputSeparator = '|'; - -// PrintRegister prints a register's name and value to stdout. It will -// print four registers on a line. For the first register in a set, -// pass 0 for |start_col|. For registers in a set, pass the most recent -// return value of PrintRegister. -// The caller is responsible for printing the final newline after a set -// of registers is completely printed, regardless of the number of calls -// to PrintRegister. -static const int kMaxWidth = 80; // optimize for an 80-column terminal -static int PrintRegister(const char *name, uint32_t value, int start_col) { - char buffer[64]; - snprintf(buffer, sizeof(buffer), " %5s = 0x%08x", name, value); - - if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) { - start_col = 0; - printf("\n "); - } - fputs(buffer, stdout); - - return start_col + strlen(buffer); -} - -// PrintRegister64 does the same thing, but for 64-bit registers. -static int PrintRegister64(const char *name, uint64_t value, int start_col) { - char buffer[64]; - snprintf(buffer, sizeof(buffer), " %5s = 0x%016" PRIx64 , name, value); - - if (start_col + static_cast<ssize_t>(strlen(buffer)) > kMaxWidth) { - start_col = 0; - printf("\n "); - } - fputs(buffer, stdout); - - return start_col + strlen(buffer); -} - -// StripSeparator takes a string |original| and returns a copy -// of the string with all occurences of |kOutputSeparator| removed. -static string StripSeparator(const string &original) { - string result = original; - string::size_type position = 0; - while ((position = result.find(kOutputSeparator, position)) != string::npos) { - result.erase(position, 1); - } - position = 0; - while ((position = result.find('\n', position)) != string::npos) { - result.erase(position, 1); - } - return result; -} - -// PrintStackContents prints the stack contents of the current frame to stdout. -static void PrintStackContents(const string &indent, - const StackFrame *frame, - const StackFrame *prev_frame, - const string &cpu, - const MemoryRegion *memory, - const CodeModules* modules, - SourceLineResolverInterface *resolver) { - // Find stack range. - int word_length = 0; - uint64_t stack_begin = 0, stack_end = 0; - if (cpu == "x86") { - word_length = 4; - const StackFrameX86 *frame_x86 = static_cast<const StackFrameX86*>(frame); - const StackFrameX86 *prev_frame_x86 = - static_cast<const StackFrameX86*>(prev_frame); - if ((frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP) && - (prev_frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP)) { - stack_begin = frame_x86->context.esp; - stack_end = prev_frame_x86->context.esp; - } - } else if (cpu == "amd64") { - word_length = 8; - const StackFrameAMD64 *frame_amd64 = - static_cast<const StackFrameAMD64*>(frame); - const StackFrameAMD64 *prev_frame_amd64 = - static_cast<const StackFrameAMD64*>(prev_frame); - if ((frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP) && - (prev_frame_amd64->context_validity & - StackFrameAMD64::CONTEXT_VALID_RSP)) { - stack_begin = frame_amd64->context.rsp; - stack_end = prev_frame_amd64->context.rsp; - } - } else if (cpu == "arm") { - word_length = 4; - const StackFrameARM *frame_arm = static_cast<const StackFrameARM*>(frame); - const StackFrameARM *prev_frame_arm = - static_cast<const StackFrameARM*>(prev_frame); - if ((frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP) && - (prev_frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP)) { - stack_begin = frame_arm->context.iregs[13]; - stack_end = prev_frame_arm->context.iregs[13]; - } - } else if (cpu == "arm64") { - word_length = 8; - const StackFrameARM64 *frame_arm64 = - static_cast<const StackFrameARM64*>(frame); - const StackFrameARM64 *prev_frame_arm64 = - static_cast<const StackFrameARM64*>(prev_frame); - if ((frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) && - (prev_frame_arm64->context_validity & - StackFrameARM64::CONTEXT_VALID_SP)) { - stack_begin = frame_arm64->context.iregs[31]; - stack_end = prev_frame_arm64->context.iregs[31]; - } - } - if (!word_length || !stack_begin || !stack_end) - return; - - // Print stack contents. - printf("\n%sStack contents:", indent.c_str()); - for(uint64_t address = stack_begin; address < stack_end; ) { - // Print the start address of this row. - if (word_length == 4) - printf("\n%s %08x", indent.c_str(), static_cast<uint32_t>(address)); - else - printf("\n%s %016" PRIx64, indent.c_str(), address); - - // Print data in hex. - const int kBytesPerRow = 16; - string data_as_string; - for (int i = 0; i < kBytesPerRow; ++i, ++address) { - uint8_t value = 0; - if (address < stack_end && - memory->GetMemoryAtAddress(address, &value)) { - printf(" %02x", value); - data_as_string.push_back(isprint(value) ? value : '.'); - } else { - printf(" "); - data_as_string.push_back(' '); - } - } - // Print data as string. - printf(" %s", data_as_string.c_str()); - } - - // Try to find instruction pointers from stack. - printf("\n%sPossible instruction pointers:\n", indent.c_str()); - for (uint64_t address = stack_begin; address < stack_end; - address += word_length) { - StackFrame pointee_frame; - - // Read a word (possible instruction pointer) from stack. - if (word_length == 4) { - uint32_t data32 = 0; - memory->GetMemoryAtAddress(address, &data32); - pointee_frame.instruction = data32; - } else { - uint64_t data64 = 0; - memory->GetMemoryAtAddress(address, &data64); - pointee_frame.instruction = data64; - } - pointee_frame.module = - modules->GetModuleForAddress(pointee_frame.instruction); - - // Try to look up the function name. - if (pointee_frame.module) - resolver->FillSourceLineInfo(&pointee_frame); - - // Print function name. - if (!pointee_frame.function_name.empty()) { - if (word_length == 4) { - printf("%s *(0x%08x) = 0x%08x", indent.c_str(), - static_cast<uint32_t>(address), - static_cast<uint32_t>(pointee_frame.instruction)); - } else { - printf("%s *(0x%016" PRIx64 ") = 0x%016" PRIx64, - indent.c_str(), address, pointee_frame.instruction); - } - printf(" <%s> [%s : %d + 0x%" PRIx64 "]\n", - pointee_frame.function_name.c_str(), - PathnameStripper::File(pointee_frame.source_file_name).c_str(), - pointee_frame.source_line, - pointee_frame.instruction - pointee_frame.source_line_base); - } - } - printf("\n"); -} - -// PrintStack prints the call stack in |stack| to stdout, in a reasonably -// useful form. Module, function, and source file names are displayed if -// they are available. The code offset to the base code address of the -// source line, function, or module is printed, preferring them in that -// order. If no source line, function, or module information is available, -// an absolute code offset is printed. -// -// If |cpu| is a recognized CPU name, relevant register state for each stack -// frame printed is also output, if available. -static void PrintStack(const CallStack *stack, - const string &cpu, - bool output_stack_contents, - const MemoryRegion* memory, - const CodeModules* modules, - SourceLineResolverInterface* resolver) { - int frame_count = stack->frames()->size(); - if (frame_count == 0) { - printf(" <no frames>\n"); - } - for (int frame_index = 0; frame_index < frame_count; ++frame_index) { - const StackFrame *frame = stack->frames()->at(frame_index); - printf("%2d ", frame_index); - - uint64_t instruction_address = frame->ReturnAddress(); - - if (frame->module) { - printf("%s", PathnameStripper::File(frame->module->code_file()).c_str()); - if (!frame->function_name.empty()) { - printf("!%s", frame->function_name.c_str()); - if (!frame->source_file_name.empty()) { - string source_file = PathnameStripper::File(frame->source_file_name); - printf(" [%s : %d + 0x%" PRIx64 "]", - source_file.c_str(), - frame->source_line, - instruction_address - frame->source_line_base); - } else { - printf(" + 0x%" PRIx64, instruction_address - frame->function_base); - } - } else { - printf(" + 0x%" PRIx64, - instruction_address - frame->module->base_address()); - } - } else { - printf("0x%" PRIx64, instruction_address); - } - printf("\n "); - - int sequence = 0; - if (cpu == "x86") { - const StackFrameX86 *frame_x86 = - reinterpret_cast<const StackFrameX86*>(frame); - - if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EIP) - sequence = PrintRegister("eip", frame_x86->context.eip, sequence); - if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESP) - sequence = PrintRegister("esp", frame_x86->context.esp, sequence); - if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBP) - sequence = PrintRegister("ebp", frame_x86->context.ebp, sequence); - if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EBX) - sequence = PrintRegister("ebx", frame_x86->context.ebx, sequence); - if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_ESI) - sequence = PrintRegister("esi", frame_x86->context.esi, sequence); - if (frame_x86->context_validity & StackFrameX86::CONTEXT_VALID_EDI) - sequence = PrintRegister("edi", frame_x86->context.edi, sequence); - if (frame_x86->context_validity == StackFrameX86::CONTEXT_VALID_ALL) { - sequence = PrintRegister("eax", frame_x86->context.eax, sequence); - sequence = PrintRegister("ecx", frame_x86->context.ecx, sequence); - sequence = PrintRegister("edx", frame_x86->context.edx, sequence); - sequence = PrintRegister("efl", frame_x86->context.eflags, sequence); - } - } else if (cpu == "ppc") { - const StackFramePPC *frame_ppc = - reinterpret_cast<const StackFramePPC*>(frame); - - if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_SRR0) - sequence = PrintRegister("srr0", frame_ppc->context.srr0, sequence); - if (frame_ppc->context_validity & StackFramePPC::CONTEXT_VALID_GPR1) - sequence = PrintRegister("r1", frame_ppc->context.gpr[1], sequence); - } else if (cpu == "amd64") { - const StackFrameAMD64 *frame_amd64 = - reinterpret_cast<const StackFrameAMD64*>(frame); - - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RAX) - sequence = PrintRegister64("rax", frame_amd64->context.rax, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDX) - sequence = PrintRegister64("rdx", frame_amd64->context.rdx, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RCX) - sequence = PrintRegister64("rcx", frame_amd64->context.rcx, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBX) - sequence = PrintRegister64("rbx", frame_amd64->context.rbx, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSI) - sequence = PrintRegister64("rsi", frame_amd64->context.rsi, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RDI) - sequence = PrintRegister64("rdi", frame_amd64->context.rdi, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP) - sequence = PrintRegister64("rbp", frame_amd64->context.rbp, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RSP) - sequence = PrintRegister64("rsp", frame_amd64->context.rsp, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R8) - sequence = PrintRegister64("r8", frame_amd64->context.r8, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R9) - sequence = PrintRegister64("r9", frame_amd64->context.r9, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R10) - sequence = PrintRegister64("r10", frame_amd64->context.r10, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R11) - sequence = PrintRegister64("r11", frame_amd64->context.r11, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R12) - sequence = PrintRegister64("r12", frame_amd64->context.r12, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R13) - sequence = PrintRegister64("r13", frame_amd64->context.r13, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R14) - sequence = PrintRegister64("r14", frame_amd64->context.r14, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_R15) - sequence = PrintRegister64("r15", frame_amd64->context.r15, sequence); - if (frame_amd64->context_validity & StackFrameAMD64::CONTEXT_VALID_RIP) - sequence = PrintRegister64("rip", frame_amd64->context.rip, sequence); - } else if (cpu == "sparc") { - const StackFrameSPARC *frame_sparc = - reinterpret_cast<const StackFrameSPARC*>(frame); - - if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_SP) - sequence = PrintRegister("sp", frame_sparc->context.g_r[14], sequence); - if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_FP) - sequence = PrintRegister("fp", frame_sparc->context.g_r[30], sequence); - if (frame_sparc->context_validity & StackFrameSPARC::CONTEXT_VALID_PC) - sequence = PrintRegister("pc", frame_sparc->context.pc, sequence); - } else if (cpu == "arm") { - const StackFrameARM *frame_arm = - reinterpret_cast<const StackFrameARM*>(frame); - - // Argument registers (caller-saves), which will likely only be valid - // for the youngest frame. - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R0) - sequence = PrintRegister("r0", frame_arm->context.iregs[0], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R1) - sequence = PrintRegister("r1", frame_arm->context.iregs[1], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R2) - sequence = PrintRegister("r2", frame_arm->context.iregs[2], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R3) - sequence = PrintRegister("r3", frame_arm->context.iregs[3], sequence); - - // General-purpose callee-saves registers. - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R4) - sequence = PrintRegister("r4", frame_arm->context.iregs[4], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R5) - sequence = PrintRegister("r5", frame_arm->context.iregs[5], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R6) - sequence = PrintRegister("r6", frame_arm->context.iregs[6], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R7) - sequence = PrintRegister("r7", frame_arm->context.iregs[7], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R8) - sequence = PrintRegister("r8", frame_arm->context.iregs[8], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R9) - sequence = PrintRegister("r9", frame_arm->context.iregs[9], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R10) - sequence = PrintRegister("r10", frame_arm->context.iregs[10], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_R12) - sequence = PrintRegister("r12", frame_arm->context.iregs[12], sequence); - - // Registers with a dedicated or conventional purpose. - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_FP) - sequence = PrintRegister("fp", frame_arm->context.iregs[11], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_SP) - sequence = PrintRegister("sp", frame_arm->context.iregs[13], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_LR) - sequence = PrintRegister("lr", frame_arm->context.iregs[14], sequence); - if (frame_arm->context_validity & StackFrameARM::CONTEXT_VALID_PC) - sequence = PrintRegister("pc", frame_arm->context.iregs[15], sequence); - } else if (cpu == "arm64") { - const StackFrameARM64 *frame_arm64 = - reinterpret_cast<const StackFrameARM64*>(frame); - - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X0) { - sequence = - PrintRegister64("x0", frame_arm64->context.iregs[0], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X1) { - sequence = - PrintRegister64("x1", frame_arm64->context.iregs[1], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X2) { - sequence = - PrintRegister64("x2", frame_arm64->context.iregs[2], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X3) { - sequence = - PrintRegister64("x3", frame_arm64->context.iregs[3], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X4) { - sequence = - PrintRegister64("x4", frame_arm64->context.iregs[4], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X5) { - sequence = - PrintRegister64("x5", frame_arm64->context.iregs[5], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X6) { - sequence = - PrintRegister64("x6", frame_arm64->context.iregs[6], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X7) { - sequence = - PrintRegister64("x7", frame_arm64->context.iregs[7], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X8) { - sequence = - PrintRegister64("x8", frame_arm64->context.iregs[8], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X9) { - sequence = - PrintRegister64("x9", frame_arm64->context.iregs[9], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X10) { - sequence = - PrintRegister64("x10", frame_arm64->context.iregs[10], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X11) { - sequence = - PrintRegister64("x11", frame_arm64->context.iregs[11], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X12) { - sequence = - PrintRegister64("x12", frame_arm64->context.iregs[12], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X13) { - sequence = - PrintRegister64("x13", frame_arm64->context.iregs[13], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X14) { - sequence = - PrintRegister64("x14", frame_arm64->context.iregs[14], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X15) { - sequence = - PrintRegister64("x15", frame_arm64->context.iregs[15], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X16) { - sequence = - PrintRegister64("x16", frame_arm64->context.iregs[16], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X17) { - sequence = - PrintRegister64("x17", frame_arm64->context.iregs[17], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X18) { - sequence = - PrintRegister64("x18", frame_arm64->context.iregs[18], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X19) { - sequence = - PrintRegister64("x19", frame_arm64->context.iregs[19], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X20) { - sequence = - PrintRegister64("x20", frame_arm64->context.iregs[20], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X21) { - sequence = - PrintRegister64("x21", frame_arm64->context.iregs[21], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X22) { - sequence = - PrintRegister64("x22", frame_arm64->context.iregs[22], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X23) { - sequence = - PrintRegister64("x23", frame_arm64->context.iregs[23], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X24) { - sequence = - PrintRegister64("x24", frame_arm64->context.iregs[24], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X25) { - sequence = - PrintRegister64("x25", frame_arm64->context.iregs[25], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X26) { - sequence = - PrintRegister64("x26", frame_arm64->context.iregs[26], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X27) { - sequence = - PrintRegister64("x27", frame_arm64->context.iregs[27], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_X28) { - sequence = - PrintRegister64("x28", frame_arm64->context.iregs[28], sequence); - } - - // Registers with a dedicated or conventional purpose. - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_FP) { - sequence = - PrintRegister64("fp", frame_arm64->context.iregs[29], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_LR) { - sequence = - PrintRegister64("lr", frame_arm64->context.iregs[30], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_SP) { - sequence = - PrintRegister64("sp", frame_arm64->context.iregs[31], sequence); - } - if (frame_arm64->context_validity & StackFrameARM64::CONTEXT_VALID_PC) { - sequence = - PrintRegister64("pc", frame_arm64->context.iregs[32], sequence); - } - } else if ((cpu == "mips") || (cpu == "mips64")) { - const StackFrameMIPS* frame_mips = - reinterpret_cast<const StackFrameMIPS*>(frame); - - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_GP) - sequence = PrintRegister64("gp", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_GP], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_SP) - sequence = PrintRegister64("sp", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_SP], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_FP) - sequence = PrintRegister64("fp", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_FP], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_RA) - sequence = PrintRegister64("ra", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_RA], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_PC) - sequence = PrintRegister64("pc", frame_mips->context.epc, sequence); - - // Save registers s0-s7 - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S0) - sequence = PrintRegister64("s0", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S0], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S1) - sequence = PrintRegister64("s1", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S1], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S2) - sequence = PrintRegister64("s2", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S2], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S3) - sequence = PrintRegister64("s3", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S3], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S4) - sequence = PrintRegister64("s4", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S4], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S5) - sequence = PrintRegister64("s5", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S5], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S6) - sequence = PrintRegister64("s6", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S6], - sequence); - if (frame_mips->context_validity & StackFrameMIPS::CONTEXT_VALID_S7) - sequence = PrintRegister64("s7", - frame_mips->context.iregs[MD_CONTEXT_MIPS_REG_S7], - sequence); - } - printf("\n Found by: %s\n", frame->trust_description().c_str()); - - // Print stack contents. - if (output_stack_contents && frame_index + 1 < frame_count) { - const string indent(" "); - PrintStackContents(indent, frame, stack->frames()->at(frame_index + 1), - cpu, memory, modules, resolver); - } - } -} - -// PrintStackMachineReadable prints the call stack in |stack| to stdout, -// in the following machine readable pipe-delimited text format: -// thread number|frame number|module|function|source file|line|offset -// -// Module, function, source file, and source line may all be empty -// depending on availability. The code offset follows the same rules as -// PrintStack above. -static void PrintStackMachineReadable(int thread_num, const CallStack *stack) { - int frame_count = stack->frames()->size(); - for (int frame_index = 0; frame_index < frame_count; ++frame_index) { - const StackFrame *frame = stack->frames()->at(frame_index); - printf("%d%c%d%c", thread_num, kOutputSeparator, frame_index, - kOutputSeparator); - - uint64_t instruction_address = frame->ReturnAddress(); - - if (frame->module) { - assert(!frame->module->code_file().empty()); - printf("%s", StripSeparator(PathnameStripper::File( - frame->module->code_file())).c_str()); - if (!frame->function_name.empty()) { - printf("%c%s", kOutputSeparator, - StripSeparator(frame->function_name).c_str()); - if (!frame->source_file_name.empty()) { - printf("%c%s%c%d%c0x%" PRIx64, - kOutputSeparator, - StripSeparator(frame->source_file_name).c_str(), - kOutputSeparator, - frame->source_line, - kOutputSeparator, - instruction_address - frame->source_line_base); - } else { - printf("%c%c%c0x%" PRIx64, - kOutputSeparator, // empty source file - kOutputSeparator, // empty source line - kOutputSeparator, - instruction_address - frame->function_base); - } - } else { - printf("%c%c%c%c0x%" PRIx64, - kOutputSeparator, // empty function name - kOutputSeparator, // empty source file - kOutputSeparator, // empty source line - kOutputSeparator, - instruction_address - frame->module->base_address()); - } - } else { - // the printf before this prints a trailing separator for module name - printf("%c%c%c%c0x%" PRIx64, - kOutputSeparator, // empty function name - kOutputSeparator, // empty source file - kOutputSeparator, // empty source line - kOutputSeparator, - instruction_address); - } - printf("\n"); - } -} - -// ContainsModule checks whether a given |module| is in the vector -// |modules_without_symbols|. -static bool ContainsModule( - const vector<const CodeModule*> *modules, - const CodeModule *module) { - assert(modules); - assert(module); - vector<const CodeModule*>::const_iterator iter; - for (iter = modules->begin(); iter != modules->end(); ++iter) { - if (module->debug_file().compare((*iter)->debug_file()) == 0 && - module->debug_identifier().compare((*iter)->debug_identifier()) == 0) { - return true; - } - } - return false; -} - -// PrintModule prints a single |module| to stdout. -// |modules_without_symbols| should contain the list of modules that were -// confirmed to be missing their symbols during the stack walk. -static void PrintModule( - const CodeModule *module, - const vector<const CodeModule*> *modules_without_symbols, - const vector<const CodeModule*> *modules_with_corrupt_symbols, - uint64_t main_address) { - string symbol_issues; - if (ContainsModule(modules_without_symbols, module)) { - symbol_issues = " (WARNING: No symbols, " + - PathnameStripper::File(module->debug_file()) + ", " + - module->debug_identifier() + ")"; - } else if (ContainsModule(modules_with_corrupt_symbols, module)) { - symbol_issues = " (WARNING: Corrupt symbols, " + - PathnameStripper::File(module->debug_file()) + ", " + - module->debug_identifier() + ")"; - } - uint64_t base_address = module->base_address(); - printf("0x%08" PRIx64 " - 0x%08" PRIx64 " %s %s%s%s\n", - base_address, base_address + module->size() - 1, - PathnameStripper::File(module->code_file()).c_str(), - module->version().empty() ? "???" : module->version().c_str(), - main_address != 0 && base_address == main_address ? " (main)" : "", - symbol_issues.c_str()); -} - -// PrintModules prints the list of all loaded |modules| to stdout. -// |modules_without_symbols| should contain the list of modules that were -// confirmed to be missing their symbols during the stack walk. -static void PrintModules( - const CodeModules *modules, - const vector<const CodeModule*> *modules_without_symbols, - const vector<const CodeModule*> *modules_with_corrupt_symbols) { - if (!modules) - return; - - printf("\n"); - printf("Loaded modules:\n"); - - uint64_t main_address = 0; - const CodeModule *main_module = modules->GetMainModule(); - if (main_module) { - main_address = main_module->base_address(); - } - - unsigned int module_count = modules->module_count(); - for (unsigned int module_sequence = 0; - module_sequence < module_count; - ++module_sequence) { - const CodeModule *module = modules->GetModuleAtSequence(module_sequence); - PrintModule(module, modules_without_symbols, modules_with_corrupt_symbols, - main_address); - } -} - -// PrintModulesMachineReadable outputs a list of loaded modules, -// one per line, in the following machine-readable pipe-delimited -// text format: -// Module|{Module Filename}|{Version}|{Debug Filename}|{Debug Identifier}| -// {Base Address}|{Max Address}|{Main} -static void PrintModulesMachineReadable(const CodeModules *modules) { - if (!modules) - return; - - uint64_t main_address = 0; - const CodeModule *main_module = modules->GetMainModule(); - if (main_module) { - main_address = main_module->base_address(); - } - - unsigned int module_count = modules->module_count(); - for (unsigned int module_sequence = 0; - module_sequence < module_count; - ++module_sequence) { - const CodeModule *module = modules->GetModuleAtSequence(module_sequence); - uint64_t base_address = module->base_address(); - printf("Module%c%s%c%s%c%s%c%s%c0x%08" PRIx64 "%c0x%08" PRIx64 "%c%d\n", - kOutputSeparator, - StripSeparator(PathnameStripper::File(module->code_file())).c_str(), - kOutputSeparator, StripSeparator(module->version()).c_str(), - kOutputSeparator, - StripSeparator(PathnameStripper::File(module->debug_file())).c_str(), - kOutputSeparator, - StripSeparator(module->debug_identifier()).c_str(), - kOutputSeparator, base_address, - kOutputSeparator, base_address + module->size() - 1, - kOutputSeparator, - main_module != NULL && base_address == main_address ? 1 : 0); - } -} - -} // namespace - -void PrintProcessState(const ProcessState& process_state, - bool output_stack_contents, - SourceLineResolverInterface* resolver) { - // Print OS and CPU information. - string cpu = process_state.system_info()->cpu; - string cpu_info = process_state.system_info()->cpu_info; - printf("Operating system: %s\n", process_state.system_info()->os.c_str()); - printf(" %s\n", - process_state.system_info()->os_version.c_str()); - printf("CPU: %s\n", cpu.c_str()); - if (!cpu_info.empty()) { - // This field is optional. - printf(" %s\n", cpu_info.c_str()); - } - printf(" %d CPU%s\n", - process_state.system_info()->cpu_count, - process_state.system_info()->cpu_count != 1 ? "s" : ""); - printf("\n"); - - // Print GPU information - string gl_version = process_state.system_info()->gl_version; - string gl_vendor = process_state.system_info()->gl_vendor; - string gl_renderer = process_state.system_info()->gl_renderer; - printf("GPU:"); - if (!gl_version.empty() || !gl_vendor.empty() || !gl_renderer.empty()) { - printf(" %s\n", gl_version.c_str()); - printf(" %s\n", gl_vendor.c_str()); - printf(" %s\n", gl_renderer.c_str()); - } else { - printf(" UNKNOWN\n"); - } - printf("\n"); - - // Print crash information. - if (process_state.crashed()) { - printf("Crash reason: %s\n", process_state.crash_reason().c_str()); - printf("Crash address: 0x%" PRIx64 "\n", process_state.crash_address()); - } else { - printf("No crash\n"); - } - - string assertion = process_state.assertion(); - if (!assertion.empty()) { - printf("Assertion: %s\n", assertion.c_str()); - } - - // Compute process uptime if the process creation and crash times are - // available in the dump. - if (process_state.time_date_stamp() != 0 && - process_state.process_create_time() != 0 && - process_state.time_date_stamp() >= process_state.process_create_time()) { - printf("Process uptime: %d seconds\n", - process_state.time_date_stamp() - - process_state.process_create_time()); - } else { - printf("Process uptime: not available\n"); - } - - // If the thread that requested the dump is known, print it first. - int requesting_thread = process_state.requesting_thread(); - if (requesting_thread != -1) { - printf("\n"); - printf("Thread %d (%s)\n", - requesting_thread, - process_state.crashed() ? "crashed" : - "requested dump, did not crash"); - PrintStack(process_state.threads()->at(requesting_thread), cpu, - output_stack_contents, - process_state.thread_memory_regions()->at(requesting_thread), - process_state.modules(), resolver); - } - - // Print all of the threads in the dump. - int thread_count = process_state.threads()->size(); - for (int thread_index = 0; thread_index < thread_count; ++thread_index) { - if (thread_index != requesting_thread) { - // Don't print the crash thread again, it was already printed. - printf("\n"); - printf("Thread %d\n", thread_index); - PrintStack(process_state.threads()->at(thread_index), cpu, - output_stack_contents, - process_state.thread_memory_regions()->at(thread_index), - process_state.modules(), resolver); - } - } - - PrintModules(process_state.modules(), - process_state.modules_without_symbols(), - process_state.modules_with_corrupt_symbols()); -} - -void PrintProcessStateMachineReadable(const ProcessState& process_state) { - // Print OS and CPU information. - // OS|{OS Name}|{OS Version} - // CPU|{CPU Name}|{CPU Info}|{Number of CPUs} - // GPU|{GPU version}|{GPU vendor}|{GPU renderer} - printf("OS%c%s%c%s\n", kOutputSeparator, - StripSeparator(process_state.system_info()->os).c_str(), - kOutputSeparator, - StripSeparator(process_state.system_info()->os_version).c_str()); - printf("CPU%c%s%c%s%c%d\n", kOutputSeparator, - StripSeparator(process_state.system_info()->cpu).c_str(), - kOutputSeparator, - // this may be empty - StripSeparator(process_state.system_info()->cpu_info).c_str(), - kOutputSeparator, - process_state.system_info()->cpu_count); - printf("GPU%c%s%c%s%c%s\n", kOutputSeparator, - StripSeparator(process_state.system_info()->gl_version).c_str(), - kOutputSeparator, - StripSeparator(process_state.system_info()->gl_vendor).c_str(), - kOutputSeparator, - StripSeparator(process_state.system_info()->gl_renderer).c_str()); - - int requesting_thread = process_state.requesting_thread(); - - // Print crash information. - // Crash|{Crash Reason}|{Crash Address}|{Crashed Thread} - printf("Crash%c", kOutputSeparator); - if (process_state.crashed()) { - printf("%s%c0x%" PRIx64 "%c", - StripSeparator(process_state.crash_reason()).c_str(), - kOutputSeparator, process_state.crash_address(), kOutputSeparator); - } else { - // print assertion info, if available, in place of crash reason, - // instead of the unhelpful "No crash" - string assertion = process_state.assertion(); - if (!assertion.empty()) { - printf("%s%c%c", StripSeparator(assertion).c_str(), - kOutputSeparator, kOutputSeparator); - } else { - printf("No crash%c%c", kOutputSeparator, kOutputSeparator); - } - } - - if (requesting_thread != -1) { - printf("%d\n", requesting_thread); - } else { - printf("\n"); - } - - PrintModulesMachineReadable(process_state.modules()); - - // blank line to indicate start of threads - printf("\n"); - - // If the thread that requested the dump is known, print it first. - if (requesting_thread != -1) { - PrintStackMachineReadable(requesting_thread, - process_state.threads()->at(requesting_thread)); - } - - // Print all of the threads in the dump. - int thread_count = process_state.threads()->size(); - for (int thread_index = 0; thread_index < thread_count; ++thread_index) { - if (thread_index != requesting_thread) { - // Don't print the crash thread again, it was already printed. - PrintStackMachineReadable(thread_index, - process_state.threads()->at(thread_index)); - } - } -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.h deleted file mode 100644 index a74f7b6da..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalk_common.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalk_common.cc: Module shared by the {micro,mini}dump_stackwalck -// executables to print the content of dumps (w/ stack traces) on the console. - - -#ifndef PROCESSOR_STACKWALK_COMMON_H__ -#define PROCESSOR_STACKWALK_COMMON_H__ - -namespace google_breakpad { - -class ProcessState; -class SourceLineResolverInterface; - -void PrintProcessStateMachineReadable(const ProcessState& process_state); -void PrintProcessState(const ProcessState& process_state, - bool output_stack_contents, - SourceLineResolverInterface* resolver); - -} // namespace google_breakpad - -#endif // PROCESSOR_STACKWALK_COMMON_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc deleted file mode 100644 index 98cb0b5be..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker.cc +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker.cc: Generic stackwalker. -// -// See stackwalker.h for documentation. -// -// Author: Mark Mentovai - -#include "google_breakpad/processor/stackwalker.h" - -#include <assert.h> - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/code_modules.h" -#include "google_breakpad/processor/dump_context.h" -#include "google_breakpad/processor/stack_frame.h" -#include "google_breakpad/processor/stack_frame_symbolizer.h" -#include "google_breakpad/processor/system_info.h" -#include "processor/linked_ptr.h" -#include "processor/logging.h" -#include "processor/stackwalker_ppc.h" -#include "processor/stackwalker_ppc64.h" -#include "processor/stackwalker_sparc.h" -#include "processor/stackwalker_x86.h" -#include "processor/stackwalker_amd64.h" -#include "processor/stackwalker_arm.h" -#include "processor/stackwalker_arm64.h" -#include "processor/stackwalker_mips.h" - -namespace google_breakpad { - -const int Stackwalker::kRASearchWords = 40; - -uint32_t Stackwalker::max_frames_ = 1024; -bool Stackwalker::max_frames_set_ = false; - -uint32_t Stackwalker::max_frames_scanned_ = 1024; - -Stackwalker::Stackwalker(const SystemInfo* system_info, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer) - : system_info_(system_info), - memory_(memory), - modules_(modules), - frame_symbolizer_(frame_symbolizer) { - assert(frame_symbolizer_); -} - -void InsertSpecialAttentionModule( - StackFrameSymbolizer::SymbolizerResult symbolizer_result, - const CodeModule* module, - vector<const CodeModule*>* modules) { - if (!module) { - return; - } - assert(symbolizer_result == StackFrameSymbolizer::kError || - symbolizer_result == StackFrameSymbolizer::kWarningCorruptSymbols); - bool found = false; - vector<const CodeModule*>::iterator iter; - for (iter = modules->begin(); iter != modules->end(); ++iter) { - if (*iter == module) { - found = true; - break; - } - } - if (!found) { - BPLOG(INFO) << ((symbolizer_result == StackFrameSymbolizer::kError) ? - "Couldn't load symbols for: " : - "Detected corrupt symbols for: ") - << module->debug_file() << "|" << module->debug_identifier(); - modules->push_back(module); - } -} - -bool Stackwalker::Walk( - CallStack* stack, - vector<const CodeModule*>* modules_without_symbols, - vector<const CodeModule*>* modules_with_corrupt_symbols) { - BPLOG_IF(ERROR, !stack) << "Stackwalker::Walk requires |stack|"; - assert(stack); - stack->Clear(); - - BPLOG_IF(ERROR, !modules_without_symbols) << "Stackwalker::Walk requires " - << "|modules_without_symbols|"; - BPLOG_IF(ERROR, !modules_without_symbols) << "Stackwalker::Walk requires " - << "|modules_with_corrupt_symbols|"; - assert(modules_without_symbols); - assert(modules_with_corrupt_symbols); - - // Begin with the context frame, and keep getting callers until there are - // no more. - - // Keep track of the number of scanned or otherwise dubious frames seen - // so far, as the caller may have set a limit. - uint32_t scanned_frames = 0; - - // Take ownership of the pointer returned by GetContextFrame. - scoped_ptr<StackFrame> frame(GetContextFrame()); - - while (frame.get()) { - // frame already contains a good frame with properly set instruction and - // frame_pointer fields. The frame structure comes from either the - // context frame (above) or a caller frame (below). - - // Resolve the module information, if a module map was provided. - StackFrameSymbolizer::SymbolizerResult symbolizer_result = - frame_symbolizer_->FillSourceLineInfo(modules_, system_info_, - frame.get()); - switch (symbolizer_result) { - case StackFrameSymbolizer::kInterrupt: - BPLOG(INFO) << "Stack walk is interrupted."; - return false; - break; - case StackFrameSymbolizer::kError: - InsertSpecialAttentionModule(symbolizer_result, frame->module, - modules_without_symbols); - break; - case StackFrameSymbolizer::kWarningCorruptSymbols: - InsertSpecialAttentionModule(symbolizer_result, frame->module, - modules_with_corrupt_symbols); - break; - case StackFrameSymbolizer::kNoError: - break; - default: - assert(false); - break; - } - - // Keep track of the number of dubious frames so far. - switch (frame.get()->trust) { - case StackFrame::FRAME_TRUST_NONE: - case StackFrame::FRAME_TRUST_SCAN: - case StackFrame::FRAME_TRUST_CFI_SCAN: - scanned_frames++; - break; - default: - break; - } - - // Add the frame to the call stack. Relinquish the ownership claim - // over the frame, because the stack now owns it. - stack->frames_.push_back(frame.release()); - if (stack->frames_.size() > max_frames_) { - // Only emit an error message in the case where the limit - // reached is the default limit, not set by the user. - if (!max_frames_set_) - BPLOG(ERROR) << "The stack is over " << max_frames_ << " frames."; - break; - } - - // Get the next frame and take ownership. - bool stack_scan_allowed = scanned_frames < max_frames_scanned_; - frame.reset(GetCallerFrame(stack, stack_scan_allowed)); - } - - return true; -} - - -// static -Stackwalker* Stackwalker::StackwalkerForCPU( - const SystemInfo* system_info, - DumpContext* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer) { - if (!context) { - BPLOG(ERROR) << "Can't choose a stackwalker implementation without context"; - return NULL; - } - - Stackwalker* cpu_stackwalker = NULL; - - uint32_t cpu = context->GetContextCPU(); - switch (cpu) { - case MD_CONTEXT_X86: - cpu_stackwalker = new StackwalkerX86(system_info, - context->GetContextX86(), - memory, modules, frame_symbolizer); - break; - - case MD_CONTEXT_PPC: - cpu_stackwalker = new StackwalkerPPC(system_info, - context->GetContextPPC(), - memory, modules, frame_symbolizer); - break; - - case MD_CONTEXT_PPC64: - cpu_stackwalker = new StackwalkerPPC64(system_info, - context->GetContextPPC64(), - memory, modules, frame_symbolizer); - break; - - case MD_CONTEXT_AMD64: - cpu_stackwalker = new StackwalkerAMD64(system_info, - context->GetContextAMD64(), - memory, modules, frame_symbolizer); - break; - - case MD_CONTEXT_SPARC: - cpu_stackwalker = new StackwalkerSPARC(system_info, - context->GetContextSPARC(), - memory, modules, frame_symbolizer); - break; - - case MD_CONTEXT_MIPS: - case MD_CONTEXT_MIPS64: - cpu_stackwalker = new StackwalkerMIPS(system_info, - context->GetContextMIPS(), - memory, modules, frame_symbolizer); - break; - - case MD_CONTEXT_ARM: - { - int fp_register = -1; - if (system_info->os_short == "ios") - fp_register = MD_CONTEXT_ARM_REG_IOS_FP; - cpu_stackwalker = new StackwalkerARM(system_info, - context->GetContextARM(), - fp_register, memory, modules, - frame_symbolizer); - break; - } - - case MD_CONTEXT_ARM64: - cpu_stackwalker = new StackwalkerARM64(system_info, - context->GetContextARM64(), - memory, modules, - frame_symbolizer); - break; - } - - BPLOG_IF(ERROR, !cpu_stackwalker) << "Unknown CPU type " << HexString(cpu) << - ", can't choose a stackwalker " - "implementation"; - return cpu_stackwalker; -} - -bool Stackwalker::InstructionAddressSeemsValid(uint64_t address) { - StackFrame frame; - frame.instruction = address; - StackFrameSymbolizer::SymbolizerResult symbolizer_result = - frame_symbolizer_->FillSourceLineInfo(modules_, system_info_, &frame); - - if (!frame.module) { - // not inside any loaded module - return false; - } - - if (!frame_symbolizer_->HasImplementation()) { - // No valid implementation to symbolize stack frame, but the address is - // within a known module. - return true; - } - - if (symbolizer_result != StackFrameSymbolizer::kNoError && - symbolizer_result != StackFrameSymbolizer::kWarningCorruptSymbols) { - // Some error occurred during symbolization, but the address is within a - // known module - return true; - } - - return !frame.function_name.empty(); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.cc deleted file mode 100644 index e81fec282..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.cc +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_address_list.cc: a pseudo stack walker. -// -// See stackwalker_address_list.h for documentation. -// -// Author: Chris Hamilton <chrisha@chromium.org> - -#include <assert.h> - -#include <vector> - -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame.h" -#include "processor/logging.h" -#include "processor/stackwalker_address_list.h" - -namespace google_breakpad { - -StackwalkerAddressList::StackwalkerAddressList( - const uint64_t* frames, - size_t frame_count, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer) - : Stackwalker(NULL, NULL, modules, frame_symbolizer), - frames_(frames), - frame_count_(frame_count) { - assert(frames); - assert(frame_symbolizer); -} - -StackFrame* StackwalkerAddressList::GetContextFrame() { - if (frame_count_ == 0) - return NULL; - - StackFrame* frame = new StackFrame(); - frame->instruction = frames_[0]; - frame->trust = StackFrame::FRAME_TRUST_PREWALKED; - return frame; -} - -StackFrame* StackwalkerAddressList::GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed) { - if (!stack) { - BPLOG(ERROR) << "Can't get caller frame without stack"; - return NULL; - } - - size_t frame_index = stack->frames()->size(); - - // There are no more frames to fetch. - if (frame_index >= frame_count_) - return NULL; - - // All frames have the highest level of trust because they were - // explicitly provided. - StackFrame* frame = new StackFrame(); - frame->instruction = frames_[frame_index]; - frame->trust = StackFrame::FRAME_TRUST_PREWALKED; - return frame; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.h deleted file mode 100644 index 0f8c989ef..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list.h +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_address_list.h: a pseudo stackwalker. -// -// Doesn't actually walk a stack, rather initializes a CallStack given an -// explicit list of already walked return addresses. -// -// Author: Chris Hamilton <chrisha@chromium.org> - -#ifndef PROCESSOR_STACKWALKER_ADDRESS_LIST_H_ -#define PROCESSOR_STACKWALKER_ADDRESS_LIST_H_ - -#include "common/basictypes.h" -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/processor/stackwalker.h" - -namespace google_breakpad { - -class CodeModules; - -class StackwalkerAddressList : public Stackwalker { - public: - // Initializes this stack walker with an explicit set of frame addresses. - // |modules| and |frame_symbolizer| are passed directly through to the base - // Stackwalker constructor. - StackwalkerAddressList(const uint64_t* frames, - size_t frame_count, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer); - - private: - // Implementation of Stackwalker. - virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed); - - const uint64_t* frames_; - size_t frame_count_; - - DISALLOW_COPY_AND_ASSIGN(StackwalkerAddressList); -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_STACKWALKER_ADDRESS_LIST_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list_unittest.cc deleted file mode 100644 index ab4e9c088..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_address_list_unittest.cc +++ /dev/null @@ -1,197 +0,0 @@ -// Copyright (c) 2013, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_address_list_unittest.cc: Unit tests for the -// StackwalkerAddressList class. -// -// Author: Chris Hamilton <chrisha@chromium.org> - -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame.h" -#include "processor/stackwalker_unittest_utils.h" -#include "processor/stackwalker_address_list.h" - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::CallStack; -using google_breakpad::CodeModule; -using google_breakpad::StackFrameSymbolizer; -using google_breakpad::StackFrame; -using google_breakpad::Stackwalker; -using google_breakpad::StackwalkerAddressList; -using std::vector; -using testing::_; -using testing::AnyNumber; -using testing::Return; -using testing::SetArgumentPointee; - -#define arraysize(f) (sizeof(f) / sizeof(*f)) - -// Addresses and sizes of a couple dummy modules. -uint64_t kModule1Base = 0x40000000; -uint64_t kModule1Size = 0x10000; -uint64_t kModule2Base = 0x50000000; -uint64_t kModule2Size = 0x10000; - -// A handful of addresses that lie within the modules above. -const uint64_t kDummyFrames[] = { - 0x50003000, 0x50002000, 0x50001000, 0x40002000, 0x40001000 }; - -class StackwalkerAddressListTest : public testing::Test { - public: - StackwalkerAddressListTest() - : // Give the two modules reasonable standard locations and names - // for tests to play with. - module1(kModule1Base, kModule1Size, "module1", "version1"), - module2(kModule2Base, kModule2Size, "module2", "version2") { - // Create some modules with some stock debugging information. - modules.Add(&module1); - modules.Add(&module2); - - // By default, none of the modules have symbol info; call - // SetModuleSymbols to override this. - EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _)) - .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); - - // Avoid GMOCK WARNING "Uninteresting mock function call - returning - // directly" for FreeSymbolData(). - EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); - } - - // Set the Breakpad symbol information that supplier should return for - // MODULE to INFO. - void SetModuleSymbols(MockCodeModule *module, const string &info) { - size_t buffer_size; - char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size); - EXPECT_CALL(supplier, GetCStringSymbolData(module, NULL, _, _, _)) - .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), - SetArgumentPointee<4>(buffer_size), - Return(MockSymbolSupplier::FOUND))); - } - - void CheckCallStack(const CallStack& call_stack) { - const std::vector<StackFrame*>* frames = call_stack.frames(); - ASSERT_EQ(arraysize(kDummyFrames), frames->size()); - for (size_t i = 0; i < arraysize(kDummyFrames); ++i) { - ASSERT_EQ(kDummyFrames[i], frames->at(i)->instruction); - ASSERT_EQ(StackFrame::FRAME_TRUST_PREWALKED, frames->at(i)->trust); - } - ASSERT_EQ(static_cast<const CodeModule*>(&module2), frames->at(0)->module); - ASSERT_EQ(static_cast<const CodeModule*>(&module2), frames->at(1)->module); - ASSERT_EQ(static_cast<const CodeModule*>(&module2), frames->at(2)->module); - ASSERT_EQ(static_cast<const CodeModule*>(&module1), frames->at(3)->module); - ASSERT_EQ(static_cast<const CodeModule*>(&module1), frames->at(4)->module); - } - - MockCodeModule module1; - MockCodeModule module2; - MockCodeModules modules; - MockSymbolSupplier supplier; - BasicSourceLineResolver resolver; -}; - -TEST_F(StackwalkerAddressListTest, ScanWithoutSymbols) { - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAddressList walker(kDummyFrames, arraysize(kDummyFrames), - &modules, &frame_symbolizer); - - CallStack call_stack; - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - - // The stack starts in module2, so we expect that to be the first module - // found without symbols. - ASSERT_EQ(2U, modules_without_symbols.size()); - ASSERT_EQ("module2", modules_without_symbols[0]->debug_file()); - ASSERT_EQ("module1", modules_without_symbols[1]->debug_file()); - ASSERT_EQ(0u, modules_with_corrupt_symbols.size()); - - ASSERT_NO_FATAL_FAILURE(CheckCallStack(call_stack)); -} - -TEST_F(StackwalkerAddressListTest, ScanWithSymbols) { - // File : FILE number(dex) name - // Function: FUNC address(hex) size(hex) parameter_size(hex) name - // Line : address(hex) size(hex) line(dec) filenum(dec) - SetModuleSymbols(&module2, - "FILE 1 module2.cc\n" - "FUNC 3000 100 10 mod2func3\n" - "3000 10 1 1\n" - "FUNC 2000 200 10 mod2func2\n" - "FUNC 1000 300 10 mod2func1\n"); - SetModuleSymbols(&module1, - "FUNC 2000 200 10 mod1func2\n" - "FUNC 1000 300 10 mod1func1\n"); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAddressList walker(kDummyFrames, arraysize(kDummyFrames), - &modules, &frame_symbolizer); - - CallStack call_stack; - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - - ASSERT_EQ(0u, modules_without_symbols.size()); - ASSERT_EQ(0u, modules_with_corrupt_symbols.size()); - - ASSERT_NO_FATAL_FAILURE(CheckCallStack(call_stack)); - - const std::vector<StackFrame*>* frames = call_stack.frames(); - - // We have full file/line information for the first function call. - ASSERT_EQ("mod2func3", frames->at(0)->function_name); - ASSERT_EQ(0x50003000u, frames->at(0)->function_base); - ASSERT_EQ("module2.cc", frames->at(0)->source_file_name); - ASSERT_EQ(1, frames->at(0)->source_line); - ASSERT_EQ(0x50003000u, frames->at(0)->source_line_base); - - ASSERT_EQ("mod2func2", frames->at(1)->function_name); - ASSERT_EQ(0x50002000u, frames->at(1)->function_base); - - ASSERT_EQ("mod2func1", frames->at(2)->function_name); - ASSERT_EQ(0x50001000u, frames->at(2)->function_base); - - ASSERT_EQ("mod1func2", frames->at(3)->function_name); - ASSERT_EQ(0x40002000u, frames->at(3)->function_base); - - ASSERT_EQ("mod1func1", frames->at(4)->function_name); - ASSERT_EQ(0x40001000u, frames->at(4)->function_base); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.cc deleted file mode 100644 index 440724a1e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.cc +++ /dev/null @@ -1,340 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_amd64.cc: amd64-specific stackwalker. -// -// See stackwalker_amd64.h for documentation. -// -// Author: Mark Mentovai, Ted Mielczarek - -#include <assert.h> - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "google_breakpad/processor/system_info.h" -#include "processor/cfi_frame_info.h" -#include "processor/logging.h" -#include "processor/stackwalker_amd64.h" - -namespace google_breakpad { - - -const StackwalkerAMD64::CFIWalker::RegisterSet -StackwalkerAMD64::cfi_register_map_[] = { - // It may seem like $rip and $rsp are callee-saves, because the callee is - // responsible for having them restored upon return. But the callee_saves - // flags here really means that the walker should assume they're - // unchanged if the CFI doesn't mention them --- clearly wrong for $rip - // and $rsp. - { "$rax", NULL, false, - StackFrameAMD64::CONTEXT_VALID_RAX, &MDRawContextAMD64::rax }, - { "$rdx", NULL, false, - StackFrameAMD64::CONTEXT_VALID_RDX, &MDRawContextAMD64::rdx }, - { "$rcx", NULL, false, - StackFrameAMD64::CONTEXT_VALID_RCX, &MDRawContextAMD64::rcx }, - { "$rbx", NULL, true, - StackFrameAMD64::CONTEXT_VALID_RBX, &MDRawContextAMD64::rbx }, - { "$rsi", NULL, false, - StackFrameAMD64::CONTEXT_VALID_RSI, &MDRawContextAMD64::rsi }, - { "$rdi", NULL, false, - StackFrameAMD64::CONTEXT_VALID_RDI, &MDRawContextAMD64::rdi }, - { "$rbp", NULL, true, - StackFrameAMD64::CONTEXT_VALID_RBP, &MDRawContextAMD64::rbp }, - { "$rsp", ".cfa", false, - StackFrameAMD64::CONTEXT_VALID_RSP, &MDRawContextAMD64::rsp }, - { "$r8", NULL, false, - StackFrameAMD64::CONTEXT_VALID_R8, &MDRawContextAMD64::r8 }, - { "$r9", NULL, false, - StackFrameAMD64::CONTEXT_VALID_R9, &MDRawContextAMD64::r9 }, - { "$r10", NULL, false, - StackFrameAMD64::CONTEXT_VALID_R10, &MDRawContextAMD64::r10 }, - { "$r11", NULL, false, - StackFrameAMD64::CONTEXT_VALID_R11, &MDRawContextAMD64::r11 }, - { "$r12", NULL, true, - StackFrameAMD64::CONTEXT_VALID_R12, &MDRawContextAMD64::r12 }, - { "$r13", NULL, true, - StackFrameAMD64::CONTEXT_VALID_R13, &MDRawContextAMD64::r13 }, - { "$r14", NULL, true, - StackFrameAMD64::CONTEXT_VALID_R14, &MDRawContextAMD64::r14 }, - { "$r15", NULL, true, - StackFrameAMD64::CONTEXT_VALID_R15, &MDRawContextAMD64::r15 }, - { "$rip", ".ra", false, - StackFrameAMD64::CONTEXT_VALID_RIP, &MDRawContextAMD64::rip }, -}; - -StackwalkerAMD64::StackwalkerAMD64(const SystemInfo* system_info, - const MDRawContextAMD64* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* resolver_helper) - : Stackwalker(system_info, memory, modules, resolver_helper), - context_(context), - cfi_walker_(cfi_register_map_, - (sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) { -} - -uint64_t StackFrameAMD64::ReturnAddress() const { - assert(context_validity & StackFrameAMD64::CONTEXT_VALID_RIP); - return context.rip; -} - -StackFrame* StackwalkerAMD64::GetContextFrame() { - if (!context_) { - BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; - } - - StackFrameAMD64* frame = new StackFrameAMD64(); - - // The instruction pointer is stored directly in a register, so pull it - // straight out of the CPU context structure. - frame->context = *context_; - frame->context_validity = StackFrameAMD64::CONTEXT_VALID_ALL; - frame->trust = StackFrame::FRAME_TRUST_CONTEXT; - frame->instruction = frame->context.rip; - - return frame; -} - -StackFrameAMD64* StackwalkerAMD64::GetCallerByCFIFrameInfo( - const vector<StackFrame*> &frames, - CFIFrameInfo* cfi_frame_info) { - StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back()); - - scoped_ptr<StackFrameAMD64> frame(new StackFrameAMD64()); - if (!cfi_walker_ - .FindCallerRegisters(*memory_, *cfi_frame_info, - last_frame->context, last_frame->context_validity, - &frame->context, &frame->context_validity)) - return NULL; - - // Make sure we recovered all the essentials. - static const int essentials = (StackFrameAMD64::CONTEXT_VALID_RIP - | StackFrameAMD64::CONTEXT_VALID_RSP); - if ((frame->context_validity & essentials) != essentials) - return NULL; - - frame->trust = StackFrame::FRAME_TRUST_CFI; - return frame.release(); -} - -bool StackwalkerAMD64::IsEndOfStack(uint64_t caller_rip, uint64_t caller_rsp, - uint64_t callee_rsp) { - // Treat an instruction address of 0 as end-of-stack. - if (caller_rip == 0) { - return true; - } - - // If the new stack pointer is at a lower address than the old, then - // that's clearly incorrect. Treat this as end-of-stack to enforce - // progress and avoid infinite loops. - if (caller_rsp < callee_rsp) { - return true; - } - - return false; -} - -// Returns true if `ptr` is not in x86-64 canonical form. -// https://en.wikipedia.org/wiki/X86-64#Virtual_address_space_details -static bool is_non_canonical(uint64_t ptr) { - return ptr > 0x7FFFFFFFFFFF && ptr < 0xFFFF800000000000; -} - -StackFrameAMD64* StackwalkerAMD64::GetCallerByFramePointerRecovery( - const vector<StackFrame*>& frames) { - StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back()); - uint64_t last_rsp = last_frame->context.rsp; - uint64_t last_rbp = last_frame->context.rbp; - - // Assume the presence of a frame pointer. This is not mandated by the - // AMD64 ABI, c.f. section 3.2.2 footnote 7, though it is typical for - // compilers to still preserve the frame pointer and not treat %rbp as a - // general purpose register. - // - // With this assumption, the CALL instruction pushes the return address - // onto the stack and sets %rip to the procedure to enter. The procedure - // then establishes the stack frame with a prologue that PUSHes the current - // %rbp onto the stack, MOVes the current %rsp to %rbp, and then allocates - // space for any local variables. Using this procedure linking information, - // it is possible to locate frame information for the callee: - // - // %caller_rsp = *(%callee_rbp + 16) - // %caller_rip = *(%callee_rbp + 8) - // %caller_rbp = *(%callee_rbp) - - // If rbp is not 8-byte aligned it can't be a frame pointer. - if (last_rbp % 8 != 0) { - return NULL; - } - - uint64_t caller_rip, caller_rbp; - if (memory_->GetMemoryAtAddress(last_rbp + 8, &caller_rip) && - memory_->GetMemoryAtAddress(last_rbp, &caller_rbp)) { - uint64_t caller_rsp = last_rbp + 16; - - // If the recovered rip is not a canonical address it can't be - // the return address, so rbp must not have been a frame pointer. - if (is_non_canonical(caller_rip)) { - return NULL; - } - - // Simple sanity check that the stack is growing downwards as expected. - if (IsEndOfStack(caller_rip, caller_rsp, last_rsp) || - caller_rbp < last_rbp) { - // Reached end-of-stack or stack is not growing downwards. - return NULL; - } - - StackFrameAMD64* frame = new StackFrameAMD64(); - frame->trust = StackFrame::FRAME_TRUST_FP; - frame->context = last_frame->context; - frame->context.rip = caller_rip; - frame->context.rsp = caller_rsp; - frame->context.rbp = caller_rbp; - frame->context_validity = StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP | - StackFrameAMD64::CONTEXT_VALID_RBP; - return frame; - } - - return NULL; -} - -StackFrameAMD64* StackwalkerAMD64::GetCallerByStackScan( - const vector<StackFrame*> &frames) { - StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back()); - uint64_t last_rsp = last_frame->context.rsp; - uint64_t caller_rip_address, caller_rip; - - if (!ScanForReturnAddress(last_rsp, &caller_rip_address, &caller_rip, - frames.size() == 1 /* is_context_frame */)) { - // No plausible return address was found. - return NULL; - } - - // Create a new stack frame (ownership will be transferred to the caller) - // and fill it in. - StackFrameAMD64* frame = new StackFrameAMD64(); - - frame->trust = StackFrame::FRAME_TRUST_SCAN; - frame->context = last_frame->context; - frame->context.rip = caller_rip; - // The caller's %rsp is directly underneath the return address pushed by - // the call. - frame->context.rsp = caller_rip_address + 8; - frame->context_validity = StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP; - - // Other unwinders give up if they don't have an %rbp value, so see if we - // can pass some plausible value on. - if (last_frame->context_validity & StackFrameAMD64::CONTEXT_VALID_RBP) { - // Functions typically push their caller's %rbp immediately upon entry, - // and then set %rbp to point to that. So if the callee's %rbp is - // pointing to the first word below the alleged return address, presume - // that the caller's %rbp is saved there. - if (caller_rip_address - 8 == last_frame->context.rbp) { - uint64_t caller_rbp = 0; - if (memory_->GetMemoryAtAddress(last_frame->context.rbp, &caller_rbp) && - caller_rbp > caller_rip_address) { - frame->context.rbp = caller_rbp; - frame->context_validity |= StackFrameAMD64::CONTEXT_VALID_RBP; - } - } else if (last_frame->context.rbp >= caller_rip_address + 8) { - // If the callee's %rbp is plausible as a value for the caller's - // %rbp, presume that the callee left it unchanged. - frame->context.rbp = last_frame->context.rbp; - frame->context_validity |= StackFrameAMD64::CONTEXT_VALID_RBP; - } - } - - return frame; -} - -StackFrame* StackwalkerAMD64::GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed) { - if (!memory_ || !stack) { - BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; - } - - const vector<StackFrame*> &frames = *stack->frames(); - StackFrameAMD64* last_frame = static_cast<StackFrameAMD64*>(frames.back()); - scoped_ptr<StackFrameAMD64> new_frame; - - // If we have DWARF CFI information, use it. - scoped_ptr<CFIFrameInfo> cfi_frame_info( - frame_symbolizer_->FindCFIFrameInfo(last_frame)); - if (cfi_frame_info.get()) - new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); - - // If CFI was not available or failed, try using frame pointer recovery. - if (!new_frame.get()) { - new_frame.reset(GetCallerByFramePointerRecovery(frames)); - } - - // If all else fails, fall back to stack scanning. - if (stack_scan_allowed && !new_frame.get()) { - new_frame.reset(GetCallerByStackScan(frames)); - } - - // If nothing worked, tell the caller. - if (!new_frame.get()) - return NULL; - - if (system_info_->os_short == "nacl") { - // Apply constraints from Native Client's x86-64 sandbox. These - // registers have the 4GB-aligned sandbox base address (from r15) - // added to them, and only the bottom 32 bits are relevant for - // stack walking. - new_frame->context.rip = static_cast<uint32_t>(new_frame->context.rip); - new_frame->context.rsp = static_cast<uint32_t>(new_frame->context.rsp); - new_frame->context.rbp = static_cast<uint32_t>(new_frame->context.rbp); - } - - if (IsEndOfStack(new_frame->context.rip, new_frame->context.rsp, - last_frame->context.rsp)) { - // Reached end-of-stack. - return NULL; - } - - // new_frame->context.rip is the return address, which is the instruction - // after the CALL that caused us to arrive at the callee. Set - // new_frame->instruction to one less than that, so it points within the - // CALL instruction. See StackFrame::instruction for details, and - // StackFrameAMD64::ReturnAddress. - new_frame->instruction = new_frame->context.rip - 1; - - return new_frame.release(); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.h deleted file mode 100644 index 67c455104..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64.h +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_amd64.h: amd64-specific stackwalker. -// -// Provides stack frames given amd64 register context and a memory region -// corresponding to a amd64 stack. -// -// Author: Mark Mentovai, Ted Mielczarek - - -#ifndef PROCESSOR_STACKWALKER_AMD64_H__ -#define PROCESSOR_STACKWALKER_AMD64_H__ - -#include <vector> - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/stackwalker.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/cfi_frame_info.h" - -namespace google_breakpad { - -class CodeModules; - -class StackwalkerAMD64 : public Stackwalker { - public: - // context is a amd64 context object that gives access to amd64-specific - // register state corresponding to the innermost called frame to be - // included in the stack. The other arguments are passed directly through - // to the base Stackwalker constructor. - StackwalkerAMD64(const SystemInfo* system_info, - const MDRawContextAMD64* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer); - - private: - // A STACK CFI-driven frame walker for the AMD64 - typedef SimpleCFIWalker<uint64_t, MDRawContextAMD64> CFIWalker; - - // Implementation of Stackwalker, using amd64 context (stack pointer in %rsp, - // stack base in %rbp) and stack conventions (saved stack pointer at 0(%rbp)) - virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed); - - // Use cfi_frame_info (derived from STACK CFI records) to construct - // the frame that called frames.back(). The caller takes ownership - // of the returned frame. Return NULL on failure. - StackFrameAMD64* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames, - CFIFrameInfo* cfi_frame_info); - - // Checks whether end-of-stack is reached. An instruction address of 0 is an - // end-of-stack marker. If the stack pointer of the caller is at a lower - // address than the stack pointer of the callee, then that's clearly incorrect - // and it is treated as end-of-stack to enforce progress and avoid infinite - // loops. - bool IsEndOfStack(uint64_t caller_rip, uint64_t caller_rsp, - uint64_t callee_rsp); - - // Assumes a traditional frame layout where the frame pointer has not been - // omitted. The expectation is that caller's %rbp is pushed to the stack - // after the return address of the callee, and that the callee's %rsp can - // be used to find the pushed %rbp. - // Caller owns the returned frame object. Returns NULL on failure. - StackFrameAMD64* GetCallerByFramePointerRecovery( - const vector<StackFrame*>& frames); - - // Scan the stack for plausible return addresses. The caller takes ownership - // of the returned frame. Return NULL on failure. - StackFrameAMD64* GetCallerByStackScan(const vector<StackFrame*> &frames); - - // Stores the CPU context corresponding to the innermost stack frame to - // be returned by GetContextFrame. - const MDRawContextAMD64* context_; - - // Our register map, for cfi_walker_. - static const CFIWalker::RegisterSet cfi_register_map_[]; - - // Our CFI frame walker. - const CFIWalker cfi_walker_; -}; - - -} // namespace google_breakpad - - -#endif // PROCESSOR_STACKWALKER_AMD64_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64_unittest.cc deleted file mode 100644 index 935bef866..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_amd64_unittest.cc +++ /dev/null @@ -1,932 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// stackwalker_amd64_unittest.cc: Unit tests for StackwalkerAMD64 class. - -#include <string.h> -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/test_assembler.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/stackwalker_unittest_utils.h" -#include "processor/stackwalker_amd64.h" - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::CallStack; -using google_breakpad::CodeModule; -using google_breakpad::StackFrameSymbolizer; -using google_breakpad::StackFrame; -using google_breakpad::StackFrameAMD64; -using google_breakpad::Stackwalker; -using google_breakpad::StackwalkerAMD64; -using google_breakpad::SystemInfo; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Label; -using google_breakpad::test_assembler::Section; -using std::vector; -using testing::_; -using testing::AnyNumber; -using testing::Return; -using testing::SetArgumentPointee; -using testing::Test; - -class StackwalkerAMD64Fixture { - public: - StackwalkerAMD64Fixture() - : stack_section(kLittleEndian), - // Give the two modules reasonable standard locations and names - // for tests to play with. - module1(0x00007400c0000000ULL, 0x10000, "module1", "version1"), - module2(0x00007500b0000000ULL, 0x10000, "module2", "version2") { - // Identify the system as a Linux system. - system_info.os = "Linux"; - system_info.os_short = "linux"; - system_info.os_version = "Horrendous Hippo"; - system_info.cpu = "x86"; - system_info.cpu_info = ""; - - // Put distinctive values in the raw CPU context. - BrandContext(&raw_context); - - // Create some modules with some stock debugging information. - modules.Add(&module1); - modules.Add(&module2); - - // By default, none of the modules have symbol info; call - // SetModuleSymbols to override this. - EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _)) - .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); - - // Avoid GMOCK WARNING "Uninteresting mock function call - returning - // directly" for FreeSymbolData(). - EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); - - // Reset max_frames_scanned since it's static. - Stackwalker::set_max_frames_scanned(1024); - } - - // Set the Breakpad symbol information that supplier should return for - // MODULE to INFO. - void SetModuleSymbols(MockCodeModule *module, const string &info) { - size_t buffer_size; - char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size); - EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _)) - .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), - SetArgumentPointee<4>(buffer_size), - Return(MockSymbolSupplier::FOUND))); - } - - // Populate stack_region with the contents of stack_section. Use - // stack_section.start() as the region's starting address. - void RegionFromSection() { - string contents; - ASSERT_TRUE(stack_section.GetContents(&contents)); - stack_region.Init(stack_section.start().Value(), contents); - } - - // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking. - void BrandContext(MDRawContextAMD64 *raw_context) { - uint8_t x = 173; - for (size_t i = 0; i < sizeof(*raw_context); i++) - reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17); - } - - SystemInfo system_info; - MDRawContextAMD64 raw_context; - Section stack_section; - MockMemoryRegion stack_region; - MockCodeModule module1; - MockCodeModule module2; - MockCodeModules modules; - MockSymbolSupplier supplier; - BasicSourceLineResolver resolver; - CallStack call_stack; - const vector<StackFrame *> *frames; -}; - -class GetContextFrame: public StackwalkerAMD64Fixture, public Test { }; - -class SanityCheck: public StackwalkerAMD64Fixture, public Test { }; - -TEST_F(SanityCheck, NoResolver) { - // There should be no references to the stack in this walk: we don't - // provide any call frame information, so trying to reconstruct the - // context frame's caller should fail. So there's no need for us to - // provide stack contents. - raw_context.rip = 0x00007400c0000200ULL; - raw_context.rbp = 0x8000000080000000ULL; - - StackFrameSymbolizer frame_symbolizer(NULL, NULL); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - // This should succeed even without a resolver or supplier. - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_GE(1U, frames->size()); - StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -TEST_F(GetContextFrame, Simple) { - // There should be no references to the stack in this walk: we don't - // provide any call frame information, so trying to reconstruct the - // context frame's caller should fail. So there's no need for us to - // provide stack contents. - raw_context.rip = 0x00007400c0000200ULL; - raw_context.rbp = 0x8000000080000000ULL; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_GE(1U, frames->size()); - StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -// The stackwalker should be able to produce the context frame even -// without stack memory present. -TEST_F(GetContextFrame, NoStackMemory) { - raw_context.rip = 0x00007400c0000200ULL; - raw_context.rbp = 0x8000000080000000ULL; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, NULL, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_GE(1U, frames->size()); - StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -class GetCallerFrame: public StackwalkerAMD64Fixture, public Test { }; - -TEST_F(GetCallerFrame, ScanWithoutSymbols) { - // When the stack walker resorts to scanning the stack, - // only addresses located within loaded modules are - // considered valid return addresses. - // Force scanning through three frames to ensure that the - // stack pointer is set properly in scan-recovered frames. - stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address1 = 0x00007500b0000100ULL; - uint64_t return_address2 = 0x00007500b0000900ULL; - Label frame1_sp, frame2_sp, frame1_rbp; - stack_section - // frame 0 - .Append(16, 0) // space - - .D64(0x00007400b0000000ULL) // junk that's not - .D64(0x00007500d0000000ULL) // a return address - - .D64(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(16, 0) // space - - .D64(0x00007400b0000000ULL) // more junk - .D64(0x00007500d0000000ULL) - - .Mark(&frame1_rbp) - .D64(stack_section.start()) // This is in the right place to be - // a saved rbp, but it's bogus, so - // we shouldn't report it. - - .D64(return_address2) // actual return address - // frame 2 - .Mark(&frame2_sp) - .Append(32, 0); // end of stack - - RegionFromSection(); - - raw_context.rip = 0x00007400c0000200ULL; - raw_context.rbp = frame1_rbp.Value(); - raw_context.rsp = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(2U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(3U, frames->size()); - - StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP | - StackFrameAMD64::CONTEXT_VALID_RBP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.rip); - EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); - EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); - - StackFrameAMD64 *frame2 = static_cast<StackFrameAMD64 *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust); - ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP), - frame2->context_validity); - EXPECT_EQ(return_address2, frame2->context.rip); - EXPECT_EQ(frame2_sp.Value(), frame2->context.rsp); -} - -TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { - // During stack scanning, if a potential return address - // is located within a loaded module that has symbols, - // it is only considered a valid return address if it - // lies within a function's bounds. - stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address = 0x00007500b0000110ULL; - Label frame1_sp, frame1_rbp; - - stack_section - // frame 0 - .Append(16, 0) // space - - .D64(0x00007400b0000000ULL) // junk that's not - .D64(0x00007500b0000000ULL) // a return address - - .D64(0x00007400c0001000ULL) // a couple of plausible addresses - .D64(0x00007500b000aaaaULL) // that are not within functions - - .D64(return_address) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(32, 0) // end of stack - .Mark(&frame1_rbp); - RegionFromSection(); - - raw_context.rip = 0x00007400c0000200ULL; - raw_context.rbp = frame1_rbp.Value(); - raw_context.rsp = stack_section.start().Value(); - - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 100 400 10 platypus\n"); - SetModuleSymbols(&module2, - // The calling frame's function. - "FUNC 100 400 10 echidna\n"); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ("platypus", frame0->function_name); - EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base); - - StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP | - StackFrameAMD64::CONTEXT_VALID_RBP), - frame1->context_validity); - EXPECT_EQ(return_address, frame1->context.rip); - EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); - EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); - EXPECT_EQ("echidna", frame1->function_name); - EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base); -} - -// StackwalkerAMD64::GetCallerByFramePointerRecovery should never return an -// instruction pointer of 0 because IP of 0 is an end of stack marker and the -// stack walk may be terminated prematurely. Instead it should return NULL -// so that the stack walking code can proceed to stack scanning. -TEST_F(GetCallerFrame, GetCallerByFramePointerRecovery) { - MockCodeModule user32_dll(0x00007ff9cb8a0000ULL, 0x14E000, "user32.dll", - "version1"); - SetModuleSymbols(&user32_dll, // user32.dll - "PUBLIC fa60 0 DispatchMessageWorker\n" - "PUBLIC fee0 0 UserCallWinProcCheckWow\n" - "PUBLIC 1cdb0 0 _fnHkINLPMSG\n" - "STACK CFI INIT fa60 340 .cfa: $rsp .ra: .cfa 8 - ^\n" - "STACK CFI fa60 .cfa: $rsp 128 +\n" - "STACK CFI INIT fee0 49f .cfa: $rsp .ra: .cfa 8 - ^\n" - "STACK CFI fee0 .cfa: $rsp 240 +\n" - "STACK CFI INIT 1cdb0 9f .cfa: $rsp .ra: .cfa 8 - ^\n" - "STACK CFI 1cdb0 .cfa: $rsp 80 +\n"); - - // Create some modules with some stock debugging information. - MockCodeModules local_modules; - local_modules.Add(&user32_dll); - - Label frame0_rsp; - Label frame0_rbp; - Label frame1_rsp; - Label frame2_rsp; - - stack_section.start() = 0x00000099abf0f238ULL; - stack_section - .Mark(&frame0_rsp) - .D64(0x00007ff9cb8b00dcULL) - .Mark(&frame1_rsp) - .D64(0x0000000000000000ULL) - .D64(0x0000000000000001ULL) - .D64(0x00000099abf0f308ULL) - .D64(0x00007ff9cb8bce3aULL) // Stack residue from execution of - // user32!_fnHkINLPMSG+0x8a - .D64(0x000000000000c2e0ULL) - .D64(0x00000099abf0f328ULL) - .D64(0x0000000100000001ULL) - .D64(0x0000000000000000ULL) - .D64(0x0000000000000000ULL) - .D64(0x0000000000000000ULL) - .D64(0x0000000000000000ULL) - .D64(0x0000000000000000ULL) - .D64(0x0000000000000000ULL) - .D64(0x00007ff9ccad53e4ULL) - .D64(0x0000000000000048ULL) - .D64(0x0000000000000001ULL) - .D64(0x00000099abf0f5e0ULL) - .D64(0x00000099b61f7388ULL) - .D64(0x0000000000000030ULL) - .D64(0xffffff66540f0a1fULL) - .D64(0xffffff6649e08c77ULL) - .D64(0x00007ff9cb8affb4ULL) // Return address in - // user32!UserCallWinProcCheckWow+0xd4 - .D64(0x0000000000000000ULL) - .D64(0x00000099abf0f368ULL) - .D64(0x0000000000000000ULL) - .D64(0x0000000000000000ULL) - .D64(0x0000000000000000ULL) - .D64(0x00000099a8150fd8ULL) - .D64(0x00000099abf0f3e8ULL) - .D64(0x00007ff9cb8afc07ULL) // Return address in - // user32!DispatchMessageWorker+0x1a7 - .Mark(&frame2_rsp) - .Append(256, 0) - .Mark(&frame0_rbp) // The following are expected by - // GetCallerByFramePointerRecovery. - .D64(0xfffffffffffffffeULL) // %caller_rbp = *(%callee_rbp) - .D64(0x0000000000000000ULL) // %caller_rip = *(%callee_rbp + 8) - .D64(0x00000099a3e31040ULL) // %caller_rsp = *(%callee_rbp + 16) - .Append(256, 0); - - RegionFromSection(); - raw_context.rip = 0x00000099a8150fd8ULL; // IP in context frame is guarbage - raw_context.rsp = frame0_rsp.Value(); - raw_context.rbp = frame0_rbp.Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, - &local_modules, &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - - ASSERT_EQ(3U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame->trust); - ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame->context_validity); - EXPECT_EQ("", frame->function_name); - EXPECT_EQ(0x00000099a8150fd8ULL, frame->instruction); - EXPECT_EQ(0x00000099a8150fd8ULL, frame->context.rip); - EXPECT_EQ(frame0_rsp.Value(), frame->context.rsp); - EXPECT_EQ(frame0_rbp.Value(), frame->context.rbp); - } - - { // To avoid reusing locals by mistake - StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame->trust); - ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP | - StackFrameAMD64::CONTEXT_VALID_RBP), - frame->context_validity); - EXPECT_EQ("UserCallWinProcCheckWow", frame->function_name); - EXPECT_EQ(140710838468828ULL, frame->instruction + 1); - EXPECT_EQ(140710838468828ULL, frame->context.rip); - EXPECT_EQ(frame1_rsp.Value(), frame->context.rsp); - EXPECT_EQ(&user32_dll, frame->module); - } - - { // To avoid reusing locals by mistake - StackFrameAMD64 *frame = static_cast<StackFrameAMD64 *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust); - ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP | - StackFrameAMD64::CONTEXT_VALID_RBP), - frame->context_validity); - EXPECT_EQ("DispatchMessageWorker", frame->function_name); - EXPECT_EQ(140710838467591ULL, frame->instruction + 1); - EXPECT_EQ(140710838467591ULL, frame->context.rip); - EXPECT_EQ(frame2_rsp.Value(), frame->context.rsp); - EXPECT_EQ(&user32_dll, frame->module); - } -} - -// Don't use frame pointer recovery if %rbp is not 8-byte aligned, which -// indicates that it's not being used as a frame pointer. -TEST_F(GetCallerFrame, FramePointerNotAligned) { - stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address1 = 0x00007500b0000100ULL; - Label frame0_rbp, not_frame1_rbp, frame1_sp; - stack_section - // frame 0 - .Align(8, 0) - .Append(2, 0) // mis-align the frame pointer - .Mark(&frame0_rbp) - .D64(not_frame1_rbp) // not the previous frame pointer - .D64(0x00007500b0000a00ULL) // plausible but wrong return address - .Align(8, 0) - .D64(return_address1) // return address - // frame 1 - .Mark(&frame1_sp) - .Mark(¬_frame1_rbp) - .Append(32, 0); // end of stack - - - RegionFromSection(); - - raw_context.rip = 0x00007400c0000200ULL; - raw_context.rbp = frame0_rbp.Value(); - raw_context.rsp = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.rip); - EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); -} - -// Don't use frame pointer recovery if the recovered %rip is not -// a canonical x86-64 address. -TEST_F(GetCallerFrame, NonCanonicalInstructionPointerFromFramePointer) { - stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address1 = 0x00007500b0000100ULL; - Label frame0_rbp, frame1_sp, not_frame1_bp; - stack_section - // frame 0 - .Align(8, 0) - .Mark(&frame0_rbp) - .D64(not_frame1_bp) // some junk on the stack - .D64(0xDADADADADADADADA) // not the return address - .D64(return_address1) // return address - // frame 1 - .Mark(&frame1_sp) - .Append(16, 0) - .Mark(¬_frame1_bp) - .Append(32, 0); // end of stack - - - RegionFromSection(); - - raw_context.rip = 0x00007400c0000200ULL; - raw_context.rbp = frame0_rbp.Value(); - raw_context.rsp = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.rip); - EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); -} - -// Test that set_max_frames_scanned prevents using stack scanning -// to find caller frames. -TEST_F(GetCallerFrame, ScanningNotAllowed) { - // When the stack walker resorts to scanning the stack, - // only addresses located within loaded modules are - // considered valid return addresses. - stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address1 = 0x00007500b0000100ULL; - uint64_t return_address2 = 0x00007500b0000900ULL; - Label frame1_sp, frame2_sp, frame1_rbp; - stack_section - // frame 0 - .Append(16, 0) // space - - .D64(0x00007400b0000000ULL) // junk that's not - .D64(0x00007500d0000000ULL) // a return address - - .D64(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(16, 0) // space - - .D64(0x00007400b0000000ULL) // more junk - .D64(0x00007500d0000000ULL) - - .Mark(&frame1_rbp) - .D64(stack_section.start()) // This is in the right place to be - // a saved rbp, but it's bogus, so - // we shouldn't report it. - - .D64(return_address2) // actual return address - // frame 2 - .Mark(&frame2_sp) - .Append(32, 0); // end of stack - - RegionFromSection(); - - raw_context.rip = 0x00007400c0000200ULL; - raw_context.rbp = frame1_rbp.Value(); - raw_context.rsp = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - Stackwalker::set_max_frames_scanned(0); - - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - - StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); -} - -TEST_F(GetCallerFrame, CallerPushedRBP) { - // Functions typically push their %rbp upon entry and set %rbp pointing - // there. If stackwalking finds a plausible address for the next frame's - // %rbp directly below the return address, assume that it is indeed the - // next frame's %rbp. - stack_section.start() = 0x8000000080000000ULL; - uint64_t return_address = 0x00007500b0000110ULL; - Label frame0_rbp, frame1_sp, frame1_rbp; - - stack_section - // frame 0 - .Append(16, 0) // space - - .D64(0x00007400b0000000ULL) // junk that's not - .D64(0x00007500b0000000ULL) // a return address - - .D64(0x00007400c0001000ULL) // a couple of plausible addresses - .D64(0x00007500b000aaaaULL) // that are not within functions - - .Mark(&frame0_rbp) - .D64(frame1_rbp) // caller-pushed %rbp - .D64(return_address) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(32, 0) // body of frame1 - .Mark(&frame1_rbp); // end of stack - RegionFromSection(); - - raw_context.rip = 0x00007400c0000200ULL; - raw_context.rbp = frame0_rbp.Value(); - raw_context.rsp = stack_section.start().Value(); - - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 100 400 10 sasquatch\n"); - SetModuleSymbols(&module2, - // The calling frame's function. - "FUNC 100 400 10 yeti\n"); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(frame0_rbp.Value(), frame0->context.rbp); - EXPECT_EQ("sasquatch", frame0->function_name); - EXPECT_EQ(0x00007400c0000100ULL, frame0->function_base); - - StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); - ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP | - StackFrameAMD64::CONTEXT_VALID_RBP), - frame1->context_validity); - EXPECT_EQ(return_address, frame1->context.rip); - EXPECT_EQ(frame1_sp.Value(), frame1->context.rsp); - EXPECT_EQ(frame1_rbp.Value(), frame1->context.rbp); - EXPECT_EQ("yeti", frame1->function_name); - EXPECT_EQ(0x00007500b0000100ULL, frame1->function_base); -} - -struct CFIFixture: public StackwalkerAMD64Fixture { - CFIFixture() { - // Provide a bunch of STACK CFI records; we'll walk to the caller - // from every point in this series, expecting to find the same set - // of register values. - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 4000 1000 10 enchiridion\n" - // Initially, just a return address. - "STACK CFI INIT 4000 100 .cfa: $rsp 8 + .ra: .cfa 8 - ^\n" - // Push %rbx. - "STACK CFI 4001 .cfa: $rsp 16 + $rbx: .cfa 16 - ^\n" - // Save %r12 in %rbx. Weird, but permitted. - "STACK CFI 4002 $r12: $rbx\n" - // Allocate frame space, and save %r13. - "STACK CFI 4003 .cfa: $rsp 40 + $r13: .cfa 32 - ^\n" - // Put the return address in %r13. - "STACK CFI 4005 .ra: $r13\n" - // Save %rbp, and use it as a frame pointer. - "STACK CFI 4006 .cfa: $rbp 16 + $rbp: .cfa 24 - ^\n" - - // The calling function. - "FUNC 5000 1000 10 epictetus\n" - // Mark it as end of stack. - "STACK CFI INIT 5000 1000 .cfa: $rsp .ra 0\n"); - - // Provide some distinctive values for the caller's registers. - expected.rsp = 0x8000000080000000ULL; - expected.rip = 0x00007400c0005510ULL; - expected.rbp = 0x68995b1de4700266ULL; - expected.rbx = 0x5a5beeb38de23be8ULL; - expected.r12 = 0xed1b02e8cc0fc79cULL; - expected.r13 = 0x1d20ad8acacbe930ULL; - expected.r14 = 0xe94cffc2f7adaa28ULL; - expected.r15 = 0xb638d17d8da413b5ULL; - - // By default, registers are unchanged. - raw_context = expected; - } - - // Walk the stack, using stack_section as the contents of the stack - // and raw_context as the current register values. (Set - // raw_context.rsp to the stack's starting address.) Expect two - // stack frames; in the older frame, expect the callee-saves - // registers to have values matching those in 'expected'. - void CheckWalk() { - RegionFromSection(); - raw_context.rsp = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerAMD64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameAMD64 *frame0 = static_cast<StackFrameAMD64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameAMD64::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ("enchiridion", frame0->function_name); - EXPECT_EQ(0x00007400c0004000ULL, frame0->function_base); - - StackFrameAMD64 *frame1 = static_cast<StackFrameAMD64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ((StackFrameAMD64::CONTEXT_VALID_RIP | - StackFrameAMD64::CONTEXT_VALID_RSP | - StackFrameAMD64::CONTEXT_VALID_RBP | - StackFrameAMD64::CONTEXT_VALID_RBX | - StackFrameAMD64::CONTEXT_VALID_R12 | - StackFrameAMD64::CONTEXT_VALID_R13 | - StackFrameAMD64::CONTEXT_VALID_R14 | - StackFrameAMD64::CONTEXT_VALID_R15), - frame1->context_validity); - EXPECT_EQ(expected.rip, frame1->context.rip); - EXPECT_EQ(expected.rsp, frame1->context.rsp); - EXPECT_EQ(expected.rbp, frame1->context.rbp); - EXPECT_EQ(expected.rbx, frame1->context.rbx); - EXPECT_EQ(expected.r12, frame1->context.r12); - EXPECT_EQ(expected.r13, frame1->context.r13); - EXPECT_EQ(expected.r14, frame1->context.r14); - EXPECT_EQ(expected.r15, frame1->context.r15); - EXPECT_EQ("epictetus", frame1->function_name); - } - - // The values we expect to find for the caller's registers. - MDRawContextAMD64 expected; -}; - -class CFI: public CFIFixture, public Test { }; - -TEST_F(CFI, At4000) { - Label frame1_rsp = expected.rsp; - stack_section - .D64(0x00007400c0005510ULL) // return address - .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x00007400c0004000ULL; - CheckWalk(); -} - -TEST_F(CFI, At4001) { - Label frame1_rsp = expected.rsp; - stack_section - .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0x00007400c0005510ULL) // return address - .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x00007400c0004001ULL; - raw_context.rbx = 0xbe0487d2f9eafe29ULL; // callee's (distinct) %rbx value - CheckWalk(); -} - -TEST_F(CFI, At4002) { - Label frame1_rsp = expected.rsp; - stack_section - .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0x00007400c0005510ULL) // return address - .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x00007400c0004002ULL; - raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 - raw_context.r12 = 0xb0118de918a4bceaULL; // callee's (distinct) %r12 value - CheckWalk(); -} - -TEST_F(CFI, At4003) { - Label frame1_rsp = expected.rsp; - stack_section - .D64(0x0e023828dffd4d81ULL) // garbage - .D64(0x1d20ad8acacbe930ULL) // saved %r13 - .D64(0x319e68b49e3ace0fULL) // garbage - .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0x00007400c0005510ULL) // return address - .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x00007400c0004003ULL; - raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 - raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12 - raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13 - CheckWalk(); -} - -// The results here should be the same as those at module offset 0x4003. -TEST_F(CFI, At4004) { - Label frame1_rsp = expected.rsp; - stack_section - .D64(0x0e023828dffd4d81ULL) // garbage - .D64(0x1d20ad8acacbe930ULL) // saved %r13 - .D64(0x319e68b49e3ace0fULL) // garbage - .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0x00007400c0005510ULL) // return address - .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x00007400c0004004ULL; - raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 - raw_context.r12 = 0x89d04fa804c87a43ULL; // callee's (distinct) %r12 - raw_context.r13 = 0x5118e02cbdb24b03ULL; // callee's (distinct) %r13 - CheckWalk(); -} - -TEST_F(CFI, At4005) { - Label frame1_rsp = expected.rsp; - stack_section - .D64(0x4b516dd035745953ULL) // garbage - .D64(0x1d20ad8acacbe930ULL) // saved %r13 - .D64(0xa6d445e16ae3d872ULL) // garbage - .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0xaa95fa054aedfbaeULL) // garbage - .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x00007400c0004005ULL; - raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 - raw_context.r12 = 0x46b1b8868891b34aULL; // callee's %r12 - raw_context.r13 = 0x00007400c0005510ULL; // return address - CheckWalk(); -} - -TEST_F(CFI, At4006) { - Label frame0_rbp; - Label frame1_rsp = expected.rsp; - stack_section - .D64(0x043c6dfceb91aa34ULL) // garbage - .D64(0x1d20ad8acacbe930ULL) // saved %r13 - .D64(0x68995b1de4700266ULL) // saved %rbp - .Mark(&frame0_rbp) // frame pointer points here - .D64(0x5a5beeb38de23be8ULL) // saved %rbx - .D64(0xf015ee516ad89eabULL) // garbage - .Mark(&frame1_rsp); // This effectively sets stack_section.start(). - raw_context.rip = 0x00007400c0004006ULL; - raw_context.rbp = frame0_rbp.Value(); - raw_context.rbx = 0xed1b02e8cc0fc79cULL; // saved %r12 - raw_context.r12 = 0x26e007b341acfebdULL; // callee's %r12 - raw_context.r13 = 0x00007400c0005510ULL; // return address - CheckWalk(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc deleted file mode 100644 index e4fc58697..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.cc +++ /dev/null @@ -1,296 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_arm.cc: arm-specific stackwalker. -// -// See stackwalker_arm.h for documentation. -// -// Author: Mark Mentovai, Ted Mielczarek, Jim Blandy - -#include <vector> - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/cfi_frame_info.h" -#include "processor/logging.h" -#include "processor/stackwalker_arm.h" - -namespace google_breakpad { - - -StackwalkerARM::StackwalkerARM(const SystemInfo* system_info, - const MDRawContextARM* context, - int fp_register, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* resolver_helper) - : Stackwalker(system_info, memory, modules, resolver_helper), - context_(context), fp_register_(fp_register), - context_frame_validity_(StackFrameARM::CONTEXT_VALID_ALL) { } - - -StackFrame* StackwalkerARM::GetContextFrame() { - if (!context_) { - BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; - } - - StackFrameARM* frame = new StackFrameARM(); - - // The instruction pointer is stored directly in a register (r15), so pull it - // straight out of the CPU context structure. - frame->context = *context_; - frame->context_validity = context_frame_validity_; - frame->trust = StackFrame::FRAME_TRUST_CONTEXT; - frame->instruction = frame->context.iregs[MD_CONTEXT_ARM_REG_PC]; - - return frame; -} - -StackFrameARM* StackwalkerARM::GetCallerByCFIFrameInfo( - const vector<StackFrame*> &frames, - CFIFrameInfo* cfi_frame_info) { - StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back()); - - static const char* register_names[] = { - "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", - "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc", - "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", - "fps", "cpsr", - NULL - }; - - // Populate a dictionary with the valid register values in last_frame. - CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers; - for (int i = 0; register_names[i]; i++) - if (last_frame->context_validity & StackFrameARM::RegisterValidFlag(i)) - callee_registers[register_names[i]] = last_frame->context.iregs[i]; - - // Use the STACK CFI data to recover the caller's register values. - CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; - if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, - &caller_registers)) - return NULL; - - // Construct a new stack frame given the values the CFI recovered. - scoped_ptr<StackFrameARM> frame(new StackFrameARM()); - for (int i = 0; register_names[i]; i++) { - CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry = - caller_registers.find(register_names[i]); - if (entry != caller_registers.end()) { - // We recovered the value of this register; fill the context with the - // value from caller_registers. - frame->context_validity |= StackFrameARM::RegisterValidFlag(i); - frame->context.iregs[i] = entry->second; - } else if (4 <= i && i <= 11 && (last_frame->context_validity & - StackFrameARM::RegisterValidFlag(i))) { - // If the STACK CFI data doesn't mention some callee-saves register, and - // it is valid in the callee, assume the callee has not yet changed it. - // Registers r4 through r11 are callee-saves, according to the Procedure - // Call Standard for the ARM Architecture, which the Linux ABI follows. - frame->context_validity |= StackFrameARM::RegisterValidFlag(i); - frame->context.iregs[i] = last_frame->context.iregs[i]; - } - } - // If the CFI doesn't recover the PC explicitly, then use .ra. - if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_PC)) { - CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry = - caller_registers.find(".ra"); - if (entry != caller_registers.end()) { - if (fp_register_ == -1) { - frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC; - frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = entry->second; - } else { - // The CFI updated the link register and not the program counter. - // Handle getting the program counter from the link register. - frame->context_validity |= StackFrameARM::CONTEXT_VALID_PC; - frame->context_validity |= StackFrameARM::CONTEXT_VALID_LR; - frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = entry->second; - frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = - last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR]; - } - } - } - // If the CFI doesn't recover the SP explicitly, then use .cfa. - if (!(frame->context_validity & StackFrameARM::CONTEXT_VALID_SP)) { - CFIFrameInfo::RegisterValueMap<uint32_t>::iterator entry = - caller_registers.find(".cfa"); - if (entry != caller_registers.end()) { - frame->context_validity |= StackFrameARM::CONTEXT_VALID_SP; - frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = entry->second; - } - } - - // If we didn't recover the PC and the SP, then the frame isn't very useful. - static const int essentials = (StackFrameARM::CONTEXT_VALID_SP - | StackFrameARM::CONTEXT_VALID_PC); - if ((frame->context_validity & essentials) != essentials) - return NULL; - - frame->trust = StackFrame::FRAME_TRUST_CFI; - return frame.release(); -} - -StackFrameARM* StackwalkerARM::GetCallerByStackScan( - const vector<StackFrame*> &frames) { - StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back()); - uint32_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP]; - uint32_t caller_sp, caller_pc; - - if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, - frames.size() == 1 /* is_context_frame */)) { - // No plausible return address was found. - return NULL; - } - - // ScanForReturnAddress found a reasonable return address. Advance - // %sp to the location above the one where the return address was - // found. - caller_sp += 4; - - // Create a new stack frame (ownership will be transferred to the caller) - // and fill it in. - StackFrameARM* frame = new StackFrameARM(); - - frame->trust = StackFrame::FRAME_TRUST_SCAN; - frame->context = last_frame->context; - frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = caller_pc; - frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = caller_sp; - frame->context_validity = StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_SP; - - return frame; -} - -StackFrameARM* StackwalkerARM::GetCallerByFramePointer( - const vector<StackFrame*> &frames) { - StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back()); - - if (!(last_frame->context_validity & - StackFrameARM::RegisterValidFlag(fp_register_))) { - return NULL; - } - - uint32_t last_fp = last_frame->context.iregs[fp_register_]; - - uint32_t caller_fp = 0; - if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) { - BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x" - << std::hex << last_fp; - return NULL; - } - - uint32_t caller_lr = 0; - if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 4, &caller_lr)) { - BPLOG(ERROR) << "Unable to read caller_lr from last_fp + 4: 0x" - << std::hex << (last_fp + 4); - return NULL; - } - - uint32_t caller_sp = last_fp ? last_fp + 8 : - last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP]; - - // Create a new stack frame (ownership will be transferred to the caller) - // and fill it in. - StackFrameARM* frame = new StackFrameARM(); - - frame->trust = StackFrame::FRAME_TRUST_FP; - frame->context = last_frame->context; - frame->context.iregs[fp_register_] = caller_fp; - frame->context.iregs[MD_CONTEXT_ARM_REG_SP] = caller_sp; - frame->context.iregs[MD_CONTEXT_ARM_REG_PC] = - last_frame->context.iregs[MD_CONTEXT_ARM_REG_LR]; - frame->context.iregs[MD_CONTEXT_ARM_REG_LR] = caller_lr; - frame->context_validity = StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_LR | - StackFrameARM::RegisterValidFlag(fp_register_) | - StackFrameARM::CONTEXT_VALID_SP; - return frame; -} - -StackFrame* StackwalkerARM::GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed) { - if (!memory_ || !stack) { - BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; - } - - const vector<StackFrame*> &frames = *stack->frames(); - StackFrameARM* last_frame = static_cast<StackFrameARM*>(frames.back()); - scoped_ptr<StackFrameARM> frame; - - // See if there is DWARF call frame information covering this address. - scoped_ptr<CFIFrameInfo> cfi_frame_info( - frame_symbolizer_->FindCFIFrameInfo(last_frame)); - if (cfi_frame_info.get()) - frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); - - // If CFI failed, or there wasn't CFI available, fall back - // to frame pointer, if this is configured. - if (fp_register_ >= 0 && !frame.get()) - frame.reset(GetCallerByFramePointer(frames)); - - // If everuthing failed, fall back to stack scanning. - if (stack_scan_allowed && !frame.get()) - frame.reset(GetCallerByStackScan(frames)); - - // If nothing worked, tell the caller. - if (!frame.get()) - return NULL; - - - // An instruction address of zero marks the end of the stack. - if (frame->context.iregs[MD_CONTEXT_ARM_REG_PC] == 0) - return NULL; - - // If the new stack pointer is at a lower address than the old, then - // that's clearly incorrect. Treat this as end-of-stack to enforce - // progress and avoid infinite loops. - if (frame->context.iregs[MD_CONTEXT_ARM_REG_SP] - < last_frame->context.iregs[MD_CONTEXT_ARM_REG_SP]) - return NULL; - - // The new frame's context's PC is the return address, which is one - // instruction past the instruction that caused us to arrive at the - // callee. Set new_frame->instruction to one less than the PC. This won't - // reference the beginning of the call instruction, but it's at least - // within it, which is sufficient to get the source line information to - // match up with the line that contains the function call. Callers that - // require the exact return address value may access - // frame->context.iregs[MD_CONTEXT_ARM_REG_PC]. - frame->instruction = frame->context.iregs[MD_CONTEXT_ARM_REG_PC] - 2; - - return frame.release(); -} - - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h deleted file mode 100644 index 9081a40cd..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm.h +++ /dev/null @@ -1,107 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_arm.h: arm-specific stackwalker. -// -// Provides stack frames given arm register context and a memory region -// corresponding to an arm stack. -// -// Author: Mark Mentovai, Ted Mielczarek - - -#ifndef PROCESSOR_STACKWALKER_ARM_H__ -#define PROCESSOR_STACKWALKER_ARM_H__ - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/stackwalker.h" - -namespace google_breakpad { - -class CodeModules; - -class StackwalkerARM : public Stackwalker { - public: - // context is an arm context object that gives access to arm-specific - // register state corresponding to the innermost called frame to be - // included in the stack. The other arguments are passed directly through - // to the base Stackwalker constructor. - StackwalkerARM(const SystemInfo* system_info, - const MDRawContextARM* context, - int fp_register, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer); - - // Change the context validity mask of the frame returned by - // GetContextFrame to VALID. This is only for use by unit tests; the - // default behavior is correct for all application code. - void SetContextFrameValidity(int valid) { context_frame_validity_ = valid; } - - private: - // Implementation of Stackwalker, using arm context and stack conventions. - virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed); - - // Use cfi_frame_info (derived from STACK CFI records) to construct - // the frame that called frames.back(). The caller takes ownership - // of the returned frame. Return NULL on failure. - StackFrameARM* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames, - CFIFrameInfo* cfi_frame_info); - - // Use the frame pointer. The caller takes ownership of the returned frame. - // Return NULL on failure. - StackFrameARM* GetCallerByFramePointer(const vector<StackFrame*> &frames); - - // Scan the stack for plausible return addresses. The caller takes ownership - // of the returned frame. Return NULL on failure. - StackFrameARM* GetCallerByStackScan(const vector<StackFrame*> &frames); - - // Stores the CPU context corresponding to the youngest stack frame, to - // be returned by GetContextFrame. - const MDRawContextARM* context_; - - // The register to use a as frame pointer. The value is -1 if frame pointer - // cannot be used. - int fp_register_; - - // Validity mask for youngest stack frame. This is always - // CONTEXT_VALID_ALL in real use; it is only changeable for the sake of - // unit tests. - int context_frame_validity_; -}; - - -} // namespace google_breakpad - - -#endif // PROCESSOR_STACKWALKER_ARM_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.cc deleted file mode 100644 index 31119a97e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.cc +++ /dev/null @@ -1,278 +0,0 @@ -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_arm64.cc: arm64-specific stackwalker. -// -// See stackwalker_arm64.h for documentation. -// -// Author: Mark Mentovai, Ted Mielczarek, Jim Blandy, Colin Blundell - -#include <vector> - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/cfi_frame_info.h" -#include "processor/logging.h" -#include "processor/stackwalker_arm64.h" - -namespace google_breakpad { - - -StackwalkerARM64::StackwalkerARM64(const SystemInfo* system_info, - const MDRawContextARM64* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* resolver_helper) - : Stackwalker(system_info, memory, modules, resolver_helper), - context_(context), - context_frame_validity_(StackFrameARM64::CONTEXT_VALID_ALL) { } - - -StackFrame* StackwalkerARM64::GetContextFrame() { - if (!context_) { - BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; - } - - StackFrameARM64* frame = new StackFrameARM64(); - - // The instruction pointer is stored directly in a register (x32), so pull it - // straight out of the CPU context structure. - frame->context = *context_; - frame->context_validity = context_frame_validity_; - frame->trust = StackFrame::FRAME_TRUST_CONTEXT; - frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC]; - - return frame; -} - -StackFrameARM64* StackwalkerARM64::GetCallerByCFIFrameInfo( - const vector<StackFrame*> &frames, - CFIFrameInfo* cfi_frame_info) { - StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back()); - - static const char* register_names[] = { - "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", - "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", - "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", - "x24", "x25", "x26", "x27", "x28", "x29", "x30", "sp", - "pc", NULL - }; - - // Populate a dictionary with the valid register values in last_frame. - CFIFrameInfo::RegisterValueMap<uint64_t> callee_registers; - for (int i = 0; register_names[i]; i++) { - if (last_frame->context_validity & StackFrameARM64::RegisterValidFlag(i)) - callee_registers[register_names[i]] = last_frame->context.iregs[i]; - } - - // Use the STACK CFI data to recover the caller's register values. - CFIFrameInfo::RegisterValueMap<uint64_t> caller_registers; - if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, - &caller_registers)) { - return NULL; - } - // Construct a new stack frame given the values the CFI recovered. - scoped_ptr<StackFrameARM64> frame(new StackFrameARM64()); - for (int i = 0; register_names[i]; i++) { - CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry = - caller_registers.find(register_names[i]); - if (entry != caller_registers.end()) { - // We recovered the value of this register; fill the context with the - // value from caller_registers. - frame->context_validity |= StackFrameARM64::RegisterValidFlag(i); - frame->context.iregs[i] = entry->second; - } else if (19 <= i && i <= 29 && (last_frame->context_validity & - StackFrameARM64::RegisterValidFlag(i))) { - // If the STACK CFI data doesn't mention some callee-saves register, and - // it is valid in the callee, assume the callee has not yet changed it. - // Registers r19 through r29 are callee-saves, according to the Procedure - // Call Standard for the ARM AARCH64 Architecture, which the Linux ABI - // follows. - frame->context_validity |= StackFrameARM64::RegisterValidFlag(i); - frame->context.iregs[i] = last_frame->context.iregs[i]; - } - } - // If the CFI doesn't recover the PC explicitly, then use .ra. - if (!(frame->context_validity & StackFrameARM64::CONTEXT_VALID_PC)) { - CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry = - caller_registers.find(".ra"); - if (entry != caller_registers.end()) { - frame->context_validity |= StackFrameARM64::CONTEXT_VALID_PC; - frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = entry->second; - } - } - // If the CFI doesn't recover the SP explicitly, then use .cfa. - if (!(frame->context_validity & StackFrameARM64::CONTEXT_VALID_SP)) { - CFIFrameInfo::RegisterValueMap<uint64_t>::iterator entry = - caller_registers.find(".cfa"); - if (entry != caller_registers.end()) { - frame->context_validity |= StackFrameARM64::CONTEXT_VALID_SP; - frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = entry->second; - } - } - - // If we didn't recover the PC and the SP, then the frame isn't very useful. - static const uint64_t essentials = (StackFrameARM64::CONTEXT_VALID_SP - | StackFrameARM64::CONTEXT_VALID_PC); - if ((frame->context_validity & essentials) != essentials) - return NULL; - - frame->trust = StackFrame::FRAME_TRUST_CFI; - return frame.release(); -} - -StackFrameARM64* StackwalkerARM64::GetCallerByStackScan( - const vector<StackFrame*> &frames) { - StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back()); - uint64_t last_sp = last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP]; - uint64_t caller_sp, caller_pc; - - if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, - frames.size() == 1 /* is_context_frame */)) { - // No plausible return address was found. - return NULL; - } - - // ScanForReturnAddress found a reasonable return address. Advance - // %sp to the location above the one where the return address was - // found. - caller_sp += 8; - - // Create a new stack frame (ownership will be transferred to the caller) - // and fill it in. - StackFrameARM64* frame = new StackFrameARM64(); - - frame->trust = StackFrame::FRAME_TRUST_SCAN; - frame->context = last_frame->context; - frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = caller_pc; - frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = caller_sp; - frame->context_validity = StackFrameARM64::CONTEXT_VALID_PC | - StackFrameARM64::CONTEXT_VALID_SP; - - return frame; -} - -StackFrameARM64* StackwalkerARM64::GetCallerByFramePointer( - const vector<StackFrame*> &frames) { - StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back()); - - uint64_t last_fp = last_frame->context.iregs[MD_CONTEXT_ARM64_REG_FP]; - - uint64_t caller_fp = 0; - if (last_fp && !memory_->GetMemoryAtAddress(last_fp, &caller_fp)) { - BPLOG(ERROR) << "Unable to read caller_fp from last_fp: 0x" - << std::hex << last_fp; - return NULL; - } - - uint64_t caller_lr = 0; - if (last_fp && !memory_->GetMemoryAtAddress(last_fp + 8, &caller_lr)) { - BPLOG(ERROR) << "Unable to read caller_lr from last_fp + 8: 0x" - << std::hex << (last_fp + 8); - return NULL; - } - - uint64_t caller_sp = last_fp ? last_fp + 16 : - last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP]; - - // Create a new stack frame (ownership will be transferred to the caller) - // and fill it in. - StackFrameARM64* frame = new StackFrameARM64(); - - frame->trust = StackFrame::FRAME_TRUST_FP; - frame->context = last_frame->context; - frame->context.iregs[MD_CONTEXT_ARM64_REG_FP] = caller_fp; - frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] = caller_sp; - frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] = - last_frame->context.iregs[MD_CONTEXT_ARM64_REG_LR]; - frame->context.iregs[MD_CONTEXT_ARM64_REG_LR] = caller_lr; - frame->context_validity = StackFrameARM64::CONTEXT_VALID_PC | - StackFrameARM64::CONTEXT_VALID_LR | - StackFrameARM64::CONTEXT_VALID_FP | - StackFrameARM64::CONTEXT_VALID_SP; - return frame; -} - -StackFrame* StackwalkerARM64::GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed) { - if (!memory_ || !stack) { - BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; - } - - const vector<StackFrame*> &frames = *stack->frames(); - StackFrameARM64* last_frame = static_cast<StackFrameARM64*>(frames.back()); - scoped_ptr<StackFrameARM64> frame; - - // See if there is DWARF call frame information covering this address. - scoped_ptr<CFIFrameInfo> cfi_frame_info( - frame_symbolizer_->FindCFIFrameInfo(last_frame)); - if (cfi_frame_info.get()) - frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); - - // If CFI failed, or there wasn't CFI available, fall back to frame pointer. - if (!frame.get()) - frame.reset(GetCallerByFramePointer(frames)); - - // If everything failed, fall back to stack scanning. - if (stack_scan_allowed && !frame.get()) - frame.reset(GetCallerByStackScan(frames)); - - // If nothing worked, tell the caller. - if (!frame.get()) - return NULL; - - // An instruction address of zero marks the end of the stack. - if (frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] == 0) - return NULL; - - // If the new stack pointer is at a lower address than the old, then - // that's clearly incorrect. Treat this as end-of-stack to enforce - // progress and avoid infinite loops. - if (frame->context.iregs[MD_CONTEXT_ARM64_REG_SP] - < last_frame->context.iregs[MD_CONTEXT_ARM64_REG_SP]) - return NULL; - - // The new frame's context's PC is the return address, which is one - // instruction past the instruction that caused us to arrive at the callee. - // ARM64 instructions have a uniform 4-byte encoding, so subtracting 4 off - // the return address gets back to the beginning of the call instruction. - // Callers that require the exact return address value may access - // frame->context.iregs[MD_CONTEXT_ARM64_REG_PC]. - frame->instruction = frame->context.iregs[MD_CONTEXT_ARM64_REG_PC] - 4; - - return frame.release(); -} - - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.h deleted file mode 100644 index 121e82467..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64.h +++ /dev/null @@ -1,104 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_arm64.h: arm64-specific stackwalker. -// -// Provides stack frames given arm64 register context and a memory region -// corresponding to an arm64 stack. -// -// Author: Mark Mentovai, Ted Mielczarek, Colin Blundell - - -#ifndef PROCESSOR_STACKWALKER_ARM64_H__ -#define PROCESSOR_STACKWALKER_ARM64_H__ - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/stackwalker.h" - -namespace google_breakpad { - -class CodeModules; - -class StackwalkerARM64 : public Stackwalker { - public: - // context is an arm64 context object that gives access to arm64-specific - // register state corresponding to the innermost called frame to be - // included in the stack. The other arguments are passed directly through - // to the base Stackwalker constructor. - StackwalkerARM64(const SystemInfo* system_info, - const MDRawContextARM64* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer); - - // Change the context validity mask of the frame returned by - // GetContextFrame to VALID. This is only for use by unit tests; the - // default behavior is correct for all application code. - void SetContextFrameValidity(uint64_t valid) { - context_frame_validity_ = valid; - } - - private: - // Implementation of Stackwalker, using arm64 context and stack conventions. - virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed); - - // Use cfi_frame_info (derived from STACK CFI records) to construct - // the frame that called frames.back(). The caller takes ownership - // of the returned frame. Return NULL on failure. - StackFrameARM64* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames, - CFIFrameInfo* cfi_frame_info); - - // Use the frame pointer. The caller takes ownership of the returned frame. - // Return NULL on failure. - StackFrameARM64* GetCallerByFramePointer(const vector<StackFrame*> &frames); - - // Scan the stack for plausible return addresses. The caller takes ownership - // of the returned frame. Return NULL on failure. - StackFrameARM64* GetCallerByStackScan(const vector<StackFrame*> &frames); - - // Stores the CPU context corresponding to the youngest stack frame, to - // be returned by GetContextFrame. - const MDRawContextARM64* context_; - - // Validity mask for youngest stack frame. This is always - // CONTEXT_VALID_ALL in real use; it is only changeable for the sake of - // unit tests. - uint64_t context_frame_validity_; -}; - - -} // namespace google_breakpad - - -#endif // PROCESSOR_STACKWALKER_ARM64_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64_unittest.cc deleted file mode 100644 index f9d18cea0..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm64_unittest.cc +++ /dev/null @@ -1,880 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// stackwalker_arm64_unittest.cc: Unit tests for StackwalkerARM64 class. - -#include <string.h> -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/test_assembler.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/stackwalker_unittest_utils.h" -#include "processor/stackwalker_arm64.h" -#include "processor/windows_frame_info.h" - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::CallStack; -using google_breakpad::CodeModule; -using google_breakpad::StackFrameSymbolizer; -using google_breakpad::StackFrame; -using google_breakpad::StackFrameARM64; -using google_breakpad::Stackwalker; -using google_breakpad::StackwalkerARM64; -using google_breakpad::SystemInfo; -using google_breakpad::WindowsFrameInfo; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Label; -using google_breakpad::test_assembler::Section; -using std::vector; -using testing::_; -using testing::AnyNumber; -using testing::Return; -using testing::SetArgumentPointee; -using testing::Test; - -class StackwalkerARM64Fixture { - public: - StackwalkerARM64Fixture() - : stack_section(kLittleEndian), - // Give the two modules reasonable standard locations and names - // for tests to play with. - module1(0x40000000, 0x10000, "module1", "version1"), - module2(0x50000000, 0x10000, "module2", "version2") { - // Identify the system as an iOS system. - system_info.os = "iOS"; - system_info.os_short = "ios"; - system_info.cpu = "arm64"; - system_info.cpu_info = ""; - - // Put distinctive values in the raw CPU context. - BrandContext(&raw_context); - - // Create some modules with some stock debugging information. - modules.Add(&module1); - modules.Add(&module2); - - // By default, none of the modules have symbol info; call - // SetModuleSymbols to override this. - EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _)) - .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); - - // Avoid GMOCK WARNING "Uninteresting mock function call - returning - // directly" for FreeSymbolData(). - EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); - - // Reset max_frames_scanned since it's static. - Stackwalker::set_max_frames_scanned(1024); - } - - // Set the Breakpad symbol information that supplier should return for - // MODULE to INFO. - void SetModuleSymbols(MockCodeModule *module, const string &info) { - size_t buffer_size; - char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size); - EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _)) - .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), - SetArgumentPointee<4>(buffer_size), - Return(MockSymbolSupplier::FOUND))); - } - - // Populate stack_region with the contents of stack_section. Use - // stack_section.start() as the region's starting address. - void RegionFromSection() { - string contents; - ASSERT_TRUE(stack_section.GetContents(&contents)); - stack_region.Init(stack_section.start().Value(), contents); - } - - // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking. - void BrandContext(MDRawContextARM64 *raw_context) { - uint8_t x = 173; - for (size_t i = 0; i < sizeof(*raw_context); i++) - reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17); - } - - SystemInfo system_info; - MDRawContextARM64 raw_context; - Section stack_section; - MockMemoryRegion stack_region; - MockCodeModule module1; - MockCodeModule module2; - MockCodeModules modules; - MockSymbolSupplier supplier; - BasicSourceLineResolver resolver; - CallStack call_stack; - const vector<StackFrame *> *frames; -}; - -class SanityCheck: public StackwalkerARM64Fixture, public Test { }; - -TEST_F(SanityCheck, NoResolver) { - // Since the context's frame pointer is garbage, the stack walk will end after - // the first frame. - StackFrameSymbolizer frame_symbolizer(NULL, NULL); - StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - // This should succeed even without a resolver or supplier. - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - StackFrameARM64 *frame = static_cast<StackFrameARM64 *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -class GetContextFrame: public StackwalkerARM64Fixture, public Test { }; - -// The stackwalker should be able to produce the context frame even -// without stack memory present. -TEST_F(GetContextFrame, NoStackMemory) { - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, NULL, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - StackFrameARM64 *frame = static_cast<StackFrameARM64 *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -class GetCallerFrame: public StackwalkerARM64Fixture, public Test { }; - -TEST_F(GetCallerFrame, ScanWithoutSymbols) { - // When the stack walker resorts to scanning the stack, - // only addresses located within loaded modules are - // considered valid return addresses. - // Force scanning through three frames to ensure that the - // stack pointer is set properly in scan-recovered frames. - stack_section.start() = 0x80000000; - uint64_t return_address1 = 0x50000100; - uint64_t return_address2 = 0x50000900; - Label frame1_sp, frame2_sp; - stack_section - // frame 0 - .Append(16, 0) // space - - .D64(0x40090000) // junk that's not - .D64(0x60000000) // a return address - - .D64(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(16, 0) // space - - .D64(0xF0000000) // more junk - .D64(0x0000000D) - - .D64(return_address2) // actual return address - // frame 2 - .Mark(&frame2_sp) - .Append(64, 0); // end of stack - RegionFromSection(); - - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510; - raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(2U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(3U, frames->size()); - - StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL, - frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC | - StackFrameARM64::CONTEXT_VALID_SP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]); - - StackFrameARM64 *frame2 = static_cast<StackFrameARM64 *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust); - ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC | - StackFrameARM64::CONTEXT_VALID_SP), - frame2->context_validity); - EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM64_REG_PC]); - EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM64_REG_SP]); -} - -TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { - // During stack scanning, if a potential return address - // is located within a loaded module that has symbols, - // it is only considered a valid return address if it - // lies within a function's bounds. - stack_section.start() = 0x80000000; - uint64_t return_address = 0x50000200; - Label frame1_sp; - - stack_section - // frame 0 - .Append(16, 0) // space - - .D64(0x40090000) // junk that's not - .D64(0x60000000) // a return address - - .D64(0x40001000) // a couple of plausible addresses - .D64(0x5000F000) // that are not within functions - - .D64(return_address) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(64, 0); // end of stack - RegionFromSection(); - - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40000200; - raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value(); - - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 100 400 10 monotreme\n"); - SetModuleSymbols(&module2, - // The calling frame's function. - "FUNC 100 400 10 marsupial\n"); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL, - frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - EXPECT_EQ("monotreme", frame0->function_name); - EXPECT_EQ(0x40000100ULL, frame0->function_base); - - StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC | - StackFrameARM64::CONTEXT_VALID_SP), - frame1->context_validity); - EXPECT_EQ(return_address, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]); - EXPECT_EQ("marsupial", frame1->function_name); - EXPECT_EQ(0x50000100ULL, frame1->function_base); -} - -TEST_F(GetCallerFrame, ScanFirstFrame) { - // If the stackwalker resorts to stack scanning, it will scan much - // farther to find the caller of the context frame. - stack_section.start() = 0x80000000; - uint64_t return_address1 = 0x50000100; - uint64_t return_address2 = 0x50000900; - Label frame1_sp, frame2_sp; - stack_section - // frame 0 - .Append(32, 0) // space - - .D64(0x40090000) // junk that's not - .D64(0x60000000) // a return address - - .Append(96, 0) // more space - - .D64(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(32, 0) // space - - .D64(0xF0000000) // more junk - .D64(0x0000000D) - - .Append(336, 0) // more space - - .D64(return_address2) // actual return address - // (won't be found) - // frame 2 - .Mark(&frame2_sp) - .Append(64, 0); // end of stack - RegionFromSection(); - - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510; - raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(2U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL, - frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC | - StackFrameARM64::CONTEXT_VALID_SP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]); -} - -// Test that set_max_frames_scanned prevents using stack scanning -// to find caller frames. -TEST_F(GetCallerFrame, ScanningNotAllowed) { - // When the stack walker resorts to scanning the stack, - // only addresses located within loaded modules are - // considered valid return addresses. - stack_section.start() = 0x80000000; - uint64_t return_address1 = 0x50000100; - uint64_t return_address2 = 0x50000900; - Label frame1_sp, frame2_sp; - stack_section - // frame 0 - .Append(16, 0) // space - - .D64(0x40090000) // junk that's not - .D64(0x60000000) // a return address - - .D64(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(16, 0) // space - - .D64(0xF0000000) // more junk - .D64(0x0000000D) - - .D64(return_address2) // actual return address - // frame 2 - .Mark(&frame2_sp) - .Append(64, 0); // end of stack - RegionFromSection(); - - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510; - raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - Stackwalker::set_max_frames_scanned(0); - - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - - StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL, - frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); -} - -class GetFramesByFramePointer: public StackwalkerARM64Fixture, public Test { }; - -TEST_F(GetFramesByFramePointer, OnlyFramePointer) { - stack_section.start() = 0x80000000; - uint64_t return_address1 = 0x50000100; - uint64_t return_address2 = 0x50000900; - Label frame1_sp, frame2_sp; - Label frame1_fp, frame2_fp; - stack_section - // frame 0 - .Append(64, 0) // Whatever values on the stack. - .D64(0x0000000D) // junk that's not - .D64(0xF0000000) // a return address. - - .Mark(&frame1_fp) // Next fp will point to the next value. - .D64(frame2_fp) // Save current frame pointer. - .D64(return_address2) // Save current link register. - .Mark(&frame1_sp) - - // frame 1 - .Append(64, 0) // Whatever values on the stack. - .D64(0x0000000D) // junk that's not - .D64(0xF0000000) // a return address. - - .Mark(&frame2_fp) - .D64(0) - .D64(0) - .Mark(&frame2_sp) - - // frame 2 - .Append(64, 0) // Whatever values on the stack. - .D64(0x0000000D) // junk that's not - .D64(0xF0000000); // a return address. - RegionFromSection(); - - - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x40005510; - raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = return_address1; - raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = frame1_fp.Value(); - raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, - &stack_region, &modules, &frame_symbolizer); - - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(2U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(3U, frames->size()); - - StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM64::CONTEXT_VALID_ALL, - frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); - ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC | - StackFrameARM64::CONTEXT_VALID_LR | - StackFrameARM64::CONTEXT_VALID_FP | - StackFrameARM64::CONTEXT_VALID_SP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]); - EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM64_REG_LR]); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]); - EXPECT_EQ(frame2_fp.Value(), - frame1->context.iregs[MD_CONTEXT_ARM64_REG_FP]); - - StackFrameARM64 *frame2 = static_cast<StackFrameARM64 *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame2->trust); - ASSERT_EQ((StackFrameARM64::CONTEXT_VALID_PC | - StackFrameARM64::CONTEXT_VALID_LR | - StackFrameARM64::CONTEXT_VALID_FP | - StackFrameARM64::CONTEXT_VALID_SP), - frame2->context_validity); - EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM64_REG_PC]); - EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM64_REG_LR]); - EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM64_REG_SP]); - EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM64_REG_FP]); -} - -struct CFIFixture: public StackwalkerARM64Fixture { - CFIFixture() { - // Provide a bunch of STACK CFI records; we'll walk to the caller - // from every point in this series, expecting to find the same set - // of register values. - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 4000 1000 10 enchiridion\n" - // Initially, nothing has been pushed on the stack, - // and the return address is still in the link - // register (x30). - "STACK CFI INIT 4000 100 .cfa: sp 0 + .ra: x30\n" - // Push x19, x20, the frame pointer and the link register. - "STACK CFI 4001 .cfa: sp 32 + .ra: .cfa -8 + ^" - " x19: .cfa -32 + ^ x20: .cfa -24 + ^ " - " x29: .cfa -16 + ^\n" - // Save x19..x22 in x0..x3: verify that we populate - // the youngest frame with all the values we have. - "STACK CFI 4002 x19: x0 x20: x1 x21: x2 x22: x3\n" - // Restore x19..x22. Save the non-callee-saves register x1. - "STACK CFI 4003 .cfa: sp 40 + x1: .cfa 40 - ^" - " x19: x19 x20: x20 x21: x21 x22: x22\n" - // Move the .cfa back eight bytes, to point at the return - // address, and restore the sp explicitly. - "STACK CFI 4005 .cfa: sp 32 + x1: .cfa 32 - ^" - " x29: .cfa 8 - ^ .ra: .cfa ^ sp: .cfa 8 +\n" - // Recover the PC explicitly from a new stack slot; - // provide garbage for the .ra. - "STACK CFI 4006 .cfa: sp 40 + pc: .cfa 40 - ^\n" - - // The calling function. - "FUNC 5000 1000 10 epictetus\n" - // Mark it as end of stack. - "STACK CFI INIT 5000 1000 .cfa: 0 .ra: 0\n" - - // A function whose CFI makes the stack pointer - // go backwards. - "FUNC 6000 1000 20 palinal\n" - "STACK CFI INIT 6000 1000 .cfa: sp 8 - .ra: x30\n" - - // A function with CFI expressions that can't be - // evaluated. - "FUNC 7000 1000 20 rhetorical\n" - "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n"); - - // Provide some distinctive values for the caller's registers. - expected.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040005510L; - expected.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L; - expected.iregs[19] = 0x5e68b5d5b5d55e68L; - expected.iregs[20] = 0x34f3ebd1ebd134f3L; - expected.iregs[21] = 0x74bca31ea31e74bcL; - expected.iregs[22] = 0x16b32dcb2dcb16b3L; - expected.iregs[23] = 0x21372ada2ada2137L; - expected.iregs[24] = 0x557dbbbbbbbb557dL; - expected.iregs[25] = 0x8ca748bf48bf8ca7L; - expected.iregs[26] = 0x21f0ab46ab4621f0L; - expected.iregs[27] = 0x146732b732b71467L; - expected.iregs[28] = 0xa673645fa673645fL; - expected.iregs[MD_CONTEXT_ARM64_REG_FP] = 0xe11081128112e110L; - - // Expect CFI to recover all callee-saves registers. Since CFI is the - // only stack frame construction technique we have, aside from the - // context frame itself, there's no way for us to have a set of valid - // registers smaller than this. - expected_validity = (StackFrameARM64::CONTEXT_VALID_PC | - StackFrameARM64::CONTEXT_VALID_SP | - StackFrameARM64::CONTEXT_VALID_X19 | - StackFrameARM64::CONTEXT_VALID_X20 | - StackFrameARM64::CONTEXT_VALID_X21 | - StackFrameARM64::CONTEXT_VALID_X22 | - StackFrameARM64::CONTEXT_VALID_X23 | - StackFrameARM64::CONTEXT_VALID_X24 | - StackFrameARM64::CONTEXT_VALID_X25 | - StackFrameARM64::CONTEXT_VALID_X26 | - StackFrameARM64::CONTEXT_VALID_X27 | - StackFrameARM64::CONTEXT_VALID_X28 | - StackFrameARM64::CONTEXT_VALID_FP); - - // By default, context frames provide all registers, as normal. - context_frame_validity = StackFrameARM64::CONTEXT_VALID_ALL; - - // By default, registers are unchanged. - raw_context = expected; - } - - // Walk the stack, using stack_section as the contents of the stack - // and raw_context as the current register values. (Set the stack - // pointer to the stack's starting address.) Expect two stack - // frames; in the older frame, expect the callee-saves registers to - // have values matching those in 'expected'. - void CheckWalk() { - RegionFromSection(); - raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, - &modules, &frame_symbolizer); - walker.SetContextFrameValidity(context_frame_validity); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameARM64 *frame0 = static_cast<StackFrameARM64 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(context_frame_validity, frame0->context_validity); - EXPECT_EQ("enchiridion", frame0->function_name); - EXPECT_EQ(0x0000000040004000UL, frame0->function_base); - - StackFrameARM64 *frame1 = static_cast<StackFrameARM64 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ(expected_validity, frame1->context_validity); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X1) - EXPECT_EQ(expected.iregs[1], frame1->context.iregs[1]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X19) - EXPECT_EQ(expected.iregs[19], frame1->context.iregs[19]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X20) - EXPECT_EQ(expected.iregs[20], frame1->context.iregs[20]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X21) - EXPECT_EQ(expected.iregs[21], frame1->context.iregs[21]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X22) - EXPECT_EQ(expected.iregs[22], frame1->context.iregs[22]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X23) - EXPECT_EQ(expected.iregs[23], frame1->context.iregs[23]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X24) - EXPECT_EQ(expected.iregs[24], frame1->context.iregs[24]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X25) - EXPECT_EQ(expected.iregs[25], frame1->context.iregs[25]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X26) - EXPECT_EQ(expected.iregs[26], frame1->context.iregs[26]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X27) - EXPECT_EQ(expected.iregs[27], frame1->context.iregs[27]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_X28) - EXPECT_EQ(expected.iregs[28], frame1->context.iregs[28]); - if (expected_validity & StackFrameARM64::CONTEXT_VALID_FP) - EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_FP], - frame1->context.iregs[MD_CONTEXT_ARM64_REG_FP]); - - // We would never have gotten a frame in the first place if the SP - // and PC weren't valid or ->instruction weren't set. - EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_SP], - frame1->context.iregs[MD_CONTEXT_ARM64_REG_SP]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_PC], - frame1->context.iregs[MD_CONTEXT_ARM64_REG_PC]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM64_REG_PC], - frame1->instruction + 4); - EXPECT_EQ("epictetus", frame1->function_name); - } - - // The values we expect to find for the caller's registers. - MDRawContextARM64 expected; - - // The validity mask for expected. - uint64_t expected_validity; - - // The validity mask to impose on the context frame. - uint64_t context_frame_validity; -}; - -class CFI: public CFIFixture, public Test { }; - -TEST_F(CFI, At4000) { - stack_section.start() = expected.iregs[MD_CONTEXT_ARM64_REG_SP]; - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004000L; - raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = 0x0000000040005510L; - CheckWalk(); -} - -TEST_F(CFI, At4001) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP]; - stack_section - .D64(0x5e68b5d5b5d55e68L) // saved x19 - .D64(0x34f3ebd1ebd134f3L) // saved x20 - .D64(0xe11081128112e110L) // saved fp - .D64(0x0000000040005510L) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004001L; - // distinct callee x19, x20 and fp - raw_context.iregs[19] = 0xadc9f635a635adc9L; - raw_context.iregs[20] = 0x623135ac35ac6231L; - raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L; - CheckWalk(); -} - -// As above, but unwind from a context that has only the PC and SP. -TEST_F(CFI, At4001LimitedValidity) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP]; - stack_section - .D64(0x5e68b5d5b5d55e68L) // saved x19 - .D64(0x34f3ebd1ebd134f3L) // saved x20 - .D64(0xe11081128112e110L) // saved fp - .D64(0x0000000040005510L) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - context_frame_validity = - StackFrameARM64::CONTEXT_VALID_PC | StackFrameARM64::CONTEXT_VALID_SP; - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004001L; - raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L; - - expected_validity = (StackFrameARM64::CONTEXT_VALID_PC - | StackFrameARM64::CONTEXT_VALID_SP - | StackFrameARM64::CONTEXT_VALID_FP - | StackFrameARM64::CONTEXT_VALID_X19 - | StackFrameARM64::CONTEXT_VALID_X20); - CheckWalk(); -} - -TEST_F(CFI, At4002) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP]; - stack_section - .D64(0xff3dfb81fb81ff3dL) // no longer saved x19 - .D64(0x34f3ebd1ebd134f3L) // no longer saved x20 - .D64(0xe11081128112e110L) // saved fp - .D64(0x0000000040005510L) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004002L; - raw_context.iregs[0] = 0x5e68b5d5b5d55e68L; // saved x19 - raw_context.iregs[1] = 0x34f3ebd1ebd134f3L; // saved x20 - raw_context.iregs[2] = 0x74bca31ea31e74bcL; // saved x21 - raw_context.iregs[3] = 0x16b32dcb2dcb16b3L; // saved x22 - raw_context.iregs[19] = 0xadc9f635a635adc9L; // distinct callee x19 - raw_context.iregs[20] = 0x623135ac35ac6231L; // distinct callee x20 - raw_context.iregs[21] = 0xac4543564356ac45L; // distinct callee x21 - raw_context.iregs[22] = 0x2561562f562f2561L; // distinct callee x22 - // distinct callee fp - raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L; - CheckWalk(); -} - -TEST_F(CFI, At4003) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP]; - stack_section - .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves) - .D64(0xff3dfb81fb81ff3dL) // no longer saved x19 - .D64(0x34f3ebd1ebd134f3L) // no longer saved x20 - .D64(0xe11081128112e110L) // saved fp - .D64(0x0000000040005510L) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004003L; - // distinct callee x1 and fp - raw_context.iregs[1] = 0xfb756319fb756319L; - raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L; - // caller's x1 - expected.iregs[1] = 0xdd5a48c848c8dd5aL; - expected_validity |= StackFrameARM64::CONTEXT_VALID_X1; - CheckWalk(); -} - -// We have no new rule at module offset 0x4004, so the results here should -// be the same as those at module offset 0x4003. -TEST_F(CFI, At4004) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP]; - stack_section - .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves) - .D64(0xff3dfb81fb81ff3dL) // no longer saved x19 - .D64(0x34f3ebd1ebd134f3L) // no longer saved x20 - .D64(0xe11081128112e110L) // saved fp - .D64(0x0000000040005510L) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004004L; - // distinct callee x1 and fp - raw_context.iregs[1] = 0xfb756319fb756319L; - raw_context.iregs[MD_CONTEXT_ARM64_REG_FP] = 0x5fc4be14be145fc4L; - // caller's x1 - expected.iregs[1] = 0xdd5a48c848c8dd5aL; - expected_validity |= StackFrameARM64::CONTEXT_VALID_X1; - CheckWalk(); -} - -// Here we move the .cfa, but provide an explicit rule to recover the SP, -// so again there should be no change in the registers recovered. -TEST_F(CFI, At4005) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP]; - stack_section - .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves) - .D64(0xff3dfb81fb81ff3dL) // no longer saved x19 - .D64(0x34f3ebd1ebd134f3L) // no longer saved x20 - .D64(0xe11081128112e110L) // saved fp - .D64(0x0000000040005510L) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004005L; - raw_context.iregs[1] = 0xfb756319fb756319L; // distinct callee x1 - expected.iregs[1] = 0xdd5a48c848c8dd5aL; // caller's x1 - expected_validity |= StackFrameARM64::CONTEXT_VALID_X1; - CheckWalk(); -} - -// Here we provide an explicit rule for the PC, and have the saved .ra be -// bogus. -TEST_F(CFI, At4006) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM64_REG_SP]; - stack_section - .D64(0x0000000040005510L) // saved pc - .D64(0xdd5a48c848c8dd5aL) // saved x1 (even though it's not callee-saves) - .D64(0xff3dfb81fb81ff3dL) // no longer saved x19 - .D64(0x34f3ebd1ebd134f3L) // no longer saved x20 - .D64(0xe11081128112e110L) // saved fp - .D64(0xf8d157835783f8d1L) // .ra rule recovers this, which is garbage - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040004006L; - raw_context.iregs[1] = 0xfb756319fb756319L; // distinct callee x1 - expected.iregs[1] = 0xdd5a48c848c8dd5aL; // caller's x1 - expected_validity |= StackFrameARM64::CONTEXT_VALID_X1; - CheckWalk(); -} - -// Check that we reject rules that would cause the stack pointer to -// move in the wrong direction. -TEST_F(CFI, RejectBackwards) { - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040006000L; - raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L; - raw_context.iregs[MD_CONTEXT_ARM64_REG_LR] = 0x0000000040005510L; - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); -} - -// Check that we reject rules whose expressions' evaluation fails. -TEST_F(CFI, RejectBadExpressions) { - raw_context.iregs[MD_CONTEXT_ARM64_REG_PC] = 0x0000000040007000L; - raw_context.iregs[MD_CONTEXT_ARM64_REG_SP] = 0x0000000080000000L; - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM64 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm_unittest.cc deleted file mode 100644 index 8a0fd5e95..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_arm_unittest.cc +++ /dev/null @@ -1,974 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// stackwalker_arm_unittest.cc: Unit tests for StackwalkerARM class. - -#include <string.h> -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/test_assembler.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/stackwalker_unittest_utils.h" -#include "processor/stackwalker_arm.h" -#include "processor/windows_frame_info.h" - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::CallStack; -using google_breakpad::CodeModule; -using google_breakpad::StackFrameSymbolizer; -using google_breakpad::StackFrame; -using google_breakpad::StackFrameARM; -using google_breakpad::Stackwalker; -using google_breakpad::StackwalkerARM; -using google_breakpad::SystemInfo; -using google_breakpad::WindowsFrameInfo; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Label; -using google_breakpad::test_assembler::Section; -using std::vector; -using testing::_; -using testing::AnyNumber; -using testing::Return; -using testing::SetArgumentPointee; -using testing::Test; - -class StackwalkerARMFixture { - public: - StackwalkerARMFixture() - : stack_section(kLittleEndian), - // Give the two modules reasonable standard locations and names - // for tests to play with. - module1(0x40000000, 0x10000, "module1", "version1"), - module2(0x50000000, 0x10000, "module2", "version2") { - // Identify the system as a Linux system. - system_info.os = "Linux"; - system_info.os_short = "linux"; - system_info.os_version = "Lugubrious Labrador"; - system_info.cpu = "arm"; - system_info.cpu_info = ""; - - // Put distinctive values in the raw CPU context. - BrandContext(&raw_context); - - // Create some modules with some stock debugging information. - modules.Add(&module1); - modules.Add(&module2); - - // By default, none of the modules have symbol info; call - // SetModuleSymbols to override this. - EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _)) - .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); - - // Avoid GMOCK WARNING "Uninteresting mock function call - returning - // directly" for FreeSymbolData(). - EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); - - // Reset max_frames_scanned since it's static. - Stackwalker::set_max_frames_scanned(1024); - } - - // Set the Breakpad symbol information that supplier should return for - // MODULE to INFO. - void SetModuleSymbols(MockCodeModule *module, const string &info) { - size_t buffer_size; - char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size); - EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _)) - .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), - SetArgumentPointee<4>(buffer_size), - Return(MockSymbolSupplier::FOUND))); - } - - // Populate stack_region with the contents of stack_section. Use - // stack_section.start() as the region's starting address. - void RegionFromSection() { - string contents; - ASSERT_TRUE(stack_section.GetContents(&contents)); - stack_region.Init(stack_section.start().Value(), contents); - } - - // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking. - void BrandContext(MDRawContextARM *raw_context) { - uint8_t x = 173; - for (size_t i = 0; i < sizeof(*raw_context); i++) - reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17); - } - - SystemInfo system_info; - MDRawContextARM raw_context; - Section stack_section; - MockMemoryRegion stack_region; - MockCodeModule module1; - MockCodeModule module2; - MockCodeModules modules; - MockSymbolSupplier supplier; - BasicSourceLineResolver resolver; - CallStack call_stack; - const vector<StackFrame *> *frames; -}; - -class SanityCheck: public StackwalkerARMFixture, public Test { }; - -TEST_F(SanityCheck, NoResolver) { - // Since we have no call frame information, and all unwinding - // requires call frame information, the stack walk will end after - // the first frame. - StackFrameSymbolizer frame_symbolizer(NULL, NULL); - StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &frame_symbolizer); - // This should succeed even without a resolver or supplier. - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -class GetContextFrame: public StackwalkerARMFixture, public Test { }; - -TEST_F(GetContextFrame, Simple) { - // Since we have no call frame information, and all unwinding - // requires call frame information, the stack walk will end after - // the first frame. - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -// The stackwalker should be able to produce the context frame even -// without stack memory present. -TEST_F(GetContextFrame, NoStackMemory) { - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, NULL, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - StackFrameARM *frame = static_cast<StackFrameARM *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -class GetCallerFrame: public StackwalkerARMFixture, public Test { }; - -TEST_F(GetCallerFrame, ScanWithoutSymbols) { - // When the stack walker resorts to scanning the stack, - // only addresses located within loaded modules are - // considered valid return addresses. - // Force scanning through three frames to ensure that the - // stack pointer is set properly in scan-recovered frames. - stack_section.start() = 0x80000000; - uint32_t return_address1 = 0x50000100; - uint32_t return_address2 = 0x50000900; - Label frame1_sp, frame2_sp; - stack_section - // frame 0 - .Append(16, 0) // space - - .D32(0x40090000) // junk that's not - .D32(0x60000000) // a return address - - .D32(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(16, 0) // space - - .D32(0xF0000000) // more junk - .D32(0x0000000D) - - .D32(return_address2) // actual return address - // frame 2 - .Mark(&frame2_sp) - .Append(32, 0); // end of stack - RegionFromSection(); - - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; - raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(2U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(3U, frames->size()); - - StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_SP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); - - StackFrameARM *frame2 = static_cast<StackFrameARM *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust); - ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_SP), - frame2->context_validity); - EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM_REG_PC]); - EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM_REG_SP]); -} - -TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { - // During stack scanning, if a potential return address - // is located within a loaded module that has symbols, - // it is only considered a valid return address if it - // lies within a function's bounds. - stack_section.start() = 0x80000000; - uint32_t return_address = 0x50000200; - Label frame1_sp; - - stack_section - // frame 0 - .Append(16, 0) // space - - .D32(0x40090000) // junk that's not - .D32(0x60000000) // a return address - - .D32(0x40001000) // a couple of plausible addresses - .D32(0x5000F000) // that are not within functions - - .D32(return_address) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(32, 0); // end of stack - RegionFromSection(); - - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40000200; - raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); - - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 100 400 10 monotreme\n"); - SetModuleSymbols(&module2, - // The calling frame's function. - "FUNC 100 400 10 marsupial\n"); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - EXPECT_EQ("monotreme", frame0->function_name); - EXPECT_EQ(0x40000100U, frame0->function_base); - - StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_SP), - frame1->context_validity); - EXPECT_EQ(return_address, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); - EXPECT_EQ("marsupial", frame1->function_name); - EXPECT_EQ(0x50000100U, frame1->function_base); -} - -TEST_F(GetCallerFrame, ScanFirstFrame) { - // If the stackwalker resorts to stack scanning, it will scan much - // farther to find the caller of the context frame. - stack_section.start() = 0x80000000; - uint32_t return_address1 = 0x50000100; - uint32_t return_address2 = 0x50000900; - Label frame1_sp, frame2_sp; - stack_section - // frame 0 - .Append(32, 0) // space - - .D32(0x40090000) // junk that's not - .D32(0x60000000) // a return address - - .Append(96, 0) // more space - - .D32(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(32, 0) // space - - .D32(0xF0000000) // more junk - .D32(0x0000000D) - - .Append(136, 0) // more space - - .D32(return_address2) // actual return address - // (won't be found) - // frame 2 - .Mark(&frame2_sp) - .Append(32, 0); // end of stack - RegionFromSection(); - - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; - raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(2U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_SP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); -} - -// Test that set_max_frames_scanned prevents using stack scanning -// to find caller frames. -TEST_F(GetCallerFrame, ScanningNotAllowed) { - // When the stack walker resorts to scanning the stack, - // only addresses located within loaded modules are - // considered valid return addresses. - stack_section.start() = 0x80000000; - uint32_t return_address1 = 0x50000100; - uint32_t return_address2 = 0x50000900; - Label frame1_sp, frame2_sp; - stack_section - // frame 0 - .Append(16, 0) // space - - .D32(0x40090000) // junk that's not - .D32(0x60000000) // a return address - - .D32(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(16, 0) // space - - .D32(0xF0000000) // more junk - .D32(0x0000000D) - - .D32(return_address2) // actual return address - // frame 2 - .Mark(&frame2_sp) - .Append(32, 0); // end of stack - RegionFromSection(); - - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; - raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &frame_symbolizer); - Stackwalker::set_max_frames_scanned(0); - - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - - StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); -} - -struct CFIFixture: public StackwalkerARMFixture { - CFIFixture() { - // Provide a bunch of STACK CFI records; we'll walk to the caller - // from every point in this series, expecting to find the same set - // of register values. - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 4000 1000 10 enchiridion\n" - // Initially, nothing has been pushed on the stack, - // and the return address is still in the link register. - "STACK CFI INIT 4000 100 .cfa: sp .ra: lr\n" - // Push r4, the frame pointer, and the link register. - "STACK CFI 4001 .cfa: sp 12 + r4: .cfa 12 - ^" - " r11: .cfa 8 - ^ .ra: .cfa 4 - ^\n" - // Save r4..r7 in r0..r3: verify that we populate - // the youngest frame with all the values we have. - "STACK CFI 4002 r4: r0 r5: r1 r6: r2 r7: r3\n" - // Restore r4..r7. Save the non-callee-saves register r1. - "STACK CFI 4003 .cfa: sp 16 + r1: .cfa 16 - ^" - " r4: r4 r5: r5 r6: r6 r7: r7\n" - // Move the .cfa back four bytes, to point at the return - // address, and restore the sp explicitly. - "STACK CFI 4005 .cfa: sp 12 + r1: .cfa 12 - ^" - " r11: .cfa 4 - ^ .ra: .cfa ^ sp: .cfa 4 +\n" - // Recover the PC explicitly from a new stack slot; - // provide garbage for the .ra. - "STACK CFI 4006 .cfa: sp 16 + pc: .cfa 16 - ^\n" - - // The calling function. - "FUNC 5000 1000 10 epictetus\n" - // Mark it as end of stack. - "STACK CFI INIT 5000 1000 .cfa: 0 .ra: 0\n" - - // A function whose CFI makes the stack pointer - // go backwards. - "FUNC 6000 1000 20 palinal\n" - "STACK CFI INIT 6000 1000 .cfa: sp 4 - .ra: lr\n" - - // A function with CFI expressions that can't be - // evaluated. - "FUNC 7000 1000 20 rhetorical\n" - "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n"); - - // Provide some distinctive values for the caller's registers. - expected.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; - expected.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000; - expected.iregs[4] = 0xb5d55e68; - expected.iregs[5] = 0xebd134f3; - expected.iregs[6] = 0xa31e74bc; - expected.iregs[7] = 0x2dcb16b3; - expected.iregs[8] = 0x2ada2137; - expected.iregs[9] = 0xbbbb557d; - expected.iregs[10] = 0x48bf8ca7; - expected.iregs[MD_CONTEXT_ARM_REG_FP] = 0x8112e110; - - // Expect CFI to recover all callee-saves registers. Since CFI is the - // only stack frame construction technique we have, aside from the - // context frame itself, there's no way for us to have a set of valid - // registers smaller than this. - expected_validity = (StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_SP | - StackFrameARM::CONTEXT_VALID_R4 | - StackFrameARM::CONTEXT_VALID_R5 | - StackFrameARM::CONTEXT_VALID_R6 | - StackFrameARM::CONTEXT_VALID_R7 | - StackFrameARM::CONTEXT_VALID_R8 | - StackFrameARM::CONTEXT_VALID_R9 | - StackFrameARM::CONTEXT_VALID_R10 | - StackFrameARM::CONTEXT_VALID_FP); - - // By default, context frames provide all registers, as normal. - context_frame_validity = StackFrameARM::CONTEXT_VALID_ALL; - - // By default, registers are unchanged. - raw_context = expected; - } - - // Walk the stack, using stack_section as the contents of the stack - // and raw_context as the current register values. (Set the stack - // pointer to the stack's starting address.) Expect two stack - // frames; in the older frame, expect the callee-saves registers to - // have values matching those in 'expected'. - void CheckWalk() { - RegionFromSection(); - raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, - &modules, &frame_symbolizer); - walker.SetContextFrameValidity(context_frame_validity); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(context_frame_validity, frame0->context_validity); - EXPECT_EQ("enchiridion", frame0->function_name); - EXPECT_EQ(0x40004000U, frame0->function_base); - - StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ(expected_validity, frame1->context_validity); - if (expected_validity & StackFrameARM::CONTEXT_VALID_R1) - EXPECT_EQ(expected.iregs[1], frame1->context.iregs[1]); - if (expected_validity & StackFrameARM::CONTEXT_VALID_R4) - EXPECT_EQ(expected.iregs[4], frame1->context.iregs[4]); - if (expected_validity & StackFrameARM::CONTEXT_VALID_R5) - EXPECT_EQ(expected.iregs[5], frame1->context.iregs[5]); - if (expected_validity & StackFrameARM::CONTEXT_VALID_R6) - EXPECT_EQ(expected.iregs[6], frame1->context.iregs[6]); - if (expected_validity & StackFrameARM::CONTEXT_VALID_R7) - EXPECT_EQ(expected.iregs[7], frame1->context.iregs[7]); - if (expected_validity & StackFrameARM::CONTEXT_VALID_R8) - EXPECT_EQ(expected.iregs[8], frame1->context.iregs[8]); - if (expected_validity & StackFrameARM::CONTEXT_VALID_R9) - EXPECT_EQ(expected.iregs[9], frame1->context.iregs[9]); - if (expected_validity & StackFrameARM::CONTEXT_VALID_R10) - EXPECT_EQ(expected.iregs[10], frame1->context.iregs[10]); - if (expected_validity & StackFrameARM::CONTEXT_VALID_FP) - EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_FP], - frame1->context.iregs[MD_CONTEXT_ARM_REG_FP]); - - // We would never have gotten a frame in the first place if the SP - // and PC weren't valid or ->instruction weren't set. - EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_SP], - frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_PC], - frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_ARM_REG_PC], - frame1->instruction + 2); - EXPECT_EQ("epictetus", frame1->function_name); - } - - // The values we expect to find for the caller's registers. - MDRawContextARM expected; - - // The validity mask for expected. - int expected_validity; - - // The validity mask to impose on the context frame. - int context_frame_validity; -}; - -class CFI: public CFIFixture, public Test { }; - -TEST_F(CFI, At4000) { - stack_section.start() = expected.iregs[MD_CONTEXT_ARM_REG_SP]; - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004000; - raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = 0x40005510; - CheckWalk(); -} - -TEST_F(CFI, At4001) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; - stack_section - .D32(0xb5d55e68) // saved r4 - .D32(0x8112e110) // saved fp - .D32(0x40005510) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004001; - raw_context.iregs[4] = 0x635adc9f; // distinct callee r4 - raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0xbe145fc4; // distinct callee fp - CheckWalk(); -} - -// As above, but unwind from a context that has only the PC and SP. -TEST_F(CFI, At4001LimitedValidity) { - context_frame_validity = - StackFrameARM::CONTEXT_VALID_PC | StackFrameARM::CONTEXT_VALID_SP; - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004001; - raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0xbe145fc4; // distinct callee fp - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; - stack_section - .D32(0xb5d55e68) // saved r4 - .D32(0x8112e110) // saved fp - .D32(0x40005510) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - expected_validity = (StackFrameARM::CONTEXT_VALID_PC - | StackFrameARM::CONTEXT_VALID_SP - | StackFrameARM::CONTEXT_VALID_FP - | StackFrameARM::CONTEXT_VALID_R4); - CheckWalk(); -} - -TEST_F(CFI, At4002) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; - stack_section - .D32(0xfb81ff3d) // no longer saved r4 - .D32(0x8112e110) // saved fp - .D32(0x40005510) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004002; - raw_context.iregs[0] = 0xb5d55e68; // saved r4 - raw_context.iregs[1] = 0xebd134f3; // saved r5 - raw_context.iregs[2] = 0xa31e74bc; // saved r6 - raw_context.iregs[3] = 0x2dcb16b3; // saved r7 - raw_context.iregs[4] = 0xfdd35466; // distinct callee r4 - raw_context.iregs[5] = 0xf18c946c; // distinct callee r5 - raw_context.iregs[6] = 0xac2079e8; // distinct callee r6 - raw_context.iregs[7] = 0xa449829f; // distinct callee r7 - raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0xbe145fc4; // distinct callee fp - CheckWalk(); -} - -TEST_F(CFI, At4003) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; - stack_section - .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves) - .D32(0xcb78040e) // no longer saved r4 - .D32(0x8112e110) // saved fp - .D32(0x40005510) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004003; - raw_context.iregs[1] = 0xfb756319; // distinct callee r1 - raw_context.iregs[MD_CONTEXT_ARM_REG_FP] = 0x0a2857ea; // distinct callee fp - expected.iregs[1] = 0x48c8dd5a; // caller's r1 - expected_validity |= StackFrameARM::CONTEXT_VALID_R1; - CheckWalk(); -} - -// We have no new rule at module offset 0x4004, so the results here should -// be the same as those at module offset 0x4003. -TEST_F(CFI, At4004) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; - stack_section - .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves) - .D32(0xcb78040e) // no longer saved r4 - .D32(0x8112e110) // saved fp - .D32(0x40005510) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004004; - raw_context.iregs[1] = 0xfb756319; // distinct callee r1 - expected.iregs[1] = 0x48c8dd5a; // caller's r1 - expected_validity |= StackFrameARM::CONTEXT_VALID_R1; - CheckWalk(); -} - -// Here we move the .cfa, but provide an explicit rule to recover the SP, -// so again there should be no change in the registers recovered. -TEST_F(CFI, At4005) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; - stack_section - .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves) - .D32(0xf013f841) // no longer saved r4 - .D32(0x8112e110) // saved fp - .D32(0x40005510) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004005; - raw_context.iregs[1] = 0xfb756319; // distinct callee r1 - expected.iregs[1] = 0x48c8dd5a; // caller's r1 - expected_validity |= StackFrameARM::CONTEXT_VALID_R1; - CheckWalk(); -} - -// Here we provide an explicit rule for the PC, and have the saved .ra be -// bogus. -TEST_F(CFI, At4006) { - Label frame1_sp = expected.iregs[MD_CONTEXT_ARM_REG_SP]; - stack_section - .D32(0x40005510) // saved pc - .D32(0x48c8dd5a) // saved r1 (even though it's not callee-saves) - .D32(0xf013f841) // no longer saved r4 - .D32(0x8112e110) // saved fp - .D32(0xf8d15783) // .ra rule recovers this, which is garbage - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40004006; - raw_context.iregs[1] = 0xfb756319; // callee's r1, different from caller's - expected.iregs[1] = 0x48c8dd5a; // caller's r1 - expected_validity |= StackFrameARM::CONTEXT_VALID_R1; - CheckWalk(); -} - -// Check that we reject rules that would cause the stack pointer to -// move in the wrong direction. -TEST_F(CFI, RejectBackwards) { - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40006000; - raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000; - raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = 0x40005510; - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); -} - -// Check that we reject rules whose expressions' evaluation fails. -TEST_F(CFI, RejectBadExpressions) { - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40007000; - raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = 0x80000000; - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, -1, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); -} - -class StackwalkerARMFixtureIOS : public StackwalkerARMFixture { - public: - StackwalkerARMFixtureIOS() { - system_info.os = "iOS"; - system_info.os_short = "ios"; - } -}; - -class GetFramesByFramePointer: public StackwalkerARMFixtureIOS, public Test { }; - -TEST_F(GetFramesByFramePointer, OnlyFramePointer) { - stack_section.start() = 0x80000000; - uint32_t return_address1 = 0x50000100; - uint32_t return_address2 = 0x50000900; - Label frame1_sp, frame2_sp; - Label frame1_fp, frame2_fp; - stack_section - // frame 0 - .Append(32, 0) // Whatever values on the stack. - .D32(0x0000000D) // junk that's not - .D32(0xF0000000) // a return address. - - .Mark(&frame1_fp) // Next fp will point to the next value. - .D32(frame2_fp) // Save current frame pointer. - .D32(return_address2) // Save current link register. - .Mark(&frame1_sp) - - // frame 1 - .Append(32, 0) // Whatever values on the stack. - .D32(0x0000000D) // junk that's not - .D32(0xF0000000) // a return address. - - .Mark(&frame2_fp) - .D32(0) - .D32(0) - .Mark(&frame2_sp) - - // frame 2 - .Append(32, 0) // Whatever values on the stack. - .D32(0x0000000D) // junk that's not - .D32(0xF0000000); // a return address. - RegionFromSection(); - - - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x40005510; - raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = return_address1; - raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value(); - raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP, - &stack_region, &modules, &frame_symbolizer); - - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(2U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(3U, frames->size()); - - StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); - ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_LR | - StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) | - StackFrameARM::CONTEXT_VALID_SP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); - EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM_REG_LR]); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); - EXPECT_EQ(frame2_fp.Value(), - frame1->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]); - - StackFrameARM *frame2 = static_cast<StackFrameARM *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame2->trust); - ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_LR | - StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) | - StackFrameARM::CONTEXT_VALID_SP), - frame2->context_validity); - EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM_REG_PC]); - EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_LR]); - EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM_REG_SP]); - EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]); -} - -TEST_F(GetFramesByFramePointer, FramePointerAndCFI) { - // Provide the standatd STACK CFI records that is obtained when exmining an - // executable produced by XCode. - SetModuleSymbols(&module1, - // Adding a function in CFI. - "FUNC 4000 1000 10 enchiridion\n" - - "STACK CFI INIT 4000 100 .cfa: sp 0 + .ra: lr\n" - "STACK CFI 4001 .cfa: sp 8 + .ra: .cfa -4 + ^" - " r7: .cfa -8 + ^\n" - "STACK CFI 4002 .cfa: r7 8 +\n" - ); - - stack_section.start() = 0x80000000; - uint32_t return_address1 = 0x40004010; - uint32_t return_address2 = 0x50000900; - Label frame1_sp, frame2_sp; - Label frame1_fp, frame2_fp; - stack_section - // frame 0 - .Append(32, 0) // Whatever values on the stack. - .D32(0x0000000D) // junk that's not - .D32(0xF0000000) // a return address. - - .Mark(&frame1_fp) // Next fp will point to the next value. - .D32(frame2_fp) // Save current frame pointer. - .D32(return_address2) // Save current link register. - .Mark(&frame1_sp) - - // frame 1 - .Append(32, 0) // Whatever values on the stack. - .D32(0x0000000D) // junk that's not - .D32(0xF0000000) // a return address. - - .Mark(&frame2_fp) - .D32(0) - .D32(0) - .Mark(&frame2_sp) - - // frame 2 - .Append(32, 0) // Whatever values on the stack. - .D32(0x0000000D) // junk that's not - .D32(0xF0000000); // a return address. - RegionFromSection(); - - - raw_context.iregs[MD_CONTEXT_ARM_REG_PC] = 0x50000400; - raw_context.iregs[MD_CONTEXT_ARM_REG_LR] = return_address1; - raw_context.iregs[MD_CONTEXT_ARM_REG_IOS_FP] = frame1_fp.Value(); - raw_context.iregs[MD_CONTEXT_ARM_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerARM walker(&system_info, &raw_context, MD_CONTEXT_ARM_REG_IOS_FP, - &stack_region, &modules, &frame_symbolizer); - - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module2", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(3U, frames->size()); - - StackFrameARM *frame0 = static_cast<StackFrameARM *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameARM::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameARM *frame1 = static_cast<StackFrameARM *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); - ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_LR | - StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) | - StackFrameARM::CONTEXT_VALID_SP), - frame1->context_validity); - EXPECT_EQ(return_address1, frame1->context.iregs[MD_CONTEXT_ARM_REG_PC]); - EXPECT_EQ(return_address2, frame1->context.iregs[MD_CONTEXT_ARM_REG_LR]); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_ARM_REG_SP]); - EXPECT_EQ(frame2_fp.Value(), - frame1->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]); - EXPECT_EQ("enchiridion", frame1->function_name); - EXPECT_EQ(0x40004000U, frame1->function_base); - - - StackFrameARM *frame2 = static_cast<StackFrameARM *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); - ASSERT_EQ((StackFrameARM::CONTEXT_VALID_PC | - StackFrameARM::CONTEXT_VALID_LR | - StackFrameARM::RegisterValidFlag(MD_CONTEXT_ARM_REG_IOS_FP) | - StackFrameARM::CONTEXT_VALID_SP), - frame2->context_validity); - EXPECT_EQ(return_address2, frame2->context.iregs[MD_CONTEXT_ARM_REG_PC]); - EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_LR]); - EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_ARM_REG_SP]); - EXPECT_EQ(0U, frame2->context.iregs[MD_CONTEXT_ARM_REG_IOS_FP]); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.cc deleted file mode 100644 index db55d460c..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.cc +++ /dev/null @@ -1,448 +0,0 @@ -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_mips.cc: MIPS-specific stackwalker. -// -// See stackwalker_mips.h for documentation. -// -// Author: Tata Elxsi - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_modules.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/cfi_frame_info.h" -#include "processor/logging.h" -#include "processor/postfix_evaluator-inl.h" -#include "processor/stackwalker_mips.h" -#include "processor/windows_frame_info.h" -#include "google_breakpad/common/minidump_cpu_mips.h" - -namespace google_breakpad { - -StackwalkerMIPS::StackwalkerMIPS(const SystemInfo* system_info, - const MDRawContextMIPS* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* resolver_helper) -: Stackwalker(system_info, memory, modules, resolver_helper), - context_(context) { - if (context_->context_flags & MD_CONTEXT_MIPS64 ) { - if ((memory_ && memory_->GetBase() + memory_->GetSize() - 1) - > 0xffffffffffffffff) { - BPLOG(ERROR) << "Memory out of range for stackwalking mips64: " - << HexString(memory_->GetBase()) - << "+" - << HexString(memory_->GetSize()); - memory_ = NULL; - } - } else { - if ((memory_ && memory_->GetBase() + memory_->GetSize() - 1) > 0xffffffff) { - BPLOG(ERROR) << "Memory out of range for stackwalking mips32: " - << HexString(memory_->GetBase()) - << "+" - << HexString(memory_->GetSize()); - memory_ = NULL; - } - } -} - -StackFrame* StackwalkerMIPS::GetContextFrame() { - if (!context_) { - BPLOG(ERROR) << "Can't get context frame without context."; - return NULL; - } - - StackFrameMIPS* frame = new StackFrameMIPS(); - - // The instruction pointer is stored directly in a register, so pull it - // straight out of the CPU context structure. - frame->context = *context_; - frame->context_validity = StackFrameMIPS::CONTEXT_VALID_ALL; - frame->trust = StackFrame::FRAME_TRUST_CONTEXT; - frame->instruction = frame->context.epc; - - return frame; -} - -// Register names for mips. -static const char* const kRegisterNames[] = { - "$zero", "$at", "$v0", "$v1", "$a0", "$a1", "$a2", "$a3", "$to", "$t1", - "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$s0", "$s1", "$s2", "$s3", - "$s4", "$s5", "$s6", "$s7", "$t8", "$t9", "$k0", "$k1", "$gp", "$sp", - "$fp", "$ra", NULL - // TODO(gordanac): add float point save registers -}; - -StackFrameMIPS* StackwalkerMIPS::GetCallerByCFIFrameInfo( - const vector<StackFrame*>& frames, - CFIFrameInfo* cfi_frame_info) { - StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back()); - - if (context_->context_flags & MD_CONTEXT_MIPS) { - uint32_t sp = 0, pc = 0; - - // Populate a dictionary with the valid register values in last_frame. - CFIFrameInfo::RegisterValueMap<uint32_t> callee_registers; - // Use the STACK CFI data to recover the caller's register values. - CFIFrameInfo::RegisterValueMap<uint32_t> caller_registers; - - for (int i = 0; kRegisterNames[i]; ++i) { - caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i]; - callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i]; - } - - if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, - &caller_registers)) { - return NULL; - } - - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator entry = - caller_registers.find(".cfa"); - - if (entry != caller_registers.end()) { - sp = entry->second; - caller_registers["$sp"] = entry->second; - } - - entry = caller_registers.find(".ra"); - if (entry != caller_registers.end()) { - caller_registers["$ra"] = entry->second; - pc = entry->second - 2 * sizeof(pc); - } - caller_registers["$pc"] = pc; - // Construct a new stack frame given the values the CFI recovered. - scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS()); - - for (int i = 0; kRegisterNames[i]; ++i) { - CFIFrameInfo::RegisterValueMap<uint32_t>::const_iterator caller_entry = - caller_registers.find(kRegisterNames[i]); - - if (caller_entry != caller_registers.end()) { - // The value of this register is recovered; fill the context with the - // value from caller_registers. - frame->context.iregs[i] = caller_entry->second; - frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i); - } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) || - (i > INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) && - (last_frame->context_validity & - StackFrameMIPS::RegisterValidFlag(i))) { - // If the STACK CFI data doesn't mention some callee-save register, and - // it is valid in the callee, assume the callee has not yet changed it. - // Calee-save registers according to the MIPS o32 ABI specification are: - // $s0 to $s7 - // $sp, $s8 - frame->context.iregs[i] = last_frame->context.iregs[i]; - frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i); - } - } - - frame->context.epc = caller_registers["$pc"]; - frame->instruction = caller_registers["$pc"]; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC; - - frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"]; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA; - - frame->trust = StackFrame::FRAME_TRUST_CFI; - - return frame.release(); - } else { - uint64_t sp = 0, pc = 0; - - // Populate a dictionary with the valid register values in last_frame. - CFIFrameInfo::RegisterValueMap<uint64_t> callee_registers; - // Use the STACK CFI data to recover the caller's register values. - CFIFrameInfo::RegisterValueMap<uint64_t> caller_registers; - - for (int i = 0; kRegisterNames[i]; ++i) { - caller_registers[kRegisterNames[i]] = last_frame->context.iregs[i]; - callee_registers[kRegisterNames[i]] = last_frame->context.iregs[i]; - } - - if (!cfi_frame_info->FindCallerRegs(callee_registers, *memory_, - &caller_registers)) { - return NULL; - } - - CFIFrameInfo::RegisterValueMap<uint64_t>::const_iterator entry = - caller_registers.find(".cfa"); - - if (entry != caller_registers.end()) { - sp = entry->second; - caller_registers["$sp"] = entry->second; - } - - entry = caller_registers.find(".ra"); - if (entry != caller_registers.end()) { - caller_registers["$ra"] = entry->second; - pc = entry->second - 2 * sizeof(pc); - } - caller_registers["$pc"] = pc; - // Construct a new stack frame given the values the CFI recovered. - scoped_ptr<StackFrameMIPS> frame(new StackFrameMIPS()); - - for (int i = 0; kRegisterNames[i]; ++i) { - CFIFrameInfo::RegisterValueMap<uint64_t>::const_iterator caller_entry = - caller_registers.find(kRegisterNames[i]); - - if (caller_entry != caller_registers.end()) { - // The value of this register is recovered; fill the context with the - // value from caller_registers. - frame->context.iregs[i] = caller_entry->second; - frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i); - } else if (((i >= INDEX_MIPS_REG_S0 && i <= INDEX_MIPS_REG_S7) || - (i >= INDEX_MIPS_REG_GP && i < INDEX_MIPS_REG_RA)) && - (last_frame->context_validity & - StackFrameMIPS::RegisterValidFlag(i))) { - // If the STACK CFI data doesn't mention some callee-save register, and - // it is valid in the callee, assume the callee has not yet changed it. - // Calee-save registers according to the MIPS o32 ABI specification are: - // $s0 to $s7 - // $sp, $s8 - frame->context.iregs[i] = last_frame->context.iregs[i]; - frame->context_validity |= StackFrameMIPS::RegisterValidFlag(i); - } - } - - frame->context.epc = caller_registers["$pc"]; - frame->instruction = caller_registers["$pc"]; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC; - - frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = caller_registers["$ra"]; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA; - - frame->trust = StackFrame::FRAME_TRUST_CFI; - - return frame.release(); - } -} - -StackFrame* StackwalkerMIPS::GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed) { - if (!memory_ || !stack) { - BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; - } - - const vector<StackFrame*>& frames = *stack->frames(); - StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back()); - scoped_ptr<StackFrameMIPS> new_frame; - - // See if there is DWARF call frame information covering this address. - scoped_ptr<CFIFrameInfo> cfi_frame_info( - frame_symbolizer_->FindCFIFrameInfo(last_frame)); - if (cfi_frame_info.get()) - new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info.get())); - - // If caller frame is not found in CFI try analyzing the stack. - if (stack_scan_allowed && !new_frame.get()) { - new_frame.reset(GetCallerByStackScan(frames)); - } - - // If nothing worked, tell the caller. - if (!new_frame.get()) { - return NULL; - } - - // Treat an instruction address of 0 as end-of-stack. - if (new_frame->context.epc == 0) { - return NULL; - } - - // If the new stack pointer is at a lower address than the old, then - // that's clearly incorrect. Treat this as end-of-stack to enforce - // progress and avoid infinite loops. - if (new_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] <= - last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP]) { - return NULL; - } - - return new_frame.release(); -} - -StackFrameMIPS* StackwalkerMIPS::GetCallerByStackScan( - const vector<StackFrame*>& frames) { - const uint32_t kMaxFrameStackSize = 1024; - const uint32_t kMinArgsOnStack = 4; - - StackFrameMIPS* last_frame = static_cast<StackFrameMIPS*>(frames.back()); - - if (context_->context_flags & MD_CONTEXT_MIPS) { - uint32_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP]; - uint32_t caller_pc, caller_sp, caller_fp; - - // Return address cannot be obtained directly. - // Force stackwalking. - - // We cannot use frame pointer to get the return address. - // We'll scan the stack for a - // return address. This can happen if last_frame is executing code - // for a module for which we don't have symbols. - int count = kMaxFrameStackSize / sizeof(caller_pc); - - if (frames.size() > 1) { - // In case of mips32 ABI stack frame of a nonleaf function - // must have minimum stack frame assigned for 4 arguments (4 words). - // Move stack pointer for 4 words to avoid reporting non-existing frames - // for all frames except the topmost one. - // There is no way of knowing if topmost frame belongs to a leaf or - // a nonleaf function. - last_sp += kMinArgsOnStack * sizeof(caller_pc); - // Adjust 'count' so that return address is scanned only in limits - // of one stack frame. - count -= kMinArgsOnStack; - } - - do { - // Scanning for return address from stack pointer of the last frame. - if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) { - // If we can't find an instruction pointer even with stack scanning, - // give up. - BPLOG(ERROR) << " ScanForReturnAddress failed "; - return NULL; - } - // Get $fp stored in the stack frame. - if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc), - &caller_fp)) { - BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ; - return NULL; - } - - count = count - (caller_sp - last_sp) / sizeof(caller_pc); - // Now scan the next address in the stack. - last_sp = caller_sp + sizeof(caller_pc); - } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0); - - if (!count) { - BPLOG(INFO) << " No frame found " ; - return NULL; - } - - // ScanForReturnAddress found a reasonable return address. Advance - // $sp to the location above the one where the return address was - // found. - caller_sp += sizeof(caller_pc); - // caller_pc is actually containing $ra value; - // $pc is two instructions before $ra, - // so the caller_pc needs to be decremented accordingly. - caller_pc -= 2 * sizeof(caller_pc); - - // Create a new stack frame (ownership will be transferred to the caller) - // and fill it in. - StackFrameMIPS* frame = new StackFrameMIPS(); - frame->trust = StackFrame::FRAME_TRUST_SCAN; - frame->context = last_frame->context; - frame->context.epc = caller_pc; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC; - frame->instruction = caller_pc; - - frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP; - frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP; - - frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = - caller_pc + 2 * sizeof(caller_pc); - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA; - - return frame; - } else { - uint64_t last_sp = last_frame->context.iregs[MD_CONTEXT_MIPS_REG_SP]; - uint64_t caller_pc, caller_sp, caller_fp; - - // Return address cannot be obtained directly. - // Force stackwalking. - - // We cannot use frame pointer to get the return address. - // We'll scan the stack for a - // return address. This can happen if last_frame is executing code - // for a module for which we don't have symbols. - int count = kMaxFrameStackSize / sizeof(caller_pc); - - do { - // Scanning for return address from stack pointer of the last frame. - if (!ScanForReturnAddress(last_sp, &caller_sp, &caller_pc, count)) { - // If we can't find an instruction pointer even with stack scanning, - // give up. - BPLOG(ERROR) << " ScanForReturnAddress failed "; - return NULL; - } - // Get $fp stored in the stack frame. - if (!memory_->GetMemoryAtAddress(caller_sp - sizeof(caller_pc), - &caller_fp)) { - BPLOG(INFO) << " GetMemoryAtAddress for fp failed " ; - return NULL; - } - - count = count - (caller_sp - last_sp) / sizeof(caller_pc); - // Now scan the next address in the stack. - last_sp = caller_sp + sizeof(caller_pc); - } while ((caller_fp - caller_sp >= kMaxFrameStackSize) && count > 0); - - if (!count) { - BPLOG(INFO) << " No frame found " ; - return NULL; - } - - // ScanForReturnAddress found a reasonable return address. Advance - // $sp to the location above the one where the return address was - // found. - caller_sp += sizeof(caller_pc); - // caller_pc is actually containing $ra value; - // $pc is two instructions before $ra, - // so the caller_pc needs to be decremented accordingly. - caller_pc -= 2 * sizeof(caller_pc); - - // Create a new stack frame (ownership will be transferred to the caller) - // and fill it in. - StackFrameMIPS* frame = new StackFrameMIPS(); - frame->trust = StackFrame::FRAME_TRUST_SCAN; - frame->context = last_frame->context; - frame->context.epc = caller_pc; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_PC; - frame->instruction = caller_pc; - - frame->context.iregs[MD_CONTEXT_MIPS_REG_SP] = caller_sp; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_SP; - frame->context.iregs[MD_CONTEXT_MIPS_REG_FP] = caller_fp; - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_FP; - - frame->context.iregs[MD_CONTEXT_MIPS_REG_RA] = - caller_pc + 2 * sizeof(caller_pc); - frame->context_validity |= StackFrameMIPS::CONTEXT_VALID_RA; - - return frame; - } -} - -} // namespace google_breakpad - diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.h deleted file mode 100644 index 5f97791fb..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips.h +++ /dev/null @@ -1,85 +0,0 @@ -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_mips.h: MIPS-specific stackwalker. -// -// Provides stack frames given MIPS register context and a memory region -// corresponding to a MIPSstack. -// -// Author: Tata Elxsi - -#ifndef PROCESSOR_STACKWALKER_MIPS_H__ -#define PROCESSOR_STACKWALKER_MIPS_H__ - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/stackwalker.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/cfi_frame_info.h" - -namespace google_breakpad { - -class CodeModules; - -class StackwalkerMIPS : public Stackwalker { - public: - // Context is a MIPS context object that gives access to mips-specific - // register state corresponding to the innermost called frame to be - // included in the stack. The other arguments are passed directly - // through to the base Stackwalker constructor. - StackwalkerMIPS(const SystemInfo* system_info, - const MDRawContextMIPS* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer); - - private: - // Implementation of Stackwalker, using mips context and stack conventions. - virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed); - - // Use cfi_frame_info (derived from STACK CFI records) to construct - // the frame that called frames.back(). The caller takes ownership - // of the returned frame. Return NULL on failure. - StackFrameMIPS* GetCallerByCFIFrameInfo(const vector<StackFrame*>& frames, - CFIFrameInfo* cfi_frame_info); - - // Scan the stack for plausible return address and frame pointer pair. - // The caller takes ownership of the returned frame. Return NULL on failure. - StackFrameMIPS* GetCallerByStackScan(const vector<StackFrame*>& frames); - - // Stores the CPU context corresponding to the innermost stack frame to - // be returned by GetContextFrame. - const MDRawContextMIPS* context_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_STACKWALKER_MIPS_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips_unittest.cc deleted file mode 100644 index 5398c2b33..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_mips_unittest.cc +++ /dev/null @@ -1,707 +0,0 @@ -// Copyright (c) 2013, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Gordana Cmiljanovic <gordana.cmiljanovic@imgtec.com> - -// stackwalker_mips_unittest.cc: Unit tests for StackwalkerMIPS class. - -#include <string.h> -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/test_assembler.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/stackwalker_unittest_utils.h" -#include "processor/stackwalker_mips.h" -#include "processor/windows_frame_info.h" - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::CallStack; -using google_breakpad::CodeModule; -using google_breakpad::StackFrameSymbolizer; -using google_breakpad::StackFrame; -using google_breakpad::StackFrameMIPS; -using google_breakpad::Stackwalker; -using google_breakpad::StackwalkerMIPS; -using google_breakpad::SystemInfo; -using google_breakpad::WindowsFrameInfo; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Label; -using google_breakpad::test_assembler::Section; -using std::vector; -using testing::_; -using testing::AnyNumber; -using testing::Return; -using testing::SetArgumentPointee; -using testing::Test; - -class StackwalkerMIPSFixture { - public: - StackwalkerMIPSFixture() - : stack_section(kLittleEndian), - // Give the two modules reasonable standard locations and names - // for tests to play with. - module1(0x00400000, 0x10000, "module1", "version1"), - module2(0x00500000, 0x10000, "module2", "version2") { - // Identify the system as a Linux system. - system_info.os = "Linux"; - system_info.os_short = "linux"; - system_info.os_version = "Observant Opossum"; // Jealous Jellyfish - system_info.cpu = "mips"; - system_info.cpu_info = ""; - - // Put distinctive values in the raw CPU context. - BrandContext(&raw_context); - - // Create some modules with some stock debugging information. - modules.Add(&module1); - modules.Add(&module2); - - // By default, none of the modules have symbol info; call - // SetModuleSymbols to override this. - EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _)) - .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); - - // Avoid GMOCK WARNING "Uninteresting mock function call - returning - // directly" for FreeSymbolData(). - EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); - - // Reset max_frames_scanned since it's static. - Stackwalker::set_max_frames_scanned(1024); - } - - // Set the Breakpad symbol information that supplier should return for - // MODULE to INFO. - void SetModuleSymbols(MockCodeModule* module, const string& info) { - size_t buffer_size; - char* buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size); - EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _)) - .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), - SetArgumentPointee<4>(buffer_size), - Return(MockSymbolSupplier::FOUND))); - } - - // Populate stack_region with the contents of stack_section. Use - // stack_section.start() as the region's starting address. - void RegionFromSection() { - string contents; - ASSERT_TRUE(stack_section.GetContents(&contents)); - stack_region.Init(stack_section.start().Value(), contents); - } - - // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking. - void BrandContext(MDRawContextMIPS* raw_context) { - uint8_t x = 173; - for (size_t i = 0; i < sizeof(*raw_context); ++i) - reinterpret_cast<uint8_t*>(raw_context)[i] = (x += 17); - } - - SystemInfo system_info; - MDRawContextMIPS raw_context; - Section stack_section; - MockMemoryRegion stack_region; - MockCodeModule module1; - MockCodeModule module2; - MockCodeModules modules; - MockSymbolSupplier supplier; - BasicSourceLineResolver resolver; - CallStack call_stack; - const vector<StackFrame*>* frames; -}; - -class SanityCheck: public StackwalkerMIPSFixture, public Test { }; - -TEST_F(SanityCheck, NoResolver) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - stack_section.start() = 0x80000000; - stack_section.D32(0).D32(0x0); - RegionFromSection(); - raw_context.epc = 0x00400020; - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; - - StackFrameSymbolizer frame_symbolizer(NULL, NULL); - StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - // This should succeed, even without a resolver or supplier. - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -class GetContextFrame: public StackwalkerMIPSFixture, public Test { }; - -TEST_F(GetContextFrame, Simple) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - stack_section.start() = 0x80000000; - stack_section.D32(0).D32(0x0); - RegionFromSection(); - raw_context.epc = 0x00400020; - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -// The stackwalker should be able to produce the context frame even -// without stack memory present. -TEST_F(GetContextFrame, NoStackMemory) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - raw_context.epc = 0x00400020; - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, NULL, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - StackFrameMIPS* frame = static_cast<StackFrameMIPS*>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -class GetCallerFrame: public StackwalkerMIPSFixture, public Test { }; - -TEST_F(GetCallerFrame, ScanWithoutSymbols) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - // When the stack walker resorts to scanning the stack, - // only addresses located within loaded modules are - // considered valid return addresses. - // Force scanning through three frames to ensure that the - // stack pointer is set properly in scan-recovered frames. - stack_section.start() = 0x80000000; - uint32_t return_address1 = 0x00400100; - uint32_t return_address2 = 0x00400900; - Label frame1_sp, frame2_sp; - stack_section - // frame 0 - .Append(16, 0) // space - - .D32(0x00490000) // junk that's not - .D32(0x00600000) // a return address - - .D32(frame1_sp) // stack pointer - .D32(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(16, 0) // space - - .D32(0xF0000000) // more junk - .D32(0x0000000D) - - .D32(frame2_sp) // stack pointer - .D32(return_address2) // actual return address - // frame 2 - .Mark(&frame2_sp) - .Append(32, 0); // end of stack - RegionFromSection(); - - raw_context.epc = 0x00405510; - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); - raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(3U, frames->size()); - - StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC | - StackFrameMIPS::CONTEXT_VALID_SP | - StackFrameMIPS::CONTEXT_VALID_FP | - StackFrameMIPS::CONTEXT_VALID_RA), - frame1->context_validity); - EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); - - StackFrameMIPS* frame2 = static_cast<StackFrameMIPS*>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame2->trust); - ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC | - StackFrameMIPS::CONTEXT_VALID_SP | - StackFrameMIPS::CONTEXT_VALID_FP | - StackFrameMIPS::CONTEXT_VALID_RA), - frame2->context_validity); - EXPECT_EQ(return_address2 - 2 * sizeof(return_address2), frame2->context.epc); - EXPECT_EQ(frame2_sp.Value(), frame2->context.iregs[MD_CONTEXT_MIPS_REG_SP]); -} - -TEST_F(GetCallerFrame, ScanWithFunctionSymbols) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - // During stack scanning, if a potential return address - // is located within a loaded module that has symbols, - // it is only considered a valid return address if it - // lies within a function's bounds. - stack_section.start() = 0x80000000; - uint32_t return_address = 0x00500200; - Label frame1_sp; - stack_section - // frame 0 - .Append(16, 0) // space - - .D32(0x00490000) // junk that's not - .D32(0x00600000) // a return address - - .D32(0x00401000) // a couple of plausible addresses - .D32(0x0050F000) // that are not within functions - - .D32(frame1_sp) // stack pointer - .D32(return_address) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(32, 0); // end of stack - RegionFromSection(); - - raw_context.epc = 0x00400200; - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); - raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address; - - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 100 400 10 monotreme\n"); - SetModuleSymbols(&module2, - // The calling frame's function. - "FUNC 100 400 10 marsupial\n"); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - EXPECT_EQ("monotreme", frame0->function_name); - EXPECT_EQ(0x00400100U, frame0->function_base); - - StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC | - StackFrameMIPS::CONTEXT_VALID_SP | - StackFrameMIPS::CONTEXT_VALID_FP | - StackFrameMIPS::CONTEXT_VALID_RA), - frame1->context_validity); - EXPECT_EQ(return_address - 2 * sizeof(return_address), frame1->context.epc); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); - EXPECT_EQ("marsupial", frame1->function_name); - EXPECT_EQ(0x00500100U, frame1->function_base); -} - -TEST_F(GetCallerFrame, CheckStackFrameSizeLimit) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - // If the stackwalker resorts to stack scanning, it will scan only - // 1024 bytes of stack which correspondes to maximum size of stack frame. - stack_section.start() = 0x80000000; - uint32_t return_address1 = 0x00500100; - uint32_t return_address2 = 0x00500900; - Label frame1_sp, frame2_sp; - stack_section - // frame 0 - .Append(32, 0) // space - - .D32(0x00490000) // junk that's not - .D32(0x00600000) // a return address - - .Append(96, 0) // more space - - .D32(frame1_sp) // stack pointer - .D32(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(128 * 4, 0) // space - - .D32(0x00F00000) // more junk - .D32(0x0000000D) - - .Append(128 * 4, 0) // more space - - .D32(frame2_sp) // stack pointer - .D32(return_address2) // actual return address - // (won't be found) - // frame 2 - .Mark(&frame2_sp) - .Append(32, 0); // end of stack - RegionFromSection(); - - raw_context.epc = 0x00405510; - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); - raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(2U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ("module2", modules_without_symbols[1]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); - - StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameMIPS::CONTEXT_VALID_PC | - StackFrameMIPS::CONTEXT_VALID_SP | - StackFrameMIPS::CONTEXT_VALID_FP | - StackFrameMIPS::CONTEXT_VALID_RA), - frame1->context_validity); - EXPECT_EQ(return_address1 - 2 * sizeof(return_address1), frame1->context.epc); - EXPECT_EQ(frame1_sp.Value(), frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); -} - -// Test that set_max_frames_scanned prevents using stack scanning -// to find caller frames. -TEST_F(GetCallerFrame, ScanningNotAllowed) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - // When the stack walker resorts to scanning the stack, - // only fixed number of frames are allowed to be scanned out from stack - stack_section.start() = 0x80000000; - uint32_t return_address1 = 0x00500100; - uint32_t return_address2 = 0x00500900; - Label frame1_sp, frame2_sp; - stack_section - // frame 0 - .Append(32, 0) // space - - .D32(0x00490000) // junk that's not - .D32(0x00600000) // a return address - - .Append(96, 0) // more space - - .D32(frame1_sp) // stack pointer - .D32(return_address1) // actual return address - // frame 1 - .Mark(&frame1_sp) - .Append(128 * 4, 0) // space - - .D32(0x00F00000) // more junk - .D32(0x0000000D) - - .Append(128 * 4, 0) // more space - - .D32(frame2_sp) // stack pointer - .D32(return_address2) // actual return address - // (won't be found) - // frame 2 - .Mark(&frame2_sp) - .Append(32, 0); // end of stack - RegionFromSection(); - - raw_context.epc = 0x00405510; - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); - raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = return_address1; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - Stackwalker::set_max_frames_scanned(0); - - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - - StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0, memcmp(&raw_context, &frame0->context, sizeof(raw_context))); -} - -struct CFIFixture: public StackwalkerMIPSFixture { - CFIFixture() { - // Provide some STACK CFI records; - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 4000 1000 0 enchiridion\n" - // Initially, nothing has been pushed on the stack, - // and the return address is still in the $ra register. - "STACK CFI INIT 4000 1000 .cfa: $sp 0 + .ra: $ra\n" - // Move stack pointer. - "STACK CFI 4004 .cfa: $sp 32 +\n" - // store $fp and ra - "STACK CFI 4008 $fp: .cfa -8 + ^ .ra: .cfa -4 + ^\n" - // restore $fp - "STACK CFI 400c .cfa: $fp 32 +\n" - // restore $sp - "STACK CFI 4018 .cfa: $sp 32 +\n" - - "STACK CFI 4020 $fp: $fp .cfa: $sp 0 + .ra: .ra\n" - - // The calling function. - "FUNC 5000 1000 0 epictetus\n" - // Initially, nothing has been pushed on the stack, - // and the return address is still in the $ra register. - "STACK CFI INIT 5000 1000 .cfa: $sp .ra: $ra\n" - // Mark it as end of stack. - "STACK CFI INIT 5000 8 .cfa: $sp 0 + .ra: $ra\n" - - // A function whose CFI makes the stack pointer - // go backwards. - "FUNC 6000 1000 20 palinal\n" - "STACK CFI INIT 6000 1000 .cfa: $sp 4 - .ra: $ra\n" - - // A function with CFI expressions that can't be - // evaluated. - "FUNC 7000 1000 20 rhetorical\n" - "STACK CFI INIT 7000 1000 .cfa: moot .ra: ambiguous\n" - ); - - // Provide some distinctive values for the caller's registers. - expected.epc = 0x00405508; - expected.iregs[MD_CONTEXT_MIPS_REG_S0] = 0x0; - expected.iregs[MD_CONTEXT_MIPS_REG_S1] = 0x1; - expected.iregs[MD_CONTEXT_MIPS_REG_S2] = 0x2; - expected.iregs[MD_CONTEXT_MIPS_REG_S3] = 0x3; - expected.iregs[MD_CONTEXT_MIPS_REG_S4] = 0x4; - expected.iregs[MD_CONTEXT_MIPS_REG_S5] = 0x5; - expected.iregs[MD_CONTEXT_MIPS_REG_S6] = 0x6; - expected.iregs[MD_CONTEXT_MIPS_REG_S7] = 0x7; - expected.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; - expected.iregs[MD_CONTEXT_MIPS_REG_FP] = 0x80000000; - expected.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510; - - // Expect CFI to recover all callee-save registers. Since CFI is the - // only stack frame construction technique we have, aside from the - // context frame itself, there's no way for us to have a set of valid - // registers smaller than this. - expected_validity = (StackFrameMIPS::CONTEXT_VALID_PC | - StackFrameMIPS::CONTEXT_VALID_S0 | - StackFrameMIPS::CONTEXT_VALID_S1 | - StackFrameMIPS::CONTEXT_VALID_S2 | - StackFrameMIPS::CONTEXT_VALID_S3 | - StackFrameMIPS::CONTEXT_VALID_S4 | - StackFrameMIPS::CONTEXT_VALID_S5 | - StackFrameMIPS::CONTEXT_VALID_S6 | - StackFrameMIPS::CONTEXT_VALID_S7 | - StackFrameMIPS::CONTEXT_VALID_SP | - StackFrameMIPS::CONTEXT_VALID_FP | - StackFrameMIPS::CONTEXT_VALID_RA); - - // By default, context frames provide all registers, as normal. - context_frame_validity = StackFrameMIPS::CONTEXT_VALID_ALL; - - // By default, registers are unchanged. - raw_context = expected; - } - - // Walk the stack, using stack_section as the contents of the stack - // and raw_context as the current register values. (Set the stack - // pointer to the stack's starting address.) Expect two stack - // frames; in the older frame, expect the callee-saves registers to - // have values matching those in 'expected'. - void CheckWalk() { - RegionFromSection(); - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, - &modules, &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - StackFrameMIPS* frame0 = static_cast<StackFrameMIPS*>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameMIPS::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ("enchiridion", frame0->function_name); - EXPECT_EQ(0x00404000U, frame0->function_base); - - StackFrameMIPS* frame1 = static_cast<StackFrameMIPS*>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ(expected_validity, frame1->context_validity); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S0], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_S0]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S1], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_S1]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S2], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_S2]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S3], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_S3]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S4], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_S4]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S5], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_S5]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S6], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_S6]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_S7], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_S7]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_FP], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_FP]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_RA], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_RA]); - EXPECT_EQ(expected.iregs[MD_CONTEXT_MIPS_REG_SP], - frame1->context.iregs[MD_CONTEXT_MIPS_REG_SP]); - EXPECT_EQ(expected.epc, frame1->context.epc); - EXPECT_EQ(expected.epc, frame1->instruction); - EXPECT_EQ("epictetus", frame1->function_name); - EXPECT_EQ(0x00405000U, frame1->function_base); - } - - // The values we expect to find for the caller's registers. - MDRawContextMIPS expected; - - // The validity mask for expected. - int expected_validity; - - // The validity mask to impose on the context frame. - int context_frame_validity; -}; - -class CFI: public CFIFixture, public Test { }; - -// TODO(gordanac): add CFI tests - -TEST_F(CFI, At4004) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - Label frame1_sp = expected.iregs[MD_CONTEXT_MIPS_REG_SP]; - stack_section - // frame0 - .Append(24, 0) // space - .D32(frame1_sp) // stack pointer - .D32(0x00405510) // return address - .Mark(&frame1_sp); // This effectively sets stack_section.start(). - raw_context.epc = 0x00404004; - CheckWalk(); -} - -// Check that we reject rules that would cause the stack pointer to -// move in the wrong direction. -TEST_F(CFI, RejectBackwards) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - raw_context.epc = 0x40005000; - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; - raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); -} - -// Check that we reject rules whose expressions' evaluation fails. -TEST_F(CFI, RejectBadExpressions) { - raw_context.context_flags = raw_context.context_flags | MD_CONTEXT_MIPS_FULL; - raw_context.epc = 0x00407000; - raw_context.iregs[MD_CONTEXT_MIPS_REG_SP] = 0x80000000; - raw_context.iregs[MD_CONTEXT_MIPS_REG_RA] = 0x00405510; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerMIPS walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.cc deleted file mode 100644 index 7e2088440..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.cc +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_ppc.cc: ppc-specific stackwalker. -// -// See stackwalker_ppc.h for documentation. -// -// Author: Mark Mentovai - - -#include "processor/stackwalker_ppc.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/logging.h" - -namespace google_breakpad { - - -StackwalkerPPC::StackwalkerPPC(const SystemInfo* system_info, - const MDRawContextPPC* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* resolver_helper) - : Stackwalker(system_info, memory, modules, resolver_helper), - context_(context) { - if (memory_ && memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { - // This implementation only covers 32-bit ppc CPUs. The limits of the - // supplied stack are invalid. Mark memory_ = NULL, which will cause - // stackwalking to fail. - BPLOG(ERROR) << "Memory out of range for stackwalking: " << - HexString(memory_->GetBase()) << "+" << - HexString(memory_->GetSize()); - memory_ = NULL; - } -} - - -StackFrame* StackwalkerPPC::GetContextFrame() { - if (!context_) { - BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; - } - - StackFramePPC* frame = new StackFramePPC(); - - // The instruction pointer is stored directly in a register, so pull it - // straight out of the CPU context structure. - frame->context = *context_; - frame->context_validity = StackFramePPC::CONTEXT_VALID_ALL; - frame->trust = StackFrame::FRAME_TRUST_CONTEXT; - frame->instruction = frame->context.srr0; - - return frame; -} - - -StackFrame* StackwalkerPPC::GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed) { - if (!memory_ || !stack) { - BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; - } - - // The instruction pointers for previous frames are saved on the stack. - // The typical ppc calling convention is for the called procedure to store - // its return address in the calling procedure's stack frame at 8(%r1), - // and to allocate its own stack frame by decrementing %r1 (the stack - // pointer) and saving the old value of %r1 at 0(%r1). Because the ppc has - // no hardware stack, there is no distinction between the stack pointer and - // frame pointer, and what is typically thought of as the frame pointer on - // an x86 is usually referred to as the stack pointer on a ppc. - - StackFramePPC* last_frame = static_cast<StackFramePPC*>( - stack->frames()->back()); - - // A caller frame must reside higher in memory than its callee frames. - // Anything else is an error, or an indication that we've reached the - // end of the stack. - uint32_t stack_pointer; - if (!memory_->GetMemoryAtAddress(last_frame->context.gpr[1], - &stack_pointer) || - stack_pointer <= last_frame->context.gpr[1]) { - return NULL; - } - - // Mac OS X/Darwin gives 1 as the return address from the bottom-most - // frame in a stack (a thread's entry point). I haven't found any - // documentation on this, but 0 or 1 would be bogus return addresses, - // so check for them here and return false (end of stack) when they're - // hit to avoid having a phantom frame. - uint32_t instruction; - if (!memory_->GetMemoryAtAddress(stack_pointer + 8, &instruction) || - instruction <= 1) { - return NULL; - } - - StackFramePPC* frame = new StackFramePPC(); - - frame->context = last_frame->context; - frame->context.srr0 = instruction; - frame->context.gpr[1] = stack_pointer; - frame->context_validity = StackFramePPC::CONTEXT_VALID_SRR0 | - StackFramePPC::CONTEXT_VALID_GPR1; - frame->trust = StackFrame::FRAME_TRUST_FP; - - // frame->context.srr0 is the return address, which is one instruction - // past the branch that caused us to arrive at the callee. Set - // frame_ppc->instruction to four less than that. Since all ppc - // instructions are 4 bytes wide, this is the address of the branch - // instruction. This allows source line information to match up with the - // line that contains a function call. Callers that require the exact - // return address value may access the context.srr0 field of StackFramePPC. - frame->instruction = frame->context.srr0 - 4; - - return frame; -} - - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.h deleted file mode 100644 index 012e5c32f..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc.h +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_ppc.h: ppc-specific stackwalker. -// -// Provides stack frames given ppc register context and a memory region -// corresponding to a ppc stack. -// -// Author: Mark Mentovai - - -#ifndef PROCESSOR_STACKWALKER_PPC_H__ -#define PROCESSOR_STACKWALKER_PPC_H__ - - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/stackwalker.h" - -namespace google_breakpad { - -class CodeModules; - -class StackwalkerPPC : public Stackwalker { - public: - // context is a ppc context object that gives access to ppc-specific - // register state corresponding to the innermost called frame to be - // included in the stack. The other arguments are passed directly through - // to the base Stackwalker constructor. - StackwalkerPPC(const SystemInfo* system_info, - const MDRawContextPPC* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer); - - private: - // Implementation of Stackwalker, using ppc context (stack pointer in %r1, - // saved program counter in %srr0) and stack conventions (saved stack - // pointer at 0(%r1), return address at 8(0(%r1)). - virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed); - - // Stores the CPU context corresponding to the innermost stack frame to - // be returned by GetContextFrame. - const MDRawContextPPC* context_; -}; - - -} // namespace google_breakpad - - -#endif // PROCESSOR_STACKWALKER_PPC_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.cc deleted file mode 100644 index 51c71fe56..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.cc +++ /dev/null @@ -1,137 +0,0 @@ -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_ppc64.cc: ppc64-specific stackwalker. -// -// See stackwalker_ppc64.h for documentation. - - -#include "processor/stackwalker_ppc64.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/logging.h" - -#include <stdio.h> - -namespace google_breakpad { - - -StackwalkerPPC64::StackwalkerPPC64(const SystemInfo* system_info, - const MDRawContextPPC64* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* resolver_helper) - : Stackwalker(system_info, memory, modules, resolver_helper), - context_(context) { -} - - -StackFrame* StackwalkerPPC64::GetContextFrame() { - if (!context_) { - BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; - } - - StackFramePPC64* frame = new StackFramePPC64(); - - // The instruction pointer is stored directly in a register, so pull it - // straight out of the CPU context structure. - frame->context = *context_; - frame->context_validity = StackFramePPC64::CONTEXT_VALID_ALL; - frame->trust = StackFrame::FRAME_TRUST_CONTEXT; - frame->instruction = frame->context.srr0; - - return frame; -} - - -StackFrame* StackwalkerPPC64::GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed) { - if (!memory_ || !stack) { - BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; - } - - // The instruction pointers for previous frames are saved on the stack. - // The typical ppc64 calling convention is for the called procedure to store - // its return address in the calling procedure's stack frame at 8(%r1), - // and to allocate its own stack frame by decrementing %r1 (the stack - // pointer) and saving the old value of %r1 at 0(%r1). Because the ppc64 has - // no hardware stack, there is no distinction between the stack pointer and - // frame pointer, and what is typically thought of as the frame pointer on - // an x86 is usually referred to as the stack pointer on a ppc64. - - StackFramePPC64* last_frame = static_cast<StackFramePPC64*>( - stack->frames()->back()); - - // A caller frame must reside higher in memory than its callee frames. - // Anything else is an error, or an indication that we've reached the - // end of the stack. - uint64_t stack_pointer; - if (!memory_->GetMemoryAtAddress(last_frame->context.gpr[1], - &stack_pointer) || - stack_pointer <= last_frame->context.gpr[1]) { - return NULL; - } - - // Mac OS X/Darwin gives 1 as the return address from the bottom-most - // frame in a stack (a thread's entry point). I haven't found any - // documentation on this, but 0 or 1 would be bogus return addresses, - // so check for them here and return false (end of stack) when they're - // hit to avoid having a phantom frame. - uint64_t instruction; - if (!memory_->GetMemoryAtAddress(stack_pointer + 16, &instruction) || - instruction <= 1) { - return NULL; - } - - StackFramePPC64* frame = new StackFramePPC64(); - - frame->context = last_frame->context; - frame->context.srr0 = instruction; - frame->context.gpr[1] = stack_pointer; - frame->context_validity = StackFramePPC64::CONTEXT_VALID_SRR0 | - StackFramePPC64::CONTEXT_VALID_GPR1; - frame->trust = StackFrame::FRAME_TRUST_FP; - - // frame->context.srr0 is the return address, which is one instruction - // past the branch that caused us to arrive at the callee. Set - // frame_ppc64->instruction to eight less than that. Since all ppc64 - // instructions are 8 bytes wide, this is the address of the branch - // instruction. This allows source line information to match up with the - // line that contains a function call. Callers that require the exact - // return address value may access the context.srr0 field of StackFramePPC64. - frame->instruction = frame->context.srr0 - 8; - - return frame; -} - - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.h deleted file mode 100644 index a406343af..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_ppc64.h +++ /dev/null @@ -1,77 +0,0 @@ -// Copyright (c) 2013 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_ppc64.h: ppc-specific stackwalker. -// -// Provides stack frames given ppc64 register context and a memory region -// corresponding to a ppc64 stack. - - -#ifndef PROCESSOR_STACKWALKER_PPC64_H__ -#define PROCESSOR_STACKWALKER_PPC64_H__ - - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/stackwalker.h" - -namespace google_breakpad { - -class CodeModules; - -class StackwalkerPPC64 : public Stackwalker { - public: - // context is a ppc64 context object that gives access to ppc64-specific - // register state corresponding to the innermost called frame to be - // included in the stack. The other arguments are passed directly through - // to the base Stackwalker constructor. - StackwalkerPPC64(const SystemInfo* system_info, - const MDRawContextPPC64* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer); - - private: - // Implementation of Stackwalker, using ppc64 context (stack pointer in %r1, - // saved program counter in %srr0) and stack conventions (saved stack - // pointer at 0(%r1), return address at 8(0(%r1)). - virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed); - - // Stores the CPU context corresponding to the innermost stack frame to - // be returned by GetContextFrame. - const MDRawContextPPC64* context_; -}; - - -} // namespace google_breakpad - - -#endif // PROCESSOR_STACKWALKER_PPC64_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc deleted file mode 100644 index f692d4c4c..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest.cc +++ /dev/null @@ -1,433 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_selftest.cc: Tests StackwalkerX86 or StackwalkerPPC using the -// running process' stack as test data, if running on an x86 or ppc and -// compiled with gcc. This test is not enabled in the "make check" suite -// by default, because certain optimizations interfere with its proper -// operation. To turn it on, configure with --enable-selftest. -// -// Optimizations that cause problems: -// - stack frame reuse. The Recursor function here calls itself with -// |return Recursor|. When the caller's frame is reused, it will cause -// CountCallerFrames to correctly return the same number of frames -// in both the caller and callee. This is considered an unexpected -// condition in the test, which expects a callee to have one more -// caller frame in the stack than its caller. -// - frame pointer omission. Even with a stackwalker that understands -// this optimization, the code to harness debug information currently -// only exists to retrieve it from minidumps, not the current process. -// -// This test can also serve as a developmental and debugging aid if -// PRINT_STACKS is defined. -// -// Author: Mark Mentovai - -#include <assert.h> - -#include "processor/logging.h" - -#if defined(__i386) && !defined(__i386__) -#define __i386__ -#endif -#if defined(__sparc) && !defined(__sparc__) -#define __sparc__ -#endif - -#if (defined(__SUNPRO_CC) || defined(__GNUC__)) && \ - (defined(__i386__) || defined(__ppc__) || defined(__sparc__)) - - -#include <stdio.h> - -#include "common/scoped_ptr.h" -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/stack_frame.h" -#include "google_breakpad/processor/stack_frame_cpu.h" - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::CallStack; -using google_breakpad::CodeModule; -using google_breakpad::MemoryRegion; -using google_breakpad::scoped_ptr; -using google_breakpad::StackFrame; -using google_breakpad::StackFramePPC; -using google_breakpad::StackFrameX86; -using google_breakpad::StackFrameSPARC; - -#if defined(__i386__) -#include "processor/stackwalker_x86.h" -using google_breakpad::StackwalkerX86; -#elif defined(__ppc__) -#include "processor/stackwalker_ppc.h" -using google_breakpad::StackwalkerPPC; -#elif defined(__sparc__) -#include "processor/stackwalker_sparc.h" -using google_breakpad::StackwalkerSPARC; -#endif // __i386__ || __ppc__ || __sparc__ - -#define RECURSION_DEPTH 100 - - -// A simple MemoryRegion subclass that provides direct access to this -// process' memory space by pointer. -class SelfMemoryRegion : public MemoryRegion { - public: - virtual uint64_t GetBase() const { return 0; } - virtual uint32_t GetSize() const { return 0xffffffff; } - - bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const { - return GetMemoryAtAddressInternal(address, value); } - bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const { - return GetMemoryAtAddressInternal(address, value); } - bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const { - return GetMemoryAtAddressInternal(address, value); } - bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const { - return GetMemoryAtAddressInternal(address, value); } - void Print() const { - assert(false); - } - - private: - template<typename T> bool GetMemoryAtAddressInternal(uint64_t address, - T* value) { - // Without knowing what addresses are actually mapped, just assume that - // everything low is not mapped. This helps the stackwalker catch the - // end of a stack when it tries to dereference a null or low pointer - // in an attempt to find the caller frame. Other unmapped accesses will - // cause the program to crash, but that would properly be a test failure. - if (address < 0x100) - return false; - - uint8_t* memory = 0; - *value = *reinterpret_cast<const T*>(&memory[address]); - return true; - } -}; - - -#if defined(__GNUC__) - - -#if defined(__i386__) - -// GetEBP returns the current value of the %ebp register. Because it's -// implemented as a function, %ebp itself contains GetEBP's frame pointer -// and not the caller's frame pointer. Dereference %ebp to obtain the -// caller's frame pointer, which the compiler-generated preamble stored -// on the stack (provided frame pointers are not being omitted.) Because -// this function depends on the compiler-generated preamble, inlining is -// disabled. -static uint32_t GetEBP() __attribute__((noinline)); -static uint32_t GetEBP() { - uint32_t ebp; - __asm__ __volatile__( - "movl (%%ebp), %0" - : "=a" (ebp) - ); - return ebp; -} - - -// The caller's %esp is 8 higher than the value of %ebp in this function, -// assuming that it's not inlined and that the standard prolog is used. -// The CALL instruction places a 4-byte return address on the stack above -// the caller's %esp, and this function's prolog will save the caller's %ebp -// on the stack as well, for another 4 bytes, before storing %esp in %ebp. -static uint32_t GetESP() __attribute__((noinline)); -static uint32_t GetESP() { - uint32_t ebp; - __asm__ __volatile__( - "movl %%ebp, %0" - : "=a" (ebp) - ); - return ebp + 8; -} - - -// GetEIP returns the instruction pointer identifying the next instruction -// to execute after GetEIP returns. It obtains this information from the -// stack, where it was placed by the call instruction that called GetEIP. -// This function depends on frame pointers not being omitted. It is possible -// to write a pure asm version of this routine that has no compiler-generated -// preamble and uses %esp instead of %ebp; that would function in the -// absence of frame pointers. However, the simpler approach is used here -// because GetEBP and stackwalking necessarily depends on access to frame -// pointers. Because this function depends on a call instruction and the -// compiler-generated preamble, inlining is disabled. -static uint32_t GetEIP() __attribute__((noinline)); -static uint32_t GetEIP() { - uint32_t eip; - __asm__ __volatile__( - "movl 4(%%ebp), %0" - : "=a" (eip) - ); - return eip; -} - - -#elif defined(__ppc__) - - -// GetSP returns the current value of the %r1 register, which by convention, -// is the stack pointer on ppc. Because it's implemented as a function, -// %r1 itself contains GetSP's own stack pointer and not the caller's stack -// pointer. Dereference %r1 to obtain the caller's stack pointer, which the -// compiler-generated prolog stored on the stack. Because this function -// depends on the compiler-generated prolog, inlining is disabled. -static uint32_t GetSP() __attribute__((noinline)); -static uint32_t GetSP() { - uint32_t sp; - __asm__ __volatile__( - "lwz %0, 0(r1)" - : "=r" (sp) - ); - return sp; -} - - -// GetPC returns the program counter identifying the next instruction to -// execute after GetPC returns. It obtains this information from the -// link register, where it was placed by the branch instruction that called -// GetPC. Because this function depends on the caller's use of a branch -// instruction, inlining is disabled. -static uint32_t GetPC() __attribute__((noinline)); -static uint32_t GetPC() { - uint32_t lr; - __asm__ __volatile__( - "mflr %0" - : "=r" (lr) - ); - return lr; -} - - -#elif defined(__sparc__) - - -// GetSP returns the current value of the %sp/%o6/%g_r[14] register, which -// by convention, is the stack pointer on sparc. Because it's implemented -// as a function, %sp itself contains GetSP's own stack pointer and not -// the caller's stack pointer. Dereference to obtain the caller's stack -// pointer, which the compiler-generated prolog stored on the stack. -// Because this function depends on the compiler-generated prolog, inlining -// is disabled. -static uint32_t GetSP() __attribute__((noinline)); -static uint32_t GetSP() { - uint32_t sp; - __asm__ __volatile__( - "mov %%fp, %0" - : "=r" (sp) - ); - return sp; -} - -// GetFP returns the current value of the %fp register. Because it's -// implemented as a function, %fp itself contains GetFP's frame pointer -// and not the caller's frame pointer. Dereference %fp to obtain the -// caller's frame pointer, which the compiler-generated preamble stored -// on the stack (provided frame pointers are not being omitted.) Because -// this function depends on the compiler-generated preamble, inlining is -// disabled. -static uint32_t GetFP() __attribute__((noinline)); -static uint32_t GetFP() { - uint32_t fp; - __asm__ __volatile__( - "ld [%%fp+56], %0" - : "=r" (fp) - ); - return fp; -} - -// GetPC returns the program counter identifying the next instruction to -// execute after GetPC returns. It obtains this information from the -// link register, where it was placed by the branch instruction that called -// GetPC. Because this function depends on the caller's use of a branch -// instruction, inlining is disabled. -static uint32_t GetPC() __attribute__((noinline)); -static uint32_t GetPC() { - uint32_t pc; - __asm__ __volatile__( - "mov %%i7, %0" - : "=r" (pc) - ); - return pc + 8; -} - -#endif // __i386__ || __ppc__ || __sparc__ - -#elif defined(__SUNPRO_CC) - -#if defined(__i386__) -extern "C" { -extern uint32_t GetEIP(); -extern uint32_t GetEBP(); -extern uint32_t GetESP(); -} -#elif defined(__sparc__) -extern "C" { -extern uint32_t GetPC(); -extern uint32_t GetFP(); -extern uint32_t GetSP(); -} -#endif // __i386__ || __sparc__ - -#endif // __GNUC__ || __SUNPRO_CC - -// CountCallerFrames returns the number of stack frames beneath the function -// that called CountCallerFrames. Because this function's return value -// is dependent on the size of the stack beneath it, inlining is disabled, -// and any function that calls this should not be inlined either. -#if defined(__GNUC__) -static unsigned int CountCallerFrames() __attribute__((noinline)); -#elif defined(__SUNPRO_CC) -static unsigned int CountCallerFrames(); -#endif -static unsigned int CountCallerFrames() { - SelfMemoryRegion memory; - BasicSourceLineResolver resolver; - -#if defined(__i386__) - MDRawContextX86 context = MDRawContextX86(); - context.eip = GetEIP(); - context.ebp = GetEBP(); - context.esp = GetESP(); - - StackwalkerX86 stackwalker = StackwalkerX86(NULL, &context, &memory, NULL, - NULL, &resolver); -#elif defined(__ppc__) - MDRawContextPPC context = MDRawContextPPC(); - context.srr0 = GetPC(); - context.gpr[1] = GetSP(); - - StackwalkerPPC stackwalker = StackwalkerPPC(NULL, &context, &memory, NULL, - NULL, &resolver); -#elif defined(__sparc__) - MDRawContextSPARC context = MDRawContextSPARC(); - context.pc = GetPC(); - context.g_r[14] = GetSP(); - context.g_r[30] = GetFP(); - - StackwalkerSPARC stackwalker = StackwalkerSPARC(NULL, &context, &memory, - NULL, NULL, &resolver); -#endif // __i386__ || __ppc__ || __sparc__ - - CallStack stack; - vector<const CodeModule*> modules_without_symbols; - stackwalker.Walk(&stack, &modules_without_symbols); - -#ifdef PRINT_STACKS - printf("\n"); - for (unsigned int frame_index = 0; - frame_index < stack.frames()->size(); - ++frame_index) { - StackFrame *frame = stack.frames()->at(frame_index); - printf("frame %-3d instruction = 0x%08" PRIx64, - frame_index, frame->instruction); -#if defined(__i386__) - StackFrameX86 *frame_x86 = reinterpret_cast<StackFrameX86*>(frame); - printf(" esp = 0x%08x ebp = 0x%08x\n", - frame_x86->context.esp, frame_x86->context.ebp); -#elif defined(__ppc__) - StackFramePPC *frame_ppc = reinterpret_cast<StackFramePPC*>(frame); - printf(" gpr[1] = 0x%08x\n", frame_ppc->context.gpr[1]); -#elif defined(__sparc__) - StackFrameSPARC *frame_sparc = reinterpret_cast<StackFrameSPARC*>(frame); - printf(" sp = 0x%08x fp = 0x%08x\n", - frame_sparc->context.g_r[14], frame_sparc->context.g_r[30]); -#endif // __i386__ || __ppc__ || __sparc__ - } -#endif // PRINT_STACKS - - // Subtract 1 because the caller wants the number of frames beneath - // itself. Because the caller called us, subract two for our frame and its - // frame, which are included in stack.size(). - return stack.frames()->size() - 2; -} - - -// Recursor verifies that the number stack frames beneath itself is one more -// than the number of stack frames beneath its parent. When depth frames -// have been reached, Recursor stops checking and returns success. If the -// frame count check fails at any depth, Recursor will stop and return false. -// Because this calls CountCallerFrames, inlining is disabled. -#if defined(__GNUC__) -static bool Recursor(unsigned int depth, unsigned int parent_callers) - __attribute__((noinline)); -#elif defined(__SUNPRO_CC) -static bool Recursor(unsigned int depth, unsigned int parent_callers); -#endif -static bool Recursor(unsigned int depth, unsigned int parent_callers) { - unsigned int callers = CountCallerFrames(); - if (callers != parent_callers + 1) - return false; - - if (depth) - return Recursor(depth - 1, callers); - - // depth == 0 - return true; -} - - -// Because this calls CountCallerFrames, inlining is disabled - but because -// it's main (and nobody calls it other than the entry point), it wouldn't -// be inlined anyway. -#if defined(__GNUC__) -int main(int argc, char** argv) __attribute__((noinline)); -#elif defined(__SUNPRO_CC) -int main(int argc, char** argv); -#endif -int main(int argc, char** argv) { - BPLOG_INIT(&argc, &argv); - - return Recursor(RECURSION_DEPTH, CountCallerFrames()) ? 0 : 1; -} - - -#else -// Not i386 or ppc or sparc? We can only test stacks we know how to walk. - - -int main(int argc, char **argv) { - BPLOG_INIT(&argc, &argv); - - // "make check" interprets an exit status of 77 to mean that the test is - // not supported. - BPLOG(ERROR) << "Selftest not supported here"; - return 77; -} - - -#endif // (__GNUC__ || __SUNPRO_CC) && (__i386__ || __ppc__ || __sparc__) diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest_sol.s b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest_sol.s deleted file mode 100644 index 648b0499a..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_selftest_sol.s +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (c) 2007, Google Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are - * met: - * - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above - * copyright notice, this list of conditions and the following disclaimer - * in the documentation and/or other materials provided with the - * distribution. - * * Neither the name of Google Inc. nor the names of its - * contributors may be used to endorse or promote products derived from - * this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -/* stackwalker_selftest_sol.s - * On Solaris, the recommeded compiler is CC, so we can not use gcc inline - * asm, use this method instead. - * - * How to compile: as -P -L -D_ASM -D_STDC -K PIC -o \ - * src/processor/stackwalker_selftest_sol.o \ - * src/processor/stackwalker_selftest_sol.s - * - * Author: Michael Shang - */ - -#include <sys/asm_linkage.h> - -#if defined(__i386) - - -ENTRY(GetEBP) - pushl %ebp - movl %esp,%ebp - subl $0x00000004,%esp - movl 0x00000000(%ebp),%eax - movl %eax,0xfffffffc(%ebp) - movl 0xfffffffc(%ebp),%eax - leave - ret -SET_SIZE(GetEBP) - -ENTRY(GetEIP) - pushl %ebp - movl %esp,%ebp - subl $0x00000004,%esp - movl 0x00000004(%ebp),%eax - movl %eax,0xfffffffc(%ebp) - movl 0xfffffffc(%ebp),%eax - leave - ret -SET_SIZE(GetEIP) - -ENTRY(GetESP) - pushl %ebp - movl %esp,%ebp - subl $0x00000004,%esp - movl %ebp,%eax - movl %eax,0xfffffffc(%ebp) - movl 0xfffffffc(%ebp),%eax - addl $0x00000008,%eax - leave - ret -SET_SIZE(GetESP) - - -#elif defined(__sparc) - - -ENTRY(GetPC) - save %sp, -120, %sp - mov %i7, %i4 - inccc 8, %i4 - mov %i4, %i0 - ret - restore -SET_SIZE(GetPC) - -ENTRY(GetSP) - save %sp, -120, %sp - mov %fp, %i4 - mov %i4, %i0 - ret - restore -SET_SIZE(GetSP) - -ENTRY(GetFP) - save %sp, -120, %sp - ld [%fp + 56], %g1 - mov %g1, %i0 - ret - restore -SET_SIZE(GetFP) - - -#endif // __i386 || __sparc diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.cc deleted file mode 100644 index ff2ea75a8..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.cc +++ /dev/null @@ -1,139 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_sparc.cc: sparc-specific stackwalker. -// -// See stackwalker_sparc.h for documentation. -// -// Author: Michael Shang - - -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/logging.h" -#include "processor/stackwalker_sparc.h" - -namespace google_breakpad { - - -StackwalkerSPARC::StackwalkerSPARC(const SystemInfo* system_info, - const MDRawContextSPARC* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* resolver_helper) - : Stackwalker(system_info, memory, modules, resolver_helper), - context_(context) { -} - - -StackFrame* StackwalkerSPARC::GetContextFrame() { - if (!context_) { - BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; - } - - StackFrameSPARC* frame = new StackFrameSPARC(); - - // The instruction pointer is stored directly in a register, so pull it - // straight out of the CPU context structure. - frame->context = *context_; - frame->context_validity = StackFrameSPARC::CONTEXT_VALID_ALL; - frame->trust = StackFrame::FRAME_TRUST_CONTEXT; - frame->instruction = frame->context.pc; - - return frame; -} - - -StackFrame* StackwalkerSPARC::GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed) { - if (!memory_ || !stack) { - BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; - } - - StackFrameSPARC* last_frame = static_cast<StackFrameSPARC*>( - stack->frames()->back()); - - // new: caller - // old: callee - // %fp, %i6 and g_r[30] is the same, see minidump_format.h - // %sp, %o6 and g_r[14] is the same, see minidump_format.h - // %sp_new = %fp_old - // %fp_new = *(%fp_old + 32 + 32 - 8), where the callee's %i6 - // %pc_new = *(%fp_old + 32 + 32 - 4) + 8 - // which is callee's %i7 plus 8 - - // A caller frame must reside higher in memory than its callee frames. - // Anything else is an error, or an indication that we've reached the - // end of the stack. - uint64_t stack_pointer = last_frame->context.g_r[30]; - if (stack_pointer <= last_frame->context.g_r[14]) { - return NULL; - } - - uint32_t instruction; - if (!memory_->GetMemoryAtAddress(stack_pointer + 60, - &instruction) || instruction <= 1) { - return NULL; - } - - uint32_t stack_base; - if (!memory_->GetMemoryAtAddress(stack_pointer + 56, - &stack_base) || stack_base <= 1) { - return NULL; - } - - StackFrameSPARC* frame = new StackFrameSPARC(); - - frame->context = last_frame->context; - frame->context.g_r[14] = stack_pointer; - frame->context.g_r[30] = stack_base; - - // frame->context.pc is the return address, which is 2 instruction - // past the branch that caused us to arrive at the callee, which are - // a CALL instruction then a NOP instruction. - // frame_ppc->instruction to 8 less than that. Since all sparc - // instructions are 4 bytes wide, this is the address of the branch - // instruction. This allows source line information to match up with the - // line that contains a function call. Callers that require the exact - // return address value may access the %i7/g_r[31] field of StackFrameSPARC. - frame->context.pc = instruction + 8; - frame->instruction = instruction; - frame->context_validity = StackFrameSPARC::CONTEXT_VALID_PC | - StackFrameSPARC::CONTEXT_VALID_SP | - StackFrameSPARC::CONTEXT_VALID_FP; - frame->trust = StackFrame::FRAME_TRUST_FP; - - return frame; -} - - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.h deleted file mode 100644 index e8f2a3888..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_sparc.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_sparc.h: sparc-specific stackwalker. -// -// Provides stack frames given sparc register context and a memory region -// corresponding to an sparc stack. -// -// Author: Michael Shang - - -#ifndef PROCESSOR_STACKWALKER_SPARC_H__ -#define PROCESSOR_STACKWALKER_SPARC_H__ - - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/stackwalker.h" - -namespace google_breakpad { - -class CodeModules; - -class StackwalkerSPARC : public Stackwalker { - public: - // context is a sparc context object that gives access to sparc-specific - // register state corresponding to the innermost called frame to be - // included in the stack. The other arguments are passed directly through - // to the base Stackwalker constructor. - StackwalkerSPARC(const SystemInfo* system_info, - const MDRawContextSPARC* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer); - - private: - // Implementation of Stackwalker, using sparc context (%fp, %sp, %pc) and - // stack conventions - virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed); - - // Stores the CPU context corresponding to the innermost stack frame to - // be returned by GetContextFrame. - const MDRawContextSPARC* context_; -}; - - -} // namespace google_breakpad - - -#endif // PROCESSOR_STACKWALKER_SPARC_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_unittest_utils.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_unittest_utils.h deleted file mode 100644 index ee22a8fe1..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_unittest_utils.h +++ /dev/null @@ -1,224 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// Mock classes for writing stackwalker tests, shared amongst architectures. - -#ifndef PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_ -#define PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_ - -#include <assert.h> -#include <stdlib.h> -#include <string> -#include <vector> - -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/code_modules.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/symbol_supplier.h" -#include "google_breakpad/processor/system_info.h" -#include "processor/linked_ptr.h" - -class MockMemoryRegion: public google_breakpad::MemoryRegion { - public: - MockMemoryRegion(): base_address_(0) { } - - // Set this region's address and contents. If we have placed an - // instance of this class in a test fixture class, individual tests - // can use this to provide the region's contents. - void Init(uint64_t base_address, const string &contents) { - base_address_ = base_address; - contents_ = contents; - } - - uint64_t GetBase() const { return base_address_; } - uint32_t GetSize() const { return contents_.size(); } - - bool GetMemoryAtAddress(uint64_t address, uint8_t *value) const { - return GetMemoryLittleEndian(address, value); - } - bool GetMemoryAtAddress(uint64_t address, uint16_t *value) const { - return GetMemoryLittleEndian(address, value); - } - bool GetMemoryAtAddress(uint64_t address, uint32_t *value) const { - return GetMemoryLittleEndian(address, value); - } - bool GetMemoryAtAddress(uint64_t address, uint64_t *value) const { - return GetMemoryLittleEndian(address, value); - } - void Print() const { - assert(false); - } - - private: - // Fetch a little-endian value from ADDRESS in contents_ whose size - // is BYTES, and store it in *VALUE. Return true on success. - template<typename ValueType> - bool GetMemoryLittleEndian(uint64_t address, ValueType *value) const { - if (address < base_address_ || - address - base_address_ + sizeof(ValueType) > contents_.size()) - return false; - ValueType v = 0; - int start = address - base_address_; - // The loop condition is odd, but it's correct for size_t. - for (size_t i = sizeof(ValueType) - 1; i < sizeof(ValueType); i--) - v = (v << 8) | static_cast<unsigned char>(contents_[start + i]); - *value = v; - return true; - } - - uint64_t base_address_; - string contents_; -}; - -class MockCodeModule: public google_breakpad::CodeModule { - public: - MockCodeModule(uint64_t base_address, uint64_t size, - const string &code_file, const string &version) - : base_address_(base_address), size_(size), code_file_(code_file) { } - - uint64_t base_address() const { return base_address_; } - uint64_t size() const { return size_; } - string code_file() const { return code_file_; } - string code_identifier() const { return code_file_; } - string debug_file() const { return code_file_; } - string debug_identifier() const { return code_file_; } - string version() const { return version_; } - google_breakpad::CodeModule *Copy() const { - abort(); // Tests won't use this. - } - virtual uint64_t shrink_down_delta() const { return 0; } - virtual void SetShrinkDownDelta(uint64_t shrink_down_delta) {} - - private: - uint64_t base_address_; - uint64_t size_; - string code_file_; - string version_; -}; - -class MockCodeModules: public google_breakpad::CodeModules { - public: - typedef google_breakpad::CodeModule CodeModule; - typedef google_breakpad::CodeModules CodeModules; - - void Add(const MockCodeModule *module) { - modules_.push_back(module); - } - - unsigned int module_count() const { return modules_.size(); } - - const CodeModule *GetModuleForAddress(uint64_t address) const { - for (ModuleVector::const_iterator i = modules_.begin(); - i != modules_.end(); i++) { - const MockCodeModule *module = *i; - if (module->base_address() <= address && - address - module->base_address() < module->size()) - return module; - } - return NULL; - }; - - const CodeModule *GetMainModule() const { return modules_[0]; } - - const CodeModule *GetModuleAtSequence(unsigned int sequence) const { - return modules_.at(sequence); - } - - const CodeModule *GetModuleAtIndex(unsigned int index) const { - return modules_.at(index); - } - - 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: - typedef std::vector<const MockCodeModule *> ModuleVector; - ModuleVector modules_; -}; - -class MockSymbolSupplier: public google_breakpad::SymbolSupplier { - public: - typedef google_breakpad::CodeModule CodeModule; - typedef google_breakpad::SystemInfo SystemInfo; - MOCK_METHOD3(GetSymbolFile, SymbolResult(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file)); - MOCK_METHOD4(GetSymbolFile, SymbolResult(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - string *symbol_data)); - MOCK_METHOD5(GetCStringSymbolData, SymbolResult(const CodeModule *module, - const SystemInfo *system_info, - string *symbol_file, - char **symbol_data, - size_t *symbol_data_size)); - MOCK_METHOD1(FreeSymbolData, void(const CodeModule *module)); - - // Copies the passed string contents into a newly allocated buffer. - // The newly allocated buffer will be freed during destruction. - char* CopySymbolDataAndOwnTheCopy(const std::string &info, - size_t *symbol_data_size) { - *symbol_data_size = info.size() + 1; - char *symbol_data = new char[*symbol_data_size]; - memcpy(symbol_data, info.c_str(), info.size()); - symbol_data[info.size()] = '\0'; - symbol_data_to_free_.push_back(symbol_data); - return symbol_data; - } - - virtual ~MockSymbolSupplier() { - for (SymbolDataVector::const_iterator i = symbol_data_to_free_.begin(); - i != symbol_data_to_free_.end(); i++) { - char* symbol_data = *i; - delete [] symbol_data; - } - } - - private: - // List of symbol data to be freed upon destruction - typedef std::vector<char*> SymbolDataVector; - SymbolDataVector symbol_data_to_free_; -}; - -#endif // PROCESSOR_STACKWALKER_UNITTEST_UTILS_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc deleted file mode 100644 index 29d98e4b8..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.cc +++ /dev/null @@ -1,672 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_x86.cc: x86-specific stackwalker. -// -// See stackwalker_x86.h for documentation. -// -// Author: Mark Mentovai - -#include <assert.h> -#include <string> - -#include "common/scoped_ptr.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_modules.h" -#include "google_breakpad/processor/memory_region.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/logging.h" -#include "processor/postfix_evaluator-inl.h" -#include "processor/stackwalker_x86.h" -#include "processor/windows_frame_info.h" -#include "processor/cfi_frame_info.h" - -namespace google_breakpad { - -// Max reasonable size for a single x86 frame is 128 KB. This value is used in -// a heuristic for recovering of the EBP chain after a scan for return address. -// This value is based on a stack frame size histogram built for a set of -// popular third party libraries which suggests that 99.5% of all frames are -// smaller than 128 KB. -static const uint32_t kMaxReasonableGapBetweenFrames = 128 * 1024; - -const StackwalkerX86::CFIWalker::RegisterSet -StackwalkerX86::cfi_register_map_[] = { - // It may seem like $eip and $esp are callee-saves, because (with Unix or - // cdecl calling conventions) the callee is responsible for having them - // restored upon return. But the callee_saves flags here really means - // that the walker should assume they're unchanged if the CFI doesn't - // mention them, which is clearly wrong for $eip and $esp. - { "$eip", ".ra", false, - StackFrameX86::CONTEXT_VALID_EIP, &MDRawContextX86::eip }, - { "$esp", ".cfa", false, - StackFrameX86::CONTEXT_VALID_ESP, &MDRawContextX86::esp }, - { "$ebp", NULL, true, - StackFrameX86::CONTEXT_VALID_EBP, &MDRawContextX86::ebp }, - { "$eax", NULL, false, - StackFrameX86::CONTEXT_VALID_EAX, &MDRawContextX86::eax }, - { "$ebx", NULL, true, - StackFrameX86::CONTEXT_VALID_EBX, &MDRawContextX86::ebx }, - { "$ecx", NULL, false, - StackFrameX86::CONTEXT_VALID_ECX, &MDRawContextX86::ecx }, - { "$edx", NULL, false, - StackFrameX86::CONTEXT_VALID_EDX, &MDRawContextX86::edx }, - { "$esi", NULL, true, - StackFrameX86::CONTEXT_VALID_ESI, &MDRawContextX86::esi }, - { "$edi", NULL, true, - StackFrameX86::CONTEXT_VALID_EDI, &MDRawContextX86::edi }, -}; - -StackwalkerX86::StackwalkerX86(const SystemInfo* system_info, - const MDRawContextX86* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* resolver_helper) - : Stackwalker(system_info, memory, modules, resolver_helper), - context_(context), - cfi_walker_(cfi_register_map_, - (sizeof(cfi_register_map_) / sizeof(cfi_register_map_[0]))) { - if (memory_ && memory_->GetBase() + memory_->GetSize() - 1 > 0xffffffff) { - // The x86 is a 32-bit CPU, the limits of the supplied stack are invalid. - // Mark memory_ = NULL, which will cause stackwalking to fail. - BPLOG(ERROR) << "Memory out of range for stackwalking: " << - HexString(memory_->GetBase()) << "+" << - HexString(memory_->GetSize()); - memory_ = NULL; - } -} - -StackFrameX86::~StackFrameX86() { - if (windows_frame_info) - delete windows_frame_info; - windows_frame_info = NULL; - if (cfi_frame_info) - delete cfi_frame_info; - cfi_frame_info = NULL; -} - -uint64_t StackFrameX86::ReturnAddress() const { - assert(context_validity & StackFrameX86::CONTEXT_VALID_EIP); - return context.eip; -} - -StackFrame* StackwalkerX86::GetContextFrame() { - if (!context_) { - BPLOG(ERROR) << "Can't get context frame without context"; - return NULL; - } - - StackFrameX86* frame = new StackFrameX86(); - - // The instruction pointer is stored directly in a register, so pull it - // straight out of the CPU context structure. - frame->context = *context_; - frame->context_validity = StackFrameX86::CONTEXT_VALID_ALL; - frame->trust = StackFrame::FRAME_TRUST_CONTEXT; - frame->instruction = frame->context.eip; - - return frame; -} - -StackFrameX86* StackwalkerX86::GetCallerByWindowsFrameInfo( - const vector<StackFrame*> &frames, - WindowsFrameInfo* last_frame_info, - bool stack_scan_allowed) { - StackFrame::FrameTrust trust = StackFrame::FRAME_TRUST_NONE; - - StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); - - // Save the stack walking info we found, in case we need it later to - // find the callee of the frame we're constructing now. - last_frame->windows_frame_info = last_frame_info; - - // This function only covers the full STACK WIN case. If - // last_frame_info is VALID_PARAMETER_SIZE-only, then we should - // assume the traditional frame format or use some other strategy. - if (last_frame_info->valid != WindowsFrameInfo::VALID_ALL) - return NULL; - - // This stackwalker sets each frame's %esp to its value immediately prior - // to the CALL into the callee. This means that %esp points to the last - // callee argument pushed onto the stack, which may not be where %esp points - // after the callee returns. Specifically, the value is correct for the - // cdecl calling convention, but not other conventions. The cdecl - // convention requires a caller to pop its callee's arguments from the - // stack after the callee returns. This is usually accomplished by adding - // the known size of the arguments to %esp. Other calling conventions, - // including stdcall, thiscall, and fastcall, require the callee to pop any - // parameters stored on the stack before returning. This is usually - // accomplished by using the RET n instruction, which pops n bytes off - // the stack after popping the return address. - // - // Because each frame's %esp will point to a location on the stack after - // callee arguments have been PUSHed, when locating things in a stack frame - // relative to %esp, the size of the arguments to the callee need to be - // taken into account. This seems a little bit unclean, but it's better - // than the alternative, which would need to take these same things into - // account, but only for cdecl functions. With this implementation, we get - // to be agnostic about each function's calling convention. Furthermore, - // this is how Windows debugging tools work, so it means that the %esp - // values produced by this stackwalker directly correspond to the %esp - // values you'll see there. - // - // If the last frame has no callee (because it's the context frame), just - // set the callee parameter size to 0: the stack pointer can't point to - // callee arguments because there's no callee. This is correct as long - // as the context wasn't captured while arguments were being pushed for - // a function call. Note that there may be functions whose parameter sizes - // are unknown, 0 is also used in that case. When that happens, it should - // be possible to walk to the next frame without reference to %esp. - - uint32_t last_frame_callee_parameter_size = 0; - int frames_already_walked = frames.size(); - if (frames_already_walked >= 2) { - const StackFrameX86* last_frame_callee - = static_cast<StackFrameX86*>(frames[frames_already_walked - 2]); - WindowsFrameInfo* last_frame_callee_info - = last_frame_callee->windows_frame_info; - if (last_frame_callee_info && - (last_frame_callee_info->valid - & WindowsFrameInfo::VALID_PARAMETER_SIZE)) { - last_frame_callee_parameter_size = - last_frame_callee_info->parameter_size; - } - } - - // Set up the dictionary for the PostfixEvaluator. %ebp and %esp are used - // in each program string, and their previous values are known, so set them - // here. - PostfixEvaluator<uint32_t>::DictionaryType dictionary; - // Provide the current register values. - dictionary["$ebp"] = last_frame->context.ebp; - dictionary["$esp"] = last_frame->context.esp; - // Provide constants from the debug info for last_frame and its callee. - // .cbCalleeParams is a Breakpad extension that allows us to use the - // PostfixEvaluator engine when certain types of debugging information - // are present without having to write the constants into the program - // string as literals. - dictionary[".cbCalleeParams"] = last_frame_callee_parameter_size; - dictionary[".cbSavedRegs"] = last_frame_info->saved_register_size; - dictionary[".cbLocals"] = last_frame_info->local_size; - - uint32_t raSearchStart = last_frame->context.esp + - last_frame_callee_parameter_size + - last_frame_info->local_size + - last_frame_info->saved_register_size; - - uint32_t raSearchStartOld = raSearchStart; - uint32_t found = 0; // dummy value - // Scan up to three words above the calculated search value, in case - // the stack was aligned to a quadword boundary. - // - // TODO(ivan.penkov): Consider cleaning up the scan for return address that - // follows. The purpose of this scan is to adjust the .raSearchStart - // calculation (which is based on register %esp) in the cases where register - // %esp may have been aligned (up to a quadword). There are two problems - // with this approach: - // 1) In practice, 64 byte boundary alignment is seen which clearly can not - // be handled by a three word scan. - // 2) A search for a return address is "guesswork" by definition because - // the results will be different depending on what is left on the stack - // from previous executions. - // So, basically, the results from this scan should be ignored if other means - // for calculation of the value of .raSearchStart are available. - if (ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3) && - last_frame->trust == StackFrame::FRAME_TRUST_CONTEXT && - last_frame->windows_frame_info != NULL && - last_frame_info->type_ == WindowsFrameInfo::STACK_INFO_FPO && - raSearchStartOld == raSearchStart && - found == last_frame->context.eip) { - // The context frame represents an FPO-optimized Windows system call. - // On the top of the stack we have a pointer to the current instruction. - // This means that the callee has returned but the return address is still - // on the top of the stack which is very atypical situaltion. - // Skip one slot from the stack and do another scan in order to get the - // actual return address. - raSearchStart += 4; - ScanForReturnAddress(raSearchStart, &raSearchStart, &found, 3); - } - - dictionary[".cbParams"] = last_frame_info->parameter_size; - - // Decide what type of program string to use. The program string is in - // postfix notation and will be passed to PostfixEvaluator::Evaluate. - // Given the dictionary and the program string, it is possible to compute - // the return address and the values of other registers in the calling - // function. Because of bugs described below, the stack may need to be - // scanned for these values. The results of program string evaluation - // will be used to determine whether to scan for better values. - string program_string; - bool recover_ebp = true; - - trust = StackFrame::FRAME_TRUST_CFI; - if (!last_frame_info->program_string.empty()) { - // The FPO data has its own program string, which will tell us how to - // get to the caller frame, and may even fill in the values of - // nonvolatile registers and provide pointers to local variables and - // parameters. In some cases, particularly with program strings that use - // .raSearchStart, the stack may need to be scanned afterward. - program_string = last_frame_info->program_string; - } else if (last_frame_info->allocates_base_pointer) { - // The function corresponding to the last frame doesn't use the frame - // pointer for conventional purposes, but it does allocate a new - // frame pointer and use it for its own purposes. Its callee's - // information is still accessed relative to %esp, and the previous - // value of %ebp can be recovered from a location in its stack frame, - // within the saved-register area. - // - // Functions that fall into this category use the %ebp register for - // a purpose other than the frame pointer. They restore the caller's - // %ebp before returning. These functions create their stack frame - // after a CALL by decrementing the stack pointer in an amount - // sufficient to store local variables, and then PUSHing saved - // registers onto the stack. Arguments to a callee function, if any, - // are PUSHed after that. Walking up to the caller, therefore, - // can be done solely with calculations relative to the stack pointer - // (%esp). The return address is recovered from the memory location - // above the known sizes of the callee's parameters, saved registers, - // and locals. The caller's stack pointer (the value of %esp when - // the caller executed CALL) is the location immediately above the - // saved return address. The saved value of %ebp to be restored for - // the caller is at a known location in the saved-register area of - // the stack frame. - // - // For this type of frame, MSVC 14 (from Visual Studio 8/2005) in - // link-time code generation mode (/LTCG and /GL) can generate erroneous - // debugging data. The reported size of saved registers can be 0, - // which is clearly an error because these frames must, at the very - // least, save %ebp. For this reason, in addition to those given above - // about the use of .raSearchStart, the stack may need to be scanned - // for a better return address and a better frame pointer after the - // program string is evaluated. - // - // %eip_new = *(%esp_old + callee_params + saved_regs + locals) - // %ebp_new = *(%esp_old + callee_params + saved_regs - 8) - // %esp_new = %esp_old + callee_params + saved_regs + locals + 4 - program_string = "$eip .raSearchStart ^ = " - "$ebp $esp .cbCalleeParams + .cbSavedRegs + 8 - ^ = " - "$esp .raSearchStart 4 + ="; - } else { - // The function corresponding to the last frame doesn't use %ebp at - // all. The callee frame is located relative to %esp. - // - // The called procedure's instruction pointer and stack pointer are - // recovered in the same way as the case above, except that no - // frame pointer (%ebp) is used at all, so it is not saved anywhere - // in the callee's stack frame and does not need to be recovered. - // Because %ebp wasn't used in the callee, whatever value it has - // is the value that it had in the caller, so it can be carried - // straight through without bringing its validity into question. - // - // Because of the use of .raSearchStart, the stack will possibly be - // examined to locate a better return address after program string - // evaluation. The stack will not be examined to locate a saved - // %ebp value, because these frames do not save (or use) %ebp. - // - // %eip_new = *(%esp_old + callee_params + saved_regs + locals) - // %esp_new = %esp_old + callee_params + saved_regs + locals + 4 - // %ebp_new = %ebp_old - program_string = "$eip .raSearchStart ^ = " - "$esp .raSearchStart 4 + ="; - recover_ebp = false; - } - - // Check for alignment operators in the program string. If alignment - // operators are found, then current %ebp must be valid and it is the only - // reliable data point that can be used for getting to the previous frame. - // E.g. the .raSearchStart calculation (above) is based on %esp and since - // %esp was aligned in the current frame (which is a lossy operation) the - // calculated value of .raSearchStart cannot be correct and should not be - // used. Instead .raSearchStart must be calculated based on %ebp. - // The code that follows assumes that .raSearchStart is supposed to point - // at the saved return address (ebp + 4). - // For some more details on this topic, take a look at the following thread: - // https://groups.google.com/forum/#!topic/google-breakpad-dev/ZP1FA9B1JjM - if ((StackFrameX86::CONTEXT_VALID_EBP & last_frame->context_validity) != 0 && - program_string.find('@') != string::npos) { - raSearchStart = last_frame->context.ebp + 4; - } - - // The difference between raSearch and raSearchStart is unknown, - // but making them the same seems to work well in practice. - dictionary[".raSearchStart"] = raSearchStart; - dictionary[".raSearch"] = raSearchStart; - - // Now crank it out, making sure that the program string set at least the - // two required variables. - PostfixEvaluator<uint32_t> evaluator = - PostfixEvaluator<uint32_t>(&dictionary, memory_); - PostfixEvaluator<uint32_t>::DictionaryValidityType dictionary_validity; - if (!evaluator.Evaluate(program_string, &dictionary_validity) || - dictionary_validity.find("$eip") == dictionary_validity.end() || - dictionary_validity.find("$esp") == dictionary_validity.end()) { - // Program string evaluation failed. It may be that %eip is not somewhere - // with stack frame info, and %ebp is pointing to non-stack memory, so - // our evaluation couldn't succeed. We'll scan the stack for a return - // address. This can happen if the stack is in a module for which - // we don't have symbols, and that module is compiled without a - // frame pointer. - uint32_t location_start = last_frame->context.esp; - uint32_t location, eip; - if (!stack_scan_allowed - || !ScanForReturnAddress(location_start, &location, &eip, - frames.size() == 1 /* is_context_frame */)) { - // if we can't find an instruction pointer even with stack scanning, - // give up. - return NULL; - } - - // This seems like a reasonable return address. Since program string - // evaluation failed, use it and set %esp to the location above the - // one where the return address was found. - dictionary["$eip"] = eip; - dictionary["$esp"] = location + 4; - trust = StackFrame::FRAME_TRUST_SCAN; - } - - // Since this stack frame did not use %ebp in a traditional way, - // locating the return address isn't entirely deterministic. In that - // case, the stack can be scanned to locate the return address. - // - // However, if program string evaluation resulted in both %eip and - // %ebp values of 0, trust that the end of the stack has been - // reached and don't scan for anything else. - if (dictionary["$eip"] != 0 || dictionary["$ebp"] != 0) { - int offset = 0; - - // This scan can only be done if a CodeModules object is available, to - // check that candidate return addresses are in fact inside a module. - // - // TODO(mmentovai): This ignores dynamically-generated code. One possible - // solution is to check the minidump's memory map to see if the candidate - // %eip value comes from a mapped executable page, although this would - // require dumps that contain MINIDUMP_MEMORY_INFO, which the Breakpad - // client doesn't currently write (it would need to call MiniDumpWriteDump - // with the MiniDumpWithFullMemoryInfo type bit set). Even given this - // ability, older OSes (pre-XP SP2) and CPUs (pre-P4) don't enforce - // an independent execute privilege on memory pages. - - uint32_t eip = dictionary["$eip"]; - if (modules_ && !modules_->GetModuleForAddress(eip)) { - // The instruction pointer at .raSearchStart was invalid, so start - // looking one 32-bit word above that location. - uint32_t location_start = dictionary[".raSearchStart"] + 4; - uint32_t location; - if (stack_scan_allowed - && ScanForReturnAddress(location_start, &location, &eip, - frames.size() == 1 /* is_context_frame */)) { - // This is a better return address that what program string - // evaluation found. Use it, and set %esp to the location above the - // one where the return address was found. - dictionary["$eip"] = eip; - dictionary["$esp"] = location + 4; - offset = location - location_start; - trust = StackFrame::FRAME_TRUST_CFI_SCAN; - } - } - - if (recover_ebp) { - // When trying to recover the previous value of the frame pointer (%ebp), - // start looking at the lowest possible address in the saved-register - // area, and look at the entire saved register area, increased by the - // size of |offset| to account for additional data that may be on the - // stack. The scan is performed from the highest possible address to - // the lowest, because the expectation is that the function's prolog - // would have saved %ebp early. - uint32_t ebp = dictionary["$ebp"]; - - // When a scan for return address is used, it is possible to skip one or - // more frames (when return address is not in a known module). One - // indication for skipped frames is when the value of %ebp is lower than - // the location of the return address on the stack - bool has_skipped_frames = - (trust != StackFrame::FRAME_TRUST_CFI && ebp <= raSearchStart + offset); - - uint32_t value; // throwaway variable to check pointer validity - if (has_skipped_frames || !memory_->GetMemoryAtAddress(ebp, &value)) { - int fp_search_bytes = last_frame_info->saved_register_size + offset; - uint32_t location_end = last_frame->context.esp + - last_frame_callee_parameter_size; - - for (uint32_t location = location_end + fp_search_bytes; - location >= location_end; - location -= 4) { - if (!memory_->GetMemoryAtAddress(location, &ebp)) - break; - - if (memory_->GetMemoryAtAddress(ebp, &value)) { - // The candidate value is a pointer to the same memory region - // (the stack). Prefer it as a recovered %ebp result. - dictionary["$ebp"] = ebp; - break; - } - } - } - } - } - - // Create a new stack frame (ownership will be transferred to the caller) - // and fill it in. - StackFrameX86* frame = new StackFrameX86(); - - frame->trust = trust; - frame->context = last_frame->context; - frame->context.eip = dictionary["$eip"]; - frame->context.esp = dictionary["$esp"]; - frame->context.ebp = dictionary["$ebp"]; - frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP; - - // These are nonvolatile (callee-save) registers, and the program string - // may have filled them in. - if (dictionary_validity.find("$ebx") != dictionary_validity.end()) { - frame->context.ebx = dictionary["$ebx"]; - frame->context_validity |= StackFrameX86::CONTEXT_VALID_EBX; - } - if (dictionary_validity.find("$esi") != dictionary_validity.end()) { - frame->context.esi = dictionary["$esi"]; - frame->context_validity |= StackFrameX86::CONTEXT_VALID_ESI; - } - if (dictionary_validity.find("$edi") != dictionary_validity.end()) { - frame->context.edi = dictionary["$edi"]; - frame->context_validity |= StackFrameX86::CONTEXT_VALID_EDI; - } - - return frame; -} - -StackFrameX86* StackwalkerX86::GetCallerByCFIFrameInfo( - const vector<StackFrame*> &frames, - CFIFrameInfo* cfi_frame_info) { - StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); - last_frame->cfi_frame_info = cfi_frame_info; - - scoped_ptr<StackFrameX86> frame(new StackFrameX86()); - if (!cfi_walker_ - .FindCallerRegisters(*memory_, *cfi_frame_info, - last_frame->context, last_frame->context_validity, - &frame->context, &frame->context_validity)) - return NULL; - - // Make sure we recovered all the essentials. - static const int essentials = (StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP); - if ((frame->context_validity & essentials) != essentials) - return NULL; - - frame->trust = StackFrame::FRAME_TRUST_CFI; - - return frame.release(); -} - -StackFrameX86* StackwalkerX86::GetCallerByEBPAtBase( - const vector<StackFrame*> &frames, - bool stack_scan_allowed) { - StackFrame::FrameTrust trust; - StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); - uint32_t last_esp = last_frame->context.esp; - uint32_t last_ebp = last_frame->context.ebp; - - // Assume that the standard %ebp-using x86 calling convention is in - // use. - // - // The typical x86 calling convention, when frame pointers are present, - // is for the calling procedure to use CALL, which pushes the return - // address onto the stack and sets the instruction pointer (%eip) to - // the entry point of the called routine. The called routine then - // PUSHes the calling routine's frame pointer (%ebp) onto the stack - // before copying the stack pointer (%esp) to the frame pointer (%ebp). - // Therefore, the calling procedure's frame pointer is always available - // by dereferencing the called procedure's frame pointer, and the return - // address is always available at the memory location immediately above - // the address pointed to by the called procedure's frame pointer. The - // calling procedure's stack pointer (%esp) is 8 higher than the value - // of the called procedure's frame pointer at the time the calling - // procedure made the CALL: 4 bytes for the return address pushed by the - // CALL itself, and 4 bytes for the callee's PUSH of the caller's frame - // pointer. - // - // %eip_new = *(%ebp_old + 4) - // %esp_new = %ebp_old + 8 - // %ebp_new = *(%ebp_old) - - uint32_t caller_eip, caller_esp, caller_ebp; - - if (memory_->GetMemoryAtAddress(last_ebp + 4, &caller_eip) && - memory_->GetMemoryAtAddress(last_ebp, &caller_ebp)) { - caller_esp = last_ebp + 8; - trust = StackFrame::FRAME_TRUST_FP; - } else { - // We couldn't read the memory %ebp refers to. It may be that %ebp - // is pointing to non-stack memory. We'll scan the stack for a - // return address. This can happen if last_frame is executing code - // for a module for which we don't have symbols, and that module - // is compiled without a frame pointer. - if (!stack_scan_allowed - || !ScanForReturnAddress(last_esp, &caller_esp, &caller_eip, - frames.size() == 1 /* is_context_frame */)) { - // if we can't find an instruction pointer even with stack scanning, - // give up. - return NULL; - } - - // ScanForReturnAddress found a reasonable return address. Advance %esp to - // the location immediately above the one where the return address was - // found. - caller_esp += 4; - // Try to restore the %ebp chain. The caller %ebp should be stored at a - // location immediately below the one where the return address was found. - // A valid caller %ebp must be greater than the address where it is stored - // and the gap between the two adjacent frames should be reasonable. - uint32_t restored_ebp_chain = caller_esp - 8; - if (!memory_->GetMemoryAtAddress(restored_ebp_chain, &caller_ebp) || - caller_ebp <= restored_ebp_chain || - caller_ebp - restored_ebp_chain > kMaxReasonableGapBetweenFrames) { - // The restored %ebp chain doesn't appear to be valid. - // Assume that %ebp is unchanged. - caller_ebp = last_ebp; - } - - trust = StackFrame::FRAME_TRUST_SCAN; - } - - // Create a new stack frame (ownership will be transferred to the caller) - // and fill it in. - StackFrameX86* frame = new StackFrameX86(); - - frame->trust = trust; - frame->context = last_frame->context; - frame->context.eip = caller_eip; - frame->context.esp = caller_esp; - frame->context.ebp = caller_ebp; - frame->context_validity = StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP; - - return frame; -} - -StackFrame* StackwalkerX86::GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed) { - if (!memory_ || !stack) { - BPLOG(ERROR) << "Can't get caller frame without memory or stack"; - return NULL; - } - - const vector<StackFrame*> &frames = *stack->frames(); - StackFrameX86* last_frame = static_cast<StackFrameX86*>(frames.back()); - scoped_ptr<StackFrameX86> new_frame; - - // If the resolver has Windows stack walking information, use that. - WindowsFrameInfo* windows_frame_info - = frame_symbolizer_->FindWindowsFrameInfo(last_frame); - if (windows_frame_info) - new_frame.reset(GetCallerByWindowsFrameInfo(frames, windows_frame_info, - stack_scan_allowed)); - - // If the resolver has DWARF CFI information, use that. - if (!new_frame.get()) { - CFIFrameInfo* cfi_frame_info = - frame_symbolizer_->FindCFIFrameInfo(last_frame); - if (cfi_frame_info) - new_frame.reset(GetCallerByCFIFrameInfo(frames, cfi_frame_info)); - } - - // Otherwise, hope that the program was using a traditional frame structure. - if (!new_frame.get()) - new_frame.reset(GetCallerByEBPAtBase(frames, stack_scan_allowed)); - - // If nothing worked, tell the caller. - if (!new_frame.get()) - return NULL; - - // Treat an instruction address of 0 as end-of-stack. - if (new_frame->context.eip == 0) - return NULL; - - // If the new stack pointer is at a lower address than the old, then - // that's clearly incorrect. Treat this as end-of-stack to enforce - // progress and avoid infinite loops. - if (new_frame->context.esp <= last_frame->context.esp) - return NULL; - - // new_frame->context.eip is the return address, which is the instruction - // after the CALL that caused us to arrive at the callee. Set - // new_frame->instruction to one less than that, so it points within the - // CALL instruction. See StackFrame::instruction for details, and - // StackFrameAMD64::ReturnAddress. - new_frame->instruction = new_frame->context.eip - 1; - - return new_frame.release(); -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h deleted file mode 100644 index 0659a13bf..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86.h +++ /dev/null @@ -1,117 +0,0 @@ -// -*- mode: c++ -*- - -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// stackwalker_x86.h: x86-specific stackwalker. -// -// Provides stack frames given x86 register context and a memory region -// corresponding to an x86 stack. -// -// Author: Mark Mentovai - - -#ifndef PROCESSOR_STACKWALKER_X86_H__ -#define PROCESSOR_STACKWALKER_X86_H__ - -#include <vector> - -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/stackwalker.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/cfi_frame_info.h" - -namespace google_breakpad { - -class CodeModules; - - -class StackwalkerX86 : public Stackwalker { - public: - // context is an x86 context object that gives access to x86-specific - // register state corresponding to the innermost called frame to be - // included in the stack. The other arguments are passed directly through - // to the base Stackwalker constructor. - StackwalkerX86(const SystemInfo* system_info, - const MDRawContextX86* context, - MemoryRegion* memory, - const CodeModules* modules, - StackFrameSymbolizer* frame_symbolizer); - - private: - // A STACK CFI-driven frame walker for the X86. - typedef SimpleCFIWalker<uint32_t, MDRawContextX86> CFIWalker; - - // Implementation of Stackwalker, using x86 context (%ebp, %esp, %eip) and - // stack conventions (saved %ebp at [%ebp], saved %eip at 4[%ebp], or - // alternate conventions as guided by any WindowsFrameInfo available for the - // code in question.). - virtual StackFrame* GetContextFrame(); - virtual StackFrame* GetCallerFrame(const CallStack* stack, - bool stack_scan_allowed); - - // Use windows_frame_info (derived from STACK WIN and FUNC records) - // to construct the frame that called frames.back(). The caller - // takes ownership of the returned frame. Return NULL on failure. - StackFrameX86* GetCallerByWindowsFrameInfo( - const vector<StackFrame*> &frames, - WindowsFrameInfo* windows_frame_info, - bool stack_scan_allowed); - - // Use cfi_frame_info (derived from STACK CFI records) to construct - // the frame that called frames.back(). The caller takes ownership - // of the returned frame. Return NULL on failure. - StackFrameX86* GetCallerByCFIFrameInfo(const vector<StackFrame*> &frames, - CFIFrameInfo* cfi_frame_info); - - // Assuming a traditional frame layout --- where the caller's %ebp - // has been pushed just after the return address and the callee's - // %ebp points to the saved %ebp --- construct the frame that called - // frames.back(). The caller takes ownership of the returned frame. - // Return NULL on failure. - StackFrameX86* GetCallerByEBPAtBase(const vector<StackFrame*> &frames, - bool stack_scan_allowed); - - // Stores the CPU context corresponding to the innermost stack frame to - // be returned by GetContextFrame. - const MDRawContextX86* context_; - - // Our register map, for cfi_walker_. - static const CFIWalker::RegisterSet cfi_register_map_[]; - - // Our CFI frame walker. - const CFIWalker cfi_walker_; -}; - - -} // namespace google_breakpad - - -#endif // PROCESSOR_STACKWALKER_X86_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc deleted file mode 100644 index d4c61c8c4..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/stackwalker_x86_unittest.cc +++ /dev/null @@ -1,2128 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// stackwalker_x86_unittest.cc: Unit tests for StackwalkerX86 class. - -#include <string> -#include <vector> - -#include "breakpad_googletest_includes.h" -#include "common/test_assembler.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/minidump_format.h" -#include "google_breakpad/processor/basic_source_line_resolver.h" -#include "google_breakpad/processor/call_stack.h" -#include "google_breakpad/processor/code_module.h" -#include "google_breakpad/processor/source_line_resolver_interface.h" -#include "google_breakpad/processor/stack_frame_cpu.h" -#include "processor/stackwalker_unittest_utils.h" -#include "processor/stackwalker_x86.h" -#include "processor/windows_frame_info.h" - -using google_breakpad::BasicSourceLineResolver; -using google_breakpad::CallStack; -using google_breakpad::CodeModule; -using google_breakpad::StackFrameSymbolizer; -using google_breakpad::StackFrame; -using google_breakpad::StackFrameX86; -using google_breakpad::Stackwalker; -using google_breakpad::StackwalkerX86; -using google_breakpad::SystemInfo; -using google_breakpad::WindowsFrameInfo; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Label; -using google_breakpad::test_assembler::Section; -using std::vector; -using testing::_; -using testing::AnyNumber; -using testing::Return; -using testing::SetArgumentPointee; -using testing::Test; - -class StackwalkerX86Fixture { - public: - StackwalkerX86Fixture() - : stack_section(kLittleEndian), - // Give the two modules reasonable standard locations and names - // for tests to play with. - module1(0x40000000, 0x10000, "module1", "version1"), - module2(0x50000000, 0x10000, "module2", "version2"), - module3(0x771d0000, 0x180000, "module3", "version3"), - module4(0x75f90000, 0x46000, "module4", "version4"), - module5(0x75730000, 0x110000, "module5", "version5"), - module6(0x647f0000, 0x1ba8000, "module6", "version6") { - // Identify the system as a Linux system. - system_info.os = "Linux"; - system_info.os_short = "linux"; - system_info.os_version = "Salacious Skink"; - system_info.cpu = "x86"; - system_info.cpu_info = ""; - - // Put distinctive values in the raw CPU context. - BrandContext(&raw_context); - - // Create some modules with some stock debugging information. - modules.Add(&module1); - modules.Add(&module2); - modules.Add(&module3); - modules.Add(&module4); - modules.Add(&module5); - modules.Add(&module6); - - // By default, none of the modules have symbol info; call - // SetModuleSymbols to override this. - EXPECT_CALL(supplier, GetCStringSymbolData(_, _, _, _, _)) - .WillRepeatedly(Return(MockSymbolSupplier::NOT_FOUND)); - - // Avoid GMOCK WARNING "Uninteresting mock function call - returning - // directly" for FreeSymbolData(). - EXPECT_CALL(supplier, FreeSymbolData(_)).Times(AnyNumber()); - - // Reset max_frames_scanned since it's static. - Stackwalker::set_max_frames_scanned(1024); - } - - // Set the Breakpad symbol information that supplier should return for - // MODULE to INFO. - void SetModuleSymbols(MockCodeModule *module, const string &info) { - size_t buffer_size; - char *buffer = supplier.CopySymbolDataAndOwnTheCopy(info, &buffer_size); - EXPECT_CALL(supplier, GetCStringSymbolData(module, &system_info, _, _, _)) - .WillRepeatedly(DoAll(SetArgumentPointee<3>(buffer), - SetArgumentPointee<4>(buffer_size), - Return(MockSymbolSupplier::FOUND))); - } - - // Populate stack_region with the contents of stack_section. Use - // stack_section.start() as the region's starting address. - void RegionFromSection() { - string contents; - ASSERT_TRUE(stack_section.GetContents(&contents)); - stack_region.Init(stack_section.start().Value(), contents); - } - - // Fill RAW_CONTEXT with pseudo-random data, for round-trip checking. - void BrandContext(MDRawContextX86 *raw_context) { - uint8_t x = 173; - for (size_t i = 0; i < sizeof(*raw_context); i++) - reinterpret_cast<uint8_t *>(raw_context)[i] = (x += 17); - } - - SystemInfo system_info; - MDRawContextX86 raw_context; - Section stack_section; - MockMemoryRegion stack_region; - MockCodeModule module1; - MockCodeModule module2; - MockCodeModule module3; - MockCodeModule module4; - MockCodeModule module5; - MockCodeModule module6; - MockCodeModules modules; - MockSymbolSupplier supplier; - BasicSourceLineResolver resolver; - CallStack call_stack; - const vector<StackFrame *> *frames; -}; - -class SanityCheck: public StackwalkerX86Fixture, public Test { }; - -TEST_F(SanityCheck, NoResolver) { - stack_section.start() = 0x80000000; - stack_section.D32(0).D32(0); // end-of-stack marker - RegionFromSection(); - raw_context.eip = 0x40000200; - raw_context.ebp = 0x80000000; - - StackFrameSymbolizer frame_symbolizer(NULL, NULL); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - // This should succeed, even without a resolver or supplier. - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -class GetContextFrame: public StackwalkerX86Fixture, public Test { }; - -TEST_F(GetContextFrame, Simple) { - stack_section.start() = 0x80000000; - stack_section.D32(0).D32(0); // end-of-stack marker - RegionFromSection(); - raw_context.eip = 0x40000200; - raw_context.ebp = 0x80000000; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -// The stackwalker should be able to produce the context frame even -// without stack memory present. -TEST_F(GetContextFrame, NoStackMemory) { - raw_context.eip = 0x40000200; - raw_context.ebp = 0x80000000; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, NULL, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); - // Check that the values from the original raw context made it - // through to the context in the stack frame. - EXPECT_EQ(0, memcmp(&raw_context, &frame->context, sizeof(raw_context))); -} - -class GetCallerFrame: public StackwalkerX86Fixture, public Test { - protected: - void IPAddressIsNotInKnownModuleTestImpl(bool has_corrupt_symbols); -}; - -// Walk a traditional frame. A traditional frame saves the caller's -// %ebp just below the return address, and has its own %ebp pointing -// at the saved %ebp. -TEST_F(GetCallerFrame, Traditional) { - stack_section.start() = 0x80000000; - Label frame0_ebp, frame1_ebp; - stack_section - .Append(12, 0) // frame 0: space - .Mark(&frame0_ebp) // frame 0 %ebp points here - .D32(frame1_ebp) // frame 0: saved %ebp - .D32(0x40008679) // frame 0: return address - .Append(8, 0) // frame 1: space - .Mark(&frame1_ebp) // frame 1 %ebp points here - .D32(0) // frame 1: saved %ebp (stack end) - .D32(0); // frame 1: return address (stack end) - RegionFromSection(); - raw_context.eip = 0x4000c7a5; - raw_context.esp = stack_section.start().Value(); - raw_context.ebp = frame0_ebp.Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - EXPECT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x4000c7a5U, frame0->instruction); - EXPECT_EQ(0x4000c7a5U, frame0->context.eip); - EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); - EXPECT_EQ(NULL, frame0->windows_frame_info); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x40008679U, frame1->instruction + 1); - EXPECT_EQ(0x40008679U, frame1->context.eip); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(NULL, frame1->windows_frame_info); - } -} - -// Walk a traditional frame, but use a bogus %ebp value, forcing a scan -// of the stack for something that looks like a return address. -TEST_F(GetCallerFrame, TraditionalScan) { - stack_section.start() = 0x80000000; - Label frame1_ebp; - Label frame1_esp; - stack_section - // frame 0 - .D32(0xf065dc76) // locals area: - .D32(0x46ee2167) // garbage that doesn't look like - .D32(0xbab023ec) // a return address - .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan) - .D32(0x4000129d) // return address - // frame 1 - .Mark(&frame1_esp) - .Append(8, 0) // space - .Mark(&frame1_ebp) // %ebp points here - .D32(0) // saved %ebp (stack end) - .D32(0); // return address (stack end) - - RegionFromSection(); - raw_context.eip = 0x4000f49d; - raw_context.esp = stack_section.start().Value(); - // Make the frame pointer bogus, to make the stackwalker scan the stack - // for something that looks like a return address. - raw_context.ebp = 0xd43eed6e; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x4000f49dU, frame0->instruction); - EXPECT_EQ(0x4000f49dU, frame0->context.eip); - EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); - EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); - EXPECT_EQ(NULL, frame0->windows_frame_info); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x4000129dU, frame1->instruction + 1); - EXPECT_EQ(0x4000129dU, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(NULL, frame1->windows_frame_info); - } -} - -// Force scanning for a return address a long way down the stack -TEST_F(GetCallerFrame, TraditionalScanLongWay) { - stack_section.start() = 0x80000000; - Label frame1_ebp; - Label frame1_esp; - stack_section - // frame 0 - .D32(0xf065dc76) // locals area: - .D32(0x46ee2167) // garbage that doesn't look like - .D32(0xbab023ec) // a return address - .Append(20 * 4, 0) // a bunch of space - .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan) - .D32(0x4000129d) // return address - // frame 1 - .Mark(&frame1_esp) - .Append(8, 0) // space - .Mark(&frame1_ebp) // %ebp points here - .D32(0) // saved %ebp (stack end) - .D32(0); // return address (stack end) - - RegionFromSection(); - raw_context.eip = 0x4000f49d; - raw_context.esp = stack_section.start().Value(); - // Make the frame pointer bogus, to make the stackwalker scan the stack - // for something that looks like a return address. - raw_context.ebp = 0xd43eed6e; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x4000f49dU, frame0->instruction); - EXPECT_EQ(0x4000f49dU, frame0->context.eip); - EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); - EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); - EXPECT_EQ(NULL, frame0->windows_frame_info); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x4000129dU, frame1->instruction + 1); - EXPECT_EQ(0x4000129dU, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(NULL, frame1->windows_frame_info); - } -} - -// Test that set_max_frames_scanned prevents using stack scanning -// to find caller frames. -TEST_F(GetCallerFrame, ScanningNotAllowed) { - stack_section.start() = 0x80000000; - Label frame1_ebp; - stack_section - // frame 0 - .D32(0xf065dc76) // locals area: - .D32(0x46ee2167) // garbage that doesn't look like - .D32(0xbab023ec) // a return address - .D32(frame1_ebp) // saved %ebp (%ebp fails to point here, forcing scan) - .D32(0x4000129d) // return address - // frame 1 - .Append(8, 0) // space - .Mark(&frame1_ebp) // %ebp points here - .D32(0) // saved %ebp (stack end) - .D32(0); // return address (stack end) - - RegionFromSection(); - raw_context.eip = 0x4000f49d; - raw_context.esp = stack_section.start().Value(); - // Make the frame pointer bogus, to make the stackwalker scan the stack - // for something that looks like a return address. - raw_context.ebp = 0xd43eed6e; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - Stackwalker::set_max_frames_scanned(0); - - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module1", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(1U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x4000f49dU, frame0->instruction); - EXPECT_EQ(0x4000f49dU, frame0->context.eip); - EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); - EXPECT_EQ(0xd43eed6eU, frame0->context.ebp); - EXPECT_EQ(NULL, frame0->windows_frame_info); - } -} - -// Use Windows frame data (a "STACK WIN 4" record, from a -// FrameTypeFrameData DIA record) to walk a stack frame. -TEST_F(GetCallerFrame, WindowsFrameData) { - SetModuleSymbols(&module1, - "STACK WIN 4 aa85 176 0 0 4 10 4 0 1" - " $T2 $esp .cbSavedRegs + =" - " $T0 .raSearchStart =" - " $eip $T0 ^ =" - " $esp $T0 4 + =" - " $ebx $T2 4 - ^ =" - " $edi $T2 8 - ^ =" - " $esi $T2 12 - ^ =" - " $ebp $T2 16 - ^ =\n"); - Label frame1_esp, frame1_ebp; - stack_section.start() = 0x80000000; - stack_section - // frame 0 - .D32(frame1_ebp) // saved regs: %ebp - .D32(0xa7120d1a) // %esi - .D32(0x630891be) // %edi - .D32(0x9068a878) // %ebx - .D32(0xa08ea45f) // locals: unused - .D32(0x40001350) // return address - // frame 1 - .Mark(&frame1_esp) - .Append(12, 0) // empty space - .Mark(&frame1_ebp) - .D32(0) // saved %ebp (stack end) - .D32(0); // saved %eip (stack end) - - RegionFromSection(); - raw_context.eip = 0x4000aa85; - raw_context.esp = stack_section.start().Value(); - raw_context.ebp = 0xf052c1de; // should not be needed to walk frame - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x4000aa85U, frame0->instruction); - EXPECT_EQ(0x4000aa85U, frame0->context.eip); - EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); - EXPECT_EQ(0xf052c1deU, frame0->context.ebp); - EXPECT_TRUE(frame0->windows_frame_info != NULL); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP - | StackFrameX86::CONTEXT_VALID_EBX - | StackFrameX86::CONTEXT_VALID_ESI - | StackFrameX86::CONTEXT_VALID_EDI), - frame1->context_validity); - EXPECT_EQ(0x40001350U, frame1->instruction + 1); - EXPECT_EQ(0x40001350U, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(0x9068a878U, frame1->context.ebx); - EXPECT_EQ(0xa7120d1aU, frame1->context.esi); - EXPECT_EQ(0x630891beU, frame1->context.edi); - EXPECT_EQ(NULL, frame1->windows_frame_info); - } -} - -// Use Windows frame data (a "STACK WIN 4" record, from a -// FrameTypeFrameData DIA record) to walk a stack frame where the stack -// is aligned and we must search -TEST_F(GetCallerFrame, WindowsFrameDataAligned) { - SetModuleSymbols(&module1, - "STACK WIN 4 aa85 176 0 0 4 4 8 0 1" - " $T1 .raSearch =" - " $T0 $T1 4 - 8 @ =" - " $ebp $T1 4 - ^ =" - " $eip $T1 ^ =" - " $esp $T1 4 + ="); - Label frame0_esp, frame0_ebp; - Label frame1_esp, frame1_ebp; - stack_section.start() = 0x80000000; - stack_section - // frame 0 - .Mark(&frame0_esp) - .D32(0x0ffa0ffa) // unused saved register - .D32(0xdeaddead) // locals - .D32(0xbeefbeef) - .D32(0) // 8-byte alignment - .Mark(&frame0_ebp) - .D32(frame1_ebp) // saved %ebp - .D32(0x5000129d) // return address - // frame 1 - .Mark(&frame1_esp) - .D32(0x1) // parameter - .Mark(&frame1_ebp) - .D32(0) // saved %ebp (stack end) - .D32(0); // saved %eip (stack end) - - RegionFromSection(); - raw_context.eip = 0x4000aa85; - raw_context.esp = frame0_esp.Value(); - raw_context.ebp = frame0_ebp.Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(1U, modules_without_symbols.size()); - ASSERT_EQ("module2", modules_without_symbols[0]->debug_file()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x4000aa85U, frame0->instruction); - EXPECT_EQ(0x4000aa85U, frame0->context.eip); - EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); - EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); - EXPECT_TRUE(frame0->windows_frame_info != NULL); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x5000129dU, frame1->instruction + 1); - EXPECT_EQ(0x5000129dU, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(NULL, frame1->windows_frame_info); - } -} - -// Use Windows frame data (a "STACK WIN 4" record, from a -// FrameTypeFrameData DIA record) to walk a frame, and depend on the -// parameter size from the callee as well. -TEST_F(GetCallerFrame, WindowsFrameDataParameterSize) { - SetModuleSymbols(&module1, "FUNC 1000 100 c module1::wheedle\n"); - SetModuleSymbols(&module2, - // Note bogus parameter size in FUNC record; the stack walker - // should prefer the STACK WIN record, and see '4' below. - "FUNC aa85 176 beef module2::whine\n" - "STACK WIN 4 aa85 176 0 0 4 10 4 0 1" - " $T2 $esp .cbLocals + .cbSavedRegs + =" - " $T0 .raSearchStart =" - " $eip $T0 ^ =" - " $esp $T0 4 + =" - " $ebp $T0 20 - ^ =" - " $ebx $T0 8 - ^ =\n"); - Label frame0_esp, frame0_ebp; - Label frame1_esp; - Label frame2_esp, frame2_ebp; - stack_section.start() = 0x80000000; - stack_section - // frame 0, in module1::wheedle. Traditional frame. - .Mark(&frame0_esp) - .Append(16, 0) // frame space - .Mark(&frame0_ebp) - .D32(0x6fa902e0) // saved %ebp. Not a frame pointer. - .D32(0x5000aa95) // return address, in module2::whine - // frame 1, in module2::whine. FrameData frame. - .Mark(&frame1_esp) - .D32(0xbaa0cb7a) // argument 3 passed to module1::wheedle - .D32(0xbdc92f9f) // argument 2 - .D32(0x0b1d8442) // argument 1 - .D32(frame2_ebp) // saved %ebp - .D32(0xb1b90a15) // unused - .D32(0xf18e072d) // unused - .D32(0x2558c7f3) // saved %ebx - .D32(0x0365e25e) // unused - .D32(0x2a179e38) // return address; $T0 points here - // frame 2, in no module - .Mark(&frame2_esp) - .Append(12, 0) // empty space - .Mark(&frame2_ebp) - .D32(0) // saved %ebp (stack end) - .D32(0); // saved %eip (stack end) - - RegionFromSection(); - raw_context.eip = 0x40001004; // in module1::wheedle - raw_context.esp = stack_section.start().Value(); - raw_context.ebp = frame0_ebp.Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(3U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x40001004U, frame0->instruction); - EXPECT_EQ(0x40001004U, frame0->context.eip); - EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); - EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); - EXPECT_EQ(&module1, frame0->module); - EXPECT_EQ("module1::wheedle", frame0->function_name); - EXPECT_EQ(0x40001000U, frame0->function_base); - // The FUNC record for module1::wheedle should have produced a - // WindowsFrameInfo structure with only the parameter size valid. - ASSERT_TRUE(frame0->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, - frame0->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_UNKNOWN, - frame0->windows_frame_info->type_); - EXPECT_EQ(12U, frame0->windows_frame_info->parameter_size); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_FP, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x5000aa95U, frame1->instruction + 1); - EXPECT_EQ(0x5000aa95U, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(0x6fa902e0U, frame1->context.ebp); - EXPECT_EQ(&module2, frame1->module); - EXPECT_EQ("module2::whine", frame1->function_name); - EXPECT_EQ(0x5000aa85U, frame1->function_base); - ASSERT_TRUE(frame1->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame1->windows_frame_info->type_); - // This should not see the 0xbeef parameter size from the FUNC - // record, but should instead see the STACK WIN record. - EXPECT_EQ(4U, frame1->windows_frame_info->parameter_size); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP - | StackFrameX86::CONTEXT_VALID_EBX), - frame2->context_validity); - EXPECT_EQ(0x2a179e38U, frame2->instruction + 1); - EXPECT_EQ(0x2a179e38U, frame2->context.eip); - EXPECT_EQ(frame2_esp.Value(), frame2->context.esp); - EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp); - EXPECT_EQ(0x2558c7f3U, frame2->context.ebx); - EXPECT_EQ(NULL, frame2->module); - EXPECT_EQ(NULL, frame2->windows_frame_info); - } -} - -// Use Windows frame data (a "STACK WIN 4" record, from a -// FrameTypeFrameData DIA record) to walk a stack frame, where the -// expression fails to yield both an $eip and an $ebp value, and the stack -// walker must scan. -TEST_F(GetCallerFrame, WindowsFrameDataScan) { - SetModuleSymbols(&module1, - "STACK WIN 4 c8c 111 0 0 4 10 4 0 1 bad program string\n"); - // Mark frame 1's PC as the end of the stack. - SetModuleSymbols(&module2, - "FUNC 7c38 accf 0 module2::function\n" - "STACK WIN 4 7c38 accf 0 0 4 10 4 0 1 $eip 0 = $ebp 0 =\n"); - Label frame1_esp; - stack_section.start() = 0x80000000; - stack_section - // frame 0 - .Append(16, 0x2a) // unused, garbage - .D32(0x50007ce9) // return address - // frame 1 - .Mark(&frame1_esp) - .Append(8, 0); // empty space - - RegionFromSection(); - raw_context.eip = 0x40000c9c; - raw_context.esp = stack_section.start().Value(); - raw_context.ebp = 0x2ae314cd; // should not be needed to walk frame - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x40000c9cU, frame0->instruction); - EXPECT_EQ(0x40000c9cU, frame0->context.eip); - EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); - EXPECT_EQ(0x2ae314cdU, frame0->context.ebp); - EXPECT_TRUE(frame0->windows_frame_info != NULL); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the walker - // does not actually fetch the EBP after a scan (forcing the next frame - // to be scanned as well). But let's grandfather the existing behavior in - // for now. - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x50007ce9U, frame1->instruction + 1); - EXPECT_EQ(0x50007ce9U, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_TRUE(frame1->windows_frame_info != NULL); - } -} - -// Use Windows frame data (a "STACK WIN 4" record, from a -// FrameTypeFrameData DIA record) to walk a stack frame, where the -// expression yields an $eip that falls outside of any module, and the -// stack walker must scan. -TEST_F(GetCallerFrame, WindowsFrameDataBadEIPScan) { - SetModuleSymbols(&module1, - "STACK WIN 4 6e6 e7 0 0 0 8 4 0 1" - // A traditional frame, actually. - " $eip $ebp 4 + ^ = $esp $ebp 8 + = $ebp $ebp ^ =\n"); - // Mark frame 1's PC as the end of the stack. - SetModuleSymbols(&module2, - "FUNC cfdb 8406 0 module2::function\n" - "STACK WIN 4 cfdb 8406 0 0 0 0 0 0 1 $eip 0 = $ebp 0 =\n"); - stack_section.start() = 0x80000000; - - // In this stack, the context's %ebp is pointing at the wrong place, so - // the stack walker needs to scan to find the return address, and then - // scan again to find the caller's saved %ebp. - Label frame0_ebp, frame1_ebp, frame1_esp; - stack_section - // frame 0 - .Append(8, 0x2a) // garbage - .Mark(&frame0_ebp) // frame 0 %ebp points here, but should point - // at *** below - // The STACK WIN record says that the following two values are - // frame 1's saved %ebp and return address, but the %ebp is wrong; - // they're garbage. The stack walker will scan for the right values. - .D32(0x3d937b2b) // alleged to be frame 1's saved %ebp - .D32(0x17847f5b) // alleged to be frame 1's return address - .D32(frame1_ebp) // frame 1's real saved %ebp; scan will find - .D32(0x2b2b2b2b) // first word of realigned register save area - // *** frame 0 %ebp ought to be pointing here - .D32(0x2c2c2c2c) // realigned locals area - .D32(0x5000d000) // frame 1's real saved %eip; scan will find - // Frame 1, in module2::function. The STACK WIN record describes - // this as the oldest frame, without referring to its contents, so - // we needn't to provide any actual data here. - .Mark(&frame1_esp) - .Mark(&frame1_ebp) // frame 1 %ebp points here - // A dummy value for frame 1's %ebp to point at. The scan recognizes the - // saved %ebp because it points to a valid word in the stack memory region. - .D32(0x2d2d2d2d); - - RegionFromSection(); - raw_context.eip = 0x40000700; - raw_context.esp = stack_section.start().Value(); - raw_context.ebp = frame0_ebp.Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x40000700U, frame0->instruction); - EXPECT_EQ(0x40000700U, frame0->context.eip); - EXPECT_EQ(stack_section.start().Value(), frame0->context.esp); - EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); - EXPECT_TRUE(frame0->windows_frame_info != NULL); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust); - // I'd argue that CONTEXT_VALID_EBP shouldn't be here, since the - // walker does not actually fetch the EBP after a scan (forcing the - // next frame to be scanned as well). But let's grandfather the existing - // behavior in for now. - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x5000d000U, frame1->instruction + 1); - EXPECT_EQ(0x5000d000U, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_TRUE(frame1->windows_frame_info != NULL); - } -} - -// Use Windows FrameTypeFPO data to walk a stack frame for a function that -// does not modify %ebp from the value it had in the caller. -TEST_F(GetCallerFrame, WindowsFPOUnchangedEBP) { - SetModuleSymbols(&module1, - // Note bogus parameter size in FUNC record; the walker - // should prefer the STACK WIN record, and see the '8' below. - "FUNC e8a8 100 feeb module1::discombobulated\n" - "STACK WIN 0 e8a8 100 0 0 8 4 10 0 0 0\n"); - Label frame0_esp; - Label frame1_esp, frame1_ebp; - stack_section.start() = 0x80000000; - stack_section - // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame. - .Mark(&frame0_esp) - // no outgoing parameters; this is the youngest frame. - .D32(0x7c521352) // four bytes of saved registers - .Append(0x10, 0x42) // local area - .D32(0x40009b5b) // return address, in module1, no function - // frame 1, in module1, no function. - .Mark(&frame1_esp) - .D32(0xf60ea7fc) // junk - .Mark(&frame1_ebp) - .D32(0) // saved %ebp (stack end) - .D32(0); // saved %eip (stack end) - - RegionFromSection(); - raw_context.eip = 0x4000e8b8; // in module1::whine - raw_context.esp = stack_section.start().Value(); - // Frame pointer unchanged from caller. - raw_context.ebp = frame1_ebp.Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x4000e8b8U, frame0->instruction); - EXPECT_EQ(0x4000e8b8U, frame0->context.eip); - EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); - // unchanged from caller - EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); - EXPECT_EQ(&module1, frame0->module); - EXPECT_EQ("module1::discombobulated", frame0->function_name); - EXPECT_EQ(0x4000e8a8U, frame0->function_base); - // The STACK WIN record for module1::discombobulated should have - // produced a fully populated WindowsFrameInfo structure. - ASSERT_TRUE(frame0->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, - frame0->windows_frame_info->type_); - EXPECT_EQ(0x10U, frame0->windows_frame_info->local_size); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x40009b5bU, frame1->instruction + 1); - EXPECT_EQ(0x40009b5bU, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(&module1, frame1->module); - EXPECT_EQ("", frame1->function_name); - EXPECT_EQ(NULL, frame1->windows_frame_info); - } -} - -// Use Windows FrameTypeFPO data to walk a stack frame for a function -// that uses %ebp for its own purposes, saving the value it had in the -// caller in the standard place in the saved register area. -TEST_F(GetCallerFrame, WindowsFPOUsedEBP) { - SetModuleSymbols(&module1, - // Note bogus parameter size in FUNC record; the walker - // should prefer the STACK WIN record, and see the '8' below. - "FUNC 9aa8 e6 abbe module1::RaisedByTheAliens\n" - "STACK WIN 0 9aa8 e6 a 0 10 8 4 0 0 1\n"); - Label frame0_esp; - Label frame1_esp, frame1_ebp; - stack_section.start() = 0x80000000; - stack_section - // frame 0, in module1::wheedle. FrameTypeFPO (STACK WIN 0) frame. - .Mark(&frame0_esp) - // no outgoing parameters; this is the youngest frame. - .D32(frame1_ebp) // saved register area: saved %ebp - .D32(0xb68bd5f9) // saved register area: something else - .D32(0xd25d05fc) // local area - .D32(0x4000debe) // return address, in module1, no function - // frame 1, in module1, no function. - .Mark(&frame1_esp) - .D32(0xf0c9a974) // junk - .Mark(&frame1_ebp) - .D32(0) // saved %ebp (stack end) - .D32(0); // saved %eip (stack end) - - RegionFromSection(); - raw_context.eip = 0x40009ab8; // in module1::RaisedByTheAliens - raw_context.esp = stack_section.start().Value(); - // RaisedByTheAliens uses %ebp for its own mysterious purposes. - raw_context.ebp = 0xecbdd1a5; - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x40009ab8U, frame0->instruction); - EXPECT_EQ(0x40009ab8U, frame0->context.eip); - EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); - EXPECT_EQ(0xecbdd1a5, frame0->context.ebp); - EXPECT_EQ(&module1, frame0->module); - EXPECT_EQ("module1::RaisedByTheAliens", frame0->function_name); - EXPECT_EQ(0x40009aa8U, frame0->function_base); - // The STACK WIN record for module1::RaisedByTheAliens should have - // produced a fully populated WindowsFrameInfo structure. - ASSERT_TRUE(frame0->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, - frame0->windows_frame_info->type_); - EXPECT_EQ("", frame0->windows_frame_info->program_string); - EXPECT_TRUE(frame0->windows_frame_info->allocates_base_pointer); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x4000debeU, frame1->instruction + 1); - EXPECT_EQ(0x4000debeU, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(&module1, frame1->module); - EXPECT_EQ("", frame1->function_name); - EXPECT_EQ(NULL, frame1->windows_frame_info); - } -} - -// This is a regression unit test which covers a bug which has to do with -// FPO-optimized Windows system call stubs in the context frame. There is -// a more recent Windows system call dispatch mechanism which differs from -// the one which is being tested here. The newer system call dispatch -// mechanism creates an extra context frame (KiFastSystemCallRet). -TEST_F(GetCallerFrame, WindowsFPOSystemCall) { - SetModuleSymbols(&module3, // ntdll.dll - "PUBLIC 1f8ac c ZwWaitForSingleObject\n" - "STACK WIN 0 1f8ac 1b 0 0 c 0 0 0 0 0\n"); - SetModuleSymbols(&module4, // kernelbase.dll - "PUBLIC 109f9 c WaitForSingleObjectEx\n" - "PUBLIC 36590 0 _except_handler4\n" - "STACK WIN 4 109f9 df c 0 c c 48 0 1 $T0 $ebp = $eip " - "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " - "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n" - "STACK WIN 4 36590 154 17 0 10 0 14 0 1 $T0 $ebp = $eip " - "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 " - ".cbSavedRegs - = $P $T0 8 + .cbParams + =\n"); - SetModuleSymbols(&module5, // kernel32.dll - "PUBLIC 11136 8 WaitForSingleObject\n" - "PUBLIC 11151 c WaitForSingleObjectExImplementation\n" - "STACK WIN 4 11136 16 5 0 8 0 0 0 1 $T0 $ebp = $eip " - "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " - "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n" - "STACK WIN 4 11151 7a 5 0 c 0 0 0 1 $T0 $ebp = $eip " - "$T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " - "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =\n"); - SetModuleSymbols(&module6, // chrome.dll - "FILE 7038 some_file_name.h\n" - "FILE 839776 some_file_name.cc\n" - "FUNC 217fda 17 4 function_217fda\n" - "217fda 4 102 839776\n" - "FUNC 217ff1 a 4 function_217ff1\n" - "217ff1 0 594 7038\n" - "217ff1 a 596 7038\n" - "STACK WIN 0 217ff1 a 0 0 4 0 0 0 0 0\n"); - - Label frame0_esp, frame1_esp; - Label frame1_ebp, frame2_ebp, frame3_ebp; - stack_section.start() = 0x002ff290; - stack_section - .Mark(&frame0_esp) - .D32(0x771ef8c1) // EIP in frame 0 (system call) - .D32(0x75fa0a91) // return address of frame 0 - .Mark(&frame1_esp) - .D32(0x000017b0) // args to child - .D32(0x00000000) - .D32(0x002ff2d8) - .D32(0x88014a2e) - .D32(0x002ff364) - .D32(0x000017b0) - .D32(0x00000000) - .D32(0x00000024) - .D32(0x00000001) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x9e3b9800) - .D32(0xfffffff7) - .D32(0x00000000) - .D32(0x002ff2a4) - .D32(0x64a07ff1) // random value to be confused with a return address - .D32(0x002ff8dc) - .D32(0x75fc6590) // random value to be confused with a return address - .D32(0xfdd2c6ea) - .D32(0x00000000) - .Mark(&frame1_ebp) - .D32(frame2_ebp) // Child EBP - .D32(0x75741194) // return address of frame 1 - .D32(0x000017b0) // args to child - .D32(0x0036ee80) - .D32(0x00000000) - .D32(0x65bc7d14) - .Mark(&frame2_ebp) - .D32(frame3_ebp) // Child EBP - .D32(0x75741148) // return address of frame 2 - .D32(0x000017b0) // args to child - .D32(0x0036ee80) - .D32(0x00000000) - .Mark(&frame3_ebp) - .D32(0) // saved %ebp (stack end) - .D32(0); // saved %eip (stack end) - - RegionFromSection(); - raw_context.eip = 0x771ef8c1; // in ntdll::ZwWaitForSingleObject - raw_context.esp = stack_section.start().Value(); - ASSERT_TRUE(raw_context.esp == frame0_esp.Value()); - raw_context.ebp = frame1_ebp.Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - - ASSERT_EQ(4U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x771ef8c1U, frame0->instruction); - EXPECT_EQ(0x771ef8c1U, frame0->context.eip); - EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame0->context.ebp); - EXPECT_EQ(&module3, frame0->module); - EXPECT_EQ("ZwWaitForSingleObject", frame0->function_name); - // The STACK WIN record for module3!ZwWaitForSingleObject should have - // produced a fully populated WindowsFrameInfo structure. - ASSERT_TRUE(frame0->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FPO, - frame0->windows_frame_info->type_); - EXPECT_EQ("", frame0->windows_frame_info->program_string); - EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP - | StackFrameX86::CONTEXT_VALID_ESP - | StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x75fa0a91U, frame1->instruction + 1); - EXPECT_EQ(0x75fa0a91U, frame1->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(&module4, frame1->module); - EXPECT_EQ("WaitForSingleObjectEx", frame1->function_name); - // The STACK WIN record for module4!WaitForSingleObjectEx should have - // produced a fully populated WindowsFrameInfo structure. - ASSERT_TRUE(frame1->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame1->windows_frame_info->type_); - EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L " - "$T0 .cbSavedRegs - = $P $T0 8 + .cbParams + =", - frame1->windows_frame_info->program_string); - EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer); - } -} - -// Scan the stack for a better return address and potentially skip frames -// when the calculated return address is not in a known module. Note, that -// the span of this scan is somewhat arbitrarily limited to 160 search words -// for the context frame and 40 search words (pointers) for the other frames: -// const int kRASearchWords = 40; -// This means that frames can be skipped only when their size is relatively -// small: smaller than 4 * kRASearchWords * sizeof(InstructionType) -TEST_F(GetCallerFrame, ReturnAddressIsNotInKnownModule) { - MockCodeModule msvcrt_dll(0x77be0000, 0x58000, "msvcrt.dll", "version1"); - SetModuleSymbols(&msvcrt_dll, // msvcrt.dll - "PUBLIC 38180 0 wcsstr\n" - "STACK WIN 4 38180 61 10 0 8 0 0 0 1 $T0 $ebp = $eip $T0 " - "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " - "- = $P $T0 4 + .cbParams + =\n"); - - MockCodeModule kernel32_dll(0x7c800000, 0x103000, "kernel32.dll", "version1"); - SetModuleSymbols(&kernel32_dll, // kernel32.dll - "PUBLIC efda 8 FindNextFileW\n" - "STACK WIN 4 efda 1bb c 0 8 8 3c 0 1 $T0 $ebp = $eip $T0 " - "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " - "- = $P $T0 4 + .cbParams + =\n"); - - MockCodeModule chrome_dll(0x1c30000, 0x28C8000, "chrome.dll", "version1"); - SetModuleSymbols(&chrome_dll, // chrome.dll - "FUNC e3cff 4af 0 file_util::FileEnumerator::Next()\n" - "e3cff 1a 711 2505\n" - "STACK WIN 4 e3cff 4af 20 0 4 c 94 0 1 $T1 .raSearch = " - "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp " - "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 " - "$T0 160 - ^ =\n"); - - // Create some modules with some stock debugging information. - MockCodeModules local_modules; - local_modules.Add(&msvcrt_dll); - local_modules.Add(&kernel32_dll); - local_modules.Add(&chrome_dll); - - Label frame0_esp; - Label frame0_ebp; - Label frame1_ebp; - Label frame2_ebp; - Label frame3_ebp; - - stack_section.start() = 0x0932f2d0; - stack_section - .Mark(&frame0_esp) - .D32(0x0764e000) - .D32(0x0764e068) - .Mark(&frame0_ebp) - .D32(frame1_ebp) // Child EBP - .D32(0x001767a0) // return address of frame 0 - // Not in known module - .D32(0x0764e0c6) - .D32(0x001bb1b8) - .D32(0x0764e068) - .D32(0x00000003) - .D32(0x0764e068) - .D32(0x00000003) - .D32(0x07578828) - .D32(0x0764e000) - .D32(0x00000000) - .D32(0x001c0010) - .D32(0x0764e0c6) - .Mark(&frame1_ebp) - .D32(frame2_ebp) // Child EBP - .D32(0x7c80f10f) // return address of frame 1 - // inside kernel32!FindNextFileW - .D32(0x000008f8) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x0932f34c) - .D32(0x0764e000) - .D32(0x00001000) - .D32(0x00000000) - .D32(0x00000001) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x0932f6a8) - .D32(0x00000000) - .D32(0x0932f6d8) - .D32(0x00000000) - .D32(0x000000d6) - .D32(0x0764e000) - .D32(0x7ff9a000) - .D32(0x0932f3fc) - .D32(0x00000001) - .D32(0x00000001) - .D32(0x07578828) - .D32(0x0000002e) - .D32(0x0932f340) - .D32(0x0932eef4) - .D32(0x0932ffdc) - .D32(0x7c839ad8) - .D32(0x7c80f0d8) - .D32(0x00000000) - .Mark(&frame2_ebp) - .D32(frame3_ebp) // Child EBP - .D32(0x01d13f91) // return address of frame 2 - // inside chrome_dll!file_util::FileEnumerator::Next - .D32(0x07578828) - .D32(0x0932f6ac) - .D32(0x0932f9c4) - .D32(0x0932f9b4) - .D32(0x00000000) - .D32(0x00000003) - .D32(0x0932f978) - .D32(0x01094330) - .D32(0x00000000) - .D32(0x00000001) - .D32(0x01094330) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x07f30000) - .D32(0x01c3ba17) - .D32(0x08bab840) - .D32(0x07f31580) - .D32(0x00000000) - .D32(0x00000007) - .D32(0x0932f940) - .D32(0x0000002e) - .D32(0x0932f40c) - .D32(0x01d13b53) - .D32(0x0932f958) - .D32(0x00000001) - .D32(0x00000007) - .D32(0x0932f940) - .D32(0x0000002e) - .D32(0x00000000) - .D32(0x0932f6ac) - .D32(0x01e13ef0) - .D32(0x00000001) - .D32(0x00000007) - .D32(0x0932f958) - .D32(0x08bab840) - .D32(0x0932f9b4) - .D32(0x00000000) - .D32(0x0932f9b4) - .D32(0x000000a7) - .D32(0x000000a7) - .D32(0x0932f998) - .D32(0x579627a2) - .Mark(&frame3_ebp) - .D32(0) // saved %ebp (stack end) - .D32(0); // saved %eip (stack end) - - RegionFromSection(); - raw_context.eip = 0x77c181cd; // inside msvcrt!wcsstr - raw_context.esp = frame0_esp.Value(); - raw_context.ebp = frame0_ebp.Value(); - // sanity - ASSERT_TRUE(raw_context.esp == stack_section.start().Value()); - ASSERT_TRUE(raw_context.ebp == stack_section.start().Value() + 8); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, - &local_modules, &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - - ASSERT_EQ(3U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(0x77c181cdU, frame0->instruction); - EXPECT_EQ(0x77c181cdU, frame0->context.eip); - EXPECT_EQ(frame0_esp.Value(), frame0->context.esp); - EXPECT_EQ(frame0_ebp.Value(), frame0->context.ebp); - EXPECT_EQ(&msvcrt_dll, frame0->module); - EXPECT_EQ("wcsstr", frame0->function_name); - ASSERT_TRUE(frame0->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame0->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame0->windows_frame_info->type_); - EXPECT_EQ("$T0 $ebp = $eip $T0 " - "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " - "- = $P $T0 4 + .cbParams + =", - frame0->windows_frame_info->program_string); - // It has program string, so allocates_base_pointer is not expected - EXPECT_FALSE(frame0->windows_frame_info->allocates_base_pointer); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI_SCAN, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(0x7c80f10fU, frame1->instruction + 1); - EXPECT_EQ(0x7c80f10fU, frame1->context.eip); - // frame 1 was skipped, so intead of frame1_ebp compare with frame2_ebp. - EXPECT_EQ(frame2_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(&kernel32_dll, frame1->module); - EXPECT_EQ("FindNextFileW", frame1->function_name); - ASSERT_TRUE(frame1->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame1->windows_frame_info->type_); - EXPECT_EQ("$T0 $ebp = $eip $T0 " - "4 + ^ = $ebp $T0 ^ = $esp $T0 8 + = $L $T0 .cbSavedRegs " - "- = $P $T0 4 + .cbParams + =", - frame1->windows_frame_info->program_string); - EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP), - frame2->context_validity); - EXPECT_EQ(0x01d13f91U, frame2->instruction + 1); - EXPECT_EQ(0x01d13f91U, frame2->context.eip); - // frame 1 was skipped, so intead of frame2_ebp compare with frame3_ebp. - EXPECT_EQ(frame3_ebp.Value(), frame2->context.ebp); - EXPECT_EQ(&chrome_dll, frame2->module); - EXPECT_EQ("file_util::FileEnumerator::Next()", frame2->function_name); - ASSERT_TRUE(frame2->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame2->windows_frame_info->type_); - EXPECT_EQ("$T1 .raSearch = " - "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp " - "$T1 4 + = $20 $T0 152 - ^ = $23 $T0 156 - ^ = $24 " - "$T0 160 - ^ =", - frame2->windows_frame_info->program_string); - EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer); - } -} - -// Test the .raSearchStart/.raSearch calculation when alignment operators are -// used in the program string. The current %ebp must be valid and it is the -// only reliable data point that can be used for that calculation. -TEST_F(GetCallerFrame, HandleAlignmentInProgramString) { - MockCodeModule chrome_dll(0x59630000, 0x19e3000, "chrome.dll", "version1"); - SetModuleSymbols(&chrome_dll, // chrome.dll - "FUNC 56422 50c 8 base::MessageLoop::RunTask" - "(base::PendingTask const &)\n" - "56422 e 458 4589\n" - "STACK WIN 4 56422 50c 11 0 8 c ac 0 1 $T1 .raSearch = $T0 " - "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = " - "$20 $T0 176 - ^ = $23 $T0 180 - ^ = $24 $T0 184 - ^ =\n" - "FUNC 55d34 34a 0 base::MessageLoop::DoWork()\n" - "55d34 11 596 4589\n" - "STACK WIN 4 55d34 34a 19 0 0 c 134 0 1 $T1 .raSearch = " - "$T0 $T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp " - "$T1 4 + = $20 $T0 312 - ^ = $23 $T0 316 - ^ = $24 $T0 " - "320 - ^ =\n" - "FUNC 55c39 fb 0 base::MessagePumpForIO::DoRunLoop()\n" - "55c39 d 518 19962\n" - "STACK WIN 4 55c39 fb d 0 0 c 34 0 1 $T1 .raSearch = $T0 " - "$T1 4 - 64 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + " - "= $20 $T0 56 - ^ = $23 $T0 60 - ^ = $24 $T0 64 - ^ =\n" - "FUNC 55bf0 49 4 base::MessagePumpWin::Run(base::" - "MessagePump::Delegate *)\n" - "55bf0 49 48 4724\n" - "STACK WIN 4 55bf0 49 c 0 4 0 10 0 1 $T0 $ebp = $eip $T0 4 " - "+ ^ = $ebp $T0 ^ = $esp $T0 8 + =\n" - "FUNC 165d de 4 malloc\n" - "165d 6 119 54\n" - "STACK WIN 4 165d de d 0 4 8 0 0 1 $T1 .raSearch = $T0 " - "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 " - "+ = $23 $T0 4 - ^ = $24 $T0 8 - ^ =\n" - "FUNC 55ac9 79 0 base::MessageLoop::RunInternal()\n" - "55ac9 d 427 4589\n" - "STACK WIN 4 55ac9 79 d 0 0 8 10 0 1 $T1 .raSearch = $T0 " - "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = " - "$23 $T0 20 - ^ = $24 $T0 24 - ^ =\n"); - - // Create some modules with some stock debugging information. - MockCodeModules local_modules; - local_modules.Add(&chrome_dll); - - Label frame0_esp; - Label frame0_ebp; - Label frame1_esp; - Label frame1_ebp; - Label frame2_esp; - Label frame2_ebp; - Label frame3_esp; - Label frame3_ebp; - - stack_section.start() = 0x046bfc80; - stack_section - .D32(0) - .Mark(&frame0_esp) - .D32(0x01e235a0) - .D32(0x00000000) - .D32(0x01e9f580) - .D32(0x01e9f580) - .D32(0x00000020) - .D32(0x00000000) - .D32(0x00463674) - .D32(0x00000020) - .D32(0x00000000) - .D32(0x046bfcd8) - .D32(0x046bfcd8) - .D32(0x0001204b) - .D32(0x00000000) - .D32(0xfdddb523) - .D32(0x00000000) - .D32(0x00000007) - .D32(0x00000040) - .D32(0x00000000) - .D32(0x59631693) // chrome_59630000!malloc+0x36 - .D32(0x01e9f580) - .D32(0x01e9f580) - .D32(0x046bfcf8) - .D32(0x77da6704) // ntdll!NtSetIoCompletion+0xc - .D32(0x046bfd4c) - .D32(0x59685bec) // chrome_59630000!base::MessageLoop::StartHistogrammer.. - .D32(0x01e235a0) - - .Mark(&frame0_ebp) - .D32(frame1_ebp) // Child EBP .D32(0x046bfd0c) - .D32(0x59685c2e) // Return address in - // chrome_59630000!base::MessagePumpWin::Run+0x3e - .Mark(&frame1_esp) - .D32(0x01e75a90) - .D32(0x046bfd4c) - .D32(0x01e75a90) - .D32(0x00000000) - .D32(0x00000300) - .D32(0x00000001) - - .Mark(&frame1_ebp) - .D32(frame2_ebp) // Child EBP .D32(0x046bfd30) - .D32(0x59685b3c) // Return address in - // chrome_59630000!base::MessageLoop::RunInternal+0x73 - .Mark(&frame2_esp) - .D32(0x01e75a90) - .D32(0x00000000) - .D32(0x046bfd4c) - .D32(0x59658123) // chrome_59630000!std::deque.. - .D32(0x046bfda0) - .D32(0x01e79d70) - .D32(0x046bfda0) - - .Mark(&frame2_ebp) // .D32(0x046bfd40) - .D32(0) // saved %ebp (stack end) - .D32(0); // saved %eip (stack end) - - RegionFromSection(); - raw_context.eip = 0x59685c46; // Context frame in - // base::MessagePumpForIO::DoRunLoop - raw_context.esp = frame0_esp.Value(); - raw_context.ebp = frame0_ebp.Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, - &local_modules, &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - - ASSERT_EQ(3U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame->context_validity); - EXPECT_EQ("base::MessagePumpForIO::DoRunLoop()", frame->function_name); - EXPECT_EQ(0x59685c46U, frame->instruction); - EXPECT_EQ(0x59685c46U, frame->context.eip); - EXPECT_EQ(frame0_esp.Value(), frame->context.esp); - EXPECT_EQ(frame0_ebp.Value(), frame->context.ebp); - EXPECT_EQ(&chrome_dll, frame->module); - ASSERT_TRUE(frame->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame->windows_frame_info->type_); - EXPECT_EQ("$T1 .raSearch = $T0 " - "$T1 4 - 64 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + " - "= $20 $T0 56 - ^ = $23 $T0 60 - ^ = $24 $T0 64 - ^ =", - frame->windows_frame_info->program_string); - EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP), - frame->context_validity); - EXPECT_EQ("base::MessagePumpWin::Run(base::MessagePump::Delegate *)", - frame->function_name); - EXPECT_EQ(1500011566U, frame->instruction + 1); - EXPECT_EQ(1500011566U, frame->context.eip); - EXPECT_EQ(frame1_esp.Value(), frame->context.esp); - EXPECT_EQ(frame1_ebp.Value(), frame->context.ebp); - EXPECT_EQ(&chrome_dll, frame->module); - ASSERT_TRUE(frame->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame->windows_frame_info->type_); - EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =", - frame->windows_frame_info->program_string); - EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame = static_cast<StackFrameX86 *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP), - frame->context_validity); - EXPECT_EQ("base::MessageLoop::RunInternal()", frame->function_name); - EXPECT_EQ(1500011324U, frame->instruction + 1); - EXPECT_EQ(1500011324U, frame->context.eip); - EXPECT_EQ(frame2_esp.Value(), frame->context.esp); - EXPECT_EQ(frame2_ebp.Value(), frame->context.ebp); - EXPECT_EQ(&chrome_dll, frame->module); - ASSERT_TRUE(frame->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame->windows_frame_info->type_); - EXPECT_EQ("$T1 .raSearch = $T0 " - "$T1 4 - 8 @ = $ebp $T1 4 - ^ = $eip $T1 ^ = $esp $T1 4 + = " - "$23 $T0 20 - ^ = $24 $T0 24 - ^ =", - frame->windows_frame_info->program_string); - EXPECT_FALSE(frame->windows_frame_info->allocates_base_pointer); - } -} - -// Scan the stack for a return address and potentially skip frames when the -// current IP address is not in a known module. Note, that that the span of -// this scan is limited to 120 search words for the context frame and 30 -// search words (pointers) for the other frames: -// const int kRASearchWords = 30; -void GetCallerFrame::IPAddressIsNotInKnownModuleTestImpl( - bool has_corrupt_symbols) { - MockCodeModule remoting_core_dll(0x54080000, 0x501000, "remoting_core.dll", - "version1"); - string symbols_func_section = - "FUNC 137214 17d 10 PK11_Verify\n" - "FUNC 15c834 37 14 nsc_ECDSAVerifyStub\n" - "FUNC 1611d3 91 14 NSC_Verify\n" - "FUNC 162ff7 60 4 sftk_SessionFromHandle\n"; - string symbols_stack_section = - "STACK WIN 4 137214 17d 9 0 10 0 10 0 1 $T0 $ebp = " - "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n" - "STACK WIN 4 15c834 37 6 0 14 0 18 0 1 $T0 $ebp = " - "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n" - "STACK WIN 4 1611d3 91 7 0 14 0 8 0 1 $T0 $ebp = " - "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n" - "STACK WIN 4 162ff7 60 5 0 4 0 0 0 1 $T0 $ebp = " - "$eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =\n"; - - string symbols = symbols_func_section; - if (has_corrupt_symbols) { - symbols.append(string(1, '\0')); // null terminator in the middle - symbols.append("\n"); - symbols.append("FUNC 1234\n" // invalid FUNC records - "FUNNC 1234\n" - "STACK WIN 4 1234 234 23 " // invalid STACK record - "23423423 234 23 234 234 " - "234 23 234 23 234 234 " - "234 234 234\n"); - } - symbols.append(symbols_stack_section); - SetModuleSymbols(&remoting_core_dll, symbols); - - // Create some modules with some stock debugging information. - MockCodeModules local_modules; - local_modules.Add(&remoting_core_dll); - - Label frame0_esp; - Label frame0_ebp; - Label frame1_ebp; - Label frame1_esp; - Label frame2_ebp; - Label frame2_esp; - Label frame3_ebp; - Label frame3_esp; - Label bogus_stack_location_1; - Label bogus_stack_location_2; - Label bogus_stack_location_3; - - stack_section.start() = 0x01a3ea28; - stack_section - .Mark(&frame0_esp) - .D32(bogus_stack_location_2) - .D32(bogus_stack_location_1) - .D32(0x042478e4) - .D32(bogus_stack_location_2) - .D32(0x00000000) - .D32(0x041f0420) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x00000040) - .D32(0x00000001) - .D32(0x00b7e0d0) - .D32(0x00000000) - .D32(0x00000040) - .D32(0x00000001) - .D32(0x00b7f570) - .Mark(&bogus_stack_location_1) - .D32(0x00000000) - .D32(0x00000040) - .D32(0x00000008) - .D32(0x04289530) - .D32(0x00000000) - .D32(0x00000040) - .D32(0x00000008) - .D32(0x00b7e910) - .D32(0x00000000) - .D32(0x00000040) - .D32(0x00000008) - .D32(0x00b7d998) - .D32(0x00000000) - .D32(0x00000040) - .D32(0x00000008) - .D32(0x00b7dec0) - .Mark(&bogus_stack_location_2) - .D32(0x00000000) - .D32(0x00000040) - .D32(0x00000008) - .D32(0x04289428) - .D32(0x00000000) - .D32(0x00000040) - .D32(0x00000008) - .D32(0x00b7f258) - .Mark(&bogus_stack_location_3) - .D32(0x00000000) - .D32(0x041f3560) - .D32(0x00000041) - .D32(0x00000020) - .D32(0xffffffff) - .Mark(&frame0_ebp) - .D32(frame1_ebp) // Child %ebp - .D32(0x541dc866) // return address of frame 0 - // inside remoting_core!nsc_ECDSAVerifyStub+0x32 - .Mark(&frame1_esp) - .D32(0x04247860) - .D32(0x01a3eaec) - .D32(0x01a3eaf8) - .D32(0x541e304f) // remoting_core!sftk_SessionFromHandle+0x58 - .D32(0x0404c620) - .D32(0x00000040) - .D32(0x01a3eb2c) - .D32(0x01a3ec08) - .D32(0x00000014) - .Mark(&frame1_ebp) - .D32(frame2_ebp) // Child %ebp - .D32(0x541e1234) // return address of frame 1 - // inside remoting_core!NSC_Verify+0x61 - .Mark(&frame2_esp) - .D32(0x04247858) - .D32(0x0404c620) - .D32(0x00000040) - .D32(0x01a3ec08) - .D32(0x00000014) - .D32(0x01000005) - .D32(0x00b2f7a0) - .D32(0x041f0420) - .D32(0x041f3650) - .Mark(&frame2_ebp) - .D32(frame3_ebp) // Child %ebp - .D32(0x541b734d) // return address of frame 1 - // inside remoting_core!PK11_Verify+0x139 - .Mark(&frame3_esp) - .D32(0x01000005) - .D32(0x01a3ec08) - .D32(0x00000014) - .D32(0x0404c620) - .D32(0x00000040) - .D32(0x04073e00) - .D32(0x04073e00) - .D32(0x04247050) - .D32(0x00001041) - .D32(0x00000000) - .D32(0x00000000) - .D32(0x00000000) - .Mark(&frame3_ebp) - .D32(0) // saved %ebp (stack end) - .D32(0); // saved %eip (stack end) - - RegionFromSection(); - raw_context.eip = 0x4247860; // IP address not in known module - raw_context.ebp = 0x5420362d; // bogus - raw_context.esp = frame0_esp.Value(); - - // sanity - ASSERT_TRUE(raw_context.esp == stack_section.start().Value()); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, - &local_modules, &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - if (has_corrupt_symbols) { - ASSERT_EQ(1U, modules_with_corrupt_symbols.size()); - ASSERT_EQ("remoting_core.dll", - modules_with_corrupt_symbols[0]->debug_file()); - } else { - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - } - frames = call_stack.frames(); - - ASSERT_EQ(4U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ(raw_context.eip, frame0->context.eip); - EXPECT_EQ(raw_context.ebp, frame0->context.ebp); - EXPECT_EQ(raw_context.esp, frame0->context.esp); - EXPECT_EQ(NULL, frame0->module); // IP not in known module - EXPECT_EQ("", frame0->function_name); - ASSERT_EQ(NULL, frame0->windows_frame_info); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_SCAN, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP), - frame1->context_validity); - EXPECT_EQ(frame1_ebp.Value(), frame1->context.ebp); - EXPECT_EQ(frame1_esp.Value(), frame1->context.esp); - EXPECT_EQ(&remoting_core_dll, frame1->module); - EXPECT_EQ("nsc_ECDSAVerifyStub", frame1->function_name); - ASSERT_TRUE(frame1->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame1->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame1->windows_frame_info->type_); - EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =", - frame1->windows_frame_info->program_string); - EXPECT_FALSE(frame1->windows_frame_info->allocates_base_pointer); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame2 = static_cast<StackFrameX86 *>(frames->at(2)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame2->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP), - frame2->context_validity); - EXPECT_EQ(frame2_ebp.Value(), frame2->context.ebp); - EXPECT_EQ(frame2_esp.Value(), frame2->context.esp); - EXPECT_EQ(&remoting_core_dll, frame2->module); - EXPECT_EQ("NSC_Verify", frame2->function_name); - ASSERT_TRUE(frame2->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame2->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame2->windows_frame_info->type_); - EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =", - frame2->windows_frame_info->program_string); - EXPECT_FALSE(frame2->windows_frame_info->allocates_base_pointer); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame3 = static_cast<StackFrameX86 *>(frames->at(3)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame3->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP), - frame3->context_validity); - EXPECT_EQ(frame3_ebp.Value(), frame3->context.ebp); - EXPECT_EQ(frame3_esp.Value(), frame3->context.esp); - EXPECT_EQ(&remoting_core_dll, frame3->module); - EXPECT_EQ("PK11_Verify", frame3->function_name); - ASSERT_TRUE(frame3->windows_frame_info != NULL); - EXPECT_EQ(WindowsFrameInfo::VALID_ALL, frame3->windows_frame_info->valid); - EXPECT_EQ(WindowsFrameInfo::STACK_INFO_FRAME_DATA, - frame3->windows_frame_info->type_); - EXPECT_EQ("$T0 $ebp = $eip $T0 4 + ^ = $ebp $T0 ^ = $esp $T0 8 + =", - frame3->windows_frame_info->program_string); - EXPECT_FALSE(frame3->windows_frame_info->allocates_base_pointer); - } -} - -// Runs IPAddressIsNotInKnownModule test with good symbols -TEST_F(GetCallerFrame, IPAddressIsNotInKnownModule) { - IPAddressIsNotInKnownModuleTestImpl(false /* has_corrupt_modules */); -} - -// Runs IPAddressIsNotInKnownModule test with corrupt symbols -TEST_F(GetCallerFrame, IPAddressIsNotInKnownModule_CorruptSymbols) { - IPAddressIsNotInKnownModuleTestImpl(true /* has_corrupt_modules */); -} - -struct CFIFixture: public StackwalkerX86Fixture { - CFIFixture() { - // Provide a bunch of STACK CFI records; individual tests walk to the - // caller from every point in this series, expecting to find the same - // set of register values. - SetModuleSymbols(&module1, - // The youngest frame's function. - "FUNC 4000 1000 10 enchiridion\n" - // Initially, just a return address. - "STACK CFI INIT 4000 100 .cfa: $esp 4 + .ra: .cfa 4 - ^\n" - // Push %ebx. - "STACK CFI 4001 .cfa: $esp 8 + $ebx: .cfa 8 - ^\n" - // Move %esi into %ebx. Weird, but permitted. - "STACK CFI 4002 $esi: $ebx\n" - // Allocate frame space, and save %edi. - "STACK CFI 4003 .cfa: $esp 20 + $edi: .cfa 16 - ^\n" - // Put the return address in %edi. - "STACK CFI 4005 .ra: $edi\n" - // Save %ebp, and use it as a frame pointer. - "STACK CFI 4006 .cfa: $ebp 8 + $ebp: .cfa 12 - ^\n" - - // The calling function. - "FUNC 5000 1000 10 epictetus\n" - // Mark it as end of stack. - "STACK CFI INIT 5000 1000 .cfa: $esp .ra 0\n"); - - // Provide some distinctive values for the caller's registers. - expected.esp = 0x80000000; - expected.eip = 0x40005510; - expected.ebp = 0xc0d4aab9; - expected.ebx = 0x60f20ce6; - expected.esi = 0x53d1379d; - expected.edi = 0xafbae234; - - // By default, registers are unchanged. - raw_context = expected; - } - - // Walk the stack, using stack_section as the contents of the stack - // and raw_context as the current register values. (Set - // raw_context.esp to the stack's starting address.) Expect two - // stack frames; in the older frame, expect the callee-saves - // registers to have values matching those in 'expected'. - void CheckWalk() { - RegionFromSection(); - raw_context.esp = stack_section.start().Value(); - - StackFrameSymbolizer frame_symbolizer(&supplier, &resolver); - StackwalkerX86 walker(&system_info, &raw_context, &stack_region, &modules, - &frame_symbolizer); - vector<const CodeModule*> modules_without_symbols; - vector<const CodeModule*> modules_with_corrupt_symbols; - ASSERT_TRUE(walker.Walk(&call_stack, &modules_without_symbols, - &modules_with_corrupt_symbols)); - ASSERT_EQ(0U, modules_without_symbols.size()); - ASSERT_EQ(0U, modules_with_corrupt_symbols.size()); - frames = call_stack.frames(); - ASSERT_EQ(2U, frames->size()); - - { // To avoid reusing locals by mistake - StackFrameX86 *frame0 = static_cast<StackFrameX86 *>(frames->at(0)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CONTEXT, frame0->trust); - ASSERT_EQ(StackFrameX86::CONTEXT_VALID_ALL, frame0->context_validity); - EXPECT_EQ("enchiridion", frame0->function_name); - EXPECT_EQ(0x40004000U, frame0->function_base); - ASSERT_TRUE(frame0->windows_frame_info != NULL); - ASSERT_EQ(WindowsFrameInfo::VALID_PARAMETER_SIZE, - frame0->windows_frame_info->valid); - ASSERT_TRUE(frame0->cfi_frame_info != NULL); - } - - { // To avoid reusing locals by mistake - StackFrameX86 *frame1 = static_cast<StackFrameX86 *>(frames->at(1)); - EXPECT_EQ(StackFrame::FRAME_TRUST_CFI, frame1->trust); - ASSERT_EQ((StackFrameX86::CONTEXT_VALID_EIP | - StackFrameX86::CONTEXT_VALID_ESP | - StackFrameX86::CONTEXT_VALID_EBP | - StackFrameX86::CONTEXT_VALID_EBX | - StackFrameX86::CONTEXT_VALID_ESI | - StackFrameX86::CONTEXT_VALID_EDI), - frame1->context_validity); - EXPECT_EQ(expected.eip, frame1->context.eip); - EXPECT_EQ(expected.esp, frame1->context.esp); - EXPECT_EQ(expected.ebp, frame1->context.ebp); - EXPECT_EQ(expected.ebx, frame1->context.ebx); - EXPECT_EQ(expected.esi, frame1->context.esi); - EXPECT_EQ(expected.edi, frame1->context.edi); - EXPECT_EQ("epictetus", frame1->function_name); - } - } - - // The values the stack walker should find for the caller's registers. - MDRawContextX86 expected; -}; - -class CFI: public CFIFixture, public Test { }; - -TEST_F(CFI, At4000) { - Label frame1_esp = expected.esp; - stack_section - .D32(0x40005510) // return address - .Mark(&frame1_esp); // This effectively sets stack_section.start(). - raw_context.eip = 0x40004000; - CheckWalk(); -} - -TEST_F(CFI, At4001) { - Label frame1_esp = expected.esp; - stack_section - .D32(0x60f20ce6) // saved %ebx - .D32(0x40005510) // return address - .Mark(&frame1_esp); // This effectively sets stack_section.start(). - raw_context.eip = 0x40004001; - raw_context.ebx = 0x91aa9a8b; // callee's %ebx value - CheckWalk(); -} - -TEST_F(CFI, At4002) { - Label frame1_esp = expected.esp; - stack_section - .D32(0x60f20ce6) // saved %ebx - .D32(0x40005510) // return address - .Mark(&frame1_esp); // This effectively sets stack_section.start(). - raw_context.eip = 0x40004002; - raw_context.ebx = 0x53d1379d; // saved %esi - raw_context.esi = 0xa5c790ed; // callee's %esi value - CheckWalk(); -} - -TEST_F(CFI, At4003) { - Label frame1_esp = expected.esp; - stack_section - .D32(0x56ec3db7) // garbage - .D32(0xafbae234) // saved %edi - .D32(0x53d67131) // garbage - .D32(0x60f20ce6) // saved %ebx - .D32(0x40005510) // return address - .Mark(&frame1_esp); // This effectively sets stack_section.start(). - raw_context.eip = 0x40004003; - raw_context.ebx = 0x53d1379d; // saved %esi - raw_context.esi = 0xa97f229d; // callee's %esi - raw_context.edi = 0xb05cc997; // callee's %edi - CheckWalk(); -} - -// The results here should be the same as those at module offset -// 0x4003. -TEST_F(CFI, At4004) { - Label frame1_esp = expected.esp; - stack_section - .D32(0xe29782c2) // garbage - .D32(0xafbae234) // saved %edi - .D32(0x5ba29ce9) // garbage - .D32(0x60f20ce6) // saved %ebx - .D32(0x40005510) // return address - .Mark(&frame1_esp); // This effectively sets stack_section.start(). - raw_context.eip = 0x40004004; - raw_context.ebx = 0x53d1379d; // saved %esi - raw_context.esi = 0x0fb7dc4e; // callee's %esi - raw_context.edi = 0x993b4280; // callee's %edi - CheckWalk(); -} - -TEST_F(CFI, At4005) { - Label frame1_esp = expected.esp; - stack_section - .D32(0xe29782c2) // garbage - .D32(0xafbae234) // saved %edi - .D32(0x5ba29ce9) // garbage - .D32(0x60f20ce6) // saved %ebx - .D32(0x8036cc02) // garbage - .Mark(&frame1_esp); // This effectively sets stack_section.start(). - raw_context.eip = 0x40004005; - raw_context.ebx = 0x53d1379d; // saved %esi - raw_context.esi = 0x0fb7dc4e; // callee's %esi - raw_context.edi = 0x40005510; // return address - CheckWalk(); -} - -TEST_F(CFI, At4006) { - Label frame0_ebp; - Label frame1_esp = expected.esp; - stack_section - .D32(0xdcdd25cd) // garbage - .D32(0xafbae234) // saved %edi - .D32(0xc0d4aab9) // saved %ebp - .Mark(&frame0_ebp) // frame pointer points here - .D32(0x60f20ce6) // saved %ebx - .D32(0x8036cc02) // garbage - .Mark(&frame1_esp); // This effectively sets stack_section.start(). - raw_context.eip = 0x40004006; - raw_context.ebp = frame0_ebp.Value(); - raw_context.ebx = 0x53d1379d; // saved %esi - raw_context.esi = 0x743833c9; // callee's %esi - raw_context.edi = 0x40005510; // return address - CheckWalk(); -} - diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_address_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_address_map-inl.h deleted file mode 100644 index 67e07976e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_address_map-inl.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_address_map-inl.h: StaticAddressMap implementation. -// -// See static_address_map.h for documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_STATIC_ADDRESS_MAP_INL_H__ -#define PROCESSOR_STATIC_ADDRESS_MAP_INL_H__ - -#include "processor/static_address_map.h" - -#include "processor/logging.h" - -namespace google_breakpad { - -template<typename AddressType, typename EntryType> -bool StaticAddressMap<AddressType, EntryType>::Retrieve( - const AddressType &address, - const EntryType *&entry, AddressType *entry_address) const { - - // upper_bound gives the first element whose key is greater than address, - // but we want the first element whose key is less than or equal to address. - // Decrement the iterator to get there, but not if the upper_bound already - // points to the beginning of the map - in that case, address is lower than - // the lowest stored key, so return false. - - MapConstIterator iterator = map_.upper_bound(address); - if (iterator == map_.begin()) - return false; - --iterator; - - entry = iterator.GetValuePtr(); - // Make sure AddressType is a copyable basic type - if (entry_address) - *entry_address = iterator.GetKey(); - - return true; -} - -} // namespace google_breakpad - -#endif // PROCESSOR_STATIC_ADDRESS_MAP_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_address_map.h b/toolkit/crashreporter/google-breakpad/src/processor/static_address_map.h deleted file mode 100644 index 6bafc6675..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_address_map.h +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_address_map.h: StaticAddressMap. -// -// StaticAddressMap is a wrapper class of StaticMap, just as AddressMap wraps -// std::map. StaticAddressMap provides read-only Retrieve() operation, similar -// as AddressMap. However, the difference between StaticAddressMap and -// AddressMap is that StaticAddressMap does not support dynamic operation -// Store() due to the static nature of the underlying StaticMap. -// -// See address_map.h for reference. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_STATIC_ADDRESS_MAP_H__ -#define PROCESSOR_STATIC_ADDRESS_MAP_H__ - -#include "processor/static_map-inl.h" - -namespace google_breakpad { - -// AddressType MUST be a basic type, e.g.: integer types etc -// EntryType could be a complex type, so we retrieve its pointer instead. -template<typename AddressType, typename EntryType> -class StaticAddressMap { - public: - StaticAddressMap(): map_() { } - explicit StaticAddressMap(const char *map_data): map_(map_data) { } - - // Locates the entry stored at the highest address less than or equal to - // the address argument. If there is no such range, returns false. The - // entry is returned in entry, which is a required argument. If - // entry_address is not NULL, it will be set to the address that the entry - // was stored at. - bool Retrieve(const AddressType &address, - const EntryType *&entry, AddressType *entry_address) const; - - private: - friend class ModuleComparer; - // Convenience types. - typedef StaticAddressMap* SelfPtr; - typedef StaticMap<AddressType, EntryType> AddressToEntryMap; - typedef typename AddressToEntryMap::const_iterator MapConstIterator; - - AddressToEntryMap map_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_STATIC_ADDRESS_MAP_H__ - diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_address_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/static_address_map_unittest.cc deleted file mode 100644 index 12c735cff..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_address_map_unittest.cc +++ /dev/null @@ -1,236 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_address_map_unittest.cc: Unit tests for StaticAddressMap. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include <climits> -#include <cstdlib> -#include <ctime> -#include <string> -#include <iostream> -#include <sstream> - -#include "breakpad_googletest_includes.h" -#include "common/using_std_string.h" -#include "processor/address_map-inl.h" -#include "processor/static_address_map-inl.h" -#include "processor/simple_serializer-inl.h" -#include "map_serializers-inl.h" - -typedef google_breakpad::StaticAddressMap<int, char> TestMap; -typedef google_breakpad::AddressMap<int, string> AddrMap; - -class TestStaticAddressMap : public ::testing::Test { - protected: - void SetUp() { - for (int testcase = 0; testcase < kNumberTestCases; ++testcase) { - testdata[testcase] = new int[testsize[testcase]]; - } - - // Test data set0: NULL (empty map) - - // Test data set1: single element. - testdata[1][0] = 10; - - // Test data set2: six elements. - const int tempdata[] = {5, 10, 14, 15, 16, 20}; - for (int i = 0; i < testsize[2]; ++i) - testdata[2][i] = tempdata[i]; - - // Test data set3: - srand(time(NULL)); - for (int i = 0; i < testsize[3]; ++i) - testdata[3][i] = rand(); - - // Setup maps. - std::stringstream sstream; - for (int testcase = 0; testcase < kNumberTestCases; ++testcase) { - for (int data_item = 0; data_item < testsize[testcase]; ++data_item) { - sstream.clear(); - sstream << "test " << testdata[testcase][data_item]; - addr_map[testcase].Store(testdata[testcase][data_item], sstream.str()); - } - map_data[testcase] = serializer.Serialize(addr_map[testcase], NULL); - test_map[testcase] = TestMap(map_data[testcase]); - } - } - - void TearDown() { - for (int i = 0; i < kNumberTestCases; ++i) { - delete [] map_data[i]; - delete [] testdata[i]; - } - } - - void CompareRetrieveResult(int testcase, int target) { - int address; - int address_test; - string entry; - string entry_test; - const char *entry_cstring = NULL; - bool found; - bool found_test; - - found = addr_map[testcase].Retrieve(target, &entry, &address); - found_test = - test_map[testcase].Retrieve(target, entry_cstring, &address_test); - - ASSERT_EQ(found, found_test); - - if (found && found_test) { - ASSERT_EQ(address, address_test); - entry_test = entry_cstring; - ASSERT_EQ(entry, entry_test); - } - } - - void RetrieveTester(int testcase) { - int target; - target = INT_MIN; - CompareRetrieveResult(testcase, target); - target = INT_MAX; - CompareRetrieveResult(testcase, target); - - srand(time(0)); - for (int data_item = 0; data_item < testsize[testcase]; ++data_item) { - // Retrive (aka, search) for target address and compare results from - // AddressMap and StaticAddressMap. - - // First, assign the search target to be one of original testdata that is - // known to exist in the map. - target = testdata[testcase][data_item]; - CompareRetrieveResult(testcase, target); - // Then, add +2 / -1 bias to target value, in order to test searching for - // a target address not stored in the map. - target -= 1; - CompareRetrieveResult(testcase, target); - target += 3; - CompareRetrieveResult(testcase, target); - // Repeatedly test searching for random target addresses. - target = rand(); - CompareRetrieveResult(testcase, target); - } - } - - // Test data sets: - static const int kNumberTestCases = 4; - static const int testsize[]; - int *testdata[kNumberTestCases]; - - AddrMap addr_map[kNumberTestCases]; - TestMap test_map[kNumberTestCases]; - char *map_data[kNumberTestCases]; - google_breakpad::AddressMapSerializer<int, string> serializer; -}; - -const int TestStaticAddressMap::testsize[] = {0, 1, 6, 1000}; - -TEST_F(TestStaticAddressMap, TestEmptyMap) { - int testcase = 0; - int target; - target = INT_MIN; - CompareRetrieveResult(testcase, target); - target = INT_MAX; - CompareRetrieveResult(testcase, target); - for (int data_item = 0; data_item < testsize[testcase]; ++data_item) { - target = testdata[testcase][data_item]; - CompareRetrieveResult(testcase, target); - target -= 1; - CompareRetrieveResult(testcase, target); - target += 3; - CompareRetrieveResult(testcase, target); - target = rand(); - CompareRetrieveResult(testcase, target); - } -} - -TEST_F(TestStaticAddressMap, TestOneElementMap) { - int testcase = 1; - int target; - target = INT_MIN; - CompareRetrieveResult(testcase, target); - target = INT_MAX; - CompareRetrieveResult(testcase, target); - for (int data_item = 0; data_item < testsize[testcase]; ++data_item) { - target = testdata[testcase][data_item]; - CompareRetrieveResult(testcase, target); - target -= 1; - CompareRetrieveResult(testcase, target); - target += 3; - CompareRetrieveResult(testcase, target); - target = rand(); - CompareRetrieveResult(testcase, target); - } -} - -TEST_F(TestStaticAddressMap, TestSixElementsMap) { - int testcase = 2; - int target; - target = INT_MIN; - CompareRetrieveResult(testcase, target); - target = INT_MAX; - CompareRetrieveResult(testcase, target); - for (int data_item = 0; data_item < testsize[testcase]; ++data_item) { - target = testdata[testcase][data_item]; - CompareRetrieveResult(testcase, target); - target -= 1; - CompareRetrieveResult(testcase, target); - target += 3; - CompareRetrieveResult(testcase, target); - target = rand(); - CompareRetrieveResult(testcase, target); - } -} - -TEST_F(TestStaticAddressMap, Test1000RandomElementsMap) { - int testcase = 3; - int target; - target = INT_MIN; - CompareRetrieveResult(testcase, target); - target = INT_MAX; - CompareRetrieveResult(testcase, target); - for (int data_item = 0; data_item < testsize[testcase]; ++data_item) { - target = testdata[testcase][data_item]; - CompareRetrieveResult(testcase, target); - target -= 1; - CompareRetrieveResult(testcase, target); - target += 3; - CompareRetrieveResult(testcase, target); - target = rand(); - CompareRetrieveResult(testcase, target); - } -} - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map-inl.h deleted file mode 100644 index 777c76218..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map-inl.h +++ /dev/null @@ -1,92 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_contained_range_map-inl.h: Hierarchically-organized range map, -// i.e., StaticContainedRangeMap implementation. -// -// See static_contained_range_map.h for documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_STATIC_CONTAINED_RANGE_MAP_INL_H__ -#define PROCESSOR_STATIC_CONTAINED_RANGE_MAP_INL_H__ - -#include "processor/static_contained_range_map.h" -#include "processor/logging.h" - -namespace google_breakpad { - -template<typename AddressType, typename EntryType> -StaticContainedRangeMap<AddressType, EntryType>::StaticContainedRangeMap( - const char *base) - : base_(*(reinterpret_cast<const AddressType*>(base))), - entry_size_(*(reinterpret_cast<const uint32_t*>(base + sizeof(base_)))), - entry_ptr_(reinterpret_cast<const EntryType *>( - base + sizeof(base_) + sizeof(entry_size_))), - map_(base + sizeof(base_) + sizeof(entry_size_) + entry_size_) { - if (entry_size_ == 0) - entry_ptr_ = NULL; -} - - -template<typename AddressType, typename EntryType> -bool StaticContainedRangeMap<AddressType, EntryType>::RetrieveRange( - const AddressType &address, const EntryType *&entry) const { - - // Get an iterator to the child range whose high address is equal to or - // greater than the supplied address. If the supplied address is higher - // than all of the high addresses in the range, then this range does not - // contain a child at address, so return false. If the supplied address - // is lower than the base address of the child range, then it is not within - // the child range, so return false. - MapConstIterator iterator = map_.lower_bound(address); - - if (iterator == map_.end()) - return false; - - const char *memory_child = - reinterpret_cast<const char*>(iterator.GetValuePtr()); - - StaticContainedRangeMap child_map(memory_child); - - if (address < child_map.base_) - return false; - - // The child in iterator->second contains the specified address. Find out - // if it has a more-specific descendant that also contains it. If it does, - // it will set |entry| appropriately. If not, set |entry| to the child. - if (!child_map.RetrieveRange(address, entry)) - entry = child_map.entry_ptr_; - - return true; -} - -} // namespace google_breakpad - -#endif // PROCESSOR_STATIC_CONTAINED_RANGE_MAP_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map.h b/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map.h deleted file mode 100644 index 6a9b8b7b6..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map.h +++ /dev/null @@ -1,96 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_contained_range_map.h: StaticContainedRangeMap. -// -// StaticContainedRangeMap is similar to ContainedRangeMap. However, -// StaticContainedRangeMap wraps a StaticMap instead of std::map, and does not -// support dynamic operations like StoreRange(...). -// StaticContainedRangeMap provides same RetrieveRange(...) interfaces as -// ContainedRangeMap. -// -// Please see contained_range_map.h for more documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_STATIC_CONTAINED_RANGE_MAP_H__ -#define PROCESSOR_STATIC_CONTAINED_RANGE_MAP_H__ - -#include "processor/static_map-inl.h" - -namespace google_breakpad { - -template<typename AddressType, typename EntryType> -class StaticContainedRangeMap { - public: - StaticContainedRangeMap(): base_(), entry_size_(), entry_ptr_(), map_() { } - explicit StaticContainedRangeMap(const char *base); - - // Retrieves the most specific (smallest) descendant range encompassing - // the specified address. This method will only return entries held by - // child ranges, and not the entry contained by |this|. This is necessary - // to support a sparsely-populated root range. If no descendant range - // encompasses the address, returns false. - bool RetrieveRange(const AddressType &address, const EntryType *&entry) const; - - private: - friend class ModuleComparer; - // AddressToRangeMap stores pointers. This makes reparenting simpler in - // StoreRange, because it doesn't need to copy entire objects. - typedef StaticContainedRangeMap* SelfPtr; - typedef - StaticMap<AddressType, StaticContainedRangeMap> AddressToRangeMap; - typedef typename AddressToRangeMap::const_iterator MapConstIterator; - - // The base address of this range. The high address does not need to - // be stored, because it is used as the key to an object in its parent's - // map, and all ContainedRangeMaps except for the root range are contained - // within maps. The root range does not actually contain an entry, so its - // base_ field is meaningless, and the fact that it has no parent and thus - // no key is unimportant. For this reason, the base_ field should only be - // is accessed on child ContainedRangeMap objects, and never on |this|. - AddressType base_; - - // The entry corresponding to this range. The root range does not - // actually contain an entry, so its entry_ field is meaningless. For - // this reason, the entry_ field should only be accessed on child - // ContainedRangeMap objects, and never on |this|. - uint32_t entry_size_; - const EntryType *entry_ptr_; - - // The map containing child ranges, keyed by each child range's high - // address. This is a pointer to avoid allocating map structures for - // leaf nodes, where they are not needed. - AddressToRangeMap map_; -}; - -} // namespace google_breakpad - - -#endif // PROCESSOR_STATIC_CONTAINED_RANGE_MAP_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map_unittest.cc deleted file mode 100644 index 4ee47578e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_contained_range_map_unittest.cc +++ /dev/null @@ -1,320 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_contained_range_map_unittest.cc: Unit tests for -// StaticContainedRangeMap. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include "breakpad_googletest_includes.h" -#include "common/scoped_ptr.h" -#include "processor/contained_range_map-inl.h" -#include "processor/static_contained_range_map-inl.h" -#include "processor/simple_serializer-inl.h" -#include "processor/map_serializers-inl.h" -#include "processor/logging.h" - -namespace { - -typedef google_breakpad::ContainedRangeMap<unsigned int, int> CRMMap; -typedef google_breakpad::StaticContainedRangeMap<unsigned int, int> TestMap; - -// Each element in test_data contains the expected result when calling -// RetrieveRange on an address. -const int test_data[] = { - 0, // 0 - 0, // 1 - 0, // 2 - 0, // 3 - 0, // 4 - 0, // 5 - 0, // 6 - 0, // 7 - 9, // 8 - 7, // 9 - 1, // 10 - 5, // 11 - 6, // 12 - 6, // 13 - 6, // 14 - 6, // 15 - 6, // 16 - 6, // 17 - 6, // 18 - 5, // 19 - 7, // 20 - 8, // 21 - 0, // 22 - 0, // 23 - 0, // 24 - 0, // 25 - 0, // 26 - 0, // 27 - 0, // 28 - 0, // 29 - 10, // 30 - 10, // 31 - 10, // 32 - 11, // 33 - 11, // 34 - 11, // 35 - 0, // 36 - 0, // 37 - 0, // 38 - 0, // 39 - 14, // 40 - 14, // 41 - 14, // 42 - 14, // 43 - 15, // 44 - 15, // 45 - 15, // 46 - 15, // 47 - 0, // 48 - 0, // 49 - 19, // 50 - 18, // 51 - 18, // 52 - 18, // 53 - 18, // 54 - 18, // 55 - 18, // 56 - 18, // 57 - 18, // 58 - 20, // 59 - 21, // 60 - 25, // 61 - 26, // 62 - 26, // 63 - 26, // 64 - 26, // 65 - 26, // 66 - 26, // 67 - 24, // 68 - 22, // 69 - 30, // 70 - 30, // 71 - 30, // 72 - 30, // 73 - 31, // 74 - 31, // 75 - 30, // 76 - 32, // 77 - 32, // 78 - 30, // 79 - 34, // 80 - 35, // 81 - 36, // 82 - 39, // 83 - 38, // 84 - 37, // 85 - 43, // 86 - 44, // 87 - 41, // 88 - 45, // 89 - 42, // 90 - 0, // 91 - 0, // 92 - 0, // 93 - 0, // 94 - 0, // 95 - 0, // 96 - 0, // 97 - 0, // 98 - 0 // 99 -}; - -} // namespace - -namespace google_breakpad { - -class TestStaticCRMMap : public ::testing::Test { - protected: - void SetUp(); - - // A referrence map for testing StaticCRMMap. - google_breakpad::ContainedRangeMap<unsigned int, int> crm_map_; - - // Static version of crm_map using serialized data of crm_map. - // The goal of testing is to make sure TestMap provides same results for - // lookup operation(s) as CRMMap does. - google_breakpad::StaticContainedRangeMap<unsigned int, int> test_map_; - - google_breakpad::ContainedRangeMapSerializer<unsigned int, int> serializer_; - - scoped_array<char> serialized_data_; -}; - -void TestStaticCRMMap::SetUp() { - // First, do the StoreRange tests. This validates the containment - // rules. - // We confirm the referrence map correctly stores data during setup. - ASSERT_TRUE (crm_map_.StoreRange(10, 10, 1)); - ASSERT_FALSE(crm_map_.StoreRange(10, 10, 2)); // exactly equal to 1 - ASSERT_FALSE(crm_map_.StoreRange(11, 10, 3)); // begins inside 1 and extends up - ASSERT_FALSE(crm_map_.StoreRange( 9, 10, 4)); // begins below 1 and ends inside - ASSERT_TRUE (crm_map_.StoreRange(11, 9, 5)); // contained by existing - ASSERT_TRUE (crm_map_.StoreRange(12, 7, 6)); - ASSERT_TRUE (crm_map_.StoreRange( 9, 12, 7)); // contains existing - ASSERT_TRUE (crm_map_.StoreRange( 9, 13, 8)); - ASSERT_TRUE (crm_map_.StoreRange( 8, 14, 9)); - ASSERT_TRUE (crm_map_.StoreRange(30, 3, 10)); - ASSERT_TRUE (crm_map_.StoreRange(33, 3, 11)); - ASSERT_TRUE (crm_map_.StoreRange(30, 6, 12)); // storable but totally masked - ASSERT_TRUE (crm_map_.StoreRange(40, 8, 13)); // will be totally masked - ASSERT_TRUE (crm_map_.StoreRange(40, 4, 14)); - ASSERT_TRUE (crm_map_.StoreRange(44, 4, 15)); - ASSERT_FALSE(crm_map_.StoreRange(32, 10, 16)); // begins in #10, ends in #14 - ASSERT_FALSE(crm_map_.StoreRange(50, 0, 17)); // zero length - ASSERT_TRUE (crm_map_.StoreRange(50, 10, 18)); - ASSERT_TRUE (crm_map_.StoreRange(50, 1, 19)); - ASSERT_TRUE (crm_map_.StoreRange(59, 1, 20)); - ASSERT_TRUE (crm_map_.StoreRange(60, 1, 21)); - ASSERT_TRUE (crm_map_.StoreRange(69, 1, 22)); - ASSERT_TRUE (crm_map_.StoreRange(60, 10, 23)); - ASSERT_TRUE (crm_map_.StoreRange(68, 1, 24)); - ASSERT_TRUE (crm_map_.StoreRange(61, 1, 25)); - ASSERT_TRUE (crm_map_.StoreRange(61, 8, 26)); - ASSERT_FALSE(crm_map_.StoreRange(59, 9, 27)); - ASSERT_FALSE(crm_map_.StoreRange(59, 10, 28)); - ASSERT_FALSE(crm_map_.StoreRange(59, 11, 29)); - ASSERT_TRUE (crm_map_.StoreRange(70, 10, 30)); - ASSERT_TRUE (crm_map_.StoreRange(74, 2, 31)); - ASSERT_TRUE (crm_map_.StoreRange(77, 2, 32)); - ASSERT_FALSE(crm_map_.StoreRange(72, 6, 33)); - ASSERT_TRUE (crm_map_.StoreRange(80, 3, 34)); - ASSERT_TRUE (crm_map_.StoreRange(81, 1, 35)); - ASSERT_TRUE (crm_map_.StoreRange(82, 1, 36)); - ASSERT_TRUE (crm_map_.StoreRange(83, 3, 37)); - ASSERT_TRUE (crm_map_.StoreRange(84, 1, 38)); - ASSERT_TRUE (crm_map_.StoreRange(83, 1, 39)); - ASSERT_TRUE (crm_map_.StoreRange(86, 5, 40)); - ASSERT_TRUE (crm_map_.StoreRange(88, 1, 41)); - ASSERT_TRUE (crm_map_.StoreRange(90, 1, 42)); - ASSERT_TRUE (crm_map_.StoreRange(86, 1, 43)); - ASSERT_TRUE (crm_map_.StoreRange(87, 1, 44)); - ASSERT_TRUE (crm_map_.StoreRange(89, 1, 45)); - ASSERT_TRUE (crm_map_.StoreRange(87, 4, 46)); - ASSERT_TRUE (crm_map_.StoreRange(87, 3, 47)); - ASSERT_FALSE(crm_map_.StoreRange(86, 2, 48)); - - // Serialize crm_map to generate serialized data. - unsigned int size; - serialized_data_.reset(serializer_.Serialize(&crm_map_, &size)); - BPLOG(INFO) << "Serialized data size: " << size << " Bytes."; - - // Construct test_map_ from serialized data. - test_map_ = TestMap(serialized_data_.get()); -} - -TEST_F(TestStaticCRMMap, TestEmptyMap) { - CRMMap empty_crm_map; - - unsigned int size; - scoped_array<char> serialized_data; - serialized_data.reset(serializer_.Serialize(&empty_crm_map, &size)); - scoped_ptr<TestMap> test_map(new TestMap(serialized_data.get())); - - const unsigned int kCorrectSizeForEmptyMap = 16; - ASSERT_EQ(kCorrectSizeForEmptyMap, size); - - const int *entry_test; - ASSERT_FALSE(test_map->RetrieveRange(-1, entry_test)); - ASSERT_FALSE(test_map->RetrieveRange(0, entry_test)); - ASSERT_FALSE(test_map->RetrieveRange(10, entry_test)); -} - -TEST_F(TestStaticCRMMap, TestSingleElementMap) { - CRMMap crm_map; - // Test on one element: - int entry = 1; - crm_map.StoreRange(10, 10, entry); - - unsigned int size; - scoped_array<char> serialized_data; - serialized_data.reset(serializer_.Serialize(&crm_map, &size)); - scoped_ptr<TestMap> test_map(new TestMap(serialized_data.get())); - - const unsigned int kCorrectSizeForSingleElementMap = 40; - ASSERT_EQ(kCorrectSizeForSingleElementMap, size); - - const int *entry_test; - ASSERT_FALSE(test_map->RetrieveRange(-1, entry_test)); - ASSERT_FALSE(test_map->RetrieveRange(0, entry_test)); - ASSERT_TRUE(test_map->RetrieveRange(10, entry_test)); - ASSERT_EQ(*entry_test, entry); - ASSERT_TRUE(test_map->RetrieveRange(13, entry_test)); - ASSERT_EQ(*entry_test, entry); -} - -TEST_F(TestStaticCRMMap, RunTestData) { - unsigned int test_high = sizeof(test_data) / sizeof(test_data[0]); - - // Now, do the RetrieveRange tests. This further validates that the - // objects were stored properly and that retrieval returns the correct - // object. - // If GENERATE_TEST_DATA is defined, instead of the retrieval tests, a - // new test_data array will be printed. Exercise caution when doing this. - // Be sure to verify the results manually! -#ifdef GENERATE_TEST_DATA - printf(" const int test_data[] = {\n"); -#endif // GENERATE_TEST_DATA - - for (unsigned int address = 0; address < test_high; ++address) { - const int *entryptr; - int value = 0; - if (test_map_.RetrieveRange(address, entryptr)) - value = *entryptr; - -#ifndef GENERATE_TEST_DATA - // Don't use ASSERT inside the loop because it won't show the failed - // |address|, and the line number will always be the same. That makes - // it difficult to figure out which test failed. - EXPECT_EQ(value, test_data[address]) << "FAIL: retrieve address " - << address; -#else // !GENERATE_TEST_DATA - printf(" %d%c%s // %d\n", value, - address == test_high - 1 ? ' ' : ',', - value < 10 ? " " : "", - address); -#endif // !GENERATE_TEST_DATA - } - -#ifdef GENERATE_TEST_DATA - printf(" };\n"); -#endif // GENERATE_TEST_DATA -} - -} // namespace google_breakpad - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_map-inl.h deleted file mode 100644 index e6aac6aba..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_map-inl.h +++ /dev/null @@ -1,176 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_map-inl.h: StaticMap implementation. -// -// See static_map.h for documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - - -#ifndef PROCESSOR_STATIC_MAP_INL_H__ -#define PROCESSOR_STATIC_MAP_INL_H__ - -#include "processor/static_map.h" -#include "processor/static_map_iterator-inl.h" -#include "processor/logging.h" - -namespace google_breakpad { - -template<typename Key, typename Value, typename Compare> -StaticMap<Key, Value, Compare>::StaticMap(const char* raw_data) - : raw_data_(raw_data), - compare_() { - // First 4 Bytes store the number of nodes. - num_nodes_ = *(reinterpret_cast<const uint32_t*>(raw_data_)); - - offsets_ = reinterpret_cast<const uint32_t*>( - raw_data_ + sizeof(num_nodes_)); - - keys_ = reinterpret_cast<const Key*>( - raw_data_ + (1 + num_nodes_) * sizeof(uint32_t)); -} - -// find(), lower_bound() and upper_bound() implement binary search algorithm. -template<typename Key, typename Value, typename Compare> -StaticMapIterator<Key, Value, Compare> -StaticMap<Key, Value, Compare>::find(const Key &key) const { - int begin = 0; - int end = num_nodes_; - int middle; - int compare_result; - while (begin < end) { - middle = begin + (end - begin) / 2; - compare_result = compare_(key, GetKeyAtIndex(middle)); - if (compare_result == 0) - return IteratorAtIndex(middle); - if (compare_result < 0) { - end = middle; - } else { - begin = middle + 1; - } - } - return this->end(); -} - -template<typename Key, typename Value, typename Compare> -StaticMapIterator<Key, Value, Compare> -StaticMap<Key, Value, Compare>::lower_bound(const Key &key) const { - int begin = 0; - int end = num_nodes_; - int middle; - int comp_result; - while (begin < end) { - middle = begin + (end - begin) / 2; - comp_result = compare_(key, GetKeyAtIndex(middle)); - if (comp_result == 0) - return IteratorAtIndex(middle); - if (comp_result < 0) { - end = middle; - } else { - begin = middle + 1; - } - } - return IteratorAtIndex(begin); -} - -template<typename Key, typename Value, typename Compare> -StaticMapIterator<Key, Value, Compare> -StaticMap<Key, Value, Compare>::upper_bound(const Key &key) const { - int begin = 0; - int end = num_nodes_; - int middle; - int compare_result; - while (begin < end) { - middle = begin + (end - begin) / 2; - compare_result = compare_(key, GetKeyAtIndex(middle)); - if (compare_result == 0) - return IteratorAtIndex(middle + 1); - if (compare_result < 0) { - end = middle; - } else { - begin = middle + 1; - } - } - return IteratorAtIndex(begin); -} - -template<typename Key, typename Value, typename Compare> -bool StaticMap<Key, Value, Compare>::ValidateInMemoryStructure() const { - // check the number of nodes is non-negative: - if (!raw_data_) return false; - int32_t num_nodes = *(reinterpret_cast<const int32_t*>(raw_data_)); - if (num_nodes < 0) { - BPLOG(INFO) << "StaticMap check failed: negative number of nodes"; - return false; - } - - int node_index = 0; - if (num_nodes_) { - uint64_t first_offset = sizeof(int32_t) * (num_nodes_ + 1) - + sizeof(Key) * num_nodes_; - // Num_nodes_ is too large. - if (first_offset > 0xffffffffUL) { - BPLOG(INFO) << "StaticMap check failed: size exceeds limit"; - return false; - } - if (offsets_[node_index] != static_cast<uint32_t>(first_offset)) { - BPLOG(INFO) << "StaticMap check failed: first node offset is incorrect"; - return false; - } - } - - for (node_index = 1; node_index < num_nodes_; ++node_index) { - // Check offsets[i] is strictly increasing: - if (offsets_[node_index] <= offsets_[node_index - 1]) { - BPLOG(INFO) << "StaticMap check failed: node offsets non-increasing"; - return false; - } - // Check Key[i] is strictly increasing as no duplicate keys are allowed. - if (compare_(GetKeyAtIndex(node_index), - GetKeyAtIndex(node_index - 1)) <= 0) { - BPLOG(INFO) << "StaticMap check failed: node keys non-increasing"; - return false; - } - } - return true; -} - -template<typename Key, typename Value, typename Compare> -const Key StaticMap<Key, Value, Compare>::GetKeyAtIndex(int index) const { - if (index < 0 || index >= num_nodes_) { - BPLOG(ERROR) << "Key index out of range error"; - // Key type is required to be primitive type. Return 0 if index is invalid. - return 0; - } - return keys_[index]; -} - -} // namespace google_breakpad - -#endif // PROCESSOR_STATIC_MAP_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map.h b/toolkit/crashreporter/google-breakpad/src/processor/static_map.h deleted file mode 100644 index 9723ab2a8..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_map.h +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_map.h: StaticMap. -// -// StaticMap provides lookup interfaces and iterators similar as stl::map's. -// These lookup operations are purely Read-Only, thus memory -// allocation & deallocation is mostly avoided (intentionally). -// -// The chunk of memory should contain data with pre-defined pattern: -// **************** header *************** -// uint32 (4 bytes): number of nodes -// uint32 (4 bytes): address offset of node1's mapped_value -// uint32 (4 bytes): address offset of node2's mapped_value -// ... -// uint32 (4 bytes): address offset of nodeN's mapped_value -// -// ************* Key array ************ -// (X bytes): node1's key -// (X bytes): node2's key -// ... -// (X bytes): nodeN's key -// -// ************* Value array ********** -// (? bytes): node1's mapped_value -// (? bytes): node2's mapped_value -// ... -// (? bytes): nodeN's mapped_value -// -// REQUIREMENT: Key type MUST be primitive type or pointers so that: -// X = sizeof(typename Key); -// -// Note: since address offset is stored as uint32, user should keep in mind that -// StaticMap only supports up to 4GB size of memory data. - -// Author: Siyang Xie (lambxsy@google.com) - - -#ifndef PROCESSOR_STATIC_MAP_H__ -#define PROCESSOR_STATIC_MAP_H__ - -#include "processor/static_map_iterator-inl.h" - -namespace google_breakpad { - -// Default functor to compare keys. -template<typename Key> -class DefaultCompare { - public: - int operator()(const Key &k1, const Key &k2) const { - if (k1 < k2) return -1; - if (k1 == k2) return 0; - return 1; - } -}; - -template<typename Key, typename Value, typename Compare = DefaultCompare<Key> > -class StaticMap { - public: - typedef StaticMapIterator<Key, Value, Compare> iterator; - typedef StaticMapIterator<Key, Value, Compare> const_iterator; - - StaticMap() : raw_data_(0), - num_nodes_(0), - offsets_(0), - compare_() { } - - explicit StaticMap(const char* raw_data); - - inline bool empty() const { return num_nodes_ == 0; } - inline unsigned int size() const { return num_nodes_; } - - // Return iterators. - inline iterator begin() const { return IteratorAtIndex(0); } - inline iterator last() const { return IteratorAtIndex(num_nodes_ - 1); } - inline iterator end() const { return IteratorAtIndex(num_nodes_); } - inline iterator IteratorAtIndex(int index) const { - return iterator(raw_data_, index); - } - - // Lookup operations. - iterator find(const Key &k) const; - - // lower_bound(k) searches in a sorted range for the first element that has a - // key not less than the argument k. - iterator lower_bound(const Key &k) const; - - // upper_bound(k) searches in a sorted range for the first element that has a - // key greater than the argument k. - iterator upper_bound(const Key &k) const; - - // Checks if the underlying memory data conforms to the predefined pattern: - // first check the number of nodes is non-negative, - // then check both offsets and keys are strictly increasing (sorted). - bool ValidateInMemoryStructure() const; - - private: - const Key GetKeyAtIndex(int i) const; - - // Start address of a raw memory chunk with serialized data. - const char* raw_data_; - - // Number of nodes in the static map. - int32_t num_nodes_; - - // Array of offset addresses for stored values. - // For example: - // address_of_i-th_node_value = raw_data_ + offsets_[i] - const uint32_t* offsets_; - - // keys_[i] = key of i_th node - const Key* keys_; - - Compare compare_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_STATIC_MAP_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator-inl.h deleted file mode 100644 index 7a7db5ad9..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator-inl.h +++ /dev/null @@ -1,147 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_map_iterator-inl.h: StaticMapIterator implementation. -// -// See static_map_iterator.h for documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_STATIC_MAP_ITERATOR_INL_H__ -#define PROCESSOR_STATIC_MAP_ITERATOR_INL_H__ - -#include "processor/static_map_iterator.h" - -#include "processor/logging.h" - -namespace google_breakpad { - -template<typename Key, typename Value, typename Compare> -StaticMapIterator<Key, Value, Compare>::StaticMapIterator(const char* base, - const int &index): - index_(index), base_(base) { - // See static_map.h for documentation on - // bytes format of serialized StaticMap data. - num_nodes_ = *(reinterpret_cast<const int32_t*>(base_)); - offsets_ = reinterpret_cast<const uint32_t*>(base_ + sizeof(num_nodes_)); - keys_ = reinterpret_cast<const Key*>( - base_ + (1 + num_nodes_) * sizeof(num_nodes_)); -} - -// Increment & Decrement operators: -template<typename Key, typename Value, typename Compare> -StaticMapIterator<Key, Value, Compare>& -StaticMapIterator<Key, Value, Compare>::operator++() { - if (!IsValid()) { - BPLOG(ERROR) << "operator++ on invalid iterator"; - return *this; - } - if (++index_ > num_nodes_) index_ = num_nodes_; - return *this; -} - -template<typename Key, typename Value, typename Compare> -StaticMapIterator<Key, Value, Compare> -StaticMapIterator<Key, Value, Compare>::operator++(int postfix_operator) { - if (!IsValid()) { - BPLOG(ERROR) << "operator++ on invalid iterator"; - return *this; - } - StaticMapIterator<Key, Value, Compare> tmp = *this; - if (++index_ > num_nodes_) index_ = num_nodes_; - return tmp; -} - -template<typename Key, typename Value, typename Compare> -StaticMapIterator<Key, Value, Compare>& -StaticMapIterator<Key, Value, Compare>::operator--() { - if (!IsValid()) { - BPLOG(ERROR) << "operator++ on invalid iterator"; - return *this; - } - - if (--index_ < 0) index_ = 0; - return *this; -} - -template<typename Key, typename Value, typename Compare> -StaticMapIterator<Key, Value, Compare> -StaticMapIterator<Key, Value, Compare>::operator--(int postfix_operator) { - if (!IsValid()) { - BPLOG(ERROR) << "operator++ on invalid iterator"; - return *this; - } - StaticMapIterator<Key, Value, Compare> tmp = *this; - - if (--index_ < 0) index_ = 0; - return tmp; -} - -template<typename Key, typename Value, typename Compare> -const Key* StaticMapIterator<Key, Value, Compare>::GetKeyPtr() const { - if (!IsValid()) { - BPLOG(ERROR) << "call GetKeyPtr() on invalid iterator"; - return NULL; - } - return &(keys_[index_]); -} - -template<typename Key, typename Value, typename Compare> -const char* StaticMapIterator<Key, Value, Compare>::GetValueRawPtr() const { - if (!IsValid()) { - BPLOG(ERROR) << "call GetValuePtr() on invalid iterator"; - return NULL; - } - return base_ + offsets_[index_]; -} - -template<typename Key, typename Value, typename Compare> -bool StaticMapIterator<Key, Value, Compare>::operator==( - const StaticMapIterator<Key, Value, Compare>& x) const { - return base_ == x.base_ && index_ == x.index_; -} - -template<typename Key, typename Value, typename Compare> -bool StaticMapIterator<Key, Value, Compare>::operator!=( - const StaticMapIterator<Key, Value, Compare>& x) const { - // Only need to compare base_ and index_. - // Other data members are auxiliary. - return base_ != x.base_ || index_ != x.index_; -} - -template<typename Key, typename Value, typename Compare> -bool StaticMapIterator<Key, Value, Compare>::IsValid() const { - if (!base_ || index_ < 0 || index_ > num_nodes_) - return false; - - return true; -} - -} // namespace google_breakpad - -#endif // PROCESSOR_STATIC_MAP_ITERATOR_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator.h b/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator.h deleted file mode 100644 index 1af8fff45..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_map_iterator.h +++ /dev/null @@ -1,112 +0,0 @@ -// Copyright 2010 Google Inc. All Rights Reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_map_iterator.h: StaticMapIterator template class declaration. -// -// StaticMapIterator provides increment and decrement operators to iterate -// through a StaticMap map. It does not provide *, -> operators, user should -// use GetKeyPtr(), GetKey(), GetValuePtr() interfaces to retrieve data or -// pointer to data. StaticMapIterator is essentially a const_iterator. -// -// Author: Siyang Xie (lambxsy@google.com) - - -#ifndef PROCESSOR_STATIC_MAP_ITERATOR_H__ -#define PROCESSOR_STATIC_MAP_ITERATOR_H__ - -#include "google_breakpad/common/breakpad_types.h" - -namespace google_breakpad { - -// Forward declaration. -template<typename Key, typename Value, typename Compare> class StaticMap; - -// StaticMapIterator does not support operator*() or operator->(), -// User should use GetKey(), GetKeyPtr(), GetValuePtr() instead; -template<typename Key, typename Value, typename Compare> -class StaticMapIterator { - public: - // Constructors. - StaticMapIterator(): index_(-1), base_(NULL) { } - - // Increment & Decrement operators: - StaticMapIterator& operator++(); - StaticMapIterator operator++(int post_fix_operator); - - StaticMapIterator& operator--(); - StaticMapIterator operator--(int post_fix_operator); - - // Interface for retrieving data / pointer to data. - const Key* GetKeyPtr() const; - - // Run time error will occur if GetKey() is called on an invalid iterator. - inline const Key GetKey() const { return *GetKeyPtr(); } - - // return a raw memory pointer that points to the start address of value. - const char* GetValueRawPtr() const; - - // return a reinterpret-casted pointer to the value. - inline const Value* GetValuePtr() const { - return reinterpret_cast<const Value*>(GetValueRawPtr()); - } - - bool operator==(const StaticMapIterator& x) const; - bool operator!=(const StaticMapIterator& x) const; - - // Check if this iterator is valid. - // If iterator is invalid, user is forbidden to use ++/-- operator - // or interfaces for retrieving data / pointer to data. - bool IsValid() const; - - private: - friend class StaticMap<Key, Value, Compare>; - - // Only StaticMap can call this constructor. - explicit StaticMapIterator(const char* base, const int32_t &index); - - // Index of node that the iterator is pointing to. - int32_t index_; - - // Beginning address of the serialized map data. - const char* base_; - - // Number of nodes in the map. Use it to identify end() iterator. - int32_t num_nodes_; - - // offsets_ is an array of offset addresses of mapped values. - // For example: - // address_of_i-th_node_value = base_ + offsets_[i] - const uint32_t* offsets_; - - // keys_[i] = key of i_th node. - const Key* keys_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_STATIC_MAP_ITERATOR_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/static_map_unittest.cc deleted file mode 100644 index 393d43d5c..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_map_unittest.cc +++ /dev/null @@ -1,386 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_map_unittest.cc: Unit tests for StaticMap. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include <climits> -#include <map> - -#include "breakpad_googletest_includes.h" -#include "processor/static_map-inl.h" - - -typedef int ValueType; -typedef int KeyType; -typedef google_breakpad::StaticMap< KeyType, ValueType > TestMap; -typedef std::map< KeyType, ValueType > StdMap; - -template<typename Key, typename Value> -class SimpleMapSerializer { - public: - static char* Serialize(const std::map<Key, Value> &stdmap, - unsigned int* size = NULL) { - unsigned int size_per_node = - sizeof(uint32_t) + sizeof(Key) + sizeof(Value); - unsigned int memsize = sizeof(int32_t) + size_per_node * stdmap.size(); - if (size) *size = memsize; - - // Allocate memory for serialized data: - char* mem = reinterpret_cast<char*>(operator new(memsize)); - char* address = mem; - - // Writer the number of nodes: - new (address) uint32_t(static_cast<uint32_t>(stdmap.size())); - address += sizeof(uint32_t); - - // Nodes' offset: - uint32_t* offsets = reinterpret_cast<uint32_t*>(address); - address += sizeof(uint32_t) * stdmap.size(); - - // Keys: - Key* keys = reinterpret_cast<Key*>(address); - address += sizeof(Key) * stdmap.size(); - - // Traversing map: - typename std::map<Key, Value>::const_iterator iter = stdmap.begin(); - for (int index = 0; iter != stdmap.end(); ++iter, ++index) { - offsets[index] = static_cast<unsigned int>(address - mem); - keys[index] = iter->first; - new (address) Value(iter->second); - address += sizeof(Value); - } - return mem; - } -}; - - -class TestInvalidMap : public ::testing::Test { - protected: - void SetUp() { - memset(data, 0, kMemorySize); - } - - // 40 Bytes memory can hold a StaticMap with up to 3 nodes. - static const int kMemorySize = 40; - char data[kMemorySize]; - TestMap test_map; -}; - -TEST_F(TestInvalidMap, TestNegativeNumberNodes) { - memset(data, 0xff, sizeof(uint32_t)); // Set the number of nodes = -1 - test_map = TestMap(data); - ASSERT_FALSE(test_map.ValidateInMemoryStructure()); -} - -TEST_F(TestInvalidMap, TestWrongOffsets) { - uint32_t* header = reinterpret_cast<uint32_t*>(data); - const uint32_t kNumNodes = 2; - const uint32_t kHeaderOffset = - sizeof(uint32_t) + kNumNodes * (sizeof(uint32_t) + sizeof(KeyType)); - - header[0] = kNumNodes; - header[1] = kHeaderOffset + 3; // Wrong offset for first node - test_map = TestMap(data); - ASSERT_FALSE(test_map.ValidateInMemoryStructure()); - - header[1] = kHeaderOffset; // Correct offset for first node - header[2] = kHeaderOffset - 1; // Wrong offset for second node - test_map = TestMap(data); - ASSERT_FALSE(test_map.ValidateInMemoryStructure()); -} - -TEST_F(TestInvalidMap, TestUnSortedKeys) { - uint32_t* header = reinterpret_cast<uint32_t*>(data); - const uint32_t kNumNodes = 2; - const uint32_t kHeaderOffset = - sizeof(uint32_t) + kNumNodes * (sizeof(uint32_t) + sizeof(KeyType)); - header[0] = kNumNodes; - header[1] = kHeaderOffset; - header[2] = kHeaderOffset + sizeof(ValueType); - - KeyType* keys = reinterpret_cast<KeyType*>( - data + (kNumNodes + 1) * sizeof(uint32_t)); - // Set keys in non-increasing order. - keys[0] = 10; - keys[1] = 7; - test_map = TestMap(data); - ASSERT_FALSE(test_map.ValidateInMemoryStructure()); -} - - -class TestValidMap : public ::testing::Test { - protected: - void SetUp() { - int testcase = 0; - - // Empty map. - map_data[testcase] = - serializer.Serialize(std_map[testcase], &size[testcase]); - test_map[testcase] = TestMap(map_data[testcase]); - ++testcase; - - // Single element. - std_map[testcase].insert(std::make_pair(2, 8)); - map_data[testcase] = - serializer.Serialize(std_map[testcase], &size[testcase]); - test_map[testcase] = TestMap(map_data[testcase]); - ++testcase; - - // 100 elements. - for (int i = 0; i < 100; ++i) - std_map[testcase].insert(std::make_pair(i, 2 * i)); - map_data[testcase] = - serializer.Serialize(std_map[testcase], &size[testcase]); - test_map[testcase] = TestMap(map_data[testcase]); - ++testcase; - - // 1000 random elements. - for (int i = 0; i < 1000; ++i) - std_map[testcase].insert(std::make_pair(rand(), rand())); - map_data[testcase] = - serializer.Serialize(std_map[testcase], &size[testcase]); - test_map[testcase] = TestMap(map_data[testcase]); - - // Set correct size of memory allocation for each test case. - unsigned int size_per_node = - sizeof(uint32_t) + sizeof(KeyType) + sizeof(ValueType); - for (testcase = 0; testcase < kNumberTestCases; ++testcase) { - correct_size[testcase] = - sizeof(uint32_t) + std_map[testcase].size() * size_per_node; - } - } - - void TearDown() { - for (int i = 0;i < kNumberTestCases; ++i) - ::operator delete(map_data[i]); - } - - - void IteratorTester(int test_case) { - // scan through: - iter_test = test_map[test_case].begin(); - iter_std = std_map[test_case].begin(); - - for (; iter_test != test_map[test_case].end() && - iter_std != std_map[test_case].end(); - ++iter_test, ++iter_std) { - ASSERT_EQ(iter_test.GetKey(), iter_std->first); - ASSERT_EQ(*(iter_test.GetValuePtr()), iter_std->second); - } - ASSERT_TRUE(iter_test == test_map[test_case].end() - && iter_std == std_map[test_case].end()); - - // Boundary testcase. - if (!std_map[test_case].empty()) { - // rear boundary case: - iter_test = test_map[test_case].end(); - iter_std = std_map[test_case].end(); - --iter_std; - --iter_test; - ASSERT_EQ(iter_test.GetKey(), iter_std->first); - ASSERT_EQ(*(iter_test.GetValuePtr()), iter_std->second); - - ++iter_test; - ++iter_std; - ASSERT_TRUE(iter_test == test_map[test_case].end()); - - --iter_test; - --iter_std; - ASSERT_TRUE(iter_test != test_map[test_case].end()); - ASSERT_TRUE(iter_test == test_map[test_case].last()); - ASSERT_EQ(iter_test.GetKey(), iter_std->first); - ASSERT_EQ(*(iter_test.GetValuePtr()), iter_std->second); - - // front boundary case: - iter_test = test_map[test_case].begin(); - --iter_test; - ASSERT_TRUE(iter_test == test_map[test_case].begin()); - } - } - - void CompareLookupResult(int test_case) { - bool found1 = (iter_test != test_map[test_case].end()); - bool found2 = (iter_std != std_map[test_case].end()); - ASSERT_EQ(found1, found2); - - if (found1 && found2) { - ASSERT_EQ(iter_test.GetKey(), iter_std->first); - ASSERT_EQ(*(iter_test.GetValuePtr()), iter_std->second); - } - } - - void FindTester(int test_case, const KeyType &key) { - iter_test = test_map[test_case].find(key); - iter_std = std_map[test_case].find(key); - CompareLookupResult(test_case); - } - - void LowerBoundTester(int test_case, const KeyType &key) { - iter_test = test_map[test_case].lower_bound(key); - iter_std = std_map[test_case].lower_bound(key); - CompareLookupResult(test_case); - } - - void UpperBoundTester(int test_case, const KeyType &key) { - iter_test = test_map[test_case].upper_bound(key); - iter_std = std_map[test_case].upper_bound(key); - CompareLookupResult(test_case); - } - - void LookupTester(int test_case) { - StdMap::const_iterator iter; - // Test find(): - for (iter = std_map[test_case].begin(); - iter != std_map[test_case].end(); - ++iter) { - FindTester(test_case, iter->first); - FindTester(test_case, iter->first + 1); - FindTester(test_case, iter->first - 1); - } - FindTester(test_case, INT_MIN); - FindTester(test_case, INT_MAX); - // random test: - for (int i = 0; i < rand()%5000 + 5000; ++i) - FindTester(test_case, rand()); - - // Test lower_bound(): - for (iter = std_map[test_case].begin(); - iter != std_map[test_case].end(); - ++iter) { - LowerBoundTester(test_case, iter->first); - LowerBoundTester(test_case, iter->first + 1); - LowerBoundTester(test_case, iter->first - 1); - } - LowerBoundTester(test_case, INT_MIN); - LowerBoundTester(test_case, INT_MAX); - // random test: - for (int i = 0; i < rand()%5000 + 5000; ++i) - LowerBoundTester(test_case, rand()); - - // Test upper_bound(): - for (iter = std_map[test_case].begin(); - iter != std_map[test_case].end(); - ++iter) { - UpperBoundTester(test_case, iter->first); - UpperBoundTester(test_case, iter->first + 1); - UpperBoundTester(test_case, iter->first - 1); - } - UpperBoundTester(test_case, INT_MIN); - UpperBoundTester(test_case, INT_MAX); - // random test: - for (int i = 0; i < rand()%5000 + 5000; ++i) - UpperBoundTester(test_case, rand()); - } - - static const int kNumberTestCases = 4; - StdMap std_map[kNumberTestCases]; - TestMap test_map[kNumberTestCases]; - TestMap::const_iterator iter_test; - StdMap::const_iterator iter_std; - char* map_data[kNumberTestCases]; - unsigned int size[kNumberTestCases]; - unsigned int correct_size[kNumberTestCases]; - SimpleMapSerializer<KeyType, ValueType> serializer; -}; - -TEST_F(TestValidMap, TestEmptyMap) { - int test_case = 0; - // Assert memory size allocated during serialization is correct. - ASSERT_EQ(correct_size[test_case], size[test_case]); - - // Sanity check of serialized data: - ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure()); - ASSERT_EQ(std_map[test_case].empty(), test_map[test_case].empty()); - ASSERT_EQ(std_map[test_case].size(), test_map[test_case].size()); - - // Test Iterator. - IteratorTester(test_case); - - // Test lookup operations. - LookupTester(test_case); -} - -TEST_F(TestValidMap, TestSingleElement) { - int test_case = 1; - // Assert memory size allocated during serialization is correct. - ASSERT_EQ(correct_size[test_case], size[test_case]); - - // Sanity check of serialized data: - ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure()); - ASSERT_EQ(std_map[test_case].empty(), test_map[test_case].empty()); - ASSERT_EQ(std_map[test_case].size(), test_map[test_case].size()); - - // Test Iterator. - IteratorTester(test_case); - - // Test lookup operations. - LookupTester(test_case); -} - -TEST_F(TestValidMap, Test100Elements) { - int test_case = 2; - // Assert memory size allocated during serialization is correct. - ASSERT_EQ(correct_size[test_case], size[test_case]); - - // Sanity check of serialized data: - ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure()); - ASSERT_EQ(std_map[test_case].empty(), test_map[test_case].empty()); - ASSERT_EQ(std_map[test_case].size(), test_map[test_case].size()); - - // Test Iterator. - IteratorTester(test_case); - - // Test lookup operations. - LookupTester(test_case); -} - -TEST_F(TestValidMap, Test1000RandomElements) { - int test_case = 3; - // Assert memory size allocated during serialization is correct. - ASSERT_EQ(correct_size[test_case], size[test_case]); - - // Sanity check of serialized data: - ASSERT_TRUE(test_map[test_case].ValidateInMemoryStructure()); - ASSERT_EQ(std_map[test_case].empty(), test_map[test_case].empty()); - ASSERT_EQ(std_map[test_case].size(), test_map[test_case].size()); - - // Test Iterator. - IteratorTester(test_case); - - // Test lookup operations. - LookupTester(test_case); -} - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_range_map-inl.h b/toolkit/crashreporter/google-breakpad/src/processor/static_range_map-inl.h deleted file mode 100644 index f6cef1a9e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_range_map-inl.h +++ /dev/null @@ -1,130 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_range_map-inl.h: StaticRangeMap implementation. -// -// See static_range_map.h for documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_STATIC_RANGE_MAP_INL_H__ -#define PROCESSOR_STATIC_RANGE_MAP_INL_H__ - -#include "processor/static_range_map.h" -#include "processor/logging.h" - -namespace google_breakpad { - -template<typename AddressType, typename EntryType> -bool StaticRangeMap<AddressType, EntryType>::RetrieveRange( - const AddressType &address, const EntryType *&entry, - AddressType *entry_base, AddressType *entry_size) const { - MapConstIterator iterator = map_.lower_bound(address); - if (iterator == map_.end()) - return false; - - // The map is keyed by the high address of each range, so |address| is - // guaranteed to be lower than the range's high address. If |range| is - // not directly preceded by another range, it's possible for address to - // be below the range's low address, though. When that happens, address - // references something not within any range, so return false. - - const Range *range = iterator.GetValuePtr(); - - // Make sure AddressType and EntryType are copyable basic types - // e.g.: integer types, pointers etc - if (address < range->base()) - return false; - - entry = range->entryptr(); - if (entry_base) - *entry_base = range->base(); - if (entry_size) - *entry_size = iterator.GetKey() - range->base() + 1; - - return true; -} - - -template<typename AddressType, typename EntryType> -bool StaticRangeMap<AddressType, EntryType>::RetrieveNearestRange( - const AddressType &address, const EntryType *&entry, - AddressType *entry_base, AddressType *entry_size) const { - // If address is within a range, RetrieveRange can handle it. - if (RetrieveRange(address, entry, entry_base, entry_size)) - return true; - - // upper_bound gives the first element whose key is greater than address, - // but we want the first element whose key is less than or equal to address. - // Decrement the iterator to get there, but not if the upper_bound already - // points to the beginning of the map - in that case, address is lower than - // the lowest stored key, so return false. - - MapConstIterator iterator = map_.upper_bound(address); - if (iterator == map_.begin()) - return false; - --iterator; - - const Range *range = iterator.GetValuePtr(); - entry = range->entryptr(); - if (entry_base) - *entry_base = range->base(); - if (entry_size) - *entry_size = iterator.GetKey() - range->base() + 1; - - return true; -} - -template<typename AddressType, typename EntryType> -bool StaticRangeMap<AddressType, EntryType>::RetrieveRangeAtIndex( - int index, const EntryType *&entry, - AddressType *entry_base, AddressType *entry_size) const { - - if (index >= GetCount()) { - BPLOG(ERROR) << "Index out of range: " << index << "/" << GetCount(); - return false; - } - - MapConstIterator iterator = map_.IteratorAtIndex(index); - - const Range *range = iterator.GetValuePtr(); - - entry = range->entryptr(); - if (entry_base) - *entry_base = range->base(); - if (entry_size) - *entry_size = iterator.GetKey() - range->base() + 1; - - return true; -} - -} // namespace google_breakpad - - -#endif // PROCESSOR_STATIC_RANGE_MAP_INL_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_range_map.h b/toolkit/crashreporter/google-breakpad/src/processor/static_range_map.h deleted file mode 100644 index 91aabb032..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_range_map.h +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// static_range_map.h: StaticRangeMap. -// -// StaticRangeMap is similar as RangeMap. However, StaticRangeMap wraps a -// StaticMap instead of std::map, and does not support dynamic operations like -// StoreRange(...). StaticRangeMap provides same Retrieve*() interfaces as -// RangeMap. Please see range_map.h for more documentation. -// -// Author: Siyang Xie (lambxsy@google.com) - -#ifndef PROCESSOR_STATIC_RANGE_MAP_H__ -#define PROCESSOR_STATIC_RANGE_MAP_H__ - - -#include "processor/static_map-inl.h" - -namespace google_breakpad { - -// AddressType is basic type, e.g.: integer types, pointers etc -// EntryType could be a complex type, so we retrieve its pointer instead. -template<typename AddressType, typename EntryType> -class StaticRangeMap { - public: - StaticRangeMap(): map_() { } - explicit StaticRangeMap(const char *memory): map_(memory) { } - - // Locates the range encompassing the supplied address. If there is - // no such range, returns false. entry_base and entry_size, if non-NULL, - // are set to the base and size of the entry's range. - bool RetrieveRange(const AddressType &address, const EntryType *&entry, - AddressType *entry_base, AddressType *entry_size) const; - - // Locates the range encompassing the supplied address, if one exists. - // If no range encompasses the supplied address, locates the nearest range - // to the supplied address that is lower than the address. Returns false - // if no range meets these criteria. entry_base and entry_size, if - // non-NULL, are set to the base and size of the entry's range. - bool RetrieveNearestRange(const AddressType &address, const EntryType *&entry, - AddressType *entry_base, AddressType *entry_size) - const; - - // Treating all ranges as a list ordered by the address spaces that they - // occupy, locates the range at the index specified by index. Returns - // false if index is larger than the number of ranges stored. entry_base - // and entry_size, if non-NULL, are set to the base and size of the entry's - // range. - // - // RetrieveRangeAtIndex is not optimized for speedy operation. - bool RetrieveRangeAtIndex(int index, const EntryType *&entry, - AddressType *entry_base, AddressType *entry_size) - const; - - // Returns the number of ranges stored in the RangeMap. - inline int GetCount() const { return map_.size(); } - - private: - friend class ModuleComparer; - class Range { - public: - AddressType base() const { - return *(reinterpret_cast<const AddressType*>(this)); - } - const EntryType* entryptr() const { - return reinterpret_cast<const EntryType*>(this + sizeof(AddressType)); - } - }; - - // Convenience types. - typedef StaticRangeMap* SelfPtr; - typedef StaticMap<AddressType, Range> AddressToRangeMap; - typedef typename AddressToRangeMap::const_iterator MapConstIterator; - - AddressToRangeMap map_; -}; - -} // namespace google_breakpad - -#endif // PROCESSOR_STATIC_RANGE_MAP_H__ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/static_range_map_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/static_range_map_unittest.cc deleted file mode 100644 index 282173622..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/static_range_map_unittest.cc +++ /dev/null @@ -1,421 +0,0 @@ -// Copyright (c) 2010 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// static_range_map_unittest.cc: Unit tests for StaticRangeMap. -// -// Author: Siyang Xie (lambxsy@google.com) - -#include "breakpad_googletest_includes.h" -#include "common/scoped_ptr.h" -#include "processor/range_map-inl.h" -#include "processor/static_range_map-inl.h" -#include "processor/simple_serializer-inl.h" -#include "processor/map_serializers-inl.h" -#include "processor/logging.h" - - -namespace { -// Types used for testing. -typedef int AddressType; -typedef int EntryType; -typedef google_breakpad::StaticRangeMap< AddressType, EntryType > TestMap; -typedef google_breakpad::RangeMap< AddressType, EntryType > RMap; - -// RangeTest contains data to use for store and retrieve tests. See -// RunTests for descriptions of the tests. -struct RangeTest { - // Base address to use for test - AddressType address; - - // Size of range to use for test - AddressType size; - - // Unique ID of range - unstorable ranges must have unique IDs too - EntryType id; - - // Whether this range is expected to be stored successfully or not - bool expect_storable; -}; - -// A RangeTestSet encompasses multiple RangeTests, which are run in -// sequence on the same RangeMap. -struct RangeTestSet { - // An array of RangeTests - const RangeTest* range_tests; - - // The number of tests in the set - unsigned int range_test_count; -}; - -// These tests will be run sequentially. The first set of tests exercises -// most functions of RangeTest, and verifies all of the bounds-checking. -const RangeTest range_tests_0[] = { - { INT_MIN, 16, 1, true }, // lowest possible range - { -2, 5, 2, true }, // a range through zero - { INT_MAX - 9, 11, 3, false }, // tests anti-overflow - { INT_MAX - 9, 10, 4, true }, // highest possible range - { 5, 0, 5, false }, // tests anti-zero-size - { 5, 1, 6, true }, // smallest possible range - { -20, 15, 7, true }, // entirely negative - - { 10, 10, 10, true }, // causes the following tests to fail - { 9, 10, 11, false }, // one-less base, one-less high - { 9, 11, 12, false }, // one-less base, identical high - { 9, 12, 13, false }, // completely contains existing - { 10, 9, 14, false }, // identical base, one-less high - { 10, 10, 15, false }, // exactly identical to existing range - { 10, 11, 16, false }, // identical base, one-greater high - { 11, 8, 17, false }, // contained completely within - { 11, 9, 18, false }, // one-greater base, identical high - { 11, 10, 19, false }, // one-greater base, one-greater high - { 9, 2, 20, false }, // overlaps bottom by one - { 10, 1, 21, false }, // overlaps bottom by one, contained - { 19, 1, 22, false }, // overlaps top by one, contained - { 19, 2, 23, false }, // overlaps top by one - - { 9, 1, 24, true }, // directly below without overlap - { 20, 1, 25, true }, // directly above without overlap - - { 6, 3, 26, true }, // exactly between two ranges, gapless - { 7, 3, 27, false }, // tries to span two ranges - { 7, 5, 28, false }, // tries to span three ranges - { 4, 20, 29, false }, // tries to contain several ranges - - { 30, 50, 30, true }, - { 90, 25, 31, true }, - { 35, 65, 32, false }, // tries to span two noncontiguous - { 120, 10000, 33, true }, // > 8-bit - { 20000, 20000, 34, true }, // > 8-bit - { 0x10001, 0x10001, 35, true }, // > 16-bit - - { 27, -1, 36, false } // tests high < base -}; - -// Attempt to fill the entire space. The entire space must be filled with -// three stores because AddressType is signed for these tests, so RangeMap -// treats the size as signed and rejects sizes that appear to be negative. -// Even if these tests were run as unsigned, two stores would be needed -// to fill the space because the entire size of the space could only be -// described by using one more bit than would be present in AddressType. -const RangeTest range_tests_1[] = { - { INT_MIN, INT_MAX, 50, true }, // From INT_MIN to -2, inclusive - { -1, 2, 51, true }, // From -1 to 0, inclusive - { 1, INT_MAX, 52, true }, // From 1 to INT_MAX, inclusive - { INT_MIN, INT_MAX, 53, false }, // Can't fill the space twice - { -1, 2, 54, false }, - { 1, INT_MAX, 55, false }, - { -3, 6, 56, false }, // -3 to 2, inclusive - spans 3 ranges -}; - -// A light round of testing to verify that RetrieveRange does the right -// the right thing at the extremities of the range when nothing is stored -// there. Checks are forced without storing anything at the extremities -// by setting size = 0. -const RangeTest range_tests_2[] = { - { INT_MIN, 0, 100, false }, // makes RetrieveRange check low end - { -1, 3, 101, true }, - { INT_MAX, 0, 102, false }, // makes RetrieveRange check high end -}; - -// Similar to the previous test set, but with a couple of ranges closer -// to the extremities. -const RangeTest range_tests_3[] = { - { INT_MIN + 1, 1, 110, true }, - { INT_MAX - 1, 1, 111, true }, - { INT_MIN, 0, 112, false }, // makes RetrieveRange check low end - { INT_MAX, 0, 113, false } // makes RetrieveRange check high end -}; - -// The range map is cleared between sets of tests listed here. -const RangeTestSet range_test_sets[] = { - { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) }, - { range_tests_1, sizeof(range_tests_1) / sizeof(RangeTest) }, - { range_tests_2, sizeof(range_tests_2) / sizeof(RangeTest) }, - { range_tests_3, sizeof(range_tests_3) / sizeof(RangeTest) }, - { range_tests_0, sizeof(range_tests_0) / sizeof(RangeTest) } // Run again -}; - -} // namespace - -namespace google_breakpad { -class TestStaticRangeMap : public ::testing::Test { - protected: - void SetUp() { - kTestCasesCount_ = sizeof(range_test_sets) / sizeof(RangeTestSet); - } - - // StoreTest uses the data in a RangeTest and calls StoreRange on the - // test RangeMap. It returns true if the expected result occurred, and - // false if something else happened. - void StoreTest(RMap* range_map, const RangeTest* range_test); - - // RetrieveTest uses the data in RangeTest and calls RetrieveRange on the - // test RangeMap. If it retrieves the expected value (which can be no - // map entry at the specified range,) it returns true, otherwise, it returns - // false. RetrieveTest will check the values around the base address and - // the high address of a range to guard against off-by-one errors. - void RetrieveTest(TestMap* range_map, const RangeTest* range_test); - - // Test RetrieveRangeAtIndex, which is supposed to return objects in order - // according to their addresses. This test is performed by looping through - // the map, calling RetrieveRangeAtIndex for all possible indices in sequence, - // and verifying that each call returns a different object than the previous - // call, and that ranges are returned with increasing base addresses. Returns - // false if the test fails. - void RetrieveIndexTest(const TestMap* range_map, int set); - - void RunTestCase(int test_case); - - unsigned int kTestCasesCount_; - RangeMapSerializer<AddressType, EntryType> serializer_; -}; - -void TestStaticRangeMap::StoreTest(RMap* range_map, - const RangeTest* range_test) { - bool stored = range_map->StoreRange(range_test->address, - range_test->size, - range_test->id); - EXPECT_EQ(stored, range_test->expect_storable) - << "StoreRange id " << range_test->id << "FAILED"; -} - -void TestStaticRangeMap::RetrieveTest(TestMap* range_map, - const RangeTest* range_test) { - for (unsigned int side = 0; side <= 1; ++side) { - // When side == 0, check the low side (base address) of each range. - // When side == 1, check the high side (base + size) of each range. - - // Check one-less and one-greater than the target address in addition - // to the target address itself. - - // If the size of the range is only 1, don't check one greater than - // the base or one less than the high - for a successfully stored - // range, these tests would erroneously fail because the range is too - // small. - AddressType low_offset = -1; - AddressType high_offset = 1; - if (range_test->size == 1) { - if (!side) // When checking the low side, - high_offset = 0; // don't check one over the target. - else // When checking the high side, - low_offset = 0; // don't check one under the target. - } - - for (AddressType offset = low_offset; offset <= high_offset; ++offset) { - AddressType address = - offset + - (!side ? range_test->address : - range_test->address + range_test->size - 1); - - bool expected_result = false; // This is correct for tests not stored. - if (range_test->expect_storable) { - if (offset == 0) // When checking the target address, - expected_result = true; // test should always succeed. - else if (offset == -1) // When checking one below the target, - expected_result = side; // should fail low and succeed high. - else // When checking one above the target, - expected_result = !side; // should succeed low and fail high. - } - - const EntryType* id; - AddressType retrieved_base; - AddressType retrieved_size; - bool retrieved = range_map->RetrieveRange(address, id, - &retrieved_base, - &retrieved_size); - - bool observed_result = retrieved && *id == range_test->id; - EXPECT_EQ(observed_result, expected_result) - << "RetrieveRange id " << range_test->id - << ", side " << side << ", offset " << offset << " FAILED."; - - // If a range was successfully retrieved, check that the returned - // bounds match the range as stored. - if (observed_result == true) { - EXPECT_EQ(retrieved_base, range_test->address) - << "RetrieveRange id " << range_test->id - << ", side " << side << ", offset " << offset << " FAILED."; - EXPECT_EQ(retrieved_size, range_test->size) - << "RetrieveRange id " << range_test->id - << ", side " << side << ", offset " << offset << " FAILED."; - } - - // Now, check RetrieveNearestRange. The nearest range is always - // expected to be different from the test range when checking one - // less than the low side. - bool expected_nearest = range_test->expect_storable; - if (!side && offset < 0) - expected_nearest = false; - - AddressType nearest_base; - AddressType nearest_size; - bool retrieved_nearest = range_map->RetrieveNearestRange(address, - id, - &nearest_base, - &nearest_size); - - // When checking one greater than the high side, RetrieveNearestRange - // should usually return the test range. When a different range begins - // at that address, though, then RetrieveNearestRange should return the - // range at the address instead of the test range. - if (side && offset > 0 && nearest_base == address) { - expected_nearest = false; - } - - bool observed_nearest = retrieved_nearest && - *id == range_test->id; - - EXPECT_EQ(observed_nearest, expected_nearest) - << "RetrieveRange id " << range_test->id - << ", side " << side << ", offset " << offset << " FAILED."; - - // If a range was successfully retrieved, check that the returned - // bounds match the range as stored. - if (expected_nearest ==true) { - EXPECT_EQ(nearest_base, range_test->address) - << "RetrieveRange id " << range_test->id - << ", side " << side << ", offset " << offset << " FAILED."; - EXPECT_EQ(nearest_size, range_test->size) - << "RetrieveRange id " << range_test->id - << ", side " << side << ", offset " << offset << " FAILED."; - } - } - } -} - -void TestStaticRangeMap::RetrieveIndexTest(const TestMap* range_map, int set) { - AddressType last_base = 0; - const EntryType* last_entry = 0; - const EntryType* entry; - int object_count = range_map->GetCount(); - for (int object_index = 0; object_index < object_count; ++object_index) { - AddressType base; - ASSERT_TRUE(range_map->RetrieveRangeAtIndex(object_index, - entry, - &base, - NULL)) - << "FAILED: RetrieveRangeAtIndex set " << set - << " index " << object_index; - - ASSERT_TRUE(entry) << "FAILED: RetrieveRangeAtIndex set " << set - << " index " << object_index; - - // It's impossible to do these comparisons unless there's a previous - // object to compare against. - if (last_entry) { - // The object must be different from the last_entry one. - EXPECT_NE(*entry, *last_entry) << "FAILED: RetrieveRangeAtIndex set " - << set << " index " << object_index; - // Each object must have a base greater than the previous object's base. - EXPECT_GT(base, last_base) << "FAILED: RetrieveRangeAtIndex set " << set - << " index " << object_index; - } - last_entry = entry; - last_base = base; - } - - // Make sure that RetrieveRangeAtIndex doesn't allow lookups at indices that - // are too high. - ASSERT_FALSE(range_map->RetrieveRangeAtIndex( - object_count, entry, NULL, NULL)) << "FAILED: RetrieveRangeAtIndex set " - << set << " index " << object_count - << " (too large)"; -} - -// RunTests runs a series of test sets. -void TestStaticRangeMap::RunTestCase(int test_case) { - // Maintain the range map in a pointer so that deletion can be meaningfully - // tested. - scoped_ptr<RMap> rmap(new RMap()); - - const RangeTest* range_tests = range_test_sets[test_case].range_tests; - unsigned int range_test_count = range_test_sets[test_case].range_test_count; - - // Run the StoreRange test, which validates StoreRange and initializes - // the RangeMap with data for the RetrieveRange test. - int stored_count = 0; // The number of ranges successfully stored - for (unsigned int range_test_index = 0; - range_test_index < range_test_count; - ++range_test_index) { - const RangeTest* range_test = &range_tests[range_test_index]; - StoreTest(rmap.get(), range_test); - - if (range_test->expect_storable) - ++stored_count; - } - - scoped_array<char> memaddr(serializer_.Serialize(*rmap, NULL)); - scoped_ptr<TestMap> static_range_map(new TestMap(memaddr.get())); - - // The RangeMap's own count of objects should also match. - EXPECT_EQ(static_range_map->GetCount(), stored_count); - - // Run the RetrieveRange test - for (unsigned int range_test_index = 0; - range_test_index < range_test_count; - ++range_test_index) { - const RangeTest* range_test = &range_tests[range_test_index]; - RetrieveTest(static_range_map.get(), range_test); - } - - RetrieveIndexTest(static_range_map.get(), test_case); -} - -TEST_F(TestStaticRangeMap, TestCase0) { - int test_case = 0; - RunTestCase(test_case); -} - -TEST_F(TestStaticRangeMap, TestCase1) { - int test_case = 1; - RunTestCase(test_case); -} - -TEST_F(TestStaticRangeMap, TestCase2) { - int test_case = 2; - RunTestCase(test_case); -} - -TEST_F(TestStaticRangeMap, TestCase3) { - int test_case = 3; - RunTestCase(test_case); -} - -TEST_F(TestStaticRangeMap, RunTestCase0Again) { - int test_case = 0; - RunTestCase(test_case); -} - -} // namespace google_breakpad - -int main(int argc, char *argv[]) { - ::testing::InitGoogleTest(&argc, argv); - - return RUN_ALL_TESTS(); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.cc b/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.cc deleted file mode 100644 index a6ee26a26..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.cc +++ /dev/null @@ -1,6418 +0,0 @@ -// Copyright (c) 2015 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ntstatus_reason_win.h: Windows NTSTATUS code to string. -// -// Provides a means to convert NTSTATUS codes to strings. -// -// Author: Ben Wagner - -#include <string> - -#include "common/stdio_wrapper.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_exception_win32.h" -#include "processor/symbolic_constants_win.h" - -namespace google_breakpad { - -string NTStatusToString(uint32_t ntstatus) { - string reason; - // The content of this switch was created from ntstatus.h in the 8.1 SDK with - // - // egrep '#define [A-Z_0-9]+\s+\(\(NTSTATUS\)0xC[0-9A-F]+L\)' ntstatus.h - // | tr -d '\r' - // | sed -r 's@#define ([A-Z_0-9]+)\s+\(\(NTSTATUS\)(0xC[0-9A-F]+)L\).*@\2 \1@' - // | sort - // | sed -r 's@(0xC[0-9A-F]+) ([A-Z_0-9]+)@ case MD_NTSTATUS_WIN_\2:\n reason = "\2";\n break;@' - // - // With easy copy to clipboard with - // | xclip -selection c # on linux - // | clip # on windows - // | pbcopy # on mac - // - // and then the default case added. - switch (ntstatus) { - case MD_NTSTATUS_WIN_STATUS_UNSUCCESSFUL: - reason = "STATUS_UNSUCCESSFUL"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_IMPLEMENTED: - reason = "STATUS_NOT_IMPLEMENTED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_INFO_CLASS: - reason = "STATUS_INVALID_INFO_CLASS"; - break; - case MD_NTSTATUS_WIN_STATUS_INFO_LENGTH_MISMATCH: - reason = "STATUS_INFO_LENGTH_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCESS_VIOLATION: - reason = "STATUS_ACCESS_VIOLATION"; - break; - case MD_NTSTATUS_WIN_STATUS_IN_PAGE_ERROR: - reason = "STATUS_IN_PAGE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA: - reason = "STATUS_PAGEFILE_QUOTA"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_HANDLE: - reason = "STATUS_INVALID_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_STACK: - reason = "STATUS_BAD_INITIAL_STACK"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_INITIAL_PC: - reason = "STATUS_BAD_INITIAL_PC"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_CID: - reason = "STATUS_INVALID_CID"; - break; - case MD_NTSTATUS_WIN_STATUS_TIMER_NOT_CANCELED: - reason = "STATUS_TIMER_NOT_CANCELED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER: - reason = "STATUS_INVALID_PARAMETER"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_DEVICE: - reason = "STATUS_NO_SUCH_DEVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_FILE: - reason = "STATUS_NO_SUCH_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_REQUEST: - reason = "STATUS_INVALID_DEVICE_REQUEST"; - break; - case MD_NTSTATUS_WIN_STATUS_END_OF_FILE: - reason = "STATUS_END_OF_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_WRONG_VOLUME: - reason = "STATUS_WRONG_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_MEDIA_IN_DEVICE: - reason = "STATUS_NO_MEDIA_IN_DEVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_MEDIA: - reason = "STATUS_UNRECOGNIZED_MEDIA"; - break; - case MD_NTSTATUS_WIN_STATUS_NONEXISTENT_SECTOR: - reason = "STATUS_NONEXISTENT_SECTOR"; - break; - case MD_NTSTATUS_WIN_STATUS_MORE_PROCESSING_REQUIRED: - reason = "STATUS_MORE_PROCESSING_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_MEMORY: - reason = "STATUS_NO_MEMORY"; - break; - case MD_NTSTATUS_WIN_STATUS_CONFLICTING_ADDRESSES: - reason = "STATUS_CONFLICTING_ADDRESSES"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_VIEW: - reason = "STATUS_NOT_MAPPED_VIEW"; - break; - case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_FREE_VM: - reason = "STATUS_UNABLE_TO_FREE_VM"; - break; - case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DELETE_SECTION: - reason = "STATUS_UNABLE_TO_DELETE_SECTION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_SYSTEM_SERVICE: - reason = "STATUS_INVALID_SYSTEM_SERVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_ILLEGAL_INSTRUCTION: - reason = "STATUS_ILLEGAL_INSTRUCTION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_SEQUENCE: - reason = "STATUS_INVALID_LOCK_SEQUENCE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_VIEW_SIZE: - reason = "STATUS_INVALID_VIEW_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_FILE_FOR_SECTION: - reason = "STATUS_INVALID_FILE_FOR_SECTION"; - break; - case MD_NTSTATUS_WIN_STATUS_ALREADY_COMMITTED: - reason = "STATUS_ALREADY_COMMITTED"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCESS_DENIED: - reason = "STATUS_ACCESS_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_BUFFER_TOO_SMALL: - reason = "STATUS_BUFFER_TOO_SMALL"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECT_TYPE_MISMATCH: - reason = "STATUS_OBJECT_TYPE_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_NONCONTINUABLE_EXCEPTION: - reason = "STATUS_NONCONTINUABLE_EXCEPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_DISPOSITION: - reason = "STATUS_INVALID_DISPOSITION"; - break; - case MD_NTSTATUS_WIN_STATUS_UNWIND: - reason = "STATUS_UNWIND"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_STACK: - reason = "STATUS_BAD_STACK"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_UNWIND_TARGET: - reason = "STATUS_INVALID_UNWIND_TARGET"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_LOCKED: - reason = "STATUS_NOT_LOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_PARITY_ERROR: - reason = "STATUS_PARITY_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_DECOMMIT_VM: - reason = "STATUS_UNABLE_TO_DECOMMIT_VM"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_COMMITTED: - reason = "STATUS_NOT_COMMITTED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PORT_ATTRIBUTES: - reason = "STATUS_INVALID_PORT_ATTRIBUTES"; - break; - case MD_NTSTATUS_WIN_STATUS_PORT_MESSAGE_TOO_LONG: - reason = "STATUS_PORT_MESSAGE_TOO_LONG"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_MIX: - reason = "STATUS_INVALID_PARAMETER_MIX"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_QUOTA_LOWER: - reason = "STATUS_INVALID_QUOTA_LOWER"; - break; - case MD_NTSTATUS_WIN_STATUS_DISK_CORRUPT_ERROR: - reason = "STATUS_DISK_CORRUPT_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_INVALID: - reason = "STATUS_OBJECT_NAME_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_NOT_FOUND: - reason = "STATUS_OBJECT_NAME_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECT_NAME_COLLISION: - reason = "STATUS_OBJECT_NAME_COLLISION"; - break; - case MD_NTSTATUS_WIN_STATUS_PORT_DISCONNECTED: - reason = "STATUS_PORT_DISCONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_ALREADY_ATTACHED: - reason = "STATUS_DEVICE_ALREADY_ATTACHED"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_INVALID: - reason = "STATUS_OBJECT_PATH_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_NOT_FOUND: - reason = "STATUS_OBJECT_PATH_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECT_PATH_SYNTAX_BAD: - reason = "STATUS_OBJECT_PATH_SYNTAX_BAD"; - break; - case MD_NTSTATUS_WIN_STATUS_DATA_OVERRUN: - reason = "STATUS_DATA_OVERRUN"; - break; - case MD_NTSTATUS_WIN_STATUS_DATA_LATE_ERROR: - reason = "STATUS_DATA_LATE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_DATA_ERROR: - reason = "STATUS_DATA_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_CRC_ERROR: - reason = "STATUS_CRC_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_SECTION_TOO_BIG: - reason = "STATUS_SECTION_TOO_BIG"; - break; - case MD_NTSTATUS_WIN_STATUS_PORT_CONNECTION_REFUSED: - reason = "STATUS_PORT_CONNECTION_REFUSED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PORT_HANDLE: - reason = "STATUS_INVALID_PORT_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_SHARING_VIOLATION: - reason = "STATUS_SHARING_VIOLATION"; - break; - case MD_NTSTATUS_WIN_STATUS_QUOTA_EXCEEDED: - reason = "STATUS_QUOTA_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PAGE_PROTECTION: - reason = "STATUS_INVALID_PAGE_PROTECTION"; - break; - case MD_NTSTATUS_WIN_STATUS_MUTANT_NOT_OWNED: - reason = "STATUS_MUTANT_NOT_OWNED"; - break; - case MD_NTSTATUS_WIN_STATUS_SEMAPHORE_LIMIT_EXCEEDED: - reason = "STATUS_SEMAPHORE_LIMIT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_SET: - reason = "STATUS_PORT_ALREADY_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_SECTION_NOT_IMAGE: - reason = "STATUS_SECTION_NOT_IMAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_SUSPEND_COUNT_EXCEEDED: - reason = "STATUS_SUSPEND_COUNT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_THREAD_IS_TERMINATING: - reason = "STATUS_THREAD_IS_TERMINATING"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_WORKING_SET_LIMIT: - reason = "STATUS_BAD_WORKING_SET_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_FILE_MAP: - reason = "STATUS_INCOMPATIBLE_FILE_MAP"; - break; - case MD_NTSTATUS_WIN_STATUS_SECTION_PROTECTION: - reason = "STATUS_SECTION_PROTECTION"; - break; - case MD_NTSTATUS_WIN_STATUS_EAS_NOT_SUPPORTED: - reason = "STATUS_EAS_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_EA_TOO_LARGE: - reason = "STATUS_EA_TOO_LARGE"; - break; - case MD_NTSTATUS_WIN_STATUS_NONEXISTENT_EA_ENTRY: - reason = "STATUS_NONEXISTENT_EA_ENTRY"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_EAS_ON_FILE: - reason = "STATUS_NO_EAS_ON_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_EA_CORRUPT_ERROR: - reason = "STATUS_EA_CORRUPT_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_LOCK_CONFLICT: - reason = "STATUS_FILE_LOCK_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_LOCK_NOT_GRANTED: - reason = "STATUS_LOCK_NOT_GRANTED"; - break; - case MD_NTSTATUS_WIN_STATUS_DELETE_PENDING: - reason = "STATUS_DELETE_PENDING"; - break; - case MD_NTSTATUS_WIN_STATUS_CTL_FILE_NOT_SUPPORTED: - reason = "STATUS_CTL_FILE_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_UNKNOWN_REVISION: - reason = "STATUS_UNKNOWN_REVISION"; - break; - case MD_NTSTATUS_WIN_STATUS_REVISION_MISMATCH: - reason = "STATUS_REVISION_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_OWNER: - reason = "STATUS_INVALID_OWNER"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PRIMARY_GROUP: - reason = "STATUS_INVALID_PRIMARY_GROUP"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_IMPERSONATION_TOKEN: - reason = "STATUS_NO_IMPERSONATION_TOKEN"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_DISABLE_MANDATORY: - reason = "STATUS_CANT_DISABLE_MANDATORY"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_LOGON_SERVERS: - reason = "STATUS_NO_LOGON_SERVERS"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_LOGON_SESSION: - reason = "STATUS_NO_SUCH_LOGON_SESSION"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_PRIVILEGE: - reason = "STATUS_NO_SUCH_PRIVILEGE"; - break; - case MD_NTSTATUS_WIN_STATUS_PRIVILEGE_NOT_HELD: - reason = "STATUS_PRIVILEGE_NOT_HELD"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_ACCOUNT_NAME: - reason = "STATUS_INVALID_ACCOUNT_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_USER_EXISTS: - reason = "STATUS_USER_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_USER: - reason = "STATUS_NO_SUCH_USER"; - break; - case MD_NTSTATUS_WIN_STATUS_GROUP_EXISTS: - reason = "STATUS_GROUP_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_GROUP: - reason = "STATUS_NO_SUCH_GROUP"; - break; - case MD_NTSTATUS_WIN_STATUS_MEMBER_IN_GROUP: - reason = "STATUS_MEMBER_IN_GROUP"; - break; - case MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_GROUP: - reason = "STATUS_MEMBER_NOT_IN_GROUP"; - break; - case MD_NTSTATUS_WIN_STATUS_LAST_ADMIN: - reason = "STATUS_LAST_ADMIN"; - break; - case MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD: - reason = "STATUS_WRONG_PASSWORD"; - break; - case MD_NTSTATUS_WIN_STATUS_ILL_FORMED_PASSWORD: - reason = "STATUS_ILL_FORMED_PASSWORD"; - break; - case MD_NTSTATUS_WIN_STATUS_PASSWORD_RESTRICTION: - reason = "STATUS_PASSWORD_RESTRICTION"; - break; - case MD_NTSTATUS_WIN_STATUS_LOGON_FAILURE: - reason = "STATUS_LOGON_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCOUNT_RESTRICTION: - reason = "STATUS_ACCOUNT_RESTRICTION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_HOURS: - reason = "STATUS_INVALID_LOGON_HOURS"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_WORKSTATION: - reason = "STATUS_INVALID_WORKSTATION"; - break; - case MD_NTSTATUS_WIN_STATUS_PASSWORD_EXPIRED: - reason = "STATUS_PASSWORD_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCOUNT_DISABLED: - reason = "STATUS_ACCOUNT_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_NONE_MAPPED: - reason = "STATUS_NONE_MAPPED"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_LUIDS_REQUESTED: - reason = "STATUS_TOO_MANY_LUIDS_REQUESTED"; - break; - case MD_NTSTATUS_WIN_STATUS_LUIDS_EXHAUSTED: - reason = "STATUS_LUIDS_EXHAUSTED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_SUB_AUTHORITY: - reason = "STATUS_INVALID_SUB_AUTHORITY"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_ACL: - reason = "STATUS_INVALID_ACL"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_SID: - reason = "STATUS_INVALID_SID"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_SECURITY_DESCR: - reason = "STATUS_INVALID_SECURITY_DESCR"; - break; - case MD_NTSTATUS_WIN_STATUS_PROCEDURE_NOT_FOUND: - reason = "STATUS_PROCEDURE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_FORMAT: - reason = "STATUS_INVALID_IMAGE_FORMAT"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_TOKEN: - reason = "STATUS_NO_TOKEN"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_INHERITANCE_ACL: - reason = "STATUS_BAD_INHERITANCE_ACL"; - break; - case MD_NTSTATUS_WIN_STATUS_RANGE_NOT_LOCKED: - reason = "STATUS_RANGE_NOT_LOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_DISK_FULL: - reason = "STATUS_DISK_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_SERVER_DISABLED: - reason = "STATUS_SERVER_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_SERVER_NOT_DISABLED: - reason = "STATUS_SERVER_NOT_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_GUIDS_REQUESTED: - reason = "STATUS_TOO_MANY_GUIDS_REQUESTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GUIDS_EXHAUSTED: - reason = "STATUS_GUIDS_EXHAUSTED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_ID_AUTHORITY: - reason = "STATUS_INVALID_ID_AUTHORITY"; - break; - case MD_NTSTATUS_WIN_STATUS_AGENTS_EXHAUSTED: - reason = "STATUS_AGENTS_EXHAUSTED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_VOLUME_LABEL: - reason = "STATUS_INVALID_VOLUME_LABEL"; - break; - case MD_NTSTATUS_WIN_STATUS_SECTION_NOT_EXTENDED: - reason = "STATUS_SECTION_NOT_EXTENDED"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_MAPPED_DATA: - reason = "STATUS_NOT_MAPPED_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_RESOURCE_DATA_NOT_FOUND: - reason = "STATUS_RESOURCE_DATA_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_RESOURCE_TYPE_NOT_FOUND: - reason = "STATUS_RESOURCE_TYPE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_RESOURCE_NAME_NOT_FOUND: - reason = "STATUS_RESOURCE_NAME_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_ARRAY_BOUNDS_EXCEEDED: - reason = "STATUS_ARRAY_BOUNDS_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOAT_DENORMAL_OPERAND: - reason = "STATUS_FLOAT_DENORMAL_OPERAND"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOAT_DIVIDE_BY_ZERO: - reason = "STATUS_FLOAT_DIVIDE_BY_ZERO"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOAT_INEXACT_RESULT: - reason = "STATUS_FLOAT_INEXACT_RESULT"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOAT_INVALID_OPERATION: - reason = "STATUS_FLOAT_INVALID_OPERATION"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOAT_OVERFLOW: - reason = "STATUS_FLOAT_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOAT_STACK_CHECK: - reason = "STATUS_FLOAT_STACK_CHECK"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOAT_UNDERFLOW: - reason = "STATUS_FLOAT_UNDERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_INTEGER_DIVIDE_BY_ZERO: - reason = "STATUS_INTEGER_DIVIDE_BY_ZERO"; - break; - case MD_NTSTATUS_WIN_STATUS_INTEGER_OVERFLOW: - reason = "STATUS_INTEGER_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_PRIVILEGED_INSTRUCTION: - reason = "STATUS_PRIVILEGED_INSTRUCTION"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_PAGING_FILES: - reason = "STATUS_TOO_MANY_PAGING_FILES"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_INVALID: - reason = "STATUS_FILE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_ALLOTTED_SPACE_EXCEEDED: - reason = "STATUS_ALLOTTED_SPACE_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCES: - reason = "STATUS_INSUFFICIENT_RESOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_DFS_EXIT_PATH_FOUND: - reason = "STATUS_DFS_EXIT_PATH_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_DATA_ERROR: - reason = "STATUS_DEVICE_DATA_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_CONNECTED: - reason = "STATUS_DEVICE_NOT_CONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_POWER_FAILURE: - reason = "STATUS_DEVICE_POWER_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_FREE_VM_NOT_AT_BASE: - reason = "STATUS_FREE_VM_NOT_AT_BASE"; - break; - case MD_NTSTATUS_WIN_STATUS_MEMORY_NOT_ALLOCATED: - reason = "STATUS_MEMORY_NOT_ALLOCATED"; - break; - case MD_NTSTATUS_WIN_STATUS_WORKING_SET_QUOTA: - reason = "STATUS_WORKING_SET_QUOTA"; - break; - case MD_NTSTATUS_WIN_STATUS_MEDIA_WRITE_PROTECTED: - reason = "STATUS_MEDIA_WRITE_PROTECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_READY: - reason = "STATUS_DEVICE_NOT_READY"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_GROUP_ATTRIBUTES: - reason = "STATUS_INVALID_GROUP_ATTRIBUTES"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_IMPERSONATION_LEVEL: - reason = "STATUS_BAD_IMPERSONATION_LEVEL"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_OPEN_ANONYMOUS: - reason = "STATUS_CANT_OPEN_ANONYMOUS"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_VALIDATION_CLASS: - reason = "STATUS_BAD_VALIDATION_CLASS"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_TOKEN_TYPE: - reason = "STATUS_BAD_TOKEN_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_MASTER_BOOT_RECORD: - reason = "STATUS_BAD_MASTER_BOOT_RECORD"; - break; - case MD_NTSTATUS_WIN_STATUS_INSTRUCTION_MISALIGNMENT: - reason = "STATUS_INSTRUCTION_MISALIGNMENT"; - break; - case MD_NTSTATUS_WIN_STATUS_INSTANCE_NOT_AVAILABLE: - reason = "STATUS_INSTANCE_NOT_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_PIPE_NOT_AVAILABLE: - reason = "STATUS_PIPE_NOT_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PIPE_STATE: - reason = "STATUS_INVALID_PIPE_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_PIPE_BUSY: - reason = "STATUS_PIPE_BUSY"; - break; - case MD_NTSTATUS_WIN_STATUS_ILLEGAL_FUNCTION: - reason = "STATUS_ILLEGAL_FUNCTION"; - break; - case MD_NTSTATUS_WIN_STATUS_PIPE_DISCONNECTED: - reason = "STATUS_PIPE_DISCONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_PIPE_CLOSING: - reason = "STATUS_PIPE_CLOSING"; - break; - case MD_NTSTATUS_WIN_STATUS_PIPE_CONNECTED: - reason = "STATUS_PIPE_CONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_PIPE_LISTENING: - reason = "STATUS_PIPE_LISTENING"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_READ_MODE: - reason = "STATUS_INVALID_READ_MODE"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_TIMEOUT: - reason = "STATUS_IO_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_FORCED_CLOSED: - reason = "STATUS_FILE_FORCED_CLOSED"; - break; - case MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STARTED: - reason = "STATUS_PROFILING_NOT_STARTED"; - break; - case MD_NTSTATUS_WIN_STATUS_PROFILING_NOT_STOPPED: - reason = "STATUS_PROFILING_NOT_STOPPED"; - break; - case MD_NTSTATUS_WIN_STATUS_COULD_NOT_INTERPRET: - reason = "STATUS_COULD_NOT_INTERPRET"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_IS_A_DIRECTORY: - reason = "STATUS_FILE_IS_A_DIRECTORY"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED: - reason = "STATUS_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_REMOTE_NOT_LISTENING: - reason = "STATUS_REMOTE_NOT_LISTENING"; - break; - case MD_NTSTATUS_WIN_STATUS_DUPLICATE_NAME: - reason = "STATUS_DUPLICATE_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_PATH: - reason = "STATUS_BAD_NETWORK_PATH"; - break; - case MD_NTSTATUS_WIN_STATUS_NETWORK_BUSY: - reason = "STATUS_NETWORK_BUSY"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_DOES_NOT_EXIST: - reason = "STATUS_DEVICE_DOES_NOT_EXIST"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_COMMANDS: - reason = "STATUS_TOO_MANY_COMMANDS"; - break; - case MD_NTSTATUS_WIN_STATUS_ADAPTER_HARDWARE_ERROR: - reason = "STATUS_ADAPTER_HARDWARE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_NETWORK_RESPONSE: - reason = "STATUS_INVALID_NETWORK_RESPONSE"; - break; - case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_NETWORK_ERROR: - reason = "STATUS_UNEXPECTED_NETWORK_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_REMOTE_ADAPTER: - reason = "STATUS_BAD_REMOTE_ADAPTER"; - break; - case MD_NTSTATUS_WIN_STATUS_PRINT_QUEUE_FULL: - reason = "STATUS_PRINT_QUEUE_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SPOOL_SPACE: - reason = "STATUS_NO_SPOOL_SPACE"; - break; - case MD_NTSTATUS_WIN_STATUS_PRINT_CANCELLED: - reason = "STATUS_PRINT_CANCELLED"; - break; - case MD_NTSTATUS_WIN_STATUS_NETWORK_NAME_DELETED: - reason = "STATUS_NETWORK_NAME_DELETED"; - break; - case MD_NTSTATUS_WIN_STATUS_NETWORK_ACCESS_DENIED: - reason = "STATUS_NETWORK_ACCESS_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_DEVICE_TYPE: - reason = "STATUS_BAD_DEVICE_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_NETWORK_NAME: - reason = "STATUS_BAD_NETWORK_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_NAMES: - reason = "STATUS_TOO_MANY_NAMES"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_SESSIONS: - reason = "STATUS_TOO_MANY_SESSIONS"; - break; - case MD_NTSTATUS_WIN_STATUS_SHARING_PAUSED: - reason = "STATUS_SHARING_PAUSED"; - break; - case MD_NTSTATUS_WIN_STATUS_REQUEST_NOT_ACCEPTED: - reason = "STATUS_REQUEST_NOT_ACCEPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_REDIRECTOR_PAUSED: - reason = "STATUS_REDIRECTOR_PAUSED"; - break; - case MD_NTSTATUS_WIN_STATUS_NET_WRITE_FAULT: - reason = "STATUS_NET_WRITE_FAULT"; - break; - case MD_NTSTATUS_WIN_STATUS_PROFILING_AT_LIMIT: - reason = "STATUS_PROFILING_AT_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_SAME_DEVICE: - reason = "STATUS_NOT_SAME_DEVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_RENAMED: - reason = "STATUS_FILE_RENAMED"; - break; - case MD_NTSTATUS_WIN_STATUS_VIRTUAL_CIRCUIT_CLOSED: - reason = "STATUS_VIRTUAL_CIRCUIT_CLOSED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SECURITY_ON_OBJECT: - reason = "STATUS_NO_SECURITY_ON_OBJECT"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_WAIT: - reason = "STATUS_CANT_WAIT"; - break; - case MD_NTSTATUS_WIN_STATUS_PIPE_EMPTY: - reason = "STATUS_PIPE_EMPTY"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_ACCESS_DOMAIN_INFO: - reason = "STATUS_CANT_ACCESS_DOMAIN_INFO"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_TERMINATE_SELF: - reason = "STATUS_CANT_TERMINATE_SELF"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_SERVER_STATE: - reason = "STATUS_INVALID_SERVER_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_STATE: - reason = "STATUS_INVALID_DOMAIN_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_DOMAIN_ROLE: - reason = "STATUS_INVALID_DOMAIN_ROLE"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_DOMAIN: - reason = "STATUS_NO_SUCH_DOMAIN"; - break; - case MD_NTSTATUS_WIN_STATUS_DOMAIN_EXISTS: - reason = "STATUS_DOMAIN_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_DOMAIN_LIMIT_EXCEEDED: - reason = "STATUS_DOMAIN_LIMIT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_OPLOCK_NOT_GRANTED: - reason = "STATUS_OPLOCK_NOT_GRANTED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_OPLOCK_PROTOCOL: - reason = "STATUS_INVALID_OPLOCK_PROTOCOL"; - break; - case MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_CORRUPTION: - reason = "STATUS_INTERNAL_DB_CORRUPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_INTERNAL_ERROR: - reason = "STATUS_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_GENERIC_NOT_MAPPED: - reason = "STATUS_GENERIC_NOT_MAPPED"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_DESCRIPTOR_FORMAT: - reason = "STATUS_BAD_DESCRIPTOR_FORMAT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_USER_BUFFER: - reason = "STATUS_INVALID_USER_BUFFER"; - break; - case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_IO_ERROR: - reason = "STATUS_UNEXPECTED_IO_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_CREATE_ERR: - reason = "STATUS_UNEXPECTED_MM_CREATE_ERR"; - break; - case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_MAP_ERROR: - reason = "STATUS_UNEXPECTED_MM_MAP_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_UNEXPECTED_MM_EXTEND_ERR: - reason = "STATUS_UNEXPECTED_MM_EXTEND_ERR"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_LOGON_PROCESS: - reason = "STATUS_NOT_LOGON_PROCESS"; - break; - case MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_EXISTS: - reason = "STATUS_LOGON_SESSION_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_1: - reason = "STATUS_INVALID_PARAMETER_1"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_2: - reason = "STATUS_INVALID_PARAMETER_2"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_3: - reason = "STATUS_INVALID_PARAMETER_3"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_4: - reason = "STATUS_INVALID_PARAMETER_4"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_5: - reason = "STATUS_INVALID_PARAMETER_5"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_6: - reason = "STATUS_INVALID_PARAMETER_6"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_7: - reason = "STATUS_INVALID_PARAMETER_7"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_8: - reason = "STATUS_INVALID_PARAMETER_8"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_9: - reason = "STATUS_INVALID_PARAMETER_9"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_10: - reason = "STATUS_INVALID_PARAMETER_10"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_11: - reason = "STATUS_INVALID_PARAMETER_11"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PARAMETER_12: - reason = "STATUS_INVALID_PARAMETER_12"; - break; - case MD_NTSTATUS_WIN_STATUS_REDIRECTOR_NOT_STARTED: - reason = "STATUS_REDIRECTOR_NOT_STARTED"; - break; - case MD_NTSTATUS_WIN_STATUS_REDIRECTOR_STARTED: - reason = "STATUS_REDIRECTOR_STARTED"; - break; - case MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW: - reason = "STATUS_STACK_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_PACKAGE: - reason = "STATUS_NO_SUCH_PACKAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_FUNCTION_TABLE: - reason = "STATUS_BAD_FUNCTION_TABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_VARIABLE_NOT_FOUND: - reason = "STATUS_VARIABLE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_EMPTY: - reason = "STATUS_DIRECTORY_NOT_EMPTY"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_CORRUPT_ERROR: - reason = "STATUS_FILE_CORRUPT_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_A_DIRECTORY: - reason = "STATUS_NOT_A_DIRECTORY"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_LOGON_SESSION_STATE: - reason = "STATUS_BAD_LOGON_SESSION_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_LOGON_SESSION_COLLISION: - reason = "STATUS_LOGON_SESSION_COLLISION"; - break; - case MD_NTSTATUS_WIN_STATUS_NAME_TOO_LONG: - reason = "STATUS_NAME_TOO_LONG"; - break; - case MD_NTSTATUS_WIN_STATUS_FILES_OPEN: - reason = "STATUS_FILES_OPEN"; - break; - case MD_NTSTATUS_WIN_STATUS_CONNECTION_IN_USE: - reason = "STATUS_CONNECTION_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_MESSAGE_NOT_FOUND: - reason = "STATUS_MESSAGE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_PROCESS_IS_TERMINATING: - reason = "STATUS_PROCESS_IS_TERMINATING"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_LOGON_TYPE: - reason = "STATUS_INVALID_LOGON_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_GUID_TRANSLATION: - reason = "STATUS_NO_GUID_TRANSLATION"; - break; - case MD_NTSTATUS_WIN_STATUS_CANNOT_IMPERSONATE: - reason = "STATUS_CANNOT_IMPERSONATE"; - break; - case MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED: - reason = "STATUS_IMAGE_ALREADY_LOADED"; - break; - case MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_PRESENT: - reason = "STATUS_ABIOS_NOT_PRESENT"; - break; - case MD_NTSTATUS_WIN_STATUS_ABIOS_LID_NOT_EXIST: - reason = "STATUS_ABIOS_LID_NOT_EXIST"; - break; - case MD_NTSTATUS_WIN_STATUS_ABIOS_LID_ALREADY_OWNED: - reason = "STATUS_ABIOS_LID_ALREADY_OWNED"; - break; - case MD_NTSTATUS_WIN_STATUS_ABIOS_NOT_LID_OWNER: - reason = "STATUS_ABIOS_NOT_LID_OWNER"; - break; - case MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_COMMAND: - reason = "STATUS_ABIOS_INVALID_COMMAND"; - break; - case MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_LID: - reason = "STATUS_ABIOS_INVALID_LID"; - break; - case MD_NTSTATUS_WIN_STATUS_ABIOS_SELECTOR_NOT_AVAILABLE: - reason = "STATUS_ABIOS_SELECTOR_NOT_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_ABIOS_INVALID_SELECTOR: - reason = "STATUS_ABIOS_INVALID_SELECTOR"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_LDT: - reason = "STATUS_NO_LDT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_LDT_SIZE: - reason = "STATUS_INVALID_LDT_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_LDT_OFFSET: - reason = "STATUS_INVALID_LDT_OFFSET"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_LDT_DESCRIPTOR: - reason = "STATUS_INVALID_LDT_DESCRIPTOR"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NE_FORMAT: - reason = "STATUS_INVALID_IMAGE_NE_FORMAT"; - break; - case MD_NTSTATUS_WIN_STATUS_RXACT_INVALID_STATE: - reason = "STATUS_RXACT_INVALID_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_RXACT_COMMIT_FAILURE: - reason = "STATUS_RXACT_COMMIT_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_MAPPED_FILE_SIZE_ZERO: - reason = "STATUS_MAPPED_FILE_SIZE_ZERO"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_OPENED_FILES: - reason = "STATUS_TOO_MANY_OPENED_FILES"; - break; - case MD_NTSTATUS_WIN_STATUS_CANCELLED: - reason = "STATUS_CANCELLED"; - break; - case MD_NTSTATUS_WIN_STATUS_CANNOT_DELETE: - reason = "STATUS_CANNOT_DELETE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_COMPUTER_NAME: - reason = "STATUS_INVALID_COMPUTER_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_DELETED: - reason = "STATUS_FILE_DELETED"; - break; - case MD_NTSTATUS_WIN_STATUS_SPECIAL_ACCOUNT: - reason = "STATUS_SPECIAL_ACCOUNT"; - break; - case MD_NTSTATUS_WIN_STATUS_SPECIAL_GROUP: - reason = "STATUS_SPECIAL_GROUP"; - break; - case MD_NTSTATUS_WIN_STATUS_SPECIAL_USER: - reason = "STATUS_SPECIAL_USER"; - break; - case MD_NTSTATUS_WIN_STATUS_MEMBERS_PRIMARY_GROUP: - reason = "STATUS_MEMBERS_PRIMARY_GROUP"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_CLOSED: - reason = "STATUS_FILE_CLOSED"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_THREADS: - reason = "STATUS_TOO_MANY_THREADS"; - break; - case MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_PROCESS: - reason = "STATUS_THREAD_NOT_IN_PROCESS"; - break; - case MD_NTSTATUS_WIN_STATUS_TOKEN_ALREADY_IN_USE: - reason = "STATUS_TOKEN_ALREADY_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_PAGEFILE_QUOTA_EXCEEDED: - reason = "STATUS_PAGEFILE_QUOTA_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_COMMITMENT_LIMIT: - reason = "STATUS_COMMITMENT_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_LE_FORMAT: - reason = "STATUS_INVALID_IMAGE_LE_FORMAT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_NOT_MZ: - reason = "STATUS_INVALID_IMAGE_NOT_MZ"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_PROTECT: - reason = "STATUS_INVALID_IMAGE_PROTECT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_16: - reason = "STATUS_INVALID_IMAGE_WIN_16"; - break; - case MD_NTSTATUS_WIN_STATUS_LOGON_SERVER_CONFLICT: - reason = "STATUS_LOGON_SERVER_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_TIME_DIFFERENCE_AT_DC: - reason = "STATUS_TIME_DIFFERENCE_AT_DC"; - break; - case MD_NTSTATUS_WIN_STATUS_SYNCHRONIZATION_REQUIRED: - reason = "STATUS_SYNCHRONIZATION_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_DLL_NOT_FOUND: - reason = "STATUS_DLL_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_OPEN_FAILED: - reason = "STATUS_OPEN_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_PRIVILEGE_FAILED: - reason = "STATUS_IO_PRIVILEGE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_ORDINAL_NOT_FOUND: - reason = "STATUS_ORDINAL_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_ENTRYPOINT_NOT_FOUND: - reason = "STATUS_ENTRYPOINT_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_CONTROL_C_EXIT: - reason = "STATUS_CONTROL_C_EXIT"; - break; - case MD_NTSTATUS_WIN_STATUS_LOCAL_DISCONNECT: - reason = "STATUS_LOCAL_DISCONNECT"; - break; - case MD_NTSTATUS_WIN_STATUS_REMOTE_DISCONNECT: - reason = "STATUS_REMOTE_DISCONNECT"; - break; - case MD_NTSTATUS_WIN_STATUS_REMOTE_RESOURCES: - reason = "STATUS_REMOTE_RESOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_LINK_FAILED: - reason = "STATUS_LINK_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_LINK_TIMEOUT: - reason = "STATUS_LINK_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_CONNECTION: - reason = "STATUS_INVALID_CONNECTION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS: - reason = "STATUS_INVALID_ADDRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED: - reason = "STATUS_DLL_INIT_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_MISSING_SYSTEMFILE: - reason = "STATUS_MISSING_SYSTEMFILE"; - break; - case MD_NTSTATUS_WIN_STATUS_UNHANDLED_EXCEPTION: - reason = "STATUS_UNHANDLED_EXCEPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_APP_INIT_FAILURE: - reason = "STATUS_APP_INIT_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_PAGEFILE_CREATE_FAILED: - reason = "STATUS_PAGEFILE_CREATE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_PAGEFILE: - reason = "STATUS_NO_PAGEFILE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_LEVEL: - reason = "STATUS_INVALID_LEVEL"; - break; - case MD_NTSTATUS_WIN_STATUS_WRONG_PASSWORD_CORE: - reason = "STATUS_WRONG_PASSWORD_CORE"; - break; - case MD_NTSTATUS_WIN_STATUS_ILLEGAL_FLOAT_CONTEXT: - reason = "STATUS_ILLEGAL_FLOAT_CONTEXT"; - break; - case MD_NTSTATUS_WIN_STATUS_PIPE_BROKEN: - reason = "STATUS_PIPE_BROKEN"; - break; - case MD_NTSTATUS_WIN_STATUS_REGISTRY_CORRUPT: - reason = "STATUS_REGISTRY_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_REGISTRY_IO_FAILED: - reason = "STATUS_REGISTRY_IO_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_EVENT_PAIR: - reason = "STATUS_NO_EVENT_PAIR"; - break; - case MD_NTSTATUS_WIN_STATUS_UNRECOGNIZED_VOLUME: - reason = "STATUS_UNRECOGNIZED_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_SERIAL_NO_DEVICE_INITED: - reason = "STATUS_SERIAL_NO_DEVICE_INITED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_ALIAS: - reason = "STATUS_NO_SUCH_ALIAS"; - break; - case MD_NTSTATUS_WIN_STATUS_MEMBER_NOT_IN_ALIAS: - reason = "STATUS_MEMBER_NOT_IN_ALIAS"; - break; - case MD_NTSTATUS_WIN_STATUS_MEMBER_IN_ALIAS: - reason = "STATUS_MEMBER_IN_ALIAS"; - break; - case MD_NTSTATUS_WIN_STATUS_ALIAS_EXISTS: - reason = "STATUS_ALIAS_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_LOGON_NOT_GRANTED: - reason = "STATUS_LOGON_NOT_GRANTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_SECRETS: - reason = "STATUS_TOO_MANY_SECRETS"; - break; - case MD_NTSTATUS_WIN_STATUS_SECRET_TOO_LONG: - reason = "STATUS_SECRET_TOO_LONG"; - break; - case MD_NTSTATUS_WIN_STATUS_INTERNAL_DB_ERROR: - reason = "STATUS_INTERNAL_DB_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_FULLSCREEN_MODE: - reason = "STATUS_FULLSCREEN_MODE"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_CONTEXT_IDS: - reason = "STATUS_TOO_MANY_CONTEXT_IDS"; - break; - case MD_NTSTATUS_WIN_STATUS_LOGON_TYPE_NOT_GRANTED: - reason = "STATUS_LOGON_TYPE_NOT_GRANTED"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_REGISTRY_FILE: - reason = "STATUS_NOT_REGISTRY_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_NT_CROSS_ENCRYPTION_REQUIRED: - reason = "STATUS_NT_CROSS_ENCRYPTION_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_DOMAIN_CTRLR_CONFIG_ERROR: - reason = "STATUS_DOMAIN_CTRLR_CONFIG_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_FT_MISSING_MEMBER: - reason = "STATUS_FT_MISSING_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_ILL_FORMED_SERVICE_ENTRY: - reason = "STATUS_ILL_FORMED_SERVICE_ENTRY"; - break; - case MD_NTSTATUS_WIN_STATUS_ILLEGAL_CHARACTER: - reason = "STATUS_ILLEGAL_CHARACTER"; - break; - case MD_NTSTATUS_WIN_STATUS_UNMAPPABLE_CHARACTER: - reason = "STATUS_UNMAPPABLE_CHARACTER"; - break; - case MD_NTSTATUS_WIN_STATUS_UNDEFINED_CHARACTER: - reason = "STATUS_UNDEFINED_CHARACTER"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOPPY_VOLUME: - reason = "STATUS_FLOPPY_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOPPY_ID_MARK_NOT_FOUND: - reason = "STATUS_FLOPPY_ID_MARK_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOPPY_WRONG_CYLINDER: - reason = "STATUS_FLOPPY_WRONG_CYLINDER"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOPPY_UNKNOWN_ERROR: - reason = "STATUS_FLOPPY_UNKNOWN_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOPPY_BAD_REGISTERS: - reason = "STATUS_FLOPPY_BAD_REGISTERS"; - break; - case MD_NTSTATUS_WIN_STATUS_DISK_RECALIBRATE_FAILED: - reason = "STATUS_DISK_RECALIBRATE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_DISK_OPERATION_FAILED: - reason = "STATUS_DISK_OPERATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_DISK_RESET_FAILED: - reason = "STATUS_DISK_RESET_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_SHARED_IRQ_BUSY: - reason = "STATUS_SHARED_IRQ_BUSY"; - break; - case MD_NTSTATUS_WIN_STATUS_FT_ORPHANING: - reason = "STATUS_FT_ORPHANING"; - break; - case MD_NTSTATUS_WIN_STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT: - reason = "STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_PARTITION_FAILURE: - reason = "STATUS_PARTITION_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_BLOCK_LENGTH: - reason = "STATUS_INVALID_BLOCK_LENGTH"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_NOT_PARTITIONED: - reason = "STATUS_DEVICE_NOT_PARTITIONED"; - break; - case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_LOCK_MEDIA: - reason = "STATUS_UNABLE_TO_LOCK_MEDIA"; - break; - case MD_NTSTATUS_WIN_STATUS_UNABLE_TO_UNLOAD_MEDIA: - reason = "STATUS_UNABLE_TO_UNLOAD_MEDIA"; - break; - case MD_NTSTATUS_WIN_STATUS_EOM_OVERFLOW: - reason = "STATUS_EOM_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_MEDIA: - reason = "STATUS_NO_MEDIA"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SUCH_MEMBER: - reason = "STATUS_NO_SUCH_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_MEMBER: - reason = "STATUS_INVALID_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_KEY_DELETED: - reason = "STATUS_KEY_DELETED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_LOG_SPACE: - reason = "STATUS_NO_LOG_SPACE"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_SIDS: - reason = "STATUS_TOO_MANY_SIDS"; - break; - case MD_NTSTATUS_WIN_STATUS_LM_CROSS_ENCRYPTION_REQUIRED: - reason = "STATUS_LM_CROSS_ENCRYPTION_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_KEY_HAS_CHILDREN: - reason = "STATUS_KEY_HAS_CHILDREN"; - break; - case MD_NTSTATUS_WIN_STATUS_CHILD_MUST_BE_VOLATILE: - reason = "STATUS_CHILD_MUST_BE_VOLATILE"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_CONFIGURATION_ERROR: - reason = "STATUS_DEVICE_CONFIGURATION_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_INTERNAL_ERROR: - reason = "STATUS_DRIVER_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_STATE: - reason = "STATUS_INVALID_DEVICE_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_DEVICE_ERROR: - reason = "STATUS_IO_DEVICE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_PROTOCOL_ERROR: - reason = "STATUS_DEVICE_PROTOCOL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_BACKUP_CONTROLLER: - reason = "STATUS_BACKUP_CONTROLLER"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_FILE_FULL: - reason = "STATUS_LOG_FILE_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_LATE: - reason = "STATUS_TOO_LATE"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_TRUST_LSA_SECRET: - reason = "STATUS_NO_TRUST_LSA_SECRET"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_TRUST_SAM_ACCOUNT: - reason = "STATUS_NO_TRUST_SAM_ACCOUNT"; - break; - case MD_NTSTATUS_WIN_STATUS_TRUSTED_DOMAIN_FAILURE: - reason = "STATUS_TRUSTED_DOMAIN_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_TRUSTED_RELATIONSHIP_FAILURE: - reason = "STATUS_TRUSTED_RELATIONSHIP_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CORRUPT: - reason = "STATUS_EVENTLOG_FILE_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_EVENTLOG_CANT_START: - reason = "STATUS_EVENTLOG_CANT_START"; - break; - case MD_NTSTATUS_WIN_STATUS_TRUST_FAILURE: - reason = "STATUS_TRUST_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_MUTANT_LIMIT_EXCEEDED: - reason = "STATUS_MUTANT_LIMIT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_NETLOGON_NOT_STARTED: - reason = "STATUS_NETLOGON_NOT_STARTED"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCOUNT_EXPIRED: - reason = "STATUS_ACCOUNT_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_POSSIBLE_DEADLOCK: - reason = "STATUS_POSSIBLE_DEADLOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_NETWORK_CREDENTIAL_CONFLICT: - reason = "STATUS_NETWORK_CREDENTIAL_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_REMOTE_SESSION_LIMIT: - reason = "STATUS_REMOTE_SESSION_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_EVENTLOG_FILE_CHANGED: - reason = "STATUS_EVENTLOG_FILE_CHANGED"; - break; - case MD_NTSTATUS_WIN_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT: - reason = "STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT"; - break; - case MD_NTSTATUS_WIN_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT: - reason = "STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT"; - break; - case MD_NTSTATUS_WIN_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT: - reason = "STATUS_NOLOGON_SERVER_TRUST_ACCOUNT"; - break; - case MD_NTSTATUS_WIN_STATUS_DOMAIN_TRUST_INCONSISTENT: - reason = "STATUS_DOMAIN_TRUST_INCONSISTENT"; - break; - case MD_NTSTATUS_WIN_STATUS_FS_DRIVER_REQUIRED: - reason = "STATUS_FS_DRIVER_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_IMAGE_ALREADY_LOADED_AS_DLL: - reason = "STATUS_IMAGE_ALREADY_LOADED_AS_DLL"; - break; - case MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING: - reason = "STATUS_INCOMPATIBLE_WITH_GLOBAL_SHORT_NAME_REGISTRY_SETTING"; - break; - case MD_NTSTATUS_WIN_STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME: - reason = "STATUS_SHORT_NAMES_NOT_ENABLED_ON_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_SECURITY_STREAM_IS_INCONSISTENT: - reason = "STATUS_SECURITY_STREAM_IS_INCONSISTENT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_LOCK_RANGE: - reason = "STATUS_INVALID_LOCK_RANGE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_ACE_CONDITION: - reason = "STATUS_INVALID_ACE_CONDITION"; - break; - case MD_NTSTATUS_WIN_STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT: - reason = "STATUS_IMAGE_SUBSYSTEM_NOT_PRESENT"; - break; - case MD_NTSTATUS_WIN_STATUS_NOTIFICATION_GUID_ALREADY_DEFINED: - reason = "STATUS_NOTIFICATION_GUID_ALREADY_DEFINED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_EXCEPTION_HANDLER: - reason = "STATUS_INVALID_EXCEPTION_HANDLER"; - break; - case MD_NTSTATUS_WIN_STATUS_DUPLICATE_PRIVILEGES: - reason = "STATUS_DUPLICATE_PRIVILEGES"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_ALLOWED_ON_SYSTEM_FILE: - reason = "STATUS_NOT_ALLOWED_ON_SYSTEM_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_REPAIR_NEEDED: - reason = "STATUS_REPAIR_NEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_QUOTA_NOT_ENABLED: - reason = "STATUS_QUOTA_NOT_ENABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_APPLICATION_PACKAGE: - reason = "STATUS_NO_APPLICATION_PACKAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_NETWORK_OPEN_RESTRICTION: - reason = "STATUS_NETWORK_OPEN_RESTRICTION"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_USER_SESSION_KEY: - reason = "STATUS_NO_USER_SESSION_KEY"; - break; - case MD_NTSTATUS_WIN_STATUS_USER_SESSION_DELETED: - reason = "STATUS_USER_SESSION_DELETED"; - break; - case MD_NTSTATUS_WIN_STATUS_RESOURCE_LANG_NOT_FOUND: - reason = "STATUS_RESOURCE_LANG_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_INSUFF_SERVER_RESOURCES: - reason = "STATUS_INSUFF_SERVER_RESOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_BUFFER_SIZE: - reason = "STATUS_INVALID_BUFFER_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_COMPONENT: - reason = "STATUS_INVALID_ADDRESS_COMPONENT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_ADDRESS_WILDCARD: - reason = "STATUS_INVALID_ADDRESS_WILDCARD"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_ADDRESSES: - reason = "STATUS_TOO_MANY_ADDRESSES"; - break; - case MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_EXISTS: - reason = "STATUS_ADDRESS_ALREADY_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_ADDRESS_CLOSED: - reason = "STATUS_ADDRESS_CLOSED"; - break; - case MD_NTSTATUS_WIN_STATUS_CONNECTION_DISCONNECTED: - reason = "STATUS_CONNECTION_DISCONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_CONNECTION_RESET: - reason = "STATUS_CONNECTION_RESET"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_NODES: - reason = "STATUS_TOO_MANY_NODES"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_ABORTED: - reason = "STATUS_TRANSACTION_ABORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_TIMED_OUT: - reason = "STATUS_TRANSACTION_TIMED_OUT"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_RELEASE: - reason = "STATUS_TRANSACTION_NO_RELEASE"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_MATCH: - reason = "STATUS_TRANSACTION_NO_MATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONDED: - reason = "STATUS_TRANSACTION_RESPONDED"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_ID: - reason = "STATUS_TRANSACTION_INVALID_ID"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_TYPE: - reason = "STATUS_TRANSACTION_INVALID_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_SERVER_SESSION: - reason = "STATUS_NOT_SERVER_SESSION"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_CLIENT_SESSION: - reason = "STATUS_NOT_CLIENT_SESSION"; - break; - case MD_NTSTATUS_WIN_STATUS_CANNOT_LOAD_REGISTRY_FILE: - reason = "STATUS_CANNOT_LOAD_REGISTRY_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_DEBUG_ATTACH_FAILED: - reason = "STATUS_DEBUG_ATTACH_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_SYSTEM_PROCESS_TERMINATED: - reason = "STATUS_SYSTEM_PROCESS_TERMINATED"; - break; - case MD_NTSTATUS_WIN_STATUS_DATA_NOT_ACCEPTED: - reason = "STATUS_DATA_NOT_ACCEPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_BROWSER_SERVERS_FOUND: - reason = "STATUS_NO_BROWSER_SERVERS_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_VDM_HARD_ERROR: - reason = "STATUS_VDM_HARD_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_CANCEL_TIMEOUT: - reason = "STATUS_DRIVER_CANCEL_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_REPLY_MESSAGE_MISMATCH: - reason = "STATUS_REPLY_MESSAGE_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_MAPPED_ALIGNMENT: - reason = "STATUS_MAPPED_ALIGNMENT"; - break; - case MD_NTSTATUS_WIN_STATUS_IMAGE_CHECKSUM_MISMATCH: - reason = "STATUS_IMAGE_CHECKSUM_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA: - reason = "STATUS_LOST_WRITEBEHIND_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_CLIENT_SERVER_PARAMETERS_INVALID: - reason = "STATUS_CLIENT_SERVER_PARAMETERS_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_PASSWORD_MUST_CHANGE: - reason = "STATUS_PASSWORD_MUST_CHANGE"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_FOUND: - reason = "STATUS_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_TINY_STREAM: - reason = "STATUS_NOT_TINY_STREAM"; - break; - case MD_NTSTATUS_WIN_STATUS_RECOVERY_FAILURE: - reason = "STATUS_RECOVERY_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_STACK_OVERFLOW_READ: - reason = "STATUS_STACK_OVERFLOW_READ"; - break; - case MD_NTSTATUS_WIN_STATUS_FAIL_CHECK: - reason = "STATUS_FAIL_CHECK"; - break; - case MD_NTSTATUS_WIN_STATUS_DUPLICATE_OBJECTID: - reason = "STATUS_DUPLICATE_OBJECTID"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECTID_EXISTS: - reason = "STATUS_OBJECTID_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_CONVERT_TO_LARGE: - reason = "STATUS_CONVERT_TO_LARGE"; - break; - case MD_NTSTATUS_WIN_STATUS_RETRY: - reason = "STATUS_RETRY"; - break; - case MD_NTSTATUS_WIN_STATUS_FOUND_OUT_OF_SCOPE: - reason = "STATUS_FOUND_OUT_OF_SCOPE"; - break; - case MD_NTSTATUS_WIN_STATUS_ALLOCATE_BUCKET: - reason = "STATUS_ALLOCATE_BUCKET"; - break; - case MD_NTSTATUS_WIN_STATUS_PROPSET_NOT_FOUND: - reason = "STATUS_PROPSET_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_MARSHALL_OVERFLOW: - reason = "STATUS_MARSHALL_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_VARIANT: - reason = "STATUS_INVALID_VARIANT"; - break; - case MD_NTSTATUS_WIN_STATUS_DOMAIN_CONTROLLER_NOT_FOUND: - reason = "STATUS_DOMAIN_CONTROLLER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCOUNT_LOCKED_OUT: - reason = "STATUS_ACCOUNT_LOCKED_OUT"; - break; - case MD_NTSTATUS_WIN_STATUS_HANDLE_NOT_CLOSABLE: - reason = "STATUS_HANDLE_NOT_CLOSABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_CONNECTION_REFUSED: - reason = "STATUS_CONNECTION_REFUSED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRACEFUL_DISCONNECT: - reason = "STATUS_GRACEFUL_DISCONNECT"; - break; - case MD_NTSTATUS_WIN_STATUS_ADDRESS_ALREADY_ASSOCIATED: - reason = "STATUS_ADDRESS_ALREADY_ASSOCIATED"; - break; - case MD_NTSTATUS_WIN_STATUS_ADDRESS_NOT_ASSOCIATED: - reason = "STATUS_ADDRESS_NOT_ASSOCIATED"; - break; - case MD_NTSTATUS_WIN_STATUS_CONNECTION_INVALID: - reason = "STATUS_CONNECTION_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_CONNECTION_ACTIVE: - reason = "STATUS_CONNECTION_ACTIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_NETWORK_UNREACHABLE: - reason = "STATUS_NETWORK_UNREACHABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_HOST_UNREACHABLE: - reason = "STATUS_HOST_UNREACHABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_PROTOCOL_UNREACHABLE: - reason = "STATUS_PROTOCOL_UNREACHABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_PORT_UNREACHABLE: - reason = "STATUS_PORT_UNREACHABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_REQUEST_ABORTED: - reason = "STATUS_REQUEST_ABORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_CONNECTION_ABORTED: - reason = "STATUS_CONNECTION_ABORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_COMPRESSION_BUFFER: - reason = "STATUS_BAD_COMPRESSION_BUFFER"; - break; - case MD_NTSTATUS_WIN_STATUS_USER_MAPPED_FILE: - reason = "STATUS_USER_MAPPED_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_AUDIT_FAILED: - reason = "STATUS_AUDIT_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_TIMER_RESOLUTION_NOT_SET: - reason = "STATUS_TIMER_RESOLUTION_NOT_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_CONNECTION_COUNT_LIMIT: - reason = "STATUS_CONNECTION_COUNT_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_LOGIN_TIME_RESTRICTION: - reason = "STATUS_LOGIN_TIME_RESTRICTION"; - break; - case MD_NTSTATUS_WIN_STATUS_LOGIN_WKSTA_RESTRICTION: - reason = "STATUS_LOGIN_WKSTA_RESTRICTION"; - break; - case MD_NTSTATUS_WIN_STATUS_IMAGE_MP_UP_MISMATCH: - reason = "STATUS_IMAGE_MP_UP_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_LOGON_INFO: - reason = "STATUS_INSUFFICIENT_LOGON_INFO"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_DLL_ENTRYPOINT: - reason = "STATUS_BAD_DLL_ENTRYPOINT"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_SERVICE_ENTRYPOINT: - reason = "STATUS_BAD_SERVICE_ENTRYPOINT"; - break; - case MD_NTSTATUS_WIN_STATUS_LPC_REPLY_LOST: - reason = "STATUS_LPC_REPLY_LOST"; - break; - case MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT1: - reason = "STATUS_IP_ADDRESS_CONFLICT1"; - break; - case MD_NTSTATUS_WIN_STATUS_IP_ADDRESS_CONFLICT2: - reason = "STATUS_IP_ADDRESS_CONFLICT2"; - break; - case MD_NTSTATUS_WIN_STATUS_REGISTRY_QUOTA_LIMIT: - reason = "STATUS_REGISTRY_QUOTA_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_PATH_NOT_COVERED: - reason = "STATUS_PATH_NOT_COVERED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_CALLBACK_ACTIVE: - reason = "STATUS_NO_CALLBACK_ACTIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_LICENSE_QUOTA_EXCEEDED: - reason = "STATUS_LICENSE_QUOTA_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_PWD_TOO_SHORT: - reason = "STATUS_PWD_TOO_SHORT"; - break; - case MD_NTSTATUS_WIN_STATUS_PWD_TOO_RECENT: - reason = "STATUS_PWD_TOO_RECENT"; - break; - case MD_NTSTATUS_WIN_STATUS_PWD_HISTORY_CONFLICT: - reason = "STATUS_PWD_HISTORY_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_PLUGPLAY_NO_DEVICE: - reason = "STATUS_PLUGPLAY_NO_DEVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_COMPRESSION: - reason = "STATUS_UNSUPPORTED_COMPRESSION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_HW_PROFILE: - reason = "STATUS_INVALID_HW_PROFILE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PLUGPLAY_DEVICE_PATH: - reason = "STATUS_INVALID_PLUGPLAY_DEVICE_PATH"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_ORDINAL_NOT_FOUND: - reason = "STATUS_DRIVER_ORDINAL_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_ENTRYPOINT_NOT_FOUND: - reason = "STATUS_DRIVER_ENTRYPOINT_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_RESOURCE_NOT_OWNED: - reason = "STATUS_RESOURCE_NOT_OWNED"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_LINKS: - reason = "STATUS_TOO_MANY_LINKS"; - break; - case MD_NTSTATUS_WIN_STATUS_QUOTA_LIST_INCONSISTENT: - reason = "STATUS_QUOTA_LIST_INCONSISTENT"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_IS_OFFLINE: - reason = "STATUS_FILE_IS_OFFLINE"; - break; - case MD_NTSTATUS_WIN_STATUS_EVALUATION_EXPIRATION: - reason = "STATUS_EVALUATION_EXPIRATION"; - break; - case MD_NTSTATUS_WIN_STATUS_ILLEGAL_DLL_RELOCATION: - reason = "STATUS_ILLEGAL_DLL_RELOCATION"; - break; - case MD_NTSTATUS_WIN_STATUS_LICENSE_VIOLATION: - reason = "STATUS_LICENSE_VIOLATION"; - break; - case MD_NTSTATUS_WIN_STATUS_DLL_INIT_FAILED_LOGOFF: - reason = "STATUS_DLL_INIT_FAILED_LOGOFF"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_UNABLE_TO_LOAD: - reason = "STATUS_DRIVER_UNABLE_TO_LOAD"; - break; - case MD_NTSTATUS_WIN_STATUS_DFS_UNAVAILABLE: - reason = "STATUS_DFS_UNAVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLUME_DISMOUNTED: - reason = "STATUS_VOLUME_DISMOUNTED"; - break; - case MD_NTSTATUS_WIN_STATUS_WX86_INTERNAL_ERROR: - reason = "STATUS_WX86_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_WX86_FLOAT_STACK_CHECK: - reason = "STATUS_WX86_FLOAT_STACK_CHECK"; - break; - case MD_NTSTATUS_WIN_STATUS_VALIDATE_CONTINUE: - reason = "STATUS_VALIDATE_CONTINUE"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_MATCH: - reason = "STATUS_NO_MATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_MORE_MATCHES: - reason = "STATUS_NO_MORE_MATCHES"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_A_REPARSE_POINT: - reason = "STATUS_NOT_A_REPARSE_POINT"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_INVALID: - reason = "STATUS_IO_REPARSE_TAG_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_MISMATCH: - reason = "STATUS_IO_REPARSE_TAG_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_REPARSE_DATA_INVALID: - reason = "STATUS_IO_REPARSE_DATA_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_REPARSE_TAG_NOT_HANDLED: - reason = "STATUS_IO_REPARSE_TAG_NOT_HANDLED"; - break; - case MD_NTSTATUS_WIN_STATUS_PWD_TOO_LONG: - reason = "STATUS_PWD_TOO_LONG"; - break; - case MD_NTSTATUS_WIN_STATUS_STOWED_EXCEPTION: - reason = "STATUS_STOWED_EXCEPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_REPARSE_POINT_NOT_RESOLVED: - reason = "STATUS_REPARSE_POINT_NOT_RESOLVED"; - break; - case MD_NTSTATUS_WIN_STATUS_DIRECTORY_IS_A_REPARSE_POINT: - reason = "STATUS_DIRECTORY_IS_A_REPARSE_POINT"; - break; - case MD_NTSTATUS_WIN_STATUS_RANGE_LIST_CONFLICT: - reason = "STATUS_RANGE_LIST_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_SOURCE_ELEMENT_EMPTY: - reason = "STATUS_SOURCE_ELEMENT_EMPTY"; - break; - case MD_NTSTATUS_WIN_STATUS_DESTINATION_ELEMENT_FULL: - reason = "STATUS_DESTINATION_ELEMENT_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_ILLEGAL_ELEMENT_ADDRESS: - reason = "STATUS_ILLEGAL_ELEMENT_ADDRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_MAGAZINE_NOT_PRESENT: - reason = "STATUS_MAGAZINE_NOT_PRESENT"; - break; - case MD_NTSTATUS_WIN_STATUS_REINITIALIZATION_NEEDED: - reason = "STATUS_REINITIALIZATION_NEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_ENCRYPTION_FAILED: - reason = "STATUS_ENCRYPTION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_DECRYPTION_FAILED: - reason = "STATUS_DECRYPTION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_RANGE_NOT_FOUND: - reason = "STATUS_RANGE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_RECOVERY_POLICY: - reason = "STATUS_NO_RECOVERY_POLICY"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_EFS: - reason = "STATUS_NO_EFS"; - break; - case MD_NTSTATUS_WIN_STATUS_WRONG_EFS: - reason = "STATUS_WRONG_EFS"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_USER_KEYS: - reason = "STATUS_NO_USER_KEYS"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_NOT_ENCRYPTED: - reason = "STATUS_FILE_NOT_ENCRYPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_EXPORT_FORMAT: - reason = "STATUS_NOT_EXPORT_FORMAT"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_ENCRYPTED: - reason = "STATUS_FILE_ENCRYPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_GUID_NOT_FOUND: - reason = "STATUS_WMI_GUID_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_INSTANCE_NOT_FOUND: - reason = "STATUS_WMI_INSTANCE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_ITEMID_NOT_FOUND: - reason = "STATUS_WMI_ITEMID_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_TRY_AGAIN: - reason = "STATUS_WMI_TRY_AGAIN"; - break; - case MD_NTSTATUS_WIN_STATUS_SHARED_POLICY: - reason = "STATUS_SHARED_POLICY"; - break; - case MD_NTSTATUS_WIN_STATUS_POLICY_OBJECT_NOT_FOUND: - reason = "STATUS_POLICY_OBJECT_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_POLICY_ONLY_IN_DS: - reason = "STATUS_POLICY_ONLY_IN_DS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLUME_NOT_UPGRADED: - reason = "STATUS_VOLUME_NOT_UPGRADED"; - break; - case MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_NOT_ACTIVE: - reason = "STATUS_REMOTE_STORAGE_NOT_ACTIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_REMOTE_STORAGE_MEDIA_ERROR: - reason = "STATUS_REMOTE_STORAGE_MEDIA_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_TRACKING_SERVICE: - reason = "STATUS_NO_TRACKING_SERVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_SERVER_SID_MISMATCH: - reason = "STATUS_SERVER_SID_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_NO_ATTRIBUTE_OR_VALUE: - reason = "STATUS_DS_NO_ATTRIBUTE_OR_VALUE"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_INVALID_ATTRIBUTE_SYNTAX: - reason = "STATUS_DS_INVALID_ATTRIBUTE_SYNTAX"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED: - reason = "STATUS_DS_ATTRIBUTE_TYPE_UNDEFINED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS: - reason = "STATUS_DS_ATTRIBUTE_OR_VALUE_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_BUSY: - reason = "STATUS_DS_BUSY"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_UNAVAILABLE: - reason = "STATUS_DS_UNAVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_NO_RIDS_ALLOCATED: - reason = "STATUS_DS_NO_RIDS_ALLOCATED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_NO_MORE_RIDS: - reason = "STATUS_DS_NO_MORE_RIDS"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_INCORRECT_ROLE_OWNER: - reason = "STATUS_DS_INCORRECT_ROLE_OWNER"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_INIT_ERROR: - reason = "STATUS_DS_RIDMGR_INIT_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_OBJ_CLASS_VIOLATION: - reason = "STATUS_DS_OBJ_CLASS_VIOLATION"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_NON_LEAF: - reason = "STATUS_DS_CANT_ON_NON_LEAF"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_CANT_ON_RDN: - reason = "STATUS_DS_CANT_ON_RDN"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_OBJ_CLASS: - reason = "STATUS_DS_CANT_MOD_OBJ_CLASS"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_CROSS_DOM_MOVE_FAILED: - reason = "STATUS_DS_CROSS_DOM_MOVE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_GC_NOT_AVAILABLE: - reason = "STATUS_DS_GC_NOT_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_DIRECTORY_SERVICE_REQUIRED: - reason = "STATUS_DIRECTORY_SERVICE_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_REPARSE_ATTRIBUTE_CONFLICT: - reason = "STATUS_REPARSE_ATTRIBUTE_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_ENABLE_DENY_ONLY: - reason = "STATUS_CANT_ENABLE_DENY_ONLY"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_FAULTS: - reason = "STATUS_FLOAT_MULTIPLE_FAULTS"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOAT_MULTIPLE_TRAPS: - reason = "STATUS_FLOAT_MULTIPLE_TRAPS"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_REMOVED: - reason = "STATUS_DEVICE_REMOVED"; - break; - case MD_NTSTATUS_WIN_STATUS_JOURNAL_DELETE_IN_PROGRESS: - reason = "STATUS_JOURNAL_DELETE_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_JOURNAL_NOT_ACTIVE: - reason = "STATUS_JOURNAL_NOT_ACTIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_NOINTERFACE: - reason = "STATUS_NOINTERFACE"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_RIDMGR_DISABLED: - reason = "STATUS_DS_RIDMGR_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_ADMIN_LIMIT_EXCEEDED: - reason = "STATUS_DS_ADMIN_LIMIT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_SLEEP: - reason = "STATUS_DRIVER_FAILED_SLEEP"; - break; - case MD_NTSTATUS_WIN_STATUS_MUTUAL_AUTHENTICATION_FAILED: - reason = "STATUS_MUTUAL_AUTHENTICATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_CORRUPT_SYSTEM_FILE: - reason = "STATUS_CORRUPT_SYSTEM_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_DATATYPE_MISALIGNMENT_ERROR: - reason = "STATUS_DATATYPE_MISALIGNMENT_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_READ_ONLY: - reason = "STATUS_WMI_READ_ONLY"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_SET_FAILURE: - reason = "STATUS_WMI_SET_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_COMMITMENT_MINIMUM: - reason = "STATUS_COMMITMENT_MINIMUM"; - break; - case MD_NTSTATUS_WIN_STATUS_REG_NAT_CONSUMPTION: - reason = "STATUS_REG_NAT_CONSUMPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSPORT_FULL: - reason = "STATUS_TRANSPORT_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE: - reason = "STATUS_DS_SAM_INIT_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_ONLY_IF_CONNECTED: - reason = "STATUS_ONLY_IF_CONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_SENSITIVE_GROUP_VIOLATION: - reason = "STATUS_DS_SENSITIVE_GROUP_VIOLATION"; - break; - case MD_NTSTATUS_WIN_STATUS_PNP_RESTART_ENUMERATION: - reason = "STATUS_PNP_RESTART_ENUMERATION"; - break; - case MD_NTSTATUS_WIN_STATUS_JOURNAL_ENTRY_DELETED: - reason = "STATUS_JOURNAL_ENTRY_DELETED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_CANT_MOD_PRIMARYGROUPID: - reason = "STATUS_DS_CANT_MOD_PRIMARYGROUPID"; - break; - case MD_NTSTATUS_WIN_STATUS_SYSTEM_IMAGE_BAD_SIGNATURE: - reason = "STATUS_SYSTEM_IMAGE_BAD_SIGNATURE"; - break; - case MD_NTSTATUS_WIN_STATUS_PNP_REBOOT_REQUIRED: - reason = "STATUS_PNP_REBOOT_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_POWER_STATE_INVALID: - reason = "STATUS_POWER_STATE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_INVALID_GROUP_TYPE: - reason = "STATUS_DS_INVALID_GROUP_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN: - reason = "STATUS_DS_NO_NEST_GLOBALGROUP_IN_MIXEDDOMAIN"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN: - reason = "STATUS_DS_NO_NEST_LOCALGROUP_IN_MIXEDDOMAIN"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER: - reason = "STATUS_DS_GLOBAL_CANT_HAVE_LOCAL_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER: - reason = "STATUS_DS_GLOBAL_CANT_HAVE_UNIVERSAL_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER: - reason = "STATUS_DS_UNIVERSAL_CANT_HAVE_LOCAL_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER: - reason = "STATUS_DS_GLOBAL_CANT_HAVE_CROSSDOMAIN_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER: - reason = "STATUS_DS_LOCAL_CANT_HAVE_CROSSDOMAIN_LOCAL_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_HAVE_PRIMARY_MEMBERS: - reason = "STATUS_DS_HAVE_PRIMARY_MEMBERS"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_NOT_SUPPORTED: - reason = "STATUS_WMI_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_POWER: - reason = "STATUS_INSUFFICIENT_POWER"; - break; - case MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_PASSWORD: - reason = "STATUS_SAM_NEED_BOOTKEY_PASSWORD"; - break; - case MD_NTSTATUS_WIN_STATUS_SAM_NEED_BOOTKEY_FLOPPY: - reason = "STATUS_SAM_NEED_BOOTKEY_FLOPPY"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_CANT_START: - reason = "STATUS_DS_CANT_START"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE: - reason = "STATUS_DS_INIT_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_SAM_INIT_FAILURE: - reason = "STATUS_SAM_INIT_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_GC_REQUIRED: - reason = "STATUS_DS_GC_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY: - reason = "STATUS_DS_LOCAL_MEMBER_OF_LOCAL_ONLY"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS: - reason = "STATUS_DS_NO_FPO_IN_UNIVERSAL_GROUPS"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED: - reason = "STATUS_DS_MACHINE_ACCOUNT_QUOTA_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_MULTIPLE_FAULT_VIOLATION: - reason = "STATUS_MULTIPLE_FAULT_VIOLATION"; - break; - case MD_NTSTATUS_WIN_STATUS_CURRENT_DOMAIN_NOT_ALLOWED: - reason = "STATUS_CURRENT_DOMAIN_NOT_ALLOWED"; - break; - case MD_NTSTATUS_WIN_STATUS_CANNOT_MAKE: - reason = "STATUS_CANNOT_MAKE"; - break; - case MD_NTSTATUS_WIN_STATUS_SYSTEM_SHUTDOWN: - reason = "STATUS_SYSTEM_SHUTDOWN"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_INIT_FAILURE_CONSOLE: - reason = "STATUS_DS_INIT_FAILURE_CONSOLE"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_SAM_INIT_FAILURE_CONSOLE: - reason = "STATUS_DS_SAM_INIT_FAILURE_CONSOLE"; - break; - case MD_NTSTATUS_WIN_STATUS_UNFINISHED_CONTEXT_DELETED: - reason = "STATUS_UNFINISHED_CONTEXT_DELETED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_TGT_REPLY: - reason = "STATUS_NO_TGT_REPLY"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECTID_NOT_FOUND: - reason = "STATUS_OBJECTID_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_IP_ADDRESSES: - reason = "STATUS_NO_IP_ADDRESSES"; - break; - case MD_NTSTATUS_WIN_STATUS_WRONG_CREDENTIAL_HANDLE: - reason = "STATUS_WRONG_CREDENTIAL_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_CRYPTO_SYSTEM_INVALID: - reason = "STATUS_CRYPTO_SYSTEM_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_MAX_REFERRALS_EXCEEDED: - reason = "STATUS_MAX_REFERRALS_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_MUST_BE_KDC: - reason = "STATUS_MUST_BE_KDC"; - break; - case MD_NTSTATUS_WIN_STATUS_STRONG_CRYPTO_NOT_SUPPORTED: - reason = "STATUS_STRONG_CRYPTO_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_PRINCIPALS: - reason = "STATUS_TOO_MANY_PRINCIPALS"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_PA_DATA: - reason = "STATUS_NO_PA_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_PKINIT_NAME_MISMATCH: - reason = "STATUS_PKINIT_NAME_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_LOGON_REQUIRED: - reason = "STATUS_SMARTCARD_LOGON_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_KDC_INVALID_REQUEST: - reason = "STATUS_KDC_INVALID_REQUEST"; - break; - case MD_NTSTATUS_WIN_STATUS_KDC_UNABLE_TO_REFER: - reason = "STATUS_KDC_UNABLE_TO_REFER"; - break; - case MD_NTSTATUS_WIN_STATUS_KDC_UNKNOWN_ETYPE: - reason = "STATUS_KDC_UNKNOWN_ETYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_SHUTDOWN_IN_PROGRESS: - reason = "STATUS_SHUTDOWN_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_SERVER_SHUTDOWN_IN_PROGRESS: - reason = "STATUS_SERVER_SHUTDOWN_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_ON_SBS: - reason = "STATUS_NOT_SUPPORTED_ON_SBS"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_GUID_DISCONNECTED: - reason = "STATUS_WMI_GUID_DISCONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_DISABLED: - reason = "STATUS_WMI_ALREADY_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_WMI_ALREADY_ENABLED: - reason = "STATUS_WMI_ALREADY_ENABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_MFT_TOO_FRAGMENTED: - reason = "STATUS_MFT_TOO_FRAGMENTED"; - break; - case MD_NTSTATUS_WIN_STATUS_COPY_PROTECTION_FAILURE: - reason = "STATUS_COPY_PROTECTION_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_CSS_AUTHENTICATION_FAILURE: - reason = "STATUS_CSS_AUTHENTICATION_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_PRESENT: - reason = "STATUS_CSS_KEY_NOT_PRESENT"; - break; - case MD_NTSTATUS_WIN_STATUS_CSS_KEY_NOT_ESTABLISHED: - reason = "STATUS_CSS_KEY_NOT_ESTABLISHED"; - break; - case MD_NTSTATUS_WIN_STATUS_CSS_SCRAMBLED_SECTOR: - reason = "STATUS_CSS_SCRAMBLED_SECTOR"; - break; - case MD_NTSTATUS_WIN_STATUS_CSS_REGION_MISMATCH: - reason = "STATUS_CSS_REGION_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_CSS_RESETS_EXHAUSTED: - reason = "STATUS_CSS_RESETS_EXHAUSTED"; - break; - case MD_NTSTATUS_WIN_STATUS_PASSWORD_CHANGE_REQUIRED: - reason = "STATUS_PASSWORD_CHANGE_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_PKINIT_FAILURE: - reason = "STATUS_PKINIT_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_SUBSYSTEM_FAILURE: - reason = "STATUS_SMARTCARD_SUBSYSTEM_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_KERB_KEY: - reason = "STATUS_NO_KERB_KEY"; - break; - case MD_NTSTATUS_WIN_STATUS_HOST_DOWN: - reason = "STATUS_HOST_DOWN"; - break; - case MD_NTSTATUS_WIN_STATUS_UNSUPPORTED_PREAUTH: - reason = "STATUS_UNSUPPORTED_PREAUTH"; - break; - case MD_NTSTATUS_WIN_STATUS_EFS_ALG_BLOB_TOO_BIG: - reason = "STATUS_EFS_ALG_BLOB_TOO_BIG"; - break; - case MD_NTSTATUS_WIN_STATUS_PORT_NOT_SET: - reason = "STATUS_PORT_NOT_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_DEBUGGER_INACTIVE: - reason = "STATUS_DEBUGGER_INACTIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_VERSION_CHECK_FAILURE: - reason = "STATUS_DS_VERSION_CHECK_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_AUDITING_DISABLED: - reason = "STATUS_AUDITING_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_PRENT4_MACHINE_ACCOUNT: - reason = "STATUS_PRENT4_MACHINE_ACCOUNT"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER: - reason = "STATUS_DS_AG_CANT_HAVE_UNIVERSAL_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_32: - reason = "STATUS_INVALID_IMAGE_WIN_32"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_WIN_64: - reason = "STATUS_INVALID_IMAGE_WIN_64"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_BINDINGS: - reason = "STATUS_BAD_BINDINGS"; - break; - case MD_NTSTATUS_WIN_STATUS_NETWORK_SESSION_EXPIRED: - reason = "STATUS_NETWORK_SESSION_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_APPHELP_BLOCK: - reason = "STATUS_APPHELP_BLOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_ALL_SIDS_FILTERED: - reason = "STATUS_ALL_SIDS_FILTERED"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_SAFE_MODE_DRIVER: - reason = "STATUS_NOT_SAFE_MODE_DRIVER"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT: - reason = "STATUS_ACCESS_DISABLED_BY_POLICY_DEFAULT"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PATH: - reason = "STATUS_ACCESS_DISABLED_BY_POLICY_PATH"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER: - reason = "STATUS_ACCESS_DISABLED_BY_POLICY_PUBLISHER"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_BY_POLICY_OTHER: - reason = "STATUS_ACCESS_DISABLED_BY_POLICY_OTHER"; - break; - case MD_NTSTATUS_WIN_STATUS_FAILED_DRIVER_ENTRY: - reason = "STATUS_FAILED_DRIVER_ENTRY"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_ENUMERATION_ERROR: - reason = "STATUS_DEVICE_ENUMERATION_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_MOUNT_POINT_NOT_RESOLVED: - reason = "STATUS_MOUNT_POINT_NOT_RESOLVED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_DEVICE_OBJECT_PARAMETER: - reason = "STATUS_INVALID_DEVICE_OBJECT_PARAMETER"; - break; - case MD_NTSTATUS_WIN_STATUS_MCA_OCCURED: - reason = "STATUS_MCA_OCCURED"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED_CRITICAL: - reason = "STATUS_DRIVER_BLOCKED_CRITICAL"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_BLOCKED: - reason = "STATUS_DRIVER_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_DATABASE_ERROR: - reason = "STATUS_DRIVER_DATABASE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_SYSTEM_HIVE_TOO_LARGE: - reason = "STATUS_SYSTEM_HIVE_TOO_LARGE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMPORT_OF_NON_DLL: - reason = "STATUS_INVALID_IMPORT_OF_NON_DLL"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SECRETS: - reason = "STATUS_NO_SECRETS"; - break; - case MD_NTSTATUS_WIN_STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY: - reason = "STATUS_ACCESS_DISABLED_NO_SAFER_UI_BY_POLICY"; - break; - case MD_NTSTATUS_WIN_STATUS_FAILED_STACK_SWITCH: - reason = "STATUS_FAILED_STACK_SWITCH"; - break; - case MD_NTSTATUS_WIN_STATUS_HEAP_CORRUPTION: - reason = "STATUS_HEAP_CORRUPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_WRONG_PIN: - reason = "STATUS_SMARTCARD_WRONG_PIN"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_BLOCKED: - reason = "STATUS_SMARTCARD_CARD_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED: - reason = "STATUS_SMARTCARD_CARD_NOT_AUTHENTICATED"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CARD: - reason = "STATUS_SMARTCARD_NO_CARD"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEY_CONTAINER: - reason = "STATUS_SMARTCARD_NO_KEY_CONTAINER"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_CERTIFICATE: - reason = "STATUS_SMARTCARD_NO_CERTIFICATE"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_NO_KEYSET: - reason = "STATUS_SMARTCARD_NO_KEYSET"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_IO_ERROR: - reason = "STATUS_SMARTCARD_IO_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_DOWNGRADE_DETECTED: - reason = "STATUS_DOWNGRADE_DETECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_REVOKED: - reason = "STATUS_SMARTCARD_CERT_REVOKED"; - break; - case MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED: - reason = "STATUS_ISSUING_CA_UNTRUSTED"; - break; - case MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_C: - reason = "STATUS_REVOCATION_OFFLINE_C"; - break; - case MD_NTSTATUS_WIN_STATUS_PKINIT_CLIENT_FAILURE: - reason = "STATUS_PKINIT_CLIENT_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_CERT_EXPIRED: - reason = "STATUS_SMARTCARD_CERT_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_FAILED_PRIOR_UNLOAD: - reason = "STATUS_DRIVER_FAILED_PRIOR_UNLOAD"; - break; - case MD_NTSTATUS_WIN_STATUS_SMARTCARD_SILENT_CONTEXT: - reason = "STATUS_SMARTCARD_SILENT_CONTEXT"; - break; - case MD_NTSTATUS_WIN_STATUS_PER_USER_TRUST_QUOTA_EXCEEDED: - reason = "STATUS_PER_USER_TRUST_QUOTA_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED: - reason = "STATUS_ALL_USER_TRUST_QUOTA_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED: - reason = "STATUS_USER_DELETE_TRUST_QUOTA_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_NAME_NOT_UNIQUE: - reason = "STATUS_DS_NAME_NOT_UNIQUE"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_DUPLICATE_ID_FOUND: - reason = "STATUS_DS_DUPLICATE_ID_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_GROUP_CONVERSION_ERROR: - reason = "STATUS_DS_GROUP_CONVERSION_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLSNAP_PREPARE_HIBERNATE: - reason = "STATUS_VOLSNAP_PREPARE_HIBERNATE"; - break; - case MD_NTSTATUS_WIN_STATUS_USER2USER_REQUIRED: - reason = "STATUS_USER2USER_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_STACK_BUFFER_OVERRUN: - reason = "STATUS_STACK_BUFFER_OVERRUN"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_S4U_PROT_SUPPORT: - reason = "STATUS_NO_S4U_PROT_SUPPORT"; - break; - case MD_NTSTATUS_WIN_STATUS_CROSSREALM_DELEGATION_FAILURE: - reason = "STATUS_CROSSREALM_DELEGATION_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_REVOCATION_OFFLINE_KDC: - reason = "STATUS_REVOCATION_OFFLINE_KDC"; - break; - case MD_NTSTATUS_WIN_STATUS_ISSUING_CA_UNTRUSTED_KDC: - reason = "STATUS_ISSUING_CA_UNTRUSTED_KDC"; - break; - case MD_NTSTATUS_WIN_STATUS_KDC_CERT_EXPIRED: - reason = "STATUS_KDC_CERT_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_KDC_CERT_REVOKED: - reason = "STATUS_KDC_CERT_REVOKED"; - break; - case MD_NTSTATUS_WIN_STATUS_PARAMETER_QUOTA_EXCEEDED: - reason = "STATUS_PARAMETER_QUOTA_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_HIBERNATION_FAILURE: - reason = "STATUS_HIBERNATION_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_DELAY_LOAD_FAILED: - reason = "STATUS_DELAY_LOAD_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_AUTHENTICATION_FIREWALL_FAILED: - reason = "STATUS_AUTHENTICATION_FIREWALL_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_VDM_DISALLOWED: - reason = "STATUS_VDM_DISALLOWED"; - break; - case MD_NTSTATUS_WIN_STATUS_HUNG_DISPLAY_DRIVER_THREAD: - reason = "STATUS_HUNG_DISPLAY_DRIVER_THREAD"; - break; - case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE: - reason = "STATUS_INSUFFICIENT_RESOURCE_FOR_SPECIFIED_SHARED_SECTION_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_CRUNTIME_PARAMETER: - reason = "STATUS_INVALID_CRUNTIME_PARAMETER"; - break; - case MD_NTSTATUS_WIN_STATUS_NTLM_BLOCKED: - reason = "STATUS_NTLM_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_SRC_SID_EXISTS_IN_FOREST: - reason = "STATUS_DS_SRC_SID_EXISTS_IN_FOREST"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST: - reason = "STATUS_DS_DOMAIN_NAME_EXISTS_IN_FOREST"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST: - reason = "STATUS_DS_FLAT_NAME_EXISTS_IN_FOREST"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_USER_PRINCIPAL_NAME: - reason = "STATUS_INVALID_USER_PRINCIPAL_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_FATAL_USER_CALLBACK_EXCEPTION: - reason = "STATUS_FATAL_USER_CALLBACK_EXCEPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_ASSERTION_FAILURE: - reason = "STATUS_ASSERTION_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_VERIFIER_STOP: - reason = "STATUS_VERIFIER_STOP"; - break; - case MD_NTSTATUS_WIN_STATUS_CALLBACK_POP_STACK: - reason = "STATUS_CALLBACK_POP_STACK"; - break; - case MD_NTSTATUS_WIN_STATUS_INCOMPATIBLE_DRIVER_BLOCKED: - reason = "STATUS_INCOMPATIBLE_DRIVER_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_HIVE_UNLOADED: - reason = "STATUS_HIVE_UNLOADED"; - break; - case MD_NTSTATUS_WIN_STATUS_COMPRESSION_DISABLED: - reason = "STATUS_COMPRESSION_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_SYSTEM_LIMITATION: - reason = "STATUS_FILE_SYSTEM_LIMITATION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IMAGE_HASH: - reason = "STATUS_INVALID_IMAGE_HASH"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_CAPABLE: - reason = "STATUS_NOT_CAPABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_REQUEST_OUT_OF_SEQUENCE: - reason = "STATUS_REQUEST_OUT_OF_SEQUENCE"; - break; - case MD_NTSTATUS_WIN_STATUS_IMPLEMENTATION_LIMIT: - reason = "STATUS_IMPLEMENTATION_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_ELEVATION_REQUIRED: - reason = "STATUS_ELEVATION_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SECURITY_CONTEXT: - reason = "STATUS_NO_SECURITY_CONTEXT"; - break; - case MD_NTSTATUS_WIN_STATUS_PKU2U_CERT_FAILURE: - reason = "STATUS_PKU2U_CERT_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_BEYOND_VDL: - reason = "STATUS_BEYOND_VDL"; - break; - case MD_NTSTATUS_WIN_STATUS_ENCOUNTERED_WRITE_IN_PROGRESS: - reason = "STATUS_ENCOUNTERED_WRITE_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_PTE_CHANGED: - reason = "STATUS_PTE_CHANGED"; - break; - case MD_NTSTATUS_WIN_STATUS_PURGE_FAILED: - reason = "STATUS_PURGE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_CRED_REQUIRES_CONFIRMATION: - reason = "STATUS_CRED_REQUIRES_CONFIRMATION"; - break; - case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE: - reason = "STATUS_CS_ENCRYPTION_INVALID_SERVER_RESPONSE"; - break; - case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER: - reason = "STATUS_CS_ENCRYPTION_UNSUPPORTED_SERVER"; - break; - case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE: - reason = "STATUS_CS_ENCRYPTION_EXISTING_ENCRYPTED_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE: - reason = "STATUS_CS_ENCRYPTION_NEW_ENCRYPTED_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_CS_ENCRYPTION_FILE_NOT_CSE: - reason = "STATUS_CS_ENCRYPTION_FILE_NOT_CSE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_LABEL: - reason = "STATUS_INVALID_LABEL"; - break; - case MD_NTSTATUS_WIN_STATUS_DRIVER_PROCESS_TERMINATED: - reason = "STATUS_DRIVER_PROCESS_TERMINATED"; - break; - case MD_NTSTATUS_WIN_STATUS_AMBIGUOUS_SYSTEM_DEVICE: - reason = "STATUS_AMBIGUOUS_SYSTEM_DEVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_SYSTEM_DEVICE_NOT_FOUND: - reason = "STATUS_SYSTEM_DEVICE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_RESTART_BOOT_APPLICATION: - reason = "STATUS_RESTART_BOOT_APPLICATION"; - break; - case MD_NTSTATUS_WIN_STATUS_INSUFFICIENT_NVRAM_RESOURCES: - reason = "STATUS_INSUFFICIENT_NVRAM_RESOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_SESSION: - reason = "STATUS_INVALID_SESSION"; - break; - case MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_SESSION: - reason = "STATUS_THREAD_ALREADY_IN_SESSION"; - break; - case MD_NTSTATUS_WIN_STATUS_THREAD_NOT_IN_SESSION: - reason = "STATUS_THREAD_NOT_IN_SESSION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_WEIGHT: - reason = "STATUS_INVALID_WEIGHT"; - break; - case MD_NTSTATUS_WIN_STATUS_REQUEST_PAUSED: - reason = "STATUS_REQUEST_PAUSED"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_RANGES_PROCESSED: - reason = "STATUS_NO_RANGES_PROCESSED"; - break; - case MD_NTSTATUS_WIN_STATUS_DISK_RESOURCES_EXHAUSTED: - reason = "STATUS_DISK_RESOURCES_EXHAUSTED"; - break; - case MD_NTSTATUS_WIN_STATUS_NEEDS_REMEDIATION: - reason = "STATUS_NEEDS_REMEDIATION"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_FEATURE_NOT_SUPPORTED: - reason = "STATUS_DEVICE_FEATURE_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_UNREACHABLE: - reason = "STATUS_DEVICE_UNREACHABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_TOKEN: - reason = "STATUS_INVALID_TOKEN"; - break; - case MD_NTSTATUS_WIN_STATUS_SERVER_UNAVAILABLE: - reason = "STATUS_SERVER_UNAVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_NOT_AVAILABLE: - reason = "STATUS_FILE_NOT_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_INSUFFICIENT_RESOURCES: - reason = "STATUS_DEVICE_INSUFFICIENT_RESOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_PACKAGE_UPDATING: - reason = "STATUS_PACKAGE_UPDATING"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_READ_FROM_COPY: - reason = "STATUS_NOT_READ_FROM_COPY"; - break; - case MD_NTSTATUS_WIN_STATUS_FT_WRITE_FAILURE: - reason = "STATUS_FT_WRITE_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_FT_DI_SCAN_REQUIRED: - reason = "STATUS_FT_DI_SCAN_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECT_NOT_EXTERNALLY_BACKED: - reason = "STATUS_OBJECT_NOT_EXTERNALLY_BACKED"; - break; - case MD_NTSTATUS_WIN_STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN: - reason = "STATUS_EXTERNAL_BACKING_PROVIDER_UNKNOWN"; - break; - case MD_NTSTATUS_WIN_STATUS_DATA_CHECKSUM_ERROR: - reason = "STATUS_DATA_CHECKSUM_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_INTERMIXED_KERNEL_EA_OPERATION: - reason = "STATUS_INTERMIXED_KERNEL_EA_OPERATION"; - break; - case MD_NTSTATUS_WIN_STATUS_TRIM_READ_ZERO_NOT_SUPPORTED: - reason = "STATUS_TRIM_READ_ZERO_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TOO_MANY_SEGMENT_DESCRIPTORS: - reason = "STATUS_TOO_MANY_SEGMENT_DESCRIPTORS"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_OFFSET_ALIGNMENT: - reason = "STATUS_INVALID_OFFSET_ALIGNMENT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_FIELD_IN_PARAMETER_LIST: - reason = "STATUS_INVALID_FIELD_IN_PARAMETER_LIST"; - break; - case MD_NTSTATUS_WIN_STATUS_OPERATION_IN_PROGRESS: - reason = "STATUS_OPERATION_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_INITIATOR_TARGET_PATH: - reason = "STATUS_INVALID_INITIATOR_TARGET_PATH"; - break; - case MD_NTSTATUS_WIN_STATUS_SCRUB_DATA_DISABLED: - reason = "STATUS_SCRUB_DATA_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_REDUNDANT_STORAGE: - reason = "STATUS_NOT_REDUNDANT_STORAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_RESIDENT_FILE_NOT_SUPPORTED: - reason = "STATUS_RESIDENT_FILE_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_COMPRESSED_FILE_NOT_SUPPORTED: - reason = "STATUS_COMPRESSED_FILE_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_SUPPORTED: - reason = "STATUS_DIRECTORY_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_OPERATION_TIMEOUT: - reason = "STATUS_IO_OPERATION_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_SYSTEM_NEEDS_REMEDIATION: - reason = "STATUS_SYSTEM_NEEDS_REMEDIATION"; - break; - case MD_NTSTATUS_WIN_STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN: - reason = "STATUS_APPX_INTEGRITY_FAILURE_CLR_NGEN"; - break; - case MD_NTSTATUS_WIN_STATUS_SHARE_UNAVAILABLE: - reason = "STATUS_SHARE_UNAVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_APISET_NOT_HOSTED: - reason = "STATUS_APISET_NOT_HOSTED"; - break; - case MD_NTSTATUS_WIN_STATUS_APISET_NOT_PRESENT: - reason = "STATUS_APISET_NOT_PRESENT"; - break; - case MD_NTSTATUS_WIN_STATUS_DEVICE_HARDWARE_ERROR: - reason = "STATUS_DEVICE_HARDWARE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_TASK_NAME: - reason = "STATUS_INVALID_TASK_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_TASK_INDEX: - reason = "STATUS_INVALID_TASK_INDEX"; - break; - case MD_NTSTATUS_WIN_STATUS_THREAD_ALREADY_IN_TASK: - reason = "STATUS_THREAD_ALREADY_IN_TASK"; - break; - case MD_NTSTATUS_WIN_STATUS_CALLBACK_BYPASS: - reason = "STATUS_CALLBACK_BYPASS"; - break; - case MD_NTSTATUS_WIN_STATUS_UNDEFINED_SCOPE: - reason = "STATUS_UNDEFINED_SCOPE"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_CAP: - reason = "STATUS_INVALID_CAP"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_GUI_PROCESS: - reason = "STATUS_NOT_GUI_PROCESS"; - break; - case MD_NTSTATUS_WIN_STATUS_FAIL_FAST_EXCEPTION: - reason = "STATUS_FAIL_FAST_EXCEPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_IMAGE_CERT_REVOKED: - reason = "STATUS_IMAGE_CERT_REVOKED"; - break; - case MD_NTSTATUS_WIN_STATUS_DYNAMIC_CODE_BLOCKED: - reason = "STATUS_DYNAMIC_CODE_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_PORT_CLOSED: - reason = "STATUS_PORT_CLOSED"; - break; - case MD_NTSTATUS_WIN_STATUS_MESSAGE_LOST: - reason = "STATUS_MESSAGE_LOST"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_MESSAGE: - reason = "STATUS_INVALID_MESSAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_REQUEST_CANCELED: - reason = "STATUS_REQUEST_CANCELED"; - break; - case MD_NTSTATUS_WIN_STATUS_RECURSIVE_DISPATCH: - reason = "STATUS_RECURSIVE_DISPATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_LPC_RECEIVE_BUFFER_EXPECTED: - reason = "STATUS_LPC_RECEIVE_BUFFER_EXPECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_LPC_INVALID_CONNECTION_USAGE: - reason = "STATUS_LPC_INVALID_CONNECTION_USAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_LPC_REQUESTS_NOT_ALLOWED: - reason = "STATUS_LPC_REQUESTS_NOT_ALLOWED"; - break; - case MD_NTSTATUS_WIN_STATUS_RESOURCE_IN_USE: - reason = "STATUS_RESOURCE_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_HARDWARE_MEMORY_ERROR: - reason = "STATUS_HARDWARE_MEMORY_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_THREADPOOL_HANDLE_EXCEPTION: - reason = "STATUS_THREADPOOL_HANDLE_EXCEPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED: - reason = "STATUS_THREADPOOL_SET_EVENT_ON_COMPLETION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED: - reason = "STATUS_THREADPOOL_RELEASE_SEMAPHORE_ON_COMPLETION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED: - reason = "STATUS_THREADPOOL_RELEASE_MUTEX_ON_COMPLETION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED: - reason = "STATUS_THREADPOOL_FREE_LIBRARY_ON_COMPLETION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_THREADPOOL_RELEASED_DURING_OPERATION: - reason = "STATUS_THREADPOOL_RELEASED_DURING_OPERATION"; - break; - case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING: - reason = "STATUS_CALLBACK_RETURNED_WHILE_IMPERSONATING"; - break; - case MD_NTSTATUS_WIN_STATUS_APC_RETURNED_WHILE_IMPERSONATING: - reason = "STATUS_APC_RETURNED_WHILE_IMPERSONATING"; - break; - case MD_NTSTATUS_WIN_STATUS_PROCESS_IS_PROTECTED: - reason = "STATUS_PROCESS_IS_PROTECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_MCA_EXCEPTION: - reason = "STATUS_MCA_EXCEPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE: - reason = "STATUS_CERTIFICATE_MAPPING_NOT_UNIQUE"; - break; - case MD_NTSTATUS_WIN_STATUS_SYMLINK_CLASS_DISABLED: - reason = "STATUS_SYMLINK_CLASS_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_IDN_NORMALIZATION: - reason = "STATUS_INVALID_IDN_NORMALIZATION"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_UNICODE_TRANSLATION: - reason = "STATUS_NO_UNICODE_TRANSLATION"; - break; - case MD_NTSTATUS_WIN_STATUS_ALREADY_REGISTERED: - reason = "STATUS_ALREADY_REGISTERED"; - break; - case MD_NTSTATUS_WIN_STATUS_CONTEXT_MISMATCH: - reason = "STATUS_CONTEXT_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_PORT_ALREADY_HAS_COMPLETION_LIST: - reason = "STATUS_PORT_ALREADY_HAS_COMPLETION_LIST"; - break; - case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_PRIORITY: - reason = "STATUS_CALLBACK_RETURNED_THREAD_PRIORITY"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_THREAD: - reason = "STATUS_INVALID_THREAD"; - break; - case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_TRANSACTION: - reason = "STATUS_CALLBACK_RETURNED_TRANSACTION"; - break; - case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LDR_LOCK: - reason = "STATUS_CALLBACK_RETURNED_LDR_LOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_LANG: - reason = "STATUS_CALLBACK_RETURNED_LANG"; - break; - case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_PRI_BACK: - reason = "STATUS_CALLBACK_RETURNED_PRI_BACK"; - break; - case MD_NTSTATUS_WIN_STATUS_CALLBACK_RETURNED_THREAD_AFFINITY: - reason = "STATUS_CALLBACK_RETURNED_THREAD_AFFINITY"; - break; - case MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_DISABLED: - reason = "STATUS_DISK_REPAIR_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_DOMAIN_RENAME_IN_PROGRESS: - reason = "STATUS_DS_DOMAIN_RENAME_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_DISK_QUOTA_EXCEEDED: - reason = "STATUS_DISK_QUOTA_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_CONTENT_BLOCKED: - reason = "STATUS_CONTENT_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_CLUSTERS: - reason = "STATUS_BAD_CLUSTERS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLUME_DIRTY: - reason = "STATUS_VOLUME_DIRTY"; - break; - case MD_NTSTATUS_WIN_STATUS_DISK_REPAIR_UNSUCCESSFUL: - reason = "STATUS_DISK_REPAIR_UNSUCCESSFUL"; - break; - case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_OVERFULL: - reason = "STATUS_CORRUPT_LOG_OVERFULL"; - break; - case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CORRUPTED: - reason = "STATUS_CORRUPT_LOG_CORRUPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UNAVAILABLE: - reason = "STATUS_CORRUPT_LOG_UNAVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_DELETED_FULL: - reason = "STATUS_CORRUPT_LOG_DELETED_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_CLEARED: - reason = "STATUS_CORRUPT_LOG_CLEARED"; - break; - case MD_NTSTATUS_WIN_STATUS_ORPHAN_NAME_EXHAUSTED: - reason = "STATUS_ORPHAN_NAME_EXHAUSTED"; - break; - case MD_NTSTATUS_WIN_STATUS_PROACTIVE_SCAN_IN_PROGRESS: - reason = "STATUS_PROACTIVE_SCAN_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_ENCRYPTED_IO_NOT_POSSIBLE: - reason = "STATUS_ENCRYPTED_IO_NOT_POSSIBLE"; - break; - case MD_NTSTATUS_WIN_STATUS_CORRUPT_LOG_UPLEVEL_RECORDS: - reason = "STATUS_CORRUPT_LOG_UPLEVEL_RECORDS"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_CHECKED_OUT: - reason = "STATUS_FILE_CHECKED_OUT"; - break; - case MD_NTSTATUS_WIN_STATUS_CHECKOUT_REQUIRED: - reason = "STATUS_CHECKOUT_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_FILE_TYPE: - reason = "STATUS_BAD_FILE_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_TOO_LARGE: - reason = "STATUS_FILE_TOO_LARGE"; - break; - case MD_NTSTATUS_WIN_STATUS_FORMS_AUTH_REQUIRED: - reason = "STATUS_FORMS_AUTH_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_VIRUS_INFECTED: - reason = "STATUS_VIRUS_INFECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_VIRUS_DELETED: - reason = "STATUS_VIRUS_DELETED"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_MCFG_TABLE: - reason = "STATUS_BAD_MCFG_TABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_CANNOT_BREAK_OPLOCK: - reason = "STATUS_CANNOT_BREAK_OPLOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_KEY: - reason = "STATUS_BAD_KEY"; - break; - case MD_NTSTATUS_WIN_STATUS_BAD_DATA: - reason = "STATUS_BAD_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_KEY: - reason = "STATUS_NO_KEY"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_HANDLE_REVOKED: - reason = "STATUS_FILE_HANDLE_REVOKED"; - break; - case MD_NTSTATUS_WIN_STATUS_WOW_ASSERTION: - reason = "STATUS_WOW_ASSERTION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_SIGNATURE: - reason = "STATUS_INVALID_SIGNATURE"; - break; - case MD_NTSTATUS_WIN_STATUS_HMAC_NOT_SUPPORTED: - reason = "STATUS_HMAC_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_AUTH_TAG_MISMATCH: - reason = "STATUS_AUTH_TAG_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_STATE_TRANSITION: - reason = "STATUS_INVALID_STATE_TRANSITION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_KERNEL_INFO_VERSION: - reason = "STATUS_INVALID_KERNEL_INFO_VERSION"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PEP_INFO_VERSION: - reason = "STATUS_INVALID_PEP_INFO_VERSION"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_QUEUE_OVERFLOW: - reason = "STATUS_IPSEC_QUEUE_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_ND_QUEUE_OVERFLOW: - reason = "STATUS_ND_QUEUE_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_HOPLIMIT_EXCEEDED: - reason = "STATUS_HOPLIMIT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_PROTOCOL_NOT_SUPPORTED: - reason = "STATUS_PROTOCOL_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_FASTPATH_REJECTED: - reason = "STATUS_FASTPATH_REJECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED: - reason = "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_DISCONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR: - reason = "STATUS_LOST_WRITEBEHIND_DATA_NETWORK_SERVER_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR: - reason = "STATUS_LOST_WRITEBEHIND_DATA_LOCAL_DISK_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_XML_PARSE_ERROR: - reason = "STATUS_XML_PARSE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_XMLDSIG_ERROR: - reason = "STATUS_XMLDSIG_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_WRONG_COMPARTMENT: - reason = "STATUS_WRONG_COMPARTMENT"; - break; - case MD_NTSTATUS_WIN_STATUS_AUTHIP_FAILURE: - reason = "STATUS_AUTHIP_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS: - reason = "STATUS_DS_OID_MAPPED_GROUP_CANT_HAVE_MEMBERS"; - break; - case MD_NTSTATUS_WIN_STATUS_DS_OID_NOT_FOUND: - reason = "STATUS_DS_OID_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_INCORRECT_ACCOUNT_TYPE: - reason = "STATUS_INCORRECT_ACCOUNT_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_HASH_NOT_SUPPORTED: - reason = "STATUS_HASH_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_HASH_NOT_PRESENT: - reason = "STATUS_HASH_NOT_PRESENT"; - break; - case MD_NTSTATUS_WIN_STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED: - reason = "STATUS_SECONDARY_IC_PROVIDER_NOT_REGISTERED"; - break; - case MD_NTSTATUS_WIN_STATUS_GPIO_CLIENT_INFORMATION_INVALID: - reason = "STATUS_GPIO_CLIENT_INFORMATION_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_GPIO_VERSION_NOT_SUPPORTED: - reason = "STATUS_GPIO_VERSION_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GPIO_INVALID_REGISTRATION_PACKET: - reason = "STATUS_GPIO_INVALID_REGISTRATION_PACKET"; - break; - case MD_NTSTATUS_WIN_STATUS_GPIO_OPERATION_DENIED: - reason = "STATUS_GPIO_OPERATION_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE: - reason = "STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE"; - break; - case MD_NTSTATUS_WIN_STATUS_CANNOT_SWITCH_RUNLEVEL: - reason = "STATUS_CANNOT_SWITCH_RUNLEVEL"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_RUNLEVEL_SETTING: - reason = "STATUS_INVALID_RUNLEVEL_SETTING"; - break; - case MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_TIMEOUT: - reason = "STATUS_RUNLEVEL_SWITCH_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT: - reason = "STATUS_RUNLEVEL_SWITCH_AGENT_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_RUNLEVEL_SWITCH_IN_PROGRESS: - reason = "STATUS_RUNLEVEL_SWITCH_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_APPCONTAINER: - reason = "STATUS_NOT_APPCONTAINER"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_SUPPORTED_IN_APPCONTAINER: - reason = "STATUS_NOT_SUPPORTED_IN_APPCONTAINER"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_PACKAGE_SID_LENGTH: - reason = "STATUS_INVALID_PACKAGE_SID_LENGTH"; - break; - case MD_NTSTATUS_WIN_STATUS_APP_DATA_NOT_FOUND: - reason = "STATUS_APP_DATA_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_APP_DATA_EXPIRED: - reason = "STATUS_APP_DATA_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_APP_DATA_CORRUPT: - reason = "STATUS_APP_DATA_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_APP_DATA_LIMIT_EXCEEDED: - reason = "STATUS_APP_DATA_LIMIT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_APP_DATA_REBOOT_REQUIRED: - reason = "STATUS_APP_DATA_REBOOT_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED: - reason = "STATUS_OFFLOAD_READ_FLT_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED: - reason = "STATUS_OFFLOAD_WRITE_FLT_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED: - reason = "STATUS_OFFLOAD_READ_FILE_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED: - reason = "STATUS_OFFLOAD_WRITE_FILE_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_DBG_NO_STATE_CHANGE: - reason = "DBG_NO_STATE_CHANGE"; - break; - case MD_NTSTATUS_WIN_DBG_APP_NOT_IDLE: - reason = "DBG_APP_NOT_IDLE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_BINDING: - reason = "RPC_NT_INVALID_STRING_BINDING"; - break; - case MD_NTSTATUS_WIN_RPC_NT_WRONG_KIND_OF_BINDING: - reason = "RPC_NT_WRONG_KIND_OF_BINDING"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_BINDING: - reason = "RPC_NT_INVALID_BINDING"; - break; - case MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_SUPPORTED: - reason = "RPC_NT_PROTSEQ_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_RPC_PROTSEQ: - reason = "RPC_NT_INVALID_RPC_PROTSEQ"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_STRING_UUID: - reason = "RPC_NT_INVALID_STRING_UUID"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_ENDPOINT_FORMAT: - reason = "RPC_NT_INVALID_ENDPOINT_FORMAT"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_NET_ADDR: - reason = "RPC_NT_INVALID_NET_ADDR"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_ENDPOINT_FOUND: - reason = "RPC_NT_NO_ENDPOINT_FOUND"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_TIMEOUT: - reason = "RPC_NT_INVALID_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_RPC_NT_OBJECT_NOT_FOUND: - reason = "RPC_NT_OBJECT_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_RPC_NT_ALREADY_REGISTERED: - reason = "RPC_NT_ALREADY_REGISTERED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_TYPE_ALREADY_REGISTERED: - reason = "RPC_NT_TYPE_ALREADY_REGISTERED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_ALREADY_LISTENING: - reason = "RPC_NT_ALREADY_LISTENING"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS_REGISTERED: - reason = "RPC_NT_NO_PROTSEQS_REGISTERED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NOT_LISTENING: - reason = "RPC_NT_NOT_LISTENING"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_MGR_TYPE: - reason = "RPC_NT_UNKNOWN_MGR_TYPE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_IF: - reason = "RPC_NT_UNKNOWN_IF"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_BINDINGS: - reason = "RPC_NT_NO_BINDINGS"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_PROTSEQS: - reason = "RPC_NT_NO_PROTSEQS"; - break; - case MD_NTSTATUS_WIN_RPC_NT_CANT_CREATE_ENDPOINT: - reason = "RPC_NT_CANT_CREATE_ENDPOINT"; - break; - case MD_NTSTATUS_WIN_RPC_NT_OUT_OF_RESOURCES: - reason = "RPC_NT_OUT_OF_RESOURCES"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SERVER_UNAVAILABLE: - reason = "RPC_NT_SERVER_UNAVAILABLE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SERVER_TOO_BUSY: - reason = "RPC_NT_SERVER_TOO_BUSY"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_NETWORK_OPTIONS: - reason = "RPC_NT_INVALID_NETWORK_OPTIONS"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_CALL_ACTIVE: - reason = "RPC_NT_NO_CALL_ACTIVE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED: - reason = "RPC_NT_CALL_FAILED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_CALL_FAILED_DNE: - reason = "RPC_NT_CALL_FAILED_DNE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_PROTOCOL_ERROR: - reason = "RPC_NT_PROTOCOL_ERROR"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TRANS_SYN: - reason = "RPC_NT_UNSUPPORTED_TRANS_SYN"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_TYPE: - reason = "RPC_NT_UNSUPPORTED_TYPE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_TAG: - reason = "RPC_NT_INVALID_TAG"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_BOUND: - reason = "RPC_NT_INVALID_BOUND"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_ENTRY_NAME: - reason = "RPC_NT_NO_ENTRY_NAME"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_NAME_SYNTAX: - reason = "RPC_NT_INVALID_NAME_SYNTAX"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_NAME_SYNTAX: - reason = "RPC_NT_UNSUPPORTED_NAME_SYNTAX"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UUID_NO_ADDRESS: - reason = "RPC_NT_UUID_NO_ADDRESS"; - break; - case MD_NTSTATUS_WIN_RPC_NT_DUPLICATE_ENDPOINT: - reason = "RPC_NT_DUPLICATE_ENDPOINT"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_TYPE: - reason = "RPC_NT_UNKNOWN_AUTHN_TYPE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_MAX_CALLS_TOO_SMALL: - reason = "RPC_NT_MAX_CALLS_TOO_SMALL"; - break; - case MD_NTSTATUS_WIN_RPC_NT_STRING_TOO_LONG: - reason = "RPC_NT_STRING_TOO_LONG"; - break; - case MD_NTSTATUS_WIN_RPC_NT_PROTSEQ_NOT_FOUND: - reason = "RPC_NT_PROTSEQ_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_RPC_NT_PROCNUM_OUT_OF_RANGE: - reason = "RPC_NT_PROCNUM_OUT_OF_RANGE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_BINDING_HAS_NO_AUTH: - reason = "RPC_NT_BINDING_HAS_NO_AUTH"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_SERVICE: - reason = "RPC_NT_UNKNOWN_AUTHN_SERVICE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHN_LEVEL: - reason = "RPC_NT_UNKNOWN_AUTHN_LEVEL"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_AUTH_IDENTITY: - reason = "RPC_NT_INVALID_AUTH_IDENTITY"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNKNOWN_AUTHZ_SERVICE: - reason = "RPC_NT_UNKNOWN_AUTHZ_SERVICE"; - break; - case MD_NTSTATUS_WIN_EPT_NT_INVALID_ENTRY: - reason = "EPT_NT_INVALID_ENTRY"; - break; - case MD_NTSTATUS_WIN_EPT_NT_CANT_PERFORM_OP: - reason = "EPT_NT_CANT_PERFORM_OP"; - break; - case MD_NTSTATUS_WIN_EPT_NT_NOT_REGISTERED: - reason = "EPT_NT_NOT_REGISTERED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NOTHING_TO_EXPORT: - reason = "RPC_NT_NOTHING_TO_EXPORT"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INCOMPLETE_NAME: - reason = "RPC_NT_INCOMPLETE_NAME"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_VERS_OPTION: - reason = "RPC_NT_INVALID_VERS_OPTION"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_MORE_MEMBERS: - reason = "RPC_NT_NO_MORE_MEMBERS"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NOT_ALL_OBJS_UNEXPORTED: - reason = "RPC_NT_NOT_ALL_OBJS_UNEXPORTED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INTERFACE_NOT_FOUND: - reason = "RPC_NT_INTERFACE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_RPC_NT_ENTRY_ALREADY_EXISTS: - reason = "RPC_NT_ENTRY_ALREADY_EXISTS"; - break; - case MD_NTSTATUS_WIN_RPC_NT_ENTRY_NOT_FOUND: - reason = "RPC_NT_ENTRY_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NAME_SERVICE_UNAVAILABLE: - reason = "RPC_NT_NAME_SERVICE_UNAVAILABLE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_NAF_ID: - reason = "RPC_NT_INVALID_NAF_ID"; - break; - case MD_NTSTATUS_WIN_RPC_NT_CANNOT_SUPPORT: - reason = "RPC_NT_CANNOT_SUPPORT"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_CONTEXT_AVAILABLE: - reason = "RPC_NT_NO_CONTEXT_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INTERNAL_ERROR: - reason = "RPC_NT_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_RPC_NT_ZERO_DIVIDE: - reason = "RPC_NT_ZERO_DIVIDE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_ADDRESS_ERROR: - reason = "RPC_NT_ADDRESS_ERROR"; - break; - case MD_NTSTATUS_WIN_RPC_NT_FP_DIV_ZERO: - reason = "RPC_NT_FP_DIV_ZERO"; - break; - case MD_NTSTATUS_WIN_RPC_NT_FP_UNDERFLOW: - reason = "RPC_NT_FP_UNDERFLOW"; - break; - case MD_NTSTATUS_WIN_RPC_NT_FP_OVERFLOW: - reason = "RPC_NT_FP_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_RPC_NT_CALL_IN_PROGRESS: - reason = "RPC_NT_CALL_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_MORE_BINDINGS: - reason = "RPC_NT_NO_MORE_BINDINGS"; - break; - case MD_NTSTATUS_WIN_RPC_NT_GROUP_MEMBER_NOT_FOUND: - reason = "RPC_NT_GROUP_MEMBER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_EPT_NT_CANT_CREATE: - reason = "EPT_NT_CANT_CREATE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_OBJECT: - reason = "RPC_NT_INVALID_OBJECT"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_INTERFACES: - reason = "RPC_NT_NO_INTERFACES"; - break; - case MD_NTSTATUS_WIN_RPC_NT_CALL_CANCELLED: - reason = "RPC_NT_CALL_CANCELLED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_BINDING_INCOMPLETE: - reason = "RPC_NT_BINDING_INCOMPLETE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_COMM_FAILURE: - reason = "RPC_NT_COMM_FAILURE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_UNSUPPORTED_AUTHN_LEVEL: - reason = "RPC_NT_UNSUPPORTED_AUTHN_LEVEL"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_PRINC_NAME: - reason = "RPC_NT_NO_PRINC_NAME"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NOT_RPC_ERROR: - reason = "RPC_NT_NOT_RPC_ERROR"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SEC_PKG_ERROR: - reason = "RPC_NT_SEC_PKG_ERROR"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NOT_CANCELLED: - reason = "RPC_NT_NOT_CANCELLED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_HANDLE: - reason = "RPC_NT_INVALID_ASYNC_HANDLE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_ASYNC_CALL: - reason = "RPC_NT_INVALID_ASYNC_CALL"; - break; - case MD_NTSTATUS_WIN_RPC_NT_PROXY_ACCESS_DENIED: - reason = "RPC_NT_PROXY_ACCESS_DENIED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_COOKIE_AUTH_FAILED: - reason = "RPC_NT_COOKIE_AUTH_FAILED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NO_MORE_ENTRIES: - reason = "RPC_NT_NO_MORE_ENTRIES"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_OPEN_FAIL: - reason = "RPC_NT_SS_CHAR_TRANS_OPEN_FAIL"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SS_CHAR_TRANS_SHORT_FILE: - reason = "RPC_NT_SS_CHAR_TRANS_SHORT_FILE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SS_IN_NULL_CONTEXT: - reason = "RPC_NT_SS_IN_NULL_CONTEXT"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_MISMATCH: - reason = "RPC_NT_SS_CONTEXT_MISMATCH"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SS_CONTEXT_DAMAGED: - reason = "RPC_NT_SS_CONTEXT_DAMAGED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SS_HANDLES_MISMATCH: - reason = "RPC_NT_SS_HANDLES_MISMATCH"; - break; - case MD_NTSTATUS_WIN_RPC_NT_SS_CANNOT_GET_CALL_HANDLE: - reason = "RPC_NT_SS_CANNOT_GET_CALL_HANDLE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_NULL_REF_POINTER: - reason = "RPC_NT_NULL_REF_POINTER"; - break; - case MD_NTSTATUS_WIN_RPC_NT_ENUM_VALUE_OUT_OF_RANGE: - reason = "RPC_NT_ENUM_VALUE_OUT_OF_RANGE"; - break; - case MD_NTSTATUS_WIN_RPC_NT_BYTE_COUNT_TOO_SMALL: - reason = "RPC_NT_BYTE_COUNT_TOO_SMALL"; - break; - case MD_NTSTATUS_WIN_RPC_NT_BAD_STUB_DATA: - reason = "RPC_NT_BAD_STUB_DATA"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_ES_ACTION: - reason = "RPC_NT_INVALID_ES_ACTION"; - break; - case MD_NTSTATUS_WIN_RPC_NT_WRONG_ES_VERSION: - reason = "RPC_NT_WRONG_ES_VERSION"; - break; - case MD_NTSTATUS_WIN_RPC_NT_WRONG_STUB_VERSION: - reason = "RPC_NT_WRONG_STUB_VERSION"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OBJECT: - reason = "RPC_NT_INVALID_PIPE_OBJECT"; - break; - case MD_NTSTATUS_WIN_RPC_NT_INVALID_PIPE_OPERATION: - reason = "RPC_NT_INVALID_PIPE_OPERATION"; - break; - case MD_NTSTATUS_WIN_RPC_NT_WRONG_PIPE_VERSION: - reason = "RPC_NT_WRONG_PIPE_VERSION"; - break; - case MD_NTSTATUS_WIN_RPC_NT_PIPE_CLOSED: - reason = "RPC_NT_PIPE_CLOSED"; - break; - case MD_NTSTATUS_WIN_RPC_NT_PIPE_DISCIPLINE_ERROR: - reason = "RPC_NT_PIPE_DISCIPLINE_ERROR"; - break; - case MD_NTSTATUS_WIN_RPC_NT_PIPE_EMPTY: - reason = "RPC_NT_PIPE_EMPTY"; - break; - case MD_NTSTATUS_WIN_STATUS_PNP_BAD_MPS_TABLE: - reason = "STATUS_PNP_BAD_MPS_TABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_PNP_TRANSLATION_FAILED: - reason = "STATUS_PNP_TRANSLATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_PNP_IRQ_TRANSLATION_FAILED: - reason = "STATUS_PNP_IRQ_TRANSLATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_PNP_INVALID_ID: - reason = "STATUS_PNP_INVALID_ID"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_REISSUE_AS_CACHED: - reason = "STATUS_IO_REISSUE_AS_CACHED"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_INVALID: - reason = "STATUS_CTX_WINSTATION_NAME_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_INVALID_PD: - reason = "STATUS_CTX_INVALID_PD"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_PD_NOT_FOUND: - reason = "STATUS_CTX_PD_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_CLOSE_PENDING: - reason = "STATUS_CTX_CLOSE_PENDING"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_NO_OUTBUF: - reason = "STATUS_CTX_NO_OUTBUF"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_INF_NOT_FOUND: - reason = "STATUS_CTX_MODEM_INF_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_INVALID_MODEMNAME: - reason = "STATUS_CTX_INVALID_MODEMNAME"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_RESPONSE_ERROR: - reason = "STATUS_CTX_RESPONSE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_TIMEOUT: - reason = "STATUS_CTX_MODEM_RESPONSE_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_CARRIER: - reason = "STATUS_CTX_MODEM_RESPONSE_NO_CARRIER"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE: - reason = "STATUS_CTX_MODEM_RESPONSE_NO_DIALTONE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_BUSY: - reason = "STATUS_CTX_MODEM_RESPONSE_BUSY"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_MODEM_RESPONSE_VOICE: - reason = "STATUS_CTX_MODEM_RESPONSE_VOICE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_TD_ERROR: - reason = "STATUS_CTX_TD_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_CLIENT_INVALID: - reason = "STATUS_CTX_LICENSE_CLIENT_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_NOT_AVAILABLE: - reason = "STATUS_CTX_LICENSE_NOT_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_LICENSE_EXPIRED: - reason = "STATUS_CTX_LICENSE_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NOT_FOUND: - reason = "STATUS_CTX_WINSTATION_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_NAME_COLLISION: - reason = "STATUS_CTX_WINSTATION_NAME_COLLISION"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_BUSY: - reason = "STATUS_CTX_WINSTATION_BUSY"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_BAD_VIDEO_MODE: - reason = "STATUS_CTX_BAD_VIDEO_MODE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_GRAPHICS_INVALID: - reason = "STATUS_CTX_GRAPHICS_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_NOT_CONSOLE: - reason = "STATUS_CTX_NOT_CONSOLE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_QUERY_TIMEOUT: - reason = "STATUS_CTX_CLIENT_QUERY_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_DISCONNECT: - reason = "STATUS_CTX_CONSOLE_DISCONNECT"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_CONSOLE_CONNECT: - reason = "STATUS_CTX_CONSOLE_CONNECT"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DENIED: - reason = "STATUS_CTX_SHADOW_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_WINSTATION_ACCESS_DENIED: - reason = "STATUS_CTX_WINSTATION_ACCESS_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_INVALID_WD: - reason = "STATUS_CTX_INVALID_WD"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_WD_NOT_FOUND: - reason = "STATUS_CTX_WD_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_INVALID: - reason = "STATUS_CTX_SHADOW_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_DISABLED: - reason = "STATUS_CTX_SHADOW_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_RDP_PROTOCOL_ERROR: - reason = "STATUS_RDP_PROTOCOL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_NOT_SET: - reason = "STATUS_CTX_CLIENT_LICENSE_NOT_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_CLIENT_LICENSE_IN_USE: - reason = "STATUS_CTX_CLIENT_LICENSE_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE: - reason = "STATUS_CTX_SHADOW_ENDED_BY_MODE_CHANGE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_SHADOW_NOT_RUNNING: - reason = "STATUS_CTX_SHADOW_NOT_RUNNING"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_LOGON_DISABLED: - reason = "STATUS_CTX_LOGON_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_CTX_SECURITY_LAYER_ERROR: - reason = "STATUS_CTX_SECURITY_LAYER_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_TS_INCOMPATIBLE_SESSIONS: - reason = "STATUS_TS_INCOMPATIBLE_SESSIONS"; - break; - case MD_NTSTATUS_WIN_STATUS_TS_VIDEO_SUBSYSTEM_ERROR: - reason = "STATUS_TS_VIDEO_SUBSYSTEM_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_FOUND: - reason = "STATUS_MUI_FILE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_MUI_INVALID_FILE: - reason = "STATUS_MUI_INVALID_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_MUI_INVALID_RC_CONFIG: - reason = "STATUS_MUI_INVALID_RC_CONFIG"; - break; - case MD_NTSTATUS_WIN_STATUS_MUI_INVALID_LOCALE_NAME: - reason = "STATUS_MUI_INVALID_LOCALE_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME: - reason = "STATUS_MUI_INVALID_ULTIMATEFALLBACK_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_MUI_FILE_NOT_LOADED: - reason = "STATUS_MUI_FILE_NOT_LOADED"; - break; - case MD_NTSTATUS_WIN_STATUS_RESOURCE_ENUM_USER_STOP: - reason = "STATUS_RESOURCE_ENUM_USER_STOP"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NODE: - reason = "STATUS_CLUSTER_INVALID_NODE"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_EXISTS: - reason = "STATUS_CLUSTER_NODE_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_IN_PROGRESS: - reason = "STATUS_CLUSTER_JOIN_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_FOUND: - reason = "STATUS_CLUSTER_NODE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND: - reason = "STATUS_CLUSTER_LOCAL_NODE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_EXISTS: - reason = "STATUS_CLUSTER_NETWORK_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_FOUND: - reason = "STATUS_CLUSTER_NETWORK_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_EXISTS: - reason = "STATUS_CLUSTER_NETINTERFACE_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETINTERFACE_NOT_FOUND: - reason = "STATUS_CLUSTER_NETINTERFACE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_REQUEST: - reason = "STATUS_CLUSTER_INVALID_REQUEST"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK_PROVIDER: - reason = "STATUS_CLUSTER_INVALID_NETWORK_PROVIDER"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_DOWN: - reason = "STATUS_CLUSTER_NODE_DOWN"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UNREACHABLE: - reason = "STATUS_CLUSTER_NODE_UNREACHABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_MEMBER: - reason = "STATUS_CLUSTER_NODE_NOT_MEMBER"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS: - reason = "STATUS_CLUSTER_JOIN_NOT_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_INVALID_NETWORK: - reason = "STATUS_CLUSTER_INVALID_NETWORK"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_NET_ADAPTERS: - reason = "STATUS_CLUSTER_NO_NET_ADAPTERS"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_UP: - reason = "STATUS_CLUSTER_NODE_UP"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_PAUSED: - reason = "STATUS_CLUSTER_NODE_PAUSED"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NODE_NOT_PAUSED: - reason = "STATUS_CLUSTER_NODE_NOT_PAUSED"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NO_SECURITY_CONTEXT: - reason = "STATUS_CLUSTER_NO_SECURITY_CONTEXT"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NETWORK_NOT_INTERNAL: - reason = "STATUS_CLUSTER_NETWORK_NOT_INTERNAL"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_POISONED: - reason = "STATUS_CLUSTER_POISONED"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_NON_CSV_PATH: - reason = "STATUS_CLUSTER_NON_CSV_PATH"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL: - reason = "STATUS_CLUSTER_CSV_VOLUME_NOT_LOCAL"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS: - reason = "STATUS_CLUSTER_CSV_READ_OPLOCK_BREAK_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR: - reason = "STATUS_CLUSTER_CSV_AUTO_PAUSE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_REDIRECTED: - reason = "STATUS_CLUSTER_CSV_REDIRECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_NOT_REDIRECTED: - reason = "STATUS_CLUSTER_CSV_NOT_REDIRECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING: - reason = "STATUS_CLUSTER_CSV_VOLUME_DRAINING"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS: - reason = "STATUS_CLUSTER_CSV_SNAPSHOT_CREATION_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL: - reason = "STATUS_CLUSTER_CSV_VOLUME_DRAINING_SUCCEEDED_DOWNLEVEL"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OPCODE: - reason = "STATUS_ACPI_INVALID_OPCODE"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_STACK_OVERFLOW: - reason = "STATUS_ACPI_STACK_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_ASSERT_FAILED: - reason = "STATUS_ACPI_ASSERT_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_INDEX: - reason = "STATUS_ACPI_INVALID_INDEX"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGUMENT: - reason = "STATUS_ACPI_INVALID_ARGUMENT"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_FATAL: - reason = "STATUS_ACPI_FATAL"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_SUPERNAME: - reason = "STATUS_ACPI_INVALID_SUPERNAME"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ARGTYPE: - reason = "STATUS_ACPI_INVALID_ARGTYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_OBJTYPE: - reason = "STATUS_ACPI_INVALID_OBJTYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TARGETTYPE: - reason = "STATUS_ACPI_INVALID_TARGETTYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INCORRECT_ARGUMENT_COUNT: - reason = "STATUS_ACPI_INCORRECT_ARGUMENT_COUNT"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_ADDRESS_NOT_MAPPED: - reason = "STATUS_ACPI_ADDRESS_NOT_MAPPED"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_EVENTTYPE: - reason = "STATUS_ACPI_INVALID_EVENTTYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_HANDLER_COLLISION: - reason = "STATUS_ACPI_HANDLER_COLLISION"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_DATA: - reason = "STATUS_ACPI_INVALID_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_REGION: - reason = "STATUS_ACPI_INVALID_REGION"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_ACCESS_SIZE: - reason = "STATUS_ACPI_INVALID_ACCESS_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_ACQUIRE_GLOBAL_LOCK: - reason = "STATUS_ACPI_ACQUIRE_GLOBAL_LOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_ALREADY_INITIALIZED: - reason = "STATUS_ACPI_ALREADY_INITIALIZED"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_NOT_INITIALIZED: - reason = "STATUS_ACPI_NOT_INITIALIZED"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_MUTEX_LEVEL: - reason = "STATUS_ACPI_INVALID_MUTEX_LEVEL"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNED: - reason = "STATUS_ACPI_MUTEX_NOT_OWNED"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_MUTEX_NOT_OWNER: - reason = "STATUS_ACPI_MUTEX_NOT_OWNER"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_RS_ACCESS: - reason = "STATUS_ACPI_RS_ACCESS"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_INVALID_TABLE: - reason = "STATUS_ACPI_INVALID_TABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_REG_HANDLER_FAILED: - reason = "STATUS_ACPI_REG_HANDLER_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_ACPI_POWER_REQUEST_FAILED: - reason = "STATUS_ACPI_POWER_REQUEST_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_SECTION_NOT_FOUND: - reason = "STATUS_SXS_SECTION_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_CANT_GEN_ACTCTX: - reason = "STATUS_SXS_CANT_GEN_ACTCTX"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_INVALID_ACTCTXDATA_FORMAT: - reason = "STATUS_SXS_INVALID_ACTCTXDATA_FORMAT"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_NOT_FOUND: - reason = "STATUS_SXS_ASSEMBLY_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_FORMAT_ERROR: - reason = "STATUS_SXS_MANIFEST_FORMAT_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_PARSE_ERROR: - reason = "STATUS_SXS_MANIFEST_PARSE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_ACTIVATION_CONTEXT_DISABLED: - reason = "STATUS_SXS_ACTIVATION_CONTEXT_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_KEY_NOT_FOUND: - reason = "STATUS_SXS_KEY_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_VERSION_CONFLICT: - reason = "STATUS_SXS_VERSION_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_WRONG_SECTION_TYPE: - reason = "STATUS_SXS_WRONG_SECTION_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_THREAD_QUERIES_DISABLED: - reason = "STATUS_SXS_THREAD_QUERIES_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_MISSING: - reason = "STATUS_SXS_ASSEMBLY_MISSING"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET: - reason = "STATUS_SXS_PROCESS_DEFAULT_ALREADY_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_EARLY_DEACTIVATION: - reason = "STATUS_SXS_EARLY_DEACTIVATION"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_INVALID_DEACTIVATION: - reason = "STATUS_SXS_INVALID_DEACTIVATION"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_MULTIPLE_DEACTIVATION: - reason = "STATUS_SXS_MULTIPLE_DEACTIVATION"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY: - reason = "STATUS_SXS_SYSTEM_DEFAULT_ACTIVATION_CONTEXT_EMPTY"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_PROCESS_TERMINATION_REQUESTED: - reason = "STATUS_SXS_PROCESS_TERMINATION_REQUESTED"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_CORRUPT_ACTIVATION_STACK: - reason = "STATUS_SXS_CORRUPT_ACTIVATION_STACK"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_CORRUPTION: - reason = "STATUS_SXS_CORRUPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE: - reason = "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_VALUE"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME: - reason = "STATUS_SXS_INVALID_IDENTITY_ATTRIBUTE_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE: - reason = "STATUS_SXS_IDENTITY_DUPLICATE_ATTRIBUTE"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_IDENTITY_PARSE_ERROR: - reason = "STATUS_SXS_IDENTITY_PARSE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_COMPONENT_STORE_CORRUPT: - reason = "STATUS_SXS_COMPONENT_STORE_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISMATCH: - reason = "STATUS_SXS_FILE_HASH_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT: - reason = "STATUS_SXS_MANIFEST_IDENTITY_SAME_BUT_CONTENTS_DIFFERENT"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_IDENTITIES_DIFFERENT: - reason = "STATUS_SXS_IDENTITIES_DIFFERENT"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT: - reason = "STATUS_SXS_ASSEMBLY_IS_NOT_A_DEPLOYMENT"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY: - reason = "STATUS_SXS_FILE_NOT_PART_OF_ASSEMBLY"; - break; - case MD_NTSTATUS_WIN_STATUS_ADVANCED_INSTALLER_FAILED: - reason = "STATUS_ADVANCED_INSTALLER_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_XML_ENCODING_MISMATCH: - reason = "STATUS_XML_ENCODING_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_MANIFEST_TOO_BIG: - reason = "STATUS_SXS_MANIFEST_TOO_BIG"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_SETTING_NOT_REGISTERED: - reason = "STATUS_SXS_SETTING_NOT_REGISTERED"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE: - reason = "STATUS_SXS_TRANSACTION_CLOSURE_INCOMPLETE"; - break; - case MD_NTSTATUS_WIN_STATUS_SMI_PRIMITIVE_INSTALLER_FAILED: - reason = "STATUS_SMI_PRIMITIVE_INSTALLER_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_GENERIC_COMMAND_FAILED: - reason = "STATUS_GENERIC_COMMAND_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_SXS_FILE_HASH_MISSING: - reason = "STATUS_SXS_FILE_HASH_MISSING"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_CONFLICT: - reason = "STATUS_TRANSACTIONAL_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_INVALID_TRANSACTION: - reason = "STATUS_INVALID_TRANSACTION"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ACTIVE: - reason = "STATUS_TRANSACTION_NOT_ACTIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_TM_INITIALIZATION_FAILED: - reason = "STATUS_TM_INITIALIZATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_RM_NOT_ACTIVE: - reason = "STATUS_RM_NOT_ACTIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_RM_METADATA_CORRUPT: - reason = "STATUS_RM_METADATA_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_JOINED: - reason = "STATUS_TRANSACTION_NOT_JOINED"; - break; - case MD_NTSTATUS_WIN_STATUS_DIRECTORY_NOT_RM: - reason = "STATUS_DIRECTORY_NOT_RM"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE: - reason = "STATUS_TRANSACTIONS_UNSUPPORTED_REMOTE"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_RESIZE_INVALID_SIZE: - reason = "STATUS_LOG_RESIZE_INVALID_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_REMOTE_FILE_VERSION_MISMATCH: - reason = "STATUS_REMOTE_FILE_VERSION_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_ALREADY_EXISTS: - reason = "STATUS_CRM_PROTOCOL_ALREADY_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_PROPAGATION_FAILED: - reason = "STATUS_TRANSACTION_PROPAGATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_CRM_PROTOCOL_NOT_FOUND: - reason = "STATUS_CRM_PROTOCOL_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_SUPERIOR_EXISTS: - reason = "STATUS_TRANSACTION_SUPERIOR_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUEST_NOT_VALID: - reason = "STATUS_TRANSACTION_REQUEST_NOT_VALID"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_REQUESTED: - reason = "STATUS_TRANSACTION_NOT_REQUESTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_ABORTED: - reason = "STATUS_TRANSACTION_ALREADY_ABORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_ALREADY_COMMITTED: - reason = "STATUS_TRANSACTION_ALREADY_COMMITTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER: - reason = "STATUS_TRANSACTION_INVALID_MARSHALL_BUFFER"; - break; - case MD_NTSTATUS_WIN_STATUS_CURRENT_TRANSACTION_NOT_VALID: - reason = "STATUS_CURRENT_TRANSACTION_NOT_VALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_GROWTH_FAILED: - reason = "STATUS_LOG_GROWTH_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_OBJECT_NO_LONGER_EXISTS: - reason = "STATUS_OBJECT_NO_LONGER_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_FOUND: - reason = "STATUS_STREAM_MINIVERSION_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_STREAM_MINIVERSION_NOT_VALID: - reason = "STATUS_STREAM_MINIVERSION_NOT_VALID"; - break; - case MD_NTSTATUS_WIN_STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION: - reason = "STATUS_MINIVERSION_INACCESSIBLE_FROM_SPECIFIED_TRANSACTION"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT: - reason = "STATUS_CANT_OPEN_MINIVERSION_WITH_MODIFY_INTENT"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS: - reason = "STATUS_CANT_CREATE_MORE_STREAM_MINIVERSIONS"; - break; - case MD_NTSTATUS_WIN_STATUS_HANDLE_NO_LONGER_VALID: - reason = "STATUS_HANDLE_NO_LONGER_VALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_CORRUPTION_DETECTED: - reason = "STATUS_LOG_CORRUPTION_DETECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_RM_DISCONNECTED: - reason = "STATUS_RM_DISCONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_SUPERIOR: - reason = "STATUS_ENLISTMENT_NOT_SUPERIOR"; - break; - case MD_NTSTATUS_WIN_STATUS_FILE_IDENTITY_NOT_PERSISTENT: - reason = "STATUS_FILE_IDENTITY_NOT_PERSISTENT"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY: - reason = "STATUS_CANT_BREAK_TRANSACTIONAL_DEPENDENCY"; - break; - case MD_NTSTATUS_WIN_STATUS_CANT_CROSS_RM_BOUNDARY: - reason = "STATUS_CANT_CROSS_RM_BOUNDARY"; - break; - case MD_NTSTATUS_WIN_STATUS_TXF_DIR_NOT_EMPTY: - reason = "STATUS_TXF_DIR_NOT_EMPTY"; - break; - case MD_NTSTATUS_WIN_STATUS_INDOUBT_TRANSACTIONS_EXIST: - reason = "STATUS_INDOUBT_TRANSACTIONS_EXIST"; - break; - case MD_NTSTATUS_WIN_STATUS_TM_VOLATILE: - reason = "STATUS_TM_VOLATILE"; - break; - case MD_NTSTATUS_WIN_STATUS_ROLLBACK_TIMER_EXPIRED: - reason = "STATUS_ROLLBACK_TIMER_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_TXF_ATTRIBUTE_CORRUPT: - reason = "STATUS_TXF_ATTRIBUTE_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION: - reason = "STATUS_EFS_NOT_ALLOWED_IN_TRANSACTION"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED: - reason = "STATUS_TRANSACTIONAL_OPEN_NOT_ALLOWED"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE: - reason = "STATUS_TRANSACTED_MAPPING_UNSUPPORTED_REMOTE"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_REQUIRED_PROMOTION: - reason = "STATUS_TRANSACTION_REQUIRED_PROMOTION"; - break; - case MD_NTSTATUS_WIN_STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION: - reason = "STATUS_CANNOT_EXECUTE_FILE_IN_TRANSACTION"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTIONS_NOT_FROZEN: - reason = "STATUS_TRANSACTIONS_NOT_FROZEN"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_FREEZE_IN_PROGRESS: - reason = "STATUS_TRANSACTION_FREEZE_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_NOT_SNAPSHOT_VOLUME: - reason = "STATUS_NOT_SNAPSHOT_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_SAVEPOINT_WITH_OPEN_FILES: - reason = "STATUS_NO_SAVEPOINT_WITH_OPEN_FILES"; - break; - case MD_NTSTATUS_WIN_STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION: - reason = "STATUS_SPARSE_NOT_ALLOWED_IN_TRANSACTION"; - break; - case MD_NTSTATUS_WIN_STATUS_TM_IDENTITY_MISMATCH: - reason = "STATUS_TM_IDENTITY_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_FLOATED_SECTION: - reason = "STATUS_FLOATED_SECTION"; - break; - case MD_NTSTATUS_WIN_STATUS_CANNOT_ACCEPT_TRANSACTED_WORK: - reason = "STATUS_CANNOT_ACCEPT_TRANSACTED_WORK"; - break; - case MD_NTSTATUS_WIN_STATUS_CANNOT_ABORT_TRANSACTIONS: - reason = "STATUS_CANNOT_ABORT_TRANSACTIONS"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_FOUND: - reason = "STATUS_TRANSACTION_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_RESOURCEMANAGER_NOT_FOUND: - reason = "STATUS_RESOURCEMANAGER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_ENLISTMENT_NOT_FOUND: - reason = "STATUS_ENLISTMENT_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_FOUND: - reason = "STATUS_TRANSACTIONMANAGER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_NOT_ONLINE: - reason = "STATUS_TRANSACTIONMANAGER_NOT_ONLINE"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION: - reason = "STATUS_TRANSACTIONMANAGER_RECOVERY_NAME_COLLISION"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ROOT: - reason = "STATUS_TRANSACTION_NOT_ROOT"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_OBJECT_EXPIRED: - reason = "STATUS_TRANSACTION_OBJECT_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION: - reason = "STATUS_COMPRESSION_NOT_ALLOWED_IN_TRANSACTION"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED: - reason = "STATUS_TRANSACTION_RESPONSE_NOT_ENLISTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_RECORD_TOO_LONG: - reason = "STATUS_TRANSACTION_RECORD_TOO_LONG"; - break; - case MD_NTSTATUS_WIN_STATUS_NO_LINK_TRACKING_IN_TRANSACTION: - reason = "STATUS_NO_LINK_TRACKING_IN_TRANSACTION"; - break; - case MD_NTSTATUS_WIN_STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION: - reason = "STATUS_OPERATION_NOT_SUPPORTED_IN_TRANSACTION"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_INTEGRITY_VIOLATED: - reason = "STATUS_TRANSACTION_INTEGRITY_VIOLATED"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH: - reason = "STATUS_TRANSACTIONMANAGER_IDENTITY_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT: - reason = "STATUS_RM_CANNOT_BE_FROZEN_FOR_SNAPSHOT"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_MUST_WRITETHROUGH: - reason = "STATUS_TRANSACTION_MUST_WRITETHROUGH"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NO_SUPERIOR: - reason = "STATUS_TRANSACTION_NO_SUPERIOR"; - break; - case MD_NTSTATUS_WIN_STATUS_EXPIRED_HANDLE: - reason = "STATUS_EXPIRED_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_TRANSACTION_NOT_ENLISTED: - reason = "STATUS_TRANSACTION_NOT_ENLISTED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_INVALID: - reason = "STATUS_LOG_SECTOR_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_PARITY_INVALID: - reason = "STATUS_LOG_SECTOR_PARITY_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_SECTOR_REMAPPED: - reason = "STATUS_LOG_SECTOR_REMAPPED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INCOMPLETE: - reason = "STATUS_LOG_BLOCK_INCOMPLETE"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_INVALID_RANGE: - reason = "STATUS_LOG_INVALID_RANGE"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_BLOCKS_EXHAUSTED: - reason = "STATUS_LOG_BLOCKS_EXHAUSTED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_READ_CONTEXT_INVALID: - reason = "STATUS_LOG_READ_CONTEXT_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_RESTART_INVALID: - reason = "STATUS_LOG_RESTART_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_VERSION: - reason = "STATUS_LOG_BLOCK_VERSION"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_BLOCK_INVALID: - reason = "STATUS_LOG_BLOCK_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_READ_MODE_INVALID: - reason = "STATUS_LOG_READ_MODE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_METADATA_CORRUPT: - reason = "STATUS_LOG_METADATA_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INVALID: - reason = "STATUS_LOG_METADATA_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_METADATA_INCONSISTENT: - reason = "STATUS_LOG_METADATA_INCONSISTENT"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_RESERVATION_INVALID: - reason = "STATUS_LOG_RESERVATION_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_CANT_DELETE: - reason = "STATUS_LOG_CANT_DELETE"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_LIMIT_EXCEEDED: - reason = "STATUS_LOG_CONTAINER_LIMIT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_START_OF_LOG: - reason = "STATUS_LOG_START_OF_LOG"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_POLICY_ALREADY_INSTALLED: - reason = "STATUS_LOG_POLICY_ALREADY_INSTALLED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_POLICY_NOT_INSTALLED: - reason = "STATUS_LOG_POLICY_NOT_INSTALLED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_POLICY_INVALID: - reason = "STATUS_LOG_POLICY_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_POLICY_CONFLICT: - reason = "STATUS_LOG_POLICY_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_PINNED_ARCHIVE_TAIL: - reason = "STATUS_LOG_PINNED_ARCHIVE_TAIL"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_RECORD_NONEXISTENT: - reason = "STATUS_LOG_RECORD_NONEXISTENT"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_RECORDS_RESERVED_INVALID: - reason = "STATUS_LOG_RECORDS_RESERVED_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_SPACE_RESERVED_INVALID: - reason = "STATUS_LOG_SPACE_RESERVED_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_TAIL_INVALID: - reason = "STATUS_LOG_TAIL_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_FULL: - reason = "STATUS_LOG_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_MULTIPLEXED: - reason = "STATUS_LOG_MULTIPLEXED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_DEDICATED: - reason = "STATUS_LOG_DEDICATED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS: - reason = "STATUS_LOG_ARCHIVE_NOT_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_ARCHIVE_IN_PROGRESS: - reason = "STATUS_LOG_ARCHIVE_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_EPHEMERAL: - reason = "STATUS_LOG_EPHEMERAL"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_NOT_ENOUGH_CONTAINERS: - reason = "STATUS_LOG_NOT_ENOUGH_CONTAINERS"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_ALREADY_REGISTERED: - reason = "STATUS_LOG_CLIENT_ALREADY_REGISTERED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_CLIENT_NOT_REGISTERED: - reason = "STATUS_LOG_CLIENT_NOT_REGISTERED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_FULL_HANDLER_IN_PROGRESS: - reason = "STATUS_LOG_FULL_HANDLER_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_READ_FAILED: - reason = "STATUS_LOG_CONTAINER_READ_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_WRITE_FAILED: - reason = "STATUS_LOG_CONTAINER_WRITE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_OPEN_FAILED: - reason = "STATUS_LOG_CONTAINER_OPEN_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_CONTAINER_STATE_INVALID: - reason = "STATUS_LOG_CONTAINER_STATE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_STATE_INVALID: - reason = "STATUS_LOG_STATE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_PINNED: - reason = "STATUS_LOG_PINNED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_METADATA_FLUSH_FAILED: - reason = "STATUS_LOG_METADATA_FLUSH_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_INCONSISTENT_SECURITY: - reason = "STATUS_LOG_INCONSISTENT_SECURITY"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_APPENDED_FLUSH_FAILED: - reason = "STATUS_LOG_APPENDED_FLUSH_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_LOG_PINNED_RESERVATION: - reason = "STATUS_LOG_PINNED_RESERVATION"; - break; - case MD_NTSTATUS_WIN_STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD: - reason = "STATUS_VIDEO_HUNG_DISPLAY_DRIVER_THREAD"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_NO_HANDLER_DEFINED: - reason = "STATUS_FLT_NO_HANDLER_DEFINED"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_DEFINED: - reason = "STATUS_FLT_CONTEXT_ALREADY_DEFINED"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST: - reason = "STATUS_FLT_INVALID_ASYNCHRONOUS_REQUEST"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_DISALLOW_FAST_IO: - reason = "STATUS_FLT_DISALLOW_FAST_IO"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_INVALID_NAME_REQUEST: - reason = "STATUS_FLT_INVALID_NAME_REQUEST"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_NOT_SAFE_TO_POST_OPERATION: - reason = "STATUS_FLT_NOT_SAFE_TO_POST_OPERATION"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_NOT_INITIALIZED: - reason = "STATUS_FLT_NOT_INITIALIZED"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_READY: - reason = "STATUS_FLT_FILTER_NOT_READY"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_POST_OPERATION_CLEANUP: - reason = "STATUS_FLT_POST_OPERATION_CLEANUP"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_INTERNAL_ERROR: - reason = "STATUS_FLT_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_DELETING_OBJECT: - reason = "STATUS_FLT_DELETING_OBJECT"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_MUST_BE_NONPAGED_POOL: - reason = "STATUS_FLT_MUST_BE_NONPAGED_POOL"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_DUPLICATE_ENTRY: - reason = "STATUS_FLT_DUPLICATE_ENTRY"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_CBDQ_DISABLED: - reason = "STATUS_FLT_CBDQ_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_ATTACH: - reason = "STATUS_FLT_DO_NOT_ATTACH"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_DO_NOT_DETACH: - reason = "STATUS_FLT_DO_NOT_DETACH"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_ALTITUDE_COLLISION: - reason = "STATUS_FLT_INSTANCE_ALTITUDE_COLLISION"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NAME_COLLISION: - reason = "STATUS_FLT_INSTANCE_NAME_COLLISION"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_FILTER_NOT_FOUND: - reason = "STATUS_FLT_FILTER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_NOT_FOUND: - reason = "STATUS_FLT_VOLUME_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_INSTANCE_NOT_FOUND: - reason = "STATUS_FLT_INSTANCE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND: - reason = "STATUS_FLT_CONTEXT_ALLOCATION_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_INVALID_CONTEXT_REGISTRATION: - reason = "STATUS_FLT_INVALID_CONTEXT_REGISTRATION"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_NAME_CACHE_MISS: - reason = "STATUS_FLT_NAME_CACHE_MISS"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_NO_DEVICE_OBJECT: - reason = "STATUS_FLT_NO_DEVICE_OBJECT"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_VOLUME_ALREADY_MOUNTED: - reason = "STATUS_FLT_VOLUME_ALREADY_MOUNTED"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_ALREADY_ENLISTED: - reason = "STATUS_FLT_ALREADY_ENLISTED"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_CONTEXT_ALREADY_LINKED: - reason = "STATUS_FLT_CONTEXT_ALREADY_LINKED"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_NO_WAITER_FOR_REPLY: - reason = "STATUS_FLT_NO_WAITER_FOR_REPLY"; - break; - case MD_NTSTATUS_WIN_STATUS_FLT_REGISTRATION_BUSY: - reason = "STATUS_FLT_REGISTRATION_BUSY"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_NO_DESCRIPTOR: - reason = "STATUS_MONITOR_NO_DESCRIPTOR"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT: - reason = "STATUS_MONITOR_UNKNOWN_DESCRIPTOR_FORMAT"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM: - reason = "STATUS_MONITOR_INVALID_DESCRIPTOR_CHECKSUM"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK: - reason = "STATUS_MONITOR_INVALID_STANDARD_TIMING_BLOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED: - reason = "STATUS_MONITOR_WMI_DATABLOCK_REGISTRATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK: - reason = "STATUS_MONITOR_INVALID_SERIAL_NUMBER_MONDSC_BLOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK: - reason = "STATUS_MONITOR_INVALID_USER_FRIENDLY_MONDSC_BLOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA: - reason = "STATUS_MONITOR_NO_MORE_DESCRIPTOR_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK: - reason = "STATUS_MONITOR_INVALID_DETAILED_TIMING_BLOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_MONITOR_INVALID_MANUFACTURE_DATE: - reason = "STATUS_MONITOR_INVALID_MANUFACTURE_DATE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER: - reason = "STATUS_GRAPHICS_NOT_EXCLUSIVE_MODE_OWNER"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER: - reason = "STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER: - reason = "STATUS_GRAPHICS_INVALID_DISPLAY_ADAPTER"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_WAS_RESET: - reason = "STATUS_GRAPHICS_ADAPTER_WAS_RESET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_DRIVER_MODEL: - reason = "STATUS_GRAPHICS_INVALID_DRIVER_MODEL"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_MODE_CHANGED: - reason = "STATUS_GRAPHICS_PRESENT_MODE_CHANGED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_OCCLUDED: - reason = "STATUS_GRAPHICS_PRESENT_OCCLUDED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_DENIED: - reason = "STATUS_GRAPHICS_PRESENT_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANNOTCOLORCONVERT: - reason = "STATUS_GRAPHICS_CANNOTCOLORCONVERT"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DRIVER_MISMATCH: - reason = "STATUS_GRAPHICS_DRIVER_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED: - reason = "STATUS_GRAPHICS_PRESENT_REDIRECTION_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PRESENT_UNOCCLUDED: - reason = "STATUS_GRAPHICS_PRESENT_UNOCCLUDED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE: - reason = "STATUS_GRAPHICS_WINDOWDC_NOT_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED: - reason = "STATUS_GRAPHICS_WINDOWLESS_PRESENT_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDEO_MEMORY: - reason = "STATUS_GRAPHICS_NO_VIDEO_MEMORY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_LOCK_MEMORY: - reason = "STATUS_GRAPHICS_CANT_LOCK_MEMORY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_BUSY: - reason = "STATUS_GRAPHICS_ALLOCATION_BUSY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOO_MANY_REFERENCES: - reason = "STATUS_GRAPHICS_TOO_MANY_REFERENCES"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_LATER: - reason = "STATUS_GRAPHICS_TRY_AGAIN_LATER"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TRY_AGAIN_NOW: - reason = "STATUS_GRAPHICS_TRY_AGAIN_NOW"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_INVALID: - reason = "STATUS_GRAPHICS_ALLOCATION_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE: - reason = "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNAVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED: - reason = "STATUS_GRAPHICS_UNSWIZZLING_APERTURE_UNSUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION: - reason = "STATUS_GRAPHICS_CANT_EVICT_PINNED_ALLOCATION"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE: - reason = "STATUS_GRAPHICS_INVALID_ALLOCATION_USAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION: - reason = "STATUS_GRAPHICS_CANT_RENDER_LOCKED_ALLOCATION"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CLOSED: - reason = "STATUS_GRAPHICS_ALLOCATION_CLOSED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE: - reason = "STATUS_GRAPHICS_INVALID_ALLOCATION_INSTANCE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE: - reason = "STATUS_GRAPHICS_INVALID_ALLOCATION_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE: - reason = "STATUS_GRAPHICS_WRONG_ALLOCATION_DEVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST: - reason = "STATUS_GRAPHICS_ALLOCATION_CONTENT_LOST"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE: - reason = "STATUS_GRAPHICS_GPU_EXCEPTION_ON_DEVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY: - reason = "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_VIDPN_TOPOLOGY_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_VIDPN_TOPOLOGY_CURRENTLY_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN: - reason = "STATUS_GRAPHICS_INVALID_VIDPN"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE: - reason = "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET: - reason = "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_VIDPN_MODALITY_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET: - reason = "STATUS_GRAPHICS_INVALID_VIDPN_SOURCEMODESET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET: - reason = "STATUS_GRAPHICS_INVALID_VIDPN_TARGETMODESET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_FREQUENCY: - reason = "STATUS_GRAPHICS_INVALID_FREQUENCY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_ACTIVE_REGION: - reason = "STATUS_GRAPHICS_INVALID_ACTIVE_REGION"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_TOTAL_REGION: - reason = "STATUS_GRAPHICS_INVALID_TOTAL_REGION"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE: - reason = "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_SOURCE_MODE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE: - reason = "STATUS_GRAPHICS_INVALID_VIDEO_PRESENT_TARGET_MODE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET: - reason = "STATUS_GRAPHICS_PINNED_MODE_MUST_REMAIN_IN_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY: - reason = "STATUS_GRAPHICS_PATH_ALREADY_IN_TOPOLOGY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET: - reason = "STATUS_GRAPHICS_MODE_ALREADY_IN_MODESET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET: - reason = "STATUS_GRAPHICS_INVALID_VIDEOPRESENTSOURCESET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET: - reason = "STATUS_GRAPHICS_INVALID_VIDEOPRESENTTARGETSET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET: - reason = "STATUS_GRAPHICS_SOURCE_ALREADY_IN_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ALREADY_IN_SET: - reason = "STATUS_GRAPHICS_TARGET_ALREADY_IN_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH: - reason = "STATUS_GRAPHICS_INVALID_VIDPN_PRESENT_PATH"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY: - reason = "STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET: - reason = "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGESET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE: - reason = "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET: - reason = "STATUS_GRAPHICS_FREQUENCYRANGE_NOT_IN_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET: - reason = "STATUS_GRAPHICS_FREQUENCYRANGE_ALREADY_IN_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_MODESET: - reason = "STATUS_GRAPHICS_STALE_MODESET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET: - reason = "STATUS_GRAPHICS_INVALID_MONITOR_SOURCEMODESET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE: - reason = "STATUS_GRAPHICS_INVALID_MONITOR_SOURCE_MODE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN: - reason = "STATUS_GRAPHICS_NO_RECOMMENDED_FUNCTIONAL_VIDPN"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE: - reason = "STATUS_GRAPHICS_MODE_ID_MUST_BE_UNIQUE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION: - reason = "STATUS_GRAPHICS_EMPTY_ADAPTER_MONITOR_MODE_SUPPORT_INTERSECTION"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES: - reason = "STATUS_GRAPHICS_VIDEO_PRESENT_TARGETS_LESS_THAN_SOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY: - reason = "STATUS_GRAPHICS_PATH_NOT_IN_TOPOLOGY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE: - reason = "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_SOURCE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET: - reason = "STATUS_GRAPHICS_ADAPTER_MUST_HAVE_AT_LEAST_ONE_TARGET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET: - reason = "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTORSET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR: - reason = "STATUS_GRAPHICS_INVALID_MONITORDESCRIPTOR"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET: - reason = "STATUS_GRAPHICS_MONITORDESCRIPTOR_NOT_IN_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET: - reason = "STATUS_GRAPHICS_MONITORDESCRIPTOR_ALREADY_IN_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE: - reason = "STATUS_GRAPHICS_MONITORDESCRIPTOR_ID_MUST_BE_UNIQUE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE: - reason = "STATUS_GRAPHICS_INVALID_VIDPN_TARGET_SUBSET_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_RESOURCES_NOT_RELATED: - reason = "STATUS_GRAPHICS_RESOURCES_NOT_RELATED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE: - reason = "STATUS_GRAPHICS_SOURCE_ID_MUST_BE_UNIQUE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE: - reason = "STATUS_GRAPHICS_TARGET_ID_MUST_BE_UNIQUE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET: - reason = "STATUS_GRAPHICS_NO_AVAILABLE_VIDPN_TARGET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER: - reason = "STATUS_GRAPHICS_MONITOR_COULD_NOT_BE_ASSOCIATED_WITH_ADAPTER"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_VIDPNMGR: - reason = "STATUS_GRAPHICS_NO_VIDPNMGR"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_ACTIVE_VIDPN: - reason = "STATUS_GRAPHICS_NO_ACTIVE_VIDPN"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY: - reason = "STATUS_GRAPHICS_STALE_VIDPN_TOPOLOGY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NOT_CONNECTED: - reason = "STATUS_GRAPHICS_MONITOR_NOT_CONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY: - reason = "STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE: - reason = "STATUS_GRAPHICS_INVALID_PRIMARYSURFACE_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE: - reason = "STATUS_GRAPHICS_INVALID_VISIBLEREGION_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_STRIDE: - reason = "STATUS_GRAPHICS_INVALID_STRIDE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELFORMAT: - reason = "STATUS_GRAPHICS_INVALID_PIXELFORMAT"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COLORBASIS: - reason = "STATUS_GRAPHICS_INVALID_COLORBASIS"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE: - reason = "STATUS_GRAPHICS_INVALID_PIXELVALUEACCESSMODE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY: - reason = "STATUS_GRAPHICS_TARGET_NOT_IN_TOPOLOGY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT: - reason = "STATUS_GRAPHICS_NO_DISPLAY_MODE_MANAGEMENT_SUPPORT"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE: - reason = "STATUS_GRAPHICS_VIDPN_SOURCE_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN: - reason = "STATUS_GRAPHICS_CANT_ACCESS_ACTIVE_VIDPN"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL: - reason = "STATUS_GRAPHICS_INVALID_PATH_IMPORTANCE_ORDINAL"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION: - reason = "STATUS_GRAPHICS_INVALID_PATH_CONTENT_GEOMETRY_TRANSFORMATION"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_PATH_CONTENT_GEOMETRY_TRANSFORMATION_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_GAMMA_RAMP: - reason = "STATUS_GRAPHICS_INVALID_GAMMA_RAMP"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_GAMMA_RAMP_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_MULTISAMPLING_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MODE_NOT_IN_MODESET: - reason = "STATUS_GRAPHICS_MODE_NOT_IN_MODESET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON: - reason = "STATUS_GRAPHICS_INVALID_VIDPN_TOPOLOGY_RECOMMENDATION_REASON"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE: - reason = "STATUS_GRAPHICS_INVALID_PATH_CONTENT_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE: - reason = "STATUS_GRAPHICS_INVALID_COPYPROTECTION_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS: - reason = "STATUS_GRAPHICS_UNASSIGNED_MODESET_ALREADY_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING: - reason = "STATUS_GRAPHICS_INVALID_SCANLINE_ORDERING"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED: - reason = "STATUS_GRAPHICS_TOPOLOGY_CHANGES_NOT_ALLOWED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS: - reason = "STATUS_GRAPHICS_NO_AVAILABLE_IMPORTANCE_ORDINALS"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT: - reason = "STATUS_GRAPHICS_INCOMPATIBLE_PRIVATE_FORMAT"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM: - reason = "STATUS_GRAPHICS_INVALID_MODE_PRUNING_ALGORITHM"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN: - reason = "STATUS_GRAPHICS_INVALID_MONITOR_CAPABILITY_ORIGIN"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT: - reason = "STATUS_GRAPHICS_INVALID_MONITOR_FREQUENCYRANGE_CONSTRAINT"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED: - reason = "STATUS_GRAPHICS_MAX_NUM_PATHS_REACHED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION: - reason = "STATUS_GRAPHICS_CANCEL_VIDPN_TOPOLOGY_AUGMENTATION"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_CLIENT_TYPE: - reason = "STATUS_GRAPHICS_INVALID_CLIENT_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET: - reason = "STATUS_GRAPHICS_CLIENTVIDPN_NOT_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED: - reason = "STATUS_GRAPHICS_SPECIFIED_CHILD_ALREADY_CONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_CHILD_DESCRIPTOR_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER: - reason = "STATUS_GRAPHICS_NOT_A_LINKED_ADAPTER"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED: - reason = "STATUS_GRAPHICS_LEADLINK_NOT_ENUMERATED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED: - reason = "STATUS_GRAPHICS_CHAINLINKS_NOT_ENUMERATED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY: - reason = "STATUS_GRAPHICS_ADAPTER_CHAIN_NOT_READY"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED: - reason = "STATUS_GRAPHICS_CHAINLINKS_NOT_STARTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON: - reason = "STATUS_GRAPHICS_CHAINLINKS_NOT_POWERED_ON"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE: - reason = "STATUS_GRAPHICS_INCONSISTENT_DEVICE_LINK_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER: - reason = "STATUS_GRAPHICS_NOT_POST_DEVICE_DRIVER"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED: - reason = "STATUS_GRAPHICS_ADAPTER_ACCESS_NOT_EXCLUDED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_OPM_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_COPP_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_COPP_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_UAB_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_UAB_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS: - reason = "STATUS_GRAPHICS_OPM_INVALID_ENCRYPTED_PARAMETERS"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST: - reason = "STATUS_GRAPHICS_OPM_NO_PROTECTED_OUTPUTS_EXIST"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INTERNAL_ERROR: - reason = "STATUS_GRAPHICS_OPM_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_HANDLE: - reason = "STATUS_GRAPHICS_OPM_INVALID_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH: - reason = "STATUS_GRAPHICS_PVP_INVALID_CERTIFICATE_LENGTH"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED: - reason = "STATUS_GRAPHICS_OPM_SPANNING_MODE_ENABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED: - reason = "STATUS_GRAPHICS_OPM_THEATER_MODE_ENABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PVP_HFS_FAILED: - reason = "STATUS_GRAPHICS_PVP_HFS_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_SRM: - reason = "STATUS_GRAPHICS_OPM_INVALID_SRM"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP: - reason = "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_HDCP"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP: - reason = "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_ACP"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA: - reason = "STATUS_GRAPHICS_OPM_OUTPUT_DOES_NOT_SUPPORT_CGMSA"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET: - reason = "STATUS_GRAPHICS_OPM_HDCP_SRM_NEVER_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH: - reason = "STATUS_GRAPHICS_OPM_RESOLUTION_TOO_HIGH"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE: - reason = "STATUS_GRAPHICS_OPM_ALL_HDCP_HARDWARE_ALREADY_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS: - reason = "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_NO_LONGER_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS: - reason = "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_COPP_SEMANTICS"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST: - reason = "STATUS_GRAPHICS_OPM_INVALID_INFORMATION_REQUEST"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR: - reason = "STATUS_GRAPHICS_OPM_DRIVER_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS: - reason = "STATUS_GRAPHICS_OPM_PROTECTED_OUTPUT_DOES_NOT_HAVE_OPM_SEMANTICS"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_OPM_SIGNALING_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST: - reason = "STATUS_GRAPHICS_OPM_INVALID_CONFIGURATION_REQUEST"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_I2C_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST: - reason = "STATUS_GRAPHICS_I2C_DEVICE_DOES_NOT_EXIST"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA: - reason = "STATUS_GRAPHICS_I2C_ERROR_TRANSMITTING_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA: - reason = "STATUS_GRAPHICS_I2C_ERROR_RECEIVING_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_DDCCI_VCP_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_DATA: - reason = "STATUS_GRAPHICS_DDCCI_INVALID_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE: - reason = "STATUS_GRAPHICS_DDCCI_MONITOR_RETURNED_INVALID_TIMING_STATUS_BYTE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING: - reason = "STATUS_GRAPHICS_DDCCI_INVALID_CAPABILITIES_STRING"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MCA_INTERNAL_ERROR: - reason = "STATUS_GRAPHICS_MCA_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND: - reason = "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_COMMAND"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH: - reason = "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_LENGTH"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM: - reason = "STATUS_GRAPHICS_DDCCI_INVALID_MESSAGE_CHECKSUM"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE: - reason = "STATUS_GRAPHICS_INVALID_PHYSICAL_MONITOR_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS: - reason = "STATUS_GRAPHICS_MONITOR_NO_LONGER_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED: - reason = "STATUS_GRAPHICS_ONLY_CONSOLE_SESSION_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME: - reason = "STATUS_GRAPHICS_NO_DISPLAY_DEVICE_CORRESPONDS_TO_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP: - reason = "STATUS_GRAPHICS_DISPLAY_DEVICE_NOT_ATTACHED_TO_DESKTOP"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED: - reason = "STATUS_GRAPHICS_MIRRORING_DEVICES_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INVALID_POINTER: - reason = "STATUS_GRAPHICS_INVALID_POINTER"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE: - reason = "STATUS_GRAPHICS_NO_MONITORS_CORRESPOND_TO_DISPLAY_DEVICE"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL: - reason = "STATUS_GRAPHICS_PARAMETER_ARRAY_TOO_SMALL"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_INTERNAL_ERROR: - reason = "STATUS_GRAPHICS_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS: - reason = "STATUS_GRAPHICS_SESSION_TYPE_CHANGE_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_LOCKED_VOLUME: - reason = "STATUS_FVE_LOCKED_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NOT_ENCRYPTED: - reason = "STATUS_FVE_NOT_ENCRYPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_BAD_INFORMATION: - reason = "STATUS_FVE_BAD_INFORMATION"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_TOO_SMALL: - reason = "STATUS_FVE_TOO_SMALL"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_FAILED_WRONG_FS: - reason = "STATUS_FVE_FAILED_WRONG_FS"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_BAD_PARTITION_SIZE: - reason = "STATUS_FVE_BAD_PARTITION_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_FS_NOT_EXTENDED: - reason = "STATUS_FVE_FS_NOT_EXTENDED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_FS_MOUNTED: - reason = "STATUS_FVE_FS_MOUNTED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NO_LICENSE: - reason = "STATUS_FVE_NO_LICENSE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_ACTION_NOT_ALLOWED: - reason = "STATUS_FVE_ACTION_NOT_ALLOWED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_BAD_DATA: - reason = "STATUS_FVE_BAD_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_NOT_BOUND: - reason = "STATUS_FVE_VOLUME_NOT_BOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NOT_DATA_VOLUME: - reason = "STATUS_FVE_NOT_DATA_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_CONV_READ_ERROR: - reason = "STATUS_FVE_CONV_READ_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_CONV_WRITE_ERROR: - reason = "STATUS_FVE_CONV_WRITE_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_OVERLAPPED_UPDATE: - reason = "STATUS_FVE_OVERLAPPED_UPDATE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_FAILED_SECTOR_SIZE: - reason = "STATUS_FVE_FAILED_SECTOR_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_FAILED_AUTHENTICATION: - reason = "STATUS_FVE_FAILED_AUTHENTICATION"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NOT_OS_VOLUME: - reason = "STATUS_FVE_NOT_OS_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NOT_FOUND: - reason = "STATUS_FVE_KEYFILE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_INVALID: - reason = "STATUS_FVE_KEYFILE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_KEYFILE_NO_VMK: - reason = "STATUS_FVE_KEYFILE_NO_VMK"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_TPM_DISABLED: - reason = "STATUS_FVE_TPM_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO: - reason = "STATUS_FVE_TPM_SRK_AUTH_NOT_ZERO"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_TPM_INVALID_PCR: - reason = "STATUS_FVE_TPM_INVALID_PCR"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_TPM_NO_VMK: - reason = "STATUS_FVE_TPM_NO_VMK"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_PIN_INVALID: - reason = "STATUS_FVE_PIN_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_APPLICATION: - reason = "STATUS_FVE_AUTH_INVALID_APPLICATION"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_AUTH_INVALID_CONFIG: - reason = "STATUS_FVE_AUTH_INVALID_CONFIG"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_DEBUGGER_ENABLED: - reason = "STATUS_FVE_DEBUGGER_ENABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_DRY_RUN_FAILED: - reason = "STATUS_FVE_DRY_RUN_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_BAD_METADATA_POINTER: - reason = "STATUS_FVE_BAD_METADATA_POINTER"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_OLD_METADATA_COPY: - reason = "STATUS_FVE_OLD_METADATA_COPY"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_REBOOT_REQUIRED: - reason = "STATUS_FVE_REBOOT_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_RAW_ACCESS: - reason = "STATUS_FVE_RAW_ACCESS"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_RAW_BLOCKED: - reason = "STATUS_FVE_RAW_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY: - reason = "STATUS_FVE_NO_AUTOUNLOCK_MASTER_KEY"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_MOR_FAILED: - reason = "STATUS_FVE_MOR_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NO_FEATURE_LICENSE: - reason = "STATUS_FVE_NO_FEATURE_LICENSE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED: - reason = "STATUS_FVE_POLICY_USER_DISABLE_RDV_NOT_ALLOWED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_CONV_RECOVERY_FAILED: - reason = "STATUS_FVE_CONV_RECOVERY_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG: - reason = "STATUS_FVE_VIRTUALIZED_SPACE_TOO_BIG"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_INVALID_DATUM_TYPE: - reason = "STATUS_FVE_INVALID_DATUM_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_TOO_SMALL: - reason = "STATUS_FVE_VOLUME_TOO_SMALL"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_ENH_PIN_INVALID: - reason = "STATUS_FVE_ENH_PIN_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE: - reason = "STATUS_FVE_FULL_ENCRYPTION_NOT_ALLOWED_ON_TP_STORAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE: - reason = "STATUS_FVE_WIPE_NOT_ALLOWED_ON_TP_STORAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK: - reason = "STATUS_FVE_NOT_ALLOWED_ON_CSV_STACK"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_ON_CLUSTER: - reason = "STATUS_FVE_NOT_ALLOWED_ON_CLUSTER"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING: - reason = "STATUS_FVE_NOT_ALLOWED_TO_UPGRADE_WHILE_CONVERTING"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE: - reason = "STATUS_FVE_WIPE_CANCEL_NOT_APPLICABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_EDRIVE_DRY_RUN_FAILED: - reason = "STATUS_FVE_EDRIVE_DRY_RUN_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_DISABLED: - reason = "STATUS_FVE_SECUREBOOT_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_SECUREBOOT_CONFIG_CHANGE: - reason = "STATUS_FVE_SECUREBOOT_CONFIG_CHANGE"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_DEVICE_LOCKEDOUT: - reason = "STATUS_FVE_DEVICE_LOCKEDOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT: - reason = "STATUS_FVE_VOLUME_EXTEND_PREVENTS_EOW_DECRYPT"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_NOT_DE_VOLUME: - reason = "STATUS_FVE_NOT_DE_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_DISABLED: - reason = "STATUS_FVE_PROTECTION_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED: - reason = "STATUS_FVE_PROTECTION_CANNOT_BE_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOT_FOUND: - reason = "STATUS_FWP_CALLOUT_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_CONDITION_NOT_FOUND: - reason = "STATUS_FWP_CONDITION_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_FILTER_NOT_FOUND: - reason = "STATUS_FWP_FILTER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_LAYER_NOT_FOUND: - reason = "STATUS_FWP_LAYER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_NOT_FOUND: - reason = "STATUS_FWP_PROVIDER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND: - reason = "STATUS_FWP_PROVIDER_CONTEXT_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_SUBLAYER_NOT_FOUND: - reason = "STATUS_FWP_SUBLAYER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_NOT_FOUND: - reason = "STATUS_FWP_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_ALREADY_EXISTS: - reason = "STATUS_FWP_ALREADY_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_IN_USE: - reason = "STATUS_FWP_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS: - reason = "STATUS_FWP_DYNAMIC_SESSION_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_WRONG_SESSION: - reason = "STATUS_FWP_WRONG_SESSION"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_NO_TXN_IN_PROGRESS: - reason = "STATUS_FWP_NO_TXN_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_TXN_IN_PROGRESS: - reason = "STATUS_FWP_TXN_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_TXN_ABORTED: - reason = "STATUS_FWP_TXN_ABORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_SESSION_ABORTED: - reason = "STATUS_FWP_SESSION_ABORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_TXN: - reason = "STATUS_FWP_INCOMPATIBLE_TXN"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_TIMEOUT: - reason = "STATUS_FWP_TIMEOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_NET_EVENTS_DISABLED: - reason = "STATUS_FWP_NET_EVENTS_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_LAYER: - reason = "STATUS_FWP_INCOMPATIBLE_LAYER"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_KM_CLIENTS_ONLY: - reason = "STATUS_FWP_KM_CLIENTS_ONLY"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_LIFETIME_MISMATCH: - reason = "STATUS_FWP_LIFETIME_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_BUILTIN_OBJECT: - reason = "STATUS_FWP_BUILTIN_OBJECT"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_CALLOUTS: - reason = "STATUS_FWP_TOO_MANY_CALLOUTS"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_NOTIFICATION_DROPPED: - reason = "STATUS_FWP_NOTIFICATION_DROPPED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_TRAFFIC_MISMATCH: - reason = "STATUS_FWP_TRAFFIC_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_SA_STATE: - reason = "STATUS_FWP_INCOMPATIBLE_SA_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_NULL_POINTER: - reason = "STATUS_FWP_NULL_POINTER"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ENUMERATOR: - reason = "STATUS_FWP_INVALID_ENUMERATOR"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_FLAGS: - reason = "STATUS_FWP_INVALID_FLAGS"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_NET_MASK: - reason = "STATUS_FWP_INVALID_NET_MASK"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_RANGE: - reason = "STATUS_FWP_INVALID_RANGE"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_INTERVAL: - reason = "STATUS_FWP_INVALID_INTERVAL"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_ZERO_LENGTH_ARRAY: - reason = "STATUS_FWP_ZERO_LENGTH_ARRAY"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_NULL_DISPLAY_NAME: - reason = "STATUS_FWP_NULL_DISPLAY_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_ACTION_TYPE: - reason = "STATUS_FWP_INVALID_ACTION_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_WEIGHT: - reason = "STATUS_FWP_INVALID_WEIGHT"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_MATCH_TYPE_MISMATCH: - reason = "STATUS_FWP_MATCH_TYPE_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_TYPE_MISMATCH: - reason = "STATUS_FWP_TYPE_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_OUT_OF_BOUNDS: - reason = "STATUS_FWP_OUT_OF_BOUNDS"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_RESERVED: - reason = "STATUS_FWP_RESERVED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_CONDITION: - reason = "STATUS_FWP_DUPLICATE_CONDITION"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_KEYMOD: - reason = "STATUS_FWP_DUPLICATE_KEYMOD"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER: - reason = "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_LAYER"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER: - reason = "STATUS_FWP_ACTION_INCOMPATIBLE_WITH_SUBLAYER"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER: - reason = "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_LAYER"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT: - reason = "STATUS_FWP_CONTEXT_INCOMPATIBLE_WITH_CALLOUT"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_AUTH_METHOD: - reason = "STATUS_FWP_INCOMPATIBLE_AUTH_METHOD"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_DH_GROUP: - reason = "STATUS_FWP_INCOMPATIBLE_DH_GROUP"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_EM_NOT_SUPPORTED: - reason = "STATUS_FWP_EM_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_NEVER_MATCH: - reason = "STATUS_FWP_NEVER_MATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_PROVIDER_CONTEXT_MISMATCH: - reason = "STATUS_FWP_PROVIDER_CONTEXT_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_PARAMETER: - reason = "STATUS_FWP_INVALID_PARAMETER"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_TOO_MANY_SUBLAYERS: - reason = "STATUS_FWP_TOO_MANY_SUBLAYERS"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_CALLOUT_NOTIFICATION_FAILED: - reason = "STATUS_FWP_CALLOUT_NOTIFICATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_AUTH_TRANSFORM: - reason = "STATUS_FWP_INVALID_AUTH_TRANSFORM"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_CIPHER_TRANSFORM: - reason = "STATUS_FWP_INVALID_CIPHER_TRANSFORM"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM: - reason = "STATUS_FWP_INCOMPATIBLE_CIPHER_TRANSFORM"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TRANSFORM_COMBINATION: - reason = "STATUS_FWP_INVALID_TRANSFORM_COMBINATION"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_DUPLICATE_AUTH_METHOD: - reason = "STATUS_FWP_DUPLICATE_AUTH_METHOD"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_TUNNEL_ENDPOINT: - reason = "STATUS_FWP_INVALID_TUNNEL_ENDPOINT"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_L2_DRIVER_NOT_READY: - reason = "STATUS_FWP_L2_DRIVER_NOT_READY"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED: - reason = "STATUS_FWP_KEY_DICTATOR_ALREADY_REGISTERED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL: - reason = "STATUS_FWP_KEY_DICTATION_INVALID_KEYING_MATERIAL"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_CONNECTIONS_DISABLED: - reason = "STATUS_FWP_CONNECTIONS_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INVALID_DNS_NAME: - reason = "STATUS_FWP_INVALID_DNS_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_STILL_ON: - reason = "STATUS_FWP_STILL_ON"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_IKEEXT_NOT_RUNNING: - reason = "STATUS_FWP_IKEEXT_NOT_RUNNING"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_TCPIP_NOT_READY: - reason = "STATUS_FWP_TCPIP_NOT_READY"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_CLOSING: - reason = "STATUS_FWP_INJECT_HANDLE_CLOSING"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_INJECT_HANDLE_STALE: - reason = "STATUS_FWP_INJECT_HANDLE_STALE"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_CANNOT_PEND: - reason = "STATUS_FWP_CANNOT_PEND"; - break; - case MD_NTSTATUS_WIN_STATUS_FWP_DROP_NOICMP: - reason = "STATUS_FWP_DROP_NOICMP"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_CLOSING: - reason = "STATUS_NDIS_CLOSING"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_BAD_VERSION: - reason = "STATUS_NDIS_BAD_VERSION"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_BAD_CHARACTERISTICS: - reason = "STATUS_NDIS_BAD_CHARACTERISTICS"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_FOUND: - reason = "STATUS_NDIS_ADAPTER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_OPEN_FAILED: - reason = "STATUS_NDIS_OPEN_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_DEVICE_FAILED: - reason = "STATUS_NDIS_DEVICE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_FULL: - reason = "STATUS_NDIS_MULTICAST_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_EXISTS: - reason = "STATUS_NDIS_MULTICAST_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_MULTICAST_NOT_FOUND: - reason = "STATUS_NDIS_MULTICAST_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_REQUEST_ABORTED: - reason = "STATUS_NDIS_REQUEST_ABORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_RESET_IN_PROGRESS: - reason = "STATUS_NDIS_RESET_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PACKET: - reason = "STATUS_NDIS_INVALID_PACKET"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DEVICE_REQUEST: - reason = "STATUS_NDIS_INVALID_DEVICE_REQUEST"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_NOT_READY: - reason = "STATUS_NDIS_ADAPTER_NOT_READY"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_LENGTH: - reason = "STATUS_NDIS_INVALID_LENGTH"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_DATA: - reason = "STATUS_NDIS_INVALID_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_BUFFER_TOO_SHORT: - reason = "STATUS_NDIS_BUFFER_TOO_SHORT"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_OID: - reason = "STATUS_NDIS_INVALID_OID"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_ADAPTER_REMOVED: - reason = "STATUS_NDIS_ADAPTER_REMOVED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_MEDIA: - reason = "STATUS_NDIS_UNSUPPORTED_MEDIA"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_GROUP_ADDRESS_IN_USE: - reason = "STATUS_NDIS_GROUP_ADDRESS_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_FILE_NOT_FOUND: - reason = "STATUS_NDIS_FILE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_ERROR_READING_FILE: - reason = "STATUS_NDIS_ERROR_READING_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_ALREADY_MAPPED: - reason = "STATUS_NDIS_ALREADY_MAPPED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_RESOURCE_CONFLICT: - reason = "STATUS_NDIS_RESOURCE_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_MEDIA_DISCONNECTED: - reason = "STATUS_NDIS_MEDIA_DISCONNECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_ADDRESS: - reason = "STATUS_NDIS_INVALID_ADDRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_PAUSED: - reason = "STATUS_NDIS_PAUSED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_INTERFACE_NOT_FOUND: - reason = "STATUS_NDIS_INTERFACE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_UNSUPPORTED_REVISION: - reason = "STATUS_NDIS_UNSUPPORTED_REVISION"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT: - reason = "STATUS_NDIS_INVALID_PORT"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_INVALID_PORT_STATE: - reason = "STATUS_NDIS_INVALID_PORT_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_LOW_POWER_STATE: - reason = "STATUS_NDIS_LOW_POWER_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_REINIT_REQUIRED: - reason = "STATUS_NDIS_REINIT_REQUIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_NOT_SUPPORTED: - reason = "STATUS_NDIS_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_POLICY: - reason = "STATUS_NDIS_OFFLOAD_POLICY"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED: - reason = "STATUS_NDIS_OFFLOAD_CONNECTION_REJECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_OFFLOAD_PATH_REJECTED: - reason = "STATUS_NDIS_OFFLOAD_PATH_REJECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED: - reason = "STATUS_NDIS_DOT11_AUTO_CONFIG_ENABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_MEDIA_IN_USE: - reason = "STATUS_NDIS_DOT11_MEDIA_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_DOT11_POWER_STATE_INVALID: - reason = "STATUS_NDIS_DOT11_POWER_STATE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL: - reason = "STATUS_NDIS_PM_WOL_PATTERN_LIST_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL: - reason = "STATUS_NDIS_PM_PROTOCOL_OFFLOAD_LIST_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_ERROR_MASK: - reason = "STATUS_TPM_ERROR_MASK"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_AUTHFAIL: - reason = "STATUS_TPM_AUTHFAIL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BADINDEX: - reason = "STATUS_TPM_BADINDEX"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAMETER: - reason = "STATUS_TPM_BAD_PARAMETER"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAILURE: - reason = "STATUS_TPM_AUDITFAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_CLEAR_DISABLED: - reason = "STATUS_TPM_CLEAR_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DEACTIVATED: - reason = "STATUS_TPM_DEACTIVATED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DISABLED: - reason = "STATUS_TPM_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DISABLED_CMD: - reason = "STATUS_TPM_DISABLED_CMD"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_FAIL: - reason = "STATUS_TPM_FAIL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_ORDINAL: - reason = "STATUS_TPM_BAD_ORDINAL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INSTALL_DISABLED: - reason = "STATUS_TPM_INSTALL_DISABLED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYHANDLE: - reason = "STATUS_TPM_INVALID_KEYHANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_KEYNOTFOUND: - reason = "STATUS_TPM_KEYNOTFOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_ENC: - reason = "STATUS_TPM_INAPPROPRIATE_ENC"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_MIGRATEFAIL: - reason = "STATUS_TPM_MIGRATEFAIL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_PCR_INFO: - reason = "STATUS_TPM_INVALID_PCR_INFO"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOSPACE: - reason = "STATUS_TPM_NOSPACE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOSRK: - reason = "STATUS_TPM_NOSRK"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOTSEALED_BLOB: - reason = "STATUS_TPM_NOTSEALED_BLOB"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_OWNER_SET: - reason = "STATUS_TPM_OWNER_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_RESOURCES: - reason = "STATUS_TPM_RESOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_SHORTRANDOM: - reason = "STATUS_TPM_SHORTRANDOM"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_SIZE: - reason = "STATUS_TPM_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_WRONGPCRVAL: - reason = "STATUS_TPM_WRONGPCRVAL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_PARAM_SIZE: - reason = "STATUS_TPM_BAD_PARAM_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_SHA_THREAD: - reason = "STATUS_TPM_SHA_THREAD"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_SHA_ERROR: - reason = "STATUS_TPM_SHA_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_FAILEDSELFTEST: - reason = "STATUS_TPM_FAILEDSELFTEST"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_AUTH2FAIL: - reason = "STATUS_TPM_AUTH2FAIL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BADTAG: - reason = "STATUS_TPM_BADTAG"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_IOERROR: - reason = "STATUS_TPM_IOERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_ENCRYPT_ERROR: - reason = "STATUS_TPM_ENCRYPT_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DECRYPT_ERROR: - reason = "STATUS_TPM_DECRYPT_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_AUTHHANDLE: - reason = "STATUS_TPM_INVALID_AUTHHANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NO_ENDORSEMENT: - reason = "STATUS_TPM_NO_ENDORSEMENT"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_KEYUSAGE: - reason = "STATUS_TPM_INVALID_KEYUSAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_WRONG_ENTITYTYPE: - reason = "STATUS_TPM_WRONG_ENTITYTYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_POSTINIT: - reason = "STATUS_TPM_INVALID_POSTINIT"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INAPPROPRIATE_SIG: - reason = "STATUS_TPM_INAPPROPRIATE_SIG"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_KEY_PROPERTY: - reason = "STATUS_TPM_BAD_KEY_PROPERTY"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_MIGRATION: - reason = "STATUS_TPM_BAD_MIGRATION"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_SCHEME: - reason = "STATUS_TPM_BAD_SCHEME"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_DATASIZE: - reason = "STATUS_TPM_BAD_DATASIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_MODE: - reason = "STATUS_TPM_BAD_MODE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_PRESENCE: - reason = "STATUS_TPM_BAD_PRESENCE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_VERSION: - reason = "STATUS_TPM_BAD_VERSION"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NO_WRAP_TRANSPORT: - reason = "STATUS_TPM_NO_WRAP_TRANSPORT"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_UNSUCCESSFUL: - reason = "STATUS_TPM_AUDITFAIL_UNSUCCESSFUL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_AUDITFAIL_SUCCESSFUL: - reason = "STATUS_TPM_AUDITFAIL_SUCCESSFUL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOTRESETABLE: - reason = "STATUS_TPM_NOTRESETABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOTLOCAL: - reason = "STATUS_TPM_NOTLOCAL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_TYPE: - reason = "STATUS_TPM_BAD_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_RESOURCE: - reason = "STATUS_TPM_INVALID_RESOURCE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOTFIPS: - reason = "STATUS_TPM_NOTFIPS"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_FAMILY: - reason = "STATUS_TPM_INVALID_FAMILY"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NO_NV_PERMISSION: - reason = "STATUS_TPM_NO_NV_PERMISSION"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_REQUIRES_SIGN: - reason = "STATUS_TPM_REQUIRES_SIGN"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_KEY_NOTSUPPORTED: - reason = "STATUS_TPM_KEY_NOTSUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_AUTH_CONFLICT: - reason = "STATUS_TPM_AUTH_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_AREA_LOCKED: - reason = "STATUS_TPM_AREA_LOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_LOCALITY: - reason = "STATUS_TPM_BAD_LOCALITY"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_READ_ONLY: - reason = "STATUS_TPM_READ_ONLY"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_PER_NOWRITE: - reason = "STATUS_TPM_PER_NOWRITE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_FAMILYCOUNT: - reason = "STATUS_TPM_FAMILYCOUNT"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_WRITE_LOCKED: - reason = "STATUS_TPM_WRITE_LOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_ATTRIBUTES: - reason = "STATUS_TPM_BAD_ATTRIBUTES"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_STRUCTURE: - reason = "STATUS_TPM_INVALID_STRUCTURE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_KEY_OWNER_CONTROL: - reason = "STATUS_TPM_KEY_OWNER_CONTROL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_COUNTER: - reason = "STATUS_TPM_BAD_COUNTER"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOT_FULLWRITE: - reason = "STATUS_TPM_NOT_FULLWRITE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_CONTEXT_GAP: - reason = "STATUS_TPM_CONTEXT_GAP"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_MAXNVWRITES: - reason = "STATUS_TPM_MAXNVWRITES"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOOPERATOR: - reason = "STATUS_TPM_NOOPERATOR"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_RESOURCEMISSING: - reason = "STATUS_TPM_RESOURCEMISSING"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_LOCK: - reason = "STATUS_TPM_DELEGATE_LOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_FAMILY: - reason = "STATUS_TPM_DELEGATE_FAMILY"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DELEGATE_ADMIN: - reason = "STATUS_TPM_DELEGATE_ADMIN"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_TRANSPORT_NOTEXCLUSIVE: - reason = "STATUS_TPM_TRANSPORT_NOTEXCLUSIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_OWNER_CONTROL: - reason = "STATUS_TPM_OWNER_CONTROL"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DAA_RESOURCES: - reason = "STATUS_TPM_DAA_RESOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA0: - reason = "STATUS_TPM_DAA_INPUT_DATA0"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DAA_INPUT_DATA1: - reason = "STATUS_TPM_DAA_INPUT_DATA1"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_SETTINGS: - reason = "STATUS_TPM_DAA_ISSUER_SETTINGS"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DAA_TPM_SETTINGS: - reason = "STATUS_TPM_DAA_TPM_SETTINGS"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DAA_STAGE: - reason = "STATUS_TPM_DAA_STAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DAA_ISSUER_VALIDITY: - reason = "STATUS_TPM_DAA_ISSUER_VALIDITY"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DAA_WRONG_W: - reason = "STATUS_TPM_DAA_WRONG_W"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_HANDLE: - reason = "STATUS_TPM_BAD_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_DELEGATE: - reason = "STATUS_TPM_BAD_DELEGATE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BADCONTEXT: - reason = "STATUS_TPM_BADCONTEXT"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_TOOMANYCONTEXTS: - reason = "STATUS_TPM_TOOMANYCONTEXTS"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_MA_TICKET_SIGNATURE: - reason = "STATUS_TPM_MA_TICKET_SIGNATURE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_MA_DESTINATION: - reason = "STATUS_TPM_MA_DESTINATION"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_MA_SOURCE: - reason = "STATUS_TPM_MA_SOURCE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_MA_AUTHORITY: - reason = "STATUS_TPM_MA_AUTHORITY"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_PERMANENTEK: - reason = "STATUS_TPM_PERMANENTEK"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_BAD_SIGNATURE: - reason = "STATUS_TPM_BAD_SIGNATURE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOCONTEXTSPACE: - reason = "STATUS_TPM_NOCONTEXTSPACE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_BLOCKED: - reason = "STATUS_TPM_COMMAND_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INVALID_HANDLE: - reason = "STATUS_TPM_INVALID_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DUPLICATE_VHANDLE: - reason = "STATUS_TPM_DUPLICATE_VHANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_BLOCKED: - reason = "STATUS_TPM_EMBEDDED_COMMAND_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED: - reason = "STATUS_TPM_EMBEDDED_COMMAND_UNSUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_RETRY: - reason = "STATUS_TPM_RETRY"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NEEDS_SELFTEST: - reason = "STATUS_TPM_NEEDS_SELFTEST"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DOING_SELFTEST: - reason = "STATUS_TPM_DOING_SELFTEST"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_DEFEND_LOCK_RUNNING: - reason = "STATUS_TPM_DEFEND_LOCK_RUNNING"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_COMMAND_CANCELED: - reason = "STATUS_TPM_COMMAND_CANCELED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_TOO_MANY_CONTEXTS: - reason = "STATUS_TPM_TOO_MANY_CONTEXTS"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_NOT_FOUND: - reason = "STATUS_TPM_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_ACCESS_DENIED: - reason = "STATUS_TPM_ACCESS_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_INSUFFICIENT_BUFFER: - reason = "STATUS_TPM_INSUFFICIENT_BUFFER"; - break; - case MD_NTSTATUS_WIN_STATUS_TPM_PPI_FUNCTION_UNSUPPORTED: - reason = "STATUS_TPM_PPI_FUNCTION_UNSUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_ERROR_MASK: - reason = "STATUS_PCP_ERROR_MASK"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_READY: - reason = "STATUS_PCP_DEVICE_NOT_READY"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_INVALID_HANDLE: - reason = "STATUS_PCP_INVALID_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_INVALID_PARAMETER: - reason = "STATUS_PCP_INVALID_PARAMETER"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_FLAG_NOT_SUPPORTED: - reason = "STATUS_PCP_FLAG_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_NOT_SUPPORTED: - reason = "STATUS_PCP_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_BUFFER_TOO_SMALL: - reason = "STATUS_PCP_BUFFER_TOO_SMALL"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_INTERNAL_ERROR: - reason = "STATUS_PCP_INTERNAL_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_FAILED: - reason = "STATUS_PCP_AUTHENTICATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_AUTHENTICATION_IGNORED: - reason = "STATUS_PCP_AUTHENTICATION_IGNORED"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_POLICY_NOT_FOUND: - reason = "STATUS_PCP_POLICY_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_PROFILE_NOT_FOUND: - reason = "STATUS_PCP_PROFILE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_VALIDATION_FAILED: - reason = "STATUS_PCP_VALIDATION_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_PCP_DEVICE_NOT_FOUND: - reason = "STATUS_PCP_DEVICE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_CODE: - reason = "STATUS_HV_INVALID_HYPERCALL_CODE"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_HYPERCALL_INPUT: - reason = "STATUS_HV_INVALID_HYPERCALL_INPUT"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_ALIGNMENT: - reason = "STATUS_HV_INVALID_ALIGNMENT"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARAMETER: - reason = "STATUS_HV_INVALID_PARAMETER"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_ACCESS_DENIED: - reason = "STATUS_HV_ACCESS_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_STATE: - reason = "STATUS_HV_INVALID_PARTITION_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_OPERATION_DENIED: - reason = "STATUS_HV_OPERATION_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_UNKNOWN_PROPERTY: - reason = "STATUS_HV_UNKNOWN_PROPERTY"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE: - reason = "STATUS_HV_PROPERTY_VALUE_OUT_OF_RANGE"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_MEMORY: - reason = "STATUS_HV_INSUFFICIENT_MEMORY"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_PARTITION_TOO_DEEP: - reason = "STATUS_HV_PARTITION_TOO_DEEP"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PARTITION_ID: - reason = "STATUS_HV_INVALID_PARTITION_ID"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_VP_INDEX: - reason = "STATUS_HV_INVALID_VP_INDEX"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PORT_ID: - reason = "STATUS_HV_INVALID_PORT_ID"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_CONNECTION_ID: - reason = "STATUS_HV_INVALID_CONNECTION_ID"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFERS: - reason = "STATUS_HV_INSUFFICIENT_BUFFERS"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_NOT_ACKNOWLEDGED: - reason = "STATUS_HV_NOT_ACKNOWLEDGED"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_ACKNOWLEDGED: - reason = "STATUS_HV_ACKNOWLEDGED"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_SAVE_RESTORE_STATE: - reason = "STATUS_HV_INVALID_SAVE_RESTORE_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_SYNIC_STATE: - reason = "STATUS_HV_INVALID_SYNIC_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_OBJECT_IN_USE: - reason = "STATUS_HV_OBJECT_IN_USE"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO: - reason = "STATUS_HV_INVALID_PROXIMITY_DOMAIN_INFO"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_NO_DATA: - reason = "STATUS_HV_NO_DATA"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INACTIVE: - reason = "STATUS_HV_INACTIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_NO_RESOURCES: - reason = "STATUS_HV_NO_RESOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_FEATURE_UNAVAILABLE: - reason = "STATUS_HV_FEATURE_UNAVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_BUFFER: - reason = "STATUS_HV_INSUFFICIENT_BUFFER"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS: - reason = "STATUS_HV_INSUFFICIENT_DEVICE_DOMAINS"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_INVALID_LP_INDEX: - reason = "STATUS_HV_INVALID_LP_INDEX"; - break; - case MD_NTSTATUS_WIN_STATUS_HV_NOT_PRESENT: - reason = "STATUS_HV_NOT_PRESENT"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_BAD_SPI: - reason = "STATUS_IPSEC_BAD_SPI"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_SA_LIFETIME_EXPIRED: - reason = "STATUS_IPSEC_SA_LIFETIME_EXPIRED"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_WRONG_SA: - reason = "STATUS_IPSEC_WRONG_SA"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_REPLAY_CHECK_FAILED: - reason = "STATUS_IPSEC_REPLAY_CHECK_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_INVALID_PACKET: - reason = "STATUS_IPSEC_INVALID_PACKET"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_INTEGRITY_CHECK_FAILED: - reason = "STATUS_IPSEC_INTEGRITY_CHECK_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_CLEAR_TEXT_DROP: - reason = "STATUS_IPSEC_CLEAR_TEXT_DROP"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_AUTH_FIREWALL_DROP: - reason = "STATUS_IPSEC_AUTH_FIREWALL_DROP"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_THROTTLE_DROP: - reason = "STATUS_IPSEC_THROTTLE_DROP"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_BLOCK: - reason = "STATUS_IPSEC_DOSP_BLOCK"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_RECEIVED_MULTICAST: - reason = "STATUS_IPSEC_DOSP_RECEIVED_MULTICAST"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_INVALID_PACKET: - reason = "STATUS_IPSEC_DOSP_INVALID_PACKET"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED: - reason = "STATUS_IPSEC_DOSP_STATE_LOOKUP_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_ENTRIES: - reason = "STATUS_IPSEC_DOSP_MAX_ENTRIES"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED: - reason = "STATUS_IPSEC_DOSP_KEYMOD_NOT_ALLOWED"; - break; - case MD_NTSTATUS_WIN_STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES: - reason = "STATUS_IPSEC_DOSP_MAX_PER_IP_RATELIMIT_QUEUES"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_DUPLICATE_HANDLER: - reason = "STATUS_VID_DUPLICATE_HANDLER"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_TOO_MANY_HANDLERS: - reason = "STATUS_VID_TOO_MANY_HANDLERS"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_QUEUE_FULL: - reason = "STATUS_VID_QUEUE_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_HANDLER_NOT_PRESENT: - reason = "STATUS_VID_HANDLER_NOT_PRESENT"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_INVALID_OBJECT_NAME: - reason = "STATUS_VID_INVALID_OBJECT_NAME"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_TOO_LONG: - reason = "STATUS_VID_PARTITION_NAME_TOO_LONG"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG: - reason = "STATUS_VID_MESSAGE_QUEUE_NAME_TOO_LONG"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_PARTITION_ALREADY_EXISTS: - reason = "STATUS_VID_PARTITION_ALREADY_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_PARTITION_DOES_NOT_EXIST: - reason = "STATUS_VID_PARTITION_DOES_NOT_EXIST"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_PARTITION_NAME_NOT_FOUND: - reason = "STATUS_VID_PARTITION_NAME_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS: - reason = "STATUS_VID_MESSAGE_QUEUE_ALREADY_EXISTS"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT: - reason = "STATUS_VID_EXCEEDED_MBP_ENTRY_MAP_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MB_STILL_REFERENCED: - reason = "STATUS_VID_MB_STILL_REFERENCED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED: - reason = "STATUS_VID_CHILD_GPA_PAGE_SET_CORRUPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_SETTINGS: - reason = "STATUS_VID_INVALID_NUMA_SETTINGS"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_INVALID_NUMA_NODE_INDEX: - reason = "STATUS_VID_INVALID_NUMA_NODE_INDEX"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED: - reason = "STATUS_VID_NOTIFICATION_QUEUE_ALREADY_ASSOCIATED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE: - reason = "STATUS_VID_INVALID_MEMORY_BLOCK_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_PAGE_RANGE_OVERFLOW: - reason = "STATUS_VID_PAGE_RANGE_OVERFLOW"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE: - reason = "STATUS_VID_INVALID_MESSAGE_QUEUE_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_INVALID_GPA_RANGE_HANDLE: - reason = "STATUS_VID_INVALID_GPA_RANGE_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE: - reason = "STATUS_VID_NO_MEMORY_BLOCK_NOTIFICATION_QUEUE"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED: - reason = "STATUS_VID_MEMORY_BLOCK_LOCK_COUNT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_INVALID_PPM_HANDLE: - reason = "STATUS_VID_INVALID_PPM_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MBPS_ARE_LOCKED: - reason = "STATUS_VID_MBPS_ARE_LOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MESSAGE_QUEUE_CLOSED: - reason = "STATUS_VID_MESSAGE_QUEUE_CLOSED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED: - reason = "STATUS_VID_VIRTUAL_PROCESSOR_LIMIT_EXCEEDED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_STOP_PENDING: - reason = "STATUS_VID_STOP_PENDING"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_INVALID_PROCESSOR_STATE: - reason = "STATUS_VID_INVALID_PROCESSOR_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT: - reason = "STATUS_VID_EXCEEDED_KM_CONTEXT_COUNT_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED: - reason = "STATUS_VID_KM_INTERFACE_ALREADY_INITIALIZED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET: - reason = "STATUS_VID_MB_PROPERTY_ALREADY_SET_RESET"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MMIO_RANGE_DESTROYED: - reason = "STATUS_VID_MMIO_RANGE_DESTROYED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_INVALID_CHILD_GPA_PAGE_SET: - reason = "STATUS_VID_INVALID_CHILD_GPA_PAGE_SET"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED: - reason = "STATUS_VID_RESERVE_PAGE_SET_IS_BEING_USED"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL: - reason = "STATUS_VID_RESERVE_PAGE_SET_TOO_SMALL"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE: - reason = "STATUS_VID_MBP_ALREADY_LOCKED_USING_RESERVED_PAGE"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT: - reason = "STATUS_VID_MBP_COUNT_EXCEEDED_LIMIT"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_CORRUPT: - reason = "STATUS_VID_SAVED_STATE_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM: - reason = "STATUS_VID_SAVED_STATE_UNRECOGNIZED_ITEM"; - break; - case MD_NTSTATUS_WIN_STATUS_VID_SAVED_STATE_INCOMPATIBLE: - reason = "STATUS_VID_SAVED_STATE_INCOMPATIBLE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DATABASE_FULL: - reason = "STATUS_VOLMGR_DATABASE_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED: - reason = "STATUS_VOLMGR_DISK_CONFIGURATION_CORRUPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC: - reason = "STATUS_VOLMGR_DISK_CONFIGURATION_NOT_IN_SYNC"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED: - reason = "STATUS_VOLMGR_PACK_CONFIG_UPDATE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME: - reason = "STATUS_VOLMGR_DISK_CONTAINS_NON_SIMPLE_VOLUME"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DUPLICATE: - reason = "STATUS_VOLMGR_DISK_DUPLICATE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_DYNAMIC: - reason = "STATUS_VOLMGR_DISK_DYNAMIC"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_ID_INVALID: - reason = "STATUS_VOLMGR_DISK_ID_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_INVALID: - reason = "STATUS_VOLMGR_DISK_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAST_VOTER: - reason = "STATUS_VOLMGR_DISK_LAST_VOTER"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_INVALID: - reason = "STATUS_VOLMGR_DISK_LAYOUT_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS: - reason = "STATUS_VOLMGR_DISK_LAYOUT_NON_BASIC_BETWEEN_BASIC_PARTITIONS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED: - reason = "STATUS_VOLMGR_DISK_LAYOUT_NOT_CYLINDER_ALIGNED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL: - reason = "STATUS_VOLMGR_DISK_LAYOUT_PARTITIONS_TOO_SMALL"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS: - reason = "STATUS_VOLMGR_DISK_LAYOUT_PRIMARY_BETWEEN_LOGICAL_PARTITIONS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS: - reason = "STATUS_VOLMGR_DISK_LAYOUT_TOO_MANY_PARTITIONS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_MISSING: - reason = "STATUS_VOLMGR_DISK_MISSING"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_EMPTY: - reason = "STATUS_VOLMGR_DISK_NOT_EMPTY"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE: - reason = "STATUS_VOLMGR_DISK_NOT_ENOUGH_SPACE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_REVECTORING_FAILED: - reason = "STATUS_VOLMGR_DISK_REVECTORING_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID: - reason = "STATUS_VOLMGR_DISK_SECTOR_SIZE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_SET_NOT_CONTAINED: - reason = "STATUS_VOLMGR_DISK_SET_NOT_CONTAINED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS: - reason = "STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_MEMBERS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES: - reason = "STATUS_VOLMGR_DISK_USED_BY_MULTIPLE_PLEXES"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED: - reason = "STATUS_VOLMGR_DYNAMIC_DISK_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_ALREADY_USED: - reason = "STATUS_VOLMGR_EXTENT_ALREADY_USED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS: - reason = "STATUS_VOLMGR_EXTENT_NOT_CONTIGUOUS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION: - reason = "STATUS_VOLMGR_EXTENT_NOT_IN_PUBLIC_REGION"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED: - reason = "STATUS_VOLMGR_EXTENT_NOT_SECTOR_ALIGNED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION: - reason = "STATUS_VOLMGR_EXTENT_OVERLAPS_EBR_PARTITION"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH: - reason = "STATUS_VOLMGR_EXTENT_VOLUME_LENGTHS_DO_NOT_MATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED: - reason = "STATUS_VOLMGR_FAULT_TOLERANT_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID: - reason = "STATUS_VOLMGR_INTERLEAVE_LENGTH_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS: - reason = "STATUS_VOLMGR_MAXIMUM_REGISTERED_USERS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_IN_SYNC: - reason = "STATUS_VOLMGR_MEMBER_IN_SYNC"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE: - reason = "STATUS_VOLMGR_MEMBER_INDEX_DUPLICATE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_INDEX_INVALID: - reason = "STATUS_VOLMGR_MEMBER_INDEX_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_MISSING: - reason = "STATUS_VOLMGR_MEMBER_MISSING"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_NOT_DETACHED: - reason = "STATUS_VOLMGR_MEMBER_NOT_DETACHED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_MEMBER_REGENERATING: - reason = "STATUS_VOLMGR_MEMBER_REGENERATING"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_ALL_DISKS_FAILED: - reason = "STATUS_VOLMGR_ALL_DISKS_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_REGISTERED_USERS: - reason = "STATUS_VOLMGR_NO_REGISTERED_USERS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_SUCH_USER: - reason = "STATUS_VOLMGR_NO_SUCH_USER"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NOTIFICATION_RESET: - reason = "STATUS_VOLMGR_NOTIFICATION_RESET"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID: - reason = "STATUS_VOLMGR_NUMBER_OF_MEMBERS_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID: - reason = "STATUS_VOLMGR_NUMBER_OF_PLEXES_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_DUPLICATE: - reason = "STATUS_VOLMGR_PACK_DUPLICATE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_ID_INVALID: - reason = "STATUS_VOLMGR_PACK_ID_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_INVALID: - reason = "STATUS_VOLMGR_PACK_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_NAME_INVALID: - reason = "STATUS_VOLMGR_PACK_NAME_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_OFFLINE: - reason = "STATUS_VOLMGR_PACK_OFFLINE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_HAS_QUORUM: - reason = "STATUS_VOLMGR_PACK_HAS_QUORUM"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_WITHOUT_QUORUM: - reason = "STATUS_VOLMGR_PACK_WITHOUT_QUORUM"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_STYLE_INVALID: - reason = "STATUS_VOLMGR_PARTITION_STYLE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PARTITION_UPDATE_FAILED: - reason = "STATUS_VOLMGR_PARTITION_UPDATE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_IN_SYNC: - reason = "STATUS_VOLMGR_PLEX_IN_SYNC"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_DUPLICATE: - reason = "STATUS_VOLMGR_PLEX_INDEX_DUPLICATE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_INDEX_INVALID: - reason = "STATUS_VOLMGR_PLEX_INDEX_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_LAST_ACTIVE: - reason = "STATUS_VOLMGR_PLEX_LAST_ACTIVE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_MISSING: - reason = "STATUS_VOLMGR_PLEX_MISSING"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_REGENERATING: - reason = "STATUS_VOLMGR_PLEX_REGENERATING"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_TYPE_INVALID: - reason = "STATUS_VOLMGR_PLEX_TYPE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_RAID5: - reason = "STATUS_VOLMGR_PLEX_NOT_RAID5"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE: - reason = "STATUS_VOLMGR_PLEX_NOT_SIMPLE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_STRUCTURE_SIZE_INVALID: - reason = "STATUS_VOLMGR_STRUCTURE_SIZE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS: - reason = "STATUS_VOLMGR_TOO_MANY_NOTIFICATION_REQUESTS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_TRANSACTION_IN_PROGRESS: - reason = "STATUS_VOLMGR_TRANSACTION_IN_PROGRESS"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE: - reason = "STATUS_VOLMGR_UNEXPECTED_DISK_LAYOUT_CHANGE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK: - reason = "STATUS_VOLMGR_VOLUME_CONTAINS_MISSING_DISK"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_ID_INVALID: - reason = "STATUS_VOLMGR_VOLUME_ID_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_INVALID: - reason = "STATUS_VOLMGR_VOLUME_LENGTH_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE: - reason = "STATUS_VOLMGR_VOLUME_LENGTH_NOT_SECTOR_SIZE_MULTIPLE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_MIRRORED: - reason = "STATUS_VOLMGR_VOLUME_NOT_MIRRORED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_NOT_RETAINED: - reason = "STATUS_VOLMGR_VOLUME_NOT_RETAINED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_OFFLINE: - reason = "STATUS_VOLMGR_VOLUME_OFFLINE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_RETAINED: - reason = "STATUS_VOLMGR_VOLUME_RETAINED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID: - reason = "STATUS_VOLMGR_NUMBER_OF_EXTENTS_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE: - reason = "STATUS_VOLMGR_DIFFERENT_SECTOR_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_BAD_BOOT_DISK: - reason = "STATUS_VOLMGR_BAD_BOOT_DISK"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_OFFLINE: - reason = "STATUS_VOLMGR_PACK_CONFIG_OFFLINE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_CONFIG_ONLINE: - reason = "STATUS_VOLMGR_PACK_CONFIG_ONLINE"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NOT_PRIMARY_PACK: - reason = "STATUS_VOLMGR_NOT_PRIMARY_PACK"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED: - reason = "STATUS_VOLMGR_PACK_LOG_UPDATE_FAILED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID: - reason = "STATUS_VOLMGR_NUMBER_OF_DISKS_IN_PLEX_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID: - reason = "STATUS_VOLMGR_NUMBER_OF_DISKS_IN_MEMBER_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_VOLUME_MIRRORED: - reason = "STATUS_VOLMGR_VOLUME_MIRRORED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED: - reason = "STATUS_VOLMGR_PLEX_NOT_SIMPLE_SPANNED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NO_VALID_LOG_COPIES: - reason = "STATUS_VOLMGR_NO_VALID_LOG_COPIES"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_PRIMARY_PACK_PRESENT: - reason = "STATUS_VOLMGR_PRIMARY_PACK_PRESENT"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID: - reason = "STATUS_VOLMGR_NUMBER_OF_DISKS_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_MIRROR_NOT_SUPPORTED: - reason = "STATUS_VOLMGR_MIRROR_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLMGR_RAID5_NOT_SUPPORTED: - reason = "STATUS_VOLMGR_RAID5_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_BCD_TOO_MANY_ELEMENTS: - reason = "STATUS_BCD_TOO_MANY_ELEMENTS"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_MISSING: - reason = "STATUS_VHD_DRIVE_FOOTER_MISSING"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH: - reason = "STATUS_VHD_DRIVE_FOOTER_CHECKSUM_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_DRIVE_FOOTER_CORRUPT: - reason = "STATUS_VHD_DRIVE_FOOTER_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNKNOWN: - reason = "STATUS_VHD_FORMAT_UNKNOWN"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_FORMAT_UNSUPPORTED_VERSION: - reason = "STATUS_VHD_FORMAT_UNSUPPORTED_VERSION"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH: - reason = "STATUS_VHD_SPARSE_HEADER_CHECKSUM_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION: - reason = "STATUS_VHD_SPARSE_HEADER_UNSUPPORTED_VERSION"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_SPARSE_HEADER_CORRUPT: - reason = "STATUS_VHD_SPARSE_HEADER_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_FAILURE: - reason = "STATUS_VHD_BLOCK_ALLOCATION_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT: - reason = "STATUS_VHD_BLOCK_ALLOCATION_TABLE_CORRUPT"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_BLOCK_SIZE: - reason = "STATUS_VHD_INVALID_BLOCK_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_BITMAP_MISMATCH: - reason = "STATUS_VHD_BITMAP_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_NOT_FOUND: - reason = "STATUS_VHD_PARENT_VHD_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_ID_MISMATCH: - reason = "STATUS_VHD_CHILD_PARENT_ID_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH: - reason = "STATUS_VHD_CHILD_PARENT_TIMESTAMP_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_METADATA_READ_FAILURE: - reason = "STATUS_VHD_METADATA_READ_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_METADATA_WRITE_FAILURE: - reason = "STATUS_VHD_METADATA_WRITE_FAILURE"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_SIZE: - reason = "STATUS_VHD_INVALID_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_FILE_SIZE: - reason = "STATUS_VHD_INVALID_FILE_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_VIRTDISK_PROVIDER_NOT_FOUND: - reason = "STATUS_VIRTDISK_PROVIDER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_VIRTDISK_NOT_VIRTUAL_DISK: - reason = "STATUS_VIRTDISK_NOT_VIRTUAL_DISK"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_PARENT_VHD_ACCESS_DENIED: - reason = "STATUS_VHD_PARENT_VHD_ACCESS_DENIED"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH: - reason = "STATUS_VHD_CHILD_PARENT_SIZE_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED: - reason = "STATUS_VHD_DIFFERENCING_CHAIN_CYCLE_DETECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT: - reason = "STATUS_VHD_DIFFERENCING_CHAIN_ERROR_IN_PARENT"; - break; - case MD_NTSTATUS_WIN_STATUS_VIRTUAL_DISK_LIMITATION: - reason = "STATUS_VIRTUAL_DISK_LIMITATION"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_TYPE: - reason = "STATUS_VHD_INVALID_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_INVALID_STATE: - reason = "STATUS_VHD_INVALID_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE: - reason = "STATUS_VIRTDISK_UNSUPPORTED_DISK_SECTOR_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ALREADY_OWNED: - reason = "STATUS_VIRTDISK_DISK_ALREADY_OWNED"; - break; - case MD_NTSTATUS_WIN_STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE: - reason = "STATUS_VIRTDISK_DISK_ONLINE_AND_WRITABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTLOG_TRACKING_NOT_INITIALIZED: - reason = "STATUS_CTLOG_TRACKING_NOT_INITIALIZED"; - break; - case MD_NTSTATUS_WIN_STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE: - reason = "STATUS_CTLOG_LOGFILE_SIZE_EXCEEDED_MAXSIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTLOG_VHD_CHANGED_OFFLINE: - reason = "STATUS_CTLOG_VHD_CHANGED_OFFLINE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTLOG_INVALID_TRACKING_STATE: - reason = "STATUS_CTLOG_INVALID_TRACKING_STATE"; - break; - case MD_NTSTATUS_WIN_STATUS_CTLOG_INCONSISTENT_TRACKING_FILE: - reason = "STATUS_CTLOG_INCONSISTENT_TRACKING_FILE"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_METADATA_FULL: - reason = "STATUS_VHD_METADATA_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_RKF_KEY_NOT_FOUND: - reason = "STATUS_RKF_KEY_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_RKF_DUPLICATE_KEY: - reason = "STATUS_RKF_DUPLICATE_KEY"; - break; - case MD_NTSTATUS_WIN_STATUS_RKF_BLOB_FULL: - reason = "STATUS_RKF_BLOB_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_RKF_STORE_FULL: - reason = "STATUS_RKF_STORE_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_RKF_FILE_BLOCKED: - reason = "STATUS_RKF_FILE_BLOCKED"; - break; - case MD_NTSTATUS_WIN_STATUS_RKF_ACTIVE_KEY: - reason = "STATUS_RKF_ACTIVE_KEY"; - break; - case MD_NTSTATUS_WIN_STATUS_RDBSS_RESTART_OPERATION: - reason = "STATUS_RDBSS_RESTART_OPERATION"; - break; - case MD_NTSTATUS_WIN_STATUS_RDBSS_CONTINUE_OPERATION: - reason = "STATUS_RDBSS_CONTINUE_OPERATION"; - break; - case MD_NTSTATUS_WIN_STATUS_RDBSS_POST_OPERATION: - reason = "STATUS_RDBSS_POST_OPERATION"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_HANDLE: - reason = "STATUS_BTH_ATT_INVALID_HANDLE"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_READ_NOT_PERMITTED: - reason = "STATUS_BTH_ATT_READ_NOT_PERMITTED"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_WRITE_NOT_PERMITTED: - reason = "STATUS_BTH_ATT_WRITE_NOT_PERMITTED"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_PDU: - reason = "STATUS_BTH_ATT_INVALID_PDU"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION: - reason = "STATUS_BTH_ATT_INSUFFICIENT_AUTHENTICATION"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED: - reason = "STATUS_BTH_ATT_REQUEST_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_OFFSET: - reason = "STATUS_BTH_ATT_INVALID_OFFSET"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION: - reason = "STATUS_BTH_ATT_INSUFFICIENT_AUTHORIZATION"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_PREPARE_QUEUE_FULL: - reason = "STATUS_BTH_ATT_PREPARE_QUEUE_FULL"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND: - reason = "STATUS_BTH_ATT_ATTRIBUTE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG: - reason = "STATUS_BTH_ATT_ATTRIBUTE_NOT_LONG"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE: - reason = "STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION_KEY_SIZE"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH: - reason = "STATUS_BTH_ATT_INVALID_ATTRIBUTE_VALUE_LENGTH"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNLIKELY: - reason = "STATUS_BTH_ATT_UNLIKELY"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION: - reason = "STATUS_BTH_ATT_INSUFFICIENT_ENCRYPTION"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE: - reason = "STATUS_BTH_ATT_UNSUPPORTED_GROUP_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_INSUFFICIENT_RESOURCES: - reason = "STATUS_BTH_ATT_INSUFFICIENT_RESOURCES"; - break; - case MD_NTSTATUS_WIN_STATUS_BTH_ATT_UNKNOWN_ERROR: - reason = "STATUS_BTH_ATT_UNKNOWN_ERROR"; - break; - case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_ROLLBACK_DETECTED: - reason = "STATUS_SECUREBOOT_ROLLBACK_DETECTED"; - break; - case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_VIOLATION: - reason = "STATUS_SECUREBOOT_POLICY_VIOLATION"; - break; - case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_INVALID_POLICY: - reason = "STATUS_SECUREBOOT_INVALID_POLICY"; - break; - case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND: - reason = "STATUS_SECUREBOOT_POLICY_PUBLISHER_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_POLICY_NOT_SIGNED: - reason = "STATUS_SECUREBOOT_POLICY_NOT_SIGNED"; - break; - case MD_NTSTATUS_WIN_STATUS_SECUREBOOT_FILE_REPLACED: - reason = "STATUS_SECUREBOOT_FILE_REPLACED"; - break; - case MD_NTSTATUS_WIN_STATUS_AUDIO_ENGINE_NODE_NOT_FOUND: - reason = "STATUS_AUDIO_ENGINE_NODE_NOT_FOUND"; - break; - case MD_NTSTATUS_WIN_STATUS_HDAUDIO_EMPTY_CONNECTION_LIST: - reason = "STATUS_HDAUDIO_EMPTY_CONNECTION_LIST"; - break; - case MD_NTSTATUS_WIN_STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED: - reason = "STATUS_HDAUDIO_CONNECTION_LIST_NOT_SUPPORTED"; - break; - case MD_NTSTATUS_WIN_STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED: - reason = "STATUS_HDAUDIO_NO_LOGICAL_DEVICES_CREATED"; - break; - case MD_NTSTATUS_WIN_STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY: - reason = "STATUS_HDAUDIO_NULL_LINKED_LIST_ENTRY"; - break; - case MD_NTSTATUS_WIN_STATUS_VOLSNAP_BOOTFILE_NOT_VALID: - reason = "STATUS_VOLSNAP_BOOTFILE_NOT_VALID"; - break; - case MD_NTSTATUS_WIN_STATUS_IO_PREEMPTED: - reason = "STATUS_IO_PREEMPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_STORED: - reason = "STATUS_SVHDX_ERROR_STORED"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_ERROR_NOT_AVAILABLE: - reason = "STATUS_SVHDX_ERROR_NOT_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE: - reason = "STATUS_SVHDX_UNIT_ATTENTION_AVAILABLE"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED: - reason = "STATUS_SVHDX_UNIT_ATTENTION_CAPACITY_DATA_CHANGED"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED: - reason = "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_PREEMPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED: - reason = "STATUS_SVHDX_UNIT_ATTENTION_RESERVATIONS_RELEASED"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED: - reason = "STATUS_SVHDX_UNIT_ATTENTION_REGISTRATIONS_PREEMPTED"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED: - reason = "STATUS_SVHDX_UNIT_ATTENTION_OPERATING_DEFINITION_CHANGED"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_RESERVATION_CONFLICT: - reason = "STATUS_SVHDX_RESERVATION_CONFLICT"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_WRONG_FILE_TYPE: - reason = "STATUS_SVHDX_WRONG_FILE_TYPE"; - break; - case MD_NTSTATUS_WIN_STATUS_SVHDX_VERSION_MISMATCH: - reason = "STATUS_SVHDX_VERSION_MISMATCH"; - break; - case MD_NTSTATUS_WIN_STATUS_VHD_SHARED: - reason = "STATUS_VHD_SHARED"; - break; - case MD_NTSTATUS_WIN_STATUS_SPACES_RESILIENCY_TYPE_INVALID: - reason = "STATUS_SPACES_RESILIENCY_TYPE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID: - reason = "STATUS_SPACES_DRIVE_SECTOR_SIZE_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_SPACES_INTERLEAVE_LENGTH_INVALID: - reason = "STATUS_SPACES_INTERLEAVE_LENGTH_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID: - reason = "STATUS_SPACES_NUMBER_OF_COLUMNS_INVALID"; - break; - case MD_NTSTATUS_WIN_STATUS_SPACES_NOT_ENOUGH_DRIVES: - reason = "STATUS_SPACES_NOT_ENOUGH_DRIVES"; - break; - default: { - char reason_string[11]; - snprintf(reason_string, sizeof(reason_string), "0x%08x", ntstatus); - reason = reason_string; - break; - } - } - return reason; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.h b/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.h deleted file mode 100644 index c05c91698..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/symbolic_constants_win.h +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright (c) 2015 Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// ntstatus_reason_win.h: Windows NTSTATUS code to string. -// -// Provides a means to convert NTSTATUS codes to strings. -// -// Author: Ben Wagner - -#ifndef GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_ -#define GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_ - -#include <string> - -#include "google_breakpad/common/breakpad_types.h" - -namespace google_breakpad { - -/* Converts a NTSTATUS code to a reason string. */ -std::string NTStatusToString(uint32_t ntstatus); - -} // namespace google_breakpad - -#endif // GOOGLE_BREAKPAD_PROCESSOR_SYMBOLIC_CONSTANTS_WIN_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc deleted file mode 100644 index 2cfbb0888..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.cc +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// synth_minidump.cc: Implementation of SynthMinidump. See synth_minidump.h - -#include "processor/synth_minidump.h" - -namespace google_breakpad { - -namespace SynthMinidump { - -Section::Section(const Dump &dump) - : test_assembler::Section(dump.endianness()) { } - -void Section::CiteLocationIn(test_assembler::Section *section) const { - if (this) - (*section).D32(size_).D32(file_offset_); - else - (*section).D32(0).D32(0); -} - -void Stream::CiteStreamIn(test_assembler::Section *section) const { - section->D32(type_); - CiteLocationIn(section); -} - -SystemInfo::SystemInfo(const Dump &dump, - const MDRawSystemInfo &system_info, - const String &csd_version) - : Stream(dump, MD_SYSTEM_INFO_STREAM) { - D16(system_info.processor_architecture); - D16(system_info.processor_level); - D16(system_info.processor_revision); - D8(system_info.number_of_processors); - D8(system_info.product_type); - D32(system_info.major_version); - D32(system_info.minor_version); - D32(system_info.build_number); - D32(system_info.platform_id); - csd_version.CiteStringIn(this); - D16(system_info.suite_mask); - D16(system_info.reserved2); // Well, why not? - - // MDCPUInformation cpu; - if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_X86) { - D32(system_info.cpu.x86_cpu_info.vendor_id[0]); - D32(system_info.cpu.x86_cpu_info.vendor_id[1]); - D32(system_info.cpu.x86_cpu_info.vendor_id[2]); - D32(system_info.cpu.x86_cpu_info.version_information); - D32(system_info.cpu.x86_cpu_info.feature_information); - D32(system_info.cpu.x86_cpu_info.amd_extended_cpu_features); - } else if (system_info.processor_architecture == MD_CPU_ARCHITECTURE_ARM) { - D32(system_info.cpu.arm_cpu_info.cpuid); - D32(system_info.cpu.arm_cpu_info.elf_hwcaps); - } else { - D64(system_info.cpu.other_cpu_info.processor_features[0]); - D64(system_info.cpu.other_cpu_info.processor_features[1]); - } -} - -const MDRawSystemInfo SystemInfo::windows_x86 = { - MD_CPU_ARCHITECTURE_X86, // processor_architecture - 6, // processor_level - 0xd08, // processor_revision - 1, // number_of_processors - 1, // product_type - 5, // major_version - 1, // minor_version - 2600, // build_number - 2, // platform_id - 0xdeadbeef, // csd_version_rva - 0x100, // suite_mask - 0, // reserved2 - { // cpu - { // x86_cpu_info - { 0x756e6547, 0x49656e69, 0x6c65746e }, // vendor_id - 0x6d8, // version_information - 0xafe9fbff, // feature_information - 0xffffffff // amd_extended_cpu_features - } - } -}; - -const string SystemInfo::windows_x86_csd_version = "Service Pack 2"; - -String::String(const Dump &dump, const string &contents) : Section(dump) { - D32(contents.size() * 2); - for (string::const_iterator i = contents.begin(); i != contents.end(); i++) - D16(*i); -} - -void String::CiteStringIn(test_assembler::Section *section) const { - section->D32(file_offset_); -} - -void Memory::CiteMemoryIn(test_assembler::Section *section) const { - section->D64(address_); - CiteLocationIn(section); -} - -Context::Context(const Dump &dump, const MDRawContextX86 &context) - : Section(dump) { - // The caller should have properly set the CPU type flag. - // The high 24 bits identify the CPU. Note that context records with no CPU - // type information can be valid (e.g. produced by ::RtlCaptureContext). - assert(((context.context_flags & MD_CONTEXT_CPU_MASK) == 0) || - (context.context_flags & MD_CONTEXT_X86)); - // It doesn't make sense to store x86 registers in big-endian form. - assert(dump.endianness() == kLittleEndian); - D32(context.context_flags); - D32(context.dr0); - D32(context.dr1); - D32(context.dr2); - D32(context.dr3); - D32(context.dr6); - D32(context.dr7); - D32(context.float_save.control_word); - D32(context.float_save.status_word); - D32(context.float_save.tag_word); - D32(context.float_save.error_offset); - D32(context.float_save.error_selector); - D32(context.float_save.data_offset); - D32(context.float_save.data_selector); - // context.float_save.register_area[] contains 8-bit quantities and - // does not need to be swapped. - Append(context.float_save.register_area, - sizeof(context.float_save.register_area)); - D32(context.float_save.cr0_npx_state); - D32(context.gs); - D32(context.fs); - D32(context.es); - D32(context.ds); - D32(context.edi); - D32(context.esi); - D32(context.ebx); - D32(context.edx); - D32(context.ecx); - D32(context.eax); - D32(context.ebp); - D32(context.eip); - D32(context.cs); - D32(context.eflags); - D32(context.esp); - D32(context.ss); - // context.extended_registers[] contains 8-bit quantities and does - // not need to be swapped. - Append(context.extended_registers, sizeof(context.extended_registers)); - assert(Size() == sizeof(MDRawContextX86)); -} - -Context::Context(const Dump &dump, const MDRawContextARM &context) - : Section(dump) { - // The caller should have properly set the CPU type flag. - assert((context.context_flags & MD_CONTEXT_ARM) || - (context.context_flags & MD_CONTEXT_ARM_OLD)); - // It doesn't make sense to store ARM registers in big-endian form. - assert(dump.endianness() == kLittleEndian); - D32(context.context_flags); - for (int i = 0; i < MD_CONTEXT_ARM_GPR_COUNT; ++i) - D32(context.iregs[i]); - D32(context.cpsr); - D64(context.float_save.fpscr); - for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPR_COUNT; ++i) - D64(context.float_save.regs[i]); - for (int i = 0; i < MD_FLOATINGSAVEAREA_ARM_FPEXTRA_COUNT; ++i) - D32(context.float_save.extra[i]); - assert(Size() == sizeof(MDRawContextARM)); -} - -Context::Context(const Dump &dump, const MDRawContextMIPS &context) - : Section(dump) { - // The caller should have properly set the CPU type flag. - assert(context.context_flags & MD_CONTEXT_MIPS); - D32(context.context_flags); - D32(context._pad0); - - for (int i = 0; i < MD_CONTEXT_MIPS_GPR_COUNT; ++i) - D64(context.iregs[i]); - - D64(context.mdhi); - D64(context.mdlo); - - for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i) - D32(context.hi[i]); - - for (int i = 0; i < MD_CONTEXT_MIPS_DSP_COUNT; ++i) - D32(context.lo[i]); - - D32(context.dsp_control); - D32(context._pad1); - - D64(context.epc); - D64(context.badvaddr); - D32(context.status); - D32(context.cause); - - for (int i = 0; i < MD_FLOATINGSAVEAREA_MIPS_FPR_COUNT; ++i) - D64(context.float_save.regs[i]); - - D32(context.float_save.fpcsr); - D32(context.float_save.fir); - - assert(Size() == sizeof(MDRawContextMIPS)); -} - -Thread::Thread(const Dump &dump, - uint32_t thread_id, const Memory &stack, const Context &context, - uint32_t suspend_count, uint32_t priority_class, - uint32_t priority, uint64_t teb) : Section(dump) { - D32(thread_id); - D32(suspend_count); - D32(priority_class); - D32(priority); - D64(teb); - stack.CiteMemoryIn(this); - context.CiteLocationIn(this); - assert(Size() == sizeof(MDRawThread)); -} - -Module::Module(const Dump &dump, - uint64_t base_of_image, - uint32_t size_of_image, - const String &name, - uint32_t time_date_stamp, - uint32_t checksum, - const MDVSFixedFileInfo &version_info, - const Section *cv_record, - const Section *misc_record) : Section(dump) { - D64(base_of_image); - D32(size_of_image); - D32(checksum); - D32(time_date_stamp); - name.CiteStringIn(this); - D32(version_info.signature); - D32(version_info.struct_version); - D32(version_info.file_version_hi); - D32(version_info.file_version_lo); - D32(version_info.product_version_hi); - D32(version_info.product_version_lo); - D32(version_info.file_flags_mask); - D32(version_info.file_flags); - D32(version_info.file_os); - D32(version_info.file_type); - D32(version_info.file_subtype); - D32(version_info.file_date_hi); - D32(version_info.file_date_lo); - cv_record->CiteLocationIn(this); - misc_record->CiteLocationIn(this); - D64(0).D64(0); -} - -const MDVSFixedFileInfo Module::stock_version_info = { - MD_VSFIXEDFILEINFO_SIGNATURE, // signature - MD_VSFIXEDFILEINFO_VERSION, // struct_version - 0x11111111, // file_version_hi - 0x22222222, // file_version_lo - 0x33333333, // product_version_hi - 0x44444444, // product_version_lo - MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags_mask - MD_VSFIXEDFILEINFO_FILE_FLAGS_DEBUG, // file_flags - MD_VSFIXEDFILEINFO_FILE_OS_NT | MD_VSFIXEDFILEINFO_FILE_OS__WINDOWS32, - // file_os - MD_VSFIXEDFILEINFO_FILE_TYPE_APP, // file_type - MD_VSFIXEDFILEINFO_FILE_SUBTYPE_UNKNOWN, // file_subtype - 0, // file_date_hi - 0 // file_date_lo -}; - -Exception::Exception(const Dump &dump, - const Context &context, - uint32_t thread_id, - uint32_t exception_code, - uint32_t exception_flags, - uint64_t exception_address) - : Stream(dump, MD_EXCEPTION_STREAM) { - D32(thread_id); - D32(0); // __align - D32(exception_code); - D32(exception_flags); - D64(0); // exception_record - D64(exception_address); - D32(0); // number_parameters - D32(0); // __align - for (int i = 0; i < MD_EXCEPTION_MAXIMUM_PARAMETERS; ++i) - D64(0); // exception_information - context.CiteLocationIn(this); - assert(Size() == sizeof(MDRawExceptionStream)); -} - -Dump::Dump(uint64_t flags, - Endianness endianness, - uint32_t version, - uint32_t date_time_stamp) - : test_assembler::Section(endianness), - file_start_(0), - stream_directory_(*this), - stream_count_(0), - thread_list_(*this, MD_THREAD_LIST_STREAM), - module_list_(*this, MD_MODULE_LIST_STREAM), - memory_list_(*this, MD_MEMORY_LIST_STREAM) - { - D32(MD_HEADER_SIGNATURE); - D32(version); - D32(stream_count_label_); - D32(stream_directory_rva_); - D32(0); - D32(date_time_stamp); - D64(flags); - assert(Size() == sizeof(MDRawHeader)); -} - -Dump &Dump::Add(SynthMinidump::Section *section) { - section->Finish(file_start_ + Size()); - Append(*section); - return *this; -} - -Dump &Dump::Add(Stream *stream) { - Add(static_cast<SynthMinidump::Section *>(stream)); - stream->CiteStreamIn(&stream_directory_); - stream_count_++; - return *this; -} - -Dump &Dump::Add(Memory *memory) { - // Add the memory contents themselves to the file. - Add(static_cast<SynthMinidump::Section *>(memory)); - - // The memory list is a list of MDMemoryDescriptors, not of actual - // memory elements. Produce a descriptor, and add that to the list. - SynthMinidump::Section descriptor(*this); - memory->CiteMemoryIn(&descriptor); - memory_list_.Add(&descriptor); - return *this; -} - -Dump &Dump::Add(Thread *thread) { - thread_list_.Add(thread); - return *this; -} - -Dump &Dump::Add(Module *module) { - module_list_.Add(module); - return *this; -} - -void Dump::Finish() { - if (!thread_list_.Empty()) Add(&thread_list_); - if (!module_list_.Empty()) Add(&module_list_); - if (!memory_list_.Empty()) Add(&memory_list_); - - // Create the stream directory. We don't use - // stream_directory_.Finish here, because the stream directory isn't - // cited using a location descriptor; rather, the Minidump header - // has the stream count and MDRVA. - stream_count_label_ = stream_count_; - stream_directory_rva_ = file_start_ + Size(); - Append(static_cast<test_assembler::Section &>(stream_directory_)); -} - -} // namespace SynthMinidump - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.h b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.h deleted file mode 100644 index 8dac8784e..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump.h +++ /dev/null @@ -1,372 +0,0 @@ -// -*- mode: C++ -*- - -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// synth_minidump.h: Interface to SynthMinidump: fake minidump generator. -// -// We treat a minidump file as the concatenation of a bunch of -// test_assembler::Sections. The file header, stream directory, -// streams, memory regions, strings, and so on --- each is a Section -// that eventually gets appended to the minidump. Dump, Memory, -// Context, Thread, and so on all inherit from test_assembler::Section. -// For example: -// -// using google_breakpad::test_assembler::kLittleEndian; -// using google_breakpad::SynthMinidump::Context; -// using google_breakpad::SynthMinidump::Dump; -// using google_breakpad::SynthMinidump::Memory; -// using google_breakpad::SynthMinidump::Thread; -// -// Dump minidump(MD_NORMAL, kLittleEndian); -// -// Memory stack1(minidump, 0x569eb0a9); -// ... build contents of stack1 with test_assembler::Section functions ... -// -// MDRawContextX86 x86_context1; -// x86_context1.context_flags = MD_CONTEXT_X86; -// x86_context1.eip = 0x7c90eb94; -// x86_context1.esp = 0x569eb0a9; -// x86_context1.ebp = x86_context1.esp + something appropriate; -// Context context1(minidump, x86_context1); -// -// Thread thread1(minidump, 0xe4a4821d, stack1, context1); -// -// minidump.Add(&stack1); -// minidump.Add(&context1); -// minidump.Add(&thread1); -// minidump.Finish(); -// -// string contents; -// EXPECT_TRUE(minidump.GetContents(&contents)); -// // contents now holds the bytes of a minidump file -// -// Because the test_assembler classes let us write Label references to -// sections before the Labels' values are known, this gives us -// flexibility in how we put the dump together: minidump pieces can -// hold the file offsets of other minidump pieces before the -// referents' positions have been decided. As long as everything has -// been placed by the time we call dump.GetContents to obtain the -// bytes, all the Labels' values will be known, and everything will -// get patched up appropriately. -// -// The dump.Add(thing) functions append THINGS's contents to the -// minidump, but they also do two other things: -// -// - dump.Add(thing) invokes thing->Finish, which tells *thing the -// offset within the file at which it was placed, and allows *thing -// to do any final content generation. -// -// - If THING is something which should receive an entry in some sort -// of list or directory, then dump.Add(THING) automatically creates -// the appropriate directory or list entry. Streams must appear in -// the stream directory; memory ranges should be listed in the -// memory list; threads should be placed in the thread list; and so -// on. -// -// By convention, Section subclass constructors that take references -// to other Sections do not take care of 'Add'ing their arguments to -// the dump. For example, although the Thread constructor takes -// references to a Memory and a Context, it does not add them to the -// dump on the caller's behalf. Rather, the caller is responsible for -// 'Add'ing every section they create. This allows Sections to be -// cited from more than one place; for example, Memory ranges are -// cited both from Thread objects (as their stack contents) and by the -// memory list stream. -// -// If you forget to Add some Section, the Dump::GetContents call will -// fail, as the test_assembler::Labels used to cite the Section's -// contents from elsewhere will still be undefined. -#ifndef PROCESSOR_SYNTH_MINIDUMP_H_ -#define PROCESSOR_SYNTH_MINIDUMP_H_ - -#include <assert.h> - -#include <iostream> -#include <string> - -#include "common/test_assembler.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" -#include "google_breakpad/common/minidump_format.h" - -namespace google_breakpad { - -namespace SynthMinidump { - -using test_assembler::Endianness; -using test_assembler::kBigEndian; -using test_assembler::kLittleEndian; -using test_assembler::kUnsetEndian; -using test_assembler::Label; - -class Dump; -class Memory; -class String; - -// A test_assembler::Section which will be appended to a minidump. -class Section: public test_assembler::Section { - public: - explicit Section(const Dump &dump); - - // Append an MDLocationDescriptor referring to this section to SECTION. - // If 'this' is NULL, append a descriptor with a zero length and MDRVA. - // - // (I couldn't find the language in the C++ standard that says that - // invoking member functions of a NULL pointer to a class type is - // bad, if such language exists. Having this function handle NULL - // 'this' is convenient, but if it causes trouble, it's not hard to - // do differently.) - void CiteLocationIn(test_assembler::Section *section) const; - - // Note that this section's contents are complete, and that it has - // been placed in the minidump file at OFFSET. The 'Add' member - // functions call the Finish member function of the object being - // added for you; if you are 'Add'ing this section, you needn't Finish it. - virtual void Finish(const Label &offset) { - file_offset_ = offset; size_ = Size(); - } - - protected: - // This section's size and offset within the minidump file. - Label file_offset_, size_; -}; - -// A stream within a minidump file. 'Add'ing a stream to a minidump -// creates an entry for it in the minidump's stream directory. -class Stream: public Section { - public: - // Create a stream of type TYPE. You can append whatever contents - // you like to this stream using the test_assembler::Section methods. - Stream(const Dump &dump, uint32_t type) : Section(dump), type_(type) { } - - // Append an MDRawDirectory referring to this stream to SECTION. - void CiteStreamIn(test_assembler::Section *section) const; - - private: - // The type of this stream. - uint32_t type_; -}; - -class SystemInfo: public Stream { - public: - // Create an MD_SYSTEM_INFO_STREAM stream belonging to DUMP holding - // an MDRawSystem info structure initialized with the values from - // SYSTEM_INFO, except that the csd_version field is replaced with - // the file offset of the string CSD_VERSION, which can be 'Add'ed - // to the dump at the desired location. - // - // Remember that you are still responsible for 'Add'ing CSD_VERSION - // to the dump yourself. - SystemInfo(const Dump &dump, - const MDRawSystemInfo &system_info, - const String &csd_version); - - // Stock MDRawSystemInfo information and associated strings, for - // writing tests. - static const MDRawSystemInfo windows_x86; - static const string windows_x86_csd_version; -}; - -// An MDString: a string preceded by a 32-bit length. -class String: public Section { - public: - String(const Dump &dump, const string &value); - - // Append an MDRVA referring to this string to SECTION. - void CiteStringIn(test_assembler::Section *section) const; -}; - -// A range of memory contents. 'Add'ing a memory range to a minidump -// creates n entry for it in the minidump's memory list. By -// convention, the 'start', 'Here', and 'Mark' member functions refer -// to memory addresses. -class Memory: public Section { - public: - Memory(const Dump &dump, uint64_t address) - : Section(dump), address_(address) { start() = address; } - - // Append an MDMemoryDescriptor referring to this memory range to SECTION. - void CiteMemoryIn(test_assembler::Section *section) const; - - private: - // The process address from which these memory contents were taken. - // Shouldn't this be a Label? - uint64_t address_; -}; - -class Context: public Section { - public: - // Create a context belonging to DUMP whose contents are a copy of CONTEXT. - Context(const Dump &dump, const MDRawContextX86 &context); - Context(const Dump &dump, const MDRawContextARM &context); - Context(const Dump &dump, const MDRawContextMIPS &context); - // Add an empty context to the dump. - Context(const Dump &dump) : Section(dump) {} - // Add constructors for other architectures here. Remember to byteswap. -}; - -class Thread: public Section { - public: - // Create a thread belonging to DUMP with the given values, citing - // STACK and CONTEXT (which you must Add to the dump separately). - Thread(const Dump &dump, - uint32_t thread_id, - const Memory &stack, - const Context &context, - uint32_t suspend_count = 0, - uint32_t priority_class = 0, - uint32_t priority = 0, - uint64_t teb = 0); -}; - -class Module: public Section { - public: - // Create a module with the given values. Note that CV_RECORD and - // MISC_RECORD can be NULL, in which case the corresponding location - // descriptior in the minidump will have a length of zero. - Module(const Dump &dump, - uint64_t base_of_image, - uint32_t size_of_image, - const String &name, - uint32_t time_date_stamp = 1262805309, - uint32_t checksum = 0, - const MDVSFixedFileInfo &version_info = Module::stock_version_info, - const Section *cv_record = NULL, - const Section *misc_record = NULL); - - private: - // A standard MDVSFixedFileInfo structure to use as a default for - // minidumps. There's no reason to make users write out all this crap - // over and over. - static const MDVSFixedFileInfo stock_version_info; -}; - -class Exception : public Stream { -public: - Exception(const Dump &dump, - const Context &context, - uint32_t thread_id = 0, - uint32_t exception_code = 0, - uint32_t exception_flags = 0, - uint64_t exception_address = 0); -}; - -// A list of entries starting with a 32-bit count, like a memory list -// or a thread list. -template<typename Element> -class List: public Stream { - public: - List(const Dump &dump, uint32_t type) : Stream(dump, type), count_(0) { - D32(count_label_); - } - - // Add ELEMENT to this list. - void Add(Element *element) { - element->Finish(file_offset_ + Size()); - Append(*element); - count_++; - } - - // Return true if this List is empty, false otherwise. - bool Empty() { return count_ == 0; } - - // Finish up the contents of this section, mark it as having been - // placed at OFFSET. - virtual void Finish(const Label &offset) { - Stream::Finish(offset); - count_label_ = count_; - } - - private: - size_t count_; - Label count_label_; -}; - -class Dump: public test_assembler::Section { - public: - - // Create a test_assembler::Section containing a minidump file whose - // header uses the given values. ENDIANNESS determines the - // endianness of the signature; we set this section's default - // endianness by this. - Dump(uint64_t flags, - Endianness endianness = kLittleEndian, - uint32_t version = MD_HEADER_VERSION, - uint32_t date_time_stamp = 1262805309); - - // The following functions call OBJECT->Finish(), and append the - // contents of OBJECT to this minidump. They also record OBJECT in - // whatever directory or list is appropriate for its type. The - // stream directory, memory list, thread list, and module list are - // accumulated this way. - Dump &Add(SynthMinidump::Section *object); // simply append data - Dump &Add(Stream *object); // append, record in stream directory - Dump &Add(Memory *object); // append, record in memory list - Dump &Add(Thread *object); // append, record in thread list - Dump &Add(Module *object); // append, record in module list - - // Complete the construction of the minidump, given the Add calls - // we've seen up to this point. After this call, this Dump's - // contents are complete, all labels should be defined if everything - // Cited has been Added, and you may call GetContents on it. - void Finish(); - - private: - // A label representing the start of the minidump file. - Label file_start_; - - // The stream directory. We construct this incrementally from - // Add(Stream *) calls. - SynthMinidump::Section stream_directory_; // The directory's contents. - size_t stream_count_; // The number of streams so far. - Label stream_count_label_; // Cited in file header. - Label stream_directory_rva_; // The directory's file offset. - - // This minidump's thread list. We construct this incrementally from - // Add(Thread *) calls. - List<Thread> thread_list_; - - // This minidump's module list. We construct this incrementally from - // Add(Module *) calls. - List<Module> module_list_; - - // This minidump's memory list. We construct this incrementally from - // Add(Memory *) calls. This is actually a list of MDMemoryDescriptors, - // not memory ranges --- thus the odd type. - List<SynthMinidump::Section> memory_list_; -}; - -} // namespace SynthMinidump - -} // namespace google_breakpad - -#endif // PROCESSOR_SYNTH_MINIDUMP_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest.cc b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest.cc deleted file mode 100644 index 8835b4493..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest.cc +++ /dev/null @@ -1,336 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// Original author: Jim Blandy <jimb@mozilla.com> <jimb@red-bean.com> - -// synth_minidump_unittest.cc: Unit tests for google_breakpad::SynthMinidump -// classes. - -#include <sstream> -#include <string> - -#include "breakpad_googletest_includes.h" -#include "common/using_std_string.h" -#include "google_breakpad/common/minidump_format.h" -#include "processor/synth_minidump.h" -#include "processor/synth_minidump_unittest_data.h" - -using google_breakpad::SynthMinidump::Context; -using google_breakpad::SynthMinidump::Dump; -using google_breakpad::SynthMinidump::Exception; -using google_breakpad::SynthMinidump::List; -using google_breakpad::SynthMinidump::Memory; -using google_breakpad::SynthMinidump::Module; -using google_breakpad::SynthMinidump::Section; -using google_breakpad::SynthMinidump::Stream; -using google_breakpad::SynthMinidump::String; -using google_breakpad::SynthMinidump::SystemInfo; -using google_breakpad::test_assembler::kBigEndian; -using google_breakpad::test_assembler::kLittleEndian; -using google_breakpad::test_assembler::Label; - -TEST(Section, Simple) { - Dump dump(0); - Section section(dump); - section.L32(0x12345678); - section.Finish(0); - string contents; - ASSERT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("\x78\x56\x34\x12", 4), contents); -} - -TEST(Section, CiteLocationIn) { - Dump dump(0, kBigEndian); - Section section1(dump), section2(dump); - section1.Append("order"); - section2.Append("mayhem"); - section2.Finish(0x32287ec2); - section2.CiteLocationIn(§ion1); - string contents; - ASSERT_TRUE(section1.GetContents(&contents)); - string expected("order\0\0\0\x06\x32\x28\x7e\xc2", 13); - EXPECT_EQ(expected, contents); -} - -TEST(Stream, CiteStreamIn) { - Dump dump(0, kLittleEndian); - Stream stream(dump, 0x40cae2b3); - Section section(dump); - stream.Append("stream contents"); - section.Append("section contents"); - stream.Finish(0x41424344); - stream.CiteStreamIn(§ion); - string contents; - ASSERT_TRUE(section.GetContents(&contents)); - string expected("section contents" - "\xb3\xe2\xca\x40" - "\x0f\0\0\0" - "\x44\x43\x42\x41", - 16 + 4 + 4 + 4); - EXPECT_EQ(expected, contents); -} - -TEST(Memory, CiteMemoryIn) { - Dump dump(0, kBigEndian); - Memory memory(dump, 0x76d010874ab019f9ULL); - Section section(dump); - memory.Append("memory contents"); - section.Append("section contents"); - memory.Finish(0x51525354); - memory.CiteMemoryIn(§ion); - string contents; - ASSERT_TRUE(section.GetContents(&contents)); - string expected("section contents" - "\x76\xd0\x10\x87\x4a\xb0\x19\xf9" - "\0\0\0\x0f" - "\x51\x52\x53\x54", - 16 + 8 + 4 + 4); - EXPECT_EQ(contents, expected); -} - -TEST(Memory, Here) { - Dump dump(0, kBigEndian); - Memory memory(dump, 0x89979731eb060ed4ULL); - memory.Append(1729, 42); - Label l = memory.Here(); - ASSERT_EQ(0x89979731eb060ed4ULL + 1729, l.Value()); -} - -TEST(Context, X86) { - Dump dump(0, kLittleEndian); - assert(x86_raw_context.context_flags & MD_CONTEXT_X86); - Context context(dump, x86_raw_context); - string contents; - ASSERT_TRUE(context.GetContents(&contents)); - EXPECT_EQ(sizeof(x86_expected_contents), contents.size()); - EXPECT_TRUE(memcmp(contents.data(), x86_expected_contents, contents.size()) - == 0); -} - -TEST(Context, ARM) { - Dump dump(0, kLittleEndian); - assert(arm_raw_context.context_flags & MD_CONTEXT_ARM); - Context context(dump, arm_raw_context); - string contents; - ASSERT_TRUE(context.GetContents(&contents)); - EXPECT_EQ(sizeof(arm_expected_contents), contents.size()); - EXPECT_TRUE(memcmp(contents.data(), arm_expected_contents, contents.size()) - == 0); -} - -TEST(ContextDeathTest, X86BadFlags) { - Dump dump(0, kLittleEndian); - MDRawContextX86 raw; - raw.context_flags = MD_CONTEXT_AMD64; - ASSERT_DEATH(Context context(dump, raw);, - "context\\.context_flags & (0x[0-9a-f]+|MD_CONTEXT_X86)"); -} - -TEST(ContextDeathTest, X86BadEndianness) { - Dump dump(0, kBigEndian); - MDRawContextX86 raw; - raw.context_flags = MD_CONTEXT_X86; - ASSERT_DEATH(Context context(dump, raw);, - "dump\\.endianness\\(\\) == kLittleEndian"); -} - -TEST(Thread, Simple) { - Dump dump(0, kLittleEndian); - Context context(dump, x86_raw_context); - context.Finish(0x8665da0c); - Memory stack(dump, 0xaad55a93cc3c0efcULL); - stack.Append("stack contents"); - stack.Finish(0xe08cdbd1); - google_breakpad::SynthMinidump::Thread thread( - dump, 0x3d7ec360, stack, context, - 0x3593f44d, // suspend count - 0xab352b82, // priority class - 0x2753d838, // priority - 0xeb2de4be3f29e3e9ULL); // thread environment block - string contents; - ASSERT_TRUE(thread.GetContents(&contents)); - static const uint8_t expected_bytes[] = { - 0x60, 0xc3, 0x7e, 0x3d, // thread id - 0x4d, 0xf4, 0x93, 0x35, // suspend count - 0x82, 0x2b, 0x35, 0xab, // priority class - 0x38, 0xd8, 0x53, 0x27, // priority - 0xe9, 0xe3, 0x29, 0x3f, 0xbe, 0xe4, 0x2d, 0xeb, // thread environment block - 0xfc, 0x0e, 0x3c, 0xcc, 0x93, 0x5a, 0xd5, 0xaa, // stack address - 0x0e, 0x00, 0x00, 0x00, // stack size - 0xd1, 0xdb, 0x8c, 0xe0, // stack MDRVA - 0xcc, 0x02, 0x00, 0x00, // context size - 0x0c, 0xda, 0x65, 0x86 // context MDRVA - }; - EXPECT_EQ(sizeof(expected_bytes), contents.size()); - EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0); -} - -TEST(Exception, Simple) { - Dump dump(0, kLittleEndian); - Context context(dump, x86_raw_context); - context.Finish(0x8665da0c); - - Exception exception(dump, context, - 0x1234abcd, // thread id - 0xdcba4321, // exception code - 0xf0e0d0c0, // exception flags - 0x0919a9b9c9d9e9f9ULL); // exception address - string contents; - ASSERT_TRUE(exception.GetContents(&contents)); - static const uint8_t expected_bytes[] = { - 0xcd, 0xab, 0x34, 0x12, // thread id - 0x00, 0x00, 0x00, 0x00, // __align - 0x21, 0x43, 0xba, 0xdc, // exception code - 0xc0, 0xd0, 0xe0, 0xf0, // exception flags - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception record - 0xf9, 0xe9, 0xd9, 0xc9, 0xb9, 0xa9, 0x19, 0x09, // exception address - 0x00, 0x00, 0x00, 0x00, // number parameters - 0x00, 0x00, 0x00, 0x00, // __align - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // exception_information - 0xcc, 0x02, 0x00, 0x00, // context size - 0x0c, 0xda, 0x65, 0x86 // context MDRVA - }; - EXPECT_EQ(sizeof(expected_bytes), contents.size()); - EXPECT_TRUE(memcmp(contents.data(), expected_bytes, contents.size()) == 0); -} - -TEST(String, Simple) { - Dump dump(0, kBigEndian); - String s(dump, "All mimsy were the borogoves"); - string contents; - ASSERT_TRUE(s.GetContents(&contents)); - static const char expected[] = - "\x00\x00\x00\x38\0A\0l\0l\0 \0m\0i\0m\0s\0y\0 \0w\0e\0r\0e" - "\0 \0t\0h\0e\0 \0b\0o\0r\0o\0g\0o\0v\0e\0s"; - string expected_string(expected, sizeof(expected) - 1); - EXPECT_EQ(expected_string, contents); -} - -TEST(String, CiteStringIn) { - Dump dump(0, kLittleEndian); - String s(dump, "and the mome wraths outgrabe"); - Section section(dump); - section.Append("initial"); - s.CiteStringIn(§ion); - s.Finish(0xdc2bb469); - string contents; - ASSERT_TRUE(section.GetContents(&contents)); - EXPECT_EQ(string("initial\x69\xb4\x2b\xdc", 7 + 4), contents); -} - -TEST(List, Empty) { - Dump dump(0, kBigEndian); - List<Section> list(dump, 0x2442779c); - EXPECT_TRUE(list.Empty()); - list.Finish(0x84e09808); - string contents; - ASSERT_TRUE(list.GetContents(&contents)); - EXPECT_EQ(string("\0\0\0\0", 4), contents); -} - -TEST(List, Two) { - Dump dump(0, kBigEndian); - List<Section> list(dump, 0x26c9f498); - Section section1(dump); - section1.Append("section one contents"); - EXPECT_TRUE(list.Empty()); - list.Add(§ion1); - EXPECT_FALSE(list.Empty()); - Section section2(dump); - section2.Append("section two contents"); - list.Add(§ion2); - list.Finish(0x1e5bb60e); - string contents; - ASSERT_TRUE(list.GetContents(&contents)); - EXPECT_EQ(string("\0\0\0\x02section one contentssection two contents", 44), - contents); -} - -TEST(Dump, Header) { - Dump dump(0x9f738b33685cc84cULL, kLittleEndian, 0xb3817faf, 0x2c741c0a); - dump.Finish(); - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - ASSERT_EQ(string("\x4d\x44\x4d\x50" // signature - "\xaf\x7f\x81\xb3" // version - "\0\0\0\0" // stream count - "\x20\0\0\0" // directory RVA (could be anything) - "\0\0\0\0" // checksum - "\x0a\x1c\x74\x2c" // time_date_stamp - "\x4c\xc8\x5c\x68\x33\x8b\x73\x9f", // flags - 32), - contents); -} - -TEST(Dump, HeaderBigEndian) { - Dump dump(0x206ce3cc6fb8e0f0ULL, kBigEndian, 0x161693e2, 0x35667744); - dump.Finish(); - string contents; - ASSERT_TRUE(dump.GetContents(&contents)); - ASSERT_EQ(string("\x50\x4d\x44\x4d" // signature - "\x16\x16\x93\xe2" // version - "\0\0\0\0" // stream count - "\0\0\0\x20" // directory RVA (could be anything) - "\0\0\0\0" // checksum - "\x35\x66\x77\x44" // time_date_stamp - "\x20\x6c\xe3\xcc\x6f\xb8\xe0\xf0", // flags - 32), - contents); -} - -TEST(Dump, OneSection) { - Dump dump(0, kLittleEndian); - Section section(dump); - section.Append("section contents"); - dump.Add(§ion); - dump.Finish(); - string dump_contents; - // Just check for undefined labels; don't worry about the contents. - ASSERT_TRUE(dump.GetContents(&dump_contents)); - - Section referencing_section(dump); - section.CiteLocationIn(&referencing_section); - string contents; - ASSERT_TRUE(referencing_section.GetContents(&contents)); - ASSERT_EQ(string("\x10\0\0\0\x20\0\0\0", 8), contents); -} diff --git a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest_data.h b/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest_data.h deleted file mode 100644 index 3403372e6..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/synth_minidump_unittest_data.h +++ /dev/null @@ -1,418 +0,0 @@ -// -*- mode: C++ -*- - -// Not copyrightable: random test data. -// synth_minidump_unittest_data.h: verbose test data for SynthMinidump tests. - -#ifndef PROCESSOR_SYNTH_MINIDUMP_UNITTEST_DATA_H_ -#define PROCESSOR_SYNTH_MINIDUMP_UNITTEST_DATA_H_ - -#include "google_breakpad/common/minidump_format.h" - -static const MDRawContextX86 x86_raw_context = { - 0xded5d71b, // context_flags - 0x9fdb432e, // dr0 - 0x26b7a81a, // dr1 - 0xcac7e348, // dr2 - 0xcf99ec09, // dr3 - 0x7dc8c2cd, // dr6 - 0x21deb880, // dr7 - - // float_save - { - 0x8a5d2bb0, // control_word - 0x0286c4c9, // status_word - 0xf1feea21, // tag_word - 0xb2d40576, // error_offset - 0x48146cde, // error_selector - 0x983f9b21, // data_offset - 0x475be12c, // data_selector - - // register_area - { - 0xd9, 0x04, 0x20, 0x6b, 0x88, 0x3a, 0x3f, 0xd5, - 0x59, 0x7a, 0xa9, 0xeb, 0xd0, 0x5c, 0xdf, 0xfe, - 0xad, 0xdd, 0x4a, 0x8b, 0x10, 0xcc, 0x9a, 0x33, - 0xcb, 0xb6, 0xf7, 0x86, 0xcd, 0x69, 0x25, 0xae, - 0x25, 0xe5, 0x7a, 0xa1, 0x8f, 0xb2, 0x84, 0xd9, - 0xf7, 0x2d, 0x8a, 0xa1, 0x80, 0x81, 0x7f, 0x67, - 0x07, 0xa8, 0x23, 0xf1, 0x8c, 0xdc, 0xd8, 0x04, - 0x8b, 0x9d, 0xb1, 0xcd, 0x61, 0x0c, 0x9c, 0x69, - 0xc7, 0x8d, 0x17, 0xb6, 0xe5, 0x0b, 0x94, 0xf7, - 0x78, 0x9b, 0x63, 0x49, 0xba, 0xfc, 0x08, 0x4d - }, - - 0x84c53a90, // cr0_npx_state - }, - - 0x79f71e76, // gs - 0x8107bd25, // fs - 0x452d2921, // es - 0x87ec2875, // ds - 0xf8bb73f5, // edi - 0xa63ebb88, // esi - 0x95d35ebe, // ebx - 0x17aa2456, // edx - 0x135fa208, // ecx - 0x500615e6, // eax - 0x66d14205, // ebp - 0x000719a5, // eip - 0x477b481b, // cs - 0x8684dfba, // eflags - 0xe33ccddf, // esp - 0xc0e65d33, // ss - - // extended_registers - { - 0x68, 0x63, 0xdf, 0x50, 0xf7, 0x3b, 0xe8, 0xe5, - 0xcb, 0xd6, 0x66, 0x60, 0xe5, 0xa3, 0x58, 0xb3, - 0x6f, 0x34, 0xca, 0x02, 0x9b, 0x5f, 0xd0, 0x41, - 0xbd, 0xc5, 0x2d, 0xf8, 0xff, 0x15, 0xa2, 0xd0, - 0xe3, 0x2b, 0x3b, 0x8a, 0x9f, 0xc3, 0x9e, 0x28, - 0x0a, 0xc2, 0xac, 0x3b, 0x67, 0x37, 0x01, 0xfd, - 0xc3, 0xaf, 0x60, 0xf6, 0x2c, 0x4f, 0xa9, 0x52, - 0x92, 0xe5, 0x28, 0xde, 0x34, 0xb6, 0x2e, 0x44, - 0x15, 0xa4, 0xb6, 0xe4, 0xc9, 0x1a, 0x14, 0xb9, - 0x51, 0x33, 0x3c, 0xe0, 0xc7, 0x94, 0xf0, 0xf7, - 0x78, 0xdd, 0xe5, 0xca, 0xb7, 0xa6, 0xe0, 0x14, - 0xa6, 0x03, 0xab, 0x77, 0xad, 0xbd, 0xd2, 0x53, - 0x3d, 0x07, 0xe7, 0xaf, 0x90, 0x44, 0x71, 0xbe, - 0x0c, 0xdf, 0x2b, 0x97, 0x40, 0x48, 0xd5, 0xf9, - 0x62, 0x03, 0x91, 0x84, 0xd6, 0xdd, 0x29, 0x97, - 0x35, 0x02, 0xfb, 0x59, 0x97, 0xb0, 0xec, 0xa9, - 0x39, 0x6f, 0x81, 0x71, 0x2a, 0xf0, 0xe7, 0x2c, - 0x4e, 0x93, 0x90, 0xcb, 0x67, 0x69, 0xde, 0xd7, - 0x68, 0x3b, 0x0f, 0x69, 0xa8, 0xf4, 0xa8, 0x83, - 0x42, 0x80, 0x47, 0x65, 0x7a, 0xc9, 0x19, 0x5d, - 0xcb, 0x43, 0xa5, 0xff, 0xf8, 0x9e, 0x62, 0xf4, - 0xe2, 0x6c, 0xcc, 0x17, 0x55, 0x7c, 0x0d, 0x5c, - 0x8d, 0x16, 0x01, 0xd7, 0x3a, 0x0c, 0xf4, 0x7f, - 0x71, 0xdc, 0x48, 0xe9, 0x4b, 0xfe, 0x1a, 0xd0, - 0x04, 0x15, 0x33, 0xec, 0x78, 0xc6, 0x7e, 0xde, - 0x7c, 0x23, 0x18, 0x8d, 0x8f, 0xc2, 0x74, 0xc1, - 0x48, 0xcd, 0x5d, 0xee, 0xee, 0x81, 0x9e, 0x49, - 0x47, 0x8a, 0xf8, 0x61, 0xa3, 0x9c, 0x81, 0x96, - 0xbe, 0x2b, 0x5e, 0xbc, 0xcd, 0x34, 0x0a, 0x2a, - 0x3b, 0x8b, 0x7d, 0xa1, 0xf2, 0x8d, 0xb4, 0x51, - 0x9e, 0x14, 0x78, 0xa3, 0x58, 0x65, 0x2d, 0xd6, - 0x50, 0x40, 0x36, 0x32, 0x31, 0xd4, 0x3e, 0xc2, - 0xe0, 0x87, 0x1c, 0x05, 0x95, 0x80, 0x84, 0x24, - 0x08, 0x6f, 0x5b, 0xc7, 0xe1, 0x1d, 0xd5, 0xa3, - 0x94, 0x44, 0xa1, 0x7c, 0xd8, 0x4b, 0x86, 0xd2, - 0xc6, 0xa9, 0xf3, 0xe2, 0x4d, 0x6e, 0x1f, 0x0e, - 0xf2, 0xf5, 0x71, 0xf9, 0x71, 0x05, 0x24, 0xc9, - 0xc1, 0xe8, 0x91, 0x42, 0x61, 0x86, 0x57, 0x68, - 0xd9, 0xc9, 0x1d, 0xd5, 0x5a, 0xe9, 0xba, 0xe6, - 0x15, 0x8f, 0x87, 0xbd, 0x62, 0x56, 0xed, 0xda, - 0xc2, 0xa5, 0xd5, 0x39, 0xac, 0x05, 0x10, 0x14, - 0x4a, 0xe7, 0xe7, 0x3c, 0x3f, 0xb7, 0xbb, 0xed, - 0x01, 0x6e, 0xcd, 0xee, 0x81, 0xb4, 0x62, 0xf4, - 0x62, 0x16, 0xff, 0x20, 0xb4, 0xf0, 0xbc, 0xff, - 0x7d, 0xd9, 0xcf, 0x95, 0x30, 0x27, 0xe0, 0x2f, - 0x98, 0x53, 0x80, 0x15, 0x13, 0xef, 0x44, 0x58, - 0x12, 0x16, 0xdb, 0x11, 0xef, 0x73, 0x51, 0xcd, - 0x42, 0x3f, 0x98, 0x6c, 0xc9, 0x68, 0xc3, 0xf4, - 0x5b, 0x0f, 0x5d, 0x77, 0xed, 0xdf, 0x0f, 0xff, - 0xb8, 0x69, 0x98, 0x50, 0x77, 0x7a, 0xe8, 0x90, - 0x27, 0x46, 0x10, 0xd2, 0xb5, 0x00, 0x3b, 0x36, - 0x43, 0x6d, 0x67, 0x41, 0x20, 0x3a, 0x32, 0xe0, - 0x2e, 0x5a, 0xfb, 0x4e, 0x4f, 0xa4, 0xf7, 0xc2, - 0xe6, 0x81, 0x1a, 0x51, 0xa8, 0x7c, 0xd4, 0x60, - 0x7c, 0x45, 0xe2, 0xba, 0x5b, 0x42, 0xf3, 0xbf, - 0x28, 0xaa, 0xf2, 0x90, 0xe4, 0x94, 0xdd, 0xaa, - 0x22, 0xd3, 0x71, 0x33, 0xa1, 0x01, 0x43, 0x0e, - 0xfa, 0x46, 0xd2, 0x6e, 0x55, 0x5e, 0x49, 0xeb, - 0x94, 0xf0, 0xb0, 0xb1, 0x2e, 0xf2, 0x3d, 0x6c, - 0x00, 0x5e, 0x01, 0x56, 0x3b, 0xfd, 0x5b, 0xa1, - 0x2f, 0x63, 0x1d, 0xbf, 0xf9, 0xd8, 0x13, 0xf7, - 0x4d, 0xb7, 0x1e, 0x3d, 0x98, 0xd2, 0xee, 0xb8, - 0x48, 0xc8, 0x5b, 0x91, 0x0f, 0x54, 0x9e, 0x26, - 0xb2, 0xc7, 0x3a, 0x6c, 0x8a, 0x35, 0xe1, 0xba - } -}; - -static const uint8_t x86_expected_contents[] = { - 0x1b, 0xd7, 0xd5, 0xde, - 0x2e, 0x43, 0xdb, 0x9f, - 0x1a, 0xa8, 0xb7, 0x26, - 0x48, 0xe3, 0xc7, 0xca, - 0x09, 0xec, 0x99, 0xcf, - 0xcd, 0xc2, 0xc8, 0x7d, - 0x80, 0xb8, 0xde, 0x21, - 0xb0, 0x2b, 0x5d, 0x8a, - 0xc9, 0xc4, 0x86, 0x02, - 0x21, 0xea, 0xfe, 0xf1, - 0x76, 0x05, 0xd4, 0xb2, - 0xde, 0x6c, 0x14, 0x48, - 0x21, 0x9b, 0x3f, 0x98, - 0x2c, 0xe1, 0x5b, 0x47, - - // float_save.register_area --- unswapped - 0xd9, 0x04, 0x20, 0x6b, 0x88, 0x3a, 0x3f, 0xd5, - 0x59, 0x7a, 0xa9, 0xeb, 0xd0, 0x5c, 0xdf, 0xfe, - 0xad, 0xdd, 0x4a, 0x8b, 0x10, 0xcc, 0x9a, 0x33, - 0xcb, 0xb6, 0xf7, 0x86, 0xcd, 0x69, 0x25, 0xae, - 0x25, 0xe5, 0x7a, 0xa1, 0x8f, 0xb2, 0x84, 0xd9, - 0xf7, 0x2d, 0x8a, 0xa1, 0x80, 0x81, 0x7f, 0x67, - 0x07, 0xa8, 0x23, 0xf1, 0x8c, 0xdc, 0xd8, 0x04, - 0x8b, 0x9d, 0xb1, 0xcd, 0x61, 0x0c, 0x9c, 0x69, - 0xc7, 0x8d, 0x17, 0xb6, 0xe5, 0x0b, 0x94, 0xf7, - 0x78, 0x9b, 0x63, 0x49, 0xba, 0xfc, 0x08, 0x4d, - - 0x90, 0x3a, 0xc5, 0x84, - 0x76, 0x1e, 0xf7, 0x79, - 0x25, 0xbd, 0x07, 0x81, - 0x21, 0x29, 0x2d, 0x45, - 0x75, 0x28, 0xec, 0x87, - 0xf5, 0x73, 0xbb, 0xf8, - 0x88, 0xbb, 0x3e, 0xa6, - 0xbe, 0x5e, 0xd3, 0x95, - 0x56, 0x24, 0xaa, 0x17, - 0x08, 0xa2, 0x5f, 0x13, - 0xe6, 0x15, 0x06, 0x50, - 0x05, 0x42, 0xd1, 0x66, - 0xa5, 0x19, 0x07, 0x00, - 0x1b, 0x48, 0x7b, 0x47, - 0xba, 0xdf, 0x84, 0x86, - 0xdf, 0xcd, 0x3c, 0xe3, - 0x33, 0x5d, 0xe6, 0xc0, - - // extended_registers --- unswapped - 0x68, 0x63, 0xdf, 0x50, 0xf7, 0x3b, 0xe8, 0xe5, - 0xcb, 0xd6, 0x66, 0x60, 0xe5, 0xa3, 0x58, 0xb3, - 0x6f, 0x34, 0xca, 0x02, 0x9b, 0x5f, 0xd0, 0x41, - 0xbd, 0xc5, 0x2d, 0xf8, 0xff, 0x15, 0xa2, 0xd0, - 0xe3, 0x2b, 0x3b, 0x8a, 0x9f, 0xc3, 0x9e, 0x28, - 0x0a, 0xc2, 0xac, 0x3b, 0x67, 0x37, 0x01, 0xfd, - 0xc3, 0xaf, 0x60, 0xf6, 0x2c, 0x4f, 0xa9, 0x52, - 0x92, 0xe5, 0x28, 0xde, 0x34, 0xb6, 0x2e, 0x44, - 0x15, 0xa4, 0xb6, 0xe4, 0xc9, 0x1a, 0x14, 0xb9, - 0x51, 0x33, 0x3c, 0xe0, 0xc7, 0x94, 0xf0, 0xf7, - 0x78, 0xdd, 0xe5, 0xca, 0xb7, 0xa6, 0xe0, 0x14, - 0xa6, 0x03, 0xab, 0x77, 0xad, 0xbd, 0xd2, 0x53, - 0x3d, 0x07, 0xe7, 0xaf, 0x90, 0x44, 0x71, 0xbe, - 0x0c, 0xdf, 0x2b, 0x97, 0x40, 0x48, 0xd5, 0xf9, - 0x62, 0x03, 0x91, 0x84, 0xd6, 0xdd, 0x29, 0x97, - 0x35, 0x02, 0xfb, 0x59, 0x97, 0xb0, 0xec, 0xa9, - 0x39, 0x6f, 0x81, 0x71, 0x2a, 0xf0, 0xe7, 0x2c, - 0x4e, 0x93, 0x90, 0xcb, 0x67, 0x69, 0xde, 0xd7, - 0x68, 0x3b, 0x0f, 0x69, 0xa8, 0xf4, 0xa8, 0x83, - 0x42, 0x80, 0x47, 0x65, 0x7a, 0xc9, 0x19, 0x5d, - 0xcb, 0x43, 0xa5, 0xff, 0xf8, 0x9e, 0x62, 0xf4, - 0xe2, 0x6c, 0xcc, 0x17, 0x55, 0x7c, 0x0d, 0x5c, - 0x8d, 0x16, 0x01, 0xd7, 0x3a, 0x0c, 0xf4, 0x7f, - 0x71, 0xdc, 0x48, 0xe9, 0x4b, 0xfe, 0x1a, 0xd0, - 0x04, 0x15, 0x33, 0xec, 0x78, 0xc6, 0x7e, 0xde, - 0x7c, 0x23, 0x18, 0x8d, 0x8f, 0xc2, 0x74, 0xc1, - 0x48, 0xcd, 0x5d, 0xee, 0xee, 0x81, 0x9e, 0x49, - 0x47, 0x8a, 0xf8, 0x61, 0xa3, 0x9c, 0x81, 0x96, - 0xbe, 0x2b, 0x5e, 0xbc, 0xcd, 0x34, 0x0a, 0x2a, - 0x3b, 0x8b, 0x7d, 0xa1, 0xf2, 0x8d, 0xb4, 0x51, - 0x9e, 0x14, 0x78, 0xa3, 0x58, 0x65, 0x2d, 0xd6, - 0x50, 0x40, 0x36, 0x32, 0x31, 0xd4, 0x3e, 0xc2, - 0xe0, 0x87, 0x1c, 0x05, 0x95, 0x80, 0x84, 0x24, - 0x08, 0x6f, 0x5b, 0xc7, 0xe1, 0x1d, 0xd5, 0xa3, - 0x94, 0x44, 0xa1, 0x7c, 0xd8, 0x4b, 0x86, 0xd2, - 0xc6, 0xa9, 0xf3, 0xe2, 0x4d, 0x6e, 0x1f, 0x0e, - 0xf2, 0xf5, 0x71, 0xf9, 0x71, 0x05, 0x24, 0xc9, - 0xc1, 0xe8, 0x91, 0x42, 0x61, 0x86, 0x57, 0x68, - 0xd9, 0xc9, 0x1d, 0xd5, 0x5a, 0xe9, 0xba, 0xe6, - 0x15, 0x8f, 0x87, 0xbd, 0x62, 0x56, 0xed, 0xda, - 0xc2, 0xa5, 0xd5, 0x39, 0xac, 0x05, 0x10, 0x14, - 0x4a, 0xe7, 0xe7, 0x3c, 0x3f, 0xb7, 0xbb, 0xed, - 0x01, 0x6e, 0xcd, 0xee, 0x81, 0xb4, 0x62, 0xf4, - 0x62, 0x16, 0xff, 0x20, 0xb4, 0xf0, 0xbc, 0xff, - 0x7d, 0xd9, 0xcf, 0x95, 0x30, 0x27, 0xe0, 0x2f, - 0x98, 0x53, 0x80, 0x15, 0x13, 0xef, 0x44, 0x58, - 0x12, 0x16, 0xdb, 0x11, 0xef, 0x73, 0x51, 0xcd, - 0x42, 0x3f, 0x98, 0x6c, 0xc9, 0x68, 0xc3, 0xf4, - 0x5b, 0x0f, 0x5d, 0x77, 0xed, 0xdf, 0x0f, 0xff, - 0xb8, 0x69, 0x98, 0x50, 0x77, 0x7a, 0xe8, 0x90, - 0x27, 0x46, 0x10, 0xd2, 0xb5, 0x00, 0x3b, 0x36, - 0x43, 0x6d, 0x67, 0x41, 0x20, 0x3a, 0x32, 0xe0, - 0x2e, 0x5a, 0xfb, 0x4e, 0x4f, 0xa4, 0xf7, 0xc2, - 0xe6, 0x81, 0x1a, 0x51, 0xa8, 0x7c, 0xd4, 0x60, - 0x7c, 0x45, 0xe2, 0xba, 0x5b, 0x42, 0xf3, 0xbf, - 0x28, 0xaa, 0xf2, 0x90, 0xe4, 0x94, 0xdd, 0xaa, - 0x22, 0xd3, 0x71, 0x33, 0xa1, 0x01, 0x43, 0x0e, - 0xfa, 0x46, 0xd2, 0x6e, 0x55, 0x5e, 0x49, 0xeb, - 0x94, 0xf0, 0xb0, 0xb1, 0x2e, 0xf2, 0x3d, 0x6c, - 0x00, 0x5e, 0x01, 0x56, 0x3b, 0xfd, 0x5b, 0xa1, - 0x2f, 0x63, 0x1d, 0xbf, 0xf9, 0xd8, 0x13, 0xf7, - 0x4d, 0xb7, 0x1e, 0x3d, 0x98, 0xd2, 0xee, 0xb8, - 0x48, 0xc8, 0x5b, 0x91, 0x0f, 0x54, 0x9e, 0x26, - 0xb2, 0xc7, 0x3a, 0x6c, 0x8a, 0x35, 0xe1, 0xba -}; - -static const MDRawContextARM arm_raw_context = { - // context_flags - 0x591b9e6a, - // iregs - { - 0xa21594de, - 0x820d8a25, - 0xc4e133b2, - 0x173a1c02, - 0x105fb175, - 0xe871793f, - 0x5def70b3, - 0xcee3a623, - 0x7b3aa9b8, - 0x52518537, - 0x627012c5, - 0x22723dcc, - 0x16fcc971, - 0x20988bcb, - 0xf1ab806b, - 0x99d5fc03, - }, - // cpsr - 0xb70df511, - // float_save - { - // fpscr - 0xa1e1f7ce1077e6b5ULL, - // regs - { - 0xbcb8d002eed7fbdeULL, - 0x4dd26a43b96ae97fULL, - 0x8eec22db8b31741cULL, - 0xfd634bd7c5ad66a0ULL, - 0x1681da0daeb3debeULL, - 0x474a32bdf72d0b71ULL, - 0xcaf464f8b1044834ULL, - 0xcaa6592ae5c7582aULL, - 0x4ee46889d877c3dbULL, - 0xf8930cf301645cf5ULL, - 0x4da7e9ebba27f7c7ULL, - 0x69a7b02761944da3ULL, - 0x2cda2b2e78195c06ULL, - 0x66b227ab9b460a42ULL, - 0x7e77e49e52ee0849ULL, - 0xd62cd9663e76f255ULL, - 0xe9370f082451514bULL, - 0x50a1c674dd1b6029ULL, - 0x405db4575829eac4ULL, - 0x67b948764649eee7ULL, - 0x93731885419229d4ULL, - 0xdb0338bad72a4ce7ULL, - 0xa0a451f996fca4c8ULL, - 0xb4508ea668400a45ULL, - 0xbff28c5c7a142423ULL, - 0x4f31b42b96f3a431ULL, - 0x2ce6789d4ea1ff37ULL, - 0xfa150b52e4f82a3cULL, - 0xe9ec40449e6ed4f3ULL, - 0x5ceca87836fe2251ULL, - 0x66f50de463ee238cULL, - 0x42823efcd59ab511ULL, - }, - // extra - { - 0xe9e14cd2, - 0x865bb640, - 0x9f3f0b3e, - 0x94a71c52, - 0x3c012f19, - 0x6436637c, - 0x46ccedcb, - 0x7b341be7, - } - } -}; - -static const uint8_t arm_expected_contents[] = { - 0x6a, 0x9e, 0x1b, 0x59, - 0xde, 0x94, 0x15, 0xa2, - 0x25, 0x8a, 0x0d, 0x82, - 0xb2, 0x33, 0xe1, 0xc4, - 0x02, 0x1c, 0x3a, 0x17, - 0x75, 0xb1, 0x5f, 0x10, - 0x3f, 0x79, 0x71, 0xe8, - 0xb3, 0x70, 0xef, 0x5d, - 0x23, 0xa6, 0xe3, 0xce, - 0xb8, 0xa9, 0x3a, 0x7b, - 0x37, 0x85, 0x51, 0x52, - 0xc5, 0x12, 0x70, 0x62, - 0xcc, 0x3d, 0x72, 0x22, - 0x71, 0xc9, 0xfc, 0x16, - 0xcb, 0x8b, 0x98, 0x20, - 0x6b, 0x80, 0xab, 0xf1, - 0x03, 0xfc, 0xd5, 0x99, - 0x11, 0xf5, 0x0d, 0xb7, - 0xb5, 0xe6, 0x77, 0x10, - 0xce, 0xf7, 0xe1, 0xa1, - 0xde, 0xfb, 0xd7, 0xee, - 0x02, 0xd0, 0xb8, 0xbc, - 0x7f, 0xe9, 0x6a, 0xb9, - 0x43, 0x6a, 0xd2, 0x4d, - 0x1c, 0x74, 0x31, 0x8b, - 0xdb, 0x22, 0xec, 0x8e, - 0xa0, 0x66, 0xad, 0xc5, - 0xd7, 0x4b, 0x63, 0xfd, - 0xbe, 0xde, 0xb3, 0xae, - 0x0d, 0xda, 0x81, 0x16, - 0x71, 0x0b, 0x2d, 0xf7, - 0xbd, 0x32, 0x4a, 0x47, - 0x34, 0x48, 0x04, 0xb1, - 0xf8, 0x64, 0xf4, 0xca, - 0x2a, 0x58, 0xc7, 0xe5, - 0x2a, 0x59, 0xa6, 0xca, - 0xdb, 0xc3, 0x77, 0xd8, - 0x89, 0x68, 0xe4, 0x4e, - 0xf5, 0x5c, 0x64, 0x01, - 0xf3, 0x0c, 0x93, 0xf8, - 0xc7, 0xf7, 0x27, 0xba, - 0xeb, 0xe9, 0xa7, 0x4d, - 0xa3, 0x4d, 0x94, 0x61, - 0x27, 0xb0, 0xa7, 0x69, - 0x06, 0x5c, 0x19, 0x78, - 0x2e, 0x2b, 0xda, 0x2c, - 0x42, 0x0a, 0x46, 0x9b, - 0xab, 0x27, 0xb2, 0x66, - 0x49, 0x08, 0xee, 0x52, - 0x9e, 0xe4, 0x77, 0x7e, - 0x55, 0xf2, 0x76, 0x3e, - 0x66, 0xd9, 0x2c, 0xd6, - 0x4b, 0x51, 0x51, 0x24, - 0x08, 0x0f, 0x37, 0xe9, - 0x29, 0x60, 0x1b, 0xdd, - 0x74, 0xc6, 0xa1, 0x50, - 0xc4, 0xea, 0x29, 0x58, - 0x57, 0xb4, 0x5d, 0x40, - 0xe7, 0xee, 0x49, 0x46, - 0x76, 0x48, 0xb9, 0x67, - 0xd4, 0x29, 0x92, 0x41, - 0x85, 0x18, 0x73, 0x93, - 0xe7, 0x4c, 0x2a, 0xd7, - 0xba, 0x38, 0x03, 0xdb, - 0xc8, 0xa4, 0xfc, 0x96, - 0xf9, 0x51, 0xa4, 0xa0, - 0x45, 0x0a, 0x40, 0x68, - 0xa6, 0x8e, 0x50, 0xb4, - 0x23, 0x24, 0x14, 0x7a, - 0x5c, 0x8c, 0xf2, 0xbf, - 0x31, 0xa4, 0xf3, 0x96, - 0x2b, 0xb4, 0x31, 0x4f, - 0x37, 0xff, 0xa1, 0x4e, - 0x9d, 0x78, 0xe6, 0x2c, - 0x3c, 0x2a, 0xf8, 0xe4, - 0x52, 0x0b, 0x15, 0xfa, - 0xf3, 0xd4, 0x6e, 0x9e, - 0x44, 0x40, 0xec, 0xe9, - 0x51, 0x22, 0xfe, 0x36, - 0x78, 0xa8, 0xec, 0x5c, - 0x8c, 0x23, 0xee, 0x63, - 0xe4, 0x0d, 0xf5, 0x66, - 0x11, 0xb5, 0x9a, 0xd5, - 0xfc, 0x3e, 0x82, 0x42, - 0xd2, 0x4c, 0xe1, 0xe9, - 0x40, 0xb6, 0x5b, 0x86, - 0x3e, 0x0b, 0x3f, 0x9f, - 0x52, 0x1c, 0xa7, 0x94, - 0x19, 0x2f, 0x01, 0x3c, - 0x7c, 0x63, 0x36, 0x64, - 0xcb, 0xed, 0xcc, 0x46, - 0xe7, 0x1b, 0x34, 0x7b -}; - -#endif // PROCESSOR_SYNTH_MINIDUMP_UNITTEST_DATA_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/tokenize.cc b/toolkit/crashreporter/google-breakpad/src/processor/tokenize.cc deleted file mode 100644 index 8fce87a22..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/tokenize.cc +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (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 <string.h> - -#include <string> -#include <vector> - -#include "common/using_std_string.h" - -namespace google_breakpad { - -#ifdef _MSC_VER -#define strtok_r strtok_s -#endif - -using std::vector; - -bool Tokenize(char *line, - const char *separators, - int max_tokens, - vector<char*> *tokens) { - tokens->clear(); - tokens->reserve(max_tokens); - - int remaining = max_tokens; - - // Split tokens on the separator character. - // strip them out before exhausting max_tokens. - char *save_ptr; - char *token = strtok_r(line, separators, &save_ptr); - while (token && --remaining > 0) { - tokens->push_back(token); - if (remaining > 1) - token = strtok_r(NULL, separators, &save_ptr); - } - - // If there's anything left, just add it as a single token. - if (remaining == 0 && (token = strtok_r(NULL, "\r\n", &save_ptr))) { - tokens->push_back(token); - } - - return tokens->size() == static_cast<unsigned int>(max_tokens); -} - -void StringToVector(const string &str, vector<char> &vec) { - vec.resize(str.length() + 1); - std::copy(str.begin(), str.end(), - vec.begin()); - vec[str.length()] = '\0'; -} - -} // namespace google_breakpad diff --git a/toolkit/crashreporter/google-breakpad/src/processor/tokenize.h b/toolkit/crashreporter/google-breakpad/src/processor/tokenize.h deleted file mode 100644 index 9ff571d5c..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/tokenize.h +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2010, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -// Implements a Tokenize function for splitting up strings. - -#ifndef GOOGLE_BREAKPAD_PROCESSOR_TOKENIZE_H_ -#define GOOGLE_BREAKPAD_PROCESSOR_TOKENIZE_H_ - -#include <string> -#include <vector> - -#include "common/using_std_string.h" - -namespace google_breakpad { - -// Splits line into at most max_tokens tokens, separated by any of the -// characters in separators and placing them in the tokens vector. -// line is a 0-terminated string that optionally ends with a newline -// character or combination, which will be removed. -// If more tokens than max_tokens are present, the final token is placed -// into the vector without splitting it up at all. This modifies line as -// a side effect. Returns true if exactly max_tokens tokens are returned, -// and false if fewer are returned. This is not considered a failure of -// Tokenize, but may be treated as a failure if the caller expects an -// exact, as opposed to maximum, number of tokens. - -bool Tokenize(char *line, - const char *separators, - int max_tokens, - std::vector<char*> *tokens); -// For convenience, since you need a char* to pass to Tokenize. -// You can call StringToVector on a string, and use &vec[0]. -void StringToVector(const string &str, std::vector<char> &vec); - -} // namespace google_breakpad - -#endif // GOOGLE_BREAKPAD_PROCESSOR_TOKENIZE_H_ diff --git a/toolkit/crashreporter/google-breakpad/src/processor/windows_frame_info.h b/toolkit/crashreporter/google-breakpad/src/processor/windows_frame_info.h deleted file mode 100644 index f96e0a438..000000000 --- a/toolkit/crashreporter/google-breakpad/src/processor/windows_frame_info.h +++ /dev/null @@ -1,209 +0,0 @@ -// Copyright (c) 2006, Google Inc. -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// * Redistributions of source code must retain the above copyright -// notice, this list of conditions and the following disclaimer. -// * Redistributions in binary form must reproduce the above -// copyright notice, this list of conditions and the following disclaimer -// in the documentation and/or other materials provided with the -// distribution. -// * Neither the name of Google Inc. nor the names of its -// contributors may be used to endorse or promote products derived from -// this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -// windows_frame_info.h: Holds debugging information about a stack frame. -// -// This structure is specific to Windows debugging information obtained -// from pdb files using the DIA API. -// -// Author: Mark Mentovai - - -#ifndef PROCESSOR_WINDOWS_FRAME_INFO_H__ -#define PROCESSOR_WINDOWS_FRAME_INFO_H__ - -#include <string.h> -#include <stdlib.h> - -#include <string> -#include <vector> - -#include "common/using_std_string.h" -#include "google_breakpad/common/breakpad_types.h" -#include "processor/logging.h" -#include "processor/tokenize.h" - -namespace google_breakpad { - -#ifdef _WIN32 -#define strtoull _strtoui64 -#endif - -struct WindowsFrameInfo { - public: - enum Validity { - VALID_NONE = 0, - VALID_PARAMETER_SIZE = 1, - VALID_ALL = -1 - }; - - // The types for stack_info_. This is equivalent to MS DIA's - // StackFrameTypeEnum. Each identifies a different type of frame - // information, although all are represented in the symbol file in the - // same format. These are used as indices to the stack_info_ array. - enum StackInfoTypes { - STACK_INFO_FPO = 0, - STACK_INFO_TRAP, // not used here - STACK_INFO_TSS, // not used here - STACK_INFO_STANDARD, - STACK_INFO_FRAME_DATA, - STACK_INFO_LAST, // must be the last sequentially-numbered item - STACK_INFO_UNKNOWN = -1 - }; - - WindowsFrameInfo() : type_(STACK_INFO_UNKNOWN), - valid(VALID_NONE), - prolog_size(0), - epilog_size(0), - parameter_size(0), - saved_register_size(0), - local_size(0), - max_stack_size(0), - allocates_base_pointer(0), - program_string() {} - - WindowsFrameInfo(StackInfoTypes type, - uint32_t set_prolog_size, - uint32_t set_epilog_size, - uint32_t set_parameter_size, - uint32_t set_saved_register_size, - uint32_t set_local_size, - uint32_t set_max_stack_size, - int set_allocates_base_pointer, - const string set_program_string) - : type_(type), - valid(VALID_ALL), - prolog_size(set_prolog_size), - epilog_size(set_epilog_size), - parameter_size(set_parameter_size), - saved_register_size(set_saved_register_size), - local_size(set_local_size), - max_stack_size(set_max_stack_size), - allocates_base_pointer(set_allocates_base_pointer), - program_string(set_program_string) {} - - // Parse a textual serialization of a WindowsFrameInfo object from - // a string. Returns NULL if parsing fails, or a new object - // otherwise. type, rva and code_size are present in the STACK line, - // but not the StackFrameInfo structure, so return them as outparams. - static WindowsFrameInfo *ParseFromString(const string string, - int &type, - uint64_t &rva, - uint64_t &code_size) { - // The format of a STACK WIN record is documented at: - // - // https://chromium.googlesource.com/breakpad/breakpad/+/master/docs/symbol_files.md - - std::vector<char> buffer; - StringToVector(string, buffer); - std::vector<char*> tokens; - if (!Tokenize(&buffer[0], " \r\n", 11, &tokens)) - return NULL; - - type = strtol(tokens[0], NULL, 16); - if (type < 0 || type > STACK_INFO_LAST - 1) - return NULL; - - rva = strtoull(tokens[1], NULL, 16); - code_size = strtoull(tokens[2], NULL, 16); - uint32_t prolog_size = strtoul(tokens[3], NULL, 16); - uint32_t epilog_size = strtoul(tokens[4], NULL, 16); - uint32_t parameter_size = strtoul(tokens[5], NULL, 16); - uint32_t saved_register_size = strtoul(tokens[6], NULL, 16); - uint32_t local_size = strtoul(tokens[7], NULL, 16); - uint32_t max_stack_size = strtoul(tokens[8], NULL, 16); - int has_program_string = strtoul(tokens[9], NULL, 16); - - const char *program_string = ""; - int allocates_base_pointer = 0; - if (has_program_string) { - program_string = tokens[10]; - } else { - allocates_base_pointer = strtoul(tokens[10], NULL, 16); - } - - return new WindowsFrameInfo(static_cast<StackInfoTypes>(type), - prolog_size, - epilog_size, - parameter_size, - saved_register_size, - local_size, - max_stack_size, - allocates_base_pointer, - program_string); - } - - // CopyFrom makes "this" WindowsFrameInfo object identical to "that". - void CopyFrom(const WindowsFrameInfo &that) { - type_ = that.type_; - valid = that.valid; - prolog_size = that.prolog_size; - epilog_size = that.epilog_size; - parameter_size = that.parameter_size; - saved_register_size = that.saved_register_size; - local_size = that.local_size; - max_stack_size = that.max_stack_size; - allocates_base_pointer = that.allocates_base_pointer; - program_string = that.program_string; - } - - // Clears the WindowsFrameInfo object so that users will see it as though - // it contains no information. - void Clear() { - type_ = STACK_INFO_UNKNOWN; - valid = VALID_NONE; - program_string.erase(); - } - - StackInfoTypes type_; - - // Identifies which fields in the structure are valid. This is of - // type Validity, but it is defined as an int because it's not - // possible to OR values into an enumerated type. Users must check - // this field before using any other. - int valid; - - // These values come from IDiaFrameData. - uint32_t prolog_size; - uint32_t epilog_size; - uint32_t parameter_size; - uint32_t saved_register_size; - uint32_t local_size; - uint32_t max_stack_size; - - // Only one of allocates_base_pointer or program_string will be valid. - // If program_string is empty, use allocates_base_pointer. - bool allocates_base_pointer; - string program_string; -}; - -} // namespace google_breakpad - - -#endif // PROCESSOR_WINDOWS_FRAME_INFO_H__ |