sh: Fix memory leak in dwarf_unwind_stack()
authorMatt Fleming <matt@console-pimps.org>
Sat, 10 Oct 2009 15:03:11 +0000 (16:03 +0100)
committerMatt Fleming <matt@console-pimps.org>
Sun, 11 Oct 2009 16:12:28 +0000 (17:12 +0100)
If we broke out of the while (1) loop because the return address of
"frame" was zero, then "frame" needs to be free'd before we return.

Signed-off-by: Matt Fleming <matt@console-pimps.org>
arch/sh/include/asm/dwarf.h
arch/sh/kernel/dwarf.c

index aacdc74..eef8753 100644 (file)
@@ -376,6 +376,7 @@ static inline unsigned int DW_CFA_operand(unsigned long insn)
 
 extern struct dwarf_frame *dwarf_unwind_stack(unsigned long,
                                              struct dwarf_frame *);
+extern void dwarf_free_frame(struct dwarf_frame *);
 extern int dwarf_parse_section(char *, char *, struct module *);
 extern void dwarf_module_unload(struct module *);
 
index 981315c..ce8bff4 100644 (file)
@@ -530,6 +530,16 @@ static int dwarf_cfa_execute_insns(unsigned char *insn_start,
 }
 
 /**
+ *     dwarf_free_frame - free the memory allocated for @frame
+ *     @frame: the frame to free
+ */
+void dwarf_free_frame(struct dwarf_frame *frame)
+{
+       dwarf_frame_free_regs(frame);
+       mempool_free(frame, dwarf_frame_pool);
+}
+
+/**
  *     dwarf_unwind_stack - recursively unwind the stack
  *     @pc: address of the function to unwind
  *     @prev: struct dwarf_frame of the previous stackframe on the callstack
@@ -649,8 +659,7 @@ struct dwarf_frame * dwarf_unwind_stack(unsigned long pc,
        return frame;
 
 bail:
-       dwarf_frame_free_regs(frame);
-       mempool_free(frame, dwarf_frame_pool);
+       dwarf_free_frame(frame);
        return NULL;
 }
 
@@ -837,10 +846,8 @@ static void dwarf_unwinder_dump(struct task_struct *task,
        while (1) {
                frame = dwarf_unwind_stack(return_addr, _frame);
 
-               if (_frame) {
-                       dwarf_frame_free_regs(_frame);
-                       mempool_free(_frame, dwarf_frame_pool);
-               }
+               if (_frame)
+                       dwarf_free_frame(_frame);
 
                _frame = frame;
 
@@ -850,6 +857,9 @@ static void dwarf_unwinder_dump(struct task_struct *task,
                return_addr = frame->return_addr;
                ops->address(data, return_addr, 1);
        }
+
+       if (frame)
+               dwarf_free_frame(frame);
 }
 
 static struct unwinder dwarf_unwinder = {