[ARM] 5384/1: unwind: Add stack unwinding support for loadable modules

Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]
From: Linux Kernel Mailing List
Date: Saturday, March 28, 2009 - 3:01 pm

Gitweb:     http://git.kernel.org/linus/2e1926e7b5d39eb31880152d636e8d8d011888cb
Commit:     2e1926e7b5d39eb31880152d636e8d8d011888cb
Parent:     bff595c15c92b9c5c8f3d32edefcef6c3cbdd59f
Author:     Catalin Marinas <catalin.marinas@arm.com>
AuthorDate: Wed Feb 11 13:09:54 2009 +0100
Committer:  Russell King <rmk+kernel@arm.linux.org.uk>
CommitDate: Thu Feb 19 11:27:19 2009 +0000

    [ARM] 5384/1: unwind: Add stack unwinding support for loadable modules
    
    This patch adds ELF section parsing for the unwinding tables in loadable
    modules together with the PREL31 relocation symbol resolving.
    
    Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
    Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
 arch/arm/include/asm/elf.h    |    1 +
 arch/arm/include/asm/module.h |   22 +++++++++++---
 arch/arm/kernel/module.c      |   64 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 82 insertions(+), 5 deletions(-)

diff --git a/arch/arm/include/asm/elf.h b/arch/arm/include/asm/elf.h
index a58378c..def8eac 100644
--- a/arch/arm/include/asm/elf.h
+++ b/arch/arm/include/asm/elf.h
@@ -50,6 +50,7 @@ typedef struct user_fp elf_fpregset_t;
 #define R_ARM_ABS32	2
 #define R_ARM_CALL	28
 #define R_ARM_JUMP24	29
+#define R_ARM_PREL31	42
 
 /*
  * These are used to set parameters in the core dumps.
diff --git a/arch/arm/include/asm/module.h b/arch/arm/include/asm/module.h
index 24b168d..e4dfa69 100644
--- a/arch/arm/include/asm/module.h
+++ b/arch/arm/include/asm/module.h
@@ -1,15 +1,27 @@
 #ifndef _ASM_ARM_MODULE_H
 #define _ASM_ARM_MODULE_H
 
-struct mod_arch_specific
-{
-	int foo;
-};
-
 #define Elf_Shdr	Elf32_Shdr
 #define Elf_Sym		Elf32_Sym
 #define Elf_Ehdr	Elf32_Ehdr
 
+struct unwind_table;
+
+struct mod_arch_specific
+{
+#ifdef CONFIG_ARM_UNWIND
+	Elf_Shdr *unw_sec_init;
+	Elf_Shdr *unw_sec_devinit;
+	Elf_Shdr *unw_sec_core;
+	Elf_Shdr *sec_init_text;
+	Elf_Shdr *sec_devinit_text;
+	Elf_Shdr *sec_core_text;
+	struct unwind_table *unwind_init;
+	struct unwind_table *unwind_devinit;
+	struct unwind_table *unwind_core;
+#endif
+};
+
 /*
  * Include the ARM architecture version.
  */
diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c
index dab48f2..13dbd5b 100644
--- a/arch/arm/kernel/module.c
+++ b/arch/arm/kernel/module.c
@@ -22,6 +22,7 @@
 
 #include <asm/pgtable.h>
 #include <asm/sections.h>
+#include <asm/unwind.h>
 
 #ifdef CONFIG_XIP_KERNEL
 /*
@@ -66,6 +67,24 @@ int module_frob_arch_sections(Elf_Ehdr *hdr,
 			      char *secstrings,
 			      struct module *mod)
 {
+#ifdef CONFIG_ARM_UNWIND
+	Elf_Shdr *s, *sechdrs_end = sechdrs + hdr->e_shnum;
+
+	for (s = sechdrs; s < sechdrs_end; s++) {
+		if (strcmp(".ARM.exidx.init.text", secstrings + s->sh_name) == 0)
+			mod->arch.unw_sec_init = s;
+		else if (strcmp(".ARM.exidx.devinit.text", secstrings + s->sh_name) == 0)
+			mod->arch.unw_sec_devinit = s;
+		else if (strcmp(".ARM.exidx", secstrings + s->sh_name) == 0)
+			mod->arch.unw_sec_core = s;
+		else if (strcmp(".init.text", secstrings + s->sh_name) == 0)
+			mod->arch.sec_init_text = s;
+		else if (strcmp(".devinit.text", secstrings + s->sh_name) == 0)
+			mod->arch.sec_devinit_text = s;
+		else if (strcmp(".text", secstrings + s->sh_name) == 0)
+			mod->arch.sec_core_text = s;
+	}
+#endif
 	return 0;
 }
 
@@ -104,6 +123,10 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 		loc = dstsec->sh_addr + rel->r_offset;
 
 		switch (ELF32_R_TYPE(rel->r_info)) {
+		case R_ARM_NONE:
+			/* ignore */
+			break;
+
 		case R_ARM_ABS32:
 			*(u32 *)loc += sym->st_value;
 			break;
@@ -132,6 +155,11 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,
 			*(u32 *)loc |= offset & 0x00ffffff;
 			break;
 
+		case R_ARM_PREL31:
+			offset = *(u32 *)loc + sym->st_value - loc;
+			*(u32 *)loc = offset & 0x7fffffff;
+			break;
+
 		default:
 			printk(KERN_ERR "%s: unknown relocation: %u\n",
 			       module->name, ELF32_R_TYPE(rel->r_info));
@@ -150,14 +178,50 @@ apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
 	return -ENOEXEC;
 }
 
+#ifdef CONFIG_ARM_UNWIND
+static void register_unwind_tables(struct module *mod)
+{
+	if (mod->arch.unw_sec_init && mod->arch.sec_init_text)
+		mod->arch.unwind_init =
+			unwind_table_add(mod->arch.unw_sec_init->sh_addr,
+					 mod->arch.unw_sec_init->sh_size,
+					 mod->arch.sec_init_text->sh_addr,
+					 mod->arch.sec_init_text->sh_size);
+	if (mod->arch.unw_sec_devinit && mod->arch.sec_devinit_text)
+		mod->arch.unwind_devinit =
+			unwind_table_add(mod->arch.unw_sec_devinit->sh_addr,
+					 mod->arch.unw_sec_devinit->sh_size,
+					 mod->arch.sec_devinit_text->sh_addr,
+					 mod->arch.sec_devinit_text->sh_size);
+	if (mod->arch.unw_sec_core && mod->arch.sec_core_text)
+		mod->arch.unwind_core =
+			unwind_table_add(mod->arch.unw_sec_core->sh_addr,
+					 mod->arch.unw_sec_core->sh_size,
+					 mod->arch.sec_core_text->sh_addr,
+					 mod->arch.sec_core_text->sh_size);
+}
+
+static void unregister_unwind_tables(struct module *mod)
+{
+	unwind_table_del(mod->arch.unwind_init);
+	unwind_table_del(mod->arch.unwind_devinit);
+	unwind_table_del(mod->arch.unwind_core);
+}
+#else
+static inline void register_unwind_tables(struct module *mod) { }
+static inline void unregister_unwind_tables(struct module *mod) { }
+#endif
+
 int
 module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 		struct module *module)
 {
+	register_unwind_tables(module);
 	return 0;
 }
 
 void
 module_arch_cleanup(struct module *mod)
 {
+	unregister_unwind_tables(mod);
 }
--
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Previous message: [thread] [date] [author]
Next message: [thread] [date] [author]

Messages in current thread:
[ARM] 5384/1: unwind: Add stack unwinding support for load ..., Linux Kernel Mailing ..., (Sat Mar 28, 3:01 pm)