| 1 | /* |
1 | /* |
| 2 | * Copyright 2003-2005 Gentoo Foundation |
2 | * Copyright 2003-2005 Gentoo Foundation |
| 3 | * Distributed under the terms of the GNU General Public License v2 |
3 | * Distributed under the terms of the GNU General Public License v2 |
| 4 | * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.96 2005/12/28 22:26:47 solar Exp $ |
4 | * $Header: /var/cvsroot/gentoo-projects/pax-utils/scanelf.c,v 1.97 2005/12/29 14:03:25 vapier Exp $ |
| 5 | * |
5 | * |
| 6 | * Copyright 2003-2005 Ned Ludd - <solar@gentoo.org> |
6 | * Copyright 2003-2005 Ned Ludd - <solar@gentoo.org> |
| 7 | * Copyright 2004-2005 Mike Frysinger - <vapier@gentoo.org> |
7 | * Copyright 2004-2005 Mike Frysinger - <vapier@gentoo.org> |
| 8 | */ |
8 | */ |
| 9 | |
9 | |
| … | |
… | |
| 21 | #include <dirent.h> |
21 | #include <dirent.h> |
| 22 | #include <getopt.h> |
22 | #include <getopt.h> |
| 23 | #include <assert.h> |
23 | #include <assert.h> |
| 24 | #include "paxinc.h" |
24 | #include "paxinc.h" |
| 25 | |
25 | |
| 26 | static const char *rcsid = "$Id: scanelf.c,v 1.96 2005/12/28 22:26:47 solar Exp $"; |
26 | static const char *rcsid = "$Id: scanelf.c,v 1.97 2005/12/29 14:03:25 vapier Exp $"; |
| 27 | #define argv0 "scanelf" |
27 | #define argv0 "scanelf" |
| 28 | |
28 | |
| 29 | #define IS_MODIFIER(c) (c == '%' || c == '#') |
29 | #define IS_MODIFIER(c) (c == '%' || c == '#') |
| 30 | |
30 | |
| 31 | |
31 | |
| … | |
… | |
| 488 | |
488 | |
| 489 | #define LDSO_CACHE_MAGIC "ld.so-" |
489 | #define LDSO_CACHE_MAGIC "ld.so-" |
| 490 | #define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1) |
490 | #define LDSO_CACHE_MAGIC_LEN (sizeof LDSO_CACHE_MAGIC -1) |
| 491 | #define LDSO_CACHE_VER "1.7.0" |
491 | #define LDSO_CACHE_VER "1.7.0" |
| 492 | #define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1) |
492 | #define LDSO_CACHE_VER_LEN (sizeof LDSO_CACHE_VER -1) |
|
|
493 | #define FLAG_ANY -1 |
|
|
494 | #define FLAG_TYPE_MASK 0x00ff |
|
|
495 | #define FLAG_LIBC4 0x0000 |
|
|
496 | #define FLAG_ELF 0x0001 |
|
|
497 | #define FLAG_ELF_LIBC5 0x0002 |
|
|
498 | #define FLAG_ELF_LIBC6 0x0003 |
|
|
499 | #define FLAG_REQUIRED_MASK 0xff00 |
|
|
500 | #define FLAG_SPARC_LIB64 0x0100 |
|
|
501 | #define FLAG_IA64_LIB64 0x0200 |
|
|
502 | #define FLAG_X8664_LIB64 0x0300 |
|
|
503 | #define FLAG_S390_LIB64 0x0400 |
|
|
504 | #define FLAG_POWERPC_LIB64 0x0500 |
|
|
505 | #define FLAG_MIPS64_LIBN32 0x0600 |
|
|
506 | #define FLAG_MIPS64_LIBN64 0x0700 |
| 493 | |
507 | |
| 494 | static char *lookup_cache_lib(char *); |
508 | static char *lookup_cache_lib(elfobj *, char *); |
| 495 | static char *lookup_cache_lib(char *fname) |
509 | static char *lookup_cache_lib(elfobj *elf, char *fname) |
| 496 | { |
510 | { |
| 497 | int fd = 0; |
511 | int fd = 0; |
| 498 | char *strs; |
512 | char *strs; |
| 499 | static char buf[_POSIX_PATH_MAX] = ""; |
513 | static char buf[_POSIX_PATH_MAX] = ""; |
| 500 | const char *cachefile = "/etc/ld.so.cache"; |
514 | const char *cachefile = "/etc/ld.so.cache"; |
| … | |
… | |
| 503 | typedef struct { |
517 | typedef struct { |
| 504 | char magic[LDSO_CACHE_MAGIC_LEN]; |
518 | char magic[LDSO_CACHE_MAGIC_LEN]; |
| 505 | char version[LDSO_CACHE_VER_LEN]; |
519 | char version[LDSO_CACHE_VER_LEN]; |
| 506 | int nlibs; |
520 | int nlibs; |
| 507 | } header_t; |
521 | } header_t; |
|
|
522 | header_t *header; |
| 508 | |
523 | |
| 509 | typedef struct { |
524 | typedef struct { |
| 510 | int flags; |
525 | int flags; |
| 511 | int sooffset; |
526 | int sooffset; |
| 512 | int liboffset; |
527 | int liboffset; |
| 513 | } libentry_t; |
528 | } libentry_t; |
| 514 | |
|
|
| 515 | header_t *header; |
|
|
| 516 | libentry_t *libent; |
529 | libentry_t *libent; |
| 517 | |
530 | |
| 518 | if (fname == NULL) |
531 | if (fname == NULL) |
| 519 | return NULL; |
532 | return NULL; |
| 520 | |
533 | |
| 521 | if (ldcache == 0) { |
534 | if (ldcache == 0) { |
| 522 | if (stat(cachefile, &st) || (fd = open(cachefile, O_RDONLY)) < 0) |
535 | if (stat(cachefile, &st) || (fd = open(cachefile, O_RDONLY)) == -1) |
| 523 | return NULL; |
536 | return NULL; |
| 524 | /* save the cache size for latter unmapping */ |
537 | |
|
|
538 | /* cache these values so we only map/unmap the cache file once */ |
| 525 | ldcache_size = st.st_size; |
539 | ldcache_size = st.st_size; |
| 526 | |
|
|
| 527 | if ((ldcache = mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0)) == (caddr_t) -1) |
540 | ldcache = mmap(0, ldcache_size, PROT_READ, MAP_SHARED, fd, 0); |
|
|
541 | |
|
|
542 | close(fd); |
|
|
543 | |
|
|
544 | if (ldcache == (caddr_t)-1) |
| 528 | return NULL; |
545 | return NULL; |
| 529 | |
|
|
| 530 | close(fd); |
|
|
| 531 | |
546 | |
| 532 | if (memcmp(((header_t *) ldcache)->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN)) |
547 | if (memcmp(((header_t *) ldcache)->magic, LDSO_CACHE_MAGIC, LDSO_CACHE_MAGIC_LEN)) |
| 533 | return NULL; |
548 | return NULL; |
| 534 | |
|
|
| 535 | if (memcmp (((header_t *) ldcache)->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN)) |
549 | if (memcmp (((header_t *) ldcache)->version, LDSO_CACHE_VER, LDSO_CACHE_VER_LEN)) |
| 536 | return NULL; |
550 | return NULL; |
| 537 | } |
551 | } |
| 538 | |
552 | |
| 539 | header = (header_t *) ldcache; |
553 | header = (header_t *) ldcache; |
| 540 | libent = (libentry_t *) (ldcache + sizeof(header_t)); |
554 | libent = (libentry_t *) (ldcache + sizeof(header_t)); |
| 541 | strs = (char *) &libent[header->nlibs]; |
555 | strs = (char *) &libent[header->nlibs]; |
| 542 | |
556 | |
| 543 | for (fd = 0; fd < header->nlibs; fd++) { |
557 | for (fd = 0; fd < header->nlibs; fd++) { |
|
|
558 | /* this should be more fine grained, but for now we assume that |
|
|
559 | * diff arches will not be cached together. and we ignore the |
|
|
560 | * the different multilib mips cases. */ |
|
|
561 | if (elf->elf_class == ELFCLASS64 && !(libent[fd].flags & FLAG_REQUIRED_MASK)) |
|
|
562 | continue; |
|
|
563 | if (elf->elf_class == ELFCLASS32 && (libent[fd].flags & FLAG_REQUIRED_MASK)) |
|
|
564 | continue; |
|
|
565 | |
| 544 | if (strcmp(fname, strs + libent[fd].sooffset) != 0) |
566 | if (strcmp(fname, strs + libent[fd].sooffset) != 0) |
| 545 | continue; |
567 | continue; |
| 546 | strncpy(buf, strs + libent[fd].liboffset, sizeof(buf)); |
568 | strncpy(buf, strs + libent[fd].liboffset, sizeof(buf)); |
| 547 | } |
569 | } |
| 548 | return buf; |
570 | return buf; |
| … | |
… | |
| 583 | needed = (char*)(elf->data + offset); \ |
605 | needed = (char*)(elf->data + offset); \ |
| 584 | if (op == 0) { \ |
606 | if (op == 0) { \ |
| 585 | if (!be_wewy_wewy_quiet) { \ |
607 | if (!be_wewy_wewy_quiet) { \ |
| 586 | if (*found_needed) xchrcat(ret, ',', ret_len); \ |
608 | if (*found_needed) xchrcat(ret, ',', ret_len); \ |
| 587 | if (printcache) \ |
609 | if (printcache) \ |
| 588 | if ((p = lookup_cache_lib(needed)) != NULL) \ |
610 | if ((p = lookup_cache_lib(elf, needed)) != NULL) \ |
| 589 | needed = p; \ |
611 | needed = p; \ |
| 590 | xstrcat(ret, needed, ret_len); \ |
612 | xstrcat(ret, needed, ret_len); \ |
| 591 | } \ |
613 | } \ |
| 592 | *found_needed = 1; \ |
614 | *found_needed = 1; \ |
| 593 | } else { \ |
615 | } else { \ |