/*
* 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 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
* Copyright 2012 Milan Jurik. All rights reserved.
*/
#include <ctype.h>
#include <elfedit.h>
#include <sys/elf_SPARC.h>
#include <strings.h>
#include <debug.h>
#include <conv.h>
#include <cap_msg.h>
/*
* Capabilities section
*/
/*
* This module uses shared code for several of the commands.
* It is sometimes necessary to know which specific command
* is active.
*/
typedef enum {
/* Dump command, used as module default to display dynamic section */
/* Commands that do not correspond directly to a specific DT tag */
/* Commands that embody tag specific knowledge */
} CAP_CMD_T;
#ifndef _ELF64
/*
* We supply this function for the msg module
*/
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 cap_opt_t enum specifies a bit value for every optional
* argument allowed by a command in this module.
*/
typedef enum {
/* capabilities group */
/* not name */
} cap_opt_t;
/*
* A variable of type ARGSTATE is used by each command to maintain
* information about the arguments and related things. It is
* initialized by process_args(), and used by the other routines.
*/
typedef struct {
struct {
} cap;
struct { /* String table */
} str;
} ARGSTATE;
/*
* Lookup the string table associated with the capabilities
* section.
*
* entry:
* argstate - Argument state block
* required - If TRUE, failure to obtain a string table should be
* considered to be an error.
*
* exit:
* If a string table is found, argstate->str is updated to reference it.
* If no string table is found, and required is TRUE, an error is issued
* and this routine does not return to the caller. Otherwise, this
* routine returns quietly without modifying argstate->str.
*/
static void
{
/* String table already loaded? */
return;
/*
* We can't proceed if the capabilities section does not have
* an associated string table.
*/
/* Error if the operation requires a string table */
if (required)
return;
}
}
/*
* Given an index into the capabilities array, locate the index of the
* initial element in its capabilities group, and the number of elements
* in the group.
*/
static void
{
*ret_end_ndx = ndx;
/*
* The group starts with a non-NULL tag that is either the
* first tag in the array, or is preceded by a NULL tag.
*/
ndx--;
ndx--;
*ret_start_ndx = ndx;
/*
* The group is terminated by a series of 1 or more NULL tags.
*/
ndx = *ret_end_ndx;
ndx++;
ndx++;
*ret_end_ndx = ndx;
}
/*
* If a CA_SUNW_ID element exists within the current capabilities group
* in the given argument state, return the string pointer to the name.
* Otherwise return a pointer to a descriptive "noname" string.
*/
static const char *
{
}
break;
}
}
/*
* Given an index into the capabilities array, set the argstate cap.grp_*
* fields to reflect the capabilities group containing the index.
*
* The group concept is used to limit operations to a related group
* spilling across groups.
*/
static void
{
return;
}
/*
* Given an index into the capabilities array, issue a group title for
* the capabilities group that contains it.
*/
static void
{
loc_argstate = *argstate;
}
/*
* Standard argument processing for cap module
*
* entry
* obj_state, argc, argv - Standard command 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.
*/
static void
{
/* Add each new option to the options mask */
}
/* If there may be an arbitrary amount of output, use a pager */
if (argc == 0)
/* Locate the capabilities section */
/*
* If -capid was specified, locate the specified capabilities group,
* and narrow the section data to use only that group. Otherwise,
* use the whole array.
*/
Word i;
/*
* -capid requires the capability section to have an
* associated string table.
*/
ELFEDIT_MSG_ERR, 0)) == 0))
break;
} else {
}
}
/*
* Print ELF capabilities values, taking the calling command, and output style
* into account.
*
* entry:
* cmd - CAP_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 - Argument state block
* print_type - Specifies which capabilities elements to display.
* ndx = If print_type is PRINT_CAP_T_NDX, displays the index specified.
* Otherwise ignored.
*/
typedef enum {
/* given by arg */
} PRINT_CAP_T;
static void
{
const char *str;
return;
/*
* Pick an output style. cap:dump is required to use the default
* style. The other commands use the current output style.
*/
/* How many elements do we examine? */
if (print_type == PRINT_CAP_T_NDX) {
return; /* Out of range */
cnt = 1;
} else {
}
/* Load string table if there is one */
str_size = 0;
} else {
}
/*
* If we are only displaying certain tag types and
* this isn't one of those, move on to next element.
*/
continue;
}
/*
* If capability type requires a string table, and we don't
* have one, force an error.
*/
case CA_SUNW_PLAT:
case CA_SUNW_MACH:
case CA_SUNW_ID:
break;
}
if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
if (header_done) {
header_done = FALSE;
}
}
if (header_done == FALSE) {
header_done = TRUE;
Elf_cap_title(0);
}
} else {
/*
* If CAP_CMD_T_TAG, and not in default output
* style, display the tag rather than the value.
*/
if (cmd == CAP_CMD_T_TAG) {
if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
&inv_buf));
} else {
}
printed = 1;
continue;
}
/* Displaying the value in simple or numeric mode */
if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) {
if (print_type == PRINT_CAP_T_TAG) {
printed = 1;
continue;
}
case CA_SUNW_HW_1:
printed = 1;
continue;
case CA_SUNW_SF_1:
printed = 1;
continue;
case CA_SUNW_HW_2:
printed = 1;
continue;
case CA_SUNW_PLAT:
case CA_SUNW_MACH:
case CA_SUNW_ID:
ELFEDIT_MSG_ERR, 0));
printed = 1;
continue;
}
}
}
printed = 1;
}
/*
* If nothing was output under the print types that are
* based on tag type, issue an error saying it doesn't exist.
*/
}
}
/*
* Process the elt argument: This will be a tag type if -capndx is
* not present and this is a print request. It will be an index otherwise.
*
* entry:
* argstate - Argument state block
* arg - Argument string to be converted into an index
* argname - String giving the name by which the argument is
* referred in the online help for the command.
* print_request - True if the command is to print the current
* value(s) and return without changing anything.
* print_type - Address of variable containing PRINT_CAP_T_
* code specifying how the elements will be displayed.
*
* exit:
* If print_request is False: arg is converted into an integer value.
* If -capndx was used, we convert it into an integer. If it was not
* used, then arg is a tag name --- we find the first capabilities entry
* that matches. If no entry matches, and there is an extra CA_NULL,
* it is added. Otherwise an error is issued. *print_type is set
* to PRINT_CAP_T_NDX.
*
* If print_request is True: If -capndx was used, arg is converted into
* an integer value, *print_type is set to PRINT_CAP_T_NDX, and
* the value is returned. If -capndx was not used, *print_type is set to
* PRINT_CAP_T_TAG, and the tag value is returned.
*/
static Word
{
/* Assume we are returning an index, alter as needed below */
/*
* If -capndx was used, this is a simple numeric index.
* Determine its capability group because some operations
* (move, delete) are limited to operate within it.
*/
return (ndx);
}
/* The argument is a CA_ tag type, not a numeric index */
/*
* If this is a printing request, then we let print_cap() show
* all the items with this tag type.
*/
if (print_request) {
return (ca_value);
}
/*
* If we haven't determined a capability group yet, either via
* -capid, or -capndx, then make it the initial group, which
* represent the object capabilities.
*/
/*
* Locate the first entry with the given tag type within the
* capabilities group.
*/
return (ndx);
}
/*
* If we hit a NULL, then only more NULLs can follow it and
* there's no need to look further. If there is more than
* one NULL, we can grab the first one and turn it into
* an element of the desired type.
*/
return (ndx);
}
break;
}
}
/* No room to create one, so we're out of options and must fail */
/*NOTREACHED*/
return (0); /* For lint */
}
/*
* Argument processing for the bitmask commands. Convert the arguments
* to integer form, apply -and/-cmp/-or, and return the resulting value.
*
* entry:
* argstate - Argument state block
* orig - Value of original bitmask
* const_sym - NULL, or array of name->integer mappings for
* applicable symbolic constant names.
*/
static Word
{
int i;
/* Collect the arguments */
/* Complement the value? */
/* Perform any requested bit operations */
return (flags);
}
/*
* Common processing for capabilities value setting.
*
* entry:
* argstate - Argument state block
* cap - capabilities data pointer
* ndx - capabilities data index
* cap_ndx - capabilities section index
* cap_name - capabilities section name
* cap_tag - capabilities tag
* const_type - data conversion type
*/
static elfedit_cmdret_t
{
/* Set the value */
return (ELFEDIT_CMDRET_NONE);
} else {
return (ELFEDIT_CMDRET_MOD);
}
}
/*
* Common body for the cap: 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 CAP_CMD_T_* constants listed above, specifying
* which command to implement.
* obj_state, argc, argv - Standard command arguments
*/
static elfedit_cmdret_t
{
const char *cap_name;
int print_only = 0;
/* Process the optional arguments */
/* Check number of arguments, gather information */
switch (cmd) {
case CAP_CMD_T_DUMP:
/* cap:dump can accept an optional index argument */
print_only = 1;
break;
case CAP_CMD_T_TAG:
case CAP_CMD_T_VALUE:
}
break;
case CAP_CMD_T_DELETE:
0, &print_type);
do_autoprint = 0;
break;
case CAP_CMD_T_MOVE:
do_autoprint = 0;
break;
case CAP_CMD_T_HW1:
break;
case CAP_CMD_T_SF1:
break;
case CAP_CMD_T_HW2:
break;
default:
/* Note expected: All commands should have been caught above */
break;
}
/* If this is a request to print current values, do it and return */
if (print_only) {
return (ELFEDIT_CMDRET_NONE);
}
switch (cmd) {
/*
* CAP_CMD_T_DUMP can't get here: It is a print-only
* command.
*/
case CAP_CMD_T_TAG:
{
} else {
}
}
break;
case CAP_CMD_T_VALUE:
{
} else {
}
} else {
}
}
break;
case CAP_CMD_T_DELETE:
{
const char *msg_prefix =
/*
* We want to limit the deleted elements to be
* in the range of the current capabilities group,
* and for the resulting NULL elements to be inserted
* at the end of the group, rather than at the end
* of the section. To do this, we set the array length
* in the call to the delete function so that it thinks
* the array ends with the current group.
*
* The delete function will catch attempts to delete
* past this virtual end, but the error message will
* not make sense to the user. In order to prevent that,
* we check for the condition here and provide a more
* useful error.
*/
cap_group_id(&argstate));
}
break;
case CAP_CMD_T_MOVE:
{
const char *msg_prefix =
cnt = 1;
} else {
}
/*
* Moves are required to be self contained within
* the bounds of the selected capability group.
* The move utility function contains bounds checking,
* but is not sub-array aware. Hence, we bounds check
* check it here, and then hand of the validated
* operation to the move utility function to execute.
*/
cap_group_id(&argstate));
}
break;
case CAP_CMD_T_HW1:
{
}
break;
case CAP_CMD_T_SF1:
{
}
break;
case CAP_CMD_T_HW2:
{
}
break;
}
/*
* If we modified the capabilities section header, tell libelf.
*/
if (ret == ELFEDIT_CMDRET_MOD)
/* Do autoprint */
if (do_autoprint)
return (ret);
}
/*
* Command completion functions for the commands
*/
/*
* -capid command completion: Supply all CA_SUNW_ID names found in the object.
*/
static void
{
return;
return;
/* If no associated string table, we have no strings to complete */
return;
}
/*
* Command completion for the first argument, which specifies
* the capabilities element to use. Examines the options to see if
* -capndx is present, and if not, supplies the completion
* strings for argument 1.
*/
/*ARGSUSED*/
static void
{
Word i;
/* -capid id_name */
return;
}
/* Make sure it's the first argument */
return;
/* Is -capndx present? If so, we don't complete tag types */
for (i = 0; i < num_opt; i++)
return;
/*
* Supply capability tag names. There are very few of these, so
* rather than worry about whether a given tag exists in the
* file or not, we simply serve up all the possibilities.
*/
}
/*ARGSUSED*/
static void
{
/* -capid id_name */
return;
}
/* First plain argument */
return;
}
/* The second argument is always a tag value */
}
/*ARGSUSED*/
static void
{
/* -capid id_name */
return;
}
/* This routine allows multiple flags to be specified */
}
/*ARGSUSED*/
static void
{
/* -capid id_name */
return;
}
/* This routine allows multiple flags to be specified */
}
/*ARGSUSED*/
static void
{
/* -capid id_name */
return;
}
/* This routine allows multiple flags to be specified */
}
/*
* Implementation functions for the commands
*/
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
/*ARGSUSED*/
{
/* For commands that only accept -capid, -and, -cmp, -o, and -or */
/* MSG_INTL(MSG_OPTDESC_CAPID) */
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ NULL }
};
/* For commands that only accept -capid and -capndx */
/* MSG_INTL(MSG_OPTDESC_CAPID) */
/* MSG_INTL(MSG_OPTDESC_CAPNDX) */
{ NULL }
};
/* cap:dump */
static const char *name_dump[] = {
};
{ MSG_ORIG(MSG_STR_ELT),
/* MSG_INTL(MSG_ARGDESC_ELT) */
{ NULL }
};
/* cap:tag */
/* MSG_INTL(MSG_OPTDESC_CAPID) */
/* MSG_INTL(MSG_OPTDESC_CAPNDX) */
CAP_OPT_F_CAPNDX, 0 },
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ NULL }
};
{ MSG_ORIG(MSG_STR_ELT),
/* MSG_INTL(MSG_A1_TAG_ELT) */
/* MSG_INTL(MSG_A2_TAG_VALUE) */
{ NULL }
};
/* cap:value */
/* MSG_INTL(MSG_OPTDESC_CAPID) */
/* MSG_INTL(MSG_OPTDESC_CAPNDX) */
CAP_OPT_F_CAPNDX, 0 },
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
/* MSG_INTL(MSG_OPTDESC_S) */
CAP_OPT_F_STRVAL, 0 },
{ NULL }
};
{ MSG_ORIG(MSG_STR_ELT),
/* MSG_INTL(MSG_ARGDESC_ELT) */
/* MSG_INTL(MSG_A2_VALUE_VALUE) */
{ NULL }
};
/* cap:delete */
{ MSG_ORIG(MSG_STR_ELT),
/* MSG_INTL(MSG_ARGDESC_ELT) */
0 },
/* MSG_INTL(MSG_A2_DELETE_COUNT) */
{ NULL }
};
/* cap:move */
{ MSG_ORIG(MSG_STR_ELT),
/* MSG_INTL(MSG_ARGDESC_ELT) */
0 },
/* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */
0 },
/* MSG_INTL(MSG_A3_MOVE_COUNT) */
{ NULL }
};
/* cap:hw1 */
/* MSG_INTL(MSG_A1_HW1_VALUE) */
{ NULL }
};
/* cap:sf1 */
/* MSG_INTL(MSG_A1_SF1_VALUE) */
{ NULL }
};
/* cap:hw2 */
/* MSG_INTL(MSG_A1_HW2_VALUE) */
{ NULL }
};
/* cap:dump */
/* MSG_INTL(MSG_DESC_DUMP) */
/* MSG_INTL(MSG_HELP_DUMP) */
/* cap:tag */
/* MSG_INTL(MSG_DESC_TAG) */
/* MSG_INTL(MSG_HELP_TAG) */
/* cap:value */
/* MSG_INTL(MSG_DESC_VALUE) */
/* MSG_INTL(MSG_HELP_VALUE) */
/* cap:delete */
/* MSG_INTL(MSG_DESC_DELETE) */
/* MSG_INTL(MSG_HELP_DELETE) */
/* cap:move */
/* MSG_INTL(MSG_DESC_MOVE) */
/* MSG_INTL(MSG_HELP_MOVE) */
/* cap:hw1 */
/* MSG_INTL(MSG_DESC_HW1) */
/* MSG_INTL(MSG_HELP_HW1) */
/* cap:sf1 */
/* MSG_INTL(MSG_DESC_SF1) */
/* MSG_INTL(MSG_HELP_SF1) */
/* cap:hw2 */
/* MSG_INTL(MSG_DESC_HW2) */
/* MSG_INTL(MSG_HELP_HW2) */
{ NULL }
};
/* MSG_INTL(MSG_MOD_DESC) */
return (&module);
}