diff --git a/libunwind/src/DwarfInstructions.hpp b/libunwind/src/DwarfInstructions.hpp --- a/libunwind/src/DwarfInstructions.hpp +++ b/libunwind/src/DwarfInstructions.hpp @@ -46,20 +46,25 @@ DW_X86_RET_ADDR = 8 }; - typedef typename CFI_Parser::RegisterLocation RegisterLocation; - typedef typename CFI_Parser::PrologInfo PrologInfo; - typedef typename CFI_Parser::FDE_Info FDE_Info; - typedef typename CFI_Parser::CIE_Info CIE_Info; + typedef typename CFI_Parser::RegisterSavedWhere RegisterSavedWhere; + typedef typename CFI_Parser::PrologInfo PrologInfo; + typedef typename CFI_Parser::FDE_Info FDE_Info; + typedef typename CFI_Parser::CIE_Info CIE_Info; static pint_t evaluateExpression(pint_t expression, A &addressSpace, const R ®isters, pint_t initialStackValue); static pint_t getSavedRegister(A &addressSpace, const R ®isters, - pint_t cfa, const RegisterLocation &savedReg); + pint_t cfa, const RegisterSavedWhere location, + const int64_t value); static double getSavedFloatRegister(A &addressSpace, const R ®isters, - pint_t cfa, const RegisterLocation &savedReg); + pint_t cfa, + const RegisterSavedWhere location, + const int64_t value); static v128 getSavedVectorRegister(A &addressSpace, const R ®isters, - pint_t cfa, const RegisterLocation &savedReg); + pint_t cfa, + const RegisterSavedWhere location, + const int64_t value); static pint_t getCFA(A &addressSpace, const PrologInfo &prolog, const R ®isters) { @@ -67,7 +72,7 @@ return (pint_t)((sint_t)registers.getRegister((int)prolog.cfaRegister) + prolog.cfaRegisterOffset); if (prolog.cfaExpression != 0) - return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, + return evaluateExpression((pint_t)prolog.cfaExpression, addressSpace, registers, 0); assert(0 && "getCFA(): unknown location"); __builtin_unreachable(); @@ -78,21 +83,20 @@ template typename A::pint_t DwarfInstructions::getSavedRegister( A &addressSpace, const R ®isters, pint_t cfa, - const RegisterLocation &savedReg) { - switch (savedReg.location) { + const RegisterSavedWhere location, const int64_t value) { + switch (location) { case CFI_Parser::kRegisterInCFA: - return (pint_t)addressSpace.getRegister(cfa + (pint_t)savedReg.value); + return (pint_t)addressSpace.getRegister(cfa + (pint_t)value); case CFI_Parser::kRegisterAtExpression: - return (pint_t)addressSpace.getRegister(evaluateExpression( - (pint_t)savedReg.value, addressSpace, registers, cfa)); + return (pint_t)addressSpace.getRegister( + evaluateExpression((pint_t)value, addressSpace, registers, cfa)); case CFI_Parser::kRegisterIsExpression: - return evaluateExpression((pint_t)savedReg.value, addressSpace, - registers, cfa); + return evaluateExpression((pint_t)value, addressSpace, registers, cfa); case CFI_Parser::kRegisterInRegister: - return registers.getRegister((int)savedReg.value); + return registers.getRegister((int)value); case CFI_Parser::kRegisterUnused: case CFI_Parser::kRegisterOffsetFromCFA: @@ -105,15 +109,14 @@ template double DwarfInstructions::getSavedFloatRegister( A &addressSpace, const R ®isters, pint_t cfa, - const RegisterLocation &savedReg) { - switch (savedReg.location) { + const RegisterSavedWhere location, const int64_t value) { + switch (location) { case CFI_Parser::kRegisterInCFA: - return addressSpace.getDouble(cfa + (pint_t)savedReg.value); + return addressSpace.getDouble(cfa + (pint_t)value); case CFI_Parser::kRegisterAtExpression: return addressSpace.getDouble( - evaluateExpression((pint_t)savedReg.value, addressSpace, - registers, cfa)); + evaluateExpression((pint_t)value, addressSpace, registers, cfa)); case CFI_Parser::kRegisterIsExpression: case CFI_Parser::kRegisterUnused: @@ -128,15 +131,14 @@ template v128 DwarfInstructions::getSavedVectorRegister( A &addressSpace, const R ®isters, pint_t cfa, - const RegisterLocation &savedReg) { - switch (savedReg.location) { + const RegisterSavedWhere location, const int64_t value) { + switch (location) { case CFI_Parser::kRegisterInCFA: - return addressSpace.getVector(cfa + (pint_t)savedReg.value); + return addressSpace.getVector(cfa + (pint_t)value); case CFI_Parser::kRegisterAtExpression: return addressSpace.getVector( - evaluateExpression((pint_t)savedReg.value, addressSpace, - registers, cfa)); + evaluateExpression((pint_t)value, addressSpace, registers, cfa)); case CFI_Parser::kRegisterIsExpression: case CFI_Parser::kRegisterUnused: @@ -171,23 +173,27 @@ assert(lastReg >= (int)cieInfo.returnAddressRegister && "register range does not contain return address register"); for (int i = 0; i <= lastReg; ++i) { - if (prolog.savedRegisters[i].location != + if (prolog.savedRegisterLocations[i] != CFI_Parser::kRegisterUnused) { if (registers.validFloatRegister(i)) newRegisters.setFloatRegister( i, getSavedFloatRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i])); + prolog.savedRegisterLocations[i], + prolog.savedRegisterValues[i])); else if (registers.validVectorRegister(i)) newRegisters.setVectorRegister( i, getSavedVectorRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i])); + prolog.savedRegisterLocations[i], + prolog.savedRegisterValues[i])); else if (i == (int)cieInfo.returnAddressRegister) returnAddress = getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i]); + prolog.savedRegisterLocations[i], + prolog.savedRegisterValues[i]); else if (registers.validRegister(i)) newRegisters.setRegister( i, getSavedRegister(addressSpace, registers, cfa, - prolog.savedRegisters[i])); + prolog.savedRegisterLocations[i], + prolog.savedRegisterValues[i])); else return UNW_EBADREG; } @@ -206,7 +212,7 @@ // restored. autia1716 is used instead of autia as autia1716 assembles // to a NOP on pre-v8.3a architectures. if ((R::getArch() == REGISTERS_ARM64) && - prolog.savedRegisters[UNW_ARM64_RA_SIGN_STATE].value) { + prolog.savedRegisterValues[UNW_ARM64_RA_SIGN_STATE]) { #if !defined(_LIBUNWIND_IS_NATIVE_ONLY) return UNW_ECROSSRASIGNING; #else diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp --- a/libunwind/src/DwarfParser.hpp +++ b/libunwind/src/DwarfParser.hpp @@ -67,7 +67,7 @@ enum { kMaxRegisterNumber = _LIBUNWIND_HIGHEST_DWARF_REGISTER }; - enum RegisterSavedWhere { + enum RegisterSavedWhere : uint8_t { kRegisterUnused, kRegisterInCFA, kRegisterOffsetFromCFA, @@ -75,21 +75,18 @@ kRegisterAtExpression, kRegisterIsExpression }; - struct RegisterLocation { - RegisterSavedWhere location; - int64_t value; - }; /// Information about a frame layout and registers saved determined /// by "running" the DWARF FDE "instructions" struct PrologInfo { - uint32_t cfaRegister; - int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset - int64_t cfaExpression; // CFA = expression - uint32_t spExtraArgSize; - uint32_t codeOffsetAtStackDecrement; - bool registersInOtherRegisters; - bool sameValueUsed; - RegisterLocation savedRegisters[kMaxRegisterNumber + 1]; + uint32_t cfaRegister; + int32_t cfaRegisterOffset; // CFA = (cfaRegister)+cfaRegisterOffset + int64_t cfaExpression; // CFA = expression + uint32_t spExtraArgSize; + uint32_t codeOffsetAtStackDecrement; + bool registersInOtherRegisters; + bool sameValueUsed; + RegisterSavedWhere savedRegisterLocations[kMaxRegisterNumber + 1]; + int64_t savedRegisterValues[kMaxRegisterNumber + 1]; }; struct PrologInfoStackEntry { @@ -443,8 +440,8 @@ "malformed DW_CFA_offset_extended DWARF unwind, reg too big"); return false; } - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; + results->savedRegisterLocations[reg] = kRegisterInCFA; + results->savedRegisterValues[reg] = offset; _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended(reg=%" PRIu64 ", " "offset=%" PRId64 ")\n", reg, offset); @@ -456,7 +453,9 @@ "malformed DW_CFA_restore_extended DWARF unwind, reg too big"); return false; } - results->savedRegisters[reg] = initialState.savedRegisters[reg]; + results->savedRegisterLocations[reg] = + initialState.savedRegisterLocations[reg]; + results->savedRegisterValues[reg] = initialState.savedRegisterValues[reg]; _LIBUNWIND_TRACE_DWARF("DW_CFA_restore_extended(reg=%" PRIu64 ")\n", reg); break; case DW_CFA_undefined: @@ -466,7 +465,7 @@ "malformed DW_CFA_undefined DWARF unwind, reg too big"); return false; } - results->savedRegisters[reg].location = kRegisterUnused; + results->savedRegisterLocations[reg] = kRegisterUnused; _LIBUNWIND_TRACE_DWARF("DW_CFA_undefined(reg=%" PRIu64 ")\n", reg); break; case DW_CFA_same_value: @@ -480,7 +479,7 @@ // "same value" means register was stored in frame, but its current // value has not changed, so no need to restore from frame. // We model this as if the register was never saved. - results->savedRegisters[reg].location = kRegisterUnused; + results->savedRegisterLocations[reg] = kRegisterUnused; // set flag to disable conversion to compact unwind results->sameValueUsed = true; _LIBUNWIND_TRACE_DWARF("DW_CFA_same_value(reg=%" PRIu64 ")\n", reg); @@ -498,8 +497,8 @@ "malformed DW_CFA_register DWARF unwind, reg2 too big"); return false; } - results->savedRegisters[reg].location = kRegisterInRegister; - results->savedRegisters[reg].value = (int64_t)reg2; + results->savedRegisterLocations[reg] = kRegisterInRegister; + results->savedRegisterValues[reg] = (int64_t)reg2; // set flag to disable conversion to compact unwind results->registersInOtherRegisters = true; _LIBUNWIND_TRACE_DWARF( @@ -576,15 +575,15 @@ "malformed DW_CFA_expression DWARF unwind, reg too big"); return false; } - results->savedRegisters[reg].location = kRegisterAtExpression; - results->savedRegisters[reg].value = (int64_t)p; + results->savedRegisterLocations[reg] = kRegisterAtExpression; + results->savedRegisterValues[reg] = (int64_t)p; length = addressSpace.getULEB128(p, instructionsEnd); assert(length < static_cast(~0) && "pointer overflow"); p += static_cast(length); _LIBUNWIND_TRACE_DWARF("DW_CFA_expression(reg=%" PRIu64 ", " "expression=0x%" PRIx64 ", " "length=%" PRIu64 ")\n", - reg, results->savedRegisters[reg].value, length); + reg, results->savedRegisterValues[reg], length); break; case DW_CFA_offset_extended_sf: reg = addressSpace.getULEB128(p, instructionsEnd); @@ -595,8 +594,8 @@ } offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; + results->savedRegisterLocations[reg] = kRegisterInCFA; + results->savedRegisterValues[reg] = offset; _LIBUNWIND_TRACE_DWARF("DW_CFA_offset_extended_sf(reg=%" PRIu64 ", " "offset=%" PRId64 ")\n", reg, offset); @@ -634,8 +633,8 @@ } offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterOffsetFromCFA; - results->savedRegisters[reg].value = offset; + results->savedRegisterLocations[reg] = kRegisterOffsetFromCFA; + results->savedRegisterValues[reg] = offset; _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset(reg=%" PRIu64 ", " "offset=%" PRId64 "\n", reg, offset); @@ -649,8 +648,8 @@ } offset = addressSpace.getSLEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterOffsetFromCFA; - results->savedRegisters[reg].value = offset; + results->savedRegisterLocations[reg] = kRegisterOffsetFromCFA; + results->savedRegisterValues[reg] = offset; _LIBUNWIND_TRACE_DWARF("DW_CFA_val_offset_sf(reg=%" PRIu64 ", " "offset=%" PRId64 "\n", reg, offset); @@ -662,14 +661,14 @@ "malformed DW_CFA_val_expression DWARF unwind, reg too big"); return false; } - results->savedRegisters[reg].location = kRegisterIsExpression; - results->savedRegisters[reg].value = (int64_t)p; + results->savedRegisterLocations[reg] = kRegisterIsExpression; + results->savedRegisterValues[reg] = (int64_t)p; length = addressSpace.getULEB128(p, instructionsEnd); assert(length < static_cast(~0) && "pointer overflow"); p += static_cast(length); _LIBUNWIND_TRACE_DWARF("DW_CFA_val_expression(reg=%" PRIu64 ", " "expression=0x%" PRIx64 ", length=%" PRIu64 ")\n", - reg, results->savedRegisters[reg].value, length); + reg, results->savedRegisterValues[reg], length); break; case DW_CFA_GNU_args_size: length = addressSpace.getULEB128(p, instructionsEnd); @@ -685,8 +684,8 @@ } offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = -offset; + results->savedRegisterLocations[reg] = kRegisterInCFA; + results->savedRegisterValues[reg] = -offset; _LIBUNWIND_TRACE_DWARF( "DW_CFA_GNU_negative_offset_extended(%" PRId64 ")\n", offset); break; @@ -700,7 +699,7 @@ switch (arch) { #if defined(_LIBUNWIND_TARGET_AARCH64) case REGISTERS_ARM64: - results->savedRegisters[UNW_ARM64_RA_SIGN_STATE].value ^= 0x1; + results->savedRegisterValues[UNW_ARM64_RA_SIGN_STATE] ^= 0x1; _LIBUNWIND_TRACE_DWARF("DW_CFA_AARCH64_negate_ra_state\n"); break; #endif @@ -709,15 +708,14 @@ case REGISTERS_SPARC: _LIBUNWIND_TRACE_DWARF("DW_CFA_GNU_window_save()\n"); for (reg = UNW_SPARC_O0; reg <= UNW_SPARC_O7; reg++) { - results->savedRegisters[reg].location = kRegisterInRegister; - results->savedRegisters[reg].value = + results->savedRegisterLocations[reg] = kRegisterInRegister; + results->savedRegisterValues[reg] = ((int64_t)reg - UNW_SPARC_O0) + UNW_SPARC_I0; } for (reg = UNW_SPARC_L0; reg <= UNW_SPARC_I7; reg++) { - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = - ((int64_t)reg - UNW_SPARC_L0) * 4; + results->savedRegisterLocations[reg] = kRegisterInCFA; + results->savedRegisterValues[reg] = ((int64_t)reg - UNW_SPARC_L0) * 4; } break; #endif @@ -740,8 +738,8 @@ } offset = (int64_t)addressSpace.getULEB128(p, instructionsEnd) * cieInfo.dataAlignFactor; - results->savedRegisters[reg].location = kRegisterInCFA; - results->savedRegisters[reg].value = offset; + results->savedRegisterLocations[reg] = kRegisterInCFA; + results->savedRegisterValues[reg] = offset; _LIBUNWIND_TRACE_DWARF("DW_CFA_offset(reg=%d, offset=%" PRId64 ")\n", operand, offset); break; @@ -758,7 +756,10 @@ reg); return false; } - results->savedRegisters[reg] = initialState.savedRegisters[reg]; + results->savedRegisterLocations[reg] = + initialState.savedRegisterLocations[reg]; + results->savedRegisterValues[reg] = + initialState.savedRegisterValues[reg]; _LIBUNWIND_TRACE_DWARF("DW_CFA_restore(reg=%" PRIu64 ")\n", static_cast(operand)); break;