OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [utils/] [ldd.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/* vi: set sw=4 ts=4: */
2
/*
3
 * A small little ldd implementation for uClibc
4
 *
5
 * Copyright (C) 2000 by Lineo, inc and Erik Andersen
6
 * Copyright (C) 2000-2002 Erik Andersen <andersee@debian.org>
7
 *
8
 * Several functions in this file (specifically, elf_find_section_type(),
9
 * elf_find_phdr_type(), and elf_find_dynamic(), were stolen from elflib.c from
10
 * elfvector (http://www.BitWagon.com/elfvector.html) by John F. Reiser
11
 * <jreiser@BitWagon.com>, which is copyright 2000 BitWagon Software LLC
12
 * (GPL2).
13
 *
14
 * This program is free software; you can redistribute it and/or modify
15
 * it under the terms of the GNU General Public License as published by
16
 * the Free Software Foundation; either version 2 of the License, or
17
 * (at your option) any later version.
18
 *
19
 * This program is distributed in the hope that it will be useful,
20
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22
 * General Public License for more details.
23
 *
24
 * You should have received a copy of the GNU General Public License
25
 * along with this program; if not, write to the Free Software
26
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27
 *
28
 */
29
 
30
 
31
#define _GNU_SOURCE
32
#include <stdlib.h>
33
#include <stdio.h>
34
#include <fcntl.h>
35
#include <string.h>
36
#include <unistd.h>
37
#include <sys/mman.h>
38
#include <sys/stat.h>
39
#include <sys/types.h>
40
#include <sys/types.h>
41
#include <sys/wait.h>
42
 
43
#include "bswap.h"
44
#if defined (sun)
45
#include "link.h"
46
#else
47
#include "elf.h"
48
#endif
49
 
50
#ifdef DMALLOC
51
#include <dmalloc.h>
52
#endif
53
 
54
#if defined(__arm__)
55
#define MATCH_MACHINE(x) (x == EM_ARM)
56
#define ELFCLASSM       ELFCLASS32
57
#endif
58
 
59
#if defined(__s390__)
60
#define MATCH_MACHINE(x) (x == EM_S390)
61
#define ELFCLASSM       ELFCLASS32
62
#endif
63
 
64
#if defined(__i386__)
65
#ifndef EM_486
66
#define MATCH_MACHINE(x) (x == EM_386)
67
#else
68
#define MATCH_MACHINE(x) (x == EM_386 || x == EM_486)
69
#endif
70
#define ELFCLASSM       ELFCLASS32
71
#endif
72
 
73
#if defined(__mc68000__) 
74
#define MATCH_MACHINE(x) (x == EM_68K)
75
#define ELFCLASSM       ELFCLASS32
76
#endif
77
 
78
#if defined(__mips__)
79
#define MATCH_MACHINE(x) (x == EM_MIPS || x == EM_MIPS_RS3_LE)
80
#define ELFCLASSM       ELFCLASS32
81
#endif
82
 
83
#if defined(__powerpc__)
84
#define MATCH_MACHINE(x) (x == EM_PPC)
85
#define ELFCLASSM       ELFCLASS32
86
#endif
87
 
88
#if defined(__sh__)
89
#define MATCH_MACHINE(x) (x == EM_SH)
90
#define ELFCLASSM       ELFCLASS32
91
#endif
92
 
93
#if defined (__v850e__)
94
#define MATCH_MACHINE(x) ((x) == EM_V850 || (x) == EM_CYGNUS_V850)
95
#define ELFCLASSM       ELFCLASS32
96
#endif
97
 
98
#if defined (__sparc__)
99
#define MATCH_MACHINE(x) ((x) == EM_SPARC || (x) == EM_SPARC32PLUS)
100
#define ELFCLASSM    ELFCLASS32
101
#endif
102
 
103
#if defined(__cris__)
104
#define MATCH_MACHINE(x) (x == EM_CRIS)
105
#define ELFCLASSM       ELFCLASS32
106
#endif
107
 
108
#ifndef MATCH_MACHINE
109
#warning "You really should add a MATCH_MACHINE() macro for your architecture"
110
#endif
111
 
112
#if __BYTE_ORDER == __LITTLE_ENDIAN
113
#define ELFDATAM        ELFDATA2LSB
114
#elif __BYTE_ORDER == __BIG_ENDIAN
115
#define ELFDATAM        ELFDATA2MSB
116
#endif
117
 
118
struct library {
119
        char *name;
120
        int resolved;
121
        char *path;
122
        struct library *next;
123
};
124
struct library *lib_list = NULL;
125
char not_found[] = "not found";
126
char *interp = NULL;
127
char *interp_dir = NULL;
128
int byteswap;
129
static int interpreter_already_found=0;
130
 
131
inline uint32_t byteswap32_to_host(uint32_t value)
132
{
133
        if (byteswap==1) {
134
                return(bswap_32(value));
135
        } else {
136
                return(value);
137
        }
138
}
139
 
140
 
141
 
142
Elf32_Shdr * elf_find_section_type( int key, Elf32_Ehdr *ehdr)
143
{
144
        int j;
145
        Elf32_Shdr *shdr;
146
        shdr = (Elf32_Shdr *)(ehdr->e_shoff + (char *)ehdr);
147
        for (j = ehdr->e_shnum; --j>=0; ++shdr) {
148
                if (key==(int)byteswap32_to_host(shdr->sh_type)) {
149
                        return shdr;
150
                }
151
        }
152
        return NULL;
153
}
154
 
155
Elf32_Phdr * elf_find_phdr_type( int type, Elf32_Ehdr *ehdr)
156
{
157
        int j;
158
        Elf32_Phdr *phdr = (Elf32_Phdr *)(ehdr->e_phoff + (char *)ehdr);
159
        for (j = ehdr->e_phnum; --j>=0; ++phdr) {
160
                if (type==(int)byteswap32_to_host(phdr->p_type)) {
161
                        return phdr;
162
                }
163
        }
164
        return NULL;
165
}
166
 
167
/* Returns value if return_val==1, ptr otherwise */
168
void * elf_find_dynamic(int const key, Elf32_Dyn *dynp,
169
        Elf32_Ehdr *ehdr, int return_val)
170
{
171
        Elf32_Phdr *pt_text = elf_find_phdr_type(PT_LOAD, ehdr);
172
        unsigned tx_reloc = byteswap32_to_host(pt_text->p_vaddr) - byteswap32_to_host(pt_text->p_offset);
173
        for (; DT_NULL!=byteswap32_to_host(dynp->d_tag); ++dynp) {
174
                if (key == (int)byteswap32_to_host(dynp->d_tag)) {
175
                        if (return_val == 1)
176
                                return (void *)(intptr_t)byteswap32_to_host(dynp->d_un.d_val);
177
                        else
178
                                return (void *)(byteswap32_to_host(dynp->d_un.d_val) - tx_reloc + (char *)ehdr );
179
                }
180
        }
181
        return NULL;
182
}
183
 
184
int check_elf_header(Elf32_Ehdr *const ehdr)
185
{
186
        if (! ehdr || strncmp((void *)ehdr, ELFMAG, SELFMAG) != 0 ||
187
                        ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
188
                        ehdr->e_ident[EI_VERSION] != EV_CURRENT)
189
        {
190
                return 1;
191
        }
192
 
193
        /* Check if the target endianness matches the host's endianness */
194
        byteswap = 0;
195
#if __BYTE_ORDER == __LITTLE_ENDIAN
196
        if (ehdr->e_ident[5] == ELFDATA2MSB) {
197
                /* Ick -- we will have to byte-swap everything */
198
                byteswap = 1;
199
        }
200
#elif __BYTE_ORDER == __BIG_ENDIAN
201
        if (ehdr->e_ident[5] == ELFDATA2LSB) {
202
                /* Ick -- we will have to byte-swap everything */
203
                byteswap = 1;
204
        }
205
#else
206
#error Unknown host byte order!
207
#endif
208
 
209
        /* Be vary lazy, and only byteswap the stuff we use */
210
        if (byteswap==1) {
211
                ehdr->e_type=bswap_16(ehdr->e_type);
212
                ehdr->e_phoff=bswap_32(ehdr->e_phoff);
213
                ehdr->e_shoff=bswap_32(ehdr->e_shoff);
214
                ehdr->e_phnum=bswap_16(ehdr->e_phnum);
215
                ehdr->e_shnum=bswap_16(ehdr->e_shnum);
216
        }
217
 
218
        return 0;
219
}
220
 
221
/* This function's behavior must exactly match that
222
 * in uClibc/ldso/ldso/readelflib1.c */
223
static void search_for_named_library(char *name, char *result, const char *path_list)
224
{
225
        int i, count = 1;
226
        char *path, *path_n;
227
        struct stat filestat;
228
 
229
        /* We need a writable copy of this string */
230
        path = strdup(path_list);
231
        if (!path) {
232
                fprintf(stderr, "Out of memory!\n");
233
                exit(EXIT_FAILURE);
234
        }
235
        /* Eliminate all double //s */
236
        path_n=path;
237
        while((path_n=strstr(path_n, "//"))) {
238
                i = strlen(path_n);
239
                memmove(path_n, path_n+1, i-1);
240
                *(path_n + i - 1)='\0';
241
        }
242
 
243
        /* Replace colons with zeros in path_list and count them */
244
        for(i=strlen(path); i > 0; i--) {
245
                if (path[i]==':') {
246
                        path[i]=0;
247
                        count++;
248
                }
249
        }
250
        path_n = path;
251
        for (i = 0; i < count; i++) {
252
                strcpy(result, path_n);
253
                strcat(result, "/");
254
                strcat(result, name);
255
                if (stat (result, &filestat) == 0 && filestat.st_mode & S_IRUSR) {
256
                        free(path);
257
                        return;
258
                }
259
                path_n += (strlen(path_n) + 1);
260
        }
261
        free(path);
262
        *result = '\0';
263
}
264
 
265
void locate_library_file(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, int is_suid, struct library *lib)
266
{
267
        char *buf;
268
        char *path;
269
        struct stat filestat;
270
 
271
        /* If this is a fully resolved name, our job is easy */
272
        if (stat (lib->name, &filestat) == 0) {
273
                lib->path = lib->name;
274
                return;
275
        }
276
 
277
        /* We need some elbow room here.  Make some room...*/
278
        buf = malloc(1024);
279
        if (!buf) {
280
                fprintf(stderr, "Out of memory!\n");
281
                exit(EXIT_FAILURE);
282
        }
283
 
284
        /* This function must match the behavior of _dl_load_shared_library
285
         * in readelflib1.c or things won't work out as expected... */
286
 
287
        /* The ABI specifies that RPATH is searched first, so do that now.  */
288
        path = (char *)elf_find_dynamic(DT_RPATH, dynamic, ehdr, 0);
289
        if (path) {
290
                search_for_named_library(lib->name, buf, path);
291
                if (*buf != '\0') {
292
                        lib->path = buf;
293
                        return;
294
                }
295
        }
296
 
297
        /* Next check LD_{ELF_}LIBRARY_PATH if specified and allowed.
298
         * Since this app doesn't actually run an executable I will skip
299
         * the suid check, and just use LD_{ELF_}LIBRARY_PATH if set */
300
        if (is_suid==1)
301
                path = NULL;
302
        else
303
                path = getenv("LD_LIBRARY_PATH");
304
        if (path) {
305
                search_for_named_library(lib->name, buf, path);
306
                if (*buf != '\0') {
307
                        lib->path = buf;
308
                        return;
309
                }
310
        }
311
 
312
#ifdef USE_CACHE
313
        /* FIXME -- add code to check the Cache here */
314
#endif
315
 
316
 
317
        /* Next look for libraries wherever the shared library
318
         * loader was installed -- this is usually where we
319
         * should find things... */
320
        if (interp_dir) {
321
                search_for_named_library(lib->name, buf, interp_dir);
322
                if (*buf != '\0') {
323
                        lib->path = buf;
324
                        return;
325
                }
326
        }
327
 
328
        /* Lastly, search the standard list of paths for the library.
329
           This list must exactly match the list in uClibc/ldso/ldso/readelflib1.c */
330
        path =  UCLIBC_RUNTIME_PREFIX "usr/X11R6/lib:"
331
                        UCLIBC_RUNTIME_PREFIX "usr/lib:"
332
                        UCLIBC_RUNTIME_PREFIX "lib:"
333
                        "/usr/lib:"
334
                        "/lib";
335
        search_for_named_library(lib->name, buf, path);
336
        if (*buf != '\0') {
337
                lib->path = buf;
338
        } else {
339
                free(buf);
340
                lib->path = not_found;
341
        }
342
}
343
 
344
static int add_library(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, int is_setuid, char *s)
345
{
346
        char *tmp, *tmp1, *tmp2;
347
        struct library *cur, *newlib=lib_list;
348
 
349
        if (!s || !strlen(s))
350
                return 1;
351
 
352
        tmp = s;
353
        while (*tmp) {
354
                if (*tmp == '/')
355
                        s = tmp + 1;
356
                tmp++;
357
        }
358
 
359
        /* We add libc.so.0 elsewhere */
360
        if (interpreter_already_found && (tmp=strrchr(interp, '/')) != NULL)
361
        {
362
                int len = strlen(interp_dir);
363
                if (strcmp(s, interp+1+len)==0)
364
                        return 1;
365
        }
366
 
367
        for (cur = lib_list; cur; cur=cur->next) {
368
                /* Check if this library is already in the list */
369
                tmp1 = tmp2 = cur->name;
370
                while (*tmp1) {
371
                        if (*tmp1 == '/')
372
                                tmp2 = tmp1 + 1;
373
                        tmp1++;
374
                }
375
                if(strcmp(tmp2, s)==0) {
376
                        //printf("find_elf_interpreter is skipping '%s' (already in list)\n", cur->name);
377
                        return 0;
378
                }
379
        }
380
 
381
        /* Ok, this lib needs to be added to the list */
382
        newlib = malloc(sizeof(struct library));
383
        if (!newlib)
384
                return 1;
385
        newlib->name = malloc(strlen(s)+1);
386
        strcpy(newlib->name, s);
387
        newlib->resolved = 0;
388
        newlib->path = NULL;
389
        newlib->next = NULL;
390
 
391
        /* Now try and locate where this library might be living... */
392
        locate_library_file(ehdr, dynamic, is_setuid, newlib);
393
 
394
        //printf("add_library is adding '%s' to '%s'\n", newlib->name, newlib->path);
395
        if (!lib_list) {
396
                lib_list = newlib;
397
        } else {
398
                for (cur = lib_list;  cur->next; cur=cur->next); /* nothing */
399
                cur->next = newlib;
400
        }
401
        return 0;
402
}
403
 
404
 
405
static void find_needed_libraries(Elf32_Ehdr* ehdr, Elf32_Dyn* dynamic, char *strtab, int is_setuid)
406
{
407
        Elf32_Dyn  *dyns;
408
 
409
        for (dyns=dynamic; byteswap32_to_host(dyns->d_tag)!=DT_NULL; ++dyns) {
410
                if (DT_NEEDED == byteswap32_to_host(dyns->d_tag)) {
411
                        add_library(ehdr, dynamic, is_setuid,
412
                                        (char*)strtab + byteswap32_to_host(dyns->d_un.d_val));
413
                }
414
        }
415
}
416
 
417
static struct library * find_elf_interpreter(Elf32_Ehdr* ehdr)
418
{
419
        Elf32_Phdr *phdr;
420
 
421
        if (interpreter_already_found==1)
422
                return NULL;
423
        phdr = elf_find_phdr_type(PT_INTERP, ehdr);
424
        if (phdr) {
425
                struct library *cur, *newlib=NULL;
426
                char *s = (char*)ehdr + byteswap32_to_host(phdr->p_offset);
427
 
428
                char *tmp, *tmp1;
429
                interp = strdup(s);
430
                interp_dir = strdup(s);
431
                tmp = strrchr(interp_dir, '/');
432
                if (*tmp)
433
                        *tmp = '\0';
434
                else {
435
                        free(interp_dir);
436
                        interp_dir = interp;
437
                }
438
                tmp1 = tmp = s;
439
                while (*tmp) {
440
                        if (*tmp == '/')
441
                                tmp1 = tmp + 1;
442
                        tmp++;
443
                }
444
                for (cur = lib_list; cur; cur=cur->next) {
445
                        /* Check if this library is already in the list */
446
                        if(strcmp(cur->name, tmp1)==0) {
447
                                //printf("find_elf_interpreter is replacing '%s' (already in list)\n", cur->name);
448
                                newlib = cur;
449
                                free(newlib->name);
450
                                free(newlib->path);
451
                                return NULL;
452
                        }
453
                }
454
                if (newlib == NULL)
455
                        newlib = malloc(sizeof(struct library));
456
                if (!newlib)
457
                        return NULL;
458
                newlib->name = malloc(strlen(s)+1);
459
                strcpy(newlib->name, s);
460
                newlib->path = newlib->name;
461
                newlib->resolved = 1;
462
                newlib->next = NULL;
463
 
464
#if 0
465
                //printf("find_elf_interpreter is adding '%s' to '%s'\n", newlib->name, newlib->path);
466
                if (!lib_list) {
467
                        lib_list = newlib;
468
                } else {
469
                        for (cur = lib_list;  cur->next; cur=cur->next); /* nothing */
470
                        cur->next = newlib;
471
                }
472
#endif
473
                interpreter_already_found=1;
474
                return newlib;
475
        }
476
        return NULL;
477
}
478
 
479
/* map the .so, and locate interesting pieces */
480
int find_dependancies(char* filename)
481
{
482
        int is_suid = 0;
483
        FILE *thefile;
484
        struct stat statbuf;
485
        char *dynstr=NULL;
486
        Elf32_Ehdr *ehdr = NULL;
487
        Elf32_Shdr *dynsec = NULL;
488
        Elf32_Dyn *dynamic = NULL;
489
        struct library *interp;
490
 
491
        if (filename == not_found)
492
                return 0;
493
 
494
        if (!filename) {
495
                fprintf(stderr, "No filename specified.\n");
496
                return -1;
497
        }
498
        if (!(thefile = fopen(filename, "r"))) {
499
                perror(filename);
500
                return -1;
501
        }
502
        if (fstat(fileno(thefile), &statbuf) < 0) {
503
                perror(filename);
504
                return -1;
505
        }
506
 
507
        if ((size_t)statbuf.st_size < sizeof(Elf32_Ehdr))
508
                goto foo;
509
 
510
        if (!S_ISREG(statbuf.st_mode))
511
                goto foo;
512
 
513
        /* mmap the file to make reading stuff from it effortless */
514
        ehdr = (Elf32_Ehdr *)mmap(0, statbuf.st_size,
515
                        PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(thefile), 0);
516
 
517
foo:
518
        /* Check if this looks like a legit ELF file */
519
        if (check_elf_header(ehdr)) {
520
                fprintf(stderr, "%s: not an ELF file.\n", filename);
521
                return -1;
522
        }
523
        /* Check if this is the right kind of ELF file */
524
        if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN) {
525
                fprintf(stderr, "%s: not a dynamic executable\n", filename);
526
                return -1;
527
        }
528
        if (ehdr->e_type == ET_EXEC) {
529
                if (statbuf.st_mode & S_ISUID)
530
                        is_suid = 1;
531
                if ((statbuf.st_mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
532
                        is_suid = 1;
533
                /* FIXME */
534
                if (is_suid)
535
                        fprintf(stderr, "%s: is setuid\n", filename);
536
        }
537
 
538
        interpreter_already_found=0;
539
        interp = find_elf_interpreter(ehdr);
540
 
541
#ifdef __LDSO_LDD_SUPPORT
542
        if (interp && ehdr->e_type == ET_EXEC && ehdr->e_ident[EI_CLASS] == ELFCLASSM &&
543
                        ehdr->e_ident[EI_DATA] == ELFDATAM
544
                && ehdr->e_ident[EI_VERSION] == EV_CURRENT && MATCH_MACHINE(ehdr->e_machine))
545
        {
546
                struct stat statbuf;
547
                if (stat(interp->path, &statbuf) == 0 && S_ISREG(statbuf.st_mode)) {
548
                        pid_t pid;
549
                        int status;
550
                        static const char * const environment[] = {
551
                                "PATH=/usr/bin:/bin:/usr/sbin:/sbin",
552
                                "SHELL=/bin/sh",
553
                                "LD_TRACE_LOADED_OBJECTS=1",
554
                                NULL
555
                        };
556
 
557
                        if ((pid = fork()) == 0) {
558
                                /* Cool, it looks like we should be able to actually
559
                                 * run this puppy.  Do so now... */
560
                                execle(filename, filename, NULL, environment);
561
                                _exit(0xdead);
562
                        }
563
 
564
                        /* Wait till it returns */
565
                        waitpid(pid, &status, 0);
566
                        if (WIFEXITED(status) && WEXITSTATUS(status)==0) {
567
                                return 1;
568
                        }
569
 
570
                        /* If the exec failed, we fall through to trying to find
571
                         * all the needed libraries ourselves by rummaging about
572
                         * in the ELF headers... */
573
                }
574
        }
575
#endif
576
 
577
        dynsec = elf_find_section_type(SHT_DYNAMIC, ehdr);
578
        if (dynsec) {
579
                dynamic = (Elf32_Dyn*)(byteswap32_to_host(dynsec->sh_offset) + (intptr_t)ehdr);
580
                dynstr = (char *)elf_find_dynamic(DT_STRTAB, dynamic, ehdr, 0);
581
                find_needed_libraries(ehdr, dynamic, dynstr, is_suid);
582
        }
583
 
584
        return 0;
585
}
586
 
587
 
588
 
589
int main( int argc, char** argv)
590
{
591
        int multi=0;
592
        int got_em_all=1;
593
        char *filename = NULL;
594
        struct library *cur;
595
 
596
        if (argc < 2) {
597
                fprintf(stderr, "ldd: missing file arguments\n");
598
                fprintf(stderr, "Try `ldd --help' for more information.\n");
599
                exit(EXIT_FAILURE);
600
        }
601
        if (argc > 2) {
602
                multi++;
603
        }
604
 
605
        while (--argc > 0) {
606
                ++argv;
607
 
608
                if(strcmp(*argv, "--")==0) {
609
                        /* Ignore "--" */
610
                        continue;
611
                }
612
 
613
                if(strcmp(*argv, "--help")==0) {
614
                        fprintf(stderr, "Usage: ldd [OPTION]... FILE...\n");
615
                        fprintf(stderr, "\t--help\t\tprint this help and exit\n");
616
                        exit(EXIT_FAILURE);
617
                }
618
 
619
                filename=*argv;
620
                if (!filename) {
621
                        fprintf(stderr, "No filename specified.\n");
622
                        exit(EXIT_FAILURE);
623
                }
624
 
625
                if (multi) {
626
                        printf("%s:\n", *argv);
627
                }
628
 
629
                if (find_dependancies(filename)!=0)
630
                        continue;
631
 
632
                while(got_em_all) {
633
                        got_em_all=0;
634
                        /* Keep walking the list till everybody is resolved */
635
                        for (cur = lib_list; cur; cur=cur->next) {
636
                                if (cur->resolved == 0 && cur->path) {
637
                                        got_em_all=1;
638
                                        //printf("checking sub-depends for '%s\n", cur->path);
639
                                        find_dependancies(cur->path);
640
                                        cur->resolved = 1;
641
                                }
642
                        }
643
                }
644
 
645
 
646
                /* Print the list */
647
                got_em_all=0;
648
                for (cur = lib_list; cur; cur=cur->next) {
649
                        got_em_all=1;
650
                        printf("\t%s => %s (0x00000000)\n", cur->name, cur->path);
651
                }
652
                if (interp_dir && got_em_all==1)
653
                        printf("\t%s => %s (0x00000000)\n", interp, interp);
654
                if (got_em_all==0)
655
                        printf("\tnot a dynamic executable\n");
656
 
657
                for (cur = lib_list; cur; cur=cur->next) {
658
                        free(cur->name);
659
                        cur->name=NULL;
660
                        if (cur->path && cur->path != not_found)
661
                                free(cur->path);
662
                        cur->path=NULL;
663
                }
664
                lib_list=NULL;
665
        }
666
 
667
        return 0;
668
}
669
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.