DXR is a code search and navigation tool aimed at making sense of large projects. It supports full-text and regex searches as well as structural queries.

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#ifndef mozilla_recordreplay_MemorySnapshot_h
#define mozilla_recordreplay_MemorySnapshot_h

#include "mozilla/Types.h"
#include "ProcessRecordReplay.h"

namespace mozilla {
namespace recordreplay {

// Memory Snapshots Overview.
//
// As described in ProcessRewind.h, some subset of the checkpoints which are
// reached during execution are saved, so that their state can be restored
// later. Memory snapshots are used to save and restore the contents of all
// heap memory: everything except thread stacks (see ThreadSnapshot.h for
// saving and restoring these) and untracked memory (which is not saved or
// restored, see ProcessRecordReplay.h).
//
// Each memory snapshot is a diff of the heap memory contents compared to the
// next one. See MemorySnapshot.cpp for how diffs are represented and computed.
//
// Rewinding must restore the exact contents of heap memory that existed when
// the target checkpoint was reached. Because of this, memory that is allocated
// at a point when a checkpoint is saved will never actually be returned to the
// system. We instead keep a set of free blocks that are unused at the current
// point of execution and are available to satisfy new allocations.

// Make sure that a block of memory in a fixed allocation is already allocated.
void CheckFixedMemory(void* aAddress, size_t aSize);

// After marking a block of memory in a fixed allocation as non-writable,
// restore writability to any dirty pages in the range.
void RestoreWritableFixedMemory(void* aAddress, size_t aSize);

// Allocate memory, trying to use a specific address if provided but only if
// it is free.
void* AllocateMemoryTryAddress(void* aAddress, size_t aSize, MemoryKind aKind);

// Note a range of memory that was just allocated from the system, and the
// kind of memory allocation that was performed.
void RegisterAllocatedMemory(void* aBaseAddress, size_t aSize,
                             MemoryKind aKind);

// Exclude a region of memory from snapshots, before the first checkpoint has
// been reached.
void AddInitialUntrackedMemoryRegion(uint8_t* aBase, size_t aSize);

// Return whether a range of memory is in a tracked region. This excludes
// memory that was allocated after the last checkpoint and is not write
// protected.
bool MemoryRangeIsTracked(void* aAddress, size_t aSize);

// Initialize the memory snapshots system.
void InitializeMemorySnapshots();

// Take the first heap memory snapshot.
void TakeFirstMemorySnapshot();

// Take a differential heap memory snapshot compared to the last one,
// associated with the last saved checkpoint.
void TakeDiffMemorySnapshot();

// Restore all heap memory to its state when the most recent checkpoint was
// saved. This requires no checkpoints to have been saved after this one.
void RestoreMemoryToLastSavedCheckpoint();

// Restore all heap memory to its state at a checkpoint where a complete diff
// was saved vs. the following saved checkpoint. This requires that no
// tracked heap memory has been changed since the last saved checkpoint.
void RestoreMemoryToLastSavedDiffCheckpoint();

// Erase all information from the last diff snapshot taken, so that tracked
// heap memory changes are with respect to the previous checkpoint.
void EraseLastSavedDiffMemorySnapshot();

// Set whether to allow changes to tracked heap memory at this point. If such
// changes occur when they are not allowed then the process will crash.
void SetMemoryChangesAllowed(bool aAllowed);

struct MOZ_RAII AutoDisallowMemoryChanges {
  AutoDisallowMemoryChanges() { SetMemoryChangesAllowed(false); }
  ~AutoDisallowMemoryChanges() { SetMemoryChangesAllowed(true); }
};

// After a SEGV on the specified address, check if the violation occurred due
// to the memory having been write protected by the snapshot mechanism. This
// function returns whether the fault has been handled and execution may
// continue.
bool HandleDirtyMemoryFault(uint8_t* aAddress);

// For debugging, note a point where we hit an unrecoverable failure and try
// to make things easier for the debugger.
void UnrecoverableSnapshotFailure();

// After rewinding, mark all memory that has been allocated since the snapshot
// was taken as free.
void FixupFreeRegionsAfterRewind();

// When WANT_COUNTDOWN_THREAD is defined (see MemorySnapshot.cpp), set a count
// that, after a thread consumes it, causes the thread to report a fatal error.
// This is used for debugging and is a workaround for lldb often being unable
// to interrupt a running process.
void StartCountdown(size_t aCount);

// Per StartCountdown, set a countdown and remove it on destruction.
struct MOZ_RAII AutoCountdown {
  explicit AutoCountdown(size_t aCount);
  ~AutoCountdown();
};

// Initialize the thread consuming the countdown.
void InitializeCountdownThread();

// This is an alternative to memmove/memcpy that can be called in areas where
// faults in write protected memory are not allowed. It's hard to avoid dynamic
// code loading when calling memmove/memcpy directly.
void MemoryMove(void* aDst, const void* aSrc, size_t aSize);

// Similarly, zero out a range of memory without doing anything weird with
// dynamic code loading.
void MemoryZero(void* aDst, size_t aSize);

}  // namespace recordreplay
}  // namespace mozilla

#endif  // mozilla_recordreplay_MemorySnapshot_h