# File metasm/parse_c.rb, line 413 def align(parser) [@members.to_a.map { |m| m.type.align(parser) }.max || 1, (pack || 8)].min end
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 468 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
# File metasm/parse_c.rb, line 3684 def dump_def(scope, r=[''], 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
see Metasm::C::Union#expand_member_offset
# File metasm/parse_c.rb, line 547 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
returns the @member element that has offsetof(m) == off
# File metasm/parse_c.rb, line 483 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
# File metasm/parse_c.rb, line 415 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
# File metasm/parse_c.rb, line 491 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
updates the @fldoffset / @fldbitoffset hash storing the offset of members
# File metasm/parse_c.rb, line 503 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