import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * from lldbsuite.test import lldbutil import json import uuid import os import shutil import time class TestObjectFileJSON(TestBase): TRIPLE = "arm64-apple-macosx13.0.0" def setUp(self): TestBase.setUp(self) self.source = "main.c" def emitJSON(self, data, path): json_object = json.dumps(data, indent=4) with open(path, "w") as outfile: outfile.write(json_object) def toModuleSpec(self, path): module_spec = lldb.SBModuleSpec() module_spec.SetFileSpec(lldb.SBFileSpec(path)) return module_spec @no_debug_info_test def test_target(self): triple = "arm64-apple-macosx13.0.0" data = { "triple": triple, "uuid": str(uuid.uuid4()), "type": "executable", } json_object_file = self.getBuildArtifact("a.json") self.emitJSON(data, json_object_file) target = self.dbg.CreateTarget(json_object_file) self.assertTrue(target.IsValid()) self.assertEqual(target.GetTriple(), triple) @no_debug_info_test def test_module(self): self.build() exe = self.getBuildArtifact("a.out") target = self.dbg.CreateTarget(exe) data = { "triple": target.GetTriple(), "uuid": str(uuid.uuid4()), } json_object_file_b = self.getBuildArtifact("b.json") self.emitJSON(data, json_object_file_b) module = target.AddModule(self.toModuleSpec(json_object_file_b)) self.assertFalse(module.IsValid()) TEXT_file_addr = 0x100000000 DATA_file_addr = 0x100001000 foo_file_addr = TEXT_file_addr + 0x100 bar_file_addr = DATA_file_addr + 0x10 TEXT_size = 0x222 text_size = 0x20 DATA_size = 0x333 foo_size = 0x11 bar_size = 0x22 slide = 0x100000000 data = { "triple": target.GetTriple(), "uuid": str(uuid.uuid4()), "type": "sharedlibrary", "sections": [ { "user_id": 0x100, "name": "__PAGEZERO", "type": "container", "address": 0, "size": 0x100000000, "flags": 0x101 }, { "user_id": 0x200, "name": "__TEXT", "type": "container", "address": TEXT_file_addr, "size": TEXT_size, "flags": 0x202, "file_offset": 0, "file_size": TEXT_size, "read": True, "write": False, "execute": True, "subsections": [ { "name": "__text", "type": "code", "address": TEXT_file_addr, "size": text_size, "alignment": 2, "read": True, "write": False, "execute": True, }, { "name": "__fake", "address": TEXT_file_addr + 1 * text_size, "size": text_size, "fake": True }, { "name": "__encrypted", "address": TEXT_file_addr + 2 * text_size, "size": text_size, "encrypted": True }, { "name": "__tls", "address": TEXT_file_addr + 2 * text_size, "size": text_size, "thread_specific": True } ], }, { "name": "__DATA", "type": "data", "address": DATA_file_addr, "size": DATA_size, "read": True, "write": True, "execute": False, "flags": 0x303, "file_offset": DATA_file_addr - TEXT_file_addr, "file_size": DATA_size, }, ], "symbols": [ { "name": "foo", "type": "code", "address": foo_file_addr, "size": foo_size, }, { "name": "bar", "type": "data", "address": bar_file_addr, "size": bar_size, }, ], } json_object_file_c = self.getBuildArtifact("c.json") self.emitJSON(data, json_object_file_c) module = target.AddModule(self.toModuleSpec(json_object_file_c)) self.assertTrue(module.IsValid()) TEXT_section = module.GetSectionAtIndex(0) self.assertTrue(TEXT_section.IsValid()) self.assertEqual(TEXT_section.GetName(), "__PAGEZERO") self.assertEqual(TEXT_section.file_addr, 0) self.assertEqual(TEXT_section.size, 0x100000000) self.assertEqual(TEXT_section.GetSectionType(), lldb.eSectionTypeContainer) self.assertEqual(TEXT_section.GetNumSubSections(), 0) text_permissions = TEXT_section.GetPermissions() self.assertFalse((text_permissions & lldb.ePermissionsReadable) != 0) self.assertFalse((text_permissions & lldb.ePermissionsWritable) != 0) self.assertFalse((text_permissions & lldb.ePermissionsExecutable) != 0) TEXT_section = module.GetSectionAtIndex(1) self.assertTrue(TEXT_section.IsValid()) self.assertEqual(TEXT_section.GetName(), "__TEXT") self.assertEqual(TEXT_section.file_addr, TEXT_file_addr) self.assertEqual(TEXT_section.size, TEXT_size) self.assertEqual(TEXT_section.file_offset, 0) self.assertEqual(TEXT_section.file_size, TEXT_size) self.assertEqual(TEXT_section.GetSectionType(), lldb.eSectionTypeContainer) self.assertEqual(TEXT_section.GetNumSubSections(), 4) text_permissions = TEXT_section.GetPermissions() self.assertTrue((text_permissions & lldb.ePermissionsReadable) != 0) self.assertFalse((text_permissions & lldb.ePermissionsWritable) != 0) self.assertTrue((text_permissions & lldb.ePermissionsExecutable) != 0) text_section = TEXT_section.GetSubSectionAtIndex(0) self.assertEqual(text_section.GetName(), "__text") self.assertEqual(text_section.size, text_size) self.assertEqual(text_section.GetAlignment(), 4) self.assertEqual(text_section.GetSectionType(), lldb.eSectionTypeCode) self.assertEqual(text_section.GetNumSubSections(), 0) text_permissions = text_section.GetPermissions() self.assertTrue((text_permissions & lldb.ePermissionsReadable) != 0) self.assertFalse((text_permissions & lldb.ePermissionsWritable) != 0) self.assertTrue((text_permissions & lldb.ePermissionsExecutable) != 0) DATA_section = module.GetSectionAtIndex(2) self.assertTrue(DATA_section.IsValid()) self.assertEqual(DATA_section.GetName(), "__DATA") self.assertEqual(DATA_section.file_addr, DATA_file_addr) self.assertEqual(DATA_section.size, DATA_size) self.assertEqual(DATA_section.file_offset, DATA_file_addr - TEXT_file_addr) self.assertEqual(DATA_section.file_size, DATA_size) self.assertEqual(DATA_section.GetSectionType(), lldb.eSectionTypeData) data_permissions = DATA_section.GetPermissions() self.assertTrue((data_permissions & lldb.ePermissionsReadable) != 0) self.assertTrue((data_permissions & lldb.ePermissionsWritable) != 0) self.assertFalse((data_permissions & lldb.ePermissionsExecutable) != 0) foo_symbol = module.FindSymbol("foo") self.assertTrue(foo_symbol.IsValid()) self.assertEqual(foo_symbol.addr.GetFileAddress(), foo_file_addr) self.assertEqual(foo_symbol.GetSize(), foo_size) bar_symbol = module.FindSymbol("bar") self.assertTrue(bar_symbol.IsValid()) self.assertEqual(bar_symbol.addr.GetFileAddress(), bar_file_addr) self.assertEqual(bar_symbol.GetSize(), bar_size) # Verify the user_ids and flags are set correctly since there is no API # for this on lldb.SBSection self.expect("target modules dump sections c.json", substrs = [ "0x0000000000000100 container [0x0000000000000000-0x0000000100000000) --- 0x00000000 0x00000000 0x00000101 c.json.__PAGEZERO", "0x0000000000000200 container [0x0000000100000000-0x0000000100000222) r-x 0x00000000 0x00000222 0x00000202 c.json.__TEXT", "0x0000000000000001 code [0x0000000100000000-0x0000000100000020) r-x 0x00000000 0x00000000 0x00000000 c.json.__TEXT.__text", "0x0000000000000002 code [0x0000000100000020-0x0000000100000040) --- 0x00000000 0x00000000 0x00000000 c.json.__TEXT.__fake", "0x0000000000000003 code [0x0000000100000040-0x0000000100000060) --- 0x00000000 0x00000000 0x00000000 c.json.__TEXT.__encrypted", "0x0000000000000004 code [0x0000000100000040-0x0000000100000060) --- 0x00000000 0x00000000 0x00000000 c.json.__TEXT.__tls", "0x0000000000000005 data [0x0000000100001000-0x0000000100001333) rw- 0x00001000 0x00000333 0x00000303 c.json.__DATA" ]) error = target.SetSectionLoadAddress(TEXT_section, TEXT_file_addr + slide) self.assertSuccess(error) error = target.SetSectionLoadAddress(DATA_section, DATA_file_addr + slide) self.assertSuccess(error) self.assertEqual(foo_symbol.addr.GetLoadAddress(target), foo_file_addr + slide) self.assertEqual(bar_symbol.addr.GetLoadAddress(target), bar_file_addr + slide)