diff options
Diffstat (limited to 'bfd/coffgen.c')
-rw-r--r-- | bfd/coffgen.c | 33 |
1 files changed, 32 insertions, 1 deletions
diff --git a/bfd/coffgen.c b/bfd/coffgen.c index f87e54f..c1811cb 100644 --- a/bfd/coffgen.c +++ b/bfd/coffgen.c @@ -42,7 +42,9 @@ #include "libbfd.h" #include "coff/internal.h" #include "libcoff.h" +#include "elf-bfd.h" #include "hashtab.h" +#include "safe-ctype.h" /* Extract a long section name at STRINDEX and copy it to the bfd objstack. Return NULL in case of error. */ @@ -1270,9 +1272,24 @@ coff_write_alien_symbol (bfd *abfd, if (c != (coff_symbol_type *) NULL) native->u.syment.n_flags = bfd_asymbol_bfd (&c->symbol)->flags; } + + const elf_symbol_type *elfsym = elf_symbol_from (symbol); + if (elfsym + && (symbol->flags & BSF_FUNCTION) + && elfsym->internal_elf_sym.st_size) + { + /* coff_data (abfd)->local_n_btshft is what ought to be used here, + just that it's set only when reading in COFF objects. */ + native->u.syment.n_type = DT_FCN << 4; + native->u.syment.n_numaux = 1; + native[1].u.auxent.x_sym.x_misc.x_fsize + = elfsym->internal_elf_sym.st_size; + /* FIXME .u.auxent.x_sym.x_fcnary.x_fcn.x_endndx would better also + be set, which would require updating the field once the next + function is seen. */ + } } - native->u.syment.n_type = 0; if (symbol->flags & BSF_FILE) native->u.syment.n_sclass = C_FILE; else if (symbol->flags & BSF_LOCAL) @@ -3104,6 +3121,19 @@ coff_gc_sweep_symbol (struct coff_link_hash_entry *h, typedef bool (*gc_sweep_hook_fn) (bfd *, struct bfd_link_info *, asection *, const struct internal_reloc *); +static inline bool +is_subsection (const char *str, const char *prefix) +{ + size_t n = strlen (prefix); + if (strncmp (str, prefix, n) != 0) + return false; + if (str[n] == 0) + return true; + else if (str[n] != '$') + return false; + return ISDIGIT (str[n + 1]) && str[n + 2] == 0; +} + static bool coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) { @@ -3125,6 +3155,7 @@ coff_gc_sweep (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info *info) else if (startswith (o->name, ".idata") || startswith (o->name, ".pdata") || startswith (o->name, ".xdata") + || is_subsection (o->name, ".didat") || startswith (o->name, ".rsrc")) o->gc_mark = 1; |