Class: Indis::MachO::DyldInfoParser

Inherits:
Object
  • Object
show all
Defined in:
lib/indis-macho/dyld_info_parser.rb

Constant Summary

BIND_OPCODE_MASK =
0xF0
BIND_IMMEDIATE_MASK =
0x0F
BIND_OPCODES =
{
  0x00 => :BIND_OPCODE_DONE,
  0x10 => :BIND_OPCODE_SET_DYLIB_ORDINAL_IMM,
  0x20 => :BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB,
  0x30 => :BIND_OPCODE_SET_DYLIB_SPECIAL_IMM,
  0x40 => :BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM,
  0x50 => :BIND_OPCODE_SET_TYPE_IMM,
  0x60 => :BIND_OPCODE_SET_ADDEND_SLEB,
  0x70 => :BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
  0x80 => :BIND_OPCODE_ADD_ADDR_ULEB,
  0x90 => :BIND_OPCODE_DO_BIND,
  0xA0 => :BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB,
  0xB0 => :BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED,
  0xC0 => :BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB,
}
TYPE_IMM =
{
  1 => :POINTER,
  2 => :TEXT_ABSOLUTE32,
  3 => :TEXT_PCREL32,
}

Instance Method Summary collapse

Constructor Details

#initialize(bytes) ⇒ DyldInfoParser



50
51
52
# File 'lib/indis-macho/dyld_info_parser.rb', line 50

def initialize(bytes)
  @bytes = StringIO.new(bytes)
end

Instance Method Details

#parseObject



54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'lib/indis-macho/dyld_info_parser.rb', line 54

def parse
  syms = []
  sym = {offset: 0}
  begin
    
    b = pop
    opcode = BIND_OPCODES[b & BIND_OPCODE_MASK]
    imm = b & BIND_IMMEDIATE_MASK
    #puts "** OPCODE #{opcode} IMM #{imm}"
    case opcode
    when :BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
      sym[:library] = imm
    when :BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
      sym[:flags] = []
      sym[:flags] << :WEAK_IMPORT if imm & 1 == 1
      sym[:flags] << :NON_WEAK_DEFINITION if imm & 8 == 8
      
      nm = ''
      c = pop
      while c != 0 do
        nm += c.chr
        c = pop
      end
      sym[:name] = nm
    when :BIND_OPCODE_SET_TYPE_IMM
      #puts "Unknown type #{imm}" unless TYPE_IMM[imm]
      sym[:type] = TYPE_IMM[imm] || imm
    when :BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
      sym[:segment] = imm
      sym[:offset] = pop_uleb
    when :BIND_OPCODE_DONE
      #break
    when :BIND_OPCODE_DO_BIND
      syms << sym.dup
      sym[:offset] += 4
    when :BIND_OPCODE_ADD_ADDR_ULEB
      u = pop_uleb
      sym[:offset] += u
    when :BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
      syms << sym.dup
      sym[:offset] += 4 + imm*4
    when :BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
      count = pop_uleb
      skip  = pop_uleb
      count.times do
        syms << sym.dup
        sym[:offset] += skip + 4
      end
    when :BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB
      syms << sym.dup
      sym[:offset] += 4 + pop_uleb
    when :BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB
      sym[:library] = pop_uleb
    else
      raise "unknown opcode #{opcode} #{(b & BIND_OPCODE_MASK).to_s 16}"
    end
    sym[:offset] &= 0xffffffff
  end while @bytes.pos < @bytes.length
  syms
end