Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

?

  • Loading branch information...
commit 99de68e25d201a936bcbded0471bb353083e6f66 1 parent bd29415
comex authored November 05, 2011
11  dyldcache/binary.c
@@ -4,15 +4,6 @@
4 4
 
5 5
 #define downcast(val, typ) ({ typeof(val) v = (val); typ t = (typ) v; if(t != v) die("out of range %s", #val); t; })
6 6
 
7  
-static const char *convert_lc_str(const struct load_command *cmd, union lc_str lcs) {
8  
-    const char *ret = ((const char *) cmd) + lcs.offset;
9  
-    size_t size = cmd->cmdsize - lcs.offset;
10  
-    if(lcs.offset >= cmd->cmdsize || strnlen(ret, size) == size) {
11  
-        die("bad lc_str");
12  
-    }
13  
-    return ret;
14  
-}
15  
-
16 7
 void b_prange_load_dyldcache(struct binary *binary, prange_t pr, const char *name) {
17 8
 #define _arg name
18 9
 
@@ -94,7 +85,7 @@ void b_dyldcache_load_macho(const struct binary *binary, const char *filename, s
94 85
             struct binary *p = out->reexports = malloc(out->nreexports * sizeof(struct binary));
95 86
             CMD_ITERATE(b_mach_hdr(out), cmd) {
96 87
                 if(cmd->cmd == LC_REEXPORT_DYLIB) {
97  
-                    const char *name = convert_lc_str(cmd, ((struct dylib_command *) cmd)->dylib.name);
  88
+                    const char *name = convert_lc_str(cmd, ((struct dylib_command *) cmd)->dylib.name.offset);
98 89
                     b_dyldcache_load_macho(binary, name, p);
99 90
                     p++;
100 91
                 }
12  mach-o/binary.c
@@ -153,7 +153,7 @@ void b_prange_load_macho_nosyms(struct binary *binary, prange_t pr, size_t offse
153 153
             die("fat file is empty");
154 154
         }
155 155
         
156  
-        prange_t fat_pr;
  156
+        prange_t fat_pr = {NULL, 0}; /* no, gcc, it won't be used uninitialized */
157 157
         int highest_score = 0;
158 158
         while(nfat_arch--) {
159 159
             int score = 0;
@@ -426,3 +426,13 @@ addr_t b_macho_reloc_base(const struct binary *binary) {
426 426
     }
427 427
     die("no segments");
428 428
 }
  429
+
  430
+const char *convert_lc_str(const struct load_command *cmd, uint32_t offset) {
  431
+    const char *ret = ((const char *) cmd) + offset;
  432
+    size_t size = cmd->cmdsize - offset;
  433
+    if(offset >= cmd->cmdsize || strnlen(ret, size) == size) {
  434
+        die("bad lc_str");
  435
+    }
  436
+    return ret;
  437
+}
  438
+
4  mach-o/binary.h
@@ -3,6 +3,8 @@
3 3
 
4 4
 #define CMD_ITERATE(hdr, cmd) for(struct load_command *cmd = (struct load_command *)((hdr) + 1), *end = (struct load_command *)((char *)(hdr + 1) + (hdr)->sizeofcmds); cmd < end; cmd = (struct load_command *)((char *)cmd + cmd->cmdsize))
5 5
 
  6
+struct load_command;
  7
+
6 8
 struct mach_binary {
7 9
     // this is unnecessary, don't use it
8 10
     struct mach_header *hdr;
@@ -46,5 +48,7 @@ addr_t b_macho_reloc_base(const struct binary *binary);
46 48
 
47 49
 #define b_pointer_size(binary) (sizeof(addr_t) == 4 ? (uint8_t) 4 : (binary)->pointer_size)
48 50
 
  51
+const char *convert_lc_str(const struct load_command *cmd, uint32_t offset);
  52
+
49 53
 __END_DECLS
50 54
 
95  mach-o/inject.c
@@ -18,7 +18,7 @@ addr_t b_allocate_vmaddr(const struct binary *binary) {
18 18
 }
19 19
 
20 20
 // this function is used by both b_macho_extend_cmds and b_inject_macho_binary
21  
-static void handle_retarded_dyld_info(void *ptr, uint32_t size, int num_segments, int num_dylibs, bool kill_dones) {
  21
+static void handle_retarded_dyld_info(void *ptr, uint32_t size, int num_segments, int *dylib_map, int num_dylib_map, bool kill_dones) {
22 22
     // seriously, take a look at dyldinfo.cpp from ld64, especially, in this case, the separate handing of different LC_DYLD_INFO sections and the different meaning of BIND_OPCODE_DONE in lazy bind vs the other binds
23 23
     // not to mention the impossibility of reading this data without knowing every single opcode
24 24
     // and the lack of nop
@@ -43,20 +43,35 @@ static void handle_retarded_dyld_info(void *ptr, uint32_t size, int num_segments
43 43
             break;
44 44
         }
45 45
         case BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
46  
-            if(immediate + num_dylibs > BIND_IMMEDIATE_MASK) {
47  
-                die("too many dylibs (imm)");
  46
+            if(dylib_map) {
  47
+                if(immediate == BIND_SPECIAL_DYLIB_SELF) break;
  48
+                if(immediate >= num_dylib_map) {
  49
+                    die("invalid dylib reference");
  50
+                }
  51
+                if(dylib_map[immediate] > BIND_IMMEDIATE_MASK) {
  52
+                    //die("too many dylibs (imm)");
  53
+                    *((uint8_t *) ptr - 1) = BIND_OPCODE_SET_DYLIB_SPECIAL_IMM | ;
  54
+
  55
+                } else {
  56
+                    *((uint8_t *) ptr - 1) = opcode | dylib_map[immediate];
  57
+                }
48 58
             }
49  
-            *((uint8_t *) ptr - 1) = opcode | (immediate + num_dylibs);
50 59
             break;
51  
-        case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: {
52  
-            uint8_t ordinal = read_int(&ptr, end, uint8_t);
53  
-            if(ordinal + num_dylibs > 0x7f) {
54  
-                die("too many dylibs (uleb)");
  60
+        case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
  61
+            if(dylib_map) {
  62
+                uint8_t ordinal = read_int(&ptr, end, uint8_t);
  63
+                if(ordinal == BIND_SPECIAL_DYLIB_SELF) break;
  64
+                if(ordinal >= num_dylib_map) {
  65
+                    die("invalid dylib reference");
  66
+                }
  67
+                if(dylib_map[ordinal] > 0x7f) {
  68
+                    die("too many dylibs (uleb)");
  69
+                }
  70
+                *((uint8_t *) ptr - 1) = dylib_map[ordinal];
  71
+            } else {
  72
+                read_uleb128(&ptr, end);
55 73
             }
56  
-            *((uint8_t *) ptr - 1) = ordinal + num_dylibs;
57 74
             break;
58  
-        }
59  
-
60 75
         // things we have to get through
61 76
         case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
62 77
             ptr += strnlen(ptr, end - ptr);
@@ -142,7 +157,7 @@ uint32_t b_macho_extend_cmds(struct binary *binary, size_t space) {
142 157
             X(dyl->export_off)
143 158
             #define Y(a) if(dyl->a##_off) { \
144 159
                 prange_t pr = rangeconv_off((range_t) {binary, dyl->a##_off, dyl->a##_size}, MUST_FIND); \
145  
-                handle_retarded_dyld_info(pr.start, pr.size, 1, 0, false); \
  160
+                handle_retarded_dyld_info(pr.start, pr.size, 1, NULL, 0, false); \
146 161
                 dyl->a##_off += stuff_size; \
147 162
             }
148 163
             Y(bind)
@@ -434,16 +449,20 @@ void b_inject_macho_binary(struct binary *target, const struct binary *binary, a
434 449
     }
435 450
 
436 451
     uint32_t init_ptrs[100];
437  
-    int num_init_ptrs = 0;
  452
+    unsigned num_init_ptrs = 0;
438 453
     uint32_t *reserved1s[100];
439  
-    int num_reserved1s = 0;
  454
+    unsigned num_reserved1s = 0;
440 455
     struct copy { ptrdiff_t off; void *start; size_t size; } copies[100];
441  
-    int num_copies = 0;
442  
-
443  
-    int num_segments, num_dylibs;
  456
+    unsigned num_copies = 0;
  457
+    // the names of the source's loaded dylibs
  458
+    const char *dylib_names[100];
  459
+    unsigned num_dylibs = 0;
  460
+    // dylib ordinal from target -> source
  461
+    int dylib_map[100] = {0};
  462
+    unsigned num_dylib_map = 1; // size of dylib_map
  463
+
  464
+    unsigned num_segments = 0;
444 465
     if(userland) {
445  
-        num_segments = 0;
446  
-        num_dylibs = 0;
447 466
         CMD_ITERATE(hdr, cmd) {
448 467
             switch(cmd->cmd) {
449 468
             case LC_SEGMENT: {
@@ -469,7 +488,7 @@ void b_inject_macho_binary(struct binary *target, const struct binary *binary, a
469 488
                 break;
470 489
             }
471 490
             case LC_LOAD_DYLIB:
472  
-                num_dylibs++;
  491
+                if(num_dylibs < 100) dylib_names[num_dylibs++] = convert_lc_str(cmd, ((struct dylib_command *) cmd)->dylib.name.offset);
473 492
                 break;
474 493
             }
475 494
         }
@@ -513,9 +532,22 @@ void b_inject_macho_binary(struct binary *target, const struct binary *binary, a
513 532
         }
514 533
         case LC_LOAD_DYLIB:
515 534
             if(userland) {
  535
+                unsigned int targetlib;
  536
+                const char *name = convert_lc_str(cmd, ((struct dylib_command *) cmd)->dylib.name.offset);
  537
+                for(targetlib = 0; targetlib < num_dylibs; targetlib++) {
  538
+                    if(!strcmp(name, dylib_names[targetlib])) {
  539
+                        goto ok;
  540
+                    }
  541
+                }
  542
+
  543
+                // otherwise, we have to add a new LC
  544
+                
516 545
                 void *newcmd = ADD_COMMAND(cmd->cmdsize);
517 546
                 memcpy(newcmd, cmd, cmd->cmdsize);
518  
-                
  547
+                num_dylibs++;
  548
+
  549
+                ok:
  550
+                if(num_dylib_map < 100) dylib_map[num_dylib_map++] = targetlib + 1;
519 551
             }
520 552
             break;
521 553
         }
@@ -577,7 +609,7 @@ void b_inject_macho_binary(struct binary *target, const struct binary *binary, a
577 609
         newseg->flags = 0;
578 610
 
579 611
         void *ptr = malloc(stub_size);
580  
-        for(int i = 0; i < num_init_ptrs; i++) {
  612
+        for(unsigned i = 0; i < num_init_ptrs; i++) {
581 613
             memcpy(ptr, part1, sizeof(part1));
582 614
             ptr += sizeof(part1);
583 615
             memcpy(ptr, &init_ptrs[i], 4);
@@ -671,18 +703,23 @@ void b_inject_macho_binary(struct binary *target, const struct binary *binary, a
671 703
             {
672 704
                 struct moveme *restrict m = &li[0].moveme[MM_UNDEFSYM];
673 705
                 for(struct nlist *nl = m->copied_to; (void *) (nl + 1) <= (m->copied_to + m->copied_size); nl++) {
674  
-                    uint16_t lib = GET_LIBRARY_ORDINAL(nl->n_desc);
  706
+                    unsigned lib = GET_LIBRARY_ORDINAL(nl->n_desc);
675 707
                     if(lib != SELF_LIBRARY_ORDINAL && lib <= MAX_LIBRARY_ORDINAL) {
676  
-                        if(lib + num_dylibs > MAX_LIBRARY_ORDINAL) {
677  
-                            die("too many libraries5");
  708
+
  709
+                        if(lib >= num_dylib_map) {
  710
+                            die("invalid dylib reference");
  711
+                        }
  712
+                        unsigned new = dylib_map[lib];
  713
+                        if(new > MAX_LIBRARY_ORDINAL) {
  714
+                            die("too many libraries");
678 715
                         }
679  
-                        SET_LIBRARY_ORDINAL(nl->n_desc, lib + num_dylibs);
  716
+                        SET_LIBRARY_ORDINAL(nl->n_desc, new + 1);
680 717
                     }
681 718
                 }
682 719
             }
683 720
 
684 721
             // ... and update section references
685  
-            for(int i = 0; i < num_reserved1s; i++) {
  722
+            for(unsigned i = 0; i < num_reserved1s; i++) {
686 723
                 *reserved1s[i] += *li[0].moveme[MM_INDIRECT].size;
687 724
             }
688 725
 
@@ -690,7 +727,7 @@ void b_inject_macho_binary(struct binary *target, const struct binary *binary, a
690 727
             if(li->dyld_info) {
691 728
                 for(int i = MM_BIND; i <= MM_LAZY_BIND; i++) {
692 729
                     if(*li[1].moveme[i].off) {
693  
-                        handle_retarded_dyld_info(linkedit - linkedit_off + *li[1].moveme[i].off, *li[0].moveme[i].size, num_segments, num_dylibs, i != MM_LAZY_BIND);
  730
+                        handle_retarded_dyld_info(linkedit - linkedit_off + *li[1].moveme[i].off, *li[0].moveme[i].size, num_segments, dylib_map, num_dylib_map, i != MM_LAZY_BIND);
694 731
                     }
695 732
                 }
696 733
             }
@@ -716,7 +753,7 @@ void b_inject_macho_binary(struct binary *target, const struct binary *binary, a
716 753
 
717 754
     // finally, expand the binary in memory and actually copy in the new stuff
718 755
     target->valid_range = pdup(target->valid_range, seg_off, 0);
719  
-    for(int i = 0; i < num_copies; i++) {
  756
+    for(unsigned i = 0; i < num_copies; i++) {
720 757
         memcpy(target->valid_range.start + copies[i].off, copies[i].start, copies[i].size);
721 758
     }
722 759
 }
2  mach-o/link.c
@@ -167,7 +167,7 @@ static void do_bind_section(struct binary *load, const struct binary *target, bo

0 notes on commit 99de68e

Please sign in to comment.
Something went wrong with that request. Please try again.