1 |
commit: 8a389efbb1b504de7964ab093af1d528da7ebf3b |
2 |
Author: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
3 |
AuthorDate: Fri Jan 1 14:06:22 2021 +0000 |
4 |
Commit: Fabian Groffen <grobian <AT> gentoo <DOT> org> |
5 |
CommitDate: Fri Jan 1 14:06:22 2021 +0000 |
6 |
URL: https://gitweb.gentoo.org/proj/pax-utils.git/commit/?id=8a389efb |
7 |
|
8 |
scanmacho: add support for dumping UUIDs |
9 |
|
10 |
Add flag -U/--uuid to dump the object's UUID. |
11 |
|
12 |
(This is in particular useful when comparing against TextAPI stubs, |
13 |
.tbd files.) |
14 |
|
15 |
Signed-off-by: Fabian Groffen <grobian <AT> gentoo.org> |
16 |
|
17 |
macho.h | 6 ++++++ |
18 |
scanmacho.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++------ |
19 |
2 files changed, 56 insertions(+), 6 deletions(-) |
20 |
|
21 |
diff --git a/macho.h b/macho.h |
22 |
index 7457473..79da151 100644 |
23 |
--- a/macho.h |
24 |
+++ b/macho.h |
25 |
@@ -258,6 +258,12 @@ struct rpath_command { |
26 |
union lc_str path; |
27 |
}; |
28 |
|
29 |
+struct uuid_command { |
30 |
+ uint32_t cmd; |
31 |
+ uint32_t cmdsize; |
32 |
+ uint8_t uuid[16]; |
33 |
+}; |
34 |
+ |
35 |
struct fat_header |
36 |
{ |
37 |
uint32_t magic; |
38 |
|
39 |
diff --git a/scanmacho.c b/scanmacho.c |
40 |
index 71b1593..e2aa485 100644 |
41 |
--- a/scanmacho.c |
42 |
+++ b/scanmacho.c |
43 |
@@ -1,12 +1,12 @@ |
44 |
/* |
45 |
- * Copyright 2008-2012 Gentoo Foundation |
46 |
+ * Copyright 2008-2021 Gentoo Foundation |
47 |
* Distributed under the terms of the GNU General Public License v2 |
48 |
* |
49 |
* based on scanelf by: |
50 |
* Copyright 2003-2012 Ned Ludd - <solar@g.o> |
51 |
* Copyright 2004-2012 Mike Frysinger - <vapier@g.o> |
52 |
* for Darwin specific fun: |
53 |
- * 2008-2013 Fabian Groffen - <grobian@g.o> |
54 |
+ * 2008-2021 Fabian Groffen - <grobian@g.o> |
55 |
*/ |
56 |
|
57 |
const char argv0[] = "scanmacho"; |
58 |
@@ -37,6 +37,7 @@ static char show_rpath = 0; |
59 |
static char show_needed = 0; |
60 |
static char show_interp = 0; |
61 |
static char show_bind = 0; |
62 |
+static char show_uuid = 0; |
63 |
static char show_soname = 0; |
64 |
static char show_banner = 1; |
65 |
static char show_endian = 0; |
66 |
@@ -181,18 +182,54 @@ static char *macho_file_soname(fatobj *fobj, char *found_soname) |
67 |
return NULL; |
68 |
} |
69 |
|
70 |
+static char *macho_file_uuid(fatobj *fobj, char *found_uuid) |
71 |
+{ |
72 |
+ loadcmd *lcmd; |
73 |
+ uint32_t lc_uuid; |
74 |
+ static char uuid_buf[32 + 4 + 1]; |
75 |
+ |
76 |
+ if (!show_uuid) |
77 |
+ return NULL; |
78 |
+ |
79 |
+ lcmd = firstloadcmd(fobj); |
80 |
+ lc_uuid = MGET(fobj->swapped, LC_UUID); |
81 |
+ |
82 |
+ do { |
83 |
+ if (lcmd->lcmd->cmd == lc_uuid) { |
84 |
+ struct uuid_command *ucmd = lcmd->data; |
85 |
+ unsigned char *uuid; |
86 |
+ uuid = (unsigned char *)(ucmd->uuid); |
87 |
+ *found_uuid = 1; |
88 |
+ free(lcmd); |
89 |
+ if (be_wewy_wewy_quiet) |
90 |
+ return NULL; |
91 |
+ snprintf(uuid_buf, sizeof(uuid_buf), |
92 |
+ "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" |
93 |
+ "%02x%02x%02x%02x%02x%02x", |
94 |
+ uuid[0], uuid[1], uuid[2], uuid[3], |
95 |
+ uuid[4], uuid[5], |
96 |
+ uuid[6], uuid[7], |
97 |
+ uuid[8], uuid[9], |
98 |
+ uuid[10], uuid[11], uuid[12], uuid[13], uuid[14], uuid[15]); |
99 |
+ return uuid_buf; |
100 |
+ } |
101 |
+ } while (nextloadcmd(lcmd)); |
102 |
+ |
103 |
+ return NULL; |
104 |
+} |
105 |
+ |
106 |
/* scan a macho file and show all the fun stuff */ |
107 |
#define prints(str) ({ ssize_t ret = write(fileno(stdout), str, strlen(str)); ret; }) |
108 |
static int scanmacho_fatobj(fatobj *fobj) |
109 |
{ |
110 |
unsigned long i; |
111 |
char found_rpath, found_needed, found_interp, found_soname, |
112 |
- found_lib, found_file; |
113 |
+ found_lib, found_file, found_uuid; |
114 |
static char *out_buffer = NULL; |
115 |
static size_t out_len; |
116 |
|
117 |
found_rpath = found_needed = found_interp = found_soname = \ |
118 |
- found_lib = found_file = 0; |
119 |
+ found_lib = found_file = found_uuid = 0; |
120 |
|
121 |
if (be_verbose > 2) |
122 |
printf("%s: scanning file {%s,%s}\n", fobj->filename, |
123 |
@@ -228,6 +265,7 @@ static int scanmacho_fatobj(fatobj *fobj) |
124 |
case 'b': prints("FLAGS "); break; |
125 |
case 'Z': prints("SIZE "); break; |
126 |
case 'S': prints("INSTALLNAME "); break; |
127 |
+ case 'U': prints("UUID "); break; |
128 |
case 'N': prints("LIB "); break; |
129 |
case 'a': prints("ARCH "); break; |
130 |
case 'O': prints("PERM "); break; |
131 |
@@ -293,6 +331,7 @@ static int scanmacho_fatobj(fatobj *fobj) |
132 |
case 'i': out = macho_file_interp(fobj, &found_interp); break; |
133 |
case 'b': get_machomhflags(fobj, &out_buffer, &out_len); break; |
134 |
case 'S': out = macho_file_soname(fobj, &found_soname); break; |
135 |
+ case 'U': out = macho_file_uuid(fobj, &found_uuid); break; |
136 |
case 'a': out = get_machomtype(fobj); break; |
137 |
case 'Z': snprintf(ubuf, sizeof(ubuf), "%llu", (unsigned long long int)fobj->len); out = ubuf; break;; |
138 |
default: warnf("'%c' has no scan code?", out_format[i]); |
139 |
@@ -532,8 +571,8 @@ static void scanmacho_envpath(void) |
140 |
free(path); |
141 |
} |
142 |
|
143 |
-/* 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 */ |
144 |
-#define PARSE_FLAGS "pRmyArnibSN:gE:M:DO:ZaqvF:f:o:CBhV" |
145 |
+/* 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 */ |
146 |
+#define PARSE_FLAGS "pRmyArnibSUN:gE:M:DO:ZaqvF:f:o:CBhV" |
147 |
#define a_argument required_argument |
148 |
static struct option const long_opts[] = { |
149 |
{"path", no_argument, NULL, 'p'}, |
150 |
@@ -546,6 +585,7 @@ static struct option const long_opts[] = { |
151 |
{"interp", no_argument, NULL, 'i'}, |
152 |
{"bind", no_argument, NULL, 'b'}, |
153 |
{"soname", no_argument, NULL, 'S'}, |
154 |
+ {"uuid", no_argument, NULL, 'U'}, |
155 |
{"lib", a_argument, NULL, 'N'}, |
156 |
{"gmatch", no_argument, NULL, 'g'}, |
157 |
{"etype", a_argument, NULL, 'E'}, |
158 |
@@ -577,6 +617,7 @@ static const char * const opts_help[] = { |
159 |
"Print LC_LOAD_DYLINKER information (ELF: INTERP)", |
160 |
"Print flags from mach_header (ELF: BIND)", |
161 |
"Print LC_ID_DYLIB information (ELF: SONAME)", |
162 |
+ "Print LC_UUID information", |
163 |
"Find a specified library", |
164 |
"Use strncmp to match libraries. (use with -N)", |
165 |
"Print only Mach-O files matching mach_header\n" |
166 |
@@ -678,6 +719,7 @@ static int parseargs(int argc, char *argv[]) |
167 |
case 'i': show_interp = 1; break; |
168 |
case 'b': show_bind = 1; break; |
169 |
case 'S': show_soname = 1; break; |
170 |
+ case 'U': show_uuid = 1; break; |
171 |
case 'q': be_quiet = 1; break; |
172 |
case 'v': be_verbose = (be_verbose % 20) + 1; break; |
173 |
case 'a': show_perms = show_endian = show_bind = 1; break; |
174 |
@@ -717,6 +759,7 @@ static int parseargs(int argc, char *argv[]) |
175 |
case 'i': show_interp = 1; break; |
176 |
case 'b': show_bind = 1; break; |
177 |
case 'S': show_soname = 1; break; |
178 |
+ case 'U': show_uuid = 1; break; |
179 |
default: |
180 |
err("Invalid format specifier '%c' (byte %i)", |
181 |
out_format[i], i+1); |
182 |
@@ -738,6 +781,7 @@ static int parseargs(int argc, char *argv[]) |
183 |
if (show_interp) xstrcat(&out_format, "%i ", &fmt_len); |
184 |
if (show_bind) xstrcat(&out_format, "%b ", &fmt_len); |
185 |
if (show_soname) xstrcat(&out_format, "%S ", &fmt_len); |
186 |
+ if (show_uuid) xstrcat(&out_format, "%U ", &fmt_len); |
187 |
if (find_lib) xstrcat(&out_format, "%N ", &fmt_len); |
188 |
if (!be_quiet) xstrcat(&out_format, "%F ", &fmt_len); |
189 |
} |