📄 boot1.c
字号:
PROT_READ | PROT_WRITE | PROT_EXEC); } } } /* OK, now do the relocations. We do not do a lazy binding here, so that once we are done, we have considerably more flexibility. */ goof = 0; for (indx = 0; indx < 2; indx++) { int i; ELF_RELOC *rpnt; unsigned long *reloc_addr; unsigned long symbol_addr; int symtab_index; unsigned long rel_addr, rel_size;#ifdef ELF_USES_RELOCA rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt-> dynamic_info[DT_RELA]); rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt-> dynamic_info[DT_RELASZ]);#else rel_addr = (indx ? tpnt->dynamic_info[DT_JMPREL] : tpnt-> dynamic_info[DT_REL]); rel_size = (indx ? tpnt->dynamic_info[DT_PLTRELSZ] : tpnt-> dynamic_info[DT_RELSZ]);#endif if (!rel_addr) continue; /* Now parse the relocation information */ rpnt = (ELF_RELOC *) (rel_addr + load_addr); for (i = 0; i < rel_size; i += sizeof(ELF_RELOC), rpnt++) { reloc_addr = (unsigned long *) (load_addr + (unsigned long) rpnt->r_offset); symtab_index = ELF32_R_SYM(rpnt->r_info); symbol_addr = 0; if (symtab_index) { char *strtab; Elf32_Sym *symtab; symtab = (Elf32_Sym *) (tpnt->dynamic_info[DT_SYMTAB] + load_addr); strtab = (char *) (tpnt->dynamic_info[DT_STRTAB] + load_addr); /* We only do a partial dynamic linking right now. The user is not supposed to redefine any symbols that start with a '_', so we can do this with confidence. */ if (!_dl_symbol(strtab + symtab[symtab_index].st_name)) continue; symbol_addr = load_addr + symtab[symtab_index].st_value; if (!symbol_addr) { /* * This will segfault - you cannot call a function until * we have finished the relocations. */ SEND_STDERR("ELF dynamic loader - unable to " "self-bootstrap - symbol "); SEND_STDERR(strtab + symtab[symtab_index].st_name); SEND_STDERR(" undefined.\n"); goof++; } } /* * Use this machine-specific macro to perform the actual relocation. */ PERFORM_BOOTSTRAP_RELOC(rpnt, reloc_addr, symbol_addr, load_addr); } } if (goof) { _dl_exit(14); } /* OK, at this point we have a crude malloc capability. Start to build the tables of the modules that are required for this beast to run. We start with the basic executable, and then go from there. Eventually we will run across ourself, and we will need to properly deal with that as well. */ _dl_malloc_addr = malloc_buffer; _dl_mmap_zero = mmap_zero; /* Now we have done the mandatory linking of some things. We are now free to start using global variables, since these things have all been fixed up by now. Still no function calls outside of this library , since the dynamic resolver is not yet ready. */ lpnt = (unsigned long *) (tpnt->dynamic_info[DT_PLTGOT] + load_addr); INIT_GOT(lpnt, tpnt); /* OK, this was a big step, now we need to scan all of the user images and load them properly. */ tpnt->next = 0; tpnt->libname = 0; tpnt->libtype = program_interpreter; { elfhdr *epnt; elf_phdr *ppnt; int i; epnt = (elfhdr *) auxv_t[AT_BASE].a_un.a_ptr; tpnt->n_phent = epnt->e_phnum; tpnt->ppnt = ppnt = (elf_phdr *) (load_addr + epnt->e_phoff); for (i = 0; i < epnt->e_phnum; i++, ppnt++) { if (ppnt->p_type == PT_DYNAMIC) { tpnt->dynamic_addr = ppnt->p_vaddr + load_addr; tpnt->dynamic_size = ppnt->p_filesz; } } } tpnt->chains = chains; tpnt->loadaddr = (char *) load_addr; brk_addr = 0; rpnt = NULL; /* At this point we are now free to examine the user application, and figure out which libraries are supposed to be called. Until we have this list, we will not be completely ready for dynamic linking */ { elf_phdr *ppnt; int i; ppnt = (elf_phdr *) auxv_t[AT_PHDR].a_un.a_ptr; for (i = 0; i < auxv_t[AT_PHNUM].a_un.a_val; i++, ppnt++) { if (ppnt->p_type == PT_LOAD) { if (ppnt->p_vaddr + ppnt->p_memsz > brk_addr) brk_addr = ppnt->p_vaddr + ppnt->p_memsz; } if (ppnt->p_type == PT_DYNAMIC) {#ifndef ALLOW_ZERO_PLTGOT /* make sure it's really there. */ if (app_tpnt->dynamic_info[DT_PLTGOT] == 0) continue;#endif /* OK, we have what we need - slip this one into the list. */ app_tpnt = _dl_add_elf_hash_table("", 0, app_tpnt->dynamic_info, ppnt->p_vaddr, ppnt->p_filesz); _dl_loaded_modules->libtype = elf_executable; _dl_loaded_modules->ppnt = (elf_phdr *) auxv_t[AT_PHDR].a_un.a_ptr; _dl_loaded_modules->n_phent = auxv_t[AT_PHNUM].a_un.a_val; _dl_symbol_tables = rpnt = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt, 0, sizeof(*rpnt)); rpnt->dyn = _dl_loaded_modules; app_tpnt->usage_count++; app_tpnt->symbol_scope = _dl_symbol_tables; lpnt = (unsigned long *) (app_tpnt->dynamic_info[DT_PLTGOT]);#ifdef ALLOW_ZERO_PLTGOT if (lpnt)#endif INIT_GOT(lpnt, _dl_loaded_modules); } if (ppnt->p_type == PT_INTERP) { /* OK, fill this in - we did not have this before */ tpnt->libname = _dl_strdup((char *) ppnt->p_offset + (auxv_t[AT_PHDR].a_un.a_val & 0xfffff000)); } } } if (argv[0]) { _dl_progname = argv[0]; } /* Now we need to figure out what kind of options are selected. Note that for SUID programs we ignore the settings in LD_LIBRARY_PATH */ { _dl_not_lazy = _dl_getenv("LD_BIND_NOW", envp); if ((auxv_t[AT_UID].a_un.a_val == -1 && _dl_suid_ok()) || (auxv_t[AT_UID].a_un.a_val != -1 && auxv_t[AT_UID].a_un.a_val == auxv_t[AT_EUID].a_un.a_val && auxv_t[AT_GID].a_un.a_val== auxv_t[AT_EGID].a_un.a_val)) { _dl_secure = 0; _dl_preload = _dl_getenv("LD_PRELOAD", envp); _dl_library_path = _dl_getenv("LD_LIBRARY_PATH", envp); } else { _dl_secure = 1; _dl_preload = _dl_getenv("LD_PRELOAD", envp); _dl_unsetenv("LD_AOUT_PRELOAD", envp); _dl_unsetenv("LD_LIBRARY_PATH", envp); _dl_unsetenv("LD_AOUT_LIBRARY_PATH", envp); _dl_library_path = NULL; } }#ifdef DL_TRACE _dl_trace_loaded_objects = _dl_getenv("LD_TRACE_LOADED_OBJECTS", envp);#endif /* OK, we now have the application in the list, and we have some basic stuff in place. Now search through the list for other shared libraries that should be loaded, and insert them on the list in the correct order. */#ifdef USE_CACHE _dl_map_cache();#endif { struct elf_resolve *tcurr; struct elf_resolve *tpnt1; char *lpnt; if (_dl_preload) { char c, *str, *str2; str = _dl_preload; while (*str == ':' || *str == ' ' || *str == '\t') str++; while (*str) { str2 = str; while (*str2 && *str2 != ':' && *str2 != ' ' && *str2 != '\t') str2++; c = *str2; *str2 = '\0'; if (!_dl_secure || _dl_strchr(str, '/') == NULL) { tpnt1 = _dl_load_shared_library(_dl_secure, NULL, str); if (!tpnt1) {#ifdef DL_TRACE if (_dl_trace_loaded_objects) _dl_dprintf(1, "\t%s => not found\n", str); else {#endif _dl_dprintf(2, "%s: can't load " "library '%s'\n", _dl_progname, str); _dl_exit(15);#ifdef DL_TRACE }#endif } else {#ifdef DL_TRACE if (_dl_trace_loaded_objects && !tpnt1->usage_count) { /* this is a real hack to make ldd not print * the library itself when run on a library. */ if (_dl_strcmp(_dl_progname, str) != 0) _dl_dprintf(1, "\t%s => %s (0x%x)\n", str, tpnt1->libname, (unsigned) tpnt1->loadaddr); }#endif rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt->next, 0, sizeof(*(rpnt->next))); rpnt = rpnt->next; tpnt1->usage_count++; tpnt1->symbol_scope = _dl_symbol_tables; tpnt1->libtype = elf_lib; rpnt->dyn = tpnt1; } } *str2 = c; str = str2; while (*str == ':' || *str == ' ' || *str == '\t') str++; } } { int fd; struct stat st; char *preload; if (!_dl_stat(LDSO_PRELOAD, &st) && st.st_size > 0) { if ((fd = _dl_open(LDSO_PRELOAD, O_RDONLY)) < 0) { _dl_dprintf(2, "%s: can't open file '%s'\n", _dl_progname, LDSO_PRELOAD); } else { preload = (caddr_t) _dl_mmap(0, st.st_size + 1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); _dl_close(fd); if (preload == (caddr_t) - 1) { _dl_dprintf(2, "%s: can't map file '%s'\n", _dl_progname, LDSO_PRELOAD); } else { char c, *cp, *cp2; /* convert all separators and comments to spaces */ for (cp = preload; *cp; /*nada */ ) { if (*cp == ':' || *cp == '\t' || *cp == '\n') { *cp++ = ' '; } else if (*cp == '#') { do *cp++ = ' '; while (*cp != '\n' && *cp != '\0'); } else { cp++; } } /* find start of first library */ for (cp = preload; *cp && *cp == ' '; cp++) /*nada */ ; while (*cp) { /* find end of library */ for (cp2 = cp; *cp && *cp != ' '; cp++) /*nada */ ; c = *cp; *cp = '\0'; tpnt1 = _dl_load_shared_library(0, NULL, cp2); if (!tpnt1) {#ifdef DL_TRACE if (_dl_trace_loaded_objects) _dl_dprintf(1, "\t%s => not found\n", cp2); else {#endif _dl_dprintf(2, "%s: can't load library '%s'\n", _dl_progname, cp2); _dl_exit(15);#ifdef DL_TRACE }#endif } else {#ifdef DL_TRACE if (_dl_trace_loaded_objects && !tpnt1->usage_count) { _dl_dprintf(1, "\t%s => %s (0x%x)\n", cp2, tpnt1->libname, (unsigned) tpnt1->loadaddr); }#endif rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt->next, 0, sizeof(*(rpnt->next))); rpnt = rpnt->next; tpnt1->usage_count++; tpnt1->symbol_scope = _dl_symbol_tables; tpnt1->libtype = elf_lib; rpnt->dyn = tpnt1; } /* find start of next library */ *cp = c; for ( /*nada */ ; *cp && *cp == ' '; cp++) /*nada */ ; } _dl_munmap(preload, st.st_size + 1); } } } } for (tcurr = _dl_loaded_modules; tcurr; tcurr = tcurr->next) { for (dpnt = (Elf32_Dyn *) tcurr->dynamic_addr; dpnt->d_tag; dpnt++) { if (dpnt->d_tag == DT_NEEDED) { lpnt = tcurr->loadaddr + tcurr->dynamic_info[DT_STRTAB] + dpnt->d_un.d_val; if (tpnt && _dl_strcmp(lpnt, _dl_get_last_path_component(tpnt->libname)) == 0) { struct elf_resolve *ttmp;#ifdef DL_TRACE if (_dl_trace_loaded_objects && !tpnt->usage_count) { _dl_dprintf(1, "\t%s => %s (0x%x)\n", lpnt, tpnt->libname, (unsigned) tpnt->loadaddr); }#endif ttmp = _dl_loaded_modules; while (ttmp->next) ttmp = ttmp->next; ttmp->next = tpnt; tpnt->prev = ttmp; tpnt->next = NULL; rpnt->next = (struct dyn_elf *) _dl_malloc(sizeof(struct dyn_elf)); _dl_memset(rpnt->next, 0, sizeof(*(rpnt->next))); rpnt = rpnt->next; rpnt->dyn = tpnt; tpnt->usage_count++; tpnt->symbol_scope = _dl_symbol_tables; tpnt = NULL; continue; } if (!(tpnt1 = _dl_load_shared_library(0, tcurr, lpnt))) {#ifdef DL_TRACE if (_dl_trace_loaded_objects) _dl_dprintf(1, "\t%s => not found\n", lpnt); else {#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -