#include <ctype.h>
#include <elfedit.h>
#include <sys/elf_SPARC.h>
#include <strings.h>
#include <debug.h>
#include <conv.h>
#include <dyn_msg.h>
typedef enum {
DYN_CMD_T_DUMP = 0,
DYN_CMD_T_TAG = 1,
DYN_CMD_T_VALUE = 2,
DYN_CMD_T_DELETE = 3,
DYN_CMD_T_MOVE = 4,
DYN_CMD_T_RUNPATH = 5,
DYN_CMD_T_POSFLAG1 = 6,
DYN_CMD_T_FLAGS = 7,
DYN_CMD_T_FLAGS1 = 8,
DYN_CMD_T_FEATURE1 = 9,
DYN_CMD_T_CHECKSUM = 10,
DYN_CMD_T_SUNW_LDMACH = 11
} DYN_CMD_T;
#ifndef _ELF64
const char *
_dyn_msg(Msg mid)
{
return (gettext(MSG_ORIG(mid)));
}
#endif
static const char *
mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl)
{
Msg msg = (Msg)hdl;
return (MSG_INTL(msg));
}
typedef enum {
DYN_OPT_F_ADD = 1,
DYN_OPT_F_AND = 2,
DYN_OPT_F_CMP = 4,
DYN_OPT_F_DYNNDX_ELT = 8,
DYN_OPT_F_DYNNDX_VAL = 16,
DYN_OPT_F_NEEDED = 32,
DYN_OPT_F_OR = 64,
DYN_OPT_F_STRVAL = 128
} dyn_opt_t;
typedef struct {
elfedit_obj_state_t *obj_state;
elfedit_section_t *strsec;
struct {
elfedit_section_t *sec;
Dyn *data;
Word num;
Word null_ndx;
Word num_null_ndx;
} dyn;
dyn_opt_t optmask;
int argc;
const char **argv;
const char *dyn_elt_str;
} ARGSTATE;
static void
set_null_ndx(ARGSTATE *argstate)
{
Word num, null_ndx;
num = argstate->dyn.num;
argstate->dyn.num_null_ndx = 0;
for (null_ndx = 0; null_ndx < num; null_ndx++)
if (argstate->dyn.data[null_ndx].d_tag == DT_NULL) {
argstate->dyn.num_null_ndx++;
break;
}
argstate->dyn.null_ndx = null_ndx;
for (; null_ndx < num; null_ndx++)
if (argstate->dyn.data[null_ndx].d_tag == DT_NULL)
argstate->dyn.num_null_ndx++;
}
static Word
convert_dt_null(ARGSTATE *argstate, Xword d_tag, Xword d_val)
{
Conv_inv_buf_t inv_buf;
Word ndx;
Dyn *dyn;
Ehdr *ehdr;
if (argstate->dyn.num_null_ndx <= 1)
elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
EC_WORD(argstate->dyn.sec->sec_shndx),
argstate->dyn.sec->sec_name);
ehdr = argstate->obj_state->os_ehdr;
elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_CONVNULL),
EC_WORD(argstate->dyn.sec->sec_shndx), argstate->dyn.sec->sec_name,
EC_WORD(argstate->dyn.null_ndx), conv_dyn_tag(d_tag,
ehdr->e_ident[EI_OSABI], ehdr->e_machine, 0, &inv_buf));
ndx = argstate->dyn.null_ndx;
dyn = &argstate->dyn.data[ndx];
dyn->d_tag = d_tag;
dyn->d_un.d_val = d_val;
set_null_ndx(argstate);
return (ndx);
}
static void
process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[],
ARGSTATE *argstate)
{
elfedit_getopt_state_t getopt_state;
elfedit_getopt_ret_t *getopt_ret;
bzero(argstate, sizeof (*argstate));
argstate->obj_state = obj_state;
elfedit_getopt_init(&getopt_state, &argc, &argv);
while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) {
argstate->optmask |= getopt_ret->gor_idmask;
switch (getopt_ret->gor_idmask) {
case DYN_OPT_F_DYNNDX_VAL:
case DYN_OPT_F_NEEDED:
argstate->dyn_elt_str = getopt_ret->gor_value;
break;
}
}
if (argc == 0)
elfedit_pager_init();
argstate->argc = argc;
argstate->argv = argv;
argstate->dyn.sec = elfedit_sec_getdyn(obj_state, &argstate->dyn.data,
&argstate->dyn.num);
argstate->strsec = elfedit_sec_getstr(obj_state,
argstate->dyn.sec->sec_shdr->sh_link, 0);
set_null_ndx(argstate);
}
typedef enum {
PRINT_DYN_T_ALL = 0,
PRINT_DYN_T_NDX = 1,
PRINT_DYN_T_TAG = 2,
PRINT_DYN_T_RUNPATH = 3
} PRINT_DYN_T;
static void
print_dyn(DYN_CMD_T cmd, int autoprint, ARGSTATE *argstate,
PRINT_DYN_T print_type, Word arg)
{
elfedit_outstyle_t outstyle;
Conv_fmt_flags_t flags_fmt_flags;
Word end_ndx, ndx, printed = 0;
Dyn *dyn;
int header_done = 0;
Xword last_d_val;
int one_shot;
int osabi_solaris;
if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0))
return;
osabi_solaris =
elfedit_test_osabi(argstate->obj_state, ELFOSABI_SOLARIS, 0);
outstyle = (cmd == DYN_CMD_T_DUMP) ?
ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle();
flags_fmt_flags = (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) ?
CONV_FMT_NOBKT : 0;
if (print_type == PRINT_DYN_T_NDX) {
if (arg >= argstate->dyn.num)
return;
ndx = arg;
} else {
ndx = 0;
}
one_shot = 0;
dyn = &argstate->dyn.data[ndx];
for (; (ndx < argstate->dyn.num) &&
((print_type != PRINT_DYN_T_NDX) || ((ndx == arg) || one_shot));
dyn++, ndx++) {
union {
Conv_inv_buf_t inv;
Conv_dyn_flag_buf_t flag;
Conv_dyn_flag1_buf_t flag1;
Conv_dyn_posflag1_buf_t posflag1;
Conv_dyn_feature1_buf_t feature1;
} c_buf;
const char *name;
if (one_shot) {
one_shot = 0;
} else {
switch (print_type) {
case PRINT_DYN_T_TAG:
if (dyn->d_tag != arg)
continue;
break;
case PRINT_DYN_T_RUNPATH:
if ((dyn->d_tag != DT_RPATH) &&
(dyn->d_tag != DT_RUNPATH))
continue;
break;
}
}
name = NULL;
switch (dyn->d_tag) {
case DT_NULL:
if (!((outstyle == ELFEDIT_OUTSTYLE_DEFAULT) &&
(print_type == PRINT_DYN_T_ALL) &&
(dyn->d_un.d_val == 0)))
break;
end_ndx = ndx;
while ((end_ndx < (argstate->dyn.num - 1)) &&
((dyn + 1)->d_tag == DT_NULL) &&
((dyn + 1)->d_un.d_val == 0)) {
dyn++;
end_ndx++;
}
if (header_done == 0) {
header_done = 1;
Elf_dyn_title(0);
}
Elf_dyn_null_entry(0, dyn, ndx, end_ndx);
ndx = end_ndx;
printed = 1;
last_d_val = dyn->d_un.d_val;
continue;
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:
name = elfedit_offset_to_str(argstate->strsec,
dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
break;
case DT_SUNW_AUXILIARY:
case DT_SUNW_FILTER:
if (osabi_solaris)
name = elfedit_offset_to_str(argstate->strsec,
dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
break;
case DT_FLAGS:
name = conv_dyn_flag(dyn->d_un.d_val,
flags_fmt_flags, &c_buf.flag);
break;
case DT_FLAGS_1:
name = conv_dyn_flag1(dyn->d_un.d_val,
flags_fmt_flags, &c_buf.flag1);
break;
case DT_POSFLAG_1:
if ((cmd == DYN_CMD_T_POSFLAG1) &&
(print_type == PRINT_DYN_T_TAG) &&
((argstate->optmask & DYN_OPT_F_NEEDED) != 0) &&
((ndx + 1) < argstate->dyn.num)) {
Dyn *dyn1 = &argstate->dyn.data[ndx + 1];
if (dyn1->d_tag != DT_NEEDED)
continue;
name = elfedit_offset_to_str(argstate->strsec,
dyn1->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
if (strncmp(name, argstate->dyn_elt_str,
strlen(argstate->dyn_elt_str)) != 0)
continue;
}
name = conv_dyn_posflag1(dyn->d_un.d_val,
flags_fmt_flags, &c_buf.posflag1);
one_shot = (outstyle == ELFEDIT_OUTSTYLE_DEFAULT);
break;
case DT_FEATURE_1:
name = conv_dyn_feature1(dyn->d_un.d_val,
flags_fmt_flags, &c_buf.feature1);
break;
case DT_DEPRECATED_SPARC_REGISTER:
name = MSG_INTL(MSG_STR_DEPRECATED);
break;
case DT_SUNW_LDMACH:
if (osabi_solaris)
name = conv_ehdr_mach((Half)dyn->d_un.d_val, 0,
&c_buf.inv);
break;
}
if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) {
Ehdr *ehdr;
if (header_done == 0) {
header_done = 1;
Elf_dyn_title(0);
}
if (name == NULL)
name = MSG_ORIG(MSG_STR_EMPTY);
ehdr = argstate->obj_state->os_ehdr;
Elf_dyn_entry(0, dyn, ndx, name,
ehdr->e_ident[EI_OSABI], ehdr->e_machine);
} else {
switch (print_type) {
case PRINT_DYN_T_TAG:
switch (dyn->d_tag) {
case DT_NEEDED:
break;
case DT_POSFLAG_1:
break;
default:
if (printed &&
(last_d_val == dyn->d_un.d_val))
continue;
}
break;
case PRINT_DYN_T_RUNPATH:
if (printed && (last_d_val == dyn->d_un.d_val))
continue;
break;
}
if ((name != NULL) &&
(outstyle == ELFEDIT_OUTSTYLE_SIMPLE)) {
elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), name);
} else {
elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL),
EC_XWORD(dyn->d_un.d_val));
}
}
printed = 1;
last_d_val = dyn->d_un.d_val;
}
if (!printed) {
if (print_type == PRINT_DYN_T_TAG) {
Conv_inv_buf_t inv_buf;
Ehdr *ehdr = argstate->obj_state->os_ehdr;
elfedit_msg(ELFEDIT_MSG_ERR,
MSG_INTL(MSG_ERR_NODYNELT),
EC_WORD(argstate->dyn.sec->sec_shndx),
argstate->dyn.sec->sec_name, conv_dyn_tag(arg,
ehdr->e_ident[EI_OSABI], ehdr->e_machine,
0, &inv_buf));
}
if (print_type == PRINT_DYN_T_RUNPATH)
elfedit_msg(ELFEDIT_MSG_ERR,
MSG_INTL(MSG_ERR_NORUNPATH),
EC_WORD(argstate->dyn.sec->sec_shndx),
argstate->dyn.sec->sec_name);
}
}
static Word
arg_to_index(ARGSTATE *argstate, const char *arg,
int print_request, PRINT_DYN_T *print_type)
{
Word ndx;
Xword dt_value;
Dyn *dyn;
*print_type = PRINT_DYN_T_NDX;
if ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0)
return ((Word) elfedit_atoui_range(arg, MSG_ORIG(MSG_STR_ELT),
0, argstate->dyn.num - 1, NULL));
dt_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_DT);
if ((argstate->optmask & DYN_OPT_F_DYNNDX_VAL) != 0) {
ndx = ((Word) elfedit_atoui_range(argstate->dyn_elt_str,
MSG_ORIG(MSG_STR_INDEX), 0, argstate->dyn.num - 1, NULL));
if (argstate->dyn.data[ndx].d_tag != dt_value) {
Ehdr *ehdr = argstate->obj_state->os_ehdr;
uchar_t osabi = ehdr->e_ident[EI_OSABI];
Half mach = ehdr->e_machine;
Conv_inv_buf_t is, want;
elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_WRONGTAG),
EC_WORD(argstate->dyn.sec->sec_shndx),
argstate->dyn.sec->sec_name, ndx,
conv_dyn_tag(dt_value, osabi, mach, 0, &want),
conv_dyn_tag(argstate->dyn.data[ndx].d_tag,
osabi, mach, 0, &is));
}
return (ndx);
}
if (print_request) {
*print_type = PRINT_DYN_T_TAG;
return (dt_value);
}
if ((argstate->optmask & DYN_OPT_F_NEEDED) != 0) {
Word retndx = argstate->dyn.num;
const char *name;
size_t len;
len = strlen(argstate->dyn_elt_str);
for (ndx = 0, dyn = argstate->dyn.data;
ndx < argstate->dyn.num; dyn++, ndx++) {
if ((dyn->d_tag == DT_NEEDED) &&
(ndx > 0) && (retndx == (ndx - 1))) {
name = elfedit_offset_to_str(argstate->strsec,
dyn->d_un.d_val, ELFEDIT_MSG_DEBUG, 0);
if (strncmp(name,
argstate->dyn_elt_str, len) == 0)
return (retndx);
continue;
}
if (dyn->d_tag == dt_value)
retndx = ndx;
}
elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NEEDEDNOMATCH),
EC_WORD(argstate->dyn.sec->sec_shndx),
argstate->dyn.sec->sec_name, argstate->dyn_elt_str);
}
for (ndx = 0; ndx < argstate->dyn.num; ndx++) {
if (argstate->dyn.data[ndx].d_tag == dt_value) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_DT2NDX),
EC_WORD(argstate->dyn.sec->sec_shndx),
argstate->dyn.sec->sec_name, EC_WORD(ndx), arg);
return (ndx);
}
}
if (argstate->dyn.num_null_ndx > 1)
return (convert_dt_null(argstate, dt_value, 0));
elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NODTELT),
EC_WORD(argstate->dyn.sec->sec_shndx),
argstate->dyn.sec->sec_name, arg);
return (0);
}
static elfedit_cmdret_t
cmd_body_value(ARGSTATE *argstate, Word *ret_ndx)
{
elfedit_section_t *dynsec = argstate->dyn.sec;
elfedit_section_t *strsec = argstate->strsec;
elfedit_dyn_elt_t strpad_elt;
Word i;
Dyn *dyn = argstate->dyn.data;
Word numdyn = argstate->dyn.num;
int minus_add, minus_s, minus_dynndx;
Word tmp_val;
Xword arg1, arg2;
int arg2_known = 1;
minus_add = ((argstate->optmask & DYN_OPT_F_ADD) != 0);
minus_s = ((argstate->optmask & DYN_OPT_F_STRVAL) != 0);
minus_dynndx = ((argstate->optmask & DYN_OPT_F_DYNNDX_ELT) != 0);
elfedit_dyn_elt_init(&strpad_elt);
arg1 = minus_dynndx ?
elfedit_atoui_range(argstate->argv[0], MSG_ORIG(MSG_STR_ELT),
0, numdyn - 1, NULL) :
elfedit_atoconst(argstate->argv[0], ELFEDIT_CONST_DT);
if (minus_s) {
if ((!minus_dynndx && (arg1 == DT_SUNW_STRPAD)) ||
(minus_dynndx && (dyn[arg1].d_tag == DT_SUNW_STRPAD)))
elfedit_msg(ELFEDIT_MSG_ERR,
MSG_INTL(MSG_ERR_STRPADSTRVAL),
EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
strpad_elt.dn_dyn.d_un.d_val = 0;
(void) elfedit_dynstr_getpad(argstate->obj_state,
argstate->dyn.sec, &strpad_elt);
if (minus_dynndx == 0) {
if (elfedit_sec_findstr(strsec,
strpad_elt.dn_dyn.d_un.d_val, argstate->argv[1],
&tmp_val) == 0) {
arg2_known = 0;
} else {
arg2 = tmp_val;
}
} else {
arg2 = elfedit_dynstr_insert(dynsec, strsec,
&strpad_elt, argstate->argv[1]);
}
} else {
arg2 = elfedit_atoui(argstate->argv[1], NULL);
}
if (!minus_dynndx && !(minus_add && !arg2_known)) {
for (i = 0; i < numdyn; i++) {
if ((dyn[i].d_tag == arg1) &&
(!minus_add || (dyn[i].d_un.d_val == arg2))) {
arg1 = i;
minus_dynndx = 1;
break;
}
}
}
if (minus_dynndx) {
if (!arg2_known)
arg2 = elfedit_dynstr_insert(dynsec, strsec,
&strpad_elt, argstate->argv[1]);
*ret_ndx = arg1;
if (dyn[arg1].d_un.d_val == arg2) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_X_OK),
dynsec->sec_shndx, dynsec->sec_name,
EC_WORD(arg1), EC_XWORD(arg2));
return (ELFEDIT_CMDRET_NONE);
} else {
if ((dyn[arg1].d_tag == DT_NULL) && (arg2 != 0))
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_DTNULLVALUE),
dynsec->sec_shndx, dynsec->sec_name,
EC_WORD(arg1), EC_XWORD(arg2));
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_X_CHG),
dynsec->sec_shndx, dynsec->sec_name,
EC_WORD(arg1), EC_XWORD(dyn[arg1].d_un.d_val),
EC_XWORD(arg2));
dyn[arg1].d_un.d_val = arg2;
return (ELFEDIT_CMDRET_MOD);
}
}
if (argstate->dyn.num_null_ndx <= 1)
elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
if (!arg2_known)
arg2 = elfedit_dynstr_insert(dynsec, strsec,
&strpad_elt, argstate->argv[1]);
*ret_ndx = convert_dt_null(argstate, arg1, arg2);
return (ELFEDIT_CMDRET_MOD);
}
static elfedit_cmdret_t
cmd_body_runpath(ARGSTATE *argstate)
{
elfedit_section_t *dynsec = argstate->dyn.sec;
elfedit_section_t *strsec = argstate->strsec;
elfedit_dyn_elt_t rpath_elt;
elfedit_dyn_elt_t runpath_elt;
elfedit_dyn_elt_t strpad_elt;
Word i;
Dyn *dyn = argstate->dyn.data;
Word numdyn = argstate->dyn.num;
elfedit_dyn_elt_init(&rpath_elt);
elfedit_dyn_elt_init(&runpath_elt);
elfedit_dyn_elt_init(&strpad_elt);
for (i = 0; i < numdyn; i++) {
switch (dyn[i].d_tag) {
case DT_RPATH:
elfedit_dyn_elt_save(&rpath_elt, i, &dyn[i]);
break;
case DT_RUNPATH:
elfedit_dyn_elt_save(&runpath_elt, i, &dyn[i]);
break;
case DT_SUNW_STRPAD:
if (elfedit_test_osabi(argstate->obj_state,
ELFOSABI_SOLARIS, 0))
elfedit_dyn_elt_save(&strpad_elt, i, &dyn[i]);
break;
}
}
if (rpath_elt.dn_seen || runpath_elt.dn_seen) {
if ((!rpath_elt.dn_seen ||
(strcmp(elfedit_dyn_offset_to_str(strsec, &rpath_elt),
argstate->argv[0]) == 0)) &&
(!runpath_elt.dn_seen ||
(strcmp(elfedit_dyn_offset_to_str(strsec, &runpath_elt),
argstate->argv[0]) == 0))) {
if (rpath_elt.dn_seen)
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_OLDRPATHOK),
EC_WORD(dynsec->sec_shndx),
dynsec->sec_name, EC_WORD(rpath_elt.dn_ndx),
elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_RPATH, 1));
if (runpath_elt.dn_seen)
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_OLDRPATHOK),
EC_WORD(dynsec->sec_shndx),
dynsec->sec_name,
EC_WORD(runpath_elt.dn_ndx),
elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_RUNPATH, 1));
return (ELFEDIT_CMDRET_NONE);
}
} else if (argstate->dyn.num_null_ndx <= 1) {
elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOEXTRANULL),
EC_WORD(dynsec->sec_shndx), dynsec->sec_name);
}
rpath_elt.dn_dyn.d_un.d_val = runpath_elt.dn_dyn.d_un.d_val =
elfedit_dynstr_insert(dynsec, strsec, &strpad_elt,
argstate->argv[0]);
if (rpath_elt.dn_seen) {
elfedit_msg(ELFEDIT_MSG_DEBUG, MSG_INTL(MSG_DEBUG_PREVRPATH),
EC_WORD(dynsec->sec_shndx), dynsec->sec_name,
EC_WORD(rpath_elt.dn_ndx),
elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_RPATH, 1),
elfedit_dyn_offset_to_str(strsec, &rpath_elt));
dyn[rpath_elt.dn_ndx] = rpath_elt.dn_dyn;
}
if (runpath_elt.dn_seen || !rpath_elt.dn_seen) {
if (runpath_elt.dn_seen) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_PREVRPATH),
EC_WORD(dynsec->sec_shndx), dynsec->sec_name,
EC_WORD(runpath_elt.dn_ndx),
elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_RUNPATH, 1),
elfedit_dyn_offset_to_str(strsec, &runpath_elt));
dyn[runpath_elt.dn_ndx] = runpath_elt.dn_dyn;
} else {
(void) convert_dt_null(argstate, DT_RUNPATH,
runpath_elt.dn_dyn.d_un.d_val);
}
}
return (ELFEDIT_CMDRET_MOD);
}
static Word
flag_bitop(ARGSTATE *argstate, Word orig, elfedit_const_t const_type)
{
Word flags = 0;
int i;
for (i = 0; i < argstate->argc; i++)
flags |= (Word) elfedit_atoconst(argstate->argv[i], const_type);
if (argstate->optmask & DYN_OPT_F_CMP)
flags = ~flags;
if (argstate->optmask & DYN_OPT_F_AND)
flags &= orig;
else if (argstate->optmask & DYN_OPT_F_OR)
flags |= orig;
return (flags);
}
static elfedit_cmdret_t
cmd_body(DYN_CMD_T cmd, elfedit_obj_state_t *obj_state,
int argc, const char *argv[])
{
ARGSTATE argstate;
Dyn *dyn;
const char *dyn_name;
Word dyn_ndx, dyn_num, null_ndx;
elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE;
PRINT_DYN_T print_type = PRINT_DYN_T_ALL;
Word ndx;
int print_only = 0;
int do_autoprint = 1;
process_args(obj_state, argc, argv, &argstate);
dyn = argstate.dyn.data;
dyn_num = argstate.dyn.num;
dyn_name = argstate.dyn.sec->sec_name;
dyn_ndx = argstate.dyn.sec->sec_shndx;
switch (cmd) {
case DYN_CMD_T_DUMP:
if (argstate.argc > 1)
elfedit_command_usage();
print_only = 1;
if (argstate.argc == 1)
ndx = arg_to_index(&argstate, argstate.argv[0],
print_only, &print_type);
break;
case DYN_CMD_T_TAG:
print_only = (argstate.argc != 2);
if (argstate.argc > 0) {
if (argstate.argc > 2)
elfedit_command_usage();
ndx = arg_to_index(&argstate, argstate.argv[0],
print_only, &print_type);
}
break;
case DYN_CMD_T_VALUE:
print_only = (argstate.argc != 2);
if (argstate.argc > 2)
elfedit_command_usage();
if (argstate.argc > 0) {
if (print_only) {
ndx = arg_to_index(&argstate, argstate.argv[0],
print_only, &print_type);
} else {
print_type = PRINT_DYN_T_NDX;
}
}
break;
case DYN_CMD_T_DELETE:
if ((argstate.argc < 1) || (argstate.argc > 2))
elfedit_command_usage();
ndx = arg_to_index(&argstate, argstate.argv[0],
0, &print_type);
do_autoprint = 0;
break;
case DYN_CMD_T_MOVE:
if ((argstate.argc < 2) || (argstate.argc > 3))
elfedit_command_usage();
ndx = arg_to_index(&argstate, argstate.argv[0],
0, &print_type);
do_autoprint = 0;
break;
case DYN_CMD_T_RUNPATH:
if (argstate.argc > 1)
elfedit_command_usage();
print_type = PRINT_DYN_T_RUNPATH;
print_only = (argstate.argc == 0);
break;
case DYN_CMD_T_POSFLAG1:
print_only = (argstate.argc == 0);
ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_POSFLAG_1, 1),
print_only, &print_type);
break;
case DYN_CMD_T_FLAGS:
print_only = (argstate.argc == 0);
ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_FLAGS, 1),
print_only, &print_type);
break;
case DYN_CMD_T_FLAGS1:
print_only = (argstate.argc == 0);
ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_FLAGS_1, 1),
print_only, &print_type);
break;
case DYN_CMD_T_FEATURE1:
print_only = (argstate.argc == 0);
ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_FEATURE_1, 1),
print_only, &print_type);
break;
case DYN_CMD_T_CHECKSUM:
ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_CHECKSUM, 1),
print_only, &print_type);
break;
case DYN_CMD_T_SUNW_LDMACH:
if (argstate.argc > 1)
elfedit_command_usage();
(void) elfedit_test_osabi(argstate.obj_state,
ELFOSABI_SOLARIS, 1);
print_only = (argstate.argc == 0);
ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str(
ELFEDIT_CONST_DT, DT_SUNW_LDMACH, 1),
print_only, &print_type);
break;
default:
elfedit_command_usage();
break;
}
if (print_only) {
print_dyn(cmd, 0, &argstate, print_type, ndx);
return (ELFEDIT_CMDRET_NONE);
}
switch (cmd) {
case DYN_CMD_T_TAG:
{
Ehdr *ehdr = argstate.obj_state->os_ehdr;
uchar_t osabi = ehdr->e_ident[EI_OSABI];
Half mach = ehdr->e_machine;
Conv_inv_buf_t inv_buf1, inv_buf2;
Xword d_tag = (Xword) elfedit_atoconst(argstate.argv[1],
ELFEDIT_CONST_DT);
if (dyn[ndx].d_tag == d_tag) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx, dyn_name,
EC_WORD(ndx), conv_dyn_tag(d_tag, osabi,
mach, 0, &inv_buf1));
} else {
Xword orig_d_tag = dyn[ndx].d_tag;
ret = ELFEDIT_CMDRET_MOD;
dyn[ndx].d_tag = d_tag;
null_ndx = argstate.dyn.null_ndx;
set_null_ndx(&argstate);
if ((argstate.dyn.null_ndx >=
argstate.dyn.num) &&
(null_ndx != argstate.dyn.null_ndx))
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_NULLTERM),
dyn_ndx, dyn_name,
EC_WORD(ndx), conv_dyn_tag(d_tag,
osabi, mach, 0, &inv_buf1));
if (d_tag == DT_NULL) {
if ((ndx + 1) < null_ndx)
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_NULCLIP),
dyn_ndx, dyn_name,
EC_WORD(ndx),
conv_dyn_tag(d_tag, osabi,
mach, 0, &inv_buf1));
} else {
if ((ndx + 1) > argstate.dyn.null_ndx)
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_NULHIDE),
dyn_ndx, dyn_name,
EC_WORD(ndx),
conv_dyn_tag(d_tag, osabi,
mach, 0, &inv_buf1));
}
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_CHG),
dyn_ndx, dyn_name, EC_WORD(ndx),
conv_dyn_tag(orig_d_tag, osabi, mach, 0,
&inv_buf1),
conv_dyn_tag(d_tag, osabi, mach, 0,
&inv_buf2));
}
}
break;
case DYN_CMD_T_VALUE:
ret = cmd_body_value(&argstate, &ndx);
break;
case DYN_CMD_T_DELETE:
{
Word cnt = (argstate.argc == 1) ? 1 :
(Word) elfedit_atoui_range(argstate.argv[1],
MSG_ORIG(MSG_STR_COUNT), 1, dyn_num - ndx, NULL);
const char *msg_prefix =
elfedit_sec_msgprefix(argstate.dyn.sec);
elfedit_array_elts_delete(msg_prefix, argstate.dyn.data,
sizeof (Dyn), dyn_num, ndx, cnt);
ret = ELFEDIT_CMDRET_MOD;
}
break;
case DYN_CMD_T_MOVE:
{
Dyn save;
Word cnt;
Word dstndx;
const char *msg_prefix =
elfedit_sec_msgprefix(argstate.dyn.sec);
dstndx = (Word)
elfedit_atoui_range(argstate.argv[1],
MSG_ORIG(MSG_STR_DST_INDEX), 0, dyn_num - 1,
NULL);
if (argstate.argc == 2) {
cnt = 1;
} else {
cnt = (Word) elfedit_atoui_range(
argstate.argv[2], MSG_ORIG(MSG_STR_COUNT),
1, dyn_num, NULL);
}
elfedit_array_elts_move(msg_prefix, argstate.dyn.data,
sizeof (save), dyn_num, ndx, dstndx, cnt, &save);
ret = ELFEDIT_CMDRET_MOD;
}
break;
case DYN_CMD_T_RUNPATH:
ret = cmd_body_runpath(&argstate);
break;
case DYN_CMD_T_POSFLAG1:
{
Conv_dyn_posflag1_buf_t buf1, buf2;
Word flags;
flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
ELFEDIT_CONST_DF_P1);
if (dyn[ndx].d_un.d_val == flags) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
dyn_name, EC_WORD(ndx),
conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0,
&buf1));
} else {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_CHG),
dyn_ndx, dyn_name, EC_WORD(ndx),
conv_dyn_posflag1(dyn[ndx].d_un.d_val, 0,
&buf1),
conv_dyn_posflag1(flags, 0, &buf2));
ret = ELFEDIT_CMDRET_MOD;
dyn[ndx].d_un.d_val = flags;
}
}
break;
case DYN_CMD_T_FLAGS:
{
Conv_dyn_flag_buf_t buf1, buf2;
Word flags;
flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
ELFEDIT_CONST_DF);
if (dyn[ndx].d_un.d_val == flags) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
dyn_name, EC_WORD(ndx),
conv_dyn_flag(dyn[ndx].d_un.d_val, 0,
&buf1));
} else {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_CHG),
dyn_ndx, dyn_name, EC_WORD(ndx),
conv_dyn_flag(dyn[ndx].d_un.d_val, 0,
&buf1),
conv_dyn_flag(flags, 0, &buf2));
ret = ELFEDIT_CMDRET_MOD;
dyn[ndx].d_un.d_val = flags;
}
}
break;
case DYN_CMD_T_FLAGS1:
{
Conv_dyn_flag1_buf_t buf1, buf2;
Word flags1;
flags1 = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
ELFEDIT_CONST_DF_1);
if (dyn[ndx].d_un.d_val == flags1) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
dyn_name, EC_WORD(ndx),
conv_dyn_flag1(dyn[ndx].d_un.d_val,
0, &buf1));
} else {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_CHG),
dyn_ndx, dyn_name, EC_WORD(ndx),
conv_dyn_flag1(dyn[ndx].d_un.d_val,
0, &buf1),
conv_dyn_flag1(flags1, 0, &buf2));
ret = ELFEDIT_CMDRET_MOD;
dyn[ndx].d_un.d_val = flags1;
}
}
break;
case DYN_CMD_T_FEATURE1:
{
Conv_dyn_feature1_buf_t buf1, buf2;
Word flags;
flags = flag_bitop(&argstate, dyn[ndx].d_un.d_val,
ELFEDIT_CONST_DTF_1);
if (dyn[ndx].d_un.d_val == flags) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
dyn_name, EC_WORD(ndx),
conv_dyn_feature1(dyn[ndx].d_un.d_val, 0,
&buf1));
} else {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_CHG),
dyn_ndx, dyn_name, EC_WORD(ndx),
conv_dyn_feature1(dyn[ndx].d_un.d_val, 0,
&buf1),
conv_dyn_feature1(flags, 0, &buf2));
ret = ELFEDIT_CMDRET_MOD;
dyn[ndx].d_un.d_val = flags;
}
}
break;
case DYN_CMD_T_CHECKSUM:
{
long checksum = elf_checksum(obj_state->os_elf);
if (dyn[ndx].d_un.d_val == checksum) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_X_OK), dyn_ndx,
dyn_name, EC_WORD(ndx), EC_XWORD(checksum));
} else {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_X_CHG),
dyn_ndx, dyn_name, EC_WORD(ndx),
EC_XWORD(dyn[ndx].d_un.d_val),
EC_XWORD(checksum));
ret = ELFEDIT_CMDRET_MOD;
dyn[ndx].d_un.d_val = checksum;
}
}
break;
case DYN_CMD_T_SUNW_LDMACH:
{
Conv_inv_buf_t buf1, buf2;
Half ldmach;
ldmach = (Half) elfedit_atoconst(argstate.argv[0],
ELFEDIT_CONST_EM);
if (dyn[ndx].d_un.d_val == ldmach) {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_OK), dyn_ndx,
dyn_name, EC_WORD(ndx),
conv_ehdr_mach(dyn[ndx].d_un.d_val, 0,
&buf1));
} else {
elfedit_msg(ELFEDIT_MSG_DEBUG,
MSG_INTL(MSG_DEBUG_S_CHG),
dyn_ndx, dyn_name, EC_WORD(ndx),
conv_ehdr_mach(dyn[ndx].d_un.d_val, 0,
&buf1),
conv_ehdr_mach(ldmach, 0, &buf2));
ret = ELFEDIT_CMDRET_MOD;
dyn[ndx].d_un.d_val = ldmach;
}
}
break;
}
if (ret == ELFEDIT_CMDRET_MOD)
elfedit_modified_data(argstate.dyn.sec);
if (do_autoprint)
print_dyn(cmd, 1, &argstate, print_type, ndx);
return (ret);
}
static void
cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
const char *argv[], int num_opt)
{
elfedit_section_t *cache;
Dyn *dyn;
Word i;
const char *s;
char *s2;
char buf[128];
if ((argc - num_opt) != 1)
return;
for (i = 0; i < num_opt; i++)
if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0)
return;
if ((obj_state == NULL) || (obj_state->os_dynndx == SHN_UNDEF)) {
elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT);
return;
}
cache = &obj_state->os_secarr[obj_state->os_dynndx];
dyn = (Dyn *) cache->sec_data->d_buf;
i = cache->sec_shdr->sh_size / cache->sec_shdr->sh_entsize;
for (; i-- > 0; dyn++) {
s = elfedit_atoconst_value_to_str(ELFEDIT_CONST_DT,
dyn->d_tag, 0);
if (s == NULL)
continue;
elfedit_cpl_match(cpldata, s, 1);
if (strlen(s) < 3)
continue;
(void) strlcpy(buf, s + 3, sizeof (buf));
for (s2 = buf; *s2 != '\0'; s2++)
if (isupper(*s2))
*s2 = tolower(*s2);
elfedit_cpl_match(cpldata, buf, 1);
}
}
static void
cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
const char *argv[], int num_opt)
{
if ((argc - num_opt) == 1) {
cpl_eltarg(obj_state, cpldata, argc, argv, num_opt);
return;
}
if ((argc - num_opt) == 2)
elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DT);
}
static void
cpl_posflag1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
const char *argv[], int num_opt)
{
if ((num_opt > 1) && (argc == num_opt)) {
elfedit_section_t *dynsec, *strsec;
const char *opt = argv[num_opt - 2];
dyn_opt_t type;
Dyn *dyn;
Word i, num;
if ((obj_state == NULL) || obj_state->os_dynndx == SHN_UNDEF)
return;
if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_NEEDED)) == 0))
type = DYN_OPT_F_NEEDED;
else if ((strcmp(opt, MSG_ORIG(MSG_STR_MINUS_DYNNDX)) == 0))
type = DYN_OPT_F_DYNNDX_VAL;
else
return;
dynsec = elfedit_sec_getdyn(obj_state, &dyn, &num);
switch (type) {
case DYN_OPT_F_NEEDED:
strsec = elfedit_sec_getstr(obj_state,
dynsec->sec_shdr->sh_link, 0);
for (; num-- > 0; dyn++)
if (dyn->d_tag == DT_NEEDED)
elfedit_cpl_match(cpldata,
elfedit_offset_to_str(strsec,
dyn->d_un.d_val, ELFEDIT_MSG_DEBUG,
0), 0);
break;
case DYN_OPT_F_DYNNDX_VAL:
for (i = 0; i < num; i++, dyn++)
if (dyn->d_tag == DT_POSFLAG_1)
elfedit_cpl_ndx(cpldata, i);
break;
}
return;
}
elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_P1);
}
static void
cpl_flags(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
const char *argv[], int num_opt)
{
elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF);
}
static void
cpl_flags1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
const char *argv[], int num_opt)
{
elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DF_1);
}
static void
cpl_feature1(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
const char *argv[], int num_opt)
{
elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_DTF_1);
}
static void
cpl_sunw_ldmach(elfedit_obj_state_t *obj_state, void *cpldata, int argc,
const char *argv[], int num_opt)
{
argc -= num_opt;
argv += num_opt;
if (argc == 1)
elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_EM);
}
static elfedit_cmdret_t
cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_DUMP, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_TAG, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_VALUE, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_DELETE, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_MOVE, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_runpath(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_RUNPATH, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_posflag1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_POSFLAG1, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_flags(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_FLAGS, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_flags1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_FLAGS1, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_feature1(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_FEATURE1, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_checksum(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_CHECKSUM, obj_state, argc, argv));
}
static elfedit_cmdret_t
cmd_sunw_ldmach(elfedit_obj_state_t *obj_state, int argc, const char *argv[])
{
return (cmd_body(DYN_CMD_T_SUNW_LDMACH, obj_state, argc, argv));
}
elfedit_module_t *
elfedit_init(elfedit_module_version_t version)
{
static elfedit_cmd_optarg_t opt_ostyle[] = {
{ ELFEDIT_STDOA_OPT_O, 0,
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ NULL }
};
static elfedit_cmd_optarg_t opt_ostyle_bitop[] = {
{ ELFEDIT_STDOA_OPT_AND, 0,
ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR },
{ ELFEDIT_STDOA_OPT_CMP, 0,
ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 },
{ ELFEDIT_STDOA_OPT_O, 0,
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ ELFEDIT_STDOA_OPT_OR, 0,
ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND },
{ NULL }
};
static elfedit_cmd_optarg_t opt_minus_dynndx[] = {
{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0,
DYN_OPT_F_DYNNDX_ELT, 0 },
{ NULL }
};
static const char *name_dump[] = {
MSG_ORIG(MSG_CMD_DUMP),
MSG_ORIG(MSG_STR_EMPTY),
NULL
};
static elfedit_cmd_optarg_t arg_dump[] = {
{ MSG_ORIG(MSG_STR_ELT),
ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
ELFEDIT_CMDOA_F_OPT },
{ NULL }
};
static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL };
static elfedit_cmd_optarg_t opt_tag[] = {
{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0,
DYN_OPT_F_DYNNDX_ELT, 0 },
{ ELFEDIT_STDOA_OPT_O, 0,
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ NULL }
};
static elfedit_cmd_optarg_t arg_tag[] = {
{ MSG_ORIG(MSG_STR_ELT),
ELFEDIT_I18NHDL(MSG_A1_TAG_ELT),
ELFEDIT_CMDOA_F_OPT },
{ MSG_ORIG(MSG_STR_VALUE),
ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE),
ELFEDIT_CMDOA_F_OPT },
{ NULL }
};
static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL };
static elfedit_cmd_optarg_t opt_value[] = {
{ MSG_ORIG(MSG_STR_MINUS_ADD),
ELFEDIT_I18NHDL(MSG_OPTDESC_ADD), 0,
DYN_OPT_F_ADD, DYN_OPT_F_DYNNDX_ELT },
{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_ELT), 0,
DYN_OPT_F_DYNNDX_ELT, DYN_OPT_F_ADD },
{ ELFEDIT_STDOA_OPT_O, 0,
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ MSG_ORIG(MSG_STR_MINUS_S),
ELFEDIT_I18NHDL(MSG_OPTDESC_S), 0,
DYN_OPT_F_STRVAL, 0 },
{ NULL }
};
static elfedit_cmd_optarg_t arg_value[] = {
{ MSG_ORIG(MSG_STR_ELT),
ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
ELFEDIT_CMDOA_F_OPT },
{ MSG_ORIG(MSG_STR_VALUE),
ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE),
ELFEDIT_CMDOA_F_OPT },
{ NULL }
};
static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL };
static elfedit_cmd_optarg_t arg_delete[] = {
{ MSG_ORIG(MSG_STR_ELT),
ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
0 },
{ MSG_ORIG(MSG_STR_COUNT),
ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT),
ELFEDIT_CMDOA_F_OPT },
{ NULL }
};
static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL };
static elfedit_cmd_optarg_t arg_move[] = {
{ MSG_ORIG(MSG_STR_ELT),
ELFEDIT_I18NHDL(MSG_ARGDESC_ELT),
0 },
{ MSG_ORIG(MSG_STR_DST_INDEX),
ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX),
0 },
{ MSG_ORIG(MSG_STR_COUNT),
ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT),
ELFEDIT_CMDOA_F_OPT },
{ NULL }
};
static const char *name_runpath[] = { MSG_ORIG(MSG_CMD_RUNPATH),
MSG_ORIG(MSG_CMD_RUNPATH_A1), NULL };
static elfedit_cmd_optarg_t arg_runpath[] = {
{ MSG_ORIG(MSG_STR_NEWPATH),
ELFEDIT_I18NHDL(MSG_A1_RUNPATH_NEWPATH),
ELFEDIT_CMDOA_F_OPT },
{ NULL }
};
static const char *name_posflag1[] = { MSG_ORIG(MSG_CMD_POSFLAG1),
NULL };
static elfedit_cmd_optarg_t opt_posflag1[] = {
{ ELFEDIT_STDOA_OPT_AND, 0,
ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_AND, DYN_OPT_F_OR },
{ ELFEDIT_STDOA_OPT_CMP, 0,
ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_CMP, 0 },
{ MSG_ORIG(MSG_STR_MINUS_DYNNDX),
ELFEDIT_I18NHDL(MSG_OPTDESC_DYNNDX_VAL),
ELFEDIT_CMDOA_F_VALUE,
DYN_OPT_F_DYNNDX_VAL, DYN_OPT_F_NEEDED },
{ MSG_ORIG(MSG_STR_INDEX), 0, 0, 0 },
{ MSG_ORIG(MSG_STR_MINUS_NEEDED),
ELFEDIT_I18NHDL(MSG_OPTDESC_NEEDED),
ELFEDIT_CMDOA_F_VALUE,
DYN_OPT_F_NEEDED, DYN_OPT_F_DYNNDX_VAL },
{ MSG_ORIG(MSG_STR_PREFIX), 0, 0, 0 },
{ ELFEDIT_STDOA_OPT_O, 0,
ELFEDIT_CMDOA_F_INHERIT, 0, 0 },
{ ELFEDIT_STDOA_OPT_OR, 0,
ELFEDIT_CMDOA_F_INHERIT, DYN_OPT_F_OR, DYN_OPT_F_AND },
{ NULL }
};
static elfedit_cmd_optarg_t arg_posflag1[] = {
{ MSG_ORIG(MSG_STR_VALUE),
ELFEDIT_I18NHDL(MSG_A1_POSFLAG1_VALUE),
ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
{ NULL }
};
static const char *name_flags[] = { MSG_ORIG(MSG_CMD_FLAGS), NULL };
static elfedit_cmd_optarg_t arg_flags[] = {
{ MSG_ORIG(MSG_STR_VALUE),
ELFEDIT_I18NHDL(MSG_A1_FLAGS_VALUE),
ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
{ NULL }
};
static const char *name_flags1[] = { MSG_ORIG(MSG_CMD_FLAGS1), NULL };
static elfedit_cmd_optarg_t arg_flags1[] = {
{ MSG_ORIG(MSG_STR_VALUE),
ELFEDIT_I18NHDL(MSG_A1_FLAGS1_VALUE),
ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
{ NULL }
};
static const char *name_feature1[] = { MSG_ORIG(MSG_CMD_FEATURE1),
NULL };
static elfedit_cmd_optarg_t arg_feature1[] = {
{ MSG_ORIG(MSG_STR_VALUE),
ELFEDIT_I18NHDL(MSG_A1_FEATURE1_VALUE),
ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT },
{ NULL }
};
static const char *name_checksum[] = { MSG_ORIG(MSG_CMD_CHECKSUM),
NULL };
static const char *name_sunw_ldmach[] = { MSG_ORIG(MSG_CMD_SUNW_LDMACH),
NULL };
static elfedit_cmd_optarg_t arg_sunw_ldmach[] = {
{ MSG_ORIG(MSG_STR_VALUE),
ELFEDIT_I18NHDL(MSG_A1_SUNW_LDMACH_VALUE),
ELFEDIT_CMDOA_F_OPT },
{ NULL }
};
static elfedit_cmd_t cmds[] = {
{ cmd_dump, cpl_eltarg, name_dump,
ELFEDIT_I18NHDL(MSG_DESC_DUMP),
ELFEDIT_I18NHDL(MSG_HELP_DUMP),
opt_minus_dynndx, arg_dump },
{ cmd_tag, cpl_tag, name_tag,
ELFEDIT_I18NHDL(MSG_DESC_TAG),
ELFEDIT_I18NHDL(MSG_HELP_TAG),
opt_tag, arg_tag },
{ cmd_value, cpl_eltarg, name_value,
ELFEDIT_I18NHDL(MSG_DESC_VALUE),
ELFEDIT_I18NHDL(MSG_HELP_VALUE),
opt_value, arg_value },
{ cmd_delete, cpl_eltarg, name_delete,
ELFEDIT_I18NHDL(MSG_DESC_DELETE),
ELFEDIT_I18NHDL(MSG_HELP_DELETE),
opt_minus_dynndx, arg_delete },
{ cmd_move, cpl_eltarg, name_move,
ELFEDIT_I18NHDL(MSG_DESC_MOVE),
ELFEDIT_I18NHDL(MSG_HELP_MOVE),
opt_minus_dynndx, arg_move },
{ cmd_runpath, NULL, name_runpath,
ELFEDIT_I18NHDL(MSG_DESC_RUNPATH),
ELFEDIT_I18NHDL(MSG_HELP_RUNPATH),
opt_ostyle, arg_runpath },
{ cmd_posflag1, cpl_posflag1, name_posflag1,
ELFEDIT_I18NHDL(MSG_DESC_POSFLAG1),
ELFEDIT_I18NHDL(MSG_HELP_POSFLAG1),
opt_posflag1, arg_posflag1 },
{ cmd_flags, cpl_flags, name_flags,
ELFEDIT_I18NHDL(MSG_DESC_FLAGS),
ELFEDIT_I18NHDL(MSG_HELP_FLAGS),
opt_ostyle_bitop, arg_flags },
{ cmd_flags1, cpl_flags1, name_flags1,
ELFEDIT_I18NHDL(MSG_DESC_FLAGS1),
ELFEDIT_I18NHDL(MSG_HELP_FLAGS1),
opt_ostyle_bitop, arg_flags1 },
{ cmd_feature1, cpl_feature1, name_feature1,
ELFEDIT_I18NHDL(MSG_DESC_FEATURE1),
ELFEDIT_I18NHDL(MSG_HELP_FEATURE1),
opt_ostyle_bitop, arg_feature1 },
{ cmd_checksum, NULL, name_checksum,
ELFEDIT_I18NHDL(MSG_DESC_CHECKSUM),
ELFEDIT_I18NHDL(MSG_HELP_CHECKSUM),
NULL, NULL },
{ cmd_sunw_ldmach, cpl_sunw_ldmach, name_sunw_ldmach,
ELFEDIT_I18NHDL(MSG_DESC_SUNW_LDMACH),
ELFEDIT_I18NHDL(MSG_HELP_SUNW_LDMACH),
opt_ostyle, arg_sunw_ldmach },
{ NULL }
};
static elfedit_module_t module = {
ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME),
ELFEDIT_I18NHDL(MSG_MOD_DESC), cmds, mod_i18nhdl_to_str };
return (&module);
}