xref: /llvm-project/lldb/test/API/python_api/sbdata/TestSBData.py (revision 9c2468821ec51defd09c246fea4a47886fff8c01)
1"""Test the SBData APIs."""
2
3
4from math import fabs
5import lldb
6from lldbsuite.test.decorators import *
7from lldbsuite.test.lldbtest import *
8from lldbsuite.test import lldbutil
9
10
11class SBDataAPICase(TestBase):
12    NO_DEBUG_INFO_TESTCASE = True
13
14    def setUp(self):
15        # Call super's setUp().
16        TestBase.setUp(self)
17        # Find the line number to break on inside main.cpp.
18        self.line = line_number("main.cpp", "// set breakpoint here")
19
20    def test_byte_order_and_address_byte_size(self):
21        """Test the SBData::SetData() to ensure the byte order and address
22        byte size are obeyed"""
23        addr_data = b"\x11\x22\x33\x44\x55\x66\x77\x88"
24        error = lldb.SBError()
25        data = lldb.SBData()
26        data.SetData(error, addr_data, lldb.eByteOrderBig, 4)
27        addr = data.GetAddress(error, 0)
28        self.assertEqual(addr, 0x11223344)
29        data.SetData(error, addr_data, lldb.eByteOrderBig, 8)
30        addr = data.GetAddress(error, 0)
31        self.assertEqual(addr, 0x1122334455667788)
32        data.SetData(error, addr_data, lldb.eByteOrderLittle, 4)
33        addr = data.GetAddress(error, 0)
34        self.assertEqual(addr, 0x44332211)
35        data.SetData(error, addr_data, lldb.eByteOrderLittle, 8)
36        addr = data.GetAddress(error, 0)
37        self.assertEqual(addr, 0x8877665544332211)
38
39    def test_byte_order_and_address_byte_size_with_ownership(self):
40        """Test the SBData::SetDataWithOwnership() to ensure the byte order
41        and address byte size are obeyed even when source date is released"""
42        addr_data = b"\x11\x22\x33\x44\x55\x66\x77\x88"
43        error = lldb.SBError()
44        data = lldb.SBData()
45        data.SetDataWithOwnership(error, addr_data, lldb.eByteOrderBig, 8)
46        del addr_data
47        addr = data.GetAddress(error, 0)
48        self.assertEqual(addr, 0x1122334455667788)
49
50    def test_with_run_command(self):
51        """Test the SBData APIs."""
52        self.build()
53        self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET)
54
55        lldbutil.run_break_set_by_file_and_line(
56            self, "main.cpp", self.line, num_expected_locations=1, loc_exact=True
57        )
58
59        self.runCmd("run", RUN_SUCCEEDED)
60
61        # The stop reason of the thread should be breakpoint.
62        self.expect(
63            "thread list",
64            STOPPED_DUE_TO_BREAKPOINT,
65            substrs=["stopped", "stop reason = breakpoint"],
66        )
67
68        target = self.dbg.GetSelectedTarget()
69
70        process = target.GetProcess()
71
72        thread = lldbutil.get_stopped_thread(process, lldb.eStopReasonBreakpoint)
73        self.assertIsNotNone(thread)
74
75        frame = thread.GetSelectedFrame()
76        foobar = frame.FindVariable("foobar")
77        self.assertTrue(foobar.IsValid())
78        data = foobar.GetPointeeData(0, 2)
79        offset = 0
80        error = lldb.SBError()
81
82        self.assert_data(data.GetUnsignedInt32, offset, 1)
83        offset += 4
84        low = data.GetSignedInt16(error, offset)
85        self.assertSuccess(error)
86        offset += 2
87        high = data.GetSignedInt16(error, offset)
88        self.assertSuccess(error)
89        offset += 2
90        self.assertTrue(
91            (low == 9 and high == 0) or (low == 0 and high == 9), "foo[0].b == 9"
92        )
93        self.assertLess(
94            fabs(data.GetFloat(error, offset) - 3.14), 1, "foo[0].c == 3.14"
95        )
96        self.assertSuccess(error)
97        offset += 4
98        self.assert_data(data.GetUnsignedInt32, offset, 8)
99        offset += 4
100        self.assert_data(data.GetUnsignedInt32, offset, 5)
101        offset += 4
102
103        self.runCmd("n")
104
105        offset = 16
106
107        self.assert_data(data.GetUnsignedInt32, offset, 5)
108
109        data = foobar.GetPointeeData(1, 1)
110
111        offset = 0
112
113        self.assert_data(data.GetSignedInt32, offset, 8)
114        offset += 4
115        self.assert_data(data.GetSignedInt32, offset, 7)
116        offset += 8
117        self.assertEqual(
118            data.GetUnsignedInt32(error, offset), 0, "do not read beyond end"
119        )
120        self.assertTrue(not error.Success())
121        error.Clear()  # clear the error for the next test
122
123        star_foobar = foobar.Dereference()
124        self.assertTrue(star_foobar.IsValid())
125
126        data = star_foobar.GetData()
127
128        offset = 0
129        self.assert_data(data.GetUnsignedInt32, offset, 1)
130        offset += 4
131        self.assert_data(data.GetUnsignedInt32, offset, 9)
132
133        foobar_addr = star_foobar.GetLoadAddress()
134        foobar_addr += 12
135
136        # http://llvm.org/bugs/show_bug.cgi?id=11579
137        # lldb::SBValue::CreateValueFromAddress does not verify SBType::GetPointerType succeeds
138        # This should not crash LLDB.
139        nothing = foobar.CreateValueFromAddress(
140            "nothing",
141            foobar_addr,
142            star_foobar.GetType().GetBasicType(lldb.eBasicTypeInvalid),
143        )
144
145        new_foobar = foobar.CreateValueFromAddress(
146            "f00", foobar_addr, star_foobar.GetType()
147        )
148        self.assertTrue(new_foobar.IsValid())
149        data = new_foobar.GetData()
150
151        self.assertEqual(data.uint32[0], 8, "then foo[1].a == 8")
152        self.assertEqual(data.uint32[1], 7, "then foo[1].b == 7")
153        # exploiting that sizeof(uint32) == sizeof(float)
154        self.assertLess(fabs(data.float[2] - 3.14), 1, "foo[1].c == 3.14")
155
156        self.runCmd("n")
157
158        offset = 0
159        self.assert_data(data.GetUnsignedInt32, offset, 8)
160        offset += 4
161        self.assert_data(data.GetUnsignedInt32, offset, 7)
162        offset += 4
163        self.assertLess(
164            fabs(data.GetFloat(error, offset) - 3.14), 1, "foo[1].c == 3.14"
165        )
166        self.assertSuccess(error)
167
168        data = new_foobar.GetData()
169
170        offset = 0
171        self.assert_data(data.GetUnsignedInt32, offset, 8)
172        offset += 4
173        self.assert_data(data.GetUnsignedInt32, offset, 7)
174        offset += 4
175        self.assertLess(
176            fabs(data.GetFloat(error, offset) - 6.28), 1, "foo[1].c == 6.28"
177        )
178        self.assertSuccess(error)
179
180        self.runCmd("n")
181
182        barfoo = frame.FindVariable("barfoo")
183
184        data = barfoo.GetData()
185        offset = 0
186        self.assert_data(data.GetUnsignedInt32, offset, 1)
187        offset += 4
188        self.assert_data(data.GetUnsignedInt32, offset, 2)
189        offset += 4
190        self.assertLess(fabs(data.GetFloat(error, offset) - 3), 1, "barfoo[0].c == 3")
191        self.assertSuccess(error)
192        offset += 4
193        self.assert_data(data.GetUnsignedInt32, offset, 4)
194        offset += 4
195        self.assert_data(data.GetUnsignedInt32, offset, 5)
196        offset += 4
197        self.assertLess(fabs(data.GetFloat(error, offset) - 6), 1, "barfoo[1].c == 6")
198        self.assertSuccess(error)
199
200        new_object = barfoo.CreateValueFromData(
201            "new_object", data, barfoo.GetType().GetBasicType(lldb.eBasicTypeInt)
202        )
203        self.assertEqual(new_object.GetValue(), "1", "new_object == 1")
204
205        if data.GetByteOrder() == lldb.eByteOrderBig:
206            data.SetData(
207                error, "\0\0\0A", data.GetByteOrder(), data.GetAddressByteSize()
208            )
209        else:
210            data.SetData(
211                error, "A\0\0\0", data.GetByteOrder(), data.GetAddressByteSize()
212            )
213        self.assertSuccess(error)
214
215        data2 = lldb.SBData()
216        data2.SetData(error, "BCD", data.GetByteOrder(), data.GetAddressByteSize())
217        self.assertSuccess(error)
218
219        data.Append(data2)
220
221        # this breaks on EBCDIC
222        offset = 0
223        self.assert_data(data.GetUnsignedInt32, offset, 65)
224        offset += 4
225        self.assert_data(data.GetUnsignedInt8, offset, 66)
226        offset += 1
227        self.assert_data(data.GetUnsignedInt8, offset, 67)
228        offset += 1
229        self.assert_data(data.GetUnsignedInt8, offset, 68)
230        offset += 1
231
232        # check the new API calls introduced per LLVM llvm.org/prenhancement request
233        # 11619 (Allow creating SBData values from arrays or primitives in
234        # Python)
235
236        hello_str = "hello!"
237        data2 = lldb.SBData.CreateDataFromCString(
238            process.GetByteOrder(), process.GetAddressByteSize(), hello_str
239        )
240        self.assertEqual(len(data2.uint8), len(hello_str))
241        self.assertEqual(data2.uint8[0], 104, "h == 104")
242        self.assertEqual(data2.uint8[1], 101, "e == 101")
243        self.assertEqual(data2.uint8[2], 108, "l == 108")
244        self.assert_data(data2.GetUnsignedInt8, 3, 108)  # l
245        self.assertEqual(data2.uint8[4], 111, "o == 111")
246        self.assert_data(data2.GetUnsignedInt8, 5, 33)  # !
247
248        uint_lists = [[1, 2, 3, 4, 5], [int(i) for i in [1, 2, 3, 4, 5]]]
249        int_lists = [[2, -2], [int(i) for i in [2, -2]]]
250
251        for l in uint_lists:
252            data2 = lldb.SBData.CreateDataFromUInt64Array(
253                process.GetByteOrder(), process.GetAddressByteSize(), l
254            )
255            self.assert_data(data2.GetUnsignedInt64, 0, 1)
256            self.assert_data(data2.GetUnsignedInt64, 8, 2)
257            self.assert_data(data2.GetUnsignedInt64, 16, 3)
258            self.assert_data(data2.GetUnsignedInt64, 24, 4)
259            self.assert_data(data2.GetUnsignedInt64, 32, 5)
260
261            self.assertEqual(
262                data2.uint64s,
263                [1, 2, 3, 4, 5],
264                "read_data_helper failure: data2 == [1,2,3,4,5]",
265            )
266
267        for l in int_lists:
268            data2 = lldb.SBData.CreateDataFromSInt32Array(
269                process.GetByteOrder(), process.GetAddressByteSize(), l
270            )
271            self.assertEqual(data2.sint32[0:2], [2, -2], "signed32 data2 = [2,-2]")
272
273        data2.Append(
274            lldb.SBData.CreateDataFromSInt64Array(
275                process.GetByteOrder(), process.GetAddressByteSize(), int_lists[0]
276            )
277        )
278        self.assert_data(data2.GetSignedInt32, 0, 2)
279        self.assert_data(data2.GetSignedInt32, 4, -2)
280        self.assertEqual(data2.sint64[1:3], [2, -2], "signed64 data2 = [2,-2]")
281
282        for l in int_lists:
283            data2 = lldb.SBData.CreateDataFromSInt64Array(
284                process.GetByteOrder(), process.GetAddressByteSize(), l
285            )
286            self.assert_data(data2.GetSignedInt64, 0, 2)
287            self.assert_data(data2.GetSignedInt64, 8, -2)
288            self.assertEqual(data2.sint64[0:2], [2, -2], "signed64 data2 = [2,-2]")
289
290        for l in uint_lists:
291            data2 = lldb.SBData.CreateDataFromUInt32Array(
292                process.GetByteOrder(), process.GetAddressByteSize(), l
293            )
294            self.assert_data(data2.GetUnsignedInt32, 0, 1)
295            self.assert_data(data2.GetUnsignedInt32, 4, 2)
296            self.assert_data(data2.GetUnsignedInt32, 8, 3)
297            self.assert_data(data2.GetUnsignedInt32, 12, 4)
298            self.assert_data(data2.GetUnsignedInt32, 16, 5)
299
300        bool_list = [True, True, False, False, True, False]
301
302        data2 = lldb.SBData.CreateDataFromSInt32Array(
303            process.GetByteOrder(), process.GetAddressByteSize(), bool_list
304        )
305        self.assertEqual(
306            data2.sint32[0:6], [1, 1, 0, 0, 1, 0], "signed32 data2 = [1, 1, 0, 0, 1, 0]"
307        )
308
309        data2 = lldb.SBData.CreateDataFromUInt32Array(
310            process.GetByteOrder(), process.GetAddressByteSize(), bool_list
311        )
312        self.assertEqual(
313            data2.uint32[0:6],
314            [1, 1, 0, 0, 1, 0],
315            "unsigned32 data2 = [1, 1, 0, 0, 1, 0]",
316        )
317
318        data2 = lldb.SBData.CreateDataFromSInt64Array(
319            process.GetByteOrder(), process.GetAddressByteSize(), bool_list
320        )
321        self.assertEqual(
322            data2.sint64[0:6], [1, 1, 0, 0, 1, 0], "signed64 data2 = [1, 1, 0, 0, 1, 0]"
323        )
324
325        data2 = lldb.SBData.CreateDataFromUInt64Array(
326            process.GetByteOrder(), process.GetAddressByteSize(), bool_list
327        )
328        self.assertEqual(
329            data2.uint64[0:6], [1, 1, 0, 0, 1, 0], "signed64 data2 = [1, 1, 0, 0, 1, 0]"
330        )
331
332        data2 = lldb.SBData.CreateDataFromDoubleArray(
333            process.GetByteOrder(), process.GetAddressByteSize(), [3.14, 6.28, 2.71]
334        )
335        self.assertLess(
336            fabs(data2.GetDouble(error, 0) - 3.14), 0.5, "double data2[0] = 3.14"
337        )
338        self.assertSuccess(error)
339        self.assertLess(
340            fabs(data2.GetDouble(error, 8) - 6.28), 0.5, "double data2[1] = 6.28"
341        )
342        self.assertSuccess(error)
343        self.assertLess(
344            fabs(data2.GetDouble(error, 16) - 2.71), 0.5, "double data2[2] = 2.71"
345        )
346        self.assertSuccess(error)
347
348        data2 = lldb.SBData()
349
350        data2.SetDataFromCString(hello_str)
351        self.assertEqual(len(data2.uint8), len(hello_str))
352        self.assert_data(data2.GetUnsignedInt8, 0, 104)
353        self.assert_data(data2.GetUnsignedInt8, 1, 101)
354        self.assert_data(data2.GetUnsignedInt8, 2, 108)
355        self.assert_data(data2.GetUnsignedInt8, 3, 108)
356        self.assert_data(data2.GetUnsignedInt8, 4, 111)
357        self.assert_data(data2.GetUnsignedInt8, 5, 33)
358
359        data2.SetDataFromUInt64Array([1, 2, 3, 4, 5, 2**63])
360        self.assert_data(data2.GetUnsignedInt64, 0, 1)
361        self.assert_data(data2.GetUnsignedInt64, 8, 2)
362        self.assert_data(data2.GetUnsignedInt64, 16, 3)
363        self.assert_data(data2.GetUnsignedInt64, 24, 4)
364        self.assert_data(data2.GetUnsignedInt64, 32, 5)
365        self.assert_data(data2.GetUnsignedInt64, 40, 2**63)
366
367        self.assertEqual(
368            data2.uint64[0], 1, "read_data_helper failure: set data2[0] = 1"
369        )
370        self.assertEqual(
371            data2.uint64[1], 2, "read_data_helper failure: set data2[1] = 2"
372        )
373        self.assertEqual(
374            data2.uint64[2], 3, "read_data_helper failure: set data2[2] = 3"
375        )
376        self.assertEqual(
377            data2.uint64[3], 4, "read_data_helper failure: set data2[3] = 4"
378        )
379        self.assertEqual(
380            data2.uint64[4], 5, "read_data_helper failure: set data2[4] = 5"
381        )
382
383        self.assertEqual(
384            data2.uint64[0:2],
385            [1, 2],
386            "read_data_helper failure: set data2[0:2] = [1,2]",
387        )
388
389        data2.SetDataFromSInt32Array([2, -2])
390        self.assert_data(data2.GetSignedInt32, 0, 2)
391        self.assert_data(data2.GetSignedInt32, 4, -2)
392
393        data2.SetDataFromSInt64Array([2, -2])
394        self.assert_data(data2.GetSignedInt64, 0, 2)
395        self.assert_data(data2.GetSignedInt64, 8, -2)
396
397        data2.SetDataFromUInt32Array([1, 2, 3, 4, 5])
398        self.assert_data(data2.GetUnsignedInt32, 0, 1)
399        self.assert_data(data2.GetUnsignedInt32, 4, 2)
400        self.assert_data(data2.GetUnsignedInt32, 8, 3)
401        self.assert_data(data2.GetUnsignedInt32, 12, 4)
402        self.assert_data(data2.GetUnsignedInt32, 16, 5)
403
404        self.assertEqual(
405            data2.uint32[0], 1, "read_data_helper failure: set 32-bit data2[0] = 1"
406        )
407        self.assertEqual(
408            data2.uint32[1], 2, "read_data_helper failure: set 32-bit data2[1] = 2"
409        )
410        self.assertEqual(
411            data2.uint32[2], 3, "read_data_helper failure: set 32-bit data2[2] = 3"
412        )
413        self.assertEqual(
414            data2.uint32[3], 4, "read_data_helper failure: set 32-bit data2[3] = 4"
415        )
416        self.assertEqual(
417            data2.uint32[4], 5, "read_data_helper failure: set 32-bit data2[4] = 5"
418        )
419
420        data2.SetDataFromDoubleArray([3.14, 6.28, 2.71])
421        self.assertLess(
422            fabs(data2.GetDouble(error, 0) - 3.14), 0.5, "set double data2[0] = 3.14"
423        )
424        self.assertLess(
425            fabs(data2.GetDouble(error, 8) - 6.28), 0.5, "set double data2[1] = 6.28"
426        )
427        self.assertLess(
428            fabs(data2.GetDouble(error, 16) - 2.71), 0.5, "set double data2[2] = 2.71"
429        )
430
431        self.assertLess(
432            fabs(data2.double[0] - 3.14),
433            0.5,
434            "read_data_helper failure: set double data2[0] = 3.14",
435        )
436        self.assertLess(
437            fabs(data2.double[1] - 6.28),
438            0.5,
439            "read_data_helper failure: set double data2[1] = 6.28",
440        )
441        self.assertLess(
442            fabs(data2.double[2] - 2.71),
443            0.5,
444            "read_data_helper failure: set double data2[2] = 2.71",
445        )
446
447    def assert_data(self, func, arg, expected):
448        """Asserts func(SBError error, arg) == expected."""
449        error = lldb.SBError()
450        result = func(error, arg)
451        if not error.Success():
452            stream = lldb.SBStream()
453            error.GetDescription(stream)
454            self.assertTrue(
455                error.Success(),
456                "%s(error, %s) did not succeed: %s"
457                % (func.__name__, arg, stream.GetData()),
458            )
459        self.assertEqual(
460            expected,
461            result,
462            "%s(error, %s) == %s != %s" % (func.__name__, arg, result, expected),
463        )
464