class SMC::CoWData

a copy-on-write copy of dasm address space (continuous segment only)

Attributes

data[RW]
startaddr[RW]

Public Class Methods

new(dasm) click to toggle source
# File samples/dasm-plugins/selfmodify.rb, line 17
def initialize(dasm)
        @dasm = dasm
        @startaddr = 0
        @data = ''
end

Public Instance Methods

[](addr, len) click to toggle source

return a substring, either from the local cache or from dasm handles overlap

# File samples/dasm-plugins/selfmodify.rb, line 25
def [](addr, len)
        if @data.empty?
                s, e = @dasm.get_section_at(addr)
                return if not s
                return s.read(len)
        end
        raddr = addr - @base
        rstart = @startaddr - @base
        if raddr >= rstart and raddr+len <= rstart+@data.length
                @data[0, raddr+len-rstart]
        else
                s, e = @dasm.get_section_at(addr)
                return if not s
                obuf = s.read(len)
                len = obuf.length
                if raddr < rstart and raddr+len > rstart
                        olen = [raddr+len-rstart, @data.length].min
                        obuf[rstart-raddr, olen] = @data[0, olen]
                elsif raddr < rstart+@data.length and raddr+len > rstart+@data.length
                        obuf[0, rstart+@data.length-raddr] = @data[raddr-rstart, rstart+@data.length-raddr]
                end
                obuf
        end
end
[]=(addr, len, newdata) click to toggle source

set a substring value in the cache

# File samples/dasm-plugins/selfmodify.rb, line 51
def []=(addr, len, newdata)
        raise 'len mismatch' if len != newdata.length
        if @data.empty?
                @base = @startaddr = addr
                @data << newdata
                return
        end
        raddr = addr - @base
        rstart = @startaddr - @base
        if raddr+newdata.length < rstart
                s, e = @dasm.get_section_at(addr)
                raise if not s
                obuf = s.read(rstart-(raddr+newdata.length))
                raise if obuf.length != rstart-(raddr+newdata.length)
                newdata += obuf
        elsif raddr > rstart+@data.length
                s, e = @dasm.get_section_at(@startaddr+@data.length)
                raise if not s
                obuf = s.read(raddr-(rstart+@data.length))
                raise if obuf.length != raddr-(rstart+@data.length)
                @data += obuf
        end
        if raddr < rstart
                @data = newdata + @data[raddr+newdata.length-rstart..-1].to_s
                @startaddr = addr
        else
                @data[raddr-rstart, newdata.length] = newdata
        end
end