~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to bsd-user/elfload.c

  • Committer: pbrook
  • Date: 2007-03-04 00:52:16 UTC
  • Revision ID: git-v1:7a2d6d9650ed16b2cdb0b4876fe9efce7ef8ea6d
64bit->win32 cross build fix.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2467 c046a42c-6fe2-441c-8c8c-71466251a162

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* This is the Linux kernel elf-loading code, ported into user space */
2
 
 
3
 
#include <stdio.h>
4
 
#include <sys/types.h>
5
 
#include <fcntl.h>
6
 
#include <errno.h>
7
 
#include <unistd.h>
8
 
#include <sys/mman.h>
9
 
#include <stdlib.h>
10
 
#include <string.h>
11
 
 
12
 
#include "qemu.h"
13
 
#include "disas.h"
14
 
 
15
 
#ifdef __powerpc64__
16
 
#undef ARCH_DLINFO
17
 
#undef ELF_PLATFORM
18
 
#undef ELF_HWCAP
19
 
#undef ELF_CLASS
20
 
#undef ELF_DATA
21
 
#undef ELF_ARCH
22
 
#endif
23
 
 
24
 
/* from personality.h */
25
 
 
26
 
/*
27
 
 * Flags for bug emulation.
28
 
 *
29
 
 * These occupy the top three bytes.
30
 
 */
31
 
enum {
32
 
        ADDR_NO_RANDOMIZE =     0x0040000,      /* disable randomization of VA space */
33
 
        FDPIC_FUNCPTRS =        0x0080000,      /* userspace function ptrs point to descriptors
34
 
                                                 * (signal handling)
35
 
                                                 */
36
 
        MMAP_PAGE_ZERO =        0x0100000,
37
 
        ADDR_COMPAT_LAYOUT =    0x0200000,
38
 
        READ_IMPLIES_EXEC =     0x0400000,
39
 
        ADDR_LIMIT_32BIT =      0x0800000,
40
 
        SHORT_INODE =           0x1000000,
41
 
        WHOLE_SECONDS =         0x2000000,
42
 
        STICKY_TIMEOUTS =       0x4000000,
43
 
        ADDR_LIMIT_3GB =        0x8000000,
44
 
};
45
 
 
46
 
/*
47
 
 * Personality types.
48
 
 *
49
 
 * These go in the low byte.  Avoid using the top bit, it will
50
 
 * conflict with error returns.
51
 
 */
52
 
enum {
53
 
        PER_LINUX =             0x0000,
54
 
        PER_LINUX_32BIT =       0x0000 | ADDR_LIMIT_32BIT,
55
 
        PER_LINUX_FDPIC =       0x0000 | FDPIC_FUNCPTRS,
56
 
        PER_SVR4 =              0x0001 | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
57
 
        PER_SVR3 =              0x0002 | STICKY_TIMEOUTS | SHORT_INODE,
58
 
        PER_SCOSVR3 =           0x0003 | STICKY_TIMEOUTS |
59
 
                                         WHOLE_SECONDS | SHORT_INODE,
60
 
        PER_OSR5 =              0x0003 | STICKY_TIMEOUTS | WHOLE_SECONDS,
61
 
        PER_WYSEV386 =          0x0004 | STICKY_TIMEOUTS | SHORT_INODE,
62
 
        PER_ISCR4 =             0x0005 | STICKY_TIMEOUTS,
63
 
        PER_BSD =               0x0006,
64
 
        PER_SUNOS =             0x0006 | STICKY_TIMEOUTS,
65
 
        PER_XENIX =             0x0007 | STICKY_TIMEOUTS | SHORT_INODE,
66
 
        PER_LINUX32 =           0x0008,
67
 
        PER_LINUX32_3GB =       0x0008 | ADDR_LIMIT_3GB,
68
 
        PER_IRIX32 =            0x0009 | STICKY_TIMEOUTS,/* IRIX5 32-bit */
69
 
        PER_IRIXN32 =           0x000a | STICKY_TIMEOUTS,/* IRIX6 new 32-bit */
70
 
        PER_IRIX64 =            0x000b | STICKY_TIMEOUTS,/* IRIX6 64-bit */
71
 
        PER_RISCOS =            0x000c,
72
 
        PER_SOLARIS =           0x000d | STICKY_TIMEOUTS,
73
 
        PER_UW7 =               0x000e | STICKY_TIMEOUTS | MMAP_PAGE_ZERO,
74
 
        PER_OSF4 =              0x000f,                  /* OSF/1 v4 */
75
 
        PER_HPUX =              0x0010,
76
 
        PER_MASK =              0x00ff,
77
 
};
78
 
 
79
 
/*
80
 
 * Return the base personality without flags.
81
 
 */
82
 
#define personality(pers)       (pers & PER_MASK)
83
 
 
84
 
/* this flag is uneffective under linux too, should be deleted */
85
 
#ifndef MAP_DENYWRITE
86
 
#define MAP_DENYWRITE 0
87
 
#endif
88
 
 
89
 
/* should probably go in elf.h */
90
 
#ifndef ELIBBAD
91
 
#define ELIBBAD 80
92
 
#endif
93
 
 
94
 
#ifdef TARGET_I386
95
 
 
96
 
#define ELF_PLATFORM get_elf_platform()
97
 
 
98
 
static const char *get_elf_platform(void)
99
 
{
100
 
    static char elf_platform[] = "i386";
101
 
    int family = (thread_env->cpuid_version >> 8) & 0xff;
102
 
    if (family > 6)
103
 
        family = 6;
104
 
    if (family >= 3)
105
 
        elf_platform[1] = '0' + family;
106
 
    return elf_platform;
107
 
}
108
 
 
109
 
#define ELF_HWCAP get_elf_hwcap()
110
 
 
111
 
static uint32_t get_elf_hwcap(void)
112
 
{
113
 
  return thread_env->cpuid_features;
114
 
}
115
 
 
116
 
#ifdef TARGET_X86_64
117
 
#define ELF_START_MMAP 0x2aaaaab000ULL
118
 
#define elf_check_arch(x) ( ((x) == ELF_ARCH) )
119
 
 
120
 
#define ELF_CLASS      ELFCLASS64
121
 
#define ELF_DATA       ELFDATA2LSB
122
 
#define ELF_ARCH       EM_X86_64
123
 
 
124
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
125
 
{
126
 
    regs->rax = 0;
127
 
    regs->rsp = infop->start_stack;
128
 
    regs->rip = infop->entry;
129
 
}
130
 
 
131
 
#else
132
 
 
133
 
#define ELF_START_MMAP 0x80000000
134
 
 
135
 
/*
136
 
 * This is used to ensure we don't load something for the wrong architecture.
137
 
 */
138
 
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
139
 
 
140
 
/*
141
 
 * These are used to set parameters in the core dumps.
142
 
 */
143
 
#define ELF_CLASS       ELFCLASS32
144
 
#define ELF_DATA        ELFDATA2LSB
145
 
#define ELF_ARCH        EM_386
146
 
 
147
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
148
 
{
149
 
    regs->esp = infop->start_stack;
150
 
    regs->eip = infop->entry;
151
 
 
152
 
    /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
153
 
       starts %edx contains a pointer to a function which might be
154
 
       registered using `atexit'.  This provides a mean for the
155
 
       dynamic linker to call DT_FINI functions for shared libraries
156
 
       that have been loaded before the code runs.
157
 
 
158
 
       A value of 0 tells we have no such handler.  */
159
 
    regs->edx = 0;
160
 
}
161
 
#endif
162
 
 
163
 
#define USE_ELF_CORE_DUMP
164
 
#define ELF_EXEC_PAGESIZE       4096
165
 
 
166
 
#endif
167
 
 
168
 
#ifdef TARGET_ARM
169
 
 
170
 
#define ELF_START_MMAP 0x80000000
171
 
 
172
 
#define elf_check_arch(x) ( (x) == EM_ARM )
173
 
 
174
 
#define ELF_CLASS       ELFCLASS32
175
 
#ifdef TARGET_WORDS_BIGENDIAN
176
 
#define ELF_DATA        ELFDATA2MSB
177
 
#else
178
 
#define ELF_DATA        ELFDATA2LSB
179
 
#endif
180
 
#define ELF_ARCH        EM_ARM
181
 
 
182
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
183
 
{
184
 
    abi_long stack = infop->start_stack;
185
 
    memset(regs, 0, sizeof(*regs));
186
 
    regs->ARM_cpsr = 0x10;
187
 
    if (infop->entry & 1)
188
 
      regs->ARM_cpsr |= CPSR_T;
189
 
    regs->ARM_pc = infop->entry & 0xfffffffe;
190
 
    regs->ARM_sp = infop->start_stack;
191
 
    /* FIXME - what to for failure of get_user()? */
192
 
    get_user_ual(regs->ARM_r2, stack + 8); /* envp */
193
 
    get_user_ual(regs->ARM_r1, stack + 4); /* envp */
194
 
    /* XXX: it seems that r0 is zeroed after ! */
195
 
    regs->ARM_r0 = 0;
196
 
    /* For uClinux PIC binaries.  */
197
 
    /* XXX: Linux does this only on ARM with no MMU (do we care ?) */
198
 
    regs->ARM_r10 = infop->start_data;
199
 
}
200
 
 
201
 
#define USE_ELF_CORE_DUMP
202
 
#define ELF_EXEC_PAGESIZE       4096
203
 
 
204
 
enum
205
 
{
206
 
  ARM_HWCAP_ARM_SWP       = 1 << 0,
207
 
  ARM_HWCAP_ARM_HALF      = 1 << 1,
208
 
  ARM_HWCAP_ARM_THUMB     = 1 << 2,
209
 
  ARM_HWCAP_ARM_26BIT     = 1 << 3,
210
 
  ARM_HWCAP_ARM_FAST_MULT = 1 << 4,
211
 
  ARM_HWCAP_ARM_FPA       = 1 << 5,
212
 
  ARM_HWCAP_ARM_VFP       = 1 << 6,
213
 
  ARM_HWCAP_ARM_EDSP      = 1 << 7,
214
 
};
215
 
 
216
 
#define ELF_HWCAP (ARM_HWCAP_ARM_SWP | ARM_HWCAP_ARM_HALF              \
217
 
                    | ARM_HWCAP_ARM_THUMB | ARM_HWCAP_ARM_FAST_MULT     \
218
 
                    | ARM_HWCAP_ARM_FPA | ARM_HWCAP_ARM_VFP)
219
 
 
220
 
#endif
221
 
 
222
 
#ifdef TARGET_SPARC
223
 
#ifdef TARGET_SPARC64
224
 
 
225
 
#define ELF_START_MMAP 0x80000000
226
 
 
227
 
#ifndef TARGET_ABI32
228
 
#define elf_check_arch(x) ( (x) == EM_SPARCV9 || (x) == EM_SPARC32PLUS )
229
 
#else
230
 
#define elf_check_arch(x) ( (x) == EM_SPARC32PLUS || (x) == EM_SPARC )
231
 
#endif
232
 
 
233
 
#define ELF_CLASS   ELFCLASS64
234
 
#define ELF_DATA    ELFDATA2MSB
235
 
#define ELF_ARCH    EM_SPARCV9
236
 
 
237
 
#define STACK_BIAS              2047
238
 
 
239
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
240
 
{
241
 
#ifndef TARGET_ABI32
242
 
    regs->tstate = 0;
243
 
#endif
244
 
    regs->pc = infop->entry;
245
 
    regs->npc = regs->pc + 4;
246
 
    regs->y = 0;
247
 
#ifdef TARGET_ABI32
248
 
    regs->u_regs[14] = infop->start_stack - 16 * 4;
249
 
#else
250
 
    if (personality(infop->personality) == PER_LINUX32)
251
 
        regs->u_regs[14] = infop->start_stack - 16 * 4;
252
 
    else
253
 
        regs->u_regs[14] = infop->start_stack - 16 * 8 - STACK_BIAS;
254
 
#endif
255
 
}
256
 
 
257
 
#else
258
 
#define ELF_START_MMAP 0x80000000
259
 
 
260
 
#define elf_check_arch(x) ( (x) == EM_SPARC )
261
 
 
262
 
#define ELF_CLASS   ELFCLASS32
263
 
#define ELF_DATA    ELFDATA2MSB
264
 
#define ELF_ARCH    EM_SPARC
265
 
 
266
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
267
 
{
268
 
    regs->psr = 0;
269
 
    regs->pc = infop->entry;
270
 
    regs->npc = regs->pc + 4;
271
 
    regs->y = 0;
272
 
    regs->u_regs[14] = infop->start_stack - 16 * 4;
273
 
}
274
 
 
275
 
#endif
276
 
#endif
277
 
 
278
 
#ifdef TARGET_PPC
279
 
 
280
 
#define ELF_START_MMAP 0x80000000
281
 
 
282
 
#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
283
 
 
284
 
#define elf_check_arch(x) ( (x) == EM_PPC64 )
285
 
 
286
 
#define ELF_CLASS       ELFCLASS64
287
 
 
288
 
#else
289
 
 
290
 
#define elf_check_arch(x) ( (x) == EM_PPC )
291
 
 
292
 
#define ELF_CLASS       ELFCLASS32
293
 
 
294
 
#endif
295
 
 
296
 
#ifdef TARGET_WORDS_BIGENDIAN
297
 
#define ELF_DATA        ELFDATA2MSB
298
 
#else
299
 
#define ELF_DATA        ELFDATA2LSB
300
 
#endif
301
 
#define ELF_ARCH        EM_PPC
302
 
 
303
 
/*
304
 
 * We need to put in some extra aux table entries to tell glibc what
305
 
 * the cache block size is, so it can use the dcbz instruction safely.
306
 
 */
307
 
#define AT_DCACHEBSIZE          19
308
 
#define AT_ICACHEBSIZE          20
309
 
#define AT_UCACHEBSIZE          21
310
 
/* A special ignored type value for PPC, for glibc compatibility.  */
311
 
#define AT_IGNOREPPC            22
312
 
/*
313
 
 * The requirements here are:
314
 
 * - keep the final alignment of sp (sp & 0xf)
315
 
 * - make sure the 32-bit value at the first 16 byte aligned position of
316
 
 *   AUXV is greater than 16 for glibc compatibility.
317
 
 *   AT_IGNOREPPC is used for that.
318
 
 * - for compatibility with glibc ARCH_DLINFO must always be defined on PPC,
319
 
 *   even if DLINFO_ARCH_ITEMS goes to zero or is undefined.
320
 
 */
321
 
#define DLINFO_ARCH_ITEMS       5
322
 
#define ARCH_DLINFO                                                     \
323
 
do {                                                                    \
324
 
        NEW_AUX_ENT(AT_DCACHEBSIZE, 0x20);                              \
325
 
        NEW_AUX_ENT(AT_ICACHEBSIZE, 0x20);                              \
326
 
        NEW_AUX_ENT(AT_UCACHEBSIZE, 0);                                 \
327
 
        /*                                                              \
328
 
         * Now handle glibc compatibility.                              \
329
 
         */                                                             \
330
 
        NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);                        \
331
 
        NEW_AUX_ENT(AT_IGNOREPPC, AT_IGNOREPPC);                        \
332
 
 } while (0)
333
 
 
334
 
static inline void init_thread(struct target_pt_regs *_regs, struct image_info *infop)
335
 
{
336
 
    abi_ulong pos = infop->start_stack;
337
 
    abi_ulong tmp;
338
 
#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
339
 
    abi_ulong entry, toc;
340
 
#endif
341
 
 
342
 
    _regs->gpr[1] = infop->start_stack;
343
 
#if defined(TARGET_PPC64) && !defined(TARGET_ABI32)
344
 
    entry = ldq_raw(infop->entry) + infop->load_addr;
345
 
    toc = ldq_raw(infop->entry + 8) + infop->load_addr;
346
 
    _regs->gpr[2] = toc;
347
 
    infop->entry = entry;
348
 
#endif
349
 
    _regs->nip = infop->entry;
350
 
    /* Note that isn't exactly what regular kernel does
351
 
     * but this is what the ABI wants and is needed to allow
352
 
     * execution of PPC BSD programs.
353
 
     */
354
 
    /* FIXME - what to for failure of get_user()? */
355
 
    get_user_ual(_regs->gpr[3], pos);
356
 
    pos += sizeof(abi_ulong);
357
 
    _regs->gpr[4] = pos;
358
 
    for (tmp = 1; tmp != 0; pos += sizeof(abi_ulong))
359
 
        tmp = ldl(pos);
360
 
    _regs->gpr[5] = pos;
361
 
}
362
 
 
363
 
#define USE_ELF_CORE_DUMP
364
 
#define ELF_EXEC_PAGESIZE       4096
365
 
 
366
 
#endif
367
 
 
368
 
#ifdef TARGET_MIPS
369
 
 
370
 
#define ELF_START_MMAP 0x80000000
371
 
 
372
 
#define elf_check_arch(x) ( (x) == EM_MIPS )
373
 
 
374
 
#ifdef TARGET_MIPS64
375
 
#define ELF_CLASS   ELFCLASS64
376
 
#else
377
 
#define ELF_CLASS   ELFCLASS32
378
 
#endif
379
 
#ifdef TARGET_WORDS_BIGENDIAN
380
 
#define ELF_DATA        ELFDATA2MSB
381
 
#else
382
 
#define ELF_DATA        ELFDATA2LSB
383
 
#endif
384
 
#define ELF_ARCH    EM_MIPS
385
 
 
386
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
387
 
{
388
 
    regs->cp0_status = 2 << CP0St_KSU;
389
 
    regs->cp0_epc = infop->entry;
390
 
    regs->regs[29] = infop->start_stack;
391
 
}
392
 
 
393
 
#define USE_ELF_CORE_DUMP
394
 
#define ELF_EXEC_PAGESIZE        4096
395
 
 
396
 
#endif /* TARGET_MIPS */
397
 
 
398
 
#ifdef TARGET_SH4
399
 
 
400
 
#define ELF_START_MMAP 0x80000000
401
 
 
402
 
#define elf_check_arch(x) ( (x) == EM_SH )
403
 
 
404
 
#define ELF_CLASS ELFCLASS32
405
 
#define ELF_DATA  ELFDATA2LSB
406
 
#define ELF_ARCH  EM_SH
407
 
 
408
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
409
 
{
410
 
  /* Check other registers XXXXX */
411
 
  regs->pc = infop->entry;
412
 
  regs->regs[15] = infop->start_stack;
413
 
}
414
 
 
415
 
#define USE_ELF_CORE_DUMP
416
 
#define ELF_EXEC_PAGESIZE        4096
417
 
 
418
 
#endif
419
 
 
420
 
#ifdef TARGET_CRIS
421
 
 
422
 
#define ELF_START_MMAP 0x80000000
423
 
 
424
 
#define elf_check_arch(x) ( (x) == EM_CRIS )
425
 
 
426
 
#define ELF_CLASS ELFCLASS32
427
 
#define ELF_DATA  ELFDATA2LSB
428
 
#define ELF_ARCH  EM_CRIS
429
 
 
430
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
431
 
{
432
 
  regs->erp = infop->entry;
433
 
}
434
 
 
435
 
#define USE_ELF_CORE_DUMP
436
 
#define ELF_EXEC_PAGESIZE        8192
437
 
 
438
 
#endif
439
 
 
440
 
#ifdef TARGET_M68K
441
 
 
442
 
#define ELF_START_MMAP 0x80000000
443
 
 
444
 
#define elf_check_arch(x) ( (x) == EM_68K )
445
 
 
446
 
#define ELF_CLASS       ELFCLASS32
447
 
#define ELF_DATA        ELFDATA2MSB
448
 
#define ELF_ARCH        EM_68K
449
 
 
450
 
/* ??? Does this need to do anything?
451
 
#define ELF_PLAT_INIT(_r) */
452
 
 
453
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
454
 
{
455
 
    regs->usp = infop->start_stack;
456
 
    regs->sr = 0;
457
 
    regs->pc = infop->entry;
458
 
}
459
 
 
460
 
#define USE_ELF_CORE_DUMP
461
 
#define ELF_EXEC_PAGESIZE       8192
462
 
 
463
 
#endif
464
 
 
465
 
#ifdef TARGET_ALPHA
466
 
 
467
 
#define ELF_START_MMAP (0x30000000000ULL)
468
 
 
469
 
#define elf_check_arch(x) ( (x) == ELF_ARCH )
470
 
 
471
 
#define ELF_CLASS      ELFCLASS64
472
 
#define ELF_DATA       ELFDATA2MSB
473
 
#define ELF_ARCH       EM_ALPHA
474
 
 
475
 
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
476
 
{
477
 
    regs->pc = infop->entry;
478
 
    regs->ps = 8;
479
 
    regs->usp = infop->start_stack;
480
 
    regs->unique = infop->start_data; /* ? */
481
 
    printf("Set unique value to " TARGET_FMT_lx " (" TARGET_FMT_lx ")\n",
482
 
           regs->unique, infop->start_data);
483
 
}
484
 
 
485
 
#define USE_ELF_CORE_DUMP
486
 
#define ELF_EXEC_PAGESIZE        8192
487
 
 
488
 
#endif /* TARGET_ALPHA */
489
 
 
490
 
#ifndef ELF_PLATFORM
491
 
#define ELF_PLATFORM (NULL)
492
 
#endif
493
 
 
494
 
#ifndef ELF_HWCAP
495
 
#define ELF_HWCAP 0
496
 
#endif
497
 
 
498
 
#ifdef TARGET_ABI32
499
 
#undef ELF_CLASS
500
 
#define ELF_CLASS ELFCLASS32
501
 
#undef bswaptls
502
 
#define bswaptls(ptr) bswap32s(ptr)
503
 
#endif
504
 
 
505
 
#include "elf.h"
506
 
 
507
 
struct exec
508
 
{
509
 
  unsigned int a_info;   /* Use macros N_MAGIC, etc for access */
510
 
  unsigned int a_text;   /* length of text, in bytes */
511
 
  unsigned int a_data;   /* length of data, in bytes */
512
 
  unsigned int a_bss;    /* length of uninitialized data area, in bytes */
513
 
  unsigned int a_syms;   /* length of symbol table data in file, in bytes */
514
 
  unsigned int a_entry;  /* start address */
515
 
  unsigned int a_trsize; /* length of relocation info for text, in bytes */
516
 
  unsigned int a_drsize; /* length of relocation info for data, in bytes */
517
 
};
518
 
 
519
 
 
520
 
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
521
 
#define OMAGIC 0407
522
 
#define NMAGIC 0410
523
 
#define ZMAGIC 0413
524
 
#define QMAGIC 0314
525
 
 
526
 
/* max code+data+bss space allocated to elf interpreter */
527
 
#define INTERP_MAP_SIZE (32 * 1024 * 1024)
528
 
 
529
 
/* max code+data+bss+brk space allocated to ET_DYN executables */
530
 
#define ET_DYN_MAP_SIZE (128 * 1024 * 1024)
531
 
 
532
 
/* Necessary parameters */
533
 
#define TARGET_ELF_EXEC_PAGESIZE TARGET_PAGE_SIZE
534
 
#define TARGET_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(TARGET_ELF_EXEC_PAGESIZE-1))
535
 
#define TARGET_ELF_PAGEOFFSET(_v) ((_v) & (TARGET_ELF_EXEC_PAGESIZE-1))
536
 
 
537
 
#define INTERPRETER_NONE 0
538
 
#define INTERPRETER_AOUT 1
539
 
#define INTERPRETER_ELF 2
540
 
 
541
 
#define DLINFO_ITEMS 12
542
 
 
543
 
static inline void memcpy_fromfs(void * to, const void * from, unsigned long n)
544
 
{
545
 
        memcpy(to, from, n);
546
 
}
547
 
 
548
 
extern unsigned long x86_stack_size;
549
 
 
550
 
static int load_aout_interp(void * exptr, int interp_fd);
551
 
 
552
 
#ifdef BSWAP_NEEDED
553
 
static void bswap_ehdr(struct elfhdr *ehdr)
554
 
{
555
 
    bswap16s(&ehdr->e_type);                    /* Object file type */
556
 
    bswap16s(&ehdr->e_machine);         /* Architecture */
557
 
    bswap32s(&ehdr->e_version);         /* Object file version */
558
 
    bswaptls(&ehdr->e_entry);           /* Entry point virtual address */
559
 
    bswaptls(&ehdr->e_phoff);           /* Program header table file offset */
560
 
    bswaptls(&ehdr->e_shoff);           /* Section header table file offset */
561
 
    bswap32s(&ehdr->e_flags);           /* Processor-specific flags */
562
 
    bswap16s(&ehdr->e_ehsize);          /* ELF header size in bytes */
563
 
    bswap16s(&ehdr->e_phentsize);               /* Program header table entry size */
564
 
    bswap16s(&ehdr->e_phnum);           /* Program header table entry count */
565
 
    bswap16s(&ehdr->e_shentsize);               /* Section header table entry size */
566
 
    bswap16s(&ehdr->e_shnum);           /* Section header table entry count */
567
 
    bswap16s(&ehdr->e_shstrndx);                /* Section header string table index */
568
 
}
569
 
 
570
 
static void bswap_phdr(struct elf_phdr *phdr)
571
 
{
572
 
    bswap32s(&phdr->p_type);                    /* Segment type */
573
 
    bswaptls(&phdr->p_offset);          /* Segment file offset */
574
 
    bswaptls(&phdr->p_vaddr);           /* Segment virtual address */
575
 
    bswaptls(&phdr->p_paddr);           /* Segment physical address */
576
 
    bswaptls(&phdr->p_filesz);          /* Segment size in file */
577
 
    bswaptls(&phdr->p_memsz);           /* Segment size in memory */
578
 
    bswap32s(&phdr->p_flags);           /* Segment flags */
579
 
    bswaptls(&phdr->p_align);           /* Segment alignment */
580
 
}
581
 
 
582
 
static void bswap_shdr(struct elf_shdr *shdr)
583
 
{
584
 
    bswap32s(&shdr->sh_name);
585
 
    bswap32s(&shdr->sh_type);
586
 
    bswaptls(&shdr->sh_flags);
587
 
    bswaptls(&shdr->sh_addr);
588
 
    bswaptls(&shdr->sh_offset);
589
 
    bswaptls(&shdr->sh_size);
590
 
    bswap32s(&shdr->sh_link);
591
 
    bswap32s(&shdr->sh_info);
592
 
    bswaptls(&shdr->sh_addralign);
593
 
    bswaptls(&shdr->sh_entsize);
594
 
}
595
 
 
596
 
static void bswap_sym(struct elf_sym *sym)
597
 
{
598
 
    bswap32s(&sym->st_name);
599
 
    bswaptls(&sym->st_value);
600
 
    bswaptls(&sym->st_size);
601
 
    bswap16s(&sym->st_shndx);
602
 
}
603
 
#endif
604
 
 
605
 
/*
606
 
 * 'copy_elf_strings()' copies argument/envelope strings from user
607
 
 * memory to free pages in kernel mem. These are in a format ready
608
 
 * to be put directly into the top of new user memory.
609
 
 *
610
 
 */
611
 
static abi_ulong copy_elf_strings(int argc,char ** argv, void **page,
612
 
                                  abi_ulong p)
613
 
{
614
 
    char *tmp, *tmp1, *pag = NULL;
615
 
    int len, offset = 0;
616
 
 
617
 
    if (!p) {
618
 
        return 0;       /* bullet-proofing */
619
 
    }
620
 
    while (argc-- > 0) {
621
 
        tmp = argv[argc];
622
 
        if (!tmp) {
623
 
            fprintf(stderr, "VFS: argc is wrong");
624
 
            exit(-1);
625
 
        }
626
 
        tmp1 = tmp;
627
 
        while (*tmp++);
628
 
        len = tmp - tmp1;
629
 
        if (p < len) {  /* this shouldn't happen - 128kB */
630
 
                return 0;
631
 
        }
632
 
        while (len) {
633
 
            --p; --tmp; --len;
634
 
            if (--offset < 0) {
635
 
                offset = p % TARGET_PAGE_SIZE;
636
 
                pag = (char *)page[p/TARGET_PAGE_SIZE];
637
 
                if (!pag) {
638
 
                    pag = (char *)malloc(TARGET_PAGE_SIZE);
639
 
                    memset(pag, 0, TARGET_PAGE_SIZE);
640
 
                    page[p/TARGET_PAGE_SIZE] = pag;
641
 
                    if (!pag)
642
 
                        return 0;
643
 
                }
644
 
            }
645
 
            if (len == 0 || offset == 0) {
646
 
                *(pag + offset) = *tmp;
647
 
            }
648
 
            else {
649
 
              int bytes_to_copy = (len > offset) ? offset : len;
650
 
              tmp -= bytes_to_copy;
651
 
              p -= bytes_to_copy;
652
 
              offset -= bytes_to_copy;
653
 
              len -= bytes_to_copy;
654
 
              memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
655
 
            }
656
 
        }
657
 
    }
658
 
    return p;
659
 
}
660
 
 
661
 
static abi_ulong setup_arg_pages(abi_ulong p, struct linux_binprm *bprm,
662
 
                                 struct image_info *info)
663
 
{
664
 
    abi_ulong stack_base, size, error;
665
 
    int i;
666
 
 
667
 
    /* Create enough stack to hold everything.  If we don't use
668
 
     * it for args, we'll use it for something else...
669
 
     */
670
 
    size = x86_stack_size;
671
 
    if (size < MAX_ARG_PAGES*TARGET_PAGE_SIZE)
672
 
        size = MAX_ARG_PAGES*TARGET_PAGE_SIZE;
673
 
    error = target_mmap(0,
674
 
                        size + qemu_host_page_size,
675
 
                        PROT_READ | PROT_WRITE,
676
 
                        MAP_PRIVATE | MAP_ANON,
677
 
                        -1, 0);
678
 
    if (error == -1) {
679
 
        perror("stk mmap");
680
 
        exit(-1);
681
 
    }
682
 
    /* we reserve one extra page at the top of the stack as guard */
683
 
    target_mprotect(error + size, qemu_host_page_size, PROT_NONE);
684
 
 
685
 
    stack_base = error + size - MAX_ARG_PAGES*TARGET_PAGE_SIZE;
686
 
    p += stack_base;
687
 
 
688
 
    for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
689
 
        if (bprm->page[i]) {
690
 
            info->rss++;
691
 
            /* FIXME - check return value of memcpy_to_target() for failure */
692
 
            memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
693
 
            free(bprm->page[i]);
694
 
        }
695
 
        stack_base += TARGET_PAGE_SIZE;
696
 
    }
697
 
    return p;
698
 
}
699
 
 
700
 
static void set_brk(abi_ulong start, abi_ulong end)
701
 
{
702
 
        /* page-align the start and end addresses... */
703
 
        start = HOST_PAGE_ALIGN(start);
704
 
        end = HOST_PAGE_ALIGN(end);
705
 
        if (end <= start)
706
 
                return;
707
 
        if(target_mmap(start, end - start,
708
 
                       PROT_READ | PROT_WRITE | PROT_EXEC,
709
 
                       MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0) == -1) {
710
 
            perror("cannot mmap brk");
711
 
            exit(-1);
712
 
        }
713
 
}
714
 
 
715
 
 
716
 
/* We need to explicitly zero any fractional pages after the data
717
 
   section (i.e. bss).  This would contain the junk from the file that
718
 
   should not be in memory. */
719
 
static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
720
 
{
721
 
        abi_ulong nbyte;
722
 
 
723
 
        if (elf_bss >= last_bss)
724
 
                return;
725
 
 
726
 
        /* XXX: this is really a hack : if the real host page size is
727
 
           smaller than the target page size, some pages after the end
728
 
           of the file may not be mapped. A better fix would be to
729
 
           patch target_mmap(), but it is more complicated as the file
730
 
           size must be known */
731
 
        if (qemu_real_host_page_size < qemu_host_page_size) {
732
 
            abi_ulong end_addr, end_addr1;
733
 
            end_addr1 = (elf_bss + qemu_real_host_page_size - 1) &
734
 
                ~(qemu_real_host_page_size - 1);
735
 
            end_addr = HOST_PAGE_ALIGN(elf_bss);
736
 
            if (end_addr1 < end_addr) {
737
 
                mmap((void *)g2h(end_addr1), end_addr - end_addr1,
738
 
                     PROT_READ|PROT_WRITE|PROT_EXEC,
739
 
                     MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
740
 
            }
741
 
        }
742
 
 
743
 
        nbyte = elf_bss & (qemu_host_page_size-1);
744
 
        if (nbyte) {
745
 
            nbyte = qemu_host_page_size - nbyte;
746
 
            do {
747
 
                /* FIXME - what to do if put_user() fails? */
748
 
                put_user_u8(0, elf_bss);
749
 
                elf_bss++;
750
 
            } while (--nbyte);
751
 
        }
752
 
}
753
 
 
754
 
 
755
 
static abi_ulong create_elf_tables(abi_ulong p, int argc, int envc,
756
 
                                   struct elfhdr * exec,
757
 
                                   abi_ulong load_addr,
758
 
                                   abi_ulong load_bias,
759
 
                                   abi_ulong interp_load_addr, int ibcs,
760
 
                                   struct image_info *info)
761
 
{
762
 
        abi_ulong sp;
763
 
        int size;
764
 
        abi_ulong u_platform;
765
 
        const char *k_platform;
766
 
        const int n = sizeof(elf_addr_t);
767
 
 
768
 
        sp = p;
769
 
        u_platform = 0;
770
 
        k_platform = ELF_PLATFORM;
771
 
        if (k_platform) {
772
 
            size_t len = strlen(k_platform) + 1;
773
 
            sp -= (len + n - 1) & ~(n - 1);
774
 
            u_platform = sp;
775
 
            /* FIXME - check return value of memcpy_to_target() for failure */
776
 
            memcpy_to_target(sp, k_platform, len);
777
 
        }
778
 
        /*
779
 
         * Force 16 byte _final_ alignment here for generality.
780
 
         */
781
 
        sp = sp &~ (abi_ulong)15;
782
 
        size = (DLINFO_ITEMS + 1) * 2;
783
 
        if (k_platform)
784
 
          size += 2;
785
 
#ifdef DLINFO_ARCH_ITEMS
786
 
        size += DLINFO_ARCH_ITEMS * 2;
787
 
#endif
788
 
        size += envc + argc + 2;
789
 
        size += (!ibcs ? 3 : 1);        /* argc itself */
790
 
        size *= n;
791
 
        if (size & 15)
792
 
            sp -= 16 - (size & 15);
793
 
 
794
 
        /* This is correct because Linux defines
795
 
         * elf_addr_t as Elf32_Off / Elf64_Off
796
 
         */
797
 
#define NEW_AUX_ENT(id, val) do {               \
798
 
            sp -= n; put_user_ual(val, sp);     \
799
 
            sp -= n; put_user_ual(id, sp);      \
800
 
          } while(0)
801
 
 
802
 
        NEW_AUX_ENT (AT_NULL, 0);
803
 
 
804
 
        /* There must be exactly DLINFO_ITEMS entries here.  */
805
 
        NEW_AUX_ENT(AT_PHDR, (abi_ulong)(load_addr + exec->e_phoff));
806
 
        NEW_AUX_ENT(AT_PHENT, (abi_ulong)(sizeof (struct elf_phdr)));
807
 
        NEW_AUX_ENT(AT_PHNUM, (abi_ulong)(exec->e_phnum));
808
 
        NEW_AUX_ENT(AT_PAGESZ, (abi_ulong)(TARGET_PAGE_SIZE));
809
 
        NEW_AUX_ENT(AT_BASE, (abi_ulong)(interp_load_addr));
810
 
        NEW_AUX_ENT(AT_FLAGS, (abi_ulong)0);
811
 
        NEW_AUX_ENT(AT_ENTRY, load_bias + exec->e_entry);
812
 
        NEW_AUX_ENT(AT_UID, (abi_ulong) getuid());
813
 
        NEW_AUX_ENT(AT_EUID, (abi_ulong) geteuid());
814
 
        NEW_AUX_ENT(AT_GID, (abi_ulong) getgid());
815
 
        NEW_AUX_ENT(AT_EGID, (abi_ulong) getegid());
816
 
        NEW_AUX_ENT(AT_HWCAP, (abi_ulong) ELF_HWCAP);
817
 
        NEW_AUX_ENT(AT_CLKTCK, (abi_ulong) sysconf(_SC_CLK_TCK));
818
 
        if (k_platform)
819
 
            NEW_AUX_ENT(AT_PLATFORM, u_platform);
820
 
#ifdef ARCH_DLINFO
821
 
        /*
822
 
         * ARCH_DLINFO must come last so platform specific code can enforce
823
 
         * special alignment requirements on the AUXV if necessary (eg. PPC).
824
 
         */
825
 
        ARCH_DLINFO;
826
 
#endif
827
 
#undef NEW_AUX_ENT
828
 
 
829
 
        sp = loader_build_argptr(envc, argc, sp, p, !ibcs);
830
 
        return sp;
831
 
}
832
 
 
833
 
 
834
 
static abi_ulong load_elf_interp(struct elfhdr * interp_elf_ex,
835
 
                                 int interpreter_fd,
836
 
                                 abi_ulong *interp_load_addr)
837
 
{
838
 
        struct elf_phdr *elf_phdata  =  NULL;
839
 
        struct elf_phdr *eppnt;
840
 
        abi_ulong load_addr = 0;
841
 
        int load_addr_set = 0;
842
 
        int retval;
843
 
        abi_ulong last_bss, elf_bss;
844
 
        abi_ulong error;
845
 
        int i;
846
 
 
847
 
        elf_bss = 0;
848
 
        last_bss = 0;
849
 
        error = 0;
850
 
 
851
 
#ifdef BSWAP_NEEDED
852
 
        bswap_ehdr(interp_elf_ex);
853
 
#endif
854
 
        /* First of all, some simple consistency checks */
855
 
        if ((interp_elf_ex->e_type != ET_EXEC &&
856
 
             interp_elf_ex->e_type != ET_DYN) ||
857
 
           !elf_check_arch(interp_elf_ex->e_machine)) {
858
 
                return ~((abi_ulong)0UL);
859
 
        }
860
 
 
861
 
 
862
 
        /* Now read in all of the header information */
863
 
 
864
 
        if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > TARGET_PAGE_SIZE)
865
 
            return ~(abi_ulong)0UL;
866
 
 
867
 
        elf_phdata =  (struct elf_phdr *)
868
 
                malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
869
 
 
870
 
        if (!elf_phdata)
871
 
          return ~((abi_ulong)0UL);
872
 
 
873
 
        /*
874
 
         * If the size of this structure has changed, then punt, since
875
 
         * we will be doing the wrong thing.
876
 
         */
877
 
        if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr)) {
878
 
            free(elf_phdata);
879
 
            return ~((abi_ulong)0UL);
880
 
        }
881
 
 
882
 
        retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
883
 
        if(retval >= 0) {
884
 
            retval = read(interpreter_fd,
885
 
                           (char *) elf_phdata,
886
 
                           sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
887
 
        }
888
 
        if (retval < 0) {
889
 
                perror("load_elf_interp");
890
 
                exit(-1);
891
 
                free (elf_phdata);
892
 
                return retval;
893
 
        }
894
 
#ifdef BSWAP_NEEDED
895
 
        eppnt = elf_phdata;
896
 
        for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
897
 
            bswap_phdr(eppnt);
898
 
        }
899
 
#endif
900
 
 
901
 
        if (interp_elf_ex->e_type == ET_DYN) {
902
 
            /* in order to avoid hardcoding the interpreter load
903
 
               address in qemu, we allocate a big enough memory zone */
904
 
            error = target_mmap(0, INTERP_MAP_SIZE,
905
 
                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
906
 
                                -1, 0);
907
 
            if (error == -1) {
908
 
                perror("mmap");
909
 
                exit(-1);
910
 
            }
911
 
            load_addr = error;
912
 
            load_addr_set = 1;
913
 
        }
914
 
 
915
 
        eppnt = elf_phdata;
916
 
        for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
917
 
          if (eppnt->p_type == PT_LOAD) {
918
 
            int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
919
 
            int elf_prot = 0;
920
 
            abi_ulong vaddr = 0;
921
 
            abi_ulong k;
922
 
 
923
 
            if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
924
 
            if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
925
 
            if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
926
 
            if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
927
 
                elf_type |= MAP_FIXED;
928
 
                vaddr = eppnt->p_vaddr;
929
 
            }
930
 
            error = target_mmap(load_addr+TARGET_ELF_PAGESTART(vaddr),
931
 
                 eppnt->p_filesz + TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr),
932
 
                 elf_prot,
933
 
                 elf_type,
934
 
                 interpreter_fd,
935
 
                 eppnt->p_offset - TARGET_ELF_PAGEOFFSET(eppnt->p_vaddr));
936
 
 
937
 
            if (error == -1) {
938
 
              /* Real error */
939
 
              close(interpreter_fd);
940
 
              free(elf_phdata);
941
 
              return ~((abi_ulong)0UL);
942
 
            }
943
 
 
944
 
            if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
945
 
              load_addr = error;
946
 
              load_addr_set = 1;
947
 
            }
948
 
 
949
 
            /*
950
 
             * Find the end of the file  mapping for this phdr, and keep
951
 
             * track of the largest address we see for this.
952
 
             */
953
 
            k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
954
 
            if (k > elf_bss) elf_bss = k;
955
 
 
956
 
            /*
957
 
             * Do the same thing for the memory mapping - between
958
 
             * elf_bss and last_bss is the bss section.
959
 
             */
960
 
            k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
961
 
            if (k > last_bss) last_bss = k;
962
 
          }
963
 
 
964
 
        /* Now use mmap to map the library into memory. */
965
 
 
966
 
        close(interpreter_fd);
967
 
 
968
 
        /*
969
 
         * Now fill out the bss section.  First pad the last page up
970
 
         * to the page boundary, and then perform a mmap to make sure
971
 
         * that there are zeromapped pages up to and including the last
972
 
         * bss page.
973
 
         */
974
 
        padzero(elf_bss, last_bss);
975
 
        elf_bss = TARGET_ELF_PAGESTART(elf_bss + qemu_host_page_size - 1); /* What we have mapped so far */
976
 
 
977
 
        /* Map the last of the bss segment */
978
 
        if (last_bss > elf_bss) {
979
 
            target_mmap(elf_bss, last_bss-elf_bss,
980
 
                        PROT_READ|PROT_WRITE|PROT_EXEC,
981
 
                        MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
982
 
        }
983
 
        free(elf_phdata);
984
 
 
985
 
        *interp_load_addr = load_addr;
986
 
        return ((abi_ulong) interp_elf_ex->e_entry) + load_addr;
987
 
}
988
 
 
989
 
static int symfind(const void *s0, const void *s1)
990
 
{
991
 
    struct elf_sym *key = (struct elf_sym *)s0;
992
 
    struct elf_sym *sym = (struct elf_sym *)s1;
993
 
    int result = 0;
994
 
    if (key->st_value < sym->st_value) {
995
 
        result = -1;
996
 
    } else if (key->st_value > sym->st_value + sym->st_size) {
997
 
        result = 1;
998
 
    }
999
 
    return result;
1000
 
}
1001
 
 
1002
 
static const char *lookup_symbolxx(struct syminfo *s, target_ulong orig_addr)
1003
 
{
1004
 
#if ELF_CLASS == ELFCLASS32
1005
 
    struct elf_sym *syms = s->disas_symtab.elf32;
1006
 
#else
1007
 
    struct elf_sym *syms = s->disas_symtab.elf64;
1008
 
#endif
1009
 
 
1010
 
    // binary search
1011
 
    struct elf_sym key;
1012
 
    struct elf_sym *sym;
1013
 
 
1014
 
    key.st_value = orig_addr;
1015
 
 
1016
 
    sym = bsearch(&key, syms, s->disas_num_syms, sizeof(*syms), symfind);
1017
 
    if (sym != 0) {
1018
 
        return s->disas_strtab + sym->st_name;
1019
 
    }
1020
 
 
1021
 
    return "";
1022
 
}
1023
 
 
1024
 
/* FIXME: This should use elf_ops.h  */
1025
 
static int symcmp(const void *s0, const void *s1)
1026
 
{
1027
 
    struct elf_sym *sym0 = (struct elf_sym *)s0;
1028
 
    struct elf_sym *sym1 = (struct elf_sym *)s1;
1029
 
    return (sym0->st_value < sym1->st_value)
1030
 
        ? -1
1031
 
        : ((sym0->st_value > sym1->st_value) ? 1 : 0);
1032
 
}
1033
 
 
1034
 
/* Best attempt to load symbols from this ELF object. */
1035
 
static void load_symbols(struct elfhdr *hdr, int fd)
1036
 
{
1037
 
    unsigned int i, nsyms;
1038
 
    struct elf_shdr sechdr, symtab, strtab;
1039
 
    char *strings;
1040
 
    struct syminfo *s;
1041
 
    struct elf_sym *syms;
1042
 
 
1043
 
    lseek(fd, hdr->e_shoff, SEEK_SET);
1044
 
    for (i = 0; i < hdr->e_shnum; i++) {
1045
 
        if (read(fd, &sechdr, sizeof(sechdr)) != sizeof(sechdr))
1046
 
            return;
1047
 
#ifdef BSWAP_NEEDED
1048
 
        bswap_shdr(&sechdr);
1049
 
#endif
1050
 
        if (sechdr.sh_type == SHT_SYMTAB) {
1051
 
            symtab = sechdr;
1052
 
            lseek(fd, hdr->e_shoff
1053
 
                  + sizeof(sechdr) * sechdr.sh_link, SEEK_SET);
1054
 
            if (read(fd, &strtab, sizeof(strtab))
1055
 
                != sizeof(strtab))
1056
 
                return;
1057
 
#ifdef BSWAP_NEEDED
1058
 
            bswap_shdr(&strtab);
1059
 
#endif
1060
 
            goto found;
1061
 
        }
1062
 
    }
1063
 
    return; /* Shouldn't happen... */
1064
 
 
1065
 
 found:
1066
 
    /* Now know where the strtab and symtab are.  Snarf them. */
1067
 
    s = malloc(sizeof(*s));
1068
 
    syms = malloc(symtab.sh_size);
1069
 
    if (!syms)
1070
 
        return;
1071
 
    s->disas_strtab = strings = malloc(strtab.sh_size);
1072
 
    if (!s->disas_strtab)
1073
 
        return;
1074
 
 
1075
 
    lseek(fd, symtab.sh_offset, SEEK_SET);
1076
 
    if (read(fd, syms, symtab.sh_size) != symtab.sh_size)
1077
 
        return;
1078
 
 
1079
 
    nsyms = symtab.sh_size / sizeof(struct elf_sym);
1080
 
 
1081
 
    i = 0;
1082
 
    while (i < nsyms) {
1083
 
#ifdef BSWAP_NEEDED
1084
 
        bswap_sym(syms + i);
1085
 
#endif
1086
 
        // Throw away entries which we do not need.
1087
 
        if (syms[i].st_shndx == SHN_UNDEF ||
1088
 
                syms[i].st_shndx >= SHN_LORESERVE ||
1089
 
                ELF_ST_TYPE(syms[i].st_info) != STT_FUNC) {
1090
 
            nsyms--;
1091
 
            if (i < nsyms) {
1092
 
                syms[i] = syms[nsyms];
1093
 
            }
1094
 
            continue;
1095
 
        }
1096
 
#if defined(TARGET_ARM) || defined (TARGET_MIPS)
1097
 
        /* The bottom address bit marks a Thumb or MIPS16 symbol.  */
1098
 
        syms[i].st_value &= ~(target_ulong)1;
1099
 
#endif
1100
 
        i++;
1101
 
    }
1102
 
    syms = realloc(syms, nsyms * sizeof(*syms));
1103
 
 
1104
 
    qsort(syms, nsyms, sizeof(*syms), symcmp);
1105
 
 
1106
 
    lseek(fd, strtab.sh_offset, SEEK_SET);
1107
 
    if (read(fd, strings, strtab.sh_size) != strtab.sh_size)
1108
 
        return;
1109
 
    s->disas_num_syms = nsyms;
1110
 
#if ELF_CLASS == ELFCLASS32
1111
 
    s->disas_symtab.elf32 = syms;
1112
 
    s->lookup_symbol = lookup_symbolxx;
1113
 
#else
1114
 
    s->disas_symtab.elf64 = syms;
1115
 
    s->lookup_symbol = lookup_symbolxx;
1116
 
#endif
1117
 
    s->next = syminfos;
1118
 
    syminfos = s;
1119
 
}
1120
 
 
1121
 
int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1122
 
                    struct image_info * info)
1123
 
{
1124
 
    struct elfhdr elf_ex;
1125
 
    struct elfhdr interp_elf_ex;
1126
 
    struct exec interp_ex;
1127
 
    int interpreter_fd = -1; /* avoid warning */
1128
 
    abi_ulong load_addr, load_bias;
1129
 
    int load_addr_set = 0;
1130
 
    unsigned int interpreter_type = INTERPRETER_NONE;
1131
 
    unsigned char ibcs2_interpreter;
1132
 
    int i;
1133
 
    abi_ulong mapped_addr;
1134
 
    struct elf_phdr * elf_ppnt;
1135
 
    struct elf_phdr *elf_phdata;
1136
 
    abi_ulong elf_bss, k, elf_brk;
1137
 
    int retval;
1138
 
    char * elf_interpreter;
1139
 
    abi_ulong elf_entry, interp_load_addr = 0;
1140
 
    int status;
1141
 
    abi_ulong start_code, end_code, start_data, end_data;
1142
 
    abi_ulong reloc_func_desc = 0;
1143
 
    abi_ulong elf_stack;
1144
 
    char passed_fileno[6];
1145
 
 
1146
 
    ibcs2_interpreter = 0;
1147
 
    status = 0;
1148
 
    load_addr = 0;
1149
 
    load_bias = 0;
1150
 
    elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
1151
 
#ifdef BSWAP_NEEDED
1152
 
    bswap_ehdr(&elf_ex);
1153
 
#endif
1154
 
 
1155
 
    /* First of all, some simple consistency checks */
1156
 
    if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
1157
 
                                (! elf_check_arch(elf_ex.e_machine))) {
1158
 
            return -ENOEXEC;
1159
 
    }
1160
 
 
1161
 
    bprm->p = copy_elf_strings(1, &bprm->filename, bprm->page, bprm->p);
1162
 
    bprm->p = copy_elf_strings(bprm->envc,bprm->envp,bprm->page,bprm->p);
1163
 
    bprm->p = copy_elf_strings(bprm->argc,bprm->argv,bprm->page,bprm->p);
1164
 
    if (!bprm->p) {
1165
 
        retval = -E2BIG;
1166
 
    }
1167
 
 
1168
 
    /* Now read in all of the header information */
1169
 
    elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
1170
 
    if (elf_phdata == NULL) {
1171
 
        return -ENOMEM;
1172
 
    }
1173
 
 
1174
 
    retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
1175
 
    if(retval > 0) {
1176
 
        retval = read(bprm->fd, (char *) elf_phdata,
1177
 
                                elf_ex.e_phentsize * elf_ex.e_phnum);
1178
 
    }
1179
 
 
1180
 
    if (retval < 0) {
1181
 
        perror("load_elf_binary");
1182
 
        exit(-1);
1183
 
        free (elf_phdata);
1184
 
        return -errno;
1185
 
    }
1186
 
 
1187
 
#ifdef BSWAP_NEEDED
1188
 
    elf_ppnt = elf_phdata;
1189
 
    for (i=0; i<elf_ex.e_phnum; i++, elf_ppnt++) {
1190
 
        bswap_phdr(elf_ppnt);
1191
 
    }
1192
 
#endif
1193
 
    elf_ppnt = elf_phdata;
1194
 
 
1195
 
    elf_bss = 0;
1196
 
    elf_brk = 0;
1197
 
 
1198
 
 
1199
 
    elf_stack = ~((abi_ulong)0UL);
1200
 
    elf_interpreter = NULL;
1201
 
    start_code = ~((abi_ulong)0UL);
1202
 
    end_code = 0;
1203
 
    start_data = 0;
1204
 
    end_data = 0;
1205
 
    interp_ex.a_info = 0;
1206
 
 
1207
 
    for(i=0;i < elf_ex.e_phnum; i++) {
1208
 
        if (elf_ppnt->p_type == PT_INTERP) {
1209
 
            if ( elf_interpreter != NULL )
1210
 
            {
1211
 
                free (elf_phdata);
1212
 
                free(elf_interpreter);
1213
 
                close(bprm->fd);
1214
 
                return -EINVAL;
1215
 
            }
1216
 
 
1217
 
            /* This is the program interpreter used for
1218
 
             * shared libraries - for now assume that this
1219
 
             * is an a.out format binary
1220
 
             */
1221
 
 
1222
 
            elf_interpreter = (char *)malloc(elf_ppnt->p_filesz);
1223
 
 
1224
 
            if (elf_interpreter == NULL) {
1225
 
                free (elf_phdata);
1226
 
                close(bprm->fd);
1227
 
                return -ENOMEM;
1228
 
            }
1229
 
 
1230
 
            retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
1231
 
            if(retval >= 0) {
1232
 
                retval = read(bprm->fd, elf_interpreter, elf_ppnt->p_filesz);
1233
 
            }
1234
 
            if(retval < 0) {
1235
 
                perror("load_elf_binary2");
1236
 
                exit(-1);
1237
 
            }
1238
 
 
1239
 
            /* If the program interpreter is one of these two,
1240
 
               then assume an iBCS2 image. Otherwise assume
1241
 
               a native linux image. */
1242
 
 
1243
 
            /* JRP - Need to add X86 lib dir stuff here... */
1244
 
 
1245
 
            if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
1246
 
                strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
1247
 
              ibcs2_interpreter = 1;
1248
 
            }
1249
 
 
1250
 
#if 0
1251
 
            printf("Using ELF interpreter %s\n", elf_interpreter);
1252
 
#endif
1253
 
            if (retval >= 0) {
1254
 
                retval = open(path(elf_interpreter), O_RDONLY);
1255
 
                if(retval >= 0) {
1256
 
                    interpreter_fd = retval;
1257
 
                }
1258
 
                else {
1259
 
                    perror(elf_interpreter);
1260
 
                    exit(-1);
1261
 
                    /* retval = -errno; */
1262
 
                }
1263
 
            }
1264
 
 
1265
 
            if (retval >= 0) {
1266
 
                retval = lseek(interpreter_fd, 0, SEEK_SET);
1267
 
                if(retval >= 0) {
1268
 
                    retval = read(interpreter_fd,bprm->buf,128);
1269
 
                }
1270
 
            }
1271
 
            if (retval >= 0) {
1272
 
                interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
1273
 
                interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */
1274
 
            }
1275
 
            if (retval < 0) {
1276
 
                perror("load_elf_binary3");
1277
 
                exit(-1);
1278
 
                free (elf_phdata);
1279
 
                free(elf_interpreter);
1280
 
                close(bprm->fd);
1281
 
                return retval;
1282
 
            }
1283
 
        }
1284
 
        elf_ppnt++;
1285
 
    }
1286
 
 
1287
 
    /* Some simple consistency checks for the interpreter */
1288
 
    if (elf_interpreter){
1289
 
        interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
1290
 
 
1291
 
        /* Now figure out which format our binary is */
1292
 
        if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
1293
 
                (N_MAGIC(interp_ex) != QMAGIC)) {
1294
 
          interpreter_type = INTERPRETER_ELF;
1295
 
        }
1296
 
 
1297
 
        if (interp_elf_ex.e_ident[0] != 0x7f ||
1298
 
                strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
1299
 
            interpreter_type &= ~INTERPRETER_ELF;
1300
 
        }
1301
 
 
1302
 
        if (!interpreter_type) {
1303
 
            free(elf_interpreter);
1304
 
            free(elf_phdata);
1305
 
            close(bprm->fd);
1306
 
            return -ELIBBAD;
1307
 
        }
1308
 
    }
1309
 
 
1310
 
    /* OK, we are done with that, now set up the arg stuff,
1311
 
       and then start this sucker up */
1312
 
 
1313
 
    {
1314
 
        char * passed_p;
1315
 
 
1316
 
        if (interpreter_type == INTERPRETER_AOUT) {
1317
 
            snprintf(passed_fileno, sizeof(passed_fileno), "%d", bprm->fd);
1318
 
            passed_p = passed_fileno;
1319
 
 
1320
 
            if (elf_interpreter) {
1321
 
                bprm->p = copy_elf_strings(1,&passed_p,bprm->page,bprm->p);
1322
 
                bprm->argc++;
1323
 
            }
1324
 
        }
1325
 
        if (!bprm->p) {
1326
 
            if (elf_interpreter) {
1327
 
                free(elf_interpreter);
1328
 
            }
1329
 
            free (elf_phdata);
1330
 
            close(bprm->fd);
1331
 
            return -E2BIG;
1332
 
        }
1333
 
    }
1334
 
 
1335
 
    /* OK, This is the point of no return */
1336
 
    info->end_data = 0;
1337
 
    info->end_code = 0;
1338
 
    info->start_mmap = (abi_ulong)ELF_START_MMAP;
1339
 
    info->mmap = 0;
1340
 
    elf_entry = (abi_ulong) elf_ex.e_entry;
1341
 
 
1342
 
    /* Do this so that we can load the interpreter, if need be.  We will
1343
 
       change some of these later */
1344
 
    info->rss = 0;
1345
 
    bprm->p = setup_arg_pages(bprm->p, bprm, info);
1346
 
    info->start_stack = bprm->p;
1347
 
 
1348
 
    /* Now we do a little grungy work by mmaping the ELF image into
1349
 
     * the correct location in memory.  At this point, we assume that
1350
 
     * the image should be loaded at fixed address, not at a variable
1351
 
     * address.
1352
 
     */
1353
 
 
1354
 
    for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
1355
 
        int elf_prot = 0;
1356
 
        int elf_flags = 0;
1357
 
        abi_ulong error;
1358
 
 
1359
 
        if (elf_ppnt->p_type != PT_LOAD)
1360
 
            continue;
1361
 
 
1362
 
        if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
1363
 
        if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
1364
 
        if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
1365
 
        elf_flags = MAP_PRIVATE | MAP_DENYWRITE;
1366
 
        if (elf_ex.e_type == ET_EXEC || load_addr_set) {
1367
 
            elf_flags |= MAP_FIXED;
1368
 
        } else if (elf_ex.e_type == ET_DYN) {
1369
 
            /* Try and get dynamic programs out of the way of the default mmap
1370
 
               base, as well as whatever program they might try to exec.  This
1371
 
               is because the brk will follow the loader, and is not movable.  */
1372
 
            /* NOTE: for qemu, we do a big mmap to get enough space
1373
 
               without hardcoding any address */
1374
 
            error = target_mmap(0, ET_DYN_MAP_SIZE,
1375
 
                                PROT_NONE, MAP_PRIVATE | MAP_ANON,
1376
 
                                -1, 0);
1377
 
            if (error == -1) {
1378
 
                perror("mmap");
1379
 
                exit(-1);
1380
 
            }
1381
 
            load_bias = TARGET_ELF_PAGESTART(error - elf_ppnt->p_vaddr);
1382
 
        }
1383
 
 
1384
 
        error = target_mmap(TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr),
1385
 
                            (elf_ppnt->p_filesz +
1386
 
                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
1387
 
                            elf_prot,
1388
 
                            (MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
1389
 
                            bprm->fd,
1390
 
                            (elf_ppnt->p_offset -
1391
 
                             TARGET_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
1392
 
        if (error == -1) {
1393
 
            perror("mmap");
1394
 
            exit(-1);
1395
 
        }
1396
 
 
1397
 
#ifdef LOW_ELF_STACK
1398
 
        if (TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
1399
 
            elf_stack = TARGET_ELF_PAGESTART(elf_ppnt->p_vaddr);
1400
 
#endif
1401
 
 
1402
 
        if (!load_addr_set) {
1403
 
            load_addr_set = 1;
1404
 
            load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
1405
 
            if (elf_ex.e_type == ET_DYN) {
1406
 
                load_bias += error -
1407
 
                    TARGET_ELF_PAGESTART(load_bias + elf_ppnt->p_vaddr);
1408
 
                load_addr += load_bias;
1409
 
                reloc_func_desc = load_bias;
1410
 
            }
1411
 
        }
1412
 
        k = elf_ppnt->p_vaddr;
1413
 
        if (k < start_code)
1414
 
            start_code = k;
1415
 
        if (start_data < k)
1416
 
            start_data = k;
1417
 
        k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
1418
 
        if (k > elf_bss)
1419
 
            elf_bss = k;
1420
 
        if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
1421
 
            end_code = k;
1422
 
        if (end_data < k)
1423
 
            end_data = k;
1424
 
        k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
1425
 
        if (k > elf_brk) elf_brk = k;
1426
 
    }
1427
 
 
1428
 
    elf_entry += load_bias;
1429
 
    elf_bss += load_bias;
1430
 
    elf_brk += load_bias;
1431
 
    start_code += load_bias;
1432
 
    end_code += load_bias;
1433
 
    start_data += load_bias;
1434
 
    end_data += load_bias;
1435
 
 
1436
 
    if (elf_interpreter) {
1437
 
        if (interpreter_type & 1) {
1438
 
            elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
1439
 
        }
1440
 
        else if (interpreter_type & 2) {
1441
 
            elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
1442
 
                                            &interp_load_addr);
1443
 
        }
1444
 
        reloc_func_desc = interp_load_addr;
1445
 
 
1446
 
        close(interpreter_fd);
1447
 
        free(elf_interpreter);
1448
 
 
1449
 
        if (elf_entry == ~((abi_ulong)0UL)) {
1450
 
            printf("Unable to load interpreter\n");
1451
 
            free(elf_phdata);
1452
 
            exit(-1);
1453
 
            return 0;
1454
 
        }
1455
 
    }
1456
 
 
1457
 
    free(elf_phdata);
1458
 
 
1459
 
    if (loglevel)
1460
 
        load_symbols(&elf_ex, bprm->fd);
1461
 
 
1462
 
    if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
1463
 
    info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
1464
 
 
1465
 
#ifdef LOW_ELF_STACK
1466
 
    info->start_stack = bprm->p = elf_stack - 4;
1467
 
#endif
1468
 
    bprm->p = create_elf_tables(bprm->p,
1469
 
                    bprm->argc,
1470
 
                    bprm->envc,
1471
 
                    &elf_ex,
1472
 
                    load_addr, load_bias,
1473
 
                    interp_load_addr,
1474
 
                    (interpreter_type == INTERPRETER_AOUT ? 0 : 1),
1475
 
                    info);
1476
 
    info->load_addr = reloc_func_desc;
1477
 
    info->start_brk = info->brk = elf_brk;
1478
 
    info->end_code = end_code;
1479
 
    info->start_code = start_code;
1480
 
    info->start_data = start_data;
1481
 
    info->end_data = end_data;
1482
 
    info->start_stack = bprm->p;
1483
 
 
1484
 
    /* Calling set_brk effectively mmaps the pages that we need for the bss and break
1485
 
       sections */
1486
 
    set_brk(elf_bss, elf_brk);
1487
 
 
1488
 
    padzero(elf_bss, elf_brk);
1489
 
 
1490
 
#if 0
1491
 
    printf("(start_brk) %x\n" , info->start_brk);
1492
 
    printf("(end_code) %x\n" , info->end_code);
1493
 
    printf("(start_code) %x\n" , info->start_code);
1494
 
    printf("(end_data) %x\n" , info->end_data);
1495
 
    printf("(start_stack) %x\n" , info->start_stack);
1496
 
    printf("(brk) %x\n" , info->brk);
1497
 
#endif
1498
 
 
1499
 
    if ( info->personality == PER_SVR4 )
1500
 
    {
1501
 
            /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
1502
 
               and some applications "depend" upon this behavior.
1503
 
               Since we do not have the power to recompile these, we
1504
 
               emulate the SVr4 behavior.  Sigh.  */
1505
 
            mapped_addr = target_mmap(0, qemu_host_page_size, PROT_READ | PROT_EXEC,
1506
 
                                      MAP_FIXED | MAP_PRIVATE, -1, 0);
1507
 
    }
1508
 
 
1509
 
    info->entry = elf_entry;
1510
 
 
1511
 
    return 0;
1512
 
}
1513
 
 
1514
 
static int load_aout_interp(void * exptr, int interp_fd)
1515
 
{
1516
 
    printf("a.out interpreter not yet supported\n");
1517
 
    return(0);
1518
 
}
1519
 
 
1520
 
void do_init_thread(struct target_pt_regs *regs, struct image_info *infop)
1521
 
{
1522
 
    init_thread(regs, infop);
1523
 
}