Index: lldb/trunk/include/lldb/Symbol/FuncUnwinders.h =================================================================== --- lldb/trunk/include/lldb/Symbol/FuncUnwinders.h +++ lldb/trunk/include/lldb/Symbol/FuncUnwinders.h @@ -50,7 +50,7 @@ GetUnwindPlanAtNonCallSite (Target& target, lldb_private::Thread& thread, int current_offset); lldb::UnwindPlanSP - GetUnwindPlanFastUnwind (lldb_private::Thread& Thread); + GetUnwindPlanFastUnwind (Target& target, lldb_private::Thread& thread); lldb::UnwindPlanSP GetUnwindPlanArchitectureDefault (lldb_private::Thread& thread); @@ -111,7 +111,7 @@ private: lldb::UnwindAssemblySP - GetUnwindAssemblyProfiler (); + GetUnwindAssemblyProfiler (Target& target); UnwindTable& m_unwind_table; AddressRange m_range; Index: lldb/trunk/source/Commands/CommandObjectTarget.cpp =================================================================== --- lldb/trunk/source/Commands/CommandObjectTarget.cpp +++ lldb/trunk/source/Commands/CommandObjectTarget.cpp @@ -3775,7 +3775,7 @@ { result.GetOutputStream().Printf("Synchronous (restricted to call-sites) UnwindPlan is '%s'\n", callsite_unwind_plan->GetSourceName().AsCString()); } - UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*thread.get()); + UnwindPlanSP fast_unwind_plan = func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread.get()); if (fast_unwind_plan.get()) { result.GetOutputStream().Printf("Fast UnwindPlan is '%s'\n", fast_unwind_plan->GetSourceName().AsCString()); Index: lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp =================================================================== --- lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp +++ lldb/trunk/source/Plugins/Instruction/ARM/EmulateInstructionARM.cpp @@ -290,6 +290,9 @@ uint32_t EmulateInstructionARM::GetFramePointerRegisterNumber () const { + if (m_arch.GetTriple().getEnvironment() == llvm::Triple::Android) + return LLDB_INVALID_REGNUM; // Don't use frame pointer on android + bool is_apple = false; if (m_arch.GetTriple().getVendor() == llvm::Triple::Apple) is_apple = true; @@ -1339,29 +1342,61 @@ return false; uint32_t imm32; // the immediate operand uint32_t d; - //bool setflags = false; // Add this back if/when support eEncodingT3 eEncodingA1 - switch (encoding) + bool setflags; + switch (encoding) { case eEncodingT1: // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(imm8:'00', 32); d = Bits32 (opcode, 10, 8); imm32 = (Bits32 (opcode, 7, 0) << 2); - + setflags = false; break; - + case eEncodingT2: // d = 13; setflags = FALSE; imm32 = ZeroExtend(imm7:'00', 32); d = 13; - imm32 = ThumbImm7Scaled(opcode); // imm32 = ZeroExtend(imm7:'00', 32) - + imm32 = ThumbImm7Scaled (opcode); // imm32 = ZeroExtend(imm7:'00', 32) + setflags = false; break; - + + case eEncodingT3: + // d = UInt(Rd); setflags = (S == "1"); imm32 = ThumbExpandImm(i:imm3:imm8); + d = Bits32 (opcode, 11, 8); + imm32 = ThumbExpandImm (opcode); + setflags = Bit32 (opcode, 20); + + // if Rd == "1111" && S == "1" then SEE CMN (immediate); + if (d == 15 && setflags == 1) + return false; // CMN (immediate) not yet supported + + // if d == 15 && S == "0" then UNPREDICTABLE; + if (d == 15 && setflags == 0) + return false; + break; + + case eEncodingT4: + { + // if Rn == '1111' then SEE ADR; + // d = UInt(Rd); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); + d = Bits32 (opcode, 11, 8); + setflags = false; + uint32_t i = Bit32 (opcode, 26); + uint32_t imm3 = Bits32 (opcode, 14, 12); + uint32_t imm8 = Bits32 (opcode, 7, 0); + imm32 = (i << 11) | (imm3 << 8) | imm8; + + // if d == 15 then UNPREDICTABLE; + if (d == 15) + return false; + } + break; + default: return false; } - addr_t sp_offset = imm32; - addr_t addr = sp + sp_offset; // the adjusted stack pointer value - + // (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); + AddWithCarryResult res = AddWithCarry (sp, imm32, 0); + EmulateInstruction::Context context; if (d == 13) context.type = EmulateInstruction::eContextAdjustStackPointer; @@ -1370,26 +1405,23 @@ RegisterInfo sp_reg; GetRegisterInfo (eRegisterKindDWARF, dwarf_sp, sp_reg); - context.SetRegisterPlusOffset (sp_reg, sp_offset); - + context.SetRegisterPlusOffset (sp_reg, res.result - sp); + if (d == 15) { - if (!ALUWritePC (context, addr)) + if (!ALUWritePC (context, res.result)) return false; } else { - if (!WriteRegisterUnsigned (context, eRegisterKindDWARF, dwarf_r0 + d, addr)) + // R[d] = result; + // if setflags then + // APSR.N = result<31>; + // APSR.Z = IsZeroBit(result); + // APSR.C = carry; + // APSR.V = overflow; + if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow)) return false; - - // Add this back if/when support eEncodingT3 eEncodingA1 - //if (setflags) - //{ - // APSR.N = result<31>; - // APSR.Z = IsZeroBit(result); - // APSR.C = carry; - // APSR.V = overflow; - //} } } return true; @@ -2318,13 +2350,16 @@ context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); break; case eEncodingT2: - imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0)); + imm32 = llvm::SignExtend32<12>(Bits32(opcode, 10, 0) << 1); target = pc + imm32; context.SetISAAndImmediateSigned (eModeThumb, 4 + imm32); break; case eEncodingT3: // The 'cond' field is handled in EmulateInstructionARM::CurrentCond(). { + if (Bits32(opcode, 25, 23) == 7) + return false; // See Branches and miscellaneous control on page A6-235. + uint32_t S = Bit32(opcode, 26); uint32_t imm6 = Bits32(opcode, 21, 16); uint32_t J1 = Bit32(opcode, 13); @@ -2404,7 +2439,7 @@ default: return false; } - if (nonzero ^ (reg_val == 0)) + if (m_ignore_conditions || (nonzero ^ (reg_val == 0))) if (!BranchWritePC(context, target)) return false; @@ -2434,55 +2469,58 @@ bool success = false; - uint32_t Rn; // the base register which contains the address of the table of branch lengths - uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table - bool is_tbh; // true if table branch halfword - switch (encoding) { - case eEncodingT1: - Rn = Bits32(opcode, 19, 16); - Rm = Bits32(opcode, 3, 0); - is_tbh = BitIsSet(opcode, 4); - if (Rn == 13 || BadReg(Rm)) - return false; - if (InITBlock() && !LastInITBlock()) + if (ConditionPassed(opcode)) + { + uint32_t Rn; // the base register which contains the address of the table of branch lengths + uint32_t Rm; // the index register which contains an integer pointing to a byte/halfword in the table + bool is_tbh; // true if table branch halfword + switch (encoding) { + case eEncodingT1: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + is_tbh = BitIsSet(opcode, 4); + if (Rn == 13 || BadReg(Rm)) + return false; + if (InITBlock() && !LastInITBlock()) + return false; + break; + default: return false; - break; - default: - return false; - } + } - // Read the address of the table from the operand register Rn. - // The PC can be used, in which case the table immediately follows this instruction. - uint32_t base = ReadCoreReg(Rm, &success); - if (!success) - return false; + // Read the address of the table from the operand register Rn. + // The PC can be used, in which case the table immediately follows this instruction. + uint32_t base = ReadCoreReg(Rn, &success); + if (!success) + return false; - // the table index - uint32_t index = ReadCoreReg(Rm, &success); - if (!success) - return false; + // the table index + uint32_t index = ReadCoreReg(Rm, &success); + if (!success) + return false; - // the offsetted table address - addr_t addr = base + (is_tbh ? index*2 : index); + // the offsetted table address + addr_t addr = base + (is_tbh ? index*2 : index); - // PC-relative offset to branch forward - EmulateInstruction::Context context; - context.type = EmulateInstruction::eContextTableBranchReadMemory; - uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; - if (!success) - return false; + // PC-relative offset to branch forward + EmulateInstruction::Context context; + context.type = EmulateInstruction::eContextTableBranchReadMemory; + uint32_t offset = MemURead(context, addr, is_tbh ? 2 : 1, 0, &success) * 2; + if (!success) + return false; - const uint32_t pc = ReadCoreReg(PC_REG, &success); - if (!success) - return false; + const uint32_t pc = ReadCoreReg(PC_REG, &success); + if (!success) + return false; - // target address - addr_t target = pc + offset; - context.type = EmulateInstruction::eContextRelativeBranchImmediate; - context.SetISAAndImmediateSigned (eModeThumb, 4 + offset); + // target address + addr_t target = pc + offset; + context.type = EmulateInstruction::eContextRelativeBranchImmediate; + context.SetISAAndImmediateSigned (eModeThumb, 4 + offset); - if (!BranchWritePC(context, target)) - return false; + if (!BranchWritePC(context, target)) + return false; + } return true; } @@ -2498,14 +2536,14 @@ (result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); R[d] = result; if setflags then - APSR.N = result<31>; - APSR.Z = IsZeroBit(result); - APSR.C = carry; + APSR.N = result<31>; + APSR.Z = IsZeroBit(result); + APSR.C = carry; APSR.V = overflow; #endif - + bool success = false; - + if (ConditionPassed(opcode)) { uint32_t d; @@ -2513,8 +2551,8 @@ bool setflags; uint32_t imm32; uint32_t carry_out; - - //EncodingSpecificOperations(); + + //EncodingSpecificOperations(); switch (encoding) { case eEncodingT1: @@ -2523,7 +2561,7 @@ n = Bits32 (opcode, 5, 3); setflags = !InITBlock(); imm32 = Bits32 (opcode, 8,6); - + break; case eEncodingT2: @@ -2532,28 +2570,30 @@ n = Bits32 (opcode, 10, 8); setflags = !InITBlock(); imm32 = Bits32 (opcode, 7, 0); - + break; - + case eEncodingT3: // if Rd == '1111' && S == '1' then SEE CMN (immediate); - // if Rn == '1101' then SEE ADD (SP plus immediate); // d = UInt(Rd); n = UInt(Rn); setflags = (S == '1'); imm32 = ThumbExpandImm(i:imm3:imm8); d = Bits32 (opcode, 11, 8); n = Bits32 (opcode, 19, 16); setflags = BitIsSet (opcode, 20); imm32 = ThumbExpandImm_C (opcode, APSR_C, carry_out); - + + // if Rn == '1101' then SEE ADD (SP plus immediate); + if (n == 13) + return EmulateADDSPImm(opcode, eEncodingT3); + // if BadReg(d) || n == 15 then UNPREDICTABLE; if (BadReg (d) || (n == 15)) return false; - + break; - + case eEncodingT4: { // if Rn == '1111' then SEE ADR; - // if Rn == '1101' then SEE ADD (SP plus immediate); // d = UInt(Rd); n = UInt(Rn); setflags = FALSE; imm32 = ZeroExtend(i:imm3:imm8, 32); d = Bits32 (opcode, 11, 8); n = Bits32 (opcode, 19, 16); @@ -2562,31 +2602,36 @@ uint32_t imm3 = Bits32 (opcode, 14, 12); uint32_t imm8 = Bits32 (opcode, 7, 0); imm32 = (i << 11) | (imm3 << 8) | imm8; - + + // if Rn == '1101' then SEE ADD (SP plus immediate); + if (n == 13) + return EmulateADDSPImm(opcode, eEncodingT4); + // if BadReg(d) then UNPREDICTABLE; if (BadReg (d)) return false; - + break; - } + } + default: return false; } - + uint64_t Rn = ReadRegisterUnsigned (eRegisterKindDWARF, dwarf_r0 + n, 0, &success); if (!success) return false; - + //(result, carry, overflow) = AddWithCarry(R[n], imm32, '0'); AddWithCarryResult res = AddWithCarry (Rn, imm32, 0); - + RegisterInfo reg_n; GetRegisterInfo (eRegisterKindDWARF, dwarf_r0 + n, reg_n); - + EmulateInstruction::Context context; context.type = eContextArithmetic; context.SetRegisterPlusOffset (reg_n, imm32); - + //R[d] = result; //if setflags then //APSR.N = result<31>; @@ -2595,7 +2640,7 @@ //APSR.V = overflow; if (!WriteCoreRegOptionalFlags (context, res.result, d, setflags, res.carry_out, res.overflow)) return false; - + } return true; } @@ -2650,6 +2695,8 @@ EmulateInstruction::Context context; if (Rd == 13) context.type = EmulateInstruction::eContextAdjustStackPointer; + else if (Rd == GetFramePointerRegisterNumber()) + context.type = EmulateInstruction::eContextSetFramePointer; else context.type = EmulateInstruction::eContextRegisterPlusOffset; @@ -2968,6 +3015,13 @@ if (Rn == 15 || Rm == 15) return false; break; + case eEncodingT3: + Rn = Bits32(opcode, 19, 16); + Rm = Bits32(opcode, 3, 0); + shift_n = DecodeImmShiftThumb(opcode, shift_t); + if (Rn == 15 || BadReg(Rm)) + return false; + break; case eEncodingA1: Rn = Bits32(opcode, 19, 16); Rm = Bits32(opcode, 3, 0); @@ -4016,8 +4070,22 @@ if (wback) { EmulateInstruction::Context ctx; - ctx.type = EmulateInstruction::eContextAdjustBaseRegister; - ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); + if (Rn == 13) + { + ctx.type = eContextAdjustStackPointer; + ctx.SetImmediateSigned((int32_t) (offset_addr - base)); + } + else if (Rn == GetFramePointerRegisterNumber()) + { + ctx.type = eContextSetFramePointer; + ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); + } + else + { + ctx.type = EmulateInstruction::eContextAdjustBaseRegister; + ctx.SetRegisterPlusOffset (base_reg, (int32_t) (offset_addr - base)); + } + if (!WriteRegisterUnsigned (ctx, eRegisterKindDWARF, dwarf_r0 + Rn, offset_addr)) return false; @@ -6216,8 +6284,6 @@ break; case eEncodingT2: - // if Rt == '1111' then SEE PLD; - // if Rn == '1111' then SEE LDRB (literal); // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm12, 32); t = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); @@ -6227,7 +6293,15 @@ index = true; add = true; wback = false; - + + // if Rt == '1111' then SEE PLD; + if (t == 15) + return false; // PLD is not implemented yet + + // if Rn == '1111' then SEE LDRB (literal); + if (n == 15) + return EmulateLDRBLiteral(opcode, eEncodingT1); + // if t == 13 then UNPREDICTABLE; if (t == 13) return false; @@ -6235,14 +6309,12 @@ break; case eEncodingT3: - // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; - // if Rn == '1111' then SEE LDRB (literal); // if P == '1' && U == '1' && W == '0' then SEE LDRBT; // if P == '0' && W == '0' then UNDEFINED; if (BitIsClear (opcode, 10) && BitIsClear (opcode, 8)) return false; - // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); + // t = UInt(Rt); n = UInt(Rn); imm32 = ZeroExtend(imm8, 32); t = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); imm32 = Bits32 (opcode, 7, 0); @@ -6251,7 +6323,15 @@ index = BitIsSet (opcode, 10); add = BitIsSet (opcode, 9); wback = BitIsSet (opcode, 8); - + + // if Rt == '1111' && P == '1' && U == '0' && W == '0' then SEE PLD; + if (t == 15) + return false; // PLD is not implemented yet + + // if Rn == '1111' then SEE LDRB (literal); + if (n == 15) + return EmulateLDRBLiteral(opcode, eEncodingT1); + // if BadReg(t) || (wback && n == t) then UNPREDICTABLE; if (BadReg (t) || (wback && (n == t))) return false; @@ -6333,11 +6413,14 @@ switch (encoding) { case eEncodingT1: - // if Rt == '1111' then SEE PLD; // t = UInt(Rt); imm32 = ZeroExtend(imm12, 32); add = (U == '1'); t = Bits32 (opcode, 15, 12); imm32 = Bits32 (opcode, 11, 0); add = BitIsSet (opcode, 23); + + // if Rt == '1111' then SEE PLD; + if (t == 15) + return false; // PLD is not implemented yet // if t == 13 then UNPREDICTABLE; if (t == 13) @@ -6438,8 +6521,6 @@ break; case eEncodingT2: - // if Rt == '1111' then SEE PLD; - // if Rn == '1111' then SEE LDRB (literal); // t = UInt(Rt); n = UInt(Rn); m = UInt(Rm); t = Bits32 (opcode, 15, 12); n = Bits32 (opcode, 19, 16); @@ -6453,6 +6534,14 @@ // (shift_t, shift_n) = (SRType_LSL, UInt(imm2)); shift_t = SRType_LSL; shift_n = Bits32 (opcode, 5, 4); + + // if Rt == '1111' then SEE PLD; + if (t == 15) + return false; // PLD is not implemented yet + + // if Rn == '1111' then SEE LDRB (literal); + if (n == 15) + return EmulateLDRBLiteral(opcode, eEncodingT1); // if t == 13 || BadReg(m) then UNPREDICTABLE; if ((t == 13) || BadReg (m)) @@ -9726,14 +9815,20 @@ break; case eEncodingT2: - // if Rd == ヤ1111ユ && S == ヤ1ユ then SEE CMP (register); - // if Rn == ヤ1101ユ then SEE SUB (SP minus register); - // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S == ヤ1ユ); + // d = UInt(Rd); n = UInt(Rn); m = UInt(Rm); setflags = (S =="1"); d = Bits32 (opcode, 11, 8); n = Bits32 (opcode, 19, 16); m = Bits32 (opcode, 3, 0); setflags = BitIsSet (opcode, 20); - + + // if Rd == "1111" && S == "1" then SEE CMP (register); + if (d == 15 && setflags == 1) + return EmulateCMPImm (opcode, eEncodingT3); + + // if Rn == "1101" then SEE SUB (SP minus register); + if (n == 13) + return EmulateSUBSPReg (opcode, eEncodingT1); + // (shift_t, shift_n) = DecodeImmShift(type, imm3:imm2); shift_n = DecodeImmShiftThumb (opcode, shift_t); @@ -12740,6 +12835,7 @@ { 0xffffffc0, 0x00004280, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp , "}, // cmp (register) (Rn and Rm not both from r0-r7) { 0xffffff00, 0x00004500, ARMvAll, eEncodingT2, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp , "}, + { 0xfff08f00, 0xebb00f00, ARMvAll, eEncodingT3, No_VFP, eSize16, &EmulateInstructionARM::EmulateCMPReg, "cmp.w , {, }"}, // asr (immediate) { 0xfffff800, 0x00001000, ARMvAll, eEncodingT1, No_VFP, eSize16, &EmulateInstructionARM::EmulateASRImm, "asrs|asr , , #imm"}, { 0xffef8030, 0xea4f0020, ARMV6T2_ABOVE, eEncodingT2, No_VFP, eSize32, &EmulateInstructionARM::EmulateASRImm, "asr{s}.w , , #imm"}, @@ -13673,15 +13769,11 @@ // Our previous Call Frame Address is the stack pointer row->GetCFAValue().SetIsRegisterPlusOffset (dwarf_sp, 0); - - // Our previous PC is in the LR - row->SetRegisterLocationToRegister(dwarf_pc, dwarf_lr, true); - unwind_plan.AppendRow (row); - // All other registers are the same. - + unwind_plan.AppendRow (row); unwind_plan.SetSourceName ("EmulateInstructionARM"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); + unwind_plan.SetReturnAddressRegister (dwarf_lr); return true; } Index: lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp =================================================================== --- lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp +++ lldb/trunk/source/Plugins/Instruction/ARM64/EmulateInstructionARM64.cpp @@ -350,17 +350,12 @@ // Our previous Call Frame Address is the stack pointer row->GetCFAValue().SetIsRegisterPlusOffset(arm64_dwarf::sp, 0); - - // Our previous PC is in the LR - row->SetRegisterLocationToRegister(arm64_dwarf::pc, arm64_dwarf::lr, can_replace); unwind_plan.AppendRow (row); - - // All other registers are the same. - unwind_plan.SetSourceName ("EmulateInstructionARM64"); unwind_plan.SetSourcedFromCompiler (eLazyBoolNo); unwind_plan.SetUnwindPlanValidAtAllInstructions (eLazyBoolYes); + unwind_plan.SetReturnAddressRegister (arm64_dwarf::lr); return true; } Index: lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ lldb/trunk/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -2020,11 +2020,12 @@ symbol_section_sp, // Section in which this symbol is defined or null. symbol_value, // Offset in section or symbol value. symbol.st_size), // Size in bytes of this symbol. - true, // Size is valid - has_suffix, // Contains linker annotations? - flags); // Symbol flags. + symbol.st_size != 0, // Size is valid if it is not 0 + has_suffix, // Contains linker annotations? + flags); // Symbol flags. symtab->AddSymbol(dc_symbol); } + symtab->CalculateSymbolSizes(); return i; } Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp +++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp @@ -692,7 +692,7 @@ if (m_frame_type == eTrapHandlerFrame || m_frame_type == eDebuggerFrame) return unwind_plan_sp; - unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind (m_thread); + unwind_plan_sp = func_unwinders_sp->GetUnwindPlanFastUnwind (*m_thread.CalculateTarget(), m_thread); if (unwind_plan_sp) { if (unwind_plan_sp->PlanValidAtAddress (m_current_pc)) @@ -1403,16 +1403,13 @@ if (unwindplan_regloc.IsSame()) { - if (IsFrameZero ()) - { - UnwindLogMsg ("could not supply caller's %s (%d) location, IsSame", - regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } - else - { - return UnwindLLDB::RegisterSearchResult::eRegisterNotFound; - } + regloc.type = UnwindLLDB::RegisterLocation::eRegisterInRegister; + regloc.location.register_number = regnum.GetAsKind (eRegisterKindLLDB); + m_registers[regnum.GetAsKind (eRegisterKindLLDB)] = regloc; + UnwindLogMsg ("supplying caller's register %s (%d), saved in register %s (%d)", + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB), + regnum.GetName(), regnum.GetAsKind (eRegisterKindLLDB)); + return UnwindLLDB::RegisterSearchResult::eRegisterFound; } if (unwindplan_regloc.IsCFAPlusOffset()) Index: lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h =================================================================== --- lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h +++ lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h @@ -141,8 +141,7 @@ m_register_values (), m_pushed_regs(), m_curr_row_modified (false), - m_curr_insn_is_branch_immediate (false), - m_curr_insn_restored_a_register (false) + m_forward_branch_offset (0) { if (m_inst_emulator_ap.get()) { @@ -178,13 +177,11 @@ // While processing the instruction stream, we need to communicate some state change // information up to the higher level loop that makes decisions about how to push // the unwind instructions for the UnwindPlan we're constructing. - + // The instruction we're processing updated the UnwindPlan::Row contents bool m_curr_row_modified; - // The instruction we're examining is a branch immediate instruction - bool m_curr_insn_is_branch_immediate; - // The instruction we're processing restored a caller's reg value (e.g. in an epilogue) - bool m_curr_insn_restored_a_register; + // The instruction is branching forward with the given offset. 0 value means no branching. + uint32_t m_forward_branch_offset; }; #endif // liblldb_UnwindAssemblyInstEmulation_h_ Index: lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp =================================================================== --- lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp +++ lldb/trunk/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.cpp @@ -96,7 +96,13 @@ if (num_instructions > 0) { Instruction *inst = inst_list.GetInstructionAtIndex (0).get(); - const addr_t base_addr = inst->GetAddress().GetFileAddress(); + const lldb::addr_t base_addr = inst->GetAddress().GetFileAddress(); + + // Map for storing the unwind plan row and the value of the registers at a given offset. + // When we see a forward branch we add a new entry to this map with the actual unwind plan + // row and register context for the target address of the branch as the current data have + // to be valid for the target address of the branch too if we are in the same function. + std::map> saved_unwind_states; // Make a copy of the current instruction Row and save it in m_curr_row // so we can add updates as we process the instructions. @@ -106,18 +112,8 @@ *newrow = *last_row.get(); m_curr_row.reset(newrow); - // Once we've seen the initial prologue instructions complete, save a - // copy of the CFI at that point into prologue_completed_row for possible - // use later. - int instructions_since_last_prologue_insn = 0; // # of insns since last CFI was update - - bool reinstate_prologue_next_instruction = false; // Next iteration, re-install the prologue row of CFI - - bool last_instruction_restored_return_addr_reg = false; // re-install the prologue row of CFI if the next instruction is a branch immediate - - bool return_address_register_has_been_saved = false; // if we've seen the ra register get saved yet - - UnwindPlan::RowSP prologue_completed_row; // copy of prologue row of CFI + // Add the initial state to the save list with offset 0. + saved_unwind_states.insert({0, {last_row, m_register_values}}); // cache the pc register number (in whatever register numbering this UnwindPlan uses) for // quick reference during instruction parsing. @@ -140,10 +136,27 @@ for (size_t idx=0; idxGetAddress().GetFileAddress() - base_addr; + auto it = saved_unwind_states.upper_bound(current_offset); + assert(it != saved_unwind_states.begin() && "Unwind row for the function entry missing"); + --it; // Move it to the row corresponding to the current offset + + // If the offset of m_curr_row don't match with the offset we see in saved_unwind_states + // then we have to update m_curr_row and m_register_values based on the saved values. It + // is happenning after we processed an epilogue and a return to caller instruction. + if (it->second.first->GetOffset() != m_curr_row->GetOffset()) + { + UnwindPlan::Row *newrow = new UnwindPlan::Row; + *newrow = *it->second.first; + m_curr_row.reset(newrow); + m_register_values = it->second.second;; + } + if (log && log->GetVerbose ()) { StreamString strm; @@ -159,111 +172,30 @@ m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions); + // If the current instruction is a branch forward then save the current CFI information + // for the offset where we are branching. + if (m_forward_branch_offset != 0 && range.ContainsFileAddress(inst->GetAddress().GetFileAddress() + m_forward_branch_offset)) + { + auto newrow = std::make_shared(*m_curr_row.get()); + newrow->SetOffset(current_offset + m_forward_branch_offset); + saved_unwind_states.insert({current_offset + m_forward_branch_offset, {newrow, m_register_values}}); + unwind_plan.InsertRow(newrow); + } + // Were there any changes to the CFI while evaluating this instruction? if (m_curr_row_modified) { - reinstate_prologue_next_instruction = false; - m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr); - // Append the new row - unwind_plan.AppendRow (m_curr_row); - - // Allocate a new Row for m_curr_row, copy the current state into it - UnwindPlan::Row *newrow = new UnwindPlan::Row; - *newrow = *m_curr_row.get(); - m_curr_row.reset(newrow); - - // If m_curr_insn_restored_a_register == true, we're looking at an epilogue instruction. - // Set instructions_since_last_prologue_insn to a very high number so we don't append - // any of these epilogue instructions to our prologue_complete row. - if (m_curr_insn_restored_a_register == false && instructions_since_last_prologue_insn < 8) - instructions_since_last_prologue_insn = 0; - else - instructions_since_last_prologue_insn = 99; - - UnwindPlan::Row::RegisterLocation pc_regloc; - UnwindPlan::Row::RegisterLocation ra_regloc; - - // While parsing the instructions of this function, if we've ever - // seen the return address register (aka lr on arm) in a non-IsSame() state, - // it has been saved on the stack. If it's ever back to IsSame(), we've - // executed an epilogue. - if (ra_reg_num != LLDB_INVALID_REGNUM - && m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc) - && !ra_regloc.IsSame()) + // Save the modified row if we don't already have a CFI row in the currennt address + if (saved_unwind_states.count(current_offset + inst->GetOpcode().GetByteSize()) == 0) { - return_address_register_has_been_saved = true; - } + m_curr_row->SetOffset (current_offset + inst->GetOpcode().GetByteSize()); + unwind_plan.InsertRow (m_curr_row); + saved_unwind_states.insert({current_offset + inst->GetOpcode().GetByteSize(), {m_curr_row, m_register_values}}); - // If the caller's pc is "same", we've just executed an epilogue and we return to the caller - // after this instruction completes executing. - // If there are any instructions past this, there must have been flow control over this - // epilogue so we'll reinstate the original prologue setup instructions. - if (prologue_completed_row.get() - && pc_reg_num != LLDB_INVALID_REGNUM - && m_curr_row->GetRegisterInfo (pc_reg_num, pc_regloc) - && pc_regloc.IsSame()) - { - if (log && log->GetVerbose()) - log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- pc is , restore prologue instructions."); - reinstate_prologue_next_instruction = true; - } - else if (prologue_completed_row.get() - && return_address_register_has_been_saved - && ra_reg_num != LLDB_INVALID_REGNUM - && m_curr_row->GetRegisterInfo (ra_reg_num, ra_regloc) - && ra_regloc.IsSame()) - { - if (log && log->GetVerbose()) - log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- lr is , restore prologue instruction if the next instruction is a branch immediate."); - last_instruction_restored_return_addr_reg = true; - } - } - else - { - // If the previous instruction was a return-to-caller (epilogue), and we're still executing - // instructions in this function, there must be a code path that jumps over that epilogue. - // Also detect the case where we epilogue & branch imm to another function (tail-call opt) - // instead of a normal pop lr-into-pc exit. - // Reinstate the frame setup from the prologue. - if (reinstate_prologue_next_instruction - || (m_curr_insn_is_branch_immediate && last_instruction_restored_return_addr_reg)) - { - if (log && log->GetVerbose()) - log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- Reinstating prologue instruction set"); + // Allocate a new Row for m_curr_row, copy the current state into it UnwindPlan::Row *newrow = new UnwindPlan::Row; - *newrow = *prologue_completed_row.get(); - m_curr_row.reset(newrow); - m_curr_row->SetOffset (inst->GetAddress().GetFileAddress() + inst->GetOpcode().GetByteSize() - base_addr); - unwind_plan.AppendRow(m_curr_row); - - newrow = new UnwindPlan::Row; *newrow = *m_curr_row.get(); m_curr_row.reset(newrow); - - reinstate_prologue_next_instruction = false; - last_instruction_restored_return_addr_reg = false; - m_curr_insn_is_branch_immediate = false; - } - - // clear both of these if either one wasn't set - if (last_instruction_restored_return_addr_reg) - { - last_instruction_restored_return_addr_reg = false; - } - if (m_curr_insn_is_branch_immediate) - { - m_curr_insn_is_branch_immediate = false; - } - - // Stop updating the prologue instructions if we've seen 8 non-prologue instructions - // in a row. - if (instructions_since_last_prologue_insn++ < 8) - { - UnwindPlan::Row *newrow = new UnwindPlan::Row; - *newrow = *m_curr_row.get(); - prologue_completed_row.reset(newrow); - if (log && log->GetVerbose()) - log->Printf("UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly -- saving a copy of the current row as the prologue row."); } } } @@ -460,8 +392,7 @@ context.Dump(strm, instruction); log->PutCString (strm.GetData()); } - - const bool can_replace = true; + const bool cant_replace = false; switch (context.type) @@ -491,19 +422,12 @@ case EmulateInstruction::eContextPushRegisterOnStack: { uint32_t reg_num = LLDB_INVALID_REGNUM; - bool is_return_address_reg = false; const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind(); if (context.info_type == EmulateInstruction::eInfoTypeRegisterToRegisterPlusOffset) - { reg_num = context.info.RegisterToRegisterPlusOffset.data_reg.kinds[unwind_reg_kind]; - if (context.info.RegisterToRegisterPlusOffset.data_reg.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) - is_return_address_reg = true; - } else - { assert (!"unhandled case, add code to handle this!"); - } - + if (reg_num != LLDB_INVALID_REGNUM) { if (m_pushed_regs.find (reg_num) == m_pushed_regs.end()) @@ -512,21 +436,6 @@ const int32_t offset = addr - m_initial_sp; m_curr_row->SetRegisterLocationToAtCFAPlusOffset (reg_num, offset, cant_replace); m_curr_row_modified = true; - if (is_return_address_reg) - { - // This push was pushing the return address register, - // so this is also how we will unwind the PC... - RegisterInfo pc_reg_info; - if (instruction->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info)) - { - uint32_t pc_reg_num = pc_reg_info.kinds[unwind_reg_kind]; - if (pc_reg_num != LLDB_INVALID_REGNUM) - { - m_curr_row->SetRegisterLocationToAtCFAPlusOffset (pc_reg_num, offset, can_replace); - m_curr_row_modified = true; - } - } - } } } } @@ -598,7 +507,6 @@ log->PutCString(strm.GetData()); } - const bool must_replace = true; SetRegisterValue (*reg_info, reg_value); switch (context.type) @@ -610,7 +518,6 @@ case EmulateInstruction::eContextRegisterPlusOffset: case EmulateInstruction::eContextAdjustPC: case EmulateInstruction::eContextRegisterStore: - case EmulateInstruction::eContextAbsoluteBranchRegister: case EmulateInstruction::eContextSupervisorCall: case EmulateInstruction::eContextTableBranchReadMemory: case EmulateInstruction::eContextWriteRegisterRandomBits: @@ -619,6 +526,7 @@ case EmulateInstruction::eContextAdvancePC: case EmulateInstruction::eContextReturnFromException: case EmulateInstruction::eContextPushRegisterOnStack: + case EmulateInstruction::eContextRegisterLoad: // { // const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; // if (reg_num != LLDB_INVALID_REGNUM) @@ -633,40 +541,18 @@ // } break; - case EmulateInstruction::eContextRegisterLoad: + case EmulateInstruction::eContextAbsoluteBranchRegister: + case EmulateInstruction::eContextRelativeBranchImmediate: { - const uint32_t unwind_reg_kind = m_unwind_plan_ptr->GetRegisterKind(); - const uint32_t reg_num = reg_info->kinds[unwind_reg_kind]; - if (reg_num != LLDB_INVALID_REGNUM) + if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediate && + context.info.ISAAndImmediate.unsigned_data32 > 0) { - m_curr_row->SetRegisterLocationToRegister (reg_num, reg_num, must_replace); - m_curr_row_modified = true; - m_curr_insn_restored_a_register = true; - - if (reg_info->kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_RA) - { - // This load was restoring the return address register, - // so this is also how we will unwind the PC... - RegisterInfo pc_reg_info; - if (instruction->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info)) - { - uint32_t pc_reg_num = pc_reg_info.kinds[unwind_reg_kind]; - if (pc_reg_num != LLDB_INVALID_REGNUM) - { - m_curr_row->SetRegisterLocationToRegister (pc_reg_num, reg_num, must_replace); - m_curr_row_modified = true; - } - } - } + m_forward_branch_offset = context.info.ISAAndImmediateSigned.signed_data32; } - } - break; - - case EmulateInstruction::eContextRelativeBranchImmediate: - { - + else if (context.info_type == EmulateInstruction::eInfoTypeISAAndImmediateSigned && + context.info.ISAAndImmediateSigned.signed_data32 > 0) { - m_curr_insn_is_branch_immediate = true; + m_forward_branch_offset = context.info.ISAAndImmediate.unsigned_data32; } } break; @@ -676,9 +562,8 @@ const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()]; if (reg_num != LLDB_INVALID_REGNUM) { - m_curr_row->SetRegisterLocationToSame (reg_num, must_replace); + m_curr_row->SetRegisterLocationToSame (reg_num, /*must_replace*/ false); m_curr_row_modified = true; - m_curr_insn_restored_a_register = true; } } break; Index: lldb/trunk/source/Symbol/FuncUnwinders.cpp =================================================================== --- lldb/trunk/source/Symbol/FuncUnwinders.cpp +++ lldb/trunk/source/Symbol/FuncUnwinders.cpp @@ -154,7 +154,7 @@ // Augment the eh_frame instructions with epilogue descriptions if necessary so the // UnwindPlan can be used at any instruction in the function. - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); if (assembly_profiler_sp) { if (!assembly_profiler_sp->AugmentUnwindPlanFromCallSite (m_range, thread, *m_unwind_plan_eh_frame_augmented_sp)) @@ -179,7 +179,7 @@ Mutex::Locker lock (m_mutex); m_tried_unwind_plan_assembly = true; - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); if (assembly_profiler_sp) { m_unwind_plan_assembly_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); @@ -204,7 +204,7 @@ } UnwindPlanSP -FuncUnwinders::GetUnwindPlanFastUnwind (Thread& thread) +FuncUnwinders::GetUnwindPlanFastUnwind (Target& target, Thread& thread) { if (m_unwind_plan_fast_sp.get() || m_tried_unwind_fast) return m_unwind_plan_fast_sp; @@ -212,7 +212,7 @@ Mutex::Locker locker (m_mutex); m_tried_unwind_fast = true; - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); if (assembly_profiler_sp) { m_unwind_plan_fast_sp.reset (new UnwindPlan (lldb::eRegisterKindGeneric)); @@ -287,7 +287,7 @@ Mutex::Locker locker (m_mutex); ExecutionContext exe_ctx (target.shared_from_this(), false); - UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler()); + UnwindAssemblySP assembly_profiler_sp (GetUnwindAssemblyProfiler(target)); if (assembly_profiler_sp) assembly_profiler_sp->FirstNonPrologueInsn (m_range, exe_ctx, m_first_non_prologue_insn); return m_first_non_prologue_insn; @@ -300,12 +300,13 @@ } lldb::UnwindAssemblySP -FuncUnwinders::GetUnwindAssemblyProfiler () +FuncUnwinders::GetUnwindAssemblyProfiler (Target& target) { UnwindAssemblySP assembly_profiler_sp; ArchSpec arch; if (m_unwind_table.GetArchitecture (arch)) { + arch.MergeFrom (target.GetArchitecture ()); assembly_profiler_sp = UnwindAssembly::FindPlugin (arch); } return assembly_profiler_sp; Index: lldb/trunk/source/Symbol/UnwindPlan.cpp =================================================================== --- lldb/trunk/source/Symbol/UnwindPlan.cpp +++ lldb/trunk/source/Symbol/UnwindPlan.cpp @@ -343,11 +343,12 @@ collection::iterator it = m_row_list.begin(); while (it != m_row_list.end()) { RowSP row = *it; - if (row->GetOffset() > row_sp->GetOffset()) + if (row->GetOffset() >= row_sp->GetOffset()) break; it++; } - m_row_list.insert(it, row_sp); + if (it == m_row_list.end() || (*it)->GetOffset() != row_sp->GetOffset()) + m_row_list.insert(it, row_sp); } UnwindPlan::RowSP