this repo has no description
1/*
2This file is part of Darling.
3
4Copyright (C) 2018 Lubos Dolezel
5
6Darling is free software: you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
10
11Darling is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with Darling. If not, see <http://www.gnu.org/licenses/>.
18*/
19#include <stdio.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <sys/mman.h>
23#include <stdint.h>
24#include <stdbool.h>
25#include <stdlib.h>
26#include <mach-o/loader.h>
27#include <mach-o/fat.h>
28#include <string.h>
29#include <errno.h>
30
31bool printUuidAny(const void* mem);
32bool printUuidMH(const struct mach_header* mhdr);
33bool printUuidMH64(const struct mach_header_64* mhdr);
34bool printFat(const struct fat_header* fhdr);
35bool printTaf(const struct fat_header* fhdr);
36
37int main(int argc, const char** argv)
38{
39 if (argc != 2)
40 {
41 fprintf(stderr, "getuuid: Prints the UUID(s) of a Mach-O file, separated by semicolons (in case of fat files)\n");
42 fprintf(stderr, "Usage: getuuid <macho-file>\n");
43 return EXIT_FAILURE;
44 }
45
46 int fd = open(argv[1], O_RDONLY);
47 if (fd == -1)
48 {
49 fprintf(stderr, "Cannot open %s: %s", argv[1], strerror(errno));
50 return EXIT_FAILURE;
51 }
52
53 size_t length = lseek(fd, 0, SEEK_END);
54
55 void* mem = mmap(NULL, length, PROT_READ, MAP_SHARED, fd, 0);
56 if (mem == MAP_FAILED)
57 {
58 perror("mmap");
59 return EXIT_FAILURE;
60 }
61
62 close(fd);
63
64 int rv = EXIT_FAILURE;
65
66 if (printUuidAny(mem))
67 rv = EXIT_SUCCESS;
68
69 munmap(mem, length);
70
71 return rv;
72}
73
74bool printUuidAny(const void* mem)
75{
76 const struct mach_header* mhdr = (struct mach_header*) mem;
77
78 if (mhdr->magic == MH_MAGIC)
79 return printUuidMH(mhdr);
80 else if (mhdr->magic == MH_MAGIC_64)
81 return printUuidMH64((struct mach_header_64*) mhdr);
82 else if (mhdr->magic == FAT_MAGIC)
83 return printFat((struct fat_header*) mhdr);
84 else if (mhdr->magic == FAT_CIGAM)
85 return printTaf((struct fat_header*) mhdr);
86 else
87 {
88 fprintf(stderr, "File format not recognized\n");
89 exit(1);
90 }
91}
92
93bool printUuid(const struct load_command* lc)
94{
95 static bool hadUuid = false;
96 if (lc->cmd == LC_UUID)
97 {
98 const struct uuid_command* uuid = (const struct uuid_command*) lc;
99
100 if (hadUuid)
101 putchar(';');
102
103 printf("%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
104 uuid->uuid[0],
105 uuid->uuid[1],
106 uuid->uuid[2],
107 uuid->uuid[3],
108 uuid->uuid[4],
109 uuid->uuid[5],
110 uuid->uuid[6],
111 uuid->uuid[7],
112 uuid->uuid[8],
113 uuid->uuid[9],
114 uuid->uuid[10],
115 uuid->uuid[11],
116 uuid->uuid[12],
117 uuid->uuid[13],
118 uuid->uuid[14],
119 uuid->uuid[15]);
120
121 hadUuid = true;
122 return true;
123 }
124 return false;
125}
126
127bool printUuidMH(const struct mach_header* mhdr)
128{
129 const uint8_t* command = (const uint8_t*)(mhdr + 1);
130 for (uint32_t i = 0; i < mhdr->ncmds; i++)
131 {
132 if (printUuid((const struct load_command*) command))
133 return true;
134 else
135 command += ((const struct load_command*)command)->cmdsize;
136 }
137 return false;
138}
139
140bool printUuidMH64(const struct mach_header_64* mhdr)
141{
142 const uint8_t* command = (const uint8_t*)(mhdr + 1);
143 for (uint32_t i = 0; i < mhdr->ncmds; i++)
144 {
145 if (printUuid((const struct load_command*) command))
146 return true;
147 else
148 command += ((const struct load_command*)command)->cmdsize;
149 }
150 return false;
151}
152
153bool printFat(const struct fat_header* fhdr)
154{
155 const struct fat_arch* fa = ((const struct fat_arch*) (fhdr+1));
156 bool rv = false;
157
158 for (uint32_t i = 0; i < fhdr->nfat_arch; i++)
159 rv |= printUuidAny(((char*) fhdr) + fa[i].offset);
160
161 return rv;
162}
163
164bool printTaf(const struct fat_header* fhdr)
165{
166 const struct fat_arch* fa = ((const struct fat_arch*) (fhdr+1));
167 bool rv = false;
168
169 for (uint32_t i = 0; i < __builtin_bswap32(fhdr->nfat_arch); i++)
170 rv |= printUuidAny(((char*) fhdr) + __builtin_bswap32(fa[i].offset));
171
172 return rv;
173}
174