module.h 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. /* SPDX-License-Identifier: GPL-2.0 */
  2. /*
  3. * Copyright (C) 2020-2022 Loongson Technology Corporation Limited
  4. */
  5. #ifndef _ASM_MODULE_H
  6. #define _ASM_MODULE_H
  7. #include <asm/inst.h>
  8. #include <asm-generic/module.h>
  9. #define RELA_STACK_DEPTH 16
  10. struct mod_section {
  11. Elf_Shdr *shdr;
  12. int num_entries;
  13. int max_entries;
  14. };
  15. struct mod_arch_specific {
  16. struct mod_section got;
  17. struct mod_section plt;
  18. struct mod_section plt_idx;
  19. };
  20. struct got_entry {
  21. Elf_Addr symbol_addr;
  22. };
  23. struct plt_entry {
  24. u32 inst_lu12iw;
  25. u32 inst_lu32id;
  26. u32 inst_lu52id;
  27. u32 inst_jirl;
  28. };
  29. struct plt_idx_entry {
  30. Elf_Addr symbol_addr;
  31. };
  32. Elf_Addr module_emit_got_entry(struct module *mod, Elf_Addr val);
  33. Elf_Addr module_emit_plt_entry(struct module *mod, Elf_Addr val);
  34. static inline struct got_entry emit_got_entry(Elf_Addr val)
  35. {
  36. return (struct got_entry) { val };
  37. }
  38. static inline struct plt_entry emit_plt_entry(unsigned long val)
  39. {
  40. u32 lu12iw, lu32id, lu52id, jirl;
  41. lu12iw = (lu12iw_op << 25 | (((val >> 12) & 0xfffff) << 5) | LOONGARCH_GPR_T1);
  42. lu32id = larch_insn_gen_lu32id(LOONGARCH_GPR_T1, ADDR_IMM(val, LU32ID));
  43. lu52id = larch_insn_gen_lu52id(LOONGARCH_GPR_T1, LOONGARCH_GPR_T1, ADDR_IMM(val, LU52ID));
  44. jirl = larch_insn_gen_jirl(0, LOONGARCH_GPR_T1, 0, (val & 0xfff));
  45. return (struct plt_entry) { lu12iw, lu32id, lu52id, jirl };
  46. }
  47. static inline struct plt_idx_entry emit_plt_idx_entry(unsigned long val)
  48. {
  49. return (struct plt_idx_entry) { val };
  50. }
  51. static inline int get_plt_idx(unsigned long val, const struct mod_section *sec)
  52. {
  53. int i;
  54. struct plt_idx_entry *plt_idx = (struct plt_idx_entry *)sec->shdr->sh_addr;
  55. for (i = 0; i < sec->num_entries; i++) {
  56. if (plt_idx[i].symbol_addr == val)
  57. return i;
  58. }
  59. return -1;
  60. }
  61. static inline struct plt_entry *get_plt_entry(unsigned long val,
  62. const struct mod_section *sec_plt,
  63. const struct mod_section *sec_plt_idx)
  64. {
  65. int plt_idx = get_plt_idx(val, sec_plt_idx);
  66. struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr;
  67. if (plt_idx < 0)
  68. return NULL;
  69. return plt + plt_idx;
  70. }
  71. static inline struct got_entry *get_got_entry(Elf_Addr val,
  72. const struct mod_section *sec)
  73. {
  74. struct got_entry *got = (struct got_entry *)sec->shdr->sh_addr;
  75. int i;
  76. for (i = 0; i < sec->num_entries; i++)
  77. if (got[i].symbol_addr == val)
  78. return &got[i];
  79. return NULL;
  80. }
  81. #endif /* _ASM_MODULE_H */