metasm 1.0.3 → 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +3 -0
- data.tar.gz.sig +0 -0
- data/Gemfile +3 -2
- data/metasm.gemspec +3 -2
- data/metasm.rb +4 -1
- data/metasm/compile_c.rb +2 -2
- data/metasm/cpu/arc/decode.rb +0 -21
- data/metasm/cpu/arc/main.rb +4 -4
- data/metasm/cpu/arm/decode.rb +1 -5
- data/metasm/cpu/arm/main.rb +3 -3
- data/metasm/cpu/arm64/decode.rb +2 -6
- data/metasm/cpu/arm64/main.rb +5 -5
- data/metasm/cpu/bpf/decode.rb +3 -35
- data/metasm/cpu/bpf/main.rb +5 -5
- data/metasm/cpu/bpf/render.rb +1 -12
- data/metasm/cpu/cy16/decode.rb +0 -6
- data/metasm/cpu/cy16/main.rb +3 -3
- data/metasm/cpu/cy16/render.rb +0 -11
- data/metasm/cpu/dalvik/decode.rb +4 -26
- data/metasm/cpu/dalvik/main.rb +20 -2
- data/metasm/cpu/dalvik/opcodes.rb +3 -2
- data/metasm/cpu/{mips/compile_c.rb → ebpf.rb} +5 -2
- data/metasm/cpu/ebpf/debug.rb +61 -0
- data/metasm/cpu/ebpf/decode.rb +142 -0
- data/metasm/cpu/ebpf/main.rb +58 -0
- data/metasm/cpu/ebpf/opcodes.rb +97 -0
- data/metasm/cpu/ebpf/render.rb +36 -0
- data/metasm/cpu/ia32/debug.rb +39 -1
- data/metasm/cpu/ia32/decode.rb +111 -90
- data/metasm/cpu/ia32/decompile.rb +45 -37
- data/metasm/cpu/ia32/main.rb +10 -0
- data/metasm/cpu/ia32/parse.rb +6 -0
- data/metasm/cpu/mcs51/decode.rb +1 -1
- data/metasm/cpu/mcs51/main.rb +11 -0
- data/metasm/cpu/mips/decode.rb +8 -18
- data/metasm/cpu/mips/main.rb +3 -3
- data/metasm/cpu/mips/opcodes.rb +1 -1
- data/metasm/cpu/msp430/decode.rb +2 -6
- data/metasm/cpu/msp430/main.rb +3 -3
- data/metasm/cpu/openrisc.rb +11 -0
- data/metasm/cpu/openrisc/debug.rb +106 -0
- data/metasm/cpu/openrisc/decode.rb +182 -0
- data/metasm/cpu/openrisc/decompile.rb +350 -0
- data/metasm/cpu/openrisc/main.rb +70 -0
- data/metasm/cpu/openrisc/opcodes.rb +109 -0
- data/metasm/cpu/openrisc/render.rb +37 -0
- data/metasm/cpu/ppc/decode.rb +0 -25
- data/metasm/cpu/ppc/main.rb +6 -6
- data/metasm/cpu/ppc/opcodes.rb +3 -4
- data/metasm/cpu/python/decode.rb +0 -20
- data/metasm/cpu/python/main.rb +1 -1
- data/metasm/cpu/sh4/decode.rb +2 -6
- data/metasm/cpu/sh4/main.rb +25 -23
- data/metasm/cpu/st20/decode.rb +0 -7
- data/metasm/cpu/webasm.rb +11 -0
- data/metasm/cpu/webasm/debug.rb +31 -0
- data/metasm/cpu/webasm/decode.rb +321 -0
- data/metasm/cpu/webasm/decompile.rb +386 -0
- data/metasm/cpu/webasm/encode.rb +104 -0
- data/metasm/cpu/webasm/main.rb +81 -0
- data/metasm/cpu/webasm/opcodes.rb +214 -0
- data/metasm/cpu/x86_64/compile_c.rb +13 -9
- data/metasm/cpu/x86_64/parse.rb +1 -1
- data/metasm/cpu/z80/decode.rb +0 -27
- data/metasm/cpu/z80/main.rb +3 -3
- data/metasm/cpu/z80/render.rb +0 -11
- data/metasm/debug.rb +43 -8
- data/metasm/decode.rb +62 -14
- data/metasm/decompile.rb +793 -466
- data/metasm/disassemble.rb +188 -131
- data/metasm/disassemble_api.rb +30 -17
- data/metasm/dynldr.rb +2 -2
- data/metasm/encode.rb +8 -2
- data/metasm/exe_format/autoexe.rb +2 -0
- data/metasm/exe_format/coff.rb +21 -3
- data/metasm/exe_format/coff_decode.rb +12 -0
- data/metasm/exe_format/coff_encode.rb +6 -3
- data/metasm/exe_format/dex.rb +13 -3
- data/metasm/exe_format/elf.rb +12 -2
- data/metasm/exe_format/elf_decode.rb +59 -1
- data/metasm/exe_format/main.rb +2 -0
- data/metasm/exe_format/mz.rb +1 -0
- data/metasm/exe_format/pe.rb +25 -3
- data/metasm/exe_format/wasm.rb +402 -0
- data/metasm/gui/dasm_decomp.rb +171 -95
- data/metasm/gui/dasm_graph.rb +61 -2
- data/metasm/gui/dasm_hex.rb +2 -2
- data/metasm/gui/dasm_main.rb +45 -19
- data/metasm/gui/debug.rb +13 -4
- data/metasm/gui/gtk.rb +12 -4
- data/metasm/main.rb +108 -103
- data/metasm/os/emulator.rb +175 -0
- data/metasm/os/main.rb +11 -6
- data/metasm/parse.rb +23 -12
- data/metasm/parse_c.rb +189 -135
- data/metasm/preprocessor.rb +16 -1
- data/misc/openrisc-parser.rb +79 -0
- data/samples/dasm-plugins/scanxrefs.rb +6 -4
- data/samples/dasm-plugins/selfmodify.rb +8 -8
- data/samples/dbg-plugins/trace_func.rb +1 -1
- data/samples/disassemble-gui.rb +14 -3
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/lindebug.rb +79 -78
- data/samples/metasm-shell.rb +8 -8
- data/tests/all.rb +1 -1
- data/tests/expression.rb +2 -0
- data/tests/graph_layout.rb +1 -1
- data/tests/ia32.rb +1 -0
- data/tests/mips.rb +1 -1
- data/tests/preprocessor.rb +18 -0
- metadata +124 -6
- metadata.gz.sig +0 -0
data/metasm/disassemble_api.rb
CHANGED
@@ -130,11 +130,6 @@ class DecodedInstruction
|
|
130
130
|
end
|
131
131
|
end
|
132
132
|
|
133
|
-
class CPU
|
134
|
-
# compat alias, for scripts using older version of metasm
|
135
|
-
def get_backtrace_binding(di) backtrace_binding(di) end
|
136
|
-
end
|
137
|
-
|
138
133
|
class Disassembler
|
139
134
|
# access the default value for @@backtrace_maxblocks for newly created Disassemblers
|
140
135
|
def self.backtrace_maxblocks ; @@backtrace_maxblocks ; end
|
@@ -210,8 +205,8 @@ class Disassembler
|
|
210
205
|
alias instructionblocks each_instructionblock
|
211
206
|
|
212
207
|
# return a backtrace_binding reversed (akin to code emulation) (but not really)
|
213
|
-
def get_fwdemu_binding(di, pc=nil)
|
214
|
-
@cpu.get_fwdemu_binding(di, pc)
|
208
|
+
def get_fwdemu_binding(di, pc=nil, dbg_ctx=nil)
|
209
|
+
@cpu.get_fwdemu_binding(di, pc, dbg_ctx)
|
215
210
|
end
|
216
211
|
|
217
212
|
# reads len raw bytes from the mmaped address space
|
@@ -276,7 +271,7 @@ class Disassembler
|
|
276
271
|
if b = block_at(from_addr)
|
277
272
|
b.add_to_normal(addr)
|
278
273
|
end
|
279
|
-
@addrs_todo <<
|
274
|
+
@addrs_todo << { :addr => addr, :from => from_addr }
|
280
275
|
disassemble
|
281
276
|
end
|
282
277
|
|
@@ -286,6 +281,12 @@ class Disassembler
|
|
286
281
|
e.inv_export[e.ptr] if e
|
287
282
|
end
|
288
283
|
|
284
|
+
# return the array of all labels associated to an addr
|
285
|
+
def get_all_labels_at(addr)
|
286
|
+
addr = normalize(addr)
|
287
|
+
label_alias[addr].to_a
|
288
|
+
end
|
289
|
+
|
289
290
|
# sets the label for the specified address
|
290
291
|
# returns nil if the address is not mapped
|
291
292
|
# memcheck is passed to get_section_at to validate that the address is mapped
|
@@ -295,6 +296,7 @@ class Disassembler
|
|
295
296
|
e, b = get_section_at(addr, memcheck)
|
296
297
|
if not e
|
297
298
|
elsif not l = e.inv_export[e.ptr] or (!overwrite and l != name)
|
299
|
+
split_block(addr)
|
298
300
|
l = @program.new_label(name)
|
299
301
|
e.add_export l, e.ptr
|
300
302
|
@label_alias_cache = nil
|
@@ -683,7 +685,7 @@ class Disassembler
|
|
683
685
|
# give something equivalent to the code accessible from the (list of) entrypoints given
|
684
686
|
# from the @decoded dasm graph
|
685
687
|
# assume all jump targets have a matching label in @prog_binding
|
686
|
-
# may add
|
688
|
+
# may add inconditional jumps in the listing to preserve the code flow
|
687
689
|
def flatten_graph(entry, include_subfunc=true)
|
688
690
|
ret = []
|
689
691
|
entry = [entry] if not entry.kind_of? Array
|
@@ -691,11 +693,16 @@ class Disassembler
|
|
691
693
|
done = []
|
692
694
|
inv_binding = @prog_binding.invert
|
693
695
|
while addr = todo.pop
|
694
|
-
next if done.include?
|
696
|
+
next if done.include?(addr)
|
695
697
|
done << addr
|
696
|
-
b = @decoded[addr].block
|
697
698
|
|
698
699
|
ret << Label.new(inv_binding[addr]) if inv_binding[addr]
|
700
|
+
if not di_at(addr)
|
701
|
+
ret << @cpu.instr_jump_stop
|
702
|
+
next
|
703
|
+
end
|
704
|
+
|
705
|
+
b = @decoded[addr].block
|
699
706
|
ret.concat b.list.map { |di| di.instruction }
|
700
707
|
|
701
708
|
b.each_to_otherfunc(self) { |to|
|
@@ -709,8 +716,8 @@ class Disassembler
|
|
709
716
|
|
710
717
|
if not di = b.list[-1-@cpu.delay_slot] or not di.opcode.props[:stopexec] or di.opcode.props[:saveip]
|
711
718
|
to = b.list.last.next_addr
|
712
|
-
if todo.include? to
|
713
|
-
if done.include?
|
719
|
+
if todo.include?(to) and di_at(to)
|
720
|
+
if done.include?(to)
|
714
721
|
if not to_l = inv_binding[to]
|
715
722
|
to_l = auto_label_at(to, 'loc')
|
716
723
|
if done.include? to and idx = ret.index(@decoded[to].block.list.first.instruction)
|
@@ -721,6 +728,8 @@ class Disassembler
|
|
721
728
|
else
|
722
729
|
todo << to # ensure it's next in the listing
|
723
730
|
end
|
731
|
+
else
|
732
|
+
ret << @cpu.instr_jump_stop
|
724
733
|
end
|
725
734
|
end
|
726
735
|
end
|
@@ -977,7 +986,7 @@ class Disassembler
|
|
977
986
|
end
|
978
987
|
|
979
988
|
# loads a map file (addr => symbol)
|
980
|
-
# off is an
|
989
|
+
# off is an optional offset to add to every address found (for eg rebased binaries)
|
981
990
|
# understands:
|
982
991
|
# standard map files (eg linux-kernel.map: <addr> <type> <name>, e.g. 'c01001ba t setup_idt')
|
983
992
|
# ida map files (<sectionidx>:<sectionoffset> <name>)
|
@@ -996,7 +1005,7 @@ class Disassembler
|
|
996
1005
|
# we do not have section load order, let's just hope that the addresses are sorted (and sortable..)
|
997
1006
|
# could check the 1st part of the file, with section sizes, but it is not very convenient
|
998
1007
|
# the regexp is so that we skip the 1st part with section descriptions
|
999
|
-
# in the file, section 1 is the 1st section ; we have an
|
1008
|
+
# in the file, section 1 is the 1st section ; we have an additional section (exe header) which fixes the 0-index
|
1000
1009
|
# XXX this is PE-specific, TODO fix it for ELF (ida references sections, we reference segments...)
|
1001
1010
|
addr = sks[$1.to_i(16)] + $2.to_i(16) + off
|
1002
1011
|
set_label_at(addr, $3, false, !seen[addr])
|
@@ -1137,7 +1146,11 @@ class Disassembler
|
|
1137
1146
|
addr = Expression.parse(pp).reduce
|
1138
1147
|
len = Expression.parse(pp).reduce
|
1139
1148
|
edata = EncodedData.new(data.unpack('m*').first, :virtsize => len)
|
1140
|
-
|
1149
|
+
# check for an existing section, eg from binarypath
|
1150
|
+
existing_section = get_section_at(addr)
|
1151
|
+
if not existing_section or existing_section[0].data.to_str != edata.data.to_str
|
1152
|
+
add_section(addr, edata)
|
1153
|
+
end
|
1141
1154
|
when 'map'
|
1142
1155
|
load_map data
|
1143
1156
|
when 'decoded'
|
@@ -1741,7 +1754,7 @@ class Disassembler
|
|
1741
1754
|
end
|
1742
1755
|
|
1743
1756
|
# same as load_plugin, but hides the @gui attribute while loading, preventing the plugin do popup stuff
|
1744
|
-
# this is useful when you want to load a plugin from another plugin to enhance the plugin's
|
1757
|
+
# this is useful when you want to load a plugin from another plugin to enhance the plugin's functionality
|
1745
1758
|
# XXX this also prevents setting up kbd_callbacks etc..
|
1746
1759
|
def load_plugin_nogui(plugin_filename)
|
1747
1760
|
oldgui = gui
|
data/metasm/dynldr.rb
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
# This sample creates the dynldr.so ruby shared object that allows interaction with
|
7
7
|
# native libraries
|
8
|
-
# x86 only for now
|
8
|
+
# x86/x64 only for now
|
9
9
|
|
10
10
|
module Metasm
|
11
11
|
class DynLdr
|
@@ -1229,7 +1229,7 @@ EOS
|
|
1229
1229
|
cp.alloc_c_struct(structname, values)
|
1230
1230
|
end
|
1231
1231
|
|
1232
|
-
# return a C::AllocCStruct mapped over the string (with
|
1232
|
+
# return a C::AllocCStruct mapped over the string (with optional offset)
|
1233
1233
|
# str may be an EncodedData
|
1234
1234
|
def self.decode_c_struct(structname, str, off=0)
|
1235
1235
|
str = str.data if str.kind_of? EncodedData
|
data/metasm/encode.rb
CHANGED
@@ -214,8 +214,14 @@ class ExeFormat
|
|
214
214
|
|
215
215
|
raise EncodeError, "cannot find candidate in #{elem.inspect}, immediate too big #{wantsize.inspect} #{target_bounds.inspect}" if acceptable.empty?
|
216
216
|
|
217
|
-
# keep the shortest
|
218
|
-
|
217
|
+
# keep the shortest, use a hack make sort consistent in all cases
|
218
|
+
# see https://8thlight.com/blog/will-warner/2013/03/26/stable-sorting-in-ruby.html
|
219
|
+
n = 0
|
220
|
+
mod_map = acceptable.map { |edata| n += 1 ; [[edata.virtsize, n], edata] }
|
221
|
+
interm_sort = mod_map.sort { |left, right| left[0] <=> right[0] }
|
222
|
+
mod_sort_result = interm_sort.collect { |edata| edata[1] }
|
223
|
+
result = mod_sort_result.first
|
224
|
+
result
|
219
225
|
else
|
220
226
|
elem
|
221
227
|
end
|
@@ -37,6 +37,7 @@ end
|
|
37
37
|
|
38
38
|
# register a new binary file signature
|
39
39
|
def self.register_signature(sig, exe=nil, &b)
|
40
|
+
sig.force_encoding('binary') if sig.respond_to?(:force_encoding)
|
40
41
|
(@signatures ||= []) << [sig, exe || b]
|
41
42
|
end
|
42
43
|
|
@@ -59,6 +60,7 @@ register_signature("dex\n") { DEX }
|
|
59
60
|
register_signature("dey\n") { DEY }
|
60
61
|
register_signature("\xfa\x70\x0e\x1f") { FatELF }
|
61
62
|
register_signature("\x50\x4b\x03\x04") { ZIP }
|
63
|
+
register_signature("\0asm") { WasmFile }
|
62
64
|
register_signature('Metasm.dasm') { Disassembler }
|
63
65
|
|
64
66
|
# replacement for AutoExe where #load defaults to a Shellcode of the specified CPU
|
data/metasm/exe_format/coff.rb
CHANGED
@@ -213,7 +213,7 @@ class COFF < ExeFormat
|
|
213
213
|
end
|
214
214
|
|
215
215
|
# tree-like structure, holds all misc data the program might need (icons, cursors, version information)
|
216
|
-
#
|
216
|
+
# conventionally structured in a 3-level depth structure:
|
217
217
|
# I resource type (icon/cursor/etc, see +TYPES+)
|
218
218
|
# II resource id (icon n1, icon 'toto', ...)
|
219
219
|
# III language-specific version (icon n1 en, icon n1 en-dvorak...)
|
@@ -230,6 +230,12 @@ class COFF < ExeFormat
|
|
230
230
|
end
|
231
231
|
end
|
232
232
|
|
233
|
+
# unwind info
|
234
|
+
class ExceptionEntry < SerialStruct
|
235
|
+
# function start RVA, function end RVA, UNWIND_INFO RVA
|
236
|
+
words :func, :func_end, :unwind
|
237
|
+
end
|
238
|
+
|
233
239
|
# array of relocations to apply to an executable file
|
234
240
|
# when it is loaded at an address that is not its preferred_base_address
|
235
241
|
class RelocationTable < SerialStruct
|
@@ -258,9 +264,20 @@ class COFF < ExeFormat
|
|
258
264
|
end
|
259
265
|
|
260
266
|
class RSDS < SerialStruct
|
261
|
-
|
267
|
+
word :guid_03
|
268
|
+
halfs :guid_45, :guid_67
|
269
|
+
bytes :guid_8, :guid_9, :guid_a, :guid_b, :guid_c, :guid_d, :guid_e, :guid_f
|
262
270
|
word :age
|
263
271
|
strz :pdbfilename
|
272
|
+
|
273
|
+
def guid
|
274
|
+
"%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X" % [guid_03, guid_45, guid_67, guid_8, guid_9, guid_a, guid_b, guid_c, guid_d, guid_e, guid_f]
|
275
|
+
end
|
276
|
+
|
277
|
+
# http path to pdb (compressed)
|
278
|
+
def msdl_url
|
279
|
+
"http://msdl.microsoft.com/download/symbols/#{pdbfilename}/#{guid.delete("-")}#{age}/#{pdbfilename.chop}_"
|
280
|
+
end
|
264
281
|
end
|
265
282
|
end
|
266
283
|
|
@@ -396,7 +413,8 @@ class COFF < ExeFormat
|
|
396
413
|
end
|
397
414
|
|
398
415
|
attr_accessor :header, :optheader, :directory, :sections, :endianness, :symbols, :bitsize,
|
399
|
-
:export, :imports, :resource, :
|
416
|
+
:export, :imports, :resource, :exception_table, :certificates,
|
417
|
+
:relocations, :debug, :tls, :loadconfig, :delayimports, :com_header
|
400
418
|
|
401
419
|
# boolean, set to true to have #decode() ignore the base_relocs directory
|
402
420
|
attr_accessor :nodecode_relocs
|
@@ -639,6 +639,17 @@ class COFF
|
|
639
639
|
resource.decode_version(self, lang)
|
640
640
|
end
|
641
641
|
|
642
|
+
# decode the exception table, holding the start and end of every function in the binary (x64)
|
643
|
+
# includes a pointer to the UNWIND_INFO structure for exception handling
|
644
|
+
def decode_exception_table
|
645
|
+
if et = @directory['exception_table'] and sect_at_rva(et[0])
|
646
|
+
@exception_table = []
|
647
|
+
(et[1]/12).times {
|
648
|
+
@exception_table << ExceptionEntry.decode(self)
|
649
|
+
}
|
650
|
+
end
|
651
|
+
end
|
652
|
+
|
642
653
|
# decodes certificate table
|
643
654
|
def decode_certificates
|
644
655
|
if ct = @directory['certificate_table']
|
@@ -782,6 +793,7 @@ class COFF
|
|
782
793
|
decode_exports
|
783
794
|
decode_imports
|
784
795
|
decode_resources
|
796
|
+
decode_exception_table
|
785
797
|
decode_certificates
|
786
798
|
decode_debug
|
787
799
|
decode_tls
|
@@ -172,6 +172,7 @@ class COFF
|
|
172
172
|
@iat_p ||= Expression[coff.label_at(edata['iat'].last, 0, 'iat'), :-, coff.label_at(coff.encoded, 0)]
|
173
173
|
edata['idata'] << super(coff)
|
174
174
|
|
175
|
+
@libname.force_encoding('BINARY') if @libname.respond_to?(:force_encoding)
|
175
176
|
edata['nametable'] << @libname << 0
|
176
177
|
|
177
178
|
ord_mask = 1 << (coff.bitsize - 1)
|
@@ -182,6 +183,7 @@ class COFF
|
|
182
183
|
else
|
183
184
|
edata['nametable'].align 2
|
184
185
|
ptr = coff.encode_xword(rva_end['nametable'])
|
186
|
+
i.name.force_encoding('BINARY') if i.name.respond_to?(:force_encoding)
|
185
187
|
edata['nametable'] << coff.encode_half(i.hint || 0) << i.name << 0
|
186
188
|
end
|
187
189
|
edata['ilt'] << ptr
|
@@ -510,8 +512,8 @@ class COFF
|
|
510
512
|
|
511
513
|
s.encoded.reloc.each { |off, rel|
|
512
514
|
# check that the relocation looks like "program_start + integer" when bound using the fake binding
|
513
|
-
#
|
514
|
-
if rel.endianness == @endianness and [:u32, :a32, :u64, :a64].include?(rel.type) and
|
515
|
+
# TODO relocate refs to IAT (eg plt)
|
516
|
+
if rel.endianness == @endianness and [:i32, :u32, :a32, :i64, :u64, :a64].include?(rel.type) and
|
515
517
|
rel.target.bind(binding).reduce.kind_of?(Expression) and
|
516
518
|
Expression[rel.target, :-, startaddr].bind(binding).reduce.kind_of?(::Integer)
|
517
519
|
# winner !
|
@@ -519,7 +521,7 @@ class COFF
|
|
519
521
|
# build relocation
|
520
522
|
r = RelocationTable::Relocation.new
|
521
523
|
r.offset = off & 0xfff
|
522
|
-
r.type = {
|
524
|
+
r.type = { '32' => 'HIGHLOW', '64' => 'DIR64' }[rel.type.to_s[1, 2]]
|
523
525
|
|
524
526
|
# check if we need to start a new relocation table
|
525
527
|
if rt.base_addr and (rt.base_addr & ~0xfff) != (off & ~0xfff)
|
@@ -626,6 +628,7 @@ class COFF
|
|
626
628
|
end
|
627
629
|
end
|
628
630
|
s.rawaddr = nil if s.rawaddr.kind_of?(::Integer) # XXX allow to force rawaddr ?
|
631
|
+
s.name.force_encoding('BINARY') if s.name.respond_to?(:force_encoding)
|
629
632
|
s_table << s.encode(self)
|
630
633
|
}
|
631
634
|
|
data/metasm/exe_format/dex.rb
CHANGED
@@ -331,17 +331,27 @@ class DEX < ExeFormat
|
|
331
331
|
def decode_u4(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
332
332
|
def sizeof_u2 ; 2 ; end
|
333
333
|
def sizeof_u4 ; 4 ; end
|
334
|
+
def encode_uleb(val, signed=false)
|
335
|
+
v = val
|
336
|
+
out = EncodedData.new
|
337
|
+
while v > 0x7f or v < -0x40 or (signed and v > 0x3f)
|
338
|
+
out << Expression[0x80 | (v&0x7f)].encode(:u8, @endianness)
|
339
|
+
v >>= 7
|
340
|
+
end
|
341
|
+
out << Expression[v & 0x7f].encode(:u8, @endianness)
|
342
|
+
end
|
334
343
|
def decode_uleb(ed = @encoded, signed=false)
|
335
344
|
v = s = 0
|
336
|
-
while s <
|
345
|
+
while s < 10*7
|
337
346
|
b = ed.read(1).unpack('C').first.to_i
|
338
347
|
v |= (b & 0x7f) << s
|
339
|
-
break if (b&0x80) == 0
|
340
348
|
s += 7
|
349
|
+
break if (b&0x80) == 0
|
341
350
|
end
|
342
351
|
v = Expression.make_signed(v, s) if signed
|
343
352
|
v
|
344
353
|
end
|
354
|
+
def encode_sleb(val) encode_uleb(val, true) end
|
345
355
|
def decode_sleb(ed = @encoded) decode_uleb(ed, true) end
|
346
356
|
attr_accessor :header, :strings, :types, :protos, :fields, :methods, :classes
|
347
357
|
|
@@ -425,7 +435,7 @@ class DEX < ExeFormat
|
|
425
435
|
next if not c.data
|
426
436
|
(c.data.direct_methods + c.data.virtual_methods).each { |m|
|
427
437
|
n = @types[c.classidx] + '->' + m.name
|
428
|
-
dasm.
|
438
|
+
dasm.add_comment m.codeoff+m.code.insns_off, n
|
429
439
|
}
|
430
440
|
}
|
431
441
|
dasm.function[:default] = @cpu.disassembler_default_func
|
data/metasm/exe_format/elf.rb
CHANGED
@@ -78,7 +78,8 @@ class ELF < ExeFormat
|
|
78
78
|
'MIPS' => {1 => 'NOREORDER', 2 => 'PIC', 4 => 'CPIC',
|
79
79
|
8 => 'XGOT', 0x10 => '64BIT_WHIRL', 0x20 => 'ABI2',
|
80
80
|
0x40 => 'ABI_ON32', 0x80 => 'OPTIONSFIRST',
|
81
|
-
0x100 => '32BITMODE'}
|
81
|
+
0x100 => '32BITMODE'},
|
82
|
+
'OPENRISC' => { 1 => 'NODELAY' },
|
82
83
|
}
|
83
84
|
|
84
85
|
DYNAMIC_TAG = { 0 => 'NULL', 1 => 'NEEDED', 2 => 'PLTRELSZ', 3 =>
|
@@ -391,7 +392,16 @@ class ELF < ExeFormat
|
|
391
392
|
11 => '32S', 12 => '16', 13 => 'PC16', 14 => '8',
|
392
393
|
15 => 'PC8', 16 => 'DTPMOD64', 17 => 'DTPOFF64',
|
393
394
|
18 => 'TPOFF64', 19 => 'TLSGD', 20 => 'TLSLD',
|
394
|
-
21 => 'DTPOFF32', 22 => 'GOTTPOFF', 23 => 'TPOFF32' }
|
395
|
+
21 => 'DTPOFF32', 22 => 'GOTTPOFF', 23 => 'TPOFF32' },
|
396
|
+
'OPENRISC' => { 0 => 'NONE', 1 => '32', 2 => '16', 3 => '8',
|
397
|
+
4 => 'LO_16_IN_INSN', 5 => 'HI_16_IN_INSN', 6 => 'INSN_REL_26', 7 => 'GNU_VTENTRY',
|
398
|
+
8 => 'GNU_VTINHERIT', 9 => '32_PCREL', 10 => '16_PCREL', 11 => '8_PCREL',
|
399
|
+
12 => 'GOTPC_HI16', 13 => 'GOTPC_LO16', 14 => 'GOT15', 15 => 'PLT26',
|
400
|
+
16 => 'GOTOFF_HI16', 17 => 'GOTOFF_LO16', 18 => 'COPY', 19 => 'GLOB_DAT',
|
401
|
+
20 => 'JMP_SLOT', 21 => 'RELATIVE', 22 => 'TLS_GD_HI16', 23 => 'TLS_GD_LO16',
|
402
|
+
24 => 'TLS_LDM_HI16', 25 => 'TLS_LDM_LO16', 26 => 'TLS_LDO_HI16', 27 => 'TLS_LDO_LO16',
|
403
|
+
28 => 'TLS_IE_HI16', 29 => 'TLS_IE_LO16', 30 => 'TLS_LE_HI16', 31 => 'TLS_LE_LO16',
|
404
|
+
32 => 'TLS_TPOFF', 33 => 'TLS_DTPOFF', 34 => 'TLS_DTPMOD' },
|
395
405
|
}
|
396
406
|
|
397
407
|
DEFAULT_INTERP = '/lib/ld-linux.so.2'
|
@@ -742,6 +742,52 @@ class ELF
|
|
742
742
|
Metasm::Relocation.new(Expression[target], :u32, @endianness) if target
|
743
743
|
end
|
744
744
|
|
745
|
+
def arch_decode_segments_reloc_openrisc(reloc)
|
746
|
+
if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
|
747
|
+
s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
|
748
|
+
@encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
|
749
|
+
end
|
750
|
+
|
751
|
+
original_word = decode_word
|
752
|
+
|
753
|
+
# decode addend if needed
|
754
|
+
case reloc.type
|
755
|
+
when 'NONE' # no addend
|
756
|
+
else addend = reloc.addend || Expression.make_signed(original_word, 32)
|
757
|
+
end
|
758
|
+
|
759
|
+
case reloc.type
|
760
|
+
when 'NONE'
|
761
|
+
when '32', '32_PCREL'
|
762
|
+
target = reloc_target(reloc)
|
763
|
+
target = Expression[target, :-, reloc.offset] if reloc.type == '32_PCREL'
|
764
|
+
target = Expression[target, :+, addend] if addend and addend != 0
|
765
|
+
when 'INSN_REL_26'
|
766
|
+
target = reloc_target(reloc)
|
767
|
+
addend &= 0x3ff_ffff
|
768
|
+
target = Expression[target, :+, [addend, :<<, 2]] if addend and addend != 0
|
769
|
+
target = Expression[[original_word, :&, 0xfc0_0000], :|, [[target, :&, 0x3ff_ffff], :>>, 2]]
|
770
|
+
when 'HI_16_IN_INSN'
|
771
|
+
target = reloc_target(reloc)
|
772
|
+
addend &= 0xffff
|
773
|
+
target = Expression[target, :+, [addend, :<<, 16]] if addend and addend != 0
|
774
|
+
target = Expression[[original_word, :&, 0xffff_0000], :|, [[target, :>>, 16], :&, 0xffff]]
|
775
|
+
when 'LO_16_IN_INSN'
|
776
|
+
target = reloc_target(reloc)
|
777
|
+
addend &= 0xffff
|
778
|
+
target = Expression[target, :+, addend] if addend and addend != 0
|
779
|
+
target = Expression[[original_word, :&, 0xffff_0000], :|, [target, :&, 0xffff]]
|
780
|
+
when 'JMP_SLOT'
|
781
|
+
target = reloc_target(reloc)
|
782
|
+
target = Expression[target, :+, addend] if addend and addend != 0
|
783
|
+
else
|
784
|
+
puts "W: Elf: unhandled MIPS reloc #{reloc.inspect}" if $VERBOSE
|
785
|
+
target = nil
|
786
|
+
end
|
787
|
+
|
788
|
+
Metasm::Relocation.new(Expression[target], :u32, @endianness) if target
|
789
|
+
end
|
790
|
+
|
745
791
|
class DwarfDebug
|
746
792
|
# decode a DWARF2 'compilation unit'
|
747
793
|
def decode(elf, info, abbrev, str)
|
@@ -930,13 +976,14 @@ class ELF
|
|
930
976
|
case @header.machine
|
931
977
|
when 'X86_64'; X86_64.new
|
932
978
|
when '386'; Ia32.new
|
933
|
-
when 'MIPS'; (@header.flags.include?('32BITMODE') ? MIPS64 : MIPS).new
|
979
|
+
when 'MIPS'; (@header.flags.include?('32BITMODE') ? MIPS64 : MIPS).new(@endianness)
|
934
980
|
when 'PPC'; PPC.new
|
935
981
|
when 'ARM'; ARM.new
|
936
982
|
when 'AARCH64'; AArch64.new
|
937
983
|
when 'SH'; Sh4.new
|
938
984
|
when 'ARC_COMPACT'; ARC.new
|
939
985
|
when 'MSP430'; MSP430.new
|
986
|
+
when 'OPENRISC'; OpenRisc.new(:latest, @endianness, (@header.flags.include?('NODELAY') ? 0 : 1))
|
940
987
|
else raise "unsupported cpu #{@header.machine}"
|
941
988
|
end
|
942
989
|
end
|
@@ -1020,6 +1067,17 @@ EOC
|
|
1020
1067
|
d.function[Expression[fn]] = noret
|
1021
1068
|
}
|
1022
1069
|
d.function[:default] = @cpu.disassembler_default_func
|
1070
|
+
when 'openrisc'
|
1071
|
+
old_cp = d.c_parser
|
1072
|
+
d.c_parser = nil
|
1073
|
+
d.parse_c <<EOC
|
1074
|
+
void __libc_start_main(void(*)(), int, char**, void(*)(), void(*)()) __attribute__((noreturn));
|
1075
|
+
void __attribute__((noreturn)) exit(int);
|
1076
|
+
EOC
|
1077
|
+
d.function[Expression['__libc_start_main']] = @cpu.decode_c_function_prototype(d.c_parser, '__libc_start_main')
|
1078
|
+
d.function[Expression['exit']] = @cpu.decode_c_function_prototype(d.c_parser, 'exit')
|
1079
|
+
d.c_parser = old_cp
|
1080
|
+
d.function[:default] = @cpu.disassembler_default_func
|
1023
1081
|
end
|
1024
1082
|
d
|
1025
1083
|
end
|