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 2009 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include <ctype.h> 28 #include <elfedit.h> 29 #include <sys/elf_SPARC.h> 30 #include <strings.h> 31 #include <debug.h> 32 #include <conv.h> 33 #include <cap_msg.h> 34 35 36 /* 37 * Capabilities section 38 */ 39 40 41 42 43 /* 44 * This module uses shared code for several of the commands. 45 * It is sometimes necessary to know which specific command 46 * is active. 47 */ 48 typedef enum { 49 /* Dump command, used as module default to display dynamic section */ 50 CAP_CMD_T_DUMP = 0, /* cap:dump */ 51 52 /* Commands that do not correspond directly to a specific DT tag */ 53 CAP_CMD_T_TAG = 1, /* cap:tag */ 54 CAP_CMD_T_VALUE = 2, /* cap:value */ 55 CAP_CMD_T_DELETE = 3, /* cap:delete */ 56 CAP_CMD_T_MOVE = 4, /* cap:shift */ 57 58 /* Commands that embody tag specific knowledge */ 59 CAP_CMD_T_HW1 = 5, /* cap:hw1 */ 60 CAP_CMD_T_SF1 = 6, /* cap:sf1 */ 61 } CAP_CMD_T; 62 63 64 65 #ifndef _ELF64 66 /* 67 * We supply this function for the msg module 68 */ 69 const char * 70 _cap_msg(Msg mid) 71 { 72 return (gettext(MSG_ORIG(mid))); 73 } 74 #endif 75 76 77 /* 78 * This function is supplied to elfedit through our elfedit_module_t 79 * definition. It translates the opaque elfedit_i18nhdl_t handles 80 * in our module interface into the actual strings for elfedit to 81 * use. 82 * 83 * note: 84 * This module uses Msg codes for its i18n handle type. 85 * So the translation is simply to use MSG_INTL() to turn 86 * it into a string and return it. 87 */ 88 static const char * 89 mod_i18nhdl_to_str(elfedit_i18nhdl_t hdl) 90 { 91 Msg msg = (Msg)hdl; 92 93 return (MSG_INTL(msg)); 94 } 95 96 97 98 /* 99 * The cap_opt_t enum specifies a bit value for every optional 100 * argument allowed by a command in this module. 101 */ 102 typedef enum { 103 CAP_OPT_F_AND = 1, /* -and: AND (&) values to dest */ 104 CAP_OPT_F_CMP = 2, /* -cmp: Complement (~) values */ 105 CAP_OPT_F_CAPNDX = 4, /* -capndx: elt is tag index, */ 106 /* not name */ 107 CAP_OPT_F_OR = 8, /* -or: OR (|) values to dest */ 108 } cap_opt_t; 109 110 111 /* 112 * A variable of type ARGSTATE is used by each command to maintain 113 * information about the arguments and related things. It is 114 * initialized by process_args(), and used by the other routines. 115 */ 116 typedef struct { 117 elfedit_obj_state_t *obj_state; 118 struct { 119 elfedit_section_t *sec; /* Capabilities section reference */ 120 Cap *data; /* Start of capabilities section data */ 121 Word num; /* # Capabilities elts */ 122 } cap; 123 cap_opt_t optmask; /* Mask of options used */ 124 int argc; /* # of plain arguments */ 125 const char **argv; /* Plain arguments */ 126 } ARGSTATE; 127 128 129 130 /* 131 * Standard argument processing for cap module 132 * 133 * entry 134 * obj_state, argc, argv - Standard command arguments 135 * argstate - Address of ARGSTATE block to be initialized 136 * 137 * exit: 138 * On success, *argstate is initialized. On error, 139 * an error is issued and this routine does not return. 140 */ 141 static void 142 process_args(elfedit_obj_state_t *obj_state, int argc, const char *argv[], 143 ARGSTATE *argstate) 144 { 145 elfedit_getopt_state_t getopt_state; 146 elfedit_getopt_ret_t *getopt_ret; 147 148 bzero(argstate, sizeof (*argstate)); 149 argstate->obj_state = obj_state; 150 151 elfedit_getopt_init(&getopt_state, &argc, &argv); 152 153 /* Add each new option to the options mask */ 154 while ((getopt_ret = elfedit_getopt(&getopt_state)) != NULL) 155 argstate->optmask |= getopt_ret->gor_idmask; 156 157 /* If there may be an arbitrary amount of output, use a pager */ 158 if (argc == 0) 159 elfedit_pager_init(); 160 161 /* Return the updated values of argc/argv */ 162 argstate->argc = argc; 163 argstate->argv = argv; 164 165 /* Locate the capabilities section */ 166 argstate->cap.sec = elfedit_sec_getcap(obj_state, &argstate->cap.data, 167 &argstate->cap.num); 168 } 169 170 171 172 /* 173 * Print ELF capabilities values, taking the calling command, and output style 174 * into account. 175 * 176 * entry: 177 * cmd - CAP_CMD_T_* value giving identify of caller 178 * autoprint - If True, output is only produced if the elfedit 179 * autoprint flag is set. If False, output is always produced. 180 * argstate - Argument state block 181 * print_type - Specifies which capabilities elements to display. 182 * ndx = If print_type is PRINT_CAP_T_NDX, displays the index specified. 183 * Otherwise ignored. 184 */ 185 typedef enum { 186 PRINT_CAP_T_ALL = 0, /* Show all indexes */ 187 PRINT_CAP_T_NDX = 1, /* Show capabilities[arg] only */ 188 PRINT_CAP_T_TAG = 2 /* Show all elts with tag type */ 189 /* given by arg */ 190 } PRINT_CAP_T; 191 192 static void 193 print_cap(CAP_CMD_T cmd, int autoprint, ARGSTATE *argstate, 194 PRINT_CAP_T print_type, Word arg) 195 { 196 elfedit_outstyle_t outstyle; 197 Word cnt, ndx, printed = 0; 198 Cap *cap; 199 int header_done = 0; 200 Xword last_c_val = 0; 201 202 if (autoprint && ((elfedit_flags() & ELFEDIT_F_AUTOPRINT) == 0)) 203 return; 204 205 /* 206 * Pick an output style. cap:dump is required to use the default 207 * style. The other commands use the current output style. 208 */ 209 outstyle = (cmd == CAP_CMD_T_DUMP) ? 210 ELFEDIT_OUTSTYLE_DEFAULT : elfedit_outstyle(); 211 212 /* How many elements do we examine? */ 213 if (print_type == PRINT_CAP_T_NDX) { 214 if (arg >= argstate->cap.num) 215 return; /* Out of range */ 216 ndx = arg; 217 cnt = 1; 218 } else { 219 ndx = 0; 220 cnt = argstate->cap.num; 221 } 222 223 cap = &argstate->cap.data[ndx]; 224 for (; cnt--; cap++, ndx++) { 225 /* 226 * If we are only displaying certain tag types and 227 * this isn't one of those, move on to next element. 228 */ 229 if ((print_type == PRINT_CAP_T_TAG) && (cap->c_tag != arg)) 230 continue; 231 232 if (outstyle == ELFEDIT_OUTSTYLE_DEFAULT) { 233 if (header_done == 0) { 234 header_done = 1; 235 Elf_cap_title(0); 236 } 237 Elf_cap_entry(NULL, cap, ndx, 238 argstate->obj_state->os_ehdr->e_machine); 239 } else { 240 /* 241 * In simple or numeric mode under a print type 242 * that is based on tag type rather than on index, 243 * quietly: If we've already printed this value, 244 * don't print it again. A common example of this 245 * is PRINT_CAP_T_RUNPATH when both CA_RPATH and 246 * CA_RUNPATH are present with the same value. 247 */ 248 if ((print_type == PRINT_CAP_T_TAG) && printed && 249 (last_c_val == cap->c_un.c_val)) 250 continue; 251 252 if (outstyle == ELFEDIT_OUTSTYLE_SIMPLE) { 253 union { 254 Conv_cap_val_hw1_buf_t hw1; 255 Conv_cap_val_sf1_buf_t sf1; 256 } c_buf; 257 258 switch (cap->c_tag) { 259 case CA_SUNW_HW_1: 260 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 261 conv_cap_val_hw1(cap->c_un.c_val, 262 argstate->obj_state->os_ehdr-> 263 e_machine, 264 CONV_FMT_NOBKT, &c_buf.hw1)); 265 printed = 1; 266 continue; 267 case CA_SUNW_SF_1: 268 elfedit_printf(MSG_ORIG(MSG_FMT_STRNL), 269 conv_cap_val_sf1(cap->c_un.c_val, 270 argstate->obj_state->os_ehdr-> 271 e_machine, 272 CONV_FMT_NOBKT, &c_buf.sf1)); 273 printed = 1; 274 continue; 275 } 276 } 277 elfedit_printf(MSG_ORIG(MSG_FMT_HEXXWORDNL), 278 cap->c_un.c_val); 279 } 280 printed = 1; 281 last_c_val = cap->c_un.c_val; 282 } 283 284 /* 285 * If nothing was output under the print types that are 286 * based on tag type, issue an error saying it doesn't exist. 287 */ 288 if (!printed && (print_type == PRINT_CAP_T_TAG)) { 289 Conv_inv_buf_t inv_buf; 290 291 elfedit_msg(ELFEDIT_MSG_ERR, MSG_INTL(MSG_ERR_NOCAELT), 292 EC_WORD(argstate->cap.sec->sec_shndx), 293 argstate->cap.sec->sec_name, 294 conv_cap_tag(arg, 0, &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, 0, &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, 0, &inv_buf1), 532 conv_cap_tag(c_tag, 0, &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_const_to_atoui(ELFEDIT_CONST_AV)); 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 /* This routine allows multiple flags to be specified */ 736 737 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_AV); 738 } 739 740 /*ARGSUSED*/ 741 static void 742 cpl_sf1(elfedit_obj_state_t *obj_state, void *cpldata, int argc, 743 const char *argv[], int num_opt) 744 { 745 /* This routine allows multiple flags to be specified */ 746 elfedit_cpl_atoconst(cpldata, ELFEDIT_CONST_SF1_SUNW); 747 } 748 749 750 /* 751 * Implementation functions for the commands 752 */ 753 static elfedit_cmdret_t 754 cmd_dump(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 755 { 756 return (cmd_body(CAP_CMD_T_DUMP, obj_state, argc, argv)); 757 } 758 759 static elfedit_cmdret_t 760 cmd_tag(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 761 { 762 return (cmd_body(CAP_CMD_T_TAG, obj_state, argc, argv)); 763 } 764 765 static elfedit_cmdret_t 766 cmd_value(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 767 { 768 return (cmd_body(CAP_CMD_T_VALUE, obj_state, argc, argv)); 769 } 770 771 static elfedit_cmdret_t 772 cmd_delete(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 773 { 774 return (cmd_body(CAP_CMD_T_DELETE, obj_state, argc, argv)); 775 } 776 777 static elfedit_cmdret_t 778 cmd_move(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 779 { 780 return (cmd_body(CAP_CMD_T_MOVE, obj_state, argc, argv)); 781 } 782 783 static elfedit_cmdret_t 784 cmd_hw1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 785 { 786 return (cmd_body(CAP_CMD_T_HW1, obj_state, argc, argv)); 787 } 788 789 static elfedit_cmdret_t 790 cmd_sf1(elfedit_obj_state_t *obj_state, int argc, const char *argv[]) 791 { 792 return (cmd_body(CAP_CMD_T_SF1, obj_state, argc, argv)); 793 } 794 795 796 797 /*ARGSUSED*/ 798 elfedit_module_t * 799 elfedit_init(elfedit_module_version_t version) 800 { 801 /* For commands that only accept -and, -cmp, -o, and -or */ 802 static elfedit_cmd_optarg_t opt_ostyle_bitop[] = { 803 { ELFEDIT_STDOA_OPT_AND, NULL, 804 ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_AND, CAP_OPT_F_OR }, 805 { ELFEDIT_STDOA_OPT_CMP, NULL, 806 ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_CMP, 0 }, 807 { ELFEDIT_STDOA_OPT_O, NULL, 808 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 809 { ELFEDIT_STDOA_OPT_OR, NULL, 810 ELFEDIT_CMDOA_F_INHERIT, CAP_OPT_F_OR, CAP_OPT_F_AND }, 811 { NULL } 812 }; 813 814 /* For commands that only accept -capndx */ 815 static elfedit_cmd_optarg_t opt_capndx[] = { 816 { MSG_ORIG(MSG_STR_MINUS_CAPNDX), 817 /* MSG_INTL(MSG_OPTDESC_CAPNDX) */ 818 ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0, 819 CAP_OPT_F_CAPNDX, 0 }, 820 { NULL } 821 }; 822 823 /* For commands thataccept -capndx and output styles */ 824 static elfedit_cmd_optarg_t opt_ostyle_capndx[] = { 825 { MSG_ORIG(MSG_STR_MINUS_CAPNDX), 826 /* MSG_INTL(MSG_OPTDESC_CAPNDX) */ 827 ELFEDIT_I18NHDL(MSG_OPTDESC_CAPNDX), 0, 828 CAP_OPT_F_CAPNDX, 0 }, 829 { ELFEDIT_STDOA_OPT_O, NULL, 830 ELFEDIT_CMDOA_F_INHERIT, 0, 0 }, 831 { NULL } 832 }; 833 834 835 /* cap:dump */ 836 static const char *name_dump[] = { 837 MSG_ORIG(MSG_CMD_DUMP), 838 MSG_ORIG(MSG_STR_EMPTY), /* "" makes this the default command */ 839 NULL 840 }; 841 static elfedit_cmd_optarg_t arg_dump[] = { 842 { MSG_ORIG(MSG_STR_ELT), 843 /* MSG_INTL(MSG_ARGDESC_ELT) */ 844 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 845 ELFEDIT_CMDOA_F_OPT }, 846 { NULL } 847 }; 848 849 850 /* cap:tag */ 851 static const char *name_tag[] = { MSG_ORIG(MSG_CMD_TAG), NULL }; 852 static elfedit_cmd_optarg_t arg_tag[] = { 853 { MSG_ORIG(MSG_STR_ELT), 854 /* MSG_INTL(MSG_A1_TAG_ELT) */ 855 ELFEDIT_I18NHDL(MSG_A1_TAG_ELT), 856 ELFEDIT_CMDOA_F_OPT }, 857 { MSG_ORIG(MSG_STR_VALUE), 858 /* MSG_INTL(MSG_A2_TAG_VALUE) */ 859 ELFEDIT_I18NHDL(MSG_A2_TAG_VALUE), 860 ELFEDIT_CMDOA_F_OPT }, 861 { NULL } 862 }; 863 864 865 /* cap:value */ 866 static const char *name_value[] = { MSG_ORIG(MSG_CMD_VALUE), NULL }; 867 static elfedit_cmd_optarg_t arg_value[] = { 868 { MSG_ORIG(MSG_STR_ELT), 869 /* MSG_INTL(MSG_ARGDESC_ELT) */ 870 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 871 ELFEDIT_CMDOA_F_OPT }, 872 { MSG_ORIG(MSG_STR_VALUE), 873 /* MSG_INTL(MSG_A2_VALUE_VALUE) */ 874 ELFEDIT_I18NHDL(MSG_A2_VALUE_VALUE), 875 ELFEDIT_CMDOA_F_OPT }, 876 { NULL } 877 }; 878 879 /* cap:delete */ 880 static const char *name_delete[] = { MSG_ORIG(MSG_CMD_DELETE), NULL }; 881 static elfedit_cmd_optarg_t arg_delete[] = { 882 { MSG_ORIG(MSG_STR_ELT), 883 /* MSG_INTL(MSG_ARGDESC_ELT) */ 884 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 885 0 }, 886 { MSG_ORIG(MSG_STR_COUNT), 887 /* MSG_INTL(MSG_A2_DELETE_COUNT) */ 888 ELFEDIT_I18NHDL(MSG_A2_DELETE_COUNT), 889 ELFEDIT_CMDOA_F_OPT }, 890 { NULL } 891 }; 892 893 /* cap:move */ 894 static const char *name_move[] = { MSG_ORIG(MSG_CMD_MOVE), NULL }; 895 static elfedit_cmd_optarg_t arg_move[] = { 896 { MSG_ORIG(MSG_STR_ELT), 897 /* MSG_INTL(MSG_ARGDESC_ELT) */ 898 ELFEDIT_I18NHDL(MSG_ARGDESC_ELT), 899 0 }, 900 { MSG_ORIG(MSG_STR_DST_INDEX), 901 /* MSG_INTL(MSG_A2_MOVE_DST_INDEX) */ 902 ELFEDIT_I18NHDL(MSG_A2_MOVE_DST_INDEX), 903 0 }, 904 { MSG_ORIG(MSG_STR_COUNT), 905 /* MSG_INTL(MSG_A3_MOVE_COUNT) */ 906 ELFEDIT_I18NHDL(MSG_A3_MOVE_COUNT), 907 ELFEDIT_CMDOA_F_OPT }, 908 { NULL } 909 }; 910 911 /* cap:hw1 */ 912 static const char *name_hw1[] = { MSG_ORIG(MSG_CMD_HW1), NULL }; 913 static elfedit_cmd_optarg_t arg_hw1[] = { 914 { MSG_ORIG(MSG_STR_VALUE), 915 /* MSG_INTL(MSG_A1_HW1_VALUE) */ 916 ELFEDIT_I18NHDL(MSG_A1_HW1_VALUE), 917 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 918 { NULL } 919 }; 920 921 /* cap:sf1 */ 922 static const char *name_sf1[] = { MSG_ORIG(MSG_CMD_SF1), NULL }; 923 static elfedit_cmd_optarg_t arg_sf1[] = { 924 { MSG_ORIG(MSG_STR_VALUE), 925 /* MSG_INTL(MSG_A1_SF1_VALUE) */ 926 ELFEDIT_I18NHDL(MSG_A1_SF1_VALUE), 927 ELFEDIT_CMDOA_F_OPT | ELFEDIT_CMDOA_F_MULT }, 928 { NULL } 929 }; 930 931 932 933 934 static elfedit_cmd_t cmds[] = { 935 /* cap:dump */ 936 { cmd_dump, cpl_eltarg, name_dump, 937 /* MSG_INTL(MSG_DESC_DUMP) */ 938 ELFEDIT_I18NHDL(MSG_DESC_DUMP), 939 /* MSG_INTL(MSG_HELP_DUMP) */ 940 ELFEDIT_I18NHDL(MSG_HELP_DUMP), 941 opt_capndx, arg_dump }, 942 943 /* cap:tag */ 944 { cmd_tag, cpl_tag, name_tag, 945 /* MSG_INTL(MSG_DESC_TAG) */ 946 ELFEDIT_I18NHDL(MSG_DESC_TAG), 947 /* MSG_INTL(MSG_HELP_TAG) */ 948 ELFEDIT_I18NHDL(MSG_HELP_TAG), 949 opt_ostyle_capndx, arg_tag }, 950 951 /* cap:value */ 952 { cmd_value, cpl_eltarg, name_value, 953 /* MSG_INTL(MSG_DESC_VALUE) */ 954 ELFEDIT_I18NHDL(MSG_DESC_VALUE), 955 /* MSG_INTL(MSG_HELP_VALUE) */ 956 ELFEDIT_I18NHDL(MSG_HELP_VALUE), 957 opt_ostyle_capndx, arg_value }, 958 959 /* cap:delete */ 960 { cmd_delete, cpl_eltarg, name_delete, 961 /* MSG_INTL(MSG_DESC_DELETE) */ 962 ELFEDIT_I18NHDL(MSG_DESC_DELETE), 963 /* MSG_INTL(MSG_HELP_DELETE) */ 964 ELFEDIT_I18NHDL(MSG_HELP_DELETE), 965 opt_capndx, arg_delete }, 966 967 /* cap:move */ 968 { cmd_move, cpl_eltarg, name_move, 969 /* MSG_INTL(MSG_DESC_MOVE) */ 970 ELFEDIT_I18NHDL(MSG_DESC_MOVE), 971 /* MSG_INTL(MSG_HELP_MOVE) */ 972 ELFEDIT_I18NHDL(MSG_HELP_MOVE), 973 opt_capndx, arg_move }, 974 975 /* cap:hw1 */ 976 { cmd_hw1, cpl_hw1, name_hw1, 977 /* MSG_INTL(MSG_DESC_HW1) */ 978 ELFEDIT_I18NHDL(MSG_DESC_HW1), 979 /* MSG_INTL(MSG_HELP_HW1) */ 980 ELFEDIT_I18NHDL(MSG_HELP_HW1), 981 opt_ostyle_bitop, arg_hw1 }, 982 983 /* cap:sf1 */ 984 { cmd_sf1, cpl_sf1, name_sf1, 985 /* MSG_INTL(MSG_DESC_SF1) */ 986 ELFEDIT_I18NHDL(MSG_DESC_SF1), 987 /* MSG_INTL(MSG_HELP_SF1) */ 988 ELFEDIT_I18NHDL(MSG_HELP_SF1), 989 opt_ostyle_bitop, arg_sf1 }, 990 991 { NULL } 992 }; 993 994 static elfedit_module_t module = { 995 ELFEDIT_VER_CURRENT, MSG_ORIG(MSG_MOD_NAME), 996 /* MSG_INTL(MSG_MOD_DESC) */ 997 ELFEDIT_I18NHDL(MSG_MOD_DESC), 998 cmds, mod_i18nhdl_to_str }; 999 1000 return (&module); 1001 } 1002