LCOV - code coverage report
Current view: top level - src - elfclassify.c (source / functions) Coverage Total Hit
Test: elfutils-0.193 Lines: 54.7 % 406 222
Test Date: 2025-08-12 17:49:42 Functions: 77.3 % 22 17
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 50.8 % 319 162

             Branch data     Line data    Source code
       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.  */
      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
      56                 :           0 : issue (int e, const char *msg)
      57                 :             : {
      58         [ #  # ]:           0 :   if (verbose >= 0)
      59                 :             :     {
      60         [ #  # ]:           0 :       if (current_path == NULL)
      61                 :           0 :         error (0, e, "%s", msg);
      62                 :             :       else
      63                 :           0 :         error (0, e, "%s '%s'", msg, current_path);
      64                 :             :     }
      65                 :           0 :   issue_found = true;
      66                 :           0 : }
      67                 :             : 
      68                 :             : /* Non-fatal issue occurred while processing the current ELF.  */
      69                 :             : static void
      70                 :           0 : elf_issue (const char *msg)
      71                 :             : {
      72         [ #  # ]:           0 :   if (verbose >= 0)
      73                 :           0 :     error (0, 0, "%s: %s: '%s'", msg, elf_errmsg (-1), current_path);
      74                 :           0 :   issue_found = true;
      75                 :           0 : }
      76                 :             : 
      77                 :             : /* Set by parse_opt.  */
      78                 :             : static bool flag_only_regular_files;
      79                 :             : 
      80                 :             : static bool
      81                 :        1200 : open_file (void)
      82                 :             : {
      83         [ -  + ]:        1200 :   if (verbose > 1)
      84                 :           0 :     fprintf (stderr, "debug: processing file: %s\n", current_path);
      85                 :             : 
      86         [ -  + ]:        1200 :   file_fd = open (current_path, O_RDONLY | (flag_only_regular_files
      87         [ +  - ]:        1200 :                                             ? O_NOFOLLOW : 0));
      88         [ -  + ]:        1200 :   if (file_fd < 0)
      89                 :             :     {
      90   [ #  #  #  # ]:           0 :       if (!flag_only_regular_files || errno != ELOOP)
      91                 :           0 :         issue (errno, N_("opening"));
      92                 :           0 :       return false;
      93                 :             :     }
      94                 :             : 
      95                 :        1200 :   struct stat st;
      96         [ -  + ]:        1200 :   if (fstat (file_fd, &st) != 0)
      97                 :             :     {
      98                 :           0 :       issue (errno, N_("reading"));
      99                 :           0 :       return false;
     100                 :             :     }
     101                 :             : 
     102                 :             :   /* Don't even bother with directories.  */
     103         [ -  + ]:        1200 :   if (S_ISDIR (st.st_mode)
     104   [ -  +  -  - ]:        1200 :       || (flag_only_regular_files && !S_ISREG (st.st_mode)))
     105                 :             :     return false;
     106                 :             : 
     107                 :             :   return true;
     108                 :             : }
     109                 :             : 
     110                 :             : static void
     111                 :        1200 : close_file (void)
     112                 :             : {
     113         [ +  - ]:        1200 :   if (file_fd >= 0)
     114                 :             :     {
     115                 :        1200 :       close (file_fd);
     116                 :        1200 :       file_fd = -1;
     117                 :             :     }
     118                 :        1200 : }
     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
     127                 :        1200 : open_elf (void)
     128                 :             : {
     129         [ -  + ]:        1200 :   if (!open_file ())
     130                 :             :     {
     131                 :             :       /* Make sure the file descriptor is gone.  */
     132                 :           0 :       close_file ();
     133                 :           0 :       return false;
     134                 :             :     }
     135                 :             : 
     136         [ -  + ]:        1200 :   if (flag_compressed)
     137                 :           0 :     elf = dwelf_elf_begin (file_fd);
     138                 :             :   else
     139                 :        1200 :     elf = elf_begin (file_fd, ELF_C_READ, NULL);
     140                 :             : 
     141         [ -  + ]:        1200 :   if (elf == NULL)
     142                 :             :     {
     143                 :           0 :       elf_issue ("opening ELF file");
     144                 :           0 :       close_file ();
     145                 :           0 :       return false;
     146                 :             :     }
     147                 :             : 
     148                 :             :   return true;
     149                 :             : }
     150                 :             : 
     151                 :             : static void
     152                 :        1200 : close_elf (void)
     153                 :             : {
     154         [ +  - ]:        1200 :   if (elf != NULL)
     155                 :             :     {
     156                 :        1200 :       elf_end (elf);
     157                 :        1200 :       elf = NULL;
     158                 :             :     }
     159                 :             : 
     160                 :        1200 :   close_file ();
     161                 :        1200 : }
     162                 :             : 
     163                 :             : static const char *
     164                 :           0 : elf_kind_string (int kind)
     165                 :             : {
     166   [ #  #  #  #  :           0 :   switch (kind)
                      # ]
     167                 :             :     {
     168                 :             :     case ELF_K_NONE:
     169                 :             :       return "ELF_K_NONE";
     170                 :           0 :     case ELF_K_AR:
     171                 :           0 :       return "ELF_K_AR";
     172                 :           0 :     case ELF_K_COFF:
     173                 :           0 :       return "ELF_K_COFF"; /* libelf doesn't really support this.  */
     174                 :           0 :     case ELF_K_ELF:
     175                 :           0 :       return "ELF_K_ELF";
     176                 :           0 :     default:
     177                 :           0 :       return "<unknown>";
     178                 :             :     }
     179                 :             : }
     180                 :             : 
     181                 :             : static const char *
     182                 :           0 : elf_type_string (int type)
     183                 :             : {
     184   [ #  #  #  #  :           0 :   switch (type)
                   #  # ]
     185                 :             :     {
     186                 :             :     case ET_NONE:
     187                 :             :       return "ET_NONE";
     188                 :           0 :     case ET_REL:
     189                 :           0 :       return "ET_REL";
     190                 :           0 :     case ET_EXEC:
     191                 :           0 :       return "ET_EXEC";
     192                 :           0 :     case ET_DYN:
     193                 :           0 :       return "ET_DYN";
     194                 :           0 :     case ET_CORE:
     195                 :           0 :       return "ET_CORE";
     196                 :           0 :     default:
     197                 :           0 :       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
     216                 :        1200 : run_classify (void)
     217                 :             : {
     218                 :             :   /* Reset to unanalyzed default.  */
     219                 :        1200 :   elf_type = 0;
     220                 :        1200 :   has_program_load = false;
     221                 :        1200 :   has_sections = false;
     222                 :        1200 :   has_bits_alloc = false;
     223                 :        1200 :   has_program_interpreter = false;
     224                 :        1200 :   has_dynamic = false;
     225                 :        1200 :   has_soname = false;
     226                 :        1200 :   has_pie_flag = false;
     227                 :        1200 :   has_dt_debug = false;
     228                 :        1200 :   has_symtab = false;
     229                 :        1200 :   has_debug_sections = false;
     230                 :        1200 :   has_modinfo = false;
     231                 :        1200 :   has_gnu_linkonce_this_module = false;
     232                 :             : 
     233                 :        1200 :   int kind = elf_kind (elf);
     234         [ -  + ]:        1200 :   if (verbose > 0)
     235                 :           0 :     fprintf (stderr, "info: %s: ELF kind: %s (0x%x)\n", current_path,
     236                 :             :              elf_kind_string (kind), kind);
     237         [ +  + ]:        1200 :   if (kind != ELF_K_ELF)
     238                 :             :     return true;
     239                 :             : 
     240                 :        1180 :   GElf_Ehdr ehdr_storage;
     241                 :        1180 :   GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_storage);
     242         [ -  + ]:        1180 :   if (ehdr == NULL)
     243                 :             :     {
     244                 :           0 :       elf_issue (N_("ELF header"));
     245                 :           0 :       return false;
     246                 :             :     }
     247                 :        1180 :   elf_type = ehdr->e_type;
     248                 :             : 
     249                 :             :   /* Examine program headers.  */
     250                 :        1180 :   GElf_Phdr dyn_seg = { .p_type = 0 };
     251                 :             :   {
     252                 :        1180 :     size_t nphdrs;
     253         [ -  + ]:        1180 :     if (elf_getphdrnum (elf, &nphdrs) != 0)
     254                 :             :       {
     255                 :           0 :         elf_issue (N_("program headers"));
     256                 :           0 :         return false;
     257                 :             :       }
     258         [ +  + ]:        8740 :     for (size_t phdr_idx = 0; phdr_idx < nphdrs; ++phdr_idx)
     259                 :             :       {
     260                 :        7560 :         GElf_Phdr phdr_storage;
     261                 :        7560 :         GElf_Phdr *phdr = gelf_getphdr (elf, phdr_idx, &phdr_storage);
     262         [ -  + ]:        7560 :         if (phdr == NULL)
     263                 :             :           {
     264                 :           0 :             elf_issue (N_("program header"));
     265                 :           0 :             return false;
     266                 :             :           }
     267         [ +  + ]:        7560 :         if (phdr->p_type == PT_DYNAMIC)
     268                 :             :           {
     269                 :         504 :             dyn_seg = *phdr;
     270                 :         504 :             has_dynamic = true;
     271                 :             :           }
     272         [ +  + ]:        7560 :         if (phdr->p_type == PT_INTERP)
     273                 :         264 :           has_program_interpreter = true;
     274         [ +  + ]:        7560 :         if (phdr->p_type == PT_LOAD)
     275                 :        4196 :           has_program_load = true;
     276                 :             :       }
     277                 :             :   }
     278                 :             : 
     279                 :             :   /* Do we have sections?  */
     280                 :             :   {
     281                 :        1180 :     size_t nshdrs;
     282         [ -  + ]:        1180 :     if (elf_getshdrnum (elf, &nshdrs) != 0)
     283                 :             :       {
     284                 :           0 :         elf_issue (N_("section headers"));
     285                 :           0 :         return false;
     286                 :             :       }
     287         [ +  + ]:        1180 :     if (nshdrs > 0)
     288                 :         940 :       has_sections = true;
     289                 :             :   }
     290                 :             : 
     291                 :             :   {
     292                 :        1180 :     size_t shstrndx;
     293         [ -  + ]:        1180 :     if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
     294                 :             :       {
     295                 :           0 :         elf_issue (N_("section header string table index"));
     296                 :           0 :         return false;
     297                 :             :       }
     298                 :             : 
     299                 :             :     Elf_Scn *scn = NULL;
     300                 :       54396 :     while (true)
     301                 :       26608 :       {
     302                 :       27788 :         scn = elf_nextscn (elf, scn);
     303         [ +  + ]:       27788 :         if (scn == NULL)
     304                 :             :           break;
     305                 :       26608 :         GElf_Shdr shdr_storage;
     306                 :       26608 :         GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_storage);
     307         [ -  + ]:       26608 :         if (shdr == NULL)
     308                 :             :           {
     309                 :           0 :             elf_issue (N_("could not obtain section header"));
     310                 :           0 :             return false;
     311                 :             :           }
     312                 :       26608 :         const char *section_name = elf_strptr (elf, shstrndx, shdr->sh_name);
     313         [ -  + ]:       26608 :         if (section_name == NULL)
     314                 :             :           {
     315                 :           0 :             elf_issue(N_("could not obtain section name"));
     316                 :           0 :             return false;
     317                 :             :           }
     318         [ -  + ]:       26608 :         if (verbose > 2)
     319                 :           0 :           fprintf (stderr, "debug: section header %s (type %d) found\n",
     320                 :             :                    section_name, shdr->sh_type);
     321         [ +  + ]:       26608 :         if (shdr->sh_type == SHT_SYMTAB)
     322                 :             :           {
     323         [ -  + ]:         860 :             if (verbose > 1)
     324                 :           0 :               fputs ("debug: symtab section found\n", stderr);
     325                 :         860 :             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                 :       26608 :         if (shdr->sh_type != SHT_NOBITS
     330         [ +  + ]:       26608 :             && shdr->sh_type != SHT_NOTE
     331         [ +  + ]:       20392 :             && (shdr->sh_flags & SHF_ALLOC) != 0)
     332                 :             :           {
     333   [ -  +  -  - ]:        9568 :             if (verbose > 1 && !has_bits_alloc)
     334                 :           0 :               fputs ("debug: allocated (non-nobits/note) section found\n",
     335                 :             :                      stderr);
     336                 :        9568 :             has_bits_alloc = true;
     337                 :             :           }
     338         [ +  + ]:       26608 :         if (startswith (section_name, ".debug_")
     339         [ +  + ]:       22752 :             || startswith (section_name, ".zdebug_"))
     340                 :             :           {
     341   [ -  +  -  - ]:        4668 :             if (verbose > 1 && !has_debug_sections)
     342                 :           0 :               fputs ("debug: .debug_* section found\n", stderr);
     343                 :        4668 :             has_debug_sections = true;
     344                 :             :           }
     345         [ +  + ]:       26608 :         if (strcmp (section_name, ".modinfo") == 0)
     346                 :             :           {
     347         [ -  + ]:         160 :             if (verbose > 1)
     348                 :           0 :               fputs ("debug: .modinfo section found\n", stderr);
     349                 :         160 :             has_modinfo = true;
     350                 :             :           }
     351         [ +  + ]:       26608 :         if (strcmp (section_name, ".gnu.linkonce.this_module") == 0)
     352                 :             :           {
     353         [ -  + ]:         160 :             if (verbose > 1)
     354                 :           0 :               fputs ("debug: .gnu.linkonce.this_module section found\n",
     355                 :             :                      stderr);
     356                 :         160 :             has_gnu_linkonce_this_module = true;
     357                 :             :           }
     358                 :             :       }
     359                 :             :   }
     360                 :             : 
     361                 :             :   /* Examine the dynamic section.  */
     362         [ +  + ]:        1180 :   if (has_dynamic)
     363                 :             :     {
     364                 :         504 :       Elf_Data *data = elf_getdata_rawchunk (elf, dyn_seg.p_offset,
     365                 :             :                                              dyn_seg.p_filesz,
     366                 :             :                                              ELF_T_DYN);
     367         [ +  + ]:         504 :       if (data != NULL)
     368                 :       10476 :         for (int dyn_idx = 0; ; ++dyn_idx)
     369                 :       10476 :           {
     370                 :       10956 :             GElf_Dyn dyn_storage;
     371                 :       10956 :             GElf_Dyn *dyn = gelf_getdyn (data, dyn_idx, &dyn_storage);
     372         [ +  + ]:       10956 :             if (dyn == NULL)
     373                 :             :               break;
     374         [ -  + ]:       10852 :             if (verbose > 2)
     375                 :           0 :               fprintf (stderr, "debug: dynamic entry %d"
     376                 :             :                        " with tag %llu found\n",
     377                 :           0 :                        dyn_idx, (unsigned long long int) dyn->d_tag);
     378         [ +  + ]:       10852 :             if (dyn->d_tag == DT_SONAME)
     379                 :          32 :               has_soname = true;
     380   [ +  +  +  - ]:       10852 :             if (dyn->d_tag == DT_FLAGS_1 && (dyn->d_un.d_val & DF_1_PIE))
     381                 :          64 :               has_pie_flag = true;
     382         [ +  + ]:       10852 :             if (dyn->d_tag == DT_DEBUG)
     383                 :         144 :               has_dt_debug = true;
     384         [ +  + ]:       10852 :             if (dyn->d_tag == DT_NULL)
     385                 :             :               break;
     386                 :             :           }
     387                 :             :     }
     388                 :             : 
     389         [ +  - ]:        1180 :   if (verbose > 0)
     390                 :             :     {
     391                 :           0 :       fprintf (stderr, "info: %s: ELF type: %s (0x%x)\n", current_path,
     392                 :             :                elf_type_string (elf_type), elf_type);
     393         [ #  # ]:           0 :       if (has_program_load)
     394                 :           0 :         fprintf (stderr, "info: %s: PT_LOAD found\n", current_path);
     395         [ #  # ]:           0 :       if (has_sections)
     396                 :           0 :         fprintf (stderr, "info: %s: has sections\n", current_path);
     397         [ #  # ]:           0 :       if (has_bits_alloc)
     398                 :           0 :         fprintf (stderr, "info: %s: allocated (real) section found\n",
     399                 :             :                  current_path);
     400         [ #  # ]:           0 :       if (has_program_interpreter)
     401                 :           0 :         fprintf (stderr, "info: %s: program interpreter found\n",
     402                 :             :                  current_path);
     403         [ #  # ]:           0 :       if (has_dynamic)
     404                 :           0 :         fprintf (stderr, "info: %s: dynamic segment found\n", current_path);
     405         [ #  # ]:           0 :       if (has_soname)
     406                 :           0 :         fprintf (stderr, "info: %s: soname found\n", current_path);
     407         [ #  # ]:           0 :       if (has_pie_flag)
     408                 :           0 :         fprintf (stderr, "info: %s: DF_1_PIE flag found\n", current_path);
     409         [ #  # ]:           0 :       if (has_dt_debug)
     410                 :           0 :         fprintf (stderr, "info: %s: DT_DEBUG found\n", current_path);
     411         [ #  # ]:           0 :       if (has_symtab)
     412                 :           0 :         fprintf (stderr, "info: %s: symbol table found\n", current_path);
     413         [ #  # ]:           0 :       if (has_debug_sections)
     414                 :           0 :         fprintf (stderr, "info: %s: .debug_* section found\n", current_path);
     415         [ #  # ]:           0 :       if (has_modinfo)
     416                 :           0 :         fprintf (stderr, "info: %s: .modinfo section found\n", current_path);
     417         [ #  # ]:           0 :       if (has_gnu_linkonce_this_module)
     418                 :           0 :         fprintf (stderr,
     419                 :             :                  "info: %s: .gnu.linkonce.this_module section found\n",
     420                 :             :                  current_path);
     421                 :             :     }
     422                 :             : 
     423                 :             :   return true;
     424                 :             : }
     425                 :             : 
     426                 :             : static bool
     427                 :        1200 : is_elf (void)
     428                 :             : {
     429                 :        1200 :   return elf_kind (elf) != ELF_K_NONE;
     430                 :             : }
     431                 :             : 
     432                 :             : static bool
     433                 :        1200 : is_elf_file (void)
     434                 :             : {
     435                 :        1200 :   return elf_kind (elf) == ELF_K_ELF;
     436                 :             : }
     437                 :             : 
     438                 :             : static bool
     439                 :        1200 : is_elf_archive (void)
     440                 :             : {
     441                 :        1200 :   return elf_kind (elf) == ELF_K_AR;
     442                 :             : }
     443                 :             : 
     444                 :             : static bool
     445                 :        1200 : is_core (void)
     446                 :             : {
     447   [ +  +  +  + ]:        1200 :   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.)  */
     454                 :             : static bool
     455                 :        5628 : is_loadable (void)
     456                 :             : {
     457                 :        5628 :   return elf_kind (elf) == ELF_K_ELF
     458         [ +  + ]:        5548 :     && (elf_type == ET_EXEC || elf_type == ET_DYN)
     459         [ +  - ]:        3164 :     && has_program_load
     460   [ +  +  +  +  :        8792 :     && (!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).  */
     465                 :             : static bool
     466                 :        1200 : is_unstripped (void)
     467                 :             : {
     468                 :        1200 :   return elf_kind (elf) != ELF_K_NONE
     469         [ +  + ]:        1200 :     && (elf_type == ET_REL || elf_type == ET_EXEC || elf_type == ET_DYN)
     470   [ +  -  +  +  :        2180 :     && (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.  */
     477                 :             : static bool
     478                 :        1200 : is_debug_only (void)
     479                 :             : {
     480                 :        1200 :   return elf_kind (elf) != ELF_K_NONE
     481         [ +  + ]:        1200 :     && (elf_type == ET_REL || elf_type == ET_EXEC || elf_type == ET_DYN)
     482   [ +  +  +  + ]:         980 :     && (has_debug_sections || has_symtab)
     483   [ +  -  +  + ]:        2060 :     && !has_bits_alloc;
     484                 :             : }
     485                 :             : 
     486                 :             : static bool
     487                 :        1616 : is_shared (void)
     488                 :             : {
     489         [ +  + ]:        1616 :   if (!is_loadable ())
     490                 :             :     return false;
     491                 :             : 
     492                 :             :   /* The ELF type is very clear: this is an executable.  */
     493         [ +  + ]:         832 :   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         [ +  - ]:         632 :   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         [ +  + ]:         632 :   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         [ +  + ]:         504 :   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         [ +  + ]:         440 :   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         [ -  + ]:         320 :   if (has_dt_debug)
     527                 :           0 :     return false;
     528                 :             : 
     529                 :             :   return true;
     530                 :             : }
     531                 :             : 
     532                 :             : static bool
     533                 :        1200 : is_executable (void)
     534                 :             : {
     535         [ +  + ]:        1200 :   if (!is_loadable ())
     536                 :             :     return false;
     537                 :             : 
     538                 :             :   /* A loadable object which is not a shared object is treated as an
     539                 :             :      executable.  */
     540                 :         416 :   return !is_shared ();
     541                 :             : }
     542                 :             : 
     543                 :             : /* Like is_executable, but the object can also be a shared library at
     544                 :             :    the same time.  */
     545                 :             : static bool
     546                 :        1200 : is_program (void)
     547                 :             : {
     548         [ +  + ]:        1200 :   if (!is_loadable ())
     549                 :             :     return false;
     550                 :             : 
     551                 :             :   /* The ELF type is very clear: this is an executable.  */
     552         [ +  + ]:         416 :   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         [ +  + ]:         316 :   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         [ +  + ]:         252 :   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                 :         192 :   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.  */
     583                 :             : static bool
     584                 :        1200 : is_library  (void)
     585                 :             : {
     586                 :             :   /* Only ET_DYN can be shared libraries.  */
     587         [ +  + ]:        1200 :   if (elf_type != ET_DYN)
     588                 :             :     return false;
     589                 :             : 
     590         [ +  + ]:         412 :   if (!is_loadable ())
     591                 :             :     return false;
     592                 :             : 
     593                 :             :   /* Without a PT_DYNAMIC segment the library cannot be loaded.  */
     594         [ +  - ]:         316 :   if (!has_dynamic)
     595                 :             :     return false;
     596                 :             : 
     597                 :             :   /* This really is a (PIE) executable.  See is_shared.  */
     598   [ +  +  +  + ]:         316 :   if (has_pie_flag || has_dt_debug)
     599                 :         124 :     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).  */
     608                 :             : static bool
     609                 :        1200 : is_linux_kernel_module (void)
     610                 :             : {
     611                 :        1200 :   return (elf_kind (elf) == ELF_K_ELF
     612         [ +  + ]:        1180 :           && elf_type == ET_REL
     613         [ +  + ]:         396 :           && has_modinfo
     614   [ +  +  -  + ]:        1360 :           && has_gnu_linkonce_this_module);
     615                 :             : }
     616                 :             : 
     617                 :             : enum classify_requirement { do_not_care, required, forbidden };
     618                 :             : 
     619                 :             : enum 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                 :             : 
     637                 :             : enum
     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                 :             : 
     652                 :             : static bool
     653                 :        1684 : classify_check_positive (int key)
     654                 :             : {
     655                 :        1684 :   return key >= classify_check_offset
     656                 :        1684 :     && key <= classify_check_offset + classify_check_last;
     657                 :             : }
     658                 :             : 
     659                 :             : static bool
     660                 :        1564 : classify_check_negative (int key)
     661                 :             : {
     662                 :        1564 :   return key >= classify_check_not_offset
     663                 :        1564 :     && key <= classify_check_not_offset + classify_check_last;
     664                 :             : }
     665                 :             : 
     666                 :             : /* Set by parse_opt.  */
     667                 :             : static enum classify_requirement requirements[classify_check_last + 1];
     668                 :             : static enum { no_stdin, do_stdin, do_stdin0 } flag_stdin;
     669                 :             : static enum { no_print, do_print, do_print0 } flag_print;
     670                 :             : static bool flag_print_matching = true;
     671                 :             : 
     672                 :             : static error_t
     673                 :        1684 : parse_opt (int key, char *arg __attribute__ ((unused)),
     674                 :             :            struct argp_state *state __attribute__ ((unused)))
     675                 :             : {
     676         [ +  + ]:        1684 :   if (classify_check_positive (key))
     677                 :         120 :     requirements[key - classify_check_offset] = required;
     678         [ +  + ]:        1564 :   else if (classify_check_negative (key))
     679                 :         148 :     requirements[key - classify_check_not_offset] = forbidden;
     680                 :             :   else
     681   [ -  -  -  -  :        1416 :     switch (key)
          -  -  -  +  -  
             -  -  -  + ]
     682                 :             :       {
     683                 :           0 :       case 'v':
     684                 :           0 :         ++verbose;
     685                 :           0 :         break;
     686                 :             : 
     687                 :           0 :       case 'q':
     688                 :           0 :         --verbose;
     689                 :           0 :         break;
     690                 :             : 
     691                 :           0 :       case 'z':
     692                 :           0 :         flag_compressed = true;
     693                 :           0 :         break;
     694                 :             : 
     695                 :           0 :       case 'f':
     696                 :           0 :         flag_only_regular_files = true;
     697                 :           0 :         break;
     698                 :             : 
     699                 :           0 :       case classify_flag_stdin:
     700                 :           0 :         flag_stdin = do_stdin;
     701                 :           0 :         break;
     702                 :             : 
     703                 :           0 :       case classify_flag_stdin0:
     704                 :           0 :         flag_stdin = do_stdin0;
     705                 :           0 :         break;
     706                 :             : 
     707                 :           0 :       case classify_flag_no_stdin:
     708                 :           0 :         flag_stdin = no_stdin;
     709                 :           0 :         break;
     710                 :             : 
     711                 :          76 :       case classify_flag_print:
     712                 :          76 :         flag_print = do_print;
     713                 :          76 :         break;
     714                 :             : 
     715                 :           0 :       case classify_flag_print0:
     716                 :           0 :         flag_print = do_print0;
     717                 :           0 :         break;
     718                 :             : 
     719                 :           0 :       case classify_flag_no_print:
     720                 :           0 :         flag_print = no_print;
     721                 :           0 :         break;
     722                 :             : 
     723                 :           0 :       case classify_flag_matching:
     724                 :           0 :         flag_print_matching = true;
     725                 :           0 :         break;
     726                 :             : 
     727                 :           0 :       case classify_flag_not_matching:
     728                 :           0 :         flag_print_matching = false;
     729                 :           0 :         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.  */
     740                 :             : static void
     741                 :        1200 : process_current_path (int *status)
     742                 :             : {
     743                 :        1200 :   bool checks_passed = true;
     744                 :             : 
     745   [ +  -  +  - ]:        1200 :   if (open_elf () && run_classify ())
     746                 :        1200 :     {
     747                 :        1200 :       bool checks[] =
     748                 :             :         {
     749                 :             :          [classify_elf] = is_elf (),
     750                 :             :          [classify_elf_file] = is_elf_file (),
     751                 :             :          [classify_elf_archive] = is_elf_archive (),
     752                 :        1200 :          [classify_core] = is_core (),
     753                 :        1200 :          [classify_unstripped] = is_unstripped (),
     754                 :        1200 :          [classify_executable] = is_executable (),
     755                 :        1200 :          [classify_program] = is_program (),
     756                 :        1200 :          [classify_shared] = is_shared (),
     757                 :        1200 :          [classify_library] = is_library (),
     758                 :        1200 :          [classify_linux_kernel_module] = is_linux_kernel_module (),
     759                 :        1200 :          [classify_debug_only] = is_debug_only (),
     760                 :        1200 :          [classify_loadable] = is_loadable (),
     761                 :             :         };
     762                 :             : 
     763         [ -  + ]:        1200 :       if (verbose > 1)
     764                 :             :         {
     765         [ #  # ]:           0 :           if (checks[classify_elf])
     766                 :           0 :             fprintf (stderr, "debug: %s: elf\n", current_path);
     767         [ #  # ]:           0 :           if (checks[classify_elf_file])
     768                 :           0 :             fprintf (stderr, "debug: %s: elf_file\n", current_path);
     769         [ #  # ]:           0 :           if (checks[classify_elf_archive])
     770                 :           0 :             fprintf (stderr, "debug: %s: elf_archive\n", current_path);
     771         [ #  # ]:           0 :           if (checks[classify_core])
     772                 :           0 :             fprintf (stderr, "debug: %s: core\n", current_path);
     773         [ #  # ]:           0 :           if (checks[classify_unstripped])
     774                 :           0 :             fprintf (stderr, "debug: %s: unstripped\n", current_path);
     775         [ #  # ]:           0 :           if (checks[classify_executable])
     776                 :           0 :             fprintf (stderr, "debug: %s: executable\n", current_path);
     777         [ #  # ]:           0 :           if (checks[classify_program])
     778                 :           0 :             fprintf (stderr, "debug: %s: program\n", current_path);
     779         [ #  # ]:           0 :           if (checks[classify_shared])
     780                 :           0 :             fprintf (stderr, "debug: %s: shared\n", current_path);
     781         [ #  # ]:           0 :           if (checks[classify_library])
     782                 :           0 :             fprintf (stderr, "debug: %s: library\n", current_path);
     783         [ #  # ]:           0 :           if (checks[classify_linux_kernel_module])
     784                 :           0 :             fprintf (stderr, "debug: %s: linux kernel module\n", current_path);
     785         [ #  # ]:           0 :           if (checks[classify_debug_only])
     786                 :           0 :             fprintf (stderr, "debug: %s: debug-only\n", current_path);
     787         [ #  # ]:           0 :           if (checks[classify_loadable])
     788                 :           0 :             fprintf (stderr, "debug: %s: loadable\n", current_path);
     789                 :             :         }
     790                 :             : 
     791                 :        1200 :       for (enum classify_check check = 0;
     792         [ +  + ]:       15600 :            check <= classify_check_last; ++check)
     793      [ +  +  + ]:       14400 :         switch (requirements[check])
     794                 :             :           {
     795                 :        1712 :           case required:
     796         [ +  - ]:        1712 :             if (!checks[check])
     797                 :       14400 :               checks_passed = false;
     798                 :             :             break;
     799                 :         688 :           case forbidden:
     800         [ +  - ]:         688 :             if (checks[check])
     801                 :       14400 :               checks_passed = false;
     802                 :             :             break;
     803                 :             :           case do_not_care:
     804                 :             :             break;
     805                 :             :           }
     806                 :             :     }
     807         [ #  # ]:           0 :   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         [ #  # ]:           0 :            check <= classify_check_last; ++check)
     813         [ #  # ]:           0 :         if (requirements[check] == required)
     814                 :           0 :           checks_passed = false;
     815                 :             :     }
     816                 :             : 
     817                 :        1200 :   close_elf ();
     818                 :             : 
     819   [ +  -  +  - ]:        1200 :   switch (flag_print)
     820                 :             :     {
     821                 :         540 :     case do_print:
     822         [ +  - ]:         540 :       if (checks_passed == flag_print_matching)
     823                 :         540 :         puts (current_path);
     824                 :             :       break;
     825                 :           0 :     case do_print0:
     826         [ #  # ]:           0 :       if (checks_passed == flag_print_matching)
     827         [ #  # ]:           0 :         if (fwrite (current_path, strlen (current_path) + 1, 1, stdout) < 1)
     828                 :           0 :           issue (errno, N_("writing to standard output"));
     829                 :             :       break;
     830                 :         660 :     case no_print:
     831         [ -  + ]:         660 :       if (!checks_passed)
     832                 :           0 :         *status = 1;
     833                 :             :       break;
     834                 :             :     }
     835                 :        1200 : }
     836                 :             : 
     837                 :             : /* Called to process standard input if flag_stdin is not no_stdin.  */
     838                 :             : static void
     839                 :           0 : process_stdin (int *status)
     840                 :             : {
     841                 :           0 :   char delim;
     842         [ #  # ]:           0 :   if (flag_stdin == do_stdin0)
     843                 :             :     delim = '\0';
     844                 :             :   else
     845                 :           0 :     delim = '\n';
     846                 :             : 
     847                 :           0 :   char *buffer = NULL;
     848                 :           0 :   size_t buffer_size = 0;
     849                 :           0 :   while (true)
     850                 :           0 :     {
     851                 :           0 :       ssize_t ret = getdelim (&buffer, &buffer_size, delim, stdin);
     852         [ #  # ]:           0 :       if (ferror (stdin))
     853                 :             :         {
     854                 :           0 :           current_path = NULL;
     855                 :           0 :           issue (errno, N_("reading from standard input"));
     856                 :           0 :           break;
     857                 :             :         }
     858         [ #  # ]:           0 :       if (feof (stdin))
     859                 :             :         break;
     860         [ #  # ]:           0 :       if (ret < 0)
     861                 :           0 :         abort ();           /* Cannot happen due to error checks above.  */
     862   [ #  #  #  # ]:           0 :       if (delim != '\0' && ret > 0 && buffer[ret - 1] == '\n')
     863                 :           0 :         buffer[ret - 1] = '\0';
     864                 :           0 :       current_path = buffer;
     865                 :           0 :       process_current_path (status);
     866                 :             :     }
     867                 :             : 
     868                 :           0 :   free (buffer);
     869                 :           0 : }
     870                 :             : 
     871                 :             : int
     872                 :         268 : main (int argc, char **argv)
     873                 :             : {
     874                 :         268 :   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 \
     891                 :             : and 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, \
     945                 :             : separated by newlines"), 2 },
     946                 :             :       { "stdin0", classify_flag_stdin0, NULL, 0,
     947                 :             :         N_("Also read file names to process from standard input, \
     948                 :             : separated 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                 :         268 :   const struct argp argp =
     976                 :             :     {
     977                 :             :       .options = options,
     978                 :             :       .parser = parse_opt,
     979                 :             :       .args_doc = N_("FILE..."),
     980                 :             :       .doc = N_("\
     981                 :             : Determine the type of an ELF file.\
     982                 :             : \n\n\
     983                 :             : All of the classification options must apply at the same time to a \
     984                 :             : particular file.  Classification options can be negated using a \
     985                 :             : \"--not-\" prefix.\
     986                 :             : \n\n\
     987                 :             : Since modern ELF does not clearly distinguish between programs and \
     988                 :             : dynamic shared objects, you should normally use either --executable or \
     989                 :             : --shared to identify the primary purpose of a file.  \
     990                 :             : Only one of the --shared and --executable checks can pass for a file.\
     991                 :             : \n\n\
     992                 :             : If you want to know whether an ELF object might a program or a \
     993                 :             : shared library (but could be both), then use --program or --library. \
     994                 :             : Some ELF files will classify as both a program and a library.\
     995                 :             : \n\n\
     996                 :             : If you just want to know whether an ELF file is loadable (as program \
     997                 :             : or library) use --loadable.  Note that files that only contain \
     998                 :             : (separate) debug information (--debug-only) are never --loadable (even \
     999                 :             : though they might contain program headers).  Linux kernel modules are \
    1000                 :             : also not --loadable (in the normal sense).\
    1001                 :             : \n\n\
    1002                 :             : Without any of the --print options, the program exits with status 0 \
    1003                 :             : if the requested checks pass for all input files, with 1 if a check \
    1004                 :             : fails for any file, and 2 if there is an environmental issue (such \
    1005                 :             : as a file read error or a memory allocation error).\
    1006                 :             : \n\n\
    1007                 :             : When printing file names, the program exits with status 0 even if \
    1008                 :             : no file names are printed, and exits with status 2 if there is an \
    1009                 :             : environmental issue.\
    1010                 :             : \n\n\
    1011                 :             : On usage error (e.g. a bad option was given), the program exits with \
    1012                 :             : a status code larger than 2.\
    1013                 :             : \n\n\
    1014                 :             : The --quiet or -q option suppresses some error warning output, but \
    1015                 :             : doesn'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                 :         268 :   requirements[classify_elf] = required;
    1022                 :             : 
    1023                 :         268 :   int remaining;
    1024         [ -  + ]:         268 :   if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
    1025                 :             :     return 2;
    1026                 :             : 
    1027                 :         268 :   elf_version (EV_CURRENT);
    1028                 :             : 
    1029                 :         268 :   int status = 0;
    1030                 :             : 
    1031         [ +  + ]:        1468 :   for (int i = remaining; i < argc; ++i)
    1032                 :             :     {
    1033                 :        1200 :       current_path = argv[i];
    1034                 :        1200 :       process_current_path (&status);
    1035                 :             :     }
    1036                 :             : 
    1037         [ -  + ]:         268 :   if (flag_stdin != no_stdin)
    1038                 :           0 :     process_stdin (&status);
    1039                 :             : 
    1040         [ -  + ]:         268 :   if (issue_found)
    1041                 :             :     return 2;
    1042                 :             : 
    1043                 :         268 :   return status;
    1044                 :             : }
        

Generated by: LCOV version 2.0-1