909 lines
25 KiB
Diff
909 lines
25 KiB
Diff
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||
|
From: Peter Jones <pjones@redhat.com>
|
||
|
Date: Mon, 6 Nov 2017 18:31:56 -0500
|
||
|
Subject: [PATCH] make better backtraces
|
||
|
|
||
|
Signed-off-by: Peter Jones <pjones@redhat.com>
|
||
|
---
|
||
|
Makefile.util.def | 6 ++
|
||
|
grub-core/Makefile.core.def | 15 ++--
|
||
|
grub-core/{lib => commands}/backtrace.c | 2 +-
|
||
|
grub-core/gdb/cstub.c | 1 -
|
||
|
grub-core/kern/arm64/backtrace.c | 94 ++++++++++++++++++++++++
|
||
|
grub-core/kern/backtrace.c | 97 +++++++++++++++++++++++++
|
||
|
grub-core/kern/dl.c | 45 ++++++++++++
|
||
|
grub-core/kern/i386/backtrace.c | 125 ++++++++++++++++++++++++++++++++
|
||
|
grub-core/kern/i386/pc/init.c | 4 +-
|
||
|
grub-core/kern/ieee1275/init.c | 1 -
|
||
|
grub-core/kern/misc.c | 13 ++--
|
||
|
grub-core/kern/mm.c | 6 +-
|
||
|
grub-core/lib/arm64/backtrace.c | 62 ----------------
|
||
|
grub-core/lib/i386/backtrace.c | 78 --------------------
|
||
|
include/grub/backtrace.h | 10 ++-
|
||
|
include/grub/dl.h | 2 +
|
||
|
include/grub/kernel.h | 3 +
|
||
|
grub-core/kern/arm/efi/startup.S | 2 +
|
||
|
grub-core/kern/arm/startup.S | 2 +
|
||
|
grub-core/kern/arm64/efi/startup.S | 2 +
|
||
|
grub-core/kern/i386/qemu/startup.S | 3 +-
|
||
|
grub-core/kern/ia64/efi/startup.S | 3 +-
|
||
|
grub-core/kern/sparc64/ieee1275/crt0.S | 3 +-
|
||
|
grub-core/Makefile.am | 1 +
|
||
|
24 files changed, 414 insertions(+), 166 deletions(-)
|
||
|
rename grub-core/{lib => commands}/backtrace.c (98%)
|
||
|
create mode 100644 grub-core/kern/arm64/backtrace.c
|
||
|
create mode 100644 grub-core/kern/backtrace.c
|
||
|
create mode 100644 grub-core/kern/i386/backtrace.c
|
||
|
delete mode 100644 grub-core/lib/arm64/backtrace.c
|
||
|
delete mode 100644 grub-core/lib/i386/backtrace.c
|
||
|
|
||
|
diff --git a/Makefile.util.def b/Makefile.util.def
|
||
|
index f4fbd2506..cbd661d63 100644
|
||
|
--- a/Makefile.util.def
|
||
|
+++ b/Makefile.util.def
|
||
|
@@ -49,6 +49,12 @@ library = {
|
||
|
common = grub-core/partmap/msdos.c;
|
||
|
common = grub-core/fs/proc.c;
|
||
|
common = grub-core/fs/archelp.c;
|
||
|
+ common = grub-core/kern/backtrace.c;
|
||
|
+
|
||
|
+ x86 = grub-core/kern/i386/backtrace.c;
|
||
|
+ i386_xen = grub-core/kern/i386/backtrace.c;
|
||
|
+ x86_64_xen = grub-core/kern/i386/backtrace.c;
|
||
|
+ arm64 = grub-core/kern/arm64/backtrace.c;
|
||
|
};
|
||
|
|
||
|
library = {
|
||
|
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
||
|
index 067b97a42..cb24f92a4 100644
|
||
|
--- a/grub-core/Makefile.core.def
|
||
|
+++ b/grub-core/Makefile.core.def
|
||
|
@@ -130,6 +130,12 @@ kernel = {
|
||
|
common = kern/rescue_reader.c;
|
||
|
common = kern/term.c;
|
||
|
common = kern/qsort.c;
|
||
|
+ common = kern/backtrace.c;
|
||
|
+
|
||
|
+ x86 = kern/i386/backtrace.c;
|
||
|
+ i386_xen = kern/i386/backtrace.c;
|
||
|
+ x86_64_xen = kern/i386/backtrace.c;
|
||
|
+ arm64 = kern/arm64/backtrace.c;
|
||
|
|
||
|
noemu = kern/compiler-rt.c;
|
||
|
noemu = kern/mm.c;
|
||
|
@@ -176,9 +182,6 @@ kernel = {
|
||
|
|
||
|
softdiv = lib/division.c;
|
||
|
|
||
|
- x86 = lib/i386/backtrace.c;
|
||
|
- x86 = lib/backtrace.c;
|
||
|
-
|
||
|
i386 = kern/i386/dl.c;
|
||
|
i386_xen = kern/i386/dl.c;
|
||
|
|
||
|
@@ -2277,13 +2280,11 @@ module = {
|
||
|
|
||
|
module = {
|
||
|
name = backtrace;
|
||
|
- x86 = lib/i386/backtrace.c;
|
||
|
- i386_xen = lib/i386/backtrace.c;
|
||
|
- x86_64_xen = lib/i386/backtrace.c;
|
||
|
- common = lib/backtrace.c;
|
||
|
+ common = commands/backtrace.c;
|
||
|
enable = x86;
|
||
|
enable = i386_xen;
|
||
|
enable = x86_64_xen;
|
||
|
+ enable = arm64;
|
||
|
};
|
||
|
|
||
|
module = {
|
||
|
diff --git a/grub-core/lib/backtrace.c b/grub-core/commands/backtrace.c
|
||
|
similarity index 98%
|
||
|
rename from grub-core/lib/backtrace.c
|
||
|
rename to grub-core/commands/backtrace.c
|
||
|
index c0ad6ab8b..8b5ec3913 100644
|
||
|
--- a/grub-core/lib/backtrace.c
|
||
|
+++ b/grub-core/commands/backtrace.c
|
||
|
@@ -54,7 +54,7 @@ grub_cmd_backtrace (grub_command_t cmd __attribute__ ((unused)),
|
||
|
int argc __attribute__ ((unused)),
|
||
|
char **args __attribute__ ((unused)))
|
||
|
{
|
||
|
- grub_backtrace ();
|
||
|
+ grub_backtrace (1);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
diff --git a/grub-core/gdb/cstub.c b/grub-core/gdb/cstub.c
|
||
|
index b64acd70f..99281472d 100644
|
||
|
--- a/grub-core/gdb/cstub.c
|
||
|
+++ b/grub-core/gdb/cstub.c
|
||
|
@@ -215,7 +215,6 @@ grub_gdb_trap (int trap_no)
|
||
|
grub_printf ("Unhandled exception 0x%x at ", trap_no);
|
||
|
grub_backtrace_print_address ((void *) grub_gdb_regs[PC]);
|
||
|
grub_printf ("\n");
|
||
|
- grub_backtrace_pointer ((void *) grub_gdb_regs[EBP]);
|
||
|
grub_fatal ("Unhandled exception");
|
||
|
}
|
||
|
|
||
|
diff --git a/grub-core/kern/arm64/backtrace.c b/grub-core/kern/arm64/backtrace.c
|
||
|
new file mode 100644
|
||
|
index 000000000..019c6fdfe
|
||
|
--- /dev/null
|
||
|
+++ b/grub-core/kern/arm64/backtrace.c
|
||
|
@@ -0,0 +1,94 @@
|
||
|
+/*
|
||
|
+ * GRUB -- GRand Unified Bootloader
|
||
|
+ * Copyright (C) 2009 Free Software Foundation, Inc.
|
||
|
+ *
|
||
|
+ * GRUB is free software: you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, either version 3 of the License, or
|
||
|
+ * (at your option) any later version.
|
||
|
+ *
|
||
|
+ * GRUB is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <grub/misc.h>
|
||
|
+#include <grub/command.h>
|
||
|
+#include <grub/err.h>
|
||
|
+#include <grub/dl.h>
|
||
|
+#include <grub/mm.h>
|
||
|
+#include <grub/term.h>
|
||
|
+#include <grub/backtrace.h>
|
||
|
+
|
||
|
+#define MAX_STACK_FRAME 102400
|
||
|
+
|
||
|
+struct fplr
|
||
|
+{
|
||
|
+ void *lr;
|
||
|
+ struct fplr *fp;
|
||
|
+};
|
||
|
+
|
||
|
+void
|
||
|
+grub_backtrace_pointer (void *frame, unsigned int skip)
|
||
|
+{
|
||
|
+ unsigned int x = 0;
|
||
|
+ struct fplr *fplr = (struct fplr *)frame;
|
||
|
+
|
||
|
+ while (fplr)
|
||
|
+ {
|
||
|
+ const char *name = NULL;
|
||
|
+ char *addr = NULL;
|
||
|
+
|
||
|
+ grub_dprintf("backtrace", "fp is %p next_fp is %p\n",
|
||
|
+ fplr, fplr->fp);
|
||
|
+
|
||
|
+ if (x >= skip)
|
||
|
+ {
|
||
|
+ name = grub_get_symbol_by_addr (fplr->lr, 1);
|
||
|
+ if (name)
|
||
|
+ addr = grub_resolve_symbol (name);
|
||
|
+ grub_backtrace_print_address (fplr->lr);
|
||
|
+
|
||
|
+ if (addr && addr != fplr->lr)
|
||
|
+ grub_printf (" %s() %p+%p \n", name ? name : "unknown", addr,
|
||
|
+ (void *)((grub_uint64_t)fplr->lr - (grub_uint64_t)addr));
|
||
|
+ else
|
||
|
+ grub_printf(" %s() %p \n", name ? name : "unknown", addr);
|
||
|
+
|
||
|
+ }
|
||
|
+
|
||
|
+ x += 1;
|
||
|
+
|
||
|
+ if (fplr->fp < fplr ||
|
||
|
+ (grub_uint64_t)fplr->fp - (grub_uint64_t)fplr > MAX_STACK_FRAME ||
|
||
|
+ fplr->fp == fplr)
|
||
|
+ {
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ fplr = fplr->fp;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+asm ("\t.global \"_text\"\n"
|
||
|
+ "_text:\n"
|
||
|
+ "\t.quad .text\n"
|
||
|
+ "\t.global \"_data\"\n"
|
||
|
+ "_data:\n"
|
||
|
+ "\t.quad .data\n"
|
||
|
+ );
|
||
|
+
|
||
|
+extern grub_uint64_t _text;
|
||
|
+extern grub_uint64_t _data;
|
||
|
+
|
||
|
+void
|
||
|
+grub_backtrace_arch (unsigned int skip)
|
||
|
+{
|
||
|
+ grub_printf ("Backtrace (.text %p .data %p):\n",
|
||
|
+ (void *)_text, (void *)_data);
|
||
|
+ skip += 1;
|
||
|
+ grub_backtrace_pointer(__builtin_frame_address(0), skip);
|
||
|
+}
|
||
|
diff --git a/grub-core/kern/backtrace.c b/grub-core/kern/backtrace.c
|
||
|
new file mode 100644
|
||
|
index 000000000..4a82e865c
|
||
|
--- /dev/null
|
||
|
+++ b/grub-core/kern/backtrace.c
|
||
|
@@ -0,0 +1,97 @@
|
||
|
+/*
|
||
|
+ * GRUB -- GRand Unified Bootloader
|
||
|
+ * Copyright (C) 2009 Free Software Foundation, Inc.
|
||
|
+ *
|
||
|
+ * GRUB is free software: you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, either version 3 of the License, or
|
||
|
+ * (at your option) any later version.
|
||
|
+ *
|
||
|
+ * GRUB is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <grub/misc.h>
|
||
|
+#include <grub/command.h>
|
||
|
+#include <grub/err.h>
|
||
|
+#include <grub/dl.h>
|
||
|
+#include <grub/mm.h>
|
||
|
+#include <grub/term.h>
|
||
|
+#include <grub/backtrace.h>
|
||
|
+
|
||
|
+GRUB_MOD_LICENSE ("GPLv3+");
|
||
|
+
|
||
|
+static void
|
||
|
+grub_backtrace_print_address_default (void *addr)
|
||
|
+{
|
||
|
+#ifndef GRUB_UTIL
|
||
|
+ grub_dl_t mod;
|
||
|
+ void *start_addr;
|
||
|
+
|
||
|
+ FOR_DL_MODULES (mod)
|
||
|
+ {
|
||
|
+ grub_dl_segment_t segment;
|
||
|
+ for (segment = mod->segment; segment; segment = segment->next)
|
||
|
+ if (segment->addr <= addr && (grub_uint8_t *) segment->addr
|
||
|
+ + segment->size > (grub_uint8_t *) addr)
|
||
|
+ {
|
||
|
+ grub_printf ("%s.%x+%" PRIxGRUB_SIZE, mod->name,
|
||
|
+ segment->section,
|
||
|
+ (grub_size_t)
|
||
|
+ ((grub_uint8_t *)addr - (grub_uint8_t *)segment->addr));
|
||
|
+ return;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ start_addr = grub_resolve_symbol ("_start");
|
||
|
+ if (start_addr && start_addr < addr)
|
||
|
+ grub_printf ("kernel+%" PRIxGRUB_SIZE,
|
||
|
+ (grub_size_t)
|
||
|
+ ((grub_uint8_t *)addr - (grub_uint8_t *)start_addr));
|
||
|
+ else
|
||
|
+#endif
|
||
|
+ grub_printf ("%p", addr);
|
||
|
+}
|
||
|
+
|
||
|
+static void
|
||
|
+grub_backtrace_pointer_default (void *frame __attribute__((__unused__)),
|
||
|
+ unsigned int skip __attribute__((__unused__)))
|
||
|
+{
|
||
|
+ return;
|
||
|
+}
|
||
|
+
|
||
|
+void
|
||
|
+grub_backtrace_pointer (void *frame, unsigned int skip)
|
||
|
+ __attribute__((__weak__,
|
||
|
+ __alias__(("grub_backtrace_pointer_default"))));
|
||
|
+
|
||
|
+void
|
||
|
+grub_backtrace_print_address (void *addr)
|
||
|
+ __attribute__((__weak__,
|
||
|
+ __alias__(("grub_backtrace_print_address_default"))));
|
||
|
+
|
||
|
+static void
|
||
|
+grub_backtrace_arch_default(unsigned int skip)
|
||
|
+{
|
||
|
+ grub_backtrace_pointer(__builtin_frame_address(0), skip + 1);
|
||
|
+}
|
||
|
+
|
||
|
+void grub_backtrace_arch (unsigned int skip)
|
||
|
+ __attribute__((__weak__, __alias__(("grub_backtrace_arch_default"))));
|
||
|
+
|
||
|
+void grub_backtrace (unsigned int skip)
|
||
|
+{
|
||
|
+ grub_backtrace_arch(skip + 1);
|
||
|
+}
|
||
|
+
|
||
|
+void grub_debug_backtrace (const char * const debug,
|
||
|
+ unsigned int skip)
|
||
|
+{
|
||
|
+ if (grub_debug_enabled (debug))
|
||
|
+ grub_backtrace (skip + 1);
|
||
|
+}
|
||
|
diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c
|
||
|
index 621070918..5028d157c 100644
|
||
|
--- a/grub-core/kern/dl.c
|
||
|
+++ b/grub-core/kern/dl.c
|
||
|
@@ -124,6 +124,50 @@ grub_dl_resolve_symbol (const char *name)
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
+void *
|
||
|
+grub_resolve_symbol (const char *name)
|
||
|
+{
|
||
|
+ grub_symbol_t sym;
|
||
|
+
|
||
|
+ sym = grub_dl_resolve_symbol (name);
|
||
|
+ if (sym)
|
||
|
+ return sym->addr;
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
+const char *
|
||
|
+grub_get_symbol_by_addr(const void *addr, int isfunc)
|
||
|
+{
|
||
|
+ unsigned int i;
|
||
|
+ grub_symbol_t before = NULL, after = NULL;
|
||
|
+ for (i = 0; i < GRUB_SYMTAB_SIZE; i++)
|
||
|
+ {
|
||
|
+ grub_symbol_t sym;
|
||
|
+ for (sym = grub_symtab[i]; sym; sym = sym->next)
|
||
|
+ {
|
||
|
+ //grub_printf ("addr 0x%08llx symbol %s\n", (unsigned long long)sym->addr, sym->name);
|
||
|
+ if (sym->addr > addr)
|
||
|
+ {
|
||
|
+ if (!after || sym->addr > after->addr)
|
||
|
+ after = sym;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (isfunc != sym->isfunc)
|
||
|
+ continue;
|
||
|
+ if (sym->addr > addr)
|
||
|
+ continue;
|
||
|
+
|
||
|
+ if ((!before && sym->addr <= addr) || (before && before->addr <= sym->addr))
|
||
|
+ before = sym;
|
||
|
+ }
|
||
|
+ }
|
||
|
+
|
||
|
+ if (before && addr < after->addr)
|
||
|
+ return before->name;
|
||
|
+
|
||
|
+ return NULL;
|
||
|
+}
|
||
|
+
|
||
|
/* Register a symbol with the name NAME and the address ADDR. */
|
||
|
grub_err_t
|
||
|
grub_dl_register_symbol (const char *name, void *addr, int isfunc,
|
||
|
@@ -336,6 +380,7 @@ grub_dl_resolve_symbols (grub_dl_t mod, Elf_Ehdr *e)
|
||
|
const char *str;
|
||
|
Elf_Word size, entsize;
|
||
|
|
||
|
+ grub_dprintf ("modules", "Resolving symbols for \"%s\"\n", mod->name);
|
||
|
for (i = 0, s = (Elf_Shdr *) ((char *) e + e->e_shoff);
|
||
|
i < e->e_shnum;
|
||
|
i++, s = (Elf_Shdr *) ((char *) s + e->e_shentsize))
|
||
|
diff --git a/grub-core/kern/i386/backtrace.c b/grub-core/kern/i386/backtrace.c
|
||
|
new file mode 100644
|
||
|
index 000000000..2413f9a57
|
||
|
--- /dev/null
|
||
|
+++ b/grub-core/kern/i386/backtrace.c
|
||
|
@@ -0,0 +1,125 @@
|
||
|
+/*
|
||
|
+ * GRUB -- GRand Unified Bootloader
|
||
|
+ * Copyright (C) 2009 Free Software Foundation, Inc.
|
||
|
+ *
|
||
|
+ * GRUB is free software: you can redistribute it and/or modify
|
||
|
+ * it under the terms of the GNU General Public License as published by
|
||
|
+ * the Free Software Foundation, either version 3 of the License, or
|
||
|
+ * (at your option) any later version.
|
||
|
+ *
|
||
|
+ * GRUB is distributed in the hope that it will be useful,
|
||
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
+ * GNU General Public License for more details.
|
||
|
+ *
|
||
|
+ * You should have received a copy of the GNU General Public License
|
||
|
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||
|
+ */
|
||
|
+
|
||
|
+#include <grub/misc.h>
|
||
|
+#include <grub/command.h>
|
||
|
+#include <grub/err.h>
|
||
|
+#include <grub/dl.h>
|
||
|
+#include <grub/mm.h>
|
||
|
+#include <grub/term.h>
|
||
|
+#include <grub/backtrace.h>
|
||
|
+
|
||
|
+#define MAX_STACK_FRAME 102400
|
||
|
+
|
||
|
+void
|
||
|
+grub_backtrace_pointer (void *frame, unsigned int skip)
|
||
|
+{
|
||
|
+ void **ebp = (void **)frame;
|
||
|
+ unsigned long x = 0;
|
||
|
+
|
||
|
+ while (ebp)
|
||
|
+ {
|
||
|
+ void **next_ebp = (void **)ebp[0];
|
||
|
+ const char *name = NULL;
|
||
|
+ char *addr = NULL;
|
||
|
+
|
||
|
+ grub_dprintf("backtrace", "ebp is %p next_ebp is %p\n", ebp, next_ebp);
|
||
|
+
|
||
|
+ if (x >= skip)
|
||
|
+ {
|
||
|
+ name = grub_get_symbol_by_addr (ebp[1], 1);
|
||
|
+ if (name)
|
||
|
+ addr = grub_resolve_symbol (name);
|
||
|
+ grub_backtrace_print_address (ebp[1]);
|
||
|
+
|
||
|
+ if (addr && addr != ebp[1])
|
||
|
+ grub_printf (" %s() %p+%p \n", name ? name : "unknown", addr,
|
||
|
+ (char *)((char *)ebp[1] - addr));
|
||
|
+ else
|
||
|
+ grub_printf(" %s() %p \n", name ? name : "unknown", addr);
|
||
|
+
|
||
|
+#if 0
|
||
|
+ grub_printf ("(");
|
||
|
+ for (i = 0, arg = ebp[2]; arg != next_ebp && i < 12; arg++, i++)
|
||
|
+ grub_printf ("%p,", arg);
|
||
|
+ grub_printf (")\n");
|
||
|
+#endif
|
||
|
+ }
|
||
|
+
|
||
|
+ x += 1;
|
||
|
+
|
||
|
+ if (next_ebp < ebp || next_ebp - ebp > MAX_STACK_FRAME || next_ebp == ebp)
|
||
|
+ {
|
||
|
+ //grub_printf ("Invalid stack frame at %p (%p)\n", ebp, next_ebp);
|
||
|
+ break;
|
||
|
+ }
|
||
|
+ ebp = next_ebp;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+#if defined (__x86_64__)
|
||
|
+asm ("\t.global \"_text\"\n"
|
||
|
+ "_text:\n"
|
||
|
+ "\t.quad .text\n"
|
||
|
+ "\t.global \"_data\"\n"
|
||
|
+ "_data:\n"
|
||
|
+ "\t.quad .data\n"
|
||
|
+ );
|
||
|
+#elif defined(__i386__)
|
||
|
+asm ("\t.global \"_text\"\n"
|
||
|
+ "_text:\n"
|
||
|
+ "\t.long .text\n"
|
||
|
+ "\t.global \"_data\"\n"
|
||
|
+ "_data:\n"
|
||
|
+ "\t.long .data\n"
|
||
|
+ );
|
||
|
+#else
|
||
|
+#warning I dunno...
|
||
|
+#endif
|
||
|
+
|
||
|
+extern unsigned long _text;
|
||
|
+extern unsigned long _data;
|
||
|
+
|
||
|
+#ifdef GRUB_UTIL
|
||
|
+#define EXT_C(x) x
|
||
|
+#endif
|
||
|
+
|
||
|
+void
|
||
|
+grub_backtrace_arch (unsigned int skip)
|
||
|
+{
|
||
|
+ grub_printf ("Backtrace (.text %p .data %p):\n",
|
||
|
+ (void *)_text, (void *)_data);
|
||
|
+ skip += 1;
|
||
|
+#if defined (__x86_64__)
|
||
|
+ asm volatile ("movq %%rbp, %%rdi\n"
|
||
|
+ "movq 0, %%rsi\n"
|
||
|
+ "movl %0, %%esi\n"
|
||
|
+ "call " EXT_C("grub_backtrace_pointer")
|
||
|
+ :
|
||
|
+ : "r" (skip));
|
||
|
+#elif defined(__i386__)
|
||
|
+ asm volatile ("addl $8, %%esp\n"
|
||
|
+ "pushl %0\n"
|
||
|
+ "pushl %%ebp\n"
|
||
|
+ "call " EXT_C("grub_backtrace_pointer")
|
||
|
+ :
|
||
|
+ : "r" (skip));
|
||
|
+#else
|
||
|
+ grub_backtrace_pointer(__builtin_frame_address(0), skip);
|
||
|
+#endif
|
||
|
+}
|
||
|
diff --git a/grub-core/kern/i386/pc/init.c b/grub-core/kern/i386/pc/init.c
|
||
|
index 27bc68b8a..b51d0abfa 100644
|
||
|
--- a/grub-core/kern/i386/pc/init.c
|
||
|
+++ b/grub-core/kern/i386/pc/init.c
|
||
|
@@ -153,7 +153,7 @@ compact_mem_regions (void)
|
||
|
}
|
||
|
|
||
|
grub_addr_t grub_modbase;
|
||
|
-extern grub_uint8_t _start[], _edata[];
|
||
|
+extern grub_uint8_t _edata[];
|
||
|
|
||
|
/* Helper for grub_machine_init. */
|
||
|
static int
|
||
|
@@ -217,7 +217,7 @@ grub_machine_init (void)
|
||
|
/* This has to happen before any BIOS calls. */
|
||
|
grub_via_workaround_init ();
|
||
|
|
||
|
- grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - _start);
|
||
|
+ grub_modbase = GRUB_MEMORY_MACHINE_DECOMPRESSION_ADDR + (_edata - (grub_uint8_t *)_start);
|
||
|
|
||
|
/* Initialize the console as early as possible. */
|
||
|
grub_console_init ();
|
||
|
diff --git a/grub-core/kern/ieee1275/init.c b/grub-core/kern/ieee1275/init.c
|
||
|
index e01bc6eab..e731a57a4 100644
|
||
|
--- a/grub-core/kern/ieee1275/init.c
|
||
|
+++ b/grub-core/kern/ieee1275/init.c
|
||
|
@@ -60,7 +60,6 @@
|
||
|
#define HEAP_MAX_ADDR (unsigned long) (32 * 1024 * 1024)
|
||
|
#endif
|
||
|
|
||
|
-extern char _start[];
|
||
|
extern char _end[];
|
||
|
|
||
|
#ifdef __sparc__
|
||
|
diff --git a/grub-core/kern/misc.c b/grub-core/kern/misc.c
|
||
|
index e758ab341..5c2d2039d 100644
|
||
|
--- a/grub-core/kern/misc.c
|
||
|
+++ b/grub-core/kern/misc.c
|
||
|
@@ -1110,15 +1110,15 @@ grub_xasprintf (const char *fmt, ...)
|
||
|
}
|
||
|
|
||
|
/* Abort GRUB. This function does not return. */
|
||
|
-static void __attribute__ ((noreturn))
|
||
|
+static inline void __attribute__ ((noreturn))
|
||
|
grub_abort (void)
|
||
|
{
|
||
|
-#ifndef GRUB_UTIL
|
||
|
-#if (defined(__i386__) || defined(__x86_64__)) && !defined(GRUB_MACHINE_EMU)
|
||
|
- grub_backtrace();
|
||
|
+#if !defined(GRUB_MACHINE_EMU) && !defined(GRUB_UTIL)
|
||
|
+ grub_backtrace (1);
|
||
|
+#else
|
||
|
+ grub_printf ("\n");
|
||
|
#endif
|
||
|
-#endif
|
||
|
- grub_printf ("\nAborted.");
|
||
|
+ grub_printf ("Aborted.");
|
||
|
|
||
|
#ifndef GRUB_UTIL
|
||
|
if (grub_term_inputs)
|
||
|
@@ -1145,6 +1145,7 @@ grub_fatal (const char *fmt, ...)
|
||
|
{
|
||
|
va_list ap;
|
||
|
|
||
|
+ grub_printf ("\n");
|
||
|
va_start (ap, fmt);
|
||
|
grub_vprintf (_(fmt), ap);
|
||
|
va_end (ap);
|
||
|
diff --git a/grub-core/kern/mm.c b/grub-core/kern/mm.c
|
||
|
index ee88ff611..002cbfa4f 100644
|
||
|
--- a/grub-core/kern/mm.c
|
||
|
+++ b/grub-core/kern/mm.c
|
||
|
@@ -95,13 +95,13 @@ get_header_from_pointer (void *ptr, grub_mm_header_t *p, grub_mm_region_t *r)
|
||
|
break;
|
||
|
|
||
|
if (! *r)
|
||
|
- grub_fatal ("out of range pointer %p", ptr);
|
||
|
+ grub_fatal ("out of range pointer %p\n", ptr);
|
||
|
|
||
|
*p = (grub_mm_header_t) ptr - 1;
|
||
|
if ((*p)->magic == GRUB_MM_FREE_MAGIC)
|
||
|
- grub_fatal ("double free at %p", *p);
|
||
|
+ grub_fatal ("double free at %p\n", *p);
|
||
|
if ((*p)->magic != GRUB_MM_ALLOC_MAGIC)
|
||
|
- grub_fatal ("alloc magic is broken at %p: %lx", *p,
|
||
|
+ grub_fatal ("alloc magic is broken at %p: %lx\n", *p,
|
||
|
(unsigned long) (*p)->magic);
|
||
|
}
|
||
|
|
||
|
diff --git a/grub-core/lib/arm64/backtrace.c b/grub-core/lib/arm64/backtrace.c
|
||
|
deleted file mode 100644
|
||
|
index 1079b5380..000000000
|
||
|
--- a/grub-core/lib/arm64/backtrace.c
|
||
|
+++ /dev/null
|
||
|
@@ -1,62 +0,0 @@
|
||
|
-/*
|
||
|
- * GRUB -- GRand Unified Bootloader
|
||
|
- * Copyright (C) 2009 Free Software Foundation, Inc.
|
||
|
- *
|
||
|
- * GRUB is free software: you can redistribute it and/or modify
|
||
|
- * it under the terms of the GNU General Public License as published by
|
||
|
- * the Free Software Foundation, either version 3 of the License, or
|
||
|
- * (at your option) any later version.
|
||
|
- *
|
||
|
- * GRUB is distributed in the hope that it will be useful,
|
||
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
- * GNU General Public License for more details.
|
||
|
- *
|
||
|
- * You should have received a copy of the GNU General Public License
|
||
|
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||
|
- */
|
||
|
-
|
||
|
-#include <grub/misc.h>
|
||
|
-#include <grub/command.h>
|
||
|
-#include <grub/err.h>
|
||
|
-#include <grub/dl.h>
|
||
|
-#include <grub/mm.h>
|
||
|
-#include <grub/term.h>
|
||
|
-#include <grub/backtrace.h>
|
||
|
-
|
||
|
-#define MAX_STACK_FRAME 102400
|
||
|
-
|
||
|
-void
|
||
|
-grub_backtrace_pointer (int frame)
|
||
|
-{
|
||
|
- while (1)
|
||
|
- {
|
||
|
- void *lp = __builtin_return_address (frame);
|
||
|
- if (!lp)
|
||
|
- break;
|
||
|
-
|
||
|
- lp = __builtin_extract_return_addr (lp);
|
||
|
-
|
||
|
- grub_printf ("%p: ", lp);
|
||
|
- grub_backtrace_print_address (lp);
|
||
|
- grub_printf (" (");
|
||
|
- for (i = 0; i < 2; i++)
|
||
|
- grub_printf ("%p,", ((void **)ptr) [i + 2]);
|
||
|
- grub_printf ("%p)\n", ((void **)ptr) [i + 2]);
|
||
|
- nptr = *(void **)ptr;
|
||
|
- if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME
|
||
|
- || nptr == ptr)
|
||
|
- {
|
||
|
- grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr);
|
||
|
- break;
|
||
|
- }
|
||
|
- ptr = nptr;
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-void
|
||
|
-grub_backtrace (void)
|
||
|
-{
|
||
|
- grub_backtrace_pointer (1);
|
||
|
-}
|
||
|
-
|
||
|
diff --git a/grub-core/lib/i386/backtrace.c b/grub-core/lib/i386/backtrace.c
|
||
|
deleted file mode 100644
|
||
|
index c67273db3..000000000
|
||
|
--- a/grub-core/lib/i386/backtrace.c
|
||
|
+++ /dev/null
|
||
|
@@ -1,78 +0,0 @@
|
||
|
-/*
|
||
|
- * GRUB -- GRand Unified Bootloader
|
||
|
- * Copyright (C) 2009 Free Software Foundation, Inc.
|
||
|
- *
|
||
|
- * GRUB is free software: you can redistribute it and/or modify
|
||
|
- * it under the terms of the GNU General Public License as published by
|
||
|
- * the Free Software Foundation, either version 3 of the License, or
|
||
|
- * (at your option) any later version.
|
||
|
- *
|
||
|
- * GRUB is distributed in the hope that it will be useful,
|
||
|
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
- * GNU General Public License for more details.
|
||
|
- *
|
||
|
- * You should have received a copy of the GNU General Public License
|
||
|
- * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
||
|
- */
|
||
|
-#include <config.h>
|
||
|
-#ifdef GRUB_UTIL
|
||
|
-#define REALLY_GRUB_UTIL GRUB_UTIL
|
||
|
-#undef GRUB_UTIL
|
||
|
-#endif
|
||
|
-
|
||
|
-#include <grub/symbol.h>
|
||
|
-#include <grub/dl.h>
|
||
|
-
|
||
|
-#ifdef REALLY_GRUB_UTIL
|
||
|
-#define GRUB_UTIL REALLY_GRUB_UTIL
|
||
|
-#undef REALLY_GRUB_UTIL
|
||
|
-#endif
|
||
|
-
|
||
|
-#include <grub/misc.h>
|
||
|
-#include <grub/command.h>
|
||
|
-#include <grub/err.h>
|
||
|
-#include <grub/mm.h>
|
||
|
-#include <grub/term.h>
|
||
|
-#include <grub/backtrace.h>
|
||
|
-
|
||
|
-#define MAX_STACK_FRAME 102400
|
||
|
-
|
||
|
-void
|
||
|
-grub_backtrace_pointer (void *ebp)
|
||
|
-{
|
||
|
- void *ptr, *nptr;
|
||
|
- unsigned i;
|
||
|
-
|
||
|
- ptr = ebp;
|
||
|
- while (1)
|
||
|
- {
|
||
|
- grub_printf ("%p: ", ptr);
|
||
|
- grub_backtrace_print_address (((void **) ptr)[1]);
|
||
|
- grub_printf (" (");
|
||
|
- for (i = 0; i < 2; i++)
|
||
|
- grub_printf ("%p,", ((void **)ptr) [i + 2]);
|
||
|
- grub_printf ("%p)\n", ((void **)ptr) [i + 2]);
|
||
|
- nptr = *(void **)ptr;
|
||
|
- if (nptr < ptr || (void **) nptr - (void **) ptr > MAX_STACK_FRAME
|
||
|
- || nptr == ptr)
|
||
|
- {
|
||
|
- grub_printf ("Invalid stack frame at %p (%p)\n", ptr, nptr);
|
||
|
- break;
|
||
|
- }
|
||
|
- ptr = nptr;
|
||
|
- }
|
||
|
-}
|
||
|
-
|
||
|
-void
|
||
|
-grub_backtrace (void)
|
||
|
-{
|
||
|
-#ifdef __x86_64__
|
||
|
- asm volatile ("movq %%rbp, %%rdi\n"
|
||
|
- "callq *%%rax": :"a"(grub_backtrace_pointer));
|
||
|
-#else
|
||
|
- asm volatile ("movl %%ebp, %%eax\n"
|
||
|
- "calll *%%ecx": :"c"(grub_backtrace_pointer));
|
||
|
-#endif
|
||
|
-}
|
||
|
-
|
||
|
diff --git a/include/grub/backtrace.h b/include/grub/backtrace.h
|
||
|
index 395519762..275cf85e2 100644
|
||
|
--- a/include/grub/backtrace.h
|
||
|
+++ b/include/grub/backtrace.h
|
||
|
@@ -19,8 +19,14 @@
|
||
|
#ifndef GRUB_BACKTRACE_HEADER
|
||
|
#define GRUB_BACKTRACE_HEADER 1
|
||
|
|
||
|
-void grub_backtrace (void);
|
||
|
-void grub_backtrace_pointer (void *ptr);
|
||
|
+#include <grub/symbol.h>
|
||
|
+#include <grub/types.h>
|
||
|
+
|
||
|
+void EXPORT_FUNC(grub_debug_backtrace) (const char * const debug,
|
||
|
+ unsigned int skip);
|
||
|
+void EXPORT_FUNC(grub_backtrace) (unsigned int skip);
|
||
|
+void grub_backtrace_arch (unsigned int skip);
|
||
|
+void grub_backtrace_pointer (void *ptr, unsigned int skip);
|
||
|
void grub_backtrace_print_address (void *addr);
|
||
|
|
||
|
#endif
|
||
|
diff --git a/include/grub/dl.h b/include/grub/dl.h
|
||
|
index b1ed3c333..7b5bfb07c 100644
|
||
|
--- a/include/grub/dl.h
|
||
|
+++ b/include/grub/dl.h
|
||
|
@@ -244,6 +244,8 @@ grub_dl_get (const char *name)
|
||
|
|
||
|
#endif
|
||
|
|
||
|
+void * EXPORT_FUNC(grub_resolve_symbol) (const char *name);
|
||
|
+const char * EXPORT_FUNC(grub_get_symbol_by_addr) (const void *addr, int isfunc);
|
||
|
grub_err_t grub_dl_register_symbol (const char *name, void *addr,
|
||
|
int isfunc, grub_dl_t mod);
|
||
|
|
||
|
diff --git a/include/grub/kernel.h b/include/grub/kernel.h
|
||
|
index ecd88ca72..ae69218af 100644
|
||
|
--- a/include/grub/kernel.h
|
||
|
+++ b/include/grub/kernel.h
|
||
|
@@ -108,6 +108,9 @@ grub_addr_t grub_modules_get_end (void);
|
||
|
|
||
|
#endif
|
||
|
|
||
|
+void EXPORT_FUNC(start) (void);
|
||
|
+void EXPORT_FUNC(_start) (void);
|
||
|
+
|
||
|
/* The start point of the C code. */
|
||
|
void grub_main (void) __attribute__ ((noreturn));
|
||
|
|
||
|
diff --git a/grub-core/kern/arm/efi/startup.S b/grub-core/kern/arm/efi/startup.S
|
||
|
index 9f8265315..f3bc41f9d 100644
|
||
|
--- a/grub-core/kern/arm/efi/startup.S
|
||
|
+++ b/grub-core/kern/arm/efi/startup.S
|
||
|
@@ -23,6 +23,8 @@
|
||
|
.file "startup.S"
|
||
|
.text
|
||
|
.arm
|
||
|
+ .globl start, _start
|
||
|
+FUNCTION(start)
|
||
|
FUNCTION(_start)
|
||
|
/*
|
||
|
* EFI_SYSTEM_TABLE and EFI_HANDLE are passed in r1/r0.
|
||
|
diff --git a/grub-core/kern/arm/startup.S b/grub-core/kern/arm/startup.S
|
||
|
index 3946fe8e1..5679a1d00 100644
|
||
|
--- a/grub-core/kern/arm/startup.S
|
||
|
+++ b/grub-core/kern/arm/startup.S
|
||
|
@@ -48,6 +48,8 @@
|
||
|
|
||
|
.text
|
||
|
.arm
|
||
|
+ .globl start, _start
|
||
|
+FUNCTION(start)
|
||
|
FUNCTION(_start)
|
||
|
b codestart
|
||
|
|
||
|
diff --git a/grub-core/kern/arm64/efi/startup.S b/grub-core/kern/arm64/efi/startup.S
|
||
|
index 666a7ee3c..41676bdb2 100644
|
||
|
--- a/grub-core/kern/arm64/efi/startup.S
|
||
|
+++ b/grub-core/kern/arm64/efi/startup.S
|
||
|
@@ -19,7 +19,9 @@
|
||
|
#include <grub/symbol.h>
|
||
|
|
||
|
.file "startup.S"
|
||
|
+ .globl start, _start
|
||
|
.text
|
||
|
+FUNCTION(start)
|
||
|
FUNCTION(_start)
|
||
|
/*
|
||
|
* EFI_SYSTEM_TABLE and EFI_HANDLE are passed in x1/x0.
|
||
|
diff --git a/grub-core/kern/i386/qemu/startup.S b/grub-core/kern/i386/qemu/startup.S
|
||
|
index 0d89858d9..939f182fc 100644
|
||
|
--- a/grub-core/kern/i386/qemu/startup.S
|
||
|
+++ b/grub-core/kern/i386/qemu/startup.S
|
||
|
@@ -24,7 +24,8 @@
|
||
|
|
||
|
.text
|
||
|
.code32
|
||
|
- .globl _start
|
||
|
+ .globl start, _start
|
||
|
+start:
|
||
|
_start:
|
||
|
jmp codestart
|
||
|
|
||
|
diff --git a/grub-core/kern/ia64/efi/startup.S b/grub-core/kern/ia64/efi/startup.S
|
||
|
index d75c6d7cc..8f2a593e5 100644
|
||
|
--- a/grub-core/kern/ia64/efi/startup.S
|
||
|
+++ b/grub-core/kern/ia64/efi/startup.S
|
||
|
@@ -24,8 +24,9 @@
|
||
|
.psr lsb
|
||
|
.lsb
|
||
|
|
||
|
- .global _start
|
||
|
+ .global start, _start
|
||
|
.proc _start
|
||
|
+start:
|
||
|
_start:
|
||
|
alloc loc0=ar.pfs,2,4,0,0
|
||
|
mov loc1=rp
|
||
|
diff --git a/grub-core/kern/sparc64/ieee1275/crt0.S b/grub-core/kern/sparc64/ieee1275/crt0.S
|
||
|
index 03b916f05..701bf63ab 100644
|
||
|
--- a/grub-core/kern/sparc64/ieee1275/crt0.S
|
||
|
+++ b/grub-core/kern/sparc64/ieee1275/crt0.S
|
||
|
@@ -22,7 +22,8 @@
|
||
|
|
||
|
.text
|
||
|
.align 4
|
||
|
- .globl _start
|
||
|
+ .globl start, _start
|
||
|
+start:
|
||
|
_start:
|
||
|
ba codestart
|
||
|
mov %o4, %o0
|
||
|
diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
|
||
|
index 0108c0d42..f36200bd6 100644
|
||
|
--- a/grub-core/Makefile.am
|
||
|
+++ b/grub-core/Makefile.am
|
||
|
@@ -66,6 +66,7 @@ CLEANFILES += grub_script.yy.c grub_script.yy.h
|
||
|
|
||
|
include $(srcdir)/Makefile.core.am
|
||
|
|
||
|
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/backtrace.h
|
||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/cache.h
|
||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/command.h
|
||
|
KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/device.h
|