bool FIRCLSDwarfInstructionsEnumerate()

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;
}