clayborg created this revision.
clayborg added reviewers: labath, aprantl.

Prior to this fix, ELF files might contain PT_LOAD program headers that had a 
valid p_vaddr, and a valid file p_offset, but the p_filesz would be zero. For 
example in 
llvm-project/lldb/test/testcases/functionalities/postmortem/elf-core/thread_crash/linux-i386.core
 we see:

  Program Headers:
  Index   p_type           p_flags    p_offset           p_vaddr            
p_paddr            p_filesz           p_memsz            p_align
  ======= ---------------- ---------- ------------------ ------------------ 
------------------ ------------------ ------------------ ------------------
  [    0] PT_NOTE          0x00000000 0x0000000000000474 0x0000000000000000 
0x0000000000000000 0x0000000000001940 0x0000000000000000 0x0000000000000000
  [    1] PT_LOAD          0x00000005 0x0000000000002000 0x0000000008048000 
0x0000000000000000 0x0000000000000000 0x0000000000003000 0x0000000000001000
  [    2] PT_LOAD          0x00000004 0x0000000000002000 0x000000000804b000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [    3] PT_LOAD          0x00000006 0x0000000000002000 0x000000000804c000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [    4] PT_LOAD          0x00000006 0x0000000000002000 0x0000000009036000 
0x0000000000000000 0x0000000000000000 0x0000000000025000 0x0000000000001000
  [    5] PT_LOAD          0x00000000 0x0000000000002000 0x00000000f63a1000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [    6] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f63a2000 
0x0000000000000000 0x0000000000000000 0x0000000000800000 0x0000000000001000
  [    7] PT_LOAD          0x00000000 0x0000000000002000 0x00000000f6ba2000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [    8] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f6ba3000 
0x0000000000000000 0x0000000000000000 0x0000000000804000 0x0000000000001000
  [    9] PT_LOAD          0x00000005 0x0000000000002000 0x00000000f73a7000 
0x0000000000000000 0x0000000000000000 0x00000000001b1000 0x0000000000001000
  [   10] PT_LOAD          0x00000004 0x0000000000002000 0x00000000f7558000 
0x0000000000000000 0x0000000000000000 0x0000000000002000 0x0000000000001000
  [   11] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f755a000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   12] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f755b000 
0x0000000000000000 0x0000000000000000 0x0000000000003000 0x0000000000001000
  [   13] PT_LOAD          0x00000005 0x0000000000002000 0x00000000f755e000 
0x0000000000000000 0x0000000000000000 0x0000000000019000 0x0000000000001000
  [   14] PT_LOAD          0x00000004 0x0000000000002000 0x00000000f7577000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   15] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f7578000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   16] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f7579000 
0x0000000000000000 0x0000000000000000 0x0000000000002000 0x0000000000001000
  [   17] PT_LOAD          0x00000005 0x0000000000002000 0x00000000f757b000 
0x0000000000000000 0x0000000000000000 0x000000000001c000 0x0000000000001000
  [   18] PT_LOAD          0x00000004 0x0000000000002000 0x00000000f7597000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   19] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f7598000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   20] PT_LOAD          0x00000005 0x0000000000002000 0x00000000f7599000 
0x0000000000000000 0x0000000000000000 0x0000000000053000 0x0000000000001000
  [   21] PT_LOAD          0x00000004 0x0000000000002000 0x00000000f75ec000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   22] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f75ed000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   23] PT_LOAD          0x00000005 0x0000000000002000 0x00000000f75ee000 
0x0000000000000000 0x0000000000000000 0x0000000000176000 0x0000000000001000
  [   24] PT_LOAD          0x00000004 0x0000000000002000 0x00000000f7764000 
0x0000000000000000 0x0000000000000000 0x0000000000006000 0x0000000000001000
  [   25] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f776a000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   26] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f776b000 
0x0000000000000000 0x0000000000000000 0x0000000000003000 0x0000000000001000
  [   27] PT_LOAD          0x00000006 0x0000000000002000 0x00000000f778a000 
0x0000000000000000 0x0000000000000000 0x0000000000002000 0x0000000000001000
  [   28] PT_LOAD          0x00000004 0x0000000000002000 0x00000000f778c000 
0x0000000000000000 0x0000000000002000 0x0000000000002000 0x0000000000001000
  [   29] PT_LOAD          0x00000005 0x0000000000004000 0x00000000f778e000 
0x0000000000000000 0x0000000000002000 0x0000000000002000 0x0000000000001000
  [   30] PT_LOAD          0x00000005 0x0000000000006000 0x00000000f7790000 
0x0000000000000000 0x0000000000000000 0x0000000000022000 0x0000000000001000
  [   31] PT_LOAD          0x00000004 0x0000000000006000 0x00000000f77b3000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   32] PT_LOAD          0x00000006 0x0000000000006000 0x00000000f77b4000 
0x0000000000000000 0x0000000000000000 0x0000000000001000 0x0000000000001000
  [   33] PT_LOAD          0x00000006 0x0000000000006000 0x00000000ffa25000 
0x0000000000000000 0x0000000000000000 0x0000000000022000 0x0000000000001000

Prior to this fix if users tried to read memory from one of these addresses 
like 0x8048000, they would end up incorrectly reading from the next memory 
region that actually had a p_filesz which would be 0x00000000f778c000 in this 
case. This fix correctly doesn't include program headers with zero p_filesz in 
the ProcessELFCore::m_core_aranges that is used to read memory. I found two 
cores files that have this same issue and added tests.


https://reviews.llvm.org/D67370

Files:
  
lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
  lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp


Index: lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
===================================================================
--- lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -118,16 +118,20 @@
   FileRange file_range(header.p_offset, header.p_filesz);
   VMRangeToFileOffset::Entry range_entry(addr, header.p_memsz, file_range);
 
-  VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
-  if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
-      last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
-      last_entry->GetByteSize() == last_entry->data.GetByteSize()) {
-    last_entry->SetRangeEnd(range_entry.GetRangeEnd());
-    last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
-  } else {
-    m_core_aranges.Append(range_entry);
+  // Only add to m_core_aranges if the file size is non zero. Some core files
+  // have PT_LOAD segments for all address ranges, but set f_filesz to zero for
+  // the .text sections since they can be retrieved from the object files.
+  if (header.p_filesz > 0) {
+    VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
+    if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() 
&&
+        last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
+        last_entry->GetByteSize() == last_entry->data.GetByteSize()) {
+      last_entry->SetRangeEnd(range_entry.GetRangeEnd());
+      last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
+    } else {
+      m_core_aranges.Append(range_entry);
+    }
   }
-
   // Keep a separate map of permissions that that isn't coalesced so all ranges
   // are maintained.
   const uint32_t permissions =
Index: 
lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
===================================================================
--- 
lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
+++ 
lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
@@ -51,6 +51,17 @@
         self.assertEqual(process.GetProcessID(), pid)
 
         for thread in process:
+            # Verify that if we try to read memory from a PT_LOAD that has
+            # p_filesz of zero that we don't get bytes from the next section
+            # that actually did have bytes. The addresses below were found by
+            # dumping the program headers of linux-i386.core and
+            # linux-x86_64.core and verifying that they had a p_filesz of zero.
+            mem_err = lldb.SBError()
+            if process.GetAddressByteSize() == 4:
+                bytes_read = process.ReadMemory(0x8048000, 4, mem_err)
+            else:
+                bytes_read = process.ReadMemory(0x400000, 4, mem_err)
+            self.assertEqual(bytes_read, None)
             reason = thread.GetStopReason()
             if( thread.GetThreadID() == tid ):
                 self.assertEqual(reason, lldb.eStopReasonSignal)


Index: lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
===================================================================
--- lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -118,16 +118,20 @@
   FileRange file_range(header.p_offset, header.p_filesz);
   VMRangeToFileOffset::Entry range_entry(addr, header.p_memsz, file_range);
 
-  VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
-  if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
-      last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
-      last_entry->GetByteSize() == last_entry->data.GetByteSize()) {
-    last_entry->SetRangeEnd(range_entry.GetRangeEnd());
-    last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
-  } else {
-    m_core_aranges.Append(range_entry);
+  // Only add to m_core_aranges if the file size is non zero. Some core files
+  // have PT_LOAD segments for all address ranges, but set f_filesz to zero for
+  // the .text sections since they can be retrieved from the object files.
+  if (header.p_filesz > 0) {
+    VMRangeToFileOffset::Entry *last_entry = m_core_aranges.Back();
+    if (last_entry && last_entry->GetRangeEnd() == range_entry.GetRangeBase() &&
+        last_entry->data.GetRangeEnd() == range_entry.data.GetRangeBase() &&
+        last_entry->GetByteSize() == last_entry->data.GetByteSize()) {
+      last_entry->SetRangeEnd(range_entry.GetRangeEnd());
+      last_entry->data.SetRangeEnd(range_entry.data.GetRangeEnd());
+    } else {
+      m_core_aranges.Append(range_entry);
+    }
   }
-
   // Keep a separate map of permissions that that isn't coalesced so all ranges
   // are maintained.
   const uint32_t permissions =
Index: lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
+++ lldb/packages/Python/lldbsuite/test/functionalities/postmortem/elf-core/thread_crash/TestLinuxCoreThreads.py
@@ -51,6 +51,17 @@
         self.assertEqual(process.GetProcessID(), pid)
 
         for thread in process:
+            # Verify that if we try to read memory from a PT_LOAD that has
+            # p_filesz of zero that we don't get bytes from the next section
+            # that actually did have bytes. The addresses below were found by
+            # dumping the program headers of linux-i386.core and
+            # linux-x86_64.core and verifying that they had a p_filesz of zero.
+            mem_err = lldb.SBError()
+            if process.GetAddressByteSize() == 4:
+                bytes_read = process.ReadMemory(0x8048000, 4, mem_err)
+            else:
+                bytes_read = process.ReadMemory(0x400000, 4, mem_err)
+            self.assertEqual(bytes_read, None)
             reason = thread.GetStopReason()
             if( thread.GetThreadID() == tid ):
                 self.assertEqual(reason, lldb.eStopReasonSignal)
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to