metasm 1.0.1 → 1.0.2
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 +7 -0
- data/.gitignore +1 -0
- data/.hgtags +3 -0
- data/Gemfile +1 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +2 -0
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +22 -0
- data/{lib/metasm.rb → metasm.rb} +11 -3
- data/{lib/metasm → metasm}/compile_c.rb +13 -7
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +425 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +289 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
- data/metasm/cpu/bpf/decode.rb +142 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +41 -0
- data/metasm/cpu/cy16.rb +9 -0
- data/metasm/cpu/cy16/decode.rb +253 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +41 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
- data/metasm/cpu/mips.rb +14 -0
- data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +247 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +136 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
- data/metasm/cpu/x86_64/opcodes.rb +136 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +313 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +59 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
- data/{lib/metasm → metasm}/decode.rb +35 -4
- data/{lib/metasm → metasm}/decompile.rb +15 -16
- data/{lib/metasm → metasm}/disassemble.rb +201 -45
- data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
- data/{lib/metasm → metasm}/dynldr.rb +220 -133
- data/{lib/metasm → metasm}/encode.rb +10 -1
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
- data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1695 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +93 -27
- data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
- data/{lib/metasm → metasm}/gui/qt.rb +12 -2
- data/{lib/metasm → metasm}/gui/win32.rb +179 -42
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +389 -264
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +330 -0
- data/{lib/metasm → metasm}/os/windows.rb +132 -42
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +26 -24
- data/{lib/metasm → metasm}/parse_c.rb +221 -116
- data/{lib/metasm → metasm}/preprocessor.rb +55 -40
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +2 -1
- data/misc/lint.rb +58 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +26 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +35 -5
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +12 -3
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +175 -381
- data/samples/metasm-shell.rb +1 -2
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +55 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +79 -26
- data/tests/mips.rb +9 -2
- data/tests/x86_64.rb +66 -18
- metadata +330 -218
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -873
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- data/samples/rubstop.rb +0 -399
@@ -84,7 +84,7 @@ class Preprocessor
|
|
84
84
|
# modifies the list, returns an array of list of tokens/nil
|
85
85
|
# handles nesting
|
86
86
|
def self.parse_arglist(lexer, list=nil)
|
87
|
-
readtok = lambda { list ? list.shift : lexer.
|
87
|
+
readtok = lambda { list ? list.shift : lexer.readtok_nopp }
|
88
88
|
unreadtok = lambda { |t| list ? (list.unshift(t) if t) : lexer.unreadtok(t) }
|
89
89
|
tok = nil
|
90
90
|
unreadlist = []
|
@@ -378,6 +378,7 @@ class Preprocessor
|
|
378
378
|
# hash filename => file content
|
379
379
|
attr_accessor :hooked_include
|
380
380
|
attr_accessor :warn_redefinition
|
381
|
+
attr_accessor :may_preprocess
|
381
382
|
|
382
383
|
# global default search directory for #included <files>
|
383
384
|
@@include_search_path = ['/usr/include']
|
@@ -385,18 +386,14 @@ class Preprocessor
|
|
385
386
|
def self.include_search_path=(np) @@include_search_path=np end
|
386
387
|
|
387
388
|
def initialize(text='')
|
388
|
-
@queue = []
|
389
389
|
@backtrace = []
|
390
390
|
@definition = %w[__FILE__ __LINE__ __COUNTER__ __DATE__ __TIME__].inject({}) { |h, n| h.update n => SpecialMacro.new(n) }
|
391
391
|
@include_search_path = @@include_search_path.dup
|
392
392
|
# stack of :accept/:discard/:discard_all/:testing, represents the current nesting of #if..#endif
|
393
393
|
@ifelse_nesting = []
|
394
|
-
@text = text
|
395
|
-
@pos = 0
|
396
|
-
@filename = 'unknown'
|
397
|
-
@lineno = 1
|
398
394
|
@warn_redefinition = true
|
399
395
|
@hooked_include = {}
|
396
|
+
@may_preprocess = false
|
400
397
|
@pragma_once = {}
|
401
398
|
@pragma_callback = lambda { |otok|
|
402
399
|
tok = otok
|
@@ -405,6 +402,7 @@ class Preprocessor
|
|
405
402
|
unreadtok tok
|
406
403
|
puts otok.exception("unhandled pragma #{str.inspect}").message if $VERBOSE
|
407
404
|
}
|
405
|
+
feed!(text)
|
408
406
|
define '__METASM__', VERSION
|
409
407
|
end
|
410
408
|
|
@@ -493,11 +491,16 @@ class Preprocessor
|
|
493
491
|
def feed!(text, filename='unknown', lineno=1)
|
494
492
|
raise ArgumentError, 'need something to parse!' if not text
|
495
493
|
@text = text
|
494
|
+
if not @may_preprocess and (@text =~ /^\s*(#|\?\?=)/ or (not @definition.empty? and
|
495
|
+
@text =~ /#{@definition.keys.map { |k| Regexp.escape(k) }.join('|')}/))
|
496
|
+
@may_preprocess = true
|
497
|
+
end
|
496
498
|
# @filename[-1] used in trace_macros to distinguish generic/specific files
|
497
499
|
@filename = "\"#{filename}\""
|
498
500
|
@lineno = lineno
|
499
501
|
@pos = 0
|
500
502
|
@queue = []
|
503
|
+
@backtrace = []
|
501
504
|
self
|
502
505
|
end
|
503
506
|
|
@@ -512,7 +515,7 @@ class Preprocessor
|
|
512
515
|
|
513
516
|
# reads one character from self.text
|
514
517
|
# updates self.lineno
|
515
|
-
# handles
|
518
|
+
# handles \-continued lines
|
516
519
|
def getchar
|
517
520
|
@ungetcharpos = @pos
|
518
521
|
@ungetcharlineno = @lineno
|
@@ -520,11 +523,11 @@ class Preprocessor
|
|
520
523
|
@pos += 1
|
521
524
|
|
522
525
|
# check trigraph
|
523
|
-
if c == ?? and @text[@pos] == ?? and Trigraph[@text[@pos+1]]
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
end
|
526
|
+
#if c == ?? and @text[@pos] == ?? and Trigraph[@text[@pos+1]]
|
527
|
+
# puts "can i has trigraf plox ??#{c.chr} (#@filename:#@lineno)" if $VERBOSE
|
528
|
+
# c = Trigraph[@text[@pos+1]]
|
529
|
+
# @pos += 2
|
530
|
+
#end
|
528
531
|
|
529
532
|
# check line continuation
|
530
533
|
# TODO portability
|
@@ -567,9 +570,9 @@ class Preprocessor
|
|
567
570
|
end
|
568
571
|
|
569
572
|
# calls readtok_nopp and handles preprocessor directives
|
570
|
-
def readtok
|
571
|
-
lastpos = @pos
|
573
|
+
def readtok
|
572
574
|
tok = readtok_nopp
|
575
|
+
return tok if not @may_preprocess # shortcut
|
573
576
|
|
574
577
|
if not tok
|
575
578
|
# end of file: resume parent
|
@@ -579,32 +582,41 @@ class Preprocessor
|
|
579
582
|
tok = readtok
|
580
583
|
end
|
581
584
|
|
582
|
-
elsif
|
583
|
-
|
584
|
-
|
585
|
-
|
585
|
+
elsif tok.type == :punct and tok.raw == '#' and not tok.expanded_from and @ifelse_nesting.last != :testing
|
586
|
+
# backward check for :eol (skip the '#' itself)
|
587
|
+
pos = @pos-2
|
588
|
+
while pos >= 0 # if reach start of file, proceed
|
589
|
+
case @text[pos, 1]
|
590
|
+
when "\n"
|
591
|
+
pos -= 1 if pos > 0 and @text[pos-1] == ?\r
|
592
|
+
return tok if pos > 0 and @text[pos-1] == ?\\ # check if the newline was a line-continuation
|
593
|
+
return tok if pos > 2 and @text[pos-3, 3] == '??/' # trigraph
|
594
|
+
break # proceed
|
595
|
+
when /\s/ # beware switch order, this matches "\n" too
|
596
|
+
else return tok # false alarm
|
597
|
+
end
|
598
|
+
pos -= 1
|
599
|
+
end
|
586
600
|
pretok = []
|
587
601
|
rewind = true
|
588
|
-
|
589
|
-
|
590
|
-
pretok << (ntok = readtok_nopp)
|
591
|
-
break if not ntok
|
602
|
+
while ntok = readtok_nopp
|
603
|
+
pretok << ntok
|
592
604
|
if ntok.type == :space # nothing
|
593
|
-
|
594
|
-
|
595
|
-
elsif state == 2 and ntok.type == :string and not ntok.expanded_from
|
605
|
+
next
|
606
|
+
elsif ntok.type == :string and not ntok.expanded_from
|
596
607
|
rewind = false if preprocessor_directive(ntok)
|
597
|
-
break
|
598
|
-
else break
|
599
608
|
end
|
609
|
+
break
|
600
610
|
end
|
601
611
|
if rewind
|
602
612
|
# false alarm: revert
|
603
613
|
pretok.reverse_each { |t| unreadtok t }
|
614
|
+
else
|
615
|
+
# XXX return :eol ?
|
616
|
+
tok = readtok
|
604
617
|
end
|
605
|
-
tok = readtok if lastpos == 0 # else return the :eol
|
606
618
|
|
607
|
-
elsif
|
619
|
+
elsif tok.type == :string and m = @definition[tok.raw] and not tok.expanded_from.to_a.find { |ef| ef.raw == m.name.raw } and
|
608
620
|
((m.args and margs = Macro.parse_arglist(self)) or not m.args)
|
609
621
|
|
610
622
|
if defined? @traced_macros and tok.backtrace[-2].to_s[0] == ?" and m.name and m.name.backtrace[-2].to_s[0] == ?<
|
@@ -637,21 +649,20 @@ class Preprocessor
|
|
637
649
|
when ?a..?z, ?A..?Z, ?0..?9, ?$, ?_
|
638
650
|
tok.type = :string
|
639
651
|
raw = tok.raw << c
|
640
|
-
|
641
|
-
case c
|
642
|
-
when nil; ungetchar; break # avoids 'no method "coerce" for nil' warning
|
652
|
+
while c = getchar
|
653
|
+
case c
|
643
654
|
when ?a..?z, ?A..?Z, ?0..?9, ?$, ?_
|
644
|
-
|
645
|
-
else ungetchar; break
|
655
|
+
else break
|
646
656
|
end
|
657
|
+
raw << c
|
647
658
|
end
|
659
|
+
ungetchar
|
648
660
|
|
649
661
|
when ?\ , ?\t, ?\r, ?\n, ?\f
|
650
662
|
tok.type = ((c == ?\ || c == ?\t) ? :space : :eol)
|
651
663
|
raw = tok.raw << c
|
652
|
-
|
653
|
-
case c
|
654
|
-
when nil; break
|
664
|
+
while c = getchar
|
665
|
+
case c
|
655
666
|
when ?\ , ?\t
|
656
667
|
when ?\n, ?\f, ?\r; tok.type = :eol
|
657
668
|
else break
|
@@ -676,8 +687,7 @@ class Preprocessor
|
|
676
687
|
tok.type = :space
|
677
688
|
raw << c
|
678
689
|
seenstar = false
|
679
|
-
|
680
|
-
raise tok, 'unterminated c++ comment' if not c = getchar
|
690
|
+
while c = getchar
|
681
691
|
raw << c
|
682
692
|
case c
|
683
693
|
when ?*; seenstar = true
|
@@ -685,6 +695,7 @@ class Preprocessor
|
|
685
695
|
else seenstar = false
|
686
696
|
end
|
687
697
|
end
|
698
|
+
raise tok, 'unterminated c++ comment' if not c
|
688
699
|
else
|
689
700
|
# just a slash
|
690
701
|
ungetchar
|
@@ -705,6 +716,7 @@ class Preprocessor
|
|
705
716
|
tok.type = :quoted
|
706
717
|
tok.raw << delimiter
|
707
718
|
tok.value = ''
|
719
|
+
tok.value.force_encoding('binary') if tok.value.respond_to?(:force_encoding)
|
708
720
|
c = nil
|
709
721
|
loop do
|
710
722
|
raise tok, 'unterminated string' if not c = getchar
|
@@ -767,6 +779,9 @@ class Preprocessor
|
|
767
779
|
def define(name, value=nil, from=caller.first)
|
768
780
|
from =~ /^(.*?):(\d+)/
|
769
781
|
btfile, btlineno = $1, $2.to_i
|
782
|
+
if not @may_preprocess and @text =~ /#{Regexp.escape name}/
|
783
|
+
@may_preprocess = true
|
784
|
+
end
|
770
785
|
t = Token.new([btfile, btlineno])
|
771
786
|
t.type = :string
|
772
787
|
t.raw = name.dup
|
@@ -1095,7 +1110,7 @@ class Preprocessor
|
|
1095
1110
|
nil while dir = readtok and dir.type == :space
|
1096
1111
|
raise cmd, 'qstring expected' if not dir or dir.type != :quoted
|
1097
1112
|
dir = ::File.expand_path dir.value
|
1098
|
-
raise cmd,
|
1113
|
+
raise cmd, "invalid path #{dir.inspect}" if not ::File.directory? dir
|
1099
1114
|
@include_search_path.unshift dir
|
1100
1115
|
|
1101
1116
|
when 'push_macro', 'pop_macro'
|
@@ -19,8 +19,10 @@ module Renderable
|
|
19
19
|
r = proc { |e|
|
20
20
|
case e
|
21
21
|
when Expression
|
22
|
-
yield e
|
23
22
|
r[e.lexpr] ; r[e.rexpr]
|
23
|
+
yield e
|
24
|
+
when ExpressionType
|
25
|
+
yield e
|
24
26
|
when Renderable
|
25
27
|
e.render.each { |re| r[re] }
|
26
28
|
end
|
@@ -64,45 +66,13 @@ end
|
|
64
66
|
|
65
67
|
class Expression
|
66
68
|
include Renderable
|
67
|
-
attr_accessor :render_info
|
68
|
-
|
69
|
-
# this is an accessor to @@render_int, the lambda used to render integers > 10
|
70
|
-
# usage: Expression.render_int = lambda { |e| '0x%x' % e }
|
71
|
-
# or Expression.render_int { |e| '0x%x' % e }
|
72
|
-
# XXX the returned string should be suitable for inclusion in a label name etc
|
73
|
-
def self.render_int(&b)
|
74
|
-
if b
|
75
|
-
@@render_int = b
|
76
|
-
else
|
77
|
-
@@render_int
|
78
|
-
end
|
79
|
-
end
|
80
|
-
def self.render_int=(p)
|
81
|
-
@@render_int = p
|
82
|
-
end
|
83
|
-
@@render_int = nil
|
84
69
|
|
85
70
|
def render_integer(e)
|
86
|
-
if render_info and @render_info[:char]
|
87
|
-
ee = e
|
88
|
-
v = []
|
89
|
-
while ee > 0
|
90
|
-
v << (ee & 0xff)
|
91
|
-
ee >>= 8
|
92
|
-
end
|
93
|
-
v.reverse! if @render_info[:char] == :big
|
94
|
-
if not v.empty? and v.all? { |c| c < 0x7f }
|
95
|
-
# XXX endianness
|
96
|
-
return "'" + v.pack('C*').inspect.gsub("'") { '\\\'' }[1...-1] + "'"
|
97
|
-
end
|
98
|
-
end
|
99
71
|
if e < 0
|
100
72
|
neg = true
|
101
73
|
e = -e
|
102
74
|
end
|
103
75
|
if e < 10; e = e.to_s
|
104
|
-
elsif @@render_int
|
105
|
-
e = @@render_int[e]
|
106
76
|
else
|
107
77
|
e = '%xh' % e
|
108
78
|
e = '0' << e unless (?0..?9).include? e[0]
|
@@ -114,17 +84,23 @@ class Expression
|
|
114
84
|
NOSQ1 = NOSQ2 = {:* => [:*], :+ => [:+, :-, :*], :- => [:+, :-, :*]}
|
115
85
|
NOSQ2[:-] = [:*]
|
116
86
|
def render
|
117
|
-
l = @lexpr.kind_of?(Integer) ? render_integer(@lexpr) : @lexpr
|
118
|
-
r = @rexpr.kind_of?(Integer) ? render_integer(@rexpr) : @rexpr
|
119
|
-
l = ['(', l, ')'] if @lexpr.kind_of?
|
120
|
-
r = ['(', r, ')'] if @rexpr.kind_of?
|
87
|
+
l = @lexpr.kind_of?(::Integer) ? render_integer(@lexpr) : @lexpr
|
88
|
+
r = @rexpr.kind_of?(::Integer) ? render_integer(@rexpr) : @rexpr
|
89
|
+
l = ['(', l, ')'] if @lexpr.kind_of?(Expression) and (not oa = NOSQ1[@op] or not oa.include?(@lexpr.op))
|
90
|
+
r = ['(', r, ')'] if @rexpr.kind_of?(Expression) and (not oa = NOSQ2[@op] or not oa.include?(@rexpr.op))
|
121
91
|
op = @op if l or @op != :+
|
122
92
|
if op == :+
|
123
93
|
r0 = [r].flatten.first
|
124
94
|
r0 = r0.render.flatten.first while r0.kind_of? Renderable
|
125
|
-
op = nil if (r0.kind_of?
|
95
|
+
op = nil if (r0.kind_of?(::Integer) and r0 < 0) or (r0.kind_of?(::String) and r0[0] == ?-) or r0 == :-
|
126
96
|
end
|
127
97
|
[l, op, r].compact
|
128
98
|
end
|
129
99
|
end
|
100
|
+
|
101
|
+
class ExpressionString
|
102
|
+
include Renderable
|
103
|
+
|
104
|
+
def render; hide_str ? @expr.render : render_str ; end
|
105
|
+
end
|
130
106
|
end
|
data/misc/hexdump.rb
CHANGED
@@ -51,5 +51,6 @@ if $0 == __FILE__
|
|
51
51
|
fmt << 'd' if ARGV.delete '-D'
|
52
52
|
fmt << 'a' if ARGV.delete '-A'
|
53
53
|
fmt = ['c', 'd', 'a'] if ARGV.delete '-a'
|
54
|
-
File.open(ARGV.first, 'rb')
|
54
|
+
infd = ARGV.empty? ? $stdin : File.open(ARGV.first, 'rb')
|
55
|
+
infd.hexdump(:fmt => fmt)
|
55
56
|
end
|
data/misc/lint.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
3
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
4
|
+
#
|
5
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
6
|
+
|
7
|
+
|
8
|
+
# this is a ruby code cleaner tool
|
9
|
+
# it passes its argument to ruby -v -c, which displays warnings (eg unused variable)
|
10
|
+
# it shows the incriminated line along the warning, to help identify false positives
|
11
|
+
# probably linux-only, and need ruby-1.9.1 or newer
|
12
|
+
|
13
|
+
def lint(tg)
|
14
|
+
if File.symlink?(tg)
|
15
|
+
# nothing
|
16
|
+
elsif File.directory?(tg)
|
17
|
+
Dir.entries(tg).each { |ent|
|
18
|
+
next if ent == '.' or ent == '..'
|
19
|
+
ent = File.join(tg, ent)
|
20
|
+
lint(ent) if File.directory?(ent) or ent =~ /\.rb$/
|
21
|
+
}
|
22
|
+
else
|
23
|
+
lint_file(tg)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def lint_file(tg)
|
28
|
+
flines = nil
|
29
|
+
compile_warn(tg).each_line { |line|
|
30
|
+
file, lineno, warn = line.split(/\s*:\s*/, 3)
|
31
|
+
if file == tg
|
32
|
+
if not flines
|
33
|
+
puts "#{tg}:"
|
34
|
+
flines = File.readlines(file) #File.open(file, 'rb') { |fd| fd.readlines }
|
35
|
+
end
|
36
|
+
puts " l.#{lineno}: #{warn.strip}: #{flines[lineno.to_i-1].strip.inspect}"
|
37
|
+
end
|
38
|
+
}
|
39
|
+
puts if flines
|
40
|
+
end
|
41
|
+
|
42
|
+
def compile_warn(tg)
|
43
|
+
r, w = IO.pipe('binary')
|
44
|
+
if !fork
|
45
|
+
r.close
|
46
|
+
$stderr.reopen w
|
47
|
+
$stdout.reopen '/dev/null'
|
48
|
+
exec 'ruby', '-v', '-c', tg
|
49
|
+
exit!
|
50
|
+
else
|
51
|
+
w.close
|
52
|
+
end
|
53
|
+
r
|
54
|
+
end
|
55
|
+
|
56
|
+
ARGV << '.' if ARGV.empty?
|
57
|
+
ARGV.each { |arg| lint arg }
|
58
|
+
|
data/misc/txt2html.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# encoding: binary (rage)
|
2
3
|
# This file is part of Metasm, the Ruby assembly manipulation suite
|
3
4
|
# Copyright (C) 2006-2009 Yoann GUILLOT
|
4
5
|
#
|
@@ -48,7 +49,7 @@ class Elem
|
|
48
49
|
if e.class.ancestors.include? Elem
|
49
50
|
@content << e
|
50
51
|
else
|
51
|
-
@content << e.to_s.gsub(Regexp.new("(#{@@quotechars.keys.join('|')})")) { |x| @@quotechars[x] }
|
52
|
+
@content << e.to_s.gsub(Regexp.new("(#{@@quotechars.keys.join('|')})", 'm')) { |x| @@quotechars[x] }
|
52
53
|
end
|
53
54
|
}
|
54
55
|
self
|
@@ -273,7 +274,7 @@ class Txt2Html
|
|
273
274
|
puts "compiling #{outf}..." if $VERBOSE
|
274
275
|
|
275
276
|
@pathfix = outf.split('/')[0...-1].map { '../' }.join
|
276
|
-
out = compile(File.
|
277
|
+
out = compile(File.open(f, 'rb') { |fd| fd.read }.gsub("\r", '') + "\n\n")
|
277
278
|
File.open(outf, 'wb') { |fd| fd.write out.to_s.gsub("\r", '').gsub("\n", "\r\n") }
|
278
279
|
end
|
279
280
|
|
@@ -368,13 +369,13 @@ class Txt2Html
|
|
368
369
|
out
|
369
370
|
end
|
370
371
|
|
371
|
-
# handle **bold_words** *italic* `fixed` <links>
|
372
|
+
# handle **bold_words** *italic* `fixed` <links> **bold__word__with__underscore**
|
372
373
|
def compile_string(str)
|
373
374
|
o = [str]
|
374
375
|
on = []
|
375
376
|
o.each { |s|
|
376
377
|
while s.kind_of? String and o1 = s.index('**') and o2 = s.index('**', o1+2) and not s[o1..o2].index(' ')
|
377
|
-
on << s[0...o1] << Html::Elem.new('b').add(s[o1+2...o2].tr('_', ' '))
|
378
|
+
on << s[0...o1] << Html::Elem.new('b').add(s[o1+2...o2].tr('_', ' ').gsub(' ', '_'))
|
378
379
|
s = s[o2+2..-1]
|
379
380
|
end
|
380
381
|
on << s
|
@@ -383,7 +384,7 @@ class Txt2Html
|
|
383
384
|
on = []
|
384
385
|
o.each { |s|
|
385
386
|
while s.kind_of? String and o1 = s.index('*') and o2 = s.index('*', o1+1) and not s[o1..o2].index(' ')
|
386
|
-
on << s[0...o1] << Html::Elem.new('i').add(s[o1+1...o2].tr('_', ' '))
|
387
|
+
on << s[0...o1] << Html::Elem.new('i').add(s[o1+1...o2].tr('_', ' ').gsub(' ', '_'))
|
387
388
|
s = s[o2+1..-1]
|
388
389
|
end
|
389
390
|
on << s
|
@@ -409,19 +410,20 @@ class Txt2Html
|
|
409
410
|
when 'txt'
|
410
411
|
tg = outfilename(lnk)
|
411
412
|
Txt2Html.new(lnk)
|
412
|
-
on << Html::A.new(@pathfix + tg, File.basename(lnk, '.txt').tr('_', ' '))
|
413
|
+
on << Html::A.new(@pathfix + tg, File.basename(lnk, '.txt').tr('_', ' ').gsub(' ', '_'))
|
413
414
|
when 'jpg', 'png'
|
414
415
|
on << Html::Img.new(lnk)
|
415
416
|
end
|
416
417
|
else
|
418
|
+
on << Html::A.new(lnk, lnk)
|
417
419
|
if lnk =~ /\.txt$/
|
418
420
|
@@seen_nofile ||= []
|
419
421
|
if not @@seen_nofile.include? lnk
|
420
422
|
@@seen_nofile << lnk
|
421
423
|
puts "reference to missing #{lnk.inspect}"
|
422
424
|
end
|
425
|
+
on.last.hclass('brokenlink')
|
423
426
|
end
|
424
|
-
on << Html::A.new(lnk, lnk)
|
425
427
|
end
|
426
428
|
end
|
427
429
|
on << s
|
data/samples/bindiff.rb
CHANGED
@@ -294,7 +294,6 @@ class BinDiffWidget < Gui::DrawableWidget
|
|
294
294
|
set_status('match funcs') {
|
295
295
|
# refine the layout matching with actual function matching
|
296
296
|
already_matched = []
|
297
|
-
match_score = {}
|
298
297
|
layout_match.each { |f1, list|
|
299
298
|
puts "matching #{Expression[f1]}" if $VERBOSE
|
300
299
|
begin
|
@@ -429,8 +428,8 @@ end
|
|
429
428
|
# show in window 1 the match of the function found in win 2
|
430
429
|
def sync1
|
431
430
|
c2 = curfunc2
|
432
|
-
if a1 = match_funcs.
|
433
|
-
@dasm1.gui.focus_addr(a1
|
431
|
+
if a1 = match_funcs.find_key { |k| match_funcs[k][0] == c2 }
|
432
|
+
@dasm1.gui.focus_addr(a1)
|
434
433
|
end
|
435
434
|
end
|
436
435
|
|
@@ -491,7 +490,7 @@ $VERBOSE = true
|
|
491
490
|
# parse arguments
|
492
491
|
opts = {}
|
493
492
|
OptionParser.new { |opt|
|
494
|
-
opt.banner = 'Usage: bindiff.rb [options] <
|
493
|
+
opt.banner = 'Usage: bindiff.rb [options] <exe1> <exe2> [<entrypoints>]'
|
495
494
|
opt.on('-P <plugin>', '--plugin <plugin>', 'load a metasm disassembler plugin') { |h| (opts[:plugin] ||= []) << h }
|
496
495
|
opt.on('-e <code>', '--eval <code>', 'eval a ruby code') { |h| (opts[:hookstr] ||= []) << h }
|
497
496
|
opt.on('--map1 <mapfile>', 'load a map file (addr <-> name association)') { |f| opts[:map1] = f }
|