📄 elf.c
字号:
/* If the section has relocs, set up a section header for the SHT_REL[A] section. If two relocation sections are required for this section, it is up to the processor-specific back-end to create the other. */ if ((asect->flags & SEC_RELOC) != 0 && !_bfd_elf_init_reloc_shdr (abfd, &elf_section_data (asect)->rel_hdr, asect, elf_section_data (asect)->use_rela_p)) *failedptr = true;}/* Assign all ELF section numbers. The dummy first section is handled here too. The link/info pointers for the standard section types are filled in here too, while we're at it. */static booleanassign_section_numbers (abfd) bfd *abfd;{ struct elf_obj_tdata *t = elf_tdata (abfd); asection *sec; unsigned int section_number; Elf_Internal_Shdr **i_shdrp; section_number = 1; for (sec = abfd->sections; sec; sec = sec->next) { struct bfd_elf_section_data *d = elf_section_data (sec); d->this_idx = section_number++; if ((sec->flags & SEC_RELOC) == 0) d->rel_idx = 0; else d->rel_idx = section_number++; if (d->rel_hdr2) d->rel_idx2 = section_number++; else d->rel_idx2 = 0; } t->shstrtab_section = section_number++; elf_elfheader (abfd)->e_shstrndx = t->shstrtab_section; t->shstrtab_hdr.sh_size = _bfd_stringtab_size (elf_shstrtab (abfd)); if (bfd_get_symcount (abfd) > 0) { t->symtab_section = section_number++; t->strtab_section = section_number++; } elf_elfheader (abfd)->e_shnum = section_number; /* Set up the list of section header pointers, in agreement with the indices. */ i_shdrp = ((Elf_Internal_Shdr **) bfd_alloc (abfd, section_number * sizeof (Elf_Internal_Shdr *))); if (i_shdrp == NULL) return false; i_shdrp[0] = ((Elf_Internal_Shdr *) bfd_alloc (abfd, sizeof (Elf_Internal_Shdr))); if (i_shdrp[0] == NULL) { bfd_release (abfd, i_shdrp); return false; } memset (i_shdrp[0], 0, sizeof (Elf_Internal_Shdr)); elf_elfsections (abfd) = i_shdrp; i_shdrp[t->shstrtab_section] = &t->shstrtab_hdr; if (bfd_get_symcount (abfd) > 0) { i_shdrp[t->symtab_section] = &t->symtab_hdr; i_shdrp[t->strtab_section] = &t->strtab_hdr; t->symtab_hdr.sh_link = t->strtab_section; } for (sec = abfd->sections; sec; sec = sec->next) { struct bfd_elf_section_data *d = elf_section_data (sec); asection *s; const char *name; i_shdrp[d->this_idx] = &d->this_hdr; if (d->rel_idx != 0) i_shdrp[d->rel_idx] = &d->rel_hdr; if (d->rel_idx2 != 0) i_shdrp[d->rel_idx2] = d->rel_hdr2; /* Fill in the sh_link and sh_info fields while we're at it. */ /* sh_link of a reloc section is the section index of the symbol table. sh_info is the section index of the section to which the relocation entries apply. */ if (d->rel_idx != 0) { d->rel_hdr.sh_link = t->symtab_section; d->rel_hdr.sh_info = d->this_idx; } if (d->rel_idx2 != 0) { d->rel_hdr2->sh_link = t->symtab_section; d->rel_hdr2->sh_info = d->this_idx; } switch (d->this_hdr.sh_type) { case SHT_REL: case SHT_RELA: /* A reloc section which we are treating as a normal BFD section. sh_link is the section index of the symbol table. sh_info is the section index of the section to which the relocation entries apply. We assume that an allocated reloc section uses the dynamic symbol table. FIXME: How can we be sure? */ s = bfd_get_section_by_name (abfd, ".dynsym"); if (s != NULL) d->this_hdr.sh_link = elf_section_data (s)->this_idx; /* We look up the section the relocs apply to by name. */ name = sec->name; if (d->this_hdr.sh_type == SHT_REL) name += 4; else name += 5; s = bfd_get_section_by_name (abfd, name); if (s != NULL) d->this_hdr.sh_info = elf_section_data (s)->this_idx; break; case SHT_STRTAB: /* We assume that a section named .stab*str is a stabs string section. We look for a section with the same name but without the trailing ``str'', and set its sh_link field to point to this section. */ if (strncmp (sec->name, ".stab", sizeof ".stab" - 1) == 0 && strcmp (sec->name + strlen (sec->name) - 3, "str") == 0) { size_t len; char *alc; len = strlen (sec->name); alc = (char *) bfd_malloc (len - 2); if (alc == NULL) return false; strncpy (alc, sec->name, len - 3); alc[len - 3] = '\0'; s = bfd_get_section_by_name (abfd, alc); free (alc); if (s != NULL) { elf_section_data (s)->this_hdr.sh_link = d->this_idx; /* This is a .stab section. */ elf_section_data (s)->this_hdr.sh_entsize = 4 + 2 * bfd_get_arch_size (abfd) / 8; } } break; case SHT_DYNAMIC: case SHT_DYNSYM: case SHT_GNU_verneed: case SHT_GNU_verdef: /* sh_link is the section header index of the string table used for the dynamic entries, or the symbol table, or the version strings. */ s = bfd_get_section_by_name (abfd, ".dynstr"); if (s != NULL) d->this_hdr.sh_link = elf_section_data (s)->this_idx; break; case SHT_HASH: case SHT_GNU_versym: /* sh_link is the section header index of the symbol table this hash table or version table is for. */ s = bfd_get_section_by_name (abfd, ".dynsym"); if (s != NULL) d->this_hdr.sh_link = elf_section_data (s)->this_idx; break; } } return true;}/* Map symbol from it's internal number to the external number, moving all local symbols to be at the head of the list. */static INLINE intsym_is_global (abfd, sym) bfd *abfd; asymbol *sym;{ /* If the backend has a special mapping, use it. */ if (get_elf_backend_data (abfd)->elf_backend_sym_is_global) return ((*get_elf_backend_data (abfd)->elf_backend_sym_is_global) (abfd, sym)); return ((sym->flags & (BSF_GLOBAL | BSF_WEAK)) != 0 || bfd_is_und_section (bfd_get_section (sym)) || bfd_is_com_section (bfd_get_section (sym)));}static booleanelf_map_symbols (abfd) bfd *abfd;{ int symcount = bfd_get_symcount (abfd); asymbol **syms = bfd_get_outsymbols (abfd); asymbol **sect_syms; int num_locals = 0; int num_globals = 0; int num_locals2 = 0; int num_globals2 = 0; int max_index = 0; int num_sections = 0; int idx; asection *asect; asymbol **new_syms; asymbol *sym;#ifdef DEBUG fprintf (stderr, "elf_map_symbols\n"); fflush (stderr);#endif /* Add a section symbol for each BFD section. FIXME: Is this really necessary? */ for (asect = abfd->sections; asect; asect = asect->next) { if (max_index < asect->index) max_index = asect->index; } max_index++; sect_syms = (asymbol **) bfd_zalloc (abfd, max_index * sizeof (asymbol *)); if (sect_syms == NULL) return false; elf_section_syms (abfd) = sect_syms; for (idx = 0; idx < symcount; idx++) { sym = syms[idx]; if ((sym->flags & BSF_SECTION_SYM) != 0 && sym->value == 0) { asection *sec; sec = sym->section; if (sec->owner != NULL) { if (sec->owner != abfd) { if (sec->output_offset != 0) continue; sec = sec->output_section; /* Empty sections in the input files may have had a section symbol created for them. (See the comment near the end of _bfd_generic_link_output_symbols in linker.c). If the linker script discards such sections then we will reach this point. Since we know that we cannot avoid this case, we detect it and skip the abort and the assignment to the sect_syms array. To reproduce this particular case try running the linker testsuite test ld-scripts/weak.exp for an ELF port that uses the generic linker. */ if (sec->owner == NULL) continue; BFD_ASSERT (sec->owner == abfd); } sect_syms[sec->index] = syms[idx]; } } } for (asect = abfd->sections; asect; asect = asect->next) { if (sect_syms[asect->index] != NULL) continue; sym = bfd_make_empty_symbol (abfd); if (sym == NULL) return false; sym->the_bfd = abfd; sym->name = asect->name; sym->value = 0; /* Set the flags to 0 to indicate that this one was newly added. */ sym->flags = 0; sym->section = asect; sect_syms[asect->index] = sym; num_sections++;#ifdef DEBUG fprintf (stderr, _("creating section symbol, name = %s, value = 0x%.8lx, index = %d, section = 0x%.8lx\n"), asect->name, (long) asect->vma, asect->index, (long) asect);#endif } /* Classify all of the symbols. */ for (idx = 0; idx < symcount; idx++) { if (!sym_is_global (abfd, syms[idx])) num_locals++; else num_globals++; } for (asect = abfd->sections; asect; asect = asect->next) { if (sect_syms[asect->index] != NULL && sect_syms[asect->index]->flags == 0) { sect_syms[asect->index]->flags = BSF_SECTION_SYM; if (!sym_is_global (abfd, sect_syms[asect->index])) num_locals++; else num_globals++; sect_syms[asect->index]->flags = 0; } } /* Now sort the symbols so the local symbols are first. */ new_syms = ((asymbol **) bfd_alloc (abfd, (num_locals + num_globals) * sizeof (asymbol *))); if (new_syms == NULL) return false; for (idx = 0; idx < symcount; idx++) { asymbol *sym = syms[idx]; int i; if (!sym_is_global (abfd, sym)) i = num_locals2++; else i = num_locals + num_globals2++; new_syms[i] = sym; sym->udata.i = i + 1; } for (asect = abfd->sections; asect; asect = asect->next) { if (sect_syms[asect->index] != NULL && sect_syms[asect->index]->flags == 0) { asymbol *sym = sect_syms[asect->index]; int i; sym->flags = BSF_SECTION_SYM; if (!sym_is_global (abfd, sym)) i = num_locals2++; else i = num_locals + num_globals2++; new_syms[i] = sym; sym->udata.i = i + 1; } } bfd_set_symtab (abfd, new_syms, num_locals + num_globals); elf_num_locals (abfd) = num_locals; elf_num_globals (abfd) = num_globals; return true;}/* Align to the maximum file alignment that could be required for any ELF data structure. */static INLINE file_ptr align_file_position PARAMS ((file_ptr, int));static INLINE file_ptralign_file_position (off, align) file_ptr off; int align;{ return (off + align - 1) & ~(align - 1);}/* Assign a file position to a section, optionally aligning to the required section alignment. */INLINE file_ptr_bfd_elf_assign_file_position_for_section (i_shdrp, offset, align) Elf_Internal_Shdr *i_shdrp; file_ptr offset; boolean align;{ if (align) { unsigned int al; al = i_shdrp->sh_addralign; if (al > 1) offset = BFD_ALIGN (offset, al); } i_shdrp->sh_offset = offset; if (i_shdrp->bfd_section != NULL) i_shdrp->bfd_section->filepos = offset; if (i_shdrp->sh_type != SHT_NOBITS) offset += i_shdrp->sh_size; return offset;}/* Compute the file positions we are going to put the sections at, and otherwise prepare to begin writing out the ELF file. If LINK_INFO is not NULL, this is being called by the ELF backend linker. */boolean_bfd_elf_compute_section_file_positions (abfd, link_info) bfd *abfd; struct bfd_link_info *link_info;{ struct elf_backend_data *bed = get_elf_backend_data (abfd); boolean failed; struct bfd_strtab_hash *strtab; Elf_Internal_Shdr *shstrtab_hdr; if (abfd->output_has_begun) return true; /* Do any elf backend specific processing first. */ if (bed->elf_backend_begin_write_processing) (*bed->elf_backend_begin_write_processing) (abfd, link_info); if (! prep_headers (abfd)) return false; /* Post process the headers if necessary. */ if (bed->elf_backend_post_process_headers) (*bed->elf_backend_post_process_headers) (abfd, link_info); failed = false; bfd_map_over_sections (abfd, elf_fake_sections, &failed); if (failed) return false; if (!assign_section_numbers (abfd)) return false; /* The backend linker builds symbol table information itself. */ if (link_info == NULL && bfd_get_symcount (abfd) > 0) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -