metasm 1.0.3 → 1.0.4
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.
- 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
|