| GCC Code Coverage Report | |||||||||||||||||||||
        
  | 
    |||||||||||||||||||||
| Line | Branch | Exec | Source | 
1  | 
    /* $OpenBSD: nm.c,v 1.52 2017/09/12 08:32:44 mpi Exp $ */  | 
    ||
2  | 
    /* $NetBSD: nm.c,v 1.7 1996/01/14 23:04:03 pk Exp $ */  | 
    ||
3  | 
    |||
4  | 
    /*  | 
    ||
5  | 
    * Copyright (c) 1989, 1993  | 
    ||
6  | 
    * The Regents of the University of California. All rights reserved.  | 
    ||
7  | 
    *  | 
    ||
8  | 
    * This code is derived from software contributed to Berkeley by  | 
    ||
9  | 
    * Hans Huebner.  | 
    ||
10  | 
    *  | 
    ||
11  | 
    * Redistribution and use in source and binary forms, with or without  | 
    ||
12  | 
    * modification, are permitted provided that the following conditions  | 
    ||
13  | 
    * are met:  | 
    ||
14  | 
    * 1. Redistributions of source code must retain the above copyright  | 
    ||
15  | 
    * notice, this list of conditions and the following disclaimer.  | 
    ||
16  | 
    * 2. Redistributions in binary form must reproduce the above copyright  | 
    ||
17  | 
    * notice, this list of conditions and the following disclaimer in the  | 
    ||
18  | 
    * documentation and/or other materials provided with the distribution.  | 
    ||
19  | 
    * 3. Neither the name of the University nor the names of its contributors  | 
    ||
20  | 
    * may be used to endorse or promote products derived from this software  | 
    ||
21  | 
    * without specific prior written permission.  | 
    ||
22  | 
    *  | 
    ||
23  | 
    * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND  | 
    ||
24  | 
    * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE  | 
    ||
25  | 
    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE  | 
    ||
26  | 
    * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE  | 
    ||
27  | 
    * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL  | 
    ||
28  | 
    * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS  | 
    ||
29  | 
    * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)  | 
    ||
30  | 
    * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT  | 
    ||
31  | 
    * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY  | 
    ||
32  | 
    * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF  | 
    ||
33  | 
    * SUCH DAMAGE.  | 
    ||
34  | 
    */  | 
    ||
35  | 
    |||
36  | 
    #include <sys/types.h>  | 
    ||
37  | 
    #include <sys/mman.h>  | 
    ||
38  | 
    #include <a.out.h>  | 
    ||
39  | 
    #include <elf_abi.h>  | 
    ||
40  | 
    #include <ar.h>  | 
    ||
41  | 
    #include <ranlib.h>  | 
    ||
42  | 
    #include <unistd.h>  | 
    ||
43  | 
    #include <err.h>  | 
    ||
44  | 
    #include <errno.h>  | 
    ||
45  | 
    #include <ctype.h>  | 
    ||
46  | 
    #include <link.h>  | 
    ||
47  | 
    |||
48  | 
    #include <stdio.h>  | 
    ||
49  | 
    #include <stdlib.h>  | 
    ||
50  | 
    #include <string.h>  | 
    ||
51  | 
    #include <getopt.h>  | 
    ||
52  | 
    #include "util.h"  | 
    ||
53  | 
    #include "elfuncs.h"  | 
    ||
54  | 
    |||
55  | 
    #define SYMTABMAG "/ "  | 
    ||
56  | 
    #define STRTABMAG "//"  | 
    ||
57  | 
    #define SYM64MAG "/SYM64/ "  | 
    ||
58  | 
    |||
59  | 
    union hdr { | 
    ||
60  | 
    Elf32_Ehdr elf32;  | 
    ||
61  | 
    Elf64_Ehdr elf64;  | 
    ||
62  | 
    };  | 
    ||
63  | 
    |||
64  | 
    int armap;  | 
    ||
65  | 
    int demangle;  | 
    ||
66  | 
    int non_object_warning;  | 
    ||
67  | 
    int print_only_external_symbols;  | 
    ||
68  | 
    int print_only_undefined_symbols;  | 
    ||
69  | 
    int print_all_symbols;  | 
    ||
70  | 
    int print_file_each_line;  | 
    ||
71  | 
    int show_extensions;  | 
    ||
72  | 
    int issize;  | 
    ||
73  | 
    char posix_fmtstr[6];  | 
    ||
74  | 
    int posix_output;  | 
    ||
75  | 
    char posix_radix = 'x';  | 
    ||
76  | 
    int usemmap = 1;  | 
    ||
77  | 
    int dynamic_only;  | 
    ||
78  | 
    |||
79  | 
    /* size vars */  | 
    ||
80  | 
    unsigned long total_text, total_data, total_bss, total_total;  | 
    ||
81  | 
    int non_object_warning, print_totals;  | 
    ||
82  | 
    |||
83  | 
    int rev;  | 
    ||
84  | 
    int fname(const void *, const void *);  | 
    ||
85  | 
    int rname(const void *, const void *);  | 
    ||
86  | 
    int value(const void *, const void *);  | 
    ||
87  | 
    char *otherstring(struct xnlist *);  | 
    ||
88  | 
    int (*sfunc)(const void *, const void *) = fname;  | 
    ||
89  | 
    char typeletter(struct xnlist *);  | 
    ||
90  | 
    int mmbr_name(struct ar_hdr *, char **, int, int *, FILE *);  | 
    ||
91  | 
    int show_symtab(off_t, u_long, const char *, FILE *);  | 
    ||
92  | 
    int show_symdef(off_t, u_long, const char *, FILE *);  | 
    ||
93  | 
    |||
94  | 
    /* some macros for symbol type (nlist.n_type) handling */  | 
    ||
95  | 
    #define IS_EXTERNAL(x) ((x) & N_EXT)  | 
    ||
96  | 
    #define SYMBOL_TYPE(x) ((x) & (N_TYPE | N_STAB))  | 
    ||
97  | 
    |||
98  | 
    void pipe2cppfilt(void);  | 
    ||
99  | 
    void usage(void);  | 
    ||
100  | 
    char *symname(struct xnlist *);  | 
    ||
101  | 
    int process_file(int, const char *);  | 
    ||
102  | 
    int show_archive(int, const char *, FILE *);  | 
    ||
103  | 
    int show_file(int, int, const char *, FILE *fp, off_t, union hdr *);  | 
    ||
104  | 
    void print_symbol(const char *, struct xnlist *);  | 
    ||
105  | 
    |||
106  | 
    #define OPTSTRING_NM "aABCDegnopPrst:uvw"  | 
    ||
107  | 
    const struct option longopts_nm[] = { | 
    ||
108  | 
    	{ "debug-syms",		no_argument,		0,	'a' }, | 
    ||
109  | 
    	{ "demangle",		no_argument,		0,	'C' }, | 
    ||
110  | 
    	{ "dynamic",		no_argument,		0,	'D' }, | 
    ||
111  | 
    	{ "extern-only",	no_argument,		0,	'g' }, | 
    ||
112  | 
    /*	{ "line-numbers",	no_argument,		0,	'l' }, */ | 
    ||
113  | 
    	{ "no-sort",		no_argument,		0,	'p' }, | 
    ||
114  | 
    	{ "numeric-sort",	no_argument,		0,	'n' }, | 
    ||
115  | 
    	{ "print-armap",	no_argument,		0,	's' }, | 
    ||
116  | 
    	{ "print-file-name",	no_argument,		0,	'o' }, | 
    ||
117  | 
    	{ "reverse-sort",	no_argument,		0,	'r' }, | 
    ||
118  | 
    /*	{ "size-sort",		no_argument,		&szval,	1 }, */ | 
    ||
119  | 
    	{ "undefined-only",	no_argument,		0,	'u' }, | 
    ||
120  | 
    	{ "help",		no_argument,		0,	'?' }, | 
    ||
121  | 
    	{ NULL } | 
    ||
122  | 
    };  | 
    ||
123  | 
    |||
124  | 
    /*  | 
    ||
125  | 
    * main()  | 
    ||
126  | 
    * parse command line, execute process_file() for each file  | 
    ||
127  | 
    * specified on the command line.  | 
    ||
128  | 
    */  | 
    ||
129  | 
    int  | 
    ||
130  | 
    main(int argc, char *argv[])  | 
    ||
131  | 
    { | 
    ||
132  | 
    extern char *__progname;  | 
    ||
133  | 
    extern int optind;  | 
    ||
134  | 
    const char *optstr;  | 
    ||
135  | 
    const struct option *lopts;  | 
    ||
136  | 
    int ch, eval;  | 
    ||
137  | 
    |||
138  | 
    ✗✓ | 376  | 
    	if (pledge("stdio rpath proc exec flock cpath wpath", NULL) == -1) | 
    
139  | 
    err(1, "pledge");  | 
    ||
140  | 
    |||
141  | 
    optstr = OPTSTRING_NM;  | 
    ||
142  | 
    lopts = longopts_nm;  | 
    ||
143  | 
    ✗✓ | 188  | 
    	if (!strcmp(__progname, "size")) { | 
    
144  | 
    		if (pledge("stdio rpath flock cpath wpath", NULL) == -1) | 
    ||
145  | 
    err(1, "pledge");  | 
    ||
146  | 
    |||
147  | 
    issize = 1;  | 
    ||
148  | 
    optstr = "tw";  | 
    ||
149  | 
    lopts = NULL;  | 
    ||
150  | 
    }  | 
    ||
151  | 
    |||
152  | 
    ✓✓ | 556  | 
    	while ((ch = getopt_long(argc, argv, optstr, lopts, NULL)) != -1) { | 
    
153  | 
    ✓✗✓✗ ✗✓✗✗ ✗✓✗✗ ✗✗✗✗ ✗✗  | 
    736  | 
    		switch (ch) { | 
    
154  | 
    case 'a':  | 
    ||
155  | 
    print_all_symbols = 1;  | 
    ||
156  | 
    break;  | 
    ||
157  | 
    case 'B':  | 
    ||
158  | 
    /* no-op, compat with gnu-nm */  | 
    ||
159  | 
    break;  | 
    ||
160  | 
    case 'C':  | 
    ||
161  | 
    5  | 
    demangle = 1;  | 
    |
162  | 
    5  | 
    break;  | 
    |
163  | 
    case 'D':  | 
    ||
164  | 
    dynamic_only = 1;  | 
    ||
165  | 
    break;  | 
    ||
166  | 
    case 'e':  | 
    ||
167  | 
    show_extensions = 1;  | 
    ||
168  | 
    break;  | 
    ||
169  | 
    case 'g':  | 
    ||
170  | 
    180  | 
    print_only_external_symbols = 1;  | 
    |
171  | 
    180  | 
    break;  | 
    |
172  | 
    case 'n':  | 
    ||
173  | 
    case 'v':  | 
    ||
174  | 
    sfunc = value;  | 
    ||
175  | 
    break;  | 
    ||
176  | 
    case 'A':  | 
    ||
177  | 
    case 'o':  | 
    ||
178  | 
    183  | 
    print_file_each_line = 1;  | 
    |
179  | 
    183  | 
    break;  | 
    |
180  | 
    case 'p':  | 
    ||
181  | 
    sfunc = NULL;  | 
    ||
182  | 
    break;  | 
    ||
183  | 
    case 'P':  | 
    ||
184  | 
    posix_output = 1;  | 
    ||
185  | 
    break;  | 
    ||
186  | 
    case 'r':  | 
    ||
187  | 
    rev = 1;  | 
    ||
188  | 
    break;  | 
    ||
189  | 
    case 's':  | 
    ||
190  | 
    armap = 1;  | 
    ||
191  | 
    break;  | 
    ||
192  | 
    case 'u':  | 
    ||
193  | 
    print_only_undefined_symbols = 1;  | 
    ||
194  | 
    break;  | 
    ||
195  | 
    case 'w':  | 
    ||
196  | 
    non_object_warning = 1;  | 
    ||
197  | 
    break;  | 
    ||
198  | 
    case 't':  | 
    ||
199  | 
    			if (issize) { | 
    ||
200  | 
    print_totals = 1;  | 
    ||
201  | 
    			} else { | 
    ||
202  | 
    posix_radix = *optarg;  | 
    ||
203  | 
    if (strlen(optarg) != 1 ||  | 
    ||
204  | 
    (posix_radix != 'd' && posix_radix != 'o' &&  | 
    ||
205  | 
    posix_radix != 'x'))  | 
    ||
206  | 
    usage();  | 
    ||
207  | 
    }  | 
    ||
208  | 
    break;  | 
    ||
209  | 
    case '?':  | 
    ||
210  | 
    default:  | 
    ||
211  | 
    usage();  | 
    ||
212  | 
    }  | 
    ||
213  | 
    }  | 
    ||
214  | 
    |||
215  | 
    ✗✓ | 188  | 
    if (posix_output)  | 
    
216  | 
    (void)snprintf(posix_fmtstr, sizeof posix_fmtstr, "%%%c %%%c",  | 
    ||
217  | 
    posix_radix, posix_radix);  | 
    ||
218  | 
    ✓✓ | 188  | 
    if (demangle)  | 
    
219  | 
    5  | 
    pipe2cppfilt();  | 
    |
220  | 
    |||
221  | 
    ✗✓ | 188  | 
    	if (pledge("stdio rpath flock cpath wpath", NULL) == -1) | 
    
222  | 
    err(1, "pledge");  | 
    ||
223  | 
    |||
224  | 
    188  | 
    argv += optind;  | 
    |
225  | 
    188  | 
    argc -= optind;  | 
    |
226  | 
    |||
227  | 
    ✗✓ | 188  | 
    if (rev && sfunc == fname)  | 
    
228  | 
    sfunc = rname;  | 
    ||
229  | 
    |||
230  | 
    eval = 0;  | 
    ||
231  | 
    ✓✗ | 188  | 
    if (*argv)  | 
    
232  | 
    		do { | 
    ||
233  | 
    14035  | 
    eval |= process_file(argc, *argv);  | 
    |
234  | 
    ✓✓ | 14035  | 
    } while (*++argv);  | 
    
235  | 
    else  | 
    ||
236  | 
    eval |= process_file(1, "a.out");  | 
    ||
237  | 
    |||
238  | 
    ✗✓ | 188  | 
    if (issize && print_totals)  | 
    
239  | 
    		printf("\n%lu\t%lu\t%lu\t%lu\t%lx\tTOTAL\n", | 
    ||
240  | 
    total_text, total_data, total_bss,  | 
    ||
241  | 
    total_total, total_total);  | 
    ||
242  | 
    exit(eval);  | 
    ||
243  | 
    }  | 
    ||
244  | 
    |||
245  | 
    /*  | 
    ||
246  | 
    * process_file()  | 
    ||
247  | 
    * show symbols in the file given as an argument. Accepts archive and  | 
    ||
248  | 
    * object files as input.  | 
    ||
249  | 
    */  | 
    ||
250  | 
    int  | 
    ||
251  | 
    process_file(int count, const char *fname)  | 
    ||
252  | 
    { | 
    ||
253  | 
    28070  | 
    union hdr exec_head;  | 
    |
254  | 
    FILE *fp;  | 
    ||
255  | 
    int retval;  | 
    ||
256  | 
    size_t bytes;  | 
    ||
257  | 
    14035  | 
    char magic[SARMAG];  | 
    |
258  | 
    |||
259  | 
    ✗✓ | 14035  | 
    	if (!(fp = fopen(fname, "r"))) { | 
    
260  | 
    		warn("cannot read %s", fname); | 
    ||
261  | 
    return(1);  | 
    ||
262  | 
    }  | 
    ||
263  | 
    |||
264  | 
    ✓✓ | 14035  | 
    if (!issize && count > 1)  | 
    
265  | 
    14027  | 
    		(void)printf("\n%s:\n", fname); | 
    |
266  | 
    |||
267  | 
    /*  | 
    ||
268  | 
    * first check whether this is an object file - read a object  | 
    ||
269  | 
    * header, and skip back to the beginning  | 
    ||
270  | 
    */  | 
    ||
271  | 
    14035  | 
    bzero(&exec_head, sizeof(exec_head));  | 
    |
272  | 
    14035  | 
    bytes = fread((char *)&exec_head, 1, sizeof(exec_head), fp);  | 
    |
273  | 
    ✗✓ | 14035  | 
    	if (bytes < sizeof(exec_head)) { | 
    
274  | 
    		if (bytes < sizeof(exec_head.elf32) || IS_ELF(exec_head.elf32)) { | 
    ||
275  | 
    			warnx("%s: bad format", fname); | 
    ||
276  | 
    (void)fclose(fp);  | 
    ||
277  | 
    return(1);  | 
    ||
278  | 
    }  | 
    ||
279  | 
    }  | 
    ||
280  | 
    14035  | 
    rewind(fp);  | 
    |
281  | 
    |||
282  | 
    /* this could be an archive */  | 
    ||
283  | 
    ✓✓✓✗ ✓✗✗✓  | 
    56131  | 
    	if (!IS_ELF(exec_head.elf32)) { | 
    
284  | 
    ✓✗✗✓ | 
    6  | 
    if (fread(magic, sizeof(magic), (size_t)1, fp) != 1 ||  | 
    
285  | 
    3  | 
    		    strncmp(magic, ARMAG, SARMAG)) { | 
    |
286  | 
    			warnx("%s: not object file or archive", fname); | 
    ||
287  | 
    (void)fclose(fp);  | 
    ||
288  | 
    return(1);  | 
    ||
289  | 
    }  | 
    ||
290  | 
    3  | 
    retval = show_archive(count, fname, fp);  | 
    |
291  | 
    3  | 
    } else  | 
    |
292  | 
    14032  | 
    retval = show_file(count, 1, fname, fp, 0, &exec_head);  | 
    |
293  | 
    14035  | 
    (void)fclose(fp);  | 
    |
294  | 
    14035  | 
    return(retval);  | 
    |
295  | 
    14035  | 
    }  | 
    |
296  | 
    |||
297  | 
    char *nametab;  | 
    ||
298  | 
    |||
299  | 
    /*  | 
    ||
300  | 
    *  | 
    ||
301  | 
    * given the archive member header -- produce member name  | 
    ||
302  | 
    */  | 
    ||
303  | 
    int  | 
    ||
304  | 
    mmbr_name(struct ar_hdr *arh, char **name, int baselen, int *namelen, FILE *fp)  | 
    ||
305  | 
    { | 
    ||
306  | 
    228  | 
    char *p = *name + strlen(*name);  | 
    |
307  | 
    long i;  | 
    ||
308  | 
    |||
309  | 
    ✗✓✗✗ | 
    114  | 
    	if (nametab && arh->ar_name[0] == '/') { | 
    
310  | 
    int len;  | 
    ||
311  | 
    |||
312  | 
    i = atol(&arh->ar_name[1]);  | 
    ||
313  | 
    len = strlen(&nametab[i]) + 1;  | 
    ||
314  | 
    		if (len > *namelen) { | 
    ||
315  | 
    p -= (long)*name;  | 
    ||
316  | 
    if ((*name = realloc(*name, baselen+len)) == NULL)  | 
    ||
317  | 
    err(1, NULL);  | 
    ||
318  | 
    *namelen = len;  | 
    ||
319  | 
    p += (long)*name;  | 
    ||
320  | 
    }  | 
    ||
321  | 
    strlcpy(p, &nametab[i], len);  | 
    ||
322  | 
    p += len - 1;  | 
    ||
323  | 
    } else  | 
    ||
324  | 
    #ifdef AR_EFMT1  | 
    ||
325  | 
    /*  | 
    ||
326  | 
    * BSD 4.4 extended AR format: #1/<namelen>, with name as the  | 
    ||
327  | 
    * first <namelen> bytes of the file  | 
    ||
328  | 
    */  | 
    ||
329  | 
    ✗✓✗✗ | 
    114  | 
    if ((arh->ar_name[0] == '#') &&  | 
    
330  | 
    (arh->ar_name[1] == '1') &&  | 
    ||
331  | 
    (arh->ar_name[2] == '/') &&  | 
    ||
332  | 
    	    (isdigit((unsigned char)arh->ar_name[3]))) { | 
    ||
333  | 
    int len = atoi(&arh->ar_name[3]);  | 
    ||
334  | 
    |||
335  | 
    		if (len > *namelen) { | 
    ||
336  | 
    p -= (long)*name;  | 
    ||
337  | 
    if ((*name = realloc(*name, baselen+len)) == NULL)  | 
    ||
338  | 
    err(1, NULL);  | 
    ||
339  | 
    *namelen = len;  | 
    ||
340  | 
    p += (long)*name;  | 
    ||
341  | 
    }  | 
    ||
342  | 
    		if (fread(p, len, 1, fp) != 1) { | 
    ||
343  | 
    			warnx("%s: premature EOF", *name); | 
    ||
344  | 
    free(*name);  | 
    ||
345  | 
    return(1);  | 
    ||
346  | 
    }  | 
    ||
347  | 
    p += len;  | 
    ||
348  | 
    } else  | 
    ||
349  | 
    #endif  | 
    ||
350  | 
    ✓✓ | 3876  | 
    for (i = 0; i < sizeof(arh->ar_name); ++i)  | 
    
351  | 
    ✓✗✓✓ | 
    3648  | 
    if (arh->ar_name[i] && arh->ar_name[i] != ' ')  | 
    
352  | 
    1167  | 
    *p++ = arh->ar_name[i];  | 
    |
353  | 
    114  | 
    *p = '\0';  | 
    |
354  | 
    ✓✗ | 114  | 
    if (p[-1] == '/')  | 
    
355  | 
    114  | 
    *--p = '\0';  | 
    |
356  | 
    |||
357  | 
    114  | 
    return (0);  | 
    |
358  | 
    114  | 
    }  | 
    |
359  | 
    |||
360  | 
    /*  | 
    ||
361  | 
    * show_symtab()  | 
    ||
362  | 
    * show archive ranlib index (fs5)  | 
    ||
363  | 
    */  | 
    ||
364  | 
    int  | 
    ||
365  | 
    show_symtab(off_t off, u_long len, const char *name, FILE *fp)  | 
    ||
366  | 
    { | 
    ||
367  | 
    struct ar_hdr ar_head;  | 
    ||
368  | 
    int *symtab, *ps;  | 
    ||
369  | 
    char *strtab, *p;  | 
    ||
370  | 
    int num, rval = 0;  | 
    ||
371  | 
    int namelen;  | 
    ||
372  | 
    off_t restore;  | 
    ||
373  | 
    |||
374  | 
    restore = ftello(fp);  | 
    ||
375  | 
    |||
376  | 
    MMAP(symtab, len, PROT_READ, MAP_PRIVATE|MAP_FILE, fileno(fp), off);  | 
    ||
377  | 
    if (symtab == MAP_FAILED)  | 
    ||
378  | 
    return (1);  | 
    ||
379  | 
    |||
380  | 
    namelen = sizeof(ar_head.ar_name);  | 
    ||
381  | 
    	if ((p = malloc(sizeof(ar_head.ar_name))) == NULL) { | 
    ||
382  | 
    		warn("%s: malloc", name); | 
    ||
383  | 
    MUNMAP(symtab, len);  | 
    ||
384  | 
    }  | 
    ||
385  | 
    |||
386  | 
    	printf("\nArchive index:\n"); | 
    ||
387  | 
    num = betoh32(*symtab);  | 
    ||
388  | 
    strtab = (char *)(symtab + num + 1);  | 
    ||
389  | 
    	for (ps = symtab + 1; num--; ps++, strtab += strlen(strtab) + 1) { | 
    ||
390  | 
    		if (fseeko(fp, betoh32(*ps), SEEK_SET)) { | 
    ||
391  | 
    			warn("%s: fseeko", name); | 
    ||
392  | 
    rval = 1;  | 
    ||
393  | 
    break;  | 
    ||
394  | 
    }  | 
    ||
395  | 
    |||
396  | 
    if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||  | 
    ||
397  | 
    		    memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) { | 
    ||
398  | 
    			warnx("%s: member fseeko", name); | 
    ||
399  | 
    rval = 1;  | 
    ||
400  | 
    break;  | 
    ||
401  | 
    }  | 
    ||
402  | 
    |||
403  | 
    *p = '\0';  | 
    ||
404  | 
    		if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) { | 
    ||
405  | 
    rval = 1;  | 
    ||
406  | 
    break;  | 
    ||
407  | 
    }  | 
    ||
408  | 
    |||
409  | 
    		printf("%s in %s\n", strtab, p); | 
    ||
410  | 
    }  | 
    ||
411  | 
    |||
412  | 
    fseeko(fp, restore, SEEK_SET);  | 
    ||
413  | 
    |||
414  | 
    free(p);  | 
    ||
415  | 
    MUNMAP(symtab, len);  | 
    ||
416  | 
    return (rval);  | 
    ||
417  | 
    }  | 
    ||
418  | 
    |||
419  | 
    /*  | 
    ||
420  | 
    * show_symdef()  | 
    ||
421  | 
    * show archive ranlib index (gob)  | 
    ||
422  | 
    */  | 
    ||
423  | 
    int  | 
    ||
424  | 
    show_symdef(off_t off, u_long len, const char *name, FILE *fp)  | 
    ||
425  | 
    { | 
    ||
426  | 
    struct ranlib *prn, *eprn;  | 
    ||
427  | 
    struct ar_hdr ar_head;  | 
    ||
428  | 
    char *symdef;  | 
    ||
429  | 
    char *strtab, *p;  | 
    ||
430  | 
    u_long size;  | 
    ||
431  | 
    int namelen, rval = 0;  | 
    ||
432  | 
    |||
433  | 
    MMAP(symdef, len, PROT_READ, MAP_PRIVATE|MAP_FILE, fileno(fp), off);  | 
    ||
434  | 
    if (symdef == MAP_FAILED)  | 
    ||
435  | 
    return (1);  | 
    ||
436  | 
    if (usemmap)  | 
    ||
437  | 
    (void)madvise(symdef, len, MADV_SEQUENTIAL);  | 
    ||
438  | 
    |||
439  | 
    namelen = sizeof(ar_head.ar_name);  | 
    ||
440  | 
    	if ((p = malloc(sizeof(ar_head.ar_name))) == NULL) { | 
    ||
441  | 
    		warn("%s: malloc", name); | 
    ||
442  | 
    MUNMAP(symdef, len);  | 
    ||
443  | 
    return (1);  | 
    ||
444  | 
    }  | 
    ||
445  | 
    |||
446  | 
    size = *(u_long *)symdef;  | 
    ||
447  | 
    prn = (struct ranlib *)(symdef + sizeof(u_long));  | 
    ||
448  | 
    eprn = prn + size / sizeof(*prn);  | 
    ||
449  | 
    strtab = symdef + sizeof(u_long) + size + sizeof(u_long);  | 
    ||
450  | 
    |||
451  | 
    	printf("\nArchive index:\n"); | 
    ||
452  | 
    	for (; prn < eprn; prn++) { | 
    ||
453  | 
    		if (fseeko(fp, prn->ran_off, SEEK_SET)) { | 
    ||
454  | 
    			warn("%s: fseeko", name); | 
    ||
455  | 
    rval = 1;  | 
    ||
456  | 
    break;  | 
    ||
457  | 
    }  | 
    ||
458  | 
    |||
459  | 
    if (fread(&ar_head, sizeof(ar_head), 1, fp) != 1 ||  | 
    ||
460  | 
    		    memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) { | 
    ||
461  | 
    			warnx("%s: member fseeko", name); | 
    ||
462  | 
    rval = 1;  | 
    ||
463  | 
    break;  | 
    ||
464  | 
    }  | 
    ||
465  | 
    |||
466  | 
    *p = '\0';  | 
    ||
467  | 
    		if (mmbr_name(&ar_head, &p, 0, &namelen, fp)) { | 
    ||
468  | 
    rval = 1;  | 
    ||
469  | 
    break;  | 
    ||
470  | 
    }  | 
    ||
471  | 
    |||
472  | 
    		printf("%s in %s\n", strtab + prn->ran_un.ran_strx, p); | 
    ||
473  | 
    }  | 
    ||
474  | 
    |||
475  | 
    free(p);  | 
    ||
476  | 
    MUNMAP(symdef, len);  | 
    ||
477  | 
    return (rval);  | 
    ||
478  | 
    }  | 
    ||
479  | 
    |||
480  | 
    /*  | 
    ||
481  | 
    * show_archive()  | 
    ||
482  | 
    * show symbols in the given archive file  | 
    ||
483  | 
    */  | 
    ||
484  | 
    int  | 
    ||
485  | 
    show_archive(int count, const char *fname, FILE *fp)  | 
    ||
486  | 
    { | 
    ||
487  | 
    6  | 
    struct ar_hdr ar_head;  | 
    |
488  | 
    3  | 
    union hdr exec_head;  | 
    |
489  | 
    int i, rval;  | 
    ||
490  | 
    off_t last_ar_off, foff, symtaboff;  | 
    ||
491  | 
    3  | 
    char *name;  | 
    |
492  | 
    3  | 
    int baselen, namelen;  | 
    |
493  | 
    u_long mmbrlen, symtablen;  | 
    ||
494  | 
    |||
495  | 
    3  | 
    baselen = strlen(fname) + 3;  | 
    |
496  | 
    ✗✓ | 3  | 
    if (posix_output)  | 
    
497  | 
    baselen += 2;  | 
    ||
498  | 
    3  | 
    namelen = sizeof(ar_head.ar_name);  | 
    |
499  | 
    ✗✓ | 3  | 
    if ((name = malloc(baselen + namelen)) == NULL)  | 
    
500  | 
    err(1, NULL);  | 
    ||
501  | 
    |||
502  | 
    rval = 0;  | 
    ||
503  | 
    3  | 
    nametab = NULL;  | 
    |
504  | 
    symtaboff = 0;  | 
    ||
505  | 
    symtablen = 0;  | 
    ||
506  | 
    |||
507  | 
    /* while there are more entries in the archive */  | 
    ||
508  | 
    ✓✓ | 123  | 
    	while (fread(&ar_head, sizeof(ar_head), 1, fp) == 1) { | 
    
509  | 
    /* bad archive entry - stop processing this archive */  | 
    ||
510  | 
    ✗✓ | 117  | 
    		if (memcmp(ar_head.ar_fmag, ARFMAG, sizeof(ar_head.ar_fmag))) { | 
    
511  | 
    			warnx("%s: bad format archive header", fname); | 
    ||
512  | 
    rval = 1;  | 
    ||
513  | 
    break;  | 
    ||
514  | 
    }  | 
    ||
515  | 
    |||
516  | 
    /* remember start position of current archive object */  | 
    ||
517  | 
    117  | 
    last_ar_off = ftello(fp);  | 
    |
518  | 
    117  | 
    mmbrlen = atol(ar_head.ar_size);  | 
    |
519  | 
    |||
520  | 
    ✗✓ | 234  | 
    if (strncmp(ar_head.ar_name, RANLIBMAG,  | 
    
521  | 
    117  | 
    		    sizeof(RANLIBMAG) - 1) == 0) { | 
    |
522  | 
    if (!issize && armap &&  | 
    ||
523  | 
    			    show_symdef(last_ar_off, mmbrlen, fname, fp)) { | 
    ||
524  | 
    rval = 1;  | 
    ||
525  | 
    break;  | 
    ||
526  | 
    }  | 
    ||
527  | 
    goto skip;  | 
    ||
528  | 
    ✓✓ | 234  | 
    } else if (strncmp(ar_head.ar_name, SYMTABMAG,  | 
    
529  | 
    117  | 
    		    sizeof(SYMTABMAG) - 1) == 0) { | 
    |
530  | 
    /* if nametab hasn't been seen yet -- doit later */  | 
    ||
531  | 
    ✓✗ | 3  | 
    			if (!nametab) { | 
    
532  | 
    symtablen = mmbrlen;  | 
    ||
533  | 
    symtaboff = last_ar_off;  | 
    ||
534  | 
    3  | 
    goto skip;  | 
    |
535  | 
    }  | 
    ||
536  | 
    |||
537  | 
    /* load the Sys5 long names table */  | 
    ||
538  | 
    ✗✓ | 228  | 
    } else if (strncmp(ar_head.ar_name, STRTABMAG,  | 
    
539  | 
    114  | 
    		    sizeof(STRTABMAG) - 1) == 0) { | 
    |
540  | 
    char *p;  | 
    ||
541  | 
    |||
542  | 
    			if ((nametab = malloc(mmbrlen)) == NULL) { | 
    ||
543  | 
    				warn("%s: nametab", fname); | 
    ||
544  | 
    rval = 1;  | 
    ||
545  | 
    break;  | 
    ||
546  | 
    }  | 
    ||
547  | 
    |||
548  | 
    			if (fread(nametab, mmbrlen, (size_t)1, fp) != 1) { | 
    ||
549  | 
    				warnx("%s: premature EOF", fname); | 
    ||
550  | 
    rval = 1;  | 
    ||
551  | 
    break;  | 
    ||
552  | 
    }  | 
    ||
553  | 
    |||
554  | 
    for (p = nametab, i = mmbrlen; i--; p++)  | 
    ||
555  | 
    if (*p == '\n')  | 
    ||
556  | 
    *p = '\0';  | 
    ||
557  | 
    |||
558  | 
    if (issize || !armap || !symtablen || !symtaboff)  | 
    ||
559  | 
    goto skip;  | 
    ||
560  | 
    }  | 
    ||
561  | 
    #ifdef __mips64  | 
    ||
562  | 
    else if (memcmp(ar_head.ar_name, SYM64MAG,  | 
    ||
563  | 
    		    sizeof(ar_head.ar_name)) == 0) { | 
    ||
564  | 
    /* IRIX6-compatible archive map */  | 
    ||
565  | 
    goto skip;  | 
    ||
566  | 
    }  | 
    ||
567  | 
    #endif  | 
    ||
568  | 
    |||
569  | 
    ✗✓ | 114  | 
    		if (!issize && armap && symtablen && symtaboff) { | 
    
570  | 
    			if (show_symtab(symtaboff, symtablen, fname, fp)) { | 
    ||
571  | 
    rval = 1;  | 
    ||
572  | 
    break;  | 
    ||
573  | 
    			} else { | 
    ||
574  | 
    symtaboff = 0;  | 
    ||
575  | 
    symtablen = 0;  | 
    ||
576  | 
    }  | 
    ||
577  | 
    }  | 
    ||
578  | 
    |||
579  | 
    /*  | 
    ||
580  | 
    * construct a name of the form "archive.a:obj.o:" for the  | 
    ||
581  | 
    * current archive entry if the object name is to be printed  | 
    ||
582  | 
    * on each output line  | 
    ||
583  | 
    */  | 
    ||
584  | 
    114  | 
    *name = '\0';  | 
    |
585  | 
    ✗✓ | 114  | 
    if (posix_output)  | 
    
586  | 
    snprintf(name, baselen - 1, "%s[", fname);  | 
    ||
587  | 
    ✗✓ | 114  | 
    else if (count > 1)  | 
    
588  | 
    snprintf(name, baselen - 1, "%s:", fname);  | 
    ||
589  | 
    |||
590  | 
    ✗✓ | 114  | 
    		if (mmbr_name(&ar_head, &name, baselen, &namelen, fp)) { | 
    
591  | 
    rval = 1;  | 
    ||
592  | 
    break;  | 
    ||
593  | 
    }  | 
    ||
594  | 
    |||
595  | 
    ✗✓ | 114  | 
    if (posix_output)  | 
    
596  | 
    strlcat(name, "]", baselen + namelen);  | 
    ||
597  | 
    |||
598  | 
    114  | 
    foff = ftello(fp);  | 
    |
599  | 
    |||
600  | 
    /* get and check current object's header */  | 
    ||
601  | 
    ✗✓ | 228  | 
    if (fread((char *)&exec_head, sizeof(exec_head),  | 
    
602  | 
    114  | 
    		    (size_t)1, fp) != 1) { | 
    |
603  | 
    			warnx("%s: premature EOF", fname); | 
    ||
604  | 
    rval = 1;  | 
    ||
605  | 
    break;  | 
    ||
606  | 
    }  | 
    ||
607  | 
    |||
608  | 
    114  | 
    rval |= show_file(2, non_object_warning, name, fp, foff, &exec_head);  | 
    |
609  | 
    /*  | 
    ||
610  | 
    * skip to next archive object - it starts at the next  | 
    ||
611  | 
    * even byte boundary  | 
    ||
612  | 
    */  | 
    ||
613  | 
    #define even(x) (((x) + 1) & ~1)  | 
    ||
614  | 
    ✓✗ | 117  | 
    skip:		if (fseeko(fp, last_ar_off + even(mmbrlen), SEEK_SET)) { | 
    
615  | 
    			warn("%s", fname); | 
    ||
616  | 
    rval = 1;  | 
    ||
617  | 
    break;  | 
    ||
618  | 
    }  | 
    ||
619  | 
    }  | 
    ||
620  | 
    3  | 
    free(nametab);  | 
    |
621  | 
    3  | 
    nametab = NULL;  | 
    |
622  | 
    3  | 
    free(name);  | 
    |
623  | 
    3  | 
    return(rval);  | 
    |
624  | 
    3  | 
    }  | 
    |
625  | 
    |||
626  | 
    char *stab;  | 
    ||
627  | 
    |||
628  | 
    /*  | 
    ||
629  | 
    * show_file()  | 
    ||
630  | 
    * show symbols from the object file pointed to by fp. The current  | 
    ||
631  | 
    * file pointer for fp is expected to be at the beginning of an object  | 
    ||
632  | 
    * file header.  | 
    ||
633  | 
    */  | 
    ||
634  | 
    int  | 
    ||
635  | 
    show_file(int count, int warn_fmt, const char *name, FILE *fp, off_t foff, union hdr *head)  | 
    ||
636  | 
    { | 
    ||
637  | 
    28292  | 
    u_long text, data, bss, total;  | 
    |
638  | 
    14146  | 
    struct xnlist *np, *names, **snames;  | 
    |
639  | 
    14146  | 
    int i, nrawnames, nnames;  | 
    |
640  | 
    14146  | 
    size_t stabsize;  | 
    |
641  | 
    |||
642  | 
    ✓✗✓✗ ✓✗✓✗ ✗✗  | 
    56584  | 
    if (IS_ELF(head->elf32) &&  | 
    
643  | 
    ✗✓ | 14146  | 
    head->elf32.e_ident[EI_CLASS] == ELFCLASS32 &&  | 
    
644  | 
    	    head->elf32.e_ident[EI_VERSION] == ELF_TARG_VER) { | 
    ||
645  | 
    void *shdr;  | 
    ||
646  | 
    |||
647  | 
    if (!(shdr = elf32_load_shdrs(name, fp, foff, &head->elf32)))  | 
    ||
648  | 
    return (1);  | 
    ||
649  | 
    |||
650  | 
    i = issize?  | 
    ||
651  | 
    elf32_size(&head->elf32, shdr, &text, &data, &bss) :  | 
    ||
652  | 
    elf32_symload(name, fp, foff, &head->elf32, shdr,  | 
    ||
653  | 
    &names, &snames, &stabsize, &nrawnames);  | 
    ||
654  | 
    free(shdr);  | 
    ||
655  | 
    if (i)  | 
    ||
656  | 
    return (i);  | 
    ||
657  | 
    |||
658  | 
    ✗✗✓✗ ✓✗✓✗ ✓✗✓✗  | 
    70730  | 
    } else if (IS_ELF(head->elf64) &&  | 
    
659  | 
    ✓✗ | 14146  | 
    head->elf64.e_ident[EI_CLASS] == ELFCLASS64 &&  | 
    
660  | 
    14146  | 
    	    head->elf64.e_ident[EI_VERSION] == ELF_TARG_VER) { | 
    |
661  | 
    void *shdr;  | 
    ||
662  | 
    |||
663  | 
    ✗✓ | 14146  | 
    if (!(shdr = elf64_load_shdrs(name, fp, foff, &head->elf64)))  | 
    
664  | 
    return (1);  | 
    ||
665  | 
    |||
666  | 
    ✗✓ | 42438  | 
    i = issize?  | 
    
667  | 
    elf64_size(&head->elf64, shdr, &text, &data, &bss) :  | 
    ||
668  | 
    14146  | 
    elf64_symload(name, fp, foff, &head->elf64, shdr,  | 
    |
669  | 
    &names, &snames, &stabsize, &nrawnames);  | 
    ||
670  | 
    14146  | 
    free(shdr);  | 
    |
671  | 
    ✗✓ | 14146  | 
    if (i)  | 
    
672  | 
    return (i);  | 
    ||
673  | 
    ✓✗ | 14146  | 
    	} else { | 
    
674  | 
    if (warn_fmt)  | 
    ||
675  | 
    			warnx("%s: bad format", name); | 
    ||
676  | 
    return (1);  | 
    ||
677  | 
    }  | 
    ||
678  | 
    |||
679  | 
    ✗✓ | 14146  | 
    	if (issize) { | 
    
680  | 
    static int first = 1;  | 
    ||
681  | 
    |||
682  | 
    		if (first) { | 
    ||
683  | 
    first = 0;  | 
    ||
684  | 
    			printf("text\tdata\tbss\tdec\thex\n"); | 
    ||
685  | 
    }  | 
    ||
686  | 
    |||
687  | 
    total = text + data + bss;  | 
    ||
688  | 
    		printf("%lu\t%lu\t%lu\t%lu\t%lx", | 
    ||
689  | 
    text, data, bss, total, total);  | 
    ||
690  | 
    if (count > 1)  | 
    ||
691  | 
    			(void)printf("\t%s", name); | 
    ||
692  | 
    |||
693  | 
    total_text += text;  | 
    ||
694  | 
    total_data += data;  | 
    ||
695  | 
    total_bss += bss;  | 
    ||
696  | 
    total_total += total;  | 
    ||
697  | 
    |||
698  | 
    		printf("\n"); | 
    ||
699  | 
    return (0);  | 
    ||
700  | 
    }  | 
    ||
701  | 
    /* else we are nm */  | 
    ||
702  | 
    |||
703  | 
    /*  | 
    ||
704  | 
    * it seems that string table is sequential  | 
    ||
705  | 
    * relative to the symbol table order  | 
    ||
706  | 
    */  | 
    ||
707  | 
    ✗✓ | 14146  | 
    if (sfunc == NULL && usemmap)  | 
    
708  | 
    (void)madvise(stab, stabsize, MADV_SEQUENTIAL);  | 
    ||
709  | 
    |||
710  | 
    /*  | 
    ||
711  | 
    * fix up the symbol table and filter out unwanted entries  | 
    ||
712  | 
    *  | 
    ||
713  | 
    * common symbols are characterized by a n_type of N_UNDF and a  | 
    ||
714  | 
    * non-zero n_value -- change n_type to N_COMM for all such  | 
    ||
715  | 
    * symbols to make life easier later.  | 
    ||
716  | 
    *  | 
    ||
717  | 
    * filter out all entries which we don't want to print anyway  | 
    ||
718  | 
    */  | 
    ||
719  | 
    ✓✓ | 1277930  | 
    	for (np = names, i = nnames = 0; i < nrawnames; np++, i++) { | 
    
720  | 
    /*  | 
    ||
721  | 
    * make n_un.n_name a character pointer by adding the string  | 
    ||
722  | 
    * table's base to n_un.n_strx  | 
    ||
723  | 
    *  | 
    ||
724  | 
    * don't mess with zero offsets  | 
    ||
725  | 
    */  | 
    ||
726  | 
    ✓✗ | 624819  | 
    if (np->nl.n_un.n_strx)  | 
    
727  | 
    624819  | 
    np->nl.n_un.n_name = stab + np->nl.n_un.n_strx;  | 
    |
728  | 
    else  | 
    ||
729  | 
    np->nl.n_un.n_name = "";  | 
    ||
730  | 
    ✓✓✓✓ | 
    1233725  | 
    if (print_only_external_symbols && !IS_EXTERNAL(np->nl.n_type))  | 
    
731  | 
    continue;  | 
    ||
732  | 
    ✗✓✗✗ | 
    298347  | 
    if (print_only_undefined_symbols &&  | 
    
733  | 
    SYMBOL_TYPE(np->nl.n_type) != N_UNDF)  | 
    ||
734  | 
    continue;  | 
    ||
735  | 
    |||
736  | 
    298347  | 
    snames[nnames++] = np;  | 
    |
737  | 
    298347  | 
    }  | 
    |
738  | 
    |||
739  | 
    /* sort the symbol table if applicable */  | 
    ||
740  | 
    ✓✗ | 14146  | 
    if (sfunc)  | 
    
741  | 
    14146  | 
    qsort(snames, (size_t)nnames, sizeof(*snames), sfunc);  | 
    |
742  | 
    |||
743  | 
    ✓✓ | 14146  | 
    if (count > 1)  | 
    
744  | 
    14141  | 
    		(void)printf("\n%s:\n", name); | 
    |
745  | 
    |||
746  | 
    /* print out symbols */  | 
    ||
747  | 
    ✓✓ | 624986  | 
    for (i = 0; i < nnames; i++)  | 
    
748  | 
    298347  | 
    print_symbol(name, snames[i]);  | 
    |
749  | 
    |||
750  | 
    14146  | 
    free(snames);  | 
    |
751  | 
    14146  | 
    free(names);  | 
    |
752  | 
    ✓✗ | 42438  | 
    MUNMAP(stab, stabsize);  | 
    
753  | 
    14146  | 
    return(0);  | 
    |
754  | 
    14146  | 
    }  | 
    |
755  | 
    |||
756  | 
    char *  | 
    ||
757  | 
    symname(struct xnlist *sym)  | 
    ||
758  | 
    { | 
    ||
759  | 
    596694  | 
    return sym->nl.n_un.n_name;  | 
    |
760  | 
    }  | 
    ||
761  | 
    |||
762  | 
    /*  | 
    ||
763  | 
    * print_symbol()  | 
    ||
764  | 
    * show one symbol  | 
    ||
765  | 
    */  | 
    ||
766  | 
    void  | 
    ||
767  | 
    print_symbol(const char *name, struct xnlist *sym)  | 
    ||
768  | 
    { | 
    ||
769  | 
    ✓✓ | 596694  | 
    	if (print_file_each_line) { | 
    
770  | 
    ✗✓ | 298217  | 
    if (posix_output)  | 
    
771  | 
    			(void)printf("%s: ", name); | 
    ||
772  | 
    else  | 
    ||
773  | 
    298217  | 
    			(void)printf("%s:", name); | 
    |
774  | 
    }  | 
    ||
775  | 
    |||
776  | 
    ✗✓ | 298347  | 
    	if (posix_output) { | 
    
777  | 
    		(void)printf("%s %c ", symname(sym), typeletter(sym)); | 
    ||
778  | 
    if (SYMBOL_TYPE(sym->nl.n_type) != N_UNDF)  | 
    ||
779  | 
    (void)printf(posix_fmtstr, sym->nl.n_value,  | 
    ||
780  | 
    sym->n_size);  | 
    ||
781  | 
    		(void)printf("\n"); | 
    ||
782  | 
    	} else { | 
    ||
783  | 
    /*  | 
    ||
784  | 
    * handle undefined-only format especially (no space is  | 
    ||
785  | 
    * left for symbol values, no type field is printed)  | 
    ||
786  | 
    */  | 
    ||
787  | 
    ✓✗ | 298347  | 
    		if (!print_only_undefined_symbols) { | 
    
788  | 
    /* print symbol's value */  | 
    ||
789  | 
    ✓✓ | 298347  | 
    if (SYMBOL_TYPE(sym->nl.n_type) == N_UNDF)  | 
    
790  | 
    198536  | 
    				(void)printf("        "); | 
    |
791  | 
    else  | 
    ||
792  | 
    99811  | 
    				(void)printf("%08lx", sym->nl.n_value); | 
    |
793  | 
    |||
794  | 
    /* print type information */  | 
    ||
795  | 
    ✗✓ | 596694  | 
    if (show_extensions)  | 
    
796  | 
    298347  | 
    				(void)printf(" %c   ", typeletter(sym)); | 
    |
797  | 
    else  | 
    ||
798  | 
    298347  | 
    				(void)printf(" %c ", typeletter(sym)); | 
    |
799  | 
    }  | 
    ||
800  | 
    |||
801  | 
    298347  | 
    (void)puts(symname(sym));  | 
    |
802  | 
    }  | 
    ||
803  | 
    298347  | 
    }  | 
    |
804  | 
    |||
805  | 
    /*  | 
    ||
806  | 
    * typeletter()  | 
    ||
807  | 
    * return a description letter for the given basic type code of an  | 
    ||
808  | 
    * symbol table entry. The return value will be upper case for  | 
    ||
809  | 
    * external, lower case for internal symbols.  | 
    ||
810  | 
    */  | 
    ||
811  | 
    char  | 
    ||
812  | 
    typeletter(struct xnlist *np)  | 
    ||
813  | 
    { | 
    ||
814  | 
    596694  | 
    int ext = IS_EXTERNAL(np->nl.n_type);  | 
    |
815  | 
    |||
816  | 
    ✓✓ | 298347  | 
    if (np->nl.n_other)  | 
    
817  | 
    15083  | 
    return np->nl.n_other;  | 
    |
818  | 
    |||
819  | 
    ✗✓✓✓ ✓✓✗✓ ✗  | 
    283264  | 
    	switch(SYMBOL_TYPE(np->nl.n_type)) { | 
    
820  | 
    case N_ABS:  | 
    ||
821  | 
    return(ext? 'A' : 'a');  | 
    ||
822  | 
    case N_BSS:  | 
    ||
823  | 
    2989  | 
    return(ext? 'B' : 'b');  | 
    |
824  | 
    case N_COMM:  | 
    ||
825  | 
    1400  | 
    return(ext? 'C' : 'c');  | 
    |
826  | 
    case N_DATA:  | 
    ||
827  | 
    7707  | 
    return(ext? 'D' : 'd');  | 
    |
828  | 
    case N_FN:  | 
    ||
829  | 
    /* NOTE: N_FN == N_WARNING,  | 
    ||
830  | 
    * in this case, the N_EXT bit is to considered as  | 
    ||
831  | 
    * part of the symbol's type itself.  | 
    ||
832  | 
    */  | 
    ||
833  | 
    13567  | 
    return(ext? 'F' : 'W');  | 
    |
834  | 
    case N_TEXT:  | 
    ||
835  | 
    59077  | 
    return(ext? 'T' : 't');  | 
    |
836  | 
    case N_SIZE:  | 
    ||
837  | 
    return(ext? 'S' : 's');  | 
    ||
838  | 
    case N_UNDF:  | 
    ||
839  | 
    198524  | 
    return(ext? 'U' : 'u');  | 
    |
840  | 
    }  | 
    ||
841  | 
    	return('?'); | 
    ||
842  | 
    298347  | 
    }  | 
    |
843  | 
    |||
844  | 
    int  | 
    ||
845  | 
    fname(const void *a0, const void *b0)  | 
    ||
846  | 
    { | 
    ||
847  | 
    2793912  | 
    struct xnlist * const *a = a0, * const *b = b0;  | 
    |
848  | 
    |||
849  | 
    1396956  | 
    return(strcmp((*a)->nl.n_un.n_name, (*b)->nl.n_un.n_name));  | 
    |
850  | 
    }  | 
    ||
851  | 
    |||
852  | 
    int  | 
    ||
853  | 
    rname(const void *a0, const void *b0)  | 
    ||
854  | 
    { | 
    ||
855  | 
    struct xnlist * const *a = a0, * const *b = b0;  | 
    ||
856  | 
    |||
857  | 
    return(strcmp((*b)->nl.n_un.n_name, (*a)->nl.n_un.n_name));  | 
    ||
858  | 
    }  | 
    ||
859  | 
    |||
860  | 
    int  | 
    ||
861  | 
    value(const void *a0, const void *b0)  | 
    ||
862  | 
    { | 
    ||
863  | 
    struct xnlist * const *a = a0, * const *b = b0;  | 
    ||
864  | 
    |||
865  | 
    if (SYMBOL_TYPE((*a)->nl.n_type) == N_UNDF)  | 
    ||
866  | 
    if (SYMBOL_TYPE((*b)->nl.n_type) == N_UNDF)  | 
    ||
867  | 
    return(0);  | 
    ||
868  | 
    else  | 
    ||
869  | 
    return(-1);  | 
    ||
870  | 
    else if (SYMBOL_TYPE((*b)->nl.n_type) == N_UNDF)  | 
    ||
871  | 
    return(1);  | 
    ||
872  | 
    	if (rev) { | 
    ||
873  | 
    if ((*a)->nl.n_value == (*b)->nl.n_value)  | 
    ||
874  | 
    return(rname(a0, b0));  | 
    ||
875  | 
    return((*b)->nl.n_value > (*a)->nl.n_value ? 1 : -1);  | 
    ||
876  | 
    	} else { | 
    ||
877  | 
    if ((*a)->nl.n_value == (*b)->nl.n_value)  | 
    ||
878  | 
    return(fname(a0, b0));  | 
    ||
879  | 
    return((*a)->nl.n_value > (*b)->nl.n_value ? 1 : -1);  | 
    ||
880  | 
    }  | 
    ||
881  | 
    }  | 
    ||
882  | 
    |||
883  | 
    #define CPPFILT "/usr/bin/c++filt"  | 
    ||
884  | 
    |||
885  | 
    void  | 
    ||
886  | 
    pipe2cppfilt(void)  | 
    ||
887  | 
    { | 
    ||
888  | 
    10  | 
    int pip[2];  | 
    |
889  | 
    5  | 
    char *argv[2];  | 
    |
890  | 
    |||
891  | 
    5  | 
    argv[0] = "c++filt";  | 
    |
892  | 
    5  | 
    argv[1] = NULL;  | 
    |
893  | 
    |||
894  | 
    ✗✓ | 5  | 
    if (pipe(pip) == -1)  | 
    
895  | 
    err(1, "pipe");  | 
    ||
896  | 
    ✗✗✓ | 5  | 
    	switch(fork()) { | 
    
897  | 
    case -1:  | 
    ||
898  | 
    err(1, "fork");  | 
    ||
899  | 
    default:  | 
    ||
900  | 
    dup2(pip[0], 0);  | 
    ||
901  | 
    close(pip[0]);  | 
    ||
902  | 
    close(pip[1]);  | 
    ||
903  | 
    execve(CPPFILT, argv, NULL);  | 
    ||
904  | 
    err(1, "execve");  | 
    ||
905  | 
    case 0:  | 
    ||
906  | 
    5  | 
    dup2(pip[1], 1);  | 
    |
907  | 
    5  | 
    close(pip[1]);  | 
    |
908  | 
    5  | 
    close(pip[0]);  | 
    |
909  | 
    }  | 
    ||
910  | 
    5  | 
    }  | 
    |
911  | 
    |||
912  | 
    void  | 
    ||
913  | 
    usage(void)  | 
    ||
914  | 
    { | 
    ||
915  | 
    extern char *__progname;  | 
    ||
916  | 
    |||
917  | 
    if (issize)  | 
    ||
918  | 
    fprintf(stderr, "usage: %s [-tw] [file ...]\n", __progname);  | 
    ||
919  | 
    else  | 
    ||
920  | 
    fprintf(stderr, "usage: %s [-AaCDegnoPprsuw] [-t d|o|x] [file ...]\n",  | 
    ||
921  | 
    __progname);  | 
    ||
922  | 
    exit(1);  | 
    ||
923  | 
    }  | 
    
| Generated by: GCOVR (Version 3.3) |