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