📄 elf32-m32r.c
字号:
reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } /* Sanity check the address (offset in section). */ if (reloc_entry->address > input_section->_cooked_size) return bfd_reloc_outofrange; ret = bfd_reloc_ok; if (bfd_is_und_section (symbol->section) && output_bfd == (bfd *) NULL) ret = bfd_reloc_undefined; if (bfd_is_com_section (symbol->section)) relocation = 0; else relocation = symbol->value; relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; relocation += reloc_entry->addend; /* Save the information, and let LO16 do the actual relocation. */ n = (struct m32r_hi16 *) bfd_malloc (sizeof *n); if (n == NULL) return bfd_reloc_outofrange; n->addr = (bfd_byte *) data + reloc_entry->address; n->addend = relocation; n->next = m32r_hi16_list; m32r_hi16_list = n; if (output_bfd != (bfd *) NULL) reloc_entry->address += input_section->output_offset; return ret;}/* Handle an M32R ELF HI16 reloc. */static voidm32r_elf_relocate_hi16 (input_bfd, type, relhi, rello, contents, addend) bfd *input_bfd; int type; Elf_Internal_Rela *relhi; Elf_Internal_Rela *rello; bfd_byte *contents; bfd_vma addend;{ unsigned long insn; bfd_vma addlo; insn = bfd_get_32 (input_bfd, contents + relhi->r_offset); addlo = bfd_get_32 (input_bfd, contents + rello->r_offset); if (type == R_M32R_HI16_SLO) addlo = ((addlo & 0xffff) ^ 0x8000) - 0x8000; else addlo &= 0xffff; addend += ((insn & 0xffff) << 16) + addlo; /* Reaccount for sign extension of low part. */ if (type == R_M32R_HI16_SLO && (addend & 0x8000) != 0) addend += 0x10000; bfd_put_32 (input_bfd, (insn & 0xffff0000) | ((addend >> 16) & 0xffff), contents + relhi->r_offset);}/* Do an R_M32R_LO16 relocation. This is a straightforward 16 bit inplace relocation; this function exists in order to do the R_M32R_HI16_[SU]LO relocation described above. */bfd_reloc_status_typem32r_elf_lo16_reloc (input_bfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *input_bfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message;{ /* This part is from bfd_elf_generic_reloc. If we're relocating, and this an external symbol, we don't want to change anything. */ if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 && reloc_entry->addend == 0) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } if (m32r_hi16_list != NULL) { struct m32r_hi16 *l; l = m32r_hi16_list; while (l != NULL) { unsigned long insn; unsigned long val; unsigned long vallo; struct m32r_hi16 *next; /* Do the HI16 relocation. Note that we actually don't need to know anything about the LO16 itself, except where to find the low 16 bits of the addend needed by the LO16. */ insn = bfd_get_32 (input_bfd, l->addr); vallo = ((bfd_get_32 (input_bfd, (bfd_byte *) data + reloc_entry->address) & 0xffff) ^ 0x8000) - 0x8000; val = ((insn & 0xffff) << 16) + vallo; val += l->addend; /* Reaccount for sign extension of low part. */ if ((val & 0x8000) != 0) val += 0x10000; insn = (insn &~ 0xffff) | ((val >> 16) & 0xffff); bfd_put_32 (input_bfd, insn, l->addr); next = l->next; free (l); l = next; } m32r_hi16_list = NULL; } /* Now do the LO16 reloc in the usual way. ??? It would be nice to call bfd_elf_generic_reloc here, but we have partial_inplace == TRUE. bfd_elf_generic_reloc will pass the handling back to bfd_install_relocation which will install a section relative addend which is wrong. */ return m32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data, input_section, output_bfd, error_message);}/* Do generic partial_inplace relocation. This is a local replacement for bfd_elf_generic_reloc. */bfd_reloc_status_typem32r_elf_generic_reloc (input_bfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *input_bfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED;{ bfd_reloc_status_type ret; bfd_vma relocation; bfd_byte *inplace_address; /* This part is from bfd_elf_generic_reloc. If we're relocating, and this an external symbol, we don't want to change anything. */ if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 && reloc_entry->addend == 0) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } /* Now do the the reloc in the usual way. ??? It would be nice to call bfd_elf_generic_reloc here, but we have partial_inplace == TRUE. bfd_elf_generic_reloc will pass the handling back to bfd_install_relocation which will install a section relative addend which is wrong. */ /* Sanity check the address (offset in section). */ if (reloc_entry->address > input_section->_cooked_size) return bfd_reloc_outofrange; ret = bfd_reloc_ok; if (bfd_is_und_section (symbol->section) && output_bfd == (bfd *) NULL) ret = bfd_reloc_undefined; if (bfd_is_com_section (symbol->section) || output_bfd != (bfd *) NULL) relocation = 0; else relocation = symbol->value; /* Only do this for a final link. */ if (output_bfd == (bfd *) NULL) { relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; } relocation += reloc_entry->addend; inplace_address = (bfd_byte *) data + reloc_entry->address;#define DOIT(x) \ x = ( (x & ~reloc_entry->howto->dst_mask) | \ (((x & reloc_entry->howto->src_mask) + relocation) & \ reloc_entry->howto->dst_mask)) switch (reloc_entry->howto->size) { case 1: { short x = bfd_get_16 (input_bfd, inplace_address); DOIT (x); bfd_put_16 (input_bfd, x, inplace_address); } break; case 2: { unsigned long x = bfd_get_32 (input_bfd, inplace_address); DOIT (x); bfd_put_32 (input_bfd, x, inplace_address); } break; default: BFD_ASSERT (0); } if (output_bfd != (bfd *) NULL) reloc_entry->address += input_section->output_offset; return ret;}/* Handle the R_M32R_SDA16 reloc. This reloc is used to compute the address of objects in the small data area and to perform loads and stores from that area. The lower 16 bits are sign extended and added to the register specified in the instruction, which is assumed to point to _SDA_BASE_. */static bfd_reloc_status_typem32r_elf_sda16_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry; asymbol *symbol; PTR data ATTRIBUTE_UNUSED; asection *input_section; bfd *output_bfd; char **error_message ATTRIBUTE_UNUSED;{ /* This part is from bfd_elf_generic_reloc. */ if (output_bfd != (bfd *) NULL && (symbol->flags & BSF_SECTION_SYM) == 0 && (! reloc_entry->howto->partial_inplace || reloc_entry->addend == 0)) { reloc_entry->address += input_section->output_offset; return bfd_reloc_ok; } if (output_bfd != NULL) { /* FIXME: See bfd_perform_relocation. Is this right? */ return bfd_reloc_continue; } /* FIXME: not sure what to do here yet. But then again, the linker may never call us. */ abort ();}/* Map BFD reloc types to M32R ELF reloc types. */struct m32r_reloc_map{ bfd_reloc_code_real_type bfd_reloc_val; unsigned char elf_reloc_val;};static const struct m32r_reloc_map m32r_reloc_map[] ={ { BFD_RELOC_NONE, R_M32R_NONE }, { BFD_RELOC_16, R_M32R_16 }, { BFD_RELOC_32, R_M32R_32 }, { BFD_RELOC_M32R_24, R_M32R_24 }, { BFD_RELOC_M32R_10_PCREL, R_M32R_10_PCREL }, { BFD_RELOC_M32R_18_PCREL, R_M32R_18_PCREL }, { BFD_RELOC_M32R_26_PCREL, R_M32R_26_PCREL }, { BFD_RELOC_M32R_HI16_ULO, R_M32R_HI16_ULO }, { BFD_RELOC_M32R_HI16_SLO, R_M32R_HI16_SLO }, { BFD_RELOC_M32R_LO16, R_M32R_LO16 }, { BFD_RELOC_M32R_SDA16, R_M32R_SDA16 }, { BFD_RELOC_VTABLE_INHERIT, R_M32R_GNU_VTINHERIT }, { BFD_RELOC_VTABLE_ENTRY, R_M32R_GNU_VTENTRY },};static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup (abfd, code) bfd *abfd ATTRIBUTE_UNUSED; bfd_reloc_code_real_type code;{ unsigned int i; for (i = 0; i < sizeof (m32r_reloc_map) / sizeof (struct m32r_reloc_map); i++) { if (m32r_reloc_map[i].bfd_reloc_val == code) return &m32r_elf_howto_table[m32r_reloc_map[i].elf_reloc_val]; } return NULL;}/* Set the howto pointer for an M32R ELF reloc. */static voidm32r_info_to_howto_rel (abfd, cache_ptr, dst) bfd *abfd ATTRIBUTE_UNUSED; arelent *cache_ptr; Elf32_Internal_Rel *dst;{ unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); BFD_ASSERT (r_type < (unsigned int) R_M32R_max); cache_ptr->howto = &m32r_elf_howto_table[r_type];}/* Given a BFD section, try to locate the corresponding ELF section index. */boolean_bfd_m32r_elf_section_from_bfd_section (abfd, hdr, sec, retval) bfd *abfd ATTRIBUTE_UNUSED; Elf32_Internal_Shdr *hdr ATTRIBUTE_UNUSED; asection *sec; int *retval;{ if (strcmp (bfd_get_section_name (abfd, sec), ".scommon") == 0) { *retval = SHN_M32R_SCOMMON; return true; } return false;}/* M32R ELF uses two common sections. One is the usual one, and the other is for small objects. All the small objects are kept together, and then referenced via one register, which yields faster assembler code. It is up to the compiler to emit an instruction to load the register with _SDA_BASE. This is what we use for the small common section. This approach is copied from elf32-mips.c. */static asection m32r_elf_scom_section;static asymbol m32r_elf_scom_symbol;static asymbol *m32r_elf_scom_symbol_ptr;/* Handle the special M32R section numbers that a symbol may use. */void_bfd_m32r_elf_symbol_processing (abfd, asym) bfd *abfd ATTRIBUTE_UNUSED; asymbol *asym;{ elf_symbol_type *elfsym; elfsym = (elf_symbol_type *) asym; switch (elfsym->internal_elf_sym.st_shndx) { case SHN_M32R_SCOMMON: if (m32r_elf_scom_section.name == NULL) { /* Initialize the small common section. */ m32r_elf_scom_section.name = ".scommon"; m32r_elf_scom_section.flags = SEC_IS_COMMON; m32r_elf_scom_section.output_section = &m32r_elf_scom_section; m32r_elf_scom_section.symbol = &m32r_elf_scom_symbol; m32r_elf_scom_section.symbol_ptr_ptr = &m32r_elf_scom_symbol_ptr; m32r_elf_scom_symbol.name = ".scommon"; m32r_elf_scom_symbol.flags = BSF_SECTION_SYM; m32r_elf_scom_symbol.section = &m32r_elf_scom_section; m32r_elf_scom_symbol_ptr = &m32r_elf_scom_symbol; } asym->section = &m32r_elf_scom_section; asym->value = elfsym->internal_elf_sym.st_size; break; }}/* Hook called by the linker routine which adds symbols from an object file. We must handle the special M32R section numbers here. We also keep watching for whether we need to create the sdata special linker sections. */static booleanm32r_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; bfd_vma *valp;{ if (! info->relocateable && (*namep)[0] == '_' && (*namep)[1] == 'S' && strcmp (*namep, "_SDA_BASE_") == 0) { /* This is simpler than using _bfd_elf_create_linker_section (our needs are simpler than ppc's needs). Also _bfd_elf_create_linker_section currently has a bug where if a .sdata section already exists a new one is created that follows it which screws of _SDA_BASE_ address calcs because output_offset != 0. */ struct elf_link_hash_entry *h; asection *s = bfd_get_section_by_name (abfd, ".sdata"); /* The following code was cobbled from elf32-ppc.c and elflink.c. */ if (s == NULL) { int flags = (SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED); s = bfd_make_section_anyway (abfd, ".sdata"); if (s == NULL) return false;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -