FreeBSD/libexec/rtld-elf/amd64/reloc.c
/*
 * Process the special R_X86_64_COPY relocations in the main program.  These
 * copy data from a shared object into a region in the main program's BSS
 * segment.
 *
 * Returns 0 on success, -1 on failure.
 */
Process the special R_X86_64_COPY relocations in the main program.  These
copy data from a shared object into a region in the main program's BSS
segment.

Returns 0 on success, -1 on failure.
Process the special R_X86_64_COPY relocations in the main program . These copy data from a shared object into a region in the main program ' s BSS segment . Returns 0 on success - 1 on failure .
int
do_copy_relocations(Obj_Entry *dstobj)
{
    const Elf_Rela *relalim;
    const Elf_Rela *rela;
    assert(dstobj->mainprog);	
    relalim = (const Elf_Rela *) ((caddr_t) dstobj->rela + dstobj->relasize);
    for (rela = dstobj->rela;  rela < relalim;  rela++) {
	if (ELF_R_TYPE(rela->r_info) == R_X86_64_COPY) {
	    void *dstaddr;
	    const Elf_Sym *dstsym;
	    const char *name;
	    size_t size;
	    const void *srcaddr;
	    const Elf_Sym *srcsym;
	    const Obj_Entry *srcobj, *defobj;
	    SymLook req;
	    int res;
	    dstaddr = (void *) (dstobj->relocbase + rela->r_offset);
	    dstsym = dstobj->symtab + ELF_R_SYM(rela->r_info);
	    name = dstobj->strtab + dstsym->st_name;
	    size = dstsym->st_size;
	    symlook_init(&req, name);
	    req.ventry = fetch_ventry(dstobj, ELF_R_SYM(rela->r_info));
	    req.flags = SYMLOOK_EARLY;
	    for (srcobj = globallist_next(dstobj); srcobj != NULL;
	      srcobj = globallist_next(srcobj)) {
		res = symlook_obj(&req, srcobj);
		if (res == 0) {
		    srcsym = req.sym_out;
		    defobj = req.defobj_out;
		    break;
		}
	    }
	    if (srcobj == NULL) {
		_rtld_error("Undefined symbol \"%s\" referenced from COPY"
		  " relocation in %s", name, dstobj->path);
		return -1;
	    }
	    srcaddr = (const void *) (defobj->relocbase + srcsym->st_value);
	    memcpy(dstaddr, srcaddr, size);
	}
    }
    return 0;
}
int do_copy_relocations ( Obj_Entry * dstobj ) { const Elf_Rela * relalim ; const Elf_Rela * rela ; assert ( dstobj -> mainprog ) ; relalim = ( const Elf_Rela * ) ( ( caddr_t ) dstobj -> rela + dstobj -> relasize ) ; for ( rela = dstobj -> rela ; rela < relalim ; rela ++ ) { if ( ELF_R_TYPE ( rela -> r_info ) == R_X86_64_COPY ) { void * dstaddr ; const Elf_Sym * dstsym ; const char * name ; size_t size ; const void * srcaddr ; const Elf_Sym * srcsym ; const Obj_Entry * srcobj , * defobj ; SymLook req ; int res ; dstaddr = ( void * ) ( dstobj -> relocbase + rela -> r_offset ) ; dstsym = dstobj -> symtab + ELF_R_SYM ( rela -> r_info ) ; name = dstobj -> strtab + dstsym -> st_name ; size = dstsym -> st_size ; symlook_init ( & req , name ) ; req . ventry = fetch_ventry ( dstobj , ELF_R_SYM ( rela -> r_info ) ) ; req . flags = SYMLOOK_EARLY ; for ( srcobj = globallist_next ( dstobj ) ; srcobj != NULL ; srcobj = globallist_next ( srcobj ) ) { res = symlook_obj ( & req , srcobj ) ; if ( res == 0 ) { srcsym = req . sym_out ; defobj = req . defobj_out ; break ; } } if ( srcobj == NULL ) { _rtld_error ( " \" \" " " " , name , dstobj -> path ) ; return -1 ; } srcaddr = ( const void * ) ( defobj -> relocbase + srcsym -> st_value ) ; memcpy ( dstaddr , srcaddr , size ) ; } } return 0 ; }
Process the special R_X86_64_COPY relocations in the main program.
Process the special R_X86_64_COPY relocations in the main program .
/* COPY relocations are invalid elsewhere */