You can subscribe to this list here.
| 2002 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(1) |
Oct
(122) |
Nov
(152) |
Dec
(69) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2003 |
Jan
(6) |
Feb
(25) |
Mar
(73) |
Apr
(82) |
May
(24) |
Jun
(25) |
Jul
(10) |
Aug
(11) |
Sep
(10) |
Oct
(54) |
Nov
(203) |
Dec
(182) |
| 2004 |
Jan
(307) |
Feb
(305) |
Mar
(430) |
Apr
(312) |
May
(187) |
Jun
(342) |
Jul
(487) |
Aug
(637) |
Sep
(336) |
Oct
(373) |
Nov
(441) |
Dec
(210) |
| 2005 |
Jan
(385) |
Feb
(480) |
Mar
(636) |
Apr
(544) |
May
(679) |
Jun
(625) |
Jul
(810) |
Aug
(838) |
Sep
(634) |
Oct
(521) |
Nov
(965) |
Dec
(543) |
| 2006 |
Jan
(494) |
Feb
(431) |
Mar
(546) |
Apr
(411) |
May
(406) |
Jun
(322) |
Jul
(256) |
Aug
(401) |
Sep
(345) |
Oct
(542) |
Nov
(308) |
Dec
(481) |
| 2007 |
Jan
(427) |
Feb
(326) |
Mar
(367) |
Apr
(255) |
May
(244) |
Jun
(204) |
Jul
(223) |
Aug
(231) |
Sep
(354) |
Oct
(374) |
Nov
(497) |
Dec
(362) |
| 2008 |
Jan
(322) |
Feb
(482) |
Mar
(658) |
Apr
(422) |
May
(476) |
Jun
(396) |
Jul
(455) |
Aug
(267) |
Sep
(280) |
Oct
(253) |
Nov
(232) |
Dec
(304) |
| 2009 |
Jan
(486) |
Feb
(470) |
Mar
(458) |
Apr
(423) |
May
(696) |
Jun
(461) |
Jul
(551) |
Aug
(575) |
Sep
(134) |
Oct
(110) |
Nov
(157) |
Dec
(102) |
| 2010 |
Jan
(226) |
Feb
(86) |
Mar
(147) |
Apr
(117) |
May
(107) |
Jun
(203) |
Jul
(193) |
Aug
(238) |
Sep
(300) |
Oct
(246) |
Nov
(23) |
Dec
(75) |
| 2011 |
Jan
(133) |
Feb
(195) |
Mar
(315) |
Apr
(200) |
May
(267) |
Jun
(293) |
Jul
(353) |
Aug
(237) |
Sep
(278) |
Oct
(611) |
Nov
(274) |
Dec
(260) |
| 2012 |
Jan
(303) |
Feb
(391) |
Mar
(417) |
Apr
(441) |
May
(488) |
Jun
(655) |
Jul
(590) |
Aug
(610) |
Sep
(526) |
Oct
(478) |
Nov
(359) |
Dec
(372) |
| 2013 |
Jan
(467) |
Feb
(226) |
Mar
(391) |
Apr
(281) |
May
(299) |
Jun
(252) |
Jul
(311) |
Aug
(352) |
Sep
(481) |
Oct
(571) |
Nov
(222) |
Dec
(231) |
| 2014 |
Jan
(185) |
Feb
(329) |
Mar
(245) |
Apr
(238) |
May
(281) |
Jun
(399) |
Jul
(382) |
Aug
(500) |
Sep
(579) |
Oct
(435) |
Nov
(487) |
Dec
(256) |
| 2015 |
Jan
(338) |
Feb
(357) |
Mar
(330) |
Apr
(294) |
May
(191) |
Jun
(108) |
Jul
(142) |
Aug
(261) |
Sep
(190) |
Oct
(54) |
Nov
(83) |
Dec
(22) |
| 2016 |
Jan
(49) |
Feb
(89) |
Mar
(33) |
Apr
(50) |
May
(27) |
Jun
(34) |
Jul
(53) |
Aug
(53) |
Sep
(98) |
Oct
(206) |
Nov
(93) |
Dec
(53) |
| 2017 |
Jan
(65) |
Feb
(82) |
Mar
(102) |
Apr
(86) |
May
(187) |
Jun
(67) |
Jul
(23) |
Aug
(93) |
Sep
(65) |
Oct
(45) |
Nov
(35) |
Dec
(17) |
| 2018 |
Jan
(26) |
Feb
(35) |
Mar
(38) |
Apr
(32) |
May
(8) |
Jun
(43) |
Jul
(27) |
Aug
(30) |
Sep
(43) |
Oct
(42) |
Nov
(38) |
Dec
(67) |
| 2019 |
Jan
(32) |
Feb
(37) |
Mar
(53) |
Apr
(64) |
May
(49) |
Jun
(18) |
Jul
(14) |
Aug
(53) |
Sep
(25) |
Oct
(30) |
Nov
(49) |
Dec
(31) |
| 2020 |
Jan
(87) |
Feb
(45) |
Mar
(37) |
Apr
(51) |
May
(99) |
Jun
(36) |
Jul
(11) |
Aug
(14) |
Sep
(20) |
Oct
(24) |
Nov
(40) |
Dec
(23) |
| 2021 |
Jan
(14) |
Feb
(53) |
Mar
(85) |
Apr
(15) |
May
(19) |
Jun
(3) |
Jul
(14) |
Aug
(1) |
Sep
(57) |
Oct
(73) |
Nov
(56) |
Dec
(22) |
| 2022 |
Jan
(3) |
Feb
(22) |
Mar
(6) |
Apr
(55) |
May
(46) |
Jun
(39) |
Jul
(15) |
Aug
(9) |
Sep
(11) |
Oct
(34) |
Nov
(20) |
Dec
(36) |
| 2023 |
Jan
(79) |
Feb
(41) |
Mar
(99) |
Apr
(169) |
May
(48) |
Jun
(16) |
Jul
(16) |
Aug
(57) |
Sep
(19) |
Oct
|
Nov
|
Dec
|
| S | M | T | W | T | F | S |
|---|---|---|---|---|---|---|
|
1
(22) |
2
(4) |
3
(12) |
4
|
5
(3) |
6
(15) |
7
(13) |
|
8
(12) |
9
(1) |
10
(17) |
11
(16) |
12
(15) |
13
(15) |
14
|
|
15
(1) |
16
(17) |
17
(16) |
18
(14) |
19
(1) |
20
(14) |
21
(2) |
|
22
(5) |
23
|
24
|
25
|
26
|
27
(1) |
28
(15) |
|
29
|
30
|
31
|
|
|
|
|
|
From: <sv...@va...> - 2013-12-01 19:28:57
|
Author: philippe
Date: Sun Dec 1 19:28:48 2013
New Revision: 13744
Log:
Decrease helgrind memory use for applications allocating many blocks
Use a pool allocator for the MallocMeta struct that helgrind maintains
for each client allocated block.
For perf/heap on x86, this decreases the max amount of mmap-ed memory
for the core area from 56Mb to 36Mb.
On amd64, decreases from 104Mb to 62Mb.
Modified:
trunk/helgrind/hg_main.c
Modified: trunk/helgrind/hg_main.c
==============================================================================
--- trunk/helgrind/hg_main.c (original)
+++ trunk/helgrind/hg_main.c Sun Dec 1 19:28:48 2013
@@ -54,6 +54,7 @@
#include "pub_tool_vki.h" // VKI_PAGE_SIZE
#include "pub_tool_libcproc.h" // VG_(atfork)
#include "pub_tool_aspacemgr.h" // VG_(am_is_valid_for_client)
+#include "pub_tool_poolalloc.h"
#include "hg_basics.h"
#include "hg_wordset.h"
@@ -3943,14 +3944,17 @@
(obviously). */
static VgHashTable hg_mallocmeta_table = NULL;
+/* MallocMeta are small elements. We use a pool to avoid
+ the overhead of malloc for each MallocMeta. */
+static PoolAlloc *MallocMeta_poolalloc = NULL;
static MallocMeta* new_MallocMeta ( void ) {
- MallocMeta* md = HG_(zalloc)( "hg.new_MallocMeta.1", sizeof(MallocMeta) );
- tl_assert(md);
+ MallocMeta* md = VG_(allocEltPA) (MallocMeta_poolalloc);
+ VG_(memset)(md, 0, sizeof(MallocMeta));
return md;
}
static void delete_MallocMeta ( MallocMeta* md ) {
- HG_(free)(md);
+ VG_(freeEltPA)(MallocMeta_poolalloc, md);
}
@@ -5359,6 +5363,12 @@
hg_mallocmeta_table
= VG_(HT_construct)( "hg_malloc_metadata_table" );
+ MallocMeta_poolalloc = VG_(newPA) ( sizeof(MallocMeta),
+ 1000,
+ HG_(zalloc),
+ "hg_malloc_metadata_pool",
+ HG_(free));
+
// add a callback to clean up on (threaded) fork.
VG_(atfork)(NULL/*pre*/, NULL/*parent*/, evh__atfork_child/*child*/);
}
|
|
From: Philippe W. <phi...@sk...> - 2013-12-01 19:18:46
|
On Sun, 2013-12-01 at 15:59 +0100, Bart Van Assche wrote: > Hello Philippe, > > Can you explain why you made this change ? In other words, do you > consider adding Xen hypercalls as a new feature or rather as a bug fix ? > For me it doesn't matter whether or not a bug number has been assigned. > What e.g. if a platform change would be requested as a wishlist item in > the KDE bugzilla tracker ? Would the fact that a bug number has been > assigned to a platform change be sufficient for you to conclude that it > must be mentioned under "FIXED BUGS" and not under "PLATFORM CHANGES" ? Hello Bart, The idea is that the FIXED BUGS contains all bugs that were reported in bugzilla and that are fixed/implemented. If some of these bugs are in fact not bugs but rather wishes for new features that are now implemented, these are also mentioned in the FIXED BUGS. On top of that, new features or relevant technical changes are also documented in specific sections such as PLATFORM CHANGES, TOOLS CHANGES, OTHER CHANGES. The above is similar to what was done for the NEWS in previous releases. For the specific example of Xen specific syscalls, in the past, these were only referenced in the fixed bugs section. But if relevant (e.g. if the support is now complete or allows to run significantly more programs), IMO, they could also be mentioned in PLATFORM CHANGES, so as to better inform the users. Philippe > > Thanks, > > Bart. > > On 12/01/13 15:51, sv...@va... wrote: > > Author: philippe > > Date: Sun Dec 1 14:51:21 2013 > > New Revision: 13742 > > > > Log: > > Move bug fix announcement to the FIXED BUGS section > > > > > > Modified: > > trunk/NEWS > > > > Modified: trunk/NEWS > > ============================================================================== > > --- trunk/NEWS (original) > > +++ trunk/NEWS Sun Dec 1 14:51:21 2013 > > @@ -4,7 +4,6 @@ > > > > * ================== PLATFORM CHANGES ================= > > > > -328205 Implement additional Xen hypercalls > > > > * ==================== TOOL CHANGES ==================== > > > > @@ -30,6 +29,7 @@ > > 327238 Callgrind Assertion 'passed <= last_bb->cjmp_count' failed > > 327837 dwz compressed alternate .debug_info and .debug_str not read correctly > > 327916 DW_TAG_typedef may have no name > > +328205 Implement additional Xen hypercalls > > > > Release 3.9.0 (31 October 2013) > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > > > > > ------------------------------------------------------------------------------ > > Rapidly troubleshoot problems before they affect your business. Most IT > > organizations don't have a clear picture of how application performance > > affects their revenue. With AppDynamics, you get 100% visibility into your > > Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro! > > http://pubads.g.doubleclick.net/gampad/clk?id=84349351&iu=/4140/ostg.clktrk > > _______________________________________________ > > Valgrind-developers mailing list > > Val...@li... > > https://lists.sourceforge.net/lists/listinfo/valgrind-developers > > > |
|
From: Bart V. A. <bva...@ac...> - 2013-12-01 15:00:03
|
Hello Philippe, Can you explain why you made this change ? In other words, do you consider adding Xen hypercalls as a new feature or rather as a bug fix ? For me it doesn't matter whether or not a bug number has been assigned. What e.g. if a platform change would be requested as a wishlist item in the KDE bugzilla tracker ? Would the fact that a bug number has been assigned to a platform change be sufficient for you to conclude that it must be mentioned under "FIXED BUGS" and not under "PLATFORM CHANGES" ? Thanks, Bart. On 12/01/13 15:51, sv...@va... wrote: > Author: philippe > Date: Sun Dec 1 14:51:21 2013 > New Revision: 13742 > > Log: > Move bug fix announcement to the FIXED BUGS section > > > Modified: > trunk/NEWS > > Modified: trunk/NEWS > ============================================================================== > --- trunk/NEWS (original) > +++ trunk/NEWS Sun Dec 1 14:51:21 2013 > @@ -4,7 +4,6 @@ > > * ================== PLATFORM CHANGES ================= > > -328205 Implement additional Xen hypercalls > > * ==================== TOOL CHANGES ==================== > > @@ -30,6 +29,7 @@ > 327238 Callgrind Assertion 'passed <= last_bb->cjmp_count' failed > 327837 dwz compressed alternate .debug_info and .debug_str not read correctly > 327916 DW_TAG_typedef may have no name > +328205 Implement additional Xen hypercalls > > Release 3.9.0 (31 October 2013) > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > > ------------------------------------------------------------------------------ > Rapidly troubleshoot problems before they affect your business. Most IT > organizations don't have a clear picture of how application performance > affects their revenue. With AppDynamics, you get 100% visibility into your > Java,.NET, & PHP application. Start your 15-day FREE TRIAL of AppDynamics Pro! > http://pubads.g.doubleclick.net/gampad/clk?id=84349351&iu=/4140/ostg.clktrk > _______________________________________________ > Valgrind-developers mailing list > Val...@li... > https://lists.sourceforge.net/lists/listinfo/valgrind-developers > |
|
From: <sv...@va...> - 2013-12-01 14:56:44
|
Author: philippe
Date: Sun Dec 1 14:56:28 2013
New Revision: 13743
Log:
Fix 326462 Refactor vgdb to isolate invoker stuff into separate module
vgdb.c contained (conditionally compiled) "invoker" code to have ptrace syscalls
used to allow gdb/vgdb to connect to a valgrind process blocked in a syscall.
This "invoker" code is ptrace based.
Not all platforms are using ptrace.
=> refactor vgdb so as allow invoker code to be added more cleanly
for non ptrace based platforms (e.g. Darwin, Solaris).
* add file vgdb.h for:
- definition of the vgdb-invoker interface
- common declarations between vgdb.c and vgdb-invoker implementations
* move ptrace related code from vgdb.c to new file vgdb-invoker-ptrace.c
* new file vgdb-invoker-none.c containing an empty invoker implementation
used on platforms that do not (yet) have a invoker implementation
(e.g. android and darwin).
* modified Makefile.am to use one of the vgdb-invoker-*.c file depending
on the platform.
* small changes related to changing ptraceinvoker to invoker in various files:
gdbserver_tests/make_local_links, gdbserver_tests/nlcontrolc.vgtest,
gdbserver_tests/mcinvokeRU.vgtest, gdbserver_tests/nlsigvgdb.vgtest
gdbserver_tests/mcinvokeWS.vgtest, coregrind/m_gdbserver/README_DEVELOPERS
Patch from Ivo Raisr, slightly modified
Added:
trunk/coregrind/vgdb-invoker-none.c
trunk/coregrind/vgdb-invoker-ptrace.c
trunk/coregrind/vgdb.h
Modified:
trunk/NEWS
trunk/coregrind/Makefile.am
trunk/coregrind/m_gdbserver/README_DEVELOPERS
trunk/coregrind/vgdb.c
trunk/gdbserver_tests/make_local_links
trunk/gdbserver_tests/mcinvokeRU.vgtest
trunk/gdbserver_tests/mcinvokeWS.vgtest
trunk/gdbserver_tests/nlcontrolc.vgtest
trunk/gdbserver_tests/nlsigvgdb.vgtest
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sun Dec 1 14:56:28 2013
@@ -24,7 +24,7 @@
https://bugs.kde.org/show_bug.cgi?id=XXXXXX
where XXXXXX is the bug number as listed below.
-
+326462 Refactor vgdb to isolate invoker stuff into separate module
326983 Clear direction flag after tests on amd64.
327238 Callgrind Assertion 'passed <= last_bb->cjmp_count' failed
327837 dwz compressed alternate .debug_info and .debug_str not read correctly
Modified: trunk/coregrind/Makefile.am
==============================================================================
--- trunk/coregrind/Makefile.am (original)
+++ trunk/coregrind/Makefile.am Sun Dec 1 14:56:28 2013
@@ -59,7 +59,22 @@
valgrind_LDFLAGS += -Wl,-z,noexecstack
endif
+
vgdb_SOURCES = vgdb.c
+if VGCONF_OS_IS_LINUX
+if VGCONF_PLATVARIANT_IS_ANDROID
+vgdb_SOURCES += vgdb-invoker-none.c
+else
+vgdb_SOURCES += vgdb-invoker-ptrace.c
+endif
+endif
+if VGCONF_OS_IS_DARWIN
+# Some darwin specific stuff is needed as ptrace is not
+# fully supported on MacOS. Till we find someone courageous
+# having access to Darwin, 'none' implementation is used.
+vgdb_SOURCES += vgdb-invoker-none.c
+endif
+
vgdb_CPPFLAGS = $(AM_CPPFLAGS_PRI)
vgdb_CFLAGS = $(AM_CFLAGS_PRI)
vgdb_CCASFLAGS = $(AM_CCASFLAGS_PRI)
Modified: trunk/coregrind/m_gdbserver/README_DEVELOPERS
==============================================================================
--- trunk/coregrind/m_gdbserver/README_DEVELOPERS (original)
+++ trunk/coregrind/m_gdbserver/README_DEVELOPERS Sun Dec 1 14:56:28 2013
@@ -165,7 +165,7 @@
by valgrind. If not, vgdb will force the invocation of the gdbserver
code inside the valgrind process.
-This forced invocation is implemented using the ptrace system call:
+On Linux, this forced invocation is implemented using the ptrace system call:
using ptrace, vgdb will cause the valgrind process to call the
gdbserver code.
@@ -272,10 +272,12 @@
Optional but heavily recommended:
To have a proper wake up of a Valgrind process with all threads
blocked in a system call, some architecture specific code
-has to be done in vgdb.c : search for PTRACEINVOKER processor symbol
-to see what has to be completed.
+has to be done in vgdb-invoker-*.c.
+Typically, for a linux system supporting ptrace, you have to modify
+vgdb-invoker-ptrace.c.
-For Linux based platforms, all the ptrace calls should be ok.
+For Linux based platforms, all the ptrace calls in vgdb-invoker-ptrace.c
+should be ok.
The only thing needed is the code needed to "push a dummy call" on the stack,
i.e. assign the relevant registers in the struct user_regs_struct, and push
values on the stack according to the ABI.
@@ -337,7 +339,6 @@
(such as search leaks)?
-
* currently jump(s) and inferior call(s) are somewhat dangerous
when called from a block not yet instrumented : instead
of continuing till the next Imark, where there will be a
Added: trunk/coregrind/vgdb-invoker-none.c
==============================================================================
--- trunk/coregrind/vgdb-invoker-none.c (added)
+++ trunk/coregrind/vgdb-invoker-none.c Sun Dec 1 14:56:28 2013
@@ -0,0 +1,56 @@
+/*--------------------------------------------------------------------*/
+/*--- Empty implementation of vgdb invoker subsystem. ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2011-2013 Philippe Waroquiers
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "vgdb.h"
+
+#include <stdio.h>
+#include <sys/time.h>
+
+void invoker_restrictions_msg(void)
+{
+ fprintf(stderr,
+ "Note: vgdb invoker not implemented on this platform.\n"
+ "For more info: read user manual section"
+ " 'Limitations of the Valgrind gdbserver'.\n");
+}
+
+void invoker_cleanup_restore_and_detach(void *v_pid)
+{
+ DEBUG(1, "invoker_cleanup_restore_and_detach");
+}
+
+Bool invoker_invoke_gdbserver(pid_t pid)
+{
+ DEBUG(2, "invoker_invoke_gdbserver not implemented\n");
+ /* Returning True signals to not retry (too soon) to invoke. */
+ return True;
+}
+
+void invoker_valgrind_dying(void)
+{
+}
Added: trunk/coregrind/vgdb-invoker-ptrace.c
==============================================================================
--- trunk/coregrind/vgdb-invoker-ptrace.c (added)
+++ trunk/coregrind/vgdb-invoker-ptrace.c Sun Dec 1 14:56:28 2013
@@ -0,0 +1,917 @@
+/*--------------------------------------------------------------------*/
+/*--- Implementation of vgdb invoker subsystem via ptrace() calls. ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2011-2013 Philippe Waroquiers
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#include "config.h"
+
+#include "vgdb.h"
+#include "pub_core_threadstate.h"
+
+#include <alloca.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ptrace.h>
+#include <sys/time.h>
+#include <sys/user.h>
+#include <sys/wait.h>
+
+#if VEX_HOST_WORDSIZE == 8
+typedef Addr64 CORE_ADDR;
+#elif VEX_HOST_WORDSIZE == 4
+typedef Addr32 CORE_ADDR;
+#else
+# error "unexpected wordsize"
+#endif
+
+#if VEX_HOST_WORDSIZE == 8
+typedef Addr64 PTRACE_XFER_TYPE;
+typedef void* PTRACE_ARG3_TYPE;
+#elif VEX_HOST_WORDSIZE == 4
+typedef Addr32 PTRACE_XFER_TYPE;
+typedef void* PTRACE_ARG3_TYPE;
+#else
+# error "unexpected wordsize"
+#endif
+
+/* True if we have continued pid_of_save_regs after PTRACE_ATTACH. */
+static Bool pid_of_save_regs_continued = False;
+
+/* True when loss of connection indicating that the Valgrind
+ process is dying. */
+static Bool dying = False;
+
+/* ptrace_(read|write)_memory are modified extracts of linux-low.c
+ from gdb 6.6. Copyrighted FSF */
+/* Copy LEN bytes from valgrind memory starting at MEMADDR
+ to vgdb memory starting at MYADDR. */
+static
+int ptrace_read_memory (pid_t inferior_pid, CORE_ADDR memaddr,
+ void *myaddr, size_t len)
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+ / sizeof (PTRACE_XFER_TYPE);
+ /* Allocate buffer of that many longwords. */
+ register PTRACE_XFER_TYPE *buffer
+ = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+
+ /* Read all the longwords */
+ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) {
+ errno = 0;
+ buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, 0);
+ if (errno)
+ return errno;
+ }
+
+ /* Copy appropriate bytes out of the buffer. */
+ memcpy (myaddr,
+ (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), len);
+
+ return 0;
+}
+
+/* Copy LEN bytes of data from vgdb memory at MYADDR
+ to valgrind memory at MEMADDR.
+ On failure (cannot write the valgrind memory)
+ returns the value of errno. */
+__attribute__((unused)) /* not used on all platforms */
+static
+int ptrace_write_memory (pid_t inferior_pid, CORE_ADDR memaddr,
+ const void *myaddr, size_t len)
+{
+ register int i;
+ /* Round starting address down to longword boundary. */
+ register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
+ /* Round ending address up; get number of longwords that makes. */
+ register int count
+ = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
+ / sizeof (PTRACE_XFER_TYPE);
+ /* Allocate buffer of that many longwords. */
+ register PTRACE_XFER_TYPE *buffer
+ = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
+
+ if (debuglevel >= 1) {
+ DEBUG (1, "Writing ");
+ for (i = 0; i < len; i++)
+ PDEBUG (1, "%02x", ((const unsigned char*)myaddr)[i]);
+ PDEBUG(1, " to %p\n", (void *) memaddr);
+ }
+
+ /* Fill start and end extra bytes of buffer with existing memory data. */
+
+ buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, 0);
+
+ if (count > 1) {
+ buffer[count - 1]
+ = ptrace (PTRACE_PEEKTEXT, inferior_pid,
+ (PTRACE_ARG3_TYPE) (addr + (count - 1)
+ * sizeof (PTRACE_XFER_TYPE)),
+ 0);
+ }
+
+ /* Copy data to be written over corresponding part of buffer */
+
+ memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
+ myaddr, len);
+
+ /* Write the entire buffer. */
+
+ for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) {
+ errno = 0;
+ ptrace (PTRACE_POKETEXT, inferior_pid,
+ (PTRACE_ARG3_TYPE) addr, buffer[i]);
+ if (errno)
+ return errno;
+ }
+
+ return 0;
+}
+
+/* subset of VG_(threads) needed for vgdb ptrace.
+ This is initialized when process is attached. */
+typedef struct {
+ ThreadStatus status;
+ Int lwpid;
+}
+VgdbThreadState;
+static VgdbThreadState vgdb_threads[VG_N_THREADS];
+
+static const
+HChar* name_of_ThreadStatus ( ThreadStatus status )
+{
+ switch (status) {
+ case VgTs_Empty: return "VgTs_Empty";
+ case VgTs_Init: return "VgTs_Init";
+ case VgTs_Runnable: return "VgTs_Runnable";
+ case VgTs_WaitSys: return "VgTs_WaitSys";
+ case VgTs_Yielding: return "VgTs_Yielding";
+ case VgTs_Zombie: return "VgTs_Zombie";
+ default: return "VgTs_???";
+ }
+}
+
+static
+char *status_image (int status)
+{
+ static char result[256];
+ int sz = 0;
+#define APPEND(...) sz += snprintf (result+sz, 256 - sz - 1, __VA_ARGS__)
+
+ result[0] = 0;
+
+ if (WIFEXITED(status))
+ APPEND ("WIFEXITED %d ", WEXITSTATUS(status));
+
+ if (WIFSIGNALED(status)) {
+ APPEND ("WIFSIGNALED %d ", WTERMSIG(status));
+ if (WCOREDUMP(status)) APPEND ("WCOREDUMP ");
+ }
+
+ if (WIFSTOPPED(status))
+ APPEND ("WIFSTOPPED %d ", WSTOPSIG(status));
+
+#ifdef WIFCONTINUED
+ if (WIFCONTINUED(status))
+ APPEND ("WIFCONTINUED ");
+#endif
+
+ return result;
+#undef APPEND
+}
+
+/* Wait till the process pid is reported as stopped with signal_expected.
+ If other signal(s) than signal_expected are received, waitstopped
+ will pass them to pid, waiting for signal_expected to stop pid.
+ Returns True when process is in stopped state with signal_expected.
+ Returns False if a problem was encountered while waiting for pid
+ to be stopped.
+
+ If pid is reported as being dead/exited, waitstopped will return False.
+*/
+static
+Bool waitstopped (pid_t pid, int signal_expected, const char *msg)
+{
+ pid_t p;
+ int status = 0;
+ int signal_received;
+ int res;
+
+ while (1) {
+ DEBUG(1, "waitstopped %s before waitpid signal_expected %d\n",
+ msg, signal_expected);
+ p = waitpid(pid, &status, __WALL);
+ DEBUG(1, "after waitpid pid %d p %d status 0x%x %s\n", pid, p,
+ status, status_image (status));
+ if (p != pid) {
+ ERROR(errno, "%s waitpid pid %d in waitstopped %d status 0x%x %s\n",
+ msg, pid, p, status, status_image (status));
+ return False;
+ }
+
+ if (WIFEXITED(status)) {
+ shutting_down = True;
+ return False;
+ }
+
+ assert (WIFSTOPPED(status));
+ signal_received = WSTOPSIG(status);
+ if (signal_received == signal_expected)
+ break;
+
+ /* pid received a signal which is not the signal we are waiting for.
+ We continue pid, transmitting this signal. */
+ DEBUG(1, "waitstopped PTRACE_CONT with signal %d\n", signal_received);
+ res = ptrace (PTRACE_CONT, pid, NULL, signal_received);
+ if (res != 0) {
+ ERROR(errno, "waitstopped PTRACE_CONT\n");
+ return False;
+ }
+ }
+
+ return True;
+}
+
+/* Stops the given pid, wait for the process to be stopped.
+ Returns True if succesful, False otherwise.
+ msg is used in tracing and error reporting. */
+static
+Bool stop (pid_t pid, const char *msg)
+{
+ long res;
+
+ DEBUG(1, "%s SIGSTOP pid %d\n", msg, pid);
+ res = kill (pid, SIGSTOP);
+ if (res != 0) {
+ ERROR(errno, "%s SIGSTOP pid %d %ld\n", msg, pid, res);
+ return False;
+ }
+
+ return waitstopped (pid, SIGSTOP, msg);
+
+}
+
+/* Attaches to given pid, wait for the process to be stopped.
+ Returns True if succesful, False otherwise.
+ msg is used in tracing and error reporting. */
+static
+Bool attach (pid_t pid, const char *msg)
+{
+ long res;
+ static Bool output_error = True;
+ static Bool initial_attach = True;
+ // For a ptrace_scope protected system, we do not want to output
+ // repetitively attach error. We will output once an error
+ // for the initial_attach. Once the 1st attach has succeeded, we
+ // again show all errors.
+
+ DEBUG(1, "%s PTRACE_ATTACH pid %d\n", msg, pid);
+ res = ptrace (PTRACE_ATTACH, pid, NULL, NULL);
+ if (res != 0) {
+ if (output_error || debuglevel > 0) {
+ ERROR(errno, "%s PTRACE_ATTACH pid %d %ld\n", msg, pid, res);
+ if (initial_attach)
+ output_error = False;
+ }
+ return False;
+ }
+
+ initial_attach = False;
+ output_error = True;
+ return waitstopped(pid, SIGSTOP, msg);
+}
+
+/* once we are attached to the pid, get the list of threads and stop
+ them all.
+ Returns True if all threads properly suspended, False otherwise. */
+static
+Bool acquire_and_suspend_threads (pid_t pid)
+{
+ int i;
+ int rw;
+ Bool pid_found = False;
+ Addr vgt;
+ int sz_tst;
+ int off_status;
+ int off_lwpid;
+ int nr_live_threads = 0;
+
+ if (shared32 != NULL) {
+ vgt = shared32->threads;
+ sz_tst = shared32->sizeof_ThreadState;
+ off_status = shared32->offset_status;
+ off_lwpid = shared32->offset_lwpid;
+ }
+ else if (shared64 != NULL) {
+ vgt = shared64->threads;
+ sz_tst = shared64->sizeof_ThreadState;
+ off_status = shared64->offset_status;
+ off_lwpid = shared64->offset_lwpid;
+ } else {
+ assert (0);
+ }
+
+ /* note: the entry 0 is unused */
+ for (i = 1; i < VG_N_THREADS; i++) {
+ vgt += sz_tst;
+ rw = ptrace_read_memory(pid, vgt+off_status,
+ &(vgdb_threads[i].status),
+ sizeof(ThreadStatus));
+ if (rw != 0) {
+ ERROR(rw, "status ptrace_read_memory\n");
+ return False;
+ }
+
+ rw = ptrace_read_memory(pid, vgt+off_lwpid,
+ &(vgdb_threads[i].lwpid),
+ sizeof(Int));
+ if (rw != 0) {
+ ERROR(rw, "lwpid ptrace_read_memory\n");
+ return False;
+ }
+
+ if (vgdb_threads[i].status != VgTs_Empty) {
+ DEBUG(1, "found tid %d status %s lwpid %d\n",
+ i, name_of_ThreadStatus(vgdb_threads[i].status),
+ vgdb_threads[i].lwpid);
+ nr_live_threads++;
+ if (vgdb_threads[i].lwpid <= 1) {
+ if (vgdb_threads[i].lwpid == 0
+ && vgdb_threads[i].status == VgTs_Init) {
+ DEBUG(1, "not set lwpid tid %d status %s lwpid %d\n",
+ i, name_of_ThreadStatus(vgdb_threads[i].status),
+ vgdb_threads[i].lwpid);
+ } else {
+ ERROR(1, "unexpected lwpid tid %d status %s lwpid %d\n",
+ i, name_of_ThreadStatus(vgdb_threads[i].status),
+ vgdb_threads[i].lwpid);
+ }
+ /* in case we have a VtTs_Init thread with lwpid not yet set,
+ we try again later. */
+ return False;
+ }
+ if (vgdb_threads[i].lwpid == pid) {
+ assert (!pid_found);
+ assert (i == 1);
+ pid_found = True;
+ } else {
+ if (!attach(vgdb_threads[i].lwpid, "attach_thread")) {
+ ERROR(0, "ERROR attach pid %d tid %d\n",
+ vgdb_threads[i].lwpid, i);
+ return False;
+ }
+ }
+ }
+ }
+ /* If we found no thread, it means the process is stopping, and
+ we better do not force anything to happen during that. */
+ if (nr_live_threads > 0)
+ return True;
+ else
+ return False;
+}
+
+static
+void detach_from_all_threads (pid_t pid)
+{
+ int i;
+ long res;
+ Bool pid_found = False;
+
+ /* detach from all the threads */
+ for (i = 1; i < VG_N_THREADS; i++) {
+ if (vgdb_threads[i].status != VgTs_Empty) {
+ if (vgdb_threads[i].status == VgTs_Init
+ && vgdb_threads[i].lwpid == 0) {
+ DEBUG(1, "skipping PTRACE_DETACH pid %d tid %d status %s\n",
+ vgdb_threads[i].lwpid, i,
+ name_of_ThreadStatus (vgdb_threads[i].status));
+ } else {
+ if (vgdb_threads[i].lwpid == pid) {
+ assert (!pid_found);
+ pid_found = True;
+ }
+ DEBUG(1, "PTRACE_DETACH pid %d tid %d status %s\n",
+ vgdb_threads[i].lwpid, i,
+ name_of_ThreadStatus (vgdb_threads[i].status));
+ res = ptrace (PTRACE_DETACH, vgdb_threads[i].lwpid, NULL, NULL);
+ if (res != 0) {
+ ERROR(errno, "PTRACE_DETACH pid %d tid %d status %s res %ld\n",
+ vgdb_threads[i].lwpid, i,
+ name_of_ThreadStatus (vgdb_threads[i].status),
+ res);
+ }
+ }
+ }
+ }
+
+ if (!pid_found && pid) {
+ /* No threads are live. Process is busy stopping.
+ We need to detach from pid explicitely. */
+ DEBUG(1, "no thread live => PTRACE_DETACH pid %d\n", pid);
+ res = ptrace (PTRACE_DETACH, pid, NULL, NULL);
+ if (res != 0)
+ ERROR(errno, "PTRACE_DETACH pid %d res %ld\n", pid, res);
+ }
+}
+
+// if > 0, pid for which registers have to be restored.
+static int pid_of_save_regs = 0;
+static struct user user_save;
+
+// The below indicates if ptrace_getregs (and ptrace_setregs) can be used.
+// Note that some linux versions are defining PTRACE_GETREGS but using
+// it gives back EIO.
+// has_working_ptrace_getregs can take the following values:
+// -1 : PTRACE_GETREGS is defined
+// runtime check not yet done.
+// 0 : PTRACE_GETREGS runtime check has failed.
+// 1 : PTRACE_GETREGS defined and runtime check ok.
+#ifdef HAVE_PTRACE_GETREGS
+static int has_working_ptrace_getregs = -1;
+#endif
+
+/* Get the registers from pid into regs.
+ regs_bsz value gives the length of *regs.
+ Returns True if all ok, otherwise False. */
+static
+Bool getregs (pid_t pid, void *regs, long regs_bsz)
+{
+ DEBUG(1, "getregs regs_bsz %ld\n", regs_bsz);
+# ifdef HAVE_PTRACE_GETREGS
+ if (has_working_ptrace_getregs) {
+ // Platforms having GETREGS
+ long res;
+ DEBUG(1, "getregs PTRACE_GETREGS\n");
+ res = ptrace (PTRACE_GETREGS, pid, NULL, regs);
+ if (res == 0) {
+ if (has_working_ptrace_getregs == -1) {
+ // First call to PTRACE_GETREGS succesful =>
+ has_working_ptrace_getregs = 1;
+ DEBUG(1, "detected a working PTRACE_GETREGS\n");
+ }
+ assert (has_working_ptrace_getregs == 1);
+ return True;
+ }
+ else if (has_working_ptrace_getregs == 1) {
+ // We had a working call, but now it fails.
+ // This is unexpected.
+ ERROR(errno, "PTRACE_GETREGS %ld\n", res);
+ return False;
+ } else {
+ // Check this is the first call:
+ assert (has_working_ptrace_getregs == -1);
+ if (errno == EIO) {
+ DEBUG(1, "detected a broken PTRACE_GETREGS with EIO\n");
+ has_working_ptrace_getregs = 0;
+ // Fall over to the PTRACE_PEEKUSER case.
+ } else {
+ ERROR(errno, "broken PTRACE_GETREGS unexpected errno %ld\n", res);
+ return False;
+ }
+ }
+ }
+# endif
+
+ // We assume PTRACE_PEEKUSER is defined everywhere.
+ {
+# ifdef PT_ENDREGS
+ long peek_bsz = PT_ENDREGS;
+ assert (peek_bsz <= regs_bsz);
+# else
+ long peek_bsz = regs_bsz-1;
+# endif
+ char *pregs = (char *) regs;
+ long offset;
+ errno = 0;
+ DEBUG(1, "getregs PTRACE_PEEKUSER(s) peek_bsz %ld\n", peek_bsz);
+ for (offset = 0; offset < peek_bsz; offset = offset + sizeof(long)) {
+ *(long *)(pregs+offset) = ptrace(PTRACE_PEEKUSER, pid, offset, NULL);
+ if (errno != 0) {
+ ERROR(errno, "PTRACE_PEEKUSER offset %ld\n", offset);
+ return False;
+ }
+ }
+ return True;
+ }
+
+ // If neither PTRACE_GETREGS not PTRACE_PEEKUSER have returned,
+ // then we are in serious trouble.
+ assert (0);
+}
+
+/* Set the registers of pid to regs.
+ regs_bsz value gives the length of *regs.
+ Returns True if all ok, otherwise False. */
+static
+Bool setregs (pid_t pid, void *regs, long regs_bsz)
+{
+ DEBUG(1, "setregs regs_bsz %ld\n", regs_bsz);
+// Note : the below is checking for GETREGS, not SETREGS
+// as if one is defined and working, the other one should also work.
+# ifdef HAVE_PTRACE_GETREGS
+ if (has_working_ptrace_getregs) {
+ // Platforms having SETREGS
+ long res;
+ // setregs can never be called before getregs has done a runtime check.
+ assert (has_working_ptrace_getregs == 1);
+ DEBUG(1, "setregs PTRACE_SETREGS\n");
+ res = ptrace (PTRACE_SETREGS, pid, NULL, regs);
+ if (res != 0) {
+ ERROR(errno, "PTRACE_SETREGS %ld\n", res);
+ return False;
+ }
+ return True;
+ }
+# endif
+
+ {
+ char *pregs = (char *) regs;
+ long offset;
+ long res;
+# ifdef PT_ENDREGS
+ long peek_bsz = PT_ENDREGS;
+ assert (peek_bsz <= regs_bsz);
+# else
+ long peek_bsz = regs_bsz-1;
+# endif
+ errno = 0;
+ DEBUG(1, "setregs PTRACE_POKEUSER(s) %ld\n", peek_bsz);
+ for (offset = 0; offset < peek_bsz; offset = offset + sizeof(long)) {
+ res = ptrace(PTRACE_POKEUSER, pid, offset, *(long*)(pregs+offset));
+ if (errno != 0) {
+ ERROR(errno, "PTRACE_POKEUSER offset %ld res %ld\n", offset, res);
+ return False;
+ }
+ }
+ return True;
+ }
+
+ // If neither PTRACE_SETREGS not PTRACE_POKEUSER have returned,
+ // then we are in serious trouble.
+ assert (0);
+}
+
+/* Restore the registers to the saved value, then detaches from all threads */
+static
+void restore_and_detach (pid_t pid)
+{
+ if (pid_of_save_regs) {
+ /* In case the 'main pid' has been continued, we need to stop it
+ before resetting the registers. */
+ if (pid_of_save_regs_continued) {
+ pid_of_save_regs_continued = False;
+ if (!stop(pid_of_save_regs, "sigstop before reset regs"))
+ DEBUG(0, "Could not sigstop before reset");
+ }
+
+ DEBUG(1, "setregs restore registers pid %d\n", pid_of_save_regs);
+ if (!setregs(pid_of_save_regs, &user_save.regs, sizeof(user_save.regs))) {
+ ERROR(errno, "setregs restore registers pid %d after cont\n",
+ pid_of_save_regs);
+ }
+ pid_of_save_regs = 0;
+ } else {
+ DEBUG(1, "PTRACE_SETREGS restore registers: no pid\n");
+ }
+ detach_from_all_threads(pid);
+}
+
+Bool invoker_invoke_gdbserver (pid_t pid)
+{
+ long res;
+ Bool stopped;
+ struct user user_mod;
+ Addr sp;
+ /* A specific int value is passed to invoke_gdbserver, to check
+ everything goes according to the plan. */
+ const int check = 0x8BADF00D; // ate bad food.
+
+ const Addr bad_return = 0;
+ // A bad return address will be pushed on the stack.
+ // The function invoke_gdbserver cannot return. If ever it returns, a NULL
+ // address pushed on the stack should ensure this is detected.
+
+ /* Not yet attached. If problem, vgdb can abort,
+ no cleanup needed. */
+
+ DEBUG(1, "attach to 'main' pid %d\n", pid);
+ if (!attach(pid, "attach main pid")) {
+ ERROR(0, "error attach main pid %d\n", pid);
+ return False;
+ }
+
+ /* Now, we are attached. If problem, detach and return. */
+
+ if (!acquire_and_suspend_threads(pid)) {
+ detach_from_all_threads(pid);
+ /* if the pid does not exist anymore, we better stop */
+ if (kill(pid, 0) != 0)
+ XERROR (errno, "invoke_gdbserver: check for pid %d existence failed\n",
+ pid);
+ return False;
+ }
+
+ if (!getregs(pid, &user_mod.regs, sizeof(user_mod.regs))) {
+ detach_from_all_threads(pid);
+ return False;
+ }
+ user_save = user_mod;
+
+#if defined(VGA_x86)
+ sp = user_mod.regs.esp;
+#elif defined(VGA_amd64)
+ sp = user_mod.regs.rsp;
+ if (shared32 != NULL) {
+ /* 64bit vgdb speaking with a 32bit executable.
+ To have system call restart properly, we need to sign extend rax.
+ For more info:
+ web search '[patch] Fix syscall restarts for amd64->i386 biarch'
+ e.g. http://sourceware.org/ml/gdb-patches/2009-11/msg00592.html */
+ *(long *)&user_save.regs.rax = *(int*)&user_save.regs.rax;
+ DEBUG(1, "Sign extending %8.8lx to %8.8lx\n",
+ user_mod.regs.rax, user_save.regs.rax);
+ }
+#elif defined(VGA_arm)
+ sp = user_mod.regs.uregs[13];
+#elif defined(VGA_ppc32)
+ sp = user_mod.regs.gpr[1];
+#elif defined(VGA_ppc64)
+ sp = user_mod.regs.gpr[1];
+#elif defined(VGA_s390x)
+ sp = user_mod.regs.gprs[15];
+#elif defined(VGA_mips32)
+ long long *p = (long long *)user_mod.regs;
+ sp = p[29];
+#elif defined(VGA_mips64)
+ sp = user_mod.regs[29];
+#else
+ I_die_here : (sp) architecture missing in vgdb.c
+#endif
+
+
+ // the magic below is derived from spying what gdb sends to
+ // the (classical) gdbserver when invoking a C function.
+ if (shared32 != NULL) {
+ // vgdb speaking with a 32bit executable.
+#if defined(VGA_x86) || defined(VGA_amd64)
+ const int regsize = 4;
+ int rw;
+ /* push check arg on the stack */
+ sp = sp - regsize;
+ DEBUG(1, "push check arg ptrace_write_memory\n");
+ assert(regsize == sizeof(check));
+ rw = ptrace_write_memory(pid, sp,
+ &check,
+ regsize);
+ if (rw != 0) {
+ ERROR(rw, "push check arg ptrace_write_memory");
+ detach_from_all_threads(pid);
+ return False;
+ }
+
+ sp = sp - regsize;
+ DEBUG(1, "push bad_return return address ptrace_write_memory\n");
+ // Note that for a 64 bits vgdb, only 4 bytes of NULL bad_return
+ // are written.
+ rw = ptrace_write_memory(pid, sp,
+ &bad_return,
+ regsize);
+ if (rw != 0) {
+ ERROR(rw, "push bad_return return address ptrace_write_memory");
+ detach_from_all_threads(pid);
+ return False;
+ }
+#if defined(VGA_x86)
+ /* set ebp, esp, eip and orig_eax to invoke gdbserver */
+ // compiled in 32bits, speaking with a 32bits exe
+ user_mod.regs.ebp = sp; // bp set to sp
+ user_mod.regs.esp = sp;
+ user_mod.regs.eip = shared32->invoke_gdbserver;
+ user_mod.regs.orig_eax = -1L;
+#elif defined(VGA_amd64)
+ /* set ebp, esp, eip and orig_eax to invoke gdbserver */
+ // compiled in 64bits, speaking with a 32bits exe
+ user_mod.regs.rbp = sp; // bp set to sp
+ user_mod.regs.rsp = sp;
+ user_mod.regs.rip = shared32->invoke_gdbserver;
+ user_mod.regs.orig_rax = -1L;
+#else
+ I_die_here : not x86 or amd64 in x86/amd64 section/
+#endif
+
+#elif defined(VGA_ppc32) || defined(VGA_ppc64)
+ user_mod.regs.nip = shared32->invoke_gdbserver;
+ user_mod.regs.trap = -1L;
+ /* put check arg in register 3 */
+ user_mod.regs.gpr[3] = check;
+ /* put NULL return address in Link Register */
+ user_mod.regs.link = bad_return;
+
+#elif defined(VGA_arm)
+ /* put check arg in register 0 */
+ user_mod.regs.uregs[0] = check;
+ /* put NULL return address in Link Register */
+ user_mod.regs.uregs[14] = bad_return;
+ user_mod.regs.uregs[15] = shared32->invoke_gdbserver;
+
+#elif defined(VGA_s390x)
+ XERROR(0, "(fn32) s390x has no 32bits implementation");
+#elif defined(VGA_mips32)
+ /* put check arg in register 4 */
+ p[4] = check;
+ /* put NULL return address in ra */
+ p[31] = bad_return;
+ p[34] = shared32->invoke_gdbserver;
+ p[25] = shared32->invoke_gdbserver;
+ /* make stack space for args */
+ p[29] = sp - 32;
+
+#elif defined(VGA_mips64)
+ assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe
+#else
+ I_die_here : architecture missing in vgdb.c
+#endif
+ }
+
+ else if (shared64 != NULL) {
+#if defined(VGA_x86)
+ assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
+#elif defined(VGA_amd64)
+ // vgdb speaking with a 64 bit executable.
+ const int regsize = 8;
+ int rw;
+
+ /* give check arg in rdi */
+ user_mod.regs.rdi = check;
+
+ /* push return address on stack : return to breakaddr */
+ sp = sp - regsize;
+ DEBUG(1, "push bad_return return address ptrace_write_memory\n");
+ rw = ptrace_write_memory(pid, sp,
+ &bad_return,
+ sizeof(bad_return));
+ if (rw != 0) {
+ ERROR(rw, "push bad_return return address ptrace_write_memory");
+ detach_from_all_threads(pid);
+ return False;
+ }
+
+ /* set rbp, rsp, rip and orig_rax to invoke gdbserver */
+ user_mod.regs.rbp = sp; // bp set to sp
+ user_mod.regs.rsp = sp;
+ user_mod.regs.rip = shared64->invoke_gdbserver;
+ user_mod.regs.orig_rax = -1L;
+
+#elif defined(VGA_arm)
+ assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
+#elif defined(VGA_ppc32)
+ assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
+#elif defined(VGA_ppc64)
+ Addr64 func_addr;
+ Addr64 toc_addr;
+ int rw;
+ rw = ptrace_read_memory(pid, shared64->invoke_gdbserver,
+ &func_addr,
+ sizeof(Addr64));
+ if (rw != 0) {
+ ERROR(rw, "ppc64 read func_addr\n");
+ detach_from_all_threads(pid);
+ return False;
+ }
+ rw = ptrace_read_memory(pid, shared64->invoke_gdbserver+8,
+ &toc_addr,
+ sizeof(Addr64));
+ if (rw != 0) {
+ ERROR(rw, "ppc64 read toc_addr\n");
+ detach_from_all_threads(pid);
+ return False;
+ }
+ // We are not pushing anything on the stack, so it is not
+ // very clear why the sp has to be decreased, but it seems
+ // needed. The ppc64 ABI might give some lights on this ?
+ user_mod.regs.gpr[1] = sp - 220;
+ user_mod.regs.gpr[2] = toc_addr;
+ user_mod.regs.nip = func_addr;
+ user_mod.regs.trap = -1L;
+ /* put check arg in register 3 */
+ user_mod.regs.gpr[3] = check;
+ /* put bad_return return address in Link Register */
+ user_mod.regs.link = bad_return;
+#elif defined(VGA_s390x)
+ /* put check arg in register r2 */
+ user_mod.regs.gprs[2] = check;
+ /* bad_return Return address is in r14 */
+ user_mod.regs.gprs[14] = bad_return;
+ /* minimum stack frame */
+ sp = sp - 160;
+ user_mod.regs.gprs[15] = sp;
+ /* set program counter */
+ user_mod.regs.psw.addr = shared64->invoke_gdbserver;
+#elif defined(VGA_mips32)
+ assert(0); // cannot vgdb a 64 bits executable with a 32 bits exe
+#elif defined(VGA_mips64)
+ /* put check arg in register 4 */
+ user_mod.regs[4] = check;
+ /* put NULL return address in ra */
+ user_mod.regs[31] = bad_return;
+ user_mod.regs[34] = shared64->invoke_gdbserver;
+ user_mod.regs[25] = shared64->invoke_gdbserver;
+#else
+ I_die_here: architecture missing in vgdb.c
+#endif
+ }
+ else {
+ assert(0);
+ }
+
+ if (!setregs(pid, &user_mod.regs, sizeof(user_mod.regs))) {
+ detach_from_all_threads(pid);
+ return False;
+ }
+ /* Now that we have modified the registers, we set
+ pid_of_save_regs to indicate that restore_and_detach
+ must restore the registers in case of cleanup. */
+ pid_of_save_regs = pid;
+ pid_of_save_regs_continued = False;
+
+
+ /* We PTRACE_CONT-inue pid.
+ Either gdbserver will be invoked directly (if all
+ threads are interruptible) or gdbserver will be
+ called soon by the scheduler. In the first case,
+ pid will stop on the break inserted above when
+ gdbserver returns. In the 2nd case, the break will
+ be encountered directly. */
+ DEBUG(1, "PTRACE_CONT to invoke\n");
+ res = ptrace (PTRACE_CONT, pid, NULL, NULL);
+ if (res != 0) {
+ ERROR(errno, "PTRACE_CONT\n");
+ restore_and_detach(pid);
+ return False;
+ }
+ pid_of_save_regs_continued = True;
+ /* Wait for SIGSTOP generated by m_gdbserver.c give_control_back_to_vgdb */
+ stopped = waitstopped (pid, SIGSTOP,
+ "waitpid status after PTRACE_CONT to invoke");
+ if (stopped) {
+ /* Here pid has properly stopped on the break. */
+ pid_of_save_regs_continued = False;
+ restore_and_detach(pid);
+ return True;
+ } else {
+ /* Whatever kind of problem happened. We shutdown. */
+ shutting_down = True;
+ return False;
+ }
+}
+
+void invoker_cleanup_restore_and_detach(void *v_pid)
+{
+ DEBUG(1, "invoker_cleanup_restore_and_detach dying: %d\n", dying);
+ if (!dying)
+ restore_and_detach(*(int*)v_pid);
+}
+
+void invoker_restrictions_msg(void)
+{
+}
+
+void invoker_valgrind_dying(void)
+{
+ /* Avoid messing up with registers of valgrind when it is dying. */
+ pid_of_save_regs_continued = False;
+ dying = True;
+}
Modified: trunk/coregrind/vgdb.c
==============================================================================
--- trunk/coregrind/vgdb.c (original)
+++ trunk/coregrind/vgdb.c Sun Dec 1 14:56:28 2013
@@ -26,34 +26,28 @@
The GNU General Public License is contained in the file COPYING.
*/
-#include "pub_core_basics.h"
-#include "pub_core_vki.h"
-#include "pub_core_libcsetjmp.h"
-#include "pub_core_threadstate.h"
-#include "pub_core_gdbserver.h"
+#include "vgdb.h"
+
#include "config.h"
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
#include <limits.h>
-#include <unistd.h>
-#include <string.h>
#include <poll.h>
#include <pthread.h>
+#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/types.h>
-#include <sys/socket.h>
+#include <string.h>
+#include <unistd.h>
#include <netinet/in.h>
-#include <arpa/inet.h>
#include <sys/mman.h>
-#include <sys/ptrace.h>
-#include <sys/wait.h>
-#include <assert.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
/* vgdb has two usages:
1. relay application between gdb and the gdbserver embedded in valgrind.
2. standalone to send monitor commands to a running valgrind-ified process
@@ -72,75 +66,18 @@
As a standalone utility, vgdb builds command packets to write to valgrind,
sends it and reads the reply. The same two threads are used to write/read.
Once all the commands are sent and their replies received, vgdb will exit.
-
*/
-/* define PTRACEINVOKER to compile the ptrace related code
- which ensures a valgrind process blocked in a system call
- can be "waken up". PTRACEINVOKER implies some architecture
- specific code and/or some OS specific code. */
-#if defined(VGA_arm) || defined(VGA_x86) || defined(VGA_amd64) \
- || defined(VGA_ppc32) || defined(VGA_ppc64) || defined(VGA_s390x) \
- || defined(VGA_mips32) || defined(VGA_mips64)
-#define PTRACEINVOKER
-#else
-I_die_here : (PTRACEINVOKER) architecture missing in vgdb.c
-#endif
-
-/* Some darwin specific stuff is needed as ptrace is not
- fully supported on MacOS. Till we find someone courageous
- having access to Darwin, there is no PTRACEINVOKER. */
-#if defined(VGO_darwin)
-#undef PTRACEINVOKER
-#endif
-
-#if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android)
-#undef PTRACEINVOKER
-#endif
-
-#if defined(PTRACEINVOKER)
-#include <sys/user.h>
-#endif
-
-
-// Outputs information for the user about ptrace not working.
-static void ptrace_restrictions_msg(void);
-
-static int debuglevel;
-static struct timeval dbgtv;
-/* if level <= debuglevel, print timestamp, then print provided by debug info */
-#define DEBUG(level, ...) (level <= debuglevel ? \
- gettimeofday(&dbgtv, NULL), \
- fprintf(stderr, "%ld.%6.6ld ", \
- (long int)dbgtv.tv_sec, \
- (long int)dbgtv.tv_usec), \
- fprintf(stderr, __VA_ARGS__),fflush(stderr) \
- : 0)
-
-/* same as DEBUG but does not print time stamp info */
-#define PDEBUG(level, ...) (level <= debuglevel ? \
- fprintf(stderr, __VA_ARGS__),fflush(stderr) \
- : 0)
-
-/* if errno != 0,
- report the errno and fprintf the ... varargs on stderr. */
-#define ERROR(errno, ...) ((errno == 0 ? 0 : perror("syscall failed")), \
- fprintf(stderr, __VA_ARGS__), \
- fflush(stderr))
-/* same as ERROR, but also exits with status 1 */
-#define XERROR(errno, ...) ((errno == 0 ? 0 : perror("syscall failed")), \
- fprintf(stderr, __VA_ARGS__), \
- fflush(stderr), \
- exit(1))
-
+int debuglevel;
+struct timeval dbgtv;
static char *vgdb_prefix = NULL;
/* Will be set to True when any condition indicating we have to shutdown
is encountered. */
-static Bool shutting_down = False;
+Bool shutting_down = False;
-static VgdbShared32 *shared32;
-static VgdbShared64 *shared64;
+VgdbShared32 *shared32;
+VgdbShared64 *shared64;
#define VS_written_by_vgdb (shared32 != NULL ? \
shared32->written_by_vgdb \
: shared64->written_by_vgdb)
@@ -266,898 +203,11 @@
}
-#if VEX_HOST_WORDSIZE == 8
-typedef Addr64 CORE_ADDR;
-typedef Addr64 PTRACE_XFER_TYPE;
-typedef void* PTRACE_ARG3_TYPE;
-#elif VEX_HOST_WORDSIZE == 4
-typedef Addr32 CORE_ADDR;
-typedef Addr32 PTRACE_XFER_TYPE;
-typedef void* PTRACE_ARG3_TYPE;
-#else
-# error "unexpected wordsize"
-#endif
-
-static Bool pid_of_save_regs_continued = False;
-// True if we have continued pid_of_save_regs after PTRACE_ATTACH
-
-static Bool dying = False;
-// Set to True when loss of connection indicating that the Valgrind
-// process is dying.
-
-/* To be called when connection with valgrind is lost. In case we
-have lost the connection, it means that Valgrind has closed the
-connection and is busy exiting. We can't and don't have to stop it in
-this case. */
-static
-void valgrind_dying(void)
-{
- pid_of_save_regs_continued = False;
- dying = True;
-}
-
-
-#ifdef PTRACEINVOKER
-/* ptrace_(read|write)_memory are modified extracts of linux-low.c
- from gdb 6.6. Copyrighted FSF */
-/* Copy LEN bytes from valgrind memory starting at MEMADDR
- to vgdb memory starting at MYADDR. */
-
-static
-int ptrace_read_memory (pid_t inferior_pid, CORE_ADDR memaddr,
- void *myaddr, int len)
-{
- register int i;
- /* Round starting address down to longword boundary. */
- register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
- /* Round ending address up; get number of longwords that makes. */
- register int count
- = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
- / sizeof (PTRACE_XFER_TYPE);
- /* Allocate buffer of that many longwords. */
- register PTRACE_XFER_TYPE *buffer
- = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
-
- /* Read all the longwords */
- for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) {
- errno = 0;
- buffer[i] = ptrace (PTRACE_PEEKTEXT, inferior_pid,
- (PTRACE_ARG3_TYPE) addr, 0);
- if (errno)
- return errno;
- }
-
- /* Copy appropriate bytes out of the buffer. */
- memcpy (myaddr,
- (char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)), len);
-
- return 0;
-}
-
-/* Copy LEN bytes of data from vgdb memory at MYADDR
- to valgrind memory at MEMADDR.
- On failure (cannot write the valgrind memory)
- returns the value of errno. */
-__attribute__((unused)) /* not used on all platforms */
-static
-int ptrace_write_memory (pid_t inferior_pid, CORE_ADDR memaddr,
- const void *myaddr, int len)
-{
- register int i;
- /* Round starting address down to longword boundary. */
- register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);
- /* Round ending address up; get number of longwords that makes. */
- register int count
- = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)
- / sizeof (PTRACE_XFER_TYPE);
- /* Allocate buffer of that many longwords. */
- register PTRACE_XFER_TYPE *buffer
- = (PTRACE_XFER_TYPE *) alloca (count * sizeof (PTRACE_XFER_TYPE));
-
- if (debuglevel >= 1) {
- DEBUG (1, "Writing ");
- for (i = 0; i < len; i++)
- PDEBUG (1, "%02x", ((const unsigned char*)myaddr)[i]);
- PDEBUG(1, " to %p\n", (void *) memaddr);
- }
-
- /* Fill start and end extra bytes of buffer with existing memory data. */
-
- buffer[0] = ptrace (PTRACE_PEEKTEXT, inferior_pid,
- (PTRACE_ARG3_TYPE) addr, 0);
-
- if (count > 1) {
- buffer[count - 1]
- = ptrace (PTRACE_PEEKTEXT, inferior_pid,
- (PTRACE_ARG3_TYPE) (addr + (count - 1)
- * sizeof (PTRACE_XFER_TYPE)),
- 0);
- }
-
- /* Copy data to be written over corresponding part of buffer */
-
- memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),
- myaddr, len);
-
- /* Write the entire buffer. */
-
- for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE)) {
- errno = 0;
- ptrace (PTRACE_POKETEXT, inferior_pid,
- (PTRACE_ARG3_TYPE) addr, buffer[i]);
- if (errno)
- return errno;
- }
-
- return 0;
-}
-
-/* subset of VG_(threads) needed for vgdb ptrace.
- This is initialized when process is attached. */
-typedef struct {
- ThreadStatus status;
- Int lwpid;
-}
-VgdbThreadState;
-static VgdbThreadState vgdb_threads[VG_N_THREADS];
-
-static const
-HChar* name_of_ThreadStatus ( ThreadStatus status )
-{
- switch (status) {
- case VgTs_Empty: return "VgTs_Empty";
- case VgTs_Init: return "VgTs_Init";
- case VgTs_Runnable: return "VgTs_Runnable";
- case VgTs_WaitSys: return "VgTs_WaitSys";
- case VgTs_Yielding: return "VgTs_Yielding";
- case VgTs_Zombie: return "VgTs_Zombie";
- default: return "VgTs_???";
- }
-}
-
-static
-char *status_image (int status)
-{
- static char result[256];
- int sz = 0;
-#define APPEND(...) sz += snprintf (result+sz, 256 - sz - 1, __VA_ARGS__)
-
- result[0] = 0;
-
- if (WIFEXITED(status))
- APPEND ("WIFEXITED %d ", WEXITSTATUS(status));
-
- if (WIFSIGNALED(status)) {
- APPEND ("WIFSIGNALED %d ", WTERMSIG(status));
- if (WCOREDUMP(status)) APPEND ("WCOREDUMP ");
- }
-
- if (WIFSTOPPED(status))
- APPEND ("WIFSTOPPED %d ", WSTOPSIG(status));
-
-#ifdef WIFCONTINUED
- if (WIFCONTINUED(status))
- APPEND ("WIFCONTINUED ");
-#endif
-
- return result;
-#undef APPEND
-}
-
-/* Wait till the process pid is reported as stopped with signal_expected.
- If other signal(s) than signal_expected are received, waitstopped
- will pass them to pid, waiting for signal_expected to stop pid.
- Returns True when process is in stopped state with signal_expected.
- Returns False if a problem was encountered while waiting for pid
- to be stopped.
-
- If pid is reported as being dead/exited, waitstopped will return False.
-*/
-static
-Bool waitstopped (int pid, int signal_expected, const char *msg)
-{
- pid_t p;
- int status = 0;
- int signal_received;
- int res;
-
- while (1) {
- DEBUG(1, "waitstopped %s before waitpid signal_expected %d\n",
- msg, signal_expected);
- p = waitpid(pid, &status, __WALL);
- DEBUG(1, "after waitpid pid %d p %d status 0x%x %s\n", pid, p,
- status, status_image (status));
- if (p != pid) {
- ERROR(errno, "%s waitpid pid %d in waitstopped %d status 0x%x %s\n",
- msg, pid, p, status, status_image (status));
- return False;
- }
-
- if (WIFEXITED(status)) {
- shutting_down = True;
- return False;
- }
-
- assert (WIFSTOPPED(status));
- signal_received = WSTOPSIG(status);
- if (signal_received == signal_expected)
- break;
-
- /* pid received a signal which is not the signal we are waiting for.
- We continue pid, transmitting this signal. */
- DEBUG(1, "waitstopped PTRACE_CONT with signal %d\n", signal_received);
- res = ptrace (PTRACE_CONT, pid, NULL, signal_received);
- if (res != 0) {
- ERROR(errno, "waitstopped PTRACE_CONT\n");
- return False;
- }
- }
-
- return True;
-}
-
-/* Stops the given pid, wait for the process to be stopped.
- Returns True if succesful, False otherwise.
- msg is used in tracing and error reporting. */
-static
-Bool stop (int pid, const char *msg)
-{
- long res;
-
- DEBUG(1, "%s SIGSTOP pid %d\n", msg, pid);
- res = kill (pid, SIGSTOP);
- if (res != 0) {
- ERROR(errno, "%s SIGSTOP pid %d %ld\n", msg, pid, res);
- return False;
- }
-
- return waitstopped (pid, SIGSTOP, msg);
-
-}
-
-/* Attaches to given pid, wait for the process to be stopped.
- Returns True if succesful, False otherwise.
- msg is used in tracing and error reporting. */
-static
-Bool attach (int pid, const char *msg)
-{
- long res;
- static Bool output_error = True;
- static Bool initial_attach = True;
- // For a ptrace_scope protected system, we do not want to output
- // repetitively attach error. We will output once an error
- // for the initial_attach. Once the 1st attach has succeeded, we
- // again show all errors.
-
- DEBUG(1, "%s PTRACE_ATTACH pid %d\n", msg, pid);
- res = ptrace (PTRACE_ATTACH, pid, NULL, NULL);
- if (res != 0) {
- if (output_error || debuglevel > 0) {
- ERROR(errno, "%s PTRACE_ATTACH pid %d %ld\n", msg, pid, res);
- if (initial_attach)
- output_error = False;
- }
- return False;
- }
-
- initial_attach = False;
- output_error = True;
- return waitstopped(pid, SIGSTOP, msg);
-}
-
-/* once we are attached to the pid, get the list of threads and stop
- them all.
- Returns True if all threads properly suspended, False otherwise. */
-static
-Bool acquire_and_suspend_threads(int pid)
-{
- int i;
- int rw;
- Bool pid_found = False;
- Addr vgt;
- int sz_tst;
- int off_status;
- int off_lwpid;
- int nr_live_threads = 0;
-
- if (shared32 != NULL) {
- vgt = shared32->threads;
- sz_tst = shared32->sizeof_ThreadState;
- off_status = shared32->offset_status;
- off_lwpid = shared32->offset_lwpid;
- }
- else if (shared64 != NULL) {
- vgt = shared64->threads;
- sz_tst = shared64->sizeof_ThreadState;
- off_status = shared64->offset_status;
- off_lwpid = shared64->offset_lwpid;
- } else {
- assert (0);
- }
-
- /* note: the entry 0 is unused */
- for (i = 1; i < VG_N_THREADS; i++) {
- vgt += sz_tst;
- rw = ptrace_read_memory(pid, vgt+off_status,
- &(vgdb_threads[i].status),
- sizeof(ThreadStatus));
- if (rw != 0) {
- ERROR(rw, "status ptrace_read_memory\n");
- return False;
- }
-
- rw = ptrace_read_memory(pid, vgt+off_lwpid,
- &(vgdb_threads[i].lwpid),
- sizeof(Int));
- if (rw != 0) {
- ERROR(rw, "lwpid ptrace_read_memory\n");
- return False;
- }
-
- if (vgdb_threads[i].status != VgTs_Empty) {
- DEBUG(1, "found tid %d status %s lwpid %d\n",
- i, name_of_ThreadStatus(vgdb_threads[i].status),
- vgdb_threads[i].lwpid);
- nr_live_threads++;
- if (vgdb_threads[i].lwpid <= 1) {
- if (vgdb_threads[i].lwpid == 0
- && vgdb_threads[i].status == VgTs_Init) {
- DEBUG(1, "not set lwpid tid %d status %s lwpid %d\n",
- i, name_of_ThreadStatus(vgdb_threads[i].status),
- vgdb_threads[i].lwpid);
- } else {
- ERROR(1, "unexpected lwpid tid %d status %s lwpid %d\n",
- i, name_of_ThreadStatus(vgdb_threads[i].status),
- vgdb_threads[i].lwpid);
- }
- /* in case we have a VtTs_Init thread with lwpid not yet set,
- we try again later. */
- return False;
- }
- if (vgdb_threads[i].lwpid == pid) {
- assert (!pid_found);
- assert (i == 1);
- pid_found = True;
- } else {
- if (!attach(vgdb_threads[i].lwpid, "attach_thread")) {
- ERROR(0, "ERROR attach pid %d tid %d\n",
- vgdb_threads[i].lwpid, i);
- return False;
- }
- }
- }
- }
- /* If we found no thread, it means the process is stopping, and
- we better do not force anything to happen during that. */
- if (nr_live_threads > 0)
- return True;
- else
- return False;
-}
-
-static
-void detach_from_all_threads(int pid)
-{
- int i;
- long res;
- Bool pid_found = False;
-
- /* detach from all the threads */
- for (i = 1; i < VG_N_THREADS; i++) {
- if (vgdb_threads[i].status != VgTs_Empty) {
- if (vgdb_threads[i].status == VgTs_Init
- && vgdb_threads[i].lwpid == 0) {
- DEBUG(1, "skipping PTRACE_DETACH pid %d tid %d status %s\n",
- vgdb_threads[i].lwpid, i,
- name_of_ThreadStatus (vgdb_threads[i].status));
- } else {
- if (vgdb_threads[i].lwpid == pid) {
- assert (!pid_found);
- pid_found = True;
- }
- DEBUG(1, "PTRACE_DETACH pid %d tid %d status %s\n",
- vgdb_threads[i].lwpid, i,
- name_of_ThreadStatus (vgdb_threads[i].status));
- res = ptrace (PTRACE_DETACH, vgdb_threads[i].lwpid, NULL, NULL);
- if (res != 0) {
- ERROR(errno, "PTRACE_DETACH pid %d tid %d status %s res %ld\n",
- vgdb_threads[i].lwpid, i,
- name_of_ThreadStatus (vgdb_threads[i].status),
- res);
- }
- }
- }
- }
-
- if (!pid_found && pid) {
- /* No threads are live. Process is busy stopping.
- We need to detach from pid explicitely. */
- DEBUG(1, "no thread live => PTRACE_DETACH pid %d\n", pid);
- res = ptrace (PTRACE_DETACH, pid, NULL, NULL);
- if (res != 0)
- ERROR(errno, "PTRACE_DETACH pid %d res %ld\n", pid, res);
- }
-}
-
-// if > 0, pid for which registers have to be restored.
-static int pid_of_save_regs = 0;
-static struct user user_save;
-
-// The below indicates if ptrace_getregs (and ptrace_setregs) can be used.
-// Note that some linux versions are defining PTRACE_GETREGS but using
-// it gives back EIO.
-// has_working_ptrace_getregs can take the following values:
-// -1 : PTRACE_GETREGS is defined
-// runtime check not yet done.
-// 0 : PTRACE_GETREGS runtime check has failed.
-// 1 : PTRACE_GETREGS defined and runtime check ok.
-#ifdef HAVE_PTRACE_GETREGS
-static int has_working_ptrace_getregs = -1;
-#endif
-
-/* Get the registers from pid into regs.
- regs_bsz value gives the length of *regs.
- Returns True if all ok, otherwise False. */
-static
-Bool getregs (int pid, void *regs, long regs_bsz)
-{
- DEBUG(1, "getregs regs_bsz %ld\n", regs_bsz);
-# ifdef HAVE_PTRACE_GETREGS
- if (has_working_ptrace_getregs) {
- // Platforms having GETREGS
- long res;
- DEBUG(1, "getregs PTRACE_GETREGS\n");
- res = ptrace (PTRACE_GETREGS, pid, NULL, regs);
- if (res == 0) {
- if (has_working_ptrace_getregs == -1) {
- // First call to PTRACE_GETREGS succesful =>
- has_working_ptrace_getregs = 1;
- DEBUG(1, "detected a working PTRACE_GETREGS\n");
- }
- assert (has_working_ptrace_getregs == 1);
- return True;
- }
- else if (has_working_ptrace_getregs == 1) {
- // We had a working call, but now it fails.
- // This is unexpected.
- ERROR(errno, "PTRACE_GETREGS %ld\n", res);
- return False;
- } else {
- // Check this is the first call:
- assert (has_working_ptrace_getregs == -1);
- if (errno == EIO) {
- DEBUG(1, "detected a broken PTRACE_GETREGS with EIO\n");
- has_working_ptrace_getregs = 0;
- // Fall over to the PTRACE_PEEKUSER case.
- } else {
- ERROR(errno, "broken PTRACE_GETREGS unexpected errno %ld\n", res);
- return False;
- }
- }
- }
-# endif
-
- // We assume PTRACE_PEEKUSER is defined everywhere.
- {
-# ifdef PT_ENDREGS
- long peek_bsz = PT_ENDREGS;
- assert (peek_bsz <= regs_bsz);
-# else
- long peek_bsz = regs_bsz-1;
-# endif
- char *pregs = (char *) regs;
- long offset;
- errno = 0;
- DEBUG(1, "getregs PTRACE_PEEKUSER(s) peek_bsz %ld\n", peek_bsz);
- for (offset = 0; offset < peek_bsz; offset = offset + sizeof(long)) {
- *(long *)(pregs+offset) = ptrace(PTRACE_PEEKUSER, pid, offset, NULL);
- if (errno != 0) {
- ERROR(errno, "PTRACE_PEEKUSER offset %ld\n", offset);
- return False;
- }
- }
- return True;
- }
-
- // If neither PTRACE_GETREGS not PTRACE_PEEKUSER have returned,
- // then we are in serious trouble.
- assert (0);
-}
-
-/* Set the registers of pid to regs.
- regs_bsz value gives the length of *regs.
- Returns True if all ok, otherwise False. */
-static
-Bool setregs (int pid, void *regs, long regs_bsz)
-{
- DEBUG(1, "setregs regs_bsz %ld\n", regs_bsz);
-// Note : the below is checking for GETREGS, not SETREGS
-// as if one is defined and working, the other one should also work.
-# ifdef HAVE_PTRACE_GETREGS
- if (has_working_ptrace_getregs) {
- // Platforms having SETREGS
- long res;
- // setregs can never be called before getregs has done a runtime check.
- assert (has_working_ptrace_getregs == 1);
- DEBUG(1, "setregs PTRACE_SETREGS\n");
- res = ptrace (PTRACE_SETREGS, pid, NULL, regs);
- if (res != 0) {
- ERROR(errno, "PTRACE_SETREGS %ld\n", res);
- return False;
- }
- return True;
- }
-# endif
-
- {
- char *pregs = (char *) regs;
- long offset;
- long res;
-# ifdef PT_ENDREGS
- long peek_bsz = PT_ENDREGS;
- assert (peek_bsz <= regs_bsz);
-# else
- long peek_bsz = regs_bsz-1;
-# endif
- errno = 0;
- DEBUG(1, "setregs PTRACE_POKEUSER(s) %ld\n", peek_bsz);
- for (offset = 0; offset < peek_bsz; offset = offset + sizeof(long)) {
- res = ptrace(PTRACE_POKEUSER, pid, offset, *(long*)(pregs+offset));
- if (errno != 0) {
- ERROR(errno, "PTRACE_POKEUSER offset %ld res %ld\n", offset, res);
- return False;
- }
- }
- return True;
- }
-
- // If neither PTRACE_SETREGS not PTRACE_POKEUSER have returned,
- // then we are in serious trouble.
- assert (0);
-}
-
-/* Restore the registers to the saved value, then detaches from all threads */
-static
-void restore_and_detach(int pid)
-{
- if (pid_o...
[truncated message content] |
|
From: <sv...@va...> - 2013-12-01 14:51:30
|
Author: philippe
Date: Sun Dec 1 14:51:21 2013
New Revision: 13742
Log:
Move bug fix announcement to the FIXED BUGS section
Modified:
trunk/NEWS
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sun Dec 1 14:51:21 2013
@@ -4,7 +4,6 @@
* ================== PLATFORM CHANGES =================
-328205 Implement additional Xen hypercalls
* ==================== TOOL CHANGES ====================
@@ -30,6 +29,7 @@
327238 Callgrind Assertion 'passed <= last_bb->cjmp_count' failed
327837 dwz compressed alternate .debug_info and .debug_str not read correctly
327916 DW_TAG_typedef may have no name
+328205 Implement additional Xen hypercalls
Release 3.9.0 (31 October 2013)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
From: <sv...@va...> - 2013-12-01 12:59:39
|
Author: bart
Date: Sun Dec 1 12:59:32 2013
New Revision: 13741
Log:
NEWS: Mark #328205 as fixed
Modified:
trunk/NEWS
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sun Dec 1 12:59:32 2013
@@ -4,6 +4,8 @@
* ================== PLATFORM CHANGES =================
+328205 Implement additional Xen hypercalls
+
* ==================== TOOL CHANGES ====================
* Helgrind:
|
|
From: <sv...@va...> - 2013-12-01 12:52:08
|
Author: philippe
Date: Sun Dec 1 12:52:00 2013
New Revision: 13740
Log:
Announce bug fixed for several bugs in NEWS
fixed in r13709 326983 Clear direction flag after tests on amd64.
fixed in r13712 327238 Callgrind Assertion 'passed <= last_bb->cjmp_count' failed
fixed in r13715 327837 dwz compressed alternate .debug_info and .debug_str not read correctly
fixed in r13718 327916 DW_TAG_typedef may have no name
Modified:
trunk/NEWS
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sun Dec 1 12:52:00 2013
@@ -24,7 +24,10 @@
where XXXXXX is the bug number as listed below.
-
+326983 Clear direction flag after tests on amd64.
+327238 Callgrind Assertion 'passed <= last_bb->cjmp_count' failed
+327837 dwz compressed alternate .debug_info and .debug_str not read correctly
+327916 DW_TAG_typedef may have no name
Release 3.9.0 (31 October 2013)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
From: <sv...@va...> - 2013-12-01 12:42:40
|
Author: philippe
Date: Sun Dec 1 12:42:30 2013
New Revision: 13739
Log:
Create 3.10.0 section in NEWS, add (first draft of) README_DEVELOPERS_processes
* add the new sections for next 3.10.0 release in NEWS.
* add file README_DEVELOPERS_processes.
As discussed on valdev and documented in README_DEVELOPERS_processes,
the idea is to document fixed bugs or new features in NEWS together
with the commit fixing/implementing these.
Looking at SVN, the below bugs should be added in 3.10.0 fixed bugs.
I will add them in NEWS shortly.
Thanks
Philippe
r13709 | tom | 2013-11-01 11:46:28 +0100 (Fri, 01 Nov 2013) | 2 lines
Clear direction flag after tests on amd64. BZ#326983.
r13712 | weidendo | 2013-11-12 16:32:58 +0100 (Tue, 12 Nov 2013) | 17 lines
Fix bug 327238.
assertion failure in Callgrind: bbcc.c:585 (vgCallgrind_setup_bbcc):
Assertion 'passed <= last_bb->cjmp_count' failed
r13715 | mjw | 2013-11-20 12:54:38 +0100 (Wed, 20 Nov 2013) | 5 lines
dwz compressed alternate .debug_info and .debug_str not read correctly.
Bug #327837. The buildid from the .gnu_debugaltlink section was parsed
incorrectly (from the wrong offset). Causing the debug alt file not to
be found.
r13718 | mjw | 2013-11-24 18:19:35 +0100 (Sun, 24 Nov 2013) | 5 lines
Bug 327916 - DW_TAG_typedef may have no name
We already accepted DW_TAG_typedef without a name for Ada. But g++ for
OpenMP can also emit such nameless DW_TAG_typedefs. Just accept them.
Also fix up anonymous enum and typedef printing in tytypes.c.
Added:
trunk/README_DEVELOPERS_processes
Modified:
trunk/NEWS
Modified: trunk/NEWS
==============================================================================
--- trunk/NEWS (original)
+++ trunk/NEWS Sun Dec 1 12:42:30 2013
@@ -1,3 +1,30 @@
+Release 3.10.0 (?? ?????? 201?)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+3.10.0 is not yet released.
+
+* ================== PLATFORM CHANGES =================
+
+* ==================== TOOL CHANGES ====================
+
+* Helgrind:
+
+* ==================== OTHER CHANGES ====================
+
+* ==================== FIXED BUGS ====================
+
+The following bugs have been fixed or resolved. Note that "n-i-bz"
+stands for "not in bugzilla" -- that is, a bug that was reported to us
+but never got a bugzilla entry. We encourage you to file bugs in
+bugzilla (https://bugs.kde.org/enter_bug.cgi?product=valgrind) rather
+than mailing the developers (or mailing lists) directly -- bugs that
+are not entered into bugzilla tend to get forgotten about or ignored.
+
+To see details of a given bug, visit
+ https://bugs.kde.org/show_bug.cgi?id=XXXXXX
+where XXXXXX is the bug number as listed below.
+
+
+
Release 3.9.0 (31 October 2013)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Added: trunk/README_DEVELOPERS_processes
==============================================================================
--- trunk/README_DEVELOPERS_processes (added)
+++ trunk/README_DEVELOPERS_processes Sun Dec 1 12:42:30 2013
@@ -0,0 +1,94 @@
+This file documents various "processes" that are used by Valgrind
+developers for development and release activities.
+This file contains one section for each process.
+A summary of each process is given here. Each process is described
+more in details afterwards.
+
+
+* Update of the NEWS file: NEWS describes fixed bugs and new features.
+ It is updated and committed together with the code fixing the bug/implementing
+ the feature.
+
+* Major release production:
+ See docs/internals/release-HOWTO.txt (currently a bit out of date)
+
+* Minor/correction release production: TBD
+
+
+Processes detailed descriptions:
+
+Update of the NEWS file.
+========================
+ The NEWS file gives for each release:
+ - the list of fixed bugs,
+ - a short description of each functional change,
+ - a short description of each technical change impacting the users.
+
+ The update of the NEWS file should be committed together with the
+ code change (or as part of the last committed change) that fixes the
+ bug or implements the new feature/technical change.
+ The documentation (e.g. user manual) should also be committed as part of
+ the code change.
+
+ Fixing a bug
+ ------------
+ When fixing a bug, add a line in the 'FIXED BUGS' section of
+ the NEWS file. Keep the list of bugs sorted by bugzilla entry number.
+
+ Once you have commit the change, update the bug status in bugzilla,
+ adding in the comment the revision number of the commit fixing the bug.
+
+ If a bug is not entered in bugzilla (not encouraged), use "n-i-bz"
+ and add the bug line at the end of the bug list.
+
+ The file docs/internals/X_Y_BUGSTATUS.txt (where X_Y is the last
+ major release e.g. 3_9) contains information/statuses for some bugs.
+ If a bug is fixed, remove the (possible) bug info from this file.
+
+ Implementing a change
+ ---------------------
+ When implementing a functional or 'user impacting' technical change,
+ add a short description of the change in the relevant sub-section
+ (e.g. TOOL CHANGES, PLATFORM CHANGES, ...).
+
+
+ Some special cases:
+ -------------------
+ Some bugs or changes only touch the VEX SVN repository, so it is not
+ possible to commit the NEWS change together with the code changes.
+ In such a case, first commit the VEX change. Then just after, commit
+ the NEWS change. In the bugzilla status, reference (at least) the Valgrind
+ revision number.
+
+ Some changes or bug fixes are very big and might be implemented over
+ a significant period. In such a case, update the NEWS as part of the
+ final commit.
+ If relevant, you might already update the NEWS file as part of
+ earlier commits, using the word 'PARTIAL' to indicate that the change or
+ bug fix is not complete yet.
+
+ Some bugs are reported more than once in bugzilla.
+ Also document in NEWS that such duplicated bugs have been fixed, using a line
+ such as:
+ 308333 == 307106
+ to indicate that the bug 308333 is a duplicate of 307106, and was thus
+ fixed in the commit that fixed 307106.
+ Change also the status of the duplicated bug in bugzilla,
+ indicating in the comment the commit revision that fixed the 'master bug'.
+
+
+
+Minor/correction release:
+=========================
+Describe here how to do changes and bug fixed in a minor (correction) release
+and how/when to merge the branch to the trunk.
+
+Proposal to be discussed:
+When a bug is fixed on the branch, the NEWS file is updated on the branch
+(i.e. a 3.9.1 section is created if needed).
+
+When often to merge the branch to trunk ?
+ after each fix ?
+ just after the correction release is produced ?
+
+How is the branch merged to the trunk ?
|
|
From: <sv...@va...> - 2013-12-01 10:59:14
|
Author: bart
Date: Sun Dec 1 10:59:07 2013
New Revision: 13738
Log:
xen: Implement XEN_DOMCTL_set_max_evtchn
This is new in Xen 4.4.
From: Ian Campbell <ian...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-domctl.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:59:07 2013
@@ -759,6 +759,10 @@
}
break;
+ case VKI_XEN_DOMCTL_set_max_evtchn:
+ PRE_XEN_DOMCTL_READ(set_max_evtchn, max_port);
+ break;
+
default:
bad_subop(tid, layout, arrghs, status, flags,
"__HYPERVISOR_domctl", domctl->cmd);
@@ -1149,6 +1153,7 @@
case VKI_XEN_DOMCTL_set_cpuid:
case VKI_XEN_DOMCTL_unpausedomain:
case VKI_XEN_DOMCTL_sethvmcontext:
+ case VKI_XEN_DOMCTL_set_max_evtchn:
/* No output fields */
break;
Modified: trunk/include/vki/vki-xen-domctl.h
==============================================================================
--- trunk/include/vki/vki-xen-domctl.h (original)
+++ trunk/include/vki/vki-xen-domctl.h Sun Dec 1 10:59:07 2013
@@ -84,6 +84,7 @@
#define VKI_XEN_DOMCTL_set_broken_page_p2m 67
#define VKI_XEN_DOMCTL_setnodeaffinity 68
#define VKI_XEN_DOMCTL_getnodeaffinity 69
+#define VKI_XEN_DOMCTL_set_max_evtchn 70
#define VKI_XEN_DOMCTL_gdbsx_guestmemio 1000
#define VKI_XEN_DOMCTL_gdbsx_pausevcpu 1001
#define VKI_XEN_DOMCTL_gdbsx_unpausevcpu 1002
@@ -304,6 +305,10 @@
vki_uint32_t size;
};
+struct vki_xen_domctl_set_max_evtchn {
+ vki_uint32_t max_port;
+};
+
struct vki_xen_domctl {
vki_uint32_t cmd;
vki_uint32_t interface_version; /* XEN_DOMCTL_INTERFACE_VERSION */
@@ -359,6 +364,7 @@
//struct vki_xen_domctl_set_access_required access_required;
//struct vki_xen_domctl_audit_p2m audit_p2m;
//struct vki_xen_domctl_set_virq_handler set_virq_handler;
+ struct vki_xen_domctl_set_max_evtchn set_max_evtchn;
//struct vki_xen_domctl_gdbsx_memio gdbsx_guest_memio;
//struct vki_xen_domctl_set_broken_page_p2m set_broken_page_p2m;
//struct vki_xen_domctl_gdbsx_pauseunp_vcpu gdbsx_pauseunp_vcpu;
|
|
From: <sv...@va...> - 2013-12-01 10:58:45
|
Author: bart
Date: Sun Dec 1 10:58:38 2013
New Revision: 13737
Log:
xen: XEN_SYSCTL_debugkeys hypercall
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-sysctl.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:58:38 2013
@@ -472,6 +472,14 @@
}
break;
+ case VKI_XEN_SYSCTL_debug_keys:
+ PRE_XEN_SYSCTL_READ(debug_keys, keys);
+ PRE_XEN_SYSCTL_READ(debug_keys, nr_keys);
+ PRE_MEM_READ("XEN_SYSCTL_debug_keys *keys",
+ (Addr)sysctl->u.debug_keys.keys.p,
+ sysctl->u.debug_keys.nr_keys * sizeof(char));
+ break;
+
case VKI_XEN_SYSCTL_sched_id:
/* No inputs */
break;
@@ -1100,6 +1108,10 @@
POST_MEM_WRITE((Addr)sysctl->u.numainfo.node_to_node_distance.p,
sizeof(uint32_t) * sysctl->u.numainfo.max_node_index);
break;
+
+ /* No outputs */
+ case VKI_XEN_SYSCTL_debug_keys:
+ break;
}
#undef POST_XEN_SYSCTL_WRITE
#undef __POST_XEN_SYSCTL_WRITE
Modified: trunk/include/vki/vki-xen-sysctl.h
==============================================================================
--- trunk/include/vki/vki-xen-sysctl.h (original)
+++ trunk/include/vki/vki-xen-sysctl.h Sun Dec 1 10:58:38 2013
@@ -104,6 +104,12 @@
struct vki_xenctl_bitmap cpumap; /* OUT: IF */
};
+struct vki_xen_sysctl_debug_keys {
+ /* IN variables. */
+ VKI_XEN_GUEST_HANDLE_64(char) keys;
+ vki_uint32_t nr_keys;
+};
+
struct vki_xen_sysctl_topologyinfo {
vki_uint32_t max_cpu_index;
VKI_XEN_GUEST_HANDLE_64(vki_uint32) cpu_to_core;
@@ -170,7 +176,7 @@
struct vki_xen_sysctl_getdomaininfolist_00000008 getdomaininfolist_00000008;
struct vki_xen_sysctl_getdomaininfolist_00000009 getdomaininfolist_00000009;
struct vki_xen_sysctl_getdomaininfolist_0000000a getdomaininfolist_0000000a;
- //struct vki_xen_sysctl_debug_keys debug_keys;
+ struct vki_xen_sysctl_debug_keys debug_keys;
//struct vki_xen_sysctl_getcpuinfo getcpuinfo;
//struct vki_xen_sysctl_availheap availheap;
//struct vki_xen_sysctl_get_pmstat get_pmstat;
|
|
From: <sv...@va...> - 2013-12-01 10:58:17
|
Author: bart
Date: Sun Dec 1 10:58:11 2013
New Revision: 13736
Log:
xen: XEN_SYSCTL_readconsole hypercall
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-sysctl.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:58:11 2013
@@ -433,6 +433,18 @@
__PRE_XEN_SYSCTL_READ(_sysctl, _sysctl, _field)
switch (sysctl->cmd) {
+ case VKI_XEN_SYSCTL_readconsole:
+ /* These are all unconditionally read */
+ PRE_XEN_SYSCTL_READ(readconsole, clear);
+ PRE_XEN_SYSCTL_READ(readconsole, incremental);
+ PRE_XEN_SYSCTL_READ(readconsole, buffer);
+ PRE_XEN_SYSCTL_READ(readconsole, count);
+
+ /* 'index' only read if 'incremental' is nonzero */
+ if (sysctl->u.readconsole.incremental)
+ PRE_XEN_SYSCTL_READ(readconsole, index);
+ break;
+
case VKI_XEN_SYSCTL_getdomaininfolist:
switch (sysctl->interface_version)
{
@@ -984,6 +996,11 @@
__POST_XEN_SYSCTL_WRITE(_sysctl, _sysctl, _field)
switch (sysctl->cmd) {
+ case VKI_XEN_SYSCTL_readconsole:
+ POST_MEM_WRITE((Addr)sysctl->u.readconsole.buffer.p,
+ sysctl->u.readconsole.count * sizeof(char));
+ break;
+
case VKI_XEN_SYSCTL_getdomaininfolist:
switch (sysctl->interface_version)
{
Modified: trunk/include/vki/vki-xen-sysctl.h
==============================================================================
--- trunk/include/vki/vki-xen-sysctl.h (original)
+++ trunk/include/vki/vki-xen-sysctl.h Sun Dec 1 10:58:11 2013
@@ -38,6 +38,27 @@
#define VKI_XEN_SYSCTL_scheduler_op 19
#define VKI_XEN_SYSCTL_coverage_op 20
+struct vki_xen_sysctl_readconsole {
+ /* IN */
+ vki_uint8_t clear;
+ vki_uint8_t incremental;
+
+ vki_uint8_t pad0, pad1;
+
+ /*
+ * IN: Start index for consumption if @incremental.
+ * OUT: End index after consuming from the console.
+ */
+ vki_uint32_t index;
+ VKI_XEN_GUEST_HANDLE_64(char) buffer; /* IN */
+
+ /*
+ * IN: size of buffer.
+ * OUT: bytes written into buffer.
+ */
+ vki_uint32_t count;
+};
+
struct vki_xen_sysctl_getdomaininfolist_00000008 {
/* IN variables. */
vki_xen_domid_t first_domain;
@@ -138,7 +159,7 @@
vki_uint32_t cmd;
vki_uint32_t interface_version; /* XEN_SYSCTL_INTERFACE_VERSION */
union {
- //struct vki_xen_sysctl_readconsole readconsole;
+ struct vki_xen_sysctl_readconsole readconsole;
//struct vki_xen_sysctl_tbuf_op tbuf_op;
struct vki_xen_sysctl_physinfo_00000008 physinfo_00000008;
struct vki_xen_sysctl_physinfo_0000000a physinfo_0000000a;
|
|
From: <sv...@va...> - 2013-12-01 10:57:50
|
Author: bart
Date: Sun Dec 1 10:57:43 2013
New Revision: 13735
Log:
xen: XEN_DOMCTL_shadow_op hypercall
And some of the sub-subops. It is a little hacky given the legacy way of
having several methods of enabling/disbling LOG_DIRTY mode.
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-domctl.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:57:43 2013
@@ -696,6 +696,49 @@
__PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, buffer);
break;
+ case VKI_XEN_DOMCTL_shadow_op:
+ PRE_XEN_DOMCTL_READ(shadow_op, op);
+
+ switch(domctl->u.shadow_op.op)
+ {
+ case VKI_XEN_DOMCTL_SHADOW_OP_OFF:
+ /* No further inputs */
+ break;
+
+ case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE:
+ PRE_XEN_DOMCTL_READ(shadow_op, mode);
+ switch(domctl->u.shadow_op.mode)
+ {
+ case XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY:
+ goto domctl_shadow_op_enable_logdirty;
+
+
+ default:
+ bad_subop(tid, layout, arrghs, status, flags,
+ "__HYPERVISOR_domctl shadowop mode",
+ domctl->u.shadow_op.mode);
+ break;
+ }
+
+ case VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY:
+ domctl_shadow_op_enable_logdirty:
+ /* No further inputs */
+ break;
+
+ case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN:
+ case VKI_XEN_DOMCTL_SHADOW_OP_PEEK:
+ PRE_XEN_DOMCTL_READ(shadow_op, dirty_bitmap);
+ PRE_XEN_DOMCTL_READ(shadow_op, pages);
+ break;
+
+ default:
+ bad_subop(tid, layout, arrghs, status, flags,
+ "__HYPERVISOR_domctl shadow(10)",
+ domctl->u.shadow_op.op);
+ break;
+ }
+ break;
+
default:
bad_subop(tid, layout, arrghs, status, flags,
"__HYPERVISOR_domctl", domctl->cmd);
@@ -1212,6 +1255,27 @@
domctl->u.vcpuextstate.size);
break;
+ case VKI_XEN_DOMCTL_shadow_op:
+ switch(domctl->u.shadow_op.op)
+ {
+ case VKI_XEN_DOMCTL_SHADOW_OP_OFF:
+ /* No outputs */
+ break;
+
+ case VKI_XEN_DOMCTL_SHADOW_OP_CLEAN:
+ case VKI_XEN_DOMCTL_SHADOW_OP_PEEK:
+ POST_XEN_DOMCTL_WRITE(shadow_op, pages);
+ POST_XEN_DOMCTL_WRITE(shadow_op, stats.fault_count);
+ POST_XEN_DOMCTL_WRITE(shadow_op, stats.dirty_count);
+ if(domctl->u.shadow_op.dirty_bitmap.p)
+ POST_MEM_WRITE((Addr)domctl->u.shadow_op.dirty_bitmap.p,
+ domctl->u.shadow_op.pages * sizeof(vki_uint8_t));
+ break;
+
+ default:
+ break;
+ }
+ break;
}
#undef POST_XEN_DOMCTL_WRITE
#undef __POST_XEN_DOMCTL_WRITE
Modified: trunk/include/vki/vki-xen-domctl.h
==============================================================================
--- trunk/include/vki/vki-xen-domctl.h (original)
+++ trunk/include/vki/vki-xen-domctl.h Sun Dec 1 10:57:43 2013
@@ -173,6 +173,40 @@
struct vki_xenctl_bitmap cpumap; /* IN/OUT */
};
+struct vki_xen_domctl_shadow_op_stats {
+ vki_uint32_t fault_count;
+ vki_uint32_t dirty_count;
+};
+
+/* vki_xen_domctl_shadow_op.op is an utter mess for compatibily reasons. */
+
+struct vki_xen_domctl_shadow_op {
+ vki_uint32_t op; /* IN */
+
+#define VKI_XEN_DOMCTL_SHADOW_OP_OFF 0
+#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE 32
+#define VKI_XEN_DOMCTL_SHADOW_OP_CLEAN 11
+#define VKI_XEN_DOMCTL_SHADOW_OP_PEEK 12
+#define VKI_XEN_DOMCTL_SHADOW_OP_GET_ALLOCATION 30
+#define VKI_XEN_DOMCTL_SHADOW_OP_SET_ALLOCATION 31
+
+#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_TEST 1
+#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY 2
+#define VKI_XEN_DOMCTL_SHADOW_OP_ENABLE_TRANSLATE 3
+
+ vki_uint32_t mode;
+
+#define XEN_DOMCTL_SHADOW_ENABLE_REFCOUNT (1 << 1)
+#define XEN_DOMCTL_SHADOW_ENABLE_LOG_DIRTY (1 << 2)
+#define XEN_DOMCTL_SHADOW_ENABLE_TRANSLATE (1 << 3)
+#define XEN_DOMCTL_SHADOW_ENABLE_EXTERNAL (1 << 4)
+
+ vki_uint32_t mb;
+ VKI_XEN_GUEST_HANDLE_64(vki_uint8) dirty_bitmap;
+ vki_xen_uint64_aligned_t pages;
+ struct vki_xen_domctl_shadow_op_stats stats;
+};
+
struct vki_xen_domctl_max_mem {
/* IN variables. */
vki_xen_uint64_aligned_t max_memkb;
@@ -285,7 +319,7 @@
struct vki_xen_domctl_getpageframeinfo3 getpageframeinfo3;
struct vki_xen_domctl_nodeaffinity nodeaffinity;
struct vki_xen_domctl_vcpuaffinity vcpuaffinity;
- //struct vki_xen_domctl_shadow_op shadow_op;
+ struct vki_xen_domctl_shadow_op shadow_op;
struct vki_xen_domctl_max_mem max_mem;
struct vki_xen_domctl_vcpucontext vcpucontext;
struct vki_xen_domctl_getvcpuinfo getvcpuinfo;
|
|
From: <sv...@va...> - 2013-12-01 10:57:21
|
Author: bart
Date: Sun Dec 1 10:57:14 2013
New Revision: 13734
Log:
xen: XEN_DOMCTL_sethvmcontext hypercall
Xen reads 'num' and 'array' from the structure, and reads the entire buffer.
Nothing gets written back.
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:57:14 2013
@@ -590,6 +590,14 @@
__PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, size);
break;
+ case VKI_XEN_DOMCTL_sethvmcontext:
+ __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, size);
+ __PRE_XEN_DOMCTL_READ(sethvmcontext, hvmcontext, buffer);
+ PRE_MEM_READ("XEN_DOMCTL_sethvmcontext *buffer",
+ (Addr)domctl->u.hvmcontext.buffer.p,
+ domctl->u.hvmcontext.size);
+ break;
+
case VKI_XEN_DOMCTL_max_mem:
PRE_XEN_DOMCTL_READ(max_mem, max_memkb);
break;
@@ -1068,6 +1076,7 @@
case VKI_XEN_DOMCTL_setnodeaffinity:
case VKI_XEN_DOMCTL_set_cpuid:
case VKI_XEN_DOMCTL_unpausedomain:
+ case VKI_XEN_DOMCTL_sethvmcontext:
/* No output fields */
break;
|
|
From: <sv...@va...> - 2013-12-01 10:56:34
|
Author: bart
Date: Sun Dec 1 10:56:28 2013
New Revision: 13733
Log:
xen: XEN_DOMCTL_getpageframeinfo3 hypercall
Xen reads 'num' and the 'array' pointer from ARG1, and proceeds to read and
modify-in-place the entire userspace array.
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-domctl.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:56:28 2013
@@ -673,6 +673,14 @@
(Addr)&domctl->u.cpuid, sizeof(domctl->u.cpuid));
break;
+ case VKI_XEN_DOMCTL_getpageframeinfo3:
+ PRE_XEN_DOMCTL_READ(getpageframeinfo3, num);
+ PRE_XEN_DOMCTL_READ(getpageframeinfo3, array.p);
+ PRE_MEM_READ("XEN_DOMCTL_getpageframeinfo3 *u.getpageframeinfo3.array.p",
+ (Addr)domctl->u.getpageframeinfo3.array.p,
+ domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t));
+ break;
+
case VKI_XEN_DOMCTL_getvcpuextstate:
__PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, vcpu);
__PRE_XEN_DOMCTL_READ(getvcpuextstate, vcpuextstate, xfeature_mask);
@@ -1182,6 +1190,12 @@
__POST_XEN_DOMCTL_WRITE(getvcpucontext, vcpucontext, ctxt.p);
break;
+ case VKI_XEN_DOMCTL_getpageframeinfo3:
+ POST_MEM_WRITE((Addr)domctl->u.getpageframeinfo3.array.p,
+ domctl->u.getpageframeinfo3.num * sizeof(vki_xen_pfn_t));
+ break;
+
+
case VKI_XEN_DOMCTL_getvcpuextstate:
__POST_XEN_DOMCTL_WRITE(getvcpuextstate, vcpuextstate, xfeature_mask);
__POST_XEN_DOMCTL_WRITE(getvcpuextstate, vcpuextstate, size);
Modified: trunk/include/vki/vki-xen-domctl.h
==============================================================================
--- trunk/include/vki/vki-xen-domctl.h (original)
+++ trunk/include/vki/vki-xen-domctl.h Sun Dec 1 10:56:28 2013
@@ -163,6 +163,10 @@
typedef struct vki_xen_domctl_nodeaffinity vki_xen_domctl_nodeaffinity_t;
DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_domctl_nodeaffinity_t);
+struct vki_xen_domctl_getpageframeinfo3 {
+ vki_xen_uint64_aligned_t num; /* IN */
+ VKI_XEN_GUEST_HANDLE_64(vki_xen_pfn_t) array; /* IN/OUT */
+};
struct vki_xen_domctl_vcpuaffinity {
vki_uint32_t vcpu; /* IN */
@@ -278,7 +282,7 @@
//struct vki_xen_domctl_getmemlist getmemlist;
//struct vki_xen_domctl_getpageframeinfo getpageframeinfo;
//struct vki_xen_domctl_getpageframeinfo2 getpageframeinfo2;
- //struct vki_xen_domctl_getpageframeinfo3 getpageframeinfo3;
+ struct vki_xen_domctl_getpageframeinfo3 getpageframeinfo3;
struct vki_xen_domctl_nodeaffinity nodeaffinity;
struct vki_xen_domctl_vcpuaffinity vcpuaffinity;
//struct vki_xen_domctl_shadow_op shadow_op;
|
|
From: <sv...@va...> - 2013-12-01 10:56:02
|
Author: bart
Date: Sun Dec 1 10:55:54 2013
New Revision: 13732
Log:
xen: XEN_DOMCTL_gethvmcontext hypercall
The semantics of XEN_DOMCTL_gethvmcontext are little interesting.
If the 'buffer' field of the structure is NULL, the hypercall is a request for
the required buffer size, which written into the 'size' paramater.
If 'buffer' is non NULL, Xen will write to the buffer, and update 'size' with
the amount of data written.
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-domctl.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:55:54 2013
@@ -581,6 +581,15 @@
PRE_XEN_DOMCTL_READ(createdomain, flags);
break;
+ case VKI_XEN_DOMCTL_gethvmcontext:
+ /* Xen unconditionally reads the 'buffer' pointer */
+ __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, buffer);
+ /* Xen only consumes 'size' if 'buffer' is non NULL. A NULL
+ * buffer is a request for the required size. */
+ if ( domctl->u.hvmcontext.buffer.p )
+ __PRE_XEN_DOMCTL_READ(gethvmcontext, hvmcontext, size);
+ break;
+
case VKI_XEN_DOMCTL_max_mem:
PRE_XEN_DOMCTL_READ(max_mem, max_memkb);
break;
@@ -1077,6 +1086,16 @@
POST_XEN_DOMCTL_WRITE(getvcpuinfo, cpu);
break;
+ case VKI_XEN_DOMCTL_gethvmcontext:
+ /* Xen unconditionally writes size... */
+ __POST_XEN_DOMCTL_WRITE(gethvmcontext, hvmcontext, size);
+ /* ...but only writes to the buffer if it was non NULL */
+ if ( domctl->u.hvmcontext.buffer.p )
+ POST_MEM_WRITE((Addr)domctl->u.hvmcontext.buffer.p,
+ sizeof(*domctl->u.hvmcontext.buffer.p)
+ * domctl->u.hvmcontext.size);
+ break;
+
case VKI_XEN_DOMCTL_scheduler_op:
if ( domctl->u.scheduler_op.cmd == VKI_XEN_DOMCTL_SCHEDOP_getinfo ) {
switch(domctl->u.scheduler_op.sched_id) {
Modified: trunk/include/vki/vki-xen-domctl.h
==============================================================================
--- trunk/include/vki/vki-xen-domctl.h (original)
+++ trunk/include/vki/vki-xen-domctl.h Sun Dec 1 10:55:54 2013
@@ -243,6 +243,13 @@
typedef struct vki_xen_guest_tsc_info vki_xen_guest_tsc_info_t;
DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_guest_tsc_info_t);
+struct vki_xen_domctl_hvmcontext {
+ vki_uint32_t size; /* IN/OUT size of buffer */
+ VKI_XEN_GUEST_HANDLE_64(vki_uint8) buffer; /* IN/OUT */
+};
+typedef struct vki_xen_domctl_hvmcontext vki_xen_domctl_hvmcontext_t;
+DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_domctl_hvmcontext_t);
+
struct vki_xen_domctl_tsc_info {
VKI_XEN_GUEST_HANDLE_64(vki_xen_guest_tsc_info_t) out_info; /* OUT */
vki_xen_guest_tsc_info_t info; /* IN */
@@ -291,7 +298,7 @@
//struct vki_xen_domctl_disable_migrate disable_migrate;
struct vki_xen_domctl_tsc_info tsc_info;
//struct vki_xen_domctl_real_mode_area real_mode_area;
- //struct vki_xen_domctl_hvmcontext hvmcontext;
+ struct vki_xen_domctl_hvmcontext hvmcontext;
//struct vki_xen_domctl_hvmcontext_partial hvmcontext_partial;
struct vki_xen_domctl_address_size address_size;
//struct vki_xen_domctl_sendtrigger sendtrigger;
|
|
From: <sv...@va...> - 2013-12-01 10:55:20
|
Author: bart
Date: Sun Dec 1 10:55:13 2013
New Revision: 13731
Log:
xen: XENMEM_remove_from_physmap hypercall
Xen reads the entire structure and writes nothing.
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-memory.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:55:13 2013
@@ -188,6 +188,15 @@
break;
};
+ case VKI_XENMEM_remove_from_physmap: {
+ struct vki_xen_remove_from_physmap *arg =
+ (struct vki_xen_remove_from_physmap *)ARG2;
+ PRE_MEM_READ("XENMEM_remove_from_physmap domid",
+ (Addr)&arg->domid, sizeof(arg->domid));
+ PRE_MEM_READ("XENMEM_remove_from_physmap gpfn",
+ (Addr)&arg->gpfn, sizeof(arg->gpfn));
+ }
+
case VKI_XENMEM_get_sharing_freed_pages:
case VKI_XENMEM_get_sharing_shared_pages:
break;
@@ -769,6 +778,7 @@
case VKI_XENMEM_decrease_reservation:
case VKI_XENMEM_claim_pages:
case VKI_XENMEM_maximum_gpfn:
+ case VKI_XENMEM_remove_from_physmap:
/* No outputs */
break;
case VKI_XENMEM_increase_reservation:
Modified: trunk/include/vki/vki-xen-memory.h
==============================================================================
--- trunk/include/vki/vki-xen-memory.h (original)
+++ trunk/include/vki/vki-xen-memory.h Sun Dec 1 10:55:13 2013
@@ -61,6 +61,11 @@
vki_xen_pfn_t gpfn;
};
+struct vki_xen_remove_from_physmap {
+ vki_xen_domid_t domid;
+ vki_xen_pfn_t gpfn;
+};
+
#endif // __VKI_XEN_MEMORY_H
/*--------------------------------------------------------------------*/
|
|
From: <sv...@va...> - 2013-12-01 10:54:49
|
Author: bart
Date: Sun Dec 1 10:54:42 2013
New Revision: 13730
Log:
xen: XENMEM_add_to_physmap hypercall
Xen reads the entire structure, and if the space is _gmfn, will write the
structure back
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-memory.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:54:42 2013
@@ -172,6 +172,22 @@
break;
}
+ case VKI_XENMEM_add_to_physmap: {
+ struct vki_xen_add_to_physmap *arg =
+ (struct vki_xen_add_to_physmap *)ARG2;
+ PRE_MEM_READ("XENMEM_add_to_physmap domid",
+ (Addr)&arg->domid, sizeof(arg->domid));
+ PRE_MEM_READ("XENMEM_add_to_physmap size",
+ (Addr)&arg->size, sizeof(arg->size));
+ PRE_MEM_READ("XENMEM_add_to_physmap space",
+ (Addr)&arg->space, sizeof(arg->space));
+ PRE_MEM_READ("XENMEM_add_to_physmap idx",
+ (Addr)&arg->idx, sizeof(arg->idx));
+ PRE_MEM_READ("XENMEM_add_to_physmap gpfn",
+ (Addr)&arg->gpfn, sizeof(arg->gpfn));
+ break;
+ };
+
case VKI_XENMEM_get_sharing_freed_pages:
case VKI_XENMEM_get_sharing_shared_pages:
break;
@@ -774,6 +790,13 @@
break;
}
+ case VKI_XENMEM_add_to_physmap: {
+ struct vki_xen_add_to_physmap *arg =
+ (struct vki_xen_add_to_physmap *)ARG2;
+ if (arg->space == VKI_XENMAPSPACE_gmfn_range)
+ POST_MEM_WRITE(ARG2, sizeof(*arg));
+ }
+
case VKI_XENMEM_get_sharing_freed_pages:
case VKI_XENMEM_get_sharing_shared_pages:
/* No outputs */
Modified: trunk/include/vki/vki-xen-memory.h
==============================================================================
--- trunk/include/vki/vki-xen-memory.h (original)
+++ trunk/include/vki/vki-xen-memory.h Sun Dec 1 10:54:42 2013
@@ -46,6 +46,21 @@
unsigned int nr_extents; /* OUT */
};
+struct vki_xen_add_to_physmap {
+ vki_xen_domid_t domid;
+ vki_uint16_t size;
+
+#define VKI_XENMAPSPACE_shared_info 0
+#define VKI_XENMAPSPACE_grant_table 1
+#define VKI_XENMAPSPACE_gmfn 2
+#define VKI_XENMAPSPACE_gmfn_range 3
+#define VKI_XENMAPSPACE_gmfn_foreign 4
+
+ unsigned int space;
+ vki_xen_ulong_t idx;
+ vki_xen_pfn_t gpfn;
+};
+
#endif // __VKI_XEN_MEMORY_H
/*--------------------------------------------------------------------*/
|
|
From: <sv...@va...> - 2013-12-01 10:54:13
|
Author: bart
Date: Sun Dec 1 10:54:06 2013
New Revision: 13729
Log:
xen: XENMEM_machphys_mfn_list hypercall
The XENMEM_machphys_mfn_list implementation reads 'max_extents' and
'extents_start'. It writes to the array at 'extents_start', and writes the
number of extents written into the 'nr_extents' field.
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-memory.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:54:06 2013
@@ -103,6 +103,16 @@
(Addr)ARG2, sizeof(vki_xen_domid_t));
break;
+ case VKI_XENMEM_machphys_mfn_list: {
+ struct vki_xen_machphys_mfn_list *arg =
+ (struct vki_xen_machphys_mfn_list *)ARG2;
+ PRE_MEM_READ("XENMEM_machphys_mfn_list max_extents",
+ (Addr)&arg->max_extents, sizeof(arg->max_extents));
+ PRE_MEM_READ("XENMEM_machphys_mfn_list extent_start",
+ (Addr)&arg->extent_start, sizeof(arg->extent_start));
+ break;
+ }
+
case VKI_XENMEM_set_memory_map: {
struct vki_xen_foreign_memory_map *arg =
(struct vki_xen_foreign_memory_map *)ARG2;
@@ -755,6 +765,15 @@
break;
}
+ case VKI_XENMEM_machphys_mfn_list: {
+ struct vki_xen_machphys_mfn_list *arg =
+ (struct vki_xen_machphys_mfn_list *)ARG2;
+ POST_MEM_WRITE((Addr)&arg->nr_extents, sizeof(arg->nr_extents));
+ POST_MEM_WRITE((Addr)arg->extent_start.p,
+ sizeof(vki_xen_pfn_t) * arg->nr_extents);
+ break;
+ }
+
case VKI_XENMEM_get_sharing_freed_pages:
case VKI_XENMEM_get_sharing_shared_pages:
/* No outputs */
Modified: trunk/include/vki/vki-xen-memory.h
==============================================================================
--- trunk/include/vki/vki-xen-memory.h (original)
+++ trunk/include/vki/vki-xen-memory.h Sun Dec 1 10:54:06 2013
@@ -40,6 +40,12 @@
vki_xen_domid_t domid;
};
+struct vki_xen_machphys_mfn_list {
+ unsigned int max_extents; /* IN */
+ VKI_XEN_GUEST_HANDLE(vki_xen_pfn_t) extent_start; /* OUT */
+ unsigned int nr_extents; /* OUT */
+};
+
#endif // __VKI_XEN_MEMORY_H
/*--------------------------------------------------------------------*/
|
|
From: <sv...@va...> - 2013-12-01 10:53:44
|
Author: bart
Date: Sun Dec 1 10:53:34 2013
New Revision: 13728
Log:
xen: XENMEM_maximum_gpfn hypercall
Xen reads a 16 bit domid from the pointer provided in ARG2, but does not write
anything back.
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:53:34 2013
@@ -98,6 +98,11 @@
/* No inputs */
break;
+ case VKI_XENMEM_maximum_gpfn:
+ PRE_MEM_READ("XENMEM_maximum_gpfn domid",
+ (Addr)ARG2, sizeof(vki_xen_domid_t));
+ break;
+
case VKI_XENMEM_set_memory_map: {
struct vki_xen_foreign_memory_map *arg =
(struct vki_xen_foreign_memory_map *)ARG2;
@@ -737,6 +742,7 @@
case VKI_XENMEM_set_memory_map:
case VKI_XENMEM_decrease_reservation:
case VKI_XENMEM_claim_pages:
+ case VKI_XENMEM_maximum_gpfn:
/* No outputs */
break;
case VKI_XENMEM_increase_reservation:
|
|
From: <sv...@va...> - 2013-12-01 10:53:11
|
Author: bart
Date: Sun Dec 1 10:53:05 2013
New Revision: 13727
Log:
xen: XENMEM_maximum_ram_page hypercall
Xen does not read or write any memory for this hypercall
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:53:05 2013
@@ -93,6 +93,11 @@
PRINT("__HYPERVISOR_memory_op ( %ld, %lx )", ARG1, ARG2);
switch (ARG1) {
+
+ case VKI_XENMEM_maximum_ram_page:
+ /* No inputs */
+ break;
+
case VKI_XENMEM_set_memory_map: {
struct vki_xen_foreign_memory_map *arg =
(struct vki_xen_foreign_memory_map *)ARG2;
@@ -728,6 +733,7 @@
POST(memory_op)
{
switch (ARG1) {
+ case VKI_XENMEM_maximum_ram_page:
case VKI_XENMEM_set_memory_map:
case VKI_XENMEM_decrease_reservation:
case VKI_XENMEM_claim_pages:
|
|
From: <sv...@va...> - 2013-12-01 10:52:29
|
Author: bart
Date: Sun Dec 1 10:52:22 2013
New Revision: 13726
Log:
xen: Infratructure for XEN_TMEM_* hypercalls
and an implementation of XEN_TMEM_control save_begin.
Xen will read various fields at various time, but write nothing back for a
save_begin subop.
From: Andrew Cooper <and...@ci...>
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Added:
trunk/include/vki/vki-xen-tmem.h
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:52:22 2013
@@ -670,6 +670,61 @@
#undef PRE_XEN_HVMOP_READ
}
+PRE(tmem_op)
+{
+ struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1;
+
+ PRINT("__HYPERVISOR_tmem_op ( %d )", tmem->cmd);
+
+ /* Common part for xen_tmem_op:
+ * vki_uint32_t cmd;
+ */
+ PRE_MEM_READ("__HYPERVISOR_tmem_op cmd", ARG1, sizeof(vki_uint32_t));
+
+
+#define __PRE_XEN_TMEMOP_READ(_tmem, _union, _field) \
+ PRE_MEM_READ("XEN_tmem_op_" #_tmem " u." #_union "." #_field, \
+ (Addr)&tmem->u._union._field, \
+ sizeof(tmem->u._union._field))
+#define PRE_XEN_TMEMOP_READ(_tmem, _field) \
+ __PRE_XEN_TMEMOP_READ(_tmem, _tmem, _field)
+
+ switch(tmem->cmd) {
+
+ case VKI_XEN_TMEM_control:
+
+ /* Common part for control hypercall:
+ * vki_int32_t pool_id;
+ * vki_uint32_t subop;
+ */
+ PRE_MEM_READ("__HYPERVISOR_tmem_op pool_id",
+ (Addr)&tmem->pool_id, sizeof(&tmem->pool_id));
+ PRE_XEN_TMEMOP_READ(ctrl, subop);
+
+ switch (tmem->u.ctrl.subop) {
+
+ case VKI_XEN_TMEMC_save_begin:
+ PRE_XEN_TMEMOP_READ(ctrl, cli_id);
+ PRE_XEN_TMEMOP_READ(ctrl, arg1);
+ PRE_XEN_TMEMOP_READ(ctrl, buf);
+ break;
+
+ default:
+ bad_subop(tid, layout, arrghs, status, flags,
+ "__HYPERVISOR_tmem_op_control", tmem->u.ctrl.subop);
+ }
+
+ break;
+
+ default:
+ bad_subop(tid, layout, arrghs, status, flags,
+ "__HYPERVISOR_tmem_op", ARG1);
+ }
+
+#undef PRE_XEN_TMEMOP_READ
+#undef __PRE_XEN_TMEMOP_READ
+}
+
POST(memory_op)
{
switch (ARG1) {
@@ -1080,6 +1135,24 @@
#undef POST_XEN_HVMOP_WRITE
}
+POST(tmem_op)
+{
+ struct vki_xen_tmem_op *tmem = (struct vki_xen_tmem_op *)ARG1;
+
+ switch(tmem->cmd) {
+
+ case VKI_XEN_TMEM_control:
+
+ switch(tmem->u.ctrl.subop) {
+ /* No outputs */
+ case VKI_XEN_TMEMC_save_begin:
+ break;
+ }
+
+ break;
+ }
+}
+
typedef
struct {
SyscallTableEntry entry;
@@ -1140,7 +1213,7 @@
HYPXY(__VKI_XEN_sysctl, sysctl, 1), // 35
HYPXY(__VKI_XEN_domctl, domctl, 1), // 36
// __VKI_XEN_kexec_op // 37
- // __VKI_XEN_tmem_op // 38
+ HYPXY(__VKI_XEN_tmem_op, tmem_op, 1), // 38
};
static void bad_before ( ThreadId tid,
Added: trunk/include/vki/vki-xen-tmem.h
==============================================================================
--- trunk/include/vki/vki-xen-tmem.h (added)
+++ trunk/include/vki/vki-xen-tmem.h Sun Dec 1 10:52:22 2013
@@ -0,0 +1,75 @@
+#ifndef __VKI_XEN_TMEM_H
+#define __VKI_XEN_TMEM_H
+
+typedef VKI_XEN_GUEST_HANDLE(char) vki_xen_tmem_cli_va_t;
+
+
+/* version of ABI */
+#define VKI_XEN_TMEM_spec_version 1
+
+/* Commands to HYPERVISOR_tmem_op() */
+#define VKI_XEN_TMEM_control 0
+#define VKI_XEN_TMEM_new_pool 1
+#define VKI_XEN_TMEM_destroy_pool 2
+#define VKI_XEN_TMEM_new_page 3
+#define VKI_XEN_TMEM_put_page 4
+#define VKI_XEN_TMEM_get_page 5
+#define VKI_XEN_TMEM_flush_page 6
+#define VKI_XEN_TMEM_flush_object 7
+#define VKI_XEN_TMEM_read 8
+#define VKI_XEN_TMEM_write 9
+#define VKI_XEN_TMEM_xchg 10
+/* Privileged commands to HYPERVISOR_tmem_op() */
+#define VKI_XEN_tmem_auth 101
+#define VKI_XEN_tmem_restore_new 102
+
+/* for cmd = TMEM_CONTROL */
+struct vki_xen_tmem_ctrl {
+ vki_uint32_t subop;
+
+/* Subops for HYPERVISOR_tmem_op(TMEM_CONTROL) */
+#define VKI_XEN_TMEMC_thaw 0
+#define VKI_XEN_TMEMC_freeze 1
+#define VKI_XEN_TMEMC_flush 2
+#define VKI_XEN_TMEMC_destroy 3
+#define VKI_XEN_TMEMC_list 4
+#define VKI_XEN_TMEMC_set_weight 5
+#define VKI_XEN_TMEMC_set_cap 6
+#define VKI_XEN_TMEMC_set_compress 7
+#define VKI_XEN_TMEMC_query_freeable_mb 8
+#define VKI_XEN_TMEMC_save_begin 10
+#define VKI_XEN_TMEMC_save_get_version 11
+#define VKI_XEN_TMEMC_save_get_maxpools 12
+#define VKI_XEN_TMEMC_save_get_client_weight 13
+#define VKI_XEN_TMEMC_save_get_client_cap 14
+#define VKI_XEN_TMEMC_save_get_client_flags 15
+#define VKI_XEN_TMEMC_save_get_pool_flags 16
+#define VKI_XEN_TMEMC_save_get_pool_npages 17
+#define VKI_XEN_TMEMC_save_get_pool_uuid 18
+#define VKI_XEN_TMEMC_save_get_next_page 19
+#define VKI_XEN_TMEMC_save_get_next_inv 20
+#define VKI_XEN_TMEMC_save_end 21
+#define VKI_XEN_TMEMC_restore_begin 30
+#define VKI_XEN_TMEMC_restore_put_page 32
+#define VKI_XEN_TMEMC_restore_flush_page 33
+
+ vki_uint32_t cli_id;
+ vki_uint32_t arg1;
+ vki_uint32_t arg2;
+ vki_uint64_t oid[3];
+ vki_xen_tmem_cli_va_t buf;
+};
+
+struct vki_xen_tmem_op {
+ vki_uint32_t cmd;
+ vki_int32_t pool_id;
+ union {
+ struct vki_xen_tmem_ctrl ctrl;
+ } u;
+};
+
+#endif // __VKI_XEN_TMEM_H
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
Modified: trunk/include/vki/vki-xen.h
==============================================================================
--- trunk/include/vki/vki-xen.h (original)
+++ trunk/include/vki/vki-xen.h Sun Dec 1 10:52:22 2013
@@ -58,6 +58,7 @@
#endif
DEFINE_VKI_XEN_GUEST_HANDLE(void);
+DEFINE_VKI_XEN_GUEST_HANDLE(char);
DEFINE_VKI_XEN_GUEST_HANDLE(vki_xen_pfn_t);
__DEFINE_VKI_XEN_GUEST_HANDLE(vki_ulong, unsigned long);
@@ -84,6 +85,7 @@
#include <vki/vki-xen-gnttab.h>
#include <vki/vki-xen-version.h>
#include <vki/vki-xen-hvm.h>
+#include <vki/vki-xen-tmem.h>
#endif // __VKI_XEN_H
|
|
From: <sv...@va...> - 2013-12-01 10:51:30
|
Author: bart
Date: Sun Dec 1 10:51:19 2013
New Revision: 13725
Log:
xen: Fix XEN_SYSCTL_getdomaininfolist for version 0xa
From: Andrew Cooper <and...@ci...>
Also add a default case so future bumps of the sysctl interface version dont
result in spurious passes of the IOCTL handler.
Signed-off-by: Andrew Cooper <and...@ci...>
Signed-off-by: Ian Campbell <ian...@ci...>
Modified:
trunk/coregrind/m_syswrap/syswrap-xen.c
trunk/include/vki/vki-xen-sysctl.h
Modified: trunk/coregrind/m_syswrap/syswrap-xen.c
==============================================================================
--- trunk/coregrind/m_syswrap/syswrap-xen.c (original)
+++ trunk/coregrind/m_syswrap/syswrap-xen.c Sun Dec 1 10:51:19 2013
@@ -401,6 +401,17 @@
PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, max_domains);
PRE_XEN_SYSCTL_READ(getdomaininfolist_00000009, buffer);
break;
+ case 0x0000000a:
+ PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, first_domain);
+ PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, max_domains);
+ PRE_XEN_SYSCTL_READ(getdomaininfolist_0000000a, buffer);
+ break;
+ default:
+ VG_(dmsg)("WARNING: XEN_SYSCTL_getdomaininfolist for sysctl version "
+ "%"PRIx32" not implemented yet\n",
+ sysctl->interface_version);
+ SET_STATUS_Failure(VKI_EINVAL);
+ return;
}
break;
@@ -801,6 +812,12 @@
sizeof(*sysctl->u.getdomaininfolist_00000009.buffer.p)
* sysctl->u.getdomaininfolist_00000009.num_domains);
break;
+ case 0x0000000a:
+ POST_XEN_SYSCTL_WRITE(getdomaininfolist_0000000a, num_domains);
+ POST_MEM_WRITE((Addr)sysctl->u.getdomaininfolist_0000000a.buffer.p,
+ sizeof(*sysctl->u.getdomaininfolist_0000000a.buffer.p)
+ * sysctl->u.getdomaininfolist_0000000a.num_domains);
+ break;
}
break;
Modified: trunk/include/vki/vki-xen-sysctl.h
==============================================================================
--- trunk/include/vki/vki-xen-sysctl.h (original)
+++ trunk/include/vki/vki-xen-sysctl.h Sun Dec 1 10:51:19 2013
@@ -56,6 +56,15 @@
vki_uint32_t num_domains;
};
+struct vki_xen_sysctl_getdomaininfolist_0000000a {
+ /* IN variables. */
+ vki_xen_domid_t first_domain;
+ vki_uint32_t max_domains;
+ VKI_XEN_GUEST_HANDLE_64(vki_xen_domctl_getdomaininfo_00000009_t) buffer;
+ /* OUT variables. */
+ vki_uint32_t num_domains;
+};
+
#define VKI_XEN_SYSCTL_CPUPOOL_OP_CREATE 1 /* C */
#define VKI_XEN_SYSCTL_CPUPOOL_OP_DESTROY 2 /* D */
#define VKI_XEN_SYSCTL_CPUPOOL_OP_INFO 3 /* I */
@@ -139,6 +148,7 @@
//struct vki_xen_sysctl_perfc_op perfc_op;
struct vki_xen_sysctl_getdomaininfolist_00000008 getdomaininfolist_00000008;
struct vki_xen_sysctl_getdomaininfolist_00000009 getdomaininfolist_00000009;
+ struct vki_xen_sysctl_getdomaininfolist_0000000a getdomaininfolist_0000000a;
//struct vki_xen_sysctl_debug_keys debug_keys;
//struct vki_xen_sysctl_getcpuinfo getcpuinfo;
//struct vki_xen_sysctl_availheap availheap;
|