$OpenBSD: patch-binutils_rdcoff_c,v 1.3 2010/06/27 20:58:10 ckuethe Exp $ --- binutils/rdcoff.c.orig Sat Jun 26 11:22:44 2010 +++ binutils/rdcoff.c Sat Jun 26 11:31:17 2010 @@ -82,6 +82,9 @@ struct coff_types struct coff_slots *slots; /* Basic types. */ debug_type basic[T_MAX + 1]; + /* Some general information, kept here for convenience. */ + size_t intsize; /* sizeof (int) */ + size_t doublesize; /* sizeof (double) */ }; static debug_type *coff_get_slot (struct coff_types *, int); @@ -101,6 +104,7 @@ static bfd_boolean parse_coff_symbol (bfd *, struct coff_types *, asymbol *, long, struct internal_syment *, void *, debug_type, bfd_boolean); static bfd_boolean external_coff_symbol_p (int sym_class); +static bfd_vma coff_convert_register (bfd *, bfd_vma); /* Return the slot for a type. */ @@ -271,8 +275,7 @@ parse_coff_base_type (bfd *abfd, struct coff_symbols * break; case T_INT: - /* FIXME: Perhaps the size should depend upon the architecture. */ - ret = debug_make_int_type (dhandle, 4, FALSE); + ret = debug_make_int_type (dhandle, types->intsize, FALSE); name = "int"; break; @@ -287,7 +290,7 @@ parse_coff_base_type (bfd *abfd, struct coff_symbols * break; case T_DOUBLE: - ret = debug_make_float_type (dhandle, 8); + ret = debug_make_float_type (dhandle, types->doublesize); name = "double"; break; @@ -307,7 +310,7 @@ parse_coff_base_type (bfd *abfd, struct coff_symbols * break; case T_UINT: - ret = debug_make_int_type (dhandle, 4, TRUE); + ret = debug_make_int_type (dhandle, types->intsize, TRUE); name = "unsigned int"; break; @@ -565,6 +568,8 @@ parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct case C_WEAKEXT: case C_EXT: + /* AVR COFF abuses C_EXTDEF */ + case C_EXTDEF: if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, DEBUG_GLOBAL, bfd_asymbol_value (sym))) return FALSE; @@ -580,9 +585,9 @@ parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct break; case C_REG: - /* FIXME: We may need to convert the register number. */ if (! debug_record_variable (dhandle, bfd_asymbol_name (sym), type, - DEBUG_REGISTER, bfd_asymbol_value (sym))) + DEBUG_REGISTER, + coff_convert_register (abfd, bfd_asymbol_value (sym)))) return FALSE; break; @@ -596,9 +601,9 @@ parse_coff_symbol (bfd *abfd ATTRIBUTE_UNUSED, struct break; case C_REGPARM: - /* FIXME: We may need to convert the register number. */ if (! debug_record_parameter (dhandle, bfd_asymbol_name (sym), type, - DEBUG_PARM_REG, bfd_asymbol_value (sym))) + DEBUG_PARM_REG, + coff_convert_register (abfd, bfd_asymbol_value (sym)))) return FALSE; break; @@ -648,6 +653,28 @@ external_coff_symbol_p (int sym_class) return FALSE; } +static bfd_vma +coff_convert_register (abfd, val) + bfd *abfd; + bfd_vma val; +{ + + switch (bfd_get_arch (abfd)) + { + case bfd_arch_avr: + /* AVR COFF wants to describe up to four registers by the four + bytes of the 32-bit value. Unused bytes are filled with + 0xff. In theory, this would allow for non-contiguous + register usage to hold a single value, but hopefully, no + compiler is going to use that feature. We could not handle + it anyway. */ + return val & 0xff; + + default: + return val; + } +} + /* This is the main routine. It looks through all the symbols and handles them. */ @@ -674,7 +701,18 @@ parse_coff (bfd *abfd, asymbol **syms, long symcount, types.slots = NULL; for (i = 0; i <= T_MAX; i++) types.basic[i] = DEBUG_TYPE_NULL; + switch (bfd_get_arch (abfd)) + { + case bfd_arch_avr: + types.intsize = 2; + types.doublesize = 4; + break; + default: + types.intsize = 4; + types.doublesize = 8; + } + next_c_file = -1; fnname = NULL; fnclass = 0; @@ -734,7 +772,6 @@ parse_coff (bfd *abfd, asymbol **syms, long symcount, switch (syment.n_sclass) { case C_EFCN: - case C_EXTDEF: case C_ULABEL: case C_USTATIC: case C_LINE: @@ -757,6 +794,8 @@ parse_coff (bfd *abfd, asymbol **syms, long symcount, /* Fall through. */ case C_WEAKEXT: case C_EXT: + /* AVR COFF abuses C_EXTDEF for C_EXT */ + case C_EXTDEF: if (ISFCN (syment.n_type)) { fnname = name;