📄 elf-hppa.h
字号:
{ Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Rela *rel; Elf_Internal_Rela *relend; struct elf64_hppa_link_hash_table *hppa_info = elf64_hppa_hash_table (info); symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; rel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) { int r_type; reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info); unsigned long r_symndx; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; asection *sym_sec; bfd_vma relocation; bfd_reloc_status_type r; const char *sym_name; const char *dyn_name; char *dynh_buf = NULL; size_t dynh_buflen = 0; struct elf64_hppa_dyn_hash_entry *dyn_h = NULL; r_type = ELF_R_TYPE (rel->r_info); if (r_type < 0 || r_type >= (int) R_PARISC_UNIMPLEMENTED) { bfd_set_error (bfd_error_bad_value); return false; } r_symndx = ELF_R_SYM (rel->r_info); if (info->relocateable) { /* This is a relocateable link. We don't have to change anything, unless the reloc is against a section symbol, in which case we have to adjust according to where the section symbol winds up in the output section. */ if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; if (ELF_ST_TYPE (sym->st_info) == STT_SECTION) { sym_sec = local_sections[r_symndx]; rel->r_addend += sym_sec->output_offset; } } continue; } /* This is a final link. */ h = NULL; sym = NULL; sym_sec = NULL; if (r_symndx < symtab_hdr->sh_info) { /* This is a local symbol. */ sym = local_syms + r_symndx; sym_sec = local_sections[r_symndx]; relocation = ((ELF_ST_TYPE (sym->st_info) == STT_SECTION ? 0 : sym->st_value) + sym_sec->output_offset + sym_sec->output_section->vma); /* If this symbol has an entry in the PA64 dynamic hash table, then get it. */ dyn_name = get_dyn_name (input_section, h, rel, &dynh_buf, &dynh_buflen); dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table, dyn_name, false, false); } else { /* This is not a local symbol. */ long indx; indx = r_symndx - symtab_hdr->sh_info; h = elf_sym_hashes (input_bfd)[indx]; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf_link_hash_entry *) h->root.u.i.link; if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { sym_sec = h->root.u.def.section; /* If this symbol has an entry in the PA64 dynamic hash table, then get it. */ dyn_name = get_dyn_name (input_section, h, rel, &dynh_buf, &dynh_buflen); dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table, dyn_name, false, false); /* If we have a relocation against a symbol defined in a shared library and we have not created an entry in the PA64 dynamic symbol hash table for it, then we lose. */ if (sym_sec->output_section == NULL && dyn_h == NULL) { (*_bfd_error_handler) (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"), bfd_get_filename (input_bfd), h->root.root.string, bfd_get_section_name (input_bfd, input_section)); relocation = 0; } else if (sym_sec->output_section) relocation = (h->root.u.def.value + sym_sec->output_offset + sym_sec->output_section->vma); /* Value will be provided via one of the offsets in the dyn_h hash table entry. */ else relocation = 0; } /* Allow undefined symbols in shared libraries. */ else if (info->shared && !info->no_undefined && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT) { if (info->symbolic) (*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, rel->r_offset, false); /* If this symbol has an entry in the PA64 dynamic hash table, then get it. */ dyn_name = get_dyn_name (input_section, h, rel, &dynh_buf, &dynh_buflen); dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table, dyn_name, false, false); if (dyn_h == NULL) { (*_bfd_error_handler) (_("%s: warning: unresolvable relocation against symbol `%s' from %s section"), bfd_get_filename (input_bfd), h->root.root.string, bfd_get_section_name (input_bfd, input_section)); relocation = 0; } relocation = 0; } else if (h->root.type == bfd_link_hash_undefweak) relocation = 0; else { if (!((*info->callbacks->undefined_symbol) (info, h->root.root.string, input_bfd, input_section, rel->r_offset, true))) return false; break; } } if (h != NULL) sym_name = h->root.root.string; else { sym_name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); if (sym_name == NULL) return false; if (*sym_name == '\0') sym_name = bfd_section_name (input_bfd, sym_sec); } r = elf_hppa_final_link_relocate (rel, input_bfd, output_bfd, input_section, contents, relocation, info, sym_sec, h, dyn_h); if (r != bfd_reloc_ok) { switch (r) { default: abort (); case bfd_reloc_overflow: { if (!((*info->callbacks->reloc_overflow) (info, sym_name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_offset))) return false; } break; } } } return true;}/* Compute the value for a relocation (REL) during a final link stage, then insert the value into the proper location in CONTENTS. VALUE is a tentative value for the relocation and may be overridden and modified here based on the specific relocation to be performed. For example we do conversions for PC-relative branches in this routine or redirection of calls to external routines to stubs. The work of actually applying the relocation is left to a helper routine in an attempt to reduce the complexity and size of this function. */static bfd_reloc_status_typeelf_hppa_final_link_relocate (rel, input_bfd, output_bfd, input_section, contents, value, info, sym_sec, h, dyn_h) Elf_Internal_Rela *rel; bfd *input_bfd; bfd *output_bfd; asection *input_section; bfd_byte *contents; bfd_vma value; struct bfd_link_info *info; asection *sym_sec; struct elf_link_hash_entry *h ATTRIBUTE_UNUSED; struct elf64_hppa_dyn_hash_entry *dyn_h;{ unsigned int insn; bfd_vma offset = rel->r_offset; bfd_vma addend = rel->r_addend; reloc_howto_type *howto = elf_hppa_howto_table + ELF_R_TYPE (rel->r_info); unsigned int r_type = howto->type; bfd_byte *hit_data = contents + offset; struct elf64_hppa_link_hash_table *hppa_info = elf64_hppa_hash_table (info); insn = bfd_get_32 (input_bfd, hit_data); switch (r_type) { case R_PARISC_NONE: break; /* Basic function call support. I'm not entirely sure if PCREL14F is actually needed or even handled correctly. Note for a call to a function defined in another dynamic library we want to redirect the call to a stub. */ /* Random PC relative relocs. */ case R_PARISC_PCREL21L: case R_PARISC_PCREL14R: case R_PARISC_PCREL14F: case R_PARISC_PCREL14WR: case R_PARISC_PCREL14DR: case R_PARISC_PCREL16F: case R_PARISC_PCREL16WF: case R_PARISC_PCREL16DF: { /* If this is a call to a function defined in another dynamic library, then redirect the call to the local stub for this function. */ if (sym_sec == NULL || sym_sec->output_section == NULL) value = (dyn_h->stub_offset + hppa_info->stub_sec->output_offset + hppa_info->stub_sec->output_section->vma); /* Turn VALUE into a proper PC relative address. */ value -= (offset + input_section->output_offset + input_section->output_section->vma); /* Adjust for any field selectors. */ if (r_type == R_PARISC_PCREL21L) value = hppa_field_adjust (value, -8 + addend, e_lsel); else if (r_type == R_PARISC_PCREL14F || r_type == R_PARISC_PCREL16F || r_type == R_PARISC_PCREL16WF || r_type == R_PARISC_PCREL16DF) value = hppa_field_adjust (value, -8 + addend, e_fsel); else value = hppa_field_adjust (value, -8 + addend, e_rsel); /* Apply the relocation to the given instruction. */ insn = elf_hppa_relocate_insn (insn, value, r_type); break; } case R_PARISC_PCREL12F: case R_PARISC_PCREL22F: case R_PARISC_PCREL17F: case R_PARISC_PCREL22C: case R_PARISC_PCREL17C: case R_PARISC_PCREL17R: { /* If this is a call to a function defined in another dynamic library, then redirect the call to the local stub for this function. */ if (sym_sec == NULL || sym_sec->output_section == NULL) value = (dyn_h->stub_offset + hppa_info->stub_sec->output_offset + hppa_info->stub_sec->output_section->vma); /* Turn VALUE into a proper PC relative address. */ value -= (offset + input_section->output_offset + input_section->output_section->vma); /* Adjust for any field selectors. */ if (r_type == R_PARISC_PCREL17R) value = hppa_field_adjust (value, -8 + addend, e_rsel); else value = hppa_field_adjust (value, -8 + addend, e_fsel); /* All branches are implicitly shifted by 2 places. */ value >>= 2; /* Apply the relocation to the given instruction. */ insn = elf_hppa_relocate_insn (insn, value, r_type); break; } /* Indirect references to data through the DLT. */ case R_PARISC_DLTIND14
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -