Exemplo n.º 1
0
void
_dl_boot_bind(const long sp, long *dl_data, Elf_Dyn *dynamicp)
{
	struct elf_object  dynld;	/* Resolver data for the loader */
	AuxInfo		*auxstack;
	long		*stack;
	Elf_Dyn		*dynp;
	int		n, argc;
	char **argv, **envp;
	long loff;

	/*
	 * Scan argument and environment vectors. Find dynamic
	 * data vector put after them.
	 */
	stack = (long *)sp;
	argc = *stack++;
	argv = (char **)stack;
	envp = &argv[argc + 1];
	stack = (long *)envp;
	while (*stack++ != 0L)
		;

	/*
	 * Zero out dl_data.
	 */
	for (n = 0; n <= AUX_entry; n++)
		dl_data[n] = 0;

	/*
	 * Dig out auxiliary data set up by exec call. Move all known
	 * tags to an indexed local table for easy access.
	 */
	for (auxstack = (AuxInfo *)stack; auxstack->au_id != AUX_null;
	    auxstack++) {
		if (auxstack->au_id > AUX_entry)
			continue;
		dl_data[auxstack->au_id] = auxstack->au_v;
	}
	loff = dl_data[AUX_base];	/* XXX assumes ld.so is linked at 0x0 */

	/*
	 * We need to do 'selfreloc' in case the code weren't
	 * loaded at the address it was linked to.
	 *
	 * Scan the DYNAMIC section for the loader.
	 * Cache the data for easier access.
	 */

	dynp = (Elf_Dyn *)((long)_DYNAMIC + loff);
	_dl_memset(dynld.Dyn.info, 0, sizeof(dynld.Dyn.info));
	while (dynp != NULL && dynp->d_tag != DT_NULL) {
		if (dynp->d_tag < DT_NUM)
			dynld.Dyn.info[dynp->d_tag] = dynp->d_un.d_val;
		else if (dynp->d_tag >= DT_LOPROC &&
		    dynp->d_tag < DT_LOPROC + DT_PROCNUM)
			dynld.Dyn.info[dynp->d_tag - DT_LOPROC + DT_NUM] =
			    dynp->d_un.d_val;
		if (dynp->d_tag == DT_TEXTREL)
			dynld.dyn.textrel = 1;
		dynp++;
	}

	/*
	 * Do the 'bootstrap relocation'. This is really only needed if
	 * the code was loaded at another location than it was linked to.
	 * We don't do undefined symbols resolving (to difficult..)
	 */

	/* "relocate" dyn.X values if they represent addresses */
	{
		int i, val;
		/* must be code, not pic data */
		int table[20];

		i = 0;
		table[i++] = DT_PLTGOT;
		table[i++] = DT_HASH;
		table[i++] = DT_STRTAB;
		table[i++] = DT_SYMTAB;
		table[i++] = DT_RELA;
		table[i++] = DT_INIT;
		table[i++] = DT_FINI;
		table[i++] = DT_REL;
		table[i++] = DT_JMPREL;
		/* other processors insert their extras here */
		table[i++] = DT_NULL;
		for (i = 0; table[i] != DT_NULL; i++) {
			val = table[i];
			if (val >= DT_LOPROC && val < DT_LOPROC + DT_PROCNUM)
				val = val - DT_LOPROC + DT_NUM;
			else if (val >= DT_NUM)
				continue;
			if (dynld.Dyn.info[val] != 0)
				dynld.Dyn.info[val] += loff;
		}
	}

	{
		u_int32_t rs;
		Elf_Rel *rp;
		int	i;

		rp = (Elf_Rel *)(dynld.Dyn.info[DT_REL]);
		rs = dynld.dyn.relsz;

		for (i = 0; i < rs; i += sizeof (Elf_Rel)) {
			Elf_Addr *ra;
			const Elf_Sym *sp;

			sp = dynld.dyn.symtab;
			sp += ELF_R_SYM(rp->r_info);

			if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) {
#if 0
/* cannot printf in this function */
				_dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n");
				_dl_wrstderr("Undefined symbol: ");
				_dl_wrstderr((char *)dynld.dyn.strtab +
				    sp->st_name);
#endif
				_dl_exit(5);
			}

			ra = (Elf_Addr *)(rp->r_offset + loff);
			RELOC_REL(rp, sp, ra, loff);
			rp++;
		}
	}

	for (n = 0; n < 2; n++) {
		unsigned long rs;
		Elf_RelA *rp;
		int	i;

		switch (n) {
		case 0:
			rp = (Elf_RelA *)(dynld.Dyn.info[DT_JMPREL]);
			rs = dynld.dyn.pltrelsz;
			break;
		case 1:
			rp = (Elf_RelA *)(dynld.Dyn.info[DT_RELA]);
			rs = dynld.dyn.relasz;
			break;
		default:
			rp = NULL;
			rs = 0;
		}
		for (i = 0; i < rs; i += sizeof (Elf_RelA)) {
			Elf_Addr *ra;
			const Elf_Sym *sp;

			sp = dynld.dyn.symtab;
			sp += ELF_R_SYM(rp->r_info);
			if (ELF_R_SYM(rp->r_info) && sp->st_value == 0) {
#if 0
				_dl_wrstderr("Dynamic loader failure: self bootstrapping impossible.\n");
				_dl_wrstderr("Undefined symbol: ");
				_dl_wrstderr((char *)dynld.dyn.strtab +
				    sp->st_name);
#endif
				_dl_exit(6);
			}

			ra = (Elf_Addr *)(rp->r_offset + loff);
			RELOC_RELA(rp, sp, ra, loff, dynld.dyn.pltgot);
			rp++;
		}
	}

	RELOC_GOT(&dynld, loff);

	/*
	 * we have been fully relocated here, so most things no longer
	 * need the loff adjustment
	 */
}
Exemplo n.º 2
0
/* We are running on the process being loaded */
unsigned int __ldep(struct init_data_dl *initd)
{   
    unsigned int rsize, n;
	Elf32_Rel *rel;
    Elf32_Rela *rela;
	Elf32_Sym *sym;
	dyncache dync;
    int i;

    /******************************************************/
    /*                     LD Relocation                  */
    /******************************************************/
    /*
    We need to relocate ourselves.
    First add the offset to the dynamic section pointers.
    */
    Elf32_Dyn *dyn = (Elf32_Dyn *)(initd->ld_dynamic);
    
    for(i = 0; i < 24; i++)
        dync.data[i] = 0;
    
    i = 0;
    while(dyn[i].d_tag != DT_NULL)
    {
        if(dyn[i].d_tag < 24 || dyn[i].d_tag == 30)
        {
            switch(dyn[i].d_tag)
            {
                case DT_PLTGOT:
                case DT_HASH:
                case DT_STRTAB:
                case DT_SYMTAB:
                case DT_RELA:
                case DT_INIT:
                case DT_FINI:
                case DT_REL:
                case DT_DEBUG:
                case DT_JMPREL:
                    dync.data[dyn[i].d_tag] = (unsigned int)dyn[i].d_un.d_ptr + (unsigned int)initd->ld_start;
                    break;
                case DT_SYMBOLIC:
                    dync.data[DT_FLAGS] |= DF_SYMBOLIC;
                    break;
                case DT_FLAGS:
                    dync.data[25] |= dyn[i].d_un.d_val;
                    break;
                default:
                    dync.data[dyn[i].d_tag] = dyn[i].d_un.d_val;
            }
        }
        i++;
    }
    
    // relocate rel relocation section
	rel = (Elf32_Rel*)dync.data[DT_REL];
    rsize = dync.data[DT_RELSZ];
    
    n = 0;
    do
    {
        for (i = 0; i < rsize; i += sizeof (Elf32_Rel)) 
        {
		    sym = (Elf32_Sym*)(dync.data[DT_SYMTAB] + sizeof(Elf32_Sym) * ELF32_R_SYM(rel->r_info));
                        
		    RELOC_REL(rel, sym, (unsigned int*)(rel->r_offset + initd->ld_start), initd->ld_start);
		    rel++;
	    }
        n++;
        rel = (Elf32_Rel*)dync.data[DT_JMPREL];
	    rsize = dync.data[DT_PLTRELSZ];
    }while(n < 2 && dync.data[DT_PLTREL] == DT_REL);
    
    // relocate DT_RELA (if JMPREL is of type DT_RELA we will initialize it here)
    rela = (Elf32_Rela*)dync.data[DT_RELA];
	rsize = dync.data[DT_RELASZ];
    
    n = 0;
    do
    {
        for (i = 0; i < rsize; i += sizeof(Elf32_Rela)) 
        {
		    sym = (Elf32_Sym*)(dync.data[DT_SYMTAB] + sizeof(Elf32_Sym) * ELF32_R_SYM(rel->r_info)); // get the symbol from the table by adding it's offset
            
		    RELOC_RELA(rela, sym, (unsigned int*)(rel->r_offset + initd->ld_start), initd->ld_start);
		    rela++;
	    }
        n++;
        rela = (Elf32_Rela*)dync.data[DT_JMPREL];
	    rsize = dync.data[DT_PLTRELSZ];
    }while(n < 2 && dync.data[DT_PLTREL] == DT_RELA);
    
    __ldmain(initd, &dync);
    
    return initd->prg_start;
}