]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Get AMD64 slightly further before dying:
authorNicholas Nethercote <njn@valgrind.org>
Tue, 30 Nov 2004 11:40:24 +0000 (11:40 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Tue, 30 Nov 2004 11:40:24 +0000 (11:40 +0000)
- 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

coregrind/amd64-linux/syscall.S
coregrind/amd64/Makefile.am
coregrind/ume.c

index af024b4600b672387040b25d137fdfe2e17d415f..2b01fdc41c7a485a0ae9c2d34f6857b8e9532bc0 100644 (file)
 #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):
index 2c39310c1471f316f0b45abdf040ba8805d6d726..c87e43b4bfa0aad8409c5387212e402d9699f096 100644 (file)
@@ -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 $@
index 00357241d84e277de85685de94b099501093b206..14120484f1f3911da8aedc06d669a0cc0bc008ae 100644 (file)
@@ -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);