lldb: debug info test, lldb plugin, readme
This commit is contained in:
137
_lldb/README.md
137
_lldb/README.md
@@ -12,15 +12,16 @@ llgo build -o cl/_testdata/debug/out -dbg ./cl/_testdata/debug
|
|||||||
lldb -O "command script import _lldb/llgo_plugin.py" ./cl/_testdata/debug/out
|
lldb -O "command script import _lldb/llgo_plugin.py" ./cl/_testdata/debug/out
|
||||||
```
|
```
|
||||||
|
|
||||||
```lldb
|
```shell
|
||||||
/opt/homebrew/bin/lldb -O "command script import _lldb/llgo_plugin.py" ./cl/_testdata/debug/out
|
/opt/homebrew/bin/lldb -O "command script import _lldb/llgo_plugin.py" ./cl/_testdata/debug/out
|
||||||
|
# github.com/goplus/llgo/cl/_testdata/debug
|
||||||
Breakpoint 1: no locations (pending).
|
Breakpoint 1: no locations (pending).
|
||||||
Breakpoint set in dummy target, will get copied into future targets.
|
Breakpoint set in dummy target, will get copied into future targets.
|
||||||
(lldb) command script import _lldb/llgo_plugin.py
|
(lldb) command script import _lldb/llgo_plugin.py
|
||||||
(lldb) target create "./cl/_testdata/debug/out"
|
(lldb) target create "./cl/_testdata/debug/out"
|
||||||
Current executable set to '/Users/lijie/source/goplus/llgo/cl/_testdata/debug/out' (arm64).
|
Current executable set to '/Users/lijie/source/goplus/llgo/cl/_testdata/debug/out' (arm64).
|
||||||
(lldb) r
|
(lldb) r
|
||||||
Process 16088 launched: '/Users/lijie/source/goplus/llgo/cl/_testdata/debug/out' (arm64)
|
Process 21992 launched: '/Users/lijie/source/goplus/llgo/cl/_testdata/debug/out' (arm64)
|
||||||
globalInt: 301
|
globalInt: 301
|
||||||
s: 0x100123e40
|
s: 0x100123e40
|
||||||
0x100123be0
|
0x100123be0
|
||||||
@@ -32,7 +33,7 @@ called function with struct
|
|||||||
called function with types
|
called function with types
|
||||||
0x100123e40
|
0x100123e40
|
||||||
0x1000343d0
|
0x1000343d0
|
||||||
Process 16088 stopped
|
Process 21992 stopped
|
||||||
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
|
* thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
|
||||||
frame #0: 0x000000010001b3b4 out`main at in.go:225:12
|
frame #0: 0x000000010001b3b4 out`main at in.go:225:12
|
||||||
222 // s.i8: '\x01'
|
222 // s.i8: '\x01'
|
||||||
@@ -45,80 +46,68 @@ Process 16088 stopped
|
|||||||
(lldb) v
|
(lldb) v
|
||||||
var i int = <variable not available>
|
var i int = <variable not available>
|
||||||
var s github.com/goplus/llgo/cl/_testdata/debug.StructWithAllTypeFields = {
|
var s github.com/goplus/llgo/cl/_testdata/debug.StructWithAllTypeFields = {
|
||||||
i8: '\x12',
|
i8 = '\x12',
|
||||||
i16: 2,
|
i16 = 2,
|
||||||
i32: 3,
|
i32 = 3,
|
||||||
i64: 4,
|
i64 = 4,
|
||||||
i: 5,
|
i = 5,
|
||||||
u8: '\x06',
|
u8 = '\x06',
|
||||||
u16: 7,
|
u16 = 7,
|
||||||
u32: 8,
|
u32 = 8,
|
||||||
u64: 9,
|
u64 = 9,
|
||||||
u: 10,
|
u = 10,
|
||||||
f32: 11,
|
f32 = 11,
|
||||||
f64: 12,
|
f64 = 12,
|
||||||
b: true,
|
b = true,
|
||||||
c64: { real: 13, imag: 14 },
|
c64 = {real = 13, imag = 14},
|
||||||
c128: { real: 15, imag: 16 },
|
c128 = {real = 15, imag = 16},
|
||||||
slice: []int{
|
slice = []int{21, 22, 23},
|
||||||
21, 22, 23
|
arr = [3]int{24, 25, 26},
|
||||||
},
|
arr2 = [3]github.com/goplus/llgo/cl/_testdata/debug.E{{i = 27}, {i = 28}, {i = 29}},
|
||||||
arr: [3]int{
|
s = "hello",
|
||||||
24, 25, 26,
|
e = {i = 30},
|
||||||
},
|
pf = 0x0000000100123d10,
|
||||||
arr2: [3]github.com/goplus/llgo/cl/_testdata/debug.E{
|
pi = 0x00000001001149e0,
|
||||||
{ i: 27 }, { i: 28 }, { i: 29 },
|
intr = {type = 0x0000000100116810, data = 0x00000001001149d0},
|
||||||
},
|
m = {count = 4296130304},
|
||||||
s: "hello",
|
c = {},
|
||||||
e: { i: 30 },
|
err = {type = 0x0000000100116840, data = 0x0000000100112940},
|
||||||
pf: 0x0000000100123d10,
|
fn = {f = 0x000000010001b4a4, data = 0x00000001001149c0},
|
||||||
pi: 0x00000001001149e0,
|
pad1 = 100,
|
||||||
intr: { type: 0x0000000100116810, data: 0x00000001001149d0 },
|
pad2 = 200
|
||||||
m: { count: 4296130304 },
|
|
||||||
c: { },
|
|
||||||
err: { type: 0x0000000100116840, data: 0x0000000100112940 },
|
|
||||||
fn: { f: 0x000000010001b4a4, data: 0x00000001001149c0 },
|
|
||||||
pad1: 100,
|
|
||||||
pad2: 200,
|
|
||||||
}
|
}
|
||||||
var globalStructPtr *github.com/goplus/llgo/cl/_testdata/debug.StructWithAllTypeFields = <variable not available>
|
var globalStructPtr *github.com/goplus/llgo/cl/_testdata/debug.StructWithAllTypeFields = <variable not available>
|
||||||
var globalStruct github.com/goplus/llgo/cl/_testdata/debug.StructWithAllTypeFields = {
|
var globalStruct github.com/goplus/llgo/cl/_testdata/debug.StructWithAllTypeFields = {
|
||||||
i8: '\x01',
|
i8 = '\x01',
|
||||||
i16: 2,
|
i16 = 2,
|
||||||
i32: 3,
|
i32 = 3,
|
||||||
i64: 4,
|
i64 = 4,
|
||||||
i: 5,
|
i = 5,
|
||||||
u8: '\x06',
|
u8 = '\x06',
|
||||||
u16: 7,
|
u16 = 7,
|
||||||
u32: 8,
|
u32 = 8,
|
||||||
u64: 9,
|
u64 = 9,
|
||||||
u: 10,
|
u = 10,
|
||||||
f32: 11,
|
f32 = 11,
|
||||||
f64: 12,
|
f64 = 12,
|
||||||
b: true,
|
b = true,
|
||||||
c64: { real: 13, imag: 14 },
|
c64 = {real = 13, imag = 14},
|
||||||
c128: { real: 15, imag: 16 },
|
c128 = {real = 15, imag = 16},
|
||||||
slice: []int{
|
slice = []int{21, 22, 23},
|
||||||
21, 22, 23
|
arr = [3]int{24, 25, 26},
|
||||||
},
|
arr2 = [3]github.com/goplus/llgo/cl/_testdata/debug.E{{i = 27}, {i = 28}, {i = 29}},
|
||||||
arr: [3]int{
|
s = "hello",
|
||||||
24, 25, 26,
|
e = {i = 30},
|
||||||
},
|
pf = 0x0000000100123d10,
|
||||||
arr2: [3]github.com/goplus/llgo/cl/_testdata/debug.E{
|
pi = 0x00000001001149e0,
|
||||||
{ i: 27 }, { i: 28 }, { i: 29 },
|
intr = {type = 0x0000000100116810, data = 0x00000001001149d0},
|
||||||
},
|
m = {count = 4296130304},
|
||||||
s: "hello",
|
c = {},
|
||||||
e: { i: 30 },
|
err = {type = 0x0000000100116840, data = 0x0000000100112940},
|
||||||
pf: 0x0000000100123d10,
|
fn = {f = 0x000000010001b4a4, data = 0x00000001001149c0},
|
||||||
pi: 0x00000001001149e0,
|
pad1 = 100,
|
||||||
intr: { type: 0x0000000100116810, data: 0x00000001001149d0 },
|
pad2 = 200
|
||||||
m: { count: 4296130304 },
|
|
||||||
c: { },
|
|
||||||
err: { type: 0x0000000100116840, data: 0x0000000100112940 },
|
|
||||||
fn: { f: 0x000000010001b4a4, data: 0x00000001001149c0 },
|
|
||||||
pad1: 100,
|
|
||||||
pad2: 200,
|
|
||||||
}
|
}
|
||||||
var globalInt int = 301
|
var globalInt int = 301
|
||||||
var err error = { type: 0x0000000100112900, data: 0x000000000000001a }
|
var err error = {type = 0x0000000100112900, data = 0x000000000000001a}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ import lldb
|
|||||||
|
|
||||||
|
|
||||||
def __lldb_init_module(debugger, _):
|
def __lldb_init_module(debugger, _):
|
||||||
debugger.HandleCommand(
|
|
||||||
'command script add -f llgo_plugin.format_go_variable gv')
|
|
||||||
debugger.HandleCommand(
|
debugger.HandleCommand(
|
||||||
'command script add -f llgo_plugin.print_go_expression p')
|
'command script add -f llgo_plugin.print_go_expression p')
|
||||||
debugger.HandleCommand(
|
debugger.HandleCommand(
|
||||||
@@ -44,23 +42,6 @@ def is_llgo_compiler(target):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def format_go_variable(debugger, command, result, _internal_dict):
|
|
||||||
target = debugger.GetSelectedTarget()
|
|
||||||
if not is_llgo_compiler(target):
|
|
||||||
result.AppendMessage("Not a LLGo compiled binary.")
|
|
||||||
return
|
|
||||||
|
|
||||||
frame = debugger.GetSelectedTarget().GetProcess(
|
|
||||||
).GetSelectedThread().GetSelectedFrame()
|
|
||||||
var = frame.EvaluateExpression(command)
|
|
||||||
|
|
||||||
if var.error.Success():
|
|
||||||
formatted = format_value(var, debugger)
|
|
||||||
result.AppendMessage(formatted)
|
|
||||||
else:
|
|
||||||
result.AppendMessage(f"Error: {var.error}")
|
|
||||||
|
|
||||||
|
|
||||||
def print_go_expression(debugger, command, result, _internal_dict):
|
def print_go_expression(debugger, command, result, _internal_dict):
|
||||||
target = debugger.GetSelectedTarget()
|
target = debugger.GetSelectedTarget()
|
||||||
if not is_llgo_compiler(target):
|
if not is_llgo_compiler(target):
|
||||||
@@ -149,6 +130,9 @@ def format_slice(var, debugger, indent):
|
|||||||
element_size = element_type.GetByteSize()
|
element_size = element_type.GetByteSize()
|
||||||
|
|
||||||
target = debugger.GetSelectedTarget()
|
target = debugger.GetSelectedTarget()
|
||||||
|
indent_str = ' ' * indent
|
||||||
|
next_indent_str = ' ' * (indent + 1)
|
||||||
|
|
||||||
for i in range(length):
|
for i in range(length):
|
||||||
element_address = ptr_value + i * element_size
|
element_address = ptr_value + i * element_size
|
||||||
element = target.CreateValueFromAddress(
|
element = target.CreateValueFromAddress(
|
||||||
@@ -158,45 +142,40 @@ def format_slice(var, debugger, indent):
|
|||||||
elements.append(value)
|
elements.append(value)
|
||||||
|
|
||||||
type_name = var.GetType().GetName()
|
type_name = var.GetType().GetName()
|
||||||
indent_str = ' ' * indent
|
|
||||||
next_indent_str = ' ' * (indent + 1)
|
|
||||||
|
|
||||||
if len(elements) > 5: # For long slices, print only first and last few elements
|
if len(elements) > 5: # 如果元素数量大于5,则进行折行显示
|
||||||
result = f"{type_name}{{\n{next_indent_str}{', '.join(elements[:3])},\n{
|
result = f"{type_name}{{\n{next_indent_str}" + \
|
||||||
next_indent_str}...,\n{next_indent_str}{', '.join(elements[-2:])}\n{indent_str}}}"
|
f",\n{next_indent_str}".join(elements) + f"\n{indent_str}}}"
|
||||||
else:
|
else:
|
||||||
result = f"{type_name}{{\n{next_indent_str}{', '.join(elements)}\n{
|
result = f"{type_name}{{{', '.join(elements)}}}"
|
||||||
indent_str}}}"
|
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def format_array(var, debugger, indent):
|
def format_array(var, debugger, indent):
|
||||||
elements = []
|
elements = []
|
||||||
|
indent_str = ' ' * indent
|
||||||
|
next_indent_str = ' ' * (indent + 1)
|
||||||
|
|
||||||
for i in range(var.GetNumChildren()):
|
for i in range(var.GetNumChildren()):
|
||||||
value = format_value(var.GetChildAtIndex(
|
value = format_value(var.GetChildAtIndex(
|
||||||
i), debugger, include_type=False, indent=indent+1)
|
i), debugger, include_type=False, indent=indent+1)
|
||||||
elements.append(value)
|
elements.append(value)
|
||||||
|
|
||||||
array_size = var.GetNumChildren()
|
array_size = var.GetNumChildren()
|
||||||
element_type = map_type_name(var.GetType().GetArrayElementType().GetName())
|
element_type = map_type_name(var.GetType().GetArrayElementType().GetName())
|
||||||
type_name = f"[{array_size}]{element_type}"
|
type_name = f"[{array_size}]{element_type}"
|
||||||
indent_str = ' ' * indent
|
|
||||||
next_indent_str = ' ' * (indent + 1)
|
|
||||||
|
|
||||||
if len(elements) > 5: # For long arrays, print only first and last few elements
|
if len(elements) > 5: # 如果元素数量大于5,则进行折行显示
|
||||||
result = f"{type_name}{{\n{next_indent_str}{', '.join(elements[:3])},\n{
|
return f"{type_name}{{\n{next_indent_str}" + f",\n{next_indent_str}".join(elements) + f"\n{indent_str}}}"
|
||||||
next_indent_str}...,\n{next_indent_str}{', '.join(elements[-2:])},\n{indent_str}}}"
|
|
||||||
else:
|
else:
|
||||||
result = f"{type_name}{{\n{next_indent_str}{', '.join(elements)},\n{
|
return f"{type_name}{{{', '.join(elements)}}}"
|
||||||
indent_str}}}"
|
|
||||||
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
def format_string(var):
|
def format_string(var):
|
||||||
summary = var.GetSummary()
|
summary = var.GetSummary()
|
||||||
if summary is not None:
|
if summary is not None:
|
||||||
return summary
|
return summary # Keep the quotes
|
||||||
else:
|
else:
|
||||||
data = var.GetChildMemberWithName('data').GetValue()
|
data = var.GetChildMemberWithName('data').GetValue()
|
||||||
length = int(var.GetChildMemberWithName('len').GetValue())
|
length = int(var.GetChildMemberWithName('len').GetValue())
|
||||||
@@ -214,19 +193,15 @@ def format_struct(var, debugger, include_type=True, indent=0, type_name=""):
|
|||||||
for i in range(var.GetNumChildren()):
|
for i in range(var.GetNumChildren()):
|
||||||
child = var.GetChildAtIndex(i)
|
child = var.GetChildAtIndex(i)
|
||||||
child_name = child.GetName()
|
child_name = child.GetName()
|
||||||
child_type = map_type_name(child.GetType().GetName())
|
|
||||||
child_value = format_value(
|
child_value = format_value(
|
||||||
child, debugger, include_type=False, indent=indent+1)
|
child, debugger, include_type=False, indent=indent+1)
|
||||||
|
children.append(f"{child_name} = {child_value}")
|
||||||
|
|
||||||
if '\n' in child_value or var.GetNumChildren() > 3:
|
if len(children) > 5: # 如果字段数量大于5,则进行折行显示
|
||||||
children.append(f"{next_indent_str}{child_name}: {child_value},")
|
struct_content = "{\n" + ",\n".join(
|
||||||
else:
|
[f"{next_indent_str}{child}" for child in children]) + f"\n{indent_str}}}"
|
||||||
children.append(f"{child_name}: {child_value}")
|
|
||||||
|
|
||||||
if var.GetNumChildren() <= 3 and all('\n' not in child for child in children):
|
|
||||||
struct_content = f"{{ {', '.join(children)} }}"
|
|
||||||
else:
|
else:
|
||||||
struct_content = "{\n" + "\n".join(children) + "\n" + indent_str + "}"
|
struct_content = f"{{{', '.join(children)}}}"
|
||||||
|
|
||||||
if include_type:
|
if include_type:
|
||||||
return f"{type_name}{struct_content}"
|
return f"{type_name}{struct_content}"
|
||||||
@@ -237,13 +212,7 @@ def format_struct(var, debugger, include_type=True, indent=0, type_name=""):
|
|||||||
def format_pointer(var, debugger, indent, type_name):
|
def format_pointer(var, debugger, indent, type_name):
|
||||||
if not var.IsValid() or var.GetValueAsUnsigned() == 0:
|
if not var.IsValid() or var.GetValueAsUnsigned() == 0:
|
||||||
return "<variable not available>"
|
return "<variable not available>"
|
||||||
pointee = var.Dereference()
|
return var.GetValue() # Return the address as a string
|
||||||
if pointee.IsValid():
|
|
||||||
pointee_value = format_value(
|
|
||||||
pointee, debugger, include_type=False, indent=indent)
|
|
||||||
return f"{var.GetValue()}"
|
|
||||||
else:
|
|
||||||
return f"{var.GetValue()}"
|
|
||||||
|
|
||||||
|
|
||||||
def map_type_name(type_name):
|
def map_type_name(type_name):
|
||||||
|
|||||||
6
_lldb/runlldb.sh
Executable file
6
_lldb/runlldb.sh
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
go run ./cmd/llgo build -o ./cl/_testdata/debug/out -dbg ./cl/_testdata/debug/
|
||||||
|
lldb -O "command script import _lldb/llgo_plugin.py" ./cl/_testdata/debug/out
|
||||||
7
_lldb/runtest.sh
Executable file
7
_lldb/runtest.sh
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
go run ./cmd/llgo build -o ./cl/_testdata/debug/out -dbg ./cl/_testdata/debug/
|
||||||
|
|
||||||
|
/opt/homebrew/bin/lldb -S _lldb/runtest.lldb
|
||||||
137
_lldb/test.py
137
_lldb/test.py
@@ -7,6 +7,7 @@ import signal
|
|||||||
from dataclasses import dataclass, field
|
from dataclasses import dataclass, field
|
||||||
from typing import List
|
from typing import List
|
||||||
import lldb
|
import lldb
|
||||||
|
import llgo_plugin # Add this import
|
||||||
|
|
||||||
|
|
||||||
class LLDBTestException(Exception):
|
class LLDBTestException(Exception):
|
||||||
@@ -81,6 +82,11 @@ class LLDBDebugger:
|
|||||||
raise LLDBTestException(f"Failed to create target for {
|
raise LLDBTestException(f"Failed to create target for {
|
||||||
self.executable_path}")
|
self.executable_path}")
|
||||||
|
|
||||||
|
self.debugger.HandleCommand(
|
||||||
|
'command script add -f llgo_plugin.print_go_expression p')
|
||||||
|
self.debugger.HandleCommand(
|
||||||
|
'command script add -f llgo_plugin.print_all_variables v')
|
||||||
|
|
||||||
def set_breakpoint(self, file_spec, line_number):
|
def set_breakpoint(self, file_spec, line_number):
|
||||||
bp = self.target.BreakpointCreateByLocation(
|
bp = self.target.BreakpointCreateByLocation(
|
||||||
file_spec, line_number)
|
file_spec, line_number)
|
||||||
@@ -97,121 +103,30 @@ class LLDBDebugger:
|
|||||||
if self.process.GetState() != lldb.eStateStopped:
|
if self.process.GetState() != lldb.eStateStopped:
|
||||||
raise LLDBTestException("Process didn't stop at breakpoint")
|
raise LLDBTestException("Process didn't stop at breakpoint")
|
||||||
|
|
||||||
def get_variable_value(self, var_name):
|
def get_variable_value(self, var_expression):
|
||||||
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
||||||
|
|
||||||
if isinstance(var_name, lldb.SBValue):
|
# 处理结构体成员访问、指针解引用和数组索引
|
||||||
var = var_name
|
parts = var_expression.split('.')
|
||||||
else:
|
var = frame.FindVariable(parts[0])
|
||||||
# process struct field access
|
|
||||||
parts = var_name.split('.')
|
for part in parts[1:]:
|
||||||
if len(parts) > 1:
|
if not var.IsValid():
|
||||||
var = frame.FindVariable(parts[0])
|
return None
|
||||||
for part in parts[1:]:
|
|
||||||
if var.IsValid():
|
# 处理数组索引
|
||||||
var = var.GetChildMemberWithName(part)
|
if '[' in part and ']' in part:
|
||||||
else:
|
array_name, index = part.split('[')
|
||||||
return None
|
index = int(index.rstrip(']'))
|
||||||
|
var = var.GetChildAtIndex(index)
|
||||||
|
# 处理指针解引用
|
||||||
|
elif var.GetType().IsPointerType():
|
||||||
|
var = var.Dereference()
|
||||||
|
var = var.GetChildMemberWithName(part)
|
||||||
else:
|
else:
|
||||||
actual_var_name = var_name.split('=')[0].strip()
|
var = var.GetChildMemberWithName(part)
|
||||||
if '(' in actual_var_name:
|
|
||||||
actual_var_name = actual_var_name.split('(')[-1].strip()
|
|
||||||
var = frame.FindVariable(actual_var_name)
|
|
||||||
|
|
||||||
return self.format_value(var) if var.IsValid() else None
|
return llgo_plugin.format_value(var, self.debugger) if var.IsValid() else None
|
||||||
|
|
||||||
def format_value(self, var, include_type=True):
|
|
||||||
if var.IsValid():
|
|
||||||
type_name = var.GetTypeName()
|
|
||||||
var_type = var.GetType()
|
|
||||||
type_class = var_type.GetTypeClass()
|
|
||||||
|
|
||||||
if type_name.startswith('[]'): # Slice
|
|
||||||
return self.format_slice(var)
|
|
||||||
elif var_type.IsArrayType():
|
|
||||||
return self.format_array(var)
|
|
||||||
elif type_name == 'string': # String
|
|
||||||
return self.format_string(var)
|
|
||||||
elif type_class in [lldb.eTypeClassStruct, lldb.eTypeClassClass]:
|
|
||||||
return self.format_struct(var, include_type)
|
|
||||||
else:
|
|
||||||
value = var.GetValue()
|
|
||||||
summary = var.GetSummary()
|
|
||||||
if value is not None:
|
|
||||||
return str(value)
|
|
||||||
elif summary is not None:
|
|
||||||
return summary
|
|
||||||
else:
|
|
||||||
return "None"
|
|
||||||
return "None"
|
|
||||||
|
|
||||||
def format_slice(self, var):
|
|
||||||
length = int(var.GetChildMemberWithName('len').GetValue())
|
|
||||||
data_ptr = var.GetChildMemberWithName('data')
|
|
||||||
elements = []
|
|
||||||
|
|
||||||
# Get the actual pointer value
|
|
||||||
ptr_value = int(data_ptr.GetValue(), 16)
|
|
||||||
element_type = data_ptr.GetType().GetPointeeType()
|
|
||||||
element_size = element_type.GetByteSize()
|
|
||||||
|
|
||||||
for i in range(length):
|
|
||||||
element_address = ptr_value + i * element_size
|
|
||||||
element = self.target.CreateValueFromAddress(
|
|
||||||
f"element_{i}", lldb.SBAddress(element_address, self.target), element_type)
|
|
||||||
value = self.format_value(element, include_type=False)
|
|
||||||
elements.append(value)
|
|
||||||
|
|
||||||
type_name = var.GetType().GetName().split(
|
|
||||||
'[]')[-1] # Extract element type from slice type
|
|
||||||
type_name = self.type_mapping.get(type_name, type_name) # Use mapping
|
|
||||||
result = f"[]{type_name}{{{', '.join(elements)}}}"
|
|
||||||
return result
|
|
||||||
|
|
||||||
def format_array(self, var):
|
|
||||||
elements = []
|
|
||||||
for i in range(var.GetNumChildren()):
|
|
||||||
value = self.format_value(
|
|
||||||
var.GetChildAtIndex(i), include_type=False)
|
|
||||||
elements.append(value)
|
|
||||||
array_size = var.GetNumChildren()
|
|
||||||
type_name = var.GetType().GetArrayElementType().GetName()
|
|
||||||
type_name = self.type_mapping.get(type_name, type_name) # Use mapping
|
|
||||||
return f"[{array_size}]{type_name}{{{', '.join(elements)}}}"
|
|
||||||
|
|
||||||
def format_pointer(self, var):
|
|
||||||
target = var.Dereference()
|
|
||||||
if target.IsValid():
|
|
||||||
return f"*{self.get_variable_value(target.GetName())}"
|
|
||||||
else:
|
|
||||||
return str(var.GetValue())
|
|
||||||
|
|
||||||
def format_string(self, var):
|
|
||||||
summary = var.GetSummary()
|
|
||||||
if summary is not None:
|
|
||||||
return summary.strip('"')
|
|
||||||
else:
|
|
||||||
data = var.GetChildMemberWithName('data').GetValue()
|
|
||||||
length = int(var.GetChildMemberWithName('len').GetValue())
|
|
||||||
if data and length:
|
|
||||||
error = lldb.SBError()
|
|
||||||
return self.process.ReadCStringFromMemory(int(data, 16), length + 1, error)
|
|
||||||
return "None"
|
|
||||||
|
|
||||||
def format_struct(self, var, include_type=True):
|
|
||||||
children = []
|
|
||||||
for i in range(var.GetNumChildren()):
|
|
||||||
child = var.GetChildAtIndex(i)
|
|
||||||
child_name = child.GetName()
|
|
||||||
child_value = self.format_value(child)
|
|
||||||
children.append(f"{child_name} = {child_value}")
|
|
||||||
|
|
||||||
struct_content = f"{{{', '.join(children)}}}"
|
|
||||||
if include_type:
|
|
||||||
struct_name = var.GetTypeName()
|
|
||||||
return f"{struct_name}{struct_content}"
|
|
||||||
else:
|
|
||||||
return struct_content
|
|
||||||
|
|
||||||
def get_all_variable_names(self):
|
def get_all_variable_names(self):
|
||||||
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
frame = self.process.GetSelectedThread().GetFrameAtIndex(0)
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ func FuncWithAllTypeStructParam(s StructWithAllTypeFields) {
|
|||||||
// s.slice: []int{21, 22, 23}
|
// s.slice: []int{21, 22, 23}
|
||||||
// s.arr: [3]int{24, 25, 26}
|
// s.arr: [3]int{24, 25, 26}
|
||||||
// s.arr2: [3]github.com/goplus/llgo/cl/_testdata/debug.E{{i = 27}, {i = 28}, {i = 29}}
|
// s.arr2: [3]github.com/goplus/llgo/cl/_testdata/debug.E{{i = 27}, {i = 28}, {i = 29}}
|
||||||
// s.s: hello
|
// s.s: "hello"
|
||||||
// s.e: github.com/goplus/llgo/cl/_testdata/debug.E{i = 30}
|
// s.e: github.com/goplus/llgo/cl/_testdata/debug.E{i = 30}
|
||||||
// s.pad1: 100
|
// s.pad1: 100
|
||||||
// s.pad2: 200
|
// s.pad2: 200
|
||||||
@@ -147,7 +147,7 @@ func FuncWithAllTypeParams(
|
|||||||
// slice: []int{21, 22, 23}
|
// slice: []int{21, 22, 23}
|
||||||
// arr: [3]int{24, 25, 26}
|
// arr: [3]int{24, 25, 26}
|
||||||
// arr2: [3]github.com/goplus/llgo/cl/_testdata/debug.E{{i = 27}, {i = 28}, {i = 29}}
|
// arr2: [3]github.com/goplus/llgo/cl/_testdata/debug.E{{i = 27}, {i = 28}, {i = 29}}
|
||||||
// s: hello
|
// s: "hello"
|
||||||
// e: github.com/goplus/llgo/cl/_testdata/debug.E{i = 30}
|
// e: github.com/goplus/llgo/cl/_testdata/debug.E{i = 30}
|
||||||
i8 = 9
|
i8 = 9
|
||||||
// Expected:
|
// Expected:
|
||||||
|
|||||||
Reference in New Issue
Block a user