class Metasm::C::Struct

Attributes

pack[RW]

Public Instance Methods

align(parser) click to toggle source
# File metasm/parse_c.rb, line 424
def align(parser) [@members.to_a.map { |m| m.type.align(parser) }.max || 1, (pack || 8)].min end
bitoffsetof(parser, name) click to toggle source

returns the [bitoffset, bitlength] of the field if it is a bitfield this should be added to the offsetof(field)

# File metasm/parse_c.rb, line 479
def bitoffsetof(parser, name)
        raise parser, 'undefined structure' if not members
        update_member_cache(parser) if not fldlist
        return @fldbitoffset[name] if fldbitoffset and @fldbitoffset[name]
        return @fldbitoffset[name.name] if fldbitoffset and name.respond_to?(:name) and @fldbitoffset[name.name]
        return if @fldlist[name] or @members.include?(name)
        raise parser, 'undefined union' if not @members
        raise parser, 'unknown union member' if not findmember(name)

        @members.find { |m|
                m.type.untypedef.kind_of?(Union) and m.type.untypedef.findmember(name)
        }.type.untypedef.bitoffsetof(parser, name)
end
dump_def(scope, r=[CRenderString.new], dep=[]) click to toggle source
Calls superclass method Metasm::C::Union#dump_def
# File metasm/parse_c.rb, line 3733
def dump_def(scope, r=[CRenderString.new], dep=[])
        if pack
                r, dep = super(scope, r, dep)
                r.last <<
                if @pack == 1; (has_attribute('packed') or has_attribute_var('pack')) ? '' : " __attribute__((packed))"
                else has_attribute_var('pack') ? '' : " __attribute__((pack(#@pack)))"
                end
                [r, dep]
        else
                super(scope, r, dep)
        end
end
expand_member_offset(c_parser, off, str) click to toggle source

see Union#expand_member_offset

# File metasm/parse_c.rb, line 558
def expand_member_offset(c_parser, off, str)
        members.to_a.each { |m|
                mo = offsetof(c_parser, m)
                if mo == off or mo + c_parser.sizeof(m) > off
                        if bitoffsetof(c_parser, m)
                                # ignore bitfields
                                str << "+#{off}" if off > 0
                                return self
                        end

                        str << '.' << m.name if m.name
                        if m.type.respond_to?(:expand_member_offset)
                                return m.type.expand_member_offset(c_parser, off-mo, str)
                        else
                                return m.type
                        end
                elsif mo > off
                        break
                end
        }
        # XXX that works only for pointer-style str
        str << "+#{off}" if off > 0
        nil
end
findmember_atoffset(parser, off) click to toggle source

returns the @member element that has offsetof(m) == off

# File metasm/parse_c.rb, line 494
def findmember_atoffset(parser, off)
        return if not members
        update_member_cache(parser) if not fldlist
        if m = @fldoffset.index(off)
                @fldlist[m]
        end
end
offsetof(parser, name) click to toggle source
# File metasm/parse_c.rb, line 426
def offsetof(parser, name)
        raise parser, 'undefined structure' if not members
        update_member_cache(parser) if not fldlist
        return @fldoffset[name] if @fldoffset[name]
        return @fldoffset[name.name] if name.respond_to?(:name) and @fldoffset[name.name]

        # this is almost never reached, only for <struct>.offsetof(anonymoussubstructmembername)
        raise parser, 'unknown structure member' if (name.kind_of?(::String) ?  !findmember(name) : !@members.include?(name))

        indirect = true if name.kind_of?(::String) and not @fldlist[name]

        al = align(parser)
        off = 0
        bit_off = 0
        isz = nil

        @members.each_with_index { |m, i|
                if bits and b = @bits[i]
                        if not isz
                                mal = [m.type.align(parser), al].min
                                off = (off + mal - 1) / mal * mal
                        end
                        isz = parser.sizeof(m)
                        if b == 0 or (bit_off > 0 and bit_off + b > 8*isz)
                                bit_off = 0
                                mal = [m.type.align(parser), al].min
                                off = (off + isz + mal - 1) / mal * mal
                        end
                        break if m.name == name or m == name
                        bit_off += b
                else
                        if isz
                                off += isz
                                bit_off = 0
                                isz = nil
                        end
                        mal = [m.type.align(parser), al].min
                        off = (off + mal - 1) / mal * mal
                        if m.name == name or m == name
                                break
                        elsif indirect and m.type.untypedef.kind_of? Union and m.type.untypedef.findmember(name)
                                off += m.type.untypedef.offsetof(parser, name)
                                break
                        else
                                off += parser.sizeof(m)
                        end
                end
        }
        off
end
parse_members(parser, scope) click to toggle source
Calls superclass method Metasm::C::Union#parse_members
# File metasm/parse_c.rb, line 502
def parse_members(parser, scope)
        super(parser, scope)

        if has_attribute 'packed'
                @pack = 1
        elsif p = has_attribute_var('pack')
                @pack = p[/\d+/].to_i
                raise parser, "illegal struct pack(#{p})" if @pack == 0
        end
end
update_member_cache(parser) click to toggle source

updates the @fldoffset / @fldbitoffset hash storing the offset of members

Calls superclass method Metasm::C::Union#update_member_cache
# File metasm/parse_c.rb, line 514
def update_member_cache(parser)
        super(parser)

        @fldoffset = {}
        @fldbitoffset = {} if fldbitoffset

        al = align(parser)
        off = 0
        bit_off = 0
        isz = nil

        @members.each_with_index { |m, i|
                if bits and b = @bits[i]
                        if not isz
                                mal = [m.type.align(parser), al].min
                                off = (off + mal - 1) / mal * mal
                        end
                        isz = parser.sizeof(m)
                        if b == 0 or (bit_off > 0 and bit_off + b > 8*isz)
                                bit_off = 0
                                mal = [m.type.align(parser), al].min
                                off = (off + isz + mal - 1) / mal * mal
                        end
                        if m.name
                                @fldoffset[m.name] = off
                                @fldbitoffset ||= {}
                                @fldbitoffset[m.name] = [bit_off, b]
                        end
                        bit_off += b
                else
                        if isz
                                off += isz
                                bit_off = 0
                                isz = nil
                        end
                        mal = [m.type.align(parser), al].min
                        off = (off + mal - 1) / mal * mal
                        @fldoffset[m.name] = off if m.name
                        off += parser.sizeof(m)
                end
        }
end