tcc 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (283) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +35 -0
  3. data/README.md +196 -0
  4. data/ext/tcc/extconf.rb +25 -0
  5. data/ext/tcc/tcc-0.9.26.patch +30 -0
  6. data/ext/tcc/tcc-0.9.26/COPYING +504 -0
  7. data/ext/tcc/tcc-0.9.26/Changelog +396 -0
  8. data/ext/tcc/tcc-0.9.26/Makefile +349 -0
  9. data/ext/tcc/tcc-0.9.26/README +101 -0
  10. data/ext/tcc/tcc-0.9.26/TODO +93 -0
  11. data/ext/tcc/tcc-0.9.26/VERSION +1 -0
  12. data/ext/tcc/tcc-0.9.26/arm-gen.c +2005 -0
  13. data/ext/tcc/tcc-0.9.26/c67-gen.c +2560 -0
  14. data/ext/tcc/tcc-0.9.26/coff.h +446 -0
  15. data/ext/tcc/tcc-0.9.26/config.h +8 -0
  16. data/ext/tcc/tcc-0.9.26/config.mak +28 -0
  17. data/ext/tcc/tcc-0.9.26/config.texi +1 -0
  18. data/ext/tcc/tcc-0.9.26/configure +540 -0
  19. data/ext/tcc/tcc-0.9.26/conftest.c +71 -0
  20. data/ext/tcc/tcc-0.9.26/elf.h +1731 -0
  21. data/ext/tcc/tcc-0.9.26/examples/ex1.c +8 -0
  22. data/ext/tcc/tcc-0.9.26/examples/ex2.c +98 -0
  23. data/ext/tcc/tcc-0.9.26/examples/ex3.c +24 -0
  24. data/ext/tcc/tcc-0.9.26/examples/ex4.c +26 -0
  25. data/ext/tcc/tcc-0.9.26/examples/ex5.c +8 -0
  26. data/ext/tcc/tcc-0.9.26/i386-asm.c +1498 -0
  27. data/ext/tcc/tcc-0.9.26/i386-asm.h +473 -0
  28. data/ext/tcc/tcc-0.9.26/i386-gen.c +1096 -0
  29. data/ext/tcc/tcc-0.9.26/i386-tok.h +243 -0
  30. data/ext/tcc/tcc-0.9.26/il-gen.c +667 -0
  31. data/ext/tcc/tcc-0.9.26/il-opcodes.h +251 -0
  32. data/ext/tcc/tcc-0.9.26/include/float.h +57 -0
  33. data/ext/tcc/tcc-0.9.26/include/stdarg.h +41 -0
  34. data/ext/tcc/tcc-0.9.26/include/stdbool.h +10 -0
  35. data/ext/tcc/tcc-0.9.26/include/stddef.h +28 -0
  36. data/ext/tcc/tcc-0.9.26/include/tcclib.h +78 -0
  37. data/ext/tcc/tcc-0.9.26/include/varargs.h +12 -0
  38. data/ext/tcc/tcc-0.9.26/lib/Makefile +102 -0
  39. data/ext/tcc/tcc-0.9.26/lib/alloca86-bt.S +47 -0
  40. data/ext/tcc/tcc-0.9.26/lib/alloca86.S +35 -0
  41. data/ext/tcc/tcc-0.9.26/lib/alloca86_64.S +42 -0
  42. data/ext/tcc/tcc-0.9.26/lib/bcheck.c +875 -0
  43. data/ext/tcc/tcc-0.9.26/lib/libtcc1.c +691 -0
  44. data/ext/tcc/tcc-0.9.26/libtcc.c +1941 -0
  45. data/ext/tcc/tcc-0.9.26/libtcc.h +103 -0
  46. data/ext/tcc/tcc-0.9.26/stab.def +234 -0
  47. data/ext/tcc/tcc-0.9.26/stab.h +17 -0
  48. data/ext/tcc/tcc-0.9.26/tcc-doc.html +2332 -0
  49. data/ext/tcc/tcc-0.9.26/tcc-doc.info +1151 -0
  50. data/ext/tcc/tcc-0.9.26/tcc-doc.texi +1268 -0
  51. data/ext/tcc/tcc-0.9.26/tcc.1 +415 -0
  52. data/ext/tcc/tcc-0.9.26/tcc.c +352 -0
  53. data/ext/tcc/tcc-0.9.26/tcc.h +1379 -0
  54. data/ext/tcc/tcc-0.9.26/tccasm.c +1118 -0
  55. data/ext/tcc/tcc-0.9.26/tcccoff.c +948 -0
  56. data/ext/tcc/tcc-0.9.26/tccelf.c +3129 -0
  57. data/ext/tcc/tcc-0.9.26/tccgen.c +5841 -0
  58. data/ext/tcc/tcc-0.9.26/tccpe.c +1887 -0
  59. data/ext/tcc/tcc-0.9.26/tccpp.c +3128 -0
  60. data/ext/tcc/tcc-0.9.26/tccrun.c +737 -0
  61. data/ext/tcc/tcc-0.9.26/tcctok.h +278 -0
  62. data/ext/tcc/tcc-0.9.26/tests/Makefile +199 -0
  63. data/ext/tcc/tcc-0.9.26/tests/asmtest.S +609 -0
  64. data/ext/tcc/tcc-0.9.26/tests/boundtest.c +233 -0
  65. data/ext/tcc/tcc-0.9.26/tests/gcctestsuite.sh +33 -0
  66. data/ext/tcc/tcc-0.9.26/tests/libtcc_test.c +76 -0
  67. data/ext/tcc/tcc-0.9.26/tests/tcctest.c +2713 -0
  68. data/ext/tcc/tcc-0.9.26/tests/tests2/00_assignment.c +18 -0
  69. data/ext/tcc/tcc-0.9.26/tests/tests2/00_assignment.expect +3 -0
  70. data/ext/tcc/tcc-0.9.26/tests/tests2/01_comment.c +14 -0
  71. data/ext/tcc/tcc-0.9.26/tests/tests2/01_comment.expect +5 -0
  72. data/ext/tcc/tcc-0.9.26/tests/tests2/02_printf.c +18 -0
  73. data/ext/tcc/tcc-0.9.26/tests/tests2/02_printf.expect +15 -0
  74. data/ext/tcc/tcc-0.9.26/tests/tests2/03_struct.c +31 -0
  75. data/ext/tcc/tcc-0.9.26/tests/tests2/03_struct.expect +6 -0
  76. data/ext/tcc/tcc-0.9.26/tests/tests2/04_for.c +15 -0
  77. data/ext/tcc/tcc-0.9.26/tests/tests2/04_for.expect +10 -0
  78. data/ext/tcc/tcc-0.9.26/tests/tests2/05_array.c +21 -0
  79. data/ext/tcc/tcc-0.9.26/tests/tests2/05_array.expect +10 -0
  80. data/ext/tcc/tcc-0.9.26/tests/tests2/06_case.c +29 -0
  81. data/ext/tcc/tcc-0.9.26/tests/tests2/06_case.expect +8 -0
  82. data/ext/tcc/tcc-0.9.26/tests/tests2/07_function.c +30 -0
  83. data/ext/tcc/tcc-0.9.26/tests/tests2/07_function.expect +4 -0
  84. data/ext/tcc/tcc-0.9.26/tests/tests2/08_while.c +24 -0
  85. data/ext/tcc/tcc-0.9.26/tests/tests2/08_while.expect +11 -0
  86. data/ext/tcc/tcc-0.9.26/tests/tests2/09_do_while.c +24 -0
  87. data/ext/tcc/tcc-0.9.26/tests/tests2/09_do_while.expect +11 -0
  88. data/ext/tcc/tcc-0.9.26/tests/tests2/10_pointer.c +40 -0
  89. data/ext/tcc/tcc-0.9.26/tests/tests2/10_pointer.expect +8 -0
  90. data/ext/tcc/tcc-0.9.26/tests/tests2/11_precedence.c +40 -0
  91. data/ext/tcc/tcc-0.9.26/tests/tests2/11_precedence.expect +15 -0
  92. data/ext/tcc/tcc-0.9.26/tests/tests2/12_hashdefine.c +14 -0
  93. data/ext/tcc/tcc-0.9.26/tests/tests2/12_hashdefine.expect +2 -0
  94. data/ext/tcc/tcc-0.9.26/tests/tests2/13_integer_literals.c +20 -0
  95. data/ext/tcc/tcc-0.9.26/tests/tests2/13_integer_literals.expect +5 -0
  96. data/ext/tcc/tcc-0.9.26/tests/tests2/14_if.c +21 -0
  97. data/ext/tcc/tcc-0.9.26/tests/tests2/14_if.expect +2 -0
  98. data/ext/tcc/tcc-0.9.26/tests/tests2/15_recursion.c +21 -0
  99. data/ext/tcc/tcc-0.9.26/tests/tests2/15_recursion.expect +10 -0
  100. data/ext/tcc/tcc-0.9.26/tests/tests2/16_nesting.c +21 -0
  101. data/ext/tcc/tcc-0.9.26/tests/tests2/16_nesting.expect +18 -0
  102. data/ext/tcc/tcc-0.9.26/tests/tests2/17_enum.c +29 -0
  103. data/ext/tcc/tcc-0.9.26/tests/tests2/17_enum.expect +3 -0
  104. data/ext/tcc/tcc-0.9.26/tests/tests2/18_include.c +12 -0
  105. data/ext/tcc/tcc-0.9.26/tests/tests2/18_include.expect +3 -0
  106. data/ext/tcc/tcc-0.9.26/tests/tests2/18_include.h +1 -0
  107. data/ext/tcc/tcc-0.9.26/tests/tests2/19_pointer_arithmetic.c +28 -0
  108. data/ext/tcc/tcc-0.9.26/tests/tests2/19_pointer_arithmetic.expect +3 -0
  109. data/ext/tcc/tcc-0.9.26/tests/tests2/20_pointer_comparison.c +24 -0
  110. data/ext/tcc/tcc-0.9.26/tests/tests2/20_pointer_comparison.expect +6 -0
  111. data/ext/tcc/tcc-0.9.26/tests/tests2/21_char_array.c +33 -0
  112. data/ext/tcc/tcc-0.9.26/tests/tests2/21_char_array.expect +7 -0
  113. data/ext/tcc/tcc-0.9.26/tests/tests2/22_floating_point.c +50 -0
  114. data/ext/tcc/tcc-0.9.26/tests/tests2/22_floating_point.expect +16 -0
  115. data/ext/tcc/tcc-0.9.26/tests/tests2/23_type_coercion.c +54 -0
  116. data/ext/tcc/tcc-0.9.26/tests/tests2/23_type_coercion.expect +12 -0
  117. data/ext/tcc/tcc-0.9.26/tests/tests2/24_math_library.c +28 -0
  118. data/ext/tcc/tcc-0.9.26/tests/tests2/24_math_library.expect +18 -0
  119. data/ext/tcc/tcc-0.9.26/tests/tests2/25_quicksort.c +83 -0
  120. data/ext/tcc/tcc-0.9.26/tests/tests2/25_quicksort.expect +2 -0
  121. data/ext/tcc/tcc-0.9.26/tests/tests2/26_character_constants.c +17 -0
  122. data/ext/tcc/tcc-0.9.26/tests/tests2/26_character_constants.expect +8 -0
  123. data/ext/tcc/tcc-0.9.26/tests/tests2/27_sizeof.c +16 -0
  124. data/ext/tcc/tcc-0.9.26/tests/tests2/27_sizeof.expect +3 -0
  125. data/ext/tcc/tcc-0.9.26/tests/tests2/28_strings.c +46 -0
  126. data/ext/tcc/tcc-0.9.26/tests/tests2/28_strings.expect +19 -0
  127. data/ext/tcc/tcc-0.9.26/tests/tests2/29_array_address.c +13 -0
  128. data/ext/tcc/tcc-0.9.26/tests/tests2/29_array_address.expect +1 -0
  129. data/ext/tcc/tcc-0.9.26/tests/tests2/30_hanoi.c +122 -0
  130. data/ext/tcc/tcc-0.9.26/tests/tests2/30_hanoi.expect +71 -0
  131. data/ext/tcc/tcc-0.9.26/tests/tests2/31_args.c +14 -0
  132. data/ext/tcc/tcc-0.9.26/tests/tests2/31_args.expect +7 -0
  133. data/ext/tcc/tcc-0.9.26/tests/tests2/32_led.c +266 -0
  134. data/ext/tcc/tcc-0.9.26/tests/tests2/32_led.expect +4 -0
  135. data/ext/tcc/tcc-0.9.26/tests/tests2/33_ternary_op.c +15 -0
  136. data/ext/tcc/tcc-0.9.26/tests/tests2/33_ternary_op.expect +10 -0
  137. data/ext/tcc/tcc-0.9.26/tests/tests2/34_array_assignment.c +23 -0
  138. data/ext/tcc/tcc-0.9.26/tests/tests2/34_array_assignment.expect +2 -0
  139. data/ext/tcc/tcc-0.9.26/tests/tests2/35_sizeof.c +14 -0
  140. data/ext/tcc/tcc-0.9.26/tests/tests2/35_sizeof.expect +2 -0
  141. data/ext/tcc/tcc-0.9.26/tests/tests2/36_array_initialisers.c +21 -0
  142. data/ext/tcc/tcc-0.9.26/tests/tests2/36_array_initialisers.expect +20 -0
  143. data/ext/tcc/tcc-0.9.26/tests/tests2/37_sprintf.c +17 -0
  144. data/ext/tcc/tcc-0.9.26/tests/tests2/37_sprintf.expect +20 -0
  145. data/ext/tcc/tcc-0.9.26/tests/tests2/38_multiple_array_index.c +32 -0
  146. data/ext/tcc/tcc-0.9.26/tests/tests2/38_multiple_array_index.expect +4 -0
  147. data/ext/tcc/tcc-0.9.26/tests/tests2/39_typedef.c +31 -0
  148. data/ext/tcc/tcc-0.9.26/tests/tests2/39_typedef.expect +3 -0
  149. data/ext/tcc/tcc-0.9.26/tests/tests2/40_stdio.c +52 -0
  150. data/ext/tcc/tcc-0.9.26/tests/tests2/40_stdio.expect +27 -0
  151. data/ext/tcc/tcc-0.9.26/tests/tests2/41_hashif.c +85 -0
  152. data/ext/tcc/tcc-0.9.26/tests/tests2/41_hashif.expect +6 -0
  153. data/ext/tcc/tcc-0.9.26/tests/tests2/42_function_pointer.c +18 -0
  154. data/ext/tcc/tcc-0.9.26/tests/tests2/42_function_pointer.expect +2 -0
  155. data/ext/tcc/tcc-0.9.26/tests/tests2/43_void_param.c +15 -0
  156. data/ext/tcc/tcc-0.9.26/tests/tests2/43_void_param.expect +1 -0
  157. data/ext/tcc/tcc-0.9.26/tests/tests2/44_scoped_declarations.c +17 -0
  158. data/ext/tcc/tcc-0.9.26/tests/tests2/44_scoped_declarations.expect +1 -0
  159. data/ext/tcc/tcc-0.9.26/tests/tests2/45_empty_for.c +18 -0
  160. data/ext/tcc/tcc-0.9.26/tests/tests2/45_empty_for.expect +10 -0
  161. data/ext/tcc/tcc-0.9.26/tests/tests2/46_grep.c +564 -0
  162. data/ext/tcc/tcc-0.9.26/tests/tests2/47_switch_return.c +24 -0
  163. data/ext/tcc/tcc-0.9.26/tests/tests2/47_switch_return.expect +4 -0
  164. data/ext/tcc/tcc-0.9.26/tests/tests2/48_nested_break.c +26 -0
  165. data/ext/tcc/tcc-0.9.26/tests/tests2/48_nested_break.expect +1 -0
  166. data/ext/tcc/tcc-0.9.26/tests/tests2/49_bracket_evaluation.c +23 -0
  167. data/ext/tcc/tcc-0.9.26/tests/tests2/49_bracket_evaluation.expect +1 -0
  168. data/ext/tcc/tcc-0.9.26/tests/tests2/50_logical_second_arg.c +29 -0
  169. data/ext/tcc/tcc-0.9.26/tests/tests2/50_logical_second_arg.expect +20 -0
  170. data/ext/tcc/tcc-0.9.26/tests/tests2/51_static.c +30 -0
  171. data/ext/tcc/tcc-0.9.26/tests/tests2/51_static.expect +8 -0
  172. data/ext/tcc/tcc-0.9.26/tests/tests2/52_unnamed_enum.c +27 -0
  173. data/ext/tcc/tcc-0.9.26/tests/tests2/52_unnamed_enum.expect +9 -0
  174. data/ext/tcc/tcc-0.9.26/tests/tests2/54_goto.c +56 -0
  175. data/ext/tcc/tcc-0.9.26/tests/tests2/54_goto.expect +8 -0
  176. data/ext/tcc/tcc-0.9.26/tests/tests2/55_lshift_type.c +52 -0
  177. data/ext/tcc/tcc-0.9.26/tests/tests2/55_lshift_type.expect +1 -0
  178. data/ext/tcc/tcc-0.9.26/tests/tests2/LICENSE +37 -0
  179. data/ext/tcc/tcc-0.9.26/tests/tests2/Makefile +98 -0
  180. data/ext/tcc/tcc-0.9.26/texi2pod.pl +427 -0
  181. data/ext/tcc/tcc-0.9.26/win32/build-tcc.bat +60 -0
  182. data/ext/tcc/tcc-0.9.26/win32/examples/dll.c +12 -0
  183. data/ext/tcc/tcc-0.9.26/win32/examples/fib.c +23 -0
  184. data/ext/tcc/tcc-0.9.26/win32/examples/hello_dll.c +19 -0
  185. data/ext/tcc/tcc-0.9.26/win32/examples/hello_win.c +163 -0
  186. data/ext/tcc/tcc-0.9.26/win32/include/_mingw.h +139 -0
  187. data/ext/tcc/tcc-0.9.26/win32/include/assert.h +54 -0
  188. data/ext/tcc/tcc-0.9.26/win32/include/conio.h +409 -0
  189. data/ext/tcc/tcc-0.9.26/win32/include/ctype.h +281 -0
  190. data/ext/tcc/tcc-0.9.26/win32/include/dir.h +31 -0
  191. data/ext/tcc/tcc-0.9.26/win32/include/direct.h +68 -0
  192. data/ext/tcc/tcc-0.9.26/win32/include/dirent.h +135 -0
  193. data/ext/tcc/tcc-0.9.26/win32/include/dos.h +55 -0
  194. data/ext/tcc/tcc-0.9.26/win32/include/errno.h +75 -0
  195. data/ext/tcc/tcc-0.9.26/win32/include/excpt.h +123 -0
  196. data/ext/tcc/tcc-0.9.26/win32/include/fcntl.h +52 -0
  197. data/ext/tcc/tcc-0.9.26/win32/include/fenv.h +108 -0
  198. data/ext/tcc/tcc-0.9.26/win32/include/inttypes.h +297 -0
  199. data/ext/tcc/tcc-0.9.26/win32/include/io.h +418 -0
  200. data/ext/tcc/tcc-0.9.26/win32/include/limits.h +111 -0
  201. data/ext/tcc/tcc-0.9.26/win32/include/locale.h +91 -0
  202. data/ext/tcc/tcc-0.9.26/win32/include/malloc.h +175 -0
  203. data/ext/tcc/tcc-0.9.26/win32/include/math.h +777 -0
  204. data/ext/tcc/tcc-0.9.26/win32/include/mem.h +13 -0
  205. data/ext/tcc/tcc-0.9.26/win32/include/memory.h +40 -0
  206. data/ext/tcc/tcc-0.9.26/win32/include/process.h +176 -0
  207. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/conio_s.h +42 -0
  208. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/crtdbg_s.h +19 -0
  209. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/io_s.h +33 -0
  210. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/mbstring_s.h +52 -0
  211. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/search_s.h +25 -0
  212. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/stdio_s.h +145 -0
  213. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/stdlib_s.h +67 -0
  214. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/stralign_s.h +30 -0
  215. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/string_s.h +41 -0
  216. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/sys/timeb_s.h +34 -0
  217. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/tchar_s.h +266 -0
  218. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/time_s.h +61 -0
  219. data/ext/tcc/tcc-0.9.26/win32/include/sec_api/wchar_s.h +128 -0
  220. data/ext/tcc/tcc-0.9.26/win32/include/setjmp.h +160 -0
  221. data/ext/tcc/tcc-0.9.26/win32/include/share.h +28 -0
  222. data/ext/tcc/tcc-0.9.26/win32/include/signal.h +63 -0
  223. data/ext/tcc/tcc-0.9.26/win32/include/stdint.h +209 -0
  224. data/ext/tcc/tcc-0.9.26/win32/include/stdio.h +429 -0
  225. data/ext/tcc/tcc-0.9.26/win32/include/stdlib.h +580 -0
  226. data/ext/tcc/tcc-0.9.26/win32/include/string.h +164 -0
  227. data/ext/tcc/tcc-0.9.26/win32/include/sys/fcntl.h +13 -0
  228. data/ext/tcc/tcc-0.9.26/win32/include/sys/file.h +14 -0
  229. data/ext/tcc/tcc-0.9.26/win32/include/sys/locking.h +30 -0
  230. data/ext/tcc/tcc-0.9.26/win32/include/sys/stat.h +290 -0
  231. data/ext/tcc/tcc-0.9.26/win32/include/sys/time.h +69 -0
  232. data/ext/tcc/tcc-0.9.26/win32/include/sys/timeb.h +133 -0
  233. data/ext/tcc/tcc-0.9.26/win32/include/sys/types.h +118 -0
  234. data/ext/tcc/tcc-0.9.26/win32/include/sys/unistd.h +14 -0
  235. data/ext/tcc/tcc-0.9.26/win32/include/sys/utime.h +146 -0
  236. data/ext/tcc/tcc-0.9.26/win32/include/tchar.h +1102 -0
  237. data/ext/tcc/tcc-0.9.26/win32/include/time.h +287 -0
  238. data/ext/tcc/tcc-0.9.26/win32/include/vadefs.h +11 -0
  239. data/ext/tcc/tcc-0.9.26/win32/include/values.h +4 -0
  240. data/ext/tcc/tcc-0.9.26/win32/include/wchar.h +871 -0
  241. data/ext/tcc/tcc-0.9.26/win32/include/wctype.h +172 -0
  242. data/ext/tcc/tcc-0.9.26/win32/include/winapi/basetsd.h +149 -0
  243. data/ext/tcc/tcc-0.9.26/win32/include/winapi/basetyps.h +85 -0
  244. data/ext/tcc/tcc-0.9.26/win32/include/winapi/guiddef.h +151 -0
  245. data/ext/tcc/tcc-0.9.26/win32/include/winapi/intrin.h +11 -0
  246. data/ext/tcc/tcc-0.9.26/win32/include/winapi/poppack.h +8 -0
  247. data/ext/tcc/tcc-0.9.26/win32/include/winapi/pshpack1.h +8 -0
  248. data/ext/tcc/tcc-0.9.26/win32/include/winapi/pshpack2.h +8 -0
  249. data/ext/tcc/tcc-0.9.26/win32/include/winapi/pshpack4.h +8 -0
  250. data/ext/tcc/tcc-0.9.26/win32/include/winapi/pshpack8.h +8 -0
  251. data/ext/tcc/tcc-0.9.26/win32/include/winapi/reason.h +80 -0
  252. data/ext/tcc/tcc-0.9.26/win32/include/winapi/specstrings.h +7 -0
  253. data/ext/tcc/tcc-0.9.26/win32/include/winapi/stralign.h +154 -0
  254. data/ext/tcc/tcc-0.9.26/win32/include/winapi/tvout.h +79 -0
  255. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winbase.h +2951 -0
  256. data/ext/tcc/tcc-0.9.26/win32/include/winapi/wincon.h +301 -0
  257. data/ext/tcc/tcc-0.9.26/win32/include/winapi/windef.h +293 -0
  258. data/ext/tcc/tcc-0.9.26/win32/include/winapi/windows.h +123 -0
  259. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winerror.h +3166 -0
  260. data/ext/tcc/tcc-0.9.26/win32/include/winapi/wingdi.h +4080 -0
  261. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winnetwk.h +476 -0
  262. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winnls.h +765 -0
  263. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winnt.h +5770 -0
  264. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winreg.h +272 -0
  265. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winuser.h +5651 -0
  266. data/ext/tcc/tcc-0.9.26/win32/include/winapi/winver.h +160 -0
  267. data/ext/tcc/tcc-0.9.26/win32/lib/chkstk.S +191 -0
  268. data/ext/tcc/tcc-0.9.26/win32/lib/crt1.c +34 -0
  269. data/ext/tcc/tcc-0.9.26/win32/lib/dllcrt1.c +13 -0
  270. data/ext/tcc/tcc-0.9.26/win32/lib/dllmain.c +9 -0
  271. data/ext/tcc/tcc-0.9.26/win32/lib/gdi32.def +337 -0
  272. data/ext/tcc/tcc-0.9.26/win32/lib/kernel32.def +765 -0
  273. data/ext/tcc/tcc-0.9.26/win32/lib/msvcrt.def +1399 -0
  274. data/ext/tcc/tcc-0.9.26/win32/lib/user32.def +654 -0
  275. data/ext/tcc/tcc-0.9.26/win32/lib/wincrt1.c +64 -0
  276. data/ext/tcc/tcc-0.9.26/win32/tcc-win32.txt +156 -0
  277. data/ext/tcc/tcc-0.9.26/win32/tools/tiny_impdef.c +243 -0
  278. data/ext/tcc/tcc-0.9.26/win32/tools/tiny_libmaker.c +258 -0
  279. data/ext/tcc/tcc-0.9.26/x86_64-asm.h +448 -0
  280. data/ext/tcc/tcc-0.9.26/x86_64-gen.c +1701 -0
  281. data/lib/tcc.rb +291 -0
  282. data/tcc.gemspec +15 -0
  283. metadata +343 -0
@@ -0,0 +1,3129 @@
1
+ /*
2
+ * ELF file handling for TCC
3
+ *
4
+ * Copyright (c) 2001-2004 Fabrice Bellard
5
+ *
6
+ * This library is free software; you can redistribute it and/or
7
+ * modify it under the terms of the GNU Lesser General Public
8
+ * License as published by the Free Software Foundation; either
9
+ * version 2 of the License, or (at your option) any later version.
10
+ *
11
+ * This library is distributed in the hope that it will be useful,
12
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
+ * Lesser General Public License for more details.
15
+ *
16
+ * You should have received a copy of the GNU Lesser General Public
17
+ * License along with this library; if not, write to the Free Software
18
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
+ */
20
+
21
+ #include "tcc.h"
22
+
23
+ static int new_undef_sym = 0; /* Is there a new undefined sym since last new_undef_sym() */
24
+
25
+ ST_FUNC int put_elf_str(Section *s, const char *sym)
26
+ {
27
+ int offset, len;
28
+ char *ptr;
29
+
30
+ len = strlen(sym) + 1;
31
+ offset = s->data_offset;
32
+ ptr = section_ptr_add(s, len);
33
+ memcpy(ptr, sym, len);
34
+ return offset;
35
+ }
36
+
37
+ /* elf symbol hashing function */
38
+ static unsigned long elf_hash(const unsigned char *name)
39
+ {
40
+ unsigned long h = 0, g;
41
+
42
+ while (*name) {
43
+ h = (h << 4) + *name++;
44
+ g = h & 0xf0000000;
45
+ if (g)
46
+ h ^= g >> 24;
47
+ h &= ~g;
48
+ }
49
+ return h;
50
+ }
51
+
52
+ /* rebuild hash table of section s */
53
+ /* NOTE: we do factorize the hash table code to go faster */
54
+ static void rebuild_hash(Section *s, unsigned int nb_buckets)
55
+ {
56
+ ElfW(Sym) *sym;
57
+ int *ptr, *hash, nb_syms, sym_index, h;
58
+ char *strtab;
59
+
60
+ strtab = s->link->data;
61
+ nb_syms = s->data_offset / sizeof(ElfW(Sym));
62
+
63
+ s->hash->data_offset = 0;
64
+ ptr = section_ptr_add(s->hash, (2 + nb_buckets + nb_syms) * sizeof(int));
65
+ ptr[0] = nb_buckets;
66
+ ptr[1] = nb_syms;
67
+ ptr += 2;
68
+ hash = ptr;
69
+ memset(hash, 0, (nb_buckets + 1) * sizeof(int));
70
+ ptr += nb_buckets + 1;
71
+
72
+ sym = (ElfW(Sym) *)s->data + 1;
73
+ for(sym_index = 1; sym_index < nb_syms; sym_index++) {
74
+ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
75
+ h = elf_hash(strtab + sym->st_name) % nb_buckets;
76
+ *ptr = hash[h];
77
+ hash[h] = sym_index;
78
+ } else {
79
+ *ptr = 0;
80
+ }
81
+ ptr++;
82
+ sym++;
83
+ }
84
+ }
85
+
86
+ /* return the symbol number */
87
+ ST_FUNC int put_elf_sym(Section *s, addr_t value, unsigned long size,
88
+ int info, int other, int shndx, const char *name)
89
+ {
90
+ int name_offset, sym_index;
91
+ int nbuckets, h;
92
+ ElfW(Sym) *sym;
93
+ Section *hs;
94
+
95
+ sym = section_ptr_add(s, sizeof(ElfW(Sym)));
96
+ if (name)
97
+ name_offset = put_elf_str(s->link, name);
98
+ else
99
+ name_offset = 0;
100
+ /* XXX: endianness */
101
+ sym->st_name = name_offset;
102
+ sym->st_value = value;
103
+ sym->st_size = size;
104
+ sym->st_info = info;
105
+ sym->st_other = other;
106
+ sym->st_shndx = shndx;
107
+ sym_index = sym - (ElfW(Sym) *)s->data;
108
+ hs = s->hash;
109
+ if (hs) {
110
+ int *ptr, *base;
111
+ ptr = section_ptr_add(hs, sizeof(int));
112
+ base = (int *)hs->data;
113
+ /* only add global or weak symbols */
114
+ if (ELFW(ST_BIND)(info) != STB_LOCAL) {
115
+ /* add another hashing entry */
116
+ nbuckets = base[0];
117
+ h = elf_hash(name) % nbuckets;
118
+ *ptr = base[2 + h];
119
+ base[2 + h] = sym_index;
120
+ base[1]++;
121
+ /* we resize the hash table */
122
+ hs->nb_hashed_syms++;
123
+ if (hs->nb_hashed_syms > 2 * nbuckets) {
124
+ rebuild_hash(s, 2 * nbuckets);
125
+ }
126
+ } else {
127
+ *ptr = 0;
128
+ base[1]++;
129
+ }
130
+ }
131
+ return sym_index;
132
+ }
133
+
134
+ /* find global ELF symbol 'name' and return its index. Return 0 if not
135
+ found. */
136
+ ST_FUNC int find_elf_sym(Section *s, const char *name)
137
+ {
138
+ ElfW(Sym) *sym;
139
+ Section *hs;
140
+ int nbuckets, sym_index, h;
141
+ const char *name1;
142
+
143
+ hs = s->hash;
144
+ if (!hs)
145
+ return 0;
146
+ nbuckets = ((int *)hs->data)[0];
147
+ h = elf_hash(name) % nbuckets;
148
+ sym_index = ((int *)hs->data)[2 + h];
149
+ while (sym_index != 0) {
150
+ sym = &((ElfW(Sym) *)s->data)[sym_index];
151
+ name1 = s->link->data + sym->st_name;
152
+ if (!strcmp(name, name1))
153
+ return sym_index;
154
+ sym_index = ((int *)hs->data)[2 + nbuckets + sym_index];
155
+ }
156
+ return 0;
157
+ }
158
+
159
+ /* return elf symbol value, signal error if 'err' is nonzero */
160
+ ST_FUNC addr_t get_elf_sym_addr(TCCState *s, const char *name, int err)
161
+ {
162
+ int sym_index;
163
+ ElfW(Sym) *sym;
164
+
165
+ sym_index = find_elf_sym(s->symtab, name);
166
+ sym = &((ElfW(Sym) *)s->symtab->data)[sym_index];
167
+ if (!sym_index || sym->st_shndx == SHN_UNDEF) {
168
+ if (err)
169
+ tcc_error("%s not defined", name);
170
+ return 0;
171
+ }
172
+ return sym->st_value;
173
+ }
174
+
175
+ /* return elf symbol value */
176
+ LIBTCCAPI void *tcc_get_symbol(TCCState *s, const char *name)
177
+ {
178
+ return (void*)(uintptr_t)get_elf_sym_addr(s, name, 0);
179
+ }
180
+
181
+ #ifdef TCC_IS_NATIVE
182
+ /* return elf symbol value or error */
183
+ ST_FUNC void* tcc_get_symbol_err(TCCState *s, const char *name)
184
+ {
185
+ return (void*)get_elf_sym_addr(s, name, 1);
186
+ }
187
+ #endif
188
+
189
+ /* add an elf symbol : check if it is already defined and patch
190
+ it. Return symbol index. NOTE that sh_num can be SHN_UNDEF. */
191
+ ST_FUNC int add_elf_sym(Section *s, addr_t value, unsigned long size,
192
+ int info, int other, int sh_num, const char *name)
193
+ {
194
+ ElfW(Sym) *esym;
195
+ int sym_bind, sym_index, sym_type, esym_bind;
196
+ unsigned char sym_vis, esym_vis, new_vis;
197
+
198
+ sym_bind = ELFW(ST_BIND)(info);
199
+ sym_type = ELFW(ST_TYPE)(info);
200
+ sym_vis = ELFW(ST_VISIBILITY)(other);
201
+
202
+ if (sym_bind != STB_LOCAL) {
203
+ /* we search global or weak symbols */
204
+ sym_index = find_elf_sym(s, name);
205
+ if (!sym_index)
206
+ goto do_def;
207
+ esym = &((ElfW(Sym) *)s->data)[sym_index];
208
+ if (esym->st_shndx != SHN_UNDEF) {
209
+ esym_bind = ELFW(ST_BIND)(esym->st_info);
210
+ /* propagate the most constraining visibility */
211
+ /* STV_DEFAULT(0)<STV_PROTECTED(3)<STV_HIDDEN(2)<STV_INTERNAL(1) */
212
+ esym_vis = ELFW(ST_VISIBILITY)(esym->st_other);
213
+ if (esym_vis == STV_DEFAULT) {
214
+ new_vis = sym_vis;
215
+ } else if (sym_vis == STV_DEFAULT) {
216
+ new_vis = esym_vis;
217
+ } else {
218
+ new_vis = (esym_vis < sym_vis) ? esym_vis : sym_vis;
219
+ }
220
+ esym->st_other = (esym->st_other & ~ELFW(ST_VISIBILITY)(-1))
221
+ | new_vis;
222
+ other = esym->st_other; /* in case we have to patch esym */
223
+ if (sh_num == SHN_UNDEF) {
224
+ /* ignore adding of undefined symbol if the
225
+ corresponding symbol is already defined */
226
+ } else if (sym_bind == STB_GLOBAL && esym_bind == STB_WEAK) {
227
+ /* global overrides weak, so patch */
228
+ goto do_patch;
229
+ } else if (sym_bind == STB_WEAK && esym_bind == STB_GLOBAL) {
230
+ /* weak is ignored if already global */
231
+ } else if (sym_bind == STB_WEAK && esym_bind == STB_WEAK) {
232
+ /* keep first-found weak definition, ignore subsequents */
233
+ } else if (sym_vis == STV_HIDDEN || sym_vis == STV_INTERNAL) {
234
+ /* ignore hidden symbols after */
235
+ } else if (esym->st_shndx == SHN_COMMON
236
+ && (sh_num < SHN_LORESERVE || sh_num == SHN_COMMON)) {
237
+ /* gr: Happens with 'tcc ... -static tcctest.c' on e.g. Ubuntu 6.01
238
+ No idea if this is the correct solution ... */
239
+ goto do_patch;
240
+ } else if (s == tcc_state->dynsymtab_section) {
241
+ /* we accept that two DLL define the same symbol */
242
+ } else {
243
+ #if 0
244
+ printf("new_bind=%x new_shndx=%x new_vis=%x old_bind=%x old_shndx=%x old_vis=%x\n",
245
+ sym_bind, sh_num, new_vis, esym_bind, esym->st_shndx, esym_vis);
246
+ #endif
247
+ tcc_error_noabort("'%s' defined twice", name);
248
+ }
249
+ } else {
250
+ do_patch:
251
+ esym->st_info = ELFW(ST_INFO)(sym_bind, sym_type);
252
+ esym->st_shndx = sh_num;
253
+ new_undef_sym = 1;
254
+ esym->st_value = value;
255
+ esym->st_size = size;
256
+ esym->st_other = other;
257
+ }
258
+ } else {
259
+ do_def:
260
+ sym_index = put_elf_sym(s, value, size,
261
+ ELFW(ST_INFO)(sym_bind, sym_type), other,
262
+ sh_num, name);
263
+ }
264
+ return sym_index;
265
+ }
266
+
267
+ /* put relocation */
268
+ ST_FUNC void put_elf_reloc(Section *symtab, Section *s, unsigned long offset,
269
+ int type, int symbol)
270
+ {
271
+ char buf[256];
272
+ Section *sr;
273
+ ElfW_Rel *rel;
274
+
275
+ sr = s->reloc;
276
+ if (!sr) {
277
+ /* if no relocation section, create it */
278
+ snprintf(buf, sizeof(buf), REL_SECTION_FMT, s->name);
279
+ /* if the symtab is allocated, then we consider the relocation
280
+ are also */
281
+ sr = new_section(tcc_state, buf, SHT_RELX, symtab->sh_flags);
282
+ sr->sh_entsize = sizeof(ElfW_Rel);
283
+ sr->link = symtab;
284
+ sr->sh_info = s->sh_num;
285
+ s->reloc = sr;
286
+ }
287
+ rel = section_ptr_add(sr, sizeof(ElfW_Rel));
288
+ rel->r_offset = offset;
289
+ rel->r_info = ELFW(R_INFO)(symbol, type);
290
+ #ifdef TCC_TARGET_X86_64
291
+ rel->r_addend = 0;
292
+ #endif
293
+ }
294
+
295
+ /* put stab debug information */
296
+
297
+ ST_FUNC void put_stabs(const char *str, int type, int other, int desc,
298
+ unsigned long value)
299
+ {
300
+ Stab_Sym *sym;
301
+
302
+ sym = section_ptr_add(stab_section, sizeof(Stab_Sym));
303
+ if (str) {
304
+ sym->n_strx = put_elf_str(stabstr_section, str);
305
+ } else {
306
+ sym->n_strx = 0;
307
+ }
308
+ sym->n_type = type;
309
+ sym->n_other = other;
310
+ sym->n_desc = desc;
311
+ sym->n_value = value;
312
+ }
313
+
314
+ ST_FUNC void put_stabs_r(const char *str, int type, int other, int desc,
315
+ unsigned long value, Section *sec, int sym_index)
316
+ {
317
+ put_stabs(str, type, other, desc, value);
318
+ put_elf_reloc(symtab_section, stab_section,
319
+ stab_section->data_offset - sizeof(unsigned int),
320
+ R_DATA_32, sym_index);
321
+ }
322
+
323
+ ST_FUNC void put_stabn(int type, int other, int desc, int value)
324
+ {
325
+ put_stabs(NULL, type, other, desc, value);
326
+ }
327
+
328
+ ST_FUNC void put_stabd(int type, int other, int desc)
329
+ {
330
+ put_stabs(NULL, type, other, desc, 0);
331
+ }
332
+
333
+ /* In an ELF file symbol table, the local symbols must appear below
334
+ the global and weak ones. Since TCC cannot sort it while generating
335
+ the code, we must do it after. All the relocation tables are also
336
+ modified to take into account the symbol table sorting */
337
+ static void sort_syms(TCCState *s1, Section *s)
338
+ {
339
+ int *old_to_new_syms;
340
+ ElfW(Sym) *new_syms;
341
+ int nb_syms, i;
342
+ ElfW(Sym) *p, *q;
343
+ ElfW_Rel *rel, *rel_end;
344
+ Section *sr;
345
+ int type, sym_index;
346
+
347
+ nb_syms = s->data_offset / sizeof(ElfW(Sym));
348
+ new_syms = tcc_malloc(nb_syms * sizeof(ElfW(Sym)));
349
+ old_to_new_syms = tcc_malloc(nb_syms * sizeof(int));
350
+
351
+ /* first pass for local symbols */
352
+ p = (ElfW(Sym) *)s->data;
353
+ q = new_syms;
354
+ for(i = 0; i < nb_syms; i++) {
355
+ if (ELFW(ST_BIND)(p->st_info) == STB_LOCAL) {
356
+ old_to_new_syms[i] = q - new_syms;
357
+ *q++ = *p;
358
+ }
359
+ p++;
360
+ }
361
+ /* save the number of local symbols in section header */
362
+ s->sh_info = q - new_syms;
363
+
364
+ /* then second pass for non local symbols */
365
+ p = (ElfW(Sym) *)s->data;
366
+ for(i = 0; i < nb_syms; i++) {
367
+ if (ELFW(ST_BIND)(p->st_info) != STB_LOCAL) {
368
+ old_to_new_syms[i] = q - new_syms;
369
+ *q++ = *p;
370
+ }
371
+ p++;
372
+ }
373
+
374
+ /* we copy the new symbols to the old */
375
+ memcpy(s->data, new_syms, nb_syms * sizeof(ElfW(Sym)));
376
+ tcc_free(new_syms);
377
+
378
+ /* now we modify all the relocations */
379
+ for(i = 1; i < s1->nb_sections; i++) {
380
+ sr = s1->sections[i];
381
+ if (sr->sh_type == SHT_RELX && sr->link == s) {
382
+ rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
383
+ for(rel = (ElfW_Rel *)sr->data;
384
+ rel < rel_end;
385
+ rel++) {
386
+ sym_index = ELFW(R_SYM)(rel->r_info);
387
+ type = ELFW(R_TYPE)(rel->r_info);
388
+ sym_index = old_to_new_syms[sym_index];
389
+ rel->r_info = ELFW(R_INFO)(sym_index, type);
390
+ }
391
+ }
392
+ }
393
+
394
+ tcc_free(old_to_new_syms);
395
+ }
396
+
397
+ /* relocate common symbols in the .bss section */
398
+ ST_FUNC void relocate_common_syms(void)
399
+ {
400
+ ElfW(Sym) *sym, *sym_end;
401
+ unsigned long offset, align;
402
+
403
+ sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
404
+ for(sym = (ElfW(Sym) *)symtab_section->data + 1;
405
+ sym < sym_end;
406
+ sym++) {
407
+ if (sym->st_shndx == SHN_COMMON) {
408
+ /* align symbol */
409
+ align = sym->st_value;
410
+ offset = bss_section->data_offset;
411
+ offset = (offset + align - 1) & -align;
412
+ sym->st_value = offset;
413
+ sym->st_shndx = bss_section->sh_num;
414
+ offset += sym->st_size;
415
+ bss_section->data_offset = offset;
416
+ }
417
+ }
418
+ }
419
+
420
+ /* relocate symbol table, resolve undefined symbols if do_resolve is
421
+ true and output error if undefined symbol. */
422
+ ST_FUNC void relocate_syms(TCCState *s1, int do_resolve)
423
+ {
424
+ ElfW(Sym) *sym, *esym, *sym_end;
425
+ int sym_bind, sh_num, sym_index;
426
+ const char *name;
427
+
428
+ sym_end = (ElfW(Sym) *)(symtab_section->data + symtab_section->data_offset);
429
+ for(sym = (ElfW(Sym) *)symtab_section->data + 1;
430
+ sym < sym_end;
431
+ sym++) {
432
+ sh_num = sym->st_shndx;
433
+ if (sh_num == SHN_UNDEF) {
434
+ name = strtab_section->data + sym->st_name;
435
+ if (do_resolve) {
436
+ #if defined TCC_IS_NATIVE && !defined _WIN32
437
+ void *addr;
438
+ name = symtab_section->link->data + sym->st_name;
439
+ addr = resolve_sym(s1, name);
440
+ if (addr) {
441
+ sym->st_value = (addr_t)addr;
442
+ goto found;
443
+ }
444
+ #endif
445
+ } else if (s1->dynsym) {
446
+ /* if dynamic symbol exist, then use it */
447
+ sym_index = find_elf_sym(s1->dynsym, name);
448
+ if (sym_index) {
449
+ esym = &((ElfW(Sym) *)s1->dynsym->data)[sym_index];
450
+ sym->st_value = esym->st_value;
451
+ goto found;
452
+ }
453
+ }
454
+ /* XXX: _fp_hw seems to be part of the ABI, so we ignore
455
+ it */
456
+ if (!strcmp(name, "_fp_hw"))
457
+ goto found;
458
+ /* only weak symbols are accepted to be undefined. Their
459
+ value is zero */
460
+ sym_bind = ELFW(ST_BIND)(sym->st_info);
461
+ if (sym_bind == STB_WEAK) {
462
+ sym->st_value = 0;
463
+ } else {
464
+ tcc_error_noabort("undefined symbol '%s'", name);
465
+ }
466
+ } else if (sh_num < SHN_LORESERVE) {
467
+ /* add section base */
468
+ sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
469
+ }
470
+ found: ;
471
+ }
472
+ }
473
+
474
+ #ifdef TCC_HAS_RUNTIME_PLTGOT
475
+ #ifdef TCC_TARGET_X86_64
476
+ #define JMP_TABLE_ENTRY_SIZE 14
477
+ static addr_t add_jmp_table(TCCState *s1, addr_t val)
478
+ {
479
+ char *p = s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset;
480
+ s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
481
+ /* jmp *0x0(%rip) */
482
+ p[0] = 0xff;
483
+ p[1] = 0x25;
484
+ *(int *)(p + 2) = 0;
485
+ *(addr_t *)(p + 6) = val;
486
+ return (addr_t)p;
487
+ }
488
+
489
+ static addr_t add_got_table(TCCState *s1, addr_t val)
490
+ {
491
+ addr_t *p = (addr_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
492
+ s1->runtime_plt_and_got_offset += sizeof(addr_t);
493
+ *p = val;
494
+ return (addr_t)p;
495
+ }
496
+ #elif defined TCC_TARGET_ARM
497
+ #define JMP_TABLE_ENTRY_SIZE 8
498
+ static addr_t add_jmp_table(TCCState *s1, int val)
499
+ {
500
+ uint32_t *p = (uint32_t *)(s1->runtime_plt_and_got + s1->runtime_plt_and_got_offset);
501
+ s1->runtime_plt_and_got_offset += JMP_TABLE_ENTRY_SIZE;
502
+ /* ldr pc, [pc, #-4] */
503
+ p[0] = 0xE51FF004;
504
+ p[1] = val;
505
+ return (addr_t)p;
506
+ }
507
+ #endif
508
+ #endif /* def TCC_HAS_RUNTIME_PLTGOT */
509
+
510
+ /* relocate a given section (CPU dependent) */
511
+ ST_FUNC void relocate_section(TCCState *s1, Section *s)
512
+ {
513
+ Section *sr;
514
+ ElfW_Rel *rel, *rel_end, *qrel;
515
+ ElfW(Sym) *sym;
516
+ int type, sym_index;
517
+ unsigned char *ptr;
518
+ addr_t val, addr;
519
+ #if defined TCC_TARGET_I386 || defined TCC_TARGET_X86_64
520
+ int esym_index;
521
+ #endif
522
+
523
+ sr = s->reloc;
524
+ rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
525
+ qrel = (ElfW_Rel *)sr->data;
526
+ for(rel = qrel;
527
+ rel < rel_end;
528
+ rel++) {
529
+ ptr = s->data + rel->r_offset;
530
+
531
+ sym_index = ELFW(R_SYM)(rel->r_info);
532
+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
533
+ val = sym->st_value;
534
+ #ifdef TCC_TARGET_X86_64
535
+ val += rel->r_addend;
536
+ #endif
537
+ type = ELFW(R_TYPE)(rel->r_info);
538
+ addr = s->sh_addr + rel->r_offset;
539
+
540
+ /* CPU specific */
541
+ switch(type) {
542
+ #if defined(TCC_TARGET_I386)
543
+ case R_386_32:
544
+ if (s1->output_type == TCC_OUTPUT_DLL) {
545
+ esym_index = s1->symtab_to_dynsym[sym_index];
546
+ qrel->r_offset = rel->r_offset;
547
+ if (esym_index) {
548
+ qrel->r_info = ELFW(R_INFO)(esym_index, R_386_32);
549
+ qrel++;
550
+ break;
551
+ } else {
552
+ qrel->r_info = ELFW(R_INFO)(0, R_386_RELATIVE);
553
+ qrel++;
554
+ }
555
+ }
556
+ *(int *)ptr += val;
557
+ break;
558
+ case R_386_PC32:
559
+ if (s1->output_type == TCC_OUTPUT_DLL) {
560
+ /* DLL relocation */
561
+ esym_index = s1->symtab_to_dynsym[sym_index];
562
+ if (esym_index) {
563
+ qrel->r_offset = rel->r_offset;
564
+ qrel->r_info = ELFW(R_INFO)(esym_index, R_386_PC32);
565
+ qrel++;
566
+ break;
567
+ }
568
+ }
569
+ *(int *)ptr += val - addr;
570
+ break;
571
+ case R_386_PLT32:
572
+ *(int *)ptr += val - addr;
573
+ break;
574
+ case R_386_GLOB_DAT:
575
+ case R_386_JMP_SLOT:
576
+ *(int *)ptr = val;
577
+ break;
578
+ case R_386_GOTPC:
579
+ *(int *)ptr += s1->got->sh_addr - addr;
580
+ break;
581
+ case R_386_GOTOFF:
582
+ *(int *)ptr += val - s1->got->sh_addr;
583
+ break;
584
+ case R_386_GOT32:
585
+ /* we load the got offset */
586
+ *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
587
+ break;
588
+ case R_386_16:
589
+ if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY) {
590
+ output_file:
591
+ tcc_error("can only produce 16-bit binary files");
592
+ }
593
+ *(short *)ptr += val;
594
+ break;
595
+ case R_386_PC16:
596
+ if (s1->output_format != TCC_OUTPUT_FORMAT_BINARY)
597
+ goto output_file;
598
+ *(short *)ptr += val - addr;
599
+ break;
600
+ #elif defined(TCC_TARGET_ARM)
601
+ case R_ARM_PC24:
602
+ case R_ARM_CALL:
603
+ case R_ARM_JUMP24:
604
+ case R_ARM_PLT32:
605
+ {
606
+ int x, is_thumb, is_call, h, blx_avail;
607
+ x = (*(int *)ptr)&0xffffff;
608
+ (*(int *)ptr) &= 0xff000000;
609
+ if (x & 0x800000)
610
+ x -= 0x1000000;
611
+ x <<= 2;
612
+ blx_avail = (TCC_ARM_VERSION >= 5);
613
+ is_thumb = val & 1;
614
+ is_call = (type == R_ARM_CALL);
615
+ x += val - addr;
616
+ h = x & 2;
617
+ #ifdef TCC_HAS_RUNTIME_PLTGOT
618
+ if (s1->output_type == TCC_OUTPUT_MEMORY) {
619
+ if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
620
+ if (!(x & 3) || !blx_avail || !is_call) {
621
+ x += add_jmp_table(s1, val) - val; /* add veneer */
622
+ is_thumb = 0; /* Veneer uses ARM instructions */
623
+ }
624
+ }
625
+ #endif
626
+ if ((x & 3) || x >= 0x2000000 || x < -0x2000000)
627
+ if (!(x & 3) || !blx_avail || !is_call)
628
+ tcc_error("can't relocate value at %x",addr);
629
+ x >>= 2;
630
+ x &= 0xffffff;
631
+ /* Only reached if blx is avail and it is a call */
632
+ if (is_thumb) {
633
+ x |= h << 24;
634
+ (*(int *)ptr) = 0xfa << 24; /* bl -> blx */
635
+ }
636
+ (*(int *)ptr) |= x;
637
+ }
638
+ break;
639
+ /* Since these relocations only concern Thumb-2 and blx instruction was
640
+ introduced before Thumb-2, we can assume blx is available and not
641
+ guard its use */
642
+ case R_ARM_THM_CALL:
643
+ case R_ARM_THM_JUMP24:
644
+ {
645
+ int x, hi, lo, s, j1, j2, i1, i2, imm10, imm11;
646
+ int to_thumb, is_call, to_plt, blx_bit = 1 << 12;
647
+ Section *plt;
648
+
649
+ /* weak reference */
650
+ if (sym->st_shndx == SHN_UNDEF &&
651
+ ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
652
+ break;
653
+
654
+ /* Get initial offset */
655
+ hi = (*(uint16_t *)ptr);
656
+ lo = (*(uint16_t *)(ptr+2));
657
+ s = (hi >> 10) & 1;
658
+ j1 = (lo >> 13) & 1;
659
+ j2 = (lo >> 11) & 1;
660
+ i1 = (j1 ^ s) ^ 1;
661
+ i2 = (j2 ^ s) ^ 1;
662
+ imm10 = hi & 0x3ff;
663
+ imm11 = lo & 0x7ff;
664
+ x = (s << 24) | (i1 << 23) | (i2 << 22) |
665
+ (imm10 << 12) | (imm11 << 1);
666
+ if (x & 0x01000000)
667
+ x -= 0x02000000;
668
+
669
+ /* Relocation infos */
670
+ to_thumb = val & 1;
671
+ plt = s1->plt;
672
+ to_plt = (val >= plt->sh_addr) &&
673
+ (val < plt->sh_addr + plt->data_offset);
674
+ is_call = (type == R_ARM_THM_CALL);
675
+
676
+ /* Compute final offset */
677
+ if (to_plt && !is_call) /* Point to 1st instr of Thumb stub */
678
+ x -= 4;
679
+ x += val - addr;
680
+ if (!to_thumb && is_call) {
681
+ blx_bit = 0; /* bl -> blx */
682
+ x = (x + 3) & -4; /* Compute offset from aligned PC */
683
+ }
684
+
685
+ /* Check that relocation is possible
686
+ * offset must not be out of range
687
+ * if target is to be entered in arm mode:
688
+ - bit 1 must not set
689
+ - instruction must be a call (bl) or a jump to PLT */
690
+ if (!to_thumb || x >= 0x1000000 || x < -0x1000000)
691
+ if (to_thumb || (val & 2) || (!is_call && !to_plt))
692
+ tcc_error("can't relocate value at %x",addr);
693
+
694
+ /* Compute and store final offset */
695
+ s = (x >> 24) & 1;
696
+ i1 = (x >> 23) & 1;
697
+ i2 = (x >> 22) & 1;
698
+ j1 = s ^ (i1 ^ 1);
699
+ j2 = s ^ (i2 ^ 1);
700
+ imm10 = (x >> 12) & 0x3ff;
701
+ imm11 = (x >> 1) & 0x7ff;
702
+ (*(uint16_t *)ptr) = (uint16_t) ((hi & 0xf800) |
703
+ (s << 10) | imm10);
704
+ (*(uint16_t *)(ptr+2)) = (uint16_t) ((lo & 0xc000) |
705
+ (j1 << 13) | blx_bit | (j2 << 11) |
706
+ imm11);
707
+ }
708
+ break;
709
+ case R_ARM_MOVT_ABS:
710
+ case R_ARM_MOVW_ABS_NC:
711
+ {
712
+ int x, imm4, imm12;
713
+ if (type == R_ARM_MOVT_ABS)
714
+ val >>= 16;
715
+ imm12 = val & 0xfff;
716
+ imm4 = (val >> 12) & 0xf;
717
+ x = (imm4 << 16) | imm12;
718
+ if (type == R_ARM_THM_MOVT_ABS)
719
+ *(int *)ptr |= x;
720
+ else
721
+ *(int *)ptr += x;
722
+ }
723
+ break;
724
+ case R_ARM_THM_MOVT_ABS:
725
+ case R_ARM_THM_MOVW_ABS_NC:
726
+ {
727
+ int x, i, imm4, imm3, imm8;
728
+ if (type == R_ARM_THM_MOVT_ABS)
729
+ val >>= 16;
730
+ imm8 = val & 0xff;
731
+ imm3 = (val >> 8) & 0x7;
732
+ i = (val >> 11) & 1;
733
+ imm4 = (val >> 12) & 0xf;
734
+ x = (imm3 << 28) | (imm8 << 16) | (i << 10) | imm4;
735
+ if (type == R_ARM_THM_MOVT_ABS)
736
+ *(int *)ptr |= x;
737
+ else
738
+ *(int *)ptr += x;
739
+ }
740
+ break;
741
+ case R_ARM_PREL31:
742
+ {
743
+ int x;
744
+ x = (*(int *)ptr) & 0x7fffffff;
745
+ (*(int *)ptr) &= 0x80000000;
746
+ x = (x * 2) / 2;
747
+ x += val - addr;
748
+ if((x^(x>>1))&0x40000000)
749
+ tcc_error("can't relocate value at %x",addr);
750
+ (*(int *)ptr) |= x & 0x7fffffff;
751
+ }
752
+ case R_ARM_ABS32:
753
+ *(int *)ptr += val;
754
+ break;
755
+ case R_ARM_REL32:
756
+ *(int *)ptr += val - addr;
757
+ break;
758
+ case R_ARM_BASE_PREL:
759
+ *(int *)ptr += s1->got->sh_addr - addr;
760
+ break;
761
+ case R_ARM_GOTOFF32:
762
+ *(int *)ptr += val - s1->got->sh_addr;
763
+ break;
764
+ case R_ARM_GOT_BREL:
765
+ /* we load the got offset */
766
+ *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
767
+ break;
768
+ case R_ARM_COPY:
769
+ break;
770
+ case R_ARM_V4BX:
771
+ /* trade Thumb support for ARMv4 support */
772
+ if ((0x0ffffff0 & *(int*)ptr) == 0x012FFF10)
773
+ *(int*)ptr ^= 0xE12FFF10 ^ 0xE1A0F000; /* BX Rm -> MOV PC, Rm */
774
+ break;
775
+ default:
776
+ fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
777
+ type, (unsigned)addr, ptr, (unsigned)val);
778
+ break;
779
+ #elif defined(TCC_TARGET_C67)
780
+ case R_C60_32:
781
+ *(int *)ptr += val;
782
+ break;
783
+ case R_C60LO16:
784
+ {
785
+ uint32_t orig;
786
+
787
+ /* put the low 16 bits of the absolute address */
788
+ // add to what is already there
789
+
790
+ orig = ((*(int *)(ptr )) >> 7) & 0xffff;
791
+ orig |= (((*(int *)(ptr+4)) >> 7) & 0xffff) << 16;
792
+
793
+ //patch both at once - assumes always in pairs Low - High
794
+
795
+ *(int *) ptr = (*(int *) ptr & (~(0xffff << 7)) ) | (((val+orig) & 0xffff) << 7);
796
+ *(int *)(ptr+4) = (*(int *)(ptr+4) & (~(0xffff << 7)) ) | ((((val+orig)>>16) & 0xffff) << 7);
797
+ }
798
+ break;
799
+ case R_C60HI16:
800
+ break;
801
+ default:
802
+ fprintf(stderr,"FIXME: handle reloc type %x at %x [%p] to %x\n",
803
+ type, (unsigned)addr, ptr, (unsigned)val);
804
+ break;
805
+ #elif defined(TCC_TARGET_X86_64)
806
+ case R_X86_64_64:
807
+ if (s1->output_type == TCC_OUTPUT_DLL) {
808
+ qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
809
+ qrel->r_addend = *(long long *)ptr + val;
810
+ qrel++;
811
+ }
812
+ *(long long *)ptr += val;
813
+ break;
814
+ case R_X86_64_32:
815
+ case R_X86_64_32S:
816
+ if (s1->output_type == TCC_OUTPUT_DLL) {
817
+ /* XXX: this logic may depend on TCC's codegen
818
+ now TCC uses R_X86_64_32 even for a 64bit pointer */
819
+ qrel->r_info = ELFW(R_INFO)(0, R_X86_64_RELATIVE);
820
+ qrel->r_addend = *(int *)ptr + val;
821
+ qrel++;
822
+ }
823
+ *(int *)ptr += val;
824
+ break;
825
+
826
+ case R_X86_64_PC32:
827
+ if (s1->output_type == TCC_OUTPUT_DLL) {
828
+ /* DLL relocation */
829
+ esym_index = s1->symtab_to_dynsym[sym_index];
830
+ if (esym_index) {
831
+ qrel->r_offset = rel->r_offset;
832
+ qrel->r_info = ELFW(R_INFO)(esym_index, R_X86_64_PC32);
833
+ qrel->r_addend = *(int *)ptr;
834
+ qrel++;
835
+ break;
836
+ }
837
+ }
838
+ /* fall through */
839
+ case R_X86_64_PLT32: {
840
+ long long diff;
841
+ diff = (long long)val - addr;
842
+ if (diff <= -2147483647 || diff > 2147483647) {
843
+ #ifdef TCC_HAS_RUNTIME_PLTGOT
844
+ /* XXX: naive support for over 32bit jump */
845
+ if (s1->output_type == TCC_OUTPUT_MEMORY) {
846
+ val = (add_jmp_table(s1, val - rel->r_addend) +
847
+ rel->r_addend);
848
+ diff = val - addr;
849
+ }
850
+ #endif
851
+ if (diff <= -2147483647 || diff > 2147483647) {
852
+ tcc_error("internal error: relocation failed");
853
+ }
854
+ }
855
+ *(int *)ptr += diff;
856
+ }
857
+ break;
858
+ case R_X86_64_GLOB_DAT:
859
+ case R_X86_64_JUMP_SLOT:
860
+ /* They don't need addend */
861
+ *(int *)ptr = val - rel->r_addend;
862
+ break;
863
+ case R_X86_64_GOTPCREL:
864
+ #ifdef TCC_HAS_RUNTIME_PLTGOT
865
+ if (s1->output_type == TCC_OUTPUT_MEMORY) {
866
+ val = add_got_table(s1, val - rel->r_addend) + rel->r_addend;
867
+ *(int *)ptr += val - addr;
868
+ break;
869
+ }
870
+ #endif
871
+ *(int *)ptr += (s1->got->sh_addr - addr +
872
+ s1->sym_attrs[sym_index].got_offset - 4);
873
+ break;
874
+ case R_X86_64_GOTTPOFF:
875
+ *(int *)ptr += val - s1->got->sh_addr;
876
+ break;
877
+ case R_X86_64_GOT32:
878
+ /* we load the got offset */
879
+ *(int *)ptr += s1->sym_attrs[sym_index].got_offset;
880
+ break;
881
+ #else
882
+ #error unsupported processor
883
+ #endif
884
+ }
885
+ }
886
+ /* if the relocation is allocated, we change its symbol table */
887
+ if (sr->sh_flags & SHF_ALLOC)
888
+ sr->link = s1->dynsym;
889
+ }
890
+
891
+ /* relocate relocation table in 'sr' */
892
+ static void relocate_rel(TCCState *s1, Section *sr)
893
+ {
894
+ Section *s;
895
+ ElfW_Rel *rel, *rel_end;
896
+
897
+ s = s1->sections[sr->sh_info];
898
+ rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
899
+ for(rel = (ElfW_Rel *)sr->data;
900
+ rel < rel_end;
901
+ rel++) {
902
+ rel->r_offset += s->sh_addr;
903
+ }
904
+ }
905
+
906
+ /* count the number of dynamic relocations so that we can reserve
907
+ their space */
908
+ static int prepare_dynamic_rel(TCCState *s1, Section *sr)
909
+ {
910
+ ElfW_Rel *rel, *rel_end;
911
+ int sym_index, esym_index, type, count;
912
+
913
+ count = 0;
914
+ rel_end = (ElfW_Rel *)(sr->data + sr->data_offset);
915
+ for(rel = (ElfW_Rel *)sr->data; rel < rel_end; rel++) {
916
+ sym_index = ELFW(R_SYM)(rel->r_info);
917
+ type = ELFW(R_TYPE)(rel->r_info);
918
+ switch(type) {
919
+ #if defined(TCC_TARGET_I386)
920
+ case R_386_32:
921
+ #elif defined(TCC_TARGET_X86_64)
922
+ case R_X86_64_32:
923
+ case R_X86_64_32S:
924
+ case R_X86_64_64:
925
+ #endif
926
+ count++;
927
+ break;
928
+ #if defined(TCC_TARGET_I386)
929
+ case R_386_PC32:
930
+ #elif defined(TCC_TARGET_X86_64)
931
+ case R_X86_64_PC32:
932
+ #endif
933
+ esym_index = s1->symtab_to_dynsym[sym_index];
934
+ if (esym_index)
935
+ count++;
936
+ break;
937
+ default:
938
+ break;
939
+ }
940
+ }
941
+ if (count) {
942
+ /* allocate the section */
943
+ sr->sh_flags |= SHF_ALLOC;
944
+ sr->sh_size = count * sizeof(ElfW_Rel);
945
+ }
946
+ return count;
947
+ }
948
+
949
+ static struct sym_attr *alloc_sym_attr(TCCState *s1, int index)
950
+ {
951
+ int n;
952
+ struct sym_attr *tab;
953
+
954
+ if (index >= s1->nb_sym_attrs) {
955
+ /* find immediately bigger power of 2 and reallocate array */
956
+ n = 1;
957
+ while (index >= n)
958
+ n *= 2;
959
+ tab = tcc_realloc(s1->sym_attrs, n * sizeof(*s1->sym_attrs));
960
+ s1->sym_attrs = tab;
961
+ memset(s1->sym_attrs + s1->nb_sym_attrs, 0,
962
+ (n - s1->nb_sym_attrs) * sizeof(*s1->sym_attrs));
963
+ s1->nb_sym_attrs = n;
964
+ }
965
+ return &s1->sym_attrs[index];
966
+ }
967
+
968
+ /* XXX: suppress that */
969
+ static void put32(unsigned char *p, uint32_t val)
970
+ {
971
+ p[0] = val;
972
+ p[1] = val >> 8;
973
+ p[2] = val >> 16;
974
+ p[3] = val >> 24;
975
+ }
976
+
977
+ #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_ARM) || \
978
+ defined(TCC_TARGET_X86_64)
979
+ static uint32_t get32(unsigned char *p)
980
+ {
981
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
982
+ }
983
+ #endif
984
+
985
+ static void build_got(TCCState *s1)
986
+ {
987
+ unsigned char *ptr;
988
+
989
+ /* if no got, then create it */
990
+ s1->got = new_section(s1, ".got", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
991
+ s1->got->sh_entsize = 4;
992
+ add_elf_sym(symtab_section, 0, 4, ELFW(ST_INFO)(STB_GLOBAL, STT_OBJECT),
993
+ 0, s1->got->sh_num, "_GLOBAL_OFFSET_TABLE_");
994
+ ptr = section_ptr_add(s1->got, 3 * PTR_SIZE);
995
+ #if PTR_SIZE == 4
996
+ /* keep space for _DYNAMIC pointer, if present */
997
+ put32(ptr, 0);
998
+ /* two dummy got entries */
999
+ put32(ptr + 4, 0);
1000
+ put32(ptr + 8, 0);
1001
+ #else
1002
+ /* keep space for _DYNAMIC pointer, if present */
1003
+ put32(ptr, 0);
1004
+ put32(ptr + 4, 0);
1005
+ /* two dummy got entries */
1006
+ put32(ptr + 8, 0);
1007
+ put32(ptr + 12, 0);
1008
+ put32(ptr + 16, 0);
1009
+ put32(ptr + 20, 0);
1010
+ #endif
1011
+ }
1012
+
1013
+ /* put a got entry corresponding to a symbol in symtab_section. 'size'
1014
+ and 'info' can be modifed if more precise info comes from the DLL */
1015
+ static void put_got_entry(TCCState *s1,
1016
+ int reloc_type, unsigned long size, int info,
1017
+ int sym_index)
1018
+ {
1019
+ int index;
1020
+ const char *name;
1021
+ ElfW(Sym) *sym;
1022
+ unsigned long offset;
1023
+ int *ptr;
1024
+
1025
+ if (!s1->got)
1026
+ build_got(s1);
1027
+
1028
+ /* if a got entry already exists for that symbol, no need to add one */
1029
+ if (sym_index < s1->nb_sym_attrs &&
1030
+ s1->sym_attrs[sym_index].got_offset)
1031
+ return;
1032
+
1033
+ alloc_sym_attr(s1, sym_index)->got_offset = s1->got->data_offset;
1034
+
1035
+ if (s1->dynsym) {
1036
+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1037
+ name = symtab_section->link->data + sym->st_name;
1038
+ offset = sym->st_value;
1039
+ #if defined(TCC_TARGET_I386) || defined(TCC_TARGET_X86_64)
1040
+ if (reloc_type ==
1041
+ #ifdef TCC_TARGET_X86_64
1042
+ R_X86_64_JUMP_SLOT
1043
+ #else
1044
+ R_386_JMP_SLOT
1045
+ #endif
1046
+ ) {
1047
+ Section *plt;
1048
+ uint8_t *p;
1049
+ int modrm;
1050
+
1051
+ #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1052
+ modrm = 0x25;
1053
+ #else
1054
+ /* if we build a DLL, we add a %ebx offset */
1055
+ if (s1->output_type == TCC_OUTPUT_DLL)
1056
+ modrm = 0xa3;
1057
+ else
1058
+ modrm = 0x25;
1059
+ #endif
1060
+
1061
+ /* add a PLT entry */
1062
+ plt = s1->plt;
1063
+ if (plt->data_offset == 0) {
1064
+ /* first plt entry */
1065
+ p = section_ptr_add(plt, 16);
1066
+ p[0] = 0xff; /* pushl got + PTR_SIZE */
1067
+ p[1] = modrm + 0x10;
1068
+ put32(p + 2, PTR_SIZE);
1069
+ p[6] = 0xff; /* jmp *(got + PTR_SIZE * 2) */
1070
+ p[7] = modrm;
1071
+ put32(p + 8, PTR_SIZE * 2);
1072
+ }
1073
+
1074
+ p = section_ptr_add(plt, 16);
1075
+ p[0] = 0xff; /* jmp *(got + x) */
1076
+ p[1] = modrm;
1077
+ put32(p + 2, s1->got->data_offset);
1078
+ p[6] = 0x68; /* push $xxx */
1079
+ put32(p + 7, (plt->data_offset - 32) >> 1);
1080
+ p[11] = 0xe9; /* jmp plt_start */
1081
+ put32(p + 12, -(plt->data_offset));
1082
+
1083
+ /* the symbol is modified so that it will be relocated to
1084
+ the PLT */
1085
+ #if !defined(TCC_OUTPUT_DLL_WITH_PLT)
1086
+ if (s1->output_type == TCC_OUTPUT_EXE)
1087
+ #endif
1088
+ offset = plt->data_offset - 16;
1089
+ }
1090
+ #elif defined(TCC_TARGET_ARM)
1091
+ if (reloc_type == R_ARM_JUMP_SLOT) {
1092
+ Section *plt;
1093
+ uint8_t *p;
1094
+
1095
+ /* if we build a DLL, we add a %ebx offset */
1096
+ if (s1->output_type == TCC_OUTPUT_DLL)
1097
+ tcc_error("DLLs unimplemented!");
1098
+
1099
+ /* add a PLT entry */
1100
+ plt = s1->plt;
1101
+ if (plt->data_offset == 0) {
1102
+ /* first plt entry */
1103
+ p = section_ptr_add(plt, 16);
1104
+ put32(p , 0xe52de004);
1105
+ put32(p + 4, 0xe59fe010);
1106
+ put32(p + 8, 0xe08fe00e);
1107
+ put32(p + 12, 0xe5bef008);
1108
+ }
1109
+
1110
+ if (s1->sym_attrs[sym_index].plt_thumb_stub) {
1111
+ p = section_ptr_add(plt, 20);
1112
+ put32(p , 0x4778); // bx pc
1113
+ put32(p+2, 0x46c0); // nop
1114
+ p += 4;
1115
+ } else
1116
+ p = section_ptr_add(plt, 16);
1117
+ put32(p , 0xe59fc004); // ldr ip, [pc, #4] // offset in GOT
1118
+ put32(p+4, 0xe08fc00c); // add ip, pc, ip // absolute address or offset
1119
+ put32(p+8, 0xe59cf000); // ldr pc, [ip] // load absolute address or load offset
1120
+ put32(p+12, s1->got->data_offset);
1121
+
1122
+ /* the symbol is modified so that it will be relocated to
1123
+ the PLT */
1124
+ if (s1->output_type == TCC_OUTPUT_EXE)
1125
+ offset = plt->data_offset - 16;
1126
+ }
1127
+ #elif defined(TCC_TARGET_C67)
1128
+ tcc_error("C67 got not implemented");
1129
+ #else
1130
+ #error unsupported CPU
1131
+ #endif
1132
+ index = put_elf_sym(s1->dynsym, offset,
1133
+ size, info, 0, sym->st_shndx, name);
1134
+ /* put a got entry */
1135
+ put_elf_reloc(s1->dynsym, s1->got,
1136
+ s1->got->data_offset,
1137
+ reloc_type, index);
1138
+ }
1139
+ ptr = section_ptr_add(s1->got, PTR_SIZE);
1140
+ *ptr = 0;
1141
+ }
1142
+
1143
+ /* build GOT and PLT entries */
1144
+ ST_FUNC void build_got_entries(TCCState *s1)
1145
+ {
1146
+ Section *s;
1147
+ ElfW_Rel *rel, *rel_end;
1148
+ ElfW(Sym) *sym;
1149
+ int i, type, reloc_type, sym_index;
1150
+
1151
+ for(i = 1; i < s1->nb_sections; i++) {
1152
+ s = s1->sections[i];
1153
+ if (s->sh_type != SHT_RELX)
1154
+ continue;
1155
+ /* no need to handle got relocations */
1156
+ if (s->link != symtab_section)
1157
+ continue;
1158
+ rel_end = (ElfW_Rel *)(s->data + s->data_offset);
1159
+ for(rel = (ElfW_Rel *)s->data;
1160
+ rel < rel_end;
1161
+ rel++) {
1162
+ type = ELFW(R_TYPE)(rel->r_info);
1163
+ switch(type) {
1164
+ #if defined(TCC_TARGET_I386)
1165
+ case R_386_GOT32:
1166
+ case R_386_GOTOFF:
1167
+ case R_386_GOTPC:
1168
+ case R_386_PLT32:
1169
+ if (!s1->got)
1170
+ build_got(s1);
1171
+ if (type == R_386_GOT32 || type == R_386_PLT32) {
1172
+ sym_index = ELFW(R_SYM)(rel->r_info);
1173
+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1174
+ /* look at the symbol got offset. If none, then add one */
1175
+ if (type == R_386_GOT32)
1176
+ reloc_type = R_386_GLOB_DAT;
1177
+ else
1178
+ reloc_type = R_386_JMP_SLOT;
1179
+ put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1180
+ sym_index);
1181
+ }
1182
+ break;
1183
+ #elif defined(TCC_TARGET_ARM)
1184
+ case R_ARM_GOT_BREL:
1185
+ case R_ARM_GOTOFF32:
1186
+ case R_ARM_BASE_PREL:
1187
+ case R_ARM_PLT32:
1188
+ if (!s1->got)
1189
+ build_got(s1);
1190
+ if (type == R_ARM_GOT_BREL || type == R_ARM_PLT32) {
1191
+ sym_index = ELFW(R_SYM)(rel->r_info);
1192
+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1193
+ /* look at the symbol got offset. If none, then add one */
1194
+ if (type == R_ARM_GOT_BREL)
1195
+ reloc_type = R_ARM_GLOB_DAT;
1196
+ else
1197
+ reloc_type = R_ARM_JUMP_SLOT;
1198
+ put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1199
+ sym_index);
1200
+ }
1201
+ break;
1202
+ #elif defined(TCC_TARGET_C67)
1203
+ case R_C60_GOT32:
1204
+ case R_C60_GOTOFF:
1205
+ case R_C60_GOTPC:
1206
+ case R_C60_PLT32:
1207
+ if (!s1->got)
1208
+ build_got(s1);
1209
+ if (type == R_C60_GOT32 || type == R_C60_PLT32) {
1210
+ sym_index = ELFW(R_SYM)(rel->r_info);
1211
+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1212
+ /* look at the symbol got offset. If none, then add one */
1213
+ if (type == R_C60_GOT32)
1214
+ reloc_type = R_C60_GLOB_DAT;
1215
+ else
1216
+ reloc_type = R_C60_JMP_SLOT;
1217
+ put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1218
+ sym_index);
1219
+ }
1220
+ break;
1221
+ #elif defined(TCC_TARGET_X86_64)
1222
+ case R_X86_64_GOT32:
1223
+ case R_X86_64_GOTTPOFF:
1224
+ case R_X86_64_GOTPCREL:
1225
+ case R_X86_64_PLT32:
1226
+ if (!s1->got)
1227
+ build_got(s1);
1228
+ if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL ||
1229
+ type == R_X86_64_PLT32) {
1230
+ sym_index = ELFW(R_SYM)(rel->r_info);
1231
+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1232
+ /* look at the symbol got offset. If none, then add one */
1233
+ if (type == R_X86_64_GOT32 || type == R_X86_64_GOTPCREL)
1234
+ reloc_type = R_X86_64_GLOB_DAT;
1235
+ else
1236
+ reloc_type = R_X86_64_JUMP_SLOT;
1237
+ put_got_entry(s1, reloc_type, sym->st_size, sym->st_info,
1238
+ sym_index);
1239
+ }
1240
+ break;
1241
+ #else
1242
+ #error unsupported CPU
1243
+ #endif
1244
+ default:
1245
+ break;
1246
+ }
1247
+ }
1248
+ }
1249
+ }
1250
+
1251
+ ST_FUNC Section *new_symtab(TCCState *s1,
1252
+ const char *symtab_name, int sh_type, int sh_flags,
1253
+ const char *strtab_name,
1254
+ const char *hash_name, int hash_sh_flags)
1255
+ {
1256
+ Section *symtab, *strtab, *hash;
1257
+ int *ptr, nb_buckets;
1258
+
1259
+ symtab = new_section(s1, symtab_name, sh_type, sh_flags);
1260
+ symtab->sh_entsize = sizeof(ElfW(Sym));
1261
+ strtab = new_section(s1, strtab_name, SHT_STRTAB, sh_flags);
1262
+ put_elf_str(strtab, "");
1263
+ symtab->link = strtab;
1264
+ put_elf_sym(symtab, 0, 0, 0, 0, 0, NULL);
1265
+
1266
+ nb_buckets = 1;
1267
+
1268
+ hash = new_section(s1, hash_name, SHT_HASH, hash_sh_flags);
1269
+ hash->sh_entsize = sizeof(int);
1270
+ symtab->hash = hash;
1271
+ hash->link = symtab;
1272
+
1273
+ ptr = section_ptr_add(hash, (2 + nb_buckets + 1) * sizeof(int));
1274
+ ptr[0] = nb_buckets;
1275
+ ptr[1] = 1;
1276
+ memset(ptr + 2, 0, (nb_buckets + 1) * sizeof(int));
1277
+ return symtab;
1278
+ }
1279
+
1280
+ /* put dynamic tag */
1281
+ static void put_dt(Section *dynamic, int dt, addr_t val)
1282
+ {
1283
+ ElfW(Dyn) *dyn;
1284
+ dyn = section_ptr_add(dynamic, sizeof(ElfW(Dyn)));
1285
+ dyn->d_tag = dt;
1286
+ dyn->d_un.d_val = val;
1287
+ }
1288
+
1289
+ static void add_init_array_defines(TCCState *s1, const char *section_name)
1290
+ {
1291
+ Section *s;
1292
+ long end_offset;
1293
+ char sym_start[1024];
1294
+ char sym_end[1024];
1295
+
1296
+ snprintf(sym_start, sizeof(sym_start), "__%s_start", section_name + 1);
1297
+ snprintf(sym_end, sizeof(sym_end), "__%s_end", section_name + 1);
1298
+
1299
+ s = find_section(s1, section_name);
1300
+ if (!s) {
1301
+ end_offset = 0;
1302
+ s = data_section;
1303
+ } else {
1304
+ end_offset = s->data_offset;
1305
+ }
1306
+
1307
+ add_elf_sym(symtab_section,
1308
+ 0, 0,
1309
+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1310
+ s->sh_num, sym_start);
1311
+ add_elf_sym(symtab_section,
1312
+ end_offset, 0,
1313
+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1314
+ s->sh_num, sym_end);
1315
+ }
1316
+
1317
+ ST_FUNC void tcc_add_bcheck(TCCState *s1)
1318
+ {
1319
+ #ifdef CONFIG_TCC_BCHECK
1320
+ unsigned long *ptr;
1321
+ Section *init_section;
1322
+ unsigned char *pinit;
1323
+ int sym_index;
1324
+
1325
+ if (0 == s1->do_bounds_check)
1326
+ return;
1327
+
1328
+ /* XXX: add an object file to do that */
1329
+ ptr = section_ptr_add(bounds_section, sizeof(unsigned long));
1330
+ *ptr = 0;
1331
+ add_elf_sym(symtab_section, 0, 0,
1332
+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1333
+ bounds_section->sh_num, "__bounds_start");
1334
+ #ifdef TCC_TARGET_I386
1335
+ if (s1->output_type != TCC_OUTPUT_MEMORY) {
1336
+ /* add 'call __bound_init()' in .init section */
1337
+ init_section = find_section(s1, ".init");
1338
+ pinit = section_ptr_add(init_section, 5);
1339
+ pinit[0] = 0xe8;
1340
+ put32(pinit + 1, -4);
1341
+ sym_index = find_elf_sym(symtab_section, "__bound_init");
1342
+ put_elf_reloc(symtab_section, init_section,
1343
+ init_section->data_offset - 4, R_386_PC32, sym_index);
1344
+ }
1345
+ #endif
1346
+ #endif
1347
+ }
1348
+
1349
+ static inline int tcc_add_support(TCCState *s1, const char *filename)
1350
+ {
1351
+ char buf[1024];
1352
+ snprintf(buf, sizeof(buf), "%s/%s", s1->tcc_lib_path, filename);
1353
+ return tcc_add_file(s1, buf);
1354
+ }
1355
+
1356
+ /* add tcc runtime libraries */
1357
+ ST_FUNC void tcc_add_runtime(TCCState *s1)
1358
+ {
1359
+ tcc_add_bcheck(s1);
1360
+
1361
+ /* add libc */
1362
+ if (!s1->nostdlib) {
1363
+ tcc_add_library(s1, "c");
1364
+ #ifdef CONFIG_USE_LIBGCC
1365
+ tcc_add_file(s1, TCC_LIBGCC);
1366
+ #elif !defined WITHOUT_LIBTCC
1367
+ tcc_add_support(s1, "libtcc1.a");
1368
+ #endif
1369
+ /* add crt end if not memory output */
1370
+ if (s1->output_type != TCC_OUTPUT_MEMORY)
1371
+ tcc_add_crt(s1, "crtn.o");
1372
+ }
1373
+ }
1374
+
1375
+ /* add various standard linker symbols (must be done after the
1376
+ sections are filled (for example after allocating common
1377
+ symbols)) */
1378
+ ST_FUNC void tcc_add_linker_symbols(TCCState *s1)
1379
+ {
1380
+ char buf[1024];
1381
+ int i;
1382
+ Section *s;
1383
+
1384
+ add_elf_sym(symtab_section,
1385
+ text_section->data_offset, 0,
1386
+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1387
+ text_section->sh_num, "_etext");
1388
+ add_elf_sym(symtab_section,
1389
+ data_section->data_offset, 0,
1390
+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1391
+ data_section->sh_num, "_edata");
1392
+ add_elf_sym(symtab_section,
1393
+ bss_section->data_offset, 0,
1394
+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1395
+ bss_section->sh_num, "_end");
1396
+ /* horrible new standard ldscript defines */
1397
+ add_init_array_defines(s1, ".preinit_array");
1398
+ add_init_array_defines(s1, ".init_array");
1399
+ add_init_array_defines(s1, ".fini_array");
1400
+
1401
+ /* add start and stop symbols for sections whose name can be
1402
+ expressed in C */
1403
+ for(i = 1; i < s1->nb_sections; i++) {
1404
+ s = s1->sections[i];
1405
+ if (s->sh_type == SHT_PROGBITS &&
1406
+ (s->sh_flags & SHF_ALLOC)) {
1407
+ const char *p;
1408
+ int ch;
1409
+
1410
+ /* check if section name can be expressed in C */
1411
+ p = s->name;
1412
+ for(;;) {
1413
+ ch = *p;
1414
+ if (!ch)
1415
+ break;
1416
+ if (!isid(ch) && !isnum(ch))
1417
+ goto next_sec;
1418
+ p++;
1419
+ }
1420
+ snprintf(buf, sizeof(buf), "__start_%s", s->name);
1421
+ add_elf_sym(symtab_section,
1422
+ 0, 0,
1423
+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1424
+ s->sh_num, buf);
1425
+ snprintf(buf, sizeof(buf), "__stop_%s", s->name);
1426
+ add_elf_sym(symtab_section,
1427
+ s->data_offset, 0,
1428
+ ELFW(ST_INFO)(STB_GLOBAL, STT_NOTYPE), 0,
1429
+ s->sh_num, buf);
1430
+ }
1431
+ next_sec: ;
1432
+ }
1433
+ }
1434
+
1435
+ static void tcc_output_binary(TCCState *s1, FILE *f,
1436
+ const int *section_order)
1437
+ {
1438
+ Section *s;
1439
+ int i, offset, size;
1440
+
1441
+ offset = 0;
1442
+ for(i=1;i<s1->nb_sections;i++) {
1443
+ s = s1->sections[section_order[i]];
1444
+ if (s->sh_type != SHT_NOBITS &&
1445
+ (s->sh_flags & SHF_ALLOC)) {
1446
+ while (offset < s->sh_offset) {
1447
+ fputc(0, f);
1448
+ offset++;
1449
+ }
1450
+ size = s->sh_size;
1451
+ fwrite(s->data, 1, size, f);
1452
+ offset += size;
1453
+ }
1454
+ }
1455
+ }
1456
+
1457
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1458
+ #define HAVE_PHDR 1
1459
+ #define EXTRA_RELITEMS 14
1460
+
1461
+ /* move the relocation value from .dynsym to .got */
1462
+ void patch_dynsym_undef(TCCState *s1, Section *s)
1463
+ {
1464
+ uint32_t *gotd = (void *)s1->got->data;
1465
+ ElfW(Sym) *sym, *sym_end;
1466
+
1467
+ gotd += 3; // dummy entries in .got
1468
+ /* relocate symbols in .dynsym */
1469
+ sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1470
+ for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++) {
1471
+ if (sym->st_shndx == SHN_UNDEF) {
1472
+ *gotd++ = sym->st_value + 6; // XXX 6 is magic ?
1473
+ sym->st_value = 0;
1474
+ }
1475
+ }
1476
+ }
1477
+ #else
1478
+ #define HAVE_PHDR 0
1479
+ #define EXTRA_RELITEMS 9
1480
+
1481
+ /* zero plt offsets of weak symbols in .dynsym */
1482
+ void patch_dynsym_undef(TCCState *s1, Section *s)
1483
+ {
1484
+ ElfW(Sym) *sym, *sym_end;
1485
+
1486
+ sym_end = (ElfW(Sym) *)(s->data + s->data_offset);
1487
+ for (sym = (ElfW(Sym) *)s->data + 1; sym < sym_end; sym++)
1488
+ if (sym->st_shndx == SHN_UNDEF && ELFW(ST_BIND)(sym->st_info) == STB_WEAK)
1489
+ sym->st_value = 0;
1490
+ }
1491
+ #endif
1492
+
1493
+ ST_FUNC void fill_got_entry(TCCState *s1, ElfW_Rel *rel)
1494
+ {
1495
+ int sym_index = ELFW(R_SYM) (rel->r_info);
1496
+ ElfW(Sym) *sym = &((ElfW(Sym) *) symtab_section->data)[sym_index];
1497
+ unsigned long offset;
1498
+
1499
+ if (sym_index >= s1->nb_sym_attrs)
1500
+ return;
1501
+ offset = s1->sym_attrs[sym_index].got_offset;
1502
+ section_reserve(s1->got, offset + PTR_SIZE);
1503
+ #ifdef TCC_TARGET_X86_64
1504
+ /* only works for x86-64 */
1505
+ put32(s1->got->data + offset + 4, sym->st_value >> 32);
1506
+ #endif
1507
+ put32(s1->got->data + offset, sym->st_value & 0xffffffff);
1508
+ }
1509
+
1510
+ ST_FUNC void fill_got(TCCState *s1)
1511
+ {
1512
+ Section *s;
1513
+ ElfW_Rel *rel, *rel_end;
1514
+ int i;
1515
+
1516
+ for(i = 1; i < s1->nb_sections; i++) {
1517
+ s = s1->sections[i];
1518
+ if (s->sh_type != SHT_RELX)
1519
+ continue;
1520
+ /* no need to handle got relocations */
1521
+ if (s->link != symtab_section)
1522
+ continue;
1523
+ rel_end = (ElfW_Rel *) (s->data + s->data_offset);
1524
+ for(rel = (ElfW_Rel *) s->data; rel < rel_end; rel++) {
1525
+ switch (ELFW(R_TYPE) (rel->r_info)) {
1526
+ case R_X86_64_GOT32:
1527
+ case R_X86_64_GOTPCREL:
1528
+ case R_X86_64_PLT32:
1529
+ fill_got_entry(s1, rel);
1530
+ break;
1531
+ }
1532
+ }
1533
+ }
1534
+ }
1535
+
1536
+
1537
+ /* output an ELF file */
1538
+ /* XXX: suppress unneeded sections */
1539
+ static int elf_output_file(TCCState *s1, const char *filename)
1540
+ {
1541
+ ElfW(Ehdr) ehdr;
1542
+ FILE *f;
1543
+ int fd, mode, ret;
1544
+ int *section_order;
1545
+ int shnum, i, phnum, file_offset, offset, size, j, sh_order_index, k;
1546
+ long long tmp;
1547
+ addr_t addr;
1548
+ Section *strsec, *s;
1549
+ ElfW(Shdr) shdr, *sh;
1550
+ ElfW(Phdr) *phdr, *ph;
1551
+ Section *interp, *dynamic, *dynstr;
1552
+ unsigned long saved_dynamic_data_offset;
1553
+ ElfW(Sym) *sym;
1554
+ int type, file_type;
1555
+ addr_t rel_addr, rel_size;
1556
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1557
+ addr_t bss_addr, bss_size;
1558
+ #endif
1559
+
1560
+ file_type = s1->output_type;
1561
+ s1->nb_errors = 0;
1562
+
1563
+ if (file_type != TCC_OUTPUT_OBJ) {
1564
+ tcc_add_runtime(s1);
1565
+ }
1566
+
1567
+ phdr = NULL;
1568
+ section_order = NULL;
1569
+ interp = NULL;
1570
+ dynamic = NULL;
1571
+ dynstr = NULL; /* avoid warning */
1572
+ saved_dynamic_data_offset = 0; /* avoid warning */
1573
+
1574
+ if (file_type != TCC_OUTPUT_OBJ) {
1575
+ relocate_common_syms();
1576
+
1577
+ tcc_add_linker_symbols(s1);
1578
+
1579
+ if (!s1->static_link) {
1580
+ const char *name;
1581
+ int sym_index, index;
1582
+ ElfW(Sym) *esym, *sym_end;
1583
+
1584
+ if (file_type == TCC_OUTPUT_EXE) {
1585
+ char *ptr;
1586
+ /* allow override the dynamic loader */
1587
+ const char *elfint = getenv("LD_SO");
1588
+ if (elfint == NULL)
1589
+ elfint = CONFIG_TCC_ELFINTERP;
1590
+ /* add interpreter section only if executable */
1591
+ interp = new_section(s1, ".interp", SHT_PROGBITS, SHF_ALLOC);
1592
+ interp->sh_addralign = 1;
1593
+ ptr = section_ptr_add(interp, 1+strlen(elfint));
1594
+ strcpy(ptr, elfint);
1595
+ }
1596
+
1597
+ /* add dynamic symbol table */
1598
+ s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
1599
+ ".dynstr",
1600
+ ".hash", SHF_ALLOC);
1601
+ dynstr = s1->dynsym->link;
1602
+
1603
+ /* add dynamic section */
1604
+ dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
1605
+ SHF_ALLOC | SHF_WRITE);
1606
+ dynamic->link = dynstr;
1607
+ dynamic->sh_entsize = sizeof(ElfW(Dyn));
1608
+
1609
+ /* add PLT */
1610
+ s1->plt = new_section(s1, ".plt", SHT_PROGBITS,
1611
+ SHF_ALLOC | SHF_EXECINSTR);
1612
+ s1->plt->sh_entsize = 4;
1613
+
1614
+ build_got(s1);
1615
+
1616
+ /* scan for undefined symbols and see if they are in the
1617
+ dynamic symbols. If a symbol STT_FUNC or STT_GNU_IFUNC
1618
+ is found, then we add it in the PLT. If a symbol
1619
+ STT_OBJECT is found, we add it in the .bss section with
1620
+ a suitable relocation */
1621
+ sym_end = (ElfW(Sym) *)(symtab_section->data +
1622
+ symtab_section->data_offset);
1623
+ if (file_type == TCC_OUTPUT_EXE) {
1624
+ for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1625
+ sym < sym_end;
1626
+ sym++) {
1627
+ if (sym->st_shndx == SHN_UNDEF) {
1628
+ name = symtab_section->link->data + sym->st_name;
1629
+ sym_index = find_elf_sym(s1->dynsymtab_section, name);
1630
+ if (sym_index) {
1631
+ esym = &((ElfW(Sym) *)s1->dynsymtab_section->data)[sym_index];
1632
+ type = ELFW(ST_TYPE)(esym->st_info);
1633
+ if ((type == STT_FUNC) || (type == STT_GNU_IFUNC)) {
1634
+ /* Indirect functions shall have STT_FUNC type
1635
+ * in executable dynsym section. Indeed, a dlsym
1636
+ * call following a lazy resolution would pick
1637
+ * the symbol value from the executable dynsym
1638
+ * entry which would contain the address of the
1639
+ * function wanted by the caller of dlsym
1640
+ * instead of the address of the function that
1641
+ * would return that address */
1642
+ put_got_entry(s1, R_JMP_SLOT, esym->st_size,
1643
+ ELFW(ST_INFO)(STB_GLOBAL,STT_FUNC),
1644
+ sym - (ElfW(Sym) *)symtab_section->data);
1645
+ } else if (type == STT_OBJECT) {
1646
+ unsigned long offset;
1647
+ ElfW(Sym) *dynsym, *dynsym_end;
1648
+ offset = bss_section->data_offset;
1649
+ /* XXX: which alignment ? */
1650
+ offset = (offset + 16 - 1) & -16;
1651
+ index = put_elf_sym(s1->dynsym, offset, esym->st_size,
1652
+ esym->st_info, 0,
1653
+ bss_section->sh_num, name);
1654
+ // Ensure R_COPY works for weak symbol aliases
1655
+ if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1656
+ dynsym_end = (ElfW(Sym) *)
1657
+ (s1->dynsymtab_section->data +
1658
+ s1->dynsymtab_section->data_offset);
1659
+ for(dynsym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1660
+ dynsym < dynsym_end; dynsym++) {
1661
+ if ((dynsym->st_value == esym->st_value)
1662
+ && (ELFW(ST_BIND)(dynsym->st_info) == STB_GLOBAL)) {
1663
+ char *dynname;
1664
+ dynname = s1->dynsymtab_section->link->data
1665
+ + dynsym->st_name;
1666
+ put_elf_sym(s1->dynsym, offset,
1667
+ dynsym->st_size,
1668
+ dynsym->st_info, 0,
1669
+ bss_section->sh_num,
1670
+ dynname);
1671
+ break;
1672
+ }
1673
+ }
1674
+ }
1675
+ put_elf_reloc(s1->dynsym, bss_section,
1676
+ offset, R_COPY, index);
1677
+ offset += esym->st_size;
1678
+ bss_section->data_offset = offset;
1679
+ }
1680
+ } else {
1681
+ /* STB_WEAK undefined symbols are accepted */
1682
+ /* XXX: _fp_hw seems to be part of the ABI, so we ignore
1683
+ it */
1684
+ if (ELFW(ST_BIND)(sym->st_info) == STB_WEAK ||
1685
+ !strcmp(name, "_fp_hw")) {
1686
+ } else {
1687
+ tcc_error_noabort("undefined symbol '%s'", name);
1688
+ }
1689
+ }
1690
+ } else if (s1->rdynamic &&
1691
+ ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1692
+ /* if -rdynamic option, then export all non
1693
+ local symbols */
1694
+ name = symtab_section->link->data + sym->st_name;
1695
+ put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1696
+ sym->st_info, 0,
1697
+ sym->st_shndx, name);
1698
+ }
1699
+ }
1700
+
1701
+ if (s1->nb_errors)
1702
+ goto fail;
1703
+
1704
+ /* now look at unresolved dynamic symbols and export
1705
+ corresponding symbol */
1706
+ sym_end = (ElfW(Sym) *)(s1->dynsymtab_section->data +
1707
+ s1->dynsymtab_section->data_offset);
1708
+ for(esym = (ElfW(Sym) *)s1->dynsymtab_section->data + 1;
1709
+ esym < sym_end;
1710
+ esym++) {
1711
+ if (esym->st_shndx == SHN_UNDEF) {
1712
+ name = s1->dynsymtab_section->link->data + esym->st_name;
1713
+ sym_index = find_elf_sym(symtab_section, name);
1714
+ if (sym_index) {
1715
+ /* XXX: avoid adding a symbol if already
1716
+ present because of -rdynamic ? */
1717
+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1718
+ put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1719
+ sym->st_info, 0,
1720
+ sym->st_shndx, name);
1721
+ } else {
1722
+ if (ELFW(ST_BIND)(esym->st_info) == STB_WEAK) {
1723
+ /* weak symbols can stay undefined */
1724
+ } else {
1725
+ tcc_warning("undefined dynamic symbol '%s'", name);
1726
+ }
1727
+ }
1728
+ }
1729
+ }
1730
+ } else {
1731
+ int nb_syms;
1732
+ /* shared library case : we simply export all the global symbols */
1733
+ nb_syms = symtab_section->data_offset / sizeof(ElfW(Sym));
1734
+ s1->symtab_to_dynsym = tcc_mallocz(sizeof(int) * nb_syms);
1735
+ for(sym = (ElfW(Sym) *)symtab_section->data + 1;
1736
+ sym < sym_end;
1737
+ sym++) {
1738
+ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
1739
+ #if defined(TCC_OUTPUT_DLL_WITH_PLT)
1740
+ if ((ELFW(ST_TYPE)(sym->st_info) == STT_FUNC ||
1741
+ ELFW(ST_TYPE)(sym->st_info) == STT_GNU_IFUNC)
1742
+ && sym->st_shndx == SHN_UNDEF) {
1743
+ int visibility = ELFW(ST_BIND)(sym->st_info);
1744
+ put_got_entry(s1, R_JMP_SLOT, sym->st_size,
1745
+ ELFW(ST_INFO)(visibility,STT_FUNC),
1746
+ sym - (ElfW(Sym) *)symtab_section->data);
1747
+ }
1748
+ else if (ELFW(ST_TYPE)(sym->st_info) == STT_OBJECT) {
1749
+ put_got_entry(s1, R_X86_64_GLOB_DAT, sym->st_size,
1750
+ sym->st_info,
1751
+ sym - (ElfW(Sym) *)symtab_section->data);
1752
+ }
1753
+ else
1754
+ #endif
1755
+ {
1756
+ name = symtab_section->link->data + sym->st_name;
1757
+ index = put_elf_sym(s1->dynsym, sym->st_value, sym->st_size,
1758
+ sym->st_info, 0,
1759
+ sym->st_shndx, name);
1760
+ s1->symtab_to_dynsym[sym -
1761
+ (ElfW(Sym) *)symtab_section->data] =
1762
+ index;
1763
+ }
1764
+ }
1765
+ }
1766
+ }
1767
+
1768
+ build_got_entries(s1);
1769
+
1770
+ /* add a list of needed dlls */
1771
+ for(i = 0; i < s1->nb_loaded_dlls; i++) {
1772
+ DLLReference *dllref = s1->loaded_dlls[i];
1773
+ if (dllref->level == 0)
1774
+ put_dt(dynamic, DT_NEEDED, put_elf_str(dynstr, dllref->name));
1775
+ }
1776
+
1777
+ if (s1->rpath)
1778
+ put_dt(dynamic, DT_RPATH, put_elf_str(dynstr, s1->rpath));
1779
+
1780
+ /* XXX: currently, since we do not handle PIC code, we
1781
+ must relocate the readonly segments */
1782
+ if (file_type == TCC_OUTPUT_DLL) {
1783
+ if (s1->soname)
1784
+ put_dt(dynamic, DT_SONAME, put_elf_str(dynstr, s1->soname));
1785
+ put_dt(dynamic, DT_TEXTREL, 0);
1786
+ }
1787
+
1788
+ if (s1->symbolic)
1789
+ put_dt(dynamic, DT_SYMBOLIC, 0);
1790
+
1791
+ /* add necessary space for other entries */
1792
+ saved_dynamic_data_offset = dynamic->data_offset;
1793
+ dynamic->data_offset += sizeof(ElfW(Dyn)) * EXTRA_RELITEMS;
1794
+ } else {
1795
+ /* still need to build got entries in case of static link */
1796
+ build_got_entries(s1);
1797
+ }
1798
+ }
1799
+
1800
+ memset(&ehdr, 0, sizeof(ehdr));
1801
+
1802
+ /* we add a section for symbols */
1803
+ strsec = new_section(s1, ".shstrtab", SHT_STRTAB, 0);
1804
+ put_elf_str(strsec, "");
1805
+
1806
+ /* compute number of sections */
1807
+ shnum = s1->nb_sections;
1808
+
1809
+ /* this array is used to reorder sections in the output file */
1810
+ section_order = tcc_malloc(sizeof(int) * shnum);
1811
+ section_order[0] = 0;
1812
+ sh_order_index = 1;
1813
+
1814
+ /* compute number of program headers */
1815
+ switch(file_type) {
1816
+ default:
1817
+ case TCC_OUTPUT_OBJ:
1818
+ phnum = 0;
1819
+ break;
1820
+ case TCC_OUTPUT_EXE:
1821
+ if (!s1->static_link)
1822
+ phnum = 4 + HAVE_PHDR;
1823
+ else
1824
+ phnum = 2;
1825
+ break;
1826
+ case TCC_OUTPUT_DLL:
1827
+ phnum = 3;
1828
+ break;
1829
+ }
1830
+
1831
+ /* allocate strings for section names and decide if an unallocated
1832
+ section should be output */
1833
+ /* NOTE: the strsec section comes last, so its size is also
1834
+ correct ! */
1835
+ for(i = 1; i < s1->nb_sections; i++) {
1836
+ s = s1->sections[i];
1837
+ s->sh_name = put_elf_str(strsec, s->name);
1838
+ #if 0 //gr
1839
+ printf("section: f=%08x t=%08x i=%08x %s %s\n",
1840
+ s->sh_flags,
1841
+ s->sh_type,
1842
+ s->sh_info,
1843
+ s->name,
1844
+ s->reloc ? s->reloc->name : "n"
1845
+ );
1846
+ #endif
1847
+ /* when generating a DLL, we include relocations but we may
1848
+ patch them */
1849
+ if (file_type == TCC_OUTPUT_DLL &&
1850
+ s->sh_type == SHT_RELX &&
1851
+ !(s->sh_flags & SHF_ALLOC)) {
1852
+ /* //gr: avoid bogus relocs for empty (debug) sections */
1853
+ if (s1->sections[s->sh_info]->sh_flags & SHF_ALLOC)
1854
+ prepare_dynamic_rel(s1, s);
1855
+ else if (s1->do_debug)
1856
+ s->sh_size = s->data_offset;
1857
+ } else if (s1->do_debug ||
1858
+ file_type == TCC_OUTPUT_OBJ ||
1859
+ (s->sh_flags & SHF_ALLOC) ||
1860
+ i == (s1->nb_sections - 1)) {
1861
+ /* we output all sections if debug or object file */
1862
+ s->sh_size = s->data_offset;
1863
+ }
1864
+ }
1865
+
1866
+ /* allocate program segment headers */
1867
+ phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
1868
+
1869
+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1870
+ file_offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
1871
+ } else {
1872
+ file_offset = 0;
1873
+ }
1874
+ if (phnum > 0) {
1875
+ /* compute section to program header mapping */
1876
+ if (s1->has_text_addr) {
1877
+ int a_offset, p_offset;
1878
+ addr = s1->text_addr;
1879
+ /* we ensure that (addr % ELF_PAGE_SIZE) == file_offset %
1880
+ ELF_PAGE_SIZE */
1881
+ a_offset = (int) (addr & (s1->section_align - 1));
1882
+ p_offset = file_offset & (s1->section_align - 1);
1883
+ if (a_offset < p_offset)
1884
+ a_offset += s1->section_align;
1885
+ file_offset += (a_offset - p_offset);
1886
+ } else {
1887
+ if (file_type == TCC_OUTPUT_DLL)
1888
+ addr = 0;
1889
+ else
1890
+ addr = ELF_START_ADDR;
1891
+ /* compute address after headers */
1892
+ addr += (file_offset & (s1->section_align - 1));
1893
+ }
1894
+
1895
+ /* dynamic relocation table information, for .dynamic section */
1896
+ rel_size = 0;
1897
+ rel_addr = 0;
1898
+
1899
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1900
+ bss_addr = bss_size = 0;
1901
+ #endif
1902
+ /* leave one program header for the program interpreter */
1903
+ ph = &phdr[0];
1904
+ if (interp)
1905
+ ph += 1 + HAVE_PHDR;
1906
+
1907
+ for(j = 0; j < 2; j++) {
1908
+ ph->p_type = PT_LOAD;
1909
+ if (j == 0)
1910
+ ph->p_flags = PF_R | PF_X;
1911
+ else
1912
+ ph->p_flags = PF_R | PF_W;
1913
+ ph->p_align = s1->section_align;
1914
+
1915
+ /* we do the following ordering: interp, symbol tables,
1916
+ relocations, progbits, nobits */
1917
+ /* XXX: do faster and simpler sorting */
1918
+ for(k = 0; k < 5; k++) {
1919
+ for(i = 1; i < s1->nb_sections; i++) {
1920
+ s = s1->sections[i];
1921
+ /* compute if section should be included */
1922
+ if (j == 0) {
1923
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1924
+ SHF_ALLOC)
1925
+ continue;
1926
+ } else {
1927
+ if ((s->sh_flags & (SHF_ALLOC | SHF_WRITE)) !=
1928
+ (SHF_ALLOC | SHF_WRITE))
1929
+ continue;
1930
+ }
1931
+ if (s == interp) {
1932
+ if (k != 0)
1933
+ continue;
1934
+ } else if (s->sh_type == SHT_DYNSYM ||
1935
+ s->sh_type == SHT_STRTAB ||
1936
+ s->sh_type == SHT_HASH) {
1937
+ if (k != 1)
1938
+ continue;
1939
+ } else if (s->sh_type == SHT_RELX) {
1940
+ if (k != 2)
1941
+ continue;
1942
+ } else if (s->sh_type == SHT_NOBITS) {
1943
+ if (k != 4)
1944
+ continue;
1945
+ } else {
1946
+ if (k != 3)
1947
+ continue;
1948
+ }
1949
+ section_order[sh_order_index++] = i;
1950
+
1951
+ /* section matches: we align it and add its size */
1952
+ tmp = addr;
1953
+ addr = (addr + s->sh_addralign - 1) &
1954
+ ~(s->sh_addralign - 1);
1955
+ file_offset += (int) ( addr - tmp );
1956
+ s->sh_offset = file_offset;
1957
+ s->sh_addr = addr;
1958
+
1959
+ /* update program header infos */
1960
+ if (ph->p_offset == 0) {
1961
+ ph->p_offset = file_offset;
1962
+ ph->p_vaddr = addr;
1963
+ ph->p_paddr = ph->p_vaddr;
1964
+ }
1965
+ /* update dynamic relocation infos */
1966
+ if (s->sh_type == SHT_RELX) {
1967
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
1968
+ if (!strcmp(strsec->data + s->sh_name, ".rel.got")) { // rel_size == 0) {
1969
+ rel_addr = addr;
1970
+ rel_size += s->sh_size; // XXX only first rel.
1971
+ }
1972
+ if (!strcmp(strsec->data + s->sh_name, ".rel.bss")) { // rel_size == 0) {
1973
+ bss_addr = addr;
1974
+ bss_size = s->sh_size; // XXX only first rel.
1975
+ }
1976
+ #else
1977
+ if (rel_size == 0)
1978
+ rel_addr = addr;
1979
+ rel_size += s->sh_size;
1980
+ #endif
1981
+ }
1982
+ addr += s->sh_size;
1983
+ if (s->sh_type != SHT_NOBITS)
1984
+ file_offset += s->sh_size;
1985
+ }
1986
+ }
1987
+ ph->p_filesz = file_offset - ph->p_offset;
1988
+ ph->p_memsz = addr - ph->p_vaddr;
1989
+ ph++;
1990
+ if (j == 0) {
1991
+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
1992
+ /* if in the middle of a page, we duplicate the page in
1993
+ memory so that one copy is RX and the other is RW */
1994
+ if ((addr & (s1->section_align - 1)) != 0)
1995
+ addr += s1->section_align;
1996
+ } else {
1997
+ addr = (addr + s1->section_align - 1) & ~(s1->section_align - 1);
1998
+ file_offset = (file_offset + s1->section_align - 1) &
1999
+ ~(s1->section_align - 1);
2000
+ }
2001
+ }
2002
+ }
2003
+
2004
+ /* if interpreter, then add corresponing program header */
2005
+ if (interp) {
2006
+ ph = &phdr[0];
2007
+
2008
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2009
+ {
2010
+ int len = phnum * sizeof(ElfW(Phdr));
2011
+
2012
+ ph->p_type = PT_PHDR;
2013
+ ph->p_offset = sizeof(ElfW(Ehdr));
2014
+ ph->p_vaddr = interp->sh_addr - len;
2015
+ ph->p_paddr = ph->p_vaddr;
2016
+ ph->p_filesz = ph->p_memsz = len;
2017
+ ph->p_flags = PF_R | PF_X;
2018
+ ph->p_align = 4; // interp->sh_addralign;
2019
+ ph++;
2020
+ }
2021
+ #endif
2022
+
2023
+ ph->p_type = PT_INTERP;
2024
+ ph->p_offset = interp->sh_offset;
2025
+ ph->p_vaddr = interp->sh_addr;
2026
+ ph->p_paddr = ph->p_vaddr;
2027
+ ph->p_filesz = interp->sh_size;
2028
+ ph->p_memsz = interp->sh_size;
2029
+ ph->p_flags = PF_R;
2030
+ ph->p_align = interp->sh_addralign;
2031
+ }
2032
+
2033
+ /* if dynamic section, then add corresponing program header */
2034
+ if (dynamic) {
2035
+ ElfW(Sym) *sym_end;
2036
+
2037
+ ph = &phdr[phnum - 1];
2038
+
2039
+ ph->p_type = PT_DYNAMIC;
2040
+ ph->p_offset = dynamic->sh_offset;
2041
+ ph->p_vaddr = dynamic->sh_addr;
2042
+ ph->p_paddr = ph->p_vaddr;
2043
+ ph->p_filesz = dynamic->sh_size;
2044
+ ph->p_memsz = dynamic->sh_size;
2045
+ ph->p_flags = PF_R | PF_W;
2046
+ ph->p_align = dynamic->sh_addralign;
2047
+
2048
+ /* put GOT dynamic section address */
2049
+ put32(s1->got->data, dynamic->sh_addr);
2050
+
2051
+ /* relocate the PLT */
2052
+ if (file_type == TCC_OUTPUT_EXE
2053
+ #if defined(TCC_OUTPUT_DLL_WITH_PLT)
2054
+ || file_type == TCC_OUTPUT_DLL
2055
+ #endif
2056
+ ) {
2057
+ uint8_t *p, *p_end;
2058
+
2059
+ p = s1->plt->data;
2060
+ p_end = p + s1->plt->data_offset;
2061
+ if (p < p_end) {
2062
+ #if defined(TCC_TARGET_I386)
2063
+ put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2064
+ put32(p + 8, get32(p + 8) + s1->got->sh_addr);
2065
+ p += 16;
2066
+ while (p < p_end) {
2067
+ put32(p + 2, get32(p + 2) + s1->got->sh_addr);
2068
+ p += 16;
2069
+ }
2070
+ #elif defined(TCC_TARGET_X86_64)
2071
+ int x = s1->got->sh_addr - s1->plt->sh_addr - 6;
2072
+ put32(p + 2, get32(p + 2) + x);
2073
+ put32(p + 8, get32(p + 8) + x - 6);
2074
+ p += 16;
2075
+ while (p < p_end) {
2076
+ put32(p + 2, get32(p + 2) + x + s1->plt->data - p);
2077
+ p += 16;
2078
+ }
2079
+ #elif defined(TCC_TARGET_ARM)
2080
+ int x;
2081
+ x=s1->got->sh_addr - s1->plt->sh_addr - 12;
2082
+ p += 16;
2083
+ while (p < p_end) {
2084
+ if (get32(p) == 0x46c04778) /* PLT Thumb stub present */
2085
+ p += 4;
2086
+ put32(p + 12, x + get32(p + 12) + s1->plt->data - p);
2087
+ p += 16;
2088
+ }
2089
+ #elif defined(TCC_TARGET_C67)
2090
+ /* XXX: TODO */
2091
+ #else
2092
+ #error unsupported CPU
2093
+ #endif
2094
+ }
2095
+ }
2096
+
2097
+ /* relocate symbols in .dynsym */
2098
+ sym_end = (ElfW(Sym) *)(s1->dynsym->data + s1->dynsym->data_offset);
2099
+ for(sym = (ElfW(Sym) *)s1->dynsym->data + 1;
2100
+ sym < sym_end;
2101
+ sym++) {
2102
+ if (sym->st_shndx == SHN_UNDEF) {
2103
+ /* relocate to the PLT if the symbol corresponds
2104
+ to a PLT entry */
2105
+ if (sym->st_value)
2106
+ sym->st_value += s1->plt->sh_addr;
2107
+ } else if (sym->st_shndx < SHN_LORESERVE) {
2108
+ /* do symbol relocation */
2109
+ sym->st_value += s1->sections[sym->st_shndx]->sh_addr;
2110
+ }
2111
+ }
2112
+
2113
+ /* put dynamic section entries */
2114
+ dynamic->data_offset = saved_dynamic_data_offset;
2115
+ put_dt(dynamic, DT_HASH, s1->dynsym->hash->sh_addr);
2116
+ put_dt(dynamic, DT_STRTAB, dynstr->sh_addr);
2117
+ put_dt(dynamic, DT_SYMTAB, s1->dynsym->sh_addr);
2118
+ put_dt(dynamic, DT_STRSZ, dynstr->data_offset);
2119
+ put_dt(dynamic, DT_SYMENT, sizeof(ElfW(Sym)));
2120
+ #ifdef TCC_TARGET_X86_64
2121
+ put_dt(dynamic, DT_RELA, rel_addr);
2122
+ put_dt(dynamic, DT_RELASZ, rel_size);
2123
+ put_dt(dynamic, DT_RELAENT, sizeof(ElfW_Rel));
2124
+ #else
2125
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2126
+ put_dt(dynamic, DT_PLTGOT, s1->got->sh_addr);
2127
+ put_dt(dynamic, DT_PLTRELSZ, rel_size);
2128
+ put_dt(dynamic, DT_JMPREL, rel_addr);
2129
+ put_dt(dynamic, DT_PLTREL, DT_REL);
2130
+ put_dt(dynamic, DT_REL, bss_addr);
2131
+ put_dt(dynamic, DT_RELSZ, bss_size);
2132
+ #else
2133
+ put_dt(dynamic, DT_REL, rel_addr);
2134
+ put_dt(dynamic, DT_RELSZ, rel_size);
2135
+ put_dt(dynamic, DT_RELENT, sizeof(ElfW_Rel));
2136
+ #endif
2137
+ #endif
2138
+ if (s1->do_debug)
2139
+ put_dt(dynamic, DT_DEBUG, 0);
2140
+ put_dt(dynamic, DT_NULL, 0);
2141
+ }
2142
+
2143
+ ehdr.e_phentsize = sizeof(ElfW(Phdr));
2144
+ ehdr.e_phnum = phnum;
2145
+ ehdr.e_phoff = sizeof(ElfW(Ehdr));
2146
+ }
2147
+
2148
+ /* all other sections come after */
2149
+ for(i = 1; i < s1->nb_sections; i++) {
2150
+ s = s1->sections[i];
2151
+ if (phnum > 0 && (s->sh_flags & SHF_ALLOC))
2152
+ continue;
2153
+ section_order[sh_order_index++] = i;
2154
+
2155
+ file_offset = (file_offset + s->sh_addralign - 1) &
2156
+ ~(s->sh_addralign - 1);
2157
+ s->sh_offset = file_offset;
2158
+ if (s->sh_type != SHT_NOBITS)
2159
+ file_offset += s->sh_size;
2160
+ }
2161
+
2162
+ /* if building executable or DLL, then relocate each section
2163
+ except the GOT which is already relocated */
2164
+ if (file_type != TCC_OUTPUT_OBJ) {
2165
+ relocate_syms(s1, 0);
2166
+
2167
+ if (s1->nb_errors != 0) {
2168
+ fail:
2169
+ ret = -1;
2170
+ goto the_end;
2171
+ }
2172
+
2173
+ /* relocate sections */
2174
+ /* XXX: ignore sections with allocated relocations ? */
2175
+ for(i = 1; i < s1->nb_sections; i++) {
2176
+ s = s1->sections[i];
2177
+ if (s->reloc && s != s1->got)
2178
+ relocate_section(s1, s);
2179
+ }
2180
+
2181
+ /* relocate relocation entries if the relocation tables are
2182
+ allocated in the executable */
2183
+ for(i = 1; i < s1->nb_sections; i++) {
2184
+ s = s1->sections[i];
2185
+ if ((s->sh_flags & SHF_ALLOC) &&
2186
+ s->sh_type == SHT_RELX) {
2187
+ relocate_rel(s1, s);
2188
+ }
2189
+ }
2190
+
2191
+ /* get entry point address */
2192
+ if (file_type == TCC_OUTPUT_EXE)
2193
+ ehdr.e_entry = get_elf_sym_addr(s1, "_start", 1);
2194
+ else
2195
+ ehdr.e_entry = text_section->sh_addr; /* XXX: is it correct ? */
2196
+ }
2197
+ if (file_type == TCC_OUTPUT_EXE && s1->static_link)
2198
+ fill_got(s1);
2199
+
2200
+ /* write elf file */
2201
+ if (file_type == TCC_OUTPUT_OBJ)
2202
+ mode = 0666;
2203
+ else
2204
+ mode = 0777;
2205
+ unlink(filename);
2206
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, mode);
2207
+ if (fd < 0) {
2208
+ tcc_error_noabort("could not write '%s'", filename);
2209
+ goto fail;
2210
+ }
2211
+ f = fdopen(fd, "wb");
2212
+ if (s1->verbose)
2213
+ printf("<- %s\n", filename);
2214
+
2215
+ #ifdef TCC_TARGET_COFF
2216
+ if (s1->output_format == TCC_OUTPUT_FORMAT_COFF) {
2217
+ tcc_output_coff(s1, f);
2218
+ } else
2219
+ #endif
2220
+ if (s1->output_format == TCC_OUTPUT_FORMAT_ELF) {
2221
+ sort_syms(s1, symtab_section);
2222
+
2223
+ /* align to 4 */
2224
+ file_offset = (file_offset + 3) & -4;
2225
+
2226
+ /* fill header */
2227
+ ehdr.e_ident[0] = ELFMAG0;
2228
+ ehdr.e_ident[1] = ELFMAG1;
2229
+ ehdr.e_ident[2] = ELFMAG2;
2230
+ ehdr.e_ident[3] = ELFMAG3;
2231
+ ehdr.e_ident[4] = ELFCLASSW;
2232
+ ehdr.e_ident[5] = ELFDATA2LSB;
2233
+ ehdr.e_ident[6] = EV_CURRENT;
2234
+ #if defined(__FreeBSD__) || defined(__FreeBSD_kernel__)
2235
+ ehdr.e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
2236
+ #endif
2237
+ #ifdef TCC_TARGET_ARM
2238
+ #ifdef TCC_ARM_EABI
2239
+ ehdr.e_ident[EI_OSABI] = 0;
2240
+ ehdr.e_flags = 4 << 24;
2241
+ #else
2242
+ ehdr.e_ident[EI_OSABI] = ELFOSABI_ARM;
2243
+ #endif
2244
+ #endif
2245
+ switch(file_type) {
2246
+ default:
2247
+ case TCC_OUTPUT_EXE:
2248
+ ehdr.e_type = ET_EXEC;
2249
+ break;
2250
+ case TCC_OUTPUT_DLL:
2251
+ ehdr.e_type = ET_DYN;
2252
+ break;
2253
+ case TCC_OUTPUT_OBJ:
2254
+ ehdr.e_type = ET_REL;
2255
+ break;
2256
+ }
2257
+ ehdr.e_machine = EM_TCC_TARGET;
2258
+ ehdr.e_version = EV_CURRENT;
2259
+ ehdr.e_shoff = file_offset;
2260
+ ehdr.e_ehsize = sizeof(ElfW(Ehdr));
2261
+ ehdr.e_shentsize = sizeof(ElfW(Shdr));
2262
+ ehdr.e_shnum = shnum;
2263
+ ehdr.e_shstrndx = shnum - 1;
2264
+
2265
+ fwrite(&ehdr, 1, sizeof(ElfW(Ehdr)), f);
2266
+ fwrite(phdr, 1, phnum * sizeof(ElfW(Phdr)), f);
2267
+ offset = sizeof(ElfW(Ehdr)) + phnum * sizeof(ElfW(Phdr));
2268
+
2269
+ for(i=1;i<s1->nb_sections;i++) {
2270
+ s = s1->sections[section_order[i]];
2271
+ if (s->sh_type != SHT_NOBITS) {
2272
+ if (s->sh_type == SHT_DYNSYM)
2273
+ patch_dynsym_undef(s1, s);
2274
+ while (offset < s->sh_offset) {
2275
+ fputc(0, f);
2276
+ offset++;
2277
+ }
2278
+ size = s->sh_size;
2279
+ fwrite(s->data, 1, size, f);
2280
+ offset += size;
2281
+ }
2282
+ }
2283
+
2284
+ /* output section headers */
2285
+ while (offset < ehdr.e_shoff) {
2286
+ fputc(0, f);
2287
+ offset++;
2288
+ }
2289
+
2290
+ for(i=0;i<s1->nb_sections;i++) {
2291
+ sh = &shdr;
2292
+ memset(sh, 0, sizeof(ElfW(Shdr)));
2293
+ s = s1->sections[i];
2294
+ if (s) {
2295
+ sh->sh_name = s->sh_name;
2296
+ sh->sh_type = s->sh_type;
2297
+ sh->sh_flags = s->sh_flags;
2298
+ sh->sh_entsize = s->sh_entsize;
2299
+ sh->sh_info = s->sh_info;
2300
+ if (s->link)
2301
+ sh->sh_link = s->link->sh_num;
2302
+ sh->sh_addralign = s->sh_addralign;
2303
+ sh->sh_addr = s->sh_addr;
2304
+ sh->sh_offset = s->sh_offset;
2305
+ sh->sh_size = s->sh_size;
2306
+ }
2307
+ fwrite(sh, 1, sizeof(ElfW(Shdr)), f);
2308
+ }
2309
+ } else {
2310
+ tcc_output_binary(s1, f, section_order);
2311
+ }
2312
+ fclose(f);
2313
+
2314
+ ret = 0;
2315
+ the_end:
2316
+ tcc_free(s1->symtab_to_dynsym);
2317
+ tcc_free(section_order);
2318
+ tcc_free(phdr);
2319
+ tcc_free(s1->sym_attrs);
2320
+ return ret;
2321
+ }
2322
+
2323
+ LIBTCCAPI int tcc_output_file(TCCState *s, const char *filename)
2324
+ {
2325
+ int ret;
2326
+ #ifdef TCC_TARGET_PE
2327
+ if (s->output_type != TCC_OUTPUT_OBJ) {
2328
+ ret = pe_output_file(s, filename);
2329
+ } else
2330
+ #endif
2331
+ {
2332
+ ret = elf_output_file(s, filename);
2333
+ }
2334
+ return ret;
2335
+ }
2336
+
2337
+ static void *load_data(int fd, unsigned long file_offset, unsigned long size)
2338
+ {
2339
+ void *data;
2340
+
2341
+ data = tcc_malloc(size);
2342
+ lseek(fd, file_offset, SEEK_SET);
2343
+ read(fd, data, size);
2344
+ return data;
2345
+ }
2346
+
2347
+ typedef struct SectionMergeInfo {
2348
+ Section *s; /* corresponding existing section */
2349
+ unsigned long offset; /* offset of the new section in the existing section */
2350
+ uint8_t new_section; /* true if section 's' was added */
2351
+ uint8_t link_once; /* true if link once section */
2352
+ } SectionMergeInfo;
2353
+
2354
+ /* load an object file and merge it with current files */
2355
+ /* XXX: handle correctly stab (debug) info */
2356
+ ST_FUNC int tcc_load_object_file(TCCState *s1,
2357
+ int fd, unsigned long file_offset)
2358
+ {
2359
+ ElfW(Ehdr) ehdr;
2360
+ ElfW(Shdr) *shdr, *sh;
2361
+ int size, i, j, offset, offseti, nb_syms, sym_index, ret;
2362
+ unsigned char *strsec, *strtab;
2363
+ int *old_to_new_syms;
2364
+ char *sh_name, *name;
2365
+ SectionMergeInfo *sm_table, *sm;
2366
+ ElfW(Sym) *sym, *symtab;
2367
+ ElfW_Rel *rel, *rel_end;
2368
+ Section *s;
2369
+
2370
+ int stab_index;
2371
+ int stabstr_index;
2372
+
2373
+ stab_index = stabstr_index = 0;
2374
+
2375
+ if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
2376
+ goto fail1;
2377
+ if (ehdr.e_ident[0] != ELFMAG0 ||
2378
+ ehdr.e_ident[1] != ELFMAG1 ||
2379
+ ehdr.e_ident[2] != ELFMAG2 ||
2380
+ ehdr.e_ident[3] != ELFMAG3)
2381
+ goto fail1;
2382
+ /* test if object file */
2383
+ if (ehdr.e_type != ET_REL)
2384
+ goto fail1;
2385
+ /* test CPU specific stuff */
2386
+ if (ehdr.e_ident[5] != ELFDATA2LSB ||
2387
+ ehdr.e_machine != EM_TCC_TARGET) {
2388
+ fail1:
2389
+ tcc_error_noabort("invalid object file");
2390
+ return -1;
2391
+ }
2392
+ /* read sections */
2393
+ shdr = load_data(fd, file_offset + ehdr.e_shoff,
2394
+ sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2395
+ sm_table = tcc_mallocz(sizeof(SectionMergeInfo) * ehdr.e_shnum);
2396
+
2397
+ /* load section names */
2398
+ sh = &shdr[ehdr.e_shstrndx];
2399
+ strsec = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2400
+
2401
+ /* load symtab and strtab */
2402
+ old_to_new_syms = NULL;
2403
+ symtab = NULL;
2404
+ strtab = NULL;
2405
+ nb_syms = 0;
2406
+ for(i = 1; i < ehdr.e_shnum; i++) {
2407
+ sh = &shdr[i];
2408
+ if (sh->sh_type == SHT_SYMTAB) {
2409
+ if (symtab) {
2410
+ tcc_error_noabort("object must contain only one symtab");
2411
+ fail:
2412
+ ret = -1;
2413
+ goto the_end;
2414
+ }
2415
+ nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2416
+ symtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2417
+ sm_table[i].s = symtab_section;
2418
+
2419
+ /* now load strtab */
2420
+ sh = &shdr[sh->sh_link];
2421
+ strtab = load_data(fd, file_offset + sh->sh_offset, sh->sh_size);
2422
+ }
2423
+ }
2424
+
2425
+ /* now examine each section and try to merge its content with the
2426
+ ones in memory */
2427
+ for(i = 1; i < ehdr.e_shnum; i++) {
2428
+ /* no need to examine section name strtab */
2429
+ if (i == ehdr.e_shstrndx)
2430
+ continue;
2431
+ sh = &shdr[i];
2432
+ sh_name = strsec + sh->sh_name;
2433
+ /* ignore sections types we do not handle */
2434
+ if (sh->sh_type != SHT_PROGBITS &&
2435
+ sh->sh_type != SHT_RELX &&
2436
+ #ifdef TCC_ARM_EABI
2437
+ sh->sh_type != SHT_ARM_EXIDX &&
2438
+ #endif
2439
+ sh->sh_type != SHT_NOBITS &&
2440
+ sh->sh_type != SHT_PREINIT_ARRAY &&
2441
+ sh->sh_type != SHT_INIT_ARRAY &&
2442
+ sh->sh_type != SHT_FINI_ARRAY &&
2443
+ strcmp(sh_name, ".stabstr")
2444
+ )
2445
+ continue;
2446
+ if (sh->sh_addralign < 1)
2447
+ sh->sh_addralign = 1;
2448
+ /* find corresponding section, if any */
2449
+ for(j = 1; j < s1->nb_sections;j++) {
2450
+ s = s1->sections[j];
2451
+ if (!strcmp(s->name, sh_name)) {
2452
+ if (!strncmp(sh_name, ".gnu.linkonce",
2453
+ sizeof(".gnu.linkonce") - 1)) {
2454
+ /* if a 'linkonce' section is already present, we
2455
+ do not add it again. It is a little tricky as
2456
+ symbols can still be defined in
2457
+ it. */
2458
+ sm_table[i].link_once = 1;
2459
+ goto next;
2460
+ } else {
2461
+ goto found;
2462
+ }
2463
+ }
2464
+ }
2465
+ /* not found: create new section */
2466
+ s = new_section(s1, sh_name, sh->sh_type, sh->sh_flags);
2467
+ /* take as much info as possible from the section. sh_link and
2468
+ sh_info will be updated later */
2469
+ s->sh_addralign = sh->sh_addralign;
2470
+ s->sh_entsize = sh->sh_entsize;
2471
+ sm_table[i].new_section = 1;
2472
+ found:
2473
+ if (sh->sh_type != s->sh_type) {
2474
+ tcc_error_noabort("invalid section type");
2475
+ goto fail;
2476
+ }
2477
+
2478
+ /* align start of section */
2479
+ offset = s->data_offset;
2480
+
2481
+ if (0 == strcmp(sh_name, ".stab")) {
2482
+ stab_index = i;
2483
+ goto no_align;
2484
+ }
2485
+ if (0 == strcmp(sh_name, ".stabstr")) {
2486
+ stabstr_index = i;
2487
+ goto no_align;
2488
+ }
2489
+
2490
+ size = sh->sh_addralign - 1;
2491
+ offset = (offset + size) & ~size;
2492
+ if (sh->sh_addralign > s->sh_addralign)
2493
+ s->sh_addralign = sh->sh_addralign;
2494
+ s->data_offset = offset;
2495
+ no_align:
2496
+ sm_table[i].offset = offset;
2497
+ sm_table[i].s = s;
2498
+ /* concatenate sections */
2499
+ size = sh->sh_size;
2500
+ if (sh->sh_type != SHT_NOBITS) {
2501
+ unsigned char *ptr;
2502
+ lseek(fd, file_offset + sh->sh_offset, SEEK_SET);
2503
+ ptr = section_ptr_add(s, size);
2504
+ read(fd, ptr, size);
2505
+ } else {
2506
+ s->data_offset += size;
2507
+ }
2508
+ next: ;
2509
+ }
2510
+
2511
+ /* //gr relocate stab strings */
2512
+ if (stab_index && stabstr_index) {
2513
+ Stab_Sym *a, *b;
2514
+ unsigned o;
2515
+ s = sm_table[stab_index].s;
2516
+ a = (Stab_Sym *)(s->data + sm_table[stab_index].offset);
2517
+ b = (Stab_Sym *)(s->data + s->data_offset);
2518
+ o = sm_table[stabstr_index].offset;
2519
+ while (a < b)
2520
+ a->n_strx += o, a++;
2521
+ }
2522
+
2523
+ /* second short pass to update sh_link and sh_info fields of new
2524
+ sections */
2525
+ for(i = 1; i < ehdr.e_shnum; i++) {
2526
+ s = sm_table[i].s;
2527
+ if (!s || !sm_table[i].new_section)
2528
+ continue;
2529
+ sh = &shdr[i];
2530
+ if (sh->sh_link > 0)
2531
+ s->link = sm_table[sh->sh_link].s;
2532
+ if (sh->sh_type == SHT_RELX) {
2533
+ s->sh_info = sm_table[sh->sh_info].s->sh_num;
2534
+ /* update backward link */
2535
+ s1->sections[s->sh_info]->reloc = s;
2536
+ }
2537
+ }
2538
+ sm = sm_table;
2539
+
2540
+ /* resolve symbols */
2541
+ old_to_new_syms = tcc_mallocz(nb_syms * sizeof(int));
2542
+
2543
+ sym = symtab + 1;
2544
+ for(i = 1; i < nb_syms; i++, sym++) {
2545
+ if (sym->st_shndx != SHN_UNDEF &&
2546
+ sym->st_shndx < SHN_LORESERVE) {
2547
+ sm = &sm_table[sym->st_shndx];
2548
+ if (sm->link_once) {
2549
+ /* if a symbol is in a link once section, we use the
2550
+ already defined symbol. It is very important to get
2551
+ correct relocations */
2552
+ if (ELFW(ST_BIND)(sym->st_info) != STB_LOCAL) {
2553
+ name = strtab + sym->st_name;
2554
+ sym_index = find_elf_sym(symtab_section, name);
2555
+ if (sym_index)
2556
+ old_to_new_syms[i] = sym_index;
2557
+ }
2558
+ continue;
2559
+ }
2560
+ /* if no corresponding section added, no need to add symbol */
2561
+ if (!sm->s)
2562
+ continue;
2563
+ /* convert section number */
2564
+ sym->st_shndx = sm->s->sh_num;
2565
+ /* offset value */
2566
+ sym->st_value += sm->offset;
2567
+ }
2568
+ /* add symbol */
2569
+ name = strtab + sym->st_name;
2570
+ sym_index = add_elf_sym(symtab_section, sym->st_value, sym->st_size,
2571
+ sym->st_info, sym->st_other,
2572
+ sym->st_shndx, name);
2573
+ old_to_new_syms[i] = sym_index;
2574
+ }
2575
+
2576
+ /* third pass to patch relocation entries */
2577
+ for(i = 1; i < ehdr.e_shnum; i++) {
2578
+ s = sm_table[i].s;
2579
+ if (!s)
2580
+ continue;
2581
+ sh = &shdr[i];
2582
+ offset = sm_table[i].offset;
2583
+ switch(s->sh_type) {
2584
+ case SHT_RELX:
2585
+ /* take relocation offset information */
2586
+ offseti = sm_table[sh->sh_info].offset;
2587
+ rel_end = (ElfW_Rel *)(s->data + s->data_offset);
2588
+ for(rel = (ElfW_Rel *)(s->data + offset);
2589
+ rel < rel_end;
2590
+ rel++) {
2591
+ int type;
2592
+ unsigned sym_index;
2593
+ /* convert symbol index */
2594
+ type = ELFW(R_TYPE)(rel->r_info);
2595
+ sym_index = ELFW(R_SYM)(rel->r_info);
2596
+ /* NOTE: only one symtab assumed */
2597
+ if (sym_index >= nb_syms)
2598
+ goto invalid_reloc;
2599
+ sym_index = old_to_new_syms[sym_index];
2600
+ /* ignore link_once in rel section. */
2601
+ if (!sym_index && !sm->link_once
2602
+ #ifdef TCC_TARGET_ARM
2603
+ && type != R_ARM_V4BX
2604
+ #endif
2605
+ ) {
2606
+ invalid_reloc:
2607
+ tcc_error_noabort("Invalid relocation entry [%2d] '%s' @ %.8x",
2608
+ i, strsec + sh->sh_name, rel->r_offset);
2609
+ goto fail;
2610
+ }
2611
+ rel->r_info = ELFW(R_INFO)(sym_index, type);
2612
+ /* offset the relocation offset */
2613
+ rel->r_offset += offseti;
2614
+ #ifdef TCC_TARGET_ARM
2615
+ /* Jumps and branches from a Thumb code to a PLT entry need
2616
+ special handling since PLT entries are ARM code.
2617
+ Unconditional bl instructions referencing PLT entries are
2618
+ handled by converting these instructions into blx
2619
+ instructions. Other case of instructions referencing a PLT
2620
+ entry require to add a Thumb stub before the PLT entry to
2621
+ switch to ARM mode. We set bit 0 of the got offset of a
2622
+ symbol to indicate such a case. */
2623
+ if (type == R_ARM_THM_JUMP24)
2624
+ alloc_sym_attr(s1, sym_index)->plt_thumb_stub = 1;
2625
+ #endif
2626
+ }
2627
+ break;
2628
+ default:
2629
+ break;
2630
+ }
2631
+ }
2632
+
2633
+ ret = 0;
2634
+ the_end:
2635
+ tcc_free(symtab);
2636
+ tcc_free(strtab);
2637
+ tcc_free(old_to_new_syms);
2638
+ tcc_free(sm_table);
2639
+ tcc_free(strsec);
2640
+ tcc_free(shdr);
2641
+ return ret;
2642
+ }
2643
+
2644
+ typedef struct ArchiveHeader {
2645
+ char ar_name[16]; /* name of this member */
2646
+ char ar_date[12]; /* file mtime */
2647
+ char ar_uid[6]; /* owner uid; printed as decimal */
2648
+ char ar_gid[6]; /* owner gid; printed as decimal */
2649
+ char ar_mode[8]; /* file mode, printed as octal */
2650
+ char ar_size[10]; /* file size, printed as decimal */
2651
+ char ar_fmag[2]; /* should contain ARFMAG */
2652
+ } ArchiveHeader;
2653
+
2654
+ static int get_be32(const uint8_t *b)
2655
+ {
2656
+ return b[3] | (b[2] << 8) | (b[1] << 16) | (b[0] << 24);
2657
+ }
2658
+
2659
+ /* load only the objects which resolve undefined symbols */
2660
+ static int tcc_load_alacarte(TCCState *s1, int fd, int size)
2661
+ {
2662
+ int i, bound, nsyms, sym_index, off, ret;
2663
+ uint8_t *data;
2664
+ const char *ar_names, *p;
2665
+ const uint8_t *ar_index;
2666
+ ElfW(Sym) *sym;
2667
+
2668
+ data = tcc_malloc(size);
2669
+ if (read(fd, data, size) != size)
2670
+ goto fail;
2671
+ nsyms = get_be32(data);
2672
+ ar_index = data + 4;
2673
+ ar_names = ar_index + nsyms * 4;
2674
+
2675
+ do {
2676
+ bound = 0;
2677
+ for(p = ar_names, i = 0; i < nsyms; i++, p += strlen(p)+1) {
2678
+ sym_index = find_elf_sym(symtab_section, p);
2679
+ if(sym_index) {
2680
+ sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
2681
+ if(sym->st_shndx == SHN_UNDEF) {
2682
+ off = get_be32(ar_index + i * 4) + sizeof(ArchiveHeader);
2683
+ #if 0
2684
+ printf("%5d\t%s\t%08x\n", i, p, sym->st_shndx);
2685
+ #endif
2686
+ ++bound;
2687
+ lseek(fd, off, SEEK_SET);
2688
+ if(tcc_load_object_file(s1, fd, off) < 0) {
2689
+ fail:
2690
+ ret = -1;
2691
+ goto the_end;
2692
+ }
2693
+ }
2694
+ }
2695
+ }
2696
+ } while(bound);
2697
+ ret = 0;
2698
+ the_end:
2699
+ tcc_free(data);
2700
+ return ret;
2701
+ }
2702
+
2703
+ /* load a '.a' file */
2704
+ ST_FUNC int tcc_load_archive(TCCState *s1, int fd)
2705
+ {
2706
+ ArchiveHeader hdr;
2707
+ char ar_size[11];
2708
+ char ar_name[17];
2709
+ char magic[8];
2710
+ int size, len, i;
2711
+ unsigned long file_offset;
2712
+
2713
+ /* skip magic which was already checked */
2714
+ read(fd, magic, sizeof(magic));
2715
+
2716
+ for(;;) {
2717
+ len = read(fd, &hdr, sizeof(hdr));
2718
+ if (len == 0)
2719
+ break;
2720
+ if (len != sizeof(hdr)) {
2721
+ tcc_error_noabort("invalid archive");
2722
+ return -1;
2723
+ }
2724
+ memcpy(ar_size, hdr.ar_size, sizeof(hdr.ar_size));
2725
+ ar_size[sizeof(hdr.ar_size)] = '\0';
2726
+ size = strtol(ar_size, NULL, 0);
2727
+ memcpy(ar_name, hdr.ar_name, sizeof(hdr.ar_name));
2728
+ for(i = sizeof(hdr.ar_name) - 1; i >= 0; i--) {
2729
+ if (ar_name[i] != ' ')
2730
+ break;
2731
+ }
2732
+ ar_name[i + 1] = '\0';
2733
+ // printf("name='%s' size=%d %s\n", ar_name, size, ar_size);
2734
+ file_offset = lseek(fd, 0, SEEK_CUR);
2735
+ /* align to even */
2736
+ size = (size + 1) & ~1;
2737
+ if (!strcmp(ar_name, "/")) {
2738
+ /* coff symbol table : we handle it */
2739
+ if(s1->alacarte_link)
2740
+ return tcc_load_alacarte(s1, fd, size);
2741
+ } else if (!strcmp(ar_name, "//") ||
2742
+ !strcmp(ar_name, "__.SYMDEF") ||
2743
+ !strcmp(ar_name, "__.SYMDEF/") ||
2744
+ !strcmp(ar_name, "ARFILENAMES/")) {
2745
+ /* skip symbol table or archive names */
2746
+ } else {
2747
+ if (tcc_load_object_file(s1, fd, file_offset) < 0)
2748
+ return -1;
2749
+ }
2750
+ lseek(fd, file_offset + size, SEEK_SET);
2751
+ }
2752
+ return 0;
2753
+ }
2754
+
2755
+ #ifndef TCC_TARGET_PE
2756
+ /* load a DLL and all referenced DLLs. 'level = 0' means that the DLL
2757
+ is referenced by the user (so it should be added as DT_NEEDED in
2758
+ the generated ELF file) */
2759
+ ST_FUNC int tcc_load_dll(TCCState *s1, int fd, const char *filename, int level)
2760
+ {
2761
+ ElfW(Ehdr) ehdr;
2762
+ ElfW(Shdr) *shdr, *sh, *sh1;
2763
+ int i, j, nb_syms, nb_dts, sym_bind, ret;
2764
+ ElfW(Sym) *sym, *dynsym;
2765
+ ElfW(Dyn) *dt, *dynamic;
2766
+ unsigned char *dynstr;
2767
+ const char *name, *soname;
2768
+ DLLReference *dllref;
2769
+
2770
+ read(fd, &ehdr, sizeof(ehdr));
2771
+
2772
+ /* test CPU specific stuff */
2773
+ if (ehdr.e_ident[5] != ELFDATA2LSB ||
2774
+ ehdr.e_machine != EM_TCC_TARGET) {
2775
+ tcc_error_noabort("bad architecture");
2776
+ return -1;
2777
+ }
2778
+
2779
+ /* read sections */
2780
+ shdr = load_data(fd, ehdr.e_shoff, sizeof(ElfW(Shdr)) * ehdr.e_shnum);
2781
+
2782
+ /* load dynamic section and dynamic symbols */
2783
+ nb_syms = 0;
2784
+ nb_dts = 0;
2785
+ dynamic = NULL;
2786
+ dynsym = NULL; /* avoid warning */
2787
+ dynstr = NULL; /* avoid warning */
2788
+ for(i = 0, sh = shdr; i < ehdr.e_shnum; i++, sh++) {
2789
+ switch(sh->sh_type) {
2790
+ case SHT_DYNAMIC:
2791
+ nb_dts = sh->sh_size / sizeof(ElfW(Dyn));
2792
+ dynamic = load_data(fd, sh->sh_offset, sh->sh_size);
2793
+ break;
2794
+ case SHT_DYNSYM:
2795
+ nb_syms = sh->sh_size / sizeof(ElfW(Sym));
2796
+ dynsym = load_data(fd, sh->sh_offset, sh->sh_size);
2797
+ sh1 = &shdr[sh->sh_link];
2798
+ dynstr = load_data(fd, sh1->sh_offset, sh1->sh_size);
2799
+ break;
2800
+ default:
2801
+ break;
2802
+ }
2803
+ }
2804
+
2805
+ /* compute the real library name */
2806
+ soname = tcc_basename(filename);
2807
+
2808
+ for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2809
+ if (dt->d_tag == DT_SONAME) {
2810
+ soname = dynstr + dt->d_un.d_val;
2811
+ }
2812
+ }
2813
+
2814
+ /* if the dll is already loaded, do not load it */
2815
+ for(i = 0; i < s1->nb_loaded_dlls; i++) {
2816
+ dllref = s1->loaded_dlls[i];
2817
+ if (!strcmp(soname, dllref->name)) {
2818
+ /* but update level if needed */
2819
+ if (level < dllref->level)
2820
+ dllref->level = level;
2821
+ ret = 0;
2822
+ goto the_end;
2823
+ }
2824
+ }
2825
+
2826
+ // printf("loading dll '%s'\n", soname);
2827
+
2828
+ /* add the dll and its level */
2829
+ dllref = tcc_mallocz(sizeof(DLLReference) + strlen(soname));
2830
+ dllref->level = level;
2831
+ strcpy(dllref->name, soname);
2832
+ dynarray_add((void ***)&s1->loaded_dlls, &s1->nb_loaded_dlls, dllref);
2833
+
2834
+ /* add dynamic symbols in dynsym_section */
2835
+ for(i = 1, sym = dynsym + 1; i < nb_syms; i++, sym++) {
2836
+ sym_bind = ELFW(ST_BIND)(sym->st_info);
2837
+ if (sym_bind == STB_LOCAL)
2838
+ continue;
2839
+ name = dynstr + sym->st_name;
2840
+ add_elf_sym(s1->dynsymtab_section, sym->st_value, sym->st_size,
2841
+ sym->st_info, sym->st_other, sym->st_shndx, name);
2842
+ }
2843
+
2844
+ /* load all referenced DLLs */
2845
+ for(i = 0, dt = dynamic; i < nb_dts; i++, dt++) {
2846
+ switch(dt->d_tag) {
2847
+ case DT_NEEDED:
2848
+ name = dynstr + dt->d_un.d_val;
2849
+ for(j = 0; j < s1->nb_loaded_dlls; j++) {
2850
+ dllref = s1->loaded_dlls[j];
2851
+ if (!strcmp(name, dllref->name))
2852
+ goto already_loaded;
2853
+ }
2854
+ if (tcc_add_dll(s1, name, AFF_REFERENCED_DLL) < 0) {
2855
+ tcc_error_noabort("referenced dll '%s' not found", name);
2856
+ ret = -1;
2857
+ goto the_end;
2858
+ }
2859
+ already_loaded:
2860
+ break;
2861
+ }
2862
+ }
2863
+ ret = 0;
2864
+ the_end:
2865
+ tcc_free(dynstr);
2866
+ tcc_free(dynsym);
2867
+ tcc_free(dynamic);
2868
+ tcc_free(shdr);
2869
+ return ret;
2870
+ }
2871
+
2872
+ #define LD_TOK_NAME 256
2873
+ #define LD_TOK_EOF (-1)
2874
+
2875
+ /* return next ld script token */
2876
+ static int ld_next(TCCState *s1, char *name, int name_size)
2877
+ {
2878
+ int c;
2879
+ char *q;
2880
+
2881
+ redo:
2882
+ switch(ch) {
2883
+ case ' ':
2884
+ case '\t':
2885
+ case '\f':
2886
+ case '\v':
2887
+ case '\r':
2888
+ case '\n':
2889
+ inp();
2890
+ goto redo;
2891
+ case '/':
2892
+ minp();
2893
+ if (ch == '*') {
2894
+ file->buf_ptr = parse_comment(file->buf_ptr);
2895
+ ch = file->buf_ptr[0];
2896
+ goto redo;
2897
+ } else {
2898
+ q = name;
2899
+ *q++ = '/';
2900
+ goto parse_name;
2901
+ }
2902
+ break;
2903
+ /* case 'a' ... 'z': */
2904
+ case 'a':
2905
+ case 'b':
2906
+ case 'c':
2907
+ case 'd':
2908
+ case 'e':
2909
+ case 'f':
2910
+ case 'g':
2911
+ case 'h':
2912
+ case 'i':
2913
+ case 'j':
2914
+ case 'k':
2915
+ case 'l':
2916
+ case 'm':
2917
+ case 'n':
2918
+ case 'o':
2919
+ case 'p':
2920
+ case 'q':
2921
+ case 'r':
2922
+ case 's':
2923
+ case 't':
2924
+ case 'u':
2925
+ case 'v':
2926
+ case 'w':
2927
+ case 'x':
2928
+ case 'y':
2929
+ case 'z':
2930
+ /* case 'A' ... 'z': */
2931
+ case 'A':
2932
+ case 'B':
2933
+ case 'C':
2934
+ case 'D':
2935
+ case 'E':
2936
+ case 'F':
2937
+ case 'G':
2938
+ case 'H':
2939
+ case 'I':
2940
+ case 'J':
2941
+ case 'K':
2942
+ case 'L':
2943
+ case 'M':
2944
+ case 'N':
2945
+ case 'O':
2946
+ case 'P':
2947
+ case 'Q':
2948
+ case 'R':
2949
+ case 'S':
2950
+ case 'T':
2951
+ case 'U':
2952
+ case 'V':
2953
+ case 'W':
2954
+ case 'X':
2955
+ case 'Y':
2956
+ case 'Z':
2957
+ case '_':
2958
+ case '\\':
2959
+ case '.':
2960
+ case '$':
2961
+ case '~':
2962
+ q = name;
2963
+ parse_name:
2964
+ for(;;) {
2965
+ if (!((ch >= 'a' && ch <= 'z') ||
2966
+ (ch >= 'A' && ch <= 'Z') ||
2967
+ (ch >= '0' && ch <= '9') ||
2968
+ strchr("/.-_+=$:\\,~", ch)))
2969
+ break;
2970
+ if ((q - name) < name_size - 1) {
2971
+ *q++ = ch;
2972
+ }
2973
+ minp();
2974
+ }
2975
+ *q = '\0';
2976
+ c = LD_TOK_NAME;
2977
+ break;
2978
+ case CH_EOF:
2979
+ c = LD_TOK_EOF;
2980
+ break;
2981
+ default:
2982
+ c = ch;
2983
+ inp();
2984
+ break;
2985
+ }
2986
+ #if 0
2987
+ printf("tok=%c %d\n", c, c);
2988
+ if (c == LD_TOK_NAME)
2989
+ printf(" name=%s\n", name);
2990
+ #endif
2991
+ return c;
2992
+ }
2993
+
2994
+ static int ld_add_file(TCCState *s1, const char filename[])
2995
+ {
2996
+ int ret;
2997
+
2998
+ ret = tcc_add_file_internal(s1, filename, 0);
2999
+ if (ret)
3000
+ ret = tcc_add_dll(s1, filename, 0);
3001
+ return ret;
3002
+ }
3003
+
3004
+ static inline int new_undef_syms(void)
3005
+ {
3006
+ int ret = 0;
3007
+ ret = new_undef_sym;
3008
+ new_undef_sym = 0;
3009
+ return ret;
3010
+ }
3011
+
3012
+ static int ld_add_file_list(TCCState *s1, const char *cmd, int as_needed)
3013
+ {
3014
+ char filename[1024], libname[1024];
3015
+ int t, group, nblibs = 0, ret = 0;
3016
+ char **libs = NULL;
3017
+
3018
+ group = !strcmp(cmd, "GROUP");
3019
+ if (!as_needed)
3020
+ new_undef_syms();
3021
+ t = ld_next(s1, filename, sizeof(filename));
3022
+ if (t != '(')
3023
+ expect("(");
3024
+ t = ld_next(s1, filename, sizeof(filename));
3025
+ for(;;) {
3026
+ libname[0] = '\0';
3027
+ if (t == LD_TOK_EOF) {
3028
+ tcc_error_noabort("unexpected end of file");
3029
+ ret = -1;
3030
+ goto lib_parse_error;
3031
+ } else if (t == ')') {
3032
+ break;
3033
+ } else if (t == '-') {
3034
+ t = ld_next(s1, filename, sizeof(filename));
3035
+ if ((t != LD_TOK_NAME) || (filename[0] != 'l')) {
3036
+ tcc_error_noabort("library name expected");
3037
+ ret = -1;
3038
+ goto lib_parse_error;
3039
+ }
3040
+ pstrcpy(libname, sizeof libname, &filename[1]);
3041
+ if (s1->static_link) {
3042
+ snprintf(filename, sizeof filename, "lib%s.a", libname);
3043
+ } else {
3044
+ snprintf(filename, sizeof filename, "lib%s.so", libname);
3045
+ }
3046
+ } else if (t != LD_TOK_NAME) {
3047
+ tcc_error_noabort("filename expected");
3048
+ ret = -1;
3049
+ goto lib_parse_error;
3050
+ }
3051
+ if (!strcmp(filename, "AS_NEEDED")) {
3052
+ ret = ld_add_file_list(s1, cmd, 1);
3053
+ if (ret)
3054
+ goto lib_parse_error;
3055
+ } else {
3056
+ /* TODO: Implement AS_NEEDED support. Ignore it for now */
3057
+ if (!as_needed) {
3058
+ ret = ld_add_file(s1, filename);
3059
+ if (ret)
3060
+ goto lib_parse_error;
3061
+ if (group) {
3062
+ /* Add the filename *and* the libname to avoid future conversions */
3063
+ dynarray_add((void ***) &libs, &nblibs, tcc_strdup(filename));
3064
+ if (libname[0] != '\0')
3065
+ dynarray_add((void ***) &libs, &nblibs, tcc_strdup(libname));
3066
+ }
3067
+ }
3068
+ }
3069
+ t = ld_next(s1, filename, sizeof(filename));
3070
+ if (t == ',') {
3071
+ t = ld_next(s1, filename, sizeof(filename));
3072
+ }
3073
+ }
3074
+ if (group && !as_needed) {
3075
+ while (new_undef_syms()) {
3076
+ int i;
3077
+
3078
+ for (i = 0; i < nblibs; i ++)
3079
+ ld_add_file(s1, libs[i]);
3080
+ }
3081
+ }
3082
+ lib_parse_error:
3083
+ dynarray_reset(&libs, &nblibs);
3084
+ return ret;
3085
+ }
3086
+
3087
+ /* interpret a subset of GNU ldscripts to handle the dummy libc.so
3088
+ files */
3089
+ ST_FUNC int tcc_load_ldscript(TCCState *s1)
3090
+ {
3091
+ char cmd[64];
3092
+ char filename[1024];
3093
+ int t, ret;
3094
+
3095
+ ch = file->buf_ptr[0];
3096
+ ch = handle_eob();
3097
+ for(;;) {
3098
+ t = ld_next(s1, cmd, sizeof(cmd));
3099
+ if (t == LD_TOK_EOF)
3100
+ return 0;
3101
+ else if (t != LD_TOK_NAME)
3102
+ return -1;
3103
+ if (!strcmp(cmd, "INPUT") ||
3104
+ !strcmp(cmd, "GROUP")) {
3105
+ ret = ld_add_file_list(s1, cmd, 0);
3106
+ if (ret)
3107
+ return ret;
3108
+ } else if (!strcmp(cmd, "OUTPUT_FORMAT") ||
3109
+ !strcmp(cmd, "TARGET")) {
3110
+ /* ignore some commands */
3111
+ t = ld_next(s1, cmd, sizeof(cmd));
3112
+ if (t != '(')
3113
+ expect("(");
3114
+ for(;;) {
3115
+ t = ld_next(s1, filename, sizeof(filename));
3116
+ if (t == LD_TOK_EOF) {
3117
+ tcc_error_noabort("unexpected end of file");
3118
+ return -1;
3119
+ } else if (t == ')') {
3120
+ break;
3121
+ }
3122
+ }
3123
+ } else {
3124
+ return -1;
3125
+ }
3126
+ }
3127
+ return 0;
3128
+ }
3129
+ #endif /* ndef TCC_TARGET_PE */