changeset 2:747f68297ba5 default tip

add c language mach-O loader program. this program only analize, can't still load now.
author taiki <taiki@cr.ie.u-ryukyu.ac.jp>
date Tue, 04 Mar 2014 14:41:35 +0900
parents 1b796d0dd763
children
files Makefile mach-o-loader/Makefile mach-o-loader/loader.c mach-o-loader/loader.h sample/sample.c
diffstat 5 files changed, 306 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile	Tue Feb 05 15:26:25 2013 +0900
+++ b/Makefile	Tue Mar 04 14:41:35 2014 +0900
@@ -2,7 +2,7 @@
 
 TARGET = loader
 
-CFLAGES = -Wall -O0 -g -std=c99 -o
+CFLAGES = -Wall -O5 -std=c99 -o
 
 $(TARGET): loader.c
 	$(CC) $(CFLAGES) $(TARGET) loader.c 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mach-o-loader/Makefile	Tue Mar 04 14:41:35 2014 +0900
@@ -0,0 +1,12 @@
+TARGET = loader
+
+CC = clang
+
+CFLAGS = -g -O2 -Wall
+
+
+$(TARGET): loader.c
+	$(CC) $(CFLAGS) -o $@ $^
+
+clean:
+	rm $(TARGET) *.o
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mach-o-loader/loader.c	Tue Mar 04 14:41:35 2014 +0900
@@ -0,0 +1,282 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include <mach-o/loader.h>
+#include "loader.h"
+
+#define MAX_COMMAND_LEN 10000
+#define MAX_SECTION_LEN 10000
+
+int analyze(char* head)
+{
+    struct mach_header_64 *mh64 = (struct mach_header_64 *)head;
+
+    // mach header is 32 bytes
+    int com_index = sizeof(struct mach_header_64); 
+
+    for (int cmds = 0; cmds < mh64->ncmds; cmds++) {
+
+        struct load_command *com = (struct load_command *) (head + com_index);
+
+        switch(com->cmd) {
+            case LC_SEGMENT_64:
+            {
+                struct segment_command_64 *sc = 
+                    (struct segment_command_64 *) (head + com_index);
+                com_index += sizeof(struct segment_command_64);
+
+                printf("segment command:\n");
+                printf("\tcmd :%0xd \n", sc->cmd);
+                printf("\tcmdsize :%d \n", sc->cmdsize);
+                printf("\tsegname :%s \n", sc->segname);
+                printf("\tvmaddr :%0llx \n", sc->vmaddr);
+                printf("\tnsects :%d \n", sc->nsects);
+
+                int nsects = sc->nsects;
+                printf("sections:\n");
+                for (int sects = 0; sects < nsects; sects++) {
+                    struct section_64 *sc64 = (struct section_64*) (head + com_index);
+                    printf("\t%s\n", sc64->sectname);
+                    com_index += sizeof(struct section_64); 
+                }
+                break;
+            }
+            case LC_UUID:
+            {
+                struct uuid_command *uc = 
+                    (struct uuid_command*) (head + com_index);
+                com_index += sizeof(struct uuid_command);
+
+                printf("uuid command\n");
+                for(int i = 0; i < 16; i++) {
+                    printf("%u", uc->uuid[i]);
+                }
+                printf("\n");
+                break;
+            }
+            case LC_SYMTAB:
+            {
+                struct symtab_command *syt = 
+                    (struct symtab_command*) (head + com_index);
+                com_index += sizeof(struct symtab_command);
+
+                printf("symtab_command\n");
+                printf("\tsymoff %d\n", syt->symoff);
+                printf("\tnsyms %d\n", syt->nsyms);
+                break;
+            }
+            case LC_DYSYMTAB:
+            {
+                struct dysymtab_command *dysyt = 
+                    (struct dysymtab_command*) (head + com_index);
+                com_index += sizeof(struct dysymtab_command);
+
+                printf("dysymtab_command\n");
+                printf("symtab_command\n");
+                printf("\tsymoff %d\n", dysyt->cmd);
+                printf("\tnsyms %d\n", dysyt->cmdsize);
+                break;
+            }
+            case LC_THREAD:
+            {
+                printf("thread\n");
+                break;
+            }
+            case LC_UNIXTHREAD:
+            {
+                printf("unix thread\n");
+                break;
+            }
+            case LC_ID_DYLIB:
+            {
+                printf("unix thread\n");
+                break;
+            }
+            case LC_PREBOUND_DYLIB:
+            {
+                printf("unix thread\n");
+                break;
+            }
+            case LC_LOAD_DYLINKER:
+            {
+                struct dylinker_command *dylc = (struct dylinker_command *) (head + com_index);
+                printf("load dylinker\n");
+                printf("\tcmdsize: %d\n", dylc->cmdsize);
+                printf("\tdylc->name.offset: %d\n", dylc->name.offset);
+                char *name = (head + com_index) + sizeof(struct dylinker_command);
+                printf("\tname: %s\n", name);
+                com_index = com_index + dylc->cmdsize;
+                break;
+            }
+            case LC_ID_DYLINKER:
+            {
+                printf("id dylinker\n");
+                break;
+            }
+            case LC_ROUTINES:
+            {
+                printf("routines\n");
+                break;
+            }
+            case LC_ROUTINES_64:
+            {
+                printf("iroutines 64\n");
+                break;
+            }
+            case LC_TWOLEVEL_HINTS:
+            {
+                printf("two level hints\n");
+                break;
+            }
+            case LC_SUB_FRAMEWORK:
+            {
+                printf("sub framework\n");
+                break;
+            }
+            case LC_SUB_UMBRELLA:
+            {
+                printf("sub umbrella\n");
+                break;
+            }
+            case LC_SUB_LIBRARY:
+            {
+                printf("sub library\n");
+                break;
+            }
+            case LC_SUB_CLIENT:
+            {
+
+                printf("sub client\n");
+                break;
+            }
+            case LC_DYLD_INFO_ONLY:
+            {
+                struct dyld_info_command *dyldi_com = (struct dyld_info_command *) (head + com_index);
+                com_index += sizeof(struct dyld_info_command);
+                printf("dyld info only\n");
+                printf("\tcmdsize: %d\n", dyldi_com->cmdsize);
+                break;
+            }
+            case LC_VERSION_MIN_MACOSX:
+            {
+                struct version_min_command *vm_com = (struct version_min_command *) (head +  com_index);
+                com_index += sizeof(struct version_min_command); 
+                printf("version min macosx\n");
+                break;
+            }
+            case LC_SOURCE_VERSION:
+            {
+                struct source_version_command *sv_com = (struct source_version_command *) (head + com_index);
+                com_index += sizeof(struct source_version_command);
+                printf("source version\n");
+                break;
+            }
+            case LC_DATA_IN_CODE:
+            {
+                struct linkedit_data_command *ld_com = (struct linkedit_data_command*) (head + com_index);
+                com_index += sizeof(struct linkedit_data_command);
+                printf("data in code\n");
+                break;
+            }
+            case LC_DYLIB_CODE_SIGN_DRS:
+            {
+                printf("cylib code sign drs\n");
+                break;
+            }
+            case LC_LOAD_DYLIB:
+            {
+                struct dylib_command *dl_com = (struct dylib_command *) (head + com_index);
+                printf("lc load dylib\n");
+                int offset = dl_com->dylib.name.offset;
+                printf("\tname offset: %d\n",offset);
+                char *name = (head + com_index) + sizeof(struct dylib_command);
+                printf("\tname: %s\n", name);
+                com_index = com_index + dl_com->cmdsize;
+                break;
+            }
+            case LC_MAIN:
+            {
+                struct entry_point_command *ep_com = (struct entry_point_command *) (head + com_index);
+                com_index += sizeof(struct entry_point_command); 
+                printf("lc main\n");
+                break;
+            }
+            case LC_FUNCTION_STARTS:
+            {
+                struct linkedit_data_command *ld_com = (struct linkedit_data_command*) (head + com_index);
+                com_index += sizeof(struct linkedit_data_command);
+                printf("lc functions starts\n");
+                break;
+            }
+            default:
+                printf("no suitable cmd:%d\n", com->cmd);
+                break;
+        }
+    }
+    
+    return 0;
+}
+
+int check_header(int fp, struct stat sb, char* head)
+{
+    struct mach_header_64 *mh64 = (struct mach_header_64 *)head;
+    if (MH_MAGIC_64 != mh64->magic) {
+        fprintf(stderr, "This is no mach header 64.\n");
+        return -1;
+    }
+
+    if (MH_EXECUTE != mh64->filetype) {
+        fprintf(stderr, "This isn't executable file.\n");
+        return -1;
+    }
+
+    if (CPU_TYPE_X86_64 != mh64->cputype) {
+        fprintf(stderr, "No suitable cpu type.\n");
+        return -1;
+    }
+
+    printf("numbler of load commands : %d\n", mh64->ncmds);
+    printf("size of cmds : %d\n", mh64->sizeofcmds);
+
+    return 0;
+} 
+
+int main(int argc, char *argv[])
+{
+    
+    char *filename = argv[1];
+    int fp = 0;
+    
+    if ((fp = open(filename, O_RDONLY)) < 0) {
+        fprintf(stderr, "can not open file\t: %s\n", filename);
+        return -1;
+    }
+
+    struct stat sb;
+    if (fstat(fp, &sb) < 0) {
+        fprintf(stderr, "can not get stat\t: %s\n", filename);
+        return -1;
+    }
+
+    char *head = (char *)mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fp, 0);
+    if ((int)head < 0) {
+        fprintf(stderr, "can't map memory.\n"); 
+        return -1;
+    }
+
+    if (check_header(fp, sb, head) < 0) {
+        return -1;
+    }
+
+    analyze(head);
+
+    close(fp); /* close file */
+
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mach-o-loader/loader.h	Tue Mar 04 14:41:35 2014 +0900
@@ -0,0 +1,10 @@
+#ifndef LOADER
+#define LOADER
+
+struct mach_o_data {
+    int mh64_size;
+    int sc64_size;
+    int sect64_size;
+};
+
+#endif /* LOADER */
--- a/sample/sample.c	Tue Feb 05 15:26:25 2013 +0900
+++ b/sample/sample.c	Tue Mar 04 14:41:35 2014 +0900
@@ -5,4 +5,5 @@
     int c = 3;
 
     a = b + c;
+    a += c;
 }