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