Usermode/libc - Fixing some bugs in environment handling
[tpg/acess2.git] / AcessNative / ld-acess_src / elf_load.c
1 /*\r
2  * Acess v0.1\r
3  * ELF Executable Loader Code\r
4  */\r
5 #define DEBUG   1\r
6 #include <stdlib.h>\r
7 #include <stdio.h>\r
8 #include <string.h>\r
9 #include <unistd.h>\r
10 #include "common.h"\r
11 #include "elf32.h"\r
12 \r
13 #define DEBUG_WARN      1\r
14 \r
15 #define MKPTR(_type,_val)       ((_type*)(uintptr_t)(_val))\r
16 #define PTRMK(_type,_val)       MKPTR(_type,_val)\r
17 #define PTR(_val)       ((void*)(uintptr_t)(_val))\r
18 \r
19 #if DEBUG\r
20 # define ENTER(...)     printf("%s: ---- ENTER ----\n", __func__);\r
21 # define LOG(s, ...)    printf("%s: " s, __func__, __VA_ARGS__)\r
22 # define LOGS(s)        printf("%s: " s, __func__)\r
23 # define LEAVE(...)\r
24 #else\r
25 # define ENTER(...)\r
26 # define LOG(...)\r
27 # define LOGS(...)\r
28 # define LEAVE(...)\r
29 #endif\r
30 \r
31 // === PROTOTYPES ===\r
32 void    *Elf_Load(int FD);\r
33 void    *Elf32Load(int FD, Elf32_Ehdr *hdr);\r
34 \r
35 // === CODE ===\r
36 void *Elf_Load(int FD)\r
37 {\r
38         Elf32_Ehdr      hdr;\r
39         \r
40         // Read ELF Header\r
41         acess_read(FD, &hdr, sizeof(hdr));\r
42         \r
43         // Check the file type\r
44         if(hdr.e_ident[0] != 0x7F || hdr.e_ident[1] != 'E' || hdr.e_ident[2] != 'L' || hdr.e_ident[3] != 'F') {\r
45                 Warning("Non-ELF File was passed to the ELF loader\n");\r
46                 return NULL;\r
47         }\r
48 \r
49         switch(hdr.e_ident[4])\r
50         {\r
51         case ELFCLASS32:\r
52                 return Elf32Load(FD, &hdr);\r
53         default:\r
54                 return NULL;\r
55         }\r
56 }\r
57 void *Elf32Load(int FD, Elf32_Ehdr *hdr)\r
58 {\r
59         Elf32_Phdr      *phtab;\r
60          int    i;\r
61          int    iPageCount;\r
62         uint32_t        max, base;\r
63         uint32_t        addr;\r
64         uint32_t        baseDiff = 0;\r
65         \r
66         ENTER("iFD", FD);\r
67         \r
68         // Check for a program header\r
69         if(hdr->phoff == 0) {\r
70                 #if DEBUG_WARN\r
71                 Warning("ELF File does not contain a program header\n");\r
72                 #endif\r
73                 LEAVE('n');\r
74                 return NULL;\r
75         }\r
76         \r
77         // Read Program Header Table\r
78         phtab = malloc( sizeof(Elf32_Phdr) * hdr->phentcount );\r
79         if( !phtab ) {\r
80                 LEAVE('n');\r
81                 return NULL;\r
82         }\r
83         LOG("hdr.phoff = 0x%08x\n", hdr->phoff);\r
84         acess_seek(FD, hdr->phoff, ACESS_SEEK_SET);\r
85         acess_read(FD, phtab, sizeof(Elf32_Phdr) * hdr->phentcount);\r
86         \r
87         // Count Pages\r
88         iPageCount = 0;\r
89         LOG("hdr.phentcount = %i\n", hdr->phentcount);\r
90         for( i = 0; i < hdr->phentcount; i++ )\r
91         {\r
92                 // Ignore Non-LOAD types\r
93                 if(phtab[i].Type != PT_LOAD)\r
94                         continue;\r
95                 iPageCount += ((phtab[i].VAddr&0xFFF) + phtab[i].MemSize + 0xFFF) >> 12;\r
96                 LOG("phtab[%i] = {VAddr:0x%x, MemSize:0x%x}\n", i, phtab[i].VAddr, phtab[i].MemSize);\r
97         }\r
98         \r
99         LOG("iPageCount = %i\n", iPageCount);\r
100         \r
101         // Allocate Information Structure\r
102         //ret = malloc( sizeof(tBinary) + sizeof(tBinaryPage)*iPageCount );\r
103         // Fill Info Struct\r
104         //ret->Entry = hdr.entrypoint;\r
105         //ret->Base = -1;               // Set Base to maximum value\r
106         //ret->NumPages = iPageCount;\r
107         //ret->Interpreter = NULL;\r
108 \r
109         // Prescan for base and size\r
110         max = 0;\r
111         base = 0xFFFFFFFF;\r
112         for( i = 0; i < hdr->phentcount; i ++)\r
113         {\r
114                 if( phtab[i].Type != PT_LOAD )\r
115                         continue;\r
116                 if( phtab[i].VAddr < base )\r
117                         base = phtab[i].VAddr;\r
118                 if( phtab[i].VAddr + phtab[i].MemSize > max )\r
119                         max = phtab[i].VAddr + phtab[i].MemSize;\r
120         }\r
121 \r
122         LOG("base = %08x, max = %08x\n", base, max);\r
123 \r
124         if( base == 0 ) {\r
125                 // Find a nice space (31 address bits allowed)\r
126                 base = FindFreeRange( max, 31 );\r
127                 LOG("new base = %08x\n", base);\r
128                 if( base == 0 ) return NULL;\r
129                 baseDiff = base;\r
130         }\r
131         \r
132         // Load Pages\r
133         for( i = 0; i < hdr->phentcount; i++ )\r
134         {\r
135                 // Get Interpreter Name\r
136                 if( phtab[i].Type == PT_INTERP )\r
137                 {\r
138                         char *tmp;\r
139                         //if(ret->Interpreter)  continue;\r
140                         tmp = malloc(phtab[i].FileSize);\r
141                         acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
142                         acess_read(FD, tmp, phtab[i].FileSize);\r
143                         //ret->Interpreter = Binary_RegInterp(tmp);\r
144                         LOG("Interpreter '%s'\n", tmp);\r
145                         free(tmp);\r
146                         continue;\r
147                 }\r
148                 // Ignore non-LOAD types\r
149                 if(phtab[i].Type != PT_LOAD)    continue;\r
150                 \r
151                 LOG("phtab[%i] = PT_LOAD {Adj VAddr:0x%x, Offset:0x%x, FileSize:0x%x, MemSize:0x%x}\n",\r
152                         i, phtab[i].VAddr+baseDiff, phtab[i].Offset, phtab[i].FileSize, phtab[i].MemSize);\r
153                 \r
154                 addr = phtab[i].VAddr + baseDiff;\r
155 \r
156                 if( AllocateMemory( addr, phtab[i].MemSize ) ) {\r
157                         fprintf(stderr, "Elf_Load: Unable to map memory at %x (0x%x bytes)\n",\r
158                                 addr, phtab[i].MemSize);\r
159                         free( phtab );\r
160                         return NULL;\r
161                 }\r
162                 \r
163                 acess_seek(FD, phtab[i].Offset, ACESS_SEEK_SET);\r
164                 acess_read(FD, PTRMK(void, addr), phtab[i].FileSize);\r
165                 memset( PTRMK(char, addr) + phtab[i].FileSize, 0, phtab[i].MemSize - phtab[i].FileSize );\r
166         }\r
167         \r
168         // Clean Up\r
169         free(phtab);\r
170         // Return\r
171         LEAVE('p', base);\r
172         return PTRMK(void, base);\r
173 }\r

UCC git Repository :: git.ucc.asn.au