📄 coff-arm.c
字号:
BFD_ASSERT (tmp_name); sprintf (tmp_name, ARM2THUMB_GLUE_ENTRY_NAME, name); myh = coff_link_hash_lookup (coff_hash_table (info), tmp_name, false, false, true); if (myh != NULL) { free (tmp_name); return; /* we've already seen this guy */ } /* The only trick here is using globals->arm_glue_size as the value. Even though the section isn't allocated yet, this is where we will be putting it. */ bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name, BSF_GLOBAL, s, globals->arm_glue_size + 1, NULL, true, false, (struct bfd_link_hash_entry **) & myh); free (tmp_name); globals->arm_glue_size += ARM2THUMB_GLUE_SIZE; return;}static voidrecord_thumb_to_arm_glue (info, h) struct bfd_link_info * info; struct coff_link_hash_entry * h;{ const char * name = h->root.root.string; register asection * s; char * tmp_name; struct coff_link_hash_entry * myh; struct coff_arm_link_hash_table * globals; globals = coff_arm_hash_table (info); BFD_ASSERT (globals != NULL); BFD_ASSERT (globals->bfd_of_glue_owner != NULL); s = bfd_get_section_by_name (globals->bfd_of_glue_owner, THUMB2ARM_GLUE_SECTION_NAME); BFD_ASSERT (s != NULL); tmp_name = (char *) bfd_malloc (strlen (name) + strlen (THUMB2ARM_GLUE_ENTRY_NAME) + 1); BFD_ASSERT (tmp_name); sprintf (tmp_name, THUMB2ARM_GLUE_ENTRY_NAME, name); myh = coff_link_hash_lookup (coff_hash_table (info), tmp_name, false, false, true); if (myh != NULL) { free (tmp_name); return; /* we've already seen this guy */ } bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name, BSF_GLOBAL, s, globals->thumb_glue_size + 1, NULL, true, false, (struct bfd_link_hash_entry **) & myh); /* If we mark it 'thumb', the disassembler will do a better job. */ myh->class = C_THUMBEXTFUNC; free (tmp_name); /* Allocate another symbol to mark where we switch to arm mode. */#define CHANGE_TO_ARM "__%s_change_to_arm"#define BACK_FROM_ARM "__%s_back_from_arm" tmp_name = (char *) bfd_malloc (strlen (name) + strlen (CHANGE_TO_ARM) + 1); BFD_ASSERT (tmp_name); sprintf (tmp_name, globals->support_old_code ? BACK_FROM_ARM : CHANGE_TO_ARM, name); myh = NULL; bfd_coff_link_add_one_symbol (info, globals->bfd_of_glue_owner, tmp_name, BSF_LOCAL, s, globals->thumb_glue_size + (globals->support_old_code ? 8 : 4), NULL, true, false, (struct bfd_link_hash_entry **) & myh); free (tmp_name); globals->thumb_glue_size += THUMB2ARM_GLUE_SIZE; return;}/* Select a BFD to be used to hold the sections used by the glue code. This function is called from the linker scripts in ld/emultempl/ {armcoff/pe}.em */booleanbfd_arm_get_bfd_for_interworking (abfd, info) bfd * abfd; struct bfd_link_info * info;{ struct coff_arm_link_hash_table * globals; flagword flags; asection * sec; /* If we are only performing a partial link do not bother getting a bfd to hold the glue. */ if (info->relocateable) return true; globals = coff_arm_hash_table (info); BFD_ASSERT (globals != NULL); if (globals->bfd_of_glue_owner != NULL) return true; sec = bfd_get_section_by_name (abfd, ARM2THUMB_GLUE_SECTION_NAME); if (sec == NULL) { flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY; sec = bfd_make_section (abfd, ARM2THUMB_GLUE_SECTION_NAME); if (sec == NULL || ! bfd_set_section_flags (abfd, sec, flags) || ! bfd_set_section_alignment (abfd, sec, 2)) return false; } sec = bfd_get_section_by_name (abfd, THUMB2ARM_GLUE_SECTION_NAME); if (sec == NULL) { flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_CODE | SEC_READONLY; sec = bfd_make_section (abfd, THUMB2ARM_GLUE_SECTION_NAME); if (sec == NULL || ! bfd_set_section_flags (abfd, sec, flags) || ! bfd_set_section_alignment (abfd, sec, 2)) return false; } /* Save the bfd for later use. */ globals->bfd_of_glue_owner = abfd; return true;}booleanbfd_arm_process_before_allocation (abfd, info, support_old_code) bfd * abfd; struct bfd_link_info * info; int support_old_code;{ asection * sec; struct coff_arm_link_hash_table * globals; /* If we are only performing a partial link do not bother to construct any glue. */ if (info->relocateable) return true; /* Here we have a bfd that is to be included on the link. We have a hook to do reloc rummaging, before section sizes are nailed down. */ _bfd_coff_get_external_symbols (abfd); globals = coff_arm_hash_table (info); BFD_ASSERT (globals != NULL); BFD_ASSERT (globals->bfd_of_glue_owner != NULL); globals->support_old_code = support_old_code; /* Rummage around all the relocs and map the glue vectors. */ sec = abfd->sections; if (sec == NULL) return true; for (; sec != NULL; sec = sec->next) { struct internal_reloc * i; struct internal_reloc * rel; if (sec->reloc_count == 0) continue; /* Load the relocs. */ /* FIXME: there may be a storage leak here. */ i = _bfd_coff_read_internal_relocs (abfd, sec, 1, 0, 0, 0); BFD_ASSERT (i != 0); for (rel = i; rel < i + sec->reloc_count; ++rel) { unsigned short r_type = rel->r_type; long symndx; struct coff_link_hash_entry * h; symndx = rel->r_symndx; /* If the relocation is not against a symbol it cannot concern us. */ if (symndx == -1) continue; /* If the index is outside of the range of our table, something has gone wrong. */ if (symndx >= obj_conv_table_size (abfd)) { _bfd_error_handler (_("%s: illegal symbol index in reloc: %d"), bfd_get_filename (abfd), symndx); continue; } h = obj_coff_sym_hashes (abfd)[symndx]; /* If the relocation is against a static symbol it must be within the current section and so cannot be a cross ARM/Thumb relocation. */ if (h == NULL) continue; switch (r_type) { case ARM_26: /* This one is a call from arm code. We need to look up the target of the call. If it is a thumb target, we insert glue. */ if (h->class == C_THUMBEXTFUNC) record_arm_to_thumb_glue (info, h); break;#ifndef ARM_WINCE case ARM_THUMB23: /* This one is a call from thumb code. We used to look for ARM_THUMB9 and ARM_THUMB12 as well. We need to look up the target of the call. If it is an arm target, we insert glue. If the symbol does not exist it will be given a class of C_EXT and so we will generate a stub for it. This is not really a problem, since the link is doomed anyway. */ switch (h->class) { case C_EXT: case C_STAT: case C_LABEL: record_thumb_to_arm_glue (info, h); break; default: ; } break;#endif default: break; } } } return true;}#endif /* ! defined (COFF_IMAGE_WITH_PE) */#define coff_bfd_reloc_type_lookup coff_arm_reloc_type_lookup#define coff_relocate_section coff_arm_relocate_section#define coff_bfd_is_local_label_name coff_arm_is_local_label_name#define coff_adjust_symndx coff_arm_adjust_symndx#define coff_link_output_has_begun coff_arm_link_output_has_begun#define coff_final_link_postscript coff_arm_final_link_postscript#define coff_bfd_merge_private_bfd_data coff_arm_merge_private_bfd_data#define coff_bfd_print_private_bfd_data coff_arm_print_private_bfd_data#define coff_bfd_set_private_flags _bfd_coff_arm_set_private_flags#define coff_bfd_copy_private_bfd_data coff_arm_copy_private_bfd_data#define coff_bfd_link_hash_table_create coff_arm_link_hash_table_create/* When doing a relocateable link, we want to convert ARM26 relocs into ARM26D relocs. */static booleancoff_arm_adjust_symndx (obfd, info, ibfd, sec, irel, adjustedp) bfd *obfd ATTRIBUTE_UNUSED; struct bfd_link_info *info ATTRIBUTE_UNUSED; bfd *ibfd; asection *sec; struct internal_reloc *irel; boolean *adjustedp;{ if (irel->r_type == 3) { struct coff_link_hash_entry *h; h = obj_coff_sym_hashes (ibfd)[irel->r_symndx]; if (h != NULL && (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) && h->root.u.def.section->output_section == sec->output_section) irel->r_type = 7; } *adjustedp = false; return true;}/* Called when merging the private data areas of two BFDs. This is important as it allows us to detect if we are attempting to merge binaries compiled for different ARM targets, eg different CPUs or differents APCS's. */static booleancoff_arm_merge_private_bfd_data (ibfd, obfd) bfd * ibfd; bfd * obfd;{ BFD_ASSERT (ibfd != NULL && obfd != NULL); if (ibfd == obfd) return true; /* If the two formats are different we cannot merge anything. This is not an error, since it is permissable to change the input and output formats. */ if ( ibfd->xvec->flavour != bfd_target_coff_flavour || obfd->xvec->flavour != bfd_target_coff_flavour) return true; /* Verify that the APCS is the same for the two BFDs */ if (APCS_SET (ibfd)) { if (APCS_SET (obfd)) { /* If the src and dest have different APCS flag bits set, fail. */ if (APCS_26_FLAG (obfd) != APCS_26_FLAG (ibfd)) { _bfd_error_handler /* xgettext: c-format */ (_("%s: ERROR: compiled for APCS-%d whereas target %s uses APCS-%d"), bfd_get_filename (ibfd), APCS_26_FLAG (ibfd) ? 26 : 32, bfd_get_filename (obfd), APCS_26_FLAG (obfd) ? 26 : 32 ); bfd_set_error (bfd_error_wrong_format); return false; } if (APCS_FLOAT_FLAG (obfd) != APCS_FLOAT_FLAG (ibfd)) { const char *msg; if (APCS_FLOAT_FLAG (ibfd)) /* xgettext: c-format */ msg = _("%s: ERROR: passes floats in float registers whereas target %s uses integer registers"); else /* xgettext: c-format */ msg = _("%s: ERROR: passes floats in integer registers whereas target %s uses float registers"); _bfd_error_handler (msg, bfd_get_filename (ibfd), bfd_get_filename (obfd)); bfd_set_error (bfd_error_wrong_format); return false; } if (PIC_FLAG (obfd) != PIC_FLAG (ibfd)) { const char * msg; if (PIC_FLAG (ibfd)) /* xgettext: c-format */ msg = _("%s: ERROR: compiled as position independent code, whereas target %s is absolute position"); else /* xgettext: c-format */ msg = _("%s: ERROR: compiled as absolute position code, whereas target %s is position independent"); _bfd_error_handler (msg, bfd_get_filename (ibfd), bfd_get_filename (obfd)); bfd_set_error (bfd_error_wrong_format); return false; } } else { SET_APCS_FLAGS (obfd, APCS_26_FLAG (ibfd) | APCS_FLOAT_FLAG (ibfd) | PIC_FLAG (ibfd)); /* Set up the arch and fields as well as these are probably wrong. */ bfd_set_arch_mach (obfd, bfd_get_arch (ibfd), bfd_get_mach (ibfd)); } } /* Check the interworking support. */ if (INTERWORK_SET (ibfd)) { if (INTERWORK_SET (obfd)) { /* If the src and dest differ in their interworking issue a warning. */ if (INTERWORK_FLAG (obfd) != INTERWORK_FLAG (ibfd)) { const char * msg; if (INTERWORK_FLAG (ibfd)) /* xgettext: c-format */ msg = _("Warning: input file %s supports interworking, whereas %s does not."); else /* xgettext: c-format */ msg = _("Warning: input file %s does not support interworking, whereas %s does."); _bfd_error_handler (msg, bfd_get_filename (ibfd), bfd_get_filename (obfd)); } } else { SET_INTERWORK_FLAG (obfd, INTERWORK_FLAG (ibfd)); } } return true;}/* Display the flags field. */static booleancoff_arm_print_private_bfd_data (abfd, ptr) bfd * abfd; PTR ptr;{ FILE * file = (FILE *) ptr; BFD_ASSERT (abfd != NULL && ptr != NULL); /* xgettext:c-format */ fprintf (file, _("private flags = %x:"), coff_data (abfd)->flags); if (APCS_SET (abfd)) { /* xgettext: APCS is ARM Prodecure Call Standard, it should not be translated. */ fprintf (file, " [APCS-%d]", APCS_26_FLAG (abfd) ? 26 : 32); if (APCS_FLOAT_FLAG (abfd)) fprintf (file, _(" [floats passed in float registers]")); else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -