diff --git a/Main.mm b/Main.mm index 9fecf51..b0efc1a 100644 --- a/Main.mm +++ b/Main.mm @@ -12,7 +12,6 @@ void trace(NSString* format,...) printf("\e[%dm%s\e[0m\n",31+DSCE_VERSION%6,message.UTF8String); } -BOOL flagList=false; BOOL flagPad=false; #import "LocationBase.h" @@ -36,93 +35,133 @@ void trace(NSString* format,...) #import "Selector.m" #import "Output.m" -void extract(CacheSet* cache,CacheImage* image) +void process(NSMutableArray* args) { - // TODO: check for leaks between images + NSString* cachePath=args[0]; + [args removeObjectAtIndex:0]; - @autoreleasepool + CacheSet* cache=[CacheSet.alloc initWithPathPrefix:cachePath].autorelease; + assert(cache); + + if([args containsObject:@"list"]) { - double startTime=NSDate.date.timeIntervalSince1970; + assert(args.count==1); - NSString* outPath=[@"Out" stringByAppendingString:image.path]; - NSString* outFolder=outPath.stringByDeletingLastPathComponent; - assert([NSFileManager.defaultManager createDirectoryAtPath:outFolder withIntermediateDirectories:true attributes:nil error:nil]); + NSArray* images=[cache imagesWithPathPrefix:@"/"]; - [Output runWithCache:cache image:image outPath:outPath]; + trace(@"list %x images",images.count); - trace(@"image took %.2lf seconds",NSDate.date.timeIntervalSince1970-startTime); - } -} - -int main(int argc,char** argv) -{ - NSString* edge=[@"" stringByPaddingToLength:9+log10(DSCE_VERSION) withString:@"─" startingAtIndex:0]; - trace(@"┌%@┐",edge); - trace(@"│ dsce v%d │",DSCE_VERSION); - trace(@"└%@┘",edge); - - if(argc<3) - { - trace(@"usage: dsce [list] [pad] [path prefix ...]"); - return 1; + for(CacheImage* image in images) + { + trace(@"%@",image.path); + } + + return; } - double startTime=NSDate.date.timeIntervalSince1970; - - NSString* cachePath=[NSString stringWithUTF8String:argv[1]]; - CacheSet* cache=[CacheSet.alloc initWithPathPrefix:cachePath].autorelease; - assert(cache); - - NSMutableArray* images=NSMutableArray.alloc.init.autorelease; - - for(int index=2;index* images=NSMutableArray.alloc.init.autorelease; + for(NSString* arg in args) + { NSArray* subset=[cache imagesWithPathPrefix:arg]; + if(subset.count==0) { trace(@"no images found for %@*",arg); abort(); } + [images addObjectsFromArray:subset]; } - if(flagList) + for(int index=0;index ( list | search | [pad] ... )"); + return 1; + } + + double startTime=NSDate.date.timeIntervalSince1970; + + NSMutableArray* args=NSMutableArray.alloc.init.autorelease; + for(int index=1;index* fixups; @property(retain) NSMutableArray* exports; @property(retain) NSMutableDictionary* sels; +@property(assign) long baseAddressDelta; +(void)runWithCache:(CacheSet*)cache image:(CacheImage*)image outPath:(NSString*)outPath; diff --git a/Output.m b/Output.m index ff7bd55..7c08e91 100644 --- a/Output.m +++ b/Output.m @@ -82,12 +82,15 @@ -(void)extractWithPath:(NSString*)outPath self.stepFixProtoRefs; self.stepFixProtos; self.stepFixPointersNew; + self.stepFixInitOffsets; self.stepBuildLinkedit; self.stepMarkUUID; self.stepSyncHeader; trace(@"write %@",outPath); - [self.data writeToFile:outPath atomically:false]; + NSError* error=nil; + [self.data writeToFile:outPath options:0 error:&error]; + assert(!error); } -(BOOL)needsObjcImpostor @@ -97,7 +100,7 @@ -(BOOL)needsObjcImpostor -(BOOL)needsGotImpostor { - if(self.cache.majorVersion!=13) + if(self.cache.majorVersion<13) { return false; } @@ -185,8 +188,6 @@ -(void)stepImportHeader { if(self.shouldMakeContiguous) { - // unlike objc impostor, there's a gap here - self.addPadCommandCommon; } @@ -244,6 +245,7 @@ -(void)stepImportHeader break; // TODO: explicitly list ignored commands, add assert for unrecognied + // the current list is sort of arbitrary and could be omitting important things default: skipped++; @@ -410,10 +412,14 @@ -(void)importSegmentsCommon:(BOOL)linkeditPhase long newSegOffset=self.data.length; assert(isAligned(newSegOffset,0x1000)); + // TODO: in contiguous mode, assert that we are actually contiguous + if(newSegOffset==0) { newSegAddress-=HEADER_EXTRA; addressDelta-=HEADER_EXTRA; + + self.baseAddressDelta=addressDelta; } [data increaseLengthBy:-addressDelta]; @@ -642,7 +648,6 @@ -(void)writeFixupsWithData:(NSMutableData*)data [data appendBytes:trieBytes.data() length:trieBytes.size()]; // to avoid gap before symtab, the padding is counted as part of the exports trie - // this is not an issue since the structure defines its own end align(data.length,0x1000,true,&padding); [data increaseLengthBy:padding]; @@ -818,8 +823,6 @@ -(void)stepImportRebases { self.fixups=NSMutableDictionary.alloc.init.autorelease; - // TODO: almost like duplication with LocationBase protocol... not quite - [self.header forEachSectionCommand:^(struct segment_command_64* segment,struct section_64* section) { if(self.shouldMakeContiguous&&!strcmp(section->sectname,IMPOSTOR_PAD)) @@ -898,7 +901,7 @@ -(void)stepFixSelRefs } long* refs=(long*)wrapOffset(self,section->offset).pointer; - int count=section->size/sizeof(long*); + int count=section->size/sizeof(long); trace(@"fixing %x selector refs",count); @@ -938,7 +941,7 @@ -(void)stepFixClasses } long* classes=(long*)wrapOffset(self,section->offset).pointer; - int count=section->size/sizeof(long*); + int count=section->size/sizeof(long); trace(@"fixing %x classes",count); @@ -968,7 +971,7 @@ -(void)stepFixCats } long* cats=(long*)wrapOffset(self,section->offset).pointer; - int count=section->size/sizeof(long*); + int count=section->size/sizeof(long); trace(@"fixing %x categories",count); @@ -993,7 +996,7 @@ -(void)stepFixProtoRefs } long* refs=(long*)wrapOffset(self,section->offset).pointer; - int count=section->size/sizeof(long*); + int count=section->size/sizeof(long); trace(@"fixing %x protocol refs",count); @@ -1015,7 +1018,7 @@ -(void)stepFixProtos } long* refs=(long*)wrapOffset(self,section->offset).pointer; - int count=section->size/sizeof(long*); + int count=section->size/sizeof(long); trace(@"fixing %x protocols",count); @@ -1039,7 +1042,7 @@ -(long)embeddedProtoAddressWithName:(char*)target assert(section); long* refs=(long*)wrapOffset(self,section->offset).pointer; - int count=section->size/sizeof(long*); + int count=section->size/sizeof(long); for(int index=0;indexoffset).pointer; + int count=section->size/sizeof(int); + + trace(@"fixing %x initializer offsets",count); + + for(int index=0;index