labath created this revision.
labath added a reviewer: jasonmolenda.
labath added a subscriber: lldb-commits.

This adds the knowledge of the DW_CFA_GNU_args_size instruction to the eh_frame 
parsing code.
Right now it is ignored as I am unsure how is it supposed to be handled, but 
now we are at least
able to parse the rest of the FDE containing this instruction.

I also add a fix for a bug which was exposed by this instruction. Namely, a 
mismatched sequence
of remember/restore instructions in the input could cause us to pop an empty 
stack and crash. Now
we just log the error and ignore the offending instruction.

http://reviews.llvm.org/D22266

Files:
  source/Symbol/DWARFCallFrameInfo.cpp

Index: source/Symbol/DWARFCallFrameInfo.cpp
===================================================================
--- source/Symbol/DWARFCallFrameInfo.cpp
+++ source/Symbol/DWARFCallFrameInfo.cpp
@@ -408,6 +408,7 @@
 bool
 DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address 
startaddr, UnwindPlan& unwind_plan)
 {
+    Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND);
     lldb::offset_t offset = dwarf_offset;
     lldb::offset_t current_entry = offset;
 
@@ -648,13 +649,32 @@
                         // the stack and place them in the current row. (This 
operation is
                         // useful for compilers that move epilogue code into 
the body of a
                         // function.)
+                        if (stack.empty())
+                        {
+                            if (log)
+                                log->Printf(
+                                    "DWARFCallFrameInfo::%s(dwarf_offset: %" 
PRIx32 ", startaddr: %" PRIx64
+                                    " encountered DW_CFA_restore_state but 
state stack is empty. Corrupt unwind info?",
+                                    __FUNCTION__, dwarf_offset, 
startaddr.GetFileAddress());
+                            break;
+                        }
                         lldb::addr_t offset = row->GetOffset ();
                         row = stack.back ();
                         stack.pop_back ();
                         row->SetOffset (offset);
                         break;
                     }
 
+                    case DW_CFA_GNU_args_size: // 0x2e
+                    {
+                        // The DW_CFA_GNU_args_size instruction takes an 
unsigned LEB128 operand
+                        // representing an argument size. This instruction 
specifies the total of
+                        // the size of the arguments which have been pushed 
onto the stack.
+
+                        // TODO: Figure out how we should handle this.
+                        m_cfi_data.GetULEB128(&offset);
+                    }
+
                     case DW_CFA_val_offset          :   // 0x14
                     case DW_CFA_val_offset_sf       :   // 0x15
                     default:


Index: source/Symbol/DWARFCallFrameInfo.cpp
===================================================================
--- source/Symbol/DWARFCallFrameInfo.cpp
+++ source/Symbol/DWARFCallFrameInfo.cpp
@@ -408,6 +408,7 @@
 bool
 DWARFCallFrameInfo::FDEToUnwindPlan (dw_offset_t dwarf_offset, Address startaddr, UnwindPlan& unwind_plan)
 {
+    Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_UNWIND);
     lldb::offset_t offset = dwarf_offset;
     lldb::offset_t current_entry = offset;
 
@@ -648,13 +649,32 @@
                         // the stack and place them in the current row. (This operation is
                         // useful for compilers that move epilogue code into the body of a
                         // function.)
+                        if (stack.empty())
+                        {
+                            if (log)
+                                log->Printf(
+                                    "DWARFCallFrameInfo::%s(dwarf_offset: %" PRIx32 ", startaddr: %" PRIx64
+                                    " encountered DW_CFA_restore_state but state stack is empty. Corrupt unwind info?",
+                                    __FUNCTION__, dwarf_offset, startaddr.GetFileAddress());
+                            break;
+                        }
                         lldb::addr_t offset = row->GetOffset ();
                         row = stack.back ();
                         stack.pop_back ();
                         row->SetOffset (offset);
                         break;
                     }
 
+                    case DW_CFA_GNU_args_size: // 0x2e
+                    {
+                        // The DW_CFA_GNU_args_size instruction takes an unsigned LEB128 operand
+                        // representing an argument size. This instruction specifies the total of
+                        // the size of the arguments which have been pushed onto the stack.
+
+                        // TODO: Figure out how we should handle this.
+                        m_cfi_data.GetULEB128(&offset);
+                    }
+
                     case DW_CFA_val_offset          :   // 0x14
                     case DW_CFA_val_offset_sf       :   // 0x15
                     default:
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to