~ximion/listaller/master

« back to all changes in this revision

Viewing changes to contrib/apbuild/relaytool

  • Committer: Matthias Klumpp
  • Date: 2011-07-12 11:51:32 UTC
  • mfrom: (0.4.6)
  • Revision ID: git-v1:40deffc428db6704895e2a37de271e46234ef169
Merge branch 'master' of /home/matthias/Development/Listaller/liextrajunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/bin/bash
 
2
 
 
3
# relaytool 1.2
 
4
# Copyright 2004-2005 Mike Hearn <mike@plan99.net>
 
5
# Copyright 2005 Vincent Béron <vberon@mecano.gme.usherb.ca>
 
6
# Copyright 2006 Psyche <psyche@ruidoabsurdo.com>
 
7
# Copyright 2007 Taj Morton <tajmorton@gmail.com>
 
8
#
 
9
#############################################################################
 
10
#
 
11
# Permission is hereby granted, free of charge, to any person obtaining a copy
 
12
# of this software and associated documentation files (the "Software"), to deal
 
13
# in the Software without restriction, including without limitation the rights
 
14
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
15
# copies of the Software, and to permit persons to whom the Software is
 
16
# furnished to do so, subject to the following conditions:
 
17
#
 
18
# The above copyright notice and this permission notice shall be included in
 
19
# all copies or substantial portions of the Software.
 
20
#
 
21
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
22
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
23
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
24
# COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 
25
# IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
26
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
27
#
 
28
#############################################################################
 
29
#
 
30
# TODO:
 
31
#   - Figure out how to grab the GOT addr on PowerPC
 
32
#   - Port to more archs
 
33
#   - Figure out a way to check if we're on an ELF platform or not,
 
34
#     maybe check for _GLOBAL_OFFSET_TABLE_ ?
 
35
 
 
36
using_partial_map=false
 
37
using_minimal_list=false
 
38
using_multilink=false
 
39
outdir="."
 
40
 
 
41
if [[ "$1" == "--version" ]]; then
 
42
    echo "Relaytool 1.11"
 
43
    echo "Copyright 2004 Mike Hearn"
 
44
    echo "Copyright 2005 Vincent Béron"
 
45
    echo
 
46
    echo "See $0 for license details."
 
47
    exit 1
 
48
fi
 
49
 
 
50
if [[ "$@" == "" ]] || [[ "$1" == "--help" ]] || [[ "$1" == "-h" ]]; then
 
51
    echo "Relaytool will generate a file that can be used instead of linking"
 
52
    echo "directly against a library, which will dlopen the DSO at init time"
 
53
    echo
 
54
    echo "Usage: relaytool [OPTION]... [LINKER COMMAND]..."
 
55
    echo
 
56
    echo "Options:"
 
57
    echo "  --relay LIB               If a matching -lLIB is found, generate a file"
 
58
    echo "                            that can be used instead of linking directly to"
 
59
    echo "                            LIB. The name of the file is echoed on stdout."
 
60
    echo "                            Multiple --relay can be used together, a file will"
 
61
    echo "                            be generated for each matching ones."
 
62
    echo "  --replace-all-libs        Generate a file for every -lLIB parameter."
 
63
    echo "  --minimal-list OBJ_LIST   Will look in OBJ_LIST for undefined symbols, and"
 
64
    echo "                            generate a file creating only the needed symbols"
 
65
    echo "                            for each LIB."
 
66
    echo "  --partial-map MAP_FILE    Generate a file creating only the symbols contained"
 
67
    echo "                            in MAP_FILE. Will apply to all further -lLIB"
 
68
    echo "                            parameters, so in general is not suitable to"
 
69
    echo "                            multiple libs in the same invocation of relaytool."
 
70
    echo "  --no-replace              Echo -lLIB on stdout even if a --relay LIB is"
 
71
    echo "                            found, so it'll be linked in normally."
 
72
    echo "  --multilink [SONAMES...]  If a library has different SONAMES on different"
 
73
    echo "                            Linux distributions you can specify the various"
 
74
    echo "                            SONAMES that it's known by here. Relaytool will"
 
75
    echo "                            attempt to load them (in the order provided) until"
 
76
    echo "                            one if found. This cannot be used with multiple"
 
77
    echo "                            --relay options. The first SONAME in the list will"
 
78
    echo "                            be used as the name in the _is_present variable and"
 
79
    echo "                            _symbol_is_present function."
 
80
    echo "  --out-dir DIRECTORY       Write stub file to DIRECTORY instead of CWD."
 
81
    echo "Linker commands:"
 
82
    echo "  -LPATH                    Add PATH to the list of paths to search for LIBs."
 
83
    echo "  -lLIB                     If a matching --relay LIB is found (or if"
 
84
    echo "                            --replace-all-libs is specified), generate a file"
 
85
    echo "                            that can be used instead of linking directly to"
 
86
    echo "                            LIB. If there's no --relay LIB, echo -lLIB to"
 
87
    echo "                            stdout."
 
88
    echo " All other linker commands are passed as is to stdout."
 
89
    echo "Other commands:"
 
90
    echo "  --help|-h                 Print this help."
 
91
    echo "  --version                 Print version information."
 
92
    exit 1
 
93
fi
 
94
 
 
95
function error() {
 
96
    echo $@ >/dev/stderr
 
97
    exit 1
 
98
}
 
99
 
 
100
function readfinallink() {
 
101
    link_name="$1"
 
102
    while [ -L "$link_name" ]; do
 
103
        new_name=$( readlink "$link_name" )
 
104
        if [ "${new_name:0:1}" == "/" ]; then
 
105
            link_name="$new_name"
 
106
        else
 
107
            link_name="`dirname "$link_name"`/$new_name"
 
108
        fi
 
109
    done
 
110
    if [ -f "$link_name" ]; then
 
111
        echo -n "$link_name"
 
112
        exit 0
 
113
    else
 
114
        exit 1
 
115
    fi
 
116
}
 
117
 
 
118
function relay() {
 
119
    lib="$1"
 
120
    if $using_multilink; then
 
121
        libname=$( echo $( basename ${multilinklist[0]} ) | sed 's/\.so.*//' | tr '-' '_' | tr '.' '_' )
 
122
    else
 
123
        libname=$( echo $( basename "$lib" ) | sed 's/\.so.*//' | tr '-' '_' | tr '.' '_' )
 
124
    fi
 
125
    soname=$( objdump -x "$lib" |grep SONAME | awk '{print $2}' )
 
126
    outfile="$outdir/`basename "$soname"`.stub.c"
 
127
 
 
128
    echo -n "$outfile"
 
129
 
 
130
    if $using_partial_map; then
 
131
        functions=$( grep "^F " "$partial_map" | cut -d' ' -f2 )
 
132
        variables=$( grep "^V " "$partial_map" | cut -d' ' -f2 )
 
133
    else
 
134
        functions=$( nm --extern-only -D "$lib" | awk '{ if (($2 == "T") || ($2 == "W")) print $3; }' | LC_ALL=C grep -v '\(\<_init\>\|\<_fini\>\)' | LC_ALL=C sort -u )
 
135
        variables=$( nm --extern-only -D "$lib" | awk '{ if (($2 == "D") || ($2 == "G") || ($2 == "B") || ($2 == "V")) print $3; }' | LC_ALL=C sort -u )
 
136
    fi
 
137
    if $using_minimal_list; then
 
138
        functions="$functions
 
139
$( nm `echo "$object_list"` | awk '{ if ($1 == "U") print $2; }' | LC_ALL=C sort -u )"
 
140
        functions=$( echo "$functions" | LC_ALL=C sort | LC_ALL=C uniq -d )
 
141
        variables="$variables
 
142
$( nm `echo "$object_list"` | awk '{ if ($1 == "U") print $2; }' | LC_ALL=C sort -u )"
 
143
        variables=$( echo "$variables" | LC_ALL=C sort | LC_ALL=C uniq -d )
 
144
    fi
 
145
 
 
146
    if [ "$functions" == "" ] && [ "$variables" == "" ]; then
 
147
        # Nothing will be used, so do nothing for that lib
 
148
        exit 1
 
149
    fi
 
150
 
 
151
    cat <<EOF >"$outfile"
 
152
/* automatically generated: `date` by `id -un`@`uname -n`, do not edit
 
153
 *
 
154
 * Built by relaytool, a program for building delay-load jumptables
 
155
 * relaytool is (C) 2004 Mike Hearn <mike@navi.cx>
 
156
 * See http://autopackage.org/ for details.
 
157
 */
 
158
#include <dlfcn.h>
 
159
#include <stdio.h>
 
160
#include <unistd.h>
 
161
#include <stdlib.h>
 
162
#include <string.h>
 
163
#include <assert.h>
 
164
#include <sys/mman.h>
 
165
 
 
166
#ifdef __cplusplus
 
167
    extern "C" {
 
168
#endif
 
169
 
 
170
static void **ptrs;
 
171
static char *functions[] = {
 
172
EOF
 
173
 
 
174
    for s in $functions; do
 
175
        echo "    \"$s\"," >>"$outfile"
 
176
    done
 
177
    echo "    0" >>"$outfile"
 
178
 
 
179
    cat <<EOF >>"$outfile"
 
180
};
 
181
 
 
182
static char *variables[] = {
 
183
EOF
 
184
 
 
185
    for s in $variables; do
 
186
        echo "    \"$s\"," >>"$outfile"
 
187
    done
 
188
    echo "    0" >>"$outfile"
 
189
 
 
190
    cat <<EOF >>"$outfile"
 
191
};
 
192
 
 
193
/* 1 if present, 0 if not */
 
194
int ${libname}_is_present = 0;
 
195
 
 
196
static void *handle = 0;
 
197
 
 
198
/* 1 if present, 0 if not, 0 with warning to stderr if lib not present or symbol not found */
 
199
int ${libname}_symbol_is_present(char *s)
 
200
{
 
201
    int i;
 
202
 
 
203
    if( !${libname}_is_present ) {
 
204
        fprintf(stderr, "%s: relaytool: `basename "$lib"` not present so cannot check for symbol %s.\n", getenv("_"), s);
 
205
        fprintf(stderr, "%s: relaytool: This probably indicates a bug in the application, please report.\n", getenv("_"));
 
206
        return 0;
 
207
    }
 
208
 
 
209
    i = 0;
 
210
    while (functions[i++]) if (!strcmp( functions[i - 1], s )) return ptrs[i - 1] > 0 ? 1 : 0;
 
211
    i = 0;
 
212
    while (variables[i++]) if (!strcmp( variables[i - 1], s )) return dlsym( handle, s ) > 0 ? 1 : 0;
 
213
 
 
214
    fprintf( stderr, "%s: relaytool: %s is an unknown symbol in `basename "$lib"`.\n", getenv("_"), s );
 
215
    fprintf( stderr, "%s: relaytool: If you are the developer of this program, please correct the symbol name or rerun relaytool.\n", getenv("_") );
 
216
    return 0;
 
217
}
 
218
 
 
219
__attribute__((noreturn)) void _relaytool_stubcall_${libname}(int offset)
 
220
{
 
221
    fprintf( stderr, "%s: relaytool: stub call to `basename "${lib}"`:%s, aborting.\n", getenv("_"),
 
222
             functions[offset / sizeof(void*)] );
 
223
    exit( 1 );
 
224
}
 
225
 
 
226
#if defined( __i386__ )
 
227
    #define FIXUP_GOT_RELOC(sym, addr) \\
 
228
        asm("\tmovl %0, %%eax\n" \\
 
229
            "\tmovl %%eax, " sym "@GOT(%%ebx)\n" : : "r" (addr));
 
230
#elif defined( __powerpc__ )
 
231
 
 
232
    /* The PowerPC ELF ABI is a twisted nightmare. Until I figure it out,
 
233
       for now we don't support GOT fixup on this architecture */
 
234
        
 
235
    #error Variables are not currently supported on PowerPC
 
236
        
 
237
#elif defined( __x86_64__ )
 
238
    #define FIXUP_GOT_RELOC(sym, addr) \\
 
239
        asm("\tmovq %0, %%rax\n" \\
 
240
            "\tmovq %%rax, " sym "@GOT(%%rbx)\n" : : "r" (addr));
 
241
#else        
 
242
    #error Please define FIXUP_GOT_RELOC for your architecture
 
243
#endif
 
244
 
 
245
void __attribute__((constructor)) _relaytool_init_${libname}()
 
246
{
 
247
    int i = 0;
 
248
 
 
249
    ptrs = malloc( sizeof(functions) );
 
250
    memset( ptrs, 0, sizeof(functions) );
 
251
EOF
 
252
    if $using_multilink; then
 
253
      echo -n "char *multilink_libs[${#multilinklist[@]}] = {" | cat >> "$outfile"
 
254
      for l in ${multilinklist[@]}; do
 
255
        echo -n "\"$l\"" | cat >> "$outfile";
 
256
        if [[ "$l" != "${multilinklist[${#multilinklist[@]}-1]}" ]]; then
 
257
            echo -n ", " | cat >> "$outfile";
 
258
        else
 
259
            echo "};" | cat >> "$outfile"
 
260
        fi
 
261
      done
 
262
      echo 'int multilink_count=0;' | cat >> "$outfile"
 
263
      
 
264
      echo 'while (!handle) {
 
265
          handle = dlopen(multilink_libs[multilink_count++], RTLD_LAZY );' | cat >> "$outfile"
 
266
      echo "if (multilink_count==${#multilinklist[@]}) break;}"| cat >> "$outfile"
 
267
    else
 
268
      echo "handle = dlopen( \"$soname\", RTLD_LAZY );" | cat >> "$outfile"
 
269
    fi
 
270
cat <<EOF >>"$outfile"
 
271
    if (!handle) return;
 
272
    
 
273
    ${libname}_is_present = 1;
 
274
 
 
275
    /* build function jumptable */
 
276
    while (functions[i++]) ptrs[i - 1] = dlsym( handle, functions[i - 1] );
 
277
    
 
278
EOF
 
279
 
 
280
    if [ "$variables" != "" ]; then echo "    /* now fixup the global offset table for variable imports */" >>"$outfile"; fi
 
281
    for s in $variables; do
 
282
        echo "    FIXUP_GOT_RELOC( \"$s\", dlsym(handle, \"$s\") );" >>"$outfile"
 
283
    done
 
284
 
 
285
    cat <<EOF >>"$outfile"
 
286
}
 
287
 
 
288
#if defined( __i386__ )
 
289
 
 
290
#define JUMP_SLOT(name, index)  \\
 
291
    asm(".section .text." name ", \"ax\", @progbits\n" \\
 
292
        ".globl  " name "\n" \\
 
293
        ".hidden " name "\n" \\
 
294
        "        .type " name ", @function\n"  \\
 
295
        name ":\n" \\
 
296
        "        movl ptrs, %eax\n" \\
 
297
        "        movl " #index "(%eax), %eax\n" \\
 
298
        "        test %eax, %eax\n" \\
 
299
        "        jnz  JS" #index "\n" \\
 
300
        "        push \$" #index "\n" \\
 
301
        "        call _relaytool_stubcall_${libname}\n" \\
 
302
        "JS" #index ":    jmp *%eax\n");
 
303
 
 
304
 
 
305
#elif defined( __x86_64__ )
 
306
 
 
307
#define JUMP_SLOT(name, index)  \\
 
308
    asm(".section .text." name ", \"ax\", @progbits\n" \\
 
309
        ".globl  " name "\n" \\
 
310
        ".hidden " name "\n" \\
 
311
        "        .type " name ", @function\n"  \\
 
312
        name ":\n" \\
 
313
        "        movq ptrs, %r11\n" \\
 
314
        "        movq " #index "(%r11), %r11\n" \\
 
315
        "        test %r11, %r11\n" \\
 
316
        "        jnz  JS" #index "\n" \\
 
317
        "        push $" #index "\n" \\
 
318
        "        call _relaytool_stubcall_${libname}\n" \\
 
319
        "JS" #index ":    jmp *%r11\n");
 
320
#elif defined( __powerpc__ )
 
321
 
 
322
#define JUMP_SLOT(name, index) \                                \
 
323
    asm(".section .text." name ", \"ax\", @progbits\n" \\
 
324
        ".globl  " name "\n" \\
 
325
        ".hidden " name "\n" \\
 
326
        "        .type " name ", @function\n" \\
 
327
        name ":\n" \\
 
328
        "        lis r11, ptrs@ha\n" \\
 
329
        "        lwz r11, " #index "(r11)\n" \\
 
330
        "        cmpi cr0,r11,0\n" \\
 
331
        "        beq- 1f\n" \\
 
332
        "        mtctr r11\n" \\
 
333
        "        bctr\n" \\
 
334
        "1:      li r3, " #index "\n" \\
 
335
        "        b _relaytool_stubcall_${libname}\n" \\
 
336
        );
 
337
        
 
338
#else        
 
339
    #error Please define JUMP_SLOT for your architecture
 
340
#endif
 
341
 
 
342
/* define placeholders for the variable imports: their type doesn't matter,
 
343
   however we must restrict ELF symbol scope to prevent the definition in the imported
 
344
   shared library being bound to this dummy symbol (not all libs are compiled -Bsymbolic)
 
345
 */
 
346
EOF
 
347
 
 
348
    for s in $variables; do
 
349
        echo "int $s __attribute__(( visibility(\"hidden\") )) = -1;" >>"$outfile"
 
350
    done
 
351
 
 
352
    cat <<EOF >>"$outfile"
 
353
 
 
354
/* define each jump slot in its own section. this increases generated code
 
355
   size, but it means unused slots can be deleted by the linker when
 
356
   --gc-sections is used.
 
357
 */
 
358
EOF
 
359
 
 
360
# now generate the stubs
 
361
    c=0
 
362
    for s in $functions; do
 
363
        echo "JUMP_SLOT(\"$s\", $[c * $arch_ptr_size]);" >>"$outfile"
 
364
        (( c++ ))
 
365
    done
 
366
 
 
367
    echo >>"$outfile"
 
368
 
 
369
    cat <<EOF >>"$outfile"
 
370
 
 
371
#ifdef __cplusplus
 
372
    }
 
373
#endif
 
374
EOF
 
375
    
 
376
}
 
377
 
 
378
function fakerelay() {
 
379
    lib="$1"
 
380
    libname=$( echo $( basename "$lib" ) | sed 's/\.so.*//' | tr '-' '_' | tr '.' '_' )
 
381
    soname=$( objdump -x "$lib" |grep SONAME | awk '{print $2}' )
 
382
    outfile="$outdir/`basename "$soname"`.stub.c"
 
383
 
 
384
    echo -n "$outfile"
 
385
 
 
386
    cat <<EOF >"$outfile"
 
387
/* automatically generated: `date` by `id -un`@`uname -n`, do not edit
 
388
 *
 
389
 * Built by relaytool, a program for building delay-load jumptables
 
390
 * relaytool is (C) 2004 Mike Hearn <mike@navi.cx>
 
391
 * See http://autopackage.org/ for details.
 
392
 */
 
393
 
 
394
#ifdef __cplusplus
 
395
    extern "C" {
 
396
#endif
 
397
 
 
398
/* 1 if present, 0 if not */
 
399
int ${libname}_is_present = 1;
 
400
 
 
401
/* 1 if present, 0 if not, 0 with warning to stderr if lib not present or symbol not found */
 
402
int ${libname}_symbol_is_present(char * s)
 
403
{
 
404
    return 1;
 
405
}
 
406
 
 
407
#ifdef __cplusplus
 
408
    }
 
409
#endif
 
410
EOF
 
411
    
 
412
}
 
413
 
 
414
no_replace=false
 
415
replace_all=false
 
416
arch_ok=false
 
417
arch_ptr_size=0
 
418
case `uname -m` in
 
419
    i386 | i486 | i586 | i686 )
 
420
        arch_ok=true
 
421
        arch_ptr_size=4
 
422
        ;;
 
423
    x86_64)
 
424
        arch_ok=true
 
425
        arch_ptr_size=8
 
426
        ;;                                   
 
427
esac
 
428
 
 
429
searchpath=( "/usr/lib" "/usr/local/lib" "/lib" `pwd` )
 
430
multilinklist=( )
 
431
relaylist=( )
 
432
 
 
433
# process arguments
 
434
i=1
 
435
while (( i <= $# )); do
 
436
    a="${!i}"
 
437
    
 
438
    if [ "${a:0:2}" == "-L" ]; then
 
439
        searchpath[${#searchpath}]="${a:2}"
 
440
        echo -n "$a " # copy to stdout
 
441
 
 
442
    elif [ "$a" == "--replace-all-libs" ]; then
 
443
        replace_all=true
 
444
 
 
445
    elif [ "$a" == "--partial-map" ]; then
 
446
        using_partial_map=true
 
447
        (( i++ ))
 
448
        partial_map="${!i}"
 
449
 
 
450
    elif [ "$a" == "--minimal-list" ]; then
 
451
        using_minimal_list=true
 
452
        (( i++ ))
 
453
        object_list="${!i}"
 
454
 
 
455
    elif [ "$a" == "--no-replace" ]; then
 
456
        no_replace=true
 
457
 
 
458
    elif [ "$a" == "--multilink" ]; then
 
459
        using_multilink=true
 
460
        (( i++ ))
 
461
        while [[ $i -lt $# && ${!i:0:2} != "--" ]]; do
 
462
                multilinklist[${#multilinklist[@]}]="${!i}"
 
463
                (( i++ ))
 
464
        done
 
465
        continue # $i has already been incremented, just continue with the loop
 
466
 
 
467
    elif [ "$a" == "--relay" ]; then
 
468
        (( i++ ))
 
469
        relaylist[${#relaylist[@]}]="${!i}"
 
470
 
 
471
    elif [ "$a" == "--out-dir" ]; then
 
472
        (( i++ ))
 
473
        outdir="${!i}"
 
474
 
 
475
    elif [ "$a" == "-ldl" ]; then
 
476
        # libdl won't ever be supported by relaytool, so just pass it to stdout
 
477
        echo -n "$a "
 
478
 
 
479
    elif [ "${a:0:2}" == "-l" ]; then
 
480
        lib="${a:2}"
 
481
        
 
482
        # is this lib meant to be relayed?
 
483
        if $replace_all; then
 
484
            found=true
 
485
        else
 
486
            found=false
 
487
            for b in ${relaylist[@]}; do
 
488
                if [ "$b" == "$lib" ]; then
 
489
                    found=true
 
490
                fi
 
491
            done
 
492
        fi
 
493
 
 
494
        if $found && $arch_ok; then
 
495
        
 
496
            # yes, so let's find its absolute filename by checking in each search path directory
 
497
            spfound=false
 
498
            for d in ${searchpath[@]}; do
 
499
                if [ -e "$d/lib$lib.so" ]; then
 
500
                
 
501
                    absname=$( readfinallink "$d/lib$lib.so" )
 
502
                    if [ $? != 0 ] || [ ! -f "$absname" ]; then
 
503
                        error broken symlink "$absname"
 
504
                    fi
 
505
                    
 
506
                    stubfile=$( relay "$absname" )
 
507
 
 
508
                    # now we have to compile the stub
 
509
                    if [ $? == 0 ]; then
 
510
                        stubobj=$( echo "$stubfile" | sed 's/\.c$/\.o/' )
 
511
                        # remove -include flags from CFLAGS, if any
 
512
                        CFLAGS=$( echo $CFLAGS | sed 's/-include .*\.h//g' )
 
513
                        if [ -e /dev/tty ]; then
 
514
                            ${CC:-gcc} ${CFLAGS} -fPIC -c -o "$stubobj" "$stubfile" 2>/dev/tty
 
515
                        else
 
516
                            ${CC:-gcc} ${CFLAGS} -fPIC -c -o "$stubobj" "$stubfile"
 
517
                        fi
 
518
                        echo -n "$stubobj "
 
519
                    fi
 
520
 
 
521
                    if $no_replace; then
 
522
                        echo -n "-l$lib "
 
523
                    fi
 
524
                    
 
525
                    spfound=true
 
526
                    break;
 
527
                fi
 
528
            done
 
529
 
 
530
            if ! $spfound; then
 
531
                error could not find "$lib" in search path
 
532
            fi
 
533
        elif $found && ! $arch_ok; then
 
534
            # yes, so let's find its absolute filename by checking in each search path directory
 
535
            spfound=false
 
536
            for d in ${searchpath[@]}; do
 
537
                if [ -e "$d/lib$lib.so" ]; then
 
538
                
 
539
                    absname=$( readfinallink "$d/lib$lib.so" )
 
540
                    if [ $? != 0 ] || [ ! -f "$absname" ]; then
 
541
                        error broken symlink "$absname"
 
542
                    fi
 
543
                    
 
544
                    # Create a stub C source that just contains dummy 
 
545
                    # libwhatever_... support functions
 
546
                    stubfile=$( fakerelay "$absname" )
 
547
 
 
548
                    # now we have to compile the stub
 
549
                    if [ $? == 0 ]; then
 
550
                        stubobj=$( echo "$stubfile" | sed 's/\.c$/\.o/' )
 
551
                        # remove -include flags from CFLAGS, if any
 
552
                        CFLAGS=$( echo $CFLAGS | sed 's/-include .*\.h//g' )
 
553
                        if [ -e /dev/tty ]; then
 
554
                            ${CC:-gcc} ${CFLAGS} -fPIC -c -o "$stubobj" "$stubfile" 2>/dev/tty
 
555
                        else
 
556
                            ${CC:-gcc} ${CFLAGS} -fPIC -c -o "$stubobj" "$stubfile"
 
557
                        fi
 
558
                        echo -n "$stubobj "
 
559
                    fi
 
560
 
 
561
                    if $no_replace; then
 
562
                        echo -n "-l$lib "
 
563
                    fi
 
564
                    
 
565
                    spfound=true
 
566
                    break;
 
567
                fi
 
568
            done
 
569
 
 
570
            if ! $spfound; then
 
571
                error could not find "$lib" in search path
 
572
            fi
 
573
        else
 
574
            echo -n "$a "
 
575
        fi
 
576
        
 
577
    else
 
578
        # just copy whatever we don't recognise
 
579
        echo -n "$a "
 
580
    fi
 
581
    
 
582
    (( i++ ))
 
583
done
 
584
echo