Fix three unit tests on recent ARM devices.

Three unit tests were failing on recent ARM devices (e.g. Galaxy Nexus
or Nexus 4), while ran properly on older ones (e.g. Nexus S).

The main issue is that the instruction cache needs to be explicitely
cleared on ARM after writing machine code bytes to a malloc()-ed
page with PROT_EXEC.
Review URL: https://breakpad.appspot.com/540002

git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1132 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
digit@chromium.org 2013-03-21 08:22:37 +00:00
parent 4867c9e9d0
commit 0192fc21b9

View file

@ -54,6 +54,27 @@ using namespace google_breakpad;
namespace {
// Flush the instruction cache for a given memory range.
// Only required on ARM.
void FlushInstructionCache(const char* memory, uint32_t memory_size) {
#if defined(__arm__)
long begin = reinterpret_cast<long>(memory);
long end = begin + static_cast<long>(memory_size);
# if defined(__ANDROID__)
// Provided by Android's <unistd.h>
cacheflush(begin, end, 0);
# elif defined(__linux__)
// GLibc/ARM doesn't provide a wrapper for it, do a direct syscall.
# ifndef __ARM_NR_cacheflush
# define __ARM_NR_cacheflush 0xf0002
# endif
syscall(__ARM_NR_cacheflush, begin, end, 0);
# else
# error "Your operating system is not supported yet"
# endif
#endif
}
// Length of a formatted GUID string =
// sizeof(MDGUID) * 2 + 4 (for dashes) + 1 (null terminator)
const int kGUIDStringSize = 37;
@ -449,6 +470,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemory) {
// of the block of memory, because the minidump should contain 128
// bytes on either side of the instruction pointer.
memcpy(memory + kOffset, instructions, sizeof(instructions));
FlushInstructionCache(memory, kMemorySize);
// Now execute the instructions, which should crash.
typedef void (*void_function)(void);
@ -541,6 +563,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMinBound) {
// of the block of memory, because the minidump should contain 128
// bytes on either side of the instruction pointer.
memcpy(memory + kOffset, instructions, sizeof(instructions));
FlushInstructionCache(memory, kMemorySize);
// Now execute the instructions, which should crash.
typedef void (*void_function)(void);
@ -632,6 +655,7 @@ TEST(ExceptionHandlerTest, InstructionPointerMemoryMaxBound) {
// of the block of memory, because the minidump should contain 128
// bytes on either side of the instruction pointer.
memcpy(memory + kOffset, instructions, sizeof(instructions));
FlushInstructionCache(memory, kMemorySize);
// Now execute the instructions, which should crash.
typedef void (*void_function)(void);