1c1121908SPaolo Severiniimport lldb 2c1121908SPaolo Severiniimport binascii 3c1121908SPaolo Severinifrom lldbsuite.test.lldbtest import * 4c1121908SPaolo Severinifrom lldbsuite.test.decorators import * 5*33c0f93fSPavel Labathfrom lldbsuite.test.gdbclientutils import * 6*33c0f93fSPavel Labathfrom lldbsuite.test.lldbgdbclient import GDBRemoteTestBase 7c1121908SPaolo Severini 8c1121908SPaolo SeveriniLLDB_INVALID_ADDRESS = lldb.LLDB_INVALID_ADDRESS 9c1121908SPaolo Severiniload_address = 0x400000000 10c1121908SPaolo Severini 11c1121908SPaolo Severinidef format_register_value(val): 12c1121908SPaolo Severini """ 13c1121908SPaolo Severini Encode each byte by two hex digits in little-endian order. 14c1121908SPaolo Severini """ 15c1121908SPaolo Severini result = "" 16c1121908SPaolo Severini mask = 0xff 17c1121908SPaolo Severini shift = 0 18c1121908SPaolo Severini for i in range(0, 8): 19c1121908SPaolo Severini x = (val & mask) >> shift 20c1121908SPaolo Severini result += format(x, '02x') 21c1121908SPaolo Severini mask <<= 8 22c1121908SPaolo Severini shift += 8 23c1121908SPaolo Severini return result 24c1121908SPaolo Severini 25c1121908SPaolo Severini 26c1121908SPaolo Severiniclass MyResponder(MockGDBServerResponder): 27c1121908SPaolo Severini current_pc = load_address + 0x0a 28c1121908SPaolo Severini 29c1121908SPaolo Severini def __init__(self, obj_path, module_name = ""): 30c1121908SPaolo Severini self._obj_path = obj_path 31c1121908SPaolo Severini self._module_name = module_name or obj_path 32c1121908SPaolo Severini MockGDBServerResponder.__init__(self) 33c1121908SPaolo Severini 34c1121908SPaolo Severini def respond(self, packet): 35c1121908SPaolo Severini if packet[0:13] == "qRegisterInfo": 36c1121908SPaolo Severini return self.qRegisterInfo(packet[13:]) 37c1121908SPaolo Severini return MockGDBServerResponder.respond(self, packet) 38c1121908SPaolo Severini 39c1121908SPaolo Severini def qSupported(self, client_supported): 40c1121908SPaolo Severini return "qXfer:libraries:read+;PacketSize=1000;vContSupported-" 41c1121908SPaolo Severini 42c1121908SPaolo Severini def qHostInfo(self): 43c1121908SPaolo Severini return "" 44c1121908SPaolo Severini 45c1121908SPaolo Severini def QEnableErrorStrings(self): 46c1121908SPaolo Severini return "" 47c1121908SPaolo Severini 48c1121908SPaolo Severini def qfThreadInfo(self): 49c1121908SPaolo Severini return "OK" 50c1121908SPaolo Severini 51c1121908SPaolo Severini def qRegisterInfo(self, index): 52c1121908SPaolo Severini if (index == 0): 53c1121908SPaolo Severini return "name:pc;alt-name:pc;bitsize:64;offset:0;encoding:uint;format:hex;set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;" 54c1121908SPaolo Severini return "E45" 55c1121908SPaolo Severini 56c1121908SPaolo Severini def qProcessInfo(self): 57c1121908SPaolo Severini return "pid:1;ppid:1;uid:1;gid:1;euid:1;egid:1;name:%s;triple:%s;ptrsize:4" % (hex_encode_bytes("lldb"), hex_encode_bytes("wasm32-unknown-unknown-wasm")) 58c1121908SPaolo Severini 59c1121908SPaolo Severini def haltReason(self): 60c1121908SPaolo Severini return "T05thread:1;" 61c1121908SPaolo Severini 62c1121908SPaolo Severini def readRegister(self, register): 63c1121908SPaolo Severini return format_register_value(self.current_pc) 64c1121908SPaolo Severini 65c1121908SPaolo Severini def qXferRead(self, obj, annex, offset, length): 66c1121908SPaolo Severini if obj == "libraries": 67c1121908SPaolo Severini xml = '<library-list><library name=\"%s\"><section address=\"%d\"/></library></library-list>' % (self._module_name, load_address) 68c1121908SPaolo Severini return xml, False 69c1121908SPaolo Severini else: 70c1121908SPaolo Severini return None, False 71c1121908SPaolo Severini 72c1121908SPaolo Severini def readMemory(self, addr, length): 73c1121908SPaolo Severini if addr < load_address: 74c1121908SPaolo Severini return "E02" 75c1121908SPaolo Severini result = "" 76c1121908SPaolo Severini with open(self._obj_path, mode='rb') as file: 77c1121908SPaolo Severini file_content = bytearray(file.read()) 78c1121908SPaolo Severini addr_from = addr - load_address 79c1121908SPaolo Severini addr_to = addr_from + min(length, len(file_content) - addr_from) 80c1121908SPaolo Severini for i in range(addr_from, addr_to): 81c1121908SPaolo Severini result += format(file_content[i], '02x') 82c1121908SPaolo Severini file.close() 83c1121908SPaolo Severini return result 84c1121908SPaolo Severini 85c1121908SPaolo Severini 86c1121908SPaolo Severiniclass TestWasm(GDBRemoteTestBase): 87c1121908SPaolo Severini 8856b03c35SRaphael Isemann @skipIfAsan 89d41d5286SPavel Labath @skipIfXmlSupportMissing 90c1121908SPaolo Severini def test_load_module_with_embedded_symbols_from_remote(self): 91c1121908SPaolo Severini """Test connecting to a WebAssembly engine via GDB-remote and loading a Wasm module with embedded DWARF symbols""" 92c1121908SPaolo Severini 93c1121908SPaolo Severini yaml_path = "test_wasm_embedded_debug_sections.yaml" 94c1121908SPaolo Severini yaml_base, ext = os.path.splitext(yaml_path) 95c1121908SPaolo Severini obj_path = self.getBuildArtifact(yaml_base) 96c1121908SPaolo Severini self.yaml2obj(yaml_path, obj_path) 97c1121908SPaolo Severini 98c1121908SPaolo Severini self.server.responder = MyResponder(obj_path, "test_wasm") 99c1121908SPaolo Severini 100c1121908SPaolo Severini target = self.dbg.CreateTarget("") 101c1121908SPaolo Severini process = self.connect(target) 102c1121908SPaolo Severini lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateStopped]) 103c1121908SPaolo Severini 104c1121908SPaolo Severini num_modules = target.GetNumModules() 105c1121908SPaolo Severini self.assertEquals(1, num_modules) 106c1121908SPaolo Severini 107c1121908SPaolo Severini module = target.GetModuleAtIndex(0) 108c1121908SPaolo Severini num_sections = module.GetNumSections() 109c1121908SPaolo Severini self.assertEquals(5, num_sections) 110c1121908SPaolo Severini 111c1121908SPaolo Severini code_section = module.GetSectionAtIndex(0) 112c1121908SPaolo Severini self.assertEquals("code", code_section.GetName()) 113c1121908SPaolo Severini self.assertEquals(load_address | code_section.GetFileOffset(), code_section.GetLoadAddress(target)) 114c1121908SPaolo Severini 115c1121908SPaolo Severini debug_info_section = module.GetSectionAtIndex(1) 116c1121908SPaolo Severini self.assertEquals(".debug_info", debug_info_section.GetName()) 117c1121908SPaolo Severini self.assertEquals(load_address | debug_info_section.GetFileOffset(), debug_info_section.GetLoadAddress(target)) 118c1121908SPaolo Severini 119c1121908SPaolo Severini debug_abbrev_section = module.GetSectionAtIndex(2) 120c1121908SPaolo Severini self.assertEquals(".debug_abbrev", debug_abbrev_section.GetName()) 121c1121908SPaolo Severini self.assertEquals(load_address | debug_abbrev_section.GetFileOffset(), debug_abbrev_section.GetLoadAddress(target)) 122c1121908SPaolo Severini 123c1121908SPaolo Severini debug_line_section = module.GetSectionAtIndex(3) 124c1121908SPaolo Severini self.assertEquals(".debug_line", debug_line_section.GetName()) 125c1121908SPaolo Severini self.assertEquals(load_address | debug_line_section.GetFileOffset(), debug_line_section.GetLoadAddress(target)) 126c1121908SPaolo Severini 127c1121908SPaolo Severini debug_str_section = module.GetSectionAtIndex(4) 128c1121908SPaolo Severini self.assertEquals(".debug_str", debug_str_section.GetName()) 129c1121908SPaolo Severini self.assertEquals(load_address | debug_line_section.GetFileOffset(), debug_line_section.GetLoadAddress(target)) 130c1121908SPaolo Severini 131c1121908SPaolo Severini 13256b03c35SRaphael Isemann @skipIfAsan 133d41d5286SPavel Labath @skipIfXmlSupportMissing 134c1121908SPaolo Severini def test_load_module_with_stripped_symbols_from_remote(self): 135c1121908SPaolo Severini """Test connecting to a WebAssembly engine via GDB-remote and loading a Wasm module with symbols stripped into a separate Wasm file""" 136c1121908SPaolo Severini 137c1121908SPaolo Severini sym_yaml_path = "test_sym.yaml" 138c1121908SPaolo Severini sym_yaml_base, ext = os.path.splitext(sym_yaml_path) 139c1121908SPaolo Severini sym_obj_path = self.getBuildArtifact(sym_yaml_base) + ".wasm" 140c1121908SPaolo Severini self.yaml2obj(sym_yaml_path, sym_obj_path) 141c1121908SPaolo Severini 142c1121908SPaolo Severini yaml_path = "test_wasm_external_debug_sections.yaml" 143c1121908SPaolo Severini yaml_base, ext = os.path.splitext(yaml_path) 144c1121908SPaolo Severini obj_path = self.getBuildArtifact(yaml_base) + ".wasm" 145c1121908SPaolo Severini self.yaml2obj(yaml_path, obj_path) 146c1121908SPaolo Severini 147c1121908SPaolo Severini self.server.responder = MyResponder(obj_path, "test_wasm") 148c1121908SPaolo Severini 149c1121908SPaolo Severini folder, _ = os.path.split(obj_path) 150c1121908SPaolo Severini self.runCmd("settings set target.debug-file-search-paths " + os.path.abspath(folder)) 151c1121908SPaolo Severini 152c1121908SPaolo Severini target = self.dbg.CreateTarget("") 153c1121908SPaolo Severini process = self.connect(target) 154c1121908SPaolo Severini lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateStopped]) 155c1121908SPaolo Severini 156c1121908SPaolo Severini num_modules = target.GetNumModules() 157c1121908SPaolo Severini self.assertEquals(1, num_modules) 158c1121908SPaolo Severini 159c1121908SPaolo Severini module = target.GetModuleAtIndex(0) 160c1121908SPaolo Severini num_sections = module.GetNumSections() 161c1121908SPaolo Severini self.assertEquals(5, num_sections) 162c1121908SPaolo Severini 163c1121908SPaolo Severini code_section = module.GetSectionAtIndex(0) 164c1121908SPaolo Severini self.assertEquals("code", code_section.GetName()) 165c1121908SPaolo Severini self.assertEquals(load_address | code_section.GetFileOffset(), code_section.GetLoadAddress(target)) 166c1121908SPaolo Severini 167c1121908SPaolo Severini debug_info_section = module.GetSectionAtIndex(1) 168c1121908SPaolo Severini self.assertEquals(".debug_info", debug_info_section.GetName()) 169c1121908SPaolo Severini self.assertEquals(LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target)) 170c1121908SPaolo Severini 171c1121908SPaolo Severini debug_abbrev_section = module.GetSectionAtIndex(2) 172c1121908SPaolo Severini self.assertEquals(".debug_abbrev", debug_abbrev_section.GetName()) 173c1121908SPaolo Severini self.assertEquals(LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target)) 174c1121908SPaolo Severini 175c1121908SPaolo Severini debug_line_section = module.GetSectionAtIndex(3) 176c1121908SPaolo Severini self.assertEquals(".debug_line", debug_line_section.GetName()) 177c1121908SPaolo Severini self.assertEquals(LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)) 178c1121908SPaolo Severini 179c1121908SPaolo Severini debug_str_section = module.GetSectionAtIndex(4) 180c1121908SPaolo Severini self.assertEquals(".debug_str", debug_str_section.GetName()) 181c1121908SPaolo Severini self.assertEquals(LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)) 182c1121908SPaolo Severini 183c1121908SPaolo Severini 18456b03c35SRaphael Isemann @skipIfAsan 185d41d5286SPavel Labath @skipIfXmlSupportMissing 186c1121908SPaolo Severini def test_load_module_from_file(self): 187c1121908SPaolo Severini """Test connecting to a WebAssembly engine via GDB-remote and loading a Wasm module from a file""" 188c1121908SPaolo Severini 189c1121908SPaolo Severini yaml_path = "test_wasm_embedded_debug_sections.yaml" 190c1121908SPaolo Severini yaml_base, ext = os.path.splitext(yaml_path) 191c1121908SPaolo Severini obj_path = self.getBuildArtifact(yaml_base) 192c1121908SPaolo Severini self.yaml2obj(yaml_path, obj_path) 193c1121908SPaolo Severini 194c1121908SPaolo Severini self.server.responder = MyResponder(obj_path) 195c1121908SPaolo Severini 196c1121908SPaolo Severini target = self.dbg.CreateTarget("") 197c1121908SPaolo Severini process = self.connect(target) 198c1121908SPaolo Severini lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, [lldb.eStateStopped]) 199c1121908SPaolo Severini 200c1121908SPaolo Severini num_modules = target.GetNumModules() 201c1121908SPaolo Severini self.assertEquals(1, num_modules) 202c1121908SPaolo Severini 203c1121908SPaolo Severini module = target.GetModuleAtIndex(0) 204c1121908SPaolo Severini num_sections = module.GetNumSections() 205c1121908SPaolo Severini self.assertEquals(5, num_sections) 206c1121908SPaolo Severini 207c1121908SPaolo Severini code_section = module.GetSectionAtIndex(0) 208c1121908SPaolo Severini self.assertEquals("code", code_section.GetName()) 209c1121908SPaolo Severini self.assertEquals(load_address | code_section.GetFileOffset(), code_section.GetLoadAddress(target)) 210c1121908SPaolo Severini 211c1121908SPaolo Severini debug_info_section = module.GetSectionAtIndex(1) 212c1121908SPaolo Severini self.assertEquals(".debug_info", debug_info_section.GetName()) 213c1121908SPaolo Severini self.assertEquals(LLDB_INVALID_ADDRESS, debug_info_section.GetLoadAddress(target)) 214c1121908SPaolo Severini 215c1121908SPaolo Severini debug_abbrev_section = module.GetSectionAtIndex(2) 216c1121908SPaolo Severini self.assertEquals(".debug_abbrev", debug_abbrev_section.GetName()) 217c1121908SPaolo Severini self.assertEquals(LLDB_INVALID_ADDRESS, debug_abbrev_section.GetLoadAddress(target)) 218c1121908SPaolo Severini 219c1121908SPaolo Severini debug_line_section = module.GetSectionAtIndex(3) 220c1121908SPaolo Severini self.assertEquals(".debug_line", debug_line_section.GetName()) 221c1121908SPaolo Severini self.assertEquals(LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)) 222c1121908SPaolo Severini 223c1121908SPaolo Severini debug_str_section = module.GetSectionAtIndex(4) 224c1121908SPaolo Severini self.assertEquals(".debug_str", debug_str_section.GetName()) 225c1121908SPaolo Severini self.assertEquals(LLDB_INVALID_ADDRESS, debug_line_section.GetLoadAddress(target)) 226c1121908SPaolo Severini 227