ruby-macho 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,16 +1,25 @@
1
1
  module MachO
2
- # Opens the given filename as a MachOFile or FatFile, depending on its magic.
3
- # @param filename [String] the file being opened
4
- # @return [MachO::MachOFile] if the file is a Mach-O
5
- # @return [MachO::FatFile] if the file is a Fat file
6
- def self.open(filename)
7
- # open file and test magic instead of using exceptions for control?
8
- begin
9
- file = MachOFile.new(filename)
10
- rescue FatBinaryError
11
- file = FatFile.new(filename)
12
- end
2
+ # Opens the given filename as a MachOFile or FatFile, depending on its magic.
3
+ # @param filename [String] the file being opened
4
+ # @return [MachO::MachOFile] if the file is a Mach-O
5
+ # @return [MachO::FatFile] if the file is a Fat file
6
+ # @raise [ArgumentError] if the given file does not exist
7
+ # @raise [MachO::TruncatedFileError] if the file is too small to have a valid header
8
+ # @raise [MachO::MagicError] if the file's magic is not valid Mach-O magic
9
+ def self.open(filename)
10
+ raise ArgumentError.new("#{filename}: no such file") unless File.file?(filename)
11
+ raise TruncatedFileError.new unless File.stat(filename).size >= 4
13
12
 
14
- file
15
- end
16
- end
13
+ magic = File.open(filename, "rb") { |f| f.read(4) }.unpack("N").first
14
+
15
+ if MachO.fat_magic?(magic)
16
+ file = FatFile.new(filename)
17
+ elsif MachO.magic?(magic)
18
+ file = MachOFile.new(filename)
19
+ else
20
+ raise MagicError.new(magic)
21
+ end
22
+
23
+ file
24
+ end
25
+ end
@@ -1,159 +1,159 @@
1
1
  module MachO
2
- # type mask
3
- SECTION_TYPE = 0x000000ff
4
-
5
- # attributes mask
6
- SECTION_ATTRIBUTES = 0xffffff00
7
-
8
- # user settable attributes mask
9
- SECTION_ATTRIBUTES_USR = 0xff000000
10
-
11
- # system settable attributes mask
12
- SECTION_ATTRIBUTES_SYS = 0x00ffff00
13
-
14
- # association of section flag symbols to values
15
- # @api private
16
- SECTION_FLAGS = {
17
- :S_REGULAR => 0x0,
18
- :S_ZEROFILL => 0x1,
19
- :S_CSTRING_LITERALS => 0x2,
20
- :S_4BYTE_LITERALS => 0x3,
21
- :S_8BYTE_LITERALS => 0x4,
22
- :S_LITERAL_POINTERS => 0x5,
23
- :S_NON_LAZY_SYMBOL_POINTERS => 0x6,
24
- :S_LAZY_SYMBOL_POINTERS => 0x7,
25
- :S_SYMBOL_STUBS => 0x8,
26
- :S_MOD_INIT_FUNC_POINTERS => 0x9,
27
- :S_MOD_TERM_FUNC_POINTERS => 0xa,
28
- :S_COALESCED => 0xb,
29
- :S_GB_ZEROFILE => 0xc,
30
- :S_INTERPOSING => 0xd,
31
- :S_16BYTE_LITERALS => 0xe,
32
- :S_DTRACE_DOF => 0xf,
33
- :S_LAZY_DYLIB_SYMBOL_POINTERS => 0x10,
34
- :S_THREAD_LOCAL_REGULAR => 0x11,
35
- :S_THREAD_LOCAL_ZEROFILL => 0x12,
36
- :S_THREAD_LOCAL_VARIABLES => 0x13,
37
- :S_THREAD_LOCAL_VARIABLE_POINTERS => 0x14,
38
- :S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => 0x15,
39
- :S_ATTR_PURE_INSTRUCTIONS => 0x80000000,
40
- :S_ATTR_NO_TOC => 0x40000000,
41
- :S_ATTR_STRIP_STATIC_SYMS => 0x20000000,
42
- :S_ATTR_NO_DEAD_STRIP => 0x10000000,
43
- :S_ATTR_LIVE_SUPPORT => 0x08000000,
44
- :S_ATTR_SELF_MODIFYING_CODE => 0x04000000,
45
- :S_ATTR_DEBUG => 0x02000000,
46
- :S_ATTR_SOME_INSTRUCTIONS => 0x00000400,
47
- :S_ATTR_EXT_RELOC => 0x00000200,
48
- :S_ATTR_LOC_RELOC => 0x00000100
49
- }
50
-
51
- # association of section name symbols to names
52
- # @api private
53
- SECTION_NAMES = {
54
- :SECT_TEXT => "__text",
55
- :SECT_FVMLIB_INIT0 => "__fvmlib_init0",
56
- :SECT_FVMLIB_INIT1 => "__fvmlib_init1",
57
- :SECT_DATA => "__data",
58
- :SECT_BSS => "__bss",
59
- :SECT_COMMON => "__common",
60
- :SECT_OBJC_SYMBOLS => "__symbol_table",
61
- :SECT_OBJC_MODULES => "__module_info",
62
- :SECT_OBJC_STRINGS => "__selector_strs",
63
- :SECT_OBJC_REFS => "__selector_refs",
64
- :SECT_ICON_HEADER => "__header",
65
- :SECT_ICON_TIFF => "__tiff"
66
- }
67
-
68
- # Represents a section of a segment for 32-bit architectures.
69
- class Section < MachOStructure
70
- # @return [String] the name of the section, including null pad bytes
71
- attr_reader :sectname
72
-
73
- # @return [String] the name of the segment's section, including null pad bytes
74
- attr_reader :segname
75
-
76
- # @return [Fixnum] the memory address of the section
77
- attr_reader :addr
78
-
79
- # @return [Fixnum] the size, in bytes, of the section
80
- attr_reader :size
81
-
82
- # @return [Fixnum] the file offset of the section
83
- attr_reader :offset
84
-
85
- # @return [Fixnum] the section alignment (power of 2) of the section
86
- attr_reader :align
87
-
88
- # @return [Fixnum] the file offset of the section's relocation entries
89
- attr_reader :reloff
90
-
91
- # @return [Fixnum] the number of relocation entries
92
- attr_reader :nreloc
93
-
94
- # @return [Fixnum] flags for type and addrributes of the section
95
- attr_reader :flags
96
-
97
- # @return [void] reserved (for offset or index)
98
- attr_reader :reserved1
99
-
100
- # @return [void] reserved (for count or sizeof)
101
- attr_reader :reserved2
102
-
103
- FORMAT = "a16a16VVVVVVVVV"
104
- SIZEOF = 68
105
-
106
- # @api private
107
- def initialize(sectname, segname, addr, size, offset, align, reloff,
108
- nreloc, flags, reserved1, reserved2)
109
- @sectname = sectname
110
- @segname = segname
111
- @addr = addr
112
- @size = size
113
- @offset = offset
114
- @align = align
115
- @reloff = reloff
116
- @nreloc = nreloc
117
- @flags = flags
118
- @reserved1 = reserved1
119
- @reserved2 = reserved2
120
- end
121
-
122
- # @return [String] the section's name, with any trailing NULL characters removed
123
- def section_name
124
- @sectname.delete("\x00")
125
- end
126
-
127
- # @return [String] the parent segment's name, with any trailing NULL characters removed
128
- def segment_name
129
- @segname.delete("\x00")
130
- end
131
-
132
- # @example
133
- # puts "this section is regular" if sect.flag?(:S_REGULAR)
134
- # @param flag [Symbol] a section flag symbol
135
- # @return [Boolean] true if `flag` is present in the section's flag field
136
- def flag?(flag)
137
- flag = SECTION_FLAGS[flag]
138
- return false if flag.nil?
139
- flags & flag == flag
140
- end
141
- end
142
-
143
- # Represents a section of a segment for 64-bit architectures.
144
- class Section64 < Section
145
- # @return [void] reserved
146
- attr_reader :reserved3
147
-
148
- FORMAT = "a16a16QQVVVVVVVV"
149
- SIZEOF = 80
150
-
151
- # @api private
152
- def initialize(sectname, segname, addr, size, offset, align, reloff,
153
- nreloc, flags, reserved1, reserved2, reserved3)
154
- super(sectname, segname, addr, size, offset, align, reloff,
155
- nreloc, flags, reserved1, reserved2)
156
- @reserved3 = reserved3
157
- end
158
- end
2
+ # type mask
3
+ SECTION_TYPE = 0x000000ff
4
+
5
+ # attributes mask
6
+ SECTION_ATTRIBUTES = 0xffffff00
7
+
8
+ # user settable attributes mask
9
+ SECTION_ATTRIBUTES_USR = 0xff000000
10
+
11
+ # system settable attributes mask
12
+ SECTION_ATTRIBUTES_SYS = 0x00ffff00
13
+
14
+ # association of section flag symbols to values
15
+ # @api private
16
+ SECTION_FLAGS = {
17
+ :S_REGULAR => 0x0,
18
+ :S_ZEROFILL => 0x1,
19
+ :S_CSTRING_LITERALS => 0x2,
20
+ :S_4BYTE_LITERALS => 0x3,
21
+ :S_8BYTE_LITERALS => 0x4,
22
+ :S_LITERAL_POINTERS => 0x5,
23
+ :S_NON_LAZY_SYMBOL_POINTERS => 0x6,
24
+ :S_LAZY_SYMBOL_POINTERS => 0x7,
25
+ :S_SYMBOL_STUBS => 0x8,
26
+ :S_MOD_INIT_FUNC_POINTERS => 0x9,
27
+ :S_MOD_TERM_FUNC_POINTERS => 0xa,
28
+ :S_COALESCED => 0xb,
29
+ :S_GB_ZEROFILE => 0xc,
30
+ :S_INTERPOSING => 0xd,
31
+ :S_16BYTE_LITERALS => 0xe,
32
+ :S_DTRACE_DOF => 0xf,
33
+ :S_LAZY_DYLIB_SYMBOL_POINTERS => 0x10,
34
+ :S_THREAD_LOCAL_REGULAR => 0x11,
35
+ :S_THREAD_LOCAL_ZEROFILL => 0x12,
36
+ :S_THREAD_LOCAL_VARIABLES => 0x13,
37
+ :S_THREAD_LOCAL_VARIABLE_POINTERS => 0x14,
38
+ :S_THREAD_LOCAL_INIT_FUNCTION_POINTERS => 0x15,
39
+ :S_ATTR_PURE_INSTRUCTIONS => 0x80000000,
40
+ :S_ATTR_NO_TOC => 0x40000000,
41
+ :S_ATTR_STRIP_STATIC_SYMS => 0x20000000,
42
+ :S_ATTR_NO_DEAD_STRIP => 0x10000000,
43
+ :S_ATTR_LIVE_SUPPORT => 0x08000000,
44
+ :S_ATTR_SELF_MODIFYING_CODE => 0x04000000,
45
+ :S_ATTR_DEBUG => 0x02000000,
46
+ :S_ATTR_SOME_INSTRUCTIONS => 0x00000400,
47
+ :S_ATTR_EXT_RELOC => 0x00000200,
48
+ :S_ATTR_LOC_RELOC => 0x00000100
49
+ }.freeze
50
+
51
+ # association of section name symbols to names
52
+ # @api private
53
+ SECTION_NAMES = {
54
+ :SECT_TEXT => "__text",
55
+ :SECT_FVMLIB_INIT0 => "__fvmlib_init0",
56
+ :SECT_FVMLIB_INIT1 => "__fvmlib_init1",
57
+ :SECT_DATA => "__data",
58
+ :SECT_BSS => "__bss",
59
+ :SECT_COMMON => "__common",
60
+ :SECT_OBJC_SYMBOLS => "__symbol_table",
61
+ :SECT_OBJC_MODULES => "__module_info",
62
+ :SECT_OBJC_STRINGS => "__selector_strs",
63
+ :SECT_OBJC_REFS => "__selector_refs",
64
+ :SECT_ICON_HEADER => "__header",
65
+ :SECT_ICON_TIFF => "__tiff"
66
+ }.freeze
67
+
68
+ # Represents a section of a segment for 32-bit architectures.
69
+ class Section < MachOStructure
70
+ # @return [String] the name of the section, including null pad bytes
71
+ attr_reader :sectname
72
+
73
+ # @return [String] the name of the segment's section, including null pad bytes
74
+ attr_reader :segname
75
+
76
+ # @return [Fixnum] the memory address of the section
77
+ attr_reader :addr
78
+
79
+ # @return [Fixnum] the size, in bytes, of the section
80
+ attr_reader :size
81
+
82
+ # @return [Fixnum] the file offset of the section
83
+ attr_reader :offset
84
+
85
+ # @return [Fixnum] the section alignment (power of 2) of the section
86
+ attr_reader :align
87
+
88
+ # @return [Fixnum] the file offset of the section's relocation entries
89
+ attr_reader :reloff
90
+
91
+ # @return [Fixnum] the number of relocation entries
92
+ attr_reader :nreloc
93
+
94
+ # @return [Fixnum] flags for type and addrributes of the section
95
+ attr_reader :flags
96
+
97
+ # @return [void] reserved (for offset or index)
98
+ attr_reader :reserved1
99
+
100
+ # @return [void] reserved (for count or sizeof)
101
+ attr_reader :reserved2
102
+
103
+ FORMAT = "a16a16L=9"
104
+ SIZEOF = 68
105
+
106
+ # @api private
107
+ def initialize(sectname, segname, addr, size, offset, align, reloff,
108
+ nreloc, flags, reserved1, reserved2)
109
+ @sectname = sectname
110
+ @segname = segname
111
+ @addr = addr
112
+ @size = size
113
+ @offset = offset
114
+ @align = align
115
+ @reloff = reloff
116
+ @nreloc = nreloc
117
+ @flags = flags
118
+ @reserved1 = reserved1
119
+ @reserved2 = reserved2
120
+ end
121
+
122
+ # @return [String] the section's name, with any trailing NULL characters removed
123
+ def section_name
124
+ @sectname.delete("\x00")
125
+ end
126
+
127
+ # @return [String] the parent segment's name, with any trailing NULL characters removed
128
+ def segment_name
129
+ @segname.delete("\x00")
130
+ end
131
+
132
+ # @example
133
+ # puts "this section is regular" if sect.flag?(:S_REGULAR)
134
+ # @param flag [Symbol] a section flag symbol
135
+ # @return [Boolean] true if `flag` is present in the section's flag field
136
+ def flag?(flag)
137
+ flag = SECTION_FLAGS[flag]
138
+ return false if flag.nil?
139
+ flags & flag == flag
140
+ end
141
+ end
142
+
143
+ # Represents a section of a segment for 64-bit architectures.
144
+ class Section64 < Section
145
+ # @return [void] reserved
146
+ attr_reader :reserved3
147
+
148
+ FORMAT = "a16a16Q=2L=8"
149
+ SIZEOF = 80
150
+
151
+ # @api private
152
+ def initialize(sectname, segname, addr, size, offset, align, reloff,
153
+ nreloc, flags, reserved1, reserved2, reserved3)
154
+ super(sectname, segname, addr, size, offset, align, reloff,
155
+ nreloc, flags, reserved1, reserved2)
156
+ @reserved3 = reserved3
157
+ end
158
+ end
159
159
  end
@@ -1,22 +1,38 @@
1
1
  module MachO
2
- # A general purpose pseudo-structure.
3
- # @abstract
4
- class MachOStructure
5
- # The format of the data structure, in String#unpack format.
6
- FORMAT = ""
2
+ # A general purpose pseudo-structure.
3
+ # @abstract
4
+ class MachOStructure
5
+ # The String#unpack format of the data structure.
6
+ FORMAT = ""
7
7
 
8
- # The size of the data structure, in bytes.
9
- SIZEOF = 0
8
+ # The size of the data structure, in bytes.
9
+ SIZEOF = 0
10
10
 
11
- # @return [Fixnum] the size, in bytes, of the represented structure.
12
- def self.bytesize
13
- self::SIZEOF
14
- end
11
+ # @return [Fixnum] the size, in bytes, of the represented structure.
12
+ def self.bytesize
13
+ self::SIZEOF
14
+ end
15
15
 
16
- # @return [MachO::MachOStructure] a new MachOStructure initialized with `bin`
17
- # @api private
18
- def self.new_from_bin(bin)
19
- self.new(*bin.unpack(self::FORMAT))
20
- end
21
- end
16
+ # @param endianness [Symbol] either :big or :little
17
+ # @param bin [String] the string to be unpacked into the new structure
18
+ # @return [MachO::MachOStructure] a new MachOStructure initialized with `bin`
19
+ # @api private
20
+ def self.new_from_bin(endianness, bin)
21
+ format = specialize_format(self::FORMAT, endianness)
22
+
23
+ self.new(*bin.unpack(format))
24
+ end
25
+
26
+ private
27
+
28
+ # Convert an abstract (native-endian) String#unpack format to big or little.
29
+ # @param format [String] the format string being converted
30
+ # @param endianness [Symbol] either :big or :little
31
+ # @return [String] the converted string
32
+ # @api private
33
+ def self.specialize_format(format, endianness)
34
+ modifier = (endianness == :big) ? ">" : "<"
35
+ format.tr("=", modifier)
36
+ end
37
+ end
22
38
  end
@@ -1,65 +1,65 @@
1
1
  module MachO
2
- # A collection of convenient methods for common operations on Mach-O and Fat binaries.
3
- module Tools
4
- # @param filename [String] the Mach-O or Fat binary being read
5
- # @return [Array<String>] an array of all dylibs linked to the binary
6
- def self.dylibs(filename)
7
- file = MachO.open(filename)
2
+ # A collection of convenient methods for common operations on Mach-O and Fat binaries.
3
+ module Tools
4
+ # @param filename [String] the Mach-O or Fat binary being read
5
+ # @return [Array<String>] an array of all dylibs linked to the binary
6
+ def self.dylibs(filename)
7
+ file = MachO.open(filename)
8
8
 
9
- file.linked_dylibs
10
- end
9
+ file.linked_dylibs
10
+ end
11
11
 
12
- # Changes the dylib ID of a Mach-O or Fat binary, overwriting the source file.
13
- # @param filename [String] the Mach-O or Fat binary being modified
14
- # @param new_id [String] the new dylib ID for the binary
15
- # @return [void]
16
- # @todo unstub for fat files
17
- def self.change_dylib_id(filename, new_id)
18
- file = MachO.open(filename)
12
+ # Changes the dylib ID of a Mach-O or Fat binary, overwriting the source file.
13
+ # @param filename [String] the Mach-O or Fat binary being modified
14
+ # @param new_id [String] the new dylib ID for the binary
15
+ # @return [void]
16
+ # @todo unstub for fat files
17
+ def self.change_dylib_id(filename, new_id)
18
+ file = MachO.open(filename)
19
19
 
20
- file.dylib_id = new_id
21
- file.write!
22
- end
20
+ file.dylib_id = new_id
21
+ file.write!
22
+ end
23
23
 
24
- # Changes a shared library install name in a Mach-O or Fat binary, overwriting the source file.
25
- # @param filename [String] the Mach-O or Fat binary being modified
26
- # @param old_name [String] the old shared library name
27
- # @param new_name [String] the new shared library name
28
- # @return [void]
29
- # @todo unstub for fat files
30
- def self.change_install_name(filename, old_name, new_name)
31
- file = MachO.open(filename)
24
+ # Changes a shared library install name in a Mach-O or Fat binary, overwriting the source file.
25
+ # @param filename [String] the Mach-O or Fat binary being modified
26
+ # @param old_name [String] the old shared library name
27
+ # @param new_name [String] the new shared library name
28
+ # @return [void]
29
+ # @todo unstub for fat files
30
+ def self.change_install_name(filename, old_name, new_name)
31
+ file = MachO.open(filename)
32
32
 
33
- file.change_install_name(old_name, new_name)
34
- file.write!
35
- end
33
+ file.change_install_name(old_name, new_name)
34
+ file.write!
35
+ end
36
36
 
37
- # Changes a runtime path in a Mach-O or Fat binary, overwriting the source file.
38
- # @param filename [String] the Mach-O or Fat binary being modified
39
- # @param old_path [String] the old runtime path
40
- # @param new_path [String] the new runtime path
41
- # @return [void]
42
- # @todo unstub
43
- def self.change_rpath(filename, old_path, new_path)
44
- raise "stub"
45
- end
37
+ # Changes a runtime path in a Mach-O or Fat binary, overwriting the source file.
38
+ # @param filename [String] the Mach-O or Fat binary being modified
39
+ # @param old_path [String] the old runtime path
40
+ # @param new_path [String] the new runtime path
41
+ # @return [void]
42
+ # @todo unstub
43
+ def self.change_rpath(filename, old_path, new_path)
44
+ raise UnimplementedError.new("changing rpaths in a Mach-O")
45
+ end
46
46
 
47
- # Add a runtime path to a Mach-O or Fat binary, overwriting the source file.
48
- # @param filename [String] the Mach-O or Fat binary being modified
49
- # @param new_path [String] the new runtime path
50
- # @return [void]
51
- # @todo unstub
52
- def self.add_rpath(filename, new_path)
53
- raise "stub"
54
- end
47
+ # Add a runtime path to a Mach-O or Fat binary, overwriting the source file.
48
+ # @param filename [String] the Mach-O or Fat binary being modified
49
+ # @param new_path [String] the new runtime path
50
+ # @return [void]
51
+ # @todo unstub
52
+ def self.add_rpath(filename, new_path)
53
+ raise UnimplementedError.new("adding rpaths to a Mach-O")
54
+ end
55
55
 
56
- # Delete a runtime path from a Mach-O or Fat binary, overwriting the source file.
57
- # @param filename [String] the Mach-O or Fat binary being modified
58
- # @param old_path [String] the old runtime path
59
- # @return [void]
60
- # @todo unstub
61
- def self.delete_rpath(filename, old_path)
62
- raise "stub"
63
- end
64
- end
56
+ # Delete a runtime path from a Mach-O or Fat binary, overwriting the source file.
57
+ # @param filename [String] the Mach-O or Fat binary being modified
58
+ # @param old_path [String] the old runtime path
59
+ # @return [void]
60
+ # @todo unstub
61
+ def self.delete_rpath(filename, old_path)
62
+ raise UnimplementedError.new("removing rpaths from a Mach-O")
63
+ end
64
+ end
65
65
  end