/* Unaligned memory access functionality. Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. Written by Ulrich Drepper <drepper@redhat.com>, 2001. This program is Open Source software; you can redistribute it and/or modify it under the terms of the Open Software License version 1.0 as published by the Open Source Initiative. You should have received a copy of the Open Software License along with this program; if not, you may obtain a copy of the Open Software License version 1.0 from http://www.opensource.org/licenses/osl.php or by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 3001 King Ranch Road, Ukiah, CA 95482. */ #ifndef _MEMORY_ACCESS_H #define _MEMORY_ACCESS_H 1 #include <byteswap.h> #include <limits.h> #include <stdint.h> /* Number decoding macros. See 7.6 Variable Length Data. */ #define get_uleb128(var, addr) \ do { \ unsigned char __b = *((const unsigned char *) addr); \ addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ var = __b & 0x7f; \ if (__b & 0x80) \ { \ __b = *((const unsigned char *) addr); \ addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ var |= (__b & 0x7f) << 7; \ if (__b & 0x80) \ { \ __b = *((const unsigned char *) addr); \ addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ var |= (__b & 0x7f) << 14; \ if (__b & 0x80) \ { \ __b = *((const unsigned char *) addr); \ addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ var |= (__b & 0x7f) << 21; \ if (__b & 0x80) \ /* Other implementation set VALUE to UINT_MAX in this \ case. So we better do this as well. */ \ var = UINT_MAX; \ } \ } \ } \ } while (0) /* The signed case is a big more complicated. */ #define get_sleb128(var, addr) \ do { \ unsigned char __b = *((const unsigned char *) addr); \ addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ int32_t __res = __b & 0x7f; \ if ((__b & 0x80) == 0) \ { \ if (__b & 0x40) \ __res |= 0xffffff80; \ } \ else \ { \ __b = *((const unsigned char *) addr); \ addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ __res |= (__b & 0x7f) << 7; \ if ((__b & 0x80) == 0) \ { \ if (__b & 0x40) \ __res |= 0xffffc000; \ } \ else \ { \ __b = *((const unsigned char *) addr); \ addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ __res |= (__b & 0x7f) << 14; \ if ((__b & 0x80) == 0) \ { \ if (__b & 0x40) \ __res |= 0xffe00000; \ } \ else \ { \ __b = *((const unsigned char *) addr); \ addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ __res |= (__b & 0x7f) << 21; \ if ((__b & 0x80) == 0) \ { \ if (__b & 0x40) \ __res |= 0xf0000000; \ } \ else \ /* Other implementation set VALUE to INT_MAX in this \ case. So we better do this as well. */ \ __res = INT_MAX; \ } \ } \ } \ var = __res; \ } while (0) /* We use simple memory access functions in case the hardware allows it. The caller has to make sure we don't have alias problems. */ #if ALLOW_UNALIGNED # define read_2ubyte_unaligned(Dbg, Addr) \ (unlikely ((Dbg)->other_byte_order) \ ? bswap_16 (*((const uint16_t *) (Addr))) \ : *((const uint16_t *) (Addr))) # define read_2sbyte_unaligned(Dbg, Addr) \ (unlikely ((Dbg)->other_byte_order) \ ? (int16_t) bswap_16 (*((const int16_t *) (Addr))) \ : *((const int16_t *) (Addr))) # define read_4ubyte_unaligned_noncvt(Addr) \ *((const uint32_t *) (Addr)) # define read_4ubyte_unaligned(Dbg, Addr) \ (unlikely ((Dbg)->other_byte_order) \ ? bswap_32 (*((const uint32_t *) (Addr))) \ : *((const uint32_t *) (Addr))) # define read_4sbyte_unaligned(Dbg, Addr) \ (unlikely ((Dbg)->other_byte_order) \ ? (int32_t) bswap_32 (*((const int32_t *) (Addr))) \ : *((const int32_t *) (Addr))) # define read_8ubyte_unaligned(Dbg, Addr) \ (unlikely ((Dbg)->other_byte_order) \ ? bswap_64 (*((const uint64_t *) (Addr))) \ : *((const uint64_t *) (Addr))) # define read_8sbyte_unaligned(Dbg, Addr) \ (unlikely ((Dbg)->other_byte_order) \ ? (int64_t) bswap_64 (*((const int64_t *) (Addr))) \ : *((const int64_t *) (Addr))) #else union unaligned { void *p; uint16_t u2; uint32_t u4; uint64_t u8; int16_t s2; int32_t s4; int64_t s8; } __attribute__ ((packed)); static inline uint16_t read_2ubyte_unaligned (Dwarf *dbg, const void *p) { const union unaligned *up = p; if (dbg->other_byte_order) return bswap_16 (up->u2); return up->u2; } static inline int16_t read_2sbyte_unaligned (Dwarf *dbg, const void *p) { const union unaligned *up = p; if (dbg->other_byte_order) return (int16_t) bswap_16 (up->u2); return up->s2; } static inline uint32_t read_4ubyte_unaligned_noncvt (const void *p) { const union unaligned *up = p; return up->u4; } static inline uint32_t read_4ubyte_unaligned (Dwarf *dbg, const void *p) { const union unaligned *up = p; if (dbg->other_byte_order) return bswap_32 (up->u4); return up->u4; } static inline int32_t read_4sbyte_unaligned (Dwarf *dbg, const void *p) { const union unaligned *up = p; if (dbg->other_byte_order) return (int32_t) bswap_32 (up->u4); return up->s4; } static inline uint64_t read_8ubyte_unaligned (Dwarf *dbg, const void *p) { const union unaligned *up = p; if (dbg->other_byte_order) return bswap_64 (up->u8); return up->u8; } static inline int64_t read_8sbyte_unaligned (Dwarf *dbg, const void *p) { const union unaligned *up = p; if (dbg->other_byte_order) return (int64_t) bswap_64 (up->u8); return up->s8; } #endif /* allow unaligned */ #define read_2ubyte_unaligned_inc(Dbg, Addr) \ ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr); \ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ t_; }) #define read_2sbyte_unaligned_inc(Dbg, Addr) \ ({ int16_t t_ = read_2sbyte_unaligned (Dbg, Addr); \ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ t_; }) #define read_4ubyte_unaligned_inc(Dbg, Addr) \ ({ uint32_t t_ = read_4ubyte_unaligned (Dbg, Addr); \ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ t_; }) #define read_4sbyte_unaligned_inc(Dbg, Addr) \ ({ int32_t t_ = read_4sbyte_unaligned (Dbg, Addr); \ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ t_; }) #define read_8ubyte_unaligned_inc(Dbg, Addr) \ ({ uint64_t t_ = read_8ubyte_unaligned (Dbg, Addr); \ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ t_; }) #define read_8sbyte_unaligned_inc(Dbg, Addr) \ ({ int64_t t_ = read_8sbyte_unaligned (Dbg, Addr); \ Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ t_; }) #endif /* memory-access.h */