Revision 53a5960a linux-user/elfload.c

b/linux-user/elfload.c
97 97

  
98 98
static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop)
99 99
{
100
    target_long *stack = (void *)infop->start_stack;
100
    target_long stack = infop->start_stack;
101 101
    memset(regs, 0, sizeof(*regs));
102 102
    regs->ARM_cpsr = 0x10;
103 103
    if (infop->entry & 1)
104 104
      regs->ARM_cpsr |= CPSR_T;
105 105
    regs->ARM_pc = infop->entry & 0xfffffffe;
106 106
    regs->ARM_sp = infop->start_stack;
107
    regs->ARM_r2 = tswapl(stack[2]); /* envp */
108
    regs->ARM_r1 = tswapl(stack[1]); /* argv */
107
    regs->ARM_r2 = tgetl(stack + 8); /* envp */
108
    regs->ARM_r1 = tgetl(stack + 4); /* envp */
109 109
    /* XXX: it seems that r0 is zeroed after ! */
110
    //    regs->ARM_r0 = tswapl(stack[0]); /* argc */
110
    //    regs->ARM_r0 = tgetl(stack); /* argc */
111 111
}
112 112

  
113 113
#define USE_ELF_CORE_DUMP
......
202 202
    _r->gpr[3] = bprm->argc;                               \
203 203
    _r->gpr[4] = (unsigned long)++pos;                     \
204 204
    for (; tmp != 0; pos++)                                \
205
        tmp = *pos;                                        \
205
        tmp = ldl(pos);                                    \
206 206
    _r->gpr[5] = (unsigned long)pos;                       \
207 207
} while (0)
208 208

  
......
297 297
 */
298 298
struct linux_binprm {
299 299
        char buf[128];
300
        unsigned long page[MAX_ARG_PAGES];
300
        void *page[MAX_ARG_PAGES];
301 301
        unsigned long p;
302 302
        int sh_bang;
303 303
	int fd;
......
427 427
}
428 428
#endif
429 429

  
430
static void * get_free_page(void)
431
{
432
    void *	retval;
433

  
434
    /* User-space version of kernel get_free_page.  Returns a page-aligned
435
     * page-sized chunk of memory.
436
     */
437
    retval = (void *)target_mmap(0, qemu_host_page_size, PROT_READ|PROT_WRITE, 
438
                                 MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
439

  
440
    if((long)retval == -1) {
441
	perror("get_free_page");
442
	exit(-1);
443
    }
444
    else {
445
	return(retval);
446
    }
447
}
448

  
449
static void free_page(void * pageaddr)
450
{
451
    target_munmap((unsigned long)pageaddr, qemu_host_page_size);
452
}
453

  
454 430
/*
455 431
 * 'copy_string()' copies argument/envelope strings from user
456 432
 * memory to free pages in kernel mem. These are in a format ready
457 433
 * to be put directly into the top of new user memory.
458 434
 *
459 435
 */
460
static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
436
static unsigned long copy_strings(int argc,char ** argv, void **page,
461 437
                unsigned long p)
462 438
{
463 439
    char *tmp, *tmp1, *pag = NULL;
......
482 458
	    --p; --tmp; --len;
483 459
	    if (--offset < 0) {
484 460
		offset = p % TARGET_PAGE_SIZE;
485
                pag = (char *) page[p/TARGET_PAGE_SIZE];
461
                pag = (char *)page[p/TARGET_PAGE_SIZE];
486 462
                if (!pag) {
487
                    pag = (char *)get_free_page();
488
                    page[p/TARGET_PAGE_SIZE] = (unsigned long)pag;
463
                    pag = (char *)malloc(TARGET_PAGE_SIZE);
464
                    page[p/TARGET_PAGE_SIZE] = pag;
489 465
                    if (!pag)
490 466
                        return 0;
491 467
		}
......
591 567
    }
592 568
}
593 569

  
594
unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
595
						struct image_info * info)
570
static inline void memcpy_to_target(target_ulong dest, const void *src,
571
                                    unsigned long len)
596 572
{
597
    unsigned long stack_base, size, error;
573
    void *host_ptr;
574

  
575
    host_ptr = lock_user(dest, len, 0);
576
    memcpy(host_ptr, src, len);
577
    unlock_user(host_ptr, dest, 1);
578
}
579

  
580
unsigned long setup_arg_pages(target_ulong p, struct linux_binprm * bprm,
581
					      struct image_info * info)
582
{
583
    target_ulong stack_base, size, error;
598 584
    int i;
599 585

  
600 586
    /* Create enough stack to hold everything.  If we don't use
......
627 613
	if (bprm->page[i]) {
628 614
	    info->rss++;
629 615

  
630
	    memcpy((void *)stack_base, (void *)bprm->page[i], TARGET_PAGE_SIZE);
631
	    free_page((void *)bprm->page[i]);
616
	    memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE);
617
	    free(bprm->page[i]);
632 618
	}
633
	stack_base += TARGET_PAGE_SIZE;
619
        stack_base += TARGET_PAGE_SIZE;
634 620
    }
635 621
    return p;
636 622
}
......
657 643
static void padzero(unsigned long elf_bss)
658 644
{
659 645
        unsigned long nbyte;
660
        char * fpnt;
661 646

  
662 647
        /* XXX: this is really a hack : if the real host page size is
663 648
           smaller than the target page size, some pages after the end
......
679 664
        nbyte = elf_bss & (qemu_host_page_size-1);
680 665
        if (nbyte) {
681 666
	    nbyte = qemu_host_page_size - nbyte;
682
	    fpnt = (char *) elf_bss;
683 667
	    do {
684
		*fpnt++ = 0;
668
		tput8(elf_bss, 0);
669
                elf_bss++;
685 670
	    } while (--nbyte);
686 671
        }
687 672
}
688 673

  
689
static unsigned int * create_elf_tables(char *p, int argc, int envc,
690
                                        struct elfhdr * exec,
691
                                        unsigned long load_addr,
692
                                        unsigned long load_bias,
693
                                        unsigned long interp_load_addr, int ibcs,
694
                                        struct image_info *info)
674

  
675
static unsigned long create_elf_tables(target_ulong p, int argc, int envc,
676
                                       struct elfhdr * exec,
677
                                       unsigned long load_addr,
678
                                       unsigned long load_bias,
679
                                       unsigned long interp_load_addr, int ibcs,
680
                                       struct image_info *info)
695 681
{
696
        target_ulong *argv, *envp;
697
        target_ulong *sp, *csp;
698
        target_ulong *u_platform;
682
        target_ulong argv, envp;
683
        target_ulong sp;
684
        int size;
685
        target_ulong u_platform;
699 686
        const char *k_platform;
700
        int v;
687
        const int n = sizeof(target_ulong);
701 688

  
702
	/*
703
	 * Force 16 byte _final_ alignment here for generality.
704
	 */
705
        sp = (unsigned int *) (~15UL & (unsigned long) p);
706
        u_platform = NULL;
689
        sp = p;
690
        u_platform = 0;
707 691
        k_platform = ELF_PLATFORM;
708 692
        if (k_platform) {
709 693
            size_t len = strlen(k_platform) + 1;
710
            sp -= (len + sizeof(target_ulong) - 1) / sizeof(target_ulong);
711
            u_platform = (target_ulong *)sp;
712
            __copy_to_user(u_platform, k_platform, len);
694
            sp -= (len + n - 1) & ~(n - 1);
695
            u_platform = sp;
696
            memcpy_to_target(sp, k_platform, len);
713 697
        }
714
        csp = sp;
715
        csp -= (DLINFO_ITEMS + 1) * 2;
698
	/*
699
	 * Force 16 byte _final_ alignment here for generality.
700
	 */
701
        sp = sp &~ (target_ulong)15;
702
        size = (DLINFO_ITEMS + 1) * 2;
716 703
        if (k_platform)
717
          csp -= 2;
704
          size += 2;
718 705
#ifdef DLINFO_ARCH_ITEMS
719
	csp -= DLINFO_ARCH_ITEMS*2;
706
	size += DLINFO_ARCH_ITEMS * 2;
720 707
#endif
721
        csp -= envc+1;
722
        csp -= argc+1;
723
	csp -= (!ibcs ? 3 : 1);	/* argc itself */
724
        if ((unsigned long)csp & 15UL)
725
            sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);
708
        size += envc + argc + 2;
709
	size += (!ibcs ? 3 : 1);	/* argc itself */
710
        size *= n;
711
        if (size & 15)
712
            sp -= 16 - (size & 15);
726 713
        
727
#define NEW_AUX_ENT(id, val) \
728
          sp -= 2; \
729
          put_user (id, sp); \
730
          put_user (val, sp + 1)
714
#define NEW_AUX_ENT(id, val) do { \
715
            sp -= n; tputl(sp, val); \
716
            sp -= n; tputl(sp, id); \
717
          } while(0)
731 718
        NEW_AUX_ENT (AT_NULL, 0);
732 719

  
733 720
        /* There must be exactly DLINFO_ITEMS entries here.  */
......
744 731
        NEW_AUX_ENT(AT_EGID, (target_ulong) getegid());
745 732
        NEW_AUX_ENT(AT_HWCAP, (target_ulong) ELF_HWCAP);
746 733
        if (k_platform)
747
            NEW_AUX_ENT(AT_PLATFORM, (target_ulong) u_platform);
734
            NEW_AUX_ENT(AT_PLATFORM, u_platform);
748 735
#ifdef ARCH_DLINFO
749 736
	/* 
750 737
	 * ARCH_DLINFO must come last so platform specific code can enforce
......
754 741
#endif
755 742
#undef NEW_AUX_ENT
756 743

  
757
        sp -= envc+1;
744
        sp -= (envc + 1) * n;
758 745
        envp = sp;
759
        sp -= argc+1;
746
        sp -= (argc + 1) * n;
760 747
        argv = sp;
761 748
        if (!ibcs) {
762
                put_user((target_ulong)envp,--sp);
763
                put_user((target_ulong)argv,--sp);
749
            sp -= n; tputl(sp, envp);
750
            sp -= n; tputl(sp, argv);
764 751
        }
765
        put_user(argc,--sp);
766
        info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);
752
        sp -= n; tputl(sp, argc);
753
        info->arg_start = p;
767 754
        while (argc-->0) {
768
                put_user((target_ulong)p,argv++);
769
                do {
770
                    get_user(v, p);
771
                    p++;
772
                } while (v != 0);
755
            tputl(argv, p); argv += n;
756
            p += target_strlen(p) + 1;
773 757
        }
774
        put_user(0,argv);
775
        info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
758
        tputl(argv, 0);
759
        info->arg_end = info->env_start = p;
776 760
        while (envc-->0) {
777
                put_user((target_ulong)p,envp++);
778
                do {
779
                    get_user(v, p);
780
                    p++;
781
                } while (v != 0);
761
            tputl(envp, p); envp += n;
762
            p += target_strlen(p) + 1;
782 763
        }
783
        put_user(0,envp);
784
        info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
764
        tputl(envp, 0);
765
        info->env_end = p;
785 766
        return sp;
786 767
}
787 768

  
788 769

  
789

  
790 770
static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
791 771
				     int interpreter_fd,
792 772
				     unsigned long *interp_load_addr)
......
1335 1315
#ifdef LOW_ELF_STACK
1336 1316
    info->start_stack = bprm->p = elf_stack - 4;
1337 1317
#endif
1338
    bprm->p = (unsigned long)
1339
      create_elf_tables((char *)bprm->p,
1318
    bprm->p = create_elf_tables(bprm->p,
1340 1319
		    bprm->argc,
1341 1320
		    bprm->envc,
1342 1321
                    &elf_ex,
......
1432 1411
        if(retval>=0) {
1433 1412
	    retval = load_elf_binary(&bprm,regs,infop);
1434 1413
	}
1414
        
1435 1415
        if(retval>=0) {
1436 1416
	    /* success.  Initialize important registers */
1437 1417
            init_thread(regs, infop);
......
1440 1420

  
1441 1421
        /* Something went wrong, return the inode and free the argument pages*/
1442 1422
        for (i=0 ; i<MAX_ARG_PAGES ; i++) {
1443
	    free_page((void *)bprm.page[i]);
1423
	    free(bprm.page[i]);
1444 1424
	}
1445 1425
        return(retval);
1446 1426
}

Also available in: Unified diff