This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug libc/11754] New: RFE: dlopen of ET_EXEC file


Request For Enhancement (RFE):  Please enhance dlopen() of an ET_EXEC file to
work in many cases.  Currently dlopen() of an ET_EXEC file always fails with the
dlerror() string "cannot dynamically load executable".  However, the test
program below shows by example that dlopen() of the corresponding ET_DYN file
(just change Elf32_Ehdr.e_type from ET_EXEC to ET_DYN) can give useful results.
 In particular, the file is mapped into the address space, along with all its
DT_NEEDED dependencies, and can be invoked successfully at its .e_entry point. 
If the handle returned by dlopen() were not NULL, then dlsym() probably would
work, too.  All of these are useful properties that would be nice to have. 
Thank you.

-----hello.c
#include <stdio.h>

int
main(int argc, char *argv[])
{
	printf("Hello world.\n");
	return 0;
}
-----dlopen-exec.c
/* Show that dlopen of an ET_EXEC file would mostly work, at least if the
 * address space that is requested is currently unoccupied.
 *
 * Compile and run via:
 *    gcc -m32 -g -o hello32 hello.c
 *    gcc -m32 -g -o dlopen-exec -Ttext-segment=0x0a000000 dlopen-exec.c -ldl
 *    ./dlopen-exec
 * -Ttext-segment=0x0a000000 leaves enough room for the default 0x08048000.
 */

#include <dlfcn.h>
#include <elf.h>
#include <sys/fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/* i386 code to invoke an ET_EXEC image that has been loaded into memory. */
void
raw_start(Elf32_Addr entry, int original_argc, char const **original_argv)
{
	asm("mov 2*4(%ebp),%eax");  /* entry */
	asm("mov 3*4(%ebp),%ecx");  /* original_argc */
	asm("mov 4*4(%ebp),%edx");  /* original_argv */
	asm("mov %edx,%esp");  /* Trim stack. */
	asm("push %ecx");      /* New argc */
	asm("sub %edx,%edx");  /* no rtld_fini function */
	asm("jmp *%eax");      /* Goto entry. */
}

char fname[] = "/tmp/dlopen-exec-XXXXXX";

int
main(int argc, char const *argv[])
{
	/* Try to dlopen an ET_EXEC file. */
	void *handle = dlopen("./hello32", RTLD_LAZY);
	if (0==handle) {
		fprintf(stderr, "dlopen ./hello32 failed:%s\n", dlerror());
	}

	/* Write a new file that is the same except for ET_DYN. */
	/* Error checking has been omitted in this section. */
	int const fdi = open("./hello32", O_RDONLY);
	struct stat sb;
	fstat(fdi, &sb);
	Elf32_Ehdr *const ehdr = malloc(sb.st_size);
	read(fdi, ehdr, sb.st_size);
	close(fdi);
	ehdr->e_type = ET_DYN;
	int const fdo = mkstemp(fname);
	write(fdo, ehdr, sb.st_size);
	close(fdo);

	/* Try to dlopen the ET_DYN file. */
	void *h2 = dlopen(fname, RTLD_LAZY);
	if (0==handle) {
		fprintf(stderr, "dlopen failed:%s\n", dlerror());
	}
	else {
		fprintf(stderr, "Success: %s\n", fname);
	}
	unlink(fname);  /* Clean up. */

	/* dlopen() "succeeded" even though the return value was 0.
	 * Demonstrate success by executing the loaded program.
	 */
	raw_start(ehdr->e_entry, argc, argv);

	return 0;
}
-----console log
$ gcc -m32 -g -o hello32 hello.c
$ gcc -m32 -g -o dlopen-exec -Ttext-segment=0x0a000000 dlopen-exec.c -ldl
$ ./dlopen-exec
dlopen ./hello32 failed:./hello32: cannot dynamically load executable
dlopen failed:(null)
Hello world.
$ 
-----

-- 
           Summary: RFE: dlopen of ET_EXEC file
           Product: glibc
           Version: 2.12
            Status: NEW
          Severity: normal
          Priority: P2
         Component: libc
        AssignedTo: drepper at redhat dot com
        ReportedBy: jreiser at BitWagon dot com
                CC: glibc-bugs at sources dot redhat dot com


http://sourceware.org/bugzilla/show_bug.cgi?id=11754

------- You are receiving this mail because: -------
You are on the CC list for the bug, or are watching someone who is.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]