indis-macho 0.2.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/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +5 -0
- data/Gemfile.ci +6 -0
- data/LICENSE +674 -0
- data/README.md +6 -0
- data/Rakefile +9 -0
- data/indis-macho.gemspec +21 -0
- data/lib/indis-macho.rb +224 -0
- data/lib/indis-macho/command.rb +271 -0
- data/lib/indis-macho/symbol.rb +143 -0
- data/lib/indis-macho/version.rb +23 -0
- data/spec/fixtures/app-arm-release.o +0 -0
- data/spec/fixtures/single-object.o +0 -0
- data/spec/indis-macho/binary_format_spec.rb +7 -0
- data/spec/indis-macho/macho_spec.rb +100 -0
- data/spec/spec_helper.rb +8 -0
- metadata +103 -0
data/README.md
ADDED
data/Rakefile
ADDED
data/indis-macho.gemspec
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/indis-macho/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Vladimir Pouzanov"]
|
6
|
+
gem.email = ["farcaller@gmail.com"]
|
7
|
+
gem.description = "Mach-o format processor for indis provides support for loading mach-o binaries for analysis"
|
8
|
+
gem.summary = "Mach-o format processor for indis"
|
9
|
+
gem.homepage = "http://www.indis.org/"
|
10
|
+
gem.license = "GPL-3"
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = "indis-macho"
|
16
|
+
gem.require_paths = ["lib"]
|
17
|
+
gem.version = Indis::MachO::VERSION
|
18
|
+
|
19
|
+
gem.add_development_dependency 'rspec'
|
20
|
+
gem.add_runtime_dependency 'indis-core'
|
21
|
+
end
|
data/lib/indis-macho.rb
ADDED
@@ -0,0 +1,224 @@
|
|
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
|
+
require 'indis-core/binary_format'
|
20
|
+
require 'indis-core/segment'
|
21
|
+
require 'indis-core/section'
|
22
|
+
require 'indis-core/symbol'
|
23
|
+
require 'indis-macho/version'
|
24
|
+
require 'indis-macho/command'
|
25
|
+
require 'indis-macho/symbol'
|
26
|
+
|
27
|
+
module Indis
|
28
|
+
module BinaryFormat
|
29
|
+
|
30
|
+
class MachO < Format
|
31
|
+
MH_MAGIC = 0xfeedface
|
32
|
+
|
33
|
+
CPUTYPE = {
|
34
|
+
12 => :CPU_TYPE_ARM
|
35
|
+
}
|
36
|
+
|
37
|
+
CPUSUBTYPE = {
|
38
|
+
5 => :CPU_SUBTYPE_ARM_V4T,
|
39
|
+
6 => :CPU_SUBTYPE_ARM_V6,
|
40
|
+
7 => :CPU_SUBTYPE_ARM_V5TEJ,
|
41
|
+
8 => :CPU_SUBTYPE_ARM_XSCALE,
|
42
|
+
9 => :CPU_SUBTYPE_ARM_V7
|
43
|
+
}
|
44
|
+
|
45
|
+
FILETYPE = {
|
46
|
+
0x1 => :MH_OBJECT,
|
47
|
+
0x2 => :MH_EXECUTE,
|
48
|
+
0x3 => :MH_FVMLIB,
|
49
|
+
0x4 => :MH_CORE,
|
50
|
+
0x5 => :MH_PRELOAD,
|
51
|
+
0x6 => :MH_DYLIB,
|
52
|
+
0x7 => :MH_DYLINKER,
|
53
|
+
0x8 => :MH_BUNDLE,
|
54
|
+
0x9 => :MH_DYLIB_STUB,
|
55
|
+
0xa => :MH_DSYM,
|
56
|
+
0xb => :MH_KEXT_BUNDLE
|
57
|
+
}
|
58
|
+
|
59
|
+
FLAGS = {
|
60
|
+
0x1 => :MH_NOUNDEFS,
|
61
|
+
0x2 => :MH_INCRLINK,
|
62
|
+
0x4 => :MH_DYLDLINK,
|
63
|
+
0x8 => :MH_BINDATLOAD,
|
64
|
+
0x10 => :MH_PREBOUND,
|
65
|
+
0x20 => :MH_SPLIT_SEGS,
|
66
|
+
0x40 => :MH_LAZY_INIT,
|
67
|
+
0x80 => :MH_TWOLEVEL,
|
68
|
+
0x100 => :MH_FORCE_FLAT,
|
69
|
+
0x200 => :MH_NOMULTIDEFS,
|
70
|
+
0x400 => :MH_NOFIXPREBINDING,
|
71
|
+
0x800 => :MH_PREBINDABLE,
|
72
|
+
0x1000 => :MH_ALLMODSBOUND,
|
73
|
+
0x2000 => :MH_SUBSECTIONS_VIA_SYMBOLS,
|
74
|
+
0x4000 => :MH_CANONICAL,
|
75
|
+
0x8000 => :MH_WEAK_DEFINES,
|
76
|
+
0x10000 => :MH_BINDS_TO_WEAK,
|
77
|
+
0x20000 => :MH_ALLOW_STACK_EXECUTION,
|
78
|
+
0x40000 => :MH_ROOT_SAFE,
|
79
|
+
0x80000 => :MH_SETUID_SAFE,
|
80
|
+
0x100000 => :MH_NO_REEXPORTED_DYLIBS,
|
81
|
+
0x200000 => :MH_PIE,
|
82
|
+
0x400000 => :MH_DEAD_STRIPPABLE_DYLIB,
|
83
|
+
0x800000 => :MH_HAS_TLV_DESCRIPTORS,
|
84
|
+
0x1000000 => :MH_NO_HEAP_EXECUTION,
|
85
|
+
}
|
86
|
+
|
87
|
+
attr_reader :cputype, :cpusubtype, :filetype, :commands
|
88
|
+
|
89
|
+
def self.magic
|
90
|
+
MH_MAGIC
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.name
|
94
|
+
'Mach-O'
|
95
|
+
end
|
96
|
+
|
97
|
+
def initialize(target, io)
|
98
|
+
super(target, io)
|
99
|
+
|
100
|
+
@commands = []
|
101
|
+
|
102
|
+
parse_header
|
103
|
+
parse_commands
|
104
|
+
|
105
|
+
build_segments
|
106
|
+
build_dylibs if self.flags.include? :MH_TWOLEVEL
|
107
|
+
build_symbols
|
108
|
+
end
|
109
|
+
|
110
|
+
def flags
|
111
|
+
f = []
|
112
|
+
FLAGS.each_pair do |k, v|
|
113
|
+
f << v if @flags_val & k == k
|
114
|
+
end
|
115
|
+
f
|
116
|
+
end
|
117
|
+
|
118
|
+
private
|
119
|
+
def validate_format
|
120
|
+
raise "Not a Mach-O" if @io.length < 4
|
121
|
+
magic = @io.read(4).unpack('V')[0]
|
122
|
+
raise "Bad magic" unless magic == MH_MAGIC
|
123
|
+
@io.seek(-4, IO::SEEK_CUR)
|
124
|
+
end
|
125
|
+
|
126
|
+
def parse_header
|
127
|
+
validate_format
|
128
|
+
|
129
|
+
@magic, @cputype, @cpusubtype, @filetype, @ncmds, @sizeofcmds, @flags_val = @io.read(7*4).unpack('VVVVVVV')
|
130
|
+
|
131
|
+
@cputype = CPUTYPE[@cputype]
|
132
|
+
raise "Unknown CPU type" unless @cputype
|
133
|
+
|
134
|
+
@cpusubtype = CPUSUBTYPE[@cpusubtype]
|
135
|
+
raise "Unknown CPU subtype" unless @cpusubtype
|
136
|
+
|
137
|
+
@filetype = FILETYPE[@filetype]
|
138
|
+
raise "Unknown file type" unless @filetype
|
139
|
+
end
|
140
|
+
|
141
|
+
def parse_commands
|
142
|
+
@ncmds.times do
|
143
|
+
cmd, size = @io.read(2*4).unpack('VV')
|
144
|
+
|
145
|
+
begin
|
146
|
+
c = Indis::MachO::Command.class_of_command(cmd).new(cmd, size, @io)
|
147
|
+
@commands << c
|
148
|
+
rescue Indis::MachO::UnknownCommandError
|
149
|
+
print "Unknown command #{cmd} size #{size}, skipping\n"
|
150
|
+
@io.read(size-8)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def build_segments
|
156
|
+
@indexed_sections = [nil]
|
157
|
+
segcommands = @commands.map{ |c| c if c.is_a?(Indis::MachO::SegmentCommand) }.compact
|
158
|
+
|
159
|
+
@target.segments = []
|
160
|
+
|
161
|
+
pos = @target.io.pos
|
162
|
+
segcommands.each do |cmd|
|
163
|
+
name = if cmd.segname.length > 0
|
164
|
+
cmd.segname
|
165
|
+
else
|
166
|
+
if cmd.sections.length > 0 && cmd.sections.first.segname.length > 0
|
167
|
+
cmd.sections.first.segname
|
168
|
+
else
|
169
|
+
name = '*NONAME*'
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
@target.io.pos = cmd.fileoff
|
174
|
+
seg = Indis::Segment.new(@target, name, cmd.vmaddr, cmd.vmsize, cmd.fileoff, @target.io.read(cmd.filesize))
|
175
|
+
@target.segments << seg
|
176
|
+
|
177
|
+
cmd.sections.each do |sec|
|
178
|
+
sec.index = @indexed_sections.length
|
179
|
+
s = Indis::Section.new(seg, sec.sectname, sec.addr, sec.size, sec.offset)
|
180
|
+
seg.sections << s
|
181
|
+
@indexed_sections << s
|
182
|
+
end
|
183
|
+
end
|
184
|
+
@target.io.pos = pos
|
185
|
+
end
|
186
|
+
|
187
|
+
def build_dylibs
|
188
|
+
@indexed_dylibs = [nil]
|
189
|
+
dylibcommands = @commands.map{ |c| c if c.is_a?(Indis::MachO::LoadDyLibCommand) }.compact
|
190
|
+
|
191
|
+
dylibcommands.each do |dy|
|
192
|
+
@indexed_dylibs << dy.name
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
def build_symbols
|
197
|
+
symtabcommand = @commands.map{ |c| c if c.is_a?(Indis::MachO::SymTabCommand) }.compact
|
198
|
+
return if symtabcommand.length == 0
|
199
|
+
|
200
|
+
@target.symbols = {}
|
201
|
+
|
202
|
+
cmd = symtabcommand.first
|
203
|
+
cmd.symbols.each do |sym|
|
204
|
+
sec = if sym.sect > 0
|
205
|
+
@indexed_sections[sym.sect]
|
206
|
+
else
|
207
|
+
nil
|
208
|
+
end
|
209
|
+
|
210
|
+
dy = if self.flags.include? :MH_TWOLEVEL
|
211
|
+
l2 = sym.twolevel_library_ordinal
|
212
|
+
@indexed_dylibs[l2] if l2.is_a? Fixnum
|
213
|
+
else
|
214
|
+
nil
|
215
|
+
end
|
216
|
+
|
217
|
+
s = Indis::Symbol.new(sym.name, sec, dy, sym.value, sym)
|
218
|
+
@target.symbols[sym.name] = s
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,271 @@
|
|
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
|
+
require 'indis-macho/symbol'
|
20
|
+
|
21
|
+
module Indis
|
22
|
+
module MachO
|
23
|
+
|
24
|
+
class UnknownCommandError < RuntimeError; end
|
25
|
+
|
26
|
+
class Command
|
27
|
+
LC_REQ_DYLD = 0x80000000
|
28
|
+
|
29
|
+
CMD = {
|
30
|
+
0x1 => :LC_SEGMENT,
|
31
|
+
0x2 => :LC_SYMTAB,
|
32
|
+
0x3 => :LC_SYMSEG,
|
33
|
+
0x4 => :LC_THREAD,
|
34
|
+
0x5 => :LC_UNIXTHREAD,
|
35
|
+
0x6 => :LC_LOADFVMLIB,
|
36
|
+
0x7 => :LC_IDFVMLIB,
|
37
|
+
0x8 => :LC_IDENT,
|
38
|
+
0x9 => :LC_FVMFILE,
|
39
|
+
0xa => :LC_PREPAGE,
|
40
|
+
0xb => :LC_DYSYMTAB,
|
41
|
+
0xc => :LC_LOAD_DYLIB,
|
42
|
+
0xd => :LC_ID_DYLIB,
|
43
|
+
0xe => :LC_LOAD_DYLINKER,
|
44
|
+
0xf => :LC_ID_DYLINKER,
|
45
|
+
0x10 => :LC_PREBOUND_DYLIB,
|
46
|
+
0x11 => :LC_ROUTINES,
|
47
|
+
0x12 => :LC_SUB_FRAMEWORK,
|
48
|
+
0x13 => :LC_SUB_UMBRELLA,
|
49
|
+
0x14 => :LC_SUB_CLIENT,
|
50
|
+
0x15 => :LC_SUB_LIBRARY,
|
51
|
+
0x16 => :LC_TWOLEVEL_HINTS,
|
52
|
+
0x17 => :LC_PREBIND_CKSUM,
|
53
|
+
|
54
|
+
0x18 | LC_REQ_DYLD => :LC_LOAD_WEAK_DYLIB,
|
55
|
+
0x19 => :LC_SEGMENT_64,
|
56
|
+
0x1a => :LC_ROUTINES_64,
|
57
|
+
0x1b => :LC_UUID,
|
58
|
+
0x1c | LC_REQ_DYLD => :LC_RPATH,
|
59
|
+
0x1d => :LC_CODE_SIGNATURE,
|
60
|
+
0x1e => :LC_SEGMENT_SPLIT_INFO,
|
61
|
+
0x1f | LC_REQ_DYLD => :LC_REEXPORT_DYLIB,
|
62
|
+
0x20 => :LC_LAZY_LOAD_DYLIB,
|
63
|
+
0x21 => :LC_ENCRYPTION_INFO,
|
64
|
+
0x22 => :LC_DYLD_INFO,
|
65
|
+
0x22|LC_REQ_DYLD => :LC_DYLD_INFO_ONLY,
|
66
|
+
|
67
|
+
0x23 | LC_REQ_DYLD => :LC_LOAD_UPWARD_DYLIB,
|
68
|
+
0x24 => :LC_VERSION_MIN_MACOSX,
|
69
|
+
0x25 => :LC_VERSION_MIN_IPHONEOS,
|
70
|
+
0x26 => :LC_FUNCTION_STARTS,
|
71
|
+
0x27 => :LC_DYLD_ENVIRONMENT,
|
72
|
+
}
|
73
|
+
|
74
|
+
CMD_CLASS = {
|
75
|
+
LC_SEGMENT: :SegmentCommand,
|
76
|
+
LC_DYLD_INFO_ONLY: :DyldInfoOnlyCommand,
|
77
|
+
LC_SYMTAB: :SymTabCommand,
|
78
|
+
LC_DYSYMTAB: :DySymTabCommand,
|
79
|
+
LC_LOAD_DYLINKER: :LoadDyLinkerCommand,
|
80
|
+
LC_UUID: :UUIDCommand,
|
81
|
+
LC_UNIXTHREAD: :ARMUnixThreadCommand,
|
82
|
+
LC_ENCRYPTION_INFO: :EncryptionInfoCommand,
|
83
|
+
LC_LOAD_DYLIB: :LoadDyLibCommand,
|
84
|
+
LC_CODE_SIGNATURE: :CodeSignatureCommand,
|
85
|
+
LC_VERSION_MIN_IPHONEOS: :VersionMinIPhoneOSCommand,
|
86
|
+
LC_FUNCTION_STARTS: :FunctionStartsCommand,
|
87
|
+
}
|
88
|
+
|
89
|
+
attr_reader :cmd, :length
|
90
|
+
|
91
|
+
def initialize(cmd, length, payload)
|
92
|
+
@cmd = CMD[cmd]
|
93
|
+
@length = length
|
94
|
+
raise "Unknown mach-o command" unless @cmd
|
95
|
+
|
96
|
+
process(payload)
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.class_of_command(c)
|
100
|
+
cmd = CMD[c]
|
101
|
+
raise UnknownCommandError, "Unknown mach-o command #{c.to_s(16)}" unless cmd
|
102
|
+
clsnm = CMD_CLASS[cmd]
|
103
|
+
raise "Unsupported mach-o command #{c.to_s(16)} (#{cmd})" unless clsnm
|
104
|
+
cls = Indis::MachO.const_get(clsnm)
|
105
|
+
end
|
106
|
+
|
107
|
+
private
|
108
|
+
def process(payload)
|
109
|
+
return unless self.class.fields
|
110
|
+
self.class.fields.each do |f|
|
111
|
+
case f[0]
|
112
|
+
when :string
|
113
|
+
s = payload.read(f[2]).strip.gsub("\0", "")
|
114
|
+
instance_variable_set("@#{f[1]}".to_sym, s)
|
115
|
+
when :uint32
|
116
|
+
instance_variable_set("@#{f[1]}".to_sym, payload.read(4).unpack('V')[0])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.f_string(name, sz)
|
122
|
+
@fields ||= []
|
123
|
+
@fields << [:string, name, sz]
|
124
|
+
attr_reader name.to_sym
|
125
|
+
end
|
126
|
+
|
127
|
+
def self.f_uint32(*names)
|
128
|
+
@fields ||= []
|
129
|
+
names.each do |nm|
|
130
|
+
@fields << [:uint32, nm]
|
131
|
+
attr_reader nm.to_sym
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def self.fields
|
136
|
+
@fields
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
class SectionSubCommand < Command # LC_SEGMENT.sub
|
141
|
+
f_string :sectname, 16
|
142
|
+
f_string :segname, 16
|
143
|
+
f_uint32 :addr, :size, :offset, :align, :reloff, :nreloc, :flags, :reserved1, :reseved2
|
144
|
+
attr_accessor :index
|
145
|
+
|
146
|
+
def initialize(payload)
|
147
|
+
process(payload)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
class SegmentCommand < Command # LC_SEGMENT
|
152
|
+
f_string :segname, 16
|
153
|
+
f_uint32 :vmaddr, :vmsize, :fileoff, :filesize, :maxprot, :initprot, :nsects, :flags
|
154
|
+
attr_reader :sections
|
155
|
+
|
156
|
+
def process(payload)
|
157
|
+
super(payload)
|
158
|
+
|
159
|
+
@sections = []
|
160
|
+
@nsects.times do
|
161
|
+
s = SectionSubCommand.new(payload)
|
162
|
+
@sections << s
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class SymTabCommand < Command # LC_SYMTAB
|
168
|
+
f_uint32 :symoff, :nsyms, :stroff, :strsize
|
169
|
+
attr_reader :symbols
|
170
|
+
|
171
|
+
def process(payload)
|
172
|
+
super(payload)
|
173
|
+
|
174
|
+
pos = payload.pos
|
175
|
+
|
176
|
+
payload.pos = @stroff
|
177
|
+
strings = payload.read(@strsize)
|
178
|
+
|
179
|
+
payload.pos = @symoff
|
180
|
+
@symbols = []
|
181
|
+
|
182
|
+
@nsyms.times do |n|
|
183
|
+
s = Indis::MachO::Symbol.new(payload, strings)
|
184
|
+
@symbols << s
|
185
|
+
end
|
186
|
+
payload.pos = pos
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
class DySymTabCommand < Command # LC_DYSYMTAB
|
191
|
+
f_uint32 :ilocalsym, :nlocalsym, :iextdefsym, :nextdefsym, :iundefsym, :nundefsym, :tocoff,
|
192
|
+
:ntoc, :modtaboff, :nmodtab, :extrefsymoff, :nextrefsyms, :indirectsymoff, :nindirectsyms,
|
193
|
+
:extreloff, :nextrel, :locreloff, :nlocrel
|
194
|
+
end
|
195
|
+
|
196
|
+
class LoadDyLinkerCommand < Command # LC_LOAD_DYLINKER
|
197
|
+
attr_reader :name
|
198
|
+
|
199
|
+
def process(payload)
|
200
|
+
super(payload)
|
201
|
+
@name = payload.read(@length-8).strip
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
class UUIDCommand < Command # LC_UUID
|
206
|
+
attr_reader :UUID
|
207
|
+
|
208
|
+
def process(payload)
|
209
|
+
super(payload)
|
210
|
+
@UUID = payload.read(16)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
class ARMUnixThreadCommand < Command # LC_UNIXTHREAD
|
215
|
+
REGISTERS = [:r0, :r1, :r2, :r3, :r4, :r5, :r6, :r7, :r8, :r9, :r10, :r11, :r12, :sp, :lr, :pc, :cpsr]
|
216
|
+
f_uint32 :flavor, :count
|
217
|
+
attr_reader :registers
|
218
|
+
|
219
|
+
def process(payload)
|
220
|
+
super(payload)
|
221
|
+
# XXX: this one parses only ARM thread state, need to get back to mach-o header to know the flavor
|
222
|
+
|
223
|
+
@registers = payload.read(4*17).unpack('V'*17)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
class EncryptionInfoCommand < Command # LC_ENCRYPTION_INFO
|
228
|
+
f_uint32 :cryptoff, :cryptsize, :cryptid
|
229
|
+
end
|
230
|
+
|
231
|
+
class LoadDyLibCommand < Command # LC_LOAD_DYLIB
|
232
|
+
attr_reader :name, :timestamp, :current_version, :compatibility_version
|
233
|
+
|
234
|
+
def process(payload)
|
235
|
+
super(payload)
|
236
|
+
|
237
|
+
ofs_to_name = payload.read(4).unpack('V')[0]
|
238
|
+
|
239
|
+
@timestamp, @current_version, @compatibility_version = payload.read(4*3).unpack('VVV')
|
240
|
+
|
241
|
+
name_sz = @length - ofs_to_name - 4*3 + 8 + 4
|
242
|
+
@name = payload.read(name_sz).strip
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
class CodeSignatureCommand < Command # LC_CODE_SIGNATURE
|
247
|
+
f_uint32 :dataoff, :datasize
|
248
|
+
end
|
249
|
+
|
250
|
+
class VersionMinIPhoneOSCommand < Command # LC_VERSION_MIN_IPHONEOS
|
251
|
+
attr_reader :version, :sdk
|
252
|
+
|
253
|
+
def process(payload)
|
254
|
+
v, s = payload.read(8).unpack('VV')
|
255
|
+
|
256
|
+
@version = "#{(v & 0xffff0000) >> 16}.#{(v & 0xff00) >> 8}.#{v & 0xff}"
|
257
|
+
@sdk = s
|
258
|
+
end
|
259
|
+
end
|
260
|
+
|
261
|
+
class FunctionStartsCommand < Command # LC_FUNCTION_STARTS
|
262
|
+
f_uint32 :dataoff, :datasize
|
263
|
+
end
|
264
|
+
|
265
|
+
class DyldInfoOnlyCommand < Command # LC_DYLD_INFO_ONLY
|
266
|
+
f_uint32 :rebase_off, :rebase_size, :bind_off, :bind_size, :weak_bind_off, :weak_bind_size,
|
267
|
+
:lazy_bind_off, :lazy_bind_size, :export_off, :export_size
|
268
|
+
end
|
269
|
+
|
270
|
+
end
|
271
|
+
end
|