module.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2007-2009 Michal Simek <[email protected]>
  4. * Copyright (C) 2007-2009 PetaLogix
  5. */
  6. #include <linux/export.h>
  7. #include <linux/moduleloader.h>
  8. #include <linux/kernel.h>
  9. #include <linux/elf.h>
  10. #include <linux/vmalloc.h>
  11. #include <linux/fs.h>
  12. #include <linux/string.h>
  13. #include <linux/pgtable.h>
  14. #include <asm/cacheflush.h>
  15. int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
  16. unsigned int symindex, unsigned int relsec, struct module *module)
  17. {
  18. unsigned int i;
  19. Elf32_Rela *rela = (void *)sechdrs[relsec].sh_addr;
  20. Elf32_Sym *sym;
  21. unsigned long int *location;
  22. unsigned long int value;
  23. pr_debug("Applying add relocation section %u to %u\n",
  24. relsec, sechdrs[relsec].sh_info);
  25. for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rela); i++) {
  26. location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr +
  27. rela[i].r_offset;
  28. sym = (Elf32_Sym *)sechdrs[symindex].sh_addr +
  29. ELF32_R_SYM(rela[i].r_info);
  30. value = sym->st_value + rela[i].r_addend;
  31. switch (ELF32_R_TYPE(rela[i].r_info)) {
  32. /*
  33. * Be careful! mb-gcc / mb-ld splits the relocs between the
  34. * text and the reloc table. In general this means we must
  35. * read the current contents of (*location), add any offset
  36. * then store the result back in
  37. */
  38. case R_MICROBLAZE_32:
  39. *location = value;
  40. break;
  41. case R_MICROBLAZE_64:
  42. location[0] = (location[0] & 0xFFFF0000) |
  43. (value >> 16);
  44. location[1] = (location[1] & 0xFFFF0000) |
  45. (value & 0xFFFF);
  46. break;
  47. case R_MICROBLAZE_64_PCREL:
  48. value -= (unsigned long int)(location) + 4;
  49. location[0] = (location[0] & 0xFFFF0000) |
  50. (value >> 16);
  51. location[1] = (location[1] & 0xFFFF0000) |
  52. (value & 0xFFFF);
  53. pr_debug("R_MICROBLAZE_64_PCREL (%08lx)\n",
  54. value);
  55. break;
  56. case R_MICROBLAZE_32_PCREL_LO:
  57. pr_debug("R_MICROBLAZE_32_PCREL_LO\n");
  58. break;
  59. case R_MICROBLAZE_64_NONE:
  60. pr_debug("R_MICROBLAZE_64_NONE\n");
  61. break;
  62. case R_MICROBLAZE_NONE:
  63. pr_debug("R_MICROBLAZE_NONE\n");
  64. break;
  65. default:
  66. pr_err("module %s: Unknown relocation: %u\n",
  67. module->name,
  68. ELF32_R_TYPE(rela[i].r_info));
  69. return -ENOEXEC;
  70. }
  71. }
  72. return 0;
  73. }
  74. int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
  75. struct module *module)
  76. {
  77. flush_dcache();
  78. return 0;
  79. }