Branch data Line data Source code
1 : : /* Unaligned memory access functionality. 2 : : Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc. 3 : : Written by Ulrich Drepper <drepper@redhat.com>, 2001. 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 <byteswap.h> 33 : : #include <endian.h> 34 : : #include <limits.h> 35 : : #include <stdint.h> 36 : : 37 : : 38 : : /* When loading this file we require the macro MACHINE_ENCODING to be 39 : : defined to signal the endianness of the architecture which is 40 : : defined. */ 41 : : #ifndef MACHINE_ENCODING 42 : : # error "MACHINE_ENCODING needs to be defined" 43 : : #endif 44 : : #if MACHINE_ENCODING != __BIG_ENDIAN && MACHINE_ENCODING != __LITTLE_ENDIAN 45 : : # error "MACHINE_ENCODING must signal either big or little endian" 46 : : #endif 47 : : 48 : : 49 : : /* We use simple memory access functions in case the hardware allows it. 50 : : The caller has to make sure we don't have alias problems. */ 51 : : #if ALLOW_UNALIGNED 52 : : 53 : : # define read_2ubyte_unaligned(Addr) \ 54 : : (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \ 55 : : ? bswap_16 (*((const uint16_t *) (Addr))) \ 56 : : : *((const uint16_t *) (Addr))) 57 : : # define read_2sbyte_unaligned(Addr) \ 58 : : (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \ 59 : : ? (int16_t) bswap_16 (*((const int16_t *) (Addr))) \ 60 : : : *((const int16_t *) (Addr))) 61 : : 62 : : # define read_4ubyte_unaligned_noncvt(Addr) \ 63 : : *((const uint32_t *) (Addr)) 64 : : # define read_4ubyte_unaligned(Addr) \ 65 : : (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \ 66 : : ? bswap_32 (*((const uint32_t *) (Addr))) \ 67 : : : *((const uint32_t *) (Addr))) 68 : : # define read_4sbyte_unaligned(Addr) \ 69 : : (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \ 70 : : ? (int32_t) bswap_32 (*((const int32_t *) (Addr))) \ 71 : : : *((const int32_t *) (Addr))) 72 : : 73 : : # define read_8ubyte_unaligned(Addr) \ 74 : : (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \ 75 : : ? bswap_64 (*((const uint64_t *) (Addr))) \ 76 : : : *((const uint64_t *) (Addr))) 77 : : # define read_8sbyte_unaligned(Addr) \ 78 : : (unlikely (MACHINE_ENCODING != __BYTE_ORDER) \ 79 : : ? (int64_t) bswap_64 (*((const int64_t *) (Addr))) \ 80 : : : *((const int64_t *) (Addr))) 81 : : 82 : : #else 83 : : 84 : : union unaligned 85 : : { 86 : : void *p; 87 : : uint16_t u2; 88 : : uint32_t u4; 89 : : uint64_t u8; 90 : : int16_t s2; 91 : : int32_t s4; 92 : : int64_t s8; 93 : : } attribute_packed; 94 : : 95 : : static inline uint16_t 96 : 501 : read_2ubyte_unaligned (const void *p) 97 : : { 98 : 501 : const union unaligned *up = p; 99 : 501 : if (MACHINE_ENCODING != __BYTE_ORDER) 100 : : return bswap_16 (up->u2); 101 [ + + # # : 501 : return up->u2; # # ] 102 : : } 103 : : static inline int16_t 104 : 0 : read_2sbyte_unaligned (const void *p) 105 : : { 106 : 0 : const union unaligned *up = p; 107 : 0 : if (MACHINE_ENCODING != __BYTE_ORDER) 108 : : return (int16_t) bswap_16 (up->u2); 109 : 0 : return up->s2; 110 : : } 111 : : 112 : : static inline uint32_t 113 : : read_4ubyte_unaligned_noncvt (const void *p) 114 : : { 115 : : const union unaligned *up = p; 116 : : return up->u4; 117 : : } 118 : : static inline uint32_t 119 : 297 : read_4ubyte_unaligned (const void *p) 120 : : { 121 : 297 : const union unaligned *up = p; 122 : 297 : if (MACHINE_ENCODING != __BYTE_ORDER) 123 : : return bswap_32 (up->u4); 124 [ + + + + : 297 : return up->u4; + + + + + + + + + - ] 125 : : } 126 : : static inline int32_t 127 : 0 : read_4sbyte_unaligned (const void *p) 128 : : { 129 : 0 : const union unaligned *up = p; 130 : 0 : if (MACHINE_ENCODING != __BYTE_ORDER) 131 : : return (int32_t) bswap_32 (up->u4); 132 [ # # # # : 0 : return up->s4; # # ] 133 : : } 134 : : 135 : : static inline uint64_t 136 : 0 : read_8ubyte_unaligned (const void *p) 137 : : { 138 : 0 : const union unaligned *up = p; 139 : 0 : if (MACHINE_ENCODING != __BYTE_ORDER) 140 : : return bswap_64 (up->u8); 141 : 0 : return up->u8; 142 : : } 143 : : static inline int64_t 144 : : read_8sbyte_unaligned (const void *p) 145 : : { 146 : : const union unaligned *up = p; 147 : : if (MACHINE_ENCODING != __BYTE_ORDER) 148 : : return (int64_t) bswap_64 (up->u8); 149 : : return up->s8; 150 : : } 151 : : 152 : : #endif /* allow unaligned */ 153 : : 154 : : 155 : : #define read_2ubyte_unaligned_inc(Addr) \ 156 : : ({ uint16_t t_ = read_2ubyte_unaligned (Addr); \ 157 : : Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ 158 : : t_; }) 159 : : #define read_2sbyte_unaligned_inc(Addr) \ 160 : : ({ int16_t t_ = read_2sbyte_unaligned (Addr); \ 161 : : Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2); \ 162 : : t_; }) 163 : : 164 : : #define read_4ubyte_unaligned_inc(Addr) \ 165 : : ({ uint32_t t_ = read_4ubyte_unaligned (Addr); \ 166 : : Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ 167 : : t_; }) 168 : : #define read_4sbyte_unaligned_inc(Addr) \ 169 : : ({ int32_t t_ = read_4sbyte_unaligned (Addr); \ 170 : : Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4); \ 171 : : t_; }) 172 : : 173 : : #define read_8ubyte_unaligned_inc(Addr) \ 174 : : ({ uint64_t t_ = read_8ubyte_unaligned (Addr); \ 175 : : Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ 176 : : t_; }) 177 : : #define read_8sbyte_unaligned_inc(Addr) \ 178 : : ({ int64_t t_ = read_8sbyte_unaligned (Addr); \ 179 : : Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8); \ 180 : : t_; }) 181 : : 182 : : #endif /* memory-access.h */