Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
michael@0 | 1 | // Copyright (c) 2010 Google Inc. |
michael@0 | 2 | // All rights reserved. |
michael@0 | 3 | // |
michael@0 | 4 | // Redistribution and use in source and binary forms, with or without |
michael@0 | 5 | // modification, are permitted provided that the following conditions are |
michael@0 | 6 | // met: |
michael@0 | 7 | // |
michael@0 | 8 | // * Redistributions of source code must retain the above copyright |
michael@0 | 9 | // notice, this list of conditions and the following disclaimer. |
michael@0 | 10 | // * Redistributions in binary form must reproduce the above |
michael@0 | 11 | // copyright notice, this list of conditions and the following disclaimer |
michael@0 | 12 | // in the documentation and/or other materials provided with the |
michael@0 | 13 | // distribution. |
michael@0 | 14 | // * Neither the name of Google Inc. nor the names of its |
michael@0 | 15 | // contributors may be used to endorse or promote products derived from |
michael@0 | 16 | // this software without specific prior written permission. |
michael@0 | 17 | // |
michael@0 | 18 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
michael@0 | 19 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
michael@0 | 20 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
michael@0 | 21 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
michael@0 | 22 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
michael@0 | 23 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
michael@0 | 24 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
michael@0 | 25 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
michael@0 | 26 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
michael@0 | 27 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
michael@0 | 28 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
michael@0 | 29 | |
michael@0 | 30 | // minidump.h: A minidump reader. |
michael@0 | 31 | // |
michael@0 | 32 | // The basic structure of this module tracks the structure of the minidump |
michael@0 | 33 | // file itself. At the top level, a minidump file is represented by a |
michael@0 | 34 | // Minidump object. Like most other classes in this module, Minidump |
michael@0 | 35 | // provides a Read method that initializes the object with information from |
michael@0 | 36 | // the file. Most of the classes in this file are wrappers around the |
michael@0 | 37 | // "raw" structures found in the minidump file itself, and defined in |
michael@0 | 38 | // minidump_format.h. For example, each thread is represented by a |
michael@0 | 39 | // MinidumpThread object, whose parameters are specified in an MDRawThread |
michael@0 | 40 | // structure. A properly byte-swapped MDRawThread can be obtained from a |
michael@0 | 41 | // MinidumpThread easily by calling its thread() method. |
michael@0 | 42 | // |
michael@0 | 43 | // Most of the module lazily reads only the portion of the minidump file |
michael@0 | 44 | // necessary to fulfill the user's request. Calling Minidump::Read |
michael@0 | 45 | // only reads the minidump's directory. The thread list is not read until |
michael@0 | 46 | // it is needed, and even once it's read, the memory regions for each |
michael@0 | 47 | // thread's stack aren't read until they're needed. This strategy avoids |
michael@0 | 48 | // unnecessary file input, and allocating memory for data in which the user |
michael@0 | 49 | // has no interest. Note that although memory allocations for a typical |
michael@0 | 50 | // minidump file are not particularly large, it is possible for legitimate |
michael@0 | 51 | // minidumps to be sizable. A full-memory minidump, for example, contains |
michael@0 | 52 | // a snapshot of the entire mapped memory space. Even a normal minidump, |
michael@0 | 53 | // with stack memory only, can be large if, for example, the dump was |
michael@0 | 54 | // generated in response to a crash that occurred due to an infinite- |
michael@0 | 55 | // recursion bug that caused the stack's limits to be exceeded. Finally, |
michael@0 | 56 | // some users of this library will unfortunately find themselves in the |
michael@0 | 57 | // position of having to process potentially-hostile minidumps that might |
michael@0 | 58 | // attempt to cause problems by forcing the minidump processor to over- |
michael@0 | 59 | // allocate memory. |
michael@0 | 60 | // |
michael@0 | 61 | // Memory management in this module is based on a strict |
michael@0 | 62 | // you-don't-own-anything policy. The only object owned by the user is |
michael@0 | 63 | // the top-level Minidump object, the creation and destruction of which |
michael@0 | 64 | // must be the user's own responsibility. All other objects obtained |
michael@0 | 65 | // through interaction with this module are ultimately owned by the |
michael@0 | 66 | // Minidump object, and will be freed upon the Minidump object's destruction. |
michael@0 | 67 | // Because memory regions can potentially involve large allocations, a |
michael@0 | 68 | // FreeMemory method is provided by MinidumpMemoryRegion, allowing the user |
michael@0 | 69 | // to release data when it is no longer needed. Use of this method is |
michael@0 | 70 | // optional but recommended. If freed data is later required, it will |
michael@0 | 71 | // be read back in from the minidump file again. |
michael@0 | 72 | // |
michael@0 | 73 | // There is one exception to this memory management policy: |
michael@0 | 74 | // Minidump::ReadString will return a string object to the user, and the user |
michael@0 | 75 | // is responsible for its deletion. |
michael@0 | 76 | // |
michael@0 | 77 | // Author: Mark Mentovai |
michael@0 | 78 | |
michael@0 | 79 | #ifndef GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ |
michael@0 | 80 | #define GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ |
michael@0 | 81 | |
michael@0 | 82 | #ifndef _WIN32 |
michael@0 | 83 | #include <unistd.h> |
michael@0 | 84 | #endif |
michael@0 | 85 | |
michael@0 | 86 | #include <iostream> |
michael@0 | 87 | #include <map> |
michael@0 | 88 | #include <string> |
michael@0 | 89 | #include <vector> |
michael@0 | 90 | |
michael@0 | 91 | #include "common/using_std_string.h" |
michael@0 | 92 | #include "google_breakpad/common/minidump_format.h" |
michael@0 | 93 | #include "google_breakpad/processor/code_module.h" |
michael@0 | 94 | #include "google_breakpad/processor/code_modules.h" |
michael@0 | 95 | #include "google_breakpad/processor/memory_region.h" |
michael@0 | 96 | |
michael@0 | 97 | |
michael@0 | 98 | namespace google_breakpad { |
michael@0 | 99 | |
michael@0 | 100 | |
michael@0 | 101 | using std::map; |
michael@0 | 102 | using std::vector; |
michael@0 | 103 | |
michael@0 | 104 | |
michael@0 | 105 | class Minidump; |
michael@0 | 106 | template<typename AddressType, typename EntryType> class RangeMap; |
michael@0 | 107 | |
michael@0 | 108 | |
michael@0 | 109 | // MinidumpObject is the base of all Minidump* objects except for Minidump |
michael@0 | 110 | // itself. |
michael@0 | 111 | class MinidumpObject { |
michael@0 | 112 | public: |
michael@0 | 113 | virtual ~MinidumpObject() {} |
michael@0 | 114 | |
michael@0 | 115 | bool valid() const { return valid_; } |
michael@0 | 116 | |
michael@0 | 117 | protected: |
michael@0 | 118 | explicit MinidumpObject(Minidump* minidump); |
michael@0 | 119 | |
michael@0 | 120 | // Refers to the Minidump object that is the ultimate parent of this |
michael@0 | 121 | // Some MinidumpObjects are owned by other MinidumpObjects, but at the |
michael@0 | 122 | // root of the ownership tree is always a Minidump. The Minidump object |
michael@0 | 123 | // is kept here for access to its seeking and reading facilities, and |
michael@0 | 124 | // for access to data about the minidump file itself, such as whether |
michael@0 | 125 | // it should be byte-swapped. |
michael@0 | 126 | Minidump* minidump_; |
michael@0 | 127 | |
michael@0 | 128 | // MinidumpObjects are not valid when created. When a subclass populates |
michael@0 | 129 | // its own fields, it can set valid_ to true. Accessors and mutators may |
michael@0 | 130 | // wish to consider or alter the valid_ state as they interact with |
michael@0 | 131 | // objects. |
michael@0 | 132 | bool valid_; |
michael@0 | 133 | }; |
michael@0 | 134 | |
michael@0 | 135 | |
michael@0 | 136 | // This class exists primarily to provide a virtual destructor in a base |
michael@0 | 137 | // class common to all objects that might be stored in |
michael@0 | 138 | // Minidump::mStreamObjects. Some object types (MinidumpContext) will |
michael@0 | 139 | // never be stored in Minidump::mStreamObjects, but are represented as |
michael@0 | 140 | // streams and adhere to the same interface, and may be derived from |
michael@0 | 141 | // this class. |
michael@0 | 142 | class MinidumpStream : public MinidumpObject { |
michael@0 | 143 | public: |
michael@0 | 144 | virtual ~MinidumpStream() {} |
michael@0 | 145 | |
michael@0 | 146 | protected: |
michael@0 | 147 | explicit MinidumpStream(Minidump* minidump); |
michael@0 | 148 | |
michael@0 | 149 | private: |
michael@0 | 150 | // Populate (and validate) the MinidumpStream. minidump_ is expected |
michael@0 | 151 | // to be positioned at the beginning of the stream, so that the next |
michael@0 | 152 | // read from the minidump will be at the beginning of the stream. |
michael@0 | 153 | // expected_size should be set to the stream's length as contained in |
michael@0 | 154 | // the MDRawDirectory record or other identifying record. A class |
michael@0 | 155 | // that implements MinidumpStream can compare expected_size to a |
michael@0 | 156 | // known size as an integrity check. |
michael@0 | 157 | virtual bool Read(uint32_t expected_size) = 0; |
michael@0 | 158 | }; |
michael@0 | 159 | |
michael@0 | 160 | |
michael@0 | 161 | // MinidumpContext carries a CPU-specific MDRawContext structure, which |
michael@0 | 162 | // contains CPU context such as register states. Each thread has its |
michael@0 | 163 | // own context, and the exception record, if present, also has its own |
michael@0 | 164 | // context. Note that if the exception record is present, the context it |
michael@0 | 165 | // refers to is probably what the user wants to use for the exception |
michael@0 | 166 | // thread, instead of that thread's own context. The exception thread's |
michael@0 | 167 | // context (as opposed to the exception record's context) will contain |
michael@0 | 168 | // context for the exception handler (which performs minidump generation), |
michael@0 | 169 | // and not the context that caused the exception (which is probably what the |
michael@0 | 170 | // user wants). |
michael@0 | 171 | class MinidumpContext : public MinidumpStream { |
michael@0 | 172 | public: |
michael@0 | 173 | virtual ~MinidumpContext(); |
michael@0 | 174 | |
michael@0 | 175 | // Returns an MD_CONTEXT_* value such as MD_CONTEXT_X86 or MD_CONTEXT_PPC |
michael@0 | 176 | // identifying the CPU type that the context was collected from. The |
michael@0 | 177 | // returned value will identify the CPU only, and will have any other |
michael@0 | 178 | // MD_CONTEXT_* bits masked out. Returns 0 on failure. |
michael@0 | 179 | uint32_t GetContextCPU() const; |
michael@0 | 180 | |
michael@0 | 181 | // A convenience method to get the instruction pointer out of the |
michael@0 | 182 | // MDRawContext, since it varies per-CPU architecture. |
michael@0 | 183 | bool GetInstructionPointer(uint64_t* ip) const; |
michael@0 | 184 | |
michael@0 | 185 | // Returns raw CPU-specific context data for the named CPU type. If the |
michael@0 | 186 | // context data does not match the CPU type or does not exist, returns |
michael@0 | 187 | // NULL. |
michael@0 | 188 | const MDRawContextAMD64* GetContextAMD64() const; |
michael@0 | 189 | const MDRawContextARM* GetContextARM() const; |
michael@0 | 190 | const MDRawContextPPC* GetContextPPC() const; |
michael@0 | 191 | const MDRawContextSPARC* GetContextSPARC() const; |
michael@0 | 192 | const MDRawContextX86* GetContextX86() const; |
michael@0 | 193 | |
michael@0 | 194 | // Print a human-readable representation of the object to stdout. |
michael@0 | 195 | void Print(); |
michael@0 | 196 | |
michael@0 | 197 | protected: |
michael@0 | 198 | explicit MinidumpContext(Minidump* minidump); |
michael@0 | 199 | |
michael@0 | 200 | // The CPU-specific context structure. |
michael@0 | 201 | union { |
michael@0 | 202 | MDRawContextBase* base; |
michael@0 | 203 | MDRawContextX86* x86; |
michael@0 | 204 | MDRawContextPPC* ppc; |
michael@0 | 205 | MDRawContextAMD64* amd64; |
michael@0 | 206 | // on Solaris SPARC, sparc is defined as a numeric constant, |
michael@0 | 207 | // so variables can NOT be named as sparc |
michael@0 | 208 | MDRawContextSPARC* ctx_sparc; |
michael@0 | 209 | MDRawContextARM* arm; |
michael@0 | 210 | } context_; |
michael@0 | 211 | |
michael@0 | 212 | // Store this separately because of the weirdo AMD64 context |
michael@0 | 213 | uint32_t context_flags_; |
michael@0 | 214 | |
michael@0 | 215 | private: |
michael@0 | 216 | friend class MinidumpThread; |
michael@0 | 217 | friend class MinidumpException; |
michael@0 | 218 | |
michael@0 | 219 | bool Read(uint32_t expected_size); |
michael@0 | 220 | |
michael@0 | 221 | // Free the CPU-specific context structure. |
michael@0 | 222 | void FreeContext(); |
michael@0 | 223 | |
michael@0 | 224 | // If the minidump contains a SYSTEM_INFO_STREAM, makes sure that the |
michael@0 | 225 | // system info stream gives an appropriate CPU type matching the context |
michael@0 | 226 | // CPU type in context_cpu_type. Returns false if the CPU type does not |
michael@0 | 227 | // match. Returns true if the CPU type matches or if the minidump does |
michael@0 | 228 | // not contain a system info stream. |
michael@0 | 229 | bool CheckAgainstSystemInfo(uint32_t context_cpu_type); |
michael@0 | 230 | }; |
michael@0 | 231 | |
michael@0 | 232 | |
michael@0 | 233 | // MinidumpMemoryRegion does not wrap any MDRaw structure, and only contains |
michael@0 | 234 | // a reference to an MDMemoryDescriptor. This object is intended to wrap |
michael@0 | 235 | // portions of a minidump file that contain memory dumps. In normal |
michael@0 | 236 | // minidumps, each MinidumpThread owns a MinidumpMemoryRegion corresponding |
michael@0 | 237 | // to the thread's stack memory. MinidumpMemoryList also gives access to |
michael@0 | 238 | // memory regions in its list as MinidumpMemoryRegions. This class |
michael@0 | 239 | // adheres to MemoryRegion so that it may be used as a data provider to |
michael@0 | 240 | // the Stackwalker family of classes. |
michael@0 | 241 | class MinidumpMemoryRegion : public MinidumpObject, |
michael@0 | 242 | public MemoryRegion { |
michael@0 | 243 | public: |
michael@0 | 244 | virtual ~MinidumpMemoryRegion(); |
michael@0 | 245 | |
michael@0 | 246 | static void set_max_bytes(uint32_t max_bytes) { max_bytes_ = max_bytes; } |
michael@0 | 247 | static uint32_t max_bytes() { return max_bytes_; } |
michael@0 | 248 | |
michael@0 | 249 | // Returns a pointer to the base of the memory region. Returns the |
michael@0 | 250 | // cached value if available, otherwise, reads the minidump file and |
michael@0 | 251 | // caches the memory region. |
michael@0 | 252 | const uint8_t* GetMemory() const; |
michael@0 | 253 | |
michael@0 | 254 | // The address of the base of the memory region. |
michael@0 | 255 | uint64_t GetBase() const; |
michael@0 | 256 | |
michael@0 | 257 | // The size, in bytes, of the memory region. |
michael@0 | 258 | uint32_t GetSize() const; |
michael@0 | 259 | |
michael@0 | 260 | // Frees the cached memory region, if cached. |
michael@0 | 261 | void FreeMemory(); |
michael@0 | 262 | |
michael@0 | 263 | // Obtains the value of memory at the pointer specified by address. |
michael@0 | 264 | bool GetMemoryAtAddress(uint64_t address, uint8_t* value) const; |
michael@0 | 265 | bool GetMemoryAtAddress(uint64_t address, uint16_t* value) const; |
michael@0 | 266 | bool GetMemoryAtAddress(uint64_t address, uint32_t* value) const; |
michael@0 | 267 | bool GetMemoryAtAddress(uint64_t address, uint64_t* value) const; |
michael@0 | 268 | |
michael@0 | 269 | // Print a human-readable representation of the object to stdout. |
michael@0 | 270 | void Print(); |
michael@0 | 271 | |
michael@0 | 272 | protected: |
michael@0 | 273 | explicit MinidumpMemoryRegion(Minidump* minidump); |
michael@0 | 274 | |
michael@0 | 275 | private: |
michael@0 | 276 | friend class MinidumpThread; |
michael@0 | 277 | friend class MinidumpMemoryList; |
michael@0 | 278 | |
michael@0 | 279 | // Identify the base address and size of the memory region, and the |
michael@0 | 280 | // location it may be found in the minidump file. |
michael@0 | 281 | void SetDescriptor(MDMemoryDescriptor* descriptor); |
michael@0 | 282 | |
michael@0 | 283 | // Implementation for GetMemoryAtAddress |
michael@0 | 284 | template<typename T> bool GetMemoryAtAddressInternal(uint64_t address, |
michael@0 | 285 | T* value) const; |
michael@0 | 286 | |
michael@0 | 287 | // The largest memory region that will be read from a minidump. The |
michael@0 | 288 | // default is 1MB. |
michael@0 | 289 | static uint32_t max_bytes_; |
michael@0 | 290 | |
michael@0 | 291 | // Base address and size of the memory region, and its position in the |
michael@0 | 292 | // minidump file. |
michael@0 | 293 | MDMemoryDescriptor* descriptor_; |
michael@0 | 294 | |
michael@0 | 295 | // Cached memory. |
michael@0 | 296 | mutable vector<uint8_t>* memory_; |
michael@0 | 297 | }; |
michael@0 | 298 | |
michael@0 | 299 | |
michael@0 | 300 | // MinidumpThread contains information about a thread of execution, |
michael@0 | 301 | // including a snapshot of the thread's stack and CPU context. For |
michael@0 | 302 | // the thread that caused an exception, the context carried by |
michael@0 | 303 | // MinidumpException is probably desired instead of the CPU context |
michael@0 | 304 | // provided here. |
michael@0 | 305 | // Note that a MinidumpThread may be valid() even if it does not |
michael@0 | 306 | // contain a memory region or context. |
michael@0 | 307 | class MinidumpThread : public MinidumpObject { |
michael@0 | 308 | public: |
michael@0 | 309 | virtual ~MinidumpThread(); |
michael@0 | 310 | |
michael@0 | 311 | const MDRawThread* thread() const { return valid_ ? &thread_ : NULL; } |
michael@0 | 312 | // GetMemory may return NULL even if the MinidumpThread is valid, |
michael@0 | 313 | // if the thread memory cannot be read. |
michael@0 | 314 | virtual MinidumpMemoryRegion* GetMemory(); |
michael@0 | 315 | // GetContext may return NULL even if the MinidumpThread is valid. |
michael@0 | 316 | virtual MinidumpContext* GetContext(); |
michael@0 | 317 | |
michael@0 | 318 | // The thread ID is used to determine if a thread is the exception thread, |
michael@0 | 319 | // so a special getter is provided to retrieve this data from the |
michael@0 | 320 | // MDRawThread structure. Returns false if the thread ID cannot be |
michael@0 | 321 | // determined. |
michael@0 | 322 | virtual bool GetThreadID(uint32_t *thread_id) const; |
michael@0 | 323 | |
michael@0 | 324 | // Print a human-readable representation of the object to stdout. |
michael@0 | 325 | void Print(); |
michael@0 | 326 | |
michael@0 | 327 | protected: |
michael@0 | 328 | explicit MinidumpThread(Minidump* minidump); |
michael@0 | 329 | |
michael@0 | 330 | private: |
michael@0 | 331 | // These objects are managed by MinidumpThreadList. |
michael@0 | 332 | friend class MinidumpThreadList; |
michael@0 | 333 | |
michael@0 | 334 | // This works like MinidumpStream::Read, but is driven by |
michael@0 | 335 | // MinidumpThreadList. No size checking is done, because |
michael@0 | 336 | // MinidumpThreadList handles that directly. |
michael@0 | 337 | bool Read(); |
michael@0 | 338 | |
michael@0 | 339 | MDRawThread thread_; |
michael@0 | 340 | MinidumpMemoryRegion* memory_; |
michael@0 | 341 | MinidumpContext* context_; |
michael@0 | 342 | }; |
michael@0 | 343 | |
michael@0 | 344 | |
michael@0 | 345 | // MinidumpThreadList contains all of the threads (as MinidumpThreads) in |
michael@0 | 346 | // a process. |
michael@0 | 347 | class MinidumpThreadList : public MinidumpStream { |
michael@0 | 348 | public: |
michael@0 | 349 | virtual ~MinidumpThreadList(); |
michael@0 | 350 | |
michael@0 | 351 | static void set_max_threads(uint32_t max_threads) { |
michael@0 | 352 | max_threads_ = max_threads; |
michael@0 | 353 | } |
michael@0 | 354 | static uint32_t max_threads() { return max_threads_; } |
michael@0 | 355 | |
michael@0 | 356 | virtual unsigned int thread_count() const { |
michael@0 | 357 | return valid_ ? thread_count_ : 0; |
michael@0 | 358 | } |
michael@0 | 359 | |
michael@0 | 360 | // Sequential access to threads. |
michael@0 | 361 | virtual MinidumpThread* GetThreadAtIndex(unsigned int index) const; |
michael@0 | 362 | |
michael@0 | 363 | // Random access to threads. |
michael@0 | 364 | MinidumpThread* GetThreadByID(uint32_t thread_id); |
michael@0 | 365 | |
michael@0 | 366 | // Print a human-readable representation of the object to stdout. |
michael@0 | 367 | void Print(); |
michael@0 | 368 | |
michael@0 | 369 | protected: |
michael@0 | 370 | explicit MinidumpThreadList(Minidump* aMinidump); |
michael@0 | 371 | |
michael@0 | 372 | private: |
michael@0 | 373 | friend class Minidump; |
michael@0 | 374 | |
michael@0 | 375 | typedef map<uint32_t, MinidumpThread*> IDToThreadMap; |
michael@0 | 376 | typedef vector<MinidumpThread> MinidumpThreads; |
michael@0 | 377 | |
michael@0 | 378 | static const uint32_t kStreamType = MD_THREAD_LIST_STREAM; |
michael@0 | 379 | |
michael@0 | 380 | bool Read(uint32_t aExpectedSize); |
michael@0 | 381 | |
michael@0 | 382 | // The largest number of threads that will be read from a minidump. The |
michael@0 | 383 | // default is 256. |
michael@0 | 384 | static uint32_t max_threads_; |
michael@0 | 385 | |
michael@0 | 386 | // Access to threads using the thread ID as the key. |
michael@0 | 387 | IDToThreadMap id_to_thread_map_; |
michael@0 | 388 | |
michael@0 | 389 | // The list of threads. |
michael@0 | 390 | MinidumpThreads* threads_; |
michael@0 | 391 | uint32_t thread_count_; |
michael@0 | 392 | }; |
michael@0 | 393 | |
michael@0 | 394 | |
michael@0 | 395 | // MinidumpModule wraps MDRawModule, which contains information about loaded |
michael@0 | 396 | // code modules. Access is provided to various data referenced indirectly |
michael@0 | 397 | // by MDRawModule, such as the module's name and a specification for where |
michael@0 | 398 | // to locate debugging information for the module. |
michael@0 | 399 | class MinidumpModule : public MinidumpObject, |
michael@0 | 400 | public CodeModule { |
michael@0 | 401 | public: |
michael@0 | 402 | virtual ~MinidumpModule(); |
michael@0 | 403 | |
michael@0 | 404 | static void set_max_cv_bytes(uint32_t max_cv_bytes) { |
michael@0 | 405 | max_cv_bytes_ = max_cv_bytes; |
michael@0 | 406 | } |
michael@0 | 407 | static uint32_t max_cv_bytes() { return max_cv_bytes_; } |
michael@0 | 408 | |
michael@0 | 409 | static void set_max_misc_bytes(uint32_t max_misc_bytes) { |
michael@0 | 410 | max_misc_bytes_ = max_misc_bytes; |
michael@0 | 411 | } |
michael@0 | 412 | static uint32_t max_misc_bytes() { return max_misc_bytes_; } |
michael@0 | 413 | |
michael@0 | 414 | const MDRawModule* module() const { return valid_ ? &module_ : NULL; } |
michael@0 | 415 | |
michael@0 | 416 | // CodeModule implementation |
michael@0 | 417 | virtual uint64_t base_address() const { |
michael@0 | 418 | return valid_ ? module_.base_of_image : static_cast<uint64_t>(-1); |
michael@0 | 419 | } |
michael@0 | 420 | virtual uint64_t size() const { return valid_ ? module_.size_of_image : 0; } |
michael@0 | 421 | virtual string code_file() const; |
michael@0 | 422 | virtual string code_identifier() const; |
michael@0 | 423 | virtual string debug_file() const; |
michael@0 | 424 | virtual string debug_identifier() const; |
michael@0 | 425 | virtual string version() const; |
michael@0 | 426 | virtual const CodeModule* Copy() const; |
michael@0 | 427 | |
michael@0 | 428 | // The CodeView record, which contains information to locate the module's |
michael@0 | 429 | // debugging information (pdb). This is returned as uint8_t* because |
michael@0 | 430 | // the data can be of types MDCVInfoPDB20* or MDCVInfoPDB70*, or it may be |
michael@0 | 431 | // of a type unknown to Breakpad, in which case the raw data will still be |
michael@0 | 432 | // returned but no byte-swapping will have been performed. Check the |
michael@0 | 433 | // record's signature in the first four bytes to differentiate between |
michael@0 | 434 | // the various types. Current toolchains generate modules which carry |
michael@0 | 435 | // MDCVInfoPDB70 by default. Returns a pointer to the CodeView record on |
michael@0 | 436 | // success, and NULL on failure. On success, the optional |size| argument |
michael@0 | 437 | // is set to the size of the CodeView record. |
michael@0 | 438 | const uint8_t* GetCVRecord(uint32_t* size); |
michael@0 | 439 | |
michael@0 | 440 | // The miscellaneous debug record, which is obsolete. Current toolchains |
michael@0 | 441 | // do not generate this type of debugging information (dbg), and this |
michael@0 | 442 | // field is not expected to be present. Returns a pointer to the debugging |
michael@0 | 443 | // record on success, and NULL on failure. On success, the optional |size| |
michael@0 | 444 | // argument is set to the size of the debugging record. |
michael@0 | 445 | const MDImageDebugMisc* GetMiscRecord(uint32_t* size); |
michael@0 | 446 | |
michael@0 | 447 | // Print a human-readable representation of the object to stdout. |
michael@0 | 448 | void Print(); |
michael@0 | 449 | |
michael@0 | 450 | private: |
michael@0 | 451 | // These objects are managed by MinidumpModuleList. |
michael@0 | 452 | friend class MinidumpModuleList; |
michael@0 | 453 | |
michael@0 | 454 | explicit MinidumpModule(Minidump* minidump); |
michael@0 | 455 | |
michael@0 | 456 | // This works like MinidumpStream::Read, but is driven by |
michael@0 | 457 | // MinidumpModuleList. No size checking is done, because |
michael@0 | 458 | // MinidumpModuleList handles that directly. |
michael@0 | 459 | bool Read(); |
michael@0 | 460 | |
michael@0 | 461 | // Reads indirectly-referenced data, including the module name, CodeView |
michael@0 | 462 | // record, and miscellaneous debugging record. This is necessary to allow |
michael@0 | 463 | // MinidumpModuleList to fully construct MinidumpModule objects without |
michael@0 | 464 | // requiring seeks to read a contiguous set of MinidumpModule objects. |
michael@0 | 465 | // All auxiliary data should be available when Read is called, in order to |
michael@0 | 466 | // allow the CodeModule getters to be const methods. |
michael@0 | 467 | bool ReadAuxiliaryData(); |
michael@0 | 468 | |
michael@0 | 469 | // The largest number of bytes that will be read from a minidump for a |
michael@0 | 470 | // CodeView record or miscellaneous debugging record, respectively. The |
michael@0 | 471 | // default for each is 1024. |
michael@0 | 472 | static uint32_t max_cv_bytes_; |
michael@0 | 473 | static uint32_t max_misc_bytes_; |
michael@0 | 474 | |
michael@0 | 475 | // True after a successful Read. This is different from valid_, which is |
michael@0 | 476 | // not set true until ReadAuxiliaryData also completes successfully. |
michael@0 | 477 | // module_valid_ is only used by ReadAuxiliaryData and the functions it |
michael@0 | 478 | // calls to determine whether the object is ready for auxiliary data to |
michael@0 | 479 | // be read. |
michael@0 | 480 | bool module_valid_; |
michael@0 | 481 | |
michael@0 | 482 | // True if debug info was read from the module. Certain modules |
michael@0 | 483 | // may contain debug records in formats we don't support, |
michael@0 | 484 | // so we can just set this to false to ignore them. |
michael@0 | 485 | bool has_debug_info_; |
michael@0 | 486 | |
michael@0 | 487 | MDRawModule module_; |
michael@0 | 488 | |
michael@0 | 489 | // Cached module name. |
michael@0 | 490 | const string* name_; |
michael@0 | 491 | |
michael@0 | 492 | // Cached CodeView record - this is MDCVInfoPDB20 or (likely) |
michael@0 | 493 | // MDCVInfoPDB70, or possibly something else entirely. Stored as a uint8_t |
michael@0 | 494 | // because the structure contains a variable-sized string and its exact |
michael@0 | 495 | // size cannot be known until it is processed. |
michael@0 | 496 | vector<uint8_t>* cv_record_; |
michael@0 | 497 | |
michael@0 | 498 | // If cv_record_ is present, cv_record_signature_ contains a copy of the |
michael@0 | 499 | // CodeView record's first four bytes, for ease of determinining the |
michael@0 | 500 | // type of structure that cv_record_ contains. |
michael@0 | 501 | uint32_t cv_record_signature_; |
michael@0 | 502 | |
michael@0 | 503 | // Cached MDImageDebugMisc (usually not present), stored as uint8_t |
michael@0 | 504 | // because the structure contains a variable-sized string and its exact |
michael@0 | 505 | // size cannot be known until it is processed. |
michael@0 | 506 | vector<uint8_t>* misc_record_; |
michael@0 | 507 | }; |
michael@0 | 508 | |
michael@0 | 509 | |
michael@0 | 510 | // MinidumpModuleList contains all of the loaded code modules for a process |
michael@0 | 511 | // in the form of MinidumpModules. It maintains a map of these modules |
michael@0 | 512 | // so that it may easily provide a code module corresponding to a specific |
michael@0 | 513 | // address. |
michael@0 | 514 | class MinidumpModuleList : public MinidumpStream, |
michael@0 | 515 | public CodeModules { |
michael@0 | 516 | public: |
michael@0 | 517 | virtual ~MinidumpModuleList(); |
michael@0 | 518 | |
michael@0 | 519 | static void set_max_modules(uint32_t max_modules) { |
michael@0 | 520 | max_modules_ = max_modules; |
michael@0 | 521 | } |
michael@0 | 522 | static uint32_t max_modules() { return max_modules_; } |
michael@0 | 523 | |
michael@0 | 524 | // CodeModules implementation. |
michael@0 | 525 | virtual unsigned int module_count() const { |
michael@0 | 526 | return valid_ ? module_count_ : 0; |
michael@0 | 527 | } |
michael@0 | 528 | virtual const MinidumpModule* GetModuleForAddress(uint64_t address) const; |
michael@0 | 529 | virtual const MinidumpModule* GetMainModule() const; |
michael@0 | 530 | virtual const MinidumpModule* GetModuleAtSequence( |
michael@0 | 531 | unsigned int sequence) const; |
michael@0 | 532 | virtual const MinidumpModule* GetModuleAtIndex(unsigned int index) const; |
michael@0 | 533 | virtual const CodeModules* Copy() const; |
michael@0 | 534 | |
michael@0 | 535 | // Print a human-readable representation of the object to stdout. |
michael@0 | 536 | void Print(); |
michael@0 | 537 | |
michael@0 | 538 | protected: |
michael@0 | 539 | explicit MinidumpModuleList(Minidump* minidump); |
michael@0 | 540 | |
michael@0 | 541 | private: |
michael@0 | 542 | friend class Minidump; |
michael@0 | 543 | |
michael@0 | 544 | typedef vector<MinidumpModule> MinidumpModules; |
michael@0 | 545 | |
michael@0 | 546 | static const uint32_t kStreamType = MD_MODULE_LIST_STREAM; |
michael@0 | 547 | |
michael@0 | 548 | bool Read(uint32_t expected_size); |
michael@0 | 549 | |
michael@0 | 550 | // The largest number of modules that will be read from a minidump. The |
michael@0 | 551 | // default is 1024. |
michael@0 | 552 | static uint32_t max_modules_; |
michael@0 | 553 | |
michael@0 | 554 | // Access to modules using addresses as the key. |
michael@0 | 555 | RangeMap<uint64_t, unsigned int> *range_map_; |
michael@0 | 556 | |
michael@0 | 557 | MinidumpModules *modules_; |
michael@0 | 558 | uint32_t module_count_; |
michael@0 | 559 | }; |
michael@0 | 560 | |
michael@0 | 561 | |
michael@0 | 562 | // MinidumpMemoryList corresponds to a minidump's MEMORY_LIST_STREAM stream, |
michael@0 | 563 | // which references the snapshots of all of the memory regions contained |
michael@0 | 564 | // within the minidump. For a normal minidump, this includes stack memory |
michael@0 | 565 | // (also referenced by each MinidumpThread, in fact, the MDMemoryDescriptors |
michael@0 | 566 | // here and in MDRawThread both point to exactly the same data in a |
michael@0 | 567 | // minidump file, conserving space), as well as a 256-byte snapshot of memory |
michael@0 | 568 | // surrounding the instruction pointer in the case of an exception. Other |
michael@0 | 569 | // types of minidumps may contain significantly more memory regions. Full- |
michael@0 | 570 | // memory minidumps contain all of a process' mapped memory. |
michael@0 | 571 | class MinidumpMemoryList : public MinidumpStream { |
michael@0 | 572 | public: |
michael@0 | 573 | virtual ~MinidumpMemoryList(); |
michael@0 | 574 | |
michael@0 | 575 | static void set_max_regions(uint32_t max_regions) { |
michael@0 | 576 | max_regions_ = max_regions; |
michael@0 | 577 | } |
michael@0 | 578 | static uint32_t max_regions() { return max_regions_; } |
michael@0 | 579 | |
michael@0 | 580 | unsigned int region_count() const { return valid_ ? region_count_ : 0; } |
michael@0 | 581 | |
michael@0 | 582 | // Sequential access to memory regions. |
michael@0 | 583 | MinidumpMemoryRegion* GetMemoryRegionAtIndex(unsigned int index); |
michael@0 | 584 | |
michael@0 | 585 | // Random access to memory regions. Returns the region encompassing |
michael@0 | 586 | // the address identified by address. |
michael@0 | 587 | MinidumpMemoryRegion* GetMemoryRegionForAddress(uint64_t address); |
michael@0 | 588 | |
michael@0 | 589 | // Print a human-readable representation of the object to stdout. |
michael@0 | 590 | void Print(); |
michael@0 | 591 | |
michael@0 | 592 | private: |
michael@0 | 593 | friend class Minidump; |
michael@0 | 594 | |
michael@0 | 595 | typedef vector<MDMemoryDescriptor> MemoryDescriptors; |
michael@0 | 596 | typedef vector<MinidumpMemoryRegion> MemoryRegions; |
michael@0 | 597 | |
michael@0 | 598 | static const uint32_t kStreamType = MD_MEMORY_LIST_STREAM; |
michael@0 | 599 | |
michael@0 | 600 | explicit MinidumpMemoryList(Minidump* minidump); |
michael@0 | 601 | |
michael@0 | 602 | bool Read(uint32_t expected_size); |
michael@0 | 603 | |
michael@0 | 604 | // The largest number of memory regions that will be read from a minidump. |
michael@0 | 605 | // The default is 256. |
michael@0 | 606 | static uint32_t max_regions_; |
michael@0 | 607 | |
michael@0 | 608 | // Access to memory regions using addresses as the key. |
michael@0 | 609 | RangeMap<uint64_t, unsigned int> *range_map_; |
michael@0 | 610 | |
michael@0 | 611 | // The list of descriptors. This is maintained separately from the list |
michael@0 | 612 | // of regions, because MemoryRegion doesn't own its MemoryDescriptor, it |
michael@0 | 613 | // maintains a pointer to it. descriptors_ provides the storage for this |
michael@0 | 614 | // purpose. |
michael@0 | 615 | MemoryDescriptors *descriptors_; |
michael@0 | 616 | |
michael@0 | 617 | // The list of regions. |
michael@0 | 618 | MemoryRegions *regions_; |
michael@0 | 619 | uint32_t region_count_; |
michael@0 | 620 | }; |
michael@0 | 621 | |
michael@0 | 622 | |
michael@0 | 623 | // MinidumpException wraps MDRawExceptionStream, which contains information |
michael@0 | 624 | // about the exception that caused the minidump to be generated, if the |
michael@0 | 625 | // minidump was generated in an exception handler called as a result of |
michael@0 | 626 | // an exception. It also provides access to a MinidumpContext object, |
michael@0 | 627 | // which contains the CPU context for the exception thread at the time |
michael@0 | 628 | // the exception occurred. |
michael@0 | 629 | class MinidumpException : public MinidumpStream { |
michael@0 | 630 | public: |
michael@0 | 631 | virtual ~MinidumpException(); |
michael@0 | 632 | |
michael@0 | 633 | const MDRawExceptionStream* exception() const { |
michael@0 | 634 | return valid_ ? &exception_ : NULL; |
michael@0 | 635 | } |
michael@0 | 636 | |
michael@0 | 637 | // The thread ID is used to determine if a thread is the exception thread, |
michael@0 | 638 | // so a special getter is provided to retrieve this data from the |
michael@0 | 639 | // MDRawExceptionStream structure. Returns false if the thread ID cannot |
michael@0 | 640 | // be determined. |
michael@0 | 641 | bool GetThreadID(uint32_t *thread_id) const; |
michael@0 | 642 | |
michael@0 | 643 | MinidumpContext* GetContext(); |
michael@0 | 644 | |
michael@0 | 645 | // Print a human-readable representation of the object to stdout. |
michael@0 | 646 | void Print(); |
michael@0 | 647 | |
michael@0 | 648 | private: |
michael@0 | 649 | friend class Minidump; |
michael@0 | 650 | |
michael@0 | 651 | static const uint32_t kStreamType = MD_EXCEPTION_STREAM; |
michael@0 | 652 | |
michael@0 | 653 | explicit MinidumpException(Minidump* minidump); |
michael@0 | 654 | |
michael@0 | 655 | bool Read(uint32_t expected_size); |
michael@0 | 656 | |
michael@0 | 657 | MDRawExceptionStream exception_; |
michael@0 | 658 | MinidumpContext* context_; |
michael@0 | 659 | }; |
michael@0 | 660 | |
michael@0 | 661 | // MinidumpAssertion wraps MDRawAssertionInfo, which contains information |
michael@0 | 662 | // about an assertion that caused the minidump to be generated. |
michael@0 | 663 | class MinidumpAssertion : public MinidumpStream { |
michael@0 | 664 | public: |
michael@0 | 665 | virtual ~MinidumpAssertion(); |
michael@0 | 666 | |
michael@0 | 667 | const MDRawAssertionInfo* assertion() const { |
michael@0 | 668 | return valid_ ? &assertion_ : NULL; |
michael@0 | 669 | } |
michael@0 | 670 | |
michael@0 | 671 | string expression() const { |
michael@0 | 672 | return valid_ ? expression_ : ""; |
michael@0 | 673 | } |
michael@0 | 674 | |
michael@0 | 675 | string function() const { |
michael@0 | 676 | return valid_ ? function_ : ""; |
michael@0 | 677 | } |
michael@0 | 678 | |
michael@0 | 679 | string file() const { |
michael@0 | 680 | return valid_ ? file_ : ""; |
michael@0 | 681 | } |
michael@0 | 682 | |
michael@0 | 683 | // Print a human-readable representation of the object to stdout. |
michael@0 | 684 | void Print(); |
michael@0 | 685 | |
michael@0 | 686 | private: |
michael@0 | 687 | friend class Minidump; |
michael@0 | 688 | |
michael@0 | 689 | static const uint32_t kStreamType = MD_ASSERTION_INFO_STREAM; |
michael@0 | 690 | |
michael@0 | 691 | explicit MinidumpAssertion(Minidump* minidump); |
michael@0 | 692 | |
michael@0 | 693 | bool Read(uint32_t expected_size); |
michael@0 | 694 | |
michael@0 | 695 | MDRawAssertionInfo assertion_; |
michael@0 | 696 | string expression_; |
michael@0 | 697 | string function_; |
michael@0 | 698 | string file_; |
michael@0 | 699 | }; |
michael@0 | 700 | |
michael@0 | 701 | |
michael@0 | 702 | // MinidumpSystemInfo wraps MDRawSystemInfo and provides information about |
michael@0 | 703 | // the system on which the minidump was generated. See also MinidumpMiscInfo. |
michael@0 | 704 | class MinidumpSystemInfo : public MinidumpStream { |
michael@0 | 705 | public: |
michael@0 | 706 | virtual ~MinidumpSystemInfo(); |
michael@0 | 707 | |
michael@0 | 708 | const MDRawSystemInfo* system_info() const { |
michael@0 | 709 | return valid_ ? &system_info_ : NULL; |
michael@0 | 710 | } |
michael@0 | 711 | |
michael@0 | 712 | // GetOS and GetCPU return textual representations of the operating system |
michael@0 | 713 | // and CPU that produced the minidump. Unlike most other Minidump* methods, |
michael@0 | 714 | // they return string objects, not weak pointers. Defined values for |
michael@0 | 715 | // GetOS() are "mac", "windows", and "linux". Defined values for GetCPU |
michael@0 | 716 | // are "x86" and "ppc". These methods return an empty string when their |
michael@0 | 717 | // values are unknown. |
michael@0 | 718 | string GetOS(); |
michael@0 | 719 | string GetCPU(); |
michael@0 | 720 | |
michael@0 | 721 | // I don't know what CSD stands for, but this field is documented as |
michael@0 | 722 | // returning a textual representation of the OS service pack. On other |
michael@0 | 723 | // platforms, this provides additional information about an OS version |
michael@0 | 724 | // level beyond major.minor.micro. Returns NULL if unknown. |
michael@0 | 725 | const string* GetCSDVersion(); |
michael@0 | 726 | |
michael@0 | 727 | // If a CPU vendor string can be determined, returns a pointer to it, |
michael@0 | 728 | // otherwise, returns NULL. CPU vendor strings can be determined from |
michael@0 | 729 | // x86 CPUs with CPUID 0. |
michael@0 | 730 | const string* GetCPUVendor(); |
michael@0 | 731 | |
michael@0 | 732 | // Print a human-readable representation of the object to stdout. |
michael@0 | 733 | void Print(); |
michael@0 | 734 | |
michael@0 | 735 | protected: |
michael@0 | 736 | explicit MinidumpSystemInfo(Minidump* minidump); |
michael@0 | 737 | MDRawSystemInfo system_info_; |
michael@0 | 738 | |
michael@0 | 739 | // Textual representation of the OS service pack, for minidumps produced |
michael@0 | 740 | // by MiniDumpWriteDump on Windows. |
michael@0 | 741 | const string* csd_version_; |
michael@0 | 742 | |
michael@0 | 743 | private: |
michael@0 | 744 | friend class Minidump; |
michael@0 | 745 | |
michael@0 | 746 | static const uint32_t kStreamType = MD_SYSTEM_INFO_STREAM; |
michael@0 | 747 | |
michael@0 | 748 | bool Read(uint32_t expected_size); |
michael@0 | 749 | |
michael@0 | 750 | // A string identifying the CPU vendor, if known. |
michael@0 | 751 | const string* cpu_vendor_; |
michael@0 | 752 | }; |
michael@0 | 753 | |
michael@0 | 754 | |
michael@0 | 755 | // MinidumpMiscInfo wraps MDRawMiscInfo and provides information about |
michael@0 | 756 | // the process that generated the minidump, and optionally additional system |
michael@0 | 757 | // information. See also MinidumpSystemInfo. |
michael@0 | 758 | class MinidumpMiscInfo : public MinidumpStream { |
michael@0 | 759 | public: |
michael@0 | 760 | const MDRawMiscInfo* misc_info() const { |
michael@0 | 761 | return valid_ ? &misc_info_ : NULL; |
michael@0 | 762 | } |
michael@0 | 763 | |
michael@0 | 764 | // Print a human-readable representation of the object to stdout. |
michael@0 | 765 | void Print(); |
michael@0 | 766 | |
michael@0 | 767 | private: |
michael@0 | 768 | friend class Minidump; |
michael@0 | 769 | |
michael@0 | 770 | static const uint32_t kStreamType = MD_MISC_INFO_STREAM; |
michael@0 | 771 | |
michael@0 | 772 | explicit MinidumpMiscInfo(Minidump* minidump_); |
michael@0 | 773 | |
michael@0 | 774 | bool Read(uint32_t expected_size_); |
michael@0 | 775 | |
michael@0 | 776 | MDRawMiscInfo misc_info_; |
michael@0 | 777 | }; |
michael@0 | 778 | |
michael@0 | 779 | |
michael@0 | 780 | // MinidumpBreakpadInfo wraps MDRawBreakpadInfo, which is an optional stream in |
michael@0 | 781 | // a minidump that provides additional information about the process state |
michael@0 | 782 | // at the time the minidump was generated. |
michael@0 | 783 | class MinidumpBreakpadInfo : public MinidumpStream { |
michael@0 | 784 | public: |
michael@0 | 785 | const MDRawBreakpadInfo* breakpad_info() const { |
michael@0 | 786 | return valid_ ? &breakpad_info_ : NULL; |
michael@0 | 787 | } |
michael@0 | 788 | |
michael@0 | 789 | // These thread IDs are used to determine if threads deserve special |
michael@0 | 790 | // treatment, so special getters are provided to retrieve this data from |
michael@0 | 791 | // the MDRawBreakpadInfo structure. The getters return false if the thread |
michael@0 | 792 | // IDs cannot be determined. |
michael@0 | 793 | bool GetDumpThreadID(uint32_t *thread_id) const; |
michael@0 | 794 | bool GetRequestingThreadID(uint32_t *thread_id) const; |
michael@0 | 795 | |
michael@0 | 796 | // Print a human-readable representation of the object to stdout. |
michael@0 | 797 | void Print(); |
michael@0 | 798 | |
michael@0 | 799 | private: |
michael@0 | 800 | friend class Minidump; |
michael@0 | 801 | |
michael@0 | 802 | static const uint32_t kStreamType = MD_BREAKPAD_INFO_STREAM; |
michael@0 | 803 | |
michael@0 | 804 | explicit MinidumpBreakpadInfo(Minidump* minidump_); |
michael@0 | 805 | |
michael@0 | 806 | bool Read(uint32_t expected_size_); |
michael@0 | 807 | |
michael@0 | 808 | MDRawBreakpadInfo breakpad_info_; |
michael@0 | 809 | }; |
michael@0 | 810 | |
michael@0 | 811 | // MinidumpMemoryInfo wraps MDRawMemoryInfo, which provides information |
michael@0 | 812 | // about mapped memory regions in a process, including their ranges |
michael@0 | 813 | // and protection. |
michael@0 | 814 | class MinidumpMemoryInfo : public MinidumpObject { |
michael@0 | 815 | public: |
michael@0 | 816 | const MDRawMemoryInfo* info() const { return valid_ ? &memory_info_ : NULL; } |
michael@0 | 817 | |
michael@0 | 818 | // The address of the base of the memory region. |
michael@0 | 819 | uint64_t GetBase() const { return valid_ ? memory_info_.base_address : 0; } |
michael@0 | 820 | |
michael@0 | 821 | // The size, in bytes, of the memory region. |
michael@0 | 822 | uint32_t GetSize() const { return valid_ ? memory_info_.region_size : 0; } |
michael@0 | 823 | |
michael@0 | 824 | // Return true if the memory protection allows execution. |
michael@0 | 825 | bool IsExecutable() const; |
michael@0 | 826 | |
michael@0 | 827 | // Return true if the memory protection allows writing. |
michael@0 | 828 | bool IsWritable() const; |
michael@0 | 829 | |
michael@0 | 830 | // Print a human-readable representation of the object to stdout. |
michael@0 | 831 | void Print(); |
michael@0 | 832 | |
michael@0 | 833 | private: |
michael@0 | 834 | // These objects are managed by MinidumpMemoryInfoList. |
michael@0 | 835 | friend class MinidumpMemoryInfoList; |
michael@0 | 836 | |
michael@0 | 837 | explicit MinidumpMemoryInfo(Minidump* minidump); |
michael@0 | 838 | |
michael@0 | 839 | // This works like MinidumpStream::Read, but is driven by |
michael@0 | 840 | // MinidumpMemoryInfoList. No size checking is done, because |
michael@0 | 841 | // MinidumpMemoryInfoList handles that directly. |
michael@0 | 842 | bool Read(); |
michael@0 | 843 | |
michael@0 | 844 | MDRawMemoryInfo memory_info_; |
michael@0 | 845 | }; |
michael@0 | 846 | |
michael@0 | 847 | // MinidumpMemoryInfoList contains a list of information about |
michael@0 | 848 | // mapped memory regions for a process in the form of MDRawMemoryInfo. |
michael@0 | 849 | // It maintains a map of these structures so that it may easily provide |
michael@0 | 850 | // info corresponding to a specific address. |
michael@0 | 851 | class MinidumpMemoryInfoList : public MinidumpStream { |
michael@0 | 852 | public: |
michael@0 | 853 | virtual ~MinidumpMemoryInfoList(); |
michael@0 | 854 | |
michael@0 | 855 | unsigned int info_count() const { return valid_ ? info_count_ : 0; } |
michael@0 | 856 | |
michael@0 | 857 | const MinidumpMemoryInfo* GetMemoryInfoForAddress(uint64_t address) const; |
michael@0 | 858 | const MinidumpMemoryInfo* GetMemoryInfoAtIndex(unsigned int index) const; |
michael@0 | 859 | |
michael@0 | 860 | // Print a human-readable representation of the object to stdout. |
michael@0 | 861 | void Print(); |
michael@0 | 862 | |
michael@0 | 863 | private: |
michael@0 | 864 | friend class Minidump; |
michael@0 | 865 | |
michael@0 | 866 | typedef vector<MinidumpMemoryInfo> MinidumpMemoryInfos; |
michael@0 | 867 | |
michael@0 | 868 | static const uint32_t kStreamType = MD_MEMORY_INFO_LIST_STREAM; |
michael@0 | 869 | |
michael@0 | 870 | explicit MinidumpMemoryInfoList(Minidump* minidump); |
michael@0 | 871 | |
michael@0 | 872 | bool Read(uint32_t expected_size); |
michael@0 | 873 | |
michael@0 | 874 | // Access to memory info using addresses as the key. |
michael@0 | 875 | RangeMap<uint64_t, unsigned int> *range_map_; |
michael@0 | 876 | |
michael@0 | 877 | MinidumpMemoryInfos* infos_; |
michael@0 | 878 | uint32_t info_count_; |
michael@0 | 879 | }; |
michael@0 | 880 | |
michael@0 | 881 | |
michael@0 | 882 | // Minidump is the user's interface to a minidump file. It wraps MDRawHeader |
michael@0 | 883 | // and provides access to the minidump's top-level stream directory. |
michael@0 | 884 | class Minidump { |
michael@0 | 885 | public: |
michael@0 | 886 | // path is the pathname of a file containing the minidump. |
michael@0 | 887 | explicit Minidump(const string& path); |
michael@0 | 888 | // input is an istream wrapping minidump data. Minidump holds a |
michael@0 | 889 | // weak pointer to input, and the caller must ensure that the stream |
michael@0 | 890 | // is valid as long as the Minidump object is. |
michael@0 | 891 | explicit Minidump(std::istream& input); |
michael@0 | 892 | |
michael@0 | 893 | virtual ~Minidump(); |
michael@0 | 894 | |
michael@0 | 895 | // path may be empty if the minidump was not opened from a file |
michael@0 | 896 | virtual string path() const { |
michael@0 | 897 | return path_; |
michael@0 | 898 | } |
michael@0 | 899 | static void set_max_streams(uint32_t max_streams) { |
michael@0 | 900 | max_streams_ = max_streams; |
michael@0 | 901 | } |
michael@0 | 902 | static uint32_t max_streams() { return max_streams_; } |
michael@0 | 903 | |
michael@0 | 904 | static void set_max_string_length(uint32_t max_string_length) { |
michael@0 | 905 | max_string_length_ = max_string_length; |
michael@0 | 906 | } |
michael@0 | 907 | static uint32_t max_string_length() { return max_string_length_; } |
michael@0 | 908 | |
michael@0 | 909 | virtual const MDRawHeader* header() const { return valid_ ? &header_ : NULL; } |
michael@0 | 910 | |
michael@0 | 911 | // Reads the CPU information from the system info stream and generates the |
michael@0 | 912 | // appropriate CPU flags. The returned context_cpu_flags are the same as |
michael@0 | 913 | // if the CPU type bits were set in the context_flags of a context record. |
michael@0 | 914 | // On success, context_cpu_flags will have the flags that identify the CPU. |
michael@0 | 915 | // If a system info stream is missing, context_cpu_flags will be 0. |
michael@0 | 916 | // Returns true if the current position in the stream was not changed. |
michael@0 | 917 | // Returns false when the current location in the stream was changed and the |
michael@0 | 918 | // attempt to restore the original position failed. |
michael@0 | 919 | bool GetContextCPUFlagsFromSystemInfo(uint32_t* context_cpu_flags); |
michael@0 | 920 | |
michael@0 | 921 | // Reads the minidump file's header and top-level stream directory. |
michael@0 | 922 | // The minidump is expected to be positioned at the beginning of the |
michael@0 | 923 | // header. Read() sets up the stream list and map, and validates the |
michael@0 | 924 | // Minidump object. |
michael@0 | 925 | virtual bool Read(); |
michael@0 | 926 | |
michael@0 | 927 | // The next set of methods are stubs that call GetStream. They exist to |
michael@0 | 928 | // force code generation of the templatized API within the module, and |
michael@0 | 929 | // to avoid exposing an ugly API (GetStream needs to accept a garbage |
michael@0 | 930 | // parameter). |
michael@0 | 931 | virtual MinidumpThreadList* GetThreadList(); |
michael@0 | 932 | MinidumpModuleList* GetModuleList(); |
michael@0 | 933 | MinidumpMemoryList* GetMemoryList(); |
michael@0 | 934 | MinidumpException* GetException(); |
michael@0 | 935 | MinidumpAssertion* GetAssertion(); |
michael@0 | 936 | virtual MinidumpSystemInfo* GetSystemInfo(); |
michael@0 | 937 | MinidumpMiscInfo* GetMiscInfo(); |
michael@0 | 938 | MinidumpBreakpadInfo* GetBreakpadInfo(); |
michael@0 | 939 | MinidumpMemoryInfoList* GetMemoryInfoList(); |
michael@0 | 940 | |
michael@0 | 941 | // The next set of methods are provided for users who wish to access |
michael@0 | 942 | // data in minidump files directly, while leveraging the rest of |
michael@0 | 943 | // this class and related classes to handle the basic minidump |
michael@0 | 944 | // structure and known stream types. |
michael@0 | 945 | |
michael@0 | 946 | unsigned int GetDirectoryEntryCount() const { |
michael@0 | 947 | return valid_ ? header_.stream_count : 0; |
michael@0 | 948 | } |
michael@0 | 949 | const MDRawDirectory* GetDirectoryEntryAtIndex(unsigned int index) const; |
michael@0 | 950 | |
michael@0 | 951 | // The next 2 methods are lower-level I/O routines. They use fd_. |
michael@0 | 952 | |
michael@0 | 953 | // Reads count bytes from the minidump at the current position into |
michael@0 | 954 | // the storage area pointed to by bytes. bytes must be of sufficient |
michael@0 | 955 | // size. After the read, the file position is advanced by count. |
michael@0 | 956 | bool ReadBytes(void* bytes, size_t count); |
michael@0 | 957 | |
michael@0 | 958 | // Sets the position of the minidump file to offset. |
michael@0 | 959 | bool SeekSet(off_t offset); |
michael@0 | 960 | |
michael@0 | 961 | // Returns the current position of the minidump file. |
michael@0 | 962 | off_t Tell(); |
michael@0 | 963 | |
michael@0 | 964 | // The next 2 methods are medium-level I/O routines. |
michael@0 | 965 | |
michael@0 | 966 | // ReadString returns a string which is owned by the caller! offset |
michael@0 | 967 | // specifies the offset that a length-encoded string is stored at in the |
michael@0 | 968 | // minidump file. |
michael@0 | 969 | string* ReadString(off_t offset); |
michael@0 | 970 | |
michael@0 | 971 | // SeekToStreamType positions the file at the beginning of a stream |
michael@0 | 972 | // identified by stream_type, and informs the caller of the stream's |
michael@0 | 973 | // length by setting *stream_length. Because stream_map maps each stream |
michael@0 | 974 | // type to only one stream in the file, this might mislead the user into |
michael@0 | 975 | // thinking that the stream that this seeks to is the only stream with |
michael@0 | 976 | // type stream_type. That can't happen for streams that these classes |
michael@0 | 977 | // deal with directly, because they're only supposed to be present in the |
michael@0 | 978 | // file singly, and that's verified when stream_map_ is built. Users who |
michael@0 | 979 | // are looking for other stream types should be aware of this |
michael@0 | 980 | // possibility, and consider using GetDirectoryEntryAtIndex (possibly |
michael@0 | 981 | // with GetDirectoryEntryCount) if expecting multiple streams of the same |
michael@0 | 982 | // type in a single minidump file. |
michael@0 | 983 | bool SeekToStreamType(uint32_t stream_type, uint32_t* stream_length); |
michael@0 | 984 | |
michael@0 | 985 | bool swap() const { return valid_ ? swap_ : false; } |
michael@0 | 986 | |
michael@0 | 987 | // Print a human-readable representation of the object to stdout. |
michael@0 | 988 | void Print(); |
michael@0 | 989 | |
michael@0 | 990 | private: |
michael@0 | 991 | // MinidumpStreamInfo is used in the MinidumpStreamMap. It lets |
michael@0 | 992 | // the Minidump object locate interesting streams quickly, and |
michael@0 | 993 | // provides a convenient place to stash MinidumpStream objects. |
michael@0 | 994 | struct MinidumpStreamInfo { |
michael@0 | 995 | MinidumpStreamInfo() : stream_index(0), stream(NULL) {} |
michael@0 | 996 | ~MinidumpStreamInfo() { delete stream; } |
michael@0 | 997 | |
michael@0 | 998 | // Index into the MinidumpDirectoryEntries vector |
michael@0 | 999 | unsigned int stream_index; |
michael@0 | 1000 | |
michael@0 | 1001 | // Pointer to the stream if cached, or NULL if not yet populated |
michael@0 | 1002 | MinidumpStream* stream; |
michael@0 | 1003 | }; |
michael@0 | 1004 | |
michael@0 | 1005 | typedef vector<MDRawDirectory> MinidumpDirectoryEntries; |
michael@0 | 1006 | typedef map<uint32_t, MinidumpStreamInfo> MinidumpStreamMap; |
michael@0 | 1007 | |
michael@0 | 1008 | template<typename T> T* GetStream(T** stream); |
michael@0 | 1009 | |
michael@0 | 1010 | // Opens the minidump file, or if already open, seeks to the beginning. |
michael@0 | 1011 | bool Open(); |
michael@0 | 1012 | |
michael@0 | 1013 | // The largest number of top-level streams that will be read from a minidump. |
michael@0 | 1014 | // Note that streams are only read (and only consume memory) as needed, |
michael@0 | 1015 | // when directed by the caller. The default is 128. |
michael@0 | 1016 | static uint32_t max_streams_; |
michael@0 | 1017 | |
michael@0 | 1018 | // The maximum length of a UTF-16 string that will be read from a minidump |
michael@0 | 1019 | // in 16-bit words. The default is 1024. UTF-16 strings are converted |
michael@0 | 1020 | // to UTF-8 when stored in memory, and each UTF-16 word will be represented |
michael@0 | 1021 | // by as many as 3 bytes in UTF-8. |
michael@0 | 1022 | static unsigned int max_string_length_; |
michael@0 | 1023 | |
michael@0 | 1024 | MDRawHeader header_; |
michael@0 | 1025 | |
michael@0 | 1026 | // The list of streams. |
michael@0 | 1027 | MinidumpDirectoryEntries* directory_; |
michael@0 | 1028 | |
michael@0 | 1029 | // Access to streams using the stream type as the key. |
michael@0 | 1030 | MinidumpStreamMap* stream_map_; |
michael@0 | 1031 | |
michael@0 | 1032 | // The pathname of the minidump file to process, set in the constructor. |
michael@0 | 1033 | // This may be empty if the minidump was opened directly from a stream. |
michael@0 | 1034 | const string path_; |
michael@0 | 1035 | |
michael@0 | 1036 | // The stream for all file I/O. Used by ReadBytes and SeekSet. |
michael@0 | 1037 | // Set based on the path in Open, or directly in the constructor. |
michael@0 | 1038 | std::istream* stream_; |
michael@0 | 1039 | |
michael@0 | 1040 | // swap_ is true if the minidump file should be byte-swapped. If the |
michael@0 | 1041 | // minidump was produced by a CPU that is other-endian than the CPU |
michael@0 | 1042 | // processing the minidump, this will be true. If the two CPUs are |
michael@0 | 1043 | // same-endian, this will be false. |
michael@0 | 1044 | bool swap_; |
michael@0 | 1045 | |
michael@0 | 1046 | // Validity of the Minidump structure, false immediately after |
michael@0 | 1047 | // construction or after a failed Read(); true following a successful |
michael@0 | 1048 | // Read(). |
michael@0 | 1049 | bool valid_; |
michael@0 | 1050 | }; |
michael@0 | 1051 | |
michael@0 | 1052 | |
michael@0 | 1053 | } // namespace google_breakpad |
michael@0 | 1054 | |
michael@0 | 1055 | |
michael@0 | 1056 | #endif // GOOGLE_BREAKPAD_PROCESSOR_MINIDUMP_H__ |