This revision was automatically updated to reflect the committed changes.
Closed by commit rL304976: Fix backtrace of noreturn functions situated at the 
end of a module (authored by labath).

Changed prior to commit:
  https://reviews.llvm.org/D32022?vs=101555&id=101900#toc

Repository:
  rL LLVM

https://reviews.llvm.org/D32022

Files:
  lldb/trunk/include/lldb/Core/Address.h
  lldb/trunk/include/lldb/Core/Section.h
  lldb/trunk/include/lldb/Target/SectionLoadList.h
  
lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py
  
lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c
  
lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py
  
lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s
  
lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.core
  
lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/test.out
  lldb/trunk/source/Core/Address.cpp
  lldb/trunk/source/Core/Section.cpp
  lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
  lldb/trunk/source/Target/SectionLoadList.cpp
  lldb/trunk/source/Target/StackFrame.cpp

Index: lldb/trunk/include/lldb/Core/Address.h
===================================================================
--- lldb/trunk/include/lldb/Core/Address.h
+++ lldb/trunk/include/lldb/Core/Address.h
@@ -422,18 +422,24 @@
   ///     a section + offset. The Target's SectionLoadList object
   ///     is used to resolve the address.
   ///
+  /// @param[in] allow_section_end
+  ///     If true, treat an address pointing to the end of the module as
+  ///     belonging to that module.
+  ///
   /// @return
   ///     Returns \b true if the load address was resolved to be
   ///     section/offset, \b false otherwise. It is often ok for an
   ///     address no not resolve to a section in a module, this often
   ///     happens for JIT'ed code, or any load addresses on the stack
   ///     or heap.
   //------------------------------------------------------------------
-  bool SetLoadAddress(lldb::addr_t load_addr, Target *target);
+  bool SetLoadAddress(lldb::addr_t load_addr, Target *target,
+                      bool allow_section_end = false);
 
   bool SetOpcodeLoadAddress(
       lldb::addr_t load_addr, Target *target,
-      lldb::AddressClass addr_class = lldb::eAddressClassInvalid);
+      lldb::AddressClass addr_class = lldb::eAddressClassInvalid,
+      bool allow_section_end = false);
 
   bool SetCallableLoadAddress(lldb::addr_t load_addr, Target *target);
 
Index: lldb/trunk/include/lldb/Core/Section.h
===================================================================
--- lldb/trunk/include/lldb/Core/Section.h
+++ lldb/trunk/include/lldb/Core/Section.h
@@ -143,7 +143,8 @@
 
   lldb::addr_t GetLoadBaseAddress(Target *target) const;
 
-  bool ResolveContainedAddress(lldb::addr_t offset, Address &so_addr) const;
+  bool ResolveContainedAddress(lldb::addr_t offset, Address &so_addr,
+                               bool allow_section_end = false) const;
 
   lldb::offset_t GetFileOffset() const { return m_file_offset; }
 
Index: lldb/trunk/include/lldb/Target/SectionLoadList.h
===================================================================
--- lldb/trunk/include/lldb/Target/SectionLoadList.h
+++ lldb/trunk/include/lldb/Target/SectionLoadList.h
@@ -47,7 +47,8 @@
 
   lldb::addr_t GetSectionLoadAddress(const lldb::SectionSP &section_sp) const;
 
-  bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr) const;
+  bool ResolveLoadAddress(lldb::addr_t load_addr, Address &so_addr,
+                          bool allow_section_end = false) const;
 
   bool SetSectionLoadAddress(const lldb::SectionSP &section_sp,
                              lldb::addr_t load_addr,
Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s
===================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/a.s
@@ -0,0 +1,35 @@
+# compile this with:
+# as a.s -o a.o --32 && ld a.o -m elf_i386
+# generate core file with:
+# ulimit -s 12 && ./a.out
+
+.text
+
+.globl func2
+.type func2, @function
+func2:
+  pushl %ebp
+  movl  %esp, %ebp
+  movl  0,    %eax
+  popl  %ebp
+  ret
+.size func2, .-func2
+
+.globl _start
+.type _start, @function
+_start:
+  pushl %ebp
+  movl  %esp, %ebp
+  call  func1
+  popl  %ebp
+  ret
+.size _start, .-_start
+
+.globl func1
+.type func1, @function
+func1:
+  pushl %ebp
+  movl  %esp, %ebp
+  call  func2
+.size func1, .-func1
+
Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py
===================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/module-end/TestNoReturnModuleEnd.py
@@ -0,0 +1,53 @@
+"""
+Test that we properly display the backtrace when a noreturn function happens to
+be at the end of the stack.
+"""
+
+from __future__ import print_function
+
+import shutil
+import struct
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestNoreturnModuleEnd(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+    mydir = TestBase.compute_mydir(__file__)
+
+    def setUp(self):
+        super(TestNoreturnModuleEnd, self).setUp()
+        self._initial_platform = lldb.DBG.GetSelectedPlatform()
+
+    def tearDown(self):
+        lldb.DBG.SetSelectedPlatform(self._initial_platform)
+        super(TestNoreturnModuleEnd, self).tearDown()
+
+    def test(self):
+        target = self.dbg.CreateTarget("test.out")
+        process = target.LoadCore("test.core")
+        self.assertTrue(process.IsValid(), PROCESS_IS_VALID)
+        self.assertEqual(process.GetNumThreads(), 1)
+
+        thread = process.GetSelectedThread()
+        self.assertTrue(thread.IsValid())
+
+        backtrace = [
+            ["func2", 3],
+            ["func1", 8],
+            ["_start", 8],
+        ]
+        self.assertEqual(thread.GetNumFrames(), len(backtrace))
+        for i in range(len(backtrace)):
+            frame = thread.GetFrameAtIndex(i)
+            self.assertTrue(frame.IsValid())
+            symbol = frame.GetSymbol()
+            self.assertTrue(symbol.IsValid())
+            self.assertEqual(symbol.GetName(), backtrace[i][0])
+            function_start = symbol.GetStartAddress().GetLoadAddress(target)
+            self.assertEquals(function_start + backtrace[i][1], frame.GetPC())
+
+        self.dbg.DeleteTarget(target)
Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py
===================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/TestNoreturnUnwind.py
@@ -17,8 +17,6 @@
     mydir = TestBase.compute_mydir(__file__)
 
     @skipIfWindows  # clang-cl does not support gcc style attributes.
-    @expectedFailureAndroid(bugnumber="llvm.org/pr31192")
-    @expectedFailureAll(bugnumber="llvm.org/pr31192", oslist=['linux'], compiler="gcc", archs=['arm'])
     def test(self):
         """Test that we can backtrace correctly with 'noreturn' functions on the stack"""
         self.build()
Index: lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c
===================================================================
--- lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c
+++ lldb/trunk/packages/Python/lldbsuite/test/functionalities/unwind/noreturn/main.c
@@ -29,8 +29,6 @@
 int
 main (int argc, char *argv[])
 {
-    sleep (2);
-
 	func_a ();
 
 	return 0;
Index: lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
+++ lldb/trunk/source/Plugins/Process/Utility/RegisterContextLLDB.cpp
@@ -329,7 +329,8 @@
   if (abi)
     pc = abi->FixCodeAddress(pc);
 
-  m_current_pc.SetLoadAddress(pc, &process->GetTarget());
+  const bool allow_section_end = true;
+  m_current_pc.SetLoadAddress(pc, &process->GetTarget(), allow_section_end);
 
   // If we don't have a Module for some reason, we're not going to find
   // symbol/function information - just
@@ -477,11 +478,12 @@
   // Or if we're in the middle of the stack (and not "above" an asynchronous
   // event like sigtramp),
   // and our "current" pc is the start of a function...
-  if (m_sym_ctx_valid && GetNextFrame()->m_frame_type != eTrapHandlerFrame &&
+  if (GetNextFrame()->m_frame_type != eTrapHandlerFrame &&
       GetNextFrame()->m_frame_type != eDebuggerFrame &&
-      addr_range.GetBaseAddress().IsValid() &&
-      addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() &&
-      addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()) {
+      (!m_sym_ctx_valid ||
+       (addr_range.GetBaseAddress().IsValid() &&
+        addr_range.GetBaseAddress().GetSection() == m_current_pc.GetSection() &&
+        addr_range.GetBaseAddress().GetOffset() == m_current_pc.GetOffset()))) {
     decr_pc_and_recompute_addr_range = true;
   }
 
Index: lldb/trunk/source/Core/Address.cpp
===================================================================
--- lldb/trunk/source/Core/Address.cpp
+++ lldb/trunk/source/Core/Address.cpp
@@ -361,8 +361,9 @@
 }
 
 bool Address::SetOpcodeLoadAddress(lldb::addr_t load_addr, Target *target,
-                                   AddressClass addr_class) {
-  if (SetLoadAddress(load_addr, target)) {
+                                   AddressClass addr_class,
+                                   bool allow_section_end) {
+  if (SetLoadAddress(load_addr, target, allow_section_end)) {
     if (target) {
       if (addr_class == eAddressClassInvalid)
         addr_class = GetAddressClass();
@@ -1001,9 +1002,10 @@
   return eAddressClassUnknown;
 }
 
-bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target) {
-  if (target &&
-      target->GetSectionLoadList().ResolveLoadAddress(load_addr, *this))
+bool Address::SetLoadAddress(lldb::addr_t load_addr, Target *target,
+                             bool allow_section_end) {
+  if (target && target->GetSectionLoadList().ResolveLoadAddress(
+                    load_addr, *this, allow_section_end))
     return true;
   m_section_wp.reset();
   m_offset = load_addr;
Index: lldb/trunk/source/Core/Section.cpp
===================================================================
--- lldb/trunk/source/Core/Section.cpp
+++ lldb/trunk/source/Core/Section.cpp
@@ -220,18 +220,18 @@
   return load_base_addr;
 }
 
-bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr) const {
+bool Section::ResolveContainedAddress(addr_t offset, Address &so_addr,
+                                      bool allow_section_end) const {
   const size_t num_children = m_children.GetSize();
-  if (num_children > 0) {
-    for (size_t i = 0; i < num_children; i++) {
-      Section *child_section = m_children.GetSectionAtIndex(i).get();
-
-      addr_t child_offset = child_section->GetOffset();
-      if (child_offset <= offset &&
-          offset - child_offset < child_section->GetByteSize())
-        return child_section->ResolveContainedAddress(offset - child_offset,
-                                                      so_addr);
-    }
+  for (size_t i = 0; i < num_children; i++) {
+    Section *child_section = m_children.GetSectionAtIndex(i).get();
+
+    addr_t child_offset = child_section->GetOffset();
+    if (child_offset <= offset &&
+        offset - child_offset <
+            child_section->GetByteSize() + (allow_section_end ? 1 : 0))
+      return child_section->ResolveContainedAddress(offset - child_offset,
+                                                    so_addr, allow_section_end);
   }
   so_addr.SetOffset(offset);
   so_addr.SetSection(const_cast<Section *>(this)->shared_from_this());
Index: lldb/trunk/source/Target/StackFrame.cpp
===================================================================
--- lldb/trunk/source/Target/StackFrame.cpp
+++ lldb/trunk/source/Target/StackFrame.cpp
@@ -191,9 +191,10 @@
     if (thread_sp) {
       TargetSP target_sp(thread_sp->CalculateTarget());
       if (target_sp) {
+        const bool allow_section_end = true;
         if (m_frame_code_addr.SetOpcodeLoadAddress(
                 m_frame_code_addr.GetOffset(), target_sp.get(),
-                eAddressClassCode)) {
+                eAddressClassCode, allow_section_end)) {
           ModuleSP module_sp(m_frame_code_addr.GetModule());
           if (module_sp) {
             m_sc.module_sp = module_sp;
Index: lldb/trunk/source/Target/SectionLoadList.cpp
===================================================================
--- lldb/trunk/source/Target/SectionLoadList.cpp
+++ lldb/trunk/source/Target/SectionLoadList.cpp
@@ -207,8 +207,8 @@
   return erased;
 }
 
-bool SectionLoadList::ResolveLoadAddress(addr_t load_addr,
-                                         Address &so_addr) const {
+bool SectionLoadList::ResolveLoadAddress(addr_t load_addr, Address &so_addr,
+                                         bool allow_section_end) const {
   // First find the top level section that this load address exists in
   std::lock_guard<std::recursive_mutex> guard(m_mutex);
   if (!m_addr_to_sect.empty()) {
@@ -220,10 +220,11 @@
       const addr_t pos_load_addr = pos->first;
       if (load_addr >= pos_load_addr) {
         addr_t offset = load_addr - pos_load_addr;
-        if (offset < pos->second->GetByteSize()) {
+        if (offset < pos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
           // We have found the top level section, now we need to find the
           // deepest child section.
-          return pos->second->ResolveContainedAddress(offset, so_addr);
+          return pos->second->ResolveContainedAddress(offset, so_addr,
+                                                      allow_section_end);
         }
       }
     } else {
@@ -233,10 +234,12 @@
           m_addr_to_sect.rbegin();
       if (load_addr >= rpos->first) {
         addr_t offset = load_addr - rpos->first;
-        if (offset < rpos->second->GetByteSize()) {
+        if (offset <
+            rpos->second->GetByteSize() + (allow_section_end ? 1 : 0)) {
           // We have found the top level section, now we need to find the
           // deepest child section.
-          return rpos->second->ResolveContainedAddress(offset, so_addr);
+          return rpos->second->ResolveContainedAddress(offset, so_addr,
+                                                       allow_section_end);
         }
       }
     }
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to