aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel/dwarf.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/dwarf.c')
-rw-r--r--arch/sh/kernel/dwarf.c42
1 files changed, 26 insertions, 16 deletions
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index a8234b2010d..67a049e75ec 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -22,6 +22,7 @@
#include <linux/mm.h>
#include <linux/elf.h>
#include <linux/ftrace.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <asm/dwarf.h>
#include <asm/unwinder.h>
@@ -48,6 +49,8 @@ static DEFINE_SPINLOCK(dwarf_fde_lock);
static struct dwarf_cie *cached_cie;
+static unsigned int dwarf_unwinder_ready;
+
/**
* dwarf_frame_alloc_reg - allocate memory for a DWARF register
* @frame: the DWARF frame whose list of registers we insert on
@@ -581,6 +584,13 @@ struct dwarf_frame *dwarf_unwind_stack(unsigned long pc,
unsigned long addr;
/*
+ * If we've been called in to before initialization has
+ * completed, bail out immediately.
+ */
+ if (!dwarf_unwinder_ready)
+ return NULL;
+
+ /*
* If we're starting at the top of the stack we need get the
* contents of a physical register to get the CFA in order to
* begin the virtual unwinding of the stack.
@@ -844,8 +854,10 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
rb_link_node(&cie->node, parent, rb_node);
rb_insert_color(&cie->node, &cie_root);
+#ifdef CONFIG_MODULES
if (mod != NULL)
list_add_tail(&cie->link, &mod->arch.cie_list);
+#endif
spin_unlock_irqrestore(&dwarf_cie_lock, flags);
@@ -934,8 +946,10 @@ static int dwarf_parse_fde(void *entry, u32 entry_type,
rb_link_node(&fde->node, parent, rb_node);
rb_insert_color(&fde->node, &fde_root);
+#ifdef CONFIG_MODULES
if (mod != NULL)
list_add_tail(&fde->link, &mod->arch.fde_list);
+#endif
spin_unlock_irqrestore(&dwarf_fde_lock, flags);
@@ -981,29 +995,19 @@ static struct unwinder dwarf_unwinder = {
static void dwarf_unwinder_cleanup(void)
{
- struct rb_node **fde_rb_node = &fde_root.rb_node;
- struct rb_node **cie_rb_node = &cie_root.rb_node;
+ struct dwarf_fde *fde, *next_fde;
+ struct dwarf_cie *cie, *next_cie;
/*
* Deallocate all the memory allocated for the DWARF unwinder.
* Traverse all the FDE/CIE lists and remove and free all the
* memory associated with those data structures.
*/
- while (*fde_rb_node) {
- struct dwarf_fde *fde;
-
- fde = rb_entry(*fde_rb_node, struct dwarf_fde, node);
- rb_erase(*fde_rb_node, &fde_root);
+ rbtree_postorder_for_each_entry_safe(fde, next_fde, &fde_root, node)
kfree(fde);
- }
- while (*cie_rb_node) {
- struct dwarf_cie *cie;
-
- cie = rb_entry(*cie_rb_node, struct dwarf_cie, node);
- rb_erase(*cie_rb_node, &cie_root);
+ rbtree_postorder_for_each_entry_safe(cie, next_cie, &cie_root, node)
kfree(cie);
- }
kmem_cache_destroy(dwarf_reg_cachep);
kmem_cache_destroy(dwarf_frame_cachep);
@@ -1162,7 +1166,7 @@ void module_dwarf_cleanup(struct module *mod)
*/
static int __init dwarf_unwinder_init(void)
{
- int err;
+ int err = -ENOMEM;
dwarf_frame_cachep = kmem_cache_create("dwarf_frames",
sizeof(struct dwarf_frame), 0,
@@ -1176,11 +1180,15 @@ static int __init dwarf_unwinder_init(void)
mempool_alloc_slab,
mempool_free_slab,
dwarf_frame_cachep);
+ if (!dwarf_frame_pool)
+ goto out;
dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ,
mempool_alloc_slab,
mempool_free_slab,
dwarf_reg_cachep);
+ if (!dwarf_reg_pool)
+ goto out;
err = dwarf_parse_section(__start_eh_frame, __stop_eh_frame, NULL);
if (err)
@@ -1190,11 +1198,13 @@ static int __init dwarf_unwinder_init(void)
if (err)
goto out;
+ dwarf_unwinder_ready = 1;
+
return 0;
out:
printk(KERN_ERR "Failed to initialise DWARF unwinder: %d\n", err);
dwarf_unwinder_cleanup();
- return -EINVAL;
+ return err;
}
early_initcall(dwarf_unwinder_init);