📄 pgcore.c
字号:
pgc->pgc_doff) != 0) return (1); } }#ifdef __sparcv9 if (P->status.pr_dmodel == PR_MODEL_LP64) { asrset_t asrs; if (Plwp_getasrs(P, lsp->pr_lwpid, asrs) == 0) { if (write_note(pgc->pgc_fd, NT_ASRS, &asrs, sizeof (asrset_t), pgc->pgc_doff) != 0) return (1); } }#endif /* __sparcv9 */#endif /* sparc */ return (0);}static uint_tcount_sections(pgcore_t *pgc){ struct ps_prochandle *P = pgc->P; file_info_t *fptr; uint_t cnt; uint_t nshdrs = 0; if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB))) return (0); fptr = list_next(&P->file_head); for (cnt = P->num_files; cnt > 0; cnt--, fptr = list_next(fptr)) { int hit_symtab = 0; Pbuild_file_symtab(P, fptr); if ((pgc->pgc_content & CC_CONTENT_CTF) && Pbuild_file_ctf(P, fptr) != NULL) { sym_tbl_t *sym; nshdrs++; if (fptr->file_ctf_dyn) { sym = &fptr->file_dynsym; } else { sym = &fptr->file_symtab; hit_symtab = 1; } if (sym->sym_data != NULL && sym->sym_symn != 0 && sym->sym_strs != NULL) nshdrs += 2; } if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab && fptr->file_symtab.sym_data != NULL && fptr->file_symtab.sym_symn != 0 && fptr->file_symtab.sym_strs != NULL) { nshdrs += 2; } } return (nshdrs == 0 ? 0 : nshdrs + 2);}static intwrite_shdr(pgcore_t *pgc, shstrtype_t name, uint_t type, ulong_t flags, uintptr_t addr, ulong_t offset, size_t size, uint_t link, uint_t info, uintptr_t addralign, uintptr_t entsize){ if (pgc->P->status.pr_dmodel == PR_MODEL_ILP32) { Elf32_Shdr shdr; bzero(&shdr, sizeof (shdr)); shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, name); shdr.sh_type = type; shdr.sh_flags = flags; shdr.sh_addr = (Elf32_Addr)addr; shdr.sh_offset = offset; shdr.sh_size = size; shdr.sh_link = link; shdr.sh_info = info; shdr.sh_addralign = addralign; shdr.sh_entsize = entsize; if (pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), *pgc->pgc_soff) != sizeof (shdr)) return (-1); *pgc->pgc_soff += sizeof (shdr);#ifdef _LP64 } else { Elf64_Shdr shdr; bzero(&shdr, sizeof (shdr)); shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, name); shdr.sh_type = type; shdr.sh_flags = flags; shdr.sh_addr = addr; shdr.sh_offset = offset; shdr.sh_size = size; shdr.sh_link = link; shdr.sh_info = info; shdr.sh_addralign = addralign; shdr.sh_entsize = entsize; if (pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), *pgc->pgc_soff) != sizeof (shdr)) return (-1); *pgc->pgc_soff += sizeof (shdr);#endif /* _LP64 */ } return (0);}static intdump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym){ sym_tbl_t *sym = dynsym ? &fptr->file_dynsym : &fptr->file_symtab; shstrtype_t symname = dynsym ? STR_DYNSYM : STR_SYMTAB; shstrtype_t strname = dynsym ? STR_DYNSTR : STR_STRTAB; uint_t symtype = dynsym ? SHT_DYNSYM : SHT_SYMTAB; size_t size; uintptr_t addr = fptr->file_map->map_pmap.pr_vaddr; if (sym->sym_data == NULL || sym->sym_symn == 0 || sym->sym_strs == NULL) return (0); size = sym->sym_hdr.sh_size; if (pwrite64(pgc->pgc_fd, sym->sym_data->d_buf, size, *pgc->pgc_doff) != size) return (-1); if (write_shdr(pgc, symname, symtype, 0, addr, *pgc->pgc_doff, size, index + 1, sym->sym_hdr.sh_info, sym->sym_hdr.sh_addralign, sym->sym_hdr.sh_entsize) != 0) return (-1); *pgc->pgc_doff += roundup(size, 8); size = sym->sym_strhdr.sh_size; if (pwrite64(pgc->pgc_fd, sym->sym_strs, size, *pgc->pgc_doff) != size) return (-1); if (write_shdr(pgc, strname, SHT_STRTAB, SHF_STRINGS, addr, *pgc->pgc_doff, size, 0, 0, 1, 0) != 0) return (-1); *pgc->pgc_doff += roundup(size, 8); return (0);}static intdump_sections(pgcore_t *pgc){ struct ps_prochandle *P = pgc->P; file_info_t *fptr; uint_t cnt; uint_t index = 1; if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB))) return (0); fptr = list_next(&P->file_head); for (cnt = P->num_files; cnt > 0; cnt--, fptr = list_next(fptr)) { int hit_symtab = 0; Pbuild_file_symtab(P, fptr); if ((pgc->pgc_content & CC_CONTENT_CTF) && Pbuild_file_ctf(P, fptr) != NULL) { sym_tbl_t *sym; uint_t dynsym; uint_t symindex = 0; /* * Write the symtab out first so we can correctly * set the sh_link field in the CTF section header. * symindex will be 0 if there is no corresponding * symbol table section. */ if (fptr->file_ctf_dyn) { sym = &fptr->file_dynsym; dynsym = 1; } else { sym = &fptr->file_symtab; dynsym = 0; hit_symtab = 1; } if (sym->sym_data != NULL && sym->sym_symn != 0 && sym->sym_strs != NULL) { symindex = index; if (dump_symtab(pgc, fptr, index, dynsym) != 0) return (-1); index += 2; } /* * Write the CTF data that we've read out of the * file itself into the core file. */ if (pwrite64(pgc->pgc_fd, fptr->file_ctf_buf, fptr->file_ctf_size, *pgc->pgc_doff) != fptr->file_ctf_size) return (-1); if (write_shdr(pgc, STR_CTF, SHT_PROGBITS, 0, fptr->file_map->map_pmap.pr_vaddr, *pgc->pgc_doff, fptr->file_ctf_size, symindex, 0, 4, 0) != 0) return (-1); index++; *pgc->pgc_doff += roundup(fptr->file_ctf_size, 8); } if ((pgc->pgc_content & CC_CONTENT_SYMTAB) && !hit_symtab && fptr->file_symtab.sym_data != NULL && fptr->file_symtab.sym_symn != 0 && fptr->file_symtab.sym_strs != NULL) { if (dump_symtab(pgc, fptr, index, 0) != 0) return (-1); index += 2; } } return (0);}/*ARGSUSED*/static intdump_map(void *data, const prmap_t *pmp, const char *name){ pgcore_t *pgc = data; struct ps_prochandle *P = pgc->P;#ifdef _LP64 Elf64_Phdr phdr;#else Elf32_Phdr phdr;#endif size_t n; bzero(&phdr, sizeof (phdr)); phdr.p_type = PT_LOAD; phdr.p_vaddr = pmp->pr_vaddr; phdr.p_memsz = pmp->pr_size; if (pmp->pr_mflags & MA_READ) phdr.p_flags |= PF_R; if (pmp->pr_mflags & MA_WRITE) phdr.p_flags |= PF_W; if (pmp->pr_mflags & MA_EXEC) phdr.p_flags |= PF_X; if (pmp->pr_vaddr + pmp->pr_size > P->status.pr_stkbase && pmp->pr_vaddr < P->status.pr_stkbase + P->status.pr_stksize) { if (!(pgc->pgc_content & CC_CONTENT_STACK)) goto exclude; } else if ((pmp->pr_mflags & MA_ANON) && pmp->pr_vaddr + pmp->pr_size > P->status.pr_brkbase && pmp->pr_vaddr < P->status.pr_brkbase + P->status.pr_brksize) { if (!(pgc->pgc_content & CC_CONTENT_HEAP)) goto exclude; } else if (pmp->pr_mflags & MA_ISM) { if (pmp->pr_mflags & MA_NORESERVE) { if (!(pgc->pgc_content & CC_CONTENT_DISM)) goto exclude; } else { if (!(pgc->pgc_content & CC_CONTENT_ISM)) goto exclude; } } else if (pmp->pr_mflags & MA_SHM) { if (!(pgc->pgc_content & CC_CONTENT_SHM)) goto exclude; } else if (pmp->pr_mflags & MA_SHARED) { if (pmp->pr_mflags & MA_ANON) { if (!(pgc->pgc_content & CC_CONTENT_SHANON)) goto exclude; } else { if (!(pgc->pgc_content & CC_CONTENT_SHFILE)) goto exclude; } } else if (pmp->pr_mflags & MA_ANON) { if (!(pgc->pgc_content & CC_CONTENT_ANON)) goto exclude; } else if (phdr.p_flags == (PF_R | PF_X)) { if (!(pgc->pgc_content & CC_CONTENT_TEXT)) goto exclude; } else if (phdr.p_flags == PF_R) { if (!(pgc->pgc_content & CC_CONTENT_RODATA)) goto exclude; } else { if (!(pgc->pgc_content & CC_CONTENT_DATA)) goto exclude; } n = 0; while (n < pmp->pr_size) { size_t csz = MIN(pmp->pr_size - n, pgc->pgc_chunksz); /* * If we can't read out part of the victim's address * space for some reason ignore that failure and try to * emit a partial core file without that mapping's data. * As in the kernel, we mark these failures with the * PF_SUNW_FAILURE flag and store the errno where the * mapping would have been. */ if (Pread(P, pgc->pgc_chunk, csz, pmp->pr_vaddr + n) != csz || pwrite64(pgc->pgc_fd, pgc->pgc_chunk, csz, *pgc->pgc_doff + n) != csz) { int err = errno; (void) pwrite64(pgc->pgc_fd, &err, sizeof (err), *pgc->pgc_doff); *pgc->pgc_doff += roundup(sizeof (err), 8); phdr.p_flags |= PF_SUNW_FAILURE; (void) ftruncate64(pgc->pgc_fd, *pgc->pgc_doff); goto exclude; } n += csz; } phdr.p_offset = *pgc->pgc_doff; phdr.p_filesz = pmp->pr_size; *pgc->pgc_doff += roundup(phdr.p_filesz, 8);exclude: if (P->status.pr_dmodel == PR_MODEL_NATIVE) { if (pwrite64(pgc->pgc_fd, &phdr, sizeof (phdr), *pgc->pgc_poff) != sizeof (phdr)) return (1); *pgc->pgc_poff += sizeof (phdr);#ifdef _LP64 } else { Elf32_Phdr phdr32; bzero(&phdr32, sizeof (phdr32)); phdr32.p_type = phdr.p_type; phdr32.p_vaddr = (Elf32_Addr)phdr.p_vaddr; phdr32.p_memsz = (Elf32_Word)phdr.p_memsz; phdr32.p_flags = phdr.p_flags; phdr32.p_offset = (Elf32_Off)phdr.p_offset; phdr32.p_filesz = (Elf32_Word)phdr.p_filesz; if (pwrite64(pgc->pgc_fd, &phdr32, sizeof (phdr32), *pgc->pgc_poff) != sizeof (phdr32)) return (1); *pgc->pgc_poff += sizeof (phdr32);#endif /* _LP64 */ } return (0);}intwrite_shstrtab(struct ps_prochandle *P, pgcore_t *pgc){ off64_t off = *pgc->pgc_doff; size_t size = 0; shstrtab_t *s = &pgc->pgc_shstrtab; int i, ndx; if (shstrtab_size(s) == 1) return (0); /* * Preemptively stick the name of the shstrtab in the string table. */ (void) shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB); size = shstrtab_size(s); if (pwrite64(pgc->pgc_fd, "", 1, off) != 1) return (1); /* * Dump all the strings that we used being sure we include the * terminating null character. */ for (i = 0; i < STR_NUM; i++) { if ((ndx = s->sst_ndx[i]) != 0) { const char *str = shstrtab_data[i]; size_t len = strlen(str) + 1; if (pwrite64(pgc->pgc_fd, str, len, off + ndx) != len) return (1); } } if (P->status.pr_dmodel == PR_MODEL_ILP32) { Elf32_Shdr shdr; bzero(&shdr, sizeof (shdr)); shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB); shdr.sh_size = size; shdr.sh_offset = *pgc->pgc_doff; shdr.sh_addralign = 1; shdr.sh_flags = SHF_STRINGS; shdr.sh_type = SHT_STRTAB; if (pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), *pgc->pgc_soff) != sizeof (shdr)) return (1); *pgc->pgc_soff += sizeof (shdr);#ifdef _LP64 } else { Elf64_Shdr shdr; bzero(&shdr, sizeof (shdr)); shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB); shdr.sh_size = size; shdr.sh_offset = *pgc->pgc_doff; shdr.sh_addralign = 1; shdr.sh_flags = SHF_STRINGS; shdr.sh_type = SHT_STRTAB; if (pwrite64(pgc->pgc_fd, &shdr, sizeof (shdr), *pgc->pgc_soff) != sizeof (shdr)) return (1); *pgc->pgc_soff += sizeof (shdr);#endif /* _LP64 */ } *pgc->pgc_doff += roundup(size, 8); return (0);}/* * Don't explicity stop the process; that's up to the consumer. */intPfgcore(struct ps_prochandle *P, int fd, core_content_t content){ char plat[SYS_NMLN]; char zonename[ZONENAME_MAX]; int platlen = -1; pgcore_t pgc; off64_t poff, soff, doff, boff; struct utsname uts; uint_t nphdrs, nshdrs; if (ftruncate64(fd, 0) != 0) return (-1); if (content == CC_CONTENT_INVALID) { errno = EINVAL; return (-1); } /* * Cache the mappings and other useful data. */ (void) Prd_agent(P); (void) Ppsinfo(P); pgc.P = P; pgc.pgc_fd = fd; pgc.pgc_poff = &poff; pgc.pgc_soff = &soff; pgc.pgc_doff = &doff; pgc.pgc_content = content; pgc.pgc_chunksz = PAGESIZE; if ((pgc.pgc_chunk = malloc(pgc.pgc_chunksz)) == NULL) return (-1); shstrtab_init(&pgc.pgc_shstrtab); /* * There are two PT_NOTE program headers for ancillary data, and * one for each mapping. */ nphdrs = 2 + P->map_count; nshdrs = count_sections(&pgc); (void) Pplatform(P, plat, sizeof (plat)); platlen = strlen(plat) + 1; Preadauxvec(P); (void) Puname(P, &uts); if (Pzonename(P, zonename, sizeof (zonename)) == NULL) zonename[0] = '\0'; /* * Set up the ELF header. */ if (P->status.pr_dmodel == PR_MODEL_ILP32) { Elf32_Ehdr ehdr; bzero(&ehdr, sizeof (ehdr)); ehdr.e_ident[EI_MAG0] = ELFMAG0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -