libredex/InteractiveDebugging.h (32 lines of code) (raw):
/*
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#pragma once
#include "Macros.h"
#include <stddef.h>
#if !defined(NDEBUG) && !IS_WINDOWS
namespace cfg {
class ControlFlowGraph;
class Block;
using BlockId = size_t;
} // namespace cfg
// namespace cfg
class IRCode;
// The following APIs are intended to be called from the debugger (athough
// there's no harm calling them from internal code if desired).
// __attribute__((used)) is important so that the linker does not discard them,
// as they may not be referenced by any other code. Consider making LLDB
// aliases in redex/.lldbinit for functions in this file to make them easier to
// call when debugging.
const char* methname()
__attribute__((used)); // NOTE: This allocates the string which is returned.
void dumpmethname() __attribute__((used));
void dumpir() __attribute__((used));
void dumpir(const IRCode* ir_code) __attribute__((used));
void dumpcfg() __attribute__((used));
void dumpcfg(const cfg::ControlFlowGraph& cfg) __attribute__((used));
void dumpblock(const cfg::Block* block) __attribute__((used));
void dumpblock(cfg::BlockId block_id) __attribute__((used));
void setdumpfile(const char* file_name) __attribute__((used));
void setdumpfilemode(const char* mode) __attribute__((used));
// Helper macros
// Note: These work with Clang, and likely need modification to work on other
// compilers.
// Break into the debugger when the current method's name contains the passed in
// substring
#define METHBREAK(meth_name_substr) \
if (methname() && strstr(methname(), meth_name_substr)) { \
__builtin_debugtrap(); \
}
// Break into the debugger when the current method's name exactly matches the
// passed in name
#define METHBREAK_EXACT(meth_name) \
if (methname() && strcmp(methname(), meth_name) == 0) { \
__builtin_debugtrap(); \
}
// Convenience wrappers for disabling optimizations for a function or set of
// functions. This allows for easier debugging of specific files/functions,
// without making the rest of Redex slow.
// Typical usage would be to place OPT_OFF just below includes at the top of a
// CPP file, or to wrap a function in an OPT_OFF/OPT_ON pair.
#define OPT_OFF _Pragma("clang optimize off")
#define OPT_ON _Pragma("clang optimize on")
#endif