74 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			74 lines
		
	
	
		
			1.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| #include <sys/cdefs.h>
 | |
| 
 | |
| #include <sys/types.h>
 | |
| 
 | |
| #include <err.h>
 | |
| #include <errno.h>
 | |
| #include <libelf.h>
 | |
| #include <stdbool.h>
 | |
| #include <stdlib.h>
 | |
| #include <unistd.h>
 | |
| #include <stdlib.h>
 | |
| #include <string.h>
 | |
| 
 | |
| #include "_libelf.h"
 | |
| #include "../libelf_compat.h"
 | |
| 
 | |
| void *
 | |
| libelf_mmap(void *addr, size_t len, int prot, int flags, int fd, off_t offset)
 | |
| {
 | |
|     void *p; /* malloc'ed pointer */
 | |
|     size_t bufsize;
 | |
| 
 | |
|     if ((addr != NULL) || (flags != MAP_PRIVATE) || (prot != PROT_READ)) {
 | |
| 	LIBELF_SET_ERROR(ARGUMENT, 0);
 | |
| 	return (MAP_FAILED);
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * Fall back to malloc+read.
 | |
|      */
 | |
|     p = NULL;
 | |
|     bufsize = 1024 * 1024;
 | |
|     while (/*CONSTCOND*/true) {
 | |
| 	void *newp = realloc(p, bufsize);
 | |
| 	ssize_t rsz;
 | |
| 
 | |
| 	if (newp == NULL) {
 | |
| 	    free(p);
 | |
| 	    LIBELF_SET_ERROR(RESOURCE, 0);
 | |
| 	    return (MAP_FAILED);
 | |
| 	}
 | |
| 	p = newp;
 | |
| 	rsz = pread(fd, p, bufsize, 0);
 | |
| 	if (rsz == -1) {
 | |
| 	    free(p);
 | |
| 	    LIBELF_SET_ERROR(IO, errno);
 | |
| 	    return (MAP_FAILED);
 | |
| 	} else if ((size_t) rsz > bufsize) {
 | |
| 	    free(p);
 | |
| 	    LIBELF_SET_ERROR(IO, EIO); /* XXX */
 | |
| 	    return (MAP_FAILED);
 | |
| 	} else if ((size_t) rsz < bufsize) {
 | |
| 	    /*
 | |
| 	     * try to shrink the buffer.
 | |
| 	     */
 | |
| 	    newp = realloc(p, (size_t) rsz);
 | |
| 	    if (newp != NULL) {
 | |
| 		p = newp;
 | |
| 	    }
 | |
| 	    break;
 | |
| 	}
 | |
| 	bufsize *= 2;
 | |
|     }
 | |
| 
 | |
|     return p;
 | |
| }
 | |
| 
 | |
| int
 | |
| libelf_munmap(void *addr, size_t len)
 | |
| {
 | |
|     free(addr);
 | |
|     return 0;
 | |
| }
 | 
