dyn.c revision ba2be53024c0b999e74ba9adcd7d80fec5df8c57
/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <ctype.h>
#include <elfedit.h>
#include <sys/elf_SPARC.h>
#include <strings.h>
#include <debug.h>
#include <conv.h>
#include <dyn_msg.h>
/*
* Dynamic 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 */
DYN_CMD_T_DUMP = 0, /* dyn:dump */
/* Commands that do not correspond directly to a specific DT tag */
/* Commands that embody tag specific knowledge */
} DYN_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 dyn_opt_t enum specifies a bit value for every optional
* argument allowed by a command in this module.
*/
typedef enum {
/* modifying an existing one */
/* not name */
} dyn_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 {
} dyn;
int argc; /* # of plain arguments */
const char **argv; /* Plain arguments */
} ARGSTATE;
/*
* Set argstate null_ndx field for current dynamic area
*/
static void
{
break;
}
/* Count the number of remaining DT_NULL items */
}
/*
* Convert the first available DT_NULL slot in the dynamic section
* into something else.
*
* entry:
* argstate - Argument state block
* d_tag, d_val - Values to be set in new element
*
* exit:
* If an extra DT_NULL slot is available, a debug message is
* issued, the slot is converted to its new use, and the argstate
* block state related to DT_NULL slots is updated.
*
* if no extra DT_NULL slot is present, an error is issued and
* this routine does not return to the caller.
*/
static Word
{
/* If we lack an extra element, we can't continue */
/* Recompute the DT_NULL situation */
return (ndx);
}
/*
* Standard argument processing for dyn 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 dynamic section, and the assocated string table */
/* Index of first DT_NULL */
}
/*
* Print ELF header values, taking the calling command, and output style
* into account.
*
* entry:
* cmd - DYN_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 dynamic elements to display.
* ndx = If print_type is PRINT_DYN_T_NDX, displays the index specified.
* Otherwise ignored.
*/
typedef enum {
PRINT_DYN_T_ALL = 0, /* Show all indexes */
/* given by arg */
} PRINT_DYN_T;
static void
{
int header_done = 0;
return;
/*
* Pick an output style. dyn:dump is required to use the default
* style. The other commands use the current output style.
*/
/*
* When using the simple output style, omit the
* brackets from around the values.
*/
CONV_FMT_NOBKT : 0;
/* How many elements do we examine? */
if (print_type == PRINT_DYN_T_NDX) {
return; /* Out of range */
cnt = 1;
} else {
ndx = 0;
}
union {
} c_buf;
const char *name;
/*
* If we are only displaying certain tag types and
* this isn't one of those, move on to next element.
*/
switch (print_type) {
case PRINT_DYN_T_TAG:
continue;
break;
case PRINT_DYN_T_RUNPATH:
continue;
break;
}
/*
* Print the information numerically, and if possible
* as a string.
*/
case DT_NULL:
if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) &&
(print_type == PRINT_DYN_T_ALL) &&
break;
/*
* Special case: DT_NULLs can come in groups
* that we prefer to reduce to a single line.
*/
dyn++;
end_ndx++;
cnt--;
}
if (header_done == 0) {
header_done = 1;
Elf_dyn_title(0);
}
printed = 1;
continue;
/*
* Print the information numerically, and if possible
* as a string.
*/
case DT_NEEDED:
case DT_SONAME:
case DT_FILTER:
case DT_AUXILIARY:
case DT_CONFIG:
case DT_RPATH:
case DT_RUNPATH:
case DT_USED:
case DT_DEPAUDIT:
case DT_AUDIT:
case DT_SUNW_AUXILIARY:
case DT_SUNW_FILTER:
break;
case DT_FLAGS:
break;
case DT_FLAGS_1:
break;
case DT_POSFLAG_1:
break;
case DT_FEATURE_1:
break;
break;
case DT_SUNW_LDMACH:
break;
}
if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
if (header_done == 0) {
header_done = 1;
Elf_dyn_title(0);
}
} else {
/*
* In simple or numeric mode under a print type
* that is based on tag type rather than on index,
* quietly: If we've already printed this value,
* don't print it again. A common example of this
* is PRINT_DYN_T_RUNPATH when both DT_RPATH and
* DT_RUNPATH are present with the same value.
*/
switch (print_type) {
case PRINT_DYN_T_TAG:
case PRINT_DYN_T_RUNPATH:
continue;
}
(outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) {
} else {
}
}
printed = 1;
}
/*
* If nothing was output under the print types that are
* based on tag type, issue an error saying it doesn't exist.
*/
if (!printed) {
if (print_type == PRINT_DYN_T_TAG) {
0, &inv_buf));
}
if (print_type == PRINT_DYN_T_RUNPATH)
}
}
/*
* Process the elt argument: This will be a tag type if -dynndx 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_DYN_T_
* code specifying how the elements will be displayed.
*
* exit:
* If print_request is False: arg is converted into an integer value.
* If -dynndx was used, we convert it into an integer. If it was not
* used, then arg is a tag name --- we find the first dynamic entry
* that matches. If no entry matches, and there is an extra DT_NULL,
* it is added. Otherwise an error is issued. *print_type is set
* to PRINT_DYN_T_NDX.
*
* If print_request is True: If -dynndx was used, arg is converted into
* an integer value, *print_type is set to PRINT_DYN_T_NDX, and
* the value is returned. If -dynndx was not used, *print_type is set to
* PRINT_DYN_T_TAG, and the tag value is returned.
*/
static Word
{
/* Assume we are returning an index, alter as needed below */
/* If -dynndx was used, this is a simple numeric index */
/* The argument is a DT_ tag type, not a numeric index */
/*
* If this is a printing request, then we let print_dyn() show
* all the items with this tag type.
*/
if (print_request) {
return (dt_value);
}
/* Locate the first entry with the given tag type */
return (ndx);
}
}
/* Not found. Can we create one? */
/* No room to create one, so we're out of options and must fail */
/*NOTREACHED*/
return (0); /* For lint */
}
/*
* Called by cmd_body() for dyn:value. Implements the core functionality
* for that command.
*
* This routine expects that both the index and value arguments are
* present.
*/
static elfedit_cmdret_t
{
Word i;
int arg2_known = 1;
/*
* The first argument is an index if -dynndx is used, and is a
* tag value otherwise.
*/
arg1 = minus_dynndx ?
if (minus_s) {
/*
* Don't allow the user to specify -s when manipulating a
* DT_SUNW_STRPAD element. Since DT_SUNW_STRPAD is used to
* manage the extra space used for strings, this would break
* our ability to add the string.
*/
/* Locate DT_SUNW_STRPAD element if present */
/*
* Look up the string: If the user specified the -dynndx
* -option, then we will insert it if possible, and
* fail with an error if not. However, if they did not
* specify -dynndx, we want to look up the string if it is
* already there, but defer the insertion. The reason for
* this is that we may have to grab an unused DT_NULL element
* below, and if there are none available, we won't want
* to have modified the string table.
*
* This isn't a problem, because if the string isn't
* in the string table, it can't be used by a dynamic element.
* Hence, we don't need to insert it to know that there is
* no match.
*/
if (minus_dynndx == 0) {
&tmp_val) == 0) {
arg2_known = 0;
} else {
}
} else {
}
} else { /* Argument 2 is an integer */
}
/*
* Search the dynamic section and see if an item with the
* specified tag value already exists. We can reduce this
* to a simple update of an existing value if -add is not
* specified or the existing d_un value matches the new one.
*
* In either of these cases, we will change arg1 to be the
* index, and set minus_dynndx, causing the simple update to
* happen immediately below.
*/
for (i = 0; i < numdyn; i++) {
arg1 = i;
minus_dynndx = 1;
break;
}
}
}
/*
* If -dynndx is used, then this is a relatively simple
* operation, as we simply write over the specified index.
*/
if (minus_dynndx) {
/*
* If we held back from inserting a new string into
* the dynstr above, we insert it now, because we
* have a slot in the dynamic section, and we need
* the string offset ot finish.
*/
if (!arg2_known)
return (ELFEDIT_CMDRET_NONE);
} else {
/* Warn if setting DT_NULL value to non-zero */
return (ELFEDIT_CMDRET_MOD);
}
}
/*
* We need a new slot in the dynamic section. If we can't have
* one, then we fail.
*/
/*
* If we still need to insert a new string into the dynstr,
* then it is safe now, because if we succeed, we know that
* there is an available slot to receive it. If we fail, we
* haven't claimed the extra slot yet, and it will be unharmed.
*/
if (!arg2_known)
/* Use an extra DT_NULL slot and enter the new element */
return (ELFEDIT_CMDRET_MOD);
}
/*
* Called by cmd_body() for dyn:runpath. Implements the core functionality
* for that command.
*
* History Lesson And Strategy:
*
* This routine handles both DT_RPATH and DT_RUNPATH entries, altering
* either or both if they are present.
*
* The original SYSV ABI only had DT_RPATH, and the runtime loader used
* it to search for things in the following order:
*
* DT_RPATH, LD_LIBRARY_PATH, defaults
*
* Solaris did not follow this rule, an extremely rare deviation from
* the ABI. Environment variables should supercede everything else,
* otherwise they are not very useful. This decision was made at the
* very beginning of the SunOS 5.x development, so we have always
* deviated from the ABI and and instead search in the order
*
* LD_LIBRARY_PATH, DT_RPATH, defaults
*
* Other Unix variants initially followed the ABI, but in recent years
* have come to agree with the early Solaris folks that it was a mistake.
* Hence, DT_RUNPATH was invented, with the search order:
*
* LD_LIBRARY_PATH, DT_RUNPATH, defaults
*
* So for Solaris, DT_RPATH and DT_RUNPATH mean the same thing. If both
* are present (which does happen), we set them both to the new
* value. If either one is present, we set that one. If neither is
* present, and we have a spare DT_NULL slot, we create a DT_RUNPATH, but
* not a DT_RPATH, to conserve available slots for other uses.
*/
static elfedit_cmdret_t
{
Word i;
/* Go through the tags and gather what we need */
for (i = 0; i < numdyn; i++) {
case DT_RPATH:
break;
case DT_RUNPATH:
break;
case DT_SUNW_STRPAD:
break;
}
}
/* Do we have an available dynamic section entry to use? */
/*
* We have seen a DT_RPATH, or a DT_RUNPATH, or both.
* If all of these have the same string as the desired
* new value, then we don't need to alter anything and can
* simply return. Otherwise, we'll modify them all to have
* the new string (below).
*/
(!runpath_elt.dn_seen ||
if (runpath_elt.dn_seen)
return (ELFEDIT_CMDRET_NONE);
}
/*
* There is no DT_RPATH or DT_RUNPATH in the dynamic array,
* and there are no extra DT_NULL entries that we can
* convert into one. We cannot proceed.
*/
}
/* Does the string exist in the table already, or can we add it? */
/* Update DT_RPATH entry if present */
}
/*
* Update the DT_RUNPATH entry in the dynamic section, if present.
* If one is not present, and there is also no DT_RPATH, then
* we use a spare DT_NULL entry to create a new DT_RUNPATH.
*/
if (runpath_elt.dn_seen) {
} else { /* Using a spare DT_NULL entry */
}
}
return (ELFEDIT_CMDRET_MOD);
}
/*
* 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_type - ELFEDIT_CONST_* value for type of constants
*/
static Word
{
int i;
/* Collect the arguments */
/* Complement the value? */
/* Perform any requested bit operations */
return (flags);
}
/*
* Common body for the dyn: 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 DYN_CMD_T_* constants listed above, specifying
* which command to implement.
* obj_state, argc, argv - Standard command arguments
*/
static elfedit_cmdret_t
{
const char *dyn_name;
int print_only = 0;
int do_autoprint = 1;
/* Process the optional arguments */
/* Check number of arguments, gather information */
switch (cmd) {
case DYN_CMD_T_DUMP:
/* dyn:dump can accept an optional index argument */
print_only = 1;
break;
case DYN_CMD_T_TAG:
}
break;
case DYN_CMD_T_VALUE:
if (print_only) {
print_only, &print_type);
} else {
}
}
break;
case DYN_CMD_T_DELETE:
0, &print_type);
do_autoprint = 0;
break;
case DYN_CMD_T_MOVE:
do_autoprint = 0;
break;
case DYN_CMD_T_RUNPATH:
/*
* dyn:runpath does not accept an explicit index
* argument, so we implicitly only show the DT_RPATH and
* DT_RUNPATH elements.
*/
break;
case DYN_CMD_T_POSFLAG1:
break;
case DYN_CMD_T_FLAGS:
break;
case DYN_CMD_T_FLAGS1:
break;
case DYN_CMD_T_FEATURE1:
break;
case DYN_CMD_T_CHECKSUM:
break;
case DYN_CMD_T_SUNW_LDMACH:
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) {
/*
* DYN_CMD_T_DUMP can't get here: It is a print-only
* command.
*/
case DYN_CMD_T_TAG:
{
} else {
/*
* Update null termination index. Warn if we
* just clobbered the only DT_NULL termination
* for the array.
*/
0, &inv_buf1));
/*
* Warning if
* - Inserting a DT_NULL cuts off following
* non-null elements.
* - Inserting a non-DT_NULL after the
* first null element, will be
* ignored by rtld.
*/
0, &inv_buf1));
} else {
0, &inv_buf1));
}
/* Debug message that we changed it */
&inv_buf1),
}
}
break;
case DYN_CMD_T_VALUE:
break;
case DYN_CMD_T_DELETE:
{
const char *msg_prefix =
}
break;
case DYN_CMD_T_MOVE:
{
const char *msg_prefix =
NULL);
cnt = 1;
} else {
}
}
break;
case DYN_CMD_T_RUNPATH:
break;
case DYN_CMD_T_POSFLAG1:
{
/* Set the value */
&buf1));
} else {
&buf1),
}
}
break;
case DYN_CMD_T_FLAGS:
{
/* Set the value */
&buf1));
} else {
&buf1),
}
}
break;
case DYN_CMD_T_FLAGS1:
{
/* Set the value */
0, &buf1));
} else {
0, &buf1),
}
}
break;
case DYN_CMD_T_FEATURE1:
{
/* Set the value */
&buf1));
} else {
&buf1),
}
}
break;
case DYN_CMD_T_CHECKSUM:
{
/* Set the value */
} else {
}
}
break;
case DYN_CMD_T_SUNW_LDMACH:
{
/* Set the value */
&buf1));
} else {
&buf1),
}
}
break;
}
/*
* If we modified the dynamic section header, tell libelf.
*/
if (ret == ELFEDIT_CMDRET_MOD)
/* Do autoprint */
if (do_autoprint)
return (ret);
}
/*
* Command completion functions for the commands
*/
/*
* Command completion for the first argument, which specifies
* the dynamic element to use. Examines the options to see if
* -dynndx is present, and if not, supplies the completion
* strings for argument 1.
*/
/*ARGSUSED*/
static void
{
Word i;
const char *s;
char *s2;
char buf[128];
/* Make sure it's the first argument */
return;
/* Is -dynndx present? If so, we don't complete tag types */
for (i = 0; i < num_opt; i++)
return;
/*
* If there is no object, or if there is no dynamic section,
* then supply all possible names.
*/
return;
}
/* Supply completions for the tags present in the dynamic section */
for (; i-- > 0; dyn++) {
if (s == NULL)
continue;
/*
* To get the informal tag names that are lowercase
* and lack the leading DT_, we copy the string we
* have into a buffer and process it.
*/
if (strlen(s) < 3)
continue;
}
}
/*ARGSUSED*/
static void
{
/* First argument */
return;
}
/* The second argument is always a tag value */
}
/*ARGSUSED*/
static void
{
/* This routine allows multiple flags to be specified */
}
/*ARGSUSED*/
static void
{
/* This routine allows multiple flags to be specified */
}
/*ARGSUSED*/
static void
{
/* This routine allows multiple flags to be specified */
}
/*ARGSUSED*/
static void
{
/* This routine allows multiple flags to be specified */
}
/*ARGSUSED*/
static void
{
/*
* This command doesn't accept options, so num_opt should be
* 0. This is a defensive measure, in case that should change.
*/
if (argc == 1)
}
/*
* 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
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
static elfedit_cmdret_t
{
}
/*ARGSUSED*/
{
/* For commands that only accept -o */
static elfedit_cmd_optarg_t opt_ostyle[] = {
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ NULL }
};
/* For commands that only accept -and, -cmp, -o, -or */
static elfedit_cmd_optarg_t opt_ostyle_bitop[] = {
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ NULL }
};
/* For commands that only accept -dynndx */
static elfedit_cmd_optarg_t opt_minus_dynndx[] = {
/* MSG_INTL(MSG_OPTDESC_DYNNDX) */
DYN_OPT_F_DYNNDX, 0 },
{ NULL }
};
/* dyn:dump */
static const char *name_dump[] = {
};
static elfedit_cmd_optarg_t arg_dump[] = {
{ MSG_ORIG(MSG_STR_ELT),
/* MSG_INTL(MSG_ARGDESC_ELT) */
{ NULL }
};
/* dyn:tag */
static elfedit_cmd_optarg_t opt_tag[] = {
/* MSG_INTL(MSG_OPTDESC_DYNNDX) */
DYN_OPT_F_DYNNDX, 0 },
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ NULL }
};
static elfedit_cmd_optarg_t arg_tag[] = {
{ MSG_ORIG(MSG_STR_ELT),
/* MSG_INTL(MSG_A1_TAG_ELT) */
/* MSG_INTL(MSG_A2_TAG_VALUE) */
{ NULL }
};
/* dyn:value */
static elfedit_cmd_optarg_t opt_value[] = {
/* MSG_INTL(MSG_OPTDESC_ADD) */
/* MSG_INTL(MSG_OPTDESC_DYNNDX) */
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
/* MSG_INTL(MSG_OPTDESC_S) */
DYN_OPT_F_STRVAL, 0 },
{ NULL }
};
static elfedit_cmd_optarg_t arg_value[] = {
{ MSG_ORIG(MSG_STR_ELT),
/* MSG_INTL(MSG_ARGDESC_ELT) */
/* MSG_INTL(MSG_A2_VALUE_VALUE) */
{ NULL }
};
/* dyn:delete */
static elfedit_cmd_optarg_t arg_delete[] = {
{ MSG_ORIG(MSG_STR_ELT),
/* MSG_INTL(MSG_ARGDESC_ELT) */
0 },
/* MSG_INTL(MSG_A2_DELETE_COUNT) */
{ NULL }
};
/* dyn:move */
static elfedit_cmd_optarg_t arg_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 }
};
/* dyn:runpath / dyn:rpath */
static elfedit_cmd_optarg_t arg_runpath[] = {
/* MSG_INTL(MSG_A1_RUNPATH_NEWPATH) */
{ NULL }
};
/* dyn:posflag1 */
NULL };
static elfedit_cmd_optarg_t arg_posflag1[] = {
/* MSG_INTL(MSG_A1_POSFLAG1_VALUE) */
{ NULL }
};
/* dyn:flags */
static elfedit_cmd_optarg_t arg_flags[] = {
/* MSG_INTL(MSG_A1_FLAGS_VALUE) */
{ NULL }
};
/* dyn:flags1 */
static elfedit_cmd_optarg_t arg_flags1[] = {
/* MSG_INTL(MSG_A1_FLAGS1_VALUE) */
{ NULL }
};
/* dyn:feature1 */
NULL };
static elfedit_cmd_optarg_t arg_feature1[] = {
/* MSG_INTL(MSG_A1_FEATURE1_VALUE) */
{ NULL }
};
/* dyn:checksum */
NULL };
/* dyn:sunw_ldmach */
NULL };
static elfedit_cmd_optarg_t arg_sunw_ldmach[] = {
/* MSG_INTL(MSG_A1_SUNW_LDMACH_VALUE) */
{ NULL }
};
static elfedit_cmd_t cmds[] = {
/* dyn:dump */
/* MSG_INTL(MSG_DESC_DUMP) */
/* MSG_INTL(MSG_HELP_DUMP) */
/* dyn:tag */
/* MSG_INTL(MSG_DESC_TAG) */
/* MSG_INTL(MSG_HELP_TAG) */
/* dyn:value */
/* MSG_INTL(MSG_DESC_VALUE) */
/* MSG_INTL(MSG_HELP_VALUE) */
/* dyn:delete */
/* MSG_INTL(MSG_DESC_DELETE) */
/* MSG_INTL(MSG_HELP_DELETE) */
/* dyn:move */
/* MSG_INTL(MSG_DESC_MOVE) */
/* MSG_INTL(MSG_HELP_MOVE) */
/* dyn:runpath */
/* MSG_INTL(MSG_DESC_RUNPATH) */
/* MSG_INTL(MSG_HELP_RUNPATH) */
/* dyn:posflag1 */
/* MSG_INTL(MSG_DESC_POSFLAG1) */
/* MSG_INTL(MSG_HELP_POSFLAG1) */
/* dyn:flags */
/* MSG_INTL(MSG_DESC_FLAGS) */
/* MSG_INTL(MSG_HELP_FLAGS) */
/* dyn:flags1 */
/* MSG_INTL(MSG_DESC_FLAGS1) */
/* MSG_INTL(MSG_HELP_FLAGS1) */
/* dyn:feature1 */
/* MSG_INTL(MSG_DESC_FEATURE1) */
/* MSG_INTL(MSG_HELP_FEATURE1) */
/* dyn:checksum */
/* MSG_INTL(MSG_DESC_CHECKSUM) */
/* MSG_INTL(MSG_HELP_CHECKSUM) */
/* dyn:sunw_ldmach */
/* MSG_INTL(MSG_DESC_SUNW_LDMACH) */
/* MSG_INTL(MSG_HELP_SUNW_LDMACH) */
{ NULL }
};
static elfedit_module_t module = {
/* MSG_INTL(MSG_MOD_DESC) */
return (&module);
}