| 
									
										
										
										
											2019-04-19 15:38:03 +09:00
										 |  |  | # frozen_string_literal: true | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-13 15:24:18 +01:00
										 |  |  | require "macho" | 
					
						
							| 
									
										
										
										
											2016-09-20 17:37:08 -04:00
										 |  |  | require "os/mac/architecture_list" | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-25 00:28:26 +02:00
										 |  |  | # {Pathname} extension for dealing with Mach-O files. | 
					
						
							|  |  |  | # | 
					
						
							|  |  |  | # @api private | 
					
						
							| 
									
										
										
										
											2016-11-08 16:16:34 -05:00
										 |  |  | module MachOShim | 
					
						
							| 
									
										
										
										
											2019-03-10 21:05:51 -04:00
										 |  |  |   extend Forwardable | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   delegate [:dylib_id, :rpaths, :delete_rpath] => :macho | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  |   def macho | 
					
						
							|  |  |  |     @macho ||= begin | 
					
						
							|  |  |  |       MachO.open(to_s) | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2020-08-25 00:28:26 +02:00
										 |  |  |   private :macho | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  |   def mach_data | 
					
						
							|  |  |  |     @mach_data ||= begin | 
					
						
							|  |  |  |       machos = [] | 
					
						
							|  |  |  |       mach_data = [] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-07 13:37:23 -04:00
										 |  |  |       if MachO::Utils.fat_magic?(macho.magic) | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  |         machos = macho.machos | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         machos << macho | 
					
						
							|  |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       machos.each do |m| | 
					
						
							|  |  |  |         arch = case m.cputype | 
					
						
							| 
									
										
										
										
											2016-06-17 20:41:08 -04:00
										 |  |  |         when :x86_64, :i386, :ppc64 then m.cputype | 
					
						
							|  |  |  |         when :ppc then :ppc7400 | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  |         else :dunno | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         type = case m.filetype | 
					
						
							| 
									
										
										
										
											2016-08-07 13:37:23 -04:00
										 |  |  |         when :dylib, :bundle then m.filetype | 
					
						
							|  |  |  |         when :execute then :executable | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  |         else :dunno | 
					
						
							|  |  |  |         end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-17 15:32:44 +01:00
										 |  |  |         mach_data << { arch: arch, type: type } | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  |       end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       mach_data | 
					
						
							| 
									
										
										
										
											2016-02-15 17:56:47 +01:00
										 |  |  |     rescue MachO::NotAMachOError | 
					
						
							|  |  |  |       # Silently ignore errors that indicate the file is not a Mach-O binary ... | 
					
						
							|  |  |  |       [] | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  |     rescue | 
					
						
							| 
									
										
										
										
											2016-02-15 17:56:47 +01:00
										 |  |  |       # ... but complain about other (parse) errors for further investigation. | 
					
						
							| 
									
										
										
										
											2018-06-06 11:22:21 -04:00
										 |  |  |       onoe "Failed to read Mach-O binary: #{self}" | 
					
						
							| 
									
										
										
										
											2020-04-05 15:44:50 +01:00
										 |  |  |       raise if Homebrew::EnvConfig.developer? | 
					
						
							| 
									
										
										
										
											2018-09-17 02:45:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  |       [] | 
					
						
							|  |  |  |     end | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2020-08-25 00:28:26 +02:00
										 |  |  |   private :mach_data | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-07 19:37:52 -05:00
										 |  |  |   def dynamically_linked_libraries(except: :none) | 
					
						
							|  |  |  |     lcs = macho.dylib_load_commands.reject { |lc| lc.type == except } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-03-04 14:05:32 +01:00
										 |  |  |     lcs.map(&:name).map(&:to_s).uniq | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 17:37:08 -04:00
										 |  |  |   def archs | 
					
						
							|  |  |  |     mach_data.map { |m| m.fetch :arch }.extend(ArchitectureListExtension) | 
					
						
							|  |  |  |   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.any? { |m| m.fetch(:type) == :dylib } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   def mach_o_executable? | 
					
						
							|  |  |  |     mach_data.any? { |m| m.fetch(:type) == :executable } | 
					
						
							|  |  |  |   end | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-01 16:43:00 -08:00
										 |  |  |   alias binary_executable? mach_o_executable? | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-09-20 17:37:08 -04:00
										 |  |  |   def mach_o_bundle? | 
					
						
							|  |  |  |     mach_data.any? { |m| m.fetch(:type) == :bundle } | 
					
						
							|  |  |  |   end | 
					
						
							| 
									
										
										
										
											2016-02-01 14:19:29 -05:00
										 |  |  | end |