commit:     8a389efbb1b504de7964ab093af1d528da7ebf3b
Author:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
AuthorDate: Fri Jan  1 14:06:22 2021 +0000
Commit:     Fabian Groffen <grobian <AT> gentoo <DOT> org>
CommitDate: Fri Jan  1 14:06:22 2021 +0000
URL:        https://gitweb.gentoo.org/proj/pax-utils.git/commit/?id=8a389efb

scanmacho: add support for dumping UUIDs

Add flag -U/--uuid to dump the object's UUID.

(This is in particular useful when comparing against TextAPI stubs,
.tbd files.)

Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org>

 macho.h     |  6 ++++++
 scanmacho.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------
 2 files changed, 56 insertions(+), 6 deletions(-)

diff --git a/macho.h b/macho.h
index 7457473..79da151 100644
--- a/macho.h
+++ b/macho.h
@@ -258,6 +258,12 @@ struct rpath_command {
     union lc_str path;
 };
 
+struct uuid_command {
+    uint32_t cmd;
+    uint32_t cmdsize;
+    uint8_t uuid[16];
+};
+
 struct fat_header
 {
        uint32_t magic;

diff --git a/scanmacho.c b/scanmacho.c
index 71b1593..e2aa485 100644
--- a/scanmacho.c
+++ b/scanmacho.c
@@ -1,12 +1,12 @@
 /*
- * Copyright 2008-2012 Gentoo Foundation
+ * Copyright 2008-2021 Gentoo Foundation
  * Distributed under the terms of the GNU General Public License v2
  *
  * based on scanelf by:
  * Copyright 2003-2012 Ned Ludd        - <[email protected]>
  * Copyright 2004-2012 Mike Frysinger  - <[email protected]>
  * for Darwin specific fun:
- *           2008-2013 Fabian Groffen  - <[email protected]>
+ *           2008-2021 Fabian Groffen  - <[email protected]>
  */
 
 const char argv0[] = "scanmacho";
@@ -37,6 +37,7 @@ static char show_rpath = 0;
 static char show_needed = 0;
 static char show_interp = 0;
 static char show_bind = 0;
+static char show_uuid = 0;
 static char show_soname = 0;
 static char show_banner = 1;
 static char show_endian = 0;
@@ -181,18 +182,54 @@ static char *macho_file_soname(fatobj *fobj, char 
*found_soname)
        return NULL;
 }
 
+static char *macho_file_uuid(fatobj *fobj, char *found_uuid)
+{
+       loadcmd *lcmd;
+       uint32_t lc_uuid;
+       static char uuid_buf[32 + 4 + 1];
+
+       if (!show_uuid)
+               return NULL;
+
+       lcmd = firstloadcmd(fobj);
+       lc_uuid = MGET(fobj->swapped, LC_UUID);
+
+       do {
+               if (lcmd->lcmd->cmd == lc_uuid) {
+                       struct uuid_command *ucmd = lcmd->data;
+                       unsigned char *uuid;
+                       uuid = (unsigned char *)(ucmd->uuid);
+                       *found_uuid = 1;
+                       free(lcmd);
+                       if (be_wewy_wewy_quiet)
+                               return NULL;
+                       snprintf(uuid_buf, sizeof(uuid_buf),
+                                       
"%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-"
+                                       "%02x%02x%02x%02x%02x%02x",
+                                       uuid[0], uuid[1], uuid[2], uuid[3],
+                                       uuid[4], uuid[5],
+                                       uuid[6], uuid[7],
+                                       uuid[8], uuid[9],
+                                       uuid[10], uuid[11], uuid[12], uuid[13], 
uuid[14], uuid[15]);
+                       return uuid_buf;
+               }
+       } while (nextloadcmd(lcmd));
+
+       return NULL;
+}
+
 /* scan a macho file and show all the fun stuff */
 #define prints(str) ({ ssize_t ret = write(fileno(stdout), str, strlen(str)); 
ret; })
 static int scanmacho_fatobj(fatobj *fobj)
 {
        unsigned long i;
        char found_rpath, found_needed, found_interp, found_soname,
-                found_lib, found_file;
+                found_lib, found_file, found_uuid;
        static char *out_buffer = NULL;
        static size_t out_len;
 
        found_rpath = found_needed = found_interp = found_soname = \
-       found_lib = found_file = 0;
+       found_lib = found_file = found_uuid = 0;
 
        if (be_verbose > 2)
                printf("%s: scanning file {%s,%s}\n", fobj->filename,
@@ -228,6 +265,7 @@ static int scanmacho_fatobj(fatobj *fobj)
                        case 'b': prints("FLAGS "); break;
                        case 'Z': prints("SIZE "); break;
                        case 'S': prints("INSTALLNAME "); break;
+                       case 'U': prints("UUID "); break;
                        case 'N': prints("LIB "); break;
                        case 'a': prints("ARCH "); break;
                        case 'O': prints("PERM "); break;
@@ -293,6 +331,7 @@ static int scanmacho_fatobj(fatobj *fobj)
                case 'i': out = macho_file_interp(fobj, &found_interp); break;
                case 'b': get_machomhflags(fobj, &out_buffer, &out_len); break;
                case 'S': out = macho_file_soname(fobj, &found_soname); break;
+               case 'U': out = macho_file_uuid(fobj, &found_uuid); break;
                case 'a': out = get_machomtype(fobj); break;
                case 'Z': snprintf(ubuf, sizeof(ubuf), "%llu", (unsigned long 
long int)fobj->len); out = ubuf; break;;
                default: warnf("'%c' has no scan code?", out_format[i]);
@@ -532,8 +571,8 @@ static void scanmacho_envpath(void)
        free(path);
 }
 
-/* usage / invocation handling functions */ /* Free Flags: c d e j k l s t u w 
x z G H I J K L P Q T U W X Y */
-#define PARSE_FLAGS "pRmyArnibSN:gE:M:DO:ZaqvF:f:o:CBhV"
+/* usage / invocation handling functions */ /* Free Flags: c d e j k l s t u w 
x z G H I J K L P Q T W X Y */
+#define PARSE_FLAGS "pRmyArnibSUN:gE:M:DO:ZaqvF:f:o:CBhV"
 #define a_argument required_argument
 static struct option const long_opts[] = {
        {"path",      no_argument, NULL, 'p'},
@@ -546,6 +585,7 @@ static struct option const long_opts[] = {
        {"interp",    no_argument, NULL, 'i'},
        {"bind",      no_argument, NULL, 'b'},
        {"soname",    no_argument, NULL, 'S'},
+       {"uuid",      no_argument, NULL, 'U'},
        {"lib",        a_argument, NULL, 'N'},
        {"gmatch",    no_argument, NULL, 'g'},
        {"etype",      a_argument, NULL, 'E'},
@@ -577,6 +617,7 @@ static const char * const opts_help[] = {
        "Print LC_LOAD_DYLINKER information (ELF: INTERP)",
        "Print flags from mach_header (ELF: BIND)",
        "Print LC_ID_DYLIB information (ELF: SONAME)",
+       "Print LC_UUID information",
        "Find a specified library",
        "Use strncmp to match libraries. (use with -N)",
        "Print only Mach-O files matching mach_header\n"
@@ -678,6 +719,7 @@ static int parseargs(int argc, char *argv[])
                case 'i': show_interp = 1; break;
                case 'b': show_bind = 1; break;
                case 'S': show_soname = 1; break;
+               case 'U': show_uuid = 1; break;
                case 'q': be_quiet = 1; break;
                case 'v': be_verbose = (be_verbose % 20) + 1; break;
                case 'a': show_perms = show_endian = show_bind = 1; break;
@@ -717,6 +759,7 @@ static int parseargs(int argc, char *argv[])
                        case 'i': show_interp = 1; break;
                        case 'b': show_bind = 1; break;
                        case 'S': show_soname = 1; break;
+                       case 'U': show_uuid = 1; break;
                        default:
                                err("Invalid format specifier '%c' (byte %i)",
                                    out_format[i], i+1);
@@ -738,6 +781,7 @@ static int parseargs(int argc, char *argv[])
                if (show_interp)   xstrcat(&out_format, "%i ", &fmt_len);
                if (show_bind)     xstrcat(&out_format, "%b ", &fmt_len);
                if (show_soname)   xstrcat(&out_format, "%S ", &fmt_len);
+               if (show_uuid)     xstrcat(&out_format, "%U ", &fmt_len);
                if (find_lib)      xstrcat(&out_format, "%N ", &fmt_len);
                if (!be_quiet)     xstrcat(&out_format, "%F ", &fmt_len);
        }

Reply via email to