OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [fs/] [binfmt_elf.c] - Blame information for rev 852

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 * linux/fs/binfmt_elf.c
3
 *
4
 * These are the functions used to load ELF format executables as used
5
 * on SVr4 machines.  Information on the format may be found in the book
6
 * "UNIX SYSTEM V RELEASE 4 Programmers Guide: Ansi C and Programming Support
7
 * Tools".
8
 *
9
 * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
10
 */
11
 
12
#include <linux/module.h>
13
 
14
#include <linux/fs.h>
15
#include <linux/stat.h>
16
#include <linux/sched.h>
17
#include <linux/mm.h>
18
#include <linux/mman.h>
19
#include <linux/a.out.h>
20
#include <linux/errno.h>
21
#include <linux/signal.h>
22
#include <linux/binfmts.h>
23
#include <linux/string.h>
24
#include <linux/fcntl.h>
25
#include <linux/ptrace.h>
26
#include <linux/malloc.h>
27
#include <linux/shm.h>
28
#include <linux/personality.h>
29
#include <linux/elfcore.h>
30
 
31
#include <asm/segment.h>
32
#include <asm/pgtable.h>
33
 
34
#include <linux/config.h>
35
 
36
#define DLINFO_ITEMS 12
37
 
38
#include <linux/elf.h>
39
 
40 707 simons
#define JUMP_TO_MAIN 0
41 718 simons
#define STACK_SIZE (32*PAGE_SIZE)
42 199 simons
 
43
static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs);
44
 
45
#define ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ELF_EXEC_PAGESIZE-1))
46
#define ELF_PAGEOFFSET(_v) ((_v) & (ELF_EXEC_PAGESIZE-1))
47
 
48
static struct linux_binfmt elf_format =
49
{
50
#ifndef MODULE
51
        NULL, NULL, load_elf_binary, NULL, NULL
52
#else
53
  NULL, &mod_use_count_, load_elf_binary, load_elf_library, elf_core_dump
54
#endif
55
};
56
 
57
struct sec_add {
58
        unsigned long pm_add;
59
        unsigned long vm_add;
60
        int len;
61
} sec[ELF_SECTION_NB];
62
 
63
unsigned short *or32_consth_add = (unsigned short *)NULL;
64
unsigned long or32_consth_rel;
65
 
66 707 simons
#if JUMP_TO_MAIN
67 199 simons
unsigned long *create_elf_tables(char *p, int argc, int envc, struct pt_regs *regs)
68
{
69
        unsigned long *argv, *envp;
70
        unsigned long *sp;
71
 
72
        /*
73
         * Force 16 byte alignment here for generality.
74
         */
75
        sp = (unsigned long *) (~15UL & (unsigned long) p);
76
        sp -= 2;
77
        sp -= envc + 1;
78
        envp = sp;
79
        sp -= argc + 1;
80
        argv = sp;
81
 
82
        regs->gprs[1] = argc;
83
        put_user((unsigned long) argc, --sp);
84
        current->mm->arg_start = (unsigned long) p;
85
        regs->gprs[2] = (unsigned long) argv;
86
        while (argc-- > 0) {
87
                put_user(p, argv++);
88
                while (get_user(p++))   /* nothing */
89
                        ;
90
        }
91
        put_user(0, argv);
92
        current->mm->arg_end = current->mm->env_start = (unsigned long) p;
93
        regs->gprs[3] = (unsigned long) envp;
94
        while (envc-- > 0) {
95
                put_user(p, envp++);
96
                while (get_user(p++))   /* nothing */
97
                        ;
98
        }
99
        put_user(0, envp);
100
        current->mm->env_end = (unsigned long) p;
101
        return sp;
102
}
103 707 simons
#else
104
unsigned long *create_elf_tables(char *p, int argc, int envc, struct pt_regs *regs)
105
{
106
        unsigned long *argv, *envp;
107
        unsigned long *sp;
108 199 simons
 
109 707 simons
        /*
110
         * Force 16 byte alignment here for generality.
111
         */
112
        sp = (unsigned long *) (~15UL & (unsigned long) p);
113
        sp -= 2;
114
        sp -= envc + 1;
115
        envp = sp;
116
        sp -= argc + 1;
117
        argv = sp;
118
 
119
        regs->gprs[1] = sp;
120
        put_user((unsigned long) argc, --sp);
121
        current->mm->arg_start = (unsigned long) p;
122
        while (argc-- > 0) {
123
                put_user(p, argv++);
124
                while (get_user(p++))   /* nothing */
125
                        ;
126
        }
127
        put_user(0, argv);
128
        current->mm->arg_end = current->mm->env_start = (unsigned long) p;
129
        while (envc-- > 0) {
130
                put_user(p, envp++);
131
                while (get_user(p++))   /* nothing */
132
                        ;
133
        }
134
        put_user(0, envp);
135
        current->mm->env_end = (unsigned long) p;
136
        return sp;
137
}
138
#endif
139
 
140 199 simons
static unsigned long putstring(unsigned long p, char * string)
141
{
142
        unsigned long l = strlen(string)+1;
143
        p -= l;
144
        memcpy((void*)p, string, l);
145
        return p;
146
}
147
 
148
static unsigned long putstringarray(unsigned long p, int count, char ** array)
149
{
150
        while(count) {
151
                p=putstring(p, array[--count]);
152
        }
153
        return p;
154
}
155
 
156 701 simons
static unsigned long stringarraylen(int count, char ** array)
157
{
158
        int l = 4;
159
        while(count) {
160
                l += strlen(array[--count]);
161
                l++;
162
                l+=4;
163
        }
164
        return l;
165
}
166
 
167 199 simons
int do_relocate(int dst_indx,
168
                int rel_nb,
169
                struct elf32_rel *rel_ptr,
170
                struct elf32_sym *sym_ptr,
171
                struct sec_add *sec)
172
{
173
        struct elf32_sym *sym_tab;
174
        void *rel_loc;
175
        unsigned long tmp;
176
        int src_indx;
177
        int i;
178
 
179
        for(i = 0; i < rel_nb; i++, rel_ptr++) {
180 707 simons
 
181 199 simons
                /* Symbol tab */
182
                sym_tab = sym_ptr + (rel_ptr->r_info >> 8);
183
                /* Section index of section that contains symbol */
184
                src_indx = sym_tab->st_shndx;
185
                /* Location in physical memory to which this relocation
186
                   is refering to */
187
                rel_loc = (void *)(rel_ptr->r_offset + sec[dst_indx].pm_add);
188
                if((rel_ptr->r_info & 0x000000ff) == R_OR32_32) {
189 852 simons
_print("R_OR32_32:       rel_loc %.8lx vm_add = %.8lx pm_add = %.8lx val = %.8lx\n", rel_loc, sec[src_indx].vm_add, sec[src_indx].pm_add, sym_tab->st_value);
190 199 simons
                        *(unsigned long *)rel_loc = *(unsigned long *)rel_loc
191
                                                - sec[src_indx].vm_add
192 852 simons
                                                + sec[src_indx].pm_add
193
                                                + sym_tab->st_value;
194 199 simons
                }
195
                else if((rel_ptr->r_info & 0x000000ff) == R_OR32_16) {
196 852 simons
_print("R_OR32_16:       rel_loc %.8lx vm_add = %.8lx pm_add = %.8lx\n", rel_loc, sec[src_indx].vm_add, sec[src_indx].pm_add);
197 199 simons
                        *(unsigned short *)rel_loc = *(unsigned short *)rel_loc
198
                                                - sec[src_indx].vm_add
199 852 simons
                                                + sec[src_indx].pm_add
200
                                                + sym_tab->st_value;
201 199 simons
                }
202
                else if((rel_ptr->r_info & 0x000000ff) == R_OR32_8) {
203 852 simons
_print("R_OR32_8:        rel_loc %.8lx vm_add = %.8lx pm_add = %.8lx\n", rel_loc, sec[src_indx].vm_add, sec[src_indx].pm_add);
204 199 simons
                        *(unsigned char *)rel_loc = *(unsigned char *)rel_loc
205
                                                - sec[src_indx].vm_add
206 852 simons
                                                + sec[src_indx].pm_add
207
                                                + sym_tab->st_value;
208 199 simons
                }
209
                else if((rel_ptr->r_info & 0x000000ff) == R_OR32_CONSTH) {
210 852 simons
_print("R_OR32_CONSTH:   rel_loc %.8lx *rel_loc %.8lx\n", rel_loc, *(((unsigned short *)rel_loc) + 1));
211
_print("                 vm_add  %.8lx pm_add   %.8lx\n", sec[src_indx].vm_add, sec[src_indx].pm_add);
212 199 simons
                        or32_consth_add = (((unsigned short *)rel_loc) + 1);
213
                        or32_consth_rel = *or32_consth_add << 16;
214
                }
215
                else if((rel_ptr->r_info & 0x000000ff) == R_OR32_CONST) {
216 852 simons
_print("R_OR32_CONST:    rel_loc %.8lx *rel_loc %.8lx\n", rel_loc, *(((unsigned short *)rel_loc) + 1));
217
_print("                 vm_add  %.8lx pm_add   %.8lx\n", sec[src_indx].vm_add, sec[src_indx].pm_add);
218
_print("                 consth  %.8lx st_value %.8lx\n", or32_consth_rel, sym_tab->st_value);
219
 
220 199 simons
                        tmp = or32_consth_rel | *(((unsigned short *)rel_loc) + 1);
221 852 simons
                        tmp = tmp + sym_tab->st_value - sec[src_indx].vm_add +
222 199 simons
                                                sec[src_indx].pm_add;
223
                        *(((unsigned short *)rel_loc) + 1) = tmp & 0x0000ffff;
224
                        if(or32_consth_add != (unsigned short *)NULL) {
225
                                *or32_consth_add = tmp >> 16;
226
                                or32_consth_add = (unsigned short *)NULL;
227
                                or32_consth_rel = 0;
228
                        }
229
                }
230
                else if((rel_ptr->r_info & 0x000000ff) == R_OR32_JUMPTARG) {
231 852 simons
_print("R_OR32_JUMPTARG: rel_loc %.8lx vm_add = %.8lx pm_add = %.8lx\n", rel_loc, sec[src_indx].vm_add, sec[src_indx].pm_add);
232
_print("                 pm_add  %.8lx\n", sec[dst_indx].pm_add);
233 199 simons
                        tmp = ((*(unsigned long *)rel_loc) & 0x03ffffff);
234
                        tmp = (tmp & 0x02000000) ? (tmp | 0xfc000000) : tmp;
235
                        tmp = tmp + ((sym_tab->st_value -
236
                                sec[src_indx].vm_add +
237
                                sec[src_indx].pm_add -
238
                                sec[dst_indx].pm_add) >> 2);
239
                        *(unsigned long *)rel_loc =
240
                                ((*(unsigned long *)rel_loc) & 0xfc000000) |
241
                                (tmp & 0x03ffffff);
242
                }
243
                else {
244
                        return -ELNRNG;
245
                }
246
        }
247
        return 0;
248
}
249
 
250 707 simons
#if JUMP_TO_MAIN
251 199 simons
unsigned long do_find_main(int sym_nb, struct elf32_sym *sym_prt, char *str_ptr)
252
{
253
        int i;
254
 
255
        for(i = 0; i < sym_nb; i++, sym_prt++) {
256
                if(sym_prt->st_name == 0)
257
                        continue;
258
 
259
                if(strcmp(&str_ptr[sym_prt->st_name], "_main") == 0)
260
                        return (sym_prt->st_value + sec[sym_prt->st_shndx].pm_add);
261
        }
262
        return 0;
263
}
264 707 simons
#else
265
unsigned long do_find_start(int sym_nb, struct elf32_sym *sym_prt, char *str_ptr)
266
{
267
        int i;
268
 
269
        for(i = 0; i < sym_nb; i++, sym_prt++) {
270
                if(sym_prt->st_name == 0)
271
                        continue;
272
 
273
                if(strcmp(&str_ptr[sym_prt->st_name], "_start") == 0)
274
                        return (sym_prt->st_value + sec[sym_prt->st_shndx].pm_add);
275
        }
276
        return 0;
277
}
278
#endif
279 199 simons
/*
280
 * These are the functions used to load ELF style executables and shared
281
 * libraries.  There is no binary dependent code anywhere else.
282
 */
283
 
284
#define INTERPRETER_NONE 0
285
#define INTERPRETER_AOUT 1
286
#define INTERPRETER_ELF 2
287
 
288
 
289
static inline int do_load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
290
{
291
        struct elfhdr elf_ex;
292
        struct file *file;
293
        int i,j;
294
        int old_fs;
295
        struct elf32_shdr *elf_spnt, *elf_shdata;
296
        int elf_exec_fileno;
297
        unsigned long elf_entry = 0;
298 701 simons
        unsigned long code_start, code_end, code_len = 0;
299
        unsigned long data_start, data_end, data_len = 0;
300
        unsigned long bss_start, bss_end, bss_len = 0;
301
        unsigned long stack_len = 0;
302 625 simons
        int rel_indx, symtab_indx = 0, strtab_indx = 0;
303 199 simons
        struct elf32_rel *rel_ptr;
304 625 simons
        struct elf32_sym *sym_ptr = (struct elf32_sym *)0;
305
        char *str_ptr = (char *)0;
306 199 simons
        int retval;
307
 
308
        or32_consth_add = 0;
309
        or32_consth_rel = 0;
310 701 simons
 
311
        current->personality = PER_LINUX;
312
 
313
        elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
314
 
315
        if (elf_exec_fileno < 0)
316
                return elf_exec_fileno;
317
 
318
        file = current->files->fd[elf_exec_fileno];
319
 
320
 
321 199 simons
        elf_ex = *((struct elfhdr *) bprm->buf);        /* exec-header */
322
 
323
        /* First of all, some simple consistency checks */
324
        if (elf_ex.e_type != ET_REL ||
325 701 simons
 
326
                        !bprm->inode->i_op ||
327
                        !bprm->inode->i_op->default_file_ops ||
328
                        !bprm->inode->i_op->default_file_ops->mmap ||
329
                        elf_ex.e_ident[0] != 0x7f ||
330
                        strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0) {
331 199 simons
                return -ENOEXEC;
332
        }
333
 
334 701 simons
        if (flush_old_exec(bprm)) {
335
                return -ENOMEM;
336
        }
337
 
338 199 simons
        if(elf_ex.e_shnum > ELF_SECTION_NB)
339
                return -ETOOMANYSECT;
340
 
341
        for(i = 0; i < ELF_SECTION_NB; i++)
342
                sec[i].len = 0;
343
 
344
        /* Now read in all of the header information */
345 701 simons
        elf_shdata = (struct elf32_shdr *) kmalloc(elf_ex.e_shnum *
346
                        elf_ex.e_shentsize, GFP_KERNEL);
347 199 simons
 
348 701 simons
        if (elf_shdata == NULL)
349 199 simons
                return -ENOMEM;
350 701 simons
 
351 199 simons
        retval = read_exec(bprm->inode, elf_ex.e_shoff, (char *) elf_shdata,
352
                           elf_ex.e_shentsize * elf_ex.e_shnum, 1);
353 701 simons
 
354 199 simons
        if (retval < 0) {
355
                kfree(elf_shdata);
356
                return retval;
357
        }
358
 
359
        /* OK, This is the point of no return */
360
 
361
        current->mm->end_data = 0;
362
        current->mm->end_code = 0;
363
 
364
        /* Now we do a little grungy work by mmaping the ELF image into
365
           the memory.  At this point, we assume that at a variable
366
           address. */
367
 
368
        old_fs = get_fs();
369
        set_fs(get_ds());
370
 
371 701 simons
        /* Calculate the total size of memory needed */
372 199 simons
        for(i = 0, elf_spnt = elf_shdata; i < elf_ex.e_shnum; i++, elf_spnt++) {
373 701 simons
                if(elf_spnt->sh_type == SHT_PROGBITS) {
374
                        if(elf_spnt->sh_flags & SHF_EXECINSTR)
375
                                code_len += (elf_spnt->sh_size + 3) & ~(3);
376
                        else if(elf_spnt->sh_flags & SHF_ALLOC)
377
                                data_len += (elf_spnt->sh_size + 3) & ~(3);
378
                }
379
                else if(elf_spnt->sh_type == SHT_NOBITS) {
380
                        if(elf_spnt->sh_flags & SHF_ALLOC)
381
                                bss_len += (elf_spnt->sh_size + 3) & ~(3);
382
                }
383
        }
384 199 simons
 
385 707 simons
        /* Make room on stack for arguments & environment */
386
        stack_len = STACK_SIZE;
387
        stack_len += strlen(bprm->filename) + 1;
388
        stack_len += stringarraylen(bprm->envc, bprm->envp);
389
        stack_len += stringarraylen(bprm->argc, bprm->argv);
390
 
391 701 simons
        /* Allocate space */
392
        retval = (unsigned long)do_mmap(NULL,
393
                                        0,
394
                                        code_len + code_len + bss_len + stack_len,
395
                                        PROT_EXEC | PROT_WRITE | PROT_READ,
396
                                        0,
397
                                        0);
398 199 simons
 
399 701 simons
        if(retval > (unsigned long)-4096) {
400
                kfree(elf_shdata);
401
                return retval;
402
        }
403 199 simons
 
404 701 simons
        code_start = retval;
405
        code_end = code_start;
406
        data_start = code_start + code_len;
407
        data_end = data_start;
408
        bss_start = data_start + data_len;
409
        bss_end = bss_start;
410
 
411
        current->mm->executable = 0;
412
 
413
        /* Now copy sections in memory */
414
 
415
        for(i = 0, elf_spnt = elf_shdata; i < elf_ex.e_shnum; i++, elf_spnt++) {
416
 
417
                if(elf_spnt->sh_type == SHT_PROGBITS && elf_spnt->sh_flags & SHF_EXECINSTR) {
418
 
419 707 simons
                        if(elf_spnt->sh_size == 0)
420
                                continue;
421
 
422 701 simons
                        retval = read_exec(bprm->inode, elf_spnt->sh_offset,
423
                                        (char *)code_end, elf_spnt->sh_size, 1);
424
 
425
                        if (retval < 0) {
426
                                do_munmap(code_start, code_len + code_len + bss_len + stack_len);
427 199 simons
                                kfree(elf_shdata);
428 701 simons
                                return retval;
429 199 simons
                        }
430 701 simons
 
431
                        sec[i].pm_add = code_end;
432
                        sec[i].vm_add = elf_spnt->sh_addr;
433 199 simons
 
434 701 simons
                        code_end = code_end + ((elf_spnt->sh_size + 3) & ~(3));
435
                }
436
                else if (elf_spnt->sh_type == SHT_PROGBITS && elf_spnt->sh_flags & SHF_ALLOC) {
437
 
438 707 simons
                        if(elf_spnt->sh_size == 0)
439
                                continue;
440
 
441 701 simons
                        retval = read_exec(bprm->inode, elf_spnt->sh_offset,
442
                                        (char *)data_end, elf_spnt->sh_size, 1);
443
 
444
                        if (retval < 0) {
445
                                do_munmap(code_start, code_len + code_len + bss_len + stack_len);
446
                                kfree(elf_shdata);
447
                                return retval;
448
                        }
449
 
450
                        sec[i].pm_add = data_end;
451 199 simons
                        sec[i].vm_add = elf_spnt->sh_addr;
452
 
453 701 simons
                        data_end = data_end + ((elf_spnt->sh_size + 3) & ~(3));
454 199 simons
                }
455 701 simons
                else if (elf_spnt->sh_type == SHT_NOBITS && elf_spnt->sh_flags & SHF_ALLOC) {
456
 
457 707 simons
                        if(elf_spnt->sh_size == 0)
458
                                continue;
459
 
460 701 simons
                        sec[i].pm_add = bss_end;
461
                        sec[i].vm_add = elf_spnt->sh_addr;
462
 
463
                        bss_end = bss_end + ((elf_spnt->sh_size + 3) & ~(3));
464
                }
465 199 simons
        }
466
 
467 701 simons
        /* Set bss and stack to zero */
468
        memset((void*)(bss_start), 0, bss_len + stack_len);
469
 
470 199 simons
        for(i = 0, elf_spnt = elf_shdata; i < elf_ex.e_shnum; elf_spnt++, i++) {
471
                if(elf_spnt->sh_type == SHT_SYMTAB && (elf_spnt->sh_size != 0)) {
472
                        struct elf32_shdr *link_shdr;
473
                        int sym_nb;
474
                        unsigned long retval;
475
 
476
                        /* Map symtab section */
477
                        retval = (unsigned long)do_mmap(NULL,
478
                                                        0,
479
                                                        elf_spnt->sh_size,
480
                                                        PROT_READ,
481
                                                        0,
482
                                                        0);
483
                        if(retval > (unsigned long)-4096) {
484
                                for(j = 0; j < elf_ex.e_shnum; j++)
485
                                                if(sec[j].len)
486
                                                        do_munmap(sec[j].pm_add, sec[j].len);
487 701 simons
                                do_munmap(code_start, code_len + code_len + bss_len + stack_len);
488 199 simons
                                kfree(elf_shdata);
489
                                return retval;
490
                        }
491
 
492 625 simons
                        symtab_indx = i;
493 199 simons
                        sec[symtab_indx].pm_add = retval;
494
                        sym_ptr = (struct elf32_sym *)retval;
495
                        sec[symtab_indx].len = elf_spnt->sh_size;
496
 
497
                        retval = read_exec(bprm->inode, elf_spnt->sh_offset,
498
                                        (char *)retval, elf_spnt->sh_size, 1);
499
                        if (retval < 0) {
500
                                for(j = 0; j < elf_ex.e_shnum; j++)
501
                                        if(sec[j].len)
502
                                                do_munmap(sec[j].pm_add, sec[j].len);
503 701 simons
                                do_munmap(code_start, code_len + code_len + bss_len + stack_len);
504 199 simons
                                kfree(elf_shdata);
505
                                return retval;
506
                        }
507
 
508
                        strtab_indx = elf_spnt->sh_link;
509
                        link_shdr = elf_shdata + strtab_indx;
510
 
511
                        /* Map strtab section */
512
                        retval = (unsigned long)do_mmap(NULL,
513
                                                        0,
514
                                                        link_shdr->sh_size,
515
                                                        PROT_READ,
516
                                                        0,
517
                                                        0);
518
                        if(retval > (unsigned long)-4096) {
519
                                for(j = 0; j < elf_ex.e_shnum; j++)
520
                                        if(sec[j].len)
521
                                                do_munmap(sec[j].pm_add, sec[j].len);
522 701 simons
                                do_munmap(code_start, code_len + code_len + bss_len + stack_len);
523
                                kfree(elf_shdata);
524
                                return retval;
525 199 simons
                        }
526
 
527
                        sec[strtab_indx].pm_add = retval;
528
                        str_ptr = (char *)retval;
529
                        sec[strtab_indx].len = link_shdr->sh_size;
530
 
531
                        retval = read_exec(bprm->inode, link_shdr->sh_offset,
532
                                        (char *)retval, link_shdr->sh_size, 1);
533
                        if (retval < 0) {
534
                                for(j = 0; j < elf_ex.e_shnum; j++)
535
                                        if(sec[j].len)
536
                                                do_munmap(sec[j].pm_add, sec[j].len);
537 701 simons
                                do_munmap(code_start, code_len + code_len + bss_len + stack_len);
538 199 simons
                                kfree(elf_shdata);
539
                                return retval;
540
                        }
541
 
542
                        sym_nb = sec[symtab_indx].len / sizeof(struct elf32_sym);
543 707 simons
#if JUMP_TO_MAIN
544 199 simons
                        elf_entry = do_find_main(sym_nb, sym_ptr, str_ptr);
545 707 simons
#else
546
                        elf_entry = do_find_start(sym_nb, sym_ptr, str_ptr);
547
#endif
548 199 simons
                        break;
549
                }
550
        }
551
 
552
        for(i = 0, elf_spnt = elf_shdata; i < elf_ex.e_shnum; elf_spnt++, i++) {
553
                if(elf_spnt->sh_type == SHT_REL && (elf_spnt->sh_size != 0)) {
554
                        struct elf32_shdr *link_shdr;
555
                        int rel_nb;
556
                        unsigned long retval;
557
 
558
                        /* Map rel section */
559
                        retval = (unsigned long)do_mmap(NULL,
560
                                                        0,
561
                                                        elf_spnt->sh_size,
562
                                                        PROT_READ,
563
                                                        0,
564
                                                        0);
565
                        if(retval > (unsigned long)-4096) {
566
                                for(j = 0; j < elf_ex.e_shnum; j++)
567
                                        if(sec[j].len)
568
                                                do_munmap(sec[j].pm_add, sec[j].len);
569 701 simons
                                do_munmap(code_start, code_len + code_len + bss_len + stack_len);
570
                                kfree(elf_shdata);
571
                                return retval;
572 199 simons
                        }
573
 
574
                        sec[i].pm_add = retval;
575
                        rel_ptr = (struct elf32_rel *)retval;
576
                        sec[i].len = elf_spnt->sh_size;
577
 
578
                        retval = read_exec(bprm->inode, elf_spnt->sh_offset,
579
                                        (char *)retval, elf_spnt->sh_size, 1);
580
                        if (retval < 0) {
581
                                for(j = 0; j < elf_ex.e_shnum; j++)
582
                                        if(sec[j].len)
583
                                                do_munmap(sec[j].pm_add, sec[j].len);
584 701 simons
                                do_munmap(code_start, code_len + code_len + bss_len + stack_len);
585 199 simons
                                kfree(elf_shdata);
586
                                return retval;
587
                        }
588
 
589
                        rel_indx = i;
590
                        link_shdr = elf_shdata + symtab_indx;
591
 
592
                        /* Now do relocations for the n-th section. n is read from
593
                           real setiona hader info field. */
594
 
595
                        rel_nb = sec[rel_indx].len / sizeof(struct elf32_rel);
596 625 simons
                        retval = do_relocate(elf_spnt->sh_info, rel_nb, rel_ptr, sym_ptr,  sec);
597 199 simons
 
598
                        if (retval < 0) {
599
                                for(j = 0; j < elf_ex.e_shnum; j++)
600
                                        if(sec[j].len)
601
                                                do_munmap(sec[j].pm_add, sec[j].len);
602 701 simons
                                do_munmap(code_start, code_len + code_len + bss_len + stack_len);
603 199 simons
                                kfree(elf_shdata);
604
                                return retval;
605
                        }
606
 
607
                        /* Now unmap rel section */
608
                        do_munmap(sec[rel_indx].pm_add, sec[rel_indx].len);
609
                        sec[rel_indx].len = 0;
610
                }
611
        }
612
 
613
        /* Now unmap sym and str sections */
614
        do_munmap(sec[symtab_indx].pm_add, sec[symtab_indx].len);
615
        sec[symtab_indx].len = 0;
616
        do_munmap(sec[strtab_indx].pm_add, sec[strtab_indx].len);
617
        sec[strtab_indx].len = 0;
618
 
619
        set_fs(old_fs);
620
        kfree(elf_shdata);
621
 
622
        if (current->exec_domain && current->exec_domain->use_count)
623
                (*current->exec_domain->use_count)--;
624
        if (current->binfmt && current->binfmt->use_count)
625
                (*current->binfmt->use_count)--;
626
        current->exec_domain = lookup_exec_domain(current->personality);
627
        current->binfmt = &elf_format;
628
        if (current->exec_domain && current->exec_domain->use_count)
629
                (*current->exec_domain->use_count)++;
630
        if (current->binfmt && current->binfmt->use_count)
631
                (*current->binfmt->use_count)++;
632
 
633 701 simons
        bprm->p = bss_end + stack_len - 4;
634 199 simons
 
635
        bprm->p = putstringarray(bprm->p, 1, &bprm->filename);
636
 
637
        bprm->p = putstringarray(bprm->p, bprm->envc, bprm->envp);
638
 
639
        bprm->p = putstringarray(bprm->p, bprm->argc, bprm->argv);
640
 
641
        current->suid = current->euid = current->fsuid = bprm->e_uid;
642
        current->sgid = current->egid = current->fsgid = bprm->e_gid;
643
        current->flags &= ~PF_FORKNOEXEC;
644
        bprm->p = (unsigned long)create_elf_tables((char *) bprm->p, bprm->argc, bprm->envc, regs);
645
 
646 701 simons
        current->mm->brk = bss_end;
647
        current->mm->start_code  = code_start;
648
        current->mm->end_code = code_end;
649
        current->mm->start_data  = data_start;
650
        current->mm->end_data = data_end;
651 199 simons
        current->mm->start_stack = bprm->p;
652
 
653 701 simons
_print("%s - %s:%d\n",__FILE__,__FUNCTION__,__LINE__);
654
_print("   start_code = %x\n", current->mm->start_code);
655
_print("   end_code = %x\n", current->mm->end_code);
656
_print("   start_data = %x\n", current->mm->start_data);
657
_print("   end_data = %x\n", current->mm->end_data);
658
_print("   start_brk = %x\n", current->mm->start_brk);
659
_print("   brk = %x\n", current->mm->brk);
660
_print("   start_stack = %x\n", current->mm->start_stack);
661
_print("   arg_start = %x\n", current->mm->arg_start);
662
_print("   env_start = %x\n", current->mm->env_start);
663
_print("   env_end = %x\n", current->mm->env_end);
664
_print("   elf_entry = %x\n", elf_entry);
665 199 simons
 
666
        start_thread(regs, elf_entry, bprm->p);
667
 
668
        if (current->flags & PF_PTRACED)
669
                send_sig(SIGTRAP, current, 0);
670
 
671
        return 0;
672
}
673
 
674
static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
675
{
676
        int retval;
677
 
678
        MOD_INC_USE_COUNT;
679
        retval = do_load_elf_binary(bprm, regs);
680
        MOD_DEC_USE_COUNT;
681
        return retval;
682
}
683
 
684
int init_elf_binfmt(void)
685
{
686
        return register_binfmt(&elf_format);
687
}
688
 
689
#ifdef MODULE
690
 
691
int init_module(void)
692
{
693
        /* Install the COFF, ELF and XOUT loaders.
694
         * N.B. We *rely* on the table being the right size with the
695
         * right number of free slots...
696
         */
697
        return init_elf_binfmt();
698
}
699
 
700
 
701
void cleanup_module(void)
702
{
703
        /* Remove the COFF and ELF loaders. */
704
        unregister_binfmt(&elf_format);
705
}
706
 
707
#endif

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.