module_no.c 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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. int apply_relocate(Elf32_Shdr *sechdrs,
  13. const char *strtab,
  14. unsigned int symindex,
  15. unsigned int relsec,
  16. struct module *me)
  17. {
  18. unsigned int i;
  19. Elf32_Rel *rel = (void *)sechdrs[relsec].sh_addr;
  20. Elf32_Sym *sym;
  21. uint32_t *location;
  22. DEBUGP("Applying relocate section %u to %u\n", relsec,
  23. sechdrs[relsec].sh_info);
  24. for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
  25. /* This is where to make the change */
  26. location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
  27. + rel[i].r_offset;
  28. /* This is the symbol it is referring to. Note that all
  29. undefined symbols have been resolved. */
  30. sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
  31. + ELF32_R_SYM(rel[i].r_info);
  32. switch (ELF32_R_TYPE(rel[i].r_info)) {
  33. case R_68K_32:
  34. /* We add the value into the location given */
  35. *location += sym->st_value;
  36. break;
  37. case R_68K_PC32:
  38. /* Add the value, subtract its postition */
  39. *location += sym->st_value - (uint32_t)location;
  40. break;
  41. default:
  42. printk(KERN_ERR "module %s: Unknown relocation: %u\n",
  43. me->name, ELF32_R_TYPE(rel[i].r_info));
  44. return -ENOEXEC;
  45. }
  46. }
  47. return 0;
  48. }
  49. int apply_relocate_add(Elf32_Shdr *sechdrs,
  50. const char *strtab,
  51. unsigned int symindex,
  52. unsigned int relsec,
  53. struct module *me)
  54. {
  55. unsigned int i;
  56. Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
  57. Elf32_Sym *sym;
  58. uint32_t *location;
  59. DEBUGP("Applying relocate_add section %u to %u\n", relsec,
  60. sechdrs[relsec].sh_info);
  61. for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
  62. /* This is where to make the change */
  63. location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
  64. + rel[i].r_offset;
  65. /* This is the symbol it is referring to. Note that all
  66. undefined symbols have been resolved. */
  67. sym = (Elf32_Sym *)sechdrs[symindex].sh_addr
  68. + ELF32_R_SYM(rel[i].r_info);
  69. switch (ELF32_R_TYPE(rel[i].r_info)) {
  70. case R_68K_32:
  71. /* We add the value into the location given */
  72. *location = rel[i].r_addend + sym->st_value;
  73. break;
  74. case R_68K_PC32:
  75. /* Add the value, subtract its postition */
  76. *location = rel[i].r_addend + sym->st_value - (uint32_t)location;
  77. break;
  78. default:
  79. printk(KERN_ERR "module %s: Unknown relocation: %u\n",
  80. me->name, ELF32_R_TYPE(rel[i].r_info));
  81. return -ENOEXEC;
  82. }
  83. }
  84. return 0;
  85. }