elf64-sparc.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,055 行 · 第 1/5 页
C
2,055 行
|| ! bfd_set_section_flags (dynobj, sreloc, flags) || ! bfd_set_section_alignment (dynobj, sreloc, 3)) return false; } } sreloc->_raw_size += sizeof (Elf64_External_Rela); } break; case R_SPARC_REGISTER: /* Nothing to do. */ break; default: (*_bfd_error_handler) (_("%s: check_relocs: unhandled reloc type %d"), bfd_get_filename(abfd), ELF64_R_TYPE_ID (rel->r_info)); return false; } } return true;}/* Hook called by the linker routine which adds symbols from an object file. We use it for STT_REGISTER symbols. */static booleansparc64_elf_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp) bfd *abfd; struct bfd_link_info *info; const Elf_Internal_Sym *sym; const char **namep; flagword *flagsp ATTRIBUTE_UNUSED; asection **secp ATTRIBUTE_UNUSED; bfd_vma *valp ATTRIBUTE_UNUSED;{ static char *stt_types[] = { "NOTYPE", "OBJECT", "FUNCTION" }; if (ELF_ST_TYPE (sym->st_info) == STT_REGISTER) { int reg; struct sparc64_elf_app_reg *p; reg = (int)sym->st_value; switch (reg & ~1) { case 2: reg -= 2; break; case 6: reg -= 4; break; default: (*_bfd_error_handler) (_("%s: Only registers %%g[2367] can be declared using STT_REGISTER"), bfd_get_filename (abfd)); return false; } if (info->hash->creator != abfd->xvec || (abfd->flags & DYNAMIC) != 0) { /* STT_REGISTER only works when linking an elf64_sparc object. If STT_REGISTER comes from a dynamic object, don't put it into the output bfd. The dynamic linker will recheck it. */ *namep = NULL; return true; } p = sparc64_elf_hash_table(info)->app_regs + reg; if (p->name != NULL && strcmp (p->name, *namep)) { (*_bfd_error_handler) (_("Register %%g%d used incompatibly: " "previously declared in %s to %s, in %s redefined to %s"), (int)sym->st_value, bfd_get_filename (p->abfd), *p->name ? p->name : "#scratch", bfd_get_filename (abfd), **namep ? *namep : "#scratch"); return false; } if (p->name == NULL) { if (**namep) { struct elf_link_hash_entry *h; h = (struct elf_link_hash_entry *) bfd_link_hash_lookup (info->hash, *namep, false, false, false); if (h != NULL) { unsigned char type = h->type; if (type > STT_FUNC) type = 0; (*_bfd_error_handler) (_("Symbol `%s' has differing types: " "previously %s, REGISTER in %s"), *namep, stt_types [type], bfd_get_filename (abfd)); return false; } p->name = bfd_hash_allocate (&info->hash->table, strlen (*namep) + 1); if (!p->name) return false; strcpy (p->name, *namep); } else p->name = ""; p->bind = ELF_ST_BIND (sym->st_info); p->abfd = abfd; p->shndx = sym->st_shndx; } else { if (p->bind == STB_WEAK && ELF_ST_BIND (sym->st_info) == STB_GLOBAL) { p->bind = STB_GLOBAL; p->abfd = abfd; } } *namep = NULL; return true; } else if (! *namep || ! **namep) return true; else { int i; struct sparc64_elf_app_reg *p; p = sparc64_elf_hash_table(info)->app_regs; for (i = 0; i < 4; i++, p++) if (p->name != NULL && ! strcmp (p->name, *namep)) { unsigned char type = ELF_ST_TYPE (sym->st_info); if (type > STT_FUNC) type = 0; (*_bfd_error_handler) (_("Symbol `%s' has differing types: " "REGISTER in %s, %s in %s"), *namep, bfd_get_filename (p->abfd), stt_types [type], bfd_get_filename (abfd)); return false; } } return true;}/* This function takes care of emiting STT_REGISTER symbols which we cannot easily keep in the symbol hash table. */static booleansparc64_elf_output_arch_syms (output_bfd, info, finfo, func) bfd *output_bfd ATTRIBUTE_UNUSED; struct bfd_link_info *info; PTR finfo; boolean (*func) PARAMS ((PTR, const char *, Elf_Internal_Sym *, asection *));{ int reg; struct sparc64_elf_app_reg *app_regs = sparc64_elf_hash_table(info)->app_regs; Elf_Internal_Sym sym; /* We arranged in size_dynamic_sections to put the STT_REGISTER entries at the end of the dynlocal list, so they came at the end of the local symbols in the symtab. Except that they aren't STB_LOCAL, so we need to back up symtab->sh_info. */ if (elf_hash_table (info)->dynlocal) { bfd * dynobj = elf_hash_table (info)->dynobj; asection *dynsymsec = bfd_get_section_by_name (dynobj, ".dynsym"); struct elf_link_local_dynamic_entry *e; for (e = elf_hash_table (info)->dynlocal; e ; e = e->next) if (e->input_indx == -1) break; if (e) { elf_section_data (dynsymsec->output_section)->this_hdr.sh_info = e->dynindx; } } if (info->strip == strip_all) return true; for (reg = 0; reg < 4; reg++) if (app_regs [reg].name != NULL) { if (info->strip == strip_some && bfd_hash_lookup (info->keep_hash, app_regs [reg].name, false, false) == NULL) continue; sym.st_value = reg < 2 ? reg + 2 : reg + 4; sym.st_size = 0; sym.st_other = 0; sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER); sym.st_shndx = app_regs [reg].shndx; if (! (*func) (finfo, app_regs [reg].name, &sym, sym.st_shndx == SHN_ABS ? bfd_abs_section_ptr : bfd_und_section_ptr)) return false; } return true;}static intsparc64_elf_get_symbol_type (elf_sym, type) Elf_Internal_Sym * elf_sym; int type;{ if (ELF_ST_TYPE (elf_sym->st_info) == STT_REGISTER) return STT_REGISTER; else return type;}/* A STB_GLOBAL,STT_REGISTER symbol should be BSF_GLOBAL even in SHN_UNDEF section. */static voidsparc64_elf_symbol_processing (abfd, asym) bfd *abfd ATTRIBUTE_UNUSED; asymbol *asym;{ elf_symbol_type *elfsym; elfsym = (elf_symbol_type *) asym; if (elfsym->internal_elf_sym.st_info == ELF_ST_INFO (STB_GLOBAL, STT_REGISTER)) { asym->flags |= BSF_GLOBAL; }}/* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to change the definition to something the rest of the link can understand. */static booleansparc64_elf_adjust_dynamic_symbol (info, h) struct bfd_link_info *info; struct elf_link_hash_entry *h;{ bfd *dynobj; asection *s; unsigned int power_of_two; dynobj = elf_hash_table (info)->dynobj; /* Make sure we know what is going on here. */ BFD_ASSERT (dynobj != NULL && ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) || h->weakdef != NULL || ((h->elf_link_hash_flags & ELF_LINK_HASH_DEF_DYNAMIC) != 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_REF_REGULAR) != 0 && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0))); /* If this is a function, put it in the procedure linkage table. We will fill in the contents of the procedure linkage table later (although we could actually do it here). The STT_NOTYPE condition is a hack specifically for the Oracle libraries delivered for Solaris; for some inexplicable reason, they define some of their functions as STT_NOTYPE when they really should be STT_FUNC. */ if (h->type == STT_FUNC || (h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0 || (h->type == STT_NOTYPE && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && (h->root.u.def.section->flags & SEC_CODE) != 0)) { if (! elf_hash_table (info)->dynamic_sections_created) { /* This case can occur if we saw a WPLT30 reloc in an input file, but none of the input files were dynamic objects. In such a case, we don't actually need to build a procedure linkage table, and we can just do a WDISP30 reloc instead. */ BFD_ASSERT ((h->elf_link_hash_flags & ELF_LINK_HASH_NEEDS_PLT) != 0); return true; } s = bfd_get_section_by_name (dynobj, ".plt"); BFD_ASSERT (s != NULL); /* The first four bit in .plt is reserved. */ if (s->_raw_size == 0) s->_raw_size = PLT_HEADER_SIZE; /* If this symbol is not defined in a regular file, and we are not generating a shared library, then set the symbol to this location in the .plt. This is required to make function pointers compare as equal between the normal executable and the shared library. */ if (! info->shared && (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR) == 0) { h->root.u.def.section = s; h->root.u.def.value = s->_raw_size; } /* To simplify matters later, just store the plt index here. */ h->plt.offset = s->_raw_size / PLT_ENTRY_SIZE; /* Make room for this entry. */ s->_raw_size += PLT_ENTRY_SIZE; /* We also need to make an entry in the .rela.plt section. */ s = bfd_get_section_by_name (dynobj, ".rela.plt"); BFD_ASSERT (s != NULL); s->_raw_size += sizeof (Elf64_External_Rela); /* The procedure linkage table size is bounded by the magnitude of the offset we can describe in the entry. */ if (s->_raw_size >= (bfd_vma)1 << 32) { bfd_set_error (bfd_error_bad_value); return false; } return true; } /* If this is a weak symbol, and there is a real definition, the processor independent code will have arranged for us to see the real definition first, and we can just use the same value. */ if (h->weakdef != NULL) { BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined || h->weakdef->root.type == bfd_link_hash_defweak); h->root.u.def.section = h->weakdef->root.u.def.section; h->root.u.def.value = h->weakdef->root.u.def.value; return true; } /* This is a reference to a symbol defined by a dynamic object which is not a function. */ /* If we are creating a shared library, we must presume that the only references to the symbol are via the global offset table. For such cases we need not do anything here; the relocations will be handled correctly by relocate_section. */ if (info->shared) return true; /* We must allocate the symbol in our .dynbss section, which will become part of the .bss section of the executable. There will be an entry for this symbol in the .dynsym section. The dynamic object will contain position independent code, so all references from the dynamic object to this symbol will go through the global offset table. The dynamic linker will use the .dynsym entry to determine the address it must put in the global offset table, so both the dynamic object and the regular object will refer to the same memory location for the variable. */ s = bfd_get_section_by_name (dynobj, ".dynbss"); BFD_ASSERT (s != NULL); /* We must generate a R_SPARC_COPY reloc to tell the dynamic linker to copy the initial value out of the dynamic object and into the runtime process image. We need to remember the offset into the .rel.bss section we are going to use. */ if ((h->root.u.def.section->flags & SEC_ALLOC) != 0) { asection *srel; srel = bfd_get_section_by_name (dynobj, ".rela.bss"); BFD_ASSERT (srel != NULL); srel->_raw_size += sizeof (Elf64_External_Rela); h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_COPY; } /* We need to figure out the alignment required for this symbol. I have no idea how ELF linkers handle this. 16-bytes is the size of the largest type that requires hard alignment -- long double. */ power_of_two = bfd_log2 (h->size); if (power_of_two > 4) power_of_two = 4; /* Apply the required alignment. */ s->_raw_size = BFD_ALIGN (s->_raw_size, (bfd_size_type) (1 << power_of_two)); if (power_of_two > bfd_get_section_alignment (dynobj, s)) { if (! bfd_set_section_alignment (dynobj, s, power_of_two)) return false; } /* Define the symbol as being at this point in the section. */ h->root.u.def.section = s; h->root.u.def.value = s->_raw_size; /* Increment the section size to make room for the symbol. */ s->_raw_size += h->size; return true;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?