indis-macho 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +1 -2
- data/indis-macho.gemspec +1 -1
- data/lib/indis-macho.rb +41 -6
- data/lib/indis-macho/command.rb +78 -1
- data/lib/indis-macho/dyld_info_parser.rb +127 -0
- data/lib/indis-macho/symbol.rb +34 -30
- data/lib/indis-macho/version.rb +1 -1
- data/spec/indis-macho/macho_spec.rb +29 -5
- metadata +7 -6
data/README.md
CHANGED
data/indis-macho.gemspec
CHANGED
data/lib/indis-macho.rb
CHANGED
@@ -105,6 +105,7 @@ module Indis
|
|
105
105
|
build_segments
|
106
106
|
build_dylibs if self.flags.include? :MH_TWOLEVEL
|
107
107
|
build_symbols
|
108
|
+
build_indirect_symbols
|
108
109
|
end
|
109
110
|
|
110
111
|
def flags
|
@@ -115,6 +116,26 @@ module Indis
|
|
115
116
|
f
|
116
117
|
end
|
117
118
|
|
119
|
+
def resolve_symbol_at_address(vmaddr)
|
120
|
+
segcommands = @commands.map{ |c| c if c.is_a?(Indis::MachO::SegmentCommand) }.compact
|
121
|
+
seg = segcommands.find { |seg| vmaddr >= seg.vmaddr && vmaddr < seg.vmaddr+seg.vmsize }
|
122
|
+
return nil unless seg
|
123
|
+
|
124
|
+
ok_types = [:S_NON_LAZY_SYMBOL_POINTERS, :S_LAZY_SYMBOL_POINTERS, :S_LAZY_DYLIB_SYMBOL_POINTERS,
|
125
|
+
:S_THREAD_LOCAL_VARIABLE_POINTERS, :S_SYMBOL_STUBS]
|
126
|
+
sect = seg.sections.find { |sec| vmaddr >= sec.addr && vmaddr < sec.addr+sec.size && ok_types.include?(sec.type) }
|
127
|
+
return nil unless sect
|
128
|
+
|
129
|
+
stride = sect.type == :S_SYMBOL_STUBS ? sect.reserved2 : 4 # cctools/otool/ofile_print.c:8105
|
130
|
+
index = sect.reserved1 + (vmaddr - sect.addr) / stride
|
131
|
+
|
132
|
+
return nil if index >= @indirect_symbols.length
|
133
|
+
|
134
|
+
symb = @symbols[@indirect_symbols[index]].name
|
135
|
+
@target.publish_event(:macho_indirect_symbol_resolved, vmaddr, symb)
|
136
|
+
symb
|
137
|
+
end
|
138
|
+
|
118
139
|
private
|
119
140
|
def validate_format
|
120
141
|
raise "Not a Mach-O" if @io.length < 4
|
@@ -145,6 +166,7 @@ module Indis
|
|
145
166
|
begin
|
146
167
|
c = Indis::MachO::Command.class_of_command(cmd).new(cmd, size, @io)
|
147
168
|
@commands << c
|
169
|
+
@target.publish_event(:macho_command_processed, c)
|
148
170
|
rescue Indis::MachO::UnknownCommandError
|
149
171
|
print "Unknown command #{cmd} size #{size}, skipping\n"
|
150
172
|
@io.read(size-8)
|
@@ -173,11 +195,13 @@ module Indis
|
|
173
195
|
@target.io.pos = cmd.fileoff
|
174
196
|
seg = Indis::Segment.new(@target, name, cmd.vmaddr, cmd.vmsize, cmd.fileoff, @target.io.read(cmd.filesize))
|
175
197
|
@target.segments << seg
|
198
|
+
@target.publish_event(:target_segment_processed, seg)
|
176
199
|
|
177
200
|
cmd.sections.each do |sec|
|
178
201
|
sec.index = @indexed_sections.length
|
179
|
-
s = Indis::Section.new(seg, sec.sectname, sec.addr, sec.size, sec.offset)
|
202
|
+
s = Indis::Section.new(seg, sec.sectname, sec.addr, sec.size, sec.offset, sec.type, sec.attributes)
|
180
203
|
seg.sections << s
|
204
|
+
@target.publish_event(:target_section_processed, s)
|
181
205
|
@indexed_sections << s
|
182
206
|
end
|
183
207
|
end
|
@@ -194,13 +218,16 @@ module Indis
|
|
194
218
|
end
|
195
219
|
|
196
220
|
def build_symbols
|
197
|
-
symtabcommand = @commands.
|
221
|
+
symtabcommand = @commands.find{ |c| c.is_a?(Indis::MachO::SymTabCommand) }
|
198
222
|
return if symtabcommand.length == 0
|
199
223
|
|
200
|
-
@
|
224
|
+
@symbols = symtabcommand.symbols
|
225
|
+
|
226
|
+
@target.symbols = []
|
201
227
|
|
202
|
-
|
203
|
-
|
228
|
+
symtabcommand.symbols.each do |sym|
|
229
|
+
next if sym.stab?
|
230
|
+
|
204
231
|
sec = if sym.sect > 0
|
205
232
|
@indexed_sections[sym.sect]
|
206
233
|
else
|
@@ -215,9 +242,17 @@ module Indis
|
|
215
242
|
end
|
216
243
|
|
217
244
|
s = Indis::Symbol.new(sym.name, sec, dy, sym.value, sym)
|
218
|
-
@target.symbols
|
245
|
+
@target.symbols << s
|
246
|
+
@target.publish_event(:target_symbol_processed, s)
|
219
247
|
end
|
220
248
|
end
|
249
|
+
|
250
|
+
def build_indirect_symbols
|
251
|
+
dysymtabcommand = @commands.find{ |c| c.is_a?(Indis::MachO::DySymTabCommand) }
|
252
|
+
return if !dysymtabcommand || dysymtabcommand.length == 0
|
253
|
+
|
254
|
+
@indirect_symbols = dysymtabcommand.indirect_symbols
|
255
|
+
end
|
221
256
|
end
|
222
257
|
|
223
258
|
end
|
data/lib/indis-macho/command.rb
CHANGED
@@ -17,6 +17,7 @@
|
|
17
17
|
##############################################################################
|
18
18
|
|
19
19
|
require 'indis-macho/symbol'
|
20
|
+
require 'indis-macho/dyld_info_parser'
|
20
21
|
|
21
22
|
module Indis
|
22
23
|
module MachO
|
@@ -140,11 +141,53 @@ module Indis
|
|
140
141
|
class SectionSubCommand < Command # LC_SEGMENT.sub
|
141
142
|
f_string :sectname, 16
|
142
143
|
f_string :segname, 16
|
143
|
-
f_uint32 :addr, :size, :offset, :align, :reloff, :nreloc, :flags, :reserved1, :
|
144
|
+
f_uint32 :addr, :size, :offset, :align, :reloff, :nreloc, :flags, :reserved1, :reserved2
|
144
145
|
attr_accessor :index
|
146
|
+
attr_reader :type, :attributes
|
147
|
+
|
148
|
+
SECTION_TYPE_MASK = 0x000000ff
|
149
|
+
SECTION_ATTRIBUTES_MASK = 0xffffff00
|
150
|
+
|
151
|
+
SECTION_TYPE = {
|
152
|
+
0x00 => :S_REGULAR, # regular section
|
153
|
+
0x01 => :S_ZEROFILL, # zero-fill on demand section
|
154
|
+
0x02 => :S_CSTRING_LITERALS, # section with only literal C strings
|
155
|
+
0x03 => :S_4BYTE_LITERALS, # section with only 4 byte literals
|
156
|
+
0x04 => :S_8BYTE_LITERALS, # section with only 8 byte literals
|
157
|
+
0x05 => :S_LITERAL_POINTERS, # section with only pointers to literals
|
158
|
+
0x06 => :S_NON_LAZY_SYMBOL_POINTERS, # section with only non-lazy symbol pointers
|
159
|
+
0x07 => :S_LAZY_SYMBOL_POINTERS, # section with only lazy symbol pointers
|
160
|
+
0x08 => :S_SYMBOL_STUBS, # section with only symbol stubs (s.a. byte size of stub in the reserved2)
|
161
|
+
0x09 => :S_MOD_INIT_FUNC_POINTERS, # section with only function pointers for initialization
|
162
|
+
0x0a => :S_MOD_TERM_FUNC_POINTERS, # section with only function pointers for termination
|
163
|
+
0x0b => :S_COALESCED, # section contains symbols that are to be coalesced
|
164
|
+
0x0c => :S_GB_ZEROFILL, # zero fill on demand section (>4Gb)
|
165
|
+
0x0d => :S_INTERPOSING, # section with only pairs of function pointers for interposing
|
166
|
+
0x0e => :S_16BYTE_LITERALS, # section with only 16 byte literals
|
167
|
+
0x0f => :S_DTRACE_DOF, # section contains DTrace Object Format
|
168
|
+
0x10 => :S_LAZY_DYLIB_SYMBOL_POINTERS, # section with only lazy symbol pointers to lazy loaded dylibs
|
169
|
+
0x11 => :S_THREAD_LOCAL_REGULAR, # template of initial values for TLVs
|
170
|
+
0x12 => :S_THREAD_LOCAL_ZEROFILL, # template of initial values for TLVs (zero-filled on demand?)
|
171
|
+
0x13 => :S_THREAD_LOCAL_VARIABLES, # TLV descriptors
|
172
|
+
0x14 => :S_THREAD_LOCAL_VARIABLE_POINTERS, # pointers to TLV descriptors
|
173
|
+
0x15 => :S_THREAD_LOCAL_INIT_FUNCTION_POINTERS, # functions to call to initialize TLV values
|
174
|
+
}
|
175
|
+
|
176
|
+
SECTION_ATTRIBUTES = {
|
177
|
+
0x80000000 => :S_ATTR_PURE_INSTRUCTIONS, # section contains only true machine instructions
|
178
|
+
0x40000000 => :S_ATTR_NO_TOC, # section contains coalesced symbols that are not to be in a ranlib table of contents
|
179
|
+
0x20000000 => :S_ATTR_STRIP_STATIC_SYMS, # ok to strip static symbols in this section in files with the MH_DYLDLINK flag
|
180
|
+
0x10000000 => :S_ATTR_NO_DEAD_STRIP, # no dead stripping
|
181
|
+
0x08000000 => :S_ATTR_LIVE_SUPPORT, # blocks are live if they reference live blocks
|
182
|
+
0x04000000 => :S_ATTR_SELF_MODIFYING_CODE, # Used with i386 code stubs written on by dyld
|
183
|
+
# s.a. S_ATTR_DEBUG & friends in loader.h
|
184
|
+
}
|
145
185
|
|
146
186
|
def initialize(payload)
|
147
187
|
process(payload)
|
188
|
+
@type = SECTION_TYPE[@flags & SECTION_TYPE_MASK]
|
189
|
+
atr = @falgs & SECTION_ATTRIBUTES_MASK
|
190
|
+
@attributes = SECTION_ATTRIBUTES.map { |k,v| (atr & k == k) ? v : nil }.compact
|
148
191
|
end
|
149
192
|
end
|
150
193
|
|
@@ -191,6 +234,16 @@ module Indis
|
|
191
234
|
f_uint32 :ilocalsym, :nlocalsym, :iextdefsym, :nextdefsym, :iundefsym, :nundefsym, :tocoff,
|
192
235
|
:ntoc, :modtaboff, :nmodtab, :extrefsymoff, :nextrefsyms, :indirectsymoff, :nindirectsyms,
|
193
236
|
:extreloff, :nextrel, :locreloff, :nlocrel
|
237
|
+
attr_reader :indirect_symbols
|
238
|
+
|
239
|
+
def process(payload)
|
240
|
+
super(payload)
|
241
|
+
|
242
|
+
ofs = payload.pos
|
243
|
+
payload.pos = @indirectsymoff
|
244
|
+
@indirect_symbols = payload.read(@nindirectsyms * 4).unpack('V*')
|
245
|
+
payload.pos = ofs
|
246
|
+
end
|
194
247
|
end
|
195
248
|
|
196
249
|
class LoadDyLinkerCommand < Command # LC_LOAD_DYLINKER
|
@@ -265,6 +318,30 @@ module Indis
|
|
265
318
|
class DyldInfoOnlyCommand < Command # LC_DYLD_INFO_ONLY
|
266
319
|
f_uint32 :rebase_off, :rebase_size, :bind_off, :bind_size, :weak_bind_off, :weak_bind_size,
|
267
320
|
:lazy_bind_off, :lazy_bind_size, :export_off, :export_size
|
321
|
+
attr_reader :bind_symbols, :weak_bind_symbols, :lazy_bind_symbols
|
322
|
+
|
323
|
+
def process(payload)
|
324
|
+
super(payload)
|
325
|
+
|
326
|
+
# TODO: rebase
|
327
|
+
|
328
|
+
off = payload.pos
|
329
|
+
payload.pos = @bind_off
|
330
|
+
bind = payload.read(@bind_size)
|
331
|
+
@bind_symbols = DyldInfoParser.new(bind).parse if @bind_size > 0
|
332
|
+
|
333
|
+
payload.pos = @weak_bind_off
|
334
|
+
weak_bind = payload.read(@weak_bind_size)
|
335
|
+
@weak_bind_symbols = DyldInfoParser.new(weak_bind).parse if @weak_bind_size > 0
|
336
|
+
|
337
|
+
payload.pos = @lazy_bind_off
|
338
|
+
lazy_bind = payload.read(@lazy_bind_size)
|
339
|
+
@lazy_bind_symbols = DyldInfoParser.new(lazy_bind).parse if @lazy_bind_size > 0
|
340
|
+
|
341
|
+
# TODO: export
|
342
|
+
|
343
|
+
payload.pos = off
|
344
|
+
end
|
268
345
|
end
|
269
346
|
|
270
347
|
end
|
@@ -0,0 +1,127 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# Indis framework #
|
3
|
+
# Copyright (C) 2012 Vladimir "Farcaller" Pouzanov <farcaller@gmail.com> #
|
4
|
+
# #
|
5
|
+
# This program is free software: you can redistribute it and/or modify #
|
6
|
+
# it under the terms of the GNU General Public License as published by #
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or #
|
8
|
+
# (at your option) any later version. #
|
9
|
+
# #
|
10
|
+
# This program is distributed in the hope that it will be useful, #
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
13
|
+
# GNU General Public License for more details. #
|
14
|
+
# #
|
15
|
+
# You should have received a copy of the GNU General Public License #
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
17
|
+
##############################################################################
|
18
|
+
|
19
|
+
module Indis
|
20
|
+
module MachO
|
21
|
+
|
22
|
+
class DyldInfoParser
|
23
|
+
BIND_OPCODE_MASK = 0xF0
|
24
|
+
BIND_IMMEDIATE_MASK = 0x0F
|
25
|
+
|
26
|
+
BIND_OPCODES = {
|
27
|
+
0x00 => :BIND_OPCODE_DONE,
|
28
|
+
0x10 => :BIND_OPCODE_SET_DYLIB_ORDINAL_IMM,
|
29
|
+
0x20 => :BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB,
|
30
|
+
0x30 => :BIND_OPCODE_SET_DYLIB_SPECIAL_IMM,
|
31
|
+
0x40 => :BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM,
|
32
|
+
0x50 => :BIND_OPCODE_SET_TYPE_IMM,
|
33
|
+
0x60 => :BIND_OPCODE_SET_ADDEND_SLEB,
|
34
|
+
0x70 => :BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB,
|
35
|
+
0x80 => :BIND_OPCODE_ADD_ADDR_ULEB,
|
36
|
+
0x90 => :BIND_OPCODE_DO_BIND,
|
37
|
+
0xA0 => :BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB,
|
38
|
+
0xB0 => :BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED,
|
39
|
+
0xC0 => :BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB,
|
40
|
+
}
|
41
|
+
|
42
|
+
TYPE_IMM = {
|
43
|
+
1 => :POINTER,
|
44
|
+
2 => :TEXT_ABSOLUTE32,
|
45
|
+
3 => :TEXT_PCREL32,
|
46
|
+
}
|
47
|
+
|
48
|
+
def initialize(bytes)
|
49
|
+
@bytes = StringIO.new(bytes)
|
50
|
+
end
|
51
|
+
|
52
|
+
def parse
|
53
|
+
syms = []
|
54
|
+
sym = {offset: 0}
|
55
|
+
begin
|
56
|
+
|
57
|
+
b = pop
|
58
|
+
opcode = BIND_OPCODES[b & BIND_OPCODE_MASK]
|
59
|
+
imm = b & BIND_IMMEDIATE_MASK
|
60
|
+
#puts "** OPCODE #{opcode} IMM #{imm}"
|
61
|
+
case opcode
|
62
|
+
when :BIND_OPCODE_SET_DYLIB_ORDINAL_IMM
|
63
|
+
sym[:library] = imm
|
64
|
+
when :BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM
|
65
|
+
sym[:flags] = []
|
66
|
+
sym[:flags] << :WEAK_IMPORT if imm & 1 == 1
|
67
|
+
sym[:flags] << :NON_WEAK_DEFINITION if imm & 8 == 8
|
68
|
+
|
69
|
+
nm = ''
|
70
|
+
c = pop
|
71
|
+
while c != 0 do
|
72
|
+
nm += c.chr
|
73
|
+
c = pop
|
74
|
+
end
|
75
|
+
sym[:name] = nm
|
76
|
+
when :BIND_OPCODE_SET_TYPE_IMM
|
77
|
+
#puts "Unknown type #{imm}" unless TYPE_IMM[imm]
|
78
|
+
sym[:type] = TYPE_IMM[imm] || imm
|
79
|
+
when :BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
|
80
|
+
sym[:segment] = imm
|
81
|
+
sym[:offset] = pop_uleb
|
82
|
+
when :BIND_OPCODE_DONE
|
83
|
+
#break
|
84
|
+
when :BIND_OPCODE_DO_BIND
|
85
|
+
syms << sym.dup
|
86
|
+
sym[:offset] += 4
|
87
|
+
when :BIND_OPCODE_ADD_ADDR_ULEB
|
88
|
+
u = pop_uleb
|
89
|
+
sym[:offset] += u
|
90
|
+
when :BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED
|
91
|
+
syms << sym.dup
|
92
|
+
sym[:offset] += 4 + imm*4
|
93
|
+
when :BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB
|
94
|
+
count = pop_uleb
|
95
|
+
skip = pop_uleb
|
96
|
+
count.times do
|
97
|
+
syms << sym.dup
|
98
|
+
sym[:offset] += skip + 4
|
99
|
+
end
|
100
|
+
else
|
101
|
+
raise "unknown opcode #{opcode} #{(b & BIND_OPCODE_MASK).to_s 16}"
|
102
|
+
end
|
103
|
+
sym[:offset] &= 0xffffffff
|
104
|
+
end while @bytes.pos < @bytes.length
|
105
|
+
syms
|
106
|
+
end
|
107
|
+
|
108
|
+
private
|
109
|
+
def pop
|
110
|
+
@bytes.read(1).ord
|
111
|
+
end
|
112
|
+
|
113
|
+
def pop_uleb
|
114
|
+
result = 0
|
115
|
+
bit = 0
|
116
|
+
begin
|
117
|
+
p = pop
|
118
|
+
slice = p & 0x7f
|
119
|
+
result |= (slice << bit)
|
120
|
+
bit += 7
|
121
|
+
end while p & 0x80 != 0
|
122
|
+
result
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
data/lib/indis-macho/symbol.rb
CHANGED
@@ -32,35 +32,35 @@ module Indis
|
|
32
32
|
0xa => :INDR,
|
33
33
|
}
|
34
34
|
STAB = {
|
35
|
-
0x20 => :N_GSYM,
|
36
|
-
0x22 => :N_FNAME,
|
37
|
-
0x24 => :N_FUN,
|
38
|
-
0x26 => :N_STSYM,
|
39
|
-
0x28 => :N_LCSYM,
|
40
|
-
0x2e => :N_BNSYM,
|
41
|
-
0x3c => :N_OPT,
|
42
|
-
0x40 => :N_RSYM,
|
43
|
-
0x44 => :N_SLINE,
|
44
|
-
0x4e => :N_ENSYM,
|
45
|
-
0x60 => :N_SSYM,
|
46
|
-
0x64 => :N_SO,
|
47
|
-
0x66 => :N_OSO,
|
48
|
-
0x80 => :N_LSYM,
|
49
|
-
0x82 => :N_BINCL,
|
50
|
-
0x84 => :N_SOL,
|
51
|
-
0x86 => :N_PARAMS,
|
52
|
-
0x88 => :N_VERSION,
|
53
|
-
0x8A => :N_OLEVEL,
|
54
|
-
0xa0 => :N_PSYM,
|
55
|
-
0xa2 => :N_EINCL,
|
56
|
-
0xa4 => :N_ENTRY,
|
57
|
-
0xc0 => :N_LBRAC,
|
58
|
-
0xc2 => :N_EXCL,
|
59
|
-
0xe0 => :N_RBRAC,
|
60
|
-
0xe2 => :N_BCOMM,
|
61
|
-
0xe4 => :N_ECOMM,
|
62
|
-
0xe8 => :N_ECOML,
|
63
|
-
0xfe => :N_LENG,
|
35
|
+
0x20 => :N_GSYM, # global symbol
|
36
|
+
0x22 => :N_FNAME, # procedure name (f77 kludge)
|
37
|
+
0x24 => :N_FUN, # procedure name
|
38
|
+
0x26 => :N_STSYM, # static symbol
|
39
|
+
0x28 => :N_LCSYM, # .lcomm symbol
|
40
|
+
0x2e => :N_BNSYM, # begin nsect symbol
|
41
|
+
0x3c => :N_OPT, # emitted with gcc2_compiled and in gcc source
|
42
|
+
0x40 => :N_RSYM, # register symbol
|
43
|
+
0x44 => :N_SLINE, # src line
|
44
|
+
0x4e => :N_ENSYM, # end nsect symbol
|
45
|
+
0x60 => :N_SSYM, # structure elt
|
46
|
+
0x64 => :N_SO, # source file name
|
47
|
+
0x66 => :N_OSO, # object file name
|
48
|
+
0x80 => :N_LSYM, # local symbol
|
49
|
+
0x82 => :N_BINCL, # include file beginning
|
50
|
+
0x84 => :N_SOL, # #included file name
|
51
|
+
0x86 => :N_PARAMS, # compiler parameters
|
52
|
+
0x88 => :N_VERSION, # compiler version
|
53
|
+
0x8A => :N_OLEVEL, # compiler -O level
|
54
|
+
0xa0 => :N_PSYM, # parameter
|
55
|
+
0xa2 => :N_EINCL, # include file end
|
56
|
+
0xa4 => :N_ENTRY, # alternate entry
|
57
|
+
0xc0 => :N_LBRAC, # left bracket
|
58
|
+
0xc2 => :N_EXCL, # deleted include file
|
59
|
+
0xe0 => :N_RBRAC, # right bracket
|
60
|
+
0xe2 => :N_BCOMM, # begin common
|
61
|
+
0xe4 => :N_ECOMM, # end common
|
62
|
+
0xe8 => :N_ECOML, # end common (local name)
|
63
|
+
0xfe => :N_LENG, # second stab entry with length information
|
64
64
|
}
|
65
65
|
REFERENCE_TYPE_MASK = 0xf
|
66
66
|
DESC_REFERENCE = {
|
@@ -94,7 +94,11 @@ module Indis
|
|
94
94
|
@name = strtab[name_idx..-1].split("\0", 2)[0]
|
95
95
|
end
|
96
96
|
|
97
|
-
#
|
97
|
+
# if stab?
|
98
|
+
# puts ".stabs \"#{@name}\", #{STAB[@type_val]}, #{@sect}, #{self.desc}, #{@value}"
|
99
|
+
# else
|
100
|
+
# puts "SYM \"#{@name}\", #{TYPE[@type_val & TYPE_MASK]}, #{@sect}, #{self.desc}, #{@value}"
|
101
|
+
# end
|
98
102
|
end
|
99
103
|
|
100
104
|
def type
|
data/lib/indis-macho/version.rb
CHANGED
@@ -14,10 +14,11 @@ def macho_target_double(*args)
|
|
14
14
|
if o[:symbols]
|
15
15
|
target.should_receive(:symbols){ o[:symbols] }.any_number_of_times
|
16
16
|
else
|
17
|
-
target.should_receive(:symbols).any_number_of_times.and_return(
|
17
|
+
target.should_receive(:symbols).any_number_of_times.and_return([])
|
18
18
|
end
|
19
19
|
target.stub(:vamap=)
|
20
20
|
target.stub(:io).and_return(o[:io])
|
21
|
+
target.stub(:publish_event)
|
21
22
|
target
|
22
23
|
end
|
23
24
|
|
@@ -87,14 +88,37 @@ describe Indis::BinaryFormat::MachO do
|
|
87
88
|
end
|
88
89
|
|
89
90
|
it "should parse symbols" do
|
90
|
-
sym =
|
91
|
+
sym = []
|
91
92
|
io = StringIO.new(File.open('spec/fixtures/single-object.o', 'rb').read().force_encoding('BINARY'))
|
92
93
|
target = macho_target_double(io: io, symbols: sym)
|
93
94
|
|
94
95
|
m = Indis::BinaryFormat::MachO.new(target, io)
|
95
96
|
|
96
|
-
sym.
|
97
|
-
sym.
|
98
|
-
sym.
|
97
|
+
sym.find {|s| s.name == '_add' }.should be_a(Indis::Symbol)
|
98
|
+
sym.find {|s| s.name == '_sub' }.should be_a(Indis::Symbol)
|
99
|
+
sym.find {|s| s.name == '_printf' }.should be_a(Indis::Symbol)
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should parse dyld operands" do
|
103
|
+
io = StringIO.new(File.open('spec/fixtures/app-arm-release.o', 'rb').read().force_encoding('BINARY'))
|
104
|
+
target = macho_target_double(io: io)
|
105
|
+
|
106
|
+
m = Indis::BinaryFormat::MachO.new(target, io)
|
107
|
+
dysymtab = m.commands.map{ |c| c if c.is_a?(Indis::MachO::DyldInfoOnlyCommand) }.compact.first
|
108
|
+
dysymtab.bind_symbols.length.should == 20
|
109
|
+
dysymtab.weak_bind_symbols.should be_nil
|
110
|
+
dysymtab.lazy_bind_symbols.length.should == 10
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should post events while parsing" do
|
114
|
+
io = StringIO.new(File.open('spec/fixtures/app-arm-release.o', 'rb').read().force_encoding('BINARY'))
|
115
|
+
target = macho_target_double(io: io)
|
116
|
+
|
117
|
+
target.should_receive(:publish_event).with(:macho_command_processed, anything).exactly(20).times
|
118
|
+
target.should_receive(:publish_event).with(:target_segment_processed, anything).exactly(4).times
|
119
|
+
target.should_receive(:publish_event).with(:target_section_processed, anything).exactly(22).times
|
120
|
+
target.should_receive(:publish_event).with(:target_symbol_processed, anything).exactly(51).times
|
121
|
+
|
122
|
+
m = Indis::BinaryFormat::MachO.new(target, io)
|
99
123
|
end
|
100
124
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: indis-macho
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-04-
|
12
|
+
date: 2012-04-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -32,17 +32,17 @@ dependencies:
|
|
32
32
|
requirement: !ruby/object:Gem::Requirement
|
33
33
|
none: false
|
34
34
|
requirements:
|
35
|
-
- -
|
35
|
+
- - ~>
|
36
36
|
- !ruby/object:Gem::Version
|
37
|
-
version:
|
37
|
+
version: 0.1.2
|
38
38
|
type: :runtime
|
39
39
|
prerelease: false
|
40
40
|
version_requirements: !ruby/object:Gem::Requirement
|
41
41
|
none: false
|
42
42
|
requirements:
|
43
|
-
- -
|
43
|
+
- - ~>
|
44
44
|
- !ruby/object:Gem::Version
|
45
|
-
version:
|
45
|
+
version: 0.1.2
|
46
46
|
description: Mach-o format processor for indis provides support for loading mach-o
|
47
47
|
binaries for analysis
|
48
48
|
email:
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- indis-macho.gemspec
|
63
63
|
- lib/indis-macho.rb
|
64
64
|
- lib/indis-macho/command.rb
|
65
|
+
- lib/indis-macho/dyld_info_parser.rb
|
65
66
|
- lib/indis-macho/symbol.rb
|
66
67
|
- lib/indis-macho/version.rb
|
67
68
|
- spec/fixtures/app-arm-release.o
|