1
1
/*
2
- * Copyright (c) 2007 Apple Inc. All Rights Reserved.
2
+ * Copyright (c) 2007-2009 Apple Inc. All Rights Reserved.
3
3
*
4
4
* @APPLE_LICENSE_HEADER_START@
5
5
*
31
31
#import <mach-o/arch.h>
32
32
#import <mach-o/loader.h>
33
33
34
+ // from "objc-private.h"
35
+ // masks for objc_image_info.flags
36
+ #define OBJC_IMAGE_IS_REPLACEMENT (1<<0)
37
+ #define OBJC_IMAGE_SUPPORTS_GC (1<<1)
38
+ #define OBJC_IMAGE_REQUIRES_GC (1<<2)
39
+ #define OBJC_IMAGE_OPTIMIZED_BY_DYLD (1<<3)
40
+ #define OBJC_IMAGE_SUPPORTS_COMPACTION (1<<4)
41
+
34
42
typedef char bool ;
35
43
#define true 1
36
44
#define false 0
@@ -40,6 +48,7 @@ bool verbose;
40
48
bool quiet ;
41
49
bool rrOnly ;
42
50
bool patch = true;
51
+ bool unpatch = false;
43
52
44
53
struct gcinfo {
45
54
bool hasObjC ;
@@ -60,14 +69,10 @@ int main(int argc, char *argv[]) {
60
69
int i ;
61
70
//dumpinfo("/System/Library/Frameworks/AppKit.framework/AppKit");
62
71
if (argc == 1 ) {
63
- printf ("Usage: gcinfo [-v] [-r] [--] library_or_executable_image [image2 ...]\n" );
64
- printf (" prints Garbage Collection readiness of named images, ignoring those without ObjC segments\n" );
65
- printf (" 'GC' - compiled with write-barriers, presumably otherwise aware\n" );
66
- printf (" 'RR' - retain/release (presumed) aware for non-GC\n" );
67
- printf (" 'GC-only' - compiled with write-barriers and marked at compile time as not being retain/release savvy\n" );
68
- printf (" -v - provide archtectural details\n" );
69
- printf (" -r - only show libraries that are non-GC, e.g. RR only\n" );
70
- printf (" -- - read files & directories from stdin, e.g. find /Plug-ins | gcinfo --\n" );
72
+ printf ("Usage: markgc [-v] [-r] [--] library_or_executable_image [image2 ...]\n" );
73
+ printf (" changes Garbage Collection readiness of named images, ignoring those without ObjC segments\n" );
74
+ printf (" -p - patch RR binary to (apparently) support GC (default)\n" );
75
+ printf (" -u - unpatch GC binary to RR only\n" );
71
76
printf (
"\nAuthor: [email protected] \n" );
72
77
exit (0 );
73
78
}
@@ -84,22 +89,13 @@ int main(int argc, char *argv[]) {
84
89
quiet = true;
85
90
continue ;
86
91
}
87
- if (!strcmp (argv [i ], "-r" )) {
88
- quiet = true;
89
- rrOnly = true;
90
- continue ;
91
- }
92
92
if (!strcmp (argv [i ], "-p" )) {
93
93
patch = true;
94
94
continue ;
95
95
}
96
- if (!strcmp (argv [i ], "--" )) {
97
- char buf [1024 ];
98
- while (fgets (buf , 1024 , stdin )) {
99
- int len = strlen (buf );
100
- buf [len - 1 ] = 0 ;
101
- dumpinfo (buf );
102
- }
96
+ if (!strcmp (argv [i ], "-u" )) {
97
+ unpatch = true;
98
+ patch = false;
103
99
continue ;
104
100
}
105
101
dumpinfo (argv [i ]);
@@ -116,30 +112,36 @@ void patchFile(uint32_t value, size_t offset) {
116
112
int fd = open (FileName , 1 );
117
113
off_t lresult = lseek (fd , offset , SEEK_SET );
118
114
if (lresult == -1 ) {
119
- printf ("couldn't seek to %x position on fd %d\n" , offset , fd );
115
+ printf ("couldn't seek to 0x%lx position on fd %d\n" , offset , fd );
120
116
++ Errors ;
121
117
return ;
122
118
}
123
- int wresult = write (fd , & value , 4 );
119
+ size_t wresult = write (fd , & value , 4 );
124
120
if (wresult != 4 ) {
125
121
++ Errors ;
126
122
printf ("didn't write new value\n" );
127
123
}
128
124
else {
129
- printf ("patched %s at offset %p \n" , FileName , offset );
125
+ printf ("patched %s at offset 0x%lx \n" , FileName , offset );
130
126
}
131
127
close (fd );
132
128
}
133
129
134
- uint32_t iiflags (struct imageInfo * ii , uint32_t size , bool needsFlip ) {
130
+ uint32_t iiflags (struct imageInfo * ii , size_t size , bool needsFlip ) {
135
131
if (needsFlip ) {
136
132
ii -> flags = OSSwapInt32 (ii -> flags );
137
133
}
138
- if (debug ) printf ("flags->%x, nitems %d\n" , ii -> flags , size /sizeof (struct imageInfo ));
134
+ if (debug ) printf ("flags->%x, nitems %lu\n" , ii -> flags , size /sizeof (struct imageInfo ));
135
+ uint32_t support_mask = (OBJC_IMAGE_SUPPORTS_GC | OBJC_IMAGE_SUPPORTS_COMPACTION );
139
136
uint32_t flags = ii -> flags ;
140
- if (patch && (flags & 0x2 ) == 0 ) {
137
+ if (patch && (flags & support_mask ) != support_mask ) {
141
138
//printf("will patch %s at offset %p\n", FileName, (char*)(&ii->flags) - FileBase);
142
- uint32_t newvalue = flags | 0x2 ;
139
+ uint32_t newvalue = flags | support_mask ;
140
+ if (needsFlip ) newvalue = OSSwapInt32 (newvalue );
141
+ patchFile (newvalue , (char * )(& ii -> flags ) - FileBase );
142
+ }
143
+ if (unpatch && (flags & support_mask ) == support_mask ) {
144
+ uint32_t newvalue = flags & ~support_mask ;
143
145
if (needsFlip ) newvalue = OSSwapInt32 (newvalue );
144
146
patchFile (newvalue , (char * )(& ii -> flags ) - FileBase );
145
147
}
@@ -194,7 +196,7 @@ void dosect64(void *start, struct section_64 *sect, bool needsFlip, struct gcinf
194
196
sect -> size = OSSwapInt64 (sect -> size );
195
197
}
196
198
// these guys aren't inline - they point elsewhere
197
- gcip -> flags = iiflags (start + sect -> offset , sect -> size , needsFlip );
199
+ gcip -> flags = iiflags (start + sect -> offset , ( size_t ) sect -> size , needsFlip );
198
200
}
199
201
200
202
void doseg32 (void * start , struct segment_command * seg , bool needsFlip , struct gcinfo * gcip ) {
@@ -207,9 +209,8 @@ void doseg32(void *start, struct segment_command *seg, bool needsFlip, struct gc
207
209
if (seg -> segname [0 ]) {
208
210
if (strcmp ("__OBJC" , seg -> segname )) return ;
209
211
}
210
- int nsects ;
211
212
struct section * sect = (struct section * )(seg + 1 );
212
- for (int nsects = 0 ; nsects < seg -> nsects ; ++ nsects ) {
213
+ for (uint32_t nsects = 0 ; nsects < seg -> nsects ; ++ nsects ) {
213
214
// sections directly follow
214
215
215
216
dosect32 (start , sect + nsects , needsFlip , gcip );
@@ -224,9 +225,8 @@ void doseg64(void *start, struct segment_command_64 *seg, bool needsFlip, struct
224
225
seg -> fileoff = OSSwapInt64 (seg -> fileoff );
225
226
seg -> nsects = OSSwapInt32 (seg -> nsects );
226
227
}
227
- int nsects ;
228
228
struct section_64 * sect = (struct section_64 * )(seg + 1 );
229
- for (int nsects = 0 ; nsects < seg -> nsects ; ++ nsects ) {
229
+ for (uint32_t nsects = 0 ; nsects < seg -> nsects ; ++ nsects ) {
230
230
// sections directly follow
231
231
232
232
dosect64 (start , sect + nsects , needsFlip , gcip );
@@ -274,11 +274,11 @@ void dodylib(void *start, struct dylib_command *dylibCmd, bool needsFlip) {
274
274
if (!verbose ) return ;
275
275
if (needsFlip ) {
276
276
}
277
- int count = dylibCmd -> cmdsize - sizeof (struct dylib_command );
277
+ size_t count = dylibCmd -> cmdsize - sizeof (struct dylib_command );
278
278
//printf("offset is %d, count is %d\n", dylibCmd->dylib.name.offset, count);
279
279
if (dylibCmd -> dylib .name .offset > count ) return ;
280
280
//printf("-->%.*s<---", count, ((void *)dylibCmd)+dylibCmd->dylib.name.offset);
281
- if (verbose ) printf ("load %s\n" , ((void * )dylibCmd )+ dylibCmd -> dylib .name .offset );
281
+ if (verbose ) printf ("load %s\n" , ((char * )dylibCmd )+ dylibCmd -> dylib .name .offset );
282
282
}
283
283
284
284
struct load_command * doloadcommand (void * start , struct load_command * lc , bool needsFlip , bool is32 , struct gcinfo * gcip ) {
@@ -309,7 +309,7 @@ struct load_command *doloadcommand(void *start, struct load_command *lc, bool ne
309
309
return (struct load_command * )((void * )lc + lc -> cmdsize );
310
310
}
311
311
312
- void doofile (void * start , uint32_t size , struct gcinfo * gcip ) {
312
+ void doofile (void * start , size_t size , struct gcinfo * gcip ) {
313
313
struct mach_header * mh = (struct mach_header * )start ;
314
314
bool isFlipped = false;
315
315
if (mh -> magic == MH_CIGAM || mh -> magic == MH_CIGAM_64 ) {
@@ -411,16 +411,16 @@ bool openFile(const char *filename) {
411
411
close (fd );
412
412
return false;
413
413
}
414
- FileSize = statb .st_size ;
414
+ FileSize = ( size_t ) statb .st_size ;
415
415
FileBase = malloc (FileSize );
416
416
if (!FileBase ) {
417
- printf ("couldn't malloc %d bytes\n" , FileSize );
417
+ printf ("couldn't malloc %lu bytes\n" , FileSize );
418
418
close (fd );
419
419
return false;
420
420
}
421
421
off_t readsize = read (fd , FileBase , FileSize );
422
422
if (readsize != FileSize ) {
423
- printf ("read %d bytes, wanted %d \n" , readsize , FileSize );
423
+ printf ("read %ld bytes, wanted %ld \n" , ( size_t ) readsize , FileSize );
424
424
close (fd );
425
425
return false;
426
426
}
0 commit comments