Class: MachO::MachOFile
- Inherits:
-
Object
- Object
- MachO::MachOFile
- Defined in:
- lib/macho/macho_file.rb
Overview
Represents a Mach-O file, which contains a header and load commands as well as binary executable instructions. Mach-O binaries are architecture specific.
Instance Attribute Summary collapse
- #header ⇒ MachO::MachHeader, MachO::MachHeader64 readonly
-
#load_commands ⇒ Array<MachO::LoadCommand>
readonly
An array of the file's load commands.
Class Method Summary collapse
-
.new_from_bin(bin) ⇒ MachO::MachOFile
Creates a new MachOFile instance from a binary string.
Instance Method Summary collapse
-
#bundle? ⇒ Boolean
True if the Mach-O is of type
MH_BUNDLE, false otherwise. -
#change_install_name(old_name, new_name) ⇒ void
(also: #change_dylib)
Changes the shared library
old_nametonew_name. -
#command(name) ⇒ Array<MachO::LoadCommand>
(also: #[])
All load commands of a given name.
-
#cpusubtype ⇒ String
A string representation of the Mach-O's CPU subtype.
-
#cputype ⇒ String
A string representation of the Mach-O's CPU type.
-
#dylib? ⇒ Boolean
True if the Mach-O is of type
MH_DYLIB, false otherwise. -
#dylib_id ⇒ String?
The Mach-O's dylib ID, or
nilif not a dylib. -
#dylib_id=(new_id) ⇒ void
Changes the Mach-O's dylib ID to
new_id. -
#executable? ⇒ Boolean
True if the Mach-O is of type
MH_EXECUTE, false otherwise. -
#filetype ⇒ String
A string representation of the Mach-O's filetype.
-
#flags ⇒ Fixnum
Execution flags set by the linker.
-
#initialize(filename) ⇒ MachOFile
constructor
Creates a new FatFile from the given filename.
- #initialize_from_bin(bin) ⇒ Object private
-
#linked_dylibs ⇒ Array<String>
All shared libraries linked to the Mach-O.
-
#magic ⇒ Fixnum
The Mach-O's magic number.
-
#magic32? ⇒ Boolean
True if the Mach-O has 32-bit magic, false otherwise.
-
#magic64? ⇒ Boolean
True if the Mach-O has 64-bit magic, false otherwise.
-
#magic_string ⇒ String
A string representation of the Mach-O's magic number.
-
#ncmds ⇒ Fixnum
The number of load commands in the Mach-O's header.
-
#sections(segment) ⇒ Array<MachO::Section>, Array<MachO::Section64>
All sections of the segment
segment. -
#segments ⇒ Array<MachO::SegmentCommand>, Array<MachO::SegmentCommand64>
All segment load commands in the Mach-O.
-
#serialize ⇒ String
The file's raw Mach-O data.
-
#sizeofcmds ⇒ Fixnum
The size of all load commands, in bytes.
-
#write(filename) ⇒ void
Write all Mach-O data to the given filename.
-
#write! ⇒ void
Write all Mach-O data to the file used to initialize the instance.
Constructor Details
#initialize(filename) ⇒ MachOFile
Creates a new FatFile from the given filename.
28 29 30 31 32 33 34 35 |
# File 'lib/macho/macho_file.rb', line 28 def initialize(filename) raise ArgumentError.new("#{filetype}: no such file") unless File.exist?(filename) @filename = filename @raw_data = open(@filename, "rb") { |f| f.read } @header = get_mach_header @load_commands = get_load_commands end |
Instance Attribute Details
#header ⇒ MachO::MachHeader, MachO::MachHeader64 (readonly)
10 11 12 |
# File 'lib/macho/macho_file.rb', line 10 def header @header end |
#load_commands ⇒ Array<MachO::LoadCommand> (readonly)
Returns an array of the file's load commands.
13 14 15 |
# File 'lib/macho/macho_file.rb', line 13 def load_commands @load_commands end |
Class Method Details
.new_from_bin(bin) ⇒ MachO::MachOFile
Creates a new MachOFile instance from a binary string.
18 19 20 21 22 23 |
# File 'lib/macho/macho_file.rb', line 18 def self.new_from_bin(bin) instance = allocate instance.initialize_from_bin(bin) instance end |
Instance Method Details
#bundle? ⇒ Boolean
Returns true if the Mach-O is of type MH_BUNDLE, false otherwise.
72 73 74 |
# File 'lib/macho/macho_file.rb', line 72 def bundle? header.filetype == MH_BUNDLE end |
#change_install_name(old_name, new_name) ⇒ void Also known as: change_dylib
This method returns an undefined value.
Changes the shared library old_name to new_name
186 187 188 189 190 191 |
# File 'lib/macho/macho_file.rb', line 186 def change_install_name(old_name, new_name) dylib_cmd = command("LC_LOAD_DYLIB").find { |d| d.name.to_s == old_name } raise DylibUnknownError.new(old_name) if dylib_cmd.nil? set_name_in_dylib(dylib_cmd, old_name, new_name) end |
#command(name) ⇒ Array<MachO::LoadCommand> Also known as: []
All load commands of a given name.
121 122 123 |
# File 'lib/macho/macho_file.rb', line 121 def command(name) load_commands.select { |lc| lc.to_s == name } end |
#cpusubtype ⇒ String
Returns a string representation of the Mach-O's CPU subtype.
97 98 99 |
# File 'lib/macho/macho_file.rb', line 97 def cpusubtype CPU_SUBTYPES[header.cpusubtype] end |
#cputype ⇒ String
Returns a string representation of the Mach-O's CPU type.
92 93 94 |
# File 'lib/macho/macho_file.rb', line 92 def cputype CPU_TYPES[header.cputype] end |
#dylib? ⇒ Boolean
Returns true if the Mach-O is of type MH_DYLIB, false otherwise.
67 68 69 |
# File 'lib/macho/macho_file.rb', line 67 def dylib? header.filetype == MH_DYLIB end |
#dylib_id ⇒ String?
The Mach-O's dylib ID, or nil if not a dylib.
142 143 144 145 146 147 148 149 150 |
# File 'lib/macho/macho_file.rb', line 142 def dylib_id if !dylib? return nil end dylib_id_cmd = command("LC_ID_DYLIB").first dylib_id_cmd.name.to_s end |
#dylib_id=(new_id) ⇒ void
This method returns an undefined value.
Changes the Mach-O's dylib ID to new_id. Does nothing if not a dylib.
158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/macho/macho_file.rb', line 158 def dylib_id=(new_id) if !new_id.is_a?(String) raise ArgumentError.new("argument must be a String") end if !dylib? return nil end dylib_cmd = command("LC_ID_DYLIB").first old_id = dylib_id set_name_in_dylib(dylib_cmd, old_id, new_id) end |
#executable? ⇒ Boolean
Returns true if the Mach-O is of type MH_EXECUTE, false otherwise.
62 63 64 |
# File 'lib/macho/macho_file.rb', line 62 def executable? header.filetype == MH_EXECUTE end |
#filetype ⇒ String
Returns a string representation of the Mach-O's filetype.
87 88 89 |
# File 'lib/macho/macho_file.rb', line 87 def filetype MH_FILETYPES[header.filetype] end |
#flags ⇒ Fixnum
Returns execution flags set by the linker.
112 113 114 |
# File 'lib/macho/macho_file.rb', line 112 def flags header.flags end |
#initialize_from_bin(bin) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
38 39 40 41 42 43 |
# File 'lib/macho/macho_file.rb', line 38 def initialize_from_bin(bin) @filename = nil @raw_data = bin @header = get_mach_header @load_commands = get_load_commands end |
#linked_dylibs ⇒ Array<String>
All shared libraries linked to the Mach-O.
175 176 177 |
# File 'lib/macho/macho_file.rb', line 175 def linked_dylibs command("LC_LOAD_DYLIB").map(&:name).map(&:to_s) end |
#magic ⇒ Fixnum
Returns the Mach-O's magic number.
77 78 79 |
# File 'lib/macho/macho_file.rb', line 77 def magic header.magic end |
#magic32? ⇒ Boolean
Returns true if the Mach-O has 32-bit magic, false otherwise.
52 53 54 |
# File 'lib/macho/macho_file.rb', line 52 def magic32? MachO.magic32?(header.magic) end |
#magic64? ⇒ Boolean
Returns true if the Mach-O has 64-bit magic, false otherwise.
57 58 59 |
# File 'lib/macho/macho_file.rb', line 57 def magic64? MachO.magic64?(header.magic) end |
#magic_string ⇒ String
Returns a string representation of the Mach-O's magic number.
82 83 84 |
# File 'lib/macho/macho_file.rb', line 82 def magic_string MH_MAGICS[header.magic] end |
#ncmds ⇒ Fixnum
Returns the number of load commands in the Mach-O's header.
102 103 104 |
# File 'lib/macho/macho_file.rb', line 102 def ncmds header.ncmds end |
#sections(segment) ⇒ Array<MachO::Section>, Array<MachO::Section64>
All sections of the segment segment.
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/macho/macho_file.rb', line 199 def sections(segment) sections = [] if !segment.is_a?(SegmentCommand) && !segment.is_a?(SegmentCommand64) raise ArgumentError.new("not a valid segment") end if segment.nsects.zero? return sections end offset = segment.offset + segment.class.bytesize segment.nsects.times do if segment.is_a? SegmentCommand sections << Section.new_from_bin(@raw_data.slice(offset, Section.bytesize)) offset += Section.bytesize else sections << Section64.new_from_bin(@raw_data.slice(offset, Section64.bytesize)) offset += Section64.bytesize end end sections end |
#segments ⇒ Array<MachO::SegmentCommand>, Array<MachO::SegmentCommand64>
All segment load commands in the Mach-O.
130 131 132 133 134 135 136 |
# File 'lib/macho/macho_file.rb', line 130 def segments if magic32? command("LC_SEGMENT") else command("LC_SEGMENT_64") end end |
#serialize ⇒ String
The file's raw Mach-O data.
47 48 49 |
# File 'lib/macho/macho_file.rb', line 47 def serialize @raw_data end |
#sizeofcmds ⇒ Fixnum
Returns the size of all load commands, in bytes.
107 108 109 |
# File 'lib/macho/macho_file.rb', line 107 def sizeofcmds header.sizeofcmds end |
#write(filename) ⇒ void
This method returns an undefined value.
Write all Mach-O data to the given filename.
228 229 230 |
# File 'lib/macho/macho_file.rb', line 228 def write(filename) File.open(filename, "wb") { |f| f.write(@raw_data) } end |
#write! ⇒ void
Overwrites all data in the file!
This method returns an undefined value.
Write all Mach-O data to the file used to initialize the instance.
237 238 239 240 241 242 243 |
# File 'lib/macho/macho_file.rb', line 237 def write! if @filename.nil? raise MachOError.new("cannot write to a default file when initialized from a binary string") else File.open(@filename, "wb") { |f| f.write(@raw_data) } end end |