static bfd_boolean elf32_sparc_merge_private_bfd_data (bfd *ibfd, bfd *obfd) { bfd_boolean error; unsigned long ibfd_mach; /* FIXME: This should not be static. */ static unsigned long previous_ibfd_e_flags = (unsigned long) -1; if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour || bfd_get_flavour (obfd) != bfd_target_elf_flavour) return TRUE; error = FALSE; ibfd_mach = bfd_get_mach (ibfd); if (bfd_mach_sparc_64bit_p (ibfd_mach)) { error = TRUE; (*_bfd_error_handler) (_("%B: compiled for a 64 bit system and target is 32 bit"), ibfd); } else if ((ibfd->flags & DYNAMIC) == 0) { if (bfd_get_mach (obfd) < ibfd_mach) bfd_set_arch_mach (obfd, bfd_arch_sparc, ibfd_mach); } if (((elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA) != previous_ibfd_e_flags) && previous_ibfd_e_flags != (unsigned long) -1) { (*_bfd_error_handler) (_("%B: linking little endian files with big endian files"), ibfd); error = TRUE; } previous_ibfd_e_flags = elf_elfheader (ibfd)->e_flags & EF_SPARC_LEDATA; if (error) { bfd_set_error (bfd_error_bad_value); return FALSE; } return TRUE; }
static int sim_prepare_for_program (SIM_DESC sd, bfd* abfd) { sim_cpu *cpu; int elf_flags = 0; cpu = STATE_CPU (sd, 0); if (abfd != NULL) { asection *s; if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) elf_flags = elf_elfheader (abfd)->e_flags; cpu->cpu_elf_start = bfd_get_start_address (abfd); /* See if any section sets the reset address */ cpu->cpu_use_elf_start = 1; for (s = abfd->sections; s && cpu->cpu_use_elf_start; s = s->next) { if (s->flags & SEC_LOAD) { bfd_size_type size; size = bfd_get_section_size (s); if (size > 0) { bfd_vma lma; if (STATE_LOAD_AT_LMA_P (sd)) lma = bfd_section_lma (abfd, s); else lma = bfd_section_vma (abfd, s); if (lma <= 0xFFFE && lma+size >= 0x10000) cpu->cpu_use_elf_start = 0; } } } if (elf_flags & E_M68HC12_BANKS) { if (sim_get_bank_parameters (sd, abfd) != 0) sim_io_eprintf (sd, "Memory bank parameters are not initialized\n"); } } if (!sim_hw_configure (sd)) return SIM_RC_FAIL; /* reset all state information */ sim_board_reset (sd); return SIM_RC_OK; }
/******************************************************* Function: ld_get_section_name *******************************************************/ char * ld_get_section_name(void *pobj, int sect_ndx) { bfd *abfd = (bfd *) pobj; Elf_Internal_Shdr **i_shdrp = elf_elfsections (abfd); Elf_Internal_Shdr *p_shdr = i_shdrp[sect_ndx]; char *tbl = bfd_elf_get_str_section(abfd, elf_elfheader (abfd)->e_shstrndx); return &tbl[p_shdr->sh_name]; }
static void elf32_sparc_final_write_processing (bfd *abfd, bfd_boolean linker ATTRIBUTE_UNUSED) { switch (bfd_get_mach (abfd)) { case bfd_mach_sparc : case bfd_mach_sparc_sparclet : case bfd_mach_sparc_sparclite : break; /* nothing to do */ case bfd_mach_sparc_v8plus : elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS; elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK; elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS; break; case bfd_mach_sparc_v8plusa : elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS; elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK; elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1; break; case bfd_mach_sparc_v8plusb : case bfd_mach_sparc_v8plusc : case bfd_mach_sparc_v8plusd : case bfd_mach_sparc_v8pluse : case bfd_mach_sparc_v8plusv : case bfd_mach_sparc_v8plusm : case bfd_mach_sparc_v8plusm8 : elf_elfheader (abfd)->e_machine = EM_SPARC32PLUS; elf_elfheader (abfd)->e_flags &=~ EF_SPARC_32PLUS_MASK; elf_elfheader (abfd)->e_flags |= EF_SPARC_32PLUS | EF_SPARC_SUN_US1 | EF_SPARC_SUN_US3; break; case bfd_mach_sparc_sparclite_le : elf_elfheader (abfd)->e_flags |= EF_SPARC_LEDATA; break; default : abort (); break; } }
bfd_boolean ipa_is_whirl(bfd *abfd) { Elf_Internal_Ehdr *i_ehdrp; /* Elf file header, internal form */ i_ehdrp = elf_elfheader (abfd); if (i_ehdrp->e_type == ET_SGI_IR) { return(TRUE); } return(FALSE); }
char * fbsd_make_corefile_notes (bfd *obfd, int *note_size) { const struct regcache *regcache = get_current_regcache (); struct gdbarch *gdbarch = get_regcache_arch (regcache); gregset_t gregs; fpregset_t fpregs; char *note_data = NULL; Elf_Internal_Ehdr *i_ehdrp; const struct regset *regset; size_t size; /* Put a "FreeBSD" label in the ELF header. */ i_ehdrp = elf_elfheader (obfd); i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; gdb_assert (gdbarch_regset_from_core_section_p (gdbarch)); size = sizeof gregs; regset = gdbarch_regset_from_core_section (gdbarch, ".reg", size); gdb_assert (regset && regset->collect_regset); regset->collect_regset (regset, regcache, -1, &gregs, size); note_data = elfcore_write_prstatus (obfd, note_data, note_size, ptid_get_pid (inferior_ptid), find_stop_signal (), &gregs); size = sizeof fpregs; regset = gdbarch_regset_from_core_section (gdbarch, ".reg2", size); gdb_assert (regset && regset->collect_regset); regset->collect_regset (regset, regcache, -1, &fpregs, size); note_data = elfcore_write_prfpreg (obfd, note_data, note_size, &fpregs, sizeof (fpregs)); if (get_exec_file (0)) { const char *fname = lbasename (get_exec_file (0)); char *psargs = xstrdup (fname); if (get_inferior_args ()) psargs = reconcat (psargs, psargs, " ", get_inferior_args (), (char *) NULL); note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, fname, psargs); } make_cleanup (xfree, note_data); return note_data; }
enum sh64_elf_cr_type sh64_get_contents_type (asection *sec, bfd_vma addr, sh64_elf_crange *rangep) { asection *cranges; /* Fill in the range with the boundaries of the section as a default. */ if (bfd_get_flavour (sec->owner) == bfd_target_elf_flavour && elf_elfheader (sec->owner)->e_type == ET_EXEC) { rangep->cr_addr = bfd_get_section_vma (sec->owner, sec); rangep->cr_size = sec->size; rangep->cr_type = CRT_NONE; } else return FALSE; /* If none of the pertinent bits are set, then it's a SHcompact (or at least not SHmedia). */ if ((elf_section_data (sec)->this_hdr.sh_flags & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == 0) { enum sh64_elf_cr_type cr_type = ((bfd_get_section_flags (sec->owner, sec) & SEC_CODE) != 0 ? CRT_SH5_ISA16 : CRT_DATA); rangep->cr_type = cr_type; return cr_type; } /* If only the SHF_SH5_ISA32 bit is set, then we have SHmedia. */ if ((elf_section_data (sec)->this_hdr.sh_flags & (SHF_SH5_ISA32 | SHF_SH5_ISA32_MIXED)) == SHF_SH5_ISA32) { rangep->cr_type = CRT_SH5_ISA32; return CRT_SH5_ISA32; } /* Otherwise, we have to look up the .cranges section. */ cranges = bfd_get_section_by_name (sec->owner, SH64_CRANGES_SECTION_NAME); if (cranges == NULL) /* A mixed section but there's no .cranges section. This is probably bad input; it does not comply to specs. */ return CRT_NONE; /* If this call fails, we will still have CRT_NONE in rangep->cr_type and that will be suitable to return. */ sh64_address_in_cranges (cranges, addr, rangep); return rangep->cr_type; }
static enum gdb_osabi frv_linux_elf_osabi_sniffer (bfd *abfd) { int elf_flags; elf_flags = elf_elfheader (abfd)->e_flags; /* Assume GNU/Linux if using the FDPIC ABI. If/when another OS shows up that uses this ABI, we'll need to start using .note sections or some such. */ if (elf_flags & EF_FRV_FDPIC) return GDB_OSABI_LINUX; else return GDB_OSABI_UNKNOWN; }
static void set_default_propeller_dis_options (struct disassemble_info *info) { is_p2 = 0; is_compress = 0; is_nocompress = 0; /* check for p2 object files */ if (info->flavour == bfd_target_elf_flavour && info->section != NULL) { Elf_Internal_Ehdr *header; header = elf_elfheader (info->section->owner); if ((header->e_flags & EF_PROPELLER_MACH) == EF_PROPELLER_PROP2) { is_p2 = 1; } } }
static char * fbsd_make_corefile_notes (bfd *obfd, int *note_size) { gregset_t gregs; fpregset_t fpregs; char *note_data = NULL; Elf_Internal_Ehdr *i_ehdrp; char fakename; /* Put a "FreeBSD" label in the ELF header. */ i_ehdrp = elf_elfheader (obfd); i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; fill_gregset (&gregs, -1); note_data = elfcore_write_prstatus (obfd, note_data, note_size, ptid_get_pid (inferior_ptid), stop_signal, &gregs); fill_fpregset (&fpregs, -1); note_data = elfcore_write_prfpreg (obfd, note_data, note_size, &fpregs, sizeof (fpregs)); fakename = '\0'; note_data = elfcore_write_thrmisc (obfd, note_data, note_size, &fakename, sizeof (fakename)); if (get_exec_file (0)) { char *fname = strrchr (get_exec_file (0), '/') + 1; char *psargs = xstrdup (fname); if (get_inferior_args ()) psargs = reconcat (psargs, psargs, " ", get_inferior_args (), NULL); note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, fname, psargs); } make_cleanup (xfree, note_data); return note_data; }
static char * fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) { struct regcache *regcache = get_current_regcache (); char *note_data; Elf_Internal_Ehdr *i_ehdrp; struct fbsd_collect_regset_section_cb_data data; /* Put a "FreeBSD" label in the ELF header. */ i_ehdrp = elf_elfheader (obfd); i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD; gdb_assert (gdbarch_iterate_over_regset_sections_p (gdbarch)); data.regcache = regcache; data.obfd = obfd; data.note_data = NULL; data.note_size = note_size; target_fetch_registers (regcache, -1); gdbarch_iterate_over_regset_sections (gdbarch, fbsd_collect_regset_section_cb, &data, regcache); note_data = data.note_data; if (get_exec_file (0)) { const char *fname = lbasename (get_exec_file (0)); char *psargs = xstrdup (fname); if (get_inferior_args ()) psargs = reconcat (psargs, psargs, " ", get_inferior_args (), (char *) NULL); note_data = elfcore_write_prpsinfo (obfd, note_data, note_size, fname, psargs); } return note_data; }
/******************************************************* Function: ipa_process_whirl I need to read the WHIRL symbol table so the internal mechanisms of IPA will have their data structures correctly filled out. Since IPA needs an mmapped view of the object I'm trying to remap it here. It is not ready for archives yet. I am overloading the usrdata field of the bfd with the assumption that bfd is done with it. #ifdef KEY Nope, bfd isn't done with usrdata. An example is warning_callback where a later bfd accesses an earlier bfd's usrdata. #endif *******************************************************/ void ipa_process_whirl ( bfd *abfd) { off_t mapped_size; #ifdef KEY abfd->ipa_usrdata = #else abfd->usrdata = #endif (PTR)ipa_open_input((char *)abfd->filename, &mapped_size); #if !defined(__ALWAYS_USE_64BIT_ELF__) && !defined(FAT_WHIRL_OBJECTS) /* Should be sync. with Config_Target_From_ELF() defined in be.so */ if( ( elf_elfheader (abfd)->e_flags & EF_IRIX_ABI64 ) == 0 ) process_whirl32 ( (void *)abfd, elf_elfheader (abfd)->e_shnum, #ifdef KEY abfd->ipa_usrdata+elf_elfheader(abfd)->e_shoff, #else abfd->usrdata+elf_elfheader(abfd)->e_shoff, #endif 0, /* check_whirl_revision */ abfd->filename); else #endif process_whirl64 ( (void *)abfd, elf_elfheader (abfd)->e_shnum, #ifdef KEY abfd->ipa_usrdata+elf_elfheader(abfd)->e_shoff, #else abfd->usrdata+elf_elfheader(abfd)->e_shoff, #endif 0, /* check_whirl_revision */ abfd->filename); }
static bool bfin_fdpic_load (SIM_DESC sd, SIM_CPU *cpu, struct bfd *abfd, bu32 *sp, bu32 *elf_addrs, char **ldso_path) { bool ret; int i; Elf_Internal_Ehdr *iehdr; Elf32_External_Ehdr ehdr; Elf_Internal_Phdr *phdrs; unsigned char *data; long phdr_size; int phdrc; bu32 nsegs; bu32 max_load_addr; unsigned char null[4] = { 0, 0, 0, 0 }; ret = false; *ldso_path = NULL; /* See if this an FDPIC ELF. */ phdrs = NULL; if (!abfd) goto skip_fdpic_init; if (bfd_seek (abfd, 0, SEEK_SET) != 0) goto skip_fdpic_init; if (bfd_bread (&ehdr, sizeof (ehdr), abfd) != sizeof (ehdr)) goto skip_fdpic_init; iehdr = elf_elfheader (abfd); if (!(iehdr->e_flags & EF_BFIN_FDPIC)) goto skip_fdpic_init; if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) sim_io_printf (sd, "Loading FDPIC ELF %s\n Load base: %#x\n ELF entry: %#x\n", bfd_get_filename (abfd), fdpic_load_offset, elf_addrs[0]); /* Grab the Program Headers to set up the loadsegs on the stack. */ phdr_size = bfd_get_elf_phdr_upper_bound (abfd); if (phdr_size == -1) goto skip_fdpic_init; phdrs = xmalloc (phdr_size); phdrc = bfd_get_elf_phdrs (abfd, phdrs); if (phdrc == -1) goto skip_fdpic_init; /* Push the Ehdr onto the stack. */ *sp -= sizeof (ehdr); elf_addrs[3] = *sp; sim_write (sd, *sp, (void *)&ehdr, sizeof (ehdr)); if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) sim_io_printf (sd, " Elf_Ehdr: %#x\n", *sp); /* Since we're relocating things ourselves, we need to relocate the start address as well. */ elf_addrs[0] = bfd_get_start_address (abfd) + fdpic_load_offset; /* And the Exec's Phdrs onto the stack. */ if (STATE_PROG_BFD (sd) == abfd) { elf_addrs[4] = elf_addrs[0]; phdr_size = iehdr->e_phentsize * iehdr->e_phnum; if (bfd_seek (abfd, iehdr->e_phoff, SEEK_SET) != 0) goto skip_fdpic_init; data = xmalloc (phdr_size); if (bfd_bread (data, phdr_size, abfd) != phdr_size) goto skip_fdpic_init; *sp -= phdr_size; elf_addrs[1] = *sp; elf_addrs[2] = phdrc; sim_write (sd, *sp, data, phdr_size); free (data); if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) sim_io_printf (sd, " Elf_Phdrs: %#x\n", *sp); } /* Now push all the loadsegs. */ nsegs = 0; max_load_addr = 0; for (i = phdrc; i >= 0; --i) if (phdrs[i].p_type == PT_LOAD) { Elf_Internal_Phdr *p = &phdrs[i]; bu32 paddr, vaddr, memsz, filesz; paddr = p->p_paddr + fdpic_load_offset; vaddr = p->p_vaddr; memsz = p->p_memsz; filesz = p->p_filesz; if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) sim_io_printf (sd, " PHDR %i: vma %#x lma %#x filesz %#x memsz %#x\n", i, vaddr, paddr, filesz, memsz); data = xmalloc (memsz); if (memsz != filesz) memset (data + filesz, 0, memsz - filesz); if (bfd_seek (abfd, p->p_offset, SEEK_SET) == 0 && bfd_bread (data, filesz, abfd) == filesz) sim_write (sd, paddr, data, memsz); free (data); max_load_addr = MAX (paddr + memsz, max_load_addr); *sp -= 12; sim_write (sd, *sp+0, (void *)&paddr, 4); /* loadseg.addr */ sim_write (sd, *sp+4, (void *)&vaddr, 4); /* loadseg.p_vaddr */ sim_write (sd, *sp+8, (void *)&memsz, 4); /* loadseg.p_memsz */ ++nsegs; } else if (phdrs[i].p_type == PT_DYNAMIC) { elf_addrs[5] = phdrs[i].p_paddr + fdpic_load_offset; if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) sim_io_printf (sd, " PT_DYNAMIC: %#x\n", elf_addrs[5]); } else if (phdrs[i].p_type == PT_INTERP) { uint32_t off = phdrs[i].p_offset; uint32_t len = phdrs[i].p_filesz; *ldso_path = xmalloc (len); if (bfd_seek (abfd, off, SEEK_SET) != 0 || bfd_bread (*ldso_path, len, abfd) != len) { free (*ldso_path); *ldso_path = NULL; } else if (STATE_OPEN_KIND (sd) == SIM_OPEN_DEBUG) sim_io_printf (sd, " PT_INTERP: %s\n", *ldso_path); } /* Update the load offset with a few extra pages. */ fdpic_load_offset = ALIGN (MAX (max_load_addr, fdpic_load_offset), 0x10000); fdpic_load_offset += 0x10000; /* Push the summary loadmap info onto the stack last. */ *sp -= 4; sim_write (sd, *sp+0, null, 2); /* loadmap.version */ sim_write (sd, *sp+2, (void *)&nsegs, 2); /* loadmap.nsegs */ ret = true; skip_fdpic_init: free (phdrs); return ret; }
static struct eh_cie_fde * find_merged_cie (bfd *abfd, asection *sec, struct eh_frame_hdr_info *hdr_info, struct elf_reloc_cookie *cookie, struct eh_cie_fde *cie_inf) { unsigned long r_symndx; struct cie *cie, *new_cie; Elf_Internal_Rela *rel; void **loc; /* Use CIE_INF if we have already decided to keep it. */ if (!cie_inf->removed) return cie_inf; /* If we have merged CIE_INF with another CIE, use that CIE instead. */ if (cie_inf->u.cie.merged) return cie_inf->u.cie.u.merged_with; cie = cie_inf->u.cie.u.full_cie; /* Assume we will need to keep CIE_INF. */ cie_inf->removed = 0; cie_inf->u.cie.u.sec = sec; /* If we are not merging CIEs, use CIE_INF. */ if (cie == NULL) return cie_inf; if (cie->per_encoding != DW_EH_PE_omit) { /* Work out the address of personality routine, either as an absolute value or as a symbol. */ rel = cookie->rels + cie->personality.reloc_index; memset (&cie->personality, 0, sizeof (cie->personality)); #ifdef BFD64 if (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64) r_symndx = ELF64_R_SYM (rel->r_info); else #endif r_symndx = ELF32_R_SYM (rel->r_info); if (r_symndx >= cookie->locsymcount || ELF_ST_BIND (cookie->locsyms[r_symndx].st_info) != STB_LOCAL) { struct elf_link_hash_entry *h; r_symndx -= cookie->extsymoff; h = cookie->sym_hashes[r_symndx]; 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; cie->personality.h = h; } else { Elf_Internal_Sym *sym; asection *sym_sec; sym = &cookie->locsyms[r_symndx]; sym_sec = bfd_section_from_elf_index (abfd, sym->st_shndx); if (sym_sec == NULL) return cie_inf; if (sym_sec->kept_section != NULL) sym_sec = sym_sec->kept_section; if (sym_sec->output_section == NULL) return cie_inf; cie->local_personality = 1; cie->personality.val = (sym->st_value + sym_sec->output_offset + sym_sec->output_section->vma); } } /* See if we can merge this CIE with an earlier one. */ cie->output_sec = sec->output_section; cie_compute_hash (cie); if (hdr_info->cies == NULL) { hdr_info->cies = htab_try_create (1, cie_hash, cie_eq, free); if (hdr_info->cies == NULL) return cie_inf; } loc = htab_find_slot_with_hash (hdr_info->cies, cie, cie->hash, INSERT); if (loc == NULL) return cie_inf; new_cie = (struct cie *) *loc; if (new_cie == NULL) { /* Keep CIE_INF and record it in the hash table. */ new_cie = malloc (sizeof (struct cie)); if (new_cie == NULL) return cie_inf; memcpy (new_cie, cie, sizeof (struct cie)); *loc = new_cie; } else { /* Merge CIE_INF with NEW_CIE->CIE_INF. */ cie_inf->removed = 1; cie_inf->u.cie.merged = 1; cie_inf->u.cie.u.merged_with = new_cie->cie_inf; if (cie_inf->u.cie.make_lsda_relative) new_cie->cie_inf->u.cie.make_lsda_relative = 1; } return new_cie->cie_inf; }
bfd_boolean _bfd_elf_discard_section_eh_frame (bfd *abfd, struct bfd_link_info *info, asection *sec, bfd_boolean (*reloc_symbol_deleted_p) (bfd_vma, void *), struct elf_reloc_cookie *cookie) { bfd_byte *ehbuf = NULL, *buf; bfd_byte *last_cie, *last_fde; struct cie_header hdr; struct cie cie; struct elf_link_hash_table *htab; struct eh_frame_hdr_info *hdr_info; struct eh_frame_sec_info *sec_info = NULL; unsigned int leb128_tmp; unsigned int cie_usage_count, last_cie_ndx, i, offset; unsigned int make_relative, make_lsda_relative; bfd_size_type new_size; unsigned int ptr_size; if (sec->_raw_size == 0) { /* This file does not contain .eh_frame information. */ return FALSE; } if ((sec->output_section != NULL && bfd_is_abs_section (sec->output_section))) { /* At least one of the sections is being discarded from the link, so we should just ignore them. */ return FALSE; } htab = elf_hash_table (info); hdr_info = &htab->eh_info; /* Read the frame unwind information from abfd. */ ehbuf = bfd_malloc (sec->_raw_size); if (ehbuf == NULL) goto free_no_table; if (! bfd_get_section_contents (abfd, sec, ehbuf, 0, sec->_raw_size)) goto free_no_table; if (sec->_raw_size >= 4 && bfd_get_32 (abfd, ehbuf) == 0 && cookie->rel == cookie->relend) { /* Empty .eh_frame section. */ free (ehbuf); return FALSE; } /* If .eh_frame section size doesn't fit into int, we cannot handle it (it would need to use 64-bit .eh_frame format anyway). */ if (sec->_raw_size != (unsigned int) sec->_raw_size) goto free_no_table; ptr_size = (elf_elfheader (abfd)->e_ident[EI_CLASS] == ELFCLASS64) ? 8 : 4; buf = ehbuf; last_cie = NULL; last_cie_ndx = 0; memset (&cie, 0, sizeof (cie)); cie_usage_count = 0; new_size = sec->_raw_size; make_relative = hdr_info->last_cie.make_relative; make_lsda_relative = hdr_info->last_cie.make_lsda_relative; sec_info = bfd_zmalloc (sizeof (struct eh_frame_sec_info) + 99 * sizeof (struct eh_cie_fde)); if (sec_info == NULL) goto free_no_table; sec_info->alloced = 100; #define ENSURE_NO_RELOCS(buf) \ if (cookie->rel < cookie->relend \ && (cookie->rel->r_offset \ < (bfd_size_type) ((buf) - ehbuf)) \ && cookie->rel->r_info != 0) \ goto free_no_table #define SKIP_RELOCS(buf) \ while (cookie->rel < cookie->relend \ && (cookie->rel->r_offset \ < (bfd_size_type) ((buf) - ehbuf))) \ cookie->rel++ #define GET_RELOC(buf) \ ((cookie->rel < cookie->relend \ && (cookie->rel->r_offset \ == (bfd_size_type) ((buf) - ehbuf))) \ ? cookie->rel : NULL) for (;;) { unsigned char *aug; if (sec_info->count == sec_info->alloced) { sec_info = bfd_realloc (sec_info, sizeof (struct eh_frame_sec_info) + (sec_info->alloced + 99) * sizeof (struct eh_cie_fde)); if (sec_info == NULL) goto free_no_table; memset (&sec_info->entry[sec_info->alloced], 0, 100 * sizeof (struct eh_cie_fde)); sec_info->alloced += 100; } last_fde = buf; /* If we are at the end of the section, we still need to decide on whether to output or discard last encountered CIE (if any). */ if ((bfd_size_type) (buf - ehbuf) == sec->_raw_size) hdr.id = (unsigned int) -1; else { if ((bfd_size_type) (buf + 4 - ehbuf) > sec->_raw_size) /* No space for CIE/FDE header length. */ goto free_no_table; hdr.length = bfd_get_32 (abfd, buf); if (hdr.length == 0xffffffff) /* 64-bit .eh_frame is not supported. */ goto free_no_table; buf += 4; if ((bfd_size_type) (buf - ehbuf) + hdr.length > sec->_raw_size) /* CIE/FDE not contained fully in this .eh_frame input section. */ goto free_no_table; sec_info->entry[sec_info->count].offset = last_fde - ehbuf; sec_info->entry[sec_info->count].size = 4 + hdr.length; if (hdr.length == 0) { /* CIE with length 0 must be only the last in the section. */ if ((bfd_size_type) (buf - ehbuf) < sec->_raw_size) goto free_no_table; ENSURE_NO_RELOCS (buf); sec_info->count++; /* Now just finish last encountered CIE processing and break the loop. */ hdr.id = (unsigned int) -1; } else { hdr.id = bfd_get_32 (abfd, buf); buf += 4; if (hdr.id == (unsigned int) -1) goto free_no_table; } } if (hdr.id == 0 || hdr.id == (unsigned int) -1) { unsigned int initial_insn_length; /* CIE */ if (last_cie != NULL) { /* Now check if this CIE is identical to the last CIE, in which case we can remove it provided we adjust all FDEs. Also, it can be removed if we have removed all FDEs using it. */ if ((!info->relocatable && hdr_info->last_cie_sec && (sec->output_section == hdr_info->last_cie_sec->output_section) && cie_compare (&cie, &hdr_info->last_cie) == 0) || cie_usage_count == 0) { new_size -= cie.hdr.length + 4; sec_info->entry[last_cie_ndx].removed = 1; sec_info->entry[last_cie_ndx].sec = hdr_info->last_cie_sec; sec_info->entry[last_cie_ndx].new_offset = hdr_info->last_cie_offset; } else { hdr_info->last_cie = cie; hdr_info->last_cie_sec = sec; hdr_info->last_cie_offset = last_cie - ehbuf; sec_info->entry[last_cie_ndx].make_relative = cie.make_relative; sec_info->entry[last_cie_ndx].make_lsda_relative = cie.make_lsda_relative; sec_info->entry[last_cie_ndx].per_encoding_relative = (cie.per_encoding & 0x70) == DW_EH_PE_pcrel; } } if (hdr.id == (unsigned int) -1) break; last_cie_ndx = sec_info->count; sec_info->entry[sec_info->count].cie = 1; cie_usage_count = 0; memset (&cie, 0, sizeof (cie)); cie.hdr = hdr; cie.version = *buf++; /* Cannot handle unknown versions. */ if (cie.version != 1) goto free_no_table; if (strlen (buf) > sizeof (cie.augmentation) - 1) goto free_no_table; strcpy (cie.augmentation, buf); buf = strchr (buf, '\0') + 1; ENSURE_NO_RELOCS (buf); if (buf[0] == 'e' && buf[1] == 'h') { /* GCC < 3.0 .eh_frame CIE */ /* We cannot merge "eh" CIEs because __EXCEPTION_TABLE__ is private to each CIE, so we don't need it for anything. Just skip it. */ buf += ptr_size; SKIP_RELOCS (buf); } read_uleb128 (cie.code_align, buf); read_sleb128 (cie.data_align, buf); /* Note - in DWARF2 the return address column is an unsigned byte. In DWARF3 it is a ULEB128. We are following DWARF3. For most ports this will not matter as the value will be less than 128. For the others (eg FRV, SH, MMIX, IA64) they need a fixed GCC which conforms to the DWARF3 standard. */ read_uleb128 (cie.ra_column, buf); ENSURE_NO_RELOCS (buf); cie.lsda_encoding = DW_EH_PE_omit; cie.fde_encoding = DW_EH_PE_omit; cie.per_encoding = DW_EH_PE_omit; aug = cie.augmentation; if (aug[0] != 'e' || aug[1] != 'h') { if (*aug == 'z') { aug++; read_uleb128 (cie.augmentation_size, buf); ENSURE_NO_RELOCS (buf); } while (*aug != '\0') switch (*aug++) { case 'L': cie.lsda_encoding = *buf++; ENSURE_NO_RELOCS (buf); if (get_DW_EH_PE_width (cie.lsda_encoding, ptr_size) == 0) goto free_no_table; break; case 'R': cie.fde_encoding = *buf++; ENSURE_NO_RELOCS (buf); if (get_DW_EH_PE_width (cie.fde_encoding, ptr_size) == 0) goto free_no_table; break; case 'P': { int per_width; cie.per_encoding = *buf++; per_width = get_DW_EH_PE_width (cie.per_encoding, ptr_size); if (per_width == 0) goto free_no_table; if ((cie.per_encoding & 0xf0) == DW_EH_PE_aligned) buf = (ehbuf + ((buf - ehbuf + per_width - 1) & ~((bfd_size_type) per_width - 1))); ENSURE_NO_RELOCS (buf); /* Ensure we have a reloc here, against a global symbol. */ if (GET_RELOC (buf) != NULL) { unsigned long r_symndx; #ifdef BFD64 if (ptr_size == 8) r_symndx = ELF64_R_SYM (cookie->rel->r_info); else #endif r_symndx = ELF32_R_SYM (cookie->rel->r_info); if (r_symndx >= cookie->locsymcount) { struct elf_link_hash_entry *h; r_symndx -= cookie->extsymoff; h = cookie->sym_hashes[r_symndx]; 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; cie.personality = h; } cookie->rel++; } buf += per_width; } break; default: /* Unrecognized augmentation. Better bail out. */ goto free_no_table; } } /* For shared libraries, try to get rid of as many RELATIVE relocs as possible. */ if (info->shared && (get_elf_backend_data (abfd) ->elf_backend_can_make_relative_eh_frame (abfd, info, sec)) && (cie.fde_encoding & 0xf0) == DW_EH_PE_absptr) cie.make_relative = 1; if (info->shared && (get_elf_backend_data (abfd) ->elf_backend_can_make_lsda_relative_eh_frame (abfd, info, sec)) && (cie.lsda_encoding & 0xf0) == DW_EH_PE_absptr) cie.make_lsda_relative = 1; /* If FDE encoding was not specified, it defaults to DW_EH_absptr. */ if (cie.fde_encoding == DW_EH_PE_omit) cie.fde_encoding = DW_EH_PE_absptr; initial_insn_length = cie.hdr.length - (buf - last_fde - 4); if (initial_insn_length <= 50) { cie.initial_insn_length = initial_insn_length; memcpy (cie.initial_instructions, buf, initial_insn_length); } buf += initial_insn_length; ENSURE_NO_RELOCS (buf); last_cie = last_fde; } else { /* Ensure this FDE uses the last CIE encountered. */ if (last_cie == NULL || hdr.id != (unsigned int) (buf - 4 - last_cie)) goto free_no_table; ENSURE_NO_RELOCS (buf); if (GET_RELOC (buf) == NULL) /* This should not happen. */ goto free_no_table; if ((*reloc_symbol_deleted_p) (buf - ehbuf, cookie)) { /* This is a FDE against a discarded section. It should be deleted. */ new_size -= hdr.length + 4; sec_info->entry[sec_info->count].removed = 1; } else { if (info->shared && (((cie.fde_encoding & 0xf0) == DW_EH_PE_absptr && cie.make_relative == 0) || (cie.fde_encoding & 0xf0) == DW_EH_PE_aligned)) { /* If a shared library uses absolute pointers which we cannot turn into PC relative, don't create the binary search table, since it is affected by runtime relocations. */ hdr_info->table = FALSE; } cie_usage_count++; hdr_info->fde_count++; } if (cie.lsda_encoding != DW_EH_PE_omit) { unsigned int dummy; aug = buf; buf += 2 * get_DW_EH_PE_width (cie.fde_encoding, ptr_size); if (cie.augmentation[0] == 'z') read_uleb128 (dummy, buf); /* If some new augmentation data is added before LSDA in FDE augmentation area, this need to be adjusted. */ sec_info->entry[sec_info->count].lsda_offset = (buf - aug); } buf = last_fde + 4 + hdr.length; SKIP_RELOCS (buf); } sec_info->entry[sec_info->count].fde_encoding = cie.fde_encoding; sec_info->entry[sec_info->count].lsda_encoding = cie.lsda_encoding; sec_info->count++; } elf_section_data (sec)->sec_info = sec_info; sec->sec_info_type = ELF_INFO_TYPE_EH_FRAME; /* Ok, now we can assign new offsets. */ offset = 0; last_cie_ndx = 0; for (i = 0; i < sec_info->count; i++) { if (! sec_info->entry[i].removed) { sec_info->entry[i].new_offset = offset; offset += sec_info->entry[i].size; if (sec_info->entry[i].cie) { last_cie_ndx = i; make_relative = sec_info->entry[i].make_relative; make_lsda_relative = sec_info->entry[i].make_lsda_relative; } else { sec_info->entry[i].make_relative = make_relative; sec_info->entry[i].make_lsda_relative = make_lsda_relative; sec_info->entry[i].per_encoding_relative = 0; } } else if (sec_info->entry[i].cie && sec_info->entry[i].sec == sec) { /* Need to adjust new_offset too. */ BFD_ASSERT (sec_info->entry[last_cie_ndx].offset == sec_info->entry[i].new_offset); sec_info->entry[i].new_offset = sec_info->entry[last_cie_ndx].new_offset; } } if (hdr_info->last_cie_sec == sec) { BFD_ASSERT (sec_info->entry[last_cie_ndx].offset == hdr_info->last_cie_offset); hdr_info->last_cie_offset = sec_info->entry[last_cie_ndx].new_offset; } /* FIXME: Currently it is not possible to shrink sections to zero size at this point, so build a fake minimal CIE. */ if (new_size == 0) new_size = 16; /* Shrink the sec as needed. */ sec->_cooked_size = new_size; if (sec->_cooked_size == 0) sec->flags |= SEC_EXCLUDE; free (ehbuf); return new_size != sec->_raw_size; free_no_table: if (ehbuf) free (ehbuf); if (sec_info) free (sec_info); hdr_info->table = FALSE; hdr_info->last_cie.hdr.length = 0; return FALSE; }
/******************************************************* Function: get_command_line *******************************************************/ string * get_command_line(bfd *abfd, string in_path, string out_path, int *arg_count) { static const_string default_compilation_flags[] = DEFAULT_COMPILATION_FLAGS; int i; int argc = 0; string *old_argv; string *new_argv; Elf_Internal_Ehdr *ehdr = elf_elfheader (abfd); for (i = 1; i < (int)ehdr->e_shnum; i++) { Elf_Internal_Shdr *p_shdr = elf_elfsections (abfd)[i]; if (p_shdr->sh_info == WT_COMP_FLAGS) { char *base_addr; int j; ELF_WORD *args; if (p_shdr->sh_size <= 1) continue; base_addr = (char *) p_shdr->contents; argc = (int)(*((ELF_WORD *) base_addr)); args = (ELF_WORD *) (base_addr + sizeof(ELF_WORD)); old_argv = (string *) ALLOCA (sizeof(string) * argc); MALLOC_ASSERT (old_argv); for (j = 0; j < argc; j++) { OBJ_ASSERT (args[j] < (ELF_WORD)p_shdr->sh_size, abfd, "invalid WT_COMP_FLAGS WHIRL section"); old_argv[j] = base_addr + args[j]; } break; } } if (argc == 0) { argc = DEFAULT_COMPILATION_ARGC; old_argv = default_compilation_flags; } new_argv = (string *) MALLOC ((argc + 6) * sizeof(string)); MALLOC_ASSERT (new_argv); for (i = 0; i < argc; i++) new_argv[i] = old_argv[i]; new_argv[argc++] = "-64"; new_argv[argc++] = in_path; new_argv[argc++] = "-o"; new_argv[argc++] = out_path; new_argv[argc++] = "-c"; new_argv[argc] = 0; *arg_count = argc; return new_argv; } /* get_command_line */
static enum gdb_osabi generic_elf_osabi_sniffer (bfd *abfd) { unsigned int elfosabi; enum gdb_osabi osabi = GDB_OSABI_UNKNOWN; elfosabi = elf_elfheader (abfd)->e_ident[EI_OSABI]; switch (elfosabi) { case ELFOSABI_NONE: case ELFOSABI_GNU: /* When the EI_OSABI field in the ELF header is ELFOSABI_NONE (0), then the ELF structures in the file are conforming to the base specification for that machine (there are no OS-specific extensions). In order to determine the real OS in use, we must look for OS-specific notes. The same applies for ELFOSABI_GNU: this can mean GNU/Hurd, GNU/Linux, and possibly more. */ bfd_map_over_sections (abfd, generic_elf_osabi_sniff_abi_tag_sections, &osabi); break; case ELFOSABI_FREEBSD: osabi = GDB_OSABI_FREEBSD_ELF; break; case ELFOSABI_NETBSD: osabi = GDB_OSABI_NETBSD_ELF; break; case ELFOSABI_SOLARIS: osabi = GDB_OSABI_SOLARIS; break; case ELFOSABI_HPUX: /* For some reason the default value for the EI_OSABI field is ELFOSABI_HPUX for all PA-RISC targets (with the exception of GNU/Linux). We use HP-UX ELF as the default, but let any OS-specific notes override this. */ osabi = GDB_OSABI_HPUX_ELF; bfd_map_over_sections (abfd, generic_elf_osabi_sniff_abi_tag_sections, &osabi); break; case ELFOSABI_OPENVMS: osabi = GDB_OSABI_OPENVMS; break; } if (osabi == GDB_OSABI_UNKNOWN) { /* The FreeBSD folks have been naughty; they stored the string "FreeBSD" in the padding of the e_ident field of the ELF header to "brand" their ELF binaries in FreeBSD 3.x. */ if (memcmp (&elf_elfheader (abfd)->e_ident[8], "FreeBSD", sizeof ("FreeBSD")) == 0) osabi = GDB_OSABI_FREEBSD_ELF; } return osabi; }
static struct mdebug_extra_func_info * non_heuristic_proc_desc (CORE_ADDR pc, CORE_ADDR *addrptr) { CORE_ADDR startaddr; struct mdebug_extra_func_info *proc_desc; struct block *b = block_for_pc (pc); struct symbol *sym; struct obj_section *sec; struct mips_objfile_private *priv; find_pc_partial_function (pc, NULL, &startaddr, NULL); if (addrptr) *addrptr = startaddr; priv = NULL; sec = find_pc_section (pc); if (sec != NULL) { priv = (struct mips_objfile_private *) objfile_data (sec->objfile, mips_pdr_data); /* Search the ".pdr" section generated by GAS. This includes most of the information normally found in ECOFF PDRs. */ the_bfd = sec->objfile->obfd; if (priv == NULL && (the_bfd->format == bfd_object && bfd_get_flavour (the_bfd) == bfd_target_elf_flavour && elf_elfheader (the_bfd)->e_ident[EI_CLASS] == ELFCLASS64)) { /* Right now GAS only outputs the address as a four-byte sequence. This means that we should not bother with this method on 64-bit targets (until that is fixed). */ priv = obstack_alloc (&sec->objfile->objfile_obstack, sizeof (struct mips_objfile_private)); priv->size = 0; set_objfile_data (sec->objfile, mips_pdr_data, priv); } else if (priv == NULL) { asection *bfdsec; priv = obstack_alloc (&sec->objfile->objfile_obstack, sizeof (struct mips_objfile_private)); bfdsec = bfd_get_section_by_name (sec->objfile->obfd, ".pdr"); if (bfdsec != NULL) { priv->size = bfd_section_size (sec->objfile->obfd, bfdsec); priv->contents = obstack_alloc (&sec->objfile->objfile_obstack, priv->size); bfd_get_section_contents (sec->objfile->obfd, bfdsec, priv->contents, 0, priv->size); /* In general, the .pdr section is sorted. However, in the presence of multiple code sections (and other corner cases) it can become unsorted. Sort it so that we can use a faster binary search. */ qsort (priv->contents, priv->size / 32, 32, compare_pdr_entries); } else priv->size = 0; set_objfile_data (sec->objfile, mips_pdr_data, priv); } the_bfd = NULL; if (priv->size != 0) { int low, mid, high; char *ptr; CORE_ADDR pdr_pc; low = 0; high = priv->size / 32; /* We've found a .pdr section describing this objfile. We want to find the entry which describes this code address. The .pdr information is not very descriptive; we have only a function start address. We have to look for the closest entry, because the local symbol at the beginning of this function may have been stripped - so if we ask the symbol table for the start address we may get a preceding global function. */ /* First, find the last .pdr entry starting at or before PC. */ do { mid = (low + high) / 2; ptr = priv->contents + mid * 32; pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); pdr_pc += ANOFFSET (sec->objfile->section_offsets, SECT_OFF_TEXT (sec->objfile)); if (pdr_pc > pc) high = mid; else low = mid + 1; } while (low != high); /* Both low and high point one past the PDR of interest. If both are zero, that means this PC is before any region covered by a PDR, i.e. pdr_pc for the first PDR entry is greater than PC. */ if (low > 0) { ptr = priv->contents + (low - 1) * 32; pdr_pc = bfd_get_signed_32 (sec->objfile->obfd, ptr); pdr_pc += ANOFFSET (sec->objfile->section_offsets, SECT_OFF_TEXT (sec->objfile)); } /* We don't have a range, so we have no way to know for sure whether we're in the correct PDR or a PDR for a preceding function and the current function was a stripped local symbol. But if the PDR's PC is at least as great as the best guess from the symbol table, assume that it does cover the right area; if a .pdr section is present at all then nearly every function will have an entry. The biggest exception will be the dynamic linker stubs; conveniently these are placed before .text instead of after. */ if (pc >= pdr_pc && pdr_pc >= startaddr) { struct symbol *sym = find_pc_function (pc); if (addrptr) *addrptr = pdr_pc; /* Fill in what we need of the proc_desc. */ proc_desc = (struct mdebug_extra_func_info *) obstack_alloc (&sec->objfile->objfile_obstack, sizeof (struct mdebug_extra_func_info)); PROC_LOW_ADDR (proc_desc) = pdr_pc; PROC_FRAME_OFFSET (proc_desc) = bfd_get_signed_32 (sec->objfile->obfd, ptr + 20); PROC_FRAME_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 24); PROC_REG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 4); PROC_FREG_MASK (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 12); PROC_REG_OFFSET (proc_desc) = bfd_get_signed_32 (sec->objfile->obfd, ptr + 8); PROC_FREG_OFFSET (proc_desc) = bfd_get_signed_32 (sec->objfile->obfd, ptr + 16); PROC_PC_REG (proc_desc) = bfd_get_32 (sec->objfile->obfd, ptr + 28); proc_desc->pdr.isym = (long) sym; return proc_desc; } } } if (b == NULL) return NULL; if (startaddr > BLOCK_START (b)) { /* This is the "pathological" case referred to in a comment in print_frame_info. It might be better to move this check into symbol reading. */ return NULL; } sym = lookup_symbol (MDEBUG_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0); /* If we never found a PDR for this function in symbol reading, then examine prologues to find the information. */ if (sym) { proc_desc = (struct mdebug_extra_func_info *) SYMBOL_VALUE (sym); if (PROC_FRAME_REG (proc_desc) == -1) return NULL; else return proc_desc; } else return NULL; }