LCOV - code coverage report
Current view: top level - libpkg - pkg_abi_macho.c (source / functions) Hit Total Coverage
Test: plop Lines: 171 252 67.9 %
Date: 2024-12-30 07:09:03 Functions: 8 8 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 74 165 44.8 %

           Branch data     Line data    Source code
       1                 :            : /*-
       2                 :            :  * Copyright (c) 2024 Keve Müller <kevemueller@users.github.com>
       3                 :            :  *
       4                 :            :  * SPDX-License-Identifier: BSD-2-Clause
       5                 :            :  */
       6                 :            : 
       7                 :            : #include <errno.h>
       8                 :            : 
       9                 :            : #include "private/binfmt.h"
      10                 :            : #include "private/binfmt_macho.h"
      11                 :            : #include "private/pkg.h"
      12                 :            : #include "private/event.h"
      13                 :            : #include "private/pkg_abi.h"
      14                 :            : 
      15                 :            : /**
      16                 :            :  * Routines to support pkg_abi.c functions when dealing with Mach-O files.
      17                 :            :  * Supports getting struct pkg_abi from the binary's load commands.
      18                 :            :  * Supports getting shared libary information (needed, provided & loader).
      19                 :            :  * Picks right binary in Universal binary based on ABI.
      20                 :            :  */
      21                 :            : 
      22                 :            : static enum pkg_arch
      23                 :         45 : cputype_to_pkg_arch(const cpu_type_subtype_t cpu)
      24                 :            : {
      25   [ -  +  -  + ]:         45 :         switch (cpu.type) {
      26                 :            :         case CPU_TYPE_ARM:
      27         [ -  + ]:         15 :                 if (cpu.type_is64_32) {
      28                 :          0 :                         return (PKG_ARCH_UNKNOWN); /* aarch64-x32 */
      29         [ +  - ]:         15 :                 } else if (cpu.type_is64) {
      30                 :         15 :                         return (PKG_ARCH_AARCH64);
      31                 :            :                 } else {
      32   [ #  #  #  #  :          0 :                         switch (cpu.subtype_arm) {
          #  #  #  #  #  
                #  #  # ]
      33                 :            :                         case CPU_SUBTYPE_ARM_V7:
      34                 :            :                         case CPU_SUBTYPE_ARM_V7S:
      35                 :            :                         case CPU_SUBTYPE_ARM_V7K:
      36                 :            :                         case CPU_SUBTYPE_ARM_V7M:
      37                 :            :                         case CPU_SUBTYPE_ARM_V7EM:
      38                 :          0 :                                 return (PKG_ARCH_ARMV7);
      39                 :            :                         case CPU_SUBTYPE_ARM_V6:
      40                 :            :                         case CPU_SUBTYPE_ARM_V6M:
      41                 :          0 :                                 return (PKG_ARCH_ARMV6);
      42                 :            :                         case CPU_SUBTYPE_ARM_XSCALE:
      43                 :            :                         case CPU_SUBTYPE_ARM_V5:
      44                 :            :                         case CPU_SUBTYPE_ARM_V4T:
      45                 :          0 :                         case CPU_SUBTYPE_ARM_ALL:
      46                 :            :                         default:
      47                 :          0 :                                 return (PKG_ARCH_UNKNOWN);
      48                 :            :                         }
      49                 :            :                 }
      50                 :            :         case CPU_TYPE_POWERPC:
      51         [ #  # ]:          0 :                 if (cpu.type_is64_32) {
      52                 :          0 :                         return (PKG_ARCH_UNKNOWN); /* powerpc64-x32 */
      53         [ #  # ]:          0 :                 } else if (cpu.type_is64) {
      54                 :          0 :                         return (PKG_ARCH_POWERPC64);
      55                 :            :                 } else {
      56                 :          0 :                         return (PKG_ARCH_POWERPC);
      57                 :            :                 }
      58                 :            :         case CPU_TYPE_X86:
      59         [ -  + ]:         30 :                 if (cpu.type_is64_32) {
      60                 :          0 :                         return (PKG_ARCH_UNKNOWN); /* amd64-x32 */
      61         [ +  - ]:         30 :                 } else if (cpu.type_is64) {
      62                 :         30 :                         return (PKG_ARCH_AMD64);
      63                 :            :                 } else {
      64                 :          0 :                         return (PKG_ARCH_I386);
      65                 :            :                 }
      66                 :            :         default:
      67                 :          0 :                 return (PKG_ARCH_UNKNOWN);
      68                 :            :         }
      69                 :         45 : }
      70                 :            : 
      71                 :            : static cpu_type_subtype_t
      72                 :         25 : pkg_arch_to_cputype(enum pkg_arch arch) {
      73                 :         25 :         cpu_type_subtype_t cpu = { 0 };
      74                 :            : 
      75   [ -  +  +  -  :         25 :         switch (arch) {
          -  +  -  -  -  
                -  -  - ]
      76                 :            :         case PKG_ARCH_AARCH64:
      77                 :          9 :                 cpu.type = CPU_TYPE_ARM;
      78                 :          9 :                 cpu.type_is64 = true;
      79                 :          9 :                 break;
      80                 :            :         case PKG_ARCH_AMD64:
      81                 :         12 :                 cpu.type = CPU_TYPE_X86;
      82                 :         12 :                 cpu.type_is64 = true;
      83                 :         12 :                 cpu.subtype_x86 = CPU_SUBTYPE_X86_ALL;
      84                 :         12 :                 break;
      85                 :            :         case PKG_ARCH_ARMV6:
      86                 :          0 :                 cpu.type = CPU_TYPE_ARM;
      87                 :          0 :                 cpu.subtype_arm = CPU_SUBTYPE_ARM_V6;
      88                 :          0 :                 break;
      89                 :            :         case PKG_ARCH_ARMV7:
      90                 :          0 :                 cpu.type = CPU_TYPE_ARM;
      91                 :          0 :                 cpu.subtype_arm = CPU_SUBTYPE_ARM_V7;
      92                 :          0 :                 break;
      93                 :            :         case PKG_ARCH_I386:
      94                 :          4 :                 cpu.type = CPU_TYPE_X86;
      95                 :          4 :                 cpu.subtype_x86 = CPU_SUBTYPE_X86_ALL;
      96                 :          4 :                 break;
      97                 :            :         case PKG_ARCH_POWERPC:
      98                 :          0 :                 cpu.type = CPU_TYPE_POWERPC;
      99                 :          0 :                 cpu.subtype_ppc = CPU_SUBTYPE_POWERPC_ALL;
     100                 :          0 :                 break;
     101                 :            :         case PKG_ARCH_POWERPC64:
     102                 :          0 :                 cpu.type = CPU_TYPE_POWERPC;
     103                 :          0 :                 cpu.type_is64 = true;
     104                 :          0 :                 cpu.subtype_ppc = CPU_SUBTYPE_POWERPC_ALL;
     105                 :          0 :                 break;
     106                 :            :         case PKG_ARCH_POWERPC64LE:
     107                 :            :         case PKG_ARCH_RISCV32:
     108                 :            :         case PKG_ARCH_RISCV64:
     109                 :            :         case PKG_ARCH_UNKNOWN:
     110                 :          0 :                 cpu.type = CPU_TYPE_ANY;
     111                 :          0 :                 break;
     112                 :            :         }
     113                 :            : 
     114                 :         25 :         return cpu;
     115                 :            : }
     116                 :            : 
     117                 :            : 
     118                 :            : /**
     119                 :            :  * Using the passed mf descriptor, match the best entry using the provided hint.
     120                 :            :  * No hint or no architecture in hint -> first entry. Debug1 warning if this is not precise match (there were multiple to choose from)
     121                 :            :  * Hint -> always match, even if single architecture in file. Notice if match fails and return null.
     122                 :            :  */
     123                 :            : static const fat_arch_t *
     124                 :         44 : match_entry(macho_file_t *mf, enum pkg_arch arch_hint)
     125                 :            : {
     126                 :         44 :         const fat_arch_t *p = mf->arch;
     127         [ +  + ]:         44 :         if (arch_hint != PKG_ARCH_UNKNOWN) {
     128                 :         25 :                 const cpu_type_subtype_t cpu_hint = pkg_arch_to_cputype(arch_hint);
     129                 :         25 :                 const fat_arch_t *p_end = p + mf->narch;
     130         [ +  + ]:         39 :                 while (p < p_end) {
     131                 :            :                         // do not match cpu_hint.type == CPU_TYPE_ANY which is used if the
     132                 :            :                         // arch_hint was not recognized
     133   [ +  +  +  + ]:         35 :                         if (p->cpu.type == cpu_hint.type &&
     134                 :         23 :                             p->cpu.type_is64 == cpu_hint.type_is64) {
     135   [ -  +  -  + ]:         21 :                                 switch (cpu_hint.type) {
     136                 :            :                                 case CPU_TYPE_ARM:
     137         [ #  # ]:          9 :                                         if (p->cpu.subtype_arm ==
     138         [ -  + ]:          9 :                                                 CPU_SUBTYPE_ARM_ALL ||
     139                 :          0 :                                             cpu_hint.subtype_arm ==
     140         [ #  # ]:          0 :                                                 CPU_SUBTYPE_ARM_ALL ||
     141                 :          0 :                                             p->cpu.subtype_arm ==
     142                 :          0 :                                                 cpu_hint.subtype_arm) {
     143                 :          9 :                                                         return p;
     144                 :            :                                         }
     145                 :          0 :                                         break;
     146                 :            :                                 case CPU_TYPE_POWERPC:
     147         [ #  # ]:          0 :                                         if (p->cpu.subtype_ppc ==
     148         [ #  # ]:          0 :                                                 CPU_SUBTYPE_POWERPC_ALL ||
     149                 :          0 :                                             cpu_hint.subtype_ppc ==
     150         [ #  # ]:          0 :                                                 CPU_SUBTYPE_POWERPC_ALL ||
     151                 :          0 :                                             p->cpu.subtype_ppc ==
     152                 :          0 :                                                 cpu_hint.subtype_ppc) {
     153                 :          0 :                                                         return p;
     154                 :            :                                         }
     155                 :          0 :                                         break;
     156                 :            :                                 case CPU_TYPE_X86:
     157         [ #  # ]:         12 :                                         if (p->cpu.subtype_x86 ==
     158         [ -  + ]:         12 :                                                 CPU_SUBTYPE_X86_ALL ||
     159                 :          0 :                                             cpu_hint.subtype_x86 ==
     160         [ #  # ]:          0 :                                                 CPU_SUBTYPE_X86_ALL ||
     161                 :          0 :                                             p->cpu.subtype_x86 ==
     162                 :          0 :                                                 cpu_hint.subtype_x86) {
     163                 :         12 :                                                         return p;
     164                 :            :                                         }
     165                 :          0 :                                         break;
     166                 :            :                                 default:
     167                 :          0 :                                         break;
     168                 :            :                                 }
     169                 :          0 :                         }
     170                 :         14 :                         pkg_debug(1, "Looking for %s, did not match %s",
     171                 :         14 :                             pkg_arch_to_string(PKG_OS_DARWIN, arch_hint),
     172                 :         14 :                             pkg_arch_to_string(PKG_OS_DARWIN, cputype_to_pkg_arch(p->cpu)));
     173                 :         14 :                         p++;
     174                 :            :                 }
     175                 :          4 :                 pkg_emit_notice("Scanned %d entr%s, found none matching selector %s",
     176                 :          4 :                         mf->narch, mf->narch > 1 ? "ies" : "y",
     177                 :          4 :                         pkg_arch_to_string(PKG_OS_DARWIN, arch_hint));
     178                 :          4 :                 return 0;
     179         [ +  + ]:         19 :         } else if (mf->narch > 1 ) {
     180                 :          8 :                 pkg_debug(1,"Found %"PRIu32" entries in universal binary, picking first",
     181                 :          8 :                         mf->narch);
     182                 :          8 :         }
     183                 :         19 :         return p;
     184                 :         44 : }
     185                 :            : 
     186                 :            : /**
     187                 :            :  * With a not-null, potentially pre-populated os_info structure, fill
     188                 :            :  * all members of os_info except altabi with values obtained by parsing the Mach-O
     189                 :            :  * file passed with file descriptor.
     190                 :            :  *
     191                 :            :  * The arch_hint is used to determine the fat entry to be parsed in a universal
     192                 :            :  * binary. If arch_hint is PKG_ARCH_UNKNOWN, the first entry is used.
     193                 :            :  *
     194                 :            :  * Returns EPKG_OK if all went fine, EPKG_FATAL if anything went wrong.
     195                 :            :  * Seeks the file descriptor to an arbitrary position.
     196                 :            :  */
     197                 :            : int
     198                 :         35 : pkg_macho_abi_from_fd(int fd, struct pkg_abi *abi, enum pkg_arch arch_hint)
     199                 :            : {
     200                 :         35 :         *abi = (struct pkg_abi){0};
     201                 :            : 
     202                 :            :         ssize_t x;
     203                 :         35 :         pkg_error_t ret = EPKG_FATAL;
     204                 :            : 
     205                 :         35 :         macho_file_t *mf = 0;
     206                 :         35 :         build_version_t *bv = 0;
     207                 :            : 
     208         [ +  - ]:         35 :         if ((x = read_macho_file(fd, &mf)) < 0) {
     209                 :          0 :                 goto cleanup;
     210                 :            :         }
     211                 :            : 
     212                 :         35 :         const fat_arch_t *p = match_entry(mf, arch_hint);
     213                 :            : 
     214         [ +  + ]:         35 :         if (!p) {
     215                 :          4 :                 goto cleanup;
     216                 :            :         }
     217                 :            : 
     218         [ -  + ]:         31 :         if (-1 == (x = lseek(fd, p->offset, SEEK_SET))) {
     219                 :          0 :                 goto cleanup;
     220                 :            :         }
     221                 :         31 :         size_t n = 0;
     222                 :            :         macho_header_t mh;
     223         [ +  - ]:         31 :         if ((x = read_macho_header(fd, &mh)) < 0) {
     224                 :          0 :                 goto cleanup;
     225                 :            :         }
     226                 :         31 :         const bool swap = mh.swap;
     227                 :         31 :         n = 0;
     228         [ +  + ]:        488 :         for (uint32_t ui = mh.ncmds; ui-- > 0;) {
     229                 :        457 :                 size_t n0 = n;
     230                 :            :                 uint32_t loadcmdtype;
     231                 :            :                 uint32_t loadcmdsize;
     232         [ -  + ]:        457 :                 READ(u32, loadcmdtype);
     233         [ -  + ]:        457 :                 READ(u32, loadcmdsize);
     234                 :        457 :                 enum MachOLoadCommand loadcmd = loadcmdtype & ~LC_REQ_DYLD;
     235   [ -  +  -  +  :        457 :                 switch (loadcmd) {
                   +  - ]
     236                 :            :                 case LC_BUILD_VERSION:
     237         [ +  - ]:         14 :                         if (bv) { // overwrite previous LC_VERSION_MIN_X
     238                 :            :                                   // values
     239                 :          0 :                                 free(bv);
     240                 :          0 :                                 bv = 0;
     241                 :          0 :                         }
     242         [ +  - ]:         14 :                         READ(build_version, bv);
     243                 :         31 :                         break;
     244                 :            :                 case LC_VERSION_MIN_IPHONEOS:
     245                 :            :                 case LC_VERSION_MIN_MACOSX:
     246                 :            :                 case LC_VERSION_MIN_TVOS:
     247                 :            :                 case LC_VERSION_MIN_WATCHOS:
     248         [ -  + ]:        443 :                         if (!bv) {
     249   [ -  +  -  + ]:         34 :                                 if ((x = read_min_version(fd, swap, loadcmd,
     250                 :         17 :                                          &bv)) < 0) {
     251                 :          0 :                                         goto cleanup;
     252                 :            :                                 }
     253                 :         17 :                                 n += x;
     254                 :         17 :                                 break;
     255                 :            :                         }
     256                 :            :                         // have seen the more precise
     257                 :            :                         // LC_BUILD_VERSION already
     258                 :            :                         // fall through and disregard this
     259                 :            :                 default:
     260                 :        426 :                         break;
     261                 :            :                 }
     262                 :        457 :                 const uint32_t fill = loadcmdsize - (n - n0);
     263   [ +  +  +  - ]:        457 :                 if (fill && -1 == (x = lseek(fd, fill, SEEK_CUR))) {
     264                 :          0 :                         goto cleanup;
     265                 :            :                 }
     266                 :        457 :                 n += fill;
     267         [ -  + ]:        457 :                 if (n > mh.sizeofcmds) {
     268                 :            :                         // we passed the frame boundary of the load commands
     269                 :          0 :                         pkg_emit_error("Mach-O structure misread.");
     270                 :          0 :                         errno = EINVAL;
     271                 :          0 :                         goto cleanup;
     272                 :            :                 }
     273                 :            :         }
     274                 :            : 
     275         [ +  - ]:         62 :         if (bv) {
     276                 :            :                 macho_version_t darwin;
     277                 :         31 :                 map_platform_to_darwin(&darwin, bv->platform, bv->minos);
     278                 :            : 
     279                 :         31 :                 abi->os = PKG_OS_DARWIN;
     280                 :            : 
     281                 :         31 :                 abi->major = darwin.major;
     282                 :         31 :                 abi->minor = darwin.minor;
     283                 :         31 :                 abi->patch = darwin.patch;
     284                 :            : 
     285                 :         31 :                 abi->arch = cputype_to_pkg_arch(mh.cpu);
     286                 :            : 
     287         [ +  - ]:         31 :                 if (abi->arch == PKG_ARCH_UNKNOWN) {
     288                 :          0 :                         ret = EPKG_FATAL;
     289                 :          0 :                 } else {
     290                 :         31 :                         ret = EPKG_OK;
     291                 :            :                 }
     292                 :         31 :         } else {
     293                 :          0 :                 pkg_emit_notice("No OS version information found in binary.");
     294                 :          0 :                 ret = EPKG_WARN;
     295                 :            :         }
     296                 :            : 
     297                 :            : cleanup:
     298                 :         35 :         free(bv);
     299                 :         35 :         free(mf);
     300                 :         35 :         return ret;
     301                 :         35 : }
     302                 :            : 
     303                 :            : static int
     304                 :          9 : analyse_macho(int fd, struct pkg *pkg)
     305                 :            : {
     306                 :            :         ssize_t x;
     307                 :          9 :         pkg_error_t ret = EPKG_END;
     308                 :            : 
     309                 :          9 :         macho_file_t *mf = 0;
     310                 :            : 
     311         [ +  - ]:          9 :         if ((x = read_macho_file(fd, &mf)) < 0) {
     312                 :          0 :                 goto cleanup;
     313                 :            :         }
     314                 :            : 
     315                 :          9 :         const fat_arch_t *p = match_entry(mf, ctx.abi.arch);
     316                 :            : 
     317         [ +  - ]:          9 :         if (!p) {
     318                 :          0 :                 goto cleanup;
     319                 :            :         }
     320                 :            : 
     321         [ -  + ]:          9 :         if (-1 == (x = lseek(fd, p->offset, SEEK_SET))) {
     322                 :          0 :                 goto cleanup;
     323                 :            :         }
     324                 :          9 :         size_t n = 0;
     325                 :            :         macho_header_t mh;
     326         [ +  - ]:          9 :         if ((x = read_macho_header(fd, &mh)) < 0) {
     327                 :          0 :                 goto cleanup;
     328                 :            :         }
     329                 :          9 :         const bool swap = mh.swap;
     330                 :          9 :         n = 0;
     331         [ +  + ]:        140 :         for (uint32_t ui = mh.ncmds; ui-- > 0;) {
     332                 :        131 :                 size_t n0 = n;
     333                 :            :                 uint32_t loadcmdtype;
     334                 :            :                 uint32_t loadcmdsize;
     335         [ -  + ]:        131 :                 READ(u32, loadcmdtype);
     336         [ -  + ]:        131 :                 READ(u32, loadcmdsize);
     337                 :        131 :                 enum MachOLoadCommand loadcmd = loadcmdtype & ~LC_REQ_DYLD;
     338   [ -  +  +  +  :        131 :                 switch (loadcmd) {
             -  -  -  +  
                      - ]
     339                 :            :                 case LC_RPATH:
     340                 :            :                 case LC_LOAD_DYLINKER:;
     341                 :          6 :                         char *dylinker = 0;
     342   [ +  -  +  - ]:         12 :                         if ((x = read_path(fd, swap, loadcmdsize,
     343                 :          6 :                                         &dylinker)) < 0) {
     344                 :          0 :                                 goto cleanup;
     345                 :            :                         }
     346                 :          6 :                         n += x;
     347                 :          6 :                         pkg_debug(3, "load_dylinker %d: %s\n", loadcmd, dylinker);
     348                 :          6 :                         free(dylinker);
     349                 :         21 :                         break;
     350                 :            :                 case LC_ID_DYLIB:   // provides
     351                 :            :                 case LC_LOAD_DYLIB: // requires...
     352                 :            :                 case LC_LOAD_WEAK_DYLIB:
     353                 :            :                 case LC_REEXPORT_DYLIB:
     354                 :            :                 case LC_LAZY_LOAD_DYLIB:
     355                 :            :                 case LC_LOAD_UPWARD_DYLIB:;
     356                 :         15 :                         dylib_t *dylib = 0;
     357   [ +  -  +  - ]:         30 :                         if ((x = read_dylib(fd, swap, loadcmdsize,
     358                 :         15 :                                         &dylib)) < 0) {
     359                 :          0 :                                 goto cleanup;
     360                 :            :                         }
     361                 :         15 :                         n += x;
     362                 :            :                         // while under Darwin full path references are recommended and ubiquitous,
     363                 :            :                         // we align with pkg native environment and use only the basename
     364                 :            :                         // this also strips off any @executable_path, @loader_path, @rpath components
     365                 :         15 :                         const char * basename = strrchr(dylib->path, '/');
     366         [ +  - ]:         15 :                         basename = basename ? basename + 1 : dylib->path;
     367                 :         15 :                         pkg_debug(3,
     368                 :            :                                 "Adding dynamic library path: %s ts %"PRIu32" current(%"PRIuFAST16", %"PRIuFAST16", %"PRIuFAST16") compat(%"PRIuFAST16", %"PRIuFAST16", %"PRIuFAST16")\n",
     369                 :         15 :                                 dylib->path, dylib->timestamp,
     370                 :         15 :                                 dylib->current_version.major,
     371                 :         15 :                                 dylib->current_version.minor,
     372                 :         15 :                                 dylib->current_version.patch,
     373                 :         15 :                                 dylib->compatibility_version.major,
     374                 :         15 :                                 dylib->compatibility_version.minor,
     375                 :         15 :                                 dylib->compatibility_version.patch);
     376                 :            : 
     377                 :            :                         char *lib_with_version;
     378         [ +  + ]:         15 :                         if (dylib->current_version.patch) {
     379                 :          1 :                                 xasprintf(&lib_with_version, "%s-%"PRIuFAST16".%"PRIuFAST16".%"PRIuFAST16, basename, dylib->current_version.major, dylib->current_version.minor, dylib->current_version.patch);
     380                 :          1 :                         } else {
     381                 :         14 :                                 xasprintf(&lib_with_version, "%s-%"PRIuFAST16".%"PRIuFAST16, basename, dylib->current_version.major, dylib->current_version.minor);
     382                 :            :                         }
     383         [ +  + ]:         15 :                         if (LC_ID_DYLIB == loadcmd) {
     384                 :          3 :                                 pkg_addshlib_provided(pkg, lib_with_version, PKG_SHLIB_FLAGS_NONE);
     385                 :          3 :                         } else {
     386                 :         12 :                                 pkg_addshlib_required(pkg, lib_with_version, PKG_SHLIB_FLAGS_NONE);
     387                 :            :                         }
     388                 :         15 :                         free(lib_with_version);
     389                 :         15 :                         free(dylib);
     390                 :         15 :                         break;
     391                 :            :                 default:
     392                 :        110 :                         break;
     393                 :            :                 }
     394                 :        131 :                 const uint32_t fill = loadcmdsize - (n - n0);
     395   [ +  +  -  + ]:        131 :                 if (fill && -1 == (x = lseek(fd, fill, SEEK_CUR))) {
     396                 :          0 :                         goto cleanup;
     397                 :            :                 }
     398                 :        131 :                 n += fill;
     399         [ +  - ]:        131 :                 if (n > mh.sizeofcmds) {
     400                 :            :                         // we passed the frame boundary of the load commands
     401                 :          0 :                         pkg_emit_error("Mach-O structure misread.");
     402                 :          0 :                         errno = EINVAL;
     403                 :          0 :                         goto cleanup;
     404                 :            :                 }
     405                 :          9 :         }
     406                 :            : 
     407                 :            : cleanup:
     408                 :          9 :         free(mf);
     409                 :          9 :         return ret;
     410                 :          9 : }
     411                 :            : 
     412                 :            : int
     413                 :          9 : pkg_analyse_init_macho(__unused const char *stage)
     414                 :            : {
     415                 :          9 :         return EPKG_OK;
     416                 :            : }
     417                 :            : 
     418                 :            : int
     419                 :          9 : pkg_analyse_macho(const bool developer_mode, struct pkg *pkg, const char *fpath)
     420                 :            : {
     421                 :          9 :         int ret = EPKG_OK;
     422                 :          9 :         pkg_debug(1, "Analysing Mach-O %s", fpath);
     423                 :            : 
     424                 :          9 :         int fd = open(fpath, O_RDONLY);
     425         [ -  + ]:          9 :         if (-1 == fd) {
     426                 :            :                 // pkg_emit_errno("open_pkg_analyse_macho", fpath);
     427                 :            :                 // ret = EPKG_FATAL;
     428                 :            :                 // Be consistent with analyse_elf and return no error if fpath cannot be opened
     429                 :          0 :                 return ret;
     430                 :            :         } else {
     431                 :          9 :                 ret = analyse_macho(fd, pkg);
     432         [ +  - ]:          9 :                 if (-1 == close(fd)) {
     433                 :          0 :                         pkg_emit_errno("close_pkg_analyse_macho", fpath);
     434                 :          0 :                         ret = EPKG_FATAL;
     435                 :          0 :                 }
     436                 :            :         }
     437         [ +  - ]:          9 :         if (developer_mode) {
     438   [ #  #  #  # ]:          0 :                 if (ret != EPKG_OK && ret != EPKG_END) {
     439                 :          0 :                         return EPKG_WARN;
     440                 :            :                 }
     441                 :          0 :         }
     442                 :          9 :         return ret;
     443                 :          9 : }
     444                 :            : 
     445                 :            : int
     446                 :          9 : pkg_analyse_close_macho()
     447                 :            : {
     448                 :          9 :         return EPKG_OK;
     449                 :            : }

Generated by: LCOV version 1.15