1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
|
/*
* Copyright 2003-2006 Gentoo Foundation
* Distributed under the terms of the GNU General Public License v2
* $Header: /var/cvsroot/gentoo-projects/pax-utils/paxmacho.c,v 1.2 2006/01/05 03:12:07 vapier Exp $
*
* Copyright 2005-2006 Ned Ludd - <solar@gentoo.org>
* Copyright 2005-2006 Mike Frysinger - <vapier@gentoo.org>
*/
#include "paxinc.h"
#define argv0 "paxmacho"
/*
* Setup a bunch of helper functions to translate
* binary defines into readable strings.
*/
#define QUERY(n) { #n, n }
typedef struct {
const char *str;
int value;
} pairtype;
static inline const char *find_pairtype(pairtype *pt, int type)
{
int i;
for (i = 0; pt[i].str; ++i)
if (type == pt[i].value)
return pt[i].str;
return "UNKNOWN TYPE";
}
/* translate misc mach-o MH_ defines */
static pairtype macho_mh_type[] = {
QUERY(MH_OBJECT),
QUERY(MH_EXECUTE),
QUERY(MH_BUNDLE),
QUERY(MH_DYLIB),
QUERY(MH_PRELOAD),
QUERY(MH_CORE),
QUERY(MH_DYLINKER),
{ 0, 0 }
};
const char *get_machomhtype(int mh_type)
{
return find_pairtype(macho_mh_type, mh_type);
}
/* Read a macho into memory */
#define IS_MACHO_MAGIC(m) \
(m == MH_MAGIC || m == MH_CIGAM || \
m == MH_MAGIC_64 || m == MH_CIGAM_64)
#define DO_WE_LIKE_MACHO(buff) 1
machoobj *readmacho(const char *filename)
{
struct stat st;
int fd;
machoobj *macho;
struct mach_header *mhdr;
if (stat(filename, &st) == -1)
return NULL;
if ((fd = open(filename, O_RDONLY)) == -1)
return NULL;
/* make sure we have enough bytes to scan e_ident */
if (st.st_size <= sizeof(struct mach_header))
goto close_fd_and_return;
macho = (machoobj*)malloc(sizeof(*macho));
if (macho == NULL)
goto close_fd_and_return;
memset(macho, 0x00, sizeof(*macho));
macho->fd = fd;
macho->len = st.st_size;
macho->data = (char*)mmap(0, macho->len, PROT_READ, MAP_PRIVATE, fd, 0);
if (macho->data == (char*)MAP_FAILED) {
warn("mmap on '%s' of %li bytes failed :(", filename, (unsigned long)macho->len);
goto free_macho_and_return;
}
mhdr = (struct mach_header*)macho->data;
do_reverse_endian = (mhdr->magic == MH_CIGAM || mhdr->magic == MH_CIGAM_64);
macho->macho_class = (EGET(mhdr->magic) == MH_MAGIC ? MH_MAGIC : MH_MAGIC_64);
if (!IS_MACHO_MAGIC(mhdr->magic)) /* make sure we have an macho */
goto unmap_data_and_return;
if (1 || !DO_WE_LIKE_MACHO(mhdr)) { /* check class and stuff */
warn("we no likey %s: {%i:%s}",
filename,
(int)EGET(mhdr->filetype), get_machomhtype(EGET(mhdr->filetype)));
goto unmap_data_and_return;
}
macho->filename = filename;
macho->base_filename = strrchr(filename, '/');
if (macho->base_filename == NULL)
macho->base_filename = macho->filename;
else
macho->base_filename = macho->base_filename + 1;
macho->mhdr = (void*)macho->data;
return macho;
unmap_data_and_return:
munmap(macho->data, macho->len);
free_macho_and_return:
free(macho);
close_fd_and_return:
close(fd);
return NULL;
}
/* undo the readmacho() stuff */
void unreadmacho(machoobj *macho)
{
munmap(macho->data, macho->len);
close(macho->fd);
free(macho);
}
|