ffi 0.4.0-x86-mswin32

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ffi might be problematic. Click here for more details.

Files changed (316) hide show
  1. data/LICENSE +51 -0
  2. data/README.rdoc +69 -0
  3. data/Rakefile +142 -0
  4. data/ext/ffi_c/AbstractMemory.c +412 -0
  5. data/ext/ffi_c/AbstractMemory.h +68 -0
  6. data/ext/ffi_c/AutoPointer.c +60 -0
  7. data/ext/ffi_c/AutoPointer.h +18 -0
  8. data/ext/ffi_c/Buffer.c +171 -0
  9. data/ext/ffi_c/Callback.c +374 -0
  10. data/ext/ffi_c/Callback.h +47 -0
  11. data/ext/ffi_c/DynamicLibrary.c +213 -0
  12. data/ext/ffi_c/DynamicLibrary.h +22 -0
  13. data/ext/ffi_c/Invoker.c +962 -0
  14. data/ext/ffi_c/LastError.c +135 -0
  15. data/ext/ffi_c/LastError.h +18 -0
  16. data/ext/ffi_c/MemoryPointer.c +156 -0
  17. data/ext/ffi_c/MemoryPointer.h +20 -0
  18. data/ext/ffi_c/NullPointer.c +143 -0
  19. data/ext/ffi_c/Platform.c +59 -0
  20. data/ext/ffi_c/Platform.h +16 -0
  21. data/ext/ffi_c/Pointer.c +164 -0
  22. data/ext/ffi_c/Pointer.h +25 -0
  23. data/ext/ffi_c/Struct.c +477 -0
  24. data/ext/ffi_c/Struct.h +26 -0
  25. data/ext/ffi_c/Type.c +230 -0
  26. data/ext/ffi_c/Type.h +28 -0
  27. data/ext/ffi_c/Types.c +118 -0
  28. data/ext/ffi_c/Types.h +54 -0
  29. data/ext/ffi_c/compat.h +22 -0
  30. data/ext/ffi_c/endian.h +40 -0
  31. data/ext/ffi_c/extconf.rb +31 -0
  32. data/ext/ffi_c/ffi.c +76 -0
  33. data/ext/ffi_c/libffi.bsd.mk +34 -0
  34. data/ext/ffi_c/libffi.darwin.mk +75 -0
  35. data/ext/ffi_c/libffi.gnu.mk +29 -0
  36. data/ext/ffi_c/libffi.mk +13 -0
  37. data/ext/ffi_c/libffi/ChangeLog +3243 -0
  38. data/ext/ffi_c/libffi/ChangeLog.libffi +347 -0
  39. data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
  40. data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
  41. data/ext/ffi_c/libffi/LICENSE +21 -0
  42. data/ext/ffi_c/libffi/Makefile.am +177 -0
  43. data/ext/ffi_c/libffi/Makefile.in +1640 -0
  44. data/ext/ffi_c/libffi/README +328 -0
  45. data/ext/ffi_c/libffi/TODO +1 -0
  46. data/ext/ffi_c/libffi/acinclude.m4 +92 -0
  47. data/ext/ffi_c/libffi/aclocal.m4 +7516 -0
  48. data/ext/ffi_c/libffi/compile +142 -0
  49. data/ext/ffi_c/libffi/config.guess +1516 -0
  50. data/ext/ffi_c/libffi/config.sub +1626 -0
  51. data/ext/ffi_c/libffi/configure +24414 -0
  52. data/ext/ffi_c/libffi/configure.ac +365 -0
  53. data/ext/ffi_c/libffi/configure.host +11 -0
  54. data/ext/ffi_c/libffi/depcomp +584 -0
  55. data/ext/ffi_c/libffi/doc/libffi.info +533 -0
  56. data/ext/ffi_c/libffi/doc/libffi.texi +541 -0
  57. data/ext/ffi_c/libffi/doc/stamp-vti +4 -0
  58. data/ext/ffi_c/libffi/doc/version.texi +4 -0
  59. data/ext/ffi_c/libffi/fficonfig.h.in +160 -0
  60. data/ext/ffi_c/libffi/include/Makefile.am +9 -0
  61. data/ext/ffi_c/libffi/include/Makefile.in +422 -0
  62. data/ext/ffi_c/libffi/include/ffi.h.in +393 -0
  63. data/ext/ffi_c/libffi/include/ffi_common.h +98 -0
  64. data/ext/ffi_c/libffi/install-sh +323 -0
  65. data/ext/ffi_c/libffi/libffi.pc.in +10 -0
  66. data/ext/ffi_c/libffi/libtool-version +29 -0
  67. data/ext/ffi_c/libffi/ltcf-c.sh +861 -0
  68. data/ext/ffi_c/libffi/ltcf-cxx.sh +1069 -0
  69. data/ext/ffi_c/libffi/ltcf-gcj.sh +700 -0
  70. data/ext/ffi_c/libffi/ltconfig +2862 -0
  71. data/ext/ffi_c/libffi/ltmain.sh +6930 -0
  72. data/ext/ffi_c/libffi/man/Makefile.am +8 -0
  73. data/ext/ffi_c/libffi/man/Makefile.in +395 -0
  74. data/ext/ffi_c/libffi/man/ffi.3 +31 -0
  75. data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
  76. data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +66 -0
  77. data/ext/ffi_c/libffi/mdate-sh +201 -0
  78. data/ext/ffi_c/libffi/missing +353 -0
  79. data/ext/ffi_c/libffi/mkinstalldirs +158 -0
  80. data/ext/ffi_c/libffi/src/alpha/ffi.c +284 -0
  81. data/ext/ffi_c/libffi/src/alpha/ffitarget.h +48 -0
  82. data/ext/ffi_c/libffi/src/alpha/osf.S +366 -0
  83. data/ext/ffi_c/libffi/src/arm/ffi.c +309 -0
  84. data/ext/ffi_c/libffi/src/arm/ffitarget.h +49 -0
  85. data/ext/ffi_c/libffi/src/arm/sysv.S +299 -0
  86. data/ext/ffi_c/libffi/src/closures.c +596 -0
  87. data/ext/ffi_c/libffi/src/cris/ffi.c +383 -0
  88. data/ext/ffi_c/libffi/src/cris/ffitarget.h +51 -0
  89. data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
  90. data/ext/ffi_c/libffi/src/debug.c +59 -0
  91. data/ext/ffi_c/libffi/src/dlmalloc.c +5099 -0
  92. data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
  93. data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
  94. data/ext/ffi_c/libffi/src/frv/ffitarget.h +61 -0
  95. data/ext/ffi_c/libffi/src/ia64/ffi.c +580 -0
  96. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +50 -0
  97. data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
  98. data/ext/ffi_c/libffi/src/ia64/unix.S +560 -0
  99. data/ext/ffi_c/libffi/src/java_raw_api.c +359 -0
  100. data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
  101. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +48 -0
  102. data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
  103. data/ext/ffi_c/libffi/src/m68k/ffi.c +278 -0
  104. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
  105. data/ext/ffi_c/libffi/src/m68k/sysv.S +234 -0
  106. data/ext/ffi_c/libffi/src/mips/ffi.c +926 -0
  107. data/ext/ffi_c/libffi/src/mips/ffitarget.h +202 -0
  108. data/ext/ffi_c/libffi/src/mips/n32.S +534 -0
  109. data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
  110. data/ext/ffi_c/libffi/src/pa/ffi.c +709 -0
  111. data/ext/ffi_c/libffi/src/pa/ffitarget.h +77 -0
  112. data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
  113. data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
  114. data/ext/ffi_c/libffi/src/powerpc/aix.S +225 -0
  115. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +247 -0
  116. data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
  117. data/ext/ffi_c/libffi/src/powerpc/darwin.S +245 -0
  118. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +317 -0
  119. data/ext/ffi_c/libffi/src/powerpc/ffi.c +1429 -0
  120. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +800 -0
  121. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +118 -0
  122. data/ext/ffi_c/libffi/src/powerpc/linux64.S +187 -0
  123. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +236 -0
  124. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +327 -0
  125. data/ext/ffi_c/libffi/src/powerpc/sysv.S +230 -0
  126. data/ext/ffi_c/libffi/src/prep_cif.c +174 -0
  127. data/ext/ffi_c/libffi/src/raw_api.c +254 -0
  128. data/ext/ffi_c/libffi/src/s390/ffi.c +780 -0
  129. data/ext/ffi_c/libffi/src/s390/ffitarget.h +60 -0
  130. data/ext/ffi_c/libffi/src/s390/sysv.S +434 -0
  131. data/ext/ffi_c/libffi/src/sh/ffi.c +716 -0
  132. data/ext/ffi_c/libffi/src/sh/ffitarget.h +49 -0
  133. data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
  134. data/ext/ffi_c/libffi/src/sh64/ffi.c +453 -0
  135. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
  136. data/ext/ffi_c/libffi/src/sh64/sysv.S +530 -0
  137. data/ext/ffi_c/libffi/src/sparc/ffi.c +610 -0
  138. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +66 -0
  139. data/ext/ffi_c/libffi/src/sparc/v8.S +272 -0
  140. data/ext/ffi_c/libffi/src/sparc/v9.S +307 -0
  141. data/ext/ffi_c/libffi/src/types.c +77 -0
  142. data/ext/ffi_c/libffi/src/x86/darwin.S +443 -0
  143. data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
  144. data/ext/ffi_c/libffi/src/x86/ffi.c +475 -0
  145. data/ext/ffi_c/libffi/src/x86/ffi64.c +572 -0
  146. data/ext/ffi_c/libffi/src/x86/ffitarget.h +90 -0
  147. data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
  148. data/ext/ffi_c/libffi/src/x86/sysv.S +437 -0
  149. data/ext/ffi_c/libffi/src/x86/unix64.S +418 -0
  150. data/ext/ffi_c/libffi/src/x86/win32.S +391 -0
  151. data/ext/ffi_c/libffi/testsuite/Makefile.am +71 -0
  152. data/ext/ffi_c/libffi/testsuite/Makefile.in +447 -0
  153. data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
  154. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +289 -0
  155. data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +263 -0
  156. data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
  157. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +36 -0
  158. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +97 -0
  159. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +89 -0
  160. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +89 -0
  161. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +90 -0
  162. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +97 -0
  163. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +99 -0
  164. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +98 -0
  165. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +72 -0
  166. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +102 -0
  167. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +103 -0
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +104 -0
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +110 -0
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +97 -0
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +99 -0
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +101 -0
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +121 -0
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +98 -0
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +103 -0
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +98 -0
  177. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +98 -0
  178. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +106 -0
  179. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +98 -0
  180. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +117 -0
  181. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +106 -0
  182. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +132 -0
  183. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +121 -0
  184. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +107 -0
  185. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +125 -0
  186. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +105 -0
  187. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +96 -0
  188. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +98 -0
  189. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +99 -0
  190. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +101 -0
  191. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +99 -0
  192. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +100 -0
  193. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +101 -0
  194. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +99 -0
  195. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +99 -0
  196. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +99 -0
  197. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +99 -0
  198. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +99 -0
  199. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +100 -0
  200. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +51 -0
  201. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +51 -0
  202. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +82 -0
  203. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +82 -0
  204. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +94 -0
  205. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +99 -0
  206. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +82 -0
  207. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +94 -0
  208. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +52 -0
  209. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +50 -0
  210. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +50 -0
  211. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +50 -0
  212. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +51 -0
  213. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +54 -0
  214. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +51 -0
  215. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +86 -0
  216. data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
  217. data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +58 -0
  218. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +57 -0
  219. data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +72 -0
  220. data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
  221. data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +69 -0
  222. data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +63 -0
  223. data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +53 -0
  224. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +160 -0
  225. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +169 -0
  226. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +141 -0
  227. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +118 -0
  228. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +119 -0
  229. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +119 -0
  230. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +120 -0
  231. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +139 -0
  232. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +119 -0
  233. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +139 -0
  234. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +139 -0
  235. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +98 -0
  236. data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
  237. data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
  238. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +35 -0
  239. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
  240. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
  241. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
  242. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
  243. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
  244. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
  245. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
  246. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
  247. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +42 -0
  248. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
  249. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
  250. data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
  251. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
  252. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
  253. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
  254. data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +65 -0
  255. data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
  256. data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +59 -0
  257. data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +63 -0
  258. data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +65 -0
  259. data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
  260. data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
  261. data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +80 -0
  262. data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +67 -0
  263. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +86 -0
  264. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +38 -0
  265. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +123 -0
  266. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
  267. data/ext/ffi_c/libffi/texinfo.tex +7482 -0
  268. data/ext/ffi_c/rbffi.h +23 -0
  269. data/gen/Rakefile +12 -0
  270. data/lib/1.8/ffi_c.so +0 -0
  271. data/lib/1.9/ffi_c.so +0 -0
  272. data/lib/ffi.rb +11 -0
  273. data/lib/ffi/autopointer.rb +61 -0
  274. data/lib/ffi/buffer.rb +0 -0
  275. data/lib/ffi/callback.rb +10 -0
  276. data/lib/ffi/enum.rb +78 -0
  277. data/lib/ffi/errno.rb +8 -0
  278. data/lib/ffi/ffi.rb +96 -0
  279. data/lib/ffi/io.rb +21 -0
  280. data/lib/ffi/library.rb +243 -0
  281. data/lib/ffi/managedstruct.rb +55 -0
  282. data/lib/ffi/memorypointer.rb +73 -0
  283. data/lib/ffi/platform.rb +78 -0
  284. data/lib/ffi/pointer.rb +119 -0
  285. data/lib/ffi/struct.rb +354 -0
  286. data/lib/ffi/tools/const_generator.rb +177 -0
  287. data/lib/ffi/tools/generator.rb +58 -0
  288. data/lib/ffi/tools/generator_task.rb +35 -0
  289. data/lib/ffi/tools/struct_generator.rb +194 -0
  290. data/lib/ffi/tools/types_generator.rb +123 -0
  291. data/lib/ffi/types.rb +153 -0
  292. data/lib/ffi/union.rb +17 -0
  293. data/lib/ffi/variadic.rb +30 -0
  294. data/spec/ffi/bool_spec.rb +24 -0
  295. data/spec/ffi/buffer_spec.rb +196 -0
  296. data/spec/ffi/callback_spec.rb +560 -0
  297. data/spec/ffi/enum_spec.rb +164 -0
  298. data/spec/ffi/errno_spec.rb +13 -0
  299. data/spec/ffi/library_spec.rb +144 -0
  300. data/spec/ffi/managed_struct_spec.rb +56 -0
  301. data/spec/ffi/number_spec.rb +231 -0
  302. data/spec/ffi/pointer_spec.rb +195 -0
  303. data/spec/ffi/rbx/attach_function_spec.rb +27 -0
  304. data/spec/ffi/rbx/memory_pointer_spec.rb +102 -0
  305. data/spec/ffi/rbx/spec_helper.rb +1 -0
  306. data/spec/ffi/rbx/struct_spec.rb +13 -0
  307. data/spec/ffi/spec_helper.rb +17 -0
  308. data/spec/ffi/string_spec.rb +103 -0
  309. data/spec/ffi/struct_callback_spec.rb +41 -0
  310. data/spec/ffi/struct_initialize_spec.rb +30 -0
  311. data/spec/ffi/struct_spec.rb +476 -0
  312. data/spec/ffi/typedef_spec.rb +48 -0
  313. data/spec/ffi/union_spec.rb +60 -0
  314. data/spec/ffi/variadic_spec.rb +84 -0
  315. data/spec/spec.opts +4 -0
  316. metadata +375 -0
@@ -0,0 +1,49 @@
1
+ /* -----------------------------------------------------------------*-C-*-
2
+ ffitarget.h - Copyright (c) 1996-2003 Red Hat, Inc.
3
+ Target configuration macros for ARM.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ ``Software''), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be included
14
+ in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ DEALINGS IN THE SOFTWARE.
24
+
25
+ ----------------------------------------------------------------------- */
26
+
27
+ #ifndef LIBFFI_TARGET_H
28
+ #define LIBFFI_TARGET_H
29
+
30
+ #ifndef LIBFFI_ASM
31
+ typedef unsigned long ffi_arg;
32
+ typedef signed long ffi_sarg;
33
+
34
+ typedef enum ffi_abi {
35
+ FFI_FIRST_ABI = 0,
36
+ FFI_SYSV,
37
+ FFI_DEFAULT_ABI = FFI_SYSV,
38
+ FFI_LAST_ABI = FFI_DEFAULT_ABI + 1
39
+ } ffi_abi;
40
+ #endif
41
+
42
+ /* ---- Definitions for closures ----------------------------------------- */
43
+
44
+ #define FFI_CLOSURES 1
45
+ #define FFI_TRAMPOLINE_SIZE 20
46
+ #define FFI_NATIVE_RAW_API 0
47
+
48
+ #endif
49
+
@@ -0,0 +1,299 @@
1
+ /* -----------------------------------------------------------------------
2
+ sysv.S - Copyright (c) 1998, 2008 Red Hat, Inc.
3
+
4
+ ARM Foreign Function Interface
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ ``Software''), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be included
15
+ in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
21
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
22
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24
+ DEALINGS IN THE SOFTWARE.
25
+ ----------------------------------------------------------------------- */
26
+
27
+ #define LIBFFI_ASM
28
+ #include <fficonfig.h>
29
+ #include <ffi.h>
30
+ #ifdef HAVE_MACHINE_ASM_H
31
+ #include <machine/asm.h>
32
+ #else
33
+ #ifdef __USER_LABEL_PREFIX__
34
+ #define CONCAT1(a, b) CONCAT2(a, b)
35
+ #define CONCAT2(a, b) a ## b
36
+
37
+ /* Use the right prefix for global labels. */
38
+ #define CNAME(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
39
+ #else
40
+ #define CNAME(x) x
41
+ #endif
42
+ #define ENTRY(x) .globl CNAME(x); .type CNAME(x),%function; CNAME(x):
43
+ #endif
44
+
45
+ #ifdef __ELF__
46
+ #define LSYM(x) .x
47
+ #else
48
+ #define LSYM(x) x
49
+ #endif
50
+
51
+ /* We need a better way of testing for this, but for now, this is all
52
+ we can do. */
53
+ @ This selects the minimum architecture level required.
54
+ #define __ARM_ARCH__ 3
55
+
56
+ #if defined(__ARM_ARCH_4__) || defined(__ARM_ARCH_4T__)
57
+ # undef __ARM_ARCH__
58
+ # define __ARM_ARCH__ 4
59
+ #endif
60
+
61
+ #if defined(__ARM_ARCH_5__) || defined(__ARM_ARCH_5T__) \
62
+ || defined(__ARM_ARCH_5E__) || defined(__ARM_ARCH_5TE__) \
63
+ || defined(__ARM_ARCH_5TEJ__)
64
+ # undef __ARM_ARCH__
65
+ # define __ARM_ARCH__ 5
66
+ #endif
67
+
68
+ #if defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) \
69
+ || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6Z__) \
70
+ || defined(__ARM_ARCH_6ZK__)
71
+ # undef __ARM_ARCH__
72
+ # define __ARM_ARCH__ 6
73
+ #endif
74
+
75
+ #if __ARM_ARCH__ >= 5
76
+ # define call_reg(x) blx x
77
+ #elif defined (__ARM_ARCH_4T__)
78
+ # define call_reg(x) mov lr, pc ; bx x
79
+ # if defined(__thumb__) || defined(__THUMB_INTERWORK__)
80
+ # define __INTERWORKING__
81
+ # endif
82
+ #else
83
+ # define call_reg(x) mov lr, pc ; mov pc, x
84
+ #endif
85
+
86
+ /* Conditionally compile unwinder directives. */
87
+ #ifdef __ARM_EABI__
88
+ #define UNWIND
89
+ #else
90
+ #define UNWIND @
91
+ #endif
92
+
93
+
94
+ #if defined(__thumb__) && !defined(__THUMB_INTERWORK__)
95
+ .macro ARM_FUNC_START name
96
+ .text
97
+ .align 0
98
+ .thumb
99
+ .thumb_func
100
+ ENTRY(\name)
101
+ bx pc
102
+ nop
103
+ .arm
104
+ UNWIND .fnstart
105
+ /* A hook to tell gdb that we've switched to ARM mode. Also used to call
106
+ directly from other local arm routines. */
107
+ _L__\name:
108
+ .endm
109
+ #else
110
+ .macro ARM_FUNC_START name
111
+ .text
112
+ .align 0
113
+ .arm
114
+ ENTRY(\name)
115
+ UNWIND .fnstart
116
+ .endm
117
+ #endif
118
+
119
+ .macro RETLDM regs=, cond=, dirn=ia
120
+ #if defined (__INTERWORKING__)
121
+ .ifc "\regs",""
122
+ ldr\cond lr, [sp], #4
123
+ .else
124
+ ldm\cond\dirn sp!, {\regs, lr}
125
+ .endif
126
+ bx\cond lr
127
+ #else
128
+ .ifc "\regs",""
129
+ ldr\cond pc, [sp], #4
130
+ .else
131
+ ldm\cond\dirn sp!, {\regs, pc}
132
+ .endif
133
+ #endif
134
+ .endm
135
+
136
+
137
+ @ r0: ffi_prep_args
138
+ @ r1: &ecif
139
+ @ r2: cif->bytes
140
+ @ r3: fig->flags
141
+ @ sp+0: ecif.rvalue
142
+ @ sp+4: fn
143
+
144
+ @ This assumes we are using gas.
145
+ ARM_FUNC_START ffi_call_SYSV
146
+ @ Save registers
147
+ stmfd sp!, {r0-r3, fp, lr}
148
+ UNWIND .save {r0-r3, fp, lr}
149
+ mov fp, sp
150
+
151
+ UNWIND .setfp fp, sp
152
+
153
+ @ Make room for all of the new args.
154
+ sub sp, fp, r2
155
+
156
+ @ Place all of the ffi_prep_args in position
157
+ mov ip, r0
158
+ mov r0, sp
159
+ @ r1 already set
160
+
161
+ @ Call ffi_prep_args(stack, &ecif)
162
+ call_reg(ip)
163
+
164
+ @ move first 4 parameters in registers
165
+ ldmia sp, {r0-r3}
166
+
167
+ @ and adjust stack
168
+ ldr ip, [fp, #8]
169
+ cmp ip, #16
170
+ movhs ip, #16
171
+ add sp, sp, ip
172
+
173
+ @ call (fn) (...)
174
+ ldr ip, [fp, #28]
175
+ call_reg(ip)
176
+
177
+ @ Remove the space we pushed for the args
178
+ mov sp, fp
179
+
180
+ @ Load r2 with the pointer to storage for the return value
181
+ ldr r2, [sp, #24]
182
+
183
+ @ Load r3 with the return type code
184
+ ldr r3, [sp, #12]
185
+
186
+ @ If the return value pointer is NULL, assume no return value.
187
+ cmp r2, #0
188
+ beq LSYM(Lepilogue)
189
+
190
+ @ return INT
191
+ cmp r3, #FFI_TYPE_INT
192
+ #ifdef __SOFTFP__
193
+ cmpne r3, #FFI_TYPE_FLOAT
194
+ #endif
195
+ streq r0, [r2]
196
+ beq LSYM(Lepilogue)
197
+
198
+ @ return INT64
199
+ cmp r3, #FFI_TYPE_SINT64
200
+ #ifdef __SOFTFP__
201
+ cmpne r3, #FFI_TYPE_DOUBLE
202
+ #endif
203
+ stmeqia r2, {r0, r1}
204
+
205
+ #ifndef __SOFTFP__
206
+ beq LSYM(Lepilogue)
207
+
208
+ @ return FLOAT
209
+ cmp r3, #FFI_TYPE_FLOAT
210
+ stfeqs f0, [r2]
211
+ beq LSYM(Lepilogue)
212
+
213
+ @ return DOUBLE or LONGDOUBLE
214
+ cmp r3, #FFI_TYPE_DOUBLE
215
+ stfeqd f0, [r2]
216
+ #endif
217
+
218
+ LSYM(Lepilogue):
219
+ RETLDM "r0-r3,fp"
220
+
221
+ .ffi_call_SYSV_end:
222
+ UNWIND .fnend
223
+ .size CNAME(ffi_call_SYSV),.ffi_call_SYSV_end-CNAME(ffi_call_SYSV)
224
+
225
+ /*
226
+ unsigned int FFI_HIDDEN
227
+ ffi_closure_SYSV_inner (closure, respp, args)
228
+ ffi_closure *closure;
229
+ void **respp;
230
+ void *args;
231
+ */
232
+
233
+ ARM_FUNC_START ffi_closure_SYSV
234
+ UNWIND .pad #16
235
+ add ip, sp, #16
236
+ stmfd sp!, {ip, lr}
237
+ UNWIND .save {r0, lr}
238
+ add r2, sp, #8
239
+ .pad #16
240
+ sub sp, sp, #16
241
+ str sp, [sp, #8]
242
+ add r1, sp, #8
243
+ bl ffi_closure_SYSV_inner
244
+ cmp r0, #FFI_TYPE_INT
245
+ beq .Lretint
246
+
247
+ cmp r0, #FFI_TYPE_FLOAT
248
+ #ifdef __SOFTFP__
249
+ beq .Lretint
250
+ #else
251
+ beq .Lretfloat
252
+ #endif
253
+
254
+ cmp r0, #FFI_TYPE_DOUBLE
255
+ #ifdef __SOFTFP__
256
+ beq .Lretlonglong
257
+ #else
258
+ beq .Lretdouble
259
+ #endif
260
+
261
+ cmp r0, #FFI_TYPE_LONGDOUBLE
262
+ #ifdef __SOFTFP__
263
+ beq .Lretlonglong
264
+ #else
265
+ beq .Lretlongdouble
266
+ #endif
267
+
268
+ cmp r0, #FFI_TYPE_SINT64
269
+ beq .Lretlonglong
270
+ .Lclosure_epilogue:
271
+ add sp, sp, #16
272
+ ldmfd sp, {sp, pc}
273
+ .Lretint:
274
+ ldr r0, [sp]
275
+ b .Lclosure_epilogue
276
+ .Lretlonglong:
277
+ ldr r0, [sp]
278
+ ldr r1, [sp, #4]
279
+ b .Lclosure_epilogue
280
+
281
+ #ifndef __SOFTFP__
282
+ .Lretfloat:
283
+ ldfs f0, [sp]
284
+ b .Lclosure_epilogue
285
+ .Lretdouble:
286
+ ldfd f0, [sp]
287
+ b .Lclosure_epilogue
288
+ .Lretlongdouble:
289
+ ldfd f0, [sp]
290
+ b .Lclosure_epilogue
291
+ #endif
292
+
293
+ .ffi_closure_SYSV_end:
294
+ UNWIND .fnend
295
+ .size CNAME(ffi_closure_SYSV),.ffi_closure_SYSV_end-CNAME(ffi_closure_SYSV)
296
+
297
+ #if defined __ELF__ && defined __linux__
298
+ .section .note.GNU-stack,"",%progbits
299
+ #endif
@@ -0,0 +1,596 @@
1
+ /* -----------------------------------------------------------------------
2
+ closures.c - Copyright (c) 2007 Red Hat, Inc.
3
+ Copyright (C) 2007 Free Software Foundation, Inc
4
+
5
+ Code to allocate and deallocate memory for closures.
6
+
7
+ Permission is hereby granted, free of charge, to any person obtaining
8
+ a copy of this software and associated documentation files (the
9
+ ``Software''), to deal in the Software without restriction, including
10
+ without limitation the rights to use, copy, modify, merge, publish,
11
+ distribute, sublicense, and/or sell copies of the Software, and to
12
+ permit persons to whom the Software is furnished to do so, subject to
13
+ the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included
16
+ in all copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED ``AS IS'', WITHOUT WARRANTY OF ANY KIND,
19
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25
+ DEALINGS IN THE SOFTWARE.
26
+ ----------------------------------------------------------------------- */
27
+
28
+ #if defined __linux__ && !defined _GNU_SOURCE
29
+ #define _GNU_SOURCE 1
30
+ #endif
31
+
32
+ #include <ffi.h>
33
+ #include <ffi_common.h>
34
+
35
+ #ifndef FFI_MMAP_EXEC_WRIT
36
+ # if __gnu_linux__
37
+ /* This macro indicates it may be forbidden to map anonymous memory
38
+ with both write and execute permission. Code compiled when this
39
+ option is defined will attempt to map such pages once, but if it
40
+ fails, it falls back to creating a temporary file in a writable and
41
+ executable filesystem and mapping pages from it into separate
42
+ locations in the virtual memory space, one location writable and
43
+ another executable. */
44
+ # define FFI_MMAP_EXEC_WRIT 1
45
+ # define HAVE_MNTENT 1
46
+ # endif
47
+ # ifdef X86_WIN32
48
+ /* Windows systems may have Data Execution Protection (DEP) enabled,
49
+ which requires the use of VirtualMalloc/VirtualFree to alloc/free
50
+ executable memory. */
51
+ # define FFI_MMAP_EXEC_WRIT 1
52
+ # endif
53
+ #endif
54
+
55
+ #if FFI_MMAP_EXEC_WRIT && !defined FFI_MMAP_EXEC_SELINUX
56
+ # ifdef __linux__
57
+ /* When defined to 1 check for SELinux and if SELinux is active,
58
+ don't attempt PROT_EXEC|PROT_WRITE mapping at all, as that
59
+ might cause audit messages. */
60
+ # define FFI_MMAP_EXEC_SELINUX 1
61
+ # endif
62
+ #endif
63
+
64
+ #if FFI_CLOSURES
65
+
66
+ # if FFI_MMAP_EXEC_WRIT
67
+
68
+ #define USE_LOCKS 1
69
+ #define USE_DL_PREFIX 1
70
+ #define USE_BUILTIN_FFS 1
71
+
72
+ /* We need to use mmap, not sbrk. */
73
+ #define HAVE_MORECORE 0
74
+
75
+ /* We could, in theory, support mremap, but it wouldn't buy us anything. */
76
+ #define HAVE_MREMAP 0
77
+
78
+ /* We have no use for this, so save some code and data. */
79
+ #define NO_MALLINFO 1
80
+
81
+ /* We need all allocations to be in regular segments, otherwise we
82
+ lose track of the corresponding code address. */
83
+ #define DEFAULT_MMAP_THRESHOLD MAX_SIZE_T
84
+
85
+ /* Don't allocate more than a page unless needed. */
86
+ #define DEFAULT_GRANULARITY ((size_t)malloc_getpagesize)
87
+
88
+ #if FFI_CLOSURE_TEST
89
+ /* Don't release single pages, to avoid a worst-case scenario of
90
+ continuously allocating and releasing single pages, but release
91
+ pairs of pages, which should do just as well given that allocations
92
+ are likely to be small. */
93
+ #define DEFAULT_TRIM_THRESHOLD ((size_t)malloc_getpagesize)
94
+ #endif
95
+
96
+ #include <sys/types.h>
97
+ #include <sys/stat.h>
98
+ #include <fcntl.h>
99
+ #include <errno.h>
100
+ #include <unistd.h>
101
+ #include <string.h>
102
+ #include <stdio.h>
103
+ #ifndef X86_WIN32
104
+ #ifdef HAVE_MNTENT
105
+ #include <mntent.h>
106
+ #endif /* HAVE_MNTENT */
107
+ #include <sys/param.h>
108
+ #include <pthread.h>
109
+
110
+ /* We don't want sys/mman.h to be included after we redefine mmap and
111
+ dlmunmap. */
112
+ #include <sys/mman.h>
113
+ #define LACKS_SYS_MMAN_H 1
114
+
115
+ #if FFI_MMAP_EXEC_SELINUX
116
+ #include <sys/statfs.h>
117
+ #include <stdlib.h>
118
+
119
+ static int selinux_enabled = -1;
120
+
121
+ static int
122
+ selinux_enabled_check (void)
123
+ {
124
+ struct statfs sfs;
125
+ FILE *f;
126
+ char *buf = NULL;
127
+ size_t len = 0;
128
+
129
+ if (statfs ("/selinux", &sfs) >= 0
130
+ && (unsigned int) sfs.f_type == 0xf97cff8cU)
131
+ return 1;
132
+ f = fopen ("/proc/mounts", "r");
133
+ if (f == NULL)
134
+ return 0;
135
+ while (getline (&buf, &len, f) >= 0)
136
+ {
137
+ char *p = strchr (buf, ' ');
138
+ if (p == NULL)
139
+ break;
140
+ p = strchr (p + 1, ' ');
141
+ if (p == NULL)
142
+ break;
143
+ if (strncmp (p + 1, "selinuxfs ", 10) != 0)
144
+ {
145
+ free (buf);
146
+ fclose (f);
147
+ return 1;
148
+ }
149
+ }
150
+ free (buf);
151
+ fclose (f);
152
+ return 0;
153
+ }
154
+
155
+ #define is_selinux_enabled() (selinux_enabled >= 0 ? selinux_enabled \
156
+ : (selinux_enabled = selinux_enabled_check ()))
157
+
158
+ #else
159
+
160
+ #define is_selinux_enabled() 0
161
+
162
+ #endif
163
+ #endif /* X86_WIN32 */
164
+
165
+ /* Declare all functions defined in dlmalloc.c as static. */
166
+ static void *dlmalloc(size_t);
167
+ static void dlfree(void*);
168
+ static void *dlcalloc(size_t, size_t) MAYBE_UNUSED;
169
+ static void *dlrealloc(void *, size_t) MAYBE_UNUSED;
170
+ static void *dlmemalign(size_t, size_t) MAYBE_UNUSED;
171
+ static void *dlvalloc(size_t) MAYBE_UNUSED;
172
+ static int dlmallopt(int, int) MAYBE_UNUSED;
173
+ static size_t dlmalloc_footprint(void) MAYBE_UNUSED;
174
+ static size_t dlmalloc_max_footprint(void) MAYBE_UNUSED;
175
+ static void** dlindependent_calloc(size_t, size_t, void**) MAYBE_UNUSED;
176
+ static void** dlindependent_comalloc(size_t, size_t*, void**) MAYBE_UNUSED;
177
+ static void *dlpvalloc(size_t) MAYBE_UNUSED;
178
+ static int dlmalloc_trim(size_t) MAYBE_UNUSED;
179
+ static size_t dlmalloc_usable_size(void*) MAYBE_UNUSED;
180
+ static void dlmalloc_stats(void) MAYBE_UNUSED;
181
+
182
+ #ifndef X86_WIN32
183
+ /* Use these for mmap and munmap within dlmalloc.c. */
184
+ static void *dlmmap(void *, size_t, int, int, int, off_t);
185
+ static int dlmunmap(void *, size_t);
186
+ #endif /* X86_WIN32 */
187
+
188
+ #define mmap dlmmap
189
+ #define munmap dlmunmap
190
+
191
+ #include "dlmalloc.c"
192
+
193
+ #undef mmap
194
+ #undef munmap
195
+
196
+ #ifndef X86_WIN32
197
+
198
+ /* A mutex used to synchronize access to *exec* variables in this file. */
199
+ static pthread_mutex_t open_temp_exec_file_mutex = PTHREAD_MUTEX_INITIALIZER;
200
+
201
+ /* A file descriptor of a temporary file from which we'll map
202
+ executable pages. */
203
+ static int execfd = -1;
204
+
205
+ /* The amount of space already allocated from the temporary file. */
206
+ static size_t execsize = 0;
207
+
208
+ /* Open a temporary file name, and immediately unlink it. */
209
+ static int
210
+ open_temp_exec_file_name (char *name)
211
+ {
212
+ int fd = mkstemp (name);
213
+
214
+ if (fd != -1)
215
+ unlink (name);
216
+
217
+ return fd;
218
+ }
219
+
220
+ /* Open a temporary file in the named directory. */
221
+ static int
222
+ open_temp_exec_file_dir (const char *dir)
223
+ {
224
+ static const char suffix[] = "/ffiXXXXXX";
225
+ int lendir = strlen (dir);
226
+ char *tempname = __builtin_alloca (lendir + sizeof (suffix));
227
+
228
+ if (!tempname)
229
+ return -1;
230
+
231
+ memcpy (tempname, dir, lendir);
232
+ memcpy (tempname + lendir, suffix, sizeof (suffix));
233
+
234
+ return open_temp_exec_file_name (tempname);
235
+ }
236
+
237
+ /* Open a temporary file in the directory in the named environment
238
+ variable. */
239
+ static int
240
+ open_temp_exec_file_env (const char *envvar)
241
+ {
242
+ const char *value = getenv (envvar);
243
+
244
+ if (!value)
245
+ return -1;
246
+
247
+ return open_temp_exec_file_dir (value);
248
+ }
249
+
250
+ #ifdef HAVE_MNTENT
251
+ /* Open a temporary file in an executable and writable mount point
252
+ listed in the mounts file. Subsequent calls with the same mounts
253
+ keep searching for mount points in the same file. Providing NULL
254
+ as the mounts file closes the file. */
255
+ static int
256
+ open_temp_exec_file_mnt (const char *mounts)
257
+ {
258
+ static const char *last_mounts;
259
+ static FILE *last_mntent;
260
+
261
+ if (mounts != last_mounts)
262
+ {
263
+ if (last_mntent)
264
+ endmntent (last_mntent);
265
+
266
+ last_mounts = mounts;
267
+
268
+ if (mounts)
269
+ last_mntent = setmntent (mounts, "r");
270
+ else
271
+ last_mntent = NULL;
272
+ }
273
+
274
+ if (!last_mntent)
275
+ return -1;
276
+
277
+ for (;;)
278
+ {
279
+ int fd;
280
+ struct mntent mnt;
281
+ char buf[MAXPATHLEN * 3];
282
+
283
+ if (getmntent_r (last_mntent, &mnt, buf, sizeof (buf)))
284
+ return -1;
285
+
286
+ if (hasmntopt (&mnt, "ro")
287
+ || hasmntopt (&mnt, "noexec")
288
+ || access (mnt.mnt_dir, W_OK))
289
+ continue;
290
+
291
+ fd = open_temp_exec_file_dir (mnt.mnt_dir);
292
+
293
+ if (fd != -1)
294
+ return fd;
295
+ }
296
+ }
297
+ #endif /* HAVE_MNTENT */
298
+
299
+ /* Instructions to look for a location to hold a temporary file that
300
+ can be mapped in for execution. */
301
+ static struct
302
+ {
303
+ int (*func)(const char *);
304
+ const char *arg;
305
+ int repeat;
306
+ } open_temp_exec_file_opts[] = {
307
+ { open_temp_exec_file_env, "TMPDIR", 0 },
308
+ { open_temp_exec_file_dir, "/tmp", 0 },
309
+ { open_temp_exec_file_dir, "/var/tmp", 0 },
310
+ { open_temp_exec_file_dir, "/dev/shm", 0 },
311
+ { open_temp_exec_file_env, "HOME", 0 },
312
+ #ifdef HAVE_MNTENT
313
+ { open_temp_exec_file_mnt, "/etc/mtab", 1 },
314
+ { open_temp_exec_file_mnt, "/proc/mounts", 1 },
315
+ #endif /* HAVE_MNTENT */
316
+ };
317
+
318
+ /* Current index into open_temp_exec_file_opts. */
319
+ static int open_temp_exec_file_opts_idx = 0;
320
+
321
+ /* Reset a current multi-call func, then advances to the next entry.
322
+ If we're at the last, go back to the first and return nonzero,
323
+ otherwise return zero. */
324
+ static int
325
+ open_temp_exec_file_opts_next (void)
326
+ {
327
+ if (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
328
+ open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func (NULL);
329
+
330
+ open_temp_exec_file_opts_idx++;
331
+ if (open_temp_exec_file_opts_idx
332
+ == (sizeof (open_temp_exec_file_opts)
333
+ / sizeof (*open_temp_exec_file_opts)))
334
+ {
335
+ open_temp_exec_file_opts_idx = 0;
336
+ return 1;
337
+ }
338
+
339
+ return 0;
340
+ }
341
+
342
+ /* Return a file descriptor of a temporary zero-sized file in a
343
+ writable and exexutable filesystem. */
344
+ static int
345
+ open_temp_exec_file (void)
346
+ {
347
+ int fd;
348
+
349
+ do
350
+ {
351
+ fd = open_temp_exec_file_opts[open_temp_exec_file_opts_idx].func
352
+ (open_temp_exec_file_opts[open_temp_exec_file_opts_idx].arg);
353
+
354
+ if (!open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat
355
+ || fd == -1)
356
+ {
357
+ if (open_temp_exec_file_opts_next ())
358
+ break;
359
+ }
360
+ }
361
+ while (fd == -1);
362
+
363
+ return fd;
364
+ }
365
+
366
+ /* Map in a chunk of memory from the temporary exec file into separate
367
+ locations in the virtual memory address space, one writable and one
368
+ executable. Returns the address of the writable portion, after
369
+ storing an offset to the corresponding executable portion at the
370
+ last word of the requested chunk. */
371
+ static void *
372
+ dlmmap_locked (void *start, size_t length, int prot, int flags, off_t offset)
373
+ {
374
+ void *ptr;
375
+
376
+ if (execfd == -1)
377
+ {
378
+ open_temp_exec_file_opts_idx = 0;
379
+ retry_open:
380
+ execfd = open_temp_exec_file ();
381
+ if (execfd == -1)
382
+ return MFAIL;
383
+ }
384
+
385
+ offset = execsize;
386
+
387
+ if (ftruncate (execfd, offset + length))
388
+ return MFAIL;
389
+
390
+ flags &= ~(MAP_PRIVATE | MAP_ANONYMOUS);
391
+ flags |= MAP_SHARED;
392
+
393
+ ptr = mmap (NULL, length, (prot & ~PROT_WRITE) | PROT_EXEC,
394
+ flags, execfd, offset);
395
+ if (ptr == MFAIL)
396
+ {
397
+ if (!offset)
398
+ {
399
+ close (execfd);
400
+ goto retry_open;
401
+ }
402
+ ftruncate (execfd, offset);
403
+ return MFAIL;
404
+ }
405
+ else if (!offset
406
+ && open_temp_exec_file_opts[open_temp_exec_file_opts_idx].repeat)
407
+ open_temp_exec_file_opts_next ();
408
+
409
+ start = mmap (start, length, prot, flags, execfd, offset);
410
+
411
+ if (start == MFAIL)
412
+ {
413
+ munmap (ptr, length);
414
+ ftruncate (execfd, offset);
415
+ return start;
416
+ }
417
+
418
+ mmap_exec_offset ((char *)start, length) = (char*)ptr - (char*)start;
419
+
420
+ execsize += length;
421
+
422
+ return start;
423
+ }
424
+
425
+ /* Map in a writable and executable chunk of memory if possible.
426
+ Failing that, fall back to dlmmap_locked. */
427
+ static void *
428
+ dlmmap (void *start, size_t length, int prot,
429
+ int flags, int fd, off_t offset)
430
+ {
431
+ void *ptr;
432
+
433
+ assert (start == NULL && length % malloc_getpagesize == 0
434
+ && prot == (PROT_READ | PROT_WRITE)
435
+ && flags == (MAP_PRIVATE | MAP_ANONYMOUS)
436
+ && fd == -1 && offset == 0);
437
+
438
+ #if FFI_CLOSURE_TEST
439
+ printf ("mapping in %zi\n", length);
440
+ #endif
441
+
442
+ if (execfd == -1 && !is_selinux_enabled ())
443
+ {
444
+ ptr = mmap (start, length, prot | PROT_EXEC, flags, fd, offset);
445
+
446
+ if (ptr != MFAIL || (errno != EPERM && errno != EACCES))
447
+ /* Cool, no need to mess with separate segments. */
448
+ return ptr;
449
+
450
+ /* If MREMAP_DUP is ever introduced and implemented, try mmap
451
+ with ((prot & ~PROT_WRITE) | PROT_EXEC) and mremap with
452
+ MREMAP_DUP and prot at this point. */
453
+ }
454
+
455
+ if (execsize == 0 || execfd == -1)
456
+ {
457
+ pthread_mutex_lock (&open_temp_exec_file_mutex);
458
+ ptr = dlmmap_locked (start, length, prot, flags, offset);
459
+ pthread_mutex_unlock (&open_temp_exec_file_mutex);
460
+
461
+ return ptr;
462
+ }
463
+
464
+ return dlmmap_locked (start, length, prot, flags, offset);
465
+ }
466
+
467
+ /* Release memory at the given address, as well as the corresponding
468
+ executable page if it's separate. */
469
+ static int
470
+ dlmunmap (void *start, size_t length)
471
+ {
472
+ /* We don't bother decreasing execsize or truncating the file, since
473
+ we can't quite tell whether we're unmapping the end of the file.
474
+ We don't expect frequent deallocation anyway. If we did, we
475
+ could locate pages in the file by writing to the pages being
476
+ deallocated and checking that the file contents change.
477
+ Yuck. */
478
+ msegmentptr seg = segment_holding (gm, start);
479
+ void *code;
480
+
481
+ #if FFI_CLOSURE_TEST
482
+ printf ("unmapping %zi\n", length);
483
+ #endif
484
+
485
+ if (seg && (code = add_segment_exec_offset (start, seg)) != start)
486
+ {
487
+ int ret = munmap (code, length);
488
+ if (ret)
489
+ return ret;
490
+ }
491
+
492
+ return munmap (start, length);
493
+ }
494
+
495
+ #if FFI_CLOSURE_FREE_CODE
496
+ /* Return segment holding given code address. */
497
+ static msegmentptr
498
+ segment_holding_code (mstate m, char* addr)
499
+ {
500
+ msegmentptr sp = &m->seg;
501
+ for (;;) {
502
+ if (addr >= add_segment_exec_offset (sp->base, sp)
503
+ && addr < add_segment_exec_offset (sp->base, sp) + sp->size)
504
+ return sp;
505
+ if ((sp = sp->next) == 0)
506
+ return 0;
507
+ }
508
+ }
509
+ #endif
510
+
511
+ #endif /* X86_WIN32 */
512
+
513
+ /* Allocate a chunk of memory with the given size. Returns a pointer
514
+ to the writable address, and sets *CODE to the executable
515
+ corresponding virtual address. */
516
+ void *
517
+ ffi_closure_alloc (size_t size, void **code)
518
+ {
519
+ void *ptr;
520
+
521
+ if (!code)
522
+ return NULL;
523
+
524
+ ptr = dlmalloc (size);
525
+
526
+ if (ptr)
527
+ {
528
+ msegmentptr seg = segment_holding (gm, ptr);
529
+
530
+ *code = add_segment_exec_offset (ptr, seg);
531
+ }
532
+
533
+ return ptr;
534
+ }
535
+
536
+ /* Release a chunk of memory allocated with ffi_closure_alloc. If
537
+ FFI_CLOSURE_FREE_CODE is nonzero, the given address can be the
538
+ writable or the executable address given. Otherwise, only the
539
+ writable address can be provided here. */
540
+ void
541
+ ffi_closure_free (void *ptr)
542
+ {
543
+ #if FFI_CLOSURE_FREE_CODE
544
+ msegmentptr seg = segment_holding_code (gm, ptr);
545
+
546
+ if (seg)
547
+ ptr = sub_segment_exec_offset (ptr, seg);
548
+ #endif
549
+
550
+ dlfree (ptr);
551
+ }
552
+
553
+
554
+ #if FFI_CLOSURE_TEST
555
+ /* Do some internal sanity testing to make sure allocation and
556
+ deallocation of pages are working as intended. */
557
+ int main ()
558
+ {
559
+ void *p[3];
560
+ #define GET(idx, len) do { p[idx] = dlmalloc (len); printf ("allocated %zi for p[%i]\n", (len), (idx)); } while (0)
561
+ #define PUT(idx) do { printf ("freeing p[%i]\n", (idx)); dlfree (p[idx]); } while (0)
562
+ GET (0, malloc_getpagesize / 2);
563
+ GET (1, 2 * malloc_getpagesize - 64 * sizeof (void*));
564
+ PUT (1);
565
+ GET (1, 2 * malloc_getpagesize);
566
+ GET (2, malloc_getpagesize / 2);
567
+ PUT (1);
568
+ PUT (0);
569
+ PUT (2);
570
+ return 0;
571
+ }
572
+ #endif /* FFI_CLOSURE_TEST */
573
+ # else /* ! FFI_MMAP_EXEC_WRIT */
574
+
575
+ /* On many systems, memory returned by malloc is writable and
576
+ executable, so just use it. */
577
+
578
+ #include <stdlib.h>
579
+
580
+ void *
581
+ ffi_closure_alloc (size_t size, void **code)
582
+ {
583
+ if (!code)
584
+ return NULL;
585
+
586
+ return *code = malloc (size);
587
+ }
588
+
589
+ void
590
+ ffi_closure_free (void *ptr)
591
+ {
592
+ free (ptr);
593
+ }
594
+
595
+ # endif /* ! FFI_MMAP_EXEC_WRIT */
596
+ #endif /* FFI_CLOSURES */