mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-28 20:43:45 +08:00
coffcode.h handle_COMDAT tidy
I started down the path of attempting to fix https://sourceware.org/pipermail/binutils/2023-April/127263.html but decided after a while that I didn't want to mess with this code.. This patch is a just a few things that I thought worth doing, the main one being reporting of errors up the call chain. The while loop to for loop change is shamelessly stolen from Oleg. * coffcode.h (handle_COMDAT): Return bool. Make sec_flags a flagword*, and adjust to suit. Replace while loop with for loop. Check isym.n_numaux before reading aux entries. Alloc coff_comdat_info and name in one call to bfd_alloc. Remove goto breakloop. (styp_to_sec_flags): Adjust handle_COMDAT call.
This commit is contained in:
parent
880853ed94
commit
cb3f0ff479
103
bfd/coffcode.h
103
bfd/coffcode.h
@ -852,9 +852,9 @@ styp_to_sec_flags (bfd *abfd,
|
|||||||
|
|
||||||
#else /* COFF_WITH_PE */
|
#else /* COFF_WITH_PE */
|
||||||
|
|
||||||
static flagword
|
static bool
|
||||||
handle_COMDAT (bfd * abfd,
|
handle_COMDAT (bfd * abfd,
|
||||||
flagword sec_flags,
|
flagword *sec_flags,
|
||||||
void * hdr,
|
void * hdr,
|
||||||
const char *name,
|
const char *name,
|
||||||
asection *section)
|
asection *section)
|
||||||
@ -864,7 +864,7 @@ handle_COMDAT (bfd * abfd,
|
|||||||
int seen_state = 0;
|
int seen_state = 0;
|
||||||
char *target_name = NULL;
|
char *target_name = NULL;
|
||||||
|
|
||||||
sec_flags |= SEC_LINK_ONCE;
|
*sec_flags |= SEC_LINK_ONCE;
|
||||||
|
|
||||||
/* Unfortunately, the PE format stores essential information in
|
/* Unfortunately, the PE format stores essential information in
|
||||||
the symbol table, of all places. We need to extract that
|
the symbol table, of all places. We need to extract that
|
||||||
@ -884,18 +884,19 @@ handle_COMDAT (bfd * abfd,
|
|||||||
rather messy. */
|
rather messy. */
|
||||||
|
|
||||||
if (! _bfd_coff_get_external_symbols (abfd))
|
if (! _bfd_coff_get_external_symbols (abfd))
|
||||||
return sec_flags;
|
return true;
|
||||||
|
|
||||||
esymstart = esym = (bfd_byte *) obj_coff_external_syms (abfd);
|
esymstart = esym = (bfd_byte *) obj_coff_external_syms (abfd);
|
||||||
esymend = esym + obj_raw_syment_count (abfd) * bfd_coff_symesz (abfd);
|
esymend = esym + obj_raw_syment_count (abfd) * bfd_coff_symesz (abfd);
|
||||||
|
|
||||||
while (esym < esymend)
|
for (struct internal_syment isym;
|
||||||
|
esym < esymend;
|
||||||
|
esym += (isym.n_numaux + 1) * bfd_coff_symesz (abfd))
|
||||||
{
|
{
|
||||||
struct internal_syment isym;
|
|
||||||
char buf[SYMNMLEN + 1];
|
char buf[SYMNMLEN + 1];
|
||||||
const char *symname;
|
const char *symname;
|
||||||
|
|
||||||
bfd_coff_swap_sym_in (abfd, esym, & isym);
|
bfd_coff_swap_sym_in (abfd, esym, &isym);
|
||||||
|
|
||||||
BFD_ASSERT (sizeof (internal_s->s_name) <= SYMNMLEN);
|
BFD_ASSERT (sizeof (internal_s->s_name) <= SYMNMLEN);
|
||||||
|
|
||||||
@ -933,7 +934,7 @@ handle_COMDAT (bfd * abfd,
|
|||||||
{
|
{
|
||||||
_bfd_error_handler (_("%pB: unable to load COMDAT section name"),
|
_bfd_error_handler (_("%pB: unable to load COMDAT section name"),
|
||||||
abfd);
|
abfd);
|
||||||
break;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (seen_state)
|
switch (seen_state)
|
||||||
@ -968,7 +969,7 @@ handle_COMDAT (bfd * abfd,
|
|||||||
cf PR 21781. */
|
cf PR 21781. */
|
||||||
_bfd_error_handler (_("%pB: error: unexpected symbol '%s' in COMDAT section"),
|
_bfd_error_handler (_("%pB: error: unexpected symbol '%s' in COMDAT section"),
|
||||||
abfd, symname);
|
abfd, symname);
|
||||||
goto breakloop;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME LATER: MSVC generates section names
|
/* FIXME LATER: MSVC generates section names
|
||||||
@ -982,8 +983,21 @@ handle_COMDAT (bfd * abfd,
|
|||||||
" does not match section name '%s'"),
|
" does not match section name '%s'"),
|
||||||
abfd, symname, name);
|
abfd, symname, name);
|
||||||
|
|
||||||
|
/* This is the section symbol. */
|
||||||
seen_state = 1;
|
seen_state = 1;
|
||||||
|
target_name = strchr (name, '$');
|
||||||
|
if (target_name != NULL)
|
||||||
|
{
|
||||||
|
/* Gas mode. */
|
||||||
|
seen_state = 2;
|
||||||
|
/* Skip the `$'. */
|
||||||
|
target_name += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isym.n_numaux == 0)
|
||||||
|
aux.x_scn.x_comdat = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
/* PR 17512: file: e2cfe54f. */
|
/* PR 17512: file: e2cfe54f. */
|
||||||
if (esym + bfd_coff_symesz (abfd) >= esymend)
|
if (esym + bfd_coff_symesz (abfd) >= esymend)
|
||||||
{
|
{
|
||||||
@ -993,18 +1007,9 @@ handle_COMDAT (bfd * abfd,
|
|||||||
abfd, symname);
|
abfd, symname);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
/* This is the section symbol. */
|
bfd_coff_swap_aux_in (abfd, esym + bfd_coff_symesz (abfd),
|
||||||
bfd_coff_swap_aux_in (abfd, (esym + bfd_coff_symesz (abfd)),
|
|
||||||
isym.n_type, isym.n_sclass,
|
isym.n_type, isym.n_sclass,
|
||||||
0, isym.n_numaux, & aux);
|
0, isym.n_numaux, &aux);
|
||||||
|
|
||||||
target_name = strchr (name, '$');
|
|
||||||
if (target_name != NULL)
|
|
||||||
{
|
|
||||||
/* Gas mode. */
|
|
||||||
seen_state = 2;
|
|
||||||
/* Skip the `$'. */
|
|
||||||
target_name += 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Microsoft uses NODUPLICATES and
|
/* FIXME: Microsoft uses NODUPLICATES and
|
||||||
@ -1027,23 +1032,23 @@ handle_COMDAT (bfd * abfd,
|
|||||||
{
|
{
|
||||||
case IMAGE_COMDAT_SELECT_NODUPLICATES:
|
case IMAGE_COMDAT_SELECT_NODUPLICATES:
|
||||||
#ifdef STRICT_PE_FORMAT
|
#ifdef STRICT_PE_FORMAT
|
||||||
sec_flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
|
*sec_flags |= SEC_LINK_DUPLICATES_ONE_ONLY;
|
||||||
#else
|
#else
|
||||||
sec_flags &= ~SEC_LINK_ONCE;
|
*sec_flags &= ~SEC_LINK_ONCE;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IMAGE_COMDAT_SELECT_ANY:
|
case IMAGE_COMDAT_SELECT_ANY:
|
||||||
sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
|
*sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IMAGE_COMDAT_SELECT_SAME_SIZE:
|
case IMAGE_COMDAT_SELECT_SAME_SIZE:
|
||||||
sec_flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
|
*sec_flags |= SEC_LINK_DUPLICATES_SAME_SIZE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IMAGE_COMDAT_SELECT_EXACT_MATCH:
|
case IMAGE_COMDAT_SELECT_EXACT_MATCH:
|
||||||
/* Not yet fully implemented ??? */
|
/* Not yet fully implemented ??? */
|
||||||
sec_flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
|
*sec_flags |= SEC_LINK_DUPLICATES_SAME_CONTENTS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* debug$S gets this case; other
|
/* debug$S gets this case; other
|
||||||
@ -1056,16 +1061,16 @@ handle_COMDAT (bfd * abfd,
|
|||||||
case IMAGE_COMDAT_SELECT_ASSOCIATIVE:
|
case IMAGE_COMDAT_SELECT_ASSOCIATIVE:
|
||||||
#ifdef STRICT_PE_FORMAT
|
#ifdef STRICT_PE_FORMAT
|
||||||
/* FIXME: This is not currently implemented. */
|
/* FIXME: This is not currently implemented. */
|
||||||
sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
|
*sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
|
||||||
#else
|
#else
|
||||||
sec_flags &= ~SEC_LINK_ONCE;
|
*sec_flags &= ~SEC_LINK_ONCE;
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: /* 0 means "no symbol" */
|
default: /* 0 means "no symbol" */
|
||||||
/* debug$F gets this case; other
|
/* debug$F gets this case; other
|
||||||
implications ??? */
|
implications ??? */
|
||||||
sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
|
*sec_flags |= SEC_LINK_DUPLICATES_DISCARD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1082,7 +1087,6 @@ handle_COMDAT (bfd * abfd,
|
|||||||
symname + (TARGET_UNDERSCORE ? 1 : 0)) != 0)
|
symname + (TARGET_UNDERSCORE ? 1 : 0)) != 0)
|
||||||
{
|
{
|
||||||
/* Not the name we're looking for */
|
/* Not the name we're looking for */
|
||||||
esym += (isym.n_numaux + 1) * bfd_coff_symesz (abfd);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
@ -1090,42 +1094,30 @@ handle_COMDAT (bfd * abfd,
|
|||||||
/* MSVC mode: the lexically second symbol (or
|
/* MSVC mode: the lexically second symbol (or
|
||||||
drop through from the above). */
|
drop through from the above). */
|
||||||
{
|
{
|
||||||
char *newname;
|
|
||||||
size_t amt;
|
|
||||||
|
|
||||||
/* This must the second symbol with the
|
/* This must the second symbol with the
|
||||||
section #. It is the actual symbol name.
|
section #. It is the actual symbol name.
|
||||||
Intel puts the two adjacent, but Alpha (at
|
Intel puts the two adjacent, but Alpha (at
|
||||||
least) spreads them out. */
|
least) spreads them out. */
|
||||||
|
|
||||||
amt = sizeof (struct coff_comdat_info);
|
struct coff_comdat_info *comdat;
|
||||||
coff_section_data (abfd, section)->comdat
|
size_t len = strlen (symname) + 1;
|
||||||
= (struct coff_comdat_info *) bfd_alloc (abfd, amt);
|
|
||||||
if (coff_section_data (abfd, section)->comdat == NULL)
|
|
||||||
abort ();
|
|
||||||
|
|
||||||
coff_section_data (abfd, section)->comdat->symbol =
|
comdat = bfd_alloc (abfd, sizeof (*comdat) + len);
|
||||||
(esym - esymstart) / bfd_coff_symesz (abfd);
|
if (comdat == NULL)
|
||||||
|
return false;
|
||||||
|
|
||||||
amt = strlen (symname) + 1;
|
coff_section_data (abfd, section)->comdat = comdat;
|
||||||
newname = (char *) bfd_alloc (abfd, amt);
|
comdat->symbol = (esym - esymstart) / bfd_coff_symesz (abfd);
|
||||||
if (newname == NULL)
|
char *newname = (char *) (comdat + 1);
|
||||||
abort ();
|
comdat->name = newname;
|
||||||
|
memcpy (newname, symname, len);
|
||||||
strcpy (newname, symname);
|
return true;
|
||||||
coff_section_data (abfd, section)->comdat->name
|
}
|
||||||
= newname;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
goto breakloop;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
esym += (isym.n_numaux + 1) * bfd_coff_symesz (abfd);
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
breakloop:
|
|
||||||
return sec_flags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1276,7 +1268,8 @@ styp_to_sec_flags (bfd *abfd,
|
|||||||
break;
|
break;
|
||||||
case IMAGE_SCN_LNK_COMDAT:
|
case IMAGE_SCN_LNK_COMDAT:
|
||||||
/* COMDAT gets very special treatment. */
|
/* COMDAT gets very special treatment. */
|
||||||
sec_flags = handle_COMDAT (abfd, sec_flags, hdr, name, section);
|
if (!handle_COMDAT (abfd, &sec_flags, hdr, name, section))
|
||||||
|
result = false;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
/* Silently ignore for now. */
|
/* Silently ignore for now. */
|
||||||
|
Loading…
Reference in New Issue
Block a user