main.c revision 39773e466ff90ce703d7f52f3267d7e96c09c6f5
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Dump an elf file.
*/
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <libelf.h>
#include <link.h>
#include <stdarg.h>
#include <unistd.h>
#include <libgen.h>
#include <libintl.h>
#include <locale.h>
#include <errno.h>
#include <strings.h>
#include <debug.h>
#include <conv.h>
#include <msg.h>
#include <_elfdump.h>
/* MATCH is used to retain information about -N and -I options */
typedef enum {
MATCH_T_NAME, /* Record contains a name */
MATCH_T_NDX, /* Record contains a single index */
MATCH_T_RANGE /* Record contains an index range */
} MATCH_T;
typedef struct _match {
union {
const char *name; /* MATCH_T_NAME */
struct { /* MATCH_T_NDX and MATCH_T_RANGE */
int start;
int end; /* Only for MATCH_T_RANGE */
} ndx;
} value;
} MATCH;
/* List of MATCH records used by match() to implement -N and -I options */
const char *
{
}
/*
* Determine whether a symbol name should be demangled.
*/
const char *
{
if (flags & FLG_DEMANGLE)
return (Elf_demangle_name(name));
else
return ((char *)name);
}
/*
* Define our own standard error routine.
*/
void
{
}
/*
* The full usage message
*/
static void
{
}
/*
* Convert the ASCII representation of an index, or index range, into
* binary form, and store it in rec:
*
* index: An positive or 0 valued integer
* range: Two indexes, separated by a ':' character, denoting
* a range of allowed values. If the second value is omitted,
* any values equal to or greater than the first will match.
*
* exit:
* On success, *rec is filled in with a MATCH_T_NDX or MATCH_T_RANGE
* value, and this function returns (1). On failure, the contents
* of *rec are undefined, and (0) is returned.
*/
int
{
char *endptr;
/* Value must use some of the input, and be 0 or positive */
return (0);
if (*str != ':') {
} else {
str++; /* Skip the ':' */
if (*str == '\0') {
} else {
return (0);
}
}
/* Syntax error if anything is left over */
if (*str != '\0')
return (0);
return (1);
}
/*
* Returns True (1) if the item with the given name or index should
* be displayed, and False (0) if it should not be.
*
* entry:
* strict - A strict match requires an explicit match to
* a user specified -I or -N option. A non-strict match
* succeeds if the match list is empty.
* name - Name of item under consideration, or NULL if the name
* should not be considered.
* ndx - if (ndx >= 0) index of item under consideration.
* A negative value indicates that the item has no index.
*
* exit:
* by one of the -N or -I command line options, or if no such option
* was used in the command invocation.
*/
int
{
/* If no match options were specified, allow everything */
return (1);
/* Run through the match records and check for a hit */
case MATCH_T_NAME:
return (1);
break;
case MATCH_T_NDX:
return (1);
break;
case MATCH_T_RANGE:
/*
* A range end value less than 0 means that any value
* above the start is acceptible.
*/
return (1);
break;
}
}
/* Nothing matched */
return (0);
}
/*
* Add an entry to match_list for use by match().
*
* Return True (1) for success. On failure, an error is written
* to stderr, and False (0) is returned.
*/
static int
{
return (0);
}
/* Insert at end of match_list */
if (match_list == NULL) {
match_list = rec;
} else {
;
}
return (1);
}
static void
{
else
}
static void
{
/*
* Determine if the archive symbol table itself is required.
*/
/*
* Get the archive symbol table.
*/
/*
* The arsym could be 0 even though there was no error.
* Print the error message only when there was
* real error from elf_getarsym().
*/
return;
}
}
/*
* Print the archive symbol table only when the archive symbol
* table exists and it was requested to print.
*/
if (arsym) {
char index[MAXNDXSIZE];
/*
* Print out all the symbol entries.
*/
/*
* For each object obtain an elf descriptor so that we
* can establish the members name. Note, we have had
* archives where the archive header has not been
* obtainable so be lenient with errors.
*/
if (_elf)
arhdr = 0;
ELF_C_READ, elf)) == 0) {
arhdr = 0;
arhdr = 0;
}
if (offset == 0)
}
/* LINTED */
MSG_INTL(MSG_STR_NULL)));
else
/* LINTED */
}
if (_elf)
/*
* If we only need the archive symbol table return.
*/
if ((flags & FLG_SYMBOLS) &&
return;
/*
* Reset elf descriptor in preparation for processing each
* member.
*/
if (offset)
}
/*
* Process each object within the archive.
*/
char name[MAXPATHLEN];
return;
}
case ELF_K_AR:
break;
case ELF_K_ELF:
break;
default:
break;
}
}
}
}
int
{
char *wname = 0;
/*
* If we're on a 64-bit kernel, try to exec a full 64-bit version of
* the binary. If successful, conv_check_native() won't return.
*/
/*
* Establish locale.
*/
opterr = 0;
switch (var) {
case 'C':
flags |= FLG_DEMANGLE;
break;
case 'c':
break;
case 'd':
flags |= FLG_DYNAMIC;
break;
case 'e':
break;
case 'G':
break;
case 'g':
break;
case 'H':
break;
case 'h':
break;
case 'I':
return (1);
}
return (1);
break;
case 'i':
flags |= FLG_INTERP;
break;
case 'k':
flags |= FLG_CHECKSUM;
break;
case 'l':
flags |= FLG_LONGNAME;
break;
case 'm':
break;
case 'N':
return (1);
break;
case 'n':
break;
case 'P':
flags |= FLG_FAKESHDR;
break;
case 'p':
break;
case 'r':
break;
case 'S':
break;
case 's':
flags |= FLG_SYMBOLS;
break;
case 'u':
flags |= FLG_UNWIND;
break;
case 'v':
flags |= FLG_VERSIONS;
break;
case 'w':
break;
case 'y':
flags |= FLG_SYMINFO;
break;
case '?':
detail_usage();
return (1);
default:
break;
}
}
/*
* Validate any arguments.
*/
flags |= FLG_EVERYTHING;
return (1);
}
}
return (1);
}
/*
* If the -l/-C option is specified, set up the liblddbg.so.
*/
if (flags & FLG_LONGNAME)
if (flags & FLG_DEMANGLE)
/*
* If the -w option has indicated an output file open it. It's
* arguable whether this option has much use when multiple files are
* being processed.
*/
if (wname) {
0666)) < 0) {
wfd = 0;
}
}
/*
* Open the input file and initialize the elf interface.
*/
continue;
}
(void) elf_version(EV_CURRENT);
continue;
}
if (var > 1)
case ELF_K_AR:
break;
case ELF_K_ELF:
break;
default:
break;
}
}
if (wfd)
return (0);
}