module.c 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #include <linux/moduleloader.h>
  2. #include <linux/elf.h>
  3. #include <linux/vmalloc.h>
  4. #include <linux/fs.h>
  5. #include <linux/string.h>
  6. #include <linux/kernel.h>
  7. #if 0
  8. #define DEBUGP printk
  9. #else
  10. #define DEBUGP(fmt...)
  11. #endif
  12. void *module_alloc(unsigned long size)
  13. {
  14. if (size == 0)
  15. return NULL;
  16. return vmalloc(size);
  17. }
  18. /* Free memory returned from module_alloc */
  19. void module_free(struct module *mod, void *module_region)
  20. {
  21. vfree(module_region);
  22. /* FIXME: If module_region == mod->init_region, trim exception
  23. table entries. */
  24. }
  25. /* We don't need anything special. */
  26. int module_frob_arch_sections(Elf_Ehdr *hdr,
  27. Elf_Shdr *sechdrs,
  28. char *secstrings,
  29. struct module *mod)
  30. {
  31. return 0;
  32. }
  33. int apply_relocate(Elf32_Shdr *sechdrs,
  34. const char *strtab,
  35. unsigned int symindex,
  36. unsigned int relsec,
  37. struct module *me)
  38. {
  39. printk(KERN_ERR "module %s: RELOCATION unsupported\n",
  40. me->name);
  41. return -ENOEXEC;
  42. }
  43. int apply_relocate_add(Elf32_Shdr *sechdrs,
  44. const char *strtab,
  45. unsigned int symindex,
  46. unsigned int relsec,
  47. struct module *me)
  48. {
  49. unsigned int i;
  50. Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
  51. DEBUGP("Applying relocate section %u to %u\n", relsec,
  52. sechdrs[relsec].sh_info);
  53. for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
  54. /* This is where to make the change */
  55. uint32_t *loc = (uint32_t *)(sechdrs[sechdrs[relsec].sh_info].sh_addr
  56. + rela[i].r_offset);
  57. /* This is the symbol it is referring to. Note that all
  58. undefined symbols have been resolved. */
  59. Elf32_Sym *sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
  60. + ELF32_R_SYM(rela[i].r_info);
  61. uint32_t v = sym->st_value + rela[i].r_addend;
  62. switch (ELF32_R_TYPE(rela[i].r_info)) {
  63. case R_H8_DIR24R8:
  64. loc = (uint32_t *)((uint32_t)loc - 1);
  65. *loc = (*loc & 0xff000000) | ((*loc & 0xffffff) + v);
  66. break;
  67. case R_H8_DIR24A8:
  68. if (ELF32_R_SYM(rela[i].r_info))
  69. *loc += v;
  70. break;
  71. case R_H8_DIR32:
  72. case R_H8_DIR32A16:
  73. *loc += v;
  74. break;
  75. case R_H8_PCREL16:
  76. v -= (unsigned long)loc + 2;
  77. if ((Elf32_Sword)v > 0x7fff ||
  78. (Elf32_Sword)v < -(Elf32_Sword)0x8000)
  79. goto overflow;
  80. else
  81. *(unsigned short *)loc = v;
  82. break;
  83. case R_H8_PCREL8:
  84. v -= (unsigned long)loc + 1;
  85. if ((Elf32_Sword)v > 0x7f ||
  86. (Elf32_Sword)v < -(Elf32_Sword)0x80)
  87. goto overflow;
  88. else
  89. *(unsigned char *)loc = v;
  90. break;
  91. default:
  92. printk(KERN_ERR "module %s: Unknown relocation: %u\n",
  93. me->name, ELF32_R_TYPE(rela[i].r_info));
  94. return -ENOEXEC;
  95. }
  96. }
  97. return 0;
  98. overflow:
  99. printk(KERN_ERR "module %s: relocation offset overflow: %08x\n",
  100. me->name, rela[i].r_offset);
  101. return -ENOEXEC;
  102. }
  103. int module_finalize(const Elf_Ehdr *hdr,
  104. const Elf_Shdr *sechdrs,
  105. struct module *me)
  106. {
  107. return 0;
  108. }
  109. void module_arch_cleanup(struct module *mod)
  110. {
  111. }