Improvements for Android:

* All Linux targets: add minimal ioctl support for the ION_IOC family

* Android targets: change proprietary-ioctl support for GPUs from
  being a build-time #define kludge to being controlled by --kernel-variant,
  as it should be.  Update documentation accordingly.



git-svn-id: svn://svn.valgrind.org/valgrind/trunk@14440
This commit is contained in:
Julian Seward 2014-09-03 15:19:25 +00:00
parent f5b14667aa
commit 7e3f04874a
10 changed files with 237 additions and 145 deletions

3
NEWS
View File

@ -27,6 +27,9 @@ significantly improved relative to the 3.9.0 release.
* Both 32- and 64-bit executables are supported on MacOSX 10.8 and 10.9.
* Configuration for and running on Android targets has changed.
See README.android in the source tree for details.
* ================== DEPRECATED FEATURES =================
* --db-attach is now deprecated and will be removed in the next

View File

@ -1,9 +1,15 @@
How to cross-compile for Android. These notes were last updated on
17 Feb 2012, for Valgrind SVN revision 12390/2257.
How to cross-compile and run on Android. Please read to the end,
since there are important details further down regarding crash
avoidance and GPU support.
This is known to work at least for :
ARM:
These notes were last updated on 3 Sept 2014, for Valgrind SVN
revision 14439/2941.
These instructions are known to work, or have worked at some time in
the past, for:
arm:
Android 4.0.3 running on a (rooted, AOSP build) Nexus S.
Android 4.0.3 running on Motorola Xoom.
Android 4.0.3 running on android arm emulator.
@ -34,7 +40,7 @@ install them are described in README.android_emulator.
You can get android-ndk-r6 from
http://dl.google.com/android/ndk/android-ndk-r6-linux-x86.tar.bz2
Install it somewhere. Doesn't matter where. Then do this:
Install it somewhere. Doesn't matter where. Then:
# Modify this (obviously). Note, this "export" command is only done
@ -44,25 +50,12 @@ Install it somewhere. Doesn't matter where. Then do this:
export NDKROOT=/path/to/android-ndk-r6
# Modify this too. Tell the build system which Android hardware you
# are building for. It needs to know this so it can compile in
# support for the right Android-hw-specific ioctls. (sigh.) As with
# NDKROOT above, this is merely to avoid repeated typing; none of the
# commands read it.
#
# Currently the supported values are: nexus_s pandaboard
# So choose one of the below:
#
export HWKIND=nexus_s # Samsung Nexus S; also Xoom (for now)
export HWKIND=generic # A generic Android device. eg, Pandaboard
export HWKIND=emulator # Android emulator
# Then cd to the root of your Valgrind source tree.
#
cd /path/to/valgrind/source/tree
# After this point, you don't need to modify anything; just copy and
# After this point, you don't need to modify anything. Just copy and
# paste the commands below.
@ -83,6 +76,7 @@ export AR=$NDKROOT/toolchains/mipsel-linux-android-4.8/prebuilt/linux-x86_64/bin
export LD=$NDKROOT/toolchains/mipsel-linux-android-4.8/prebuilt/linux-x86_64/bin/mipsel-linux-android-ld
export CC=$NDKROOT/toolchains/mipsel-linux-android-4.8/prebuilt/linux-x86_64/bin/mipsel-linux-android-gcc
# Do configuration stuff. Don't mess with the --prefix in the
# configure command below, even if you think it's wrong.
# You may need to set the --with-tmpdir path to something
@ -94,7 +88,7 @@ export CC=$NDKROOT/toolchains/mipsel-linux-android-4.8/prebuilt/linux-x86_64/bin
./autogen.sh
# for ARM
CPPFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm -DANDROID_HARDWARE_$HWKIND" \
CPPFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm" \
CFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm" \
./configure --prefix=/data/local/Inst \
--host=armv7-unknown-linux --target=armv7-unknown-linux \
@ -103,19 +97,20 @@ CPPFLAGS="--sysroot=$NDKROOT/platforms/android-3/arch-arm -DANDROID_HARDWARE_$HW
# It is not clear what this platform nr really is.
# for x86
CPPFLAGS="--sysroot=$NDKROOT/platforms/android-9/arch-x86 -DANDROID_HARDWARE_$HWKIND" \
CPPFLAGS="--sysroot=$NDKROOT/platforms/android-9/arch-x86" \
CFLAGS="--sysroot=$NDKROOT/platforms/android-9/arch-x86 -fno-pic" \
./configure --prefix=/data/local/Inst \
--host=i686-android-linux --target=i686-android-linux \
--with-tmpdir=/sdcard
# for MIPS32
CPPFLAGS="--sysroot=$NDKROOT/platforms/android-18/arch-mips -DANDROID_HARDWARE_$HWKIND" \
CPPFLAGS="--sysroot=$NDKROOT/platforms/android-18/arch-mips" \
CFLAGS="--sysroot=$NDKROOT/platforms/android-18/arch-mips" \
./configure --prefix=/data/local/Inst \
--host=mipsel-linux-android --target=mipsel-linux-android \
--with-tmpdir=/sdcard
# At the end of the configure run, a few lines of details
# are printed. Make sure that you see these two lines:
#
@ -148,8 +143,26 @@ make -j2 install DESTDIR=`pwd`/Inst
#
adb push Inst /
# To run (on the device)
/data/local/Inst/bin/valgrind [the usual args etc]
# To run (on the device). There are two things you need to consider:
#
# (1) if you are running on the Android emulator, Valgrind may crash
# at startup. This is because the emulator (for ARM) may not be
# simulating a hardware TLS register. To get around this, run
# Valgrind with:
# --kernel-variant=android-emulator-no-hw-tls
#
# (2) if you are running a real device, you need to tell Valgrind
# what GPU it has, so Valgrind knows how to handle custom GPU
# ioctls. You can choose one of the following:
# --kernel-variant=android-gpu-sgx5xx # PowerVR SGX 5XX series
# --kernel-variant=android-gpu-adreno3xx # Qualcomm Adreno 3XX series
# If you don't choose one, the program will still run, but Memcheck
# may report false errors after the program performs GPU-specific ioctls.
#
# Anyway: to run on the device:
#
/data/local/Inst/bin/valgrind [kernel variant args] [the usual args etc]
# Once you're up and running, a handy modify-V-rebuild-reinstall

View File

@ -61,6 +61,14 @@ adb shell
adb push Inst /
# IMPORTANT: when running Valgrind, you may need give it the flag
#
# --kernel-variant=android-emulator-no-hw-tls
#
# since otherwise it may crash at startup.
# See README.android for details.
# if you need to debug:
# You have on the android side a gdbserver
# on the device side:

View File

@ -179,9 +179,11 @@ static void usage_NORETURN ( Bool debug_help )
" where hint is one of lax-ioctls fuse-compatible enable-outer\n"
" no-inner-prefix no-nptl-pthread-stackcache none\n"
" --fair-sched=no|yes|try schedule threads fairly on multicore systems [no]\n"
" --kernel-variant=variant1,variant2,... handle non-standard kernel"
" variants [none]\n"
" where variant is one of bproc none\n"
" --kernel-variant=variant1,variant2,...\n"
" handle non-standard kernel variants [none]\n"
" where variant is one of:\n"
" bproc android-emulator-no-hw-tls\n"
" android-gpu-sgx5xx android-gpu-adreno3xx none\n"
" --merge-recursive-frames=<number> merge frames between identical\n"
" program counters in max <number> frames) [0]\n"
" --num-transtab-sectors=<number> size of translated code cache [%d]\n"
@ -627,7 +629,11 @@ void main_process_cmd_line_options ( /*OUT*/Bool* logging_to_fd,
VG_(clo_smc_check),
Vg_SmcAllNonFile);
else if VG_USETX_CLO (arg, "--kernel-variant", "bproc",
else if VG_USETX_CLO (arg, "--kernel-variant",
"bproc,"
"android-emulator-no-hw-tls,"
"android-gpu-sgx5xx,"
"android-gpu-adreno3xx",
VG_(clo_kernel_variant)) {}
else if VG_BOOL_CLO(arg, "--dsymutil", VG_(clo_dsymutil)) {}

View File

@ -280,41 +280,43 @@ static void assign_guest_tls(ThreadId tid, Addr tlsptr)
static SysRes sys_set_tls ( ThreadId tid, Addr tlsptr )
{
assign_guest_tls(tid, tlsptr);
#if defined(ANDROID_HARDWARE_emulator)
/* Android emulator does not provide an hw tls register.
So, the tls register is emulated by the kernel.
This emulated value is set by the __NR_ARM_set_tls syscall.
The emulated value must be read by the kernel helper function
located at 0xffff0fe0.
The emulated tlsptr is located at 0xffff0ff0
(so slightly after the kernel helper function).
Note that applications are not supposed to read this directly.
For compatibility : if there is a hw tls register, the kernel
will put at 0xffff0fe0 the instructions to read it, so
as to have old applications calling the kernel helper
working properly.
For having emulated guest TLS working correctly with
Valgrind, it is needed to execute the syscall to set
the emulated TLS value in addition to the assignment
of TPIDRURO.
if (KernelVariantiS(KernelVariant_android_emulator_no_hw_tls,
VG_(clo_kernel_variant))) {
/* Android emulator does not provide an hw tls register.
So, the tls register is emulated by the kernel.
This emulated value is set by the __NR_ARM_set_tls syscall.
The emulated value must be read by the kernel helper function
located at 0xffff0fe0.
The emulated tlsptr is located at 0xffff0ff0
(so slightly after the kernel helper function).
Note that applications are not supposed to read this directly.
For compatibility : if there is a hw tls register, the kernel
will put at 0xffff0fe0 the instructions to read it, so
as to have old applications calling the kernel helper
working properly.
Note: the below means that if we need thread local storage
for Valgrind host, then there will be a conflict between
the need of the guest tls and of the host tls.
If all the guest code would cleanly call 0xffff0fe0,
then we might maybe intercept this. However, at least
__libc_preinit reads directly 0xffff0ff0.
*/
/* ??? might call the below if auxv->u.a_val & VKI_HWCAP_TLS ???
Unclear if real hardware having tls hw register sets
VKI_HWCAP_TLS. */
return VG_(do_syscall1) (__NR_ARM_set_tls, tlsptr);
#else
return VG_(mk_SysRes_Success)( 0 );
#endif
For having emulated guest TLS working correctly with
Valgrind, it is needed to execute the syscall to set
the emulated TLS value in addition to the assignment
of TPIDRURO.
Note: the below means that if we need thread local storage
for Valgrind host, then there will be a conflict between
the need of the guest tls and of the host tls.
If all the guest code would cleanly call 0xffff0fe0,
then we might maybe intercept this. However, at least
__libc_preinit reads directly 0xffff0ff0.
*/
/* ??? might call the below if auxv->u.a_val & VKI_HWCAP_TLS ???
Unclear if real hardware having tls hw register sets
VKI_HWCAP_TLS. */
return VG_(do_syscall1) (__NR_ARM_set_tls, tlsptr);
} else {
return VG_(mk_SysRes_Success)( 0 );
}
}
/* ---------------------------------------------------------------------

View File

@ -7149,99 +7149,95 @@ POST(sys_ioctl)
/* --- BEGIN special IOCTL handlers for specific Android hardware --- */
# if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) \
|| defined(VGPV_mips32_linux_android)
/* BEGIN undocumented ioctls for PowerVR SGX 540 (the GPU on Nexus S) */
if (KernelVariantiS(KernelVariant_android_gpu_sgx5xx,
VG_(clo_kernel_variant))) {
# if defined(ANDROID_HARDWARE_nexus_s)
if (ARG2 >= 0xC01C6700 && ARG2 <= 0xC01C67FF && ARG3 >= 0x1000) {
/* What's going on here: there appear to be a bunch of ioctls
of the form 0xC01C67xx which are undocumented, and if
unhandled give rise to a vast number of false positives in
Memcheck.
/* BEGIN undocumented ioctls for the graphics hardware (??)
(libpvr) on Nexus S */
if (ARG2 >= 0xC01C6700 && ARG2 <= 0xC01C67FF && ARG3 >= 0x1000) {
/* What's going on here: there appear to be a bunch of ioctls of
the form 0xC01C67xx which are undocumented, and if unhandled
give rise to a vast number of false positives in Memcheck.
The "normal" interpretation of an ioctl of this form would
be that the 3rd arg is a pointer to an area of size 0x1C
(28 bytes) which is filled in by the kernel. Hence you
might think that "POST_MEM_WRITE(ARG3, 28)" would fix it.
But it doesn't.
The "normal" intrepretation of an ioctl of this form would be
that the 3rd arg is a pointer to an area of size 0x1C (28
bytes) which is filled in by the kernel. Hence you might
think that "POST_MEM_WRITE(ARG3, 28)" would fix it. But it
doesn't.
It requires POST_MEM_WRITE(ARG3, 256) to silence them.
One interpretation of this is that ARG3 really does point
to a 28 byte struct, but inside that are pointers to other
areas also filled in by the kernel. If these happen to be
allocated just back up the stack then the 256 byte paint
might cover them too, somewhat indiscriminately.
It requires POST_MEM_WRITE(ARG3, 256) to silence them. One
interpretation of this is that ARG3 really does point to a 28
byte struct, but inside that are pointers to other areas also
filled in by the kernel. If these happen to be allocated
just back up the stack then the 256 byte paint might cover
them too, somewhat indiscriminately.
By printing out ARG3 and also the 28 bytes that it points
at, it's possible to guess that the 7 word structure has
this form
By printing out ARG3 and also the 28 bytes that it points at,
it's possible to guess that the 7 word structure has this form
0 1 2 3 4 5 6
ioctl-number 0x1C ptr1 ptr1size ptr2 ptr2size aBitMask
0 1 2 3 4 5 6
ioctl-number 0x1C ptr1 ptr1size ptr2 ptr2size aBitMask
Unfortunately that doesn't seem to work for some reason, so
stay with the blunt-instrument approach for the time being.
*/
if (1) {
/* blunt-instrument approach */
if (0) VG_(printf)("QQQQQQQQQQ c01c quick hack actioned"
" (%08lx, %08lx)\n", ARG2, ARG3);
POST_MEM_WRITE(ARG3, 256);
} else {
/* be a bit more sophisticated */
if (0) VG_(printf)("QQQQQQQQQQ c01c quick hack actioned"
" (%08lx, %08lx) (fancy)\n", ARG2, ARG3);
POST_MEM_WRITE(ARG3, 28);
UInt* word = (UInt*)ARG3;
if (word && word[2] && word[3] < 0x200/*stay sane*/)
POST_MEM_WRITE(word[2], word[3]); // "ptr1"
if (word && word[4] && word[5] < 0x200/*stay sane*/)
POST_MEM_WRITE(word[4], word[5]); // "ptr2"
}
if (0) {
Int i;
VG_(printf)("QQQQQQQQQQ ");
for (i = 0; i < (0x1C/4); i++) {
VG_(printf)("%08x ", ((UInt*)(ARG3))[i]);
Unfortunately that doesn't seem to work for some reason,
so stay with the blunt-instrument approach for the time
being.
*/
if (1) {
/* blunt-instrument approach */
POST_MEM_WRITE(ARG3, 256);
} else {
/* be a bit more sophisticated */
POST_MEM_WRITE(ARG3, 28);
UInt* word = (UInt*)ARG3;
if (word && word[2] && word[3] < 0x200/*stay sane*/)
POST_MEM_WRITE(word[2], word[3]); // "ptr1"
if (word && word[4] && word[5] < 0x200/*stay sane*/)
POST_MEM_WRITE(word[4], word[5]); // "ptr2"
}
VG_(printf)("\n");
goto post_sys_ioctl__out;
}
return;
}
/* END Nexus S specific ioctls */
/* END undocumented ioctls for PowerVR SGX 540 (the GPU on Nexus S) */
# elif defined(ANDROID_HARDWARE_generic) || defined(ANDROID_HARDWARE_emulator)
/* BEGIN generic/emulator specific ioctls */
/* currently none are known */
/* END generic/emulator specific ioctls */
# else /* no ANDROID_HARDWARE_anything defined */
# warning ""
# warning "You need to define one the CPP symbols ANDROID_HARDWARE_blah"
# warning "at configure time, to tell Valgrind what hardware you are"
# warning "building for. Currently known values are"
# warning ""
# warning " ANDROID_HARDWARE_nexus_s Samsung Nexus S"
# warning " ANDROID_HARDWARE_generic Generic device (eg, Pandaboard)"
# warning " ANDROID_HARDWARE_emulator x86 or arm emulator"
# warning ""
# warning "Make sure you exactly follow the steps in README.android."
# warning ""
# error "No CPP symbol ANDROID_HARDWARE_blah defined. Giving up."
# endif /* cases for ANDROID_HARDWARE_blah */
# endif /* defined(VGPV_*_linux_android) */
/* BEGIN undocumented ioctls for Qualcomm Adreno 3xx */
if (KernelVariantiS(KernelVariant_android_gpu_sgx5xx,
VG_(clo_kernel_variant))) {
if (ARG2 == 0xC00C0902) {
POST_MEM_WRITE(ARG3, 24); // 16 is not enough
goto post_sys_ioctl__out;
}
}
/* END undocumented ioctls for Qualcomm Adreno 3xx */
/* --- END special IOCTL handlers for specific Android hardware --- */
/* --- normal handling --- */
switch (ARG2 /* request */) {
/* The Linux kernel "ion" memory allocator, used on Android. Note:
this is pretty poor given that there's no pre-handling to check
that writable areas are addressable. */
case VKI_ION_IOC_ALLOC:
POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_allocation_data));
break;
case VKI_ION_IOC_MAP:
POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_fd_data));
break;
case VKI_ION_IOC_FREE: // is this necessary?
POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_handle_data));
break;
case VKI_ION_IOC_SHARE:
break;
case VKI_ION_IOC_IMPORT: // is this necessary?
POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_fd_data));
break;
case VKI_ION_IOC_SYNC:
break;
case VKI_ION_IOC_CUSTOM: // is this necessary?
POST_MEM_WRITE(ARG3, sizeof(struct vki_ion_custom_data));
break;
case VKI_TCSETS:
case VKI_TCSETSW:
case VKI_TCSETSF:
@ -8448,6 +8444,9 @@ POST(sys_ioctl)
}
break;
}
post_sys_ioctl__out:
{} /* keep C compilers happy */
}
/* ---------------------------------------------------------------------

View File

@ -338,8 +338,12 @@ extern VgSmc VG_(clo_smc_check);
/* A set of minor kernel variants,
so they can be properly handled by m_syswrap. */
typedef enum {
KernelVariant_bproc
typedef
enum {
KernelVariant_bproc,
KernelVariant_android_emulator_no_hw_tls,
KernelVariant_android_gpu_sgx5xx,
KernelVariant_android_gpu_adreno3xx
}
KernelVariant;
// Build mask to check or set KernelVariant a membership

View File

@ -3446,6 +3446,57 @@ struct vki_ethtool_ts_info {
#define VKI_ETHTOOL_SCHANNELS 0x0000003d /* Set no of channels */
#define VKI_ETHTOOL_GET_TS_INFO 0x00000041 /* Get time stamping and PHC info */
//----------------------------------------------------------------------
// From linux-3.15.8/drivers/staging/android/uapi/ion.h
//----------------------------------------------------------------------
typedef int vki_ion_user_handle_t;
struct vki_ion_allocation_data {
vki_size_t len;
vki_size_t align;
unsigned int heap_id_mask;
unsigned int flags;
vki_ion_user_handle_t handle;
};
struct vki_ion_fd_data {
vki_ion_user_handle_t handle;
int fd;
};
struct vki_ion_handle_data {
vki_ion_user_handle_t handle;
};
struct vki_ion_custom_data {
unsigned int cmd;
unsigned long arg;
};
#define VKI_ION_IOC_MAGIC 'I'
#define VKI_ION_IOC_ALLOC \
_VKI_IOWR(VKI_ION_IOC_MAGIC, 0, struct vki_ion_allocation_data)
#define VKI_ION_IOC_FREE \
_VKI_IOWR(VKI_ION_IOC_MAGIC, 1, struct vki_ion_handle_data)
#define VKI_ION_IOC_MAP \
_VKI_IOWR(VKI_ION_IOC_MAGIC, 2, struct vki_ion_fd_data)
#define VKI_ION_IOC_SHARE \
_VKI_IOWR(VKI_ION_IOC_MAGIC, 4, struct vki_ion_fd_data)
#define VKI_ION_IOC_IMPORT \
_VKI_IOWR(VKI_ION_IOC_MAGIC, 5, struct vki_ion_fd_data)
#define VKI_ION_IOC_SYNC \
_VKI_IOWR(VKI_ION_IOC_MAGIC, 7, struct vki_ion_fd_data)
#define VKI_ION_IOC_CUSTOM \
_VKI_IOWR(VKI_ION_IOC_MAGIC, 6, struct vki_ion_custom_data)
//----------------------------------------------------------------------
// From drivers/staging/lustre/lustre/include/lustre/lustre_user.h
//----------------------------------------------------------------------

View File

@ -92,8 +92,11 @@ usage: valgrind [options] prog-and-args
where hint is one of lax-ioctls fuse-compatible enable-outer
no-inner-prefix no-nptl-pthread-stackcache none
--fair-sched=no|yes|try schedule threads fairly on multicore systems [no]
--kernel-variant=variant1,variant2,... handle non-standard kernel variants [none]
where variant is one of bproc none
--kernel-variant=variant1,variant2,...
handle non-standard kernel variants [none]
where variant is one of:
bproc android-emulator-no-hw-tls
android-gpu-sgx5xx android-gpu-adreno3xx none
--merge-recursive-frames=<number> merge frames between identical
program counters in max <number> frames) [0]
--num-transtab-sectors=<number> size of translated code cache [16]

View File

@ -92,8 +92,11 @@ usage: valgrind [options] prog-and-args
where hint is one of lax-ioctls fuse-compatible enable-outer
no-inner-prefix no-nptl-pthread-stackcache none
--fair-sched=no|yes|try schedule threads fairly on multicore systems [no]
--kernel-variant=variant1,variant2,... handle non-standard kernel variants [none]
where variant is one of bproc none
--kernel-variant=variant1,variant2,...
handle non-standard kernel variants [none]
where variant is one of:
bproc android-emulator-no-hw-tls
android-gpu-sgx5xx android-gpu-adreno3xx none
--merge-recursive-frames=<number> merge frames between identical
program counters in max <number> frames) [0]
--num-transtab-sectors=<number> size of translated code cache [16]