Index: libexec/rtld-elf/map_object.c =================================================================== --- libexec/rtld-elf/map_object.c +++ libexec/rtld-elf/map_object.c @@ -193,6 +193,8 @@ base_flags = MAP_PRIVATE | MAP_ANON | MAP_NOCORE; if (npagesizes > 1 && round_page(segs[0]->p_filesz) >= pagesizes[1]) base_flags |= MAP_ALIGNED_SUPER; + if (base_vaddr != 0) + base_flags |= MAP_FIXED | MAP_EXCL; mapbase = mmap(base_addr, mapsize, PROT_NONE, base_flags, -1, 0); if (mapbase == (caddr_t) -1) { Index: libexec/rtld-elf/rtld.c =================================================================== --- libexec/rtld-elf/rtld.c +++ libexec/rtld-elf/rtld.c @@ -345,7 +345,8 @@ const Elf_Phdr *phdr; Objlist initlist; RtldLockState lockstate; - char **argv, *argv0, **env, *kexecpath, *library_path_rpath; + Elf_Addr *argcp; + char **argv, *argv0, **env, **envp, *kexecpath, *library_path_rpath; caddr_t imgentry; char buf[MAXPATHLEN]; int argc, fd, i, mib[2], phnum; @@ -359,6 +360,7 @@ */ /* Find the auxiliary vector on the stack. */ + argcp = sp; argc = *sp++; argv = (char **) sp; sp += argc + 1; /* Skip over arguments and NULL terminator */ @@ -466,12 +468,56 @@ dbg("initializing thread locks"); lockdflt_init(); + fd = -1; + /* * Load the main program, or process its program header if it is * already loaded. */ - if (aux_info[AT_EXECFD] != NULL) { /* Load the main program. */ + if (aux_info[AT_EXECFD] != NULL) { fd = aux_info[AT_EXECFD]->a_un.a_val; + } else { + assert(aux_info[AT_PHDR] != NULL); + phdr = (const Elf_Phdr *) aux_info[AT_PHDR]->a_un.a_ptr; + if (phdr == obj_rtld.phdr) { + dbg("opening main program in direct exec mode"); + if (argc >= 2) { + argv0 = argv[1]; + fd = open(argv0, O_RDONLY | O_CLOEXEC | O_VERIFY); + if (fd == -1) { + rtld_printf("Opening %s: %s\n", argv0, + rtld_strerror(errno)); + rtld_die(); + } + + /* + * Shift by 1, to hide the ld.so name argument. + * XXX Shift will be > 1 when options are implemented. + */ + main_argc = argc - 1; + main_argv = argv + 1; + do { + *argv = *(argv + 1); + argv++; + } while (*argv != 0); + *argcp -= 1; + envp = argv; + do { + *envp = *(envp + 1); + envp++; + } while (*envp != 0); + auxp = (Elf_Auxinfo *)(envp + 1); + do { + *auxp = *(auxp + 1); + auxp++; + } while (auxp->a_type != AT_NULL); + } else { + rtld_printf("no binary\n"); + rtld_die(); + } + } + } + if (fd != -1) { /* Load the main program. */ dbg("loading main program"); obj_main = map_object(fd, argv0, NULL); close(fd); @@ -492,7 +538,7 @@ rtld_die(); } - if (aux_info[AT_EXECPATH] != NULL) { + if (aux_info[AT_EXECPATH] != NULL && fd == -1) { kexecpath = aux_info[AT_EXECPATH]->a_un.a_ptr; dbg("AT_EXECPATH %p %s", kexecpath, kexecpath); if (kexecpath[0] == '/') @@ -504,7 +550,7 @@ else obj_main->path = xstrdup(buf); } else { - dbg("No AT_EXECPATH"); + dbg("No AT_EXECPATH or direct exec"); obj_main->path = xstrdup(argv0); } dbg("obj_main path %s", obj_main->path);