Beispiel #1
0
bool
CompilerType::ReadFromMemory (lldb_private::ExecutionContext *exe_ctx,
                              lldb::addr_t addr,
                              AddressType address_type,
                              lldb_private::DataExtractor &data)
{
    if (!IsValid())
        return false;
    
    // Can't convert a file address to anything valid without more
    // context (which Module it came from)
    if (address_type == eAddressTypeFile)
        return false;
    
    if (!GetCompleteType())
        return false;
    
    const uint64_t byte_size = GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL);
    if (data.GetByteSize() < byte_size)
    {
        lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0'));
        data.SetData(data_sp);
    }
    
    uint8_t* dst = const_cast<uint8_t*>(data.PeekData(0, byte_size));
    if (dst != nullptr)
    {
        if (address_type == eAddressTypeHost)
        {
            if (addr == 0)
                return false;
            // The address is an address in this process, so just copy it
            memcpy (dst, (uint8_t*)nullptr + addr, byte_size);
            return true;
        }
        else
        {
            Process *process = nullptr;
            if (exe_ctx)
                process = exe_ctx->GetProcessPtr();
            if (process)
            {
                Error error;
                return process->ReadMemory(addr, dst, byte_size, error) == byte_size;
            }
        }
    }
    return false;
}
Beispiel #2
0
Error
Value::GetValueAsData (ExecutionContext *exe_ctx,
                       DataExtractor &data,
                       uint32_t data_offset,
                       Module *module)
{
    data.Clear();

    Error error;
    lldb::addr_t address = LLDB_INVALID_ADDRESS;
    AddressType address_type = eAddressTypeFile;
    Address file_so_addr;
    const CompilerType &ast_type = GetCompilerType();
    switch (m_value_type)
    {
    case eValueTypeVector:
        if (ast_type.IsValid())
            data.SetAddressByteSize (ast_type.GetPointerByteSize());
        else
            data.SetAddressByteSize(sizeof(void *));
        data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order);
        break;

    case eValueTypeScalar:
        {
            data.SetByteOrder (endian::InlHostByteOrder());
            if (ast_type.IsValid())
                data.SetAddressByteSize (ast_type.GetPointerByteSize());
            else
                data.SetAddressByteSize(sizeof(void *));

            uint32_t limit_byte_size = UINT32_MAX;
            
            if (ast_type.IsValid() && ast_type.IsScalarType())
            {
                uint64_t type_encoding_count = 0;
                lldb::Encoding type_encoding = ast_type.GetEncoding(type_encoding_count);
                
                if (type_encoding == eEncodingUint || type_encoding == eEncodingSint)
                    limit_byte_size = ast_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr);
            }
            
            if (m_value.GetData (data, limit_byte_size))
                return error;   // Success;
            
            error.SetErrorStringWithFormat("extracting data from value failed");
            break;
        }
    case eValueTypeLoadAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read load address (no execution context)");
        }
        else 
        {
            Process *process = exe_ctx->GetProcessPtr();
            if (process == NULL || !process->IsAlive())
            {
                Target *target = exe_ctx->GetTargetPtr();
                if (target)
                {
                    // Allow expressions to run and evaluate things when the target
                    // has memory sections loaded. This allows you to use "target modules load"
                    // to load your executable and any shared libraries, then execute
                    // commands where you can look at types in data sections.
                    const SectionLoadList &target_sections = target->GetSectionLoadList();
                    if (!target_sections.IsEmpty())
                    {
                        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
                        if (target_sections.ResolveLoadAddress(address, file_so_addr))
                        {
                            address_type = eAddressTypeLoad;
                            data.SetByteOrder(target->GetArchitecture().GetByteOrder());
                            data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
                        }
                        else
                            address = LLDB_INVALID_ADDRESS;
                    }
//                    else
//                    {
//                        ModuleSP exe_module_sp (target->GetExecutableModule());
//                        if (exe_module_sp)
//                        {
//                            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
//                            if (address != LLDB_INVALID_ADDRESS)
//                            {
//                                if (exe_module_sp->ResolveFileAddress(address, file_so_addr))
//                                {
//                                    data.SetByteOrder(target->GetArchitecture().GetByteOrder());
//                                    data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
//                                    address_type = eAddressTypeFile;
//                                }
//                                else
//                                {
//                                    address = LLDB_INVALID_ADDRESS;
//                                }
//                            }
//                        }
//                    }
                }
                else
                {
                    error.SetErrorString ("can't read load address (invalid process)");
                }
            }
            else
            {
                address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
                address_type = eAddressTypeLoad;
                data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize());
            }
        }
        break;

    case eValueTypeFileAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read file address (no execution context)");
        }
        else if (exe_ctx->GetTargetPtr() == NULL)
        {
            error.SetErrorString ("can't read file address (invalid target)");
        }
        else
        {
            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
            if (address == LLDB_INVALID_ADDRESS)
            {
                error.SetErrorString ("invalid file address");
            }
            else
            {
                if (module == NULL)
                {
                    // The only thing we can currently lock down to a module so that
                    // we can resolve a file address, is a variable.
                    Variable *variable = GetVariable();
                    if (variable)
                    {
                        SymbolContext var_sc;
                        variable->CalculateSymbolContext(&var_sc);
                        module = var_sc.module_sp.get();
                    }
                }
                
                if (module)
                {
                    bool resolved = false;
                    ObjectFile *objfile = module->GetObjectFile();
                    if (objfile)
                    {
                        Address so_addr(address, objfile->GetSectionList());
                        addr_t load_address = so_addr.GetLoadAddress (exe_ctx->GetTargetPtr());
                        bool process_launched_and_stopped = exe_ctx->GetProcessPtr()
                            ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), true /* must_exist */)
                            : false;
                        // Don't use the load address if the process has exited.
                        if (load_address != LLDB_INVALID_ADDRESS && process_launched_and_stopped)
                        {
                            resolved = true;
                            address = load_address;
                            address_type = eAddressTypeLoad;
                            data.SetByteOrder(exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder());
                            data.SetAddressByteSize(exe_ctx->GetTargetRef().GetArchitecture().GetAddressByteSize());
                        }
                        else
                        {
                            if (so_addr.IsSectionOffset())
                            {
                                resolved = true;
                                file_so_addr = so_addr;
                                data.SetByteOrder(objfile->GetByteOrder());
                                data.SetAddressByteSize(objfile->GetAddressByteSize());
                            }
                        }
                    }
                    if (!resolved)
                    {
                        Variable *variable = GetVariable();
                        
                        if (module)
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s' in %s",
                                                                address, 
                                                                variable->GetName().AsCString(""),
                                                                module->GetFileSpec().GetPath().c_str());
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " in %s",
                                                                address, 
                                                                module->GetFileSpec().GetPath().c_str());
                        }
                        else
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s'",
                                                                address, 
                                                                variable->GetName().AsCString(""));
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64, address);
                        }
                    }
                }
                else
                {
                    // Can't convert a file address to anything valid without more
                    // context (which Module it came from)
                    error.SetErrorString ("can't read memory from file address without more context");
                }
            }
        }
        break;

    case eValueTypeHostAddress:
        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
        address_type = eAddressTypeHost;
        if (exe_ctx)
        {
            Target *target = exe_ctx->GetTargetPtr();
            if (target)
            {
                data.SetByteOrder(target->GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
                break;
            }
        }
        // fallback to host settings
        data.SetByteOrder(endian::InlHostByteOrder());
        data.SetAddressByteSize(sizeof(void *));
        break;
    }

    // Bail if we encountered any errors
    if (error.Fail())
        return error;

    if (address == LLDB_INVALID_ADDRESS)
    {
        error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load");
        return error;
    }

    // If we got here, we need to read the value from memory
    size_t byte_size = GetValueByteSize (&error, exe_ctx);

    // Bail if we encountered any errors getting the byte size
    if (error.Fail())
        return error;

    // Make sure we have enough room within "data", and if we don't make
    // something large enough that does
    if (!data.ValidOffsetForDataOfSize (data_offset, byte_size))
    {
        DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0'));
        data.SetData(data_sp);
    }

    uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size));
    if (dst != NULL)
    {
        if (address_type == eAddressTypeHost)
        {
            // The address is an address in this process, so just copy it.
            if (address == 0)
            {
                error.SetErrorStringWithFormat("trying to read from host address of 0.");
                return error;
            }
            memcpy (dst, (uint8_t*)NULL + address, byte_size);
        }
        else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile))
        {
            if (file_so_addr.IsValid())
            {
                // We have a file address that we were able to translate into a
                // section offset address so we might be able to read this from
                // the object files if we don't have a live process. Lets always
                // try and read from the process if we have one though since we
                // want to read the actual value by setting "prefer_file_cache"
                // to false. 
                const bool prefer_file_cache = false;
                if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size)
                {
                    error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed", (uint64_t)address);
                }
            }
            else
            {
                // The execution context might have a NULL process, but it
                // might have a valid process in the exe_ctx->target, so use
                // the ExecutionContext::GetProcess accessor to ensure we
                // get the process if there is one.
                Process *process = exe_ctx->GetProcessPtr();

                if (process)
                {
                    const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error);
                    if (bytes_read != byte_size)
                        error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (%u of %u bytes read)",
                                                       (uint64_t)address, 
                                                       (uint32_t)bytes_read, 
                                                       (uint32_t)byte_size);
                }
                else
                {
                    error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (invalid process)", (uint64_t)address);
                }
            }
        }
        else
        {
            error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type);
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("out of memory");
    }

    return error;
}
Error
IRExecutionUnit::DisassembleFunction (Stream &stream,
                                      lldb::ProcessSP &process_wp)
{
    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));

    ExecutionContext exe_ctx(process_wp);

    Error ret;

    ret.Clear();

    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;

    for (JittedFunction &function : m_jitted_functions)
    {
        if (strstr(function.m_name.c_str(), m_name.AsCString()))
        {
            func_local_addr = function.m_local_addr;
            func_remote_addr = function.m_remote_addr;
        }
    }

    if (func_local_addr == LLDB_INVALID_ADDRESS)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString());
        return ret;
    }

    if (log)
        log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr);

    std::pair <lldb::addr_t, lldb::addr_t> func_range;

    func_range = GetRemoteRangeForLocal(func_local_addr);

    if (func_range.first == 0 && func_range.second == 0)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString());
        return ret;
    }

    if (log)
        log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);

    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the target");
        return ret;
    }

    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));

    Process *process = exe_ctx.GetProcessPtr();
    Error err;
    process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);

    if (!err.Success())
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
        return ret;
    }

    ArchSpec arch(target->GetArchitecture());

    const char *plugin_name = NULL;
    const char *flavor_string = NULL;
    lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name);

    if (!disassembler_sp)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
        return ret;
    }

    if (!process)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the process");
        return ret;
    }

    DataExtractor extractor(buffer_sp,
                            process->GetByteOrder(),
                            target->GetArchitecture().GetAddressByteSize());

    if (log)
    {
        log->Printf("Function data has contents:");
        extractor.PutToLog (log,
                            0,
                            extractor.GetByteSize(),
                            func_remote_addr,
                            16,
                            DataExtractor::TypeUInt8);
    }

    disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);

    InstructionList &instruction_list = disassembler_sp->GetInstructionList();
    const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
    const char *disassemble_format = "${addr-file-or-load}: ";
    if (exe_ctx.HasTargetScope())
    {
        disassemble_format = exe_ctx.GetTargetRef().GetDebugger().GetDisassemblyFormat();
    }

    for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize();
         instruction_index < num_instructions;
         ++instruction_index)
    {
        Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
        instruction->Dump (&stream,
                           max_opcode_byte_size,
                           true,
                           true,
                           &exe_ctx,
                           NULL,
                           NULL,
                           disassemble_format);
        stream.PutChar('\n');
    }
    // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
    // I'll fix that but for now, just clear the list and it will go away nicely.
    disassembler_sp->GetInstructionList().Clear();
    return ret;
}
Beispiel #4
0
void
AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded()
{
    // TODO: implement HashTableSignature...
    Process *process = GetProcess();
    
    if (process)
    {
        // Update the process stop ID that indicates the last time we updated the
        // map, whether it was successful or not.
        m_isa_to_descriptor_stop_id = process->GetStopID();
        
        Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS));
        
        ProcessSP process_sp = process->shared_from_this();
        
        ModuleSP objc_module_sp(GetObjCModule());
        
        if (!objc_module_sp)
            return;
        
        uint32_t isa_count = 0;
        
        lldb::addr_t hash_table_ptr = GetISAHashTablePointer ();
        if (hash_table_ptr != LLDB_INVALID_ADDRESS)
        {
            // Read the NXHashTable struct:
            //
            // typedef struct {
            //     const NXHashTablePrototype *prototype;
            //     unsigned   count;
            //     unsigned   nbBuckets;
            //     void       *buckets;
            //     const void *info;
            // } NXHashTable;

            Error error;
            DataBufferHeap buffer(1024, 0);
            if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) == 20)
            {
                const uint32_t addr_size = m_process->GetAddressByteSize();
                const ByteOrder byte_order = m_process->GetByteOrder();
                DataExtractor data (buffer.GetBytes(), buffer.GetByteSize(), byte_order, addr_size);
                lldb::offset_t offset = addr_size; // Skip prototype
                const uint32_t count = data.GetU32(&offset);
                const uint32_t num_buckets = data.GetU32(&offset);
                const addr_t buckets_ptr = data.GetPointer(&offset);
                if (m_hash_signature.NeedsUpdate (count, num_buckets, buckets_ptr))
                {
                    m_hash_signature.UpdateSignature (count, num_buckets, buckets_ptr);

                    const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t);
                    buffer.SetByteSize(data_size);
                    
                    if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size, error) == data_size)
                    {
                        data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order);
                        offset = 0;
                        for (uint32_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx)
                        {
                            const uint32_t bucket_isa_count = data.GetU32 (&offset);
                            const lldb::addr_t bucket_data = data.GetU32 (&offset);
                            

                            if (bucket_isa_count == 0)
                                continue;
                            
                            isa_count += bucket_isa_count;

                            ObjCISA isa;
                            if (bucket_isa_count == 1)
                            {
                                // When we only have one entry in the bucket, the bucket data is the "isa"
                                isa = bucket_data;
                                if (isa)
                                {
                                    if (!ISAIsCached(isa))
                                    {
                                        ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
                                        
                                        if (log && log->GetVerbose())
                                            log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
                                        
                                        AddClass (isa, descriptor_sp);
                                    }
                                }
                            }
                            else
                            {
                                // When we have more than one entry in the bucket, the bucket data is a pointer
                                // to an array of "isa" values
                                addr_t isa_addr = bucket_data;
                                for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count; ++isa_idx, isa_addr += addr_size)
                                {
                                    isa = m_process->ReadPointerFromMemory(isa_addr, error);

                                    if (isa && isa != LLDB_INVALID_ADDRESS)
                                    {
                                        if (!ISAIsCached(isa))
                                        {
                                            ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp));
                                            
                                            if (log && log->GetVerbose())
                                                log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa);
                                            
                                            AddClass (isa, descriptor_sp);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }        
    }
    else
    {
        m_isa_to_descriptor_stop_id = UINT32_MAX;
    }
}
size_t
UnwindMacOSXFrameBackchain::GetStackFrameData_i386 (const ExecutionContext &exe_ctx)
{
    m_cursors.clear();
    
    Frame *first_frame = exe_ctx.GetFramePtr();

    Process *process = exe_ctx.GetProcessPtr();
    if (process == NULL)
        return 0;
    
    std::pair<lldb::addr_t, lldb::addr_t> fp_pc_pair;

    struct Frame_i386
    {
        uint32_t fp;
        uint32_t pc;
    };

    RegisterContext *reg_ctx = m_thread.GetRegisterContext().get();
    assert (reg_ctx);

    Cursor cursor;
    cursor.pc = reg_ctx->GetPC (LLDB_INVALID_ADDRESS);
    cursor.fp = reg_ctx->GetFP (0);
    
    Frame_i386 frame = { static_cast<uint32_t>(cursor.fp), static_cast<uint32_t>(cursor.pc) };

    m_cursors.push_back(cursor);

    const size_t k_frame_size = sizeof(frame);
    Error error;
    while (frame.fp != 0 && frame.pc != 0 && ((frame.fp & 7) == 0))
    {
        // Read both the FP and PC (8 bytes)
        if (process->ReadMemory (frame.fp, &frame.fp, k_frame_size, error) != k_frame_size)
            break;
        if (frame.pc >= 0x1000)
        {
            cursor.pc = frame.pc;
            cursor.fp = frame.fp;
            m_cursors.push_back (cursor);
        }
    }
    if (!m_cursors.empty())
    {
        lldb::addr_t first_frame_pc = m_cursors.front().pc;
        if (first_frame_pc != LLDB_INVALID_ADDRESS)
        {
            const uint32_t resolve_scope = eSymbolContextModule |
                                           eSymbolContextCompUnit |
                                           eSymbolContextFunction |
                                           eSymbolContextSymbol;

            SymbolContext first_frame_sc (first_frame->GetSymbolContext(resolve_scope));
            const AddressRange *addr_range_ptr = NULL;
            AddressRange range;
            if (first_frame_sc.function)
                addr_range_ptr = &first_frame_sc.function->GetAddressRange();
            else if (first_frame_sc.symbol)
            {
                range.GetBaseAddress() = first_frame_sc.symbol->GetAddress();
                range.SetByteSize (first_frame_sc.symbol->GetByteSize());
                addr_range_ptr = &range;
            }

            if (addr_range_ptr)
            {
                if (first_frame->GetFrameCodeAddress() == addr_range_ptr->GetBaseAddress())
                {
                    // We are at the first instruction, so we can recover the
                    // previous PC by dereferencing the SP
                    lldb::addr_t first_frame_sp = reg_ctx->GetSP (0);
                    // Read the real second frame return address into frame.pc
                    if (first_frame_sp && process->ReadMemory (first_frame_sp, &frame.pc, sizeof(frame.pc), error) == sizeof(frame.pc))
                    {
                        cursor.fp = m_cursors.front().fp;
                        cursor.pc = frame.pc;           // Set the new second frame PC

                        // Insert the second frame
                        m_cursors.insert(m_cursors.begin()+1, cursor);
                        
                        m_cursors.front().fp = first_frame_sp;
                    }
                }
            }
        }
    }
//    uint32_t i=0;
//    printf("      PC                 FP\n");
//    printf("      ------------------ ------------------ \n");
//    for (i=0; i<m_cursors.size(); ++i)
//    {
//        printf("[%3u] 0x%16.16" PRIx64 " 0x%16.16" PRIx64 "\n", i, m_cursors[i].pc, m_cursors[i].fp);
//    }
    return m_cursors.size();
}
Beispiel #6
0
/*
 * long ptrace(enum request, int pid, void* addr, void* data)
 */
void SysCalls::sys_ptrace(CONTEXT& ctx)
{
	int request = ctx.Ebx;
	int pid = ctx.Ecx;
	void* addr = (void*)ctx.Edx;
	void* data = (void*)ctx.Esi;

	Process * pTraced = g_pKernelTable->FindProcess(pid);

	//TODO: what does ptrace on a process with threads actually do?
	ThreadInfo * pTracedThread = pTraced->m_ThreadList[0];

	switch(request)
	{
	case linux::PTRACE_TRACEME:
		ktrace("ptrace PTRACE_TRACEME\n");
		P->m_ptrace.OwnerPid = P->m_ParentPid;
		P->m_ptrace.Request = linux::PTRACE_TRACEME;
		ctx.Eax = 0;
		break;

	case linux::PTRACE_SYSCALL:
		{
			ktrace("ptrace PTRACE_SYSCALL pid %d\n", pid);
			pTraced->m_ptrace.Request = linux::PTRACE_SYSCALL;
			if((int)data!=0 && (int)data!=linux::SIGSTOP)
				pTraced->m_ptrace.new_signal = (int)data;
			ktrace("ptrace_syscall resuming pid %d\n",pid);
			ResumeThread(pTraced->m_KernelThreadHandle); //kernel handler thread is paused when using ptrace
			ctx.Eax = 0;
		}
		break;

	case linux::PTRACE_CONT:
		{
			ktrace("ptrace PTRACE_CONT pid %d\n", pid);
			pTraced->m_ptrace.Request = 0;
			if((int)data!=0 && (int)data!=linux::SIGSTOP)
				pTraced->m_ptrace.new_signal = (int)data;
			ktrace("ptrace_cont resuming pid %d\n",pid);
			ResumeThread(pTraced->m_KernelThreadHandle); //kernel handler thread is paused when using ptrace
			ctx.Eax = 0;
		}
		break;

	case linux::PTRACE_PEEKUSR:
		{
			ktrace("ptrace PTRACE_PEEKUSR pid %d addr 0x%lx (reg %ld) data 0x%08lx\n", pid, addr, (DWORD)addr>>2, data);

			if((unsigned long)addr > sizeof(linux::user)-3)
			{
				ctx.Eax = -linux::EFAULT;
				break;
			}

			//read data at offset 'addr' in the kernel 'user' struct (struct user in asm/user.h)
			//we don't keep one of those so make one here
			CONTEXT *pTracedCtx;
			CONTEXT TempCtx;
			if(pTraced->m_ptrace.ctx_valid)
				pTracedCtx = &pTraced->m_ptrace.ctx; 
			else
			{
				ktrace("peekusr get Traced context\n");
				//it's possible that the traced process has caught a signal and then
				//signalled us, however it's kernel thread has yet to sleep
				//so we do an extra suspend here to get the correct context
				SuspendThread(pTracedThread->hThread);
				TempCtx.ContextFlags = CONTEXT_FULL;
				GetThreadContext(pTracedThread->hThread, &TempCtx);
				ResumeThread(pTracedThread->hThread);
				pTracedCtx = &TempCtx;
			}

			linux::user usr;
			memset(&usr,0,sizeof(usr));
			usr.regs.eax  = pTracedCtx->Eax;
			usr.regs.ebx  = pTracedCtx->Ebx;
			usr.regs.ecx  = pTracedCtx->Ecx;
			usr.regs.edx  = pTracedCtx->Edx;
			usr.regs.esi  = pTracedCtx->Esi;
			usr.regs.edi  = pTracedCtx->Edi;
			usr.regs.ebp  = pTracedCtx->Ebp;
			usr.regs.ds   = (unsigned short)pTracedCtx->SegDs;
			usr.regs.__ds = 0;
			usr.regs.es   = (unsigned short)pTracedCtx->SegEs;
			usr.regs.__es = 0;
			usr.regs.fs   = (unsigned short)pTracedCtx->SegFs;
			usr.regs.__fs = 0;
			usr.regs.gs   = (unsigned short)pTracedCtx->SegGs;
			usr.regs.__gs = 0;
			usr.regs.cs   = (unsigned short)pTracedCtx->SegCs;
			usr.regs.__cs = 0;
			usr.regs.ss   = (unsigned short)pTracedCtx->SegSs;
			usr.regs.__ss = 0;
			usr.regs.orig_eax = pTraced->m_ptrace.Saved_Eax;
			usr.regs.eip  = pTracedCtx->Eip;
			usr.regs.eflags = pTracedCtx->EFlags;
			usr.regs.esp  = pTracedCtx->Esp;
			//usr.signal = SIGTRAP; //man ptrace says parent thinks Traced is in this state

			char * pWanted = ((char*)&usr) + (DWORD)addr;
			DWORD retdata = *((DWORD*)pWanted);
			P->WriteMemory((ADDR)data, sizeof(retdata), &retdata);

			ktrace("ptrace [0x%x]=0x%x eax=0x%x orig_eax=0x%x\n", addr, retdata, usr.regs.eax, usr.regs.orig_eax);

			ctx.Eax = 0;
		}
		break;

	case linux::PTRACE_PEEKTEXT:
	case linux::PTRACE_PEEKDATA:
		{
			ktrace("ptrace PTRACE_PEEKDATA pid %d addr 0x%lx data 0x%08lx\n", pid, addr, data);
			DWORD tmp;
			if(!pTraced->ReadMemory(&tmp, (ADDR)addr, sizeof(tmp)))
			{
				ctx.Eax = -linux::EFAULT;
			}
			else
			{
				P->WriteMemory((ADDR)data, sizeof(tmp), &tmp);
				ctx.Eax = tmp;
				ktrace("ptrace [0x%x]=0x%x\n", addr, tmp);
			}
		}
		break;

	case linux::PTRACE_KILL:
		ktrace("ptrace PTRACE_KILL pid %d \n", pid);
		pTraced->SendSignal(linux::SIGKILL);
		ResumeThread(pTraced->m_KernelThreadHandle); //need to wake kernel handler thread so it can die
		ctx.Eax = 0;
		break;

	default:
		ktrace("IMPLEMENT ptrace request %lx\n", ctx.Ebx);
		ctx.Eax = -linux::ENOSYS;
		break;
	}
}
bool
ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, 
                                                     lldb::DynamicValueType use_dynamic, 
                                                     TypeAndOrName &class_type_or_name, 
                                                     Address &dynamic_address)
{
    // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
    // in the object.  That will point to the "address point" within the vtable (not the beginning of the
    // vtable.)  We can then look up the symbol containing this "address point" and that symbol's name 
    // demangled will contain the full class name.
    // The second pointer above the "address point" is the "offset_to_top".  We'll use that to get the
    // start of the value object which holds the dynamic type.
    //
    
    class_type_or_name.Clear();
    
    // Only a pointer or reference type can have a different dynamic and static type:
    if (CouldHaveDynamicValue (in_value))
    {
        // First job, pull out the address at 0 offset from the object.
        AddressType address_type;
        lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
        if (original_ptr == LLDB_INVALID_ADDRESS)
            return false;
        
        ExecutionContext exe_ctx (in_value.GetExecutionContextRef());

        Target *target = exe_ctx.GetTargetPtr();
        Process *process = exe_ctx.GetProcessPtr();

        char memory_buffer[16];
        DataExtractor data(memory_buffer, sizeof(memory_buffer), 
                           process->GetByteOrder(), 
                           process->GetAddressByteSize());
        size_t address_byte_size = process->GetAddressByteSize();
        Error error;
        size_t bytes_read = process->ReadMemory (original_ptr, 
                                                 memory_buffer, 
                                                 address_byte_size, 
                                                 error);
        if (!error.Success() || (bytes_read != address_byte_size))
        {
            return false;
        }
        
        lldb::offset_t offset = 0;
        lldb::addr_t vtable_address_point = data.GetAddress (&offset);
            
        if (offset == 0)
            return false;
        
        // Now find the symbol that contains this address:
        
        SymbolContext sc;
        Address address_point_address;
        if (target && !target->GetSectionLoadList().IsEmpty())
        {
            if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
            {
                target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
                Symbol *symbol = sc.symbol;
                if (symbol != NULL)
                {
                    const char *name = symbol->GetMangled().GetDemangledName().AsCString();
                    if (strstr(name, vtable_demangled_prefix) == name)
                    {
                        Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_OBJECT));
                        if (log)
                            log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has vtable symbol '%s'\n",
                                         original_ptr,
                                         in_value.GetTypeName().GetCString(),
                                         name);
                        // We are a C++ class, that's good.  Get the class name and look it up:
                        const char *class_name = name + strlen(vtable_demangled_prefix);
                        class_type_or_name.SetName (class_name);
                        const bool exact_match = true;
                        TypeList class_types;
                        
                        uint32_t num_matches = 0;
                        // First look in the module that the vtable symbol came from
                        // and look for a single exact match.
                        if (sc.module_sp)
                        {
                            num_matches = sc.module_sp->FindTypes (sc,
                                                                   ConstString(class_name),
                                                                   exact_match,
                                                                   1,
                                                                   class_types);
                        }
                        
                        // If we didn't find a symbol, then move on to the entire
                        // module list in the target and get as many unique matches
                        // as possible
                        if (num_matches == 0)
                        {
                            num_matches = target->GetImages().FindTypes (sc,
                                                                         ConstString(class_name),
                                                                         exact_match,
                                                                         UINT32_MAX,
                                                                         class_types);
                        }
                        
                        lldb::TypeSP type_sp;
                        if (num_matches == 0)
                        {
                            if (log)
                                log->Printf("0x%16.16" PRIx64 ": is not dynamic\n", original_ptr);
                            return false;
                        }
                        if (num_matches == 1)
                        {
                            type_sp = class_types.GetTypeAtIndex(0);
                            if (log)
                                log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has dynamic type: uid={0x%" PRIx64 "}, type-name='%s'\n",
                                             original_ptr,
                                             in_value.GetTypeName().AsCString(),
                                             type_sp->GetID(),
                                             type_sp->GetName().GetCString());

                            class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
                        }
                        else if (num_matches > 1)
                        {
                            size_t i;
                            if (log)
                            {
                                for (i = 0; i < num_matches; i++)
                                {
                                    type_sp = class_types.GetTypeAtIndex(i);
                                    if (type_sp)
                                    {
                                        if (log)
                                            log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types: uid={0x%" PRIx64 "}, type-name='%s'\n",
                                                         original_ptr,
                                                         in_value.GetTypeName().AsCString(),
                                                         type_sp->GetID(),
                                                         type_sp->GetName().GetCString());
                                    }
                                }
                            }

                            for (i = 0; i < num_matches; i++)
                            {
                                type_sp = class_types.GetTypeAtIndex(i);
                                if (type_sp)
                                {
                                    if (type_sp->GetClangFullType().IsCXXClassType())
                                    {
                                        if (log)
                                            log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, picking this one: uid={0x%" PRIx64 "}, type-name='%s'\n",
                                                         original_ptr,
                                                         in_value.GetTypeName().AsCString(),
                                                         type_sp->GetID(),
                                                         type_sp->GetName().GetCString());
                                        class_type_or_name.SetTypeSP(type_sp);
                                        break;
                                    }
                                }
                            }
                            
                            if (i == num_matches)
                            {
                                if (log)
                                    log->Printf ("0x%16.16" PRIx64 ": static-type = '%s' has multiple matching dynamic types, didn't find a C++ match\n",
                                                 original_ptr,
                                                 in_value.GetTypeName().AsCString());
                                return false;
                            }
                        }

                        // There can only be one type with a given name,
                        // so we've just found duplicate definitions, and this
                        // one will do as well as any other.
                        // We don't consider something to have a dynamic type if
                        // it is the same as the static type.  So compare against
                        // the value we were handed.
                        if (type_sp)
                        {
                            if (ClangASTContext::AreTypesSame (in_value.GetClangType(),
                                                               type_sp->GetClangFullType()))
                            {
                                // The dynamic type we found was the same type,
                                // so we don't have a dynamic type here...
                                return false;
                            }

                            // The offset_to_top is two pointers above the address.
                            Address offset_to_top_address = address_point_address;
                            int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
                            offset_to_top_address.Slide (slide);
                            
                            Error error;
                            lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
                            
                            size_t bytes_read = process->ReadMemory (offset_to_top_location, 
                                                                     memory_buffer, 
                                                                     address_byte_size, 
                                                                     error);
                                                                     
                            if (!error.Success() || (bytes_read != address_byte_size))
                            {
                                return false;
                            }
                            
                            offset = 0;
                            int64_t offset_to_top = data.GetMaxS64(&offset, process->GetAddressByteSize());
                            
                            // So the dynamic type is a value that starts at offset_to_top
                            // above the original address.
                            lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
                            if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
                            {
                                dynamic_address.SetRawAddress(dynamic_addr);
                            }
                            return true;
                        }
                    }
                }
            }
        }
    }
    
    return class_type_or_name.IsEmpty() == false;
}
Beispiel #8
0
    virtual bool
    Execute (Args& command,
             CommandReturnObject &result)
    {
        Process *process = m_interpreter.GetDebugger().GetExecutionContext().process;
        if (process == NULL)
        {
            result.AppendError("need a process to read memory");
            result.SetStatus(eReturnStatusFailed);
            return false;
        }
        const size_t argc = command.GetArgumentCount();

        if (argc == 0 || argc > 2)
        {
            result.AppendErrorWithFormat ("%s takes 1 or two args.\n", m_cmd_name.c_str());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        size_t item_byte_size = m_options.m_byte_size;
        if (item_byte_size == 0)
        {
            if (m_options.m_format == eFormatPointer)
                item_byte_size = process->GetTarget().GetArchitecture().GetAddressByteSize();
            else
                item_byte_size = 1;
        }

        size_t item_count = m_options.m_count;

        size_t num_per_line = m_options.m_num_per_line;
        if (num_per_line == 0)
        {
            num_per_line = (16/item_byte_size);
            if (num_per_line == 0)
                num_per_line = 1;
        }

        size_t total_byte_size = m_options.m_count * item_byte_size;
        if (total_byte_size == 0)
            total_byte_size = 32;

        lldb::addr_t addr = Args::StringToUInt64(command.GetArgumentAtIndex(0), LLDB_INVALID_ADDRESS, 0);

        if (addr == LLDB_INVALID_ADDRESS)
        {
            result.AppendErrorWithFormat("invalid start address string '%s'.\n", command.GetArgumentAtIndex(0));
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (argc == 2)
        {
            lldb::addr_t end_addr = Args::StringToUInt64(command.GetArgumentAtIndex(1), LLDB_INVALID_ADDRESS, 0);
            if (end_addr == LLDB_INVALID_ADDRESS)
            {
                result.AppendErrorWithFormat("Invalid end address string '%s'.\n", command.GetArgumentAtIndex(1));
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (end_addr <= addr)
            {
                result.AppendErrorWithFormat("End address (0x%llx) must be greater that the start address (0x%llx).\n", end_addr, addr);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
            else if (item_count != 0)
            {
                result.AppendErrorWithFormat("Specify either the end address (0x%llx) or the count (--count %u), not both.\n", end_addr, item_count);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }

            total_byte_size = end_addr - addr;
            item_count = total_byte_size / item_byte_size;
        }
        else
        {
            if (item_count == 0)
                item_count = 32;
        }

        DataBufferSP data_sp(new DataBufferHeap (total_byte_size, '\0'));
        Error error;
        size_t bytes_read = process->ReadMemory(addr, data_sp->GetBytes (), data_sp->GetByteSize(), error);
        if (bytes_read == 0)
        {
            result.AppendWarningWithFormat("Read from 0x%llx failed.\n", addr);
            result.AppendError(error.AsCString());
            result.SetStatus(eReturnStatusFailed);
            return false;
        }

        if (bytes_read < total_byte_size)
            result.AppendWarningWithFormat("Not all bytes (%u/%u) were able to be read from 0x%llx.\n", bytes_read, total_byte_size, addr);

        result.SetStatus(eReturnStatusSuccessFinishResult);
        DataExtractor data (data_sp, 
                            process->GetTarget().GetArchitecture().GetByteOrder(), 
                            process->GetTarget().GetArchitecture().GetAddressByteSize());

        StreamFile outfile_stream;
        Stream *output_stream = NULL;

        if (m_options.m_outfile_filespec)
        {
            char path[PATH_MAX];
            m_options.m_outfile_filespec.GetPath (path, sizeof(path));
            char mode[16] = { 'w', '\0' };
            if (m_options.m_append_to_outfile)
                mode[0] = 'a';
                
            if (outfile_stream.GetFile ().Open (path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
            {
                if (m_options.m_output_as_binary)
                {
                    int bytes_written = outfile_stream.Write (data_sp->GetBytes(), bytes_read);
                    if (bytes_written > 0)
                    {
                        result.GetOutputStream().Printf ("%i bytes %s to '%s'\n", 
                                                         bytes_written, 
                                                         m_options.m_append_to_outfile ? "appended" : "written", 
                                                         path);
                        return true;
                    }
                    else 
                    {
                        result.AppendErrorWithFormat("Failed to write %zu bytes to '%s'.\n", bytes_read, path);
                        result.SetStatus(eReturnStatusFailed);
                        return false;
                    }
                }
                else
                {
                    // We are going to write ASCII to the file just point the
                    // output_stream to our outfile_stream...
                    output_stream = &outfile_stream;
                }
            }
            else 
            {
                result.AppendErrorWithFormat("Failed to open file '%s' with a mode of '%s'.\n", path, mode);
                result.SetStatus(eReturnStatusFailed);
                return false;
            }
        }
        else 
        {
            output_stream = &result.GetOutputStream();
        }

        assert (output_stream);
        data.Dump (output_stream,
                   0,
                   m_options.m_format,
                   item_byte_size,
                   item_count,
                   num_per_line,
                   addr,
                   0,
                   0);
        output_stream->EOL();
        return true;
    }
Beispiel #9
0
Error
Value::GetValueAsData (ExecutionContext *exe_ctx, 
                       clang::ASTContext *ast_context, 
                       DataExtractor &data, 
                       uint32_t data_offset,
                       Module *module)
{
    data.Clear();

    Error error;
    lldb::addr_t address = LLDB_INVALID_ADDRESS;
    AddressType address_type = eAddressTypeFile;
    Address file_so_addr;
    switch (m_value_type)
    {
    default:
        error.SetErrorStringWithFormat("invalid value type %i", m_value_type);
        break;

    case eValueTypeScalar:
        data.SetByteOrder (lldb::endian::InlHostByteOrder());
        if (m_context_type == eContextTypeClangType && ast_context)
        {
            uint32_t ptr_bit_width = ClangASTType::GetClangTypeBitWidth (ast_context, 
                                                                     ClangASTContext::GetVoidPtrType(ast_context, false));
            uint32_t ptr_byte_size = (ptr_bit_width + 7) / 8;
            data.SetAddressByteSize (ptr_byte_size);
        }
        else
            data.SetAddressByteSize(sizeof(void *));
        if (m_value.GetData (data))
            return error;   // Success;
        error.SetErrorStringWithFormat("extracting data from value failed");
        break;

    case eValueTypeLoadAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read load address (no execution context)");
        }
        else 
        {
            Process *process = exe_ctx->GetProcessPtr();
            if (process == NULL)
            {
                error.SetErrorString ("can't read load address (invalid process)");
            }
            else
            {
                address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
                address_type = eAddressTypeLoad;
                data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize());
            }
        }
        break;

    case eValueTypeFileAddress:
        if (exe_ctx == NULL)
        {
            error.SetErrorString ("can't read file address (no execution context)");
        }
        else if (exe_ctx->GetTargetPtr() == NULL)
        {
            error.SetErrorString ("can't read file address (invalid target)");
        }
        else
        {
            address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
            if (address == LLDB_INVALID_ADDRESS)
            {
                error.SetErrorString ("invalid file address");
            }
            else
            {
                if (module == NULL)
                {
                    // The only thing we can currently lock down to a module so that
                    // we can resolve a file address, is a variable.
                    Variable *variable = GetVariable();
                    if (variable)
                    {
                        SymbolContext var_sc;
                        variable->CalculateSymbolContext(&var_sc);
                        module = var_sc.module_sp.get();
                    }
                }
                
                if (module)
                {
                    bool resolved = false;
                    ObjectFile *objfile = module->GetObjectFile();
                    if (objfile)
                    {
                        Address so_addr(address, objfile->GetSectionList());
                        addr_t load_address = so_addr.GetLoadAddress (exe_ctx->GetTargetPtr());
                        bool process_launched_and_stopped = exe_ctx->GetProcessPtr()
                            ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), true /* must_exist */)
                            : false;
                        // Don't use the load address if the process has exited.
                        if (load_address != LLDB_INVALID_ADDRESS && process_launched_and_stopped)
                        {
                            resolved = true;
                            address = load_address;
                            address_type = eAddressTypeLoad;
                            data.SetByteOrder(exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder());
                            data.SetAddressByteSize(exe_ctx->GetTargetRef().GetArchitecture().GetAddressByteSize());
                        }
                        else
                        {
                            if (so_addr.IsSectionOffset())
                            {
                                resolved = true;
                                file_so_addr = so_addr;
                                data.SetByteOrder(objfile->GetByteOrder());
                                data.SetAddressByteSize(objfile->GetAddressByteSize());
                            }
                        }
                    }
                    if (!resolved)
                    {
                        Variable *variable = GetVariable();
                        
                        if (module)
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s' in %s%s%s", 
                                                                address, 
                                                                variable->GetName().AsCString(""),
                                                                module->GetFileSpec().GetDirectory().GetCString(),
                                                                module->GetFileSpec().GetDirectory() ? "/" : "",
                                                                module->GetFileSpec().GetFilename().GetCString());
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx in %s%s%s", 
                                                                address, 
                                                                module->GetFileSpec().GetDirectory().GetCString(),
                                                                module->GetFileSpec().GetDirectory() ? "/" : "",
                                                                module->GetFileSpec().GetFilename().GetCString());
                        }
                        else
                        {
                            if (variable)
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", 
                                                                address, 
                                                                variable->GetName().AsCString(""));
                            else
                                error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx", address);
                        }
                    }
                }
                else
                {
                    // Can't convert a file address to anything valid without more
                    // context (which Module it came from)
                    error.SetErrorString ("can't read memory from file address without more context");
                }
            }
        }
        break;

    case eValueTypeHostAddress:
        address = m_value.ULongLong(LLDB_INVALID_ADDRESS);
        address_type = eAddressTypeHost;
        if (exe_ctx)
        {
            Target *target = exe_ctx->GetTargetPtr();
            if (target)
            {
                data.SetByteOrder(target->GetArchitecture().GetByteOrder());
                data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
                break;
            }
        }
        // fallback to host settings
        data.SetByteOrder(lldb::endian::InlHostByteOrder());
        data.SetAddressByteSize(sizeof(void *));
        break;
    }

    // Bail if we encountered any errors
    if (error.Fail())
        return error;

    if (address == LLDB_INVALID_ADDRESS)
    {
        error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load");
        return error;
    }

    // If we got here, we need to read the value from memory
    uint32_t byte_size = GetValueByteSize (ast_context, &error);

    // Bail if we encountered any errors getting the byte size
    if (error.Fail())
        return error;

    // Make sure we have enough room within "data", and if we don't make
    // something large enough that does
    if (!data.ValidOffsetForDataOfSize (data_offset, byte_size))
    {
        DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0'));
        data.SetData(data_sp);
    }

    uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size));
    if (dst != NULL)
    {
        if (address_type == eAddressTypeHost)
        {
            // The address is an address in this process, so just copy it
            memcpy (dst, (uint8_t*)NULL + address, byte_size);
        }
        else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile))
        {
            if (file_so_addr.IsValid())
            {
                // We have a file address that we were able to translate into a
                // section offset address so we might be able to read this from
                // the object files if we don't have a live process. Lets always
                // try and read from the process if we have one though since we
                // want to read the actual value by setting "prefer_file_cache"
                // to false. 
                const bool prefer_file_cache = false;
                if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size)
                {
                    error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address);
                }
            }
            else
            {
                // The execution context might have a NULL process, but it
                // might have a valid process in the exe_ctx->target, so use
                // the ExecutionContext::GetProcess accessor to ensure we
                // get the process if there is one.
                Process *process = exe_ctx->GetProcessPtr();

                if (process)
                {
                    const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error);
                    if (bytes_read != byte_size)
                        error.SetErrorStringWithFormat("read memory from 0x%llx failed (%u of %u bytes read)", 
                                                       (uint64_t)address, 
                                                       (uint32_t)bytes_read, 
                                                       (uint32_t)byte_size);
                }
                else
                {
                    error.SetErrorStringWithFormat("read memory from 0x%llx failed (invalid process)", (uint64_t)address);                    
                }
            }
        }
        else
        {
            error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type);
        }
    }
    else
    {
        error.SetErrorStringWithFormat ("out of memory");
    }

    return error;
}
bool
ItaniumABILanguageRuntime::GetDynamicTypeAndAddress (ValueObject &in_value, 
                                                     lldb::DynamicValueType use_dynamic, 
                                                     TypeAndOrName &class_type_or_name, 
                                                     Address &dynamic_address)
{
    // For Itanium, if the type has a vtable pointer in the object, it will be at offset 0
    // in the object.  That will point to the "address point" within the vtable (not the beginning of the
    // vtable.)  We can then look up the symbol containing this "address point" and that symbol's name 
    // demangled will contain the full class name.
    // The second pointer above the "address point" is the "offset_to_top".  We'll use that to get the
    // start of the value object which holds the dynamic type.
    //
    
    // Only a pointer or reference type can have a different dynamic and static type:
    if (CouldHaveDynamicValue (in_value))
    {
        // FIXME: Can we get the Clang Type and ask it if the thing is really virtual?  That would avoid false positives,
        // at the cost of not looking for the dynamic type of objects if DWARF->Clang gets it wrong.
        
        // First job, pull out the address at 0 offset from the object.
        AddressType address_type;
        lldb::addr_t original_ptr = in_value.GetPointerValue(&address_type);
        if (original_ptr == LLDB_INVALID_ADDRESS)
            return false;
            
        Target *target = in_value.GetUpdatePoint().GetTargetSP().get();
        Process *process = in_value.GetUpdatePoint().GetProcessSP().get();

        char memory_buffer[16];
        DataExtractor data(memory_buffer, sizeof(memory_buffer), 
                           process->GetByteOrder(), 
                           process->GetAddressByteSize());
        size_t address_byte_size = process->GetAddressByteSize();
        Error error;
        size_t bytes_read = process->ReadMemory (original_ptr, 
                                                 memory_buffer, 
                                                 address_byte_size, 
                                                 error);
        if (!error.Success() || (bytes_read != address_byte_size))
        {
            return false;
        }
        
        uint32_t offset_ptr = 0;
        lldb::addr_t vtable_address_point = data.GetAddress (&offset_ptr);
            
        if (offset_ptr == 0)
            return false;
        
        // Now find the symbol that contains this address:
        
        SymbolContext sc;
        Address address_point_address;
        if (target && !target->GetSectionLoadList().IsEmpty())
        {
            if (target->GetSectionLoadList().ResolveLoadAddress (vtable_address_point, address_point_address))
            {
                target->GetImages().ResolveSymbolContextForAddress (address_point_address, eSymbolContextSymbol, sc);
                Symbol *symbol = sc.symbol;
                if (symbol != NULL)
                {
                    const char *name = symbol->GetMangled().GetDemangledName().AsCString();
                    if (strstr(name, vtable_demangled_prefix) == name)
                    {
                         // We are a C++ class, that's good.  Get the class name and look it up:
                        const char *class_name = name + strlen(vtable_demangled_prefix);
                        class_type_or_name.SetName (class_name);
                        TypeList class_types;
                        uint32_t num_matches = target->GetImages().FindTypes (sc, 
                                                                              ConstString(class_name),
                                                                              true,
                                                                              UINT32_MAX,
                                                                              class_types);
                        if (num_matches == 1)
                        {
                            class_type_or_name.SetTypeSP(class_types.GetTypeAtIndex(0));
                        }
                        else if (num_matches > 1)
                        {
                            for (size_t i = 0; i < num_matches; i++)
                            {
                                lldb::TypeSP this_type(class_types.GetTypeAtIndex(i));
                                if (this_type)
                                {
                                    if (ClangASTContext::IsCXXClassType(this_type->GetClangFullType()))
                                    {
                                        // There can only be one type with a given name,
                                        // so we've just found duplicate definitions, and this
                                        // one will do as well as any other.
                                        // We don't consider something to have a dynamic type if
                                        // it is the same as the static type.  So compare against
                                        // the value we were handed:
                                        
                                        clang::ASTContext *in_ast_ctx = in_value.GetClangAST ();
                                        clang::ASTContext *this_ast_ctx = this_type->GetClangAST ();
                                        if (in_ast_ctx != this_ast_ctx
                                            || !ClangASTContext::AreTypesSame (in_ast_ctx, 
                                                                               in_value.GetClangType(),
                                                                               this_type->GetClangFullType()))
                                        {
                                            class_type_or_name.SetTypeSP (this_type);
                                            return true;
                                        }
                                        return false;
                                    }
                                }
                            }
                        }
                        else
                            return false;
                            
                        // The offset_to_top is two pointers above the address.
                        Address offset_to_top_address = address_point_address;
                        int64_t slide = -2 * ((int64_t) target->GetArchitecture().GetAddressByteSize());
                        offset_to_top_address.Slide (slide);
                        
                        Error error;
                        lldb::addr_t offset_to_top_location = offset_to_top_address.GetLoadAddress(target);
                        
                        size_t bytes_read = process->ReadMemory (offset_to_top_location, 
                                                                 memory_buffer, 
                                                                 address_byte_size, 
                                                                 error);
                                                                 
                        if (!error.Success() || (bytes_read != address_byte_size))
                        {
                            return false;
                        }
                        
                        offset_ptr = 0;
                        int64_t offset_to_top = data.GetMaxS64(&offset_ptr, process->GetAddressByteSize());
                        
                        // So the dynamic type is a value that starts at offset_to_top
                        // above the original address.
                        lldb::addr_t dynamic_addr = original_ptr + offset_to_top;
                        if (!target->GetSectionLoadList().ResolveLoadAddress (dynamic_addr, dynamic_address))
                        {
                            dynamic_address.SetOffset(dynamic_addr);
                            dynamic_address.SetSection(NULL);
                        }
                        return true;
                    }
                }
            }
        }
        
    }
    
    return false;
}
Beispiel #11
0
Error
ClangExpressionParser::DisassembleFunction (Stream &stream, ExecutionContext &exe_ctx, RecordingMemoryManager *jit_memory_manager)
{
    lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
    
    const char *name = m_expr.FunctionName();
    
    Error ret;
    
    ret.Clear();
    
    lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
    lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
    
    std::vector<JittedFunction>::iterator pos, end = m_jitted_functions.end();
    
    for (pos = m_jitted_functions.begin(); pos < end; pos++)
    {
        if (strstr(pos->m_name.c_str(), name))
        {
            func_local_addr = pos->m_local_addr;
            func_remote_addr = pos->m_remote_addr;
        }
    }
    
    if (func_local_addr == LLDB_INVALID_ADDRESS)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", name);
        return ret;
    }
    
    if (log)
        log->Printf("Found function, has local address 0x%llx and remote address 0x%llx", (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
    
    std::pair <lldb::addr_t, lldb::addr_t> func_range;
    
    func_range = jit_memory_manager->GetRemoteRangeForLocal(func_local_addr);
    
    if (func_range.first == 0 && func_range.second == 0)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't find code range for function %s", name);
        return ret;
    }
    
    if (log)
        log->Printf("Function's code range is [0x%llx+0x%llx]", func_range.first, func_range.second);
    
    Target *target = exe_ctx.GetTargetPtr();
    if (!target)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the target");
    }
    
    lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
    
    Process *process = exe_ctx.GetProcessPtr();
    Error err;
    process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
    
    if (!err.Success())
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
        return ret;
    }
    
    ArchSpec arch(target->GetArchitecture());
    
    Disassembler *disassembler = Disassembler::FindPlugin(arch, NULL);
    
    if (disassembler == NULL)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
        return ret;
    }
    
    if (!process)
    {
        ret.SetErrorToGenericError();
        ret.SetErrorString("Couldn't find the process");
        return ret;
    }
    
    DataExtractor extractor(buffer_sp, 
                            process->GetByteOrder(),
                            target->GetArchitecture().GetAddressByteSize());
    
    if (log)
    {
        log->Printf("Function data has contents:");
        extractor.PutToLog (log.get(),
                            0,
                            extractor.GetByteSize(),
                            func_remote_addr,
                            16,
                            DataExtractor::TypeUInt8);
    }
    
    disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false);
    
    InstructionList &instruction_list = disassembler->GetInstructionList();
    const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
    for (uint32_t instruction_index = 0, num_instructions = instruction_list.GetSize(); 
         instruction_index < num_instructions; 
         ++instruction_index)
    {
        Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
        instruction->Dump (&stream,
                           max_opcode_byte_size,
                           true,
                           true,
                           &exe_ctx);
        stream.PutChar('\n');
    }
    
    return ret;
}
Beispiel #12
0
const char *
ValueObject::GetSummaryAsCString (ExecutionContextScope *exe_scope)
{
    if (UpdateValueIfNeeded (exe_scope))
    {
        if (m_summary_str.empty())
        {
            void *clang_type = GetOpaqueClangQualType();

            // See if this is a pointer to a C string?
            uint32_t fixed_length = 0;
            if (clang_type && ClangASTContext::IsCStringType (clang_type, fixed_length))
            {
                Process *process = exe_scope->CalculateProcess();
                if (process != NULL)
                {
                    StreamString sstr;
                    lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS;
                    lldb::AddressType cstr_address_type = eAddressTypeInvalid;
                    switch (GetValue().GetValueType())
                    {
                    case Value::eValueTypeScalar:
                        cstr_address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS);
                        cstr_address_type = eAddressTypeLoad;
                        break;

                    case Value::eValueTypeLoadAddress:
                    case Value::eValueTypeFileAddress:
                    case Value::eValueTypeHostAddress:
                        {
                            uint32_t data_offset = 0;
                            cstr_address = m_data.GetPointer(&data_offset);
                            cstr_address_type = m_value.GetValueAddressType();
                            if (cstr_address_type == eAddressTypeInvalid)
                                cstr_address_type = eAddressTypeLoad;
                        }
                        break;
                    }

                    if (cstr_address != LLDB_INVALID_ADDRESS)
                    {
                        DataExtractor data;
                        size_t bytes_read = 0;
                        std::vector<char> data_buffer;
                        std::vector<char> cstr_buffer;
                        size_t cstr_length;
                        Error error;
                        if (fixed_length > 0)
                        {
                            data_buffer.resize(fixed_length);
                            // Resize the formatted buffer in case every character
                            // uses the "\xXX" format and one extra byte for a NULL
                            cstr_buffer.resize(data_buffer.size() * 4 + 1);
                            data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost);
                            bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), fixed_length, error);
                            if (bytes_read > 0)
                            {
                                sstr << '"';
                                cstr_length = data.Dump (&sstr,
                                                         0,                 // Start offset in "data"
                                                         eFormatChar,       // Print as characters
                                                         1,                 // Size of item (1 byte for a char!)
                                                         bytes_read,        // How many bytes to print?
                                                         UINT32_MAX,        // num per line
                                                         LLDB_INVALID_ADDRESS,// base address
                                                         0,                 // bitfield bit size
                                                         0);                // bitfield bit offset
                                sstr << '"';
                            }
                        }
                        else
                        {
                            const size_t k_max_buf_size = 256;
                            data_buffer.resize (k_max_buf_size + 1);
                            // NULL terminate in case we don't get the entire C string
                            data_buffer.back() = '\0';
                            // Make a formatted buffer that can contain take 4
                            // bytes per character in case each byte uses the
                            // "\xXX" format and one extra byte for a NULL
                            cstr_buffer.resize (k_max_buf_size * 4 + 1);

                            data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost);
                            size_t total_cstr_len = 0;
                            while ((bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), k_max_buf_size, error)) > 0)
                            {
                                size_t len = strlen(data_buffer.data());
                                if (len == 0)
                                    break;
                                if (len > bytes_read)
                                    len = bytes_read;
                                if (sstr.GetSize() == 0)
                                    sstr << '"';

                                cstr_length = data.Dump (&sstr,
                                                         0,                 // Start offset in "data"
                                                         eFormatChar,       // Print as characters
                                                         1,                 // Size of item (1 byte for a char!)
                                                         len,               // How many bytes to print?
                                                         UINT32_MAX,        // num per line
                                                         LLDB_INVALID_ADDRESS,// base address
                                                         0,                 // bitfield bit size
                                                         0);                // bitfield bit offset

                                if (len < k_max_buf_size)
                                    break;
                                cstr_address += total_cstr_len;
                            }
                            if (sstr.GetSize() > 0)
                                sstr << '"';
                        }

                        if (sstr.GetSize() > 0)
                            m_summary_str.assign (sstr.GetData(), sstr.GetSize());
                    }
                }
            }
        }
    }
    if (m_summary_str.empty())
        return NULL;
    return m_summary_str.c_str();
}