Bug 1509562 Part 3 - Remove dependence on CallEvent_* enum, r=lsmyth.

--HG--
extra : rebase_source : d8e5c15d7160b22278d13829a0aa36b7b2ab3657
This commit is contained in:
Brian Hackett 2018-11-23 09:27:38 -10:00
Родитель 0c9d0e2f87
Коммит ad1353a4b7
5 изменённых файлов: 123 добавлений и 59 удалений

Просмотреть файл

@ -177,7 +177,7 @@ ProcessMiddlemanCall(const char* aInputData, size_t aInputSize,
redirection.mMiddlemanCall(cx);
}
RecordReplayInvokeCall(call->mCallId, &arguments);
RecordReplayInvokeCall(redirection.mBaseFunction, &arguments);
{
MiddlemanCallContext cx(call, &arguments, MiddlemanCallPhase::MiddlemanOutput);

Просмотреть файл

@ -134,6 +134,7 @@ RecordReplayInterface_Initialize(int aArgc, char* aArgv[])
fprintf(stderr, "Initialization Failure: %s\n", gInitializationFailureMessage);
}
LateInitializeRedirections();
Thread::InitializeThreads();
Thread* thread = Thread::GetById(MainThreadId);

Просмотреть файл

@ -39,7 +39,7 @@ CallPreambleHook(PreambleFn aPreamble, size_t aCallId, CallArguments* aArguments
return true;
case PreambleResult::PassThrough: {
AutoEnsurePassThroughThreadEvents pt;
RecordReplayInvokeCall(aCallId, aArguments);
RecordReplayInvokeCall(OriginalFunction(aCallId), aArguments);
return true;
}
case PreambleResult::Redirect:
@ -120,7 +120,7 @@ RecordReplayInterceptCall(int aCallId, CallArguments* aArguments)
// from being flushed in case we end up blocking.
res.reset();
thread->SetPassThrough(true);
RecordReplayInvokeCall(aCallId, aArguments);
RecordReplayInvokeCall(redirection.mOriginalFunction, aArguments);
thread->SetPassThrough(false);
res.emplace(thread);
}
@ -287,9 +287,9 @@ __asm(
} // extern "C"
MOZ_NEVER_INLINE void
RecordReplayInvokeCall(size_t aCallId, CallArguments* aArguments)
RecordReplayInvokeCall(void* aFunction, CallArguments* aArguments)
{
RecordReplayInvokeCallRaw(aArguments, OriginalFunction(aCallId));
RecordReplayInvokeCallRaw(aArguments, aFunction);
}
///////////////////////////////////////////////////////////////////////////////
@ -953,6 +953,19 @@ InitializeRedirections()
return true;
}
void*
OriginalFunction(const char* aName)
{
size_t numRedirections = NumRedirections();
for (size_t i = 0; i < numRedirections; i++) {
const Redirection& redirection = GetRedirection(i);
if (!strcmp(aName, redirection.mName)) {
return redirection.mOriginalFunction;
}
}
MOZ_CRASH("OriginalFunction: unknown redirection");
}
///////////////////////////////////////////////////////////////////////////////
// Utility
///////////////////////////////////////////////////////////////////////////////

Просмотреть файл

@ -269,6 +269,10 @@ void EarlyInitializeRedirections();
// gInitializationFailureMessage.
bool InitializeRedirections();
// Platform specific function called after setting up redirections in recording
// or replaying processes.
void LateInitializeRedirections();
// Functions for saving or restoring system error codes.
static inline ErrorType SaveError() { return errno; }
static inline void RestoreError(ErrorType aError) { errno = aError; }
@ -286,17 +290,8 @@ OriginalFunction(size_t aCallId)
return GetRedirection(aCallId).mOriginalFunction;
}
#define TokenPaste(aFirst, aSecond) aFirst ## aSecond
// Call the original function for a call event ID with a particular ABI and any
// number of arguments.
#define OriginalCallABI(aName, aReturnType, aABI, ...) \
TokenPaste(CallFunction, aABI) <aReturnType> \
(OriginalFunction(CallEvent_ ##aName), ##__VA_ARGS__)
// Call the original function for a call event ID with the default ABI.
#define OriginalCall(aName, aReturnType, ...) \
OriginalCallABI(aName, aReturnType, DEFAULTABI, ##__VA_ARGS__)
// Get the address of the original function by name.
void* OriginalFunction(const char* aName);
static inline ThreadEvent
CallIdToThreadEvent(size_t aCallId)
@ -305,7 +300,7 @@ CallIdToThreadEvent(size_t aCallId)
}
void
RecordReplayInvokeCall(size_t aCallId, CallArguments* aArguments);
RecordReplayInvokeCall(void* aFunction, CallArguments* aArguments);
///////////////////////////////////////////////////////////////////////////////
// Callback Redirections

Просмотреть файл

@ -717,6 +717,47 @@ enum CallEvent { \
#undef MAKE_CALL_EVENT
///////////////////////////////////////////////////////////////////////////////
// Original functions
///////////////////////////////////////////////////////////////////////////////
// Specify all the redirections for which the original function (with its
// normal non-redirected semantics) is needed.
#define FOR_EACH_ORIGINAL_FUNCTION(MACRO) \
MACRO(__workq_kernreturn) \
MACRO(CFDataGetLength) \
MACRO(CGPathApply) \
MACRO(close) \
MACRO(lseek) \
MACRO(mach_absolute_time) \
MACRO(mmap) \
MACRO(mprotect) \
MACRO(munmap) \
MACRO(objc_msgSend) \
MACRO(open) \
MACRO(OSSpinLockLock) \
MACRO(pipe) \
MACRO(PL_HashTableDestroy) \
MACRO(pthread_cond_wait) \
MACRO(pthread_cond_timedwait) \
MACRO(pthread_cond_timedwait_relative_np) \
MACRO(pthread_create) \
MACRO(pthread_mutex_destroy) \
MACRO(pthread_mutex_init) \
MACRO(pthread_mutex_lock) \
MACRO(pthread_mutex_trylock) \
MACRO(pthread_mutex_unlock) \
MACRO(read) \
MACRO(start_wqthread) \
MACRO(write)
#define DECLARE_ORIGINAL_FUNCTION(aName) \
static void* gOriginal_ ##aName;
FOR_EACH_ORIGINAL_FUNCTION(DECLARE_ORIGINAL_FUNCTION)
#undef DECLARE_ORIGINAL_FUNCTION
///////////////////////////////////////////////////////////////////////////////
// Callbacks
///////////////////////////////////////////////////////////////////////////////
@ -1076,7 +1117,7 @@ Preamble_mmap(CallArguments* aArguments)
// For fixed allocations, make sure this memory region is mapped and zero.
if (!HasSavedCheckpoint()) {
// Make sure this memory region is writable.
OriginalCall(mprotect, int, address, size, PROT_READ | PROT_WRITE | PROT_EXEC);
CallFunction<int>(gOriginal_mprotect, address, size, PROT_READ | PROT_WRITE | PROT_EXEC);
}
memset(address, 0, size);
memory = address;
@ -1090,7 +1131,7 @@ Preamble_mmap(CallArguments* aArguments)
// then this is no problem, but after saving a checkpoint we have to make
// sure that protection flags are what we expect them to be.
int newProt = HasSavedCheckpoint() ? (PROT_READ | PROT_EXEC) : prot;
memory = OriginalCall(mmap, void*, address, size, newProt, flags, fd, offset);
memory = CallFunction<void*>(gOriginal_mmap, address, size, newProt, flags, fd, offset);
if (flags & MAP_FIXED) {
MOZ_RELEASE_ASSERT(memory == address);
@ -1244,7 +1285,7 @@ Preamble___workq_kernreturn(CallArguments* aArguments)
// Make sure we know this thread exists.
Thread::Current();
RecordReplayInvokeCall(CallEvent___workq_kernreturn, aArguments);
RecordReplayInvokeCall(gOriginal___workq_kernreturn, aArguments);
return PreambleResult::Veto;
}
@ -1259,7 +1300,7 @@ Preamble_start_wqthread(CallArguments* aArguments)
Thread::WaitForeverNoIdle();
}
RecordReplayInvokeCall(CallEvent_start_wqthread, aArguments);
RecordReplayInvokeCall(gOriginal_start_wqthread, aArguments);
return PreambleResult::Veto;
}
@ -1271,7 +1312,7 @@ static void
DirectLockMutex(pthread_mutex_t* aMutex)
{
AutoPassThroughThreadEvents pt;
ssize_t rv = OriginalCall(pthread_mutex_lock, ssize_t, aMutex);
ssize_t rv = CallFunction<ssize_t>(gOriginal_pthread_mutex_lock, aMutex);
MOZ_RELEASE_ASSERT(rv == 0);
}
@ -1279,7 +1320,7 @@ static void
DirectUnlockMutex(pthread_mutex_t* aMutex)
{
AutoPassThroughThreadEvents pt;
ssize_t rv = OriginalCall(pthread_mutex_unlock, ssize_t, aMutex);
ssize_t rv = CallFunction<ssize_t>(gOriginal_pthread_mutex_unlock, aMutex);
MOZ_RELEASE_ASSERT(rv == 0);
}
@ -1338,7 +1379,7 @@ Preamble_pthread_cond_wait(CallArguments* aArguments)
auto& mutex = aArguments->Arg<1, pthread_mutex_t*>();
aArguments->Rval<ssize_t>() =
WaitForCvar(mutex, cond, false,
[=]() { return OriginalCall(pthread_cond_wait, ssize_t, cond, mutex); });
[=]() { return CallFunction<ssize_t>(gOriginal_pthread_cond_wait, cond, mutex); });
return PreambleResult::Veto;
}
@ -1350,8 +1391,8 @@ Preamble_pthread_cond_timedwait(CallArguments* aArguments)
auto& timeout = aArguments->Arg<2, timespec*>();
aArguments->Rval<ssize_t>() =
WaitForCvar(mutex, cond, true,
[=]() { return OriginalCall(pthread_cond_timedwait, ssize_t,
cond, mutex, timeout); });
[=]() { return CallFunction<ssize_t>(gOriginal_pthread_cond_timedwait,
cond, mutex, timeout); });
return PreambleResult::Veto;
}
@ -1363,8 +1404,8 @@ Preamble_pthread_cond_timedwait_relative_np(CallArguments* aArguments)
auto& timeout = aArguments->Arg<2, timespec*>();
aArguments->Rval<ssize_t>() =
WaitForCvar(mutex, cond, true,
[=]() { return OriginalCall(pthread_cond_timedwait_relative_np, ssize_t,
cond, mutex, timeout); });
[=]() { return CallFunction<ssize_t>(gOriginal_pthread_cond_timedwait_relative_np,
cond, mutex, timeout); });
return PreambleResult::Veto;
}
@ -1421,7 +1462,7 @@ Preamble_pthread_mutex_init(CallArguments* aArguments)
auto& attr = aArguments->Arg<1, pthread_mutexattr_t*>();
Lock::New(mutex);
aArguments->Rval<ssize_t>() = OriginalCall(pthread_mutex_init, ssize_t, mutex, attr);
aArguments->Rval<ssize_t>() = CallFunction<ssize_t>(gOriginal_pthread_mutex_init, mutex, attr);
return PreambleResult::Veto;
}
@ -1431,7 +1472,7 @@ Preamble_pthread_mutex_destroy(CallArguments* aArguments)
auto& mutex = aArguments->Arg<0, pthread_mutex_t*>();
Lock::Destroy(mutex);
aArguments->Rval<ssize_t>() = OriginalCall(pthread_mutex_destroy, ssize_t, mutex);
aArguments->Rval<ssize_t>() = CallFunction<ssize_t>(gOriginal_pthread_mutex_destroy, mutex);
return PreambleResult::Veto;
}
@ -1443,13 +1484,13 @@ Preamble_pthread_mutex_lock(CallArguments* aArguments)
Lock* lock = Lock::Find(mutex);
if (!lock) {
AutoEnsurePassThroughThreadEventsUseStackPointer pt;
aArguments->Rval<ssize_t>() = OriginalCall(pthread_mutex_lock, ssize_t, mutex);
aArguments->Rval<ssize_t>() = CallFunction<ssize_t>(gOriginal_pthread_mutex_lock, mutex);
return PreambleResult::Veto;
}
ssize_t rv = 0;
if (IsRecording()) {
AutoPassThroughThreadEvents pt;
rv = OriginalCall(pthread_mutex_lock, ssize_t, mutex);
rv = CallFunction<ssize_t>(gOriginal_pthread_mutex_lock, mutex);
}
rv = RecordReplayValue(rv);
MOZ_RELEASE_ASSERT(rv == 0 || rv == EDEADLK);
@ -1471,13 +1512,13 @@ Preamble_pthread_mutex_trylock(CallArguments* aArguments)
Lock* lock = Lock::Find(mutex);
if (!lock) {
AutoEnsurePassThroughThreadEvents pt;
aArguments->Rval<ssize_t>() = OriginalCall(pthread_mutex_trylock, ssize_t, mutex);
aArguments->Rval<ssize_t>() = CallFunction<ssize_t>(gOriginal_pthread_mutex_trylock, mutex);
return PreambleResult::Veto;
}
ssize_t rv = 0;
if (IsRecording()) {
AutoPassThroughThreadEvents pt;
rv = OriginalCall(pthread_mutex_trylock, ssize_t, mutex);
rv = CallFunction<ssize_t>(gOriginal_pthread_mutex_trylock, mutex);
}
rv = RecordReplayValue(rv);
MOZ_RELEASE_ASSERT(rv == 0 || rv == EBUSY);
@ -1499,7 +1540,7 @@ Preamble_pthread_mutex_unlock(CallArguments* aArguments)
Lock* lock = Lock::Find(mutex);
if (!lock) {
AutoEnsurePassThroughThreadEventsUseStackPointer pt;
aArguments->Rval<ssize_t>() = OriginalCall(pthread_mutex_unlock, ssize_t, mutex);
aArguments->Rval<ssize_t>() = CallFunction<ssize_t>(gOriginal_pthread_mutex_unlock, mutex);
return PreambleResult::Veto;
}
lock->Exit();
@ -1568,7 +1609,7 @@ Preamble_mach_absolute_time(CallArguments* aArguments)
// This function might be called through OSSpinLock while setting gTlsThreadKey.
Thread* thread = Thread::GetByStackPointer(&thread);
if (!thread || thread->PassThroughEvents()) {
aArguments->Rval<uint64_t>() = OriginalCall(mach_absolute_time, uint64_t);
aArguments->Rval<uint64_t>() = CallFunction<uint64_t>(gOriginal_mach_absolute_time);
return PreambleResult::Veto;
}
return PreambleResult::Redirect;
@ -1674,7 +1715,7 @@ Preamble_PL_HashTableDestroy(CallArguments* aArguments)
auto& table = aArguments->Arg<0, PLHashTable*>();
void* priv = table->allocPriv;
OriginalCall(PL_HashTableDestroy, void, table);
CallFunction<void>(gOriginal_PL_HashTableDestroy, table);
DestroyPLHashTableCallbacks(priv);
return PreambleResult::Veto;
}
@ -1709,7 +1750,7 @@ Preamble_objc_msgSend(CallArguments* aArguments)
!strcmp(message, "nextEventMatchingMask:untilDate:inMode:dequeue:"))
{
PassThroughThreadEventsAllowCallbacks([&]() {
RecordReplayInvokeCall(CallEvent_objc_msgSend, aArguments);
RecordReplayInvokeCall(gOriginal_objc_msgSend, aArguments);
});
RecordReplayBytes(&aArguments->Rval<size_t>(), sizeof(size_t));
return PreambleResult::Veto;
@ -2092,7 +2133,7 @@ RR_CFDataGetBytePtr(Stream& aEvents, CallArguments* aArguments, ErrorType* aErro
size_t len = 0;
if (IsRecording()) {
len = OriginalCall(CFDataGetLength, size_t, aArguments->Arg<0, CFDataRef>());
len = CallFunction<size_t>(gOriginal_CFDataGetLength, aArguments->Arg<0, CFDataRef>());
}
aEvents.RecordOrReplayValue(&len);
if (IsReplaying()) {
@ -2416,7 +2457,7 @@ Preamble_CGPathApply(CallArguments* aArguments)
RegisterCallbackData(data);
PassThroughThreadEventsAllowCallbacks([&]() {
CallbackWrapperData wrapperData(function, data);
OriginalCall(CGPathApply, void, path, &wrapperData, CGPathApplierFunctionWrapper);
CallFunction<void>(gOriginal_CGPathApply, path, &wrapperData, CGPathApplierFunctionWrapper);
});
RemoveCallbackData(data);
@ -2489,7 +2530,7 @@ Preamble_OSSpinLockLock(CallArguments* aArguments)
// so make sure events are passed through here. Note that we don't have to
// redirect OSSpinLockUnlock, as it doesn't have these issues.
AutoEnsurePassThroughThreadEventsUseStackPointer pt;
OriginalCall(OSSpinLockLock, void, lock);
CallFunction<void>(gOriginal_OSSpinLockLock, lock);
return PreambleResult::Veto;
}
@ -2551,14 +2592,27 @@ EarlyInitializeRedirections()
// We will get confused if we try to redirect the same address in multiple places.
for (size_t j = 0; j < i; j++) {
if (gRedirections[j].mBaseFunction == redirection.mBaseFunction) {
PrintSpew("Redirection %s shares the same address as %s, skipping.\n",
redirection.mName, gRedirections[j].mName);
redirection.mBaseFunction = nullptr;
break;
}
}
}
}
// Bind the gOriginal functions to their redirections' base addresses until we
// finish installing redirections.
LateInitializeRedirections();
}
void
LateInitializeRedirections()
{
#define INIT_ORIGINAL_FUNCTION(aName) \
gOriginal_ ##aName = OriginalFunction(#aName);
FOR_EACH_ORIGINAL_FUNCTION(INIT_ORIGINAL_FUNCTION)
#undef INIT_ORIGINAL_FUNCTION
}
///////////////////////////////////////////////////////////////////////////////
@ -2575,9 +2629,9 @@ SymbolNameRaw(void* aPtr)
void*
DirectAllocateMemory(void* aAddress, size_t aSize)
{
void* res = OriginalCall(mmap, void*,
aAddress, aSize, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
void* res = CallFunction<void*>(gOriginal_mmap, aAddress, aSize,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE, -1, 0);
MOZ_RELEASE_ASSERT(res && res != (void*)-1);
return res;
}
@ -2585,7 +2639,7 @@ DirectAllocateMemory(void* aAddress, size_t aSize)
void
DirectDeallocateMemory(void* aAddress, size_t aSize)
{
ssize_t rv = OriginalCall(munmap, int, aAddress, aSize);
ssize_t rv = CallFunction<int>(gOriginal_munmap, aAddress, aSize);
MOZ_RELEASE_ASSERT(rv >= 0);
}
@ -2593,8 +2647,8 @@ void
DirectWriteProtectMemory(void* aAddress, size_t aSize, bool aExecutable,
bool aIgnoreFailures /* = false */)
{
ssize_t rv = OriginalCall(mprotect, int, aAddress, aSize,
PROT_READ | (aExecutable ? PROT_EXEC : 0));
ssize_t rv = CallFunction<int>(gOriginal_mprotect, aAddress, aSize,
PROT_READ | (aExecutable ? PROT_EXEC : 0));
MOZ_RELEASE_ASSERT(aIgnoreFailures || rv == 0);
}
@ -2602,8 +2656,8 @@ void
DirectUnprotectMemory(void* aAddress, size_t aSize, bool aExecutable,
bool aIgnoreFailures /* = false */)
{
ssize_t rv = OriginalCall(mprotect, int, aAddress, aSize,
PROT_READ | PROT_WRITE | (aExecutable ? PROT_EXEC : 0));
ssize_t rv = CallFunction<int>(gOriginal_mprotect, aAddress, aSize,
PROT_READ | PROT_WRITE | (aExecutable ? PROT_EXEC : 0));
MOZ_RELEASE_ASSERT(aIgnoreFailures || rv == 0);
}
@ -2611,7 +2665,7 @@ void
DirectSeekFile(FileHandle aFd, uint64_t aOffset)
{
static_assert(sizeof(uint64_t) == sizeof(off_t), "off_t should have 64 bits");
ssize_t rv = HANDLE_EINTR(OriginalCall(lseek, int, aFd, aOffset, SEEK_SET));
ssize_t rv = HANDLE_EINTR(CallFunction<int>(gOriginal_lseek, aFd, aOffset, SEEK_SET));
MOZ_RELEASE_ASSERT(rv >= 0);
}
@ -2620,7 +2674,7 @@ DirectOpenFile(const char* aFilename, bool aWriting)
{
int flags = aWriting ? (O_WRONLY | O_CREAT | O_TRUNC) : O_RDONLY;
int perms = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
int fd = HANDLE_EINTR(OriginalCall(open, int, aFilename, flags, perms));
int fd = HANDLE_EINTR(CallFunction<int>(gOriginal_open, aFilename, flags, perms));
MOZ_RELEASE_ASSERT(fd > 0);
return fd;
}
@ -2628,7 +2682,7 @@ DirectOpenFile(const char* aFilename, bool aWriting)
void
DirectCloseFile(FileHandle aFd)
{
ssize_t rv = HANDLE_EINTR(OriginalCall(close, int, aFd));
ssize_t rv = HANDLE_EINTR(CallFunction<int>(gOriginal_close, aFd));
MOZ_RELEASE_ASSERT(rv >= 0);
}
@ -2642,7 +2696,7 @@ DirectDeleteFile(const char* aFilename)
void
DirectWrite(FileHandle aFd, const void* aData, size_t aSize)
{
ssize_t rv = HANDLE_EINTR(OriginalCall(write, int, aFd, aData, aSize));
ssize_t rv = HANDLE_EINTR(CallFunction<int>(gOriginal_write, aFd, aData, aSize));
MOZ_RELEASE_ASSERT((size_t) rv == aSize);
}
@ -2658,7 +2712,7 @@ DirectRead(FileHandle aFd, void* aData, size_t aSize)
// Clear the memory in case it is write protected by the memory snapshot
// mechanism.
memset(aData, 0, aSize);
ssize_t rv = HANDLE_EINTR(OriginalCall(read, int, aFd, aData, aSize));
ssize_t rv = HANDLE_EINTR(CallFunction<int>(gOriginal_read, aFd, aData, aSize));
MOZ_RELEASE_ASSERT(rv >= 0);
return (size_t) rv;
}
@ -2667,7 +2721,7 @@ void
DirectCreatePipe(FileHandle* aWriteFd, FileHandle* aReadFd)
{
int fds[2];
ssize_t rv = OriginalCall(pipe, int, fds);
ssize_t rv = CallFunction<int>(gOriginal_pipe, fds);
MOZ_RELEASE_ASSERT(rv >= 0);
*aWriteFd = fds[1];
*aReadFd = fds[0];
@ -2687,7 +2741,7 @@ InitializeCurrentTime()
double
CurrentTime()
{
return OriginalCall(mach_absolute_time, int64_t) * gAbsoluteToNanosecondsRate / 1000.0;
return CallFunction<int64_t>(gOriginal_mach_absolute_time) * gAbsoluteToNanosecondsRate / 1000.0;
}
void
@ -2706,7 +2760,8 @@ DirectSpawnThread(void (*aFunction)(void*), void* aArgument)
MOZ_RELEASE_ASSERT(rv == 0);
pthread_t pthread;
rv = OriginalCall(pthread_create, int, &pthread, &attr, (void* (*)(void*)) aFunction, aArgument);
rv = CallFunction<int>(gOriginal_pthread_create,
&pthread, &attr, (void* (*)(void*)) aFunction, aArgument);
MOZ_RELEASE_ASSERT(rv == 0);
rv = pthread_attr_destroy(&attr);