• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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