LCOV - code coverage report
Current view: top level - elfutils/libdw - memory-access.h (source / functions) Hit Total Coverage
Test: lcov.out Lines: 4 4 100.0 %
Date: 2013-03-08 Functions: 1 1 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 17 282 6.0 %

           Branch data     Line data    Source code
       1                 :            : /* Unaligned memory access functionality.
       2                 :            :    Copyright (C) 2000-2013 Red Hat, Inc.
       3                 :            :    This file is part of elfutils.
       4                 :            :    Written by Ulrich Drepper <drepper@redhat.com>, 2001.
       5                 :            : 
       6                 :            :    This file is free software; you can redistribute it and/or modify
       7                 :            :    it under the terms of either
       8                 :            : 
       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
      12                 :            : 
      13                 :            :    or
      14                 :            : 
      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
      18                 :            : 
      19                 :            :    or both in parallel, as here.
      20                 :            : 
      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.
      25                 :            : 
      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/>.  */
      29                 :            : 
      30                 :            : #ifndef _MEMORY_ACCESS_H
      31                 :            : #define _MEMORY_ACCESS_H 1
      32                 :            : 
      33                 :            : #include <byteswap.h>
      34                 :            : #include <limits.h>
      35                 :            : #include <stdint.h>
      36                 :            : 
      37                 :            : 
      38                 :            : /* Number decoding macros.  See 7.6 Variable Length Data.  */
      39                 :            : 
      40                 :            : #define get_uleb128_step(var, addr, nth, break)                               \
      41                 :            :     __b = *(addr)++;                                                          \
      42                 :            :     var |= (uintmax_t) (__b & 0x7f) << (nth * 7);                           \
      43                 :            :     if (likely ((__b & 0x80) == 0))                                       \
      44                 :            :       break
      45                 :            : 
      46                 :            : #define get_uleb128(var, addr)                                                \
      47                 :            :   do {                                                                        \
      48                 :            :     unsigned char __b;                                                        \
      49                 :            :     var = 0;                                                                  \
      50                 :            :     get_uleb128_step (var, addr, 0, break);                                   \
      51                 :            :     var = __libdw_get_uleb128 (var, 1, &(addr));                          \
      52                 :            :   } while (0)
      53                 :            : 
      54                 :            : #define get_uleb128_rest_return(var, i, addrp)                                \
      55                 :            :   do {                                                                        \
      56                 :            :     for (; i < 10; ++i)                                                            \
      57                 :            :       {                                                                       \
      58                 :            :         get_uleb128_step (var, *addrp, i, return var);                        \
      59                 :            :       }                                                                       \
      60                 :            :     /* Other implementations set VALUE to UINT_MAX in this                    \
      61                 :            :        case.  So we better do this as well.  */                               \
      62                 :            :     return UINT64_MAX;                                                        \
      63                 :            :   } while (0)
      64                 :            : 
      65                 :            : /* The signed case is similar, but we sign-extend the result.  */
      66                 :            : 
      67                 :            : #define get_sleb128_step(var, addr, nth, break)                               \
      68                 :            :     __b = *(addr)++;                                                          \
      69                 :            :     _v |= (uint64_t) (__b & 0x7f) << (nth * 7);                                     \
      70                 :            :     if (likely ((__b & 0x80) == 0))                                       \
      71                 :            :       {                                                                       \
      72                 :            :         var = (_v << (64 - (nth * 7) - 7)) >> (64 - (nth * 7) - 7);       \
      73                 :            :         break;                                                                \
      74                 :            :       }                                                                       \
      75                 :            :     else do {} while (0)
      76                 :            : 
      77                 :            : #define get_sleb128(var, addr)                                                \
      78                 :            :   do {                                                                        \
      79                 :            :     unsigned char __b;                                                        \
      80                 :            :     int64_t _v = 0;                                                           \
      81                 :            :     get_sleb128_step (var, addr, 0, break);                                   \
      82                 :            :     var = __libdw_get_sleb128 (_v, 1, &(addr));                                   \
      83                 :            :   } while (0)
      84                 :            : 
      85                 :            : #define get_sleb128_rest_return(var, i, addrp)                                \
      86                 :            :   do {                                                                        \
      87                 :            :     for (; i < 9; ++i)                                                             \
      88                 :            :       {                                                                       \
      89                 :            :         get_sleb128_step (var, *addrp, i, return var);                        \
      90                 :            :       }                                                                       \
      91                 :            :     __b = *(*addrp)++;                                                        \
      92                 :            :     if (likely ((__b & 0x80) == 0))                                       \
      93                 :            :       return var | ((uint64_t) __b << 63);                                      \
      94                 :            :     else                                                                      \
      95                 :            :       /* Other implementations set VALUE to INT_MAX in this                   \
      96                 :            :          case.  So we better do this as well.  */                             \
      97                 :            :       return INT64_MAX;                                                       \
      98                 :            :   } while (0)
      99                 :            : 
     100                 :            : #ifdef IS_LIBDW
     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;
     107                 :            : #else
     108                 :            : static inline uint64_t
     109                 :            : __attribute__ ((unused))
     110                 :            : __libdw_get_uleb128 (uint64_t acc, unsigned int i, const unsigned char **addrp)
     111                 :            : {
     112                 :            :   unsigned char __b;
     113 [ #  # ][ #  # ]:       1927 :   get_uleb128_rest_return (acc, i, addrp);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ -  + ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  + ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ -  + ][ +  - ]
         [ #  # ][ #  # ]
         [ -  + ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ +  + ][ +  - ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     114                 :            : }
     115                 :            : static inline int64_t
     116                 :            : __attribute__ ((unused))
     117                 :      42084 : __libdw_get_sleb128 (int64_t acc, unsigned int i, const unsigned char **addrp)
     118                 :            : {
     119                 :            :   unsigned char __b;
     120                 :      42084 :   int64_t _v = acc;
     121 [ +  + ][ +  + ]:      44067 :   get_sleb128_rest_return (acc, i, addrp);
                 [ +  - ]
     122                 :            : }
     123                 :            : #endif
     124                 :            : 
     125                 :            : 
     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.  */
     128                 :            : #if ALLOW_UNALIGNED
     129                 :            : 
     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)))
     138                 :            : 
     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)))
     149                 :            : 
     150                 :            : # define read_8ubyte_unaligned_noncvt(Addr) \
     151                 :            :    *((const uint64_t *) (Addr))
     152                 :            : # define read_8ubyte_unaligned(Dbg, Addr) \
     153                 :            :   (unlikely ((Dbg)->other_byte_order)                                              \
     154                 :            :    ? bswap_64 (*((const uint64_t *) (Addr)))                                  \
     155                 :            :    : *((const uint64_t *) (Addr)))
     156                 :            : # define read_8sbyte_unaligned(Dbg, Addr) \
     157                 :            :   (unlikely ((Dbg)->other_byte_order)                                              \
     158                 :            :    ? (int64_t) bswap_64 (*((const int64_t *) (Addr)))                         \
     159                 :            :    : *((const int64_t *) (Addr)))
     160                 :            : 
     161                 :            : #else
     162                 :            : 
     163                 :            : union unaligned
     164                 :            :   {
     165                 :            :     void *p;
     166                 :            :     uint16_t u2;
     167                 :            :     uint32_t u4;
     168                 :            :     uint64_t u8;
     169                 :            :     int16_t s2;
     170                 :            :     int32_t s4;
     171                 :            :     int64_t s8;
     172                 :            :   } __attribute__ ((packed));
     173                 :            : 
     174                 :            : # define read_2ubyte_unaligned(Dbg, Addr) \
     175                 :            :   read_2ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     176                 :            : # define read_2sbyte_unaligned(Dbg, Addr) \
     177                 :            :   read_2sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     178                 :            : # define read_4ubyte_unaligned(Dbg, Addr) \
     179                 :            :   read_4ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     180                 :            : # define read_4sbyte_unaligned(Dbg, Addr) \
     181                 :            :   read_4sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     182                 :            : # define read_8ubyte_unaligned(Dbg, Addr) \
     183                 :            :   read_8ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     184                 :            : # define read_8sbyte_unaligned(Dbg, Addr) \
     185                 :            :   read_8sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     186                 :            : 
     187                 :            : static inline uint16_t
     188                 :            : read_2ubyte_unaligned_1 (bool other_byte_order, const void *p)
     189                 :            : {
     190                 :            :   const union unaligned *up = p;
     191                 :            :   if (unlikely (other_byte_order))
     192                 :            :     return bswap_16 (up->u2);
     193                 :            :   return up->u2;
     194                 :            : }
     195                 :            : static inline int16_t
     196                 :            : read_2sbyte_unaligned_1 (bool other_byte_order, const void *p)
     197                 :            : {
     198                 :            :   const union unaligned *up = p;
     199                 :            :   if (unlikely (other_byte_order))
     200                 :            :     return (int16_t) bswap_16 (up->u2);
     201                 :            :   return up->s2;
     202                 :            : }
     203                 :            : 
     204                 :            : static inline uint32_t
     205                 :            : read_4ubyte_unaligned_noncvt (const void *p)
     206                 :            : {
     207                 :            :   const union unaligned *up = p;
     208                 :            :   return up->u4;
     209                 :            : }
     210                 :            : static inline uint32_t
     211                 :            : read_4ubyte_unaligned_1 (bool other_byte_order, const void *p)
     212                 :            : {
     213                 :            :   const union unaligned *up = p;
     214                 :            :   if (unlikely (other_byte_order))
     215                 :            :     return bswap_32 (up->u4);
     216                 :            :   return up->u4;
     217                 :            : }
     218                 :            : static inline int32_t
     219                 :            : read_4sbyte_unaligned_1 (bool other_byte_order, const void *p)
     220                 :            : {
     221                 :            :   const union unaligned *up = p;
     222                 :            :   if (unlikely (other_byte_order))
     223                 :            :     return (int32_t) bswap_32 (up->u4);
     224                 :            :   return up->s4;
     225                 :            : }
     226                 :            : 
     227                 :            : static inline uint64_t
     228                 :            : read_8ubyte_unaligned_noncvt (const void *p)
     229                 :            : {
     230                 :            :   const union unaligned *up = p;
     231                 :            :   return up->u8;
     232                 :            : }
     233                 :            : static inline uint64_t
     234                 :            : read_8ubyte_unaligned_1 (bool other_byte_order, const void *p)
     235                 :            : {
     236                 :            :   const union unaligned *up = p;
     237                 :            :   if (unlikely (other_byte_order))
     238                 :            :     return bswap_64 (up->u8);
     239                 :            :   return up->u8;
     240                 :            : }
     241                 :            : static inline int64_t
     242                 :            : read_8sbyte_unaligned_1 (bool other_byte_order, const void *p)
     243                 :            : {
     244                 :            :   const union unaligned *up = p;
     245                 :            :   if (unlikely (other_byte_order))
     246                 :            :     return (int64_t) bswap_64 (up->u8);
     247                 :            :   return up->s8;
     248                 :            : }
     249                 :            : 
     250                 :            : #endif  /* allow unaligned */
     251                 :            : 
     252                 :            : 
     253                 :            : #define read_ubyte_unaligned(Nbytes, Dbg, Addr) \
     254                 :            :   ((Nbytes) == 2 ? read_2ubyte_unaligned (Dbg, Addr)                          \
     255                 :            :    : (Nbytes) == 4 ? read_4ubyte_unaligned (Dbg, Addr)                        \
     256                 :            :    : read_8ubyte_unaligned (Dbg, Addr))
     257                 :            : 
     258                 :            : #define read_sbyte_unaligned(Nbytes, Dbg, Addr) \
     259                 :            :   ((Nbytes) == 2 ? read_2sbyte_unaligned (Dbg, Addr)                          \
     260                 :            :    : (Nbytes) == 4 ? read_4sbyte_unaligned (Dbg, Addr)                        \
     261                 :            :    : read_8sbyte_unaligned (Dbg, Addr))
     262                 :            : 
     263                 :            : 
     264                 :            : #define read_2ubyte_unaligned_inc(Dbg, Addr) \
     265                 :            :   ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr);                         \
     266                 :            :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);                     \
     267                 :            :      t_; })
     268                 :            : #define read_2sbyte_unaligned_inc(Dbg, Addr) \
     269                 :            :   ({ int16_t t_ = read_2sbyte_unaligned (Dbg, Addr);                          \
     270                 :            :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);                     \
     271                 :            :      t_; })
     272                 :            : 
     273                 :            : #define read_4ubyte_unaligned_inc(Dbg, Addr) \
     274                 :            :   ({ uint32_t t_ = read_4ubyte_unaligned (Dbg, Addr);                         \
     275                 :            :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);                     \
     276                 :            :      t_; })
     277                 :            : #define read_4sbyte_unaligned_inc(Dbg, Addr) \
     278                 :            :   ({ int32_t t_ = read_4sbyte_unaligned (Dbg, Addr);                          \
     279                 :            :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);                     \
     280                 :            :      t_; })
     281                 :            : 
     282                 :            : #define read_8ubyte_unaligned_inc(Dbg, Addr) \
     283                 :            :   ({ uint64_t t_ = read_8ubyte_unaligned (Dbg, Addr);                         \
     284                 :            :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);                     \
     285                 :            :      t_; })
     286                 :            : #define read_8sbyte_unaligned_inc(Dbg, Addr) \
     287                 :            :   ({ int64_t t_ = read_8sbyte_unaligned (Dbg, Addr);                          \
     288                 :            :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);                     \
     289                 :            :      t_; })
     290                 :            : 
     291                 :            : 
     292                 :            : #define read_ubyte_unaligned_inc(Nbytes, Dbg, Addr) \
     293                 :            :   ((Nbytes) == 2 ? read_2ubyte_unaligned_inc (Dbg, Addr)                      \
     294                 :            :    : (Nbytes) == 4 ? read_4ubyte_unaligned_inc (Dbg, Addr)                    \
     295                 :            :    : read_8ubyte_unaligned_inc (Dbg, Addr))
     296                 :            : 
     297                 :            : #define read_sbyte_unaligned_inc(Nbytes, Dbg, Addr) \
     298                 :            :   ((Nbytes) == 2 ? read_2sbyte_unaligned_inc (Dbg, Addr)                      \
     299                 :            :    : (Nbytes) == 4 ? read_4sbyte_unaligned_inc (Dbg, Addr)                    \
     300                 :            :    : read_8sbyte_unaligned_inc (Dbg, Addr))
     301                 :            : 
     302                 :            : #endif  /* memory-access.h */

Generated by: LCOV version 1.9