Re: [patch] massive libtool speedup for large libs
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