📄 elf-m10300.c
字号:
/* Do nothing if this reloc is the last byte in the section. */ if (irel->r_offset == sec->_cooked_size) continue; /* See if the next instruction is an unconditional pc-relative branch, more often than not this test will fail, so we test it first to speed things up. */ code = bfd_get_8 (abfd, contents + irel->r_offset + 1); if (code != 0xca) continue; /* Also make sure the next relocation applies to the next instruction and that it's a pc-relative 8 bit branch. */ nrel = irel + 1; if (nrel == irelend || irel->r_offset + 2 != nrel->r_offset || ELF32_R_TYPE (nrel->r_info) != (int) R_MN10300_PCREL8) continue; /* Make sure our destination immediately follows the unconditional branch. */ if (symval != (sec->output_section->vma + sec->output_offset + irel->r_offset + 3)) continue; /* Now make sure we are a conditional branch. This may not be necessary, but why take the chance. Note these checks assume that R_MN10300_PCREL8 relocs only occur on bCC and bCCx insns. If they occured elsewhere, we'd need to know the start of this insn for this check to be accurate. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 1); if (code != 0xc0 && code != 0xc1 && code != 0xc2 && code != 0xc3 && code != 0xc4 && code != 0xc5 && code != 0xc6 && code != 0xc7 && code != 0xc8 && code != 0xc9 && code != 0xe8 && code != 0xe9 && code != 0xea && code != 0xeb) continue; /* We also have to be sure there is no symbol/label at the unconditional branch. */ if (mn10300_elf_symbol_address_p (abfd, sec, extsyms, irel->r_offset + 1)) continue; /* Note that we've changed the relocs, section contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; free_relocs = NULL; elf_section_data (sec)->this_hdr.contents = contents; free_contents = NULL; symtab_hdr->contents = (bfd_byte *) extsyms; free_extsyms = NULL; /* Reverse the condition of the first branch. */ switch (code) { case 0xc8: code = 0xc9; break; case 0xc9: code = 0xc8; break; case 0xc0: code = 0xc2; break; case 0xc2: code = 0xc0; break; case 0xc3: code = 0xc1; break; case 0xc1: code = 0xc3; break; case 0xc4: code = 0xc6; break; case 0xc6: code = 0xc4; break; case 0xc7: code = 0xc5; break; case 0xc5: code = 0xc7; break; case 0xe8: code = 0xe9; break; case 0x9d: code = 0xe8; break; case 0xea: code = 0xeb; break; case 0xeb: code = 0xea; break; } bfd_put_8 (abfd, code, contents + irel->r_offset - 1); /* Set the reloc type and symbol for the first branch from the second branch. */ irel->r_info = nrel->r_info; /* Make the reloc for the second branch a null reloc. */ nrel->r_info = ELF32_R_INFO (ELF32_R_SYM (nrel->r_info), R_MN10300_NONE); /* Delete two bytes of data. */ if (!mn10300_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 1, 2)) goto error_return; /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ *again = true; } /* Try to turn a 24 immediate, displacement or absolute address into a 8 immediate, displacement or absolute address. */ if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_24) { bfd_vma value = symval; value += irel->r_addend; /* See if the value will fit in 8 bits. */ if ((long) value < 0x7f && (long) value > -0x80) { unsigned char code; /* AM33 insns which have 24 operands are 6 bytes long and will have 0xfd as the first byte. */ /* Get the first opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 3); if (code == 0xfd) { /* Get the second opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 2); /* We can not relax 0x6b, 0x7b, 0x8b, 0x9b as no 24bit equivalent instructions exists. */ if (code != 0x6b && code != 0x7b && code != 0x8b && code != 0x9b && ((code & 0x0f) == 0x09 || (code & 0x0f) == 0x08 || (code & 0x0f) == 0x0a || (code & 0x0f) == 0x0b || (code & 0x0f) == 0x0e)) { /* Not safe if the high bit is on as relaxing may move the value out of high mem and thus not fit in a signed 8bit value. This is currently over conservative. */ if ((value & 0x80) == 0) { /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; free_relocs = NULL; elf_section_data (sec)->this_hdr.contents = contents; free_contents = NULL; symtab_hdr->contents = (bfd_byte *) extsyms; free_extsyms = NULL; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfb, contents + irel->r_offset - 3); bfd_put_8 (abfd, code, contents + irel->r_offset - 2); /* Fix the relocation's type. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_MN10300_8); /* Delete two bytes of data. */ if (!mn10300_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 1, 2)) goto error_return; /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ *again = true; break; } } } } } /* Try to turn a 32bit immediate, displacement or absolute address into a 16bit immediate, displacement or absolute address. */ if (ELF32_R_TYPE (irel->r_info) == (int) R_MN10300_32) { bfd_vma value = symval; value += irel->r_addend; /* See if the value will fit in 24 bits. We allow any 16bit match here. We prune those we can't handle below. */ if ((long) value < 0x7fffff && (long) value > -0x800000) { unsigned char code; /* AM33 insns which have 32bit operands are 7 bytes long and will have 0xfe as the first byte. */ /* Get the first opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 3); if (code == 0xfe) { /* Get the second opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 2); /* All the am33 32 -> 24 relaxing possibilities. */ /* We can not relax 0x6b, 0x7b, 0x8b, 0x9b as no 24bit equivalent instructions exists. */ if (code != 0x6b && code != 0x7b && code != 0x8b && code != 0x9b && ((code & 0x0f) == 0x09 || (code & 0x0f) == 0x08 || (code & 0x0f) == 0x0a || (code & 0x0f) == 0x0b || (code & 0x0f) == 0x0e)) { /* Not safe if the high bit is on as relaxing may move the value out of high mem and thus not fit in a signed 16bit value. This is currently over conservative. */ if ((value & 0x8000) == 0) { /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; free_relocs = NULL; elf_section_data (sec)->this_hdr.contents = contents; free_contents = NULL; symtab_hdr->contents = (bfd_byte *) extsyms; free_extsyms = NULL; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfd, contents + irel->r_offset - 3); bfd_put_8 (abfd, code, contents + irel->r_offset - 2); /* Fix the relocation's type. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_MN10300_24); /* Delete one byte of data. */ if (!mn10300_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 3, 1)) goto error_return; /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ *again = true; break; } } } } /* See if the value will fit in 16 bits. We allow any 16bit match here. We prune those we can't handle below. */ if ((long) value < 0x7fff && (long) value > -0x8000) { unsigned char code; /* Most insns which have 32bit operands are 6 bytes long; exceptions are pcrel insns and bit insns. We handle pcrel insns above. We don't bother trying to handle the bit insns here. The first byte of the remaining insns will be 0xfc. */ /* Get the first opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 2); if (code != 0xfc) continue; /* Get the second opcode. */ code = bfd_get_8 (abfd, contents + irel->r_offset - 1); if ((code & 0xf0) < 0x80) switch (code & 0xf0) { /* mov (d32,am),dn -> mov (d32,am),dn mov dm,(d32,am) -> mov dn,(d32,am) mov (d32,am),an -> mov (d32,am),an mov dm,(d32,am) -> mov dn,(d32,am) movbu (d32,am),dn -> movbu (d32,am),dn movbu dm,(d32,am) -> movbu dn,(d32,am) movhu (d32,am),dn -> movhu (d32,am),dn movhu dm,(d32,am) -> movhu dn,(d32,am) */ case 0x00: case 0x10: case 0x20: case 0x30: case 0x40: case 0x50: case 0x60: case 0x70: /* Not safe if the high bit is on as relaxing may move the value out of high mem and thus not fit in a signed 16bit value. */ if (code == 0xcc && (value & 0x8000)) continue; /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; free_relocs = NULL; elf_section_data (sec)->this_hdr.contents = contents; free_contents = NULL; symtab_hdr->contents = (bfd_byte *) extsyms; free_extsyms = NULL; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2); bfd_put_8 (abfd, code, contents + irel->r_offset - 1); /* Fix the relocation's type. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_MN10300_16); /* Delete two bytes of data. */ if (!mn10300_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 2, 2)) goto error_return; /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ *again = true; break; } else if ((code & 0xf0) == 0x80 || (code & 0xf0) == 0x90) switch (code & 0xf3) { /* mov dn,(abs32) -> mov dn,(abs16) movbu dn,(abs32) -> movbu dn,(abs16) movhu dn,(abs32) -> movhu dn,(abs16) */ case 0x81: case 0x82: case 0x83: /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; free_relocs = NULL; elf_section_data (sec)->this_hdr.contents = contents; free_contents = NULL; symtab_hdr->contents = (bfd_byte *) extsyms; free_extsyms = NULL; if ((code & 0xf3) == 0x81) code = 0x01 + (code & 0x0c); else if ((code & 0xf3) == 0x82) code = 0x02 + (code & 0x0c); else if ((code & 0xf3) == 0x83) code = 0x03 + (code & 0x0c); else abort (); /* Fix the opcode. */ bfd_put_8 (abfd, code, contents + irel->r_offset - 2); /* Fix the relocation's type. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_MN10300_16); /* The opcode got shorter too, so we have to fix the addend and offset too! */ irel->r_offset -= 1; /* Delete three bytes of data. */ if (!mn10300_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 1, 3)) goto error_return; /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ *again = true; break; /* mov am,(abs32) -> mov am,(abs16) mov am,(d32,sp) -> mov am,(d16,sp) mov dm,(d32,sp) -> mov dm,(d32,sp) movbu dm,(d32,sp) -> movbu dm,(d32,sp) movhu dm,(d32,sp) -> movhu dm,(d32,sp) */ case 0x80: case 0x90: case 0x91: case 0x92: case 0x93: /* sp-based offsets are zero-extended. */ if (code >= 0x90 && code <= 0x93 && (long)value < 0) continue; /* Note that we've changed the relocation contents, etc. */ elf_section_data (sec)->relocs = internal_relocs; free_relocs = NULL; elf_section_data (sec)->this_hdr.contents = contents; free_contents = NULL; symtab_hdr->contents = (bfd_byte *) extsyms; free_extsyms = NULL; /* Fix the opcode. */ bfd_put_8 (abfd, 0xfa, contents + irel->r_offset - 2); bfd_put_8 (abfd, code, contents + irel->r_offset - 1); /* Fix the relocation's type. */ irel->r_info = ELF32_R_INFO (ELF32_R_SYM (irel->r_info), R_MN10300_16); /* Delete two bytes of data. */ if (!mn10300_elf_relax_delete_bytes (abfd, sec, irel->r_offset + 2, 2)) goto error_return; /* That will change things, so, we should relax again. Note that this is not required, and it may be slow. */ *again = true; break; } else if ((code & 0xf0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -