[前][次][番号順一覧][スレッド一覧]

ruby-changes:63303

From: Aaron <ko1@a...>
Date: Fri, 9 Oct 2020 08:43:39 +0900 (JST)
Subject: [ruby-changes:63303] bca8952fc7 (master): Fix lldb disassembler so it works with core files

https://git.ruby-lang.org/ruby.git/commit/?id=bca8952fc7

From bca8952fc7e31e3d325e70368db2c83f4f701709 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <tenderlove@r...>
Date: Thu, 8 Oct 2020 16:29:17 -0700
Subject: Fix lldb disassembler so it works with core files

This fixes the lldb disassembler script so that it doesn't need a live
process when disassembling rb_iseq_t.  I also added the PC to the output
so you can tell what the VM is executing when it crashed.

For example:

```
(lldb) rbdisasm ec->cfp->iseq
PC             IDX  insn_name(operands)
0x56039f0a1720 0000 nop
0x56039f0a1728 0001 getlocal_WC_1( 5 )
0x56039f0a1738 0003 branchunless( 7 )
0x56039f0a1748 0005 getlocal_WC_0( 3 )
0x56039f0a1758 0007 putstring( (VALUE)0x56039f0c7eb8 )
0x56039f0a1768 0009 opt_send_without_block( (struct rb_call_data *)0x56039f09f140 )
0x56039f0a1778 0011 pop
0x56039f0a1780 0012 getglobal( ID: 0x7fd7 )
0x56039f0a1790 0014 branchunless( 7 )
0x56039f0a17a0 0016 getlocal_WC_0( 3 )
0x56039f0a17b0 0018 putstring( (VALUE)0x56039f0c7e90 )
0x56039f0a17c0 0020 opt_send_without_block( (struct rb_call_data *)0x56039f09f150 )
0x56039f0a17d0 0022 pop
0x56039f0a17d8 0023 getlocal_WC_0( 3 )
0x56039f0a17e8 0025 putobject( (VALUE)0x56039f0c7e68 )
0x56039f0a17f8 0027 getlocal_WC_1( 6 )
0x56039f0a1808 0029 dup
0x56039f0a1810 0030 checktype( 5 )
0x56039f0a1820 0032 branchif( 4 )
0x56039f0a1830 0034 dup
0x56039f0a1838 0035 opt_send_without_block( (struct rb_call_data *)0x56039f09f160 )
0x56039f0a1848 0037 tostring
0x56039f0a1850 0038 putobject( (VALUE)0x56039f0c7e40 )
0x56039f0a1860 0040 concatstrings( 3 )
0x56039f0a1870 0042 opt_send_without_block( (struct rb_call_data *)0x56039f09f170 )
0x56039f0a1880 0044 nop
0x56039f0a1888 0045 leave
(lldb) p ec->cfp->pc
(const VALUE *) $146 = 0x000056039f0a1848
```

Here we can see the VM is currently executing `opt_send_without_block`
(because the PC is one ahead of the current instruction)

diff --git a/misc/lldb_disasm.py b/misc/lldb_disasm.py
index 936d63f..b46d097 100644
--- a/misc/lldb_disasm.py
+++ b/misc/lldb_disasm.py
@@ -73,8 +73,14 @@ class IseqDissassembler: https://github.com/ruby/ruby/blob/trunk/misc/lldb_disasm.py#L73
         iseq_size = val.GetValueForExpressionPath("->body->iseq_size").GetValueAsUnsigned()
         iseqs = val.GetValueForExpressionPath("->body->iseq_encoded")
         idx = 0
+        print("PC             IDX  insn_name(operands) ", file=self.result)
         while idx < iseq_size:
-            idx += self.iseq_extract_values(self.debugger, self.target, self.process, self.result, iseqs, idx)
+            m = self.iseq_extract_values(self.debugger, self.target, self.process, self.result, iseqs, idx)
+            if m < 1:
+                print("Error decoding", file=self.result)
+                return
+            else:
+                idx += m
 
     def build_addr2insn(self, target):
         tIntPtr = target.FindFirstType("intptr_t")
@@ -98,16 +104,21 @@ class IseqDissassembler: https://github.com/ruby/ruby/blob/trunk/misc/lldb_disasm.py#L104
     def iseq_extract_values(self, debugger, target, process, result, iseqs, n):
         tValueP      = target.FindFirstType("VALUE")
         sizeofValueP = tValueP.GetByteSize()
-        insn = target.CreateValueFromAddress(
-                "i", lldb.SBAddress(iseqs.unsigned + (n * sizeofValueP), target), tValueP)
+        pc = iseqs.unsigned + (n * sizeofValueP)
+        insn = target.CreateValueFromAddress("i", lldb.SBAddress(pc, target), tValueP)
         addr         = insn.GetValueAsUnsigned()
         orig_insn    = self.rb_vm_insn_addr2insn2(target, result, addr)
 
         name     = self.insn_name(target, process, result, orig_insn)
         length   = self.insn_len(target, orig_insn)
-        op_types = bytes(self.insn_op_types(target, process, result, orig_insn), 'utf-8')
+        op_str = self.insn_op_types(target, process, result, orig_insn)
+        op_types = bytes(op_str, 'utf-8')
+
+        if length != (len(op_types) + 1):
+            print("error decoding iseqs", file=result)
+            return -1
 
-        print("%04d %s" % (n, name), file=result, end="")
+        print("%0#14x %04d %s" % (pc, n, name), file=result, end="")
 
         if length == 1:
             print("", file=result)
@@ -131,50 +142,81 @@ class IseqDissassembler: https://github.com/ruby/ruby/blob/trunk/misc/lldb_disasm.py#L142
     def insn_len(self, target, offset):
         size_of_char = self.tChar.GetByteSize()
 
-        addr_of_table = target.FindSymbols("insn_len.t")[0].GetSymbol().GetStartAddress().GetLoadAddress(target)
+        symbol = target.FindSymbols("insn_len.t")[0].GetSymbol()
+        section = symbol.GetStartAddress().GetSection()
+        addr_of_table = symbol.GetStartAddress().GetOffset()
 
-        addr_in_table = addr_of_table + (offset * size_of_char)
-        addr = lldb.SBAddress(addr_in_table, target)
+        error = lldb.SBError()
+        length = section.GetSectionData().GetUnsignedInt8(error, addr_of_table + (offset * size_of_char))
 
-        return target.CreateValueFromAddress("y", addr, self.tChar).GetValueAsUnsigned()
+        if error.Success():
+            return length
+        else:
+            print("error getting length: ", error)
 
     def insn_op_types(self, target, process, result, insn):
         tUShort = target.FindFirstType("unsigned short")
-        self.tChar   = target.FindFirstType("char")
 
         size_of_short = tUShort.GetByteSize()
         size_of_char =  self.tChar.GetByteSize()
 
-        addr_of_table = target.FindSymbols("insn_op_types.y")[0].GetSymbol().GetStartAddress().GetLoadAddress(target)
+        symbol = target.FindSymbols("insn_op_types.y")[0].GetSymbol()
+        section = symbol.GetStartAddress().GetSection()
+        addr_of_table = symbol.GetStartAddress().GetOffset()
+
         addr_in_table = addr_of_table + (insn * size_of_short)
-        addr = lldb.SBAddress(addr_in_table, target)
-        offset = target.CreateValueFromAddress("y", addr, tUShort).GetValueAsUnsigned()
 
-        addr_of_table = target.FindSymbols("insn_op_types.x")[0].GetSymbol().GetStartAddress().GetLoadAddress(target)
+        error = lldb.SBError()
+        offset = section.GetSectionData().GetUnsignedInt16(error, addr_in_table)
+
+        if not error.Success():
+            print("error getting op type offset: ", error)
+
+        symbol = target.FindSymbols("insn_op_types.x")[0].GetSymbol()
+        section = symbol.GetStartAddress().GetSection()
+        addr_of_table = symbol.GetStartAddress().GetOffset()
         addr_in_name_table = addr_of_table + (offset * size_of_char)
 
         error = lldb.SBError()
-        return process.ReadCStringFromMemory(addr_in_name_table, 256, error)
+        types = section.GetSectionData().GetString(error, addr_in_name_table)
+        if error.Success():
+            return types
+        else:
+            print("error getting op types: ", error)
 
     def insn_name_table_offset(self, target, offset):
         tUShort = target.FindFirstType("unsigned short")
         size_of_short = tUShort.GetByteSize()
 
-        addr_of_table = target.FindSymbols("insn_name.y")[0].GetSymbol().GetStartAddress().GetLoadAddress(target)
+        symbol = target.FindSymbols("insn_name.y")[0].GetSymbol()
+        section = symbol.GetStartAddress().GetSection()
+        table_offset = symbol.GetStartAddress().GetOffset()
+
+        table_offset = table_offset + (offset * size_of_short)
 
-        addr_in_table = addr_of_table + (offset * size_of_short)
-        addr = lldb.SBAddress(addr_in_table, target)
+        error = lldb.SBError()
+        offset = section.GetSectionData().GetUnsignedInt16(error, table_offset)
 
-        return target.CreateValueFromAddress("y", addr, tUShort).GetValueAsUnsigned()
+        if error.Success():
+            return offset
+        else:
+            print("error getting insn name table offset: ", error)
 
     def insn_name(self, target, process, result, offset):
-        tCharP = target.FindFirstType("char*")
-        addr_of_table = target.FindSymbols("insn_name.x")[0].GetSymbol().GetStartAddress().GetLoadAddress(target)
+        symbol = target.FindSymbols("insn_name.x")[0].GetSymbol()
+        section = symbol.GetStartAddress().GetSection()
+        addr_of_table = symbol.GetStartAddress().GetOffset()
+
+        name_table_offset = self.insn_name_table_offset(target, offset)
+        addr_in_name_table = addr_of_table + name_table_offset
 
-        addr_in_name_table = addr_of_table + self.insn_name_table_offset(target, offset)
-        addr = lldb.SBAddress(addr_in_name_table, target)
         error = lldb.SBError()
-        return process.ReadCStringFromMemory(addr_in_name_table, 256, error)
+        name = section.GetSectionData().GetString(error, addr_in_name_table)
+
+        if error.Success():
+            return name
+        else:
+            print('error getting insn name', error)
 
 def disasm(debugger, command, result, internal_dict):
     disassembler = IseqDissassembler(debugger, command, result, internal_dict)
-- 
cgit v0.10.2


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]