Class: MachO::FatFile

Inherits:
Object
  • Object
show all
Defined in:
lib/macho/fat_file.rb

Overview

Represents a "Fat" file, which contains a header, a listing of available architectures, and one or more Mach-O binaries.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(filename) ⇒ FatFile

Creates a new FatFile from the given filename.

Parameters:

  • filename (String)

    the fat file to load from

Raises:

  • (ArgumentError)

    if the given filename does not exist



19
20
21
22
23
24
25
26
27
# File 'lib/macho/fat_file.rb', line 19

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_fat_header
	@fat_archs = get_fat_archs
	@machos = get_machos
end

Instance Attribute Details

#fat_archsArray<MachO::FatArch> (readonly)

Returns an array of fat architectures.

Returns:



11
12
13
# File 'lib/macho/fat_file.rb', line 11

def fat_archs
  @fat_archs
end

#headerMachO::FatHeader (readonly)

Returns the file's header.

Returns:



8
9
10
# File 'lib/macho/fat_file.rb', line 8

def header
  @header
end

#machosArray<MachO::MachOFile> (readonly)

Returns an array of Mach-O binaries.

Returns:



14
15
16
# File 'lib/macho/fat_file.rb', line 14

def machos
  @machos
end

Instance Method Details

#bundle?Boolean

Returns true if the Mach-O is of type MH_BUNDLE, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_BUNDLE, false otherwise



71
72
73
# File 'lib/macho/fat_file.rb', line 71

def bundle?
	machos.first.bundle?
end

#change_install_name(old_name, new_name) ⇒ Object Also known as: change_dylib

TODO:

incomplete

Changes all dependent shared library install names from old_name to new_name. In a fat file, this changes install names in all internal Mach-Os.

Examples:

file.change_install_name('/usr/lib/libFoo.dylib', '/usr/lib/libBar.dylib')

Parameters:

  • old_name (String)

    the shared library name being changed

  • new_name (String)

    the new name



145
146
147
148
149
150
151
# File 'lib/macho/fat_file.rb', line 145

def change_install_name(old_name, new_name)
	machos.each do |macho|
		macho.change_install_name(old_name, new_name)
	end

	synchronize_raw_data
end

#core?Boolean

Returns true if the Mach-O is of type MH_CORE, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_CORE, false otherwise



51
52
53
# File 'lib/macho/fat_file.rb', line 51

def core?
	machos.first.core?
end

#dsym?Boolean

Returns true if the Mach-O is of type MH_DSYM, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_DSYM, false otherwise



76
77
78
# File 'lib/macho/fat_file.rb', line 76

def dsym?
	machos.first.dsym?
end

#dylib?Boolean

Returns true if the Mach-O is of type MH_DYLIB, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_DYLIB, false otherwise



61
62
63
# File 'lib/macho/fat_file.rb', line 61

def dylib?
	machos.first.dylib?
end

#dylib_idString?

The file's dylib ID. If the file is not a dylib, returns nil.

Examples:

file.dylib_id # => 'libBar.dylib'

Returns:

  • (String, nil)

    the file's dylib ID



103
104
105
# File 'lib/macho/fat_file.rb', line 103

def dylib_id
	machos.first.dylib_id
end

#dylib_id=(new_id) ⇒ void

This method returns an undefined value.

Changes the file's dylib ID to new_id. If the file is not a dylib, does nothing.

Examples:

file.dylib_id = 'libFoo.dylib'

Parameters:

  • new_id (String)

    the new dylib ID

Raises:

  • (ArgumentError)

    if new_id is not a String



113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/macho/fat_file.rb', line 113

def dylib_id=(new_id)
	if !new_id.is_a?(String)
		raise ArgumentError.new("argument must be a String")
	end

	if !machos.all?(&:dylib?)
		return nil
	end

	machos.each do |macho|
		macho.dylib_id = new_id
	end

	synchronize_raw_data
end

#dylinker?Boolean

Returns true if the Mach-O is of type MH_DYLINKER, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_DYLINKER, false otherwise



66
67
68
# File 'lib/macho/fat_file.rb', line 66

def dylinker?
	machos.first.dylinker?
end

#executable?Boolean

Returns true if the Mach-O is of type MH_EXECUTE, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_EXECUTE, false otherwise



41
42
43
# File 'lib/macho/fat_file.rb', line 41

def executable?
	machos.first.executable?
end

#extract(cputype) ⇒ MachO::MachOFile?

Extract a Mach-O with the given CPU type from the file.

Examples:

file.extract("CPU_TYPE_I386") # => MachO::MachOFile

Parameters:

  • cputype (String)

    the CPU type of the Mach-O being extracted

Returns:

  • (MachO::MachOFile, nil)

    the extracted Mach-O or nil if no Mach-O has the given CPU type



160
161
162
# File 'lib/macho/fat_file.rb', line 160

def extract(cputype)
	machos.select { |macho| macho.cputype == cputype }.first
end

#filetypeString

The file's type. Assumed to be the same for every Mach-O within.

Returns:

  • (String)

    the filetype



95
96
97
# File 'lib/macho/fat_file.rb', line 95

def filetype
	machos.first.filetype
end

#fvmlib?Boolean

Returns true if the Mach-O is of type MH_FVMLIB, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_FVMLIB, false otherwise



46
47
48
# File 'lib/macho/fat_file.rb', line 46

def fvmlib?
	machos.first.fvmlib?
end

#kext?Boolean

Returns true if the Mach-O is of type MH_KEXT_BUNDLE, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_KEXT_BUNDLE, false otherwise



81
82
83
# File 'lib/macho/fat_file.rb', line 81

def kext?
	machos.first.kext?
end

#linked_dylibsArray<String>

All shared libraries linked to the file's Mach-Os.

Returns:

  • (Array<String>)

    an array of all shared libraries



131
132
133
134
135
136
# File 'lib/macho/fat_file.rb', line 131

def linked_dylibs
	dylibs = machos.map(&:linked_dylibs).flatten

	# can machos inside fat binaries have different dylibs?
	dylibs.uniq!
end

#magicObject



85
86
87
# File 'lib/macho/fat_file.rb', line 85

def magic
	header.magic
end

#magic_stringObject



89
90
91
# File 'lib/macho/fat_file.rb', line 89

def magic_string
	MH_MAGICS[magic]
end

#object?Boolean

Returns true if the Mach-O is of type MH_OBJECT, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_OBJECT, false otherwise



36
37
38
# File 'lib/macho/fat_file.rb', line 36

def object?
	machos.first.object?
end

#preload?Boolean

Returns true if the Mach-O is of type MH_PRELOAD, false otherwise.

Returns:

  • (Boolean)

    true if the Mach-O is of type MH_PRELOAD, false otherwise



56
57
58
# File 'lib/macho/fat_file.rb', line 56

def preload?
	machos.first.preload?
end

#serializeString

The file's raw fat data.

Returns:

  • (String)

    the raw fat data



31
32
33
# File 'lib/macho/fat_file.rb', line 31

def serialize
	@raw_data
end

#write(filename) ⇒ Object

Write all (fat) data to the given filename.

Parameters:

  • filename (String)

    the file to write to



166
167
168
# File 'lib/macho/fat_file.rb', line 166

def write(filename)
	File.open(filename, "wb") { |f| f.write(@raw_data) }
end

#write!Object

Note:

Overwrites all data in the file!

Write all (fat) data to the file used to initialize the instance.



172
173
174
# File 'lib/macho/fat_file.rb', line 172

def write!
	File.open(@filename, "wb") { |f| f.write(@raw_data) }
end