Did you know LQ has a Linux Hardware Compatibility List?
Go Back > Forums > Non-*NIX Forums > Programming
User Name
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.


LinkBack Search this Thread
Old 12-26-2005, 09:56 PM   #1
LQ Newbie
Registered: Jul 2005
Posts: 26

Rep: Reputation: 15
memcpy or mmap or other problems

I want to implement the partial function of grip's userland exec on linux(x86_64). To implement this, I think I can follow the following step:
1. open /lib/
2. check's ELF header.
3. do mmap to read's text
4. read's text and data to the space got by mmap
5. get's entry from e_entry
6. setup the stack(to be realized)
7. jmp mmap address
But I now encountered the problem in step4:"read's text to the space got by mmap", I find that I can memcpy the first time successfully, but will failed on the following tries, It will report" memcpy: illegal seek error", could you please tell me why? And the following is my codes:
#include <elf.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>

#define is_loaded(p) ((p)->p_type == PT_LOAD ? 1 : 0)
#define is_txt_segt(p) ((is_loaded(p)) && (p)->p_flags == (PF_X|PF_R))
#define is_data_segt(p) ((is_loaded(p)) && (p)->p_flags == (PF_W|PF_R))


#define ALIGN(k, v) (((k)+((v)-1))&(~((v)-1)))

#define jmp_addr(addr) asm("\tjmp *%0\n" :: "r" (addr))

void * global_ptr = NULL;
void * global_base = NULL;

static Elf64_Ehdr *
load_elf_buf(void *elf_buf)
Elf64_Ehdr *e = (Elf64_Ehdr *) elf_buf;
Elf64_Phdr *ptab = (Elf64_Phdr *) ((char *)elf_buf + e->e_phoff);
Elf64_Phdr *p;
size_t tot_len = 0;
void * ptr, * base = NULL;
int i, flags;

/* we could use e->e_type, but this way reduces our code requirement */
for (i = 0, p = ptab; i < e->e_phnum; i++, p++) {
if (!is_loaded(p))
if (is_txt_segt(p)) {
base = (void *)p->p_vaddr;
global_base = (void *)base;
printf("%d: the address %ld\n", i, (void *)base);
tot_len += ALIGN(p->p_memsz, p->p_align);

flags = base ? (FLAGS|MAP_FIXED) : FLAGS;

if ((ptr = mmap(base, tot_len, PROT_NONE, flags, -1, 0)) == MAP_FAILED)
return NULL;

global_ptr = (void *)ptr;
for (i = 0, p = ptab; i < e->e_phnum; i++, p++) {
void * load_addr;
size_t len;

if (!is_loaded(p))

flags = 0;

/* to reduce the code size we could rely on the fact that in
* implementation, the PF_ flags are the same as PROT_ */
if (p->p_flags & PF_X)
flags |= PROT_EXEC;
if (p->p_flags & PF_W)
flags |= PROT_WRITE;
if (p->p_flags & PF_R)
flags |= PROT_READ;

/* a very ugly way of figuring out what the base load address
* of this segment is. */
load_addr = ptr + (((void *)p->p_vaddr-base)&~(p->p_align-1));
len = ALIGN(p->p_memsz, p->p_align);

if (mprotect(load_addr, len, PROT_WRITE)) {
munmap(p, tot_len);
perror("mprotect(PROT_WRITE): ");
return (NULL);

/* We need the exact load address, not the rounded down
* version. Otherwis we copy to a garbage location.. */
memcpy((void *)(ptr + ((void *)p->p_vaddr - base)), (void *)elf_buf + p->p_offset, p->p_filesz);
perror("memcpy: ");
printf("%d: the address %ld\n", i, (void *)p->p_vaddr);

if (mprotect(load_addr, len, flags)) {
munmap(p, tot_len);
perror("mprotect(flags): ");
return NULL;

e = (Elf64_Ehdr *) ptr;

return (e);

int main()
int fd = -1;
char origld[256] = "/lib64/";
Elf64_Ehdr *ehdr = NULL;
Elf64_Phdr *phdr = NULL;
Elf64_Ehdr *e = NULL;
void (*entry)();
struct stat stat;

//system("/lib64/ ./hello");

fd = open(origld, O_RDONLY);
if (fd == -1) {
perror("fd open: ");
goto err;

if (fstat(fd, &stat) == -1) {
goto err;

ehdr = mmap(0, stat.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
if (ehdr == MAP_FAILED) {
perror("mmap ehdr");
goto err;
/* Check ELF magic-ident */
if (ehdr->e_ident[EI_MAG0] != 0x7f
|| ehdr->e_ident[EI_MAG1] != 'E'
|| ehdr->e_ident[EI_MAG2] != 'L'
|| ehdr->e_ident[EI_MAG3] != 'F'
) {
fprintf(stderr, "File type not supported\n");
goto err;

/* load the dynamic linker */
if ((e = load_elf_buf(ehdr)) == NULL) {
fprintf(stderr, "Can not load elf \n");
goto err;
//entry = (void(*)())(ehdr->e_entry + (unsigned long long)(global_ptr - global_base));
entry = (void(*)())ehdr->e_entry;

/* TODO : setup the stack */

/* transfer control to the new image */

if (ehdr) {
munmap(ehdr, stat.st_size);
if (fd != -1) {



Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are Off
Pingbacks are On
Refbacks are Off

Similar Threads
Thread Thread Starter Forum Replies Last Post
how can i speed up memcpy? Thinking Programming 9 10-14-2005 07:53 AM
gdb and mmap dcfnef Programming 8 09-30-2005 10:25 AM
memcpy problems alaios Programming 4 09-17-2005 07:26 AM
Need help: Seg fault, Memcpy, and dynamically allocated arrays benobi Programming 3 06-09-2005 10:58 PM
using mmap AngryLlama Programming 1 02-09-2005 08:53 AM

All times are GMT -5. The time now is 01:45 AM.

Main Menu
Write for LQ is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration