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.
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