diff options
author | Ted Mielczarek <ted@mielczarek.org> | 2016-04-05 09:34:20 -0400 |
---|---|---|
committer | Ted Mielczarek <ted@mielczarek.org> | 2016-04-05 09:34:20 -0400 |
commit | 6c8f80aa8b3ba8120c4158c069bb298c044dedf9 (patch) | |
tree | 2164203da75d894883e042368c34370f6c3af4c8 /src/common/memory.h | |
parent | sample_app: enable C++11 for Android builds (diff) | |
download | breakpad-6c8f80aa8b3ba8120c4158c069bb298c044dedf9.tar.xz |
Switch the Linux minidump writer to use MDCVInfoELF for CV data.
This preserves full build ids in minidumps, which are useful for
tracking down the right version of system libraries from Linux
distributions.
The default build id produced by GNU binutils' ld is a 160-bit SHA-1
hash of some parts of the binary, which is exactly 20 bytes:
https://sourceware.org/binutils/docs-2.26/ld/Options.html#index-g_t_002d_002dbuild_002did-292
The bulk of the changes here are to change the signatures of the
FileID methods to use a wasteful_vector instead of raw pointers, since
build ids can be of arbitrary length.
The previous change that added support for this in the processor code
preserved the return value of `Minidump::debug_identifier()` as the
current `GUID+age` treatment for backwards-compatibility, and exposed
the full build id from `Minidump::code_identifier()`, which was
previously stubbed out for Linux dumps. This change keeps the debug ID
in the `dump_syms` output the same to match.
R=mark@chromium.org, thestig@chromium.org
BUG=
Review URL: https://codereview.chromium.org/1688743002 .
Diffstat (limited to 'src/common/memory.h')
-rw-r--r-- | src/common/memory.h | 52 |
1 files changed, 48 insertions, 4 deletions
diff --git a/src/common/memory.h b/src/common/memory.h index d6aa137d..16a612b8 100644 --- a/src/common/memory.h +++ b/src/common/memory.h @@ -64,7 +64,8 @@ class PageAllocator { : page_size_(getpagesize()), last_(NULL), current_page_(NULL), - page_offset_(0) { + page_offset_(0), + pages_allocated_(0) { } ~PageAllocator() { @@ -112,6 +113,8 @@ class PageAllocator { return false; } + unsigned long pages_allocated() { return pages_allocated_; } + private: uint8_t *GetNPages(size_t num_pages) { #if defined(__x86_64__) || defined(__aarch64__) || defined(__aarch64__) || \ @@ -136,6 +139,8 @@ class PageAllocator { header->num_pages = num_pages; last_ = header; + pages_allocated_ += num_pages; + return reinterpret_cast<uint8_t*>(a); } @@ -157,6 +162,7 @@ class PageAllocator { PageHeader *last_; uint8_t *current_page_; size_t page_offset_; + unsigned long pages_allocated_; }; // Wrapper to use with STL containers @@ -165,12 +171,30 @@ struct PageStdAllocator : public std::allocator<T> { typedef typename std::allocator<T>::pointer pointer; typedef typename std::allocator<T>::size_type size_type; - explicit PageStdAllocator(PageAllocator& allocator): allocator_(allocator) {} + explicit PageStdAllocator(PageAllocator& allocator) : allocator_(allocator), + stackdata_(NULL), + stackdata_size_(0) + {} + template <class Other> PageStdAllocator(const PageStdAllocator<Other>& other) - : allocator_(other.allocator_) {} + : allocator_(other.allocator_), + stackdata_(nullptr), + stackdata_size_(0) + {} + + explicit PageStdAllocator(PageAllocator& allocator, + pointer stackdata, + size_type stackdata_size) : allocator_(allocator), + stackdata_(stackdata), + stackdata_size_(stackdata_size) + {} inline pointer allocate(size_type n, const void* = 0) { - return static_cast<pointer>(allocator_.Alloc(sizeof(T) * n)); + const size_type size = sizeof(T) * n; + if (size <= stackdata_size_) { + return stackdata_; + } + return static_cast<pointer>(allocator_.Alloc(size)); } inline void deallocate(pointer, size_type) { @@ -188,6 +212,8 @@ struct PageStdAllocator : public std::allocator<T> { template<typename Other> friend struct PageStdAllocator; PageAllocator& allocator_; + pointer stackdata_; + size_type stackdata_size_; }; // A wasteful vector is a std::vector, except that it allocates memory from a @@ -200,6 +226,24 @@ class wasteful_vector : public std::vector<T, PageStdAllocator<T> > { : std::vector<T, PageStdAllocator<T> >(PageStdAllocator<T>(*allocator)) { std::vector<T, PageStdAllocator<T> >::reserve(size_hint); } + protected: + wasteful_vector(PageStdAllocator<T> allocator) + : std::vector<T, PageStdAllocator<T> >(allocator) {} +}; + +// auto_wasteful_vector allocates space on the stack for N entries to avoid +// using the PageAllocator for small data, while still allowing for larger data. +template<class T, unsigned int N> +class auto_wasteful_vector : public wasteful_vector<T> { + T stackdata_[N]; + public: + auto_wasteful_vector(PageAllocator* allocator) + : wasteful_vector<T>( + PageStdAllocator<T>(*allocator, + &stackdata_[0], + sizeof(stackdata_))) { + std::vector<T, PageStdAllocator<T> >::reserve(N); + } }; } // namespace google_breakpad |