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",
--
Crash-utility mailing list -- devel(a)lists.crash-utility.osci.io
To unsubscribe send an email to devel-leave(a)lists.crash-utility.osci.io
https://${domain_name}/admin/lists/devel.lists.crash-utility.osci.io/
Contribution Guidelines:
https://github.com/crash-utility/crash/wiki
I did not touch the comment, just applied since git log is good to get
the history.
Thanks
Dave