reloc_ia64.S 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /* reloc_ia64.S - position independent IA-64 ELF shared object relocator
  2. Copyright (C) 1999 Hewlett-Packard Co.
  3. Contributed by David Mosberger <davidm@hpl.hp.com>.
  4. All rights reserved.
  5. Redistribution and use in source and binary forms, with or without
  6. modification, are permitted provided that the following conditions
  7. are met:
  8. * Redistributions of source code must retain the above copyright
  9. notice, this list of conditions and the following disclaimer.
  10. * Redistributions in binary form must reproduce the above
  11. copyright notice, this list of conditions and the following
  12. disclaimer in the documentation and/or other materials
  13. provided with the distribution.
  14. * Neither the name of Hewlett-Packard Co. nor the names of its
  15. contributors may be used to endorse or promote products derived
  16. from this software without specific prior written permission.
  17. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  18. CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  19. INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  20. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
  22. BE LIABLE FOR ANYDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  23. OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  24. PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
  25. PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  26. THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
  27. TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
  28. THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  29. SUCH DAMAGE.
  30. */
  31. /*
  32. * This is written in assembly because the entire code needs to be position
  33. * independent. Note that the compiler does not generate code that's position
  34. * independent by itself because it relies on the global offset table being
  35. * relocated.
  36. */
  37. .text
  38. .psr abi64
  39. .psr lsb
  40. .lsb
  41. /*
  42. * This constant determines how many R_IA64_FPTR64LSB relocations we
  43. * can deal with. If you get EFI_BUFFER_TOO_SMALL errors, you may
  44. * need to increase this number.
  45. */
  46. #define MAX_FUNCTION_DESCRIPTORS 750
  47. #define ST_VALUE_OFF 8 /* offset of st_value in elf sym */
  48. #define EFI_SUCCESS 0
  49. #define EFI_LOAD_ERROR 1
  50. #define EFI_BUFFER_TOO_SMALL 5
  51. #define DT_NULL 0 /* Marks end of dynamic section */
  52. #define DT_RELA 7 /* Address of Rela relocs */
  53. #define DT_RELASZ 8 /* Total size of Rela relocs */
  54. #define DT_RELAENT 9 /* Size of one Rela reloc */
  55. #define DT_SYMTAB 6 /* Address of symbol table */
  56. #define DT_SYMENT 11 /* Size of one symbol table entry */
  57. #define R_IA64_NONE 0
  58. #define R_IA64_REL64MSB 0x6e
  59. #define R_IA64_REL64LSB 0x6f
  60. #define R_IA64_DIR64MSB 0x26
  61. #define R_IA64_DIR64LSB 0x27
  62. #define R_IA64_FPTR64MSB 0x46
  63. #define R_IA64_FPTR64LSB 0x47
  64. #define ldbase in0 /* load address (address of .text) */
  65. #define dyn in1 /* address of _DYNAMIC */
  66. #define d_tag r16
  67. #define d_val r17
  68. #define rela r18
  69. #define relasz r19
  70. #define relaent r20
  71. #define addr r21
  72. #define r_info r22
  73. #define r_offset r23
  74. #define r_addend r24
  75. #define r_type r25
  76. #define r_sym r25 /* alias of r_type ! */
  77. #define fptr r26
  78. #define fptr_limit r27
  79. #define symtab f8
  80. #define syment f9
  81. #define ftmp f10
  82. #define target r16
  83. #define val r17
  84. #define NLOC 0
  85. #define Pnull p6
  86. #define Prela p7
  87. #define Prelasz p8
  88. #define Prelaent p9
  89. #define Psymtab p10
  90. #define Psyment p11
  91. #define Pnone p6
  92. #define Prel p7
  93. #define Pfptr p8
  94. #define Pmore p6
  95. #define Poom p6 /* out-of-memory */
  96. .global _relocate
  97. .proc _relocate
  98. _relocate:
  99. alloc r2=ar.pfs,2,0,0,0
  100. movl fptr = @gprel(fptr_mem_base)
  101. ;;
  102. add fptr = fptr, gp
  103. movl fptr_limit = @gprel(fptr_mem_limit)
  104. ;;
  105. add fptr_limit = fptr_limit, gp
  106. search_dynamic:
  107. ld8 d_tag = [dyn],8
  108. ;;
  109. ld8 d_val = [dyn],8
  110. cmp.eq Pnull,p0 = DT_NULL,d_tag
  111. (Pnull) br.cond.sptk.few apply_relocs
  112. cmp.eq Prela,p0 = DT_RELA,d_tag
  113. cmp.eq Prelasz,p0 = DT_RELASZ,d_tag
  114. cmp.eq Psymtab,p0 = DT_SYMTAB,d_tag
  115. cmp.eq Psyment,p0 = DT_SYMENT,d_tag
  116. cmp.eq Prelaent,p0 = DT_RELAENT,d_tag
  117. ;;
  118. (Prela) add rela = d_val, ldbase
  119. (Prelasz) mov relasz = d_val
  120. (Prelaent) mov relaent = d_val
  121. (Psymtab) add val = d_val, ldbase
  122. ;;
  123. (Psyment) setf.sig syment = d_val
  124. ;;
  125. (Psymtab) setf.sig symtab = val
  126. br.sptk.few search_dynamic
  127. apply_loop:
  128. ld8 r_offset = [rela]
  129. add addr = 8,rela
  130. sub relasz = relasz,relaent
  131. ;;
  132. ld8 r_info = [addr],8
  133. ;;
  134. ld8 r_addend = [addr]
  135. add target = ldbase, r_offset
  136. add rela = rela,relaent
  137. extr.u r_type = r_info, 0, 32
  138. ;;
  139. cmp.eq Pnone,p0 = R_IA64_NONE,r_type
  140. cmp.eq Prel,p0 = R_IA64_REL64LSB,r_type
  141. cmp.eq Pfptr,p0 = R_IA64_FPTR64LSB,r_type
  142. (Prel) br.cond.sptk.few apply_REL64
  143. ;;
  144. cmp.eq Prel,p0 = R_IA64_DIR64LSB,r_type // treat DIR64 just like REL64
  145. (Pnone) br.cond.sptk.few apply_relocs
  146. (Prel) br.cond.sptk.few apply_REL64
  147. (Pfptr) br.cond.sptk.few apply_FPTR64
  148. mov r8 = EFI_LOAD_ERROR
  149. br.ret.sptk.few rp
  150. apply_relocs:
  151. cmp.ltu Pmore,p0=0,relasz
  152. (Pmore) br.cond.sptk.few apply_loop
  153. mov r8 = EFI_SUCCESS
  154. br.ret.sptk.few rp
  155. apply_REL64:
  156. ld8 val = [target]
  157. ;;
  158. add val = val,ldbase
  159. ;;
  160. st8 [target] = val
  161. br.cond.sptk.few apply_relocs
  162. // FPTR relocs are a bit more interesting: we need to lookup
  163. // the symbol's value in symtab, allocate 16 bytes of memory,
  164. // store the value in [target] in the first and the gp in the
  165. // second dword.
  166. apply_FPTR64:
  167. st8 [target] = fptr
  168. extr.u r_sym = r_info,32,32
  169. add target = 8,fptr
  170. ;;
  171. setf.sig ftmp = r_sym
  172. mov r8=EFI_BUFFER_TOO_SMALL
  173. ;;
  174. cmp.geu Poom,p0 = fptr,fptr_limit
  175. xma.lu ftmp = ftmp,syment,symtab
  176. (Poom) br.ret.sptk.few rp
  177. ;;
  178. getf.sig addr = ftmp
  179. st8 [target] = gp
  180. ;;
  181. add addr = ST_VALUE_OFF, addr
  182. ;;
  183. ld8 val = [addr]
  184. ;;
  185. add val = val,ldbase
  186. ;;
  187. st8 [fptr] = val,16
  188. br.cond.sptk.few apply_relocs
  189. .endp _relocate
  190. .data
  191. .align 16
  192. fptr_mem_base:
  193. .space MAX_FUNCTION_DESCRIPTORS*16
  194. fptr_mem_limit:
  195. #if defined(__ELF__) && defined(__linux__)
  196. .section .note.GNU-stack,"",%progbits
  197. #endif