Class: CompiledLocation::Resolver
- Inherits:
-
Object
- Object
- CompiledLocation::Resolver
- Defined in:
- lib/c_location/resolver.rb
Instance Attribute Summary collapse
-
#offset ⇒ Object
Returns the value of attribute offset.
-
#shared_library ⇒ Object
Returns the value of attribute shared_library.
Instance Method Summary collapse
- #absolutify(file, line, shared_library) ⇒ Object
-
#initialize(shared_library, offset) ⇒ Resolver
constructor
A new instance of Resolver.
- #nm(shared_library, offset) ⇒ Object
- #objdump(shared_library, offset) ⇒ Object
- #objdump_tt(shared_library, name) ⇒ Object
- #run(command) ⇒ Object
- #source_location ⇒ Object
- #which_nm ⇒ Object
- #which_objdump ⇒ Object
Constructor Details
#initialize(shared_library, offset) ⇒ Resolver
Returns a new instance of Resolver.
5 6 7 8 |
# File 'lib/c_location/resolver.rb', line 5 def initialize(shared_library, offset) self.shared_library, self.offset = [shared_library, offset] self.shared_library = `which ruby` if self.shared_library == 'ruby' end |
Instance Attribute Details
#offset ⇒ Object
Returns the value of attribute offset.
3 4 5 |
# File 'lib/c_location/resolver.rb', line 3 def offset @offset end |
#shared_library ⇒ Object
Returns the value of attribute shared_library.
3 4 5 |
# File 'lib/c_location/resolver.rb', line 3 def shared_library @shared_library end |
Instance Method Details
#absolutify(file, line, shared_library) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/c_location/resolver.rb', line 83 def absolutify(file, line, shared_library) if shared_library =~ %r{(.*/(gems|src)/[^/]*)/} potentials = Dir["#{$1}/**/#{file}"] elsif shared_library =~ %r{(.*/(rubies)/[^/]*)/} potentials = Dir["#{$1.sub('/rubies/', '/src/')}/**/#{file}"] else potentials = Dir["./**/#{file}"] end if potentials.empty? raise "Could not find the `#{file}:#{line}` that was used to build `#{shared_library}`." + "If you know where this file is please submit a pull request" else [potentials.first, line] end end |
#nm(shared_library, offset) ⇒ Object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/c_location/resolver.rb', line 32 def nm(shared_library, offset) command = "#{Shellwords.escape which_nm} -pa #{Shellwords.escape shared_library}" output = run(command) o_file = nil output.lines.each do |line| case line when /OSO (.*\.o\)?)/ o_file = $1.sub(%r{(.*)/([^/]*)\((.*)\)}, '\1/\3') when /^[01]*#{offset.to_s(16)}.*FUN (.+)/ raise "Your version of nm seems to not output OSO lines." unless o_file return objdump_tt(o_file, $1) end end raise "Could not find #{shared_library}@0x#{offset.to_s(16)} using #{command.inspect}." + "This may be because your ruby/extensions are not compiled with -g." end |
#objdump(shared_library, offset) ⇒ Object
18 19 20 21 22 23 24 25 26 27 28 29 30 |
# File 'lib/c_location/resolver.rb', line 18 def objdump(shared_library, offset) command = "#{Shellwords.escape which_objdump} --dwarf=decodedline #{Shellwords.escape shared_library}" output = run(command) if m = output.lines.detect{ |line| line =~ /\s+0x#{offset.to_s(16)}$/ } file, line, address = m.split(/\s+/) absolutify(file, line.to_i(10), shared_library) else raise "Could not find #{shared_library}@0x#{offset.to_s(16)} using #{command.inspect}." + "This may be because your ruby/extensions are not compiled with -g." end end |
#objdump_tt(shared_library, name) ⇒ Object
52 53 54 55 56 57 58 59 60 |
# File 'lib/c_location/resolver.rb', line 52 def objdump_tt(shared_library, name) output = run("#{Shellwords.escape which_objdump} -tT #{Shellwords.escape shared_library}") if output.lines.detect{ |line| line =~ /^([0-9a-f]+).*\.text\s#{Regexp.escape name}$/ } objdump(shared_library, $1.to_i(16)) else raise "Could not find #{shared_library}##{name} using #{command.inspect}." end end |
#run(command) ⇒ Object
100 101 102 103 104 |
# File 'lib/c_location/resolver.rb', line 100 def run(command) `#{command}`.tap do |output| raise "Failed to run #{command.inspect}: #{output}" unless $?.success? end end |
#source_location ⇒ Object
10 11 12 13 14 15 16 |
# File 'lib/c_location/resolver.rb', line 10 def source_location if RUBY_PLATFORM =~ /darwin/ nm(shared_library, offset) else objdump(shared_library, offset) end end |
#which_nm ⇒ Object
74 75 76 77 78 79 80 81 |
# File 'lib/c_location/resolver.rb', line 74 def which_nm nm = `which nm`.chomp return nm if $?.success? raise "You need to have `nm` installed to use c_location. " + "Try installing Xcode from the App Store. (GNU nm from binutils doesn't work unfortunately)" end |
#which_objdump ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/c_location/resolver.rb', line 62 def which_objdump objdump = `which gobjdump`.chomp return objdump if $?.success? objdump = `which objdump`.chomp return objdump if $?.success? objdump = `which /usr/local/bin/gobjdump`.chomp return objdump if $?.success? raise "You need to have `objdump` installed to use c_location. " + "Try installing the binutils package (apt-get install binutils; brew install binutils)." end |