📄 elf32-avr.c
字号:
h = NULL; else h = sym_hashes[r_symndx - symtab_hdr->sh_info]; } return true;}/* Perform a single relocation. By default we use the standard BFD routines, but a few relocs, we have to do them ourselves. */static bfd_reloc_status_typeavr_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation) reloc_howto_type * howto; bfd * input_bfd; asection * input_section; bfd_byte * contents; Elf_Internal_Rela * rel; bfd_vma relocation;{ bfd_reloc_status_type r = bfd_reloc_ok; bfd_vma x; bfd_signed_vma srel; switch (howto->type) { case R_AVR_7_PCREL: contents += rel->r_offset; srel = (bfd_signed_vma) relocation; srel += rel->r_addend; srel -= rel->r_offset; srel -= 2; /* Branch instructions add 2 to the PC... */ srel -= (input_section->output_section->vma + input_section->output_offset); if (srel & 1) return bfd_reloc_outofrange; if (srel > ((1 << 7) - 1) || (srel < - (1 << 7))) return bfd_reloc_overflow; x = bfd_get_16 (input_bfd, contents); x = (x & 0xfc07) | (((srel >> 1) << 3) & 0x3f8); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_13_PCREL: contents += rel->r_offset; srel = (bfd_signed_vma) relocation; srel += rel->r_addend; srel -= rel->r_offset; srel -= 2; /* Branch instructions add 2 to the PC... */ srel -= (input_section->output_section->vma + input_section->output_offset); if (srel & 1) return bfd_reloc_outofrange; /* AVR addresses commands as words. */ srel >>= 1; /* Check for overflow. */ if (srel < -2048 || srel > 2047) { /* Apply WRAPAROUND if possible. */ switch (bfd_get_mach (input_bfd)) { case bfd_mach_avr2: case bfd_mach_avr4: break; default: return bfd_reloc_overflow; } } x = bfd_get_16 (input_bfd, contents); x = (x & 0xf000) | (srel & 0xfff); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_LO8_LDI: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_HI8_LDI: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; srel = (srel >> 8) & 0xff; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_HH8_LDI: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; srel = (srel >> 16) & 0xff; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_LO8_LDI_NEG: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; srel = -srel; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_HI8_LDI_NEG: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; srel = -srel; srel = (srel >> 8) & 0xff; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_HH8_LDI_NEG: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; srel = -srel; srel = (srel >> 16) & 0xff; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_LO8_LDI_PM: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; if (srel & 1) return bfd_reloc_outofrange; srel = srel >> 1; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_HI8_LDI_PM: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; if (srel & 1) return bfd_reloc_outofrange; srel = srel >> 1; srel = (srel >> 8) & 0xff; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_HH8_LDI_PM: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; if (srel & 1) return bfd_reloc_outofrange; srel = srel >> 1; srel = (srel >> 16) & 0xff; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_LO8_LDI_PM_NEG: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; srel = -srel; if (srel & 1) return bfd_reloc_outofrange; srel = srel >> 1; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_HI8_LDI_PM_NEG: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; srel = -srel; if (srel & 1) return bfd_reloc_outofrange; srel = srel >> 1; srel = (srel >> 8) & 0xff; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_HH8_LDI_PM_NEG: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; srel = -srel; if (srel & 1) return bfd_reloc_outofrange; srel = srel >> 1; srel = (srel >> 16) & 0xff; x = bfd_get_16 (input_bfd, contents); x = (x & 0xf0f0) | (srel & 0xf) | ((srel << 4) & 0xf00); bfd_put_16 (input_bfd, x, contents); break; case R_AVR_CALL: contents += rel->r_offset; srel = (bfd_signed_vma) relocation + rel->r_addend; if (srel & 1) return bfd_reloc_outofrange; srel = srel >> 1; x = bfd_get_16 (input_bfd, contents); x |= ((srel & 0x10000) | ((srel << 3) & 0x1f00000)) >> 16; bfd_put_16 (input_bfd, x, contents); bfd_put_16 (input_bfd, srel & 0xffff, contents+2); break; default: r = _bfd_final_link_relocate (howto, input_bfd, input_section, contents, rel->r_offset, relocation, rel->r_addend); } return r;}/* Relocate an AVR ELF section. */static booleanelf32_avr_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; struct elf_link_hash_entry ** sym_hashes; Elf_Internal_Rela * rel; Elf_Internal_Rela * relend; symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr; sym_hashes = elf_sym_hashes (input_bfd); relend = relocs + input_section->reloc_count; for (rel = relocs; rel < relend; rel ++) { reloc_howto_type * howto; unsigned long r_symndx; Elf_Internal_Sym * sym; asection * sec; struct elf_link_hash_entry * h; bfd_vma relocation; bfd_reloc_status_type r; const char * name = NULL; int r_type; r_type = ELF32_R_TYPE (rel->r_info); 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. */ 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. */ howto = elf_avr_howto_table + ELF32_R_TYPE (rel->r_info); 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); name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, sym->st_name); name = (name == NULL) ? bfd_section_name (input_bfd, sec) : name; } 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 elf_link_hash_entry *) h->root.u.i.link; 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; 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, rel->r_offset, true))) return false; relocation = 0; } } r = avr_final_link_relocate (howto, input_bfd, input_section, contents, rel, relocation); if (r != bfd_reloc_ok) { const char * msg = (const char *) NULL; switch (r) { case bfd_reloc_overflow: r = info->callbacks->reloc_overflow (info, name, howto->name, (bfd_vma) 0, input_bfd, input_section, rel->r_offset); break; case bfd_reloc_undefined: r = info->callbacks->undefined_symbol (info, name, input_bfd, input_section, rel->r_offset, true); break; case bfd_reloc_outofrange: msg = _("internal error: out of range error"); break; case bfd_reloc_notsupported: msg = _("internal error: unsupported relocation error"); break; case bfd_reloc_dangerous: msg = _("internal error: dangerous relocation"); break; default: msg = _("internal error: unknown error"); break; } if (msg) r = info->callbacks->warning (info, msg, name, input_bfd, input_section, rel->r_offset); if (! r) return false; } } return true;}/* The final processing done just before writing out a AVR ELF object file. This gets the AVR architecture right based on the machine number. */static voidbfd_elf_avr_final_write_processing (abfd, linker) bfd *abfd; boolean linker ATTRIBUTE_UNUSED;{ unsigned long val; switch (bfd_get_mach (abfd)) { default: case bfd_mach_avr2: val = E_AVR_MACH_AVR2; break; case bfd_mach_avr1: val = E_AVR_MACH_AVR1; break; case bfd_mach_avr3: val = E_AVR_MACH_AVR3; break; case bfd_mach_avr4: val = E_AVR_MACH_AVR4; break; case bfd_mach_avr5: val = E_AVR_MACH_AVR5; break; } elf_elfheader (abfd)->e_machine = EM_AVR; elf_elfheader (abfd)->e_flags &= ~ EF_AVR_MACH; elf_elfheader (abfd)->e_flags |= val;}/* Set the right machine number. */static booleanelf32_avr_object_p (abfd) bfd *abfd;{ int e_set = bfd_mach_avr2; if (elf_elfheader (abfd)->e_machine == EM_AVR) { int e_mach = elf_elfheader (abfd)->e_flags & EF_AVR_MACH; switch (e_mach) { default: case E_AVR_MACH_AVR2: e_set = bfd_mach_avr2; break; case E_AVR_MACH_AVR1: e_set = bfd_mach_avr1; break; case E_AVR_MACH_AVR3: e_set = bfd_mach_avr3; break; case E_AVR_MACH_AVR4: e_set = bfd_mach_avr4; break; case E_AVR_MACH_AVR5: e_set = bfd_mach_avr5; break; } } return bfd_default_set_arch_mach (abfd, bfd_arch_avr, e_set);}#define ELF_ARCH bfd_arch_avr#define ELF_MACHINE_CODE EM_AVR#define ELF_MAXPAGESIZE 1#define TARGET_LITTLE_SYM bfd_elf32_avr_vec#define TARGET_LITTLE_NAME "elf32-avr"#define elf_info_to_howto avr_info_to_howto_rela#define elf_info_to_howto_rel NULL#define elf_backend_relocate_section elf32_avr_relocate_section#define elf_backend_gc_mark_hook elf32_avr_gc_mark_hook#define elf_backend_gc_sweep_hook elf32_avr_gc_sweep_hook#define elf_backend_check_relocs elf32_avr_check_relocs#define elf_backend_can_gc_sections 1#define elf_backend_final_write_processing \ bfd_elf_avr_final_write_processing#define elf_backend_object_p elf32_avr_object_p#include "elf32-target.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -