diff options
author | Mike Frysinger <vapier@gentoo.org> | 2005-11-02 04:23:21 +0000 |
---|---|---|
committer | Mike Frysinger <vapier@gentoo.org> | 2005-11-02 04:23:21 +0000 |
commit | f4971a01ffa9fbdcd3e89c7b425b9c5c9ab5280d (patch) | |
tree | 1d8b54a71b5a4a6874dbf4ad539cd697768137e1 /paxmacho.c | |
parent | - makefile update. last commit before 0.1.4 (diff) | |
download | pax-utils-f4971a01ffa9fbdcd3e89c7b425b9c5c9ab5280d.tar.gz pax-utils-f4971a01ffa9fbdcd3e89c7b425b9c5c9ab5280d.tar.bz2 pax-utils-f4971a01ffa9fbdcd3e89c7b425b9c5c9ab5280d.zip |
flesh out more of mach-o support (disabled for now)
Diffstat (limited to 'paxmacho.c')
-rw-r--r-- | paxmacho.c | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/paxmacho.c b/paxmacho.c new file mode 100644 index 0000000..59099a0 --- /dev/null +++ b/paxmacho.c @@ -0,0 +1,128 @@ +/* + * Copyright 2003-2005 Gentoo Foundation + * Distributed under the terms of the GNU General Public License v2 + * $Header: /var/cvsroot/gentoo-projects/pax-utils/paxmacho.c,v 1.1 2005/11/02 04:23:21 vapier Exp $ + * + * Copyright 2005 Ned Ludd - <solar@gentoo.org> + * Copyright 2005 Mike Frysinger - <vapier@gentoo.org> + */ + +#include <stdio.h> +#include <fcntl.h> +#include <sys/stat.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#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); +} |