~vcs-imports/qemu/git

« back to all changes in this revision

Viewing changes to linux-user/flatload.c

  • Committer: ths
  • Date: 2007-09-16 21:08:06 UTC
  • Revision ID: git-v1:5fafdf24ef2c090c164d4dc89684b3f379dbdd87
find -type f | xargs sed -i 's/[\t ]$//g' # on most files


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

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
#define UNLOADED_LIB 0x7ff000ff         /* Placeholder for unused library */
64
64
 
65
65
struct lib_info {
66
 
    abi_ulong start_code;       /* Start of text segment */
67
 
    abi_ulong start_data;       /* Start of data segment */
68
 
    abi_ulong end_data;         /* Start of bss section */
69
 
    abi_ulong start_brk;        /* End of data segment */
70
 
    abi_ulong text_len;         /* Length of text segment */
71
 
    abi_ulong entry;            /* Start address for this module */
72
 
    abi_ulong build_date;       /* When this one was compiled */
 
66
    target_ulong start_code;    /* Start of text segment */
 
67
    target_ulong start_data;    /* Start of data segment */
 
68
    target_ulong end_data;      /* Start of bss section */
 
69
    target_ulong start_brk;     /* End of data segment */
 
70
    target_ulong text_len;      /* Length of text segment */
 
71
    target_ulong entry;         /* Start address for this module */
 
72
    target_ulong build_date;    /* When this one was compiled */
73
73
    short loaded;               /* Has this library been loaded? */
74
74
};
75
75
 
89
89
 */
90
90
 
91
91
/* Push a block of strings onto the guest stack.  */
92
 
static abi_ulong copy_strings(abi_ulong p, int n, char **s)
 
92
static target_ulong copy_strings(target_ulong p, int n, char **s)
93
93
{
94
94
    int len;
95
95
 
102
102
    return p;
103
103
}
104
104
 
105
 
static int target_pread(int fd, abi_ulong ptr, abi_ulong len,
106
 
                        abi_ulong offset)
 
105
int target_pread(int fd, target_ulong ptr, target_ulong len,
 
106
                 target_ulong offset)
107
107
{
108
108
    void *buf;
109
109
    int ret;
110
110
 
111
 
    buf = lock_user(VERIFY_WRITE, ptr, len, 0);
 
111
    buf = lock_user(ptr, len, 0);
112
112
    ret = pread(fd, buf, len, offset);
113
113
    unlock_user(buf, ptr, len);
114
114
    return ret;
262
262
 
263
263
/****************************************************************************/
264
264
 
265
 
static abi_ulong
266
 
calc_reloc(abi_ulong r, struct lib_info *p, int curid, int internalp)
 
265
static target_ulong
 
266
calc_reloc(target_ulong r, struct lib_info *p, int curid, int internalp)
267
267
{
268
 
    abi_ulong addr;
 
268
    target_ulong addr;
269
269
    int id;
270
 
    abi_ulong start_brk;
271
 
    abi_ulong start_data;
272
 
    abi_ulong text_len;
273
 
    abi_ulong start_code;
 
270
    target_ulong start_brk;
 
271
    target_ulong start_data;
 
272
    target_ulong text_len;
 
273
    target_ulong start_code;
274
274
 
275
275
#ifdef CONFIG_BINFMT_SHARED_FLAT
276
276
#error needs checking
336
336
/****************************************************************************/
337
337
 
338
338
/* ??? This does not handle endianness correctly.  */
339
 
static void old_reloc(struct lib_info *libinfo, uint32_t rl)
 
339
void old_reloc(struct lib_info *libinfo, uint32_t rl)
340
340
{
341
341
#ifdef DEBUG
342
342
        char *segment[] = { "TEXT", "DATA", "BSS", "*UNKNOWN*" };
349
349
        reloc_type = rl >> 30;
350
350
        /* ??? How to handle this?  */
351
351
#if defined(CONFIG_COLDFIRE)
352
 
        ptr = (uint32_t *) ((unsigned long) libinfo->start_code + offset);
 
352
        ptr = (uint32_t *) (libinfo->start_code + offset);
353
353
#else
354
 
        ptr = (uint32_t *) ((unsigned long) libinfo->start_data + offset);
 
354
        ptr = (uint32_t *) (libinfo->start_data + offset);
355
355
#endif
356
356
 
357
357
#ifdef DEBUG
376
376
                break;
377
377
        }
378
378
        DBG_FLT("Relocation became %x\n", (int)*ptr);
379
 
}
 
379
}       
380
380
 
381
381
/****************************************************************************/
382
382
 
383
383
static int load_flat_file(struct linux_binprm * bprm,
384
 
                struct lib_info *libinfo, int id, abi_ulong *extra_stack)
 
384
                struct lib_info *libinfo, int id, target_ulong *extra_stack)
385
385
{
386
386
    struct flat_hdr * hdr;
387
 
    abi_ulong textpos = 0, datapos = 0, result;
388
 
    abi_ulong realdatastart = 0;
389
 
    abi_ulong text_len, data_len, bss_len, stack_len, flags;
390
 
    abi_ulong memp = 0; /* for finding the brk area */
391
 
    abi_ulong extra;
392
 
    abi_ulong reloc = 0, rp;
 
387
    target_ulong textpos = 0, datapos = 0, result;
 
388
    target_ulong realdatastart = 0;
 
389
    target_ulong text_len, data_len, bss_len, stack_len, flags;
 
390
    target_ulong memp = 0; /* for finding the brk area */
 
391
    target_ulong extra;
 
392
    target_ulong reloc = 0, rp;
393
393
    int i, rev, relocs = 0;
394
 
    abi_ulong fpos;
395
 
    abi_ulong start_code, end_code;
396
 
    abi_ulong indx_len;
 
394
    target_ulong fpos;
 
395
    target_ulong start_code, end_code;
 
396
    target_ulong indx_len;
397
397
 
398
398
    hdr = ((struct flat_hdr *) bprm->buf);              /* exec-header */
399
399
 
416
416
                rev, (int) FLAT_VERSION);
417
417
        return -ENOEXEC;
418
418
    }
419
 
 
 
419
   
420
420
    /* Don't allow old format executables to use shared libraries */
421
421
    if (rev == OLD_FLAT_VERSION && id != 0) {
422
422
        fprintf(stderr, "BINFMT_FLAT: shared libraries are not available\n");
440
440
    /*
441
441
     * calculate the extra space we need to map in
442
442
     */
443
 
    extra = relocs * sizeof(abi_ulong);
 
443
    extra = relocs * sizeof(target_ulong);
444
444
    if (extra < bss_len + stack_len)
445
445
        extra = bss_len + stack_len;
446
446
 
447
447
    /* Add space for library base pointers.  Make sure this does not
448
448
       misalign the  doesn't misalign the data segment.  */
449
 
    indx_len = MAX_SHARED_LIBS * sizeof(abi_ulong);
450
 
    indx_len = (indx_len + 15) & ~(abi_ulong)15;
 
449
    indx_len = MAX_SHARED_LIBS * sizeof(target_ulong);
 
450
    indx_len = (indx_len + 15) & ~(target_ulong)15;
451
451
 
452
452
    /*
453
453
     * there are a couple of cases here,  the separate code/data
485
485
#ifdef CONFIG_BINFMT_ZFLAT
486
486
        if (flags & FLAT_FLAG_GZDATA) {
487
487
            result = decompress_exec(bprm, fpos, (char *) datapos,
488
 
                                     data_len + (relocs * sizeof(abi_ulong)))
 
488
                                     data_len + (relocs * sizeof(target_ulong)))
489
489
        } else
490
490
#endif
491
491
        {
492
492
            result = target_pread(bprm->fd, datapos,
493
 
                                  data_len + (relocs * sizeof(abi_ulong)),
 
493
                                  data_len + (relocs * sizeof(target_ulong)),
494
494
                                  fpos);
495
495
        }
496
496
        if (result < 0) {
544
544
                                  text_len, 0);
545
545
            if (result >= 0) {
546
546
                result = target_pread(bprm->fd, datapos,
547
 
                    data_len + (relocs * sizeof(abi_ulong)),
 
547
                    data_len + (relocs * sizeof(target_ulong)),
548
548
                    ntohl(hdr->data_start));
549
549
            }
550
550
        }
581
581
    libinfo[id].loaded = 1;
582
582
    libinfo[id].entry = (0x00ffffff & ntohl(hdr->entry)) + textpos;
583
583
    libinfo[id].build_date = ntohl(hdr->build_date);
584
 
 
 
584
   
585
585
    /*
586
586
     * We just load the allocations into some temporary memory to
587
587
     * help simplify all this mumbo jumbo
597
597
    if (flags & FLAT_FLAG_GOTPIC) {
598
598
        rp = datapos;
599
599
        while (1) {
600
 
            abi_ulong addr;
601
 
            if (get_user_ual(addr, rp))
602
 
                return -EFAULT;
 
600
            target_ulong addr;
 
601
            addr = tgetl(rp);
603
602
            if (addr == -1)
604
603
                break;
605
604
            if (addr) {
606
605
                addr = calc_reloc(addr, libinfo, id, 0);
607
606
                if (addr == RELOC_FAILED)
608
607
                    return -ENOEXEC;
609
 
                if (put_user_ual(addr, rp))
610
 
                    return -EFAULT;
 
608
                tputl(rp, addr);
611
609
            }
612
 
            rp += sizeof(abi_ulong);
 
610
            rp += sizeof(target_ulong);
613
611
        }
614
612
    }
615
613
 
626
624
     */
627
625
    if (rev > OLD_FLAT_VERSION) {
628
626
        for (i = 0; i < relocs; i++) {
629
 
            abi_ulong addr, relval;
 
627
            target_ulong addr, relval;
630
628
 
631
629
            /* Get the address of the pointer to be
632
630
               relocated (of course, the address has to be
633
631
               relocated first).  */
634
 
            if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
635
 
                return -EFAULT;
 
632
            relval = tgetl(reloc + i * sizeof (target_ulong));
636
633
            addr = flat_get_relocate_addr(relval);
637
634
            rp = calc_reloc(addr, libinfo, id, 1);
638
635
            if (rp == RELOC_FAILED)
639
636
                return -ENOEXEC;
640
637
 
641
638
            /* Get the pointer's value.  */
642
 
            if (get_user_ual(addr, rp))
643
 
                return -EFAULT;
 
639
            addr = tgetl(rp);
644
640
            if (addr != 0) {
645
641
                /*
646
642
                 * Do the relocation.  PIC relocs in the data section are
656
652
                    return -ENOEXEC;
657
653
 
658
654
                /* Write back the relocated pointer.  */
659
 
                if (put_user_ual(addr, rp))
660
 
                    return -EFAULT;
 
655
                tputl(rp, addr);
661
656
            }
662
657
        }
663
658
    } else {
664
659
        for (i = 0; i < relocs; i++) {
665
 
            abi_ulong relval;
666
 
            if (get_user_ual(relval, reloc + i * sizeof(abi_ulong)))
667
 
                return -EFAULT;
 
660
            target_ulong relval;
 
661
            relval = tgetl(reloc + i * sizeof (target_ulong));
668
662
            old_reloc(&libinfo[0], relval);
669
663
        }
670
664
    }
671
 
 
 
665
   
672
666
    /* zero the BSS.  */
673
 
    memset((void *)((unsigned long)datapos + data_len), 0, bss_len);
 
667
    memset((void*)(datapos + data_len), 0, bss_len);
674
668
 
675
669
    return 0;
676
670
}
718
712
                    struct image_info * info)
719
713
{
720
714
    struct lib_info libinfo[MAX_SHARED_LIBS];
721
 
    abi_ulong p = bprm->p;
722
 
    abi_ulong stack_len;
723
 
    abi_ulong start_addr;
724
 
    abi_ulong sp;
 
715
    target_ulong p = bprm->p;
 
716
    target_ulong stack_len;
 
717
    target_ulong start_addr;
 
718
    target_ulong sp;
725
719
    int res;
726
720
    int i, j;
727
721
 
738
732
    stack_len += (bprm->argc + 1) * 4; /* the argv array */
739
733
    stack_len += (bprm->envc + 1) * 4; /* the envp array */
740
734
 
741
 
 
 
735
   
742
736
    res = load_flat_file(bprm, libinfo, 0, &stack_len);
743
737
    if (res > (unsigned long)-4096)
744
738
            return res;
745
 
 
 
739
   
746
740
    /* Update data segment pointers for all libraries */
747
741
    for (i=0; i<MAX_SHARED_LIBS; i++) {
748
742
        if (libinfo[i].loaded) {
749
 
            abi_ulong p;
 
743
            target_ulong p;
750
744
            p = libinfo[i].start_data;
751
745
            for (j=0; j<MAX_SHARED_LIBS; j++) {
752
746
                p -= 4;
753
 
                /* FIXME - handle put_user() failures */
754
 
                if (put_user_ual(libinfo[j].loaded
755
 
                                 ? libinfo[j].start_data
756
 
                                 : UNLOADED_LIB,
757
 
                                 p))
758
 
                    return -EFAULT;
 
747
                tput32(p, libinfo[j].loaded
 
748
                          ? libinfo[j].start_data
 
749
                          : UNLOADED_LIB);
759
750
            }
760
751
        }
761
752
    }
767
758
    p = copy_strings(p, bprm->envc, bprm->envp);
768
759
    p = copy_strings(p, bprm->argc, bprm->argv);
769
760
    /* Align stack.  */
770
 
    sp = p & ~(abi_ulong)(sizeof(abi_ulong) - 1);
 
761
    sp = p & ~(target_ulong)(sizeof(target_ulong) - 1);
771
762
    /* Enforce final stack alignment of 16 bytes.  This is sufficient
772
763
       for all current targets, and excess alignment is harmless.  */
773
764
    stack_len = bprm->envc + bprm->argc + 2;
774
765
    stack_len += 3;     /* argc, arvg, argp */
775
 
    stack_len *= sizeof(abi_ulong);
 
766
    stack_len *= sizeof(target_ulong);
776
767
    if ((sp + stack_len) & 15)
777
768
        sp -= 16 - ((sp + stack_len) & 15);
778
769
    sp = loader_build_argptr(bprm->envc, bprm->argc, sp, p, 1);
779
 
 
 
770
   
780
771
    /* Fake some return addresses to ensure the call chain will
781
772
     * initialise library in order for us.  We are required to call
782
773
     * lib 1 first, then 2, ... and finally the main program (id 0).
788
779
    for (i = MAX_SHARED_LIBS-1; i>0; i--) {
789
780
            if (libinfo[i].loaded) {
790
781
                    /* Push previos first to call address */
791
 
                    --sp;
792
 
                    if (put_user_ual(start_addr, sp))
793
 
                        return -EFAULT;
 
782
                    --sp;       put_user(start_addr, sp);
794
783
                    start_addr = libinfo[i].entry;
795
784
            }
796
785
    }
797
786
#endif
798
 
 
 
787
   
799
788
    /* Stash our initial stack pointer into the mm structure */
800
789
    info->start_code = libinfo[0].start_code;
801
790
    info->end_code = libinfo[0].start_code = libinfo[0].text_len;
809
798
 
810
799
    DBG_FLT("start_thread(entry=0x%x, start_stack=0x%x)\n",
811
800
            (int)info->entry, (int)info->start_stack);
812
 
 
 
801
   
813
802
    return 0;
814
803
}