コード例 #1
0
void
DynamicLoaderLinuxDYLD::UpdateLoadedSections(ModuleSP module, addr_t base_addr)
{
    ObjectFile *obj_file = module->GetObjectFile();
    SectionList *sections = obj_file->GetSectionList();
    SectionLoadList &load_list = m_process->GetTarget().GetSectionLoadList();
    const size_t num_sections = sections->GetSize();

    for (unsigned i = 0; i < num_sections; ++i)
    {
        Section *section = sections->GetSectionAtIndex(i).get();
        lldb::addr_t new_load_addr = section->GetFileAddress() + base_addr;
        lldb::addr_t old_load_addr = load_list.GetSectionLoadAddress(section);

        // If the file address of the section is zero then this is not an
        // allocatable/loadable section (property of ELF sh_addr).  Skip it.
        if (new_load_addr == base_addr)
            continue;

        if (old_load_addr == LLDB_INVALID_ADDRESS ||
            old_load_addr != new_load_addr)
            load_list.SetSectionLoadAddress(section, new_load_addr);
    }
}
コード例 #2
0
//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
Error
ProcessMachCore::DoLoadCore ()
{
    Error error;
    if (!m_core_module_sp)
    {
        error.SetErrorString ("invalid core module");   
        return error;
    }

    ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
    if (core_objfile == NULL)
    {
        error.SetErrorString ("invalid core object file");   
        return error;
    }
    
    if (core_objfile->GetNumThreadContexts() == 0)
    {
        error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb");
        return error;
    }

    SectionList *section_list = core_objfile->GetSectionList();
    if (section_list == NULL)
    {
        error.SetErrorString ("core file has no sections");   
        return error;
    }
        
    const uint32_t num_sections = section_list->GetNumSections(0);
    if (num_sections == 0)
    {
        error.SetErrorString ("core file has no sections");   
        return error;
    }
    
    SetCanJIT(false);

    llvm::MachO::mach_header header;
    DataExtractor data (&header, 
                        sizeof(header), 
                        m_core_module_sp->GetArchitecture().GetByteOrder(),
                        m_core_module_sp->GetArchitecture().GetAddressByteSize());

    bool ranges_are_sorted = true;
    addr_t vm_addr = 0;
    for (uint32_t i=0; i<num_sections; ++i)
    {
        Section *section = section_list->GetSectionAtIndex (i).get();
        if (section)
        {
            lldb::addr_t section_vm_addr = section->GetFileAddress();
            FileRange file_range (section->GetFileOffset(), section->GetFileSize());
            VMRangeToFileOffset::Entry range_entry (section_vm_addr,
                                                    section->GetByteSize(),
                                                    file_range);
            
            if (vm_addr > section_vm_addr)
                ranges_are_sorted = false;
            vm_addr = section->GetFileAddress();
            VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
//            printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n",
//                    i, 
//                    range_entry.GetRangeBase(),
//                    range_entry.GetRangeEnd(),
//                    range_entry.data.GetRangeBase(),
//                    range_entry.data.GetRangeEnd());

            if (last_entry &&
                last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
                last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
            {
                last_entry->SetRangeEnd (range_entry.GetRangeEnd());
                last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
                //puts("combine");
            }
            else
            {
                m_core_aranges.Append(range_entry);
            }
        }
    }
    if (!ranges_are_sorted)
    {
        m_core_aranges.Sort();
    }

    if (m_dyld_addr == LLDB_INVALID_ADDRESS || m_mach_kernel_addr == LLDB_INVALID_ADDRESS)
    {
        // We need to locate the main executable in the memory ranges
        // we have in the core file.  We need to search for both a user-process dyld binary
        // and a kernel binary in memory; we must look at all the pages in the binary so
        // we don't miss one or the other.  If we find a user-process dyld binary, stop
        // searching -- that's the one we'll prefer over the mach kernel.
        const size_t num_core_aranges = m_core_aranges.GetSize();
        for (size_t i=0; i<num_core_aranges && m_dyld_addr == LLDB_INVALID_ADDRESS; ++i)
        {
            const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i);
            lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
            lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
            for (lldb::addr_t section_vm_addr = section_vm_addr_start;
                 section_vm_addr < section_vm_addr_end;
                 section_vm_addr += 0x1000)
            {
                GetDynamicLoaderAddress (section_vm_addr);
            }
        }
    }

    // If we found both a user-process dyld and a kernel binary, we need to decide
    // which to prefer.
    if (GetCorefilePreference() == eKernelCorefile)
    {
        if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)
        {
            m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
        }
        else if (m_dyld_addr != LLDB_INVALID_ADDRESS)
        {
            m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
        }
    }
    else
    {
        if (m_dyld_addr != LLDB_INVALID_ADDRESS)
        {
            m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
        }
        else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)
        {
            m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
        }
    }

    // Even if the architecture is set in the target, we need to override
    // it to match the core file which is always single arch.
    ArchSpec arch (m_core_module_sp->GetArchitecture());
    if (arch.GetCore() == ArchSpec::eCore_x86_32_i486)
    {
        arch.SetTriple ("i386", m_target.GetPlatform().get());
    }
    if (arch.IsValid())
        m_target.SetArchitecture(arch);            

    return error;
}
コード例 #3
0
//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
Error
ProcessMachCore::DoLoadCore ()
{
    Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_DYNAMIC_LOADER | LIBLLDB_LOG_PROCESS));
    Error error;
    if (!m_core_module_sp)
    {
        error.SetErrorString ("invalid core module");   
        return error;
    }

    ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
    if (core_objfile == NULL)
    {
        error.SetErrorString ("invalid core object file");   
        return error;
    }
    
    if (core_objfile->GetNumThreadContexts() == 0)
    {
        error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb");
        return error;
    }

    SectionList *section_list = core_objfile->GetSectionList();
    if (section_list == NULL)
    {
        error.SetErrorString ("core file has no sections");   
        return error;
    }
        
    const uint32_t num_sections = section_list->GetNumSections(0);
    if (num_sections == 0)
    {
        error.SetErrorString ("core file has no sections");   
        return error;
    }
    
    SetCanJIT(false);

    llvm::MachO::mach_header header;
    DataExtractor data (&header, 
                        sizeof(header), 
                        m_core_module_sp->GetArchitecture().GetByteOrder(),
                        m_core_module_sp->GetArchitecture().GetAddressByteSize());

    bool ranges_are_sorted = true;
    addr_t vm_addr = 0;
    for (uint32_t i=0; i<num_sections; ++i)
    {
        Section *section = section_list->GetSectionAtIndex (i).get();
        if (section)
        {
            lldb::addr_t section_vm_addr = section->GetFileAddress();
            FileRange file_range (section->GetFileOffset(), section->GetFileSize());
            VMRangeToFileOffset::Entry range_entry (section_vm_addr,
                                                    section->GetByteSize(),
                                                    file_range);
            
            if (vm_addr > section_vm_addr)
                ranges_are_sorted = false;
            vm_addr = section->GetFileAddress();
            VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
//            printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n",
//                    i, 
//                    range_entry.GetRangeBase(),
//                    range_entry.GetRangeEnd(),
//                    range_entry.data.GetRangeBase(),
//                    range_entry.data.GetRangeEnd());

            if (last_entry &&
                last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
                last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
            {
                last_entry->SetRangeEnd (range_entry.GetRangeEnd());
                last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
                //puts("combine");
            }
            else
            {
                m_core_aranges.Append(range_entry);
            }
            // Some core files don't fill in the permissions correctly. If that is the case
            // assume read + execute so clients don't think the memory is not readable,
            // or executable. The memory isn't writable since this plug-in doesn't implement
            // DoWriteMemory.
            uint32_t permissions = section->GetPermissions();
            if (permissions == 0)
                permissions = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
            m_core_range_infos.Append(
                VMRangeToPermissions::Entry(section_vm_addr, section->GetByteSize(), permissions));
        }
    }
    if (!ranges_are_sorted)
    {
        m_core_aranges.Sort();
        m_core_range_infos.Sort();
    }

    if (m_dyld_addr == LLDB_INVALID_ADDRESS || m_mach_kernel_addr == LLDB_INVALID_ADDRESS)
    {
        // We need to locate the main executable in the memory ranges
        // we have in the core file.  We need to search for both a user-process dyld binary
        // and a kernel binary in memory; we must look at all the pages in the binary so
        // we don't miss one or the other.  Step through all memory segments searching for
        // a kernel binary and for a user process dyld -- we'll decide which to prefer 
        // later if both are present.

        const size_t num_core_aranges = m_core_aranges.GetSize();
        for (size_t i = 0; i < num_core_aranges; ++i)
        {
            const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i);
            lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
            lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
            for (lldb::addr_t section_vm_addr = section_vm_addr_start;
                 section_vm_addr < section_vm_addr_end;
                 section_vm_addr += 0x1000)
            {
                GetDynamicLoaderAddress (section_vm_addr);
            }
        }
    }


    if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)
    {
        // In the case of multiple kernel images found in the core file via exhaustive
        // search, we may not pick the correct one.  See if the DynamicLoaderDarwinKernel's
        // search heuristics might identify the correct one.
        // Most of the time, I expect the address from SearchForDarwinKernel() will be the
        // same as the address we found via exhaustive search.

        if (GetTarget().GetArchitecture().IsValid() == false && m_core_module_sp.get())
        {
            GetTarget().SetArchitecture (m_core_module_sp->GetArchitecture());
        }

        // SearchForDarwinKernel will end up calling back into this this class in the GetImageInfoAddress
        // method which will give it the m_mach_kernel_addr/m_dyld_addr it already has.  Save that aside
        // and set m_mach_kernel_addr/m_dyld_addr to an invalid address temporarily so 
        // DynamicLoaderDarwinKernel does a real search for the kernel using its own heuristics.

        addr_t saved_mach_kernel_addr = m_mach_kernel_addr;
        addr_t saved_user_dyld_addr = m_dyld_addr;
        m_mach_kernel_addr = LLDB_INVALID_ADDRESS;
        m_dyld_addr = LLDB_INVALID_ADDRESS;

        addr_t better_kernel_address = DynamicLoaderDarwinKernel::SearchForDarwinKernel (this);

        m_mach_kernel_addr = saved_mach_kernel_addr;
        m_dyld_addr = saved_user_dyld_addr;

        if (better_kernel_address != LLDB_INVALID_ADDRESS)
        {
            if (log)
                log->Printf ("ProcessMachCore::DoLoadCore: Using the kernel address from DynamicLoaderDarwinKernel");
            m_mach_kernel_addr = better_kernel_address;
        }
    }


    // If we found both a user-process dyld and a kernel binary, we need to decide
    // which to prefer.
    if (GetCorefilePreference() == eKernelCorefile)
    {
        if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)
        {
            if (log)
                log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr);
            m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
        }
        else if (m_dyld_addr != LLDB_INVALID_ADDRESS)
        {
            if (log)
                log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr);
            m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
        }
    }
    else
    {
        if (m_dyld_addr != LLDB_INVALID_ADDRESS)
        {
            if (log)
                log->Printf ("ProcessMachCore::DoLoadCore: Using user process dyld image at 0x%" PRIx64, m_dyld_addr);
            m_dyld_plugin_name = DynamicLoaderMacOSXDYLD::GetPluginNameStatic();
        }
        else if (m_mach_kernel_addr != LLDB_INVALID_ADDRESS)
        {
            if (log)
                log->Printf ("ProcessMachCore::DoLoadCore: Using kernel corefile image at 0x%" PRIx64, m_mach_kernel_addr);
            m_dyld_plugin_name = DynamicLoaderDarwinKernel::GetPluginNameStatic();
        }
    }

    if (m_dyld_plugin_name != DynamicLoaderMacOSXDYLD::GetPluginNameStatic())
    {
        // For non-user process core files, the permissions on the core file segments are usually
        // meaningless, they may be just "read", because we're dealing with kernel coredumps or
        // early startup coredumps and the dumper is grabbing pages of memory without knowing
        // what they are.  If they aren't marked as "exeuctable", that can break the unwinder
        // which will check a pc value to see if it is in an executable segment and stop the
        // backtrace early if it is not ("executable" and "unknown" would both be fine, but 
        // "not executable" will break the unwinder).
        size_t core_range_infos_size = m_core_range_infos.GetSize();
        for (size_t i = 0; i < core_range_infos_size; i++)
        {
            VMRangeToPermissions::Entry *ent = m_core_range_infos.GetMutableEntryAtIndex (i);
            ent->data = lldb::ePermissionsReadable | lldb::ePermissionsExecutable;
        }
    }

    // Even if the architecture is set in the target, we need to override
    // it to match the core file which is always single arch.
    ArchSpec arch (m_core_module_sp->GetArchitecture());
    if (arch.GetCore() == ArchSpec::eCore_x86_32_i486)
    {
        arch.SetTriple ("i386", GetTarget().GetPlatform().get());
    }
    if (arch.IsValid())
        GetTarget().SetArchitecture(arch);

    return error;
}
//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
Error
ProcessMachCore::DoLoadCore ()
{
    Error error;
    if (!m_core_module_sp)
    {
        error.SetErrorString ("invalid core module");   
        return error;
    }

    ObjectFile *core_objfile = m_core_module_sp->GetObjectFile();
    if (core_objfile == NULL)
    {
        error.SetErrorString ("invalid core object file");   
        return error;
    }
    
    if (core_objfile->GetNumThreadContexts() == 0)
    {
        error.SetErrorString ("core file doesn't contain any LC_THREAD load commands, or the LC_THREAD architecture is not supported in this lldb");
        return error;
    }

    SectionList *section_list = core_objfile->GetSectionList();
    if (section_list == NULL)
    {
        error.SetErrorString ("core file has no sections");   
        return error;
    }
        
    const uint32_t num_sections = section_list->GetNumSections(0);
    if (num_sections == 0)
    {
        error.SetErrorString ("core file has no sections");   
        return error;
    }
    
    SetCanJIT(false);

    llvm::MachO::mach_header header;
    DataExtractor data (&header, 
                        sizeof(header), 
                        m_core_module_sp->GetArchitecture().GetByteOrder(),
                        m_core_module_sp->GetArchitecture().GetAddressByteSize());

    bool ranges_are_sorted = true;
    addr_t vm_addr = 0;
    for (uint32_t i=0; i<num_sections; ++i)
    {
        Section *section = section_list->GetSectionAtIndex (i).get();
        if (section)
        {
            lldb::addr_t section_vm_addr = section->GetFileAddress();
            FileRange file_range (section->GetFileOffset(), section->GetFileSize());
            VMRangeToFileOffset::Entry range_entry (section_vm_addr,
                                                    section->GetByteSize(),
                                                    file_range);
            
            if (vm_addr > section_vm_addr)
                ranges_are_sorted = false;
            vm_addr = section->GetFileAddress();
            VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
//            printf ("LC_SEGMENT[%u] arange=[0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), frange=[0x%8.8x - 0x%8.8x)\n",
//                    i, 
//                    range_entry.GetRangeBase(),
//                    range_entry.GetRangeEnd(),
//                    range_entry.data.GetRangeBase(),
//                    range_entry.data.GetRangeEnd());

            if (last_entry &&
                last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
                last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase())
            {
                last_entry->SetRangeEnd (range_entry.GetRangeEnd());
                last_entry->data.SetRangeEnd (range_entry.data.GetRangeEnd());
                //puts("combine");
            }
            else
            {
                m_core_aranges.Append(range_entry);
            }
            
            // After we have added this section to our m_core_aranges map,
            // we can check the start of the section to see if it might
            // contain dyld for user space apps, or the mach kernel file 
            // for kernel cores.
            if (m_dyld_addr == LLDB_INVALID_ADDRESS)
                GetDynamicLoaderAddress (section_vm_addr);
        }
    }
    if (!ranges_are_sorted)
    {
        m_core_aranges.Sort();
    }

    // Even if the architecture is set in the target, we need to override
    // it to match the core file which is always single arch.
    ArchSpec arch (m_core_module_sp->GetArchitecture());
    if (arch.GetCore() == ArchSpec::eCore_x86_32_i486)
    {
        arch.SetTriple ("i386", m_target.GetPlatform().get());
    }
    if (arch.IsValid())
        m_target.SetArchitecture(arch);            

    if (m_dyld_addr == LLDB_INVALID_ADDRESS)
    {
        // We need to locate the main executable in the memory ranges
        // we have in the core file. We already checked the first address
        // in each memory zone above, so we just need to check each page
        // except the first page in each range and stop once we have found
        // our main executable
        const size_t num_core_aranges = m_core_aranges.GetSize();
        for (size_t i=0; i<num_core_aranges && m_dyld_addr == LLDB_INVALID_ADDRESS; ++i)
        {
            const VMRangeToFileOffset::Entry *entry = m_core_aranges.GetEntryAtIndex(i);
            lldb::addr_t section_vm_addr_start = entry->GetRangeBase();
            lldb::addr_t section_vm_addr_end = entry->GetRangeEnd();
            for (lldb::addr_t section_vm_addr = section_vm_addr_start + 0x1000;
                 section_vm_addr < section_vm_addr_end;
                 section_vm_addr += 0x1000)
            {
                if (GetDynamicLoaderAddress (section_vm_addr))
                {
                    break;
                }
            }
        }
    }
    return error;
}