📄 elf32-m32r.c
字号:
bfd_set_section_flags (abfd, s, flags); bfd_set_section_alignment (abfd, s, 2); } h = (struct elf_link_hash_entry *) bfd_link_hash_lookup (info->hash, "_SDA_BASE_", false, false, false); if ((h == NULL || h->root.type == bfd_link_hash_undefined) && !(_bfd_generic_link_add_one_symbol (info, abfd, "_SDA_BASE_", BSF_GLOBAL, s, 32768, (const char *) NULL, false, get_elf_backend_data (abfd)->collect, (struct bfd_link_hash_entry **) &h))) return false; h->type = STT_OBJECT; } switch (sym->st_shndx) { case SHN_M32R_SCOMMON: *secp = bfd_make_section_old_way (abfd, ".scommon"); (*secp)->flags |= SEC_IS_COMMON; *valp = sym->st_size; break; } return true;}/* We have to figure out the SDA_BASE value, so that we can adjust the symbol value correctly. We look up the symbol _SDA_BASE_ in the output BFD. If we can't find it, we're stuck. We cache it in the ELF target data. We don't need to adjust the symbol value for an external symbol if we are producing relocateable output. */static bfd_reloc_status_typem32r_elf_final_sda_base (output_bfd, info, error_message, psb) bfd *output_bfd; struct bfd_link_info *info; const char **error_message; bfd_vma *psb;{ if (elf_gp (output_bfd) == 0) { struct bfd_link_hash_entry *h; h = bfd_link_hash_lookup (info->hash, "_SDA_BASE_", false, false, true); if (h != (struct bfd_link_hash_entry *) NULL && h->type == bfd_link_hash_defined) elf_gp (output_bfd) = (h->u.def.value + h->u.def.section->output_section->vma + h->u.def.section->output_offset); else { /* Only get the error once. */ *psb = elf_gp (output_bfd) = 4; *error_message = (const char *) _("SDA relocation when _SDA_BASE_ not defined"); return bfd_reloc_dangerous; } } *psb = elf_gp (output_bfd); return bfd_reloc_ok;}/* Relocate an M32R/D ELF section. There is some attempt to make this function usable for many architectures, both USE_REL and USE_RELA ['twould be nice if such a critter existed], if only to serve as a learning tool. The RELOCATE_SECTION function is called by the new ELF backend linker to handle the relocations for a section. The relocs are always passed as Rela structures; if the section actually uses Rel structures, the r_addend field will always be zero. This function is responsible for adjust the section contents as necessary, and (if using Rela relocs and generating a relocateable output file) adjusting the reloc addend as necessary. This function does not have to worry about setting the reloc address or the reloc symbol index. LOCAL_SYMS is a pointer to the swapped in local symbols. LOCAL_SECTIONS is an array giving the section in the input file corresponding to the st_shndx field of each local symbol. The global hash table entry for the global symbols can be found via elf_sym_hashes (input_bfd). When generating relocateable output, this function must handle STB_LOCAL/STT_SECTION symbols specially. The output symbol is going to be the section symbol corresponding to the output section, which means that the addend must be adjusted accordingly. */static booleanm32r_elf_relocate_section (output_bfd, info, input_bfd, input_section, contents, relocs, local_syms, local_sections) bfd *output_bfd ATTRIBUTE_UNUSED; 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 = &elf_tdata (input_bfd)->symtab_hdr; struct elf_link_hash_entry **sym_hashes = elf_sym_hashes (input_bfd); Elf_Internal_Rela *rel, *relend; /* Assume success. */ boolean ret = true; rel = relocs; relend = relocs + input_section->reloc_count; for (; rel < relend; rel++) { int r_type; reloc_howto_type *howto; unsigned long r_symndx; /* We can't modify r_addend here as elf_link_input_bfd has an assert to ensure it's zero (we use REL relocs, not RELA). Therefore this should be assigning zero to `addend', but for clarity we use `r_addend'. */ bfd_vma addend = rel->r_addend; bfd_vma offset = rel->r_offset; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym; asection *sec; const char *sym_name; bfd_reloc_status_type r; const char *errmsg = NULL; h = NULL; r_type = ELF32_R_TYPE (rel->r_info); if (r_type < 0 || r_type >= (int) R_M32R_max) { (*_bfd_error_handler) (_("%s: unknown relocation type %d"), bfd_get_filename (input_bfd), (int) r_type); bfd_set_error (bfd_error_bad_value); ret = false; continue; } if (r_type == R_M32R_GNU_VTENTRY || r_type == R_M32R_GNU_VTINHERIT) continue; howto = m32r_elf_howto_table + r_type; r_symndx = ELF32_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. */ sec = NULL; if (r_symndx >= symtab_hdr->sh_info) { /* External symbol. */ continue; } /* Local symbol. */ sym = local_syms + r_symndx; sym_name = "<local symbol>"; /* STT_SECTION: symbol is associated with a section. */ if (ELF_ST_TYPE (sym->st_info) != STT_SECTION) { /* Symbol isn't associated with a section. Nothing to do. */ continue; } sec = local_sections[r_symndx]; addend += sec->output_offset + sym->st_value;#ifndef USE_REL /* This can't be done for USE_REL because it doesn't mean anything and elf_link_input_bfd asserts this stays zero. */ rel->r_addend = addend;#endif#ifndef USE_REL /* Addends are stored with relocs. We're done. */ continue;#else /* USE_REL */ /* If partial_inplace, we need to store any additional addend back in the section. */ if (! howto->partial_inplace) continue; /* ??? Here is a nice place to call a special_function like handler. */ if (r_type != R_M32R_HI16_SLO && r_type != R_M32R_HI16_ULO) r = _bfd_relocate_contents (howto, input_bfd, addend, contents + offset); else { Elf_Internal_Rela *lorel; /* We allow an arbitrary number of HI16 relocs before the LO16 reloc. This permits gcc to emit the HI and LO relocs itself. */ for (lorel = rel + 1; (lorel < relend && (ELF32_R_TYPE (lorel->r_info) == R_M32R_HI16_SLO || ELF32_R_TYPE (lorel->r_info) == R_M32R_HI16_ULO)); lorel++) continue; if (lorel < relend && ELF32_R_TYPE (lorel->r_info) == R_M32R_LO16) { m32r_elf_relocate_hi16 (input_bfd, r_type, rel, lorel, contents, addend); r = bfd_reloc_ok; } else r = _bfd_relocate_contents (howto, input_bfd, addend, contents + offset); }#endif /* USE_REL */ } else { bfd_vma relocation; /* This is a final link. */ sym = NULL; sec = NULL; if (r_symndx < symtab_hdr->sh_info) { /* Local symbol. */ sym = local_syms + r_symndx; sec = local_sections[r_symndx]; sym_name = "<local symbol>"; relocation = (sec->output_section->vma + sec->output_offset + sym->st_value); } else { /* External symbol. */ 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 elf_link_hash_entry *) h->root.u.i.link; sym_name = h->root.root.string; if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { sec = h->root.u.def.section; if (sec->output_section == NULL) relocation = 0; else relocation = (h->root.u.def.value + sec->output_section->vma + sec->output_offset); } 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, offset, true))) return false; relocation = 0; } } /* Sanity check the address. */ if (offset > input_section->_raw_size) { r = bfd_reloc_outofrange; goto check_reloc; } switch ((int) r_type) { case (int) R_M32R_10_PCREL : r = m32r_elf_do_10_pcrel_reloc (input_bfd, howto, input_section, contents, offset, sec, relocation, addend); break; case (int) R_M32R_HI16_SLO : case (int) R_M32R_HI16_ULO : { Elf_Internal_Rela *lorel; /* We allow an arbitrary number of HI16 relocs before the LO16 reloc. This permits gcc to emit the HI and LO relocs itself. */ for (lorel = rel + 1; (lorel < relend && (ELF32_R_TYPE (lorel->r_info) == R_M32R_HI16_SLO || ELF32_R_TYPE (lorel->r_info) == R_M32R_HI16_ULO)); lorel++) continue; if (lorel < relend && ELF32_R_TYPE (lorel->r_info) == R_M32R_LO16) { m32r_elf_relocate_hi16 (input_bfd, r_type, rel, lorel, contents, relocation + addend); r = bfd_reloc_ok; } else r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, offset, relocation, addend); } break; case (int) R_M32R_SDA16 : { const char *name; BFD_ASSERT (sec != NULL); name = bfd_get_section_name (abfd, sec); if (strcmp (name, ".sdata") == 0 || strcmp (name, ".sbss") == 0 || strcmp (name, ".scommon") == 0) { bfd_vma sda_base; bfd *out_bfd = sec->output_section->owner; r = m32r_elf_final_sda_base (out_bfd, info, &errmsg, &sda_base); if (r != bfd_reloc_ok) { ret = false; goto check_reloc; } /* At this point `relocation' contains the object's address. */ relocation -= sda_base; /* Now it contains the offset from _SDA_BASE_. */ } else { (*_bfd_error_handler) (_("%s: The target (%s) of an %s relocation is in the wrong section (%s)"), bfd_get_filename (input_bfd), sym_name, m32r_elf_howto_table[(int) r_type].name, bfd_get_section_name (abfd, sec)); /*bfd_set_error (bfd_error_bad_value); ??? why? */ ret = false; continue; } } /* fall through */ default : r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, offset, relocation, addend); break; } } check_reloc: if (r != bfd_reloc_ok) { /* FIXME: This should be generic enough to go in a utility. */ const char *name; if (h != NULL) name = h->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); } if (errmsg != NULL) goto common_error; switch (r) { case bfd_reloc_overflow: if (! ((*info->callbacks->reloc_overflow) (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section, offset))) return false; break; case bfd_reloc_undefined: if (! ((*info->callbacks->undefined_symbol) (info, name, input_bfd, input_section, offset, true))) return false; break; case bfd_reloc_outofrange: errmsg = _("internal error: out of range error"); goto common_error; case bfd_reloc_notsupported: errmsg = _("internal error: unsupported relocation error"); goto common_error; case bfd_reloc_dangerous: errmsg = _("internal error: dangerous error"); goto common_error; default: errmsg = _("internal error: unknown error"); /* fall through */ common_error:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -