LCOV - code coverage report
Current view: top level - libdw - memory-access.h (source / functions) Hit Total Coverage
Test: lcov.out Lines: 18 18 100.0 %
Date: 2017-01-05 09:15:16 Functions: 2 2 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* Unaligned memory access functionality.
       2             :    Copyright (C) 2000-2014 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 len_leb128(var) ((8 * sizeof (var) + 6) / 7)
      41             : 
      42             : static inline size_t
      43             : __libdw_max_len_leb128 (const size_t type_len,
      44             :                         const unsigned char *addr, const unsigned char *end)
      45             : {
      46      460945 :   const size_t pointer_len = likely (addr < end) ? end - addr : 0;
      47      460945 :   return likely (type_len <= pointer_len) ? type_len : pointer_len;
      48             : }
      49             : 
      50             : static inline size_t
      51             : __libdw_max_len_uleb128 (const unsigned char *addr, const unsigned char *end)
      52             : {
      53      352627 :   const size_t type_len = len_leb128 (uint64_t);
      54      352627 :   return __libdw_max_len_leb128 (type_len, addr, end);
      55             : }
      56             : 
      57             : static inline size_t
      58             : __libdw_max_len_sleb128 (const unsigned char *addr, const unsigned char *end)
      59             : {
      60             :   /* Subtract one step, so we don't shift into sign bit.  */
      61      108318 :   const size_t type_len = len_leb128 (int64_t) - 1;
      62      108318 :   return __libdw_max_len_leb128 (type_len, addr, end);
      63             : }
      64             : 
      65             : #define get_uleb128_step(var, addr, nth)                                      \
      66             :   do {                                                                        \
      67             :     unsigned char __b = *(addr)++;                                            \
      68             :     (var) |= (typeof (var)) (__b & 0x7f) << ((nth) * 7);                    \
      69             :     if (likely ((__b & 0x80) == 0))                                       \
      70             :       return (var);                                                           \
      71             :   } while (0)
      72             : 
      73             : static inline uint64_t
      74   168922976 : __libdw_get_uleb128 (const unsigned char **addrp, const unsigned char *end)
      75             : {
      76   168922976 :   uint64_t acc = 0;
      77             : 
      78             :   /* Unroll the first step to help the compiler optimize
      79             :      for the common single-byte case.  */
      80   168922976 :   get_uleb128_step (acc, *addrp, 0);
      81             : 
      82      705254 :   const size_t max = __libdw_max_len_uleb128 (*addrp - 1, end);
      83      384675 :   for (size_t i = 1; i < max; ++i)
      84      384675 :     get_uleb128_step (acc, *addrp, i);
      85             :   /* Other implementations set VALUE to UINT_MAX in this
      86             :      case.  So we better do this as well.  */
      87             :   return UINT64_MAX;
      88             : }
      89             : 
      90             : /* Note, addr needs to me smaller than end. */
      91             : #define get_uleb128(var, addr, end) ((var) = __libdw_get_uleb128 (&(addr), end))
      92             : 
      93             : /* The signed case is similar, but we sign-extend the result.  */
      94             : 
      95             : #define get_sleb128_step(var, addr, nth)                                      \
      96             :   do {                                                                        \
      97             :     unsigned char __b = *(addr)++;                                            \
      98             :     if (likely ((__b & 0x80) == 0))                                       \
      99             :       {                                                                       \
     100             :         struct { signed int i:7; } __s = { .i = __b };                        \
     101             :         (var) |= (typeof (var)) __s.i * ((typeof (var)) 1 << ((nth) * 7));    \
     102             :         return (var);                                                         \
     103             :       }                                                                       \
     104             :     (var) |= (typeof (var)) (__b & 0x7f) << ((nth) * 7);                    \
     105             :   } while (0)
     106             : 
     107             : static inline int64_t
     108      271345 : __libdw_get_sleb128 (const unsigned char **addrp, const unsigned char *end)
     109             : {
     110      271345 :   int64_t acc = 0;
     111             : 
     112             :   /* Unroll the first step to help the compiler optimize
     113             :      for the common single-byte case.  */
     114      271345 :   get_sleb128_step (acc, *addrp, 0);
     115             : 
     116      216636 :   const size_t max = __libdw_max_len_sleb128 (*addrp - 1, end);
     117      111894 :   for (size_t i = 1; i < max; ++i)
     118      111877 :     get_sleb128_step (acc, *addrp, i);
     119             :   /* Other implementations set VALUE to INT_MAX in this
     120             :      case.  So we better do this as well.  */
     121             :   return INT64_MAX;
     122             : }
     123             : 
     124             : #define get_sleb128(var, addr, end) ((var) = __libdw_get_sleb128 (&(addr), end))
     125             : 
     126             : 
     127             : /* We use simple memory access functions in case the hardware allows it.
     128             :    The caller has to make sure we don't have alias problems.  */
     129             : #if ALLOW_UNALIGNED
     130             : 
     131             : # define read_2ubyte_unaligned(Dbg, Addr) \
     132             :   (unlikely ((Dbg)->other_byte_order)                                              \
     133             :    ? bswap_16 (*((const uint16_t *) (Addr)))                                  \
     134             :    : *((const uint16_t *) (Addr)))
     135             : # define read_2sbyte_unaligned(Dbg, Addr) \
     136             :   (unlikely ((Dbg)->other_byte_order)                                              \
     137             :    ? (int16_t) bswap_16 (*((const int16_t *) (Addr)))                         \
     138             :    : *((const int16_t *) (Addr)))
     139             : 
     140             : # define read_4ubyte_unaligned_noncvt(Addr) \
     141             :    *((const uint32_t *) (Addr))
     142             : # define read_4ubyte_unaligned(Dbg, Addr) \
     143             :   (unlikely ((Dbg)->other_byte_order)                                              \
     144             :    ? bswap_32 (*((const uint32_t *) (Addr)))                                  \
     145             :    : *((const uint32_t *) (Addr)))
     146             : # define read_4sbyte_unaligned(Dbg, Addr) \
     147             :   (unlikely ((Dbg)->other_byte_order)                                              \
     148             :    ? (int32_t) bswap_32 (*((const int32_t *) (Addr)))                         \
     149             :    : *((const int32_t *) (Addr)))
     150             : 
     151             : # define read_8ubyte_unaligned_noncvt(Addr) \
     152             :    *((const uint64_t *) (Addr))
     153             : # define read_8ubyte_unaligned(Dbg, Addr) \
     154             :   (unlikely ((Dbg)->other_byte_order)                                              \
     155             :    ? bswap_64 (*((const uint64_t *) (Addr)))                                  \
     156             :    : *((const uint64_t *) (Addr)))
     157             : # define read_8sbyte_unaligned(Dbg, Addr) \
     158             :   (unlikely ((Dbg)->other_byte_order)                                              \
     159             :    ? (int64_t) bswap_64 (*((const int64_t *) (Addr)))                         \
     160             :    : *((const int64_t *) (Addr)))
     161             : 
     162             : #else
     163             : 
     164             : union unaligned
     165             :   {
     166             :     void *p;
     167             :     uint16_t u2;
     168             :     uint32_t u4;
     169             :     uint64_t u8;
     170             :     int16_t s2;
     171             :     int32_t s4;
     172             :     int64_t s8;
     173             :   } __attribute__ ((packed));
     174             : 
     175             : # define read_2ubyte_unaligned(Dbg, Addr) \
     176             :   read_2ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     177             : # define read_2sbyte_unaligned(Dbg, Addr) \
     178             :   read_2sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     179             : # define read_4ubyte_unaligned(Dbg, Addr) \
     180             :   read_4ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     181             : # define read_4sbyte_unaligned(Dbg, Addr) \
     182             :   read_4sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     183             : # define read_8ubyte_unaligned(Dbg, Addr) \
     184             :   read_8ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     185             : # define read_8sbyte_unaligned(Dbg, Addr) \
     186             :   read_8sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
     187             : 
     188             : static inline uint16_t
     189             : read_2ubyte_unaligned_1 (bool other_byte_order, const void *p)
     190             : {
     191             :   const union unaligned *up = p;
     192             :   if (unlikely (other_byte_order))
     193             :     return bswap_16 (up->u2);
     194             :   return up->u2;
     195             : }
     196             : static inline int16_t
     197             : read_2sbyte_unaligned_1 (bool other_byte_order, const void *p)
     198             : {
     199             :   const union unaligned *up = p;
     200             :   if (unlikely (other_byte_order))
     201             :     return (int16_t) bswap_16 (up->u2);
     202             :   return up->s2;
     203             : }
     204             : 
     205             : static inline uint32_t
     206             : read_4ubyte_unaligned_noncvt (const void *p)
     207             : {
     208             :   const union unaligned *up = p;
     209             :   return up->u4;
     210             : }
     211             : static inline uint32_t
     212             : read_4ubyte_unaligned_1 (bool other_byte_order, const void *p)
     213             : {
     214             :   const union unaligned *up = p;
     215             :   if (unlikely (other_byte_order))
     216             :     return bswap_32 (up->u4);
     217             :   return up->u4;
     218             : }
     219             : static inline int32_t
     220             : read_4sbyte_unaligned_1 (bool other_byte_order, const void *p)
     221             : {
     222             :   const union unaligned *up = p;
     223             :   if (unlikely (other_byte_order))
     224             :     return (int32_t) bswap_32 (up->u4);
     225             :   return up->s4;
     226             : }
     227             : 
     228             : static inline uint64_t
     229             : read_8ubyte_unaligned_noncvt (const void *p)
     230             : {
     231             :   const union unaligned *up = p;
     232             :   return up->u8;
     233             : }
     234             : static inline uint64_t
     235             : read_8ubyte_unaligned_1 (bool other_byte_order, const void *p)
     236             : {
     237             :   const union unaligned *up = p;
     238             :   if (unlikely (other_byte_order))
     239             :     return bswap_64 (up->u8);
     240             :   return up->u8;
     241             : }
     242             : static inline int64_t
     243             : read_8sbyte_unaligned_1 (bool other_byte_order, const void *p)
     244             : {
     245             :   const union unaligned *up = p;
     246             :   if (unlikely (other_byte_order))
     247             :     return (int64_t) bswap_64 (up->u8);
     248             :   return up->s8;
     249             : }
     250             : 
     251             : #endif  /* allow unaligned */
     252             : 
     253             : 
     254             : #define read_2ubyte_unaligned_inc(Dbg, Addr) \
     255             :   ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr);                         \
     256             :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);                     \
     257             :      t_; })
     258             : #define read_2sbyte_unaligned_inc(Dbg, Addr) \
     259             :   ({ int16_t t_ = read_2sbyte_unaligned (Dbg, Addr);                          \
     260             :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);                     \
     261             :      t_; })
     262             : 
     263             : #define read_4ubyte_unaligned_inc(Dbg, Addr) \
     264             :   ({ uint32_t t_ = read_4ubyte_unaligned (Dbg, Addr);                         \
     265             :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);                     \
     266             :      t_; })
     267             : #define read_4sbyte_unaligned_inc(Dbg, Addr) \
     268             :   ({ int32_t t_ = read_4sbyte_unaligned (Dbg, Addr);                          \
     269             :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);                     \
     270             :      t_; })
     271             : 
     272             : #define read_8ubyte_unaligned_inc(Dbg, Addr) \
     273             :   ({ uint64_t t_ = read_8ubyte_unaligned (Dbg, Addr);                         \
     274             :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);                     \
     275             :      t_; })
     276             : #define read_8sbyte_unaligned_inc(Dbg, Addr) \
     277             :   ({ int64_t t_ = read_8sbyte_unaligned (Dbg, Addr);                          \
     278             :      Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);                     \
     279             :      t_; })
     280             : 
     281             : 
     282             : #define read_addr_unaligned_inc(Nbytes, Dbg, Addr)                      \
     283             :   (assert ((Nbytes) == 4 || (Nbytes) == 8),                             \
     284             :     ((Nbytes) == 4 ? read_4ubyte_unaligned_inc (Dbg, Addr)              \
     285             :      : read_8ubyte_unaligned_inc (Dbg, Addr)))
     286             : 
     287             : #endif  /* memory-access.h */

Generated by: LCOV version 1.12