]> Dogcows Code - chaz/thecheat/blob - VMRegion.m
update contact information and project URL
[chaz/thecheat] / VMRegion.m
1
2 //
3 // VMRegion 0.1
4 // Virtual Memory Wrapper
5 //
6 // Copyright (c) 2004, Charles McGarvey
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without modification, are
10 // permitted provided that the following conditions are met:
11 //
12 // 1. Redistributions of source code must retain the above copyright notice, this list
13 // of conditions and the following disclaimer.
14 //
15 // 2. Redistributions in binary form must reproduce the above copyright notice, this
16 // list of conditions and the following disclaimer in the documentation and/or other
17 // materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
20 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
21 // OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
22 // SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
23 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24 // TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
25 // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
27 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
28 // DAMAGE.
29 //
30
31 #import "VMRegion.h"
32
33 #include <mach/mach_traps.h> // for task_for_pid(3)
34 #include <signal.h> // for stop(2)
35
36 static __inline__ vm_map_t _VMTaskFromPID( pid_t process )
37 {
38 vm_map_t task;
39
40 if ( task_for_pid( current_task(), process, &task ) == KERN_SUCCESS ) {
41 return task;
42 }
43 return 0;
44 }
45
46 static __inline__ VMRegion _VMMakeRegionWithAttributes( pid_t process, mach_vm_address_t address, mach_vm_size_t size, unsigned attribs )
47 {
48 VMRegion region;
49 region._process = process;
50 region._address = address;
51 region._size = size;
52 region._attributes = attribs;
53 return region;
54 }
55
56 unsigned _VMAttributesFromAddress( pid_t process, mach_vm_address_t address );
57
58
59 const VMRegion VMNullRegion = { 0, 0, 0, 0 };
60
61
62 #pragma mark -
63 #pragma mark VMRegion Functions
64 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
65
66 VMRegion VMMakeRegion( pid_t process, mach_vm_address_t address, mach_vm_size_t size )
67 {
68 VMRegion region;
69 region._process = process;
70 region._address = address;
71 region._size = size;
72 region._attributes = _VMAttributesFromAddress( process, address );
73 return region;
74 }
75
76 BOOL VMRegionSetData( VMRegion region, NSData *data )
77 {
78 // get the size that should be used (to prevent from writing past the region)
79 mach_vm_size_t size = (mach_vm_size_t)[data length];
80 size = (size > region._size)? region._size : size;
81
82 return VMWriteBytes( region._process, region._address, [data bytes], size );
83 }
84
85 NSString *VMStringFromRegion( VMRegion region )
86 {
87 return [NSString stringWithFormat:@"{pid:%i,%p,%u,}", region._process, region._address, region._size];
88 }
89
90
91 #pragma mark -
92 #pragma mark Utility VM Functions
93 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
94
95 unsigned VMCountRegions( pid_t process )
96 {
97 VMRegion region;
98 VMRegion prev = VMNullRegion;
99 unsigned count = 0;
100
101 while ( VMRegionIsNotNull( region = VMNextRegion( process, prev ) ) )
102 {
103 count++;
104 prev = region;
105 }
106
107 return count;
108 }
109
110 unsigned VMCountRegionsWithAttributes( pid_t process, unsigned attribs )
111 {
112 VMRegion region;
113 VMRegion prev = VMNullRegion;
114 unsigned count = 0;
115
116 while ( VMRegionIsNotNull( region = VMNextRegionWithAttributes( process, prev, attribs ) ) )
117 {
118 count++;
119 prev = region;
120 }
121
122 return count;
123 }
124
125
126 VMRegion VMNextRegion( pid_t process, VMRegion previous )
127 {
128 vm_map_t task = _VMTaskFromPID( process );
129 unsigned attribs = 0;
130
131 kern_return_t result;
132
133 mach_vm_address_t address = 0x0;
134 mach_vm_size_t size = 0;
135 vm_region_basic_info_data_64_t info;
136 mach_msg_type_number_t infoCnt = VM_REGION_BASIC_INFO_COUNT_64;
137 mach_port_t object_name = 0;
138
139 if ( !VMEqualRegions( previous, VMNullRegion ) ) {
140 address = previous._address + previous._size;
141 }
142
143 // get the next region
144 result = mach_vm_region( task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_t)(&info), &infoCnt, &object_name );
145
146 if ( result == KERN_SUCCESS ) {
147 // get the attributes
148 if ( info.protection & VM_PROT_READ ) {
149 attribs |= VMREGION_READABLE;
150 }
151 if ( info.protection & VM_PROT_WRITE ) {
152 attribs |= VMREGION_WRITABLE;
153 }
154 if ( info.protection & VM_PROT_EXECUTE ) {
155 attribs |= VMREGION_EXECUTABLE;
156 }
157 // return the region
158 return _VMMakeRegionWithAttributes( process, address, size, attribs );
159 }
160
161 return VMNullRegion;
162 }
163
164 VMRegion VMNextRegionWithAttributes( pid_t process, VMRegion previous, unsigned attribs )
165 {
166 VMRegion region;
167
168 while ( VMRegionIsNotNull( region = VMNextRegion( process, previous ) ) )
169 {
170 if ( (attribs & region._attributes) == attribs ) {
171 // pass back this region if the attributes match
172 return region;
173 }
174 previous = region;
175 }
176
177 return VMNullRegion;
178 }
179
180
181 NSData *VMReadData( pid_t process, mach_vm_address_t address, mach_vm_size_t size )
182 {
183 vm_map_t task = _VMTaskFromPID( process );
184 kern_return_t result;
185
186 void *buffer;
187 mach_vm_size_t actualSize;
188
189 // create a local block to hold the incoming data
190 buffer = (void *)malloc( (size_t)size );
191 if ( !buffer ) {
192 // no buffer, abort
193 return nil;
194 }
195
196 // perform the read
197 result = mach_vm_read_overwrite( task, address, size, (vm_offset_t)buffer, &actualSize );
198 if ( result != KERN_SUCCESS ) {
199 // read error, abort
200 free( buffer );
201 return nil;
202 }
203
204 // everything seems to be peachy, so return the data
205 return [[[NSData alloc] initWithBytesNoCopy:buffer length:actualSize freeWhenDone:YES] autorelease];
206 }
207
208 BOOL VMReadBytes( pid_t process, mach_vm_address_t address, void *bytes, mach_vm_size_t *size )
209 {
210 vm_map_t task = _VMTaskFromPID( process );
211 kern_return_t result;
212 mach_vm_size_t staticsize = *size;
213
214 // perform the read
215 result = mach_vm_read_overwrite( task, address, staticsize, (vm_offset_t)bytes, size );
216 if ( result != KERN_SUCCESS ) {
217 return NO;
218 }
219
220 return YES;
221 }
222
223 BOOL VMWriteData( pid_t process, mach_vm_address_t address, NSData *data )
224 {
225 return VMWriteBytes( process, address, [data bytes], [data length] );
226 }
227
228 BOOL VMWriteBytes( pid_t process, mach_vm_address_t address, const void *bytes, mach_vm_size_t size )
229 {
230 vm_map_t task = _VMTaskFromPID( process );
231 kern_return_t result;
232
233 // attempt to write the bytes and return success/failure
234 result = mach_vm_write( task, address, (vm_offset_t)bytes, size );
235 return (result == KERN_SUCCESS);
236 }
237
238
239 unsigned _VMAttributesFromAddress( pid_t process, mach_vm_address_t address )
240 {
241 vm_map_t task = _VMTaskFromPID( process );
242 unsigned attribs = 0;
243
244 kern_return_t result;
245
246 mach_vm_size_t size = 0;
247 vm_region_basic_info_data_64_t info;
248 mach_msg_type_number_t infoCnt = VM_REGION_BASIC_INFO_COUNT_64;
249 mach_port_t object_name = 0;
250
251 // get the next region
252 result = mach_vm_region( task, &address, &size, VM_REGION_BASIC_INFO_64, (vm_region_info_t)(&info), &infoCnt, &object_name );
253
254 if ( result == KERN_SUCCESS ) {
255 // get the attributes
256 if ( info.protection & VM_PROT_READ ) {
257 attribs |= VMREGION_READABLE;
258 }
259 if ( info.protection & VM_PROT_WRITE ) {
260 attribs |= VMREGION_WRITABLE;
261 }
262 if ( info.protection & VM_PROT_EXECUTE ) {
263 attribs |= VMREGION_EXECUTABLE;
264 }
265 // return the region attributes
266 return attribs;
267 }
268 return 0;
269 }
270
271
This page took 0.040745 seconds and 4 git commands to generate.