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
20 #include <argp.h>
21 #include <error.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. */
37 ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
38
39 /* Bug report address. */
40 ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
41
42 /* Set by parse_opt. */
43 static int verbose;
44
45 /* Set by the main function. */
46 static const char *current_path;
47
48 /* Set by open_file. */
49 static int file_fd = -1;
50
51 /* Set by issue or elf_issue. */
52 static bool issue_found;
53
54 /* Non-fatal issue occurred while processing the current_path. */
55 static void
issue(int e,const char * msg)56 issue (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. */
69 static void
elf_issue(const char * msg)70 elf_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. */
78 static bool flag_only_regular_files;
79
80 static bool
open_file(void)81 open_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
110 static void
close_file(void)111 close_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. */
121 static Elf *elf;
122
123 /* Set by parse_opt. */
124 static bool flag_compressed;
125
126 static bool
open_elf(void)127 open_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
151 static void
close_elf(void)152 close_elf (void)
153 {
154 if (elf != NULL)
155 {
156 elf_end (elf);
157 elf = NULL;
158 }
159
160 close_file ();
161 }
162
163 static const char *
elf_kind_string(int kind)164 elf_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
181 static const char *
elf_type_string(int type)182 elf_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
201 static int elf_type;
202 static bool has_program_load;
203 static bool has_sections;
204 static bool has_bits_alloc;
205 static bool has_program_interpreter;
206 static bool has_dynamic;
207 static bool has_soname;
208 static bool has_pie_flag;
209 static bool has_dt_debug;
210 static bool has_symtab;
211 static bool has_debug_sections;
212 static bool has_modinfo;
213 static bool has_gnu_linkonce_this_module;
214
215 static bool
run_classify(void)216 run_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 const char *debug_prefix = ".debug_";
339 const char *zdebug_prefix = ".zdebug_";
340 if (strncmp (section_name, debug_prefix, strlen (debug_prefix)) == 0
341 || strncmp (section_name, zdebug_prefix,
342 strlen (zdebug_prefix)) == 0)
343 {
344 if (verbose > 1 && !has_debug_sections)
345 fputs ("debug: .debug_* section found\n", stderr);
346 has_debug_sections = true;
347 }
348 if (strcmp (section_name, ".modinfo") == 0)
349 {
350 if (verbose > 1)
351 fputs ("debug: .modinfo section found\n", stderr);
352 has_modinfo = true;
353 }
354 if (strcmp (section_name, ".gnu.linkonce.this_module") == 0)
355 {
356 if (verbose > 1)
357 fputs ("debug: .gnu.linkonce.this_module section found\n",
358 stderr);
359 has_gnu_linkonce_this_module = true;
360 }
361 }
362 }
363
364 /* Examine the dynamic section. */
365 if (has_dynamic)
366 {
367 Elf_Data *data = elf_getdata_rawchunk (elf, dyn_seg.p_offset,
368 dyn_seg.p_filesz,
369 ELF_T_DYN);
370 if (data != NULL)
371 for (int dyn_idx = 0; ; ++dyn_idx)
372 {
373 GElf_Dyn dyn_storage;
374 GElf_Dyn *dyn = gelf_getdyn (data, dyn_idx, &dyn_storage);
375 if (dyn == NULL)
376 break;
377 if (verbose > 2)
378 fprintf (stderr, "debug: dynamic entry %d"
379 " with tag %llu found\n",
380 dyn_idx, (unsigned long long int) dyn->d_tag);
381 if (dyn->d_tag == DT_SONAME)
382 has_soname = true;
383 if (dyn->d_tag == DT_FLAGS_1 && (dyn->d_un.d_val & DF_1_PIE))
384 has_pie_flag = true;
385 if (dyn->d_tag == DT_DEBUG)
386 has_dt_debug = true;
387 if (dyn->d_tag == DT_NULL)
388 break;
389 }
390 }
391
392 if (verbose > 0)
393 {
394 fprintf (stderr, "info: %s: ELF type: %s (0x%x)\n", current_path,
395 elf_type_string (elf_type), elf_type);
396 if (has_program_load)
397 fprintf (stderr, "info: %s: PT_LOAD found\n", current_path);
398 if (has_sections)
399 fprintf (stderr, "info: %s: has sections\n", current_path);
400 if (has_bits_alloc)
401 fprintf (stderr, "info: %s: allocated (real) section found\n",
402 current_path);
403 if (has_program_interpreter)
404 fprintf (stderr, "info: %s: program interpreter found\n",
405 current_path);
406 if (has_dynamic)
407 fprintf (stderr, "info: %s: dynamic segment found\n", current_path);
408 if (has_soname)
409 fprintf (stderr, "info: %s: soname found\n", current_path);
410 if (has_pie_flag)
411 fprintf (stderr, "info: %s: DF_1_PIE flag found\n", current_path);
412 if (has_dt_debug)
413 fprintf (stderr, "info: %s: DT_DEBUG found\n", current_path);
414 if (has_symtab)
415 fprintf (stderr, "info: %s: symbol table found\n", current_path);
416 if (has_debug_sections)
417 fprintf (stderr, "info: %s: .debug_* section found\n", current_path);
418 if (has_modinfo)
419 fprintf (stderr, "info: %s: .modinfo section found\n", current_path);
420 if (has_gnu_linkonce_this_module)
421 fprintf (stderr,
422 "info: %s: .gnu.linkonce.this_module section found\n",
423 current_path);
424 }
425
426 return true;
427 }
428
429 static bool
is_elf(void)430 is_elf (void)
431 {
432 return elf_kind (elf) != ELF_K_NONE;
433 }
434
435 static bool
is_elf_file(void)436 is_elf_file (void)
437 {
438 return elf_kind (elf) == ELF_K_ELF;
439 }
440
441 static bool
is_elf_archive(void)442 is_elf_archive (void)
443 {
444 return elf_kind (elf) == ELF_K_AR;
445 }
446
447 static bool
is_core(void)448 is_core (void)
449 {
450 return elf_kind (elf) == ELF_K_ELF && elf_type == ET_CORE;
451 }
452
453 /* Return true if the file is a loadable object, which basically means
454 it is an ELF file, but not a relocatable object or a core dump
455 file. (The kernel and various userspace components can load ET_REL
456 files, but we disregard that for our classification purposes.) */
457 static bool
is_loadable(void)458 is_loadable (void)
459 {
460 return elf_kind (elf) == ELF_K_ELF
461 && (elf_type == ET_EXEC || elf_type == ET_DYN)
462 && has_program_load
463 && (!has_sections || has_bits_alloc); /* It isn't debug-only. */
464 }
465
466 /* Return true if the file is an ELF file which has a symbol table or
467 .debug_* sections (and thus can be stripped further). */
468 static bool
is_unstripped(void)469 is_unstripped (void)
470 {
471 return elf_kind (elf) != ELF_K_NONE
472 && (elf_type == ET_REL || elf_type == ET_EXEC || elf_type == ET_DYN)
473 && (has_symtab || has_debug_sections);
474 }
475
476 /* Return true if the file contains only debuginfo, but no loadable
477 program bits. Then it is most likely a separate .debug file, a dwz
478 multi-file or a .dwo file. Note that it can still be loadable,
479 but in that case the phdrs shouldn't be trusted. */
480 static bool
is_debug_only(void)481 is_debug_only (void)
482 {
483 return elf_kind (elf) != ELF_K_NONE
484 && (elf_type == ET_REL || elf_type == ET_EXEC || elf_type == ET_DYN)
485 && (has_debug_sections || has_symtab)
486 && !has_bits_alloc;
487 }
488
489 static bool
is_shared(void)490 is_shared (void)
491 {
492 if (!is_loadable ())
493 return false;
494
495 /* The ELF type is very clear: this is an executable. */
496 if (elf_type == ET_EXEC)
497 return false;
498
499 /* If there is no dynamic section, the file cannot be loaded as a
500 shared object. */
501 if (!has_dynamic)
502 return false;
503
504 /* If the object is marked as PIE, it is definitely an executable,
505 and not a loadlable shared object. */
506 if (has_pie_flag)
507 return false;
508
509 /* Treat a DT_SONAME tag as a strong indicator that this is a shared
510 object. */
511 if (has_soname)
512 return true;
513
514 /* This is probably a PIE program: there is no soname, but a program
515 interpreter. In theory, this file could be also a DSO with a
516 soname implied by its file name that can be run as a program.
517 This situation is impossible to resolve in the general case. */
518 if (has_program_interpreter)
519 return false;
520
521 /* Roland McGrath mentions in
522 <https://www.sourceware.org/ml/libc-alpha/2015-03/msg00605.html>,
523 that “we defined a PIE as an ET_DYN with a DT_DEBUG”. This
524 matches current binutils behavior (version 2.32). DT_DEBUG is
525 added if bfd_link_executable returns true or if bfd_link_pic
526 returns false, depending on the architectures. However, DT_DEBUG
527 is not documented as being specific to executables, therefore use
528 it only as a low-priority discriminator. */
529 if (has_dt_debug)
530 return false;
531
532 return true;
533 }
534
535 static bool
is_executable(void)536 is_executable (void)
537 {
538 if (!is_loadable ())
539 return false;
540
541 /* A loadable object which is not a shared object is treated as an
542 executable. */
543 return !is_shared ();
544 }
545
546 /* Like is_executable, but the object can also be a shared library at
547 the same time. */
548 static bool
is_program(void)549 is_program (void)
550 {
551 if (!is_loadable ())
552 return false;
553
554 /* The ELF type is very clear: this is an executable. */
555 if (elf_type == ET_EXEC)
556 return true;
557
558 /* If the object is marked as PIE, it is definitely an executable,
559 and not a loadlable shared object. */
560 if (has_pie_flag)
561 return true;
562
563 /* This is probably a PIE program. It isn't ET_EXEC, but has a
564 program interpreter. In theory, this file could be also a DSO
565 with a soname. This situation is impossible to resolve in the
566 general case. See is_shared. This is different from
567 is_executable. */
568 if (has_program_interpreter)
569 return true;
570
571 /* Roland McGrath mentions in
572 <https://www.sourceware.org/ml/libc-alpha/2015-03/msg00605.html>,
573 that “we defined a PIE as an ET_DYN with a DT_DEBUG”. This
574 matches current binutils behavior (version 2.32). DT_DEBUG is
575 added if bfd_link_executable returns true or if bfd_link_pic
576 returns false, depending on the architectures. However, DT_DEBUG
577 is not documented as being specific to executables, therefore use
578 it only as a low-priority discriminator. */
579 if (has_dt_debug)
580 return true;
581
582 return false;
583 }
584
585 /* Like is_shared but the library could also be an executable. */
586 static bool
is_library(void)587 is_library (void)
588 {
589 /* Only ET_DYN can be shared libraries. */
590 if (elf_type != ET_DYN)
591 return false;
592
593 if (!is_loadable ())
594 return false;
595
596 /* Without a PT_DYNAMIC segment the library cannot be loaded. */
597 if (!has_dynamic)
598 return false;
599
600 /* This really is a (PIE) executable. See is_shared. */
601 if (has_pie_flag || has_dt_debug)
602 return false;
603
604 /* It could still (also) be a (PIE) executable, but most likely you
605 can dlopen it just fine. */
606 return true;
607 }
608
609 /* Returns true if the file is a linux kernel module (is ET_REL and
610 has the two magic sections .modinfo and .gnu.linkonce.this_module). */
611 static bool
is_linux_kernel_module(void)612 is_linux_kernel_module (void)
613 {
614 return (elf_kind (elf) == ELF_K_ELF
615 && elf_type == ET_REL
616 && has_modinfo
617 && has_gnu_linkonce_this_module);
618 }
619
620 enum classify_requirement { do_not_care, required, forbidden };
621
622 enum classify_check
623 {
624 classify_elf,
625 classify_elf_file,
626 classify_elf_archive,
627 classify_core,
628 classify_unstripped,
629 classify_executable,
630 classify_program,
631 classify_shared,
632 classify_library,
633 classify_linux_kernel_module,
634 classify_debug_only,
635 classify_loadable,
636
637 classify_check_last = classify_loadable
638 };
639
640 enum
641 {
642 classify_check_offset = 1000,
643 classify_check_not_offset = 2000,
644
645 classify_flag_stdin = 3000,
646 classify_flag_stdin0,
647 classify_flag_no_stdin,
648 classify_flag_print,
649 classify_flag_print0,
650 classify_flag_no_print,
651 classify_flag_matching,
652 classify_flag_not_matching,
653 };
654
655 static bool
classify_check_positive(int key)656 classify_check_positive (int key)
657 {
658 return key >= classify_check_offset
659 && key <= classify_check_offset + classify_check_last;
660 }
661
662 static bool
classify_check_negative(int key)663 classify_check_negative (int key)
664 {
665 return key >= classify_check_not_offset
666 && key <= classify_check_not_offset + classify_check_last;
667 }
668
669 /* Set by parse_opt. */
670 static enum classify_requirement requirements[classify_check_last + 1];
671 static enum { no_stdin, do_stdin, do_stdin0 } flag_stdin;
672 static enum { no_print, do_print, do_print0 } flag_print;
673 static bool flag_print_matching = true;
674
675 static error_t
parse_opt(int key,char * arg,struct argp_state * state)676 parse_opt (int key, char *arg __attribute__ ((unused)),
677 struct argp_state *state __attribute__ ((unused)))
678 {
679 if (classify_check_positive (key))
680 requirements[key - classify_check_offset] = required;
681 else if (classify_check_negative (key))
682 requirements[key - classify_check_not_offset] = forbidden;
683 else
684 switch (key)
685 {
686 case 'v':
687 ++verbose;
688 break;
689
690 case 'q':
691 --verbose;
692 break;
693
694 case 'z':
695 flag_compressed = true;
696 break;
697
698 case 'f':
699 flag_only_regular_files = true;
700 break;
701
702 case classify_flag_stdin:
703 flag_stdin = do_stdin;
704 break;
705
706 case classify_flag_stdin0:
707 flag_stdin = do_stdin0;
708 break;
709
710 case classify_flag_no_stdin:
711 flag_stdin = no_stdin;
712 break;
713
714 case classify_flag_print:
715 flag_print = do_print;
716 break;
717
718 case classify_flag_print0:
719 flag_print = do_print0;
720 break;
721
722 case classify_flag_no_print:
723 flag_print = no_print;
724 break;
725
726 case classify_flag_matching:
727 flag_print_matching = true;
728 break;
729
730 case classify_flag_not_matching:
731 flag_print_matching = false;
732 break;
733
734 default:
735 return ARGP_ERR_UNKNOWN;
736 }
737
738 return 0;
739 }
740
741 /* Perform requested checks against the file at current_path. If
742 necessary, sets *STATUS to 1 if checks failed. */
743 static void
process_current_path(int * status)744 process_current_path (int *status)
745 {
746 bool checks_passed = true;
747
748 if (open_elf () && run_classify ())
749 {
750 bool checks[] =
751 {
752 [classify_elf] = is_elf (),
753 [classify_elf_file] = is_elf_file (),
754 [classify_elf_archive] = is_elf_archive (),
755 [classify_core] = is_core (),
756 [classify_unstripped] = is_unstripped (),
757 [classify_executable] = is_executable (),
758 [classify_program] = is_program (),
759 [classify_shared] = is_shared (),
760 [classify_library] = is_library (),
761 [classify_linux_kernel_module] = is_linux_kernel_module (),
762 [classify_debug_only] = is_debug_only (),
763 [classify_loadable] = is_loadable (),
764 };
765
766 if (verbose > 1)
767 {
768 if (checks[classify_elf])
769 fprintf (stderr, "debug: %s: elf\n", current_path);
770 if (checks[classify_elf_file])
771 fprintf (stderr, "debug: %s: elf_file\n", current_path);
772 if (checks[classify_elf_archive])
773 fprintf (stderr, "debug: %s: elf_archive\n", current_path);
774 if (checks[classify_core])
775 fprintf (stderr, "debug: %s: core\n", current_path);
776 if (checks[classify_unstripped])
777 fprintf (stderr, "debug: %s: unstripped\n", current_path);
778 if (checks[classify_executable])
779 fprintf (stderr, "debug: %s: executable\n", current_path);
780 if (checks[classify_program])
781 fprintf (stderr, "debug: %s: program\n", current_path);
782 if (checks[classify_shared])
783 fprintf (stderr, "debug: %s: shared\n", current_path);
784 if (checks[classify_library])
785 fprintf (stderr, "debug: %s: library\n", current_path);
786 if (checks[classify_linux_kernel_module])
787 fprintf (stderr, "debug: %s: linux kernel module\n", current_path);
788 if (checks[classify_debug_only])
789 fprintf (stderr, "debug: %s: debug-only\n", current_path);
790 if (checks[classify_loadable])
791 fprintf (stderr, "debug: %s: loadable\n", current_path);
792 }
793
794 for (enum classify_check check = 0;
795 check <= classify_check_last; ++check)
796 switch (requirements[check])
797 {
798 case required:
799 if (!checks[check])
800 checks_passed = false;
801 break;
802 case forbidden:
803 if (checks[check])
804 checks_passed = false;
805 break;
806 case do_not_care:
807 break;
808 }
809 }
810 else if (file_fd == -1)
811 checks_passed = false; /* There is nothing to check, bad file. */
812 else
813 {
814 for (enum classify_check check = 0;
815 check <= classify_check_last; ++check)
816 if (requirements[check] == required)
817 checks_passed = false;
818 }
819
820 close_elf ();
821
822 switch (flag_print)
823 {
824 case do_print:
825 if (checks_passed == flag_print_matching)
826 puts (current_path);
827 break;
828 case do_print0:
829 if (checks_passed == flag_print_matching)
830 if (fwrite (current_path, strlen (current_path) + 1, 1, stdout) < 1)
831 issue (errno, N_("writing to standard output"));
832 break;
833 case no_print:
834 if (!checks_passed)
835 *status = 1;
836 break;
837 }
838 }
839
840 /* Called to process standard input if flag_stdin is not no_stdin. */
841 static void
process_stdin(int * status)842 process_stdin (int *status)
843 {
844 char delim;
845 if (flag_stdin == do_stdin0)
846 delim = '\0';
847 else
848 delim = '\n';
849
850 char *buffer = NULL;
851 size_t buffer_size = 0;
852 while (true)
853 {
854 ssize_t ret = getdelim (&buffer, &buffer_size, delim, stdin);
855 if (ferror (stdin))
856 {
857 current_path = NULL;
858 issue (errno, N_("reading from standard input"));
859 break;
860 }
861 if (feof (stdin))
862 break;
863 if (ret < 0)
864 abort (); /* Cannot happen due to error checks above. */
865 if (delim != '\0' && ret > 0 && buffer[ret - 1] == '\n')
866 buffer[ret - 1] = '\0';
867 current_path = buffer;
868 process_current_path (status);
869 }
870
871 free (buffer);
872 }
873
874 int
main(int argc,char ** argv)875 main (int argc, char **argv)
876 {
877 const struct argp_option options[] =
878 {
879 { NULL, 0, NULL, OPTION_DOC, N_("Classification options"), 1 },
880 { "elf", classify_check_offset + classify_elf, NULL, 0,
881 N_("File looks like an ELF object or archive/static library (default)")
882 , 1 },
883 { "elf-file", classify_check_offset + classify_elf_file, NULL, 0,
884 N_("File is an regular ELF object (not an archive/static library)")
885 , 1 },
886 { "elf-archive", classify_check_offset + classify_elf_archive, NULL, 0,
887 N_("File is an ELF archive or static library")
888 , 1 },
889 { "core", classify_check_offset + classify_core, NULL, 0,
890 N_("File is an ELF core dump file")
891 , 1 },
892 { "unstripped", classify_check_offset + classify_unstripped, NULL, 0,
893 N_("File is an ELF file with symbol table or .debug_* sections \
894 and can be stripped further"), 1 },
895 { "executable", classify_check_offset + classify_executable, NULL, 0,
896 N_("File is (primarily) an ELF program executable \
897 (not primarily a DSO)"), 1 },
898 { "program", classify_check_offset + classify_program, NULL, 0,
899 N_("File is an ELF program executable \
900 (might also be a DSO)"), 1 },
901 { "shared", classify_check_offset + classify_shared, NULL, 0,
902 N_("File is (primarily) an ELF shared object (DSO) \
903 (not primarily an executable)"), 1 },
904 { "library", classify_check_offset + classify_library, NULL, 0,
905 N_("File is an ELF shared object (DSO) \
906 (might also be an executable)"), 1 },
907 { "linux-kernel-module", (classify_check_offset
908 + classify_linux_kernel_module), NULL, 0,
909 N_("File is a linux kernel module"), 1 },
910 { "debug-only", (classify_check_offset + classify_debug_only), NULL, 0,
911 N_("File is a debug only ELF file \
912 (separate .debug, .dwo or dwz multi-file)"), 1 },
913 { "loadable", classify_check_offset + classify_loadable, NULL, 0,
914 N_("File is a loadable ELF object (program or shared object)"), 1 },
915
916 /* Negated versions of the above. */
917 { "not-elf", classify_check_not_offset + classify_elf,
918 NULL, OPTION_HIDDEN, NULL, 1 },
919 { "not-elf-file", classify_check_not_offset + classify_elf_file,
920 NULL, OPTION_HIDDEN, NULL, 1 },
921 { "not-elf-archive", classify_check_not_offset + classify_elf_archive,
922 NULL, OPTION_HIDDEN, NULL, 1 },
923 { "not-core", classify_check_not_offset + classify_core,
924 NULL, OPTION_HIDDEN, NULL, 1 },
925 { "not-unstripped", classify_check_not_offset + classify_unstripped,
926 NULL, OPTION_HIDDEN, NULL, 1 },
927 { "not-executable", classify_check_not_offset + classify_executable,
928 NULL, OPTION_HIDDEN, NULL, 1 },
929 { "not-program", classify_check_not_offset + classify_program,
930 NULL, OPTION_HIDDEN, NULL, 1 },
931 { "not-shared", classify_check_not_offset + classify_shared,
932 NULL, OPTION_HIDDEN, NULL, 1 },
933 { "not-library", classify_check_not_offset + classify_library,
934 NULL, OPTION_HIDDEN, NULL, 1 },
935 { "not-linux-kernel-module", (classify_check_not_offset
936 + classify_linux_kernel_module),
937 NULL, OPTION_HIDDEN, NULL, 1 },
938 { "not-debug-only", (classify_check_not_offset + classify_debug_only),
939 NULL, OPTION_HIDDEN, NULL, 1 },
940 { "not-loadable", classify_check_not_offset + classify_loadable,
941 NULL, OPTION_HIDDEN, NULL, 1 },
942
943 { NULL, 0, NULL, OPTION_DOC, N_("Input flags"), 2 },
944 { "file", 'f', NULL, 0,
945 N_("Only classify regular (not symlink nor special device) files"), 2 },
946 { "stdin", classify_flag_stdin, NULL, 0,
947 N_("Also read file names to process from standard input, \
948 separated by newlines"), 2 },
949 { "stdin0", classify_flag_stdin0, NULL, 0,
950 N_("Also read file names to process from standard input, \
951 separated by ASCII NUL bytes"), 2 },
952 { "no-stdin", classify_flag_stdin, NULL, 0,
953 N_("Do not read files from standard input (default)"), 2 },
954 { "compressed", 'z', NULL, 0,
955 N_("Try to open compressed files or embedded (kernel) ELF images"),
956 2 },
957
958 { NULL, 0, NULL, OPTION_DOC, N_("Output flags"), 3 },
959 { "print", classify_flag_print, NULL, 0,
960 N_("Output names of files, separated by newline"), 3 },
961 { "print0", classify_flag_print0, NULL, 0,
962 N_("Output names of files, separated by ASCII NUL"), 3 },
963 { "no-print", classify_flag_no_print, NULL, 0,
964 N_("Do not output file names"), 3 },
965 { "matching", classify_flag_matching, NULL, 0,
966 N_("If printing file names, print matching files (default)"), 3 },
967 { "not-matching", classify_flag_not_matching, NULL, 0,
968 N_("If printing file names, print files that do not match"), 3 },
969
970 { NULL, 0, NULL, OPTION_DOC, N_("Additional flags"), 4 },
971 { "verbose", 'v', NULL, 0,
972 N_("Output additional information (can be specified multiple times)"), 4 },
973 { "quiet", 'q', NULL, 0,
974 N_("Suppress some error output (counterpart to --verbose)"), 4 },
975 { NULL, 0, NULL, 0, NULL, 0 }
976 };
977
978 const struct argp argp =
979 {
980 .options = options,
981 .parser = parse_opt,
982 .args_doc = N_("FILE..."),
983 .doc = N_("\
984 Determine the type of an ELF file.\
985 \n\n\
986 All of the classification options must apply at the same time to a \
987 particular file. Classification options can be negated using a \
988 \"--not-\" prefix.\
989 \n\n\
990 Since modern ELF does not clearly distinguish between programs and \
991 dynamic shared objects, you should normally use either --executable or \
992 --shared to identify the primary purpose of a file. \
993 Only one of the --shared and --executable checks can pass for a file.\
994 \n\n\
995 If you want to know whether an ELF object might a program or a \
996 shared library (but could be both), then use --program or --library. \
997 Some ELF files will classify as both a program and a library.\
998 \n\n\
999 If you just want to know whether an ELF file is loadable (as program \
1000 or library) use --loadable. Note that files that only contain \
1001 (separate) debug information (--debug-only) are never --loadable (even \
1002 though they might contain program headers). Linux kernel modules are \
1003 also not --loadable (in the normal sense).\
1004 \n\n\
1005 Without any of the --print options, the program exits with status 0 \
1006 if the requested checks pass for all input files, with 1 if a check \
1007 fails for any file, and 2 if there is an environmental issue (such \
1008 as a file read error or a memory allocation error).\
1009 \n\n\
1010 When printing file names, the program exits with status 0 even if \
1011 no file names are printed, and exits with status 2 if there is an \
1012 environmental issue.\
1013 \n\n\
1014 On usage error (e.g. a bad option was given), the program exits with \
1015 a status code larger than 2.\
1016 \n\n\
1017 The --quiet or -q option suppresses some error warning output, but \
1018 doesn't change the exit status.\
1019 ")
1020 };
1021
1022 /* Require that the file is an ELF file by default. User can
1023 disable with --not-elf. */
1024 requirements[classify_elf] = required;
1025
1026 int remaining;
1027 if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
1028 return 2;
1029
1030 elf_version (EV_CURRENT);
1031
1032 int status = 0;
1033
1034 for (int i = remaining; i < argc; ++i)
1035 {
1036 current_path = argv[i];
1037 process_current_path (&status);
1038 }
1039
1040 if (flag_stdin != no_stdin)
1041 process_stdin (&status);
1042
1043 if (issue_found)
1044 return 2;
1045
1046 return status;
1047 }
1048