diff --git a/Lua/inject.lua b/Lua/inject.lua index 0acaee1..c6dffea 100644 --- a/Lua/inject.lua +++ b/Lua/inject.lua @@ -1,6 +1,7 @@ require = require "depend" require "boilerplate" require "addrs.init" +require "messages" local assemble = require "inject.lips" local injection_points = { @@ -67,12 +68,13 @@ function inject(fn) -- set up a header to handle calling our function and the original local header = header:format(ow_before_addr) - local inject_words = {} + local inject_bytes = {} local length = 0 - local function add_word(line) - -- takes assembled code, up to 4 bytes at a time, as hex strings + local function add_word(pos, line) length = length + #line/2 - table.insert(inject_words, tonumber(line, 16)) + dprint(("%08X"):format(pos), line) + pos = pos % 0x80000000 + inject_bytes[pos] = tonumber(line, 16) end -- offset assembly labels so they work properly, and assemble! @@ -81,14 +83,15 @@ function inject(fn) assemble(asm_path, add_word, {unsafe=true, offset=true_offset + length}) printf("length: %i words", length/4) - if #inject_words > inject_maxlen then + if #inject_bytes > inject_maxlen then print("Assembly too large!") return end - for i, v in ipairs(inject_words) do - W4(inject_addr + (i - 1)*4, v) + for pos, val in pairs(inject_bytes) do + W1(pos, val) end + print_deferred() -- finally, write our new jump over the original printf('%08X: %08X', ow_addr, ow_after) diff --git a/Lua/inject/lips.lua b/Lua/inject/lips.lua index 7bbf918..1ca76c9 100644 --- a/Lua/inject/lips.lua +++ b/Lua/inject/lips.lua @@ -473,9 +473,7 @@ function Dumper:init(writer, fn, options) self.options = options or {} self.labels = {} self.commands = {} - self.buff = '' - self.pos = 0 - self.size = 0 + self.pos = options.offset or 0 self.lastcommand = nil end @@ -586,7 +584,7 @@ function Lexer:read_number() return self:read_hex() elseif self.chr == '0' and self.chr2:find('%d') then self:nextc() - return self:read_octal_number() + return self:read_octal() else return self:read_decimal() end @@ -670,13 +668,11 @@ end function Lexer:lex_string(yield) -- TODO: support escaping if self.chr ~= '"' then - print(self.chr, self.ord) self:error("expected opening double quote") end self:nextc() local buff = self:read_chars('[^"\n]') if self.chr ~= '"' then - print(self.chr) self:error("expected closing double quote") end self:nextc() @@ -1347,15 +1343,11 @@ function Parser:parse(asm) end function Dumper:error(msg) - --error(string.format('%s:%d: Dumper Error: %s', '(code)', self.pos, msg), 2) error(string.format('%s:%d: Error: %s', self.fn, self.line, msg), 2) end function Dumper:advance(by) self.pos = self.pos + by - if self.pos > self.size then - self.size = self.pos - end end function Dumper:push_instruction(t) @@ -1457,8 +1449,7 @@ function Dumper:desym(tok) if label == nil then self:error('undefined label') end - local offset = self.options.offset or 0 - return label + offset + return label elseif tok[1] == 'LABELREL' then local label = self.labels[tok[2]] if label == nil then @@ -1540,16 +1531,9 @@ function Dumper:valvar(tok, bits) end function Dumper:write(t) - -- this is gonna be really slow, but eh, optimization comes last - -- should really use a sparse table and fill in the string later for _, b in ipairs(t) do - if self.pos >= self.size then - error('Internal Error: pos out of range; size too small', 1) - end local s = ('%02X'):format(b) - local left = self.buff:sub(1, self.pos*2) - local right = self.buff:sub(self.pos*2 + 3) - self.buff = left..s..right + self.writer(self.pos, s) self.pos = self.pos + 1 end end @@ -1583,12 +1567,7 @@ function Dumper:dump_instruction(t) end function Dumper:dump() - self.pos = 0 - self.buff = '' - for i=1,self.size do - self.buff = self.buff..'00' - end - + self.pos = self.options.offset or 0 for i, t in ipairs(self.commands) do if t.line == nil then error('Internal Error: no line number available') @@ -1617,10 +1596,6 @@ function Dumper:dump() error('Internal Error: unknown command', 1) end end - - for i=1, self.size*2 - 1, 8 do - self.writer(self.buff:sub(i, i + 7)) - end end function assembler.assemble(fn_or_asm, writer, options)