| 
									
										
										
										
											2012-05-28 20:39:05 -05:00
										 |  |  | module ArchitectureListExtension | 
					
						
							|  |  |  |   def universal? | 
					
						
							|  |  |  |     self.include? :i386 and self.include? :x86_64 | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-02-03 21:06:51 -08:00
										 |  |  |   def ppc? | 
					
						
							|  |  |  |     self.include? :ppc7400 or self.include? :ppc64 | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-28 20:39:05 -05:00
										 |  |  |   def remove_ppc! | 
					
						
							|  |  |  |     self.delete :ppc7400 | 
					
						
							|  |  |  |     self.delete :ppc64 | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def as_arch_flags | 
					
						
							|  |  |  |     self.collect{ |a| "-arch #{a}" }.join(' ') | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-25 23:44:11 -05:00
										 |  |  | 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
 | 
					
						
							| 
									
										
										
										
											2013-03-10 17:33:06 +00:00
										 |  |  |       when 0x7f454c46 # ELF | 
					
						
							|  |  |  |         mach_data << { :arch => :x86_64, :type => :executable } | 
					
						
							| 
									
										
										
										
											2012-05-25 23:44:11 -05:00
										 |  |  |       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] | 
					
						
							| 
									
										
										
										
											2012-06-16 11:11:09 -05:00
										 |  |  |           when 0x00000002, 0x02000000 then :executable | 
					
						
							|  |  |  |           when 0x00000006, 0x06000000 then :dylib | 
					
						
							| 
									
										
										
										
											2012-06-16 11:35:02 -05:00
										 |  |  |           when 0x00000008, 0x08000000 then :bundle | 
					
						
							| 
									
										
										
										
											2012-06-16 11:11:09 -05:00
										 |  |  |           else :dunno | 
					
						
							|  |  |  |           end | 
					
						
							| 
									
										
										
										
											2012-05-25 23:44:11 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |         mach_data << { :arch => arch, :type => type } | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  |       mach_data | 
					
						
							|  |  |  |     rescue | 
					
						
							|  |  |  |       [] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def archs | 
					
						
							| 
									
										
										
										
											2012-05-28 20:39:05 -05:00
										 |  |  |     mach_data.map{ |m| m.fetch :arch }.extend(ArchitectureListExtension) | 
					
						
							| 
									
										
										
										
											2012-05-25 23:44:11 -05:00
										 |  |  |   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? | 
					
						
							| 
									
										
										
										
											2012-08-21 13:45:35 -05:00
										 |  |  |     mach_data.any? { |m| m.fetch(:type) == :dylib } | 
					
						
							| 
									
										
										
										
											2012-05-25 23:44:11 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def mach_o_executable? | 
					
						
							| 
									
										
										
										
											2012-08-21 13:45:35 -05:00
										 |  |  |     mach_data.any? { |m| m.fetch(:type) == :executable } | 
					
						
							| 
									
										
										
										
											2012-05-25 23:44:11 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-06-16 11:35:02 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def mach_o_bundle? | 
					
						
							| 
									
										
										
										
											2012-08-21 13:45:35 -05:00
										 |  |  |     mach_data.any? { |m| m.fetch(:type) == :bundle } | 
					
						
							| 
									
										
										
										
											2012-06-16 11:35:02 -05:00
										 |  |  |   end | 
					
						
							| 
									
										
										
										
											2012-05-25 23:44:11 -05:00
										 |  |  | end |