0, 2);
0, 2, 0);
_dl_md_reloc(elf_object_t *object, int rel, int relasz){	long	i;	long	numrela;	long	fails = 0;	Elf_Addr loff;	Elf_RelA *relas;	struct load_list *llist;	loff = object->load_offs;	numrela = object->Dyn.info[relasz] / sizeof(Elf64_Rela);	relas = (Elf64_Rela *)(object->Dyn.info[rel]);	if (relas == NULL)		return(0);	/*	 * unprotect some segments if we need it.	 */	if ((rel == DT_REL || rel == DT_RELA)) {		for (llist = object->load_list; llist != NULL; llist = llist->next) {			if (!(llist->prot & PROT_WRITE))				_dl_mprotect(llist->start, llist->size,				    llist->prot|PROT_WRITE);		}	}	for (i = 0; i < numrela; i++, relas++) {		Elf_Addr *where, value, ooff, mask;		Elf_Word type;		const Elf_Sym *sym, *this;		const char *symn;		type = ELF_R_TYPE(relas->r_info);		if (type == R_TYPE(NONE))			continue;		if (type == R_TYPE(JMP_SLOT) && rel != DT_JMPREL)			continue;		where = (Elf_Addr *)(relas->r_offset + loff);		if (RELOC_USE_ADDEND(type))			value = relas->r_addend;		else			value = 0;		sym = NULL;		symn = NULL;		if (RELOC_RESOLVE_SYMBOL(type)) {			sym = object->dyn.symtab;			sym += ELF_R_SYM(relas->r_info);			symn = object->dyn.strtab + sym->st_name;			if (sym->st_shndx != SHN_UNDEF &&			    ELF_ST_BIND(sym->st_info) == STB_LOCAL) {				value += loff;			} else {				this = NULL;				ooff = _dl_find_symbol(symn, _dl_objects,				    &this, 0, 1);				if (this == NULL) {resolve_failed:					_dl_printf("%s: %s: can't resolve "					    "reference '%s'\n",					    _dl_progname, object->load_name,					    symn);					fails++;					continue;				}				value += (Elf_Addr)(ooff + this->st_value);#ifdef notyet/* * XXX Hmm, we should change the API of _dl_find_symbol and do this in there, * XXX or maybe make a wrapper. */				if (this->st_size != sym->st_size &&				    sym->st_size != 0) {					_dl_printf("%s: %s : WARNING: "					    "symbol(%s) size mismatch ",					    _dl_progname, object->load_name,					    symn);					_dl_printf("relink your program\n");				}#endif			}		}		if (type == R_TYPE(JMP_SLOT)) {			_dl_reloc_plt((Elf_Word *)where, value, relas);			continue;		}		if (type == R_TYPE(COPY)) {			void *dstaddr = where;			const void *srcaddr;			const Elf_Sym *dstsym = sym, *srcsym = NULL;			size_t size = dstsym->st_size;			Elf_Addr soff;			soff = _dl_find_symbol(symn, object->next, &srcsym,				0, 2);			if (srcsym == NULL)				goto resolve_failed;			srcaddr = (void *)(soff + srcsym->st_value);			_dl_bcopy(srcaddr, dstaddr, size);			continue;		}		if (RELOC_PC_RELATIVE(type))			value -= (Elf_Addr)where;		if (RELOC_BASE_RELATIVE(type))			value += loff;		mask = RELOC_VALUE_BITMASK(type);		value >>= RELOC_VALUE_RIGHTSHIFT(type);		value &= mask;		if (RELOC_UNALIGNED(type)) {			/* Handle unaligned relocations. */			Elf_Addr tmp = 0;			char *ptr = (char *)where;			int i, size = RELOC_TARGET_SIZE(type)/8;			/* Read it in one byte at a time. */			for (i=0; i<size; i++)				tmp = (tmp << 8) | ptr[i];			tmp &= ~mask;			tmp |= value;			/* Write it back out. */			for (i=0; i<size; i++)				ptr[i] = ((tmp >> (8*i)) & 0xff);		} else if (RELOC_TARGET_SIZE(type) > 32) {			*where &= ~mask;			*where |= value;		} else {			Elf32_Addr *where32 = (Elf32_Addr *)where;			*where32 &= ~mask;			*where32 |= value;		}	}	/* reprotect the unprotected segments */	if ((rel == DT_REL || rel == DT_RELA)) {		for (llist = object->load_list; llist != NULL; llist = llist->next) {			if (!(llist->prot & PROT_WRITE))				_dl_mprotect(llist->start, llist->size,				    llist->prot);		}	}	return (fails);}