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 */
87static inline size_t
88diff_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 */
101static inline uint8_t
102get_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 */
116static inline bool
117is_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 */
128static inline bool
129is_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/* Use in printf() statements to dump 64-bit values
136 */
137#ifdef _WIN32
138#  define FMT_I64  "I64"
139#else
140#  define FMT_I64  "ll"
141#endif
142
143#endif  // ELFF_ELF_DEFS_H_
144