From 3833a7ce5486b9645d70f43757e34268194b6056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20P=C3=B6chtrager?= Date: Sat, 15 Feb 2014 14:53:07 +0100 Subject: [PATCH] cctools: make is_llvm_bitcode() more portable (fixes -flto with multiple -arch flags) ld64: use faster strlcpy()/strlcat() "helper" implementations ld64: fix qsort_r() helper function fix emulated _NSGetExecutablePath() for FreeBSD fix -luuid linkage issue on FreeBSD 10 Conflicts: cctools/configure.ac --- .gitignore | 2 + cctools/as/driver.c | 2 +- cctools/configure.ac | 6 +- cctools/ld64/src/3rd/helper.c | 22 +- cctools/ld64/src/3rd/qsort_r.c | 434 ++++++++++++++++++++++- cctools/ld64/src/3rd/strlcat.c | 62 ++-- cctools/ld64/src/3rd/strlcpy.c | 75 ++-- cctools/ld64/src/ld/parsers/lto_file.cpp | 1 + cctools/libstuff/emulated.c | 14 + cctools/libstuff/lto.c | 92 ++++- 10 files changed, 610 insertions(+), 100 deletions(-) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7f18ac5 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.o +*.lo diff --git a/cctools/as/driver.c b/cctools/as/driver.c index 738c40e..833201e 100644 --- a/cctools/as/driver.c +++ b/cctools/as/driver.c @@ -60,7 +60,7 @@ char **envp) _NSGetExecutablePath(p, &bufsize); } prefix = realpath(p, resolved_name); - if(realpath == NULL) + if(prefix == NULL) system_fatal("realpath(3) for %s failed", p); p = rindex(prefix, '/'); if(p != NULL) diff --git a/cctools/configure.ac b/cctools/configure.ac index d364f4b..24e7155 100644 --- a/cctools/configure.ac +++ b/cctools/configure.ac @@ -10,9 +10,9 @@ AC_ARG_PROGRAM CC=clang CXX=clang++ -CFLAGS="`cat tmp/cflags 2>/dev/null` -O3" -CXXFLAGS="`cat tmp/libcxx-conf 2>/dev/null || echo -stdlib=libc++` `cat tmp/cxxflags 2>/dev/null` -O3" -LDFLAGS="`cat tmp/ldflags 2>/dev/null`" +CFLAGS="$CFLAGS `cat tmp/cflags 2>/dev/null` -O3" +CXXFLAGS="$CXXFLAGS `cat tmp/libcxx-conf 2>/dev/null || echo -stdlib=libc++` `cat tmp/cxxflags 2>/dev/null` -O3" +LDFLAGS="$LDFLAGS `cat tmp/ldflags 2>/dev/null`" export LD_LIBRARY_PATH="`cat tmp/ldpath 2>/dev/null`" export C_INCLUDE_PATH="$C_INCLUDE_PATH:/usr/local/include" diff --git a/cctools/ld64/src/3rd/helper.c b/cctools/ld64/src/3rd/helper.c index 6f10f77..1e51dd2 100644 --- a/cctools/ld64/src/3rd/helper.c +++ b/cctools/ld64/src/3rd/helper.c @@ -13,6 +13,11 @@ #include #include #include + +#ifdef __FreeBSD__ +#include +#endif + #include "helper.h" const char ldVersionString[] = "136\n"; @@ -27,22 +32,29 @@ void __assert_rtn(const char *func, const char *file, int line, const char *msg) #endif /* __FreeBSD__ */ } - int _NSGetExecutablePath(char *path, unsigned int *size) { +#ifdef __FreeBSD__ + int mib[4]; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + size_t cb = *size; + return sysctl(mib, 4, path, &cb, NULL, 0); +#else int bufsize = *size; int ret_size; - char *localpath = (char*)malloc(bufsize); - bzero(localpath,bufsize); - ret_size = readlink("/proc/self/exe", localpath, bufsize); + ret_size = readlink("/proc/self/exe", path, bufsize-1); if (ret_size != -1) { *size = ret_size; - strcpy(path,localpath); + path[ret_size]=0; return 0; } else return -1; +#endif } int _dyld_find_unwind_sections(void* i, struct dyld_unwind_sections* sec) diff --git a/cctools/ld64/src/3rd/qsort_r.c b/cctools/ld64/src/3rd/qsort_r.c index 4a34707..a7afa16 100644 --- a/cctools/ld64/src/3rd/qsort_r.c +++ b/cctools/ld64/src/3rd/qsort_r.c @@ -1,23 +1,429 @@ -#include "qsort_r.h" +/*- + * Copyright (c) 1992, 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. + * 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. + */ + +#define I_AM_QSORT_R +#define qsort_r qsort_r_local + +#include + +#include +#include #include +#include -void *_qsort_thunk = NULL; -int (*_qsort_saved_func)(void *, const void *, const void *) = NULL; - -static int _qsort_comparator(const void *a, const void *b); - -static int _qsort_comparator(const void *a, const void *b) +#ifndef __FreeBSD__ +/* flsl.c */ +int +flsl(long mask) { - return _qsort_saved_func(_qsort_thunk, a, b); + int bit; + + if (mask == 0) + return (0); + for (bit = 1; mask != 1; bit++) + mask = (unsigned long)mask >> 1; + return (bit); +} + +/* fsl.c */ +int +fls(int mask) +{ + int bit; + if (mask == 0) + return (0); + for (bit = 1; mask != 1; bit++) + mask = (unsigned int)mask >> 1; + return (bit); +} +#endif + +/* + * Swap two areas of size number of bytes. Although qsort(3) permits random + * blocks of memory to be sorted, sorting pointers is almost certainly the + * common case (and, were it not, could easily be made so). Regardless, it + * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer + * arithmetic gets lost in the time required for comparison function calls. + */ +#define SWAP(a, b, count, size, tmp) { \ + count = size; \ + do { \ + tmp = *a; \ + *a++ = *b; \ + *b++ = tmp; \ + } while (--count); \ +} + +/* Copy one block of size size to another. */ +#define COPY(a, b, count, size, tmp1, tmp2) { \ + count = size; \ + tmp1 = a; \ + tmp2 = b; \ + do { \ + *tmp1++ = *tmp2++; \ + } while (--count); \ +} + +/* + * Build the list into a heap, where a heap is defined such that for + * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N. + * + * There two cases. If j == nmemb, select largest of Ki and Kj. If + * j < nmemb, select largest of Ki, Kj and Kj+1. + */ +#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \ + for (par_i = initval; (child_i = par_i * 2) <= nmemb; \ + par_i = child_i) { \ + child = base + child_i * size; \ + if (child_i < nmemb && compar(thunk, child, child + size) < 0) { \ + child += size; \ + ++child_i; \ + } \ + par = base + par_i * size; \ + if (compar(thunk, child, par) <= 0) \ + break; \ + SWAP(par, child, count, size, tmp); \ + } \ +} + +/* + * Select the top of the heap and 'heapify'. Since by far the most expensive + * action is the call to the compar function, a considerable optimization + * in the average case can be achieved due to the fact that k, the displaced + * elememt, is ususally quite small, so it would be preferable to first + * heapify, always maintaining the invariant that the larger child is copied + * over its parent's record. + * + * Then, starting from the *bottom* of the heap, finding k's correct place, + * again maintianing the invariant. As a result of the invariant no element + * is 'lost' when k is assigned its correct place in the heap. + * + * The time savings from this optimization are on the order of 15-20% for the + * average case. See Knuth, Vol. 3, page 158, problem 18. + * + * XXX Don't break the #define SELECT line, below. Reiser cpp gets upset. + */ +#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \ + for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \ + child = base + child_i * size; \ + if (child_i < nmemb && compar(thunk, child, child + size) < 0) { \ + child += size; \ + ++child_i; \ + } \ + par = base + par_i * size; \ + COPY(par, child, count, size, tmp1, tmp2); \ + } \ + for (;;) { \ + child_i = par_i; \ + par_i = child_i / 2; \ + child = base + child_i * size; \ + par = base + par_i * size; \ + if (child_i == 1 || compar(thunk, k, par) < 0) { \ + COPY(child, k, count, size, tmp1, tmp2); \ + break; \ + } \ + COPY(child, par, count, size, tmp1, tmp2); \ + } \ +} + +/* + * Heapsort -- Knuth, Vol. 3, page 145. Runs in O (N lg N), both average + * and worst. While heapsort is faster than the worst case of quicksort, + * the BSD quicksort does median selection so that the chance of finding + * a data set that will trigger the worst case is nonexistent. Heapsort's + * only advantage over quicksort is that it requires little additional memory. + */ +__private_extern__ int +__heapsort_r(vbase, nmemb, size, thunk, compar) + void *vbase; + size_t nmemb, size; + void *thunk; + int (*compar)(void *, const void *, const void *); +{ + size_t cnt, i, j, l; + char tmp, *tmp1, *tmp2; + char *base, *k, *p, *t; + + if (nmemb <= 1) + return (0); + + if (!size) { + errno = EINVAL; + return (-1); + } + + if ((k = malloc(size)) == NULL) + return (-1); + + /* + * Items are numbered from 1 to nmemb, so offset from size bytes + * below the starting address. + */ + base = (char *)vbase - size; + + for (l = nmemb / 2 + 1; --l;) + CREATE(l, nmemb, i, j, t, p, size, cnt, tmp); + + /* + * For each element of the heap, save the largest element into its + * final slot, save the displaced element (k), then recreate the + * heap. + */ + while (nmemb > 1) { + COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2); + COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2); + --nmemb; + SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2); + } + free(k); + return (0); +} + +/* qsort.c */ + +#include + +#ifdef I_AM_QSORT_R +typedef int cmp_t(void *, const void *, const void *); +#else +typedef int cmp_t(const void *, const void *); +#endif +#ifdef I_AM_QSORT_B +static inline char *med3(char *, char *, char *, cmp_t ^, void *) __attribute__((always_inline)); +#else +static inline char *med3(char *, char *, char *, cmp_t *, void *) __attribute__((always_inline)); +#endif +static inline void swapfunc(char *, char *, int, int) __attribute__((always_inline)); + +#define min(a, b) (a) < (b) ? a : b + +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + TYPE *pi = (TYPE *) (parmi); \ + TYPE *pj = (TYPE *) (parmj); \ + do { \ + TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +static inline void +swapfunc(a, b, n, swaptype) + char *a, *b; + int n, swaptype; +{ + if(swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +#ifdef I_AM_QSORT_R +#define CMP(t, x, y) (cmp((t), (x), (y))) +#else +#define CMP(t, x, y) (cmp((x), (y))) +#endif + +static inline char * +med3(char *a, char *b, char *c, +#ifdef I_AM_QSORT_B +cmp_t ^cmp, +#else +cmp_t *cmp, +#endif +void *thunk +#ifndef I_AM_QSORT_R +__unused +#endif +) +{ + return CMP(thunk, a, b) < 0 ? + (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) + :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); +} + +#ifdef __LP64__ +#define DEPTH(x) (2 * (flsl((long)(x)) - 1)) +#else /* !__LP64__ */ +#define DEPTH(x) (2 * (fls((int)(x)) - 1)) +#endif /* __LP64__ */ + +#ifdef I_AM_QSORT_R +int __heapsort_r(void *, size_t, size_t, void *, int (*)(void *, const void *, const void *)); +#endif + +static void +_qsort(void *a, size_t n, size_t es, +#ifdef I_AM_QSORT_R +void *thunk, +#else +#define thunk NULL +#endif +#ifdef I_AM_QSORT_B +cmp_t ^cmp, +#else +cmp_t *cmp, +#endif +int depth_limit) +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + size_t d, r; + int cmp_result; + int swaptype, swap_cnt; + +loop: + if (depth_limit-- <= 0) { +#ifdef I_AM_QSORT_B + heapsort_b(a, n, es, cmp); +#elif defined(I_AM_QSORT_R) + __heapsort_r(a, n, es, thunk, cmp); +#else + heapsort(a, n, es, cmp); +#endif + return; + } + SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) { + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + pm = (char *)a + (n / 2) * es; + if (n > 7) { + pl = a; + pn = (char *)a + (n - 1) * es; + if (n > 40) { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); + pm = med3(pm - d, pm, pm + d, cmp, thunk); + pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); + } + pm = med3(pl, pm, pn, cmp, thunk); + } + swap(a, pm); + pa = pb = (char *)a + es; + + pc = pd = (char *)a + (n - 1) * es; + for (;;) { + while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { + if (cmp_result == 0) { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { + if (cmp_result == 0) { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + break; + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + + pn = (char *)a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + + if (swap_cnt == 0) { /* Switch to insertion sort */ + r = 1 + n / 4; /* n >= 7, so r >= 2 */ + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) { + swap(pl, pl - es); + if (++swap_cnt > r) goto nevermind; + } + return; + } + +nevermind: + if ((r = pb - pa) > es) +#ifdef I_AM_QSORT_R + _qsort(a, r / es, es, thunk, cmp, depth_limit); +#else + _qsort(a, r / es, es, cmp, depth_limit); +#endif + if ((r = pd - pc) > es) { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +/* qsort(pn - r, r / es, es, cmp);*/ } void -qsort_r_local(void *base, size_t nmemb, size_t size, void *thunk, - int (*compar)(void *, const void *, const void *)) +#ifdef I_AM_QSORT_R +qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +#elif defined(I_AM_QSORT_B) +qsort_b(void *a, size_t n, size_t es, cmp_t ^cmp) +#else +qsort(void *a, size_t n, size_t es, cmp_t *cmp) +#endif { - _qsort_thunk = thunk; - _qsort_saved_func = compar; - - qsort(base, nmemb, size, _qsort_comparator); + _qsort(a, n, es, +#ifdef I_AM_QSORT_R + thunk, +#endif + cmp, DEPTH(n)); } + diff --git a/cctools/ld64/src/3rd/strlcat.c b/cctools/ld64/src/3rd/strlcat.c index 1cd8d66..500d038 100644 --- a/cctools/ld64/src/3rd/strlcat.c +++ b/cctools/ld64/src/3rd/strlcat.c @@ -1,30 +1,38 @@ -#include +/* + * Copyright (c) 2011 Apple, 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@ + */ + #include -size_t strlcat(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - size_t dlen; - - /* Find the end of dst and adjust bytes left but don't go past end */ - while (n-- != 0 && *d != '\0') - d++; - dlen = d - dst; - n = siz - dlen; - - if (n == 0) - return(dlen + strlen(s)); - while (*s != '\0') { - if (n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = '\0'; - - return(dlen + (s - src)); /* count does not include NUL */ +size_t +strlcat(char * restrict dst, const char * restrict src, size_t maxlen) { + const size_t srclen = strlen(src); + const size_t dstlen = strnlen(dst, maxlen); + if (dstlen == maxlen) return maxlen+srclen; + if (srclen < maxlen-dstlen) { + memcpy(dst+dstlen, src, srclen+1); + } else { + memcpy(dst+dstlen, src, maxlen-dstlen-1); + dst[maxlen-1] = '\0'; + } + return dstlen + srclen; } - diff --git a/cctools/ld64/src/3rd/strlcpy.c b/cctools/ld64/src/3rd/strlcpy.c index d2eab8a..c69f107 100644 --- a/cctools/ld64/src/3rd/strlcpy.c +++ b/cctools/ld64/src/3rd/strlcpy.c @@ -1,56 +1,37 @@ -/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */ - /* - * Copyright (c) 1998 Todd C. Miller + * Copyright (c) 2011 Apple, Inc. All rights reserved. * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * @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@ */ -#include #include -#ifndef HAVE_STRLCPY - -/* - * Copy src to string dst of size siz. At most siz-1 characters - * will be copied. Always NUL terminates (unless siz == 0). - * Returns strlen(src); if retval >= siz, truncation occurred. - */ size_t -strlcpy(char *dst, const char *src, size_t siz) -{ - char *d = dst; - const char *s = src; - size_t n = siz; - - /* Copy as many bytes as will fit */ - if (n != 0) { - while (--n != 0) { - if ((*d++ = *s++) == '\0') - break; - } - } - - /* Not enough room in dst, add NUL and traverse rest of src */ - if (n == 0) { - if (siz != 0) - *d = '\0'; /* NUL-terminate dst */ - while (*s++) - ; - } - - return(s - src - 1); /* count does not include NUL */ +strlcpy(char * restrict dst, const char * restrict src, size_t maxlen) { + const size_t srclen = strlen(src); + if (srclen < maxlen) { + memcpy(dst, src, srclen+1); + } else if (maxlen != 0) { + memcpy(dst, src, maxlen-1); + dst[maxlen-1] = '\0'; + } + return srclen; } -#endif - diff --git a/cctools/ld64/src/ld/parsers/lto_file.cpp b/cctools/ld64/src/ld/parsers/lto_file.cpp index 7712bb1..c91eb96 100644 --- a/cctools/ld64/src/ld/parsers/lto_file.cpp +++ b/cctools/ld64/src/ld/parsers/lto_file.cpp @@ -28,6 +28,7 @@ #define __LTO_READER_H__ #include +#include #include #include #include diff --git a/cctools/libstuff/emulated.c b/cctools/libstuff/emulated.c index 147ea6f..99f8022 100644 --- a/cctools/libstuff/emulated.c +++ b/cctools/libstuff/emulated.c @@ -14,8 +14,21 @@ #include #include +#ifdef __FreeBSD__ +#include +#endif + int _NSGetExecutablePath(char *path, unsigned int *size) { +#ifdef __FreeBSD__ + int mib[4]; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PATHNAME; + mib[3] = -1; + size_t cb = *size; + return sysctl(mib, 4, path, &cb, NULL, 0); +#else int bufsize = *size; int ret_size; ret_size = readlink("/proc/self/exe", path, bufsize-1); @@ -27,6 +40,7 @@ int _NSGetExecutablePath(char *path, unsigned int *size) } else return -1; +#endif } kern_return_t mach_timebase_info( mach_timebase_info_t info) { diff --git a/cctools/libstuff/lto.c b/cctools/libstuff/lto.c index 8bcf815..78fae9c 100644 --- a/cctools/libstuff/lto.c +++ b/cctools/libstuff/lto.c @@ -26,6 +26,79 @@ static uint32_t (*lto_get_num_symbols)(void *mod) = NULL; static lto_symbol_attributes (*lto_get_sym_attr)(void *mod, uint32_t n) = NULL; static char * (*lto_get_sym_name)(void *mod, uint32_t n) = NULL; +#ifndef __APPLE__ +static char *liblto_dirs[] = { + "/usr/lib/llvm/lib", + "/usr/lib/llvm-3.5/lib", + "/usr/lib/llvm-3.4/lib", + "/usr/lib/llvm-3.3/lib", + "/usr/lib/llvm-3.2/lib", + "/usr/lib/llvm-3.1/lib", + NULL +}; + +static void *load_liblto() +{ + /* + * Try to load it normally first, + * maybe libLTO.so is even in a known place. + */ + + void *h = dlopen("libLTO.so", RTLD_NOW); + char *p, *path; + int i; + + if(h) + return h; + + /* + * Now try the hardcoded paths from above. + */ + + for(i = 0; liblto_dirs[i] != NULL; i++){ + char liblto[MAXPATHLEN]; + snprintf(liblto, sizeof(liblto), "%s/libLTO.so", liblto_dirs); + + if((h = dlopen(liblto, RTLD_NOW))) + return h; + } + + /* + * Locate the path of the clang binary and try to load + * /../lib/libLTO.so. + */ + + path = getenv("PATH"); + + if(!path) return NULL; + path = strdup(path); + if(!path) return NULL; + + p = strtok(path, ":"); + + while(p != NULL){ + char clangbin[MAXPATHLEN]; + struct stat st; + snprintf(clangbin, sizeof(clangbin), "%s/clang", p); + + if(stat(clangbin, &st) == 0 && access(clangbin, F_OK|X_OK) == 0){ + char liblto[MAXPATHLEN]; + snprintf(liblto, sizeof(liblto), "%s/../lib/libLTO.so", p); + + if((h = dlopen(liblto, RTLD_NOW))){ + free(path); + return h; + } + } + + p = strtok(NULL, ":"); + } + + free(path); + return NULL; +} +#endif /* ! __APPLE__ */ + /* * is_llvm_bitcode() is passed an ofile struct pointer and a pointer and size * of some part of the ofile. If it is an llvm bit code it returns 1 and @@ -106,19 +179,32 @@ void **pmod) /* maybe NULL */ _NSGetExecutablePath(p, &bufsize); } prefix = realpath(p, resolved_name); - p = rindex(prefix, '/'); + p = (prefix ? rindex(prefix, '/') : NULL); if(p != NULL) p[1] = '\0'; - lto_path = makestr(prefix, "../lib/libLTO.so", NULL); +#ifdef __APPLE__ + lto_path = makestr(prefix, "../lib/libLTO.dylib", NULL); lto_handle = dlopen(lto_path, RTLD_NOW); if(lto_handle == NULL){ free(lto_path); lto_path = NULL; - lto_handle = dlopen("/usr/lib/llvm/libLTO.so", RTLD_NOW); + lto_handle = dlopen("/Applications/Xcode.app/Contents/" + "Developer/Toolchains/XcodeDefault." + "xctoolchain/usr/lib/libLTO.dylib", + RTLD_NOW); } if(lto_handle == NULL) return(0); +#else + lto_path = NULL; + lto_handle = load_liblto(); + if(lto_handle == NULL) + { + fprintf(stderr, "cannot find or load libLTO.so\n"); + return(0); + } +#endif /* __APPLE__ */ lto_is_object = dlsym(lto_handle, "lto_module_is_object_file_in_memory");