From 5da03791a71a6c5b3b1ef15ec8882bffa21ceb39 Mon Sep 17 00:00:00 2001 From: nealsid Date: Tue, 15 Apr 2008 23:09:30 +0000 Subject: As part of resolving issue 256 I'd like to check in some unit tests(ok, just one) for the private copy of nlist that I checked in last week, plus lay some of the ground work for collecting code coverage numbers. Both of these are accomplished by leveraging the built-in facilities of Xcode & Developer Tools(namely, CPlusTest and gcov integration; however, eventually I will also add a way to get lcov results from the gcov results). I also: - renamed breakpad_nlist_64.c to breakpad_nlist_64.cc to be more consistent(even though it's not C++ code it still only gets called by C++ code so I don't have to deal with extern "C" constructs). - I created a new target (minidump_tests) that has a "Coverage" configuration with the appropriate GCC flags turned on. It is only compiled in 64-bit configurations and has 10.5 as a minimum deployment target as well as uses the 10.5 SDK. git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@260 4c0a9323-5329-0410-9bdc-e9ce6186880e --- src/client/mac/handler/breakpad_nlist_64.c | 369 -------------------- src/client/mac/handler/breakpad_nlist_64.cc | 381 +++++++++++++++++++++ src/client/mac/handler/breakpad_nlist_test.cc | 81 +++++ src/client/mac/handler/breakpad_nlist_test.h | 43 +++ .../minidump_test.xcodeproj/project.pbxproj | 253 ++++++++++++++ src/client/mac/handler/minidump_tests-Info.plist | 20 ++ src/client/minidump_file_writer_unittest.cc | 12 + 7 files changed, 790 insertions(+), 369 deletions(-) delete mode 100644 src/client/mac/handler/breakpad_nlist_64.c create mode 100644 src/client/mac/handler/breakpad_nlist_64.cc create mode 100644 src/client/mac/handler/breakpad_nlist_test.cc create mode 100644 src/client/mac/handler/breakpad_nlist_test.h create mode 100644 src/client/mac/handler/minidump_tests-Info.plist (limited to 'src') diff --git a/src/client/mac/handler/breakpad_nlist_64.c b/src/client/mac/handler/breakpad_nlist_64.c deleted file mode 100644 index 2429235b..00000000 --- a/src/client/mac/handler/breakpad_nlist_64.c +++ /dev/null @@ -1,369 +0,0 @@ -/* - * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - -/* nealsid: - * This file was copied from libc/gen/nlist.c from Darwin's source code - * The version of nlist used as a base is from 10.5.2, libc-498 - * http://www.opensource.apple.com/darwinsource/10.5.2/Libc-498/gen/nlist.c - * - * The full tarball is at: - * http://www.opensource.apple.com/darwinsource/tarballs/apsl/Libc-498.tar.gz - * - * I've modified it to be compatible with 64-bit images. However, - * 32-bit compatibility has not been retained. -*/ - -#ifdef __LP64__ - -#include "breakpad_nlist_64.h" - -/* Stuff lifted from and since they are gone */ -/* - * Header prepended to each a.out file. - */ -struct exec { - unsigned short a_machtype; /* machine type */ - unsigned short a_magic; /* magic number */ - unsigned long a_text; /* size of text segment */ - unsigned long a_data; /* size of initialized data */ - unsigned long a_bss; /* size of uninitialized data */ - unsigned long a_syms; /* size of symbol table */ - unsigned long a_entry; /* entry point */ - unsigned long a_trsize; /* size of text relocation */ - unsigned long a_drsize; /* size of data relocation */ -}; - -#define OMAGIC 0407 /* old impure format */ -#define NMAGIC 0410 /* read-only text */ -#define ZMAGIC 0413 /* demand load format */ - -#define N_BADMAG(x) \ - (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC) -#define N_TXTOFF(x) \ - ((x).a_magic==ZMAGIC ? 0 : sizeof (struct exec)) -#define N_SYMOFF(x) \ - (N_TXTOFF(x) + (x).a_text+(x).a_data + (x).a_trsize+(x).a_drsize) - -/* - * nlist - retreive attributes from name list (string table version) - */ - -int -breakpad_nlist_64(const char *name, - breakpad_nlist *list, - const char **symbolNames) -{ - int fd, n; - - fd = open(name, O_RDONLY, 0); - if (fd < 0) - return (-1); - n = __breakpad_fdnlist_64(fd, list, symbolNames); - (void)close(fd); - return (n); -} - -/* Note: __fdnlist() is called from kvm_nlist in libkvm's kvm.c */ - -int -__breakpad_fdnlist_64(int fd, breakpad_nlist *list, const char **symbolNames) -{ - register breakpad_nlist *p, *q; - breakpad_nlist space[BUFSIZ/sizeof (breakpad_nlist)]; - - const register char *s1, *s2; - register int n, m; - int maxlen, nreq; - off_t sa; /* symbol address */ - off_t ss; /* start of strings */ - struct exec buf; - unsigned arch_offset = 0; - - maxlen = 500; - for (q = list, nreq = 0; - symbolNames[q-list] && symbolNames[q-list][0]; - q++, nreq++) { - - q->n_type = 0; - q->n_value = 0; - q->n_desc = 0; - q->n_sect = 0; - q->n_un.n_strx = 0; - } - - if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf) || - (N_BADMAG(buf) && *((long *)&buf) != MH_MAGIC && - NXSwapBigLongToHost(*((long *)&buf)) != FAT_MAGIC) && - /* nealsid: The following is the big-endian ppc64 check */ - (*((uint32_t*)&buf)) != FAT_MAGIC) { - return (-1); - } - - /* Deal with fat file if necessary */ - if (NXSwapBigLongToHost(*((long *)&buf)) == FAT_MAGIC || - /* nealsid: The following is the big-endian ppc64 check */ - *((int*)&buf) == FAT_MAGIC) { - struct host_basic_info hbi; - struct fat_header fh; - struct fat_arch *fat_archs, *fap; - unsigned i; - host_t host; - - /* Get our host info */ - host = mach_host_self(); - i = HOST_BASIC_INFO_COUNT; - kern_return_t kr; - if ((kr=host_info(host, HOST_BASIC_INFO, - (host_info_t)(&hbi), &i)) != KERN_SUCCESS) { - return (-1); - } - mach_port_deallocate(mach_task_self(), host); - - /* Read in the fat header */ - lseek(fd, 0, SEEK_SET); - if (read(fd, (char *)&fh, sizeof(fh)) != sizeof(fh)) { - return (-1); - } - - /* Convert fat_narchs to host byte order */ - fh.nfat_arch = NXSwapBigLongToHost(fh.nfat_arch); - - /* Read in the fat archs */ - fat_archs = (struct fat_arch *)malloc(fh.nfat_arch * - sizeof(struct fat_arch)); - if (fat_archs == NULL) { - return (-1); - } - if (read(fd, (char *)fat_archs, - sizeof(struct fat_arch) * fh.nfat_arch) != - sizeof(struct fat_arch) * fh.nfat_arch) { - free(fat_archs); - return (-1); - } - - /* - * Convert archs to host byte ordering (a constraint of - * cpusubtype_getbestarch() - */ - for (i = 0; i < fh.nfat_arch; i++) { - fat_archs[i].cputype = - NXSwapBigLongToHost(fat_archs[i].cputype); - fat_archs[i].cpusubtype = - NXSwapBigLongToHost(fat_archs[i].cpusubtype); - fat_archs[i].offset = - NXSwapBigLongToHost(fat_archs[i].offset); - fat_archs[i].size = - NXSwapBigLongToHost(fat_archs[i].size); - fat_archs[i].align = - NXSwapBigLongToHost(fat_archs[i].align); - } - - fap = NULL; - for (i = 0; i < fh.nfat_arch; i++) { - /* nealsid: Although the original Apple code uses host_info */ - /* to retrieve the CPU type, the host_info will still return */ - /* CPU_TYPE_X86 even if running as an x86_64 binary. Given that */ - /* this code isn't necessary on i386, I've decided to hardcode */ - /* looking for a 64-bit binary */ -#if TARGET_CPU_X86_64 - if (fat_archs[i].cputype == CPU_TYPE_X86_64) { -#elif TARGET_CPU_PPC64 - if (fat_archs[i].cputype == CPU_TYPE_POWERPC64) { -#else -#error undefined cpu! - { -#endif - fap = &fat_archs[i]; - break; - } - } - - if (!fap) { - free(fat_archs); - return (-1); - } - arch_offset = fap->offset; - free(fat_archs); - - /* Read in the beginning of the architecture-specific file */ - lseek(fd, arch_offset, SEEK_SET); - if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf)) { - return (-1); - } - } - - if (*((int *)&buf) == MH_MAGIC_64) { - struct mach_header_64 mh; - struct load_command *load_commands, *lcp; - struct symtab_command *stp; - long i; - - lseek(fd, arch_offset, SEEK_SET); - if (read(fd, (char *)&mh, sizeof(mh)) != sizeof(mh)) { - return (-1); - } - load_commands = (struct load_command *)malloc(mh.sizeofcmds); - if (load_commands == NULL) { - return (-1); - } - if (read(fd, (char *)load_commands, mh.sizeofcmds) != - mh.sizeofcmds) { - free(load_commands); - return (-1); - } - stp = NULL; - lcp = load_commands; - // nealsid:iterate through all load commands, looking for - // LC_SYMTAB load command - for (i = 0; i < mh.ncmds; i++) { - if (lcp->cmdsize % sizeof(long) != 0 || - lcp->cmdsize <= 0 || - (char *)lcp + lcp->cmdsize > - (char *)load_commands + mh.sizeofcmds) { - free(load_commands); - return (-1); - } - if (lcp->cmd == LC_SYMTAB) { - if (lcp->cmdsize != - sizeof(struct symtab_command)) { - free(load_commands); - return (-1); - } - stp = (struct symtab_command *)lcp; - break; - } - lcp = (struct load_command *) - ((char *)lcp + lcp->cmdsize); - } - if (stp == NULL) { - free(load_commands); - return (-1); - } - // sa points to the beginning of the symbol table - sa = stp->symoff + arch_offset; - // ss points to the beginning of the string table - ss = stp->stroff + arch_offset; - // n is the number of bytes in the symbol table - // each symbol table entry is an nlist structure - n = stp->nsyms * sizeof(breakpad_nlist); - free(load_commands); - } - else { - sa = N_SYMOFF(buf) + arch_offset; - ss = sa + buf.a_syms + arch_offset; - n = buf.a_syms; - } - - lseek(fd, sa, SEEK_SET); - - // the algorithm here is to read the nlist entries in m-sized - // chunks into q. q is then iterated over. for each entry in q, - // use the string table index(q->n_un.n_strx) to read the symbol - // name, then scan the nlist entries passed in by the user(via p), - // and look for a match - while (n) { - long savpos; - - m = sizeof (space); - if (n < m) - m = n; - if (read(fd, (char *)space, m) != m) - break; - n -= m; - savpos = lseek(fd, 0, SEEK_CUR); - for (q = space; (m -= sizeof(breakpad_nlist)) >= 0; q++) { - char nambuf[BUFSIZ]; - - if (q->n_un.n_strx == 0 || q->n_type & N_STAB) - continue; - - // seek to the location in the binary where the symbol - // name is stored & read it into memory - lseek(fd, ss+q->n_un.n_strx, SEEK_SET); - read(fd, nambuf, maxlen+1); - s2 = nambuf; - for (p = list; - symbolNames[p-list] && - symbolNames[p-list][0]; - p++) { - // get the symbol name the user has passed in that - // corresponds to the nlist entry that we're looking at - s1 = symbolNames[p - list]; - while (*s1) { - if (*s1++ != *s2++) - goto cont; - } - if (*s2) - goto cont; - - p->n_value = q->n_value; - p->n_type = q->n_type; - p->n_desc = q->n_desc; - p->n_sect = q->n_sect; - p->n_un.n_strx = q->n_un.n_strx; - if (--nreq == 0) - return (nreq); - - break; - cont: ; - } - } - lseek(fd, savpos, SEEK_SET); - } - return (nreq); - } - -#endif /* __LP64__ */ diff --git a/src/client/mac/handler/breakpad_nlist_64.cc b/src/client/mac/handler/breakpad_nlist_64.cc new file mode 100644 index 00000000..c220d88d --- /dev/null +++ b/src/client/mac/handler/breakpad_nlist_64.cc @@ -0,0 +1,381 @@ +/* + * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + +/* nealsid: + * This file was copied from libc/gen/nlist.c from Darwin's source code + * The version of nlist used as a base is from 10.5.2, libc-498 + * http://www.opensource.apple.com/darwinsource/10.5.2/Libc-498/gen/nlist.c + * + * The full tarball is at: + * http://www.opensource.apple.com/darwinsource/tarballs/apsl/Libc-498.tar.gz + * + * I've modified it to be compatible with 64-bit images. However, + * 32-bit compatibility has not been retained. +*/ + +#ifdef __LP64__ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "breakpad_nlist_64.h" +#include +#include +#include + +/* Stuff lifted from and since they are gone */ +/* + * Header prepended to each a.out file. + */ +struct exec { + unsigned short a_machtype; /* machine type */ + unsigned short a_magic; /* magic number */ + unsigned long a_text; /* size of text segment */ + unsigned long a_data; /* size of initialized data */ + unsigned long a_bss; /* size of uninitialized data */ + unsigned long a_syms; /* size of symbol table */ + unsigned long a_entry; /* entry point */ + unsigned long a_trsize; /* size of text relocation */ + unsigned long a_drsize; /* size of data relocation */ +}; + +#define OMAGIC 0407 /* old impure format */ +#define NMAGIC 0410 /* read-only text */ +#define ZMAGIC 0413 /* demand load format */ + +#define N_BADMAG(x) \ + (((x).a_magic)!=OMAGIC && ((x).a_magic)!=NMAGIC && ((x).a_magic)!=ZMAGIC) +#define N_TXTOFF(x) \ + ((x).a_magic==ZMAGIC ? 0 : sizeof (struct exec)) +#define N_SYMOFF(x) \ + (N_TXTOFF(x) + (x).a_text+(x).a_data + (x).a_trsize+(x).a_drsize) + +int +__breakpad_fdnlist_64(int fd, breakpad_nlist *list, const char **symbolNames); + +/* + * nlist - retreive attributes from name list (string table version) + */ + +int +breakpad_nlist_64(const char *name, + breakpad_nlist *list, + const char **symbolNames) { + int fd, n; + + fd = open(name, O_RDONLY, 0); + if (fd < 0) + return (-1); + n = __breakpad_fdnlist_64(fd, list, symbolNames); + (void)close(fd); + return (n); +} + +/* Note: __fdnlist() is called from kvm_nlist in libkvm's kvm.c */ + +int +__breakpad_fdnlist_64(int fd, breakpad_nlist *list, const char **symbolNames) { + register breakpad_nlist *p, *q; + breakpad_nlist space[BUFSIZ/sizeof (breakpad_nlist)]; + + const register char *s1, *s2; + register int n, m; + int maxlen, nreq; + off_t sa; /* symbol address */ + off_t ss; /* start of strings */ + struct exec buf; + unsigned arch_offset = 0; + + maxlen = 500; + for (q = list, nreq = 0; + symbolNames[q-list] && symbolNames[q-list][0]; + q++, nreq++) { + + q->n_type = 0; + q->n_value = 0; + q->n_desc = 0; + q->n_sect = 0; + q->n_un.n_strx = 0; + } + + if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf) || + (N_BADMAG(buf) && *((long *)&buf) != MH_MAGIC && + NXSwapBigLongToHost(*((long *)&buf)) != FAT_MAGIC) && + /* nealsid: The following is the big-endian ppc64 check */ + (*((uint32_t*)&buf)) != FAT_MAGIC) { + return (-1); + } + + /* Deal with fat file if necessary */ + if (NXSwapBigLongToHost(*((long *)&buf)) == FAT_MAGIC || + /* nealsid: The following is the big-endian ppc64 check */ + *((int*)&buf) == FAT_MAGIC) { + struct host_basic_info hbi; + struct fat_header fh; + struct fat_arch *fat_archs, *fap; + unsigned i; + host_t host; + + /* Get our host info */ + host = mach_host_self(); + i = HOST_BASIC_INFO_COUNT; + kern_return_t kr; + if ((kr=host_info(host, HOST_BASIC_INFO, + (host_info_t)(&hbi), &i)) != KERN_SUCCESS) { + return (-1); + } + mach_port_deallocate(mach_task_self(), host); + + /* Read in the fat header */ + lseek(fd, 0, SEEK_SET); + if (read(fd, (char *)&fh, sizeof(fh)) != sizeof(fh)) { + return (-1); + } + + /* Convert fat_narchs to host byte order */ + fh.nfat_arch = NXSwapBigLongToHost(fh.nfat_arch); + + /* Read in the fat archs */ + fat_archs = (struct fat_arch *)malloc(fh.nfat_arch * + sizeof(struct fat_arch)); + if (fat_archs == NULL) { + return (-1); + } + if (read(fd, (char *)fat_archs, + sizeof(struct fat_arch) * fh.nfat_arch) != + sizeof(struct fat_arch) * fh.nfat_arch) { + free(fat_archs); + return (-1); + } + + /* + * Convert archs to host byte ordering (a constraint of + * cpusubtype_getbestarch() + */ + for (i = 0; i < fh.nfat_arch; i++) { + fat_archs[i].cputype = + NXSwapBigLongToHost(fat_archs[i].cputype); + fat_archs[i].cpusubtype = + NXSwapBigLongToHost(fat_archs[i].cpusubtype); + fat_archs[i].offset = + NXSwapBigLongToHost(fat_archs[i].offset); + fat_archs[i].size = + NXSwapBigLongToHost(fat_archs[i].size); + fat_archs[i].align = + NXSwapBigLongToHost(fat_archs[i].align); + } + + fap = NULL; + for (i = 0; i < fh.nfat_arch; i++) { + /* nealsid: Although the original Apple code uses host_info */ + /* to retrieve the CPU type, the host_info will still return */ + /* CPU_TYPE_X86 even if running as an x86_64 binary. Given that */ + /* this code isn't necessary on i386, I've decided to hardcode */ + /* looking for a 64-bit binary */ +#if TARGET_CPU_X86_64 + if (fat_archs[i].cputype == CPU_TYPE_X86_64) { +#elif TARGET_CPU_PPC64 + if (fat_archs[i].cputype == CPU_TYPE_POWERPC64) { +#else +#error undefined cpu! + { +#endif + fap = &fat_archs[i]; + break; + } + } + + if (!fap) { + free(fat_archs); + return (-1); + } + arch_offset = fap->offset; + free(fat_archs); + + /* Read in the beginning of the architecture-specific file */ + lseek(fd, arch_offset, SEEK_SET); + if (read(fd, (char *)&buf, sizeof(buf)) != sizeof(buf)) { + return (-1); + } + } + + if (*((int *)&buf) == MH_MAGIC_64) { + struct mach_header_64 mh; + struct load_command *load_commands, *lcp; + struct symtab_command *stp; + long i; + + lseek(fd, arch_offset, SEEK_SET); + if (read(fd, (char *)&mh, sizeof(mh)) != sizeof(mh)) { + return (-1); + } + load_commands = (struct load_command *)malloc(mh.sizeofcmds); + if (load_commands == NULL) { + return (-1); + } + if (read(fd, (char *)load_commands, mh.sizeofcmds) != + mh.sizeofcmds) { + free(load_commands); + return (-1); + } + stp = NULL; + lcp = load_commands; + // nealsid:iterate through all load commands, looking for + // LC_SYMTAB load command + for (i = 0; i < mh.ncmds; i++) { + if (lcp->cmdsize % sizeof(long) != 0 || + lcp->cmdsize <= 0 || + (char *)lcp + lcp->cmdsize > + (char *)load_commands + mh.sizeofcmds) { + free(load_commands); + return (-1); + } + if (lcp->cmd == LC_SYMTAB) { + if (lcp->cmdsize != + sizeof(struct symtab_command)) { + free(load_commands); + return (-1); + } + stp = (struct symtab_command *)lcp; + break; + } + lcp = (struct load_command *) + ((char *)lcp + lcp->cmdsize); + } + if (stp == NULL) { + free(load_commands); + return (-1); + } + // sa points to the beginning of the symbol table + sa = stp->symoff + arch_offset; + // ss points to the beginning of the string table + ss = stp->stroff + arch_offset; + // n is the number of bytes in the symbol table + // each symbol table entry is an nlist structure + n = stp->nsyms * sizeof(breakpad_nlist); + free(load_commands); + } + else { + sa = N_SYMOFF(buf) + arch_offset; + ss = sa + buf.a_syms + arch_offset; + n = buf.a_syms; + } + + lseek(fd, sa, SEEK_SET); + + // the algorithm here is to read the nlist entries in m-sized + // chunks into q. q is then iterated over. for each entry in q, + // use the string table index(q->n_un.n_strx) to read the symbol + // name, then scan the nlist entries passed in by the user(via p), + // and look for a match + while (n) { + long savpos; + + m = sizeof (space); + if (n < m) + m = n; + if (read(fd, (char *)space, m) != m) + break; + n -= m; + savpos = lseek(fd, 0, SEEK_CUR); + for (q = space; (m -= sizeof(breakpad_nlist)) >= 0; q++) { + char nambuf[BUFSIZ]; + + if (q->n_un.n_strx == 0 || q->n_type & N_STAB) + continue; + + // seek to the location in the binary where the symbol + // name is stored & read it into memory + lseek(fd, ss+q->n_un.n_strx, SEEK_SET); + read(fd, nambuf, maxlen+1); + s2 = nambuf; + for (p = list; + symbolNames[p-list] && + symbolNames[p-list][0]; + p++) { + // get the symbol name the user has passed in that + // corresponds to the nlist entry that we're looking at + s1 = symbolNames[p - list]; + while (*s1) { + if (*s1++ != *s2++) + goto cont; + } + if (*s2) + goto cont; + + p->n_value = q->n_value; + p->n_type = q->n_type; + p->n_desc = q->n_desc; + p->n_sect = q->n_sect; + p->n_un.n_strx = q->n_un.n_strx; + if (--nreq == 0) + return (nreq); + + break; + cont: ; + } + } + lseek(fd, savpos, SEEK_SET); + } + return (nreq); + } + +#endif /* __LP64__ */ diff --git a/src/client/mac/handler/breakpad_nlist_test.cc b/src/client/mac/handler/breakpad_nlist_test.cc new file mode 100644 index 00000000..d0dd2f6a --- /dev/null +++ b/src/client/mac/handler/breakpad_nlist_test.cc @@ -0,0 +1,81 @@ +/* + * BreakpadNlistTest.cpp + * minidump_test + * + * Created by Neal Sidhwaney on 4/13/08. + * Copyright 2008 Google Inc. All rights reserved. + * + */ + +#include "breakpad_nlist_test.h" +#include +#include "breakpad_nlist_64.h" + +BreakpadNlistTest test1(TEST_INVOCATION(BreakpadNlistTest, CompareToNM)); + +BreakpadNlistTest::BreakpadNlistTest(TestInvocation *invocation) + : TestCase(invocation) { +} + + +BreakpadNlistTest::~BreakpadNlistTest() { +} + +void BreakpadNlistTest::CompareToNM() { +#if TARGET_CPU_X86_64 + system("/usr/bin/nm -arch x86_64 /usr/lib/dyld > /tmp/dyld-namelist.txt"); +#elif TARGET_CPU_PPC64 + system("/usr/bin/nm -arch ppc64 /usr/lib/dyld > /tmp/dyld-namelist.txt"); +#endif + + FILE *fd = fopen("/tmp/dyld-namelist.txt","rt"); + + char oneNMAddr[30]; + char symbolType; + char symbolName[500]; + while(!feof(fd)) { + fscanf(fd,"%s %c %s",oneNMAddr, &symbolType, symbolName); + breakpad_nlist symbolList[2]; + breakpad_nlist &list = symbolList[0]; + + memset(symbolList,0, sizeof(breakpad_nlist)*2); + const char *symbolNames[2]; + symbolNames[0] = (const char*)symbolName; + symbolNames[1] = "\0"; + breakpad_nlist_64("/usr/lib/dyld",&list, symbolNames); + uint64_t nmAddr = strtol(oneNMAddr,NULL,16); + if(!IsSymbolMoreThanOnceInDyld(symbolName)) { + CPTAssert(nmAddr == symbolList[0].n_value); + } + } + + fclose(fd); +} + +bool BreakpadNlistTest::IsSymbolMoreThanOnceInDyld(const char *symbolName) { + //These are the symbols that occur more than once when nm dumps + // the symbol table of /usr/lib/dyld. Our nlist program returns + // the first address because it's doing a search so we need to exclude + // these from causing the test to fail + const char *multipleSymbols[] = { + "__Z41__static_initialization_and_destruction_0ii", + "___tcf_0", + "___tcf_1", + "_read_encoded_value_with_base", + "_read_sleb128", + "_read_uleb128", + "\0"}; + + bool found = false; + + for(int i = 0; multipleSymbols[i][0]; i++) { + if(!strcmp(multipleSymbols[i],symbolName)) { + found = true; + break; + } + + } + + return found; + +} diff --git a/src/client/mac/handler/breakpad_nlist_test.h b/src/client/mac/handler/breakpad_nlist_test.h new file mode 100644 index 00000000..c778a9b3 --- /dev/null +++ b/src/client/mac/handler/breakpad_nlist_test.h @@ -0,0 +1,43 @@ +/* + * BreakpadNlistTest.h + * minidump_test + * + * Created by Neal Sidhwaney on 4/13/08. + * Copyright 2008 Google Inc. All rights reserved. + * + */ + +#include + +/* +__Z41__static_initialization_and_destruction_0ii +__Z41__static_initialization_and_destruction_0ii +__Z41__static_initialization_and_destruction_0ii +___tcf_0 +___tcf_0 +___tcf_0 +___tcf_1 +_read_encoded_value_with_base +_read_sleb128 +_read_uleb128 + +*/ + +class BreakpadNlistTest : public TestCase { +private: + + // nm dumps multiple addresses for the same symbol in + // /usr/lib/dyld. So we track those so we don't report failures + // in mismatches between what our nlist returns and what nm has + // for the duplicate symbols. + bool IsSymbolMoreThanOnceInDyld(const char *symbolName); + +public: + BreakpadNlistTest(TestInvocation* invocation); + virtual ~BreakpadNlistTest(); + + + /* This test case runs nm on /usr/lib/dyld and then compares the + output of every symbol to what our nlist implementation returns */ + void CompareToNM(); +}; diff --git a/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj b/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj index f3c7665f..8e3e9567 100644 --- a/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj +++ b/src/client/mac/handler/minidump_test.xcodeproj/project.pbxproj @@ -49,6 +49,8 @@ D2F6511E0BEF973600920385 /* macho_id.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FC0BEF947200920385 /* macho_id.cc */; }; D2F6511F0BEF973900920385 /* macho_utilities.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F650FE0BEF947200920385 /* macho_utilities.cc */; }; D2F651210BEF975400920385 /* macho_walker.cc in Sources */ = {isa = PBXBuildFile; fileRef = D2F6510C0BEF94EB00920385 /* macho_walker.cc */; }; + F982089C0DB3280D0017AECA /* breakpad_nlist_test.cc in Sources */ = {isa = PBXBuildFile; fileRef = F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */; }; + F98208A30DB32CAE0017AECA /* breakpad_nlist_64.cc in Sources */ = {isa = PBXBuildFile; fileRef = F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -106,6 +108,12 @@ D2F651080BEF949A00920385 /* dynamic_images.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = dynamic_images.h; sourceTree = ""; }; D2F6510C0BEF94EB00920385 /* macho_walker.cc */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = macho_walker.cc; path = ../../../common/mac/macho_walker.cc; sourceTree = SOURCE_ROOT; }; D2F6510D0BEF94EB00920385 /* macho_walker.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; name = macho_walker.h; path = ../../../common/mac/macho_walker.h; sourceTree = SOURCE_ROOT; }; + F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_test.h; sourceTree = ""; }; + F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_test.cc; sourceTree = ""; }; + F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = breakpad_nlist_64.cc; sourceTree = ""; }; + F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = breakpad_nlist_64.h; sourceTree = ""; }; + F9AE19B50DB040E300C98454 /* minidump_tests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "minidump_tests-Info.plist"; sourceTree = ""; }; + F9AE19C30DB04A9500C98454 /* minidump_tests.cptest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = minidump_tests.cptest; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -132,12 +140,21 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F9AE19C00DB04A9500C98454 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 08FB7794FE84155DC02AAC07 /* MinidumpWriter */ = { isa = PBXGroup; children = ( + F98208A10DB32CAE0017AECA /* breakpad_nlist_64.cc */, + F98208A20DB32CAE0017AECA /* breakpad_nlist_64.h */, D2F6510C0BEF94EB00920385 /* macho_walker.cc */, D2F6510D0BEF94EB00920385 /* macho_walker.h */, D2F651070BEF949A00920385 /* dynamic_images.cc */, @@ -152,6 +169,9 @@ 08FB7795FE84155DC02AAC07 /* Source */, 9B37CEEA0AF98EB600FA4BD4 /* Frameworks */, 1AB674ADFE9D54B511CA2CBB /* Products */, + F9AE19B50DB040E300C98454 /* minidump_tests-Info.plist */, + F982089A0DB3280D0017AECA /* breakpad_nlist_test.h */, + F982089B0DB3280D0017AECA /* breakpad_nlist_test.cc */, ); name = MinidumpWriter; sourceTree = ""; @@ -172,6 +192,7 @@ 8DD76F6C0486A84900D96B5E /* generator_test */, 9BD82A9B0B00267E0055103E /* handler_test */, 9B7CA84E0B1297F200CD3A1D /* unit_test */, + F9AE19C30DB04A9500C98454 /* minidump_tests.cptest */, ); name = Products; sourceTree = ""; @@ -257,23 +278,70 @@ productReference = 9BD82A9B0B00267E0055103E /* handler_test */; productType = "com.apple.product-type.tool"; }; + F9AE19C20DB04A9500C98454 /* minidump_tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = F9AE19C70DB04AA200C98454 /* Build configuration list for PBXNativeTarget "minidump_tests" */; + buildPhases = ( + F9AE19BE0DB04A9500C98454 /* Resources */, + F9AE19BF0DB04A9500C98454 /* Sources */, + F9AE19C00DB04A9500C98454 /* Frameworks */, + F9AE19C10DB04A9500C98454 /* ShellScript */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = minidump_tests; + productName = minidump_tests; + productReference = F9AE19C30DB04A9500C98454 /* minidump_tests.cptest */; + productType = "com.apple.product-type.bundle"; + }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 08FB7793FE84155DC02AAC07 /* Project object */ = { isa = PBXProject; buildConfigurationList = 1DEB923508733DC60010E9CD /* Build configuration list for PBXProject "minidump_test" */; + compatibilityVersion = "Xcode 2.4"; hasScannedForEncodings = 1; mainGroup = 08FB7794FE84155DC02AAC07 /* MinidumpWriter */; projectDirPath = ""; + projectRoot = ""; targets = ( 8DD76F620486A84900D96B5E /* generator_test */, 9BD82A9A0B00267E0055103E /* handler_test */, 9B7CA84D0B1297F200CD3A1D /* unit_test */, + F9AE19C20DB04A9500C98454 /* minidump_tests */, ); }; /* End PBXProject section */ +/* Begin PBXResourcesBuildPhase section */ + F9AE19BE0DB04A9500C98454 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXShellScriptBuildPhase section */ + F9AE19C10DB04A9500C98454 /* ShellScript */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "# Run the unit tests in this test bundle.\n\"${SYSTEM_DEVELOPER_DIR}/Tools/RunUnitTests\"\n# Run gcov on the framework getting tested\nif [ \"${CONFIGURATION}\" = 'Coverage' ];\nthen\n FRAMEWORK_NAME=minidump_tests\n FRAMEWORK_OBJ_DIR=${OBJROOT}/${PROJECT_NAME}.build/${CONFIGURATION}/${FRAMEWORK_NAME}.build/Objects-normal/${NATIVE_ARCH_ACTUAL}\n mkdir -p coverage\n pushd coverage\n echo find ${OBJROOT} -name *.gcda -exec gcov -o ${FRAMEWORK_OBJ_DIR} {} \\;\n find ${OBJROOT} -name *.gcda -exec gcov -o ${FRAMEWORK_OBJ_DIR} {} \\;\n popd\nfi "; + }; +/* End PBXShellScriptBuildPhase section */ + /* Begin PBXSourcesBuildPhase section */ 8DD76F640486A84900D96B5E /* Sources */ = { isa = PBXSourcesBuildPhase; @@ -324,6 +392,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + F9AE19BF0DB04A9500C98454 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + F982089C0DB3280D0017AECA /* breakpad_nlist_test.cc in Sources */, + F98208A30DB32CAE0017AECA /* breakpad_nlist_64.cc in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ @@ -456,6 +533,168 @@ }; name = Release; }; + F996CB8C0DB40AE30089CCC8 /* Coverage */ = { + isa = XCBuildConfiguration; + buildSettings = { + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_LDFLAGS = "-lcrypto"; + PREBINDING = NO; + SDKROOT = /Developer/SDKs/MacOSX10.4u.sdk; + }; + name = Coverage; + }; + F996CB8D0DB40AE30089CCC8 /* Coverage */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_CW_ASM_SYNTAX = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_ENABLE_PASCAL_STRINGS = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_THREADSAFE_STATICS = NO; + INSTALL_PATH = "$(HOME)/bin"; + PRODUCT_NAME = generator_test; + USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)"; + ZERO_LINK = NO; + }; + name = Coverage; + }; + F996CB8E0DB40AE30089CCC8 /* Coverage */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(NATIVE_ARCH)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + INSTALL_PATH = "$(HOME)/bin"; + OTHER_CFLAGS = "-Wall"; + PREBINDING = NO; + PRODUCT_NAME = handler_test; + USER_HEADER_SEARCH_PATHS = "../../.. $(inherited)"; + ZERO_LINK = NO; + }; + name = Coverage; + }; + F996CB8F0DB40AE30089CCC8 /* Coverage */ = { + isa = XCBuildConfiguration; + buildSettings = { + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = YES; + GCC_GENERATE_DEBUGGING_SYMBOLS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + INSTALL_PATH = "$(HOME)/bin"; + PREBINDING = NO; + PRODUCT_NAME = unit_test; + USER_HEADER_SEARCH_PATHS = "../../../** $(inherited)"; + ZERO_LINK = NO; + }; + name = Coverage; + }; + F996CB900DB40AE30089CCC8 /* Coverage */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + "$(NATIVE_ARCH_64_BIT)", + ppc64, + ); + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_GENERATE_TEST_COVERAGE_FILES = YES; + GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; + INFOPLIST_FILE = "minidump_tests-Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; + MACOSX_DEPLOYMENT_TARGET = 10.5; + OTHER_LDFLAGS = ( + "-framework", + Carbon, + "-framework", + CPlusTest, + "-lgcov", + ); + PREBINDING = NO; + PRODUCT_NAME = minidump_tests; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + WRAPPER_EXTENSION = cptest; + }; + name = Coverage; + }; + F9AE19C40DB04A9500C98454 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + "$(NATIVE_ARCH_64_BIT)", + ppc64, + ); + COPY_PHASE_STRIP = NO; + FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; + INFOPLIST_FILE = "minidump_tests-Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; + MACOSX_DEPLOYMENT_TARGET = 10.5; + OTHER_LDFLAGS = ( + "-framework", + Carbon, + "-framework", + CPlusTest, + ); + PREBINDING = NO; + PRODUCT_NAME = minidump_tests; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + WRAPPER_EXTENSION = cptest; + }; + name = Debug; + }; + F9AE19C50DB04A9500C98454 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = ( + "$(NATIVE_ARCH_64_BIT)", + ppc64, + ); + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + FRAMEWORK_SEARCH_PATHS = "$(DEVELOPER_LIBRARY_DIR)/Frameworks"; + GCC_ENABLE_FIX_AND_CONTINUE = NO; + GCC_MODEL_TUNING = G5; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = "$(SYSTEM_LIBRARY_DIR)/Frameworks/Carbon.framework/Headers/Carbon.h"; + INFOPLIST_FILE = "minidump_tests-Info.plist"; + INSTALL_PATH = "$(USER_LIBRARY_DIR)/Bundles"; + MACOSX_DEPLOYMENT_TARGET = 10.5; + OTHER_LDFLAGS = ( + "-framework", + Carbon, + "-framework", + CPlusTest, + ); + PREBINDING = NO; + PRODUCT_NAME = minidump_tests; + SDKROOT = /Developer/SDKs/MacOSX10.5.sdk; + WRAPPER_EXTENSION = cptest; + ZERO_LINK = NO; + }; + name = Release; + }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -463,6 +702,7 @@ isa = XCConfigurationList; buildConfigurations = ( 1DEB923208733DC60010E9CD /* Debug */, + F996CB8D0DB40AE30089CCC8 /* Coverage */, 1DEB923308733DC60010E9CD /* Release */, ); defaultConfigurationIsVisible = 0; @@ -472,6 +712,7 @@ isa = XCConfigurationList; buildConfigurations = ( 1DEB923608733DC60010E9CD /* Debug */, + F996CB8C0DB40AE30089CCC8 /* Coverage */, 1DEB923708733DC60010E9CD /* Release */, ); defaultConfigurationIsVisible = 0; @@ -481,6 +722,7 @@ isa = XCConfigurationList; buildConfigurations = ( 9B7CA8510B12984300CD3A1D /* Debug */, + F996CB8F0DB40AE30089CCC8 /* Coverage */, 9B7CA8520B12984300CD3A1D /* Release */, ); defaultConfigurationIsVisible = 0; @@ -490,11 +732,22 @@ isa = XCConfigurationList; buildConfigurations = ( 9BD82AA70B0026BF0055103E /* Debug */, + F996CB8E0DB40AE30089CCC8 /* Coverage */, 9BD82AA80B0026BF0055103E /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + F9AE19C70DB04AA200C98454 /* Build configuration list for PBXNativeTarget "minidump_tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + F9AE19C40DB04A9500C98454 /* Debug */, + F996CB900DB40AE30089CCC8 /* Coverage */, + F9AE19C50DB04A9500C98454 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; /* End XCConfigurationList section */ }; rootObject = 08FB7793FE84155DC02AAC07 /* Project object */; diff --git a/src/client/mac/handler/minidump_tests-Info.plist b/src/client/mac/handler/minidump_tests-Info.plist new file mode 100644 index 00000000..909bbe22 --- /dev/null +++ b/src/client/mac/handler/minidump_tests-Info.plist @@ -0,0 +1,20 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${EXECUTABLE_NAME} + CFBundleIdentifier + com.google.breakpad.minidump_tests + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + BNDL + CFBundleSignature + ???? + CFBundleVersion + 1.0 + + diff --git a/src/client/minidump_file_writer_unittest.cc b/src/client/minidump_file_writer_unittest.cc index 58750667..8eadff46 100644 --- a/src/client/minidump_file_writer_unittest.cc +++ b/src/client/minidump_file_writer_unittest.cc @@ -145,6 +145,18 @@ static bool CompareFile(const char *path) { ASSERT_NE(fd, -1); ASSERT_TRUE(buffer); ASSERT_EQ(read(fd, buffer, expected_byte_count), expected_byte_count); + + char *b1, *b2; + b1 = (char*)buffer; + b2 = (char*)expected; + while (*b1 == *b2) { + b1++; + b2++; + } + + printf("%d\n",b1 - (char*)buffer); + + ASSERT_EQ(memcmp(buffer, expected, expected_byte_count), 0); return true; } -- cgit v1.2.1