Skip to content

Commit

Permalink
libdrgn: Use DRGN_VMCOREINFO var as an override
Browse files Browse the repository at this point in the history
Sometimes vmcores don't contain vmcoreinfo, or don't contain the correct
vmcoreinfo. Add logic to use the DRGN_VMCOREINFO variable to override
what is (or is not) found in the ELF notes, or found by libkdumpfile.
This can help open broken vmcores, such as strange hypervisor vmcores.

Signed-off-by: Stephen Brennan <stephen.s.brennan@oracle.com>
  • Loading branch information
brenns10 committed Mar 3, 2023
1 parent d31bd50 commit 4c65518
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 22 deletions.
21 changes: 16 additions & 5 deletions docs/advanced_usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,16 @@ Some of drgn's behavior can be modified through environment variables:
dump (0 or 1). The default is 1. This environment variable is mainly
intended for testing and may be ignored in the future.

``DRGN_VMCOREINFO``
Provide an alternative vmcoreinfo which overrides the one present (if any)
in the program itself. This can be useful for enabling drgn to load programs
which it could not ordinarily open. For example, if a vmcore was created by
a hypervisor which does not support the vmcoreinfo device (or it was not
enabled), then the vmcore itself may not contain the note, or worse: it may
contain a made-up note. By inspecting the vmcore using ``strings`` or other
custom tools, you may be able to find the vmcoreinfo note from within the
dump. In that case, you can provide this data via this environment variable.

.. _kernel-special-objects:

Linux Kernel Special Objects
Expand Down Expand Up @@ -203,10 +213,11 @@ core dumps. These special objects include:

In the linux kernel, this data is normally stored in a variable called
``vmcoreinfo_data``. However, drgn reads this information from ELF note or
from the diskdump header. It is possible (in rare cases, usually with
vmcores created by hypervisors) for a vmcore to contain vmcoreinfo which
differs from the data in ``vmcoreinfo_data``, so it is important to
distinguish the contents. For that reason, we use the name ``VMCOREINFO`` to
distinguish it from the kernel variable ``vmcoreinfo_data``.
from the diskdump header. It is also possible for this information to be set
via the ``DRGN_VMCOREINFO`` variable. Thus, it is possible for a vmcore to
contain vmcoreinfo which differs from the data in ``vmcoreinfo_data``, so it
is important to distinguish the contents. For that reason, we use the name
``VMCOREINFO`` to distinguish it from the kernel variable
``vmcoreinfo_data``.

This is available without debugging information.
38 changes: 22 additions & 16 deletions libdrgn/kdump.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,28 +108,34 @@ struct drgn_error *drgn_program_set_kdump(struct drgn_program *prog)
goto err;
}

char *vmcoreinfo_override = getenv("DRGN_VMCOREINFO");
if (vmcoreinfo_override) {
err = drgn_program_parse_vmcoreinfo(prog, vmcoreinfo_override,
strlen(vmcoreinfo_override) + 1);
} else {
#if KDUMPFILE_VERSION >= KDUMPFILE_MKVER(0, 4, 1)
char *vmcoreinfo;
char *vmcoreinfo;
#else
const char *vmcoreinfo;
const char *vmcoreinfo;
#endif
ks = kdump_vmcoreinfo_raw(ctx, &vmcoreinfo);
if (ks != KDUMP_OK) {
err = drgn_error_format(DRGN_ERROR_OTHER,
"kdump_vmcoreinfo_raw: %s",
kdump_get_err(ctx));
goto err;
}
ks = kdump_vmcoreinfo_raw(ctx, &vmcoreinfo);
if (ks != KDUMP_OK) {
err = drgn_error_format(DRGN_ERROR_OTHER,
"kdump_vmcoreinfo_raw: %s",
kdump_get_err(ctx));
goto err;
}

err = drgn_program_parse_vmcoreinfo(prog, vmcoreinfo,
strlen(vmcoreinfo) + 1);
/*
* As of libkdumpfile 0.4.1, the string returned by
* kdump_vmcoreinfo_raw() needs to be freed.
*/
err = drgn_program_parse_vmcoreinfo(prog, vmcoreinfo,
strlen(vmcoreinfo) + 1);
/*
* As of libkdumpfile 0.4.1, the string returned by
* kdump_vmcoreinfo_raw() needs to be freed.
*/
#if KDUMPFILE_VERSION >= KDUMPFILE_MKVER(0, 4, 1)
free(vmcoreinfo);
free(vmcoreinfo);
#endif
}
if (err)
goto err;

Expand Down
7 changes: 6 additions & 1 deletion libdrgn/program.c
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path)
if (err)
return err;

vmcoreinfo_note = getenv("DRGN_VMCOREINFO");
if (vmcoreinfo_note)
vmcoreinfo_size = strlen(vmcoreinfo_note) + 1;

prog->core_fd = open(path, O_RDONLY);
if (prog->core_fd == -1)
return drgn_error_create_os("open", errno, path);
Expand Down Expand Up @@ -340,7 +344,8 @@ drgn_program_set_core_dump(struct drgn_program *prog, const char *path)
HOST_LITTLE_ENDIAN)
bswap_64(prog->aarch64_insn_pac_mask);
}
} else if (nhdr.n_namesz == sizeof("VMCOREINFO") &&
} else if (!vmcoreinfo_note &&
nhdr.n_namesz == sizeof("VMCOREINFO") &&
memcmp(name, "VMCOREINFO",
sizeof("VMCOREINFO")) == 0) {
vmcoreinfo_note = desc;
Expand Down

0 comments on commit 4c65518

Please sign in to comment.