xref: /titanic_51/usr/src/lib/libsaveargs/tests/dump/dump.c (revision 702941cd97e30d600c2c1275823bc58231b2c361)
1*702941cdSRichard Lowe /*
2*702941cdSRichard Lowe  * CDDL HEADER START
3*702941cdSRichard Lowe  *
4*702941cdSRichard Lowe  * The contents of this file are subject to the terms of the
5*702941cdSRichard Lowe  * Common Development and Distribution License (the "License").
6*702941cdSRichard Lowe  * You may not use this file except in compliance with the License.
7*702941cdSRichard Lowe  *
8*702941cdSRichard Lowe  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*702941cdSRichard Lowe  * or http://www.opensolaris.org/os/licensing.
10*702941cdSRichard Lowe  * See the License for the specific language governing permissions
11*702941cdSRichard Lowe  * and limitations under the License.
12*702941cdSRichard Lowe  *
13*702941cdSRichard Lowe  * When distributing Covered Code, include this CDDL HEADER in each
14*702941cdSRichard Lowe  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*702941cdSRichard Lowe  * If applicable, add the following below this CDDL HEADER, with the
16*702941cdSRichard Lowe  * fields enclosed by brackets "[]" replaced with your own identifying
17*702941cdSRichard Lowe  * information: Portions Copyright [yyyy] [name of copyright owner]
18*702941cdSRichard Lowe  *
19*702941cdSRichard Lowe  * CDDL HEADER END
20*702941cdSRichard Lowe  */
21*702941cdSRichard Lowe 
22*702941cdSRichard Lowe /*
23*702941cdSRichard Lowe  * Copyright (c) 2011, Joyent, Inc. All rights reserved.
24*702941cdSRichard Lowe  * Copyright (c) 2011, Robert Mustacchi, Inc. All rights reserved.
25*702941cdSRichard Lowe  * Copyright 2013, Richard Lowe.
26*702941cdSRichard Lowe  */
27*702941cdSRichard Lowe 
28*702941cdSRichard Lowe #include <err.h>
29*702941cdSRichard Lowe #include <fcntl.h>
30*702941cdSRichard Lowe #include <gelf.h>
31*702941cdSRichard Lowe #include <libctf.h>
32*702941cdSRichard Lowe #include <saveargs.h>
33*702941cdSRichard Lowe #include <stdarg.h>
34*702941cdSRichard Lowe #include <stdio.h>
35*702941cdSRichard Lowe #include <stdlib.h>
36*702941cdSRichard Lowe #include <strings.h>
37*702941cdSRichard Lowe #include <unistd.h>
38*702941cdSRichard Lowe 
39*702941cdSRichard Lowe extern const char *__progname;
40*702941cdSRichard Lowe 
41*702941cdSRichard Lowe typedef struct symtab_sym {
42*702941cdSRichard Lowe 	GElf_Sym ss_sym;
43*702941cdSRichard Lowe 	char *ss_name;
44*702941cdSRichard Lowe 	ctf_funcinfo_t ss_finfo;
45*702941cdSRichard Lowe 	uint8_t *ss_data;
46*702941cdSRichard Lowe 	size_t ss_size;
47*702941cdSRichard Lowe } symtab_sym_t;
48*702941cdSRichard Lowe 
49*702941cdSRichard Lowe static void
50*702941cdSRichard Lowe walk_symtab(Elf *elf, char *fname, ctf_file_t *fp,
51*702941cdSRichard Lowe     void (*callback)(ctf_file_t *, symtab_sym_t *))
52*702941cdSRichard Lowe {
53*702941cdSRichard Lowe 	Elf_Scn *stab = NULL;
54*702941cdSRichard Lowe 	Elf_Scn *text = NULL;
55*702941cdSRichard Lowe 	Elf_Data *stabdata = NULL;
56*702941cdSRichard Lowe 	Elf_Data *textdata = NULL;
57*702941cdSRichard Lowe 	GElf_Ehdr ehdr;
58*702941cdSRichard Lowe 	GElf_Shdr stabshdr;
59*702941cdSRichard Lowe 	GElf_Shdr textshdr;
60*702941cdSRichard Lowe 	int foundtext = 0, foundstab = 0;
61*702941cdSRichard Lowe 	symtab_sym_t ss;
62*702941cdSRichard Lowe 
63*702941cdSRichard Lowe 	if ((gelf_getehdr(elf, &ehdr)) == NULL)
64*702941cdSRichard Lowe 		errx(1, "could not read ELF header from %s\n",
65*702941cdSRichard Lowe 		    fname);
66*702941cdSRichard Lowe 
67*702941cdSRichard Lowe 	while ((stab = elf_nextscn(elf, stab)) != NULL) {
68*702941cdSRichard Lowe 		(void) gelf_getshdr(stab, &stabshdr);
69*702941cdSRichard Lowe 
70*702941cdSRichard Lowe 		if (stabshdr.sh_type == SHT_SYMTAB) {
71*702941cdSRichard Lowe 			foundstab = 1;
72*702941cdSRichard Lowe 			break;
73*702941cdSRichard Lowe 		}
74*702941cdSRichard Lowe 	}
75*702941cdSRichard Lowe 
76*702941cdSRichard Lowe 	while ((text = elf_nextscn(elf, text)) != NULL) {
77*702941cdSRichard Lowe 		(void) gelf_getshdr(text, &textshdr);
78*702941cdSRichard Lowe 
79*702941cdSRichard Lowe 		if (strcmp(".text", elf_strptr(elf,
80*702941cdSRichard Lowe 		    ehdr.e_shstrndx, (size_t)textshdr.sh_name)) == 0) {
81*702941cdSRichard Lowe 			foundtext = 1;
82*702941cdSRichard Lowe 			break;
83*702941cdSRichard Lowe 		}
84*702941cdSRichard Lowe 	}
85*702941cdSRichard Lowe 
86*702941cdSRichard Lowe 	if (!foundstab || !foundtext)
87*702941cdSRichard Lowe 		return;
88*702941cdSRichard Lowe 
89*702941cdSRichard Lowe 	stabdata = elf_getdata(stab, NULL);
90*702941cdSRichard Lowe 	textdata = elf_rawdata(text,  NULL);
91*702941cdSRichard Lowe 	for (unsigned symdx = 0;
92*702941cdSRichard Lowe 	    symdx < (stabshdr.sh_size / stabshdr.sh_entsize);
93*702941cdSRichard Lowe 	    symdx++) {
94*702941cdSRichard Lowe 		(void) gelf_getsym(stabdata, symdx, &ss.ss_sym);
95*702941cdSRichard Lowe 
96*702941cdSRichard Lowe 		if ((GELF_ST_TYPE(ss.ss_sym.st_info) != STT_FUNC) ||
97*702941cdSRichard Lowe 		    (ss.ss_sym.st_shndx == SHN_UNDEF))
98*702941cdSRichard Lowe 			continue;
99*702941cdSRichard Lowe 
100*702941cdSRichard Lowe 		ss.ss_name = elf_strptr(elf, stabshdr.sh_link,
101*702941cdSRichard Lowe 		    ss.ss_sym.st_name);
102*702941cdSRichard Lowe 		ss.ss_data = ((uint8_t *)(textdata->d_buf)) +
103*702941cdSRichard Lowe 		    (ss.ss_sym.st_value - textshdr.sh_addr);
104*702941cdSRichard Lowe 
105*702941cdSRichard Lowe 		if (ctf_func_info(fp, symdx, &ss.ss_finfo) == CTF_ERR) {
106*702941cdSRichard Lowe 			fprintf(stderr, "failed to get funcinfo for: %s\n",
107*702941cdSRichard Lowe 			    ss.ss_name);
108*702941cdSRichard Lowe 			continue;
109*702941cdSRichard Lowe 		}
110*702941cdSRichard Lowe 
111*702941cdSRichard Lowe 		(void) callback(fp, &ss);
112*702941cdSRichard Lowe 	}
113*702941cdSRichard Lowe }
114*702941cdSRichard Lowe 
115*702941cdSRichard Lowe void
116*702941cdSRichard Lowe check_sym(ctf_file_t *ctfp, symtab_sym_t *ss)
117*702941cdSRichard Lowe {
118*702941cdSRichard Lowe 	int rettype = ctf_type_kind(ctfp, ss->ss_finfo.ctc_return);
119*702941cdSRichard Lowe 	int start_index = 0;
120*702941cdSRichard Lowe 
121*702941cdSRichard Lowe 	if (ss->ss_finfo.ctc_argc == 0) /* No arguments, no point */
122*702941cdSRichard Lowe 		return;
123*702941cdSRichard Lowe 
124*702941cdSRichard Lowe 	if (((rettype == CTF_K_STRUCT) || (rettype == CTF_K_UNION)) &&
125*702941cdSRichard Lowe 	    ctf_type_size(ctfp, ss->ss_finfo.ctc_return) > 16)
126*702941cdSRichard Lowe 		start_index = 1;
127*702941cdSRichard Lowe 
128*702941cdSRichard Lowe 	if (saveargs_has_args(ss->ss_data, ss->ss_sym.st_size,
129*702941cdSRichard Lowe 	    ss->ss_finfo.ctc_argc, start_index) != SAVEARGS_NO_ARGS)
130*702941cdSRichard Lowe 		printf("%s has %d saved args\n", ss->ss_name,
131*702941cdSRichard Lowe 		    ss->ss_finfo.ctc_argc);
132*702941cdSRichard Lowe }
133*702941cdSRichard Lowe 
134*702941cdSRichard Lowe int
135*702941cdSRichard Lowe main(int argc, char **argv)
136*702941cdSRichard Lowe {
137*702941cdSRichard Lowe 	Elf		*elf;
138*702941cdSRichard Lowe 	ctf_file_t	*ctfp;
139*702941cdSRichard Lowe 	int errp, fd;
140*702941cdSRichard Lowe 
141*702941cdSRichard Lowe 	if (ctf_version(CTF_VERSION) == -1)
142*702941cdSRichard Lowe 		errx(1, "mismatched libctf versions\n");
143*702941cdSRichard Lowe 
144*702941cdSRichard Lowe 	if (elf_version(EV_CURRENT) == EV_NONE)
145*702941cdSRichard Lowe 		errx(1, "mismatched libelf versions\n");
146*702941cdSRichard Lowe 
147*702941cdSRichard Lowe 	if (argc != 2)
148*702941cdSRichard Lowe 		errx(2, "usage: %s <file>\n", __progname);
149*702941cdSRichard Lowe 
150*702941cdSRichard Lowe 	if ((ctfp = ctf_open(argv[1], &errp)) == NULL)
151*702941cdSRichard Lowe 		errx(1, "failed to ctf_open file: %s: %s\n", argv[1],
152*702941cdSRichard Lowe 		    ctf_errmsg(errp));
153*702941cdSRichard Lowe 
154*702941cdSRichard Lowe 	if ((fd = open(argv[1], O_RDONLY)) == -1)
155*702941cdSRichard Lowe 		errx(1, "could not open %s\n", argv[1]);
156*702941cdSRichard Lowe 
157*702941cdSRichard Lowe 	if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL)
158*702941cdSRichard Lowe 		errx(1, "could not interpret ELF from %s\n",
159*702941cdSRichard Lowe 		    argv[1]);
160*702941cdSRichard Lowe 
161*702941cdSRichard Lowe 	walk_symtab(elf, argv[1], ctfp, check_sym);
162*702941cdSRichard Lowe 
163*702941cdSRichard Lowe 	(void) elf_end(elf);
164*702941cdSRichard Lowe 	(void) close(fd);
165*702941cdSRichard Lowe 
166*702941cdSRichard Lowe 	return (0);
167*702941cdSRichard Lowe }
168