• Open Menu Close Menu
  • Apple
  • Shopping Bag
  • Apple
  • Mac
  • iPad
  • iPhone
  • Watch
  • TV
  • Music
  • Support
  • Search apple.com
  • Shopping Bag

Lists

Open Menu Close Menu
  • Terms and Conditions
  • Lists hosted on this site
  • Email the Postmaster
  • Tips for posting to public mailing lists
Re: [patch] massive libtool speedup for large libs
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [patch] massive libtool speedup for large libs


  • Subject: Re: [patch] massive libtool speedup for large libs
  • From: Scott Wheeler <email@hidden>
  • Date: Tue, 06 Mar 2007 16:26:46 +0100

Scott Wheeler wrote:
I reworked create_library() [...]

I realized that I was forgetting to swap the bytes in the fat header when creating multi-architecture libs (i.e. universal binaries). For anyone that cares, the attached patch is correct.


I'd hoped this would land somewhere that could eventually make it into the official version, but the response to the first version was rather underwhelming.

Cheers,

-Scott
--- libtool.c.orig	2007-02-02 15:19:02.000000000 +0100
+++ libtool.c	2007-03-06 14:45:42.000000000 +0100
@@ -47,6 +47,9 @@
 #include "stuff/execute.h"
 #include "stuff/version_number.h"

+#include <unistd.h>
+#include <sys/mman.h>
+
 #include "make.h"
 #include <mach/mach_init.h>
 #if defined(__OPENSTEP__) || defined(__GONZO_BUNSEN_BEAKER__)
@@ -1915,6 +1918,14 @@
  * archs into the specified output file.  Only when more than one architecture
  * is in archs will a fat file be created.
  */
+
+static void write_padding(int fd, size_t padding_size)
+{
+    char *padding = calloc(1, padding_size);
+    write(fd, padding, padding_size);
+    free(padding);
+}
+
 static
 void
 create_library(
@@ -1922,10 +1933,8 @@
 {
     unsigned long i, j, k, l, library_size, offset, pad, *time_offsets;
     enum byte_sex target_byte_sex;
-    char *library, *p;
-    kern_return_t r;
     struct arch *arch;
-    struct fat_header *fat_header;
+    struct fat_header fat_header;
     struct fat_arch *fat_arch;
     int fd;
 #ifndef __OPENSTEP__
@@ -2006,25 +2015,33 @@
 	    exit(EXIT_SUCCESS);

 	/*
-	 * This buffer is vm_allocate'ed to make sure all holes are filled with
-	 * zero bytes.
+	 * Create the output file.  The unlink() is done to handle the problem
+	 * when the outputfile is not writable but the directory allows the
+	 * file to be removed (since the file may not be there the return code
+	 * of the unlink() is ignored).
 	 */
-	if((r = vm_allocate(mach_task_self(), (vm_address_t *)&library,
-			    library_size, TRUE)) != KERN_SUCCESS)
-	    mach_fatal(r, "can't vm_allocate() buffer for output file: %s of "
-		       "size %lu", output, library_size);
+	(void)unlink(output);
+	if((fd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1){
+	    system_error("can't create output file: %s", output);
+	    return;
+	}
+

 	/*
 	 * If there is more than one architecture then fill in the fat file
 	 * header and the fat_arch structures in the buffer.
 	 */
 	if(narchs > 1){
-	    fat_header = (struct fat_header *)library;
-	    fat_header->magic = FAT_MAGIC;
-	    fat_header->nfat_arch = narchs;
+	    memset(&fat_header, 0, sizeof(struct fat_header));
+	    fat_header.magic = FAT_MAGIC;
+	    fat_header.nfat_arch = narchs;
 	    offset = sizeof(struct fat_header) +
 			    sizeof(struct fat_arch) * narchs;
-	    fat_arch = (struct fat_arch *)(library + sizeof(struct fat_header));
+#ifdef __LITTLE_ENDIAN__
+	    swap_fat_header(&fat_header, BIG_ENDIAN_BYTE_SEX);
+#endif /* __LITTLE_ENDIAN__ */
+	    write(fd, &fat_header, sizeof(struct fat_header));
+	    fat_arch = calloc(narchs, sizeof(struct fat_arch));
 	    for(i = 0; i < narchs; i++){
 		fat_arch[i].cputype = archs[i].arch_flag.cputype;
 		fat_arch[i].cpusubtype = archs[i].arch_flag.cpusubtype;
@@ -2033,12 +2050,13 @@
 		fat_arch[i].align = 2;
 		offset += archs[i].size;
 	    }
+	    offset = sizeof(struct fat_header) +
+			    sizeof(struct fat_arch) * narchs;
 #ifdef __LITTLE_ENDIAN__
-	    swap_fat_header(fat_header, BIG_ENDIAN_BYTE_SEX);
 	    swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX);
 #endif /* __LITTLE_ENDIAN__ */
-	    offset = sizeof(struct fat_header) +
-			    sizeof(struct fat_arch) * narchs;
+	    write(fd, fat_arch, sizeof(struct fat_arch) * narchs);
+	    free(fat_arch);
 	}
 	else
 	    offset = 0;
@@ -2052,8 +2070,8 @@
 	/*
 	 * Now put each arch in the buffer.
 	 */
+
 	for(i = 0; i < narchs; i++){
-	    p = library + offset;
 	    arch = archs + i;

 	    /*
@@ -2065,8 +2083,7 @@
 	     */

 	    /* put in the archive magic string */
-	    memcpy(p, ARMAG, SARMAG);
-	    p += SARMAG;
+	    write(fd, ARMAG, SARMAG);

 	    /*
 	     * Warn for what really is a bad library that has an empty table of
@@ -2105,60 +2122,52 @@
 	     *	a long for the number of bytes of the strings for the ranlibs
 	     *	the strings for the ranlib structs
 	     */
+
 	    time_offsets[i] =
-			 (p - library) +
-			 ((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr);
-	    memcpy(p, (char *)&arch->toc_ar_hdr, sizeof(struct ar_hdr));
-	    p += sizeof(struct ar_hdr);
+		lseek(fd, 0, SEEK_CUR) +
+		((char *)&toc_ar_hdr.ar_date - (char *)&toc_ar_hdr);
+	    write(fd, (char *)&arch->toc_ar_hdr, sizeof(struct ar_hdr));

 	    if(arch->toc_long_name == TRUE){
-		memcpy(p, arch->toc_name, arch->toc_name_size);
-		p += arch->toc_name_size +
-		     (round(sizeof(struct ar_hdr), 8) -
-		      sizeof(struct ar_hdr));
+		write(fd, arch->toc_name, arch->toc_name_size);
+		write_padding(fd, round(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr));
 	    }

 	    l = arch->toc_nranlibs * sizeof(struct ranlib);
 	    if(target_byte_sex != host_byte_sex)
 		l = SWAP_LONG(l);
-	    memcpy(p, (char *)&l, sizeof(long));
-	    p += sizeof(long);
+	    write(fd, (char *)&l, sizeof(long));

 	    if(target_byte_sex != host_byte_sex)
 		swap_ranlib(arch->toc_ranlibs, arch->toc_nranlibs,
 			    target_byte_sex);
-	    memcpy(p, (char *)arch->toc_ranlibs,
-		   arch->toc_nranlibs * sizeof(struct ranlib));
-	    p += arch->toc_nranlibs * sizeof(struct ranlib);
+	    write(fd, (char *)arch->toc_ranlibs,
+		  arch->toc_nranlibs * sizeof(struct ranlib));

 	    l = arch->toc_strsize;
 	    if(target_byte_sex != host_byte_sex)
 		l = SWAP_LONG(l);
-	    memcpy(p, (char *)&l, sizeof(long));
-	    p += sizeof(long);
+	    write(fd, (char *)&l, sizeof(long));

-	    memcpy(p, (char *)arch->toc_strings, arch->toc_strsize);
-	    p += arch->toc_strsize;
+	    write(fd, (char *)arch->toc_strings, arch->toc_strsize);

 	    /*
 	     * Put in the archive header and member contents for each member.
 	     */
 	    for(j = 0; j < arch->nmembers; j++){
-		memcpy(p, (char *)&(arch->members[j].ar_hdr),
-		       sizeof(struct ar_hdr));
-		p += sizeof(struct ar_hdr);
-
+		write(fd, (char *)&(arch->members[j].ar_hdr), sizeof(struct ar_hdr));
 		/*
 		 * If we are using extended format #1 for long names write out
 		 * the name.  Note the name is padded with '\0' and the
 		 * member_name_size is the unrounded size.
 		 */
 		if(arch->members[j].output_long_name == TRUE){
-		    strncpy(p, arch->members[j].member_name,
-			    arch->members[j].member_name_size);
-		    p += round(arch->members[j].member_name_size, 8) +
-			       (round(sizeof(struct ar_hdr), 8) -
-				sizeof(struct ar_hdr));
+		    write(fd, arch->members[j].member_name, arch->members[j].member_name_size);
+		    write_padding(fd,
+				  (round(arch->members[j].member_name_size, 8) -
+				   arch->members[j].member_name_size) +
+				  (round(sizeof(struct ar_hdr), 8) -
+				   sizeof(struct ar_hdr)));
 		}

 		/*
@@ -2178,33 +2187,16 @@
 		       arch->members[j].load_commands) == FALSE)
 			fatal("internal error: swap_object_headers() failed");
 		}
-		memcpy(p, arch->members[j].object_addr,
-		       arch->members[j].object_size);
-		p += arch->members[j].object_size;
+		write(fd, arch->members[j].object_addr, arch->members[j].object_size);
 		pad = round(arch->members[j].object_size, 8) -
 		      arch->members[j].object_size;
 		/* as with the UNIX ar(1) program pad with '\n' characters */
 		for(k = 0; k < pad; k++)
-		    *p++ = '\n';
+		    write(fd, "\n", 1);
 	    }
 	    offset += arch->size;
 	}

-	/*
-	 * Create the output file.  The unlink() is done to handle the problem
-	 * when the outputfile is not writable but the directory allows the
-	 * file to be removed (since the file may not be there the return code
-	 * of the unlink() is ignored).
-	 */
-	(void)unlink(output);
-	if((fd = open(output, O_WRONLY | O_CREAT | O_TRUNC, 0666)) == -1){
-	    system_error("can't create output file: %s", output);
-	    return;
-	}
-	if(write(fd, library, library_size) != (int)library_size){
-	    system_error("can't write output file: %s", output);
-	    return;
-	}
 	if(close(fd) == -1){
 	    system_fatal("can't close output file: %s", output);
 	    return;
@@ -2265,11 +2257,6 @@
 			 output);
 	    return;
 	}
-	if((r = vm_deallocate(mach_task_self(), (vm_address_t)library,
-			      library_size)) != KERN_SUCCESS){
-	    my_mach_error(r, "can't vm_deallocate() buffer for output file");
-	    return;
-	}
 }

 /*
 _______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list      (email@hidden)
Help/Unsubscribe/Update your Subscription:

This email sent to email@hidden

  • Follow-Ups:
    • Re: [patch] massive libtool speedup for large libs
      • From: "B.J. Buchalter" <email@hidden>
    • Re: [patch] massive libtool speedup for large libs
      • From: Scott Wheeler <email@hidden>
  • Prev by Date: Re: libgmalloc bug
  • Next by Date: Re: [patch] massive libtool speedup for large libs
  • Previous by thread: Re: [patch] massive libtool speedup for large libs
  • Next by thread: Re: [patch] massive libtool speedup for large libs
  • Index(es):
    • Date
    • Thread