diff options
| author | Jack Nagel | 2012-05-25 23:44:11 -0500 |
|---|---|---|
| committer | Jack Nagel | 2012-05-30 22:32:48 -0500 |
| commit | a7861783828182425c2dd7ec8dbc716843ff0f48 (patch) | |
| tree | 83b4e046d0990b304ffa84067977d74955d07e4f /Library/Homebrew/mach.rb | |
| parent | b6e0dfed2385ee61f6c55907b407cbaefb411ea6 (diff) | |
| download | brew-a7861783828182425c2dd7ec8dbc716843ff0f48.tar.bz2 | |
Pathname: add Mach-O module
The MachO module contains methods for learning about Mach-O binaries,
and can be used where one might normally shell out to file(1).
Signed-off-by: Jack Nagel <jacknagel@gmail.com>
Diffstat (limited to 'Library/Homebrew/mach.rb')
| -rw-r--r-- | Library/Homebrew/mach.rb | 93 |
1 files changed, 93 insertions, 0 deletions
diff --git a/Library/Homebrew/mach.rb b/Library/Homebrew/mach.rb new file mode 100644 index 000000000..e24cc1bc5 --- /dev/null +++ b/Library/Homebrew/mach.rb @@ -0,0 +1,93 @@ +module MachO + # Mach-O binary methods, see: + # /usr/include/mach-o/loader.h + # /usr/include/mach-o/fat.h + + def mach_data + @mach_data ||= begin + offsets = [] + mach_data = [] + + header = read(8).unpack("N2") + case header[0] + when 0xcafebabe # universal + header[1].times do |i| + # header[1] is the number of struct fat_arch in the file. + # Each struct fat_arch is 20 bytes, and the 'offset' member + # begins 8 bytes into the struct, with an additional 8 byte + # offset due to the struct fat_header at the beginning of + # the file. + offsets << read(4, 20*i + 16).unpack("N")[0] + end + when 0xcefaedfe, 0xcffaedfe, 0xfeedface, 0xfeedfacf # Single arch + offsets << 0 + else + raise "Not a Mach-O binary." + end + + offsets.each do |offset| + arch = case read(8, offset).unpack("N2") + when [0xcefaedfe, 0x07000000] then :i386 + when [0xcffaedfe, 0x07000001] then :x86_64 + when [0xfeedface, 0x00000012] then :ppc7400 + when [0xfeedfacf, 0x01000012] then :ppc64 + else :dunno + end + + type = case read(4, offset + 12).unpack("N")[0] + when 0x00000002, 0x02000000 then :executable + when 0x00000006, 0x06000000 then :dylib + else :dunno + end + + mach_data << { :arch => arch, :type => type } + end + mach_data + rescue + # read() will raise if it sees EOF, which should only happen if the + # file is < 8 bytes. Otherwise, we raise if the file is not a Mach-O + # binary. In both cases, we want to return an empty array. + [] + end + end + + def archs + mach_data.map{ |m| m.fetch :arch } + end + + def arch + case archs.length + when 0 then :dunno + when 1 then archs.first + else :universal + end + end + + def universal? + arch == :universal + end + + def i386? + arch == :i386 + end + + def x86_64? + arch == :x86_64 + end + + def ppc7400? + arch == :ppc7400 + end + + def ppc64? + arch == :ppc64 + end + + def dylib? + mach_data.map{ |m| m.fetch :type }.include? :dylib + end + + def mach_o_executable? + mach_data.map{ |m| m.fetch :type }.include? :executable + end +end |
