1 /* Unaligned memory access functionality.
2 Copyright (C) 2000-2014, 2018 Red Hat, Inc.
3 This file is part of elfutils.
4
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
7
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
11
12 or
13
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
17
18 or both in parallel, as here.
19
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
24
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
28
29 #ifndef _MEMORY_ACCESS_H
30 #define _MEMORY_ACCESS_H 1
31
32 #include <limits.h>
33 #include <stdint.h>
34
35 #include <system.h>
36
37 /* Number decoding macros. See 7.6 Variable Length Data. */
38
39 #define len_leb128(var) ((8 * sizeof (var) + 6) / 7)
40
41 static inline size_t
__libdw_max_len_leb128(const size_t type_len,const unsigned char * addr,const unsigned char * end)42 __libdw_max_len_leb128 (const size_t type_len,
43 const unsigned char *addr, const unsigned char *end)
44 {
45 const size_t pointer_len = likely (addr < end) ? end - addr : 0;
46 return likely (type_len <= pointer_len) ? type_len : pointer_len;
47 }
48
49 static inline size_t
__libdw_max_len_uleb128(const unsigned char * addr,const unsigned char * end)50 __libdw_max_len_uleb128 (const unsigned char *addr, const unsigned char *end)
51 {
52 const size_t type_len = len_leb128 (uint64_t);
53 return __libdw_max_len_leb128 (type_len, addr, end);
54 }
55
56 static inline size_t
__libdw_max_len_sleb128(const unsigned char * addr,const unsigned char * end)57 __libdw_max_len_sleb128 (const unsigned char *addr, const unsigned char *end)
58 {
59 /* Subtract one step, so we don't shift into sign bit. */
60 const size_t type_len = len_leb128 (int64_t) - 1;
61 return __libdw_max_len_leb128 (type_len, addr, end);
62 }
63
64 #define get_uleb128_step(var, addr, nth) \
65 do { \
66 unsigned char __b = *(addr)++; \
67 (var) |= (__typeof (var)) (__b & 0x7f) << ((nth) * 7); \
68 if (likely ((__b & 0x80) == 0)) \
69 return (var); \
70 } while (0)
71
72 static inline uint64_t
__libdw_get_uleb128(const unsigned char ** addrp,const unsigned char * end)73 __libdw_get_uleb128 (const unsigned char **addrp, const unsigned char *end)
74 {
75 const size_t max = __libdw_max_len_uleb128 (*addrp, end);
76 if (unlikely (max == 0))
77 return UINT64_MAX;
78
79 uint64_t acc = 0;
80
81 /* Unroll the first step to help the compiler optimize
82 for the common single-byte case. */
83 get_uleb128_step (acc, *addrp, 0);
84
85 for (size_t i = 1; i < max; ++i)
86 get_uleb128_step (acc, *addrp, i);
87 /* Other implementations set VALUE to UINT_MAX in this
88 case. So we better do this as well. */
89 return UINT64_MAX;
90 }
91
92 static inline uint64_t
__libdw_get_uleb128_unchecked(const unsigned char ** addrp)93 __libdw_get_uleb128_unchecked (const unsigned char **addrp)
94 {
95 uint64_t acc = 0;
96
97 /* Unroll the first step to help the compiler optimize
98 for the common single-byte case. */
99 get_uleb128_step (acc, *addrp, 0);
100
101 const size_t max = len_leb128 (uint64_t);
102 for (size_t i = 1; i < max; ++i)
103 get_uleb128_step (acc, *addrp, i);
104 /* Other implementations set VALUE to UINT_MAX in this
105 case. So we better do this as well. */
106 return UINT64_MAX;
107 }
108
109 /* Note, addr needs to me smaller than end. */
110 #define get_uleb128(var, addr, end) ((var) = __libdw_get_uleb128 (&(addr), end))
111 #define get_uleb128_unchecked(var, addr) ((var) = __libdw_get_uleb128_unchecked (&(addr)))
112
113 /* The signed case is similar, but we sign-extend the result. */
114
115 #define get_sleb128_step(var, addr, nth) \
116 do { \
117 unsigned char __b = *(addr)++; \
118 (var) |= (__typeof (var)) (__b & 0x7f) << ((nth) * 7); \
119 if (likely ((__b & 0x80) == 0)) \
120 { \
121 if ((__b & 0x40) != 0) \
122 (var) |= - ((__typeof (var)) 1 << (((nth) + 1) * 7)); \
123 return (var); \
124 } \
125 } while (0)
126
127 static inline int64_t
__libdw_get_sleb128(const unsigned char ** addrp,const unsigned char * end)128 __libdw_get_sleb128 (const unsigned char **addrp, const unsigned char *end)
129 {
130 const size_t max = __libdw_max_len_sleb128 (*addrp, end);
131 if (unlikely (max == 0))
132 return INT64_MAX;
133
134 /* Do the work in an unsigned type, but use implementation-defined
135 behavior to cast to signed on return. This avoids some undefined
136 behavior when shifting. */
137 uint64_t acc = 0;
138
139 /* Unroll the first step to help the compiler optimize
140 for the common single-byte case. */
141 get_sleb128_step (acc, *addrp, 0);
142
143 for (size_t i = 1; i < max; ++i)
144 get_sleb128_step (acc, *addrp, i);
145 if (*addrp == end)
146 return INT64_MAX;
147
148 /* There might be one extra byte. */
149 unsigned char b = **addrp;
150 ++*addrp;
151 if (likely ((b & 0x80) == 0))
152 {
153 /* We only need the low bit of the final byte, and as it is the
154 sign bit, we don't need to do anything else here. */
155 acc |= ((__typeof (acc)) b) << 7 * max;
156 return acc;
157 }
158
159 /* Other implementations set VALUE to INT_MAX in this
160 case. So we better do this as well. */
161 return INT64_MAX;
162 }
163
164 static inline int64_t
__libdw_get_sleb128_unchecked(const unsigned char ** addrp)165 __libdw_get_sleb128_unchecked (const unsigned char **addrp)
166 {
167 /* Do the work in an unsigned type, but use implementation-defined
168 behavior to cast to signed on return. This avoids some undefined
169 behavior when shifting. */
170 uint64_t acc = 0;
171
172 /* Unroll the first step to help the compiler optimize
173 for the common single-byte case. */
174 get_sleb128_step (acc, *addrp, 0);
175
176 /* Subtract one step, so we don't shift into sign bit. */
177 const size_t max = len_leb128 (int64_t) - 1;
178 for (size_t i = 1; i < max; ++i)
179 get_sleb128_step (acc, *addrp, i);
180
181 /* There might be one extra byte. */
182 unsigned char b = **addrp;
183 ++*addrp;
184 if (likely ((b & 0x80) == 0))
185 {
186 /* We only need the low bit of the final byte, and as it is the
187 sign bit, we don't need to do anything else here. */
188 acc |= ((__typeof (acc)) b) << 7 * max;
189 return acc;
190 }
191
192 /* Other implementations set VALUE to INT_MAX in this
193 case. So we better do this as well. */
194 return INT64_MAX;
195 }
196
197 #define get_sleb128(var, addr, end) ((var) = __libdw_get_sleb128 (&(addr), end))
198 #define get_sleb128_unchecked(var, addr) ((var) = __libdw_get_sleb128_unchecked (&(addr)))
199
200
201 /* We use simple memory access functions in case the hardware allows it.
202 The caller has to make sure we don't have alias problems. */
203 #if ALLOW_UNALIGNED
204
205 # define read_2ubyte_unaligned(Dbg, Addr) \
206 (unlikely ((Dbg)->other_byte_order) \
207 ? bswap_16 (*((const uint16_t *) (Addr))) \
208 : *((const uint16_t *) (Addr)))
209 # define read_2sbyte_unaligned(Dbg, Addr) \
210 (unlikely ((Dbg)->other_byte_order) \
211 ? (int16_t) bswap_16 (*((const int16_t *) (Addr))) \
212 : *((const int16_t *) (Addr)))
213
214 # define read_4ubyte_unaligned_noncvt(Addr) \
215 *((const uint32_t *) (Addr))
216 # define read_4ubyte_unaligned(Dbg, Addr) \
217 (unlikely ((Dbg)->other_byte_order) \
218 ? bswap_32 (*((const uint32_t *) (Addr))) \
219 : *((const uint32_t *) (Addr)))
220 # define read_4sbyte_unaligned(Dbg, Addr) \
221 (unlikely ((Dbg)->other_byte_order) \
222 ? (int32_t) bswap_32 (*((const int32_t *) (Addr))) \
223 : *((const int32_t *) (Addr)))
224
225 # define read_8ubyte_unaligned_noncvt(Addr) \
226 *((const uint64_t *) (Addr))
227 # define read_8ubyte_unaligned(Dbg, Addr) \
228 (unlikely ((Dbg)->other_byte_order) \
229 ? bswap_64 (*((const uint64_t *) (Addr))) \
230 : *((const uint64_t *) (Addr)))
231 # define read_8sbyte_unaligned(Dbg, Addr) \
232 (unlikely ((Dbg)->other_byte_order) \
233 ? (int64_t) bswap_64 (*((const int64_t *) (Addr))) \
234 : *((const int64_t *) (Addr)))
235
236 #else
237
238 union unaligned
239 {
240 void *p;
241 uint16_t u2;
242 uint32_t u4;
243 uint64_t u8;
244 int16_t s2;
245 int32_t s4;
246 int64_t s8;
247 } attribute_packed;
248
249 # define read_2ubyte_unaligned(Dbg, Addr) \
250 read_2ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
251 # define read_2sbyte_unaligned(Dbg, Addr) \
252 read_2sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
253 # define read_4ubyte_unaligned(Dbg, Addr) \
254 read_4ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
255 # define read_4sbyte_unaligned(Dbg, Addr) \
256 read_4sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
257 # define read_8ubyte_unaligned(Dbg, Addr) \
258 read_8ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
259 # define read_8sbyte_unaligned(Dbg, Addr) \
260 read_8sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
261
262 static inline uint16_t
read_2ubyte_unaligned_1(bool other_byte_order,const void * p)263 read_2ubyte_unaligned_1 (bool other_byte_order, const void *p)
264 {
265 const union unaligned *up = p;
266 if (unlikely (other_byte_order))
267 return bswap_16 (up->u2);
268 return up->u2;
269 }
270 static inline int16_t
read_2sbyte_unaligned_1(bool other_byte_order,const void * p)271 read_2sbyte_unaligned_1 (bool other_byte_order, const void *p)
272 {
273 const union unaligned *up = p;
274 if (unlikely (other_byte_order))
275 return (int16_t) bswap_16 (up->u2);
276 return up->s2;
277 }
278
279 static inline uint32_t
read_4ubyte_unaligned_noncvt(const void * p)280 read_4ubyte_unaligned_noncvt (const void *p)
281 {
282 const union unaligned *up = p;
283 return up->u4;
284 }
285 static inline uint32_t
read_4ubyte_unaligned_1(bool other_byte_order,const void * p)286 read_4ubyte_unaligned_1 (bool other_byte_order, const void *p)
287 {
288 const union unaligned *up = p;
289 if (unlikely (other_byte_order))
290 return bswap_32 (up->u4);
291 return up->u4;
292 }
293 static inline int32_t
read_4sbyte_unaligned_1(bool other_byte_order,const void * p)294 read_4sbyte_unaligned_1 (bool other_byte_order, const void *p)
295 {
296 const union unaligned *up = p;
297 if (unlikely (other_byte_order))
298 return (int32_t) bswap_32 (up->u4);
299 return up->s4;
300 }
301
302 static inline uint64_t
read_8ubyte_unaligned_noncvt(const void * p)303 read_8ubyte_unaligned_noncvt (const void *p)
304 {
305 const union unaligned *up = p;
306 return up->u8;
307 }
308 static inline uint64_t
read_8ubyte_unaligned_1(bool other_byte_order,const void * p)309 read_8ubyte_unaligned_1 (bool other_byte_order, const void *p)
310 {
311 const union unaligned *up = p;
312 if (unlikely (other_byte_order))
313 return bswap_64 (up->u8);
314 return up->u8;
315 }
316 static inline int64_t
read_8sbyte_unaligned_1(bool other_byte_order,const void * p)317 read_8sbyte_unaligned_1 (bool other_byte_order, const void *p)
318 {
319 const union unaligned *up = p;
320 if (unlikely (other_byte_order))
321 return (int64_t) bswap_64 (up->u8);
322 return up->s8;
323 }
324
325 #endif /* allow unaligned */
326
327
328 #define read_2ubyte_unaligned_inc(Dbg, Addr) \
329 ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr); \
330 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \
331 t_; })
332 #define read_2sbyte_unaligned_inc(Dbg, Addr) \
333 ({ int16_t t_ = read_2sbyte_unaligned (Dbg, Addr); \
334 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \
335 t_; })
336
337 #define read_4ubyte_unaligned_inc(Dbg, Addr) \
338 ({ uint32_t t_ = read_4ubyte_unaligned (Dbg, Addr); \
339 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \
340 t_; })
341 #define read_4sbyte_unaligned_inc(Dbg, Addr) \
342 ({ int32_t t_ = read_4sbyte_unaligned (Dbg, Addr); \
343 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \
344 t_; })
345
346 #define read_8ubyte_unaligned_inc(Dbg, Addr) \
347 ({ uint64_t t_ = read_8ubyte_unaligned (Dbg, Addr); \
348 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \
349 t_; })
350 #define read_8sbyte_unaligned_inc(Dbg, Addr) \
351 ({ int64_t t_ = read_8sbyte_unaligned (Dbg, Addr); \
352 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \
353 t_; })
354
355 /* 3ubyte reads are only used for DW_FORM_addrx3 and DW_FORM_strx3.
356 And are probably very rare. They are not optimized. They are
357 handled as if reading a 4byte value with the first (for big endian)
358 or last (for little endian) byte zero. */
359
360 static inline int
file_byte_order(bool other_byte_order)361 file_byte_order (bool other_byte_order)
362 {
363 #if BYTE_ORDER == LITTLE_ENDIAN
364 return other_byte_order ? BIG_ENDIAN : LITTLE_ENDIAN;
365 #else
366 return other_byte_order ? LITTLE_ENDIAN : BIG_ENDIAN;
367 #endif
368 }
369
370 static inline uint32_t
read_3ubyte_unaligned(Dwarf * dbg,const unsigned char * p)371 read_3ubyte_unaligned (Dwarf *dbg, const unsigned char *p)
372 {
373 union
374 {
375 uint32_t u4;
376 unsigned char c[4];
377 } d;
378 bool other_byte_order = dbg->other_byte_order;
379
380 if (file_byte_order (other_byte_order) == BIG_ENDIAN)
381 {
382 d.c[0] = 0x00;
383 d.c[1] = p[0];
384 d.c[2] = p[1];
385 d.c[3] = p[2];
386 }
387 else
388 {
389 d.c[0] = p[0];
390 d.c[1] = p[1];
391 d.c[2] = p[2];
392 d.c[3] = 0x00;
393 }
394
395 if (other_byte_order)
396 return bswap_32 (d.u4);
397 else
398 return d.u4;
399 }
400
401
402 #define read_3ubyte_unaligned_inc(Dbg, Addr) \
403 ({ uint32_t t_ = read_3ubyte_unaligned (Dbg, Addr); \
404 Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 3); \
405 t_; })
406
407 #define read_addr_unaligned_inc(Nbytes, Dbg, Addr) \
408 (assert ((Nbytes) == 4 || (Nbytes) == 8), \
409 ((Nbytes) == 4 ? read_4ubyte_unaligned_inc (Dbg, Addr) \
410 : read_8ubyte_unaligned_inc (Dbg, Addr)))
411
412 #endif /* memory-access.h */
413