resedit 1.7.3 → 1.8
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 +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
|