Skip to content

Commit 46ed8cc

Browse files
committed
[GR-16004] [GR-15444] [GR-15997] Update to FFI 1.11.1 and add documentation.
PullRequest: truffleruby/895
2 parents 6f0e413 + 3af179f commit 46ed8cc

File tree

37 files changed

+1339
-181
lines changed

37 files changed

+1339
-181
lines changed

doc/contributor/ffi.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# FFI
2+
3+
We have our own implementation of FFI, implemented entirely in Ruby + Truffle
4+
NFI.
5+
6+
Using the FFI gem C extension would be suboptimal because Sulong uses Truffle
7+
NFI to call native methods. Truffle NFI is implemented with `libffi`. The FFI C
8+
extension uses its own `libffi` to call native functions. This means we would
9+
use Truffle NFI's `libffi` to call the C extension `libffi` functions, adding
10+
overhead on every call to the C extension `libffi` functions.
11+
12+
FFI is also one way to avoid C extensions altogether, so it makes sense to not
13+
require C extension support for gems using FFI.
14+
15+
## Structure
16+
17+
* `lib/truffle/ffi`: Unchanged Ruby files from the gem.
18+
* `lib/truffle/truffle/ffi_backend`: our Ruby + Truffle NFI backend for FFI,
19+
which replaces the C extension and has the same API.
20+
* `lib/truffle/ffi.rb` coordinates `require`-ing the above.
21+
* `spec/ffi`: Specs from the FFI gem.
22+
* `src/main/ruby/truffleruby/core/truffle/ffi`: Implementation of
23+
`Truffle::FFI::Pointer`, which is also used in core and is aliased to
24+
`FFI::Pointer` once `"ffi"` is required. `Truffle::FFI::Pointer` should
25+
therefore have the same API as `FFI::Pointer` in the FFI gem.
26+
* `tool/import-ffi.sh`: Imports files from a checkout of the FFI gem.

doc/legal/legal.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ files.
141141

142142
#### FFI
143143

144-
TruffleRuby includes parts of the FFI gem 1.9.25. The FFI gem is copyright
144+
TruffleRuby includes parts of the FFI gem 1.11.1. The FFI gem is copyright
145145
2008-2016, Ruby FFI project contributors, and covered by the three-clause BSD
146146
licence (see `ffi.txt`).
147147

doc/user/security.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,9 @@ Consider potential vulnerabilities in your system `libssl`.
138138

139139
## FFI
140140

141-
We are not aware of any known vulnerabilities.
141+
Number | Description | Their Mitigation | Test | Our Mitigation
142+
--- | --- | --- | --- | ---
143+
CVE-2018-1000201 | A DLL loading issue can be hijacked on Windows when a `Symbol` is used for the library name | Treat Symbols the same as Strings in `ffi_lib` | | Applied the same mitigation, by using a version of FFI which fixed this vulnerability
142144

143145
# Notes on hashing
144146

doc/user/truffleruby-additions.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,13 @@ and set.
7777

7878
`AtomicReference` is marshalable.
7979

80+
## FFI
81+
82+
TruffleRuby includes a built-in implementation of [Ruby-FFI](https://github.com/ffi/ffi),
83+
compatible with version 1.11.1 of the `ffi` gem. This should be transparent: you can
84+
just install the `ffi` gem as normal, and it will use our built-in implementation,
85+
regardless of the version of the `ffi` gem.
86+
8087
## Polyglot programming
8188

8289
The `Polyglot` and `Java` modules provides access to the polyglot programming

lib/truffle/ffi.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ def self.find_type_size(type)
2222
end
2323

2424
module Platform
25-
CPU = RbConfig::CONFIG['host_cpu']
2625
# eregon: I would like to use rbconfig/sizeof here, but the linker requires
2726
# ffi, and the linker is needed to build the rbconfig/sizeof C extension,
2827
# so we need to break the cycle.
@@ -35,7 +34,6 @@ module Platform
3534

3635
# Require the pure-Ruby Truffle NFI backend
3736
require_relative 'truffle/ffi_backend/last_error'
38-
require_relative 'truffle/ffi_backend/data_converter'
3937
require_relative 'truffle/ffi_backend/type'
4038
require_relative 'truffle/ffi_backend/struct_layout'
4139
require_relative 'truffle/ffi_backend/struct'

lib/truffle/truffle/ffi_backend/data_converter.rb renamed to lib/truffle/ffi/data_converter.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@
2626
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
2727
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2828
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29-
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30-
#
29+
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.#
3130

3231
module FFI
3332
# This module is used to extend somes classes and give then a common API.

lib/truffle/ffi/ffi.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3030

3131
require 'ffi/platform'
32+
require 'ffi/data_converter'
3233
require 'ffi/types'
3334
require 'ffi/library'
3435
require 'ffi/errno'

lib/truffle/ffi/library.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ def ffi_lib(*names)
126126
else
127127
# TODO better library lookup logic
128128
unless libname.start_with?("/") || FFI::Platform.windows?
129-
path = ['/usr/lib/','/usr/local/lib/'].find do |pth|
129+
path = ['/usr/lib/','/usr/local/lib/','/opt/local/lib/'].find do |pth|
130130
File.exist?(pth + libname)
131131
end
132132
if path

lib/truffle/ffi/platform.rb

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ module Platform
5454
RbConfig::CONFIG['host_os'].downcase
5555
end
5656

57+
OSVERSION = RbConfig::CONFIG['host_os'].gsub(/[^\d]/, '').to_i
58+
59+
CPU = RbConfig::CONFIG['host_cpu']
60+
5761
ARCH = case CPU.downcase
5862
when /amd64|x86_64/
5963
"x86_64"
@@ -82,7 +86,6 @@ def self.is_os(os)
8286
OS == os
8387
end
8488

85-
NAME = "#{ARCH}-#{OS}"
8689
IS_GNU = defined?(GNU_LIBC)
8790
IS_LINUX = is_os("linux")
8891
IS_MAC = is_os("darwin")
@@ -92,6 +95,11 @@ def self.is_os(os)
9295
IS_SOLARIS = is_os("solaris")
9396
IS_WINDOWS = is_os("windows")
9497
IS_BSD = IS_MAC || IS_FREEBSD || IS_NETBSD || IS_OPENBSD
98+
99+
# Add the version for known ABI breaks
100+
name_version = "12" if IS_FREEBSD && OSVERSION >= 12 # 64-bit inodes
101+
102+
NAME = "#{ARCH}-#{OS}#{name_version}"
95103
CONF_DIR = File.join(File.dirname(__FILE__), 'platform', NAME)
96104

97105
public
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
rbx.platform.typedef.__int8_t = char
2+
rbx.platform.typedef.__uint8_t = uchar
3+
rbx.platform.typedef.__int16_t = short
4+
rbx.platform.typedef.__uint16_t = ushort
5+
rbx.platform.typedef.__int32_t = int
6+
rbx.platform.typedef.__uint32_t = uint
7+
rbx.platform.typedef.__int64_t = long_long
8+
rbx.platform.typedef.__uint64_t = ulong_long
9+
rbx.platform.typedef.__int_least8_t = char
10+
rbx.platform.typedef.__uint_least8_t = uchar
11+
rbx.platform.typedef.__int_least16_t = short
12+
rbx.platform.typedef.__uint_least16_t = ushort
13+
rbx.platform.typedef.__int_least32_t = int
14+
rbx.platform.typedef.__uint_least32_t = uint
15+
rbx.platform.typedef.__int_least64_t = long_long
16+
rbx.platform.typedef.__uint_least64_t = ulong_long
17+
rbx.platform.typedef.__int_fast8_t = int
18+
rbx.platform.typedef.__uint_fast8_t = uint
19+
rbx.platform.typedef.__int_fast16_t = int
20+
rbx.platform.typedef.__uint_fast16_t = uint
21+
rbx.platform.typedef.__int_fast32_t = int
22+
rbx.platform.typedef.__uint_fast32_t = uint
23+
rbx.platform.typedef.__int_fast64_t = long_long
24+
rbx.platform.typedef.__uint_fast64_t = ulong_long
25+
rbx.platform.typedef.__intptr_t = long
26+
rbx.platform.typedef.__uintptr_t = ulong
27+
rbx.platform.typedef.__intmax_t = long_long
28+
rbx.platform.typedef.__uintmax_t = ulong_long
29+
rbx.platform.typedef.__register_t = long_long
30+
rbx.platform.typedef.__vaddr_t = ulong
31+
rbx.platform.typedef.__paddr_t = ulong
32+
rbx.platform.typedef.__vsize_t = ulong
33+
rbx.platform.typedef.__psize_t = ulong
34+
rbx.platform.typedef.__clock_t = int
35+
rbx.platform.typedef.__clockid_t = int
36+
rbx.platform.typedef.__off_t = long_long
37+
rbx.platform.typedef.__ptrdiff_t = long
38+
rbx.platform.typedef.__size_t = ulong
39+
rbx.platform.typedef.__ssize_t = long
40+
rbx.platform.typedef.__time_t = int
41+
rbx.platform.typedef.__timer_t = int
42+
rbx.platform.typedef.__wchar_t = int
43+
rbx.platform.typedef.__wint_t = int
44+
rbx.platform.typedef.__rune_t = int
45+
rbx.platform.typedef.__wctrans_t = pointer
46+
rbx.platform.typedef.__wctype_t = pointer
47+
rbx.platform.typedef.__cpuid_t = ulong
48+
rbx.platform.typedef.__dev_t = int
49+
rbx.platform.typedef.__fixpt_t = uint
50+
rbx.platform.typedef.__gid_t = uint
51+
rbx.platform.typedef.__id_t = uint
52+
rbx.platform.typedef.__in_addr_t = uint
53+
rbx.platform.typedef.__in_port_t = ushort
54+
rbx.platform.typedef.__ino_t = uint
55+
rbx.platform.typedef.__key_t = long
56+
rbx.platform.typedef.__mode_t = uint
57+
rbx.platform.typedef.__nlink_t = uint
58+
rbx.platform.typedef.__pid_t = int
59+
rbx.platform.typedef.__rlim_t = ulong_long
60+
rbx.platform.typedef.__sa_family_t = uchar
61+
rbx.platform.typedef.__segsz_t = int
62+
rbx.platform.typedef.__socklen_t = uint
63+
rbx.platform.typedef.__swblk_t = int
64+
rbx.platform.typedef.__uid_t = uint
65+
rbx.platform.typedef.__useconds_t = uint
66+
rbx.platform.typedef.__suseconds_t = int
67+
rbx.platform.typedef.u_char = uchar
68+
rbx.platform.typedef.u_short = ushort
69+
rbx.platform.typedef.u_int = uint
70+
rbx.platform.typedef.u_long = ulong
71+
rbx.platform.typedef.unchar = uchar
72+
rbx.platform.typedef.ushort = ushort
73+
rbx.platform.typedef.uint = uint
74+
rbx.platform.typedef.ulong = ulong
75+
rbx.platform.typedef.cpuid_t = ulong
76+
rbx.platform.typedef.register_t = long_long
77+
rbx.platform.typedef.int8_t = char
78+
rbx.platform.typedef.uint8_t = uchar
79+
rbx.platform.typedef.int16_t = short
80+
rbx.platform.typedef.uint16_t = ushort
81+
rbx.platform.typedef.int32_t = int
82+
rbx.platform.typedef.uint32_t = uint
83+
rbx.platform.typedef.int64_t = long_long
84+
rbx.platform.typedef.uint64_t = ulong_long
85+
rbx.platform.typedef.intptr_t = long
86+
rbx.platform.typedef.uintptr_t = ulong
87+
rbx.platform.typedef.u_int8_t = uchar
88+
rbx.platform.typedef.u_int16_t = ushort
89+
rbx.platform.typedef.u_int32_t = uint
90+
rbx.platform.typedef.u_int64_t = ulong_long
91+
rbx.platform.typedef.quad_t = long_long
92+
rbx.platform.typedef.u_quad_t = ulong_long
93+
rbx.platform.typedef.qaddr_t = pointer
94+
rbx.platform.typedef.vaddr_t = ulong
95+
rbx.platform.typedef.paddr_t = ulong
96+
rbx.platform.typedef.vsize_t = ulong
97+
rbx.platform.typedef.psize_t = ulong
98+
rbx.platform.typedef.caddr_t = string
99+
rbx.platform.typedef.daddr_t = int
100+
rbx.platform.typedef.daddr32_t = int
101+
rbx.platform.typedef.daddr64_t = long_long
102+
rbx.platform.typedef.dev_t = int
103+
rbx.platform.typedef.fixpt_t = uint
104+
rbx.platform.typedef.gid_t = uint
105+
rbx.platform.typedef.id_t = uint
106+
rbx.platform.typedef.ino_t = uint
107+
rbx.platform.typedef.key_t = long
108+
rbx.platform.typedef.mode_t = uint
109+
rbx.platform.typedef.nlink_t = uint
110+
rbx.platform.typedef.pid_t = int
111+
rbx.platform.typedef.rlim_t = ulong_long
112+
rbx.platform.typedef.segsz_t = int
113+
rbx.platform.typedef.swblk_t = int
114+
rbx.platform.typedef.uid_t = uint
115+
rbx.platform.typedef.useconds_t = uint
116+
rbx.platform.typedef.suseconds_t = int
117+
rbx.platform.typedef.in_addr_t = uint
118+
rbx.platform.typedef.in_port_t = ushort
119+
rbx.platform.typedef.sa_family_t = uchar
120+
rbx.platform.typedef.socklen_t = uint
121+
rbx.platform.typedef.clock_t = int
122+
rbx.platform.typedef.clockid_t = int
123+
rbx.platform.typedef.size_t = ulong
124+
rbx.platform.typedef.ssize_t = long
125+
rbx.platform.typedef.time_t = int
126+
rbx.platform.typedef.timer_t = int
127+
rbx.platform.typedef.off_t = long_long
128+
rbx.platform.typedef.__fd_mask = int

0 commit comments

Comments
 (0)