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