diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index ef3f1ec239..c7af17f9db 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -16,6 +16,7 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include + #include "Common/Log.h" #include "Common/Serialize/Serializer.h" #include "Common/Serialize/SerializeFuncs.h" @@ -23,13 +24,14 @@ #include "Core/Debugger/Breakpoints.h" #include "Core/Debugger/MemBlockInfo.h" #include "Core/MIPS/MIPS.h" +#include "Common/StringUtils.h" class MemSlabMap { public: MemSlabMap(); ~MemSlabMap(); - bool Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, bool allocated, const std::string &tag); + bool Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, bool allocated, const char *tag); bool Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::vector &results); void Reset(); void DoState(PointerWrap &p); @@ -41,7 +43,7 @@ private: uint64_t ticks = 0; uint32_t pc = 0; bool allocated = false; - std::string tag; + char tag[32]{}; Slab *prev = nullptr; Slab *next = nullptr; @@ -72,8 +74,9 @@ struct PendingNotifyMem { uint32_t size; uint64_t ticks; uint32_t pc; - std::string tag; + char tag[32]; }; +static_assert(sizeof(PendingNotifyMem) == 64, "..."); static constexpr size_t MAX_PENDING_NOTIFIES = 512; static MemSlabMap allocMap; @@ -91,7 +94,7 @@ MemSlabMap::~MemSlabMap() { Clear(); } -bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, bool allocated, const std::string &tag) { +bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, bool allocated, const char *tag) { uint32_t end = addr + size; Slab *slab = FindSlab(addr); Slab *firstMatch = nullptr; @@ -108,8 +111,8 @@ bool MemSlabMap::Mark(uint32_t addr, uint32_t size, uint64_t ticks, uint32_t pc, slab->ticks = ticks; slab->pc = pc; } - if (!tag.empty()) - slab->tag = tag; + if (tag) + truncate_cpy(slab->tag, tag); // Move on to the next one. if (firstMatch == nullptr) @@ -130,7 +133,7 @@ bool MemSlabMap::Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::ve Slab *slab = FindSlab(addr); bool found = false; while (slab != nullptr && slab->start < end) { - if (slab->pc != 0 || !slab->tag.empty()) { + if (slab->pc != 0 || strlen(slab->tag)) { results.push_back({ flags, slab->start, slab->end - slab->start, slab->ticks, slab->pc, slab->tag, slab->allocated }); found = true; } @@ -242,7 +245,7 @@ MemSlabMap::Slab *MemSlabMap::Split(Slab *slab, uint32_t size) { next->ticks = slab->ticks; next->pc = slab->pc; next->allocated = slab->allocated; - next->tag = slab->tag; + truncate_cpy(next->tag, slab->tag); next->prev = slab; next->next = slab->next; @@ -330,14 +333,14 @@ void FlushPendingMemInfo() { allocMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); } else if (info.flags & MemBlockFlags::FREE) { // Maintain the previous allocation tag for debugging. - allocMap.Mark(info.start, info.size, info.ticks, 0, false, ""); - suballocMap.Mark(info.start, info.size, info.ticks, 0, false, ""); + allocMap.Mark(info.start, info.size, info.ticks, 0, false, nullptr); + suballocMap.Mark(info.start, info.size, info.ticks, 0, false, nullptr); } if (info.flags & MemBlockFlags::SUB_ALLOC) { suballocMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); } else if (info.flags & MemBlockFlags::SUB_FREE) { // Maintain the previous allocation tag for debugging. - suballocMap.Mark(info.start, info.size, info.ticks, 0, false, ""); + suballocMap.Mark(info.start, info.size, info.ticks, 0, false, nullptr); } if (info.flags & MemBlockFlags::TEXTURE) { textureMap.Mark(info.start, info.size, info.ticks, info.pc, true, info.tag); @@ -349,11 +352,7 @@ void FlushPendingMemInfo() { pendingNotifies.clear(); } -void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std::string &tag) { - NotifyMemInfoPC(flags, start, size, currentMIPS->pc, tag); -} - -void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const std::string &tag) { +void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const char *tagStr, size_t strLength) { if (size == 0) { return; } @@ -363,7 +362,12 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ PendingNotifyMem info{ flags, start, size }; info.ticks = CoreTiming::GetTicks(); info.pc = pc; - info.tag = tag; + size_t copyLength = strLength; + if (copyLength >= sizeof(info.tag)) { + copyLength = sizeof(info.tag) - 1; + } + memcpy(info.tag, tagStr, copyLength); + info.tag[copyLength] = 0; bool needFlush = false; { @@ -377,12 +381,16 @@ void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_ } if (flags & MemBlockFlags::WRITE) { - CBreakPoints::ExecMemCheck(start, true, size, pc, tag.c_str()); + CBreakPoints::ExecMemCheck(start, true, size, pc, tagStr); } else if (flags & MemBlockFlags::READ) { - CBreakPoints::ExecMemCheck(start, false, size, pc, tag.c_str()); + CBreakPoints::ExecMemCheck(start, false, size, pc, tagStr); } } +void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const char *str, size_t strLength) { + NotifyMemInfoPC(flags, start, size, currentMIPS->pc, str, strLength); +} + std::vector FindMemInfo(uint32_t start, uint32_t size) { FlushPendingMemInfo(); start &= ~0xC0000000; diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index fa851ffdfe..066d33113f 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -46,8 +46,18 @@ struct MemBlockInfo { bool allocated; }; -void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std::string &tag); -void NotifyMemInfoPC(MemBlockFlags flags, uint32_t start, uint32_t size, uint32_t pc, const std::string &tag); +void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const char *str, size_t strLength); + +// This lets us avoid calling strlen on string constants, instead the string length (including null) +// is computed at compile time. +template +inline void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const char(&str)[count]) { + NotifyMemInfo(flags, start, size, str, count); +} + +inline void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, const std::string &str) { + NotifyMemInfo(flags, start, size, str.c_str(), str.size() + 1); +} std::vector FindMemInfo(uint32_t start, uint32_t size); std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size); diff --git a/Core/MemMap.cpp b/Core/MemMap.cpp index f69a46db6e..521c241e3c 100644 --- a/Core/MemMap.cpp +++ b/Core/MemMap.cpp @@ -459,7 +459,7 @@ void Write_Opcode_JIT(const u32 _Address, const Opcode& _Value) Memory::WriteUnchecked_U32(_Value.encoding, _Address); } -void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength, const std::string &tag) { +void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength, const char *tag) { if (IsValidRange(_Address, _iLength)) { uint8_t *ptr = GetPointerUnchecked(_Address); memset(ptr, _iValue, _iLength); @@ -468,7 +468,7 @@ void Memset(const u32 _Address, const u8 _iValue, const u32 _iLength, const std: Write_U8(_iValue, (u32)(_Address + i)); } - NotifyMemInfo(MemBlockFlags::WRITE, _Address, _iLength, tag); + NotifyMemInfo(MemBlockFlags::WRITE, _Address, _iLength, tag, strlen(tag)); } } // namespace diff --git a/Core/MemMapHelpers.h b/Core/MemMapHelpers.h index 0983abdf9b..f67ab9aa86 100644 --- a/Core/MemMapHelpers.h +++ b/Core/MemMapHelpers.h @@ -17,6 +17,8 @@ #pragma once +#include + #include "Common/CommonTypes.h" #include "Core/Debugger/MemBlockInfo.h" #include "Core/MemMap.h" @@ -28,31 +30,34 @@ extern MIPSState *currentMIPS; namespace Memory { -inline void Memcpy(const u32 to_address, const void *from_data, const u32 len, const std::string &tag = "Memcpy") { +inline void Memcpy(const u32 to_address, const void *from_data, const u32 len, const char *tag = "Memcpy") { u8 *to = GetPointer(to_address); if (to) { memcpy(to, from_data, len); - NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag); + size_t tagLen = strlen(tag); + NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag, tagLen); } // if not, GetPointer will log. } -inline void Memcpy(void *to_data, const u32 from_address, const u32 len, const std::string &tag = "Memcpy") { +inline void Memcpy(void *to_data, const u32 from_address, const u32 len, const char *tag = "Memcpy") { const u8 *from = GetPointer(from_address); if (from) { memcpy(to_data, from, len); - NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag); + size_t tagLen = strlen(tag); + NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag, tagLen); } // if not, GetPointer will log. } -inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len, const std::string &tag = "Memcpy") { +inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len, const char *tag = "Memcpy") { Memcpy(GetPointer(to_address), from_address, len); - NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag); - NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag); + size_t tagLen = strlen(tag); + NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag, tagLen); + NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag, tagLen); } -void Memset(const u32 _Address, const u8 _Data, const u32 _iLength, const std::string &tag = "Memset"); +void Memset(const u32 _Address, const u8 _Data, const u32 _iLength, const char *tag = "Memset"); template void ReadStruct(u32 address, T *ptr)