1 /* Unaligned memory access functionality.
2 Copyright (C) 2000-2010 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2001.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
9 * the GNU Lesser General Public License as published by the Free
10 Software Foundation; either version 3 of the License, or (at
11 your option) any later version
15 * the GNU General Public License as published by the Free
16 Software Foundation; either version 2 of the License, or (at
17 your option) any later version
19 or both in parallel, as here.
21 elfutils is distributed in the hope that it will be useful, but
22 WITHOUT ANY WARRANTY; without even the implied warranty of
23 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 General Public License for more details.
26 You should have received copies of the GNU General Public License and
27 the GNU Lesser General Public License along with this program. If
28 not, see <http://www.gnu.org/licenses/>. */
30 #ifndef _MEMORY_ACCESS_H
31 #define _MEMORY_ACCESS_H 1
38 /* Number decoding macros. See 7.6 Variable Length Data. */
40 #define get_uleb128_step(var, addr, nth, break) \
42 var |= (uintmax_t) (__b & 0x7f) << (nth * 7); \
43 if (likely ((__b & 0x80) == 0)) \
46 #define get_uleb128(var, addr) \
50 get_uleb128_step (var, addr, 0, break); \
51 var = __libdw_get_uleb128 (var, 1, &(addr)); \
54 #define get_uleb128_rest_return(var, i, addrp) \
58 get_uleb128_step (var, *addrp, i, return var); \
60 /* Other implementations set VALUE to UINT_MAX in this \
61 case. So we better do this as well. */ \
65 /* The signed case is similar, but we sign-extend the result. */
67 #define get_sleb128_step(var, addr, nth, break) \
69 _v |= (uint64_t) (__b & 0x7f) << (nth * 7); \
70 if (likely ((__b & 0x80) == 0)) \
72 var = (_v << (64 - (nth * 7) - 7)) >> (64 - (nth * 7) - 7); \
77 #define get_sleb128(var, addr) \
81 get_sleb128_step (var, addr, 0, break); \
82 var = __libdw_get_sleb128 (_v, 1, &(addr)); \
85 #define get_sleb128_rest_return(var, i, addrp) \
89 get_sleb128_step (var, *addrp, i, return var); \
92 if (likely ((__b & 0x80) == 0)) \
93 return var | ((uint64_t) __b << 63); \
95 /* Other implementations set VALUE to INT_MAX in this \
96 case. So we better do this as well. */ \
101 extern uint64_t __libdw_get_uleb128 (uint64_t acc, unsigned int i,
102 const unsigned char **addrp)
103 internal_function attribute_hidden;
104 extern int64_t __libdw_get_sleb128 (int64_t acc, unsigned int i,
105 const unsigned char **addrp)
106 internal_function attribute_hidden;
108 static inline uint64_t
109 __attribute__ ((unused))
110 __libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp)
113 get_uleb128_rest_return (acc, i, addrp);
115 static inline int64_t
116 __attribute__ ((unused))
117 __libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp)
121 get_sleb128_rest_return (acc, i, addrp);
126 /* We use simple memory access functions in case the hardware allows it.
127 The caller has to make sure we don't have alias problems. */
130 # define read_2ubyte_unaligned(Dbg, Addr) \
131 (unlikely ((Dbg)->other_byte_order) \
132 ? bswap_16 (*((const uint16_t *) (Addr))) \
133 : *((const uint16_t *) (Addr)))
134 # define read_2sbyte_unaligned(Dbg, Addr) \
135 (unlikely ((Dbg)->other_byte_order) \
136 ? (int16_t) bswap_16 (*((const int16_t *) (Addr))) \
137 : *((const int16_t *) (Addr)))
139 # define read_4ubyte_unaligned_noncvt(Addr) \
140 *((const uint32_t *) (Addr))
141 # define read_4ubyte_unaligned(Dbg, Addr) \
142 (unlikely ((Dbg)->other_byte_order) \
143 ? bswap_32 (*((const uint32_t *) (Addr))) \
144 : *((const uint32_t *) (Addr)))
145 # define read_4sbyte_unaligned(Dbg, Addr) \
146 (unlikely ((Dbg)->other_byte_order) \
147 ? (int32_t) bswap_32 (*((const int32_t *) (Addr))) \
148 : *((const int32_t *) (Addr)))
150 # define read_8ubyte_unaligned(Dbg, Addr) \
151 (unlikely ((Dbg)->other_byte_order) \
152 ? bswap_64 (*((const uint64_t *) (Addr))) \
153 : *((const uint64_t *) (Addr)))
154 # define read_8sbyte_unaligned(Dbg, Addr) \
155 (unlikely ((Dbg)->other_byte_order) \
156 ? (int64_t) bswap_64 (*((const int64_t *) (Addr))) \
157 : *((const int64_t *) (Addr)))
170 } __attribute__ ((packed));
172 # define read_2ubyte_unaligned(Dbg, Addr) \
173 read_2ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
174 # define read_2sbyte_unaligned(Dbg, Addr) \
175 read_2sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
176 # define read_4ubyte_unaligned(Dbg, Addr) \
177 read_4ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
178 # define read_4sbyte_unaligned(Dbg, Addr) \
179 read_4sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
180 # define read_8ubyte_unaligned(Dbg, Addr) \
181 read_8ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
182 # define read_8sbyte_unaligned(Dbg, Addr) \
183 read_8sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
185 static inline uint16_t
186 read_2ubyte_unaligned_1 (bool other_byte_order, const void *p)
188 const union unaligned *up = p;
189 if (unlikely (other_byte_order))
190 return bswap_16 (up->u2);
193 static inline int16_t
194 read_2sbyte_unaligned_1 (bool other_byte_order, const void *p)
196 const union unaligned *up = p;
197 if (unlikely (other_byte_order))
198 return (int16_t) bswap_16 (up->u2);
202 static inline uint32_t
203 read_4ubyte_unaligned_noncvt (const void *p)
205 const union unaligned *up = p;
208 static inline uint32_t
209 read_4ubyte_unaligned_1 (bool other_byte_order, const void *p)
211 const union unaligned *up = p;
212 if (unlikely (other_byte_order))
213 return bswap_32 (up->u4);
216 static inline int32_t
217 read_4sbyte_unaligned_1 (bool other_byte_order, const void *p)
219 const union unaligned *up = p;
220 if (unlikely (other_byte_order))
221 return (int32_t) bswap_32 (up->u4);
225 static inline uint64_t
226 read_8ubyte_unaligned_1 (bool other_byte_order, const void *p)
228 const union unaligned *up = p;
229 if (unlikely (other_byte_order))
230 return bswap_64 (up->u8);
233 static inline int64_t
234 read_8sbyte_unaligned_1 (bool other_byte_order, const void *p)
236 const union unaligned *up = p;
237 if (unlikely (other_byte_order))
238 return (int64_t) bswap_64 (up->u8);
242 #endif /* allow unaligned */
245 #define read_ubyte_unaligned(Nbytes, Dbg, Addr) \
246 ((Nbytes) == 2 ? read_2ubyte_unaligned (Dbg, Addr) \
247 : (Nbytes) == 4 ? read_4ubyte_unaligned (Dbg, Addr) \
248 : read_8ubyte_unaligned (Dbg, Addr))
250 #define read_sbyte_unaligned(Nbytes, Dbg, Addr) \
251 ((Nbytes) == 2 ? read_2sbyte_unaligned (Dbg, Addr) \
252 : (Nbytes) == 4 ? read_4sbyte_unaligned (Dbg, Addr) \
253 : read_8sbyte_unaligned (Dbg, Addr))
256 #define read_2ubyte_unaligned_inc(Dbg, Addr) \
257 ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr); \
258 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \
260 #define read_2sbyte_unaligned_inc(Dbg, Addr) \
261 ({ int16_t t_ = read_2sbyte_unaligned (Dbg, Addr); \
262 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \
265 #define read_4ubyte_unaligned_inc(Dbg, Addr) \
266 ({ uint32_t t_ = read_4ubyte_unaligned (Dbg, Addr); \
267 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \
269 #define read_4sbyte_unaligned_inc(Dbg, Addr) \
270 ({ int32_t t_ = read_4sbyte_unaligned (Dbg, Addr); \
271 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \
274 #define read_8ubyte_unaligned_inc(Dbg, Addr) \
275 ({ uint64_t t_ = read_8ubyte_unaligned (Dbg, Addr); \
276 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \
278 #define read_8sbyte_unaligned_inc(Dbg, Addr) \
279 ({ int64_t t_ = read_8sbyte_unaligned (Dbg, Addr); \
280 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \
284 #define read_ubyte_unaligned_inc(Nbytes, Dbg, Addr) \
285 ((Nbytes) == 2 ? read_2ubyte_unaligned_inc (Dbg, Addr) \
286 : (Nbytes) == 4 ? read_4ubyte_unaligned_inc (Dbg, Addr) \
287 : read_8ubyte_unaligned_inc (Dbg, Addr))
289 #define read_sbyte_unaligned_inc(Nbytes, Dbg, Addr) \
290 ((Nbytes) == 2 ? read_2sbyte_unaligned_inc (Dbg, Addr) \
291 : (Nbytes) == 4 ? read_4sbyte_unaligned_inc (Dbg, Addr) \
292 : read_8sbyte_unaligned_inc (Dbg, Addr))
294 #endif /* memory-access.h */