/* Helpers to convert between BFD and GOLD symbol formats. */ static enum ld_plugin_status asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, const struct ld_plugin_symbol *ldsym) { flagword flags = BSF_NO_FLAGS; struct bfd_section *section; asym->the_bfd = abfd; asym->name = (ldsym->version ? concat (ldsym->name, "@", ldsym->version, (const char *) NULL) : ldsym->name); asym->value = 0; switch (ldsym->def) { case LDPK_WEAKDEF: flags = BSF_WEAK; /* FALLTHRU */ case LDPK_DEF: flags |= BSF_GLOBAL; if (ldsym->comdat_key) { char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key, (const char *) NULL); section = bfd_get_section_by_name (abfd, name); if (section != NULL) free (name); else { flagword sflags; sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD); section = bfd_make_section_anyway_with_flags (abfd, name, sflags); if (section == NULL) return LDPS_ERR; } } else section = bfd_get_section_by_name (abfd, ".text"); break; case LDPK_WEAKUNDEF: flags = BSF_WEAK; /* FALLTHRU */ case LDPK_UNDEF: section = bfd_und_section_ptr; break; case LDPK_COMMON: flags = BSF_GLOBAL; section = bfd_com_section_ptr; asym->value = ldsym->size; /* For ELF targets, set alignment of common symbol to 1. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) { ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON; ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1; } break; default: return LDPS_ERR; } asym->flags = flags; asym->section = section; /* Visibility only applies on ELF targets. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) { elf_symbol_type *elfsym = elf_symbol_from (abfd, asym); unsigned char visibility; if (!elfsym) einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name); switch (ldsym->visibility) { default: einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"), ldsym->visibility); case LDPV_DEFAULT: visibility = STV_DEFAULT; break; case LDPV_PROTECTED: visibility = STV_PROTECTED; break; case LDPV_INTERNAL: visibility = STV_INTERNAL; break; case LDPV_HIDDEN: visibility = STV_HIDDEN; break; } elfsym->internal_elf_sym.st_other = (visibility | (elfsym->internal_elf_sym.st_other & ~ELF_ST_VISIBILITY (-1))); } return LDPS_OK; }
/* Helpers to convert between BFD and GOLD symbol formats. */ static enum ld_plugin_status asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, const struct ld_plugin_symbol *ldsym) { flagword flags = BSF_NO_FLAGS; struct bfd_section *section; asym->the_bfd = abfd; asym->name = (ldsym->version ? concat (ldsym->name, "@", ldsym->version, (const char *) NULL) : ldsym->name); asym->value = 0; switch (ldsym->def) { case LDPK_WEAKDEF: flags = BSF_WEAK; /* FALLTHRU */ case LDPK_DEF: flags |= BSF_GLOBAL; section = bfd_get_section_by_name (abfd, ".text"); break; case LDPK_WEAKUNDEF: flags = BSF_WEAK; /* FALLTHRU */ case LDPK_UNDEF: section = bfd_und_section_ptr; break; case LDPK_COMMON: flags = BSF_GLOBAL; section = bfd_com_section_ptr; asym->value = ldsym->size; /* For ELF targets, set alignment of common symbol to 1. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) { ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON; ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1; } break; default: return LDPS_ERR; } asym->flags = flags; asym->section = section; /* Visibility only applies on ELF targets. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) { elf_symbol_type *elfsym = elf_symbol_from (abfd, asym); unsigned char visibility; if (!elfsym) einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name); switch (ldsym->visibility) { default: einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"), ldsym->visibility); case LDPV_DEFAULT: visibility = STV_DEFAULT; break; case LDPV_PROTECTED: visibility = STV_PROTECTED; break; case LDPV_INTERNAL: visibility = STV_INTERNAL; break; case LDPV_HIDDEN: visibility = STV_HIDDEN; break; } elfsym->internal_elf_sym.st_other = (visibility | (elfsym->internal_elf_sym.st_other & ~ELF_ST_VISIBILITY (-1))); } return LDPS_OK; }