Proyectos de Subversion Iphone Microlearning

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 1
// Copyright 2019 Google
2
//
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
6
//
7
//      http://www.apache.org/licenses/LICENSE-2.0
8
//
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
 
15
#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h"
16
#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h"
17
#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h"
18
#include "Crashlytics/third_party/libunwind/dwarf.h"
19
 
20
#include <string.h>
21
 
22
#if CLS_DWARF_UNWINDING_SUPPORTED
23
 
24
uint8_t FIRCLSParseUint8AndAdvance(const void** cursor) {
25
  uint8_t tmp = **(uint8_t**)cursor;
26
 
27
  *cursor += sizeof(uint8_t);
28
 
29
  return tmp;
30
}
31
 
32
uint16_t FIRCLSParseUint16AndAdvance(const void** cursor) {
33
  uint16_t tmp = **(uint16_t**)cursor;
34
 
35
  *cursor += sizeof(uint16_t);
36
 
37
  return tmp;
38
}
39
 
40
int16_t FIRCLSParseInt16AndAdvance(const void** cursor) {
41
  int16_t tmp = **(int16_t**)cursor;
42
 
43
  *cursor += sizeof(int16_t);
44
 
45
  return tmp;
46
}
47
 
48
uint32_t FIRCLSParseUint32AndAdvance(const void** cursor) {
49
  uint32_t tmp = **(uint32_t**)cursor;
50
 
51
  *cursor += sizeof(uint32_t);
52
 
53
  return tmp;
54
}
55
 
56
int32_t FIRCLSParseInt32AndAdvance(const void** cursor) {
57
  int32_t tmp = **(int32_t**)cursor;
58
 
59
  *cursor += sizeof(int32_t);
60
 
61
  return tmp;
62
}
63
 
64
uint64_t FIRCLSParseUint64AndAdvance(const void** cursor) {
65
  uint64_t tmp = **(uint64_t**)cursor;
66
 
67
  *cursor += sizeof(uint64_t);
68
 
69
  return tmp;
70
}
71
 
72
int64_t FIRCLSParseInt64AndAdvance(const void** cursor) {
73
  int64_t tmp = **(int64_t**)cursor;
74
 
75
  *cursor += sizeof(int64_t);
76
 
77
  return tmp;
78
}
79
 
80
uintptr_t FIRCLSParsePointerAndAdvance(const void** cursor) {
81
  uintptr_t tmp = **(uintptr_t**)cursor;
82
 
83
  *cursor += sizeof(uintptr_t);
84
 
85
  return tmp;
86
}
87
 
88
// Signed and Unsigned LEB128 decoding algorithms taken from Wikipedia -
89
// http://en.wikipedia.org/wiki/LEB128
90
uint64_t FIRCLSParseULEB128AndAdvance(const void** cursor) {
91
  uint64_t result = 0;
92
  char shift = 0;
93
 
94
  for (int i = 0; i < sizeof(uint64_t); ++i) {
95
    char byte;
96
 
97
    byte = **(uint8_t**)cursor;
98
 
99
    *cursor += 1;
100
 
101
    result |= ((0x7F & byte) << shift);
102
    if ((0x80 & byte) == 0) {
103
      break;
104
    }
105
 
106
    shift += 7;
107
  }
108
 
109
  return result;
110
}
111
 
112
int64_t FIRCLSParseLEB128AndAdvance(const void** cursor) {
113
  uint64_t result = 0;
114
  char shift = 0;
115
  char size = sizeof(int64_t) * 8;
116
  char byte = 0;
117
 
118
  for (int i = 0; i < sizeof(uint64_t); ++i) {
119
    byte = **(uint8_t**)cursor;
120
 
121
    *cursor += 1;
122
 
123
    result |= ((0x7F & byte) << shift);
124
    shift += 7;
125
 
126
    /* sign bit of byte is second high order bit (0x40) */
127
    if ((0x80 & byte) == 0) {
128
      break;
129
    }
130
  }
131
 
132
  if ((shift < size) && (0x40 & byte)) {
133
    // sign extend
134
    result |= -(1 << shift);
135
  }
136
 
137
  return result;
138
}
139
 
140
const char* FIRCLSParseStringAndAdvance(const void** cursor) {
141
  const char* string;
142
 
143
  string = (const char*)(*cursor);
144
 
145
  // strlen doesn't include the null character, which we need to advance past
146
  *cursor += strlen(string) + 1;
147
 
148
  return string;
149
}
150
 
151
uint64_t FIRCLSParseRecordLengthAndAdvance(const void** cursor) {
152
  uint64_t length;
153
 
154
  length = FIRCLSParseUint32AndAdvance(cursor);
155
  if (length == DWARF_EXTENDED_LENGTH_FLAG) {
156
    length = FIRCLSParseUint64AndAdvance(cursor);
157
  }
158
 
159
  return length;
160
}
161
 
162
uintptr_t FIRCLSParseAddressWithEncodingAndAdvance(const void** cursor, uint8_t encoding) {
163
  if (encoding == DW_EH_PE_omit) {
164
    return 0;
165
  }
166
 
167
  if (!cursor) {
168
    return CLS_INVALID_ADDRESS;
169
  }
170
 
171
  if (!*cursor) {
172
    return CLS_INVALID_ADDRESS;
173
  }
174
 
175
  intptr_t inputAddr = (intptr_t)*cursor;
176
  intptr_t addr;
177
 
178
  switch (encoding & DW_EH_PE_VALUE_MASK) {
179
    case DW_EH_PE_ptr:
180
      // 32 or 64 bits
181
      addr = FIRCLSParsePointerAndAdvance(cursor);
182
      break;
183
    case DW_EH_PE_uleb128:
184
      addr = (intptr_t)FIRCLSParseULEB128AndAdvance(cursor);
185
      break;
186
    case DW_EH_PE_udata2:
187
      addr = FIRCLSParseUint16AndAdvance(cursor);
188
      break;
189
    case DW_EH_PE_udata4:
190
      addr = FIRCLSParseUint32AndAdvance(cursor);
191
      break;
192
    case DW_EH_PE_udata8:
193
      addr = (intptr_t)FIRCLSParseUint64AndAdvance(cursor);
194
      break;
195
    case DW_EH_PE_sleb128:
196
      addr = (intptr_t)FIRCLSParseLEB128AndAdvance(cursor);
197
      break;
198
    case DW_EH_PE_sdata2:
199
      addr = FIRCLSParseInt16AndAdvance(cursor);
200
      break;
201
    case DW_EH_PE_sdata4:
202
      addr = FIRCLSParseInt32AndAdvance(cursor);
203
      break;
204
    case DW_EH_PE_sdata8:
205
      addr = (intptr_t)FIRCLSParseInt64AndAdvance(cursor);
206
      break;
207
    default:
208
      FIRCLSSDKLog("Unhandled: encoding 0x%02x\n", encoding);
209
      return CLS_INVALID_ADDRESS;
210
  }
211
 
212
  // and now apply the relative offset
213
  switch (encoding & DW_EH_PE_RELATIVE_OFFSET_MASK) {
214
    case DW_EH_PE_absptr:
215
      break;
216
    case DW_EH_PE_pcrel:
217
      addr += inputAddr;
218
      break;
219
    default:
220
      FIRCLSSDKLog("Unhandled: relative encoding 0x%02x\n", encoding);
221
      return CLS_INVALID_ADDRESS;
222
  }
223
 
224
  // Here's a crazy one. It seems this encoding means you actually look up
225
  // the value of the address using the result address itself
226
  if (encoding & DW_EH_PE_indirect) {
227
    if (!addr) {
228
      return CLS_INVALID_ADDRESS;
229
    }
230
 
231
    addr = *(uintptr_t*)addr;
232
  }
233
 
234
  return addr;
235
}
236
#else
237
INJECT_STRIP_SYMBOL(data_parsing)
238
#endif