1 #ifndef CUTTER_H
2 #define CUTTER_H
3 
4 #include "core/CutterCommon.h"
5 #include "core/CutterDescriptions.h"
6 #include "common/BasicInstructionHighlighter.h"
7 
8 #include <QMap>
9 #include <QMenu>
10 #include <QDebug>
11 #include <QObject>
12 #include <QStringList>
13 #include <QMessageBox>
14 #include <QJsonDocument>
15 #include <QErrorMessage>
16 #include <QMutex>
17 #include <QDir>
18 
19 class AsyncTaskManager;
20 class BasicInstructionHighlighter;
21 class CutterCore;
22 class Decompiler;
23 class R2Task;
24 class R2TaskDialog;
25 
26 #include "common/BasicBlockHighlighter.h"
27 #include "common/R2Task.h"
28 #include "common/Helpers.h"
29 #include "dialogs/R2TaskDialog.h"
30 
31 #define Core() (CutterCore::instance())
32 
33 class RCoreLocked;
34 
35 class CUTTER_EXPORT CutterCore: public QObject
36 {
37     Q_OBJECT
38 
39     friend class RCoreLocked;
40     friend class R2Task;
41 
42 public:
43     explicit CutterCore(QObject *parent = nullptr);
44     ~CutterCore();
45     static CutterCore *instance();
46 
47     void initialize(bool loadPlugins = true);
48     void loadCutterRC();
49     void loadDefaultCutterRC();
50     QDir getCutterRCDefaultDirectory() const;
51 
getAsyncTaskManager()52     AsyncTaskManager *getAsyncTaskManager() { return asyncTaskManager; }
53 
getOffset()54     RVA getOffset() const                   { return core_->offset; }
55 
56     /* Core functions (commands) */
57     static QString sanitizeStringForCommand(QString s);
58     /**
59      * @brief send a command to radare2
60      * @param str the command you want to execute
61      * @return command output
62      * @note if you want to seek to an address, you should use CutterCore::seek.
63      */
64     QString cmd(const char *str);
cmd(const QString & str)65     QString cmd(const QString &str) { return cmd(str.toUtf8().constData()); }
66     /**
67      * @brief send a command to radare2 asynchronously
68      * @param str the command you want to execute
69      * @param task a shared pointer that will be returned with the R2 command task
70      * @note connect to the &R2Task::finished signal to add your own logic once
71      *       the command is finished. Use task->getResult()/getResultJson() for the
72      *       return value.
73      *       Once you have setup connections you can start the task with task->startTask()
74      *       If you want to seek to an address, you should use CutterCore::seek.
75      */
76     bool asyncCmd(const char *str, QSharedPointer<R2Task> &task);
asyncCmd(const QString & str,QSharedPointer<R2Task> & task)77     bool asyncCmd(const QString &str, QSharedPointer<R2Task> &task) { return asyncCmd(str.toUtf8().constData(), task); }
78 
79     /**
80      * @brief Execute a radare2 command \a cmd.  By nature, the API
81      * is executing raw commands, and thus ignores multiple commands and overcome command injections.
82      * @param cmd - a raw command to execute. Passing multiple commands (e.g "px 5; pd 7 && pdf") will result in them treated as arguments to first command.
83      * @return the output of the command
84      */
85     QString cmdRaw(const char *cmd);
86 
87     /**
88      * @brief a wrapper around cmdRaw(const char *cmd,).
89      */
cmdRaw(const QString & cmd)90     QString cmdRaw(const QString &cmd) { return cmdRaw(cmd.toUtf8().constData()); };
91 
92     /**
93      * @brief Execute a radare2 command \a cmd at \a address. The function will preform a silent seek to the address
94      * without triggering the seekChanged event nor adding new entries to the seek history. By nature, the
95      * API is executing a single command without going through radare2 shell, and thus ignores multiple commands
96      * and tries to overcome command injections.
97      * @param cmd - a raw command to execute. If multiple commands will be passed (e.g "px 5; pd 7 && pdf") then
98      * only the first command will be executed.
99      * @param address - an address to which Cutter will temporarily seek.
100      * @return the output of the command
101      */
102     QString cmdRawAt(const char *cmd, RVA address);
103 
104     /**
105      * @brief a wrapper around cmdRawAt(const char *cmd, RVA address).
106      */
cmdRawAt(const QString & str,RVA address)107     QString cmdRawAt(const QString &str, RVA address) { return cmdRawAt(str.toUtf8().constData(), address); }
108 
109     QJsonDocument cmdj(const char *str);
cmdj(const QString & str)110     QJsonDocument cmdj(const QString &str) { return cmdj(str.toUtf8().constData()); }
111     QJsonDocument cmdjAt(const char *str, RVA address);
cmdList(const char * str)112     QStringList cmdList(const char *str) { return cmd(str).split(QLatin1Char('\n'), CUTTER_QT_SKIP_EMPTY_PARTS); }
cmdList(const QString & str)113     QStringList cmdList(const QString &str) { return cmdList(str.toUtf8().constData()); }
114     QString cmdTask(const QString &str);
115     QJsonDocument cmdjTask(const QString &str);
116     /**
117      * @brief send a command to radare2 and check for ESIL errors
118      * @param command the command you want to execute
119      * @note If you want to seek to an address, you should use CutterCore::seek.
120      */
121     void cmdEsil(const char *command);
cmdEsil(const QString & command)122     void cmdEsil(const QString &command) { cmdEsil(command.toUtf8().constData()); }
123     /**
124      * @brief send a command to radare2 and check for ESIL errors
125      * @param command the command you want to execute
126      * @param task a shared pointer that will be returned with the R2 command task
127      * @note connect to the &R2Task::finished signal to add your own logic once
128      *       the command is finished. Use task->getResult()/getResultJson() for the
129      *       return value.
130      *       Once you have setup connections you can start the task with task->startTask()
131      *       If you want to seek to an address, you should use CutterCore::seek.
132      */
133     bool asyncCmdEsil(const char *command, QSharedPointer<R2Task> &task);
asyncCmdEsil(const QString & command,QSharedPointer<R2Task> & task)134     bool asyncCmdEsil(const QString &command, QSharedPointer<R2Task> &task) { return asyncCmdEsil(command.toUtf8().constData(), task); }
135     QString getVersionInformation();
136 
137     QJsonDocument parseJson(const char *res, const char *cmd = nullptr);
138     QJsonDocument parseJson(const char *res, const QString &cmd = QString())
139     {
140         return parseJson(res, cmd.isNull() ? nullptr : cmd.toLocal8Bit().constData());
141     }
142 
143     QStringList autocomplete(const QString &cmd, RLinePromptType promptType, size_t limit = 4096);
144 
145     /* Functions methods */
146     void renameFunction(const RVA offset, const QString &newName);
147     void delFunction(RVA addr);
148     void renameFlag(QString old_name, QString new_name);
149     /**
150      * @brief Renames the specified local variable in the function specified by the
151      * address given.
152      * @param newName Specifies the name to which the current name of the variable
153      * should be renamed.
154      * @param oldName Specifies the current name of the function variable.
155      * @param functionAddress Specifies the exact address of the function.
156      */
157     void renameFunctionVariable(QString newName, QString oldName, RVA functionAddress);
158 
159     /**
160      * @param addr
161      * @return a function that contains addr or nullptr
162      */
163     RAnalFunction *functionIn(ut64 addr);
164 
165     /**
166      * @param addr
167      * @return the function that has its entrypoint at addr or nullptr
168      */
169     RAnalFunction *functionAt(ut64 addr);
170 
171     RVA getFunctionStart(RVA addr);
172     RVA getFunctionEnd(RVA addr);
173     RVA getLastFunctionInstruction(RVA addr);
174     QString cmdFunctionAt(QString addr);
175     QString cmdFunctionAt(RVA addr);
176     QString createFunctionAt(RVA addr);
177     QString createFunctionAt(RVA addr, QString name);
178     QStringList getDisassemblyPreview(RVA address, int num_of_lines);
179 
180     /* Flags */
181     void delFlag(RVA addr);
182     void delFlag(const QString &name);
183     void addFlag(RVA offset, QString name, RVA size);
184     QString listFlagsAsStringAt(RVA addr);
185     /**
186      * @brief Get nearest flag at or before offset.
187      * @param offset search position
188      * @param flagOffsetOut address of returned flag
189      * @return flag name
190      */
191     QString nearestFlag(RVA offset, RVA *flagOffsetOut);
192     void triggerFlagsChanged();
193 
194     /* Edition functions */
195     QString getInstructionBytes(RVA addr);
196     QString getInstructionOpcode(RVA addr);
197     void editInstruction(RVA addr, const QString &inst);
198     void nopInstruction(RVA addr);
199     void jmpReverse(RVA addr);
200     void editBytes(RVA addr, const QString &inst);
201     void editBytesEndian(RVA addr, const QString &bytes);
202 
203     /* Code/Data */
204     void setToCode(RVA addr);
205     enum class StringTypeFormats { None, ASCII_LATIN1, UTF8 };
206     /**
207      * @brief Adds string at address
208      * That function calls the 'Cs' command
209      * \param addr The address of the array where the string will be applied
210      * \param size The size of string
211      * \param type The type of string
212      */
213     void setAsString(RVA addr, int size = 0, StringTypeFormats type = StringTypeFormats::None);
214     /**
215      * @brief Removes string at address
216      * That function calls the 'Cs-' command
217      * \param addr The address of the array where the string will be applied
218      */
219     void removeString(RVA addr);
220     /**
221      * @brief Gets string at address
222      * That function calls the 'ps' command
223      * \param addr The address of the first byte of the array
224      * @return string at requested address
225      */
226     QString getString(RVA addr);
227     void setToData(RVA addr, int size, int repeat = 1);
228     int sizeofDataMeta(RVA addr);
229 
230     /* Comments */
231     void setComment(RVA addr, const QString &cmt);
232     void delComment(RVA addr);
233     QString getCommentAt(RVA addr);
234     void setImmediateBase(const QString &r2BaseName, RVA offset = RVA_INVALID);
235     void setCurrentBits(int bits, RVA offset = RVA_INVALID);
236 
237     /**
238      * @brief Changes immediate displacement to structure offset
239      * This function makes use of the "aht" command of r2 to apply structure
240      * offset to the immediate displacement used in the given instruction
241      * \param structureOffset The name of struct which will be applied
242      * \param offset The address of the instruction where the struct will be applied
243      */
244     void applyStructureOffset(const QString &structureOffset, RVA offset = RVA_INVALID);
245 
246     /* Classes */
247     QList<QString> getAllAnalClasses(bool sorted);
248     QList<AnalMethodDescription> getAnalClassMethods(const QString &cls);
249     QList<AnalBaseClassDescription> getAnalClassBaseClasses(const QString &cls);
250     QList<AnalVTableDescription> getAnalClassVTables(const QString &cls);
251     void createNewClass(const QString &cls);
252     void renameClass(const QString &oldName, const QString &newName);
253     void deleteClass(const QString &cls);
254     bool getAnalMethod(const QString &cls, const QString &meth, AnalMethodDescription *desc);
255     void renameAnalMethod(const QString &className, const QString &oldMethodName, const QString &newMethodName);
256     void setAnalMethod(const QString &cls, const AnalMethodDescription &meth);
257 
258     /* File related methods */
259     bool loadFile(QString path, ut64 baddr = 0LL, ut64 mapaddr = 0LL, int perms = R_PERM_R,
260                   int va = 0, bool loadbin = false, const QString &forceBinPlugin = QString());
261     bool tryFile(QString path, bool rw);
262     bool mapFile(QString path, RVA mapaddr);
263     void loadScript(const QString &scriptname);
264     QJsonArray getOpenedFiles();
265 
266     /* Seek functions */
267     void seek(QString thing);
268     void seek(ut64 offset);
269     void seekSilent(ut64 offset);
seekSilent(QString thing)270     void seekSilent(QString thing) { seekSilent(math(thing)); }
271     void seekPrev();
272     void seekNext();
273     void updateSeek();
274     /**
275      * @brief Raise a memory widget showing current offset, prefer last active
276      * memory widget.
277      */
278     void showMemoryWidget();
279     /**
280      * @brief Seek to \p offset and raise a memory widget showing it.
281      * @param offset
282      */
283     void seekAndShow(ut64 offset);
284     /**
285      * @brief \see CutterCore::show(ut64)
286      * @param thing - addressable expression
287      */
288     void seekAndShow(QString thing);
289     RVA getOffset();
290     RVA prevOpAddr(RVA startAddr, int count);
291     RVA nextOpAddr(RVA startAddr, int count);
292 
293     /* Math functions */
294     ut64 math(const QString &expr);
295     ut64 num(const QString &expr);
296     QString itoa(ut64 num, int rdx = 16);
297 
298     /* Config functions */
299     void setConfig(const char *k, const char *v);
300     void setConfig(const QString &k, const char *v);
301     void setConfig(const char *k, const QString &v);
setConfig(const QString & k,const QString & v)302     void setConfig(const QString &k, const QString &v) { setConfig(k.toUtf8().constData(), v); }
303     void setConfig(const char *k, int v);
setConfig(const QString & k,int v)304     void setConfig(const QString &k, int v) { setConfig(k.toUtf8().constData(), v); }
305     void setConfig(const char *k, bool v);
setConfig(const QString & k,bool v)306     void setConfig(const QString &k, bool v) { setConfig(k.toUtf8().constData(), v); }
307     void setConfig(const char *k, const QVariant &v);
setConfig(const QString & k,const QVariant & v)308     void setConfig(const QString &k, const QVariant &v) { setConfig(k.toUtf8().constData(), v); }
309     int getConfigi(const char *k);
getConfigi(const QString & k)310     int getConfigi(const QString &k) { return getConfigi(k.toUtf8().constData()); }
311     ut64 getConfigut64(const char *k);
getConfigut64(const QString & k)312     ut64 getConfigut64(const QString &k) { return getConfigut64(k.toUtf8().constData()); }
313     bool getConfigb(const char *k);
getConfigb(const QString & k)314     bool getConfigb(const QString &k) { return getConfigb(k.toUtf8().constData()); }
315     QString getConfig(const char *k);
getConfig(const QString & k)316     QString getConfig(const QString &k) { return getConfig(k.toUtf8().constData()); }
317     QString getConfigDescription(const char *k);
318     QList<QString> getColorThemes();
319 
320     /* Assembly\Hexdump related methods */
321     QByteArray assemble(const QString &code);
322     QString disassemble(const QByteArray &data);
323     QString disassembleSingleInstruction(RVA addr);
324     QList<DisassemblyLine> disassembleLines(RVA offset, int lines);
325 
326     static QByteArray hexStringToBytes(const QString &hex);
327     static QString bytesToHexString(const QByteArray &bytes);
328     enum class HexdumpFormats { Normal, Half, Word, Quad, Signed, Octal };
329     QString hexdump(RVA offset, int size, HexdumpFormats format);
330     QString getHexdumpPreview(RVA offset, int size);
331 
332     void setCPU(QString arch, QString cpu, int bits);
333     void setEndianness(bool big);
334 
335     /* SDB */
336     QList<QString> sdbList(QString path);
337     QList<QString> sdbListKeys(QString path);
338     QString sdbGet(QString path, QString key);
339     bool sdbSet(QString path, QString key, QString val);
340 
341     /* Debug */
342     QJsonDocument getRegistersInfo();
343     QJsonDocument getRegisterValues();
344     QString getRegisterName(QString registerRole);
345     RVA getProgramCounterValue();
346     void setRegister(QString regName, QString regValue);
347     void setCurrentDebugThread(int tid);
348     /**
349      * @brief Attach to a given pid from a debug session
350      */
351     void setCurrentDebugProcess(int pid);
352     /**
353      * @brief Returns a list of stack address and their telescoped references
354      * @param size number of bytes to scan
355      * @param depth telescoping depth
356      */
357     QList<QJsonObject> getStack(int size = 0x100, int depth = 6);
358     /**
359      * @brief Recursively dereferences pointers starting at the specified address
360      *        up to a given depth
361      * @param addr telescoping addr
362      * @param depth telescoping depth
363      */
364     QJsonObject getAddrRefs(RVA addr, int depth);
365     /**
366      * @brief return a RefDescription with a formatted ref string and configured colors
367      * @param ref the "ref" JSON node from getAddrRefs
368      */
369     RefDescription formatRefDesc(QJsonObject ref);
370     /**
371      * @brief Get a list of a given process's threads
372      * @param pid The pid of the process, -1 for the currently debugged process
373      * @return JSON object result of dptj
374      */
375     QJsonDocument getProcessThreads(int pid);
376     /**
377      * @brief Get a list of a given process's child processes
378      * @param pid The pid of the process, -1 for the currently debugged process
379      * @return JSON object result of dptj
380      */
381     QJsonDocument getChildProcesses(int pid);
382     QJsonDocument getBacktrace();
383     void startDebug();
384     void startEmulation();
385     /**
386      * @brief attach to a remote debugger
387      * @param uri remote debugger uri
388      * @note attachedRemote(bool) signals the result
389      */
390     void attachRemote(const QString &uri);
391     void attachDebug(int pid);
392     void stopDebug();
393     void suspendDebug();
394     void syncAndSeekProgramCounter();
395     void continueDebug();
396     void continueUntilCall();
397     void continueUntilSyscall();
398     void continueUntilDebug(QString offset);
399     void stepDebug();
400     void stepOverDebug();
401     void stepOutDebug();
402 
403     void addBreakpoint(const BreakpointDescription &config);
404     void updateBreakpoint(int index, const BreakpointDescription &config);
405     void toggleBreakpoint(RVA addr);
406     void delBreakpoint(RVA addr);
407     void delAllBreakpoints();
408     void enableBreakpoint(RVA addr);
409     void disableBreakpoint(RVA addr);
410     /**
411      * @brief Enable or disable breakpoint tracing.
412      * @param index - breakpoint index to modify
413      * @param enabled - true if tracing should be enabled
414      */
415     void setBreakpointTrace(int index, bool enabled);
416     int breakpointIndexAt(RVA addr);
417     BreakpointDescription getBreakpointAt(RVA addr);
418 
419     bool isBreakpoint(const QList<RVA> &breakpoints, RVA addr);
420     QList<RVA> getBreakpointsAddresses();
421 
422     /**
423      * @brief Get all breakpoinst that are belong to a functions at this address
424      */
425     QList<RVA> getBreakpointsInFunction(RVA funcAddr);
426     QString getActiveDebugPlugin();
427     QStringList getDebugPlugins();
428     void setDebugPlugin(QString plugin);
429     bool isDebugTaskInProgress();
430     /**
431      * @brief Check if we can use output/input redirection with the currently debugged process
432      */
433     bool isRedirectableDebugee();
434     bool currentlyDebugging = false;
435     bool currentlyEmulating = false;
436     int currentlyAttachedToPID = -1;
437     QString currentlyOpenFile;
438 
439     /* Decompilers */
440     QList<Decompiler *> getDecompilers();
441     Decompiler *getDecompilerById(const QString &id);
442 
443     /**
444      * Register a new decompiler
445      *
446      * The decompiler must have a unique id, otherwise this method will fail.
447      * The decompiler's parent will be set to this CutterCore instance, so it will automatically be freed later.
448      *
449      * @return whether the decompiler was registered successfully
450      */
451     bool registerDecompiler(Decompiler *decompiler);
452 
453     RVA getOffsetJump(RVA addr);
454     QJsonDocument getFileInfo();
455     QJsonDocument getSignatureInfo();
456     QJsonDocument getFileVersionInfo();
457     QStringList getStats();
458     void setGraphEmpty(bool empty);
459     bool isGraphEmpty();
460 
461     void getOpcodes();
462     QList<QString> opcodes;
463     QList<QString> regs;
464     void setSettings();
465 
466     void loadPDB(const QString &file);
467 
468     QByteArray ioRead(RVA addr, int len);
469 
470     QList<RVA> getSeekHistory();
471 
472     /* Plugins */
473     QStringList getAsmPluginNames();
474     QStringList getAnalPluginNames();
475 
476     /* Projects */
477     QStringList getProjectNames();
478     void openProject(const QString &name);
479     void saveProject(const QString &name);
480     void deleteProject(const QString &name);
481     static bool isProjectNameValid(const QString &name);
482 
483     /* Widgets */
484     QList<RBinPluginDescription> getRBinPluginDescriptions(const QString &type = QString());
485     QList<RIOPluginDescription> getRIOPluginDescriptions();
486     QList<RCorePluginDescription> getRCorePluginDescriptions();
487     QList<RAsmPluginDescription> getRAsmPluginDescriptions();
488     QList<FunctionDescription> getAllFunctions();
489     QList<ImportDescription> getAllImports();
490     QList<ExportDescription> getAllExports();
491     QList<SymbolDescription> getAllSymbols();
492     QList<HeaderDescription> getAllHeaders();
493     QList<ZignatureDescription> getAllZignatures();
494     QList<CommentDescription> getAllComments(const QString &filterType);
495     QList<RelocDescription> getAllRelocs();
496     QList<StringDescription> getAllStrings();
497     QList<FlagspaceDescription> getAllFlagspaces();
498     QList<FlagDescription> getAllFlags(QString flagspace = QString());
499     QList<SectionDescription> getAllSections();
500     QList<SegmentDescription> getAllSegments();
501     QList<EntrypointDescription> getAllEntrypoint();
502     QList<BinClassDescription> getAllClassesFromBin();
503     QList<BinClassDescription> getAllClassesFromFlags();
504     QList<ResourcesDescription> getAllResources();
505     QList<VTableDescription> getAllVTables();
506 
507     /**
508      * @return all loaded types
509      */
510     QList<TypeDescription> getAllTypes();
511 
512     /**
513      * @return all loaded primitive types
514      */
515     QList<TypeDescription> getAllPrimitiveTypes();
516 
517     /**
518      * @return all loaded unions
519      */
520     QList<TypeDescription> getAllUnions();
521 
522     /**
523      * @return all loaded structs
524      */
525     QList<TypeDescription> getAllStructs();
526 
527     /**
528      * @return all loaded enums
529      */
530     QList<TypeDescription> getAllEnums();
531 
532     /**
533      * @return all loaded typedefs
534      */
535     QList<TypeDescription> getAllTypedefs();
536 
537     /**
538      * @brief Fetching the C representation of a given Type
539      * @param name - the name or the type of the given Type / Struct
540      * @param category - the category of the given Type (Struct, Union, Enum, ...)
541      * @return The type decleration as C output
542      */
543     QString getTypeAsC(QString name, QString category);
544 
545 
546     /**
547      * @brief Adds new types
548      * It first uses the r_parse_c_string() function from radare2 API to parse the
549      * supplied C file (in the form of a string). If there were errors, they are displayed.
550      * If there were no errors, it uses sdb_query_lines() function from radare2 API
551      * to save the parsed types returned by r_parse_c_string()
552      * \param str Contains the definition of the data types
553      * \return returns an empty QString if there was no error, else returns the error
554      */
555     QString addTypes(const char *str);
addTypes(const QString & str)556     QString addTypes(const QString &str) { return addTypes(str.toUtf8().constData()); }
557 
558     /**
559      * @brief Checks if the given address is mapped to a region
560      * @param addr The address to be checked
561      * @return true if addr is mapped, false otherwise
562      */
563     bool isAddressMapped(RVA addr);
564 
565     QList<MemoryMapDescription> getMemoryMap();
566     QList<SearchDescription> getAllSearch(QString search_for, QString space);
567     BlockStatistics getBlockStatistics(unsigned int blocksCount);
568     QList<BreakpointDescription> getBreakpoints();
569     QList<ProcessDescription> getAllProcesses();
570     /**
571      * @brief returns a list of reg values and their telescoped references
572      * @param depth telescoping depth
573      */
574     QList<QJsonObject> getRegisterRefs(int depth = 6);
575     QVector<RegisterRefValueDescription> getRegisterRefValues();
576     QList<VariableDescription> getVariables(RVA at);
577     /**
578      * @brief Fetches all the writes or reads to the specified local variable 'variableName'
579      * in the function in which the specified offset is a part of.
580      * @param variableName Name of the local variable.
581      * @param findWrites If this is true, then locations at which modification happen to the specified
582      * local variable is fetched. Else, the locations at which the local is variable is read is fetched.
583      * @param offset An offset in the function in which the specified local variable exist.
584      * @return A list of XrefDescriptions that contains details of all the writes or reads that happen to the
585      * variable 'variableName'.
586      */
587     QList<XrefDescription> getXRefsForVariable(QString variableName, bool findWrites, RVA offset);
588     QList<XrefDescription> getXRefs(RVA addr, bool to, bool whole_function,
589                                     const QString &filterType = QString());
590 
591     QList<StringDescription> parseStringsJson(const QJsonDocument &doc);
592 
593     void handleREvent(int type, void *data);
594 
595     /* Signals related */
596     void triggerVarsChanged();
597     void triggerFunctionRenamed(const RVA offset, const QString &newName);
598     void triggerRefreshAll();
599     void triggerAsmOptionsChanged();
600     void triggerGraphOptionsChanged();
601 
602     void message(const QString &msg, bool debug = false);
603 
604     QStringList getSectionList();
605 
606     RCoreLocked core();
607 
608     static QString ansiEscapeToHtml(const QString &text);
609     BasicBlockHighlighter *getBBHighlighter();
610     BasicInstructionHighlighter *getBIHighlighter();
611 
612     /**
613      * @brief Enable or dsiable Cache mode. Cache mode is used to imagine writing to the opened file
614      * without committing the changes to the disk.
615      * @param enabled
616      */
617     void setIOCache(bool enabled);
618 
619     /**
620      * @brief Check if Cache mode is enabled.
621      * @return true if Cache is enabled, otherwise return false.
622      */
623     bool isIOCacheEnabled() const;
624 
625     /**
626      * @brief Commit write cache to the file on disk.
627      */
628     void commitWriteCache();
629 
630     /**
631      * @brief Enable or disable Write mode. When the file is opened in write mode, any changes to it will be immediately
632      * committed to the file on disk, thus modify the file. This function wrap radare2 function which re-open the file with
633      * the desired permissions.
634      * @param enabled
635      */
636     void setWriteMode(bool enabled);
637     /**
638      * @brief Check if the file is opened in write mode.
639      * @return true if write mode is enabled, otherwise return false.
640      */
641     bool isWriteModeEnabled();
642 
643 signals:
644     void refreshAll();
645 
646     void functionRenamed(const RVA offset, const QString &new_name);
647     void varsChanged();
648     void functionsChanged();
649     void flagsChanged();
650     void commentsChanged(RVA addr);
651     void registersChanged();
652     void instructionChanged(RVA offset);
653     void breakpointsChanged(RVA offset);
654     void refreshCodeViews();
655     void stackChanged();
656     /**
657      * @brief update all the widgets that are affected by rebasing in debug mode
658      */
659     void codeRebased();
660 
661     void switchedThread();
662     void switchedProcess();
663 
664     void classNew(const QString &cls);
665     void classDeleted(const QString &cls);
666     void classRenamed(const QString &oldName, const QString &newName);
667     void classAttrsChanged(const QString &cls);
668 
669     /**
670      * @brief end of current debug event received
671      */
672     void debugProcessFinished(int pid);
673 
674     void attachedRemote(bool successfully);
675 
676     void projectSaved(bool successfully, const QString &name);
677 
678     void ioCacheChanged(bool newval);
679     void writeModeChanged(bool newval);
680     void ioModeChanged();
681 
682     /**
683      * emitted when debugTask started or finished running
684      */
685     void debugTaskStateChanged();
686 
687     /**
688      * emitted when config regarding disassembly display changes
689      */
690     void asmOptionsChanged();
691 
692     /**
693      * emitted when config regarding graph display changes
694      */
695     void graphOptionsChanged();
696 
697     /**
698      * @brief seekChanged is emitted each time radare2 seek value is modified
699      * @param offset
700      */
701     void seekChanged(RVA offset);
702 
703     void toggleDebugView();
704 
705     void newMessage(const QString &msg);
706     void newDebugMessage(const QString &msg);
707 
708     void showMemoryWidgetRequested();
709 
710 private:
711     QString notes;
712 
713     /**
714      * Internal reference to the RCore.
715      * NEVER use this directly! Always use the CORE_LOCK(); macro and access it like core->...
716      */
717     RCore *core_ = nullptr;
718 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
719     QMutex coreMutex;
720 #else
721     QRecursiveMutex coreMutex;
722 #endif
723     int coreLockDepth = 0;
724     void *coreBed = nullptr;
725 
726     AsyncTaskManager *asyncTaskManager;
727     RVA offsetPriorDebugging = RVA_INVALID;
728     QErrorMessage msgBox;
729 
730     QList<Decompiler *> decompilers;
731 
732     bool emptyGraph = false;
733     BasicBlockHighlighter *bbHighlighter;
734     bool iocache = false;
735     BasicInstructionHighlighter biHighlighter;
736 
737     QSharedPointer<R2Task> debugTask;
738     R2TaskDialog *debugTaskDialog;
739 
740     QVector<QString> getCutterRCFilePaths() const;
741 };
742 
743 class CUTTER_EXPORT RCoreLocked
744 {
745     CutterCore * const core;
746 
747 public:
748     explicit RCoreLocked(CutterCore *core);
749     RCoreLocked(const RCoreLocked &) = delete;
750     RCoreLocked &operator=(const RCoreLocked &) = delete;
751     RCoreLocked(RCoreLocked &&);
752     ~RCoreLocked();
753     operator RCore *() const;
754     RCore *operator->() const;
755 };
756 
757 #endif // CUTTER_H
758