1 /*
2 * Copyright (C) 2017 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #pragma once
18
19 #include "dex_format.h"
20
21 // LEB128 encode/decode helpers:
22 // https://source.android.com/devices/tech/dalvik/dex-format.html
23
24 namespace dex {
25
26 // Reads an unsigned LEB128 value, updating the given pointer to
27 // point just past the end of the read value.
ReadULeb128(const u1 ** pptr)28 inline u4 ReadULeb128(const u1** pptr) {
29 const u1* ptr = *pptr;
30 u4 result = *(ptr++);
31
32 if (result > 0x7f) {
33 u4 cur = *(ptr++);
34 result = (result & 0x7f) | ((cur & 0x7f) << 7);
35 if (cur > 0x7f) {
36 cur = *(ptr++);
37 result |= (cur & 0x7f) << 14;
38 if (cur > 0x7f) {
39 cur = *(ptr++);
40 result |= (cur & 0x7f) << 21;
41 if (cur > 0x7f) {
42 // We don't check to see if cur is out of
43 // range here, meaning we tolerate garbage in the
44 // high four-order bits.
45 cur = *(ptr++);
46 result |= cur << 28;
47 }
48 }
49 }
50 }
51
52 *pptr = ptr;
53 return result;
54 }
55
56 // Reads a signed LEB128 value, updating the given pointer to
57 // point just past the end of the read value.
ReadSLeb128(const u1 ** pptr)58 inline s4 ReadSLeb128(const u1** pptr) {
59 const u1* ptr = *pptr;
60 s4 result = *(ptr++);
61
62 if (result <= 0x7f) {
63 result = (result << 25) >> 25;
64 } else {
65 s4 cur = *(ptr++);
66 result = (result & 0x7f) | ((cur & 0x7f) << 7);
67 if (cur <= 0x7f) {
68 result = (result << 18) >> 18;
69 } else {
70 cur = *(ptr++);
71 result |= (cur & 0x7f) << 14;
72 if (cur <= 0x7f) {
73 result = (result << 11) >> 11;
74 } else {
75 cur = *(ptr++);
76 result |= (cur & 0x7f) << 21;
77 if (cur <= 0x7f) {
78 result = (result << 4) >> 4;
79 } else {
80 // Note: We don't check to see if cur is out of
81 // range here, meaning we tolerate garbage in the
82 // high four-order bits.
83 cur = *(ptr++);
84 result |= cur << 28;
85 }
86 }
87 }
88 }
89
90 *pptr = ptr;
91 return result;
92 }
93
94 // Writes a 32-bit value in unsigned ULEB128 format.
95 // Returns the updated pointer.
WriteULeb128(u1 * ptr,u4 data)96 inline u1* WriteULeb128(u1* ptr, u4 data) {
97 for (;;) {
98 u1 out = data & 0x7f;
99 if (out != data) {
100 *ptr++ = out | 0x80;
101 data >>= 7;
102 } else {
103 *ptr++ = out;
104 break;
105 }
106 }
107 return ptr;
108 }
109
110 // Writes a 32-bit value in signed ULEB128 format.
111 // Returns the updated pointer.
WriteSLeb128(u1 * ptr,s4 value)112 inline u1* WriteSLeb128(u1* ptr, s4 value) {
113 u4 extra_bits = static_cast<u4>(value ^ (value >> 31)) >> 6;
114 u1 out = value & 0x7f;
115 while (extra_bits != 0u) {
116 *ptr++ = out | 0x80;
117 value >>= 7;
118 out = value & 0x7f;
119 extra_bits >>= 7;
120 }
121 *ptr++ = out;
122 return ptr;
123 }
124
125 } // namespace dex
126