xref: /titanic_52/usr/src/cmd/sgs/rtld.4.x/rtld.4.x.c (revision 0eb822a1c0c2bea495647510b75f77f0e57633eb)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Binary compatibility ld.so.  Intercepts the reference of a pre-SVR4
27  * SunOS executable to the dynamic linker, and then redirects to the
28  * "real" post-SVR4 SunOS ld.so.
29  */
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 /*
33  * Import data structures (N.B.: from 5.x).
34  */
35 #include <sys/types.h>
36 #include <sys/mman.h>
37 #include <sys/fcntl.h>
38 #include <sys/stat.h>
39 #include <sys/sysconfig.h>
40 #include <sys/auxv.h>
41 #include <sys/archsystm.h>
42 #include <elf.h>
43 #include <link.h>
44 
45 /*
46  * Relocation manifest constants and macros.
47  */
48 #define	ALIGN(x, a)		((int)(x) & ~((int)(a) - 1))
49 #define	ROUND(x, a)		(((int)(x) + ((int)(a) - 1)) & \
50 				    ~((int)(a) - 1))
51 #define	DYNAMIC_VERSION2	2
52 #define	RELOC_SIZE		(sizeof (struct relocation_info))
53 #define	RELOCOFF(x)		(x)->v2->ld_rel
54 #define	MASK(n)			((1<<(n))-1)
55 #define	IN_RANGE(v, n)		((-(1<<((n)-1))) <= (v) && (v) < (1<<((n)-1)))
56 
57 void	aout_reloc_write();
58 
59 /*
60  * 4.x SunOS Dynamic Link Editor public definitions (much derived from
61  * SunOS 4.x <link.h>.)
62  */
63 
64 /*
65  * Dynamic linking information.  With the exception of
66  * ld_loaded (determined at execution time) and ld_stab_hash (a special
67  * case of relocation handled at execution time), the values in this
68  * structure reflect offsets from the containing link_dynamic structure.
69  */
70 struct link_dynamic_1 {
71 	struct	link_map *ld_loaded;	/* list of loaded objects */
72 	long	ld_need;		/* list of needed objects */
73 	long	ld_rules;		/* search rules for library objects */
74 	long	ld_got;			/* global offset table */
75 	long	ld_plt;			/* procedure linkage table */
76 	long	ld_rel;			/* relocation table */
77 	long	ld_hash;		/* symbol hash table */
78 	long	ld_stab;		/* symbol table itself */
79 	long	(*ld_stab_hash)();	/* "pointer" to symbol hash function */
80 	long	ld_buckets;		/* number of hash buckets */
81 	long	ld_symbols;		/* symbol strings */
82 	long	ld_symb_size;		/* size of symbol strings */
83 	long	ld_text;		/* size of text area */
84 };
85 
86 struct link_dynamic_2 {
87 	struct	link_map *ld_loaded;	/* list of loaded objects */
88 	long	ld_need;		/* list of needed objects */
89 	long	ld_rules;		/* search rules for library objects */
90 	long	ld_got;			/* global offset table */
91 	long	ld_plt;			/* procedure linkage table */
92 	long	ld_rel;			/* relocation table */
93 	long	ld_hash;		/* symbol hash table */
94 	long	ld_stab;		/* symbol table itself */
95 	long	(*ld_stab_hash)();	/* "pointer" to symbol hash function */
96 	long	ld_buckets;		/* number of hash buckets */
97 	long	ld_symbols;		/* symbol strings */
98 	long	ld_symb_size;		/* size of symbol strings */
99 	long	ld_text;		/* size of text area */
100 	long	ld_plt_sz;		/* size of procedure linkage table */
101 };
102 
103 /*
104  * Debugger interface structure.
105  */
106 struct 	ld_debug {
107 	int	ldd_version;		/* version # of interface */
108 	int	ldd_in_debugger;	/* a debugger is running us */
109 	int	ldd_sym_loaded;		/* we loaded some symbols */
110 	char    *ldd_bp_addr;		/* place for ld-generated bpt */
111 	int	ldd_bp_inst;		/* instruction which was there */
112 	struct rtc_symb *ldd_cp;	/* commons we built */
113 };
114 
115 /*
116  * Structure associated with each object which may be or which requires
117  * execution-time link editing.  Used by the run-time linkage editor to
118  * identify needed objects and symbol definitions and references.
119  */
120 struct	link_dynamic {
121 	int	ld_version;
122 	struct 	ld_debug *ldd;
123 	union {
124 		struct link_dynamic_1 *ld_1;
125 		struct link_dynamic_2 *ld_2;
126 	} ld_un;
127 };
128 
129 struct 	old_link_dynamic {
130 	int	ld_version;		/* version # of this structure */
131 	union {
132 		struct link_dynamic_1 ld_1;
133 	} ld_un;
134 
135 	int	in_debugging;
136 	int	sym_loaded;
137 	char    *bp_addr;
138 	int	bp_inst;
139 	struct rtc_symb *cp; 		/* pointer to an array of runtime */
140 					/* allocated common symbols. */
141 };
142 
143 #define	v2	ld_un.ld_2		/* short hands */
144 #define	v1	ld_un.ld_1
145 
146 /*
147  * SunOS 4.x SPARC relocation types and relocation record.  Note that
148  * these, among other things, make this program not portable to things
149  * other than SPARC.
150  */
151 enum reloc_type {
152 	RELOC_8, RELOC_16, RELOC_32,	/* simplest relocs */
153 	RELOC_DISP8, RELOC_DISP16, RELOC_DISP32,
154 					/* Disp's (pc-rel) */
155 	RELOC_WDISP30, RELOC_WDISP22,	/* SR word disp's */
156 	RELOC_HI22, RELOC_22,		/* SR 22-bit relocs */
157 	RELOC_13, RELOC_LO10,		/* SR 13&10-bit relocs */
158 	RELOC_SFA_BASE, RELOC_SFA_OFF13, /* SR S.F.A. relocs */
159 	RELOC_BASE10, RELOC_BASE13, RELOC_BASE22,
160 					/* PIC GOT references */
161 	RELOC_PC10, RELOC_PC22,		/* PIC reference to GOT */
162 	RELOC_JMP_TBL,			/* PIC call */
163 	RELOC_SEGOFF16,			/* .so offset-in-segment */
164 	RELOC_GLOB_DAT, RELOC_JMP_SLOT, RELOC_RELATIVE,
165 					/* ld.so relocation types */
166 };
167 
168 struct relocation_info {
169 	unsigned long int r_address;	/* relocation addr */
170 	unsigned int	r_index   :24;	/* segment index or symbol index */
171 	unsigned int	r_extern  : 1;	/* if F, r_index==SEG#; if T, SYM idx */
172 	int			  : 2;	/* <unused> */
173 	enum reloc_type r_type    : 5;	/* type of relocation to perform */
174 	long int	r_addend;	/* addend for relocation value */
175 };
176 
177 /*
178  * Size of relocations.
179  */
180 #define	GETRELSZ(x)	\
181 	(x->ld_version < 2 ? \
182 	((struct old_link_dynamic *)x)->v1.ld_hash - \
183 		((struct old_link_dynamic *)x)->v1.ld_rel : \
184 	(x)->v2->ld_hash - (x)->v2->ld_rel)
185 
186 /*
187  * Interface between crt0 & ld.so.
188  */
189 struct crt_i1 {
190 	int	crt_baseaddr;		/* Address ld.so is at */
191 	int	crt_dzfd;		/* /dev/zero file descriptor */
192 	int	crt_rlfd;		/* ld.so file descriptor */
193 	struct	link_dynamic *crt_udp;	/* "main_" dynamic */
194 	char	**crt_ep;		/* environment strings */
195 	caddr_t	crt_breakp;		/* place to put initial breakpoint */
196 };
197 
198 /*
199  * Structure we provide to ELF ld.so upon entry.
200  */
201 Elf32_Boot	eb[EB_MAX];
202 
203 /*
204  * Global data.
205  */
206 char *program_name;			/* used in messages */
207 
208 /*
209  * 4.0 ld.so main entry point.
210  */
211 rtld(version, ip, dp, argp)
212 	int version;			/* interface version */
213 	struct crt_i1 *ip;		/* interface passed from program */
214 	register struct link_dynamic *dp; /* ld.so dynamic pointer */
215 	caddr_t	argp;			/* pointer to begining of args */
216 {
217 	char *ldso;			/* name of what we really want to be */
218 	int i, p;			/* working */
219 	int r;				/* working (# of *our* relocations */
220 	int page_size = 0;		/* size of a page */
221 	struct relocation_info *rp;	/* working pointer to our relocs */
222 	int fd;				/* fd assigned to ld.so */
223 	Elf32_Ehdr *ehdr;		/* ELF header of ld.so */
224 	Elf32_Phdr *phdr;		/* first Phdr in file */
225 	Elf32_Phdr *pptr;		/* working Phdr */
226 	Elf32_Phdr *lph;		/* last loadable Phdr */
227 	Elf32_Phdr *fph = 0;		/* first loadable Phdr */
228 	caddr_t maddr;			/* pointer to mapping claim */
229 	Elf32_Off mlen;			/* total mapping claim */
230 	caddr_t faddr;			/* first program mapping of ld.so */
231 	Elf32_Off foff;			/* file offset for segment mapping */
232 	Elf32_Off flen;			/* file length for segment mapping */
233 	caddr_t addr;			/* working mapping address */
234 	caddr_t zaddr;			/* /dev/zero working mapping addr */
235 	Elf32_Boot *ebp;		/* communication with ld.so */
236 	struct stat sb;			/* stat buffer for sizing */
237 	auxv_t *ap;			/* working aux pointer */
238 	void (*	wrt)();			/* address of write/iflush routine */
239 
240 	/*
241 	 * ld.so must itself be relocated, take care of this now.
242 	 * We can not refer to global data before this step is
243 	 * complete.  Perform the relocation by stepping over all
244 	 * entries in the relocation table and turn them into
245 	 * absolute addresses.  Note that, in order to avoid invoking
246 	 * as yet unrelocated items, we perform the relocation count
247 	 * by counting rather than risk invoking subroutine calls
248 	 * to intrinsic .div or .mul routines.  Note also that we
249 	 * assume that there are no symbolic relocations to be
250 	 * performed here.
251 	 */
252 	dp->v2 = (struct link_dynamic_2 *)
253 	    ((caddr_t)dp->v2 + ip->crt_baseaddr);
254 	r = 0;
255 	i = GETRELSZ(dp);
256 	while (i != 0) {
257 		i -= RELOC_SIZE;
258 		r++;
259 	}
260 	rp = (struct relocation_info *)(RELOCOFF(dp) +
261 	    (dp->ld_version < DYNAMIC_VERSION2 ?
262 	    (int)dp : ip->crt_baseaddr));
263 
264 	/*
265 	 * Determine the location of the routine that will write the relocation.
266 	 * This hasn't yet been relocated so determine the real address using
267 	 * our base address.
268 	 */
269 	wrt = (void (*)())((caddr_t)aout_reloc_write + ip->crt_baseaddr);
270 
271 	/*
272 	 * Relocate ourselves - we only need RELOC_RELATIVE and RELOC_32.
273 	 * Note, if panic() was called its probable that it will barf as the
274 	 * corresponding plt wouldn't have been relocated yet.
275 	 */
276 	for (i = 0; i < r; i++) {
277 	    long *where = (long *)((caddr_t)rp->r_address + ip->crt_baseaddr);
278 	    long what = ip->crt_baseaddr;
279 	    long value;
280 
281 	    switch (rp->r_type) {
282 	    case RELOC_RELATIVE:
283 		what += *where << (32-22);
284 		value = (*where & ~MASK(22)) | ((what >> (32-22)) & MASK(22));
285 		wrt(where, value);
286 		where++;
287 		what += (*where & MASK(10));
288 		value = (*where & ~MASK(10)) | (what & MASK(10));
289 		wrt(where, value);
290 		break;
291 
292 	    case RELOC_32:
293 		what += *where;
294 		wrt(where, what);
295 		break;
296 
297 	    default:
298 		panic("unknown relocation type %d\n", rp->r_type);
299 		break;
300 	    }
301 	    rp++;
302 	}
303 
304 	/*
305 	 * We're relocated, we can now initialize things referencing
306 	 * static storage.
307 	 */
308 	ldso = "/usr/lib/ld.so.1";
309 
310 	/*
311 	 * Close off the file descriptor used to get us here -- let it
312 	 * be available for the next (probable) use below.
313 	 */
314 	(void) close(ip->crt_rlfd);
315 
316 	/*
317 	 * Discover things about our environment: auxiliary vector (if
318 	 * any), arguments, program name, and the like.
319 	 */
320 	ebp = eb;
321 	program_name = (char *)(argp + sizeof (int));
322 	if (version != 1)
323 		panic("bad startup interface version of %d",
324 		    version);
325 	ebp->eb_tag = EB_DYNAMIC,
326 	    (ebp++)->eb_un.eb_ptr = (Elf32_Addr)ip->crt_udp;
327 	ebp->eb_tag = EB_ARGV, (ebp++)->eb_un.eb_ptr = (Elf32_Addr)program_name;
328 	ebp->eb_tag = EB_ENVP, (ebp++)->eb_un.eb_ptr = (Elf32_Addr)ip->crt_ep;
329 	ebp->eb_tag = EB_DEVZERO,
330 	    (ebp++)->eb_un.eb_val = (Elf32_Word)ip->crt_dzfd;
331 	for (addr = (caddr_t)ip->crt_ep; *addr; addr += sizeof (char *))
332 		;
333 	addr += sizeof (char *);
334 
335 	/*
336 	 * The kernel sends us an abbreviated aux vector with some
337 	 * potentially handy stuff that saves us on syscalls.
338 	 *
339 	 * Notes on 1226113
340 	 *
341 	 * The f77 compiler shipped as part of SC1.0 on 4.x creates binaries
342 	 * that use the _fix_libc_ feature of acc.  This makes the resulting
343 	 * executable object dependent on the undocumented behaviour of
344 	 * libc's .rem and .div routines e.g. that .div returns the
345 	 * remainder in %o3 (and similarly .rem returns the division in %o3).
346 	 *
347 	 * The only simple solution is to disable hardware divide for
348 	 * all 4.x applications so that the old software routines that have
349 	 * this "support" in them are used instead.  And we do that by
350 	 * clearing the divide-in-hardware flag from the aux vector before
351 	 * libc's .init routine gets to see it.  Awful isn't it.
352 	 */
353 	ebp->eb_tag = EB_AUXV, (ebp++)->eb_un.eb_ptr = (Elf32_Addr)addr;
354 	for (ap = (auxv_t *)addr; ap->a_type != AT_NULL; ap++)
355 		if (ap->a_type == AT_PAGESZ) {
356 			page_size = ap->a_un.a_val;
357 			ebp->eb_tag = EB_PAGESIZE, (ebp++)->eb_un.eb_val =
358 			    (Elf32_Word)page_size;
359 		} else if (ap->a_type == AT_SUN_HWCAP)
360 			ap->a_un.a_val &= ~AV_SPARC_HWDIV_32x32;
361 
362 	/*
363 	 * If we didn't get a page size from looking in the auxiliary
364 	 * vector, we need to get one now.
365 	 */
366 	if (page_size == 0) {
367 		page_size = sysconfig(_CONFIG_PAGESIZE);
368 		ebp->eb_tag = EB_PAGESIZE, (ebp++)->eb_un.eb_val =
369 		    (Elf32_Word)page_size;
370 	}
371 
372 	/*
373 	 * Map in the ELF-based ld.so.  Note that we're mapping it as
374 	 * an ELF database, not as a program -- we just want to walk it's
375 	 * data structures.  Further mappings will actually establish the
376 	 * program in the address space.
377 	 */
378 	if ((fd = open(ldso, O_RDONLY)) == -1)
379 		panic("unable to open %s", ldso);
380 	if (fstat(fd, &sb) == -1)
381 		panic("unable to find size of %s", ldso);
382 	ehdr = (Elf32_Ehdr *)mmap(0, sb.st_size, PROT_READ | PROT_EXEC,
383 	    MAP_SHARED, fd, 0);
384 	if (ehdr == (Elf32_Ehdr *)-1)
385 		panic("unable to map %s", ldso);
386 
387 	/*
388 	 * Validate the file we're looking at, ensure it has the correct
389 	 * ELF structures, such as: ELF magic numbers, coded for SPARC,
390 	 * is a ".so", etc.
391 	 */
392 	if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
393 	    ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
394 	    ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
395 	    ehdr->e_ident[EI_MAG3] != ELFMAG3)
396 		panic("%s is not an ELF file", ldso);
397 	if (ehdr->e_ident[EI_CLASS] != ELFCLASS32 ||
398 	    ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
399 		panic("%s has wrong class or data encoding", ldso);
400 	if (ehdr->e_type != ET_DYN)
401 		panic("%s is not a shared object", ldso);
402 	if ((ehdr->e_machine != EM_SPARC) &&
403 	    (ehdr->e_machine != EM_SPARC32PLUS))
404 		panic("%s is not a valid SPARC object: e_machine: %x",
405 		    ldso, ehdr->e_machine);
406 	if (ehdr->e_version > EV_CURRENT)
407 		panic("%s has bad ELF version of %d", ldso, ehdr->e_version);
408 
409 	/*
410 	 * Point at program headers and start figuring out what to load.
411 	 */
412 	phdr = (Elf32_Phdr *)((caddr_t)ehdr + ehdr->e_phoff);
413 	for (p = 0, pptr = phdr; p < (int)ehdr->e_phnum; p++,
414 	    pptr = (Elf32_Phdr *)((caddr_t)pptr + ehdr->e_phentsize))
415 		if (pptr->p_type == PT_LOAD) {
416 			if (fph == 0) {
417 				fph = pptr;
418 			} else if (pptr->p_vaddr <= lph->p_vaddr)
419 				panic(
420 		"%s invalid program header - segments out of order", ldso);
421 			lph = pptr;
422 		}
423 
424 	/*
425 	 * We'd better have at least one loadable segment.
426 	 */
427 	if (fph == 0)
428 		panic("%s has no loadable segments", ldso);
429 
430 	/*
431 	 * Map enough address space to hold the program (as opposed to the
432 	 * file) represented by ld.so.  The amount to be assigned is the
433 	 * range between the end of the last loadable segment and the
434 	 * beginning of the first PLUS the alignment of the first segment.
435 	 * mmap() can assign us any page-aligned address, but the relocations
436 	 * assume the alignments included in the program header.  As an
437 	 * optimization, however, let's assume that mmap() will actually
438 	 * give us an aligned address -- since if it does, we can save
439 	 * an munmap() later on.  If it doesn't -- then go try it again.
440 	 */
441 	mlen = ROUND((lph->p_vaddr + lph->p_memsz) -
442 	    ALIGN(fph->p_vaddr, page_size), page_size);
443 	maddr = (caddr_t)mmap(0, mlen, PROT_READ | PROT_EXEC,
444 	    MAP_SHARED, fd, 0);
445 	if (maddr == (caddr_t)-1)
446 		panic("unable to reserve space for %s", ldso);
447 	faddr = (caddr_t)ROUND(maddr, fph->p_align);
448 
449 	/*
450 	 * Check to see whether alignment skew was really needed.
451 	 */
452 	if (faddr != maddr) {
453 		(void) munmap(maddr, mlen);
454 		mlen = ROUND((lph->p_vaddr + lph->p_memsz) -
455 		    ALIGN(fph->p_vaddr, fph->p_align) + fph->p_align,
456 		    page_size);
457 		maddr = (caddr_t)mmap(0, mlen, PROT_READ | PROT_EXEC,
458 		    MAP_SHARED, fd, 0);
459 		if (maddr == (caddr_t)-1)
460 			panic("unable to reserve space for %s", ldso);
461 		faddr = (caddr_t)ROUND(maddr, fph->p_align);
462 	}
463 	ebp->eb_tag = EB_LDSO_BASE, (ebp++)->eb_un.eb_ptr = (Elf32_Addr)faddr;
464 
465 	/*
466 	 * We have the address space reserved, so map each loadable segment.
467 	 */
468 	for (pptr = phdr; (pptr - phdr) < (int)ehdr->e_phnum; pptr++) {
469 
470 		/*
471 		 * Skip non-loadable segments or segments that don't occupy
472 		 * any memory.
473 		 */
474 		if ((pptr->p_type != PT_LOAD) || (pptr->p_memsz == 0))
475 			continue;
476 
477 		/*
478 		 * Determine the file offset to which the mapping will
479 		 * directed (must be aligned) and how much to map (might
480 		 * be more than the file in the case of .bss.)
481 		 */
482 		foff = ALIGN(pptr->p_offset, page_size);
483 		flen = pptr->p_memsz + (pptr->p_offset - foff);
484 
485 		/*
486 		 * Set address of this segment relative to our base.
487 		 */
488 		addr = (caddr_t)ALIGN(faddr + pptr->p_vaddr, page_size);
489 
490 		/*
491 		 * Unmap anything form the last mapping address to this
492 		 * one.
493 		 */
494 		if (addr - maddr) {
495 			(void) munmap(maddr, addr - maddr);
496 			mlen -= addr - maddr;
497 		}
498 
499 		/*
500 		 * Determine the mapping protection from the section
501 		 * attributes.
502 		 */
503 		i = 0;
504 		if (pptr->p_flags & PF_R)
505 			i |= PROT_READ;
506 		if (pptr->p_flags & PF_W)
507 			i |= PROT_WRITE;
508 		if (pptr->p_flags & PF_X)
509 			i |= PROT_EXEC;
510 		if ((caddr_t)mmap((caddr_t)addr, flen, i,
511 		    MAP_FIXED | MAP_PRIVATE, fd, foff) == (caddr_t)-1)
512 			panic("unable to map a segment from %s", ldso);
513 
514 		/*
515 		 * If the memory occupancy of the segment overflows the
516 		 * definition in the file, we need to "zero out" the
517 		 * end of the mapping we've established, and if necessary,
518 		 * map some more space from /dev/zero.
519 		 */
520 		if (pptr->p_memsz > pptr->p_filesz) {
521 			foff = (int)faddr + pptr->p_vaddr + pptr->p_filesz;
522 			zaddr = (caddr_t)ROUND(foff, page_size);
523 			_zero(foff, zaddr - foff);
524 			r = (faddr + pptr->p_vaddr + pptr->p_memsz) - zaddr;
525 			if (r > 0)
526 				if ((caddr_t)mmap((caddr_t)zaddr, r, i,
527 				    MAP_FIXED | MAP_PRIVATE, ip->crt_dzfd,
528 				    0) == (caddr_t)-1)
529 					panic(
530 					"unable to map .bss /dev/zero for %s",
531 					    ldso);
532 		}
533 
534 		/*
535 		 * Update the mapping claim pointer.
536 		 */
537 		maddr = addr + ROUND(flen, page_size);
538 		mlen -= maddr - addr;
539 	}
540 
541 	/*
542 	 * Unmap any final reservation.
543 	 */
544 	if (mlen > 0)
545 		(void) munmap(maddr, mlen);
546 
547 	/*
548 	 * Clean up file descriptor space we've consumed.  Pass along
549 	 * the /dev/zero file descriptor we got -- every cycle counts.
550 	 */
551 	(void) close(fd);
552 
553 	/*
554 	 * The call itself.  Note that we start 1 instruction word in.
555 	 * The ELF ld.so contains an "entry vector" of branch instructions,
556 	 * which, for our interest are:
557 	 *	+0:	ba, a	<normal startup>
558 	 *	+4:	ba, a	<compatibility startup>
559 	 * By starting at the compatibility startup, the ELF ld.so knows
560 	 * that a pointer to "eb" is available to it and further knows
561 	 * how to calculate the offset to the program's arguments and
562 	 * other structures.
563 	 */
564 	ebp->eb_tag = EB_NULL, ebp->eb_un.eb_val = 0;
565 	(*((void (*)())(ehdr->e_entry + faddr + sizeof (long))))(eb);
566 	return (0);
567 }
568