static int writenote(struct memelfnote *men, FILE *core_fp, long *size) { Elf32_Nhdr en; en.n_namesz = strlen(men->name)+1; en.n_descsz = men->datasz; en.n_type = men->type; if(dump_write( core_fp, &en, sizeof(en), size) == -1) return 1; if(dump_write( core_fp, men->name, en.n_namesz, size) == -1) return 1; dump_seek( core_fp, roundup(dump_tell(core_fp), sizeof (Elf32_Word))); /* XXX */ if(dump_write( core_fp, men->data, men->datasz, size) == -1) return 1; dump_seek( core_fp, roundup(dump_tell(core_fp), sizeof (Elf32_Word))); /* XXX */ dump_seek( core_fp, roundup(dump_tell(core_fp), sizeof (Elf32_Word))); return 1; }
static int llcallchain_bufinfo_show(dyn_llcallchain_t *dyn, track_proc_t *proc, track_lwp_t *lwp) { char content[WIN_LINECHAR_MAX]; lat_line_t *lat_buf, *line; win_reg_t *reg; int lwpid = 0, nlines, lat; /* * Display the caption of data table: * "ADDR SIZE ACCESS% LAT(ns) DESC" */ reg = &dyn->buf_caption; reg_erase(reg); (void) snprintf(content, sizeof (content), "%16s%8s%11s%11s%34s", CAPTION_ADDR, CAPTION_SIZE, CAPTION_BUFHIT, CAPTION_AVGLAT, CAPTION_DESC); reg_line_write(&dyn->buf_caption, 1, ALIGN_LEFT, content); dump_write("%s\n", content); reg_refresh_nout(reg); /* * Get the stat of buffer. */ reg = &dyn->buf_data; reg_erase(reg); if (lwp != NULL) { lwpid = lwp->id; } if ((lat_buf = win_lat_buf_create(proc, lwpid, &nlines)) == NULL) { return (-1); } /* * Fill in the memory access information. */ win_lat_buf_fill(lat_buf, nlines, proc, lwp, &lat); /* * Check if the linear address is located in a buffer in * process address space. */ if ((line = bsearch((void *)(dyn->addr), lat_buf, nlines, sizeof (lat_line_t), bufaddr_cmp)) != NULL) { win_lat_str_build(content, WIN_LINECHAR_MAX, 0, line); reg_line_write(reg, 0, ALIGN_LEFT, content); dump_write("%s\n", content); } reg_refresh_nout(reg); free(lat_buf); return (0); }
static boolean_t latnode_data_show(track_proc_t *proc, dyn_latnode_t *dyn, map_entry_t *entry, boolean_t *note_out) { win_reg_t *reg; track_lwp_t *lwp = NULL; char content[WIN_LINECHAR_MAX], intval_buf[16], size_str[32]; *note_out = B_FALSE; if ((dyn->lwpid != 0) && (lwp = proc_lwp_find(proc, dyn->lwpid)) == NULL) { win_warn_msg(WARN_INVALID_LWPID); win_note_show(NOTE_INVALID_LWPID); *note_out = B_TRUE; return (B_FALSE); } reg = &dyn->msg; reg_erase(reg); disp_intval(intval_buf, 16); (void) snprintf(content, sizeof (content), "Break down of memory area for physical memory on node (interval: %s)", intval_buf); reg_line_write(reg, 1, ALIGN_LEFT, content); dump_write("\n*** %s\n", content); reg_refresh_nout(reg); reg = &dyn->note; reg_erase(reg); win_size2str(dyn->size, size_str, sizeof (size_str)); if (lwp != NULL) { (void) snprintf(content, sizeof (content), "Memory area(%"PRIX64", %s), thread(%d)", dyn->addr, size_str, lwp->id); } else { (void) snprintf(content, sizeof (content), "Memory area(%"PRIX64", %s), process(%d)", dyn->addr, size_str, proc->pid); } reg_line_write(reg, 1, ALIGN_LEFT, content); dump_write("\n*** %s\n", content); reg_refresh_nout(reg); latnode_data_get(proc, lwp, dyn); if (lwp != NULL) { lwp_refcount_dec(lwp); } return (B_TRUE); }
static int llcallchain_list_show(dyn_llcallchain_t *dyn, track_proc_t *proc, track_lwp_t *lwp) { perf_llrecgrp_t *llrec_grp; char content[WIN_LINECHAR_MAX]; os_perf_llrec_t *rec_arr; sym_chainlist_t chainlist; win_reg_t *reg; int i; reg = &dyn->chain_caption; reg_erase(reg); snprintf(content, WIN_LINECHAR_MAX, "Call-chain list:"); reg_line_write(reg, 1, ALIGN_LEFT, content); dump_write("%s\n", content); reg_refresh_nout(reg); reg = &dyn->pad; reg_erase(reg); dump_write("\n"); reg_refresh_nout(reg); if (lwp != NULL) { llrec_grp = &lwp->llrec_grp; } else { llrec_grp = &proc->llrec_grp; } if (sym_load(proc, SYM_TYPE_FUNC) != 0) { debug_print(NULL, 2, "Failed to load the process symbol " "(pid = %d)\n", proc->pid); return (-1); } memset(&chainlist, 0, sizeof (sym_chainlist_t)); rec_arr = llrec_grp->rec_arr; for (i = 0; i < llrec_grp->nrec_cur; i++) { if ((rec_arr[i].addr < dyn->addr) || (rec_arr[i].addr >= dyn->addr + dyn->size)) { continue; } sym_callchain_add(&proc->sym, rec_arr[i].callchain.ips, rec_arr[i].callchain.ip_num, &chainlist); } chainlist_show(&chainlist, &dyn->chain_data); return (0); }
int elf_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size, unsigned long limit) { const struct elf_phdr *const gate_phdrs = (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff); int i; Elf64_Off ofs = 0; for (i = 0; i < GATE_EHDR->e_phnum; ++i) { struct elf_phdr phdr = gate_phdrs[i]; if (phdr.p_type == PT_LOAD) { phdr.p_memsz = PAGE_ALIGN(phdr.p_memsz); phdr.p_filesz = phdr.p_memsz; if (ofs == 0) { ofs = phdr.p_offset = offset; offset += phdr.p_filesz; } else { phdr.p_offset = ofs; } } else { phdr.p_offset += ofs; } phdr.p_paddr = 0; *size += sizeof(phdr); if (*size > limit || !dump_write(file, &phdr, sizeof(phdr))) return 0; } return 1; }
static int buf_write(struct dumperinfo *di, char *ptr, size_t sz) { size_t len; int error; while (sz) { len = DEV_BSIZE - fragsz; if (len > sz) len = sz; bcopy(ptr, buffer + fragsz, len); fragsz += len; ptr += len; sz -= len; if (fragsz == DEV_BSIZE) { error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE); if (error) return error; dumplo += DEV_BSIZE; fragsz = 0; } } return (0); }
static int blk_dump(struct dumperinfo *di, vm_paddr_t pa, vm_size_t size) { vm_size_t pos, rsz; vm_offset_t va; int c, counter, error, twiddle; printf(" chunk at %#lx: %ld bytes ", (u_long)pa, (long)size); va = 0L; error = counter = twiddle = 0; for (pos = 0; pos < size; pos += MAXDUMPSZ, counter++) { if (counter % 128 == 0) printf("%c\b", "|/-\\"[twiddle++ & 3]); rsz = size - pos; rsz = (rsz > MAXDUMPSZ) ? MAXDUMPSZ : rsz; va = TLB_PHYS_TO_DIRECT(pa + pos); error = dump_write(di, (void *)va, 0, dumplo, rsz); if (error) break; dumplo += rsz; /* Check for user abort. */ c = cncheckc(); if (c == 0x03) return (ECANCELED); if (c != -1) printf("(CTRL-C to abort) "); } printf("... %s\n", (error) ? "fail" : "ok"); return (error); }
int pod_core_write_extra_phdrs(struct file *file, loff_t offset, size_t *size, unsigned long limit) { if ( vsyscall_ehdr ) { const struct podhdr *const ehdrp = (struct podhdr *) vsyscall_ehdr; const struct pod_phdr *const phdrp = (const struct pod_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); int i; Elf32_Off ofs = 0; for (i = 0; i < ehdrp->e_phnum; ++i) { struct pod_phdr phdr = phdrp[i]; if (phdr.p_type == PT_LOAD) { ofs = phdr.p_offset = offset; offset += phdr.p_filesz; } else { phdr.p_offset += ofs; } phdr.p_paddr = 0; /* match other core phdrs */ *size += sizeof(phdr); if (*size > limit || !dump_write(file, &phdr, sizeof(phdr))) return 0; } } return 1; }
static int chainlist_show(sym_chainlist_t *chainlist, win_reg_t *reg) { sym_callchain_t *chain; int nentry, nchain; int i, j = 0, k, nlines; char content[WIN_LINECHAR_MAX]; callchain_line_t *buf, *line; sym_callchain_resort(chainlist); nentry = sym_chainlist_nentry(chainlist, &nchain); reg_erase(reg); if (nentry == 0) { snprintf(content, WIN_LINECHAR_MAX, "<- Detecting call-chain ... -> "); reg_line_write(reg, 0, ALIGN_LEFT, content); dump_write("%s\n", content); reg_refresh_nout(reg); return (0); } nlines = nentry + 2 * nchain; if ((buf = zalloc(nlines * sizeof (callchain_line_t))) == NULL) { return (-1); } for (i = 0; i < nchain; i++) { if ((chain = sym_callchain_detach(chainlist)) == NULL) { break; } line = &buf[j++]; snprintf(line->content, WIN_LINECHAR_MAX, "<- call-chain %d: ->", i + 1); for (k = 0; k < chain->nentry; k++) { line = &buf[j++]; strncpy(line->content, chain->entry_arr[k].name, WIN_LINECHAR_MAX); line->content[WIN_LINECHAR_MAX - 1] = 0; } line = &buf[j++]; strcpy(line->content, ""); sym_callchain_free(chain); } if (reg->buf != NULL) { free(reg->buf); } reg->buf = (void *)buf; reg->nlines_total = nlines - 1; reg_scroll_show(reg, (void *)(reg->buf), nlines - 1, callchain_str_build); reg_refresh_nout(reg); sym_chainlist_free(chainlist); return (0); }
static void nodedetail_line_show(win_reg_t *reg, char *title, char *value, int line) { char s1[256]; snprintf(s1, sizeof (s1), "%-20s%15s", title, value); reg_line_write(reg, line, ALIGN_LEFT, s1); dump_write("%s\n", s1); }
static int buf_flush(struct dumperinfo *di) { int error; if (fragsz == 0) return (0); error = dump_write(di, buffer, 0, dumplo, DEV_BSIZE); dumplo += DEV_BSIZE; return (error); }
/* * Initialization for libcurses. */ boolean_t reg_curses_init(boolean_t first_load) { (void) initscr(); (void) refresh(); (void) start_color(); (void) keypad(stdscr, TRUE); (void) nonl(); (void) cbreak(); (void) noecho(); (void) curs_set(0); getmaxyx(stdscr, g_scr_height, g_scr_width); /* * Set a window resize signal handler. */ (void) signal(SIGWINCH, disp_on_resize); s_curses_init = B_TRUE; if ((g_scr_height < 24 || g_scr_width < 80)) { if (!first_load) { (void) mvwprintw(stdscr, 0, 0, "Terminal size is too small."); (void) mvwprintw(stdscr, 1, 0, "Please resize it to 80x24 or larger."); (void) refresh(); } else { reg_curses_fini(); stderr_print("Terminal size is too small " "(resize it to 80x24 or larger).\n"); } dump_write("\n%s\n", "Terminal size is too small."); dump_write("%s\n", "Please resize it to 80x24 or larger."); return (B_FALSE); } return (B_TRUE); }
/* * Show the 'scrolling reg'. */ void reg_scroll_show(win_reg_t *r, void *lines, int nreqs, void (*str_build_func)(char *, int, int, void *)) { int highlight, i, start, end; char content[WIN_LINECHAR_MAX]; highlight = r->scroll.highlight; if (highlight != -1) { if (highlight >= r->nlines_total) { highlight = r->nlines_total - 1; } if (highlight >= r->scroll.page_start) { if ((i = ((highlight - r->scroll.page_start) / r->nlines_scr)) != 0) { r->scroll.page_start += r->nlines_scr * i; } } else { r->scroll.page_start = (highlight / r->nlines_scr) * r->nlines_scr; } start = r->scroll.page_start; i = MIN(nreqs, r->nlines_scr); if ((end = start + i) > r->nlines_total) { end = r->nlines_total; } } else { highlight = 0; start = 0; end = MIN(nreqs, r->nlines_scr); } for (i = start; i < end; i++) { str_build_func(content, sizeof (content), i, lines); dump_write("%s\n", content); if (i != highlight) { reg_line_write(r, i - r->scroll.page_start, ALIGN_LEFT, content); } } if ((highlight >= start) && (highlight < end)) { str_build_func(content, sizeof (content), highlight, lines); reg_highlight_write(r, highlight - r->scroll.page_start, ALIGN_LEFT, content); r->scroll.highlight = highlight; } }
/* * textdump_writeblock() writes TEXTDUMP_BLOCKSIZE-sized blocks of data to * the space between di->mediaoffset and di->mediaoffset + di->mediasize. It * accepts an offset relative to di->mediaoffset. If we're carrying any * error from previous I/O, return that error and don't continue to try to * write. Most writers ignore the error and forge ahead on the basis that * there's not much you can do. */ static int textdump_writeblock(struct dumperinfo *di, off_t offset, char *buffer) { if (textdump_error) return (textdump_error); if (offset + TEXTDUMP_BLOCKSIZE > di->mediasize) return (EIO); if (offset < SIZEOF_METADATA) return (ENOSPC); textdump_error = dump_write(di, buffer, 0, offset + di->mediaoffset, TEXTDUMP_BLOCKSIZE); return (textdump_error); }
int elf_core_write_extra_data(struct file *file, size_t *size, unsigned long limit) { const struct elf_phdr *const gate_phdrs = (const struct elf_phdr *) (GATE_ADDR + GATE_EHDR->e_phoff); int i; for (i = 0; i < GATE_EHDR->e_phnum; ++i) { if (gate_phdrs[i].p_type == PT_LOAD) { void *addr = (void *)gate_phdrs[i].p_vaddr; size_t memsz = PAGE_ALIGN(gate_phdrs[i].p_memsz); *size += memsz; if (*size > limit || !dump_write(file, addr, memsz)) return 0; break; } } return 1; }
void dump_memory( int fd, FILE *fp, procfs_mapinfo *mem, long *size ) { int num, i, ok = 1; dprintf(("dumping %lld bytes of memory at %#llx\n", mem->size, mem->vaddr )); for (i = 0; i < mem->size; i+= pagesize ) { /* read memory here */ if ( ok ) { num = read( fd, membuf, min(pagesize, mem->size - i) ); } else { memset( membuf, -1, sizeof membuf ); num = pagesize; } if(dump_write( fp, membuf, min(pagesize, mem->size - i), size) == -1) return; if ( num != pagesize ) { dprintf(("cut short at %d+%d\n", i, num )); ok = 0; } } }
int pod_core_write_extra_data(struct file *file, size_t *size, unsigned long limit) { if ( vsyscall_ehdr ) { const struct podhdr *const ehdrp = (struct podhdr *) vsyscall_ehdr; const struct pod_phdr *const phdrp = (const struct pod_phdr *) (vsyscall_ehdr + ehdrp->e_phoff); int i; for (i = 0; i < ehdrp->e_phnum; ++i) { if (phdrp[i].p_type == PT_LOAD) { void *addr = (void *) phdrp[i].p_vaddr; size_t filesz = phdrp[i].p_filesz; *size += filesz; if (*size > limit || !dump_write(file, addr, filesz)) return 0; } } } return 1; }
static int ufw_send(ufw_sk *sk){ struct timeval time; struct node *cur; struct hookinfo *hki; struct iphdr *ip; struct sockaddr_in addr; double delay; int r; static struct timeval last = {0, 0}; size_t len; if(!sk){ errno = EBADF; return -1; } ip = (struct iphdr *)sk->sendbuf; len = ntohs(ip->tot_len); delay = 0; if(sk->limit_byte > 0) delay = (double)len/sk->limit_byte; if(sk->limit_packet > 0 && (ip->protocol == IPPROTO_UDP || (sk->limit_packet_flags & sk->sendbuf[(ip->ihl << 2) + 13])) && 1./sk->limit_packet > delay) delay = 1./sk->limit_packet; gettimeofday(&time, NULL); if(last.tv_sec){ delay -= time.tv_sec - last.tv_sec + (time.tv_usec - last.tv_usec)/1e6; if(delay > 0) dsleep(delay); } gettimeofday(&last, NULL); do{ addr.sin_family = AF_INET; addr.sin_port = sk->proto; addr.sin_addr.s_addr = sk->daddr; r = sendto(sk->fd, sk->sendbuf, len, 0, (struct sockaddr *)&addr, sizeof(addr)); }while(r < 0 && errno == EAGAIN); gettimeofday(&time, NULL); if(!sk->first_packet.tv_sec) sk->first_packet = time; if(r < 0){ if(sk->opts & FATAL)die("sendto"); return -1; } for(cur = sk->sendhook; cur; cur = cur->next){ hki = cur->data; if(!hki->func(sk->sendbuf, &time, 1, hki->user)) return r; } if((sk->opts & DUMP_SEND) && sk->dump) dump_write(sk->dump, sk->sendbuf, 0, &time); time.tv_sec -= sk->first_packet.tv_sec; time.tv_usec -= sk->first_packet.tv_usec; if(time.tv_usec < 0)time.tv_usec += 1000000; if(sk->opts & PRINT_SEND) print_packet(sk->sendbuf, &time, 1); return r; }
int elfcore(int fd, FILE *fp, const char *path, long coresize) { procfs_sysinfo *sysinfo; int sysinfo_len; procfs_info info; procfs_status status; int ret; procfs_mapinfo *mem = NULL, *mapinfos = NULL, *ldd_infos = NULL; int numnote=0, num, i, j, seg = 0, err, n_ldd_infos = 0; Elf32_Ehdr elf; Elf32_Phdr phdr; struct memelfnote notes[20], thread_note; off_t offset = 0, dataoff; uint64_t cur_tid_base = 0, cur_tid_size = 0; if (nodumpmem) { if (-1 == get_ldd_mapinfos(fd, &ldd_infos, &n_ldd_infos)) { /* should we bail out here? */ n_ldd_infos = 0; } } if((ret = devctl(fd, DCMD_PROC_SYSINFO, 0, 0, &sysinfo_len)) != EOK) { errno = ret; goto bailout; } if(sysinfo = alloca(sysinfo_len)) { if((ret = devctl(fd, DCMD_PROC_SYSINFO, sysinfo, sysinfo_len, 0)) != EOK) { errno = ret; goto bailout; } } if((ret = devctl(fd, DCMD_PROC_INFO, &info, sizeof info, 0)) != EOK) { errno = ret; goto bailout; } pagesize = sysconf( _SC_PAGESIZE ); if ( membuf == NULL && ((membuf = malloc( pagesize )) == NULL) ) { goto bailout; } // write elf header memcpy(elf.e_ident, ELFMAG, SELFMAG); elf.e_ident[EI_CLASS] = ELFCLASS32; elf.e_ident[EI_DATA] = ELFDATANATIVE; elf.e_ident[EI_VERSION] = EV_CURRENT; #if defined (__ARM__) elf.e_ident[EI_OSABI] = ELFOSABI_ARM; #endif memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD); if((ret = devctl(fd, DCMD_PROC_PAGEDATA, NULL, 0, &num)) != EOK) { errno = ret; goto bailout; } mapinfos = malloc( num * sizeof *mem ); if ( mapinfos == NULL ) { goto bailout; } if((ret = devctl(fd, DCMD_PROC_PAGEDATA, mapinfos, num*sizeof(*mapinfos), &num)) != EOK) { errno = ret; goto bailout; } mem = malloc( (n_ldd_infos + num) * sizeof(*mem) ); if ( mem == NULL ) { goto bailout; } /* find the offending thread */ for(status.tid = 1; devctl(fd, DCMD_PROC_TIDSTATUS, &status, sizeof status, 0) == EOK; status.tid++) { dprintf(("thread %d.flags is %#x\n", status.tid, status.flags )); if(status.why == _DEBUG_WHY_SIGNALLED) { // This is the faulting thread... dprintf(("thread %d is was SIGNALLED\n", status.tid )); cur_tid = status.tid; cur_tid_base = status.stkbase; cur_tid_size = status.stksize; } dprintf(("thread %d.why is %#x\n", status.tid, status.why )); } if(cur_tid == 0) { /* can't find the faulting thread then we need to dump all stack information */ cur_tid_only = 0; } for(seg = 0, i = 0; i < num; i++) { if(!(mapinfos[i].flags & PG_HWMAPPED) || (nodumpmem && !(mapinfos[i].flags & MAP_STACK)) ) { continue; } if ( (nodumpphys && (mapinfos[i].flags & MAP_PHYS) && !(mapinfos[i].flags & MAP_ANON)) ) { continue; } /* if we only want to dump the offending tid's stack */ if(cur_tid_only && (mapinfos[i].flags & MAP_STACK) && !OFFENDING_THREAD(cur_tid_base, cur_tid_size, &mapinfos[i])) { continue; } memcpy(&mem[seg], &mapinfos[i], sizeof(*mem)); seg++; } dprintf(("ldd mapinfos:\n")); for(i = 0; i < n_ldd_infos; i++) { dprintf(("%svaddr=%#llx, offset=%#llx, size=%#llx, flags=%#x\n", ldd_infos[i].flags & PG_HWMAPPED?"*":"", ldd_infos[i].vaddr, ldd_infos[i].offset, ldd_infos[i].size, ldd_infos[i].flags )); memcpy( &mem[seg], &ldd_infos[i], sizeof(*mem));; seg++; } free(mapinfos); mapinfos = NULL; if(n_ldd_infos) { free(ldd_infos); ldd_infos = NULL; } num = seg; elf.e_type = ET_CORE; elf.e_machine = EM_NATIVE; elf.e_version = EV_CURRENT; elf.e_entry = 0; elf.e_phoff = sizeof(elf); elf.e_shoff = 0; #ifdef __SH__ { struct cpuinfo_entry *cpu; cpu = SYSPAGE_ENTRY(cpuinfo); switch ( SH4_PVR_FAM(cpu[0].cpu) ) { case SH4_PVR_SH4A: dprintf(("Noting SH4-A CPU\n")); elf.e_flags = EF_SH4A; break; case SH4_PVR_SH4: default: elf.e_flags = EF_SH4; break; } } #else elf.e_flags = 0; #endif elf.e_ehsize = sizeof(elf); elf.e_phentsize = sizeof(phdr); elf.e_phnum = seg+1; /* xxxx */ elf.e_shentsize = 0; elf.e_shnum = 0; elf.e_shstrndx = 0; if(dump_write( fp, &elf, sizeof elf, &coresize ) == -1) goto bailout; offset += sizeof elf; offset += (elf.e_phnum) * sizeof phdr; if(sysinfo) { // write QNT_CORE_SYSINFO note memset( notes, 0, sizeof notes ); notes[numnote].name = QNX_NOTE_NAME; notes[numnote].type = QNT_CORE_SYSINFO; notes[numnote].datasz = roundup(sysinfo_len, sizeof (Elf32_Word)); notes[numnote].data = sysinfo; numnote++; } // write QNT_CORE_INFO note notes[numnote].name = QNX_NOTE_NAME; notes[numnote].type = QNT_CORE_INFO; notes[numnote].datasz = sizeof(info); notes[numnote].data = &info; numnote++; /* Write notes phdr entry */ { int sz = 0; memset( &phdr, 0, sizeof phdr ); for(i = 0; i < numnote; i++) sz += notesize(¬es[i]); for(status.tid = 1; devctl(fd, DCMD_PROC_TIDSTATUS, &status, sizeof status, 0) == EOK; status.tid++) { procfs_greg greg; procfs_fpreg fpreg; int size; if ( (err = devctl(fd, DCMD_PROC_CURTHREAD, &status.tid, sizeof status.tid, 0 )) != EOK ) { continue; } if (cur_tid_only && (cur_tid != status.tid)) { continue; } fixup_stack_boundary( &status, mem, seg ); thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_STATUS; thread_note.datasz = sizeof(status); thread_note.data = &status; sz += notesize( &thread_note ); if(devctl(fd, DCMD_PROC_GETGREG, &greg, sizeof greg, &size) == EOK) { thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_GREG; thread_note.datasz = size; thread_note.data = &greg; sz += notesize( &thread_note ); } if(devctl(fd, DCMD_PROC_GETFPREG, &fpreg, sizeof fpreg, &size) == EOK) { thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_FPREG; thread_note.datasz = size; thread_note.data = &fpreg; sz += notesize( &thread_note ); } } phdr.p_type = PT_NOTE; phdr.p_offset = offset; phdr.p_vaddr = 0; phdr.p_paddr = 0; phdr.p_filesz = sz; phdr.p_memsz = 0; phdr.p_flags = 0; phdr.p_align = 0; offset += phdr.p_filesz; if(dump_write( fp, &phdr, sizeof(phdr), &coresize) == -1) goto bailout; } /* Page-align dumped data */ dataoff = offset = roundup(offset, pagesize); for ( i = 0; i < seg; i++ ) { memset( &phdr, 0, sizeof phdr ); phdr.p_type = PT_LOAD; phdr.p_offset = offset; phdr.p_vaddr = mem[i].vaddr; phdr.p_paddr = 0; phdr.p_memsz = mem[i].size; phdr.p_flags = PF_W|PF_R; if ( mem[i].flags & MAP_ELF ) phdr.p_flags |= PF_X; phdr.p_align = pagesize; phdr.p_filesz = phdr.p_memsz; offset += phdr.p_filesz; if(dump_write( fp, &phdr, sizeof(phdr), &coresize) == -1) goto bailout; } for(i = 0; i < numnote; i++) { if (!writenote(¬es[i], fp, &coresize )) goto bailout; } for(status.tid = 1; devctl(fd, DCMD_PROC_TIDSTATUS, &status, sizeof status, 0) == EOK; status.tid++) { procfs_greg greg; procfs_fpreg fpreg; int size; if ( devctl(fd, DCMD_PROC_CURTHREAD, &status.tid, sizeof status.tid, 0 ) != EOK ) { continue; } if ( cur_tid == 0 ) cur_tid = status.tid; if (cur_tid_only && (cur_tid != status.tid)) { continue; } else if ( status.tid == cur_tid ) { dprintf(("thread %d is current thread!\n", status.tid )); slog_tid( &status, path ); status.flags |= _DEBUG_FLAG_CURTID; } // write QNT_CORE_STATUS note thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_STATUS; thread_note.datasz = sizeof(status); thread_note.data = &status; if ( !writenote( &thread_note, fp, &coresize ) ) goto bailout; if(devctl(fd, DCMD_PROC_GETGREG, &greg, sizeof greg, &size) == EOK) { // write QNT_CORE_GREG note thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_GREG; thread_note.datasz = size; thread_note.data = &greg; if ( !writenote( &thread_note, fp, &coresize ) ) goto bailout; } if(devctl(fd, DCMD_PROC_GETFPREG, &fpreg, sizeof fpreg, &size) == EOK) { // write QNT_CORE_FPREG note thread_note.name = QNX_NOTE_NAME; thread_note.type = QNT_CORE_FPREG; thread_note.datasz = size; thread_note.data = &fpreg; if ( !writenote( &thread_note, fp, &coresize ) ) goto bailout; } } dump_seek( fp, dataoff ); for ( j = 0; j < seg; j++ ) { if ( lseek( fd, mem[j].vaddr, SEEK_SET ) == -1 ) goto bailout; if ( mem[j].flags & MAP_STACK ) dump_stack_memory( fd, fp, &mem[j], &coresize ); else if (!nodumpmem) dump_memory( fd, fp, &mem[j], &coresize ); } // Return EOK when accually writing ELF files free(mem); return EOK; bailout: if ( mapinfos != NULL ) { free(mapinfos); } if ( ldd_infos != NULL ) { free(ldd_infos); } if ( mem != NULL ) { free(mem); } return errno; }
void dumpsys(struct dumperinfo *di) { struct sparc64_dump_hdr hdr; vm_size_t size, totsize, hdrsize; int error, i, nreg; /* Calculate dump size. */ size = 0; nreg = sparc64_nmemreg; for (i = 0; i < sparc64_nmemreg; i++) size += sparc64_memreg[i].mr_size; /* Account for the header size. */ hdrsize = roundup2(sizeof(hdr) + sizeof(struct sparc64_dump_reg) * nreg, DEV_BSIZE); size += hdrsize; totsize = size + 2 * sizeof(kdh); if (totsize > di->mediasize) { printf("Insufficient space on device (need %ld, have %ld), " "refusing to dump.\n", (long)totsize, (long)di->mediasize); error = ENOSPC; goto fail; } /* Determine dump offset on device. */ dumplo = di->mediaoffset + di->mediasize - totsize; mkdumpheader(&kdh, KERNELDUMPMAGIC, KERNELDUMP_SPARC64_VERSION, size, di->blocksize); printf("Dumping %lu MB (%d chunks)\n", (u_long)(size >> 20), nreg); /* Dump leader */ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); if (error) goto fail; dumplo += sizeof(kdh); /* Dump the private header. */ hdr.dh_hdr_size = hdrsize; hdr.dh_tsb_pa = tsb_kernel_phys; hdr.dh_tsb_size = tsb_kernel_size; hdr.dh_tsb_mask = tsb_kernel_mask; hdr.dh_nregions = nreg; if (buf_write(di, (char *)&hdr, sizeof(hdr)) != 0) goto fail; dumppos = hdrsize; /* Now, write out the region descriptors. */ for (i = 0; i < sparc64_nmemreg; i++) { error = reg_write(di, sparc64_memreg[i].mr_start, sparc64_memreg[i].mr_size); if (error != 0) goto fail; } buf_flush(di); /* Dump memory chunks. */ for (i = 0; i < sparc64_nmemreg; i++) { error = blk_dump(di, sparc64_memreg[i].mr_start, sparc64_memreg[i].mr_size); if (error != 0) goto fail; } /* Dump trailer */ error = dump_write(di, &kdh, 0, dumplo, sizeof(kdh)); if (error) goto fail; /* Signal completion, signoff and exit stage left. */ dump_write(di, NULL, 0, 0, 0); printf("\nDump complete\n"); return; fail: /* XXX It should look more like VMS :-) */ printf("** DUMP FAILED (ERROR %d) **\n", error); }
/* ARGSUSED */ static void * cons_handler(void *arg) { int c, cmd_id; unsigned char ch; if (!reg_curses_init(B_TRUE)) { goto L_EXIT; } win_fix_init(); /* * Excute "home" command. It shows the NumaTop default page. */ disp_go_home(); for (;;) { FD_ZERO(&s_cons_ctl.fds); FD_SET(STDIN_FILENO, &s_cons_ctl.fds); FD_SET(s_cons_ctl.pipe[0], &s_cons_ctl.fds); /* * Wait one character from "stdin" or pipe. */ if (select(s_cons_ctl.pipe[0] + 1, &s_cons_ctl.fds, NULL, NULL, NULL) > 0) { if (FD_ISSET(s_cons_ctl.pipe[0], &s_cons_ctl.fds)) { if (read(s_cons_ctl.pipe[0], &ch, 1) == 1) { /* * Character is from pipe. */ if (ch == PIPE_CHAR_QUIT) { /* * Received a QUIT notification, * "console thread" will be quit */ debug_print(NULL, 2, "cons: " "received PIPE_CHAR_QUIT\n"); break; } if (ch == PIPE_CHAR_RESIZE) { /* * Send the "RESIZE" command * to "display thread". */ (void) pthread_mutex_lock( &s_disp_ctl.mutex); CMD_ID_SET(&s_disp_ctl.cmd, CMD_RESIZE_ID); dispthr_flagset_nolock(DISP_FLAG_CMD); (void) pthread_mutex_unlock( &s_disp_ctl.mutex); } } } else { /* * Character is from STDIN. */ if ((c = getch()) == ERR) { /* * It's possile if the associated * terminal is lost. */ debug_print(NULL, 2, "cons: " "getch() failed.\n"); break; } ch = tolower((unsigned char)c); dump_write("\n<-- User hit the key '%c' " "(ascii = %d) -->\n", ch, (int)ch); cmd_id = cmd_id_get(ch); if (cmd_id != CMD_INVALID_ID) { /* * The character is a command. Send * the command to 'disp thread'. */ (void) pthread_mutex_lock( &s_disp_ctl.mutex); CMD_ID_SET(&s_disp_ctl.cmd, cmd_id); dispthr_flagset_nolock(DISP_FLAG_CMD); (void) pthread_mutex_unlock( &s_disp_ctl.mutex); } else { /* * Hit the keys 'UP'/'DOWN'/'ENTER' */ switch (ch) { case 2: /* KEY DOWN */ dispthr_flagset_lock( DISP_FLAG_SCROLLDOWN); break; case 3: /* KEY UP */ dispthr_flagset_lock( DISP_FLAG_SCROLLUP); break; case 13: /* enter. */ dispthr_flagset_lock( DISP_FLAG_SCROLLENTER); break; default: break; } } } } } reg_curses_fini(); L_EXIT: debug_print(NULL, 2, "cons thread is exiting\n"); return (NULL); }
static void llcallchain_data_show(dyn_win_t *win, boolean_t *note_out) { dyn_llcallchain_t *dyn; pid_t pid; int lwpid; uint64_t size; track_proc_t *proc; track_lwp_t *lwp = NULL; win_reg_t *reg; char content[WIN_LINECHAR_MAX], intval_buf[16]; char size_str[32]; dyn = (dyn_llcallchain_t *)(win->dyn); pid = dyn->pid; lwpid = dyn->lwpid; size = dyn->size; *note_out = B_FALSE; if ((proc = proc_find(pid)) == NULL) { win_warn_msg(WARN_INVALID_PID); win_note_show(NOTE_INVALID_PID); *note_out = B_TRUE; return; } if ((lwpid > 0) && ((lwp = proc_lwp_find(proc, lwpid)) == NULL)) { proc_refcount_dec(proc); win_warn_msg(WARN_INVALID_LWPID); win_note_show(NOTE_INVALID_LWPID); *note_out = B_TRUE; return; } reg = &dyn->msg; reg_erase(reg); disp_intval(intval_buf, 16); win_size2str(size, size_str, sizeof (size_str)); if (lwp == NULL) { (void) snprintf(content, WIN_LINECHAR_MAX, "Call-chain when process accesses the memory area (pid: %d)" " (interval: %s)", pid, intval_buf); } else { (void) snprintf(content, WIN_LINECHAR_MAX, "Call-chain when thread accesses the memory area (lwpid: %d)" " (interval: %s)", lwpid, intval_buf); } dump_write("\n*** %s\n", content); reg_line_write(reg, 1, ALIGN_LEFT, content); reg_refresh_nout(reg); llcallchain_bufinfo_show(dyn, proc, lwp); llcallchain_list_show(dyn, proc, lwp); if (lwp != NULL) { lwp_refcount_dec(lwp); } proc_refcount_dec(proc); }
/* * Commit text dump to disk. */ void textdump_dumpsys(struct dumperinfo *di) { off_t dumplen, trailer_offset; if (di->blocksize != TEXTDUMP_BLOCKSIZE) { printf("Dump partition block size (%ju) not textdump " "block size (%ju)", (uintmax_t)di->blocksize, (uintmax_t)TEXTDUMP_BLOCKSIZE); return; } /* * We don't know a priori how large the dump will be, but we do know * that we need to reserve space for metadata and that we need two * dump headers. Also leave room for one ustar header and one block * of data. */ if (di->mediasize < SIZEOF_METADATA + 2 * sizeof(kdh)) { printf("Insufficient space on dump partition.\n"); return; } textdump_error = 0; /* * Position the start of the dump so that we'll write the kernel dump * trailer immediately before the end of the partition, and then work * our way back. We will rewrite this header later to reflect the * true size if things go well. */ textdump_offset = di->mediasize - sizeof(kdh); textdump_saveoff(&trailer_offset); mkdumpheader(&kdh, TEXTDUMPMAGIC, KERNELDUMP_TEXT_VERSION, 0, TEXTDUMP_BLOCKSIZE); (void)textdump_writenextblock(di, (char *)&kdh); /* * Write a series of files in ustar format. */ if (textdump_do_ddb) db_capture_dump(di); #ifdef INCLUDE_CONFIG_FILE if (textdump_do_config) textdump_dump_config(di); #endif if (textdump_do_msgbuf) textdump_dump_msgbuf(di); if (textdump_do_panic && panicstr != NULL) textdump_dump_panic(di); if (textdump_do_version) textdump_dump_version(di); /* * Now that we know the true size, we can write out the header, then * seek back to the end and rewrite the trailer with the correct * size. */ dumplen = trailer_offset - (textdump_offset + TEXTDUMP_BLOCKSIZE); mkdumpheader(&kdh, TEXTDUMPMAGIC, KERNELDUMP_TEXT_VERSION, dumplen, TEXTDUMP_BLOCKSIZE); (void)textdump_writenextblock(di, (char *)&kdh); textdump_restoreoff(trailer_offset); (void)textdump_writenextblock(di, (char *)&kdh); /* * Terminate the dump, report any errors, and clear the pending flag. */ if (textdump_error == 0) (void)dump_write(di, NULL, 0, 0, 0); if (textdump_error == ENOSPC) printf("Insufficient space on dump partition\n"); else if (textdump_error != 0) printf("Error %d writing dump\n", textdump_error); else printf("Textdump complete.\n"); textdump_pending = 0; }
static inline int ufw_recv(ufw_sk *sk){ struct cmsghdr* cmsg; char ctlbuf[4096]; struct iovec iov; struct msghdr msg = {NULL, 0, &iov, 1, ctlbuf, sizeof(ctlbuf), 0}; ssize_t s; struct node *cur; struct hookinfo *hki; struct timeval time; struct iphdr *ip; if(!sk){ errno = EBADF; return -1; } iov.iov_base = sk->recvbuf; iov.iov_len = sizeof(sk->recvbuf); ip = (struct iphdr *)sk->recvbuf; for(;;){ next: s = recvmsg(sk->fd, &msg, MSG_WAITALL); if(s < 0){ if(errno == EAGAIN) return 0; else { if(sk->opts & FATAL)die("recvmsg"); return -1; } } /* filter */ if((sk->opts & FILTER_SADDR) && ip->daddr != sk->saddr) continue; if((sk->opts & FILTER_DADDR) && ip->saddr != sk->daddr) continue; if((sk->opts & FILTER_SPORT) && *(u_int16_t *)(sk->recvbuf + (ip->ihl << 2) + 2) != sk->sport) continue; if((sk->opts & FILTER_DPORT) && *(u_int16_t *)(sk->recvbuf + (ip->ihl << 2)) != sk->dport) continue; sk->received = 1; /* get timestamp */ for(cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) if(cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SO_TIMESTAMP && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct timeval))){ time = *(struct timeval *)CMSG_DATA(cmsg); break; } if(!sk->first_packet.tv_sec) sk->first_packet = time; for(cur = sk->recvhook; cur; cur = cur->next){ hki = cur->data; if(!hki->func(sk->recvbuf, &time, 1, hki->user)) goto next; } if((sk->opts & DUMP_RECV) && sk->dump) dump_write(sk->dump, sk->recvbuf, 0, &time); time.tv_sec -= sk->first_packet.tv_sec; time.tv_usec -= sk->first_packet.tv_usec; if(time.tv_usec < 0)time.tv_usec += 1000000; if(sk->opts & PRINT_RECV) print_packet(sk->recvbuf, &time, 0); } return -1;//never }
void dump_stack_memory( int fd, FILE *fp, procfs_mapinfo *mem, long *size ) { int num, i, max, min, base; off_t here, there; if ( (mem->flags & PG_HWMAPPED) == 0 ) { dprintf(("Ignoring non-mapped stack region: %#llx @ %#llx\n", mem->size, mem->vaddr )); return; } base = mem->offset; // base = mem->vaddr; dprintf(("blanking %lld bytes of stack memory at %#x\n", mem->size, base )); //printf("vaddr=%#x, offset=%#x, size=%lld\n", mem->vaddr, mem->offset, mem->size ); here = dump_tell(fp); max = roundup( mem->size, pagesize ); min = (mem->offset - mem->vaddr); dprintf(("max=%#x, min = %#x (%#llx->%#llx)\n", max, min, mem->vaddr+min, mem->vaddr+max )); if (gzlevel != -1) { int rsize; /* forward dumping from mem->offset to mem->offset + mem->size in gz mode */ memset(membuf, 0, pagesize); for (i = 0; i < min; i += pagesize) { if( dump_write( fp, membuf, min(pagesize, min - i), size) == -1) return; } for (i = min; i < mem->size; i += pagesize) { if ( lseek( fd, mem->vaddr + i, SEEK_SET ) == -1 ) { memset(membuf, 0, pagesize); num = pagesize; } else { rsize = (i & ~(pagesize - 1)) + pagesize; if (rsize >= mem->size) { rsize = mem->size - i; } else { rsize -= i; } if ((num = read( fd, membuf, rsize)) != rsize) { memset(membuf, -1, pagesize); } } if( dump_write( fp, membuf, num, size) == -1) return; } return; } memset( membuf, 0, sizeof membuf ); for (i = 0; i < mem->size; i+= pagesize ) { if(dump_write( fp, membuf, min( pagesize, mem->size - i ), size) == -1) return; } there = dump_tell(fp); for ( i = max - pagesize; i >= min; i -= pagesize ) { dump_seek( fp, here + i ); if ( lseek( fd, mem->vaddr + i, SEEK_SET ) == -1 ) continue; /* read memory here */ // dprintf(("attempting to read @ %#llx\n", mem->vaddr + i )); if ( (num = read( fd, membuf, pagesize )) != pagesize ) { memset( membuf, -1, sizeof membuf ); num = pagesize; } if(dump_write( fp, membuf, num, size) == -1) return; fflush( fp ); if ( num != pagesize ) { dprintf(("cut short at %d+%d\n", i, num )); break; } // else // dprintf(("read %d bytes ok\n", num )); } dump_seek( fp, there ); }