Issue18826 fix (#35137)
authormonojenkins <jo.shields+jenkins@xamarin.com>
Thu, 27 Aug 2020 15:38:44 +0000 (11:38 -0400)
committerGitHub <noreply@github.com>
Thu, 27 Aug 2020 15:38:44 +0000 (11:38 -0400)
<!--
Thank you for your Pull Request!

If you are new to contributing to Mono, please try to do your best at conforming to our coding guidelines http://www.mono-project.com/community/contributing/coding-guidelines/ but don't worry if you get something wrong. One of the project members will help you to get things landed.

Does your pull request fix any of the existing issues? Please use the following format: Fixes #issue-number
-->

Fixes mono/mono#18826

Co-authored-by: HinTak <HinTak@users.noreply.github.com>
src/mono/mono/mini/main.c

index b857ec3..7cc3fec 100644 (file)
@@ -35,6 +35,9 @@
 #    include "buildver-boehm.h"
 #  endif
 #endif
+#ifdef TARGET_OSX
+#include <mach-o/loader.h>
+#endif
 
 //#define TEST_ICALL_SYMBOL_MAP 1
 
@@ -179,8 +182,68 @@ probe_embedded (const char *program, int *ref_argc, char **ref_argv [])
                goto doclose;
        if (read (fd, sigbuffer, sizeof (sigbuffer)) == -1)
                goto doclose;
-       if (memcmp (sigbuffer+sizeof(uint64_t), "xmonkeysloveplay", 16) != 0)
-               goto doclose;
+       // First, see if "xmonkeysloveplay" is at the end of file
+       if (memcmp (sigbuffer + sizeof (uint64_t), "xmonkeysloveplay", 16) == 0)
+               goto found;
+
+#ifdef TARGET_OSX
+       {
+               /*
+                * If "xmonkeysloveplay" is not at the end of file,
+                * on Mac OS X, we try a little harder, by actually
+                * reading the binary's header structure, to see
+                * if it is located at the end of a LC_SYMTAB section.
+                *
+                * This is because Apple code-signing appends a
+                * LC_CODE_SIGNATURE section to the binary, so
+                * for a signed binary, "xmonkeysloveplay" is no
+                * longer at the end of file.
+                *
+                * The rest is sanity-checks for the header and section structures.
+                */
+               struct mach_header_64 bin_header;
+               if ((sigstart = lseek (fd, 0, SEEK_SET)) == -1)
+                       goto doclose;
+               // Find and check binary header
+               if (read (fd, &bin_header, sizeof (bin_header)) == -1)
+                       goto doclose;
+               if (bin_header.magic != MH_MAGIC_64)
+                       goto doclose;
+
+               off_t total = bin_header.sizeofcmds;
+               uint32_t count = bin_header.ncmds;
+               while (total > 0 && count > 0) {
+                       struct load_command lc;
+                       off_t sig_stored = lseek (fd, 0, SEEK_CUR); // get current offset
+                       if (read (fd, &lc, sizeof (lc)) == -1)
+                               goto doclose;
+                       if (lc.cmd == LC_SYMTAB) {
+                               struct symtab_command stc;
+                               if ((sigstart = lseek (fd, -sizeof (lc), SEEK_CUR)) == -1)
+                                       goto doclose;
+                               if (read (fd, &stc, sizeof (stc)) == -1)
+                                       goto doclose;
+
+                               // Check the end of the LC_SYMTAB section for "xmonkeysloveplay"
+                               if ((sigstart = lseek (fd, -(16 + sizeof (uint64_t)) + stc.stroff + stc.strsize, SEEK_SET)) == -1)
+                                       goto doclose;
+                               if (read (fd, sigbuffer, sizeof (sigbuffer)) == -1)
+                                       goto doclose;
+                               if (memcmp (sigbuffer + sizeof (uint64_t), "xmonkeysloveplay", 16) == 0)
+                                       goto found;
+                       }
+                       if ((sigstart = lseek (fd, sig_stored + lc.cmdsize, SEEK_SET)) == -1)
+                               goto doclose;
+                       total -= sizeof (lc.cmdsize);
+                       count--;
+               }
+       }
+#endif
+
+       // did not find "xmonkeysloveplay" at end of file or end of LC_SYMTAB section
+       goto doclose;
+
+found:
        directory_location = GUINT64_FROM_LE ((*(uint64_t *) &sigbuffer [0]));
        if (lseek (fd, directory_location, SEEK_SET) == -1)
                goto doclose;