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; }
int read_core(const char *path, struct pstate *ps) { struct corefile *cf; void *core_map; off_t c_off; int i, cfd; cf = (struct corefile *)malloc(sizeof(*cf)); if (cf == NULL) err(1, "malloc"); cfd = open(path, O_RDONLY, 0600); if (cfd < 0) err(1, "open() failed on core file"); if (fstat(cfd, &(cf->cfstat)) < 0) err(1, "fstat() failed on core"); if (cf->cfstat.st_mtimespec.tv_sec < ps->exec_stat.st_mtimespec.tv_sec) warnx("executable is more recent than core file!"); core_map = mmap(NULL, cf->cfstat.st_size, PROT_READ, MAP_PRIVATE, cfd, 0); if (core_map == MAP_FAILED) err(1, "mmap() failed on core"); close(cfd); cf->chdr = (struct core *)core_map; c_off = cf->chdr->c_hdrsize; if (CORE_GETMAGIC(*(cf->chdr)) != COREMAGIC) errx(1, "hey, that's not a core file"); printf("Core file generated from '%s' by signal %d (SIG%s)\n", cf->chdr->c_name, cf->chdr->c_signo, sys_signame[cf->chdr->c_signo]); #ifdef DEBUG printf("Core: text=0x%lx, data=0x%lx, stack=0x%lx\n", cf->chdr->c_tsize, cf->chdr->c_dsize, cf->chdr->c_ssize); #endif cf->segs = (struct coreseg **)calloc(cf->chdr->c_nseg, sizeof(cf->segs)); if (cf->segs == NULL) err(1, "calloc"); for (i = 0; i < cf->chdr->c_nseg; i++) { cf->segs[i] = (struct coreseg *)(core_map + c_off); if (CORE_GETMAGIC(*(cf->segs[i])) != CORESEGMAGIC) errx(1, "invalid segment hdr for segment %d", i); if (CORE_GETFLAG(*(cf->segs[i])) & CORE_CPU) { cf->regs = (struct reg *) ((long) cf->segs[i] + cf->chdr->c_seghdrsize); } if (CORE_GETFLAG(*(cf->segs[i])) & CORE_STACK) cf->c_stack = cf->segs[i] + cf->chdr->c_seghdrsize; c_off += cf->chdr->c_seghdrsize + cf->segs[i]->c_size; #ifdef DEBUG (void)printf("seg[%d]: midmag=0x%lx addr=0x%lx size=0x%lx\n", i, cf->segs[i]->c_midmag, cf->segs[i]->c_addr, cf->segs[i]->c_size); #endif } cf->path = (char *)path; ps->ps_flags |= PSF_CORE; ps->ps_core = cf; return (0); }