gdb plugin: Encapsulate the gdb native command gcore as nxgcore
Modify elf with nxgcore and call gcore: (gdb) nxgcore --help usage: [-h] [-o OUTPUT] [-t OBJCOPY] [-r MEMRANGE] options: -h, --help show this help message and exit -o OUTPUT, --output OUTPUT Gcore output file -t OBJCOPY, --objcopy OBJCOPY Select the appropriate architecture for the objcopy tool -r MEMRANGE, --memrange MEMRANGE examples: (gdb) nxgcore -t arm-none-eabi-objcopy -r 0x40200000,0x48000000,0x07 Signed-off-by: wangmingrong1 <wangmingrong1@xiaomi.com>
This commit is contained in:
parent
bdac8c116a
commit
b5c5e4b850
@ -86,7 +86,7 @@ To halt the board:
|
||||
.. code-block::
|
||||
|
||||
(gdb) mon halt
|
||||
|
||||
|
||||
To set a breakpoint:
|
||||
|
||||
.. code-block::
|
||||
@ -104,7 +104,7 @@ and to finally start nuttx:
|
||||
208 sched_getparam(0, ¶m);
|
||||
(gdb) continue
|
||||
Continuing.
|
||||
|
||||
|
||||
.. tip::
|
||||
|
||||
You can abbreviate ``gdb`` commands: ``info b`` is a shortcut for
|
||||
@ -130,8 +130,8 @@ opencd. By default, it assumes:
|
||||
|
||||
* ``CONFIG_DISABLE_MQUEUE=y``
|
||||
* ``CONFIG_LEGACY_PAGING=n``
|
||||
|
||||
If you need these options to be set differently, you will have to edit ``./src/rtos/nuttx_header.h`` from ``openocd``,
|
||||
|
||||
If you need these options to be set differently, you will have to edit ``./src/rtos/nuttx_header.h`` from ``openocd``,
|
||||
change the corresponding settings and then rebuild it.
|
||||
|
||||
Finally, to enable NuttX integration, you need to supply an additional ``openocd`` argument:
|
||||
@ -139,7 +139,7 @@ Finally, to enable NuttX integration, you need to supply an additional ``openocd
|
||||
.. code-block:: console
|
||||
|
||||
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c '$_TARGETNAME configure -rtos nuttx'
|
||||
|
||||
|
||||
Since ``openocd`` also needs to know the memory layout of certain datastructures, you need to have ``gdb``
|
||||
run the following commands once the ``nuttx`` binary is loaded:
|
||||
|
||||
@ -150,7 +150,7 @@ run the following commands once the ``nuttx`` binary is loaded:
|
||||
eval "monitor nuttx.state_offset %d", &((struct tcb_s *)(0))->task_state
|
||||
eval "monitor nuttx.name_offset %d", &((struct tcb_s *)(0))->name
|
||||
eval "monitor nuttx.name_size %d", sizeof(((struct tcb_s *)(0))->name)
|
||||
|
||||
|
||||
One way to do this is to define a gdb `hook` function that will be called when running ``file`` command:
|
||||
|
||||
.. code-block::
|
||||
@ -162,7 +162,7 @@ One way to do this is to define a gdb `hook` function that will be called when r
|
||||
eval "monitor nuttx.name_offset %d", &((struct tcb_s *)(0))->name
|
||||
eval "monitor nuttx.name_size %d", sizeof(((struct tcb_s *)(0))->name)
|
||||
end
|
||||
|
||||
|
||||
You will see that ``openocd`` has received the memory offsets in its output:
|
||||
|
||||
.. code-block::
|
||||
@ -196,10 +196,10 @@ You will see that ``openocd`` has received the memory offsets in its output:
|
||||
Info : state_offset: 26
|
||||
Info : name_offset: 208
|
||||
Info : name_size: 32
|
||||
target halted due to debug-request, current mode: Thread
|
||||
target halted due to debug-request, current mode: Thread
|
||||
xPSR: 0x01000000 pc: 0x000000dc msp: 0x20000cf0
|
||||
target halted due to debug-request, current mode: Thread xPSR: 0x01000000 pc: 0x000000dc msp: 0x20000cf0
|
||||
|
||||
|
||||
.. note:: You will probably see the ``Error: No symbols for NuttX`` error appear once at startup. This is OK
|
||||
unless you see it every time you step the debugger. In this case, it would mean you did not enable debug symbols.
|
||||
|
||||
@ -208,8 +208,8 @@ Now, You can now inspect threads:
|
||||
.. code-block::
|
||||
|
||||
(gdb) info threads
|
||||
Id Target Id Frame
|
||||
* 1 Remote target nx_start_application () at init/nx_bringup.c:261
|
||||
Id Target Id Frame
|
||||
* 1 Remote target nx_start_application () at init/nx_bringup.c:261
|
||||
(gdb) info registers
|
||||
r0 0x0 0
|
||||
r1 0x2f 47
|
||||
@ -261,6 +261,13 @@ the prefix is arm-ebai-none-.
|
||||
*0 Thread 0x20000398 (Name: Idle Task, State: Running, Priority: 0, Stack: 1000) 0x80001ac __start() at chip/stm32_start.c:111
|
||||
1 Thread 0x10000188 (Name: nsh_main, State: Waiting,Semaphore, Priority: 100, Stack: 2000) 0x800aa06 sys_call2() at /home/ajh/work/vela_all/nuttx/include/arch/syscall.h:187
|
||||
|
||||
.. code-block::
|
||||
|
||||
(gdb) (gdb) nxgcore -r 0x40200000,0x48000000,0x07
|
||||
Saved corefile nuttx.core
|
||||
Please run gdbserver.py to parse nuttx.core
|
||||
|
||||
|
||||
The python script has extended many commands like ``thread <id>`` ,
|
||||
``thread apply <all|id list> cmd``, ``nxsetargs`` etc.
|
||||
You can use ``help <command>`` to get help.
|
||||
|
129
tools/gdb/gcore.py
Normal file
129
tools/gdb/gcore.py
Normal file
@ -0,0 +1,129 @@
|
||||
############################################################################
|
||||
# tools/gdb/gcore.py
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import gdb
|
||||
import utils
|
||||
|
||||
|
||||
def create_file_with_size(filename, size):
|
||||
with open(filename, "wb") as f:
|
||||
f.write(b"\0" * size)
|
||||
|
||||
|
||||
def parse_args(args):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("-o", "--output", help="Gcore output file")
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--objcopy",
|
||||
help="Select the appropriate architecture for the objcopy tool",
|
||||
type=str,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--memrange",
|
||||
type=str,
|
||||
)
|
||||
return parser.parse_args(args)
|
||||
|
||||
|
||||
class NXGcore(gdb.Command):
|
||||
def __init__(self):
|
||||
super(NXGcore, self).__init__("nxgcore", gdb.COMMAND_USER)
|
||||
|
||||
def invoke(self, args, from_tty):
|
||||
try:
|
||||
args = parse_args(gdb.string_to_argv(args))
|
||||
except SystemExit:
|
||||
return
|
||||
|
||||
objfile = gdb.current_progspace().objfiles()[0]
|
||||
elffile = objfile.filename
|
||||
tmpfile = tempfile.NamedTemporaryFile(suffix=".elf")
|
||||
|
||||
# Create temporary ELF file with sections for each memory region
|
||||
|
||||
shutil.copy(elffile, tmpfile.name)
|
||||
|
||||
# If no parameters are passed in
|
||||
|
||||
if args.output:
|
||||
corefile = args.output
|
||||
else:
|
||||
corefile = elffile + ".core"
|
||||
|
||||
# Obtain memory range from macros or parameters
|
||||
|
||||
if args.memrange:
|
||||
memregion = args.memrange
|
||||
else:
|
||||
memregion = str(utils.get_symbol_value("CONFIG_BOARD_MEMORY_RANGE"))
|
||||
if len(memregion) < 3:
|
||||
print(
|
||||
"Please set CONFIG_BOARD_MEMORY_RANGE.\n"
|
||||
"Memory range of board. format: <start>,<end>,<flags>,....\n"
|
||||
"start: start address of memory range\n"
|
||||
"end: end address of memory range\n"
|
||||
"flags: Readable 0x1, writable 0x2, executable 0x4\n"
|
||||
"example:0x1000,0x2000,0x1,0x2000,0x3000,0x3,0x3000,0x4000,0x7"
|
||||
)
|
||||
return
|
||||
|
||||
# Resolve memory range and shell run commands
|
||||
|
||||
values = memregion.replace('"', "").split(",")
|
||||
|
||||
for i in range(0, len(values), 3):
|
||||
start = int(values[i], 16)
|
||||
end = int(values[i + 1], 16)
|
||||
|
||||
# Create a random section name
|
||||
|
||||
section = tmpfile.name + f"{i // 3}"
|
||||
|
||||
# Add objcopy insertion segment command and modify segment start address command
|
||||
|
||||
create_file_with_size(section, end - start)
|
||||
|
||||
os.system(
|
||||
f"{args.objcopy} --add-section {section}={section} "
|
||||
f"--set-section-flags {section}=noload,alloc {tmpfile.name}"
|
||||
)
|
||||
os.system(
|
||||
f"{args.objcopy} --change-section-address "
|
||||
f"{section}={hex(start)} {tmpfile.name}"
|
||||
)
|
||||
|
||||
os.remove(section)
|
||||
|
||||
gdb.execute(f"file {tmpfile.name}")
|
||||
gdb.execute(f"gcore {corefile}")
|
||||
gdb.execute(f"file {elffile}")
|
||||
tmpfile.close()
|
||||
|
||||
print(f"Please run gdbserver.py to parse {corefile}")
|
||||
|
||||
|
||||
NXGcore()
|
Loading…
Reference in New Issue
Block a user