📄 elf32-mips.c
字号:
2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_MIPS_CALL_HI16", /* name */ true, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ false), /* pcrel_offset */ /* Low 16 bits of displacement in global offset table. */ HOWTO (R_MIPS_CALL_LO16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_MIPS_CALL_LO16", /* name */ true, /* partial_inplace */ 0x0000ffff, /* src_mask */ 0x0000ffff, /* dst_mask */ false), /* pcrel_offset */ /* Section displacement. */ HOWTO (R_MIPS_SCN_DISP, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_MIPS_SCN_DISP", /* name */ false, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false), /* pcrel_offset */ EMPTY_HOWTO (R_MIPS_REL16), EMPTY_HOWTO (R_MIPS_ADD_IMMEDIATE), EMPTY_HOWTO (R_MIPS_PJUMP), EMPTY_HOWTO (R_MIPS_RELGOT), /* Protected jump conversion. This is an optimization hint. No relocation is required for correctness. */ HOWTO (R_MIPS_JALR, /* type */ 0, /* rightshift */ 0, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_MIPS_JALR", /* name */ false, /* partial_inplace */ 0x00000000, /* src_mask */ 0x00000000, /* dst_mask */ false), /* pcrel_offset */};/* The reloc used for BFD_RELOC_CTOR when doing a 64 bit link. This is a hack to make the linker think that we need 64 bit values. */static reloc_howto_type elf_mips_ctor64_howto = HOWTO (R_MIPS_64, /* type */ 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ mips32_64bit_reloc, /* special_function */ "R_MIPS_64", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false); /* pcrel_offset *//* The reloc used for the mips16 jump instruction. */static reloc_howto_type elf_mips16_jump_howto = HOWTO (R_MIPS16_26, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 26, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ /* This needs complex overflow detection, because the upper four bits must match the PC. */ mips16_jump_reloc, /* special_function */ "R_MIPS16_26", /* name */ true, /* partial_inplace */ 0x3ffffff, /* src_mask */ 0x3ffffff, /* dst_mask */ false); /* pcrel_offset *//* The reloc used for the mips16 gprel instruction. */static reloc_howto_type elf_mips16_gprel_howto = HOWTO (R_MIPS16_GPREL, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ mips16_gprel_reloc, /* special_function */ "R_MIPS16_GPREL", /* name */ true, /* partial_inplace */ 0x07ff001f, /* src_mask */ 0x07ff001f, /* dst_mask */ false); /* pcrel_offset *//* GNU extensions for embedded-pic. *//* High 16 bits of symbol value, pc-relative. */static reloc_howto_type elf_mips_gnu_rel_hi16 = HOWTO (R_MIPS_GNU_REL_HI16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ _bfd_mips_elf_hi16_reloc, /* special_function */ "R_MIPS_GNU_REL_HI16", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ true); /* pcrel_offset *//* Low 16 bits of symbol value, pc-relative. */static reloc_howto_type elf_mips_gnu_rel_lo16 = HOWTO (R_MIPS_GNU_REL_LO16, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ _bfd_mips_elf_lo16_reloc, /* special_function */ "R_MIPS_GNU_REL_LO16", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ true); /* pcrel_offset *//* 16 bit offset for pc-relative branches. */static reloc_howto_type elf_mips_gnu_rel16_s2 = HOWTO (R_MIPS_GNU_REL16_S2, /* type */ 2, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_MIPS_GNU_REL16_S2", /* name */ true, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ true); /* pcrel_offset *//* 64 bit pc-relative. */static reloc_howto_type elf_mips_gnu_pcrel64 = HOWTO (R_MIPS_PC64, /* type */ 0, /* rightshift */ 4, /* size (0 = byte, 1 = short, 2 = long) */ 64, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_MIPS_PC64", /* name */ true, /* partial_inplace */ MINUS_ONE, /* src_mask */ MINUS_ONE, /* dst_mask */ true); /* pcrel_offset *//* 32 bit pc-relative. */static reloc_howto_type elf_mips_gnu_pcrel32 = HOWTO (R_MIPS_PC32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_signed, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_MIPS_PC32", /* name */ true, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ true); /* pcrel_offset *//* GNU extension to record C++ vtable hierarchy */static reloc_howto_type elf_mips_gnu_vtinherit_howto = HOWTO (R_MIPS_GNU_VTINHERIT, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ NULL, /* special_function */ "R_MIPS_GNU_VTINHERIT", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false); /* pcrel_offset *//* GNU extension to record C++ vtable member usage */static reloc_howto_type elf_mips_gnu_vtentry_howto = HOWTO (R_MIPS_GNU_VTENTRY, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 0, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ _bfd_elf_rel_vtable_reloc_fn, /* special_function */ "R_MIPS_GNU_VTENTRY", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false); /* pcrel_offset *//* Do a R_MIPS_HI16 relocation. This has to be done in combination with a R_MIPS_LO16 reloc, because there is a carry from the LO16 to the HI16. Here we just save the information we need; we do the actual relocation when we see the LO16. MIPS ELF requires that the LO16 immediately follow the HI16. As a GNU extension, we permit an arbitrary number of HI16 relocs to be associated with a single LO16 reloc. This extension permits gcc to output the HI and LO relocs itself. */struct mips_hi16{ struct mips_hi16 *next; bfd_byte *addr; bfd_vma addend;};/* FIXME: This should not be a static variable. */static struct mips_hi16 *mips_hi16_list;bfd_reloc_status_type_bfd_mips_elf_hi16_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd ATTRIBUTE_UNUSED; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message;{ bfd_reloc_status_type ret; bfd_vma relocation; struct mips_hi16 *n; /* 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; } ret = bfd_reloc_ok; if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0) { boolean relocateable; bfd_vma gp; if (ret == bfd_reloc_undefined) abort (); if (output_bfd != NULL) relocateable = true; else { relocateable = false; output_bfd = symbol->section->output_section->owner; } ret = mips_elf_final_gp (output_bfd, symbol, relocateable, error_message, &gp); if (ret != bfd_reloc_ok) return ret; relocation = gp - reloc_entry->address; } else { 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; if (reloc_entry->address > input_section->_cooked_size) return bfd_reloc_outofrange; /* Save the information, and let LO16 do the actual relocation. */ n = (struct mips_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 = mips_hi16_list; mips_hi16_list = n; if (output_bfd != (bfd *) NULL) reloc_entry->address += input_section->output_offset; return ret;}/* Do a R_MIPS_LO16 relocation. This is a straightforward 16 bit inplace relocation; this function exists in order to do the R_MIPS_HI16 relocation described above. */bfd_reloc_status_type_bfd_mips_elf_lo16_reloc (abfd, reloc_entry, symbol, data, input_section, output_bfd, error_message) bfd *abfd; arelent *reloc_entry; asymbol *symbol; PTR data; asection *input_section; bfd *output_bfd; char **error_message;{ arelent gp_disp_relent; if (mips_hi16_list != NULL) { struct mips_hi16 *l; l = mips_hi16_list; while (l != NULL) { unsigned long insn; unsigned long val; unsigned long vallo; struct mips_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 (abfd, l->addr); vallo = (bfd_get_32 (abfd, (bfd_byte *) data + reloc_entry->address) & 0xffff); val = ((insn & 0xffff) << 16) + vallo; val += l->addend; /* The low order 16 bits are always treated as a signed value. Therefore, a negative value in the low order bits requires an adjustment in the high order bits. We need to make this adjustment in two ways: once for the bits we took from the data, and once for the bits we are putting back in to the data. */ if ((vallo & 0x8000) != 0) val -= 0x10000; if ((val & 0x8000) != 0) val += 0x10000; insn = (insn & ~0xffff) | ((val >> 16) & 0xffff); bfd_put_32 (abfd, insn, l->addr); if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0) { gp_disp_relent = *reloc_entry; reloc_entry = &gp_disp_relent; reloc_entry->addend = l->addend; } next = l->next; free (l); l = next; } mips_hi16_list = NULL; } else if (strcmp (bfd_asymbol_name (symbol), "_gp_disp") == 0) { bfd_reloc_status_type ret; bfd_vma gp, relocation; /* FIXME: Does this case ever occur? */ ret = mips_elf_final_gp (output_bfd, symbol, true, error_message, &gp); if (ret != bfd_reloc_ok) return ret; relocation = gp - reloc_entry->address; relocation += symbol->section->output_section->vma; relocation += symbol->section->output_offset; relocation += reloc_entry->addend; if (reloc_entry->address > input_section->_cooked_size) return bfd_reloc_outofrange; gp_disp_relent = *reloc_entry; reloc_entry = &gp_disp_relent;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -