/* Create a dummy BFD. */ bfd * plugin_get_ir_dummy_bfd (const char *name, bfd *srctemplate) { bfd *abfd; bfd_use_reserved_id = 1; abfd = bfd_create (concat (name, IRONLY_SUFFIX, (const char *) NULL), srctemplate); if (abfd != NULL) { abfd->flags |= BFD_LINKER_CREATED | BFD_PLUGIN; bfd_set_arch_info (abfd, bfd_get_arch_info (srctemplate)); bfd_set_gp_size (abfd, bfd_get_gp_size (srctemplate)); if (bfd_make_writable (abfd) && bfd_copy_private_bfd_data (srctemplate, abfd)) { flagword flags; /* Create section to own the symbols. */ flags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE); if (bfd_make_section_anyway_with_flags (abfd, ".text", flags)) return abfd; } } einfo (_("could not create dummy IR bfd: %F%E\n")); return NULL; }
static asection * make_bfd_asection (bfd *abfd, const char *name, flagword flags, bfd_size_type size, bfd_vma vma, unsigned int alignment_power) { asection *asect; char *newname; newname = bfd_alloc (abfd, (bfd_size_type) strlen (name) + 1); if (!newname) return NULL; strcpy (newname, name); asect = bfd_make_section_anyway_with_flags (abfd, newname, flags); if (!asect) return NULL; asect->size = size; asect->vma = vma; asect->filepos = bfd_tell (abfd); asect->alignment_power = alignment_power; return asect; }
static asection * make_bfd_asection (bfd *abfd, const char *name, flagword flags, bfd_size_type size, bfd_vma vma, file_ptr filepos) { asection *asect; asect = bfd_make_section_anyway_with_flags (abfd, name, flags); if (!asect) return NULL; asect->size = size; asect->vma = vma; asect->filepos = filepos; asect->alignment_power = 8; return asect; }
static void write_gcore_file_1 (bfd *obfd) { struct cleanup *cleanup; void *note_data = NULL; int note_size = 0; asection *note_sec = NULL; /* An external target method must build the notes section. */ /* FIXME: uweigand/2011-10-06: All architectures that support core file generation should be converted to gdbarch_make_corefile_notes; at that point, the target vector method can be removed. */ if (!gdbarch_make_corefile_notes_p (target_gdbarch ())) note_data = target_make_corefile_notes (obfd, ¬e_size); else note_data = gdbarch_make_corefile_notes (target_gdbarch (), obfd, ¬e_size); cleanup = make_cleanup (xfree, note_data); if (note_data == NULL || note_size == 0) error (_("Target does not support core file generation.")); /* Create the note section. */ note_sec = bfd_make_section_anyway_with_flags (obfd, "note0", SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC); if (note_sec == NULL) error (_("Failed to create 'note' section for corefile: %s"), bfd_errmsg (bfd_get_error ())); bfd_set_section_vma (obfd, note_sec, 0); bfd_set_section_alignment (obfd, note_sec, 0); bfd_set_section_size (obfd, note_sec, note_size); /* Now create the memory/load sections. */ if (gcore_memory_sections (obfd) == 0) error (_("gcore: failed to get corefile memory sections from target.")); /* Write out the contents of the note section. */ if (!bfd_set_section_contents (obfd, note_sec, note_data, 0, note_size)) warning (_("writing note section (%s)"), bfd_errmsg (bfd_get_error ())); do_cleanups (cleanup); }
static const bfd_target * netbsd_core_file_p (bfd *abfd) { int val; unsigned i; file_ptr offset; asection *asect; struct core core; struct coreseg coreseg; bfd_size_type amt = sizeof core; val = bfd_bread (&core, amt, abfd); if (val != sizeof core) { /* Too small to be a core file. */ bfd_set_error (bfd_error_wrong_format); return 0; } if (CORE_GETMAGIC (core) != COREMAGIC) { bfd_set_error (bfd_error_wrong_format); return 0; } amt = sizeof (struct netbsd_core_struct); rawptr = (struct netbsd_core_struct *) bfd_zalloc (abfd, amt); if (rawptr == NULL) return 0; rawptr->core = core; abfd->tdata.netbsd_core_data = rawptr; offset = core.c_hdrsize; for (i = 0; i < core.c_nseg; i++) { const char *sname; flagword flags; if (bfd_seek (abfd, offset, SEEK_SET) != 0) goto punt; val = bfd_bread (&coreseg, sizeof coreseg, abfd); if (val != sizeof coreseg) { bfd_set_error (bfd_error_file_truncated); goto punt; } if (CORE_GETMAGIC (coreseg) != CORESEGMAGIC) { bfd_set_error (bfd_error_wrong_format); goto punt; } offset += core.c_seghdrsize; switch (CORE_GETFLAG (coreseg)) { case CORE_CPU: sname = ".reg"; flags = SEC_ALLOC + SEC_HAS_CONTENTS; break; case CORE_DATA: sname = ".data"; flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; break; case CORE_STACK: sname = ".stack"; flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; break; default: sname = ".unknown"; flags = SEC_ALLOC + SEC_HAS_CONTENTS; break; } asect = bfd_make_section_anyway_with_flags (abfd, sname, flags); if (asect == NULL) goto punt; asect->size = coreseg.c_size; asect->vma = coreseg.c_addr; asect->filepos = offset; asect->alignment_power = 2; if (CORE_GETFLAG (coreseg) == CORE_CPU) { bfd_size_type wcookie_offset; switch (CORE_GETMID (core)) { case M_SPARC_NETBSD: wcookie_offset = SPARC_WCOOKIE_OFFSET; break; case M_SPARC64_OPENBSD: wcookie_offset = SPARC64_WCOOKIE_OFFSET; break; default: wcookie_offset = 0; break; } if (wcookie_offset > 0 && coreseg.c_size > wcookie_offset) { /* Truncate the .reg section. */ asect->size = wcookie_offset; /* And create the .wcookie section. */ flags = SEC_ALLOC + SEC_HAS_CONTENTS; asect = bfd_make_section_anyway_with_flags (abfd, ".wcookie", flags); if (asect == NULL) goto punt; asect->size = coreseg.c_size - wcookie_offset; asect->vma = 0; asect->filepos = offset + wcookie_offset; asect->alignment_power = 2; } } offset += coreseg.c_size; } /* Set architecture from machine ID. */ switch (CORE_GETMID (core)) { case M_ALPHA_NETBSD: bfd_default_set_arch_mach (abfd, bfd_arch_alpha, 0); break; case M_ARM6_NETBSD: bfd_default_set_arch_mach (abfd, bfd_arch_arm, bfd_mach_arm_3); break; case M_X86_64_NETBSD: bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_x86_64); break; case M_386_NETBSD: bfd_default_set_arch_mach (abfd, bfd_arch_i386, bfd_mach_i386_i386); break; case M_68K_NETBSD: case M_68K4K_NETBSD: bfd_default_set_arch_mach (abfd, bfd_arch_m68k, 0); break; case M_88K_OPENBSD: bfd_default_set_arch_mach (abfd, bfd_arch_m88k, 0); break; case M_HPPA_OPENBSD: bfd_default_set_arch_mach (abfd, bfd_arch_hppa, bfd_mach_hppa11); break; case M_POWERPC_NETBSD: bfd_default_set_arch_mach (abfd, bfd_arch_powerpc, bfd_mach_ppc); break; case M_SPARC_NETBSD: bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc); break; case M_SPARC64_NETBSD: case M_SPARC64_OPENBSD: bfd_default_set_arch_mach (abfd, bfd_arch_sparc, bfd_mach_sparc_v9); break; case M_VAX_NETBSD: case M_VAX4K_NETBSD: bfd_default_set_arch_mach (abfd, bfd_arch_vax, 0); break; } /* OK, we believe you. You're a core file (sure, sure). */ return abfd->xvec; punt: bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = NULL; bfd_section_list_clear (abfd); return 0; }
/* Helpers to convert between BFD and GOLD symbol formats. */ static enum ld_plugin_status asymbol_from_plugin_symbol (bfd *abfd, asymbol *asym, const struct ld_plugin_symbol *ldsym) { flagword flags = BSF_NO_FLAGS; struct bfd_section *section; asym->the_bfd = abfd; asym->name = (ldsym->version ? concat (ldsym->name, "@", ldsym->version, (const char *) NULL) : ldsym->name); asym->value = 0; switch (ldsym->def) { case LDPK_WEAKDEF: flags = BSF_WEAK; /* FALLTHRU */ case LDPK_DEF: flags |= BSF_GLOBAL; if (ldsym->comdat_key) { char *name = concat (".gnu.linkonce.t.", ldsym->comdat_key, (const char *) NULL); section = bfd_get_section_by_name (abfd, name); if (section != NULL) free (name); else { flagword sflags; sflags = (SEC_CODE | SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC | SEC_LOAD | SEC_KEEP | SEC_EXCLUDE | SEC_LINK_ONCE | SEC_LINK_DUPLICATES_DISCARD); section = bfd_make_section_anyway_with_flags (abfd, name, sflags); if (section == NULL) return LDPS_ERR; } } else section = bfd_get_section_by_name (abfd, ".text"); break; case LDPK_WEAKUNDEF: flags = BSF_WEAK; /* FALLTHRU */ case LDPK_UNDEF: section = bfd_und_section_ptr; break; case LDPK_COMMON: flags = BSF_GLOBAL; section = bfd_com_section_ptr; asym->value = ldsym->size; /* For ELF targets, set alignment of common symbol to 1. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) { ((elf_symbol_type *) asym)->internal_elf_sym.st_shndx = SHN_COMMON; ((elf_symbol_type *) asym)->internal_elf_sym.st_value = 1; } break; default: return LDPS_ERR; } asym->flags = flags; asym->section = section; /* Visibility only applies on ELF targets. */ if (bfd_get_flavour (abfd) == bfd_target_elf_flavour) { elf_symbol_type *elfsym = elf_symbol_from (abfd, asym); unsigned char visibility; if (!elfsym) einfo (_("%P%F: %s: non-ELF symbol in ELF BFD!\n"), asym->name); switch (ldsym->visibility) { default: einfo (_("%P%F: unknown ELF symbol visibility: %d!\n"), ldsym->visibility); case LDPV_DEFAULT: visibility = STV_DEFAULT; break; case LDPV_PROTECTED: visibility = STV_PROTECTED; break; case LDPV_INTERNAL: visibility = STV_INTERNAL; break; case LDPV_HIDDEN: visibility = STV_HIDDEN; break; } elfsym->internal_elf_sym.st_other = (visibility | (elfsym->internal_elf_sym.st_other & ~ELF_ST_VISIBILITY (-1))); } return LDPS_OK; }
sec_ptr bfd_make_section_anyway (bfd *abfd, const char *name) { return bfd_make_section_anyway_with_flags (abfd, name, 0); }
static void gcore_command (char *args, int from_tty) { struct cleanup *old_chain; char *corefilename, corefilename_buffer[40]; asection *note_sec = NULL; bfd *obfd; void *note_data = NULL; int note_size = 0; /* No use generating a corefile without a target process. */ if (!target_has_execution) noprocess (); if (args && *args) corefilename = args; else { /* Default corefile name is "core.PID". */ sprintf (corefilename_buffer, "core.%d", PIDGET (inferior_ptid)); corefilename = corefilename_buffer; } if (info_verbose) fprintf_filtered (gdb_stdout, "Opening corefile '%s' for output.\n", corefilename); /* Open the output file. */ obfd = bfd_openw (corefilename, default_gcore_target ()); if (!obfd) error (_("Failed to open '%s' for output."), corefilename); /* Need a cleanup that will close the file (FIXME: delete it?). */ old_chain = make_cleanup_bfd_close (obfd); bfd_set_format (obfd, bfd_core); bfd_set_arch_mach (obfd, default_gcore_arch (), default_gcore_mach ()); /* An external target method must build the notes section. */ note_data = target_make_corefile_notes (obfd, ¬e_size); /* Create the note section. */ if (note_data != NULL && note_size != 0) { note_sec = bfd_make_section_anyway_with_flags (obfd, "note0", SEC_HAS_CONTENTS | SEC_READONLY | SEC_ALLOC); if (note_sec == NULL) error (_("Failed to create 'note' section for corefile: %s"), bfd_errmsg (bfd_get_error ())); bfd_set_section_vma (obfd, note_sec, 0); bfd_set_section_alignment (obfd, note_sec, 0); bfd_set_section_size (obfd, note_sec, note_size); } /* Now create the memory/load sections. */ if (gcore_memory_sections (obfd) == 0) error (_("gcore: failed to get corefile memory sections from target.")); /* Write out the contents of the note section. */ if (note_data != NULL && note_size != 0) { if (!bfd_set_section_contents (obfd, note_sec, note_data, 0, note_size)) warning (_("writing note section (%s)"), bfd_errmsg (bfd_get_error ())); } /* Succeeded. */ fprintf_filtered (gdb_stdout, "Saved corefile %s\n", corefilename); /* Clean-ups will close the output file and free malloc memory. */ do_cleanups (old_chain); return; }
void replace_hello(const char *input_path, const char *output_path) { bfd_init(); bfd *ibfd = bfd_openr(input_path, NULL); if (ibfd == NULL) errx(1, bfd_errmsg(bfd_get_error())); if (!bfd_check_format(ibfd, bfd_object)) { bfd_close_all_done(ibfd); errx(1, "Input file is not a valid object file."); } bfd *obfd = bfd_openw(output_path, bfd_get_target(ibfd)); if (obfd == NULL) { bfd_close_all_done(ibfd); errx(1, bfd_errmsg(bfd_get_error())); } if (!bfd_set_format(obfd, bfd_get_format(ibfd))) { bfd_close_all_done(ibfd); bfd_close_all_done(obfd); errx(1, "Setting obfd format failed: %s\n", bfd_errmsg(bfd_get_error())); } bfd_set_arch_info(obfd, bfd_get_arch_info(ibfd)); // Create sections for .data asection *section = bfd_get_section_by_name(ibfd, ".data"); while (section != NULL) { if (section->flags & SEC_HAS_CONTENTS) { char *section_contents = (char *)malloc(section->size); bfd_get_section_contents(ibfd, section, section_contents, 0, section->size); char *hello_pos = (char *)memmem(section_contents, section->size, "hello", 5); if (hello_pos != NULL) { if (bfd_make_section_anyway_with_flags(obfd, ".data", section->flags) == NULL) { free(section_contents); bfd_close_all_done(ibfd); bfd_close_all_done(obfd); errx(1, bfd_errmsg(bfd_get_error())); } } free(section_contents); } section = bfd_get_next_section_by_name(ibfd, section); } asection *comment_section = bfd_make_section_anyway_with_flags(obfd, ".comment.my_objcopy", SEC_HAS_CONTENTS); if (comment_section == NULL) { bfd_close_all_done(ibfd); bfd_close_all_done(obfd); errx(1, bfd_errmsg(bfd_get_error())); } if (!bfd_set_section_size(obfd, comment_section, 3)) { bfd_close_all_done(ibfd); bfd_close_all_done(obfd); errx(1, bfd_errmsg(bfd_get_error())); } if (!bfd_set_section_contents(obfd, comment_section, "moo", 0, 3)) { bfd_close_all_done(ibfd); bfd_close_all_done(obfd); errx(1, bfd_errmsg(bfd_get_error())); } // section = bfd_get_section_by_name(ibfd, ".data"); // asection *osection = bfd_get_section_by_name(obfd, ".data"); // if (osection == NULL) { // bfd_close_all_done(ibfd); // bfd_close_all_done(obfd); // errx(1, bfd_errmsg(bfd_get_error())); // } // while (section != NULL) { // if (section->flags & SEC_HAS_CONTENTS) { // char *section_contents = (char *)malloc(section->size); // bfd_get_section_contents(ibfd, section, section_contents, 0, section->size); // // char *hello_pos = (char *)memmem(section_contents, section->size, "hello", 5); // if (hello_pos != NULL) { // hello_pos[1] = 'o'; // hello_pos[4] = 'a'; // if (bfd_set_section_contents(obfd, osection, section_contents, 0, section->size)) { // free(section_contents); // bfd_close_all_done(ibfd); // bfd_close_all_done(obfd); // errx(1, bfd_errmsg(bfd_get_error())); // } // } // // free(section_contents); // osection = bfd_get_next_section_by_name(obfd, osection); // } // // section = bfd_get_next_section_by_name(ibfd, section); // } if (!bfd_close(obfd)) errx(1, "Closing obfd failed: %s\n", bfd_errmsg(bfd_get_error())); if (!bfd_close(ibfd)) errx(1, "Closing ibfd failed: %s\n", bfd_errmsg(bfd_get_error())); }
static const bfd_target * trad_unix_core_file_p (bfd *abfd) { int val; struct user u; struct trad_core_struct *rawptr; bfd_size_type amt; flagword flags; #ifdef TRAD_CORE_USER_OFFSET /* If defined, this macro is the file position of the user struct. */ if (bfd_seek (abfd, (file_ptr) TRAD_CORE_USER_OFFSET, SEEK_SET) != 0) return 0; #endif val = bfd_bread ((void *) &u, (bfd_size_type) sizeof u, abfd); if (val != sizeof u) { /* Too small to be a core file */ bfd_set_error (bfd_error_wrong_format); return 0; } /* Sanity check perhaps??? */ if (u.u_dsize > 0x1000000) /* Remember, it's in pages... */ { bfd_set_error (bfd_error_wrong_format); return 0; } if (u.u_ssize > 0x1000000) { bfd_set_error (bfd_error_wrong_format); return 0; } /* Check that the size claimed is no greater than the file size. */ { struct stat statbuf; if (bfd_stat (abfd, &statbuf) < 0) return 0; if ((ufile_ptr) NBPG * (UPAGES + u.u_dsize #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE - u.u_tsize #endif + u.u_ssize) > (ufile_ptr) statbuf.st_size) { bfd_set_error (bfd_error_wrong_format); return 0; } #ifndef TRAD_CORE_ALLOW_ANY_EXTRA_SIZE if (((ufile_ptr) NBPG * (UPAGES + u.u_dsize + u.u_ssize) #ifdef TRAD_CORE_EXTRA_SIZE_ALLOWED /* Some systems write the file too big. */ + TRAD_CORE_EXTRA_SIZE_ALLOWED #endif ) < (ufile_ptr) statbuf.st_size) { /* The file is too big. Maybe it's not a core file or we otherwise have bad values for u_dsize and u_ssize). */ bfd_set_error (bfd_error_wrong_format); return 0; } #endif } /* OK, we believe you. You're a core file (sure, sure). */ /* Allocate both the upage and the struct core_data at once, so a single free() will free them both. */ amt = sizeof (struct trad_core_struct); rawptr = (struct trad_core_struct *) bfd_zmalloc (amt); if (rawptr == NULL) return 0; abfd->tdata.trad_core_data = rawptr; rawptr->u = u; /*Copy the uarea into the tdata part of the bfd */ /* Create the sections. */ flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; core_stacksec(abfd) = bfd_make_section_anyway_with_flags (abfd, ".stack", flags); if (core_stacksec (abfd) == NULL) goto fail; core_datasec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".data", flags); if (core_datasec (abfd) == NULL) goto fail; core_regsec (abfd) = bfd_make_section_anyway_with_flags (abfd, ".reg", SEC_HAS_CONTENTS); if (core_regsec (abfd) == NULL) goto fail; core_datasec (abfd)->size = NBPG * u.u_dsize #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE - NBPG * u.u_tsize #endif ; core_stacksec (abfd)->size = NBPG * u.u_ssize; core_regsec (abfd)->size = NBPG * UPAGES; /* Larger than sizeof struct u */ /* What a hack... we'd like to steal it from the exec file, since the upage does not seem to provide it. FIXME. */ #ifdef HOST_DATA_START_ADDR core_datasec (abfd)->vma = HOST_DATA_START_ADDR; #else core_datasec (abfd)->vma = HOST_TEXT_START_ADDR + (NBPG * u.u_tsize); #endif #ifdef HOST_STACK_START_ADDR core_stacksec (abfd)->vma = HOST_STACK_START_ADDR; #else core_stacksec (abfd)->vma = HOST_STACK_END_ADDR - (NBPG * u.u_ssize); #endif /* This is tricky. As the "register section", we give them the entire upage and stack. u.u_ar0 points to where "register 0" is stored. There are two tricks with this, though. One is that the rest of the registers might be at positive or negative (or both) displacements from *u_ar0. The other is that u_ar0 is sometimes an absolute address in kernel memory, and on other systems it is an offset from the beginning of the `struct user'. As a practical matter, we don't know where the registers actually are, so we have to pass the whole area to GDB. We encode the value of u_ar0 by setting the .regs section up so that its virtual memory address 0 is at the place pointed to by u_ar0 (by setting the vma of the start of the section to -u_ar0). GDB uses this info to locate the regs, using minor trickery to get around the offset-or-absolute-addr problem. */ core_regsec (abfd)->vma = - (bfd_vma) (unsigned long) u.u_ar0; core_datasec (abfd)->filepos = NBPG * UPAGES; core_stacksec (abfd)->filepos = (NBPG * UPAGES) + NBPG * u.u_dsize #ifdef TRAD_CORE_DSIZE_INCLUDES_TSIZE - NBPG * u.u_tsize #endif ; core_regsec (abfd)->filepos = 0; /* Register segment is the upage */ /* Align to word at least */ core_stacksec (abfd)->alignment_power = 2; core_datasec (abfd)->alignment_power = 2; core_regsec (abfd)->alignment_power = 2; return abfd->xvec; fail: bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = NULL; bfd_section_list_clear (abfd); return NULL; }
const bfd_target * xcoff64_core_p (bfd *abfd) { enum bfd_architecture arch; unsigned long mach; struct core_dumpxx core, *new_core_hdr; struct stat statbuf; asection *sec; struct __ld_info64 ldinfo; bfd_vma ld_offset; bfd_size_type i; struct vm_infox vminfo; const bfd_target *return_value = NULL; flagword flags; /* Get the header. */ if (bfd_seek (abfd, 0, SEEK_SET) != 0) goto xcoff64_core_p_error; if (sizeof (struct core_dumpxx) != bfd_bread (&core, sizeof (struct core_dumpxx), abfd)) goto xcoff64_core_p_error; if (bfd_stat (abfd, &statbuf) < 0) goto xcoff64_core_p_error; /* Sanity checks c_flag has CORE_VERSION_1, Aix 4+ c_entries = 0 for Aix 4.3+ IS_PROC64 is a macro defined in procinfo.h, test for 64 bit process. We will still be confused if a Aix 4.3 64 bit core file is copied over to a Aix 5 machine. Check file header offsets See rs6000-core.c for comment on size of core If there isn't enough of a real core file, bail. */ if ((CORE_VERSION_1 != (core.c_flag & CORE_VERSION_1)) || (0 != core.c_entries) || (! (IS_PROC64 (&core.c_u.U_proc))) || ((CHECK_FILE_OFFSET (statbuf, core.c_fdsinfox))) || ((CHECK_FILE_OFFSET (statbuf, core.c_loader))) || ((CHECK_FILE_OFFSET (statbuf, core.c_loader + core.c_lsize))) || ((CHECK_FILE_OFFSET (statbuf, core.c_thr))) || ((CHECK_FILE_OFFSET (statbuf, core.c_segregion))) || ((CHECK_FILE_OFFSET (statbuf, core.c_stack))) || ((CHECK_FILE_OFFSET (statbuf, core.c_stack + core.c_size))) || ((CHECK_FILE_OFFSET (statbuf, core.c_data))) || ((CHECK_FILE_OFFSET (statbuf, core.c_data + core.c_datasize))) || (! (core.c_flag & UBLOCK_VALID)) || (! (core.c_flag & LE_VALID))) goto xcoff64_core_p_error; /* Check for truncated stack or general truncating. */ if ((! (core.c_flag & USTACK_VALID)) || (core.c_flag & CORE_TRUNC)) { bfd_set_error (bfd_error_file_truncated); return return_value; } new_core_hdr = bfd_zalloc (abfd, sizeof (struct core_dumpxx)); if (NULL == new_core_hdr) return return_value; memcpy (new_core_hdr, &core, sizeof (struct core_dumpxx)); /* The core_hdr() macro is no longer used here because it would expand to code relying on gcc's cast-as-lvalue extension, which was removed in gcc 4.0. */ abfd->tdata.any = new_core_hdr; /* .stack section. */ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; sec = bfd_make_section_anyway_with_flags (abfd, ".stack", flags); if (NULL == sec) return return_value; sec->size = core.c_size; sec->vma = core.c_stackorg; sec->filepos = core.c_stack; /* .reg section for all registers. */ flags = SEC_HAS_CONTENTS | SEC_IN_MEMORY; sec = bfd_make_section_anyway_with_flags (abfd, ".reg", flags); if (NULL == sec) return return_value; sec->size = sizeof (struct __context64); sec->vma = 0; sec->filepos = 0; sec->contents = (bfd_byte *)&new_core_hdr->c_flt.r64; /* .ldinfo section. To actually find out how long this section is in this particular core dump would require going down the whole list of struct ld_info's. See if we can just fake it. */ flags = SEC_HAS_CONTENTS; sec = bfd_make_section_anyway_with_flags (abfd, ".ldinfo", flags); if (NULL == sec) return return_value; sec->size = core.c_lsize; sec->vma = 0; sec->filepos = core.c_loader; /* AIX 4 adds data sections from loaded objects to the core file, which can be found by examining ldinfo, and anonymously mmapped regions. */ /* .data section from executable. */ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags); if (NULL == sec) return return_value; sec->size = core.c_datasize; sec->vma = core.c_dataorg; sec->filepos = core.c_data; /* .data sections from loaded objects. */ ld_offset = core.c_loader; while (1) { if (bfd_seek (abfd, ld_offset, SEEK_SET) != 0) return return_value; if (sizeof (struct __ld_info64) != bfd_bread (&ldinfo, sizeof (struct __ld_info64), abfd)) return return_value; if (ldinfo.ldinfo_core) { flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; sec = bfd_make_section_anyway_with_flags (abfd, ".data", flags); if (NULL == sec) return return_value; sec->size = ldinfo.ldinfo_datasize; sec->vma = ldinfo.ldinfo_dataorg; sec->filepos = ldinfo.ldinfo_core; } if (0 == ldinfo.ldinfo_next) break; ld_offset += ldinfo.ldinfo_next; } /* .vmdata sections from anonymously mmapped regions. */ if (core.c_vmregions) { if (bfd_seek (abfd, core.c_vmm, SEEK_SET) != 0) return return_value; for (i = 0; i < core.c_vmregions; i++) if (sizeof (struct vm_infox) != bfd_bread (&vminfo, sizeof (struct vm_infox), abfd)) return return_value; if (vminfo.vminfo_offset) { flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; sec = bfd_make_section_anyway_with_flags (abfd, ".vmdata", flags); if (NULL == sec) return return_value; sec->size = vminfo.vminfo_size; sec->vma = vminfo.vminfo_addr; sec->filepos = vminfo.vminfo_offset; } } /* Set the architecture and machine. */ arch = DEFAULT_ARCHITECTURE; mach = DEFAULT_MACHINE; bfd_default_set_arch_mach (abfd, arch, mach); return_value = (bfd_target *) abfd->xvec; /* This is garbage for now. */ xcoff64_core_p_error: if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return return_value; }
bfd_boolean _bfd_link_section_stabs (bfd *abfd, struct stab_info *sinfo, asection *stabsec, asection *stabstrsec, void * *psecinfo, bfd_size_type *pstring_offset) { bfd_boolean first; bfd_size_type count, amt; struct stab_section_info *secinfo; bfd_byte *stabbuf = NULL; bfd_byte *stabstrbuf = NULL; bfd_byte *sym, *symend; bfd_size_type stroff, next_stroff, skip; bfd_size_type *pstridx; if (stabsec->size == 0 || stabstrsec->size == 0) /* This file does not contain stabs debugging information. */ return TRUE; if (stabsec->size % STABSIZE != 0) /* Something is wrong with the format of these stab symbols. Don't try to optimize them. */ return TRUE; if ((stabstrsec->flags & SEC_RELOC) != 0) /* We shouldn't see relocations in the strings, and we aren't prepared to handle them. */ return TRUE; if (bfd_is_abs_section (stabsec->output_section) || bfd_is_abs_section (stabstrsec->output_section)) /* At least one of the sections is being discarded from the link, so we should just ignore them. */ return TRUE; first = FALSE; if (sinfo->stabstr == NULL) { flagword flags; /* Initialize the stabs information we need to keep track of. */ first = TRUE; sinfo->strings = _bfd_stringtab_init (); if (sinfo->strings == NULL) goto error_return; /* Make sure the first byte is zero. */ (void) _bfd_stringtab_add (sinfo->strings, "", TRUE, TRUE); if (! bfd_hash_table_init (&sinfo->includes, stab_link_includes_newfunc, sizeof (struct stab_link_includes_entry))) goto error_return; flags = (SEC_HAS_CONTENTS | SEC_READONLY | SEC_DEBUGGING | SEC_LINKER_CREATED); sinfo->stabstr = bfd_make_section_anyway_with_flags (abfd, ".stabstr", flags); if (sinfo->stabstr == NULL) goto error_return; } /* Initialize the information we are going to store for this .stab section. */ count = stabsec->size / STABSIZE; amt = sizeof (struct stab_section_info); amt += (count - 1) * sizeof (bfd_size_type); *psecinfo = bfd_alloc (abfd, amt); if (*psecinfo == NULL) goto error_return; secinfo = (struct stab_section_info *) *psecinfo; secinfo->excls = NULL; stabsec->rawsize = stabsec->size; secinfo->cumulative_skips = NULL; memset (secinfo->stridxs, 0, (size_t) count * sizeof (bfd_size_type)); /* Read the stabs information from abfd. */ if (!bfd_malloc_and_get_section (abfd, stabsec, &stabbuf) || !bfd_malloc_and_get_section (abfd, stabstrsec, &stabstrbuf)) goto error_return; /* Look through the stabs symbols, work out the new string indices, and identify N_BINCL symbols which can be eliminated. */ stroff = 0; /* The stabs sections can be split when -split-by-reloc/-split-by-file is used. We must keep track of each stab section's place in the single concatenated string table. */ next_stroff = pstring_offset ? *pstring_offset : 0; skip = 0; symend = stabbuf + stabsec->size; for (sym = stabbuf, pstridx = secinfo->stridxs; sym < symend; sym += STABSIZE, ++pstridx) { bfd_size_type symstroff; int type; const char *string; if (*pstridx != 0) /* This symbol has already been handled by an N_BINCL pass. */ continue; type = sym[TYPEOFF]; if (type == 0) { /* Special type 0 stabs indicate the offset to the next string table. We only copy the very first one. */ stroff = next_stroff; next_stroff += bfd_get_32 (abfd, sym + 8); if (pstring_offset) *pstring_offset = next_stroff; if (! first) { *pstridx = (bfd_size_type) -1; ++skip; continue; } first = FALSE; } /* Store the string in the hash table, and record the index. */ symstroff = stroff + bfd_get_32 (abfd, sym + STRDXOFF); if (symstroff >= stabstrsec->size) { _bfd_error_handler /* xgettext:c-format */ (_("%B(%A+0x%lx): Stabs entry has invalid string index."), abfd, stabsec, (long) (sym - stabbuf)); bfd_set_error (bfd_error_bad_value); goto error_return; } string = (char *) stabstrbuf + symstroff; *pstridx = _bfd_stringtab_add (sinfo->strings, string, TRUE, TRUE); /* An N_BINCL symbol indicates the start of the stabs entries for a header file. We need to scan ahead to the next N_EINCL symbol, ignoring nesting, adding up all the characters in the symbol names, not including the file numbers in types (the first number after an open parenthesis). */ if (type == (int) N_BINCL) { bfd_vma sum_chars; bfd_vma num_chars; bfd_vma buf_len = 0; char * symb; char * symb_rover; int nest; bfd_byte * incl_sym; struct stab_link_includes_entry * incl_entry; struct stab_link_includes_totals * t; struct stab_excl_list * ne; symb = symb_rover = NULL; sum_chars = num_chars = 0; nest = 0; for (incl_sym = sym + STABSIZE; incl_sym < symend; incl_sym += STABSIZE) { int incl_type; incl_type = incl_sym[TYPEOFF]; if (incl_type == 0) break; else if (incl_type == (int) N_EXCL) continue; else if (incl_type == (int) N_EINCL) { if (nest == 0) break; --nest; } else if (incl_type == (int) N_BINCL) ++nest; else if (nest == 0) { const char *str; str = ((char *) stabstrbuf + stroff + bfd_get_32 (abfd, incl_sym + STRDXOFF)); for (; *str != '\0'; str++) { if (num_chars >= buf_len) { buf_len += 32 * 1024; symb = (char *) bfd_realloc_or_free (symb, buf_len); if (symb == NULL) goto error_return; symb_rover = symb + num_chars; } * symb_rover ++ = * str; sum_chars += *str; num_chars ++; if (*str == '(') { /* Skip the file number. */ ++str; while (ISDIGIT (*str)) ++str; --str; } } } } BFD_ASSERT (num_chars == (bfd_vma) (symb_rover - symb)); /* If we have already included a header file with the same value, then replaced this one with an N_EXCL symbol. */ incl_entry = (struct stab_link_includes_entry * ) bfd_hash_lookup (&sinfo->includes, string, TRUE, TRUE); if (incl_entry == NULL) goto error_return; for (t = incl_entry->totals; t != NULL; t = t->next) if (t->sum_chars == sum_chars && t->num_chars == num_chars && memcmp (t->symb, symb, num_chars) == 0) break; /* Record this symbol, so that we can set the value correctly. */ amt = sizeof *ne; ne = (struct stab_excl_list *) bfd_alloc (abfd, amt); if (ne == NULL) goto error_return; ne->offset = sym - stabbuf; ne->val = sum_chars; ne->type = (int) N_BINCL; ne->next = secinfo->excls; secinfo->excls = ne; if (t == NULL) { /* This is the first time we have seen this header file with this set of stabs strings. */ t = (struct stab_link_includes_totals *) bfd_hash_allocate (&sinfo->includes, sizeof *t); if (t == NULL) goto error_return; t->sum_chars = sum_chars; t->num_chars = num_chars; /* Trim data down. */ t->symb = symb = (char *) bfd_realloc_or_free (symb, num_chars); t->next = incl_entry->totals; incl_entry->totals = t; } else { bfd_size_type *incl_pstridx; /* We have seen this header file before. Tell the final pass to change the type to N_EXCL. */ ne->type = (int) N_EXCL; /* Free off superfluous symbols. */ free (symb); /* Mark the skipped symbols. */ nest = 0; for (incl_sym = sym + STABSIZE, incl_pstridx = pstridx + 1; incl_sym < symend; incl_sym += STABSIZE, ++incl_pstridx) { int incl_type; incl_type = incl_sym[TYPEOFF]; if (incl_type == (int) N_EINCL) { if (nest == 0) { *incl_pstridx = (bfd_size_type) -1; ++skip; break; } --nest; } else if (incl_type == (int) N_BINCL) ++nest; else if (incl_type == (int) N_EXCL) /* Keep existing exclusion marks. */ continue; else if (nest == 0) { *incl_pstridx = (bfd_size_type) -1; ++skip; } } } } } free (stabbuf); stabbuf = NULL; free (stabstrbuf); stabstrbuf = NULL; /* We need to set the section sizes such that the linker will compute the output section sizes correctly. We set the .stab size to not include the entries we don't want. We set SEC_EXCLUDE for the .stabstr section, so that it will be dropped from the link. We record the size of the strtab in the first .stabstr section we saw, and make sure we don't set SEC_EXCLUDE for that section. */ stabsec->size = (count - skip) * STABSIZE; if (stabsec->size == 0) stabsec->flags |= SEC_EXCLUDE | SEC_KEEP; stabstrsec->flags |= SEC_EXCLUDE | SEC_KEEP; sinfo->stabstr->size = _bfd_stringtab_size (sinfo->strings); /* Calculate the `cumulative_skips' array now that stabs have been deleted for this section. */ if (skip != 0) { bfd_size_type i, offset; bfd_size_type *pskips; amt = count * sizeof (bfd_size_type); secinfo->cumulative_skips = (bfd_size_type *) bfd_alloc (abfd, amt); if (secinfo->cumulative_skips == NULL) goto error_return; pskips = secinfo->cumulative_skips; pstridx = secinfo->stridxs; offset = 0; for (i = 0; i < count; i++, pskips++, pstridx++) { *pskips = offset; if (*pstridx == (bfd_size_type) -1) offset += STABSIZE; } BFD_ASSERT (offset != 0); } return TRUE; error_return: if (stabbuf != NULL) free (stabbuf); if (stabstrbuf != NULL) free (stabstrbuf); return FALSE; }
static const bfd_target * cisco_core_file_validate (bfd *abfd, int crash_info_loc) { char buf[4]; unsigned int crashinfo_offset; crashinfo_external crashinfo; bfd_size_type nread; unsigned int magic; unsigned int version; unsigned int rambase; sec_ptr asect; struct stat statbuf; bfd_size_type amt; flagword flags; if (bfd_seek (abfd, (file_ptr) crash_info_loc, SEEK_SET) != 0) return NULL; nread = bfd_bread (buf, (bfd_size_type) 4, abfd); if (nread != 4) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } crashinfo_offset = MASK_ADDR (bfd_get_32 (abfd, buf)); if (bfd_seek (abfd, (file_ptr) crashinfo_offset, SEEK_SET) != 0) { /* Most likely we failed because of a bogus (huge) offset */ bfd_set_error (bfd_error_wrong_format); return NULL; } nread = bfd_bread (&crashinfo, (bfd_size_type) sizeof (crashinfo), abfd); if (nread != sizeof (crashinfo)) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } if (bfd_stat (abfd, &statbuf) < 0) { bfd_set_error (bfd_error_system_call); return NULL; } magic = bfd_get_32 (abfd, crashinfo.magic); if (magic != CRASH_MAGIC) { bfd_set_error (bfd_error_wrong_format); return NULL; } version = bfd_get_32 (abfd, crashinfo.version); if (version == 0) { bfd_set_error (bfd_error_wrong_format); return NULL; } else if (version == 1) { /* V1 core dumps don't specify the dump base, assume 0 */ rambase = 0; } else { rambase = bfd_get_32 (abfd, crashinfo.rambase); } /* OK, we believe you. You're a core file. */ amt = sizeof (struct cisco_core_struct); abfd->tdata.cisco_core_data = (struct cisco_core_struct *) bfd_zmalloc (amt); if (abfd->tdata.cisco_core_data == NULL) return NULL; switch ((crashreason) bfd_get_32 (abfd, crashinfo.reason)) { case CRASH_REASON_NOTCRASHED: /* Crash file probably came from write core. */ abfd->tdata.cisco_core_data->sig = 0; break; case CRASH_REASON_CORRUPT: /* The crash context area was corrupt -- proceed with caution. We have no way of passing this information back to the caller. */ abfd->tdata.cisco_core_data->sig = 0; break; case CRASH_REASON_EXCEPTION: /* Crash occured due to CPU exception. */ /* This is 68k-specific; for MIPS we'll need to interpret cpu_vector differently based on the target configuration (since CISCO core files don't seem to have the processor encoded in them). */ switch (bfd_get_32 (abfd, crashinfo.cpu_vector)) { /* bus error */ case 2 : abfd->tdata.cisco_core_data->sig = SIGBUS; break; /* address error */ case 3 : abfd->tdata.cisco_core_data->sig = SIGBUS; break; /* illegal instruction */ case 4 : abfd->tdata.cisco_core_data->sig = SIGILL; break; /* zero divide */ case 5 : abfd->tdata.cisco_core_data->sig = SIGFPE; break; /* chk instruction */ case 6 : abfd->tdata.cisco_core_data->sig = SIGFPE; break; /* trapv instruction */ case 7 : abfd->tdata.cisco_core_data->sig = SIGFPE; break; /* privilege violation */ case 8 : abfd->tdata.cisco_core_data->sig = SIGSEGV; break; /* trace trap */ case 9 : abfd->tdata.cisco_core_data->sig = SIGTRAP; break; /* line 1010 emulator */ case 10: abfd->tdata.cisco_core_data->sig = SIGILL; break; /* line 1111 emulator */ case 11: abfd->tdata.cisco_core_data->sig = SIGILL; break; /* Coprocessor protocol violation. Using a standard MMU or FPU this cannot be triggered by software. Call it a SIGBUS. */ case 13: abfd->tdata.cisco_core_data->sig = SIGBUS; break; /* interrupt */ case 31: abfd->tdata.cisco_core_data->sig = SIGINT; break; /* breakpoint */ case 33: abfd->tdata.cisco_core_data->sig = SIGTRAP; break; /* floating point err */ case 48: abfd->tdata.cisco_core_data->sig = SIGFPE; break; /* floating point err */ case 49: abfd->tdata.cisco_core_data->sig = SIGFPE; break; /* zero divide */ case 50: abfd->tdata.cisco_core_data->sig = SIGFPE; break; /* underflow */ case 51: abfd->tdata.cisco_core_data->sig = SIGFPE; break; /* operand error */ case 52: abfd->tdata.cisco_core_data->sig = SIGFPE; break; /* overflow */ case 53: abfd->tdata.cisco_core_data->sig = SIGFPE; break; /* NAN */ case 54: abfd->tdata.cisco_core_data->sig = SIGFPE; break; default: #ifndef SIGEMT #define SIGEMT SIGTRAP #endif /* "software generated"*/ abfd->tdata.cisco_core_data->sig = SIGEMT; } break; default: /* Unknown crash reason. */ abfd->tdata.cisco_core_data->sig = 0; break; } /* Create a ".data" section that maps the entire file, which is essentially a dump of the target system's RAM. */ flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS; asect = bfd_make_section_anyway_with_flags (abfd, ".data", flags); if (asect == NULL) goto error_return; /* The size of memory is the size of the core file itself. */ asect->size = statbuf.st_size; asect->vma = rambase; asect->filepos = 0; /* Create a ".crash" section to allow access to the saved crash information. */ flags = SEC_HAS_CONTENTS; asect = bfd_make_section_anyway_with_flags (abfd, ".crash", flags); if (asect == NULL) goto error_return; asect->vma = 0; asect->filepos = crashinfo_offset; asect->size = sizeof (crashinfo); /* Create a ".reg" section to allow access to the saved registers. */ asect = bfd_make_section_anyway_with_flags (abfd, ".reg", flags); if (asect == NULL) goto error_return; asect->vma = 0; asect->filepos = bfd_get_32 (abfd, crashinfo.registers) - rambase; /* Since we don't know the exact size of the saved register info, choose a register section size that is either the remaining part of the file, or 1024, whichever is smaller. */ nread = statbuf.st_size - asect->filepos; asect->size = (nread < 1024) ? nread : 1024; return abfd->xvec; /* Get here if we have already started filling out the BFD and there is an error of some kind. */ error_return: bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = NULL; bfd_section_list_clear (abfd); return NULL; }
static bfd_boolean wasm_scan (bfd *abfd) { bfd_boolean error = FALSE; /* Fake VMAs for now. Choose 0x80000000 as base to avoid clashes with actual data addresses. */ bfd_vma vma = 0x80000000; int section_code; unsigned int bytes_read; char *name = NULL; asection *bfdsec; if (bfd_seek (abfd, (file_ptr) 0, SEEK_SET) != 0) goto error_return; if (! wasm_read_header (abfd, &error)) goto error_return; while ((section_code = wasm_read_byte (abfd, &error)) != EOF) { if (section_code != 0) { const char *sname = wasm_section_code_to_name (section_code); if (! sname) goto error_return; name = strdup (sname); bfdsec = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS); if (bfdsec == NULL) goto error_return; name = NULL; bfdsec->vma = vma; bfdsec->lma = vma; bfdsec->size = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); if (error) goto error_return; bfdsec->filepos = bfd_tell (abfd); bfdsec->alignment_power = 0; } else { bfd_vma payload_len; file_ptr section_start; bfd_vma namelen; char *prefix = WASM_SECTION_PREFIX; char *p; int ret; payload_len = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); if (error) goto error_return; section_start = bfd_tell (abfd); namelen = wasm_read_leb128 (abfd, &error, &bytes_read, FALSE); if (error || namelen > payload_len) goto error_return; name = bfd_zmalloc (namelen + strlen (prefix) + 1); if (! name) goto error_return; p = name; ret = sprintf (p, "%s", prefix); if (ret < 0 || (bfd_vma) ret != strlen (prefix)) goto error_return; p += ret; if (bfd_bread (p, namelen, abfd) != namelen) goto error_return; bfdsec = bfd_make_section_anyway_with_flags (abfd, name, SEC_HAS_CONTENTS); if (bfdsec == NULL) goto error_return; name = NULL; bfdsec->vma = vma; bfdsec->lma = vma; bfdsec->filepos = bfd_tell (abfd); bfdsec->size = section_start + payload_len - bfdsec->filepos; bfdsec->alignment_power = 0; } if (bfdsec->size != 0) { bfdsec->contents = bfd_zalloc (abfd, bfdsec->size); if (! bfdsec->contents) goto error_return; if (bfd_bread (bfdsec->contents, bfdsec->size, abfd) != bfdsec->size) goto error_return; } vma += bfdsec->size; } /* Make sure we're at actual EOF. There's no indication in the WebAssembly format of how long the file is supposed to be. */ if (error) goto error_return; return TRUE; error_return: if (name) free (name); for (bfdsec = abfd->sections; bfdsec; bfdsec = bfdsec->next) free ((void *) bfdsec->name); return FALSE; }