class Metasm::C::AllocCStruct
this maps a C structure from a C parser to a ruby String struct members are accessed through obj obj.fldname is an alias
Attributes
cp[RW]
sizeof[W]
str[RW]
stroff[RW]
Public Class Methods
new(cp, struct, str=nil, stroff=0)
click to toggle source
# File metasm/parse_c.rb, line 2966 def initialize(cp, struct, str=nil, stroff=0) @cp, @struct = cp, struct @str = str || [0].pack('C')*sizeof @stroff = stroff end
Public Instance Methods
[](*a)
click to toggle source
# File metasm/parse_c.rb, line 2976 def [](*a) if @struct.kind_of? C::Array and a.length == 1 and @struct.length and a[0].kind_of? Integer i = a[0] raise "#{i} out of bounds 0...#{@struct.length}" if i < 0 or i >= @struct.length off = @stroff + i*@cp.sizeof(@struct.type) return @cp.decode_c_value(@str, @struct.type, off) end return @str[@stroff..-1][*a] if a.length != 1 a = a.first return @str[@stroff..-1][a] if not a.kind_of? Symbol and not a.kind_of? String and not a.kind_of? C::Variable f = a raise "#{a.inspect} not a member" if not f.kind_of? C::Variable and not f = @struct.findmember(a.to_s, true) a = f.name || f off = @stroff + @struct.offsetof(@cp, a) if bf = @struct.bitoffsetof(@cp, a) ft = C::BaseType.new((bf[0] + bf[1] > 32) ? :__int64 : :__int32) v = @cp.decode_c_value(@str, ft, off) (v >> bf[0]) & ((1 << bf[1])-1) else @cp.decode_c_value(@str, f, off) end end
[]=(*a)
click to toggle source
# File metasm/parse_c.rb, line 3000 def []=(*a) if @struct.kind_of? C::Array and a.length == 2 and @struct.length and a[0].kind_of? Integer i = a[0] raise "#{i} out of bounds 0...#{@struct.length}" if i < 0 or i >= @struct.length off = @stroff + i*@cp.sizeof(@struct.type) val = @cp.encode_c_value(@struct.type, a[1]) @str[off, val.length] = val return end if not a.first.kind_of? Symbol and not a.first.kind_of? String and not a.first.kind_of? C::Variable # patch @str[@stroff..-1] like a string # so we must find the intended start offset, and add @stroff to it if @stroff != 0 case a.first when Range if a.first.begin >= 0 a[0] = ::Range.new(a[0].begin+@stroff, a[0].end+@stroff, a[0].exclude_end?) else raise 'no can do, use positive index' end when Integer if a.first >= 0 a[0] += @stroff else raise 'no can do, use positive index' end else raise 'no can do' end end return @str.send(:'[]=', *a) # XXX *should* work... end a, val = a f = a raise "#{a.inspect} not a struct member" if not f.kind_of? C::Variable and not f = @struct.findmember(a.to_s, true) a = f.name || f val = sizeof if val == :size off = @stroff + @struct.offsetof(@cp, a) if bf = @struct.bitoffsetof(@cp, a) raise "only Integers supported in bitfield #{a}, got #{val.inspect}" if not val.kind_of?(::Integer) # struct { int i:8; }; => size 8 or 32 ? ft = C::BaseType.new((bf[0] + bf[1] > 32) ? :__int64 : :__int32) mask = ((1 << bf[1]) - 1) << bf[0] preval = @cp.decode_c_value(@str, ft, off) val = (preval & ~mask) | ((val << bf[0]) & mask) f = ft end val = @cp.encode_c_value(f, val) @str[off, val.length] = val end
method_missing(on, *a)
click to toggle source
virtual accessors to members struct.foo is aliased to struct, struct.foo = 42 aliased to struct = 42
Calls superclass method
# File metasm/parse_c.rb, line 3056 def method_missing(on, *a) n = on.to_s if n[-1] == ?= send :[]=, n[0...-1], *a else super(on, *a) if not @struct.kind_of?(C::Union) or not @struct.findmember(n, true) send :[], n, *a end end
sizeof()
click to toggle source
# File metasm/parse_c.rb, line 2972 def sizeof @sizeof ||= @cp.sizeof(@struct) end
to_array()
click to toggle source
# File metasm/parse_c.rb, line 3115 def to_array raise NoMethodError, "Not an Array" if not @struct.kind_of?(C::Array) ary = [] @struct.length.times { |i| ary << self[i] } ary end
to_s(off=nil, maxdepth=500)
click to toggle source
# File metasm/parse_c.rb, line 3066 def to_s(off=nil, maxdepth=500) return '{ /* ... */ }' if maxdepth <= 0 str = [''] if @struct.kind_of?(C::Array) str.last << "#{@struct.type} x[#{@struct.length}] = " if not off mlist = (0...@struct.length) fldoff = mlist.inject({}) { |h, i| h.update i => i*@cp.sizeof(@struct.type) } elsif @struct.kind_of?(C::Struct) str.last << "struct #{@struct.name || '_'} x = " if not off @struct.update_member_cache(@cp) if not @struct.fldlist fldoff = @struct.fldoffset mlist = @struct.members.map { |m| m.name || m } else str.last << "union #{@struct.name || '_'} x = " if not off mlist = @struct.members.map { |m| m.name || m } end str.last << '{' mlist.each { |k| if k.kind_of? Variable # anonymous member curoff = off.to_i + @struct.offsetof(@cp, k) val = self[k] k = '?' else curoff = off.to_i + (fldoff ? fldoff[k].to_i : 0) val = self[k] end if val.kind_of?(::Integer) if val >= 0x100 val = '0x%X, // +%x' % [val, curoff] elsif val <= -0x100 val = '-0x%X, // +%x' % [-val, curoff] else val = '%d, // +%x' % [val, curoff] end elsif val.kind_of? AllocCStruct val = val.to_s(curoff, maxdepth-1) elsif not val val = 'NULL, // +%x' % curoff # pointer with NULL value else val = val.to_s.sub(/$/, ', // +%x' % curoff) end val = val.gsub("\n", "\n\t") str << "\t#{k.kind_of?(::Integer) ? "[#{k}]" : ".#{k}"} = #{val}" } str << '}' str.last << (off ? ',' : ';') str.join("\n") end
to_strz()
click to toggle source
# File metasm/parse_c.rb, line 3122 def to_strz raise NoMethodError, "Not an Array" if not @struct.kind_of?(C::Array) a = to_array a[a.index(0)..-1] = [] if a.index(0) a.pack('C*') end