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