in Crashlytics/Crashlytics/Unwind/Dwarf/FIRCLSDwarfUnwind.c [581:675]
bool FIRCLSDwarfInstructionsEnumerate(DWARFInstructions* instructions,
DWARFCIERecord* cieRecord,
FIRCLSDwarfState* state,
intptr_t pcOffset) {
if (!instructions || !cieRecord || !state) {
FIRCLSSDKLog("Error: inputs invalid\n");
return false;
}
// This is a little bit of state that can't be put into the state structure, because
// it is possible for instructions to push/pop state that does not affect this value.
intptr_t codeOffset = 0;
const void* cursor = instructions->data;
const void* endAddress = cursor + instructions->length;
FIRCLSDwarfLog("Running instructions from %p to %p\n", cursor, endAddress);
// parse the instructions, as long as:
// - our data pointer is still in range
// - the pc offset is within the range of instructions that apply
while ((cursor < endAddress) && (codeOffset < pcOffset)) {
uint8_t instruction = FIRCLSParseUint8AndAdvance(&cursor);
bool success = false;
switch (instruction) {
case DW_CFA_nop:
FIRCLSDwarfLog("DW_CFA_nop\n");
continue;
case DW_CFA_set_loc:
success = FIRCLSDwarfParseAndExecute_set_loc(&cursor, cieRecord, &codeOffset);
break;
case DW_CFA_advance_loc1:
success = FIRCLSDwarfParseAndExecute_advance_loc1(&cursor, cieRecord, &codeOffset);
break;
case DW_CFA_advance_loc2:
success = FIRCLSDwarfParseAndExecute_advance_loc2(&cursor, cieRecord, &codeOffset);
break;
case DW_CFA_advance_loc4:
success = FIRCLSDwarfParseAndExecute_advance_loc4(&cursor, cieRecord, &codeOffset);
break;
case DW_CFA_def_cfa:
success = FIRCLSDwarfParseAndExecute_def_cfa(&cursor, cieRecord, state);
break;
case DW_CFA_def_cfa_register:
success = FIRCLSDwarfParseAndExecute_def_cfa_register(&cursor, cieRecord, state);
break;
case DW_CFA_def_cfa_offset:
success = FIRCLSDwarfParseAndExecute_def_cfa_offset(&cursor, cieRecord, state);
break;
case DW_CFA_same_value:
success = FIRCLSDwarfParseAndExecute_same_value(&cursor, cieRecord, state);
break;
case DW_CFA_register:
success = FIRCLSDwarfParseAndExecute_register(&cursor, cieRecord, state);
break;
case DW_CFA_def_cfa_expression:
success = FIRCLSDwarfParseAndExecute_def_cfa_expression(&cursor, cieRecord, state);
break;
case DW_CFA_expression:
success = FIRCLSDwarfParseAndExecute_expression(&cursor, cieRecord, state);
break;
case DW_CFA_val_expression:
success = FIRCLSDwarfParseAndExecute_val_expression(&cursor, cieRecord, state);
break;
case DW_CFA_offset_extended:
case DW_CFA_restore_extended:
case DW_CFA_undefined:
case DW_CFA_remember_state:
case DW_CFA_restore_state:
case DW_CFA_offset_extended_sf:
case DW_CFA_def_cfa_sf:
case DW_CFA_def_cfa_offset_sf:
case DW_CFA_val_offset:
case DW_CFA_val_offset_sf:
case DW_CFA_GNU_window_save:
case DW_CFA_GNU_args_size:
case DW_CFA_GNU_negative_offset_extended:
FIRCLSSDKLog("Error: Unimplemented DWARF instruction 0x%x\n", instruction);
return false;
default:
success = FIRCLSDwarfParseAndExecuteInstructionWithOperand(&cursor, instruction, cieRecord,
state, &codeOffset);
break;
}
if (!success) {
FIRCLSSDKLog("Error: Failed to execute dwarf instruction 0x%x\n", instruction);
return false;
}
}
return true;
}