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 01-07-2011, 01:31 PM
Petr Tesarik
 
Default Make the __per_cpu_offset symbol available

Hi,

the code in xen_hyper_init() tries to determine the per-cpu shift from the
__per_cpu_shift symbol if available. This doesn't work because the symbol's
value is outside the kernel text address range. This patch makes a special
case for this symbol on Xen targets, so it can be used later.

Without this patch, crash initialization fails on SLES11 Xen hypervisor dumps,
because on incorrect per-cpu offset is assumed. The failure can't be fixed
simply by adding a version check, because SLES11 Xen is patched to increase
the per-cpu shift in order to support more CPUs.

It is also important not to try to relocate ABSOLUTE symbol (such as this
one), so add this condition in store_symbols().

Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
---
ia64.c | 22 ++++++++++++++++++++--
symbols.c | 3 ++-
x86.c | 22 ++++++++++++++++++++--
x86_64.c | 22 ++++++++++++++++++++--
4 files changed, 62 insertions(+), 7 deletions(-)

--- a/ia64.c
+++ b/ia64.c
@@ -20,6 +20,7 @@
#include <sys/prctl.h>

static int ia64_verify_symbol(const char *, ulong, char);
+static int ia64_hyper_verify_symbol(const char *, ulong, char);
static int ia64_eframe_search(struct bt_info *);
static void ia64_back_trace_cmd(struct bt_info *);
static void ia64_old_unwind(struct bt_info *);
@@ -571,7 +572,12 @@ ia64_dump_machdep_table(ulong arg)
fprintf(fp, " memory_size: generic_memory_size()
");
fprintf(fp, " vmalloc_start: ia64_vmalloc_start()
");
fprintf(fp, " is_task_addr: ia64_is_task_addr()
");
- fprintf(fp, " verify_symbol: ia64_verify_symbol()
");
+ if (machdep->verify_symbol == ia64_verify_symbol)
+ fprintf(fp, " verify_symbol: ia64_verify_symbol()
");
+ else if (machdep->verify_symbol == ia64_hyper_verify_symbol)
+ fprintf(fp, " verify_symbol: ia64_hyper_verify_symbol()
");
+ else
+ fprintf(fp, " verify_symbol: %lx
", (ulong)machdep->verify_symbol);
fprintf(fp, " dis_filter: ia64_dis_filter()
");
fprintf(fp, " cmd_mach: ia64_cmd_mach()
");
fprintf(fp, " get_smp_cpus: ia64_get_smp_cpus()
");
@@ -724,6 +730,18 @@ ia64_verify_symbol(const char *name, ulo
(region == KERNEL_VMALLOC_REGION)));
}

+static int
+ia64_hyper_verify_symbol(const char *name, ulong value, char type)
+{
+ if (ia64_verify_symbol(name, value, type))
+ return TRUE;
+
+ if (STREQ(name, "__per_cpu_shift"))
+ return TRUE;
+
+ return FALSE;
+}
+

/*
* Look for likely exception frames in a stack.
@@ -4225,7 +4243,7 @@ ia64_init_hyper(int when)
break;

case PRE_SYMTAB:
- machdep->verify_symbol = ia64_verify_symbol;
+ machdep->verify_symbol = ia64_hyper_verify_symbol;
machdep->machspec = &ia64_machine_specific;
if (pc->flags & KERNEL_DEBUG_QUERY)
return;
--- a/symbols.c
+++ b/symbols.c
@@ -568,7 +568,8 @@ store_symbols(bfd *abfd, int dynamic, vo
bfd_get_symbol_info(abfd, sym, &syminfo);
if (machdep->verify_symbol(syminfo.name, syminfo.value,
syminfo.type)) {
- if (kt->flags & (RELOC_SET|RELOC_FORCE))
+ if ((kt->flags & (RELOC_SET|RELOC_FORCE)) &&
+ sym->section != &bfd_abs_section)
sp->value = relocate(syminfo.value,
(char *)syminfo.name, !(first++));
else
--- a/x86.c
+++ b/x86.c
@@ -986,6 +986,7 @@ static void eframe_init(void);
static char *extract_idt_function(ulong *, char *, ulong *);
static int x86_is_task_addr(ulong);
static int x86_verify_symbol(const char *, ulong, char);
+static int x86_hyper_verify_symbol(const char *, ulong, char);
static int x86_eframe_search(struct bt_info *);
static ulong x86_in_irqstack(ulong);
static int x86_dis_filter(ulong, char *);
@@ -3254,7 +3255,12 @@ x86_dump_machdep_table(ulong arg)
fprintf(fp, " memory_size: x86_memory_size()
");
fprintf(fp, " vmalloc_start: x86_vmalloc_start()
");
fprintf(fp, " is_task_addr: x86_is_task_addr()
");
- fprintf(fp, " verify_symbol: x86_verify_symbol()
");
+ if (machdep->verify_symbol == x86_verify_symbol)
+ fprintf(fp, " verify_symbol: x86_verify_symbol()
");
+ else if (machdep->verify_symbol == x86_hyper_verify_symbol)
+ fprintf(fp, " verify_symbol: x86_hyper_verify_symbol()
");
+ else
+ fprintf(fp, " verify_symbol: %lx
", (ulong)machdep->verify_symbol);
fprintf(fp, " dis_filter: x86_dis_filter()
");
fprintf(fp, " cmd_mach: x86_cmd_mach()
");
fprintf(fp, " get_smp_cpus: x86_get_smp_cpus()
");
@@ -3789,6 +3795,18 @@ x86_verify_symbol(const char *name, ulon
return TRUE;
}

+static int
+x86_hyper_verify_symbol(const char *name, ulong value, char type)
+{
+ if (x86_verify_symbol(name, value, type))
+ return TRUE;
+
+ if (STREQ(name, "__per_cpu_shift"))
+ return TRUE;
+
+ return FALSE;
+}
+
/*
* Filter disassembly output if the output radix is not gdb's default 10
*/
@@ -4967,7 +4985,7 @@ x86_init_hyper(int when)
switch (when)
{
case PRE_SYMTAB:
- machdep->verify_symbol = x86_verify_symbol;
+ machdep->verify_symbol = x86_hyper_verify_symbol;
if (pc->flags & KERNEL_DEBUG_QUERY)
return;
machdep->pagesize = memory_page_size();
--- a/x86_64.c
+++ b/x86_64.c
@@ -27,6 +27,7 @@ static int x86_64_uvtop_level4_rhel4_xen
static ulong x86_64_vmalloc_start(void);
static int x86_64_is_task_addr(ulong);
static int x86_64_verify_symbol(const char *, ulong, char);
+static int x86_64_hyper_verify_symbol(const char *, ulong, char);
static ulong x86_64_get_task_pgd(ulong);
static int x86_64_translate_pte(ulong, void *, ulonglong);
static ulong x86_64_processor_speed(void);
@@ -491,7 +492,12 @@ x86_64_dump_machdep_table(ulong arg)
fprintf(fp, " memory_size: generic_memory_size()
");
fprintf(fp, " vmalloc_start: x86_64_vmalloc_start()
");
fprintf(fp, " is_task_addr: x86_64_is_task_addr()
");
- fprintf(fp, " verify_symbol: x86_64_verify_symbol()
");
+ if (machdep->verify_symbol == x86_64_verify_symbol)
+ fprintf(fp, " verify_symbol: x86_64_verify_symbol()
");
+ else if (machdep->verify_symbol == x86_64_hyper_verify_symbol)
+ fprintf(fp, " verify_symbol: x86_64_hyper_verify_symbol()
");
+ else
+ fprintf(fp, " verify_symbol: %lx
", (ulong)machdep->verify_symbol);
fprintf(fp, " dis_filter: x86_64_dis_filter()
");
fprintf(fp, " cmd_mach: x86_64_cmd_mach()
");
fprintf(fp, " get_smp_cpus: x86_64_get_smp_cpus()
");
@@ -1978,6 +1984,18 @@ x86_64_verify_symbol(const char *name, u
return TRUE;
}

+static int
+x86_64_hyper_verify_symbol(const char *name, ulong value, char type)
+{
+ if (x86_64_verify_symbol(name, value, type))
+ return TRUE;
+
+ if (STREQ(name, "__per_cpu_shift"))
+ return TRUE;
+
+ return FALSE;
+}
+

/*
* Get the relevant page directory pointer from a task structure.
@@ -5949,7 +5967,7 @@ x86_64_init_hyper(int when)
switch (when)
{
case PRE_SYMTAB:
- machdep->verify_symbol = x86_64_verify_symbol;
+ machdep->verify_symbol = x86_64_hyper_verify_symbol;
machdep->machspec = &x86_64_machine_specific;
if (pc->flags & KERNEL_DEBUG_QUERY)
return;

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 01-07-2011, 02:20 PM
Dave Anderson
 
Default Make the __per_cpu_offset symbol available

----- Original Message -----
> Hi,
>
> the code in xen_hyper_init() tries to determine the per-cpu shift from the
> __per_cpu_shift symbol if available. This doesn't work because the symbol's
> value is outside the kernel text address range. This patch makes a special
> case for this symbol on Xen targets, so it can be used later.

Hi Petr,

The patch looks OK -- but it seems to be a bit of overkill adding a bunch
of new functions? Couldn't each of the original functions simply have
a check like this right at the top?:

if (XEN_HYPER_MODE() && STREQ(symbol, "__per_cpu_shift"))
return TRUE;

> Without this patch, crash initialization fails on SLES11 Xen hypervisor dumps,
> because on incorrect per-cpu offset is assumed. The failure can't be fixed
> simply by adding a version check, because SLES11 Xen is patched to increase
> the per-cpu shift in order to support more CPUs.
>
> It is also important not to try to relocate ABSOLUTE symbol (such as this
> one), so add this condition in store_symbols().

The reloc stuff is only applicable to live x86/x86_64 vmlinux sessions. To absolutely
ensure backwards-compatibility, I'd rather just put this at the top of relocate():

if (XEN_HYPER_MODE())
return symval;

Would that work for you?

Dave

> Signed-off-by: Petr Tesarik <ptesarik@suse.cz>
> ---
> ia64.c | 22 ++++++++++++++++++++--
> symbols.c | 3 ++-
> x86.c | 22 ++++++++++++++++++++--
> x86_64.c | 22 ++++++++++++++++++++--
> 4 files changed, 62 insertions(+), 7 deletions(-)
>
> --- a/ia64.c
> +++ b/ia64.c
> @@ -20,6 +20,7 @@
> #include <sys/prctl.h>
>
> static int ia64_verify_symbol(const char *, ulong, char);
> +static int ia64_hyper_verify_symbol(const char *, ulong, char);
> static int ia64_eframe_search(struct bt_info *);
> static void ia64_back_trace_cmd(struct bt_info *);
> static void ia64_old_unwind(struct bt_info *);
> @@ -571,7 +572,12 @@ ia64_dump_machdep_table(ulong arg)
> fprintf(fp, " memory_size: generic_memory_size()
");
> fprintf(fp, " vmalloc_start: ia64_vmalloc_start()
");
> fprintf(fp, " is_task_addr: ia64_is_task_addr()
");
> - fprintf(fp, " verify_symbol: ia64_verify_symbol()
");
> + if (machdep->verify_symbol == ia64_verify_symbol)
> + fprintf(fp, " verify_symbol: ia64_verify_symbol()
");
> + else if (machdep->verify_symbol == ia64_hyper_verify_symbol)
> + fprintf(fp, " verify_symbol: ia64_hyper_verify_symbol()
");
> + else
> + fprintf(fp, " verify_symbol: %lx
", (ulong)machdep->verify_symbol);
> fprintf(fp, " dis_filter: ia64_dis_filter()
");
> fprintf(fp, " cmd_mach: ia64_cmd_mach()
");
> fprintf(fp, " get_smp_cpus: ia64_get_smp_cpus()
");
> @@ -724,6 +730,18 @@ ia64_verify_symbol(const char *name, ulo
> (region == KERNEL_VMALLOC_REGION)));
> }
>
> +static int
> +ia64_hyper_verify_symbol(const char *name, ulong value, char type)
> +{
> + if (ia64_verify_symbol(name, value, type))
> + return TRUE;
> +
> + if (STREQ(name, "__per_cpu_shift"))
> + return TRUE;
> +
> + return FALSE;
> +}
> +
>
> /*
> * Look for likely exception frames in a stack.
> @@ -4225,7 +4243,7 @@ ia64_init_hyper(int when)
> break;
>
> case PRE_SYMTAB:
> - machdep->verify_symbol = ia64_verify_symbol;
> + machdep->verify_symbol = ia64_hyper_verify_symbol;
> machdep->machspec = &ia64_machine_specific;
> if (pc->flags & KERNEL_DEBUG_QUERY)
> return;
> --- a/symbols.c
> +++ b/symbols.c
> @@ -568,7 +568,8 @@ store_symbols(bfd *abfd, int dynamic, vo
> bfd_get_symbol_info(abfd, sym, &syminfo);
> if (machdep->verify_symbol(syminfo.name, syminfo.value,
> syminfo.type)) {
> - if (kt->flags & (RELOC_SET|RELOC_FORCE))
> + if ((kt->flags & (RELOC_SET|RELOC_FORCE)) &&
> + sym->section != &bfd_abs_section)
> sp->value = relocate(syminfo.value,
> (char *)syminfo.name, !(first++));
> else
> --- a/x86.c
> +++ b/x86.c
> @@ -986,6 +986,7 @@ static void eframe_init(void);
> static char *extract_idt_function(ulong *, char *, ulong *);
> static int x86_is_task_addr(ulong);
> static int x86_verify_symbol(const char *, ulong, char);
> +static int x86_hyper_verify_symbol(const char *, ulong, char);
> static int x86_eframe_search(struct bt_info *);
> static ulong x86_in_irqstack(ulong);
> static int x86_dis_filter(ulong, char *);
> @@ -3254,7 +3255,12 @@ x86_dump_machdep_table(ulong arg)
> fprintf(fp, " memory_size: x86_memory_size()
");
> fprintf(fp, " vmalloc_start: x86_vmalloc_start()
");
> fprintf(fp, " is_task_addr: x86_is_task_addr()
");
> - fprintf(fp, " verify_symbol: x86_verify_symbol()
");
> + if (machdep->verify_symbol == x86_verify_symbol)
> + fprintf(fp, " verify_symbol: x86_verify_symbol()
");
> + else if (machdep->verify_symbol == x86_hyper_verify_symbol)
> + fprintf(fp, " verify_symbol: x86_hyper_verify_symbol()
");
> + else
> + fprintf(fp, " verify_symbol: %lx
", (ulong)machdep->verify_symbol);
> fprintf(fp, " dis_filter: x86_dis_filter()
");
> fprintf(fp, " cmd_mach: x86_cmd_mach()
");
> fprintf(fp, " get_smp_cpus: x86_get_smp_cpus()
");
> @@ -3789,6 +3795,18 @@ x86_verify_symbol(const char *name, ulon
> return TRUE;
> }
>
> +static int
> +x86_hyper_verify_symbol(const char *name, ulong value, char type)
> +{
> + if (x86_verify_symbol(name, value, type))
> + return TRUE;
> +
> + if (STREQ(name, "__per_cpu_shift"))
> + return TRUE;
> +
> + return FALSE;
> +}
> +
> /*
> * Filter disassembly output if the output radix is not gdb's default
> 10
> */
> @@ -4967,7 +4985,7 @@ x86_init_hyper(int when)
> switch (when)
> {
> case PRE_SYMTAB:
> - machdep->verify_symbol = x86_verify_symbol;
> + machdep->verify_symbol = x86_hyper_verify_symbol;
> if (pc->flags & KERNEL_DEBUG_QUERY)
> return;
> machdep->pagesize = memory_page_size();
> --- a/x86_64.c
> +++ b/x86_64.c
> @@ -27,6 +27,7 @@ static int x86_64_uvtop_level4_rhel4_xen
> static ulong x86_64_vmalloc_start(void);
> static int x86_64_is_task_addr(ulong);
> static int x86_64_verify_symbol(const char *, ulong, char);
> +static int x86_64_hyper_verify_symbol(const char *, ulong, char);
> static ulong x86_64_get_task_pgd(ulong);
> static int x86_64_translate_pte(ulong, void *, ulonglong);
> static ulong x86_64_processor_speed(void);
> @@ -491,7 +492,12 @@ x86_64_dump_machdep_table(ulong arg)
> fprintf(fp, " memory_size: generic_memory_size()
");
> fprintf(fp, " vmalloc_start: x86_64_vmalloc_start()
");
> fprintf(fp, " is_task_addr: x86_64_is_task_addr()
");
> - fprintf(fp, " verify_symbol: x86_64_verify_symbol()
");
> + if (machdep->verify_symbol == x86_64_verify_symbol)
> + fprintf(fp, " verify_symbol: x86_64_verify_symbol()
");
> + else if (machdep->verify_symbol == x86_64_hyper_verify_symbol)
> + fprintf(fp, " verify_symbol: x86_64_hyper_verify_symbol()
");
> + else
> + fprintf(fp, " verify_symbol: %lx
", (ulong)machdep->verify_symbol);
> fprintf(fp, " dis_filter: x86_64_dis_filter()
");
> fprintf(fp, " cmd_mach: x86_64_cmd_mach()
");
> fprintf(fp, " get_smp_cpus: x86_64_get_smp_cpus()
");
> @@ -1978,6 +1984,18 @@ x86_64_verify_symbol(const char *name, u
> return TRUE;
> }
>
> +static int
> +x86_64_hyper_verify_symbol(const char *name, ulong value, char type)
> +{
> + if (x86_64_verify_symbol(name, value, type))
> + return TRUE;
> +
> + if (STREQ(name, "__per_cpu_shift"))
> + return TRUE;
> +
> + return FALSE;
> +}
> +
>
> /*
> * Get the relevant page directory pointer from a task structure.
> @@ -5949,7 +5967,7 @@ x86_64_init_hyper(int when)
> switch (when)
> {
> case PRE_SYMTAB:
> - machdep->verify_symbol = x86_64_verify_symbol;
> + machdep->verify_symbol = x86_64_hyper_verify_symbol;
> machdep->machspec = &x86_64_machine_specific;
> if (pc->flags & KERNEL_DEBUG_QUERY)
> return;
>
> --
> Crash-utility mailing list
> Crash-utility@redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility

--
Crash-utility mailing list
Crash-utility@redhat.com
https://www.redhat.com/mailman/listinfo/crash-utility
 
Old 01-07-2011, 02:40 PM
Dave Anderson
 
Default Make the __per_cpu_offset symbol available

----- Original Message -----
> On Friday 07 of January 2011 16:20:15 Dave Anderson wrote:
> > ----- Original Message -----
> >
> > > Hi,
> > >
> > > the code in xen_hyper_init() tries to determine the per-cpu shift from
> > > the __per_cpu_shift symbol if available. This doesn't work because the
> > > symbol's value is outside the kernel text address range. This patch makes
> > > a special case for this symbol on Xen targets, so it can be used
> > > later.
> >
> > Hi Petr,
>
> Hi Dave,
>
> > The patch looks OK -- but it seems to be a bit of overkill adding a bunch
> > of new functions? Couldn't each of the original functions simply have
> > a check like this right at the top?:
> >
> > if (XEN_HYPER_MODE() && STREQ(symbol, "__per_cpu_shift"))
> > return TRUE;
>
> Er, yes. When I started the patch, I thought I would need some more special
> handling, but it then boiled down to just this one symbol, so you're right,
> it works.
>
> > > Without this patch, crash initialization fails on SLES11 Xen hypervisor
> > > dumps, because on incorrect per-cpu offset is assumed. The failure can't
> > > be fixed simply by adding a version check, because SLES11 Xen is patched
> > > to increase the per-cpu shift in order to support more CPUs.
> > >
> > > It is also important not to try to relocate ABSOLUTE symbol (such as this
> > > one), so add this condition in store_symbols().
> >
> > The reloc stuff is only applicable to live x86/x86_64 vmlinux sessions. To
> > absolutely ensure backwards-compatibility, I'd rather just put this at the
> > top of relocate():
> >
> > if (XEN_HYPER_MODE())
> > return symval;
> >
> > Would that work for you?
>
> Yes, sure. As long as we don't have live sessions on relocatable Xen
> hypervisors. Which isn't coming... Here's the shorter patch:
>
> Signed-off-by: Petr Tesarik <ptesarik@suse.cz>

Cool -- queued for the next release!

BTW, I appreciate the Xen version 4 support. Given that Red Hat has dropped
Xen as of RHEL6, there wouldn't be any ongoing maintenance coming from this
side of the house.

Thanks again,
Dave


> ---
> ia64.c | 3 +++
> symbols.c | 3 +++
> x86.c | 3 +++
> x86_64.c | 3 +++
> 4 files changed, 12 insertions(+)
>
> --- a/ia64.c
> +++ b/ia64.c
> @@ -711,6 +711,9 @@ ia64_verify_symbol(const char *name, ulo
> if (!name || !strlen(name))
> return FALSE;
>
> + if (XEN_HYPER_MODE() && STREQ(name, "__per_cpu_shift"))
> + return TRUE;
> +
> if (CRASHDEBUG(8))
> fprintf(fp, "%016lx %s
", value, name);
>
> --- a/symbols.c
> +++ b/symbols.c
> @@ -678,6 +678,9 @@ store_sysmap_symbols(void)
> static ulong
> relocate(ulong symval, char *symname, int first_symbol)
> {
> + if (XEN_HYPER_MODE())
> + return symval;
> +
> switch (kt->flags & (RELOC_SET|RELOC_FORCE))
> {
> case RELOC_SET:
> --- a/x86.c
> +++ b/x86.c
> @@ -3785,6 +3785,9 @@ x86_is_task_addr(ulong task)
> static int
> x86_verify_symbol(const char *name, ulong value, char type)
> {
> + if (XEN_HYPER_MODE() && STREQ(name, "__per_cpu_shift"))
> + return TRUE;
> +
> if (CRASHDEBUG(8) && name && strlen(name))
> fprintf(fp, "%08lx %s
", value, name);
>
> --- a/x86_64.c
> +++ b/x86_64.c
> @@ -1989,6 +1989,9 @@ x86_64_verify_symbol(const char *name, u
> if (!name || !strlen(name))
> return FALSE;
>
> + if (XEN_HYPER_MODE() && STREQ(name, "__per_cpu_shift"))
> + return TRUE;
> +
> if (!(machdep->flags & KSYMS_START)) {
> if (STREQ(name, "_text") || STREQ(name, "_stext")) {
> machdep->flags |= KSYMS_START;

--
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 10:01 PM.

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