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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rc203soc/] [sw/] [uClinux/] [fs/] [binfmt_flat.c] - Blame information for rev 1777

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

Line No. Rev Author Line
1 1627 jcastillo
/*
2
 *  linux/fs/binfmt_flat.c
3
 *
4
 *  Copyright (C) 1998  Kenneth Albanowski <kjahds@kjahds.com>
5
 *                      The Silver Hammer Group, Ltd.
6
 *
7
 *  This is a relatively simple binary format, intended solely to contain
8
 *  the bare minimum needed to load and execute simple binaries, with
9
 *  special attention to executing from ROM, when possible.
10
 *
11
 *  Originally based on:
12
 *
13
 *  linux/fs/binfmt_aout.c
14
 *
15
 *  Copyright (C) 1991, 1992, 1996  Linus Torvalds
16
 */
17
 
18
 
19
#include <linux/module.h>
20
 
21
#include <linux/fs.h>
22
#include <linux/sched.h>
23
#include <linux/kernel.h>
24
#include <linux/mm.h>
25
#include <linux/mman.h>
26
#include <linux/a.out.h>
27
#include <linux/errno.h>
28
#include <linux/signal.h>
29
#include <linux/string.h>
30
#include <linux/stat.h>
31
#include <linux/fcntl.h>
32
#include <linux/ptrace.h>
33
#include <linux/user.h>
34
#include <linux/malloc.h>
35
#include <linux/binfmts.h>
36
#include <linux/personality.h>
37
 
38
#include <asm/system.h>
39
#include <asm/segment.h>
40
#include <asm/pgtable.h>
41
#include <asm/flat.h>
42
 
43
#undef DEBUG
44
 
45
static int load_flat_binary(struct linux_binprm *, struct pt_regs * regs);
46
 
47
extern void dump_thread(struct pt_regs *, struct user *);
48
 
49
static struct linux_binfmt flat_format = {
50
#ifndef MODULE
51
        NULL, NULL, load_flat_binary, NULL, NULL
52
#else
53
        NULL, &mod_use_count_, load_flat_binary, NULL, NULL
54
#endif
55
};
56
 
57
static unsigned long putstring(unsigned long p, char * string)
58
{
59
        unsigned long l = strlen(string)+1;
60
#ifdef DEBUG
61
        printk("put_string '%s'\n", string);
62
#endif
63
        p -= l;
64
        memcpy((void*)p, string, l);
65
        return p;
66
}
67
 
68
static unsigned long putstringarray(unsigned long p, int count, char ** array)
69
{
70
        /*p=putstring(p, "");*/
71
        /*printk("p1=%x, array=%x\n", p, array);
72
        printk("array[0]=%x\n", array[0]);*/
73
#ifdef DEBUG
74
        printk("putstringarray(%d)\n", count);
75
#endif
76
        while(count) {
77
                p=putstring(p, array[--count]);
78
#ifdef DEBUG
79
                printk("p2=%x\n", p);
80
#endif
81
        }
82
        return p;
83
}
84
 
85
static unsigned long stringarraylen(int count, char ** array)
86
{
87
        int l = 4;
88
        while(count) {
89
                l += strlen(array[--count]);
90
                l++;
91
                l+=4;
92
        }
93
        return l;
94
}
95
 
96
/*
97
 * create_flat_tables() parses the env- and arg-strings in new user
98
 * memory and creates the pointer tables from them, and puts their
99
 * addresses on the "stack", returning the new stack pointer value.
100
 */
101
static unsigned long create_flat_tables(unsigned long pp, struct linux_binprm * bprm)
102
{
103
        unsigned long *argv,*envp;
104
        unsigned long * sp;
105
        char * p = (char*)pp;
106
        int argc = bprm->argc;
107
        int envc = bprm->envc;
108
 
109
        sp = (unsigned long *) ((-(unsigned long)sizeof(char *)) & (unsigned long) p);
110
#ifdef __alpha__
111
/* whee.. test-programs are so much fun. */
112
        put_user(0, --sp);
113
        put_user(0, --sp);
114
        if (bprm->loader) {
115
                put_user(0, --sp);
116
                put_user(0x3eb, --sp);
117
                put_user(bprm->loader, --sp);
118
                put_user(0x3ea, --sp);
119
        }
120
        put_user(bprm->exec, --sp);
121
        put_user(0x3e9, --sp);
122
#endif
123
        sp -= envc+1;
124
        envp = sp;
125
        sp -= argc+1;
126
        argv = sp;
127
#if defined(__i386__) || defined(__mc68000__)
128
        put_user(envp,--sp);
129
        put_user(argv,--sp);
130
#endif
131
        put_user(argc,--sp);
132
        current->mm->arg_start = (unsigned long) p;
133
        while (argc-->0) {
134
                put_user(p,argv++);
135
                while (get_user(p++)) /* nothing */ ;
136
        }
137
        put_user(NULL,argv);
138
        current->mm->arg_end = current->mm->env_start = (unsigned long) p;
139
        while (envc-->0) {
140
                put_user(p,envp++);
141
                while (get_user(p++)) /* nothing */ ;
142
        }
143
        put_user(NULL,envp);
144
        current->mm->env_end = (unsigned long) p;
145
        return (unsigned long)sp;
146
}
147
 
148
void do_reloc(struct flat_reloc * r)
149
{
150
        unsigned long * ptr = (unsigned long*)
151
                (current->mm->start_data + r->offset);
152
 
153
 
154
#ifdef DEBUG
155
        printk("Relocation of variable at DATASEG+%x (address %p, currently %x) into segment %x+%x\n",
156
                r->offset, ptr, *ptr, r->type, *ptr);
157
 
158
        printk("TEXTSEG=%x, DATASEG=%x, BSSSEG=%x\n",
159
                current->mm->start_code,
160
                current->mm->start_data,
161
                current->mm->end_data);
162
 
163
        printk("Relocation type = %d, offset = %d\n", r->type, r->offset);
164
#endif
165
 
166
        switch (r->type) {
167
        case FLAT_RELOC_TYPE_TEXT:
168
                *ptr += current->mm->start_code;
169
                break;
170
        case FLAT_RELOC_TYPE_DATA:
171
                *ptr += current->mm->start_data;
172
                break;
173
        case FLAT_RELOC_TYPE_BSS:
174
                *ptr += current->mm->end_data;
175
                break;
176
        default:
177
                printk("Unknown relocation\n");
178
        }
179
 
180
 
181
#ifdef DEBUG
182
        printk("Relocation became %x\n", *ptr);
183
#endif
184
}
185
 
186
 
187
/*
188
 * These are the functions used to load a.out style executables and shared
189
 * libraries.  There is no binary dependent code anywhere else.
190
 */
191
 
192
inline int
193
do_load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
194
{
195
        struct flat_hdr * hdr;
196
        struct file * file;
197
        unsigned long error;
198
        unsigned long pos;
199
        unsigned long p = bprm->p;
200
        unsigned long data_len, bss_len, stack_len, code_len;
201
 
202
 
203
        current->personality = PER_LINUX;
204
 
205
        file = current->files->fd[open_inode(bprm->inode, O_RDONLY)];
206
 
207
#ifdef DEBUG
208
        printk("BINFMT_FLAT: Loading file: %x\n", file);
209
        show_free_areas();
210
#endif
211
 
212
        hdr = (struct flat_hdr*)bprm->buf;
213
 
214
        if (strncmp(hdr->magic, "bFLT", 4) || (hdr->rev != 2)) {
215
                printk("bad magic/rev (%ld, need %d)\n", hdr->rev, 2);
216
                return -ENOEXEC;
217
        }
218
 
219
        if (flush_old_exec(bprm)) {
220
                printk("unable to flush\n");
221
                return -ENOMEM;
222
        }
223
 
224
        /*printk("hdr->entry = %d, hdr->data_start = %d, hdr->data_end = %d, hdr->bss_end = %d, hdr->stack_size = %d\n",
225
                hdr->entry, hdr->data_start, hdr->data_end,
226
                hdr->bss_end, hdr->stack_size);*/
227
 
228
        /* OK, This is the point of no return */
229
 
230
        code_len = hdr->data_start;
231
        data_len = hdr->data_end - hdr->data_start;
232
        bss_len = hdr->bss_end - hdr->data_end;
233
        stack_len = hdr->stack_size;
234
 
235
        /* Make room on stack for arguments & environment */
236
        stack_len += strlen(bprm->filename) + 1;
237
        stack_len += stringarraylen(bprm->envc, bprm->envp);
238
        stack_len += stringarraylen(bprm->argc, bprm->argv);
239
 
240
        /*stack_len += 4-((pos+data_len+bss_len+stack_len) & 3);*/ /* Align stack */
241
 
242
        /*printk("Stack = %d, (%d)\n", stack_len, stack_len & 3);*/
243
 
244
        error = do_mmap(file,
245
                0,
246
               code_len + data_len + bss_len + stack_len,
247
               PROT_READ|PROT_EXEC | ((hdr->flags & FLAT_FLAG_RAM) ? PROT_WRITE : 0),
248
 
249
               0);
250
 
251
        if (error >= -4096) {
252
          printk("Unable to map flat executable, errno %d\n", (int)-error);
253
          return error; /* Beyond point of no return? Oh well... */
254
        }
255
 
256
#ifdef DEBUG
257
        printk("BINFMT_FLAT: mmap returned: %x\n", error);
258
        show_free_areas();
259
#endif
260
 
261
        current->mm->executable = 0;
262
 
263
        if (is_in_rom(error)) {
264
                unsigned long result;
265
#ifdef DEBUG
266
                printk("BINFMT_FLAT: ROM mapping of file\n");
267
#endif
268
                /* do_mmap returned a ROM mapping, so allocate RAM for data + bss + stack */
269
                /*pos = kmalloc(data_len+bss_len+stack_len, GFP_KERNEL);*/
270
                pos = do_mmap(0, 0, data_len+bss_len+stack_len, PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);
271
                if (pos >= (unsigned long)-4096) {
272
                        printk("Unable to allocate RAM for process, errno %d\n", (int)-pos);
273
                        return pos;
274
                }
275
 
276
#ifdef DEBUG
277
                printk("BINFMT_FLAT: Allocated data+bss+stack (%d bytes): %x\n", data_len+bss_len+stack_len, pos);
278
                show_free_areas();
279
#endif
280
 
281
                /* And then fill it in */
282
 
283
                /*printk("Reading data from %d-%d to %x\n", hdr->data_start, hdr->data_end - hdr->data_start, pos);*/
284
 
285
                result = read_exec(bprm->inode, hdr->data_start, (char *)pos,
286
                          data_len, 0);
287
                if (result >= (unsigned long)-4096) {
288
                          do_munmap(pos, 0);
289
                          printk("Unable to read data+bss, errno %d\n", (int)-result);
290
                }
291
 
292
                /*printk("Clearing %x to %x\n", pos+data_len, pos+data_len+bss_len+stack_len);*/
293
 
294
                memset((void*)(pos + data_len), 0, bss_len + stack_len);
295
 
296
                if (bprm->inode->i_sb->s_flags & MS_SYNCHRONOUS) {
297
#ifdef DEBUG
298
                        printk("Retaining inode\n");
299
#endif
300
                        current->mm->executable = bprm->inode;
301
                        bprm->inode->i_count++;
302
                }
303
 
304
        } else {
305
#ifdef DEBUG
306
                printk("BINFMT_FLAT: RAM mapping of file\n");
307
#endif
308
 
309
                /* Since we got a RAM mapping, mmap has already allocated a block for us, and
310
                   read in the data. . */
311
 
312
                pos = error + code_len;
313
 
314
        }
315
 
316
#ifdef DEBUG
317
        printk("ROM mapping is %x, Entry point is %x, data_start is %x\n", error, hdr->entry, hdr->data_start);
318
#endif
319
 
320
        current->mm->start_code = error + hdr->entry;
321
        current->mm->end_code = error + hdr->data_start;
322
        current->mm->start_data = pos;
323
 
324
        current->mm->end_data = pos + data_len;
325
        current->mm->brk = pos + data_len + bss_len;
326
 
327
        /*printk("start_code: %x, end_code: %x\n", current->mm->start_code,current->mm->end_code);
328
        printk("start_data: %x, end_data: %x\n", current->mm->start_data,current->mm->end_data);*/
329
 
330
        /*printk("Loaded flat file, BSS=%x, DATA=%x, TEXT=%x\n",
331
                current->mm->end_data,
332
                current->mm->start_data,
333
                current->mm->start_code);*/
334
 
335
        if (is_in_rom(error)) {
336
                int r;
337
                for(r=0;r<hdr->reloc_count;r++) {
338
                        struct flat_reloc * reloc = (struct flat_reloc*)
339
                                (error + hdr->reloc_start + (sizeof(struct flat_reloc)*r));
340
                        do_reloc(reloc);
341
                }
342
        } else {
343
                int r;
344
                for(r=0;r<hdr->reloc_count;r++) {
345
                        struct flat_reloc reloc;
346
                        unsigned long result = read_exec(bprm->inode,
347
                                hdr->reloc_start + (sizeof(struct flat_reloc)*r),
348
                                (char *)&reloc,
349
                                sizeof(struct flat_reloc),
350
                                0);
351
                        if (result >= (unsigned long)-4096) {
352
                                printk("Failure reloading relocation\n");
353
                        } else
354
                                do_reloc(&reloc);
355
                }
356
        }
357
 
358
        current->mm->rss = 0;
359
        current->suid = current->euid = current->fsuid = bprm->e_uid;
360
        current->sgid = current->egid = current->fsgid = bprm->e_gid;
361
        current->flags &= ~PF_FORKNOEXEC;
362
 
363
 
364
 
365
        /*for(i=0;i<16;i++) {
366
                printk("%.2x ", ((char*)pos)[i] & 0xff);
367
        }
368
        printk("\n");*/
369
 
370
 
371
 
372
        if (current->exec_domain && current->exec_domain->use_count)
373
                (*current->exec_domain->use_count)--;
374
        if (current->binfmt && current->binfmt->use_count)
375
                (*current->binfmt->use_count)--;
376
        current->exec_domain = lookup_exec_domain(current->personality);
377
        current->binfmt = &flat_format;
378
        if (current->exec_domain && current->exec_domain->use_count)
379
                (*current->exec_domain->use_count)++;
380
        if (current->binfmt && current->binfmt->use_count)
381
                (*current->binfmt->use_count)++;
382
 
383
        /*set_brk(current->mm->start_brk, current->mm->brk);*/
384
 
385
        p = pos + data_len + bss_len + stack_len - 4;
386
 
387
#ifdef DEBUG
388
        printk("p=%x\n", p);
389
#endif
390
 
391
        p = putstringarray(p, 1, &bprm->filename);
392
 
393
#ifdef DEBUG
394
        printk("p(filename)=%x\n", p);
395
#endif
396
 
397
        p = putstringarray(p, bprm->envc, bprm->envp);
398
 
399
#ifdef DEBUG
400
        printk("p(envp)=%x\n", p);
401
#endif
402
 
403
        p = putstringarray(p, bprm->argc, bprm->argv);
404
 
405
#ifdef DEBUG
406
        printk("p(argv)=%x\n", p);
407
#endif
408
 
409
        p = create_flat_tables(p, bprm);
410
 
411
#ifdef DEBUG
412
        printk("p(create_flat_tables)=%x\n", p);
413
 
414
        printk("arg_start = %x\n", current->mm->arg_start);
415
        printk("arg_end = %x\n", current->mm->arg_end);
416
        printk("env_start = %x\n", current->mm->env_start);
417
        printk("env_end = %x\n", current->mm->env_end);
418
#endif
419
 
420
        current->mm->start_stack = p;
421
 
422
        /*printk("start_stack: %x\n", current->mm->start_stack);*/
423
 
424
        /*(*(volatile unsigned char *)0xdeadbee0) = 1;*/
425
 
426
#ifdef DEBUG    
427
        show_free_areas();
428
#endif
429
 
430
        start_thread(regs, current->mm->start_code /*, current->mm->start_data*/ /*- hdr->data_start*/, p);
431
 
432
        if (current->flags & PF_PTRACED)
433
                send_sig(SIGTRAP, current, 0);
434
        return 0;
435
}
436
 
437
static int
438
load_flat_binary(struct linux_binprm * bprm, struct pt_regs * regs)
439
{
440
        int retval;
441
 
442
        MOD_INC_USE_COUNT;
443
        retval = do_load_flat_binary(bprm, regs);
444
        MOD_DEC_USE_COUNT;
445
        return retval;
446
}
447
 
448
int init_flat_binfmt(void) {
449
        return register_binfmt(&flat_format);
450
}
451
 
452
#ifdef MODULE
453
int init_module(void) {
454
        return init_flat_binfmt();
455
}
456
 
457
void cleanup_module( void) {
458
        unregister_binfmt(&flat_format);
459
}
460
#endif
461
 

powered by: WebSVN 2.1.0

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