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