worf 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +3 -0
- data/LICENSE +201 -0
- data/README.md +73 -0
- data/Rakefile +18 -0
- data/lib/worf.rb +563 -0
- data/lib/worf/constants.erb +17 -0
- data/lib/worf/constants.rb +693 -0
- data/lib/worf/constants.yml +799 -0
- data/test/dwarf_test.rb +128 -0
- data/test/fixtures/a.out +0 -0
- data/test/fixtures/a.out.dSYM/Contents/Info.plist +20 -0
- data/test/fixtures/a.out.dSYM/Contents/Resources/DWARF/a.out +0 -0
- data/test/fixtures/out.dSYM/Contents/Info.plist +20 -0
- data/test/fixtures/out.dSYM/Contents/Resources/DWARF/out +0 -0
- data/test/fixtures/slop.c +17 -0
- data/test/fixtures/thing.c +6 -0
- data/test/helper.rb +59 -0
- data/test/mach_o_dwarf_integration_test.rb +52 -0
- data/test/ruby_test.rb +238 -0
- data/worf.gemspec +15 -0
- metadata +116 -0
data/test/dwarf_test.rb
ADDED
@@ -0,0 +1,128 @@
|
|
1
|
+
ENV["MT_NO_PLUGINS"] = "1"
|
2
|
+
|
3
|
+
require "helper"
|
4
|
+
|
5
|
+
module WORF
|
6
|
+
class Test < Minitest::Test
|
7
|
+
debug_file = "fixtures/out.dSYM/Contents/Resources/DWARF/out"
|
8
|
+
DEBUG_FILE = File.expand_path(File.join(__dir__, debug_file))
|
9
|
+
|
10
|
+
debug_file = "fixtures/a.out.dSYM/Contents/Resources/DWARF/a.out"
|
11
|
+
SLOP = File.expand_path(File.join(__dir__, debug_file))
|
12
|
+
|
13
|
+
def test_uleb128
|
14
|
+
assert_equal 624485, WORF.unpackULEB128(StringIO.new("\xE5\x8E\x26".b))
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_sleb128
|
18
|
+
assert_equal(-123456, WORF.unpackSLEB128(StringIO.new("\xC0\xBB\x78".b)))
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_debug_abbrev
|
22
|
+
File.open DEBUG_FILE do |io|
|
23
|
+
mach_o = OdinFlex::MachO.new(io)
|
24
|
+
|
25
|
+
section = mach_o.find do |thing|
|
26
|
+
thing.section? && thing.sectname == "__debug_abbrev"
|
27
|
+
end
|
28
|
+
|
29
|
+
debug_abbrev = WORF::DebugAbbrev.new io, section, mach_o.start_pos
|
30
|
+
tags = debug_abbrev.tags
|
31
|
+
|
32
|
+
assert_equal 5, tags.length
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_debug_info
|
37
|
+
File.open DEBUG_FILE do |io|
|
38
|
+
mach_o = OdinFlex::MachO.new(io)
|
39
|
+
|
40
|
+
abbrev = mach_o.find do |thing|
|
41
|
+
thing.section? && thing.sectname == "__debug_abbrev"
|
42
|
+
end
|
43
|
+
|
44
|
+
debug_abbrev = WORF::DebugAbbrev.new io, abbrev, mach_o.start_pos
|
45
|
+
|
46
|
+
info = mach_o.find do |thing|
|
47
|
+
thing.section? && thing.sectname == "__debug_info"
|
48
|
+
end
|
49
|
+
|
50
|
+
debug_info = WORF::DebugInfo.new io, info, mach_o.start_pos
|
51
|
+
units = debug_info.compile_units(debug_abbrev.tags)
|
52
|
+
|
53
|
+
assert_equal 1, units.length
|
54
|
+
assert_equal Constants::DW_TAG_compile_unit, units.first.die.tag.type
|
55
|
+
assert_equal 0xb, units.first.die.offset
|
56
|
+
assert_equal 5, units.first.die.children.length
|
57
|
+
assert_equal Constants::DW_TAG_subprogram, units.first.die.children.first.tag.type
|
58
|
+
assert_equal 0x2a, units.first.die.children.first.offset
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
class StructInfo
|
63
|
+
def initialize die, names, ranges
|
64
|
+
@die = die
|
65
|
+
@ranges = ranges
|
66
|
+
end
|
67
|
+
|
68
|
+
def byte_size; @die.byte_size; end
|
69
|
+
|
70
|
+
def used_size
|
71
|
+
@ranges.map(&:size).inject(:+)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def show unit, die, strings, dies
|
76
|
+
names = []
|
77
|
+
ranges = die.children.map do |child|
|
78
|
+
if child.tag.member?
|
79
|
+
type_die = dies.find { |d| d.offset == child.type }
|
80
|
+
size = if type_die.tag.pointer_type?
|
81
|
+
unit.address_size
|
82
|
+
else
|
83
|
+
type_die.byte_size
|
84
|
+
end
|
85
|
+
start = child.data_member_location
|
86
|
+
name = strings.string_at(child.name_offset)
|
87
|
+
names << name
|
88
|
+
Range.new(start, start + size, exclude_end: true)
|
89
|
+
else
|
90
|
+
raise NotImplementedError
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
StructInfo.new die, names, ranges
|
95
|
+
end
|
96
|
+
|
97
|
+
def test_read_struct
|
98
|
+
struct_info = nil
|
99
|
+
|
100
|
+
File.open SLOP do |io|
|
101
|
+
mach_o = OdinFlex::MachO.new(io)
|
102
|
+
|
103
|
+
abbrev = mach_o.find_section "__debug_abbrev"
|
104
|
+
debug_abbrev = WORF::DebugAbbrev.new io, abbrev, mach_o.start_pos
|
105
|
+
|
106
|
+
section_info = mach_o.find_section "__debug_str"
|
107
|
+
strings = WORF::DebugStrings.new io, section_info, mach_o.start_pos
|
108
|
+
|
109
|
+
info = mach_o.find_section "__debug_info"
|
110
|
+
debug_info = WORF::DebugInfo.new io, info, mach_o.start_pos
|
111
|
+
|
112
|
+
units = debug_info.compile_units(debug_abbrev.tags)
|
113
|
+
|
114
|
+
units.each do |unit|
|
115
|
+
unit.die.children.each do |die|
|
116
|
+
if die.tag.structure_type?
|
117
|
+
struct_info = show unit, die, strings, unit.die.to_a
|
118
|
+
break
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
assert_equal 24, struct_info.byte_size
|
125
|
+
assert_equal 17, struct_info.used_size
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/test/fixtures/a.out
ADDED
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
6
|
+
<string>English</string>
|
7
|
+
<key>CFBundleIdentifier</key>
|
8
|
+
<string>com.apple.xcode.dsym.a.out</string>
|
9
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
10
|
+
<string>6.0</string>
|
11
|
+
<key>CFBundlePackageType</key>
|
12
|
+
<string>dSYM</string>
|
13
|
+
<key>CFBundleSignature</key>
|
14
|
+
<string>????</string>
|
15
|
+
<key>CFBundleShortVersionString</key>
|
16
|
+
<string>1.0</string>
|
17
|
+
<key>CFBundleVersion</key>
|
18
|
+
<string>1</string>
|
19
|
+
</dict>
|
20
|
+
</plist>
|
Binary file
|
@@ -0,0 +1,20 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
3
|
+
<plist version="1.0">
|
4
|
+
<dict>
|
5
|
+
<key>CFBundleDevelopmentRegion</key>
|
6
|
+
<string>English</string>
|
7
|
+
<key>CFBundleIdentifier</key>
|
8
|
+
<string>com.apple.xcode.dsym.out</string>
|
9
|
+
<key>CFBundleInfoDictionaryVersion</key>
|
10
|
+
<string>6.0</string>
|
11
|
+
<key>CFBundlePackageType</key>
|
12
|
+
<string>dSYM</string>
|
13
|
+
<key>CFBundleSignature</key>
|
14
|
+
<string>????</string>
|
15
|
+
<key>CFBundleShortVersionString</key>
|
16
|
+
<string>1.0</string>
|
17
|
+
<key>CFBundleVersion</key>
|
18
|
+
<string>1</string>
|
19
|
+
</dict>
|
20
|
+
</plist>
|
Binary file
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#include <stdio.h>
|
2
|
+
#include <stdlib.h>
|
3
|
+
|
4
|
+
struct hello {
|
5
|
+
char *p;
|
6
|
+
char c;
|
7
|
+
long x;
|
8
|
+
};
|
9
|
+
|
10
|
+
int main(int argc, char **argv) {
|
11
|
+
struct hello * m;
|
12
|
+
m = malloc(sizeof(struct hello));
|
13
|
+
m->c = 123;
|
14
|
+
m->x = 123;
|
15
|
+
printf("Hello World %lu\n", m->x);
|
16
|
+
return 0;
|
17
|
+
}
|
data/test/helper.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
ENV["MT_NO_PLUGINS"] = "1"
|
2
|
+
|
3
|
+
require "minitest/autorun"
|
4
|
+
require "worf"
|
5
|
+
require "odinflex/mach-o"
|
6
|
+
require "odinflex/ar"
|
7
|
+
require "rbconfig"
|
8
|
+
require "fiddle"
|
9
|
+
|
10
|
+
module WORF
|
11
|
+
class Test < Minitest::Test
|
12
|
+
include Fiddle
|
13
|
+
|
14
|
+
module Hacks
|
15
|
+
include Fiddle
|
16
|
+
|
17
|
+
class Fiddle::Function
|
18
|
+
def to_proc
|
19
|
+
this = self
|
20
|
+
lambda { |*args| this.call(*args) }
|
21
|
+
end
|
22
|
+
end unless Function.method_defined?(:to_proc)
|
23
|
+
|
24
|
+
def self.make_function name, args, ret
|
25
|
+
ptr = Handle::DEFAULT[name]
|
26
|
+
func = Function.new ptr, args, ret, name: name
|
27
|
+
define_singleton_method name, &func.to_proc
|
28
|
+
end
|
29
|
+
|
30
|
+
make_function "strerror", [TYPE_INT], TYPE_CONST_STRING
|
31
|
+
#make_function "mprotect", [TYPE_VOIDP, TYPE_SIZE_T, TYPE_INT], TYPE_INT
|
32
|
+
make_function "_dyld_image_count", [], TYPE_INT32_T
|
33
|
+
make_function "_dyld_get_image_name", [TYPE_INT32_T], TYPE_CONST_STRING
|
34
|
+
make_function "_dyld_get_image_vmaddr_slide", [TYPE_INT32_T], TYPE_INTPTR_T
|
35
|
+
make_function "mach_task_self", [], TYPE_VOIDP
|
36
|
+
make_function "vm_protect", [TYPE_VOIDP, -TYPE_INT64_T, TYPE_SIZE_T, TYPE_CHAR, TYPE_INT], TYPE_INT
|
37
|
+
make_function "rb_intern", [TYPE_CONST_STRING], TYPE_INT
|
38
|
+
|
39
|
+
def self.mprotect addr, len, prot
|
40
|
+
vm_protect mach_task_self, addr, len, 0, prot | PROT_COPY
|
41
|
+
end
|
42
|
+
|
43
|
+
PROT_READ = 0x01
|
44
|
+
PROT_WRITE = 0x02
|
45
|
+
PROT_EXEC = 0x04
|
46
|
+
PROT_COPY = 0x10
|
47
|
+
|
48
|
+
def self.slide
|
49
|
+
executable = RbConfig.ruby
|
50
|
+
Hacks._dyld_image_count.times do |i|
|
51
|
+
name = Hacks._dyld_get_image_name(i)
|
52
|
+
if executable == name
|
53
|
+
return Hacks._dyld_get_image_vmaddr_slide(i)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
module WORF
|
4
|
+
class MachODWARFIntegrationTest < Test
|
5
|
+
def test_find_symbol_and_make_struct
|
6
|
+
addr = nil
|
7
|
+
archive = nil
|
8
|
+
|
9
|
+
File.open(RbConfig.ruby) do |f|
|
10
|
+
my_macho = OdinFlex::MachO.new f
|
11
|
+
my_macho.each do |section|
|
12
|
+
if section.symtab?
|
13
|
+
addr = section.nlist.find { |symbol|
|
14
|
+
symbol.name == "_ruby_api_version" && symbol.value > 0
|
15
|
+
}.value + Hacks.slide
|
16
|
+
|
17
|
+
archive = section.nlist.find_all(&:archive?).map(&:archive).uniq.first
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
assert addr
|
23
|
+
assert archive
|
24
|
+
|
25
|
+
found_object = nil
|
26
|
+
|
27
|
+
File.open(archive) do |f|
|
28
|
+
ar = OdinFlex::AR.new f
|
29
|
+
ar.each do |object_file|
|
30
|
+
next unless object_file.identifier.end_with?(".o")
|
31
|
+
next unless object_file.identifier == "version.o"
|
32
|
+
|
33
|
+
f.seek object_file.pos, IO::SEEK_SET
|
34
|
+
macho = OdinFlex::MachO.new f
|
35
|
+
debug_info = macho.find_section("__debug_info")&.as_dwarf || next
|
36
|
+
debug_strs = macho.find_section("__debug_str").as_dwarf
|
37
|
+
debug_abbrev = macho.find_section("__debug_abbrev").as_dwarf
|
38
|
+
|
39
|
+
debug_info.compile_units(debug_abbrev.tags).each do |unit|
|
40
|
+
unit.die.children.each do |die|
|
41
|
+
if die.name(debug_strs) == "ruby_api_version"
|
42
|
+
found_object = object_file
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
assert found_object
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/test/ruby_test.rb
ADDED
@@ -0,0 +1,238 @@
|
|
1
|
+
require "helper"
|
2
|
+
|
3
|
+
module WORF
|
4
|
+
class RubyTest < WORF::Test
|
5
|
+
def ruby_archive
|
6
|
+
File.join RbConfig::CONFIG["prefix"], "lib", RbConfig::CONFIG["LIBRUBY"]
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_ruby_archive
|
10
|
+
assert File.file?(ruby_archive)
|
11
|
+
end
|
12
|
+
|
13
|
+
def test_read_archive
|
14
|
+
files = []
|
15
|
+
File.open(ruby_archive) do |f|
|
16
|
+
OdinFlex::AR.new(f).each { |file| files << file.identifier }
|
17
|
+
end
|
18
|
+
assert_includes files, "gc.o"
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_read_archive_twice
|
22
|
+
files = []
|
23
|
+
File.open(ruby_archive) do |f|
|
24
|
+
ar = OdinFlex::AR.new(f)
|
25
|
+
ar.each { |file| files << file.identifier }
|
26
|
+
assert_includes files, "gc.o"
|
27
|
+
files.clear
|
28
|
+
ar.each { |file| files << file.identifier }
|
29
|
+
assert_includes files, "gc.o"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_macho_in_archive
|
34
|
+
File.open(ruby_archive) do |f|
|
35
|
+
ar = OdinFlex::AR.new f
|
36
|
+
gc = ar.find { |file| file.identifier == "gc.o" }
|
37
|
+
|
38
|
+
f.seek gc.pos, IO::SEEK_SET
|
39
|
+
macho = OdinFlex::MachO.new f
|
40
|
+
section = macho.find_section("__debug_str")
|
41
|
+
assert_equal "__debug_str", section.sectname
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_macho_to_dwarf
|
46
|
+
File.open(ruby_archive) do |f|
|
47
|
+
ar = OdinFlex::AR.new f
|
48
|
+
gc = ar.find { |file| file.identifier == "gc.o" }
|
49
|
+
|
50
|
+
f.seek gc.pos, IO::SEEK_SET
|
51
|
+
macho = OdinFlex::MachO.new f
|
52
|
+
debug_strs = macho.find_section("__debug_str").as_dwarf
|
53
|
+
debug_abbrev = macho.find_section("__debug_abbrev").as_dwarf
|
54
|
+
debug_info = macho.find_section("__debug_info").as_dwarf
|
55
|
+
|
56
|
+
names = []
|
57
|
+
|
58
|
+
debug_info.compile_units(debug_abbrev.tags).each do |unit|
|
59
|
+
unit.die.children.each do |die|
|
60
|
+
names << die.name(debug_strs)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
assert_includes names, "RBasic"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_rbasic_layout
|
69
|
+
File.open(ruby_archive) do |f|
|
70
|
+
ar = OdinFlex::AR.new f
|
71
|
+
gc = ar.find { |file| file.identifier == "gc.o" }
|
72
|
+
|
73
|
+
f.seek gc.pos, IO::SEEK_SET
|
74
|
+
macho = OdinFlex::MachO.new f
|
75
|
+
debug_strs = macho.find_section("__debug_str").as_dwarf
|
76
|
+
debug_abbrev = macho.find_section("__debug_abbrev").as_dwarf
|
77
|
+
debug_info = macho.find_section("__debug_info").as_dwarf
|
78
|
+
|
79
|
+
rbasic_layout = []
|
80
|
+
|
81
|
+
debug_info.compile_units(debug_abbrev.tags).each do |unit|
|
82
|
+
unit.die.children.each do |die|
|
83
|
+
if die.name(debug_strs) == "RBasic"
|
84
|
+
assert_predicate die.tag, :structure_type?
|
85
|
+
|
86
|
+
die.children.each do |child|
|
87
|
+
field_name = child.name(debug_strs)
|
88
|
+
field_type = nil
|
89
|
+
while child
|
90
|
+
field_type = child.name(debug_strs)
|
91
|
+
break unless child.type
|
92
|
+
child = unit.die.find_type(child)
|
93
|
+
end
|
94
|
+
rbasic_layout << [field_name, field_type]
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
assert_equal([["flags", "long unsigned int"], ["klass", "long unsigned int"]],
|
101
|
+
rbasic_layout)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def test_rclass_layout
|
106
|
+
File.open(ruby_archive) do |f|
|
107
|
+
ar = OdinFlex::AR.new f
|
108
|
+
gc = ar.find { |file| file.identifier == "gc.o" }
|
109
|
+
|
110
|
+
f.seek gc.pos, IO::SEEK_SET
|
111
|
+
macho = OdinFlex::MachO.new f
|
112
|
+
debug_strs = macho.find_section("__debug_str").as_dwarf
|
113
|
+
debug_abbrev = macho.find_section("__debug_abbrev").as_dwarf
|
114
|
+
debug_info = macho.find_section("__debug_info").as_dwarf
|
115
|
+
|
116
|
+
layout = []
|
117
|
+
|
118
|
+
debug_info.compile_units(debug_abbrev.tags).each do |unit|
|
119
|
+
unit.die.children.each do |die|
|
120
|
+
if die.name(debug_strs) == "RClass"
|
121
|
+
assert_predicate die.tag, :structure_type?
|
122
|
+
|
123
|
+
die.children.each do |child|
|
124
|
+
field_name = child.name(debug_strs)
|
125
|
+
type = unit.die.find_type(child)
|
126
|
+
|
127
|
+
if type.tag.typedef?
|
128
|
+
type = unit.die.find_type(type)
|
129
|
+
end
|
130
|
+
|
131
|
+
type_name = if type.tag.pointer_type?
|
132
|
+
c = unit.die.find_type(type)
|
133
|
+
"#{c.name(debug_strs)} *"
|
134
|
+
else
|
135
|
+
type.name(debug_strs)
|
136
|
+
end
|
137
|
+
|
138
|
+
type_size = if type.tag.pointer_type?
|
139
|
+
unit.address_size
|
140
|
+
else
|
141
|
+
type.byte_size
|
142
|
+
end
|
143
|
+
|
144
|
+
layout << [field_name, type_name, type_size]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
assert_equal([["basic", "RBasic", 16],
|
151
|
+
["super", "long unsigned int", 8],
|
152
|
+
["ptr", "rb_classext_struct *", 8],
|
153
|
+
["class_serial", "long long unsigned int", 8]],
|
154
|
+
layout)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
[
|
159
|
+
[:section?, OdinFlex::MachO::Section],
|
160
|
+
[:symtab?, OdinFlex::MachO::LC_SYMTAB],
|
161
|
+
[:segment?, OdinFlex::MachO::LC_SEGMENT_64],
|
162
|
+
[:dysymtab?, OdinFlex::MachO::LC_DYSYMTAB],
|
163
|
+
[:command?, OdinFlex::MachO::Command],
|
164
|
+
].each do |predicate, klass|
|
165
|
+
define_method :"test_find_#{predicate}" do
|
166
|
+
File.open(RbConfig.ruby) do |f|
|
167
|
+
my_macho = OdinFlex::MachO.new f
|
168
|
+
list = my_macho.find_all(&predicate)
|
169
|
+
refute_predicate list, :empty?
|
170
|
+
assert list.all? { |x| x.is_a?(klass) }
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
def test_rb_vm_get_insns_address_table
|
176
|
+
sym = nil
|
177
|
+
|
178
|
+
File.open(RbConfig.ruby) do |f|
|
179
|
+
my_macho = OdinFlex::MachO.new f
|
180
|
+
|
181
|
+
my_macho.each do |section|
|
182
|
+
if section.symtab?
|
183
|
+
sym = section.nlist.find do |symbol|
|
184
|
+
symbol.name == "_rb_vm_get_insns_address_table" && symbol.value
|
185
|
+
end
|
186
|
+
break if sym
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
addr = sym.value + Hacks.slide
|
192
|
+
ptr = Fiddle::Function.new(addr, [], TYPE_VOIDP).call
|
193
|
+
len = RubyVM::INSTRUCTION_NAMES.length
|
194
|
+
assert ptr[0, len * Fiddle::SIZEOF_VOIDP].unpack("Q#{len}")
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_guess_slide
|
198
|
+
File.open(RbConfig.ruby) do |f|
|
199
|
+
my_macho = OdinFlex::MachO.new f
|
200
|
+
|
201
|
+
my_macho.each do |section|
|
202
|
+
if section.symtab?
|
203
|
+
section.nlist.each do |symbol|
|
204
|
+
if symbol.name == "_rb_st_insert"
|
205
|
+
guess_slide = Fiddle::Handle::DEFAULT["rb_st_insert"] - symbol.value
|
206
|
+
assert_equal Hacks.slide, guess_slide
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
def test_find_global
|
215
|
+
File.open(RbConfig.ruby) do |f|
|
216
|
+
my_macho = OdinFlex::MachO.new f
|
217
|
+
|
218
|
+
my_macho.each do |section|
|
219
|
+
if section.symtab?
|
220
|
+
section.nlist.each do |symbol|
|
221
|
+
if symbol.name == "_ruby_api_version"
|
222
|
+
if symbol.value > 0
|
223
|
+
addr = symbol.value + Hacks.slide
|
224
|
+
pointer = Fiddle::Pointer.new(addr, Fiddle::SIZEOF_INT * 3)
|
225
|
+
assert_equal RbConfig::CONFIG["ruby_version"].split(".").map(&:to_i),
|
226
|
+
pointer[0, Fiddle::SIZEOF_INT * 3].unpack("LLL")
|
227
|
+
else
|
228
|
+
assert_predicate symbol, :stab?
|
229
|
+
assert_predicate symbol, :gsym?
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|