1 /* Unaligned memory access functionality. 2 Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc. 3 Written by Ulrich Drepper <drepper (at) 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 140 union 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 151 static inline uint16_t 152 read_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 } 159 static inline int16_t 160 read_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 168 static inline uint32_t 169 read_4ubyte_unaligned_noncvt (const void *p) 170 { 171 const union unaligned *up = p; 172 return up->u4; 173 } 174 static inline uint32_t 175 read_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 } 182 static inline int32_t 183 read_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 191 static inline uint64_t 192 read_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 } 199 static inline int64_t 200 read_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