Home | History | Annotate | Line # | Download | only in ld.elf_so
headers.c revision 1.68
      1  1.68   thorpej /*	$NetBSD: headers.c,v 1.68 2020/03/04 01:21:17 thorpej Exp $	 */
      2   1.1       cgd 
      3   1.1       cgd /*
      4   1.1       cgd  * Copyright 1996 John D. Polstra.
      5   1.1       cgd  * Copyright 1996 Matt Thomas <matt (at) 3am-software.com>
      6  1.17   mycroft  * Copyright 2002 Charles M. Hannum <root (at) ihack.net>
      7   1.1       cgd  * All rights reserved.
      8   1.1       cgd  *
      9   1.1       cgd  * Redistribution and use in source and binary forms, with or without
     10   1.1       cgd  * modification, are permitted provided that the following conditions
     11   1.1       cgd  * are met:
     12   1.1       cgd  * 1. Redistributions of source code must retain the above copyright
     13   1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     14   1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     15   1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     16   1.1       cgd  *    documentation and/or other materials provided with the distribution.
     17   1.1       cgd  * 3. All advertising materials mentioning features or use of this software
     18   1.1       cgd  *    must display the following acknowledgement:
     19   1.1       cgd  *      This product includes software developed by John Polstra.
     20   1.1       cgd  * 4. The name of the author may not be used to endorse or promote products
     21   1.1       cgd  *    derived from this software without specific prior written permission.
     22   1.1       cgd  *
     23   1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     24   1.1       cgd  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     25   1.1       cgd  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     26   1.1       cgd  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     27   1.1       cgd  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     28   1.1       cgd  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     29   1.1       cgd  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     30   1.1       cgd  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     31   1.1       cgd  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     32   1.1       cgd  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     33   1.1       cgd  */
     34   1.1       cgd 
     35   1.1       cgd /*
     36   1.1       cgd  * Dynamic linker for ELF.
     37   1.1       cgd  *
     38   1.1       cgd  * John Polstra <jdp (at) polstra.com>.
     39   1.1       cgd  */
     40   1.1       cgd 
     41  1.19     skrll #include <sys/cdefs.h>
     42  1.19     skrll #ifndef lint
     43  1.68   thorpej __RCSID("$NetBSD: headers.c,v 1.68 2020/03/04 01:21:17 thorpej Exp $");
     44  1.19     skrll #endif /* not lint */
     45  1.19     skrll 
     46   1.1       cgd #include <err.h>
     47   1.1       cgd #include <errno.h>
     48   1.1       cgd #include <fcntl.h>
     49   1.1       cgd #include <stdarg.h>
     50   1.1       cgd #include <stdio.h>
     51   1.1       cgd #include <stdlib.h>
     52   1.1       cgd #include <string.h>
     53   1.1       cgd #include <unistd.h>
     54   1.1       cgd #include <sys/types.h>
     55   1.1       cgd #include <sys/mman.h>
     56  1.29     joerg #include <sys/bitops.h>
     57   1.1       cgd #include <dirent.h>
     58   1.1       cgd 
     59   1.1       cgd #include "debug.h"
     60   1.1       cgd #include "rtld.h"
     61   1.1       cgd 
     62   1.1       cgd /*
     63   1.1       cgd  * Process a shared object's DYNAMIC section, and save the important
     64   1.1       cgd  * information in its Obj_Entry structure.
     65   1.1       cgd  */
     66   1.1       cgd void
     67  1.22  christos _rtld_digest_dynamic(const char *execname, Obj_Entry *obj)
     68   1.1       cgd {
     69   1.4  christos 	Elf_Dyn        *dynp;
     70   1.4  christos 	Needed_Entry  **needed_tail = &obj->needed;
     71  1.51  christos 	const Elf_Dyn  *dyn_soname = NULL;
     72   1.4  christos 	const Elf_Dyn  *dyn_rpath = NULL;
     73  1.30     joerg 	bool		use_pltrel = false;
     74  1.30     joerg 	bool		use_pltrela = false;
     75   1.8   mycroft 	Elf_Addr        relsz = 0, relasz = 0;
     76  1.13   mycroft 	Elf_Addr	pltrel = 0, pltrelsz = 0;
     77  1.58  christos #ifdef RTLD_LOADER
     78  1.10  fredette 	Elf_Addr	init = 0, fini = 0;
     79  1.58  christos #endif
     80   1.4  christos 
     81  1.49     skrll 	dbg(("headers: digesting PT_DYNAMIC at %p", obj->dynamic));
     82   1.5    kleink 	for (dynp = obj->dynamic; dynp->d_tag != DT_NULL; ++dynp) {
     83  1.49     skrll 		dbg(("  d_tag %ld at %p", (long)dynp->d_tag, dynp));
     84   1.4  christos 		switch (dynp->d_tag) {
     85   1.4  christos 
     86   1.5    kleink 		case DT_REL:
     87   1.4  christos 			obj->rel = (const Elf_Rel *)
     88   1.4  christos 			    (obj->relocbase + dynp->d_un.d_ptr);
     89   1.4  christos 			break;
     90   1.4  christos 
     91   1.5    kleink 		case DT_RELSZ:
     92   1.4  christos 			relsz = dynp->d_un.d_val;
     93   1.4  christos 			break;
     94   1.4  christos 
     95   1.5    kleink 		case DT_RELENT:
     96   1.4  christos 			assert(dynp->d_un.d_val == sizeof(Elf_Rel));
     97   1.4  christos 			break;
     98   1.4  christos 
     99   1.5    kleink 		case DT_JMPREL:
    100  1.13   mycroft 			pltrel = dynp->d_un.d_ptr;
    101   1.4  christos 			break;
    102   1.4  christos 
    103   1.5    kleink 		case DT_PLTRELSZ:
    104   1.8   mycroft 			pltrelsz = dynp->d_un.d_val;
    105   1.4  christos 			break;
    106   1.4  christos 
    107   1.5    kleink 		case DT_RELA:
    108   1.9    kleink 			obj->rela = (const Elf_Rela *)
    109   1.4  christos 			    (obj->relocbase + dynp->d_un.d_ptr);
    110   1.4  christos 			break;
    111   1.4  christos 
    112   1.5    kleink 		case DT_RELASZ:
    113   1.4  christos 			relasz = dynp->d_un.d_val;
    114   1.4  christos 			break;
    115   1.4  christos 
    116   1.5    kleink 		case DT_RELAENT:
    117   1.9    kleink 			assert(dynp->d_un.d_val == sizeof(Elf_Rela));
    118   1.4  christos 			break;
    119   1.4  christos 
    120   1.5    kleink 		case DT_PLTREL:
    121  1.30     joerg 			use_pltrel = dynp->d_un.d_val == DT_REL;
    122  1.30     joerg 			use_pltrela = dynp->d_un.d_val == DT_RELA;
    123  1.30     joerg 			assert(use_pltrel || use_pltrela);
    124   1.4  christos 			break;
    125   1.4  christos 
    126   1.5    kleink 		case DT_SYMTAB:
    127   1.4  christos 			obj->symtab = (const Elf_Sym *)
    128   1.4  christos 				(obj->relocbase + dynp->d_un.d_ptr);
    129   1.4  christos 			break;
    130   1.4  christos 
    131   1.5    kleink 		case DT_SYMENT:
    132   1.4  christos 			assert(dynp->d_un.d_val == sizeof(Elf_Sym));
    133   1.4  christos 			break;
    134   1.4  christos 
    135   1.5    kleink 		case DT_STRTAB:
    136   1.4  christos 			obj->strtab = (const char *)
    137   1.4  christos 			    (obj->relocbase + dynp->d_un.d_ptr);
    138   1.4  christos 			break;
    139   1.4  christos 
    140   1.5    kleink 		case DT_STRSZ:
    141   1.4  christos 			obj->strsize = dynp->d_un.d_val;
    142   1.4  christos 			break;
    143   1.4  christos 
    144  1.41    nonaka 		case DT_VERNEED:
    145  1.41    nonaka 			obj->verneed = (const Elf_Verneed *)
    146  1.41    nonaka 			    (obj->relocbase + dynp->d_un.d_ptr);
    147  1.41    nonaka 			break;
    148  1.41    nonaka 
    149  1.41    nonaka 		case DT_VERNEEDNUM:
    150  1.41    nonaka 			obj->verneednum = dynp->d_un.d_val;
    151  1.41    nonaka 			break;
    152  1.41    nonaka 
    153  1.41    nonaka 		case DT_VERDEF:
    154  1.41    nonaka 			obj->verdef = (const Elf_Verdef *)
    155  1.41    nonaka 			    (obj->relocbase + dynp->d_un.d_ptr);
    156  1.41    nonaka 			break;
    157  1.41    nonaka 
    158  1.41    nonaka 		case DT_VERDEFNUM:
    159  1.41    nonaka 			obj->verdefnum = dynp->d_un.d_val;
    160  1.41    nonaka 			break;
    161  1.41    nonaka 
    162  1.41    nonaka 		case DT_VERSYM:
    163  1.41    nonaka 			obj->versyms = (const Elf_Versym *)
    164  1.41    nonaka 			    (obj->relocbase + dynp->d_un.d_ptr);
    165  1.41    nonaka 			break;
    166  1.41    nonaka 
    167   1.5    kleink 		case DT_HASH:
    168   1.4  christos 			{
    169  1.66     kamil 				uint32_t nbuckets, nchains;
    170  1.31     skrll 				const Elf_Symindx *hashtab = (const Elf_Symindx *)
    171  1.31     skrll 				    (obj->relocbase + dynp->d_un.d_ptr);
    172   1.4  christos 
    173  1.29     joerg 				if (hashtab[0] > UINT32_MAX)
    174  1.66     kamil 					nbuckets = UINT32_MAX;
    175  1.29     joerg 				else
    176  1.66     kamil 					nbuckets = hashtab[0];
    177  1.66     kamil 				obj->nbuckets = nbuckets;
    178  1.66     kamil 				obj->nchains = (nchains = hashtab[1]);
    179   1.4  christos 				obj->buckets = hashtab + 2;
    180   1.4  christos 				obj->chains = obj->buckets + obj->nbuckets;
    181  1.66     kamil 
    182  1.66     kamil 				/* Validity check */
    183  1.66     kamil 				if (!obj->buckets || !nbuckets || !nchains)
    184  1.66     kamil 					continue;
    185  1.66     kamil 
    186  1.66     kamil 				obj->sysv_hash = true;
    187  1.66     kamil 
    188  1.66     kamil 				/*
    189  1.66     kamil 				 * Should really be in _rtld_relocate_objects,
    190  1.66     kamil 				 * but _rtld_symlook_obj might be used before.
    191  1.66     kamil 				 */
    192  1.66     kamil 				fast_divide32_prepare(obj->nbuckets,
    193  1.66     kamil 				    &obj->nbuckets_m,
    194  1.66     kamil 				    &obj->nbuckets_s1,
    195  1.66     kamil 				    &obj->nbuckets_s2);
    196  1.66     kamil 			}
    197  1.66     kamil 			break;
    198  1.66     kamil 
    199  1.66     kamil 		case DT_GNU_HASH:
    200  1.66     kamil 			{
    201  1.66     kamil 				uint32_t nmaskwords;
    202  1.66     kamil 				uint32_t nbuckets, symndx;
    203  1.66     kamil 				int bloom_size32;
    204  1.66     kamil 				bool nmw_power2;
    205  1.66     kamil 				const Elf_Symindx *hashtab = (const Elf_Symindx *)
    206  1.66     kamil 				    (obj->relocbase + dynp->d_un.d_ptr);
    207  1.66     kamil 
    208  1.66     kamil 				if (hashtab[0] > UINT32_MAX)
    209  1.66     kamil 					nbuckets = UINT32_MAX;
    210  1.66     kamil 				else
    211  1.66     kamil 					nbuckets = hashtab[0];
    212  1.66     kamil 				obj->nbuckets_gnu = nbuckets;
    213  1.66     kamil 
    214  1.66     kamil 				nmaskwords = hashtab[2];
    215  1.66     kamil 				bloom_size32 = nmaskwords * (ELFSIZE / 32);
    216  1.66     kamil 
    217  1.67     kamil 				obj->buckets_gnu = (const uint32_t *)(hashtab + 4 + bloom_size32);
    218  1.66     kamil 
    219  1.66     kamil 				nmw_power2 = powerof2(nmaskwords);
    220  1.66     kamil 
    221  1.66     kamil 				/* Validity check */
    222  1.66     kamil 				if (!nmw_power2 || !nbuckets || !obj->buckets_gnu)
    223  1.66     kamil 					continue;
    224  1.66     kamil 
    225  1.66     kamil 				obj->gnu_hash = true;
    226  1.66     kamil 
    227  1.66     kamil 				obj->mask_bm_gnu = nmaskwords - 1;
    228  1.66     kamil 				obj->symndx_gnu = (symndx = hashtab[1]);
    229  1.66     kamil 				obj->shift2_gnu = hashtab[3];
    230  1.66     kamil 				obj->bloom_gnu = (const Elf_Addr *)(hashtab + 4);
    231  1.66     kamil 				obj->chains_gnu = obj->buckets_gnu + nbuckets - symndx;
    232  1.66     kamil 
    233  1.29     joerg 				/*
    234  1.29     joerg 				 * Should really be in _rtld_relocate_objects,
    235  1.29     joerg 				 * but _rtld_symlook_obj might be used before.
    236  1.29     joerg 				 */
    237  1.66     kamil 				fast_divide32_prepare(nbuckets,
    238  1.66     kamil 				    &obj->nbuckets_m_gnu,
    239  1.66     kamil 				    &obj->nbuckets_s1_gnu,
    240  1.66     kamil 				    &obj->nbuckets_s2_gnu);
    241  1.66     kamil 
    242  1.66     kamil 				dbg(("found GNU Hash: buckets=%p "
    243  1.66     kamil 				     "nbuckets=%lu chains=%p nchains=%u "
    244  1.66     kamil 				     "bloom=%p mask_bm=%u shift2=%u "
    245  1.66     kamil 				     "symndx=%u",
    246  1.66     kamil 				    obj->buckets_gnu, obj->nbuckets_gnu,
    247  1.66     kamil 				    obj->chains_gnu, obj->nchains_gnu,
    248  1.66     kamil 				    obj->bloom_gnu, obj->mask_bm_gnu,
    249  1.66     kamil 				    obj->shift2_gnu, obj->symndx_gnu));
    250   1.4  christos 			}
    251   1.4  christos 			break;
    252   1.4  christos 
    253   1.5    kleink 		case DT_NEEDED:
    254   1.4  christos 			{
    255   1.4  christos 				Needed_Entry *nep = NEW(Needed_Entry);
    256   1.4  christos 
    257   1.4  christos 				nep->name = dynp->d_un.d_val;
    258   1.4  christos 				nep->obj = NULL;
    259   1.4  christos 				nep->next = NULL;
    260   1.4  christos 
    261   1.4  christos 				*needed_tail = nep;
    262   1.4  christos 				needed_tail = &nep->next;
    263   1.4  christos 			}
    264   1.4  christos 			break;
    265   1.4  christos 
    266   1.5    kleink 		case DT_PLTGOT:
    267   1.4  christos 			obj->pltgot = (Elf_Addr *)
    268   1.4  christos 			    (obj->relocbase + dynp->d_un.d_ptr);
    269   1.4  christos 			break;
    270   1.4  christos 
    271   1.5    kleink 		case DT_TEXTREL:
    272   1.4  christos 			obj->textrel = true;
    273   1.4  christos 			break;
    274   1.4  christos 
    275   1.5    kleink 		case DT_SYMBOLIC:
    276   1.4  christos 			obj->symbolic = true;
    277   1.4  christos 			break;
    278   1.4  christos 
    279   1.5    kleink 		case DT_RPATH:
    280  1.65    martin 		case DT_RUNPATH:
    281   1.4  christos 			/*
    282   1.4  christos 		         * We have to wait until later to process this, because
    283   1.4  christos 			 * we might not have gotten the address of the string
    284   1.4  christos 			 * table yet.
    285   1.4  christos 		         */
    286   1.4  christos 			dyn_rpath = dynp;
    287   1.4  christos 			break;
    288   1.4  christos 
    289   1.5    kleink 		case DT_SONAME:
    290  1.51  christos 			dyn_soname = dynp;
    291   1.4  christos 			break;
    292   1.4  christos 
    293   1.5    kleink 		case DT_INIT:
    294  1.58  christos #ifdef RTLD_LOADER
    295  1.10  fredette 			init = dynp->d_un.d_ptr;
    296  1.58  christos #endif
    297   1.4  christos 			break;
    298   1.4  christos 
    299  1.43      matt #ifdef HAVE_INITFINI_ARRAY
    300  1.43      matt 		case DT_INIT_ARRAY:
    301  1.59     joerg 			obj->init_array =
    302  1.59     joerg 			    (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
    303  1.49     skrll 			dbg(("headers: DT_INIT_ARRAY at %p",
    304  1.49     skrll 			    obj->init_array));
    305  1.43      matt 			break;
    306  1.43      matt 
    307  1.43      matt 		case DT_INIT_ARRAYSZ:
    308  1.43      matt 			obj->init_arraysz = dynp->d_un.d_val / sizeof(fptr_t);
    309  1.49     skrll 			dbg(("headers: DT_INIT_ARRAYZ %zu",
    310  1.49     skrll 			    obj->init_arraysz));
    311  1.43      matt 			break;
    312  1.43      matt #endif
    313  1.43      matt 
    314   1.5    kleink 		case DT_FINI:
    315  1.58  christos #ifdef RTLD_LOADER
    316  1.10  fredette 			fini = dynp->d_un.d_ptr;
    317  1.58  christos #endif
    318   1.4  christos 			break;
    319   1.1       cgd 
    320  1.43      matt #ifdef HAVE_INITFINI_ARRAY
    321  1.43      matt 		case DT_FINI_ARRAY:
    322  1.43      matt 			obj->fini_array =
    323  1.55     joerg 			    (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
    324  1.49     skrll 			dbg(("headers: DT_FINI_ARRAY at %p",
    325  1.49     skrll 			    obj->fini_array));
    326  1.43      matt 			break;
    327  1.43      matt 
    328  1.43      matt 		case DT_FINI_ARRAYSZ:
    329  1.50     skrll 			obj->fini_arraysz = dynp->d_un.d_val / sizeof(fptr_t);
    330  1.49     skrll 			dbg(("headers: DT_FINI_ARRAYZ %zu",
    331  1.49     skrll 			    obj->fini_arraysz));
    332  1.43      matt 			break;
    333  1.43      matt #endif
    334  1.43      matt 
    335  1.20    simonb 		/*
    336  1.20    simonb 		 * Don't process DT_DEBUG on MIPS as the dynamic section
    337  1.20    simonb 		 * is mapped read-only. DT_MIPS_RLD_MAP is used instead.
    338  1.20    simonb 		 * XXX: n32/n64 may use DT_DEBUG, not sure yet.
    339  1.20    simonb 		 */
    340  1.20    simonb #ifndef __mips__
    341   1.5    kleink 		case DT_DEBUG:
    342   1.1       cgd #ifdef RTLD_LOADER
    343   1.4  christos 			dynp->d_un.d_ptr = (Elf_Addr)&_rtld_debug;
    344   1.1       cgd #endif
    345   1.4  christos 			break;
    346  1.20    simonb #endif
    347   1.2    mhitch 
    348  1.14   mycroft #ifdef __mips__
    349   1.4  christos 		case DT_MIPS_LOCAL_GOTNO:
    350   1.4  christos 			obj->local_gotno = dynp->d_un.d_val;
    351   1.4  christos 			break;
    352   1.4  christos 
    353   1.4  christos 		case DT_MIPS_SYMTABNO:
    354   1.4  christos 			obj->symtabno = dynp->d_un.d_val;
    355   1.4  christos 			break;
    356   1.4  christos 
    357   1.4  christos 		case DT_MIPS_GOTSYM:
    358   1.4  christos 			obj->gotsym = dynp->d_un.d_val;
    359   1.4  christos 			break;
    360   1.2    mhitch 
    361   1.4  christos 		case DT_MIPS_RLD_MAP:
    362   1.2    mhitch #ifdef RTLD_LOADER
    363   1.4  christos 			*((Elf_Addr *)(dynp->d_un.d_ptr)) = (Elf_Addr)
    364   1.4  christos 			    &_rtld_debug;
    365   1.2    mhitch #endif
    366   1.4  christos 			break;
    367   1.2    mhitch #endif
    368  1.39      matt #ifdef __powerpc__
    369  1.53      matt #ifdef _LP64
    370  1.53      matt 		case DT_PPC64_GLINK:
    371  1.54      matt 			obj->glink = (Elf_Addr)(uintptr_t)obj->relocbase + dynp->d_un.d_ptr;
    372  1.53      matt 			break;
    373  1.53      matt #else
    374  1.39      matt 		case DT_PPC_GOT:
    375  1.39      matt 			obj->gotptr = (Elf_Addr *)(obj->relocbase + dynp->d_un.d_ptr);
    376  1.39      matt 			break;
    377  1.39      matt #endif
    378  1.53      matt #endif
    379  1.23        ad 		case DT_FLAGS_1:
    380  1.38     skrll 			obj->z_now =
    381  1.63  christos 			    ((dynp->d_un.d_val & DF_1_NOW) != 0);
    382  1.38     skrll 			obj->z_nodelete =
    383  1.38     skrll 			    ((dynp->d_un.d_val & DF_1_NODELETE) != 0);
    384  1.38     skrll 			obj->z_initfirst =
    385  1.23        ad 			    ((dynp->d_un.d_val & DF_1_INITFIRST) != 0);
    386  1.38     skrll 			obj->z_noopen =
    387  1.38     skrll 			    ((dynp->d_un.d_val & DF_1_NOOPEN) != 0);
    388  1.23        ad 			break;
    389   1.4  christos 		}
    390   1.1       cgd 	}
    391   1.1       cgd 
    392  1.28     lukem 	obj->rellim = (const Elf_Rel *)((const uint8_t *)obj->rel + relsz);
    393  1.28     lukem 	obj->relalim = (const Elf_Rela *)((const uint8_t *)obj->rela + relasz);
    394  1.30     joerg 	if (use_pltrel) {
    395  1.13   mycroft 		obj->pltrel = (const Elf_Rel *)(obj->relocbase + pltrel);
    396  1.13   mycroft 		obj->pltrellim = (const Elf_Rel *)(obj->relocbase + pltrel + pltrelsz);
    397  1.13   mycroft 		obj->pltrelalim = 0;
    398  1.13   mycroft 		/* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
    399  1.13   mycroft 		   Trim rel(a)lim to save time later. */
    400  1.13   mycroft 		if (obj->rellim && obj->pltrel &&
    401  1.13   mycroft 		    obj->rellim > obj->pltrel &&
    402  1.13   mycroft 		    obj->rellim <= obj->pltrellim)
    403  1.11   mycroft 			obj->rellim = obj->pltrel;
    404  1.30     joerg 	} else if (use_pltrela) {
    405  1.13   mycroft 		obj->pltrela = (const Elf_Rela *)(obj->relocbase + pltrel);
    406  1.13   mycroft 		obj->pltrellim = 0;
    407  1.13   mycroft 		obj->pltrelalim = (const Elf_Rela *)(obj->relocbase + pltrel + pltrelsz);
    408  1.13   mycroft 		/* On PPC and SPARC, at least, REL(A)SZ may include JMPREL.
    409  1.13   mycroft 		   Trim rel(a)lim to save time later. */
    410  1.13   mycroft 		if (obj->relalim && obj->pltrela &&
    411  1.13   mycroft 		    obj->relalim > obj->pltrela &&
    412  1.13   mycroft 		    obj->relalim <= obj->pltrelalim)
    413  1.11   mycroft 			obj->relalim = obj->pltrela;
    414   1.8   mycroft 	}
    415  1.10  fredette 
    416  1.66     kamil 	/* If the ELF Hash is present, "nchains" is the same in both hashes. */
    417  1.66     kamil 	if (!obj->sysv_hash && obj->gnu_hash) {
    418  1.66     kamil 		uint_fast32_t i, nbucket, symndx;
    419  1.66     kamil 
    420  1.66     kamil 		/* Otherwise, count the entries from the GNU Hash chain. */
    421  1.66     kamil 		nbucket = obj->nbuckets_gnu;
    422  1.66     kamil 		symndx = obj->symndx_gnu;
    423  1.66     kamil 
    424  1.66     kamil 		for (i = 0; i < nbucket; i++) {
    425  1.66     kamil 			Elf_Word bkt = obj->buckets_gnu[i];
    426  1.66     kamil 			if (bkt == 0)
    427  1.66     kamil 				continue;
    428  1.66     kamil 			const uint32_t *hashval = &obj->chains_gnu[bkt];
    429  1.66     kamil 			do {
    430  1.66     kamil 				symndx++;
    431  1.66     kamil 			} while ((*hashval++ & 1U) == 0);
    432  1.66     kamil 		}
    433  1.66     kamil 		obj->nchains_gnu = (uint32_t)symndx;
    434  1.66     kamil 	}
    435  1.66     kamil 
    436  1.57     joerg #ifdef RTLD_LOADER
    437  1.10  fredette 	if (init != 0)
    438  1.57     joerg 		obj->init = (Elf_Addr) obj->relocbase + init;
    439  1.10  fredette 	if (fini != 0)
    440  1.57     joerg 		obj->fini = (Elf_Addr) obj->relocbase + fini;
    441  1.57     joerg #endif
    442   1.4  christos 
    443   1.4  christos 	if (dyn_rpath != NULL) {
    444  1.22  christos 		_rtld_add_paths(execname, &obj->rpaths, obj->strtab +
    445  1.12   mycroft 		    dyn_rpath->d_un.d_val);
    446   1.4  christos 	}
    447  1.51  christos 	if (dyn_soname != NULL) {
    448  1.51  christos 		_rtld_object_add_name(obj, obj->strtab +
    449  1.51  christos 		    dyn_soname->d_un.d_val);
    450  1.51  christos 	}
    451   1.1       cgd }
    452   1.1       cgd 
    453   1.1       cgd /*
    454   1.1       cgd  * Process a shared object's program header.  This is used only for the
    455   1.1       cgd  * main program, when the kernel has already loaded the main program
    456   1.1       cgd  * into memory before calling the dynamic linker.  It creates and
    457   1.1       cgd  * returns an Obj_Entry structure.
    458   1.1       cgd  */
    459   1.1       cgd Obj_Entry *
    460  1.18     skrll _rtld_digest_phdr(const Elf_Phdr *phdr, int phnum, caddr_t entry)
    461   1.1       cgd {
    462   1.6   mycroft 	Obj_Entry      *obj;
    463   1.4  christos 	const Elf_Phdr *phlimit = phdr + phnum;
    464   1.4  christos 	const Elf_Phdr *ph;
    465  1.62     joerg 	bool            first_seg = true;
    466  1.62     joerg 	Elf_Addr        vaddr;
    467  1.62     joerg 	size_t          size;
    468   1.4  christos 
    469   1.6   mycroft 	obj = _rtld_obj_new();
    470  1.36     skrll 
    471  1.36     skrll 	for (ph = phdr; ph < phlimit; ++ph) {
    472  1.36     skrll 		if (ph->p_type != PT_PHDR)
    473  1.36     skrll 			continue;
    474  1.50     skrll 
    475  1.60     joerg 		obj->relocbase = (caddr_t)((uintptr_t)phdr - (uintptr_t)ph->p_vaddr);
    476  1.60     joerg 		obj->phdr = phdr; /* Equivalent to relocbase + p_vaddr. */
    477  1.46      matt 		obj->phsize = ph->p_memsz;
    478  1.49     skrll 		dbg(("headers: phdr %p (%p) phsize %zu relocbase %p",
    479  1.49     skrll 		    obj->phdr, phdr, obj->phsize, obj->relocbase));
    480  1.36     skrll 		break;
    481  1.36     skrll 	}
    482  1.50     skrll 
    483   1.4  christos 	for (ph = phdr; ph < phlimit; ++ph) {
    484  1.37     skrll 		vaddr = (Elf_Addr)(uintptr_t)(obj->relocbase + ph->p_vaddr);
    485   1.4  christos 		switch (ph->p_type) {
    486   1.4  christos 
    487   1.6   mycroft 		case PT_INTERP:
    488  1.27       mrg 			obj->interp = (const char *)(uintptr_t)vaddr;
    489  1.52     skrll 			dbg(("headers: %s %p phsize %" PRImemsz,
    490  1.49     skrll 			    "PT_INTERP", (void *)(uintptr_t)vaddr,
    491  1.49     skrll 			     ph->p_memsz));
    492   1.4  christos 			break;
    493   1.4  christos 
    494   1.5    kleink 		case PT_LOAD:
    495  1.62     joerg 			size = round_up(vaddr + ph->p_memsz) - obj->vaddrbase;
    496  1.62     joerg 			if (first_seg) {	/* First load segment */
    497  1.24  christos 				obj->vaddrbase = round_down(vaddr);
    498  1.27       mrg 				obj->mapbase = (caddr_t)(uintptr_t)obj->vaddrbase;
    499  1.62     joerg 				obj->textsize = size;
    500  1.62     joerg 				obj->mapsize = size;
    501  1.62     joerg 				first_seg = false;
    502   1.4  christos 			} else {		/* Last load segment */
    503  1.62     joerg 				obj->mapsize = MAX(obj->mapsize, size);
    504   1.4  christos 			}
    505  1.52     skrll 			dbg(("headers: %s %p phsize %" PRImemsz,
    506  1.49     skrll 			    "PT_LOAD", (void *)(uintptr_t)vaddr,
    507  1.49     skrll 			     ph->p_memsz));
    508   1.4  christos 			break;
    509   1.4  christos 
    510   1.5    kleink 		case PT_DYNAMIC:
    511  1.27       mrg 			obj->dynamic = (Elf_Dyn *)(uintptr_t)vaddr;
    512  1.52     skrll 			dbg(("headers: %s %p phsize %" PRImemsz,
    513  1.49     skrll 			    "PT_DYNAMIC", (void *)(uintptr_t)vaddr,
    514  1.49     skrll 			     ph->p_memsz));
    515   1.4  christos 			break;
    516  1.40     joerg 
    517  1.61  christos #ifdef GNU_RELRO
    518  1.61  christos 		case PT_GNU_RELRO:
    519  1.68   thorpej 			/* rounding happens later. */
    520  1.68   thorpej 			obj->relro_page = obj->relocbase + ph->p_vaddr;
    521  1.68   thorpej 			obj->relro_size = ph->p_memsz;
    522  1.61  christos 			dbg(("headers: %s %p phsize %" PRImemsz,
    523  1.61  christos 			    "PT_GNU_RELRO", (void *)(uintptr_t)vaddr,
    524  1.61  christos 			     ph->p_memsz));
    525  1.61  christos 			break;
    526  1.61  christos #endif
    527  1.61  christos 
    528  1.40     joerg #if defined(__HAVE_TLS_VARIANT_I) || defined(__HAVE_TLS_VARIANT_II)
    529  1.40     joerg 		case PT_TLS:
    530  1.40     joerg 			obj->tlsindex = 1;
    531  1.40     joerg 			obj->tlssize = ph->p_memsz;
    532  1.40     joerg 			obj->tlsalign = ph->p_align;
    533  1.40     joerg 			obj->tlsinitsize = ph->p_filesz;
    534  1.64     joerg 			obj->tlsinit = (void *)(obj->relocbase +
    535  1.64     joerg 			    (uintptr_t)ph->p_vaddr);
    536  1.52     skrll 			dbg(("headers: %s %p phsize %" PRImemsz,
    537  1.49     skrll 			    "PT_TLS", (void *)(uintptr_t)vaddr,
    538  1.49     skrll 			     ph->p_memsz));
    539  1.40     joerg 			break;
    540  1.40     joerg #endif
    541  1.44      matt #ifdef __ARM_EABI__
    542  1.44      matt 		case PT_ARM_EXIDX:
    543  1.44      matt 			obj->exidx_start = (void *)(uintptr_t)vaddr;
    544  1.44      matt 			obj->exidx_sz = ph->p_memsz;
    545  1.52     skrll 			dbg(("headers: %s %p phsize %" PRImemsz,
    546  1.49     skrll 			    "PT_ARM_EXIDX", (void *)(uintptr_t)vaddr,
    547  1.49     skrll 			     ph->p_memsz));
    548  1.44      matt 			break;
    549  1.44      matt #endif
    550   1.4  christos 		}
    551   1.1       cgd 	}
    552   1.1       cgd 
    553   1.4  christos 	obj->entry = entry;
    554   1.4  christos 	return obj;
    555   1.1       cgd }
    556