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/FIRCLSDwarfExpressionMachine.h"
16
#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDataParsing.h"
17
#include "Crashlytics/Crashlytics/Helpers/FIRCLSDefines.h"
18
#include "Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwindRegisters.h"
19
#include "Crashlytics/Crashlytics/Unwind/FIRCLSUnwind_arch.h"
20
#include "Crashlytics/Crashlytics/Helpers/FIRCLSUtility.h"
21
#include "Crashlytics/third_party/libunwind/dwarf.h"
22
 
23
#if CLS_DWARF_UNWINDING_SUPPORTED
24
 
25
static bool FIRCLSDwarfExpressionMachineExecute_bregN(FIRCLSDwarfExpressionMachine *machine,
26
                                                      uint8_t opcode);
27
static bool FIRCLSDwarfExpressionMachineExecute_deref(FIRCLSDwarfExpressionMachine *machine);
28
static bool FIRCLSDwarfExpressionMachineExecute_plus_uconst(FIRCLSDwarfExpressionMachine *machine);
29
static bool FIRCLSDwarfExpressionMachineExecute_and(FIRCLSDwarfExpressionMachine *machine);
30
static bool FIRCLSDwarfExpressionMachineExecute_plus(FIRCLSDwarfExpressionMachine *machine);
31
static bool FIRCLSDwarfExpressionMachineExecute_dup(FIRCLSDwarfExpressionMachine *machine);
32
static bool FIRCLSDwarfExpressionMachineExecute_swap(FIRCLSDwarfExpressionMachine *machine);
33
static bool FIRCLSDwarfExpressionMachineExecute_deref_size(FIRCLSDwarfExpressionMachine *machine);
34
static bool FIRCLSDwarfExpressionMachineExecute_ne(FIRCLSDwarfExpressionMachine *machine);
35
static bool FIRCLSDwarfExpressionMachineExecute_litN(FIRCLSDwarfExpressionMachine *machine,
36
                                                     uint8_t opcode);
37
 
38
#pragma mark -
39
#pragma mark Stack Implementation
40
void FIRCLSDwarfExpressionStackInit(FIRCLSDwarfExpressionStack *stack) {
41
  if (!FIRCLSIsValidPointer(stack)) {
42
    return;
43
  }
44
 
45
  memset(stack, 0, sizeof(FIRCLSDwarfExpressionStack));
46
 
47
  stack->pointer = stack->buffer;
48
}
49
 
50
bool FIRCLSDwarfExpressionStackIsValid(FIRCLSDwarfExpressionStack *stack) {
51
  if (!FIRCLSIsValidPointer(stack)) {
52
    return false;
53
  }
54
 
55
  // check for valid stack pointer
56
  if (stack->pointer < stack->buffer) {
57
    return false;
58
  }
59
 
60
  if (stack->pointer > stack->buffer + CLS_DWARF_EXPRESSION_STACK_SIZE) {
61
    return false;
62
  }
63
 
64
  return true;
65
}
66
 
67
bool FIRCLSDwarfExpressionStackPush(FIRCLSDwarfExpressionStack *stack, intptr_t value) {
68
  if (!FIRCLSDwarfExpressionStackIsValid(stack)) {
69
    return false;
70
  }
71
 
72
  if (stack->pointer == stack->buffer + CLS_DWARF_EXPRESSION_STACK_SIZE) {
73
    // overflow
74
    stack->pointer = NULL;
75
    return false;
76
  }
77
 
78
  *(stack->pointer) = value;
79
  stack->pointer += 1;
80
 
81
  return true;
82
}
83
 
84
intptr_t FIRCLSDwarfExpressionStackPeek(FIRCLSDwarfExpressionStack *stack) {
85
  if (!FIRCLSDwarfExpressionStackIsValid(stack)) {
86
    return 0;
87
  }
88
 
89
  if (stack->pointer == stack->buffer) {
90
    // underflow
91
    stack->pointer = NULL;
92
    return 0;
93
  }
94
 
95
  return *(stack->pointer - 1);
96
}
97
 
98
intptr_t FIRCLSDwarfExpressionStackPop(FIRCLSDwarfExpressionStack *stack) {
99
  if (!FIRCLSDwarfExpressionStackIsValid(stack)) {
100
    return 0;
101
  }
102
 
103
  if (stack->pointer == stack->buffer) {
104
    // underflow
105
    stack->pointer = NULL;
106
    return 0;
107
  }
108
 
109
  stack->pointer -= 1;
110
 
111
  return *(stack->pointer);
112
}
113
 
114
#pragma mark -
115
#pragma mark Machine API
116
bool FIRCLSDwarfExpressionMachineInit(FIRCLSDwarfExpressionMachine *machine,
117
                                      const void *cursor,
118
                                      const FIRCLSThreadContext *registers,
119
                                      intptr_t stackValue) {
120
  if (!FIRCLSIsValidPointer(machine)) {
121
    return false;
122
  }
123
 
124
  memset(machine, 0, sizeof(FIRCLSDwarfExpressionMachine));
125
 
126
  if (!FIRCLSIsValidPointer(cursor)) {
127
    return false;
128
  }
129
 
130
  machine->dataCursor = cursor;
131
  machine->registers = registers;
132
 
133
  FIRCLSDwarfExpressionStackInit(&machine->stack);
134
 
135
  return FIRCLSDwarfExpressionStackPush(&machine->stack, stackValue);
136
}
137
 
138
bool FIRCLSDwarfExpressionMachinePrepareForExecution(FIRCLSDwarfExpressionMachine *machine) {
139
  if (!FIRCLSIsValidPointer(machine)) {
140
    FIRCLSSDKLog("Error: invalid inputs\n");
141
    return false;
142
  }
143
 
144
  uint64_t expressionLength = FIRCLSParseULEB128AndAdvance(&machine->dataCursor);
145
 
146
  if (expressionLength == 0) {
147
    FIRCLSSDKLog("Error: DWARF expression length is zero\n");
148
    return false;
149
  }
150
 
151
  machine->endAddress = machine->dataCursor + expressionLength;
152
 
153
  return true;
154
}
155
 
156
bool FIRCLSDwarfExpressionMachineIsFinished(FIRCLSDwarfExpressionMachine *machine) {
157
  if (!FIRCLSIsValidPointer(machine)) {
158
    FIRCLSSDKLog("Error: invalid inputs\n");
159
    return true;
160
  }
161
 
162
  if (!FIRCLSIsValidPointer(machine->endAddress) || !FIRCLSIsValidPointer(machine->dataCursor)) {
163
    FIRCLSSDKLog("Error: DWARF machine pointers invalid\n");
164
    return true;
165
  }
166
 
167
  if (!FIRCLSDwarfExpressionStackIsValid(&machine->stack)) {
168
    FIRCLSSDKLog("Error: DWARF machine stack invalid\n");
169
    return true;
170
  }
171
 
172
  return machine->dataCursor >= machine->endAddress;
173
}
174
 
175
bool FIRCLSDwarfExpressionMachineGetResult(FIRCLSDwarfExpressionMachine *machine,
176
                                           intptr_t *result) {
177
  if (!FIRCLSIsValidPointer(machine) || !FIRCLSIsValidPointer(result)) {
178
    return false;
179
  }
180
 
181
  if (machine->dataCursor != machine->endAddress) {
182
    FIRCLSSDKLog("Error: DWARF expression hasn't completed execution\n");
183
    return false;
184
  }
185
 
186
  *result = FIRCLSDwarfExpressionStackPeek(&machine->stack);
187
 
188
  return FIRCLSDwarfExpressionStackIsValid(&machine->stack);
189
}
190
 
191
bool FIRCLSDwarfExpressionMachineExecuteNextOpcode(FIRCLSDwarfExpressionMachine *machine) {
192
  if (!FIRCLSIsValidPointer(machine)) {
193
    return false;
194
  }
195
 
196
  const uint8_t opcode = FIRCLSParseUint8AndAdvance(&machine->dataCursor);
197
 
198
  bool success = false;
199
 
200
  switch (opcode) {
201
    case DW_OP_deref:
202
      success = FIRCLSDwarfExpressionMachineExecute_deref(machine);
203
      break;
204
    case DW_OP_dup:
205
      success = FIRCLSDwarfExpressionMachineExecute_dup(machine);
206
      break;
207
    case DW_OP_and:
208
      success = FIRCLSDwarfExpressionMachineExecute_and(machine);
209
      break;
210
    case DW_OP_plus:
211
      success = FIRCLSDwarfExpressionMachineExecute_plus(machine);
212
      break;
213
    case DW_OP_swap:
214
      success = FIRCLSDwarfExpressionMachineExecute_swap(machine);
215
      break;
216
    case DW_OP_plus_uconst:
217
      success = FIRCLSDwarfExpressionMachineExecute_plus_uconst(machine);
218
      break;
219
    case DW_OP_ne:
220
      success = FIRCLSDwarfExpressionMachineExecute_ne(machine);
221
      break;
222
    case DW_OP_lit0:
223
    case DW_OP_lit1:
224
    case DW_OP_lit2:
225
    case DW_OP_lit3:
226
    case DW_OP_lit4:
227
    case DW_OP_lit5:
228
    case DW_OP_lit6:
229
    case DW_OP_lit7:
230
    case DW_OP_lit8:
231
    case DW_OP_lit9:
232
    case DW_OP_lit10:
233
    case DW_OP_lit11:
234
    case DW_OP_lit12:
235
    case DW_OP_lit13:
236
    case DW_OP_lit14:
237
    case DW_OP_lit15:
238
    case DW_OP_lit16:
239
    case DW_OP_lit17:
240
    case DW_OP_lit18:
241
    case DW_OP_lit19:
242
    case DW_OP_lit20:
243
    case DW_OP_lit21:
244
    case DW_OP_lit22:
245
    case DW_OP_lit23:
246
    case DW_OP_lit24:
247
    case DW_OP_lit25:
248
    case DW_OP_lit26:
249
    case DW_OP_lit27:
250
    case DW_OP_lit28:
251
    case DW_OP_lit29:
252
    case DW_OP_lit30:
253
    case DW_OP_lit31:
254
      success = FIRCLSDwarfExpressionMachineExecute_litN(machine, opcode);
255
      break;
256
    case DW_OP_breg0:
257
    case DW_OP_breg1:
258
    case DW_OP_breg2:
259
    case DW_OP_breg3:
260
    case DW_OP_breg4:
261
    case DW_OP_breg5:
262
    case DW_OP_breg6:
263
    case DW_OP_breg7:
264
    case DW_OP_breg8:
265
    case DW_OP_breg9:
266
    case DW_OP_breg10:
267
    case DW_OP_breg11:
268
    case DW_OP_breg12:
269
    case DW_OP_breg13:
270
    case DW_OP_breg14:
271
    case DW_OP_breg15:
272
    case DW_OP_breg16:
273
    case DW_OP_breg17:
274
    case DW_OP_breg18:
275
    case DW_OP_breg19:
276
    case DW_OP_breg20:
277
    case DW_OP_breg21:
278
    case DW_OP_breg22:
279
    case DW_OP_breg23:
280
    case DW_OP_breg24:
281
    case DW_OP_breg25:
282
    case DW_OP_breg26:
283
    case DW_OP_breg27:
284
    case DW_OP_breg28:
285
    case DW_OP_breg29:
286
    case DW_OP_breg30:
287
    case DW_OP_breg31:
288
      success = FIRCLSDwarfExpressionMachineExecute_bregN(machine, opcode);
289
      break;
290
    case DW_OP_deref_size:
291
      success = FIRCLSDwarfExpressionMachineExecute_deref_size(machine);
292
      break;
293
    default:
294
      FIRCLSSDKLog("Error: Unrecognized DWARF expression opcode 0x%x\n", opcode);
295
      return false;
296
  }
297
 
298
  return success;
299
}
300
 
301
#pragma mark -
302
#pragma mark Helpers
303
static intptr_t FIRCLSDwarfExpressionMachineStackPop(FIRCLSDwarfExpressionMachine *machine) {
304
  return FIRCLSDwarfExpressionStackPop(&machine->stack);
305
}
306
 
307
static bool FIRCLSDwarfExpressionMachineStackPush(FIRCLSDwarfExpressionMachine *machine,
308
                                                  intptr_t value) {
309
  return FIRCLSDwarfExpressionStackPush(&machine->stack, value);
310
}
311
 
312
#pragma mark -
313
#pragma mark Opcode Implementations
314
static bool FIRCLSDwarfExpressionMachineExecute_bregN(FIRCLSDwarfExpressionMachine *machine,
315
                                                      uint8_t opcode) {
316
  // find the register number, compute offset value, push
317
  const uint8_t regNum = opcode - DW_OP_breg0;
318
 
319
  if (regNum > CLS_DWARF_MAX_REGISTER_NUM) {
320
    FIRCLSSDKLog("Error: DW_OP_breg invalid register number\n");
321
    return false;
322
  }
323
 
324
  int64_t offset = FIRCLSParseLEB128AndAdvance(&machine->dataCursor);
325
 
326
  FIRCLSSDKLog("DW_OP_breg %d value %d\n", regNum, (int)offset);
327
 
328
  const intptr_t value =
329
      FIRCLSDwarfUnwindGetRegisterValue(machine->registers, regNum) + (intptr_t)offset;
330
 
331
  return FIRCLSDwarfExpressionMachineStackPush(machine, value);
332
}
333
 
334
static bool FIRCLSDwarfExpressionMachineExecute_deref(FIRCLSDwarfExpressionMachine *machine) {
335
  // pop stack, dereference, push result
336
  intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine);
337
 
338
  FIRCLSSDKLog("DW_OP_deref value %p\n", (void *)value);
339
 
340
  if (!FIRCLSReadMemory(value, &value, sizeof(value))) {
341
    FIRCLSSDKLog("Error: DW_OP_deref failed to read memory\n");
342
    return false;
343
  }
344
 
345
  return FIRCLSDwarfExpressionMachineStackPush(machine, value);
346
}
347
 
348
static bool FIRCLSDwarfExpressionMachineExecute_plus_uconst(FIRCLSDwarfExpressionMachine *machine) {
349
  // pop stack, add constant, push result
350
  intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine);
351
 
352
  value += FIRCLSParseULEB128AndAdvance(&machine->dataCursor);
353
 
354
  FIRCLSSDKLog("DW_OP_plus_uconst value %lu\n", value);
355
 
356
  return FIRCLSDwarfExpressionMachineStackPush(machine, value);
357
}
358
 
359
static bool FIRCLSDwarfExpressionMachineExecute_and(FIRCLSDwarfExpressionMachine *machine) {
360
  FIRCLSSDKLog("DW_OP_plus_and\n");
361
 
362
  intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine);
363
 
364
  value = value & FIRCLSDwarfExpressionMachineStackPop(machine);
365
 
366
  return FIRCLSDwarfExpressionMachineStackPush(machine, value);
367
}
368
 
369
static bool FIRCLSDwarfExpressionMachineExecute_plus(FIRCLSDwarfExpressionMachine *machine) {
370
  FIRCLSSDKLog("DW_OP_plus\n");
371
 
372
  intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine);
373
 
374
  value = value + FIRCLSDwarfExpressionMachineStackPop(machine);
375
 
376
  return FIRCLSDwarfExpressionMachineStackPush(machine, value);
377
}
378
 
379
static bool FIRCLSDwarfExpressionMachineExecute_dup(FIRCLSDwarfExpressionMachine *machine) {
380
  // duplicate top of stack
381
  intptr_t value = FIRCLSDwarfExpressionStackPeek(&machine->stack);
382
 
383
  FIRCLSSDKLog("DW_OP_dup value %lu\n", value);
384
 
385
  return FIRCLSDwarfExpressionMachineStackPush(machine, value);
386
}
387
 
388
static bool FIRCLSDwarfExpressionMachineExecute_swap(FIRCLSDwarfExpressionMachine *machine) {
389
  // swap top two values on the stack
390
  intptr_t valueA = FIRCLSDwarfExpressionMachineStackPop(machine);
391
  intptr_t valueB = FIRCLSDwarfExpressionMachineStackPop(machine);
392
 
393
  FIRCLSSDKLog("DW_OP_swap\n");
394
 
395
  if (!FIRCLSDwarfExpressionMachineStackPush(machine, valueA)) {
396
    return false;
397
  }
398
 
399
  return FIRCLSDwarfExpressionMachineStackPush(machine, valueB);
400
}
401
 
402
static bool FIRCLSDwarfExpressionMachineExecute_deref_size(FIRCLSDwarfExpressionMachine *machine) {
403
  // pop stack, dereference variable sized value, push result
404
  const void *address = (const void *)FIRCLSDwarfExpressionMachineStackPop(machine);
405
  const uint8_t readSize = FIRCLSParseUint8AndAdvance(&machine->dataCursor);
406
  intptr_t value = 0;
407
 
408
  FIRCLSSDKLog("DW_OP_deref_size %p size %u\n", address, readSize);
409
 
410
  switch (readSize) {
411
    case 1:
412
      value = FIRCLSParseUint8AndAdvance(&address);
413
      break;
414
    case 2:
415
      value = FIRCLSParseUint16AndAdvance(&address);
416
      break;
417
    case 4:
418
      value = FIRCLSParseUint32AndAdvance(&address);
419
      break;
420
    case 8:
421
      // this is a little funky, as an 8 here really doesn't make sense for 32-bit platforms
422
      value = (intptr_t)FIRCLSParseUint64AndAdvance(&address);
423
      break;
424
    default:
425
      FIRCLSSDKLog("Error: unrecognized DW_OP_deref_size argument %x\n", readSize);
426
      return false;
427
  }
428
 
429
  return FIRCLSDwarfExpressionMachineStackPush(machine, value);
430
}
431
 
432
static bool FIRCLSDwarfExpressionMachineExecute_ne(FIRCLSDwarfExpressionMachine *machine) {
433
  FIRCLSSDKLog("DW_OP_ne\n");
434
 
435
  intptr_t value = FIRCLSDwarfExpressionMachineStackPop(machine);
436
 
437
  value = value != FIRCLSDwarfExpressionMachineStackPop(machine);
438
 
439
  return FIRCLSDwarfExpressionMachineStackPush(machine, value);
440
}
441
 
442
static bool FIRCLSDwarfExpressionMachineExecute_litN(FIRCLSDwarfExpressionMachine *machine,
443
                                                     uint8_t opcode) {
444
  const uint8_t value = opcode - DW_OP_lit0;
445
 
446
  FIRCLSSDKLog("DW_OP_lit %u\n", value);
447
 
448
  return FIRCLSDwarfExpressionMachineStackPush(machine, value);
449
}
450
 
451
#else
452
INJECT_STRIP_SYMBOL(dwarf_expression_machine)
453
#endif