aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/dwarf.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2009-10-13 13:32:19 +0900
committerPaul Mundt <lethal@linux-sh.org>2009-10-13 13:32:19 +0900
commit5a3abba77dc0eb0b00332c21899123cdfa3b19e5 (patch)
treecb0b52bcb90f5c680faba380a0832203bdad2fed /arch/sh/kernel/dwarf.c
parentsh: Generalize CALLER_ADDRx support. (diff)
downloadlinux-dev-5a3abba77dc0eb0b00332c21899123cdfa3b19e5.tar.xz
linux-dev-5a3abba77dc0eb0b00332c21899123cdfa3b19e5.zip
sh: Tidy up the dwarf module helpers.
This enables us to build the dwarf unwinder both with modules enabled and disabled in addition to reducing code size in the latter case. The helpers are also consolidated, and modified to resemble the BUG module helpers. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/dwarf.c')
-rw-r--r--arch/sh/kernel/dwarf.c43
1 files changed, 39 insertions, 4 deletions
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index c274039e9c8d..718286be6648 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -20,6 +20,7 @@
#include <linux/list.h>
#include <linux/mempool.h>
#include <linux/mm.h>
+#include <linux/elf.h>
#include <asm/dwarf.h>
#include <asm/unwinder.h>
#include <asm/sections.h>
@@ -895,8 +896,8 @@ static void dwarf_unwinder_cleanup(void)
*
* Parse the information in a .eh_frame section.
*/
-int dwarf_parse_section(char *eh_frame_start, char *eh_frame_end,
- struct module *mod)
+static int dwarf_parse_section(char *eh_frame_start, char *eh_frame_end,
+ struct module *mod)
{
u32 entry_type;
void *p, *entry;
@@ -959,14 +960,47 @@ out:
return err;
}
+#ifdef CONFIG_MODULES
+int module_dwarf_finalize(const Elf_Ehdr *hdr, const Elf_Shdr *sechdrs,
+ struct module *me)
+{
+ unsigned int i, err;
+ unsigned long start, end;
+ char *secstrings = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
+
+ start = end = 0;
+
+ for (i = 1; i < hdr->e_shnum; i++) {
+ /* Alloc bit cleared means "ignore it." */
+ if ((sechdrs[i].sh_flags & SHF_ALLOC)
+ && !strcmp(secstrings+sechdrs[i].sh_name, ".eh_frame")) {
+ start = sechdrs[i].sh_addr;
+ end = start + sechdrs[i].sh_size;
+ break;
+ }
+ }
+
+ /* Did we find the .eh_frame section? */
+ if (i != hdr->e_shnum) {
+ err = dwarf_parse_section((char *)start, (char *)end, me);
+ if (err) {
+ printk(KERN_WARNING "%s: failed to parse DWARF info\n",
+ me->name);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
/**
- * dwarf_module_unload - remove FDE/CIEs associated with @mod
+ * module_dwarf_cleanup - remove FDE/CIEs associated with @mod
* @mod: the module that is being unloaded
*
* Remove any FDEs and CIEs from the global lists that came from
* @mod's .eh_frame section because @mod is being unloaded.
*/
-void dwarf_module_unload(struct module *mod)
+void module_dwarf_cleanup(struct module *mod)
{
struct dwarf_fde *fde;
struct dwarf_cie *cie;
@@ -1004,6 +1038,7 @@ again_fde:
spin_unlock_irqrestore(&dwarf_fde_lock, flags);
}
+#endif /* CONFIG_MODULES */
/**
* dwarf_unwinder_init - initialise the dwarf unwinder