Merge pull request #41 from 0xced/sdk-10.9

Use the encryption info for 64-bits goodies available in the 10.9 SDK
diff --git a/Source/CDLCSegment.m b/Source/CDLCSegment.m
index 61570d9..867f015 100644
--- a/Source/CDLCSegment.m
+++ b/Source/CDLCSegment.m
@@ -22,6 +22,8 @@
 
 @implementation CDLCSegment
 {
+    struct segment_command_64 _segmentCommand; // 64-bit, also holding 32-bit
+    
     NSString *_name;
     NSArray *_sections;
     
@@ -31,9 +33,26 @@
 - (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor;
 {
     if ((self = [super initWithDataCursor:cursor])) {
-        _name = nil;
-        _sections = nil;
-        _decryptedData = nil;
+        _segmentCommand.cmd     = [cursor readInt32];
+        _segmentCommand.cmdsize = [cursor readInt32];
+        
+        _name = [cursor readStringOfLength:16 encoding:NSASCIIStringEncoding];
+        memcpy(_segmentCommand.segname, [_name UTF8String], sizeof(_segmentCommand.segname));
+        _segmentCommand.vmaddr   = [cursor readPtr];
+        _segmentCommand.vmsize   = [cursor readPtr];
+        _segmentCommand.fileoff  = [cursor readPtr];
+        _segmentCommand.filesize = [cursor readPtr];
+        _segmentCommand.maxprot  = [cursor readInt32];
+        _segmentCommand.initprot = [cursor readInt32];
+        _segmentCommand.nsects   = [cursor readInt32];
+        _segmentCommand.flags    = [cursor readInt32];
+        
+        NSMutableArray *sections = [[NSMutableArray alloc] init];
+        for (NSUInteger index = 0; index < _segmentCommand.nsects; index++) {
+            CDSection *section = [[CDSection alloc] initWithDataCursor:cursor segment:self];
+            [sections addObject:section];
+        }
+        _sections = [sections copy];
     }
 
     return self;
@@ -41,57 +60,49 @@
 
 #pragma mark - Debugging
 
-- (NSString *)description;
-{
-    NSString *extra = [self extraDescription];
-    
-    if (extra == nil) {
-        return [NSString stringWithFormat:@"<%@:%p> name: %@",
-                NSStringFromClass([self class]), self,
-                self.name];
-    }
-    
-    return [NSString stringWithFormat:@"<%@:%p> name: %@, %@",
-            NSStringFromClass([self class]), self,
-            self.name, extra];
-}
-
 - (NSString *)extraDescription;
 {
-    // Implement in subclasses
-    return nil;
+    int padding = (int)self.machOFile.ptrSize * 2;
+    return [NSString stringWithFormat:@"vmaddr: 0x%0*llx - 0x%0*llx [0x%0*llx], offset: %lld, flags: 0x%x (%@), nsects: %d, sections: %@",
+            padding, _segmentCommand.vmaddr, padding, _segmentCommand.vmaddr + _segmentCommand.vmsize - 1, padding, _segmentCommand.vmsize,
+            _segmentCommand.fileoff, self.flags, [self flagDescription], _segmentCommand.nsects, self.sections.count > 0 ? self.sections : @"N/A"];
 }
 
 #pragma mark -
 
+- (uint32_t)cmd;
+{
+    return _segmentCommand.cmd;
+}
+
+- (uint32_t)cmdsize;
+{
+    return _segmentCommand.cmdsize;
+}
+
 - (NSUInteger)vmaddr;
 {
-    // Implement in subclasses.
-    return 0;
+    return _segmentCommand.vmaddr;
 }
 
 - (NSUInteger)fileoff;
 {
-    // Implement in subclasses.
-    return 0;
+    return _segmentCommand.fileoff;
 }
 
 - (NSUInteger)filesize;
 {
-    // Implement in subclasses.
-    return 0;
+    return _segmentCommand.filesize;
 }
 
 - (vm_prot_t)initprot;
 {
-    // Implement in subclsses.
-    return 0;
+    return _segmentCommand.initprot;
 }
 
 - (uint32_t)flags;
 {
-    // Implement in subclsses.
-    return 0;
+    return _segmentCommand.flags;
 }
 
 - (BOOL)isProtected;
@@ -143,15 +154,14 @@
     if (flags & SG_PROTECTED_VERSION_1) [setFlags addObject:@"PROTECTED_VERSION_1"];
 
     if ([setFlags count] == 0)
-        return @"(none)";
+        return @"none";
 
     return [setFlags componentsJoinedByString:@" "];
 }
 
 - (BOOL)containsAddress:(NSUInteger)address;
 {
-    // Implement in subclasses
-    return NO;
+    return (address >= _segmentCommand.vmaddr) && (address < _segmentCommand.vmaddr + _segmentCommand.vmsize);
 }
 
 - (CDSection *)sectionContainingAddress:(NSUInteger)address;
@@ -188,21 +198,21 @@
 {
     [super appendToString:resultString verbose:isVerbose];
 #if 0
-    [resultString appendFormat:@"  segname %@\n",     self.name];
-    [resultString appendFormat:@"   vmaddr 0x%08x\n", segmentCommand.vmaddr];
-    [resultString appendFormat:@"   vmsize 0x%08x\n", segmentCommand.vmsize];
-    [resultString appendFormat:@"  fileoff %d\n",     segmentCommand.fileoff];
-    [resultString appendFormat:@" filesize %d\n",     segmentCommand.filesize];
-    [resultString appendFormat:@"  maxprot 0x%08x\n", segmentCommand.maxprot];
-    [resultString appendFormat:@" initprot 0x%08x\n", segmentCommand.initprot];
-    [resultString appendFormat:@"   nsects %d\n",     segmentCommand.nsects];
+    int padding = (int)self.machOFile.ptrSize * 2;
+    [resultString appendFormat:@"  segname %@\n",       self.name];
+    [resultString appendFormat:@"   vmaddr 0x%0*llx\n", padding, _segmentCommand.vmaddr];
+    [resultString appendFormat:@"   vmsize 0x%0*llx\n", padding, _segmentCommand.vmsize];
+    [resultString appendFormat:@"  fileoff %lld\n",     _segmentCommand.fileoff];
+    [resultString appendFormat:@" filesize %lld\n",     _segmentCommand.filesize];
+    [resultString appendFormat:@"  maxprot 0x%08x\n",   _segmentCommand.maxprot];
+    [resultString appendFormat:@" initprot 0x%08x\n",   _segmentCommand.initprot];
+    [resultString appendFormat:@"   nsects %d\n",       _segmentCommand.nsects];
 
     if (isVerbose)
         [resultString appendFormat:@"    flags %@\n", [self flagDescription]];
     else
-        [resultString appendFormat:@"    flags 0x%x\n", segmentCommand.flags];
+        [resultString appendFormat:@"    flags 0x%x\n", _segmentCommand.flags];
 #endif
-    // Implement in subclasses
 }
 
 - (void)writeSectionData;
diff --git a/Source/CDLCSegment32.h b/Source/CDLCSegment32.h
deleted file mode 100644
index 450c7e8..0000000
--- a/Source/CDLCSegment32.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// -*- mode: ObjC -*-
-
-//  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
-//  Copyright (C) 1997-1998, 2000-2001, 2004-2014 Steve Nygard.
-
-#import "CDLCSegment.h"
-
-@interface CDLCSegment32 : CDLCSegment
-
-@end
diff --git a/Source/CDLCSegment32.m b/Source/CDLCSegment32.m
deleted file mode 100644
index 641bdfe..0000000
--- a/Source/CDLCSegment32.m
+++ /dev/null
@@ -1,121 +0,0 @@
-// -*- mode: ObjC -*-
-
-//  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
-//  Copyright (C) 1997-1998, 2000-2001, 2004-2014 Steve Nygard.
-
-#import "CDLCSegment32.h"
-
-#import "CDSection32.h"
-
-@implementation CDLCSegment32
-{
-    struct segment_command _segmentCommand;
-}
-
-- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor;
-{
-    if ((self = [super initWithDataCursor:cursor])) {
-        _segmentCommand.cmd     = [cursor readInt32];
-        _segmentCommand.cmdsize = [cursor readInt32];
-        
-        [cursor readBytesOfLength:16 intoBuffer:_segmentCommand.segname];
-        _segmentCommand.vmaddr   = [cursor readInt32];
-        _segmentCommand.vmsize   = [cursor readInt32];
-        _segmentCommand.fileoff  = [cursor readInt32];
-        _segmentCommand.filesize = [cursor readInt32];
-        _segmentCommand.maxprot  = [cursor readInt32];
-        _segmentCommand.initprot = [cursor readInt32];
-        _segmentCommand.nsects   = [cursor readInt32];
-        _segmentCommand.flags    = [cursor readInt32];
-        
-        {
-            char buf[17];
-            
-            memcpy(buf, _segmentCommand.segname, 16);
-            buf[16] = 0;
-            NSString *str = [[NSString alloc] initWithBytes:buf length:strlen(buf) encoding:NSASCIIStringEncoding];
-            [self setName:str];
-        }
-
-        NSMutableArray *_sections = [[NSMutableArray alloc] init];
-        for (NSUInteger index = 0; index < _segmentCommand.nsects; index++) {
-            CDSection32 *section = [[CDSection32 alloc] initWithDataCursor:cursor segment:self];
-            [_sections addObject:section];
-        }
-        self.sections = [_sections copy]; 
-    }
-
-    return self;
-}
-
-#pragma mark -
-
-- (uint32_t)cmd;
-{
-    return _segmentCommand.cmd;
-}
-
-- (uint32_t)cmdsize;
-{
-    return _segmentCommand.cmdsize;
-}
-
-- (NSUInteger)vmaddr;
-{
-    return _segmentCommand.vmaddr;
-}
-
-- (NSUInteger)fileoff;
-{
-    return _segmentCommand.fileoff;
-}
-
-- (NSUInteger)filesize;
-{
-    return _segmentCommand.filesize;
-}
-
-- (vm_prot_t)initprot;
-{
-    return _segmentCommand.initprot;
-}
-
-- (uint32_t)flags;
-{
-    return _segmentCommand.flags;
-}
-
-- (NSString *)extraDescription;
-{
-    return [NSString stringWithFormat:@"vmaddr: 0x%08x - 0x%08x [0x%08x], offset: %d, flags: 0x%x (%@), nsects: %d, sections: %@",
-                     _segmentCommand.vmaddr, _segmentCommand.vmaddr + _segmentCommand.vmsize - 1, _segmentCommand.vmsize, _segmentCommand.fileoff,
-                     self.flags, [self flagDescription], _segmentCommand.nsects, self.sections];
-}
-
-- (BOOL)containsAddress:(NSUInteger)address;
-{
-    return (address >= _segmentCommand.vmaddr) && (address < _segmentCommand.vmaddr + _segmentCommand.vmsize);
-}
-
-- (void)appendToString:(NSMutableString *)resultString verbose:(BOOL)isVerbose;
-{
-    [super appendToString:resultString verbose:isVerbose];
-#if 0
-
-    [resultString appendFormat:@"  segname %@\n",     [self name]];
-    [resultString appendFormat:@"   vmaddr 0x%08x\n", segmentCommand.vmaddr];
-    [resultString appendFormat:@"   vmsize 0x%08x\n", segmentCommand.vmsize];
-    [resultString appendFormat:@"  fileoff %d\n",     segmentCommand.fileoff];
-    [resultString appendFormat:@" filesize %d\n",     segmentCommand.filesize];
-    [resultString appendFormat:@"  maxprot 0x%08x\n", segmentCommand.maxprot];
-    [resultString appendFormat:@" initprot 0x%08x\n", segmentCommand.initprot];
-    [resultString appendFormat:@"   nsects %d\n",     segmentCommand.nsects];
-
-    if (isVerbose)
-        [resultString appendFormat:@"    flags %@\n", [self flagDescription]];
-    else
-        [resultString appendFormat:@"    flags 0x%x\n", segmentCommand.flags];
-#endif
-}
-
-@end
diff --git a/Source/CDLCSegment64.h b/Source/CDLCSegment64.h
deleted file mode 100644
index fb2a013..0000000
--- a/Source/CDLCSegment64.h
+++ /dev/null
@@ -1,10 +0,0 @@
-// -*- mode: ObjC -*-
-
-//  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
-//  Copyright (C) 1997-1998, 2000-2001, 2004-2014 Steve Nygard.
-
-#import "CDLCSegment.h"
-
-@interface CDLCSegment64 : CDLCSegment
-
-@end
diff --git a/Source/CDLCSegment64.m b/Source/CDLCSegment64.m
deleted file mode 100644
index b1fb561..0000000
--- a/Source/CDLCSegment64.m
+++ /dev/null
@@ -1,98 +0,0 @@
-// -*- mode: ObjC -*-
-
-//  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
-//  Copyright (C) 1997-1998, 2000-2001, 2004-2014 Steve Nygard.
-
-#import "CDLCSegment64.h"
-
-#import "CDSection64.h"
-
-@implementation CDLCSegment64
-{
-    struct segment_command_64 _segmentCommand;
-}
-
-- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor;
-{
-    if ((self = [super initWithDataCursor:cursor])) {
-        _segmentCommand.cmd     = [cursor readInt32];
-        _segmentCommand.cmdsize = [cursor readInt32];
-        
-        [cursor readBytesOfLength:16 intoBuffer:_segmentCommand.segname];
-        _segmentCommand.vmaddr   = [cursor readInt64];
-        _segmentCommand.vmsize   = [cursor readInt64];
-        _segmentCommand.fileoff  = [cursor readInt64];
-        _segmentCommand.filesize = [cursor readInt64];
-        _segmentCommand.maxprot  = [cursor readInt32];
-        _segmentCommand.initprot = [cursor readInt32];
-        _segmentCommand.nsects   = [cursor readInt32];
-        _segmentCommand.flags    = [cursor readInt32];
-        
-        {
-            char buf[17];
-            
-            memcpy(buf, _segmentCommand.segname, 16);
-            buf[16] = 0;
-            NSString *str = [[NSString alloc] initWithBytes:buf length:strlen(buf) encoding:NSASCIIStringEncoding];
-            [self setName:str];
-        }
-
-        NSMutableArray *_sections = [[NSMutableArray alloc] init];
-        for (NSUInteger index = 0; index < _segmentCommand.nsects; index++) {
-            CDSection64 *section = [[CDSection64 alloc] initWithDataCursor:cursor segment:self];
-            [_sections addObject:section];
-        }
-        self.sections = [_sections copy]; 
-    }
-
-    return self;
-}
-
-#pragma mark -
-
-- (uint32_t)cmd;
-{
-    return _segmentCommand.cmd;
-}
-
-- (uint32_t)cmdsize;
-{
-    return _segmentCommand.cmdsize;
-}
-
-- (NSUInteger)vmaddr;
-{
-    return _segmentCommand.vmaddr;
-}
-
-- (NSUInteger)fileoff;
-{
-    return _segmentCommand.fileoff;
-}
-
-- (NSUInteger)filesize;
-{
-    return _segmentCommand.filesize;
-}
-
-- (vm_prot_t)initprot;
-{
-    return _segmentCommand.initprot;
-}
-
-- (uint32_t)flags;
-{
-    return _segmentCommand.flags;
-}
-
-- (BOOL)containsAddress:(NSUInteger)address;
-{
-    return (address >= _segmentCommand.vmaddr) && (address < _segmentCommand.vmaddr + _segmentCommand.vmsize);
-}
-
-- (NSString *)extraDescription;
-{
-    return [NSString stringWithFormat:@"addr: 0x%016lx", [self vmaddr]];
-}
-
-@end
diff --git a/Source/CDLoadCommand.m b/Source/CDLoadCommand.m
index 0c81bcf..2e2e634 100644
--- a/Source/CDLoadCommand.m
+++ b/Source/CDLoadCommand.m
@@ -17,8 +17,7 @@
 #import "CDLCRoutines32.h"
 #import "CDLCRoutines64.h"
 #import "CDLCRunPath.h"
-#import "CDLCSegment32.h"
-#import "CDLCSegment64.h"
+#import "CDLCSegment.h"
 #import "CDLCSubClient.h"
 #import "CDLCSubFramework.h"
 #import "CDLCSubLibrary.h"
@@ -48,7 +47,8 @@
     uint32_t val = [cursor peekInt32];
 
     switch (val) {
-        case LC_SEGMENT:               targetClass = [CDLCSegment32 class]; break;
+        case LC_SEGMENT:               targetClass = [CDLCSegment class]; break;
+        case LC_SEGMENT_64:            targetClass = [CDLCSegment class]; break;
         case LC_SYMTAB:                targetClass = [CDLCSymbolTable class]; break;
             //case LC_SYMSEG: // obsolete
             //case LC_THREAD: // not used?
@@ -72,7 +72,6 @@
         case LC_TWOLEVEL_HINTS:        targetClass = [CDLCTwoLevelHints class]; break;
         case LC_PREBIND_CKSUM:         targetClass = [CDLCPrebindChecksum class]; break;
         case LC_LOAD_WEAK_DYLIB:       targetClass = [CDLCDylib class]; break;
-        case LC_SEGMENT_64:            targetClass = [CDLCSegment64 class]; break;
         case LC_ROUTINES_64:           targetClass = [CDLCRoutines64 class]; break;
         case LC_UUID:                  targetClass = [CDLCUUID class]; break;
         case LC_RPATH:                 targetClass = [CDLCRunPath class]; break;
diff --git a/Source/CDMachOFile.m b/Source/CDMachOFile.m
index 350504c..3d6656a 100644
--- a/Source/CDMachOFile.m
+++ b/Source/CDMachOFile.m
@@ -18,7 +18,6 @@
 #import "CDLCEncryptionInfo.h"
 #import "CDLCRunPath.h"
 #import "CDLCSegment.h"
-#import "CDLCSegment64.h"
 #import "CDLCSymbolTable.h"
 #import "CDLCUUID.h"
 #import "CDLCVersionMinimum.h"
diff --git a/Source/CDMachOFileDataCursor.m b/Source/CDMachOFileDataCursor.m
index 7877363..9f1e46e 100644
--- a/Source/CDMachOFileDataCursor.m
+++ b/Source/CDMachOFileDataCursor.m
@@ -6,6 +6,7 @@
 #import "CDMachOFileDataCursor.h"
 
 #import "CDMachOFile.h"
+#import "CDLCSegment.h"
 #import "CDSection.h"
 
 @implementation CDMachOFileDataCursor
@@ -43,7 +44,7 @@
 - (id)initWithSection:(CDSection *)section;
 {
     if ((self = [super initWithData:[section data]])) {
-        self.machOFile = [section machOFile];
+        self.machOFile = section.segment.machOFile;
     }
 
     return self;
diff --git a/Source/CDObjectiveC1Processor.m b/Source/CDObjectiveC1Processor.m
index bc1c4d5..c3df85d 100644
--- a/Source/CDObjectiveC1Processor.m
+++ b/Source/CDObjectiveC1Processor.m
@@ -17,8 +17,6 @@
 #import "CDOCModule.h"
 #import "CDOCProtocol.h"
 #import "CDOCSymtab.h"
-#import "CDSection32.h"
-#import "CDLCSegment32.h"
 #import "CDVisitor.h"
 #import "CDProtocolUniquer.h"
 #import "CDOCClassReference.h"
diff --git a/Source/CDSection.h b/Source/CDSection.h
index d3744d7..785db82 100644
--- a/Source/CDSection.h
+++ b/Source/CDSection.h
@@ -3,24 +3,23 @@
 //  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
 //  Copyright (C) 1997-1998, 2000-2001, 2004-2014 Steve Nygard.
 
-@class CDMachOFile;
+@class CDMachOFileDataCursor;
+@class CDLCSegment;
 
 @interface CDSection : NSObject
 
-@property (retain) NSString *segmentName;
-@property (retain) NSString *sectionName;
+- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor segment:(CDLCSegment *)segment;
 
-@property (nonatomic, strong) NSData *data;
+@property (weak, readonly) CDLCSegment *segment;
 
-@property (assign) BOOL hasLoadedData;
-- (void)loadData;
-- (void)unloadData;
+@property (nonatomic, readonly) NSData *data;
+
+@property (nonatomic, readonly) NSString *segmentName;
+@property (nonatomic, readonly) NSString *sectionName;
 
 @property (nonatomic, readonly) NSUInteger addr;
 @property (nonatomic, readonly) NSUInteger size;
 
-- (CDMachOFile *)machOFile;
-
 - (BOOL)containsAddress:(NSUInteger)address;
 - (NSUInteger)fileOffsetForAddress:(NSUInteger)address;
 
diff --git a/Source/CDSection.m b/Source/CDSection.m
index 1696ead..4630b63 100644
--- a/Source/CDSection.m
+++ b/Source/CDSection.m
@@ -6,78 +6,83 @@
 #import "CDSection.h"
 
 #include <mach-o/loader.h>
-#import "CDFatFile.h"
 #import "CDMachOFile.h"
-#import "CDLCSegment32.h"
+#import "CDMachOFileDataCursor.h"
+#import "CDLCSegment.h"
 
 @implementation CDSection
 {
-    NSString *_segmentName;
-    NSString *_sectionName;
-    
-    NSData *_data;
-    BOOL _hasLoadedData;
+    struct section_64 _section; // 64-bit, also holding 32-bit
 }
 
-#pragma mark - Debugging
+@synthesize data = _data;
 
-- (NSString *)description;
+- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor segment:(CDLCSegment *)segment;
 {
-    return [NSString stringWithFormat:@"<%@:%p> segment; '%@', section: '%-16s'",
-            NSStringFromClass([self class]), self,
-            self.segmentName, [self.sectionName UTF8String]];
+    if ((self = [super init])) {
+        _segment = segment;
+        
+        _sectionName = [cursor readStringOfLength:16 encoding:NSASCIIStringEncoding];
+        memcpy(_section.sectname, [_sectionName UTF8String], sizeof(_section.sectname));
+        _segmentName = [cursor readStringOfLength:16 encoding:NSASCIIStringEncoding];
+        memcpy(_section.segname, [_segmentName UTF8String], sizeof(_section.segname));
+        _section.addr      = [cursor readPtr];
+        _section.size      = [cursor readPtr];
+        _section.offset    = [cursor readInt32];
+        _section.align     = [cursor readInt32];
+        _section.reloff    = [cursor readInt32];
+        _section.nreloc    = [cursor readInt32];
+        _section.flags     = [cursor readInt32];
+        _section.reserved1 = [cursor readInt32];
+        _section.reserved2 = [cursor readInt32];
+        if (cursor.machOFile.uses64BitABI) {
+            _section.reserved3 = [cursor readInt32];
+        }
+    }
+
+    return self;
 }
 
 #pragma mark -
 
 - (NSData *)data;
 {
-    [self loadData];
-
-    return _data;
-}
-
-- (void)loadData;
-{
-    // Impelement in subclasses
-}
-
-- (void)unloadData;
-{
-    if (self.hasLoadedData) {
-        self.hasLoadedData = NO;
-        self.data = nil;
+    if (!_data) {
+        _data = [[NSData alloc] initWithBytes:(uint8_t *)[self.segment.machOFile.data bytes] + _section.offset length:_section.size];
     }
+    return _data;
 }
 
 - (NSUInteger)addr;
 {
-    // Implement in subclasses.
-    return 0;
+    return _section.addr;
 }
 
 - (NSUInteger)size;
 {
-    // Implement in subclasses.
-    return 0;
-}
-
-- (CDMachOFile *)machOFile;
-{
-    // Implement in subclass (for now).
-    return nil;
+    return _section.size;
 }
 
 - (BOOL)containsAddress:(NSUInteger)address;
 {
-    // implement in subclasses.
-    return NO;
+    return (address >= _section.addr) && (address < _section.addr + _section.size);
 }
 
 - (NSUInteger)fileOffsetForAddress:(NSUInteger)address;
 {
-    // implement in subclasses.
-    return 0;
+    NSParameterAssert([self containsAddress:address]);
+    return _section.offset + address - _section.addr;
+}
+
+#pragma mark - Debugging
+
+- (NSString *)description;
+{
+    int padding = (int)self.segment.machOFile.ptrSize * 2;
+    return [NSString stringWithFormat:@"<%@:%p> '%@,%-16s' addr: %0*llx, size: %0*llx",
+            NSStringFromClass([self class]), self,
+            self.segmentName, [self.sectionName UTF8String],
+            padding, _section.addr, padding, _section.size];
 }
 
 @end
diff --git a/Source/CDSection32.h b/Source/CDSection32.h
deleted file mode 100644
index 22a7c15..0000000
--- a/Source/CDSection32.h
+++ /dev/null
@@ -1,17 +0,0 @@
-// -*- mode: ObjC -*-
-
-//  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
-//  Copyright (C) 1997-1998, 2000-2001, 2004-2014 Steve Nygard.
-
-#import "CDSection.h"
-
-@class CDMachOFileDataCursor, CDLCSegment32;
-
-@interface CDSection32 : CDSection
-
-- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor segment:(CDLCSegment32 *)segment;
-
-@property (weak, readonly) CDLCSegment32 *segment;
-@property (nonatomic, readonly) uint32_t offset;
-
-@end
diff --git a/Source/CDSection32.m b/Source/CDSection32.m
deleted file mode 100644
index c13878b..0000000
--- a/Source/CDSection32.m
+++ /dev/null
@@ -1,102 +0,0 @@
-// -*- mode: ObjC -*-
-
-//  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
-//  Copyright (C) 1997-1998, 2000-2001, 2004-2014 Steve Nygard.
-
-#import "CDSection32.h"
-
-#include <mach-o/loader.h>
-#import "CDFatFile.h"
-#import "CDMachOFile.h"
-#import "CDLCSegment32.h"
-
-@implementation CDSection32
-{
-    __weak CDLCSegment32 *_segment;
-    
-    struct section _section;
-}
-
-// Just to resolve multiple different definitions...
-- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor segment:(CDLCSegment32 *)segment;
-{
-    if ((self = [super init])) {
-        _segment = segment;
-        
-        [cursor readBytesOfLength:16 intoBuffer:_section.sectname];
-        [cursor readBytesOfLength:16 intoBuffer:_section.segname];
-        _section.addr      = [cursor readInt32];
-        _section.size      = [cursor readInt32];
-        _section.offset    = [cursor readInt32];
-        _section.align     = [cursor readInt32];
-        _section.reloff    = [cursor readInt32];
-        _section.nreloc    = [cursor readInt32];
-        _section.flags     = [cursor readInt32];
-        _section.reserved1 = [cursor readInt32];
-        _section.reserved2 = [cursor readInt32];
-        
-        // These aren't guaranteed to be null terminated.  Witness __cstring_object in __OBJC segment
-        char buf[17];
-        
-        memcpy(buf, _section.segname, 16);
-        buf[16] = 0;
-        self.segmentName = [[NSString alloc] initWithBytes:buf length:strlen(buf) encoding:NSASCIIStringEncoding];
-        
-        memcpy(buf, _section.sectname, 16);
-        buf[16] = 0;
-        self.sectionName = [[NSString alloc] initWithBytes:buf length:strlen(buf) encoding:NSASCIIStringEncoding];
-    }
-
-    return self;
-}
-
-#pragma mark - Debugging
-
-- (NSString *)description;
-{
-    return [NSString stringWithFormat:@"addr: 0x%08x, offset: %8d, size: %8d [0x%8x], segment; '%@', section: '%@'",
-            _section.addr, _section.offset, _section.size, _section.size, self.segmentName, self.sectionName];
-}
-
-#pragma mark -
-
-- (CDMachOFile *)machOFile;
-{
-    return [self.segment machOFile];
-}
-
-- (NSUInteger)addr;
-{
-    return _section.addr;
-}
-
-- (NSUInteger)size;
-{
-    return _section.size;
-}
-
-- (uint32_t)offset;
-{
-    return _section.offset;
-}
-
-- (void)loadData;
-{
-    if (self.hasLoadedData == NO) {
-        self.data = [[NSData alloc] initWithBytes:(uint8_t *)[self.segment.machOFile.data bytes] + _section.offset length:_section.size];
-        self.hasLoadedData = YES;
-    }
-}
-
-- (BOOL)containsAddress:(NSUInteger)address;
-{
-    return (address >= _section.addr) && (address < _section.addr + _section.size);
-}
-
-- (NSUInteger)fileOffsetForAddress:(NSUInteger)address;
-{
-    NSParameterAssert([self containsAddress:address]);
-    return _section.offset + address - _section.addr;
-}
-
-@end
diff --git a/Source/CDSection64.h b/Source/CDSection64.h
deleted file mode 100644
index 4b97e5e..0000000
--- a/Source/CDSection64.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// -*- mode: ObjC -*-
-
-//  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
-//  Copyright (C) 1997-1998, 2000-2001, 2004-2014 Steve Nygard.
-
-#import "CDSection.h"
-
-@class CDMachOFileDataCursor, CDLCSegment64;
-
-@interface CDSection64 : CDSection
-
-- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor segment:(CDLCSegment64 *)segment;
-
-@property (weak, readonly) CDLCSegment64 *segment;
-
-- (void)loadData;
-
-- (BOOL)containsAddress:(NSUInteger)address;
-- (NSUInteger)fileOffsetForAddress:(NSUInteger)address;
-
-@end
diff --git a/Source/CDSection64.m b/Source/CDSection64.m
deleted file mode 100644
index 3e7e42f..0000000
--- a/Source/CDSection64.m
+++ /dev/null
@@ -1,99 +0,0 @@
-// -*- mode: ObjC -*-
-
-//  This file is part of class-dump, a utility for examining the Objective-C segment of Mach-O files.
-//  Copyright (C) 1997-1998, 2000-2001, 2004-2014 Steve Nygard.
-
-#import "CDSection64.h"
-
-#include <mach-o/loader.h>
-#import "CDMachOFileDataCursor.h"
-#import "CDMachOFile.h"
-#import "CDLCSegment64.h"
-
-@implementation CDSection64
-{
-    __weak CDLCSegment64 *_segment;
-    
-    struct section_64 _section;
-}
-
-- (id)initWithDataCursor:(CDMachOFileDataCursor *)cursor segment:(CDLCSegment64 *)segment;
-{
-    if ((self = [super init])) {
-        _segment = segment;
-        
-        [cursor readBytesOfLength:16 intoBuffer:_section.sectname];
-        [cursor readBytesOfLength:16 intoBuffer:_section.segname];
-        _section.addr      = [cursor readInt64];
-        _section.size      = [cursor readInt64];
-        _section.offset    = [cursor readInt32];
-        _section.align     = [cursor readInt32];
-        _section.reloff    = [cursor readInt32];
-        _section.nreloc    = [cursor readInt32];
-        _section.flags     = [cursor readInt32];
-        _section.reserved1 = [cursor readInt32];
-        _section.reserved2 = [cursor readInt32];
-        _section.reserved3 = [cursor readInt32];
-        
-        // These aren't guaranteed to be null terminated.  Witness __cstring_object in __OBJC segment
-        char buf[17];
-        
-        memcpy(buf, _section.segname, 16);
-        buf[16] = 0;
-        self.segmentName = [[NSString alloc] initWithBytes:buf length:strlen(buf) encoding:NSASCIIStringEncoding];
-        
-        memcpy(buf, _section.sectname, 16);
-        buf[16] = 0;
-        self.sectionName = [[NSString alloc] initWithBytes:buf length:strlen(buf) encoding:NSASCIIStringEncoding];
-    }
-
-    return self;
-}
-
-#pragma mark - Debugging
-
-- (NSString *)description;
-{
-    return [NSString stringWithFormat:@"<%@:%p> segment; '%@', section: '%-16s', addr: %016llx, size: %016llx",
-            NSStringFromClass([self class]), self,
-            self.segmentName, [self.sectionName UTF8String],
-            _section.addr, _section.size];
-}
-
-#pragma mark -
-
-- (CDMachOFile *)machOFile;
-{
-    return [[self segment] machOFile];
-}
-
-- (NSUInteger)addr;
-{
-    return _section.addr;
-}
-
-- (NSUInteger)size;
-{
-    return _section.size;
-}
-
-- (void)loadData;
-{
-    if (self.hasLoadedData == NO) {
-        self.data = [[NSData alloc] initWithBytes:(uint8_t *)[self.segment.machOFile.data bytes] + _section.offset length:_section.size];
-        self.hasLoadedData = YES;
-    }
-}
-
-- (BOOL)containsAddress:(NSUInteger)address;
-{
-    return (address >= _section.addr) && (address < _section.addr + _section.size);
-}
-
-- (NSUInteger)fileOffsetForAddress:(NSUInteger)address;
-{
-    NSParameterAssert([self containsAddress:address]);
-    return _section.offset + address - _section.addr;
-}
-
-@end
diff --git a/class-dump.xcodeproj/project.pbxproj b/class-dump.xcodeproj/project.pbxproj
index 8f886f9..6187b97 100644
--- a/class-dump.xcodeproj/project.pbxproj
+++ b/class-dump.xcodeproj/project.pbxproj
@@ -45,8 +45,6 @@
 		013D1F2A13A5AEA100BF0A67 /* CDLCRoutines64.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82BC13A591D8003EDE60 /* CDLCRoutines64.m */; };
 		013D1F2B13A5AEA100BF0A67 /* CDLCRunPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82BE13A591D8003EDE60 /* CDLCRunPath.m */; };
 		013D1F2C13A5AEA100BF0A67 /* CDLCSegment.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82C013A591D8003EDE60 /* CDLCSegment.m */; };
-		013D1F2D13A5AEA100BF0A67 /* CDLCSegment32.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82C213A591D8003EDE60 /* CDLCSegment32.m */; };
-		013D1F2E13A5AEA100BF0A67 /* CDLCSegment64.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82C413A591D8003EDE60 /* CDLCSegment64.m */; };
 		013D1F2F13A5AEA100BF0A67 /* CDLCSubClient.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82C613A591D8003EDE60 /* CDLCSubClient.m */; };
 		013D1F3013A5AEA100BF0A67 /* CDLCSubFramework.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82C813A591D8003EDE60 /* CDLCSubFramework.m */; };
 		013D1F3113A5AEA100BF0A67 /* CDLCSubLibrary.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82CA13A591D8003EDE60 /* CDLCSubLibrary.m */; };
@@ -63,8 +61,6 @@
 		013D1F3C13A5AEA100BF0A67 /* CDFatArch.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82A213A591D7003EDE60 /* CDFatArch.m */; };
 		013D1F3D13A5AEA100BF0A67 /* CDMachOFile.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82DC13A591D8003EDE60 /* CDMachOFile.m */; };
 		013D1F3E13A5AEA100BF0A67 /* CDSection.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82FE13A591D8003EDE60 /* CDSection.m */; };
-		013D1F3F13A5AEA100BF0A67 /* CDSection32.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB830013A591D8003EDE60 /* CDSection32.m */; };
-		013D1F4013A5AEA100BF0A67 /* CDSection64.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB830213A591D8003EDE60 /* CDSection64.m */; };
 		013D1F4113A5AEA100BF0A67 /* CDSymbol.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB830813A591D8003EDE60 /* CDSymbol.m */; };
 		013D1F4213A5AEA100BF0A67 /* CDRelocationInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82FA13A591D8003EDE60 /* CDRelocationInfo.m */; };
 		013D1F4313A5AEA100BF0A67 /* CDObjectiveCProcessor.m in Sources */ = {isa = PBXBuildFile; fileRef = 01EB82E813A591D8003EDE60 /* CDObjectiveCProcessor.m */; };
@@ -328,10 +324,6 @@
 		01EB82BE13A591D8003EDE60 /* CDLCRunPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDLCRunPath.m; path = Source/CDLCRunPath.m; sourceTree = SOURCE_ROOT; };
 		01EB82BF13A591D8003EDE60 /* CDLCSegment.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDLCSegment.h; path = Source/CDLCSegment.h; sourceTree = SOURCE_ROOT; };
 		01EB82C013A591D8003EDE60 /* CDLCSegment.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDLCSegment.m; path = Source/CDLCSegment.m; sourceTree = SOURCE_ROOT; };
-		01EB82C113A591D8003EDE60 /* CDLCSegment32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDLCSegment32.h; path = Source/CDLCSegment32.h; sourceTree = SOURCE_ROOT; };
-		01EB82C213A591D8003EDE60 /* CDLCSegment32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDLCSegment32.m; path = Source/CDLCSegment32.m; sourceTree = SOURCE_ROOT; };
-		01EB82C313A591D8003EDE60 /* CDLCSegment64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDLCSegment64.h; path = Source/CDLCSegment64.h; sourceTree = SOURCE_ROOT; };
-		01EB82C413A591D8003EDE60 /* CDLCSegment64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDLCSegment64.m; path = Source/CDLCSegment64.m; sourceTree = SOURCE_ROOT; };
 		01EB82C513A591D8003EDE60 /* CDLCSubClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDLCSubClient.h; path = Source/CDLCSubClient.h; sourceTree = SOURCE_ROOT; };
 		01EB82C613A591D8003EDE60 /* CDLCSubClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDLCSubClient.m; path = Source/CDLCSubClient.m; sourceTree = SOURCE_ROOT; };
 		01EB82C713A591D8003EDE60 /* CDLCSubFramework.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDLCSubFramework.h; path = Source/CDLCSubFramework.h; sourceTree = SOURCE_ROOT; };
@@ -390,10 +382,6 @@
 		01EB82FC13A591D8003EDE60 /* CDSearchPathState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDSearchPathState.m; path = Source/CDSearchPathState.m; sourceTree = SOURCE_ROOT; };
 		01EB82FD13A591D8003EDE60 /* CDSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDSection.h; path = Source/CDSection.h; sourceTree = SOURCE_ROOT; };
 		01EB82FE13A591D8003EDE60 /* CDSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDSection.m; path = Source/CDSection.m; sourceTree = SOURCE_ROOT; };
-		01EB82FF13A591D8003EDE60 /* CDSection32.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDSection32.h; path = Source/CDSection32.h; sourceTree = SOURCE_ROOT; };
-		01EB830013A591D8003EDE60 /* CDSection32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDSection32.m; path = Source/CDSection32.m; sourceTree = SOURCE_ROOT; };
-		01EB830113A591D8003EDE60 /* CDSection64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDSection64.h; path = Source/CDSection64.h; sourceTree = SOURCE_ROOT; };
-		01EB830213A591D8003EDE60 /* CDSection64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDSection64.m; path = Source/CDSection64.m; sourceTree = SOURCE_ROOT; };
 		01EB830313A591D8003EDE60 /* CDStructureInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDStructureInfo.h; path = Source/CDStructureInfo.h; sourceTree = SOURCE_ROOT; };
 		01EB830413A591D8003EDE60 /* CDStructureInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CDStructureInfo.m; path = Source/CDStructureInfo.m; sourceTree = SOURCE_ROOT; };
 		01EB830513A591D8003EDE60 /* CDStructureTable.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CDStructureTable.h; path = Source/CDStructureTable.h; sourceTree = SOURCE_ROOT; };
@@ -702,10 +690,6 @@
 				01EB82DC13A591D8003EDE60 /* CDMachOFile.m */,
 				01EB82FD13A591D8003EDE60 /* CDSection.h */,
 				01EB82FE13A591D8003EDE60 /* CDSection.m */,
-				01EB82FF13A591D8003EDE60 /* CDSection32.h */,
-				01EB830013A591D8003EDE60 /* CDSection32.m */,
-				01EB830113A591D8003EDE60 /* CDSection64.h */,
-				01EB830213A591D8003EDE60 /* CDSection64.m */,
 				01EB830713A591D8003EDE60 /* CDSymbol.h */,
 				01EB830813A591D8003EDE60 /* CDSymbol.m */,
 				01EB82F913A591D8003EDE60 /* CDRelocationInfo.h */,
@@ -752,10 +736,6 @@
 				01EB82BE13A591D8003EDE60 /* CDLCRunPath.m */,
 				01EB82BF13A591D8003EDE60 /* CDLCSegment.h */,
 				01EB82C013A591D8003EDE60 /* CDLCSegment.m */,
-				01EB82C113A591D8003EDE60 /* CDLCSegment32.h */,
-				01EB82C213A591D8003EDE60 /* CDLCSegment32.m */,
-				01EB82C313A591D8003EDE60 /* CDLCSegment64.h */,
-				01EB82C413A591D8003EDE60 /* CDLCSegment64.m */,
 				01EB82C513A591D8003EDE60 /* CDLCSubClient.h */,
 				01EB82C613A591D8003EDE60 /* CDLCSubClient.m */,
 				01EB82C713A591D8003EDE60 /* CDLCSubFramework.h */,
@@ -1020,8 +1000,6 @@
 				013D1F2A13A5AEA100BF0A67 /* CDLCRoutines64.m in Sources */,
 				013D1F2B13A5AEA100BF0A67 /* CDLCRunPath.m in Sources */,
 				013D1F2C13A5AEA100BF0A67 /* CDLCSegment.m in Sources */,
-				013D1F2D13A5AEA100BF0A67 /* CDLCSegment32.m in Sources */,
-				013D1F2E13A5AEA100BF0A67 /* CDLCSegment64.m in Sources */,
 				013D1F2F13A5AEA100BF0A67 /* CDLCSubClient.m in Sources */,
 				013D1F3013A5AEA100BF0A67 /* CDLCSubFramework.m in Sources */,
 				013D1F3113A5AEA100BF0A67 /* CDLCSubLibrary.m in Sources */,
@@ -1038,8 +1016,6 @@
 				013D1F3C13A5AEA100BF0A67 /* CDFatArch.m in Sources */,
 				013D1F3D13A5AEA100BF0A67 /* CDMachOFile.m in Sources */,
 				013D1F3E13A5AEA100BF0A67 /* CDSection.m in Sources */,
-				013D1F3F13A5AEA100BF0A67 /* CDSection32.m in Sources */,
-				013D1F4013A5AEA100BF0A67 /* CDSection64.m in Sources */,
 				013D1F4113A5AEA100BF0A67 /* CDSymbol.m in Sources */,
 				013D1F4213A5AEA100BF0A67 /* CDRelocationInfo.m in Sources */,
 				013D1F4313A5AEA100BF0A67 /* CDObjectiveCProcessor.m in Sources */,
diff --git a/deprotect.m b/deprotect.m
index bcf0f22..54eeac5 100644
--- a/deprotect.m
+++ b/deprotect.m
@@ -16,7 +16,6 @@
 #import "CDFatFile.h"
 #import "CDLoadCommand.h"
 #import "CDLCSegment.h"
-#import "CDLCSegment64.h"
 
 void print_usage(void)
 {
@@ -48,7 +47,7 @@
                 NSCParameterAssert([decryptedData length] == segmentRange.length);
                 
                 [mdata replaceBytesInRange:segmentRange withBytes:[decryptedData bytes]];
-                if ([segment isKindOfClass:[CDLCSegment64 class]]) {
+                if (segment.machOFile.uses64BitABI) {
                     flagOffset = [segment commandOffset] + offsetof(struct segment_command_64, flags);
                 } else {
                     flagOffset = [segment commandOffset] + offsetof(struct segment_command, flags);