diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-28 14:03:14 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-03-28 14:03:14 -0700 | 
| commit | 0fe41b8982001cd14ee2c77cd776735a5024e98b (patch) | |
| tree | 83e65d595c413d55259ea14fb97748ce5efe5707 /arch/arm/kernel/module.c | |
| parent | eedf2c5296a8dfaaf9aec1a938c1d3bd73159a30 (diff) | |
| parent | 9759d22c8348343b0da4e25d6150c41712686c14 (diff) | |
Merge branch 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm
* 'devel' of master.kernel.org:/home/rmk/linux-2.6-arm: (422 commits)
  [ARM] 5435/1: fix compile warning in sanity_check_meminfo()
  [ARM] 5434/1: ARM: OMAP: Fix mailbox compile for 24xx
  [ARM] pxa: fix the bad assumption that PCMCIA sockets always start with 0
  [ARM] pxa: fix Colibri PXA300 and PXA320 LCD backlight pins
  imxfb: Fix TFT mode
  i.MX21/27: remove ifdef CONFIG_FB_IMX
  imxfb: add clock support
  mxc: add arch_reset() function
  clkdev: add possibility to get a clock based on the device name
  i.MX1: remove fb support from mach-imx
  [ARM] pxa: build arch/arm/plat-pxa/mfp.c only when PXA3xx or ARCH_MMP defined
  Gemini: Add support for Teltonika RUT100
  Gemini: gpiolib based GPIO support v2
  MAINTAINERS: add myself as Gemini architecture maintainer
  ARM: Add Gemini architecture v3
  [ARM] OMAP: Fix compile for omap2_init_common_hw()
  MAINTAINERS: Add myself as Faraday ARM core variant maintainer
  ARM: Add support for FA526 v2
  [ARM] acorn,ebsa110,footbridge,integrator,sa1100: Convert asm/io.h to linux/io.h
  [ARM] collie: fix two minor formatting nits
  ...
Diffstat (limited to 'arch/arm/kernel/module.c')
| -rw-r--r-- | arch/arm/kernel/module.c | 73 | 
1 files changed, 73 insertions, 0 deletions
| diff --git a/arch/arm/kernel/module.c b/arch/arm/kernel/module.c index dab48f27263f..d1731e39b496 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,20 @@ apply_relocate(Elf32_Shdr *sechdrs, const char *strtab, unsigned int symindex,  			*(u32 *)loc |= offset & 0x00ffffff;  			break; +	       case R_ARM_V4BX: +		       /* Preserve Rm and the condition code. Alter +			* other bits to re-code instruction as +			* MOV PC,Rm. +			*/ +		       *(u32 *)loc &= 0xf000000f; +		       *(u32 *)loc |= 0x01a0f000; +		       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 +187,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);  } | 
