metasm 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.hgtags +3 -0
- data/Gemfile +1 -0
- data/INSTALL +61 -0
- data/LICENCE +458 -0
- data/README +29 -21
- data/Rakefile +10 -0
- data/TODO +10 -12
- data/doc/code_organisation.txt +2 -0
- data/doc/core/DynLdr.txt +247 -0
- data/doc/core/ExeFormat.txt +43 -0
- data/doc/core/Expression.txt +220 -0
- data/doc/core/GNUExports.txt +27 -0
- data/doc/core/Ia32.txt +236 -0
- data/doc/core/SerialStruct.txt +108 -0
- data/doc/core/VirtualString.txt +145 -0
- data/doc/core/WindowsExports.txt +61 -0
- data/doc/core/index.txt +1 -0
- data/doc/style.css +6 -3
- data/doc/usage/debugger.txt +327 -0
- data/doc/usage/index.txt +1 -0
- data/doc/use_cases.txt +2 -2
- data/metasm.gemspec +22 -0
- data/{lib/metasm.rb → metasm.rb} +11 -3
- data/{lib/metasm → metasm}/compile_c.rb +13 -7
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +425 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/{lib/metasm → metasm/cpu}/arm.rb +7 -5
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +13 -12
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +0 -3
- data/metasm/cpu/arm/opcodes.rb +324 -0
- data/{lib/metasm → metasm/cpu}/arm/parse.rb +25 -13
- data/{lib/metasm → metasm/cpu}/arm/render.rb +2 -2
- data/metasm/cpu/arm64.rb +15 -0
- data/metasm/cpu/arm64/debug.rb +38 -0
- data/metasm/cpu/arm64/decode.rb +289 -0
- data/metasm/cpu/arm64/encode.rb +41 -0
- data/metasm/cpu/arm64/main.rb +105 -0
- data/metasm/cpu/arm64/opcodes.rb +232 -0
- data/metasm/cpu/arm64/parse.rb +20 -0
- data/metasm/cpu/arm64/render.rb +95 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/bpf.rb} +2 -4
- data/metasm/cpu/bpf/decode.rb +142 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +41 -0
- data/metasm/cpu/cy16.rb +9 -0
- data/metasm/cpu/cy16/decode.rb +253 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +41 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +35 -13
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +51 -2
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +19 -11
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +5 -7
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +5 -5
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +246 -59
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +7 -7
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +51 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +47 -16
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +31 -4
- data/metasm/cpu/mips.rb +14 -0
- data/{lib/metasm → metasm/cpu}/mips/compile_c.rb +1 -1
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +46 -16
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +11 -4
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +86 -17
- data/{lib/metasm → metasm/cpu}/mips/parse.rb +1 -1
- data/{lib/metasm → metasm/cpu}/mips/render.rb +1 -1
- data/{lib/metasm/dalvik.rb → metasm/cpu/msp430.rb} +1 -1
- data/metasm/cpu/msp430/decode.rb +247 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/{lib/metasm → metasm/cpu}/pic16c/decode.rb +6 -7
- data/{lib/metasm → metasm/cpu}/pic16c/main.rb +0 -0
- data/{lib/metasm → metasm/cpu}/pic16c/opcodes.rb +1 -1
- data/{lib/metasm/mips.rb → metasm/cpu/ppc.rb} +4 -4
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -12
- data/{lib/metasm → metasm/cpu}/ppc/decompile.rb +3 -3
- data/{lib/metasm → metasm/cpu}/ppc/encode.rb +2 -2
- data/{lib/metasm → metasm/cpu}/ppc/main.rb +17 -12
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -5
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +136 -0
- data/metasm/cpu/python/main.rb +36 -0
- data/metasm/cpu/python/opcodes.rb +180 -0
- data/{lib/metasm → metasm/cpu}/sh4.rb +1 -1
- data/{lib/metasm → metasm/cpu}/sh4/decode.rb +48 -17
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +13 -4
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +28 -17
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +57 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +55 -26
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +14 -6
- data/metasm/cpu/x86_64/opcodes.rb +136 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +10 -2
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +313 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +59 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +160 -401
- data/{lib/metasm → metasm}/decode.rb +35 -4
- data/{lib/metasm → metasm}/decompile.rb +15 -16
- data/{lib/metasm → metasm}/disassemble.rb +201 -45
- data/{lib/metasm → metasm}/disassemble_api.rb +651 -87
- data/{lib/metasm → metasm}/dynldr.rb +220 -133
- data/{lib/metasm → metasm}/encode.rb +10 -1
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +11 -3
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +53 -20
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +11 -13
- data/{lib/metasm → metasm}/exe_format/dex.rb +13 -5
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +93 -57
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +143 -34
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +122 -31
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +204 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +26 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +71 -8
- data/metasm/exe_format/pyc.rb +167 -0
- data/{lib/metasm → metasm}/exe_format/serialstruct.rb +67 -14
- data/{lib/metasm → metasm}/exe_format/shellcode.rb +7 -3
- data/metasm/exe_format/shellcode_rwx.rb +114 -0
- data/metasm/exe_format/swf.rb +205 -0
- data/{lib/metasm → metasm}/exe_format/xcoff.rb +7 -7
- data/metasm/exe_format/zip.rb +335 -0
- data/metasm/gui.rb +13 -0
- data/{lib/metasm → metasm}/gui/cstruct.rb +35 -41
- data/{lib/metasm → metasm}/gui/dasm_coverage.rb +11 -11
- data/{lib/metasm → metasm}/gui/dasm_decomp.rb +7 -20
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1695 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +12 -8
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +310 -53
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +93 -27
- data/{lib/metasm → metasm}/gui/gtk.rb +162 -40
- data/{lib/metasm → metasm}/gui/qt.rb +12 -2
- data/{lib/metasm → metasm}/gui/win32.rb +179 -42
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +389 -264
- data/{lib/metasm/os/remote.rb → metasm/os/gdbremote.rb} +146 -54
- data/{lib/metasm → metasm}/os/gnu_exports.rb +1 -1
- data/{lib/metasm → metasm}/os/linux.rb +628 -151
- data/metasm/os/main.rb +330 -0
- data/{lib/metasm → metasm}/os/windows.rb +132 -42
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +26 -24
- data/{lib/metasm → metasm}/parse_c.rb +221 -116
- data/{lib/metasm → metasm}/preprocessor.rb +55 -40
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +2 -1
- data/misc/lint.rb +58 -0
- data/misc/txt2html.rb +9 -7
- data/samples/bindiff.rb +3 -4
- data/samples/dasm-plugins/bindiff.rb +15 -0
- data/samples/dasm-plugins/bookmark.rb +133 -0
- data/samples/dasm-plugins/c_constants.rb +57 -0
- data/samples/dasm-plugins/colortheme_solarized.rb +125 -0
- data/samples/dasm-plugins/cppobj_funcall.rb +60 -0
- data/samples/dasm-plugins/dasm_all.rb +70 -0
- data/samples/dasm-plugins/demangle_cpp.rb +31 -0
- data/samples/dasm-plugins/deobfuscate.rb +251 -0
- data/samples/dasm-plugins/dump_text.rb +35 -0
- data/samples/dasm-plugins/export_graph_svg.rb +86 -0
- data/samples/dasm-plugins/findgadget.rb +75 -0
- data/samples/dasm-plugins/hl_opcode.rb +32 -0
- data/samples/dasm-plugins/hotfix_gtk_dbg.rb +19 -0
- data/samples/dasm-plugins/imm2off.rb +34 -0
- data/samples/dasm-plugins/match_libsigs.rb +93 -0
- data/samples/dasm-plugins/patch_file.rb +95 -0
- data/samples/dasm-plugins/scanfuncstart.rb +36 -0
- data/samples/dasm-plugins/scanxrefs.rb +26 -0
- data/samples/dasm-plugins/selfmodify.rb +197 -0
- data/samples/dasm-plugins/stringsxrefs.rb +28 -0
- data/samples/dasmnavig.rb +1 -1
- data/samples/dbg-apihook.rb +24 -9
- data/samples/dbg-plugins/heapscan.rb +283 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_lin.c +155 -0
- data/samples/dbg-plugins/heapscan/compiled_heapscan_win.c +128 -0
- data/samples/dbg-plugins/heapscan/graphheap.rb +616 -0
- data/samples/dbg-plugins/heapscan/heapscan.rb +709 -0
- data/samples/dbg-plugins/heapscan/winheap.h +174 -0
- data/samples/dbg-plugins/heapscan/winheap7.h +307 -0
- data/samples/dbg-plugins/trace_func.rb +214 -0
- data/samples/disassemble-gui.rb +35 -5
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +12 -3
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +175 -381
- data/samples/metasm-shell.rb +1 -2
- data/samples/peldr.rb +2 -2
- data/tests/all.rb +1 -1
- data/tests/arc.rb +26 -0
- data/tests/dynldr.rb +22 -4
- data/tests/expression.rb +55 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +79 -26
- data/tests/mips.rb +9 -2
- data/tests/x86_64.rb +66 -18
- metadata +330 -218
- data/lib/metasm/arm/opcodes.rb +0 -177
- data/lib/metasm/gui.rb +0 -23
- data/lib/metasm/gui/dasm_graph.rb +0 -1354
- data/lib/metasm/ia32.rb +0 -14
- data/lib/metasm/ia32/opcodes.rb +0 -873
- data/lib/metasm/ppc/parse.rb +0 -52
- data/lib/metasm/x86_64.rb +0 -12
- data/lib/metasm/x86_64/opcodes.rb +0 -118
- data/samples/gdbclient.rb +0 -583
- data/samples/rubstop.rb +0 -399
|
@@ -20,10 +20,10 @@ class ELF
|
|
|
20
20
|
@phoff ||= elf.segments.empty? ? 0 : elf.new_label('phdr')
|
|
21
21
|
@shoff ||= elf.sections.length <= 1 ? 0 : elf.new_label('shdr')
|
|
22
22
|
@flags ||= []
|
|
23
|
-
@ehsize ||= Header.
|
|
24
|
-
@phentsize ||= Segment.
|
|
23
|
+
@ehsize ||= Header.sizeof(elf)
|
|
24
|
+
@phentsize ||= Segment.sizeof(elf)
|
|
25
25
|
@phnum ||= elf.segments.length
|
|
26
|
-
@shentsize ||= Section.
|
|
26
|
+
@shentsize ||= Section.sizeof(elf)
|
|
27
27
|
@shnum ||= elf.sections.length
|
|
28
28
|
|
|
29
29
|
super(elf)
|
|
@@ -47,8 +47,8 @@ class ELF
|
|
|
47
47
|
# defines the @name_p field from @name and elf.section[elf.header.shstrndx]
|
|
48
48
|
# creates .shstrtab if needed
|
|
49
49
|
def make_name_p elf
|
|
50
|
-
return 0 if not name or @name == ''
|
|
51
|
-
if elf.header.shstrndx.to_i == 0
|
|
50
|
+
return 0 if not name or @name == '' or elf.header.shnum == 0
|
|
51
|
+
if elf.header.shstrndx.to_i == 0 or not elf.sections[elf.header.shstrndx]
|
|
52
52
|
sn = Section.new
|
|
53
53
|
sn.name = '.shstrtab'
|
|
54
54
|
sn.type = 'STRTAB'
|
|
@@ -140,6 +140,9 @@ class ELF
|
|
|
140
140
|
srank = rank[s]
|
|
141
141
|
nexts = @sections.find { |sec| rank[sec] > srank } # find section with rank superior
|
|
142
142
|
nexts = nexts ? @sections.index(nexts) : -1 # if none, last
|
|
143
|
+
if @header.shstrndx.to_i != 0 and nexts != -1 and @header.shstrndx >= nexts
|
|
144
|
+
@header.shstrndx += 1
|
|
145
|
+
end
|
|
143
146
|
@sections.insert(nexts, s) # insert section
|
|
144
147
|
end
|
|
145
148
|
|
|
@@ -196,6 +199,8 @@ class ELF
|
|
|
196
199
|
|
|
197
200
|
# encodes the symbol dynamic hash table in the .hash section, updates the HASH tag
|
|
198
201
|
def encode_hash
|
|
202
|
+
return if @symbols.length <= 1
|
|
203
|
+
|
|
199
204
|
if not hash = @sections.find { |s| s.type == 'HASH' }
|
|
200
205
|
hash = Section.new
|
|
201
206
|
hash.name = '.hash'
|
|
@@ -236,11 +241,13 @@ class ELF
|
|
|
236
241
|
# encodes the symbol table
|
|
237
242
|
# should have a stable self.sections array (only append allowed after this step)
|
|
238
243
|
def encode_segments_symbols(strtab)
|
|
244
|
+
return if @symbols.length <= 1
|
|
245
|
+
|
|
239
246
|
if not dynsym = @sections.find { |s| s.type == 'DYNSYM' }
|
|
240
247
|
dynsym = Section.new
|
|
241
248
|
dynsym.name = '.dynsym'
|
|
242
249
|
dynsym.type = 'DYNSYM'
|
|
243
|
-
dynsym.entsize = Symbol.
|
|
250
|
+
dynsym.entsize = Symbol.sizeof(self)
|
|
244
251
|
dynsym.addralign = 4
|
|
245
252
|
dynsym.flags = ['ALLOC']
|
|
246
253
|
dynsym.info = @symbols[1..-1].find_all { |s| s.bind == 'LOCAL' }.length + 1
|
|
@@ -251,7 +258,7 @@ class ELF
|
|
|
251
258
|
@symbols.each { |s| dynsym.encoded << s.encode(self, strtab.encoded) } # needs all section indexes, as will be in the final section header
|
|
252
259
|
|
|
253
260
|
@tag['SYMTAB'] = label_at(dynsym.encoded, 0)
|
|
254
|
-
@tag['SYMENT'] = Symbol.
|
|
261
|
+
@tag['SYMENT'] = Symbol.sizeof(self)
|
|
255
262
|
|
|
256
263
|
encode_check_section_size dynsym
|
|
257
264
|
|
|
@@ -261,7 +268,7 @@ class ELF
|
|
|
261
268
|
# encodes the relocation tables
|
|
262
269
|
# needs a complete self.symbols array
|
|
263
270
|
def encode_segments_relocs
|
|
264
|
-
return if not @relocations
|
|
271
|
+
return if not @relocations or @relocations.empty?
|
|
265
272
|
|
|
266
273
|
arch_preencode_reloc_func = "arch_#{@header.machine.downcase}_preencode_reloc"
|
|
267
274
|
send arch_preencode_reloc_func if respond_to? arch_preencode_reloc_func
|
|
@@ -287,7 +294,7 @@ class ELF
|
|
|
287
294
|
@tag['JMPREL'] = label_at(relplt.encoded, 0)
|
|
288
295
|
@tag['PLTRELSZ'] = relplt.encoded.virtsize
|
|
289
296
|
@tag['PLTREL'] = relplt.type = stype
|
|
290
|
-
@tag[stype + 'ENT'] = relplt.entsize = relplt.addralign = (stype == 'REL' ? Relocation.
|
|
297
|
+
@tag[stype + 'ENT'] = relplt.entsize = relplt.addralign = (stype == 'REL' ? Relocation.sizeof(self) : RelocationAddend.sizeof(self))
|
|
291
298
|
encode_check_section_size relplt
|
|
292
299
|
end
|
|
293
300
|
|
|
@@ -305,13 +312,13 @@ class ELF
|
|
|
305
312
|
rel.name = '.rel.dyn'
|
|
306
313
|
rel.type = 'REL'
|
|
307
314
|
rel.flags = ['ALLOC']
|
|
308
|
-
rel.entsize = rel.addralign = Relocation.
|
|
315
|
+
rel.entsize = rel.addralign = Relocation.sizeof(self)
|
|
309
316
|
encode_add_section rel
|
|
310
317
|
end
|
|
311
318
|
rel.encoded = EncodedData.new
|
|
312
319
|
list.each { |r| rel.encoded << r.encode(self) }
|
|
313
320
|
@tag['REL'] = label_at(rel.encoded, 0)
|
|
314
|
-
@tag['RELENT'] = Relocation.
|
|
321
|
+
@tag['RELENT'] = Relocation.sizeof(self)
|
|
315
322
|
@tag['RELSZ'] = rel.encoded.virtsize
|
|
316
323
|
encode_check_section_size rel
|
|
317
324
|
end
|
|
@@ -323,13 +330,13 @@ class ELF
|
|
|
323
330
|
rela.name = '.rela.dyn'
|
|
324
331
|
rela.type = 'RELA'
|
|
325
332
|
rela.flags = ['ALLOC']
|
|
326
|
-
rela.entsize = rela.addralign = RelocationAddend.
|
|
333
|
+
rela.entsize = rela.addralign = RelocationAddend.sizeof(self)
|
|
327
334
|
encode_add_section rela
|
|
328
335
|
end
|
|
329
336
|
rela.encoded = EncodedData.new
|
|
330
337
|
list.each { |r| rela.encoded << r.encode(self) }
|
|
331
338
|
@tag['RELA'] = label_at(rela.encoded, 0)
|
|
332
|
-
@tag['RELAENT'] = RelocationAddend.
|
|
339
|
+
@tag['RELAENT'] = RelocationAddend.sizeof(self)
|
|
333
340
|
@tag['RELASZ'] = rela.encoded.virtsize
|
|
334
341
|
encode_check_section_size rela
|
|
335
342
|
end
|
|
@@ -337,6 +344,8 @@ class ELF
|
|
|
337
344
|
|
|
338
345
|
# creates the .plt/.got from the @relocations
|
|
339
346
|
def arch_386_preencode_reloc
|
|
347
|
+
return if @relocations.empty?
|
|
348
|
+
|
|
340
349
|
# if .got.plt does not exist, the dynamic loader segfaults
|
|
341
350
|
if not gotplt = @sections.find { |s| s.type == 'PROGBITS' and s.name == '.got.plt' }
|
|
342
351
|
gotplt = Section.new
|
|
@@ -358,7 +367,7 @@ class ELF
|
|
|
358
367
|
when 'PC32'
|
|
359
368
|
next if not r.symbol
|
|
360
369
|
|
|
361
|
-
|
|
370
|
+
if r.symbol.type != 'FUNC'
|
|
362
371
|
# external data xref: generate a GOT entry
|
|
363
372
|
# XXX reuse .got.plt ?
|
|
364
373
|
if not got ||= @sections.find { |s| s.type == 'PROGBITS' and s.name == '.got' }
|
|
@@ -385,7 +394,7 @@ class ELF
|
|
|
385
394
|
else
|
|
386
395
|
@relocations.delete r
|
|
387
396
|
end
|
|
388
|
-
|
|
397
|
+
|
|
389
398
|
# prevoffset is label_section_start + int_section_offset
|
|
390
399
|
target_s = @sections.find { |s| s.encoded and s.encoded.export[prevoffset.lexpr] == 0 }
|
|
391
400
|
rel = target_s.encoded.reloc[prevoffset.rexpr]
|
|
@@ -411,12 +420,12 @@ class ELF
|
|
|
411
420
|
#
|
|
412
421
|
# [.got.plt header]
|
|
413
422
|
# dd _DYNAMIC
|
|
414
|
-
# dd 0
|
|
423
|
+
# dd 0 # rewritten to GOTPLT? by ld-linux
|
|
415
424
|
# dd 0 # rewritten to dlresolve_inplace by ld-linux
|
|
416
425
|
#
|
|
417
426
|
# [.got.plt + func_got_offset]
|
|
418
427
|
# dd some_func_got_default # lazily rewritten to the real addr of some_func by jmp dlresolve_inplace
|
|
419
|
-
#
|
|
428
|
+
# # base_relocated ?
|
|
420
429
|
|
|
421
430
|
# in the PIC case, _dlresolve imposes us to use the ebx register (which may not be saved by the calling function..)
|
|
422
431
|
# also geteip trashes eax, which may interfere with regparm(3)
|
|
@@ -448,7 +457,7 @@ class ELF
|
|
|
448
457
|
plt.encoded << shellcode["jmp [#{base} + #{gotplt.encoded.length}]"]
|
|
449
458
|
plt.encoded.add_export r.symbol.name+'_plt_default', plt.encoded.length
|
|
450
459
|
reloffset = @relocations.find_all { |rr| rr.type == 'JMP_SLOT' }.length
|
|
451
|
-
reloffset *= Relocation.
|
|
460
|
+
reloffset *= Relocation.sizeof(self) if @bitsize == 32
|
|
452
461
|
plt.encoded << shellcode["push #{reloffset}\njmp metasm_plt_start"]
|
|
453
462
|
|
|
454
463
|
# transform the reloc PC32 => JMP_SLOT
|
|
@@ -531,7 +540,7 @@ class ELF
|
|
|
531
540
|
|
|
532
541
|
# fill these later, but create the base relocs now
|
|
533
542
|
arch_create_reloc_func = "arch_#{@header.machine.downcase}_create_reloc"
|
|
534
|
-
next if not respond_to?(arch_create_reloc_func)
|
|
543
|
+
next if not respond_to?(arch_create_reloc_func)
|
|
535
544
|
curaddr = label_at(@encoded, 0, 'elf_start')
|
|
536
545
|
fkbind = {}
|
|
537
546
|
@sections.each { |s|
|
|
@@ -557,6 +566,9 @@ class ELF
|
|
|
557
566
|
|
|
558
567
|
encode_check_section_size strtab
|
|
559
568
|
|
|
569
|
+
# rm unused tag (shrink .nointerp binaries by allowing to skip the section entirely)
|
|
570
|
+
@tag.delete('STRTAB') if strtab.encoded.length == 1
|
|
571
|
+
|
|
560
572
|
# XXX any order needed ?
|
|
561
573
|
@tag.keys.each { |k|
|
|
562
574
|
case k
|
|
@@ -581,7 +593,7 @@ class ELF
|
|
|
581
593
|
encode_tag[k, @tag[k]]
|
|
582
594
|
end
|
|
583
595
|
}
|
|
584
|
-
encode_tag['NULL', @tag['NULL'] || 0]
|
|
596
|
+
encode_tag['NULL', @tag['NULL'] || 0] unless @tag.empty?
|
|
585
597
|
|
|
586
598
|
encode_check_section_size dynamic
|
|
587
599
|
end
|
|
@@ -598,17 +610,13 @@ class ELF
|
|
|
598
610
|
@sections.each { |s|
|
|
599
611
|
next if not s.encoded
|
|
600
612
|
s.encoded.reloc.each_value { |r|
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
else
|
|
606
|
-
symname = t.reduce_rec
|
|
607
|
-
end
|
|
608
|
-
next if not dll = autoexports[symname]
|
|
613
|
+
et = r.target.externals
|
|
614
|
+
extern = et.find_all { |name| autoexports[name] }
|
|
615
|
+
next if extern.length != 1
|
|
616
|
+
symname = extern.first
|
|
609
617
|
if not @symbols.find { |sym| sym.name == symname }
|
|
610
618
|
@tag['NEEDED'] ||= []
|
|
611
|
-
@tag['NEEDED'] |= [
|
|
619
|
+
@tag['NEEDED'] |= [autoexports[symname]]
|
|
612
620
|
sym = Symbol.new
|
|
613
621
|
sym.shndx = 'UNDEF'
|
|
614
622
|
sym.type = 'FUNC'
|
|
@@ -737,6 +745,55 @@ class ELF
|
|
|
737
745
|
@relocations << r
|
|
738
746
|
end
|
|
739
747
|
|
|
748
|
+
def arch_mips_create_reloc(section, off, binding, rel=nil)
|
|
749
|
+
rel ||= section.encoded.reloc[off]
|
|
750
|
+
startaddr = label_at(@encoded, 0)
|
|
751
|
+
r = Relocation.new
|
|
752
|
+
r.offset = Expression[label_at(section.encoded, 0, 'sect_start'), :+, off]
|
|
753
|
+
if Expression[rel.target, :-, startaddr].bind(binding).reduce.kind_of?(::Integer)
|
|
754
|
+
# this location is relative to the base load address of the ELF
|
|
755
|
+
r.type = 'REL32'
|
|
756
|
+
else
|
|
757
|
+
et = rel.target.externals
|
|
758
|
+
extern = et.find_all { |name| not binding[name] }
|
|
759
|
+
if extern.length != 1
|
|
760
|
+
puts "ELF: mips_create_reloc: ignoring reloc #{rel.target} in #{section.name}: #{extern.inspect} unknown" if $VERBOSE
|
|
761
|
+
return
|
|
762
|
+
end
|
|
763
|
+
if not sym = @symbols.find { |s| s.name == extern.first }
|
|
764
|
+
puts "ELF: mips_create_reloc: ignoring reloc #{rel.target} in #{section.name}: undefined symbol #{extern.first}" if $VERBOSE
|
|
765
|
+
return
|
|
766
|
+
end
|
|
767
|
+
r.symbol = sym
|
|
768
|
+
if Expression[rel.target, :-, sym.name].bind(binding).reduce.kind_of?(::Integer)
|
|
769
|
+
rel.target = Expression[rel.target, :-, sym.name]
|
|
770
|
+
r.type = '32'
|
|
771
|
+
elsif Expression[rel.target, :&, 0xffff0000].reduce.kind_of?(::Integer)
|
|
772
|
+
lo = Expression[rel.target, :&, 0xffff].reduce
|
|
773
|
+
lo = lo.lexpr if lo.kind_of?(Expression) and lo.op == :& and lo.rexpr == 0xffff
|
|
774
|
+
if lo.kind_of?(Expression) and lo.op == :>> and lo.rexpr == 16
|
|
775
|
+
r.type = 'HI16'
|
|
776
|
+
rel.target = Expression[rel.target, :&, 0xffff0000]
|
|
777
|
+
# XXX offset ?
|
|
778
|
+
elsif lo.kind_of?(String) or (lo.kind_of(Expression) and lo.op == :+)
|
|
779
|
+
r.type = 'LO16'
|
|
780
|
+
rel.target = Expression[rel.target, :&, 0xffff0000]
|
|
781
|
+
# XXX offset ?
|
|
782
|
+
else
|
|
783
|
+
puts "ELF: mips_create_reloc: ignoring reloc #{lo}: cannot find matching 16 reloc type" if $VERBOSE
|
|
784
|
+
return
|
|
785
|
+
end
|
|
786
|
+
#elsif Expression[rel.target, :+, label_at(section.encoded, 0)].bind(section.encoded.binding).reduce.kind_of? ::Integer
|
|
787
|
+
# rel.target = Expression[[rel.target, :+, label_at(section.encoded, 0)], :+, off]
|
|
788
|
+
# r.type = 'PC32'
|
|
789
|
+
else
|
|
790
|
+
puts "ELF: mips_create_reloc: ignoring reloc #{sym.name} + #{rel.target}: cannot find matching standard reloc type" if $VERBOSE
|
|
791
|
+
return
|
|
792
|
+
end
|
|
793
|
+
end
|
|
794
|
+
@relocations << r
|
|
795
|
+
end
|
|
796
|
+
|
|
740
797
|
# resets the fields of the elf headers that should be recalculated, eg phdr offset
|
|
741
798
|
def invalidate_header
|
|
742
799
|
@header.shoff = @header.shnum = nil
|
|
@@ -817,9 +874,13 @@ class ELF
|
|
|
817
874
|
end
|
|
818
875
|
|
|
819
876
|
if @header.type == 'REL'
|
|
820
|
-
|
|
877
|
+
encode_rel
|
|
878
|
+
else
|
|
879
|
+
encode_elf
|
|
821
880
|
end
|
|
881
|
+
end
|
|
822
882
|
|
|
883
|
+
def encode_elf
|
|
823
884
|
@encoded = EncodedData.new
|
|
824
885
|
if @header.type != 'EXEC' or @segments.find { |i| i.type == 'INTERP' }
|
|
825
886
|
# create a .dynamic section unless we are an ET_EXEC with .nointerp
|
|
@@ -870,7 +931,7 @@ class ELF
|
|
|
870
931
|
end
|
|
871
932
|
|
|
872
933
|
# add dynamic segment
|
|
873
|
-
if ds = @sections.find { |sec| sec.type == 'DYNAMIC' }
|
|
934
|
+
if ds = @sections.find { |sec| sec.type == 'DYNAMIC' } and ds.encoded.length > 1
|
|
874
935
|
ds.set_default_values self
|
|
875
936
|
seg = Segment.new
|
|
876
937
|
seg.type = 'DYNAMIC'
|
|
@@ -979,6 +1040,36 @@ class ELF
|
|
|
979
1040
|
@encoded.data
|
|
980
1041
|
end
|
|
981
1042
|
|
|
1043
|
+
def encode_rel
|
|
1044
|
+
@encoded = EncodedData.new
|
|
1045
|
+
automagic_symbols
|
|
1046
|
+
create_relocations
|
|
1047
|
+
|
|
1048
|
+
@header.phoff = @header.phnum = @header.phentsize = 0
|
|
1049
|
+
@header.entry = 0
|
|
1050
|
+
@sections.each { |sec| sec.addr = 0 }
|
|
1051
|
+
st = @sections.inject(EncodedData.new) { |edata, sec| edata << sec.encode(self) }
|
|
1052
|
+
|
|
1053
|
+
binding = {}
|
|
1054
|
+
@encoded << @header.encode(self)
|
|
1055
|
+
@encoded.align 8
|
|
1056
|
+
|
|
1057
|
+
binding[@header.shoff] = @encoded.length
|
|
1058
|
+
@encoded << st
|
|
1059
|
+
@encoded.align 8
|
|
1060
|
+
|
|
1061
|
+
@sections.each { |sec|
|
|
1062
|
+
next if not sec.encoded
|
|
1063
|
+
binding[sec.offset] = @encoded.length
|
|
1064
|
+
sec.encoded.fixup sec.encoded.binding
|
|
1065
|
+
@encoded << sec.encoded
|
|
1066
|
+
@encoded.align 8
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
@encoded.fixup! binding
|
|
1070
|
+
@encoded.data
|
|
1071
|
+
end
|
|
1072
|
+
|
|
982
1073
|
def parse_init
|
|
983
1074
|
# allow the user to specify a section, falls back to .text if none specified
|
|
984
1075
|
if not defined? @cursource or not @cursource
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
require 'metasm/exe_format/main'
|
|
8
|
+
require 'metasm/encode'
|
|
9
|
+
require 'metasm/decode'
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
module Metasm
|
|
13
|
+
# GameBoy ROM file format
|
|
14
|
+
class GameBoyRom < ExeFormat
|
|
15
|
+
class Header < SerialStruct
|
|
16
|
+
# starts at 0x104 in the file
|
|
17
|
+
mem :logo, 0x30
|
|
18
|
+
str :title, 0x10
|
|
19
|
+
byte :sgb_flag
|
|
20
|
+
byte :cartridge_type
|
|
21
|
+
byte :rom_size # n => (n+1) * 32k bytes
|
|
22
|
+
byte :ram_size
|
|
23
|
+
byte :destination_code
|
|
24
|
+
byte :old_licensee_code
|
|
25
|
+
byte :mask_rom_version
|
|
26
|
+
byte :header_checksum
|
|
27
|
+
byte :checksum_hi
|
|
28
|
+
byte :checksum_lo
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def encode_byte(val) Expression[val].encode(:u8, @endianness) end
|
|
32
|
+
def decode_byte(edata = @encoded) edata.decode_imm(:u8, @endianness) end
|
|
33
|
+
def sizeof_byte ; 1 ; end
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
attr_accessor :header
|
|
37
|
+
|
|
38
|
+
def initialize(cpu=nil)
|
|
39
|
+
@endianness = (cpu ? cpu.endianness : :little)
|
|
40
|
+
super(cpu)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def decode_header
|
|
44
|
+
@encoded.ptr = 0x104
|
|
45
|
+
@header = Header.decode(self)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def decode
|
|
49
|
+
decode_header
|
|
50
|
+
@encoded.add_export('entrypoint', 0x100)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def cpu_from_headers
|
|
54
|
+
Z80.new('gb')
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def each_section
|
|
58
|
+
yield @encoded, 0
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def get_default_entrypoints
|
|
62
|
+
['entrypoint']
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
@@ -0,0 +1,424 @@
|
|
|
1
|
+
# This file is part of Metasm, the Ruby assembly manipulation suite
|
|
2
|
+
# Copyright (C) 2006-2009 Yoann GUILLOT
|
|
3
|
+
#
|
|
4
|
+
# Licence is LGPL, see LICENCE in the top-level directory
|
|
5
|
+
|
|
6
|
+
require 'metasm/exe_format/main'
|
|
7
|
+
require 'metasm/encode'
|
|
8
|
+
require 'metasm/decode'
|
|
9
|
+
|
|
10
|
+
module Metasm
|
|
11
|
+
|
|
12
|
+
class JavaClass < ExeFormat
|
|
13
|
+
MAGIC = "\xCA\xFE\xBA\xBE"
|
|
14
|
+
|
|
15
|
+
CONSTANT_TAG = {0x1 => 'Utf8', 0x3 => 'Integer',
|
|
16
|
+
0x4 => 'Float', 0x5 => 'Long',
|
|
17
|
+
0x6 => 'Double', 0x7 => 'Class',
|
|
18
|
+
0x8 => 'String', 0x9 => 'Fieldref',
|
|
19
|
+
0xa => 'Methodref', 0xb => 'InterfaceMethodref',
|
|
20
|
+
0xc => 'NameAndType' }
|
|
21
|
+
|
|
22
|
+
class SerialStruct < Metasm::SerialStruct
|
|
23
|
+
new_int_field :u1, :u2, :u4
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class Header < SerialStruct
|
|
27
|
+
mem :magic, 4, MAGIC
|
|
28
|
+
u2 :minor_version
|
|
29
|
+
u2 :major_version
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class ConstantPool < SerialStruct
|
|
33
|
+
u2 :constant_pool_count
|
|
34
|
+
attr_accessor :constant_pool
|
|
35
|
+
|
|
36
|
+
def decode(c)
|
|
37
|
+
super(c)
|
|
38
|
+
|
|
39
|
+
@constant_pool = [nil]
|
|
40
|
+
|
|
41
|
+
i = 1
|
|
42
|
+
while i < @constant_pool_count
|
|
43
|
+
entry = ConstantPoolInfo.decode(c)
|
|
44
|
+
entry.idx = i
|
|
45
|
+
@constant_pool << entry
|
|
46
|
+
i += 1
|
|
47
|
+
|
|
48
|
+
if entry.tag =~ /Long|Double/
|
|
49
|
+
# we must insert a phantom cell
|
|
50
|
+
# for long and double constants
|
|
51
|
+
@constant_pool << nil
|
|
52
|
+
i += 1
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def encode(c)
|
|
58
|
+
cp = super(c)
|
|
59
|
+
|
|
60
|
+
@constant_pool.each { |entry|
|
|
61
|
+
next if entry.nil?
|
|
62
|
+
cp << entry.encode(c)
|
|
63
|
+
}
|
|
64
|
+
cp
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def [](idx)
|
|
68
|
+
@constant_pool[idx]
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def []=(idx, val)
|
|
72
|
+
raise 'cannot be used to add a cp entry' if @constant_pool[idx].nil?
|
|
73
|
+
@constant_pool[idx] = val
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
class ConstantPoolInfo < SerialStruct
|
|
78
|
+
u1 :tag
|
|
79
|
+
fld_enum :tag, CONSTANT_TAG
|
|
80
|
+
attr_accessor :info, :idx
|
|
81
|
+
|
|
82
|
+
def decode(c)
|
|
83
|
+
super(c)
|
|
84
|
+
|
|
85
|
+
case @tag
|
|
86
|
+
when 'Utf8'
|
|
87
|
+
@info = ConstantUtf8.decode(c)
|
|
88
|
+
when /Integer|Float/
|
|
89
|
+
@info = ConstantIntFloat.decode(c)
|
|
90
|
+
when /Long|Double/
|
|
91
|
+
@info = ConstantLongDouble.decode(c)
|
|
92
|
+
when /Class|String/
|
|
93
|
+
@info = ConstantIndex.decode(c)
|
|
94
|
+
when /ref$/
|
|
95
|
+
@info = ConstantRef.decode(c)
|
|
96
|
+
when 'NameAndType'
|
|
97
|
+
@info = ConstantNameAndType.decode(c)
|
|
98
|
+
else
|
|
99
|
+
raise 'unkown constant tag'
|
|
100
|
+
return
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def encode(c)
|
|
105
|
+
super(c) << @info.encode(c)
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
class ConstantUtf8 < SerialStruct
|
|
110
|
+
u2 :length
|
|
111
|
+
attr_accessor :bytes
|
|
112
|
+
|
|
113
|
+
def decode(c)
|
|
114
|
+
super(c)
|
|
115
|
+
@bytes = c.encoded.read(@length)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def encode(c)
|
|
119
|
+
super(c) << @bytes
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
class ConstantIntFloat < SerialStruct
|
|
124
|
+
u4 :bytes
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
class ConstantLongDouble < SerialStruct
|
|
128
|
+
u4 :high_bytes
|
|
129
|
+
u4 :low_bytes
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
class ConstantIndex < SerialStruct
|
|
133
|
+
u2 :index
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
class ConstantRef < SerialStruct
|
|
137
|
+
u2 :class_index
|
|
138
|
+
u2 :name_and_type_index
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
class ConstantNameAndType < SerialStruct
|
|
142
|
+
u2 :name_index
|
|
143
|
+
u2 :descriptor_index
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
class ClassInfo < SerialStruct
|
|
147
|
+
u2 :access_flags
|
|
148
|
+
u2 :this_class
|
|
149
|
+
u2 :super_class
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
class Interfaces < SerialStruct
|
|
153
|
+
u2 :interfaces_count
|
|
154
|
+
attr_accessor :interfaces
|
|
155
|
+
|
|
156
|
+
def decode(c)
|
|
157
|
+
super(c)
|
|
158
|
+
|
|
159
|
+
@interfaces = []
|
|
160
|
+
@interfaces_count.times {
|
|
161
|
+
@interfaces << ConstantIndex.decode(c)
|
|
162
|
+
}
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def encode(c)
|
|
166
|
+
ret = super(c)
|
|
167
|
+
|
|
168
|
+
@interfaces.each { |e|
|
|
169
|
+
ret << e.encode(c)
|
|
170
|
+
}
|
|
171
|
+
ret
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def [](idx)
|
|
175
|
+
@interfaces[idx]
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
class Fields < SerialStruct
|
|
180
|
+
u2 :fields_count
|
|
181
|
+
attr_accessor :fields
|
|
182
|
+
|
|
183
|
+
def decode(c)
|
|
184
|
+
super(c)
|
|
185
|
+
@fields = []
|
|
186
|
+
@fields_count.times {
|
|
187
|
+
@fields << FieldMethodInfo.decode(c)
|
|
188
|
+
}
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def encode(c)
|
|
192
|
+
ret = super(c)
|
|
193
|
+
|
|
194
|
+
@fields.each { |e|
|
|
195
|
+
ret << e.encode(c)
|
|
196
|
+
}
|
|
197
|
+
ret
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
def [](idx)
|
|
201
|
+
@fields[idx]
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
class Methods < SerialStruct
|
|
206
|
+
u2 :methods_count
|
|
207
|
+
attr_accessor :methods
|
|
208
|
+
|
|
209
|
+
def decode(c)
|
|
210
|
+
super(c)
|
|
211
|
+
@methods = []
|
|
212
|
+
@methods_count.times {
|
|
213
|
+
@methods << FieldMethodInfo.decode(c)
|
|
214
|
+
}
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def encode(c)
|
|
218
|
+
ret = super(c)
|
|
219
|
+
|
|
220
|
+
@methods.each { |e|
|
|
221
|
+
ret << e.encode(c)
|
|
222
|
+
}
|
|
223
|
+
ret
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def [](idx)
|
|
227
|
+
@methods[idx]
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
class FieldMethodInfo < SerialStruct
|
|
232
|
+
u2 :access_flags
|
|
233
|
+
u2 :name_index
|
|
234
|
+
u2 :descriptor_index
|
|
235
|
+
attr_accessor :attributes
|
|
236
|
+
|
|
237
|
+
def decode(c)
|
|
238
|
+
super(c)
|
|
239
|
+
@attributes = Attributes.decode(c)
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def encode(c)
|
|
243
|
+
super(c) << @attributes.encode(c)
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
class Attributes < SerialStruct
|
|
248
|
+
u2 :attributes_count
|
|
249
|
+
attr_accessor :attributes
|
|
250
|
+
|
|
251
|
+
def decode(c)
|
|
252
|
+
super(c)
|
|
253
|
+
|
|
254
|
+
@attributes = []
|
|
255
|
+
@attributes_count.times { |i|
|
|
256
|
+
@attributes << AttributeInfo.decode(c)
|
|
257
|
+
}
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def encode(c)
|
|
261
|
+
ret = super(c)
|
|
262
|
+
|
|
263
|
+
@attributes.each { |e|
|
|
264
|
+
ret << e.encode(c)
|
|
265
|
+
}
|
|
266
|
+
ret
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
def [](idx)
|
|
270
|
+
@attributes[idx]
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
class AttributeInfo < SerialStruct
|
|
275
|
+
u2 :attribute_name_index
|
|
276
|
+
u4 :attribute_length
|
|
277
|
+
attr_accessor :data
|
|
278
|
+
|
|
279
|
+
def decode(c)
|
|
280
|
+
super(c)
|
|
281
|
+
@data = c.encoded.read(@attribute_length)
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def encode(c)
|
|
285
|
+
super(c) << @data
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
def encode_u1(val) Expression[val].encode(:u8, @endianness) end
|
|
290
|
+
def encode_u2(val) Expression[val].encode(:u16, @endianness) end
|
|
291
|
+
def encode_u4(val) Expression[val].encode(:u32, @endianness) end
|
|
292
|
+
def decode_u1(edata = @encoded) edata.decode_imm(:u8, @endianness) end
|
|
293
|
+
def decode_u2(edata = @encoded) edata.decode_imm(:u16, @endianness) end
|
|
294
|
+
def decode_u4(edata = @encoded) edata.decode_imm(:u32, @endianness) end
|
|
295
|
+
def sizeof_u1 ; 1 ; end
|
|
296
|
+
def sizeof_u2 ; 2 ; end
|
|
297
|
+
def sizeof_u4 ; 4 ; end
|
|
298
|
+
|
|
299
|
+
attr_accessor :header, :constant_pool, :class_info, :interfaces, :fields, :methods, :attributes
|
|
300
|
+
|
|
301
|
+
def initialize(endianness=:big)
|
|
302
|
+
@endianness = endianness
|
|
303
|
+
@encoded = EncodedData.new
|
|
304
|
+
super()
|
|
305
|
+
end
|
|
306
|
+
|
|
307
|
+
def decode
|
|
308
|
+
@header = Header.decode(self)
|
|
309
|
+
@constant_pool = ConstantPool.decode(self)
|
|
310
|
+
@class_info = ClassInfo.decode(self)
|
|
311
|
+
@interfaces = Interfaces.decode(self)
|
|
312
|
+
@fields = Fields.decode(self)
|
|
313
|
+
@methods = Methods.decode(self)
|
|
314
|
+
@attributes = Attributes.decode(self)
|
|
315
|
+
end
|
|
316
|
+
|
|
317
|
+
def encode
|
|
318
|
+
@encoded = EncodedData.new
|
|
319
|
+
@encoded << @header.encode(self)
|
|
320
|
+
@encoded << @constant_pool.encode(self)
|
|
321
|
+
@encoded << @class_info.encode(self)
|
|
322
|
+
@encoded << @interfaces.encode(self)
|
|
323
|
+
@encoded << @fields.encode(self)
|
|
324
|
+
@encoded << @methods.encode(self)
|
|
325
|
+
@encoded << @attributes.encode(self)
|
|
326
|
+
@encoded.data
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
def cpu_from_headers
|
|
330
|
+
raise 'JVM'
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
def each_section
|
|
334
|
+
raise 'n/a'
|
|
335
|
+
end
|
|
336
|
+
|
|
337
|
+
def get_default_entrypoints
|
|
338
|
+
[]
|
|
339
|
+
end
|
|
340
|
+
|
|
341
|
+
def string_at(idx)
|
|
342
|
+
loop do
|
|
343
|
+
tmp = @constant_pool[idx].info
|
|
344
|
+
return tmp.bytes if tmp.kind_of? ConstantUtf8
|
|
345
|
+
idx = tmp.index
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
def decode_methodref(mref)
|
|
350
|
+
class_idx = mref.info.class_index
|
|
351
|
+
nt_idx = mref.info.name_and_type_index
|
|
352
|
+
name_idx = @constant_pool[nt_idx].info.name_index
|
|
353
|
+
desc_idx = @constant_pool[nt_idx].info.descriptor_index
|
|
354
|
+
|
|
355
|
+
string_at(class_idx) + '/' + string_at(name_idx) + string_at(desc_idx)
|
|
356
|
+
end
|
|
357
|
+
|
|
358
|
+
def cp_add(cpi, tag)
|
|
359
|
+
cpe = ConstantPoolInfo.new
|
|
360
|
+
cpe.tag = tag
|
|
361
|
+
cpe.info = cpi
|
|
362
|
+
cpe.idx = @constant_pool.constant_pool_count
|
|
363
|
+
|
|
364
|
+
@constant_pool.constant_pool << cpe
|
|
365
|
+
@constant_pool.constant_pool_count += 1
|
|
366
|
+
@constant_pool.constant_pool_count += 1 if tag =~ /Long|Double/
|
|
367
|
+
|
|
368
|
+
cpe.idx
|
|
369
|
+
end
|
|
370
|
+
|
|
371
|
+
def cp_find(tag)
|
|
372
|
+
constant_pool.constant_pool.each { |e|
|
|
373
|
+
next if !e or e.tag != tag
|
|
374
|
+
if yield(e.info)
|
|
375
|
+
return e.idx
|
|
376
|
+
end
|
|
377
|
+
}
|
|
378
|
+
nil
|
|
379
|
+
end
|
|
380
|
+
|
|
381
|
+
|
|
382
|
+
def cp_auto_utf8(string)
|
|
383
|
+
if idx = cp_find('Utf8') { |i| i.bytes == string }
|
|
384
|
+
return idx
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
cpi = ConstantUtf8.new
|
|
388
|
+
cpi.bytes = string
|
|
389
|
+
cpi.length = string.length
|
|
390
|
+
cp_add(cpi, 'Utf8')
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
def cp_auto_class(classname)
|
|
394
|
+
if idx = cp_find('Class') { |i| string_at(i.index) == classname }
|
|
395
|
+
return idx
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
cpi = ConstantIndex.new
|
|
399
|
+
cpi.index = cp_auto_utf8(classname)
|
|
400
|
+
cp_add(cpi, 'Class')
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
def cp_add_methodref(classname, name, descriptor)
|
|
404
|
+
nat = ConstantNameAndType.new
|
|
405
|
+
nat.name_index = cp_auto_utf8(name)
|
|
406
|
+
nat.descriptor_index = cp_auto_utf8(descriptor)
|
|
407
|
+
natidx = cp_add(nat, 'NameAndType')
|
|
408
|
+
|
|
409
|
+
cpi = ConstantRef.new
|
|
410
|
+
cpi.class_index = cp_auto_class(classname)
|
|
411
|
+
cpi.name_and_type_index = natidx
|
|
412
|
+
|
|
413
|
+
cp_add(cpi, 'Methodref')
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def attribute_create(name, data)
|
|
417
|
+
a = AttributeInfo.new
|
|
418
|
+
a.attribute_name_index = cp_auto_utf8(name)
|
|
419
|
+
a.attribute_length = data.size
|
|
420
|
+
a.data = data
|
|
421
|
+
a
|
|
422
|
+
end
|
|
423
|
+
end
|
|
424
|
+
end
|