#define CLICK_WORDS (CLICK_SIZE / sizeof(unsigned long))
-int adjust_stack(pid_t pid, struct mem_map *seg)
-{
- static unsigned long buf[CLICK_WORDS];
- struct ptrace_range pr;
- size_t off, top, bottom;
- int i;
-
- /* FIXME: kernel/VM strangeness */
- seg->mem_vir -= seg->mem_len - 1;
-
- /* Scan the stack, top to bottom, to find the lowest accessible region.
- * In practice that will be at 64MB, so we also scan for the lowest non-zero
- * region in order to keep the core file size managable.
- * Portability note: this code assumes that the stack grows down.
- */
- top = seg->mem_vir + seg->mem_len;
-
- pr.pr_space = TS_DATA;
- pr.pr_addr = (top - 1) << CLICK_SHIFT;
- pr.pr_size = sizeof(buf);
- pr.pr_ptr = buf;
-
- for (off = top - 1; off >= seg->mem_vir; off--) {
- if (ptrace(T_GETRANGE, pid, (long) &pr, 0)) {
- if (errno == EFAULT)
- break;
-
- perror("ptrace(T_GETRANGE)");
- return 1;
- }
-
- for (i = 0; i < CLICK_WORDS; i += sizeof(buf[0]))
- if (buf[i] != 0)
- bottom = off;
-
- pr.pr_addr -= sizeof(buf);
- }
-
- /* Add one extra zero page as margin. */
- if (bottom > off && bottom > seg->mem_vir)
- bottom--;
-
- seg->mem_len -= bottom - seg->mem_vir;
- seg->mem_vir = bottom;
-
- return 0;
-}
-
-int write_seg(int fd, pid_t pid, int seg, off_t seg_off, phys_bytes seg_bytes)
-{
- ssize_t w;
- static char buf[CLICK_SIZE];
- struct ptrace_range pr;
-
- pr.pr_space = (seg == T) ? TS_INS : TS_DATA;
- pr.pr_addr = seg_off;
- pr.pr_size = sizeof(buf);
- pr.pr_ptr = buf;
-
- for ( ; pr.pr_addr < seg_off + seg_bytes; pr.pr_addr += sizeof(buf))
- {
- /* Copy a chunk from user space to the block buffer. */
- if (ptrace(T_GETRANGE, pid, (long) &pr, 0)) {
- /* Create holes for inaccessible areas. */
- if (errno == EFAULT) {
- lseek(fd, sizeof(buf), SEEK_CUR);
- continue;
- }
-
- perror("ptrace(T_GETRANGE)");
- return 1;
- }
-
- if((w=write(fd, buf, sizeof(buf))) != sizeof(buf)) {
- if(w < 0) printf("write error: %s\n", strerror(errno));
- printf("write_seg: write failed: %d/%d\n", w, sizeof(buf));
- return 1;
- }
- }
-
- return 0;
-}
-
-int dumpcore(pid_t pid)
-{
- int r, seg, fd;
- vir_bytes len;
- off_t off, seg_off;
- long data;
- struct mem_map segs[NR_LOCAL_SEGS];
- struct proc procentry;
- ssize_t w;
- char core_name[PATH_MAX];
-
- /* Get the process table entry for this process. */
- len = sizeof(struct proc) / sizeof(long);
- for (off = 0; off < len; off++)
- {
- errno = 0;
- data = ptrace(T_GETUSER, pid, off * sizeof(long), 0);
- if (data == -1 && errno != 0)
- {
- perror("ptrace(T_GETUSER)");
- return 1;
- }
-
- ((long *) &procentry)[off] = data;
- }
-
- memcpy(segs, procentry.p_memmap, sizeof(segs));
-
- /* Correct and reduce the stack segment. */
- r = adjust_stack(pid, &segs[S]);
- if (r != 0)
- goto error;
-
- /* Create a core file with a temporary, unique name. */
- sprintf(core_name, "core.%d", pid);
-
- if((fd = open(core_name, O_CREAT|O_EXCL|O_WRONLY, 0600)) < 0) {
- fprintf(stderr, "couldn't open %s (%s)\n", core_name,
- strerror(errno));
- return 1;
- }
-
- /* Write out the process's segments. */
- if((w=write(fd, segs, sizeof(segs))) != sizeof(segs)) {
- if(w < 0) printf("write error: %s\n", strerror(errno));
- printf( "segs write failed: %d/%d\n", w, sizeof(segs));
- goto error;
- }
-
- /* Write out the whole kernel process table entry to get the regs. */
- if((w=write(fd, &procentry, sizeof(procentry))) != sizeof(procentry)) {
- if(w < 0) printf("write error: %s\n", strerror(errno));
- printf( "proc write failed: %d/%d\n", w, sizeof(procentry));
- goto error;
- }
-
- /* Loop through segments and write the segments themselves out. */
- for (seg = 0; seg < NR_LOCAL_SEGS; seg++) {
- len= segs[seg].mem_len << CLICK_SHIFT;
- seg_off= segs[seg].mem_vir << CLICK_SHIFT;
- r= write_seg(fd, pid, seg, seg_off, len);
- if (r != 0)
- goto error;
- }
-
- /* Give the core file its final name. */
- if (rename(core_name, "core")) {
- perror("rename");
- goto error;
- }
-
- close(fd);
-
- return 0;
-
-error:
- close(fd);
-
- unlink(core_name);
-
- return 1;
-}
-
int main(int argc, char *argv[])
{
pid_t pid;
return 1;
}
- r = dumpcore(pid);
+ if (ptrace(T_DUMPCORE, pid, 0, 0) != 0) {
+ fprintf(stderr, "warning, dumpcore failed (%s)\n",
+ strerror(errno));
+ }
if (ptrace(T_DETACH, pid, 0, 0)) {
fprintf(stderr, "warning, detaching failed (%s)\n",