From b42bb8a19e4eb53e9e570c22fe4b7296c14d36eb Mon Sep 17 00:00:00 2001 From: Nukem Date: Sun, 22 Mar 2015 19:03:04 -0400 Subject: [PATCH] Refactor comment.cpp/.h --- x64_dbg_dbg/_exports.cpp | 8 +- x64_dbg_dbg/addrinfo.cpp | 6 +- x64_dbg_dbg/bookmark.cpp | 4 +- x64_dbg_dbg/comment.cpp | 305 ++++++++++++++++++------------ x64_dbg_dbg/comment.h | 21 +- x64_dbg_dbg/debugger_commands.cpp | 2 +- x64_dbg_dbg/instruction.cpp | 12 +- 7 files changed, 213 insertions(+), 145 deletions(-) diff --git a/x64_dbg_dbg/_exports.cpp b/x64_dbg_dbg/_exports.cpp index f7c9a109..621d8996 100644 --- a/x64_dbg_dbg/_exports.cpp +++ b/x64_dbg_dbg/_exports.cpp @@ -154,7 +154,7 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoget(duint addr, SEGMENTREG segment, ADDR if(addrinfo->flags & flagcomment) { *addrinfo->comment = 0; - if(commentget(addr, addrinfo->comment)) + if(CommentGet(addr, addrinfo->comment)) retval = true; else { @@ -300,7 +300,7 @@ extern "C" DLL_EXPORT bool _dbg_addrinfoset(duint addr, ADDRINFO* addrinfo) } if(addrinfo->flags & flagcomment) //set comment { - if(commentset(addr, addrinfo->comment, true)) + if(CommentSet(addr, addrinfo->comment, true)) retval = true; } if(addrinfo->flags & flagbookmark) //set bookmark @@ -875,13 +875,13 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par case DBG_SET_AUTO_COMMENT_AT: { - return (uint)commentset((uint)param1, (const char*)param2, false); + return (uint)CommentSet((uint)param1, (const char*)param2, false); } break; case DBG_DELETE_AUTO_COMMENT_RANGE: { - commentdelrange((uint)param1, (uint)param2); + CommentDelRange((uint)param1, (uint)param2); } break; diff --git a/x64_dbg_dbg/addrinfo.cpp b/x64_dbg_dbg/addrinfo.cpp index 52a51d9a..2475333c 100644 --- a/x64_dbg_dbg/addrinfo.cpp +++ b/x64_dbg_dbg/addrinfo.cpp @@ -21,7 +21,7 @@ void dbsave() dprintf("saving database..."); DWORD ticks = GetTickCount(); JSON root = json_object(); - commentcachesave(root); + CommentCacheSave(root); labelcachesave(root); BookmarkCacheSave(root); FunctionCacheSave(root); @@ -82,7 +82,7 @@ void dbload() dputs("\ninvalid database file (JSON)!"); return; } - commentcacheload(root); + CommentCacheLoad(root); labelcacheload(root); BookmarkCacheLoad(root); FunctionCacheLoad(root); @@ -95,7 +95,7 @@ void dbload() void dbclose() { dbsave(); - commentclear(); + CommentClear(); labelclear(); BookmarkClear(); FunctionClear(); diff --git a/x64_dbg_dbg/bookmark.cpp b/x64_dbg_dbg/bookmark.cpp index 6db5e1a9..7e9f42ae 100644 --- a/x64_dbg_dbg/bookmark.cpp +++ b/x64_dbg_dbg/bookmark.cpp @@ -183,7 +183,9 @@ bool BookmarkEnum(BOOKMARKSINFO* List, size_t* Size) if(Size) { *Size = bookmarks.size() * sizeof(BOOKMARKSINFO); - return true; + + if(!List) + return true; } // Copy struct and adjust the relative offset to a virtual address diff --git a/x64_dbg_dbg/comment.cpp b/x64_dbg_dbg/comment.cpp index a42b5940..122219b8 100644 --- a/x64_dbg_dbg/comment.cpp +++ b/x64_dbg_dbg/comment.cpp @@ -8,175 +8,244 @@ typedef std::map CommentsInfo; static CommentsInfo comments; -bool commentset(uint addr, const char* text, bool manual) +bool CommentSet(uint Address, const char* Text, bool Manual) { - if(!DbgIsDebugging() or !memisvalidreadptr(fdProcessInfo->hProcess, addr) or !text or text[0] == '\1' or strlen(text) >= MAX_COMMENT_SIZE - 1) + // CHECK: Exported/Command function + if(!DbgIsDebugging()) return false; - if(!*text) //NOTE: delete when there is no text + + // A valid memory address must be supplied + if(!memisvalidreadptr(fdProcessInfo->hProcess, Address)) + return false; + + // Make sure the string is supplied, within bounds, and not a special delimiter + if(!Text || Text[0] == '\1' || strlen(Text) >= MAX_COMMENT_SIZE - 1) + return false; + + // Delete the comment if no text was supplied + if(!*Text) { - commentdel(addr); + CommentDelete(Address); return true; } + + // Fill out the structure COMMENTSINFO comment; - comment.manual = manual; - strcpy_s(comment.text, text); - ModNameFromAddr(addr, comment.mod, true); - comment.addr = addr - ModBaseFromAddr(addr); - const uint key = ModHashFromAddr(addr); - CriticalSectionLocker locker(LockComments); - if(!comments.insert(std::make_pair(key, comment)).second) //key already present + strcpy_s(comment.text, Text); + ModNameFromAddr(Address, comment.mod, true); + + comment.manual = Manual; + comment.addr = Address - ModBaseFromAddr(Address); + + // Insert into list + const uint key = ModHashFromAddr(Address); + + EXCLUSIVE_ACQUIRE(LockComments); + + // Only add if the key wasn't present + if(!comments.insert(std::make_pair(key, comment)).second) comments[key] = comment; + return true; } -bool commentget(uint addr, char* text) +bool CommentGet(uint Address, char* Text) { + // CHECK: Exported/Command function if(!DbgIsDebugging()) return false; - CriticalSectionLocker locker(LockComments); - const CommentsInfo::iterator found = comments.find(ModHashFromAddr(addr)); - if(found == comments.end()) //not found + + SHARED_ACQUIRE(LockComments); + + // Get an existing comment and copy the string buffer + auto found = comments.find(ModHashFromAddr(Address)); + + // Was it found? + if(found == comments.end()) return false; - strcpy_s(text, MAX_COMMENT_SIZE, found->second.text); + + strcpy_s(Text, MAX_COMMENT_SIZE, found->second.text); return true; } -bool commentdel(uint addr) +bool CommentDelete(uint Address) { + // CHECK: Command/Sub function if(!DbgIsDebugging()) return false; - CriticalSectionLocker locker(LockComments); - return (comments.erase(ModHashFromAddr(addr)) == 1); + + EXCLUSIVE_ACQUIRE(LockComments); + return (comments.erase(ModHashFromAddr(Address)) > 0); } -void commentdelrange(uint start, uint end) +void CommentDelRange(uint Start, uint End) { + // CHECK: Export function if(!DbgIsDebugging()) return; - bool bDelAll = (start == 0 && end == ~0); //0x00000000-0xFFFFFFFF - uint modbase = ModBaseFromAddr(start); - if(modbase != ModBaseFromAddr(end)) - return; - start -= modbase; - end -= modbase; - CriticalSectionLocker locker(LockComments); - CommentsInfo::iterator i = comments.begin(); - while(i != comments.end()) + + // Are all comments going to be deleted? + if(Start == 0x00000000 && End == 0xFFFFFFFF) { - if(i->second.manual) //ignore manual + EXCLUSIVE_ACQUIRE(LockComments); + comments.clear(); + } + else + { + // Make sure 'Start' and 'End' reference the same module + uint moduleBase = ModBaseFromAddr(Start); + + if(moduleBase != ModBaseFromAddr(End)) + return; + + // Virtual -> relative offset + Start -= moduleBase; + End -= moduleBase; + + EXCLUSIVE_ACQUIRE(LockComments); + for(auto itr = comments.begin(); itr != comments.end();) { - i++; - continue; + // Ignore manually set entries + if(itr->second.manual) + { + itr++; + continue; + } + + // [Start, End) + if(itr->second.addr >= Start && itr->second.addr < End) + itr = comments.erase(itr); + else + itr++; } - if(bDelAll || (i->second.addr >= start && i->second.addr < end)) - comments.erase(i++); - else - i++; } } -void commentcachesave(JSON root) +void CommentCacheSave(JSON Root) { - CriticalSectionLocker locker(LockComments); - const JSON jsoncomments = json_array(); - const JSON jsonautocomments = json_array(); - for(CommentsInfo::iterator i = comments.begin(); i != comments.end(); ++i) + EXCLUSIVE_ACQUIRE(LockComments); + + const JSON jsonComments = json_array(); + const JSON jsonAutoComments = json_array(); + + // Build the JSON array + for(auto & itr : comments) { - const COMMENTSINFO curComment = i->second; - JSON curjsoncomment = json_object(); - json_object_set_new(curjsoncomment, "module", json_string(curComment.mod)); - json_object_set_new(curjsoncomment, "address", json_hex(curComment.addr)); - json_object_set_new(curjsoncomment, "text", json_string(curComment.text)); - if(curComment.manual) - json_array_append_new(jsoncomments, curjsoncomment); + JSON currentComment = json_object(); + + json_object_set_new(currentComment, "module", json_string(itr.second.mod)); + json_object_set_new(currentComment, "address", json_hex(itr.second.addr)); + json_object_set_new(currentComment, "text", json_string(itr.second.text)); + + if(itr.second.manual) + json_array_append_new(jsonComments, currentComment); else - json_array_append_new(jsonautocomments, curjsoncomment); + json_array_append_new(jsonAutoComments, currentComment); } - if(json_array_size(jsoncomments)) - json_object_set(root, "comments", jsoncomments); - json_decref(jsoncomments); - if(json_array_size(jsonautocomments)) - json_object_set(root, "autocomments", jsonautocomments); - json_decref(jsonautocomments); + + // Save to the JSON root + if(json_array_size(jsonComments)) + json_object_set(Root, "comments", jsonComments); + + if(json_array_size(jsonAutoComments)) + json_object_set(Root, "autocomments", jsonAutoComments); + + json_decref(jsonComments); + json_decref(jsonAutoComments); } -void commentcacheload(JSON root) +void CommentCacheLoad(JSON Root) { - CriticalSectionLocker locker(LockComments); + EXCLUSIVE_ACQUIRE(LockBookmarks); + + // Inline lambda to parse each JSON entry + auto AddBookmarks = [](const JSON Object, bool Manual) + { + size_t i; + JSON value; + + json_array_foreach(Object, i, value) + { + COMMENTSINFO commentInfo; + + // Module + const char* mod = json_string_value(json_object_get(value, "module")); + + if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE) + strcpy_s(commentInfo.mod, mod); + else + commentInfo.mod[0] = '\0'; + + // Address/Manual + commentInfo.addr = (uint)json_hex_value(json_object_get(value, "address")); + commentInfo.manual = Manual; + + // String value + const char* text = json_string_value(json_object_get(value, "text")); + + if(text) + strcpy_s(commentInfo.text, text); + else + { + // Skip blank comments + continue; + } + + const uint key = ModHashFromName(commentInfo.mod) + commentInfo.addr; + comments.insert(std::make_pair(key, commentInfo)); + } + }; + + // Remove existing entries comments.clear(); - const JSON jsoncomments = json_object_get(root, "comments"); - if(jsoncomments) - { - size_t i; - JSON value; - json_array_foreach(jsoncomments, i, value) - { - COMMENTSINFO curComment; - const char* mod = json_string_value(json_object_get(value, "module")); - if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE) - strcpy_s(curComment.mod, mod); - else - *curComment.mod = '\0'; - curComment.addr = (uint)json_hex_value(json_object_get(value, "address")); - curComment.manual = true; - const char* text = json_string_value(json_object_get(value, "text")); - if(text) - strcpy_s(curComment.text, text); - else - continue; //skip - const uint key = ModHashFromName(curComment.mod) + curComment.addr; - comments.insert(std::make_pair(key, curComment)); - } - } - JSON jsonautocomments = json_object_get(root, "autocomments"); - if(jsonautocomments) - { - size_t i; - JSON value; - json_array_foreach(jsonautocomments, i, value) - { - COMMENTSINFO curComment; - const char* mod = json_string_value(json_object_get(value, "module")); - if(mod && *mod && strlen(mod) < MAX_MODULE_SIZE) - strcpy_s(curComment.mod, mod); - else - *curComment.mod = '\0'; - curComment.addr = (uint)json_hex_value(json_object_get(value, "address")); - curComment.manual = false; - const char* text = json_string_value(json_object_get(value, "text")); - if(text) - strcpy_s(curComment.text, text); - else - continue; //skip - const uint key = ModHashFromName(curComment.mod) + curComment.addr; - comments.insert(std::make_pair(key, curComment)); - } - } + + const JSON jsonComments = json_object_get(Root, "comments"); + const JSON jsonAutoComments = json_object_get(Root, "autocomments"); + + // Load user-set comments + if(jsonComments) + AddBookmarks(jsonComments, true); + + // Load auto-set comments + if(jsonAutoComments) + AddBookmarks(jsonAutoComments, false); } -bool commentenum(COMMENTSINFO* commentlist, size_t* cbsize) +bool CommentEnum(COMMENTSINFO* List, size_t* Size) { + // CHECK: Command function if(!DbgIsDebugging()) return false; - if(!commentlist && !cbsize) + + // At least 1 parameter must be supplied + if(!List && !Size) return false; - CriticalSectionLocker locker(LockComments); - if(!commentlist && cbsize) + + SHARED_ACQUIRE(LockComments); + + // Check if the user requested size only + if(Size) { - *cbsize = comments.size() * sizeof(COMMENTSINFO); - return true; + *Size = comments.size() * sizeof(COMMENTSINFO); + + if(!List) + return true; } - int j = 0; - for(CommentsInfo::iterator i = comments.begin(); i != comments.end(); ++i, j++) + + // Populate the returned array + for(auto & itr : comments) { - commentlist[j] = i->second; - commentlist[j].addr += ModBaseFromName(commentlist[j].mod); + *List = itr.second; + List->addr += ModBaseFromName(List->mod); + + List++; } + return true; } -void commentclear() +void CommentClear() { - CriticalSectionLocker locker(LockComments); - CommentsInfo().swap(comments); + EXCLUSIVE_ACQUIRE(LockComments); + comments.clear(); } \ No newline at end of file diff --git a/x64_dbg_dbg/comment.h b/x64_dbg_dbg/comment.h index 3f25f6ef..993a63fa 100644 --- a/x64_dbg_dbg/comment.h +++ b/x64_dbg_dbg/comment.h @@ -1,5 +1,4 @@ -#ifndef _COMMENT_H -#define _COMMENT_H +#pragma once #include "_global.h" @@ -11,13 +10,11 @@ struct COMMENTSINFO bool manual; }; -bool commentset(uint addr, const char* text, bool manual); -bool commentget(uint addr, char* text); -bool commentdel(uint addr); -void commentdelrange(uint start, uint end); -void commentcachesave(JSON root); -void commentcacheload(JSON root); -bool commentenum(COMMENTSINFO* commentlist, size_t* cbsize); -void commentclear(); - -#endif //_COMMENT_H \ No newline at end of file +bool CommentSet(uint Address, const char* Text, bool Manual); +bool CommentGet(uint Address, char* Text); +bool CommentDelete(uint Address); +void CommentDelRange(uint Start, uint End); +void CommentCacheSave(JSON Root); +void CommentCacheLoad(JSON Root); +bool CommentEnum(COMMENTSINFO* List, size_t* Size); +void CommentClear(); \ No newline at end of file diff --git a/x64_dbg_dbg/debugger_commands.cpp b/x64_dbg_dbg/debugger_commands.cpp index c3d23861..e300c590 100644 --- a/x64_dbg_dbg/debugger_commands.cpp +++ b/x64_dbg_dbg/debugger_commands.cpp @@ -811,7 +811,7 @@ CMDRESULT cbDebugBenchmark(int argc, char* argv[]) char comment[MAX_COMMENT_SIZE] = ""; for(uint i = addr; i < addr + 100000; i++) { - commentset(i, "test", false); + CommentSet(i, "test", false); labelset(i, "test", false); BookmarkSet(i, false); FunctionAdd(i, i, false); diff --git a/x64_dbg_dbg/instruction.cpp b/x64_dbg_dbg/instruction.cpp index a48047b5..d29154c5 100644 --- a/x64_dbg_dbg/instruction.cpp +++ b/x64_dbg_dbg/instruction.cpp @@ -294,7 +294,7 @@ CMDRESULT cbInstrCmt(int argc, char* argv[]) uint addr = 0; if(!valfromstring(argv[1], &addr, false)) return STATUS_ERROR; - if(!commentset(addr, argv[2], true)) + if(!CommentSet(addr, argv[2], true)) { dputs("error setting comment"); return STATUS_ERROR; @@ -312,7 +312,7 @@ CMDRESULT cbInstrCmtdel(int argc, char* argv[]) uint addr = 0; if(!valfromstring(argv[1], &addr, false)) return STATUS_ERROR; - if(!commentdel(addr)) + if(!CommentDelete(addr)) { dputs("error deleting comment"); return STATUS_ERROR; @@ -1270,14 +1270,14 @@ CMDRESULT cbInstrCommentList(int argc, char* argv[]) GuiReferenceAddColumn(0, "Comment"); GuiReferenceReloadData(); size_t cbsize; - commentenum(0, &cbsize); + CommentEnum(0, &cbsize); if(!cbsize) { dputs("no comments"); return STATUS_CONTINUE; } Memory comments(cbsize, "cbInstrCommentList:comments"); - commentenum(comments, 0); + CommentEnum(comments, 0); int count = (int)(cbsize / sizeof(COMMENTSINFO)); for(int i = 0; i < count; i++) { @@ -1400,7 +1400,7 @@ CMDRESULT cbInstrFunctionList(int argc, char* argv[]) else { char comment[MAX_COMMENT_SIZE] = ""; - if(commentget(functions[i].start, comment)) + if(CommentGet(functions[i].start, comment)) GuiReferenceSetCellContent(i, 3, comment); } } @@ -1446,7 +1446,7 @@ CMDRESULT cbInstrLoopList(int argc, char* argv[]) else { char comment[MAX_COMMENT_SIZE] = ""; - if(commentget(loops[i].start, comment)) + if(CommentGet(loops[i].start, comment)) GuiReferenceSetCellContent(i, 3, comment); } }