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 some helpful macros, and inline routines.
15  */
16 
17 #ifndef ELFF_ELF_DEFS_H_
18 #define ELFF_ELF_DEFS_H_
19 
20 #include "elff_elf.h"
21 
22 //=============================================================================
23 // Macros.
24 //=============================================================================
25 
26 /* Increments a pointer by n bytes.
27  * Param:
28  *  p - Pointer to increment.
29  *  n - Number of bytes to increment the pointer with.
30  */
31 #define INC_PTR(p, n)   (reinterpret_cast<uint8_t*>(p) + (n))
32 
33 /* Increments a constant pointer by n bytes.
34  * Param:
35  *  p - Pointer to increment.
36  *  n - Number of bytes to increment the pointer with.
37  */
38 #define INC_CPTR(p, n)  (reinterpret_cast<const uint8_t*>(p) + (n))
39 
40 /* Increments a pointer of a given type by n bytes.
41  * Param:
42  *  T - Pointer type
43  *  p - Pointer to increment.
44  *  n - Number of bytes to increment the pointer with.
45  */
46 #define INC_PTR_T(T, p, n)                              \
47     reinterpret_cast<T*>                                \
48         (reinterpret_cast<uint8_t*>(p) + (n))
49 
50 /* Increments a constant pointer of a given type by n bytes.
51  * Param:
52  *  T - Pointer type
53  *  p - Pointer to increment.
54  *  n - Number of bytes to increment the pointer with.
55  */
56 #define INC_CPTR_T(T, p, n)                                 \
57     reinterpret_cast<const T*>                              \
58         (reinterpret_cast<const uint8_t*>(p) + (n))
59 
60 /* Calculates number of entries in a static array.
61  * Param:
62  *  a - Array.
63  * Return:
64  *  Number of entries in the array.
65  */
66 #define ELFF_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
67 
68 /* Calculates offset of a field inside a structure (or a class) of the
69  * given type.
70  * Param:
71  *  T - Structure (or class) type.
72  *  f - Name of a field (member variable) for this structure (or class).
73  */
74 #define ELFF_FIELD_OFFSET(T, f) ((size_t)(size_t*)&(((T *)0)->f))
75 
76 //=============================================================================
77 // Inline routines.
78 //=============================================================================
79 
80 /* Calculates byte interval between two pointers.
81  * Param:
82  *  s - Starting pointer of the interval. Must be less, or equal to 'e'.
83  *  e - Ending pointer of the interval. Must be greater, or equal to 's'.
84  * Return:
85  *  Byte interval between two pointers.
86  */
87 static inline size_t
diff_ptr(const void * s,const void * e)88 diff_ptr(const void* s, const void* e) {
89   assert(s <= e);
90   return ((size_t)(reinterpret_cast<const uint8_t*>(e) -
91          reinterpret_cast<const uint8_t*>(s)));
92 }
93 
94 /* Gets one byte from an index inside a memory block.
95  * Param:
96  *  ptr - Address of the beginning of the memory block.
97  *  bt - Index of a byte inside the block to get.
98  * Return:
99  *  A byte at the given index inside the given memory block.
100  */
101 static inline uint8_t
get_byte(const void * ptr,uint32_t bt)102 get_byte(const void* ptr, uint32_t bt) {
103   return *(reinterpret_cast<const uint8_t*>(ptr) + bt);
104 }
105 
106 /* Checks if given address range is fully contained within a section.
107  * Param:
108  *  rp - Beginning of the range to check.
109  *  rsize - Size of the range to check.
110  *  ss - Beginning of the section that should contain the checking range.
111  *  ssize - Size of the section that should contain the checking range.
112  * Return:
113  *  true, if given address range is fully contained within a section, or
114  *  false, if any part of the address range is not contained in the secton.
115  */
116 static inline bool
is_in_section(const void * rp,size_t rsize,const void * ss,size_t ssize)117 is_in_section(const void* rp, size_t rsize, const void* ss, size_t ssize) {
118   const void* rend = INC_CPTR(rp, rsize);
119   /* We also make sure here that increment didn't overflow the pointer. */
120   return rp >= ss && ss != NULL && (diff_ptr(ss, rend) <= ssize) && rend >= rp;
121 }
122 
123 /* Checks if this code runs on CPU with a little-endian data format.
124  * Return:
125  *  true, if this code runs on CPU with a little-endian data format,
126  *  or false, if this code runs on CPU with a big-endian data format.
127  */
128 static inline bool
is_little_endian_cpu(void)129 is_little_endian_cpu(void) {
130   uint16_t tmp = 0x00FF;
131   /* Lets see if byte has flipped for little-endian. */
132   return get_byte(&tmp, 0) == 0xFF;
133 }
134 
135 #endif  // ELFF_ELF_DEFS_H_
136