summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2015-10-28 18:04:38 +0000
committerGreg Clayton <gclayton@apple.com>2015-10-28 18:04:38 +0000
commitb704b69e0bf6db0d0369ee84f7437d231a3fcfe9 (patch)
treeece8698e14cbb997b5de2e10cb1dbd0280c5174c /lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
parent06f4e43d290a107217f96cc0b6737cc3ee637c04 (diff)
downloadbcm5719-llvm-b704b69e0bf6db0d0369ee84f7437d231a3fcfe9.tar.gz
bcm5719-llvm-b704b69e0bf6db0d0369ee84f7437d231a3fcfe9.zip
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
Diffstat (limited to 'lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp')
-rw-r--r--lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp122
1 files changed, 100 insertions, 22 deletions
diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
index 88c1c97c61e..1accf13a668 100644
--- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
+++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
@@ -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;
}
OpenPOWER on IntegriCloud