The attached patch read the .debug_frame section of vmlinux into
crash. By doing this, we could backtrace kernel stack frame using
dwarf unwind information contained in that section.
ChangeLog:
- Modified section_header_info() function to initialize the offset
and size of .debug_frame section.
- Modified init_unwind_table() function to read in .debug_frame.
- Modified the prototype of unwind(), adding a int argument to
indicate whether .eh_frame or .debug_frame is used. Also there're
a few changes due to the difference between these two sections.
Well, it's the first time I came to crash utility, and I hope that
I didn't do anything wrong.
Thanks,
Wang Chao
The following patch read the .debug_frame section of vmlinux into
crash. By doing this, we could backtrace kernel stack frame using
dwarf unwind information contained in that section.
ChangeLog:
- Modified section_header_info() function to initialize the offset
and size of .debug_frame section.
- Modified init_unwind_table() function to read in .debug_frame.
- Modified the prototype of unwind(), adding a int argument to
indicate whether .eh_frame or .debug_frame is used. Also there're
a few changes due to the difference between these two sections.
default:
diff --git a/unwind_x86_32_64.c b/unwind_x86_32_64.c
index 13d86a9..754890e 100644
--- a/unwind_x86_32_64.c
+++ b/unwind_x86_32_64.c
@@ -496,7 +496,7 @@ static int processCFI(const u8 *start,
/* Unwind to previous to frame. Returns 0 if successful, negative
* number in case of an error. */
int
-unwind(struct unwind_frame_info *frame)
+unwind(struct unwind_frame_info *frame, int is_ehframe)
{
#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
const u32 *fde = NULL, *cie = NULL;
@@ -527,17 +527,22 @@ unwind(struct unwind_frame_info *frame)
fde += 1 + *fde / sizeof(*fde)) {
if (!*fde || (*fde & (sizeof(*fde) - 1)))
break;
- if (!fde[1])
+ if (is_ehframe && !fde[1])
+ continue; /* this is a CIE */
+ else if (fde[1] == 0xffffffff)
continue; /* this is a CIE */
if ((fde[1] & (sizeof(*fde) - 1))
|| fde[1] > (unsigned long)(fde + 1)
- (unsigned long)unwind_table)
continue; /* this is not a valid FDE */
- cie = fde + 1 - fde[1] / sizeof(*fde);
+ if (is_ehframe)
+ cie = fde + 1 - fde[1] / sizeof(*fde);
+ else
+ cie = unwind_table + fde[1];
if (*cie <= sizeof(*cie) + 4
|| *cie >= fde[1] - sizeof(*fde)
|| (*cie & (sizeof(*cie) - 1))
- || cie[1]
+ || (cie[1] != 0xffffffff && cie[1])
|| (ptrType = fde_pointer_type(cie)) < 0) {
cie = NULL; /* this is not a (valid) CIE */
continue;
@@ -783,10 +788,13 @@ init_unwind_table(void)
try_eh_frame:
- if (st->dwarf_eh_frame_size) {
+ if (st->dwarf_eh_frame_size || st->dwarf_debug_frame_size) {
int fd;
+ int is_ehframe = (!st->dwarf_debug_frame_size &&
+ st->dwarf_eh_frame_size);
> Hi Dave and all,
>
> The attached patch read the .debug_frame section of vmlinux into
> crash. By doing this, we could backtrace kernel stack frame using
> dwarf unwind information contained in that section.
>
> ChangeLog:
> - Modified section_header_info() function to initialize the offset
> and size of .debug_frame section.
> - Modified init_unwind_table() function to read in .debug_frame.
> - Modified the prototype of unwind(), adding a int argument to
> indicate whether .eh_frame or .debug_frame is used. Also there're
> a few changes due to the difference between these two sections.
>
> Well, it's the first time I came to crash utility, and I hope that
> I didn't do anything wrong.
>
> Thanks,
> Wang Chao
Hello Wang,
The dwarf-based backtrace code is suffering from bit-rot, and in testing
with your patch, I'm seeing a few problems with it on certain kernels,
where several backtraces of active tasks either fail, display strange
frames, show the same frame twice, or just miss frames entirely.
(which is why I kept the two possible x86_64 backtrace facilities
separate...)
But it seems to work for the most part, whereas before it could not
even attempt the backtrace.
So anyway, given that the patch does not affect the default backtrace path,
it seems safe enough to add your patch for those users who wish to run
with "unwind" turned on.
Thanks,
Dave
--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility