📄 elf32-avr.c
字号:
/* AVR-specific support for 32-bit ELF Copyright 1999, 2000 Free Software Foundation, Inc. Contributed by Denis Chertykov <denisc@overta.ru>This file is part of BFD, the Binary File Descriptor library.This program is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe Free Software Foundation; either version 2 of the License, or(at your option) any later version.This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free SoftwareFoundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include "bfd.h"#include "sysdep.h"#include "libbfd.h"#include "elf-bfd.h"#include "elf/avr.h"static reloc_howto_type *bfd_elf32_bfd_reloc_type_lookup PARAMS ((bfd *abfd, bfd_reloc_code_real_type code));static void avr_info_to_howto_rela PARAMS ((bfd *, arelent *, Elf32_Internal_Rela *));static asection *elf32_avr_gc_mark_hook PARAMS ((bfd *, struct bfd_link_info *, Elf_Internal_Rela *, struct elf_link_hash_entry *, Elf_Internal_Sym *));static boolean elf32_avr_gc_sweep_hook PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));static boolean elf32_avr_check_relocs PARAMS ((bfd *, struct bfd_link_info *, asection *, const Elf_Internal_Rela *));static bfd_reloc_status_type avr_final_link_relocate PARAMS ((reloc_howto_type *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, bfd_vma));static boolean elf32_avr_relocate_section PARAMS ((bfd *, struct bfd_link_info *, bfd *, asection *, bfd_byte *, Elf_Internal_Rela *, Elf_Internal_Sym *, asection **));static void bfd_elf_avr_final_write_processing PARAMS ((bfd *, boolean));static boolean elf32_avr_object_p PARAMS ((bfd *));/* Use RELA instead of REL */#undef USE_RELstatic reloc_howto_type elf_avr_howto_table[] ={ HOWTO (R_AVR_NONE, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_NONE", /* name */ false, /* partial_inplace */ 0, /* src_mask */ 0, /* dst_mask */ false), /* pcrel_offset */ HOWTO (R_AVR_32, /* type */ 0, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 32, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_32", /* name */ false, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false), /* pcrel_offset */ /* A 7 bit PC relative relocation. */ HOWTO (R_AVR_7_PCREL, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 7, /* bitsize */ true, /* pc_relative */ 3, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_7_PCREL", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ true), /* pcrel_offset */ /* A 13 bit PC relative relocation. */ HOWTO (R_AVR_13_PCREL, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 13, /* bitsize */ true, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_13_PCREL", /* name */ false, /* partial_inplace */ 0xfff, /* src_mask */ 0xfff, /* dst_mask */ true), /* pcrel_offset */ /* A 16 bit absolute relocation. */ HOWTO (R_AVR_16, /* type */ 0, /* rightshift */ 1, /* 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_AVR_16", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A 16 bit absolute relocation for command address. */ HOWTO (R_AVR_16_PM, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 16, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_bitfield, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_16_PM", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A low 8 bit absolute relocation of 16 bit address. For LDI command. */ HOWTO (R_AVR_LO8_LDI, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_LO8_LDI", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A high 8 bit absolute relocation of 16 bit address. For LDI command. */ HOWTO (R_AVR_HI8_LDI, /* type */ 8, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_HI8_LDI", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A high 6 bit absolute relocation of 22 bit address. For LDI command. */ HOWTO (R_AVR_HH8_LDI, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_HH8_LDI", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A negative low 8 bit absolute relocation of 16 bit address. For LDI command. */ HOWTO (R_AVR_LO8_LDI_NEG, /* type */ 0, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_LO8_LDI_NEG", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A hegative high 8 bit absolute relocation of 16 bit address. For LDI command. */ HOWTO (R_AVR_HI8_LDI_NEG, /* type */ 8, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_HI8_LDI_NEG", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A hegative high 6 bit absolute relocation of 22 bit address. For LDI command. */ HOWTO (R_AVR_HH8_LDI_NEG, /* type */ 16, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_HH8_LDI_NEG", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A low 8 bit absolute relocation of 24 bit program memory address. For LDI command. */ HOWTO (R_AVR_LO8_LDI_PM, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_LO8_LDI_PM", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A high 8 bit absolute relocation of 16 bit program memory address. For LDI command. */ HOWTO (R_AVR_HI8_LDI_PM, /* type */ 9, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_HI8_LDI_PM", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A high 8 bit absolute relocation of 24 bit program memory address. For LDI command. */ HOWTO (R_AVR_HH8_LDI_PM, /* type */ 17, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_HH8_LDI_PM", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A low 8 bit absolute relocation of a negative 24 bit program memory address. For LDI command. */ HOWTO (R_AVR_LO8_LDI_PM_NEG, /* type */ 1, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_LO8_LDI_PM_NEG", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A high 8 bit absolute relocation of a negative 16 bit program memory address. For LDI command. */ HOWTO (R_AVR_HI8_LDI_PM_NEG, /* type */ 9, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_HI8_LDI_PM_NEG", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* A high 8 bit absolute relocation of a negative 24 bit program memory address. For LDI command. */ HOWTO (R_AVR_HH8_LDI_PM_NEG, /* type */ 17, /* rightshift */ 1, /* size (0 = byte, 1 = short, 2 = long) */ 8, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_HH8_LDI_PM_NEG", /* name */ false, /* partial_inplace */ 0xffff, /* src_mask */ 0xffff, /* dst_mask */ false), /* pcrel_offset */ /* Relocation for CALL command in ATmega. */ HOWTO (R_AVR_CALL, /* type */ 1, /* rightshift */ 2, /* size (0 = byte, 1 = short, 2 = long) */ 23, /* bitsize */ false, /* pc_relative */ 0, /* bitpos */ complain_overflow_dont, /* complain_on_overflow */ bfd_elf_generic_reloc, /* special_function */ "R_AVR_CALL", /* name */ false, /* partial_inplace */ 0xffffffff, /* src_mask */ 0xffffffff, /* dst_mask */ false) /* pcrel_offset */};/* Map BFD reloc types to AVR ELF reloc types. */struct avr_reloc_map{ bfd_reloc_code_real_type bfd_reloc_val; unsigned int elf_reloc_val;}; static const struct avr_reloc_map avr_reloc_map[] ={ { BFD_RELOC_NONE, R_AVR_NONE }, { BFD_RELOC_32, R_AVR_32 }, { BFD_RELOC_AVR_7_PCREL, R_AVR_7_PCREL }, { BFD_RELOC_AVR_13_PCREL, R_AVR_13_PCREL }, { BFD_RELOC_16, R_AVR_16 }, { BFD_RELOC_AVR_16_PM, R_AVR_16_PM }, { BFD_RELOC_AVR_LO8_LDI, R_AVR_LO8_LDI}, { BFD_RELOC_AVR_HI8_LDI, R_AVR_HI8_LDI }, { BFD_RELOC_AVR_HH8_LDI, R_AVR_HH8_LDI }, { BFD_RELOC_AVR_LO8_LDI_NEG, R_AVR_LO8_LDI_NEG }, { BFD_RELOC_AVR_HI8_LDI_NEG, R_AVR_HI8_LDI_NEG }, { BFD_RELOC_AVR_HH8_LDI_NEG, R_AVR_HH8_LDI_NEG }, { BFD_RELOC_AVR_LO8_LDI_PM, R_AVR_LO8_LDI_PM }, { BFD_RELOC_AVR_HI8_LDI_PM, R_AVR_HI8_LDI_PM }, { BFD_RELOC_AVR_HH8_LDI_PM, R_AVR_HH8_LDI_PM }, { BFD_RELOC_AVR_LO8_LDI_PM_NEG, R_AVR_LO8_LDI_PM_NEG }, { BFD_RELOC_AVR_HI8_LDI_PM_NEG, R_AVR_HI8_LDI_PM_NEG }, { BFD_RELOC_AVR_HH8_LDI_PM_NEG, R_AVR_HH8_LDI_PM_NEG }, { BFD_RELOC_AVR_CALL, R_AVR_CALL }};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 (avr_reloc_map) / sizeof (struct avr_reloc_map); i++) { if (avr_reloc_map[i].bfd_reloc_val == code) return &elf_avr_howto_table[avr_reloc_map[i].elf_reloc_val]; } return NULL;}/* Set the howto pointer for an AVR ELF reloc. */static voidavr_info_to_howto_rela (abfd, cache_ptr, dst) bfd *abfd ATTRIBUTE_UNUSED; arelent *cache_ptr; Elf32_Internal_Rela *dst;{ unsigned int r_type; r_type = ELF32_R_TYPE (dst->r_info); BFD_ASSERT (r_type < (unsigned int) R_AVR_max); cache_ptr->howto = &elf_avr_howto_table[r_type];}static asection *elf32_avr_gc_mark_hook (abfd, info, rel, h, sym) bfd *abfd; struct bfd_link_info *info ATTRIBUTE_UNUSED; Elf_Internal_Rela *rel; struct elf_link_hash_entry *h; Elf_Internal_Sym *sym;{ if (h != NULL) { switch (ELF32_R_TYPE (rel->r_info)) { default: switch (h->root.type) { case bfd_link_hash_defined: case bfd_link_hash_defweak: return h->root.u.def.section; case bfd_link_hash_common: return h->root.u.c.p->section; default: break; } } } else { if (!(elf_bad_symtab (abfd) && ELF_ST_BIND (sym->st_info) != STB_LOCAL) && !((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE) && sym->st_shndx != SHN_COMMON)) { return bfd_section_from_elf_index (abfd, sym->st_shndx); } } return NULL;}static booleanelf32_avr_gc_sweep_hook (abfd, info, sec, relocs) bfd *abfd ATTRIBUTE_UNUSED; struct bfd_link_info *info ATTRIBUTE_UNUSED; asection *sec ATTRIBUTE_UNUSED; const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED;{ /* We don't use got and plt entries for avr. */ return true;}/* Look through the relocs for a section during the first phase. Since we don't do .gots or .plts, we just need to consider the virtual table relocs for gc. */static booleanelf32_avr_check_relocs (abfd, info, sec, relocs) bfd *abfd; struct bfd_link_info *info; asection *sec; const Elf_Internal_Rela *relocs;{ Elf_Internal_Shdr *symtab_hdr; struct elf_link_hash_entry **sym_hashes, **sym_hashes_end; const Elf_Internal_Rela *rel; const Elf_Internal_Rela *rel_end; if (info->relocateable) return true; symtab_hdr = &elf_tdata (abfd)->symtab_hdr; sym_hashes = elf_sym_hashes (abfd); sym_hashes_end = sym_hashes + symtab_hdr->sh_size/sizeof (Elf32_External_Sym); if (!elf_bad_symtab (abfd)) sym_hashes_end -= symtab_hdr->sh_info; rel_end = relocs + sec->reloc_count; for (rel = relocs; rel < rel_end; rel++) { struct elf_link_hash_entry *h; unsigned long r_symndx; r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx < symtab_hdr->sh_info)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -