X-Git-Url: http://git.osdn.net/view?a=blobdiff_plain;f=ldso%2Fldso%2Fdl-startup.c;h=75ea564c2dae9297f2a91ebf53ce4e8be73d9db0;hb=a899b909abe14e8e35a81997c828201d1beaff78;hp=a51b583a44b5e905b6c5c8659f6ae758a19e49fa;hpb=e092e7c30464555b3fb81adc8f2f479e892b0786;p=uclinux-h8%2FuClibc.git diff --git a/ldso/ldso/dl-startup.c b/ldso/ldso/dl-startup.c index a51b583a4..75ea564c2 100644 --- a/ldso/ldso/dl-startup.c +++ b/ldso/ldso/dl-startup.c @@ -32,8 +32,8 @@ /* * The main trick with this program is that initially, we ourselves are not - * dynamicly linked. This means that we cannot access any global variables or - * call any functions. No globals initially, since the Global Offset Table + * dynamically linked. This means that we cannot access any global variables + * or call any functions. No globals initially, since the Global Offset Table * (GOT) is initialized by the linker assuming a virtual address of 0, and no * function calls initially since the Procedure Linkage Table (PLT) is not yet * initialized. @@ -55,12 +55,12 @@ * * Fortunately, the linker itself leaves a few clues lying around, and when the * kernel starts the image, there are a few further clues. First of all, there - * is Auxiliary Vector Table information sitting on which is provided to us by - * the kernel, and which includes information about the load address that the - * program interpreter was loaded at, the number of sections, the address the - * application was loaded at and so forth. Here this information is stored in - * the array auxvt. For details see linux/fs/binfmt_elf.c where it calls - * NEW_AUX_ENT() a bunch of time.... + * is Auxiliary Vector Table information sitting on the stack which is provided + * to us by the kernel, and which includes information about the address + * that the program interpreter was loaded at, the number of sections, the + * address the application was loaded at, and so forth. Here this information + * is stored in the array auxvt. For details see linux/fs/binfmt_elf.c where + * it calls NEW_AUX_ENT() a bunch of times.... * * Next, we need to find the GOT. On most arches there is a register pointing * to the GOT, but just in case (and for new ports) I've added some (slow) C @@ -94,6 +94,11 @@ /* Pull in all the arch specific stuff */ #include "dl-startup.h" +#ifdef __LDSO_PRELINK_SUPPORT__ +/* These defined magically in the linker script. */ +extern char _begin[] attribute_hidden; +#endif + /* Static declarations */ static int (*_dl_elf_main) (int, char **, char **); @@ -164,11 +169,26 @@ DL_START(unsigned long args) aux_dat += 2; } - /* locate the ELF header. We need this done as soon as possible - * (esp since SEND_STDERR() needs this on some platforms... */ + /* + * Locate the dynamic linker ELF header. We need this done as soon as + * possible (esp since SEND_STDERR() needs this on some platforms... + */ + +#ifdef __LDSO_PRELINK_SUPPORT__ + /* + * The `_begin' symbol created by the linker script points to ld.so ELF + * We use it if the kernel is not passing a valid address through the auxvt. + */ + + if (!auxvt[AT_BASE].a_un.a_val) + auxvt[AT_BASE].a_un.a_val = (Elf32_Addr) &_begin; + /* Note: if the dynamic linker itself is prelinked, the load_addr is 0 */ + DL_INIT_LOADADDR_BOOT(load_addr, elf_machine_load_address()); +#else if (!auxvt[AT_BASE].a_un.a_val) auxvt[AT_BASE].a_un.a_val = elf_machine_load_address(); DL_INIT_LOADADDR_BOOT(load_addr, auxvt[AT_BASE].a_un.a_val); +#endif header = (ElfW(Ehdr) *) auxvt[AT_BASE].a_un.a_val; /* Check the ELF header to make sure everything looks ok. */ @@ -183,7 +203,7 @@ DL_START(unsigned long args) _dl_exit(0); } SEND_EARLY_STDERR_DEBUG("ELF header="); - SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(load_addr), 1); + SEND_ADDRESS_STDERR_DEBUG(DL_LOADADDR_BASE(header), 1); /* Locate the global offset table. Since this code must be PIC * we can take advantage of the magic offset register, if we @@ -192,7 +212,7 @@ DL_START(unsigned long args) DL_BOOT_COMPUTE_GOT(got); /* Now, finally, fix up the location of the dynamic stuff */ - DL_BOOT_COMPUTE_DYN(dpnt, got, load_addr); + DL_BOOT_COMPUTE_DYN(dpnt, got, (DL_LOADADDR_TYPE)header); SEND_EARLY_STDERR_DEBUG("First Dynamic section entry="); SEND_ADDRESS_STDERR_DEBUG(dpnt, 1); @@ -231,7 +251,7 @@ DL_START(unsigned long args) PERFORM_BOOTSTRAP_GOT(tpnt); #endif -#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__) +#if !defined(PERFORM_BOOTSTRAP_GOT) || defined(__avr32__) || defined(__mips__) /* OK, now do the relocations. We do not do a lazy binding here, so that once we are done, we have considerably more flexibility. */ @@ -258,7 +278,12 @@ DL_START(unsigned long args) if (!indx && relative_count) { rel_size -= relative_count * sizeof(ELF_RELOC); - elf_machine_relative(load_addr, rel_addr, relative_count); + if (load_addr +#ifdef __LDSO_PRELINK_SUPPORT__ + || !tpnt->dynamic_info[DT_GNU_PRELINKED_IDX] +#endif + ) + elf_machine_relative(load_addr, rel_addr, relative_count); rel_addr += relative_count * sizeof(ELF_RELOC); } @@ -321,12 +346,12 @@ DL_START(unsigned long args) __rtld_stack_end = (void *)(argv - 1); - _dl_get_ready_to_run(tpnt, load_addr, auxvt, envp, argv - DL_GET_READY_TO_RUN_EXTRA_ARGS); + _dl_elf_main = (int (*)(int, char **, char **)) + _dl_get_ready_to_run(tpnt, (DL_LOADADDR_TYPE) header, auxvt, envp, argv + DL_GET_READY_TO_RUN_EXTRA_ARGS); /* Transfer control to the application. */ SEND_STDERR_DEBUG("transfering control to application @ "); - _dl_elf_main = (int (*)(int, char **, char **)) auxvt[AT_ENTRY].a_un.a_val; SEND_ADDRESS_STDERR_DEBUG(_dl_elf_main, 1); #if !defined(START)