Hi Jiri,
On 8/14/26 2:06 PM, Jiri Slaby wrote:
When running crash on openSUSE, get_linux_banner_from_vmlinux()
returns
success but fill the target buffer with all zero bytes (`\0`).
This happens because `st->bfd` is initially opened for the main binary
(`vmlinux`), but is later overwritten with the debuginfo file
(`vmlinux.debug`) in `check_gnu_debuglink()`. In separate debug files,
`.rodata` has no content, so is marked only as `ALLOC` without
`SEC_HAS_CONTENTS`.
When `bfd_get_section_contents()` is called on a section without
`SEC_HAS_CONTENTS`, BFD clears the buffer to zeros and returns TRUE. As
a result, `get_linux_banner_from_vmlinux()` thinks it successfully read
the banner, while it actually received zeroed bytes.
Fix this by caching the original main executable's BFD (into
`st->bfd_orig`) before `st->bfd` gets swapped for the debuginfo file.
`get_linux_banner_from_vmlinux()` will then fall back to `st->bfd_orig`
if present, ensuring `.rodata` contents are read from the binary that
actually contains the raw section data.
Fixes #232.
Signed-off-by: Jiri Slaby <jirislaby(a)gmail.com>
Cc: Dave Young <yangrr.2009(a)tsinghua.org.cn>
Cc: <ltao(a)redhat.com>
Cc: <mpilaniy(a)redhat.com>
---
defs.h | 1 +
kernel.c | 5 +++--
symbols.c | 1 +
3 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/defs.h b/defs.h
index e3027e2b9141..e82af5bd5ed0 100644
--- a/defs.h
+++ b/defs.h
@@ -2920,6 +2920,7 @@ struct symbol_table_data {
#ifdef GDB_5_3
struct _bfd *bfd;
#else
+ struct bfd *bfd_orig;
struct bfd *bfd;
#endif
struct sec *sections;
diff --git a/kernel.c b/kernel.c
index e53038d5d8db..521cdf5664ef 100644
--- a/kernel.c
+++ b/kernel.c
@@ -12145,6 +12145,7 @@ check_vmcoreinfo(void)
static
int get_linux_banner_from_vmlinux(char *buf, size_t size)
{
+ struct bfd *bfd = st->bfd_orig ? : st->bfd;
struct bfd_section *sect;
long offset;
ulong start_rodata;
@@ -12156,7 +12157,7 @@ int get_linux_banner_from_vmlinux(char *buf, size_t size)
else
return FALSE;
- sect = bfd_get_section_by_name(st->bfd, ".rodata");
+ sect = bfd_get_section_by_name(bfd, ".rodata");
if (!sect)
return FALSE;
@@ -12168,7 +12169,7 @@ int get_linux_banner_from_vmlinux(char *buf, size_t size)
*/
offset = symbol_value("linux_banner") - start_rodata;
- if (!bfd_get_section_contents(st->bfd,
+ if (!bfd_get_section_contents(bfd,
sect,
buf,
offset,
diff --git a/symbols.c b/symbols.c
index a7ccdb101033..4b5585d62dba 100644
--- a/symbols.c
+++ b/symbols.c
@@ -444,6 +444,7 @@ check_gnu_debuglink(bfd *bfd)
return FALSE;
reset_bfd:
+ st->bfd_orig = st->bfd;
Nitpick:iIt is even better to add code comment here or in defs.h, eg:
/*
* Cache the original bfd in case it will be replaced by a separate debug
* file. Debug files often lack section contents (e.g., .rodata is ALLOC
* only), so we need the original binary to read actual data.
*/
Anyway, thanks for fixing the issue:
Reviewed-by: Dave Young <yangrr.2009(a)tsinghua.org.cn>
if ((st->bfd = bfd_openr(pc->debuginfo_file, NULL)) == NULL)
error(FATAL, "cannot open object file: %s\n",