diff --git a/Common/StringUtils.cpp b/Common/StringUtils.cpp index c4b88c4c3a..f88f6194ab 100644 --- a/Common/StringUtils.cpp +++ b/Common/StringUtils.cpp @@ -44,15 +44,16 @@ #include "Common/Buffer.h" #include "Common/StringUtils.h" -void truncate_cpy(char *dest, size_t destSize, const char *src) { +size_t truncate_cpy(char *dest, size_t destSize, const char *src) { size_t len = strlen(src); if (len >= destSize - 1) { memcpy(dest, src, destSize - 1); - dest[destSize - 1] = '\0'; + len = destSize - 1; } else { memcpy(dest, src, len); - dest[len] = '\0'; } + dest[len] = '\0'; + return len; } const char* safe_string(const char* s) { diff --git a/Common/StringUtils.h b/Common/StringUtils.h index 989fe8b9fd..16bfaa18e5 100644 --- a/Common/StringUtils.h +++ b/Common/StringUtils.h @@ -78,10 +78,10 @@ std::string ReplaceAll(std::string input, const std::string& src, const std::str void SkipSpace(const char **ptr); -void truncate_cpy(char *dest, size_t destSize, const char *src); +size_t truncate_cpy(char *dest, size_t destSize, const char *src); template -inline void truncate_cpy(char(&out)[Count], const char *src) { - truncate_cpy(out, Count, src); +inline size_t truncate_cpy(char(&out)[Count], const char *src) { + return truncate_cpy(out, Count, src); } const char* safe_string(const char* s); diff --git a/Core/Debugger/MemBlockInfo.cpp b/Core/Debugger/MemBlockInfo.cpp index f0be93ea60..e38b6861b7 100644 --- a/Core/Debugger/MemBlockInfo.cpp +++ b/Core/Debugger/MemBlockInfo.cpp @@ -37,7 +37,8 @@ public: 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); - bool FastFindWriteTag(MemBlockFlags flags, uint32_t addr, uint32_t size, std::string &result); + // Note that the returned pointer gets invalidated as soon as Mark is called. + const char *FastFindWriteTag(MemBlockFlags flags, uint32_t addr, uint32_t size); void Reset(); void DoState(PointerWrap &p); @@ -151,17 +152,16 @@ bool MemSlabMap::Find(MemBlockFlags flags, uint32_t addr, uint32_t size, std::ve return found; } -bool MemSlabMap::FastFindWriteTag(MemBlockFlags flags, uint32_t addr, uint32_t size, std::string &result) { +const char *MemSlabMap::FastFindWriteTag(MemBlockFlags flags, uint32_t addr, uint32_t size) { uint32_t end = addr + size; Slab *slab = FindSlab(addr); while (slab != nullptr && slab->start < end) { if (slab->pc != 0 || slab->tag[0] != '\0') { - result = slab->tag; - return true; + return slab->tag; } slab = slab->next; } - return false; + return nullptr; } void MemSlabMap::Reset() { @@ -485,7 +485,7 @@ std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, return results; } -static std::string FindWriteTagByFlag(MemBlockFlags flags, uint32_t start, uint32_t size) { +static const char *FindWriteTagByFlag(MemBlockFlags flags, uint32_t start, uint32_t size) { start &= ~0xC0000000; if (pendingNotifyMinAddr1 < start + size && pendingNotifyMaxAddr1 >= start) @@ -493,37 +493,51 @@ static std::string FindWriteTagByFlag(MemBlockFlags flags, uint32_t start, uint3 if (pendingNotifyMinAddr2 < start + size && pendingNotifyMaxAddr2 >= start) FlushPendingMemInfo(); - std::string tag; if (flags & MemBlockFlags::ALLOC) { - if (allocMap.FastFindWriteTag(MemBlockFlags::ALLOC, start, size, tag)) + const char *tag = allocMap.FastFindWriteTag(MemBlockFlags::ALLOC, start, size); + if (tag) return tag; } if (flags & MemBlockFlags::SUB_ALLOC) { - if (suballocMap.FastFindWriteTag(MemBlockFlags::SUB_ALLOC, start, size, tag)) + const char *tag = suballocMap.FastFindWriteTag(MemBlockFlags::SUB_ALLOC, start, size); + if (tag) return tag; } if (flags & MemBlockFlags::WRITE) { - if (writeMap.FastFindWriteTag(MemBlockFlags::WRITE, start, size, tag)) + const char *tag = writeMap.FastFindWriteTag(MemBlockFlags::WRITE, start, size); + if (tag) return tag; } if (flags & MemBlockFlags::TEXTURE) { - if (textureMap.FastFindWriteTag(MemBlockFlags::TEXTURE, start, size, tag)) + const char *tag = textureMap.FastFindWriteTag(MemBlockFlags::TEXTURE, start, size); + if (tag) return tag; } - return ""; + return nullptr; } -std::string GetMemWriteTagAt(uint32_t start, uint32_t size) { - std::string tag = FindWriteTagByFlag(MemBlockFlags::WRITE, start, size); - if (!tag.empty() && tag != "MemInit") - return tag; - +std::string GetMemWriteTagAt(const char *prefix, uint32_t start, uint32_t size) { + const char *tag = FindWriteTagByFlag(MemBlockFlags::WRITE, start, size); + if (tag && strcmp(tag, "MemInit") != 0) + return std::string(prefix) + tag; // Fall back to alloc and texture, especially for VRAM. We prefer write above. tag = FindWriteTagByFlag(MemBlockFlags::ALLOC | MemBlockFlags::TEXTURE, start, size); - if (!tag.empty()) - return tag; + if (tag) + return std::string(prefix) + tag; + return StringFromFormat("%s%08x_size_%08x", prefix, start, size); +} - return StringFromFormat("%08x_size_%08x", start, size); +size_t FormatMemWriteTagAt(char *buf, size_t sz, const char *prefix, uint32_t start, uint32_t size) { + const char *tag = FindWriteTagByFlag(MemBlockFlags::WRITE, start, size); + if (tag && strcmp(tag, "MemInit") != 0) { + return snprintf(buf, sz, "%s%s", prefix, tag); + } + // Fall back to alloc and texture, especially for VRAM. We prefer write above. + tag = FindWriteTagByFlag(MemBlockFlags::ALLOC | MemBlockFlags::TEXTURE, start, size); + if (tag) { + return snprintf(buf, sz, "%s%s", prefix, tag); + } + return snprintf(buf, sz, "%s%08x_size_%08x", prefix, start, size); } void MemBlockInfoInit() { diff --git a/Core/Debugger/MemBlockInfo.h b/Core/Debugger/MemBlockInfo.h index 50e3bfae53..839249f3a2 100644 --- a/Core/Debugger/MemBlockInfo.h +++ b/Core/Debugger/MemBlockInfo.h @@ -68,7 +68,9 @@ inline void NotifyMemInfo(MemBlockFlags flags, uint32_t start, uint32_t size, co std::vector FindMemInfo(uint32_t start, uint32_t size); std::vector FindMemInfoByFlag(MemBlockFlags flags, uint32_t start, uint32_t size); -std::string GetMemWriteTagAt(uint32_t start, uint32_t size); +std::string GetMemWriteTagAt(const char *prefix, uint32_t start, uint32_t size); +// Same as above but allocation-free. +size_t FormatMemWriteTagAt(char *buf, size_t sz, const char *prefix, uint32_t start, uint32_t size); void MemBlockInfoInit(); void MemBlockInfoShutdown(); diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index 57603ccf2c..462bad0a7e 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -159,7 +159,7 @@ static int Replace_memcpy() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - const std::string tag = "ReplaceMemcpy/" + GetMemWriteTagAt(srcPtr, bytes); + const std::string tag = GetMemWriteTagAt("ReplaceMemcpy/", srcPtr, bytes); NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); @@ -211,7 +211,7 @@ static int Replace_memcpy_jak() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - const std::string tag = "ReplaceMemcpy/" + GetMemWriteTagAt(srcPtr, bytes); + const std::string tag = GetMemWriteTagAt("ReplaceMemcpy/", srcPtr, bytes); NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); @@ -249,7 +249,7 @@ static int Replace_memcpy16() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - const std::string tag = "ReplaceMemcpy16/" + GetMemWriteTagAt(srcPtr, bytes); + const std::string tag = GetMemWriteTagAt("ReplaceMemcpy16/", srcPtr, bytes); NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); } @@ -290,7 +290,7 @@ static int Replace_memcpy_swizzled() { RETURN(0); if (MemBlockInfoDetailed(pitch * h)) { - const std::string tag = "ReplaceMemcpySwizzle/" + GetMemWriteTagAt(srcPtr, pitch * h); + const std::string tag = GetMemWriteTagAt("ReplaceMemcpySwizzle/", srcPtr, pitch * h); NotifyMemInfo(MemBlockFlags::READ, srcPtr, pitch * h, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, destPtr, pitch * h, tag.c_str(), tag.size()); } @@ -321,7 +321,7 @@ static int Replace_memmove() { RETURN(destPtr); if (MemBlockInfoDetailed(bytes)) { - const std::string tag = "ReplaceMemmove/" + GetMemWriteTagAt(srcPtr, bytes); + const std::string tag = GetMemWriteTagAt("ReplaceMemmove/", srcPtr, bytes); NotifyMemInfo(MemBlockFlags::READ, srcPtr, bytes, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, destPtr, bytes, tag.c_str(), tag.size()); } diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp index 6ee643fe5a..b22c439bc1 100644 --- a/Core/HLE/sceAtrac.cpp +++ b/Core/HLE/sceAtrac.cpp @@ -1268,7 +1268,7 @@ u32 _AtracDecodeData(int atracID, u8 *outbuf, u32 outbufPtr, u32 *SamplesNum, u3 if (outbufPtr != 0) { u32 outBytes = numSamples * atrac->outputChannels_ * sizeof(s16); if (packetAddr != 0 && MemBlockInfoDetailed()) { - const std::string tag = "AtracDecode/" + GetMemWriteTagAt(packetAddr, packetSize); + const std::string tag = GetMemWriteTagAt("AtracDecode/", packetAddr, packetSize); NotifyMemInfo(MemBlockFlags::READ, packetAddr, packetSize, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, outbufPtr, outBytes, tag.c_str(), tag.size()); } else { diff --git a/Core/HLE/sceDeflt.cpp b/Core/HLE/sceDeflt.cpp index d5580dcc40..985b89d543 100644 --- a/Core/HLE/sceDeflt.cpp +++ b/Core/HLE/sceDeflt.cpp @@ -59,7 +59,7 @@ static int CommonDecompress(int windowBits, u32 OutBuffer, int OutBufferLength, } if (MemBlockInfoDetailed(stream.total_in, stream.total_out)) { - const std::string tag = "sceDeflt/" + GetMemWriteTagAt(InBuffer, stream.total_in); + const std::string tag = GetMemWriteTagAt("sceDeflt/", InBuffer, stream.total_in); NotifyMemInfo(MemBlockFlags::READ, InBuffer, stream.total_in, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, OutBuffer, stream.total_out, tag.c_str(), tag.size()); } diff --git a/Core/HLE/sceDmac.cpp b/Core/HLE/sceDmac.cpp index 86c8e60a1e..5fba8f9b94 100644 --- a/Core/HLE/sceDmac.cpp +++ b/Core/HLE/sceDmac.cpp @@ -52,7 +52,7 @@ static int __DmacMemcpy(u32 dst, u32 src, u32 size) { if (!skip) { currentMIPS->InvalidateICache(src, size); if (MemBlockInfoDetailed(size)) { - const std::string tag = "DmacMemcpy/" + GetMemWriteTagAt(src, size); + const std::string tag = GetMemWriteTagAt("DmacMemcpy/", src, size); Memory::Memcpy(dst, src, size, tag.c_str(), tag.size()); } else { Memory::Memcpy(dst, src, size, "DmacMemcpy"); diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index a86deee9fe..cffedaeb46 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -656,7 +656,7 @@ static u32 sceKernelMemcpy(u32 dst, u32 src, u32 size) } if (MemBlockInfoDetailed(size)) { - const std::string tag = "KernelMemcpy/" + GetMemWriteTagAt(src, size); + const std::string tag = GetMemWriteTagAt("KernelMemcpy/", src, size); NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size()); } @@ -691,7 +691,7 @@ static u32 sysclib_memcpy(u32 dst, u32 src, u32 size) { memcpy(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size); } if (MemBlockInfoDetailed(size)) { - const std::string tag = "KernelMemcpy/" + GetMemWriteTagAt(src, size); + const std::string tag = GetMemWriteTagAt("KernelMemcpy/", src, size); NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size()); } @@ -794,7 +794,7 @@ static u32 sysclib_memmove(u32 dst, u32 src, u32 size) { memmove(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size); } if (MemBlockInfoDetailed(size)) { - const std::string tag = "KernelMemmove/" + GetMemWriteTagAt(src, size); + const std::string tag = GetMemWriteTagAt("KernelMemmove/", src, size); NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, dst, size, tag.c_str(), tag.size()); } diff --git a/Core/MemMapHelpers.h b/Core/MemMapHelpers.h index 848bfa73b6..e623d9e768 100644 --- a/Core/MemMapHelpers.h +++ b/Core/MemMapHelpers.h @@ -20,6 +20,7 @@ #include #include "Common/CommonTypes.h" +#include "Common/StringUtils.h" #include "Core/Debugger/MemBlockInfo.h" #include "Core/MemMap.h" #include "Core/MIPS/MIPS.h" @@ -70,9 +71,9 @@ inline void Memcpy(const u32 to_address, const u32 from_address, const u32 len, if (MemBlockInfoDetailed(len)) { char tagData[128]; if (!tag) { - const std::string srcTag = GetMemWriteTagAt(from_address, len); + const std::string srcTag = GetMemWriteTagAt("Memcpy/", from_address, len); tag = tagData; - tagLen = snprintf(tagData, sizeof(tagData), "Memcpy/%s", srcTag.c_str()); + tagLen = truncate_cpy(tagData, srcTag.c_str()); } NotifyMemInfo(MemBlockFlags::READ, from_address, len, tag, tagLen); NotifyMemInfo(MemBlockFlags::WRITE, to_address, len, tag, tagLen); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 22b323c713..60383b6c86 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -2864,9 +2864,10 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { if (MemBlockInfoDetailed(numBytes, numBytes)) { const uint32_t src = srcBasePtr + (srcY * srcStride + srcX) * bpp; const uint32_t dst = dstBasePtr + (dstY * dstStride + dstX) * bpp; - const std::string tag = "GPUBlockTransfer/" + GetMemWriteTagAt(src, srcSize); - NotifyMemInfo(MemBlockFlags::READ, src, srcSize, tag.c_str(), tag.size()); - NotifyMemInfo(MemBlockFlags::WRITE, dst, dstSize, tag.c_str(), tag.size()); + char tag[128]; + size_t tagSize = FormatMemWriteTagAt(tag, sizeof(tag), "GPUBlockTransfer/", src, srcSize); + NotifyMemInfo(MemBlockFlags::READ, src, srcSize, tag, tagSize); + NotifyMemInfo(MemBlockFlags::WRITE, dst, dstSize, tag, tagSize); } // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. @@ -2881,7 +2882,7 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { // Since they're identical we don't need to copy. if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) { if (MemBlockInfoDetailed(size)) { - const std::string tag = "GPUMemcpy/" + GetMemWriteTagAt(src, size); + const std::string tag = GetMemWriteTagAt("GPUMemcpy/", src, size); Memory::Memcpy(dest, src, size, tag.c_str(), tag.size()); } else { Memory::Memcpy(dest, src, size, "GPUMemcpy"); @@ -2893,7 +2894,7 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { } if (MemBlockInfoDetailed(size)) { - const std::string tag = "GPUMemcpy/" + GetMemWriteTagAt(src, size); + const std::string tag = GetMemWriteTagAt("GPUMemcpy/", src, size); NotifyMemInfo(MemBlockFlags::READ, src, size, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, dest, size, tag.c_str(), tag.size()); } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index dd4b71b166..8c26eac9b1 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -813,7 +813,7 @@ void SoftGPU::Execute_BlockTransferStart(u32 op, u32 diff) { } if (MemBlockInfoDetailed(srcSize, dstSize)) { - const std::string tag = "GPUBlockTransfer/" + GetMemWriteTagAt(src, srcSize); + const std::string tag = GetMemWriteTagAt("GPUBlockTransfer/", src, srcSize); NotifyMemInfo(MemBlockFlags::READ, src, srcSize, tag.c_str(), tag.size()); NotifyMemInfo(MemBlockFlags::WRITE, dst, dstSize, tag.c_str(), tag.size()); }