#include "defs.h" #include "gdbcore.h" #include "inferior.h" #include #include #include "elf-bfd.h" #include #ifndef HAVE_GREGSET_T typedef struct reg gregset_t; #endif #ifndef HAVE_FPREGSET_T typedef struct fpreg fpregset_t; #endif #include "gregset.h" #ifndef ELF_NOTE_NETBSD_CORE_PROCINFO #define ELF_NOTE_NETBSD_CORE_PROCINFO 1 #endif /* Dump NetBSD ELF corefile (appears in NetBSD 1.6 and later) */ #ifdef PT_MEMMAP static int nbsd_find_memory_regions (int (*func) (CORE_ADDR, unsigned long, int, int, int, void *), void *obfd) { pid_t pid = ptid_get_pid (inferior_ptid); unsigned long start, end, size; struct ptrace_mem_map_desc *md; int read, write, exec, saved_errno; char *buf; if (info_verbose) fprintf_filtered (gdb_stdout, "Reading memory regions\n"); buf = NULL; /* FIXME: 20000 is randomly choosen */ for (size = 1000; size < 20000; size += 1000) { buf = xmalloc(size); if (ptrace(PT_MEMMAP, pid, buf, size) == 0) break; saved_errno = errno; xfree(buf); if (saved_errno != ENOMEM) error ("Couldn't get the memory maps from the process\n"); } for (md = (void *)buf; size >= sizeof(*md); md++, size -= sizeof(*md)) { start = (unsigned long)md->pmmd_start; end = (unsigned long)md->pmmd_end; size = end - start; read = md->pmmd_flags & PMMD_PROT_READ; write = md->pmmd_flags & PMMD_PROT_WRITE; exec = md->pmmd_flags & PMMD_PROT_EXEC; if (info_verbose) { fprintf_filtered (gdb_stdout, "Save segment, %ld bytes at 0x%s (%c%c%c)\n", size, paddr_nz (start), read ? 'r' : '-', write ? 'w' : '-', exec ? 'x' : '-'); } /* Invoke the callback function to create the corefile segment. */ func (start, size, read, write, exec, obfd); if (md->pmmd_flags & PMMD_LAST_ENTRY) break; } return 0; } #endif /* PT_MEMMAP */ static char * netbsd_make_lwp_note (bfd *obfd, int tid, char *note_data, int *note_size) { gregset_t gregs; fpregset_t fpregs; char tname[32]; int firstmach; snprintf(tname, sizeof(tname), "NetBSD-CORE@%d", tid); switch (bfd_get_arch (obfd)) { case bfd_arch_alpha: case bfd_arch_sparc: firstmach = NT_NETBSDCORE_FIRSTMACH; break; default: firstmach = NT_NETBSDCORE_FIRSTMACH + 1; break; } fill_gregset (&gregs, -1); note_data = elfcore_write_note(obfd, note_data, note_size, tname, firstmach, &gregs, sizeof(gregs)); fill_fpregset (&fpregs, -1); note_data = elfcore_write_note(obfd, note_data, note_size, tname, firstmach + 2, &fpregs, sizeof(fpregs)); return note_data; } static char * nbsd_make_corefile_notes (bfd *obfd, int *note_size) { int32_t cpi[31 * 4 + 32 / 4]; gregset_t gregs; fpregset_t fpregs; char *note_data = NULL; char *exec_name = NULL; if (get_exec_file (0)) exec_name = strrchr (get_exec_file (0), '/') + 1; memset(cpi, 0, sizeof(cpi)); cpi[0] = NT_NETBSDCORE_PROCINFO; cpi[1] = sizeof(cpi); cpi[18] = ptid_get_pid (inferior_ptid); /* FIXME: should try harder to fill in the rest of the information */ cpi[30] = 1; /* FIXME: cpi_nlwps */ if (exec_name) strncpy(((char *)cpi) + 31 * 4, exec_name, 32); note_data = elfcore_write_note(obfd, NULL, note_size, "NetBSD-CORE", ELF_NOTE_NETBSD_CORE_PROCINFO, cpi, sizeof(cpi)); /* FIXME: only one thread for now */ note_data = netbsd_make_lwp_note(obfd, 1, note_data, note_size); make_cleanup (xfree, note_data); return note_data; } void _initialize_nbsd_nat(void) { #ifdef PT_MEMMAP extern void inftarg_set_find_memory_regions (); #endif /* PT_MEMMAP */ extern void inftarg_set_make_corefile_notes (); #ifdef PT_MEMMAP inftarg_set_find_memory_regions (nbsd_find_memory_regions); #endif /* PT_MEMMAP */ inftarg_set_make_corefile_notes (nbsd_make_corefile_notes); }