• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
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
read_2ubyte_unaligned(Dwarf * dbg,const void * p)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
read_2sbyte_unaligned(Dwarf * dbg,const void * p)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
read_4ubyte_unaligned_noncvt(const void * p)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
read_4ubyte_unaligned(Dwarf * dbg,const void * p)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
read_4sbyte_unaligned(Dwarf * dbg,const void * p)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
read_8ubyte_unaligned(Dwarf * dbg,const void * p)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
read_8sbyte_unaligned(Dwarf * dbg,const void * p)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