Index: packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py =================================================================== --- packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py +++ packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/TestLinuxCore.py @@ -21,10 +21,14 @@ _i386_pid = 32306 _x86_64_pid = 32259 _s390x_pid = 1045 + _mips64_n64_pid = 25619 + _mips64_n32_pid = 3670 + _mips_o32_pid = 3532 _i386_regions = 4 _x86_64_regions = 5 _s390x_regions = 2 + _mips_regions = 5 def setUp(self): super(LinuxCoreTestCase, self).setUp() @@ -40,6 +44,18 @@ """Test that lldb can read the process information from an i386 linux core file.""" self.do_test("linux-i386", self._i386_pid, self._i386_regions) + def test_mips_o32(self): + """Test that lldb can read the process information from an MIPS O32 linux core file.""" + self.do_test("linux-mipsel-gnuabio32", self._mips_o32_pid, self._mips_regions) + + def test_mips_n32(self): + """Test that lldb can read the process information from an MIPS N32 linux core file """ + self.do_test("linux-mips64el-gnuabin32", self._mips64_n32_pid, self._mips_regions) + + def test_mips_n64(self): + """Test that lldb can read the process information from an MIPS N64 linux core file """ + self.do_test("linux-mips64el-gnuabi64", self._mips64_n64_pid, self._mips_regions) + @skipIf(oslist=['windows']) @skipIf(triple='^mips') def test_x86_64(self): Index: source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp =================================================================== --- source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -287,10 +287,26 @@ return kal_arch_variant; } -static uint32_t mipsVariantFromElfFlags(const elf::elf_word e_flags, - uint32_t endian) { - const uint32_t mips_arch = e_flags & llvm::ELF::EF_MIPS_ARCH; +static uint32_t mipsVariantFromElfFlags (const elf::ELFHeader &header) { + const uint32_t mips_arch = header.e_flags & llvm::ELF::EF_MIPS_ARCH; + uint32_t endian = header.e_ident[EI_DATA]; uint32_t arch_variant = ArchSpec::eMIPSSubType_unknown; + uint32_t fileclass = header.e_ident[EI_CLASS]; + + // If there aren't any elf flags available (e.g core elf file) then return default + // 32 or 64 bit arch (without any architecture revision) based on object file's class. + if (header.e_type == ET_CORE) { + switch (fileclass) { + case llvm::ELF::ELFCLASS32: + return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips32el + : ArchSpec::eMIPSSubType_mips32; + case llvm::ELF::ELFCLASS64: + return (endian == ELFDATA2LSB) ? ArchSpec::eMIPSSubType_mips64el + : ArchSpec::eMIPSSubType_mips64; + default: + return arch_variant; + } + } switch (mips_arch) { case llvm::ELF::EF_MIPS_ARCH_1: @@ -325,7 +341,7 @@ static uint32_t subTypeFromElfHeader(const elf::ELFHeader &header) { if (header.e_machine == llvm::ELF::EM_MIPS) - return mipsVariantFromElfFlags(header.e_flags, header.e_ident[EI_DATA]); + return mipsVariantFromElfFlags(header); return llvm::ELF::EM_CSR_KALIMBA == header.e_machine ? kalimbaVariantFromElfFlags(header.e_flags) @@ -1348,6 +1364,10 @@ } break; } + if (arch_spec.IsMIPS() && + arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS) + // The note.n_name == LLDB_NT_OWNER_GNU is valid for Linux platform + arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); } // Process NetBSD ELF notes. else if ((note.n_name == LLDB_NT_OWNER_NETBSD) && @@ -1443,6 +1463,12 @@ break; } } + if (arch_spec.IsMIPS() && + arch_spec.GetTriple().getOS() == llvm::Triple::OSType::UnknownOS) + // In case of MIPSR6, the LLDB_NT_OWNER_GNU note is missing + // for some cases (e.g. compile with -nostdlib) + // Hence set OS to Linux + arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux); } } Index: source/Plugins/Process/elf-core/ProcessElfCore.cpp =================================================================== --- source/Plugins/Process/elf-core/ProcessElfCore.cpp +++ source/Plugins/Process/elf-core/ProcessElfCore.cpp @@ -214,9 +214,12 @@ // 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.IsValid()) - GetTarget().SetArchitecture(arch); + // In case of MIPS, Core file doesn't have architecture revision and ABI + // information. Hence we need to relied on target architecture for that. + if (arch.IsValid() && !arch.IsMIPS()) + GetTarget().SetArchitecture(arch); + SetUnixSignals(UnixSignals::Create(GetArchitecture())); // Ensure we found at least one thread that was stopped on a signal. @@ -370,6 +373,10 @@ lldb::addr_t bytes_left = 0; // Number of bytes available in the core file from the given address + // Don't proceed if core file doesn't contain the actual data for this address range. + if (file_start == file_end) + return 0; + // Figure out how many on-disk bytes remain in this segment // starting at the given offset if (file_end > file_start + offset) @@ -588,6 +595,8 @@ // The result from FXSAVE is in NT_PRXFPREG for i386 core files if (arch.GetCore() == ArchSpec::eCore_x86_64_x86_64) thread_data->fpregset = note_data; + else if(arch.IsMIPS()) + thread_data->fpregset = note_data; break; case NT_PRPSINFO: have_prpsinfo = true; @@ -655,6 +664,12 @@ (ObjectFileELF *)(m_core_module_sp->GetObjectFile()); ArchSpec arch; core_file->GetArchitecture(arch); + + ArchSpec target_arch = GetTarget().GetArchitecture(); + + if (target_arch.IsMIPS()) + return target_arch; + return arch; }