199 lines
8.5 KiB
Python
199 lines
8.5 KiB
Python
|
"""Test C bitfields."""
|
||
|
|
||
|
|
||
|
import lldb
|
||
|
from lldbsuite.test.decorators import *
|
||
|
from lldbsuite.test.lldbtest import *
|
||
|
from lldbsuite.test import lldbutil
|
||
|
|
||
|
|
||
|
class TestCase(TestBase):
|
||
|
def run_to_main(self):
|
||
|
self.build()
|
||
|
lldbutil.run_to_source_breakpoint(
|
||
|
self, "// break here", lldb.SBFileSpec("main.c")
|
||
|
)
|
||
|
|
||
|
# BitFields exhibit crashes in record layout on Windows
|
||
|
# (http://llvm.org/pr21800)
|
||
|
@skipIfWindows
|
||
|
def test_bits(self):
|
||
|
self.run_to_main()
|
||
|
|
||
|
# Check each field of Bits.
|
||
|
bits_children = [
|
||
|
ValueCheck(type="int:1"), # Unnamed and uninitialized
|
||
|
ValueCheck(type="uint32_t:1", name="b1", value="1"),
|
||
|
ValueCheck(type="uint32_t:2", name="b2", value="3"),
|
||
|
ValueCheck(type="int:2"), # Unnamed and uninitialized
|
||
|
ValueCheck(type="uint32_t:3", name="b3", value="7"),
|
||
|
ValueCheck(type="uint32_t", name="b4", value="15"),
|
||
|
ValueCheck(type="uint32_t:5", name="b5", value="31"),
|
||
|
ValueCheck(type="uint32_t:6", name="b6", value="63"),
|
||
|
ValueCheck(type="uint32_t:7", name="b7", value="127"),
|
||
|
ValueCheck(type="uint32_t:4", name="four", value="15"),
|
||
|
]
|
||
|
self.expect_var_path("bits", type="Bits", children=bits_children)
|
||
|
self.expect_expr("bits", result_children=bits_children)
|
||
|
|
||
|
# Try accessing the different fields using the expression evaluator.
|
||
|
self.expect_expr("bits.b1", result_type="uint32_t", result_value="1")
|
||
|
self.expect_expr("bits.b2", result_type="uint32_t", result_value="3")
|
||
|
self.expect_expr("bits.b3", result_type="uint32_t", result_value="7")
|
||
|
self.expect_expr("bits.b4", result_type="uint32_t", result_value="15")
|
||
|
self.expect_expr("bits.b5", result_type="uint32_t", result_value="31")
|
||
|
self.expect_expr("bits.b6", result_type="uint32_t", result_value="63")
|
||
|
self.expect_expr("bits.b7", result_type="uint32_t", result_value="127")
|
||
|
self.expect_expr("bits.four", result_type="uint32_t", result_value="15")
|
||
|
|
||
|
# Try accessing the different fields using variable paths.
|
||
|
self.expect_var_path("bits.b1", type="uint32_t:1", value="1")
|
||
|
self.expect_var_path("bits.b2", type="uint32_t:2", value="3")
|
||
|
self.expect_var_path("bits.b4", type="uint32_t", value="15")
|
||
|
self.expect_var_path("bits.b5", type="uint32_t:5", value="31")
|
||
|
self.expect_var_path("bits.b7", type="uint32_t:7", value="127")
|
||
|
|
||
|
# Check each field of MoreBits.
|
||
|
more_bits_children = [
|
||
|
ValueCheck(type="uint32_t:3", name="a", value="3"),
|
||
|
ValueCheck(type="int:1", value="0"),
|
||
|
ValueCheck(type="uint8_t:1", name="b", value="'\\0'"),
|
||
|
ValueCheck(type="uint8_t:1", name="c", value="'\\x01'"),
|
||
|
ValueCheck(type="uint8_t:1", name="d", value="'\\0'"),
|
||
|
]
|
||
|
self.expect_var_path("more_bits", type="MoreBits", children=more_bits_children)
|
||
|
self.expect_expr("more_bits", result_children=more_bits_children)
|
||
|
|
||
|
self.expect_expr("more_bits.a", result_type="uint32_t", result_value="3")
|
||
|
self.expect_expr("more_bits.b", result_type="uint8_t", result_value="'\\0'")
|
||
|
self.expect_expr("more_bits.c", result_type="uint8_t", result_value="'\\x01'")
|
||
|
self.expect_expr("more_bits.d", result_type="uint8_t", result_value="'\\0'")
|
||
|
|
||
|
# Test a struct with several single bit fields.
|
||
|
many_single_bits_children = [
|
||
|
ValueCheck(type="uint16_t:1", name="b1", value="1"),
|
||
|
ValueCheck(type="uint16_t:1", name="b2", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b3", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b4", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b5", value="1"),
|
||
|
ValueCheck(type="uint16_t:1", name="b6", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b7", value="1"),
|
||
|
ValueCheck(type="uint16_t:1", name="b8", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b9", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b10", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b11", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b12", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b13", value="1"),
|
||
|
ValueCheck(type="uint16_t:1", name="b14", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b15", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b16", value="0"),
|
||
|
ValueCheck(type="uint16_t:1", name="b17", value="0"),
|
||
|
]
|
||
|
self.expect_var_path(
|
||
|
"many_single_bits",
|
||
|
type="ManySingleBits",
|
||
|
children=many_single_bits_children,
|
||
|
)
|
||
|
self.expect_expr(
|
||
|
"many_single_bits",
|
||
|
result_type="ManySingleBits",
|
||
|
result_children=many_single_bits_children,
|
||
|
)
|
||
|
|
||
|
# Check a packed struct.
|
||
|
self.expect_expr("packed.a", result_type="char", result_value="'a'")
|
||
|
self.expect_expr("packed.b", result_type="uint32_t", result_value="10")
|
||
|
self.expect_expr(
|
||
|
"packed.c", result_type="uint32_t", result_value=str(int("7112233", 16))
|
||
|
)
|
||
|
|
||
|
# A packed struct with bitfield size > 32.
|
||
|
self.expect(
|
||
|
"v/x large_packed",
|
||
|
VARIABLES_DISPLAYED_CORRECTLY,
|
||
|
substrs=["a = 0x0000000cbbbbaaaa", "b = 0x0000000dffffeee"],
|
||
|
)
|
||
|
|
||
|
# Check reading a bitfield through a pointer in various ways (PR47743)
|
||
|
self.expect(
|
||
|
"v/x large_packed_ptr->b",
|
||
|
substrs=["large_packed_ptr->b = 0x0000000dffffeeee"],
|
||
|
)
|
||
|
self.expect(
|
||
|
"v/x large_packed_ptr[0].b",
|
||
|
substrs=["large_packed_ptr[0].b = 0x0000000dffffeeee"],
|
||
|
)
|
||
|
|
||
|
# BitFields exhibit crashes in record layout on Windows
|
||
|
# (http://llvm.org/pr21800)
|
||
|
@skipIfWindows
|
||
|
def test_expression_bug(self):
|
||
|
# Ensure evaluating (emulating) an expression does not break bitfield
|
||
|
# values for already parsed variables. The expression is run twice
|
||
|
# because the very first expression can resume a target (to allocate
|
||
|
# memory, etc.) even if it is not being jitted.
|
||
|
self.run_to_main()
|
||
|
|
||
|
self.expect(
|
||
|
"v/x large_packed",
|
||
|
VARIABLES_DISPLAYED_CORRECTLY,
|
||
|
substrs=["a = 0x0000000cbbbbaaaa", "b = 0x0000000dffffeee"],
|
||
|
)
|
||
|
self.expect(
|
||
|
"expr --allow-jit false -- more_bits.a",
|
||
|
VARIABLES_DISPLAYED_CORRECTLY,
|
||
|
substrs=["uint32_t", "3"],
|
||
|
)
|
||
|
self.expect(
|
||
|
"v/x large_packed",
|
||
|
VARIABLES_DISPLAYED_CORRECTLY,
|
||
|
substrs=["a = 0x0000000cbbbbaaaa", "b = 0x0000000dffffeee"],
|
||
|
)
|
||
|
self.expect(
|
||
|
"expr --allow-jit false -- more_bits.a",
|
||
|
VARIABLES_DISPLAYED_CORRECTLY,
|
||
|
substrs=["uint32_t", "3"],
|
||
|
)
|
||
|
self.expect(
|
||
|
"v/x large_packed",
|
||
|
VARIABLES_DISPLAYED_CORRECTLY,
|
||
|
substrs=["a = 0x0000000cbbbbaaaa", "b = 0x0000000dffffeee"],
|
||
|
)
|
||
|
|
||
|
@add_test_categories(["pyapi"])
|
||
|
# BitFields exhibit crashes in record layout on Windows
|
||
|
# (http://llvm.org/pr21800)
|
||
|
@skipIfWindows
|
||
|
def test_and_python_api(self):
|
||
|
"""Use Python APIs to inspect a bitfields variable."""
|
||
|
self.run_to_main()
|
||
|
|
||
|
# Lookup the "bits" variable which contains 8 bitfields.
|
||
|
bits = self.frame().FindVariable("bits")
|
||
|
self.DebugSBValue(bits)
|
||
|
self.assertEqual(bits.GetTypeName(), "Bits")
|
||
|
self.assertEqual(bits.GetNumChildren(), 10)
|
||
|
self.assertEqual(bits.GetByteSize(), 32)
|
||
|
|
||
|
# Notice the pattern of int(b1.GetValue(), 0). We pass a base of 0
|
||
|
# so that the proper radix is determined based on the contents of the
|
||
|
# string.
|
||
|
b1 = bits.GetChildMemberWithName("b1")
|
||
|
self.DebugSBValue(b1)
|
||
|
self.assertEqual(b1.GetName(), "b1")
|
||
|
self.assertEqual(b1.GetTypeName(), "uint32_t:1")
|
||
|
self.assertTrue(b1.IsInScope())
|
||
|
self.assertEqual(int(b1.GetValue(), 0), 1)
|
||
|
|
||
|
b7 = bits.GetChildMemberWithName("b7")
|
||
|
self.assertEqual(b7.GetName(), "b7")
|
||
|
self.assertEqual(b7.GetTypeName(), "uint32_t:7")
|
||
|
self.assertTrue(b7.IsInScope())
|
||
|
self.assertEqual(int(b7.GetValue(), 0), 127)
|
||
|
|
||
|
four = bits.GetChildMemberWithName("four")
|
||
|
self.assertEqual(four.GetName(), "four")
|
||
|
self.assertEqual(four.GetTypeName(), "uint32_t:4")
|
||
|
self.assertTrue(four.IsInScope())
|
||
|
self.assertEqual(int(four.GetValue(), 0), 15)
|