From: Nicholas Nethercote Date: Tue, 30 Nov 2004 11:40:24 +0000 (+0000) Subject: Get AMD64 slightly further before dying: X-Git-Tag: svn/VALGRIND_3_0_0~1162 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=244787cc7f00f4d1c73ae5281c3deed13785f5de;p=thirdparty%2Fvalgrind.git Get AMD64 slightly further before dying: - implemented VG_(do_syscall)() - fixed a problem in ume.c with mapping when loading, which was causing stage2's memory to be trashed - fixed stage2.lds substitution so stage2 goes in the right address git-svn-id: svn://svn.valgrind.org/valgrind/trunk@3156 --- diff --git a/coregrind/amd64-linux/syscall.S b/coregrind/amd64-linux/syscall.S index af024b4600..2b01fdc41c 100644 --- a/coregrind/amd64-linux/syscall.S +++ b/coregrind/amd64-linux/syscall.S @@ -31,11 +31,42 @@ #include "core_asm.h" #include "vki_unistd.h" -# XXX: must reinstate comments also -- see x86-linux/syscall.S +/* + Perform a Linux syscall with the "syscall" instruction. + + Incoming args (syscall number + up to 6 args) come in + %rdi, %rsi, %rdx, %rcx, %r8, %r9, and the last one on the stack + (ie. the C calling convention). + + They are passed to the syscall in the regs + %rdi, %rsi, %rdx, %r10, %r8, %r9 (yes, really %r10, not %rcx), ie. the + kernel's syscall calling convention. + %rax holds the syscall number and gets the return value. + %rcx and %r11 are clobbered by the syscall; no matter, they + are caller-save (the syscall clobbers no callee-save regs, so + we don't have to do any register saving/restoring). + + This has no effect on the virtual machine; the expectation is + that the syscall mechanism makes no useful changes to any + register except %rax, which is returned. +*/ .globl VG_(do_syscall) VG_(do_syscall): - ud2 + # Convert function calling convention --> syscall calling convention + movq %rdi, %rax + movq %rsi, %rdi + movq %rdx, %rsi + movq %rcx, %rdx + movq %r8, %r10 + movq %r9, %r8 + movq 8(%rsp), %r9 # last arg from stack + syscall + ret + + + +# XXX: must reinstate comments also -- see x86-linux/syscall.S .globl VG_(clone) VG_(clone): diff --git a/coregrind/amd64/Makefile.am b/coregrind/amd64/Makefile.am index 2c39310c14..c87e43b4bf 100644 --- a/coregrind/amd64/Makefile.am +++ b/coregrind/amd64/Makefile.am @@ -30,4 +30,4 @@ stage2.lds: Makefile $(CC) -Wl,--verbose -nostdlib 2>&1 | sed \ -e '1,/^=====\+$$/d' \ -e '/^=====\+$$/d' \ - -e 's/0x00400000/kickstart_base/g' > $@ || rm -f $@ + -e 's/0x400000/kickstart_base/g' > $@ || rm -f $@ diff --git a/coregrind/ume.c b/coregrind/ume.c index 00357241d8..14120484f1 100644 --- a/coregrind/ume.c +++ b/coregrind/ume.c @@ -225,7 +225,6 @@ ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base) ESZ(Off) off; ESZ(Word) filesz; ESZ(Word) memsz; - ESZ(Word) align; unsigned prot = 0; if (ph->p_type != PT_LOAD) @@ -235,7 +234,6 @@ ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base) if (ph->p_flags & PF_W) prot |= PROT_WRITE; if (ph->p_flags & PF_R) prot |= PROT_READ; - align = ph->p_align; addr = ph->p_vaddr+base; off = ph->p_offset; filesz = ph->p_filesz; @@ -243,21 +241,25 @@ ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base) memsz = ph->p_memsz; brkaddr = addr+memsz; - res = mmap((char *)ROUNDDN(addr, align), - ROUNDUP(bss, align)-ROUNDDN(addr, align), - prot, MAP_FIXED|MAP_PRIVATE, e->fd, ROUNDDN(off, align)); - check_mmap(res, (char*)ROUNDDN(addr,align), - ROUNDUP(bss, align)-ROUNDDN(addr, align)); + // Tom says: In the following, do what the Linux kernel does and only + // map the pages that are required instead of rounding everything to + // the specified alignment (ph->p_align). (AMD64 doesn't work if you + // use ph->p_align -- part of stage2's memory gets trashed somehow.) - /* if memsz > filesz, then we need to fill the remainder with zeroed pages */ + res = mmap((char *)PGROUNDDN(addr), PGROUNDUP(bss)-PGROUNDDN(addr), + prot, MAP_FIXED|MAP_PRIVATE, e->fd, PGROUNDDN(off)); + check_mmap(res, (char*)PGROUNDDN(addr), + PGROUNDUP(bss)-PGROUNDDN(addr)); + + // if memsz > filesz, fill the remainder with zeroed pages if (memsz > filesz) { UInt bytes; - bytes = ROUNDUP(brkaddr, align)-ROUNDUP(bss, align); + bytes = PGROUNDUP(brkaddr)-PGROUNDUP(bss); if (bytes > 0) { - res = mmap((char *)ROUNDUP(bss, align), bytes, + res = mmap((char *)PGROUNDUP(bss), bytes, prot, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); - check_mmap(res, (char*)ROUNDUP(bss,align), bytes); + check_mmap(res, (char*)PGROUNDUP(bss), bytes); } bytes = bss & (VKI_PAGE_SIZE - 1);