ragweed 0.1.7.3 → 0.2.0.pre1

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.
@@ -2,7 +2,8 @@ module Ragweed; end
2
2
  module Ragweed::Wraposx; end
3
3
  module Ragweed::Wraposx::Vm
4
4
  # these are flavor arguments for vm_region
5
- # more to be added as support for 64bit processes gets added
5
+ # only basic info is supported by apple
6
+ REGION_BASIC_INFO_64 = 9
6
7
  REGION_BASIC_INFO = 10
7
8
  REGION_EXTENDED_INFO = 11
8
9
  REGION_TOP_INFO = 12
@@ -23,232 +24,252 @@ module Ragweed::Wraposx::Vm
23
24
  INHERIT_DEFAULT = 1 # VM_INHERIT_COPY
24
25
  INHERIT_LAST_VALID = 2 # VM_INHERIT_NONE
25
26
 
26
- #define VM_REGION_BASIC_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_basic_info_data_t)/sizeof(int)))
27
- #define VM_REGION_EXTENDED_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_extended_info_data_t)/sizeof(int)))
28
- #define VM_REGION_TOP_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_top_info_data_t)/sizeof(int)))
29
- FLAVORS = { REGION_BASIC_INFO => {:size => 30, :count => 8},
30
- REGION_EXTENDED_INFO => {:size => 32, :count => 8},
31
- REGION_TOP_INFO => {:size => 17,:count => 5}
32
- }
33
-
34
27
  module Pflags
35
28
  READ = 0x1 #read permission
36
29
  WRITE = 0x2 #write permission
37
30
  EXECUTE = 0x4 #execute permission
38
31
  end
39
- end
40
32
 
41
- # Memory region info base class.
42
- #
43
- # to change slightly in 0.2.0+
44
- #
45
- class Ragweed::Wraposx::RegionInfo
46
- def initialize(str=nil)
47
- refresh(str) if str
33
+ # Memory region info base class.
34
+ #
35
+ class RegionInfo < FFI::Struct
36
+ include Ragweed::FFIStructInclude
37
+ attr_accessor :region_size
38
+ attr_accessor :base_address
48
39
  end
49
40
 
50
- # (re)loads the data from str
51
- def refresh(str)
52
- fields = self.class.const_get :FIELDS
53
- if str and not str.empty?
54
- str.unpack(fields.map {|x| x[1]}.join("")).each_with_index do |val, i|
55
- raise "i is nil" if i.nil?
56
- instance_variable_set "@#{ fields[i][0] }".intern, val
57
- end
58
- end
59
- end
41
+ class RegionBasicInfo < RegionInfo
60
42
 
61
- def to_s
62
- fields = self.class.const_get :FIELDS
63
- fields.map {|f| send(f[0])}.pack(fields.map {|x| x[1]}.join(""))
64
- end
43
+ layout :protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
44
+ :max_protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
45
+ :inheritance, Ragweed::Wraposx::Libc.find_type(:vm_inherit_t),
46
+ :shared, Ragweed::Wraposx::Libc.find_type(:boolean_t),
47
+ :reserved, Ragweed::Wraposx::Libc.find_type(:boolean_t),
48
+ :offset, :uint32,
49
+ :behavior, Ragweed::Wraposx::Libc.find_type(:vm_behavior_t),
50
+ :user_wired_count, :ushort
65
51
 
66
- def self.get(t, a, flavor)
67
- self.new(Ragweed::Wraposx::vm_region_raw(t, a, flavor))
68
- end
69
52
 
70
- def get(t, a)
71
- refresh(Ragweed::Wraposx::vm_region_raw(t, a, self.class.const_get(:FLAVOR)))
72
- end
53
+ def dump(&block)
54
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
55
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
73
56
 
74
- def inspect
75
- fields = self.class.const_get(:FIELDS)
76
- body = lambda do
77
- fields.map do |f|
78
- "#{f[0]}=#{send(f[0]).to_s}"
79
- end.join(", ")
57
+ string =<<EOM
58
+ -----------------------------------------------------------------------
59
+ BASIC INFO:
60
+ base address: #{self.base_address.to_s(16).rjust(8, "0")}
61
+
62
+ protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
63
+ max_protection: #{self.max_protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.max_protection)}
64
+ inheritance: #{self.inheritance.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.inheritance)}
65
+ shared: #{self.shared.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared)}
66
+ reserved: #{self.reserved.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.reserved)}
67
+ offset: #{self.offset.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.offset)}
68
+ behavior: #{self.behavior.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.behavior)}
69
+ user_wired_count: #{self.user_wired_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_wired_count)}
70
+ size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
71
+ EOM
80
72
  end
81
- "#<#{self.class.name.split("::").last} #{body.call}>"
82
73
  end
83
74
 
84
- def dump(&block)
85
- maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
86
- maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
87
-
88
- string =<<EOM
89
- -----------------------------------------------------------------------
90
- INFO:
91
- protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
92
- max_protection: #{self.max_protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.max_protection)}
93
- inheritance: #{self.inheritance.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.inheritance)}
94
- shared: #{self.shared.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared)}
95
- reserved: #{self.reserved.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.reserved)}
96
- offset: #{self.offset.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.offset)}
97
- behavior: #{self.behavior.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.behavior)}
98
- user_wired_count: #{self.user_wired_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_wired_count)}
99
- size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
100
- EOM
101
- end
102
- end
75
+ class RegionBasicInfo64 < RegionInfo
103
76
 
104
- class Ragweed::Wraposx::RegionBasicInfo < Ragweed::Wraposx::RegionInfo
105
-
106
- FLAVOR = Ragweed::Wraposx::Vm::REGION_BASIC_INFO
107
-
108
- (FIELDS = [ [:protection, "i"], # The current protection for the region.
109
- [:max_protection, "i"], # The maximum protection allowed for the region.
110
- [:inheritance, "I"], # The inheritance attribute for the region.
111
- [:shared, "I"], # Shared indicator. If true, the region is shared by another task. If false, the region is not shared.
112
- [:reserved, "I"], # If true the region is protected from random allocation.
113
- [:offset, "L"], # The region's offset into the memory object. The region begins at this offset.
114
- [:behavior, "i"], # Expected reference pattern for the memory.
115
- [:user_wired_count, "S"],
116
- [:size, "I"], # size of memory region returned
117
- [:base_address, "L"]
118
- ]).each {|x| attr_accessor x[0]}
119
-
120
- def dump(&block)
121
- maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
122
- maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
123
-
124
- string =<<EOM
125
- -----------------------------------------------------------------------
126
- BASIC INFO:
127
- base address: #{self.base_address.to_s(16).rjust(8, "0")}
128
-
129
- protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
130
- max_protection: #{self.max_protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.max_protection)}
131
- inheritance: #{self.inheritance.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.inheritance)}
132
- shared: #{self.shared.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared)}
133
- reserved: #{self.reserved.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.reserved)}
134
- offset: #{self.offset.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.offset)}
135
- behavior: #{self.behavior.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.behavior)}
136
- user_wired_count: #{self.user_wired_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_wired_count)}
137
- size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
138
- EOM
139
- end
77
+ layout :protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
78
+ :max_protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
79
+ :inheritance, Ragweed::Wraposx::Libc.find_type(:vm_inherit_t),
80
+ :shared, Ragweed::Wraposx::Libc.find_type(:boolean_t),
81
+ :reserved, Ragweed::Wraposx::Libc.find_type(:boolean_t),
82
+ :offset, Ragweed::Wraposx::Libc.find_type(:memory_object_offset_t),
83
+ :behavior, Ragweed::Wraposx::Libc.find_type(:vm_behavior_t),
84
+ :user_wired_count, :ushort
140
85
 
141
- def self.get(t, a)
142
- self.new(Ragweed::Wraposx::vm_region_raw(t, a, FLAVOR))
143
- end
144
- end
86
+ def dump(&block)
87
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
88
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
145
89
 
146
- class Ragweed::Wraposx::RegionExtendedInfo < Ragweed::Wraposx::RegionInfo
147
-
148
- FLAVOR = Ragweed::Wraposx::Vm::REGION_EXTENDED_INFO
149
- (FIELDS = [ [:protection, "i"],
150
- [:user_tag, "I"],
151
- [:pages_resident, "I"],
152
- [:pages_shared_now_private, "I"],
153
- [:pages_swapped_out, "I"],
154
- [:pages_dirtied, "I"],
155
- [:ref_count, "I"],
156
- [:shadow_depth, "S"],
157
- [:external_pager, "C"],
158
- [:share_mode, "C"],
159
- [:size, "I"],
160
- [:base_address, "I"] ]).each {|x| attr_accessor x[0]}
161
-
162
- def dump(&block)
163
- maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
164
- maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
165
-
166
- string =<<EOM
167
- -----------------------------------------------------------------------
168
- EXTENDED INFO:
169
- base address: #{self.base_address.to_s(16).rjust(8, "0")}
90
+ string =<<EOM
91
+ -----------------------------------------------------------------------
92
+ BASIC INFO:
93
+ base address: #{self.base_address.to_s(16).rjust(8, "0")}
170
94
 
171
- protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
172
- user_tag: #{self.user_tag.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_tag)}
173
- pages_resident: #{self.pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_resident)}
174
- pages_shared_now_private: #{self.pages_shared_now_private.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_shared_now_private)}
175
- pages_swapped_out: #{self.pages_swapped_out.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_swapped_out)}
176
- pages_dirtied: #{self.pages_dirtied.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_dirtied)}
177
- ref_count: #{self.ref_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ref_count)}
178
- shadow_depth: #{self.shadow_depth.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shadow_depth)}
179
- external_pager: #{self.external_pager.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.external_pager)}
180
- share_mode: #{self.share_mode.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.share_mode)}
181
- size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
95
+ protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
96
+ max_protection: #{self.max_protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.max_protection)}
97
+ inheritance: #{self.inheritance.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.inheritance)}
98
+ shared: #{self.shared.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared)}
99
+ reserved: #{self.reserved.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.reserved)}
100
+ offset: #{self.offset.to_s(16).rjust(16, "0")} #{maybe_hex.call(self.offset)}
101
+ behavior: #{self.behavior.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.behavior)}
102
+ user_wired_count: #{self.user_wired_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_wired_count)}
103
+ size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
182
104
  EOM
105
+ end
183
106
  end
184
107
 
185
- def self.get(t, a)
186
- self.new(Ragweed::Wraposx::vm_region_raw(t, a, FLAVOR))
187
- end
188
- end
108
+ # struct vm_region_extended_info {
109
+ # vm_prot_t protection;
110
+ # unsigned int user_tag;
111
+ # unsigned int pages_resident;
112
+ # unsigned int pages_shared_now_private;
113
+ # unsigned int pages_swapped_out;
114
+ # unsigned int pages_dirtied;
115
+ # unsigned int ref_count;
116
+ # unsigned short shadow_depth;
117
+ # unsigned char external_pager;
118
+ # unsigned char share_mode;
119
+ # };
120
+ class RegionExtendedInfo < RegionInfo
121
+ layout :protection, Ragweed::Wraposx::Libc.find_type(:vm_prot_t),
122
+ :user_tag, :uint,
123
+ :pages_resident, :uint,
124
+ :pages_shared_now_private, :uint,
125
+ :pages_swapped_out, :uint,
126
+ :pages_dirtied, :uint,
127
+ :ref_count, :uint,
128
+ :shadow_depth, :ushort,
129
+ :external_pager, :uchar,
130
+ :share_mode, :uchar
189
131
 
190
- class Ragweed::Wraposx::RegionTopInfo < Ragweed::Wraposx::RegionInfo
132
+ def dump(&block)
133
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
134
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
191
135
 
192
- FLAVOR = Ragweed::Wraposx::Vm::REGION_TOP_INFO
136
+ string =<<EOM
137
+ -----------------------------------------------------------------------
138
+ EXTENDED INFO:
139
+ base address: #{self.base_address.to_s(16).rjust(8, "0")}
140
+
141
+ protection: #{self.protection.to_s(2).rjust(8, "0")} #{Ragweed::Wraposx::Vm::Pflags.flag_dump(self.protection)}
142
+ user_tag: #{self.user_tag.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.user_tag)}
143
+ pages_resident: #{self.pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_resident)}
144
+ pages_shared_now_private: #{self.pages_shared_now_private.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_shared_now_private)}
145
+ pages_swapped_out: #{self.pages_swapped_out.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_swapped_out)}
146
+ pages_dirtied: #{self.pages_dirtied.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.pages_dirtied)}
147
+ ref_count: #{self.ref_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ref_count)}
148
+ shadow_depth: #{self.shadow_depth.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shadow_depth)}
149
+ external_pager: #{self.external_pager.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.external_pager)}
150
+ share_mode: #{self.share_mode.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.share_mode)}
151
+ size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
152
+ EOM
153
+ end
154
+ end
193
155
 
194
- (FIELDS = [ [:obj_id, "I"],
195
- [:ref_count, "I"],
196
- [:private_pages_resident, "I"],
197
- [:shared_pages_resident, "I"],
198
- [:share_mode, "C"],
199
- [:size, "I"],
200
- [:base_address,"I"]]).each {|x| attr_accessor x[0]}
156
+ # struct vm_region_top_info {
157
+ # unsigned int obj_id;
158
+ # unsigned int ref_count;
159
+ # unsigned int private_pages_resident;
160
+ # unsigned int shared_pages_resident;
161
+ # unsigned char share_mode;
162
+ # };
163
+ class RegionTopInfo < RegionInfo
164
+ layout :obj_id, :uint,
165
+ :ref_count, :uint,
166
+ :private_pages_resident, :uint,
167
+ :shared_pages_resident, :uint,
168
+ :share_mode, :uchar
201
169
 
202
- def dump(&block)
203
- maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
204
- maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
170
+ def dump(&block)
171
+ maybe_hex = lambda {|a| begin; "\n" + (" " * 9) + block.call(a, 16).hexdump(true)[10..-2]; rescue; ""; end }
172
+ maybe_dis = lambda {|a| begin; "\n" + block.call(a, 16).distorm.map {|i| " " + i.mnem}.join("\n"); rescue; ""; end }
205
173
 
206
- string =<<EOM
207
- -----------------------------------------------------------------------
208
- TOP INFO:
209
- base address: #{self.base_address.to_s(16).rjust(8, "0")}
174
+ string =<<EOM
175
+ -----------------------------------------------------------------------
176
+ TOP INFO:
177
+ base address: #{self.base_address.to_s(16).rjust(8, "0")}
210
178
 
211
- obj_id: #{self.obj_id.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.obj_id)}
212
- ref_count: #{self.ref_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ref_count)}
213
- private_pages_resident: #{self.private_pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.private_pages_resident)}
214
- shared_pages_resident: #{self.shared_pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared_pages_resident)}
215
- share_mode: #{self.share_mode.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.share_mode)}
216
- size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
179
+ obj_id: #{self.obj_id.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.obj_id)}
180
+ ref_count: #{self.ref_count.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.ref_count)}
181
+ private_pages_resident: #{self.private_pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.private_pages_resident)}
182
+ shared_pages_resident: #{self.shared_pages_resident.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.shared_pages_resident)}
183
+ share_mode: #{self.share_mode.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.share_mode)}
184
+ size: #{self.size.to_s(16).rjust(8, "0")} #{maybe_hex.call(self.size)}
217
185
  EOM
186
+ end
218
187
  end
219
188
 
220
- def self.get(t, a)
221
- self.new(Ragweed::Wraposx::vm_region_raw(t, a, FLAVOR))
222
- end
189
+ #define VM_REGION_BASIC_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_basic_info_data_t)/sizeof(int)))
190
+ #define VM_REGION_BASIC_INFO_COUNT_64 ((mach_msg_type_number_t) (sizeof(vm_region_basic_info_data_64_t)/sizeof(int)))
191
+ #define VM_REGION_EXTENDED_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_extended_info_data_t)/sizeof(int)))
192
+ #define VM_REGION_TOP_INFO_COUNT ((mach_msg_type_number_t) (sizeof(vm_region_top_info_data_t)/sizeof(int)))
193
+ FLAVORS = { REGION_BASIC_INFO => {:size => 30, :count => 8, :class => RegionBasicInfo},
194
+ REGION_BASIC_INFO_64 => {:size => 30, :count => 9, :class => RegionBasicInfo64},
195
+ REGION_EXTENDED_INFO => {:size => 32, :count => 8, :class => RegionExtendedInfo},
196
+ REGION_TOP_INFO => {:size => 17,:count => 5, :class => RegionTopInfo}
197
+ }
223
198
  end
224
199
 
225
200
  module Ragweed::Wraposx
201
+ module Libc
202
+ extend FFI::Library
203
+ ffi_lib FFI::Library::LIBC
204
+
205
+ # determine if a function is defined in the attached libraries
206
+ def self.find_function func
207
+ ffi_libraries.detect{|lib| lib.find_function(func)}
208
+ end
209
+
210
+ attach_function :vm_region, [:vm_map_t, :pointer, :pointer, :vm_region_flavor_t, :pointer, :pointer, :pointer], :int if find_function "vm_region"
211
+ attach_function :vm_region_64, [:vm_map_t, :pointer, :pointer, :vm_region_flavor_t, :pointer, :pointer, :pointer], :int if find_function "vm_region_64"
212
+ end
213
+
226
214
  class << self
227
215
 
228
- # Returns a string containing the memory region information for task
229
- # at address.
216
+ # Returns the base address, size, and a pointer to the requested information
217
+ # about the memory region at address in the target_task.
230
218
  #
231
- # The order of the elements in the returned string will change in 0.2.0+
232
- # to match the argument order.
219
+ # Currently, only VM_REGION_BASIC_INFO is supported by Apple.
220
+ # Unless this is being run in 32bits, use vm_region_64 instead.
233
221
  #
234
222
  # kern_return_t vm_region
235
- # (vm_task_t target_task,
236
- # vm_address_t address,
237
- # vm_size_t size,
238
- # vm_region_flavor_t flavor,
239
- # vm_region_info_t info,
240
- # mach_msg_type_number_t info_count,
241
- # memory_object_name_t object_name);
242
- def vm_region_raw(task, address, flavor)
243
- info = ("\x00"*Vm::FLAVORS[flavor][:size]).to_ptr
244
- count = ([Vm::FLAVORS[flavor][:count]].pack("I_")).to_ptr
245
- address = ([address].pack("I_")).to_ptr
246
- objn = ([0].pack("I_")).to_ptr
247
- sz = ("\x00"*SIZEOFINT).to_ptr
248
- r = CALLS["libc!vm_region:IPPIPPP=I"].call(task, address, sz, flavor, info, count, objn).first
223
+ # (vm_map_t target_task,
224
+ # vm_address_t *address,
225
+ # vm_size_t *size,
226
+ # vm_region_flavor_t flavor,
227
+ # vm_region_info_t info,
228
+ # mach_msg_type_number_t *info_count,
229
+ # mach_port_t *object_name);
230
+ def vm_region(task, addr, flavor)
231
+ info = FFI::MemoryPointer.new(Vm::FLAVORS[flavor][:class], 1)
232
+ count = FFI::MemoryPointer.new(:int, 1).write_int(Vm::FLAVORS[flavor][:count])
233
+ address = FFI::MemoryPointer.new(:vm_address_t, 1).write_ulong(addr)
234
+ sz = FFI::MemoryPointer.new(:vm_size_t, 1)
235
+ objn = FFI::MemoryPointer.new(:mach_port_t, 1)
236
+
237
+ r = Libc.vm_region(task, address, sz, flavor, info, count, objn)
249
238
  raise KernelCallError.new(:vm_region, r) if r != 0
250
- # this
251
- return "#{info.to_s(Vm::FLAVORS[flavor][:size])}#{sz.to_s(SIZEOFINT)}#{address.to_s(SIZEOFINT)}"
252
- end
239
+ ret = Vm::Flavors[flavor][:class].new info
240
+ ret.region_size = size.read_ulong
241
+ ret.base_address = address.read_ulong
242
+ ret
243
+ end if Libc.find_function "vm_region"
244
+
245
+ # Returns the base address, size, and a pointer to the requested information
246
+ # about the memory region at address in the target_task.
247
+ #
248
+ # Currently, only VM_REGION_BASIC_INFO is supported by Apple.
249
+ #
250
+ # kern_return_t vm_region
251
+ # (vm_map_t target_task,
252
+ # vm_address_t *address,
253
+ # vm_size_t *size,
254
+ # vm_region_flavor_t flavor,
255
+ # vm_region_info_t info,
256
+ # mach_msg_type_number_t *info_count,
257
+ # mach_port_t *object_name);
258
+ def vm_region_64(task, addr, flavor)
259
+ # OSX does this as well, so we need to do it ourselves
260
+ flavor = Vm::REGION_BASIC_INFO_64 if flavor == Vm::REGION_BASIC_INFO
261
+ info = FFI::MemoryPointer.new(:uint8, Vm::FLAVORS[flavor][:size])
262
+ count = FFI::MemoryPointer.new(Libc.find_type(:mach_msg_type_number_t), 1).write_uint(Vm::FLAVORS[flavor][:count])
263
+ address = FFI::MemoryPointer.new(Libc.find_type(:vm_address_t), 1).write_ulong(addr)
264
+ sz = FFI::MemoryPointer.new(Libc.find_type(:vm_size_t), 1)
265
+ objn = FFI::MemoryPointer.new(Libc.find_type(:mach_port_t), 1)
266
+
267
+ r = Libc.vm_region_64(task, address, sz, flavor, info, count, objn)
268
+ raise KernelCallError.new(:vm_region_64, r) if r != 0
269
+ ret = Vm::Flavors[flavor][:class].new info
270
+ ret.region_size = size.read_ulong
271
+ ret.base_address = address.read_ulong
272
+ ret
273
+ end if Libc.find_function "vm_region_64"
253
274
  end
254
275
  end
@@ -0,0 +1,102 @@
1
+ # miscelaneous structs needed for other calls/structures
2
+
3
+ module Ragweed; end
4
+ module Ragweed::Wraposx
5
+ class FpControl < FFI::Struct
6
+ layout :value, :ushort
7
+
8
+ def invalid
9
+ self.value >> 15
10
+ end
11
+ def denorm
12
+ (self.value >> 14) & 1
13
+ end
14
+ def zdiv
15
+ (self.value >> 13) & 1
16
+ end
17
+ def ovrfl
18
+ (self.value >> 12) & 1
19
+ end
20
+ def undfl
21
+ (self.value >> 11) & 1
22
+ end
23
+ def precis
24
+ (self.value >> 10) & 1
25
+ end
26
+ def res0
27
+ (self.value >> 8) & 3
28
+ end
29
+ def pc
30
+ (self.value >> 6) & 3
31
+ end
32
+ def rc
33
+ (self.value >> 4) & 3
34
+ end
35
+ def res1
36
+ (self.value >> 3) & 1
37
+ end
38
+ def res2
39
+ self.value & 7
40
+ end
41
+ end
42
+
43
+ class FpStatus < FFI::Struct
44
+ layout :value, :ushort
45
+ def invalid
46
+ self.value >> 15
47
+ end
48
+ def denorm
49
+ (self.value >> 14) & 1
50
+ end
51
+ def zdiv
52
+ (self.value >> 13) & 1
53
+ end
54
+ def ovrfl
55
+ (self.value >> 12) & 1
56
+ end
57
+ def undfl
58
+ (self.value >> 11) & 1
59
+ end
60
+ def precis
61
+ (self.value >> 10) & 1
62
+ end
63
+ def stkflt
64
+ (self.value >> 9) & 1
65
+ end
66
+ def errsumm
67
+ (self.value >> 8) & 1
68
+ end
69
+ def c0
70
+ (self.value >> 7) & 1
71
+ end
72
+ def c1
73
+ (self.value >> 6) & 1
74
+ end
75
+ def c2
76
+ (self.value >> 5) & 1
77
+ end
78
+ def tos
79
+ (self.value >> 2) & 7
80
+ end
81
+ def c2
82
+ (self.value >> 1) & 1
83
+ end
84
+ def busy
85
+ self.value & 1
86
+ end
87
+ end
88
+
89
+ class MmstReg < FFI::Struct
90
+ layout :mmst_reg, [:char, 10],
91
+ :mmst_rsrv, [:char, 6]
92
+ end
93
+
94
+ class XmmReg < FFI::Struct
95
+ layout :xmm_reg, [:char, 16]
96
+ end
97
+
98
+ class TimeValue < FFI::Struct
99
+ layout :seconds, :int,
100
+ :microseconds, :int
101
+ end
102
+ end