15aefb655Srie /*
25aefb655Srie * CDDL HEADER START
35aefb655Srie *
45aefb655Srie * The contents of this file are subject to the terms of the
55aefb655Srie * Common Development and Distribution License (the "License").
65aefb655Srie * You may not use this file except in compliance with the License.
75aefb655Srie *
85aefb655Srie * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95aefb655Srie * or http://www.opensolaris.org/os/licensing.
105aefb655Srie * See the License for the specific language governing permissions
115aefb655Srie * and limitations under the License.
125aefb655Srie *
135aefb655Srie * When distributing Covered Code, include this CDDL HEADER in each
145aefb655Srie * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155aefb655Srie * If applicable, add the following below this CDDL HEADER, with the
165aefb655Srie * fields enclosed by brackets "[]" replaced with your own identifying
175aefb655Srie * information: Portions Copyright [yyyy] [name of copyright owner]
185aefb655Srie *
195aefb655Srie * CDDL HEADER END
205aefb655Srie */
215aefb655Srie
225aefb655Srie /*
23ba7866cdSAli Bahrami * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
24*43379a28SAndy Fiddaman * Copyright 2024 Oxide Computer Company
255aefb655Srie */
265aefb655Srie
275aefb655Srie /*
285aefb655Srie * Dump an elf file.
295aefb655Srie */
305aefb655Srie #include <sys/param.h>
315aefb655Srie #include <fcntl.h>
325aefb655Srie #include <stdio.h>
33c809c407Sab196087 #include <stdlib.h>
34c809c407Sab196087 #include <ctype.h>
35ba7866cdSAli Bahrami #include <_libelf.h>
365aefb655Srie #include <link.h>
375aefb655Srie #include <stdarg.h>
385aefb655Srie #include <unistd.h>
395aefb655Srie #include <libgen.h>
405aefb655Srie #include <libintl.h>
415aefb655Srie #include <locale.h>
425aefb655Srie #include <errno.h>
435aefb655Srie #include <strings.h>
445aefb655Srie #include <debug.h>
455aefb655Srie #include <conv.h>
465aefb655Srie #include <msg.h>
475aefb655Srie #include <_elfdump.h>
48981a172dSab196087 #include <sys/elf_SPARC.h>
49981a172dSab196087 #include <sys/elf_amd64.h>
50*43379a28SAndy Fiddaman #include <sys/hexdump.h>
51981a172dSab196087
525aefb655Srie
5331fdd7caSab196087 const Cache cache_init = {NULL, NULL, NULL, NULL, 0};
545aefb655Srie
55c809c407Sab196087
56c809c407Sab196087
57981a172dSab196087 /*
58981a172dSab196087 * The -I, -N, and -T options are called "match options", because
59981a172dSab196087 * they allow selecting the items to be displayed based on matching
60981a172dSab196087 * their index, name, or type.
61981a172dSab196087 *
62981a172dSab196087 * The ELF information to which -I, -N, or -T are applied in
63981a172dSab196087 * the current invocation is called the "match item".
64981a172dSab196087 */
65c809c407Sab196087 typedef enum {
66981a172dSab196087 MATCH_ITEM_PT, /* Program header (PT_) */
67981a172dSab196087 MATCH_ITEM_SHT /* Section header (SHT_) */
68981a172dSab196087 } match_item_t;
69981a172dSab196087
70981a172dSab196087 /* match_opt_t is used to note which match option was used */
71981a172dSab196087 typedef enum {
72981a172dSab196087 MATCH_OPT_NAME, /* Record contains a name */
73981a172dSab196087 MATCH_OPT_NDX, /* Record contains a single index */
74981a172dSab196087 MATCH_OPT_RANGE, /* Record contains an index range */
75981a172dSab196087 MATCH_OPT_TYPE, /* Record contains a type (shdr or phdr) */
76981a172dSab196087 } match_opt_t;
77c809c407Sab196087
78c809c407Sab196087 typedef struct _match {
79c809c407Sab196087 struct _match *next; /* Pointer to next item in list */
80981a172dSab196087 match_opt_t opt_type;
81c809c407Sab196087 union {
82981a172dSab196087 const char *name; /* MATCH_OPT_NAME */
83981a172dSab196087 struct { /* MATCH_OPT_NDX and MATCH_OPT_RANGE */
84c809c407Sab196087 int start;
85981a172dSab196087 int end; /* Only for MATCH_OPT_RANGE */
86c809c407Sab196087 } ndx;
87981a172dSab196087 uint32_t type; /* MATCH_OPT_TYPE */
88c809c407Sab196087 } value;
89981a172dSab196087 } match_rec_t;
90c809c407Sab196087
91981a172dSab196087 static struct {
92981a172dSab196087 match_item_t item_type; /* Type of item being matched */
93981a172dSab196087 match_rec_t *list; /* Records for (-I, -N, -T) options */
94981a172dSab196087 } match_state;
95981a172dSab196087
96981a172dSab196087
97981a172dSab196087
985aefb655Srie const char *
_elfdump_msg(Msg mid)995aefb655Srie _elfdump_msg(Msg mid)
1005aefb655Srie {
1015aefb655Srie return (gettext(MSG_ORIG(mid)));
1025aefb655Srie }
1035aefb655Srie
1045aefb655Srie /*
1055aefb655Srie * Determine whether a symbol name should be demangled.
1065aefb655Srie */
1075aefb655Srie const char *
demangle(const char * name,uint_t flags)1085aefb655Srie demangle(const char *name, uint_t flags)
1095aefb655Srie {
110981a172dSab196087 if (flags & FLG_CTL_DEMANGLE)
1115aefb655Srie return (Elf_demangle_name(name));
1125aefb655Srie else
1135aefb655Srie return ((char *)name);
1145aefb655Srie }
1155aefb655Srie
1165aefb655Srie /*
1175aefb655Srie * Define our own standard error routine.
1185aefb655Srie */
1195aefb655Srie void
failure(const char * file,const char * func)1205aefb655Srie failure(const char *file, const char *func)
1215aefb655Srie {
1225aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_FAILURE),
1235aefb655Srie file, func, elf_errmsg(elf_errno()));
1245aefb655Srie }
1255aefb655Srie
1265aefb655Srie /*
1275aefb655Srie * The full usage message
1285aefb655Srie */
1295aefb655Srie static void
detail_usage()1305aefb655Srie detail_usage()
1315aefb655Srie {
1325aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL1));
1335aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL2));
1345aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL3));
1355aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL4));
1365aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL5));
1375aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL6));
1385aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL7));
1395aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL8));
1405aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL9));
1415aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL10));
1425aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL11));
1435aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL12));
1445aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL13));
1455aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL14));
1465aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL15));
1475aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL16));
1485aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL17));
1495aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL18));
1505aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL19));
1515aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL20));
152d579eb63Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL21));
153c809c407Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL22));
154c809c407Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL23));
15539773e46Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL24));
156981a172dSab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL25));
1574f680cc6SAli Bahrami (void) fprintf(stderr, MSG_INTL(MSG_USAGE_DETAIL26));
158c809c407Sab196087 }
159c809c407Sab196087
160c809c407Sab196087 /*
161c6c9aed4Sab196087 * Output a block of raw data as hex bytes. Each row is given
162c6c9aed4Sab196087 * the index of the first byte in the row.
163c6c9aed4Sab196087 *
164c6c9aed4Sab196087 * entry:
165c6c9aed4Sab196087 * data - Pointer to first byte of data to be displayed
166c6c9aed4Sab196087 * n - # of bytes of data
167*43379a28SAndy Fiddaman * bytes_per_col - # of space separated bytes to output in each column.
168c6c9aed4Sab196087 * col_per_row - # of columns to output per row
169c6c9aed4Sab196087 *
170c6c9aed4Sab196087 * exit:
171*43379a28SAndy Fiddaman * The formatted data has been sent to stdout.
172c6c9aed4Sab196087 */
173*43379a28SAndy Fiddaman typedef struct {
174*43379a28SAndy Fiddaman uint_t dd_indent;
175*43379a28SAndy Fiddaman } dump_data_t;
176*43379a28SAndy Fiddaman
177*43379a28SAndy Fiddaman static int
dump_hex_bytes_cb(void * arg,uint64_t addr,const char * str,size_t len __unused)178*43379a28SAndy Fiddaman dump_hex_bytes_cb(void *arg, uint64_t addr, const char *str,
179*43379a28SAndy Fiddaman size_t len __unused)
180c6c9aed4Sab196087 {
181c6c9aed4Sab196087 char index[MAXNDXSIZE];
182*43379a28SAndy Fiddaman dump_data_t *dd = arg;
183*43379a28SAndy Fiddaman size_t index_width;
184c6c9aed4Sab196087
185*43379a28SAndy Fiddaman (void) snprintf(index, sizeof (index), MSG_ORIG(MSG_FMT_INDEX2),
186*43379a28SAndy Fiddaman EC_WORD(addr));
187c6c9aed4Sab196087 index_width = strlen(index);
188c6c9aed4Sab196087 index_width = S_ROUND(index_width, 8);
189c6c9aed4Sab196087 dbg_print(0, MSG_ORIG(MSG_HEXDUMP_ROW),
190*43379a28SAndy Fiddaman dd->dd_indent, MSG_ORIG(MSG_STR_EMPTY),
191*43379a28SAndy Fiddaman index_width, index, str);
192*43379a28SAndy Fiddaman return (0);
193c6c9aed4Sab196087 }
194*43379a28SAndy Fiddaman
195*43379a28SAndy Fiddaman void
dump_hex_bytes(const void * data,size_t n,int indent,int bytes_per_col,int col_per_row)196*43379a28SAndy Fiddaman dump_hex_bytes(const void *data, size_t n, int indent, int bytes_per_col,
197*43379a28SAndy Fiddaman int col_per_row)
198*43379a28SAndy Fiddaman {
199*43379a28SAndy Fiddaman hexdump_t h;
200*43379a28SAndy Fiddaman dump_data_t dd = {
201*43379a28SAndy Fiddaman .dd_indent = indent
202*43379a28SAndy Fiddaman };
203*43379a28SAndy Fiddaman hexdump_init(&h);
204*43379a28SAndy Fiddaman hexdump_set_grouping(&h, bytes_per_col);
205*43379a28SAndy Fiddaman hexdump_set_width(&h, bytes_per_col * col_per_row);
206*43379a28SAndy Fiddaman (void) hexdumph(&h, data, n, HDF_DOUBLESPACE, dump_hex_bytes_cb, &dd);
207*43379a28SAndy Fiddaman hexdump_fini(&h);
208c6c9aed4Sab196087 }
209c6c9aed4Sab196087
210c6c9aed4Sab196087 /*
211c809c407Sab196087 * Convert the ASCII representation of an index, or index range, into
212c809c407Sab196087 * binary form, and store it in rec:
213c809c407Sab196087 *
214c809c407Sab196087 * index: An positive or 0 valued integer
215c809c407Sab196087 * range: Two indexes, separated by a ':' character, denoting
216c809c407Sab196087 * a range of allowed values. If the second value is omitted,
217c809c407Sab196087 * any values equal to or greater than the first will match.
218c809c407Sab196087 *
219c809c407Sab196087 * exit:
220981a172dSab196087 * On success, *rec is filled in with a MATCH_OPT_NDX or MATCH_OPT_RANGE
221c809c407Sab196087 * value, and this function returns (1). On failure, the contents
222c809c407Sab196087 * of *rec are undefined, and (0) is returned.
223c809c407Sab196087 */
224c809c407Sab196087 int
process_index_opt(const char * str,match_rec_t * rec)225981a172dSab196087 process_index_opt(const char *str, match_rec_t *rec)
226c809c407Sab196087 {
227c809c407Sab196087 #define SKIP_BLANK for (; *str && isspace(*str); str++)
228c809c407Sab196087
229c809c407Sab196087 char *endptr;
230c809c407Sab196087
231c809c407Sab196087 rec->value.ndx.start = strtol(str, &endptr, 10);
232c809c407Sab196087 /* Value must use some of the input, and be 0 or positive */
233c809c407Sab196087 if ((str == endptr) || (rec->value.ndx.start < 0))
234c809c407Sab196087 return (0);
235c809c407Sab196087 str = endptr;
236c809c407Sab196087
237c809c407Sab196087 SKIP_BLANK;
238c809c407Sab196087 if (*str != ':') {
239981a172dSab196087 rec->opt_type = MATCH_OPT_NDX;
240c809c407Sab196087 } else {
241c809c407Sab196087 str++; /* Skip the ':' */
242981a172dSab196087 rec->opt_type = MATCH_OPT_RANGE;
243c809c407Sab196087 SKIP_BLANK;
244c809c407Sab196087 if (*str == '\0') {
245c809c407Sab196087 rec->value.ndx.end = -1; /* Indicates "to end" */
246c809c407Sab196087 } else {
247c809c407Sab196087 rec->value.ndx.end = strtol(str, &endptr, 10);
248c809c407Sab196087 if ((str == endptr) || (rec->value.ndx.end < 0))
249c809c407Sab196087 return (0);
250c809c407Sab196087 str = endptr;
251c809c407Sab196087 SKIP_BLANK;
252c809c407Sab196087 }
253c809c407Sab196087 }
254c809c407Sab196087
255c809c407Sab196087 /* Syntax error if anything is left over */
256c809c407Sab196087 if (*str != '\0')
257c809c407Sab196087 return (0);
258c809c407Sab196087
259c809c407Sab196087 return (1);
260c809c407Sab196087
261c809c407Sab196087 #undef SKIP_BLANK
262c809c407Sab196087 }
263c809c407Sab196087
264c809c407Sab196087 /*
2654f680cc6SAli Bahrami * Convert a string containing a specific type of ELF constant, or an ASCII
2664f680cc6SAli Bahrami * representation of a number, to an integer. Strings starting with '0'
267981a172dSab196087 * are taken to be octal, those staring with '0x' are hex, and all
268981a172dSab196087 * others are decimal.
269981a172dSab196087 *
270981a172dSab196087 * entry:
271981a172dSab196087 * str - String to be converted
2724f680cc6SAli Bahrami * ctype - Constant type
273981a172dSab196087 * v - Address of variable to receive resulting value.
274981a172dSab196087 *
275981a172dSab196087 * exit:
276981a172dSab196087 * On success, returns True (1) and *v is set to the value.
277981a172dSab196087 * On failure, returns False (0) and *v is undefined.
278981a172dSab196087 */
2794f680cc6SAli Bahrami typedef enum {
2804f680cc6SAli Bahrami ATOUI_PT,
2814f680cc6SAli Bahrami ATOUI_SHT,
2824f680cc6SAli Bahrami ATOUI_OSABI
2834f680cc6SAli Bahrami } atoui_type_t;
2844f680cc6SAli Bahrami
285981a172dSab196087 static int
atoui(const char * str,atoui_type_t type,uint32_t * v)2864f680cc6SAli Bahrami atoui(const char *str, atoui_type_t type, uint32_t *v)
287981a172dSab196087 {
2884f680cc6SAli Bahrami conv_strtol_uvalue_t uvalue;
289981a172dSab196087 char *endptr;
290981a172dSab196087
2914f680cc6SAli Bahrami if (conv_iter_strtol_init(str, &uvalue) != 0) {
2924f680cc6SAli Bahrami switch (type) {
2934f680cc6SAli Bahrami case ATOUI_PT:
2944f680cc6SAli Bahrami if (conv_iter_phdr_type(CONV_OSABI_ALL, CONV_FMT_ALT_CF,
2954f680cc6SAli Bahrami conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
2964f680cc6SAli Bahrami break;
2974f680cc6SAli Bahrami (void) conv_iter_phdr_type(CONV_OSABI_ALL,
2984f680cc6SAli Bahrami CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
2994f680cc6SAli Bahrami break;
3004f680cc6SAli Bahrami case ATOUI_SHT:
3014f680cc6SAli Bahrami if (conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
3024f680cc6SAli Bahrami CONV_FMT_ALT_CF, conv_iter_strtol, &uvalue) ==
3034f680cc6SAli Bahrami CONV_ITER_DONE)
3044f680cc6SAli Bahrami break;
3054f680cc6SAli Bahrami (void) conv_iter_sec_type(CONV_OSABI_ALL, CONV_MACH_ALL,
3064f680cc6SAli Bahrami CONV_FMT_ALT_NF, conv_iter_strtol, &uvalue);
3074f680cc6SAli Bahrami break;
3084f680cc6SAli Bahrami case ATOUI_OSABI:
3094f680cc6SAli Bahrami if (conv_iter_ehdr_osabi(CONV_FMT_ALT_CF,
3104f680cc6SAli Bahrami conv_iter_strtol, &uvalue) == CONV_ITER_DONE)
3114f680cc6SAli Bahrami break;
3124f680cc6SAli Bahrami (void) conv_iter_ehdr_osabi(CONV_FMT_ALT_NF,
3134f680cc6SAli Bahrami conv_iter_strtol, &uvalue);
3144f680cc6SAli Bahrami break;
3154f680cc6SAli Bahrami }
3164f680cc6SAli Bahrami if (uvalue.csl_found) {
3174f680cc6SAli Bahrami *v = uvalue.csl_value;
318981a172dSab196087 return (1);
3194f680cc6SAli Bahrami }
3204f680cc6SAli Bahrami }
321981a172dSab196087
322981a172dSab196087 *v = strtoull(str, &endptr, 0);
323981a172dSab196087
324981a172dSab196087 /* If the left over part contains anything but whitespace, fail */
325981a172dSab196087 for (; *endptr; endptr++)
326981a172dSab196087 if (!isspace(*endptr))
327981a172dSab196087 return (0);
328981a172dSab196087 return (1);
329981a172dSab196087 }
330981a172dSab196087
331981a172dSab196087 /*
332981a172dSab196087 * Called after getopt() processing is finished if there is a non-empty
333981a172dSab196087 * match list. Prepares the matching code for use.
334981a172dSab196087 *
335981a172dSab196087 * exit:
336981a172dSab196087 * Returns True (1) if no errors are encountered. Writes an
337981a172dSab196087 * error string to stderr and returns False (0) otherwise.
338981a172dSab196087 */
339981a172dSab196087 static int
match_prepare(char * argv0,uint_t flags)340981a172dSab196087 match_prepare(char *argv0, uint_t flags)
341981a172dSab196087 {
342981a172dSab196087 match_rec_t *list;
343981a172dSab196087 const char *str;
344981a172dSab196087 int minus_p = (flags & FLG_SHOW_PHDR) != 0;
3454f680cc6SAli Bahrami atoui_type_t atoui_type;
346981a172dSab196087
347981a172dSab196087 /*
348981a172dSab196087 * Flag ambiguous attempt to use match option with both -p and
349981a172dSab196087 * and one or more section SHOW options. In this case, we
350981a172dSab196087 * can't tell what type of item we're supposed to match against.
351981a172dSab196087 */
352981a172dSab196087 if (minus_p && (flags & FLG_MASK_SHOW_SHDR)) {
353981a172dSab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_AMBIG_MATCH),
354981a172dSab196087 basename(argv0));
355981a172dSab196087 return (0);
356981a172dSab196087 }
357981a172dSab196087
358981a172dSab196087 /* Set the match type, based on the presence of the -p option */
359981a172dSab196087 if (minus_p) {
360981a172dSab196087 match_state.item_type = MATCH_ITEM_PT;
3614f680cc6SAli Bahrami atoui_type = ATOUI_PT;
362981a172dSab196087 } else {
363981a172dSab196087 match_state.item_type = MATCH_ITEM_SHT;
3644f680cc6SAli Bahrami atoui_type = ATOUI_SHT;
365981a172dSab196087 }
366981a172dSab196087
367981a172dSab196087 /*
368981a172dSab196087 * Scan match list and perform any necessary fixups:
369981a172dSab196087 *
370981a172dSab196087 * MATCH_OPT_NAME: If -p is specified, convert MATCH_OPT_NAME (-N)
371981a172dSab196087 * requests into MATCH_OPT_TYPE (-T).
372981a172dSab196087 *
373981a172dSab196087 * MATCH_OPT_TYPE: Now that we know item type we are matching
374981a172dSab196087 * against, we can convert the string saved in the name
375981a172dSab196087 * field during getopt() processing into an integer and
376981a172dSab196087 * write it into the type field.
377981a172dSab196087 */
378981a172dSab196087 for (list = match_state.list; list; list = list->next) {
379981a172dSab196087 if ((list->opt_type == MATCH_OPT_NAME) && minus_p)
380981a172dSab196087 list->opt_type = MATCH_OPT_TYPE;
381981a172dSab196087
382981a172dSab196087 if (list->opt_type != MATCH_OPT_TYPE)
383981a172dSab196087 continue;
384981a172dSab196087
385981a172dSab196087 str = list->value.name;
3864f680cc6SAli Bahrami if (atoui(str, atoui_type, &list->value.type) == 0) {
387981a172dSab196087 const char *fmt = minus_p ?
388981a172dSab196087 MSG_INTL(MSG_ERR_BAD_T_PT) :
389981a172dSab196087 MSG_INTL(MSG_ERR_BAD_T_SHT);
390981a172dSab196087
391981a172dSab196087 (void) fprintf(stderr, fmt, basename(argv0), str);
392981a172dSab196087 return (0);
393981a172dSab196087 }
394981a172dSab196087 }
395981a172dSab196087
396981a172dSab196087 return (1);
397981a172dSab196087 }
398981a172dSab196087
399981a172dSab196087
400981a172dSab196087 /*
401c809c407Sab196087 * Returns True (1) if the item with the given name or index should
402c809c407Sab196087 * be displayed, and False (0) if it should not be.
403c809c407Sab196087 *
404c809c407Sab196087 * entry:
405981a172dSab196087 * match_flags - Bitmask specifying matching options, as described
406981a172dSab196087 * in _elfdump.h.
407981a172dSab196087 * name - If MATCH_F_NAME flag is set, name of item under
408981a172dSab196087 * consideration. Otherwise ignored.
409c809c407Sab196087 * should not be considered.
410981a172dSab196087 * ndx - If MATCH_F_NDX flag is set, index of item under consideration.
411981a172dSab196087 * type - If MATCH_F_TYPE is set, type of item under consideration.
412981a172dSab196087 * If MATCH_F_PHDR is set, this would be a program
413981a172dSab196087 * header type (PT_). Otherwise, a section header type (SHT_).
414c809c407Sab196087 *
415c809c407Sab196087 * exit:
416c809c407Sab196087 * True will be returned if the given name/index matches those given
417981a172dSab196087 * by one of the (-I, -N -T) command line options, or if no such option
418981a172dSab196087 * was used in the command invocation and MATCH_F_STRICT is not
419981a172dSab196087 * set.
420c809c407Sab196087 */
421c809c407Sab196087 int
match(match_flags_t match_flags,const char * name,uint_t ndx,uint_t type)422981a172dSab196087 match(match_flags_t match_flags, const char *name, uint_t ndx, uint_t type)
423c809c407Sab196087 {
424981a172dSab196087 match_item_t item_type = (match_flags & MATCH_F_PHDR) ?
425981a172dSab196087 MATCH_ITEM_PT : MATCH_ITEM_SHT;
426981a172dSab196087 match_rec_t *list;
427c809c407Sab196087
428981a172dSab196087 /*
429981a172dSab196087 * If there is no match list, then we use the MATCH_F_STRICT
430981a172dSab196087 * flag to decide what to return. In the strict case, we return
431981a172dSab196087 * False (0), in the normal case, True (1).
432981a172dSab196087 */
433981a172dSab196087 if (match_state.list == NULL)
434981a172dSab196087 return ((match_flags & MATCH_F_STRICT) == 0);
435981a172dSab196087
436981a172dSab196087 /*
437981a172dSab196087 * If item being checked is not the current match type,
438981a172dSab196087 * then allow it.
439981a172dSab196087 */
440981a172dSab196087 if (item_type != match_state.item_type)
441c809c407Sab196087 return (1);
442c809c407Sab196087
443c809c407Sab196087 /* Run through the match records and check for a hit */
444981a172dSab196087 for (list = match_state.list; list; list = list->next) {
445981a172dSab196087 switch (list->opt_type) {
446981a172dSab196087 case MATCH_OPT_NAME:
447981a172dSab196087 if (((match_flags & MATCH_F_NAME) == 0) ||
448981a172dSab196087 (name == NULL))
449981a172dSab196087 break;
450981a172dSab196087 if (strcmp(list->value.name, name) == 0)
451c809c407Sab196087 return (1);
452c809c407Sab196087 break;
453981a172dSab196087 case MATCH_OPT_NDX:
454981a172dSab196087 if ((match_flags & MATCH_F_NDX) &&
455981a172dSab196087 (ndx == list->value.ndx.start))
456c809c407Sab196087 return (1);
457c809c407Sab196087 break;
458981a172dSab196087 case MATCH_OPT_RANGE:
459c809c407Sab196087 /*
460c809c407Sab196087 * A range end value less than 0 means that any value
461c809c407Sab196087 * above the start is acceptible.
462c809c407Sab196087 */
463981a172dSab196087 if ((match_flags & MATCH_F_NDX) &&
464981a172dSab196087 (ndx >= list->value.ndx.start) &&
465c809c407Sab196087 ((list->value.ndx.end < 0) ||
466c809c407Sab196087 (ndx <= list->value.ndx.end)))
467c809c407Sab196087 return (1);
468c809c407Sab196087 break;
469981a172dSab196087
470981a172dSab196087 case MATCH_OPT_TYPE:
471981a172dSab196087 if ((match_flags & MATCH_F_TYPE) &&
472981a172dSab196087 (type == list->value.type))
473981a172dSab196087 return (1);
474981a172dSab196087 break;
475c809c407Sab196087 }
476c809c407Sab196087 }
477c809c407Sab196087
478c809c407Sab196087 /* Nothing matched */
479c809c407Sab196087 return (0);
480c809c407Sab196087 }
481c809c407Sab196087
482c809c407Sab196087 /*
483981a172dSab196087 * Add an entry to match_state.list for use by match(). This routine is for
484981a172dSab196087 * use during getopt() processing. It should not be called once
485981a172dSab196087 * match_prepare() has been called.
486c809c407Sab196087 *
487c809c407Sab196087 * Return True (1) for success. On failure, an error is written
488c809c407Sab196087 * to stderr, and False (0) is returned.
489c809c407Sab196087 */
490c809c407Sab196087 static int
add_match_record(char * argv0,match_rec_t * data)491981a172dSab196087 add_match_record(char *argv0, match_rec_t *data)
492c809c407Sab196087 {
493981a172dSab196087 match_rec_t *rec;
494981a172dSab196087 match_rec_t *list;
495c809c407Sab196087
496c809c407Sab196087 if ((rec = malloc(sizeof (*rec))) == NULL) {
497c809c407Sab196087 int err = errno;
498c809c407Sab196087 (void) fprintf(stderr, MSG_INTL(MSG_ERR_MALLOC),
499c809c407Sab196087 basename(argv0), strerror(err));
500c809c407Sab196087 return (0);
501c809c407Sab196087 }
502c809c407Sab196087
503c809c407Sab196087 *rec = *data;
504c809c407Sab196087
505981a172dSab196087 /* Insert at end of match_state.list */
506981a172dSab196087 if (match_state.list == NULL) {
507981a172dSab196087 match_state.list = rec;
508c809c407Sab196087 } else {
509981a172dSab196087 for (list = match_state.list; list->next != NULL;
510981a172dSab196087 list = list->next)
511c809c407Sab196087 ;
512c809c407Sab196087 list->next = rec;
513c809c407Sab196087 }
514c809c407Sab196087
515c809c407Sab196087 rec->next = NULL;
516c809c407Sab196087 return (1);
5175aefb655Srie }
5185aefb655Srie
519981a172dSab196087 static int
decide(const char * file,int fd,Elf * elf,uint_t flags,const char * wname,int wfd,uchar_t osabi)520981a172dSab196087 decide(const char *file, int fd, Elf *elf, uint_t flags,
5214f680cc6SAli Bahrami const char *wname, int wfd, uchar_t osabi)
5225aefb655Srie {
523981a172dSab196087 int r;
524981a172dSab196087
5255aefb655Srie if (gelf_getclass(elf) == ELFCLASS64)
5264f680cc6SAli Bahrami r = regular64(file, fd, elf, flags, wname, wfd, osabi);
5275aefb655Srie else
5284f680cc6SAli Bahrami r = regular32(file, fd, elf, flags, wname, wfd, osabi);
529981a172dSab196087
530981a172dSab196087 return (r);
5315aefb655Srie }
5325aefb655Srie
533981a172dSab196087 static int
archive(const char * file,int fd,Elf * elf,uint_t flags,const char * wname,int wfd,uchar_t osabi)534981a172dSab196087 archive(const char *file, int fd, Elf *elf, uint_t flags,
5354f680cc6SAli Bahrami const char *wname, int wfd, uchar_t osabi)
5365aefb655Srie {
5375aefb655Srie Elf_Cmd cmd = ELF_C_READ;
5385aefb655Srie Elf_Arhdr *arhdr;
5397e16fca0SAli Bahrami Elf *_elf = NULL;
5405aefb655Srie size_t ptr;
5417e16fca0SAli Bahrami Elf_Arsym *arsym = NULL;
5425aefb655Srie
5435aefb655Srie /*
544d579eb63Sab196087 * Determine if the archive symbol table itself is required.
5455aefb655Srie */
546981a172dSab196087 if ((flags & FLG_SHOW_SYMBOLS) &&
547981a172dSab196087 match(MATCH_F_NAME, MSG_ORIG(MSG_ELF_ARSYM), 0, 0)) {
5485aefb655Srie /*
5495aefb655Srie * Get the archive symbol table.
5505aefb655Srie */
5515aefb655Srie if (((arsym = elf_getarsym(elf, &ptr)) == 0) && elf_errno()) {
5525aefb655Srie /*
5535aefb655Srie * The arsym could be 0 even though there was no error.
5545aefb655Srie * Print the error message only when there was
5555aefb655Srie * real error from elf_getarsym().
5565aefb655Srie */
5575aefb655Srie failure(file, MSG_ORIG(MSG_ELF_GETARSYM));
558981a172dSab196087 return (0);
5595aefb655Srie }
5605aefb655Srie }
5615aefb655Srie
5625aefb655Srie /*
5635aefb655Srie * Print the archive symbol table only when the archive symbol
5645aefb655Srie * table exists and it was requested to print.
5655aefb655Srie */
5665aefb655Srie if (arsym) {
5675aefb655Srie size_t cnt;
5685aefb655Srie char index[MAXNDXSIZE];
5695aefb655Srie size_t offset = 0, _offset = 0;
570ba7866cdSAli Bahrami const char *fmt_arsym1, *fmt_arsym2;
5715aefb655Srie
5725aefb655Srie /*
573ba7866cdSAli Bahrami * Print out all the symbol entries. The format width used
574ba7866cdSAli Bahrami * corresponds to whether the archive symbol table is 32
575ba7866cdSAli Bahrami * or 64-bit. We see them via Elf_Arhdr as size_t values
576ba7866cdSAli Bahrami * in either case with no information loss (see the comments
577ba7866cdSAli Bahrami * in libelf/getarsym.c) so this is done simply to improve
578ba7866cdSAli Bahrami * the user presentation.
5795aefb655Srie */
580ba7866cdSAli Bahrami if (_elf_getarsymwordsize(elf) == 8) {
581ba7866cdSAli Bahrami dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_64));
582ba7866cdSAli Bahrami dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_64));
583ba7866cdSAli Bahrami
584ba7866cdSAli Bahrami fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_64);
585ba7866cdSAli Bahrami fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_64);
586ba7866cdSAli Bahrami } else {
587ba7866cdSAli Bahrami dbg_print(0, MSG_INTL(MSG_ARCHIVE_SYMTAB_32));
588ba7866cdSAli Bahrami dbg_print(0, MSG_INTL(MSG_ARCHIVE_FIELDS_32));
589ba7866cdSAli Bahrami
590ba7866cdSAli Bahrami fmt_arsym1 = MSG_ORIG(MSG_FMT_ARSYM1_32);
591ba7866cdSAli Bahrami fmt_arsym2 = MSG_ORIG(MSG_FMT_ARSYM2_32);
592ba7866cdSAli Bahrami }
5935aefb655Srie
5945aefb655Srie for (cnt = 0; cnt < ptr; cnt++, arsym++) {
5955aefb655Srie /*
5965aefb655Srie * For each object obtain an elf descriptor so that we
5975aefb655Srie * can establish the members name. Note, we have had
5985aefb655Srie * archives where the archive header has not been
5995aefb655Srie * obtainable so be lenient with errors.
6005aefb655Srie */
6015aefb655Srie if ((offset == 0) || ((arsym->as_off != 0) &&
6025aefb655Srie (arsym->as_off != _offset))) {
6035aefb655Srie
6045aefb655Srie if (_elf)
6055aefb655Srie (void) elf_end(_elf);
6065aefb655Srie
6075aefb655Srie if (elf_rand(elf, arsym->as_off) !=
6085aefb655Srie arsym->as_off) {
6095aefb655Srie failure(file, MSG_ORIG(MSG_ELF_RAND));
6107e16fca0SAli Bahrami arhdr = NULL;
6115aefb655Srie } else if ((_elf = elf_begin(fd,
6125aefb655Srie ELF_C_READ, elf)) == 0) {
6135aefb655Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN));
6147e16fca0SAli Bahrami arhdr = NULL;
6155aefb655Srie } else if ((arhdr = elf_getarhdr(_elf)) == 0) {
6165aefb655Srie failure(file,
6175aefb655Srie MSG_ORIG(MSG_ELF_GETARHDR));
6187e16fca0SAli Bahrami arhdr = NULL;
6195aefb655Srie }
6205aefb655Srie
6215aefb655Srie _offset = arsym->as_off;
6225aefb655Srie if (offset == 0)
6235aefb655Srie offset = _offset;
6245aefb655Srie }
6255aefb655Srie
6265aefb655Srie (void) snprintf(index, MAXNDXSIZE,
6275aefb655Srie MSG_ORIG(MSG_FMT_INDEX), EC_XWORD(cnt));
6285aefb655Srie if (arsym->as_off)
629ba7866cdSAli Bahrami dbg_print(0, fmt_arsym1, index,
630ba7866cdSAli Bahrami EC_XWORD(arsym->as_off),
631ba7866cdSAli Bahrami arhdr ? arhdr->ar_name :
6325aefb655Srie MSG_INTL(MSG_STR_UNKNOWN), (arsym->as_name ?
6335aefb655Srie demangle(arsym->as_name, flags) :
6345aefb655Srie MSG_INTL(MSG_STR_NULL)));
6355aefb655Srie else
636ba7866cdSAli Bahrami dbg_print(0, fmt_arsym2, index,
637ba7866cdSAli Bahrami EC_XWORD(arsym->as_off));
6385aefb655Srie }
6395aefb655Srie
6405aefb655Srie if (_elf)
6415aefb655Srie (void) elf_end(_elf);
6425aefb655Srie
6435aefb655Srie /*
6445aefb655Srie * If we only need the archive symbol table return.
6455aefb655Srie */
646981a172dSab196087 if ((flags & FLG_SHOW_SYMBOLS) &&
647981a172dSab196087 match(MATCH_F_STRICT | MATCH_F_NAME,
648981a172dSab196087 MSG_ORIG(MSG_ELF_ARSYM), -1, -1))
649981a172dSab196087 return (0);
6505aefb655Srie
6515aefb655Srie /*
6525aefb655Srie * Reset elf descriptor in preparation for processing each
6535aefb655Srie * member.
6545aefb655Srie */
6555aefb655Srie if (offset)
6565aefb655Srie (void) elf_rand(elf, offset);
6575aefb655Srie }
6585aefb655Srie
6595aefb655Srie /*
6605aefb655Srie * Process each object within the archive.
6615aefb655Srie */
6625aefb655Srie while ((_elf = elf_begin(fd, cmd, elf)) != NULL) {
6635aefb655Srie char name[MAXPATHLEN];
6645aefb655Srie
6655aefb655Srie if ((arhdr = elf_getarhdr(_elf)) == NULL) {
6665aefb655Srie failure(file, MSG_ORIG(MSG_ELF_GETARHDR));
667981a172dSab196087 return (0);
6685aefb655Srie }
6695aefb655Srie if (*arhdr->ar_name != '/') {
6705aefb655Srie (void) snprintf(name, MAXPATHLEN,
6715aefb655Srie MSG_ORIG(MSG_FMT_ARNAME), file, arhdr->ar_name);
6725aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTR), name);
6735aefb655Srie
6745aefb655Srie switch (elf_kind(_elf)) {
6755aefb655Srie case ELF_K_AR:
676981a172dSab196087 if (archive(name, fd, _elf, flags,
6774f680cc6SAli Bahrami wname, wfd, osabi) == 1)
678981a172dSab196087 return (1);
6795aefb655Srie break;
6805aefb655Srie case ELF_K_ELF:
681981a172dSab196087 if (decide(name, fd, _elf, flags,
6824f680cc6SAli Bahrami wname, wfd, osabi) == 1)
683981a172dSab196087 return (1);
6845aefb655Srie break;
6855aefb655Srie default:
6865aefb655Srie (void) fprintf(stderr,
6875aefb655Srie MSG_INTL(MSG_ERR_BADFILE), name);
6885aefb655Srie break;
6895aefb655Srie }
6905aefb655Srie }
6915aefb655Srie
6925aefb655Srie cmd = elf_next(_elf);
6935aefb655Srie (void) elf_end(_elf);
6945aefb655Srie }
695981a172dSab196087
696981a172dSab196087 return (0);
6975aefb655Srie }
6985aefb655Srie
6995aefb655Srie int
main(int argc,char ** argv,char ** envp)7005aefb655Srie main(int argc, char **argv, char **envp)
7015aefb655Srie {
7025aefb655Srie Elf *elf;
7035aefb655Srie int var, fd, wfd = 0;
704981a172dSab196087 char *wname = NULL;
7055aefb655Srie uint_t flags = 0;
706981a172dSab196087 match_rec_t match_data;
707981a172dSab196087 int ret;
7087879e8a6SToomas Soome uchar_t osabi = ELFOSABI_NONE;
7095aefb655Srie
7105aefb655Srie /*
7115aefb655Srie * Establish locale.
7125aefb655Srie */
7135aefb655Srie (void) setlocale(LC_MESSAGES, MSG_ORIG(MSG_STR_EMPTY));
7145aefb655Srie (void) textdomain(MSG_ORIG(MSG_SUNW_OST_SGS));
7155aefb655Srie
7165aefb655Srie (void) setvbuf(stdout, NULL, _IOLBF, 0);
7175aefb655Srie (void) setvbuf(stderr, NULL, _IOLBF, 0);
7185aefb655Srie
7195aefb655Srie opterr = 0;
7205aefb655Srie while ((var = getopt(argc, argv, MSG_ORIG(MSG_STR_OPTIONS))) != EOF) {
7215aefb655Srie switch (var) {
7225aefb655Srie case 'C':
723981a172dSab196087 flags |= FLG_CTL_DEMANGLE;
7245aefb655Srie break;
7255aefb655Srie case 'c':
726981a172dSab196087 flags |= FLG_SHOW_SHDR;
7275aefb655Srie break;
7285aefb655Srie case 'd':
729981a172dSab196087 flags |= FLG_SHOW_DYNAMIC;
7305aefb655Srie break;
7315aefb655Srie case 'e':
732981a172dSab196087 flags |= FLG_SHOW_EHDR;
7335aefb655Srie break;
7345aefb655Srie case 'G':
735981a172dSab196087 flags |= FLG_SHOW_GOT;
7365aefb655Srie break;
7375aefb655Srie case 'g':
738981a172dSab196087 flags |= FLG_SHOW_GROUP;
7395aefb655Srie break;
7405aefb655Srie case 'H':
741981a172dSab196087 flags |= FLG_SHOW_CAP;
7425aefb655Srie break;
7435aefb655Srie case 'h':
744981a172dSab196087 flags |= FLG_SHOW_HASH;
7455aefb655Srie break;
746c809c407Sab196087 case 'I':
747981a172dSab196087 if (!process_index_opt(optarg, &match_data))
748981a172dSab196087 goto usage_brief;
749c809c407Sab196087 if (!add_match_record(argv[0], &match_data))
750c809c407Sab196087 return (1);
751981a172dSab196087 flags |= FLG_CTL_MATCH;
752c809c407Sab196087 break;
7535aefb655Srie case 'i':
754981a172dSab196087 flags |= FLG_SHOW_INTERP;
7555aefb655Srie break;
7565aefb655Srie case 'k':
757981a172dSab196087 flags |= FLG_CALC_CHECKSUM;
7585aefb655Srie break;
7595aefb655Srie case 'l':
760981a172dSab196087 flags |= FLG_CTL_LONGNAME;
7615aefb655Srie break;
7625aefb655Srie case 'm':
763981a172dSab196087 flags |= FLG_SHOW_MOVE;
7645aefb655Srie break;
7655aefb655Srie case 'N':
766981a172dSab196087 match_data.opt_type = MATCH_OPT_NAME;
767c809c407Sab196087 match_data.value.name = optarg;
768c809c407Sab196087 if (!add_match_record(argv[0], &match_data))
769c809c407Sab196087 return (1);
770981a172dSab196087 flags |= FLG_CTL_MATCH;
7715aefb655Srie break;
7725aefb655Srie case 'n':
773981a172dSab196087 flags |= FLG_SHOW_NOTE;
7745aefb655Srie break;
7754f680cc6SAli Bahrami case 'O':
7764f680cc6SAli Bahrami {
7774f680cc6SAli Bahrami uint32_t val;
7784f680cc6SAli Bahrami
7794f680cc6SAli Bahrami /*
7804f680cc6SAli Bahrami * osabi is a uchar_t in the ELF header.
7814f680cc6SAli Bahrami * Don't accept any value that exceeds
7824f680cc6SAli Bahrami * that range.
7834f680cc6SAli Bahrami */
7844f680cc6SAli Bahrami if ((atoui(optarg, ATOUI_OSABI, &val) == 0) ||
7854f680cc6SAli Bahrami (val > 255)) {
7864f680cc6SAli Bahrami (void) fprintf(stderr,
7874f680cc6SAli Bahrami MSG_INTL(MSG_ERR_BAD_T_OSABI),
7884f680cc6SAli Bahrami basename(argv[0]), optarg);
7894f680cc6SAli Bahrami return (1);
7904f680cc6SAli Bahrami }
7914f680cc6SAli Bahrami osabi = val;
7924f680cc6SAli Bahrami }
7934f680cc6SAli Bahrami flags |= FLG_CTL_OSABI;
7944f680cc6SAli Bahrami break;
79539773e46Sab196087 case 'P':
796981a172dSab196087 flags |= FLG_CTL_FAKESHDR;
79739773e46Sab196087 break;
7985aefb655Srie case 'p':
799981a172dSab196087 flags |= FLG_SHOW_PHDR;
8005aefb655Srie break;
8015aefb655Srie case 'r':
802981a172dSab196087 flags |= FLG_SHOW_RELOC;
8035aefb655Srie break;
804d579eb63Sab196087 case 'S':
805981a172dSab196087 flags |= FLG_SHOW_SORT;
806d579eb63Sab196087 break;
8075aefb655Srie case 's':
808981a172dSab196087 flags |= FLG_SHOW_SYMBOLS;
809981a172dSab196087 break;
810981a172dSab196087 case 'T':
811981a172dSab196087 /*
812981a172dSab196087 * We can't evaluate the value yet, because
813981a172dSab196087 * we need to know if -p is used or not in
814981a172dSab196087 * order to tell if we're seeing section header
815981a172dSab196087 * or program header types. So, we save the
816981a172dSab196087 * string in the name field, and then convert
817981a172dSab196087 * it to a type integer in a following pass.
818981a172dSab196087 */
819981a172dSab196087 match_data.opt_type = MATCH_OPT_TYPE;
820981a172dSab196087 match_data.value.name = optarg;
821981a172dSab196087 if (!add_match_record(argv[0], &match_data))
822981a172dSab196087 return (1);
823981a172dSab196087 flags |= FLG_CTL_MATCH;
8245aefb655Srie break;
8255aefb655Srie case 'u':
826981a172dSab196087 flags |= FLG_SHOW_UNWIND;
8275aefb655Srie break;
8285aefb655Srie case 'v':
829981a172dSab196087 flags |= FLG_SHOW_VERSIONS;
8305aefb655Srie break;
8315aefb655Srie case 'w':
8325aefb655Srie wname = optarg;
8335aefb655Srie break;
8345aefb655Srie case 'y':
835981a172dSab196087 flags |= FLG_SHOW_SYMINFO;
8365aefb655Srie break;
8375aefb655Srie case '?':
8385aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF),
8395aefb655Srie basename(argv[0]));
8405aefb655Srie detail_usage();
8415aefb655Srie return (1);
8425aefb655Srie default:
8435aefb655Srie break;
8445aefb655Srie }
8455aefb655Srie }
8465aefb655Srie
847981a172dSab196087 /* -p and -w are mutually exclusive. -w only works with sections */
848981a172dSab196087 if (((flags & FLG_SHOW_PHDR) != 0) && (wname != NULL))
849981a172dSab196087 goto usage_brief;
850981a172dSab196087
851981a172dSab196087 /* If a match argument is present, prepare the match state */
852981a172dSab196087 if ((match_state.list != NULL) && (match_prepare(argv[0], flags) == 0))
8535aefb655Srie return (1);
854981a172dSab196087
855981a172dSab196087 /*
856981a172dSab196087 * Decide what to do if no options specifying something to
857981a172dSab196087 * show or do are present.
858981a172dSab196087 *
859981a172dSab196087 * If there is no -w and no match options, then we will set all
860981a172dSab196087 * the show flags, causing a full display of everything in the
861981a172dSab196087 * file that we know how to handle.
862981a172dSab196087 *
863981a172dSab196087 * Otherwise, if there is no match list, we generate a usage
864981a172dSab196087 * error and quit.
865981a172dSab196087 *
866981a172dSab196087 * In the case where there is a match list, we go ahead and call
867981a172dSab196087 * regular() anyway, leaving it to decide what to do. If -w is
868981a172dSab196087 * present, regular() will use the match list to handle it.
869981a172dSab196087 * In addition, in the absence of explicit show/calc flags, regular()
870981a172dSab196087 * will compare the section headers to the match list and use
871981a172dSab196087 * that to generate the FLG_ bits that will display the information
872981a172dSab196087 * specified by the match list.
873981a172dSab196087 */
874981a172dSab196087 if ((flags & ~FLG_MASK_CTL) == 0) {
875981a172dSab196087 if (!wname && (match_state.list == NULL))
876981a172dSab196087 flags |= FLG_MASK_SHOW;
877981a172dSab196087 else if (match_state.list == NULL)
878981a172dSab196087 goto usage_brief;
8795aefb655Srie }
8805aefb655Srie
881981a172dSab196087 /* There needs to be at least 1 filename left following the options */
882981a172dSab196087 if ((var = argc - optind) == 0)
883981a172dSab196087 goto usage_brief;
8845aefb655Srie
8855aefb655Srie /*
8865aefb655Srie * If the -l/-C option is specified, set up the liblddbg.so.
8875aefb655Srie */
888981a172dSab196087 if (flags & FLG_CTL_LONGNAME)
8895aefb655Srie dbg_desc->d_extra |= DBG_E_LONG;
890981a172dSab196087 if (flags & FLG_CTL_DEMANGLE)
8915aefb655Srie dbg_desc->d_extra |= DBG_E_DEMANGLE;
8925aefb655Srie
8935aefb655Srie /*
8945aefb655Srie * If the -w option has indicated an output file open it. It's
8955aefb655Srie * arguable whether this option has much use when multiple files are
8965aefb655Srie * being processed.
897981a172dSab196087 *
898981a172dSab196087 * If wname is non-NULL, we know that -p was not specified, due
899981a172dSab196087 * to the test above.
9005aefb655Srie */
9015aefb655Srie if (wname) {
9025aefb655Srie if ((wfd = open(wname, (O_RDWR | O_CREAT | O_TRUNC),
9035aefb655Srie 0666)) < 0) {
9045aefb655Srie int err = errno;
9055aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN),
9065aefb655Srie wname, strerror(err));
907981a172dSab196087 return (1);
9085aefb655Srie }
9095aefb655Srie }
9105aefb655Srie
9115aefb655Srie /*
912981a172dSab196087 * Open the input file, initialize the elf interface, and
913981a172dSab196087 * process it.
9145aefb655Srie */
915981a172dSab196087 ret = 0;
916981a172dSab196087 for (; (optind < argc) && (ret == 0); optind++) {
9175aefb655Srie const char *file = argv[optind];
9185aefb655Srie
9195aefb655Srie if ((fd = open(argv[optind], O_RDONLY)) == -1) {
9205aefb655Srie int err = errno;
9215aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_OPEN),
9225aefb655Srie file, strerror(err));
9235aefb655Srie continue;
9245aefb655Srie }
9255aefb655Srie (void) elf_version(EV_CURRENT);
9265aefb655Srie if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
9275aefb655Srie failure(file, MSG_ORIG(MSG_ELF_BEGIN));
9285aefb655Srie (void) close(fd);
9295aefb655Srie continue;
9305aefb655Srie }
9315aefb655Srie
9325aefb655Srie if (var > 1)
9335aefb655Srie dbg_print(0, MSG_ORIG(MSG_FMT_NLSTRNL), file);
9345aefb655Srie
9355aefb655Srie switch (elf_kind(elf)) {
9365aefb655Srie case ELF_K_AR:
9374f680cc6SAli Bahrami ret = archive(file, fd, elf, flags, wname, wfd, osabi);
9385aefb655Srie break;
9395aefb655Srie case ELF_K_ELF:
9404f680cc6SAli Bahrami ret = decide(file, fd, elf, flags, wname, wfd, osabi);
9415aefb655Srie break;
9425aefb655Srie default:
9435aefb655Srie (void) fprintf(stderr, MSG_INTL(MSG_ERR_BADFILE), file);
9445aefb655Srie break;
9455aefb655Srie }
9465aefb655Srie
9475aefb655Srie (void) close(fd);
9485aefb655Srie (void) elf_end(elf);
9495aefb655Srie }
9505aefb655Srie
9515aefb655Srie if (wfd)
9525aefb655Srie (void) close(wfd);
953981a172dSab196087 return (ret);
954981a172dSab196087
955981a172dSab196087 usage_brief:
956981a172dSab196087 /* Control comes here for a simple usage message and exit */
957981a172dSab196087 (void) fprintf(stderr, MSG_INTL(MSG_USAGE_BRIEF),
958981a172dSab196087 basename(argv[0]));
959981a172dSab196087 return (1);
960981a172dSab196087
9615aefb655Srie }
962