metasm 1.0.1 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (235) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.hgtags +3 -0
  4. data/Gemfile +1 -0
  5. data/INSTALL +61 -0
  6. data/LICENCE +458 -0
  7. data/README +29 -21
  8. data/Rakefile +10 -0
  9. data/TODO +10 -12
  10. data/doc/code_organisation.txt +2 -0
  11. data/doc/core/DynLdr.txt +247 -0
  12. data/doc/core/ExeFormat.txt +43 -0
  13. data/doc/core/Expression.txt +220 -0
  14. data/doc/core/GNUExports.txt +27 -0
  15. data/doc/core/Ia32.txt +236 -0
  16. data/doc/core/SerialStruct.txt +108 -0
  17. data/doc/core/VirtualString.txt +145 -0
  18. data/doc/core/WindowsExports.txt +61 -0
  19. data/doc/core/index.txt +1 -0
  20. data/doc/style.css +6 -3
  21. data/doc/usage/debugger.txt +327 -0
  22. data/doc/usage/index.txt +1 -0
  23. data/doc/use_cases.txt +2 -2
  24. data/metasm.gemspec +22 -0
  25. data/{lib/metasm.rb → metasm.rb} +11 -3
  26. data/{lib/metasm → metasm}/compile_c.rb +13 -7
  27. data/metasm/cpu/arc.rb +8 -0
  28. data/metasm/cpu/arc/decode.rb +425 -0
  29. data/metasm/cpu/arc/main.rb +191 -0
  30. data/metasm/cpu/arc/opcodes.rb +588 -0
  31. data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
  32. data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
  33. data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
  34. data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
  35. data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
  36. data/metasm/cpu/arm/opcodes.rb +324 -0
  37. data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
  38. data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
  39. data/metasm/cpu/arm64.rb +15 -0
  40. data/metasm/cpu/arm64/debug.rb +38 -0
  41. data/metasm/cpu/arm64/decode.rb +289 -0
  42. data/metasm/cpu/arm64/encode.rb +41 -0
  43. data/metasm/cpu/arm64/main.rb +105 -0
  44. data/metasm/cpu/arm64/opcodes.rb +232 -0
  45. data/metasm/cpu/arm64/parse.rb +20 -0
  46. data/metasm/cpu/arm64/render.rb +95 -0
  47. data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
  48. data/metasm/cpu/bpf/decode.rb +142 -0
  49. data/metasm/cpu/bpf/main.rb +60 -0
  50. data/metasm/cpu/bpf/opcodes.rb +81 -0
  51. data/metasm/cpu/bpf/render.rb +41 -0
  52. data/metasm/cpu/cy16.rb +9 -0
  53. data/metasm/cpu/cy16/decode.rb +253 -0
  54. data/metasm/cpu/cy16/main.rb +63 -0
  55. data/metasm/cpu/cy16/opcodes.rb +78 -0
  56. data/metasm/cpu/cy16/render.rb +41 -0
  57. data/metasm/cpu/dalvik.rb +11 -0
  58. data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
  59. data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
  60. data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
  61. data/metasm/cpu/ia32.rb +17 -0
  62. data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
  63. data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
  64. data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
  65. data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
  66. data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
  67. data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
  68. data/metasm/cpu/ia32/opcodes.rb +1424 -0
  69. data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
  70. data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
  71. data/metasm/cpu/mips.rb +14 -0
  72. data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
  73. data/metasm/cpu/mips/debug.rb +42 -0
  74. data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
  75. data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
  76. data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
  77. data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
  78. data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
  79. data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
  80. data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
  81. data/metasm/cpu/msp430/decode.rb +247 -0
  82. data/metasm/cpu/msp430/main.rb +62 -0
  83. data/metasm/cpu/msp430/opcodes.rb +101 -0
  84. data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
  85. data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
  86. data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
  87. data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
  88. data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
  89. data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
  90. data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
  91. data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
  92. data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
  93. data/metasm/cpu/ppc/parse.rb +55 -0
  94. data/metasm/cpu/python.rb +8 -0
  95. data/metasm/cpu/python/decode.rb +136 -0
  96. data/metasm/cpu/python/main.rb +36 -0
  97. data/metasm/cpu/python/opcodes.rb +180 -0
  98. data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
  99. data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
  100. data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
  101. data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
  102. data/metasm/cpu/x86_64.rb +15 -0
  103. data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
  104. data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
  105. data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
  106. data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
  107. data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
  108. data/metasm/cpu/x86_64/opcodes.rb +136 -0
  109. data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
  110. data/metasm/cpu/x86_64/render.rb +35 -0
  111. data/metasm/cpu/z80.rb +9 -0
  112. data/metasm/cpu/z80/decode.rb +313 -0
  113. data/metasm/cpu/z80/main.rb +67 -0
  114. data/metasm/cpu/z80/opcodes.rb +224 -0
  115. data/metasm/cpu/z80/render.rb +59 -0
  116. data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
  117. data/{lib/metasm → metasm}/decode.rb +35 -4
  118. data/{lib/metasm → metasm}/decompile.rb +15 -16
  119. data/{lib/metasm → metasm}/disassemble.rb +201 -45
  120. data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
  121. data/{lib/metasm → metasm}/dynldr.rb +220 -133
  122. data/{lib/metasm → metasm}/encode.rb +10 -1
  123. data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
  124. data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
  125. data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
  126. data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
  127. data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
  128. data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
  129. data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
  130. data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
  131. data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
  132. data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
  133. data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
  134. data/metasm/exe_format/gb.rb +65 -0
  135. data/metasm/exe_format/javaclass.rb +424 -0
  136. data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
  137. data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
  138. data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
  139. data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
  140. data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
  141. data/metasm/exe_format/pyc.rb +167 -0
  142. data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
  143. data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
  144. data/metasm/exe_format/shellcode_rwx.rb +114 -0
  145. data/metasm/exe_format/swf.rb +205 -0
  146. data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
  147. data/metasm/exe_format/zip.rb +335 -0
  148. data/metasm/gui.rb +13 -0
  149. data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
  150. data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
  151. data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
  152. data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
  153. data/metasm/gui/dasm_graph.rb +1695 -0
  154. data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
  155. data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
  156. data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
  157. data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
  158. data/{lib/metasm → metasm}/gui/debug.rb +93 -27
  159. data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
  160. data/{lib/metasm → metasm}/gui/qt.rb +12 -2
  161. data/{lib/metasm → metasm}/gui/win32.rb +179 -42
  162. data/{lib/metasm → metasm}/gui/x11.rb +59 -59
  163. data/{lib/metasm → metasm}/main.rb +389 -264
  164. data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
  165. data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
  166. data/{lib/metasm → metasm}/os/linux.rb +628 -151
  167. data/metasm/os/main.rb +330 -0
  168. data/{lib/metasm → metasm}/os/windows.rb +132 -42
  169. data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
  170. data/{lib/metasm → metasm}/parse.rb +26 -24
  171. data/{lib/metasm → metasm}/parse_c.rb +221 -116
  172. data/{lib/metasm → metasm}/preprocessor.rb +55 -40
  173. data/{lib/metasm → metasm}/render.rb +14 -38
  174. data/misc/hexdump.rb +2 -1
  175. data/misc/lint.rb +58 -0
  176. data/misc/txt2html.rb +9 -7
  177. data/samples/bindiff.rb +3 -4
  178. data/samples/dasm-plugins/bindiff.rb +15 -0
  179. data/samples/dasm-plugins/bookmark.rb +133 -0
  180. data/samples/dasm-plugins/c_constants.rb +57 -0
  181. data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
  182. data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
  183. data/samples/dasm-plugins/dasm_all.rb +70 -0
  184. data/samples/dasm-plugins/demangle_cpp.rb +31 -0
  185. data/samples/dasm-plugins/deobfuscate.rb +251 -0
  186. data/samples/dasm-plugins/dump_text.rb +35 -0
  187. data/samples/dasm-plugins/export_graph_svg.rb +86 -0
  188. data/samples/dasm-plugins/findgadget.rb +75 -0
  189. data/samples/dasm-plugins/hl_opcode.rb +32 -0
  190. data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
  191. data/samples/dasm-plugins/imm2off.rb +34 -0
  192. data/samples/dasm-plugins/match_libsigs.rb +93 -0
  193. data/samples/dasm-plugins/patch_file.rb +95 -0
  194. data/samples/dasm-plugins/scanfuncstart.rb +36 -0
  195. data/samples/dasm-plugins/scanxrefs.rb +26 -0
  196. data/samples/dasm-plugins/selfmodify.rb +197 -0
  197. data/samples/dasm-plugins/stringsxrefs.rb +28 -0
  198. data/samples/dasmnavig.rb +1 -1
  199. data/samples/dbg-apihook.rb +24 -9
  200. data/samples/dbg-plugins/heapscan.rb +283 -0
  201. data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
  202. data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
  203. data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
  204. data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
  205. data/samples/dbg-plugins/heapscan/winheap.h +174 -0
  206. data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
  207. data/samples/dbg-plugins/trace_func.rb +214 -0
  208. data/samples/disassemble-gui.rb +35 -5
  209. data/samples/disassemble.rb +31 -6
  210. data/samples/dump_upx.rb +24 -12
  211. data/samples/dynamic_ruby.rb +12 -3
  212. data/samples/exeencode.rb +6 -5
  213. data/samples/factorize-headers-peimports.rb +1 -1
  214. data/samples/lindebug.rb +175 -381
  215. data/samples/metasm-shell.rb +1 -2
  216. data/samples/peldr.rb +2 -2
  217. data/tests/all.rb +1 -1
  218. data/tests/arc.rb +26 -0
  219. data/tests/dynldr.rb +22 -4
  220. data/tests/expression.rb +55 -0
  221. data/tests/graph_layout.rb +285 -0
  222. data/tests/ia32.rb +79 -26
  223. data/tests/mips.rb +9 -2
  224. data/tests/x86_64.rb +66 -18
  225. metadata +330 -218
  226. data/lib/metasm/arm/opcodes.rb +0 -177
  227. data/lib/metasm/gui.rb +0 -23
  228. data/lib/metasm/gui/dasm_graph.rb +0 -1354
  229. data/lib/metasm/ia32.rb +0 -14
  230. data/lib/metasm/ia32/opcodes.rb +0 -873
  231. data/lib/metasm/ppc/parse.rb +0 -52
  232. data/lib/metasm/x86_64.rb +0 -12
  233. data/lib/metasm/x86_64/opcodes.rb +0 -118
  234. data/samples/gdbclient.rb +0 -583
  235. data/samples/rubstop.rb +0 -399
@@ -139,7 +139,7 @@ class COFF
139
139
  end
140
140
 
141
141
  class ImportDirectory
142
- # encodes all import directories + iat
142
+ # encode all import directories + iat
143
143
  def self.encode(coff, ary)
144
144
  edata = { 'iat' => [] }
145
145
  %w[idata ilt nametable].each { |name| edata[name] = EncodedData.new }
@@ -160,12 +160,11 @@ class COFF
160
160
  [it, iat]
161
161
  end
162
162
 
163
- # encodes an import directory + iat + names in the edata hash received as arg
163
+ # encode one import directory + iat + names in the edata hash received as arg
164
164
  def encode(coff, edata)
165
165
  edata['iat'] << EncodedData.new
166
166
  # edata['ilt'] = edata['iat']
167
167
  label = lambda { |n| coff.label_at(edata[n], 0, n) }
168
- rva = lambda { |n| Expression[label[n], :-, coff.label_at(coff.encoded, 0)] }
169
168
  rva_end = lambda { |n| Expression[[label[n], :-, coff.label_at(coff.encoded, 0)], :+, edata[n].virtsize] }
170
169
 
171
170
  @libname_p = rva_end['nametable']
@@ -396,7 +395,8 @@ class COFF
396
395
  s.characteristics = %w[MEM_READ MEM_WRITE MEM_DISCARDABLE]
397
396
  encode_append_section s
398
397
 
399
- if @imports.first and @imports.first.iat_p.kind_of? Integer
398
+ if @imports.first and @imports.first.iat_p.kind_of?(Integer)
399
+ # ordiat = iat.sort_by { @import[x].iat_p }
400
400
  ordiat = @imports.zip(iat).sort_by { |id, it| id.iat_p.kind_of?(Integer) ? id.iat_p : 1<<65 }.map { |id, it| it }
401
401
  else
402
402
  ordiat = iat
@@ -413,7 +413,7 @@ class COFF
413
413
  plt.characteristics = %w[MEM_READ MEM_EXECUTE]
414
414
 
415
415
  @imports.zip(iat) { |id, it|
416
- if id.iat_p.kind_of? Integer and s = @sections.find { |s_| s_.virtaddr <= id.iat_p and s_.virtaddr + (s_.virtsize || s_.encoded.virtsize) > id.iat_p }
416
+ if id.iat_p.kind_of?(Integer) and @sections.find { |s_| s_.virtaddr <= id.iat_p and s_.virtaddr + (s_.virtsize || s_.encoded.virtsize) > id.iat_p }
417
417
  id.iat = it # will be fixed up after encode_section
418
418
  else
419
419
  # XXX should not be mixed (for @directory['iat'][1])
@@ -529,9 +529,7 @@ class COFF
529
529
  end
530
530
 
531
531
  # initialize reloc table base address if needed
532
- if not rt.base_addr
533
- rt.base_addr = off & ~0xfff
534
- end
532
+ rt.base_addr ||= off & ~0xfff
535
533
 
536
534
  (rt.relocs ||= []) << r
537
535
  elsif $DEBUG and not rel.target.bind(binding).reduce.kind_of?(Integer)
@@ -559,7 +557,7 @@ class COFF
559
557
  end
560
558
 
561
559
  # initialize the header from target/cpu/etc, target in ['exe' 'dll' 'kmod' 'obj']
562
- def pre_encode_header(target = 'exe', want_relocs=true)
560
+ def pre_encode_header(target='exe', want_relocs=true)
563
561
  target = {:bin => 'exe', :lib => 'dll', :obj => 'obj', 'sys' => 'kmod', 'drv' => 'kmod'}.fetch(target, target)
564
562
 
565
563
  @header.machine ||= case @cpu.shortname
@@ -650,11 +648,11 @@ class COFF
650
648
 
651
649
  # append the section bodies to @encoded, and link the resulting binary
652
650
  def encode_sections_fixup
653
- @encoded.align @optheader.file_align
654
651
  if @optheader.headers_size.kind_of?(::String)
655
652
  @encoded.fixup! @optheader.headers_size => @encoded.virtsize
656
653
  @optheader.headers_size = @encoded.virtsize
657
654
  end
655
+ @encoded.align @optheader.file_align
658
656
 
659
657
  baseaddr = @optheader.image_base.kind_of?(::Integer) ? @optheader.image_base : 0x400000
660
658
  binding = @encoded.binding(baseaddr)
@@ -689,7 +687,7 @@ class COFF
689
687
  # patch the iat where iat_p was defined
690
688
  # sort to ensure a 0-terminated will not overwrite an entry
691
689
  # (try to dump notepad.exe, which has a forwarder;)
692
- @imports.find_all { |id| id.iat_p.kind_of? Integer }.sort_by { |id| id.iat_p }.each { |id|
690
+ @imports.find_all { |id| id.iat_p.kind_of?(Integer) }.sort_by { |id| id.iat_p }.each { |id|
693
691
  s = sect_at_rva(id.iat_p)
694
692
  @encoded[s.rawaddr + s.encoded.ptr, id.iat.virtsize] = id.iat
695
693
  binding.update id.iat.binding(baseaddr + id.iat_p)
@@ -710,7 +708,7 @@ class COFF
710
708
  # creates the base relocation tables (need for references to IAT not known before)
711
709
  # defaults to generating relocatable files, eg ALSR-aware
712
710
  # pass want_relocs=false to avoid the file overhead induced by this
713
- def encode(target = 'exe', want_relocs = true)
711
+ def encode(target='exe', want_relocs=true)
714
712
  @encoded = EncodedData.new
715
713
  label_at(@encoded, 0, 'coff_start')
716
714
  pre_encode_header(target, want_relocs)
@@ -832,7 +830,7 @@ class COFF
832
830
  @lexer.unreadtok tok if not tok = @lexer.readtok or tok.type != :punct or tok.raw != '='
833
831
  raise instr, 'invalid base' if not s.virtaddr = Expression.parse(@lexer).reduce or not s.virtaddr.kind_of?(::Integer)
834
832
  if not @optheader.image_base
835
- @optheader.image_base = (s.virtaddr-0x80) & 0xfff00000
833
+ @optheader.image_base = (s.virtaddr-0x80) & 0xfff00000
836
834
  puts "Warning: no image_base specified, using #{Expression[@optheader.image_base]}" if $VERBOSE
837
835
  end
838
836
  s.virtaddr -= @optheader.image_base
@@ -43,6 +43,7 @@ class DEX < ExeFormat
43
43
 
44
44
 
45
45
  class SerialStruct < Metasm::SerialStruct
46
+ # TODO move uleb/sleb to new_field for sizeof
46
47
  new_int_field :u2, :u4, :uleb, :sleb
47
48
  end
48
49
 
@@ -135,7 +136,7 @@ class DEX < ExeFormat
135
136
 
136
137
  class MethodId < SerialStruct
137
138
  u2 :classidx
138
- u2 :typeidx
139
+ u2 :protoidx
139
140
  u4 :nameidx
140
141
  end
141
142
 
@@ -182,7 +183,7 @@ class DEX < ExeFormat
182
183
  uleb :fieldid_diff # this field id - array.previous field id
183
184
  uleb :access
184
185
 
185
- attr_accessor :field
186
+ attr_accessor :fieldid, :field
186
187
  end
187
188
 
188
189
  class EncodedMethod < SerialStruct
@@ -190,7 +191,7 @@ class DEX < ExeFormat
190
191
  uleb :access
191
192
  uleb :codeoff # offset to CodeItem
192
193
 
193
- attr_accessor :method, :code, :name
194
+ attr_accessor :methodid, :method, :code, :name
194
195
  end
195
196
 
196
197
  class TypeItem < SerialStruct
@@ -256,7 +257,7 @@ class DEX < ExeFormat
256
257
  uleb :typeidx
257
258
  uleb :handleroff
258
259
  end
259
-
260
+
260
261
  class Link < SerialStruct
261
262
  # undefined
262
263
  end
@@ -328,6 +329,8 @@ class DEX < ExeFormat
328
329
  def encode_u4(val) Expression[val].encode(:u32, @endianness) end
329
330
  def decode_u2(edata = @encoded) edata.decode_imm(:u16, @endianness) end
330
331
  def decode_u4(edata = @encoded) edata.decode_imm(:u32, @endianness) end
332
+ def sizeof_u2 ; 2 ; end
333
+ def sizeof_u4 ; 4 ; end
331
334
  def decode_uleb(ed = @encoded, signed=false)
332
335
  v = s = 0
333
336
  while s < 5*7
@@ -390,6 +393,7 @@ class DEX < ExeFormat
390
393
  (c.data.direct_methods + [0] + c.data.virtual_methods).each { |m|
391
394
  next id=0 if m == 0
392
395
  id += m.methodid_diff
396
+ m.methodid = id
393
397
  m.method = @methods[id]
394
398
  m.name = @strings[m.method.nameidx]
395
399
  @encoded.ptr = m.codeoff
@@ -441,7 +445,11 @@ class DEX < ExeFormat
441
445
  end
442
446
 
443
447
  def get_default_entrypoints
444
- []
448
+ @classes.find_all { |c| c.data }.map { |c|
449
+ (c.data.direct_methods + c.data.virtual_methods).map { |m|
450
+ m.codeoff+m.code.insns_off
451
+ }
452
+ }.flatten
445
453
  end
446
454
  end
447
455
 
@@ -26,6 +26,7 @@ class Dol < ExeFormat
26
26
 
27
27
  def decode_word(edata = @encoded) edata.decode_imm(:u32, @endianness) end
28
28
  def encode_word(w) Expression[w].encode(:u32, @endianness) end
29
+ def sizeof_word ; 4 ; end
29
30
 
30
31
  def initialize(cpu = nil)
31
32
  @endianness = :big
@@ -21,29 +21,52 @@ class ELF < ExeFormat
21
21
  TYPE_HIPROC = 0xffff
22
22
 
23
23
  MACHINE = {
24
- 0 => 'NONE', 1 => 'M32', 2 => 'SPARC', 3 => '386',
25
- 4 => '68K', 5 => '88K', 6 => '486', 7 => '860',
26
- 8 => 'MIPS', 9 => 'S370', 10 => 'MIPS_RS3_LE',
27
- 15 => 'PARISC',
28
- 17 => 'VPP500',18 => 'SPARC32PLUS', 19 => '960',
29
- 20 => 'PPC', 21 => 'PPC64', 22 => 'S390',
30
- 36 => 'V800', 37 => 'FR20', 38 => 'RH32', 39 => 'MCORE',
31
- 40 => 'ARM', 41 => 'ALPHA_STD', 42 => 'SH', 43 => 'SPARCV9',
32
- 44 => 'TRICORE', 45 => 'ARC', 46 => 'H8_300', 47 => 'H8_300H',
33
- 48 => 'H8S', 49 => 'H8_500', 50 => 'IA_64', 51 => 'MIPS_X',
24
+ 0 => 'NONE', 1 => 'M32', 2 => 'SPARC', 3 => '386',
25
+ 4 => '68K', 5 => '88K', 6 => '486', 7 => '860',
26
+ 8 => 'MIPS', 9 => 'S370', 10 => 'MIPS_RS3_LE',
27
+ 15 => 'PARISC', 17 => 'VPP500', 18 => 'SPARC32PLUS', 19 => '960',
28
+ 20 => 'PPC', 21 => 'PPC64', 22 => 'S390', 23 => 'SPU',
29
+ 36 => 'V800', 37 => 'FR20', 38 => 'RH32', 39 => 'MCORE',
30
+ 40 => 'ARM', 41 => 'ALPHA', 42 => 'SH', 43 => 'SPARCV9',
31
+ 44 => 'TRICORE', 45 => 'ARC', 46 => 'H8_300', 47 => 'H8_300H',
32
+ 48 => 'H8S', 49 => 'H8_500', 50 => 'IA_64', 51 => 'MIPS_X',
34
33
  52 => 'COLDFIRE', 53 => '68HC12', 54 => 'MMA', 55 => 'PCP',
35
- 56 => 'NCPU', 57 => 'NDR1', 58 => 'STARCORE', 59 => 'ME16',
36
- 60 => 'ST100', 61 => 'TINYJ', 62 => 'X86_64', 63 => 'PDSP',
37
- 66 => 'FX66', 67 => 'ST9PLUS',
38
- 68 => 'ST7', 69 => '68HC16', 70 => '68HC11', 71 => '68HC08',
39
- 72 => '68HC05',73 => 'SVX', 74 => 'ST19', 75 => 'VAX',
40
- 76 => 'CRIS', 77 => 'JAVELIN',78 => 'FIREPATH', 79 => 'ZSP',
41
- 80 => 'MMIX', 81 => 'HUANY', 82 => 'PRISM', 83 => 'AVR',
42
- 84 => 'FR30', 85 => 'D10V', 86 => 'D30V', 87 => 'V850',
43
- 88 => 'M32R', 89 => 'MN10300',90 => 'MN10200',91 => 'PJ',
44
- 92 => 'OPENRISC', 93 => 'ARC_A5', 94 => 'XTENSA',
45
- 99 => 'PJ',
46
- 0x9026 => 'ALPHA'
34
+ 56 => 'NCPU', 57 => 'NDR1', 58 => 'STARCORE', 59 => 'ME16',
35
+ 60 => 'ST100', 61 => 'TINYJ', 62 => 'X86_64', 63 => 'PDSP',
36
+ 64 => 'PDP10', 65 => 'PDP11', 66 => 'FX66', 67 => 'ST9PLUS',
37
+ 68 => 'ST7', 69 => '68HC16', 70 => '68HC11', 71 => '68HC08',
38
+ 72 => '68HC05',73 => 'SVX', 74 => 'ST19', 75 => 'VAX',
39
+ 76 => 'CRIS', 77 => 'JAVELIN',78 => 'FIREPATH', 79 => 'ZSP',
40
+ 80 => 'MMIX', 81 => 'HUANY', 82 => 'PRISM', 83 => 'AVR',
41
+ 84 => 'FR30', 85 => 'D10V', 86 => 'D30V', 87 => 'V850',
42
+ 88 => 'M32R', 89 => 'MN10300',90 => 'MN10200',91 => 'PJ',
43
+ 92 => 'OPENRISC', 93 => 'ARC_A5', 94 => 'XTENSA', 95 => 'VIDEOCORE',
44
+ 96 => 'TMM_GPP', 97 => 'NS32K', 98 => 'TPC', 99 => 'SNP1K',
45
+ 100 => 'ST200', 101 => 'IP2K', 102 => 'MAX', 103 => 'CR',
46
+ 104 => 'F2MC16', 105 => 'MSP430', 106 => 'BLACKFIN', 107 => 'SE_C33',
47
+ 108 => 'SEP', 109 => 'ARCA', 110 => 'UNICORE', 111 => 'EXCESS',
48
+ 112 => 'DXP', 113 => 'ALTERA_NIOS2', 114 => 'CRX', 115 => 'XGATE',
49
+ 116 => 'C166', 117 => 'M16C', 118 => 'DSPIC30F', 119 => 'CE',
50
+ 120 => 'M32C',
51
+ 131 => 'TSK3000', 132 => 'RS08', 133 => 'SHARC',
52
+ 134 => 'ECOG2', 135 => 'SCORE7', 136 => 'DSP24', 137 => 'VIDEOCORE3',
53
+ 138 => 'LATTICEMICO32', 139 => 'SE_C17', 140 => 'TI_C6000', 141 => 'TI_C2000',
54
+ 142 => 'TI_C5500',
55
+ 160 => 'MMDSP_PLUS', 161 => 'CYPRESS_M8C', 162 => 'R32C', 163 => 'TRIMEDIA',
56
+ 164 => 'QDSP6', 165 => '8051', 166 => 'STXP7X', 167 => 'NDS32',
57
+ 168 => 'ECOG1', 169 => 'MAXQ30', 170 => 'XIMO16', 171 => 'MANIK',
58
+ 172 => 'CRAYNV2', 173 => 'RX', 174 => 'METAG', 175 => 'MCST_ELBRUS',
59
+ 176 => 'ECOG16', 177 => 'CR16', 178 => 'ETPU', 179 => 'SLE9X',
60
+ 180 => 'L10M', 181 => 'K10M', 182 => 'INTEL_RESV', 183 => 'AARCH64',
61
+ 184 => 'ARM_RESV', 185 => 'AVR32', 186 => 'STM8', 187 => 'TILE64',
62
+ 188 => 'TILEPRO', 189 => 'MICROBLAZE', 190 => 'CUDA', 191 => 'TILEGX',
63
+ 192 => 'CLOUDSHIELD', 193 => 'COREA_1ST', 194 => 'COREA_2ND', 195 => 'ARC_COMPACT2',
64
+ 196 => 'OPEN8', 197 => 'RL78', 198 => 'VIDEOCORE5', 199 => '78KOR',
65
+ 200 => '56800EX', 201 => 'BA1', 202 => 'BA2', 203 => 'XCORE',
66
+ 204 => 'MCHP_PIC', 205 => 'INTEL205', 206 => 'INTEL206', 207 => 'INTEL207',
67
+ 208 => 'INTEL208', 209 => 'INTEL209', 210 => 'KM32', 211 => 'KMX32',
68
+ 212 => 'KMX16', 213 => 'KMX8', 214 => 'KVARC', 215 => 'CDP',
69
+ 216 => 'COGE', 217 => 'COOL', 218 => 'NORC',
47
70
  }
48
71
 
49
72
  FLAGS = {
@@ -52,8 +75,9 @@ class ELF < ExeFormat
52
75
  0x8000_0000 => 'LEDATA'},
53
76
  'SPARCV9' => {0 => 'TSO', 1 => 'PSO', 2 => 'RMO'}, # XXX not a flag
54
77
  'MIPS' => {1 => 'NOREORDER', 2 => 'PIC', 4 => 'CPIC',
55
- 8 => 'XGOT', 16 => '64BIT_WHIRL', 32 => 'ABI2',
56
- 64 => 'ABI_ON32'}
78
+ 8 => 'XGOT', 0x10 => '64BIT_WHIRL', 0x20 => 'ABI2',
79
+ 0x40 => 'ABI_ON32', 0x80 => 'OPTIONSFIRST',
80
+ 0x100 => '32BITMODE'}
57
81
  }
58
82
 
59
83
  DYNAMIC_TAG = { 0 => 'NULL', 1 => 'NEEDED', 2 => 'PLTRELSZ', 3 =>
@@ -300,6 +324,37 @@ class ELF < ExeFormat
300
324
  112 => 'EMB_RELST_LO', 113 => 'EMB_RELST_HI',
301
325
  114 => 'EMB_RELST_HA', 115 => 'EMB_BIT_FLD',
302
326
  116 => 'EMB_RELSDA' },
327
+ 'SH' => { 0 => 'NONE', 1 => 'DIR32', 2 => 'REL32', 3 => 'DIR8WPN',
328
+ 4 => 'IND12W', 5 => 'DIR8WPL', 6 => 'DIR8WPZ', 7 => 'DIR8BP',
329
+ 8 => 'DIR8W', 9 => 'DIR8L', 10 => 'LOOP_START', 11 => 'LOOP_END',
330
+ 22 => 'GNU_VTINHERIT', 23 => 'GNU_VTENTRY', 24 => 'SWITCH8',
331
+ 25 => 'SWITCH16', 26 => 'SWITCH32', 27 => 'USES', 28 => 'COUNT',
332
+ 29 => 'ALIGN', 30 => 'CODE', 31 => 'DATA', 32 => 'LABEL',
333
+ 33 => 'DIR16', 34 => 'DIR8', 35 => 'DIR8UL', 36 => 'DIR8UW',
334
+ 37 => 'DIR8U', 38 => 'DIR8SW', 39 => 'DIR8S', 40 => 'DIR4UL',
335
+ 41 => 'DIR4UW', 42 => 'DIR4U', 43 => 'PSHA', 44 => 'PSHL',
336
+ 45 => 'DIR5U', 46 => 'DIR6U', 47 => 'DIR6S', 48 => 'DIR10S',
337
+ 49 => 'DIR10SW', 50 => 'DIR10SL', 51 => 'DIR10SQ', 53 => 'DIR16S',
338
+ 144 => 'TLS_GD_32', 145 => 'TLS_LD_32', 146 => 'TLS_LDO_32',
339
+ 147 => 'TLS_IE_32', 148 => 'TLS_LE_32', 149 => 'TLS_DTPMOD32',
340
+ 150 => 'TLS_DTPOFF32', 151 => 'TLS_TPOFF32', 160 => 'GOT32',
341
+ 161 => 'PLT32', 162 => 'COPY', 163 => 'GLOB_DAT',
342
+ 164 => 'JMP_SLOT', 165 => 'RELATIVE', 166 => 'GOTOFF',
343
+ 167 => 'GOTPC', 168 => 'GOTPLT32', 169 => 'GOT_LOW16',
344
+ 170 => 'GOT_MEDLOW16', 171 => 'GOT_MEDHI16', 172 => 'GOT_HI16',
345
+ 173 => 'GOTPLT_LOW16', 174 => 'GOTPLT_MEDLOW16', 175 => 'GOTPLT_MEDHI16',
346
+ 176 => 'GOTPLT_HI16', 177 => 'PLT_LOW16', 178 => 'PLT_MEDLOW16',
347
+ 179 => 'PLT_MEDHI16', 180 => 'PLT_HI16', 181 => 'GOTOFF_LOW16',
348
+ 182 => 'GOTOFF_MEDLOW16', 183 => 'GOTOFF_MEDHI16', 184 => 'GOTOFF_HI16',
349
+ 185 => 'GOTPC_LOW16', 186 => 'GOTPC_MEDLOW16', 187 => 'GOTPC_MEDHI16',
350
+ 188 => 'GOTPC_HI16', 189 => 'GOT10BY4', 190 => 'GOTPLT10BY4',
351
+ 191 => 'GOT10BY8', 192 => 'GOTPLT10BY8', 193 => 'COPY64',
352
+ 194 => 'GLOB_DAT64', 195 => 'JMP_SLOT64', 196 => 'RELATIVE64',
353
+ 242 => 'SHMEDIA_CODE', 243 => 'PT_16', 244 => 'IMMS16',
354
+ 245 => 'IMMU16', 246 => 'IMM_LOW16', 247 => 'IMM_LOW16_PCREL',
355
+ 248 => 'IMM_MEDLOW16', 249 => 'IMM_MEDLOW16_PCREL', 250 => 'IMM_MEDHI16',
356
+ 251 => 'IMM_MEDHI16_PCREL', 252 => 'IMM_HI16', 253 => 'IMM_HI16_PCREL',
357
+ 254 => '64', 255 => '64_PCREL' },
303
358
  'SPARC' => { 0 => 'NONE', 1 => '8', 2 => '16', 3 => '32',
304
359
  4 => 'DISP8', 5 => 'DISP16', 6 => 'DISP32',
305
360
  7 => 'WDISP30', 8 => 'WDISP22', 9 => 'HI22',
@@ -362,11 +417,6 @@ class ELF < ExeFormat
362
417
  word :flags
363
418
  fld_bits(:flags) { |elf, hdr| FLAGS[hdr.machine] || {} }
364
419
  halfs :ehsize, :phentsize, :phnum, :shentsize, :shnum, :shstrndx
365
-
366
- def self.size elf
367
- x = elf.bitsize >> 3
368
- 40 + 3*x
369
- end
370
420
  end
371
421
 
372
422
  class Segment < SerialStruct
@@ -380,11 +430,6 @@ class ELF < ExeFormat
380
430
  else Segment64
381
431
  end
382
432
  end
383
-
384
- def self.size elf
385
- x = elf.bitsize >> 3
386
- 8 + 6*x
387
- end
388
433
  end
389
434
 
390
435
  class Segment32 < Segment
@@ -421,11 +466,6 @@ class ELF < ExeFormat
421
466
  xword :entsize
422
467
 
423
468
  attr_accessor :name, :encoded
424
-
425
- def self.size elf
426
- x = elf.bitsize >> 3
427
- 16 + 6*x
428
- end
429
469
  end
430
470
 
431
471
  class Symbol < SerialStruct
@@ -439,11 +479,6 @@ class ELF < ExeFormat
439
479
 
440
480
  attr_accessor :name_p, :value, :size, :bind, :type, :other, :shndx
441
481
  attr_accessor :name, :thunk
442
-
443
- def self.size elf
444
- x = elf.bitsize >> 3
445
- 8 + 2*x
446
- end
447
482
  end
448
483
 
449
484
  class Symbol32 < Symbol
@@ -478,12 +513,6 @@ class ELF < ExeFormat
478
513
  end
479
514
 
480
515
  def addend ; end
481
-
482
- def self.size elf
483
- x = elf.bitsize >> 3
484
- 2*x
485
- end
486
-
487
516
  end
488
517
  class Relocation32 < Relocation
489
518
  addr :offset
@@ -506,11 +535,6 @@ class ELF < ExeFormat
506
535
  else RelocationAddend64
507
536
  end
508
537
  end
509
- def self.size elf
510
- x = elf.bitsize >> 3
511
- 3*x
512
- end
513
-
514
538
  end
515
539
  class RelocationAddend32 < RelocationAddend
516
540
  addr :offset
@@ -637,6 +661,15 @@ class ELF < ExeFormat
637
661
  end
638
662
 
639
663
  def shortname; 'elf'; end
664
+
665
+ def sizeof_byte ; 1 ; end
666
+ def sizeof_half ; 2 ; end
667
+ def sizeof_word ; 4 ; end
668
+ def sizeof_sword ; 4 ; end
669
+ def sizeof_xword ; @bitsize == 32 ? 4 : 8 ; end
670
+ alias sizeof_sxword sizeof_xword
671
+ alias sizeof_addr sizeof_xword
672
+ alias sizeof_off sizeof_xword
640
673
  end
641
674
 
642
675
  class LoadedELF < ELF
@@ -689,6 +722,9 @@ class FatELF < ExeFormat
689
722
  def decode_byte(edata = @encoded) edata.decode_imm(:u8, @endianness) end
690
723
  def decode_word(edata = @encoded) edata.decode_imm(:u16, @endianness) end
691
724
  def decode_qword(edata = @encoded) edata.decode_imm(:u64, @endianness) end
725
+ def sizeof_byte ; 1 ; end
726
+ def sizeof_word ; 2 ; end
727
+ def sizeof_qword ; 8 ; end
692
728
 
693
729
  attr_accessor :header, :list
694
730
  def initialize
@@ -716,7 +752,7 @@ class FatELF < ExeFormat
716
752
  f.encoded = e.encode_string
717
753
  h = e.header
718
754
  f.machine, f.abi, f.abi_version, f.e_class, f.data =
719
- h.machine, h.abi, h.abi_version, h.e_class, h.data
755
+ h.machine, h.abi, h.abi_version, h.e_class, h.data
720
756
  end
721
757
  f.offset = new_label('fat_off')
722
758
  f.size = f.encoded.size
@@ -812,7 +848,7 @@ typedef struct { /* Verneed Auxiliary Structure. */
812
848
  Elf32_Word vna_next; /* no. of bytes from start of this */
813
849
  } Elf32_Vernaux; /* vernaux to next vernaux entry */
814
850
 
815
- typedef Elf32_Half Elf32_Versym; /* Version symbol index array */
851
+ typedef Elf32_Half Elf32_Versym; /* Version symbol index array */
816
852
 
817
853
  typedef struct {
818
854
  Elf32_Half si_boundto; /* direct bindings - symbol bound to */
@@ -18,19 +18,19 @@ class ELF
18
18
  case hdr.e_class
19
19
  when '32'; elf.bitsize = 32
20
20
  when '64', '64_icc'; elf.bitsize = 64
21
- else raise InvalidExeFormat, "E: ELF: unsupported class #{hdr.e_class}"
21
+ else puts "W: ELF: unsupported class #{hdr.e_class}, assuming 32bit"; elf.bitsize = 32
22
22
  end
23
23
 
24
24
  case hdr.data
25
25
  when 'LSB'; elf.endianness = :little
26
26
  when 'MSB'; elf.endianness = :big
27
- else raise InvalidExeFormat, "E: ELF: unsupported endianness #{hdr.data}"
27
+ else puts "W: ELF: unsupported endianness #{hdr.data}, assuming littleendian"; elf.endianness = :little
28
28
  end
29
29
 
30
30
  if hdr.i_version != 'CURRENT'
31
- raise InvalidExeFormat, "E: ELF: unsupported ELF version #{hdr.i_version}"
31
+ puts ":: ELF: unsupported ELF version #{hdr.i_version}"
32
32
  end
33
- }
33
+ }
34
34
  end
35
35
 
36
36
  class Symbol
@@ -66,7 +66,7 @@ class ELF
66
66
  # handles relocated LoadedELF
67
67
  def addr_to_fileoff(addr)
68
68
  la = module_address
69
- la = (la == 0 ? (@load_address ||= 0) : 0)
69
+ la = (la == 0 ? (@load_address ||= 0) : 0)
70
70
  addr_to_off(addr - la)
71
71
  end
72
72
 
@@ -75,7 +75,7 @@ class ELF
75
75
  def fileoff_to_addr(foff)
76
76
  if s = @segments.find { |s_| s_.type == 'LOAD' and s_.offset <= foff and s_.offset + s_.filesz > foff }
77
77
  la = module_address
78
- la = (la == 0 ? (@load_address ||= 0) : 0)
78
+ la = (la == 0 ? (@load_address ||= 0) : 0)
79
79
  s.vaddr + la + foff - s.offset
80
80
  end
81
81
  end
@@ -106,7 +106,7 @@ class ELF
106
106
  def decode_header(off = 0, decode_phdr=true, decode_shdr=true)
107
107
  @encoded.ptr = off
108
108
  @header.decode self
109
- raise InvalidExeFormat, "Invalid elf header size: #{@header.ehsize}" if Header.size(self) != @header.ehsize
109
+ raise InvalidExeFormat, "Invalid elf header size: #{@header.ehsize}" if Header.sizeof(self) != @header.ehsize
110
110
  if decode_phdr and @header.phoff != 0
111
111
  decode_program_header(@header.phoff+off)
112
112
  end
@@ -118,7 +118,7 @@ class ELF
118
118
  # decodes the section header
119
119
  # section names are read from shstrndx if possible
120
120
  def decode_section_header(off = @header.shoff)
121
- raise InvalidExeFormat, "Invalid elf section header size: #{@header.shentsize}" if Section.size(self) != @header.shentsize
121
+ raise InvalidExeFormat, "Invalid elf section header size: #{@header.shentsize}" if Section.sizeof(self) != @header.shentsize
122
122
  @encoded.add_export new_label('section_header'), off
123
123
  @encoded.ptr = off
124
124
  @sections = []
@@ -137,7 +137,7 @@ class ELF
137
137
  # decodes the program header table
138
138
  # marks the elf entrypoint as an export of +self.encoded+
139
139
  def decode_program_header(off = @header.phoff)
140
- raise InvalidExeFormat, "Invalid elf program header size: #{@header.phentsize}" if Segment.size(self) != @header.phentsize
140
+ raise InvalidExeFormat, "Invalid elf program header size: #{@header.phentsize}" if Segment.sizeof(self) != @header.phentsize
141
141
  @encoded.add_export new_label('program_header'), off
142
142
  @encoded.ptr = off
143
143
  @segments = []
@@ -224,7 +224,40 @@ class ELF
224
224
  # (gnu_hash(sym[N].name) & ~1) | (N == dynsymcount-1 || (gnu_hash(sym[N].name) % nbucket) != (gnu_hash(sym[N+1].name) % nbucket))
225
225
  # that's the hash, with its lower bit replaced by the bool [1 if i am the last sym having my hash as hash]
226
226
 
227
- return hsymcount+symndx if just_get_count
227
+ # we're going to decode the symbol table, and we just want to get the nr of symbols to read
228
+ if just_get_count
229
+ # index of highest hashed (exported) symbols
230
+ ns = hsymcount+symndx
231
+
232
+ # no way to get the number of non-exported symbols from what we have here
233
+ # so we'll decode all relocs and use the largest index we see..
234
+ rels = []
235
+ if @encoded.ptr = @tag['REL'] and @tag['RELENT'] == Relocation.sizeof(self)
236
+ p_end = @encoded.ptr + @tag['RELSZ']
237
+ while @encoded.ptr < p_end
238
+ rels << Relocation.decode(self)
239
+ end
240
+ end
241
+ if @encoded.ptr = @tag['RELA'] and @tag['RELAENT'] == RelocationAddend.sizeof(self)
242
+ p_end = @encoded.ptr + @tag['RELASZ']
243
+ while @encoded.ptr < p_end
244
+ rels << RelocationAddend.decode(self)
245
+ end
246
+ end
247
+ if @encoded.ptr = @tag['JMPREL'] and relcls = case @tag['PLTREL']
248
+ when 'REL'; Relocation
249
+ when 'RELA'; RelocationAddend
250
+ end
251
+ p_end = @encoded.ptr + @tag['PLTRELSZ']
252
+ while @encoded.ptr < p_end
253
+ rels << relcls.decode(self)
254
+ end
255
+ end
256
+ maxr = rels.map { |rel| rel.symbol }.grep(::Integer).max || -1
257
+
258
+ return [ns, maxr+1].max
259
+ end
260
+
228
261
 
229
262
  # TODO
230
263
  end
@@ -359,7 +392,7 @@ class ELF
359
392
  def decode_segments_symbols
360
393
  return unless @tag['STRTAB'] and @tag['STRSZ'] and @tag['SYMTAB'] and (@tag['HASH'] or @tag['GNU_HASH'])
361
394
 
362
- raise "E: ELF: unsupported symbol entry size: #{@tag['SYMENT']}" if @tag['SYMENT'] != Symbol.size(self)
395
+ raise "E: ELF: unsupported symbol entry size: #{@tag['SYMENT']}" if @tag['SYMENT'] != Symbol.sizeof(self)
363
396
 
364
397
  # find number of symbols
365
398
  if @tag['HASH']
@@ -394,14 +427,16 @@ class ELF
394
427
  @encoded.ptr = sec.offset
395
428
  syms = []
396
429
  raise 'Invalid symbol table' if sec.size > @encoded.length
397
- (sec.size / Symbol.size(self)).times { syms << Symbol.decode(self, strtab) }
430
+ (sec.size / Symbol.sizeof(self)).times { syms << Symbol.decode(self, strtab) }
398
431
  alreadysegs = true if @header.type == 'DYN' or @header.type == 'EXEC'
432
+ alreadysyms = @symbols.inject({}) { |h, s| h.update s.name => true } if alreadysegs
399
433
  syms.each { |s|
400
434
  if alreadysegs
401
435
  # if we already decoded the symbols from the DYNAMIC segment,
402
436
  # ignore dups and imports from this section
403
437
  next if s.shndx == 'UNDEF'
404
- next if @symbols.find { |ss| ss.name == s.name }
438
+ next if alreadysyms[s.name]
439
+ alreadysyms[s.name] = true
405
440
  end
406
441
  @symbols << s
407
442
  decode_symbol_export(s)
@@ -445,7 +480,7 @@ class ELF
445
480
  def decode_segments_relocs
446
481
  @relocations.clear
447
482
  if @encoded.ptr = @tag['REL']
448
- raise "E: ELF: unsupported rel entry size #{@tag['RELENT']}" if @tag['RELENT'] != Relocation.size(self)
483
+ raise "E: ELF: unsupported rel entry size #{@tag['RELENT']}" if @tag['RELENT'] != Relocation.sizeof(self)
449
484
  p_end = @encoded.ptr + @tag['RELSZ']
450
485
  while @encoded.ptr < p_end
451
486
  @relocations << Relocation.decode(self)
@@ -453,7 +488,7 @@ class ELF
453
488
  end
454
489
 
455
490
  if @encoded.ptr = @tag['RELA']
456
- raise "E: ELF: unsupported rela entry size #{@tag['RELAENT'].inspect}" if @tag['RELAENT'] != RelocationAddend.size(self)
491
+ raise "E: ELF: unsupported rela entry size #{@tag['RELAENT'].inspect}" if @tag['RELAENT'] != RelocationAddend.sizeof(self)
457
492
  p_end = @encoded.ptr + @tag['RELASZ']
458
493
  while @encoded.ptr < p_end
459
494
  @relocations << RelocationAddend.decode(self)
@@ -509,10 +544,28 @@ class ELF
509
544
  end
510
545
  end
511
546
 
547
+ # returns the target of a relocation using reloc.symbol
548
+ # may create new labels if the relocation targets a section
549
+ def reloc_target(reloc)
550
+ target = 0
551
+ if reloc.symbol.kind_of?(Symbol)
552
+ if reloc.symbol.type == 'SECTION'
553
+ s = @sections[reloc.symbol.shndx]
554
+ if not target = @encoded.inv_export[s.offset]
555
+ target = new_label(s.name)
556
+ @encoded.add_export(target, s.offset)
557
+ end
558
+ elsif reloc.symbol.name
559
+ target = reloc.symbol.name
560
+ end
561
+ end
562
+ target
563
+ end
564
+
512
565
  # returns the Metasm::Relocation that should be applied for reloc
513
566
  # self.encoded.ptr must point to the location that will be relocated (for implicit addends)
514
567
  def arch_decode_segments_reloc_386(reloc)
515
- if reloc.symbol and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
568
+ if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
516
569
  s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
517
570
  @encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
518
571
  end
@@ -541,15 +594,14 @@ class ELF
541
594
  when 'GLOB_DAT', 'JMP_SLOT', '32', 'PC32', 'TLS_TPOFF', 'TLS_TPOFF32'
542
595
  # XXX use versionned version
543
596
  # lazy jmp_slot ?
544
- target = 0
545
- target = reloc.symbol.name if reloc.symbol.kind_of?(Symbol) and reloc.symbol.name
597
+ target = reloc_target(reloc)
546
598
  target = Expression[target, :-, reloc.offset] if reloc.type == 'PC32'
547
599
  target = Expression[target, :+, addend] if addend and addend != 0
548
600
  target = Expression[target, :+, 'tlsoffset'] if reloc.type == 'TLS_TPOFF'
549
601
  target = Expression[:-, [target, :+, 'tlsoffset']] if reloc.type == 'TLS_TPOFF32'
550
602
  when 'COPY'
551
603
  # mark the address pointed as a copy of the relocation target
552
- if not reloc.symbol or not name = reloc.symbol.name
604
+ if not reloc.symbol.kind_of?(Symbol) or not name = reloc.symbol.name
553
605
  puts "W: Elf: symbol to COPY has no name: #{reloc.inspect}" if $VERBOSE
554
606
  name = ''
555
607
  end
@@ -567,24 +619,40 @@ class ELF
567
619
  # returns the Metasm::Relocation that should be applied for reloc
568
620
  # self.encoded.ptr must point to the location that will be relocated (for implicit addends)
569
621
  def arch_decode_segments_reloc_mips(reloc)
570
- if reloc.symbol and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
622
+ if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
571
623
  s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
572
624
  @encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
573
625
  end
574
626
 
627
+ original_word = decode_word
628
+
575
629
  # decode addend if needed
576
630
  case reloc.type
577
631
  when 'NONE' # no addend
578
- else addend = reloc.addend || decode_sword
632
+ else addend = reloc.addend || Expression.make_signed(original_word, 32)
579
633
  end
580
634
 
581
635
  case reloc.type
582
636
  when 'NONE'
583
637
  when '32', 'REL32'
584
- target = 0
585
- target = reloc.symbol.name if reloc.symbol.kind_of?(Symbol) and reloc.symbol.name
638
+ target = reloc_target(reloc)
586
639
  target = Expression[target, :-, reloc.offset] if reloc.type == 'REL32'
587
640
  target = Expression[target, :+, addend] if addend and addend != 0
641
+ when '26'
642
+ target = reloc_target(reloc)
643
+ addend &= 0x3ff_ffff
644
+ target = Expression[target, :+, [addend, :<<, 2]] if addend and addend != 0
645
+ target = Expression[[original_word, :&, 0xfc0_0000], :|, [[target, :&, 0x3ff_ffff], :>>, 2]]
646
+ when 'HI16'
647
+ target = reloc_target(reloc)
648
+ addend &= 0xffff
649
+ target = Expression[target, :+, [addend, :<<, 16]] if addend and addend != 0
650
+ target = Expression[[original_word, :&, 0xffff_0000], :|, [[target, :>>, 16], :&, 0xffff]]
651
+ when 'LO16'
652
+ target = reloc_target(reloc)
653
+ addend &= 0xffff
654
+ target = Expression[target, :+, addend] if addend and addend != 0
655
+ target = Expression[[original_word, :&, 0xffff_0000], :|, [target, :&, 0xffff]]
588
656
  else
589
657
  puts "W: Elf: unhandled MIPS reloc #{reloc.inspect}" if $VERBOSE
590
658
  target = nil
@@ -596,7 +664,7 @@ class ELF
596
664
  # returns the Metasm::Relocation that should be applied for reloc
597
665
  # self.encoded.ptr must point to the location that will be relocated (for implicit addends)
598
666
  def arch_decode_segments_reloc_x86_64(reloc)
599
- if reloc.symbol and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
667
+ if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
600
668
  s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
601
669
  @encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
602
670
  end
@@ -627,14 +695,13 @@ class ELF
627
695
  when 'GLOB_DAT', 'JMP_SLOT', '64', 'PC64', '32', 'PC32'
628
696
  # XXX use versionned version
629
697
  # lazy jmp_slot ?
630
- target = 0
631
- target = reloc.symbol.name if reloc.symbol.kind_of?(Symbol) and reloc.symbol.name
698
+ target = reloc_target(reloc)
632
699
  target = Expression[target, :-, reloc.offset] if reloc.type == 'PC64' or reloc.type == 'PC32'
633
700
  target = Expression[target, :+, addend] if addend and addend != 0
634
701
  sz = :u32 if reloc.type == '32' or reloc.type == 'PC32'
635
702
  when 'COPY'
636
703
  # mark the address pointed as a copy of the relocation target
637
- if not reloc.symbol or not name = reloc.symbol.name
704
+ if not reloc.symbol.kind_of?(Symbol) or not name = reloc.symbol.name
638
705
  puts "W: Elf: symbol to COPY has no name: #{reloc.inspect}" if $VERBOSE
639
706
  name = ''
640
707
  end
@@ -649,6 +716,33 @@ class ELF
649
716
  Metasm::Relocation.new(Expression[target], sz, @endianness) if target
650
717
  end
651
718
 
719
+ def arch_decode_segments_reloc_sh(reloc)
720
+ if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
721
+ s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
722
+ @encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
723
+ end
724
+
725
+ original_word = decode_word
726
+
727
+ # decode addend if needed
728
+ case reloc.type
729
+ when 'NONE' # no addend
730
+ else addend = reloc.addend || Expression.make_signed(original_word, 32)
731
+ end
732
+
733
+ case reloc.type
734
+ when 'NONE'
735
+ when 'GLOB_DAT', 'JMP_SLOT'
736
+ target = reloc_target(reloc)
737
+ target = Expression[target, :+, addend] if addend and addend != 0
738
+ else
739
+ puts "W: Elf: unhandled SH reloc #{reloc.inspect}" if $VERBOSE
740
+ target = nil
741
+ end
742
+
743
+ Metasm::Relocation.new(Expression[target], :u32, @endianness) if target
744
+ end
745
+
652
746
  class DwarfDebug
653
747
  # decode a DWARF2 'compilation unit'
654
748
  def decode(elf, info, abbrev, str)
@@ -749,12 +843,13 @@ class ELF
749
843
  end
750
844
 
751
845
  # decodes the ELF dynamic tags, interpret them, and decodes symbols and relocs
752
- def decode_segments_dynamic
846
+ def decode_segments_dynamic(decode_relocs=true)
753
847
  return if not dynamic = @segments.find { |s| s.type == 'DYNAMIC' }
754
848
  @encoded.ptr = add_label('dynamic_tags', dynamic.vaddr)
755
849
  decode_tags
756
850
  decode_segments_tags_interpret
757
851
  decode_segments_symbols
852
+ return if not decode_relocs
758
853
  decode_segments_relocs
759
854
  decode_segments_relocs_interpret
760
855
  end
@@ -783,6 +878,7 @@ class ELF
783
878
 
784
879
  # decodes sections, interprets symbols/relocs, fills sections.encoded
785
880
  def decode_sections
881
+ @symbols.clear # the NULL symbol is explicit in the symbol table
786
882
  decode_sections_symbols
787
883
  decode_sections_relocs
788
884
  @sections.each { |s|
@@ -804,7 +900,7 @@ class ELF
804
900
  end
805
901
 
806
902
  def decode_exports
807
- decode_segments_dynamic
903
+ decode_segments_dynamic(false)
808
904
  end
809
905
 
810
906
  # decodes the elf header, and depending on the elf type, decode segments or sections
@@ -819,12 +915,14 @@ class ELF
819
915
 
820
916
  def each_section
821
917
  @segments.each { |s| yield s.encoded, s.vaddr if s.type == 'LOAD' }
822
- return if @header.type != 'REL'
918
+ return if @header.type != 'REL'
823
919
  @sections.each { |s|
824
920
  next if not s.encoded
825
- l = new_label(s.name)
826
- s.encoded.add_export l, 0
827
- yield s.encoded, l
921
+ if not l = s.encoded.inv_export[0] or l != s.name.tr('^a-zA-Z0-9_', '_')
922
+ l = new_label(s.name)
923
+ s.encoded.add_export l, 0
924
+ end
925
+ yield s.encoded, l
828
926
  }
829
927
  end
830
928
 
@@ -833,9 +931,13 @@ class ELF
833
931
  case @header.machine
834
932
  when 'X86_64'; X86_64.new
835
933
  when '386'; Ia32.new
836
- when 'MIPS'; MIPS.new @endianness
934
+ when 'MIPS'; (@header.flags.include?('32BITMODE') ? MIPS64 : MIPS).new @endianness
837
935
  when 'PPC'; PPC.new
838
936
  when 'ARM'; ARM.new
937
+ when 'AARCH64'; AArch64.new
938
+ when 'SH'; Sh4.new
939
+ when 'ARC_COMPACT'; ARC.new
940
+ when 'MSP430'; MSP430.new
839
941
  else raise "unsupported cpu #{@header.machine}"
840
942
  end
841
943
  end
@@ -912,6 +1014,13 @@ EOC
912
1014
  (d.address_binding[s.value] ||= {})[:$t9] ||= Expression[s.value]
913
1015
  }
914
1016
  d.function[:default] = @cpu.disassembler_default_func
1017
+ when 'sh4'
1018
+ noret = DecodedFunction.new
1019
+ noret.noreturn = true
1020
+ %w[__stack_chk_fail abort exit].each { |fn|
1021
+ d.function[Expression[fn]] = noret
1022
+ }
1023
+ d.function[:default] = @cpu.disassembler_default_func
915
1024
  end
916
1025
  d
917
1026
  end