remogatto-ffi 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (324) hide show
  1. data/LICENSE +51 -0
  2. data/README.rdoc +69 -0
  3. data/Rakefile +144 -0
  4. data/ext/ffi_c/AbstractMemory.c +489 -0
  5. data/ext/ffi_c/AbstractMemory.h +160 -0
  6. data/ext/ffi_c/ArrayType.c +129 -0
  7. data/ext/ffi_c/ArrayType.h +58 -0
  8. data/ext/ffi_c/AutoPointer.c +61 -0
  9. data/ext/ffi_c/AutoPointer.h +18 -0
  10. data/ext/ffi_c/Buffer.c +187 -0
  11. data/ext/ffi_c/Call.c +431 -0
  12. data/ext/ffi_c/Call.h +77 -0
  13. data/ext/ffi_c/DynamicLibrary.c +216 -0
  14. data/ext/ffi_c/DynamicLibrary.h +22 -0
  15. data/ext/ffi_c/Function.c +498 -0
  16. data/ext/ffi_c/Function.h +73 -0
  17. data/ext/ffi_c/FunctionInfo.c +213 -0
  18. data/ext/ffi_c/LastError.c +159 -0
  19. data/ext/ffi_c/LastError.h +18 -0
  20. data/ext/ffi_c/MemoryPointer.c +178 -0
  21. data/ext/ffi_c/MemoryPointer.h +20 -0
  22. data/ext/ffi_c/MethodHandle.c +356 -0
  23. data/ext/ffi_c/MethodHandle.h +53 -0
  24. data/ext/ffi_c/Platform.c +59 -0
  25. data/ext/ffi_c/Platform.h +16 -0
  26. data/ext/ffi_c/Pointer.c +217 -0
  27. data/ext/ffi_c/Pointer.h +49 -0
  28. data/ext/ffi_c/Struct.c +770 -0
  29. data/ext/ffi_c/Struct.h +80 -0
  30. data/ext/ffi_c/StructByValue.c +140 -0
  31. data/ext/ffi_c/StructByValue.h +53 -0
  32. data/ext/ffi_c/StructLayout.c +450 -0
  33. data/ext/ffi_c/Type.c +329 -0
  34. data/ext/ffi_c/Type.h +57 -0
  35. data/ext/ffi_c/Types.c +103 -0
  36. data/ext/ffi_c/Types.h +85 -0
  37. data/ext/ffi_c/Variadic.c +260 -0
  38. data/ext/ffi_c/compat.h +72 -0
  39. data/ext/ffi_c/endian.h +40 -0
  40. data/ext/ffi_c/extconf.rb +34 -0
  41. data/ext/ffi_c/ffi.c +80 -0
  42. data/ext/ffi_c/libffi.bsd.mk +34 -0
  43. data/ext/ffi_c/libffi.darwin.mk +75 -0
  44. data/ext/ffi_c/libffi.gnu.mk +29 -0
  45. data/ext/ffi_c/libffi.mk +13 -0
  46. data/ext/ffi_c/libffi/ChangeLog +3243 -0
  47. data/ext/ffi_c/libffi/ChangeLog.libffi +347 -0
  48. data/ext/ffi_c/libffi/ChangeLog.libgcj +40 -0
  49. data/ext/ffi_c/libffi/ChangeLog.v1 +764 -0
  50. data/ext/ffi_c/libffi/LICENSE +21 -0
  51. data/ext/ffi_c/libffi/Makefile.am +177 -0
  52. data/ext/ffi_c/libffi/Makefile.in +1640 -0
  53. data/ext/ffi_c/libffi/README +328 -0
  54. data/ext/ffi_c/libffi/TODO +1 -0
  55. data/ext/ffi_c/libffi/acinclude.m4 +92 -0
  56. data/ext/ffi_c/libffi/aclocal.m4 +7516 -0
  57. data/ext/ffi_c/libffi/compile +142 -0
  58. data/ext/ffi_c/libffi/config.guess +1516 -0
  59. data/ext/ffi_c/libffi/config.sub +1626 -0
  60. data/ext/ffi_c/libffi/configure +24414 -0
  61. data/ext/ffi_c/libffi/configure.ac +365 -0
  62. data/ext/ffi_c/libffi/configure.host +11 -0
  63. data/ext/ffi_c/libffi/depcomp +584 -0
  64. data/ext/ffi_c/libffi/doc/libffi.info +533 -0
  65. data/ext/ffi_c/libffi/doc/libffi.texi +541 -0
  66. data/ext/ffi_c/libffi/doc/stamp-vti +4 -0
  67. data/ext/ffi_c/libffi/doc/version.texi +4 -0
  68. data/ext/ffi_c/libffi/fficonfig.h.in +160 -0
  69. data/ext/ffi_c/libffi/include/Makefile.am +9 -0
  70. data/ext/ffi_c/libffi/include/Makefile.in +422 -0
  71. data/ext/ffi_c/libffi/include/ffi.h.in +393 -0
  72. data/ext/ffi_c/libffi/include/ffi_common.h +98 -0
  73. data/ext/ffi_c/libffi/install-sh +323 -0
  74. data/ext/ffi_c/libffi/libffi.pc.in +10 -0
  75. data/ext/ffi_c/libffi/libtool-version +29 -0
  76. data/ext/ffi_c/libffi/ltcf-c.sh +861 -0
  77. data/ext/ffi_c/libffi/ltcf-cxx.sh +1069 -0
  78. data/ext/ffi_c/libffi/ltcf-gcj.sh +700 -0
  79. data/ext/ffi_c/libffi/ltconfig +2862 -0
  80. data/ext/ffi_c/libffi/ltmain.sh +6930 -0
  81. data/ext/ffi_c/libffi/man/Makefile.am +8 -0
  82. data/ext/ffi_c/libffi/man/Makefile.in +395 -0
  83. data/ext/ffi_c/libffi/man/ffi.3 +31 -0
  84. data/ext/ffi_c/libffi/man/ffi_call.3 +103 -0
  85. data/ext/ffi_c/libffi/man/ffi_prep_cif.3 +66 -0
  86. data/ext/ffi_c/libffi/mdate-sh +201 -0
  87. data/ext/ffi_c/libffi/missing +353 -0
  88. data/ext/ffi_c/libffi/mkinstalldirs +158 -0
  89. data/ext/ffi_c/libffi/src/alpha/ffi.c +284 -0
  90. data/ext/ffi_c/libffi/src/alpha/ffitarget.h +48 -0
  91. data/ext/ffi_c/libffi/src/alpha/osf.S +366 -0
  92. data/ext/ffi_c/libffi/src/arm/ffi.c +309 -0
  93. data/ext/ffi_c/libffi/src/arm/ffitarget.h +49 -0
  94. data/ext/ffi_c/libffi/src/arm/sysv.S +299 -0
  95. data/ext/ffi_c/libffi/src/closures.c +596 -0
  96. data/ext/ffi_c/libffi/src/cris/ffi.c +383 -0
  97. data/ext/ffi_c/libffi/src/cris/ffitarget.h +51 -0
  98. data/ext/ffi_c/libffi/src/cris/sysv.S +215 -0
  99. data/ext/ffi_c/libffi/src/debug.c +59 -0
  100. data/ext/ffi_c/libffi/src/dlmalloc.c +5099 -0
  101. data/ext/ffi_c/libffi/src/frv/eabi.S +128 -0
  102. data/ext/ffi_c/libffi/src/frv/ffi.c +292 -0
  103. data/ext/ffi_c/libffi/src/frv/ffitarget.h +61 -0
  104. data/ext/ffi_c/libffi/src/ia64/ffi.c +580 -0
  105. data/ext/ffi_c/libffi/src/ia64/ffitarget.h +50 -0
  106. data/ext/ffi_c/libffi/src/ia64/ia64_flags.h +40 -0
  107. data/ext/ffi_c/libffi/src/ia64/unix.S +560 -0
  108. data/ext/ffi_c/libffi/src/java_raw_api.c +359 -0
  109. data/ext/ffi_c/libffi/src/m32r/ffi.c +232 -0
  110. data/ext/ffi_c/libffi/src/m32r/ffitarget.h +48 -0
  111. data/ext/ffi_c/libffi/src/m32r/sysv.S +121 -0
  112. data/ext/ffi_c/libffi/src/m68k/ffi.c +278 -0
  113. data/ext/ffi_c/libffi/src/m68k/ffitarget.h +49 -0
  114. data/ext/ffi_c/libffi/src/m68k/sysv.S +234 -0
  115. data/ext/ffi_c/libffi/src/mips/ffi.c +926 -0
  116. data/ext/ffi_c/libffi/src/mips/ffitarget.h +202 -0
  117. data/ext/ffi_c/libffi/src/mips/n32.S +534 -0
  118. data/ext/ffi_c/libffi/src/mips/o32.S +381 -0
  119. data/ext/ffi_c/libffi/src/pa/ffi.c +709 -0
  120. data/ext/ffi_c/libffi/src/pa/ffitarget.h +77 -0
  121. data/ext/ffi_c/libffi/src/pa/hpux32.S +368 -0
  122. data/ext/ffi_c/libffi/src/pa/linux.S +357 -0
  123. data/ext/ffi_c/libffi/src/powerpc/aix.S +225 -0
  124. data/ext/ffi_c/libffi/src/powerpc/aix_closure.S +247 -0
  125. data/ext/ffi_c/libffi/src/powerpc/asm.h +125 -0
  126. data/ext/ffi_c/libffi/src/powerpc/darwin.S +245 -0
  127. data/ext/ffi_c/libffi/src/powerpc/darwin_closure.S +317 -0
  128. data/ext/ffi_c/libffi/src/powerpc/ffi.c +1429 -0
  129. data/ext/ffi_c/libffi/src/powerpc/ffi_darwin.c +800 -0
  130. data/ext/ffi_c/libffi/src/powerpc/ffitarget.h +118 -0
  131. data/ext/ffi_c/libffi/src/powerpc/linux64.S +187 -0
  132. data/ext/ffi_c/libffi/src/powerpc/linux64_closure.S +236 -0
  133. data/ext/ffi_c/libffi/src/powerpc/ppc_closure.S +327 -0
  134. data/ext/ffi_c/libffi/src/powerpc/sysv.S +230 -0
  135. data/ext/ffi_c/libffi/src/prep_cif.c +174 -0
  136. data/ext/ffi_c/libffi/src/raw_api.c +254 -0
  137. data/ext/ffi_c/libffi/src/s390/ffi.c +780 -0
  138. data/ext/ffi_c/libffi/src/s390/ffitarget.h +60 -0
  139. data/ext/ffi_c/libffi/src/s390/sysv.S +434 -0
  140. data/ext/ffi_c/libffi/src/sh/ffi.c +716 -0
  141. data/ext/ffi_c/libffi/src/sh/ffitarget.h +49 -0
  142. data/ext/ffi_c/libffi/src/sh/sysv.S +850 -0
  143. data/ext/ffi_c/libffi/src/sh64/ffi.c +453 -0
  144. data/ext/ffi_c/libffi/src/sh64/ffitarget.h +53 -0
  145. data/ext/ffi_c/libffi/src/sh64/sysv.S +530 -0
  146. data/ext/ffi_c/libffi/src/sparc/ffi.c +610 -0
  147. data/ext/ffi_c/libffi/src/sparc/ffitarget.h +66 -0
  148. data/ext/ffi_c/libffi/src/sparc/v8.S +272 -0
  149. data/ext/ffi_c/libffi/src/sparc/v9.S +307 -0
  150. data/ext/ffi_c/libffi/src/types.c +77 -0
  151. data/ext/ffi_c/libffi/src/x86/darwin.S +443 -0
  152. data/ext/ffi_c/libffi/src/x86/darwin64.S +416 -0
  153. data/ext/ffi_c/libffi/src/x86/ffi.c +475 -0
  154. data/ext/ffi_c/libffi/src/x86/ffi64.c +572 -0
  155. data/ext/ffi_c/libffi/src/x86/ffitarget.h +90 -0
  156. data/ext/ffi_c/libffi/src/x86/freebsd.S +458 -0
  157. data/ext/ffi_c/libffi/src/x86/sysv.S +437 -0
  158. data/ext/ffi_c/libffi/src/x86/unix64.S +418 -0
  159. data/ext/ffi_c/libffi/src/x86/win32.S +391 -0
  160. data/ext/ffi_c/libffi/testsuite/Makefile.am +71 -0
  161. data/ext/ffi_c/libffi/testsuite/Makefile.in +447 -0
  162. data/ext/ffi_c/libffi/testsuite/config/default.exp +1 -0
  163. data/ext/ffi_c/libffi/testsuite/lib/libffi-dg.exp +289 -0
  164. data/ext/ffi_c/libffi/testsuite/lib/target-libpath.exp +263 -0
  165. data/ext/ffi_c/libffi/testsuite/lib/wrapper.exp +45 -0
  166. data/ext/ffi_c/libffi/testsuite/libffi.call/call.exp +36 -0
  167. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn0.c +97 -0
  168. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn1.c +89 -0
  169. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn2.c +89 -0
  170. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn3.c +90 -0
  171. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn4.c +97 -0
  172. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn5.c +99 -0
  173. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_fn6.c +98 -0
  174. data/ext/ffi_c/libffi/testsuite/libffi.call/closure_stdcall.c +72 -0
  175. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_12byte.c +102 -0
  176. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_16byte.c +103 -0
  177. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_18byte.c +104 -0
  178. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_19byte.c +110 -0
  179. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_1_1byte.c +97 -0
  180. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte.c +99 -0
  181. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_20byte1.c +101 -0
  182. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_24byte.c +121 -0
  183. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_2byte.c +98 -0
  184. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3_1byte.c +103 -0
  185. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte1.c +98 -0
  186. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_3byte2.c +98 -0
  187. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4_1byte.c +106 -0
  188. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_4byte.c +98 -0
  189. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5_1_byte.c +117 -0
  190. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_5byte.c +106 -0
  191. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_64byte.c +132 -0
  192. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6_1_byte.c +121 -0
  193. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_6byte.c +107 -0
  194. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7_1_byte.c +125 -0
  195. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_7byte.c +105 -0
  196. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_8byte.c +96 -0
  197. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte1.c +98 -0
  198. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_9byte2.c +99 -0
  199. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_double.c +101 -0
  200. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_float.c +99 -0
  201. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_longdouble.c +100 -0
  202. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_pointer.c +101 -0
  203. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint16.c +99 -0
  204. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint32.c +99 -0
  205. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_sint64.c +99 -0
  206. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint16.c +99 -0
  207. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint32.c +99 -0
  208. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_align_uint64.c +100 -0
  209. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_double.c +51 -0
  210. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_float.c +51 -0
  211. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_schar.c +82 -0
  212. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshort.c +82 -0
  213. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_sshortchar.c +94 -0
  214. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_uchar.c +99 -0
  215. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushort.c +82 -0
  216. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_multi_ushortchar.c +94 -0
  217. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_schar.c +52 -0
  218. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sint.c +50 -0
  219. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_sshort.c +50 -0
  220. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uchar.c +50 -0
  221. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_uint.c +51 -0
  222. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ulonglong.c +54 -0
  223. data/ext/ffi_c/libffi/testsuite/libffi.call/cls_ushort.c +51 -0
  224. data/ext/ffi_c/libffi/testsuite/libffi.call/ffitest.h +86 -0
  225. data/ext/ffi_c/libffi/testsuite/libffi.call/float.c +59 -0
  226. data/ext/ffi_c/libffi/testsuite/libffi.call/float1.c +58 -0
  227. data/ext/ffi_c/libffi/testsuite/libffi.call/float2.c +57 -0
  228. data/ext/ffi_c/libffi/testsuite/libffi.call/float3.c +72 -0
  229. data/ext/ffi_c/libffi/testsuite/libffi.call/float4.c +62 -0
  230. data/ext/ffi_c/libffi/testsuite/libffi.call/many.c +69 -0
  231. data/ext/ffi_c/libffi/testsuite/libffi.call/many_win32.c +63 -0
  232. data/ext/ffi_c/libffi/testsuite/libffi.call/negint.c +53 -0
  233. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct.c +160 -0
  234. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct1.c +169 -0
  235. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct10.c +141 -0
  236. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct2.c +118 -0
  237. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct3.c +119 -0
  238. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct4.c +119 -0
  239. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct5.c +120 -0
  240. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct6.c +139 -0
  241. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct7.c +119 -0
  242. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct8.c +139 -0
  243. data/ext/ffi_c/libffi/testsuite/libffi.call/nested_struct9.c +139 -0
  244. data/ext/ffi_c/libffi/testsuite/libffi.call/problem1.c +98 -0
  245. data/ext/ffi_c/libffi/testsuite/libffi.call/promotion.c +59 -0
  246. data/ext/ffi_c/libffi/testsuite/libffi.call/pyobjc-tc.c +114 -0
  247. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl.c +35 -0
  248. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl1.c +43 -0
  249. data/ext/ffi_c/libffi/testsuite/libffi.call/return_dbl2.c +42 -0
  250. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl.c +35 -0
  251. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl1.c +36 -0
  252. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl2.c +49 -0
  253. data/ext/ffi_c/libffi/testsuite/libffi.call/return_fl3.c +42 -0
  254. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ldl.c +34 -0
  255. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll.c +41 -0
  256. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ll1.c +42 -0
  257. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sc.c +36 -0
  258. data/ext/ffi_c/libffi/testsuite/libffi.call/return_sl.c +38 -0
  259. data/ext/ffi_c/libffi/testsuite/libffi.call/return_uc.c +38 -0
  260. data/ext/ffi_c/libffi/testsuite/libffi.call/return_ul.c +38 -0
  261. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen.c +44 -0
  262. data/ext/ffi_c/libffi/testsuite/libffi.call/strlen_win32.c +44 -0
  263. data/ext/ffi_c/libffi/testsuite/libffi.call/struct1.c +65 -0
  264. data/ext/ffi_c/libffi/testsuite/libffi.call/struct2.c +67 -0
  265. data/ext/ffi_c/libffi/testsuite/libffi.call/struct3.c +59 -0
  266. data/ext/ffi_c/libffi/testsuite/libffi.call/struct4.c +63 -0
  267. data/ext/ffi_c/libffi/testsuite/libffi.call/struct5.c +65 -0
  268. data/ext/ffi_c/libffi/testsuite/libffi.call/struct6.c +64 -0
  269. data/ext/ffi_c/libffi/testsuite/libffi.call/struct7.c +74 -0
  270. data/ext/ffi_c/libffi/testsuite/libffi.call/struct8.c +80 -0
  271. data/ext/ffi_c/libffi/testsuite/libffi.call/struct9.c +67 -0
  272. data/ext/ffi_c/libffi/testsuite/libffi.special/ffitestcxx.h +86 -0
  273. data/ext/ffi_c/libffi/testsuite/libffi.special/special.exp +38 -0
  274. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest.cc +123 -0
  275. data/ext/ffi_c/libffi/testsuite/libffi.special/unwindtest_ffi_call.cc +53 -0
  276. data/ext/ffi_c/libffi/texinfo.tex +7482 -0
  277. data/ext/ffi_c/rbffi.h +26 -0
  278. data/gen/Rakefile +12 -0
  279. data/lib/ffi.rb +11 -0
  280. data/lib/ffi/autopointer.rb +61 -0
  281. data/lib/ffi/buffer.rb +0 -0
  282. data/lib/ffi/callback.rb +10 -0
  283. data/lib/ffi/enum.rb +78 -0
  284. data/lib/ffi/errno.rb +8 -0
  285. data/lib/ffi/ffi.rb +99 -0
  286. data/lib/ffi/io.rb +21 -0
  287. data/lib/ffi/library.rb +218 -0
  288. data/lib/ffi/managedstruct.rb +55 -0
  289. data/lib/ffi/memorypointer.rb +73 -0
  290. data/lib/ffi/platform.rb +78 -0
  291. data/lib/ffi/pointer.rb +119 -0
  292. data/lib/ffi/struct.rb +164 -0
  293. data/lib/ffi/tools/const_generator.rb +177 -0
  294. data/lib/ffi/tools/generator.rb +58 -0
  295. data/lib/ffi/tools/generator_task.rb +35 -0
  296. data/lib/ffi/tools/struct_generator.rb +194 -0
  297. data/lib/ffi/tools/types_generator.rb +123 -0
  298. data/lib/ffi/types.rb +153 -0
  299. data/lib/ffi/union.rb +12 -0
  300. data/lib/ffi/variadic.rb +25 -0
  301. data/spec/ffi/bool_spec.rb +24 -0
  302. data/spec/ffi/buffer_spec.rb +202 -0
  303. data/spec/ffi/callback_spec.rb +591 -0
  304. data/spec/ffi/enum_spec.rb +164 -0
  305. data/spec/ffi/errno_spec.rb +13 -0
  306. data/spec/ffi/function_spec.rb +47 -0
  307. data/spec/ffi/library_spec.rb +144 -0
  308. data/spec/ffi/managed_struct_spec.rb +56 -0
  309. data/spec/ffi/number_spec.rb +231 -0
  310. data/spec/ffi/pointer_spec.rb +195 -0
  311. data/spec/ffi/rbx/attach_function_spec.rb +27 -0
  312. data/spec/ffi/rbx/memory_pointer_spec.rb +102 -0
  313. data/spec/ffi/rbx/spec_helper.rb +1 -0
  314. data/spec/ffi/rbx/struct_spec.rb +13 -0
  315. data/spec/ffi/spec_helper.rb +17 -0
  316. data/spec/ffi/string_spec.rb +103 -0
  317. data/spec/ffi/struct_callback_spec.rb +62 -0
  318. data/spec/ffi/struct_initialize_spec.rb +30 -0
  319. data/spec/ffi/struct_spec.rb +529 -0
  320. data/spec/ffi/typedef_spec.rb +48 -0
  321. data/spec/ffi/union_spec.rb +60 -0
  322. data/spec/ffi/variadic_spec.rb +84 -0
  323. data/spec/spec.opts +4 -0
  324. metadata +432 -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 */