blob: acc586a3ef6c1543279db3df2ee7896a832f35c9 [file] [log] [blame]
/* Copyright (C) 2007-2010 The Android Open Source Project
**
** This software is licensed under the terms of the GNU General Public
** License version 2, as published by the Free Software Foundation, and
** may be copied, distributed, and modified under those terms.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
*/
/*
* Contains some helpful macros, and inline routines.
*/
#ifndef ELFF_ELF_DEFS_H_
#define ELFF_ELF_DEFS_H_
#include "elff/elff_elf.h"
//=============================================================================
// Macros.
//=============================================================================
/* Increments a pointer by n bytes.
* Param:
* p - Pointer to increment.
* n - Number of bytes to increment the pointer with.
*/
static inline uint8_t* INC_PTR(void* p, size_t n) {
return reinterpret_cast<uint8_t*>(p) + n;
}
/* Increments a constant pointer by n bytes.
* Param:
* p - Pointer to increment.
* n - Number of bytes to increment the pointer with.
*/
static inline const uint8_t* INC_CPTR(const void* p, size_t n) {
return reinterpret_cast<const uint8_t*>(p) + n;
}
/* Increments a constant pointer of a given type by n bytes.
* Param:
* T - Pointer type
* p - Pointer to increment.
* n - Number of bytes to increment the pointer with.
*/
template <typename T>
static inline const T* INC_CPTR_T_INNER_TEMPLATE(const void* p, size_t n) {
union {
const void* p;
const uint8_t* p8;
const T* pt;
} u;
u.p = p;
u.p8 += n;
return u.pt;
}
#define INC_CPTR_T(T, p, n) INC_CPTR_T_INNER_TEMPLATE<T>(p, n)
/* Calculates number of entries in a static array.
* Param:
* a - Array.
* Return:
* Number of entries in the array.
*/
#define ELFF_ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
/* Calculates offset of a field inside a structure (or a class) of the
* given type.
* Param:
* T - Structure (or class) type.
* f - Name of a field (member variable) for this structure (or class).
*/
#define ELFF_FIELD_OFFSET(T, f) offsetof(T, f)
//=============================================================================
// Inline routines.
//=============================================================================
/* Calculates byte interval between two pointers.
* Param:
* s - Starting pointer of the interval. Must be less, or equal to 'e'.
* e - Ending pointer of the interval. Must be greater, or equal to 's'.
* Return:
* Byte interval between two pointers.
*/
static inline size_t
diff_ptr(const void* s, const void* e) {
assert(s <= e);
return ((size_t)(reinterpret_cast<const uint8_t*>(e) -
reinterpret_cast<const uint8_t*>(s)));
}
/* Gets one byte from an index inside a memory block.
* Param:
* ptr - Address of the beginning of the memory block.
* bt - Index of a byte inside the block to get.
* Return:
* A byte at the given index inside the given memory block.
*/
static inline uint8_t
get_byte(const void* ptr, uint32_t bt) {
return *(reinterpret_cast<const uint8_t*>(ptr) + bt);
}
/* Checks if given address range is fully contained within a section.
* Param:
* rp - Beginning of the range to check.
* rsize - Size of the range to check.
* ss - Beginning of the section that should contain the checking range.
* ssize - Size of the section that should contain the checking range.
* Return:
* true, if given address range is fully contained within a section, or
* false, if any part of the address range is not contained in the secton.
*/
static inline bool
is_in_section(const void* rp, size_t rsize, const void* ss, size_t ssize) {
const void* rend = INC_CPTR(rp, rsize);
/* We also make sure here that increment didn't overflow the pointer. */
return rp >= ss && ss != NULL && (diff_ptr(ss, rend) <= ssize) && rend >= rp;
}
/* Checks if this code runs on CPU with a little-endian data format.
* Return:
* true, if this code runs on CPU with a little-endian data format,
* or false, if this code runs on CPU with a big-endian data format.
*/
static inline bool
is_little_endian_cpu(void) {
uint16_t tmp = 0x00FF;
/* Lets see if byte has flipped for little-endian. */
return get_byte(&tmp, 0) == 0xFF;
}
#endif // ELFF_ELF_DEFS_H_