xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_leb.c (revision bc1f688b4872ace323eaddbb1a6365d054e7bf56)
1 /*
2 
3   Copyright (C) 2000,2004 Silicon Graphics, Inc.  All Rights Reserved.
4 
5   This program is free software; you can redistribute it and/or modify it
6   under the terms of version 2.1 of the GNU Lesser General Public License
7   as published by the Free Software Foundation.
8 
9   This program is distributed in the hope that it would be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 
13   Further, this software is distributed without any warranty that it is
14   free of the rightful claim of any third person regarding infringement
15   or the like.  Any license provided herein, whether implied or
16   otherwise, applies only to this software file.  Patent licenses, if
17   any, provided herein do not apply to combinations of this program with
18   other software, or any other product whatsoever.
19 
20   You should have received a copy of the GNU Lesser General Public
21   License along with this program; if not, write the Free Software
22   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23   USA.
24 
25   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
26   Mountain View, CA 94043, or:
27 
28   http://www.sgi.com
29 
30   For further information regarding this notice, see:
31 
32   http://oss.sgi.com/projects/GenInfo/NoticeExplan
33 
34 */
35 
36 
37 
38 #include "config.h"
39 #include "dwarf_incl.h"
40 #include <stdio.h>
41 
42 
43 /*
44     decode ULEB
45 */
46 Dwarf_Unsigned
47 _dwarf_decode_u_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length)
48 {
49     unsigned char byte;
50     Dwarf_Word word_number;
51     Dwarf_Unsigned number;
52     Dwarf_Sword shift;
53     Dwarf_Sword byte_length;
54 
55     /* The following unrolls-the-loop for the first few bytes and
56        unpacks into 32 bits to make this as fast as possible.
57        word_number is assumed big enough that the shift has a defined
58        result. */
59     if ((*leb128 & 0x80) == 0) {
60         if (leb128_length != NULL)
61             *leb128_length = 1;
62         return (*leb128);
63     } else if ((*(leb128 + 1) & 0x80) == 0) {
64         if (leb128_length != NULL)
65             *leb128_length = 2;
66 
67         word_number = *leb128 & 0x7f;
68         word_number |= (*(leb128 + 1) & 0x7f) << 7;
69         return (word_number);
70     } else if ((*(leb128 + 2) & 0x80) == 0) {
71         if (leb128_length != NULL)
72             *leb128_length = 3;
73 
74         word_number = *leb128 & 0x7f;
75         word_number |= (*(leb128 + 1) & 0x7f) << 7;
76         word_number |= (*(leb128 + 2) & 0x7f) << 14;
77         return (word_number);
78     } else if ((*(leb128 + 3) & 0x80) == 0) {
79         if (leb128_length != NULL)
80             *leb128_length = 4;
81 
82         word_number = *leb128 & 0x7f;
83         word_number |= (*(leb128 + 1) & 0x7f) << 7;
84         word_number |= (*(leb128 + 2) & 0x7f) << 14;
85         word_number |= (*(leb128 + 3) & 0x7f) << 21;
86         return (word_number);
87     }
88 
89     /* The rest handles long numbers Because the 'number' may be larger
90        than the default int/unsigned, we must cast the 'byte' before
91        the shift for the shift to have a defined result. */
92     number = 0;
93     shift = 0;
94     byte_length = 1;
95     byte = *(leb128);
96     for (;;) {
97         number |= ((Dwarf_Unsigned) (byte & 0x7f)) << shift;
98 
99         if ((byte & 0x80) == 0) {
100             if (leb128_length != NULL)
101                 *leb128_length = byte_length;
102             return (number);
103         }
104         shift += 7;
105 
106         byte_length++;
107         ++leb128;
108         byte = *leb128;
109     }
110 }
111 
112 #define BITSINBYTE 8
113 
114 /*
115     decode SLEB
116 */
117 Dwarf_Signed
118 _dwarf_decode_s_leb128(Dwarf_Small * leb128, Dwarf_Word * leb128_length)
119 {
120     Dwarf_Signed number = 0;
121     Dwarf_Bool sign = 0;
122     Dwarf_Sword shift = 0;
123     unsigned char byte = *leb128;
124     Dwarf_Sword byte_length = 1;
125 
126     /* byte_length being the number of bytes of data absorbed so far in
127        turning the leb into a Dwarf_Signed. */
128 
129     for (;;) {
130         sign = byte & 0x40;
131         number |= ((Dwarf_Signed) ((byte & 0x7f))) << shift;
132         shift += 7;
133 
134         if ((byte & 0x80) == 0) {
135             break;
136         }
137         ++leb128;
138         byte = *leb128;
139         byte_length++;
140     }
141 
142     if ((shift < sizeof(Dwarf_Signed) * BITSINBYTE) && sign) {
143         number |= -((Dwarf_Signed) 1 << shift);
144     }
145 
146     if (leb128_length != NULL)
147         *leb128_length = byte_length;
148     return (number);
149 }
150