1*8e458de0SRobert Mustacchi /*
2*8e458de0SRobert Mustacchi  * This file and its contents are supplied under the terms of the
3*8e458de0SRobert Mustacchi  * Common Development and Distribution License ("CDDL"), version 1.0.
4*8e458de0SRobert Mustacchi  * You may only use this file in accordance with the terms of version
5*8e458de0SRobert Mustacchi  * 1.0 of the CDDL.
6*8e458de0SRobert Mustacchi  *
7*8e458de0SRobert Mustacchi  * A full copy of the text of the CDDL should have accompanied this
8*8e458de0SRobert Mustacchi  * source.  A copy of the CDDL is also available via the Internet at
9*8e458de0SRobert Mustacchi  * http://www.illumos.org/license/CDDL.
10*8e458de0SRobert Mustacchi  */
11*8e458de0SRobert Mustacchi 
12*8e458de0SRobert Mustacchi /*
13*8e458de0SRobert Mustacchi  * Copyright 2021 Oxide Computer Company
14*8e458de0SRobert Mustacchi  */
15*8e458de0SRobert Mustacchi 
16*8e458de0SRobert Mustacchi /*
17*8e458de0SRobert Mustacchi  * Check that a given core dump generated as part of our test framework has the
18*8e458de0SRobert Mustacchi  * sections that we'd expect. We have here the dumper binary. In that, we expect
19*8e458de0SRobert Mustacchi  * to find the following libraries and sections:
20*8e458de0SRobert Mustacchi  *
21*8e458de0SRobert Mustacchi  *   a.out:		symtab, ctf, .debug_* (dwarf)
22*8e458de0SRobert Mustacchi  *   ld.so.1:		symtab
23*8e458de0SRobert Mustacchi  *   libc.so:		symtab, ctf
24*8e458de0SRobert Mustacchi  *   libproc.so:	symtab, ctf
25*8e458de0SRobert Mustacchi  *   libdumper.so:	symtab, ctf, .debug_* (dwarf)
26*8e458de0SRobert Mustacchi  *
27*8e458de0SRobert Mustacchi  * Note, there will also be additional libraries and things here can change over
28*8e458de0SRobert Mustacchi  * time (e.g. deps of libproc, etc.), but we try to ignore them generally
29*8e458de0SRobert Mustacchi  * speaking if we can know enough to do so.
30*8e458de0SRobert Mustacchi  */
31*8e458de0SRobert Mustacchi 
32*8e458de0SRobert Mustacchi #include <err.h>
33*8e458de0SRobert Mustacchi #include <stdlib.h>
34*8e458de0SRobert Mustacchi #include <libproc.h>
35*8e458de0SRobert Mustacchi #include <gelf.h>
36*8e458de0SRobert Mustacchi #include <libelf.h>
37*8e458de0SRobert Mustacchi #include <limits.h>
38*8e458de0SRobert Mustacchi #include <string.h>
39*8e458de0SRobert Mustacchi #include <libgen.h>
40*8e458de0SRobert Mustacchi 
41*8e458de0SRobert Mustacchi typedef enum {
42*8e458de0SRobert Mustacchi 	SECMAP_CTF,
43*8e458de0SRobert Mustacchi 	SECMAP_SYMTAB,
44*8e458de0SRobert Mustacchi 	SECMAP_DEBUG,
45*8e458de0SRobert Mustacchi 	SECMAP_MAX
46*8e458de0SRobert Mustacchi } secmap_type_t;
47*8e458de0SRobert Mustacchi 
48*8e458de0SRobert Mustacchi typedef struct secmap_data {
49*8e458de0SRobert Mustacchi 	core_content_t	sd_content;
50*8e458de0SRobert Mustacchi 	const char	*sd_name;
51*8e458de0SRobert Mustacchi } secmap_data_t;
52*8e458de0SRobert Mustacchi 
53*8e458de0SRobert Mustacchi secmap_data_t secmap_data[SECMAP_MAX] = {
54*8e458de0SRobert Mustacchi 	{ CC_CONTENT_CTF, ".SUNW_ctf" },
55*8e458de0SRobert Mustacchi 	{ CC_CONTENT_SYMTAB, ".symtab" },
56*8e458de0SRobert Mustacchi 	{ CC_CONTENT_DEBUG, ".debug_" }
57*8e458de0SRobert Mustacchi };
58*8e458de0SRobert Mustacchi 
59*8e458de0SRobert Mustacchi typedef struct {
60*8e458de0SRobert Mustacchi 	uint64_t	sm_addr;
61*8e458de0SRobert Mustacchi 	char		sm_obj[PATH_MAX];
62*8e458de0SRobert Mustacchi 	size_t		sm_nfound[SECMAP_MAX];
63*8e458de0SRobert Mustacchi 	Elf		*sm_elf;
64*8e458de0SRobert Mustacchi 	GElf_Ehdr	sm_ehdr;
65*8e458de0SRobert Mustacchi 	boolean_t	sm_ctf;
66*8e458de0SRobert Mustacchi 	boolean_t	sm_debug;
67*8e458de0SRobert Mustacchi 	boolean_t	sm_symtab;
68*8e458de0SRobert Mustacchi } secmap_t;
69*8e458de0SRobert Mustacchi 
70*8e458de0SRobert Mustacchi static secmap_t *secmaps;
71*8e458de0SRobert Mustacchi static size_t secmap_count;
72*8e458de0SRobert Mustacchi static core_content_t secmap_content;
73*8e458de0SRobert Mustacchi 
74*8e458de0SRobert Mustacchi static int secmap_exit = EXIT_SUCCESS;
75*8e458de0SRobert Mustacchi 
76*8e458de0SRobert Mustacchi static void
secmap_fail(const char * fmt,...)77*8e458de0SRobert Mustacchi secmap_fail(const char *fmt, ...)
78*8e458de0SRobert Mustacchi {
79*8e458de0SRobert Mustacchi 	va_list ap;
80*8e458de0SRobert Mustacchi 
81*8e458de0SRobert Mustacchi 	va_start(ap, fmt);
82*8e458de0SRobert Mustacchi 	vwarnx(fmt, ap);
83*8e458de0SRobert Mustacchi 	va_end(ap);
84*8e458de0SRobert Mustacchi 	secmap_exit = EXIT_FAILURE;
85*8e458de0SRobert Mustacchi }
86*8e458de0SRobert Mustacchi 
87*8e458de0SRobert Mustacchi 
88*8e458de0SRobert Mustacchi static void
check_content(core_content_t content,struct ps_prochandle * Pr)89*8e458de0SRobert Mustacchi check_content(core_content_t content, struct ps_prochandle *Pr)
90*8e458de0SRobert Mustacchi {
91*8e458de0SRobert Mustacchi 	secmap_content = Pcontent(Pr);
92*8e458de0SRobert Mustacchi 
93*8e458de0SRobert Mustacchi 	if (secmap_content == CC_CONTENT_INVALID) {
94*8e458de0SRobert Mustacchi 		secmap_fail("TEST FAILED: failed to get core content");
95*8e458de0SRobert Mustacchi 		return;
96*8e458de0SRobert Mustacchi 	}
97*8e458de0SRobert Mustacchi 
98*8e458de0SRobert Mustacchi 	if (secmap_content != content) {
99*8e458de0SRobert Mustacchi 		secmap_fail("TEST FAILED: core file contains different "
100*8e458de0SRobert Mustacchi 		    "content than expected, found 0x%x, expected 0x%x",
101*8e458de0SRobert Mustacchi 		    secmap_content, content);
102*8e458de0SRobert Mustacchi 	}
103*8e458de0SRobert Mustacchi }
104*8e458de0SRobert Mustacchi 
105*8e458de0SRobert Mustacchi static secmap_t *
secmap_find(uint64_t addr)106*8e458de0SRobert Mustacchi secmap_find(uint64_t addr)
107*8e458de0SRobert Mustacchi {
108*8e458de0SRobert Mustacchi 	for (size_t i = 0; i < secmap_count; i++) {
109*8e458de0SRobert Mustacchi 		if (secmaps[i].sm_addr == addr) {
110*8e458de0SRobert Mustacchi 			return (&secmaps[i]);
111*8e458de0SRobert Mustacchi 		}
112*8e458de0SRobert Mustacchi 	}
113*8e458de0SRobert Mustacchi 
114*8e458de0SRobert Mustacchi 	return (NULL);
115*8e458de0SRobert Mustacchi }
116*8e458de0SRobert Mustacchi 
117*8e458de0SRobert Mustacchi static void
secmap_matches_content(secmap_type_t type)118*8e458de0SRobert Mustacchi secmap_matches_content(secmap_type_t type)
119*8e458de0SRobert Mustacchi {
120*8e458de0SRobert Mustacchi 	boolean_t exist = (secmap_data[type].sd_content & secmap_content) != 0;
121*8e458de0SRobert Mustacchi 	boolean_t found = B_FALSE;
122*8e458de0SRobert Mustacchi 
123*8e458de0SRobert Mustacchi 	/*
124*8e458de0SRobert Mustacchi 	 * Dumping CTF data implies that some symbol tables will exist for CTF.
125*8e458de0SRobert Mustacchi 	 */
126*8e458de0SRobert Mustacchi 	if (type == SECMAP_SYMTAB && (secmap_content & CC_CONTENT_CTF) != 0) {
127*8e458de0SRobert Mustacchi 		exist = B_TRUE;
128*8e458de0SRobert Mustacchi 	}
129*8e458de0SRobert Mustacchi 
130*8e458de0SRobert Mustacchi 	for (size_t i = 0; i < secmap_count; i++) {
131*8e458de0SRobert Mustacchi 		if (secmaps[i].sm_nfound[type] != 0) {
132*8e458de0SRobert Mustacchi 			found = B_TRUE;
133*8e458de0SRobert Mustacchi 		}
134*8e458de0SRobert Mustacchi 	}
135*8e458de0SRobert Mustacchi 
136*8e458de0SRobert Mustacchi 	if (exist != found) {
137*8e458de0SRobert Mustacchi 		secmap_fail("content type mismatch for %s: expected %s, but "
138*8e458de0SRobert Mustacchi 		    "found %s", secmap_data[type].sd_name,
139*8e458de0SRobert Mustacchi 		    exist ? "some" : "none",
140*8e458de0SRobert Mustacchi 		    found ? "some" : "none");
141*8e458de0SRobert Mustacchi 	}
142*8e458de0SRobert Mustacchi }
143*8e458de0SRobert Mustacchi 
144*8e458de0SRobert Mustacchi static secmap_t *
secmap_alloc(struct ps_prochandle * Pr,uint64_t addr)145*8e458de0SRobert Mustacchi secmap_alloc(struct ps_prochandle *Pr, uint64_t addr)
146*8e458de0SRobert Mustacchi {
147*8e458de0SRobert Mustacchi 	int fd;
148*8e458de0SRobert Mustacchi 	secmap_t *sm;
149*8e458de0SRobert Mustacchi 	char *base;
150*8e458de0SRobert Mustacchi 
151*8e458de0SRobert Mustacchi 	sm = recallocarray(secmaps, secmap_count, secmap_count + 1,
152*8e458de0SRobert Mustacchi 	    sizeof (secmap_t));
153*8e458de0SRobert Mustacchi 	if (sm == NULL) {
154*8e458de0SRobert Mustacchi 		err(EXIT_FAILURE, "TEST FAILED: failed to allocate memory for "
155*8e458de0SRobert Mustacchi 		    "secmap %zu", secmap_count + 1);
156*8e458de0SRobert Mustacchi 	}
157*8e458de0SRobert Mustacchi 
158*8e458de0SRobert Mustacchi 	secmaps = sm;
159*8e458de0SRobert Mustacchi 	sm = &secmaps[secmap_count];
160*8e458de0SRobert Mustacchi 	sm->sm_addr = addr;
161*8e458de0SRobert Mustacchi 	secmap_count++;
162*8e458de0SRobert Mustacchi 
163*8e458de0SRobert Mustacchi 	/*
164*8e458de0SRobert Mustacchi 	 * We also have some tests that we don't expect to have anything here
165*8e458de0SRobert Mustacchi 	 * because we only include the relevant sections. Experimentally, we
166*8e458de0SRobert Mustacchi 	 * know that libproc needs both anon and data mappings for this to work.
167*8e458de0SRobert Mustacchi 	 * So if we don't have both, then we'll not warn on that.
168*8e458de0SRobert Mustacchi 	 */
169*8e458de0SRobert Mustacchi 	if (Pobjname(Pr, addr, sm->sm_obj, sizeof (sm->sm_obj)) == NULL) {
170*8e458de0SRobert Mustacchi 		core_content_t need = CC_CONTENT_ANON | CC_CONTENT_DATA;
171*8e458de0SRobert Mustacchi 
172*8e458de0SRobert Mustacchi 		if ((secmap_content & need) == need) {
173*8e458de0SRobert Mustacchi 			secmap_fail("TEST FAILURE: object at address 0x%lx "
174*8e458de0SRobert Mustacchi 			    "has no name", addr);
175*8e458de0SRobert Mustacchi 		}
176*8e458de0SRobert Mustacchi 
177*8e458de0SRobert Mustacchi 		return (sm);
178*8e458de0SRobert Mustacchi 	}
179*8e458de0SRobert Mustacchi 
180*8e458de0SRobert Mustacchi 	/*
181*8e458de0SRobert Mustacchi 	 * Since we have a name, we should be able to open this elf object and
182*8e458de0SRobert Mustacchi 	 * identify it as well.
183*8e458de0SRobert Mustacchi 	 */
184*8e458de0SRobert Mustacchi 	fd = open(sm->sm_obj, O_RDONLY);
185*8e458de0SRobert Mustacchi 	if (fd < 0) {
186*8e458de0SRobert Mustacchi 		err(EXIT_FAILURE, "failed to open object %s", sm->sm_obj);
187*8e458de0SRobert Mustacchi 	}
188*8e458de0SRobert Mustacchi 
189*8e458de0SRobert Mustacchi 	sm->sm_elf = elf_begin(fd, ELF_C_READ, NULL);
190*8e458de0SRobert Mustacchi 	if (sm->sm_elf == NULL) {
191*8e458de0SRobert Mustacchi 		err(EXIT_FAILURE, "failed to find open elf object %s: %s",
192*8e458de0SRobert Mustacchi 		    sm->sm_obj, elf_errmsg(elf_errno()));
193*8e458de0SRobert Mustacchi 	}
194*8e458de0SRobert Mustacchi 
195*8e458de0SRobert Mustacchi 	if (gelf_getehdr(sm->sm_elf, &sm->sm_ehdr) == NULL) {
196*8e458de0SRobert Mustacchi 		err(EXIT_FAILURE, "failed to get ehdr for %s: %s",
197*8e458de0SRobert Mustacchi 		    sm->sm_obj, elf_errmsg(elf_errno()));
198*8e458de0SRobert Mustacchi 	}
199*8e458de0SRobert Mustacchi 
200*8e458de0SRobert Mustacchi 	base = basename(sm->sm_obj);
201*8e458de0SRobert Mustacchi 	if (strcmp(base, "dumper.32") == 0 || strcmp(base, "dumper.64") == 0) {
202*8e458de0SRobert Mustacchi 		sm->sm_debug = sm->sm_symtab = sm->sm_ctf = B_TRUE;
203*8e458de0SRobert Mustacchi 	} else if (strcmp(base, "libc.so.1") == 0) {
204*8e458de0SRobert Mustacchi 		sm->sm_symtab = sm->sm_ctf = B_TRUE;
205*8e458de0SRobert Mustacchi 	} else if (strcmp(base, "ld.so.1") == 0) {
206*8e458de0SRobert Mustacchi 		sm->sm_symtab = B_TRUE;
207*8e458de0SRobert Mustacchi 	} else if (strcmp(base, "libproc.so.1") == 0) {
208*8e458de0SRobert Mustacchi 		sm->sm_symtab = sm->sm_ctf = B_TRUE;
209*8e458de0SRobert Mustacchi 	} else if (strcmp(base,  "libdumper.so.1") == 0) {
210*8e458de0SRobert Mustacchi 		sm->sm_debug = sm->sm_symtab = sm->sm_ctf = B_TRUE;
211*8e458de0SRobert Mustacchi 	} else {
212*8e458de0SRobert Mustacchi 		sm->sm_symtab = B_TRUE;
213*8e458de0SRobert Mustacchi 	}
214*8e458de0SRobert Mustacchi 
215*8e458de0SRobert Mustacchi 	return (sm);
216*8e458de0SRobert Mustacchi }
217*8e458de0SRobert Mustacchi 
218*8e458de0SRobert Mustacchi static void
secmap_data_cmp(secmap_t * sm,const char * sname,Elf_Scn * scn,GElf_Shdr * shdr)219*8e458de0SRobert Mustacchi secmap_data_cmp(secmap_t *sm, const char *sname, Elf_Scn *scn, GElf_Shdr *shdr)
220*8e458de0SRobert Mustacchi {
221*8e458de0SRobert Mustacchi 	for (Elf_Scn *comp_scn = elf_nextscn(sm->sm_elf, NULL);
222*8e458de0SRobert Mustacchi 	    comp_scn != NULL; comp_scn = elf_nextscn(sm->sm_elf, comp_scn)) {
223*8e458de0SRobert Mustacchi 		GElf_Shdr comp_shdr;
224*8e458de0SRobert Mustacchi 		const char *comp_name;
225*8e458de0SRobert Mustacchi 		Elf_Data *src_data, *comp_data;
226*8e458de0SRobert Mustacchi 
227*8e458de0SRobert Mustacchi 		if (gelf_getshdr(comp_scn, &comp_shdr) == NULL) {
228*8e458de0SRobert Mustacchi 			secmap_fail("failed to load section header from %s "
229*8e458de0SRobert Mustacchi 			    "during data comparison", sm->sm_obj);
230*8e458de0SRobert Mustacchi 			return;
231*8e458de0SRobert Mustacchi 		}
232*8e458de0SRobert Mustacchi 
233*8e458de0SRobert Mustacchi 		comp_name = elf_strptr(sm->sm_elf, sm->sm_ehdr.e_shstrndx,
234*8e458de0SRobert Mustacchi 		    comp_shdr.sh_name);
235*8e458de0SRobert Mustacchi 		if (comp_name == NULL) {
236*8e458de0SRobert Mustacchi 			secmap_fail("failed to load section name from %s "
237*8e458de0SRobert Mustacchi 			    "with index %lu", sm->sm_obj, comp_shdr.sh_name);
238*8e458de0SRobert Mustacchi 			return;
239*8e458de0SRobert Mustacchi 		}
240*8e458de0SRobert Mustacchi 
241*8e458de0SRobert Mustacchi 		if (strcmp(comp_name, sname) != 0)
242*8e458de0SRobert Mustacchi 			continue;
243*8e458de0SRobert Mustacchi 
244*8e458de0SRobert Mustacchi 		if (comp_shdr.sh_type != shdr->sh_type ||
245*8e458de0SRobert Mustacchi 		    comp_shdr.sh_addralign != shdr->sh_addralign ||
246*8e458de0SRobert Mustacchi 		    comp_shdr.sh_size != shdr->sh_size ||
247*8e458de0SRobert Mustacchi 		    comp_shdr.sh_entsize != shdr->sh_entsize) {
248*8e458de0SRobert Mustacchi 			continue;
249*8e458de0SRobert Mustacchi 		}
250*8e458de0SRobert Mustacchi 
251*8e458de0SRobert Mustacchi 		if ((src_data = elf_getdata(scn, NULL)) == NULL) {
252*8e458de0SRobert Mustacchi 			secmap_fail("failed to load section data from "
253*8e458de0SRobert Mustacchi 			    "source to compare to %s %s", sm->sm_obj, sname);
254*8e458de0SRobert Mustacchi 			return;
255*8e458de0SRobert Mustacchi 		}
256*8e458de0SRobert Mustacchi 
257*8e458de0SRobert Mustacchi 		if ((comp_data = elf_getdata(comp_scn, NULL)) == NULL) {
258*8e458de0SRobert Mustacchi 			secmap_fail("failed to load section data from "
259*8e458de0SRobert Mustacchi 			    "source to compare to %s %s", sm->sm_obj, sname);
260*8e458de0SRobert Mustacchi 			return;
261*8e458de0SRobert Mustacchi 		}
262*8e458de0SRobert Mustacchi 
263*8e458de0SRobert Mustacchi 		if (comp_data->d_size != src_data->d_size) {
264*8e458de0SRobert Mustacchi 			secmap_fail("data size mismatch for %s: %s, core: "
265*8e458de0SRobert Mustacchi 			    "%zu, file: %zu", sm->sm_obj, sname,
266*8e458de0SRobert Mustacchi 			    src_data->d_size, comp_data->d_size);
267*8e458de0SRobert Mustacchi 			return;
268*8e458de0SRobert Mustacchi 		}
269*8e458de0SRobert Mustacchi 
270*8e458de0SRobert Mustacchi 		if (memcmp(comp_data->d_buf, src_data->d_buf,
271*8e458de0SRobert Mustacchi 		    comp_data->d_size) != 0) {
272*8e458de0SRobert Mustacchi 			secmap_fail("data mismatch between core and source "
273*8e458de0SRobert Mustacchi 			    "in %s: %s", sm->sm_obj, sname);
274*8e458de0SRobert Mustacchi 			return;
275*8e458de0SRobert Mustacchi 		}
276*8e458de0SRobert Mustacchi 
277*8e458de0SRobert Mustacchi 		return;
278*8e458de0SRobert Mustacchi 	}
279*8e458de0SRobert Mustacchi 
280*8e458de0SRobert Mustacchi 	secmap_fail("failed to find matching section for %s in %s",
281*8e458de0SRobert Mustacchi 	    sname, sm->sm_obj);
282*8e458de0SRobert Mustacchi }
283*8e458de0SRobert Mustacchi 
284*8e458de0SRobert Mustacchi static void
secmap_file_check(secmap_t * sm)285*8e458de0SRobert Mustacchi secmap_file_check(secmap_t *sm)
286*8e458de0SRobert Mustacchi {
287*8e458de0SRobert Mustacchi 	if (sm->sm_ctf && (secmap_content & CC_CONTENT_CTF) != 0 &&
288*8e458de0SRobert Mustacchi 	    sm->sm_nfound[SECMAP_CTF] == 0) {
289*8e458de0SRobert Mustacchi 		secmap_fail("expected object %s to have CTF, but it doesn't",
290*8e458de0SRobert Mustacchi 		    sm->sm_obj);
291*8e458de0SRobert Mustacchi 	}
292*8e458de0SRobert Mustacchi 
293*8e458de0SRobert Mustacchi 	if (sm->sm_symtab && (secmap_content & CC_CONTENT_SYMTAB) != 0 &&
294*8e458de0SRobert Mustacchi 	    sm->sm_nfound[SECMAP_SYMTAB] == 0) {
295*8e458de0SRobert Mustacchi 		secmap_fail("expected object %s to have a symbol table, "
296*8e458de0SRobert Mustacchi 		    "but it doesn't", sm->sm_obj);
297*8e458de0SRobert Mustacchi 	}
298*8e458de0SRobert Mustacchi 
299*8e458de0SRobert Mustacchi 	if (sm->sm_debug && (secmap_content & CC_CONTENT_DEBUG) != 0 &&
300*8e458de0SRobert Mustacchi 	    sm->sm_nfound[SECMAP_DEBUG] == 0) {
301*8e458de0SRobert Mustacchi 		secmap_fail("expected object %s to have debug sections, "
302*8e458de0SRobert Mustacchi 		    "but it doesn't", sm->sm_obj);
303*8e458de0SRobert Mustacchi 	}
304*8e458de0SRobert Mustacchi }
305*8e458de0SRobert Mustacchi 
306*8e458de0SRobert Mustacchi int
main(int argc,char * argv[])307*8e458de0SRobert Mustacchi main(int argc, char *argv[])
308*8e458de0SRobert Mustacchi {
309*8e458de0SRobert Mustacchi 	core_content_t content;
310*8e458de0SRobert Mustacchi 	struct ps_prochandle *Pr;
311*8e458de0SRobert Mustacchi 	int perr, fd;
312*8e458de0SRobert Mustacchi 	Elf *elf;
313*8e458de0SRobert Mustacchi 	Elf_Scn *scn;
314*8e458de0SRobert Mustacchi 	GElf_Ehdr ehdr;
315*8e458de0SRobert Mustacchi 
316*8e458de0SRobert Mustacchi 	if (argc != 3) {
317*8e458de0SRobert Mustacchi 		warnx("missing required file and core content");
318*8e458de0SRobert Mustacchi 		(void) fprintf(stderr, "Usage: secmapper file content\n");
319*8e458de0SRobert Mustacchi 		exit(EXIT_FAILURE);
320*8e458de0SRobert Mustacchi 	}
321*8e458de0SRobert Mustacchi 
322*8e458de0SRobert Mustacchi 	if (elf_version(EV_CURRENT) == EV_NONE) {
323*8e458de0SRobert Mustacchi 		errx(EXIT_FAILURE, "failed to init libelf");
324*8e458de0SRobert Mustacchi 	}
325*8e458de0SRobert Mustacchi 
326*8e458de0SRobert Mustacchi 	Pr = Pgrab_core(argv[1], NULL, PGRAB_RDONLY, &perr);
327*8e458de0SRobert Mustacchi 	if (Pr == NULL) {
328*8e458de0SRobert Mustacchi 		errx(EXIT_FAILURE, "failed to open %s: %s", argv[1],
329*8e458de0SRobert Mustacchi 		    Pgrab_error(perr));
330*8e458de0SRobert Mustacchi 	}
331*8e458de0SRobert Mustacchi 
332*8e458de0SRobert Mustacchi 	if ((fd = open(argv[1], O_RDONLY)) < 0) {
333*8e458de0SRobert Mustacchi 		err(EXIT_FAILURE, "failed to open %s\n", argv[1]);
334*8e458de0SRobert Mustacchi 	}
335*8e458de0SRobert Mustacchi 
336*8e458de0SRobert Mustacchi 	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
337*8e458de0SRobert Mustacchi 		errx(EXIT_FAILURE, "failed to open elf file %s: %s", argv[1],
338*8e458de0SRobert Mustacchi 		    elf_errmsg(elf_errno()));
339*8e458de0SRobert Mustacchi 	}
340*8e458de0SRobert Mustacchi 
341*8e458de0SRobert Mustacchi 	if (proc_str2content(argv[2], &content) != 0) {
342*8e458de0SRobert Mustacchi 		err(EXIT_FAILURE, "failed to parse content %s", argv[2]);
343*8e458de0SRobert Mustacchi 	}
344*8e458de0SRobert Mustacchi 
345*8e458de0SRobert Mustacchi 	if (gelf_getehdr(elf, &ehdr) == NULL) {
346*8e458de0SRobert Mustacchi 		errx(EXIT_FAILURE, "failed to get edr: %s",
347*8e458de0SRobert Mustacchi 		    elf_errmsg(elf_errno()));
348*8e458de0SRobert Mustacchi 	}
349*8e458de0SRobert Mustacchi 
350*8e458de0SRobert Mustacchi 	/*
351*8e458de0SRobert Mustacchi 	 * Before we go futher, make sure that we have the content in this file
352*8e458de0SRobert Mustacchi 	 * that we expect.
353*8e458de0SRobert Mustacchi 	 */
354*8e458de0SRobert Mustacchi 	check_content(content, Pr);
355*8e458de0SRobert Mustacchi 
356*8e458de0SRobert Mustacchi 	for (scn = elf_nextscn(elf, NULL); scn != NULL;
357*8e458de0SRobert Mustacchi 	    scn = elf_nextscn(elf, scn)) {
358*8e458de0SRobert Mustacchi 		const char *sname;
359*8e458de0SRobert Mustacchi 		GElf_Shdr shdr;
360*8e458de0SRobert Mustacchi 		size_t index;
361*8e458de0SRobert Mustacchi 		secmap_t *secmap;
362*8e458de0SRobert Mustacchi 
363*8e458de0SRobert Mustacchi 		index = elf_ndxscn(scn);
364*8e458de0SRobert Mustacchi 		if (gelf_getshdr(scn, &shdr) ==  NULL) {
365*8e458de0SRobert Mustacchi 			errx(EXIT_FAILURE, "failed to get section header for "
366*8e458de0SRobert Mustacchi 			    "shdr %zu: %s", index, elf_errmsg(elf_errno()));
367*8e458de0SRobert Mustacchi 		}
368*8e458de0SRobert Mustacchi 
369*8e458de0SRobert Mustacchi 		/*
370*8e458de0SRobert Mustacchi 		 * Skip the strtab.
371*8e458de0SRobert Mustacchi 		 */
372*8e458de0SRobert Mustacchi 		if (shdr.sh_type == SHT_STRTAB) {
373*8e458de0SRobert Mustacchi 			continue;
374*8e458de0SRobert Mustacchi 		}
375*8e458de0SRobert Mustacchi 
376*8e458de0SRobert Mustacchi 		sname = elf_strptr(elf, ehdr.e_shstrndx, shdr.sh_name);
377*8e458de0SRobert Mustacchi 		if (sname == NULL) {
378*8e458de0SRobert Mustacchi 			secmap_fail("TEST FAILURE: string name missing for "
379*8e458de0SRobert Mustacchi 			    "shdr %zu", index);
380*8e458de0SRobert Mustacchi 			continue;
381*8e458de0SRobert Mustacchi 		}
382*8e458de0SRobert Mustacchi 
383*8e458de0SRobert Mustacchi 		/*
384*8e458de0SRobert Mustacchi 		 * Find or cons up a new secmap for this object.
385*8e458de0SRobert Mustacchi 		 */
386*8e458de0SRobert Mustacchi 		secmap = secmap_find(shdr.sh_addr);
387*8e458de0SRobert Mustacchi 		if (secmap == NULL) {
388*8e458de0SRobert Mustacchi 			secmap = secmap_alloc(Pr, shdr.sh_addr);
389*8e458de0SRobert Mustacchi 		}
390*8e458de0SRobert Mustacchi 
391*8e458de0SRobert Mustacchi 		if (strcmp(sname, ".symtab") == 0) {
392*8e458de0SRobert Mustacchi 			secmap->sm_nfound[SECMAP_SYMTAB]++;
393*8e458de0SRobert Mustacchi 		} else if (strcmp(sname, ".SUNW_ctf") == 0) {
394*8e458de0SRobert Mustacchi 			secmap->sm_nfound[SECMAP_CTF]++;
395*8e458de0SRobert Mustacchi 		} else if (strncmp(sname, ".debug_", strlen(".debug_")) == 0) {
396*8e458de0SRobert Mustacchi 			secmap->sm_nfound[SECMAP_DEBUG]++;
397*8e458de0SRobert Mustacchi 		} else {
398*8e458de0SRobert Mustacchi 			continue;
399*8e458de0SRobert Mustacchi 		}
400*8e458de0SRobert Mustacchi 
401*8e458de0SRobert Mustacchi 		/*
402*8e458de0SRobert Mustacchi 		 * For one of our three primary sections, make sure that the
403*8e458de0SRobert Mustacchi 		 * data that is in the core file that we find in it actually
404*8e458de0SRobert Mustacchi 		 * matches the underlying object. That is, if the secmap
405*8e458de0SRobert Mustacchi 		 * actually has something here.
406*8e458de0SRobert Mustacchi 		 */
407*8e458de0SRobert Mustacchi 		if (secmap->sm_elf != NULL) {
408*8e458de0SRobert Mustacchi 			secmap_data_cmp(secmap, sname, scn, &shdr);
409*8e458de0SRobert Mustacchi 		}
410*8e458de0SRobert Mustacchi 	}
411*8e458de0SRobert Mustacchi 
412*8e458de0SRobert Mustacchi 	/*
413*8e458de0SRobert Mustacchi 	 * Now that we have iterated over all of these sections, check and make
414*8e458de0SRobert Mustacchi 	 * sure certain things are true of them. In particular, go through some
415*8e458de0SRobert Mustacchi 	 * of the various types of data and make sure it exists at all or
416*8e458de0SRobert Mustacchi 	 * doesn't based on our core content.
417*8e458de0SRobert Mustacchi 	 */
418*8e458de0SRobert Mustacchi 	secmap_matches_content(SECMAP_CTF);
419*8e458de0SRobert Mustacchi 	secmap_matches_content(SECMAP_SYMTAB);
420*8e458de0SRobert Mustacchi 	secmap_matches_content(SECMAP_DEBUG);
421*8e458de0SRobert Mustacchi 
422*8e458de0SRobert Mustacchi 	/*
423*8e458de0SRobert Mustacchi 	 * Finally, if we have enough information to know that we've found
424*8e458de0SRobert Mustacchi 	 * a file that we know it should at least have a given type of data,
425*8e458de0SRobert Mustacchi 	 * check for it. Here, it is OK for data to be present we don't expect
426*8e458de0SRobert Mustacchi 	 * (assuming the core content allows it). This makes this test less
427*8e458de0SRobert Mustacchi 	 * prone to broader changes in the system.
428*8e458de0SRobert Mustacchi 	 */
429*8e458de0SRobert Mustacchi 	for (size_t i = 0; i < secmap_count; i++) {
430*8e458de0SRobert Mustacchi 		secmap_file_check(&secmaps[i]);
431*8e458de0SRobert Mustacchi 	}
432*8e458de0SRobert Mustacchi 
433*8e458de0SRobert Mustacchi 	return (secmap_exit);
434*8e458de0SRobert Mustacchi }
435