metasm 1.0.0 → 1.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +3 -0
- data/.gitignore +3 -0
- data/.hgtags +3 -0
- data/Gemfile +3 -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 +3 -1
- 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 +23 -0
- data/{lib/metasm.rb → metasm.rb} +15 -3
- data/{lib/metasm → metasm}/compile_c.rb +15 -9
- data/metasm/cpu/arc.rb +8 -0
- data/metasm/cpu/arc/decode.rb +404 -0
- data/metasm/cpu/arc/main.rb +191 -0
- data/metasm/cpu/arc/opcodes.rb +588 -0
- data/metasm/cpu/arm.rb +14 -0
- data/{lib/metasm → metasm/cpu}/arm/debug.rb +2 -2
- data/{lib/metasm → metasm/cpu}/arm/decode.rb +15 -18
- data/{lib/metasm → metasm/cpu}/arm/encode.rb +23 -8
- data/{lib/metasm → metasm/cpu}/arm/main.rb +3 -6
- 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 +285 -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/mips/compile_c.rb → metasm/cpu/bpf.rb} +4 -2
- data/metasm/cpu/bpf/decode.rb +110 -0
- data/metasm/cpu/bpf/main.rb +60 -0
- data/metasm/cpu/bpf/opcodes.rb +81 -0
- data/metasm/cpu/bpf/render.rb +30 -0
- data/{lib/metasm/ppc.rb → metasm/cpu/cy16.rb} +2 -4
- data/metasm/cpu/cy16/decode.rb +247 -0
- data/metasm/cpu/cy16/main.rb +63 -0
- data/metasm/cpu/cy16/opcodes.rb +78 -0
- data/metasm/cpu/cy16/render.rb +30 -0
- data/metasm/cpu/dalvik.rb +11 -0
- data/{lib/metasm → metasm/cpu}/dalvik/decode.rb +34 -34
- data/{lib/metasm → metasm/cpu}/dalvik/main.rb +71 -4
- data/{lib/metasm → metasm/cpu}/dalvik/opcodes.rb +21 -12
- data/{lib/metasm/mips.rb → metasm/cpu/ebpf.rb} +3 -4
- data/metasm/cpu/ebpf/debug.rb +61 -0
- data/metasm/cpu/ebpf/decode.rb +142 -0
- data/metasm/cpu/ebpf/main.rb +58 -0
- data/metasm/cpu/ebpf/opcodes.rb +97 -0
- data/metasm/cpu/ebpf/render.rb +36 -0
- data/metasm/cpu/ia32.rb +17 -0
- data/{lib/metasm → metasm/cpu}/ia32/compile_c.rb +23 -9
- data/{lib/metasm → metasm/cpu}/ia32/debug.rb +44 -6
- data/{lib/metasm → metasm/cpu}/ia32/decode.rb +342 -128
- data/{lib/metasm → metasm/cpu}/ia32/decompile.rb +75 -53
- data/{lib/metasm → metasm/cpu}/ia32/encode.rb +19 -13
- data/{lib/metasm → metasm/cpu}/ia32/main.rb +66 -8
- data/metasm/cpu/ia32/opcodes.rb +1424 -0
- data/{lib/metasm → metasm/cpu}/ia32/parse.rb +55 -17
- data/{lib/metasm → metasm/cpu}/ia32/render.rb +32 -5
- data/metasm/cpu/mcs51.rb +8 -0
- data/metasm/cpu/mcs51/decode.rb +99 -0
- data/metasm/cpu/mcs51/main.rb +87 -0
- data/metasm/cpu/mcs51/opcodes.rb +120 -0
- data/metasm/cpu/mips.rb +14 -0
- data/metasm/cpu/mips/debug.rb +42 -0
- data/{lib/metasm → metasm/cpu}/mips/decode.rb +59 -38
- data/{lib/metasm → metasm/cpu}/mips/encode.rb +4 -3
- data/{lib/metasm → metasm/cpu}/mips/main.rb +13 -6
- data/{lib/metasm → metasm/cpu}/mips/opcodes.rb +87 -18
- 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 +243 -0
- data/metasm/cpu/msp430/main.rb +62 -0
- data/metasm/cpu/msp430/opcodes.rb +101 -0
- data/metasm/cpu/openrisc.rb +11 -0
- data/metasm/cpu/openrisc/debug.rb +106 -0
- data/metasm/cpu/openrisc/decode.rb +182 -0
- data/metasm/cpu/openrisc/decompile.rb +350 -0
- data/metasm/cpu/openrisc/main.rb +70 -0
- data/metasm/cpu/openrisc/opcodes.rb +109 -0
- data/metasm/cpu/openrisc/render.rb +37 -0
- data/{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/metasm/cpu/ppc.rb +11 -0
- data/{lib/metasm → metasm/cpu}/ppc/decode.rb +18 -37
- 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 +23 -18
- data/{lib/metasm → metasm/cpu}/ppc/opcodes.rb +11 -6
- data/metasm/cpu/ppc/parse.rb +55 -0
- data/metasm/cpu/python.rb +8 -0
- data/metasm/cpu/python/decode.rb +116 -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 +50 -23
- data/{lib/metasm → metasm/cpu}/sh4/main.rb +38 -27
- data/{lib/metasm → metasm/cpu}/sh4/opcodes.rb +7 -8
- data/metasm/cpu/st20.rb +9 -0
- data/metasm/cpu/st20/decode.rb +173 -0
- data/metasm/cpu/st20/decompile.rb +283 -0
- data/metasm/cpu/st20/main.rb +37 -0
- data/metasm/cpu/st20/opcodes.rb +140 -0
- data/{lib/metasm/arm.rb → metasm/cpu/webasm.rb} +4 -5
- data/metasm/cpu/webasm/debug.rb +31 -0
- data/metasm/cpu/webasm/decode.rb +321 -0
- data/metasm/cpu/webasm/decompile.rb +386 -0
- data/metasm/cpu/webasm/encode.rb +104 -0
- data/metasm/cpu/webasm/main.rb +81 -0
- data/metasm/cpu/webasm/opcodes.rb +214 -0
- data/metasm/cpu/x86_64.rb +15 -0
- data/{lib/metasm → metasm/cpu}/x86_64/compile_c.rb +40 -25
- data/{lib/metasm → metasm/cpu}/x86_64/debug.rb +4 -4
- data/{lib/metasm → metasm/cpu}/x86_64/decode.rb +58 -15
- data/{lib/metasm → metasm/cpu}/x86_64/encode.rb +59 -28
- data/{lib/metasm → metasm/cpu}/x86_64/main.rb +18 -6
- data/metasm/cpu/x86_64/opcodes.rb +138 -0
- data/{lib/metasm → metasm/cpu}/x86_64/parse.rb +12 -4
- data/metasm/cpu/x86_64/render.rb +35 -0
- data/metasm/cpu/z80.rb +9 -0
- data/metasm/cpu/z80/decode.rb +286 -0
- data/metasm/cpu/z80/main.rb +67 -0
- data/metasm/cpu/z80/opcodes.rb +224 -0
- data/metasm/cpu/z80/render.rb +48 -0
- data/{lib/metasm/os/main.rb → metasm/debug.rb} +201 -407
- data/{lib/metasm → metasm}/decode.rb +104 -24
- data/{lib/metasm → metasm}/decompile.rb +804 -478
- data/{lib/metasm → metasm}/disassemble.rb +385 -170
- data/{lib/metasm → metasm}/disassemble_api.rb +684 -105
- data/{lib/metasm → metasm}/dynldr.rb +231 -138
- data/{lib/metasm → metasm}/encode.rb +20 -5
- data/{lib/metasm → metasm}/exe_format/a_out.rb +9 -6
- data/{lib/metasm → metasm}/exe_format/autoexe.rb +3 -0
- data/{lib/metasm → metasm}/exe_format/bflt.rb +57 -27
- data/{lib/metasm → metasm}/exe_format/coff.rb +35 -7
- data/{lib/metasm → metasm}/exe_format/coff_decode.rb +70 -23
- data/{lib/metasm → metasm}/exe_format/coff_encode.rb +24 -22
- data/{lib/metasm → metasm}/exe_format/dex.rb +26 -8
- data/{lib/metasm → metasm}/exe_format/dol.rb +1 -0
- data/{lib/metasm → metasm}/exe_format/elf.rb +108 -58
- data/{lib/metasm → metasm}/exe_format/elf_decode.rb +202 -36
- data/{lib/metasm → metasm}/exe_format/elf_encode.rb +126 -32
- data/metasm/exe_format/gb.rb +65 -0
- data/metasm/exe_format/javaclass.rb +424 -0
- data/{lib/metasm → metasm}/exe_format/macho.rb +218 -16
- data/{lib/metasm → metasm}/exe_format/main.rb +28 -3
- data/{lib/metasm → metasm}/exe_format/mz.rb +2 -0
- data/{lib/metasm → metasm}/exe_format/nds.rb +7 -4
- data/{lib/metasm → metasm}/exe_format/pe.rb +96 -11
- 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/metasm/exe_format/wasm.rb +402 -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 +177 -114
- data/{lib/metasm → metasm}/gui/dasm_funcgraph.rb +0 -0
- data/metasm/gui/dasm_graph.rb +1754 -0
- data/{lib/metasm → metasm}/gui/dasm_hex.rb +16 -12
- data/{lib/metasm → metasm}/gui/dasm_listing.rb +43 -28
- data/{lib/metasm → metasm}/gui/dasm_main.rb +360 -77
- data/{lib/metasm → metasm}/gui/dasm_opcodes.rb +5 -19
- data/{lib/metasm → metasm}/gui/debug.rb +109 -34
- data/{lib/metasm → metasm}/gui/gtk.rb +174 -44
- data/{lib/metasm → metasm}/gui/qt.rb +14 -4
- data/{lib/metasm → metasm}/gui/win32.rb +180 -43
- data/{lib/metasm → metasm}/gui/x11.rb +59 -59
- data/{lib/metasm → metasm}/main.rb +421 -286
- data/metasm/os/emulator.rb +175 -0
- 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 +335 -0
- data/{lib/metasm → metasm}/os/windows.rb +151 -58
- data/{lib/metasm → metasm}/os/windows_exports.rb +141 -0
- data/{lib/metasm → metasm}/parse.rb +49 -36
- data/{lib/metasm → metasm}/parse_c.rb +405 -246
- data/{lib/metasm → metasm}/preprocessor.rb +71 -41
- data/{lib/metasm → metasm}/render.rb +14 -38
- data/misc/hexdump.rb +4 -3
- data/misc/lint.rb +58 -0
- data/misc/objdiff.rb +4 -1
- data/misc/objscan.rb +1 -1
- data/misc/openrisc-parser.rb +79 -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 +29 -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 +48 -7
- data/samples/disassemble.rb +31 -6
- data/samples/dump_upx.rb +24 -12
- data/samples/dynamic_ruby.rb +35 -27
- data/samples/elfencode.rb +15 -0
- data/samples/emubios.rb +251 -0
- data/samples/emudbg.rb +127 -0
- data/samples/exeencode.rb +6 -5
- data/samples/factorize-headers-peimports.rb +1 -1
- data/samples/lindebug.rb +186 -391
- data/samples/metasm-shell.rb +68 -57
- 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 +57 -0
- data/tests/graph_layout.rb +285 -0
- data/tests/ia32.rb +80 -26
- data/tests/mcs51.rb +27 -0
- data/tests/mips.rb +10 -3
- data/tests/preprocessor.rb +18 -0
- data/tests/x86_64.rb +66 -18
- metadata +465 -219
- metadata.gz.sig +2 -0
- 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 -872
- 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
@@ -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
|
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
|
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
|
-
|
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
|
-
|
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
|
-
|
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.
|
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.
|
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.
|
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
|
-
|
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
|
@@ -332,8 +365,7 @@ class ELF
|
|
332
365
|
# marks a symbol as @encoded.export (from s.value, using segments or sections)
|
333
366
|
def decode_symbol_export(s)
|
334
367
|
if s.name and s.shndx != 'UNDEF' and %w[NOTYPE OBJECT FUNC].include?(s.type)
|
335
|
-
if @header.type == 'REL'
|
336
|
-
sec = @sections[s.shndx]
|
368
|
+
if @header.type == 'REL' and s.shndx.kind_of?(::Integer) and sec = @sections[s.shndx]
|
337
369
|
o = sec.offset + s.value
|
338
370
|
elsif not o = addr_to_off(s.value)
|
339
371
|
# allow to point to end of segment
|
@@ -359,7 +391,7 @@ class ELF
|
|
359
391
|
def decode_segments_symbols
|
360
392
|
return unless @tag['STRTAB'] and @tag['STRSZ'] and @tag['SYMTAB'] and (@tag['HASH'] or @tag['GNU_HASH'])
|
361
393
|
|
362
|
-
raise "E: ELF: unsupported symbol entry size: #{@tag['SYMENT']}" if @tag['SYMENT'] != Symbol.
|
394
|
+
raise "E: ELF: unsupported symbol entry size: #{@tag['SYMENT']}" if @tag['SYMENT'] != Symbol.sizeof(self)
|
363
395
|
|
364
396
|
# find number of symbols
|
365
397
|
if @tag['HASH']
|
@@ -394,14 +426,16 @@ class ELF
|
|
394
426
|
@encoded.ptr = sec.offset
|
395
427
|
syms = []
|
396
428
|
raise 'Invalid symbol table' if sec.size > @encoded.length
|
397
|
-
(sec.size / Symbol.
|
429
|
+
(sec.size / Symbol.sizeof(self)).times { syms << Symbol.decode(self, strtab) }
|
398
430
|
alreadysegs = true if @header.type == 'DYN' or @header.type == 'EXEC'
|
431
|
+
alreadysyms = @symbols.inject({}) { |h, s| h.update s.name => true } if alreadysegs
|
399
432
|
syms.each { |s|
|
400
433
|
if alreadysegs
|
401
434
|
# if we already decoded the symbols from the DYNAMIC segment,
|
402
435
|
# ignore dups and imports from this section
|
403
436
|
next if s.shndx == 'UNDEF'
|
404
|
-
next if
|
437
|
+
next if alreadysyms[s.name]
|
438
|
+
alreadysyms[s.name] = true
|
405
439
|
end
|
406
440
|
@symbols << s
|
407
441
|
decode_symbol_export(s)
|
@@ -445,7 +479,7 @@ class ELF
|
|
445
479
|
def decode_segments_relocs
|
446
480
|
@relocations.clear
|
447
481
|
if @encoded.ptr = @tag['REL']
|
448
|
-
raise "E: ELF: unsupported rel entry size #{@tag['RELENT']}" if @tag['RELENT'] != Relocation.
|
482
|
+
raise "E: ELF: unsupported rel entry size #{@tag['RELENT']}" if @tag['RELENT'] != Relocation.sizeof(self)
|
449
483
|
p_end = @encoded.ptr + @tag['RELSZ']
|
450
484
|
while @encoded.ptr < p_end
|
451
485
|
@relocations << Relocation.decode(self)
|
@@ -453,7 +487,7 @@ class ELF
|
|
453
487
|
end
|
454
488
|
|
455
489
|
if @encoded.ptr = @tag['RELA']
|
456
|
-
raise "E: ELF: unsupported rela entry size #{@tag['RELAENT'].inspect}" if @tag['RELAENT'] != RelocationAddend.
|
490
|
+
raise "E: ELF: unsupported rela entry size #{@tag['RELAENT'].inspect}" if @tag['RELAENT'] != RelocationAddend.sizeof(self)
|
457
491
|
p_end = @encoded.ptr + @tag['RELASZ']
|
458
492
|
while @encoded.ptr < p_end
|
459
493
|
@relocations << RelocationAddend.decode(self)
|
@@ -509,10 +543,28 @@ class ELF
|
|
509
543
|
end
|
510
544
|
end
|
511
545
|
|
546
|
+
# returns the target of a relocation using reloc.symbol
|
547
|
+
# may create new labels if the relocation targets a section
|
548
|
+
def reloc_target(reloc)
|
549
|
+
target = 0
|
550
|
+
if reloc.symbol.kind_of?(Symbol)
|
551
|
+
if reloc.symbol.type == 'SECTION'
|
552
|
+
s = @sections[reloc.symbol.shndx]
|
553
|
+
if not target = @encoded.inv_export[s.offset]
|
554
|
+
target = new_label(s.name)
|
555
|
+
@encoded.add_export(target, s.offset)
|
556
|
+
end
|
557
|
+
elsif reloc.symbol.name
|
558
|
+
target = reloc.symbol.name
|
559
|
+
end
|
560
|
+
end
|
561
|
+
target
|
562
|
+
end
|
563
|
+
|
512
564
|
# returns the Metasm::Relocation that should be applied for reloc
|
513
565
|
# self.encoded.ptr must point to the location that will be relocated (for implicit addends)
|
514
566
|
def arch_decode_segments_reloc_386(reloc)
|
515
|
-
if reloc.symbol and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
|
567
|
+
if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
|
516
568
|
s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
|
517
569
|
@encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
|
518
570
|
end
|
@@ -541,15 +593,14 @@ class ELF
|
|
541
593
|
when 'GLOB_DAT', 'JMP_SLOT', '32', 'PC32', 'TLS_TPOFF', 'TLS_TPOFF32'
|
542
594
|
# XXX use versionned version
|
543
595
|
# lazy jmp_slot ?
|
544
|
-
target =
|
545
|
-
target = reloc.symbol.name if reloc.symbol.kind_of?(Symbol) and reloc.symbol.name
|
596
|
+
target = reloc_target(reloc)
|
546
597
|
target = Expression[target, :-, reloc.offset] if reloc.type == 'PC32'
|
547
598
|
target = Expression[target, :+, addend] if addend and addend != 0
|
548
599
|
target = Expression[target, :+, 'tlsoffset'] if reloc.type == 'TLS_TPOFF'
|
549
600
|
target = Expression[:-, [target, :+, 'tlsoffset']] if reloc.type == 'TLS_TPOFF32'
|
550
601
|
when 'COPY'
|
551
602
|
# mark the address pointed as a copy of the relocation target
|
552
|
-
if not reloc.symbol or not name = reloc.symbol.name
|
603
|
+
if not reloc.symbol.kind_of?(Symbol) or not name = reloc.symbol.name
|
553
604
|
puts "W: Elf: symbol to COPY has no name: #{reloc.inspect}" if $VERBOSE
|
554
605
|
name = ''
|
555
606
|
end
|
@@ -567,24 +618,40 @@ class ELF
|
|
567
618
|
# returns the Metasm::Relocation that should be applied for reloc
|
568
619
|
# self.encoded.ptr must point to the location that will be relocated (for implicit addends)
|
569
620
|
def arch_decode_segments_reloc_mips(reloc)
|
570
|
-
if reloc.symbol and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
|
621
|
+
if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
|
571
622
|
s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
|
572
623
|
@encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
|
573
624
|
end
|
574
625
|
|
626
|
+
original_word = decode_word
|
627
|
+
|
575
628
|
# decode addend if needed
|
576
629
|
case reloc.type
|
577
630
|
when 'NONE' # no addend
|
578
|
-
else addend = reloc.addend ||
|
631
|
+
else addend = reloc.addend || Expression.make_signed(original_word, 32)
|
579
632
|
end
|
580
633
|
|
581
634
|
case reloc.type
|
582
635
|
when 'NONE'
|
583
636
|
when '32', 'REL32'
|
584
|
-
target =
|
585
|
-
target = reloc.symbol.name if reloc.symbol.kind_of?(Symbol) and reloc.symbol.name
|
637
|
+
target = reloc_target(reloc)
|
586
638
|
target = Expression[target, :-, reloc.offset] if reloc.type == 'REL32'
|
587
639
|
target = Expression[target, :+, addend] if addend and addend != 0
|
640
|
+
when '26'
|
641
|
+
target = reloc_target(reloc)
|
642
|
+
addend &= 0x3ff_ffff
|
643
|
+
target = Expression[target, :+, [addend, :<<, 2]] if addend and addend != 0
|
644
|
+
target = Expression[[original_word, :&, 0xfc0_0000], :|, [[target, :&, 0x3ff_ffff], :>>, 2]]
|
645
|
+
when 'HI16'
|
646
|
+
target = reloc_target(reloc)
|
647
|
+
addend &= 0xffff
|
648
|
+
target = Expression[target, :+, [addend, :<<, 16]] if addend and addend != 0
|
649
|
+
target = Expression[[original_word, :&, 0xffff_0000], :|, [[target, :>>, 16], :&, 0xffff]]
|
650
|
+
when 'LO16'
|
651
|
+
target = reloc_target(reloc)
|
652
|
+
addend &= 0xffff
|
653
|
+
target = Expression[target, :+, addend] if addend and addend != 0
|
654
|
+
target = Expression[[original_word, :&, 0xffff_0000], :|, [target, :&, 0xffff]]
|
588
655
|
else
|
589
656
|
puts "W: Elf: unhandled MIPS reloc #{reloc.inspect}" if $VERBOSE
|
590
657
|
target = nil
|
@@ -596,7 +663,7 @@ class ELF
|
|
596
663
|
# returns the Metasm::Relocation that should be applied for reloc
|
597
664
|
# self.encoded.ptr must point to the location that will be relocated (for implicit addends)
|
598
665
|
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
|
666
|
+
if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
|
600
667
|
s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
|
601
668
|
@encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
|
602
669
|
end
|
@@ -627,14 +694,13 @@ class ELF
|
|
627
694
|
when 'GLOB_DAT', 'JMP_SLOT', '64', 'PC64', '32', 'PC32'
|
628
695
|
# XXX use versionned version
|
629
696
|
# lazy jmp_slot ?
|
630
|
-
target =
|
631
|
-
target = reloc.symbol.name if reloc.symbol.kind_of?(Symbol) and reloc.symbol.name
|
697
|
+
target = reloc_target(reloc)
|
632
698
|
target = Expression[target, :-, reloc.offset] if reloc.type == 'PC64' or reloc.type == 'PC32'
|
633
699
|
target = Expression[target, :+, addend] if addend and addend != 0
|
634
700
|
sz = :u32 if reloc.type == '32' or reloc.type == 'PC32'
|
635
701
|
when 'COPY'
|
636
702
|
# mark the address pointed as a copy of the relocation target
|
637
|
-
if not reloc.symbol or not name = reloc.symbol.name
|
703
|
+
if not reloc.symbol.kind_of?(Symbol) or not name = reloc.symbol.name
|
638
704
|
puts "W: Elf: symbol to COPY has no name: #{reloc.inspect}" if $VERBOSE
|
639
705
|
name = ''
|
640
706
|
end
|
@@ -649,6 +715,79 @@ class ELF
|
|
649
715
|
Metasm::Relocation.new(Expression[target], sz, @endianness) if target
|
650
716
|
end
|
651
717
|
|
718
|
+
def arch_decode_segments_reloc_sh(reloc)
|
719
|
+
if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
|
720
|
+
s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
|
721
|
+
@encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
|
722
|
+
end
|
723
|
+
|
724
|
+
original_word = decode_word
|
725
|
+
|
726
|
+
# decode addend if needed
|
727
|
+
case reloc.type
|
728
|
+
when 'NONE' # no addend
|
729
|
+
else addend = reloc.addend || Expression.make_signed(original_word, 32)
|
730
|
+
end
|
731
|
+
|
732
|
+
case reloc.type
|
733
|
+
when 'NONE'
|
734
|
+
when 'GLOB_DAT', 'JMP_SLOT'
|
735
|
+
target = reloc_target(reloc)
|
736
|
+
target = Expression[target, :+, addend] if addend and addend != 0
|
737
|
+
else
|
738
|
+
puts "W: Elf: unhandled SH reloc #{reloc.inspect}" if $VERBOSE
|
739
|
+
target = nil
|
740
|
+
end
|
741
|
+
|
742
|
+
Metasm::Relocation.new(Expression[target], :u32, @endianness) if target
|
743
|
+
end
|
744
|
+
|
745
|
+
def arch_decode_segments_reloc_openrisc(reloc)
|
746
|
+
if reloc.symbol.kind_of?(Symbol) and n = reloc.symbol.name and reloc.symbol.shndx == 'UNDEF' and @sections and
|
747
|
+
s = @sections.find { |s_| s_.name and s_.offset <= @encoded.ptr and s_.offset + s_.size > @encoded.ptr }
|
748
|
+
@encoded.add_export(new_label("#{s.name}_#{n}"), @encoded.ptr, true)
|
749
|
+
end
|
750
|
+
|
751
|
+
original_word = decode_word
|
752
|
+
|
753
|
+
# decode addend if needed
|
754
|
+
case reloc.type
|
755
|
+
when 'NONE' # no addend
|
756
|
+
else addend = reloc.addend || Expression.make_signed(original_word, 32)
|
757
|
+
end
|
758
|
+
|
759
|
+
case reloc.type
|
760
|
+
when 'NONE'
|
761
|
+
when '32', '32_PCREL'
|
762
|
+
target = reloc_target(reloc)
|
763
|
+
target = Expression[target, :-, reloc.offset] if reloc.type == '32_PCREL'
|
764
|
+
target = Expression[target, :+, addend] if addend and addend != 0
|
765
|
+
when 'INSN_REL_26'
|
766
|
+
target = reloc_target(reloc)
|
767
|
+
addend &= 0x3ff_ffff
|
768
|
+
target = Expression[target, :+, [addend, :<<, 2]] if addend and addend != 0
|
769
|
+
target = Expression[[original_word, :&, 0xfc0_0000], :|, [[target, :&, 0x3ff_ffff], :>>, 2]]
|
770
|
+
when 'HI_16_IN_INSN'
|
771
|
+
target = reloc_target(reloc)
|
772
|
+
addend &= 0xffff
|
773
|
+
target = Expression[target, :+, [addend, :<<, 16]] if addend and addend != 0
|
774
|
+
target = Expression[[original_word, :&, 0xffff_0000], :|, [[target, :>>, 16], :&, 0xffff]]
|
775
|
+
when 'LO_16_IN_INSN'
|
776
|
+
target = reloc_target(reloc)
|
777
|
+
addend &= 0xffff
|
778
|
+
target = Expression[target, :+, addend] if addend and addend != 0
|
779
|
+
target = Expression[[original_word, :&, 0xffff_0000], :|, [target, :&, 0xffff]]
|
780
|
+
when 'JMP_SLOT'
|
781
|
+
target = reloc_target(reloc)
|
782
|
+
target = Expression[target, :+, addend] if addend and addend != 0
|
783
|
+
else
|
784
|
+
puts "W: Elf: unhandled MIPS reloc #{reloc.inspect}" if $VERBOSE
|
785
|
+
target = nil
|
786
|
+
end
|
787
|
+
|
788
|
+
Metasm::Relocation.new(Expression[target], :u32, @endianness) if target
|
789
|
+
end
|
790
|
+
|
652
791
|
class DwarfDebug
|
653
792
|
# decode a DWARF2 'compilation unit'
|
654
793
|
def decode(elf, info, abbrev, str)
|
@@ -749,12 +888,13 @@ class ELF
|
|
749
888
|
end
|
750
889
|
|
751
890
|
# decodes the ELF dynamic tags, interpret them, and decodes symbols and relocs
|
752
|
-
def decode_segments_dynamic
|
891
|
+
def decode_segments_dynamic(decode_relocs=true)
|
753
892
|
return if not dynamic = @segments.find { |s| s.type == 'DYNAMIC' }
|
754
893
|
@encoded.ptr = add_label('dynamic_tags', dynamic.vaddr)
|
755
894
|
decode_tags
|
756
895
|
decode_segments_tags_interpret
|
757
896
|
decode_segments_symbols
|
897
|
+
return if not decode_relocs
|
758
898
|
decode_segments_relocs
|
759
899
|
decode_segments_relocs_interpret
|
760
900
|
end
|
@@ -783,6 +923,7 @@ class ELF
|
|
783
923
|
|
784
924
|
# decodes sections, interprets symbols/relocs, fills sections.encoded
|
785
925
|
def decode_sections
|
926
|
+
@symbols.clear # the NULL symbol is explicit in the symbol table
|
786
927
|
decode_sections_symbols
|
787
928
|
decode_sections_relocs
|
788
929
|
@sections.each { |s|
|
@@ -804,7 +945,7 @@ class ELF
|
|
804
945
|
end
|
805
946
|
|
806
947
|
def decode_exports
|
807
|
-
decode_segments_dynamic
|
948
|
+
decode_segments_dynamic(false)
|
808
949
|
end
|
809
950
|
|
810
951
|
# decodes the elf header, and depending on the elf type, decode segments or sections
|
@@ -819,12 +960,14 @@ class ELF
|
|
819
960
|
|
820
961
|
def each_section
|
821
962
|
@segments.each { |s| yield s.encoded, s.vaddr if s.type == 'LOAD' }
|
822
|
-
|
963
|
+
return if @header.type != 'REL'
|
823
964
|
@sections.each { |s|
|
824
965
|
next if not s.encoded
|
825
|
-
l =
|
826
|
-
|
827
|
-
|
966
|
+
if not l = s.encoded.inv_export[0] or l != s.name.tr('^a-zA-Z0-9_', '_')
|
967
|
+
l = new_label(s.name)
|
968
|
+
s.encoded.add_export l, 0
|
969
|
+
end
|
970
|
+
yield s.encoded, l
|
828
971
|
}
|
829
972
|
end
|
830
973
|
|
@@ -833,9 +976,14 @@ class ELF
|
|
833
976
|
case @header.machine
|
834
977
|
when 'X86_64'; X86_64.new
|
835
978
|
when '386'; Ia32.new
|
836
|
-
when 'MIPS'; MIPS.new
|
979
|
+
when 'MIPS'; (@header.flags.include?('32BITMODE') ? MIPS64 : MIPS).new(@endianness)
|
837
980
|
when 'PPC'; PPC.new
|
838
981
|
when 'ARM'; ARM.new
|
982
|
+
when 'AARCH64'; AArch64.new
|
983
|
+
when 'SH'; Sh4.new
|
984
|
+
when 'ARC_COMPACT'; ARC.new
|
985
|
+
when 'MSP430'; MSP430.new
|
986
|
+
when 'OPENRISC'; OpenRisc.new(:latest, @endianness, (@header.flags.include?('NODELAY') ? 0 : 1))
|
839
987
|
else raise "unsupported cpu #{@header.machine}"
|
840
988
|
end
|
841
989
|
end
|
@@ -912,6 +1060,24 @@ EOC
|
|
912
1060
|
(d.address_binding[s.value] ||= {})[:$t9] ||= Expression[s.value]
|
913
1061
|
}
|
914
1062
|
d.function[:default] = @cpu.disassembler_default_func
|
1063
|
+
when 'sh4'
|
1064
|
+
noret = DecodedFunction.new
|
1065
|
+
noret.noreturn = true
|
1066
|
+
%w[__stack_chk_fail abort exit].each { |fn|
|
1067
|
+
d.function[Expression[fn]] = noret
|
1068
|
+
}
|
1069
|
+
d.function[:default] = @cpu.disassembler_default_func
|
1070
|
+
when 'openrisc'
|
1071
|
+
old_cp = d.c_parser
|
1072
|
+
d.c_parser = nil
|
1073
|
+
d.parse_c <<EOC
|
1074
|
+
void __libc_start_main(void(*)(), int, char**, void(*)(), void(*)()) __attribute__((noreturn));
|
1075
|
+
void __attribute__((noreturn)) exit(int);
|
1076
|
+
EOC
|
1077
|
+
d.function[Expression['__libc_start_main']] = @cpu.decode_c_function_prototype(d.c_parser, '__libc_start_main')
|
1078
|
+
d.function[Expression['exit']] = @cpu.decode_c_function_prototype(d.c_parser, 'exit')
|
1079
|
+
d.c_parser = old_cp
|
1080
|
+
d.function[:default] = @cpu.disassembler_default_func
|
915
1081
|
end
|
916
1082
|
d
|
917
1083
|
end
|
@@ -11,7 +11,7 @@ module Metasm
|
|
11
11
|
class ELF
|
12
12
|
class Header
|
13
13
|
def set_default_values elf
|
14
|
-
@magic ||=
|
14
|
+
@magic ||= ELF::MAGIC
|
15
15
|
@e_class ||= elf.bitsize.to_s
|
16
16
|
@data ||= (elf.endianness == :big ? 'MSB' : 'LSB')
|
17
17
|
@version ||= 'CURRENT'
|
@@ -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'
|
@@ -62,6 +62,7 @@ class ELF
|
|
62
62
|
return if name_p and sne.data[@name_p, @name.length+1] == @name+0.chr
|
63
63
|
return if @name_p = sne.data.index(@name+0.chr)
|
64
64
|
@name_p = sne.virtsize
|
65
|
+
@name.force_encoding('BINARY') if name.respond_to?(:force_encoding)
|
65
66
|
sne << @name << 0
|
66
67
|
end
|
67
68
|
end
|
@@ -92,6 +93,7 @@ class ELF
|
|
92
93
|
return if name_p and s[@name_p, @name.length+1] == @name+0.chr
|
93
94
|
return if @name_p = s.index(@name+0.chr)
|
94
95
|
@name_p = strtab.length
|
96
|
+
@name.force_encoding('BINARY') if name.respond_to?(:force_encoding)
|
95
97
|
strtab << @name << 0
|
96
98
|
end
|
97
99
|
end
|
@@ -140,6 +142,9 @@ class ELF
|
|
140
142
|
srank = rank[s]
|
141
143
|
nexts = @sections.find { |sec| rank[sec] > srank } # find section with rank superior
|
142
144
|
nexts = nexts ? @sections.index(nexts) : -1 # if none, last
|
145
|
+
if @header.shstrndx.to_i != 0 and nexts != -1 and @header.shstrndx >= nexts
|
146
|
+
@header.shstrndx += 1
|
147
|
+
end
|
143
148
|
@sections.insert(nexts, s) # insert section
|
144
149
|
end
|
145
150
|
|
@@ -196,6 +201,8 @@ class ELF
|
|
196
201
|
|
197
202
|
# encodes the symbol dynamic hash table in the .hash section, updates the HASH tag
|
198
203
|
def encode_hash
|
204
|
+
return if @symbols.length <= 1
|
205
|
+
|
199
206
|
if not hash = @sections.find { |s| s.type == 'HASH' }
|
200
207
|
hash = Section.new
|
201
208
|
hash.name = '.hash'
|
@@ -236,11 +243,13 @@ class ELF
|
|
236
243
|
# encodes the symbol table
|
237
244
|
# should have a stable self.sections array (only append allowed after this step)
|
238
245
|
def encode_segments_symbols(strtab)
|
246
|
+
return if @symbols.length <= 1
|
247
|
+
|
239
248
|
if not dynsym = @sections.find { |s| s.type == 'DYNSYM' }
|
240
249
|
dynsym = Section.new
|
241
250
|
dynsym.name = '.dynsym'
|
242
251
|
dynsym.type = 'DYNSYM'
|
243
|
-
dynsym.entsize = Symbol.
|
252
|
+
dynsym.entsize = Symbol.sizeof(self)
|
244
253
|
dynsym.addralign = 4
|
245
254
|
dynsym.flags = ['ALLOC']
|
246
255
|
dynsym.info = @symbols[1..-1].find_all { |s| s.bind == 'LOCAL' }.length + 1
|
@@ -251,7 +260,7 @@ class ELF
|
|
251
260
|
@symbols.each { |s| dynsym.encoded << s.encode(self, strtab.encoded) } # needs all section indexes, as will be in the final section header
|
252
261
|
|
253
262
|
@tag['SYMTAB'] = label_at(dynsym.encoded, 0)
|
254
|
-
@tag['SYMENT'] = Symbol.
|
263
|
+
@tag['SYMENT'] = Symbol.sizeof(self)
|
255
264
|
|
256
265
|
encode_check_section_size dynsym
|
257
266
|
|
@@ -261,7 +270,7 @@ class ELF
|
|
261
270
|
# encodes the relocation tables
|
262
271
|
# needs a complete self.symbols array
|
263
272
|
def encode_segments_relocs
|
264
|
-
return if not @relocations
|
273
|
+
return if not @relocations or @relocations.empty?
|
265
274
|
|
266
275
|
arch_preencode_reloc_func = "arch_#{@header.machine.downcase}_preencode_reloc"
|
267
276
|
send arch_preencode_reloc_func if respond_to? arch_preencode_reloc_func
|
@@ -287,7 +296,7 @@ class ELF
|
|
287
296
|
@tag['JMPREL'] = label_at(relplt.encoded, 0)
|
288
297
|
@tag['PLTRELSZ'] = relplt.encoded.virtsize
|
289
298
|
@tag['PLTREL'] = relplt.type = stype
|
290
|
-
@tag[stype + 'ENT'] = relplt.entsize = relplt.addralign = (stype == 'REL' ? Relocation.
|
299
|
+
@tag[stype + 'ENT'] = relplt.entsize = relplt.addralign = (stype == 'REL' ? Relocation.sizeof(self) : RelocationAddend.sizeof(self))
|
291
300
|
encode_check_section_size relplt
|
292
301
|
end
|
293
302
|
|
@@ -305,13 +314,13 @@ class ELF
|
|
305
314
|
rel.name = '.rel.dyn'
|
306
315
|
rel.type = 'REL'
|
307
316
|
rel.flags = ['ALLOC']
|
308
|
-
rel.entsize = rel.addralign = Relocation.
|
317
|
+
rel.entsize = rel.addralign = Relocation.sizeof(self)
|
309
318
|
encode_add_section rel
|
310
319
|
end
|
311
320
|
rel.encoded = EncodedData.new
|
312
321
|
list.each { |r| rel.encoded << r.encode(self) }
|
313
322
|
@tag['REL'] = label_at(rel.encoded, 0)
|
314
|
-
@tag['RELENT'] = Relocation.
|
323
|
+
@tag['RELENT'] = Relocation.sizeof(self)
|
315
324
|
@tag['RELSZ'] = rel.encoded.virtsize
|
316
325
|
encode_check_section_size rel
|
317
326
|
end
|
@@ -323,13 +332,13 @@ class ELF
|
|
323
332
|
rela.name = '.rela.dyn'
|
324
333
|
rela.type = 'RELA'
|
325
334
|
rela.flags = ['ALLOC']
|
326
|
-
rela.entsize = rela.addralign = RelocationAddend.
|
335
|
+
rela.entsize = rela.addralign = RelocationAddend.sizeof(self)
|
327
336
|
encode_add_section rela
|
328
337
|
end
|
329
338
|
rela.encoded = EncodedData.new
|
330
339
|
list.each { |r| rela.encoded << r.encode(self) }
|
331
340
|
@tag['RELA'] = label_at(rela.encoded, 0)
|
332
|
-
@tag['RELAENT'] = RelocationAddend.
|
341
|
+
@tag['RELAENT'] = RelocationAddend.sizeof(self)
|
333
342
|
@tag['RELASZ'] = rela.encoded.virtsize
|
334
343
|
encode_check_section_size rela
|
335
344
|
end
|
@@ -337,6 +346,8 @@ class ELF
|
|
337
346
|
|
338
347
|
# creates the .plt/.got from the @relocations
|
339
348
|
def arch_386_preencode_reloc
|
349
|
+
return if @relocations.empty?
|
350
|
+
|
340
351
|
# if .got.plt does not exist, the dynamic loader segfaults
|
341
352
|
if not gotplt = @sections.find { |s| s.type == 'PROGBITS' and s.name == '.got.plt' }
|
342
353
|
gotplt = Section.new
|
@@ -358,7 +369,7 @@ class ELF
|
|
358
369
|
when 'PC32'
|
359
370
|
next if not r.symbol
|
360
371
|
|
361
|
-
|
372
|
+
if r.symbol.type != 'FUNC'
|
362
373
|
# external data xref: generate a GOT entry
|
363
374
|
# XXX reuse .got.plt ?
|
364
375
|
if not got ||= @sections.find { |s| s.type == 'PROGBITS' and s.name == '.got' }
|
@@ -385,7 +396,7 @@ class ELF
|
|
385
396
|
else
|
386
397
|
@relocations.delete r
|
387
398
|
end
|
388
|
-
|
399
|
+
|
389
400
|
# prevoffset is label_section_start + int_section_offset
|
390
401
|
target_s = @sections.find { |s| s.encoded and s.encoded.export[prevoffset.lexpr] == 0 }
|
391
402
|
rel = target_s.encoded.reloc[prevoffset.rexpr]
|
@@ -411,12 +422,12 @@ class ELF
|
|
411
422
|
#
|
412
423
|
# [.got.plt header]
|
413
424
|
# dd _DYNAMIC
|
414
|
-
# dd 0
|
425
|
+
# dd 0 # rewritten to GOTPLT? by ld-linux
|
415
426
|
# dd 0 # rewritten to dlresolve_inplace by ld-linux
|
416
427
|
#
|
417
428
|
# [.got.plt + func_got_offset]
|
418
429
|
# dd some_func_got_default # lazily rewritten to the real addr of some_func by jmp dlresolve_inplace
|
419
|
-
#
|
430
|
+
# # base_relocated ?
|
420
431
|
|
421
432
|
# in the PIC case, _dlresolve imposes us to use the ebx register (which may not be saved by the calling function..)
|
422
433
|
# also geteip trashes eax, which may interfere with regparm(3)
|
@@ -448,7 +459,7 @@ class ELF
|
|
448
459
|
plt.encoded << shellcode["jmp [#{base} + #{gotplt.encoded.length}]"]
|
449
460
|
plt.encoded.add_export r.symbol.name+'_plt_default', plt.encoded.length
|
450
461
|
reloffset = @relocations.find_all { |rr| rr.type == 'JMP_SLOT' }.length
|
451
|
-
reloffset *= Relocation.
|
462
|
+
reloffset *= Relocation.sizeof(self) if @bitsize == 32
|
452
463
|
plt.encoded << shellcode["push #{reloffset}\njmp metasm_plt_start"]
|
453
464
|
|
454
465
|
# transform the reloc PC32 => JMP_SLOT
|
@@ -510,6 +521,7 @@ class ELF
|
|
510
521
|
add_str = lambda { |n|
|
511
522
|
if n and n != '' and not ret = strtab.encoded.data.index(n + 0.chr)
|
512
523
|
ret = strtab.encoded.virtsize
|
524
|
+
n.force_encoding('BINARY') if n.respond_to?(:force_encoding)
|
513
525
|
strtab.encoded << n << 0
|
514
526
|
end
|
515
527
|
ret || 0
|
@@ -531,7 +543,7 @@ class ELF
|
|
531
543
|
|
532
544
|
# fill these later, but create the base relocs now
|
533
545
|
arch_create_reloc_func = "arch_#{@header.machine.downcase}_create_reloc"
|
534
|
-
next if not respond_to?(arch_create_reloc_func)
|
546
|
+
next if not respond_to?(arch_create_reloc_func)
|
535
547
|
curaddr = label_at(@encoded, 0, 'elf_start')
|
536
548
|
fkbind = {}
|
537
549
|
@sections.each { |s|
|
@@ -557,6 +569,9 @@ class ELF
|
|
557
569
|
|
558
570
|
encode_check_section_size strtab
|
559
571
|
|
572
|
+
# rm unused tag (shrink .nointerp binaries by allowing to skip the section entirely)
|
573
|
+
@tag.delete('STRTAB') if strtab.encoded.length == 1
|
574
|
+
|
560
575
|
# XXX any order needed ?
|
561
576
|
@tag.keys.each { |k|
|
562
577
|
case k
|
@@ -581,7 +596,7 @@ class ELF
|
|
581
596
|
encode_tag[k, @tag[k]]
|
582
597
|
end
|
583
598
|
}
|
584
|
-
encode_tag['NULL', @tag['NULL'] || 0]
|
599
|
+
encode_tag['NULL', @tag['NULL'] || 0] unless @tag.empty?
|
585
600
|
|
586
601
|
encode_check_section_size dynamic
|
587
602
|
end
|
@@ -598,17 +613,13 @@ class ELF
|
|
598
613
|
@sections.each { |s|
|
599
614
|
next if not s.encoded
|
600
615
|
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]
|
616
|
+
et = r.target.externals
|
617
|
+
extern = et.find_all { |name| autoexports[name] }
|
618
|
+
next if extern.length != 1
|
619
|
+
symname = extern.first
|
609
620
|
if not @symbols.find { |sym| sym.name == symname }
|
610
621
|
@tag['NEEDED'] ||= []
|
611
|
-
@tag['NEEDED'] |= [
|
622
|
+
@tag['NEEDED'] |= [autoexports[symname]]
|
612
623
|
sym = Symbol.new
|
613
624
|
sym.shndx = 'UNDEF'
|
614
625
|
sym.type = 'FUNC'
|
@@ -737,6 +748,55 @@ class ELF
|
|
737
748
|
@relocations << r
|
738
749
|
end
|
739
750
|
|
751
|
+
def arch_mips_create_reloc(section, off, binding, rel=nil)
|
752
|
+
rel ||= section.encoded.reloc[off]
|
753
|
+
startaddr = label_at(@encoded, 0)
|
754
|
+
r = Relocation.new
|
755
|
+
r.offset = Expression[label_at(section.encoded, 0, 'sect_start'), :+, off]
|
756
|
+
if Expression[rel.target, :-, startaddr].bind(binding).reduce.kind_of?(::Integer)
|
757
|
+
# this location is relative to the base load address of the ELF
|
758
|
+
r.type = 'REL32'
|
759
|
+
else
|
760
|
+
et = rel.target.externals
|
761
|
+
extern = et.find_all { |name| not binding[name] }
|
762
|
+
if extern.length != 1
|
763
|
+
puts "ELF: mips_create_reloc: ignoring reloc #{rel.target} in #{section.name}: #{extern.inspect} unknown" if $VERBOSE
|
764
|
+
return
|
765
|
+
end
|
766
|
+
if not sym = @symbols.find { |s| s.name == extern.first }
|
767
|
+
puts "ELF: mips_create_reloc: ignoring reloc #{rel.target} in #{section.name}: undefined symbol #{extern.first}" if $VERBOSE
|
768
|
+
return
|
769
|
+
end
|
770
|
+
r.symbol = sym
|
771
|
+
if Expression[rel.target, :-, sym.name].bind(binding).reduce.kind_of?(::Integer)
|
772
|
+
rel.target = Expression[rel.target, :-, sym.name]
|
773
|
+
r.type = '32'
|
774
|
+
elsif Expression[rel.target, :&, 0xffff0000].reduce.kind_of?(::Integer)
|
775
|
+
lo = Expression[rel.target, :&, 0xffff].reduce
|
776
|
+
lo = lo.lexpr if lo.kind_of?(Expression) and lo.op == :& and lo.rexpr == 0xffff
|
777
|
+
if lo.kind_of?(Expression) and lo.op == :>> and lo.rexpr == 16
|
778
|
+
r.type = 'HI16'
|
779
|
+
rel.target = Expression[rel.target, :&, 0xffff0000]
|
780
|
+
# XXX offset ?
|
781
|
+
elsif lo.kind_of?(String) or (lo.kind_of(Expression) and lo.op == :+)
|
782
|
+
r.type = 'LO16'
|
783
|
+
rel.target = Expression[rel.target, :&, 0xffff0000]
|
784
|
+
# XXX offset ?
|
785
|
+
else
|
786
|
+
puts "ELF: mips_create_reloc: ignoring reloc #{lo}: cannot find matching 16 reloc type" if $VERBOSE
|
787
|
+
return
|
788
|
+
end
|
789
|
+
#elsif Expression[rel.target, :+, label_at(section.encoded, 0)].bind(section.encoded.binding).reduce.kind_of? ::Integer
|
790
|
+
# rel.target = Expression[[rel.target, :+, label_at(section.encoded, 0)], :+, off]
|
791
|
+
# r.type = 'PC32'
|
792
|
+
else
|
793
|
+
puts "ELF: mips_create_reloc: ignoring reloc #{sym.name} + #{rel.target}: cannot find matching standard reloc type" if $VERBOSE
|
794
|
+
return
|
795
|
+
end
|
796
|
+
end
|
797
|
+
@relocations << r
|
798
|
+
end
|
799
|
+
|
740
800
|
# resets the fields of the elf headers that should be recalculated, eg phdr offset
|
741
801
|
def invalidate_header
|
742
802
|
@header.shoff = @header.shnum = nil
|
@@ -817,9 +877,13 @@ class ELF
|
|
817
877
|
end
|
818
878
|
|
819
879
|
if @header.type == 'REL'
|
820
|
-
|
880
|
+
encode_rel
|
881
|
+
else
|
882
|
+
encode_elf
|
821
883
|
end
|
884
|
+
end
|
822
885
|
|
886
|
+
def encode_elf
|
823
887
|
@encoded = EncodedData.new
|
824
888
|
if @header.type != 'EXEC' or @segments.find { |i| i.type == 'INTERP' }
|
825
889
|
# create a .dynamic section unless we are an ET_EXEC with .nointerp
|
@@ -870,7 +934,7 @@ class ELF
|
|
870
934
|
end
|
871
935
|
|
872
936
|
# add dynamic segment
|
873
|
-
if ds = @sections.find { |sec| sec.type == 'DYNAMIC' }
|
937
|
+
if ds = @sections.find { |sec| sec.type == 'DYNAMIC' } and ds.encoded.length > 1
|
874
938
|
ds.set_default_values self
|
875
939
|
seg = Segment.new
|
876
940
|
seg.type = 'DYNAMIC'
|
@@ -979,6 +1043,36 @@ class ELF
|
|
979
1043
|
@encoded.data
|
980
1044
|
end
|
981
1045
|
|
1046
|
+
def encode_rel
|
1047
|
+
@encoded = EncodedData.new
|
1048
|
+
automagic_symbols
|
1049
|
+
create_relocations
|
1050
|
+
|
1051
|
+
@header.phoff = @header.phnum = @header.phentsize = 0
|
1052
|
+
@header.entry = 0
|
1053
|
+
@sections.each { |sec| sec.addr = 0 }
|
1054
|
+
st = @sections.inject(EncodedData.new) { |edata, sec| edata << sec.encode(self) }
|
1055
|
+
|
1056
|
+
binding = {}
|
1057
|
+
@encoded << @header.encode(self)
|
1058
|
+
@encoded.align 8
|
1059
|
+
|
1060
|
+
binding[@header.shoff] = @encoded.length
|
1061
|
+
@encoded << st
|
1062
|
+
@encoded.align 8
|
1063
|
+
|
1064
|
+
@sections.each { |sec|
|
1065
|
+
next if not sec.encoded
|
1066
|
+
binding[sec.offset] = @encoded.length
|
1067
|
+
sec.encoded.fixup sec.encoded.binding
|
1068
|
+
@encoded << sec.encoded
|
1069
|
+
@encoded.align 8
|
1070
|
+
}
|
1071
|
+
|
1072
|
+
@encoded.fixup! binding
|
1073
|
+
@encoded.data
|
1074
|
+
end
|
1075
|
+
|
982
1076
|
def parse_init
|
983
1077
|
# allow the user to specify a section, falls back to .text if none specified
|
984
1078
|
if not defined? @cursource or not @cursource
|