📄 elf-m10300.c
字号:
{ case R_MN10300_NONE: return bfd_reloc_ok; case R_MN10300_32: value += addend; bfd_put_32 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_MN10300_24: value += addend; if ((long) value > 0x7fffff || (long) value < -0x800000) return bfd_reloc_overflow; bfd_put_8 (input_bfd, value & 0xff, hit_data); bfd_put_8 (input_bfd, (value >> 8) & 0xff, hit_data + 1); bfd_put_8 (input_bfd, (value >> 16) & 0xff, hit_data + 2); return bfd_reloc_ok; case R_MN10300_16: value += addend; if ((long) value > 0x7fff || (long) value < -0x8000) return bfd_reloc_overflow; bfd_put_16 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_MN10300_8: value += addend; if ((long) value > 0x7f || (long) value < -0x80) return bfd_reloc_overflow; bfd_put_8 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_MN10300_PCREL8: value -= (input_section->output_section->vma + input_section->output_offset); value -= offset; value += addend; if ((long) value > 0xff || (long) value < -0x100) return bfd_reloc_overflow; bfd_put_8 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_MN10300_PCREL16: value -= (input_section->output_section->vma + input_section->output_offset); value -= offset; value += addend; if ((long) value > 0xffff || (long) value < -0x10000) return bfd_reloc_overflow; bfd_put_16 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_MN10300_PCREL32: value -= (input_section->output_section->vma + input_section->output_offset); value -= offset; value += addend; bfd_put_32 (input_bfd, value, hit_data); return bfd_reloc_ok; case R_MN10300_GNU_VTINHERIT: case R_MN10300_GNU_VTENTRY: return bfd_reloc_ok; default: return bfd_reloc_notsupported; }}/* Relocate an MN10300 ELF section. */static booleanmn10300_elf_relocate_section (output_bfd, info, input_bfd, input_section, contents, relocs, local_syms, local_sections) bfd *output_bfd; struct bfd_link_info *info; bfd *input_bfd; asection *input_section; bfd_byte *contents; Elf_Internal_Rela *relocs; Elf_Internal_Sym *local_syms; asection **local_sections;{ Elf_Internal_Shdr *symtab_hdr; struct elf32_mn10300_link_hash_entry **sym_hashes; Elf_Internal_Rela *rel, *relend; symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; sym_hashes = (struct elf32_mn10300_link_hash_entry **) (elf_sym_hashes (input_bfd)); rel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) { int r_type; reloc_howto_type *howto; unsigned long r_symndx; Elf_Internal_Sym *sym; asection *sec; struct elf32_mn10300_link_hash_entry *h; bfd_vma relocation; bfd_reloc_status_type r; r_symndx = ELF32_R_SYM (rel->r_info); r_type = ELF32_R_TYPE (rel->r_info); howto = elf_mn10300_howto_table + r_type; /* Just skip the vtable gc relocs. */ if (r_type == R_MN10300_GNU_VTINHERIT || r_type == R_MN10300_GNU_VTENTRY) continue; 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) { sec = local_sections[r_symndx]; rel->r_addend += sec->output_offset + sym->st_value; } } continue; } /* This is a final link. */ h = NULL; sym = NULL; sec = NULL; if (r_symndx < symtab_hdr->sh_info) { sym = local_syms + r_symndx; sec = local_sections[r_symndx]; relocation = (sec->output_section->vma + sec->output_offset + sym->st_value); } else { h = sym_hashes[r_symndx - symtab_hdr->sh_info]; while (h->root.type == bfd_link_hash_indirect || h->root.type == bfd_link_hash_warning) h = (struct elf32_mn10300_link_hash_entry *) h->root.root.u.i.link; if (h->root.root.type == bfd_link_hash_defined || h->root.root.type == bfd_link_hash_defweak) { sec = h->root.root.u.def.section; relocation = (h->root.root.u.def.value + sec->output_section->vma + sec->output_offset); } else if (h->root.root.type == bfd_link_hash_undefweak) relocation = 0; else { if (! ((*info->callbacks->undefined_symbol) (info, h->root.root.root.string, input_bfd, input_section, rel->r_offset, true))) return false; relocation = 0; } } r = mn10300_elf_final_link_relocate (howto, input_bfd, output_bfd, input_section, contents, rel->r_offset, relocation, rel->r_addend, info, sec, h == NULL); if (r != bfd_reloc_ok) { const char *name; const char *msg = (const char *) 0; if (h != NULL) name = h->root.root.root.string; else { name = (bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name)); if (name == NULL || *name == '\0') name = bfd_section_name (input_bfd, sec); } switch (r) { case bfd_reloc_overflow: if (! ((*info->callbacks->reloc_overflow) (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_offset))) return false; break; case bfd_reloc_undefined: if (! ((*info->callbacks->undefined_symbol) (info, name, input_bfd, input_section, rel->r_offset, true))) return false; break; case bfd_reloc_outofrange: msg = _("internal error: out of range error"); goto common_error; case bfd_reloc_notsupported: msg = _("internal error: unsupported relocation error"); goto common_error; case bfd_reloc_dangerous: msg = _("internal error: dangerous error"); goto common_error; default: msg = _("internal error: unknown error"); /* fall through */ common_error: if (!((*info->callbacks->warning) (info, msg, name, input_bfd, input_section, rel->r_offset))) return false; break; } } } return true;}/* Finish initializing one hash table entry. */static booleanelf32_mn10300_finish_hash_table_entry (gen_entry, in_args) struct bfd_hash_entry *gen_entry; PTR in_args ATTRIBUTE_UNUSED;{ struct elf32_mn10300_link_hash_entry *entry; unsigned int byte_count = 0; entry = (struct elf32_mn10300_link_hash_entry *) gen_entry; /* If we already know we want to convert "call" to "calls" for calls to this symbol, then return now. */ if (entry->flags == MN10300_CONVERT_CALL_TO_CALLS) return true; /* If there are no named calls to this symbol, or there's nothing we can move from the function itself into the "call" instruction, then note that all "call" instructions should be converted into "calls" instructions and return. */ if (entry->direct_calls == 0 || (entry->stack_size == 0 && entry->movm_args == 0)) { /* Make a note that we should convert "call" instructions to "calls" instructions for calls to this symbol. */ entry->flags |= MN10300_CONVERT_CALL_TO_CALLS; return true; } /* We may be able to move some instructions from the function itself into the "call" instruction. Count how many bytes we might be able to eliminate in the function itself. */ /* A movm instruction is two bytes. */ if (entry->movm_args) byte_count += 2; /* Count the insn to allocate stack space too. */ if (entry->stack_size > 0 && entry->stack_size <= 128) byte_count += 3; else if (entry->stack_size > 0 && entry->stack_size < 256) byte_count += 4; /* If using "call" will result in larger code, then turn all the associated "call" instructions into "calls" instrutions. */ if (byte_count < entry->direct_calls) entry->flags |= MN10300_CONVERT_CALL_TO_CALLS; /* This routine never fails. */ return true;}/* This function handles relaxing for the mn10300. There's quite a few relaxing opportunites available on the mn10300: * calls:32 -> calls:16 2 bytes * call:32 -> call:16 2 bytes * call:32 -> calls:32 1 byte * call:16 -> calls:16 1 byte * These are done anytime using "calls" would result in smaller code, or when necessary to preserve the meaning of the program. * call:32 varies * call:16 * In some circumstances we can move instructions from a function prologue into a "call" instruction. This is only done if the resulting code is no larger than the original code. * jmp:32 -> jmp:16 2 bytes * jmp:16 -> bra:8 1 byte * If the previous instruction is a conditional branch around the jump/bra, we may be able to reverse its condition and change its target to the jump's target. The jump/bra can then be deleted. 2 bytes * mov abs32 -> mov abs16 1 or 2 bytes * Most instructions which accept imm32 can relax to imm16 1 or 2 bytes - Most instructions which accept imm16 can relax to imm8 1 or 2 bytes * Most instructions which accept d32 can relax to d16 1 or 2 bytes - Most instructions which accept d16 can relax to d8 1 or 2 bytes We don't handle imm16->imm8 or d16->d8 as they're very rare and somewhat more difficult to support. */static booleanmn10300_elf_relax_section (abfd, sec, link_info, again) bfd *abfd; asection *sec; struct bfd_link_info *link_info; boolean *again;{ Elf_Internal_Shdr *symtab_hdr; Elf_Internal_Rela *internal_relocs = NULL; Elf_Internal_Rela *free_relocs = NULL; Elf_Internal_Rela *irel, *irelend; bfd_byte *contents = NULL; bfd_byte *free_contents = NULL; Elf32_External_Sym *extsyms = NULL; Elf32_External_Sym *free_extsyms = NULL; struct elf32_mn10300_link_hash_table *hash_table; /* Assume nothing changes. */ *again = false; /* We need a pointer to the mn10300 specific hash table. */ hash_table = elf32_mn10300_hash_table (link_info); /* Initialize fields in each hash table entry the first time through. */ if ((hash_table->flags & MN10300_HASH_ENTRIES_INITIALIZED) == 0) { bfd *input_bfd; /* Iterate over all the input bfds. */ for (input_bfd = link_info->input_bfds; input_bfd != NULL; input_bfd = input_bfd->link_next) { asection *section; /* We're going to need all the symbols for each bfd. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; /* Get cached copy if it exists. */ if (symtab_hdr->contents != NULL) extsyms = (Elf32_External_Sym *) symtab_hdr->contents; else { /* Go get them off disk. */ extsyms = ((Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_size)); if (extsyms == NULL) goto error_return; free_extsyms = extsyms; if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 || (bfd_read (extsyms, 1, symtab_hdr->sh_size, input_bfd) != symtab_hdr->sh_size)) goto error_return; } /* Iterate over each section in this bfd. */ for (section = input_bfd->sections; section != NULL; section = section->next) { struct elf32_mn10300_link_hash_entry *hash; Elf_Internal_Sym *sym; asection *sym_sec = NULL; const char *sym_name; char *new_name; /* Get cached copy of section contents if it exists. */ if (elf_section_data (section)->this_hdr.contents != NULL) contents = elf_section_data (section)->this_hdr.contents; else if (section->_raw_size != 0) { /* Go get them off disk. */ contents = (bfd_byte *) bfd_malloc (section->_raw_size); if (contents == NULL) goto error_return; free_contents = contents; if (!bfd_get_section_contents (input_bfd, section, contents, (file_ptr) 0, section->_raw_size)) goto error_return; } else { contents = NULL; free_contents = NULL; } /* If there aren't any relocs, then there's nothing to do. */ if ((section->flags & SEC_RELOC) != 0 && section->reloc_count != 0) { /* Get a copy of the native relocations. */ internal_relocs = (_bfd_elf32_link_read_relocs (input_bfd, section, (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; /* Now examine each relocation. */ irel = internal_relocs; irelend = irel + section->reloc_count; for (; irel < irelend; irel++)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -