1 /* ldid - (Mach-O) Link-Loader Identity Editor 
   2  * Copyright (C) 2007-2012  Jay Freeman (saurik) 
   5 /* GNU Affero General Public License, Version 3 {{{ */ 
   7  * This program is free software: you can redistribute it and/or modify 
   8  * it under the terms of the GNU Affero General Public License as published by 
   9  * the Free Software Foundation, either version 3 of the License, or 
  10  * (at your option) any later version. 
  12  * This program is distributed in the hope that it will be useful, 
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
  15  * GNU Affero General Public License for more details. 
  17  * You should have received a copy of the GNU Affero General Public License 
  18  * along with this program.  If not, see <http://www.gnu.org/licenses/>. 
  22 #include "minimal/stdlib.h" 
  23 #include "minimal/string.h" 
  24 #include "minimal/mapping.h" 
  30 #include <openssl/sha.h> 
  32 #include <plist/plist.h> 
  39 #define FAT_MAGIC 0xcafebabe 
  40 #define FAT_CIGAM 0xbebafeca 
  60 #define MH_MAGIC 0xfeedface 
  61 #define MH_CIGAM 0xcefaedfe 
  63 #define MH_MAGIC_64 0xfeedfacf 
  64 #define MH_CIGAM_64 0xcffaedfe 
  66 #define MH_DYLDLINK   0x4 
  69 #define MH_EXECUTE    0x2 
  72 #define MH_DYLIB_STUB 0x9 
  79 #define LC_REQ_DYLD           uint32_t(0x80000000) 
  81 #define LC_SEGMENT            uint32_t(0x01) 
  82 #define LC_SYMTAB             uint32_t(0x02) 
  83 #define LC_DYSYMTAB           uint32_t(0x0b) 
  84 #define LC_LOAD_DYLIB         uint32_t(0x0c) 
  85 #define LC_ID_DYLIB           uint32_t(0x0d) 
  86 #define LC_SEGMENT_64         uint32_t(0x19) 
  87 #define LC_UUID               uint32_t(0x1b) 
  88 #define LC_CODE_SIGNATURE     uint32_t(0x1d) 
  89 #define LC_SEGMENT_SPLIT_INFO uint32_t(0x1e) 
  90 #define LC_REEXPORT_DYLIB     uint32_t(0x1f | LC_REQ_DYLD) 
  91 #define LC_ENCRYPTION_INFO    uint32_t(0x21) 
  92 #define LC_DYLD_INFO          uint32_t(0x22) 
  93 #define LC_DYLD_INFO_ONLY     uint32_t(0x22 | LC_REQ_DYLD) 
  98     uint32_t current_version
; 
  99     uint32_t compatibility_version
; 
 102 struct dylib_command 
{ 
 108 struct uuid_command 
{ 
 114 struct symtab_command 
{ 
 123 struct dyld_info_command 
{ 
 127     uint32_t rebase_size
; 
 130     uint32_t weak_bind_off
; 
 131     uint32_t weak_bind_size
; 
 132     uint32_t lazy_bind_off
; 
 133     uint32_t lazy_bind_size
; 
 135     uint32_t export_size
; 
 138 struct dysymtab_command 
{ 
 151     uint32_t extrefsymoff
; 
 152     uint32_t nextrefsyms
; 
 153     uint32_t indirectsymoff
; 
 154     uint32_t nindirectsyms
; 
 161 struct dylib_table_of_contents 
{ 
 162     uint32_t symbol_index
; 
 163     uint32_t module_index
; 
 166 struct dylib_module 
{ 
 167     uint32_t module_name
; 
 176     uint32_t iinit_iterm
; 
 177     uint32_t ninit_nterm
; 
 178     uint32_t objc_module_info_addr
; 
 179     uint32_t objc_module_info_size
; 
 182 struct dylib_reference 
{ 
 187 struct relocation_info 
{ 
 189     uint32_t r_symbolnum
:24; 
 208 struct segment_command 
{ 
 222 struct segment_command_64 
{ 
 264 struct linkedit_data_command 
{ 
 271 struct encryption_info_command 
{ 
 279 #define BIND_OPCODE_MASK                             0xf0 
 280 #define BIND_IMMEDIATE_MASK                          0x0f 
 281 #define BIND_OPCODE_DONE                             0x00 
 282 #define BIND_OPCODE_SET_DYLIB_ORDINAL_IMM            0x10 
 283 #define BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB           0x20 
 284 #define BIND_OPCODE_SET_DYLIB_SPECIAL_IMM            0x30 
 285 #define BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM    0x40 
 286 #define BIND_OPCODE_SET_TYPE_IMM                     0x50 
 287 #define BIND_OPCODE_SET_ADDEND_SLEB                  0x60 
 288 #define BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB      0x70 
 289 #define BIND_OPCODE_ADD_ADDR_ULEB                    0x80 
 290 #define BIND_OPCODE_DO_BIND                          0x90 
 291 #define BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB            0xa0 
 292 #define BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED      0xb0 
 293 #define BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB 0xc0 
 295 template <typename Type_
> 
 296 Type_ 
Align(Type_ value
, size_t align
) { 
 303 uint16_t Swap_(uint16_t value
) { 
 305         ((value 
>>  8) & 0x00ff) | 
 306         ((value 
<<  8) & 0xff00); 
 309 uint32_t Swap_(uint32_t value
) { 
 310     value 
= ((value 
>>  8) & 0x00ff00ff) | 
 311             ((value 
<<  8) & 0xff00ff00); 
 312     value 
= ((value 
>> 16) & 0x0000ffff) | 
 313             ((value 
<< 16) & 0xffff0000); 
 317 uint64_t Swap_(uint64_t value
) { 
 318     value 
= (value 
& 0x00000000ffffffff) << 32 | (value 
& 0xffffffff00000000) >> 32; 
 319     value 
= (value 
& 0x0000ffff0000ffff) << 16 | (value 
& 0xffff0000ffff0000) >> 16; 
 320     value 
= (value 
& 0x00ff00ff00ff00ff) << 8  | (value 
& 0xff00ff00ff00ff00) >> 8; 
 324 int16_t Swap_(int16_t value
) { 
 325     return Swap_(static_cast<uint16_t>(value
)); 
 328 int32_t Swap_(int32_t value
) { 
 329     return Swap_(static_cast<uint32_t>(value
)); 
 332 int64_t Swap_(int64_t value
) { 
 333     return Swap_(static_cast<uint64_t>(value
)); 
 338 uint16_t Swap(uint16_t value
) { 
 339     return little_ 
? Swap_(value
) : value
; 
 342 uint32_t Swap(uint32_t value
) { 
 343     return little_ 
? Swap_(value
) : value
; 
 346 uint64_t Swap(uint64_t value
) { 
 347     return little_ 
? Swap_(value
) : value
; 
 350 int16_t Swap(int16_t value
) { 
 351     return Swap(static_cast<uint16_t>(value
)); 
 354 int32_t Swap(int32_t value
) { 
 355     return Swap(static_cast<uint32_t>(value
)); 
 358 int64_t Swap(int64_t value
) { 
 359     return Swap(static_cast<uint64_t>(value
)); 
 362 template <typename Target_
> 
 374     Data(void *base
, size_t size
) : 
 381     uint16_t Swap(uint16_t value
) const { 
 382         return swapped_ 
? Swap_(value
) : value
; 
 385     uint32_t Swap(uint32_t value
) const { 
 386         return swapped_ 
? Swap_(value
) : value
; 
 389     uint64_t Swap(uint64_t value
) const { 
 390         return swapped_ 
? Swap_(value
) : value
; 
 393     int16_t Swap(int16_t value
) const { 
 394         return Swap(static_cast<uint16_t>(value
)); 
 397     int32_t Swap(int32_t value
) const { 
 398         return Swap(static_cast<uint32_t>(value
)); 
 401     int64_t Swap(int64_t value
) const { 
 402         return Swap(static_cast<uint64_t>(value
)); 
 405     void *GetBase() const { 
 409     size_t GetSize() const { 
 420     struct mach_header 
*mach_header_
; 
 421     struct load_command 
*load_command_
; 
 424     MachHeader(void *base
, size_t size
) : 
 427         mach_header_ 
= (mach_header 
*) base
; 
 429         switch (Swap(mach_header_
->magic
)) { 
 431                 swapped_ 
= !swapped_
; 
 437                 swapped_ 
= !swapped_
; 
 446         void *post 
= mach_header_ 
+ 1; 
 448             post 
= (uint32_t *) post 
+ 1; 
 449         load_command_ 
= (struct load_command 
*) post
; 
 452             Swap(mach_header_
->filetype
) == MH_EXECUTE 
|| 
 453             Swap(mach_header_
->filetype
) == MH_DYLIB 
|| 
 454             Swap(mach_header_
->filetype
) == MH_BUNDLE
 
 458     struct mach_header 
*operator ->() const { 
 462     operator struct mach_header 
*() const { 
 466     uint32_t GetCPUType() const { 
 467         return Swap(mach_header_
->cputype
); 
 470     uint32_t GetCPUSubtype() const { 
 471         return Swap(mach_header_
->cpusubtype
) & 0xff; 
 474     struct load_command 
*GetLoadCommand() const { 
 475         return load_command_
; 
 478     std::vector
<struct load_command 
*> GetLoadCommands() const { 
 479         std::vector
<struct load_command 
*> load_commands
; 
 481         struct load_command 
*load_command 
= load_command_
; 
 482         for (uint32_t cmd 
= 0; cmd 
!= Swap(mach_header_
->ncmds
); ++cmd
) { 
 483             load_commands
.push_back(load_command
); 
 484             load_command 
= (struct load_command 
*) ((uint8_t *) load_command 
+ Swap(load_command
->cmdsize
)); 
 487         return load_commands
; 
 490     std::vector
<segment_command 
*> GetSegments(const char *segment_name
) const { 
 491         std::vector
<struct segment_command 
*> segment_commands
; 
 493         _foreach (load_command
, GetLoadCommands()) { 
 494             if (Swap(load_command
->cmd
) == LC_SEGMENT
) { 
 495                 segment_command 
*segment_command 
= reinterpret_cast<struct segment_command 
*>(load_command
); 
 496                 if (strncmp(segment_command
->segname
, segment_name
, 16) == 0) 
 497                     segment_commands
.push_back(segment_command
); 
 501         return segment_commands
; 
 504     std::vector
<segment_command_64 
*> GetSegments64(const char *segment_name
) const { 
 505         std::vector
<struct segment_command_64 
*> segment_commands
; 
 507         _foreach (load_command
, GetLoadCommands()) { 
 508             if (Swap(load_command
->cmd
) == LC_SEGMENT_64
) { 
 509                 segment_command_64 
*segment_command 
= reinterpret_cast<struct segment_command_64 
*>(load_command
); 
 510                 if (strncmp(segment_command
->segname
, segment_name
, 16) == 0) 
 511                     segment_commands
.push_back(segment_command
); 
 515         return segment_commands
; 
 518     std::vector
<section 
*> GetSections(const char *segment_name
, const char *section_name
) const { 
 519         std::vector
<section 
*> sections
; 
 521         _foreach (segment
, GetSegments(segment_name
)) { 
 522             section 
*section 
= (struct section 
*) (segment 
+ 1); 
 525             for (sect 
= 0; sect 
!= Swap(segment
->nsects
); ++sect
) { 
 526                 if (strncmp(section
->sectname
, section_name
, 16) == 0) 
 527                     sections
.push_back(section
); 
 535     template <typename Target_
> 
 536     Pointer
<Target_
> GetPointer(uint32_t address
, const char *segment_name 
= NULL
) const { 
 537         load_command 
*load_command 
= (struct load_command 
*) (mach_header_ 
+ 1); 
 540         for (cmd 
= 0; cmd 
!= Swap(mach_header_
->ncmds
); ++cmd
) { 
 541             if (Swap(load_command
->cmd
) == LC_SEGMENT
) { 
 542                 segment_command 
*segment_command 
= (struct segment_command 
*) load_command
; 
 543                 if (segment_name 
!= NULL 
&& strncmp(segment_command
->segname
, segment_name
, 16) != 0) 
 546                 section 
*sections 
= (struct section 
*) (segment_command 
+ 1); 
 549                 for (sect 
= 0; sect 
!= Swap(segment_command
->nsects
); ++sect
) { 
 550                     section 
*section 
= §ions
[sect
]; 
 551                     //printf("%s %u %p %p %u\n", segment_command->segname, sect, address, section->addr, section->size); 
 552                     if (address 
>= Swap(section
->addr
) && address 
< Swap(section
->addr
) + Swap(section
->size
)) { 
 553                         //printf("0x%.8x %s\n", address, segment_command->segname); 
 554                         return Pointer
<Target_
>(this, reinterpret_cast<Target_ 
*>(address 
- Swap(section
->addr
) + Swap(section
->offset
) + (char *) mach_header_
)); 
 560             load_command 
= (struct load_command 
*) ((char *) load_command 
+ Swap(load_command
->cmdsize
)); 
 563         return Pointer
<Target_
>(this); 
 566     template <typename Target_
> 
 567     Pointer
<Target_
> GetOffset(uint32_t offset
) { 
 568         return Pointer
<Target_
>(this, reinterpret_cast<Target_ 
*>(offset 
+ (uint8_t *) mach_header_
)); 
 572 class FatMachHeader 
: 
 579     FatMachHeader(void *base
, size_t size
, fat_arch 
*fat_arch
) : 
 580         MachHeader(base
, size
), 
 585     fat_arch 
*GetFatArch() const { 
 594     fat_header 
*fat_header_
; 
 595     std::vector
<FatMachHeader
> mach_headers_
; 
 598     FatHeader(void *base
, size_t size
) : 
 601         fat_header_ 
= reinterpret_cast<struct fat_header 
*>(base
); 
 603         if (Swap(fat_header_
->magic
) == FAT_CIGAM
) { 
 604             swapped_ 
= !swapped_
; 
 606         } else if (Swap(fat_header_
->magic
) != FAT_MAGIC
) { 
 608             mach_headers_
.push_back(FatMachHeader(base
, size
, NULL
)); 
 610             size_t fat_narch 
= Swap(fat_header_
->nfat_arch
); 
 611             fat_arch 
*fat_arch 
= reinterpret_cast<struct fat_arch 
*>(fat_header_ 
+ 1); 
 613             for (arch 
= 0; arch 
!= fat_narch
; ++arch
) { 
 614                 uint32_t arch_offset 
= Swap(fat_arch
->offset
); 
 615                 uint32_t arch_size 
= Swap(fat_arch
->size
); 
 616                 mach_headers_
.push_back(FatMachHeader((uint8_t *) base 
+ arch_offset
, arch_size
, fat_arch
)); 
 622     std::vector
<FatMachHeader
> &GetMachHeaders() { 
 623         return mach_headers_
; 
 627         return fat_header_ 
!= NULL
; 
 630     struct fat_header 
*operator ->() const { 
 634     operator struct fat_header 
*() const { 
 639 FatHeader 
Map(const char *path
, bool ro 
= false) { 
 641     void *base(map(path
, 0, _not(size_t), &size
, ro
)); 
 642     return FatHeader(base
, size
); 
 645 template <typename Target_
> 
 648     const MachHeader 
*framework_
; 
 649     const Target_ 
*pointer_
; 
 652     Pointer(const MachHeader 
*framework 
= NULL
, const Target_ 
*pointer 
= NULL
) : 
 653         framework_(framework
), 
 658     operator const Target_ 
*() const { 
 662     const Target_ 
*operator ->() const { 
 666     Pointer
<Target_
> &operator ++() { 
 671     template <typename Value_
> 
 672     Value_ 
Swap(Value_ value
) { 
 673         return framework_
->Swap(value
); 
 677 #define CSMAGIC_CODEDIRECTORY      uint32_t(0xfade0c02) 
 678 #define CSMAGIC_EMBEDDED_SIGNATURE uint32_t(0xfade0cc0) 
 679 #define CSMAGIC_ENTITLEMENTS       uint32_t(0xfade7171) 
 681 #define CSSLOT_CODEDIRECTORY uint32_t(0) 
 682 #define CSSLOT_REQUIREMENTS  uint32_t(2) 
 683 #define CSSLOT_ENTITLEMENTS  uint32_t(5) 
 698     struct BlobIndex index
[]; 
 701 struct CodeDirectory 
{ 
 706     uint32_t identOffset
; 
 707     uint32_t nSpecialSlots
; 
 717 extern "C" uint32_t hash(uint8_t *k
, uint32_t length
, uint32_t initval
); 
 719 void sha1(uint8_t *hash
, uint8_t *data
, size_t size
) { 
 720     SHA1(data
, size
, hash
); 
 723 struct CodesignAllocation 
{ 
 724     FatMachHeader mach_header_
; 
 730     CodesignAllocation(FatMachHeader mach_header
, size_t offset
, size_t size
, size_t alloc
, size_t align
) : 
 731         mach_header_(mach_header
), 
 740 int main(int argc
, const char *argv
[]) { 
 746     little_ 
= endian
.byte
[0]; 
 769     uint32_t flag_CPUType(_not(uint32_t)); 
 770     uint32_t flag_CPUSubtype(_not(uint32_t)); 
 772     const char *flag_I(NULL
); 
 777     const void *xmld(NULL
); 
 780     uintptr_t noffset(_not(uintptr_t)); 
 781     uintptr_t woffset(_not(uintptr_t)); 
 783     std::vector
<std::string
> files
; 
 786         fprintf(stderr
, "usage: %s -S[entitlements.xml] <binary>\n", argv
[0]); 
 787         fprintf(stderr
, "   %s -e MobileSafari\n", argv
[0]); 
 788         fprintf(stderr
, "   %s -S cat\n", argv
[0]); 
 789         fprintf(stderr
, "   %s -Stfp.xml gdb\n", argv
[0]); 
 793     for (int argi(1); argi 
!= argc
; ++argi
) 
 794         if (argv
[argi
][0] != '-') 
 795             files
.push_back(argv
[argi
]); 
 796         else switch (argv
[argi
][1]) { 
 797             case 'R': flag_R 
= true; break; 
 798             case 'r': flag_r 
= true; break; 
 800             case 't': flag_t 
= true; break; 
 801             case 'u': flag_u 
= true; break; 
 802             case 'p': flag_p 
= true; break; 
 803             case 'e': flag_e 
= true; break; 
 804             case 'O': flag_O 
= true; break; 
 806             case 'D': flag_D 
= true; break; 
 807             case 'd': flag_d 
= true; break; 
 809             case 'a': flag_a 
= true; break; 
 813                 if (argv
[argi
][2] != '\0') { 
 814                     const char *cpu 
= argv
[argi
] + 2; 
 815                     const char *colon 
= strchr(cpu
, ':'); 
 816                     _assert(colon 
!= NULL
); 
 818                     flag_CPUType 
= strtoul(cpu
, &arge
, 0); 
 819                     _assert(arge 
== colon
); 
 820                     flag_CPUSubtype 
= strtoul(colon 
+ 1, &arge
, 0); 
 821                     _assert(arge 
== argv
[argi
] + strlen(argv
[argi
])); 
 833                 if (argv
[argi
][2] != '\0') { 
 834                     const char *xml 
= argv
[argi
] + 2; 
 835                     xmld 
= map(xml
, 0, _not(size_t), &xmls
, true); 
 841                 if (argv
[argi
][2] == '-') 
 845                     timev 
= strtoul(argv
[argi
] + 2, &arge
, 0); 
 846                     _assert(arge 
== argv
[argi
] + strlen(argv
[argi
])); 
 851                 flag_I 
= argv
[argi
] + 2; 
 856                 noffset 
= strtoul(argv
[argi
] + 2, &arge
, 0); 
 857                 _assert(arge 
== argv
[argi
] + strlen(argv
[argi
])); 
 862                 woffset 
= strtoul(argv
[argi
] + 2, &arge
, 0); 
 863                 _assert(arge 
== argv
[argi
] + strlen(argv
[argi
])); 
 871     if (files
.empty()) usage
: { 
 875     size_t filei(0), filee(0); 
 876     _foreach (file
, files
) try { 
 877         const char *path(file
.c_str()); 
 878         const char *base 
= strrchr(path
, '/'); 
 879         char *temp(NULL
), *dir
; 
 882             dir 
= strndup_(path
, base
++ - path 
+ 1); 
 888         const char *name(flag_I 
?: base
); 
 892                 FatHeader 
fat_header(Map(path
)); 
 893                 _foreach (mach_header
, fat_header
.GetMachHeaders()) { 
 895                         if (mach_header
.GetCPUType() != flag_CPUType
) 
 897                         if (mach_header
.GetCPUSubtype() != flag_CPUSubtype
) 
 901                     mach_header
->flags 
= mach_header
.Swap(mach_header
.Swap(mach_header
->flags
) | MH_DYLDLINK
); 
 903                     uint32_t size(_not(uint32_t)); { 
 904                         _foreach (load_command
, mach_header
.GetLoadCommands()) { 
 905                             switch (mach_header
.Swap(load_command
->cmd
)) { 
 906                                 case LC_CODE_SIGNATURE
: { 
 907                                     struct linkedit_data_command 
*signature 
= reinterpret_cast<struct linkedit_data_command 
*>(load_command
); 
 908                                     memset(reinterpret_cast<uint8_t *>(mach_header
.GetBase()) + mach_header
.Swap(signature
->dataoff
), 0, mach_header
.Swap(signature
->datasize
)); 
 909                                     memset(signature
, 0, sizeof(struct linkedit_data_command
)); 
 911                                     mach_header
->ncmds 
= mach_header
.Swap(mach_header
.Swap(mach_header
->ncmds
) - 1); 
 912                                     mach_header
->sizeofcmds 
= mach_header
.Swap(uint32_t(mach_header
.Swap(mach_header
->sizeofcmds
) - sizeof(struct linkedit_data_command
))); 
 916                                     struct symtab_command 
*symtab 
= reinterpret_cast<struct symtab_command 
*>(load_command
); 
 917                                     size 
= mach_header
.Swap(symtab
->stroff
) + mach_header
.Swap(symtab
->strsize
); 
 923                     _assert(size 
!= _not(uint32_t)); 
 925                     _foreach (segment
, mach_header
.GetSegments("__LINKEDIT")) { 
 926                         segment
->filesize 
-= mach_header
.GetSize() - size
; 
 928                         if (fat_arch 
*fat_arch 
= mach_header
.GetFatArch()) { 
 929                             fat_arch
->size 
= fat_header
.Swap(size
); 
 930                             clip 
= std::max(clip
, fat_header
.Swap(fat_arch
->offset
) + size
); 
 932                             clip 
= std::max(clip
, size
); 
 935                     _foreach (segment
, mach_header
.GetSegments64("__LINKEDIT")) { 
 936                         segment
->filesize 
-= mach_header
.GetSize() - size
; 
 938                         if (fat_arch 
*fat_arch 
= mach_header
.GetFatArch()) { 
 939                             fat_arch
->size 
= fat_header
.Swap(size
); 
 940                             clip 
= std::max(clip
, fat_header
.Swap(fat_arch
->offset
) + size
); 
 942                             clip 
= std::max(clip
, size
); 
 948                 _syscall(truncate(path
, clip
)); 
 952             FatHeader 
source(Map(path
)); 
 957                 offset 
+= sizeof(fat_header
) + sizeof(fat_arch
) * source
.Swap(source
->nfat_arch
); 
 959             std::vector
<CodesignAllocation
> allocations
; { 
 960                 _foreach (mach_header
, source
.GetMachHeaders()) { 
 962                         if (mach_header
.GetCPUType() != flag_CPUType
) 
 964                         if (mach_header
.GetCPUSubtype() != flag_CPUSubtype
) 
 968                     mach_header
->flags 
= mach_header
.Swap(mach_header
.Swap(mach_header
->flags
) | MH_DYLDLINK
); 
 970                     size_t size(_not(size_t)); { 
 971                         _foreach (load_command
, mach_header
.GetLoadCommands()) { 
 972                             uint32_t cmd(mach_header
.Swap(load_command
->cmd
)); 
 973                             if (cmd 
== LC_CODE_SIGNATURE
) { 
 974                                 struct linkedit_data_command 
*signature 
= reinterpret_cast<struct linkedit_data_command 
*>(load_command
); 
 975                                 size 
= mach_header
.Swap(signature
->dataoff
); 
 976                                 _assert(size 
< mach_header
.GetSize()); 
 981                         if (size 
== _not(size_t)) 
 982                             size 
= mach_header
.GetSize(); 
 986                     alloc 
+= sizeof(struct SuperBlob
); 
 989                     special 
= std::max(special
, CSSLOT_CODEDIRECTORY
); 
 990                     alloc 
+= sizeof(struct BlobIndex
); 
 991                     alloc 
+= sizeof(struct CodeDirectory
); 
 992                     alloc 
+= strlen(name
) + 1; 
 994                     special 
= std::max(special
, CSSLOT_REQUIREMENTS
); 
 995                     alloc 
+= sizeof(struct BlobIndex
); 
 999                         special 
= std::max(special
, CSSLOT_ENTITLEMENTS
); 
1000                         alloc 
+= sizeof(struct BlobIndex
); 
1001                         alloc 
+= sizeof(struct Blob
); 
1005                     size_t normal((size 
+ 0x1000 - 1) / 0x1000); 
1006                     alloc 
= Align(alloc 
+ (special 
+ normal
) * 0x14, 16); 
1008                     auto *fat_arch(mach_header
.GetFatArch()); 
1009                     uint32_t align(fat_arch 
== NULL 
? 0 : source
.Swap(fat_arch
->align
)); 
1010                     offset 
= Align(offset
, 1 << align
); 
1012                     allocations
.push_back(CodesignAllocation(mach_header
, offset
, size
, alloc
, align
)); 
1013                     offset 
+= size 
+ alloc
; 
1014                     offset 
= Align(offset
, 16); 
1018             asprintf(&temp
, "%s.%s.cs", dir
, base
); 
1019             fclose(fopen(temp
, "w+")); 
1020             _syscall(truncate(temp
, offset
)); 
1022             void *file(map(temp
, 0, offset
, NULL
, false)); 
1023             memset(file
, 0, offset
); 
1026             if (!source
.IsFat()) 
1029                 auto *fat_header(reinterpret_cast<struct fat_header 
*>(file
)); 
1030                 fat_header
->magic 
= Swap(FAT_MAGIC
); 
1031                 fat_header
->nfat_arch 
= Swap(source
.Swap(source
->nfat_arch
)); 
1032                 fat_arch 
= reinterpret_cast<struct fat_arch 
*>(fat_header 
+ 1); 
1035             _foreach (allocation
, allocations
) { 
1036                 auto &source(allocation
.mach_header_
); 
1038                 uint32_t align(allocation
.size_
); 
1039                 align 
= Align(align
, 0x10); 
1041                 if (fat_arch 
!= NULL
) { 
1042                     fat_arch
->cputype 
= Swap(source
->cputype
); 
1043                     fat_arch
->cpusubtype 
= Swap(source
->cpusubtype
); 
1044                     fat_arch
->offset 
= Swap(allocation
.offset_
); 
1045                     fat_arch
->size 
= Swap(align 
+ allocation
.alloc_
); 
1046                     fat_arch
->align 
= Swap(allocation
.align_
); 
1050                 void *target(reinterpret_cast<uint8_t *>(file
) + allocation
.offset_
); 
1051                 memcpy(target
, source
, allocation
.size_
); 
1052                 MachHeader 
mach_header(target
, align 
+ allocation
.alloc_
); 
1054                 struct linkedit_data_command 
*signature(NULL
); 
1055                 _foreach (load_command
, mach_header
.GetLoadCommands()) { 
1056                     uint32_t cmd(mach_header
.Swap(load_command
->cmd
)); 
1057                     if (cmd 
!= LC_CODE_SIGNATURE
) 
1059                     signature 
= reinterpret_cast<struct linkedit_data_command 
*>(load_command
); 
1063                 if (signature 
== NULL
) { 
1064                     mach_header
->ncmds 
= mach_header
.Swap(mach_header
.Swap(mach_header
->ncmds
) + 1); 
1065                     signature 
= reinterpret_cast<struct linkedit_data_command 
*>(reinterpret_cast<uint8_t *>(mach_header
.GetLoadCommand()) + mach_header
.Swap(mach_header
->sizeofcmds
)); 
1066                     mach_header
->sizeofcmds 
= mach_header
.Swap(mach_header
.Swap(mach_header
->sizeofcmds
) + uint32_t(sizeof(*signature
))); 
1067                     signature
->cmd 
= mach_header
.Swap(LC_CODE_SIGNATURE
); 
1068                     signature
->cmdsize 
= mach_header
.Swap(uint32_t(sizeof(*signature
))); 
1071                 signature
->dataoff 
= mach_header
.Swap(align
); 
1072                 signature
->datasize 
= mach_header
.Swap(allocation
.alloc_
); 
1074                 _foreach (segment
, mach_header
.GetSegments("__LINKEDIT")) { 
1075                     size_t size(mach_header
.Swap(align 
+ allocation
.alloc_ 
- mach_header
.Swap(segment
->fileoff
))); 
1076                     segment
->filesize 
= size
; 
1077                     segment
->vmsize 
= Align(size
, 0x1000); 
1080                 _foreach (segment
, mach_header
.GetSegments64("__LINKEDIT")) { 
1081                     size_t size(mach_header
.Swap(align 
+ allocation
.alloc_ 
- mach_header
.Swap(segment
->fileoff
))); 
1082                     segment
->filesize 
= size
; 
1083                     segment
->vmsize 
= Align(size
, 0x1000); 
1089             printf("path%zu='%s'\n", filei
, file
.c_str()); 
1091         FatHeader 
fat_header(Map(temp 
== NULL 
? path 
: temp
, !(flag_R 
|| flag_T 
|| flag_s 
|| flag_S 
|| flag_O 
|| flag_D
))); 
1093         _foreach (mach_header
, fat_header
.GetMachHeaders()) { 
1094             struct linkedit_data_command 
*signature(NULL
); 
1095             struct encryption_info_command 
*encryption(NULL
); 
1098                 if (mach_header
.GetCPUType() != flag_CPUType
) 
1100                 if (mach_header
.GetCPUSubtype() != flag_CPUSubtype
) 
1105                 printf("cpu=0x%x:0x%x\n", mach_header
.GetCPUType(), mach_header
.GetCPUSubtype()); 
1108                 if (struct fat_arch 
*fat_arch 
= mach_header
.GetFatArch()) 
1109                     printf("offset=0x%x\n", Swap(fat_arch
->offset
)); 
1111                     printf("offset=0x0\n"); 
1114             if (woffset 
!= _not(uintptr_t)) { 
1115                 Pointer
<uint32_t> wvalue(mach_header
.GetPointer
<uint32_t>(woffset
)); 
1117                     printf("(null) %p\n", reinterpret_cast<void *>(woffset
)); 
1119                     printf("0x%.08x\n", *wvalue
); 
1122             if (noffset 
!= _not(uintptr_t)) 
1123                 printf("%s\n", &*mach_header
.GetPointer
<char>(noffset
)); 
1126                 _foreach(segment
, mach_header
.GetSegments("__TEXT")) { 
1127                     printf("vmaddr=0x%x\n", mach_header
.Swap(segment
->vmaddr
)); 
1128                     printf("fileoff=0x%x\n", mach_header
.Swap(segment
->fileoff
)); 
1132                 _foreach(section
, mach_header
.GetSections("__TEXT", "__text")) 
1133                     section
->addr 
= mach_header
.Swap(0); 
1136             _foreach (load_command
, mach_header
.GetLoadCommands()) { 
1137                 uint32_t cmd(mach_header
.Swap(load_command
->cmd
)); 
1139                 if (flag_R 
&& cmd 
== LC_REEXPORT_DYLIB
) 
1140                     load_command
->cmd 
= mach_header
.Swap(LC_LOAD_DYLIB
); 
1141                 else if (cmd 
== LC_CODE_SIGNATURE
) 
1142                     signature 
= reinterpret_cast<struct linkedit_data_command 
*>(load_command
); 
1143                 else if (cmd 
== LC_ENCRYPTION_INFO
) 
1144                     encryption 
= reinterpret_cast<struct encryption_info_command 
*>(load_command
); 
1145                 else if (cmd 
== LC_UUID
) { 
1146                     volatile struct uuid_command 
*uuid_command(reinterpret_cast<struct uuid_command 
*>(load_command
)); 
1149                         printf("uuid%zu=%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x\n", filei
, 
1150                             uuid_command
->uuid
[ 0], uuid_command
->uuid
[ 1], uuid_command
->uuid
[ 2], uuid_command
->uuid
[ 3], 
1151                             uuid_command
->uuid
[ 4], uuid_command
->uuid
[ 5], uuid_command
->uuid
[ 6], uuid_command
->uuid
[ 7], 
1152                             uuid_command
->uuid
[ 8], uuid_command
->uuid
[ 9], uuid_command
->uuid
[10], uuid_command
->uuid
[11], 
1153                             uuid_command
->uuid
[12], uuid_command
->uuid
[13], uuid_command
->uuid
[14], uuid_command
->uuid
[15] 
1156                 } else if (cmd 
== LC_ID_DYLIB
) { 
1157                     volatile struct dylib_command 
*dylib_command(reinterpret_cast<struct dylib_command 
*>(load_command
)); 
1160                         printf("time%zu=0x%.8x\n", filei
, mach_header
.Swap(dylib_command
->dylib
.timestamp
)); 
1168                             dylib_command
->dylib
.timestamp 
= 0; 
1169                             timed 
= hash(reinterpret_cast<uint8_t *>(mach_header
.GetBase()), mach_header
.GetSize(), timev
); 
1172                         dylib_command
->dylib
.timestamp 
= mach_header
.Swap(timed
); 
1178                 _assert(encryption 
!= NULL
); 
1180                 printf("cryptoff=0x%x\n", mach_header
.Swap(encryption
->cryptoff
)); 
1181                 printf("cryptsize=0x%x\n", mach_header
.Swap(encryption
->cryptsize
)); 
1182                 printf("cryptid=0x%x\n", mach_header
.Swap(encryption
->cryptid
)); 
1186                 _assert(encryption 
!= NULL
); 
1187                 encryption
->cryptid 
= mach_header
.Swap(0); 
1191                 _assert(signature 
!= NULL
); 
1193                 uint32_t data 
= mach_header
.Swap(signature
->dataoff
); 
1195                 uint8_t *top 
= reinterpret_cast<uint8_t *>(mach_header
.GetBase()); 
1196                 uint8_t *blob 
= top 
+ data
; 
1197                 struct SuperBlob 
*super 
= reinterpret_cast<struct SuperBlob 
*>(blob
); 
1199                 for (size_t index(0); index 
!= Swap(super
->count
); ++index
) 
1200                     if (Swap(super
->index
[index
].type
) == CSSLOT_ENTITLEMENTS
) { 
1201                         uint32_t begin 
= Swap(super
->index
[index
].offset
); 
1202                         struct Blob 
*entitlements 
= reinterpret_cast<struct Blob 
*>(blob 
+ begin
); 
1203                         fwrite(entitlements 
+ 1, 1, Swap(entitlements
->length
) - sizeof(struct Blob
), stdout
); 
1208                 _assert(signature 
!= NULL
); 
1210                 uint32_t data 
= mach_header
.Swap(signature
->dataoff
); 
1212                 uint8_t *top 
= reinterpret_cast<uint8_t *>(mach_header
.GetBase()); 
1213                 uint8_t *blob 
= top 
+ data
; 
1214                 struct SuperBlob 
*super 
= reinterpret_cast<struct SuperBlob 
*>(blob
); 
1216                 for (size_t index(0); index 
!= Swap(super
->count
); ++index
) 
1217                     if (Swap(super
->index
[index
].type
) == CSSLOT_CODEDIRECTORY
) { 
1218                         uint32_t begin 
= Swap(super
->index
[index
].offset
); 
1219                         struct CodeDirectory 
*directory 
= reinterpret_cast<struct CodeDirectory 
*>(blob 
+ begin
); 
1221                         uint8_t (*hashes
)[20] = reinterpret_cast<uint8_t (*)[20]>(blob 
+ begin 
+ Swap(directory
->hashOffset
)); 
1222                         uint32_t pages 
= Swap(directory
->nCodeSlots
); 
1225                             for (size_t i 
= 0; i 
!= pages 
- 1; ++i
) 
1226                                 sha1(hashes
[i
], top 
+ 0x1000 * i
, 0x1000); 
1228                             sha1(hashes
[pages 
- 1], top 
+ 0x1000 * (pages 
- 1), ((data 
- 1) % 0x1000) + 1); 
1233                 _assert(signature 
!= NULL
); 
1235                 uint32_t data 
= mach_header
.Swap(signature
->dataoff
); 
1236                 uint32_t size 
= mach_header
.Swap(signature
->datasize
); 
1238                 uint8_t *top 
= reinterpret_cast<uint8_t *>(mach_header
.GetBase()); 
1239                 uint8_t *blob 
= top 
+ data
; 
1240                 struct SuperBlob 
*super 
= reinterpret_cast<struct SuperBlob 
*>(blob
); 
1241                 super
->blob
.magic 
= Swap(CSMAGIC_EMBEDDED_SIGNATURE
); 
1243                 uint32_t count 
= xmld 
== NULL 
? 2 : 3; 
1244                 uint32_t offset 
= sizeof(struct SuperBlob
) + count 
* sizeof(struct BlobIndex
); 
1246                 super
->index
[0].type 
= Swap(CSSLOT_CODEDIRECTORY
); 
1247                 super
->index
[0].offset 
= Swap(offset
); 
1249                 uint32_t begin 
= offset
; 
1250                 struct CodeDirectory 
*directory 
= reinterpret_cast<struct CodeDirectory 
*>(blob 
+ begin
); 
1251                 offset 
+= sizeof(struct CodeDirectory
); 
1253                 directory
->blob
.magic 
= Swap(CSMAGIC_CODEDIRECTORY
); 
1254                 directory
->version 
= Swap(uint32_t(0x00020001)); 
1255                 directory
->flags 
= Swap(uint32_t(0)); 
1256                 directory
->codeLimit 
= Swap(data
); 
1257                 directory
->hashSize 
= 0x14; 
1258                 directory
->hashType 
= 0x01; 
1259                 directory
->spare1 
= 0x00; 
1260                 directory
->pageSize 
= 0x0c; 
1261                 directory
->spare2 
= Swap(uint32_t(0)); 
1263                 directory
->identOffset 
= Swap(offset 
- begin
); 
1264                 strcpy(reinterpret_cast<char *>(blob 
+ offset
), name
); 
1265                 offset 
+= strlen(name
) + 1; 
1267                 uint32_t special 
= xmld 
== NULL 
? CSSLOT_REQUIREMENTS 
: CSSLOT_ENTITLEMENTS
; 
1268                 directory
->nSpecialSlots 
= Swap(special
); 
1270                 uint8_t (*hashes
)[20] = reinterpret_cast<uint8_t (*)[20]>(blob 
+ offset
); 
1271                 memset(hashes
, 0, sizeof(*hashes
) * special
); 
1273                 offset 
+= sizeof(*hashes
) * special
; 
1276                 uint32_t pages 
= (data 
+ 0x1000 - 1) / 0x1000; 
1277                 directory
->nCodeSlots 
= Swap(pages
); 
1280                     for (size_t i 
= 0; i 
!= pages 
- 1; ++i
) 
1281                         sha1(hashes
[i
], top 
+ 0x1000 * i
, 0x1000); 
1283                     sha1(hashes
[pages 
- 1], top 
+ 0x1000 * (pages 
- 1), ((data 
- 1) % 0x1000) + 1); 
1285                 directory
->hashOffset 
= Swap(offset 
- begin
); 
1286                 offset 
+= sizeof(*hashes
) * pages
; 
1287                 directory
->blob
.length 
= Swap(offset 
- begin
); 
1289                 super
->index
[1].type 
= Swap(CSSLOT_REQUIREMENTS
); 
1290                 super
->index
[1].offset 
= Swap(offset
); 
1292                 memcpy(blob 
+ offset
, "\xfa\xde\x0c\x01\x00\x00\x00\x0c\x00\x00\x00\x00", 0xc); 
1296                     super
->index
[2].type 
= Swap(CSSLOT_ENTITLEMENTS
); 
1297                     super
->index
[2].offset 
= Swap(offset
); 
1299                     uint32_t begin 
= offset
; 
1300                     struct Blob 
*entitlements 
= reinterpret_cast<struct Blob 
*>(blob 
+ begin
); 
1301                     offset 
+= sizeof(struct Blob
); 
1303                     memcpy(blob 
+ offset
, xmld
, xmls
); 
1306                     entitlements
->magic 
= Swap(CSMAGIC_ENTITLEMENTS
); 
1307                     entitlements
->length 
= Swap(offset 
- begin
); 
1310                 for (size_t index(0); index 
!= count
; ++index
) { 
1311                     uint32_t type 
= Swap(super
->index
[index
].type
); 
1312                     if (type 
!= 0 && type 
<= special
) { 
1313                         uint32_t offset 
= Swap(super
->index
[index
].offset
); 
1314                         struct Blob 
*local 
= (struct Blob 
*) (blob 
+ offset
); 
1315                         sha1((uint8_t *) (hashes 
- type
), (uint8_t *) local
, Swap(local
->length
)); 
1319                 super
->count 
= Swap(count
); 
1320                 super
->blob
.length 
= Swap(offset
); 
1322                 if (offset 
> size
) { 
1323                     fprintf(stderr
, "offset (%u) > size (%u)\n", offset
, size
); 
1325                 } //else fprintf(stderr, "offset (%zu) <= size (%zu)\n", offset, size); 
1327                 memset(blob 
+ offset
, 0, size 
- offset
); 
1332             uint8_t *top 
= reinterpret_cast<uint8_t *>(fat_header
.GetBase()); 
1333             size_t size 
= fat_header
.GetSize(); 
1336             asprintf(©
, "%s.%s.cp", dir
, base
); 
1337             FILE *file 
= fopen(copy
, "w+"); 
1338             size_t writ 
= fwrite(top
, 1, size
, file
); 
1339             _assert(writ 
== size
); 
1342             _syscall(unlink(temp
)); 
1349             _syscall(stat(path
, &info
)); 
1350             _syscall(chown(temp
, info
.st_uid
, info
.st_gid
)); 
1351             _syscall(chmod(temp
, info
.st_mode
)); 
1352             _syscall(unlink(path
)); 
1353             _syscall(rename(temp
, path
)); 
1359     } catch (const char *) {