Home | History | Annotate | Download | only in elff
      1 /* Copyright (C) 2007-2010 The Android Open Source Project
      2 **
      3 ** This software is licensed under the terms of the GNU General Public
      4 ** License version 2, as published by the Free Software Foundation, and
      5 ** may be copied, distributed, and modified under those terms.
      6 **
      7 ** This program is distributed in the hope that it will be useful,
      8 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
      9 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     10 ** GNU General Public License for more details.
     11 */
     12 
     13 /*
     14  * Contains declaration of class ElfAllocator, that implements memory
     15  * allocations for DWARF objects.
     16  */
     17 
     18 #ifndef ELFF_ELF_ALLOC_H_
     19 #define ELFF_ELF_ALLOC_H_
     20 
     21 #include <stdint.h>
     22 #include "elff-common.h"
     23 
     24 class ElfFile;
     25 
     26 /* Alignment mask for blocks, allocated with this allocator. */
     27 #define ELFALLOC_ALIGNMENT_MASK 3
     28 
     29 /* Chunk size. Even on relatively small ELF files, there are a lot of DWARF
     30  * info, which makes our parsing pretty hungry on memory. On average, memory
     31  * consumption on cached DWARF objects may easily reach 640K, which makes
     32  * choosing 32K as chunk size pretty reasonable.
     33  */
     34 #define ELF_ALLOC_CHUNK_SIZE  (32 * 1024)
     35 
     36 /* Describes a chunk of memory, allocated by ElfAllocator.
     37  * NOTE: this header's sizeof must be always aligned accordingly to the
     38  * ELFALLOC_ALIGNMENT_MASK value, so we can produce properly aligned blocks
     39  * without having to adjust alignment of the blocks, returned from alloc()
     40  * method.
     41  */
     42 typedef struct ElfAllocatorChunk {
     43   /* Previous chunk in the chain of chunks allocated by ElfAllocator instance.
     44    * For better allocation performance, ElfAllocator keeps its list of
     45    * allocated chunks in reverse order (relatively to the chunk allocation
     46    * sequence). So this field in each chunk references the chunk, allocated
     47    * just prior this one. This field contains NULL for the first allocated
     48    * chunk.
     49    */
     50   ElfAllocatorChunk*  prev;
     51 
     52   /* Address of the next available block in this chunk. */
     53   void*               avail;
     54 
     55   /* Chunk size. */
     56   size_t              size;
     57 
     58   /* Number of bytes that remain available in this chunk. */
     59   size_t              remains;
     60 } ElfAllocatorChunk;
     61 
     62 /* Encapsulates memory allocator for DWARF-related objects.
     63  * Due to the implementation of ELF/DWARF framework in this library, data,
     64  * collected during ELF/DWARF parsing stays in memory for as long, as instance
     65  * of ElfFile that's being parsed is alive. To save performance on the numerous
     66  * memory allocations (and then, deallocations) we will use this simple memory
     67  * allocator that will grab memory from the heap in large chunks and then will
     68  * provide DWARF objects with blocks of the required size inside those chunks.
     69  * This will be much faster than going to the heap all the time, and since we
     70  * will use overwritten operators new/delete for the DWARF objects that use
     71  * this allocator, this is going to be pretty flexible and reliable solution
     72  * for DWARF object allocation implementation. See DwarfAllocBase for more
     73  * details.
     74  *
     75  * Instance (always one) of this class is created by ElfFile object when it is
     76  * initializing.
     77  */
     78 class ElfAllocator {
     79  public:
     80   /* Constructs ElfAllocator instance. */
     81   ElfAllocator();
     82 
     83   /* Destructs ElfAllocator instance. */
     84   ~ElfAllocator();
     85 
     86   /* Allocates requested number of bytes for a DWARF object.
     87    * Param:
     88    *  size - Number of bytes to allocate. Value passed in this parameter
     89    *    will be rounded up accordingly to ELFALLOC_ALIGNMENT_MASK value,
     90    *    simplifying alignment adjustments for the allocated blocks.
     91    * Return:
     92    *  Address of allocated block of the requested size on success,
     93    *  or NULL on failure.
     94    */
     95   void* alloc(size_t size);
     96 
     97  protected:
     98   /* Current chunk to allocate memory from. NOTE: chunks are listed here
     99    * in reverse order (relatively to the chunk allocation sequence).
    100    */
    101   ElfAllocatorChunk*  current_chunk_;
    102 };
    103 
    104 /* Base class for all WDARF objects that will use ElfAllocator class for
    105  * instance allocations. NOTE: it's required, that all classes that use
    106  * ElfAllocator are derived from this one, as it provides compilation-time
    107  * protection from mistakenly using "traditional" operator 'new' for object
    108  * instantiation.
    109  */
    110 class DwarfAllocBase {
    111  public:
    112   /* Constructs DwarfAllocBase instance. */
    113   DwarfAllocBase() {
    114   }
    115 
    116   /* Destructs DwarfAllocBase instance. */
    117   virtual ~DwarfAllocBase() {
    118   }
    119 
    120   /* Main operator new.
    121    * Implements allocation of objects of derived classes from elf's "chunked"
    122    * allocator, instantiated in ElfFile object (see ElfAllocator class).
    123    * Param:
    124    *  size - Number of bytes to allocate for an instance of the derived class.
    125    *  elf - ELF file instance that owns the allocating object.
    126    * Return:
    127    *  Pointer to the allocated memory on success, or NULL on failure.
    128    */
    129   void* operator new(size_t size, const ElfFile* elf);
    130 
    131   /* Overwitten operator delete.
    132    * Since deleting for chunk-allocated objects is a "no-op", we don't do
    133    * anything in this operator. We, however, are obliged to implement this
    134    * operator in order to compliment overwritten operator 'new'.
    135    */
    136   void operator delete(void* ptr) {
    137   }
    138 
    139   /* Overwitten operator delete.
    140    * Since deleting for chunk-allocated objects is a "no-op", we don't do
    141    * anything in this operator. We, however, are obliged to implement this
    142    * operator in order to compliment overwritten operator 'new'.
    143    */
    144   void operator delete[](void* ptr) {
    145   }
    146 
    147  private:
    148   /* Default operator new.
    149    * We override it making 'private' in order to cause a compiler error on
    150    * attempts to instantiate objects of derived classes using this version
    151    * of operator 'new'.
    152    */
    153   void* operator new(size_t size) throw() {
    154     return NULL;
    155   }
    156 };
    157 
    158 extern "C" void* elff_alloc(size_t  size);
    159 extern "C" void  elff_free(void* ptr);
    160 
    161 #endif  // ELFF_ELF_ALLOC_H_
    162