From ec0ef80e9f48ae59958cfe0ff8a998881833ca12 Mon Sep 17 00:00:00 2001 From: DJ Delorie Date: Tue, 11 May 1999 21:05:44 +0000 Subject: [PATCH] * ecoff.c (_bfd_ecoff_write_armap): give the symtab element a reasonable mode until "ar x" is smart enough to skip it (fixes gcc/libgcc.a builds on mips-ecoff targets * coffcode.h (styp_to_sec_flags): Explain how COMDATs are supposed to work. Hack to support MS import libraries, which use different COMDAT types than GNU. (coff_slurp_symbol_table): C_SECTION symbols are local; they refer to implied zero-length sections (see peicode below) * coffgen.c (coff_get_normalized_symtab): Properly read long MS filename symbols, which use one *or more* auxents. * coffswap.h (coff_swap_aux_in): ditto * peicode.h (coff_swap_sym_in): Build the implied zero-length sections --- bfd/ChangeLog | 17 +++++++++++++++++ bfd/coffcode.h | 28 ++++++++++++++++++++++++++++ bfd/coffgen.c | 16 +++++++++++++--- bfd/coffswap.h | 11 ++++++++++- bfd/ecoff.c | 7 +++++++ bfd/peicode.h | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 125 insertions(+), 4 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index ff6e0058270..26fe092678f 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,20 @@ +1999-05-10 DJ Delorie + + * ecoff.c (_bfd_ecoff_write_armap): give the symtab element a + reasonable mode until "ar x" is smart enough to skip it (fixes + gcc/libgcc.a builds on mips-ecoff targets + + * coffcode.h (styp_to_sec_flags): Explain how COMDATs are supposed + to work. Hack to support MS import libraries, which use different + COMDAT types than GNU. + (coff_slurp_symbol_table): C_SECTION symbols are local; they refer + to implied zero-length sections (see peicode below) + * coffgen.c (coff_get_normalized_symtab): Properly read long MS + filename symbols, which use one *or more* auxents. + * coffswap.h (coff_swap_aux_in): ditto + * peicode.h (coff_swap_sym_in): Build the implied zero-length + sections + Tue May 11 15:51:58 1999 Jeffrey A Law (law@cygnus.com) * elf32-v850.c (v850_elf_howto_table): Make partial_inplace false diff --git a/bfd/coffcode.h b/bfd/coffcode.h index 383719c00c9..bee6b666e47 100644 --- a/bfd/coffcode.h +++ b/bfd/coffcode.h @@ -588,6 +588,12 @@ styp_to_sec_flags (abfd, hdr, name) can't call slurp_symtab, because the linker doesn't want the swapped symbols. */ + /* COMDAT sections are special. The first symbol is the section + symbol, which tells what kind of COMDAT section it is. The + *second* symbol is the "comdat symbol" - the one with the + unique name. GNU uses the section symbol for the unique + name; MS uses ".text" for every comdat section. Sigh. - DJ */ + if (_bfd_coff_get_external_symbols (abfd)) { bfd_byte *esym, *esymend; @@ -629,10 +635,23 @@ styp_to_sec_flags (abfd, hdr, name) isym.n_type, isym.n_sclass, 0, isym.n_numaux, (PTR) &aux); + /* FIXME: Microsoft uses NODUPLICATES and + ASSOCIATIVE, but gnu uses ANY and SAME_SIZE. + Unfortunately, gnu doesn't do the comdat + symbols right. So, until we can fix it to do + the right thing, we are temporarily disabling + comdats for the MS types (they're used in + DLLs and C++, but we don't support *their* + C++ libraries anyway - DJ */ + switch (aux.x_scn.x_comdat) { case IMAGE_COMDAT_SELECT_NODUPLICATES: +#if 0 sec_flags |= SEC_LINK_DUPLICATES_ONE_ONLY; +#else + sec_flags &= ~SEC_LINK_ONCE; +#endif break; default: @@ -649,8 +668,12 @@ styp_to_sec_flags (abfd, hdr, name) break; case IMAGE_COMDAT_SELECT_ASSOCIATIVE: +#if 0 /* FIXME: This is not currently implemented. */ sec_flags |= SEC_LINK_DUPLICATES_DISCARD; +#else + sec_flags &= ~SEC_LINK_ONCE; +#endif break; } @@ -3581,6 +3604,11 @@ coff_slurp_symbol_table (abfd) #ifdef COFF_WITH_PE if (src->u.syment.n_sclass == C_NT_WEAK) dst->symbol.flags = BSF_WEAK; + if (src->u.syment.n_sclass == C_SECTION + && src->u.syment.n_scnum > 0) + { + dst->symbol.flags = BSF_LOCAL; + } #endif if (src->u.syment.n_sclass == C_WEAKEXT) diff --git a/bfd/coffgen.c b/bfd/coffgen.c index df413833bd3..a06ed663b3d 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -1747,9 +1747,19 @@ coff_get_normalized_symtab (abfd) else { /* ordinary short filename, put into memory anyway */ - internal_ptr->u.syment._n._n_n._n_offset = (long) - copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname, - FILNMLEN); + if (internal_ptr->u.syment.n_numaux > 1 + && coff_data (abfd)->pe) + { + internal_ptr->u.syment._n._n_n._n_offset = (long) + copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname, + internal_ptr->u.syment.n_numaux * symesz); + } + else + { + internal_ptr->u.syment._n._n_n._n_offset = (long) + copy_name (abfd, (internal_ptr + 1)->u.auxent.x_file.x_fname, + FILNMLEN); + } } } else diff --git a/bfd/coffswap.h b/bfd/coffswap.h index ae30a5d966f..9bc180f4de8 100644 --- a/bfd/coffswap.h +++ b/bfd/coffswap.h @@ -422,7 +422,16 @@ coff_swap_aux_in (abfd, ext1, type, class, indx, numaux, in1) #if FILNMLEN != E_FILNMLEN -> Error, we need to cope with truncating or extending FILNMLEN!; #else - memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN); + if (numaux > 1) + { + if (indx == 0) + memcpy (in->x_file.x_fname, ext->x_file.x_fname, + numaux * sizeof (AUXENT)); + } + else + { + memcpy (in->x_file.x_fname, ext->x_file.x_fname, FILNMLEN); + } #endif } goto end; diff --git a/bfd/ecoff.c b/bfd/ecoff.c index d5c6f85a717..32a2309e941 100644 --- a/bfd/ecoff.c +++ b/bfd/ecoff.c @@ -3181,7 +3181,14 @@ _bfd_ecoff_write_armap (abfd, elength, map, orl_count, stridx) armap. */ hdr.ar_uid[0] = '0'; hdr.ar_gid[0] = '0'; +#if 0 hdr.ar_mode[0] = '0'; +#else + /* Building gcc ends up extracting the armap as a file - twice. */ + hdr.ar_mode[0] = '6'; + hdr.ar_mode[1] = '4'; + hdr.ar_mode[2] = '4'; +#endif sprintf (hdr.ar_size, "%-10d", (int) mapsize); diff --git a/bfd/peicode.h b/bfd/peicode.h index 79d16e5abe9..f15e0ec28ba 100644 --- a/bfd/peicode.h +++ b/bfd/peicode.h @@ -504,6 +504,7 @@ coff_swap_sym_in (abfd, ext1, in1) { in->n_value = 0x0; +#if 0 /* FIXME: This is clearly wrong. The problem seems to be that undefined C_SECTION symbols appear in the first object of a MS generated .lib file, and the symbols are not defined @@ -518,6 +519,55 @@ coff_swap_sym_in (abfd, ext1, in1) /* in->n_scnum = 3; */ /* else */ /* in->n_scnum = 2; */ +#else + /* Create synthetic empty sections as needed. DJ */ + if (in->n_scnum == 0) + { + asection *sec; + for (sec=abfd->sections; sec; sec=sec->next) + { + if (strcmp (sec->name, in->n_name) == 0) + { + in->n_scnum = sec->target_index; + break; + } + } + } + if (in->n_scnum == 0) + { + int unused_section_number = 0; + asection *sec; + char *name; + for (sec=abfd->sections; sec; sec=sec->next) + if (unused_section_number <= sec->target_index) + unused_section_number = sec->target_index+1; + + name = bfd_alloc (abfd, strlen (in->n_name) + 10); + if (name == NULL) + return; + strcpy (name, in->n_name); + sec = bfd_make_section_anyway (abfd, name); + + sec->vma = 0; + sec->lma = 0; + sec->_cooked_size = 0; + sec->_raw_size = 0; + sec->filepos = 0; + sec->rel_filepos = 0; + sec->reloc_count = 0; + sec->line_filepos = 0; + sec->lineno_count = 0; + sec->userdata = NULL; + sec->next = (asection *) NULL; + sec->flags = 0; + sec->alignment_power = 2; + sec->flags = SEC_HAS_CONTENTS | SEC_ALLOC | SEC_DATA | SEC_LOAD; + + sec->target_index = unused_section_number; + + in->n_scnum = unused_section_number; + } +#endif } #ifdef coff_swap_sym_in_hook -- 2.34.1