xref: /dflybsd-src/contrib/gdb-7/include/leb128.h (revision de8e141f24382815c10a4012d209bbbf7abf1112)
1*ef5ccd6cSJohn Marino /* Utilities for reading leb128 values.
2*ef5ccd6cSJohn Marino    Copyright (C) 2012 Free Software Foundation, Inc.
3*ef5ccd6cSJohn Marino 
4*ef5ccd6cSJohn Marino This file is part of the libiberty library.
5*ef5ccd6cSJohn Marino Libiberty is free software; you can redistribute it and/or
6*ef5ccd6cSJohn Marino modify it under the terms of the GNU Library General Public
7*ef5ccd6cSJohn Marino License as published by the Free Software Foundation; either
8*ef5ccd6cSJohn Marino version 2 of the License, or (at your option) any later version.
9*ef5ccd6cSJohn Marino 
10*ef5ccd6cSJohn Marino Libiberty is distributed in the hope that it will be useful,
11*ef5ccd6cSJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of
12*ef5ccd6cSJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13*ef5ccd6cSJohn Marino Library General Public License for more details.
14*ef5ccd6cSJohn Marino 
15*ef5ccd6cSJohn Marino You should have received a copy of the GNU Library General Public
16*ef5ccd6cSJohn Marino License along with libiberty; see the file COPYING.LIB.  If not, write
17*ef5ccd6cSJohn Marino to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
18*ef5ccd6cSJohn Marino Boston, MA 02110-1301, USA.  */
19*ef5ccd6cSJohn Marino 
20*ef5ccd6cSJohn Marino /* The functions defined here can be speed critical.
21*ef5ccd6cSJohn Marino    Since they are all pretty small we keep things simple and just define
22*ef5ccd6cSJohn Marino    them all as "static inline".
23*ef5ccd6cSJohn Marino 
24*ef5ccd6cSJohn Marino    WARNING: This file is used by GDB which is stuck at C90. :-(
25*ef5ccd6cSJohn Marino    Though it can use stdint.h, inttypes.h.
26*ef5ccd6cSJohn Marino    Therefore if you want to add support for "long long" you need
27*ef5ccd6cSJohn Marino    to wrap it in #ifdef CC_HAS_LONG_LONG.  */
28*ef5ccd6cSJohn Marino 
29*ef5ccd6cSJohn Marino #ifndef LEB128_H
30*ef5ccd6cSJohn Marino #define LEB128_H
31*ef5ccd6cSJohn Marino 
32*ef5ccd6cSJohn Marino /* Get a definition for inline.  */
33*ef5ccd6cSJohn Marino #include "ansidecl.h"
34*ef5ccd6cSJohn Marino 
35*ef5ccd6cSJohn Marino /* Get a definition for NULL, size_t.  */
36*ef5ccd6cSJohn Marino #include <stddef.h>
37*ef5ccd6cSJohn Marino 
38*ef5ccd6cSJohn Marino #ifdef HAVE_STDINT_H
39*ef5ccd6cSJohn Marino #include <stdint.h>
40*ef5ccd6cSJohn Marino #endif
41*ef5ccd6cSJohn Marino #ifdef HAVE_INTTYPES_H
42*ef5ccd6cSJohn Marino #include <inttypes.h>
43*ef5ccd6cSJohn Marino #endif
44*ef5ccd6cSJohn Marino 
45*ef5ccd6cSJohn Marino /* Decode the unsigned LEB128 constant at BUF into the variable pointed to
46*ef5ccd6cSJohn Marino    by R, and return the number of bytes read.
47*ef5ccd6cSJohn Marino    If we read off the end of the buffer, zero is returned,
48*ef5ccd6cSJohn Marino    and nothing is stored in R.
49*ef5ccd6cSJohn Marino 
50*ef5ccd6cSJohn Marino    Note: The result is an int instead of a pointer to the next byte to be
51*ef5ccd6cSJohn Marino    read to avoid const-vs-non-const problems.  */
52*ef5ccd6cSJohn Marino 
53*ef5ccd6cSJohn Marino static inline size_t
read_uleb128_to_uint64(const unsigned char * buf,const unsigned char * buf_end,uint64_t * r)54*ef5ccd6cSJohn Marino read_uleb128_to_uint64 (const unsigned char *buf, const unsigned char *buf_end,
55*ef5ccd6cSJohn Marino 			uint64_t *r)
56*ef5ccd6cSJohn Marino {
57*ef5ccd6cSJohn Marino   const unsigned char *p = buf;
58*ef5ccd6cSJohn Marino   unsigned int shift = 0;
59*ef5ccd6cSJohn Marino   uint64_t result = 0;
60*ef5ccd6cSJohn Marino   unsigned char byte;
61*ef5ccd6cSJohn Marino 
62*ef5ccd6cSJohn Marino   while (1)
63*ef5ccd6cSJohn Marino     {
64*ef5ccd6cSJohn Marino       if (p >= buf_end)
65*ef5ccd6cSJohn Marino 	return 0;
66*ef5ccd6cSJohn Marino 
67*ef5ccd6cSJohn Marino       byte = *p++;
68*ef5ccd6cSJohn Marino       result |= ((uint64_t) (byte & 0x7f)) << shift;
69*ef5ccd6cSJohn Marino       if ((byte & 0x80) == 0)
70*ef5ccd6cSJohn Marino 	break;
71*ef5ccd6cSJohn Marino       shift += 7;
72*ef5ccd6cSJohn Marino     }
73*ef5ccd6cSJohn Marino 
74*ef5ccd6cSJohn Marino   *r = result;
75*ef5ccd6cSJohn Marino   return p - buf;
76*ef5ccd6cSJohn Marino }
77*ef5ccd6cSJohn Marino 
78*ef5ccd6cSJohn Marino /* Decode the signed LEB128 constant at BUF into the variable pointed to
79*ef5ccd6cSJohn Marino    by R, and return the number of bytes read.
80*ef5ccd6cSJohn Marino    If we read off the end of the buffer, zero is returned,
81*ef5ccd6cSJohn Marino    and nothing is stored in R.
82*ef5ccd6cSJohn Marino 
83*ef5ccd6cSJohn Marino    Note: The result is an int instead of a pointer to the next byte to be
84*ef5ccd6cSJohn Marino    read to avoid const-vs-non-const problems.  */
85*ef5ccd6cSJohn Marino 
86*ef5ccd6cSJohn Marino static inline size_t
read_sleb128_to_int64(const unsigned char * buf,const unsigned char * buf_end,int64_t * r)87*ef5ccd6cSJohn Marino read_sleb128_to_int64 (const unsigned char *buf, const unsigned char *buf_end,
88*ef5ccd6cSJohn Marino 		       int64_t *r)
89*ef5ccd6cSJohn Marino {
90*ef5ccd6cSJohn Marino   const unsigned char *p = buf;
91*ef5ccd6cSJohn Marino   unsigned int shift = 0;
92*ef5ccd6cSJohn Marino   int64_t result = 0;
93*ef5ccd6cSJohn Marino   unsigned char byte;
94*ef5ccd6cSJohn Marino 
95*ef5ccd6cSJohn Marino   while (1)
96*ef5ccd6cSJohn Marino     {
97*ef5ccd6cSJohn Marino       if (p >= buf_end)
98*ef5ccd6cSJohn Marino 	return 0;
99*ef5ccd6cSJohn Marino 
100*ef5ccd6cSJohn Marino       byte = *p++;
101*ef5ccd6cSJohn Marino       result |= ((uint64_t) (byte & 0x7f)) << shift;
102*ef5ccd6cSJohn Marino       shift += 7;
103*ef5ccd6cSJohn Marino       if ((byte & 0x80) == 0)
104*ef5ccd6cSJohn Marino 	break;
105*ef5ccd6cSJohn Marino     }
106*ef5ccd6cSJohn Marino   if (shift < (sizeof (*r) * 8) && (byte & 0x40) != 0)
107*ef5ccd6cSJohn Marino     result |= -(((uint64_t) 1) << shift);
108*ef5ccd6cSJohn Marino 
109*ef5ccd6cSJohn Marino   *r = result;
110*ef5ccd6cSJohn Marino   return p - buf;
111*ef5ccd6cSJohn Marino }
112*ef5ccd6cSJohn Marino 
113*ef5ccd6cSJohn Marino /* Return the number of bytes to read to skip past an LEB128 number in BUF.
114*ef5ccd6cSJohn Marino    If the end isn't found before reaching BUF_END, return zero.
115*ef5ccd6cSJohn Marino 
116*ef5ccd6cSJohn Marino    Note: The result is an int instead of a pointer to the next byte to be
117*ef5ccd6cSJohn Marino    read to avoid const-vs-non-const problems.  */
118*ef5ccd6cSJohn Marino 
119*ef5ccd6cSJohn Marino static inline size_t
skip_leb128(const unsigned char * buf,const unsigned char * buf_end)120*ef5ccd6cSJohn Marino skip_leb128 (const unsigned char *buf, const unsigned char *buf_end)
121*ef5ccd6cSJohn Marino {
122*ef5ccd6cSJohn Marino   const unsigned char *p = buf;
123*ef5ccd6cSJohn Marino   unsigned char byte;
124*ef5ccd6cSJohn Marino 
125*ef5ccd6cSJohn Marino   while (1)
126*ef5ccd6cSJohn Marino     {
127*ef5ccd6cSJohn Marino       if (p == buf_end)
128*ef5ccd6cSJohn Marino 	return 0;
129*ef5ccd6cSJohn Marino 
130*ef5ccd6cSJohn Marino       byte = *p++;
131*ef5ccd6cSJohn Marino       if ((byte & 0x80) == 0)
132*ef5ccd6cSJohn Marino 	return p - buf;
133*ef5ccd6cSJohn Marino     }
134*ef5ccd6cSJohn Marino }
135*ef5ccd6cSJohn Marino 
136*ef5ccd6cSJohn Marino #endif /* LEB128_H */
137