Skip to content

Commit 542ce3f

Browse files
committed
[LLDB][DWARF] add tests code from original issue
1 parent f7d2b1d commit 542ce3f

File tree

4 files changed

+1253
-0
lines changed

4 files changed

+1253
-0
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
"""Helper library to traverse data emitted for Rust enums """
2+
from lldbsuite.test.lldbtest import *
3+
4+
DISCRIMINANT_MEMBER_NAME = "$discr$"
5+
VALUE_MEMBER_NAME = "value"
6+
7+
8+
class RustEnumValue:
9+
def __init__(self, value: lldb.SBValue):
10+
self.value = value
11+
12+
def getAllVariantTypes(self):
13+
result = []
14+
for i in range(self._inner().GetNumChildren()):
15+
result.append(self.getVariantByIndex(i).GetDisplayTypeName())
16+
return result
17+
18+
def _inner(self) -> lldb.SBValue:
19+
return self.value.GetChildAtIndex(0)
20+
21+
def getVariantByIndex(self, index):
22+
return (
23+
self._inner()
24+
.GetChildAtIndex(index)
25+
.GetChildMemberWithName(VALUE_MEMBER_NAME)
26+
)
27+
28+
@staticmethod
29+
def _getDiscriminantValueAsUnsigned(discr_sbvalue: lldb.SBValue):
30+
byte_size = discr_sbvalue.GetType().GetByteSize()
31+
error = lldb.SBError()
32+
33+
# when discriminant is u16 Clang emits 'unsigned char'
34+
# and LLDB seems to treat it as character type disalowing to call GetValueAsUnsigned
35+
if byte_size == 1:
36+
return discr_sbvalue.GetData().GetUnsignedInt8(error, 0)
37+
elif byte_size == 2:
38+
return discr_sbvalue.GetData().GetUnsignedInt16(error, 0)
39+
elif byte_size == 4:
40+
return discr_sbvalue.GetData().GetUnsignedInt32(error, 0)
41+
elif byte_size == 8:
42+
return discr_sbvalue.GetData().GetUnsignedInt64(error, 0)
43+
else:
44+
return discr_sbvalue.GetValueAsUnsigned()
45+
46+
def getCurrentVariantIndex(self):
47+
default_index = 0
48+
for i in range(self._inner().GetNumChildren()):
49+
variant: lldb.SBValue = self._inner().GetChildAtIndex(i)
50+
discr = variant.GetChildMemberWithName(DISCRIMINANT_MEMBER_NAME)
51+
if discr.IsValid():
52+
discr_unsigned_value = RustEnumValue._getDiscriminantValueAsUnsigned(
53+
discr
54+
)
55+
if variant.GetName() == f"$variant${discr_unsigned_value}":
56+
return discr_unsigned_value
57+
else:
58+
default_index = i
59+
return default_index
60+
61+
def getFields(self):
62+
result = []
63+
for i in range(self._inner().GetNumChildren()):
64+
type: lldb.SBType = self._inner().GetType()
65+
result.append(type.GetFieldAtIndex(i).GetName())
66+
return result
67+
68+
def getCurrentValue(self) -> lldb.SBValue:
69+
return self.getVariantByIndex(self.getCurrentVariantIndex())
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
"""Test that lldb recognizes enum variant emitted by Rust compiler """
2+
import logging
3+
4+
import lldb
5+
from lldbsuite.test.decorators import *
6+
from lldbsuite.test.lldbtest import *
7+
from RustEnumValue import RustEnumValue
8+
9+
class TestRustEnumStructs(TestBase):
10+
def setUp(self):
11+
TestBase.setUp(self)
12+
src_dir = self.getSourceDir()
13+
yaml_path = os.path.join(src_dir, "main.yaml")
14+
obj_path = self.getBuildArtifact("main.o")
15+
self.yaml2obj(yaml_path, obj_path)
16+
self.dbg.CreateTarget(obj_path)
17+
18+
def getFromGlobal(self, name):
19+
values = self.target().FindGlobalVariables(name, 1)
20+
self.assertEqual(values.GetSize(), 1)
21+
return RustEnumValue(values[0])
22+
23+
def test_enum_instance(self):
24+
# static ENUM_INSTANCE: A = A::A(B::B(10));
25+
value = self.getFromGlobal("ENUM_INSTANCE").getCurrentValue()
26+
self.assertEqual(value.GetType().GetDisplayTypeName(), "main::A::A")
27+
28+
value_b = RustEnumValue(value.GetChildAtIndex(0))
29+
self.assertEqual(
30+
value_b.getCurrentValue().GetChildAtIndex(0).GetData().GetUnsignedInt8(lldb.SBError(), 0),
31+
10
32+
)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/// Command:
2+
/// rustc -g --emit=obj --crate-type=bin -C panic=abort -C link-arg=-nostdlib main.rs && obj2yaml main.o -o main.yaml
3+
4+
pub enum A {
5+
A(B),
6+
}
7+
8+
pub enum B {
9+
B(u8),
10+
}
11+
12+
static ENUM_INSTANCE: A = A::A(B::B(10));
13+
14+
pub fn main() {
15+
}

0 commit comments

Comments
 (0)