LCOV - code coverage report
Current view: directory - toolkit/crashreporter/google-breakpad/src/common - memory.h (source / functions) Found Hit Coverage
Test: app.info Lines: 71 0 0.0 %
Date: 2012-06-02 Functions: 24 0 0.0 %

       1                 : // Copyright (c) 2009, Google Inc.
       2                 : // All rights reserved.
       3                 : //
       4                 : // Redistribution and use in source and binary forms, with or without
       5                 : // modification, are permitted provided that the following conditions are
       6                 : // met:
       7                 : //
       8                 : //     * Redistributions of source code must retain the above copyright
       9                 : // notice, this list of conditions and the following disclaimer.
      10                 : //     * Redistributions in binary form must reproduce the above
      11                 : // copyright notice, this list of conditions and the following disclaimer
      12                 : // in the documentation and/or other materials provided with the
      13                 : // distribution.
      14                 : //     * Neither the name of Google Inc. nor the names of its
      15                 : // contributors may be used to endorse or promote products derived from
      16                 : // this software without specific prior written permission.
      17                 : //
      18                 : // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      19                 : // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      20                 : // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      21                 : // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      22                 : // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      23                 : // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      24                 : // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      25                 : // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      26                 : // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      27                 : // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      28                 : // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      29                 : 
      30                 : #ifndef GOOGLE_BREAKPAD_COMMON_MEMORY_H_
      31                 : #define GOOGLE_BREAKPAD_COMMON_MEMORY_H_
      32                 : 
      33                 : #include <stdint.h>
      34                 : #include <stdlib.h>
      35                 : #include <unistd.h>
      36                 : #include <sys/mman.h>
      37                 : 
      38                 : #ifdef __APPLE__
      39                 : #define sys_mmap mmap
      40                 : #define sys_mmap2 mmap
      41                 : #define sys_munmap munmap
      42                 : #define MAP_ANONYMOUS MAP_ANON
      43                 : #else
      44                 : #include "common/linux/linux_syscall_support.h"
      45                 : #endif
      46                 : 
      47                 : namespace google_breakpad {
      48                 : 
      49                 : // This is very simple allocator which fetches pages from the kernel directly.
      50                 : // Thus, it can be used even when the heap may be corrupted.
      51                 : //
      52                 : // There is no free operation. The pages are only freed when the object is
      53                 : // destroyed.
      54                 : class PageAllocator {
      55                 :  public:
      56               0 :   PageAllocator()
      57               0 :       : page_size_(getpagesize()),
      58                 :         last_(NULL),
      59                 :         current_page_(NULL),
      60               0 :         page_offset_(0) {
      61               0 :   }
      62                 : 
      63               0 :   ~PageAllocator() {
      64               0 :     FreeAll();
      65               0 :   }
      66                 : 
      67               0 :   void *Alloc(unsigned bytes) {
      68               0 :     if (!bytes)
      69               0 :       return NULL;
      70                 : 
      71               0 :     if (current_page_ && page_size_ - page_offset_ >= bytes) {
      72               0 :       uint8_t *const ret = current_page_ + page_offset_;
      73               0 :       page_offset_ += bytes;
      74               0 :       if (page_offset_ == page_size_) {
      75               0 :         page_offset_ = 0;
      76               0 :         current_page_ = NULL;
      77                 :       }
      78                 : 
      79               0 :       return ret;
      80                 :     }
      81                 : 
      82                 :     const unsigned pages =
      83               0 :         (bytes + sizeof(PageHeader) + page_size_ - 1) / page_size_;
      84               0 :     uint8_t *const ret = GetNPages(pages);
      85               0 :     if (!ret)
      86               0 :       return NULL;
      87                 : 
      88               0 :     page_offset_ = (page_size_ - (page_size_ * pages - (bytes + sizeof(PageHeader)))) % page_size_;
      89               0 :     current_page_ = page_offset_ ? ret + page_size_ * (pages - 1) : NULL;
      90                 : 
      91               0 :     return ret + sizeof(PageHeader);
      92                 :   }
      93                 : 
      94                 :  private:
      95               0 :   uint8_t *GetNPages(unsigned num_pages) {
      96                 : #ifdef __x86_64
      97                 :     void *a = sys_mmap(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE,
      98                 :                        MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
      99                 : #else
     100                 :     void *a = sys_mmap2(NULL, page_size_ * num_pages, PROT_READ | PROT_WRITE,
     101               0 :                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     102                 : #endif
     103               0 :     if (a == MAP_FAILED)
     104               0 :       return NULL;
     105                 : 
     106               0 :     struct PageHeader *header = reinterpret_cast<PageHeader*>(a);
     107               0 :     header->next = last_;
     108               0 :     header->num_pages = num_pages;
     109               0 :     last_ = header;
     110                 : 
     111               0 :     return reinterpret_cast<uint8_t*>(a);
     112                 :   }
     113                 : 
     114               0 :   void FreeAll() {
     115                 :     PageHeader *next;
     116                 : 
     117               0 :     for (PageHeader *cur = last_; cur; cur = next) {
     118               0 :       next = cur->next;
     119               0 :       sys_munmap(cur, cur->num_pages * page_size_);
     120                 :     }
     121               0 :   }
     122                 : 
     123                 :   struct PageHeader {
     124                 :     PageHeader *next;  // pointer to the start of the next set of pages.
     125                 :     unsigned num_pages;  // the number of pages in this set.
     126                 :   };
     127                 : 
     128                 :   const unsigned page_size_;
     129                 :   PageHeader *last_;
     130                 :   uint8_t *current_page_;
     131                 :   unsigned page_offset_;
     132                 : };
     133                 : 
     134                 : // A wasteful vector is like a normal std::vector, except that it's very much
     135                 : // simplier and it allocates memory from a PageAllocator. It's wasteful
     136                 : // because, when resizing, it always allocates a whole new array since the
     137                 : // PageAllocator doesn't support realloc.
     138                 : template<class T>
     139                 : class wasteful_vector {
     140                 :  public:
     141               0 :   wasteful_vector(PageAllocator *allocator, unsigned size_hint = 16)
     142                 :       : allocator_(allocator),
     143                 :         a_((T*) allocator->Alloc(sizeof(T) * size_hint)),
     144                 :         allocated_(size_hint),
     145               0 :         used_(0) {
     146               0 :   }
     147                 : 
     148               0 :   void push_back(const T& new_element) {
     149               0 :     if (used_ == allocated_)
     150               0 :       Realloc(allocated_ * 2);
     151               0 :     a_[used_++] = new_element;
     152               0 :   }
     153                 : 
     154               0 :   size_t size() const {
     155               0 :     return used_;
     156                 :   }
     157                 : 
     158               0 :   void resize(unsigned sz, T c = T()) {
     159                 :     // No need to test "sz >= 0", as "sz" is unsigned.
     160               0 :     if (sz <= used_) {
     161               0 :       used_ = sz;
     162                 :     } else {
     163               0 :       unsigned a = allocated_;
     164               0 :       if (sz > a) {
     165               0 :         while (sz > a) {
     166               0 :           a *= 2;
     167                 :         }
     168               0 :         Realloc(a);
     169                 :       }
     170               0 :       while (sz > used_) {
     171               0 :         a_[used_++] = c;
     172                 :       }
     173                 :     }
     174               0 :   }
     175                 : 
     176               0 :   T& operator[](size_t index) {
     177               0 :     return a_[index];
     178                 :   }
     179                 : 
     180               0 :   const T& operator[](size_t index) const {
     181               0 :     return a_[index];
     182                 :   }
     183                 : 
     184                 :  private:
     185               0 :   void Realloc(unsigned new_size) {
     186                 :     T *new_array =
     187               0 :         reinterpret_cast<T*>(allocator_->Alloc(sizeof(T) * new_size));
     188               0 :     memcpy(new_array, a_, used_ * sizeof(T));
     189               0 :     a_ = new_array;
     190               0 :     allocated_ = new_size;
     191               0 :   }
     192                 : 
     193                 :   PageAllocator *const allocator_;
     194                 :   T *a_;  // pointer to an array of |allocated_| elements.
     195                 :   unsigned allocated_;  // size of |a_|, in elements.
     196                 :   unsigned used_;  // number of used slots in |a_|.
     197                 : };
     198                 : 
     199                 : }  // namespace google_breakpad
     200                 : 
     201               0 : inline void* operator new(size_t nbytes,
     202                 :                           google_breakpad::PageAllocator& allocator) {
     203               0 :    return allocator.Alloc(nbytes);
     204                 : }
     205                 : 
     206                 : #endif  // GOOGLE_BREAKPAD_COMMON_MEMORY_H_

Generated by: LCOV version 1.7