Exemplo n.º 1
0
void SBThread::StepOver(lldb::RunMode stop_other_threads) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf("SBThread(%p)::StepOver (stop_other_threads='%s')",
                static_cast<void *>(exe_ctx.GetThreadPtr()),
                Thread::RunModeAsCString(stop_other_threads));

  if (exe_ctx.HasThreadScope()) {
    Thread *thread = exe_ctx.GetThreadPtr();
    bool abort_other_plans = false;
    StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));

    ThreadPlanSP new_plan_sp;
    if (frame_sp) {
      if (frame_sp->HasDebugInformation()) {
        const LazyBool avoid_no_debug = eLazyBoolCalculate;
        SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
        new_plan_sp = thread->QueueThreadPlanForStepOverRange(
            abort_other_plans, sc.line_entry, sc, stop_other_threads,
            avoid_no_debug);
      } else {
        new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
            true, abort_other_plans, stop_other_threads);
      }
    }

    // This returns an error, we should use it!
    ResumeNewPlan(exe_ctx, new_plan_sp.get());
  }
}
Exemplo n.º 2
0
lldb::SBFrame SBThread::SetSelectedFrame(uint32_t idx) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  SBFrame sb_frame;
  StackFrameSP frame_sp;
  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (exe_ctx.HasThreadScope()) {
    Process::StopLocker stop_locker;
    if (stop_locker.TryLock(&exe_ctx.GetProcessPtr()->GetRunLock())) {
      Thread *thread = exe_ctx.GetThreadPtr();
      frame_sp = thread->GetStackFrameAtIndex(idx);
      if (frame_sp) {
        thread->SetSelectedFrame(frame_sp.get());
        sb_frame.SetFrameSP(frame_sp);
      }
    } else {
      if (log)
        log->Printf(
            "SBThread(%p)::SetSelectedFrame() => error: process is running",
            static_cast<void *>(exe_ctx.GetThreadPtr()));
    }
  }

  if (log) {
    SBStream frame_desc_strm;
    sb_frame.GetDescription(frame_desc_strm);
    log->Printf("SBThread(%p)::SetSelectedFrame (idx=%u) => SBFrame(%p): %s",
                static_cast<void *>(exe_ctx.GetThreadPtr()), idx,
                static_cast<void *>(frame_sp.get()), frame_desc_strm.GetData());
  }
  return sb_frame;
}
  bool DoExecute(Args &command, CommandReturnObject &result) override {
    StringList commands;
    commands.AppendString("thread backtrace");

    Thread *thread = m_exe_ctx.GetThreadPtr();
    if (thread) {
      char command_buffer[256];

      uint32_t frame_count = thread->GetStackFrameCount();
      for (uint32_t i = 0; i < frame_count; ++i) {
        StackFrameSP frame = thread->GetStackFrameAtIndex(i);
        lldb::addr_t pc = frame->GetStackID().GetPC();

        snprintf(command_buffer, sizeof(command_buffer),
                 "disassemble --bytes --address 0x%" PRIx64, pc);
        commands.AppendString(command_buffer);

        snprintf(command_buffer, sizeof(command_buffer),
                 "image show-unwind --address 0x%" PRIx64, pc);
        commands.AppendString(command_buffer);
      }
    }

    const FileSpec &outfile_spec =
        m_outfile_options.GetFile().GetCurrentValue();
    if (outfile_spec) {
      char path[PATH_MAX];
      outfile_spec.GetPath(path, sizeof(path));

      uint32_t open_options =
          File::eOpenOptionWrite | File::eOpenOptionCanCreate |
          File::eOpenOptionAppend | File::eOpenOptionCloseOnExec;

      const bool append = m_outfile_options.GetAppend().GetCurrentValue();
      if (!append)
        open_options |= File::eOpenOptionTruncate;

      StreamFileSP outfile_stream = std::make_shared<StreamFile>();
      Status error = outfile_stream->GetFile().Open(path, open_options);
      if (error.Fail()) {
        result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n",
                                     path, append ? "append" : "write",
                                     error.AsCString());
        result.SetStatus(eReturnStatusFailed);
        return false;
      }

      result.SetImmediateOutputStream(outfile_stream);
    }

    CommandInterpreterRunOptions options;
    options.SetStopOnError(false);
    options.SetEchoCommands(true);
    options.SetPrintResults(true);
    options.SetAddToHistory(false);
    m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result);

    return result.Succeeded();
  }
Exemplo n.º 4
0
ThreadPlanSP
DynamicLoaderPOSIXDYLD::GetStepThroughTrampolinePlan(Thread &thread, bool stop)
{
    LogSP log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
    ThreadPlanSP thread_plan_sp;

    StackFrame *frame = thread.GetStackFrameAtIndex(0).get();
    const SymbolContext &context = frame->GetSymbolContext(eSymbolContextSymbol);
    Symbol *sym = context.symbol;

    if (sym == NULL || !sym->IsTrampoline())
        return thread_plan_sp;

    const ConstString &sym_name = sym->GetMangled().GetName(Mangled::ePreferMangled);
    if (!sym_name)
        return thread_plan_sp;

    SymbolContextList target_symbols;
    Target &target = thread.GetProcess().GetTarget();
    ModuleList &images = target.GetImages();

    images.FindSymbolsWithNameAndType(sym_name, eSymbolTypeCode, target_symbols);
    size_t num_targets = target_symbols.GetSize();
    if (!num_targets)
        return thread_plan_sp;

    typedef std::vector<lldb::addr_t> AddressVector;
    AddressVector addrs;
    for (size_t i = 0; i < num_targets; ++i)
    {
        SymbolContext context;
        AddressRange range;
        if (target_symbols.GetContextAtIndex(i, context))
        {
            context.GetAddressRange(eSymbolContextEverything, 0, false, range);
            lldb::addr_t addr = range.GetBaseAddress().GetLoadAddress(&target);
            if (addr != LLDB_INVALID_ADDRESS)
                addrs.push_back(addr);
        }
    }

    if (addrs.size() > 0) 
    {
        AddressVector::iterator start = addrs.begin();
        AddressVector::iterator end = addrs.end();

        std::sort(start, end);
        addrs.erase(std::unique(start, end), end);
        thread_plan_sp.reset(new ThreadPlanRunToAddress(thread, addrs, stop));
    }

    return thread_plan_sp;
}
Exemplo n.º 5
0
void SBThread::StepInto(const char *target_name, uint32_t end_line,
                        SBError &error, lldb::RunMode stop_other_threads) {
  Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));

  std::unique_lock<std::recursive_mutex> lock;
  ExecutionContext exe_ctx(m_opaque_sp.get(), lock);

  if (log)
    log->Printf(
        "SBThread(%p)::StepInto (target_name='%s', stop_other_threads='%s')",
        static_cast<void *>(exe_ctx.GetThreadPtr()),
        target_name ? target_name : "<NULL>",
        Thread::RunModeAsCString(stop_other_threads));

  if (exe_ctx.HasThreadScope()) {
    bool abort_other_plans = false;

    Thread *thread = exe_ctx.GetThreadPtr();
    StackFrameSP frame_sp(thread->GetStackFrameAtIndex(0));
    ThreadPlanSP new_plan_sp;

    if (frame_sp && frame_sp->HasDebugInformation()) {
      SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
      AddressRange range;
      if (end_line == LLDB_INVALID_LINE_NUMBER)
        range = sc.line_entry.range;
      else {
        if (!sc.GetAddressRangeFromHereToEndLine(end_line, range, error.ref()))
          return;
      }

      const LazyBool step_out_avoids_code_without_debug_info =
          eLazyBoolCalculate;
      const LazyBool step_in_avoids_code_without_debug_info =
          eLazyBoolCalculate;
      new_plan_sp = thread->QueueThreadPlanForStepInRange(
          abort_other_plans, range, sc, target_name, stop_other_threads,
          step_in_avoids_code_without_debug_info,
          step_out_avoids_code_without_debug_info);
    } else {
      new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction(
          false, abort_other_plans, stop_other_threads);
    }

    error = ResumeNewPlan(exe_ctx, new_plan_sp.get());
  }
}
Exemplo n.º 6
0
void
SBThread::StepInto (const char *target_name, lldb::RunMode stop_other_threads)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));

    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    if (log)
        log->Printf ("SBThread(%p)::StepInto (target_name='%s', stop_other_threads='%s')",
                     exe_ctx.GetThreadPtr(),
                     target_name? target_name: "<NULL>",
                     Thread::RunModeAsCString (stop_other_threads));
    
    if (exe_ctx.HasThreadScope())
    {
        bool abort_other_plans = false;

        Thread *thread = exe_ctx.GetThreadPtr();
        StackFrameSP frame_sp(thread->GetStackFrameAtIndex (0));
        ThreadPlanSP new_plan_sp;

        if (frame_sp && frame_sp->HasDebugInformation ())
        {
            bool avoid_code_without_debug_info = true;
            SymbolContext sc(frame_sp->GetSymbolContext(eSymbolContextEverything));
            new_plan_sp = thread->QueueThreadPlanForStepInRange (abort_other_plans,
                                                              sc.line_entry.range,
                                                              sc,
                                                              target_name,
                                                              stop_other_threads,
                                                              avoid_code_without_debug_info);
        }
        else
        {
            new_plan_sp = thread->QueueThreadPlanForStepSingleInstruction (false,
                                                                        abort_other_plans, 
                                                                        stop_other_threads);
        }
        
        // This returns an error, we should use it!
        ResumeNewPlan (exe_ctx, new_plan_sp.get());
    }
}
Exemplo n.º 7
0
ValueObjectSP
ABI::GetReturnValueObject (Thread &thread,
                          ClangASTType &ast_type) const
{
    if (!ast_type.IsValid())
        return ValueObjectSP();
        
    Value ret_value;
    ret_value.SetContext(Value::eContextTypeClangType, 
                       ast_type.GetOpaqueQualType());
    if (GetReturnValue (thread, ret_value))
    {
        return ValueObjectConstResult::Create(
                                        thread.GetStackFrameAtIndex(0).get(),
                                        ast_type.GetASTContext(),
                                        ret_value,
                                        ConstString("FunctionReturn"));

    }
    else
        return ValueObjectSP();
}
Exemplo n.º 8
0
ValueObjectSP
ABIMacOSX_i386::GetReturnValueObjectImpl (Thread &thread,
        CompilerType &compiler_type) const
{
    Value value;
    ValueObjectSP return_valobj_sp;

    if (!compiler_type)
        return return_valobj_sp;

    //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType());
    value.SetCompilerType (compiler_type);

    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return return_valobj_sp;

    bool is_signed;

    if (compiler_type.IsIntegerType (is_signed))
    {
        size_t bit_width = compiler_type.GetBitSize(&thread);

        unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
        unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];

        switch (bit_width)
        {
        default:
        case 128:
            // Scalar can't hold 128-bit literals, so we don't handle this
            return return_valobj_sp;
        case 64:
            uint64_t raw_value;
            raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
            raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;
            if (is_signed)
                value.GetScalar() = (int64_t)raw_value;
            else
                value.GetScalar() = (uint64_t)raw_value;
            break;
        case 32:
            if (is_signed)
                value.GetScalar() = (int32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
            else
                value.GetScalar() = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
            break;
        case 16:
            if (is_signed)
                value.GetScalar() = (int16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
            else
                value.GetScalar() = (uint16_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffff);
            break;
        case 8:
            if (is_signed)
                value.GetScalar() = (int8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
            else
                value.GetScalar() = (uint8_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xff);
            break;
        }
    }
    else if (compiler_type.IsPointerType ())
    {
        unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
        uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff;
        value.GetScalar() = ptr;
    }
    else
    {
        // not handled yet
        return return_valobj_sp;
    }

    // If we get here, we have a valid Value, so make our ValueObject out of it:

    return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
                       value,
                       ConstString(""));
    return return_valobj_sp;
}
Exemplo n.º 9
0
ValueObjectSP
ABISysV_i386::GetReturnValueObjectSimple (Thread &thread,
                                          CompilerType &return_clang_type) const
{
    ValueObjectSP return_valobj_sp;
    Value value;

    if (!return_clang_type)
        return return_valobj_sp;

    value.SetCompilerType (return_clang_type);

    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return return_valobj_sp;

    const uint32_t type_flags = return_clang_type.GetTypeInfo ();

    unsigned eax_id = reg_ctx->GetRegisterInfoByName("eax", 0)->kinds[eRegisterKindLLDB];
    unsigned edx_id = reg_ctx->GetRegisterInfoByName("edx", 0)->kinds[eRegisterKindLLDB];


    // Following "IF ELSE" block categorizes various 'Fundamental Data Types'.
    // The terminology 'Fundamental Data Types' used here is adopted from
    // Table 2.1 of the reference document (specified on top of this file)

    if (type_flags & eTypeIsPointer)     // 'Pointer'
    {
        uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ;
        value.SetValueType(Value::eValueTypeScalar);
        value.GetScalar() = ptr;
        return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
                                                           value,
                                                           ConstString(""));
    }

    else if ((type_flags & eTypeIsScalar) || (type_flags & eTypeIsEnumeration)) //'Integral' + 'Floating Point'
    {
        value.SetValueType(Value::eValueTypeScalar);
        const size_t byte_size = return_clang_type.GetByteSize(nullptr);
        bool success = false;

        if (type_flags & eTypeIsInteger)    // 'Integral' except enum
        {
            const bool is_signed = ((type_flags & eTypeIsSigned) != 0);
            uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ;
            raw_value |= (thread.GetRegisterContext()->ReadRegisterAsUnsigned(edx_id, 0) & 0xffffffff) << 32;

            switch (byte_size)
            {
                default:
                   break;

                case 16:
                   // For clang::BuiltinType::UInt128 & Int128
                   // ToDo: Need to decide how to handle it
                   break ;

                case 8:
                    if (is_signed)
                        value.GetScalar() = (int64_t)(raw_value);
                    else
                        value.GetScalar() = (uint64_t)(raw_value);
                    success = true;
                    break;

                case 4:
                    if (is_signed)
                        value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
                    else
                        value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
                    success = true;
                    break;

                case 2:
                    if (is_signed)
                        value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
                    else
                        value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
                    success = true;
                    break;

                case 1:
                    if (is_signed)
                        value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
                    else
                        value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
                    success = true;
                    break;
             }

             if (success)
                 return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
                                                                    value,
                                                                    ConstString(""));
        }

        else if (type_flags & eTypeIsEnumeration)     // handles enum
        {
            uint32_t enm = thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff ;
            value.SetValueType(Value::eValueTypeScalar);
            value.GetScalar() = enm;
            return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
                                                               value,
                                                               ConstString(""));
        }

        else if (type_flags & eTypeIsFloat)  // 'Floating Point'
        {
            if (byte_size <= 12)      // handles float, double, long double, __float80
            {
                const RegisterInfo *st0_info = reg_ctx->GetRegisterInfoByName("st0", 0);
                RegisterValue st0_value;

                if (reg_ctx->ReadRegister (st0_info, st0_value))
                {
                    DataExtractor data;
                    if (st0_value.GetData(data))
                    {
                        lldb::offset_t offset = 0;
                        long double value_long_double = data.GetLongDouble(&offset);

                        if (byte_size == 4)    // float is 4 bytes
                        {
                            float value_float = (float)value_long_double;
                            value.GetScalar() = value_float;
                            success = true;
                        }
                        else if (byte_size == 8)   // double is 8 bytes
                        {
                            // On Android Platform: long double is also 8 bytes
                            // It will be handled here only.
                            double value_double = (double)value_long_double;
                            value.GetScalar() =  value_double;
                            success = true;
                        }
                        else if (byte_size == 12) // long double and __float80 are 12 bytes on i386
                        {
                            value.GetScalar() = value_long_double;
                            success = true;
                        }
                    }
                }

                if (success)
                    return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
                                                                       value,
                                                                       ConstString(""));
            }
            else if(byte_size == 16)   // handles __float128
            {
                lldb::addr_t storage_addr = (uint32_t)(thread.GetRegisterContext()->ReadRegisterAsUnsigned(eax_id, 0) & 0xffffffff);
                return_valobj_sp = ValueObjectMemory::Create (&thread,
                                                               "",
                                                              Address (storage_addr, nullptr),
                                                              return_clang_type);
            }
        }

        else  // Neither 'Integral' nor 'Floating Point'
        {
            // If flow reaches here then check type_flags
            // This type_flags is unhandled
        }
    }

    else if (type_flags & eTypeIsComplex)    // 'Complex Floating Point'
    {
       // ToDo: Yet to be implemented
    }

    else if (type_flags & eTypeIsVector)    // 'Packed'
    {
        const size_t byte_size = return_clang_type.GetByteSize(nullptr);
        if (byte_size > 0)
        {
            const RegisterInfo *vec_reg = reg_ctx->GetRegisterInfoByName("xmm0", 0);
            if (vec_reg == nullptr)
                vec_reg = reg_ctx->GetRegisterInfoByName("mm0", 0);

            if (vec_reg)
            {
                if (byte_size <= vec_reg->byte_size)
                {
                    ProcessSP process_sp (thread.GetProcess());
                    if (process_sp)
                    {
                        std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
                        const ByteOrder byte_order = process_sp->GetByteOrder();
                        RegisterValue reg_value;
                        if (reg_ctx->ReadRegister(vec_reg, reg_value))
                        {
                            Error error;
                            if (reg_value.GetAsMemoryData (vec_reg,
                                                           heap_data_ap->GetBytes(),
                                                           heap_data_ap->GetByteSize(),
                                                           byte_order,
                                                           error))
                            {
                                DataExtractor data (DataBufferSP (heap_data_ap.release()),
                                                    byte_order,
                                                    process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
                                return_valobj_sp = ValueObjectConstResult::Create (&thread,
                                                                                   return_clang_type,
                                                                                   ConstString(""),
                                                                                   data);
                            }
                        }
                    }
                }
                else if (byte_size <= vec_reg->byte_size*2)
                {
                    const RegisterInfo *vec_reg2 = reg_ctx->GetRegisterInfoByName("xmm1", 0);
                    if (vec_reg2)
                    {
                        ProcessSP process_sp (thread.GetProcess());
                        if (process_sp)
                        {
                            std::unique_ptr<DataBufferHeap> heap_data_ap (new DataBufferHeap(byte_size, 0));
                            const ByteOrder byte_order = process_sp->GetByteOrder();
                            RegisterValue reg_value;
                            RegisterValue reg_value2;
                            if (reg_ctx->ReadRegister(vec_reg, reg_value) && reg_ctx->ReadRegister(vec_reg2, reg_value2))
                            {

                                Error error;
                                if (reg_value.GetAsMemoryData (vec_reg,
                                                               heap_data_ap->GetBytes(),
                                                               vec_reg->byte_size,
                                                               byte_order,
                                                               error) &&
                                    reg_value2.GetAsMemoryData (vec_reg2,
                                                                heap_data_ap->GetBytes() + vec_reg->byte_size,
                                                                heap_data_ap->GetByteSize() - vec_reg->byte_size,
                                                                byte_order,
                                                                error))
                                {
                                    DataExtractor data (DataBufferSP (heap_data_ap.release()),
                                                        byte_order,
                                                        process_sp->GetTarget().GetArchitecture().GetAddressByteSize());
                                    return_valobj_sp = ValueObjectConstResult::Create (&thread,
                                                                                       return_clang_type,
                                                                                       ConstString(""),
                                                                                       data);
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    else    // 'Decimal Floating Point'
    {
       //ToDo: Yet to be implemented
    }
    return return_valobj_sp;
}
Exemplo n.º 10
0
ThreadPlanSP
ObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool stop_others)
{
    ThreadPlanSP ret_plan_sp;
    lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();

    MsgsendMap::iterator pos;
    pos = m_msgSend_map.find (curr_pc);
    if (pos != m_msgSend_map.end())
    {
        Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);

        const DispatchFunction *this_dispatch = &g_dispatch_functions[(*pos).second];

        lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0);

        Process *process = thread.CalculateProcess();
        const ABI *abi = process->GetABI();
        if (abi == NULL)
            return ret_plan_sp;

        Target *target = thread.CalculateTarget();

        // FIXME: Since neither the value nor the Clang QualType know their ASTContext,
        // we have to make sure the type we put in our value list comes from the same ASTContext
        // the ABI will use to get the argument values.  THis is the bottom-most frame's module.

        ClangASTContext *clang_ast_context = target->GetScratchClangASTContext();
        ValueList argument_values;
        Value input_value;
        void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false);
        input_value.SetValueType (Value::eValueTypeScalar);
        input_value.SetContext (Value::eContextTypeOpaqueClangQualType, clang_void_ptr_type);

        int obj_index;
        int sel_index;

        // If this is a struct return dispatch, then the first argument is the
        // return struct pointer, and the object is the second, and the selector is the third.
        // Otherwise the object is the first and the selector the second.
        if (this_dispatch->stret_return)
        {
            obj_index = 1;
            sel_index = 2;
            argument_values.PushValue(input_value);
            argument_values.PushValue(input_value);
            argument_values.PushValue(input_value);
        }
        else
        {
            obj_index = 0;
            sel_index = 1;
            argument_values.PushValue(input_value);
            argument_values.PushValue(input_value);
        }


        bool success = abi->GetArgumentValues (thread, argument_values);
        if (!success)
            return ret_plan_sp;

        // Okay, the first value here is the object, we actually want the class of that object.
        // For now we're just going with the ISA.
        // FIXME: This should really be the return value of [object class] to properly handle KVO interposition.

        Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));

        // This is a little cheesy, but since object->isa is the first field,
        // making the object value a load address value and resolving it will get
        // the pointer sized data pointed to by that value...
        ExecutionContext exec_ctx;
        thread.Calculate (exec_ctx);

        isa_value.SetValueType(Value::eValueTypeLoadAddress);
        isa_value.ResolveValue(&exec_ctx, clang_ast_context->getASTContext());

        if (this_dispatch->fixedup == DispatchFunction::eFixUpFixed)
        {
            // For the FixedUp method the Selector is actually a pointer to a
            // structure, the second field of which is the selector number.
            Value *sel_value = argument_values.GetValueAtIndex(sel_index);
            sel_value->GetScalar() += process->GetAddressByteSize();
            sel_value->SetValueType(Value::eValueTypeLoadAddress);
            sel_value->ResolveValue(&exec_ctx, clang_ast_context->getASTContext());
        }
        else if (this_dispatch->fixedup == DispatchFunction::eFixUpToFix)
        {
            // FIXME: If the method dispatch is not "fixed up" then the selector is actually a
            // pointer to the string name of the selector.  We need to look that up...
            // For now I'm going to punt on that and just return no plan.
            if (log)
                log->Printf ("Punting on stepping into un-fixed-up method dispatch.");
            return ret_plan_sp;
        }

        // FIXME: If this is a dispatch to the super-class, we need to get the super-class from
        // the class, and disaptch to that instead.
        // But for now I just punt and return no plan.
        if (this_dispatch->is_super)
        {
            if (log)
                log->Printf ("Punting on stepping into super method dispatch.");
            return ret_plan_sp;
        }

        ValueList dispatch_values;
        dispatch_values.PushValue (isa_value);
        dispatch_values.PushValue(*(argument_values.GetValueAtIndex(sel_index)));

        if (log)
        {
            log->Printf("Resolving method call for class - 0x%llx and selector - 0x%llx",
                        dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
                        dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong());
        }

        lldb::addr_t impl_addr = LookupInCache (dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
                                                dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong());

        if (impl_addr == LLDB_INVALID_ADDRESS)
        {

            Address resolve_address(NULL, this_dispatch->stret_return ? m_impl_stret_fn_addr : m_impl_fn_addr);

            StreamString errors;
            {
                // Scope for mutex locker:
                Mutex::Locker locker(m_impl_function_mutex);
                if (!m_impl_function.get())
                {
                    m_impl_function.reset(new ClangFunction(process->GetTargetTriple().GetCString(),
                                                            clang_ast_context,
                                                            clang_void_ptr_type,
                                                            resolve_address,
                                                            dispatch_values));

                    unsigned num_errors = m_impl_function->CompileFunction(errors);
                    if (num_errors)
                    {
                        if (log)
                            log->Printf ("Error compiling function: \"%s\".", errors.GetData());
                        return ret_plan_sp;
                    }

                    errors.Clear();
                    if (!m_impl_function->WriteFunctionWrapper(exec_ctx, errors))
                    {
                        if (log)
                            log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
                        return ret_plan_sp;
                    }
                }

            }

            errors.Clear();

            // Now write down the argument values for this call.
            lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
            if (!m_impl_function->WriteFunctionArguments (exec_ctx, args_addr, resolve_address, dispatch_values, errors))
                return ret_plan_sp;

            ret_plan_sp.reset (new ThreadPlanStepThroughObjCTrampoline (thread, this, args_addr,
                               argument_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
                               dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(),
                               dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong(),
                               stop_others));
        }
        else
        {
            if (log)
                log->Printf ("Found implementation address in cache: 0x%llx", impl_addr);

            ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
        }
    }

    return ret_plan_sp;
}
Exemplo n.º 11
0
bool
lldb_private::InferiorCallMmap (Process *process,
                                addr_t &allocated_addr,
                                addr_t addr,
                                addr_t length,
                                unsigned prot,
                                unsigned flags,
                                addr_t fd,
                                addr_t offset)
{
    Thread *thread = process->GetThreadList().GetSelectedThread().get();
    if (thread == NULL)
        return false;

    const bool append = true;
    const bool include_symbols = true;
    const bool include_inlines = false;
    SymbolContextList sc_list;
    const uint32_t count
        = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"),
                eFunctionNameTypeFull,
                include_symbols,
                include_inlines,
                append,
                sc_list);
    if (count > 0)
    {
        SymbolContext sc;
        if (sc_list.GetContextAtIndex(0, sc))
        {
            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
            const bool use_inline_block_range = false;
            EvaluateExpressionOptions options;
            options.SetStopOthers(true);
            options.SetUnwindOnError(true);
            options.SetIgnoreBreakpoints(true);
            options.SetTryAllThreads(true);
            options.SetDebug (false);
            options.SetTimeoutUsec(500000);

            addr_t prot_arg, flags_arg = 0;
            if (prot == eMmapProtNone)
                prot_arg = PROT_NONE;
            else {
                prot_arg = 0;
                if (prot & eMmapProtExec)
                    prot_arg |= PROT_EXEC;
                if (prot & eMmapProtRead)
                    prot_arg |= PROT_READ;
                if (prot & eMmapProtWrite)
                    prot_arg |= PROT_WRITE;
            }

            const ArchSpec arch =  process->GetTarget().GetArchitecture();
            flags_arg = process->GetTarget().GetPlatform()->ConvertMmapFlagsToPlatform(arch,flags);

            AddressRange mmap_range;
            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
            {
                ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
                CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
                lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset };
                lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
                                                 mmap_range.GetBaseAddress(),
                                                 clang_void_ptr_type,
                                                 args,
                                                 options));
                if (call_plan_sp)
                {
                    StreamFile error_strm;
                    // This plan is a utility plan, so set it to discard itself when done.
                    call_plan_sp->SetIsMasterPlan (true);
                    call_plan_sp->SetOkayToDiscard(true);

                    StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
                    if (frame)
                    {
                        ExecutionContext exe_ctx;
                        frame->CalculateExecutionContext (exe_ctx);
                        ExpressionResults result = process->RunThreadPlan (exe_ctx,
                                                   call_plan_sp,
                                                   options,
                                                   error_strm);
                        if (result == eExpressionCompleted)
                        {

                            allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
                            if (process->GetAddressByteSize() == 4)
                            {
                                if (allocated_addr == UINT32_MAX)
                                    return false;
                            }
                            else if (process->GetAddressByteSize() == 8)
                            {
                                if (allocated_addr == UINT64_MAX)
                                    return false;
                            }
                            return true;
                        }
                    }
                }
            }
        }
    }

    return false;
}
Exemplo n.º 12
0
ValueObjectSP ABISysV_ppc64::GetReturnValueObjectSimple(
    Thread &thread, CompilerType &return_compiler_type) const {
  ValueObjectSP return_valobj_sp;
  Value value;

  if (!return_compiler_type)
    return return_valobj_sp;

  // value.SetContext (Value::eContextTypeClangType, return_value_type);
  value.SetCompilerType(return_compiler_type);

  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
  if (!reg_ctx)
    return return_valobj_sp;

  const uint32_t type_flags = return_compiler_type.GetTypeInfo();
  if (type_flags & eTypeIsScalar) {
    value.SetValueType(Value::eValueTypeScalar);

    bool success = false;
    if (type_flags & eTypeIsInteger) {
      // Extract the register context so we can read arguments from registers

      const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
      uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
          reg_ctx->GetRegisterInfoByName("r3", 0), 0);
      const bool is_signed = (type_flags & eTypeIsSigned) != 0;
      switch (byte_size) {
      default:
        break;

      case sizeof(uint64_t):
        if (is_signed)
          value.GetScalar() = (int64_t)(raw_value);
        else
          value.GetScalar() = (uint64_t)(raw_value);
        success = true;
        break;

      case sizeof(uint32_t):
        if (is_signed)
          value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
        else
          value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
        success = true;
        break;

      case sizeof(uint16_t):
        if (is_signed)
          value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
        else
          value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
        success = true;
        break;

      case sizeof(uint8_t):
        if (is_signed)
          value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
        else
          value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
        success = true;
        break;
      }
    } else if (type_flags & eTypeIsFloat) {
      if (type_flags & eTypeIsComplex) {
        // Don't handle complex yet.
      } else {
        const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
        if (byte_size <= sizeof(long double)) {
          const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
          RegisterValue f1_value;
          if (reg_ctx->ReadRegister(f1_info, f1_value)) {
            DataExtractor data;
            if (f1_value.GetData(data)) {
              lldb::offset_t offset = 0;
              if (byte_size == sizeof(float)) {
                value.GetScalar() = (float)data.GetFloat(&offset);
                success = true;
              } else if (byte_size == sizeof(double)) {
                value.GetScalar() = (double)data.GetDouble(&offset);
                success = true;
              }
            }
          }
        }
      }
    }

    if (success)
      return_valobj_sp = ValueObjectConstResult::Create(
          thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
  } else if (type_flags & eTypeIsPointer) {
    unsigned r3_id =
        reg_ctx->GetRegisterInfoByName("r3", 0)->kinds[eRegisterKindLLDB];
    value.GetScalar() =
        (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r3_id, 0);
    value.SetValueType(Value::eValueTypeScalar);
    return_valobj_sp = ValueObjectConstResult::Create(
        thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
  } else if (type_flags & eTypeIsVector) {
    const size_t byte_size = return_compiler_type.GetByteSize(nullptr);
    if (byte_size > 0) {
      const RegisterInfo *altivec_reg = reg_ctx->GetRegisterInfoByName("v2", 0);
      if (altivec_reg) {
        if (byte_size <= altivec_reg->byte_size) {
          ProcessSP process_sp(thread.GetProcess());
          if (process_sp) {
            std::unique_ptr<DataBufferHeap> heap_data_ap(
                new DataBufferHeap(byte_size, 0));
            const ByteOrder byte_order = process_sp->GetByteOrder();
            RegisterValue reg_value;
            if (reg_ctx->ReadRegister(altivec_reg, reg_value)) {
              Status error;
              if (reg_value.GetAsMemoryData(
                      altivec_reg, heap_data_ap->GetBytes(),
                      heap_data_ap->GetByteSize(), byte_order, error)) {
                DataExtractor data(DataBufferSP(heap_data_ap.release()),
                                   byte_order, process_sp->GetTarget()
                                                   .GetArchitecture()
                                                   .GetAddressByteSize());
                return_valobj_sp = ValueObjectConstResult::Create(
                    &thread, return_compiler_type, ConstString(""), data);
              }
            }
          }
        }
      }
    }
  }

  return return_valobj_sp;
}
Exemplo n.º 13
0
bool
lldb_private::InferiorCallMunmap (Process *process,
                                  addr_t addr,
                                  addr_t length)
{
    Thread *thread = process->GetThreadList().GetSelectedThread().get();
    if (thread == NULL)
        return false;

    const bool append = true;
    const bool include_symbols = true;
    const bool include_inlines = false;
    SymbolContextList sc_list;
    const uint32_t count
        = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"),
                eFunctionNameTypeFull,
                include_symbols,
                include_inlines,
                append,
                sc_list);
    if (count > 0)
    {
        SymbolContext sc;
        if (sc_list.GetContextAtIndex(0, sc))
        {
            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
            const bool use_inline_block_range = false;
            EvaluateExpressionOptions options;
            options.SetStopOthers(true);
            options.SetUnwindOnError(true);
            options.SetIgnoreBreakpoints(true);
            options.SetTryAllThreads(true);
            options.SetDebug (false);
            options.SetTimeoutUsec(500000);

            AddressRange munmap_range;
            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
            {
                lldb::addr_t args[] = { addr, length };
                lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
                                                 munmap_range.GetBaseAddress(),
                                                 CompilerType(),
                                                 args,
                                                 options));
                if (call_plan_sp)
                {
                    StreamFile error_strm;
                    // This plan is a utility plan, so set it to discard itself when done.
                    call_plan_sp->SetIsMasterPlan (true);
                    call_plan_sp->SetOkayToDiscard(true);

                    StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
                    if (frame)
                    {
                        ExecutionContext exe_ctx;
                        frame->CalculateExecutionContext (exe_ctx);
                        ExpressionResults result = process->RunThreadPlan (exe_ctx,
                                                   call_plan_sp,
                                                   options,
                                                   error_strm);
                        if (result == eExpressionCompleted)
                        {
                            return true;
                        }
                    }
                }
            }
        }
    }

    return false;
}
Exemplo n.º 14
0
bool
lldb_private::InferiorCall (Process *process,
                            const Address *address,
                            addr_t &returned_func)
{
    Thread *thread = process->GetThreadList().GetSelectedThread().get();
    if (thread == NULL || address == NULL)
        return false;

    EvaluateExpressionOptions options;
    options.SetStopOthers(true);
    options.SetUnwindOnError(true);
    options.SetIgnoreBreakpoints(true);
    options.SetTryAllThreads(true);
    options.SetDebug (false);
    options.SetTimeoutUsec(500000);

    ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
    CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
    lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
                                     *address,
                                     clang_void_ptr_type,
                                     llvm::ArrayRef<addr_t>(),
                                     options));
    if (call_plan_sp)
    {
        StreamString error_strm;
        // This plan is a utility plan, so set it to discard itself when done.
        call_plan_sp->SetIsMasterPlan (true);
        call_plan_sp->SetOkayToDiscard(true);

        StackFrame *frame = thread->GetStackFrameAtIndex (0).get();
        if (frame)
        {
            ExecutionContext exe_ctx;
            frame->CalculateExecutionContext (exe_ctx);
            ExpressionResults result = process->RunThreadPlan (exe_ctx,
                                       call_plan_sp,
                                       options,
                                       error_strm);
            if (result == eExpressionCompleted)
            {
                returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);

                if (process->GetAddressByteSize() == 4)
                {
                    if (returned_func == UINT32_MAX)
                        return false;
                }
                else if (process->GetAddressByteSize() == 8)
                {
                    if (returned_func == UINT64_MAX)
                        return false;
                }
                return true;
            }
        }
    }

    return false;
}
Exemplo n.º 15
0
bool lldb_private::InferiorCallMunmap(Process *process, addr_t addr,
                                      addr_t length) {
   Thread *thread = process->GetThreadList().GetSelectedThread().get();
   if (thread == NULL)
       return false;
   
   const bool append = true;
   const bool include_symbols = true;
   const bool include_inlines = false;
   SymbolContextList sc_list;
   const uint32_t count
     = process->GetTarget().GetImages().FindFunctions (ConstString ("munmap"), 
                                                       eFunctionNameTypeFull,
                                                       include_symbols, 
                                                       include_inlines,
                                                       append, 
                                                       sc_list);
   if (count > 0)
   {
       SymbolContext sc;
       if (sc_list.GetContextAtIndex(0, sc))
       {
           const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
           const bool use_inline_block_range = false;
           const bool stop_other_threads = true;
           const bool unwind_on_error = true;
           const bool ignore_breakpoints = true;
           const bool try_all_threads = true;
           const uint32_t timeout_usec = 500000;
           
           AddressRange munmap_range;
           if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range))
           {
               lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread,
                                                                            munmap_range.GetBaseAddress(),
                                                                            ClangASTType(),
                                                                            stop_other_threads,
                                                                            unwind_on_error,
                                                                            ignore_breakpoints,
                                                                            &addr,
                                                                            &length));
               if (call_plan_sp)
               {
                   StreamFile error_strm;
                   // This plan is a utility plan, so set it to discard itself when done.
                   call_plan_sp->SetIsMasterPlan (true);
                   call_plan_sp->SetOkayToDiscard(true);
                   
                   Frame *frame = thread->GetStackFrameAtIndex (0).get();
                   if (frame)
                   {
                       ExecutionContext exe_ctx;
                       frame->CalculateExecutionContext (exe_ctx);
                       ExecutionResults result = process->RunThreadPlan (exe_ctx,
                                                                         call_plan_sp,        
                                                                         stop_other_threads,
                                                                         try_all_threads,
                                                                         unwind_on_error,
                                                                         ignore_breakpoints,
                                                                         timeout_usec,
                                                                         error_strm);
                       if (result == eExecutionCompleted)
                       {
                           return true;
                       }
                   }
               }
           }
       }
   }

   return false;
}
Exemplo n.º 16
0
SBError
SBThread::StepOverUntil (lldb::SBFrame &sb_frame, 
                         lldb::SBFileSpec &sb_file_spec, 
                         uint32_t line)
{
    SBError sb_error;
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API));
    char path[PATH_MAX];
    
    Mutex::Locker api_locker;
    ExecutionContext exe_ctx (m_opaque_sp.get(), api_locker);

    StackFrameSP frame_sp (sb_frame.GetFrameSP());

    if (log)
    {
        SBStream frame_desc_strm;
        sb_frame.GetDescription (frame_desc_strm);
        sb_file_spec->GetPath (path, sizeof(path));
        log->Printf ("SBThread(%p)::StepOverUntil (frame = SBFrame(%p): %s, file+line = %s:%u)", 
                     exe_ctx.GetThreadPtr(), 
                     frame_sp.get(), 
                     frame_desc_strm.GetData(),
                     path, line);
    }

    if (exe_ctx.HasThreadScope())
    {
        Target *target = exe_ctx.GetTargetPtr();
        Thread *thread = exe_ctx.GetThreadPtr();

        if (line == 0)
        {
            sb_error.SetErrorString("invalid line argument");
            return sb_error;
        }
        
        if (!frame_sp)
        {
            frame_sp = thread->GetSelectedFrame ();
            if (!frame_sp)
                frame_sp = thread->GetStackFrameAtIndex (0);
        }
    
        SymbolContext frame_sc;
        if (!frame_sp)        
        {
            sb_error.SetErrorString("no valid frames in thread to step");
            return sb_error;
        }

        // If we have a frame, get its line
        frame_sc = frame_sp->GetSymbolContext (eSymbolContextCompUnit  |
                                               eSymbolContextFunction  | 
                                               eSymbolContextLineEntry | 
                                               eSymbolContextSymbol    );
                                               
        if (frame_sc.comp_unit == NULL)
        {
            sb_error.SetErrorStringWithFormat("frame %u doesn't have debug information", frame_sp->GetFrameIndex());
            return sb_error;
        }
        
        FileSpec step_file_spec;
        if (sb_file_spec.IsValid())
        {
            // The file spec passed in was valid, so use it
            step_file_spec = sb_file_spec.ref();
        }
        else
        {
            if (frame_sc.line_entry.IsValid())
                step_file_spec = frame_sc.line_entry.file;
            else
            {
                sb_error.SetErrorString("invalid file argument or no file for frame");
                return sb_error;
            }
        }
    
        // Grab the current function, then we will make sure the "until" address is
        // within the function.  We discard addresses that are out of the current
        // function, and then if there are no addresses remaining, give an appropriate
        // error message.
        
        bool all_in_function = true;
        AddressRange fun_range = frame_sc.function->GetAddressRange();
        
        std::vector<addr_t> step_over_until_addrs;
        const bool abort_other_plans = false;
        const bool stop_other_threads = false;
        const bool check_inlines = true;
        const bool exact = false;

        SymbolContextList sc_list;
        const uint32_t num_matches = frame_sc.comp_unit->ResolveSymbolContext (step_file_spec, 
                                                                               line, 
                                                                               check_inlines, 
                                                                               exact, 
                                                                               eSymbolContextLineEntry, 
                                                                               sc_list);
        if (num_matches > 0)
        {
            SymbolContext sc;
            for (uint32_t i=0; i<num_matches; ++i)
            {
                if (sc_list.GetContextAtIndex(i, sc))
                {
                    addr_t step_addr = sc.line_entry.range.GetBaseAddress().GetLoadAddress(target);
                    if (step_addr != LLDB_INVALID_ADDRESS)
                    {
                        if (fun_range.ContainsLoadAddress(step_addr, target))
                            step_over_until_addrs.push_back(step_addr);
                        else
                            all_in_function = false;
                    }
                }
            }
        }
        
        if (step_over_until_addrs.empty())
        {
            if (all_in_function)
            {
                step_file_spec.GetPath (path, sizeof(path));
                sb_error.SetErrorStringWithFormat("No line entries for %s:%u", path, line);
            }
            else
                sb_error.SetErrorString ("step until target not in current function");
        }
        else
        {
            ThreadPlanSP new_plan_sp(thread->QueueThreadPlanForStepUntil (abort_other_plans,
                                                                        &step_over_until_addrs[0],
                                                                        step_over_until_addrs.size(),
                                                                        stop_other_threads,
                                                                        frame_sp->GetFrameIndex()));

            sb_error = ResumeNewPlan (exe_ctx, new_plan_sp.get());
        }
    }
    else
    {
        sb_error.SetErrorString("this SBThread object is invalid");
    }
    return sb_error;
}
Exemplo n.º 17
0
ValueObjectSP
ABISysV_mips64::GetReturnValueObjectImpl (Thread &thread, ClangASTType &return_clang_type) const
{
    ValueObjectSP return_valobj_sp;
    Value value;

    ExecutionContext exe_ctx (thread.shared_from_this());
    if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
        return return_valobj_sp;

    value.SetClangType(return_clang_type);

    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return return_valobj_sp;

    const size_t byte_size = return_clang_type.GetByteSize(nullptr);
    const uint32_t type_flags = return_clang_type.GetTypeInfo (NULL);

    if (type_flags & eTypeIsScalar)
    {
        value.SetValueType(Value::eValueTypeScalar);

        bool success = false;
        if (type_flags & eTypeIsInteger)
        {
            // Extract the register context so we can read arguments from registers
            // In MIPS register "r2" (v0) holds the integer function return values

            uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);

            const bool is_signed = (type_flags & eTypeIsSigned) != 0;
            switch (byte_size)
            {
                default:
                    break;

                case sizeof(uint64_t):
                    if (is_signed)
                        value.GetScalar() = (int64_t)(raw_value);
                    else
                        value.GetScalar() = (uint64_t)(raw_value);
                    success = true;
                    break;

                case sizeof(uint32_t):
                    if (is_signed)
                        value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
                    else
                        value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
                    success = true;
                    break;

                case sizeof(uint16_t):
                    if (is_signed)
                        value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
                    else
                        value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
                    success = true;
                    break;

                case sizeof(uint8_t):
                    if (is_signed)
                        value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
                    else
                        value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
                    success = true;
                    break;
            }
        }

        if (success)
        return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
                                                           value,
                                                           ConstString(""));
    }
    else if (type_flags & eTypeIsPointer)
    {
        value.SetValueType(Value::eValueTypeScalar);
        uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
        value.GetScalar() = (uint64_t)(raw_value);

        return_valobj_sp = ValueObjectConstResult::Create (thread.GetStackFrameAtIndex(0).get(),
                                                           value,
                                                           ConstString(""));
    }
    else if (type_flags & eTypeIsVector)
    {
        // TODO: Handle vector types
    }
    return return_valobj_sp;
}
Exemplo n.º 18
0
ValueObjectSP
ABISysV_mips::GetReturnValueObjectImpl (Thread &thread, CompilerType &return_clang_type) const
{
    ValueObjectSP return_valobj_sp;
    Value value;

    if (!return_clang_type)
        return return_valobj_sp;

    ExecutionContext exe_ctx (thread.shared_from_this());
    if (exe_ctx.GetTargetPtr() == NULL || exe_ctx.GetProcessPtr() == NULL)
        return return_valobj_sp;

    value.SetCompilerType(return_clang_type);

    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return return_valobj_sp;
    
    bool is_signed = false;
    bool is_complex = false;
    uint32_t count = 0;

    // In MIPS register "r2" (v0) holds the integer function return values
    const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
    size_t bit_width = return_clang_type.GetBitSize(&thread);
    
    if (return_clang_type.IsIntegerType (is_signed))
    {
        switch (bit_width)
        {
            default:
                return return_valobj_sp;
            case 64:
            {
                const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
                uint64_t raw_value;
                raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
                raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) & UINT32_MAX)) << 32;
                if (is_signed)
                    value.GetScalar() = (int64_t)raw_value;
                else
                    value.GetScalar() = (uint64_t)raw_value;
            }
                break;
            case 32:
                if (is_signed)
                    value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
                else
                    value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
                break;
            case 16:
                if (is_signed)
                    value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
                else
                    value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
                break;
            case 8:
                if (is_signed)
                    value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
                else
                    value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
                break;
        }
    }
    else if (return_clang_type.IsPointerType ())
    {
        uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
        value.GetScalar() = ptr;
    }
    else if (return_clang_type.IsAggregateType ())
    {
        // Structure/Vector is always passed in memory and pointer to that memory is passed in r2. 
        uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(reg_ctx->GetRegisterInfoByName("r2", 0), 0);
        // We have got the address. Create a memory object out of it
        return_valobj_sp = ValueObjectMemory::Create (&thread,
                                                      "",
                                                      Address (mem_address, NULL),
                                                      return_clang_type);
        return return_valobj_sp;
    }
    else if (return_clang_type.IsFloatingPointType (count, is_complex))
    {
        const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
        const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);

        if (count == 1 && !is_complex)
        {
            switch (bit_width)
            {
                default:
                    return return_valobj_sp;
                case 64:
                {
                    static_assert(sizeof(double) == sizeof(uint64_t), "");
                    uint64_t raw_value;
                    raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
                    raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(f1_info, 0) & UINT32_MAX)) << 32;
                    value.GetScalar() = *reinterpret_cast<double*>(&raw_value);
                    break;
                }
                case 32:
                {
                    static_assert(sizeof(float) == sizeof(uint32_t), "");
                    uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(f0_info, 0) & UINT32_MAX;
                    value.GetScalar() = *reinterpret_cast<float*>(&raw_value);
                    break;
                }
            }
        }
        else
        {
            // not handled yet
            return return_valobj_sp;
        }
    }
    else
    {
        // not handled yet
        return return_valobj_sp;
    }
    
    // If we get here, we have a valid Value, so make our ValueObject out of it:

    return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
                                                      value,
                                                      ConstString(""));
    return return_valobj_sp;
}
Exemplo n.º 19
0
bool lldb_private::InferiorCall(Process *process, const Address *address, addr_t &returned_func) {
    Thread *thread = process->GetThreadList().GetSelectedThread().get();
    if (thread == NULL || address == NULL)
        return false;

    const bool stop_other_threads = true;
    const bool unwind_on_error = true;
    const bool ignore_breakpoints = true;
    const bool try_all_threads = true;
    const uint32_t timeout_usec = 500000;

    ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
    ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
    ThreadPlanCallFunction *call_function_thread_plan
        = new ThreadPlanCallFunction (*thread,
                                      *address,
                                      clang_void_ptr_type,
                                      stop_other_threads,
                                      unwind_on_error,
                                      ignore_breakpoints);
    lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
    if (call_plan_sp)
    {
        StreamFile error_strm;
        // This plan is a utility plan, so set it to discard itself when done.
        call_plan_sp->SetIsMasterPlan (true);
        call_plan_sp->SetOkayToDiscard(true);

        Frame *frame = thread->GetStackFrameAtIndex (0).get();
        if (frame)
        {
            ExecutionContext exe_ctx;
            frame->CalculateExecutionContext (exe_ctx);
            ExecutionResults result = process->RunThreadPlan (exe_ctx,
                                                              call_plan_sp,
                                                              stop_other_threads,
                                                              try_all_threads,
                                                              unwind_on_error,
                                                              ignore_breakpoints,
                                                              timeout_usec,
                                                              error_strm);
            if (result == eExecutionCompleted)
            {
                returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);

                if (process->GetAddressByteSize() == 4)
                {
                    if (returned_func == UINT32_MAX)
                        return false;
                }
                else if (process->GetAddressByteSize() == 8)
                {
                    if (returned_func == UINT64_MAX)
                        return false;
                }
                return true;
            }
        }
    }

    return false;
}
Exemplo n.º 20
0
ValueObjectSP
ABISysV_arm::GetReturnValueObjectImpl (Thread &thread,
                                       lldb_private::CompilerType &compiler_type) const
{
    Value value;
    ValueObjectSP return_valobj_sp;
    
    if (!compiler_type)
        return return_valobj_sp;
    
    //value.SetContext (Value::eContextTypeClangType, compiler_type.GetOpaqueQualType());
    value.SetCompilerType (compiler_type);
            
    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return return_valobj_sp;
        
    bool is_signed;
    bool is_complex;
    uint32_t float_count;
    
    // Get the pointer to the first stack argument so we have a place to start 
    // when reading data
    
    const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
    size_t bit_width = compiler_type.GetBitSize(&thread);

    if (compiler_type.IsIntegerType (is_signed))
    {       
        switch (bit_width)
        {
            default:
                return return_valobj_sp;
            case 64:
            {
                const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
                uint64_t raw_value;
                raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
                raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32;
                if (is_signed)
                    value.GetScalar() = (int64_t)raw_value;
                else
                    value.GetScalar() = (uint64_t)raw_value;
            }
                break;
            case 32:
                if (is_signed)
                    value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
                else
                    value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
                break;
            case 16:
                if (is_signed)
                    value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
                else
                    value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
                break;
            case 8:
                if (is_signed)
                    value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
                else
                    value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
                break;
        }
    }
    else if (compiler_type.IsPointerType ())
    {
        uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
        value.GetScalar() = ptr;
    }
    else if (compiler_type.IsVectorType(nullptr, nullptr))
    {
        size_t byte_size = compiler_type.GetByteSize(&thread);
        if (byte_size <= 16)
        {
            DataBufferHeap buffer(16, 0);
            uint32_t* buffer_ptr = (uint32_t*)buffer.GetBytes();
            
            for (uint32_t i = 0; 4*i < byte_size; ++i)
            {
                const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1 + i);
                buffer_ptr[i] = reg_ctx->ReadRegisterAsUnsigned(reg_info, 0) & UINT32_MAX;
            }
            value.SetBytes(buffer.GetBytes(), byte_size);
        }
        else
        {
            if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))
                return return_valobj_sp;
        }
    }
    else if (compiler_type.IsFloatingPointType(float_count, is_complex))
    {
        if (float_count == 1 && !is_complex)
        {
            switch (bit_width)
            {
                default:
                    return return_valobj_sp;
                case 64:
                {
                    static_assert(sizeof(double) == sizeof(uint64_t), "");
                    const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG2);
                    uint64_t raw_value;
                    raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
                    raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32;
                    value.GetScalar() = *reinterpret_cast<double*>(&raw_value);
                    break;
                }
                case 16: // Half precision returned after a conversion to single precision
                case 32:
                {
                    static_assert(sizeof(float) == sizeof(uint32_t), "");
                    uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
                    value.GetScalar() = *reinterpret_cast<float*>(&raw_value);
                    break;
                }
            }
        }
        else
        {
            // not handled yet
            return return_valobj_sp;
        }
    }
    else if (compiler_type.IsAggregateType())
    {
        size_t byte_size = compiler_type.GetByteSize(&thread);
        if (byte_size <= 4)
        {
            RegisterValue r0_reg_value;
            uint32_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
            value.SetBytes(&raw_value, byte_size);
        }
        else
        {
            if (!GetReturnValuePassedInMemory(thread, reg_ctx, byte_size, value))
                return return_valobj_sp;
        }
    }
    else
    {
        // not handled yet
        return return_valobj_sp;
    }
    
    // If we get here, we have a valid Value, so make our ValueObject out of it:
    
    return_valobj_sp = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
                                                      value,
                                                      ConstString(""));
    return return_valobj_sp;
}
Exemplo n.º 21
0
bool lldb_private::InferiorCallMmap(Process *process, addr_t &allocated_addr,
                                    addr_t addr, addr_t length, unsigned prot,
                                    unsigned flags, addr_t fd, addr_t offset) {
    Thread *thread = process->GetThreadList().GetSelectedThread().get();
    if (thread == NULL)
        return false;

    const bool append = true;
    const bool include_symbols = true;
    const bool include_inlines = false;
    SymbolContextList sc_list;
    const uint32_t count
      = process->GetTarget().GetImages().FindFunctions (ConstString ("mmap"), 
                                                        eFunctionNameTypeFull,
                                                        include_symbols,
                                                        include_inlines,
                                                        append, 
                                                        sc_list);
    if (count > 0)
    {
        SymbolContext sc;
        if (sc_list.GetContextAtIndex(0, sc))
        {
            const uint32_t range_scope = eSymbolContextFunction | eSymbolContextSymbol;
            const bool use_inline_block_range = false;
            const bool stop_other_threads = true;
            const bool unwind_on_error = true;
            const bool ignore_breakpoints = true;
            const bool try_all_threads = true;
            const uint32_t timeout_usec = 500000;

            addr_t prot_arg, flags_arg = 0;
            if (prot == eMmapProtNone)
              prot_arg = PROT_NONE;
            else {
              prot_arg = 0;
              if (prot & eMmapProtExec)
                prot_arg |= PROT_EXEC;
              if (prot & eMmapProtRead)
                prot_arg |= PROT_READ;
              if (prot & eMmapProtWrite)
                prot_arg |= PROT_WRITE;
            }

            if (flags & eMmapFlagsPrivate)
              flags_arg |= MAP_PRIVATE;
            if (flags & eMmapFlagsAnon)
              flags_arg |= MAP_ANON;

            AddressRange mmap_range;
            if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, mmap_range))
            {
                ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
                ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
                ThreadPlanCallFunction *call_function_thread_plan
                  = new ThreadPlanCallFunction (*thread,
                                                mmap_range.GetBaseAddress(),
                                                clang_void_ptr_type,
                                                stop_other_threads,
                                                unwind_on_error,
                                                ignore_breakpoints,
                                                &addr,
                                                &length,
                                                &prot_arg,
                                                &flags_arg,
                                                &fd,
                                                &offset);
                lldb::ThreadPlanSP call_plan_sp (call_function_thread_plan);
                if (call_plan_sp)
                {
                    StreamFile error_strm;
                    // This plan is a utility plan, so set it to discard itself when done.
                    call_plan_sp->SetIsMasterPlan (true);
                    call_plan_sp->SetOkayToDiscard(true);
                    
                    Frame *frame = thread->GetStackFrameAtIndex (0).get();
                    if (frame)
                    {
                        ExecutionContext exe_ctx;
                        frame->CalculateExecutionContext (exe_ctx);
                        ExecutionResults result = process->RunThreadPlan (exe_ctx,
                                                                          call_plan_sp,        
                                                                          stop_other_threads,
                                                                          try_all_threads,
                                                                          unwind_on_error,
                                                                          ignore_breakpoints,
                                                                          timeout_usec,
                                                                          error_strm);
                        if (result == eExecutionCompleted)
                        {
                            
                            allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS);
                            if (process->GetAddressByteSize() == 4)
                            {
                                if (allocated_addr == UINT32_MAX)
                                    return false;
                            }
                            else if (process->GetAddressByteSize() == 8)
                            {
                                if (allocated_addr == UINT64_MAX)
                                    return false;
                            }
                            return true;
                        }
                    }
                }
            }
        }
    }

    return false;
}
Exemplo n.º 22
0
ValueObjectSP
ABIMacOSX_arm::GetReturnValueObjectImpl (Thread &thread,
        lldb_private::ClangASTType &ast_type) const
{
    Value value;
    ValueObjectSP return_valobj_sp;

    void *value_type = ast_type.GetOpaqueQualType();
    if (!value_type)
        return return_valobj_sp;

    clang::ASTContext *ast_context = ast_type.GetASTContext();
    if (!ast_context)
        return return_valobj_sp;

    value.SetContext (Value::eContextTypeClangType, value_type);

    RegisterContext *reg_ctx = thread.GetRegisterContext().get();
    if (!reg_ctx)
        return return_valobj_sp;

    bool is_signed;

    // Get the pointer to the first stack argument so we have a place to start
    // when reading data

    const RegisterInfo *r0_reg_info = reg_ctx->GetRegisterInfoByName("r0", 0);
    if (ClangASTContext::IsIntegerType (value_type, is_signed))
    {
        size_t bit_width = ClangASTType::GetClangTypeBitWidth(ast_context, value_type);

        switch (bit_width)
        {
        default:
            return return_valobj_sp;
        case 64:
        {
            const RegisterInfo *r1_reg_info = reg_ctx->GetRegisterInfoByName("r1", 0);
            uint64_t raw_value;
            raw_value = reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
            raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r1_reg_info, 0) & UINT32_MAX)) << 32;
            if (is_signed)
                value.GetScalar() = (int64_t)raw_value;
            else
                value.GetScalar() = (uint64_t)raw_value;
        }
        break;
        case 32:
            if (is_signed)
                value.GetScalar() = (int32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
            else
                value.GetScalar() = (uint32_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX);
            break;
        case 16:
            if (is_signed)
                value.GetScalar() = (int16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
            else
                value.GetScalar() = (uint16_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT16_MAX);
            break;
        case 8:
            if (is_signed)
                value.GetScalar() = (int8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
            else
                value.GetScalar() = (uint8_t)(reg_ctx->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT8_MAX);
            break;
        }
    }
    else if (ClangASTContext::IsPointerType (value_type))
    {
        uint32_t ptr = thread.GetRegisterContext()->ReadRegisterAsUnsigned(r0_reg_info, 0) & UINT32_MAX;
        value.GetScalar() = ptr;
    }
    else
    {
        // not handled yet
        return return_valobj_sp;
    }

    // If we get here, we have a valid Value, so make our ValueObject out of it:

    return_valobj_sp = ValueObjectConstResult::Create(
                           thread.GetStackFrameAtIndex(0).get(),
                           ast_type.GetASTContext(),
                           value,
                           ConstString(""));
    return return_valobj_sp;
}
Exemplo n.º 23
0
ValueObjectSP ABISysV_s390x::GetReturnValueObjectSimple(
    Thread &thread, CompilerType &return_compiler_type) const {
  ValueObjectSP return_valobj_sp;
  Value value;

  if (!return_compiler_type)
    return return_valobj_sp;

  // value.SetContext (Value::eContextTypeClangType, return_value_type);
  value.SetCompilerType(return_compiler_type);

  RegisterContext *reg_ctx = thread.GetRegisterContext().get();
  if (!reg_ctx)
    return return_valobj_sp;

  const uint32_t type_flags = return_compiler_type.GetTypeInfo();
  if (type_flags & eTypeIsScalar) {
    value.SetValueType(Value::eValueTypeScalar);

    bool success = false;
    if (type_flags & eTypeIsInteger) {
      // Extract the register context so we can read arguments from registers.
      llvm::Optional<uint64_t> byte_size =
          return_compiler_type.GetByteSize(nullptr);
      if (!byte_size)
        return return_valobj_sp;
      uint64_t raw_value = thread.GetRegisterContext()->ReadRegisterAsUnsigned(
          reg_ctx->GetRegisterInfoByName("r2", 0), 0);
      const bool is_signed = (type_flags & eTypeIsSigned) != 0;
      switch (*byte_size) {
      default:
        break;

      case sizeof(uint64_t):
        if (is_signed)
          value.GetScalar() = (int64_t)(raw_value);
        else
          value.GetScalar() = (uint64_t)(raw_value);
        success = true;
        break;

      case sizeof(uint32_t):
        if (is_signed)
          value.GetScalar() = (int32_t)(raw_value & UINT32_MAX);
        else
          value.GetScalar() = (uint32_t)(raw_value & UINT32_MAX);
        success = true;
        break;

      case sizeof(uint16_t):
        if (is_signed)
          value.GetScalar() = (int16_t)(raw_value & UINT16_MAX);
        else
          value.GetScalar() = (uint16_t)(raw_value & UINT16_MAX);
        success = true;
        break;

      case sizeof(uint8_t):
        if (is_signed)
          value.GetScalar() = (int8_t)(raw_value & UINT8_MAX);
        else
          value.GetScalar() = (uint8_t)(raw_value & UINT8_MAX);
        success = true;
        break;
      }
    } else if (type_flags & eTypeIsFloat) {
      if (type_flags & eTypeIsComplex) {
        // Don't handle complex yet.
      } else {
        llvm::Optional<uint64_t> byte_size =
            return_compiler_type.GetByteSize(nullptr);
        if (byte_size && *byte_size <= sizeof(long double)) {
          const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
          RegisterValue f0_value;
          if (reg_ctx->ReadRegister(f0_info, f0_value)) {
            DataExtractor data;
            if (f0_value.GetData(data)) {
              lldb::offset_t offset = 0;
              if (*byte_size == sizeof(float)) {
                value.GetScalar() = (float)data.GetFloat(&offset);
                success = true;
              } else if (*byte_size == sizeof(double)) {
                value.GetScalar() = (double)data.GetDouble(&offset);
                success = true;
              } else if (*byte_size == sizeof(long double)) {
                // Don't handle long double yet.
              }
            }
          }
        }
      }
    }

    if (success)
      return_valobj_sp = ValueObjectConstResult::Create(
          thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
  } else if (type_flags & eTypeIsPointer) {
    unsigned r2_id =
        reg_ctx->GetRegisterInfoByName("r2", 0)->kinds[eRegisterKindLLDB];
    value.GetScalar() =
        (uint64_t)thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_id, 0);
    value.SetValueType(Value::eValueTypeScalar);
    return_valobj_sp = ValueObjectConstResult::Create(
        thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
  }

  return return_valobj_sp;
}