elfxx-ia64.c
来自「基于4个mips核的noc设计」· C语言 代码 · 共 2,106 行 · 第 1/5 页
C
2,106 行
bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type bfd_code;{ unsigned int rtype; switch (bfd_code) { case BFD_RELOC_NONE: rtype = R_IA64_NONE; break; case BFD_RELOC_IA64_IMM14: rtype = R_IA64_IMM14; break; case BFD_RELOC_IA64_IMM22: rtype = R_IA64_IMM22; break; case BFD_RELOC_IA64_IMM64: rtype = R_IA64_IMM64; break; case BFD_RELOC_IA64_DIR32MSB: rtype = R_IA64_DIR32MSB; break; case BFD_RELOC_IA64_DIR32LSB: rtype = R_IA64_DIR32LSB; break; case BFD_RELOC_IA64_DIR64MSB: rtype = R_IA64_DIR64MSB; break; case BFD_RELOC_IA64_DIR64LSB: rtype = R_IA64_DIR64LSB; break; case BFD_RELOC_IA64_GPREL22: rtype = R_IA64_GPREL22; break; case BFD_RELOC_IA64_GPREL64I: rtype = R_IA64_GPREL64I; break; case BFD_RELOC_IA64_GPREL32MSB: rtype = R_IA64_GPREL32MSB; break; case BFD_RELOC_IA64_GPREL32LSB: rtype = R_IA64_GPREL32LSB; break; case BFD_RELOC_IA64_GPREL64MSB: rtype = R_IA64_GPREL64MSB; break; case BFD_RELOC_IA64_GPREL64LSB: rtype = R_IA64_GPREL64LSB; break; case BFD_RELOC_IA64_LTOFF22: rtype = R_IA64_LTOFF22; break; case BFD_RELOC_IA64_LTOFF64I: rtype = R_IA64_LTOFF64I; break; case BFD_RELOC_IA64_PLTOFF22: rtype = R_IA64_PLTOFF22; break; case BFD_RELOC_IA64_PLTOFF64I: rtype = R_IA64_PLTOFF64I; break; case BFD_RELOC_IA64_PLTOFF64MSB: rtype = R_IA64_PLTOFF64MSB; break; case BFD_RELOC_IA64_PLTOFF64LSB: rtype = R_IA64_PLTOFF64LSB; break; case BFD_RELOC_IA64_FPTR64I: rtype = R_IA64_FPTR64I; break; case BFD_RELOC_IA64_FPTR32MSB: rtype = R_IA64_FPTR32MSB; break; case BFD_RELOC_IA64_FPTR32LSB: rtype = R_IA64_FPTR32LSB; break; case BFD_RELOC_IA64_FPTR64MSB: rtype = R_IA64_FPTR64MSB; break; case BFD_RELOC_IA64_FPTR64LSB: rtype = R_IA64_FPTR64LSB; break; case BFD_RELOC_IA64_PCREL21B: rtype = R_IA64_PCREL21B; break; case BFD_RELOC_IA64_PCREL21BI: rtype = R_IA64_PCREL21BI; break; case BFD_RELOC_IA64_PCREL21M: rtype = R_IA64_PCREL21M; break; case BFD_RELOC_IA64_PCREL21F: rtype = R_IA64_PCREL21F; break; case BFD_RELOC_IA64_PCREL22: rtype = R_IA64_PCREL22; break; case BFD_RELOC_IA64_PCREL60B: rtype = R_IA64_PCREL60B; break; case BFD_RELOC_IA64_PCREL64I: rtype = R_IA64_PCREL64I; break; case BFD_RELOC_IA64_PCREL32MSB: rtype = R_IA64_PCREL32MSB; break; case BFD_RELOC_IA64_PCREL32LSB: rtype = R_IA64_PCREL32LSB; break; case BFD_RELOC_IA64_PCREL64MSB: rtype = R_IA64_PCREL64MSB; break; case BFD_RELOC_IA64_PCREL64LSB: rtype = R_IA64_PCREL64LSB; break; case BFD_RELOC_IA64_LTOFF_FPTR22: rtype = R_IA64_LTOFF_FPTR22; break; case BFD_RELOC_IA64_LTOFF_FPTR64I: rtype = R_IA64_LTOFF_FPTR64I; break; case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break; case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break; case BFD_RELOC_IA64_SEGREL32MSB: rtype = R_IA64_SEGREL32MSB; break; case BFD_RELOC_IA64_SEGREL32LSB: rtype = R_IA64_SEGREL32LSB; break; case BFD_RELOC_IA64_SEGREL64MSB: rtype = R_IA64_SEGREL64MSB; break; case BFD_RELOC_IA64_SEGREL64LSB: rtype = R_IA64_SEGREL64LSB; break; case BFD_RELOC_IA64_SECREL32MSB: rtype = R_IA64_SECREL32MSB; break; case BFD_RELOC_IA64_SECREL32LSB: rtype = R_IA64_SECREL32LSB; break; case BFD_RELOC_IA64_SECREL64MSB: rtype = R_IA64_SECREL64MSB; break; case BFD_RELOC_IA64_SECREL64LSB: rtype = R_IA64_SECREL64LSB; break; case BFD_RELOC_IA64_REL32MSB: rtype = R_IA64_REL32MSB; break; case BFD_RELOC_IA64_REL32LSB: rtype = R_IA64_REL32LSB; break; case BFD_RELOC_IA64_REL64MSB: rtype = R_IA64_REL64MSB; break; case BFD_RELOC_IA64_REL64LSB: rtype = R_IA64_REL64LSB; break; case BFD_RELOC_IA64_LTV32MSB: rtype = R_IA64_LTV32MSB; break; case BFD_RELOC_IA64_LTV32LSB: rtype = R_IA64_LTV32LSB; break; case BFD_RELOC_IA64_LTV64MSB: rtype = R_IA64_LTV64MSB; break; case BFD_RELOC_IA64_LTV64LSB: rtype = R_IA64_LTV64LSB; break; case BFD_RELOC_IA64_IPLTMSB: rtype = R_IA64_IPLTMSB; break; case BFD_RELOC_IA64_IPLTLSB: rtype = R_IA64_IPLTLSB; break; case BFD_RELOC_IA64_COPY: rtype = R_IA64_COPY; break; case BFD_RELOC_IA64_LTOFF22X: rtype = R_IA64_LTOFF22X; break; case BFD_RELOC_IA64_LDXMOV: rtype = R_IA64_LDXMOV; break; case BFD_RELOC_IA64_TPREL22: rtype = R_IA64_TPREL22; break; case BFD_RELOC_IA64_TPREL64MSB: rtype = R_IA64_TPREL64MSB; break; case BFD_RELOC_IA64_TPREL64LSB: rtype = R_IA64_TPREL64LSB; break; case BFD_RELOC_IA64_LTOFF_TP22: rtype = R_IA64_LTOFF_TP22; break; default: return 0; } return lookup_howto (rtype);}/* Given a ELF reloc, return the matching HOWTO structure. */static voidelfNN_ia64_info_to_howto (abfd, bfd_reloc, elf_reloc) bfd *abfd ATTRIBUTE_UNUSED; arelent *bfd_reloc; ElfNN_Internal_Rela *elf_reloc;{ bfd_reloc->howto = lookup_howto (ELFNN_R_TYPE (elf_reloc->r_info));}#define PLT_HEADER_SIZE (3 * 16)#define PLT_MIN_ENTRY_SIZE (1 * 16)#define PLT_FULL_ENTRY_SIZE (2 * 16)#define PLT_RESERVED_WORDS 3static const bfd_byte plt_header[PLT_HEADER_SIZE] ={ 0x0b, 0x10, 0x00, 0x1c, 0x00, 0x21, /* [MMI] mov r2=r14;; */ 0xe0, 0x00, 0x08, 0x00, 0x48, 0x00, /* addl r14=0,r2 */ 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */ 0x0b, 0x80, 0x20, 0x1c, 0x18, 0x14, /* [MMI] ld8 r16=[r14],8;; */ 0x10, 0x41, 0x38, 0x30, 0x28, 0x00, /* ld8 r17=[r14],8 */ 0x00, 0x00, 0x04, 0x00, /* nop.i 0x0;; */ 0x11, 0x08, 0x00, 0x1c, 0x18, 0x10, /* [MIB] ld8 r1=[r14] */ 0x60, 0x88, 0x04, 0x80, 0x03, 0x00, /* mov b6=r17 */ 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */};static const bfd_byte plt_min_entry[PLT_MIN_ENTRY_SIZE] ={ 0x11, 0x78, 0x00, 0x00, 0x00, 0x24, /* [MIB] mov r15=0 */ 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* nop.i 0x0 */ 0x00, 0x00, 0x00, 0x40 /* br.few 0 <PLT0>;; */};static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] ={ 0x0b, 0x78, 0x00, 0x02, 0x00, 0x24, /* [MMI] addl r15=0,r1;; */ 0x00, 0x41, 0x3c, 0x30, 0x28, 0xc0, /* ld8 r16=[r15],8 */ 0x01, 0x08, 0x00, 0x84, /* mov r14=r1;; */ 0x11, 0x08, 0x00, 0x1e, 0x18, 0x10, /* [MIB] ld8 r1=[r15] */ 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */ 0x60, 0x00, 0x80, 0x00 /* br.few b6;; */};#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"/* Select out of range branch fixup type. Note that Itanium does not support brl, and so it gets emulated by the kernel. */#undef USE_BRLstatic const bfd_byte oor_brl[16] ={ 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* brl.sptk.few tgt;; */ 0x00, 0x00, 0x00, 0xc0};static const bfd_byte oor_ip[48] ={ 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MLX] nop.m 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, /* movl r15=0 */ 0x01, 0x00, 0x00, 0x60, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MII] nop.m 0 */ 0x00, 0x01, 0x00, 0x60, 0x00, 0x00, /* mov r16=ip;; */ 0xf2, 0x80, 0x00, 0x80, /* add r16=r15,r16;; */ 0x11, 0x00, 0x00, 0x00, 0x01, 0x00, /* [MIB] nop.m 0 */ 0x60, 0x80, 0x04, 0x80, 0x03, 0x00, /* mov b6=r16 */ 0x60, 0x00, 0x80, 0x00 /* br b6;; */};/* These functions do relaxation for IA-64 ELF. This is primarily to support branches to targets out of range; relaxation of R_IA64_LTOFF22X and R_IA64_LDXMOV not yet supported. */static booleanelfNN_ia64_relax_section (abfd, sec, link_info, again) bfd *abfd; asection *sec; struct bfd_link_info *link_info; boolean *again;{ struct one_fixup { struct one_fixup *next; asection *tsec; bfd_vma toff; bfd_vma trampoff; }; Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Rela *internal_relocs; Elf_Internal_Rela *free_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents; bfd_byte *free_contents = NULL; ElfNN_External_Sym *extsyms; ElfNN_External_Sym *free_extsyms = NULL; struct elfNN_ia64_link_hash_table *ia64_info; struct one_fixup *fixups = NULL; boolean changed_contents = false; boolean changed_relocs = false; /* Assume we're not going to change any sizes, and we'll only need one pass. */ *again = false; /* Nothing to do if there are no relocations. */ if ((sec->flags & SEC_RELOC) == 0 || sec->reloc_count == 0) return true; /* If this is the first time we have been called for this section, initialize the cooked size. */ if (sec->_cooked_size == 0) sec->_cooked_size = sec->_raw_size; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; /* Load the relocations for this section. */ internal_relocs = (_bfd_elfNN_link_read_relocs (abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL, link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; if (! link_info->keep_memory) free_relocs = internal_relocs; ia64_info = elfNN_ia64_hash_table (link_info); irelend = internal_relocs + sec->reloc_count; for (irel = internal_relocs; irel < irelend; irel++) if (ELFNN_R_TYPE (irel->r_info) == (int) R_IA64_PCREL21B) break; /* No branch-type relocations. */ if (irel == irelend) { if (free_relocs != NULL) free (free_relocs); return true; } /* Get the section contents. */ if (elf_section_data (sec)->this_hdr.contents != NULL) contents = elf_section_data (sec)->this_hdr.contents; else { contents = (bfd_byte *) bfd_malloc (sec->_raw_size); if (contents == NULL) goto error_return; free_contents = contents; if (! bfd_get_section_contents (abfd, sec, contents, (file_ptr) 0, sec->_raw_size)) goto error_return; } /* Read this BFD's symbols. */ if (symtab_hdr->contents != NULL) extsyms = (ElfNN_External_Sym *) symtab_hdr->contents; else { extsyms = (ElfNN_External_Sym *) bfd_malloc (symtab_hdr->sh_size); if (extsyms == NULL) goto error_return; free_extsyms = extsyms; if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0 || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd) != symtab_hdr->sh_size)) goto error_return; } for (; irel < irelend; irel++) { bfd_vma symaddr, reladdr, trampoff, toff, roff; Elf_Internal_Sym isym; asection *tsec; struct one_fixup *f; if (ELFNN_R_TYPE (irel->r_info) != (int) R_IA64_PCREL21B) continue; /* Get the value of the symbol referred to by the reloc. */ if (ELFNN_R_SYM (irel->r_info) < symtab_hdr->sh_info) { /* A local symbol. */ bfd_elfNN_swap_symbol_in (abfd, extsyms + ELFNN_R_SYM (irel->r_info), &isym); if (isym.st_shndx == SHN_UNDEF) continue; /* We can't do anthing with undefined symbols. */ else if (isym.st_shndx == SHN_ABS) tsec = bfd_abs_section_ptr; else if (isym.st_shndx == SHN_COMMON) tsec = bfd_com_section_ptr; else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE) tsec = bfd_section_from_elf_index (abfd, isym.st_shndx); else continue; /* who knows. */ toff = isym.st_value; } else { unsigned long indx; struct elf_link_hash_entry *h; struct elfNN_ia64_dyn_sym_info *dyn_i; indx = ELFNN_R_SYM (irel->r_info) - symtab_hdr->sh_info; h = elf_sym_hashes (abfd)[indx]; BFD_ASSERT (h != NULL); 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; dyn_i = get_dyn_sym_info (ia64_info, h, abfd, irel, false); /* For branches to dynamic symbols, we're interested instead in a branch to the PLT entry. */ if (dyn_i && dyn_i->want_plt2) { tsec = ia64_info->plt_sec; toff = dyn_i->plt2_offset; } else { /* We can't do anthing with undefined symbols. */ if (h->root.type == bfd_link_hash_undefined || h->root.type == bfd_link_hash_undefweak) continue; tsec = h->root.u.def.section; toff = h->root.u.def.value; } } symaddr = (tsec->output_section->vma + tsec->output_offset + toff + irel->r_addend); roff = irel->r_offset; reladdr = (sec->output_section->vma + sec->output_offset + roff) & -4; /* If the branch is in range, no need to do anything. */ if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000 && (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0) continue; /* If the branch and target are in the same section, you've got one honking big section and we can't help you. You'll get an error message later. */ if (tsec == sec) continue; /* Look for an existing fixup to this address. */ for (f = fixups; f ; f = f->next) if (f->tsec == tsec && f->toff == toff) break; if (f == NULL) { /* Two alternatives: If it's a branch to a PLT entry, we can make a copy of the FULL_PLT entry. Otherwise, we'll have to use a `brl' insn to get where we're going. */ int size; if (tsec == ia64_info->plt_sec) size = sizeof (plt_full_entry); else {#ifdef USE_BRL size = sizeof (oor_brl);#else size = sizeof (oor_ip);#endif } /* Resize the current section to make room for the new branch. */ trampoff = (sec->_cooked_size + 15) & -16; contents = (bfd_byte *) bfd_realloc (contents, trampoff + size); if (contents == NULL) goto error_return; sec->_cooked_size = trampoff + size; if (tsec == ia64_info->plt_sec) { memcpy (contents + trampoff, plt_full_entry, size); /* Hijack the old relocation for use as the PLTOFF reloc. */ irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), R_IA64_PLTOFF22); irel->r_offset = trampoff; } else {#ifdef USE_BRL memcpy (contents + trampoff, oor_brl, size); irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), R_IA64_PCREL60B); irel->r_offset = trampoff + 2;#else memcpy (contents + trampoff, oor_ip, size); irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info), R_IA64_PCREL64I); irel->r_addend -= 16; irel->r_offset = trampoff + 2;#endif } /* Record the fixup so we don't do it again this section. */ f = (struct one_fixup *) bfd_malloc (sizeof (*f)); f->next = fixups; f->tsec = tsec; f->toff = toff; f->trampoff = trampoff; fixups = f; } else { /* Nop out the reloc, since we're finalizing things here. */ irel->r_info = ELFNN_R_INFO (0, R_IA64_NONE); }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?