LCOV - code coverage report
Current view: top level - libpkg - pkg_elf.c (source / functions) Hit Total Coverage
Test: rapport Lines: 281 614 45.8 %
Date: 2021-12-10 16:22:55 Functions: 11 15 73.3 %
Branches: 146 453 32.2 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2011-2012 Baptiste Daroussin <bapt@FreeBSD.org>
       3                 :            :  * Copyright (c) 2012-2013 Matthew Seaman <matthew@FreeBSD.org>
       4                 :            :  * All rights reserved.
       5                 :            :  * 
       6                 :            :  * Redistribution and use in source and binary forms, with or without
       7                 :            :  * modification, are permitted provided that the following conditions
       8                 :            :  * are met:
       9                 :            :  * 1. Redistributions of source code must retain the above copyright
      10                 :            :  *    notice, this list of conditions and the following disclaimer
      11                 :            :  *    in this position and unchanged.
      12                 :            :  * 2. Redistributions in binary form must reproduce the above copyright
      13                 :            :  *    notice, this list of conditions and the following disclaimer in the
      14                 :            :  *    documentation and/or other materials provided with the distribution.
      15                 :            :  * 
      16                 :            :  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
      17                 :            :  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
      18                 :            :  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
      19                 :            :  * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
      20                 :            :  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
      21                 :            :  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      22                 :            :  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      23                 :            :  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      24                 :            :  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
      25                 :            :  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      26                 :            :  */
      27                 :            : 
      28                 :            : #ifdef HAVE_CONFIG_H
      29                 :            : #include "pkg_config.h"
      30                 :            : #endif
      31                 :            : 
      32                 :            : #ifdef HAVE_SYS_ENDIAN_H
      33                 :            : #include <sys/endian.h>
      34                 :            : #elif HAVE_ENDIAN_H
      35                 :            : #include <endian.h>
      36                 :            : #elif HAVE_MACHINE_ENDIAN_H
      37                 :            : #include <machine/endian.h>
      38                 :            : #endif
      39                 :            : #include <sys/types.h>
      40                 :            : #if defined(HAVE_SYS_ELF_COMMON_H) && !defined(__DragonFly__)
      41                 :            : #include <sys/elf_common.h>
      42                 :            : #endif
      43                 :            : #include <sys/stat.h>
      44                 :            : 
      45                 :            : #include <assert.h>
      46                 :            : #include <ctype.h>
      47                 :            : #include <dlfcn.h>
      48                 :            : #include <fcntl.h>
      49                 :            : #include <gelf.h>
      50                 :            : #include <libgen.h>
      51                 :            : #if defined(HAVE_LINK_H) && !defined(__DragonFly__) && defined(HAVE_LIBELF)
      52                 :            : #include <link.h>
      53                 :            : #endif
      54                 :            : #include <paths.h>
      55                 :            : #include <stdbool.h>
      56                 :            : #include <string.h>
      57                 :            : #include <unistd.h>
      58                 :            : #ifdef HAVE_LIBELF
      59                 :            : #include <libelf.h>
      60                 :            : #endif
      61                 :            : 
      62                 :            : #include <bsd_compat.h>
      63                 :            : 
      64                 :            : #include "pkg.h"
      65                 :            : #include "private/pkg.h"
      66                 :            : #include "private/event.h"
      67                 :            : #include "private/elf_tables.h"
      68                 :            : #include "private/ldconfig.h"
      69                 :            : 
      70                 :            : #ifndef NT_ABI_TAG
      71                 :            : #define NT_ABI_TAG 1
      72                 :            : #endif
      73                 :            : 
      74                 :            : #define _PATH_UNAME "/usr/bin/uname"
      75                 :            : 
      76                 :            : /* FFR: when we support installing a 32bit package on a 64bit host */
      77                 :            : #define _PATH_ELF32_HINTS       "/var/run/ld-elf32.so.hints"
      78                 :            : 
      79                 :            : #ifndef roundup2
      80                 :            : #define roundup2(x, y)  (((x)+((y)-1))&(~((y)-1))) /* if y is powers of two */
      81                 :            : #endif
      82                 :            : 
      83                 :            : static const char * elf_corres_to_string(const struct _elf_corres* m, int e);
      84                 :            : static int elf_string_to_corres(const struct _elf_corres* m, const char *s);
      85                 :            : 
      86                 :            : static int
      87                 :         64 : filter_system_shlibs(const char *name, char *path, size_t pathlen)
      88                 :            : {
      89                 :            :         const char *shlib_path;
      90                 :            : 
      91                 :         64 :         shlib_path = shlib_list_find_by_name(name);
      92         [ +  - ]:         64 :         if (shlib_path == NULL) {
      93                 :            :                 /* dynamic linker could not resolve */
      94                 :          0 :                 return (EPKG_FATAL);
      95                 :            :         }
      96                 :            : 
      97         [ -  + ]:         64 :         if (pkg_object_bool(pkg_config_get("ALLOW_BASE_SHLIBS"))) {
      98         [ #  # ]:          0 :                 if (strstr(shlib_path, "/lib32/") != NULL)
      99                 :          0 :                         return (EPKG_END);
     100                 :          0 :         } else {
     101                 :            :                 /* match /lib, /lib32, /usr/lib and /usr/lib32 */
     102   [ +  +  -  + ]:         64 :                 if (strncmp(shlib_path, "/lib", 4) == 0 ||
     103                 :         16 :                     strncmp(shlib_path, "/usr/lib", 8) == 0)
     104                 :         48 :                         return (EPKG_END); /* ignore libs from base */
     105                 :            :         }
     106                 :            : 
     107         [ +  - ]:         16 :         if (path != NULL)
     108                 :          0 :                 strncpy(path, shlib_path, pathlen);
     109                 :            : 
     110                 :         16 :         return (EPKG_OK);
     111                 :         64 : }
     112                 :            : 
     113                 :            : /* ARGSUSED */
     114                 :            : static int
     115                 :         64 : add_shlibs_to_pkg(struct pkg *pkg, const char *fpath, const char *name,
     116                 :            :     bool is_shlib)
     117                 :            : {
     118                 :         64 :         struct pkg_file *file = NULL;
     119                 :            :         const char *filepath;
     120                 :            : 
     121      [ +  -  + ]:         64 :         switch(filter_system_shlibs(name, NULL, 0)) {
     122                 :            :         case EPKG_OK:           /* A non-system library */
     123                 :         16 :                 pkg_addshlib_required(pkg, name);
     124                 :         16 :                 return (EPKG_OK);
     125                 :            :         case EPKG_END:          /* A system library */
     126                 :         48 :                 return (EPKG_OK);
     127                 :            :         default:
     128                 :            :                 /* Ignore link resolution errors if we're analysing a
     129                 :            :                    shared library. */
     130         [ #  # ]:          0 :                 if (is_shlib)
     131                 :          0 :                         return (EPKG_OK);
     132                 :            : 
     133         [ #  # ]:          0 :                 while (pkg_files(pkg, &file) == EPKG_OK) {
     134                 :          0 :                         filepath = file->path;
     135   [ #  #  #  # ]:          0 :                         if (strlen(filepath) >= strlen(name) &&
     136                 :          0 :                             strcmp(&filepath[strlen(filepath) - strlen(name)], name) == 0) {
     137                 :          0 :                                 pkg_addshlib_required(pkg, name);
     138                 :          0 :                                 return (EPKG_OK);
     139                 :            :                         }
     140                 :            :                 }
     141                 :            : 
     142                 :          0 :                 pkg_emit_notice("(%s-%s) %s - required shared library %s not "
     143                 :          0 :                     "found", pkg->name, pkg->version, fpath, name);
     144                 :            : 
     145                 :          0 :                 return (EPKG_FATAL);
     146                 :            :         }
     147                 :         64 : }
     148                 :            : 
     149                 :            : static bool
     150                 :         48 : shlib_valid_abi(const char *fpath, GElf_Ehdr *hdr, const char *abi)
     151                 :            : {
     152                 :            :         int semicolon;
     153                 :            :         const char *p, *t;
     154                 :            :         char arch[64], wordsize[64];
     155                 :            :         int wclass;
     156                 :            :         const char *shlib_arch;
     157                 :            : 
     158                 :            :         /*
     159                 :            :          * ABI string is in format:
     160                 :            :          * <osname>:<osversion>:<arch>:<wordsize>[.other]
     161                 :            :          * We need here arch and wordsize only
     162                 :            :          */
     163                 :         48 :         arch[0] = '\0';
     164                 :         48 :         wordsize[0] = '\0';
     165                 :         48 :         p = abi;
     166   [ -  +  +  - ]:         96 :         for(semicolon = 0; semicolon < 3 && p != NULL; semicolon ++, p ++) {
     167                 :         96 :                 p = strchr(p, ':');
     168         [ -  + ]:         96 :                 if (p != NULL) {
     169      [ +  +  - ]:         96 :                         switch(semicolon) {
     170                 :            :                         case 1:
     171                 :            :                                 /* We have arch here */
     172                 :         48 :                                 t = strchr(p + 1, ':');
     173                 :            :                                 /* Abi line is likely invalid */
     174         [ -  + ]:         48 :                                 if (t == NULL)
     175                 :         48 :                                         return (true);
     176         [ #  # ]:          0 :                                 strlcpy(arch, p + 1, MIN((long)sizeof(arch), t - p));
     177                 :          0 :                                 break;
     178                 :            :                         case 2:
     179                 :          0 :                                 t = strchr(p + 1, ':');
     180         [ #  # ]:          0 :                                 if (t == NULL)
     181                 :          0 :                                         strlcpy(wordsize, p + 1, sizeof(wordsize));
     182                 :            :                                 else
     183         [ #  # ]:          0 :                                         strlcpy(wordsize, p + 1, MIN((long)sizeof(wordsize), t - p));
     184                 :          0 :                                 break;
     185                 :            :                         }
     186                 :         48 :                 }
     187                 :         48 :         }
     188                 :            :         /* Invalid ABI line */
     189   [ #  #  #  # ]:          0 :         if (arch[0] == '\0' || wordsize[0] == '\0')
     190                 :          0 :                 return (true);
     191                 :            : 
     192                 :          0 :         shlib_arch = elf_corres_to_string(mach_corres, (int)hdr->e_machine);
     193         [ #  # ]:          0 :         if (shlib_arch == NULL)
     194                 :          0 :                 return (true);
     195                 :            : 
     196                 :          0 :         wclass = elf_string_to_corres(wordsize_corres, wordsize);
     197         [ #  # ]:          0 :         if (wclass == -1)
     198                 :          0 :                 return (true);
     199                 :            : 
     200                 :            : 
     201                 :            :         /*
     202                 :            :          * Compare wordsize first as the arch for amd64/i386 is an abmiguous
     203                 :            :          * 'x86'
     204                 :            :          */
     205         [ #  # ]:          0 :         if ((int)hdr->e_ident[EI_CLASS] != wclass) {
     206                 :          0 :                 pkg_debug(1, "not valid elf class for shlib: %s: %s",
     207                 :          0 :                     elf_corres_to_string(wordsize_corres,
     208                 :          0 :                     (int)hdr->e_ident[EI_CLASS]),
     209                 :          0 :                     fpath);
     210                 :          0 :                 return (false);
     211                 :            :         }
     212                 :            : 
     213         [ #  # ]:          0 :         if (strcmp(shlib_arch, arch) != 0) {
     214                 :          0 :                 pkg_debug(1, "not valid abi for shlib: %s: %s", shlib_arch,
     215                 :          0 :                     fpath);
     216                 :          0 :                 return (false);
     217                 :            :         }
     218                 :            : 
     219                 :          0 :         return (true);
     220                 :         48 : }
     221                 :            : 
     222                 :            : #ifdef __FreeBSD__
     223                 :            : static bool
     224                 :          0 : is_old_freebsd_armheader(const GElf_Ehdr *e)
     225                 :            : {
     226                 :            :         GElf_Word eabi;
     227                 :            : 
     228                 :            :         /*
     229                 :            :          * Old FreeBSD arm EABI binaries were created with zeroes in [EI_OSABI].
     230                 :            :          * Attempt to identify them by the little bit of valid info that is
     231                 :            :          * present:  32-bit ARM with EABI version 4 or 5 in the flags.  OABI
     232                 :            :          * binaries (prior to freebsd 10) have the correct [EI_OSABI] value.
     233                 :            :          */
     234   [ #  #  #  # ]:          0 :         if (e->e_machine == EM_ARM && e->e_ident[EI_CLASS] == ELFCLASS32) {
     235                 :          0 :                 eabi = e->e_flags & 0xff000000;
     236   [ #  #  #  # ]:          0 :                 if (eabi == 0x04000000 || eabi == 0x05000000)
     237                 :          0 :                         return (true);
     238                 :          0 :         }
     239                 :          0 :         return (false);
     240                 :          0 : }
     241                 :            : #endif
     242                 :            : 
     243                 :            : #ifndef HAVE_ELF_NOTE
     244                 :            : typedef Elf32_Nhdr Elf_Note;
     245                 :            : #endif
     246                 :            : 
     247                 :            : static int
     248                 :        969 : analyse_elf(struct pkg *pkg, const char *fpath)
     249                 :            : {
     250                 :        969 :         Elf *e = NULL;
     251                 :            :         GElf_Ehdr elfhdr;
     252                 :        969 :         Elf_Scn *scn = NULL;
     253                 :        969 :         Elf_Scn *note = NULL;
     254                 :        969 :         Elf_Scn *dynamic = NULL;
     255                 :            :         GElf_Shdr shdr;
     256                 :            :         Elf_Data *data;
     257                 :            :         GElf_Dyn *dyn, dyn_mem;
     258                 :            :         struct stat sb;
     259                 :        969 :         int ret = EPKG_OK;
     260                 :            : 
     261                 :        969 :         size_t numdyn = 0;
     262                 :        969 :         size_t sh_link = 0;
     263                 :            :         size_t dynidx;
     264                 :            :         const char *myarch;
     265                 :            :         const char *shlib;
     266                 :        969 :         char *rpath = NULL;
     267                 :            : 
     268                 :        969 :         bool is_shlib = false;
     269                 :            : 
     270                 :        969 :         myarch = pkg_object_string(pkg_config_get("ABI"));
     271                 :            : 
     272                 :            :         int fd;
     273                 :            : 
     274                 :        969 :         pkg_debug(1, "analysing elf %s", fpath);
     275         [ +  - ]:        969 :         if (lstat(fpath, &sb) != 0)
     276                 :          0 :                 pkg_emit_errno("fstat() failed for", fpath);
     277                 :            :         /* ignore empty files and non regular files */
     278   [ +  +  +  + ]:        969 :         if (sb.st_size == 0 || !S_ISREG(sb.st_mode))
     279                 :        689 :                 return (EPKG_END); /* Empty file or sym-link: no results */
     280                 :            : 
     281         [ -  + ]:        280 :         if ((fd = open(fpath, O_RDONLY, 0)) < 0) {
     282                 :          0 :                 return (EPKG_FATAL);
     283                 :            :         }
     284                 :            : 
     285         [ -  + ]:        280 :         if ((e = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
     286                 :          0 :                 ret = EPKG_FATAL;
     287                 :          0 :                 pkg_debug(1, "elf_begin() for %s failed: %s", fpath,
     288                 :          0 :                     elf_errmsg(-1));
     289                 :          0 :                 goto cleanup;
     290                 :            :         }
     291                 :            : 
     292         [ +  + ]:        280 :         if (elf_kind(e) != ELF_K_ELF) {
     293                 :            :                 /* Not an elf file: no results */
     294                 :        232 :                 ret = EPKG_END;
     295                 :        232 :                 pkg_debug(1, "not an elf");
     296                 :        232 :                 goto cleanup;
     297                 :            :         }
     298                 :            : 
     299         [ +  - ]:         48 :         if (ctx.developer_mode)
     300                 :          0 :                 pkg->flags |= PKG_CONTAINS_ELF_OBJECTS;
     301                 :            : 
     302         [ +  - ]:         48 :         if (gelf_getehdr(e, &elfhdr) == NULL) {
     303                 :          0 :                 ret = EPKG_FATAL;
     304                 :          0 :                 pkg_emit_error("getehdr() failed: %s.", elf_errmsg(-1));
     305                 :          0 :                 goto cleanup;
     306                 :            :         }
     307                 :            : 
     308   [ -  +  #  #  :         48 :         if (elfhdr.e_type != ET_DYN && elfhdr.e_type != ET_EXEC &&
                   #  # ]
     309                 :          0 :             elfhdr.e_type != ET_REL) {
     310                 :          0 :                 pkg_debug(1, "not an elf");
     311                 :          0 :                 ret = EPKG_END;
     312                 :          0 :                 goto cleanup;
     313                 :            :         }
     314                 :            : 
     315                 :            :         /* Elf file has sections header */
     316         [ -  + ]:        864 :         while ((scn = elf_nextscn(e, scn)) != NULL) {
     317         [ +  - ]:        864 :                 if (gelf_getshdr(scn, &shdr) != &shdr) {
     318                 :          0 :                         ret = EPKG_FATAL;
     319                 :          0 :                         pkg_emit_error("getshdr() for %s failed: %s", fpath,
     320                 :          0 :                                         elf_errmsg(-1));
     321                 :          0 :                         goto cleanup;
     322                 :            :                 }
     323      [ +  +  + ]:        864 :                 switch (shdr.sh_type) {
     324                 :            :                 case SHT_NOTE:
     325         [ +  - ]:         48 :                         if ((data = elf_getdata(scn, NULL)) == NULL) {
     326                 :          0 :                                 ret = EPKG_END; /* Some error occurred, ignore this file */
     327                 :          0 :                                 goto cleanup;
     328                 :            :                         }
     329         [ +  - ]:         48 :                         else if (data->d_buf != NULL) {
     330                 :         48 :                                 Elf_Note *en = (Elf_Note *)data->d_buf;
     331         [ -  + ]:         48 :                                 if (en->n_type == NT_ABI_TAG)
     332                 :         48 :                                         note = scn;
     333                 :         48 :                         }
     334                 :         48 :                         break;
     335                 :            :                 case SHT_DYNAMIC:
     336                 :         48 :                         dynamic = scn;
     337                 :         48 :                         sh_link = shdr.sh_link;
     338         [ +  - ]:         48 :                         if (shdr.sh_entsize == 0) {
     339                 :          0 :                                 ret = EPKG_END;
     340                 :          0 :                                 goto cleanup;
     341                 :            :                         }
     342                 :         48 :                         numdyn = shdr.sh_size / shdr.sh_entsize;
     343                 :         48 :                         break;
     344                 :            :                 }
     345                 :            : 
     346   [ +  -  +  + ]:        864 :                 if (note != NULL && dynamic != NULL)
     347                 :         48 :                         break;
     348                 :            :         }
     349                 :            : 
     350                 :            :         /*
     351                 :            :          * note == NULL usually means a shared object for use with dlopen(3)
     352                 :            :          * dynamic == NULL means not a dynamically linked elf
     353                 :            :          */
     354         [ +  - ]:         48 :         if (dynamic == NULL) {
     355                 :          0 :                 ret = EPKG_END;
     356                 :          0 :                 goto cleanup; /* not a dynamically linked elf: no results */
     357                 :            :         }
     358                 :            : 
     359         [ +  - ]:         48 :         if (!shlib_valid_abi(fpath, &elfhdr, myarch)) {
     360                 :          0 :                 ret = EPKG_END;
     361                 :          0 :                 goto cleanup; /* Invalid ABI */
     362                 :            :         }
     363                 :            : 
     364                 :            : #ifdef __FreeBSD__
     365   [ -  +  #  # ]:         48 :         if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_FREEBSD &&
     366                 :          0 :             !is_old_freebsd_armheader(&elfhdr)) {
     367                 :          0 :                 ret = EPKG_END;
     368                 :          0 :                 goto cleanup;
     369                 :            :         }
     370                 :            : #endif
     371                 :            : 
     372         [ +  - ]:         48 :         if ((data = elf_getdata(dynamic, NULL)) == NULL) {
     373                 :          0 :                 ret = EPKG_END; /* Some error occurred, ignore this file */
     374                 :          0 :                 goto cleanup;
     375                 :            :         }
     376                 :            : 
     377                 :            :         /* First, scan through the data from the .dynamic section to
     378                 :            :            find any RPATH or RUNPATH settings.  These are colon
     379                 :            :            separated paths to prepend to the ld.so search paths from
     380                 :            :            the ELF hints file.  These always seem to come right after
     381                 :            :            the NEEDED shared library entries.
     382                 :            : 
     383                 :            :            NEEDED entries should resolve to a filename for installed
     384                 :            :            executables, but need not resolve for installed shared
     385                 :            :            libraries -- additional info from the apps that link
     386                 :            :            against them would be required.  Shared libraries are
     387                 :            :            distinguished by a DT_SONAME tag */
     388                 :            : 
     389                 :         48 :         rpath_list_init();
     390         [ +  + ]:       1216 :         for (dynidx = 0; dynidx < numdyn; dynidx++) {
     391         [ +  - ]:       1168 :                 if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
     392                 :          0 :                         ret = EPKG_FATAL;
     393                 :          0 :                         pkg_emit_error("getdyn() failed for %s: %s", fpath,
     394                 :          0 :                             elf_errmsg(-1));
     395                 :          0 :                         goto cleanup;
     396                 :            :                 }
     397                 :            : 
     398         [ +  + ]:       1168 :                 if (dyn->d_tag == DT_SONAME) {
     399                 :         32 :                         is_shlib = true;
     400                 :            : 
     401                 :            :                         /* The file being scanned is a shared library
     402                 :            :                            *provided* by the package. Record this if
     403                 :            :                            appropriate */
     404                 :         32 :                         shlib = elf_strptr(e, sh_link, dyn->d_un.d_val);
     405   [ +  -  -  + ]:         32 :                         if (shlib != NULL && *shlib != '\0')
     406                 :         32 :                                 pkg_addshlib_provided(pkg, shlib);
     407                 :         32 :                 }
     408                 :            : 
     409   [ +  -  +  + ]:       1168 :                 if ((dyn->d_tag == DT_RPATH || dyn->d_tag == DT_RUNPATH) &&
     410                 :       1168 :                     rpath == NULL)
     411                 :         16 :                         rpath = elf_strptr(e, sh_link, dyn->d_un.d_val);
     412                 :       1168 :         }
     413         [ +  + ]:         48 :         if (rpath != NULL) {
     414                 :         16 :                 char *p = xstrdup(fpath);
     415                 :         16 :                 shlib_list_from_rpath(rpath, get_dirname(p));
     416                 :         16 :                 free(p);
     417                 :         16 :         }
     418                 :            : 
     419                 :            :         /* Now find all of the NEEDED shared libraries. */
     420                 :            : 
     421         [ +  + ]:       1216 :         for (dynidx = 0; dynidx < numdyn; dynidx++) {
     422         [ -  + ]:       1168 :                 if ((dyn = gelf_getdyn(data, dynidx, &dyn_mem)) == NULL) {
     423                 :          0 :                         ret = EPKG_FATAL;
     424                 :          0 :                         pkg_emit_error("getdyn() failed for %s: %s", fpath,
     425                 :          0 :                             elf_errmsg(-1));
     426                 :          0 :                         goto cleanup;
     427                 :            :                 }
     428                 :            : 
     429         [ +  + ]:       1168 :                 if (dyn->d_tag != DT_NEEDED)
     430                 :       1104 :                         continue;
     431                 :            : 
     432                 :         64 :                 shlib = elf_strptr(e, sh_link, dyn->d_un.d_val);
     433                 :            : 
     434                 :         64 :                 add_shlibs_to_pkg(pkg, fpath, shlib, is_shlib);
     435                 :        112 :         }
     436                 :            : 
     437                 :            : cleanup:
     438                 :        280 :         rpath_list_free();
     439                 :            : 
     440         [ -  + ]:        280 :         if (e != NULL)
     441                 :        280 :                 elf_end(e);
     442                 :        280 :         close(fd);
     443                 :            : 
     444                 :        280 :         return (ret);
     445                 :        969 : }
     446                 :            : 
     447                 :            : static int
     448                 :          0 : analyse_fpath(struct pkg *pkg, const char *fpath)
     449                 :            : {
     450                 :            :         const char *dot;
     451                 :            : 
     452                 :          0 :         dot = strrchr(fpath, '.');
     453                 :            : 
     454         [ #  # ]:          0 :         if (dot == NULL)        /* No extension */
     455                 :          0 :                 return (EPKG_OK);
     456                 :            : 
     457   [ #  #  #  # ]:          0 :         if (dot[1] == 'a' && dot[2] == '\0')
     458                 :          0 :                 pkg->flags |= PKG_CONTAINS_STATIC_LIBS;
     459                 :            : 
     460   [ #  #  #  #  :          0 :         if ((dot[1] == 'l' && dot[2] == 'a' && dot[3] == '\0'))
                   #  # ]
     461                 :          0 :                 pkg->flags |= PKG_CONTAINS_LA;
     462                 :            : 
     463                 :          0 :         return (EPKG_OK);
     464                 :          0 : }
     465                 :            : 
     466                 :            : int
     467                 :       1330 : pkg_analyse_files(struct pkgdb *db __unused, struct pkg *pkg, const char *stage)
     468                 :            : {
     469                 :       1330 :         struct pkg_file *file = NULL;
     470                 :       1330 :         int ret = EPKG_OK;
     471                 :            :         char fpath[MAXPATHLEN +1];
     472                 :            :         const char *lib;
     473                 :       1330 :         bool failures = false;
     474                 :            : 
     475         [ +  + ]:       1330 :         if (pkghash_count(pkg->shlibs_required) != 0) {
     476                 :          8 :                 pkghash_destroy(pkg->shlibs_required);
     477                 :          8 :                 pkg->shlibs_required = NULL;
     478                 :          8 :         }
     479                 :            : 
     480         [ +  + ]:       1330 :         if (pkghash_count(pkg->shlibs_provided) != 0) {
     481                 :         20 :                 pkghash_destroy(pkg->shlibs_provided);
     482                 :         20 :                 pkg->shlibs_provided = NULL;
     483                 :         20 :         }
     484                 :            : 
     485         [ +  - ]:       1330 :         if (elf_version(EV_CURRENT) == EV_NONE)
     486                 :          0 :                 return (EPKG_FATAL);
     487                 :            : 
     488                 :       1330 :         shlib_list_init();
     489                 :            : 
     490   [ +  +  +  - ]:       1330 :         if (stage != NULL && pkg_object_bool(pkg_config_get("ALLOW_BASE_SHLIBS"))) {
     491                 :            :                 /* Do not check the return */
     492                 :          0 :                 shlib_list_from_stage(stage);
     493                 :          0 :         }
     494                 :            : 
     495                 :       1330 :         ret = shlib_list_from_elf_hints(_PATH_ELF_HINTS);
     496         [ -  + ]:       1330 :         if (ret != EPKG_OK)
     497                 :          0 :                 goto cleanup;
     498                 :            : 
     499                 :            :         /* Assume no architecture dependence, for contradiction */
     500         [ +  - ]:       1330 :         if (ctx.developer_mode)
     501                 :          0 :                 pkg->flags &= ~(PKG_CONTAINS_ELF_OBJECTS |
     502                 :            :                                 PKG_CONTAINS_STATIC_LIBS |
     503                 :            :                                 PKG_CONTAINS_LA);
     504                 :            : 
     505         [ +  + ]:       2299 :         while (pkg_files(pkg, &file) == EPKG_OK) {
     506         [ +  + ]:        969 :                 if (stage != NULL)
     507                 :        178 :                         snprintf(fpath, sizeof(fpath), "%s/%s", stage, file->path);
     508                 :            :                 else
     509                 :        791 :                         strlcpy(fpath, file->path, sizeof(fpath));
     510                 :            : 
     511                 :        969 :                 ret = analyse_elf(pkg, fpath);
     512         [ +  - ]:        969 :                 if (ctx.developer_mode) {
     513   [ #  #  #  # ]:          0 :                         if (ret != EPKG_OK && ret != EPKG_END) {
     514                 :          0 :                                 failures = true;
     515                 :          0 :                                 continue;
     516                 :            :                         }
     517                 :          0 :                         analyse_fpath(pkg, fpath);
     518                 :          0 :                 }
     519                 :            :         }
     520                 :            : 
     521                 :            :         /*
     522                 :            :          * Do not depend on libraries that a package provides itself
     523                 :            :          */
     524                 :       1330 :         pkghash_it it = pkghash_iterator(pkg->shlibs_required);
     525         [ +  + ]:       1346 :         while (pkghash_next(&it)) {
     526         [ -  + ]:         16 :                 if (pkghash_get(pkg->shlibs_provided, it.key)) {
     527                 :          0 :                         pkg_debug(2, "remove %s from required shlibs as the "
     528                 :            :                             "package %s provides this library itself",
     529                 :          0 :                             it.key, pkg->name);
     530                 :          0 :                         pkghash_del(pkg->shlibs_required, it.key);
     531                 :          0 :                         continue;
     532                 :            :                 }
     533                 :         16 :                 file = NULL;
     534         [ +  + ]:         32 :                 while (pkg_files(pkg, &file) == EPKG_OK) {
     535   [ -  +  #  # ]:         16 :                         if ((lib = strstr(file->path, it.key)) != NULL &&
     536         [ #  # ]:          0 :                             strlen(lib) == strlen(it.key) && lib[-1] == '/') {
     537                 :          0 :                                 pkg_debug(2, "remove %s from required shlibs as "
     538                 :            :                                     "the package %s provides this file itself",
     539                 :          0 :                                     it.key, pkg->name);
     540                 :            : 
     541                 :          0 :                                 pkghash_del(pkg->shlibs_required, it.key);
     542                 :          0 :                                 break;
     543                 :            :                         }
     544                 :            :                 }
     545                 :            :         }
     546                 :            : 
     547                 :            :         /*
     548                 :            :          * if the package is not supposed to provide share libraries then
     549                 :            :          * drop the provided one
     550                 :            :          */
     551         [ +  - ]:       1330 :         if (pkg_kv_get(&pkg->annotations, "no_provide_shlib") != NULL) {
     552                 :          0 :                 pkghash_destroy(pkg->shlibs_provided);
     553                 :          0 :                 pkg->shlibs_provided = NULL;
     554                 :          0 :         }
     555                 :            : 
     556         [ -  + ]:       1330 :         if (failures)
     557                 :          0 :                 goto cleanup;
     558                 :            : 
     559                 :       1330 :         ret = EPKG_OK;
     560                 :            : 
     561                 :            : cleanup:
     562                 :       1330 :         shlib_list_free();
     563                 :            : 
     564                 :       1330 :         return (ret);
     565                 :       1330 : }
     566                 :            : 
     567                 :            : static const char *
     568                 :      13988 : elf_corres_to_string(const struct _elf_corres* m, int e)
     569                 :            : {
     570                 :      13988 :         int i = 0;
     571                 :            : 
     572         [ +  - ]:      27976 :         for (i = 0; m[i].string != NULL; i++)
     573         [ +  + ]:      27976 :                 if (m[i].elf_nb == e)
     574                 :      13988 :                         return (m[i].string);
     575                 :            : 
     576                 :          0 :         return ("unknown");
     577                 :      13988 : }
     578                 :            : 
     579                 :            : static int
     580                 :          0 : elf_string_to_corres(const struct _elf_corres* m, const char *s)
     581                 :            : {
     582                 :          0 :         int i = 0;
     583                 :            : 
     584         [ #  # ]:          0 :         for (i = 0; m[i].string != NULL; i++)
     585         [ #  # ]:          0 :                 if (strcmp(m[i].string, s) == 0)
     586                 :          0 :                         return (m[i].elf_nb);
     587                 :            : 
     588                 :          0 :         return (-1);
     589                 :          0 : }
     590                 :            : 
     591                 :            : static const char *
     592                 :          0 : aeabi_parse_arm_attributes(void *data, size_t length)
     593                 :            : {
     594                 :            :         uint32_t sect_len;
     595                 :          0 :         uint8_t *section = data;
     596                 :            : 
     597                 :            : #define MOVE(len) do {          \
     598                 :            :         assert(length >= (len)); \
     599                 :            :         section += (len);       \
     600                 :            :         length -= (len);        \
     601                 :            : } while (0)
     602                 :            : 
     603   [ #  #  #  # ]:          0 :         if (length == 0 || *section != 'A')
     604                 :          0 :                 return (NULL);
     605         [ #  # ]:          0 :         MOVE(1);
     606                 :            : 
     607                 :            :         /* Read the section length */
     608         [ #  # ]:          0 :         if (length < sizeof(sect_len))
     609                 :          0 :                 return (NULL);
     610                 :          0 :         memcpy(&sect_len, section, sizeof(sect_len));
     611                 :            : 
     612                 :            :         /*
     613                 :            :          * The section length should be no longer than the section it is within
     614                 :            :          */
     615         [ #  # ]:          0 :         if (sect_len > length)
     616                 :          0 :                 return (NULL);
     617                 :            : 
     618         [ #  # ]:          0 :         MOVE(sizeof(sect_len));
     619                 :            : 
     620                 :            :         /* Skip the vendor name */
     621         [ #  # ]:          0 :         while (length != 0) {
     622         [ #  # ]:          0 :                 if (*section == '\0')
     623                 :          0 :                         break;
     624         [ #  # ]:          0 :                 MOVE(1);
     625                 :            :         }
     626         [ #  # ]:          0 :         if (length == 0)
     627                 :          0 :                 return (NULL);
     628         [ #  # ]:          0 :         MOVE(1);
     629                 :            : 
     630         [ #  # ]:          0 :         while (length != 0) {
     631                 :            :                 uint32_t tag_length;
     632                 :            : 
     633      [ #  #  # ]:          0 :                 switch(*section) {
     634                 :            :                 case 1: /* Tag_File */
     635         [ #  # ]:          0 :                         MOVE(1);
     636         [ #  # ]:          0 :                         if (length < sizeof(tag_length))
     637                 :          0 :                                 return (NULL);
     638                 :          0 :                         memcpy(&tag_length, section, sizeof(tag_length));
     639                 :          0 :                         break;
     640                 :            :                 case 2: /* Tag_Section */
     641                 :            :                 case 3: /* Tag_Symbol */
     642                 :            :                 default:
     643                 :          0 :                         return (NULL);
     644                 :            :                 }
     645                 :            :                 /* At least space for the tag and size */
     646         [ #  # ]:          0 :                 if (tag_length <= 5)
     647                 :          0 :                         return (NULL);
     648                 :          0 :                 tag_length--;
     649                 :            :                 /* Check the tag fits */
     650         [ #  # ]:          0 :                 if (tag_length > length)
     651                 :          0 :                         return (NULL);
     652                 :            : 
     653                 :            : #define MOVE_TAG(len) do {              \
     654                 :            :         assert(tag_length >= (len)); \
     655                 :            :         MOVE(len);                      \
     656                 :            :         tag_length -= (len);            \
     657                 :            : } while(0)
     658                 :            : 
     659         [ #  # ]:          0 :                 MOVE(sizeof(tag_length));
     660                 :          0 :                 tag_length -= sizeof(tag_length);
     661                 :            : 
     662         [ #  # ]:          0 :                 while (tag_length != 0) {
     663                 :            :                         uint8_t tag;
     664                 :            : 
     665         [ #  # ]:          0 :                         assert(tag_length >= length);
     666                 :            : 
     667                 :          0 :                         tag = *section;
     668   [ #  #  #  # ]:          0 :                         MOVE_TAG(1);
     669                 :            : 
     670                 :            :                         /*
     671                 :            :                          * These tag values come from:
     672                 :            :                          * 
     673                 :            :                          * Addenda to, and Errata in, the ABI for the
     674                 :            :                          * ARM Architecture. Release 2.08, section 2.3.
     675                 :            :                          */
     676         [ #  # ]:          0 :                         if (tag == 6) { /* == Tag_CPU_arch */
     677                 :            :                                 uint8_t val;
     678                 :            : 
     679                 :          0 :                                 val = *section;
     680                 :            :                                 /*
     681                 :            :                                  * We don't support values that require
     682                 :            :                                  * more than one byte.
     683                 :            :                                  */
     684         [ #  # ]:          0 :                                 if (val & (1 << 7))
     685                 :          0 :                                         return (NULL);
     686                 :            : 
     687                 :            :                                 /* We have an ARMv4 or ARMv5 */
     688         [ #  # ]:          0 :                                 if (val <= 5)
     689                 :          0 :                                         return ("arm");
     690         [ #  # ]:          0 :                                 else if (val == 6) /* We have an ARMv6 */
     691                 :          0 :                                         return ("armv6");
     692                 :            :                                 else /* We have an ARMv7+ */
     693                 :          0 :                                         return ("armv7");
     694   [ #  #  #  #  :          0 :                         } else if (tag == 4 || tag == 5 || tag == 32 ||
             #  #  #  # ]
     695         [ #  # ]:          0 :                             tag == 65 || tag == 67) {
     696   [ #  #  #  # ]:          0 :                                 while (*section != '\0' && length != 0)
     697   [ #  #  #  # ]:          0 :                                         MOVE_TAG(1);
     698         [ #  # ]:          0 :                                 if (tag_length == 0)
     699                 :          0 :                                         return (NULL);
     700                 :            :                                 /* Skip the last byte */
     701   [ #  #  #  # ]:          0 :                                 MOVE_TAG(1);
     702   [ #  #  #  #  :          0 :                         } else if ((tag >= 7 && tag <= 31) || tag == 34 ||
                   #  # ]
     703   [ #  #  #  #  :          0 :                             tag == 36 || tag == 38 || tag == 42 || tag == 44 ||
             #  #  #  # ]
     704   [ #  #  #  #  :          0 :                             tag == 64 || tag == 66 || tag == 68 || tag == 70) { 
                   #  # ]
     705                 :            :                                 /* Skip the uleb128 data */
     706   [ #  #  #  # ]:          0 :                                 while (*section & (1 << 7) && length != 0)
     707   [ #  #  #  # ]:          0 :                                         MOVE_TAG(1);
     708         [ #  # ]:          0 :                                 if (tag_length == 0)
     709                 :          0 :                                         return (NULL);
     710                 :            :                                 /* Skip the last byte */
     711   [ #  #  #  # ]:          0 :                                 MOVE_TAG(1);
     712                 :          0 :                         } else
     713                 :          0 :                                 return (NULL);
     714                 :            : #undef MOVE_TAG
     715                 :            :                 }
     716                 :            : 
     717                 :          0 :                 break;
     718                 :            :         }
     719                 :          0 :         return (NULL);
     720                 :            : #undef MOVE
     721                 :          0 : }
     722                 :            : 
     723                 :            : static bool
     724                 :       6994 : elf_note_analyse(Elf_Data *data, GElf_Ehdr *elfhdr, struct os_info *oi)
     725                 :            : {
     726                 :            :         Elf_Note note;
     727                 :            :         char *src;
     728                 :            :         uint32_t gnu_abi_tag[4];
     729                 :       6994 :         char *note_os[6] = {"Linux", "GNU", "Solaris", "FreeBSD", "NetBSD", "Syllable"};
     730                 :       6994 :         char *(*pnote_os)[6] = &note_os;
     731                 :       6994 :         char invalid_osname[] = "Unknown";
     732                 :       6994 :         uint32_t version = 0;
     733                 :       6994 :         int version_style = 1;
     734                 :            : 
     735                 :       6994 :         src = data->d_buf;
     736                 :            : 
     737         [ -  + ]:       6994 :         while ((uintptr_t)src < ((uintptr_t)data->d_buf + data->d_size)) {
     738                 :       6994 :                 memcpy(&note, src, sizeof(Elf_Note));
     739                 :       6994 :                 src += sizeof(Elf_Note);
     740   [ -  +  #  # ]:       6994 :                 if ((strncmp ((const char *) src, "FreeBSD", note.n_namesz) == 0) ||
     741         [ #  # ]:          0 :                     (strncmp ((const char *) src, "DragonFly", note.n_namesz) == 0) ||
     742         [ #  # ]:          0 :                     (strncmp ((const char *) src, "NetBSD", note.n_namesz) == 0) ||
     743                 :          0 :                     (note.n_namesz == 0)) {
     744         [ -  + ]:       6994 :                         if (note.n_type == NT_VERSION) {
     745                 :       6994 :                                 version_style = 1;
     746                 :       6994 :                                 break;
     747                 :            :                         }
     748                 :          0 :                 }
     749         [ #  # ]:          0 :                 if (strncmp ((const char *) src, "GNU", note.n_namesz) == 0) {
     750         [ #  # ]:          0 :                         if (note.n_type == NT_GNU_ABI_TAG) {
     751                 :          0 :                                 version_style = 2;
     752                 :          0 :                                 break;
     753                 :            :                         }
     754                 :          0 :                 }
     755                 :          0 :                 src += roundup2(note.n_namesz + note.n_descsz, 4);
     756                 :            :         }
     757         [ -  + ]:       6994 :         if ((uintptr_t)src >= ((uintptr_t)data->d_buf + data->d_size)) {
     758                 :          0 :                 return (false);
     759                 :            :         }
     760                 :       6994 :         free(oi->name);
     761         [ -  + ]:       6994 :         if (version_style == 2) {
     762                 :            :                 /*
     763                 :            :                  * NT_GNU_ABI_TAG
     764                 :            :                  * Operating system (OS) ABI information.  The
     765                 :            :                  * desc field contains 4 words:
     766                 :            :                  * word 0: OS descriptor (ELF_NOTE_OS_LINUX, ELF_NOTE_OS_GNU, etc)
     767                 :            :                  * word 1: major version of the ABI
     768                 :            :                  * word 2: minor version of the ABI
     769                 :            :                  * word 3: subminor version of the ABI
     770                 :            :                  */
     771                 :          0 :                 src += roundup2(note.n_namesz, 4);
     772         [ #  # ]:          0 :                 if (elfhdr->e_ident[EI_DATA] == ELFDATA2MSB) {
     773         [ #  # ]:          0 :                         for (int wdndx = 0; wdndx < 4; wdndx++) {
     774                 :          0 :                                 gnu_abi_tag[wdndx] = be32dec(src);
     775                 :          0 :                                 src += 4;
     776                 :          0 :                         }
     777                 :          0 :                 } else {
     778         [ #  # ]:          0 :                         for (int wdndx = 0; wdndx < 4; wdndx++) {
     779                 :          0 :                                 gnu_abi_tag[wdndx] = le32dec(src);
     780                 :          0 :                                 src += 4;
     781                 :          0 :                         }
     782                 :            :                 }
     783         [ #  # ]:          0 :                 if (gnu_abi_tag[0] < 6)
     784                 :          0 :                         oi->name = xstrdup((*pnote_os)[gnu_abi_tag[0]]);
     785                 :            :                 else
     786                 :          0 :                         oi->name = xstrdup(invalid_osname);
     787                 :          0 :         } else {
     788         [ -  + ]:       6994 :                 if (note.n_namesz == 0)
     789                 :          0 :                         oi->name = xstrdup(invalid_osname);
     790                 :            :                 else
     791                 :       6994 :                         oi->name = xstrdup(src);
     792                 :       6994 :                 src += roundup2(note.n_namesz, 4);
     793         [ -  + ]:       6994 :                 if (elfhdr->e_ident[EI_DATA] == ELFDATA2MSB)
     794                 :          0 :                         version = be32dec(src);
     795                 :            :                 else
     796                 :       6994 :                         version = le32dec(src);
     797                 :            :         }
     798                 :            : 
     799                 :       6994 :         free(oi->version);
     800         [ -  + ]:       6994 :         if (version_style == 2) {
     801                 :          0 :                 xasprintf(&oi->version, "%d.%d.%d", gnu_abi_tag[1],
     802                 :          0 :                     gnu_abi_tag[2], gnu_abi_tag[3]);
     803                 :          0 :         } else {
     804         [ +  - ]:       6994 :                 if (oi->osversion == 0)
     805                 :       6994 :                         oi->osversion = version;
     806                 :            : #ifdef __DragonFly__
     807                 :            :                 xasprintf(&oi->version, "%d.%d", version / 100000, (((version / 100 % 1000)+1)/2)*2);
     808                 :            : #endif
     809                 :            : #ifdef __NetBSD__
     810                 :            :                 xasprintf(&oi->version, "%d", (version + 1000000) / 100000000);
     811                 :            : #endif
     812                 :       6994 :                 xasprintf(&oi->version_major, "%d", version / 100000);
     813                 :       6994 :                 xasprintf(&oi->version_minor, "%d", (version / 1000 % 100));
     814                 :       6994 :                 xasprintf(&oi->version, "%d", version / 100000);
     815                 :            :         }
     816                 :            : 
     817                 :       6994 :         return (true);
     818                 :       6994 : }
     819                 :            : 
     820                 :            : 
     821                 :            : static int
     822                 :       6994 : pkg_get_myarch_elfparse(char *dest, size_t sz, struct os_info *oi)
     823                 :            : {
     824                 :            :         char rooted_abi_file[PATH_MAX];
     825                 :       6994 :         Elf *elf = NULL;
     826                 :            :         GElf_Ehdr elfhdr;
     827                 :            :         GElf_Shdr shdr;
     828                 :            :         Elf_Data *data;
     829                 :       6994 :         Elf_Scn *scn = NULL;
     830                 :            :         int fd, i;
     831                 :       6994 :         int ret = EPKG_OK;
     832                 :            :         const char *arch, *abi, *endian_corres_str, *wordsize_corres_str, *fpu;
     833                 :            :         bool checkroot;
     834                 :            :         struct os_info loi;
     835                 :            : 
     836                 :      13988 :         const char *abi_files[] = {
     837                 :       6994 :                 getenv("ABI_FILE"),
     838                 :            :                 _PATH_UNAME,
     839                 :            :                 _PATH_BSHELL,
     840                 :            :         };
     841                 :            : 
     842                 :       6994 :         arch = NULL;
     843                 :            : 
     844         [ +  + ]:       6994 :         if (oi == NULL) {
     845                 :       3497 :                 memset(&loi, 0, sizeof(loi));
     846                 :       3497 :                 oi = &loi;
     847                 :       3497 :         }
     848                 :            : 
     849         [ +  - ]:       6994 :         if (elf_version(EV_CURRENT) == EV_NONE) {
     850                 :          0 :                 pkg_emit_error("ELF library initialization failed: %s",
     851                 :          0 :                     elf_errmsg(-1));
     852                 :          0 :                 return (EPKG_FATAL);
     853                 :            :         }
     854                 :            : 
     855                 :            :         /*
     856                 :            :          * Perhaps not yet needed, but it may be in the future that there's no
     857                 :            :          * need to check root under some conditions where there is a rootdir.
     858                 :            :          * This also helps alleviate some excessive wrapping later.
     859                 :            :          */
     860                 :       6994 :         checkroot = ctx.pkg_rootdir != NULL;
     861         [ -  + ]:      13980 :         for (fd = -1, i = 0; i < nitems(abi_files); i++) {
     862         [ +  + ]:      13980 :                 if (abi_files[i] == NULL)
     863                 :       6986 :                         continue;
     864                 :            :                 /*
     865                 :            :                  * Try prepending rootdir and using that if it exists.  If
     866                 :            :                  * ABI_FILE is specified, assume that the consumer didn't want
     867                 :            :                  * it mangled by rootdir.
     868                 :            :                  */
     869   [ +  +  +  +  :       6994 :                 if (i > 0 && checkroot && snprintf(rooted_abi_file, PATH_MAX,
          -  +  -  +  -  
                      + ]
     870                 :       1208 :                     "%s/%s", ctx.pkg_rootdir, abi_files[i]) < PATH_MAX) {
     871         [ +  - ]:        604 :                         if ((fd = open(rooted_abi_file, O_RDONLY)) >= 0)
     872                 :          0 :                                 break;
     873                 :        604 :                 }
     874         [ -  + ]:       6994 :                 if ((fd = open(abi_files[i], O_RDONLY)) >= 0)
     875                 :       6994 :                         break;
     876                 :            :                 /* if the ABI_FILE was provided we only care about it */
     877         [ #  # ]:          0 :                 if (i == 0)
     878                 :          0 :                         break;
     879                 :          0 :         }
     880         [ +  - ]:       6994 :         if (fd == -1) {
     881                 :          0 :                 pkg_emit_error("Unable to determine the ABI\n");
     882                 :          0 :                 return (EPKG_FATAL);
     883                 :            :         }
     884                 :            : 
     885         [ +  - ]:       6994 :         if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL) {
     886                 :          0 :                 ret = EPKG_FATAL;
     887                 :          0 :                 pkg_emit_error("elf_begin() failed: %s.", elf_errmsg(-1));
     888                 :          0 :                 goto cleanup;
     889                 :            :         }
     890                 :            : 
     891         [ +  - ]:       6994 :         if (gelf_getehdr(elf, &elfhdr) == NULL) {
     892                 :          0 :                 ret = EPKG_FATAL;
     893                 :          0 :                 pkg_emit_error("getehdr() failed: %s.", elf_errmsg(-1));
     894                 :          0 :                 goto cleanup;
     895                 :            :         }
     896                 :            : 
     897                 :            : 
     898         [ +  + ]:     209884 :         while ((scn = elf_nextscn(elf, scn)) != NULL) {
     899         [ +  - ]:     202890 :                 if (gelf_getshdr(scn, &shdr) != &shdr) {
     900                 :          0 :                         ret = EPKG_FATAL;
     901                 :          0 :                         pkg_emit_error("getshdr() failed: %s.", elf_errmsg(-1));
     902                 :          0 :                         goto cleanup;
     903                 :            :                 }
     904                 :            : 
     905         [ +  + ]:     202890 :                 if (shdr.sh_type == SHT_NOTE) {
     906                 :       6994 :                         data = elf_getdata(scn, NULL);
     907                 :            :                         /*
     908                 :            :                          * loop over all the note section and override what
     909                 :            :                          * should be overridden if any
     910                 :            :                          */
     911                 :       6994 :                         elf_note_analyse(data, &elfhdr, oi);
     912                 :       6994 :                 }
     913                 :            :         }
     914                 :            : 
     915         [ +  - ]:       6994 :         if (oi->name == NULL) {
     916                 :          0 :                 ret = EPKG_FATAL;
     917                 :          0 :                 pkg_emit_error("failed to get the note section");
     918                 :          0 :                 goto cleanup;
     919                 :            :         }
     920                 :            : 
     921                 :       6994 :         snprintf(dest, sz, "%s:%s", oi->name, oi->version);
     922                 :            : 
     923                 :       6994 :         wordsize_corres_str = elf_corres_to_string(wordsize_corres,
     924                 :       6994 :             (int)elfhdr.e_ident[EI_CLASS]);
     925                 :            : 
     926                 :       6994 :         arch = elf_corres_to_string(mach_corres, (int) elfhdr.e_machine);
     927                 :            : 
     928   [ -  +  -  -  :       6994 :         switch (elfhdr.e_machine) {
                      - ]
     929                 :            :         case EM_ARM:
     930                 :          0 :                 endian_corres_str = elf_corres_to_string(endian_corres,
     931                 :          0 :                     (int)elfhdr.e_ident[EI_DATA]);
     932                 :            : 
     933         [ #  # ]:          0 :                 if (elfhdr.e_flags & EF_ARM_VFP_FLOAT)
     934                 :          0 :                         fpu = "hardfp";
     935                 :            :                 else
     936                 :          0 :                         fpu = "softfp";
     937                 :            : 
     938         [ #  # ]:          0 :                 if ((elfhdr.e_flags & 0xFF000000) != 0) {
     939                 :          0 :                         const char *sh_name = NULL;
     940                 :            :                         size_t shstrndx;
     941                 :            : 
     942                 :            :                         /* This is an EABI file, the conformance level is set */
     943                 :          0 :                         abi = "eabi";
     944                 :            : 
     945                 :            :                         /* Find which TARGET_ARCH we are building for. */
     946                 :          0 :                         elf_getshdrstrndx(elf, &shstrndx);
     947         [ #  # ]:          0 :                         while ((scn = elf_nextscn(elf, scn)) != NULL) {
     948                 :          0 :                                 sh_name = NULL;
     949         [ #  # ]:          0 :                                 if (gelf_getshdr(scn, &shdr) != &shdr) {
     950                 :          0 :                                         scn = NULL;
     951                 :          0 :                                         break;
     952                 :            :                                 }
     953                 :            : 
     954                 :          0 :                                 sh_name = elf_strptr(elf, shstrndx,
     955                 :          0 :                                     shdr.sh_name);
     956         [ #  # ]:          0 :                                 if (sh_name == NULL)
     957                 :          0 :                                         continue;
     958         [ #  # ]:          0 :                                 if (strcmp(".ARM.attributes", sh_name) == 0)
     959                 :          0 :                                         break;
     960                 :            :                         }
     961   [ #  #  #  # ]:          0 :                         if (scn != NULL && sh_name != NULL) {
     962                 :          0 :                                 data = elf_getdata(scn, NULL);
     963                 :            :                                 /*
     964                 :            :                                  * Prior to FreeBSD 10.0 libelf would return
     965                 :            :                                  * NULL from elf_getdata on the .ARM.attributes
     966                 :            :                                  * section. As this was the first release to
     967                 :            :                                  * get armv6 support assume a NULL value means
     968                 :            :                                  * arm.
     969                 :            :                                  *
     970                 :            :                                  * This assumption can be removed when 9.x
     971                 :            :                                  * is unsupported.
     972                 :            :                                  */
     973         [ #  # ]:          0 :                                 if (data != NULL) {
     974                 :          0 :                                         arch = aeabi_parse_arm_attributes(
     975                 :          0 :                                             data->d_buf, data->d_size);
     976         [ #  # ]:          0 :                                         if (arch == NULL) {
     977                 :          0 :                                                 ret = EPKG_FATAL;
     978                 :          0 :                                                 pkg_emit_error(
     979                 :            :                                                     "unknown ARM ARCH");
     980                 :          0 :                                                 goto cleanup;
     981                 :            :                                         }
     982                 :          0 :                                 }
     983                 :          0 :                         } else {
     984                 :          0 :                                 ret = EPKG_FATAL;
     985                 :          0 :                                 pkg_emit_error("Unable to find the "
     986                 :            :                                     ".ARM.attributes section");
     987                 :          0 :                                 goto cleanup;
     988                 :            :                         }
     989                 :            : 
     990         [ #  # ]:          0 :                 } else if (elfhdr.e_ident[EI_OSABI] != ELFOSABI_NONE) {
     991                 :            :                         /*
     992                 :            :                          * EABI executables all have this field set to
     993                 :            :                          * ELFOSABI_NONE, therefore it must be an oabi file.
     994                 :            :                          */
     995                 :          0 :                         abi = "oabi";
     996                 :          0 :                 } else {
     997                 :            :                         /*
     998                 :            :                          * We may have failed to positively detect the ABI,
     999                 :            :                          * set the ABI to unknown. If we end up here one of
    1000                 :            :                          * the above cases should be fixed for the binary.
    1001                 :            :                          */
    1002                 :          0 :                         ret = EPKG_FATAL;
    1003                 :          0 :                         pkg_emit_error("unknown ARM ABI");
    1004                 :          0 :                         goto cleanup;
    1005                 :            :                 }
    1006                 :          0 :                 snprintf(dest + strlen(dest), sz - strlen(dest),
    1007                 :          0 :                     ":%s:%s:%s:%s:%s", arch, wordsize_corres_str,
    1008                 :          0 :                     endian_corres_str, abi, fpu);
    1009                 :          0 :                 break;
    1010                 :            :         case EM_MIPS:
    1011                 :            :                 /*
    1012                 :            :                  * this is taken from binutils sources:
    1013                 :            :                  * include/elf/mips.h
    1014                 :            :                  * mapping is figured out from binutils:
    1015                 :            :                  * gas/config/tc-mips.c
    1016                 :            :                  */
    1017      [ #  #  # ]:          0 :                 switch (elfhdr.e_flags & EF_MIPS_ABI) {
    1018                 :            :                         case E_MIPS_ABI_O32:
    1019                 :          0 :                                 abi = "o32";
    1020                 :          0 :                                 break;
    1021                 :            :                         case E_MIPS_ABI_N32:
    1022                 :          0 :                                 abi = "n32";
    1023                 :          0 :                                 break;
    1024                 :            :                         default:
    1025         [ #  # ]:          0 :                                 if (elfhdr.e_ident[EI_DATA] == ELFCLASS32)
    1026                 :          0 :                                         abi = "o32";
    1027         [ #  # ]:          0 :                                 else if (elfhdr.e_ident[EI_DATA] == ELFCLASS64)
    1028                 :          0 :                                         abi = "n64";
    1029                 :            :                                 else
    1030                 :          0 :                                         abi = "unknown";
    1031                 :          0 :                                 break;
    1032                 :            :                 }
    1033                 :          0 :                 endian_corres_str = elf_corres_to_string(endian_corres,
    1034                 :          0 :                     (int)elfhdr.e_ident[EI_DATA]);
    1035                 :            : 
    1036                 :          0 :                 snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s:%s",
    1037                 :          0 :                     arch, wordsize_corres_str, endian_corres_str, abi);
    1038                 :          0 :                 break;
    1039                 :            : #if defined(EM_RISCV) && defined(EF_RISCV_FLOAT_ABI_MASK)
    1040                 :            :         case EM_RISCV:
    1041      [ #  #  # ]:          0 :                 switch (elfhdr.e_flags & EF_RISCV_FLOAT_ABI_MASK) {
    1042                 :            :                         case EF_RISCV_FLOAT_ABI_SOFT:
    1043                 :          0 :                                 abi = "sf";
    1044                 :          0 :                                 break;
    1045                 :            :                         case EF_RISCV_FLOAT_ABI_DOUBLE:
    1046                 :          0 :                                 abi = "hf";
    1047                 :          0 :                                 break;
    1048                 :            :                         default:
    1049                 :          0 :                                 abi = "unknown";
    1050                 :          0 :                                 break;
    1051                 :            :                 }
    1052                 :          0 :                 snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s",
    1053                 :          0 :                     arch, wordsize_corres_str, abi);
    1054                 :          0 :                 break;
    1055                 :            : #endif
    1056                 :            :         case EM_PPC:
    1057                 :            :         case EM_PPC64:
    1058                 :          0 :                 endian_corres_str = elf_corres_to_string(endian_corres,
    1059                 :          0 :                     (int)elfhdr.e_ident[EI_DATA]);
    1060                 :            : 
    1061                 :          0 :                 snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s:%s",
    1062                 :          0 :                     arch, wordsize_corres_str, endian_corres_str);
    1063                 :          0 :                 break;
    1064                 :            :         default:
    1065                 :      13988 :                 snprintf(dest + strlen(dest), sz - strlen(dest), ":%s:%s",
    1066                 :       6994 :                     arch, wordsize_corres_str);
    1067                 :       6994 :                 break;
    1068                 :       6994 :         }
    1069                 :            : 
    1070                 :            : cleanup:
    1071         [ -  + ]:       6994 :         if (elf != NULL)
    1072                 :       6994 :                 elf_end(elf);
    1073         [ +  + ]:       6994 :         if (oi == &loi) {
    1074                 :       3497 :                 free(oi->name);
    1075                 :       3497 :                 free(oi->version);
    1076                 :       3497 :                 free(oi->version_major);
    1077                 :       3497 :                 free(oi->version_minor);
    1078                 :       3497 :                 free(oi->arch);
    1079                 :       3497 :         }
    1080                 :       6994 :         close(fd);
    1081                 :       6994 :         return (ret);
    1082                 :       6994 : }
    1083                 :            : 
    1084                 :            : int
    1085                 :       5415 : pkg_arch_to_legacy(const char *arch, char *dest, size_t sz)
    1086                 :            : {
    1087                 :       5415 :         int i = 0;
    1088                 :            :         struct arch_trans *arch_trans;
    1089                 :            : 
    1090                 :       5415 :         bzero(dest, sz);
    1091                 :            :         /* Lower case the OS */
    1092   [ +  +  +  + ]:      35112 :         while (arch[i] != ':' && arch[i] != '\0') {
    1093                 :      29697 :                 dest[i] = tolower(arch[i]);
    1094                 :      29697 :                 i++;
    1095                 :            :         }
    1096         [ +  + ]:       5415 :         if (arch[i] == '\0')
    1097                 :       1368 :                 return (0);
    1098                 :            : 
    1099                 :       4047 :         dest[i++] = ':';
    1100                 :            : 
    1101                 :            :         /* Copy the version */
    1102   [ +  +  +  + ]:      12141 :         while (arch[i] != ':' && arch[i] != '\0') {
    1103                 :       8094 :                 dest[i] = arch[i];
    1104                 :       8094 :                 i++;
    1105                 :            :         }
    1106         [ +  - ]:       4047 :         if (arch[i] == '\0')
    1107                 :          0 :                 return (0);
    1108                 :            : 
    1109                 :       4047 :         dest[i++] = ':';
    1110                 :            : 
    1111         [ +  - ]:       8094 :         for (arch_trans = machine_arch_translation; arch_trans->elftype != NULL;
    1112                 :       4047 :             arch_trans++) {
    1113         [ +  + ]:       8094 :                 if (strcmp(arch + i, arch_trans->archid) == 0) {
    1114                 :       8094 :                         strlcpy(dest + i, arch_trans->elftype,
    1115                 :       4047 :                             sz - (arch + i - dest));
    1116                 :       4047 :                         return (0);
    1117                 :            :                 }
    1118                 :       4047 :         }
    1119                 :          0 :         strlcpy(dest + i, arch + i, sz - (arch + i  - dest));
    1120                 :            : 
    1121                 :          0 :         return (0);
    1122                 :       5415 : }
    1123                 :            : 
    1124                 :            : int
    1125                 :       3497 : pkg_get_myarch_legacy(char *dest, size_t sz)
    1126                 :            : {
    1127                 :            :         int i, err;
    1128                 :            : 
    1129                 :       3497 :         err = pkg_get_myarch_elfparse(dest, sz, NULL);
    1130         [ -  + ]:       3497 :         if (err)
    1131                 :          0 :                 return (err);
    1132                 :            : 
    1133         [ +  + ]:      62946 :         for (i = 0; i < strlen(dest); i++)
    1134                 :      59449 :                 dest[i] = tolower(dest[i]);
    1135                 :            : 
    1136                 :       3497 :         return (0);
    1137                 :       3497 : }
    1138                 :            : 
    1139                 :            : int
    1140                 :       3497 : pkg_get_myarch(char *dest, size_t sz, struct os_info *oi)
    1141                 :            : {
    1142                 :            :         struct arch_trans *arch_trans;
    1143                 :            :         char *arch_tweak;
    1144                 :            :         int err;
    1145                 :       3497 :         err = pkg_get_myarch_elfparse(dest, sz, oi);
    1146         [ -  + ]:       3497 :         if (err) {
    1147         [ #  # ]:          0 :                 if (oi) {
    1148                 :          0 :                         free(oi->name);
    1149                 :          0 :                 }
    1150                 :          0 :                 return (err);
    1151                 :            :         }
    1152                 :            : 
    1153                 :            : #ifdef __DragonFly__
    1154                 :            :         if (strncasecmp(dest, "DragonFly", 9) == 0) {
    1155                 :            :                 for (int i = 0; i < strlen(dest); i++)
    1156                 :            :                         dest[i] = tolower(dest[i]);
    1157                 :            :                 return (0);
    1158                 :            :         }
    1159                 :            : #endif
    1160                 :            : 
    1161                 :            :         /* Translate architecture string back to regular OS one */
    1162                 :       3497 :         arch_tweak = strchr(dest, ':');
    1163         [ +  - ]:       3497 :         if (arch_tweak == NULL)
    1164                 :          0 :                 return (0);
    1165                 :       3497 :         arch_tweak++;
    1166                 :       3497 :         arch_tweak = strchr(arch_tweak, ':');
    1167         [ +  - ]:       3497 :         if (arch_tweak == NULL)
    1168                 :          0 :                 return (0);
    1169                 :       3497 :         arch_tweak++;
    1170         [ -  + ]:       6994 :         for (arch_trans = machine_arch_translation; arch_trans->elftype != NULL;
    1171                 :       3497 :             arch_trans++) {
    1172         [ +  + ]:       6994 :                 if (strcmp(arch_tweak, arch_trans->elftype) == 0) {
    1173                 :       6994 :                         strlcpy(arch_tweak, arch_trans->archid,
    1174                 :       3497 :                             sz - (arch_tweak - dest));
    1175                 :       3497 :                         oi->arch = xstrdup(arch_tweak);
    1176                 :       3497 :                         break;
    1177                 :            :                 }
    1178                 :       3497 :         }
    1179                 :            : 
    1180                 :       3497 :         return (0);
    1181                 :       3497 : }
    1182                 :            : 

Generated by: LCOV version 1.15