📄 elf-m10300.c
字号:
{ long r_type; unsigned long r_index; unsigned char code; r_type = ELF32_R_TYPE (irel->r_info); r_index = ELF32_R_SYM (irel->r_info); if (r_type < 0 || r_type >= (int) R_MN10300_MAX) goto error_return; /* We need the name and hash table entry of the target symbol! */ hash = NULL; sym = NULL; sym_sec = NULL; if (r_index < symtab_hdr->sh_info) { /* A local symbol. */ Elf_Internal_Sym isym; bfd_elf32_swap_symbol_in (input_bfd, extsyms + r_index, &isym); if (isym.st_shndx == SHN_UNDEF) sym_sec = bfd_und_section_ptr; else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE) sym_sec = bfd_section_from_elf_index (input_bfd, isym.st_shndx); else if (isym.st_shndx == SHN_ABS) sym_sec = bfd_abs_section_ptr; else if (isym.st_shndx == SHN_COMMON) sym_sec = bfd_com_section_ptr; sym_name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, isym.st_name); /* If it isn't a function, then we don't care about it. */ if (r_index < symtab_hdr->sh_info && ELF_ST_TYPE (isym.st_info) != STT_FUNC) continue; /* Tack on an ID so we can uniquely identify this local symbol in the global hash table. */ new_name = bfd_malloc (strlen (sym_name) + 10); if (new_name == 0) goto error_return; sprintf (new_name, "%s_%08x", sym_name, (int) sym_sec); sym_name = new_name; hash = (struct elf32_mn10300_link_hash_entry *) elf_link_hash_lookup (&hash_table->static_hash_table->root, sym_name, true, true, false); free (new_name); } else { r_index -= symtab_hdr->sh_info; hash = (struct elf32_mn10300_link_hash_entry *) elf_sym_hashes (input_bfd)[r_index]; } /* If this is not a "call" instruction, then we should convert "call" instructions to "calls" instructions. */ code = bfd_get_8 (input_bfd, contents + irel->r_offset - 1); if (code != 0xdd && code != 0xcd) hash->flags |= MN10300_CONVERT_CALL_TO_CALLS; /* If this is a jump/call, then bump the direct_calls counter. Else force "call" to "calls" conversions. */ if (r_type == R_MN10300_PCREL32 || r_type == R_MN10300_PCREL16) hash->direct_calls++; else hash->flags |= MN10300_CONVERT_CALL_TO_CALLS; } } /* Now look at the actual contents to get the stack size, and a list of what registers were saved in the prologue (ie movm_args). */ if ((section->flags & SEC_CODE) != 0) { Elf32_External_Sym *esym, *esymend; int idx, shndx; shndx = _bfd_elf_section_from_bfd_section (input_bfd, section); /* Look at each function defined in this section and update info for that function. */ esym = extsyms; esymend = esym + symtab_hdr->sh_info; for (; esym < esymend; esym++) { Elf_Internal_Sym isym; bfd_elf32_swap_symbol_in (input_bfd, esym, &isym); if (isym.st_shndx == shndx && ELF_ST_TYPE (isym.st_info) == STT_FUNC) { if (isym.st_shndx == SHN_UNDEF) sym_sec = bfd_und_section_ptr; else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE) sym_sec = bfd_section_from_elf_index (input_bfd, isym.st_shndx); else if (isym.st_shndx == SHN_ABS) sym_sec = bfd_abs_section_ptr; else if (isym.st_shndx == SHN_COMMON) sym_sec = bfd_com_section_ptr; sym_name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, isym.st_name); /* Tack on an ID so we can uniquely identify this local symbol in the global hash table. */ new_name = bfd_malloc (strlen (sym_name) + 10); if (new_name == 0) goto error_return; sprintf (new_name, "%s_%08x", sym_name, (int) sym_sec); sym_name = new_name; hash = (struct elf32_mn10300_link_hash_entry *) elf_link_hash_lookup (&hash_table->static_hash_table->root, sym_name, true, true, false); free (new_name); compute_function_info (input_bfd, hash, isym.st_value, contents); } } esym = extsyms + symtab_hdr->sh_info; esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)); for (idx = 0; esym < esymend; esym++, idx++) { Elf_Internal_Sym isym; bfd_elf32_swap_symbol_in (input_bfd, esym, &isym); hash = (struct elf32_mn10300_link_hash_entry *) elf_sym_hashes (input_bfd)[idx]; if (isym.st_shndx == shndx && ELF_ST_TYPE (isym.st_info) == STT_FUNC && (hash)->root.root.u.def.section == section && ((hash)->root.root.type == bfd_link_hash_defined || (hash)->root.root.type == bfd_link_hash_defweak)) compute_function_info (input_bfd, hash, (hash)->root.root.u.def.value, contents); } } /* Cache or free any memory we allocated for the relocs. */ if (free_relocs != NULL) { free (free_relocs); free_relocs = NULL; } /* Cache or free any memory we allocated for the contents. */ if (free_contents != NULL) { if (! link_info->keep_memory) free (free_contents); else { /* Cache the section contents for elf_link_input_bfd. */ elf_section_data (section)->this_hdr.contents = contents; } free_contents = NULL; } } /* Cache or free any memory we allocated for the symbols. */ if (free_extsyms != NULL) { if (! link_info->keep_memory) free (free_extsyms); else { /* Cache the symbols for elf_link_input_bfd. */ symtab_hdr->contents = extsyms; } free_extsyms = NULL; } } /* Now iterate on each symbol in the hash table and perform the final initialization steps on each. */ elf32_mn10300_link_hash_traverse (hash_table, elf32_mn10300_finish_hash_table_entry, NULL); elf32_mn10300_link_hash_traverse (hash_table->static_hash_table, elf32_mn10300_finish_hash_table_entry, NULL); /* All entries in the hash table are fully initialized. */ hash_table->flags |= MN10300_HASH_ENTRIES_INITIALIZED; /* Now that everything has been initialized, go through each code section and delete any prologue insns which will be redundant because their operations will be performed by a "call" instruction. */ for (input_bfd = link_info->input_bfds; input_bfd != NULL; input_bfd = input_bfd->link_next) { asection *section; /* We're going to need all the symbols for each bfd. */ symtab_hdr = &elf_tdata (input_bfd)->symtab_hdr; /* Get cached copy if it exists. */ if (symtab_hdr->contents != NULL) extsyms = (Elf32_External_Sym *) symtab_hdr->contents; else { /* Go get them off disk. */ extsyms = ((Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_size)); if (extsyms == NULL) goto error_return; free_extsyms = extsyms; if (bfd_seek (input_bfd, symtab_hdr->sh_offset, SEEK_SET) != 0 || (bfd_read (extsyms, 1, symtab_hdr->sh_size, input_bfd) != symtab_hdr->sh_size)) goto error_return; } /* Walk over each section in this bfd. */ for (section = input_bfd->sections; section != NULL; section = section->next) { int shndx; Elf32_External_Sym *esym, *esymend; int idx; /* Skip non-code sections and empty sections. */ if ((section->flags & SEC_CODE) == 0 || section->_raw_size == 0) continue; if (section->reloc_count != 0) { /* Get a copy of the native relocations. */ internal_relocs = (_bfd_elf32_link_read_relocs (input_bfd, section, (PTR) NULL, (Elf_Internal_Rela *) NULL, link_info->keep_memory)); if (internal_relocs == NULL) goto error_return; if (! link_info->keep_memory) free_relocs = internal_relocs; } /* Get cached copy of section contents if it exists. */ if (elf_section_data (section)->this_hdr.contents != NULL) contents = elf_section_data (section)->this_hdr.contents; else { /* Go get them off disk. */ contents = (bfd_byte *) bfd_malloc (section->_raw_size); if (contents == NULL) goto error_return; free_contents = contents; if (!bfd_get_section_contents (input_bfd, section, contents, (file_ptr) 0, section->_raw_size)) goto error_return; } shndx = _bfd_elf_section_from_bfd_section (input_bfd, section); /* Now look for any function in this section which needs insns deleted from its prologue. */ esym = extsyms; esymend = esym + symtab_hdr->sh_info; for (; esym < esymend; esym++) { Elf_Internal_Sym isym; struct elf32_mn10300_link_hash_entry *sym_hash; asection *sym_sec = NULL; const char *sym_name; char *new_name; bfd_elf32_swap_symbol_in (input_bfd, esym, &isym); if (isym.st_shndx != shndx) continue; if (isym.st_shndx == SHN_UNDEF) sym_sec = bfd_und_section_ptr; else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE) sym_sec = bfd_section_from_elf_index (input_bfd, isym.st_shndx); else if (isym.st_shndx == SHN_ABS) sym_sec = bfd_abs_section_ptr; else if (isym.st_shndx == SHN_COMMON) sym_sec = bfd_com_section_ptr; else abort (); sym_name = bfd_elf_string_from_elf_section (input_bfd, symtab_hdr->sh_link, isym.st_name); /* Tack on an ID so we can uniquely identify this local symbol in the global hash table. */ new_name = bfd_malloc (strlen (sym_name) + 10); if (new_name == 0) goto error_return; sprintf (new_name, "%s_%08x", sym_name, (int) sym_sec); sym_name = new_name; sym_hash = (struct elf32_mn10300_link_hash_entry *) elf_link_hash_lookup (&hash_table->static_hash_table->root, sym_name, false, false, false); free (new_name); if (sym_hash == NULL) continue; if (! ((sym_hash)->flags & MN10300_CONVERT_CALL_TO_CALLS) && ! ((sym_hash)->flags & MN10300_DELETED_PROLOGUE_BYTES)) { int bytes = 0; /* Note that we've changed things. */ elf_section_data (section)->relocs = internal_relocs; free_relocs = NULL; elf_section_data (section)->this_hdr.contents = contents; free_contents = NULL; symtab_hdr->contents = (bfd_byte *) extsyms; free_extsyms = NULL; /* Count how many bytes we're going to delete. */ if (sym_hash->movm_args) bytes += 2; if (sym_hash->stack_size && sym_hash->stack_size <= 128) bytes += 3; else if (sym_hash->stack_size && sym_hash->stack_size < 256) bytes += 4; /* Note that we've deleted prologue bytes for this function. */ sym_hash->flags |= MN10300_DELETED_PROLOGUE_BYTES; /* Actually delete the bytes. */ if (!mn10300_elf_relax_delete_bytes (input_bfd, section, isym.st_value, bytes)) goto error_return; /* Something changed. Not strictly necessary, but may lead to more relaxing opportunities. */ *again = true; } } /* Look for any global functions in this section which need insns deleted from their prologues. */ esym = extsyms + symtab_hdr->sh_info; esymend = extsyms + (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)); for (idx = 0; esym < esymend; esym++, idx++) { Elf_Internal_Sym isym; struct elf32_mn10300_link_hash_entry *sym_hash; bfd_elf32_swap_symbol_in (input_bfd, esym, &isym); sym_hash = (struct elf32_mn10300_link_hash_entry *) (elf_sym_hashes (input_bfd)[idx]); if (isym.st_shndx == shndx && (sym_hash)->root.root.u.def.section == section && ! ((sym_hash)->flags & MN10300_CONVERT_CALL_TO_CALLS) && ! ((sym_hash)->flags & MN10300_DELETED_PROLOGUE_BYTES)) { int bytes = 0; /* Note that we've changed things. */ elf_section_data (section)->relocs = internal_relocs; free_relocs = NULL; elf_section_data (section)->this_hdr.contents = contents; free_contents = NULL; symtab_hdr->contents = (bfd_byte *) extsyms; free_extsyms = NULL; /* Count how many bytes we're going to delete. */ if (sym_hash->movm_args) bytes += 2; if (sym_hash->stack_size && sym_hash->stack_size <= 128) bytes += 3; else if (sym_hash->stack_size && sym_hash->stack_size < 256) bytes += 4; /* Note that we've deleted prologue bytes for this function. */ sym_hash->flags |= MN10300_DELETED_PROLOGUE_BYTES; /* Actually delete the bytes. */ if (!mn10300_elf_relax_delete_bytes (input_bfd, section, (sym_hash)->root.root.u.def.value, bytes)) goto error_return; /* Something changed. Not strictly necessary, but may lead to more relaxing opportunities. */ *again = true; } } /* Cache or free any memory we allocated for the relocs. */ if (free_relocs != NULL) { free (free_relocs);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -