this repo has no description
1/*
2This file is part of Darling.
3
4Copyright (C) 2018-2020 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 printElfdepAny(const void* mem);
32bool printElfdepMH(const struct mach_header* mhdr);
33bool printElfdepMH64(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, "elfdep: Prints the ELF dependency (SONAME) of a Mach-O file, if any\n");
42 fprintf(stderr, "Usage: elfdep <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 printElfdepAny(mem);
65
66 munmap(mem, length);
67
68 return EXIT_SUCCESS;
69}
70
71bool printElfdepAny(const void* mem)
72{
73 const struct mach_header* mhdr = (struct mach_header*) mem;
74
75 if (mhdr->magic == MH_MAGIC)
76 return printElfdepMH(mhdr);
77 else if (mhdr->magic == MH_MAGIC_64)
78 return printElfdepMH64((struct mach_header_64*) mhdr);
79 else if (mhdr->magic == FAT_MAGIC)
80 return printFat((struct fat_header*) mhdr);
81 else if (mhdr->magic == FAT_CIGAM)
82 return printTaf((struct fat_header*) mhdr);
83 else
84 {
85 fprintf(stderr, "File format not recognized\n");
86 exit(1);
87 }
88}
89
90bool printElfdep(const struct load_command* lc, const void* base)
91{
92 if (lc->cmd == LC_SEGMENT)
93 {
94 const struct segment_command* sc = (const struct segment_command*) lc;
95
96 if (strcmp(sc->segname, "__TEXT") == 0)
97 {
98 const struct section* sect = (const struct section*)(sc+1);
99 for (int i = 0; i < sc->nsects; i++)
100 {
101 if (strcmp(sect->sectname, "__elfname") == 0)
102 {
103 printf("%s\n", ((const char*)base) + sect->offset);
104 return true;
105 }
106 sect++;
107 }
108 }
109 }
110 else if (lc->cmd == LC_SEGMENT_64)
111 {
112 const struct segment_command_64* sc = (const struct segment_command_64*) lc;
113
114 if (strcmp(sc->segname, "__TEXT") == 0)
115 {
116 const struct section_64* sect = (const struct section_64*)(sc+1);
117 for (int i = 0; i < sc->nsects; i++)
118 {
119 if (strcmp(sect->sectname, "__elfname") == 0)
120 {
121 printf("%s\n", ((const char*)base) + sect->offset);
122 return true;
123 }
124 sect++;
125 }
126 }
127 }
128 return false;
129}
130
131bool printElfdepMH(const struct mach_header* mhdr)
132{
133 const uint8_t* command = (const uint8_t*)(mhdr + 1);
134 for (uint32_t i = 0; i < mhdr->ncmds; i++)
135 {
136 if (printElfdep((const struct load_command*) command, mhdr))
137 return true;
138 else
139 command += ((const struct load_command*)command)->cmdsize;
140 }
141 return false;
142}
143
144bool printElfdepMH64(const struct mach_header_64* mhdr)
145{
146 const uint8_t* command = (const uint8_t*)(mhdr + 1);
147 for (uint32_t i = 0; i < mhdr->ncmds; i++)
148 {
149 if (printElfdep((const struct load_command*) command, mhdr))
150 return true;
151 else
152 command += ((const struct load_command*)command)->cmdsize;
153 }
154 return false;
155}
156
157bool printFat(const struct fat_header* fhdr)
158{
159 const struct fat_arch* fa = ((const struct fat_arch*) (fhdr+1));
160
161 for (uint32_t i = 0; i < fhdr->nfat_arch; i++)
162 {
163 if (printElfdepAny(((char*) fhdr) + fa[i].offset))
164 return true;
165 }
166
167 return false;
168}
169
170bool printTaf(const struct fat_header* fhdr)
171{
172 const struct fat_arch* fa = ((const struct fat_arch*) (fhdr+1));
173
174 for (uint32_t i = 0; i < __builtin_bswap32(fhdr->nfat_arch); i++)
175 {
176 if (printElfdepAny(((char*) fhdr) + __builtin_bswap32(fa[i].offset)))
177 return true;
178 }
179
180 return false;
181}
182