1#!/usr/bin/env python3
2#
3# Copyright (c) 2021 Intel Corporation
4#
5# SPDX-License-Identifier: Apache-2.0
6
7import binascii
8import logging
9import struct
10import sys
11
12from enum import Enum
13from gdbstubs.gdbstub import GdbStub
14
15logger = logging.getLogger("gdbstub")
16
17# Matches same in coredump.c
18XTENSA_BLOCK_HDR_DUMMY_SOC = 255
19
20# Must match --soc arg options; see get_soc
21class XtensaSoc(Enum):
22    UNKNOWN = 0
23    SAMPLE_CONTROLLER = 1
24    ESP32 = 2
25    INTEL_ADSP_CAVS = 3
26    ESP32S2 = 4
27    ESP32S3 = 5
28    DC233C = 6
29
30
31# The previous version of this script didn't need to know
32# what toolchain Zephyr was built with; it assumed sample_controller
33# was built with the Zephyr SDK and ESP32 with Espressif's.
34# However, if a SOC can be built by two separate toolchains,
35# there is a chance that the GDBs provided by the toolchains will
36# assign different indices to the same registers. For example, the
37# Intel ADSP family of SOCs can be built with both Zephyr's
38# SDK and Cadence's XCC toolchain. With the same SOC APL,
39# the SDK's GDB assigns PC the index 0, while XCC's GDB assigns
40# it the index 32.
41#
42# (The Espressif value isn't really required, since ESP32 can
43# only be built with Espressif's toolchain, but it's included for
44# completeness.)
45class XtensaToolchain(Enum):
46    UNKNOWN = 0
47    ZEPHYR = 1
48    XCC = 2
49    ESPRESSIF = 3
50
51
52def get_gdb_reg_definition(soc, toolchain):
53    if soc == XtensaSoc.SAMPLE_CONTROLLER:
54        return GdbRegDef_Sample_Controller
55    elif soc == XtensaSoc.ESP32:
56        return GdbRegDef_ESP32
57    elif soc == XtensaSoc.INTEL_ADSP_CAVS:
58        if toolchain == XtensaToolchain.ZEPHYR:
59            return GdbRegDef_Intel_Adsp_CAVS_Zephyr
60        elif toolchain == XtensaToolchain.XCC:
61            return GdbRegDef_Intel_Adsp_CAVS_XCC
62        elif toolchain == XtensaToolchain.ESPRESSIF:
63            logger.error("Can't use espressif toolchain with CAVS. " +
64                "Use zephyr or xcc instead. Exiting...")
65            sys.exit(1)
66        else:
67            raise NotImplementedError
68    elif soc == XtensaSoc.ESP32S2:
69        return GdbRegDef_ESP32S2
70    elif soc == XtensaSoc.ESP32S3:
71        return GdbRegDef_ESP32S3
72    elif soc == XtensaSoc.DC233C:
73        return GdbRegDef_DC233C
74    else:
75        raise NotImplementedError
76
77
78class ExceptionCodes(Enum):
79    # Matches arch/xtensa/core/fatal.c->xtensa_exccause
80    ILLEGAL_INSTRUCTION = 0
81    # Syscall not fatal
82    INSTR_FETCH_ERROR = 2
83    LOAD_STORE_ERROR = 3
84    # Level-1 interrupt not fatal
85    ALLOCA = 5
86    DIVIDE_BY_ZERO = 6
87    PRIVILEGED = 8
88    LOAD_STORE_ALIGNMENT = 9
89    INSTR_PIF_DATA_ERROR = 12
90    LOAD_STORE_PIF_DATA_ERROR = 13
91    INSTR_PIF_ADDR_ERROR = 14
92    LOAD_STORE_PIF_ADDR_ERROR = 15
93    INSTR_TLB_MISS = 16
94    INSTR_TLB_MULTI_HIT = 17
95    INSTR_FETCH_PRIVILEGE = 18
96    INST_FETCH_PROHIBITED = 20
97    LOAD_STORE_TLB_MISS = 24
98    LOAD_STORE_TLB_MULTI_HIT = 25
99    LOAD_STORE_PRIVILEGE = 26
100    LOAD_PROHIBITED = 28
101    STORE_PROHIBITED = 29
102    # Coprocessor disabled spans 32 - 39
103    COPROCESSOR_DISABLED_START = 32
104    COPROCESSOR_DISABLED_END = 39
105    Z_EXCEPT_REASON = 63
106    # Others (reserved / unknown) map to default signal
107
108
109class GdbStub_Xtensa(GdbStub):
110
111    GDB_SIGNAL_DEFAULT = 7
112
113    # Mapping based on section 4.4.1.5 of the
114    # Xtensa ISA Reference Manual (Table 4–64. Exception Causes)
115    # Somewhat arbitrary; included only because GDB requests it
116    GDB_SIGNAL_MAPPING = {
117        ExceptionCodes.ILLEGAL_INSTRUCTION: 4,
118        ExceptionCodes.INSTR_FETCH_ERROR: 7,
119        ExceptionCodes.LOAD_STORE_ERROR: 11,
120        ExceptionCodes.ALLOCA: 7,
121        ExceptionCodes.DIVIDE_BY_ZERO: 8,
122        ExceptionCodes.PRIVILEGED: 11,
123        ExceptionCodes.LOAD_STORE_ALIGNMENT: 7,
124        ExceptionCodes.INSTR_PIF_DATA_ERROR: 7,
125        ExceptionCodes.LOAD_STORE_PIF_DATA_ERROR: 7,
126        ExceptionCodes.INSTR_PIF_ADDR_ERROR: 11,
127        ExceptionCodes.LOAD_STORE_PIF_ADDR_ERROR: 11,
128        ExceptionCodes.INSTR_TLB_MISS: 11,
129        ExceptionCodes.INSTR_TLB_MULTI_HIT: 11,
130        ExceptionCodes.INSTR_FETCH_PRIVILEGE: 11,
131        ExceptionCodes.INST_FETCH_PROHIBITED: 11,
132        ExceptionCodes.LOAD_STORE_TLB_MISS: 11,
133        ExceptionCodes.LOAD_STORE_TLB_MULTI_HIT: 11,
134        ExceptionCodes.LOAD_STORE_PRIVILEGE: 11,
135        ExceptionCodes.LOAD_PROHIBITED: 11,
136        ExceptionCodes.STORE_PROHIBITED: 11,
137        ExceptionCodes.Z_EXCEPT_REASON: 6,
138    }
139
140    reg_fmt = "<I"
141
142    def __init__(self, logfile, elffile):
143        super().__init__(logfile=logfile, elffile=elffile)
144
145        self.registers = None
146        self.exception_code = None
147        self.gdb_signal = self.GDB_SIGNAL_DEFAULT
148
149        self.parse_arch_data_block()
150        self.compute_signal()
151
152
153    def parse_arch_data_block(self):
154        arch_data_blk = self.logfile.get_arch_data()['data']
155
156        self.version = struct.unpack('H', arch_data_blk[1:3])[0]
157        logger.debug("Xtensa GDB stub version: %d" % self.version)
158
159        # Get SOC and toolchain to get correct format for unpack
160        self.soc = XtensaSoc(bytearray(arch_data_blk)[0])
161        logger.debug("Xtensa SOC: %s" % self.soc.name)
162
163        if self.version >= 2:
164            self.toolchain = XtensaToolchain(bytearray(arch_data_blk)[3])
165            arch_data_blk_regs = arch_data_blk[4:]
166        else:
167            # v1 only supported ESP32 and sample_controller, each of which
168            # only build with one toolchain
169            if self.soc == XtensaSoc.ESP32:
170                self.toolchain = XtensaToolchain.ESPRESSIF
171            else:
172                self.toolchain = XtensaToolchain.ZEPHYR
173            arch_data_blk_regs = arch_data_blk[3:]
174
175        logger.debug("Xtensa toolchain: %s" % self.toolchain.name)
176
177        self.gdb_reg_def = get_gdb_reg_definition(self.soc, self.toolchain)
178
179        tu = struct.unpack(self.gdb_reg_def.ARCH_DATA_BLK_STRUCT_REGS,
180                arch_data_blk_regs)
181
182        self.registers = dict()
183
184        self.map_registers(tu)
185
186
187    def map_registers(self, tu):
188        i = 0
189        for r in self.gdb_reg_def.RegNum:
190            reg_num = r.value
191            # Dummy WINDOWBASE and WINDOWSTART to enable GDB
192            # without dumping them and all AR registers;
193            # avoids interfering with interrupts / exceptions
194            if r == self.gdb_reg_def.RegNum.WINDOWBASE:
195                self.registers[reg_num] = 0
196            elif r == self.gdb_reg_def.RegNum.WINDOWSTART:
197                self.registers[reg_num] = 1
198            else:
199                if r == self.gdb_reg_def.RegNum.EXCCAUSE:
200                    self.exception_code = tu[i]
201                self.registers[reg_num] = tu[i]
202            i += 1
203
204
205    def compute_signal(self):
206        sig = self.GDB_SIGNAL_DEFAULT
207        code = ExceptionCodes(self.exception_code)
208
209        if code is None:
210            sig = self.GDB_SIGNAL_DEFAULT
211
212        if code in self.GDB_SIGNAL_MAPPING:
213            sig = self.GDB_SIGNAL_MAPPING[code]
214        elif ExceptionCodes.COPROCESSOR_DISABLED_START.value <= code <= \
215            ExceptionCodes.COPROCESSOR_DISABLED_END.value:
216            sig = 8
217
218        self.gdb_signal = sig
219
220
221    def handle_register_group_read_packet(self):
222        idx = 0
223        pkt = b''
224
225        GDB_G_PKT_MAX_REG = \
226            max([reg_num.value for reg_num in self.gdb_reg_def.RegNum])
227
228        # We try to send as many of the registers listed
229        # as possible, but we are constrained by the
230        # maximum length of the g packet
231        while idx <= GDB_G_PKT_MAX_REG and idx * 4 < self.gdb_reg_def.SOC_GDB_GPKT_BIN_SIZE:
232            if idx in self.registers:
233                bval = struct.pack(self.reg_fmt, self.registers[idx])
234                pkt += binascii.hexlify(bval)
235            else:
236                pkt += b'x' * 8
237
238            idx += 1
239
240        self.put_gdb_packet(pkt)
241
242
243    def handle_register_single_read_packet(self, pkt):
244        # format is pXX, where XX is the hex representation of the idx
245        regIdx = int('0x' + pkt[1:].decode('utf8'), 16)
246        try:
247            bval = struct.pack(self.reg_fmt, self.registers[regIdx])
248            self.put_gdb_packet(binascii.hexlify(bval))
249        except KeyError:
250            self.put_gdb_packet(b'x' * 8)
251
252
253# The following classes map registers to their index used by
254# the GDB of a specific SOC and toolchain. See xtensa_config.c.
255
256# WARNING: IF YOU CHANGE THE ORDER OF THE REGISTERS IN ONE
257# MAPPING, YOU MUST CHANGE THE ORDER TO MATCH IN THE OTHERS
258# AND IN arch/xtensa/core/coredump.c's xtensa_arch_block.r.
259# See map_registers.
260
261# For the same reason, even though the WINDOWBASE and WINDOWSTART
262# values are dummied by this script, they have to be last in the
263# mapping below.
264
265
266# sample_controller is unique to Zephyr SDK
267# sdk-ng -> overlays/xtensa_sample_controller/gdb/gdb/xtensa-config.c
268class GdbRegDef_Sample_Controller:
269    ARCH_DATA_BLK_STRUCT_REGS = '<IIIIIIIIIIIIIIIIIIIIII'
270
271    # This fits the maximum possible register index (110).
272    # Unlike on ESP32 GDB, there doesn't seem to be an
273    # actual hard limit to how big the g packet can be.
274    SOC_GDB_GPKT_BIN_SIZE = 444
275
276
277    class RegNum(Enum):
278        PC = 0
279        EXCCAUSE = 77
280        EXCVADDR = 83
281        SAR = 33
282        PS = 38
283        SCOMPARE1 = 39
284        A0 = 89
285        A1 = 90
286        A2 = 91
287        A3 = 92
288        A4 = 93
289        A5 = 94
290        A6 = 95
291        A7 = 96
292        A8 = 97
293        A9 = 98
294        A10 = 99
295        A11 = 100
296        A12 = 101
297        A13 = 102
298        A14 = 103
299        A15 = 104
300        # LBEG, LEND, and LCOUNT not on sample_controller
301        WINDOWBASE = 34
302        WINDOWSTART = 35
303
304
305# ESP32 is unique to espressif toolchain
306# espressif xtensa-overlays -> xtensa_esp32/gdb/gdb/xtensa-config.c
307class GdbRegDef_ESP32:
308    ARCH_DATA_BLK_STRUCT_REGS = '<IIIIIIIIIIIIIIIIIIIIIIIII'
309    SOC_GDB_GPKT_BIN_SIZE = 420
310
311    class RegNum(Enum):
312        PC = 0
313        EXCCAUSE = 143
314        EXCVADDR = 149
315        SAR = 68
316        PS = 73
317        SCOMPARE1 = 76
318        A0 = 157
319        A1 = 158
320        A2 = 159
321        A3 = 160
322        A4 = 161
323        A5 = 162
324        A6 = 163
325        A7 = 164
326        A8 = 165
327        A9 = 166
328        A10 = 167
329        A11 = 168
330        A12 = 169
331        A13 = 170
332        A14 = 171
333        A15 = 172
334        LBEG = 65
335        LEND = 66
336        LCOUNT = 67
337        WINDOWBASE = 69
338        WINDOWSTART = 70
339
340class GdbRegDef_ESP32S2:
341    ARCH_DATA_BLK_STRUCT_REGS = '<IIIIIIIIIIIIIIIIIIIII'
342    SOC_GDB_GPKT_BIN_SIZE = 420
343
344    class RegNum(Enum):
345        PC = 0
346        EXCCAUSE = 99
347        EXCVADDR = 115
348        SAR = 65
349        PS = 70
350        A0 = 155
351        A1 = 156
352        A2 = 157
353        A3 = 158
354        A4 = 159
355        A5 = 160
356        A6 = 161
357        A7 = 162
358        A8 = 163
359        A9 = 164
360        A10 = 165
361        A11 = 166
362        A12 = 167
363        A13 = 168
364        A14 = 169
365        A15 = 170
366        WINDOWBASE = 66
367        WINDOWSTART = 67
368
369class GdbRegDef_ESP32S3:
370    ARCH_DATA_BLK_STRUCT_REGS = '<IIIIIIIIIIIIIIIIIIIIIIIII'
371    SOC_GDB_GPKT_BIN_SIZE = 420
372
373    class RegNum(Enum):
374        PC = 0
375        EXCCAUSE = 166
376        EXCVADDR = 172
377        SAR = 68
378        PS = 73
379        SCOMPARE1 = 76
380        A0 = 212
381        A1 = 213
382        A2 = 214
383        A3 = 215
384        A4 = 216
385        A5 = 217
386        A6 = 218
387        A7 = 219
388        A8 = 220
389        A9 = 221
390        A10 = 222
391        A11 = 223
392        A12 = 224
393        A13 = 225
394        A14 = 226
395        A15 = 227
396        LBEG = 65
397        LEND = 66
398        LCOUNT = 67
399        WINDOWBASE = 69
400        WINDOWSTART = 70
401
402# sdk-ng -> overlays/xtensa_intel_apl/gdb/gdb/xtensa-config.c
403class GdbRegDef_Intel_Adsp_CAVS_Zephyr:
404    ARCH_DATA_BLK_STRUCT_REGS = '<IIIIIIIIIIIIIIIIIIIIIIIII'
405
406    # If you send all the registers below (up to index 173)
407    # GDB incorrectly assigns 0 to EXCCAUSE / EXCVADDR... for some
408    # reason. Since APL GDB sends p packets for every An register
409    # even if it was sent in the g packet, I arbitrarily shrunk the
410    # G packet to include up to A1, which fixed the issue.
411    SOC_GDB_GPKT_BIN_SIZE = 640
412
413
414    class RegNum(Enum):
415        PC = 0
416        EXCCAUSE = 148
417        EXCVADDR = 154
418        SAR = 68
419        PS = 74
420        SCOMPARE1 = 77
421        A0 = 158
422        A1 = 159
423        A2 = 160
424        A3 = 161
425        A4 = 162
426        A5 = 163
427        A6 = 164
428        A7 = 165
429        A8 = 166
430        A9 = 167
431        A10 = 168
432        A11 = 169
433        A12 = 170
434        A13 = 171
435        A14 = 172
436        A15 = 173
437        LBEG = 65
438        LEND = 66
439        LCOUNT = 67
440        WINDOWBASE = 70
441        WINDOWSTART = 71
442
443
444# Reverse-engineered from:
445# sof -> src/debug/gdb/gdb.c
446# sof -> src/arch/xtensa/include/xtensa/specreg.h
447class GdbRegDef_Intel_Adsp_CAVS_XCC:
448    ARCH_DATA_BLK_STRUCT_REGS = '<IIIIIIIIIIIIIIIIIIIIIIIII'
449
450    # xt-gdb doesn't use the g packet at all
451    SOC_GDB_GPKT_BIN_SIZE = 0
452
453
454    class RegNum(Enum):
455        PC = 32
456        EXCCAUSE = 744
457        EXCVADDR = 750
458        SAR = 515
459        PS = 742
460        SCOMPARE1 = 524
461        A0 = 256
462        A1 = 257
463        A2 = 258
464        A3 = 259
465        A4 = 260
466        A5 = 261
467        A6 = 262
468        A7 = 263
469        A8 = 264
470        A9 = 265
471        A10 = 266
472        A11 = 267
473        A12 = 268
474        A13 = 269
475        A14 = 270
476        A15 = 271
477        LBEG = 512
478        LEND = 513
479        LCOUNT = 514
480        WINDOWBASE = 584
481        WINDOWSTART = 585
482
483# sdk-ng -> overlays/xtensa_dc233c/gdb/gdb/xtensa-config.c
484class GdbRegDef_DC233C:
485    ARCH_DATA_BLK_STRUCT_REGS = '<IIIIIIIIIIIIIIIIIIIIIIIII'
486
487    SOC_GDB_GPKT_BIN_SIZE = 568
488
489    class RegNum(Enum):
490        PC = 0
491        EXCCAUSE = 93
492        EXCVADDR = 99
493        SAR = 36
494        PS = 42
495        SCOMPARE1 = 44
496        A0 = 105
497        A1 = 106
498        A2 = 107
499        A3 = 108
500        A4 = 109
501        A5 = 110
502        A6 = 111
503        A7 = 112
504        A8 = 113
505        A9 = 114
506        A10 = 115
507        A11 = 116
508        A12 = 117
509        A13 = 118
510        A14 = 119
511        A15 = 120
512        LBEG = 33
513        LEND = 34
514        LCOUNT = 35
515        WINDOWBASE = 38
516        WINDOWSTART = 39
517