mirror of
https://github.com/Zenithsiz/ftmemsim-valgrind.git
synced 2026-02-04 02:18:37 +00:00
At various places, there were either some assumption that the 'end'
boundary (highest address) was either not included, included,
or was the highest addressable word, or the highest addressable byte.
This e.g. was very visible when doing:
./vg-in-place -d -d ./helgrind/tests/tc01_simple_race|&grep regi
giving
--24040:2:stacks register 0xBEDB4000-0xBEDB4FFF as stack 0
--24040:2:stacks register 0x402C000-0x4A2C000 as stack 1
showing that the main stack end was (on x86) not the highest word
but the highest byte, while for the thread 1, the registered end
was a byte not part of the stack.
The attached patch ensures that stack bounds semantic are documented and
consistent. Also, some of the stack handling code is factorised.
The convention that the patch ensures and documents is:
start is the lowest addressable byte, end is the highest addressable byte.
(the words 'min' and 'max' have been kept when already used, as this wording is
consistent with the new semantic of start/end).
In various debug log, used brackets [ and ] to make clear that
both bounds are included.
The code to guess and register the client stack was duplicated
in all the platform specific syswrap-<plat>-<os>.c files.
Code has been factorised in syswrap-generic.c
The patch has been regression tested on
x86, amd64, ppc32/64, s390x.
It has been compiled and one test run on arm64.
Not compiled/not tested on darwin, android, mips32/64, arm
More in details, the patch does the following:
coregrind/pub_core_aspacemgr.h
include/valgrind.h
include/pub_tool_machine.h
coregrind/pub_core_scheduler.h
coregrind/pub_core_stacks.h
- document start/end semantic in various functions
also in pub_tool_machine.h:
- replaces unclear 'bottommost address' by 'lowest address'
(unclear as stack bottom is or at least can be interpreted as
the 'functional' bottom of the stack, which is the highest
address for 'stack growing downwards').
coregrind/pub_core_initimg.h
replace unclear clstack_top by clstack_end
coregrind/m_main.c
updated to clstack_end
coregrind/pub_core_threadstate.h
renamed client_stack_highest_word to client_stack_highest_byte
coregrind/m_scheduler/scheduler.c
computes client_stack_highest_byte as the highest addressable byte
Update comments in call to VG_(show_sched_status)
coregrind/m_machine.c
coregrind/m_stacktrace.c
updated to client_stack_highest_byte, and switched
stack_lowest/highest_word to stack_lowest/highest_byte accordingly
coregrind/m_stacks.c
clarify semantic of start/end,
added a comment to indicate why we invert start/end in register call
(note that the code find_stack_by_addr was already assuming that
end was included as the checks were doing e.g.
sp >= i->start && sp <= i->end
coregrind/pub_core_clientstate.h
coregrind/m_clientstate.c
renames Addr VG_(clstk_base) to Addr VG_(clstk_start_base)
(start to indicate it is the lowest address, base suffix kept
to indicate it is the initial lowest address).
coregrind/m_initimg/initimg-darwin.c
updated to VG_(clstk_start_base)
replace unclear iicii.clstack_top by iicii.clstack_end
updated clstack_max_size computation according to both bounds included.
coregrind/m_initimg/initimg-linux.c
updated to VG_(clstk_start_base)
updated VG_(clstk_end) computation according to both bounds included.
replace unclear iicii.clstack_top by iicii.clstack_end
coregrind/pub_core_aspacemgr.h
extern Addr VG_(am_startup) : clarify semantic of the returned value
coregrind/m_aspacemgr/aspacemgr-linux.c
removed a copy of a comment that was already in pub_core_aspacemgr.h
(avoid double maintenance)
renamed unclear suggested_clstack_top to suggested_clstack_end
(note that here, it looks like suggested_clstack_top was already
the last addressable byte)
* factorisation of the stack guessing and registration causes
mechanical changes in the following files:
coregrind/m_syswrap/syswrap-ppc64-linux.c
coregrind/m_syswrap/syswrap-x86-darwin.c
coregrind/m_syswrap/syswrap-amd64-linux.c
coregrind/m_syswrap/syswrap-arm-linux.c
coregrind/m_syswrap/syswrap-generic.c
coregrind/m_syswrap/syswrap-mips64-linux.c
coregrind/m_syswrap/syswrap-ppc32-linux.c
coregrind/m_syswrap/syswrap-amd64-darwin.c
coregrind/m_syswrap/syswrap-mips32-linux.c
coregrind/m_syswrap/priv_syswrap-generic.h
coregrind/m_syswrap/syswrap-x86-linux.c
coregrind/m_syswrap/syswrap-s390x-linux.c
coregrind/m_syswrap/syswrap-darwin.c
coregrind/m_syswrap/syswrap-arm64-linux.c
Some files to look at more in details:
syswrap-darwin.c : the handling of sysctl(kern.usrstack) looked
buggy to me, and has probably be made correct by the fact that
VG_(clstk_end) is now the last addressable byte. However,unsure
about this, as I could not find any documentation about
sysctl(kern.usrstack). I only find several occurences on the web,
showing that the result of this is page aligned, which I guess
means it must be 1+ the last addressable byte.
syswrap-x86-darwin.c and syswrap-amd64-darwin.c
I suspect the code that was computing client_stack_highest_word
was wrong, and the patch makes it correct.
syswrap-mips64-linux.c
not sure what to do for this code. This is the only code
that was guessing the stack differently from others.
Kept (almost) untouched. To be discussed with mips maintainers.
coregrind/pub_core_libcassert.h
coregrind/m_libcassert.c
* void VG_(show_sched_status):
renamed Bool valgrind_stack_usage to Bool stack_usage
if stack_usage, shows both the valgrind stack usage and
the client stack boundaries
coregrind/m_scheduler/scheduler.c
coregrind/m_gdbserver/server.c
coregrind/m_gdbserver/remote-utils.c
Updated comments in callers to VG_(show_sched_status)
git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14392
188 lines
7.6 KiB
C
188 lines
7.6 KiB
C
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- Machine-related stuff. pub_tool_machine.h ---*/
|
|
/*--------------------------------------------------------------------*/
|
|
|
|
/*
|
|
This file is part of Valgrind, a dynamic binary instrumentation
|
|
framework.
|
|
|
|
Copyright (C) 2000-2013 Julian Seward
|
|
jseward@acm.org
|
|
|
|
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.
|
|
*/
|
|
|
|
#ifndef __PUB_TOOL_MACHINE_H
|
|
#define __PUB_TOOL_MACHINE_H
|
|
|
|
#include "pub_tool_basics.h" // ThreadID
|
|
#include "libvex.h" // VexArchInfo
|
|
|
|
#if defined(VGP_x86_linux)
|
|
# define VG_MIN_INSTR_SZB 1 // min length of native instruction
|
|
# define VG_MAX_INSTR_SZB 16 // max length of native instruction
|
|
# define VG_CLREQ_SZB 14 // length of a client request, may
|
|
// be larger than VG_MAX_INSTR_SZB
|
|
# define VG_STACK_REDZONE_SZB 0 // number of addressable bytes below %RSP
|
|
|
|
#elif defined(VGP_amd64_linux)
|
|
# define VG_MIN_INSTR_SZB 1
|
|
# define VG_MAX_INSTR_SZB 16
|
|
# define VG_CLREQ_SZB 19
|
|
# define VG_STACK_REDZONE_SZB 128
|
|
|
|
#elif defined(VGP_ppc32_linux)
|
|
# define VG_MIN_INSTR_SZB 4
|
|
# define VG_MAX_INSTR_SZB 4
|
|
# define VG_CLREQ_SZB 20
|
|
# define VG_STACK_REDZONE_SZB 0
|
|
|
|
#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
|
|
# define VG_MIN_INSTR_SZB 4
|
|
# define VG_MAX_INSTR_SZB 4
|
|
# define VG_CLREQ_SZB 20
|
|
# define VG_STACK_REDZONE_SZB 288 // number of addressable bytes below R1
|
|
// from 64-bit PowerPC ELF ABI
|
|
// Supplement 1.7
|
|
|
|
#elif defined(VGP_arm_linux)
|
|
# define VG_MIN_INSTR_SZB 2
|
|
# define VG_MAX_INSTR_SZB 4
|
|
# define VG_CLREQ_SZB 20
|
|
# define VG_STACK_REDZONE_SZB 0
|
|
|
|
#elif defined(VGP_arm64_linux)
|
|
# define VG_MIN_INSTR_SZB 4
|
|
# define VG_MAX_INSTR_SZB 4
|
|
# define VG_CLREQ_SZB 20
|
|
# define VG_STACK_REDZONE_SZB 0
|
|
|
|
#elif defined(VGP_s390x_linux)
|
|
# define VG_MIN_INSTR_SZB 2
|
|
# define VG_MAX_INSTR_SZB 6
|
|
# define VG_CLREQ_SZB 10
|
|
# define VG_STACK_REDZONE_SZB 0 // s390 has no redzone
|
|
|
|
#elif defined(VGP_x86_darwin)
|
|
# define VG_MIN_INSTR_SZB 1 // min length of native instruction
|
|
# define VG_MAX_INSTR_SZB 16 // max length of native instruction
|
|
# define VG_CLREQ_SZB 14 // length of a client request, may
|
|
// be larger than VG_MAX_INSTR_SZB
|
|
# define VG_STACK_REDZONE_SZB 0 // number of addressable bytes below %RSP
|
|
|
|
#elif defined(VGP_amd64_darwin)
|
|
# define VG_MIN_INSTR_SZB 1
|
|
# define VG_MAX_INSTR_SZB 16
|
|
# define VG_CLREQ_SZB 19
|
|
# define VG_STACK_REDZONE_SZB 128
|
|
|
|
#elif defined(VGP_mips32_linux)
|
|
# define VG_MIN_INSTR_SZB 4
|
|
# define VG_MAX_INSTR_SZB 4
|
|
# define VG_CLREQ_SZB 20
|
|
# define VG_STACK_REDZONE_SZB 0
|
|
|
|
#elif defined(VGP_mips64_linux)
|
|
# define VG_MIN_INSTR_SZB 4
|
|
# define VG_MAX_INSTR_SZB 4
|
|
# define VG_CLREQ_SZB 20
|
|
# define VG_STACK_REDZONE_SZB 0
|
|
|
|
#else
|
|
# error Unknown platform
|
|
#endif
|
|
|
|
// Guest state accessors
|
|
// Are mostly in the core_ header.
|
|
// Only these two are available to tools.
|
|
Addr VG_(get_IP) ( ThreadId tid );
|
|
Addr VG_(get_SP) ( ThreadId tid );
|
|
|
|
|
|
// For get/set, 'area' is where the asked-for guest state will be copied
|
|
// into/from. If shadowNo == 0, the real (non-shadow) guest state is
|
|
// accessed. If shadowNo == 1, the first shadow area is accessed, and
|
|
// if shadowNo == 2, the second shadow area is accessed. This gives a
|
|
// completely general way to read/modify a thread's guest register state
|
|
// providing you know the offsets you need.
|
|
void
|
|
VG_(get_shadow_regs_area) ( ThreadId tid,
|
|
/*DST*/UChar* dst,
|
|
/*SRC*/Int shadowNo, PtrdiffT offset, SizeT size );
|
|
void
|
|
VG_(set_shadow_regs_area) ( ThreadId tid,
|
|
/*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
|
|
/*SRC*/const UChar* src );
|
|
|
|
// Apply a function 'f' to all the general purpose registers in all the
|
|
// current threads. This is all live threads, or (when the process is exiting)
|
|
// all threads that were instructed to die by the thread calling exit.
|
|
// This is very Memcheck-specific -- it's used to find the roots when
|
|
// doing leak checking.
|
|
extern void VG_(apply_to_GP_regs)(void (*f)(ThreadId tid,
|
|
const HChar* regname, UWord val));
|
|
|
|
// This iterator lets you inspect each live thread's stack bounds.
|
|
// Returns False at the end. 'tid' is the iterator and you can only
|
|
// safely change it by making calls to these functions.
|
|
extern void VG_(thread_stack_reset_iter) ( /*OUT*/ThreadId* tid );
|
|
// stack_min is the address of the lowest stack byte,
|
|
// stack_max is the address of the highest stack byte.
|
|
// In other words, the live stack is [stack_min, stack_max].
|
|
extern Bool VG_(thread_stack_next) ( /*MOD*/ThreadId* tid,
|
|
/*OUT*/Addr* stack_min,
|
|
/*OUT*/Addr* stack_max );
|
|
|
|
// Returns .client_stack_highest_byte for the given thread
|
|
// i.e. the highest addressable byte of the stack.
|
|
extern Addr VG_(thread_get_stack_max) ( ThreadId tid );
|
|
|
|
// Returns how many bytes have been allocated for the stack of the given thread
|
|
extern SizeT VG_(thread_get_stack_size) ( ThreadId tid );
|
|
|
|
// Returns the lowest address of the alternate signal stack.
|
|
// See also the man page of sigaltstack().
|
|
extern Addr VG_(thread_get_altstack_min) ( ThreadId tid );
|
|
|
|
// Returns how many bytes have been allocated for the alternate signal stack.
|
|
// See also the man page of sigaltstack().
|
|
extern SizeT VG_(thread_get_altstack_size) ( ThreadId tid );
|
|
|
|
// Given a pointer to a function as obtained by "& functionname" in C,
|
|
// produce a pointer to the actual entry point for the function. For
|
|
// most platforms it's the identity function. Unfortunately, on
|
|
// ppc64-linux it isn't (sigh).
|
|
extern void* VG_(fnptr_to_fnentry)( void* );
|
|
|
|
/* Returns the size of the largest guest register that we will
|
|
simulate in this run. This depends on both the guest architecture
|
|
and on the specific capabilities we are simulating for that guest
|
|
(eg, AVX or non-AVX ?, for amd64). */
|
|
extern Int VG_(machine_get_size_of_largest_guest_register) ( void );
|
|
|
|
/* Return host cpu info. */
|
|
extern void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch*,
|
|
/*OUT*/VexArchInfo* );
|
|
|
|
#endif // __PUB_TOOL_MACHINE_H
|
|
|
|
/*--------------------------------------------------------------------*/
|
|
/*--- end ---*/
|
|
/*--------------------------------------------------------------------*/
|