* [PATCH 0/8] GDB script improvements
@ 2023-02-27 21:15 Glenn Washburn
2023-02-27 21:15 ` [PATCH 1/8] gdb: Move runtime module loading into runtime_load_module Glenn Washburn
` (7 more replies)
0 siblings, 8 replies; 10+ messages in thread
From: Glenn Washburn @ 2023-02-27 21:15 UTC (permalink / raw)
To: grub-devel, Daniel Kiper; +Cc: Glenn Washburn
This series is patches 4-8 and 10-13 of the previous series "GDB script fixes
and improvements", with minor rearranging and the merging of patches 10 and
11.
Glenn
Glenn Washburn (8):
gdb: Move runtime module loading into runtime_load_module
gdb: Conditionally run GDB script logic for dynamically or statically
positioned GRUB
gdb: Only connect to remote target once when first sourced
gdb: Replace module symbol loading implementation with Python one
gdb: Add functions to make loading from dynamically positioned targets
easier
gdb: Allow running user-defined commands at GRUB start
gdb: Modify gdb prompt when running gdb_grub script
gdb: Add extra early initialization symbols for i386-pc
grub-core/Makefile.core.def | 4 +-
grub-core/gdb_grub.in | 160 +++++++++++++++++++++------------
grub-core/gdb_helper.py.in | 173 ++++++++++++++++++++++++++++++++++++
grub-core/gmodule.pl.in | 30 -------
4 files changed, 280 insertions(+), 87 deletions(-)
create mode 100644 grub-core/gdb_helper.py.in
delete mode 100644 grub-core/gmodule.pl.in
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH 1/8] gdb: Move runtime module loading into runtime_load_module
2023-02-27 21:15 [PATCH 0/8] GDB script improvements Glenn Washburn
@ 2023-02-27 21:15 ` Glenn Washburn
2023-02-27 21:15 ` [PATCH 2/8] gdb: Conditionally run GDB script logic for dynamically or statically positioned GRUB Glenn Washburn
` (6 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Glenn Washburn @ 2023-02-27 21:15 UTC (permalink / raw)
To: grub-devel, Daniel Kiper; +Cc: Glenn Washburn
By moving this code into a function, it can be run re-utilized while gdb is
running, not just when loading the script. This will also be useful in
some following changes which will make a separate script path for targets
which statically vs dynamically position GRUB code.
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
grub-core/gdb_grub.in | 20 +++++++++++++-------
1 file changed, 13 insertions(+), 7 deletions(-)
diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index fc17e3d899f8..d525a5a11f01 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -71,16 +71,22 @@ document load_all_modules
Load debugging information for all loaded modules.
end
+define runtime_load_module
+ break grub_dl_add
+ commands
+ silent
+ load_module mod
+ cont
+ end
+end
+document runtime_load_module
+ Load module symbols at runtime as they are loaded.
+end
+
###
set confirm off
file kernel.exec
target remote :1234
-# inform when module is loaded
-break grub_dl_add
-commands
- silent
- load_module mod
- cont
-end
+runtime_load_module
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/8] gdb: Conditionally run GDB script logic for dynamically or statically positioned GRUB
2023-02-27 21:15 [PATCH 0/8] GDB script improvements Glenn Washburn
2023-02-27 21:15 ` [PATCH 1/8] gdb: Move runtime module loading into runtime_load_module Glenn Washburn
@ 2023-02-27 21:15 ` Glenn Washburn
2023-02-27 21:15 ` [PATCH 3/8] gdb: Only connect to remote target once when first sourced Glenn Washburn
` (5 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Glenn Washburn @ 2023-02-27 21:15 UTC (permalink / raw)
To: grub-devel, Daniel Kiper; +Cc: Glenn Washburn
There are broadly two classes of targets to consider when loading symbols
for GRUB, targets that determine where to load GRUB at runtime
(dynamically positioned) and those that do not (statically positioned).
For statically poisitioned targets, symbol loading is determined at link
time, so nothing more needs to be known to load the symbols. For
dynamically positioned targets, such as EFI targets, at runtime symbols
should be offset by an amount that depends on where the runtime chose to
load GRUB.
It is important to not load symbols statically for dynamic targets
because then when subsequently loading the symbols correctly one must
take care to remove the existing static symbols, otherwise there will be
two sets of symbols and GDB seems to prefer the ones loaded first (ie the
static ones).
Use autoconf variables to generate a gdb_grub for a particular target,
which conditionally run startup code depending on if the target uses
static or dynamic loading.
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
grub-core/gdb_grub.in | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index d525a5a11f01..620d1def72d0 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -86,7 +86,20 @@ end
###
set confirm off
-file kernel.exec
-target remote :1234
-runtime_load_module
+# Note: On EFI and other platforms that load GRUB to an address that is
+# determined at runtime, the symbols in kernel.exec will be wrong.
+# However, we must start by loading some executable file or GDB will
+# fail.
+
+set $platform_efi = $_streq("@platform@", "efi")
+
+if $platform_efi
+ # Only load the executable file, not the symbols
+ exec-file kernel.exec
+else
+ file kernel.exec
+ runtime_load_module
+end
+
+target remote :1234
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 3/8] gdb: Only connect to remote target once when first sourced
2023-02-27 21:15 [PATCH 0/8] GDB script improvements Glenn Washburn
2023-02-27 21:15 ` [PATCH 1/8] gdb: Move runtime module loading into runtime_load_module Glenn Washburn
2023-02-27 21:15 ` [PATCH 2/8] gdb: Conditionally run GDB script logic for dynamically or statically positioned GRUB Glenn Washburn
@ 2023-02-27 21:15 ` Glenn Washburn
2023-02-27 21:15 ` [PATCH 4/8] gdb: Replace module symbol loading implementation with Python one Glenn Washburn
` (4 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Glenn Washburn @ 2023-02-27 21:15 UTC (permalink / raw)
To: grub-devel, Daniel Kiper; +Cc: Glenn Washburn
The gdb_grub script was originally meant to be run once when GDB first
starts up via the -x argument. So it runs commands unconditionally
assuming that the script has not been run before. Its nice to be able
to source the script again when developing the script to modify/add
commands. So only run the commands not defined in user-defined commands,
if a variable $runonce has already been set and when those commands have
been run to set $runonce.
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
grub-core/gdb_grub.in | 19 +++++++++++--------
1 file changed, 11 insertions(+), 8 deletions(-)
diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 620d1def72d0..4ca939f69a89 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -94,12 +94,15 @@ set confirm off
set $platform_efi = $_streq("@platform@", "efi")
-if $platform_efi
- # Only load the executable file, not the symbols
- exec-file kernel.exec
-else
- file kernel.exec
- runtime_load_module
-end
+if ! $runonce
+ if $platform_efi
+ # Only load the executable file, not the symbols
+ exec-file kernel.exec
+ else
+ file kernel.exec
+ runtime_load_module
+ end
-target remote :1234
+ target remote :1234
+ set $runonce = 1
+end
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 4/8] gdb: Replace module symbol loading implementation with Python one
2023-02-27 21:15 [PATCH 0/8] GDB script improvements Glenn Washburn
` (2 preceding siblings ...)
2023-02-27 21:15 ` [PATCH 3/8] gdb: Only connect to remote target once when first sourced Glenn Washburn
@ 2023-02-27 21:15 ` Glenn Washburn
2023-02-27 21:15 ` [PATCH 5/8] gdb: Add functions to make loading from dynamically positioned targets easier Glenn Washburn
` (3 subsequent siblings)
7 siblings, 0 replies; 10+ messages in thread
From: Glenn Washburn @ 2023-02-27 21:15 UTC (permalink / raw)
To: grub-devel, Daniel Kiper; +Cc: Glenn Washburn
Remove gmodule.pl and rewrite as a python in gdb_helper.py. This removes
PERL dependency for the GRUB GDB script, but adds Python as a dependency.
This is more desirable because Python is tightly integrated with GDB and
can do things not even available to GDB native scripting language. GDB must
be built with Python, however this is not a major limitation because every
major distro non-end-of-life versions build GDB with Python support. And GDB
has had support for Python since around 7.1-ish, which is about a decade.
This re-implementation has an added feature. If there is a user defined
command named "onload_<module name>", then that command will be executed
after the symbols for the specified module are loaded. When debugging a
module it can be desirable to set break points on code in the module.
This is difficult in GRUB because, at GDB start, the module is not loaded
and on EFI platforms its not known ahead of time where the module will
be loaded. So allow users to create an "onload_<modname>" command which
will be run when the module with name "modname" is loaded.
Another addition is a new convenience function is defined
$is_user_command(), which returns true if its string argument is
the name of a user-defined command.
A secondary benefit of these changes is that the script does not write
temporary files and has better error handling capabilities.
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
grub-core/Makefile.core.def | 4 +-
grub-core/gdb_grub.in | 54 ++----------------------
grub-core/gdb_helper.py.in | 82 +++++++++++++++++++++++++++++++++++++
grub-core/gmodule.pl.in | 30 --------------
4 files changed, 87 insertions(+), 83 deletions(-)
create mode 100644 grub-core/gdb_helper.py.in
delete mode 100644 grub-core/gmodule.pl.in
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index 71093a1003dd..d2b1c3e9e44d 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -20,8 +20,8 @@ transform_data = {
transform_data = {
installdir = platform;
- name = gmodule.pl;
- common = gmodule.pl.in;
+ name = gdb_helper.py;
+ common = gdb_helper.py.in;
};
transform_data = {
diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 4ca939f69a89..fc201204debc 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -1,6 +1,6 @@
###
### Load debuging information about GNU GRUB 2 modules into GDB
-### automatically. Needs readelf, Perl and gmodule.pl script
+### automatically. Needs readelf, Python and gdb_helper.py script
###
### Has to be launched from the writable and trusted
### directory containing *.image and *.module
@@ -9,63 +9,15 @@
### Lubomir Kundrak <lkudrak@skosi.org>
###
-# Add section numbers and addresses to .segments.tmp
-define dump_module_sections_helper
- set $mod = $arg0
- printf "%s", $mod->name
- set $segment = $mod->segment
- while ($segment)
- printf " %i 0x%lx", $segment->section, $segment->addr
- set $segment = $segment->next
- end
- printf "\n"
-end
+source gdb_helper.py
-define dump_module_sections
- # Set unlimited width so that lines don't get wrapped writing
- # to .segments.tmp
- with width 0 -- \
- with trace-commands off -- \
- pipe dump_module_sections_helper $arg0 | sh -c 'cat >>.segments.tmp'
-end
-document dump_module_sections
- Gather information about module whose mod structure was
- given for use with match_and_load_symbols
-end
-
-# Generate and execute GDB commands and delete temporary files
-# afterwards
-define match_and_load_symbols
- shell perl gmodule.pl <.segments.tmp >.loadsym.gdb
- source .loadsym.gdb
- shell rm -f .segments.tmp .loadsym.gdb
-end
-document match_and_load_symbols
- Launch script, that matches section names with information
- generated by dump_module_sections and load debugging info
- apropriately
-end
-
-###
-
-define load_module
- dump_module_sections $arg0
- match_and_load_symbols
-end
-document load_module
- Load debugging information for module given as argument.
-end
define load_all_modules
- shell rm -f .segments.tmp
set $this = grub_dl_head
while ($this != 0)
- dump_module_sections $this
+ load_module $this
set $this = $this->next
end
- if (grub_dl_head != 0)
- match_and_load_symbols
- end
end
document load_all_modules
Load debugging information for all loaded modules.
diff --git a/grub-core/gdb_helper.py.in b/grub-core/gdb_helper.py.in
new file mode 100644
index 000000000000..4306ef448aa6
--- /dev/null
+++ b/grub-core/gdb_helper.py.in
@@ -0,0 +1,82 @@
+import os
+import re
+import subprocess
+
+##### Convenience functions #####
+
+class IsUserCommand (gdb.Function):
+ """Set the second argument to true value if first argument is the name
+of a user-defined command.
+"""
+
+ def __init__ (self):
+ super (IsUserCommand, self).__init__ ("is_user_command")
+
+ def invoke (self, fmt, *args):
+ name = fmt.string () % tuple(a.string () for a in args)
+ for line in gdb.execute ("help user-defined", to_string=True).splitlines ():
+ line_parts = line.split(' -- ', 1)
+ if len (line_parts) > 1 and line_parts[0] == name:
+ return True
+ return False
+
+is_user_command = IsUserCommand ()
+
+##### Commands #####
+
+class GrubLoadModuleSymbols (gdb.Command):
+ """Load module symbols at correct locations.
+Takes one argument which is a pointer to a grub_dl_t struct."""
+
+ def __init__ (self):
+ super (GrubLoadModuleSymbols, self).__init__ ("load_module",
+ gdb.COMMAND_USER,
+ gdb.COMPLETE_EXPRESSION)
+
+ def invoke (self, arg, from_tty):
+ self.dont_repeat ()
+ args = gdb.string_to_argv (arg)
+ self.mod = gdb.parse_and_eval (args[0])
+ sections = self.get_section_offsets ()
+ section_names = self.get_section_names ()
+
+ sym_load_cmd_parts = ["add-symbol-file",
+ "%s.module" % (self.mod['name'].string (),)]
+ for idx, addr in sections:
+ section_name = section_names[idx]
+ if section_name == ".text":
+ sym_load_cmd_parts.append (addr)
+ else:
+ sym_load_cmd_parts.extend (["-s", section_name, addr])
+ gdb.execute (' '.join (sym_load_cmd_parts))
+
+ if is_user_command.invoke (gdb.Value ("onload_%s"), self.mod['name']):
+ gdb.execute ("onload_%s (grub_dl_t)%s" % (self.mod['name'].string (),
+ self.mod.format_string (format='x')))
+
+ def get_section_offsets (self):
+ sections = []
+ segment = self.mod['segment']
+ while segment:
+ sections.append ((int (segment['section']), segment['addr'].format_string (format='x')))
+ segment = segment['next']
+ return sections
+
+ def get_section_names (self):
+ re_index = re.compile ("^\s+\[\s*(\d+)\] (\S*)")
+ names = {}
+ modfilename = "%s.mod" % (self.mod['name'].string (),)
+
+ if not os.path.exists (modfilename):
+ raise RuntimeError ("%s not found in current directory" % (modfilename,))
+
+ c = subprocess.run (["readelf", "-SW", modfilename], text=True, capture_output=True)
+ for line in c.stdout.splitlines ()[4:]:
+ m = re_index.match (line)
+ if not m:
+ continue
+ idx, name = m.groups ()
+ names[int (idx)] = name
+ return names
+
+grub_load_module = GrubLoadModuleSymbols ()
diff --git a/grub-core/gmodule.pl.in b/grub-core/gmodule.pl.in
deleted file mode 100644
index 78aa1e64eb29..000000000000
--- a/grub-core/gmodule.pl.in
+++ /dev/null
@@ -1,30 +0,0 @@
-###
-### Generate GDB commands, that load symbols for specified module,
-### with proper section relocations. See .gdbinit
-###
-### $Id: gmodule.pl,v 1.2 2006/05/14 11:38:42 lkundrak Exp lkundrak $
-### Lubomir Kundrak <lkudrak@skosi.org>
-###
-
-use strict;
-
-while (<>) {
- my ($name, %sections) = split;
-
- print "add-symbol-file $name.module";
-
- open (READELF, "readelf -S $name.mod |") or die;
- while (<READELF>) {
- /\[\s*(\d+)\]\s+(\.\S+)/ or next;
-
- if ($2 eq '.text') {
- print " $sections{$1}";
- next;
- }
-
- print " -s $2 $sections{$1}"
- if ($sections{$1} ne '0x0' and $sections{$1} ne '');
- };
- close (READELF);
- print "\n";
-}
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 5/8] gdb: Add functions to make loading from dynamically positioned targets easier
2023-02-27 21:15 [PATCH 0/8] GDB script improvements Glenn Washburn
` (3 preceding siblings ...)
2023-02-27 21:15 ` [PATCH 4/8] gdb: Replace module symbol loading implementation with Python one Glenn Washburn
@ 2023-02-27 21:15 ` Glenn Washburn
2023-03-08 13:45 ` Daniel Kiper
2023-02-27 21:15 ` [PATCH 6/8] gdb: Allow running user-defined commands at GRUB start Glenn Washburn
` (2 subsequent siblings)
7 siblings, 1 reply; 10+ messages in thread
From: Glenn Washburn @ 2023-02-27 21:15 UTC (permalink / raw)
To: grub-devel, Daniel Kiper; +Cc: Glenn Washburn
Many targets, such as EFI, load GRUB at addresses that are determined at
runtime. So the load addresses in kernel.exec will almost certainly be
wrong. Given the address of the start of the text segment, these
functions will tell GDB to load the symbols at the proper locations. It
is left up to the user to determine how to get the text address of the
loaded GRUB image.
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
grub-core/gdb_grub.in | 21 ++++++++-
grub-core/gdb_helper.py.in | 87 ++++++++++++++++++++++++++++++++++++++
2 files changed, 107 insertions(+), 1 deletion(-)
diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index fc201204debc..18ce6b0eb2d4 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -1,6 +1,6 @@
###
### Load debuging information about GNU GRUB 2 modules into GDB
-### automatically. Needs readelf, Python and gdb_helper.py script
+### automatically. Needs readelf, objdump, Python and gdb_helper.py script
###
### Has to be launched from the writable and trusted
### directory containing *.image and *.module
@@ -12,6 +12,25 @@
source gdb_helper.py
+define dynamic_load_symbols
+ dynamic_load_kernel_exec_symbols $arg0
+
+ # We may have been very late to loading the kernel.exec symbols and
+ # and modules may already be loaded. So load symbols for any already
+ # loaded.
+ load_all_modules
+
+ if $is_grub_loaded()
+ runtime_load_module
+ end
+end
+document dynamic_load_symbols
+ Load debugging symbols from kernel.exec and any loaded modules given
+ the address of the .text segment of the UEFI binary in memory. Also
+ setup session to automatically load module symbols for modules loaded
+ in the future.
+end
+
define load_all_modules
set $this = grub_dl_head
while ($this != 0)
diff --git a/grub-core/gdb_helper.py.in b/grub-core/gdb_helper.py.in
index 4306ef448aa6..8d5ee1d292cb 100644
--- a/grub-core/gdb_helper.py.in
+++ b/grub-core/gdb_helper.py.in
@@ -4,6 +4,23 @@ import subprocess
##### Convenience functions #####
+class IsGrubLoaded (gdb.Function):
+ """Return 1 if GRUB has been loaded in memory, otherwise 0.
+The hueristic used is checking if the first 4 bytes of the memory pointed
+to by the _start symbol are not 0. This is true for QEMU on the first run
+of GRUB. This may not be true on physical hardware, where memory is not
+necessarily cleared on soft reset. This may not also be true in QEMU on
+soft resets. Also this many not be true when chainloading GRUB.
+"""
+
+ def __init__ (self):
+ super (IsGrubLoaded, self).__init__ ("is_grub_loaded")
+
+ def invoke (self):
+ return int (gdb.parse_and_eval ("*(int *) _start")) != 0
+
+is_grub_loaded = IsGrubLoaded ()
+
class IsUserCommand (gdb.Function):
"""Set the second argument to true value if first argument is the name
of a user-defined command.
@@ -24,6 +41,76 @@ is_user_command = IsUserCommand ()
##### Commands #####
+# Loading symbols is complicated by the fact that kernel.exec is an ELF
+# ELF binary, but the UEFI runtime is PE32+. All the data sections of
+# the ELF binary are concatenated (accounting for ELF section alignment)
+# and put into one .data section of the PE32+ runtime image. So given
+# the load address of the .data PE32+ section we can determine the
+# addresses each ELF data section maps to. The UEFI application is
+# loaded into memory just as it is laid out in the file. It is not
+# assumed that the binary is available, but it is known that the .text
+# section directly precedes the .data section and that .data is EFI
+# page aligned. Using this, the .data offset can be found from the .text
+# address.
+class GrubLoadKernelExecSymbols (gdb.Command):
+ """Load debugging symbols from kernel.exec given the address of the
+.text segment of the UEFI binary in memory."""
+
+ PE_SECTION_ALIGN = 12
+
+ def __init__ (self):
+ super (GrubLoadKernelExecSymbols, self).__init__ ("dynamic_load_kernel_exec_symbols",
+ gdb.COMMAND_USER,
+ gdb.COMPLETE_EXPRESSION)
+
+ def invoke (self, arg, from_tty):
+ self.dont_repeat ()
+ args = gdb.string_to_argv (arg)
+
+ if len (args) != 1:
+ raise RuntimeError ("dynamic_load_kernel_exec_symbols expects exactly one argument")
+
+ sections = self.parse_objdump_sections ("kernel.exec")
+ pe_text = args[0]
+ text_size = [s['size'] for s in sections if s['name'] == '.text'][0]
+ pe_data_offset = self.alignup (text_size, self.PE_SECTION_ALIGN)
+
+ sym_load_cmd_parts = ["add-symbol-file", "kernel.exec", pe_text]
+ offset = 0
+ for section in sections:
+ if 'DATA' in section["flags"] or section["name"] == ".bss":
+ offset = self.alignup (offset, section["align"])
+ sym_load_cmd_parts.extend (["-s", section["name"], "(%s+0x%x+0x%x)" % (pe_text, pe_data_offset, offset)])
+ offset += section["size"]
+ gdb.execute (' '.join (sym_load_cmd_parts))
+
+ @staticmethod
+ def parse_objdump_sections (filename):
+ fields = ("idx", "name", "size", "vma", "lma", "fileoff", "align")
+ re_section = re.compile ("^\s*" + "\s+".join(["(?P<%s>\S+)" % f for f in fields]))
+ c = subprocess.run (["objdump", "-h", filename], text=True, capture_output=True)
+ section_lines = c.stdout.splitlines ()[5:]
+ sections = []
+
+ for i in range (len (section_lines) >> 1):
+ m = re_section.match (section_lines[i * 2])
+ s = dict (m.groupdict ())
+ for f in ("size", "vma", "lma", "fileoff"):
+ s[f] = int (s[f], 16)
+ s["idx"] = int (s["idx"])
+ s["align"] = int (s["align"].split ("**", 1)[1])
+ s["flags"] = section_lines[(i * 2) + 1].strip ().split (", ")
+ sections.append (s)
+ return sections
+
+ @staticmethod
+ def alignup (addr, align):
+ pad = (addr % (1 << align)) and 1 or 0
+ return ((addr >> align) + pad) << align
+
+dynamic_load_kernel_exec_symbols = GrubLoadKernelExecSymbols ()
+
+
class GrubLoadModuleSymbols (gdb.Command):
"""Load module symbols at correct locations.
Takes one argument which is a pointer to a grub_dl_t struct."""
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 6/8] gdb: Allow running user-defined commands at GRUB start
2023-02-27 21:15 [PATCH 0/8] GDB script improvements Glenn Washburn
` (4 preceding siblings ...)
2023-02-27 21:15 ` [PATCH 5/8] gdb: Add functions to make loading from dynamically positioned targets easier Glenn Washburn
@ 2023-02-27 21:15 ` Glenn Washburn
2023-02-27 21:15 ` [PATCH 7/8] gdb: Modify gdb prompt when running gdb_grub script Glenn Washburn
2023-02-27 21:15 ` [PATCH 8/8] gdb: Add extra early initialization symbols for i386-pc Glenn Washburn
7 siblings, 0 replies; 10+ messages in thread
From: Glenn Washburn @ 2023-02-27 21:15 UTC (permalink / raw)
To: grub-devel, Daniel Kiper; +Cc: Glenn Washburn
A new command, run_on_start, for things to do before GRUB starts executing.
Currently, this is setting up the loading of module symbols as they are
loaded and allowing user-defined script to be run if a command named
"onstart" exists.
On some platforms, notably x86, software breakpoints set in GDB before
the GRUB image is loaded will be cleared when the image is loaded. This
is because the breakpoints work by overwriting the memory of the break-
point location with a special instruction which when hit will cause the
debugger to stop execution. Just before execution is resumed by the
debugger, the original instruction bytes are put back. When a breakpoint
is set before the GRUB image is loaded, the special debugger instruction
will be written to memory and when the GRUB image is loaded by the
firmware, which has no knowledge of the debugger, the debugger instruction
is overwritten. To the GDB user, GDB will show the breakpoint as set, but
it will never be hit. Furthermore, GDB now becomes confused, such that
even deleting and re-setting the breakpoint after the GRUB image is loaded
will not allow for a working breakpoint.
To work around this, in run_on_start, first a watchpoint is set on _start,
which will be triggered when the firmware starts loading the GRUB image.
When the _start watchpoint is hit, the current breakpoints are saved to a
file and then deleted by GDB before they can be overwritten by the firmware
and confuse GDB. Then a temporary software breakpoint is set on _start,
which will get triggered when the firmware hands off to GRUB to execute. In
that breakpoint load the previously saved and deleted breakpoints now that
there is no worry of them getting overwritten by the firmware. This is
needed for runtime_load_module to work when it is run before the GRUB image
is loaded.
Note that watchpoints are generally types of hardware breakpoints on x86, so
its deleted as soon as it gets triggered so that a minimal set of hardware
breakpoints are used, allowing more for the user.
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
grub-core/gdb_grub.in | 51 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 51 insertions(+)
diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 18ce6b0eb2d4..8e89bbf3683b 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -15,6 +15,8 @@ source gdb_helper.py
define dynamic_load_symbols
dynamic_load_kernel_exec_symbols $arg0
+ run_on_start
+
# We may have been very late to loading the kernel.exec symbols and
# and modules may already be loaded. So load symbols for any already
# loaded.
@@ -54,6 +56,54 @@ document runtime_load_module
Load module symbols at runtime as they are loaded.
end
+define run_on_start
+ # TODO: Add check to see if _start symbol is defined, if not, then
+ # the symbols have not yet been loaded and this command will not work.
+ watch *_start
+ set $break_efi_start_bpnum = $bpnum
+ commands
+ silent
+ delete $break_efi_start_bpnum
+
+ # Save the breakpoints here before the GRUB image is loaded
+ # into memory, then delete them. Later they will be reloaded
+ # once the GRUB image has been loaded. This avoids the issue
+ # where the loading of the GRUB image overwrites the software
+ # breakpoints, thus confusing GDB and effectively clearing
+ # those breakpoints.
+ save breakpoints .early-breakpoints.gdb
+ delete breakpoints
+
+ tbreak _start
+ commands
+ silent
+
+ # Reload the breakpoints now that the GRUB image has
+ # finished being loaded into memory.
+ source .early-breakpoints.gdb
+
+ runtime_load_module
+
+ if $is_user_command("onstart")
+ onstart
+ end
+ continue
+ end
+ continue
+ end
+end
+document run_on_start
+ On some targets, such as x86_64-efi, even if you know where the
+ firmware will load the GRUB image, you can not simply set a break
+ point before the image is loaded because loading the image
+ overwrites the break point in memory. So setup a hardware watch
+ point, which does not have that problem, and if that gets triggered,
+ then reset the break point. If a user-defined command named
+ "onstart" exists it will be run after the start is hit.
+ NOTE: This assumes symbols have already been correctly loaded for
+ the EFI application.
+end
+
###
set confirm off
@@ -71,6 +121,7 @@ if ! $runonce
exec-file kernel.exec
else
file kernel.exec
+ run_on_start
runtime_load_module
end
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 7/8] gdb: Modify gdb prompt when running gdb_grub script
2023-02-27 21:15 [PATCH 0/8] GDB script improvements Glenn Washburn
` (5 preceding siblings ...)
2023-02-27 21:15 ` [PATCH 6/8] gdb: Allow running user-defined commands at GRUB start Glenn Washburn
@ 2023-02-27 21:15 ` Glenn Washburn
2023-02-27 21:15 ` [PATCH 8/8] gdb: Add extra early initialization symbols for i386-pc Glenn Washburn
7 siblings, 0 replies; 10+ messages in thread
From: Glenn Washburn @ 2023-02-27 21:15 UTC (permalink / raw)
To: grub-devel, Daniel Kiper; +Cc: Glenn Washburn
This will let users know that the GDB session is using the GRUB gdb scripts.
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
grub-core/gdb_helper.py.in | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/grub-core/gdb_helper.py.in b/grub-core/gdb_helper.py.in
index 8d5ee1d292cb..5ed9eab0f529 100644
--- a/grub-core/gdb_helper.py.in
+++ b/grub-core/gdb_helper.py.in
@@ -2,6 +2,10 @@ import os
import re
import subprocess
+def prompt_hook (current_prompt):
+ return "(grub gdb) "
+gdb.prompt_hook = prompt_hook
+
##### Convenience functions #####
class IsGrubLoaded (gdb.Function):
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 8/8] gdb: Add extra early initialization symbols for i386-pc
2023-02-27 21:15 [PATCH 0/8] GDB script improvements Glenn Washburn
` (6 preceding siblings ...)
2023-02-27 21:15 ` [PATCH 7/8] gdb: Modify gdb prompt when running gdb_grub script Glenn Washburn
@ 2023-02-27 21:15 ` Glenn Washburn
7 siblings, 0 replies; 10+ messages in thread
From: Glenn Washburn @ 2023-02-27 21:15 UTC (permalink / raw)
To: grub-devel, Daniel Kiper; +Cc: Glenn Washburn
Add symbols for boot.image, disk.image, and lzma_decompress.image if the
target is i386-pc. This is only done for i386-pc because that is the only
target that uses the images. By loading the symbols for these images,
these images can be more easily debugged by allowing the setting of break-
points in that code and to see easily get the value of data symbols.
Signed-off-by: Glenn Washburn <development@efficientek.com>
---
grub-core/gdb_grub.in | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
index 8e89bbf3683b..f188a842ab93 100644
--- a/grub-core/gdb_grub.in
+++ b/grub-core/gdb_grub.in
@@ -114,12 +114,18 @@ set confirm off
# fail.
set $platform_efi = $_streq("@platform@", "efi")
+set $target = "@target_cpu@-@platform@"
if ! $runonce
if $platform_efi
# Only load the executable file, not the symbols
exec-file kernel.exec
else
+ if $_streq($target, "i386-pc")
+ add-symbol-file boot.image
+ add-symbol-file diskboot.image
+ add-symbol-file lzma_decompress.image
+ end
file kernel.exec
run_on_start
runtime_load_module
--
2.34.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 5/8] gdb: Add functions to make loading from dynamically positioned targets easier
2023-02-27 21:15 ` [PATCH 5/8] gdb: Add functions to make loading from dynamically positioned targets easier Glenn Washburn
@ 2023-03-08 13:45 ` Daniel Kiper
0 siblings, 0 replies; 10+ messages in thread
From: Daniel Kiper @ 2023-03-08 13:45 UTC (permalink / raw)
To: Glenn Washburn; +Cc: grub-devel
On Mon, Feb 27, 2023 at 03:15:35PM -0600, Glenn Washburn wrote:
> Many targets, such as EFI, load GRUB at addresses that are determined at
> runtime. So the load addresses in kernel.exec will almost certainly be
> wrong. Given the address of the start of the text segment, these
> functions will tell GDB to load the symbols at the proper locations. It
> is left up to the user to determine how to get the text address of the
> loaded GRUB image.
>
> Signed-off-by: Glenn Washburn <development@efficientek.com>
> ---
> grub-core/gdb_grub.in | 21 ++++++++-
> grub-core/gdb_helper.py.in | 87 ++++++++++++++++++++++++++++++++++++++
> 2 files changed, 107 insertions(+), 1 deletion(-)
>
> diff --git a/grub-core/gdb_grub.in b/grub-core/gdb_grub.in
> index fc201204debc..18ce6b0eb2d4 100644
> --- a/grub-core/gdb_grub.in
> +++ b/grub-core/gdb_grub.in
> @@ -1,6 +1,6 @@
> ###
> ### Load debuging information about GNU GRUB 2 modules into GDB
> -### automatically. Needs readelf, Python and gdb_helper.py script
> +### automatically. Needs readelf, objdump, Python and gdb_helper.py script
Could you add a patch which creates a separate section in the INSTALL
file with a list of required packages needed to do GRUB debugging?
Otherwise for all the patches Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>...
Daniel
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2023-03-08 13:46 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-02-27 21:15 [PATCH 0/8] GDB script improvements Glenn Washburn
2023-02-27 21:15 ` [PATCH 1/8] gdb: Move runtime module loading into runtime_load_module Glenn Washburn
2023-02-27 21:15 ` [PATCH 2/8] gdb: Conditionally run GDB script logic for dynamically or statically positioned GRUB Glenn Washburn
2023-02-27 21:15 ` [PATCH 3/8] gdb: Only connect to remote target once when first sourced Glenn Washburn
2023-02-27 21:15 ` [PATCH 4/8] gdb: Replace module symbol loading implementation with Python one Glenn Washburn
2023-02-27 21:15 ` [PATCH 5/8] gdb: Add functions to make loading from dynamically positioned targets easier Glenn Washburn
2023-03-08 13:45 ` Daniel Kiper
2023-02-27 21:15 ` [PATCH 6/8] gdb: Allow running user-defined commands at GRUB start Glenn Washburn
2023-02-27 21:15 ` [PATCH 7/8] gdb: Modify gdb prompt when running gdb_grub script Glenn Washburn
2023-02-27 21:15 ` [PATCH 8/8] gdb: Add extra early initialization symbols for i386-pc Glenn Washburn
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.