ruby-macho 0.0.9 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 119afdca4c1793c3bc3f8285c88a8126ab4e1e76
4
- data.tar.gz: 26346fa156b237e2606e8b005c95330bc1b194ad
3
+ metadata.gz: b2197be0a734893a06de0c2a50c78a125e1e0f7b
4
+ data.tar.gz: 6333cb31cc35794f81b35c1e5f5a3e5d8f63d509
5
5
  SHA512:
6
- metadata.gz: 413afe10c917e3e7365711b821904f058d48a9c92a6fcf36d1fecd132b1bbd5971e2d6e547b1684fb46061a328cfaf71afc35788068a1480d33bbde24a0e6d1d
7
- data.tar.gz: cf66bd02bac6b2956bbad64d2f0f82de46e339713ab9ddbfecea88902399f304a58fcb8588294025f647180077f4e054feb40ed85bbeaee941aa00aed26babca
6
+ metadata.gz: 2965997a877ab4c4d675f7e51b8b8ddb7fa82dda776e6b2fe5bb10bcfbf27845809723dc072257076a87c351fe03321839d669dd517ec36e0f57453a7831bef5
7
+ data.tar.gz: 326050eb144d5e9c415dcf58d10fb3da1c565044fae5bb3d1482fe9f15124c64490f95b2e595748b8f567e69db1cc8e5797cf0917c855150ae034bb9094b456c
data/lib/macho.rb CHANGED
@@ -9,6 +9,7 @@ require "#{File.dirname(__FILE__)}/macho/exceptions"
9
9
  require "#{File.dirname(__FILE__)}/macho/utils"
10
10
  require "#{File.dirname(__FILE__)}/macho/tools"
11
11
 
12
+ # The primary namespace for ruby-macho.
12
13
  module MachO
13
14
  # Opens the given filename as a MachOFile or FatFile, depending on its magic.
14
15
  # @param filename [String] the file being opened
@@ -1,59 +1,65 @@
1
1
  module MachO
2
- # generic toplevel error
2
+ # A generic Mach-O error in execution.
3
3
  class MachOError < RuntimeError
4
4
  end
5
5
 
6
- # raised when a file's magic bytes are not valid mach-o magic
6
+ # Raised when a file's magic bytes are not valid Mach-O magic.
7
7
  class MagicError < MachOError
8
+ # @param num [Fixnum] the unknown number
8
9
  def initialize(num)
9
10
  super "Unrecognized Mach-O magic: 0x#{"%02x" % num}"
10
11
  end
11
12
  end
12
13
 
13
- # raised when a fat binary is loaded with MachOFile
14
+ # Raised when a fat binary is loaded with MachOFile.
14
15
  class FatBinaryError < MachOError
15
16
  def initialize
16
17
  super "Fat binaries must be loaded with MachO::FatFile"
17
18
  end
18
19
  end
19
20
 
20
- # raised when a mach-o is loaded with FatFile
21
+ # Raised when a Mach-O is loaded with FatFile.
21
22
  class MachOBinaryError < MachOError
22
23
  def initialize
23
24
  super "Normal binaries must be loaded with MachO::MachOFile"
24
25
  end
25
26
  end
26
27
 
27
- # raised when the CPU type is unknown
28
+ # Raised when the CPU type is unknown.
28
29
  class CPUTypeError < MachOError
30
+ # @param num [Fixnum] the unknown number
29
31
  def initialize(num)
30
32
  super "Unrecognized CPU type: 0x#{"%02x" % num}"
31
33
  end
32
34
  end
33
35
 
34
- # raised when the CPU subtype is unknown
36
+ # Raised when the CPU subtype is unknown.
35
37
  class CPUSubtypeError < MachOError
38
+ # @param num [Fixnum] the unknown number
36
39
  def initialize(num)
37
40
  super "Unrecognized CPU sub-type: 0x#{"%02x" % num}"
38
41
  end
39
42
  end
40
43
 
41
- # raised when a mach-o file's filetype field is unknown
44
+ # Raised when a mach-o file's filetype field is unknown.
42
45
  class FiletypeError < MachOError
46
+ # @param num [Fixnum] the unknown number
43
47
  def initialize(num)
44
48
  super "Unrecognized Mach-O filetype code: 0x#{"%02x" % num}"
45
49
  end
46
50
  end
47
51
 
48
- # raised when an unknown load command is encountered
52
+ # Raised when an unknown load command is encountered.
49
53
  class LoadCommandError < MachOError
54
+ # @param num [Fixnum] the unknown number
50
55
  def initialize(num)
51
56
  super "Unrecognized Mach-O load command: 0x#{"%02x" % num}"
52
57
  end
53
58
  end
54
59
 
55
- # raised when load commands are too large to fit in the current file
60
+ # Raised when load commands are too large to fit in the current file.
56
61
  class HeaderPadError < MachOError
62
+ # @param filename [String] the filename
57
63
  def initialize(filename)
58
64
  super "Updated load commands do not fit in the header of " +
59
65
  "#{filename}. #{filename} needs to be relinked, possibly with " +
@@ -61,8 +67,9 @@ module MachO
61
67
  end
62
68
  end
63
69
 
64
- # raised when attempting to change a dylib name that doesn't exist
70
+ # Raised when attempting to change a dylib name that doesn't exist.
65
71
  class DylibUnknownError < MachOError
72
+ # @param dylib [String] the unknown shared library name
66
73
  def initialize(dylib)
67
74
  super "No such dylib name: #{dylib}"
68
75
  end
@@ -105,7 +105,7 @@ module MachO
105
105
  end
106
106
 
107
107
  # Write all (fat) data to the file used to initialize the instance.
108
- # IMPORTANT: Overwrites all data in the file!
108
+ # @note Overwrites all data in the file!
109
109
  def write!
110
110
  File.open(@filename, "wb") { |f| f.write(@raw_data) }
111
111
  end
@@ -158,6 +158,7 @@ module MachO
158
158
 
159
159
  # @todo this needs to be redesigned. arch[:offset] and arch[:size] are
160
160
  # already out-of-date, and the header needs to be synchronized as well.
161
+ # @private
161
162
  def synchronize_raw_data
162
163
  machos.each_with_index do |macho, i|
163
164
  arch = fat_archs[i]
data/lib/macho/headers.rb CHANGED
@@ -1,12 +1,23 @@
1
1
  module MachO
2
- # magic numbers used in Mach-O files
3
- FAT_MAGIC = 0xcafebabe # big-endian fat magic
4
- FAT_CIGAM = 0xbebafeca # little-endian fat magic
5
- MH_MAGIC = 0xfeedface # 32-bit big-endian magic
6
- MH_CIGAM = 0xcefaedfe # 32-bit little-endian magic
7
- MH_MAGIC_64 = 0xfeedfacf # 64-bit big-endian magic
8
- MH_CIGAM_64 = 0xcffaedfe # 64-bit little-endian magic
2
+ # big-endian fat magic
3
+ FAT_MAGIC = 0xcafebabe
9
4
 
5
+ # little-endian fat magic
6
+ FAT_CIGAM = 0xbebafeca
7
+
8
+ # 32-bit big-endian magic
9
+ MH_MAGIC = 0xfeedface
10
+
11
+ # 32-bit little-endian magic
12
+ MH_CIGAM = 0xcefaedfe
13
+
14
+ # 64-bit big-endian magic
15
+ MH_MAGIC_64 = 0xfeedfacf
16
+
17
+ # 64-bit little-endian magic
18
+ MH_CIGAM_64 = 0xcffaedfe
19
+
20
+ # association of magic numbers to string representations
10
21
  MH_MAGICS = {
11
22
  FAT_MAGIC => "FAT_MAGIC",
12
23
  FAT_CIGAM => "FAT_CIGAM",
@@ -16,18 +27,28 @@ module MachO
16
27
  MH_CIGAM_64 => "MH_CIGAM_64"
17
28
  }
18
29
 
19
- # capability bits used in the definition of cputype
20
- CPU_ARCH_MASK = 0xff000000
30
+ # mask for CPUs with 64-bit architectures (when running a 64-bit ABI?)
21
31
  CPU_ARCH_ABI64 = 0x01000000
22
32
 
23
- # (select) values for cputype in MachHeader/MachHeader64
33
+ # any CPU (unused?)
24
34
  CPU_TYPE_ANY = -1
35
+
36
+ # x86 compatible CPUs
25
37
  CPU_TYPE_X86 = 0x07
38
+
39
+ # i386 and later compatible CPUs
26
40
  CPU_TYPE_I386 = CPU_TYPE_X86
41
+
42
+ # x86_64 (AMD64) compatible CPUs
27
43
  CPU_TYPE_X86_64 = (CPU_TYPE_X86 | CPU_ARCH_ABI64)
44
+
45
+ # PowerPC compatible CPUs (7400 series?)
28
46
  CPU_TYPE_POWERPC = 0x24
47
+
48
+ # PowerPC64 compatible CPUs (970 series?)
29
49
  CPU_TYPE_POWERPC64 = (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
30
50
 
51
+ # association of cpu types to string representations
31
52
  CPU_TYPES = {
32
53
  CPU_TYPE_ANY => "CPU_TYPE_ANY",
33
54
  CPU_TYPE_X86 => "CPU_TYPE_X86",
@@ -37,34 +58,59 @@ module MachO
37
58
  CPU_TYPE_POWERPC64 => "CPU_TYPE_POWERPC64"
38
59
  }
39
60
 
40
- # capability bits used in the definition of cpusubtype
41
- # http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
61
+ # mask for CPU subtype capabilities
42
62
  CPU_SUBTYPE_MASK = 0xff000000
63
+
64
+ # 64-bit libraries (undocumented!)
65
+ # @see http://llvm.org/docs/doxygen/html/Support_2MachO_8h_source.html
43
66
  CPU_SUBTYPE_LIB64 = 0x80000000
44
67
 
45
- # (select) cpusubtypes
68
+ # all x86-type CPUs
46
69
  CPU_SUBTYPE_X86_ALL = 3
70
+
71
+ # all x86-type CPUs (what makes this different from CPU_SUBTYPE_X86_ALL?)
47
72
  CPU_SUBTYPE_X86_ARCH1 = 4
48
73
 
74
+ # association of cpu subtypes to string representations
49
75
  CPU_SUBTYPES = {
50
76
  CPU_SUBTYPE_X86_ALL => "CPU_SUBTYPE_X86_ALL",
51
77
  CPU_SUBTYPE_X86_ARCH1 => "CPU_SUBTYPE_X86_ARCH1"
52
78
  }
53
79
 
54
- # values for filetype in MachHeader/MachHeader64
55
- MH_OBJECT = 0x1 # relocatable object file
56
- MH_EXECUTE = 0x2 # demand paged executable file
57
- MH_FVMLIB = 0x3 # fixed VM shared library file
58
- MH_CORE = 0x4 # core file
59
- MH_PRELOAD = 0x5 # preloaded executable file
60
- MH_DYLIB = 0x6 # dynamically bound shared library
61
- MH_DYLINKER = 0x7 # dynamic link editor
62
- MH_BUNDLE = 0x8 # dynamically bound bundle file
63
- MH_DYLIB_STUB = 0x9 # shared library stub for static linking only no,
64
- # section contents
65
- MH_DSYM = 0xa # companion file with only debug sections
66
- MH_KEXT_BUNDLE = 0xb # x86_64 lexts
80
+ # relocatable object file
81
+ MH_OBJECT = 0x1
67
82
 
83
+ # demand paged executable file
84
+ MH_EXECUTE = 0x2
85
+
86
+ # fixed VM shared library file
87
+ MH_FVMLIB = 0x3
88
+
89
+ # core dump file
90
+ MH_CORE = 0x4
91
+
92
+ # preloaded executable file
93
+ MH_PRELOAD = 0x5
94
+
95
+ # dynamically bound shared library
96
+ MH_DYLIB = 0x6
97
+
98
+ # dynamic link editor
99
+ MH_DYLINKER = 0x7
100
+
101
+ # dynamically bound bundle file
102
+ MH_BUNDLE = 0x8
103
+
104
+ # shared library stub for static linking only, no section contents
105
+ MH_DYLIB_STUB = 0x9
106
+
107
+ # companion file with only debug sections
108
+ MH_DSYM = 0xa
109
+
110
+ # x86_64 kexts
111
+ MH_KEXT_BUNDLE = 0xb
112
+
113
+ # association of filetypes to string representations
68
114
  MH_FILETYPES = {
69
115
  MH_OBJECT => "MH_OBJECT",
70
116
  MH_EXECUTE => "MH_EXECUTE",
@@ -79,34 +125,85 @@ module MachO
79
125
  MH_KEXT_BUNDLE => "MH_KEXT_BUNDLE"
80
126
  }
81
127
 
82
- # values for flags field in MachHeader/MachHeader64
128
+ # the object file has no undefined references (flag)
83
129
  MH_NOUNDEFS = 0x1
130
+
131
+ # the object file is the output of an incremental link against a base file (flag)
84
132
  MH_INCRLINK = 0x2
133
+
134
+ # the object file is input for the dynamic linker and can't be staticly link edited again (flag)
85
135
  MH_DYLDLINK = 0x4
136
+
137
+ # the object file's undefined references are bound by the dynamic linker when loaded (flag)
86
138
  MH_BINDATLOAD = 0x8
139
+
140
+ # the file has its dynamic undefined references prebound (flag)
87
141
  MH_PREBOUND = 0x10
142
+
143
+ # the file has its read-only and read-write segments split (flag)
88
144
  MH_SPLIT_SEGS = 0x20
145
+
146
+ # the shared library init routine is to be run lazily via catching memory faults to its writeable segments (obsolete) (flag)
89
147
  MH_LAZY_INIT = 0x40
148
+
149
+ # the image is using two-level name space bindings (flag)
90
150
  MH_TWOLEVEL = 0x80
151
+
152
+ # the executable is forcing all images to use flat name space bindings (flag)
91
153
  MH_FORCE_FLAT = 0x100
154
+
155
+ # this umbrella guarantees no multiple defintions of symbols in its sub-images so the two-level namespace hints can always be used (flag)
92
156
  MH_NOMULTIDEFS = 0x200
157
+
158
+ # do not have dyld notify the prebinding agent about this executable (flag)
93
159
  MH_NOPREFIXBINDING = 0x400
160
+
161
+ # the binary is not prebound but can have its prebinding redone. only used when MH_PREBOUND is not set (flag)
94
162
  MH_PREBINDABLE = 0x800
163
+
164
+ # indicates that this binary binds to all two-level namespace modules of its dependent libraries. only used when MH_PREBINDABLE and MH_TWOLEVEL are both set (flag)
95
165
  MH_ALLMODSBOUND = 0x1000
166
+
167
+ # safe to divide up the sections into sub-sections via symbols for dead code stripping (flag)
96
168
  MH_SUBSECTIONS_VIA_SYMBOLS = 0x2000
169
+
170
+ # the binary has been canonicalized via the unprebind operation (flag)
97
171
  MH_CANONICAL = 0x4000
172
+
173
+ # the final linked image contains external weak symbols (flag)
98
174
  MH_WEAK_DEFINES = 0x8000
175
+
176
+ # the final linked image uses weak symbols (flag)
99
177
  MH_BINDS_TO_WEAK = 0x10000
178
+
179
+ # When this bit is set, all stacks in the task will be given stack execution privilege. Only used in MH_EXECUTE filetypes (flag)
100
180
  MH_ALLOW_STACK_EXECUTION = 0x20000
181
+
182
+ # When this bit is set, the binary declares it is safe for use in processes with uid zero (flag)
101
183
  MH_ROOT_SAFE = 0x40000
184
+
185
+ # When this bit is set, the binary declares it is safe for use in processes when issetugid() is true (flag)
102
186
  MH_SETUID_SAFE = 0x80000
187
+
188
+ # When this bit is set on a dylib, the static linker does not need to examine dependent dylibs to see if any are re-exported (flag)
103
189
  MH_NO_REEXPORTED_DYLIBS = 0x100000
190
+
191
+ # When this bit is set, the OS will load the main executable at a random address. Only used in MH_EXECUTE filetypes (flag)
104
192
  MH_PIE = 0x200000
193
+
194
+ # Only for use on dylibs. When linking against a dylib that has this bit set, the static linker will automatically not create a LC_LOAD_DYLIB load command to the dylib if no symbols are being referenced from the dylib (flag)
105
195
  MH_DEAD_STRIPPABLE_DYLIB = 0x400000
196
+
197
+ # Contains a section of type S_THREAD_LOCAL_VARIABLES (flag)
106
198
  MH_HAS_TLV_DESCRIPTORS = 0x800000
199
+
200
+ # When this bit is set, the OS will run the main executable with a non-executable heap even on platforms (e.g. i386) that don't require it. Only used in MH_EXECUTE filetypes (flag)
107
201
  MH_NO_HEAP_EXECUTION = 0x1000000
202
+
203
+ # The code was linked for use in an application extension (flag)
108
204
  MH_APP_EXTENSION_SAFE = 0x02000000
109
205
 
206
+ # association of mach header flags to string representations
110
207
  MH_FLAGS = {
111
208
  MH_NOUNDEFS => "MH_NOUNDEFS",
112
209
  MH_INCRLINK => "MH_INCRLINK",
@@ -136,7 +233,6 @@ module MachO
136
233
  MH_APP_EXTENSION_SAFE => "MH_APP_EXTENSION_SAFE"
137
234
  }
138
235
 
139
- # 'Fat' binaries envelop Mach-O binaries so include them for completeness,
140
236
  # Fat binary header structure
141
237
  class FatHeader < CStruct
142
238
  uint32 :magic
@@ -162,6 +258,10 @@ module MachO
162
258
  uint32 :sizeofcmds
163
259
  uint32 :flags
164
260
 
261
+ # @example
262
+ # puts "this mach-o has position-independent execution" if header.flag?(MH_PIE)
263
+ # @param flag [Fixnum] a mach header flag constant
264
+ # @return [Boolean] true if `flag` is present in the header's flag section
165
265
  def flag?(flag)
166
266
  flags & flag == flag
167
267
  end
@@ -178,6 +278,10 @@ module MachO
178
278
  uint32 :flags
179
279
  uint32 :reserved
180
280
 
281
+ # @example
282
+ # puts "this mach-o has position-independent execution" if header.flag?(MH_PIE)
283
+ # @param flag [Fixnum] a mach header flag constant
284
+ # @return [Boolean] true if `flag` is present in the header's flag section
181
285
  def flag?(flag)
182
286
  flags & flag == flag
183
287
  end
@@ -3,55 +3,148 @@ module MachO
3
3
  # LC_REQ_DYLD to be recognized by the dynamic linder (dyld)
4
4
  LC_REQ_DYLD = 0x80000000
5
5
 
6
- # values for cmd in LoadCommand
6
+ # segment of this file to be mapped
7
7
  LC_SEGMENT = 0x1
8
+
9
+ # link-edit stab symbol table info
8
10
  LC_SYMTAB = 0x2
11
+
12
+ # link-edit gdb symbol table info (obsolete)
9
13
  LC_SYMSEG = 0x3
14
+
15
+ # thread
10
16
  LC_THREAD = 0x4
17
+
18
+ # unix thread (includes a stack)
11
19
  LC_UNIXTHREAD = 0x5
20
+
21
+ # load a specified fixed VM shared library
12
22
  LC_LOADFVMLIB = 0x6
23
+
24
+ # fixed VM shared library identification
13
25
  LC_IDFVMLIB = 0x7
26
+
27
+ # object identification info (obsolete)
14
28
  LC_IDENT = 0x8
29
+
30
+ # fixed VM file inclusion (internal use)
15
31
  LC_FVMFILE = 0x9
32
+
33
+ # prepage command (internal use)
16
34
  LC_PREPAGE = 0xa
35
+
36
+ # dynamic link-edit symbol table info
17
37
  LC_DYSYMTAB = 0xb
38
+
39
+ # load a dynamically linked shared library
18
40
  LC_LOAD_DYLIB = 0xc
41
+
42
+ # dynamically linked shared lib ident
19
43
  LC_ID_DYLIB = 0xd
44
+
45
+ # load a dynamic linker
20
46
  LC_LOAD_DYLINKER = 0xe
47
+
48
+ # dynamic linker identification
21
49
  LC_ID_DYLINKER = 0xf
50
+
51
+ # modules prebound for a dynamically linked shared library
22
52
  LC_PREBOUND_DYLIB = 0x10
53
+
54
+ # image routines
23
55
  LC_ROUTINES = 0x11
56
+
57
+ # sub framework
24
58
  LC_SUB_FRAMEWORK = 0x12
59
+
60
+ # sub umbrella
25
61
  LC_SUB_UMBRELLA = 0x13
62
+
63
+ # sub umbrella
26
64
  LC_SUB_CLIENT = 0x14
65
+
66
+ # sub umbrella
27
67
  LC_SUB_LIBRARY = 0x15
68
+
69
+ # two-level namespace lookup hints
28
70
  LC_TWOLEVEL_HINTS = 0x16
71
+
72
+ # prebind checksum
29
73
  LC_PREBIND_CKSUM = 0x17
74
+
75
+ # load a dynamically linked shared library that is allowed to be missing (all symbols are weak imported).
30
76
  LC_LOAD_WEAK_DYLIB = (0x18 | LC_REQ_DYLD)
77
+
78
+ # 64-bit segment of this file to be mapped
31
79
  LC_SEGMENT_64 = 0x19
80
+
81
+ # 64-bit image routines
32
82
  LC_ROUTINES_64 = 0x1a
83
+
84
+ # the uuid
33
85
  LC_UUID = 0x1b
86
+
87
+ # runpath additions
34
88
  LC_RPATH = (0x1c | LC_REQ_DYLD)
89
+
90
+ # local of code signature
35
91
  LC_CODE_SIGNATURE = 0x1d
92
+
93
+ # local of info to split segments
36
94
  LC_SEGMENT_SPLIT_INFO = 0x1e
95
+
96
+ # load and re-export dylib
37
97
  LC_REEXPORT_DYLIB = (0x1f | LC_REQ_DYLD)
98
+
99
+ # delay load of dylib until first use
38
100
  LC_LAZY_LOAD_DYLIB = 0x20
101
+
102
+ # encrypted segment information
39
103
  LC_ENCRYPTION_INFO = 0x21
104
+
105
+ # compressed dyld information
40
106
  LC_DYLD_INFO = 0x22
107
+
108
+ # compressed dyld information only
41
109
  LC_DYLD_INFO_ONLY = (0x22 | LC_REQ_DYLD)
110
+
111
+ # load upward dylib
42
112
  LC_LOAD_UPWARD_DYLIB = (0x23 | LC_REQ_DYLD)
113
+
114
+ # build for MacOSX min OS version
43
115
  LC_VERSION_MIN_MACOSX = 0x24
116
+
117
+ # build for iPhoneOS min OS version
44
118
  LC_VERSION_MIN_IPHONEOS = 0x25
119
+
120
+ # compressed table of function start addresses
45
121
  LC_FUNCTION_STARTS = 0x26
122
+
123
+ # string for dyld to treat like environment variable
46
124
  LC_DYLD_ENVIRONMENT = 0x27
125
+
126
+ # replacement for LC_UNIXTHREAD
47
127
  LC_MAIN = (0x28 | LC_REQ_DYLD)
128
+
129
+ # table of non-instructions in __text
48
130
  LC_DATA_IN_CODE = 0x29
131
+
132
+ # source version used to build binary
49
133
  LC_SOURCE_VERSION = 0x2a
134
+
135
+ # Code signing DRs copied from linked dylibs
50
136
  LC_DYLIB_CODE_SIGN_DRS = 0x2b
137
+
138
+ # 64-bit encrypted segment information
51
139
  LC_ENCRYPTION_INFO_64 = 0x2c
140
+
141
+ # linker options in MH_OBJECT files
52
142
  LC_LINKER_OPTION = 0x2d
143
+
144
+ # linker options in MH_OBJECT files
53
145
  LC_LINKER_OPTIMIZATION_HINT = 0x2e
54
146
 
147
+ # association of load commands to string representations
55
148
  LOAD_COMMANDS = {
56
149
  LC_SEGMENT => "LC_SEGMENT",
57
150
  LC_SYMTAB => "LC_SYMTAB",
@@ -102,6 +195,7 @@ module MachO
102
195
  LC_LINKER_OPTIMIZATION_HINT => "LC_LINKER_OPTIMIZATION_HINT"
103
196
  }
104
197
 
198
+ # association of load commands to string representations of class names
105
199
  LC_STRUCTURES = {
106
200
  LC_SEGMENT => "SegmentCommand",
107
201
  LC_SYMTAB => "SymtabCommand",
@@ -152,60 +246,102 @@ module MachO
152
246
  LC_LINKER_OPTIMIZATION_HINT => "LinkeditDataCommand"
153
247
  }
154
248
 
155
- # currently known segment names
156
- # we don't use these anywhere right now, but they're good to have
249
+ # pagezero segment name
157
250
  SEG_PAGEZERO = "__PAGEZERO"
251
+
252
+ # text segment name
158
253
  SEG_TEXT = "__TEXT"
254
+
255
+ # data segment name
159
256
  SEG_DATA = "__DATA"
257
+
258
+ # objective-c runtime segment
160
259
  SEG_OBJC = "__OBJC"
260
+
261
+ # icon segment
161
262
  SEG_ICON = "__ICON"
263
+
264
+ # link editor structures segment
162
265
  SEG_LINKEDIT = "__LINKEDIT"
266
+
267
+ # unix stack segment
163
268
  SEG_UNIXSTACK = "__UNIXSTACK"
269
+
270
+ # segment for self-modifying code with RWX permissions
164
271
  SEG_IMPORT = "__IMPORT"
165
272
 
166
- # constant bits for flags in SegmentCommand, SegmentCommand64
273
+ # the file contents for this segment is for the high part of the VM space, the low part is zero filled (for stacks in core files)
167
274
  SG_HIGHVM = 0x1
275
+
276
+ # this segment is the VM that is allocated by a fixed VM library, for overlap checking in the link editor
168
277
  SG_FVMLIB = 0x2
278
+
279
+ # this segment has nothing that was relocated in it and nothing relocated to it, that is it maybe safely replaced without relocation
169
280
  SG_NORELOC = 0x4
281
+
282
+ # this segment is protected. if the segment starts at file offset 0, the first page of the segment is not protected. all other pages of the segment are protected.
170
283
  SG_PROTECTED_VERSION_1 = 0x8
171
284
 
172
285
  # Mach-O load command structure
173
- # this is the most generic load command - only cmd ID and size are
174
- # represented, and no actual data. used when a more specific class
175
- # isn't available/implemented
286
+ # This is the most generic load command - only cmd ID and size are
287
+ # represented, and no actual data. Used when a more specific class
288
+ # isn't available/implemented.
176
289
  class LoadCommand < MachOStructure
177
- attr_reader :offset, :cmd, :cmdsize
290
+ # @return [Fixnum] the offset in the file the command was created from
291
+ attr_reader :offset
292
+
293
+ # @return [Fixnum] the load command's identifying number
294
+ attr_reader :cmd
295
+
296
+ # @return [Fixnum] the size of the load command, in bytes
297
+ attr_reader :cmdsize
178
298
 
179
299
  @format = "VV"
180
300
  @sizeof = 8
181
301
 
302
+ # Creates a new LoadCommand given an offset and binary string
303
+ # @param offset [Fixnum] the offset to initialize with
304
+ # @param bin [String] the binary string to initialize with
305
+ # @return [MachO::LoadCommand] the new load command
306
+ # @private
182
307
  def self.new_from_bin(offset, bin)
183
308
  self.new(offset, *bin.unpack(@format))
184
309
  end
185
310
 
311
+ # @param offset [Fixnum] the offset to initialize iwth
312
+ # @param cmd [Fixnum] the load command's identifying number
313
+ # @param cmdsize [Fixnum] the size of the load command in bytes
314
+ # @private
186
315
  def initialize(offset, cmd, cmdsize)
187
316
  @offset = offset
188
317
  @cmd = cmd
189
318
  @cmdsize = cmdsize
190
319
  end
191
320
 
321
+ # @return [String] a string representation of the load command's identifying number
192
322
  def to_s
193
323
  LOAD_COMMANDS[cmd]
194
324
  end
195
325
  end
196
326
 
327
+ # A load command containing a single 128-bit unique random number identifying
328
+ # an object produced by static link editor. Corresponds to LC_UUID.
197
329
  class UUIDCommand < LoadCommand
330
+ # @return [Array<Fixnum>] the UUID
198
331
  attr_reader :uuid
199
332
 
200
333
  @format = "VVa16"
201
334
  @sizeof = 24
202
335
 
336
+ # @private
203
337
  def initialize(offset, cmd, cmdsize, uuid)
204
338
  super(offset, cmd, cmdsize)
205
339
  @uuid = uuid.unpack("C16") # re-unpack for the actual UUID array
206
340
  end
207
341
  end
208
342
 
343
+ # A load command indicating that part of this file is to be mapped into
344
+ # the task's address space. Corresponds to LC_SEGMENT.
209
345
  class SegmentCommand < LoadCommand
210
346
  attr_reader :segname, :vmaddr, :vmsize, :fileoff, :filesize, :maxprot
211
347
  attr_reader :initprot, :nsects, :flags
@@ -213,6 +349,7 @@ module MachO
213
349
  @format = "VVa16VVVVVVVV"
214
350
  @sizeof = 56
215
351
 
352
+ # @private
216
353
  def initialize(offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
217
354
  filesize, maxprot, initprot, nsects, flags)
218
355
  super(offset, cmd, cmdsize)
@@ -227,11 +364,14 @@ module MachO
227
364
  @flags = flags
228
365
  end
229
366
 
367
+ # @return [String] the segment's name, with any trailing NULL characters removed
230
368
  def segment_name
231
369
  @segname.delete("\x00")
232
370
  end
233
371
  end
234
372
 
373
+ # A load command indicating that part of this file is to be mapped into
374
+ # the task's address space. Corresponds to LC_SEGMENT_64.
235
375
  class SegmentCommand64 < LoadCommand
236
376
  attr_reader :segname, :vmaddr, :vmsize, :fileoff, :filesize, :maxprot
237
377
  attr_reader :initprot, :nsects, :flags
@@ -239,6 +379,7 @@ module MachO
239
379
  @format = "VVa16QQQQVVVV"
240
380
  @sizeof = 72
241
381
 
382
+ # @private
242
383
  def initialize(offset, cmd, cmdsize, segname, vmaddr, vmsize, fileoff,
243
384
  filesize, maxprot, initprot, nsects, flags)
244
385
  super(offset, cmd, cmdsize)
@@ -253,17 +394,22 @@ module MachO
253
394
  @flags = flags
254
395
  end
255
396
 
397
+ # @return [String] the segment's name, with any trailing NULL characters removed
256
398
  def segment_name
257
399
  @segname.delete("\x00")
258
400
  end
259
401
  end
260
402
 
403
+ # A load command representing some aspect of shared libraries, depending
404
+ # on filetype. Corresponds to LC_ID_DYLIB, LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB,
405
+ # and LC_REEXPORT_DYLIB.
261
406
  class DylibCommand < LoadCommand
262
407
  attr_reader :name, :timestamp, :current_version, :compatibility_version
263
408
 
264
409
  @format = "VVVVVV"
265
410
  @sizeof = 24
266
411
 
412
+ # @private
267
413
  def initialize(offset, cmd, cmdsize, name, timestamp, current_version,
268
414
  compatibility_version)
269
415
  super(offset, cmd, cmdsize)
@@ -274,24 +420,31 @@ module MachO
274
420
  end
275
421
  end
276
422
 
423
+ # A load command representing some aspect of the dynamic linker, depending
424
+ # on filetype. Corresponds to LC_ID_DYLINKER, LC_LOAD_DYLINKER, and
425
+ # LC_DYLD_ENVIRONMENT.
277
426
  class DylinkerCommand < LoadCommand
278
427
  attr_reader :name
279
428
 
280
429
  @format = "VVV"
281
430
  @sizeof = 12
282
431
 
432
+ # @private
283
433
  def initialize(offset, cmd, cmdsize, name)
284
434
  super(offset, cmd, cmdsize)
285
435
  @name = name
286
436
  end
287
437
  end
288
438
 
439
+ # A load command used to indicate dynamic libraries used in prebinding.
440
+ # Corresponds to LC_PREBOUND_DYLIB.
289
441
  class PreboundDylibCommand < LoadCommand
290
442
  attr_reader :name, :nmodules, :linked_modules
291
443
 
292
444
  @format = "VVVVV"
293
445
  @sizeof = 20
294
446
 
447
+ # @private
295
448
  def initialize(offset, cmd, cmdsize, name, nmodules, linked_modules)
296
449
  super(offset, cmd, cmdsize)
297
450
  @name = name
@@ -300,12 +453,15 @@ module MachO
300
453
  end
301
454
  end
302
455
 
303
- # NOTE: cctools-870 has all fields of thread_command commented out
304
- # except common ones (cmd, cmdsize)
456
+ # A load command used to represent threads.
457
+ # @note cctools-870 has all fields of thread_command commented out except common ones (cmd, cmdsize)
305
458
  class ThreadCommand < LoadCommand
306
459
 
307
460
  end
308
461
 
462
+ # A load command containing the address of the dynamic shared library
463
+ # initialization routine and an index into the module table for the module
464
+ # that defines the routine. Corresponds to LC_ROUTINES.
309
465
  class RoutinesCommand < LoadCommand
310
466
  attr_reader :init_address, :init_module, :reserved1, :reserved2
311
467
  attr_reader :reserved3, :reserved4, :reserved5, :reserved6
@@ -313,6 +469,7 @@ module MachO
313
469
  @format = "VVVVVVVVVV"
314
470
  @sizeof = 40
315
471
 
472
+ # @private
316
473
  def initialize(offset, cmd, cmdsize, init_address, init_module,
317
474
  reserved1, reserved2, reserved3, reserved4, reserved5,
318
475
  reserved6)
@@ -328,6 +485,9 @@ module MachO
328
485
  end
329
486
  end
330
487
 
488
+ # A load command containing the address of the dynamic shared library
489
+ # initialization routine and an index into the module table for the module
490
+ # that defines the routine. Corresponds to LC_ROUTINES_64.
331
491
  class RoutinesCommand64 < LoadCommand
332
492
  attr_reader :init_address, :init_module, :reserved1, :reserved2
333
493
  attr_reader :reserved3, :reserved4, :reserved5, :reserved6
@@ -335,6 +495,7 @@ module MachO
335
495
  @format = "VVQQQQQQQQ"
336
496
  @sizeof = 72
337
497
 
498
+ # @private
338
499
  def initialize(offset, cmd, cmdsize, init_address, init_module,
339
500
  reserved1, reserved2, reserved3, reserved4, reserved5,
340
501
  reserved6)
@@ -350,60 +511,85 @@ module MachO
350
511
  end
351
512
  end
352
513
 
514
+ # A load command signifying membership of a subframework containing the name
515
+ # of an umbrella framework. Corresponds to LC_SUB_FRAMEWORK.
353
516
  class SubFrameworkCommand < LoadCommand
354
517
  attr_reader :umbrella
355
518
 
356
519
  @format = "VVV"
357
520
  @sizeof = 12
358
521
 
522
+ # @private
359
523
  def initialize(offset, cmd, cmdsize, umbrella)
360
524
  super(offset, cmd, cmdsize)
361
525
  @umbrella = umbrella
362
526
  end
363
527
  end
364
528
 
529
+ # A load command signifying membership of a subumbrella containing the name
530
+ # of an umbrella framework. Corresponds to LC_SUB_UMBRELLA.
365
531
  class SubUmbrellaCommand < LoadCommand
366
532
  attr_reader :sub_umbrella
367
533
 
368
534
  @format = "VVV"
369
535
  @sizeof = 12
370
536
 
537
+ # @private
371
538
  def initialize(offset, cmd, cmdsize, sub_umbrella)
372
539
  super(offset, cmd, cmdsize)
373
540
  @sub_umbrella = sub_umbrella
374
541
  end
375
542
  end
376
543
 
544
+ # A load command signifying a sublibrary of a shared library. Corresponds
545
+ # to LC_SUB_LIBRARY.
377
546
  class SubLibraryCommand < LoadCommand
378
547
  attr_reader :sub_library
379
548
 
380
549
  @format = "VVV"
381
550
  @sizeof = 12
382
551
 
552
+ # @private
383
553
  def initialize(offset, cmd, cmdsize, sub_library)
384
554
  super(offset, cmd, cmdsize)
385
555
  @sub_library = sub_library
386
556
  end
387
557
  end
388
558
 
559
+ # A load command signifying a shared library that is a subframework of
560
+ # an umbrella framework. Corresponds to LC_SUB_CLIENT.
389
561
  class SubClientCommand < LoadCommand
390
562
  attr_reader :sub_client
391
563
 
392
564
  @format = "VVV"
393
565
  @sizeof = 12
394
566
 
567
+ # @private
395
568
  def initialize(offset, cmd, cmdsize, sub_client)
396
569
  super(offset, cmd, cmdsize)
397
570
  @sub_client = sub_client
398
571
  end
399
572
  end
400
573
 
574
+ # A load command containing the offsets and sizes of the link-edit 4.3BSD
575
+ # "stab" style symbol table information. Corresponds to LC_SYMTAB.
401
576
  class SymtabCommand < LoadCommand
402
- attr_reader :symoff, :nsyms, :stroff, :strsize
577
+ # @return [Fixnum] the symbol table's offset
578
+ attr_reader :symoff
579
+
580
+ # @return [Fixnum] the number of symbol table entries
581
+ attr_reader :nsyms
582
+
583
+ # @return the string table's offset
584
+ attr_reader :stroff
585
+
586
+ # @return the string table size in bytes
587
+ attr_reader :strsize
403
588
 
404
589
  @format = "VVVVVV"
405
590
  @sizeof = 24
406
591
 
592
+ # @private
407
593
  def initialize(offset, cmd, cmdsize, symoff, nsyms, stroff, strsize)
408
594
  super(offset, cmd, cmdsize)
409
595
  @symoff = symoff
@@ -413,16 +599,51 @@ module MachO
413
599
  end
414
600
  end
415
601
 
602
+ # A load command containing symbolic information needed to support data
603
+ # structures used by the dynamic link editor. Corresponds to LC_DYSYMTAB.
416
604
  class DysymtabCommand < LoadCommand
417
- attr_reader :ilocalsym, :nlocalsym, :iextdefsym, :nextdefsym
418
- attr_reader :iundefsym, :nundefsym, :tocoff, :ntoc, :modtaboff
419
- attr_reader :nmodtab, :extrefsymoff, :nextrefsyms, :indirectsymoff
420
- attr_reader :nindirectsyms, :extreloff, :nextrel, :locreloff, :nlocrel
605
+ attr_reader :ilocalsym
606
+
607
+ attr_reader :nlocalsym
608
+
609
+ attr_reader :iextdefsym
610
+
611
+ attr_reader :nextdefsym
612
+
613
+ attr_reader :iundefsym
614
+
615
+ attr_reader :nundefsym
616
+
617
+ attr_reader :tocoff
618
+
619
+ attr_reader :ntoc
620
+
621
+ attr_reader :modtaboff
622
+
623
+ attr_reader :nmodtab
624
+
625
+ attr_reader :extrefsymoff
626
+
627
+ attr_reader :nextrefsyms
628
+
629
+ attr_reader :indirectsymoff
630
+
631
+ attr_reader :nindirectsyms
632
+
633
+ attr_reader :extreloff
634
+
635
+ attr_reader :nextrel
636
+
637
+ attr_reader :locreloff
638
+
639
+ attr_reader :nlocrel
640
+
421
641
 
422
642
  @format = "VVVVVVVVVVVVVVVVVVVV"
423
643
  @sizeof = 80
424
644
 
425
645
  # ugh
646
+ # @private
426
647
  def initialize(offset, cmd, cmdsize, ilocalsym, nlocalsym, iextdefsym,
427
648
  nextdefsym, iundefsym, nundefsym, tocoff, ntoc, modtaboff,
428
649
  nmodtab, extrefsymoff, nextrefsyms, indirectsymoff,
@@ -449,12 +670,19 @@ module MachO
449
670
  end
450
671
  end
451
672
 
673
+ # A load command containing the offset and number of hints in the two-level
674
+ # namespace lookup hints table. Corresponds to LC_TWOLEVEL_HINTS.
452
675
  class TwolevelHintsCommand < LoadCommand
453
- attr_reader :htoffset, :nhints
676
+ # @return [Fixnum] the offset to the hint table
677
+ attr_reader :htoffset
678
+
679
+ # @return [Fixnum] the number of hints in the hint table
680
+ attr_reader :nhints
454
681
 
455
682
  @format = "VVVV"
456
683
  @sizeof = 16
457
684
 
685
+ # @private
458
686
  def initialize(offset, cmd, cmdsize, htoffset, nhints)
459
687
  super(offset, cmd, cmdsize)
460
688
  @htoffset = htoffset
@@ -462,36 +690,52 @@ module MachO
462
690
  end
463
691
  end
464
692
 
693
+ # A load command containing the value of the original checksum for prebound
694
+ # files, or zero. Corresponds to LC_PREBIND_CKSUM.
465
695
  class PrebindCksumCommand < LoadCommand
696
+ # @return [Fixnum] the checksum or 0
466
697
  attr_reader :cksum
467
698
 
468
699
  @format = "VVV"
469
700
  @sizeof = 12
470
701
 
702
+ # @private
471
703
  def initialize(offset, cmd, cmdsize, cksum)
472
704
  super(offset, cmd, cmdsize)
473
705
  @cksum = cksum
474
706
  end
475
707
  end
476
708
 
709
+ # A load command representing an rpath, which specifies a path that should
710
+ # be added to the current run path used to find @rpath prefixed dylibs.
711
+ # Corresponds to LC_RPATH.
477
712
  class RpathCommand < LoadCommand
478
713
  attr_reader :path
479
714
 
480
715
  @format = "VVV"
481
716
  @sizeof = 12
482
717
 
718
+ # @private
483
719
  def initialize(offset, cmd, cmdsize, path)
484
720
  super(offset, cmd, cmdsize)
485
721
  @path = path
486
722
  end
487
723
  end
488
724
 
725
+ # A load command representing the offsets and sizes of a blob of data in
726
+ # the __LINKEDIT segment. Corresponds to LC_CODE_SIGNATURE, LC_SEGMENT_SPLIT_INFO,
727
+ # LC_FUNCTION_STARTS, LC_DATA_IN_CODE, LC_DYLIB_CODE_SIGN_DRS, and LC_LINKER_OPTIMIZATION_HINT.
489
728
  class LinkeditDataCommand < LoadCommand
490
- attr_reader :dataoff, :datasize
729
+ # @return [Fixnum] offset to the data in the __LINKEDIT segment
730
+ attr_reader :dataoff
731
+
732
+ # @return [Fixnum] size of the data in the __LINKEDIT segment
733
+ attr_reader :datasize
491
734
 
492
735
  @format = "VVVV"
493
736
  @sizeof = 16
494
737
 
738
+ # @private
495
739
  def initialize(offset, cmd, cmdsize, dataoff, datasize)
496
740
  super(offset, cmd, cmdsize)
497
741
  @dataoff = dataoff
@@ -499,12 +743,22 @@ module MachO
499
743
  end
500
744
  end
501
745
 
746
+ # A load command representing the offset to and size of an encrypted
747
+ # segment. Corresponds to LC_ENCRYPTION_INFO.
502
748
  class EncryptionInfoCommand < LoadCommand
503
- attr_reader :cryptoff, :cryptsize, :cryptid
749
+ # @return [Fixnum] the offset to the encrypted segment
750
+ attr_reader :cryptoff
751
+
752
+ # @return [Fixnum] the size of the encrypted segment
753
+ attr_reader :cryptsize
754
+
755
+ # @return [Fixnum] the encryption system, or 0 if not encrypted yet
756
+ attr_reader :cryptid
504
757
 
505
758
  @format = "VVVVV"
506
759
  @sizeof = 20
507
760
 
761
+ # @private
508
762
  def initialize(offset, cmd, cmdsize, cryptoff, cryptsize, cryptid)
509
763
  super(offset, cmd, cmdsize)
510
764
  @cryptoff = cryptoff
@@ -513,12 +767,25 @@ module MachO
513
767
  end
514
768
  end
515
769
 
770
+ # A load command representing the offset to and size of an encrypted
771
+ # segment. Corresponds to LC_ENCRYPTION_INFO_64.
516
772
  class EncryptionInfoCommand64 < LoadCommand
517
- attr_reader :cryptoff, :cryptsize, :cryptid, :pad
773
+ # @return [Fixnum] the offset to the encrypted segment
774
+ attr_reader :cryptoff
775
+
776
+ # @return [Fixnum] the size of the encrypted segment
777
+ attr_reader :cryptsize
778
+
779
+ # @return [Fixnum] the encryption system, or 0 if not encrypted yet
780
+ attr_reader :cryptid
781
+
782
+ # @return [Fixnum] 64-bit padding value
783
+ attr_reader :pad
518
784
 
519
785
  @format = "VVVVVV"
520
786
  @sizeof = 24
521
787
 
788
+ # @private
522
789
  def initialize(offset, cmd, cmdsize, cryptoff, cryptsize, cryptid)
523
790
  super(offset, cmd, cmdsize)
524
791
  @cryptoff = cryptoff
@@ -528,12 +795,19 @@ module MachO
528
795
  end
529
796
  end
530
797
 
798
+ # A load command containing the minimum OS version on which the binary
799
+ # was built to run. Corresponds to LC_VERSION_MIN_MACOSX and LC_VERSION_MIN_IPHONEOS.
531
800
  class VersionMinCommand < LoadCommand
532
- attr_reader :version, :sdk
801
+ # @return [Fixnum] the version X.Y.Z packed as x16.y8.z8
802
+ attr_reader :version
803
+
804
+ # @return [Fixnum] the SDK version X.Y.Z packed as x16.y8.z8
805
+ attr_reader :sdk
533
806
 
534
807
  @format = "VVVV"
535
808
  @sizeof = 16
536
809
 
810
+ # @private
537
811
  def initialize(offset, cmd, cmdsize, version, sdk)
538
812
  super(offset, cmd, cmdsize)
539
813
  @version = version
@@ -541,6 +815,9 @@ module MachO
541
815
  end
542
816
  end
543
817
 
818
+ # A load command containing the file offsets and sizes of the new
819
+ # compressed form of the information dyld needs to load the image.
820
+ # Corresponds to LC_DYLD_INFO and LC_DYLD_INFO_ONLY.
544
821
  class DyldInfoCommand < LoadCommand
545
822
  attr_reader :rebase_off, :rebase_size, :bind_off, :bind_size
546
823
  attr_reader :weak_bind_off, :weak_bind_size, :lazy_bind_off
@@ -549,6 +826,7 @@ module MachO
549
826
  @format = "VVVVVVVVVVVV"
550
827
  @sizeof = 48
551
828
 
829
+ # @private
552
830
  def initialize(offset, cmd, cmdsize, rebase_off, rebase_size, bind_off,
553
831
  bind_size, weak_bind_off, weak_bind_size, lazy_bind_off,
554
832
  lazy_bind_size, export_off, export_size)
@@ -566,24 +844,34 @@ module MachO
566
844
  end
567
845
  end
568
846
 
847
+ # A load command containing linker options embedded in object files.
848
+ # Corresponds to LC_LINKER_OPTION.
569
849
  class LinkerOptionCommand < LoadCommand
850
+ # @return [Fixnum] the number of strings
570
851
  attr_reader :count
571
852
 
572
853
  @format = "VVV"
573
854
  @sizeof = 12
574
855
 
856
+ # @private
575
857
  def initialize(offset, cmd, cmdsize, count)
576
858
  super(offset, cmd, cmdsize)
577
859
  @count = count
578
860
  end
579
861
  end
580
862
 
863
+ # A load command specifying the offset of main(). Corresponds to LC_MAIN.
581
864
  class EntryPointCommand < LoadCommand
582
- attr_reader :entryoff, :stacksize
865
+ # @return [Fixnum] the file (__TEXT) offset of main()
866
+ attr_reader :entryoff
867
+
868
+ # @return [Fixnum] if not 0, the initial stack size.
869
+ attr_reader :stacksize
583
870
 
584
871
  @format = "VVQQ"
585
872
  @sizeof = 24
586
873
 
874
+ # @private
587
875
  def initialize(offset, cmd, cmdsize, entryoff, stacksize)
588
876
  super(offset, cmd, cmdsize)
589
877
  @entryoff = entryoff
@@ -591,12 +879,16 @@ module MachO
591
879
  end
592
880
  end
593
881
 
882
+ # A load command specifying the version of the sources used to build the
883
+ # binary. Corresponds to LC_SOURCE_VERSION.
594
884
  class SourceVersionCommand < LoadCommand
885
+ # @return [Fixnum] the version packed as a24.b10.c10.d10.e10
595
886
  attr_reader :version
596
887
 
597
888
  @format = "VVQ"
598
889
  @sizeof = 16
599
890
 
891
+ # @private
600
892
  def initialize(offset, cmd, cmdsize, version)
601
893
  super(offset, cmd, cmdsize)
602
894
  @version = version