New Ticket     Tickets     Wiki     Browse Source     Timeline     Roadmap     Ticket Reports     Search

Changeset 81469


Ignore:
Timestamp:
07/31/11 03:37:54 (4 years ago)
Author:
raimue@…
Message:

devel/valgrind:
Updated compatibility patch for Xcode 4 and above, initial patch was faulty.

Location:
trunk/dports/devel/valgrind
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/dports/devel/valgrind/Portfile

    r81375 r81469  
    66conflicts       valgrind-devel 
    77version         3.6.1 
    8 revision        1 
     8revision        2 
    99categories      devel 
    1010platforms       darwin 
     
    3535# as they are only used for tests 
    3636 
    37 patchfiles      patch-xcode4.diff 
     37# Compatibility patch for Xcode 4 and above, #28572 
     38if {[rpm-vercomp $xcodeversion 4.0.0] > 0} { 
     39    patchfiles-append   patch-xcode4.diff 
     40    use_autoreconf yes 
     41} 
    3842 
    3943configure.args  --mandir=${prefix}/share/man \ 
  • trunk/dports/devel/valgrind/files/patch-xcode4.diff

    r81375 r81469  
    1 Index: coregrind/link_tool_exe_darwin.in 
    2 =================================================================== 
    3 --- coregrind/link_tool_exe_darwin.in   (revision 11685) 
    4 +++ coregrind/link_tool_exe_darwin.in   (revision 11686) 
    5 @@ -160,14 +160,31 @@ 
    6      } 
    7  } 
    8   
    9 -#print "link_tool_exe_darwin: $cmd\n"; 
    10 - 
    11 +print "link_tool_exe_darwin: $cmd\n"; 
    12   
    13  # Execute the command: 
    14  my $r = system("$cmd"); 
    15   
    16 -if ($r == 0) { 
    17 -    exit 0; 
    18 -} else { 
    19 -    exit 1; 
    20 +if ($r != 0) { 
    21 +   exit 1; 
    22  } 
    23 + 
    24 + 
    25 +# and now kludge the tool exe 
    26 +# see bug 267997 
    27 + 
    28 +$cmd = "../coregrind/fixup_macho_loadcmds"; 
    29 +$cmd = "$cmd $stack_addr_str $stack_size_str $outname"; 
    30 + 
    31 +print "link_tool_exe_darwin: $cmd\n"; 
    32 + 
    33 +my $r = system("$cmd"); 
    34 + 
    35 +if ($r != 0) { 
    36 +   exit 1; 
    37 +} 
    38 + 
    39 + 
    40 + 
    41 + 
    42 +exit 0; 
     1http://github.com/mxcl/homebrew/commit/a8a0c3e56a7cea03e06f7b3c874af973704f6e3e#Library/Formula/valgrind.rb 
    432Index: coregrind/fixup_macho_loadcmds.c 
    443=================================================================== 
     
    292251+     struct fat_header   fh; 
    293252+     struct mach_header_64* mh; 
    294 +      
     253+ 
    295254+     // Assume initially that we have a thin image, and update 
    296255+     // these if it turns out to be fat. 
     
    315274+           fail("Invalid Mach-O file (1 too small)."); 
    316275+ 
    317 +        for (f = 0, arch_be = (struct fat_arch *)(fh_be+1);  
     276+        for (f = 0, arch_be = (struct fat_arch *)(fh_be+1); 
    318277+             f < fh.nfat_arch; 
    319278+             f++, arch_be++) { 
     
    601560+   if (argc != 4) 
    602561+      fail("args: -stack_addr-arg -stack_size-arg " 
    603 +           "name-of-tool-executable-to-modify");  
     562+           "name-of-tool-executable-to-modify"); 
    604563+ 
    605564+   r= sscanf(argv[1], "0x%llx", &req_stack_addr); 
     
    616575+      fail("implausible tool exe name -- not of the form *-{x86,amd64}-darwin"); 
    617576+ 
    618 +   fprintf(stderr, "fixup_macho_loadcmds: examining tool exe: %s\n",  
     577+   fprintf(stderr, "fixup_macho_loadcmds: examining tool exe: %s\n", 
    619578+           argv[3] ); 
    620579+   modify_macho_loadcmds( argv[3], req_stack_addr - req_stack_size, 
     
    651610+    flags 0x0 
    652611+*/ 
    653 Index: coregrind/Makefile.am 
    654 =================================================================== 
    655 --- coregrind/Makefile.am       (revision 11685) 
    656 +++ coregrind/Makefile.am       (revision 11686) 
    657 @@ -441,3 +441,18 @@ 
    658   
    659  install-exec-local: install-noinst_PROGRAMS install-noinst_DSYMS 
    660   
    661 +#---------------------------------------------------------------------------- 
    662 +# Darwin linker kludges 
    663 +#---------------------------------------------------------------------------- 
    664 + 
    665 +if VGCONF_OS_IS_DARWIN 
    666 + 
    667 +BUILT_SOURCES += fixup_macho_loadcmds 
    668 +fixup_macho_loadcmds: fixup_macho_loadcmds.c 
    669 +       $(CC) -g -Wall -o fixup_macho_loadcmds fixup_macho_loadcmds.c 
    670 + 
    671 +CLEANFILES += fixup_macho_loadcmds 
    672 + 
    673 +endif 
    674 + 
    675 +EXTRA_DIST += fixup_macho_loadcmds.c 
    676612Index: coregrind/link_tool_exe_darwin.in 
    677613=================================================================== 
    678614--- coregrind/link_tool_exe_darwin.in   (revision 11685) 
    679 +++ coregrind/link_tool_exe_darwin.in   (revision 11686) 
     615+++ coregrind/link_tool_exe_darwin.in   (working copy) 
    680616@@ -160,14 +160,31 @@ 
    681617     } 
    682618 } 
    683   
     619 
    684620-#print "link_tool_exe_darwin: $cmd\n"; 
     621+print "link_tool_exe_darwin: $cmd\n"; 
     622 
    685623- 
    686 +print "link_tool_exe_darwin: $cmd\n"; 
    687   
    688624 # Execute the command: 
    689625 my $r = system("$cmd"); 
    690   
     626 
    691627-if ($r == 0) { 
    692628-    exit 0; 
     
    716652+ 
    717653+exit 0; 
    718 Index: coregrind/fixup_macho_loadcmds.c 
    719 =================================================================== 
    720 --- coregrind/fixup_macho_loadcmds.c    (revision 0) 
    721 +++ coregrind/fixup_macho_loadcmds.c    (revision 11686) 
    722 @@ -0,0 +1,605 @@ 
    723 + 
    724 +/* Derived from Valgrind sources, coregrind/m_debuginfo/readmacho.c. 
    725 +   GPL 2+ therefore. 
    726 + 
    727 +   Can be compiled as either a 32- or 64-bit program (doesn't matter). 
    728 +*/ 
    729 + 
    730 +/* What does this program do?  In short it postprocesses tool 
    731 +   executables on MacOSX, after linking using /usr/bin/ld.  This is so 
    732 +   as to work around a bug in the linker on Xcode 4.0.0 and Xcode 
    733 +   4.0.1.  Xcode versions prior to 4.0.0 are unaffected. 
    734 + 
    735 +   The tracking bug is https://bugs.kde.org/show_bug.cgi?id=267997 
    736 + 
    737 +   The bug causes 64-bit tool executables to segfault at startup, 
    738 +   because: 
    739 + 
    740 +   Comparing the MachO load commands vs a (working) tool executable 
    741 +   that was created by Xcode 3.2.x, it appears that the new linker has 
    742 +   partially ignored the build system's request to place the tool 
    743 +   executable's stack at a non standard location.  The build system 
    744 +   tells the linker "-stack_addr 0x134000000 -stack_size 0x800000". 
    745 + 
    746 +   With the Xcode 3.2 linker those flags produce two results: 
    747 + 
    748 +   (1) A load command to allocate the stack at the said location: 
    749 +          Load command 3 
    750 +                cmd LC_SEGMENT_64 
    751 +            cmdsize 72 
    752 +            segname __UNIXSTACK 
    753 +             vmaddr 0x0000000133800000 
    754 +             vmsize 0x0000000000800000 
    755 +            fileoff 2285568 
    756 +           filesize 0 
    757 +            maxprot 0x00000007 
    758 +           initprot 0x00000003 
    759 +             nsects 0 
    760 +              flags 0x0 
    761 + 
    762 +   (2) A request (in LC_UNIXTHREAD) to set %rsp to the correct value 
    763 +       at process startup, 0x134000000. 
    764 + 
    765 +   With Xcode 4.0.1, (1) is missing but (2) is still present.  The 
    766 +   tool executable therefore starts up with %rsp pointing to unmapped 
    767 +   memory and faults almost instantly. 
    768 + 
    769 +   The workaround implemented by this program is documented in comment 
    770 +   8 of bug 267997, viz: 
    771 + 
    772 +   One really sick workaround is to observe that the executables 
    773 +   contain a redundant MachO load command: 
    774 + 
    775 +      Load command 2 
    776 +            cmd LC_SEGMENT_64 
    777 +        cmdsize 72 
    778 +        segname __LINKEDIT 
    779 +         vmaddr 0x0000000138dea000 
    780 +         vmsize 0x00000000000ad000 
    781 +        fileoff 2658304 
    782 +       filesize 705632 
    783 +        maxprot 0x00000007 
    784 +       initprot 0x00000001 
    785 +         nsects 0 
    786 +          flags 0x0 
    787 + 
    788 +   The described section presumably contains information intended for 
    789 +   the dynamic linker, but is irrelevant because this is a statically 
    790 +   linked executable.  Hence it might be possible to postprocess the 
    791 +   executables after linking, to overwrite this entry with the 
    792 +   information that would have been in the missing __UNIXSTACK entry. 
    793 +   I tried this by hand (with a binary editor) earlier and got 
    794 +   something that worked. 
    795 +*/ 
    796 + 
    797 +#define DEBUGPRINTING 0 
    798 + 
    799 +#include <assert.h> 
    800 +#include <stdlib.h> 
    801 +#include <stdio.h> 
    802 +#include <string.h> 
    803 +#include <sys/mman.h> 
    804 +#include <sys/stat.h> 
    805 +#include <unistd.h> 
    806 +#include <fcntl.h> 
    807 + 
    808 + 
    809 +#undef PLAT_x86_darwin 
    810 +#undef PLAT_amd64_darwin 
    811 + 
    812 +#if defined(__APPLE__) && defined(__i386__) 
    813 +#  define PLAT_x86_darwin 1 
    814 +#elif defined(__APPLE__) && defined(__x86_64__) 
    815 +#  define PLAT_amd64_darwin 1 
    816 +#else 
    817 +#  error "Can't be compiled on this platform" 
    818 +#endif 
    819 + 
    820 +#include <mach-o/loader.h> 
    821 +#include <mach-o/nlist.h> 
    822 +#include <mach-o/fat.h> 
    823 +#include <mach/i386/thread_status.h> 
    824 + 
    825 + 
    826 +typedef  unsigned char   UChar; 
    827 +typedef    signed char   Char; 
    828 +typedef           char   HChar; /* signfulness depends on host */ 
    829 + 
    830 +typedef  unsigned int    UInt; 
    831 +typedef    signed int    Int; 
    832 + 
    833 +typedef  unsigned char   Bool; 
    834 +#define  True   ((Bool)1) 
    835 +#define  False  ((Bool)0) 
    836 + 
    837 +typedef  unsigned long   UWord; 
    838 + 
    839 +typedef  UWord           SizeT; 
    840 +typedef  UWord           Addr; 
    841 + 
    842 +typedef  unsigned long long int   ULong; 
    843 +typedef    signed long long int   Long; 
    844 + 
    845 + 
    846 + 
    847 +__attribute__((noreturn)) 
    848 +void fail ( HChar* msg ) 
    849 +{ 
    850 +   fprintf(stderr, "fixup_macho_loadcmds: fail: %s\n", msg); 
    851 +   exit(1); 
    852 +} 
    853 + 
    854 + 
    855 +/*------------------------------------------------------------*/ 
    856 +/*---                                                      ---*/ 
    857 +/*--- Mach-O file mapping/unmapping helpers                ---*/ 
    858 +/*---                                                      ---*/ 
    859 +/*------------------------------------------------------------*/ 
    860 + 
    861 +typedef 
    862 +   struct { 
    863 +      /* These two describe the entire mapped-in ("primary") image, 
    864 +         fat headers, kitchen sink, whatnot: the entire file.  The 
    865 +         image is mapped into img[0 .. img_szB-1]. */ 
    866 +      UChar* img; 
    867 +      SizeT  img_szB; 
    868 +      /* These two describe the Mach-O object of interest, which is 
    869 +         presumably somewhere inside the primary image. 
    870 +         map_image_aboard() below, which generates this info, will 
    871 +         carefully check that the macho_ fields denote a section of 
    872 +         memory that falls entirely inside img[0 .. img_szB-1]. */ 
    873 +      UChar* macho_img; 
    874 +      SizeT  macho_img_szB; 
    875 +   } 
    876 +   ImageInfo; 
    877 + 
    878 + 
    879 +Bool is_macho_object_file( const void* buf, SizeT szB ) 
    880 +{ 
    881 +   /* (JRS: the Mach-O headers might not be in this mapped data, 
    882 +      because we only mapped a page for this initial check, 
    883 +      or at least not very much, and what's at the start of the file 
    884 +      is in general a so-called fat header.  The Mach-O object we're 
    885 +      interested in could be arbitrarily far along the image, and so 
    886 +      we can't assume its header will fall within this page.) */ 
    887 + 
    888 +   /* But we can say that either it's a fat object, in which case it 
    889 +      begins with a fat header, or it's unadorned Mach-O, in which 
    890 +      case it starts with a normal header.  At least do what checks we 
    891 +      can to establish whether or not we're looking at something 
    892 +      sane. */ 
    893 + 
    894 +   const struct fat_header*  fh_be = buf; 
    895 +   const struct mach_header_64* mh    = buf; 
    896 + 
    897 +   assert(buf); 
    898 +   if (szB < sizeof(struct fat_header)) 
    899 +      return False; 
    900 +   if (ntohl(fh_be->magic) == FAT_MAGIC) 
    901 +      return True; 
    902 + 
    903 +   if (szB < sizeof(struct mach_header_64)) 
    904 +      return False; 
    905 +   if (mh->magic == MH_MAGIC_64) 
    906 +      return True; 
    907 + 
    908 +   return False; 
    909 +} 
    910 + 
    911 + 
    912 +/* Unmap an image mapped in by map_image_aboard. */ 
    913 +static void unmap_image ( /*MOD*/ImageInfo* ii ) 
    914 +{ 
    915 +   Int r; 
    916 +   assert(ii->img); 
    917 +   assert(ii->img_szB > 0); 
    918 +   r = munmap( ii->img, ii->img_szB ); 
    919 +   /* Do we care if this fails?  I suppose so; it would indicate 
    920 +      some fairly serious snafu with the mapping of the file. */ 
    921 +   assert( !r ); 
    922 +   memset(ii, 0, sizeof(*ii)); 
    923 +} 
    924 + 
    925 + 
    926 +/* Map a given fat or thin object aboard, find the thin part if 
    927 +   necessary, do some checks, and write details of both the fat and 
    928 +   thin parts into *ii.  Returns 32 (and leaves the file unmapped) if 
    929 +   the thin part is a 32 bit file.  Returns 64 if it's a 64 bit file. 
    930 +   Does not return on failure.  Guarantees to return pointers to a 
    931 +   valid(ish) Mach-O image if it succeeds. */ 
    932 +static Int map_image_aboard ( /*OUT*/ImageInfo* ii, HChar* filename ) 
    933 +{ 
    934 +   memset(ii, 0, sizeof(*ii)); 
    935 + 
    936 +   /* First off, try to map the thing in. */ 
    937 +   { SizeT  size; 
    938 +     Int r, fd; 
    939 +     struct stat stat_buf; 
    940 + 
    941 +     r = stat(filename, &stat_buf); 
    942 +     if (r) 
    943 +        fail("Can't stat image (to determine its size)?!"); 
    944 +     size = stat_buf.st_size; 
    945 + 
    946 +     fd = open(filename, O_RDWR, 0); 
    947 +     if (fd == -1) 
    948 +        fail("Can't open image for possible modification!"); 
    949 +     if (DEBUGPRINTING) 
    950 +        printf("size %lu fd %d\n", size, fd); 
    951 +     void* v = mmap ( NULL, size, PROT_READ|PROT_WRITE, 
    952 +                                  MAP_FILE|MAP_SHARED, fd, 0 ); 
    953 +     if (v == MAP_FAILED) { 
    954 +        perror("mmap failed"); 
    955 +        fail("Can't mmap image for possible modification!"); 
    956 +     } 
    957 + 
    958 +     close(fd); 
    959 + 
    960 +     ii->img     = (UChar*)v; 
    961 +     ii->img_szB = size; 
    962 +   } 
    963 + 
    964 +   /* Now it's mapped in and we have .img and .img_szB set.  Look for 
    965 +      the embedded Mach-O object.  If not findable, unmap and fail. */ 
    966 +   { struct fat_header*  fh_be; 
    967 +     struct fat_header   fh; 
    968 +     struct mach_header_64* mh; 
    969 +      
    970 +     // Assume initially that we have a thin image, and update 
    971 +     // these if it turns out to be fat. 
    972 +     ii->macho_img     = ii->img; 
    973 +     ii->macho_img_szB = ii->img_szB; 
    974 + 
    975 +     // Check for fat header. 
    976 +     if (ii->img_szB < sizeof(struct fat_header)) 
    977 +        fail("Invalid Mach-O file (0 too small)."); 
    978 + 
    979 +     // Fat header is always BIG-ENDIAN 
    980 +     fh_be = (struct fat_header *)ii->img; 
    981 +     fh.magic = ntohl(fh_be->magic); 
    982 +     fh.nfat_arch = ntohl(fh_be->nfat_arch); 
    983 +     if (fh.magic == FAT_MAGIC) { 
    984 +        // Look for a good architecture. 
    985 +        struct fat_arch *arch_be; 
    986 +        struct fat_arch arch; 
    987 +        Int f; 
    988 +        if (ii->img_szB < sizeof(struct fat_header) 
    989 +                          + fh.nfat_arch * sizeof(struct fat_arch)) 
    990 +           fail("Invalid Mach-O file (1 too small)."); 
    991 + 
    992 +        for (f = 0, arch_be = (struct fat_arch *)(fh_be+1);  
    993 +             f < fh.nfat_arch; 
    994 +             f++, arch_be++) { 
    995 +           Int cputype; 
    996 +#          if defined(PLAT_x86_darwin) 
    997 +           cputype = CPU_TYPE_X86; 
    998 +#          elif defined(PLAT_amd64_darwin) 
    999 +           cputype = CPU_TYPE_X86_64; 
    1000 +#          else 
    1001 +#            error "unknown architecture" 
    1002 +#          endif 
    1003 +           arch.cputype    = ntohl(arch_be->cputype); 
    1004 +           arch.cpusubtype = ntohl(arch_be->cpusubtype); 
    1005 +           arch.offset     = ntohl(arch_be->offset); 
    1006 +           arch.size       = ntohl(arch_be->size); 
    1007 +           if (arch.cputype == cputype) { 
    1008 +              if (ii->img_szB < arch.offset + arch.size) 
    1009 +                 fail("Invalid Mach-O file (2 too small)."); 
    1010 +              ii->macho_img     = ii->img + arch.offset; 
    1011 +              ii->macho_img_szB = arch.size; 
    1012 +              break; 
    1013 +           } 
    1014 +        } 
    1015 +        if (f == fh.nfat_arch) 
    1016 +           fail("No acceptable architecture found in fat file."); 
    1017 +     } 
    1018 + 
    1019 +     /* Sanity check what we found. */ 
    1020 + 
    1021 +     /* assured by logic above */ 
    1022 +     assert(ii->img_szB >= sizeof(struct fat_header)); 
    1023 + 
    1024 +     if (ii->macho_img_szB < sizeof(struct mach_header_64)) 
    1025 +        fail("Invalid Mach-O file (3 too small)."); 
    1026 + 
    1027 +     if (ii->macho_img_szB > ii->img_szB) 
    1028 +        fail("Invalid Mach-O file (thin bigger than fat)."); 
    1029 + 
    1030 +     if (ii->macho_img >= ii->img 
    1031 +         && ii->macho_img + ii->macho_img_szB <= ii->img + ii->img_szB) { 
    1032 +        /* thin entirely within fat, as expected */ 
    1033 +     } else { 
    1034 +        fail("Invalid Mach-O file (thin not inside fat)."); 
    1035 +     } 
    1036 + 
    1037 +     mh = (struct mach_header_64 *)ii->macho_img; 
    1038 +     if (mh->magic == MH_MAGIC) { 
    1039 +        assert(ii->img); 
    1040 +        assert(ii->macho_img); 
    1041 +        assert(ii->img_szB > 0); 
    1042 +        assert(ii->macho_img_szB > 0); 
    1043 +        assert(ii->macho_img >= ii->img); 
    1044 +        assert(ii->macho_img + ii->macho_img_szB <= ii->img + ii->img_szB); 
    1045 +        return 32; 
    1046 +     } 
    1047 +     if (mh->magic != MH_MAGIC_64) 
    1048 +        fail("Invalid Mach-O file (bad magic)."); 
    1049 + 
    1050 +     if (ii->macho_img_szB < sizeof(struct mach_header_64) + mh->sizeofcmds) 
    1051 +        fail("Invalid Mach-O file (4 too small)."); 
    1052 +   } 
    1053 + 
    1054 +   assert(ii->img); 
    1055 +   assert(ii->macho_img); 
    1056 +   assert(ii->img_szB > 0); 
    1057 +   assert(ii->macho_img_szB > 0); 
    1058 +   assert(ii->macho_img >= ii->img); 
    1059 +   assert(ii->macho_img + ii->macho_img_szB <= ii->img + ii->img_szB); 
    1060 +   return 64; 
    1061 +} 
    1062 + 
    1063 + 
    1064 +/*------------------------------------------------------------*/ 
    1065 +/*---                                                      ---*/ 
    1066 +/*--- Mach-O top-level processing                          ---*/ 
    1067 +/*---                                                      ---*/ 
    1068 +/*------------------------------------------------------------*/ 
    1069 + 
    1070 +void modify_macho_loadcmds ( HChar* filename, 
    1071 +                             ULong  expected_stack_start, 
    1072 +                             ULong  expected_stack_size ) 
    1073 +{ 
    1074 +   ImageInfo ii; 
    1075 +   memset(&ii, 0, sizeof(ii)); 
    1076 + 
    1077 +   Int size = map_image_aboard( &ii, filename ); 
    1078 +   if (size == 32) { 
    1079 +      fprintf(stderr, "fixup_macho_loadcmds:   Is 32-bit MachO file;" 
    1080 +              " no modifications needed.\n"); 
    1081 +      goto out; 
    1082 +   } 
    1083 + 
    1084 +   assert(size == 64); 
    1085 + 
    1086 +   assert(ii.macho_img != NULL && ii.macho_img_szB > 0); 
    1087 + 
    1088 +   /* Poke around in the Mach-O header, to find some important 
    1089 +      stuff. 
    1090 +      * the location of the __UNIXSTACK load command, if any 
    1091 +      * the location of the __LINKEDIT load command, if any 
    1092 +      * the initial RSP value as stated in the LC_UNIXTHREAD 
    1093 +   */ 
    1094 + 
    1095 +   /* The collected data */ 
    1096 +   ULong init_rsp = 0; 
    1097 +   Bool  have_rsp = False; 
    1098 +   struct segment_command_64* seg__unixstack = NULL; 
    1099 +   struct segment_command_64* seg__linkedit  = NULL; 
    1100 + 
    1101 +   /* Loop over the load commands and fill in the above 4 variables. */ 
    1102 + 
    1103 +   { struct mach_header_64 *mh = (struct mach_header_64 *)ii.macho_img; 
    1104 +      struct load_command *cmd; 
    1105 +      Int c; 
    1106 + 
    1107 +      for (c = 0, cmd = (struct load_command *)(mh+1); 
    1108 +           c < mh->ncmds; 
    1109 +           c++, cmd = (struct load_command *)(cmd->cmdsize 
    1110 +                                              + (unsigned long)cmd)) { 
    1111 +         if (DEBUGPRINTING) 
    1112 +            printf("load cmd: offset %4lu   size %3d   kind %2d = ", 
    1113 +                   (unsigned long)((UChar*)cmd - (UChar*)ii.macho_img), 
    1114 +                   cmd->cmdsize, cmd->cmd); 
    1115 + 
    1116 +         switch (cmd->cmd) { 
    1117 +            case LC_SEGMENT_64: 
    1118 +               if (DEBUGPRINTING) 
    1119 +                  printf("LC_SEGMENT_64"); 
    1120 +               break; 
    1121 +            case LC_SYMTAB: 
    1122 +               if (DEBUGPRINTING) 
    1123 +                  printf("LC_SYMTAB"); 
    1124 +               break; 
    1125 +            case LC_UUID: 
    1126 +               if (DEBUGPRINTING) 
    1127 +                  printf("LC_UUID"); 
    1128 +               break; 
    1129 +            case LC_UNIXTHREAD: 
    1130 +               if (DEBUGPRINTING) 
    1131 +                  printf("LC_UNIXTHREAD"); 
    1132 +               break; 
    1133 +            default: 
    1134 +                  printf("???"); 
    1135 +               fail("unexpected load command in Mach header"); 
    1136 +            break; 
    1137 +         } 
    1138 +         if (DEBUGPRINTING) 
    1139 +            printf("\n"); 
    1140 + 
    1141 +         /* Note what the stated initial RSP value is, so we can 
    1142 +            check it is as expected. */ 
    1143 +         if (cmd->cmd == LC_UNIXTHREAD) { 
    1144 +            struct thread_command* tcmd = (struct thread_command*)cmd; 
    1145 +            UInt* w32s = (UInt*)( (UChar*)tcmd + sizeof(*tcmd) ); 
    1146 +            if (DEBUGPRINTING) 
    1147 +               printf("UnixThread: flavor %u = ", w32s[0]); 
    1148 +            if (w32s[0] == x86_THREAD_STATE64 && !have_rsp) { 
    1149 +               if (DEBUGPRINTING) 
    1150 +                  printf("x86_THREAD_STATE64\n"); 
    1151 +               x86_thread_state64_t* state64 
    1152 +                  = (x86_thread_state64_t*)(&w32s[2]); 
    1153 +               have_rsp = True; 
    1154 +               init_rsp = state64->__rsp; 
    1155 +               if (DEBUGPRINTING) 
    1156 +                  printf("rsp = 0x%llx\n", init_rsp); 
    1157 +            } else { 
    1158 +               if (DEBUGPRINTING) 
    1159 +                  printf("???"); 
    1160 +            } 
    1161 +            if (DEBUGPRINTING) 
    1162 +               printf("\n"); 
    1163 +         } 
    1164 + 
    1165 +         if (cmd->cmd == LC_SEGMENT_64) { 
    1166 +            struct segment_command_64 *seg = (struct segment_command_64 *)cmd; 
    1167 +            if (0 == strcmp(seg->segname, "__LINKEDIT")) 
    1168 +               seg__linkedit = seg; 
    1169 +            if (0 == strcmp(seg->segname, "__UNIXSTACK")) 
    1170 +               seg__unixstack = seg; 
    1171 +         } 
    1172 + 
    1173 +      } 
    1174 +   } 
    1175 + 
    1176 +   /* 
    1177 +      Actions are then as follows: 
    1178 + 
    1179 +      * (always) check the RSP value is as expected, and abort if not 
    1180 + 
    1181 +      * if there's a UNIXSTACK load command, check it is as expected. 
    1182 +        If not abort, if yes, do nothing more. 
    1183 + 
    1184 +      * (so there's no UNIXSTACK load command).  if there's a LINKEDIT 
    1185 +        load command, check if it is minimally usable (has 0 for 
    1186 +        nsects and flags).  If yes, convert it to a UNIXSTACK load 
    1187 +        command.  If there is none, or is unusable, then we're out of 
    1188 +        options and have to abort. 
    1189 +   */ 
    1190 +   if (!have_rsp) 
    1191 +      fail("Can't find / check initial RSP setting"); 
    1192 +   if (init_rsp != expected_stack_start + expected_stack_size) 
    1193 +      fail("Initial RSP value not as expected"); 
    1194 + 
    1195 +   fprintf(stderr, "fixup_macho_loadcmds:   " 
    1196 +                   "initial RSP is as expected (0x%llx)\n", 
    1197 +                   expected_stack_start + expected_stack_size ); 
    1198 + 
    1199 +   if (seg__unixstack) { 
    1200 +      struct segment_command_64 *seg = seg__unixstack; 
    1201 +      if (seg->vmaddr != expected_stack_start) 
    1202 +         fail("has __UNIXSTACK, but wrong ::vmaddr"); 
    1203 +      if (seg->vmsize != expected_stack_size) 
    1204 +         fail("has __UNIXSTACK, but wrong ::vmsize"); 
    1205 +      if (seg->maxprot != 7) 
    1206 +         fail("has __UNIXSTACK, but wrong ::maxprot (should be 7)"); 
    1207 +      if (seg->initprot != 3) 
    1208 +         fail("has __UNIXSTACK, but wrong ::initprot (should be 3)"); 
    1209 +      if (seg->nsects != 0) 
    1210 +         fail("has __UNIXSTACK, but wrong ::nsects (should be 0)"); 
    1211 +      if (seg->flags != 0) 
    1212 +         fail("has __UNIXSTACK, but wrong ::flags (should be 0)"); 
    1213 +      /* looks ok */ 
    1214 +      fprintf(stderr, "fixup_macho_loadcmds:   " 
    1215 +              "acceptable __UNIXSTACK present; no modifications.\n" ); 
    1216 +      goto out; 
    1217 +   } 
    1218 + 
    1219 +   if (seg__linkedit) { 
    1220 +      struct segment_command_64 *seg = seg__linkedit; 
    1221 +      if (seg->nsects != 0) 
    1222 +         fail("has __LINKEDIT, but wrong ::nsects (should be 0)"); 
    1223 +      if (seg->flags != 0) 
    1224 +         fail("has __LINKEDIT, but wrong ::flags (should be 0)"); 
    1225 +      fprintf(stderr, "fixup_macho_loadcmds:   " 
    1226 +              "no __UNIXSTACK present.\n" ); 
    1227 +      fprintf(stderr, "fixup_macho_loadcmds:   " 
    1228 +              "converting __LINKEDIT to __UNIXSTACK.\n" ); 
    1229 +      strcpy(seg->segname, "__UNIXSTACK"); 
    1230 +      seg->vmaddr   = expected_stack_start; 
    1231 +      seg->vmsize   = expected_stack_size; 
    1232 +      seg->fileoff  = 0; 
    1233 +      seg->filesize = 0; 
    1234 +      seg->maxprot  = 7; 
    1235 +      seg->initprot = 3; 
    1236 +      /* success */ 
    1237 +      goto out; 
    1238 +   } 
    1239 + 
    1240 +   /* out of options */ 
    1241 +   fail("no __UNIXSTACK found and no usable __LINKEDIT found; " 
    1242 +        "out of options."); 
    1243 +   /* NOTREACHED */ 
    1244 + 
    1245 +  out: 
    1246 +   if (ii.img) 
    1247 +      unmap_image(&ii); 
    1248 +} 
    1249 + 
    1250 + 
    1251 +static Bool is_plausible_tool_exe_name ( HChar* nm ) 
    1252 +{ 
    1253 +   HChar* p; 
    1254 +   if (!nm) 
    1255 +      return False; 
    1256 + 
    1257 +   // Does it end with this string? 
    1258 +   p = strstr(nm, "-x86-darwin"); 
    1259 +   if (p && 0 == strcmp(p, "-x86-darwin")) 
    1260 +      return True; 
    1261 + 
    1262 +   p = strstr(nm, "-amd64-darwin"); 
    1263 +   if (p && 0 == strcmp(p, "-amd64-darwin")) 
    1264 +      return True; 
    1265 + 
    1266 +   return False; 
    1267 +} 
    1268 + 
    1269 + 
    1270 +int main ( int argc, char** argv ) 
    1271 +{ 
    1272 +   Int   r; 
    1273 +   ULong req_stack_addr = 0; 
    1274 +   ULong req_stack_size = 0; 
    1275 + 
    1276 +   if (argc != 4) 
    1277 +      fail("args: -stack_addr-arg -stack_size-arg " 
    1278 +           "name-of-tool-executable-to-modify");  
    1279 + 
    1280 +   r= sscanf(argv[1], "0x%llx", &req_stack_addr); 
    1281 +   if (r != 1) fail("invalid stack_addr arg"); 
    1282 + 
    1283 +   r= sscanf(argv[2], "0x%llx", &req_stack_size); 
    1284 +   if (r != 1) fail("invalid stack_size arg"); 
    1285 + 
    1286 +   fprintf(stderr, "fixup_macho_loadcmds: " 
    1287 +           "requested stack_addr (top) 0x%llx, " 
    1288 +           "stack_size 0x%llx\n", req_stack_addr, req_stack_size ); 
    1289 + 
    1290 +   if (!is_plausible_tool_exe_name(argv[3])) 
    1291 +      fail("implausible tool exe name -- not of the form *-{x86,amd64}-darwin"); 
    1292 + 
    1293 +   fprintf(stderr, "fixup_macho_loadcmds: examining tool exe: %s\n",  
    1294 +           argv[3] ); 
    1295 +   modify_macho_loadcmds( argv[3], req_stack_addr - req_stack_size, 
    1296 +                          req_stack_size ); 
    1297 + 
    1298 +   return 0; 
    1299 +} 
    1300 + 
    1301 +/* 
    1302 +      cmd LC_SEGMENT_64 
    1303 +  cmdsize 72 
    1304 +  segname __LINKEDIT 
    1305 +   vmaddr 0x0000000138dea000 
    1306 +   vmsize 0x00000000000ad000 
    1307 +  fileoff 2658304 
    1308 + filesize 705632 
    1309 +  maxprot 0x00000007 
    1310 + initprot 0x00000001 
    1311 +   nsects 0 
    1312 +    flags 0x0 
    1313 +*/ 
    1314 + 
    1315 +/* 
    1316 +      cmd LC_SEGMENT_64 
    1317 +  cmdsize 72 
    1318 +  segname __UNIXSTACK 
    1319 +   vmaddr 0x0000000133800000 
    1320 +   vmsize 0x0000000000800000 
    1321 +  fileoff 2498560 
    1322 + filesize 0 
    1323 +  maxprot 0x00000007 
    1324 + initprot 0x00000003 
    1325 +   nsects 0 
    1326 +    flags 0x0 
    1327 +*/ 
    1328654Index: coregrind/Makefile.am 
    1329655=================================================================== 
    1330656--- coregrind/Makefile.am       (revision 11685) 
    1331 +++ coregrind/Makefile.am       (revision 11686) 
     657+++ coregrind/Makefile.am       (working copy) 
    1332658@@ -441,3 +441,18 @@ 
    1333   
     659 
    1334660 install-exec-local: install-noinst_PROGRAMS install-noinst_DSYMS 
    1335   
     661 
    1336662+#---------------------------------------------------------------------------- 
    1337663+# Darwin linker kludges 
Note: See TracChangeset for help on using the changeset viewer.