1/* Classification of ELF files. 2 Copyright (C) 2019 Red Hat, Inc. 3 This file is part of elfutils. 4 5 This file is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 3 of the License, or 8 (at your option) any later version. 9 10 elfutils is distributed in the hope that it will be useful, but 11 WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 GNU General Public License for more details. 14 15 You should have received a copy of the GNU General Public License 16 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 17 18#include <config.h> 19#include <system.h> 20 21#include <argp.h> 22#include <fcntl.h> 23#include <gelf.h> 24#include <stdbool.h> 25#include <stddef.h> 26#include <stdio.h> 27#include <stdlib.h> 28#include <string.h> 29#include <sys/stat.h> 30#include <unistd.h> 31 32#include ELFUTILS_HEADER(elf) 33#include ELFUTILS_HEADER(dwelf) 34#include "printversion.h" 35 36/* Name and version of program. */ 37ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; 38 39/* Bug report address. */ 40ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; 41 42/* Set by parse_opt. */ 43static int verbose; 44 45/* Set by the main function. */ 46static const char *current_path; 47 48/* Set by open_file. */ 49static int file_fd = -1; 50 51/* Set by issue or elf_issue. */ 52static bool issue_found; 53 54/* Non-fatal issue occurred while processing the current_path. */ 55static void 56issue (int e, const char *msg) 57{ 58 if (verbose >= 0) 59 { 60 if (current_path == NULL) 61 error (0, e, "%s", msg); 62 else 63 error (0, e, "%s '%s'", msg, current_path); 64 } 65 issue_found = true; 66} 67 68/* Non-fatal issue occurred while processing the current ELF. */ 69static void 70elf_issue (const char *msg) 71{ 72 if (verbose >= 0) 73 error (0, 0, "%s: %s: '%s'", msg, elf_errmsg (-1), current_path); 74 issue_found = true; 75} 76 77/* Set by parse_opt. */ 78static bool flag_only_regular_files; 79 80static bool 81open_file (void) 82{ 83 if (verbose > 1) 84 fprintf (stderr, "debug: processing file: %s\n", current_path); 85 86 file_fd = open (current_path, O_RDONLY | (flag_only_regular_files 87 ? O_NOFOLLOW : 0)); 88 if (file_fd < 0) 89 { 90 if (!flag_only_regular_files || errno != ELOOP) 91 issue (errno, N_("opening")); 92 return false; 93 } 94 95 struct stat st; 96 if (fstat (file_fd, &st) != 0) 97 { 98 issue (errno, N_("reading")); 99 return false; 100 } 101 102 /* Don't even bother with directories. */ 103 if (S_ISDIR (st.st_mode) 104 || (flag_only_regular_files && !S_ISREG (st.st_mode))) 105 return false; 106 107 return true; 108} 109 110static void 111close_file (void) 112{ 113 if (file_fd >= 0) 114 { 115 close (file_fd); 116 file_fd = -1; 117 } 118} 119 120/* Set by open_elf. */ 121static Elf *elf; 122 123/* Set by parse_opt. */ 124static bool flag_compressed; 125 126static bool 127open_elf (void) 128{ 129 if (!open_file ()) 130 { 131 /* Make sure the file descriptor is gone. */ 132 close_file (); 133 return false; 134 } 135 136 if (flag_compressed) 137 elf = dwelf_elf_begin (file_fd); 138 else 139 elf = elf_begin (file_fd, ELF_C_READ, NULL); 140 141 if (elf == NULL) 142 { 143 elf_issue ("opening ELF file"); 144 close_file (); 145 return false; 146 } 147 148 return true; 149} 150 151static void 152close_elf (void) 153{ 154 if (elf != NULL) 155 { 156 elf_end (elf); 157 elf = NULL; 158 } 159 160 close_file (); 161} 162 163static const char * 164elf_kind_string (int kind) 165{ 166 switch (kind) 167 { 168 case ELF_K_NONE: 169 return "ELF_K_NONE"; 170 case ELF_K_AR: 171 return "ELF_K_AR"; 172 case ELF_K_COFF: 173 return "ELF_K_COFF"; /* libelf doesn't really support this. */ 174 case ELF_K_ELF: 175 return "ELF_K_ELF"; 176 default: 177 return "<unknown>"; 178 } 179} 180 181static const char * 182elf_type_string (int type) 183{ 184 switch (type) 185 { 186 case ET_NONE: 187 return "ET_NONE"; 188 case ET_REL: 189 return "ET_REL"; 190 case ET_EXEC: 191 return "ET_EXEC"; 192 case ET_DYN: 193 return "ET_DYN"; 194 case ET_CORE: 195 return "ET_CORE"; 196 default: 197 return "<unknown>"; 198 } 199} 200 201static int elf_type; 202static bool has_program_load; 203static bool has_sections; 204static bool has_bits_alloc; 205static bool has_program_interpreter; 206static bool has_dynamic; 207static bool has_soname; 208static bool has_pie_flag; 209static bool has_dt_debug; 210static bool has_symtab; 211static bool has_debug_sections; 212static bool has_modinfo; 213static bool has_gnu_linkonce_this_module; 214 215static bool 216run_classify (void) 217{ 218 /* Reset to unanalyzed default. */ 219 elf_type = 0; 220 has_program_load = false; 221 has_sections = false; 222 has_bits_alloc = false; 223 has_program_interpreter = false; 224 has_dynamic = false; 225 has_soname = false; 226 has_pie_flag = false; 227 has_dt_debug = false; 228 has_symtab = false; 229 has_debug_sections = false; 230 has_modinfo = false; 231 has_gnu_linkonce_this_module = false; 232 233 int kind = elf_kind (elf); 234 if (verbose > 0) 235 fprintf (stderr, "info: %s: ELF kind: %s (0x%x)\n", current_path, 236 elf_kind_string (kind), kind); 237 if (kind != ELF_K_ELF) 238 return true; 239 240 GElf_Ehdr ehdr_storage; 241 GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_storage); 242 if (ehdr == NULL) 243 { 244 elf_issue (N_("ELF header")); 245 return false; 246 } 247 elf_type = ehdr->e_type; 248 249 /* Examine program headers. */ 250 GElf_Phdr dyn_seg = { .p_type = 0 }; 251 { 252 size_t nphdrs; 253 if (elf_getphdrnum (elf, &nphdrs) != 0) 254 { 255 elf_issue (N_("program headers")); 256 return false; 257 } 258 for (size_t phdr_idx = 0; phdr_idx < nphdrs; ++phdr_idx) 259 { 260 GElf_Phdr phdr_storage; 261 GElf_Phdr *phdr = gelf_getphdr (elf, phdr_idx, &phdr_storage); 262 if (phdr == NULL) 263 { 264 elf_issue (N_("program header")); 265 return false; 266 } 267 if (phdr->p_type == PT_DYNAMIC) 268 { 269 dyn_seg = *phdr; 270 has_dynamic = true; 271 } 272 if (phdr->p_type == PT_INTERP) 273 has_program_interpreter = true; 274 if (phdr->p_type == PT_LOAD) 275 has_program_load = true; 276 } 277 } 278 279 /* Do we have sections? */ 280 { 281 size_t nshdrs; 282 if (elf_getshdrnum (elf, &nshdrs) != 0) 283 { 284 elf_issue (N_("section headers")); 285 return false; 286 } 287 if (nshdrs > 0) 288 has_sections = true; 289 } 290 291 { 292 size_t shstrndx; 293 if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0)) 294 { 295 elf_issue (N_("section header string table index")); 296 return false; 297 } 298 299 Elf_Scn *scn = NULL; 300 while (true) 301 { 302 scn = elf_nextscn (elf, scn); 303 if (scn == NULL) 304 break; 305 GElf_Shdr shdr_storage; 306 GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_storage); 307 if (shdr == NULL) 308 { 309 elf_issue (N_("could not obtain section header")); 310 return false; 311 } 312 const char *section_name = elf_strptr (elf, shstrndx, shdr->sh_name); 313 if (section_name == NULL) 314 { 315 elf_issue(N_("could not obtain section name")); 316 return false; 317 } 318 if (verbose > 2) 319 fprintf (stderr, "debug: section header %s (type %d) found\n", 320 section_name, shdr->sh_type); 321 if (shdr->sh_type == SHT_SYMTAB) 322 { 323 if (verbose > 1) 324 fputs ("debug: symtab section found\n", stderr); 325 has_symtab = true; 326 } 327 /* NOBITS and NOTE sections can be in any file. We want to be 328 sure there is at least one other allocated section. */ 329 if (shdr->sh_type != SHT_NOBITS 330 && shdr->sh_type != SHT_NOTE 331 && (shdr->sh_flags & SHF_ALLOC) != 0) 332 { 333 if (verbose > 1 && !has_bits_alloc) 334 fputs ("debug: allocated (non-nobits/note) section found\n", 335 stderr); 336 has_bits_alloc = true; 337 } 338 if (startswith (section_name, ".debug_") 339 || startswith (section_name, ".zdebug_")) 340 { 341 if (verbose > 1 && !has_debug_sections) 342 fputs ("debug: .debug_* section found\n", stderr); 343 has_debug_sections = true; 344 } 345 if (strcmp (section_name, ".modinfo") == 0) 346 { 347 if (verbose > 1) 348 fputs ("debug: .modinfo section found\n", stderr); 349 has_modinfo = true; 350 } 351 if (strcmp (section_name, ".gnu.linkonce.this_module") == 0) 352 { 353 if (verbose > 1) 354 fputs ("debug: .gnu.linkonce.this_module section found\n", 355 stderr); 356 has_gnu_linkonce_this_module = true; 357 } 358 } 359 } 360 361 /* Examine the dynamic section. */ 362 if (has_dynamic) 363 { 364 Elf_Data *data = elf_getdata_rawchunk (elf, dyn_seg.p_offset, 365 dyn_seg.p_filesz, 366 ELF_T_DYN); 367 if (data != NULL) 368 for (int dyn_idx = 0; ; ++dyn_idx) 369 { 370 GElf_Dyn dyn_storage; 371 GElf_Dyn *dyn = gelf_getdyn (data, dyn_idx, &dyn_storage); 372 if (dyn == NULL) 373 break; 374 if (verbose > 2) 375 fprintf (stderr, "debug: dynamic entry %d" 376 " with tag %llu found\n", 377 dyn_idx, (unsigned long long int) dyn->d_tag); 378 if (dyn->d_tag == DT_SONAME) 379 has_soname = true; 380 if (dyn->d_tag == DT_FLAGS_1 && (dyn->d_un.d_val & DF_1_PIE)) 381 has_pie_flag = true; 382 if (dyn->d_tag == DT_DEBUG) 383 has_dt_debug = true; 384 if (dyn->d_tag == DT_NULL) 385 break; 386 } 387 } 388 389 if (verbose > 0) 390 { 391 fprintf (stderr, "info: %s: ELF type: %s (0x%x)\n", current_path, 392 elf_type_string (elf_type), elf_type); 393 if (has_program_load) 394 fprintf (stderr, "info: %s: PT_LOAD found\n", current_path); 395 if (has_sections) 396 fprintf (stderr, "info: %s: has sections\n", current_path); 397 if (has_bits_alloc) 398 fprintf (stderr, "info: %s: allocated (real) section found\n", 399 current_path); 400 if (has_program_interpreter) 401 fprintf (stderr, "info: %s: program interpreter found\n", 402 current_path); 403 if (has_dynamic) 404 fprintf (stderr, "info: %s: dynamic segment found\n", current_path); 405 if (has_soname) 406 fprintf (stderr, "info: %s: soname found\n", current_path); 407 if (has_pie_flag) 408 fprintf (stderr, "info: %s: DF_1_PIE flag found\n", current_path); 409 if (has_dt_debug) 410 fprintf (stderr, "info: %s: DT_DEBUG found\n", current_path); 411 if (has_symtab) 412 fprintf (stderr, "info: %s: symbol table found\n", current_path); 413 if (has_debug_sections) 414 fprintf (stderr, "info: %s: .debug_* section found\n", current_path); 415 if (has_modinfo) 416 fprintf (stderr, "info: %s: .modinfo section found\n", current_path); 417 if (has_gnu_linkonce_this_module) 418 fprintf (stderr, 419 "info: %s: .gnu.linkonce.this_module section found\n", 420 current_path); 421 } 422 423 return true; 424} 425 426static bool 427is_elf (void) 428{ 429 return elf_kind (elf) != ELF_K_NONE; 430} 431 432static bool 433is_elf_file (void) 434{ 435 return elf_kind (elf) == ELF_K_ELF; 436} 437 438static bool 439is_elf_archive (void) 440{ 441 return elf_kind (elf) == ELF_K_AR; 442} 443 444static bool 445is_core (void) 446{ 447 return elf_kind (elf) == ELF_K_ELF && elf_type == ET_CORE; 448} 449 450/* Return true if the file is a loadable object, which basically means 451 it is an ELF file, but not a relocatable object or a core dump 452 file. (The kernel and various userspace components can load ET_REL 453 files, but we disregard that for our classification purposes.) */ 454static bool 455is_loadable (void) 456{ 457 return elf_kind (elf) == ELF_K_ELF 458 && (elf_type == ET_EXEC || elf_type == ET_DYN) 459 && has_program_load 460 && (!has_sections || has_bits_alloc); /* It isn't debug-only. */ 461} 462 463/* Return true if the file is an ELF file which has a symbol table or 464 .debug_* sections (and thus can be stripped further). */ 465static bool 466is_unstripped (void) 467{ 468 return elf_kind (elf) != ELF_K_NONE 469 && (elf_type == ET_REL || elf_type == ET_EXEC || elf_type == ET_DYN) 470 && (has_symtab || has_debug_sections); 471} 472 473/* Return true if the file contains only debuginfo, but no loadable 474 program bits. Then it is most likely a separate .debug file, a dwz 475 multi-file or a .dwo file. Note that it can still be loadable, 476 but in that case the phdrs shouldn't be trusted. */ 477static bool 478is_debug_only (void) 479{ 480 return elf_kind (elf) != ELF_K_NONE 481 && (elf_type == ET_REL || elf_type == ET_EXEC || elf_type == ET_DYN) 482 && (has_debug_sections || has_symtab) 483 && !has_bits_alloc; 484} 485 486static bool 487is_shared (void) 488{ 489 if (!is_loadable ()) 490 return false; 491 492 /* The ELF type is very clear: this is an executable. */ 493 if (elf_type == ET_EXEC) 494 return false; 495 496 /* If there is no dynamic section, the file cannot be loaded as a 497 shared object. */ 498 if (!has_dynamic) 499 return false; 500 501 /* If the object is marked as PIE, it is definitely an executable, 502 and not a loadlable shared object. */ 503 if (has_pie_flag) 504 return false; 505 506 /* Treat a DT_SONAME tag as a strong indicator that this is a shared 507 object. */ 508 if (has_soname) 509 return true; 510 511 /* This is probably a PIE program: there is no soname, but a program 512 interpreter. In theory, this file could be also a DSO with a 513 soname implied by its file name that can be run as a program. 514 This situation is impossible to resolve in the general case. */ 515 if (has_program_interpreter) 516 return false; 517 518 /* Roland McGrath mentions in 519 <https://www.sourceware.org/ml/libc-alpha/2015-03/msg00605.html>, 520 that “we defined a PIE as an ET_DYN with a DT_DEBUG”. This 521 matches current binutils behavior (version 2.32). DT_DEBUG is 522 added if bfd_link_executable returns true or if bfd_link_pic 523 returns false, depending on the architectures. However, DT_DEBUG 524 is not documented as being specific to executables, therefore use 525 it only as a low-priority discriminator. */ 526 if (has_dt_debug) 527 return false; 528 529 return true; 530} 531 532static bool 533is_executable (void) 534{ 535 if (!is_loadable ()) 536 return false; 537 538 /* A loadable object which is not a shared object is treated as an 539 executable. */ 540 return !is_shared (); 541} 542 543/* Like is_executable, but the object can also be a shared library at 544 the same time. */ 545static bool 546is_program (void) 547{ 548 if (!is_loadable ()) 549 return false; 550 551 /* The ELF type is very clear: this is an executable. */ 552 if (elf_type == ET_EXEC) 553 return true; 554 555 /* If the object is marked as PIE, it is definitely an executable, 556 and not a loadlable shared object. */ 557 if (has_pie_flag) 558 return true; 559 560 /* This is probably a PIE program. It isn't ET_EXEC, but has a 561 program interpreter. In theory, this file could be also a DSO 562 with a soname. This situation is impossible to resolve in the 563 general case. See is_shared. This is different from 564 is_executable. */ 565 if (has_program_interpreter) 566 return true; 567 568 /* Roland McGrath mentions in 569 <https://www.sourceware.org/ml/libc-alpha/2015-03/msg00605.html>, 570 that “we defined a PIE as an ET_DYN with a DT_DEBUG”. This 571 matches current binutils behavior (version 2.32). DT_DEBUG is 572 added if bfd_link_executable returns true or if bfd_link_pic 573 returns false, depending on the architectures. However, DT_DEBUG 574 is not documented as being specific to executables, therefore use 575 it only as a low-priority discriminator. */ 576 if (has_dt_debug) 577 return true; 578 579 return false; 580} 581 582/* Like is_shared but the library could also be an executable. */ 583static bool 584is_library (void) 585{ 586 /* Only ET_DYN can be shared libraries. */ 587 if (elf_type != ET_DYN) 588 return false; 589 590 if (!is_loadable ()) 591 return false; 592 593 /* Without a PT_DYNAMIC segment the library cannot be loaded. */ 594 if (!has_dynamic) 595 return false; 596 597 /* This really is a (PIE) executable. See is_shared. */ 598 if (has_pie_flag || has_dt_debug) 599 return false; 600 601 /* It could still (also) be a (PIE) executable, but most likely you 602 can dlopen it just fine. */ 603 return true; 604} 605 606/* Returns true if the file is a linux kernel module (is ET_REL and 607 has the two magic sections .modinfo and .gnu.linkonce.this_module). */ 608static bool 609is_linux_kernel_module (void) 610{ 611 return (elf_kind (elf) == ELF_K_ELF 612 && elf_type == ET_REL 613 && has_modinfo 614 && has_gnu_linkonce_this_module); 615} 616 617enum classify_requirement { do_not_care, required, forbidden }; 618 619enum classify_check 620{ 621 classify_elf, 622 classify_elf_file, 623 classify_elf_archive, 624 classify_core, 625 classify_unstripped, 626 classify_executable, 627 classify_program, 628 classify_shared, 629 classify_library, 630 classify_linux_kernel_module, 631 classify_debug_only, 632 classify_loadable, 633 634 classify_check_last = classify_loadable 635}; 636 637enum 638{ 639 classify_check_offset = 1000, 640 classify_check_not_offset = 2000, 641 642 classify_flag_stdin = 3000, 643 classify_flag_stdin0, 644 classify_flag_no_stdin, 645 classify_flag_print, 646 classify_flag_print0, 647 classify_flag_no_print, 648 classify_flag_matching, 649 classify_flag_not_matching, 650}; 651 652static bool 653classify_check_positive (int key) 654{ 655 return key >= classify_check_offset 656 && key <= classify_check_offset + classify_check_last; 657} 658 659static bool 660classify_check_negative (int key) 661{ 662 return key >= classify_check_not_offset 663 && key <= classify_check_not_offset + classify_check_last; 664} 665 666/* Set by parse_opt. */ 667static enum classify_requirement requirements[classify_check_last + 1]; 668static enum { no_stdin, do_stdin, do_stdin0 } flag_stdin; 669static enum { no_print, do_print, do_print0 } flag_print; 670static bool flag_print_matching = true; 671 672static error_t 673parse_opt (int key, char *arg __attribute__ ((unused)), 674 struct argp_state *state __attribute__ ((unused))) 675{ 676 if (classify_check_positive (key)) 677 requirements[key - classify_check_offset] = required; 678 else if (classify_check_negative (key)) 679 requirements[key - classify_check_not_offset] = forbidden; 680 else 681 switch (key) 682 { 683 case 'v': 684 ++verbose; 685 break; 686 687 case 'q': 688 --verbose; 689 break; 690 691 case 'z': 692 flag_compressed = true; 693 break; 694 695 case 'f': 696 flag_only_regular_files = true; 697 break; 698 699 case classify_flag_stdin: 700 flag_stdin = do_stdin; 701 break; 702 703 case classify_flag_stdin0: 704 flag_stdin = do_stdin0; 705 break; 706 707 case classify_flag_no_stdin: 708 flag_stdin = no_stdin; 709 break; 710 711 case classify_flag_print: 712 flag_print = do_print; 713 break; 714 715 case classify_flag_print0: 716 flag_print = do_print0; 717 break; 718 719 case classify_flag_no_print: 720 flag_print = no_print; 721 break; 722 723 case classify_flag_matching: 724 flag_print_matching = true; 725 break; 726 727 case classify_flag_not_matching: 728 flag_print_matching = false; 729 break; 730 731 default: 732 return ARGP_ERR_UNKNOWN; 733 } 734 735 return 0; 736} 737 738/* Perform requested checks against the file at current_path. If 739 necessary, sets *STATUS to 1 if checks failed. */ 740static void 741process_current_path (int *status) 742{ 743 bool checks_passed = true; 744 745 if (open_elf () && run_classify ()) 746 { 747 bool checks[] = 748 { 749 [classify_elf] = is_elf (), 750 [classify_elf_file] = is_elf_file (), 751 [classify_elf_archive] = is_elf_archive (), 752 [classify_core] = is_core (), 753 [classify_unstripped] = is_unstripped (), 754 [classify_executable] = is_executable (), 755 [classify_program] = is_program (), 756 [classify_shared] = is_shared (), 757 [classify_library] = is_library (), 758 [classify_linux_kernel_module] = is_linux_kernel_module (), 759 [classify_debug_only] = is_debug_only (), 760 [classify_loadable] = is_loadable (), 761 }; 762 763 if (verbose > 1) 764 { 765 if (checks[classify_elf]) 766 fprintf (stderr, "debug: %s: elf\n", current_path); 767 if (checks[classify_elf_file]) 768 fprintf (stderr, "debug: %s: elf_file\n", current_path); 769 if (checks[classify_elf_archive]) 770 fprintf (stderr, "debug: %s: elf_archive\n", current_path); 771 if (checks[classify_core]) 772 fprintf (stderr, "debug: %s: core\n", current_path); 773 if (checks[classify_unstripped]) 774 fprintf (stderr, "debug: %s: unstripped\n", current_path); 775 if (checks[classify_executable]) 776 fprintf (stderr, "debug: %s: executable\n", current_path); 777 if (checks[classify_program]) 778 fprintf (stderr, "debug: %s: program\n", current_path); 779 if (checks[classify_shared]) 780 fprintf (stderr, "debug: %s: shared\n", current_path); 781 if (checks[classify_library]) 782 fprintf (stderr, "debug: %s: library\n", current_path); 783 if (checks[classify_linux_kernel_module]) 784 fprintf (stderr, "debug: %s: linux kernel module\n", current_path); 785 if (checks[classify_debug_only]) 786 fprintf (stderr, "debug: %s: debug-only\n", current_path); 787 if (checks[classify_loadable]) 788 fprintf (stderr, "debug: %s: loadable\n", current_path); 789 } 790 791 for (enum classify_check check = 0; 792 check <= classify_check_last; ++check) 793 switch (requirements[check]) 794 { 795 case required: 796 if (!checks[check]) 797 checks_passed = false; 798 break; 799 case forbidden: 800 if (checks[check]) 801 checks_passed = false; 802 break; 803 case do_not_care: 804 break; 805 } 806 } 807 else if (file_fd == -1) 808 checks_passed = false; /* There is nothing to check, bad file. */ 809 else 810 { 811 for (enum classify_check check = 0; 812 check <= classify_check_last; ++check) 813 if (requirements[check] == required) 814 checks_passed = false; 815 } 816 817 close_elf (); 818 819 switch (flag_print) 820 { 821 case do_print: 822 if (checks_passed == flag_print_matching) 823 puts (current_path); 824 break; 825 case do_print0: 826 if (checks_passed == flag_print_matching) 827 if (fwrite (current_path, strlen (current_path) + 1, 1, stdout) < 1) 828 issue (errno, N_("writing to standard output")); 829 break; 830 case no_print: 831 if (!checks_passed) 832 *status = 1; 833 break; 834 } 835} 836 837/* Called to process standard input if flag_stdin is not no_stdin. */ 838static void 839process_stdin (int *status) 840{ 841 char delim; 842 if (flag_stdin == do_stdin0) 843 delim = '\0'; 844 else 845 delim = '\n'; 846 847 char *buffer = NULL; 848 size_t buffer_size = 0; 849 while (true) 850 { 851 ssize_t ret = getdelim (&buffer, &buffer_size, delim, stdin); 852 if (ferror (stdin)) 853 { 854 current_path = NULL; 855 issue (errno, N_("reading from standard input")); 856 break; 857 } 858 if (feof (stdin)) 859 break; 860 if (ret < 0) 861 abort (); /* Cannot happen due to error checks above. */ 862 if (delim != '\0' && ret > 0 && buffer[ret - 1] == '\n') 863 buffer[ret - 1] = '\0'; 864 current_path = buffer; 865 process_current_path (status); 866 } 867 868 free (buffer); 869} 870 871int 872main (int argc, char **argv) 873{ 874 const struct argp_option options[] = 875 { 876 { NULL, 0, NULL, OPTION_DOC, N_("Classification options"), 1 }, 877 { "elf", classify_check_offset + classify_elf, NULL, 0, 878 N_("File looks like an ELF object or archive/static library (default)") 879 , 1 }, 880 { "elf-file", classify_check_offset + classify_elf_file, NULL, 0, 881 N_("File is an regular ELF object (not an archive/static library)") 882 , 1 }, 883 { "elf-archive", classify_check_offset + classify_elf_archive, NULL, 0, 884 N_("File is an ELF archive or static library") 885 , 1 }, 886 { "core", classify_check_offset + classify_core, NULL, 0, 887 N_("File is an ELF core dump file") 888 , 1 }, 889 { "unstripped", classify_check_offset + classify_unstripped, NULL, 0, 890 N_("File is an ELF file with symbol table or .debug_* sections \ 891and can be stripped further"), 1 }, 892 { "executable", classify_check_offset + classify_executable, NULL, 0, 893 N_("File is (primarily) an ELF program executable \ 894(not primarily a DSO)"), 1 }, 895 { "program", classify_check_offset + classify_program, NULL, 0, 896 N_("File is an ELF program executable \ 897(might also be a DSO)"), 1 }, 898 { "shared", classify_check_offset + classify_shared, NULL, 0, 899 N_("File is (primarily) an ELF shared object (DSO) \ 900(not primarily an executable)"), 1 }, 901 { "library", classify_check_offset + classify_library, NULL, 0, 902 N_("File is an ELF shared object (DSO) \ 903(might also be an executable)"), 1 }, 904 { "linux-kernel-module", (classify_check_offset 905 + classify_linux_kernel_module), NULL, 0, 906 N_("File is a linux kernel module"), 1 }, 907 { "debug-only", (classify_check_offset + classify_debug_only), NULL, 0, 908 N_("File is a debug only ELF file \ 909(separate .debug, .dwo or dwz multi-file)"), 1 }, 910 { "loadable", classify_check_offset + classify_loadable, NULL, 0, 911 N_("File is a loadable ELF object (program or shared object)"), 1 }, 912 913 /* Negated versions of the above. */ 914 { "not-elf", classify_check_not_offset + classify_elf, 915 NULL, OPTION_HIDDEN, NULL, 1 }, 916 { "not-elf-file", classify_check_not_offset + classify_elf_file, 917 NULL, OPTION_HIDDEN, NULL, 1 }, 918 { "not-elf-archive", classify_check_not_offset + classify_elf_archive, 919 NULL, OPTION_HIDDEN, NULL, 1 }, 920 { "not-core", classify_check_not_offset + classify_core, 921 NULL, OPTION_HIDDEN, NULL, 1 }, 922 { "not-unstripped", classify_check_not_offset + classify_unstripped, 923 NULL, OPTION_HIDDEN, NULL, 1 }, 924 { "not-executable", classify_check_not_offset + classify_executable, 925 NULL, OPTION_HIDDEN, NULL, 1 }, 926 { "not-program", classify_check_not_offset + classify_program, 927 NULL, OPTION_HIDDEN, NULL, 1 }, 928 { "not-shared", classify_check_not_offset + classify_shared, 929 NULL, OPTION_HIDDEN, NULL, 1 }, 930 { "not-library", classify_check_not_offset + classify_library, 931 NULL, OPTION_HIDDEN, NULL, 1 }, 932 { "not-linux-kernel-module", (classify_check_not_offset 933 + classify_linux_kernel_module), 934 NULL, OPTION_HIDDEN, NULL, 1 }, 935 { "not-debug-only", (classify_check_not_offset + classify_debug_only), 936 NULL, OPTION_HIDDEN, NULL, 1 }, 937 { "not-loadable", classify_check_not_offset + classify_loadable, 938 NULL, OPTION_HIDDEN, NULL, 1 }, 939 940 { NULL, 0, NULL, OPTION_DOC, N_("Input flags"), 2 }, 941 { "file", 'f', NULL, 0, 942 N_("Only classify regular (not symlink nor special device) files"), 2 }, 943 { "stdin", classify_flag_stdin, NULL, 0, 944 N_("Also read file names to process from standard input, \ 945separated by newlines"), 2 }, 946 { "stdin0", classify_flag_stdin0, NULL, 0, 947 N_("Also read file names to process from standard input, \ 948separated by ASCII NUL bytes"), 2 }, 949 { "no-stdin", classify_flag_no_stdin, NULL, 0, 950 N_("Do not read files from standard input (default)"), 2 }, 951 { "compressed", 'z', NULL, 0, 952 N_("Try to open compressed files or embedded (kernel) ELF images"), 953 2 }, 954 955 { NULL, 0, NULL, OPTION_DOC, N_("Output flags"), 3 }, 956 { "print", classify_flag_print, NULL, 0, 957 N_("Output names of files, separated by newline"), 3 }, 958 { "print0", classify_flag_print0, NULL, 0, 959 N_("Output names of files, separated by ASCII NUL"), 3 }, 960 { "no-print", classify_flag_no_print, NULL, 0, 961 N_("Do not output file names"), 3 }, 962 { "matching", classify_flag_matching, NULL, 0, 963 N_("If printing file names, print matching files (default)"), 3 }, 964 { "not-matching", classify_flag_not_matching, NULL, 0, 965 N_("If printing file names, print files that do not match"), 3 }, 966 967 { NULL, 0, NULL, OPTION_DOC, N_("Additional flags"), 4 }, 968 { "verbose", 'v', NULL, 0, 969 N_("Output additional information (can be specified multiple times)"), 4 }, 970 { "quiet", 'q', NULL, 0, 971 N_("Suppress some error output (counterpart to --verbose)"), 4 }, 972 { NULL, 0, NULL, 0, NULL, 0 } 973 }; 974 975 const struct argp argp = 976 { 977 .options = options, 978 .parser = parse_opt, 979 .args_doc = N_("FILE..."), 980 .doc = N_("\ 981Determine the type of an ELF file.\ 982\n\n\ 983All of the classification options must apply at the same time to a \ 984particular file. Classification options can be negated using a \ 985\"--not-\" prefix.\ 986\n\n\ 987Since modern ELF does not clearly distinguish between programs and \ 988dynamic shared objects, you should normally use either --executable or \ 989--shared to identify the primary purpose of a file. \ 990Only one of the --shared and --executable checks can pass for a file.\ 991\n\n\ 992If you want to know whether an ELF object might a program or a \ 993shared library (but could be both), then use --program or --library. \ 994Some ELF files will classify as both a program and a library.\ 995\n\n\ 996If you just want to know whether an ELF file is loadable (as program \ 997or library) use --loadable. Note that files that only contain \ 998(separate) debug information (--debug-only) are never --loadable (even \ 999though they might contain program headers). Linux kernel modules are \ 1000also not --loadable (in the normal sense).\ 1001\n\n\ 1002Without any of the --print options, the program exits with status 0 \ 1003if the requested checks pass for all input files, with 1 if a check \ 1004fails for any file, and 2 if there is an environmental issue (such \ 1005as a file read error or a memory allocation error).\ 1006\n\n\ 1007When printing file names, the program exits with status 0 even if \ 1008no file names are printed, and exits with status 2 if there is an \ 1009environmental issue.\ 1010\n\n\ 1011On usage error (e.g. a bad option was given), the program exits with \ 1012a status code larger than 2.\ 1013\n\n\ 1014The --quiet or -q option suppresses some error warning output, but \ 1015doesn't change the exit status.\ 1016") 1017 }; 1018 1019 /* Require that the file is an ELF file by default. User can 1020 disable with --not-elf. */ 1021 requirements[classify_elf] = required; 1022 1023 int remaining; 1024 if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0) 1025 return 2; 1026 1027 elf_version (EV_CURRENT); 1028 1029 int status = 0; 1030 1031 for (int i = remaining; i < argc; ++i) 1032 { 1033 current_path = argv[i]; 1034 process_current_path (&status); 1035 } 1036 1037 if (flag_stdin != no_stdin) 1038 process_stdin (&status); 1039 1040 if (issue_found) 1041 return 2; 1042 1043 return status; 1044} 1045