forked from zephyrproject-rtos/zephyr
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcoredump_gdbserver.py
executable file
·155 lines (116 loc) · 3.96 KB
/
coredump_gdbserver.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#!/usr/bin/env python3
#
# Copyright (c) 2020 Intel Corporation
#
# SPDX-License-Identifier: Apache-2.0
import argparse
import logging
import os
import socket
import sys
from coredump_parser.log_parser import CoredumpLogFile
from coredump_parser.elf_parser import CoredumpElfFile
import gdbstubs
LOGGING_FORMAT = "[%(levelname)s][%(name)s] %(message)s"
# Only bind to local host
GDBSERVER_HOST = ""
class FakeSocket:
def __init__(self) -> None:
self.in_stream = sys.stdin.buffer
self.out_stream = sys.stdout.buffer
def recv(self, bufsize):
return self.in_stream.read(bufsize)
def send(self, data):
n = self.out_stream.write(data)
self.out_stream.flush()
return n
def close(self):
pass
def parse_args():
parser = argparse.ArgumentParser(allow_abbrev=False)
parser.add_argument("elffile", help="Zephyr ELF binary")
parser.add_argument("logfile", help="Coredump binary log file")
parser.add_argument("--debug", action="store_true",
help="Print extra debugging information")
parser.add_argument("--port", type=int, default=1234,
help="GDB server port")
parser.add_argument("--pipe", action="store_true",
help="Use stdio to communicate with gdb")
parser.add_argument("-v", "--verbose", action="store_true",
help="Print more information")
return parser.parse_args()
def main():
args = parse_args()
# Setup logging
logging.basicConfig(format=LOGGING_FORMAT)
# Setup logging for "parser"
logger = logging.getLogger("parser")
if args.debug:
logger.setLevel(logging.DEBUG)
elif args.verbose:
logger.setLevel(logging.INFO)
else:
logger.setLevel(logging.WARNING)
# Setup logging for follow code
logger = logging.getLogger("gdbserver")
if args.debug:
logger.setLevel(logging.DEBUG)
else:
# Use INFO as default since we need to let user
# know what is going on
logger.setLevel(logging.INFO)
# Setup logging for "gdbstub"
logger = logging.getLogger("gdbstub")
if args.debug:
logger.setLevel(logging.DEBUG)
elif args.verbose:
logger.setLevel(logging.INFO)
else:
logger.setLevel(logging.WARNING)
if not os.path.isfile(args.elffile):
logger.error(f"Cannot find file {args.elffile}, exiting...")
sys.exit(1)
if not os.path.isfile(args.logfile):
logger.error(f"Cannot find file {args.logfile}, exiting...")
sys.exit(1)
logger.info(f"Log file: {args.logfile}")
logger.info(f"ELF file: {args.elffile}")
# Parse the coredump binary log file
logf = CoredumpLogFile(args.logfile)
logf.open()
if not logf.parse():
logger.error("Cannot parse log file, exiting...")
logf.close()
sys.exit(1)
# Parse ELF file for code and read-only data
elff = CoredumpElfFile(args.elffile)
elff.open()
if not elff.parse():
logger.error("Cannot parse ELF file, exiting...")
elff.close()
logf.close()
sys.exit(1)
gdbstub = gdbstubs.get_gdbstub(logf, elff)
if not args.pipe:
# Start a GDB server
gdbserver = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Reuse address so we don't have to wait for socket to be
# close before we can bind to the port again
gdbserver.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
gdbserver.bind((GDBSERVER_HOST, args.port))
gdbserver.listen(1)
logger.info(f"Waiting GDB connection on port {args.port}...")
conn, remote = gdbserver.accept()
else:
conn = FakeSocket()
remote = "pipe"
if conn:
logger.info(f"Accepted GDB connection from {remote}")
gdbstub.run(conn)
conn.close()
gdbserver.close()
logger.info("GDB session finished.")
elff.close()
logf.close()
if __name__ == "__main__":
main()