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