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