Print this page
13925 core files should include DWARF (fix mismerge)
13925 core files should include DWARF
Reviewed by: Rich Lowe <richlowe@richlowe.net>
Reviewed by: C Fraire <cfraire@me.com>
Reviewed by: Adam Leventhal <adam.leventhal@gmail.com>
Approved by: Dan McDonald <danmcd@joyent.com>

*** 67,76 **** --- 67,78 ---- #include "elf_impl.h" #include <sys/sdt.h> #include <sys/siginfo.h> #include <sys/random.h> + #include <core_shstrtab.h> + #if defined(__x86) #include <sys/comm_page_util.h> #include <sys/fp.h> #endif /* defined(__x86) */
*** 106,180 **** uint_t elf_nphdr_max = 1000; uint_t elf_nshdr_max = 10000; size_t elf_shstrtab_max = 100 * 1024; #endif - - - typedef enum { - STR_CTF, - STR_SYMTAB, - STR_DYNSYM, - STR_STRTAB, - STR_DYNSTR, - STR_SHSTRTAB, - STR_NUM - } shstrtype_t; - - static const char *shstrtab_data[] = { - ".SUNW_ctf", - ".symtab", - ".dynsym", - ".strtab", - ".dynstr", - ".shstrtab" - }; - - typedef struct shstrtab { - uint_t sst_ndx[STR_NUM]; - uint_t sst_cur; - } shstrtab_t; - - static void - shstrtab_init(shstrtab_t *s) - { - bzero(&s->sst_ndx, sizeof (s->sst_ndx)); - s->sst_cur = 1; - } - - static uint_t - shstrtab_ndx(shstrtab_t *s, shstrtype_t type) - { - uint_t ret; - - if ((ret = s->sst_ndx[type]) != 0) - return (ret); - - ret = s->sst_ndx[type] = s->sst_cur; - s->sst_cur += strlen(shstrtab_data[type]) + 1; - - return (ret); - } - - static size_t - shstrtab_size(const shstrtab_t *s) - { - return (s->sst_cur); - } - - static void - shstrtab_dump(const shstrtab_t *s, char *buf) - { - uint_t i, ndx; - - *buf = '\0'; - for (i = 0; i < STR_NUM; i++) { - if ((ndx = s->sst_ndx[i]) != 0) - (void) strcpy(buf + ndx, shstrtab_data[i]); - } - } - static int dtrace_safe_phdr(Phdr *phdrp, struct uarg *args, uintptr_t base) { ASSERT(phdrp->p_type == PT_SUNWDTRACE); --- 108,117 ----
*** 1972,1982 **** ctx->ecc_doffset += src->sh_size; } /* * Walk sections for a given ELF object, counting (or copying) those of ! * interest (CTF, symtab, strtab). */ static uint_t elf_process_obj_scns(elf_core_ctx_t *ctx, vnode_t *mvp, caddr_t saddr, Shdr *v, uint_t idx, uint_t remain, shstrtab_t *shstrtab) { --- 1909,1921 ---- ctx->ecc_doffset += src->sh_size; } /* * Walk sections for a given ELF object, counting (or copying) those of ! * interest (CTF, symtab, strtab, DWARF debug). ! * ! * Returns UINT_MAX upon low-memory. */ static uint_t elf_process_obj_scns(elf_core_ctx_t *ctx, vnode_t *mvp, caddr_t saddr, Shdr *v, uint_t idx, uint_t remain, shstrtab_t *shstrtab) {
*** 1990,2000 **** boolean_t ctf_link = B_FALSE; caddr_t shbase; size_t shsize, shstrsize; char *shstrbase; ! if ((content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)) == 0) { return (0); } if (getelfhead(mvp, credp, &ehdr, &nshdrs, &shstrndx, &nphdrs) != 0 || getelfshdr(mvp, credp, &ehdr, nshdrs, shstrndx, &shbase, &shsize, --- 1929,1940 ---- boolean_t ctf_link = B_FALSE; caddr_t shbase; size_t shsize, shstrsize; char *shstrbase; ! if ((content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB | CC_CONTENT_DEBUG)) ! == 0) { return (0); } if (getelfhead(mvp, credp, &ehdr, &nshdrs, &shstrndx, &nphdrs) != 0 || getelfshdr(mvp, credp, &ehdr, nshdrs, shstrndx, &shbase, &shsize,
*** 2028,2037 **** --- 1968,2023 ---- } } else if (symtab == NULL && (content & CC_CONTENT_SYMTAB) != 0 && strcmp(name, shstrtab_data[STR_SYMTAB]) == 0) { symchk = shdr; + } else if ((content & CC_CONTENT_DEBUG) != 0 && + strncmp(name, ".debug_", strlen(".debug_")) == 0) { + /* + * The design of the above check is intentional. In + * particular, we want to capture any sections that + * begin with '.debug_' for a few reasons: + * + * 1) Various revisions to the DWARF spec end up + * changing the set of section headers that + * exist. This ensures that we don't need to change + * the kernel to get a new version. + * + * 2) Other software uses .debug_ sections for things + * which aren't DWARF. This allows them to be captured + * as well. + * + * Because of this, we emit straight here, unlike the + * other two sections where we wait until we're done + * scanning. + */ + + /* We're only counting, don't emit! */ + if (v == NULL) { + count++; + continue; + } + + elf_ctx_resize_scratch(ctx, shdr->sh_size); + if (!shstrtab_ndx(shstrtab, name, &v[idx].sh_name)) { + count = UINT_MAX; + goto done; + } + v[idx].sh_addr = (Addr)(uintptr_t)saddr; + v[idx].sh_type = shdr->sh_type; + v[idx].sh_addralign = shdr->sh_addralign; + *doffp = roundup(*doffp, v[idx].sh_addralign); + v[idx].sh_offset = *doffp; + v[idx].sh_size = shdr->sh_size; + v[idx].sh_link = 0; + v[idx].sh_entsize = shdr->sh_entsize; + v[idx].sh_info = shdr->sh_info; + + elf_copy_scn(ctx, shdr, mvp, &v[idx]); + count++; + idx++; + continue; } else { continue; } ASSERT(symchk != NULL);
*** 2047,2076 **** continue; } symtab = symchk; strtab = strchk; ! if (symtab != NULL && ctf != NULL) { /* No other shdrs are of interest at this point */ break; } } if (ctf != NULL) count += 1; if (symtab != NULL) count += 2; if (v == NULL || count == 0 || count > remain) { count = MIN(count, remain); goto done; } /* output CTF section */ if (ctf != NULL) { elf_ctx_resize_scratch(ctx, ctf->sh_size); ! v[idx].sh_name = shstrtab_ndx(shstrtab, STR_CTF); v[idx].sh_addr = (Addr)(uintptr_t)saddr; v[idx].sh_type = SHT_PROGBITS; v[idx].sh_addralign = 4; *doffp = roundup(*doffp, v[idx].sh_addralign); v[idx].sh_offset = *doffp; --- 2033,2069 ---- continue; } symtab = symchk; strtab = strchk; ! if (symtab != NULL && ctf != NULL && ! (content & CC_CONTENT_DEBUG) == 0) { /* No other shdrs are of interest at this point */ break; } } if (ctf != NULL) count += 1; if (symtab != NULL) count += 2; + if (v == NULL || count == 0 || count > remain) { count = MIN(count, remain); goto done; } /* output CTF section */ if (ctf != NULL) { elf_ctx_resize_scratch(ctx, ctf->sh_size); ! if (!shstrtab_ndx(shstrtab, shstrtab_data[STR_CTF], ! &v[idx].sh_name)) { ! count = UINT_MAX; ! goto done; ! } ! v[idx].sh_addr = (Addr)(uintptr_t)saddr; v[idx].sh_type = SHT_PROGBITS; v[idx].sh_addralign = 4; *doffp = roundup(*doffp, v[idx].sh_addralign); v[idx].sh_offset = *doffp;
*** 2097,2112 **** elf_ctx_resize_scratch(ctx, MAX(symtab->sh_size, strtab->sh_size)); if (symtab->sh_type == SHT_DYNSYM) { ! symtab_name = shstrtab_ndx(shstrtab, STR_DYNSYM); ! strtab_name = shstrtab_ndx(shstrtab, STR_DYNSTR); } else { ! symtab_name = shstrtab_ndx(shstrtab, STR_SYMTAB); ! strtab_name = shstrtab_ndx(shstrtab, STR_STRTAB); } v[idx].sh_name = symtab_name; v[idx].sh_type = symtab->sh_type; v[idx].sh_addr = symtab->sh_addr; if (ehdr.e_type == ET_DYN || v[idx].sh_addr == 0) --- 2090,2115 ---- elf_ctx_resize_scratch(ctx, MAX(symtab->sh_size, strtab->sh_size)); if (symtab->sh_type == SHT_DYNSYM) { ! if (!shstrtab_ndx(shstrtab, shstrtab_data[STR_DYNSYM], ! &symtab_name) || ! !shstrtab_ndx(shstrtab, shstrtab_data[STR_DYNSTR], ! &strtab_name)) { ! count = UINT_MAX; ! goto done; ! } } else { ! if (!shstrtab_ndx(shstrtab, shstrtab_data[STR_SYMTAB], ! &symtab_name) || ! !shstrtab_ndx(shstrtab, shstrtab_data[STR_STRTAB], ! &strtab_name)) { ! count = UINT_MAX; ! goto done; } + } v[idx].sh_name = symtab_name; v[idx].sh_type = symtab->sh_type; v[idx].sh_addr = symtab->sh_addr; if (ehdr.e_type == ET_DYN || v[idx].sh_addr == 0)
*** 2162,2172 **** ASSERT(AS_WRITE_HELD(as)); if (v != NULL) { ASSERT(nv != 0); ! shstrtab_init(&shstrtab); remain = nv; } else { ASSERT(nv == 0); /* --- 2165,2176 ---- ASSERT(AS_WRITE_HELD(as)); if (v != NULL) { ASSERT(nv != 0); ! if (!shstrtab_init(&shstrtab)) ! return (ENOMEM); remain = nv; } else { ASSERT(nv == 0); /*
*** 2210,2219 **** --- 2214,2227 ---- if ((prot & (PROT_WRITE | PROT_EXEC)) != PROT_EXEC) continue; count = elf_process_obj_scns(ctx, mvp, saddr, v, idx, remain, &shstrtab); + if (count == UINT_MAX) { + error = ENOMEM; + goto done; + } ASSERT(count <= remain); ASSERT(v == NULL || (idx + count) < nv); remain -= count;
*** 2226,2246 **** *nshdrsp = 0; } else { /* Include room for the shrstrtab at the end */ *nshdrsp = idx + 1; } return (0); } if (idx != nv - 1) { cmn_err(CE_WARN, "elfcore: core dump failed for " "process %d; address space is changing", ctx->ecc_p->p_pid); ! return (EIO); } ! v[idx].sh_name = shstrtab_ndx(&shstrtab, STR_SHSTRTAB); v[idx].sh_size = shstrtab_size(&shstrtab); v[idx].sh_addralign = 1; v[idx].sh_offset = ctx->ecc_doffset; v[idx].sh_flags = SHF_STRINGS; v[idx].sh_type = SHT_STRTAB; --- 2234,2260 ---- *nshdrsp = 0; } else { /* Include room for the shrstrtab at the end */ *nshdrsp = idx + 1; } + /* No need to free up shstrtab so we can just return. */ return (0); } if (idx != nv - 1) { cmn_err(CE_WARN, "elfcore: core dump failed for " "process %d; address space is changing", ctx->ecc_p->p_pid); ! error = EIO; ! goto done; } ! if (!shstrtab_ndx(&shstrtab, shstrtab_data[STR_SHSTRTAB], ! &v[idx].sh_name)) { ! error = ENOMEM; ! goto done; ! } v[idx].sh_size = shstrtab_size(&shstrtab); v[idx].sh_addralign = 1; v[idx].sh_offset = ctx->ecc_doffset; v[idx].sh_flags = SHF_STRINGS; v[idx].sh_type = SHT_STRTAB;
*** 2253,2262 **** --- 2267,2279 ---- ctx->ecc_buf, v[idx].sh_size, ctx->ecc_rlimit, ctx->ecc_credp); if (error == 0) { ctx->ecc_doffset += v[idx].sh_size; } + done: + if (v != NULL) + shstrtab_fini(&shstrtab); return (error); } int elfcore(vnode_t *vp, proc_t *p, cred_t *credp, rlim64_t rlimit, int sig,
*** 2300,2312 **** /* * Count the number of section headers we're going to need. */ nshdrs = 0; ! if (content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)) { VERIFY0(elf_process_scns(&ctx, NULL, 0, &nshdrs)); - } AS_LOCK_EXIT(as); /* * The core file contents may require zero section headers, but if * we overflow the 16 bits allotted to the program header count in --- 2317,2328 ---- /* * Count the number of section headers we're going to need. */ nshdrs = 0; ! if (content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB | CC_CONTENT_DEBUG)) VERIFY0(elf_process_scns(&ctx, NULL, 0, &nshdrs)); AS_LOCK_EXIT(as); /* * The core file contents may require zero section headers, but if * we overflow the 16 bits allotted to the program header count in
*** 2315,2328 **** if (nshdrs == 0 && nphdrs >= PN_XNUM) { nshdrs = 1; } /* ! * Allocate a buffer which is sized adequately to hold the ehdr, phdrs ! * or shdrs needed to produce the core file. It is used for the three ! * tasks sequentially, not simultaneously, so it does not need space ! * for all three data at once, only the largest one. */ VERIFY(nphdrs >= 2); phdrsz = nphdrs * sizeof (Phdr); shdrsz = nshdrs * sizeof (Shdr); bigsize = MAX(sizeof (Ehdr), MAX(phdrsz, shdrsz)); --- 2331,2345 ---- if (nshdrs == 0 && nphdrs >= PN_XNUM) { nshdrs = 1; } /* ! * Allocate a buffer which is sized adequately to hold the ehdr, ! * phdrs, DWARF debug, or shdrs needed to produce the core file. It ! * is used for the four tasks sequentially, not simultaneously, so it ! * does not need space for all four data at once, only the largest ! * one. */ VERIFY(nphdrs >= 2); phdrsz = nphdrs * sizeof (Phdr); shdrsz = nshdrs * sizeof (Shdr); bigsize = MAX(sizeof (Ehdr), MAX(phdrsz, shdrsz));