void HostInfoBase::ComputeHostArchitectureSupport(ArchSpec &arch_32, ArchSpec &arch_64) { llvm::Triple triple(llvm::sys::getProcessTriple()); arch_32.Clear(); arch_64.Clear(); switch (triple.getArch()) { default: arch_32.SetTriple(triple); break; case llvm::Triple::aarch64: case llvm::Triple::ppc64: case llvm::Triple::x86_64: arch_64.SetTriple(triple); arch_32.SetTriple(triple.get32BitArchVariant()); break; case llvm::Triple::mips64: case llvm::Triple::mips64el: case llvm::Triple::sparcv9: case llvm::Triple::systemz: arch_64.SetTriple(triple); break; } }
ObjectFile * ObjectContainerUniversalMachO::GetObjectFile (const FileSpec *file) { uint32_t arch_idx = 0; ArchSpec arch; // If the module hasn't specified an architecture yet, set it to the default // architecture: if (!m_module->GetArchitecture().IsValid()) { arch = Target::GetDefaultArchitecture (); if (!arch.IsValid()) arch.SetTriple (LLDB_ARCH_DEFAULT); } else arch = m_module->GetArchitecture(); ArchSpec curr_arch; for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) { if (GetArchitectureAtIndex (arch_idx, curr_arch)) { if (arch == curr_arch) { return ObjectFile::FindPlugin (m_module, file, m_offset + m_fat_archs[arch_idx].offset, m_fat_archs[arch_idx].size); } } } return NULL; }
bool OptionGroupArchitecture::GetArchitecture(Platform *platform, ArchSpec &arch) { if (m_arch_str.empty()) arch.Clear(); else arch.SetTriple(m_arch_str.c_str(), platform); return arch.IsValid(); }
size_t ObjectFilePECOFF::GetModuleSpecifications (const lldb_private::FileSpec& file, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, lldb_private::ModuleSpecList &specs) { const size_t initial_count = specs.GetSize(); if (ObjectFilePECOFF::MagicBytesMatch(data_sp)) { DataExtractor data; data.SetData(data_sp, data_offset, length); data.SetByteOrder(eByteOrderLittle); dos_header_t dos_header; coff_header_t coff_header; if (ParseDOSHeader(data, dos_header)) { lldb::offset_t offset = dos_header.e_lfanew; uint32_t pe_signature = data.GetU32(&offset); if (pe_signature != IMAGE_NT_SIGNATURE) return false; if (ParseCOFFHeader(data, &offset, coff_header)) { ArchSpec spec; if (coff_header.machine == MachineAmd64) { spec.SetTriple("x86_64-pc-windows"); specs.Append(ModuleSpec(file, spec)); } else if (coff_header.machine == MachineX86) { spec.SetTriple("i386-pc-windows"); specs.Append(ModuleSpec(file, spec)); spec.SetTriple("i686-pc-windows"); specs.Append(ModuleSpec(file, spec)); } } } } return specs.GetSize() - initial_count; }
bool PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) { if (IsHost()) { ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); if (hostArch.GetTriple().isOSLinux()) { if (idx == 0) { arch = hostArch; return arch.IsValid(); } else if (idx == 1) { // If the default host architecture is 64-bit, look for a 32-bit variant if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit()) { arch = HostInfo::GetArchitecture(HostInfo::eArchKind32); return arch.IsValid(); } } } } else { if (m_remote_platform_sp) return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch); llvm::Triple triple; // Set the OS to linux triple.setOS(llvm::Triple::Linux); // Set the architecture switch (idx) { case 0: triple.setArchName("x86_64"); break; case 1: triple.setArchName("i386"); break; case 2: triple.setArchName("arm"); break; case 3: triple.setArchName("aarch64"); break; case 4: triple.setArchName("mips64"); break; case 5: triple.setArchName("hexagon"); break; case 6: triple.setArchName("mips"); break; case 7: triple.setArchName("mips64el"); break; case 8: triple.setArchName("mipsel"); break; default: return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the vendor by // calling triple.SetVendorName("unknown") so that it is a "unspecified unknown". // This means when someone calls triple.GetVendorName() it will return an empty string // which indicates that the vendor can be set when two architectures are merged // Now set the triple into "arch" and return true arch.SetTriple(triple); return true; } return false; }
bool PlatformRemoteGDBServer::GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) { ArchSpec remote_arch = m_gdb_client.GetSystemArchitecture(); if (idx == 0) { arch = remote_arch; return arch.IsValid(); } else if (idx == 1 && remote_arch.IsValid() && remote_arch.GetTriple().isArch64Bit()) { arch.SetTriple(remote_arch.GetTriple().get32BitArchVariant()); return arch.IsValid(); } return false; }
bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) { if (IsHost()) { ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault); if (hostArch.GetTriple().isOSOpenBSD()) { if (idx == 0) { arch = hostArch; return arch.IsValid(); } } } else { if (m_remote_platform_sp) return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch); llvm::Triple triple; // Set the OS to OpenBSD triple.setOS(llvm::Triple::OpenBSD); // Set the architecture switch (idx) { case 0: triple.setArchName("x86_64"); break; case 1: triple.setArchName("i386"); break; case 2: triple.setArchName("aarch64"); break; case 3: triple.setArchName("arm"); break; default: return false; } // Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the // vendor by // calling triple.SetVendorName("unknown") so that it is a "unspecified // unknown". // This means when someone calls triple.GetVendorName() it will return an // empty string // which indicates that the vendor can be set when two architectures are // merged // Now set the triple into "arch" and return true arch.SetTriple(triple); return true; } return false; }
ObjectFileSP ObjectContainerUniversalMachO::GetObjectFile(const FileSpec *file) { uint32_t arch_idx = 0; ArchSpec arch; // If the module hasn't specified an architecture yet, set it to the default // architecture: ModuleSP module_sp(GetModule()); if (module_sp) { if (!module_sp->GetArchitecture().IsValid()) { arch = Target::GetDefaultArchitecture(); if (!arch.IsValid()) arch.SetTriple(LLDB_ARCH_DEFAULT); } else arch = module_sp->GetArchitecture(); ArchSpec curr_arch; // First, try to find an exact match for the Arch of the Target. for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) { if (GetArchitectureAtIndex(arch_idx, curr_arch) && arch.IsExactMatch(curr_arch)) break; } // Failing an exact match, try to find a compatible Arch of the Target. if (arch_idx >= m_header.nfat_arch) { for (arch_idx = 0; arch_idx < m_header.nfat_arch; ++arch_idx) { if (GetArchitectureAtIndex(arch_idx, curr_arch) && arch.IsCompatibleMatch(curr_arch)) break; } } if (arch_idx < m_header.nfat_arch) { DataBufferSP data_sp; lldb::offset_t data_offset = 0; return ObjectFile::FindPlugin( module_sp, file, m_offset + m_fat_archs[arch_idx].offset, m_fat_archs[arch_idx].size, data_sp, data_offset); } } return ObjectFileSP(); }
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 PlatformRemoteAppleWatch::GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) { ArchSpec system_arch(GetSystemArchitecture()); const ArchSpec::Core system_core = system_arch.GetCore(); switch (system_core) { default: switch (idx) { case 0: arch.SetTriple("arm64-apple-watchos"); return true; case 1: arch.SetTriple("armv7k-apple-watchos"); return true; case 2: arch.SetTriple("armv7s-apple-watchos"); return true; case 3: arch.SetTriple("armv7-apple-watchos"); return true; case 4: arch.SetTriple("thumbv7k-apple-watchos"); return true; case 5: arch.SetTriple("thumbv7-apple-watchos"); return true; case 6: arch.SetTriple("thumbv7s-apple-watchos"); return true; default: break; } break; case ArchSpec::eCore_arm_arm64: switch (idx) { case 0: arch.SetTriple("arm64-apple-watchos"); return true; case 1: arch.SetTriple("armv7k-apple-watchos"); return true; case 2: arch.SetTriple("armv7s-apple-watchos"); return true; case 3: arch.SetTriple("armv7-apple-watchos"); return true; case 4: arch.SetTriple("thumbv7k-apple-watchos"); return true; case 5: arch.SetTriple("thumbv7-apple-watchos"); return true; case 6: arch.SetTriple("thumbv7s-apple-watchos"); return true; default: break; } break; case ArchSpec::eCore_arm_armv7k: switch (idx) { case 0: arch.SetTriple("armv7k-apple-watchos"); return true; case 1: arch.SetTriple("armv7s-apple-watchos"); return true; case 2: arch.SetTriple("armv7-apple-watchos"); return true; case 3: arch.SetTriple("thumbv7k-apple-watchos"); return true; case 4: arch.SetTriple("thumbv7-apple-watchos"); return true; case 5: arch.SetTriple("thumbv7s-apple-watchos"); return true; default: break; } break; case ArchSpec::eCore_arm_armv7s: switch (idx) { case 0: arch.SetTriple("armv7s-apple-watchos"); return true; case 1: arch.SetTriple("armv7k-apple-watchos"); return true; case 2: arch.SetTriple("armv7-apple-watchos"); return true; case 3: arch.SetTriple("thumbv7k-apple-watchos"); return true; case 4: arch.SetTriple("thumbv7-apple-watchos"); return true; case 5: arch.SetTriple("thumbv7s-apple-watchos"); return true; default: break; } break; case ArchSpec::eCore_arm_armv7: switch (idx) { case 0: arch.SetTriple("armv7-apple-watchos"); return true; case 1: arch.SetTriple("armv7k-apple-watchos"); return true; case 2: arch.SetTriple("thumbv7k-apple-watchos"); return true; case 3: arch.SetTriple("thumbv7-apple-watchos"); return true; default: break; } break; } arch.Clear(); return false; }
//---------------------------------------------------------------------- // 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; }
const ArchSpec & Host::GetArchitecture (SystemDefaultArchitecture arch_kind) { static bool g_supports_32 = false; static bool g_supports_64 = false; static ArchSpec g_host_arch_32; static ArchSpec g_host_arch_64; #if defined (__APPLE__) // Apple is different in that it can support both 32 and 64 bit executables // in the same operating system running concurrently. Here we detect the // correct host architectures for both 32 and 64 bit including if 64 bit // executables are supported on the system. if (g_supports_32 == false && g_supports_64 == false) { // All apple systems support 32 bit execution. g_supports_32 = true; uint32_t cputype, cpusubtype; uint32_t is_64_bit_capable = false; size_t len = sizeof(cputype); ArchSpec host_arch; // These will tell us about the kernel architecture, which even on a 64 // bit machine can be 32 bit... if (::sysctlbyname("hw.cputype", &cputype, &len, NULL, 0) == 0) { len = sizeof (cpusubtype); if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &len, NULL, 0) != 0) cpusubtype = CPU_TYPE_ANY; len = sizeof (is_64_bit_capable); if (::sysctlbyname("hw.cpu64bit_capable", &is_64_bit_capable, &len, NULL, 0) == 0) { if (is_64_bit_capable) g_supports_64 = true; } if (is_64_bit_capable) { #if defined (__i386__) || defined (__x86_64__) if (cpusubtype == CPU_SUBTYPE_486) cpusubtype = CPU_SUBTYPE_I386_ALL; #endif if (cputype & CPU_ARCH_ABI64) { // We have a 64 bit kernel on a 64 bit system g_host_arch_32.SetArchitecture (eArchTypeMachO, ~(CPU_ARCH_MASK) & cputype, cpusubtype); g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); } else { // We have a 32 bit kernel on a 64 bit system g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); cputype |= CPU_ARCH_ABI64; g_host_arch_64.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); } } else { g_host_arch_32.SetArchitecture (eArchTypeMachO, cputype, cpusubtype); g_host_arch_64.Clear(); } } } #else // #if defined (__APPLE__) if (g_supports_32 == false && g_supports_64 == false) { llvm::Triple triple(llvm::sys::getDefaultTargetTriple()); g_host_arch_32.Clear(); g_host_arch_64.Clear(); switch (triple.getArch()) { default: g_host_arch_32.SetTriple(triple); g_supports_32 = true; break; case llvm::Triple::x86_64: case llvm::Triple::sparcv9: case llvm::Triple::ppc64: case llvm::Triple::cellspu: g_host_arch_64.SetTriple(triple); g_supports_64 = true; break; } g_supports_32 = g_host_arch_32.IsValid(); g_supports_64 = g_host_arch_64.IsValid(); } #endif // #else for #if defined (__APPLE__) if (arch_kind == eSystemDefaultArchitecture32) return g_host_arch_32; else if (arch_kind == eSystemDefaultArchitecture64) return g_host_arch_64; if (g_supports_64) return g_host_arch_64; return g_host_arch_32; }
bool Instruction::TestEmulation (Stream *out_stream, const char *file_name) { if (!out_stream) return false; if (!file_name) { out_stream->Printf ("Instruction::TestEmulation: Missing file_name."); return false; } FILE *test_file = fopen (file_name, "r"); if (!test_file) { out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed."); return false; } char buffer[256]; if (!fgets (buffer, 255, test_file)) { out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n"); fclose (test_file); return false; } if (strncmp (buffer, "InstructionEmulationState={", 27) != 0) { out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n"); fclose (test_file); return false; } // Read all the test information from the test file into an OptionValueDictionary. OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream)); if (data_dictionary_sp.get() == NULL) { out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n"); fclose (test_file); return false; } fclose (test_file); OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary(); static ConstString description_key ("assembly_string"); static ConstString triple_key ("triple"); OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key); if (value_sp.get() == NULL) { out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n"); return false; } SetDescription (value_sp->GetStringValue()); value_sp = data_dictionary->GetValueForKey (triple_key); if (value_sp.get() == NULL) { out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n"); return false; } ArchSpec arch; arch.SetTriple (llvm::Triple (value_sp->GetStringValue())); bool success = false; std::unique_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL)); if (insn_emulator_ap.get()) success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary); if (success) out_stream->Printf ("Emulation test succeeded."); else out_stream->Printf ("Emulation test failed."); return success; }
//---------------------------------------------------------------------- // 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; }
bool PlatformDarwin::ARMGetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch) { ArchSpec system_arch (GetSystemArchitecture()); const ArchSpec::Core system_core = system_arch.GetCore(); switch (system_core) { default: switch (idx) { case 0: arch.SetTriple ("armv7-apple-ios"); return true; case 1: arch.SetTriple ("armv7f-apple-ios"); return true; case 2: arch.SetTriple ("armv7k-apple-ios"); return true; case 3: arch.SetTriple ("armv7s-apple-ios"); return true; case 4: arch.SetTriple ("armv6-apple-ios"); return true; case 5: arch.SetTriple ("armv5-apple-ios"); return true; case 6: arch.SetTriple ("armv4-apple-ios"); return true; case 7: arch.SetTriple ("arm-apple-ios"); return true; case 8: arch.SetTriple ("thumbv7-apple-ios"); return true; case 9: arch.SetTriple ("thumbv7f-apple-ios"); return true; case 10: arch.SetTriple ("thumbv7k-apple-ios"); return true; case 11: arch.SetTriple ("thumbv7s-apple-ios"); return true; case 12: arch.SetTriple ("thumbv6-apple-ios"); return true; case 13: arch.SetTriple ("thumbv5-apple-ios"); return true; case 14: arch.SetTriple ("thumbv4t-apple-ios"); return true; case 15: arch.SetTriple ("thumb-apple-ios"); return true; default: break; } break; case ArchSpec::eCore_arm_armv7f: switch (idx) { case 0: arch.SetTriple ("armv7f-apple-ios"); return true; case 1: arch.SetTriple ("armv7-apple-ios"); return true; case 2: arch.SetTriple ("armv6-apple-ios"); return true; case 3: arch.SetTriple ("armv5-apple-ios"); return true; case 4: arch.SetTriple ("armv4-apple-ios"); return true; case 5: arch.SetTriple ("arm-apple-ios"); return true; case 6: arch.SetTriple ("thumbv7f-apple-ios"); return true; case 7: arch.SetTriple ("thumbv7-apple-ios"); return true; case 8: arch.SetTriple ("thumbv6-apple-ios"); return true; case 9: arch.SetTriple ("thumbv5-apple-ios"); return true; case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true; case 11: arch.SetTriple ("thumb-apple-ios"); return true; default: break; } break; case ArchSpec::eCore_arm_armv7k: switch (idx) { case 0: arch.SetTriple ("armv7k-apple-ios"); return true; case 1: arch.SetTriple ("armv7-apple-ios"); return true; case 2: arch.SetTriple ("armv6-apple-ios"); return true; case 3: arch.SetTriple ("armv5-apple-ios"); return true; case 4: arch.SetTriple ("armv4-apple-ios"); return true; case 5: arch.SetTriple ("arm-apple-ios"); return true; case 6: arch.SetTriple ("thumbv7k-apple-ios"); return true; case 7: arch.SetTriple ("thumbv7-apple-ios"); return true; case 8: arch.SetTriple ("thumbv6-apple-ios"); return true; case 9: arch.SetTriple ("thumbv5-apple-ios"); return true; case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true; case 11: arch.SetTriple ("thumb-apple-ios"); return true; default: break; } break; case ArchSpec::eCore_arm_armv7s: switch (idx) { case 0: arch.SetTriple ("armv7s-apple-ios"); return true; case 1: arch.SetTriple ("armv7-apple-ios"); return true; case 2: arch.SetTriple ("armv6-apple-ios"); return true; case 3: arch.SetTriple ("armv5-apple-ios"); return true; case 4: arch.SetTriple ("armv4-apple-ios"); return true; case 5: arch.SetTriple ("arm-apple-ios"); return true; case 6: arch.SetTriple ("thumbv7s-apple-ios"); return true; case 7: arch.SetTriple ("thumbv7-apple-ios"); return true; case 8: arch.SetTriple ("thumbv6-apple-ios"); return true; case 9: arch.SetTriple ("thumbv5-apple-ios"); return true; case 10: arch.SetTriple ("thumbv4t-apple-ios"); return true; case 11: arch.SetTriple ("thumb-apple-ios"); return true; default: break; } break; case ArchSpec::eCore_arm_armv7: switch (idx) { case 0: arch.SetTriple ("armv7-apple-ios"); return true; case 1: arch.SetTriple ("armv6-apple-ios"); return true; case 2: arch.SetTriple ("armv5-apple-ios"); return true; case 3: arch.SetTriple ("armv4-apple-ios"); return true; case 4: arch.SetTriple ("arm-apple-ios"); return true; case 5: arch.SetTriple ("thumbv7-apple-ios"); return true; case 6: arch.SetTriple ("thumbv6-apple-ios"); return true; case 7: arch.SetTriple ("thumbv5-apple-ios"); return true; case 8: arch.SetTriple ("thumbv4t-apple-ios"); return true; case 9: arch.SetTriple ("thumb-apple-ios"); return true; default: break; } break; case ArchSpec::eCore_arm_armv6: switch (idx) { case 0: arch.SetTriple ("armv6-apple-ios"); return true; case 1: arch.SetTriple ("armv5-apple-ios"); return true; case 2: arch.SetTriple ("armv4-apple-ios"); return true; case 3: arch.SetTriple ("arm-apple-ios"); return true; case 4: arch.SetTriple ("thumbv6-apple-ios"); return true; case 5: arch.SetTriple ("thumbv5-apple-ios"); return true; case 6: arch.SetTriple ("thumbv4t-apple-ios"); return true; case 7: arch.SetTriple ("thumb-apple-ios"); return true; default: break; } break; case ArchSpec::eCore_arm_armv5: switch (idx) { case 0: arch.SetTriple ("armv5-apple-ios"); return true; case 1: arch.SetTriple ("armv4-apple-ios"); return true; case 2: arch.SetTriple ("arm-apple-ios"); return true; case 3: arch.SetTriple ("thumbv5-apple-ios"); return true; case 4: arch.SetTriple ("thumbv4t-apple-ios"); return true; case 5: arch.SetTriple ("thumb-apple-ios"); return true; default: break; } break; case ArchSpec::eCore_arm_armv4: switch (idx) { case 0: arch.SetTriple ("armv4-apple-ios"); return true; case 1: arch.SetTriple ("arm-apple-ios"); return true; case 2: arch.SetTriple ("thumbv4t-apple-ios"); return true; case 3: arch.SetTriple ("thumb-apple-ios"); return true; default: break; } break; } arch.Clear(); return false; }
//---------------------------------------------------------------------- // 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; }