static int try_load_plugin (const char *pname, bfd *abfd, int *has_plugin_p) { void *plugin_handle; struct ld_plugin_tv tv[4]; int i; ld_plugin_onload onload; enum ld_plugin_status status; *has_plugin_p = 0; plugin_handle = dlopen (pname, RTLD_NOW); if (!plugin_handle) { _bfd_error_handler ("%s\n", dlerror ()); return 0; } onload = dlsym (plugin_handle, "onload"); if (!onload) goto err; i = 0; tv[i].tv_tag = LDPT_MESSAGE; tv[i].tv_u.tv_message = message; ++i; tv[i].tv_tag = LDPT_REGISTER_CLAIM_FILE_HOOK; tv[i].tv_u.tv_register_claim_file = register_claim_file; ++i; tv[i].tv_tag = LDPT_ADD_SYMBOLS; tv[i].tv_u.tv_add_symbols = add_symbols; ++i; tv[i].tv_tag = LDPT_NULL; tv[i].tv_u.tv_val = 0; status = (*onload)(tv); if (status != LDPS_OK) goto err; *has_plugin_p = 1; abfd->plugin_format = bfd_plugin_no; if (!claim_file) goto err; if (!try_claim (abfd)) goto err; abfd->plugin_format = bfd_plugin_yes; return 1; err: return 0; }
static bfd_boolean elf32_sparc_merge_private_bfd_data (bfd *ibfd, struct bfd_link_info *info) { bfd *obfd = info->output_bfd; 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 _bfd_sparc_elf_merge_private_bfd_data (ibfd, info); }
static void _bfd_default_assert_handler (const char *bfd_formatmsg, const char *bfd_version, const char *bfd_file, int bfd_line) { _bfd_error_handler (bfd_formatmsg, bfd_version, bfd_file, bfd_line); }
bfd_boolean _bfd_elf_merge_object_attributes (bfd *ibfd, bfd *obfd) { obj_attribute *in_attr; obj_attribute *out_attr; int vendor; /* The only common attribute is currently Tag_compatibility, accepted in both processor and "gnu" sections. */ for (vendor = OBJ_ATTR_FIRST; vendor <= OBJ_ATTR_LAST; vendor++) { /* Handle Tag_compatibility. The tags are only compatible if the flags are identical and, if the flags are '1', the strings are identical. If the flags are non-zero, then we can only use the string "gnu". */ in_attr = &elf_known_obj_attributes (ibfd)[vendor][Tag_compatibility]; out_attr = &elf_known_obj_attributes (obfd)[vendor][Tag_compatibility]; if (in_attr->i > 0 && strcmp (in_attr->s, "gnu") != 0) { _bfd_error_handler (_("error: %B: Object has vendor-specific contents that " "must be processed by the '%s' toolchain"), ibfd, in_attr->s); return FALSE; } if (in_attr->i != out_attr->i || (in_attr->i != 0 && strcmp (in_attr->s, out_attr->s) != 0)) { _bfd_error_handler (_("error: %B: Object tag '%d, %s' is " "incompatible with tag '%d, %s'"), ibfd, in_attr->i, in_attr->s ? in_attr->s : "", out_attr->i, out_attr->s ? out_attr->s : ""); return FALSE; } } return TRUE; }
void _bfd_abort (const char *file, int line, const char *fn) { if (fn != NULL) _bfd_error_handler /* xgettext:c-format */ (_("BFD %s internal error, aborting at %s:%d in %s\n"), BFD_VERSION_STRING, file, line, fn); else _bfd_error_handler /* xgettext:c-format */ (_("BFD %s internal error, aborting at %s:%d\n"), BFD_VERSION_STRING, file, line); _bfd_error_handler (_("Please report this bug.\n")); _exit (EXIT_FAILURE); }
elf_property * _bfd_elf_get_property (bfd *abfd, unsigned int type, unsigned int datasz) { elf_property_list *p, **lastp; if (bfd_get_flavour (abfd) != bfd_target_elf_flavour) { /* Never should happen. */ abort (); } /* Keep the property list in order of type. */ lastp = &elf_properties (abfd); for (p = *lastp; p; p = p->next) { /* Reuse the existing entry. */ if (type == p->property.pr_type) { if (datasz > p->property.pr_datasz) { /* This can happen when mixing 32-bit and 64-bit objects. */ p->property.pr_datasz = datasz; } return &p->property; } else if (type < p->property.pr_type) break; lastp = &p->next; } p = (elf_property_list *) bfd_alloc (abfd, sizeof (*p)); if (p == NULL) { _bfd_error_handler (_("%pB: out of memory in _bfd_elf_get_property"), abfd); _exit (EXIT_FAILURE); } memset (p, 0, sizeof (*p)); p->property.pr_type = type; p->property.pr_datasz = datasz; p->next = *lastp; *lastp = p; return &p->property; }
static FILE * bfd_cache_lookup_worker (bfd *abfd, enum cache_flag flag) { bfd *orig_bfd = abfd; if ((abfd->flags & BFD_IN_MEMORY) != 0) abort (); while (abfd->my_archive != NULL && !bfd_is_thin_archive (abfd->my_archive)) abfd = abfd->my_archive; if (abfd->iostream != NULL) { /* Move the file to the start of the cache. */ if (abfd != bfd_last_cache) { snip (abfd); insert (abfd); } return (FILE *) abfd->iostream; } if (flag & CACHE_NO_OPEN) return NULL; if (bfd_open_file (abfd) == NULL) ; else if (!(flag & CACHE_NO_SEEK) && _bfd_real_fseek ((FILE *) abfd->iostream, abfd->where, SEEK_SET) != 0 && !(flag & CACHE_NO_SEEK_ERROR)) bfd_set_error (bfd_error_system_call); else return (FILE *) abfd->iostream; /* xgettext:c-format */ _bfd_error_handler (_("reopening %B: %s\n"), orig_bfd, bfd_errmsg (bfd_get_error ())); return NULL; }
bfd_boolean _bfd_elf_parse_gnu_properties (bfd *abfd, Elf_Internal_Note *note) { const struct elf_backend_data *bed = get_elf_backend_data (abfd); unsigned int align_size = bed->s->elfclass == ELFCLASS64 ? 8 : 4; bfd_byte *ptr = (bfd_byte *) note->descdata; bfd_byte *ptr_end = ptr + note->descsz; if (note->descsz < 8 || (note->descsz % align_size) != 0) { bad_size: _bfd_error_handler (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) size: %#lx"), abfd, note->type, note->descsz); return FALSE; } while (ptr != ptr_end) { unsigned int type; unsigned int datasz; elf_property *prop; if ((size_t) (ptr_end - ptr) < 8) goto bad_size; type = bfd_h_get_32 (abfd, ptr); datasz = bfd_h_get_32 (abfd, ptr + 4); ptr += 8; if (datasz > (size_t) (ptr_end - ptr)) { _bfd_error_handler (_("warning: %pB: corrupt GNU_PROPERTY_TYPE (%ld) type (0x%x) datasz: 0x%x"), abfd, note->type, type, datasz); /* Clear all properties. */ elf_properties (abfd) = NULL; return FALSE; } if (type >= GNU_PROPERTY_LOPROC) { if (bed->elf_machine_code == EM_NONE) { /* Ignore processor-specific properties with generic ELF target vector. They should be handled by the matching ELF target vector. */ goto next; } else if (type < GNU_PROPERTY_LOUSER && bed->parse_gnu_properties) { enum elf_property_kind kind = bed->parse_gnu_properties (abfd, type, ptr, datasz); if (kind == property_corrupt) { /* Clear all properties. */ elf_properties (abfd) = NULL; return FALSE; } else if (kind != property_ignored) goto next; } } else { switch (type) { case GNU_PROPERTY_STACK_SIZE: if (datasz != align_size) { _bfd_error_handler (_("warning: %pB: corrupt stack size: 0x%x"), abfd, datasz); /* Clear all properties. */ elf_properties (abfd) = NULL; return FALSE; } prop = _bfd_elf_get_property (abfd, type, datasz); if (datasz == 8) prop->u.number = bfd_h_get_64 (abfd, ptr); else prop->u.number = bfd_h_get_32 (abfd, ptr); prop->pr_kind = property_number; goto next; case GNU_PROPERTY_NO_COPY_ON_PROTECTED: if (datasz != 0) { _bfd_error_handler (_("warning: %pB: corrupt no copy on protected size: 0x%x"), abfd, datasz); /* Clear all properties. */ elf_properties (abfd) = NULL; return FALSE; } prop = _bfd_elf_get_property (abfd, type, datasz); elf_has_no_copy_on_protected (abfd) = TRUE; prop->pr_kind = property_number; goto next; default: break; } } _bfd_error_handler (_("warning: %pB: unsupported GNU_PROPERTY_TYPE (%ld) type: 0x%x"), abfd, note->type, type); next: ptr += (datasz + (align_size - 1)) & ~ (align_size - 1); } return TRUE; }
static bfd_boolean sh_symbian_import_as (struct bfd_link_info *info, bfd * abfd, char * current_name, char * new_name) { struct elf_link_hash_entry * new_hash; symbol_rename * node; if (SYMBIAN_DEBUG) fprintf (stderr, "IMPORT '%s' AS '%s'\n", current_name, new_name); for (node = rename_list; node; node = node->next) if (strcmp (node->current_name, current_name) == 0) { if (strcmp (node->new_name, new_name) == 0) /* Already added to rename list. */ return TRUE; bfd_set_error (bfd_error_invalid_operation); _bfd_error_handler (_("%B: IMPORT AS directive for %s conceals previous IMPORT AS"), abfd, current_name); return FALSE; } if ((node = bfd_malloc (sizeof * node)) == NULL) { if (SYMBIAN_DEBUG) fprintf (stderr, "IMPORT AS: No mem for new rename node\n"); return FALSE; } if ((node->current_name = bfd_malloc (strlen (current_name) + 1)) == NULL) { if (SYMBIAN_DEBUG) fprintf (stderr, "IMPORT AS: No mem for current name field in rename node\n"); free (node); return FALSE; } else strcpy (node->current_name, current_name); if ((node->new_name = bfd_malloc (strlen (new_name) + 1)) == NULL) { if (SYMBIAN_DEBUG) fprintf (stderr, "IMPORT AS: No mem for new name field in rename node\n"); free (node->current_name); free (node); return FALSE; } else strcpy (node->new_name, new_name); node->next = rename_list; node->current_hash = NULL; node->new_symndx = 0; rename_list = node; new_hash = elf_link_hash_lookup (elf_hash_table (info), node->new_name, TRUE, FALSE, TRUE); bfd_elf_link_record_dynamic_symbol (info, new_hash); if (new_hash->root.type == bfd_link_hash_new) new_hash->root.type = bfd_link_hash_undefined; return TRUE; }
const bfd_target * sco5_core_file_p (bfd *abfd) { int coffset_siz, val, nsecs, cheadoffs; int coresize; struct user *u; struct coreoffsets coffsets; struct coresecthead chead; char *secname; flagword flags; /* Read coreoffsets region at end of core (see core(FP)). */ { struct stat statbuf; if (bfd_stat (abfd, &statbuf) < 0) return NULL; coresize = statbuf.st_size; } /* Last long in core is sizeof struct coreoffsets, read it */ if ((bfd_seek (abfd, (file_ptr) (coresize - sizeof coffset_siz), SEEK_SET) != 0) || bfd_bread ((void *) &coffset_siz, (bfd_size_type) sizeof coffset_siz, abfd) != sizeof coffset_siz) { bfd_set_error (bfd_error_wrong_format); return NULL; } /* Use it to seek start of coreoffsets region, read it and determine validity */ if ((bfd_seek (abfd, (file_ptr) (coresize - coffset_siz), SEEK_SET) != 0) || (bfd_bread ((void *) &coffsets, (bfd_size_type) sizeof coffsets, abfd) != sizeof coffsets) || ((coffsets.u_info != 1) && (coffsets.u_info != C_VERSION))) { bfd_set_error (bfd_error_wrong_format); return NULL; } if (coffsets.u_info == 1) { /* Old version, no section heads, read info from user struct */ u = read_uarea (abfd, coffsets.u_user); if (! u) goto fail; if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS, (bfd_size_type) coffsets.u_usize, 0 - (bfd_vma) u->u_ar0, (file_ptr) coffsets.u_user)) goto fail; if (!make_bfd_asection (abfd, ".data", SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, ((bfd_size_type) u->u_exdata.ux_dsize + u->u_exdata.ux_bsize), (bfd_vma) u->u_exdata.ux_datorg, (file_ptr) coffsets.u_data)) goto fail; if (!make_bfd_asection (abfd, ".stack", SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS, (bfd_size_type) u->u_ssize * NBPC, (bfd_vma) u->u_sub, (file_ptr) coffsets.u_stack)) goto fail; return abfd->xvec; /* Done for version 1 */ } /* Immediately before coreoffsets region is a long with offset in core to first coresecthead (CORES_OFFSETS), the long before this is the number of section heads in the list. Read both longs and read the coresecthead and check its validity */ if ((bfd_seek (abfd, (file_ptr) (coresize - coffset_siz - 2 * sizeof coffset_siz), SEEK_SET) != 0) || (bfd_bread ((void *) &nsecs, (bfd_size_type) sizeof nsecs, abfd) != sizeof nsecs) || (bfd_bread ((void *) &cheadoffs, (bfd_size_type) sizeof cheadoffs, abfd) != sizeof cheadoffs) || (bfd_seek (abfd, (file_ptr) cheadoffs, SEEK_SET) != 0) || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd) != sizeof chead) || (chead.cs_stype != CORES_OFFSETS) || (chead.cs_x.csx_magic != COREMAGIC_NUMBER)) { bfd_set_error (bfd_error_wrong_format); goto fail; } /* OK, we believe you. You're a core file (sure, sure). */ /* Now loop over all regions and map them */ nsecs--; /* We've seen CORES_OFFSETS already */ for (; nsecs; nsecs--) { if ((bfd_seek (abfd, (file_ptr) chead.cs_hseek, SEEK_SET) != 0) || (bfd_bread ((void *) &chead, (bfd_size_type) sizeof chead, abfd) != sizeof chead)) { bfd_set_error (bfd_error_wrong_format); goto fail; } switch (chead.cs_stype) { case CORES_MAGIC: /* Core header, check magic */ if (chead.cs_x.csx_magic != COREMAGIC_NUMBER) { bfd_set_error (bfd_error_wrong_format); goto fail; } secname = NULL; nsecs++; /* MAGIC not in section cnt!*/ break; case CORES_UAREA: /* U-area, read in tdata */ u = read_uarea (abfd, chead.cs_sseek); if (! u) goto fail; /* 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. */ chead.cs_vaddr = 0 - (bfd_vma) u->u_ar0; secname = ".reg"; flags = SEC_HAS_CONTENTS; break; case CORES_PREGION: /* A program region, map it */ switch (chead.cs_x.csx_preg.csxp_rtyp) { case PT_DATA: secname = ".data"; /* Data region. */ break; case PT_STACK: secname = ".stack"; /* Stack region. */ break; case PT_SHMEM: secname = ".shmem"; /* Shared memory */ break; case PT_LIBDAT: secname = ".libdat"; /* Shared library data */ break; case PT_V86: secname = ".virt86"; /* Virtual 8086 mode */ break; case PT_SHFIL: secname = ".mmfile"; /* Memory mapped file */ break; case PT_XDATA0: secname = ".Xdat0"; /* XENIX data region, virtual 0 */ break; default: secname = ""; } flags = SEC_ALLOC + SEC_LOAD + SEC_HAS_CONTENTS; break; case CORES_PROC: /* struct proc */ case CORES_ITIMER: /* interval timers */ case CORES_SCOUTSNAME: /* struct scoutsname */ secname = NULL; /* Ignore these */ break; default: _bfd_error_handler ("Unhandled SCO core file section type %d\n", chead.cs_stype); continue; } if (secname && !make_bfd_asection (abfd, secname, flags, (bfd_size_type) chead.cs_vsize, (bfd_vma) chead.cs_vaddr, (file_ptr) chead.cs_sseek)) goto fail; } return abfd->xvec; fail: if (abfd->tdata.any) { bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = NULL; } bfd_section_list_clear (abfd); return NULL; }
const bfd_target * rs6000coff_core_p (bfd *abfd) { CoreHdr core; struct stat statbuf; bfd_size_type size; char *tmpptr; /* Values from new and old core structures. */ int c_flag; file_ptr c_stack, c_regoff, c_loader; bfd_size_type c_size, c_regsize, c_lsize; bfd_vma c_stackend; void *c_regptr; int proc64; if (!read_hdr (abfd, &core)) { if (bfd_get_error () != bfd_error_system_call) bfd_set_error (bfd_error_wrong_format); return NULL; } /* This isn't the right handler for 64-bit core files on AIX 5.x. */ if (CORE_NEW (core) && CNEW_IS_CORE_DUMPXX (core)) { bfd_set_error (bfd_error_wrong_format); return NULL; } /* Copy fields from new or old core structure. */ if (CORE_NEW (core)) { c_flag = core.new_dump.c_flag; c_stack = (file_ptr) core.new_dump.c_stack; c_size = core.new_dump.c_size; c_stackend = CNEW_STACKORG (core.new_dump) + c_size; c_lsize = CNEW_LSIZE (core.new_dump); c_loader = CNEW_LOADER (core.new_dump); #ifndef BFD64 proc64 = CNEW_PROC64 (core.new_dump); } else { c_flag = core.old.c_flag; c_stack = (file_ptr) (ptr_to_uint) core.old.c_stack; c_size = core.old.c_size; c_stackend = COLD_STACKEND; c_lsize = 0x7ffffff; c_loader = (file_ptr) (ptr_to_uint) COLD_LOADER (core.old); #endif proc64 = 0; } if (proc64) { c_regsize = sizeof (CNEW_CONTEXT64 (core.new_dump)); c_regptr = &CNEW_CONTEXT64 (core.new_dump); } else if (CORE_NEW (core)) { c_regsize = sizeof (CNEW_MSTSAVE (core.new_dump)); c_regptr = &CNEW_MSTSAVE (core.new_dump); } #ifndef BFD64 else { c_regsize = sizeof (COLD_MSTSAVE (core.old)); c_regptr = &COLD_MSTSAVE (core.old); } #endif c_regoff = (char *) c_regptr - (char *) &core; if (bfd_stat (abfd, &statbuf) < 0) { bfd_set_error (bfd_error_system_call); return NULL; } /* If the core file ulimit is too small, the system will first omit the data segment, then omit the stack, then decline to dump core altogether (as far as I know UBLOCK_VALID and LE_VALID are always set) (this is based on experimentation on AIX 3.2). Now, the thing is that GDB users will be surprised if segments just silently don't appear (well, maybe they would think to check "info files", I don't know). For the data segment, we have no choice but to keep going if it's not there, since the default behavior is not to dump it (regardless of the ulimit, it's based on SA_FULLDUMP). But for the stack segment, if it's not there, we refuse to have anything to do with this core file. The usefulness of a core dump without a stack segment is pretty limited anyway. */ if (!(c_flag & UBLOCK_VALID) || !(c_flag & LE_VALID)) { bfd_set_error (bfd_error_wrong_format); return NULL; } if (!(c_flag & USTACK_VALID)) { bfd_set_error (bfd_error_file_truncated); return NULL; } /* Don't check the core file size for a full core, AIX 4.1 includes additional shared library sections in a full core. */ if (!(c_flag & (FULL_CORE | CORE_TRUNC))) { /* If the size is wrong, it means we're misinterpreting something. */ if (c_stack + (file_ptr) c_size != statbuf.st_size) { bfd_set_error (bfd_error_wrong_format); return NULL; } } /* Sanity check on the c_tab field. */ if (!CORE_NEW (core) && ( #ifndef BFD64 c_loader < (file_ptr) sizeof core.old #else c_loader < (file_ptr) sizeof core.new_dump #endif || c_loader >= statbuf.st_size || c_loader >= c_stack)) { bfd_set_error (bfd_error_wrong_format); return NULL; } /* Issue warning if the core file was truncated during writing. */ if (c_flag & CORE_TRUNC) _bfd_error_handler (_("%s: warning core file truncated"), bfd_get_filename (abfd)); /* Allocate core file header. */ #ifndef BFD64 size = CORE_NEW (core) ? sizeof (core.new_dump) : sizeof (core.old); #else size = sizeof (core.new_dump); #endif tmpptr = (char *) bfd_zalloc (abfd, (bfd_size_type) size); if (!tmpptr) return NULL; /* Copy core file header. */ memcpy (tmpptr, &core, size); set_tdata (abfd, tmpptr); /* Set architecture. */ if (CORE_NEW (core)) { enum bfd_architecture arch; unsigned long mach; switch (CNEW_IMPL (core.new_dump)) { case POWER_RS1: case POWER_RSC: case POWER_RS2: arch = bfd_arch_rs6000; mach = bfd_mach_rs6k; break; default: arch = bfd_arch_powerpc; mach = bfd_mach_ppc; break; } bfd_default_set_arch_mach (abfd, arch, mach); } /* .stack section. */ if (!make_bfd_asection (abfd, ".stack", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, c_size, c_stackend - c_size, c_stack)) goto fail; /* .reg section for all registers. */ if (!make_bfd_asection (abfd, ".reg", SEC_HAS_CONTENTS, c_regsize, (bfd_vma) 0, c_regoff)) goto fail; /* .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. */ if (!make_bfd_asection (abfd, ".ldinfo", SEC_HAS_CONTENTS, c_lsize, (bfd_vma) 0, c_loader)) goto fail; #ifndef CORE_VERSION_1 /* .data section if present. AIX 3 dumps the complete data section and sets FULL_CORE if the ulimit is large enough, otherwise the data section is omitted. AIX 4 sets FULL_CORE even if the core file is truncated, we have to examine core.c_datasize below to find out the actual size of the .data section. */ if (c_flag & FULL_CORE) { if (!make_bfd_asection (abfd, ".data", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, (bfd_size_type) core.old.c_u.u_dsize, (bfd_vma) CDATA_ADDR (core.old.c_u.u_dsize), c_stack + c_size)) goto fail; } #endif #ifdef CORE_VERSION_1 /* AIX 4 adds data sections from loaded objects to the core file, which can be found by examining ldinfo, and anonymously mmapped regions. */ { LdInfo ldinfo; bfd_size_type ldi_datasize; file_ptr ldi_core; uint ldi_next; bfd_vma ldi_dataorg; bfd_vma core_dataorg; /* Fields from new and old core structures. */ bfd_size_type c_datasize, c_vmregions; file_ptr c_data, c_vmm; if (CORE_NEW (core)) { c_datasize = CNEW_DATASIZE (core.new_dump); c_data = (file_ptr) core.new_dump.c_data; c_vmregions = core.new_dump.c_vmregions; c_vmm = (file_ptr) core.new_dump.c_vmm; } #ifndef BFD64 else { c_datasize = core.old.c_datasize; c_data = (file_ptr) (ptr_to_uint) core.old.c_data; c_vmregions = core.old.c_vmregions; c_vmm = (file_ptr) (ptr_to_uint) core.old.c_vmm; } #endif /* .data section from executable. */ if (c_datasize) { /* If Large Memory Model is used, then the .data segment should start from BDATAORG which has been defined in the system header files. */ if (c_flag & CORE_BIGDATA) core_dataorg = BDATAORG; else core_dataorg = CDATA_ADDR (c_datasize); if (!make_bfd_asection (abfd, ".data", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, c_datasize, (bfd_vma) core_dataorg, c_data)) goto fail; } /* .data sections from loaded objects. */ if (proc64) size = (unsigned long) ((LdInfo *) 0)->l64.ldinfo_filename; else size = (unsigned long) ((LdInfo *) 0)->l32.ldinfo_filename; while (1) { if (bfd_seek (abfd, c_loader, SEEK_SET) != 0) goto fail; if (bfd_bread (&ldinfo, size, abfd) != size) goto fail; if (proc64) { ldi_core = ldinfo.l64.ldinfo_core; ldi_datasize = ldinfo.l64.ldinfo_datasize; ldi_dataorg = (bfd_vma) ldinfo.l64.ldinfo_dataorg; ldi_next = ldinfo.l64.ldinfo_next; } else { ldi_core = ldinfo.l32.ldinfo_core; ldi_datasize = ldinfo.l32.ldinfo_datasize; ldi_dataorg = (bfd_vma) (ptr_to_uint) ldinfo.l32.ldinfo_dataorg; ldi_next = ldinfo.l32.ldinfo_next; } if (ldi_core) if (!make_bfd_asection (abfd, ".data", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, ldi_datasize, ldi_dataorg, ldi_core)) goto fail; if (ldi_next == 0) break; c_loader += ldi_next; } /* .vmdata sections from anonymously mmapped regions. */ if (c_vmregions) { bfd_size_type i; if (bfd_seek (abfd, c_vmm, SEEK_SET) != 0) goto fail; for (i = 0; i < c_vmregions; i++) { VmInfo vminfo; bfd_size_type vminfo_size; file_ptr vminfo_offset; bfd_vma vminfo_addr; #ifndef BFD64 size = CORE_NEW (core) ? sizeof (vminfo.new_dump) : sizeof (vminfo.old); #else size = sizeof (vminfo.new_dump); #endif if (bfd_bread (&vminfo, size, abfd) != size) goto fail; if (CORE_NEW (core)) { vminfo_addr = (bfd_vma) vminfo.new_dump.vminfo_addr; vminfo_size = vminfo.new_dump.vminfo_size; vminfo_offset = vminfo.new_dump.vminfo_offset; } #ifndef BFD64 else { vminfo_addr = (bfd_vma) (ptr_to_uint) vminfo.old.vminfo_addr; vminfo_size = vminfo.old.vminfo_size; vminfo_offset = vminfo.old.vminfo_offset; } #endif if (vminfo_offset) if (!make_bfd_asection (abfd, ".vmdata", SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS, vminfo_size, vminfo_addr, vminfo_offset)) goto fail; } } } #endif return abfd->xvec; /* This is garbage for now. */ fail: bfd_release (abfd, abfd->tdata.any); abfd->tdata.any = NULL; bfd_section_list_clear (abfd); return NULL; }