Make core files not crash when you load a core file into LLDB with just "lldb -c core".
To do this I added a few new ways to determine the OS from PT_NOTE notes in the ELF file: 1 - Look for "LINUX" notes which indicate "linux" should be the OS 2 - Look through the "CORE" notes with NT_FILE as the type and sniff data from the paths listed in this section. On Ubuntu they contain "/lib/x86_64-linux-gnu" which has the triple and allows us to set "linux" as the OS in the architecture returned from ObjectFileELF::GetArchitecture(). Setting the OS correctly allows us to get the triple correct so we can extract registers without asserting and killing LLDB. Also use the data from the NT_FILE to set the main executable if one isn't set in ProcessElfCore::DoLoadCore(). llvm-svn: 251537
This commit is contained in:
@@ -49,6 +49,8 @@ const char *const LLDB_NT_OWNER_GNU = "GNU";
|
||||
const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
|
||||
const char *const LLDB_NT_OWNER_CSR = "csr";
|
||||
const char *const LLDB_NT_OWNER_ANDROID = "Android";
|
||||
const char *const LLDB_NT_OWNER_CORE = "CORE";
|
||||
const char *const LLDB_NT_OWNER_LINUX = "LINUX";
|
||||
|
||||
// ELF note type definitions
|
||||
const elf_word LLDB_NT_FREEBSD_ABI_TAG = 0x01;
|
||||
@@ -67,6 +69,41 @@ const elf_word LLDB_NT_GNU_ABI_OS_LINUX = 0x00;
|
||||
const elf_word LLDB_NT_GNU_ABI_OS_HURD = 0x01;
|
||||
const elf_word LLDB_NT_GNU_ABI_OS_SOLARIS = 0x02;
|
||||
|
||||
// LLDB_NT_OWNER_CORE and LLDB_NT_OWNER_LINUX note contants
|
||||
#define NT_PRSTATUS 1
|
||||
#define NT_PRFPREG 2
|
||||
#define NT_PRPSINFO 3
|
||||
#define NT_TASKSTRUCT 4
|
||||
#define NT_AUXV 6
|
||||
#define NT_SIGINFO 0x53494749
|
||||
#define NT_FILE 0x46494c45
|
||||
#define NT_PRXFPREG 0x46e62b7f
|
||||
#define NT_PPC_VMX 0x100
|
||||
#define NT_PPC_SPE 0x101
|
||||
#define NT_PPC_VSX 0x102
|
||||
#define NT_386_TLS 0x200
|
||||
#define NT_386_IOPERM 0x201
|
||||
#define NT_X86_XSTATE 0x202
|
||||
#define NT_S390_HIGH_GPRS 0x300
|
||||
#define NT_S390_TIMER 0x301
|
||||
#define NT_S390_TODCMP 0x302
|
||||
#define NT_S390_TODPREG 0x303
|
||||
#define NT_S390_CTRS 0x304
|
||||
#define NT_S390_PREFIX 0x305
|
||||
#define NT_S390_LAST_BREAK 0x306
|
||||
#define NT_S390_SYSTEM_CALL 0x307
|
||||
#define NT_S390_TDB 0x308
|
||||
#define NT_S390_VXRS_LOW 0x309
|
||||
#define NT_S390_VXRS_HIGH 0x30a
|
||||
#define NT_ARM_VFP 0x400
|
||||
#define NT_ARM_TLS 0x401
|
||||
#define NT_ARM_HW_BREAK 0x402
|
||||
#define NT_ARM_HW_WATCH 0x403
|
||||
#define NT_ARM_SYSTEM_CALL 0x404
|
||||
#define NT_METAG_CBUF 0x500
|
||||
#define NT_METAG_RPIPE 0x501
|
||||
#define NT_METAG_TLS 0x502
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
/// @class ELFRelocation
|
||||
/// @brief Generic wrapper for ELFRel and ELFRela.
|
||||
@@ -1273,6 +1310,7 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
|
||||
while (true)
|
||||
{
|
||||
// Parse the note header. If this fails, bail out.
|
||||
const lldb::offset_t note_offset = offset;
|
||||
ELFNote note = ELFNote();
|
||||
if (!note.Parse(data, &offset))
|
||||
{
|
||||
@@ -1280,11 +1318,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
|
||||
return error;
|
||||
}
|
||||
|
||||
// If a tag processor handles the tag, it should set processed to true, and
|
||||
// the loop will assume the tag processing has moved entirely past the note's payload.
|
||||
// Otherwise, leave it false and the end of the loop will handle the offset properly.
|
||||
bool processed = false;
|
||||
|
||||
if (log)
|
||||
log->Printf ("ObjectFileELF::%s parsing note name='%s', type=%" PRIu32, __FUNCTION__, note.n_name.c_str (), note.n_type);
|
||||
|
||||
@@ -1293,9 +1326,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
|
||||
(note.n_type == LLDB_NT_FREEBSD_ABI_TAG) &&
|
||||
(note.n_descsz == LLDB_NT_FREEBSD_ABI_SIZE))
|
||||
{
|
||||
// We'll consume the payload below.
|
||||
processed = true;
|
||||
|
||||
// Pull out the min version info.
|
||||
uint32_t version_info;
|
||||
if (data.GetU32 (&offset, &version_info, 1) == nullptr)
|
||||
@@ -1326,9 +1356,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
|
||||
case LLDB_NT_GNU_ABI_TAG:
|
||||
if (note.n_descsz == LLDB_NT_GNU_ABI_SIZE)
|
||||
{
|
||||
// We'll consume the payload below.
|
||||
processed = true;
|
||||
|
||||
// Pull out the min OS version supporting the ABI.
|
||||
uint32_t version_info[4];
|
||||
if (data.GetU32 (&offset, &version_info[0], note.n_descsz / 4) == nullptr)
|
||||
@@ -1371,9 +1398,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
|
||||
// Only bother processing this if we don't already have the uuid set.
|
||||
if (!uuid.IsValid())
|
||||
{
|
||||
// We'll consume the payload below.
|
||||
processed = true;
|
||||
|
||||
// 16 bytes is UUID|MD5, 20 bytes is SHA1
|
||||
if ((note.n_descsz == 16 || note.n_descsz == 20))
|
||||
{
|
||||
@@ -1396,10 +1420,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
|
||||
(note.n_type == LLDB_NT_NETBSD_ABI_TAG) &&
|
||||
(note.n_descsz == LLDB_NT_NETBSD_ABI_SIZE))
|
||||
{
|
||||
|
||||
// We'll consume the payload below.
|
||||
processed = true;
|
||||
|
||||
// Pull out the min version info.
|
||||
uint32_t version_info;
|
||||
if (data.GetU32 (&offset, &version_info, 1) == nullptr)
|
||||
@@ -1419,8 +1439,6 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
|
||||
else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) &&
|
||||
(note.n_name == LLDB_NT_OWNER_CSR))
|
||||
{
|
||||
// We'll consume the payload below.
|
||||
processed = true;
|
||||
arch_spec.GetTriple().setOS(llvm::Triple::OSType::UnknownOS);
|
||||
arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::CSR);
|
||||
|
||||
@@ -1438,9 +1456,48 @@ ObjectFileELF::RefineModuleDetailsFromNote (lldb_private::DataExtractor &data, l
|
||||
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
|
||||
arch_spec.GetTriple().setEnvironment(llvm::Triple::EnvironmentType::Android);
|
||||
}
|
||||
else if (note.n_name == LLDB_NT_OWNER_LINUX)
|
||||
{
|
||||
// This is sometimes found in core files and usually contains extended register info
|
||||
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
|
||||
}
|
||||
else if (note.n_name == LLDB_NT_OWNER_CORE)
|
||||
{
|
||||
// Parse the NT_FILE to look for stuff in paths to shared libraries
|
||||
// As the contents look like:
|
||||
// count = 0x000000000000000a (10)
|
||||
// page_size = 0x0000000000001000 (4096)
|
||||
// Index start end file_ofs path
|
||||
// ===== ------------------ ------------------ ------------------ -------------------------------------
|
||||
// [ 0] 0x0000000000400000 0x0000000000401000 0x0000000000000000 /tmp/a.out
|
||||
// [ 1] 0x0000000000600000 0x0000000000601000 0x0000000000000000 /tmp/a.out
|
||||
// [ 2] 0x0000000000601000 0x0000000000602000 0x0000000000000001 /tmp/a.out
|
||||
// [ 3] 0x00007fa79c9ed000 0x00007fa79cba8000 0x0000000000000000 /lib/x86_64-linux-gnu/libc-2.19.so
|
||||
// [ 4] 0x00007fa79cba8000 0x00007fa79cda7000 0x00000000000001bb /lib/x86_64-linux-gnu/libc-2.19.so
|
||||
// [ 5] 0x00007fa79cda7000 0x00007fa79cdab000 0x00000000000001ba /lib/x86_64-linux-gnu/libc-2.19.so
|
||||
// [ 6] 0x00007fa79cdab000 0x00007fa79cdad000 0x00000000000001be /lib/x86_64-linux-gnu/libc-2.19.so
|
||||
// [ 7] 0x00007fa79cdb2000 0x00007fa79cdd5000 0x0000000000000000 /lib/x86_64-linux-gnu/ld-2.19.so
|
||||
// [ 8] 0x00007fa79cfd4000 0x00007fa79cfd5000 0x0000000000000022 /lib/x86_64-linux-gnu/ld-2.19.so
|
||||
// [ 9] 0x00007fa79cfd5000 0x00007fa79cfd6000 0x0000000000000023 /lib/x86_64-linux-gnu/ld-2.19.so
|
||||
if (note.n_type == NT_FILE)
|
||||
{
|
||||
uint64_t count = data.GetU64(&offset);
|
||||
offset += 8 + 3*8*count; // Skip page size and all start/end/file_ofs
|
||||
for (size_t i=0; i<count; ++i)
|
||||
{
|
||||
llvm::StringRef path(data.GetCStr(&offset));
|
||||
if (path.startswith("/lib/x86_64-linux-gnu"))
|
||||
{
|
||||
arch_spec.GetTriple().setOS(llvm::Triple::OSType::Linux);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!processed)
|
||||
offset += llvm::RoundUpToAlignment(note.n_descsz, 4);
|
||||
// Calculate the offset of the next note just in case "offset" has been used
|
||||
// to poke at the contents of the note data
|
||||
offset = note_offset + note.GetByteSize();
|
||||
}
|
||||
|
||||
return error;
|
||||
@@ -3147,6 +3204,27 @@ ObjectFileELF::GetArchitecture (ArchSpec &arch)
|
||||
ParseSectionHeaders();
|
||||
}
|
||||
|
||||
if (CalculateType() == eTypeCoreFile && m_arch_spec.TripleOSIsUnspecifiedUnknown())
|
||||
{
|
||||
// Core files don't have section headers yet they have PT_NOTE program headers
|
||||
// that might shed more light on the architecture
|
||||
if (ParseProgramHeaders())
|
||||
{
|
||||
for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i)
|
||||
{
|
||||
const elf::ELFProgramHeader* header = GetProgramHeaderByIndex(i);
|
||||
if (header && header->p_type == PT_NOTE && header->p_offset != 0 && header->p_filesz > 0)
|
||||
{
|
||||
DataExtractor data;
|
||||
if (data.SetData (m_data, header->p_offset, header->p_filesz) == header->p_filesz)
|
||||
{
|
||||
lldb_private::UUID uuid;
|
||||
RefineModuleDetailsFromNote (data, m_arch_spec, uuid);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
arch = m_arch_spec;
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user