forked from OSchip/llvm-project
				
			Improve instruction emulation based stack unwinding
On ARM there is no difference petween a pop and a load instruction so a register can be loaded multiple times during the function. Add check to threat the load as a restore only if it do the restore from the same location where the register was saved. Differential revision: http://reviews.llvm.org/D11947 llvm-svn: 245546
This commit is contained in:
		
							parent
							
								
									0e1d729b75
								
							
						
					
					
						commit
						99c40e673a
					
				| 
						 | 
					@ -578,7 +578,7 @@ EmulateInstructionARM::EmulatePOP (const uint32_t opcode, const ARMEncoding enco
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            if (BitIsSet (registers, i))
 | 
					            if (BitIsSet (registers, i))
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                context.SetRegisterPlusOffset (sp_reg, addr - sp);
 | 
					                context.SetAddress(addr);
 | 
				
			||||||
                data = MemARead(context, addr, 4, 0, &success);
 | 
					                data = MemARead(context, addr, 4, 0, &success);
 | 
				
			||||||
                if (!success)
 | 
					                if (!success)
 | 
				
			||||||
                    return false;    
 | 
					                    return false;    
 | 
				
			||||||
| 
						 | 
					@ -2214,7 +2214,7 @@ EmulateInstructionARM::EmulateVPOP (const uint32_t opcode, const ARMEncoding enc
 | 
				
			||||||
        for (i=0; i<regs; ++i)
 | 
					        for (i=0; i<regs; ++i)
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
            GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
 | 
					            GetRegisterInfo (eRegisterKindDWARF, start_reg + d + i, dwarf_reg);
 | 
				
			||||||
            context.SetRegisterPlusOffset (sp_reg, addr - sp);
 | 
					            context.SetAddress(addr);
 | 
				
			||||||
            data = MemARead(context, addr, reg_byte_size, 0, &success);
 | 
					            data = MemARead(context, addr, reg_byte_size, 0, &success);
 | 
				
			||||||
            if (!success)
 | 
					            if (!success)
 | 
				
			||||||
                return false;    
 | 
					                return false;    
 | 
				
			||||||
| 
						 | 
					@ -3516,7 +3516,10 @@ EmulateInstructionARM::EmulateLDM (const uint32_t opcode, const ARMEncoding enco
 | 
				
			||||||
                context.type = EmulateInstruction::eContextRegisterPlusOffset;
 | 
					                context.type = EmulateInstruction::eContextRegisterPlusOffset;
 | 
				
			||||||
                context.SetRegisterPlusOffset (dwarf_reg, offset);
 | 
					                context.SetRegisterPlusOffset (dwarf_reg, offset);
 | 
				
			||||||
                if (wback && (n == 13)) // Pop Instruction
 | 
					                if (wback && (n == 13)) // Pop Instruction
 | 
				
			||||||
 | 
					                {
 | 
				
			||||||
                    context.type = EmulateInstruction::eContextPopRegisterOffStack;
 | 
					                    context.type = EmulateInstruction::eContextPopRegisterOffStack;
 | 
				
			||||||
 | 
					                    context.SetAddress(base_address + offset);
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                // R[i] = MemA [address, 4]; address = address + 4;
 | 
					                // R[i] = MemA [address, 4]; address = address + 4;
 | 
				
			||||||
                uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
 | 
					                uint32_t data = MemARead (context, base_address + offset, addr_byte_size, 0, &success);
 | 
				
			||||||
| 
						 | 
					@ -10307,7 +10310,7 @@ EmulateInstructionARM::EmulateLDRDImmediate (const uint32_t opcode, const ARMEnc
 | 
				
			||||||
            context.type = eContextPopRegisterOffStack;
 | 
					            context.type = eContextPopRegisterOffStack;
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            context.type = eContextRegisterLoad;
 | 
					            context.type = eContextRegisterLoad;
 | 
				
			||||||
        context.SetRegisterPlusOffset (base_reg, address - Rn);
 | 
					        context.SetAddress(address);
 | 
				
			||||||
                  
 | 
					                  
 | 
				
			||||||
        const uint32_t addr_byte_size = GetAddressByteSize();
 | 
					        const uint32_t addr_byte_size = GetAddressByteSize();
 | 
				
			||||||
        uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
 | 
					        uint32_t data = MemARead (context, address, addr_byte_size, 0, &success);
 | 
				
			||||||
| 
						 | 
					@ -10437,7 +10440,7 @@ EmulateInstructionARM::EmulateLDRDRegister (const uint32_t opcode, const ARMEnco
 | 
				
			||||||
            context.type = eContextPopRegisterOffStack;
 | 
					            context.type = eContextPopRegisterOffStack;
 | 
				
			||||||
        else
 | 
					        else
 | 
				
			||||||
            context.type = eContextRegisterLoad;
 | 
					            context.type = eContextRegisterLoad;
 | 
				
			||||||
        context.SetRegisterPlusIndirectOffset (base_reg, offset_reg);
 | 
					        context.SetAddress(address);
 | 
				
			||||||
                  
 | 
					                  
 | 
				
			||||||
        // R[t] = MemA[address,4];
 | 
					        // R[t] = MemA[address,4];
 | 
				
			||||||
        const uint32_t addr_byte_size = GetAddressByteSize();
 | 
					        const uint32_t addr_byte_size = GetAddressByteSize();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -768,8 +768,6 @@ EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode)
 | 
				
			||||||
    Context context_t;
 | 
					    Context context_t;
 | 
				
			||||||
    Context context_t2;
 | 
					    Context context_t2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0);
 | 
					 | 
				
			||||||
    context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);
 | 
					 | 
				
			||||||
    uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
 | 
					    uint8_t buffer [RegisterValue::kMaxRegisterByteSize];
 | 
				
			||||||
    Error error;
 | 
					    Error error;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -787,6 +785,8 @@ EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode)
 | 
				
			||||||
                context_t.type = eContextRegisterStore;
 | 
					                context_t.type = eContextRegisterStore;
 | 
				
			||||||
                context_t2.type = eContextRegisterStore;
 | 
					                context_t2.type = eContextRegisterStore;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            context_t.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, 0);
 | 
				
			||||||
 | 
					            context_t2.SetRegisterToRegisterPlusOffset (reg_info_Rt2, reg_info_base, size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!ReadRegister (®_info_Rt, data_Rt))
 | 
					            if (!ReadRegister (®_info_Rt, data_Rt))
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
| 
						 | 
					@ -820,6 +820,8 @@ EmulateInstructionARM64::EmulateLDPSTP (const uint32_t opcode)
 | 
				
			||||||
                context_t.type = eContextRegisterLoad;
 | 
					                context_t.type = eContextRegisterLoad;
 | 
				
			||||||
                context_t2.type = eContextRegisterLoad;
 | 
					                context_t2.type = eContextRegisterLoad;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					            context_t.SetAddress(address);
 | 
				
			||||||
 | 
					            context_t2.SetAddress(address + size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (rt_unknown)
 | 
					            if (rt_unknown)
 | 
				
			||||||
                memset (buffer, 'U', reg_info_Rt.byte_size);
 | 
					                memset (buffer, 'U', reg_info_Rt.byte_size);
 | 
				
			||||||
| 
						 | 
					@ -950,8 +952,6 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode)
 | 
				
			||||||
        return false;
 | 
					        return false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    Context context;
 | 
					    Context context;
 | 
				
			||||||
    context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    switch (memop)
 | 
					    switch (memop)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        case MemOp_STORE:
 | 
					        case MemOp_STORE:
 | 
				
			||||||
| 
						 | 
					@ -959,6 +959,7 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode)
 | 
				
			||||||
                context.type = eContextPushRegisterOnStack;
 | 
					                context.type = eContextPushRegisterOnStack;
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                context.type = eContextRegisterStore;
 | 
					                context.type = eContextRegisterStore;
 | 
				
			||||||
 | 
					            context.SetRegisterToRegisterPlusOffset (reg_info_Rt, reg_info_base, postindex ? 0 : offset);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!ReadRegister (®_info_Rt, data_Rt))
 | 
					            if (!ReadRegister (®_info_Rt, data_Rt))
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
| 
						 | 
					@ -975,6 +976,7 @@ EmulateInstructionARM64::EmulateLDRSTRImm (const uint32_t opcode)
 | 
				
			||||||
                context.type = eContextPopRegisterOffStack;
 | 
					                context.type = eContextPopRegisterOffStack;
 | 
				
			||||||
            else
 | 
					            else
 | 
				
			||||||
                context.type = eContextRegisterLoad;
 | 
					                context.type = eContextRegisterLoad;
 | 
				
			||||||
 | 
					            context.SetAddress(address);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size))
 | 
					            if (!ReadMemory (context, address, buffer, reg_info_Rt.byte_size))
 | 
				
			||||||
                return false;
 | 
					                return false;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -580,8 +580,17 @@ UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
 | 
				
			||||||
                    const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
 | 
					                    const uint32_t generic_regnum = reg_info->kinds[eRegisterKindGeneric];
 | 
				
			||||||
                    if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
 | 
					                    if (reg_num != LLDB_INVALID_REGNUM && generic_regnum != LLDB_REGNUM_GENERIC_SP)
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                        m_curr_row->SetRegisterLocationToSame (reg_num, /*must_replace*/ false);
 | 
					                        if (context.info_type == EmulateInstruction::eInfoTypeAddress)
 | 
				
			||||||
                        m_curr_row_modified = true;
 | 
					                        {
 | 
				
			||||||
 | 
					                            if (m_pushed_regs.find (reg_num) != m_pushed_regs.end () &&
 | 
				
			||||||
 | 
					                                context.info.address == m_pushed_regs[reg_num])
 | 
				
			||||||
 | 
					                            {
 | 
				
			||||||
 | 
					                                m_curr_row->SetRegisterLocationToSame (reg_num, /*must_replace*/ false);
 | 
				
			||||||
 | 
					                                m_curr_row_modified = true;
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
 | 
					                        else
 | 
				
			||||||
 | 
					                            assert (!"unhandled case, add code to handle this!");
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue