evaluate.c | 2 +- symbol.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/evaluate.c b/evaluate.c index 03992d03ae1d..78150f83a19f 100644 --- a/evaluate.c +++ b/evaluate.c @@ -1898,7 +1898,7 @@ static struct symbol *find_identifier(struct ident *ident, struct symbol_list *_ sub = find_identifier(ident, ctype->symbol_list, offset); if (!sub) continue; - *offset += sym->offset; + *offset = sym->offset; return sub; } } diff --git a/symbol.c b/symbol.c index a2731348a011..32af64050a64 100644 --- a/symbol.c +++ b/symbol.c @@ -116,6 +116,18 @@ static int bitfield_base_size(struct symbol *sym) return sym->bit_size; } +static void update_symbol_offsets(struct symbol *sym, unsigned int offset) +{ + struct symbol *field; + + if (sym->type != SYM_STRUCT && sym->type != SYM_UNION) + return; + FOR_EACH_PTR(sym->symbol_list, field) { + field->offset += offset; + update_symbol_offsets(field, offset); + } END_FOR_EACH_PTR(field); +} + /* * Structures are a bit more interesting to lay out */ @@ -174,6 +186,10 @@ static void lay_out_struct(struct symbol *sym, struct struct_union_info *info) bit_size = (bit_size + align_bit_mask) & ~align_bit_mask; sym->offset = bits_to_bytes(bit_size); + /* If it's an unnamed struct or union, update the offsets of the sub-members */ + if (sym->offset && !sym->ident) + update_symbol_offsets(sym, sym->offset); + info->bit_size = bit_size + base_size; // warning (sym->pos, "regular: offset=%d", sym->offset); }