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
24class 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 */
42typedef 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 */
78class 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 */
110class 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
158extern "C" void* elff_alloc(size_t  size);
159extern "C" void  elff_free(void* ptr);
160
161#endif  // ELFF_ELF_ALLOC_H_
162