Skip to content

Commit

Permalink
gdb plugin: Encapsulate the gdb native command gcore as nxgcore
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
W-M-R authored and xiaoxiang781216 committed Sep 20, 2024
1 parent bdac8c1 commit b5c5e4b
Show file tree
Hide file tree
Showing 2 changed files with 147 additions and 11 deletions.
29 changes: 18 additions & 11 deletions Documentation/quickstart/debugging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ To halt the board:
.. code-block::
(gdb) mon halt
To set a breakpoint:

.. code-block::
Expand All @@ -104,7 +104,7 @@ and to finally start nuttx:
208 sched_getparam(0, &param);
(gdb) continue
Continuing.
.. tip::

You can abbreviate ``gdb`` commands: ``info b`` is a shortcut for
Expand All @@ -130,16 +130,16 @@ 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:

.. 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:

Expand All @@ -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::
Expand All @@ -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::
Expand Down Expand Up @@ -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.

Expand All @@ -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
Expand Down Expand Up @@ -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.
Expand Down
129 changes: 129 additions & 0 deletions tools/gdb/gcore.py
Original file line number Diff line number Diff line change
@@ -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()

0 comments on commit b5c5e4b

Please sign in to comment.