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.
-
#core? ⇒ Boolean
True if the Mach-O is of type
MH_CORE, false otherwise. -
#cpusubtype ⇒ String
A string representation of the Mach-O's CPU subtype.
-
#cputype ⇒ String
A string representation of the Mach-O's CPU type.
-
#dsym? ⇒ Boolean
True if the Mach-O is of type
MH_DSYM, false otherwise. -
#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. -
#dylinker? ⇒ Boolean
True if the Mach-O is of type
MH_DYLINKER, false otherwise. -
#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.
-
#fvmlib? ⇒ Boolean
True if the Mach-O is of type
MH_FVMLIB, false otherwise. -
#initialize(filename) ⇒ MachOFile
constructor
Creates a new FatFile from the given filename.
- #initialize_from_bin(bin) ⇒ Object private
-
#kext? ⇒ Boolean
True if the Mach-O is of type
MH_KEXT_BUNDLE, false otherwise. -
#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.
-
#object? ⇒ Boolean
True if the Mach-O is of type
MH_OBJECT, false otherwise. -
#preload? ⇒ Boolean
True if the Mach-O is of type
MH_PRELOAD, false otherwise. -
#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.
97 98 99 |
# File 'lib/macho/macho_file.rb', line 97 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
222 223 224 225 226 227 |
# File 'lib/macho/macho_file.rb', line 222 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.
157 158 159 |
# File 'lib/macho/macho_file.rb', line 157 def command(name) load_commands.select { |lc| lc.type == name.to_sym } end |
#core? ⇒ Boolean
Returns true if the Mach-O is of type MH_CORE, false otherwise.
77 78 79 |
# File 'lib/macho/macho_file.rb', line 77 def core? header.filetype == MH_CORE end |
#cpusubtype ⇒ String
Returns a string representation of the Mach-O's CPU subtype.
132 133 134 |
# File 'lib/macho/macho_file.rb', line 132 def cpusubtype CPU_SUBTYPES[header.cpusubtype] end |
#cputype ⇒ String
Returns a string representation of the Mach-O's CPU type.
127 128 129 |
# File 'lib/macho/macho_file.rb', line 127 def cputype CPU_TYPES[header.cputype] end |
#dsym? ⇒ Boolean
Returns true if the Mach-O is of type MH_DSYM, false otherwise.
102 103 104 |
# File 'lib/macho/macho_file.rb', line 102 def dsym? header.filetype == MH_DSYM end |
#dylib? ⇒ Boolean
Returns true if the Mach-O is of type MH_DYLIB, false otherwise.
87 88 89 |
# File 'lib/macho/macho_file.rb', line 87 def dylib? header.filetype == MH_DYLIB end |
#dylib_id ⇒ String?
The Mach-O's dylib ID, or nil if not a dylib.
178 179 180 181 182 183 184 185 186 |
# File 'lib/macho/macho_file.rb', line 178 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.
194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/macho/macho_file.rb', line 194 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 |
#dylinker? ⇒ Boolean
Returns true if the Mach-O is of type MH_DYLINKER, false otherwise.
92 93 94 |
# File 'lib/macho/macho_file.rb', line 92 def dylinker? header.filetype == MH_DYLINKER end |
#executable? ⇒ Boolean
Returns true if the Mach-O is of type MH_EXECUTE, false otherwise.
67 68 69 |
# File 'lib/macho/macho_file.rb', line 67 def executable? header.filetype == MH_EXECUTE end |
#filetype ⇒ String
Returns a string representation of the Mach-O's filetype.
122 123 124 |
# File 'lib/macho/macho_file.rb', line 122 def filetype MH_FILETYPES[header.filetype] end |
#flags ⇒ Fixnum
Returns execution flags set by the linker.
147 148 149 |
# File 'lib/macho/macho_file.rb', line 147 def flags header.flags end |
#fvmlib? ⇒ Boolean
Returns true if the Mach-O is of type MH_FVMLIB, false otherwise.
72 73 74 |
# File 'lib/macho/macho_file.rb', line 72 def fvmlib? header.filetype == MH_FVMLIB 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 |
#kext? ⇒ Boolean
Returns true if the Mach-O is of type MH_KEXT_BUNDLE, false otherwise.
107 108 109 |
# File 'lib/macho/macho_file.rb', line 107 def kext? header.filetype == MH_KEXT_BUNDLE end |
#linked_dylibs ⇒ Array<String>
All shared libraries linked to the Mach-O.
211 212 213 |
# File 'lib/macho/macho_file.rb', line 211 def linked_dylibs command(:LC_LOAD_DYLIB).map(&:name).map(&:to_s) end |
#magic ⇒ Fixnum
Returns the Mach-O's magic number.
112 113 114 |
# File 'lib/macho/macho_file.rb', line 112 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.
117 118 119 |
# File 'lib/macho/macho_file.rb', line 117 def magic_string MH_MAGICS[magic] end |
#ncmds ⇒ Fixnum
Returns the number of load commands in the Mach-O's header.
137 138 139 |
# File 'lib/macho/macho_file.rb', line 137 def ncmds header.ncmds end |
#object? ⇒ Boolean
Returns true if the Mach-O is of type MH_OBJECT, false otherwise.
62 63 64 |
# File 'lib/macho/macho_file.rb', line 62 def object? header.filetype == MH_OBJECT end |
#preload? ⇒ Boolean
Returns true if the Mach-O is of type MH_PRELOAD, false otherwise.
82 83 84 |
# File 'lib/macho/macho_file.rb', line 82 def preload? header.filetype == MH_PRELOAD end |
#sections(segment) ⇒ Array<MachO::Section>, Array<MachO::Section64>
All sections of the segment segment.
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/macho/macho_file.rb', line 235 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.
166 167 168 169 170 171 172 |
# File 'lib/macho/macho_file.rb', line 166 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.
142 143 144 |
# File 'lib/macho/macho_file.rb', line 142 def sizeofcmds header.sizeofcmds end |
#write(filename) ⇒ void
This method returns an undefined value.
Write all Mach-O data to the given filename.
264 265 266 |
# File 'lib/macho/macho_file.rb', line 264 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.
273 274 275 276 277 278 279 |
# File 'lib/macho/macho_file.rb', line 273 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 |