Initialize Tizen 2.3
[external/prelink.git] / src / gather.c
1 /* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Red Hat, Inc.
2    Written by Jakub Jelinek <jakub@redhat.com>, 2001.
3
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 2, or (at your option)
7    any later version.
8
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13
14    You should have received a copy of the GNU General Public License
15    along with this program; if not, write to the Free Software Foundation,
16    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
17
18 #include <config.h>
19 #include <assert.h>
20 #include <errno.h>
21 #include <error.h>
22 #include <fcntl.h>
23 #include <fnmatch.h>
24 #include <ftw.h>
25 #include <glob.h>
26 #include <stddef.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <sys/stat.h>
31 #include <unistd.h>
32
33 #include "prelinktab.h"
34 #include "reloc.h"
35
36 #ifndef HAVE_FTW_ACTIONRETVAL
37 # define FTW_ACTIONRETVAL       0
38 # define FTW_CONTINUE           0
39 # define FTW_STOP               1
40 #endif
41
42 static int gather_lib (struct prelink_entry *ent);
43 static int implicit;
44
45 static struct prelink_dir *dirs;
46 static struct prelink_dir *blacklist;
47 #ifndef HAVE_FTW_ACTIONRETVAL
48 static char *blacklist_dir;
49 static size_t blacklist_dir_len;
50 #endif
51 static struct extension
52 {
53   const char *ext;
54   size_t len;
55   int is_glob;
56 } *blacklist_ext;
57 static int blacklist_next;
58
59 static int
60 gather_deps (DSO *dso, struct prelink_entry *ent)
61 {
62   int i, j, seen = 0;
63   FILE *f = NULL;
64   const char *argv[5];
65   const char *envp[4];
66   char *line = NULL, *p, *q = NULL;
67   const char **depends = NULL;
68   size_t ndepends = 0, ndepends_alloced = 0;
69   size_t len = 0;
70   ssize_t n;
71   Elf_Scn *scn;
72   Elf_Data *data;
73   Elf32_Lib *liblist = NULL;
74   int nliblist = 0;
75   const char *dl;
76   const char *ent_filename;
77
78   if (check_dso (dso))
79     {
80       if (! undo)
81         ent->type = ET_UNPRELINKABLE;
82       goto error_out;
83     }
84
85   ent->pltgot = dso->info[DT_PLTGOT];
86   ent->soname = strdup (dso->soname);
87   ent->flags = (dso->arch->class == ELFCLASS64 ? PCF_ELF64 : 0)
88                | (dso->arch->machine & PCF_MACHINE);
89   if (ent->soname == NULL)
90     {
91       error (0, ENOMEM, "%s: Could not record SONAME", ent->filename);
92       goto error_out;
93     }
94
95   dl = dynamic_linker ?: dso->arch->dynamic_linker;
96   if (strcmp (dso->filename, dl) == 0
97       || is_ldso_soname (dso->soname))
98     {
99       if (dynamic_info_is_set (dso, DT_GNU_PRELINKED_BIT)
100           && dynamic_info_is_set (dso, DT_CHECKSUM_BIT))
101         {
102           if (! undo && dso->arch->read_opd)
103             dso->arch->read_opd (dso, ent);
104           ent->done = 2;
105         }
106       close_dso (dso);
107       return 0;
108     }
109
110   for (i = 1; i < dso->ehdr.e_shnum; ++i)
111     {
112       const char *name;
113       if (dso->shdr[i].sh_type == SHT_GNU_LIBLIST
114           && (name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name))
115           && ! strcmp (name, ".gnu.liblist")
116           && (dso->shdr[i].sh_size % sizeof (Elf32_Lib)) == 0)
117         {
118           nliblist = dso->shdr[i].sh_size / sizeof (Elf32_Lib);
119           liblist = (Elf32_Lib *) alloca (dso->shdr[i].sh_size);
120           scn = dso->scn[i];
121           data = elf_getdata (scn, NULL);
122           if (data == NULL || elf_getdata (scn, data)
123               || data->d_buf == NULL || data->d_off
124               || data->d_size != dso->shdr[i].sh_size)
125             liblist = NULL;
126           else
127             memcpy (liblist, data->d_buf, dso->shdr[i].sh_size);
128           if (! undo)
129             break;
130         }
131       else if (undo
132                && dso->shdr[i].sh_type == SHT_PROGBITS
133                && (name = strptr (dso, dso->ehdr.e_shstrndx,
134                                   dso->shdr[i].sh_name))
135                && ! strcmp (name, ".gnu.prelink_undo"))
136         ent->done = 2;
137     }
138
139   if (! undo && dso->arch->read_opd)
140     dso->arch->read_opd (dso, ent);
141   close_dso (dso);
142   dso = NULL;
143
144   i = 0;
145   argv[i++] = dl;
146   if (ld_library_path)
147     {
148       argv[i++] = "--library-path";
149       argv[i++] = ld_library_path;
150     }
151   if (strchr (ent->filename, '/') != NULL)
152     ent_filename = ent->filename;
153   else
154     {
155       size_t flen = strlen (ent->filename);
156       char *tp = alloca (2 + flen + 1);
157       memcpy (tp, "./", 2);
158       memcpy (tp + 2, ent->filename, flen + 1);
159       ent_filename = tp;
160     }
161   argv[i++] = ent_filename;
162   argv[i] = NULL;
163   envp[0] = "LD_TRACE_LOADED_OBJECTS=1";
164   envp[1] = "LD_TRACE_PRELINKING=1";
165   envp[2] = "LD_WARN=";
166   envp[3] = NULL;
167   f = execve_open (dl, (char * const *)argv, (char * const *)envp);
168   if (f == NULL)
169     goto error_out;
170
171   do
172     {
173       n = getline (&line, &len, f);
174       if (n < 0)
175         break;
176
177       if (line[n - 1] == '\n')
178         line[n - 1] = '\0';
179
180       p = strstr (line, " => ");
181       if (p)
182         {
183           q = strstr (p, " (");
184           if (q == NULL && strcmp (p, " => not found") == 0)
185             {
186               error (0, 0, "%s: Could not find one of the dependencies",
187                      ent->filename);
188               goto error_out;
189             }
190         }
191       if (p == NULL || q == NULL)
192         {
193           if (strstr (line, "statically linked") != NULL)
194             error (0, 0, "%s: Library without dependencies", ent->filename);
195           else
196             {
197               p = strstr (line, "error while loading shared libraries: ");
198               if (p != NULL)
199                 {
200                   p += sizeof "error while loading shared libraries: " - 1;
201                   q = strstr (line, "cannot open shared object file: "
202                                     "No such file or directory");
203                   if (q != NULL)
204                     {
205                       error (0, 0,
206                              "%s: Could not find one of the dependencies",
207                              ent->filename);
208                       goto error_out;
209                     }
210                 }
211               error (0, 0, "%s: Could not parse `%s'", ent->filename, line);
212             }
213           goto error_out;
214         }
215
216       *p = '\0';
217       p += sizeof " => " - 1;
218       *q = '\0';
219       if (! strcmp (p, ent_filename))
220         {
221           ++seen;
222           continue;
223         }
224       if (ndepends == ndepends_alloced)
225         {
226           ndepends_alloced += 10;
227           depends =
228             (const char **) realloc (depends,
229                                      ndepends_alloced * sizeof (char *));
230           if (depends == NULL)
231             {
232               error (0, ENOMEM, "%s: Could not record dependencies",
233                      ent->filename);
234               goto error_out;
235             }
236         }
237
238       depends[ndepends] = strdupa (p);
239       ++ndepends;
240     } while (!feof (f));
241
242   if (execve_close (f))
243     {
244       f = NULL;
245       error (0, 0, "%s: Dependency tracing failed", ent->filename);
246       goto error_out;
247     }
248
249   f = NULL;
250   if (seen != 1)
251     {
252       error (0, 0, "%s seen %d times in LD_TRACE_PRELINKING output, expected once",
253              ent->filename, seen);
254       goto error_out;
255     }
256
257   free (line);
258   line = NULL;
259
260   if (ndepends == 0)
261     ent->depends = NULL;
262   else
263     {
264       ent->depends =
265         (struct prelink_entry **)
266         malloc (ndepends * sizeof (struct prelink_entry *));
267       if (ent->depends == NULL)
268         {
269           error (0, ENOMEM, "%s: Could not record dependencies", ent->filename);
270           goto error_out;
271         }
272     }
273
274   ent->ndepends = ndepends;
275   char *cache_dyn_depends = NULL;
276   if (ndepends)
277     {
278       cache_dyn_depends = alloca (ndepends);
279       memset (cache_dyn_depends, '\0', ndepends);
280     }
281   for (i = 0; i < ndepends; ++i)
282     {
283       ent->depends[i] = prelink_find_entry (depends [i], NULL, 1);
284       if (ent->depends[i] == NULL)
285         goto error_out_free_depends;
286
287       if (ent->depends[i]->type == ET_CACHE_DYN)
288         {
289           ent->depends[i]->type = ET_NONE;
290           free (ent->depends[i]->depends);
291           ent->depends[i]->depends = NULL;
292           ent->depends[i]->ndepends = 0;
293           cache_dyn_depends[i] = 1;
294         }
295
296       if (ent->depends[i]->type != ET_NONE
297           && ent->depends[i]->type != ET_BAD
298           && ent->depends[i]->type != ET_DYN
299           && ent->depends[i]->type != ET_UNPRELINKABLE)
300         {
301           error (0, 0, "%s is not a shared library", depends [i]);
302 error_out_regather_libs:
303           for (i = 0; i < ndepends; ++i)
304             {
305               if (cache_dyn_depends[i] && ent->depends[i]->type == ET_NONE)
306                 gather_lib (ent->depends[i]);
307             }
308           goto error_out_free_depends;
309         }
310     }
311
312   free (depends);
313   depends = NULL;
314
315   for (i = 0; i < ndepends; ++i)
316     if (ent->depends[i]->type == ET_NONE
317         && gather_lib (ent->depends[i]))
318       {
319         cache_dyn_depends[i] = 0;
320         goto error_out_regather_libs;
321       }
322
323   for (i = 0; i < ndepends; ++i)
324     for (j = 0; j < ent->depends[i]->ndepends; ++j)
325       if (ent->depends[i]->depends[j] == ent)
326         {
327           error (0, 0, "%s has a dependency cycle", ent->canon_filename);
328           goto error_out_free_depends;
329         }
330
331   for (i = 0; i < ndepends; ++i)
332     if (ent->depends[i]->type == ET_UNPRELINKABLE)
333       {
334         error (0, 0, "Could not prelink %s because its dependency %s could not be prelinked",
335                ent->filename, ent->depends[i]->filename);
336         ent->type = ET_UNPRELINKABLE;
337         goto error_out;
338       }
339
340   if (! undo && (!nliblist || liblist) && nliblist == ndepends)
341     {
342       for (i = 0; i < ndepends; ++i)
343         if (liblist[i].l_time_stamp != ent->depends[i]->timestamp
344             || liblist[i].l_checksum != ent->depends[i]->checksum
345             || ! ent->depends[i]->done)
346           break;
347
348       if (i == ndepends)
349         ent->done = 2;
350     }
351
352   return 0;
353
354 error_out_free_depends:
355   free (ent->depends);
356   ent->depends = NULL;
357   ent->ndepends = 0;
358 error_out:
359   if (f)
360     execve_close (f);
361   free (line);
362   free (depends);
363   if (dso)
364     close_dso (dso);
365   return 1;
366 }
367
368 static int
369 gather_dso (DSO *dso, struct prelink_entry *ent)
370 {
371   int prelinked;
372
373   if (verbose > 5)
374     printf ("Checking shared library %s\n", ent->canon_filename);
375
376   if (dso->ehdr.e_type != ET_DYN)
377     {
378       error (0, 0, "%s is not a shared library", ent->filename);
379       close_dso (dso);
380       return 1;
381     }
382
383   prelinked = (dynamic_info_is_set (dso, DT_GNU_PRELINKED_BIT)
384                && dynamic_info_is_set (dso, DT_CHECKSUM_BIT));
385   ent->timestamp = dso->info_DT_GNU_PRELINKED;
386   ent->checksum = dso->info_DT_CHECKSUM;
387   ent->base = dso->base;
388   ent->end = dso->end;
389   if (dso->arch->need_rel_to_rela != NULL && ! prelinked)
390     {
391       /* If the library has not been prelinked yet and we need
392          to convert REL to RELA, then make room for it.  */
393       struct reloc_info rinfo;
394       GElf_Addr adjust = 0;
395       int sec = dso->ehdr.e_shnum;
396
397       if (find_reloc_sections (dso, &rinfo))
398         {
399           close_dso (dso);
400           return 1;
401         }
402
403       assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2);
404       assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2);
405       if (rinfo.rel_to_rela)
406         {
407           sec = rinfo.first;
408           adjust = (dso->shdr[rinfo.last].sh_addr
409                     + dso->shdr[rinfo.last].sh_size
410                     - dso->shdr[rinfo.first].sh_addr) / 2;
411         }
412       if (rinfo.rel_to_rela_plt)
413         {
414           if (rinfo.plt < sec)
415             sec = rinfo.plt;
416           adjust += dso->shdr[rinfo.plt].sh_size / 2;
417         }
418       if (adjust)
419         {
420           int align = 0, i, last;
421           GElf_Addr start;
422
423           for (i = rinfo.plt ? rinfo.plt : rinfo.first;
424                i < dso->ehdr.e_shnum; i++)
425             {
426               if (dso->shdr[i].sh_addralign > align)
427                 align = dso->shdr[i].sh_addralign;
428             }
429
430           if (rinfo.plt)
431             start = dso->shdr[rinfo.plt].sh_addr
432                     + dso->shdr[rinfo.plt].sh_size;
433           else
434             start = dso->shdr[rinfo.first].sh_addr
435                     + dso->shdr[rinfo.first].sh_size;
436
437           /* Need to make sure that all the remaining sections are properly
438              aligned.  */
439           if (align)
440             adjust = (adjust + align - 1) & ~(align - 1);
441
442           /* Need to make sure adjust doesn't cause different Phdr segments
443              to overlap on the same page.  */
444           last = -1;
445           for (i = 0; i < dso->ehdr.e_phnum; ++i)
446             if (dso->phdr[i].p_type == PT_LOAD
447                 && dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz >= start)
448               {
449                 if (last != -1
450                     && (((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz
451                           - 1) ^ dso->phdr[i].p_vaddr)
452                         & ~(dso->arch->max_page_size - 1))
453                     && !(((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz
454                            + adjust - 1)
455                           ^ (dso->phdr[i].p_vaddr + adjust))
456                          & ~(dso->arch->max_page_size - 1)))
457                   {
458                     if (align >= dso->arch->max_page_size)
459                       {
460                         error (0, 0, "%s: Cannot grow reloc sections",
461                                ent->filename);
462                         close_dso (dso);
463                         return 1;
464                       }
465                     adjust = (adjust + dso->arch->max_page_size - 1)
466                              & ~(dso->arch->max_page_size - 1);
467                   }
468                 last = i;
469               }
470
471           ent->end += adjust;
472         }
473     }
474
475   if (gather_deps (dso, ent))
476     return 1;
477
478   if (ent->done && ! prelinked && ! undo)
479     ent->done = 0;
480   ent->type = ET_DYN;
481   return 0;
482 }
483
484 static int
485 gather_lib (struct prelink_entry *ent)
486 {
487   DSO *dso;
488
489   ent->type = ET_BAD;
490   dso = open_dso (ent->filename);
491   if (dso == NULL)
492     return 1;
493
494   return gather_dso (dso, ent);
495 }
496
497 static int
498 gather_exec (DSO *dso, const struct stat64 *st)
499 {
500   int i, j;
501   Elf_Data *data;
502   const char *dl;
503   struct prelink_entry *ent;
504
505   if (verbose > 5)
506     printf ("Checking executable %s\n", dso->filename);
507
508   for (i = 0; i < dso->ehdr.e_phnum; ++i)
509     if (dso->phdr[i].p_type == PT_INTERP)
510       break;
511
512   /* If there are no PT_INTERP segments, it is statically linked.  */
513   if (i == dso->ehdr.e_phnum)
514     {
515 make_unprelinkable:
516       if (undo)
517         goto error_out;
518
519       ent = prelink_find_entry (dso->filename, st, 1);
520       if (ent == NULL)
521         goto error_out;
522
523       assert (ent->type == ET_NONE);
524       ent->type = ET_UNPRELINKABLE;
525       if (dso)
526         close_dso (dso);
527       return 0;
528     }
529
530   j = addr_to_sec (dso, dso->phdr[i].p_vaddr);
531   if (j == -1 || dso->shdr[j].sh_addr != dso->phdr[i].p_vaddr
532       || dso->shdr[j].sh_type != SHT_PROGBITS)
533     {
534       error (0, 0, "%s: PT_INTERP segment not corresponding to .interp section",
535              dso->filename);
536       goto make_unprelinkable;
537     }
538
539   data = elf_getdata (dso->scn[j], NULL);
540   if (data == NULL)
541     {
542       error (0, 0, "%s: Could not read .interp section", dso->filename);
543       goto error_out;
544     }
545
546   i = strnlen (data->d_buf, data->d_size);
547   if (i == data->d_size)
548     {
549       error (0, 0, "%s: .interp section not zero terminated", dso->filename);
550       goto error_out;
551     }
552
553   dl = dynamic_linker ?: dso->arch->dynamic_linker;
554   if (strcmp (dl, data->d_buf) != 0)
555     {
556       error (0, 0, "%s: Using %s, not %s as dynamic linker", dso->filename,
557              (char *) data->d_buf, dl);
558       goto error_out;
559     }
560
561   ent = prelink_find_entry (dso->filename, st, 1);
562   if (ent == NULL)
563     goto error_out;
564
565   assert (ent->type == ET_NONE);
566   ent->u.explicit = 1;
567
568   if (gather_deps (dso, ent))
569     return 0;
570
571   for (i = 0; i < ent->ndepends; ++i)
572     ++ent->depends[i]->refs;
573
574   ent->type = ET_EXEC;
575   return 0;
576
577 error_out:
578   if (dso)
579     close_dso (dso);
580   return 0;
581 }
582
583 static int
584 add_dir_to_dirlist (const char *name, dev_t dev, int flags)
585 {
586   const char *canon_name;
587   struct prelink_dir *dir;
588   size_t len;
589
590   canon_name = prelink_canonicalize (name, NULL);
591   if (canon_name == NULL)
592     {
593       if (! all && implicit)
594         return 0;
595       error (0, errno, "Could not record directory %s", name);
596       return 1;
597     }
598
599   len = strlen (canon_name);
600
601   for (dir = blacklist; dir; dir = dir->next)
602     if (((dir->flags != FTW_CHDIR && len >= dir->len)
603          || (dir->flags == FTW_CHDIR && len == dir->len))
604         && strncmp (dir->dir, canon_name, dir->len) == 0)
605       {
606         if (dir->flags == FTW_CHDIR)
607           break;
608         if ((dir->flags & FTW_MOUNT) && dir->dev != dev)
609           continue;
610         break;
611       }
612
613   if (dir != NULL)
614     {
615       free ((char *) canon_name);
616       return 2;
617     }
618
619   dir = malloc (sizeof (struct prelink_dir) + len + 1);
620   if (dir == NULL)
621     {
622       error (0, ENOMEM, "Could not record directory %s", name);
623       free ((char *) canon_name);
624       return 1;
625     }
626
627   dir->next = dirs;
628   dir->flags = flags;
629   dir->dev = dev;
630   dir->len = len;
631   strcpy (dir->dir, canon_name);
632   free ((char *) canon_name);
633   dirs = dir;
634   return 0;
635 }
636
637 static int
638 gather_func (const char *name, const struct stat64 *st, int type,
639              struct FTW *ftwp)
640 {
641   unsigned char e_ident [sizeof (Elf64_Ehdr) + sizeof (Elf64_Phdr)];
642
643 #ifndef HAVE_FTW_ACTIONRETVAL
644   if (blacklist_dir)
645     {
646       if (strncmp (name, blacklist_dir, blacklist_dir_len) == 0)
647         return FTW_CONTINUE;
648       free (blacklist_dir);
649       blacklist_dir = NULL;
650     }
651 #endif
652   if (type == FTW_F && S_ISREG (st->st_mode) && (st->st_mode & 0111))
653     {
654       int fd, i;
655       DSO *dso;
656       struct prelink_entry *ent;
657       size_t len = strlen (name);
658       const char *base = NULL;
659
660       for (i = 0; i < blacklist_next; ++i)
661         if (blacklist_ext[i].is_glob)
662           {
663             if (base == NULL)
664               {
665                 base = strrchr (name, '/');
666                 if (base == NULL)
667                   base = name;
668                 else
669                   ++base;
670               }
671             if (fnmatch (blacklist_ext[i].ext, base, FNM_PERIOD) == 0)
672               return FTW_CONTINUE;
673           }
674         else if (blacklist_ext[i].len <= len
675                  && memcmp (name + len - blacklist_ext[i].len,
676                             blacklist_ext[i].ext, blacklist_ext[i].len) == 0)
677           return FTW_CONTINUE;
678
679       ent = prelink_find_entry (name, st, 0);
680       if (ent != NULL && ent->type != ET_NONE)
681         {
682           if (verbose > 5)
683             {
684               if (ent->type == ET_CACHE_EXEC || ent->type == ET_CACHE_DYN)
685                 printf ("Assuming prelinked %s\n", name);
686               if (ent->type == ET_UNPRELINKABLE)
687                 printf ("Assuming non-prelinkable %s\n", name);
688             }
689           ent->u.explicit = 1;
690           return FTW_CONTINUE;
691         }
692
693       if (st->st_size < sizeof (e_ident))
694         return FTW_CONTINUE;
695
696       fd = open (name, O_RDONLY);
697       if (fd == -1)
698         return FTW_CONTINUE;
699
700       if (read (fd, e_ident, sizeof (e_ident)) != sizeof (e_ident))
701         {
702 close_it:
703           close (fd);
704           return FTW_CONTINUE;
705         }
706
707       /* Quickly find ET_EXEC ELF binaries and most of PIE binaries.  */
708
709       if (memcmp (e_ident, ELFMAG, SELFMAG) != 0)
710         {
711 make_unprelinkable:
712           if (! undo)
713             {
714               ent = prelink_find_entry (name, st, 1);
715               if (ent != NULL)
716                 {
717                   assert (ent->type == ET_NONE);
718                   ent->type = ET_UNPRELINKABLE;
719                 }
720             }
721           close (fd);
722           return FTW_CONTINUE;
723         }
724
725       switch (e_ident [EI_DATA])
726         {
727         case ELFDATA2LSB:
728           if (e_ident [EI_NIDENT + 1] != 0)
729             goto make_unprelinkable;
730           if (e_ident [EI_NIDENT] != ET_EXEC)
731             {
732               if (e_ident [EI_NIDENT] != ET_DYN)
733                 goto make_unprelinkable;
734               else if (e_ident [EI_CLASS] == ELFCLASS32)
735                 {
736                   if (e_ident [offsetof (Elf32_Ehdr, e_phoff)]
737                       == sizeof (Elf32_Ehdr)
738                       && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff) + 1,
739                                  "\0\0\0", 3) == 0
740                       && (e_ident [offsetof (Elf32_Ehdr, e_phnum)]
741                           || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1])
742                       && e_ident [sizeof (Elf32_Ehdr)
743                                   + offsetof (Elf32_Phdr, p_type)] == PT_PHDR
744                       && memcmp (e_ident + sizeof (Elf32_Ehdr)
745                                  + offsetof (Elf32_Phdr, p_type) + 1,
746                                  "\0\0\0", 3) == 0)
747                     {
748 maybe_pie:
749                       dso = fdopen_dso (fd, name);
750                       if (dso == NULL)
751                         goto close_it;
752                       if (dynamic_info_is_set (dso, DT_DEBUG))
753                         {
754                           close_dso (dso);
755                           goto make_unprelinkable;
756                         }
757                       close_dso (dso);
758                     }
759                   goto close_it;
760                 }
761               else if (e_ident [EI_CLASS] == ELFCLASS64)
762                 {
763                   if (e_ident [offsetof (Elf64_Ehdr, e_phoff)]
764                       == sizeof (Elf64_Ehdr)
765                       && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff) + 1,
766                                  "\0\0\0\0\0\0\0", 7) == 0
767                       && (e_ident [offsetof (Elf64_Ehdr, e_phnum)]
768                           || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1])
769                       && e_ident [sizeof (Elf64_Ehdr)
770                                   + offsetof (Elf64_Phdr, p_type)] == PT_PHDR
771                       && memcmp (e_ident + sizeof (Elf64_Ehdr)
772                                  + offsetof (Elf64_Phdr, p_type) + 1,
773                                  "\0\0\0", 3) == 0)
774                     goto maybe_pie;
775                   goto close_it;
776                 }
777               else
778                 goto make_unprelinkable;
779             }
780           break;
781         case ELFDATA2MSB:
782           if (e_ident [EI_NIDENT] != 0)
783             goto make_unprelinkable;
784           if (e_ident [EI_NIDENT + 1] != ET_EXEC)
785             {
786               if (e_ident [EI_NIDENT + 1] != ET_DYN)
787                 goto make_unprelinkable;
788               else if (e_ident [EI_CLASS] == ELFCLASS32)
789                 {
790                   if (e_ident [offsetof (Elf32_Ehdr, e_phoff) + 3]
791                       == sizeof (Elf32_Ehdr)
792                       && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff),
793                                  "\0\0\0", 3) == 0
794                       && (e_ident [offsetof (Elf32_Ehdr, e_phnum)]
795                           || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1])
796                       && e_ident [sizeof (Elf32_Ehdr)
797                                   + offsetof (Elf32_Phdr, p_type) + 3]
798                          == PT_PHDR
799                       && memcmp (e_ident + sizeof (Elf32_Ehdr)
800                                  + offsetof (Elf32_Phdr, p_type),
801                                  "\0\0\0", 3) == 0)
802                     goto maybe_pie;
803                   goto close_it;
804                 }
805               else if (e_ident [EI_CLASS] == ELFCLASS64)
806                 {
807                   if (e_ident [offsetof (Elf64_Ehdr, e_phoff) + 7]
808                       == sizeof (Elf64_Ehdr)
809                       && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff),
810                                  "\0\0\0\0\0\0\0", 7) == 0
811                       && (e_ident [offsetof (Elf64_Ehdr, e_phnum)]
812                           || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1])
813                       && e_ident [sizeof (Elf64_Ehdr)
814                                   + offsetof (Elf64_Phdr, p_type) + 3]
815                          == PT_PHDR
816                       && memcmp (e_ident + sizeof (Elf64_Ehdr)
817                                  + offsetof (Elf64_Phdr, p_type),
818                                  "\0\0\0", 3) == 0)
819                     goto maybe_pie;
820                   goto close_it;
821                 }
822               else
823                 goto make_unprelinkable;
824             }
825           break;
826         default:
827           goto make_unprelinkable;
828         }
829
830       dso = fdopen_dso (fd, name);
831       if (dso == NULL)
832         return FTW_CONTINUE;
833
834       gather_exec (dso, st);
835     }
836   else if (type == FTW_D)
837     switch (add_dir_to_dirlist (name, st->st_dev, FTW_CHDIR))
838       {
839       case 0: return FTW_CONTINUE;
840       default: return FTW_STOP;
841       case 2:
842 #ifdef HAVE_FTW_ACTIONRETVAL
843         return FTW_SKIP_SUBTREE;
844 #else
845         {
846           blacklist_dir_len = strlen (name) + 1;
847           if (blacklist_dir_len > 1 && name[blacklist_dir_len - 2] == '/')
848             blacklist_dir_len--;
849           blacklist_dir = malloc (blacklist_dir_len + 1);
850           if (blacklist_dir == NULL)
851             {
852               error (0, ENOMEM, "Cannot store blacklisted dir name");
853               return FTW_STOP;
854             }
855           memcpy (blacklist_dir, name, blacklist_dir_len - 1);
856           blacklist_dir[blacklist_dir_len - 1] = '/';
857           blacklist_dir[blacklist_dir_len] = '\0';
858           return FTW_CONTINUE;
859         }
860 #endif
861       }
862
863   return FTW_CONTINUE;
864 }
865
866 static int
867 gather_binlib (const char *name, const struct stat64 *st)
868 {
869   unsigned char e_ident [EI_NIDENT + 2];
870   int fd, type;
871   DSO *dso;
872   struct prelink_entry *ent;
873
874   if (! S_ISREG (st->st_mode))
875     {
876       error (0, 0, "%s is not a regular file", name);
877       return 1;
878     }
879
880   ent = prelink_find_entry (name, st, 0);
881   if (ent != NULL && ent->type == ET_UNPRELINKABLE)
882     {
883       free (ent->depends);
884       ent->depends = NULL;
885       ent->ndepends = 0;
886       ent->type = ET_NONE;
887     }
888   if (ent != NULL && ent->type != ET_NONE)
889     {
890       ent->u.explicit = 1;
891       return 0;
892     }
893
894   fd = open (name, O_RDONLY);
895   if (fd == -1)
896     {
897       error (0, errno, "Could not open %s", name);
898       return 1;
899     }
900
901   if (read (fd, e_ident, sizeof (e_ident)) != sizeof (e_ident))
902     {
903       error (0, errno, "Could not read ELF header from %s", name);
904       close (fd);
905       return 1;
906     }
907
908   /* Quickly find ET_EXEC/ET_DYN ELF binaries/libraries only.  */
909
910   if (memcmp (e_ident, ELFMAG, SELFMAG) != 0)
911     {
912       error (0, 0, "%s is not an ELF object", name);
913       close (fd);
914       return 1;
915     }
916
917   switch (e_ident [EI_DATA])
918     {
919     case ELFDATA2LSB:
920       if (e_ident [EI_NIDENT + 1] != 0)
921         goto unsupported_type;
922       type = e_ident [EI_NIDENT];
923       break;
924     case ELFDATA2MSB:
925       if (e_ident [EI_NIDENT] != 0)
926         goto unsupported_type;
927       type = e_ident [EI_NIDENT + 1];
928       break;
929     default:
930       goto unsupported_type;
931     }
932
933   if (type != ET_EXEC && type != ET_DYN)
934     {
935 unsupported_type:
936       error (0, 0, "%s is neither ELF executable nor ELF shared library", name);
937       close (fd);
938       return 1;
939     }
940
941   dso = fdopen_dso (fd, name);
942   if (dso == NULL)
943     return 0;
944
945   if (type == ET_EXEC)
946     {
947       int i;
948
949       for (i = 0; i < dso->ehdr.e_phnum; ++i)
950         if (dso->phdr[i].p_type == PT_INTERP)
951           break;
952
953       /* If there are no PT_INTERP segments, it is statically linked.  */
954       if (i == dso->ehdr.e_phnum)
955         {
956           error (0, 0, "%s is statically linked", name);
957           close_dso (dso);
958           return 1;
959         }
960
961       return gather_exec (dso, st);
962     }
963
964   ent = prelink_find_entry (name, st, 1);
965   if (ent == NULL)
966     {
967       close_dso (dso);
968       return 1;
969     }
970
971   assert (ent->type == ET_NONE);
972   ent->type = ET_BAD;
973   ent->u.explicit = 1;
974   return gather_dso (dso, ent);
975 }
976
977 int
978 gather_object (const char *name, int deref, int onefs)
979 {
980   struct stat64 st;
981
982   if (stat64 (name, &st) < 0)
983     {
984       if (implicit)
985         return 0;
986       error (0, errno, "Could not stat %s", name);
987       return 1;
988     }
989
990   if (S_ISDIR (st.st_mode))
991     {
992       int flags = 0, ret;
993       if (! deref) flags |= FTW_PHYS;
994       if (onefs) flags |= FTW_MOUNT;
995
996       if (implicit && ! deref)
997         {
998           ret = add_dir_to_dirlist (name, st.st_dev, flags);
999           if (ret)
1000             return ret == 2 ? 0 : 1;
1001         }
1002       if (!all && implicit && ! deref)
1003         return 0;
1004       ++implicit;
1005       ret = nftw64 (name, gather_func, 20, flags | FTW_ACTIONRETVAL);
1006       --implicit;
1007       if (ret < 0)
1008         error (0, errno, "Failed searching %s", name);
1009 #ifndef HAVE_FTW_ACTIONRETVAL
1010       free (blacklist_dir);
1011       blacklist_dir = NULL;
1012 #endif
1013       return ret;
1014     }
1015   else
1016     return gather_binlib (name, &st);
1017 }
1018
1019 static struct config_line
1020 {
1021   struct config_line *next;
1022   char line[1];
1023 } *config_lines, **config_end = &config_lines;
1024
1025 int
1026 read_config (const char *config)
1027 {
1028   FILE *file = fopen (config, "r");
1029   char *line = NULL;
1030   size_t len, llen;
1031   int ret = 0;
1032   struct config_line *c;
1033
1034   if (file == NULL)
1035     {
1036       error (0, errno, "Can't open configuration file %s", config);
1037       return 1;
1038     }
1039
1040   do
1041     {
1042       ssize_t i = getline (&line, &len, file);
1043       char *p;
1044
1045       if (i < 0)
1046         break;
1047
1048       if (line[i - 1] == '\n')
1049         line[i - 1] = '\0';
1050
1051       p = strchr (line, '#');
1052       if (p != NULL)
1053         *p = '\0';
1054
1055       p = line + strspn (line, " \t");
1056       if (p[0] == '-' && p[1] == 'c' && (p[2] == ' ' || p[2] == '\t'))
1057         {
1058           glob_t g;
1059           p += 2 + strspn (p + 2, " \t");
1060
1061           if (!glob (p, GLOB_BRACE, NULL, &g))
1062             {
1063               size_t n;
1064
1065               for (n = 0; n < g.gl_pathc; ++n)
1066                 if (read_config (g.gl_pathv[n]))
1067                   {
1068                     ret = 1;
1069                     break;
1070                   }
1071
1072               globfree (&g);
1073               if (ret)
1074                 break;
1075             }
1076           continue;
1077         }
1078
1079       llen = strlen (p);
1080       c = malloc (sizeof (*c) + llen);
1081       if (c == NULL)
1082         {
1083           error (0, ENOMEM, "Could not cache config file");
1084           ret = 1;
1085           break;
1086         }
1087
1088       c->next = NULL;
1089       memcpy (c->line, p, llen + 1);
1090       *config_end = c;
1091       config_end = &c->next;
1092     }
1093   while (!feof (file));
1094
1095   free (line);
1096   fclose (file);
1097   return ret;
1098 }
1099
1100 int
1101 gather_config (void)
1102 {
1103   struct config_line *c;
1104   int ret = 0;
1105
1106   implicit = 1;
1107   for (c = config_lines; c; c = c->next)
1108     {
1109       int deref = 0;
1110       int onefs = 0;
1111       char *p = c->line;
1112
1113       while (*p == '-')
1114         {
1115           switch (p[1])
1116             {
1117             case 'h': deref = 1; break;
1118             case 'l': onefs = 1; break;
1119             case 'b': p = ""; continue;
1120             default:
1121               error (0, 0, "Unknown directory option `%s'\n", p);
1122               break;
1123             }
1124           p = p + 2 + strspn (p + 2, " \t");
1125         }
1126
1127       if (*p == '\0')
1128         continue;
1129
1130       if (strpbrk (p, "*?[{") == NULL)
1131         {
1132           ret = gather_object (p, deref, onefs);
1133           if (ret)
1134             {
1135               ret = 1;
1136               break;
1137             }
1138         }
1139       else
1140         {
1141           glob_t g;
1142
1143           if (!glob (p, GLOB_BRACE, NULL, &g))
1144             {
1145               size_t n;
1146
1147               for (n = 0; n < g.gl_pathc; ++n)
1148                 {
1149                   ret = gather_object (g.gl_pathv[n], deref, onefs);
1150                   if (ret)
1151                     {
1152                       ret = 1;
1153                       break;
1154                     }
1155                 }
1156
1157               globfree (&g);
1158               if (ret)
1159                 break;
1160             }
1161         }
1162     }
1163
1164   implicit = 0;
1165   return ret;
1166 }
1167
1168 static int
1169 gather_check_lib (void **p, void *info)
1170 {
1171   struct prelink_entry *e = * (struct prelink_entry **) p;
1172
1173   if (e->type != ET_DYN)
1174     return 1;
1175
1176   if (! e->u.explicit)
1177     {
1178       struct prelink_dir *dir;
1179       const char *name;
1180       size_t len;
1181
1182       name = strrchr (e->canon_filename, '/');
1183       if (!name)
1184         name = e->canon_filename;
1185       len = name - e->canon_filename;
1186
1187       for (dir = blacklist; dir; dir = dir->next)
1188         if (((dir->flags != FTW_CHDIR && len >= dir->len)
1189              || (dir->flags == FTW_CHDIR && len == dir->len))
1190             && strncmp (dir->dir, e->canon_filename, dir->len) == 0)
1191           {
1192             if (dir->flags == FTW_CHDIR)
1193               break;
1194             if ((dir->flags & FTW_MOUNT) && dir->dev != e->dev)
1195               continue;
1196             break;
1197           }
1198
1199       if (dir != NULL)
1200         {
1201           error (0, 0, "%s is present in a blacklisted directory %s",
1202                  e->canon_filename, dir->dir);
1203           e->type = ET_BAD;
1204           return 1;
1205         }
1206
1207       for (dir = dirs; dir; dir = dir->next)
1208         if (((dir->flags != FTW_CHDIR && len >= dir->len)
1209              || (dir->flags == FTW_CHDIR && len == dir->len))
1210             && strncmp (dir->dir, e->canon_filename, dir->len) == 0)
1211           {
1212             if (dir->flags == FTW_CHDIR)
1213               break;
1214             if ((dir->flags & FTW_MOUNT) && dir->dev != e->dev)
1215               continue;
1216             break;
1217           }
1218
1219       if (dir == NULL)
1220         {
1221           error (0, 0, "%s is not present in any config file directories, nor was specified on command line",
1222                  e->canon_filename);
1223           e->type = ET_BAD;
1224           return 1;
1225         }
1226     }
1227
1228   return 1;
1229 }
1230
1231 int
1232 gather_check_libs (void)
1233 {
1234   struct prelink_dir *dir;
1235   void *f;
1236
1237   htab_traverse (prelink_filename_htab, gather_check_lib, NULL);
1238
1239   dir = dirs;
1240   while (dir != NULL)
1241     {
1242       f = dir;
1243       dir = dir->next;
1244       free (f);
1245     }
1246
1247   dir = blacklist;
1248   while (dir != NULL)
1249     {
1250       f = dir;
1251       dir = dir->next;
1252       free (f);
1253     }
1254
1255   dirs = NULL;
1256   blacklist = NULL;
1257   return 0;
1258 }
1259
1260 int
1261 add_to_blacklist (const char *name, int deref, int onefs)
1262 {
1263   const char *canon_name;
1264   struct prelink_dir *path;
1265   size_t len;
1266   struct stat64 st;
1267
1268   if (stat64 (name, &st) < 0)
1269     {
1270       if (implicit)
1271         return 0;
1272       error (0, errno, "Could not stat %s", name);
1273       return 1;
1274     }
1275
1276   if (!S_ISDIR (st.st_mode))
1277     {
1278       struct prelink_entry *ent;
1279
1280       ent = prelink_find_entry (name, &st, 1);
1281       if (ent == NULL)
1282         return 1;
1283
1284       ent->type = ET_BAD;
1285       ent->u.explicit = 1;
1286       return 0;
1287     }
1288
1289   canon_name = prelink_canonicalize (name, NULL);
1290   if (canon_name == NULL)
1291     {
1292       if (implicit)
1293         return 0;
1294       error (0, errno, "Could not canonicalize %s", name);
1295       return 1;
1296     }
1297
1298   len = strlen (canon_name);
1299   path = malloc (sizeof (struct prelink_dir) + len + 1);
1300   if (path == NULL)
1301     {
1302       error (0, ENOMEM, "Could not record path %s", name);
1303       free ((char *) canon_name);
1304       return 1;
1305     }
1306
1307   path->next = blacklist;
1308   path->flags = 0;
1309   if (! deref) path->flags |= FTW_PHYS;
1310   if (onefs) path->flags |= FTW_MOUNT;
1311   path->dev = 0;
1312   path->len = len;
1313   strcpy (path->dir, canon_name);
1314   free ((char *) canon_name);
1315   blacklist = path;
1316   return 0;
1317 }
1318
1319 void
1320 add_blacklist_ext (const char *ext)
1321 {
1322   blacklist_ext = realloc (blacklist_ext,
1323                            (blacklist_next + 1) * sizeof (*blacklist_ext));
1324   if (blacklist_ext == NULL)
1325     error (EXIT_FAILURE, errno, "can't create blacklist extension list");
1326   if (*ext == '*' && strpbrk (ext + 1, "*?[{") == NULL)
1327     {
1328       blacklist_ext[blacklist_next].is_glob = 0;
1329       ext++;
1330     }
1331   else
1332     blacklist_ext[blacklist_next].is_glob = 1;
1333   blacklist_ext[blacklist_next].ext = strdup (ext);
1334   if (blacklist_ext[blacklist_next].ext == NULL)
1335     error (EXIT_FAILURE, errno, "can't create blacklist extension list");
1336   blacklist_ext[blacklist_next].len = strlen (ext);
1337   blacklist_next++;
1338 }
1339
1340 int
1341 blacklist_from_config (void)
1342 {
1343   struct config_line *c;
1344   int ret = 0;
1345
1346   implicit = 1;
1347   for (c = config_lines; c; c = c->next)
1348     {
1349       int deref = 0;
1350       int onefs = 0;
1351       int blacklist = 0;
1352       char *p = c->line;
1353
1354       while (*p == '-')
1355         {
1356           switch (p[1])
1357             {
1358             case 'h': deref = 1; break;
1359             case 'l': onefs = 1; break;
1360             case 'b': blacklist = 1; break;
1361             }
1362           p = p + 2 + strspn (p + 2, " \t");
1363         }
1364
1365       if (*p == '\0' || !blacklist)
1366         continue;
1367
1368       if (strchr (p, '/') == NULL)
1369         {
1370           add_blacklist_ext (p);
1371           continue;
1372         }
1373
1374       if (strpbrk (p, "*?[{") == NULL)
1375         {
1376           ret = add_to_blacklist (p, deref, onefs);
1377           if (ret)
1378             {
1379               ret = 1;
1380               break;
1381             }
1382         }
1383       else
1384         {
1385           glob_t g;
1386
1387           if (!glob (p, GLOB_BRACE | GLOB_PERIOD, NULL, &g))
1388             {
1389               size_t n;
1390
1391               for (n = 0; n < g.gl_pathc; ++n)
1392                 {
1393                   ret = add_to_blacklist (g.gl_pathv[n], deref, onefs);
1394                   if (ret)
1395                     {
1396                       ret = 1;
1397                       break;
1398                     }
1399                 }
1400
1401               globfree (&g);
1402               if (ret)
1403                 break;
1404             }
1405         }
1406     }
1407
1408   implicit = 0;
1409   return ret;
1410 }