about summary refs log tree commit diff stats
path: root/kernel.soso/elf.c
blob: 7c74d50c7728060a892e5d3a622c1f84862ee134 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include "elf.h"
#include "common.h"
#include "process.h"
#include "screen.h"

BOOL isElf(char *elfData)
{
    Elf32_Ehdr *hdr = (Elf32_Ehdr *) elfData;

    if (hdr->e_ident[0] == 0x7f && hdr->e_ident[1] == 'E' &&
        hdr->e_ident[2] == 'L' && hdr->e_ident[3] == 'F')
    {
        return TRUE;
    }

    return FALSE;
}

uint32 loadElf(char *elfData)
{
    uint32 v_begin, v_end;
    Elf32_Ehdr *hdr;
    Elf32_Phdr *p_entry;
    Elf32_Scdr *s_entry;

    hdr = (Elf32_Ehdr *) elfData;
    p_entry = (Elf32_Phdr *) (elfData + hdr->e_phoff);

    s_entry = (Elf32_Scdr*) (elfData + hdr->e_shoff);

    if (isElf(elfData)==FALSE)
    {
        return 0;
    }

    for (int pe = 0; pe < hdr->e_phnum; pe++, p_entry++)
    {
        //Read each entry
        printkf("loading p_entry %d\n", pe);

        if (p_entry->p_type == PT_LOAD)
        {
            v_begin = p_entry->p_vaddr;
            v_end = p_entry->p_vaddr + p_entry->p_memsz;
            printkf("p_entry: %x\n", v_begin);
            if (v_begin < USER_OFFSET)
            {
                printkf("INFO: loadElf(): can't load executable below %x\n", USER_OFFSET);
                return 0;
            }

            if (v_end > USER_STACK)
            {
                printkf("INFO: loadElf(): can't load executable above %x\n", USER_STACK);
                return 0;
            }

            //printkf("ELF: entry flags: %x (%d)\n", p_entry->p_flags, p_entry->p_flags);


            printkf("about to memcpy\n");
            memcpy((uint8 *) v_begin, (uint8 *) (elfData + p_entry->p_offset), p_entry->p_filesz);
            printkf("done with memcpy\n");
            if (p_entry->p_memsz > p_entry->p_filesz)
            {
                char* p = (char *) p_entry->p_vaddr;
                for (int i = p_entry->p_filesz; i < (int)(p_entry->p_memsz); i++)
                {
                    p[i] = 0;
                }
            }
        }
    }

    //entry point
    printkf("done loading ELF\n");
    return hdr->e_entry;
}