resedit 1.7.3 → 1.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/resedit.rb +10 -4
- data/lib/resedit/app/mz_command.rb +15 -6
- data/lib/resedit/classes/changeable.rb +27 -13
- data/lib/resedit/classes/config.rb +35 -0
- data/lib/resedit/{mz/mzenv.rb → classes/env.rb} +30 -15
- data/lib/resedit/classes/exefile.rb +339 -0
- data/lib/resedit/classes/hexwriter.rb +7 -15
- data/lib/resedit/mz/bw.rb +67 -0
- data/lib/resedit/mz/le.rb +234 -0
- data/lib/resedit/mz/multiexe.rb +85 -0
- data/lib/resedit/mz/mz.rb +231 -124
- metadata +8 -5
- data/lib/resedit/mz/mz_body.rb +0 -145
- data/lib/resedit/mz/mz_header.rb +0 -200
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d5bb82eb4e37c29d800e45d61d1fd8359afb224d
|
4
|
+
data.tar.gz: 206c81a15f6e4bc8f50893ce9c8900fb89ec4ad4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c28f9d26f1e08a3980b254ada58e772a2a65efec98ca6e4b9008625ca1f7790a61777d9dd882a618c001abcfa3a71b9d07ecacaf321c176fcfcbcb3f90d713cd
|
7
|
+
data.tar.gz: 05c2a94a3fba256b35e624d2477678d3210a3009f994fa347f500afae29dbbb7eabe79789ade857336e9ed1ecb9ab872da30d58b6ebe1d3bcf3c93de71716ce0
|
data/lib/resedit.rb
CHANGED
@@ -8,16 +8,22 @@ require 'resedit/app/app'
|
|
8
8
|
require 'resedit/text/huffman'
|
9
9
|
require 'resedit/app/font_convert'
|
10
10
|
require 'resedit/app/text_convert'
|
11
|
+
require 'resedit/classes/env'
|
12
|
+
require 'resedit/classes/colorizer'
|
13
|
+
require 'resedit/classes/hexwriter'
|
14
|
+
require 'resedit/classes/changeable'
|
15
|
+
require 'resedit/classes/exefile'
|
16
|
+
require 'resedit/classes/config'
|
11
17
|
require 'resedit/convert/bitconv'
|
12
18
|
require 'resedit/convert/bitstream'
|
13
19
|
require 'resedit/convert/codepatch'
|
14
20
|
require 'resedit/convert/colors'
|
15
21
|
require 'resedit/mz/mz'
|
16
|
-
require 'resedit/
|
17
|
-
require 'resedit/
|
18
|
-
require 'resedit/
|
22
|
+
require 'resedit/mz/bw'
|
23
|
+
require 'resedit/mz/le'
|
24
|
+
require 'resedit/mz/multiexe'
|
19
25
|
|
20
26
|
|
21
27
|
module Resedit
|
22
|
-
VERSION = "1.
|
28
|
+
VERSION = "1.8"
|
23
29
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'resedit/app/app_command'
|
2
|
-
require 'resedit/mz/
|
3
|
-
require 'resedit/
|
4
|
-
|
2
|
+
require 'resedit/mz/multiexe'
|
3
|
+
require 'resedit/classes/env'
|
5
4
|
|
6
5
|
module Resedit
|
7
6
|
|
@@ -28,7 +27,9 @@ module Resedit
|
|
28
27
|
"revert"=>[method(:revert), "revert changes", {"ofs"=>"change offset/all"}],
|
29
28
|
"hex"=>[method(:hex), "print hex file", {"ofs" => "data offset", "size" => "data size", "how"=>"original/modified", "disp" => "code/file"}],
|
30
29
|
"dasm"=>[method(:dasm), "print disasm", {"ofs" => "data offset", "size" => "data size", "how"=>"original/modified"}],
|
30
|
+
"eval"=>[method(:expr), "print expression", {"expr" => "expression"}],
|
31
31
|
}
|
32
|
+
@shorters = {"p"=>"print", "e"=>"eval"}
|
32
33
|
@files = []
|
33
34
|
@cur = nil
|
34
35
|
end
|
@@ -58,7 +59,9 @@ module Resedit
|
|
58
59
|
|
59
60
|
def getfile(id)
|
60
61
|
return @cur if id == nil
|
61
|
-
|
62
|
+
#env = !@cur ? Env.new(self) : @cur.env
|
63
|
+
env = Env.new()
|
64
|
+
i,res = env.s2i_nt(id)
|
62
65
|
if res
|
63
66
|
raise "Bad file id: " + i.to_s if @files.length < i || i < 0
|
64
67
|
return @files[i]
|
@@ -95,7 +98,7 @@ module Resedit
|
|
95
98
|
def use(params)
|
96
99
|
mz = getfile(params['file'])
|
97
100
|
if mz==nil
|
98
|
-
mz =
|
101
|
+
mz = Multiexe.new(params['file'])
|
99
102
|
@files+=[mz]
|
100
103
|
end
|
101
104
|
@cur = mz
|
@@ -105,7 +108,7 @@ module Resedit
|
|
105
108
|
|
106
109
|
def close(params)
|
107
110
|
mz = getfile(params['file'])
|
108
|
-
raise "File not found: "+fn if nil ==
|
111
|
+
raise "File not found: "+fn if nil == mz
|
109
112
|
@files -= [mz]
|
110
113
|
@cur = nil if @cur == mz
|
111
114
|
mz.close()
|
@@ -158,9 +161,15 @@ module Resedit
|
|
158
161
|
cur().dasm(params['ofs'], params['size'], params['how'])
|
159
162
|
end
|
160
163
|
|
164
|
+
def expr(params)
|
165
|
+
env = @cur && @cur.env ? @cur.env : Env.new()
|
166
|
+
puts env.s2i(params['expr'])
|
167
|
+
end
|
168
|
+
|
161
169
|
|
162
170
|
def job(params)
|
163
171
|
cmd = params['cmd']
|
172
|
+
cmd = @shorters[cmd] if @shorters[cmd]
|
164
173
|
if cmd.length==0 || File.exist?(cmd)
|
165
174
|
App::get().setShell('mz')
|
166
175
|
return if cmd.length == 0
|
@@ -224,6 +224,8 @@ module Resedit
|
|
224
224
|
|
225
225
|
def debug(); LOG.level = Logger::DEBUG end
|
226
226
|
|
227
|
+
def size; @root.size end
|
228
|
+
|
227
229
|
def dbgdump
|
228
230
|
LOG.debug("---#{@root.size()}---\n")
|
229
231
|
@root.dump()
|
@@ -294,27 +296,39 @@ module Resedit
|
|
294
296
|
file.write(bytes())
|
295
297
|
end
|
296
298
|
|
297
|
-
def
|
299
|
+
def hexify(bts)
|
300
|
+
bts.each_byte.map { |b| sprintf("%02X",b) }.join
|
301
|
+
end
|
302
|
+
|
303
|
+
def unhexify(str)
|
304
|
+
str.scan(/../).collect { |c| c.to_i(16).chr }.join
|
305
|
+
end
|
306
|
+
|
307
|
+
def saveChanges()
|
298
308
|
mode(HOW_CHANGED)
|
309
|
+
cfg = {}
|
299
310
|
chs = getChanges()
|
300
|
-
file.write([chs.length].pack('V'))
|
301
311
|
chs.each{|o,bts|
|
302
|
-
|
303
|
-
|
304
|
-
|
312
|
+
obj = {}
|
313
|
+
obj["insert"] = bts[1].length if bts[0].length==0
|
314
|
+
obj["change"] = hexify(bts[0]) if bts[0].length>0
|
315
|
+
cfg[o] = obj
|
305
316
|
}
|
317
|
+
return cfg
|
306
318
|
end
|
307
319
|
|
308
|
-
def loadChanges(
|
320
|
+
def loadChanges(hs)
|
309
321
|
mode(HOW_CHANGED)
|
310
322
|
@root.revert
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
323
|
+
hs.each{|ofs, obj|
|
324
|
+
if obj['insert']
|
325
|
+
len = obj['insert']
|
326
|
+
@root.cload(ofs.to_i, "", len)
|
327
|
+
elsif obj['change']
|
328
|
+
bts = unhexify(obj['change'])
|
329
|
+
@root.cload(ofs.to_i, bts, bts.length)
|
330
|
+
end
|
331
|
+
}
|
318
332
|
mode(HOW_CHANGED)
|
319
333
|
end
|
320
334
|
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Resedit
|
4
|
+
|
5
|
+
class Config
|
6
|
+
|
7
|
+
attr_accessor :cfg
|
8
|
+
def initialize(fname, section=nil)
|
9
|
+
@fname, @section = fname, section
|
10
|
+
@cfg = load()
|
11
|
+
@cfg = (@cfg[@section] or {}) if @section
|
12
|
+
end
|
13
|
+
|
14
|
+
def [](nm); @cfg[nm] end
|
15
|
+
def []=(nm, value); @cfg[nm]=value end
|
16
|
+
|
17
|
+
def load();
|
18
|
+
File.exists?(@fname) ? JSON.parse(File.read(@fname)) : {}
|
19
|
+
end
|
20
|
+
|
21
|
+
def save()
|
22
|
+
if @section
|
23
|
+
c = load()
|
24
|
+
c[@section] = @cfg
|
25
|
+
else
|
26
|
+
c = cfg
|
27
|
+
end
|
28
|
+
open(@fname, "w"){|f|
|
29
|
+
f.write(JSON.pretty_generate(c))
|
30
|
+
}
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -1,15 +1,17 @@
|
|
1
|
-
require '
|
1
|
+
require 'ostruct'
|
2
2
|
|
3
3
|
module Resedit
|
4
4
|
|
5
|
-
class
|
5
|
+
class Env < OpenStruct
|
6
6
|
|
7
|
-
|
7
|
+
def initialize(owner=nil)
|
8
|
+
super()
|
9
|
+
@owner = owner
|
10
|
+
@mode = @owner ? @owner.class::MODE : 16
|
11
|
+
end
|
8
12
|
|
9
|
-
def set(name,value)
|
10
|
-
|
11
|
-
define_method(name){ s2i(value) }
|
12
|
-
}
|
13
|
+
def set(name, value)
|
14
|
+
self[name] = s2i(value)
|
13
15
|
end
|
14
16
|
|
15
17
|
def s2i_nt(str)
|
@@ -18,17 +20,30 @@ module Resedit
|
|
18
20
|
return [0, false]
|
19
21
|
end
|
20
22
|
|
23
|
+
def addr2raw16(ss)
|
24
|
+
ss[0] = '0x'+ss[0] if ss[0][0,2]!='0x'
|
25
|
+
ss[1] = '0x'+ss[1] if ss[1][0,2]!='0x'
|
26
|
+
fix = 0
|
27
|
+
if ss.length == 3
|
28
|
+
raise "Dont known how to #{ss[2]} address" if ss[2]!="fix"
|
29
|
+
fix = relocFix
|
30
|
+
end
|
31
|
+
return ((s2i(ss[0])+fix) << 4) + s2i(ss[1])
|
32
|
+
end
|
33
|
+
|
34
|
+
def addr2raw32(ss)
|
35
|
+
ss[1] = '0x'+ss[1] if ss[1][0,2]!='0x'
|
36
|
+
if ss[0]==''
|
37
|
+
return @owner.body.addr2raw(s2i(ss[1]))
|
38
|
+
end
|
39
|
+
ss[0] = 'seg'+ss[0] if ss[0][0,3]!='seg'
|
40
|
+
return eval(ss[0]+"+"+ss[1])
|
41
|
+
end
|
42
|
+
|
21
43
|
def s2i(str)
|
22
44
|
ss=str.split(':')
|
23
45
|
if ss.length == 2 || ss.length == 3
|
24
|
-
|
25
|
-
ss[1] = '0x'+ss[1] if ss[1][0,2]!='0x'
|
26
|
-
fix = 0
|
27
|
-
if ss.length == 3
|
28
|
-
raise "Dont known how to #{ss[2]} address" if ss[2]!="fix"
|
29
|
-
fix = relocFix
|
30
|
-
end
|
31
|
-
return ((s2i(ss[0])+fix) << 4) + s2i(ss[1])
|
46
|
+
return @mode==32 ? addr2raw32(ss) : addr2raw16(ss)
|
32
47
|
end
|
33
48
|
return eval(str, binding())
|
34
49
|
end
|
@@ -0,0 +1,339 @@
|
|
1
|
+
require 'resedit/classes/changeable'
|
2
|
+
require 'resedit/classes/hexwriter'
|
3
|
+
require 'resedit/classes/env'
|
4
|
+
require 'json'
|
5
|
+
|
6
|
+
begin
|
7
|
+
require 'crabstone'
|
8
|
+
include Crabstone
|
9
|
+
$nocrabstone = false
|
10
|
+
rescue LoadError
|
11
|
+
$nocrabstone = true
|
12
|
+
end
|
13
|
+
|
14
|
+
module Resedit
|
15
|
+
|
16
|
+
class ExeHeader < Changeable
|
17
|
+
BLK = 0x200
|
18
|
+
PARA = 0x10
|
19
|
+
HDRDESCR = [:Magic]
|
20
|
+
HDRUNPACK = "v*"
|
21
|
+
|
22
|
+
attr_reader :info, :exe
|
23
|
+
|
24
|
+
def initialize(exe, file, fsize)
|
25
|
+
raise "Not EXE file" if fsize < self.class::HSIZE
|
26
|
+
@exe = exe
|
27
|
+
super(file, self.class::HSIZE)
|
28
|
+
@_infoOrig = loadInfo()
|
29
|
+
@_info = nil
|
30
|
+
@info = @_infoOrig
|
31
|
+
@relocFix = 0
|
32
|
+
raise "Not EXE file" if self.class::MAGIC != @info[:Magic] && (!self.class::MAGIC.is_a?(Array) || !self.class::MAGIC.include?(@info[:Magic]))
|
33
|
+
loadTables(file)
|
34
|
+
loadTail(file)
|
35
|
+
end
|
36
|
+
|
37
|
+
def mode(how)
|
38
|
+
super(how)
|
39
|
+
if @mode == HOW_ORIGINAL
|
40
|
+
@info = @_infoOrig
|
41
|
+
else
|
42
|
+
@_info = loadInfo() if !@_info
|
43
|
+
@info = @_info
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
def change(ofs, bytes)
|
49
|
+
super(ofs, bytes)
|
50
|
+
@_info = nil if (ofs < HSIZE)
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def loadInfo()
|
55
|
+
v = getData(0, self.class::HSIZE).unpack(self.class::HDRUNPACK)
|
56
|
+
ret = self.class::HDRDESCR.map.with_index { |x, i| [x, v[i]] }.to_h
|
57
|
+
return ret
|
58
|
+
end
|
59
|
+
def loadTables(file); end
|
60
|
+
def loadTail(file);
|
61
|
+
addData(file, headerSize() - self.class::HSIZE)
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
def setInfo(field, values, pack="v*")
|
66
|
+
raise "Unknown header field #{field}" if !self.class::HDRDESCR.include?(field)
|
67
|
+
values = [values] if !values.is_a?(Array)
|
68
|
+
change(self.class::HDRDESCR.index(field)*2, values.pack(pack))
|
69
|
+
end
|
70
|
+
|
71
|
+
def setBodySize(size); setFileSize(size + headerSize()) end
|
72
|
+
|
73
|
+
def headerSize(); self.class::HSIZE end
|
74
|
+
|
75
|
+
def print(what, how)
|
76
|
+
return false if what!="header"
|
77
|
+
mode(parseHow(how))
|
78
|
+
ofs=0
|
79
|
+
wsz = @exe.wsize
|
80
|
+
@info.each{|k,v|
|
81
|
+
printf("%20s:\t%s\n", k.to_s, colStr(v, changed?(ofs,wsz)))
|
82
|
+
ofs+=2
|
83
|
+
}
|
84
|
+
puts
|
85
|
+
return true
|
86
|
+
end
|
87
|
+
|
88
|
+
def setHeaderSize(size); raise "NotImplemented" end
|
89
|
+
def fileSize(); raise "NotImplemented" end
|
90
|
+
def setFileSize(size); raise "NotImplemented" end
|
91
|
+
def entry(size); raise "NotImplemented" end
|
92
|
+
end
|
93
|
+
|
94
|
+
|
95
|
+
class ExeBody < Changeable
|
96
|
+
|
97
|
+
attr_reader :exe
|
98
|
+
|
99
|
+
def initialize(exe, file, size)
|
100
|
+
@exe = exe
|
101
|
+
super(file, size)
|
102
|
+
@addsz = 0
|
103
|
+
end
|
104
|
+
|
105
|
+
def removeAppend()
|
106
|
+
mode(HOW_CHANGED)
|
107
|
+
undo(0) if @root.obuf.length==0
|
108
|
+
@addsz = 0
|
109
|
+
end
|
110
|
+
|
111
|
+
def revert(what)
|
112
|
+
super(what)
|
113
|
+
@addsz = 0
|
114
|
+
end
|
115
|
+
|
116
|
+
def printDasm(inst, str)
|
117
|
+
printf("%08X %s\n",inst.address, str)
|
118
|
+
end
|
119
|
+
|
120
|
+
def hex(wr, ofs, size, how)
|
121
|
+
wr.addressFormatter = self
|
122
|
+
if how && (how[0]='r' || how[0]='R')
|
123
|
+
wr.addBytes(readRelocated(ofs, size))
|
124
|
+
return
|
125
|
+
end
|
126
|
+
super(wr, ofs, size, how)
|
127
|
+
end
|
128
|
+
|
129
|
+
def formatAddress(raw)
|
130
|
+
return sprintf("%08X", raw)
|
131
|
+
end
|
132
|
+
|
133
|
+
def dasm(ofs, size, how, mode)
|
134
|
+
raise "Crabstone gem required to disasm." if $nocrabstone
|
135
|
+
relocated = false
|
136
|
+
if how && how[0]='r' || how[0]='R'
|
137
|
+
relocated = true
|
138
|
+
how = nil
|
139
|
+
end
|
140
|
+
mode(parseHow(how))
|
141
|
+
cs = Disassembler.new(ARCH_X86, mode==16 ? MODE_16 : MODE_32)
|
142
|
+
begin
|
143
|
+
while true
|
144
|
+
begin
|
145
|
+
d = relocated ? readRelocated(ofs, size) : getData(ofs, size)
|
146
|
+
cs.disasm(d, ofs).each {|i|
|
147
|
+
bts = i.bytes.map { |b| sprintf("%02X",b) }.join
|
148
|
+
inst = colStr(sprintf("%14s\t%s\t%s", bts, i.mnemonic, i.op_str), changed?(i.address, i.bytes.length))
|
149
|
+
printDasm(i, inst)
|
150
|
+
}
|
151
|
+
break
|
152
|
+
rescue
|
153
|
+
ofs-=1
|
154
|
+
end
|
155
|
+
end
|
156
|
+
ensure
|
157
|
+
cs.close()
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
def raw2addr(ofs); raise "Not implemented" end
|
162
|
+
def addr2raw(addr); raise "Not implemented" end
|
163
|
+
def append(bytes, where=nil); raise "NotImplemented" end
|
164
|
+
def addrFormatter(hofs); nil end
|
165
|
+
def readRelocated(ofs, size); raise "NotImplemented" end
|
166
|
+
end
|
167
|
+
|
168
|
+
class ExeFile
|
169
|
+
HDRCLASS = nil
|
170
|
+
BODYCLASS = nil
|
171
|
+
CFGEXT = ".mzcfg.json"
|
172
|
+
MODE = 16
|
173
|
+
|
174
|
+
attr_reader :header, :body, :fname, :path, :name, :env
|
175
|
+
|
176
|
+
def initialize(path=nil, quiet = false)
|
177
|
+
@quiet = quiet
|
178
|
+
@path=path
|
179
|
+
@env = Env.new(self)
|
180
|
+
if @path!=nil
|
181
|
+
@path = path.downcase()
|
182
|
+
fsize = File.size(path)
|
183
|
+
open(@path,"rb:ascii-8bit"){|f|
|
184
|
+
load(f, fsize)
|
185
|
+
}
|
186
|
+
if File.exist?(@path+CFGEXT)
|
187
|
+
cfg = JSON.parse(File.read(@path+CFGEXT))
|
188
|
+
loadConfig(cfg)
|
189
|
+
end
|
190
|
+
@fname = File.basename(@path)
|
191
|
+
@name = File.basename(@path, ".*")
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def wsize; self.class::MODE/8 end
|
196
|
+
|
197
|
+
def load(f, fsize, prev=nil)
|
198
|
+
@header = self.class::HDRCLASS.new(self, f, fsize)
|
199
|
+
@body = self.class::BODYCLASS.new(self, f, @header.fileSize() - @header.headerSize())
|
200
|
+
@env.set(:entry, @header.entry())
|
201
|
+
@env.set(:append, sprintf("0"))
|
202
|
+
end
|
203
|
+
|
204
|
+
def loadConfig(cfg)
|
205
|
+
cfg = cfg[self.class.name]
|
206
|
+
raise "Wrong config: #{self.class.name} expected" if !cfg
|
207
|
+
@header.loadChanges(cfg['header'])
|
208
|
+
@body.loadChanges(cfg['body'])
|
209
|
+
end
|
210
|
+
|
211
|
+
def close(); end
|
212
|
+
def log(fmt, *args); App::get().log(fmt, *args) if !@quiet end
|
213
|
+
def s2i(str) return @env.s2i(str) end
|
214
|
+
|
215
|
+
|
216
|
+
def is?(id)
|
217
|
+
id = id.downcase
|
218
|
+
return id == @path || id == @fname || id == @name
|
219
|
+
end
|
220
|
+
|
221
|
+
def print(what, how=nil)
|
222
|
+
puts "Header changes:" if what=="changes"
|
223
|
+
res = @header.print(what, how)
|
224
|
+
puts "Code changes:" if what=="changes"
|
225
|
+
res |= @body.print(what, how)
|
226
|
+
raise "Don't know how to print: " + what if !res
|
227
|
+
end
|
228
|
+
|
229
|
+
|
230
|
+
def hex(ofs, size=nil, how=nil, disp=nil)
|
231
|
+
ofs = ofs ? s2i(ofs) : 0
|
232
|
+
size = size ? s2i(size) : 0x100
|
233
|
+
isfile = disp && (disp[0]=='f' || disp[0]=='F') ? true : false
|
234
|
+
wr = HexWriter.new(ofs)
|
235
|
+
hsz = 0
|
236
|
+
if isfile
|
237
|
+
@header.mode(@header.parseHow(how))
|
238
|
+
hsz = @header.headerSize()
|
239
|
+
size = @header.hex(wr, ofs, size, how) if ofs < hsz
|
240
|
+
ofs -= hsz
|
241
|
+
ofs = 0 if ofs < 0
|
242
|
+
wr.addr = 0
|
243
|
+
end
|
244
|
+
@body.hex(wr, ofs, size, how) if size > 0
|
245
|
+
wr.finish()
|
246
|
+
end
|
247
|
+
|
248
|
+
def hexify(str); @header.hexify(str) end
|
249
|
+
|
250
|
+
def getValue(value, type)
|
251
|
+
s = @env.value2bytes(value, type)
|
252
|
+
return s.force_encoding(Encoding::ASCII_8BIT)
|
253
|
+
end
|
254
|
+
|
255
|
+
|
256
|
+
def append(value, type=nil, where=nil)
|
257
|
+
where = s2i(where) if where
|
258
|
+
res = @body.append(getValue(value,type), where)
|
259
|
+
s = ""
|
260
|
+
res.each{|a|
|
261
|
+
if a.is_a?(Array)
|
262
|
+
s += sprintf(" %04X:%04X", a[1], a[0])
|
263
|
+
else
|
264
|
+
s += sprintf(" %08X", a)
|
265
|
+
end
|
266
|
+
}
|
267
|
+
log("Appended at %s",s)
|
268
|
+
return res
|
269
|
+
end
|
270
|
+
|
271
|
+
|
272
|
+
def replace(value, type=nil, where=nil)
|
273
|
+
@body.removeAppend()
|
274
|
+
return append(value, type, where)
|
275
|
+
end
|
276
|
+
|
277
|
+
|
278
|
+
def change(ofs, value, disp=nil, type=nil)
|
279
|
+
ofs = s2i(ofs)
|
280
|
+
isfile = disp && (disp[0]=='f' || disp[0]=='F') ? true : false
|
281
|
+
value = getValue(value, type)
|
282
|
+
if isfile
|
283
|
+
res = @header.change(ofs,value)
|
284
|
+
else
|
285
|
+
res = @body.change(ofs,value) + @header.headerSize()
|
286
|
+
end
|
287
|
+
log("Change added at %08X", res) if res
|
288
|
+
end
|
289
|
+
|
290
|
+
def reloc(ofs); raise "NotImplemented" end
|
291
|
+
|
292
|
+
def readRelocated(ofs, size); @body.readRelocated(ofs, size) end
|
293
|
+
|
294
|
+
def dasm(ofs, size=nil, how=nil)
|
295
|
+
ofs = s2i(ofs ? ofs : "entry")
|
296
|
+
size = size ? s2i(size) : [0x20, @body.bytes.length-ofs].min
|
297
|
+
@body.dasm(ofs, size, how, self.class::MODE)
|
298
|
+
end
|
299
|
+
|
300
|
+
|
301
|
+
def valueof(str, type)
|
302
|
+
puts "value of " + str + " is:"
|
303
|
+
p getValue(str, type).unpack("H*")
|
304
|
+
end
|
305
|
+
|
306
|
+
|
307
|
+
def revert(what)
|
308
|
+
wid = @env.s2i_nt(what)
|
309
|
+
what = wid[1] ? wid[0] : what
|
310
|
+
res = @header.revert(what)
|
311
|
+
res |= @body.revert(what)
|
312
|
+
raise "Don't know how to revert: "+what if !res
|
313
|
+
log("Reverted")
|
314
|
+
end
|
315
|
+
|
316
|
+
def saveConfig()
|
317
|
+
cfg = {}
|
318
|
+
cfg['header'] = @header.saveChanges()
|
319
|
+
cfg['body'] = @body.saveChanges()
|
320
|
+
return {self.class.name => cfg}
|
321
|
+
end
|
322
|
+
|
323
|
+
def saveFile(f)
|
324
|
+
@header.saveData(f)
|
325
|
+
@body.saveData(f)
|
326
|
+
end
|
327
|
+
|
328
|
+
def save(filename)
|
329
|
+
raise "Filename expected." if !filename
|
330
|
+
open(filename, "wb:ascii-8bit"){|f|
|
331
|
+
saveFile(f)
|
332
|
+
}
|
333
|
+
open(filename+CFGEXT, "w"){|f|
|
334
|
+
f.write(JSON.pretty_generate(saveConfig()))
|
335
|
+
}
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
339
|
+
end
|