Skip to content

Commit

Permalink
PPCSymbolDB: Add alignment detection heuristic
Browse files Browse the repository at this point in the history
Update parse_entry_of in accordance to the sscanf change
  • Loading branch information
sepalani committed Nov 24, 2024
1 parent 6972ebd commit f685e28
Showing 1 changed file with 49 additions and 51 deletions.
100 changes: 49 additions & 51 deletions Source/Core/Core/PowerPC/PPCSymbolDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "Common/IOFile.h"
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
#include "Common/Unreachable.h"
#include "Core/Core.h"
#include "Core/Debugger/DebugInterface.h"
#include "Core/PowerPC/MMU.h"
Expand Down Expand Up @@ -307,7 +308,7 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
continue;
column_count = 2;

// Three columns format:
// Three columns format (with optional alignment):
// Starting Virtual
// address Size address
// -----------------------
Expand All @@ -316,83 +317,80 @@ bool PPCSymbolDB::LoadMap(const Core::CPUThreadGuard& guard, const std::string&
else
iss.str("");

// Four columns format:
// Four columns format (with optional alignment):
// Starting Virtual File
// address Size address offset
// ---------------------------------
if (iss && iss >> word && word.length() == 8 && is_hex_str(word))
column_count = 4;
}

u32 address, vaddress, size, offset, alignment;
char name[512];
static constexpr char ENTRY_OF_STRING[] = "(entry of ";
u32 address;
u32 vaddress;
u32 size = 0;
u32 offset = 0;
u32 alignment = 0;
char name[512]{};
static constexpr char ENTRY_OF_STRING[] = " (entry of ";
static constexpr std::string_view ENTRY_OF_VIEW(ENTRY_OF_STRING);
auto parse_entry_of = [](const char* line, char* name) {
const char* s = strstr(line, ENTRY_OF_STRING);
if (s)
auto parse_entry_of = [](char* name) {
if (char* s1 = strstr(name, ENTRY_OF_STRING); s1 != nullptr)
{
char container[512];
sscanf(s + ENTRY_OF_VIEW.size(), "%511s", container);
char* s2 = strchr(container, ')');
char* ptr = s1 + ENTRY_OF_VIEW.size();
sscanf(ptr, "%511s", container);
// Skip sections, those start with a dot, e.g. (entry of .text)
if (s2 && container[0] != '.')
if (char* s2 = strchr(container, ')'); s2 != nullptr && *container != '.')
{
s2[0] = '\0';
ptr += strlen(container);
// Preserve data after the entry part, usually it contains object names
strcpy(s1, ptr);
*s2 = '\0';
strcat(container, "::");
strcat(container, name);
strcpy(name, container);
}
}
};
if (column_count == 4)
auto was_alignment = [](const char* name) {
return *name == ' ' || (*name >= '0' && *name <= '9');
};
auto parse_alignment = [](char* name, u32* alignment) {
const std::string buffer(StripWhitespace(name));
return sscanf(buffer.c_str(), "%i %511[^\r\n]", alignment, name);
};
switch (column_count)
{
case 4:
// sometimes there is no alignment value, and sometimes it is because it is an entry of
// something else
if (length > 37 && line[37] == ' ')
{
alignment = 0;
sscanf(line, "%08x %08x %08x %08x %511s", &address, &size, &vaddress, &offset, name);
parse_entry_of(line, name);
}
else
{
sscanf(line, "%08x %08x %08x %08x %i %511s", &address, &size, &vaddress, &offset,
&alignment, name);
}
}
else if (column_count == 3)
{
sscanf(line, "%08x %08x %08x %08x %511[^\r\n]", &address, &size, &vaddress, &offset, name);
if (was_alignment(name))
parse_alignment(name, &alignment);
// The `else` statement was omitted to handle symbol already saved in Dolphin symbol map
// since it doesn't omit the alignment on save for such case.
parse_entry_of(name);
break;
case 3:
// some entries in the table have a function name followed by " (entry of " followed by a
// container name, followed by ")"
// instead of a space followed by a number followed by a space followed by a name
if (length > 27 && line[27] != ' ' && strstr(line, ENTRY_OF_STRING))
{
alignment = 0;
sscanf(line, "%08x %08x %08x %511s", &address, &size, &vaddress, name);
parse_entry_of(line, name);
}
else
{
sscanf(line, "%08x %08x %08x %i %511s", &address, &size, &vaddress, &alignment, name);
}
}
else if (column_count == 2)
{
sscanf(line, "%08x %511s", &address, name);
sscanf(line, "%08x %08x %08x %511[^\r\n]", &address, &size, &vaddress, name);
if (was_alignment(name))
parse_alignment(name, &alignment);
// The `else` statement was omitted to handle symbol already saved in Dolphin symbol map
// since it doesn't omit the alignment on save for such case.
parse_entry_of(name);
break;
case 2:
sscanf(line, "%08x %511[^\r\n]", &address, name);
vaddress = address;
size = 0;
}
else
{
break;
default:
// Should never happen
Common::Unreachable();
break;
}
const char* namepos = strstr(line, name);
if (namepos != nullptr) // would be odd if not :P
strcpy(name, namepos);
name[strlen(name) - 1] = 0;
if (name[strlen(name) - 1] == '\r')
name[strlen(name) - 1] = 0;

// Check if this is a valid entry.
if (strlen(name) > 0)
Expand Down

0 comments on commit f685e28

Please sign in to comment.