summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--exception_lists/packaging7
-rw-r--r--usr/src/cmd/sgs/include/conv.h4
-rw-r--r--usr/src/cmd/sgs/libconv/common/corenote.c13
-rw-r--r--usr/src/cmd/sgs/libconv/common/corenote.msg3
-rw-r--r--usr/src/common/core/core_shstrtab.c145
-rw-r--r--usr/src/common/core/core_shstrtab.h73
-rw-r--r--usr/src/lib/libproc/Makefile.com7
-rw-r--r--usr/src/lib/libproc/common/Pgcore.c222
-rw-r--r--usr/src/man/man1m/coreadm.1m32
-rw-r--r--usr/src/man/man4/core.46
-rw-r--r--usr/src/pkg/manifests/system-test-ostest.mf9
-rw-r--r--usr/src/test/os-tests/runfiles/default.run5
-rw-r--r--usr/src/test/os-tests/tests/Makefile1
-rw-r--r--usr/src/test/os-tests/tests/cores/Makefile22
-rw-r--r--usr/src/test/os-tests/tests/cores/Makefile.com17
-rw-r--r--usr/src/test/os-tests/tests/cores/Makefile.targ48
-rw-r--r--usr/src/test/os-tests/tests/cores/dumper/Makefile57
-rw-r--r--usr/src/test/os-tests/tests/cores/dumper/dumper.c64
-rw-r--r--usr/src/test/os-tests/tests/cores/libdumper/Makefile41
-rw-r--r--usr/src/test/os-tests/tests/cores/libdumper/Makefile.com44
-rw-r--r--usr/src/test/os-tests/tests/cores/libdumper/amd64/Makefile19
-rw-r--r--usr/src/test/os-tests/tests/cores/libdumper/common/libdumper.c36
-rw-r--r--usr/src/test/os-tests/tests/cores/libdumper/common/mapfile-vers44
-rw-r--r--usr/src/test/os-tests/tests/cores/libdumper/i386/Makefile18
-rw-r--r--usr/src/test/os-tests/tests/cores/scripts/Makefile36
-rw-r--r--usr/src/test/os-tests/tests/cores/scripts/core_prereqs.ksh31
-rw-r--r--usr/src/test/os-tests/tests/cores/scripts/coretests.ksh135
-rw-r--r--usr/src/test/os-tests/tests/cores/secmapper/Makefile48
-rw-r--r--usr/src/test/os-tests/tests/cores/secmapper/secmapper.c434
-rw-r--r--usr/src/uts/common/Makefile.files2
-rw-r--r--usr/src/uts/common/Makefile.rules4
-rw-r--r--usr/src/uts/common/exec/elf/elf.c160
-rw-r--r--usr/src/uts/common/sys/corectl.h3
-rw-r--r--usr/src/uts/intel/elfexec/Makefile2
-rw-r--r--usr/src/uts/sparc/elfexec/Makefile1
35 files changed, 1610 insertions, 183 deletions
diff --git a/exception_lists/packaging b/exception_lists/packaging
index ab1499c227..993ada83e4 100644
--- a/exception_lists/packaging
+++ b/exception_lists/packaging
@@ -923,3 +923,10 @@ opt/onbld/man/man1onbld/sgsmsg.1onbld
# The built link-editor demos are not delivered
#
opt/SUNWonld/
+
+#
+# Libraries that are built for tests whose compilation symlinks are only
+# needed at build time.
+#
+opt/os-tests/tests/cores/libdumper.so
+opt/os-tests/tests/cores/amd64/libdumper.so i386
diff --git a/usr/src/cmd/sgs/include/conv.h b/usr/src/cmd/sgs/include/conv.h
index cff2530673..cb11e237e3 100644
--- a/usr/src/cmd/sgs/include/conv.h
+++ b/usr/src/cmd/sgs/include/conv.h
@@ -27,7 +27,7 @@
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2018, Joyent, Inc.
* Copyright 2016 RackTop Systems.
- * Copyright 2020 Oxide Computer Company
+ * Copyright 2021 Oxide Computer Company
*/
#ifndef _CONV_H
@@ -379,7 +379,7 @@ typedef union {
} Conv_cnote_ss_flags_buf_t;
/* conv_cnote_cc_content() */
-#define CONV_CNOTE_CC_CONTENT_BUFSIZE 97
+#define CONV_CNOTE_CC_CONTENT_BUFSIZE 103
typedef union {
Conv_inv_buf_t inv_buf;
char buf[CONV_CNOTE_CC_CONTENT_BUFSIZE];
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.c b/usr/src/cmd/sgs/libconv/common/corenote.c
index 73913c5eaf..76e6c78c49 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.c
+++ b/usr/src/cmd/sgs/libconv/common/corenote.c
@@ -26,8 +26,8 @@
/*
* Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2018 Joyent, Inc.
- * Copyright 2020 Oxide Computer Company
* Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
+ * Copyright 2021 Oxide Computer Company
*/
/*
@@ -1064,6 +1064,7 @@ conv_cnote_auxv_af(Word flags, Conv_fmt_flags_t fmt_flags,
MSG_CC_CONTENT_DISM_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
MSG_CC_CONTENT_CTF_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
MSG_CC_CONTENT_SYMTAB_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
+ MSG_CC_CONTENT_DEBUG_SIZE + CONV_EXPN_FIELD_DEF_SEP_SIZE + \
CONV_INV_BUFSIZE + CONV_EXPN_FIELD_DEF_SUFFIX_SIZE
/*
@@ -1082,6 +1083,15 @@ conv_cnote_auxv_af(Word flags, Conv_fmt_flags_t fmt_flags,
#error "CONV_CNOTE_CC_CONTENT_BUFSIZE does not match CCFLGSZ"
#endif
+/*
+ * This is required to work around tools ld bootstrapping issues where
+ * CC_CONTENT_DEBUG is not present. When an illumos sysroot has this present it
+ * will probably be safe to remove this.
+ */
+#ifndef CC_CONTENT_DEBUG
+#define CC_CONTENT_DEBUG 0x2000ULL
+#endif
+
const char *
conv_cnote_cc_content(Lword flags, Conv_fmt_flags_t fmt_flags,
Conv_cnote_cc_content_buf_t *cnote_cc_content_buf)
@@ -1114,6 +1124,7 @@ conv_cnote_cc_content(Lword flags, Conv_fmt_flags_t fmt_flags,
{ (Word) CC_CONTENT_DISM, MSG_CC_CONTENT_DISM },
{ (Word) CC_CONTENT_CTF, MSG_CC_CONTENT_CTF },
{ (Word) CC_CONTENT_SYMTAB, MSG_CC_CONTENT_SYMTAB },
+ { (Word) CC_CONTENT_DEBUG, MSG_CC_CONTENT_DEBUG },
{ 0, 0 }
};
static CONV_EXPN_FIELD_ARG conv_arg = {
diff --git a/usr/src/cmd/sgs/libconv/common/corenote.msg b/usr/src/cmd/sgs/libconv/common/corenote.msg
index d8ecedaff5..c202c1c62c 100644
--- a/usr/src/cmd/sgs/libconv/common/corenote.msg
+++ b/usr/src/cmd/sgs/libconv/common/corenote.msg
@@ -25,8 +25,8 @@
#
# Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
# Copyright (c) 2018 Joyent, Inc.
-# Copyright 2020 Oxide Computer Company
# Copyright 2021 OmniOS Community Edition (OmniOSce) Association.
+# Copyright 2021 Oxide Computer Company
#
@ MSG_NT_PRSTATUS "[ NT_PRSTATUS ]"
@@ -128,6 +128,7 @@
@ MSG_CC_CONTENT_DISM "DISM"
@ MSG_CC_CONTENT_CTF "CTF"
@ MSG_CC_CONTENT_SYMTAB "SYMTAB"
+@ MSG_CC_CONTENT_DEBUG "DEBUG"
@ MSG_ERRNO_EPERM "[ EPERM ]" # 1
diff --git a/usr/src/common/core/core_shstrtab.c b/usr/src/common/core/core_shstrtab.c
new file mode 100644
index 0000000000..b1bcbce682
--- /dev/null
+++ b/usr/src/common/core/core_shstrtab.c
@@ -0,0 +1,145 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2021 Oxide Computer Company
+ */
+
+#ifndef _KERNEL
+#include <stdlib.h>
+#include <strings.h>
+#include <stddef.h>
+#else
+#include <sys/types.h>
+#include <sys/kmem.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/stddef.h>
+#endif /* _KERNEL */
+
+#include <core_shstrtab.h>
+
+const char *shstrtab_data[STR_NUM] = {
+ "",
+ ".SUNW_ctf",
+ ".symtab",
+ ".dynsym",
+ ".strtab",
+ ".dynstr",
+ ".shstrtab"
+};
+
+static void *
+shstrtab_alloc(void)
+{
+#ifdef _KERNEL
+ return (kmem_zalloc(sizeof (shstrtab_ent_t),
+ KM_NOSLEEP | KM_NORMALPRI));
+#else
+ return (calloc(1, sizeof (shstrtab_ent_t)));
+#endif
+}
+
+static void
+shstrtab_free(shstrtab_ent_t *ent)
+{
+#ifdef _KERNEL
+ if (ent->sste_name != NULL) {
+ strfree(ent->sste_name);
+ }
+ kmem_free(ent, sizeof (*ent));
+#else
+ free(ent->sste_name);
+ free(ent);
+#endif
+}
+
+
+boolean_t
+shstrtab_ndx(shstrtab_t *s, const char *name, Elf32_Word *offp)
+{
+ shstrtab_ent_t *ent;
+
+ for (ent = list_head(&s->sst_names); ent != NULL;
+ ent = list_next(&s->sst_names, ent)) {
+ if (strcmp(name, ent->sste_name) == 0) {
+ if (offp != NULL)
+ *offp = ent->sste_offset;
+ return (B_TRUE);
+ }
+ }
+
+ ent = shstrtab_alloc();
+ if (ent == NULL) {
+ return (B_FALSE);
+ }
+
+ ent->sste_name = strdup(name);
+ if (ent->sste_name == NULL) {
+ shstrtab_free(ent);
+ return (B_FALSE);
+ }
+ ent->sste_len = strlen(name) + 1;
+ ent->sste_offset = s->sst_len;
+ s->sst_len += ent->sste_len;
+
+ list_insert_tail(&s->sst_names, ent);
+
+ if (offp != NULL)
+ *offp = ent->sste_offset;
+ return (B_TRUE);
+}
+
+boolean_t
+shstrtab_init(shstrtab_t *s)
+{
+ bzero(s, sizeof (*s));
+ list_create(&s->sst_names, sizeof (shstrtab_ent_t),
+ offsetof(shstrtab_ent_t, sste_link));
+
+ return (shstrtab_ndx(s, shstrtab_data[STR_NONE], NULL));
+}
+
+void
+shstrtab_fini(shstrtab_t *s)
+{
+ shstrtab_ent_t *ent;
+
+ if (s->sst_len == 0)
+ return;
+
+ while ((ent = list_remove_head(&s->sst_names)) != NULL) {
+ shstrtab_free(ent);
+ }
+}
+
+size_t
+shstrtab_size(const shstrtab_t *s)
+{
+ return (s->sst_len);
+}
+
+void
+shstrtab_dump(shstrtab_t *s, void *buf)
+{
+ size_t off = 0;
+
+ for (shstrtab_ent_t *ent = list_head(&s->sst_names); ent != NULL;
+ ent = list_next(&s->sst_names, ent)) {
+ bcopy(ent->sste_name, buf + off, ent->sste_len);
+ off += ent->sste_len;
+ }
+}
diff --git a/usr/src/common/core/core_shstrtab.h b/usr/src/common/core/core_shstrtab.h
new file mode 100644
index 0000000000..111c3226a8
--- /dev/null
+++ b/usr/src/common/core/core_shstrtab.h
@@ -0,0 +1,73 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright 2021 Oxide Computer Company
+ */
+
+#ifndef _CORE_SHSTRTAB_H
+#define _CORE_SHSTRTAB_H
+
+/*
+ * This header contains common definitions that are used to generate a
+ * shstrtab_t for core files. This is used by libproc and the kernel to generate
+ * core files in a similar way.
+ */
+
+#include <sys/list.h>
+#include <sys/stdint.h>
+#include <sys/elf.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+ STR_NONE,
+ STR_CTF,
+ STR_SYMTAB,
+ STR_DYNSYM,
+ STR_STRTAB,
+ STR_DYNSTR,
+ STR_SHSTRTAB,
+ STR_NUM
+} shstrtype_t;
+
+extern const char *shstrtab_data[STR_NUM];
+
+typedef struct shstrtab_ent {
+ list_node_t sste_link;
+ char *sste_name;
+ size_t sste_len;
+ uint32_t sste_offset;
+} shstrtab_ent_t;
+
+typedef struct shstrtab {
+ list_t sst_names;
+ uint32_t sst_len;
+} shstrtab_t;
+
+extern boolean_t shstrtab_init(shstrtab_t *s);
+extern boolean_t shstrtab_ndx(shstrtab_t *, const char *, Elf32_Word *);
+extern void shstrtab_fini(shstrtab_t *);
+extern size_t shstrtab_size(const shstrtab_t *);
+extern void shstrtab_dump(shstrtab_t *, void *);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _CORE_SHSTRTAB_H */
diff --git a/usr/src/lib/libproc/Makefile.com b/usr/src/lib/libproc/Makefile.com
index b2f7e00e69..f5dabd2947 100644
--- a/usr/src/lib/libproc/Makefile.com
+++ b/usr/src/lib/libproc/Makefile.com
@@ -30,6 +30,7 @@ LIBRARY = libproc.a
VERS = .1
CMNOBJS = \
+ core_shstrtab.o \
list.o \
P32ton.o \
Pcontrol.o \
@@ -90,7 +91,7 @@ SRCS = $(CMNOBJS:%.o=../common/%.c) $(ISAOBJS:%.o=%.c)
LIBS = $(DYNLIB)
LDLIBS += -lrtld_db -lelf -lctf -lc
CSTD = $(CSTD_GNU99)
-CPPFLAGS += $($(MACH64)_CPPFLAGS)
+CPPFLAGS += $($(MACH64)_CPPFLAGS) -I$(SRC)/common/core
SRCDIR = ../common
@@ -126,3 +127,7 @@ objs/%.o pics/%.o: %.c
objs/%.o pics/%.o: $(SRC)/common/list/%.c
$(COMPILE.c) -o $@ $<
$(POST_PROCESS_O)
+
+objs/%.o pics/%.o: $(SRC)/common/core/%.c
+ $(COMPILE.c) -o $@ $<
+ $(POST_PROCESS_O)
diff --git a/usr/src/lib/libproc/common/Pgcore.c b/usr/src/lib/libproc/common/Pgcore.c
index 874579f055..89dc1c855f 100644
--- a/usr/src/lib/libproc/common/Pgcore.c
+++ b/usr/src/lib/libproc/common/Pgcore.c
@@ -33,6 +33,7 @@
#define _STRUCTURED_PROC 1
+#include <assert.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
@@ -46,6 +47,7 @@
#include <sys/systeminfo.h>
#include <sys/proc.h>
#include <sys/utsname.h>
+#include <core_shstrtab.h>
#include <sys/old_procfs.h>
@@ -53,32 +55,6 @@
#include "P32ton.h"
#include "proc_fd.h"
-typedef enum {
- STR_NONE,
- 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 {
- int sst_ndx[STR_NUM];
- int sst_cur;
-} shstrtab_t;
-
typedef struct {
struct ps_prochandle *P;
int pgc_fd;
@@ -120,33 +96,6 @@ gc_pwrite64(int fd, const void *buf, size_t len, off64_t off)
return (0);
}
-static void
-shstrtab_init(shstrtab_t *s)
-{
- bzero(&s->sst_ndx, sizeof (s->sst_ndx));
- s->sst_cur = 1;
-}
-
-static int
-shstrtab_ndx(shstrtab_t *s, shstrtype_t type)
-{
- int ret;
-
- if ((ret = s->sst_ndx[type]) != 0 || type == STR_NONE)
- 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);
-}
-
int
Pgcore(struct ps_prochandle *P, const char *fname, core_content_t content)
{
@@ -631,6 +580,51 @@ iter_fd(void *data, const prfdinfo_t *fdinfo)
return (0);
}
+/*
+ * Look for sections that begin with the string '.debug_'. In particular, this
+ * will catch all DWARF related sections and it will catch those that different
+ * folks use that are not related to DWARF, but still begin with this prefix
+ * (e.g. .debug_gdb_scripts). Notably though, this does not catch something like
+ * stabs (though it could). This really is filtering based on the section name,
+ * less so intent.
+ */
+static boolean_t
+is_debug_section(file_info_t *fptr, GElf_Shdr *shdr)
+{
+ if (shdr->sh_name == 0 || shdr->sh_name > fptr->file_shstrsz)
+ return (B_FALSE);
+
+ if (strncmp(fptr->file_shstrs + shdr->sh_name, ".debug_",
+ strlen(".debug_")) != 0) {
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
+}
+
+static uint_t
+count_debug(file_info_t *fptr)
+{
+ uint_t count = 0;
+ Elf_Scn *scn = NULL;
+
+ if (fptr->file_elf == NULL || fptr->file_shstrsz <= 1) {
+ return (0);
+ }
+
+ while ((scn = elf_nextscn(fptr->file_elf, scn)) != NULL) {
+ GElf_Shdr shdr;
+
+ if (gelf_getshdr(scn, &shdr) == NULL)
+ continue;
+
+ if (is_debug_section(fptr, &shdr))
+ count++;
+ }
+
+ return (count);
+}
+
static uint_t
count_sections(pgcore_t *pgc)
{
@@ -638,8 +632,10 @@ count_sections(pgcore_t *pgc)
file_info_t *fptr;
uint_t nshdrs = 0;
- if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)))
+ if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB |
+ CC_CONTENT_DEBUG))) {
return (0);
+ }
for (fptr = list_head(&P->file_head); fptr != NULL;
fptr = list_next(&P->file_head, fptr)) {
@@ -671,13 +667,16 @@ count_sections(pgcore_t *pgc)
fptr->file_symtab.sym_strs != NULL) {
nshdrs += 2;
}
+
+ if ((pgc->pgc_content & CC_CONTENT_DEBUG) != 0)
+ nshdrs += count_debug(fptr);
}
return (nshdrs == 0 ? 0 : nshdrs + 2);
}
static int
-write_shdr(pgcore_t *pgc, shstrtype_t name, uint_t type, ulong_t flags,
+write_shdr(pgcore_t *pgc, const char *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)
{
@@ -685,7 +684,9 @@ write_shdr(pgcore_t *pgc, shstrtype_t name, uint_t type, ulong_t flags,
Elf32_Shdr shdr;
bzero(&shdr, sizeof (shdr));
- shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, name);
+ if (!shstrtab_ndx(&pgc->pgc_shstrtab, name, &shdr.sh_name)) {
+ return (-1);
+ }
shdr.sh_type = type;
shdr.sh_flags = flags;
shdr.sh_addr = (Elf32_Addr)addr;
@@ -706,7 +707,9 @@ write_shdr(pgcore_t *pgc, shstrtype_t name, uint_t type, ulong_t flags,
Elf64_Shdr shdr;
bzero(&shdr, sizeof (shdr));
- shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, name);
+ if (!shstrtab_ndx(&pgc->pgc_shstrtab, name, &shdr.sh_name)) {
+ return (-1);
+ }
shdr.sh_type = type;
shdr.sh_flags = flags;
shdr.sh_addr = addr;
@@ -747,9 +750,9 @@ dump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym)
*pgc->pgc_doff) != 0)
return (-1);
- if (write_shdr(pgc, symname, symtype, 0, addr, *pgc->pgc_doff, size,
- index + 1, sym->sym_hdr_pri.sh_info, sym->sym_hdr_pri.sh_addralign,
- sym->sym_hdr_pri.sh_entsize) != 0)
+ if (write_shdr(pgc, shstrtab_data[symname], symtype, 0, addr,
+ *pgc->pgc_doff, size, index + 1, sym->sym_hdr_pri.sh_info,
+ sym->sym_hdr_pri.sh_addralign, sym->sym_hdr_pri.sh_entsize) != 0)
return (-1);
*pgc->pgc_doff += roundup(size, 8);
@@ -758,8 +761,8 @@ dump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym)
if (gc_pwrite64(pgc->pgc_fd, sym->sym_strs, size, *pgc->pgc_doff) != 0)
return (-1);
- if (write_shdr(pgc, strname, SHT_STRTAB, SHF_STRINGS, addr,
- *pgc->pgc_doff, size, 0, 0, 1, 0) != 0)
+ if (write_shdr(pgc, shstrtab_data[strname], SHT_STRTAB, SHF_STRINGS,
+ addr, *pgc->pgc_doff, size, 0, 0, 1, 0) != 0)
return (-1);
*pgc->pgc_doff += roundup(size, 8);
@@ -768,14 +771,58 @@ dump_symtab(pgcore_t *pgc, file_info_t *fptr, uint_t index, int dynsym)
}
static int
+dump_debug(pgcore_t *pgc, file_info_t *fptr, uint_t *indexp)
+{
+ Elf_Scn *scn = NULL;
+
+ if (fptr->file_elf == NULL || fptr->file_shstrsz <= 1) {
+ return (0);
+ }
+
+ while ((scn = elf_nextscn(fptr->file_elf, scn)) != NULL) {
+ GElf_Shdr shdr;
+ Elf_Data *data;
+
+ if (gelf_getshdr(scn, &shdr) == NULL)
+ continue;
+
+ if (!is_debug_section(fptr, &shdr))
+ continue;
+
+ if ((data = elf_getdata(scn, NULL)) == NULL) {
+ return (-1);
+ }
+
+ if (gc_pwrite64(pgc->pgc_fd, data->d_buf, data->d_size,
+ *pgc->pgc_doff) != 0)
+ return (-1);
+
+ if (write_shdr(pgc, fptr->file_shstrs + shdr.sh_name,
+ shdr.sh_type, shdr.sh_flags,
+ fptr->file_map->map_pmap.pr_vaddr, *pgc->pgc_doff,
+ data->d_size, 0, shdr.sh_info, shdr.sh_addralign,
+ shdr.sh_entsize) != 0) {
+ return (-1);
+ }
+
+ *indexp = *indexp + 1;
+ *pgc->pgc_doff += roundup(data->d_size, 8);
+ }
+
+ return (0);
+}
+
+static int
dump_sections(pgcore_t *pgc)
{
struct ps_prochandle *P = pgc->P;
file_info_t *fptr;
uint_t index = 1;
- if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)))
+ if (!(pgc->pgc_content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB |
+ CC_CONTENT_DEBUG))) {
return (0);
+ }
for (fptr = list_head(&P->file_head); fptr != NULL;
fptr = list_next(&P->file_head, fptr)) {
@@ -820,9 +867,10 @@ dump_sections(pgcore_t *pgc)
fptr->file_ctf_size, *pgc->pgc_doff) != 0)
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)
+ if (write_shdr(pgc, shstrtab_data[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++;
@@ -837,6 +885,11 @@ dump_sections(pgcore_t *pgc)
return (-1);
index += 2;
}
+
+ if ((pgc->pgc_content & CC_CONTENT_DEBUG) != 0 &&
+ dump_debug(pgc, fptr, &index) != 0) {
+ return (-1);
+ }
}
return (0);
@@ -995,7 +1048,6 @@ write_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);
@@ -1003,19 +1055,21 @@ write_shstrtab(struct ps_prochandle *P, pgcore_t *pgc)
/*
* Preemptively stick the name of the shstrtab in the string table.
*/
- (void) shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB);
+ if (!shstrtab_ndx(&pgc->pgc_shstrtab,
+ shstrtab_data[STR_SHSTRTAB], NULL)) {
+ return (1);
+ }
size = shstrtab_size(s);
/*
* 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 || i == STR_NONE) {
- const char *str = shstrtab_data[i];
- size_t len = strlen(str) + 1;
- if (gc_pwrite64(pgc->pgc_fd, str, len, off + ndx) != 0)
- return (1);
+ for (shstrtab_ent_t *ent = list_head(&s->sst_names); ent != NULL;
+ ent = list_next(&s->sst_names, ent)) {
+ if (gc_pwrite64(pgc->pgc_fd, ent->sste_name, ent->sste_len,
+ off + ent->sste_offset) != 0) {
+ return (1);
}
}
@@ -1023,7 +1077,10 @@ write_shstrtab(struct ps_prochandle *P, pgcore_t *pgc)
Elf32_Shdr shdr;
bzero(&shdr, sizeof (shdr));
- shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB);
+ if (!shstrtab_ndx(&pgc->pgc_shstrtab,
+ shstrtab_data[STR_SHSTRTAB], &shdr.sh_name)) {
+ return (1);
+ }
shdr.sh_size = size;
shdr.sh_offset = *pgc->pgc_doff;
shdr.sh_addralign = 1;
@@ -1040,7 +1097,10 @@ write_shstrtab(struct ps_prochandle *P, pgcore_t *pgc)
Elf64_Shdr shdr;
bzero(&shdr, sizeof (shdr));
- shdr.sh_name = shstrtab_ndx(&pgc->pgc_shstrtab, STR_SHSTRTAB);
+ if (!shstrtab_ndx(&pgc->pgc_shstrtab,
+ shstrtab_data[STR_SHSTRTAB], &shdr.sh_name)) {
+ return (1);
+ }
shdr.sh_size = size;
shdr.sh_offset = *pgc->pgc_doff;
shdr.sh_addralign = 1;
@@ -1088,6 +1148,7 @@ Pfgcore(struct ps_prochandle *P, int fd, core_content_t content)
(void) Prd_agent(P);
(void) Ppsinfo(P);
+ (void) memset(&pgc, 0, sizeof (pgc));
pgc.P = P;
pgc.pgc_fd = fd;
pgc.pgc_poff = &poff;
@@ -1098,7 +1159,9 @@ Pfgcore(struct ps_prochandle *P, int fd, core_content_t content)
if ((pgc.pgc_chunk = malloc(pgc.pgc_chunksz)) == NULL)
return (-1);
- shstrtab_init(&pgc.pgc_shstrtab);
+ if (!shstrtab_init(&pgc.pgc_shstrtab)) {
+ goto err;
+ }
/*
* There are two PT_NOTE program headers for ancillary data, and
@@ -1246,7 +1309,7 @@ Pfgcore(struct ps_prochandle *P, int fd, core_content_t content)
/*
* Write the zero indexed section if it exists.
*/
- if (nshdrs > 0 && write_shdr(&pgc, STR_NONE, 0, 0, 0, 0,
+ if (nshdrs > 0 && write_shdr(&pgc, shstrtab_data[STR_NONE], 0, 0, 0, 0,
nshdrs >= SHN_LORESERVE ? nshdrs : 0,
nshdrs - 1 >= SHN_LORESERVE ? nshdrs - 1 : 0,
nphdrs >= PN_XNUM ? nphdrs : 0, 0, 0) != 0)
@@ -1536,6 +1599,7 @@ Pfgcore(struct ps_prochandle *P, int fd, core_content_t content)
goto err;
free(pgc.pgc_chunk);
+ shstrtab_fini(&pgc.pgc_shstrtab);
return (0);
@@ -1545,6 +1609,7 @@ err:
*/
(void) ftruncate64(fd, 0);
free(pgc.pgc_chunk);
+ shstrtab_fini(&pgc.pgc_shstrtab);
return (-1);
}
@@ -1563,6 +1628,7 @@ static const char *content_str[] = {
"dism", /* CC_CONTENT_DISM */
"ctf", /* CC_CONTENT_CTF */
"symtab", /* CC_CONTENT_SYMTAB */
+ "debug" /* CC_CONTENT_DEBUG */
};
static uint_t ncontent_str = sizeof (content_str) / sizeof (content_str[0]);
diff --git a/usr/src/man/man1m/coreadm.1m b/usr/src/man/man1m/coreadm.1m
index 8b7b25e387..3073d5ce8c 100644
--- a/usr/src/man/man1m/coreadm.1m
+++ b/usr/src/man/man1m/coreadm.1m
@@ -1,13 +1,13 @@
'\" te
.\" Copyright 1989 AT&T Copyright (c) 2008 Sun Microsystems, Inc. All Rights Reserved.
+.\" Copyright 2021 Oxide Computer Company
.\" The contents of this file are subject to the terms of the Common Development and Distribution License (the "License"). You may not use this file except in compliance with the License.
.\" You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE or http://www.opensolaris.org/os/licensing. See the License for the specific language governing permissions and limitations under the License.
.\" When distributing Covered Code, include this CDDL HEADER in each file and include the License file at usr/src/OPENSOLARIS.LICENSE. If applicable, add the following below this CDDL HEADER, with the fields enclosed by brackets "[]" replaced with your own identifying information: Portions Copyright [yyyy] [name of copyright owner]
-.TH COREADM 1M "Feb 28, 2014"
+.TH COREADM 1M "August 3, 2021"
.SH NAME
coreadm \- core file administration
.SH SYNOPSIS
-.LP
.nf
\fBcoreadm\fR [\fB-g\fR \fIpattern\fR] [\fB-G\fR \fIcontent\fR] [\fB-i\fR \fIpattern\fR] [\fB-I\fR \fIcontent\fR]
[\fB-d\fR \fIoption\fR]... [\fB-e\fR \fIoption\fR]...
@@ -19,8 +19,6 @@ coreadm \- core file administration
.fi
.SH DESCRIPTION
-.sp
-.LP
\fBcoreadm\fR specifies the name and location of core files produced by
abnormally-terminating processes. See \fBcore\fR(4).
.sp
@@ -194,6 +192,20 @@ Writable private file mappings
.sp
.ne 2
.na
+\fB\fBdebug\fR\fR
+.ad
+.sp .6
+.RS 4n
+Debug sections, commonly DWARF. All sections that begin with '.debug_'.
+Note, this does capture non-DWARF related sections that begin with the
+string pattern; however, at this time other debug formats such as STABS
+are not included. Other debug formats would be included here in the
+future.
+.RE
+
+.sp
+.ne 2
+.na
\fB\fBdism\fR\fR
.ad
.sp .6
@@ -370,8 +382,6 @@ address space to which the current nonprivileged owner of the process should
not have access. If \fBsetid\fR core files are enabled, they are created mode
\fB600\fR and owned by the superuser.
.SH OPTIONS
-.sp
-.LP
The following options are supported:
.sp
.ne 2
@@ -562,8 +572,6 @@ file content to \fIcontent\fR on the parent process (usually the shell that ran
.RE
.SH OPERANDS
-.sp
-.LP
The following operands are supported:
.sp
.ne 2
@@ -576,7 +584,6 @@ process-\fBID\fR
.RE
.SH EXAMPLES
-.LP
\fBExample 1 \fRSetting the Core File Name Pattern
.sp
.LP
@@ -634,7 +641,6 @@ example# coreadm -G all -g /var/cores/%d/%f.%p.%n
.sp
.SH FILES
-.sp
.ne 2
.na
\fB\fB/var/cores\fR\fR
@@ -645,8 +651,6 @@ Directory provided for global core file storage.
.RE
.SH EXIT STATUS
-.sp
-.LP
The following exit values are returned:
.sp
.ne 2
@@ -680,15 +684,11 @@ Invalid command-line options were specified.
.RE
.SH SEE ALSO
-.sp
-.LP
\fBgcore\fR(1), \fBpfexec\fR(1), \fBsvcs\fR(1), \fBinit\fR(1M),
\fBsvcadm\fR(1M), \fBexec\fR(2), \fBfork\fR(2), \fBsetuid\fR(2), \fBtime\fR(2),
\fBsyslog\fR(3C), \fBcore\fR(4), \fBprof_attr\fR(4), \fBuser_attr\fR(4),
\fBattributes\fR(5), \fBsmf\fR(5)
.SH NOTES
-.sp
-.LP
In a local (non-global) zone, the global settings apply to processes running in
that zone. In addition, the global zone's apply to processes run in any zone.
.sp
diff --git a/usr/src/man/man4/core.4 b/usr/src/man/man4/core.4
index 95c7fea692..be63925f9f 100644
--- a/usr/src/man/man4/core.4
+++ b/usr/src/man/man4/core.4
@@ -3,7 +3,7 @@
.\" Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
.\" Copyright (c) 2013, Joyent, Inc. All rights reserved.
.\" Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
-.\" Copyright 2020 Oxide Computer Company
+.\" Copyright 2021 Oxide Computer Company
.\" Copyright 1989 AT&T
.\"
.\" The contents of this file are subject to the terms of the
@@ -21,7 +21,7 @@
.\" fields enclosed by brackets "[]" replaced with your own identifying
.\" information: Portions Copyright [yyyy] [name of copyright owner]
.\"
-.Dd October 31, 2020
+.Dd August 3, 2021
.Dt CORE 4
.Os
.Sh NAME
@@ -548,7 +548,7 @@ entry for more details.
Depending on the
.Xr coreadm 1M
settings, the section header of an ELF core file can contain entries for CTF,
-symbol table, and string table sections.
+DWARF debug information, symbol table, and string table sections.
The
.Fa sh_addr
fields are set to the base address of the first mapping of the load object that
diff --git a/usr/src/pkg/manifests/system-test-ostest.mf b/usr/src/pkg/manifests/system-test-ostest.mf
index 8eb2b28d90..84fd33d6c2 100644
--- a/usr/src/pkg/manifests/system-test-ostest.mf
+++ b/usr/src/pkg/manifests/system-test-ostest.mf
@@ -29,6 +29,8 @@ dir path=opt/os-tests
dir path=opt/os-tests/bin
dir path=opt/os-tests/runfiles
dir path=opt/os-tests/tests
+dir path=opt/os-tests/tests/cores
+$(i386_ONLY)dir path=opt/os-tests/tests/cores/amd64
dir path=opt/os-tests/tests/ddi_ufm
dir path=opt/os-tests/tests/file-locking
$(i386_ONLY)dir path=opt/os-tests/tests/i386
@@ -54,6 +56,13 @@ file path=opt/os-tests/tests/OS-6097.32 mode=0555
file path=opt/os-tests/tests/OS-6097.64 mode=0555
file path=opt/os-tests/tests/clock_gettime.32 mode=0555
file path=opt/os-tests/tests/clock_gettime.64 mode=0555
+$(i386_ONLY)file path=opt/os-tests/tests/cores/amd64/libdumper.so.1 mode=0755
+file path=opt/os-tests/tests/cores/core_prereqs mode=0555
+file path=opt/os-tests/tests/cores/coretests mode=0555
+file path=opt/os-tests/tests/cores/dumper.32 mode=0555
+file path=opt/os-tests/tests/cores/dumper.64 mode=0555
+file path=opt/os-tests/tests/cores/libdumper.so.1 mode=0755
+file path=opt/os-tests/tests/cores/secmapper mode=0555
file path=opt/os-tests/tests/ddi_ufm/ufm-test mode=0555
file path=opt/os-tests/tests/ddi_ufm/ufm-test-cleanup mode=0555
file path=opt/os-tests/tests/ddi_ufm/ufm-test-setup mode=0555
diff --git a/usr/src/test/os-tests/runfiles/default.run b/usr/src/test/os-tests/runfiles/default.run
index 363ee69942..e0fc585dc8 100644
--- a/usr/src/test/os-tests/runfiles/default.run
+++ b/usr/src/test/os-tests/runfiles/default.run
@@ -148,3 +148,8 @@ post = ksensor_fini
[/opt/os-tests/tests/stackalign]
tests = ['stackalign.32', 'stackalign.64']
+
+[/opt/os-tests/tests/cores]
+user = root
+pre = core_prereqs
+tests = ['coretests']
diff --git a/usr/src/test/os-tests/tests/Makefile b/usr/src/test/os-tests/tests/Makefile
index 28d7c8c8e2..a8f48fd878 100644
--- a/usr/src/test/os-tests/tests/Makefile
+++ b/usr/src/test/os-tests/tests/Makefile
@@ -19,6 +19,7 @@
SUBDIRS_i386 = i386 imc
SUBDIRS = \
+ cores \
ddi_ufm \
file-locking \
ksensor \
diff --git a/usr/src/test/os-tests/tests/cores/Makefile b/usr/src/test/os-tests/tests/cores/Makefile
new file mode 100644
index 0000000000..dccb694ae9
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/Makefile
@@ -0,0 +1,22 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+.PARALLEL: $(SUBDIRS)
+
+SUBDIRS = libdumper dumper scripts secmapper
+
+include $(SRC)/test/Makefile.com
+
+dumper: libdumper
diff --git a/usr/src/test/os-tests/tests/cores/Makefile.com b/usr/src/test/os-tests/tests/cores/Makefile.com
new file mode 100644
index 0000000000..daf8207a43
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/Makefile.com
@@ -0,0 +1,17 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+ROOTOPTDIR = $(ROOT)/opt/os-tests/tests
+ROOTOPTCORE = $(ROOTOPTDIR)/cores
diff --git a/usr/src/test/os-tests/tests/cores/Makefile.targ b/usr/src/test/os-tests/tests/cores/Makefile.targ
new file mode 100644
index 0000000000..9511df96ff
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/Makefile.targ
@@ -0,0 +1,48 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+$(ROOTOPTDIR):
+ $(INS.dir)
+
+$(ROOTOPTCORE): $(ROOTOPTDIR)
+ $(INS.dir)
+
+$(ROOTOPTCORE)/%: %
+ $(INS.file)
+
+$(ROOTOPTCORE)/%: %.ksh
+ $(INS.rename)
+
+%.32.o: %.c
+ $(COMPILE.c) $< -o $@
+ $(POST_PROCESS_O)
+
+%.64.o: %.c
+ $(COMPILE64.c) $< -o $@
+ $(POST_PROCESS_O)
+
+%.64: %.64.o
+ $(LINK64.c) -o $@ $< $(LDLIBS64)
+ $(POST_PROCESS)
+
+%.32: %.32.o
+ $(LINK.c) -o $@ $< $(LDLIBS)
+ $(POST_PROCESS)
+
+clobber: clean
+ $(RM) $(PROGS32) $(PROGS64)
+
+clean:
+ $(RM) $(ALLOBJS)
diff --git a/usr/src/test/os-tests/tests/cores/dumper/Makefile b/usr/src/test/os-tests/tests/cores/dumper/Makefile
new file mode 100644
index 0000000000..4e193e1193
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/dumper/Makefile
@@ -0,0 +1,57 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+PROGS = dumper
+
+PROGS32 = $(PROGS:%=%.32)
+PROGS64 = $(PROGS:%=%.64)
+ALLOBJS = $(PROGS32:%=%.o) $(PROGS64:%=%.o)
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/cmd/Makefile.ctf
+include ../Makefile.com
+
+ROOTOPTPROGS = $(PROGS32:%=$(ROOTOPTCORE)/%) \
+ $(PROGS64:%=$(ROOTOPTCORE)/%)
+
+LDLIBS += -lproc -L$(ROOTOPTCORE) -ldumper -R\$$ORIGIN
+LDLIBS64 += -lproc -L$(ROOTOPTCORE)/$(MACH64) -ldumper -R\$$ORIGIN/$(MACH64)
+
+#
+# We need to explicitly set the objects for some of our programs with
+# CTF so that way we can make sure that we have what we need.
+#
+dumper.32 := OBJS = dumper.32.o
+dumper.64 := OBJS = dumper.32.o
+
+#
+# This is admittedly, a bit gross. In particular we need to make sure
+# that we have debug information in the following programs.
+#
+STRIP_STABS = /bin/true
+
+.KEEP_STATE:
+
+all: $(PROGS32) $(PROGS64)
+
+install: $(ROOTOPTPROGS)
+
+clean:
+
+$(ROOTOPTPROGS): $(PROGS32) $(PROGS64) $(ROOTOPTCORE)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/test/os-tests/tests/cores/dumper/dumper.c b/usr/src/test/os-tests/tests/cores/dumper/dumper.c
new file mode 100644
index 0000000000..9539220139
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/dumper/dumper.c
@@ -0,0 +1,64 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2021 Oxide Computer Company
+ */
+
+/*
+ * This program is meant to be a victim process. It will set up its core content
+ * and location into the specific place we indicate in its arguments and then
+ * sleep until we gcore and ABRT it.
+ */
+
+#include <err.h>
+#include <stdlib.h>
+#include <sys/corectl.h>
+#include <libproc.h>
+#include <signal.h>
+
+extern int which_ff(uint32_t, uint32_t);
+
+int
+main(int argc, char *argv[])
+{
+ pid_t me = getpid();
+ core_content_t content;
+ sigset_t set = { 0 };
+
+ if (argc != 3) {
+ errx(EXIT_FAILURE, "<content> <dump path>");
+ }
+
+ if (proc_str2content(argv[1], &content) != 0) {
+ err(EXIT_FAILURE, "failed to parse content %s", argv[1]);
+ }
+
+ if (core_set_process_content(&content, me) != 0) {
+ err(EXIT_FAILURE, "failed to set core content to %s", argv[1]);
+ }
+
+ if (core_set_process_path(argv[2], strlen(argv[2]) + 1, me) != 0) {
+ err(EXIT_FAILURE, "failed to set core path to %s", argv[2]);
+ }
+
+ /*
+ * Call our library function to make sure it's present before we go and
+ * sleep.
+ */
+ (void) which_ff(6, 10);
+
+ for (;;) {
+ (void) sigsuspend(&set);
+ }
+
+ return (0);
+}
diff --git a/usr/src/test/os-tests/tests/cores/libdumper/Makefile b/usr/src/test/os-tests/tests/cores/libdumper/Makefile
new file mode 100644
index 0000000000..b807402808
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/libdumper/Makefile
@@ -0,0 +1,41 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+include $(SRC)/lib/Makefile.lib
+
+SUBDIRS = $(MACH)
+$(BUILD64)SUBDIRS += $(MACH64)
+
+all := TARGET = all
+clean := TARGET = clean
+clobber := TARGET = clobber
+install := TARGET = install
+
+.KEEP_STATE:
+
+all clean clobber: $(SUBDIRS)
+
+install: $(SUBDIRS)
+
+install_h:
+
+check: $(CHECKHDRS)
+
+$(SUBDIRS): FRC
+ @cd $@; pwd; $(MAKE) $(TARGET)
+
+FRC:
+
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/test/os-tests/tests/cores/libdumper/Makefile.com b/usr/src/test/os-tests/tests/cores/libdumper/Makefile.com
new file mode 100644
index 0000000000..3a985d3965
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/libdumper/Makefile.com
@@ -0,0 +1,44 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+LIBRARY = libdumper.a
+VERS = .1
+OBJECTS = libdumper.o
+
+include $(SRC)/lib/Makefile.lib
+include ../../Makefile.com
+
+ROOTLIBDIR = $(ROOTOPTCORE)
+ROOTLIBDIR64 = $(ROOTOPTCORE)/$(MACH64)
+
+LIBS = $(DYNLIB)
+LDLIBS += -lc
+SRCDIR = ../common
+
+#
+# This program needs to deliver DWARF data for debug purposes. Therefore
+# we override the strip to make sure that we can get that.
+#
+STRIP_STABS = /bin/true
+
+
+$(ROOTLIBDIR64): $(ROOTLIBDIR)
+ $(INS.dir)
+
+.KEEP_STATE:
+
+all: $(LIBS)
+
+include $(SRC)/lib/Makefile.targ
diff --git a/usr/src/test/os-tests/tests/cores/libdumper/amd64/Makefile b/usr/src/test/os-tests/tests/cores/libdumper/amd64/Makefile
new file mode 100644
index 0000000000..09690cb7b3
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/libdumper/amd64/Makefile
@@ -0,0 +1,19 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+include ../Makefile.com
+include $(SRC)/lib/Makefile.lib.64
+
+install: all $(ROOTLIBDIR64) .WAIT $(ROOTLIBS64) $(ROOTLINKS64)
diff --git a/usr/src/test/os-tests/tests/cores/libdumper/common/libdumper.c b/usr/src/test/os-tests/tests/cores/libdumper/common/libdumper.c
new file mode 100644
index 0000000000..027095a471
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/libdumper/common/libdumper.c
@@ -0,0 +1,36 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2021 Oxide Computer Company
+ */
+
+/*
+ * This is a dummy library that basically ensures we have yet another thing with
+ * CTF and DWARF data when we're testing core dumps.
+ */
+
+#include <err.h>
+#include <inttypes.h>
+#include <stdlib.h>
+
+const char *message_in_a_bottle = "Here's something that hopefully is rodata";
+
+int
+which_ff(uint32_t a, uint32_t b)
+{
+ if (a == 6 && b == 7) {
+ warnx("some debates are best left to forums");
+ abort();
+ }
+
+ return (0);
+}
diff --git a/usr/src/test/os-tests/tests/cores/libdumper/common/mapfile-vers b/usr/src/test/os-tests/tests/cores/libdumper/common/mapfile-vers
new file mode 100644
index 0000000000..e02f876869
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/libdumper/common/mapfile-vers
@@ -0,0 +1,44 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+#
+# MAPFILE HEADER START
+#
+# WARNING: STOP NOW. DO NOT MODIFY THIS FILE.
+# Object versioning must comply with the rules detailed in
+#
+# usr/src/lib/README.mapfiles
+#
+# You should not be making modifications here until you've read the most current
+# copy of that file. If you need help, contact a gatekeeper for guidance.
+#
+# MAPFILE HEADER END
+#
+
+$mapfile_version 2
+
+SYMBOL_VERSION ILLUMOSprivate {
+ global:
+ message_in_a_bottle {
+ ASSERT = {
+ TYPE = OBJECT;
+ SIZE = addrsize;
+ };
+ };
+
+ which_ff;
+ local:
+ *;
+};
diff --git a/usr/src/test/os-tests/tests/cores/libdumper/i386/Makefile b/usr/src/test/os-tests/tests/cores/libdumper/i386/Makefile
new file mode 100644
index 0000000000..0af99e030c
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/libdumper/i386/Makefile
@@ -0,0 +1,18 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide computer Company
+#
+
+include ../Makefile.com
+
+install: all $(ROOTLIBS) $(ROOTLINKS)
diff --git a/usr/src/test/os-tests/tests/cores/scripts/Makefile b/usr/src/test/os-tests/tests/cores/scripts/Makefile
new file mode 100644
index 0000000000..2e222b41c2
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/scripts/Makefile
@@ -0,0 +1,36 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+SCRIPTS = core_prereqs coretests
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/cmd/Makefile.ctf
+include ../Makefile.com
+
+ROOTOPTPROGS = $(SCRIPTS:%=$(ROOTOPTCORE)/%)
+
+.KEEP_STATE:
+
+all: $(PROGS32) $(PROGS64)
+
+install: $(ROOTOPTPROGS)
+
+$(ROOTOPTPROGS): $(ROOTOPTCORE)
+
+clean:
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/test/os-tests/tests/cores/scripts/core_prereqs.ksh b/usr/src/test/os-tests/tests/cores/scripts/core_prereqs.ksh
new file mode 100644
index 0000000000..490c47e205
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/scripts/core_prereqs.ksh
@@ -0,0 +1,31 @@
+#!/usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+#
+# The core tests require that we have per-process core dumps enabled.
+# This script is used as the pre-requisite in the test runner to verify
+# that fact.
+#
+
+set -o pipefail
+
+if coreadm | grep -q 'per-process core dumps: enabled'; then
+ exit 0
+fi
+
+echo "per -process core dumps are not enabled, skipping test" >&2
+exit 1
diff --git a/usr/src/test/os-tests/tests/cores/scripts/coretests.ksh b/usr/src/test/os-tests/tests/cores/scripts/coretests.ksh
new file mode 100644
index 0000000000..9e7f524070
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/scripts/coretests.ksh
@@ -0,0 +1,135 @@
+#!/usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+#
+# The goal of this test suite is to test certain aspects of core dump
+# generation and different core contents being specified. The
+# 'dumper.32' and 'dumper.64' programs are designed to be told what to
+# set a core content and path to, after which point we use both gcore
+# and the kernel to generate a core dump for the file and verify that it
+# has what we expect. The verification is done by the secmapper program.
+#
+
+unalias -a
+set -o pipefail
+
+core_arg0="$(basename $0)"
+core_dir="$(dirname $0)"
+core_dumper32="$core_dir/dumper.32"
+core_dumper64="$core_dir/dumper.64"
+core_checker="$core_dir/secmapper"
+
+core_tmpdir="/tmp/coretest.$$"
+core_exit=0
+
+#
+# This array describes the different types of core contents that we're
+# going to try and generate and check against.
+#
+core_contents="none
+ctf
+debug
+symtab
+ctf+debug+symtab
+anon+data+ctf+debug+symtab
+default
+default-ctf-debug-symtab
+default+debug
+default-symtab"
+
+warn()
+{
+ typeset msg="$*"
+ echo "TEST FAILED: $msg" >&2
+ core_exit=1
+}
+
+core_dump_one()
+{
+ typeset prog="$1"
+ typeset pbase=$(basename $prog)
+ typeset cont="$2"
+ typeset kpath="$3"
+ typeset gpath="$4"
+ typeset pid=
+
+ $prog "$cont" "$kpath" &
+ pid=$!
+ if (( $? != 0 )); then
+ warn "failed to spawn $core_dumper32: $cont $kpath"
+ return 1
+ fi
+
+ #
+ # This is racy, but probably should be a reasonable amount of
+ # time for dumper to be ready.
+ #
+ for ((i = 0; i < 10; i++)) {
+ if pstack $pid | grep -q 'fsigsuspend'; then
+ break
+ fi
+ }
+
+ if ! gcore -o "$gpath" -c "$cont" $pid >/dev/null; then
+ warn "failed to gcore $pid: $prog $cont $kpath"
+ fi
+
+ kill -ABRT $pid
+ fg %1
+
+ #
+ # Since we have the pid, go through and check this now.
+ #
+ if $core_checker $core_tmpdir/*.kernel.$c.$pid $c; then
+ printf "TEST PASSED: kernel %s %s\n" "$pbase" "$c"
+ else
+ warn "checker failed for kernel $c"
+ fi
+
+ if $core_checker $core_tmpdir/*.gcore.$c.$pid $c; then
+ printf "TEST PASSED: gcore %s %s\n" "$pbase" "$c"
+ else
+ warn "checker failed for gcore of $c"
+ fi
+}
+
+if [[ ! -x "$core_dumper32" || ! -x "$core_dumper64" || \
+ ! -f "$core_checker" ]]; then
+ warn "missing expected files"
+ exit $core_exit
+fi
+
+if ! mkdir "$core_tmpdir"; then
+ warn "failed to create temporary directory: $core_tmpdir"
+ exit $core_exit
+fi
+
+for c in $core_contents; do
+ kpattern="$core_tmpdir/%f.kernel.$c.%p"
+ gpattern="$core_tmpdir/%f.gcore.$c"
+
+ core_dump_one "$core_dumper32" "$c" "$kpattern" "$gpattern"
+ core_dump_one "$core_dumper64" "$c" "$kpattern" "$gpattern"
+
+done
+
+if (( core_exit == 0 )); then
+ printf "All tests passed successfully\n"
+fi
+
+rm -rf $core_tmpdir
+exit $core_exit
diff --git a/usr/src/test/os-tests/tests/cores/secmapper/Makefile b/usr/src/test/os-tests/tests/cores/secmapper/Makefile
new file mode 100644
index 0000000000..84a28a56b8
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/secmapper/Makefile
@@ -0,0 +1,48 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2021 Oxide Computer Company
+#
+
+PROG = secmapper
+OBJS = secmapper.o
+
+#
+# These are so the common makefile targets will clean things up.
+#
+ALLOBJS = $(OBJS)
+PROGS64 = $(PROG)
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/cmd/Makefile.cmd.64
+include ../Makefile.com
+
+ROOTOPTPROGS = $(PROG:%=$(ROOTOPTCORE)/%)
+
+LDLIBS += -lproc -lelf
+CSTD = $(GNU_C99)
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) -o $(PROG) $(OBJS) $(LDLIBS)
+ $(POST_PROCESS)
+
+install: $(ROOTOPTPROGS)
+
+$(ROOTOPTPROGS): $(PROG)
+
+FRC:
+
+include ../Makefile.targ
diff --git a/usr/src/test/os-tests/tests/cores/secmapper/secmapper.c b/usr/src/test/os-tests/tests/cores/secmapper/secmapper.c
new file mode 100644
index 0000000000..87800a5352
--- /dev/null
+++ b/usr/src/test/os-tests/tests/cores/secmapper/secmapper.c
@@ -0,0 +1,434 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2021 Oxide Computer Company
+ */
+
+/*
+ * Check that a given core dump generated as part of our test framework has the
+ * sections that we'd expect. We have here the dumper binary. In that, we expect
+ * to find the following libraries and sections:
+ *
+ * a.out: symtab, ctf, .debug_* (dwarf)
+ * ld.so.1: symtab
+ * libc.so: symtab, ctf
+ * libproc.so: symtab, ctf
+ * libdumper.so: symtab, ctf, .debug_* (dwarf)
+ *
+ * Note, there will also be additional libraries and things here can change over
+ * time (e.g. deps of libproc, etc.), but we try to ignore them generally
+ * speaking if we can know enough to do so.
+ */
+
+#include <err.h>
+#include <stdlib.h>
+#include <libproc.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <limits.h>
+#include <string.h>
+#include <libgen.h>
+
+typedef enum {
+ SECMAP_CTF,
+ SECMAP_SYMTAB,
+ SECMAP_DEBUG,
+ SECMAP_MAX
+} secmap_type_t;
+
+typedef struct secmap_data {
+ core_content_t sd_content;
+ const char *sd_name;
+} secmap_data_t;
+
+secmap_data_t secmap_data[SECMAP_MAX] = {
+ { CC_CONTENT_CTF, ".SUNW_ctf" },
+ { CC_CONTENT_SYMTAB, ".symtab" },
+ { CC_CONTENT_DEBUG, ".debug_" }
+};
+
+typedef struct {
+ uint64_t sm_addr;
+ char sm_obj[PATH_MAX];
+ size_t sm_nfound[SECMAP_MAX];
+ Elf *sm_elf;
+ GElf_Ehdr sm_ehdr;
+ boolean_t sm_ctf;
+ boolean_t sm_debug;
+ boolean_t sm_symtab;
+} secmap_t;
+
+static secmap_t *secmaps;
+static size_t secmap_count;
+static core_content_t secmap_content;
+
+static int secmap_exit = EXIT_SUCCESS;
+
+static void
+secmap_fail(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+ secmap_exit = EXIT_FAILURE;
+}
+
+
+static void
+check_content(core_content_t content, struct ps_prochandle *Pr)
+{
+ secmap_content = Pcontent(Pr);
+
+ if (secmap_content == CC_CONTENT_INVALID) {
+ secmap_fail("TEST FAILED: failed to get core content");
+ return;
+ }
+
+ if (secmap_content != content) {
+ secmap_fail("TEST FAILED: core file contains different "
+ "content than expected, found 0x%x, expected 0x%x",
+ secmap_content, content);
+ }
+}
+
+static secmap_t *
+secmap_find(uint64_t addr)
+{
+ for (size_t i = 0; i < secmap_count; i++) {
+ if (secmaps[i].sm_addr == addr) {
+ return (&secmaps[i]);
+ }
+ }
+
+ return (NULL);
+}
+
+static void
+secmap_matches_content(secmap_type_t type)
+{
+ boolean_t exist = (secmap_data[type].sd_content & secmap_content) != 0;
+ boolean_t found = B_FALSE;
+
+ /*
+ * Dumping CTF data implies that some symbol tables will exist for CTF.
+ */
+ if (type == SECMAP_SYMTAB && (secmap_content & CC_CONTENT_CTF) != 0) {
+ exist = B_TRUE;
+ }
+
+ for (size_t i = 0; i < secmap_count; i++) {
+ if (secmaps[i].sm_nfound[type] != 0) {
+ found = B_TRUE;
+ }
+ }
+
+ if (exist != found) {
+ secmap_fail("content type mismatch for %s: expected %s, but "
+ "found %s", secmap_data[type].sd_name,
+ exist ? "some" : "none",
+ found ? "some" : "none");
+ }
+}
+
+static secmap_t *
+secmap_alloc(struct ps_prochandle *Pr, uint64_t addr)
+{
+ int fd;
+ secmap_t *sm;
+ char *base;
+
+ sm = recallocarray(secmaps, secmap_count, secmap_count + 1,
+ sizeof (secmap_t));
+ if (sm == NULL) {
+ err(EXIT_FAILURE, "TEST FAILED: failed to allocate memory for "
+ "secmap %zu", secmap_count + 1);
+ }
+
+ secmaps = sm;
+ sm = &secmaps[secmap_count];
+ sm->sm_addr = addr;
+ secmap_count++;
+
+ /*
+ * We also have some tests that we don't expect to have anything here
+ * because we only include the relevant sections. Experimentally, we
+ * know that libproc needs both anon and data mappings for this to work.
+ * So if we don't have both, then we'll not warn on that.
+ */
+ if (Pobjname(Pr, addr, sm->sm_obj, sizeof (sm->sm_obj)) == NULL) {
+ core_content_t need = CC_CONTENT_ANON | CC_CONTENT_DATA;
+
+ if ((secmap_content & need) == need) {
+ secmap_fail("TEST FAILURE: object at address 0x%lx "
+ "has no name", addr);
+ }
+
+ return (sm);
+ }
+
+ /*
+ * Since we have a name, we should be able to open this elf object and
+ * identify it as well.
+ */
+ fd = open(sm->sm_obj, O_RDONLY);
+ if (fd < 0) {
+ err(EXIT_FAILURE, "failed to open object %s", sm->sm_obj);
+ }
+
+ sm->sm_elf = elf_begin(fd, ELF_C_READ, NULL);
+ if (sm->sm_elf == NULL) {
+ err(EXIT_FAILURE, "failed to find open elf object %s: %s",
+ sm->sm_obj, elf_errmsg(elf_errno()));
+ }
+
+ if (gelf_getehdr(sm->sm_elf, &sm->sm_ehdr) == NULL) {
+ err(EXIT_FAILURE, "failed to get ehdr for %s: %s",
+ sm->sm_obj, elf_errmsg(elf_errno()));
+ }
+
+ base = basename(sm->sm_obj);
+ if (strcmp(base, "dumper.32") == 0 || strcmp(base, "dumper.64") == 0) {
+ sm->sm_debug = sm->sm_symtab = sm->sm_ctf = B_TRUE;
+ } else if (strcmp(base, "libc.so.1") == 0) {
+ sm->sm_symtab = sm->sm_ctf = B_TRUE;
+ } else if (strcmp(base, "ld.so.1") == 0) {
+ sm->sm_symtab = B_TRUE;
+ } else if (strcmp(base, "libproc.so.1") == 0) {
+ sm->sm_symtab = sm->sm_ctf = B_TRUE;
+ } else if (strcmp(base, "libdumper.so.1") == 0) {
+ sm->sm_debug = sm->sm_symtab = sm->sm_ctf = B_TRUE;
+ } else {
+ sm->sm_symtab = B_TRUE;
+ }
+
+ return (sm);
+}
+
+static void
+secmap_data_cmp(secmap_t *sm, const char *sname, Elf_Scn *scn, GElf_Shdr *shdr)
+{
+ for (Elf_Scn *comp_scn = elf_nextscn(sm->sm_elf, NULL);
+ comp_scn != NULL; comp_scn = elf_nextscn(sm->sm_elf, comp_scn)) {
+ GElf_Shdr comp_shdr;
+ const char *comp_name;
+ Elf_Data *src_data, *comp_data;
+
+ if (gelf_getshdr(comp_scn, &comp_shdr) == NULL) {
+ secmap_fail("failed to load section header from %s "
+ "during data comparison", sm->sm_obj);
+ return;
+ }
+
+ comp_name = elf_strptr(sm->sm_elf, sm->sm_ehdr.e_shstrndx,
+ comp_shdr.sh_name);
+ if (comp_name == NULL) {
+ secmap_fail("failed to load section name from %s "
+ "with index %lu", sm->sm_obj, comp_shdr.sh_name);
+ return;
+ }
+
+ if (strcmp(comp_name, sname) != 0)
+ continue;
+
+ if (comp_shdr.sh_type != shdr->sh_type ||
+ comp_shdr.sh_addralign != shdr->sh_addralign ||
+ comp_shdr.sh_size != shdr->sh_size ||
+ comp_shdr.sh_entsize != shdr->sh_entsize) {
+ continue;
+ }
+
+ if ((src_data = elf_getdata(scn, NULL)) == NULL) {
+ secmap_fail("failed to load section data from "
+ "source to compare to %s %s", sm->sm_obj, sname);
+ return;
+ }
+
+ if ((comp_data = elf_getdata(comp_scn, NULL)) == NULL) {
+ secmap_fail("failed to load section data from "
+ "source to compare to %s %s", sm->sm_obj, sname);
+ return;
+ }
+
+ if (comp_data->d_size != src_data->d_size) {
+ secmap_fail("data size mismatch for %s: %s, core: "
+ "%zu, file: %zu", sm->sm_obj, sname,
+ src_data->d_size, comp_data->d_size);
+ return;
+ }
+
+ if (memcmp(comp_data->d_buf, src_data->d_buf,
+ comp_data->d_size) != 0) {
+ secmap_fail("data mismatch between core and source "
+ "in %s: %s", sm->sm_obj, sname);
+ return;
+ }
+
+ return;
+ }
+
+ secmap_fail("failed to find matching section for %s in %s",
+ sname, sm->sm_obj);
+}
+
+static void
+secmap_file_check(secmap_t *sm)
+{
+ if (sm->sm_ctf && (secmap_content & CC_CONTENT_CTF) != 0 &&
+ sm->sm_nfound[SECMAP_CTF] == 0) {
+ secmap_fail("expected object %s to have CTF, but it doesn't",
+ sm->sm_obj);
+ }
+
+ if (sm->sm_symtab && (secmap_content & CC_CONTENT_SYMTAB) != 0 &&
+ sm->sm_nfound[SECMAP_SYMTAB] == 0) {
+ secmap_fail("expected object %s to have a symbol table, "
+ "but it doesn't", sm->sm_obj);
+ }
+
+ if (sm->sm_debug && (secmap_content & CC_CONTENT_DEBUG) != 0 &&
+ sm->sm_nfound[SECMAP_DEBUG] == 0) {
+ secmap_fail("expected object %s to have debug sections, "
+ "but it doesn't", sm->sm_obj);
+ }
+}
+
+int
+main(int argc, char *argv[])
+{
+ core_content_t content;
+ struct ps_prochandle *Pr;
+ int perr, fd;
+ Elf *elf;
+ Elf_Scn *scn;
+ GElf_Ehdr ehdr;
+
+ if (argc != 3) {
+ warnx("missing required file and core content");
+ (void) fprintf(stderr, "Usage: secmapper file content\n");
+ exit(EXIT_FAILURE);
+ }
+
+ if (elf_version(EV_CURRENT) == EV_NONE) {
+ errx(EXIT_FAILURE, "failed to init libelf");
+ }
+
+ Pr = Pgrab_core(argv[1], NULL, PGRAB_RDONLY, &perr);
+ if (Pr == NULL) {
+ errx(EXIT_FAILURE, "failed to open %s: %s", argv[1],
+ Pgrab_error(perr));
+ }
+
+ if ((fd = open(argv[1], O_RDONLY)) < 0) {
+ err(EXIT_FAILURE, "failed to open %s\n", argv[1]);
+ }
+
+ if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
+ errx(EXIT_FAILURE, "failed to open elf file %s: %s", argv[1],
+ elf_errmsg(elf_errno()));
+ }
+
+ if (proc_str2content(argv[2], &content) != 0) {
+ err(EXIT_FAILURE, "failed to parse content %s", argv[2]);
+ }
+
+ if (gelf_getehdr(elf, &ehdr) == NULL) {
+ errx(EXIT_FAILURE, "failed to get edr: %s",
+ elf_errmsg(elf_errno()));
+ }
+
+ /*
+ * Before we go futher, make sure that we have the content in this file
+ * that we expect.
+ */
+ check_content(content, Pr);
+
+ for (scn = elf_nextscn(elf, NULL); scn != NULL;
+ scn = elf_nextscn(elf, scn)) {
+ const char *sname;
+ GElf_Shdr shdr;
+ size_t index;
+ secmap_t *secmap;
+
+ index = elf_ndxscn(scn);
+ if (gelf_getshdr(scn, &shdr) == NULL) {
+ errx(EXIT_FAILURE, "failed to get section header for "
+ "shdr %zu: %s", index, elf_errmsg(elf_errno()));
+ }
+
+ /*
+ * Skip the strtab.
+ */
+ if (shdr.sh_type == SHT_STRTAB) {
+ continue;
+ }
+
+ sname = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
+ if (sname == NULL) {
+ secmap_fail("TEST FAILURE: string name missing for "
+ "shdr %zu", index);
+ continue;
+ }
+
+ /*
+ * Find or cons up a new secmap for this object.
+ */
+ secmap = secmap_find(shdr.sh_addr);
+ if (secmap == NULL) {
+ secmap = secmap_alloc(Pr, shdr.sh_addr);
+ }
+
+ if (strcmp(sname, ".symtab") == 0) {
+ secmap->sm_nfound[SECMAP_SYMTAB]++;
+ } else if (strcmp(sname, ".SUNW_ctf") == 0) {
+ secmap->sm_nfound[SECMAP_CTF]++;
+ } else if (strncmp(sname, ".debug_", strlen(".debug_")) == 0) {
+ secmap->sm_nfound[SECMAP_DEBUG]++;
+ } else {
+ continue;
+ }
+
+ /*
+ * For one of our three primary sections, make sure that the
+ * data that is in the core file that we find in it actually
+ * matches the underlying object. That is, if the secmap
+ * actually has something here.
+ */
+ if (secmap->sm_elf != NULL) {
+ secmap_data_cmp(secmap, sname, scn, &shdr);
+ }
+ }
+
+ /*
+ * Now that we have iterated over all of these sections, check and make
+ * sure certain things are true of them. In particular, go through some
+ * of the various types of data and make sure it exists at all or
+ * doesn't based on our core content.
+ */
+ secmap_matches_content(SECMAP_CTF);
+ secmap_matches_content(SECMAP_SYMTAB);
+ secmap_matches_content(SECMAP_DEBUG);
+
+ /*
+ * Finally, if we have enough information to know that we've found
+ * a file that we know it should at least have a given type of data,
+ * check for it. Here, it is OK for data to be present we don't expect
+ * (assuming the core content allows it). This makes this test less
+ * prone to broader changes in the system.
+ */
+ for (size_t i = 0; i < secmap_count; i++) {
+ secmap_file_check(&secmaps[i]);
+ }
+
+ return (secmap_exit);
+}
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 7d32a690da..d83ae3c929 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -1081,7 +1081,7 @@ RTLS_OBJS += rtls.o
#
AOUTEXEC_OBJS +=aout.o
-ELFEXEC_OBJS += elf.o elf_notes.o old_notes.o
+ELFEXEC_OBJS += elf.o elf_notes.o old_notes.o core_shstrtab.o
INTPEXEC_OBJS +=intp.o
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index 5c5f783c0c..943f5ebc82 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -52,6 +52,10 @@ $(OBJS_DIR)/zmod.o := CPPFLAGS += -I$(SRC)/contrib/zlib
$(OBJS_DIR)/zmod_subr.o := CPPFLAGS += -I$(SRC)/contrib/zlib
$(OBJS_DIR)/lz4.o := CPPFLAGS += -I$(COMMONBASE)/lz4
+$(OBJS_DIR)/%.o: $(COMMONBASE)/core/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(COMMONBASE)/crypto/aes/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
diff --git a/usr/src/uts/common/exec/elf/elf.c b/usr/src/uts/common/exec/elf/elf.c
index 986a2d0abd..5e401b91df 100644
--- a/usr/src/uts/common/exec/elf/elf.c
+++ b/usr/src/uts/common/exec/elf/elf.c
@@ -69,6 +69,8 @@
#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>
@@ -108,71 +110,6 @@ 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)
{
@@ -1974,7 +1911,9 @@ elf_copy_scn(elf_core_ctx_t *ctx, const Shdr *src, vnode_t *src_vp, Shdr *dst)
/*
* Walk sections for a given ELF object, counting (or copying) those of
- * interest (CTF, symtab, strtab).
+ * 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,
@@ -1992,7 +1931,8 @@ elf_process_obj_scns(elf_core_ctx_t *ctx, vnode_t *mvp, caddr_t saddr,
size_t shsize, shstrsize;
char *shstrbase;
- if ((content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)) == 0) {
+ if ((content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB | CC_CONTENT_DEBUG))
+ == 0) {
return (0);
}
@@ -2030,6 +1970,50 @@ elf_process_obj_scns(elf_core_ctx_t *ctx, vnode_t *mvp, caddr_t saddr,
(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)
+ continue;
+
+ elf_ctx_resize_scratch(ctx, shdr->sh_size);
+ if (!shstrtab_ndx(shstr, 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;
}
@@ -2049,7 +2033,8 @@ elf_process_obj_scns(elf_core_ctx_t *ctx, vnode_t *mvp, caddr_t saddr,
symtab = symchk;
strtab = strchk;
- if (symtab != NULL && ctf != NULL) {
+ if (symtab != NULL && ctf != NULL &&
+ (content & CC_CONTENT_DEBUG) == 0) {
/* No other shdrs are of interest at this point */
break;
}
@@ -2059,6 +2044,7 @@ elf_process_obj_scns(elf_core_ctx_t *ctx, vnode_t *mvp, caddr_t saddr,
count += 1;
if (symtab != NULL)
count += 2;
+
if (v == NULL || count == 0 || count > remain) {
count = MIN(count, remain);
goto done;
@@ -2068,7 +2054,11 @@ elf_process_obj_scns(elf_core_ctx_t *ctx, vnode_t *mvp, caddr_t saddr,
if (ctf != NULL) {
elf_ctx_resize_scratch(ctx, ctf->sh_size);
- v[idx].sh_name = shstrtab_ndx(shstrtab, STR_CTF);
+ if (!shstrtab_ndx(shstr, 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;
@@ -2164,7 +2154,8 @@ elf_process_scns(elf_core_ctx_t *ctx, Shdr *v, uint_t nv, uint_t *nshdrsp)
if (v != NULL) {
ASSERT(nv != 0);
- shstrtab_init(&shstrtab);
+ if (!shstrtab_init(&shstrtab))
+ return (ENOMEM);
remain = nv;
} else {
ASSERT(nv == 0);
@@ -2212,6 +2203,10 @@ elf_process_scns(elf_core_ctx_t *ctx, Shdr *v, uint_t nv, uint_t *nshdrsp)
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);
@@ -2228,6 +2223,7 @@ elf_process_scns(elf_core_ctx_t *ctx, Shdr *v, uint_t nv, uint_t *nshdrsp)
/* Include room for the shrstrtab at the end */
*nshdrsp = idx + 1;
}
+ /* No need to free up shstrtab so we can just return. */
return (0);
}
@@ -2235,10 +2231,15 @@ elf_process_scns(elf_core_ctx_t *ctx, Shdr *v, uint_t nv, uint_t *nshdrsp)
cmn_err(CE_WARN, "elfcore: core dump failed for "
"process %d; address space is changing",
ctx->ecc_p->p_pid);
- return (EIO);
+ error = EIO;
+ goto done;
}
- v[idx].sh_name = shstrtab_ndx(&shstrtab, STR_SHSTRTAB);
+ 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;
@@ -2255,6 +2256,9 @@ elf_process_scns(elf_core_ctx_t *ctx, Shdr *v, uint_t nv, uint_t *nshdrsp)
ctx->ecc_doffset += v[idx].sh_size;
}
+done:
+ if (v != NULL)
+ shstrtab_fini(&shstrtab);
return (error);
}
@@ -2302,9 +2306,8 @@ top:
* Count the number of section headers we're going to need.
*/
nshdrs = 0;
- if (content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB)) {
+ if (content & (CC_CONTENT_CTF | CC_CONTENT_SYMTAB | CC_CONTENT_DEBUG))
VERIFY0(elf_process_scns(&ctx, NULL, 0, &nshdrs));
- }
AS_LOCK_EXIT(as);
/*
@@ -2317,10 +2320,11 @@ top:
}
/*
- * 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.
+ * 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);
diff --git a/usr/src/uts/common/sys/corectl.h b/usr/src/uts/common/sys/corectl.h
index 8ebc78e9e9..058d583dbc 100644
--- a/usr/src/uts/common/sys/corectl.h
+++ b/usr/src/uts/common/sys/corectl.h
@@ -87,8 +87,9 @@ extern "C" {
#define CC_CONTENT_CTF 0x0800ULL /* CTF data */
#define CC_CONTENT_SYMTAB 0x1000ULL /* symbol table */
+#define CC_CONTENT_DEBUG 0x2000ULL /* debug information */
-#define CC_CONTENT_ALL 0x1fffULL
+#define CC_CONTENT_ALL 0x3fffULL
#define CC_CONTENT_NONE 0ULL
#define CC_CONTENT_DEFAULT (CC_CONTENT_STACK | CC_CONTENT_HEAP | \
CC_CONTENT_ISM | CC_CONTENT_DISM | CC_CONTENT_SHM | \
diff --git a/usr/src/uts/intel/elfexec/Makefile b/usr/src/uts/intel/elfexec/Makefile
index 463fe1bc50..a0769172ea 100644
--- a/usr/src/uts/intel/elfexec/Makefile
+++ b/usr/src/uts/intel/elfexec/Makefile
@@ -59,7 +59,7 @@ include $(UTSBASE)/intel/Makefile.intel
ALL_TARGET = $(BINARY)
INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-INC_PATH += -I$(UTSBASE)/intel/ia32
+INC_PATH += -I$(UTSBASE)/intel/ia32 -I$(SRC)/common/core
#
# For now, disable these warnings; maintainers should endeavor
diff --git a/usr/src/uts/sparc/elfexec/Makefile b/usr/src/uts/sparc/elfexec/Makefile
index 1cc0fe03bc..04f3f57a03 100644
--- a/usr/src/uts/sparc/elfexec/Makefile
+++ b/usr/src/uts/sparc/elfexec/Makefile
@@ -56,6 +56,7 @@ include $(UTSBASE)/sparc/Makefile.sparc
#
ALL_TARGET = $(BINARY)
INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+INC_PATH += -I$(SRC)/common/core
#
# Overrides.