summaryrefslogtreecommitdiff
path: root/usr/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib')
-rw-r--r--usr/src/lib/libproc/Makefile.com7
-rw-r--r--usr/src/lib/libproc/common/Pgcore.c222
2 files changed, 150 insertions, 79 deletions
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]);