/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <unistd.h>
#include <elfedit.h>
#include <strings.h>
#include <debug.h>
#include <conv.h>
#include <syminfo_msg.h>
/*
* This module uses shared code for several of the commands.
* It is sometimes necessary to know which specific command
* is active.
*/
typedef enum {
#ifndef _ELF64
/*
* We supply this function for the msg module. Only one copy is needed.
*/
const char *
{
}
#endif
/*
* This function is supplied to elfedit through our elfedit_module_t
* definition. It translates the opaque elfedit_i18nhdl_t handles
* in our module interface into the actual strings for elfedit to
* use.
*
* note:
* This module uses Msg codes for its i18n handle type.
* So the translation is simply to use MSG_INTL() to turn
* it into a string and return it.
*/
static const char *
{
}
/*
* The sym_opt_t enum specifies a bit value for every optional
* argument allowed by a command in this module.
*/
typedef enum {
/* be referenced via DT_NEEDED */
/* dynamic entry */
/*
* A variable of type ARGSTATE is used by each command to maintain
* information about the syminfo section being used, as and for any
* auxiliary sections that are related to it. This helps us to ensure
* that we only fetch each section a single time:
* - More efficient
* - Prevents multiple ELFEDIT_MSG_DEBUG messages from
* being produced for a given section.
*/
typedef struct {
struct { /* Syminfo */
Word n;
} syminfo;
struct { /* Symbol table */
Word n;
} sym;
struct { /* String table */
} str;
struct { /* Dynamic section */
Word n;
} dynamic;
} ARGSTATE;
/*
* Standard argument processing for syminfo module
*
* entry
* obj_state, argc, argv - Standard command arguments
* optmask - Mask of allowed optional arguments.
* argstate - Address of ARGSTATE block to be initialized
*
* exit:
* On success, *argstate is initialized. On error,
* an error is issued and this routine does not return.
*
* note:
* Only the syminfo section is initially referenced by
* argstate. Use the argstate_add_XXX() routines below to
* access any other sections needed.
*/
static void
{
/* Add each new option to the options mask */
/*
* Usage error if there are too many plain arguments.
* - syminfo:dump accepts a single argument
* - syminfo:si_boundto accepts 2 arguments
* - syminfo:si_flags accepts an unbounded number
*/
/* If there may be an arbitrary amount of output, use a pager */
if (argc == 0)
/* Locate the syminfo section */
}
/*
* We maintain the state of the current syminfo table in a ARGSTATE
* structure. A syminfo is related to the dynamic symbol table, and
* can reference the dynamic section of the object. We don't look those
* things up unless we actually need them, both to be efficient, and
* to prevent duplicate ELFEDIT_MSG_DEBUG messages from being issued
* as they are located. Hence, process_args() is used to initialze the
* state block with just the syminfo section, and then one of the
* argstate_add_XXX() functions is used as needed to fetch the
* additional sections.
*
* entry:
* argstate - State block for current symbol table.
*
* exit:
* If the needed auxiliary section is not found, an error is
* issued and the argstate_add_XXX() routine does not return.
* Otherwise, the fields in argstate have been filled in, ready
* for use.
*
*/
static void
{
return;
}
static void
{
return;
}
static void
{
return;
}
/*
* Display syminfo section entries in the style used by elfdump.
*
* entry:
* argstate - State block for current symbol table.
* ndx - Index of first symbol to display
* cnt - Number of symbols to display
*/
static void
{
/*
* Loop through the syminfo entries.
*/
ELFEDIT_MSG_ERR, 0);
else
}
}
/*
* Print syminfo values, taking the calling command, and output style
* into account.
*
* entry:
* cmd - SYMINFO_CMD_T_* value giving identify of caller
* autoprint - If True, output is only produced if the elfedit
* autoprint flag is set. If False, output is always produced.
* argstate - State block for current symbol table.
* ndx - Index of first symbol to display
* cnt - Number of symbols to display
*/
static void
{
(cnt == 0))
return;
/*
* Pick an output style. syminfo:dump is required to use the default
* style. The other commands use the current output style.
*/
/*
* If doing default output, use elfdump style where we
* show all symbol attributes. In this case, the command
* that called us doesn't matter
*/
if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
return;
}
switch (cmd) {
case SYMINFO_CMD_T_SI_BOUNDTO:
if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
/* Find the dynamic section and string table */
}
if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
switch (bndto) {
case SYMINFO_BT_SELF:
SYMINFO_BT_SELF, 1);
break;
case SYMINFO_BT_PARENT:
SYMINFO_BT_PARENT, 1);
break;
case SYMINFO_BT_NONE:
SYMINFO_BT_NONE, 1);
break;
}
(bndto < SYMINFO_BT_LOWRESERVE) &&
str);
continue;
}
}
/*
* If we reach this point, we are either in numeric
* mode, or we were unable to find a string above.
* In either case, output as integer.
*/
}
break;
case SYMINFO_CMD_T_SI_FLAGS:
if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
CONV_FMT_NOBKT, &buf));
} else {
}
}
break;
}
}
/*
* Convert the given argument string into a symbol table index.
*
* entry:
* argstate - State block for current symbol table.
* arg - String containing symbol index argument.
*
* exit:
* On success, returns the symbol index. On failure, an error
* is issued and this routine does not return.
*/
static Word
{
/*
* If the -symndx option was specified, arg is an index
* into the symbol table.
*/
/*
* arg is a symbol name. Return the index of the first symbol
* that matches
*/
return (symndx);
}
/*
* Given a string argument representing an object, return the index of
* the dynamic section that should be used for the si_boundto value.
*/
static Half
{
int have_string;
/* Locate DT_SUNW_STRPAD element if present and locate the DT_NULLs */
null_cnt = 0;
case DT_NULL:
/* Count all the nulls, remember the first one */
null_cnt++;
break;
case DT_SUNW_STRPAD:
ELFOSABI_SOLARIS, 0))
break;
}
}
/*
* Look up the string in the string table and get its offset. If
* this succeeds, then it is possible that there is a DT_NEEDED
* dynamic entry that references it.
*/
if (have_string) {
goto done;
}
}
/*
* It doesn't already exist. We might be able to add a DT_NEEDED
* to the dynamic section if an extra DT_NULL is available.
* Otherwise, we have to fail here.
*/
if (null_cnt < 2)
/*
* If the string is not already in the string table, try to
* insert it. If it succeeds, we will convert the DT_NULL.
* Otherwise, an error will be issued and control will not
* return here.
*/
if (!have_string)
/* Convert the extra DT_NULL */
0, &inv_buf));
done:
return (ndx);
}
/*
* Common body for the syminfo: module commands. These commands
* share a large amount of common behavior, so it is convenient
* to centralize things and use the cmd argument to handle the
* small differences.
*
* entry:
* cmd - One of the SYMINFO_CMD_T_* constants listed above, specifying
* which command to implement.
* obj_state, argc, argv - Standard command arguments
*/
static elfedit_cmdret_t
{
/* If there are no arguments, dump the whole table and return */
return (ELFEDIT_CMDRET_NONE);
}
/* If there is a single argument, display that item and return */
return (ELFEDIT_CMDRET_NONE);
}
/*
* Syminfo [0] holds the value SYMINFO_CURRENT, as a versioning
* technique. You're not supposed to mess with it.
*/
if (ndx == 0)
/* The second value supplies a new value for the item */
switch (cmd) {
/*
* SYMINFO_CMD_T_DUMP can't get here: It never has more than
* one argument, and is handled above.
*/
case SYMINFO_CMD_T_SI_BOUNDTO:
{
else
0, 0xffff, ELFEDIT_CONST_SYMINFO_BT);
} else {
}
}
break;
case SYMINFO_CMD_T_SI_FLAGS:
{
int i;
/* Collect the arguments */
/* Complement the value? */
/* Perform any requested bit operations */
/* Set the value */
0, &flags_buf1));
} else {
0, &flags_buf1),
}
}
break;
}
/*
* If we modified the syminfo section, tell libelf.
*/
if (ret == ELFEDIT_CMDRET_MOD)
/* Do autoprint */
return (ret);
}
/*
* Command completion functions for the various commands
*/
/*ARGSUSED*/
static void
{
int i;
/*
* If -needed option is not present, the second argument can be
* an SYMINFO_BT_ value.
*/
return;
/* Is -needed there? If so, no completion is possible so return */
for (i = 0; i < num_opt; i++)
return;
}
/*ARGSUSED*/
static void
{
/* The second argument can be an SYMINFO_FLG_ value */
}
/*
* Implementation functions for the commands
*/
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
/*ARGSUSED*/
{
/* sym:dump */
static const char *name_dump[] = {
};
/* MSG_INTL(MSG_OPTDESC_SYMNDX) */
SYMINFO_OPT_F_SYMNDX, 0 },
{ NULL }
};
{ MSG_ORIG(MSG_STR_SYM),
/* MSG_INTL(MSG_A1_SYM) */
{ NULL }
};
/* sym:si_boundto */
static const char *name_si_boundto[] = {
/* MSG_INTL(MSG_OPTDESC_NEEDED) */
SYMINFO_OPT_F_NEEDED, 0 },
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
/* MSG_INTL(MSG_OPTDESC_SYMNDX) */
SYMINFO_OPT_F_SYMNDX, 0 },
{ NULL }
};
{ MSG_ORIG(MSG_STR_SYM),
/* MSG_INTL(MSG_A1_SYM) */
/* MSG_INTL(MSG_A2_DESC_SI_BOUNDTO) */
{ NULL }
};
/* sym:si_flags */
static const char *name_si_flags[] = {
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
/* MSG_INTL(MSG_OPTDESC_SYMNDX) */
SYMINFO_OPT_F_SYMNDX, 0 },
{ NULL }
};
{ MSG_ORIG(MSG_STR_SYM),
/* MSG_INTL(MSG_A1_SYM) */
/* MSG_INTL(MSG_A2_DESC_SI_FLAGS) */
{ NULL }
};
/* sym:dump */
/* MSG_INTL(MSG_DESC_DUMP) */
/* MSG_INTL(MSG_HELP_DUMP) */
/* sym:si_boundto */
/* MSG_INTL(MSG_DESC_SI_BOUNDTO) */
/* MSG_INTL(MSG_HELP_SI_BOUNDTO) */
/* sym:si_flags */
/* MSG_INTL(MSG_DESC_SI_FLAGS) */
/* MSG_INTL(MSG_HELP_SI_FLAGS) */
{ NULL }
};
/* MSG_INTL(MSG_MOD_DESC) */
return (&module);
}