forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
arch: arm64: add support for coredump
* Add support for coredump on ARM64 architectures. * Add the script used for post-processing coredump output. Signed-off-by: Marcelo Ruaro <marcelo.ruaro@huawei.com> Signed-off-by: Rodrigo Cataldo <rodrigo.cataldo@huawei.com> Signed-off-by: Roberto Medina <roberto.medina@huawei.com>
- Loading branch information
1 parent
33e3ddd
commit 6622735
Showing
6 changed files
with
243 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
/* | ||
* Copyright (c) 2022 Huawei Technologies SASU | ||
* | ||
* SPDX-License-Identifier: Apache-2.0 | ||
*/ | ||
|
||
#include <string.h> | ||
#include <zephyr/debug/coredump.h> | ||
|
||
/* Identify the version of this block (in case of architecture changes). | ||
* To be interpreted by the target architecture specific block parser. | ||
*/ | ||
#define ARCH_HDR_VER 1 | ||
|
||
/* Structure to store the architecture registers passed arch_coredump_info_dump | ||
* As callee saved registers are not provided in z_arch_esf_t structure in Zephyr | ||
* we just need 22 registers. | ||
*/ | ||
struct arm64_arch_block { | ||
struct { | ||
uint64_t x0; | ||
uint64_t x1; | ||
uint64_t x2; | ||
uint64_t x3; | ||
uint64_t x4; | ||
uint64_t x5; | ||
uint64_t x6; | ||
uint64_t x7; | ||
uint64_t x8; | ||
uint64_t x9; | ||
uint64_t x10; | ||
uint64_t x11; | ||
uint64_t x12; | ||
uint64_t x13; | ||
uint64_t x14; | ||
uint64_t x15; | ||
uint64_t x16; | ||
uint64_t x17; | ||
uint64_t x18; | ||
uint64_t lr; | ||
uint64_t spsr; | ||
uint64_t elr; | ||
} r; | ||
} __packed; | ||
|
||
|
||
/* | ||
* Register block takes up too much stack space | ||
* if defined within function. So define it here. | ||
*/ | ||
static struct arm64_arch_block arch_blk; | ||
|
||
void arch_coredump_info_dump(const z_arch_esf_t *esf) | ||
{ | ||
/* Target architecture information header */ | ||
/* Information just relevant to the python parser */ | ||
struct coredump_arch_hdr_t hdr = { | ||
.id = COREDUMP_ARCH_HDR_ID, | ||
.hdr_version = ARCH_HDR_VER, | ||
.num_bytes = sizeof(arch_blk), | ||
}; | ||
|
||
/* Nothing to process */ | ||
if (esf == NULL) { | ||
return; | ||
} | ||
|
||
(void)memset(&arch_blk, 0, sizeof(arch_blk)); | ||
|
||
/* | ||
* Copies the thread registers to a memory block that will be printed out | ||
* The thread registers are already provided by structure z_arch_esf_t | ||
*/ | ||
arch_blk.r.x0 = esf->x0; | ||
arch_blk.r.x1 = esf->x1; | ||
arch_blk.r.x2 = esf->x2; | ||
arch_blk.r.x3 = esf->x3; | ||
arch_blk.r.x4 = esf->x4; | ||
arch_blk.r.x5 = esf->x5; | ||
arch_blk.r.x6 = esf->x6; | ||
arch_blk.r.x7 = esf->x7; | ||
arch_blk.r.x8 = esf->x8; | ||
arch_blk.r.x9 = esf->x9; | ||
arch_blk.r.x10 = esf->x10; | ||
arch_blk.r.x11 = esf->x11; | ||
arch_blk.r.x12 = esf->x12; | ||
arch_blk.r.x13 = esf->x13; | ||
arch_blk.r.x14 = esf->x14; | ||
arch_blk.r.x15 = esf->x15; | ||
arch_blk.r.x16 = esf->x16; | ||
arch_blk.r.x17 = esf->x17; | ||
arch_blk.r.x18 = esf->x18; | ||
arch_blk.r.lr = esf->lr; | ||
arch_blk.r.spsr = esf->spsr; | ||
arch_blk.r.elr = esf->elr; | ||
|
||
/* Send for output */ | ||
coredump_buffer_output((uint8_t *)&hdr, sizeof(hdr)); | ||
coredump_buffer_output((uint8_t *)&arch_blk, sizeof(arch_blk)); | ||
} | ||
|
||
uint16_t arch_coredump_tgt_code_get(void) | ||
{ | ||
return COREDUMP_TGT_ARM64; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
#!/usr/bin/env python3 | ||
# | ||
# Copyright (c) 2022 Huawei Technologies SASU | ||
# | ||
# SPDX-License-Identifier: Apache-2.0 | ||
|
||
import binascii | ||
import logging | ||
import struct | ||
|
||
from gdbstubs.gdbstub import GdbStub | ||
|
||
|
||
logger = logging.getLogger("gdbstub") | ||
|
||
|
||
class RegNum(): | ||
X0 = 0 # X0-X29 - 30 GP registers | ||
X1 = 1 | ||
X2 = 2 | ||
X3 = 3 | ||
X4 = 4 | ||
X5 = 5 | ||
X6 = 6 | ||
X7 = 7 | ||
X8 = 8 | ||
X9 = 9 | ||
X10 = 10 | ||
X11 = 11 | ||
X12 = 12 | ||
X13 = 13 | ||
X14 = 14 | ||
X15 = 15 | ||
X16 = 16 | ||
X17 = 17 | ||
X18 = 18 | ||
X19 = 19 | ||
X20 = 20 | ||
X21 = 21 | ||
X22 = 22 | ||
X23 = 23 | ||
X24 = 24 | ||
X25 = 25 | ||
X26 = 26 | ||
X27 = 27 | ||
X28 = 28 | ||
X29 = 29 # Frame pointer register | ||
LR = 30 # X30 Link Register(LR) | ||
SP_EL0 = 31 # Stack pointer EL0 (SP_EL0) | ||
PC = 32 # Program Counter (PC) | ||
|
||
|
||
class GdbStub_ARM64(GdbStub): | ||
ARCH_DATA_BLK_STRUCT = "<QQQQQQQQQQQQQQQQQQQQQQ" | ||
|
||
# Default signal used by all other script, just using the same | ||
GDB_SIGNAL_DEFAULT = 7 | ||
|
||
# The number of registers expected by GDB | ||
GDB_G_PKT_NUM_REGS = 33 | ||
|
||
|
||
def __init__(self, logfile, elffile): | ||
super().__init__(logfile=logfile, elffile=elffile) | ||
self.registers = None | ||
self.gdb_signal = self.GDB_SIGNAL_DEFAULT | ||
|
||
self.parse_arch_data_block() | ||
|
||
def parse_arch_data_block(self): | ||
|
||
arch_data_blk = self.logfile.get_arch_data()['data'] | ||
|
||
tu = struct.unpack(self.ARCH_DATA_BLK_STRUCT, arch_data_blk) | ||
|
||
self.registers = dict() | ||
|
||
self.registers[RegNum.X0] = tu[0] | ||
self.registers[RegNum.X1] = tu[1] | ||
self.registers[RegNum.X2] = tu[2] | ||
self.registers[RegNum.X3] = tu[3] | ||
self.registers[RegNum.X4] = tu[4] | ||
self.registers[RegNum.X5] = tu[5] | ||
self.registers[RegNum.X6] = tu[6] | ||
self.registers[RegNum.X7] = tu[7] | ||
self.registers[RegNum.X8] = tu[8] | ||
self.registers[RegNum.X9] = tu[9] | ||
self.registers[RegNum.X10] = tu[10] | ||
self.registers[RegNum.X11] = tu[11] | ||
self.registers[RegNum.X12] = tu[12] | ||
self.registers[RegNum.X13] = tu[13] | ||
self.registers[RegNum.X14] = tu[14] | ||
self.registers[RegNum.X15] = tu[15] | ||
self.registers[RegNum.X16] = tu[16] | ||
self.registers[RegNum.X17] = tu[17] | ||
self.registers[RegNum.X18] = tu[18] | ||
|
||
# Callee saved registers are not provided in __esf structure | ||
# So they will be omitted (set to undefined) when stub generates the | ||
# packet in handle_register_group_read_packet. | ||
|
||
self.registers[RegNum.LR] = tu[19] | ||
self.registers[RegNum.SP_EL0] = tu[20] | ||
self.registers[RegNum.PC] = tu[21] | ||
|
||
|
||
def handle_register_group_read_packet(self): | ||
reg_fmt = "<Q" | ||
|
||
idx = 0 | ||
pkt = b'' | ||
|
||
while idx < self.GDB_G_PKT_NUM_REGS: | ||
if idx in self.registers: | ||
bval = struct.pack(reg_fmt, self.registers[idx]) | ||
pkt += binascii.hexlify(bval) | ||
else: | ||
# Register not in coredump -> unknown value | ||
# Send in "xxxxxxxx" | ||
pkt += b'x' * 16 | ||
|
||
idx += 1 | ||
|
||
self.put_gdb_packet(pkt) | ||
|
||
def handle_register_single_read_packet(self, pkt): | ||
# Mark registers as "<unavailable>". | ||
# 'p' packets are usually used for registers | ||
# other than the general ones (e.g. eax, ebx) | ||
# so we can safely reply "xxxxxxxx" here. | ||
self.put_gdb_packet(b'x' * 16) |