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