1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <ctype.h> 29 #include <machdep.h> 30 #include <elfedit.h> 31 #include <sys/elf_SPARC.h> 32 #include <strings.h> 33 #include <debug.h> 34 #include <conv.h> 35 #include <cap_msg.h> 36 37 38 /* 39 * Capabilities section 40 */ 41 42 43 44 45 /* 46 * This module uses shared code for several of the commands. 47 * It is sometimes necessary to know which specific command 48 * is active. 49 */ 50 typedef enum { 51 /* Dump command, used as module default to display dynamic section */ 52 CAP_CMD_T_DUMP = 0, /* cap:dump */ 53 54 /* Commands that do not correspond directly to a specific DT tag */ 55 CAP_CMD_T_TAG = 1, /* cap:tag */ 56 CAP_CMD_T_VALUE = 2, /* cap:value */ 57 CAP_CMD_T_DELETE = 3, /* cap:delete */ 58 CAP_CMD_T_MOVE = 4, /* cap:shift */ 59 60 /* Commands that embody tag specific knowledge */ 61 CAP_CMD_T_HW1 = 5, /* cap:hw1 */ 62 CAP_CMD_T_SF1 = 6, /* cap:sf1 */ 63 } CAP_CMD_T; 64 65 66 67 #ifndef _ELF64 68 /* 69 * We supply this function for the msg module 70 */ 71 const char * 72 _cap_msg(Msg mid) 73 { 74 return (gettext(MSG_ORIG(mid))); 75 } 76 #endif 77 78 79 /* 80 * This function is supplied to elfedit through our elfedit_module_t 81 * definition. It translates the opaque elfedit_i18nhdl_t handles 82 * in our module interface into the actual strings for elfedit to 83 * use. 84 * 85 * note: 86 * This module uses Msg codes for its i18n handle type. 87 * So the translation is simply to use MSG_INTL() to turn 88 * it into a string and return it. 89 */ 90 static const char * 91 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 92 { 93 Msg msg = (Msg)hdl; 94 95 return (MSG_INTL(msg)); 96 } 97 98 99 100 /* 101 * The cap_opt_t enum specifies a bit value for every optional 102 * argument allowed by a command in this module. 103 */ 104 typedef enum { 105 CAP_OPT_F_AND = 1, /* -and: AND (&) values to dest */ 106 CAP_OPT_F_CMP = 2, /* -cmp: Complement (~) values */ 107 CAP_OPT_F_CAPNDX = 4, /* -capndx: elt is tag index, */ 108 /* not name */ 109 CAP_OPT_F_OR = 8, /* -or: OR (|) values to dest */ 110 } cap_opt_t; 111 112 113 /* 114 * A variable of type ARGSTATE is used by each command to maintain 115 * information about the arguments and related things. It is 116 * initialized by process_args(), and used by the other routines. 117 */ 118 typedef struct { 119 elfedit_obj_state_t *obj_state; 120 struct { 121 elfedit_section_t *sec; /* Capabilities section reference */ 122 Cap *data; /* Start of capabilities section data */ 123 Word num; /* # Capabilities elts */ 124 } cap; 125 cap_opt_t optmask; /* Mask of options used */ 126 int argc; /* # of plain arguments */ 127 const char **argv; /* Plain arguments */ 128 } ARGSTATE; 129 130 131 132 /* 133 * Standard argument processing for cap module 134 * 135 * entry 136 * obj_state, argc, argv - Standard command arguments 137 * argstate - Address of ARGSTATE block to be initialized 138 * 139 * exit: 140 * On success, *argstate is initialized. On error, 141 * an error is issued and this routine does not return. 142 */ 143 static void 144 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 145 ARGSTATE *argstate) 146 { 147 elfedit_getopt_state_t getopt_state; 148 elfedit_getopt_ret_t *getopt_ret; 149 150 bzero(argstate, sizeof (*argstate)); 151 argstate->obj_state = obj_state; 152 153 elfedit_getopt_init(&getopt_state, &argc, &argv); 154 155 /* Add each new option to the options mask */ 156 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) 157 argstate->optmask |= getopt_ret->gor_idmask; 158 159 /* If there may be an arbitrary amount of output, use a pager */ 160 if (argc == 0) 161 elfedit_pager_init(); 162 163 /* Return the updated values of argc/argv */ 164 argstate->argc = argc; 165 argstate->argv = argv; 166 167 /* Locate the capabilities section */ 168 argstate->cap.sec = elfedit_sec_getcap(obj_state, &argstate->cap.data, 169 &argstate->cap.num); 170 } 171 172 173 174 /* 175 * Print ELF capabilities values, taking the calling command, and output style 176 * into account. 177 * 178 * entry: 179 * cmd - CAP_CMD_T_* value giving identify of caller 180 * autoprint - If True, output is only produced if the elfedit 181 * autoprint flag is set. If False, output is always produced. 182 * argstate - Argument state block 183 * print_type - Specifies which capabilities elements to display. 184 * ndx = If print_type is PRINT_CAP_T_NDX, displays the index specified. 185 * Otherwise ignored. 186 */ 187 typedef enum { 188 PRINT_CAP_T_ALL = 0, /* Show all indexes */ 189 PRINT_CAP_T_NDX = 1, /* Show capabilities[arg] only */ 190 PRINT_CAP_T_TAG = 2 /* Show all elts with tag type */ 191 /* given by arg */ 192 } PRINT_CAP_T; 193 194 static void 195 print_cap(CAP_CMD_T cmd, int autoprint, ARGSTATE *argstate, 196 PRINT_CAP_T print_type, Word arg) 197 { 198 elfedit_outstyle_t outstyle; 199 Word cnt, ndx, printed = 0; 200 Cap *cap; 201 int header_done = 0; 202 Xword last_c_val = 0; 203 204 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 205 return; 206 207 /* 208 * Pick an output style. cap:dump is required to use the default 209 * style. The other commands use the current output style. 210 */ 211 outstyle = (cmd == CAP_CMD_T_DUMP) ? 212 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 213 214 /* How many elements do we examine? */ 215 if (print_type == PRINT_CAP_T_NDX) { 216 if (arg >= argstate->cap.num) 217 return; /* Out of range */ 218 ndx = arg; 219 cnt = 1; 220 } else { 221 ndx = 0; 222 cnt = argstate->cap.num; 223 } 224 225 cap = &argstate->cap.data[ndx]; 226 for (; cnt--; cap++, ndx++) { 227 /* 228 * If we are only displaying certain tag types and 229 * this isn't one of those, move on to next element. 230 */ 231 if ((print_type == PRINT_CAP_T_TAG) && (cap->c_tag != arg)) 232 continue; 233 234 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 235 if (header_done == 0) { 236 header_done = 1; 237 Elf_cap_title(0); 238 } 239 Elf_cap_entry(NULL, cap, ndx, 240 argstate->obj_state->os_ehdr->e_machine); 241 } else { 242 /* 243 * In simple or numeric mode under a print type 244 * that is based on tag type rather than on index, 245 * quietly: If we've already printed this value, 246 * don't print it again. A common example of this 247 * is PRINT_CAP_T_RUNPATH when both CA_RPATH and 248 * CA_RUNPATH are present with the same value. 249 */ 250 if ((print_type == PRINT_CAP_T_TAG) && printed && 251 (last_c_val == cap->c_un.c_val)) 252 continue; 253 254 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 255 union { 256 Conv_cap_val_hw1_buf_t hw1; 257 Conv_cap_val_sf1_buf_t sf1; 258 } c_buf; 259 260 switch (cap->c_tag) { 261 case CA_SUNW_HW_1: 262 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 263 conv_cap_val_hw1(cap->c_un.c_val, 264 argstate->obj_state->os_ehdr-> 265 e_machine, 266 CONV_FMT_NOBKT, &c_buf.hw1)); 267 printed = 1; 268 continue; 269 case CA_SUNW_SF_1: 270 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 271 conv_cap_val_sf1(cap->c_un.c_val, 272 argstate->obj_state->os_ehdr-> 273 e_machine, 274 CONV_FMT_NOBKT, &c_buf.sf1)); 275 printed = 1; 276 continue; 277 } 278 } 279 elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), 280 cap->c_un.c_val); 281 } 282 printed = 1; 283 last_c_val = cap->c_un.c_val; 284 } 285 286 /* 287 * If nothing was output under the print types that are 288 * based on tag type, issue an error saying it doesn't exist. 289 */ 290 if (!printed && (print_type == PRINT_CAP_T_TAG)) { 291 Conv_inv_buf_t inv_buf; 292 293 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT), 294 EC_WORD(argstate->cap.sec->sec_shndx), 295 argstate->cap.sec->sec_name, conv_cap_tag(arg, &inv_buf)); 296 } 297 } 298 299 300 /* 301 * Process the elt argument: This will be a tag type if -capndx is 302 * not present and this is a print request. It will be an index otherwise. 303 * 304 * entry: 305 * argstate - Argument state block 306 * arg - Argument string to be converted into an index 307 * argname - String giving the name by which the argument is 308 * referred in the online help for the command. 309 * print_request - True if the command is to print the current 310 * value(s) and return without changing anything. 311 * print_type - Address of variable containing PRINT_CAP_T_ 312 * code specifying how the elements will be displayed. 313 * 314 * exit: 315 * If print_request is False: arg is converted into an integer value. 316 * If -capndx was used, we convert it into an integer. If it was not 317 * used, then arg is a tag name --- we find the first capabilities entry 318 * that matches. If no entry matches, and there is an extra CA_NULL, 319 * it is added. Otherwise an error is issued. *print_type is set 320 * to PRINT_CAP_T_NDX. 321 * 322 * If print_request is True: If -capndx was used, arg is converted into 323 * an integer value, *print_type is set to PRINT_CAP_T_NDX, and 324 * the value is returned. If -capndx was not used, *print_type is set to 325 * PRINT_CAP_T_TAG, and the tag value is returned. 326 */ 327 static Word 328 arg_to_index(ARGSTATE *argstate, const char *arg, const char *argname, 329 int print_request, PRINT_CAP_T *print_type) 330 { 331 Word ndx, ca_value; 332 333 334 /* Assume we are returning an index, alter as needed below */ 335 *print_type = PRINT_CAP_T_NDX; 336 337 /* If -capndx was used, this is a simple numeric index */ 338 if ((argstate->optmask & CAP_OPT_F_CAPNDX) != 0) 339 return ((Word) elfedit_atoui_range(arg, argname, 0, 340 argstate->cap.num - 1, NULL)); 341 342 /* The argument is a CA_ tag type, not a numeric index */ 343 ca_value = (Word) elfedit_atoconst(arg, ELFEDIT_CONST_CA); 344 345 /* 346 * If this is a printing request, then we let print_cap() show 347 * all the items with this tag type. 348 */ 349 if (print_request) { 350 *print_type = PRINT_CAP_T_TAG; 351 return (ca_value); 352 } 353 354 /* Locate the first entry with the given tag type */ 355 for (ndx = 0; ndx < argstate->cap.num; ndx++) { 356 if (argstate->cap.data[ndx].c_tag == ca_value) { 357 elfedit_msg(ELFEDIT_MSG_DEBUG, 358 MSG_INTL(MSG_DEBUG_CA2NDX), 359 EC_WORD(argstate->cap.sec->sec_shndx), 360 argstate->cap.sec->sec_name, EC_WORD(ndx), arg); 361 return (ndx); 362 } 363 } 364 365 /* No room to create one, so we're out of options and must fail */ 366 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT), 367 EC_WORD(argstate->cap.sec->sec_shndx), 368 argstate->cap.sec->sec_name, arg); 369 370 /*NOTREACHED*/ 371 return (0); /* For lint */ 372 } 373 374 375 /* 376 * Argument processing for the bitmask commands. Convert the arguments 377 * to integer form, apply -and/-cmp/-or, and return the resulting value. 378 * 379 * entry: 380 * argstate - Argument state block 381 * orig - Value of original bitmask 382 * const_sym - NULL, or array of name->integer mappings for 383 * applicable symbolic constant names. 384 */ 385 static Word 386 flag_bitop(ARGSTATE *argstate, Word orig, const elfedit_atoui_sym_t *const_sym) 387 { 388 Word flags = 0; 389 int i; 390 391 /* Collect the arguments */ 392 for (i = 0; i < argstate->argc; i++) 393 flags |= (Word) elfedit_atoui(argstate->argv[i], const_sym); 394 395 /* Complement the value? */ 396 if (argstate->optmask & CAP_OPT_F_CMP) 397 flags = ~flags; 398 399 /* Perform any requested bit operations */ 400 if (argstate->optmask & CAP_OPT_F_AND) 401 flags &= orig; 402 else if (argstate->optmask & CAP_OPT_F_OR) 403 flags |= orig; 404 405 return (flags); 406 } 407 408 409 410 /* 411 * Common body for the cap: module commands. These commands 412 * share a large amount of common behavior, so it is convenient 413 * to centralize things and use the cmd argument to handle the 414 * small differences. 415 * 416 * entry: 417 * cmd - One of the CAP_CMD_T_* constants listed above, specifying 418 * which command to implement. 419 * obj_state, argc, argv - Standard command arguments 420 */ 421 static elfedit_cmdret_t 422 cmd_body(CAP_CMD_T cmd, elfedit_obj_state_t *obj_state, 423 int argc, const char *argv[]) 424 { 425 ARGSTATE argstate; 426 Cap *cap; 427 const char *cap_name; 428 Word cap_ndx, cap_num; 429 elfedit_cmdret_t ret = ELFEDIT_CMDRET_NONE; 430 PRINT_CAP_T print_type = PRINT_CAP_T_ALL; 431 Word ndx; 432 int print_only = 0; 433 int do_autoprint = 1; 434 435 /* Process the optional arguments */ 436 process_args(obj_state, argc, argv, &argstate); 437 438 cap = argstate.cap.data; 439 cap_num = argstate.cap.num; 440 cap_name = argstate.cap.sec->sec_name; 441 cap_ndx = argstate.cap.sec->sec_shndx; 442 443 /* Check number of arguments, gather information */ 444 switch (cmd) { 445 case CAP_CMD_T_DUMP: 446 /* cap:dump can accept an optional index argument */ 447 if (argstate.argc > 1) 448 elfedit_command_usage(); 449 print_only = 1; 450 if (argstate.argc == 1) 451 ndx = arg_to_index(&argstate, argstate.argv[0], 452 MSG_ORIG(MSG_STR_ELT), print_only, &print_type); 453 break; 454 455 case CAP_CMD_T_TAG: 456 case CAP_CMD_T_VALUE: 457 print_only = (argstate.argc != 2); 458 if (argstate.argc > 0) { 459 if (argstate.argc > 2) 460 elfedit_command_usage(); 461 ndx = arg_to_index(&argstate, argstate.argv[0], 462 MSG_ORIG(MSG_STR_ELT), print_only, &print_type); 463 } 464 break; 465 466 case CAP_CMD_T_DELETE: 467 if ((argstate.argc < 1) || (argstate.argc > 2)) 468 elfedit_command_usage(); 469 ndx = arg_to_index(&argstate, argstate.argv[0], 470 MSG_ORIG(MSG_STR_ELT), 471 0, &print_type); 472 do_autoprint = 0; 473 break; 474 475 case CAP_CMD_T_MOVE: 476 if ((argstate.argc < 2) || (argstate.argc > 3)) 477 elfedit_command_usage(); 478 ndx = arg_to_index(&argstate, argstate.argv[0], 479 MSG_ORIG(MSG_STR_ELT), 0, &print_type); 480 do_autoprint = 0; 481 break; 482 483 case CAP_CMD_T_HW1: 484 print_only = (argstate.argc == 0); 485 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 486 ELFEDIT_CONST_CA, CA_SUNW_HW_1, 1), 487 MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); 488 break; 489 490 case CAP_CMD_T_SF1: 491 print_only = (argstate.argc == 0); 492 ndx = arg_to_index(&argstate, elfedit_atoconst_value_to_str( 493 ELFEDIT_CONST_CA, CA_SUNW_SF_1, 1), 494 MSG_ORIG(MSG_STR_VALUE), print_only, &print_type); 495 break; 496 497 default: 498 /* Note expected: All commands should have been caught above */ 499 elfedit_command_usage(); 500 break; 501 } 502 503 504 /* If this is a request to print current values, do it and return */ 505 if (print_only) { 506 print_cap(cmd, 0, &argstate, print_type, ndx); 507 return (ELFEDIT_CMDRET_NONE); 508 } 509 510 511 switch (cmd) { 512 /* 513 * CAP_CMD_T_DUMP can't get here: It is a print-only 514 * command. 515 */ 516 517 case CAP_CMD_T_TAG: 518 { 519 Conv_inv_buf_t inv_buf1, inv_buf2; 520 Word c_tag = (Word) elfedit_atoconst(argstate.argv[1], 521 ELFEDIT_CONST_CA); 522 523 if (cap[ndx].c_tag == c_tag) { 524 elfedit_msg(ELFEDIT_MSG_DEBUG, 525 MSG_INTL(MSG_DEBUG_S_OK), 526 cap_ndx, cap_name, EC_WORD(ndx), 527 conv_cap_tag(c_tag, &inv_buf1)); 528 } else { 529 elfedit_msg(ELFEDIT_MSG_DEBUG, 530 MSG_INTL(MSG_DEBUG_S_CHG), 531 cap_ndx, cap_name, EC_WORD(ndx), 532 conv_cap_tag(cap[ndx].c_tag, &inv_buf1), 533 conv_cap_tag(c_tag, &inv_buf2)); 534 cap[ndx].c_tag = c_tag; 535 ret = ELFEDIT_CMDRET_MOD; 536 } 537 } 538 break; 539 540 case CAP_CMD_T_VALUE: 541 { 542 Xword c_val = (Xword) 543 elfedit_atoui(argstate.argv[1], NULL); 544 545 if (cap[ndx].c_un.c_val == c_val) { 546 elfedit_msg(ELFEDIT_MSG_DEBUG, 547 MSG_INTL(MSG_DEBUG_X_OK), 548 argstate.cap.sec->sec_shndx, 549 argstate.cap.sec->sec_name, 550 EC_WORD(ndx), EC_XWORD(c_val)); 551 } else { 552 elfedit_msg(ELFEDIT_MSG_DEBUG, 553 MSG_INTL(MSG_DEBUG_X_CHG), 554 argstate.cap.sec->sec_shndx, 555 argstate.cap.sec->sec_name, 556 EC_WORD(ndx), EC_XWORD(cap[ndx].c_un.c_val), 557 EC_XWORD(c_val)); 558 cap[ndx].c_un.c_val = c_val; 559 ret = ELFEDIT_CMDRET_MOD; 560 } 561 } 562 break; 563 564 case CAP_CMD_T_DELETE: 565 { 566 Word cnt = (argstate.argc == 1) ? 1 : 567 (Word) elfedit_atoui_range(argstate.argv[1], 568 MSG_ORIG(MSG_STR_COUNT), 1, cap_num - ndx, NULL); 569 const char *msg_prefix = 570 elfedit_sec_msgprefix(argstate.cap.sec); 571 572 elfedit_array_elts_delete(msg_prefix, argstate.cap.data, 573 sizeof (Cap), cap_num, ndx, cnt); 574 ret = ELFEDIT_CMDRET_MOD; 575 } 576 break; 577 578 case CAP_CMD_T_MOVE: 579 { 580 Cap save; 581 Word cnt; 582 Word dstndx; 583 const char *msg_prefix = 584 elfedit_sec_msgprefix(argstate.cap.sec); 585 586 dstndx = (Word) 587 elfedit_atoui_range(argstate.argv[1], 588 MSG_ORIG(MSG_STR_DST_INDEX), 0, cap_num - 1, 589 NULL); 590 if (argstate.argc == 2) { 591 cnt = 1; 592 } else { 593 cnt = (Word) elfedit_atoui_range( 594 argstate.argv[2], MSG_ORIG(MSG_STR_COUNT), 595 1, cap_num, NULL); 596 } 597 elfedit_array_elts_move(msg_prefix, argstate.cap.data, 598 sizeof (save), cap_num, ndx, dstndx, cnt, &save); 599 ret = ELFEDIT_CMDRET_MOD; 600 } 601 break; 602 603 604 case CAP_CMD_T_HW1: 605 { 606 Conv_cap_val_hw1_buf_t buf1, buf2; 607 Half mach = argstate.obj_state->os_ehdr->e_machine; 608 Xword hw1; 609 610 hw1 = flag_bitop(&argstate, cap[ndx].c_un.c_val, 611 elfedit_mach_sunw_hw1_to_atoui(mach)); 612 613 /* Set the value */ 614 if (cap[ndx].c_un.c_val == hw1) { 615 elfedit_msg(ELFEDIT_MSG_DEBUG, 616 MSG_INTL(MSG_DEBUG_BSB_OK), cap_ndx, 617 cap_name, EC_WORD(ndx), 618 conv_cap_val_hw1(cap[ndx].c_un.c_val, mach, 619 CONV_FMT_NOBKT, &buf1)); 620 } else { 621 elfedit_msg(ELFEDIT_MSG_DEBUG, 622 MSG_INTL(MSG_DEBUG_BSB_CHG), 623 cap_ndx, cap_name, EC_WORD(ndx), 624 conv_cap_val_hw1(cap[ndx].c_un.c_val, mach, 625 CONV_FMT_NOBKT, &buf1), 626 conv_cap_val_hw1(hw1, mach, 627 CONV_FMT_NOBKT, &buf2)); 628 ret = ELFEDIT_CMDRET_MOD; 629 cap[ndx].c_un.c_val = hw1; 630 } 631 } 632 break; 633 634 case CAP_CMD_T_SF1: 635 { 636 Conv_cap_val_sf1_buf_t buf1, buf2; 637 Half mach = argstate.obj_state->os_ehdr->e_machine; 638 Xword sf1; 639 640 sf1 = flag_bitop(&argstate, cap[ndx].c_un.c_val, 641 elfedit_const_to_atoui(ELFEDIT_CONST_SF1_SUNW)); 642 643 /* Set the value */ 644 if (cap[ndx].c_un.c_val == sf1) { 645 elfedit_msg(ELFEDIT_MSG_DEBUG, 646 MSG_INTL(MSG_DEBUG_BSB_OK), cap_ndx, 647 cap_name, EC_WORD(ndx), 648 conv_cap_val_sf1(cap[ndx].c_un.c_val, mach, 649 CONV_FMT_NOBKT, &buf1)); 650 } else { 651 elfedit_msg(ELFEDIT_MSG_DEBUG, 652 MSG_INTL(MSG_DEBUG_BSB_CHG), 653 cap_ndx, cap_name, EC_WORD(ndx), 654 conv_cap_val_sf1(cap[ndx].c_un.c_val, mach, 655 CONV_FMT_NOBKT, &buf1), 656 conv_cap_val_sf1(sf1, mach, 657 CONV_FMT_NOBKT, &buf2)); 658 ret = ELFEDIT_CMDRET_MOD; 659 cap[ndx].c_un.c_val = sf1; 660 } 661 } 662 break; 663 } 664 665 /* 666 * If we modified the capabilities section header, tell libelf. 667 */ 668 if (ret == ELFEDIT_CMDRET_MOD) 669 elfedit_modified_data(argstate.cap.sec); 670 671 /* Do autoprint */ 672 if (do_autoprint) 673 print_cap(cmd, 1, &argstate, print_type, ndx); 674 675 return (ret); 676 } 677 678 679 680 /* 681 * Command completion functions for the commands 682 */ 683 684 /* 685 * Command completion for the first argument, which specifies 686 * the capabilities element to use. Examines the options to see if 687 * -capndx is present, and if not, supplies the completion 688 * strings for argument 1. 689 */ 690 /*ARGSUSED*/ 691 static void 692 cpl_eltarg(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 693 const char *argv[], int num_opt) 694 { 695 Word i; 696 697 /* Make sure it's the first argument */ 698 if ((argc - num_opt) != 1) 699 return; 700 701 /* Is -capndx present? If so, we don't complete tag types */ 702 for (i = 0; i < num_opt; i++) 703 if (strcmp(argv[i], MSG_ORIG(MSG_STR_MINUS_CAPNDX)) == 0) 704 return; 705 706 /* 707 * Supply capability tag names. There are very few of these, so 708 * rather than worry about whether a given tag exists in the 709 * file or not, we simply serve up all the possibilities. 710 */ 711 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_CA); 712 } 713 714 715 /*ARGSUSED*/ 716 static void 717 cpl_tag(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 718 const char *argv[], int num_opt) 719 { 720 /* First argument */ 721 if ((argc - num_opt) == 1) { 722 cpl_eltarg(obj_state, cpldata, argc, argv, num_opt); 723 return; 724 } 725 726 /* The second argument is always a tag value */ 727 if ((argc - num_opt) == 2) 728 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_CA); 729 } 730 731 /*ARGSUSED*/ 732 static void 733 cpl_hw1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 734 const char *argv[], int num_opt) 735 { 736 elfedit_atoui_sym_t *sym_const; 737 738 /* This routine allows multiple flags to be specified */ 739 740 /* 741 * If there is no object, then supply all the hardware 742 * capabilities we know of. 743 */ 744 if (obj_state == NULL) { 745 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_AV_386); 746 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_AV_SPARC); 747 return; 748 } 749 750 /* 751 * Supply the hardware capabilities for the type of 752 * machine the object is for, if we know any. 753 */ 754 sym_const = elfedit_mach_sunw_hw1_to_atoui( 755 obj_state->os_ehdr->e_machine); 756 if (sym_const != NULL) 757 elfedit_cpl_atoui(cpldata, sym_const); 758 } 759 760 /*ARGSUSED*/ 761 static void 762 cpl_sf1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 763 const char *argv[], int num_opt) 764 { 765 /* This routine allows multiple flags to be specified */ 766 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SF1_SUNW); 767 } 768 769 770 /* 771 * Implementation functions for the commands 772 */ 773 static elfedit_cmdret_t 774 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 775 { 776 return (cmd_body(CAP_CMD_T_DUMP, obj_state, argc, argv)); 777 } 778 779 static elfedit_cmdret_t 780 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 781 { 782 return (cmd_body(CAP_CMD_T_TAG, obj_state, argc, argv)); 783 } 784 785 static elfedit_cmdret_t 786 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 787 { 788 return (cmd_body(CAP_CMD_T_VALUE, obj_state, argc, argv)); 789 } 790 791 static elfedit_cmdret_t 792 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 793 { 794 return (cmd_body(CAP_CMD_T_DELETE, obj_state, argc, argv)); 795 } 796 797 static elfedit_cmdret_t 798 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 799 { 800 return (cmd_body(CAP_CMD_T_MOVE, obj_state, argc, argv)); 801 } 802 803 static elfedit_cmdret_t 804 cmd_hw1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 805 { 806 return (cmd_body(CAP_CMD_T_HW1, obj_state, argc, argv)); 807 } 808 809 static elfedit_cmdret_t 810 cmd_sf1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 811 { 812 return (cmd_body(CAP_CMD_T_SF1, obj_state, argc, argv)); 813 } 814 815 816 817 /*ARGSUSED*/ 818 elfedit_module_t * 819 elfedit_init(elfedit_module_version_t version) 820 { 821 /* For commands that only accept -and, -cmp, -o, and -or */ 822 static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { 823 { ELFEDIT_STDOA_OPT_AND, NULL, 824 ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_AND, CAP_OPT_F_OR }, 825 { ELFEDIT_STDOA_OPT_CMP, NULL, 826 ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_CMP, 0 }, 827 { ELFEDIT_STDOA_OPT_O, NULL, 828 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 829 { ELFEDIT_STDOA_OPT_OR, NULL, 830 ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_OR, CAP_OPT_F_AND }, 831 { NULL } 832 }; 833 834 /* For commands that only accept -capndx */ 835 static elfedit_cmd_optarg_t opt_capndx[] = { 836 { MSG_ORIG(MSG_STR_MINUS_CAPNDX), 837 /* MSG_INTL(MSG_OPTDESC_CAPNDX) */ 838 ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0, 839 CAP_OPT_F_CAPNDX, 0 }, 840 { NULL } 841 }; 842 843 /* For commands thataccept -capndx and output styles */ 844 static elfedit_cmd_optarg_t opt_ostyle_capndx[] = { 845 { MSG_ORIG(MSG_STR_MINUS_CAPNDX), 846 /* MSG_INTL(MSG_OPTDESC_CAPNDX) */ 847 ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0, 848 CAP_OPT_F_CAPNDX, 0 }, 849 { ELFEDIT_STDOA_OPT_O, NULL, 850 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 851 { NULL } 852 }; 853 854 855 /* cap:dump */ 856 static const char *name_dump[] = { 857 MSG_ORIG(MSG_CMD_DUMP), 858 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 859 NULL 860 }; 861 static elfedit_cmd_optarg_t arg_dump[] = { 862 { MSG_ORIG(MSG_STR_ELT), 863 /* MSG_INTL(MSG_ARGDESC_ELT) */ 864 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 865 ELFEDIT_CMDOA_F_OPT }, 866 { NULL } 867 }; 868 869 870 /* cap:tag */ 871 static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; 872 static elfedit_cmd_optarg_t arg_tag[] = { 873 { MSG_ORIG(MSG_STR_ELT), 874 /* MSG_INTL(MSG_A1_TAG_ELT) */ 875 ELFEDIT_I18NHDL(MSG_A1_TAG_ELT), 876 ELFEDIT_CMDOA_F_OPT }, 877 { MSG_ORIG(MSG_STR_VALUE), 878 /* MSG_INTL(MSG_A2_TAG_VALUE) */ 879 ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE), 880 ELFEDIT_CMDOA_F_OPT }, 881 { NULL } 882 }; 883 884 885 /* cap:value */ 886 static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; 887 static elfedit_cmd_optarg_t arg_value[] = { 888 { MSG_ORIG(MSG_STR_ELT), 889 /* MSG_INTL(MSG_ARGDESC_ELT) */ 890 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 891 ELFEDIT_CMDOA_F_OPT }, 892 { MSG_ORIG(MSG_STR_VALUE), 893 /* MSG_INTL(MSG_A2_VALUE_VALUE) */ 894 ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE), 895 ELFEDIT_CMDOA_F_OPT }, 896 { NULL } 897 }; 898 899 /* cap:delete */ 900 static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 901 static elfedit_cmd_optarg_t arg_delete[] = { 902 { MSG_ORIG(MSG_STR_ELT), 903 /* MSG_INTL(MSG_ARGDESC_ELT) */ 904 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 905 0 }, 906 { MSG_ORIG(MSG_STR_COUNT), 907 /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 908 ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 909 ELFEDIT_CMDOA_F_OPT }, 910 { NULL } 911 }; 912 913 /* cap:move */ 914 static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 915 static elfedit_cmd_optarg_t arg_move[] = { 916 { MSG_ORIG(MSG_STR_ELT), 917 /* MSG_INTL(MSG_ARGDESC_ELT) */ 918 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 919 0 }, 920 { MSG_ORIG(MSG_STR_DST_INDEX), 921 /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 922 ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 923 0 }, 924 { MSG_ORIG(MSG_STR_COUNT), 925 /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 926 ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 927 ELFEDIT_CMDOA_F_OPT }, 928 { NULL } 929 }; 930 931 /* cap:hw1 */ 932 static const char *name_hw1[] = { MSG_ORIG(MSG_CMD_HW1), NULL }; 933 static elfedit_cmd_optarg_t arg_hw1[] = { 934 { MSG_ORIG(MSG_STR_VALUE), 935 /* MSG_INTL(MSG_A1_HW1_VALUE) */ 936 ELFEDIT_I18NHDL(MSG_A1_HW1_VALUE), 937 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 938 { NULL } 939 }; 940 941 /* cap:sf1 */ 942 static const char *name_sf1[] = { MSG_ORIG(MSG_CMD_SF1), NULL }; 943 static elfedit_cmd_optarg_t arg_sf1[] = { 944 { MSG_ORIG(MSG_STR_VALUE), 945 /* MSG_INTL(MSG_A1_SF1_VALUE) */ 946 ELFEDIT_I18NHDL(MSG_A1_SF1_VALUE), 947 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 948 { NULL } 949 }; 950 951 952 953 954 static elfedit_cmd_t cmds[] = { 955 /* cap:dump */ 956 { cmd_dump, cpl_eltarg, name_dump, 957 /* MSG_INTL(MSG_DESC_DUMP) */ 958 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 959 /* MSG_INTL(MSG_HELP_DUMP) */ 960 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 961 opt_capndx, arg_dump }, 962 963 /* cap:tag */ 964 { cmd_tag, cpl_tag, name_tag, 965 /* MSG_INTL(MSG_DESC_TAG) */ 966 ELFEDIT_I18NHDL(MSG_DESC_TAG), 967 /* MSG_INTL(MSG_HELP_TAG) */ 968 ELFEDIT_I18NHDL(MSG_HELP_TAG), 969 opt_ostyle_capndx, arg_tag }, 970 971 /* cap:value */ 972 { cmd_value, cpl_eltarg, name_value, 973 /* MSG_INTL(MSG_DESC_VALUE) */ 974 ELFEDIT_I18NHDL(MSG_DESC_VALUE), 975 /* MSG_INTL(MSG_HELP_VALUE) */ 976 ELFEDIT_I18NHDL(MSG_HELP_VALUE), 977 opt_ostyle_capndx, arg_value }, 978 979 /* cap:delete */ 980 { cmd_delete, cpl_eltarg, name_delete, 981 /* MSG_INTL(MSG_DESC_DELETE) */ 982 ELFEDIT_I18NHDL(MSG_DESC_DELETE), 983 /* MSG_INTL(MSG_HELP_DELETE) */ 984 ELFEDIT_I18NHDL(MSG_HELP_DELETE), 985 opt_capndx, arg_delete }, 986 987 /* cap:move */ 988 { cmd_move, cpl_eltarg, name_move, 989 /* MSG_INTL(MSG_DESC_MOVE) */ 990 ELFEDIT_I18NHDL(MSG_DESC_MOVE), 991 /* MSG_INTL(MSG_HELP_MOVE) */ 992 ELFEDIT_I18NHDL(MSG_HELP_MOVE), 993 opt_capndx, arg_move }, 994 995 /* cap:hw1 */ 996 { cmd_hw1, cpl_hw1, name_hw1, 997 /* MSG_INTL(MSG_DESC_HW1) */ 998 ELFEDIT_I18NHDL(MSG_DESC_HW1), 999 /* MSG_INTL(MSG_HELP_HW1) */ 1000 ELFEDIT_I18NHDL(MSG_HELP_HW1), 1001 opt_ostyle_bitop, arg_hw1 }, 1002 1003 /* cap:sf1 */ 1004 { cmd_sf1, cpl_sf1, name_sf1, 1005 /* MSG_INTL(MSG_DESC_SF1) */ 1006 ELFEDIT_I18NHDL(MSG_DESC_SF1), 1007 /* MSG_INTL(MSG_HELP_SF1) */ 1008 ELFEDIT_I18NHDL(MSG_HELP_SF1), 1009 opt_ostyle_bitop, arg_sf1 }, 1010 1011 { NULL } 1012 }; 1013 1014 static elfedit_module_t module = { 1015 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 1016 /* MSG_INTL(MSG_MOD_DESC) */ 1017 ELFEDIT_I18NHDL(MSG_MOD_DESC), 1018 cmds, mod_i18nhdl_to_str }; 1019 1020 return (&module); 1021 } 1022