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
21extern "C" {
22#include "qemu-common.h"
23}
24#include "elff-common.h"
25
26class 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 */
44typedef 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 */
80class 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 */
112class 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