Пример #1
0
size_t
ObjCLanguage::MethodName::GetFullNames (std::vector<ConstString> &names, bool append)
{
    if (!append)
        names.clear();
    if (IsValid(false))
    {
        StreamString strm;
        const bool is_class_method = m_type == eTypeClassMethod;
        const bool is_instance_method = m_type == eTypeInstanceMethod;
        const ConstString &category = GetCategory();
        if (is_class_method || is_instance_method)
        {
            names.push_back (m_full);
            if (category)
            {
                strm.Printf("%c[%s %s]",
                            is_class_method ? '+' : '-',
                            GetClassName().GetCString(),
                            GetSelector().GetCString());
                names.push_back(ConstString(strm.GetString().c_str()));
            }
        }
        else
        {
            const ConstString &class_name = GetClassName();
            const ConstString &selector = GetSelector();
            strm.Printf("+[%s %s]", class_name.GetCString(), selector.GetCString());
            names.push_back(ConstString(strm.GetString().c_str()));
            strm.Clear();
            strm.Printf("-[%s %s]", class_name.GetCString(), selector.GetCString());
            names.push_back(ConstString(strm.GetString().c_str()));
            strm.Clear();
            if (category)
            {
                strm.Printf("+[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
                names.push_back(ConstString(strm.GetString().c_str()));
                strm.Clear();
                strm.Printf("-[%s(%s) %s]", class_name.GetCString(), category.GetCString(), selector.GetCString());
                names.push_back(ConstString(strm.GetString().c_str()));
            }
        }
    }
    return names.size();
}
Пример #2
0
size_t
UnwindAssemblyInstEmulation::WriteMemory (EmulateInstruction *instruction,
                                          const EmulateInstruction::Context &context, 
                                          lldb::addr_t addr, 
                                          const void *dst,
                                          size_t dst_len)
{
    DataExtractor data (dst, 
                        dst_len, 
                        instruction->GetArchitecture ().GetByteOrder(), 
                        instruction->GetArchitecture ().GetAddressByteSize());

    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));

    if (log && log->GetVerbose ())
    {
        StreamString strm;

        strm.PutCString ("UnwindAssemblyInstEmulation::WriteMemory   (");
        data.Dump(&strm, 0, eFormatBytes, 1, dst_len, UINT32_MAX, addr, 0, 0);
        strm.PutCString (", context = ");
        context.Dump(strm, instruction);
        log->PutCString (strm.GetData());
    }
    
    const bool can_replace = true;
    const bool cant_replace = false;

    switch (context.type)
    {
        default:
        case EmulateInstruction::eContextInvalid:
        case EmulateInstruction::eContextReadOpcode:
        case EmulateInstruction::eContextImmediate:
        case EmulateInstruction::eContextAdjustBaseRegister:
        case EmulateInstruction::eContextRegisterPlusOffset:
        case EmulateInstruction::eContextAdjustPC:
        case EmulateInstruction::eContextRegisterStore:
        case EmulateInstruction::eContextRegisterLoad:  
        case EmulateInstruction::eContextRelativeBranchImmediate:
        case EmulateInstruction::eContextAbsoluteBranchRegister:
        case EmulateInstruction::eContextSupervisorCall:
        case EmulateInstruction::eContextTableBranchReadMemory:
        case EmulateInstruction::eContextWriteRegisterRandomBits:
        case EmulateInstruction::eContextWriteMemoryRandomBits:
        case EmulateInstruction::eContextArithmetic:
        case EmulateInstruction::eContextAdvancePC:    
        case EmulateInstruction::eContextReturnFromException:
        case EmulateInstruction::eContextPopRegisterOffStack:
        case EmulateInstruction::eContextAdjustStackPointer:
            break;
            
        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())
                    {
                        m_pushed_regs[reg_num] = addr;
                        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;
                                }
                            }
                        }
                    }
                }
            }
            break;
            
    }

    return dst_len;
}
Пример #3
0
bool
UnwindAssemblyInstEmulation::WriteRegister (EmulateInstruction *instruction,
                                            const EmulateInstruction::Context &context, 
                                            const RegisterInfo *reg_info,
                                            const RegisterValue &reg_value)
{
    Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));

    if (log && log->GetVerbose ())
    {
        
        StreamString strm;
        strm.Printf ("UnwindAssemblyInstEmulation::WriteRegister (name = \"%s\", value = ", reg_info->name);
        reg_value.Dump(&strm, reg_info, false, false, eFormatDefault);
        strm.PutCString (", context = ");
        context.Dump(strm, instruction);
        log->PutCString(strm.GetData());
    }

    const bool must_replace = true;
    SetRegisterValue (*reg_info, reg_value);

    switch (context.type)
    {
        case EmulateInstruction::eContextInvalid:
        case EmulateInstruction::eContextReadOpcode:
        case EmulateInstruction::eContextImmediate:
        case EmulateInstruction::eContextAdjustBaseRegister:
        case EmulateInstruction::eContextRegisterPlusOffset:
        case EmulateInstruction::eContextAdjustPC:
        case EmulateInstruction::eContextRegisterStore:
        case EmulateInstruction::eContextRegisterLoad:  
        case EmulateInstruction::eContextAbsoluteBranchRegister:
        case EmulateInstruction::eContextSupervisorCall:
        case EmulateInstruction::eContextTableBranchReadMemory:
        case EmulateInstruction::eContextWriteRegisterRandomBits:
        case EmulateInstruction::eContextWriteMemoryRandomBits:
        case EmulateInstruction::eContextArithmetic:
        case EmulateInstruction::eContextAdvancePC:    
        case EmulateInstruction::eContextReturnFromException:
        case EmulateInstruction::eContextPushRegisterOnStack:
//            {
//                const uint32_t reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
//                if (reg_num != LLDB_INVALID_REGNUM)
//                {
//                    const bool can_replace_only_if_unspecified = true;
//
//                    m_curr_row.SetRegisterLocationToUndefined (reg_num, 
//                                                               can_replace_only_if_unspecified, 
//                                                               can_replace_only_if_unspecified);
//                    m_curr_row_modified = true;
//                }
//            }
            break;

        case EmulateInstruction::eContextRelativeBranchImmediate:
            {
                
                {
                    m_curr_insn_is_branch_immediate = true;
                }
            }
            break;

        case EmulateInstruction::eContextPopRegisterOffStack:
            {
                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_modified = true;
                    m_curr_insn_restored_a_register = true;
                }
            }
            break;

        case EmulateInstruction::eContextSetFramePointer:
            if (!m_fp_is_cfa)
            {
                m_fp_is_cfa = true;
                m_cfa_reg_info = *reg_info;
                const uint32_t cfa_reg_num = reg_info->kinds[m_unwind_plan_ptr->GetRegisterKind()];
                assert (cfa_reg_num != LLDB_INVALID_REGNUM);
                m_curr_row->SetCFARegister(cfa_reg_num);
                m_curr_row->SetCFAOffset(m_initial_sp - reg_value.GetAsUInt64());
                m_curr_row_modified = true;
            }
            break;

        case EmulateInstruction::eContextAdjustStackPointer:
            // If we have created a frame using the frame pointer, don't follow
            // subsequent adjustments to the stack pointer.
            if (!m_fp_is_cfa)
            {
                m_curr_row->SetCFAOffset (m_initial_sp - reg_value.GetAsUInt64());
                m_curr_row_modified = true;
            }
            break;
    }
    return true;
}
Пример #4
0
const char *
StopInfoMachException::GetDescription ()
{
    if (m_description.empty() && m_value != 0)
    {
        ExecutionContext exe_ctx (m_thread_wp.lock());
        Target *target = exe_ctx.GetTargetPtr();
        const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch;

        const char *exc_desc = NULL;
        const char *code_label = "code";
        const char *code_desc = NULL;
        const char *subcode_label = "subcode";
        const char *subcode_desc = NULL;
        switch (m_value)
        {
        case 1: // EXC_BAD_ACCESS
            exc_desc = "EXC_BAD_ACCESS";
            subcode_label = "address";
            switch (cpu)
            {
            case llvm::Triple::x86:
            case llvm::Triple::x86_64:
                switch (m_exc_code)
                {
                case 0xd: code_desc = "EXC_I386_GPFLT"; m_exc_data_count = 1; break;
                }
                break;
            case llvm::Triple::arm:
                switch (m_exc_code)
                {
                case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
                case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
                }
                break;

            case llvm::Triple::ppc:
            case llvm::Triple::ppc64:
                switch (m_exc_code)
                {
                case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break;
                case 0x102: code_desc = "EXC_PPC_BADSPACE";     break;
                case 0x103: code_desc = "EXC_PPC_UNALIGNED";    break;
                }
                break;

            default:
                break;
            }
            break;

        case 2: // EXC_BAD_INSTRUCTION
            exc_desc = "EXC_BAD_INSTRUCTION";
            switch (cpu)
            {
            case llvm::Triple::x86:
            case llvm::Triple::x86_64:
                if (m_exc_code == 1)
                    code_desc = "EXC_I386_INVOP";
                break;

            case llvm::Triple::ppc:
            case llvm::Triple::ppc64:
                switch (m_exc_code)
                {
                case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break; 
                case 2: code_desc = "EXC_PPC_UNIPL_INST"; break; 
                case 3: code_desc = "EXC_PPC_PRIVINST"; break; 
                case 4: code_desc = "EXC_PPC_PRIVREG"; break; 
                case 5: code_desc = "EXC_PPC_TRACE"; break; 
                case 6: code_desc = "EXC_PPC_PERFMON"; break; 
                }
                break;

            case llvm::Triple::arm:
                if (m_exc_code == 1)
                    code_desc = "EXC_ARM_UNDEFINED";
                break;

            default:
                break;
            }
            break;

        case 3: // EXC_ARITHMETIC
            exc_desc = "EXC_ARITHMETIC";
            switch (cpu)
            {
            case llvm::Triple::x86:
            case llvm::Triple::x86_64:
                switch (m_exc_code)
                {
                case 1: code_desc = "EXC_I386_DIV"; break;
                case 2: code_desc = "EXC_I386_INTO"; break;
                case 3: code_desc = "EXC_I386_NOEXT"; break;
                case 4: code_desc = "EXC_I386_EXTOVR"; break;
                case 5: code_desc = "EXC_I386_EXTERR"; break;
                case 6: code_desc = "EXC_I386_EMERR"; break;
                case 7: code_desc = "EXC_I386_BOUND"; break;
                case 8: code_desc = "EXC_I386_SSEEXTERR"; break;
                }
                break;

            case llvm::Triple::ppc:
            case llvm::Triple::ppc64:
                switch (m_exc_code)
                {
                case 1: code_desc = "EXC_PPC_OVERFLOW"; break;
                case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break;
                case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break;
                case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break;
                case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break;
                case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break;
                case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break;
                }
                break;

            default:
                break;
            }
            break;

        case 4: // EXC_EMULATION
            exc_desc = "EXC_EMULATION";
            break;


        case 5: // EXC_SOFTWARE
            exc_desc = "EXC_SOFTWARE";
            if (m_exc_code == 0x10003)
            {
                subcode_desc = "EXC_SOFT_SIGNAL";
                subcode_label = "signo";
            }
            break;
        
        case 6: // EXC_BREAKPOINT
            {
                exc_desc = "EXC_BREAKPOINT";
                switch (cpu)
                {
                case llvm::Triple::x86:
                case llvm::Triple::x86_64:
                    switch (m_exc_code)
                    {
                    case 1: code_desc = "EXC_I386_SGL"; break;
                    case 2: code_desc = "EXC_I386_BPT"; break;
                    }
                    break;

                case llvm::Triple::ppc:
                case llvm::Triple::ppc64:
                    switch (m_exc_code)
                    {
                    case 1: code_desc = "EXC_PPC_BREAKPOINT"; break;
                    }
                    break;
                
                case llvm::Triple::arm:
                    switch (m_exc_code)
                    {
                    case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break;
                    case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break;
                    case 1: code_desc = "EXC_ARM_BREAKPOINT"; break;
                    // FIXME temporary workaround, exc_code 0 does not really mean EXC_ARM_BREAKPOINT
                    case 0: code_desc = "EXC_ARM_BREAKPOINT"; break;
                    }
                    break;

                default:
                    break;
                }
            }
            break;

        case 7:
            exc_desc = "EXC_SYSCALL";
            break;

        case 8:
            exc_desc = "EXC_MACH_SYSCALL";
            break;

        case 9:
            exc_desc = "EXC_RPC_ALERT";
            break;

        case 10:
            exc_desc = "EXC_CRASH";
            break;
        case 11:
            exc_desc = "EXC_RESOURCE";
            break;
        case 12:
            exc_desc = "EXC_GUARD";
            break;
        }
        
        StreamString strm;

        if (exc_desc)
            strm.PutCString(exc_desc);
        else
            strm.Printf("EXC_??? (%" PRIu64 ")", m_value);

        if (m_exc_data_count >= 1)
        {
            if (code_desc)
                strm.Printf(" (%s=%s", code_label, code_desc);
            else
                strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code);
        }

        if (m_exc_data_count >= 2)
        {
            if (subcode_desc)
                strm.Printf(", %s=%s", subcode_label, subcode_desc);
            else
                strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode);
        }
        
        if (m_exc_data_count > 0)
            strm.PutChar(')');
        
        m_description.swap (strm.GetString());
    }
    return m_description.c_str();
}
Пример #5
0
bool
UnwindAssemblyInstEmulation::GetNonCallSiteUnwindPlanFromAssembly (AddressRange& range, 
                                                                   Thread& thread, 
                                                                   UnwindPlan& unwind_plan)
{
    if (range.GetByteSize() > 0 && 
        range.GetBaseAddress().IsValid() &&
        m_inst_emulator_ap.get())
    {
     
        // The the instruction emulation subclass setup the unwind plan for the
        // first instruction.
        m_inst_emulator_ap->CreateFunctionEntryUnwind (unwind_plan);

        // CreateFunctionEntryUnwind should have created the first row. If it
        // doesn't, then we are done.
        if (unwind_plan.GetRowCount() == 0)
            return false;
        
        ExecutionContext exe_ctx;
        thread.CalculateExecutionContext(exe_ctx);
        DisassemblerSP disasm_sp (Disassembler::DisassembleRange (m_arch,
                                                                  NULL,
                                                                  NULL,
                                                                  exe_ctx,
                                                                  range));
        
        Log *log(GetLogIfAllCategoriesSet (LIBLLDB_LOG_UNWIND));

        if (disasm_sp)
        {
            
            m_range_ptr = &range;
            m_thread_ptr = &thread;
            m_unwind_plan_ptr = &unwind_plan;

            const uint32_t addr_byte_size = m_arch.GetAddressByteSize();
            const bool show_address = true;
            const bool show_bytes = true;
            m_inst_emulator_ap->GetRegisterInfo (unwind_plan.GetRegisterKind(), 
                                                 unwind_plan.GetInitialCFARegister(), 
                                                 m_cfa_reg_info);
            
            m_fp_is_cfa = false;
            m_register_values.clear();
            m_pushed_regs.clear();

            // Initialize the CFA with a known value. In the 32 bit case
            // it will be 0x80000000, and in the 64 bit case 0x8000000000000000.
            // We use the address byte size to be safe for any future addresss sizes
            m_initial_sp = (1ull << ((addr_byte_size * 8) - 1));
            RegisterValue cfa_reg_value;
            cfa_reg_value.SetUInt (m_initial_sp, m_cfa_reg_info.byte_size);
            SetRegisterValue (m_cfa_reg_info, cfa_reg_value);

            const InstructionList &inst_list = disasm_sp->GetInstructionList ();
            const size_t num_instructions = inst_list.GetSize();

            if (num_instructions > 0)
            {
                Instruction *inst = inst_list.GetInstructionAtIndex (0).get();
                const addr_t base_addr = inst->GetAddress().GetFileAddress();

                // 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.  
                UnwindPlan::RowSP last_row = unwind_plan.GetLastRow();
                UnwindPlan::Row *newrow = new UnwindPlan::Row;
                if (last_row.get())
                    *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

                // cache the pc register number (in whatever register numbering this UnwindPlan uses) for
                // quick reference during instruction parsing.
                uint32_t pc_reg_num = LLDB_INVALID_REGNUM;
                RegisterInfo pc_reg_info;
                if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC, pc_reg_info))
                    pc_reg_num = pc_reg_info.kinds[unwind_plan.GetRegisterKind()];
                else
                    pc_reg_num = LLDB_INVALID_REGNUM;

                // cache the return address register number (in whatever register numbering this UnwindPlan uses) for
                // quick reference during instruction parsing.
                uint32_t ra_reg_num = LLDB_INVALID_REGNUM;
                RegisterInfo ra_reg_info;
                if (m_inst_emulator_ap->GetRegisterInfo (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA, ra_reg_info))
                    ra_reg_num = ra_reg_info.kinds[unwind_plan.GetRegisterKind()];
                else
                    ra_reg_num = LLDB_INVALID_REGNUM;

                for (size_t idx=0; idx<num_instructions; ++idx)
                {
                    m_curr_row_modified = false;
                    m_curr_insn_restored_a_register = false;
                    inst = inst_list.GetInstructionAtIndex (idx).get();
                    if (inst)
                    {
                        if (log && log->GetVerbose ())
                        {
                            StreamString strm;
                            inst->Dump(&strm, inst_list.GetMaxOpcocdeByteSize (), show_address, show_bytes, NULL);
                            log->PutCString (strm.GetData());
                        }

                        m_inst_emulator_ap->SetInstruction (inst->GetOpcode(), 
                                                            inst->GetAddress(), 
                                                            exe_ctx.GetTargetPtr());

                        m_inst_emulator_ap->EvaluateInstruction (eEmulateInstructionOptionIgnoreConditions);

                        // 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 evern 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())
                            {
                                return_address_register_has_been_saved = true;
                            }

                            // 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 <same>, 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 <same>, 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");
                                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.");
                            }
                        }
                    }
                }
            }
        }
        
        if (log && log->GetVerbose ())
        {
            StreamString strm;
            lldb::addr_t base_addr = range.GetBaseAddress().GetLoadAddress(thread.CalculateTarget().get());
            strm.Printf ("Resulting unwind rows for [0x%" PRIx64 " - 0x%" PRIx64 "):", base_addr, base_addr + range.GetByteSize());
            unwind_plan.Dump(strm, &thread, base_addr);
            log->PutCString (strm.GetData());
        }
        return unwind_plan.GetRowCount() > 0;
    }
    return false;
}
Пример #6
0
void
Instruction::Dump (lldb_private::Stream *s,
                   uint32_t max_opcode_byte_size,
                   bool show_address,
                   bool show_bytes,
                   const ExecutionContext* exe_ctx)
{
    const size_t opcode_column_width = 7;
    const size_t operand_column_width = 25;
    
    CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx);

    StreamString ss;
    
    if (show_address)
    {
        m_address.Dump(&ss,
                       exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL,
                       Address::DumpStyleLoadAddress,
                       Address::DumpStyleModuleWithFileAddress,
                       0);
        
        ss.PutCString(":  ");
    }
    
    if (show_bytes)
    {
        if (m_opcode.GetType() == Opcode::eTypeBytes)
        {
            // x86_64 and i386 are the only ones that use bytes right now so
            // pad out the byte dump to be able to always show 15 bytes (3 chars each) 
            // plus a space
            if (max_opcode_byte_size > 0)
                m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1);
            else
                m_opcode.Dump (&ss, 15 * 3 + 1);
        }
        else
        {
            // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
            // plus two for padding...
            if (max_opcode_byte_size > 0)
                m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1);
            else
                m_opcode.Dump (&ss, 12);
        }        
    }
    
    const size_t opcode_pos = ss.GetSize();
    
    ss.PutCString (m_opcode_name.c_str());
    ss.FillLastLineToColumn (opcode_pos + opcode_column_width, ' ');
    ss.PutCString (m_mnemocics.c_str());
    
    if (!m_comment.empty())
    {
        ss.FillLastLineToColumn (opcode_pos + opcode_column_width + operand_column_width, ' ');        
        ss.PutCString (" ; ");
        ss.PutCString (m_comment.c_str());
    }
    s->Write (ss.GetData(), ss.GetSize());
}
Пример #7
0
 const std::string &getErrorString()
 {
     return m_error_stream.GetString();
 }
Пример #8
0
void
FormatManager::GetPossibleMatches (ValueObject& valobj,
                                   CompilerType compiler_type,
                                   uint32_t reason,
                                   lldb::DynamicValueType use_dynamic,
                                   FormattersMatchVector& entries,
                                   bool did_strip_ptr,
                                   bool did_strip_ref,
                                   bool did_strip_typedef,
                                   bool root_level)
{
    compiler_type = compiler_type.GetTypeForFormatters();
    ConstString type_name(compiler_type.GetConstTypeName());
    if (valobj.GetBitfieldBitSize() > 0)
    {
        StreamString sstring;
        sstring.Printf("%s:%d",type_name.AsCString(),valobj.GetBitfieldBitSize());
        ConstString bitfieldname = ConstString(sstring.GetData());
        entries.push_back({bitfieldname,0,did_strip_ptr,did_strip_ref,did_strip_typedef});
        reason |= lldb_private::eFormatterChoiceCriterionStrippedBitField;
    }

    if (!compiler_type.IsMeaninglessWithoutDynamicResolution())
    {
        entries.push_back({type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});

        ConstString display_type_name(compiler_type.GetDisplayTypeName());
        if (display_type_name != type_name)
            entries.push_back({display_type_name,reason,did_strip_ptr,did_strip_ref,did_strip_typedef});
    }

    for (bool is_rvalue_ref = true, j = true; j && compiler_type.IsReferenceType(nullptr, &is_rvalue_ref); j = false)
    {
        CompilerType non_ref_type = compiler_type.GetNonReferenceType();
        GetPossibleMatches(valobj,
                           non_ref_type,
                           reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
                           use_dynamic,
                           entries,
                           did_strip_ptr,
                           true,
                           did_strip_typedef);
        if (non_ref_type.IsTypedefType())
        {
            CompilerType deffed_referenced_type = non_ref_type.GetTypedefedType();
            deffed_referenced_type = is_rvalue_ref ? deffed_referenced_type.GetRValueReferenceType() : deffed_referenced_type.GetLValueReferenceType();
            GetPossibleMatches(valobj,
                               deffed_referenced_type,
                               reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
                               use_dynamic,
                               entries,
                               did_strip_ptr,
                               did_strip_ref,
                               true); // this is not exactly the usual meaning of stripping typedefs
        }
    }
    
    if (compiler_type.IsPointerType())
    {
        CompilerType non_ptr_type = compiler_type.GetPointeeType();
        GetPossibleMatches(valobj,
                           non_ptr_type,
                           reason | lldb_private::eFormatterChoiceCriterionStrippedPointerReference,
                           use_dynamic,
                           entries,
                           true,
                           did_strip_ref,
                           did_strip_typedef);
        if (non_ptr_type.IsTypedefType())
        {
            CompilerType deffed_pointed_type = non_ptr_type.GetTypedefedType().GetPointerType();
            GetPossibleMatches(valobj,
                               deffed_pointed_type,
                               reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
                               use_dynamic,
                               entries,
                               did_strip_ptr,
                               did_strip_ref,
                               true); // this is not exactly the usual meaning of stripping typedefs
        }
    }
    
    for (lldb::LanguageType language_type : GetCandidateLanguages(valobj))
    {
        if (Language* language = Language::FindPlugin(language_type))
        {
            for (ConstString candidate : language->GetPossibleFormattersMatches(valobj, use_dynamic))
            {
                entries.push_back({candidate,
                                   reason | lldb_private::eFormatterChoiceCriterionLanguagePlugin,
                                   did_strip_ptr,
                                   did_strip_ref,
                                   did_strip_typedef});
            }
        }
    }
        
    // try to strip typedef chains
    if (compiler_type.IsTypedefType())
    {
        CompilerType deffed_type = compiler_type.GetTypedefedType();
        GetPossibleMatches(valobj,
                           deffed_type,
                           reason | lldb_private::eFormatterChoiceCriterionNavigatedTypedefs,
                           use_dynamic,
                           entries,
                           did_strip_ptr,
                           did_strip_ref,
                           true);
    }
    
    if (root_level)
    {
        do {
            if (!compiler_type.IsValid())
                break;
            
            CompilerType unqual_compiler_ast_type = compiler_type.GetFullyUnqualifiedType();
            if (!unqual_compiler_ast_type.IsValid())
                break;
            if (unqual_compiler_ast_type.GetOpaqueQualType() != compiler_type.GetOpaqueQualType())
                GetPossibleMatches (valobj,
                                    unqual_compiler_ast_type,
                                    reason,
                                    use_dynamic,
                                    entries,
                                    did_strip_ptr,
                                    did_strip_ref,
                                    did_strip_typedef);
        } while(false);
        
        
        // if all else fails, go to static type
        if (valobj.IsDynamic())
        {
            lldb::ValueObjectSP static_value_sp(valobj.GetStaticValue());
            if (static_value_sp)
                GetPossibleMatches(*static_value_sp.get(),
                                   static_value_sp->GetCompilerType(),
                                   reason | lldb_private::eFormatterChoiceCriterionWentToStaticValue,
                                   use_dynamic,
                                   entries,
                                   did_strip_ptr,
                                   did_strip_ref,
                                   did_strip_typedef,
                                   true);
        }
    }
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &packet)
{
    StreamString response;

    // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00

    ArchSpec host_arch(HostInfo::GetArchitecture());
    const llvm::Triple &host_triple = host_arch.GetTriple();
    response.PutCString("triple:");
    response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
    response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());

    const char* distribution_id = host_arch.GetDistributionId ().AsCString ();
    if (distribution_id)
    {
        response.PutCString("distribution_id:");
        response.PutCStringAsRawHex8(distribution_id);
        response.PutCString(";");
    }

    // Only send out MachO info when lldb-platform/llgs is running on a MachO host.
#if defined(__APPLE__)
    uint32_t cpu = host_arch.GetMachOCPUType();
    uint32_t sub = host_arch.GetMachOCPUSubType();
    if (cpu != LLDB_INVALID_CPUTYPE)
        response.Printf ("cputype:%u;", cpu);
    if (sub != LLDB_INVALID_CPUTYPE)
        response.Printf ("cpusubtype:%u;", sub);

    if (cpu == ArchSpec::kCore_arm_any)
        response.Printf("watchpoint_exceptions_received:before;");   // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
    else
        response.Printf("watchpoint_exceptions_received:after;");
#else
    if (host_arch.GetMachine() == llvm::Triple::aarch64 ||
        host_arch.GetMachine() == llvm::Triple::aarch64_be ||
        host_arch.GetMachine() == llvm::Triple::arm ||
        host_arch.GetMachine() == llvm::Triple::armeb ||
        host_arch.GetMachine() == llvm::Triple::mips64 ||
        host_arch.GetMachine() == llvm::Triple::mips64el ||
        host_arch.GetMachine() == llvm::Triple::mips ||
        host_arch.GetMachine() == llvm::Triple::mipsel)
        response.Printf("watchpoint_exceptions_received:before;");
    else
        response.Printf("watchpoint_exceptions_received:after;");
#endif

    switch (endian::InlHostByteOrder())
    {
    case eByteOrderBig:     response.PutCString ("endian:big;"); break;
    case eByteOrderLittle:  response.PutCString ("endian:little;"); break;
    case eByteOrderPDP:     response.PutCString ("endian:pdp;"); break;
    default:                response.PutCString ("endian:unknown;"); break;
    }

    uint32_t major = UINT32_MAX;
    uint32_t minor = UINT32_MAX;
    uint32_t update = UINT32_MAX;
    if (HostInfo::GetOSVersion(major, minor, update))
    {
        if (major != UINT32_MAX)
        {
            response.Printf("os_version:%u", major);
            if (minor != UINT32_MAX)
            {
                response.Printf(".%u", minor);
                if (update != UINT32_MAX)
                    response.Printf(".%u", update);
            }
            response.PutChar(';');
        }
    }

    std::string s;
    if (HostInfo::GetOSBuildString(s))
    {
        response.PutCString ("os_build:");
        response.PutCStringAsRawHex8(s.c_str());
        response.PutChar(';');
    }
    if (HostInfo::GetOSKernelDescription(s))
    {
        response.PutCString ("os_kernel:");
        response.PutCStringAsRawHex8(s.c_str());
        response.PutChar(';');
    }

#if defined(__APPLE__)

#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
    // For iOS devices, we are connected through a USB Mux so we never pretend
    // to actually have a hostname as far as the remote lldb that is connecting
    // to this lldb-platform is concerned
    response.PutCString ("hostname:");
    response.PutCStringAsRawHex8("127.0.0.1");
    response.PutChar(';');
#else   // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
    if (HostInfo::GetHostname(s))
    {
        response.PutCString ("hostname:");
        response.PutCStringAsRawHex8(s.c_str());
        response.PutChar(';');
    }
#endif  // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)

#else   // #if defined(__APPLE__)
    if (HostInfo::GetHostname(s))
    {
        response.PutCString ("hostname:");
        response.PutCStringAsRawHex8(s.c_str());
        response.PutChar(';');
    }
#endif  // #if defined(__APPLE__)

    if (g_default_packet_timeout_sec > 0)
        response.Printf ("default_packet_timeout:%u;", g_default_packet_timeout_sec);

    return SendPacketNoLock (response.GetData(), response.GetSize());
}
void
GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle (
    const ProcessInstanceInfo &proc_info, StreamString &response)
{
    response.Printf ("pid:%" PRIx64 ";parent-pid:%" PRIx64 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
                     proc_info.GetProcessID(),
                     proc_info.GetParentProcessID(),
                     proc_info.GetUserID(),
                     proc_info.GetGroupID(),
                     proc_info.GetEffectiveUserID(),
                     proc_info.GetEffectiveGroupID());

    const ArchSpec &proc_arch = proc_info.GetArchitecture();
    if (proc_arch.IsValid())
    {
        const llvm::Triple &proc_triple = proc_arch.GetTriple();
#if defined(__APPLE__)
        // We'll send cputype/cpusubtype.
        const uint32_t cpu_type = proc_arch.GetMachOCPUType();
        if (cpu_type != 0)
            response.Printf ("cputype:%" PRIx32 ";", cpu_type);

        const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType();
        if (cpu_subtype != 0)
            response.Printf ("cpusubtype:%" PRIx32 ";", cpu_subtype);

        const std::string vendor = proc_triple.getVendorName ();
        if (!vendor.empty ())
            response.Printf ("vendor:%s;", vendor.c_str ());
#else
        // We'll send the triple.
        response.PutCString("triple:");
        response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
        response.PutChar(';');
#endif
        std::string ostype = proc_triple.getOSName ();
        // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64.
        if (proc_triple.getVendor () == llvm::Triple::Apple)
        {
            switch (proc_triple.getArch ())
            {
                case llvm::Triple::arm:
                case llvm::Triple::thumb:
                case llvm::Triple::aarch64:
                    ostype = "ios";
                    break;
                default:
                    // No change.
                    break;
            }
        }
        response.Printf ("ostype:%s;", ostype.c_str ());


        switch (proc_arch.GetByteOrder ())
        {
            case lldb::eByteOrderLittle: response.PutCString ("endian:little;"); break;
            case lldb::eByteOrderBig:    response.PutCString ("endian:big;");    break;
            case lldb::eByteOrderPDP:    response.PutCString ("endian:pdp;");    break;
            default:
                // Nothing.
                break;
        }

        if (proc_triple.isArch64Bit ())
            response.PutCString ("ptrsize:8;");
        else if (proc_triple.isArch32Bit ())
            response.PutCString ("ptrsize:4;");
        else if (proc_triple.isArch16Bit ())
            response.PutCString ("ptrsize:2;");
    }
}