FAQ Search Today's Posts Mark Forums Read
» Video Reviews

» Linux Archive

Linux-archive is a website aiming to archive linux email lists and to make them easily accessible for linux users/developers.


» Sponsor

» Partners

» Sponsor

Go Back   Linux Archive > Redhat > Crash Utility

 
 
LinkBack Thread Tools
 
Old 11-25-2010, 04:30 AM
Wang Chao
 
Default Read in .debug_frame section of vmlinux

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
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.

Signed-off-by: Wang Chao <wang.chao@cn.fujitsu.com>
---
defs.h | 2 ++
symbols.c | 8 ++++++++
unwind_x86_32_64.c | 43 ++++++++++++++++++++++++++++---------------
unwind_x86_64.h | 2 +-
4 files changed, 39 insertions(+), 16 deletions(-)

diff --git a/defs.h b/defs.h
index dcece4a..ec85279 100755
--- a/defs.h
+++ b/defs.h
@@ -1977,6 +1977,8 @@ struct symbol_table_data {
struct load_module *load_modules;
off_t dwarf_eh_frame_file_offset;
ulong dwarf_eh_frame_size;
+ off_t dwarf_debug_frame_file_offset;
+ ulong dwarf_debug_frame_size;
ulong first_ksymbol;
ulong __per_cpu_start;
ulong __per_cpu_end;
diff --git a/symbols.c b/symbols.c
index ec9c893..78fca5a 100755
--- a/symbols.c
+++ b/symbols.c
@@ -8271,6 +8271,10 @@ section_header_info(bfd *bfd, asection *section, void *reqptr)
st->dwarf_eh_frame_file_offset = (off_t)section->filepos;
st->dwarf_eh_frame_size = (ulong)bfd_section_size(bfd, section);
}
+ if (STREQ(bfd_get_section_name(bfd, section), ".debug_frame")) {
+ st->dwarf_debug_frame_file_offset = (off_t)section->filepos;
+ st->dwarf_debug_frame_size = (ulong)bfd_section_size(bfd, section);
+ }
break;

case (ulong)MODULE_SECTIONS:
@@ -8291,6 +8295,10 @@ section_header_info(bfd *bfd, asection *section, void *reqptr)
st->dwarf_eh_frame_file_offset = (off_t)section->filepos;
st->dwarf_eh_frame_size = (ulong)bfd_section_size(bfd, section);
}
+ if (STREQ(bfd_get_section_name(bfd, section), ".debug_frame")) {
+ st->dwarf_debug_frame_file_offset = (off_t)section->filepos;
+ st->dwarf_debug_frame_size = (ulong)bfd_section_size(bfd, section);
+ }
break;

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);

- unwind_table_size = st->dwarf_eh_frame_size;
+ unwind_table_size = is_ehframe ? st->dwarf_eh_frame_size :
+ st->dwarf_debug_frame_size;

if (!(unwind_table = malloc(unwind_table_size))) {
error(WARNING, "cannot malloc unwind table space
");
@@ -794,18 +802,21 @@ try_eh_frame:
}

if ((fd = open(pc->namelist, O_RDONLY)) < 0) {
- error(WARNING, "cannot open %s for .eh_frame data
",
- pc->namelist);
+ error(WARNING, "cannot open %s for %s data
",
+ pc->namelist, is_ehframe ? ".eh_frame" : ".debug_frame");
free(unwind_table);
return;
}

- lseek(fd, st->dwarf_eh_frame_file_offset, SEEK_SET);
+ if (is_ehframe)
+ lseek(fd, st->dwarf_eh_frame_file_offset, SEEK_SET);
+ else
+ lseek(fd, st->dwarf_debug_frame_file_offset, SEEK_SET);

- if (read(fd, unwind_table, st->dwarf_eh_frame_size) !=
- st->dwarf_eh_frame_size) {
- error(WARNING, "cannot read .eh_frame data from %s
",
- pc->namelist);
+ if (read(fd, unwind_table, unwind_table_size) !=
+ unwind_table_size) {
+ error(WARNING, "cannot read %s data from %s
",
+ is_ehframe ? ".eh_frame" : ".debug_frame", pc->namelist);
free(unwind_table);
return;
}
@@ -1054,6 +1065,7 @@ dwarf_backtrace(struct bt_info *bt, int level, ulong stacktop)
struct syment *sp;
char *name;
struct unwind_frame_info *frame;
+ int is_ehframe = (!st->dwarf_debug_frame_size && st->dwarf_eh_frame_size);

frame = (struct unwind_frame_info *)GETBUF(sizeof(struct unwind_frame_info));
// frame->regs.rsp = bt->stkptr;
@@ -1102,7 +1114,7 @@ dwarf_backtrace(struct bt_info *bt, int level, ulong stacktop)
UNW_PC(frame), frame->regs.rbp);

while ((UNW_SP(frame) < stacktop)
- && !unwind(frame) && UNW_PC(frame)) {
+ && !unwind(frame, is_ehframe) && UNW_PC(frame)) {
/* To prevent rip pushed on IRQ stack being reported both
* both on the IRQ and process stacks
*/
@@ -1193,6 +1205,7 @@ dwarf_debug(struct bt_info *bt)
{
struct unwind_frame_info *frame;
ulong bp;
+ int is_ehframe = (!st->dwarf_debug_frame_size && st->dwarf_eh_frame_size);

if (!bt->hp->eip) {
dump_local_unwind_tables();
@@ -1220,7 +1233,7 @@ dwarf_debug(struct bt_info *bt)
sizeof(unsigned long), "reading bp", FAULT_ON_ERROR);
frame->regs.rbp = bp; /* fixme for x86 */

- unwind(frame);
+ unwind(frame, is_ehframe);

fprintf(fp, "frame size: %lx (%lx)
",
(ulong)UNW_SP(frame), (ulong)UNW_SP(frame) - bt->hp->esp);
diff --git a/unwind_x86_64.h b/unwind_x86_64.h
index 52fcf7a..d3fae15 100644
--- a/unwind_x86_64.h
+++ b/unwind_x86_64.h
@@ -54,7 +54,7 @@ struct unwind_frame_info
struct pt_regs regs;
};

-extern int unwind(struct unwind_frame_info *);
+extern int unwind(struct unwind_frame_info *, int);
extern void init_unwind_table(void);
extern void free_unwind_table(void);

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 11-29-2010, 02:26 PM
Dave Anderson
 
Default Read in .debug_frame section of vmlinux

----- "Wang Chao" <wang.chao@cn.fujitsu.com> wrote:

> 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
 

Thread Tools




All times are GMT. The time now is 07:46 AM.

VBulletin, Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO ©2007, Crawlability, Inc.
Copyright 2007 - 2008, www.linux-archive.org