1/* Unaligned memory access functionality. 2 Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper@redhat.com>, 2001. 4 5 This program is Open Source software; you can redistribute it and/or 6 modify it under the terms of the Open Software License version 1.0 as 7 published by the Open Source Initiative. 8 9 You should have received a copy of the Open Software License along 10 with this program; if not, you may obtain a copy of the Open Software 11 License version 1.0 from http://www.opensource.org/licenses/osl.php or 12 by writing the Open Source Initiative c/o Lawrence Rosen, Esq., 13 3001 King Ranch Road, Ukiah, CA 95482. */ 14 15#ifndef _MEMORY_ACCESS_H 16#define _MEMORY_ACCESS_H 1 17 18#include <byteswap.h> 19#include <limits.h> 20#include <stdint.h> 21 22 23/* Number decoding macros. See 7.6 Variable Length Data. */ 24#define get_uleb128(var, addr) \ 25 do { \ 26 unsigned char __b = *((const unsigned char *) addr); \ 27 addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ 28 var = __b & 0x7f; \ 29 if (__b & 0x80) \ 30 { \ 31 __b = *((const unsigned char *) addr); \ 32 addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ 33 var |= (__b & 0x7f) << 7; \ 34 if (__b & 0x80) \ 35 { \ 36 __b = *((const unsigned char *) addr); \ 37 addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ 38 var |= (__b & 0x7f) << 14; \ 39 if (__b & 0x80) \ 40 { \ 41 __b = *((const unsigned char *) addr); \ 42 addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ 43 var |= (__b & 0x7f) << 21; \ 44 if (__b & 0x80) \ 45 /* Other implementation set VALUE to UINT_MAX in this \ 46 case. So we better do this as well. */ \ 47 var = UINT_MAX; \ 48 } \ 49 } \ 50 } \ 51 } while (0) 52 53/* The signed case is a big more complicated. */ 54#define get_sleb128(var, addr) \ 55 do { \ 56 unsigned char __b = *((const unsigned char *) addr); \ 57 addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ 58 int32_t __res = __b & 0x7f; \ 59 if ((__b & 0x80) == 0) \ 60 { \ 61 if (__b & 0x40) \ 62 __res |= 0xffffff80; \ 63 } \ 64 else \ 65 { \ 66 __b = *((const unsigned char *) addr); \ 67 addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ 68 __res |= (__b & 0x7f) << 7; \ 69 if ((__b & 0x80) == 0) \ 70 { \ 71 if (__b & 0x40) \ 72 __res |= 0xffffc000; \ 73 } \ 74 else \ 75 { \ 76 __b = *((const unsigned char *) addr); \ 77 addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ 78 __res |= (__b & 0x7f) << 14; \ 79 if ((__b & 0x80) == 0) \ 80 { \ 81 if (__b & 0x40) \ 82 __res |= 0xffe00000; \ 83 } \ 84 else \ 85 { \ 86 __b = *((const unsigned char *) addr); \ 87 addr = (__typeof (addr)) (((uintptr_t) (addr)) + 1); \ 88 __res |= (__b & 0x7f) << 21; \ 89 if ((__b & 0x80) == 0) \ 90 { \ 91 if (__b & 0x40) \ 92 __res |= 0xf0000000; \ 93 } \ 94 else \ 95 /* Other implementation set VALUE to INT_MAX in this \ 96 case. So we better do this as well. */ \ 97 __res = INT_MAX; \ 98 } \ 99 } \ 100 } \ 101 var = __res; \ 102 } while (0) 103 104 105/* We use simple memory access functions in case the hardware allows it. 106 The caller has to make sure we don't have alias problems. */ 107#if ALLOW_UNALIGNED 108 109# define read_2ubyte_unaligned(Dbg, Addr) \ 110 (unlikely ((Dbg)->other_byte_order) \ 111 ? bswap_16 (*((const uint16_t *) (Addr))) \ 112 : *((const uint16_t *) (Addr))) 113# define read_2sbyte_unaligned(Dbg, Addr) \ 114 (unlikely ((Dbg)->other_byte_order) \ 115 ? (int16_t) bswap_16 (*((const int16_t *) (Addr))) \ 116 : *((const int16_t *) (Addr))) 117 118# define read_4ubyte_unaligned_noncvt(Addr) \ 119 *((const uint32_t *) (Addr)) 120# define read_4ubyte_unaligned(Dbg, Addr) \ 121 (unlikely ((Dbg)->other_byte_order) \ 122 ? bswap_32 (*((const uint32_t *) (Addr))) \ 123 : *((const uint32_t *) (Addr))) 124# define read_4sbyte_unaligned(Dbg, Addr) \ 125 (unlikely ((Dbg)->other_byte_order) \ 126 ? (int32_t) bswap_32 (*((const int32_t *) (Addr))) \ 127 : *((const int32_t *) (Addr))) 128 129# define read_8ubyte_unaligned(Dbg, Addr) \ 130 (unlikely ((Dbg)->other_byte_order) \ 131 ? bswap_64 (*((const uint64_t *) (Addr))) \ 132 : *((const uint64_t *) (Addr))) 133# define read_8sbyte_unaligned(Dbg, Addr) \ 134 (unlikely ((Dbg)->other_byte_order) \ 135 ? (int64_t) bswap_64 (*((const int64_t *) (Addr))) \ 136 : *((const int64_t *) (Addr))) 137 138#else 139 140union unaligned 141 { 142 void *p; 143 uint16_t u2; 144 uint32_t u4; 145 uint64_t u8; 146 int16_t s2; 147 int32_t s4; 148 int64_t s8; 149 } __attribute__ ((packed)); 150 151static inline uint16_t 152read_2ubyte_unaligned (Dwarf *dbg, const void *p) 153{ 154 const union unaligned *up = p; 155 if (dbg->other_byte_order) 156 return bswap_16 (up->u2); 157 return up->u2; 158} 159static inline int16_t 160read_2sbyte_unaligned (Dwarf *dbg, const void *p) 161{ 162 const union unaligned *up = p; 163 if (dbg->other_byte_order) 164 return (int16_t) bswap_16 (up->u2); 165 return up->s2; 166} 167 168static inline uint32_t 169read_4ubyte_unaligned_noncvt (const void *p) 170{ 171 const union unaligned *up = p; 172 return up->u4; 173} 174static inline uint32_t 175read_4ubyte_unaligned (Dwarf *dbg, const void *p) 176{ 177 const union unaligned *up = p; 178 if (dbg->other_byte_order) 179 return bswap_32 (up->u4); 180 return up->u4; 181} 182static inline int32_t 183read_4sbyte_unaligned (Dwarf *dbg, const void *p) 184{ 185 const union unaligned *up = p; 186 if (dbg->other_byte_order) 187 return (int32_t) bswap_32 (up->u4); 188 return up->s4; 189} 190 191static inline uint64_t 192read_8ubyte_unaligned (Dwarf *dbg, const void *p) 193{ 194 const union unaligned *up = p; 195 if (dbg->other_byte_order) 196 return bswap_64 (up->u8); 197 return up->u8; 198} 199static inline int64_t 200read_8sbyte_unaligned (Dwarf *dbg, const void *p) 201{ 202 const union unaligned *up = p; 203 if (dbg->other_byte_order) 204 return (int64_t) bswap_64 (up->u8); 205 return up->s8; 206} 207 208#endif /* allow unaligned */ 209 210 211#define read_2ubyte_unaligned_inc(Dbg, Addr) \ 212 ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr); \ 213 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ 214 t_; }) 215#define read_2sbyte_unaligned_inc(Dbg, Addr) \ 216 ({ int16_t t_ = read_2sbyte_unaligned (Dbg, Addr); \ 217 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ 218 t_; }) 219 220#define read_4ubyte_unaligned_inc(Dbg, Addr) \ 221 ({ uint32_t t_ = read_4ubyte_unaligned (Dbg, Addr); \ 222 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ 223 t_; }) 224#define read_4sbyte_unaligned_inc(Dbg, Addr) \ 225 ({ int32_t t_ = read_4sbyte_unaligned (Dbg, Addr); \ 226 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ 227 t_; }) 228 229#define read_8ubyte_unaligned_inc(Dbg, Addr) \ 230 ({ uint64_t t_ = read_8ubyte_unaligned (Dbg, Addr); \ 231 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ 232 t_; }) 233#define read_8sbyte_unaligned_inc(Dbg, Addr) \ 234 ({ int64_t t_ = read_8sbyte_unaligned (Dbg, Addr); \ 235 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ 236 t_; }) 237 238#endif /* memory-access.h */ 239