Beispiel #1
0
//----------------------------------------------------------------------
// Disassembler copy constructor
//----------------------------------------------------------------------
Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) :
    m_arch (arch),
    m_instruction_list(),
    m_base_addr(LLDB_INVALID_ADDRESS),
    m_flavor ()
{
    if (flavor == NULL)
        m_flavor.assign("default");
    else
        m_flavor.assign(flavor);

    // If this is an arm variant that can only include thumb (T16, T32)
    // instructions, force the arch triple to be "thumbv.." instead of
    // "armv..."
    if (arch.GetTriple().getArch() == llvm::Triple::arm
        && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m
            || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
            || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
    {
        std::string thumb_arch_name (arch.GetTriple().getArchName().str());
        // Replace "arm" with "thumb" so we get all thumb variants correct
        if (thumb_arch_name.size() > 3)
        {
            thumb_arch_name.erase(0, 3);
            thumb_arch_name.insert(0, "thumb");
        }
        m_arch.SetTriple (thumb_arch_name.c_str());
    }
}
Beispiel #2
0
bool
lldb_private::operator<(const ArchSpec& lhs, const ArchSpec& rhs)
{
    const ArchSpec::Core lhs_core = lhs.GetCore ();
    const ArchSpec::Core rhs_core = rhs.GetCore ();
    return lhs_core < rhs_core;
}
Beispiel #3
0
bool
lldb_private::operator== (const ArchSpec& lhs, const ArchSpec& rhs)
{
    const ArchSpec::Core lhs_core = lhs.GetCore ();
    const ArchSpec::Core rhs_core = rhs.GetCore ();

    if (lhs_core == rhs_core)
        return true;

    if (lhs_core == ArchSpec::kCore_any || rhs_core == ArchSpec::kCore_any)
        return true;

    if (lhs_core == ArchSpec::kCore_arm_any)
    {
        if ((rhs_core >= ArchSpec::kCore_arm_first && rhs_core <= ArchSpec::kCore_arm_last) || (rhs_core == ArchSpec::kCore_arm_any))
            return true;
    }
    else if (rhs_core == ArchSpec::kCore_arm_any)
    {
        if ((lhs_core >= ArchSpec::kCore_arm_first && lhs_core <= ArchSpec::kCore_arm_last) || (lhs_core == ArchSpec::kCore_arm_any))
            return true;
    }
    else if (lhs_core == ArchSpec::kCore_x86_32_any)
    {
        if ((rhs_core >= ArchSpec::kCore_x86_32_first && rhs_core <= ArchSpec::kCore_x86_32_last) || (rhs_core == ArchSpec::kCore_x86_32_any))
            return true;
    }
    else if (rhs_core == ArchSpec::kCore_x86_32_any)
    {
        if ((lhs_core >= ArchSpec::kCore_x86_32_first && lhs_core <= ArchSpec::kCore_x86_32_last) || (lhs_core == ArchSpec::kCore_x86_32_any))
            return true;
    }
    else if (lhs_core == ArchSpec::kCore_ppc_any)
    {
        if ((rhs_core >= ArchSpec::kCore_ppc_first && rhs_core <= ArchSpec::kCore_ppc_last) || (rhs_core == ArchSpec::kCore_ppc_any))
            return true;
    }
    else if (rhs_core == ArchSpec::kCore_ppc_any)
    {
        if ((lhs_core >= ArchSpec::kCore_ppc_first && lhs_core <= ArchSpec::kCore_ppc_last) || (lhs_core == ArchSpec::kCore_ppc_any))
            return true;
    }
    else if (lhs_core == ArchSpec::kCore_ppc64_any)
    {
        if ((rhs_core >= ArchSpec::kCore_ppc64_first && rhs_core <= ArchSpec::kCore_ppc64_last) || (rhs_core == ArchSpec::kCore_ppc64_any))
            return true;
    }
    else if (rhs_core == ArchSpec::kCore_ppc64_any)
    {
        if ((lhs_core >= ArchSpec::kCore_ppc64_first && lhs_core <= ArchSpec::kCore_ppc64_last) || (lhs_core == ArchSpec::kCore_ppc64_any))
            return true;
    }
    return false;
}
size_t
ProcessPOSIX::GetSoftwareBreakpointTrapOpcode(BreakpointSite* bp_site)
{
    static const uint8_t g_i386_opcode[] = { 0xCC };

    ArchSpec arch = GetTarget().GetArchitecture();
    const uint8_t *opcode = NULL;
    size_t opcode_size = 0;

    switch (arch.GetCore())
    {
    default:
        assert(false && "CPU type not supported!");
        break;

    case ArchSpec::eCore_x86_32_i386:
    case ArchSpec::eCore_x86_64_x86_64:
        opcode = g_i386_opcode;
        opcode_size = sizeof(g_i386_opcode);
        break;
    }

    bp_site->SetTrapOpcode(opcode, opcode_size);
    return opcode_size;
}
Beispiel #5
0
size_t
PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode (Target &target, BreakpointSite *bp_site)
{
    ArchSpec arch = target.GetArchitecture();
    const uint8_t *trap_opcode = NULL;
    size_t trap_opcode_size = 0;

    switch (arch.GetCore())
    {
    default:
        assert(false && "Unhandled architecture in PlatformFreeBSD::GetSoftwareBreakpointTrapOpcode()");
        break;

    case ArchSpec::eCore_x86_32_i386:
    case ArchSpec::eCore_x86_64_x86_64:
        {
            static const uint8_t g_i386_opcode[] = { 0xCC };
            trap_opcode = g_i386_opcode;
            trap_opcode_size = sizeof(g_i386_opcode);
        }
        break;
    }

    if (bp_site->SetTrapOpcode(trap_opcode, trap_opcode_size))
        return trap_opcode_size;

    return 0;
}
Beispiel #6
0
lldb::RegisterContextSP
POSIXThread::GetRegisterContext()
{
    if (!m_reg_context_sp)
    {
        ArchSpec arch = Host::GetArchitecture();

        switch (arch.GetCore())
        {
        default:
            assert(false && "CPU type not supported!");
            break;

        case ArchSpec::eCore_x86_32_i386:
        case ArchSpec::eCore_x86_32_i486:
        case ArchSpec::eCore_x86_32_i486sx:
            m_reg_context_sp.reset(new RegisterContext_i386(*this, 0));
            break;

        case ArchSpec::eCore_x86_64_x86_64:
            m_reg_context_sp.reset(new RegisterContext_x86_64(*this, 0));
            break;
        }
    }
    return m_reg_context_sp;
}
Beispiel #7
0
unsigned
POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
{
    unsigned reg = LLDB_INVALID_REGNUM;
    ArchSpec arch = Host::GetArchitecture();

    switch (arch.GetCore())
    {
    default:
        llvm_unreachable("CPU type not supported!");
        break;

    case ArchSpec::eCore_x86_32_i386:
    case ArchSpec::eCore_x86_32_i486:
    case ArchSpec::eCore_x86_32_i486sx:
    case ArchSpec::eCore_x86_64_x86_64:
        {
            RegisterContextSP base = GetRegisterContext();
            if (base) {
                RegisterContextPOSIX &context = static_cast<RegisterContextPOSIX &>(*base);
                reg = context.GetRegisterIndexFromOffset(offset);
            }
        }
        break;
    }
    return reg;
}
Beispiel #8
0
lldb::RegisterContextSP
POSIXThread::GetRegisterContext()
{
    if (!m_reg_context_sp)
    {
        ArchSpec arch = Host::GetArchitecture();

        switch (arch.GetCore())
        {
        default:
            assert(false && "CPU type not supported!");
            break;

        case ArchSpec::eCore_x86_32_i386:
        case ArchSpec::eCore_x86_32_i486:
        case ArchSpec::eCore_x86_32_i486sx:
            m_reg_context_sp.reset(new RegisterContext_i386(*this, 0));
            break;

        case ArchSpec::eCore_x86_64_x86_64:
// TODO: Use target OS/architecture detection rather than ifdefs so that
// lldb built on FreeBSD can debug on Linux and vice-versa.
#ifdef __linux__
            m_reg_context_sp.reset(new RegisterContextLinux_x86_64(*this, 0));
#endif
#ifdef __FreeBSD__
            m_reg_context_sp.reset(new RegisterContextFreeBSD_x86_64(*this, 0));
#endif
            break;
        }
    }
    return m_reg_context_sp;
}
Beispiel #9
0
unsigned
POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
{
    unsigned reg = LLDB_INVALID_REGNUM;
    ArchSpec arch = Host::GetArchitecture();

    switch (arch.GetCore())
    {
    default:
        llvm_unreachable("CPU type not supported!");
        break;

    case ArchSpec::eCore_mips64:
    case ArchSpec::eCore_x86_32_i386:
    case ArchSpec::eCore_x86_32_i486:
    case ArchSpec::eCore_x86_32_i486sx:
    case ArchSpec::eCore_x86_64_x86_64:
        {
            POSIXBreakpointProtocol* reg_ctx = GetPOSIXBreakpointProtocol();
            reg = reg_ctx->GetRegisterIndexFromOffset(offset);
        }
        break;
    }
    return reg;
}
Beispiel #10
0
Error
ELFLinuxPrStatus::Parse(DataExtractor &data, ArchSpec &arch)
{
    Error error;
    ByteOrder byteorder = data.GetByteOrder();
    if (GetSize(arch) > data.GetByteSize())
    {
        error.SetErrorStringWithFormat("NT_PRSTATUS size should be %lu, but the remaining bytes are: %lu",
                                       GetSize(arch), data.GetByteSize());
        return error;
    }

    switch(arch.GetCore())
    {
        case ArchSpec::eCore_s390x_generic:
        case ArchSpec::eCore_x86_64_x86_64:
            data.ExtractBytes(0, sizeof(ELFLinuxPrStatus), byteorder, this);
            break;
        case ArchSpec::eCore_x86_32_i386:
        case ArchSpec::eCore_x86_32_i486:
        {
            // Parsing from a 32 bit ELF core file, and populating/reusing the structure
            // properly, because the struct is for the 64 bit version
            offset_t offset = 0;
            si_signo = data.GetU32(&offset);
            si_code = data.GetU32(&offset);
            si_errno = data.GetU32(&offset);

            pr_cursig = data.GetU16(&offset);
            offset += 2; // pad

            pr_sigpend = data.GetU32(&offset);
            pr_sighold = data.GetU32(&offset);

            pr_pid = data.GetU32(&offset);
            pr_ppid = data.GetU32(&offset);
            pr_pgrp = data.GetU32(&offset);
            pr_sid = data.GetU32(&offset);

            pr_utime.tv_sec = data.GetU32(&offset);
            pr_utime.tv_usec = data.GetU32(&offset);

            pr_stime.tv_sec = data.GetU32(&offset);
            pr_stime.tv_usec = data.GetU32(&offset);

            pr_cutime.tv_sec = data.GetU32(&offset);
            pr_cutime.tv_usec = data.GetU32(&offset);

            pr_cstime.tv_sec = data.GetU32(&offset);
            pr_cstime.tv_usec = data.GetU32(&offset);

            break;
        }
        default:
            error.SetErrorStringWithFormat("ELFLinuxPrStatus::%s Unknown architecture", __FUNCTION__);
            break;
    }

    return error;
}
Beispiel #11
0
Error
ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch)
{
    Error error;
    ByteOrder byteorder = data.GetByteOrder();
    if (GetSize(arch) > data.GetByteSize())
    {
        error.SetErrorStringWithFormat("NT_PRPSINFO size should be %lu, but the remaining bytes are: %lu",
                                       GetSize(arch), data.GetByteSize());
        return error;
    }

    switch(arch.GetCore())
    {
        case ArchSpec::eCore_s390x_generic:
        case ArchSpec::eCore_x86_64_x86_64:
            data.ExtractBytes(0, sizeof(ELFLinuxPrPsInfo), byteorder, this);
            break;
        case ArchSpec::eCore_x86_32_i386:
        case ArchSpec::eCore_x86_32_i486:
        {
            // Parsing from a 32 bit ELF core file, and populating/reusing the structure
            // properly, because the struct is for the 64 bit version
            size_t size = 0;
            offset_t offset = 0;

            pr_state = data.GetU8(&offset);
            pr_sname = data.GetU8(&offset);
            pr_zomb = data.GetU8(&offset);
            pr_nice = data.GetU8(&offset);

            pr_flag = data.GetU32(&offset);
            pr_uid = data.GetU16(&offset);
            pr_gid = data.GetU16(&offset);

            pr_pid = data.GetU32(&offset);
            pr_ppid = data.GetU32(&offset);
            pr_pgrp = data.GetU32(&offset);
            pr_sid = data.GetU32(&offset);

            size = 16;
            data.ExtractBytes(offset, size, byteorder, pr_fname);
            offset += size;

            size = 80;
            data.ExtractBytes(offset, size, byteorder, pr_psargs);
            offset += size;

            break;
        }
        default:
            error.SetErrorStringWithFormat("ELFLinuxPrPsInfo::%s Unknown architecture", __FUNCTION__);
            break;
    }

    return error;
}
Beispiel #12
0
TEST(ArchSpecTest, TestSetTriple) {
  ArchSpec AS;

  // Various flavors of valid triples.
  EXPECT_TRUE(AS.SetTriple("12-10-apple-darwin"));
  EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_ARM), AS.GetMachOCPUType());
  EXPECT_EQ(10u, AS.GetMachOCPUSubType());
  EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
                  .consume_front("armv7f-apple-darwin"));
  EXPECT_EQ(ArchSpec::eCore_arm_armv7f, AS.GetCore());

  AS = ArchSpec();
  EXPECT_TRUE(AS.SetTriple("18.100-apple-darwin"));
  EXPECT_EQ(uint32_t(llvm::MachO::CPU_TYPE_POWERPC), AS.GetMachOCPUType());
  EXPECT_EQ(100u, AS.GetMachOCPUSubType());
  EXPECT_TRUE(llvm::StringRef(AS.GetTriple().str())
                  .consume_front("powerpc-apple-darwin"));
  EXPECT_EQ(ArchSpec::eCore_ppc_ppc970, AS.GetCore());

  AS = ArchSpec();
  EXPECT_TRUE(AS.SetTriple("i686-pc-windows"));
  EXPECT_EQ(llvm::Triple::x86, AS.GetTriple().getArch());
  EXPECT_EQ(llvm::Triple::PC, AS.GetTriple().getVendor());
  EXPECT_EQ(llvm::Triple::Win32, AS.GetTriple().getOS());
  EXPECT_TRUE(
      llvm::StringRef(AS.GetTriple().str()).consume_front("i686-pc-windows"));
  EXPECT_STREQ("i686", AS.GetArchitectureName());
  EXPECT_EQ(ArchSpec::eCore_x86_32_i686, AS.GetCore());

  // Various flavors of invalid triples.
  AS = ArchSpec();
  EXPECT_FALSE(AS.SetTriple("unknown-unknown-unknown"));

  AS = ArchSpec();
  EXPECT_FALSE(AS.SetTriple("unknown"));

  AS = ArchSpec();
  EXPECT_FALSE(AS.SetTriple(""));
}
bool
ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch)
{
    ByteOrder byteorder = data.GetByteOrder();
    size_t len;
    switch(arch.GetCore())
    {
        case ArchSpec::eCore_x86_64_x86_64:
            len = data.ExtractBytes(0, ELFLINUXPRPSINFO64_SIZE, byteorder, this);
            return len == ELFLINUXPRPSINFO64_SIZE;
        default:
            return false;
    }
}
Beispiel #14
0
TEST(ArchSpecTest, MergeFrom) {
  {
    ArchSpec A;
    ArchSpec B("x86_64-pc-linux");

    EXPECT_FALSE(A.IsValid());
    ASSERT_TRUE(B.IsValid());
    EXPECT_EQ(llvm::Triple::ArchType::x86_64, B.GetTriple().getArch());
    EXPECT_EQ(llvm::Triple::VendorType::PC, B.GetTriple().getVendor());
    EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
    EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, B.GetCore());

    A.MergeFrom(B);
    ASSERT_TRUE(A.IsValid());
    EXPECT_EQ(llvm::Triple::ArchType::x86_64, A.GetTriple().getArch());
    EXPECT_EQ(llvm::Triple::VendorType::PC, A.GetTriple().getVendor());
    EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
    EXPECT_EQ(ArchSpec::eCore_x86_64_x86_64, A.GetCore());
  }
  {
    ArchSpec A("aarch64");
    ArchSpec B("aarch64--linux-android");

    EXPECT_TRUE(A.IsValid());
    EXPECT_TRUE(B.IsValid());

    EXPECT_EQ(llvm::Triple::ArchType::aarch64, B.GetTriple().getArch());
    EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
              B.GetTriple().getVendor());
    EXPECT_EQ(llvm::Triple::OSType::Linux, B.GetTriple().getOS());
    EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
              B.GetTriple().getEnvironment());

    A.MergeFrom(B);
    EXPECT_EQ(llvm::Triple::ArchType::aarch64, A.GetTriple().getArch());
    EXPECT_EQ(llvm::Triple::VendorType::UnknownVendor,
              A.GetTriple().getVendor());
    EXPECT_EQ(llvm::Triple::OSType::Linux, A.GetTriple().getOS());
    EXPECT_EQ(llvm::Triple::EnvironmentType::Android,
              A.GetTriple().getEnvironment());
  }
}
Beispiel #15
0
const char *
POSIXThread::GetRegisterName(unsigned reg)
{
    const char * name = nullptr;
    ArchSpec arch = Host::GetArchitecture();

    switch (arch.GetCore())
    {
    default:
        assert(false && "CPU type not supported!");
        break;

    case ArchSpec::eCore_x86_32_i386:
    case ArchSpec::eCore_x86_32_i486:
    case ArchSpec::eCore_x86_32_i486sx:
    case ArchSpec::eCore_x86_64_x86_64:
        name = GetRegisterContext()->GetRegisterName(reg);
        break;
    }
    return name;
}
Beispiel #16
0
unsigned
POSIXThread::GetRegisterIndexFromOffset(unsigned offset)
{
    unsigned reg;
    ArchSpec arch = Host::GetArchitecture();

    switch (arch.GetCore())
    {
    default:
        assert(false && "CPU type not supported!");
        break;

    case ArchSpec::eCore_x86_32_i386:
    case ArchSpec::eCore_x86_32_i486:
    case ArchSpec::eCore_x86_32_i486sx:
        reg = RegisterContext_i386::GetRegisterIndexFromOffset(offset);
        break;

    case ArchSpec::eCore_x86_64_x86_64:
        reg = RegisterContext_x86_64::GetRegisterIndexFromOffset(offset);
        break;
    }
    return reg;
}
DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
    Disassembler(arch, flavor_string),
    m_exe_ctx (NULL),
    m_inst (NULL),
    m_data_from_file (false)
{
    if (!FlavorValidForArchSpec (arch, m_flavor.c_str()))
    {
        m_flavor.assign("default");
    }
    
    const char *triple = arch.GetTriple().getTriple().c_str();
    unsigned flavor = ~0U;
    
    // So far the only supported flavor is "intel" on x86.  The base class will set this
    // correctly coming in.
    if (arch.GetTriple().getArch() == llvm::Triple::x86
        || arch.GetTriple().getArch() == llvm::Triple::x86_64)
    {
        if (m_flavor == "intel")
        {
            flavor = 1;
        }
        else if (m_flavor == "att")
        {
            flavor = 0;
        }
    }
    
    ArchSpec thumb_arch(arch);
    if (arch.GetTriple().getArch() == llvm::Triple::arm)
    {
        std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str());
        // Replace "arm" with "thumb" so we get all thumb variants correct
        if (thumb_arch_name.size() > 3)
        {
            thumb_arch_name.erase(0,3);
            thumb_arch_name.insert(0, "thumb");
        }
        else
        {
            thumb_arch_name = "thumbv7";
        }
        thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str()));
    }
    
    // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions, 
    // so hardcode the primary disassembler to thumb mode.  Same for Cortex-M4 (armv7em).
    //
    // Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32
    // instructions defined in ARMv7-A.  

    if (arch.GetTriple().getArch() == llvm::Triple::arm
        && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m 
            || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em
            || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m))
    {
        triple = thumb_arch.GetTriple().getTriple().c_str();
    }

    m_disasm_ap.reset (new LLVMCDisassembler(triple, flavor, *this));
    if (!m_disasm_ap->IsValid())
    {
        // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
        // we reset it, and then we won't be valid and FindPlugin will fail and we won't get used.
        m_disasm_ap.reset();
    }

    // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler.
    if (arch.GetTriple().getArch() == llvm::Triple::arm)
    {
        std::string thumb_triple(thumb_arch.GetTriple().getTriple());
        m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), flavor, *this));
        if (!m_alternate_disasm_ap->IsValid())
        {
            m_disasm_ap.reset();
            m_alternate_disasm_ap.reset();
        }
    }
}
//----------------------------------------------------------------------
// 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;
}
//----------------------------------------------------------------------
// 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);
            }
        }
    }
    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;
}
Beispiel #21
0
bool
ArchSpec::Compare (const ArchSpec& rhs, bool exact_match) const
{
    if (GetByteOrder() != rhs.GetByteOrder())
        return false;
        
    const ArchSpec::Core lhs_core = GetCore ();
    const ArchSpec::Core rhs_core = rhs.GetCore ();

    const bool core_match = cores_match (lhs_core, rhs_core, true, exact_match);

    if (core_match)
    {
        const llvm::Triple &lhs_triple = GetTriple();
        const llvm::Triple &rhs_triple = rhs.GetTriple();

        const llvm::Triple::VendorType lhs_triple_vendor = lhs_triple.getVendor();
        const llvm::Triple::VendorType rhs_triple_vendor = rhs_triple.getVendor();
        if (lhs_triple_vendor != rhs_triple_vendor)
        {
            const bool rhs_vendor_specified = rhs.TripleVendorWasSpecified();
            const bool lhs_vendor_specified = TripleVendorWasSpecified();
            // Both architectures had the vendor specified, so if they aren't
            // equal then we return false
            if (rhs_vendor_specified && lhs_vendor_specified)
                return false;
            
            // Only fail if both vendor types are not unknown
            if (lhs_triple_vendor != llvm::Triple::UnknownVendor &&
                rhs_triple_vendor != llvm::Triple::UnknownVendor)
                return false;
        }
        
        const llvm::Triple::OSType lhs_triple_os = lhs_triple.getOS();
        const llvm::Triple::OSType rhs_triple_os = rhs_triple.getOS();
        if (lhs_triple_os != rhs_triple_os)
        {
            const bool rhs_os_specified = rhs.TripleOSWasSpecified();
            const bool lhs_os_specified = TripleOSWasSpecified();
            // Both architectures had the OS specified, so if they aren't
            // equal then we return false
            if (rhs_os_specified && lhs_os_specified)
                return false;
            // Only fail if both os types are not unknown
            if (lhs_triple_os != llvm::Triple::UnknownOS &&
                rhs_triple_os != llvm::Triple::UnknownOS)
                return false;
        }

        const llvm::Triple::EnvironmentType lhs_triple_env = lhs_triple.getEnvironment();
        const llvm::Triple::EnvironmentType rhs_triple_env = rhs_triple.getEnvironment();
            
        if (lhs_triple_env != rhs_triple_env)
        {
            // Only fail if both environment types are not unknown
            if (lhs_triple_env != llvm::Triple::UnknownEnvironment &&
                rhs_triple_env != llvm::Triple::UnknownEnvironment)
                return false;
        }
        return true;
    }
    return false;
}