2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A * Redirection ld.so. Based on the 4.x binary compatibility ld.so, used 2N/A * to redirect aliases for ld.so to the real one. 2N/A * Import data structures 2N/A * Local manifest constants and macros. 2N/A * Alias ld.so entry point -- receives a bootstrap structure and a vector 2N/A * of strings. The vector is "well-known" to us, and consists of pointers 2N/A * to string constants. This aliasing bootstrap requires no relocation in 2N/A * order to run, save for the pointers of constant strings. This second 2N/A * parameter provides this. Note that this program is carefully coded in 2N/A * order to maintain the "no bootstrapping" requirement -- it calls only 2N/A * local functions, uses no intrinsics, etc. 2N/A int i, p;
/* working */ 2N/A long j;
/* working */ 2N/A * Discover things about our environment: auxiliary vector (if 2N/A * any), arguments, program name, and the like. 2N/A * If we didn't get a page size from looking in the auxiliary 2N/A * vector, we need to get one now. 2N/A * Map in the real ld.so. Note that we're mapping it as 2N/A * an ELF database, not as a program -- we just want to walk it's 2N/A * data structures. Further mappings will actually establish the 2N/A * program in the address space. 2N/A * Validate the file we're looking at, ensure it has the correct 2N/A * ELF structures, such as: ELF magic numbers, coded for SPARC, 2N/A * Point at program headers and start figuring out what to load. 2N/A * We'd better have at least one loadable segment. 2N/A * Map enough address space to hold the program (as opposed to the 2N/A * file) represented by ld.so. The amount to be assigned is the 2N/A * range between the end of the last loadable segment and the 2N/A * beginning of the first PLUS the alignment of the first segment. 2N/A * mmap() can assign us any page-aligned address, but the relocations 2N/A * assume the alignments included in the program header. As an 2N/A * optimization, however, let's assume that mmap() will actually 2N/A * give us an aligned address -- since if it does, we can save 2N/A * an munmap() later on. If it doesn't -- then go try it again. 2N/A * Check to see whether alignment skew was really needed. 2N/A * We have the address space reserved, so map each loadable segment. 2N/A * Skip non-loadable segments or segments that don't occupy 2N/A * Determine the file offset to which the mapping will 2N/A * directed (must be aligned) and how much to map (might 2N/A * be more than the file in the case of .bss.) 2N/A * Set address of this segment relative to our base. 2N/A * If this is the first program header, record our base 2N/A * address for later use. 2N/A * Unmap anything from the last mapping address to this 2N/A * Determine the mapping protection from the section 2N/A * If the memory occupancy of the segment overflows the 2N/A * definition in the file, we need to "zero out" the 2N/A * end of the mapping we've established, and if necessary, 2N/A * Update the mapping claim pointer. 2N/A * Unmap any final reservation. 2N/A * Clean up file descriptor space we've consumed. Pass along 2N/A * the /dev/zero file descriptor we got -- every cycle counts. 2N/A * The call itself. Note that we start 1 instruction word in. 2N/A * The ELF ld.so contains an "entry vector" of branch instructions, 2N/A * which, for our interest are: 2N/A * +0: ba, a <normal startup> 2N/A * +4: ba, a <compatibility startup> 2N/A * +8: ba, a <alias startup> 2N/A * By starting at the alias startup, the ELF ld.so knows 2N/A * that a pointer to "eb" is available to it and further knows 2N/A * how to calculate the offset to the program's arguments and 2N/A * other structures. We do the "call" by returning to our 2N/A * bootstrap and then jumping to the address that we return.