Merge pull request #90 from gizmo98/patch-2
[libretro-ppsspp.git] / Core / Debugger / SymbolMap.cpp
blobae8079efab3e9a7db23e44d658c60789d6f87be9
1 // Copyright (c) 2012- PPSSPP Project.
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 // GNU General Public License 2.0 for more details.
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
18 // These functions tends to be slow in debug mode.
19 // Comment this out if debugging the symbol map itself.
20 #if defined(_MSC_VER) && defined(_DEBUG)
21 #pragma optimize("gty", on)
22 #endif
24 #if defined(_WIN32) && !defined(__MINGW32__)
25 #define _WIN32_NO_MINGW
26 #define _WIN32_USING_UNICODE
27 #endif
29 #ifdef _WIN32_NO_MINGW
30 #include "Common/CommonWindows.h"
31 #include <WindowsX.h>
32 #else
33 #include <unistd.h>
34 #endif
36 #include <algorithm>
38 #include "util/text/utf8.h"
39 #include "zlib.h"
40 #include "Common/CommonTypes.h"
41 #include "Common/FileUtil.h"
42 #include "Core/MemMap.h"
43 #include "Core/Debugger/SymbolMap.h"
45 SymbolMap symbolMap;
47 void SymbolMap::SortSymbols() {
48 lock_guard guard(lock_);
50 AssignFunctionIndices();
53 void SymbolMap::Clear() {
54 lock_guard guard(lock_);
55 functions.clear();
56 labels.clear();
57 data.clear();
58 activeFunctions.clear();
59 activeLabels.clear();
60 activeData.clear();
61 activeModuleEnds.clear();
62 modules.clear();
65 bool SymbolMap::LoadSymbolMap(const char *filename) {
66 Clear(); // let's not recurse the lock
68 lock_guard guard(lock_);
70 #ifdef _WIN32_USING_UNICODE
71 gzFile f = gzopen_w(ConvertUTF8ToWString(filename).c_str(), "r");
72 #else
73 gzFile f = gzopen(filename, "r");
74 #endif
76 if (f == Z_NULL)
77 return false;
79 //char temp[256];
80 //fgets(temp,255,f); //.text section layout
81 //fgets(temp,255,f); // Starting Virtual
82 //fgets(temp,255,f); // address Size address
83 //fgets(temp,255,f); // -----------------------
85 bool started = false;
86 bool hasModules = false;
88 while (!gzeof(f)) {
89 char line[512], temp[256] = {0};
90 char *p = gzgets(f, line, 512);
91 if (p == NULL)
92 break;
94 // Chop any newlines off.
95 for (size_t i = strlen(line) - 1; i > 0; i--) {
96 if (line[i] == '\r' || line[i] == '\n') {
97 line[i] = '\0';
101 if (strlen(line) < 4 || sscanf(line, "%s", temp) != 1)
102 continue;
104 if (strcmp(temp,"UNUSED")==0) continue;
105 if (strcmp(temp,".text")==0) {started=true;continue;};
106 if (strcmp(temp,".init")==0) {started=true;continue;};
107 if (strcmp(temp,"Starting")==0) continue;
108 if (strcmp(temp,"extab")==0) continue;
109 if (strcmp(temp,".ctors")==0) break;
110 if (strcmp(temp,".dtors")==0) break;
111 if (strcmp(temp,".rodata")==0) continue;
112 if (strcmp(temp,".data")==0) continue;
113 if (strcmp(temp,".sbss")==0) continue;
114 if (strcmp(temp,".sdata")==0) continue;
115 if (strcmp(temp,".sdata2")==0) continue;
116 if (strcmp(temp,"address")==0) continue;
117 if (strcmp(temp,"-----------------------")==0) continue;
118 if (strcmp(temp,".sbss2")==0) break;
119 if (temp[1]==']') continue;
121 if (!started) continue;
123 u32 address = -1, size, vaddress = -1;
124 int moduleIndex = 0;
125 int typeInt;
126 SymbolType type;
127 char name[128] = {0};
129 if (sscanf(line, ".module %x %08x %08x %127c", &moduleIndex, &address, &size, name) == 4) {
130 // Found a module definition.
131 ModuleEntry mod;
132 mod.index = moduleIndex;
133 strcpy(mod.name, name);
134 mod.start = address;
135 mod.size = size;
136 modules.push_back(mod);
137 hasModules = true;
138 continue;
141 sscanf(line, "%08x %08x %x %i %127c", &address, &size, &vaddress, &typeInt, name);
142 type = (SymbolType) typeInt;
143 if (!hasModules) {
144 if (!Memory::IsValidAddress(vaddress)) {
145 ERROR_LOG(LOADER, "Invalid address in symbol file: %08x (%s)", vaddress, name);
146 continue;
148 } else {
149 // The 3rd field is now used for the module index.
150 moduleIndex = vaddress;
151 vaddress = GetModuleAbsoluteAddr(address, moduleIndex);
152 if (!Memory::IsValidAddress(vaddress)) {
153 ERROR_LOG(LOADER, "Invalid address in symbol file: %08x (%s)", vaddress, name);
154 continue;
158 if (type == ST_DATA && size == 0)
159 size = 4;
161 if (!strcmp(name, ".text") || !strcmp(name, ".init") || strlen(name) <= 1) {
163 } else {
164 switch (type)
166 case ST_FUNCTION:
167 AddFunction(name, vaddress, size, moduleIndex);
168 break;
169 case ST_DATA:
170 AddData(vaddress,size,DATATYPE_BYTE, moduleIndex);
171 if (name[0] != 0)
172 AddLabel(name, vaddress, moduleIndex);
173 break;
174 case ST_NONE:
175 case ST_ALL:
176 // Shouldn't be possible.
177 break;
181 gzclose(f);
182 SortSymbols();
183 return started;
186 void SymbolMap::SaveSymbolMap(const char *filename) const {
187 lock_guard guard(lock_);
189 // Don't bother writing a blank file.
190 if (!File::Exists(filename) && functions.empty() && data.empty()) {
191 return;
194 #ifdef _WIN32_USING_UNICODE
195 gzFile f = gzopen_w(ConvertUTF8ToWString(filename).c_str(), "w9");
196 #else
197 gzFile f = gzopen(filename, "w9");
198 #endif
200 if (f == Z_NULL)
201 return;
203 gzprintf(f, ".text\n");
205 for (auto it = modules.begin(), end = modules.end(); it != end; ++it) {
206 const ModuleEntry &mod = *it;
207 gzprintf(f, ".module %x %08x %08x %s\n", mod.index, mod.start, mod.size, mod.name);
210 for (auto it = functions.begin(), end = functions.end(); it != end; ++it) {
211 const FunctionEntry& e = it->second;
212 gzprintf(f, "%08x %08x %x %i %s\n", e.start, e.size, e.module, ST_FUNCTION, GetLabelNameRel(e.start, e.module));
215 for (auto it = data.begin(), end = data.end(); it != end; ++it) {
216 const DataEntry& e = it->second;
217 gzprintf(f, "%08x %08x %x %i %s\n", e.start, e.size, e.module, ST_DATA, GetLabelNameRel(e.start, e.module));
219 gzclose(f);
222 bool SymbolMap::LoadNocashSym(const char *filename) {
223 lock_guard guard(lock_);
224 FILE *f = File::OpenCFile(filename, "r");
225 if (!f)
226 return false;
228 while (!feof(f)) {
229 char line[256], value[256] = {0};
230 char *p = fgets(line, 256, f);
231 if (p == NULL)
232 break;
234 u32 address;
235 if (sscanf(line, "%08X %s", &address, value) != 2)
236 continue;
237 if (address == 0 && strcmp(value, "0") == 0)
238 continue;
240 if (value[0] == '.') {
241 // data directives
242 char* s = strchr(value, ':');
243 if (s != NULL) {
244 *s = 0;
246 u32 size = 0;
247 if (sscanf(s + 1, "%04X", &size) != 1)
248 continue;
250 if (strcasecmp(value, ".byt") == 0) {
251 AddData(address, size, DATATYPE_BYTE, 0);
252 } else if (strcasecmp(value, ".wrd") == 0) {
253 AddData(address, size, DATATYPE_HALFWORD, 0);
254 } else if (strcasecmp(value, ".dbl") == 0) {
255 AddData(address, size, DATATYPE_WORD, 0);
256 } else if (strcasecmp(value, ".asc") == 0) {
257 AddData(address, size, DATATYPE_ASCII, 0);
260 } else { // labels
261 int size = 1;
262 char* seperator = strchr(value, ',');
263 if (seperator != NULL) {
264 *seperator = 0;
265 sscanf(seperator+1,"%08X",&size);
268 if (size != 1) {
269 AddFunction(value, address,size, 0);
270 } else {
271 AddLabel(value, address, 0);
276 fclose(f);
277 return true;
280 void SymbolMap::SaveNocashSym(const char *filename) const {
281 lock_guard guard(lock_);
283 // Don't bother writing a blank file.
284 if (!File::Exists(filename) && functions.empty() && data.empty()) {
285 return;
288 FILE* f = fopen(filename, "w");
289 if (f == NULL)
290 return;
292 // only write functions, the rest isn't really interesting
293 for (auto it = functions.begin(), end = functions.end(); it != end; ++it) {
294 const FunctionEntry& e = it->second;
295 fprintf(f, "%08X %s,%04X\n", GetModuleAbsoluteAddr(e.start,e.module),GetLabelNameRel(e.start, e.module), e.size);
298 fclose(f);
301 SymbolType SymbolMap::GetSymbolType(u32 address) const {
302 lock_guard guard(lock_);
303 if (activeFunctions.find(address) != activeFunctions.end())
304 return ST_FUNCTION;
305 if (activeData.find(address) != activeData.end())
306 return ST_DATA;
307 return ST_NONE;
310 bool SymbolMap::GetSymbolInfo(SymbolInfo *info, u32 address, SymbolType symmask) const {
311 u32 functionAddress = INVALID_ADDRESS;
312 u32 dataAddress = INVALID_ADDRESS;
314 if (symmask & ST_FUNCTION) {
315 functionAddress = GetFunctionStart(address);
317 // If both are found, we always return the function, so just do that early.
318 if (functionAddress != INVALID_ADDRESS) {
319 if (info != NULL) {
320 info->type = ST_FUNCTION;
321 info->address = functionAddress;
322 info->size = GetFunctionSize(functionAddress);
323 info->moduleAddress = GetFunctionModuleAddress(functionAddress);
326 return true;
330 if (symmask & ST_DATA) {
331 dataAddress = GetDataStart(address);
333 if (dataAddress != INVALID_ADDRESS) {
334 if (info != NULL) {
335 info->type = ST_DATA;
336 info->address = dataAddress;
337 info->size = GetDataSize(dataAddress);
338 info->moduleAddress = GetDataModuleAddress(dataAddress);
341 return true;
345 return false;
348 u32 SymbolMap::GetNextSymbolAddress(u32 address, SymbolType symmask) {
349 lock_guard guard(lock_);
350 const auto functionEntry = symmask & ST_FUNCTION ? activeFunctions.upper_bound(address) : activeFunctions.end();
351 const auto dataEntry = symmask & ST_DATA ? activeData.upper_bound(address) : activeData.end();
353 if (functionEntry == activeFunctions.end() && dataEntry == activeData.end())
354 return INVALID_ADDRESS;
356 u32 funcAddress = (functionEntry != activeFunctions.end()) ? functionEntry->first : 0xFFFFFFFF;
357 u32 dataAddress = (dataEntry != activeData.end()) ? dataEntry->first : 0xFFFFFFFF;
359 if (funcAddress <= dataAddress)
360 return funcAddress;
361 else
362 return dataAddress;
365 std::string SymbolMap::GetDescription(unsigned int address) const {
366 lock_guard guard(lock_);
367 const char* labelName = NULL;
369 u32 funcStart = GetFunctionStart(address);
370 if (funcStart != INVALID_ADDRESS) {
371 labelName = GetLabelName(funcStart);
372 } else {
373 u32 dataStart = GetDataStart(address);
374 if (dataStart != INVALID_ADDRESS)
375 labelName = GetLabelName(dataStart);
378 if (labelName != NULL)
379 return labelName;
381 char descriptionTemp[256];
382 sprintf(descriptionTemp, "(%08x)", address);
383 return descriptionTemp;
386 std::vector<SymbolEntry> SymbolMap::GetAllSymbols(SymbolType symmask) {
387 std::vector<SymbolEntry> result;
389 if (symmask & ST_FUNCTION) {
390 lock_guard guard(lock_);
391 for (auto it = activeFunctions.begin(); it != activeFunctions.end(); it++) {
392 SymbolEntry entry;
393 entry.address = it->first;
394 entry.size = GetFunctionSize(entry.address);
395 const char* name = GetLabelName(entry.address);
396 if (name != NULL)
397 entry.name = name;
398 result.push_back(entry);
402 if (symmask & ST_DATA) {
403 lock_guard guard(lock_);
404 for (auto it = activeData.begin(); it != activeData.end(); it++) {
405 SymbolEntry entry;
406 entry.address = it->first;
407 entry.size = GetDataSize(entry.address);
408 const char* name = GetLabelName(entry.address);
409 if (name != NULL)
410 entry.name = name;
411 result.push_back(entry);
415 return result;
418 void SymbolMap::AddModule(const char *name, u32 address, u32 size) {
419 lock_guard guard(lock_);
421 for (auto it = modules.begin(), end = modules.end(); it != end; ++it) {
422 if (!strcmp(it->name, name)) {
423 // Just reactivate that one.
424 it->start = address;
425 it->size = size;
426 activeModuleEnds.insert(std::make_pair(it->start + it->size, *it));
427 UpdateActiveSymbols();
428 return;
432 ModuleEntry mod;
433 strncpy(mod.name, name, ARRAY_SIZE(mod.name));
434 mod.name[ARRAY_SIZE(mod.name) - 1] = '\0';
435 mod.start = address;
436 mod.size = size;
437 mod.index = (int)modules.size() + 1;
439 modules.push_back(mod);
440 activeModuleEnds.insert(std::make_pair(mod.start + mod.size, mod));
441 UpdateActiveSymbols();
444 void SymbolMap::UnloadModule(u32 address, u32 size) {
445 lock_guard guard(lock_);
446 activeModuleEnds.erase(address + size);
447 UpdateActiveSymbols();
450 u32 SymbolMap::GetModuleRelativeAddr(u32 address, int moduleIndex) const {
451 lock_guard guard(lock_);
452 if (moduleIndex == -1) {
453 moduleIndex = GetModuleIndex(address);
456 for (auto it = modules.begin(), end = modules.end(); it != end; ++it) {
457 if (it->index == moduleIndex) {
458 return address - it->start;
461 return address;
464 u32 SymbolMap::GetModuleAbsoluteAddr(u32 relative, int moduleIndex) const {
465 lock_guard guard(lock_);
466 for (auto it = modules.begin(), end = modules.end(); it != end; ++it) {
467 if (it->index == moduleIndex) {
468 return it->start + relative;
471 return relative;
474 int SymbolMap::GetModuleIndex(u32 address) const {
475 lock_guard guard(lock_);
476 auto iter = activeModuleEnds.upper_bound(address);
477 if (iter == activeModuleEnds.end())
478 return -1;
479 return iter->second.index;
482 bool SymbolMap::IsModuleActive(int moduleIndex) const {
483 if (moduleIndex == 0) {
484 return true;
487 lock_guard guard(lock_);
488 for (auto it = activeModuleEnds.begin(), end = activeModuleEnds.end(); it != end; ++it) {
489 if (it->second.index == moduleIndex) {
490 return true;
493 return false;
496 std::vector<LoadedModuleInfo> SymbolMap::getAllModules() const {
497 lock_guard guard(lock_);
499 std::vector<LoadedModuleInfo> result;
500 for (size_t i = 0; i < modules.size(); i++) {
501 LoadedModuleInfo m;
502 m.name = modules[i].name;
503 m.address = modules[i].start;
504 m.size = modules[i].size;
506 u32 key = modules[i].start + modules[i].size;
507 m.active = activeModuleEnds.find(key) != activeModuleEnds.end();
509 result.push_back(m);
512 return result;
515 void SymbolMap::AddFunction(const char* name, u32 address, u32 size, int moduleIndex) {
516 lock_guard guard(lock_);
518 if (moduleIndex == -1) {
519 moduleIndex = GetModuleIndex(address);
520 } else if (moduleIndex == 0) {
521 sawUnknownModule = true;
524 // Is there an existing one?
525 u32 relAddress = GetModuleRelativeAddr(address, moduleIndex);
526 auto symbolKey = std::make_pair(moduleIndex, relAddress);
527 auto existing = functions.find(symbolKey);
528 if (sawUnknownModule && existing == functions.end()) {
529 // Fall back: maybe it's got moduleIndex = 0.
530 existing = functions.find(std::make_pair(0, address));
533 if (existing != functions.end()) {
534 existing->second.size = size;
535 if (existing->second.module != moduleIndex) {
536 FunctionEntry func = existing->second;
537 func.start = relAddress;
538 func.module = moduleIndex;
539 functions.erase(existing);
540 functions[symbolKey] = func;
543 // Refresh the active item if it exists.
544 auto active = activeFunctions.find(address);
545 if (active != activeFunctions.end() && active->second.module == moduleIndex) {
546 activeFunctions.erase(active);
547 activeFunctions.insert(std::make_pair(address, existing->second));
549 } else {
550 FunctionEntry func;
551 func.start = relAddress;
552 func.size = size;
553 func.index = (int)functions.size();
554 func.module = moduleIndex;
555 functions[symbolKey] = func;
557 if (IsModuleActive(moduleIndex)) {
558 activeFunctions.insert(std::make_pair(address, func));
562 AddLabel(name, address, moduleIndex);
565 u32 SymbolMap::GetFunctionStart(u32 address) const {
566 lock_guard guard(lock_);
567 auto it = activeFunctions.upper_bound(address);
568 if (it == activeFunctions.end()) {
569 // check last element
570 auto rit = activeFunctions.rbegin();
571 if (rit != activeFunctions.rend()) {
572 u32 start = rit->first;
573 u32 size = rit->second.size;
574 if (start <= address && start+size > address)
575 return start;
577 // otherwise there's no function that contains this address
578 return INVALID_ADDRESS;
581 if (it != activeFunctions.begin()) {
582 it--;
583 u32 start = it->first;
584 u32 size = it->second.size;
585 if (start <= address && start+size > address)
586 return start;
589 return INVALID_ADDRESS;
592 u32 SymbolMap::FindPossibleFunctionAtAfter(u32 address) const {
593 lock_guard guard(lock_);
594 auto it = activeFunctions.lower_bound(address);
595 if (it == activeFunctions.end()) {
596 return (u32)-1;
598 return it->first;
601 u32 SymbolMap::GetFunctionSize(u32 startAddress) const {
602 lock_guard guard(lock_);
603 auto it = activeFunctions.find(startAddress);
604 if (it == activeFunctions.end())
605 return INVALID_ADDRESS;
607 return it->second.size;
610 u32 SymbolMap::GetFunctionModuleAddress(u32 startAddress) const {
611 lock_guard guard(lock_);
612 auto it = activeFunctions.find(startAddress);
613 if (it == activeFunctions.end())
614 return INVALID_ADDRESS;
616 return GetModuleAbsoluteAddr(0, it->second.module);
619 int SymbolMap::GetFunctionNum(u32 address) const {
620 lock_guard guard(lock_);
621 u32 start = GetFunctionStart(address);
622 if (start == INVALID_ADDRESS)
623 return INVALID_ADDRESS;
625 auto it = activeFunctions.find(start);
626 if (it == activeFunctions.end())
627 return INVALID_ADDRESS;
629 return it->second.index;
632 void SymbolMap::AssignFunctionIndices() {
633 lock_guard guard(lock_);
634 int index = 0;
635 for (auto mod = activeModuleEnds.begin(), modend = activeModuleEnds.end(); mod != modend; ++mod) {
636 int moduleIndex = mod->second.index;
637 auto begin = functions.lower_bound(std::make_pair(moduleIndex, 0));
638 auto end = functions.upper_bound(std::make_pair(moduleIndex, 0xFFFFFFFF));
639 for (auto it = begin; it != end; ++it) {
640 it->second.index = index++;
645 void SymbolMap::UpdateActiveSymbols() {
646 // return; (slow in debug mode)
647 lock_guard guard(lock_);
649 activeFunctions.clear();
650 activeLabels.clear();
651 activeData.clear();
653 // On startup and shutdown, we can skip the rest. Tiny optimization.
654 if (activeModuleEnds.empty() || (functions.empty() && labels.empty() && data.empty())) {
655 return;
658 std::map<int, u32> activeModuleIndexes;
659 for (auto it = activeModuleEnds.begin(), end = activeModuleEnds.end(); it != end; ++it) {
660 activeModuleIndexes[it->second.index] = it->second.start;
663 for (auto it = functions.begin(), end = functions.end(); it != end; ++it) {
664 const auto mod = activeModuleIndexes.find(it->second.module);
665 if (it->second.module == 0) {
666 activeFunctions.insert(std::make_pair(it->second.start, it->second));
667 } else if (mod != activeModuleIndexes.end()) {
668 activeFunctions.insert(std::make_pair(mod->second + it->second.start, it->second));
672 for (auto it = labels.begin(), end = labels.end(); it != end; ++it) {
673 const auto mod = activeModuleIndexes.find(it->second.module);
674 if (it->second.module == 0) {
675 activeLabels.insert(std::make_pair(it->second.addr, it->second));
676 } else if (mod != activeModuleIndexes.end()) {
677 activeLabels.insert(std::make_pair(mod->second + it->second.addr, it->second));
681 for (auto it = data.begin(), end = data.end(); it != end; ++it) {
682 const auto mod = activeModuleIndexes.find(it->second.module);
683 if (it->second.module == 0) {
684 activeData.insert(std::make_pair(it->second.start, it->second));
685 } else if (mod != activeModuleIndexes.end()) {
686 activeData.insert(std::make_pair(mod->second + it->second.start, it->second));
690 AssignFunctionIndices();
693 bool SymbolMap::SetFunctionSize(u32 startAddress, u32 newSize) {
694 lock_guard guard(lock_);
696 auto funcInfo = activeFunctions.find(startAddress);
697 if (funcInfo != activeFunctions.end()) {
698 auto symbolKey = std::make_pair(funcInfo->second.module, funcInfo->second.start);
699 auto func = functions.find(symbolKey);
700 if (func != functions.end()) {
701 func->second.size = newSize;
702 UpdateActiveSymbols();
706 // TODO: check for overlaps
707 return true;
710 bool SymbolMap::RemoveFunction(u32 startAddress, bool removeName) {
711 lock_guard guard(lock_);
713 auto it = activeFunctions.find(startAddress);
714 if (it == activeFunctions.end())
715 return false;
717 auto symbolKey = std::make_pair(it->second.module, it->second.start);
718 auto it2 = functions.find(symbolKey);
719 if (it2 != functions.end()) {
720 functions.erase(it2);
722 activeFunctions.erase(it);
724 if (removeName) {
725 auto labelIt = activeLabels.find(startAddress);
726 if (labelIt != activeLabels.end()) {
727 symbolKey = std::make_pair(labelIt->second.module, labelIt->second.addr);
728 auto labelIt2 = labels.find(symbolKey);
729 if (labelIt2 != labels.end()) {
730 labels.erase(labelIt2);
732 activeLabels.erase(labelIt);
736 return true;
739 void SymbolMap::AddLabel(const char* name, u32 address, int moduleIndex) {
740 lock_guard guard(lock_);
742 if (moduleIndex == -1) {
743 moduleIndex = GetModuleIndex(address);
744 } else if (moduleIndex == 0) {
745 sawUnknownModule = true;
748 // Is there an existing one?
749 u32 relAddress = GetModuleRelativeAddr(address, moduleIndex);
750 auto symbolKey = std::make_pair(moduleIndex, relAddress);
751 auto existing = labels.find(symbolKey);
752 if (sawUnknownModule && existing == labels.end()) {
753 // Fall back: maybe it's got moduleIndex = 0.
754 existing = labels.find(std::make_pair(0, address));
757 if (existing != labels.end()) {
758 // We leave an existing label alone, rather than overwriting.
759 // But we'll still upgrade it to the correct module / relative address.
760 if (existing->second.module != moduleIndex) {
761 LabelEntry label = existing->second;
762 label.addr = relAddress;
763 label.module = moduleIndex;
764 labels.erase(existing);
765 labels[symbolKey] = label;
767 // Refresh the active item if it exists.
768 auto active = activeLabels.find(address);
769 if (active != activeLabels.end() && active->second.module == moduleIndex) {
770 activeLabels.erase(active);
771 activeLabels.insert(std::make_pair(address, label));
774 } else {
775 LabelEntry label;
776 label.addr = relAddress;
777 label.module = moduleIndex;
778 strncpy(label.name, name, 128);
779 label.name[127] = 0;
781 labels[symbolKey] = label;
782 if (IsModuleActive(moduleIndex)) {
783 activeLabels.insert(std::make_pair(address, label));
788 void SymbolMap::SetLabelName(const char* name, u32 address) {
789 lock_guard guard(lock_);
790 auto labelInfo = activeLabels.find(address);
791 if (labelInfo == activeLabels.end()) {
792 AddLabel(name, address);
793 } else {
794 auto symbolKey = std::make_pair(labelInfo->second.module, labelInfo->second.addr);
795 auto label = labels.find(symbolKey);
796 if (label != labels.end()) {
797 strncpy(label->second.name, name, 128);
798 label->second.name[127] = 0;
800 // Refresh the active item if it exists.
801 auto active = activeLabels.find(address);
802 if (active != activeLabels.end() && active->second.module == label->second.module) {
803 activeLabels.erase(active);
804 activeLabels.insert(std::make_pair(address, label->second));
810 const char *SymbolMap::GetLabelName(u32 address) const {
811 lock_guard guard(lock_);
812 auto it = activeLabels.find(address);
813 if (it == activeLabels.end())
814 return NULL;
816 return it->second.name;
819 const char *SymbolMap::GetLabelNameRel(u32 relAddress, int moduleIndex) const {
820 lock_guard guard(lock_);
821 auto it = labels.find(std::make_pair(moduleIndex, relAddress));
822 if (it == labels.end())
823 return NULL;
825 return it->second.name;
828 std::string SymbolMap::GetLabelString(u32 address) const {
829 lock_guard guard(lock_);
830 const char *label = GetLabelName(address);
831 if (label == NULL)
832 return "";
833 return label;
836 bool SymbolMap::GetLabelValue(const char* name, u32& dest) {
837 lock_guard guard(lock_);
838 for (auto it = activeLabels.begin(); it != activeLabels.end(); it++) {
839 if (strcasecmp(name, it->second.name) == 0) {
840 dest = it->first;
841 return true;
845 return false;
848 void SymbolMap::AddData(u32 address, u32 size, DataType type, int moduleIndex) {
849 lock_guard guard(lock_);
851 if (moduleIndex == -1) {
852 moduleIndex = GetModuleIndex(address);
853 } else if (moduleIndex == 0) {
854 sawUnknownModule = true;
857 // Is there an existing one?
858 u32 relAddress = GetModuleRelativeAddr(address, moduleIndex);
859 auto symbolKey = std::make_pair(moduleIndex, relAddress);
860 auto existing = data.find(symbolKey);
861 if (sawUnknownModule && existing == data.end()) {
862 // Fall back: maybe it's got moduleIndex = 0.
863 existing = data.find(std::make_pair(0, address));
866 if (existing != data.end()) {
867 existing->second.size = size;
868 existing->second.type = type;
869 if (existing->second.module != moduleIndex) {
870 DataEntry entry = existing->second;
871 entry.module = moduleIndex;
872 entry.start = relAddress;
873 data.erase(existing);
874 data[symbolKey] = entry;
877 // Refresh the active item if it exists.
878 auto active = activeData.find(address);
879 if (active != activeData.end() && active->second.module == moduleIndex) {
880 activeData.erase(active);
881 activeData.insert(std::make_pair(address, existing->second));
883 } else {
884 DataEntry entry;
885 entry.start = relAddress;
886 entry.size = size;
887 entry.type = type;
888 entry.module = moduleIndex;
890 data[symbolKey] = entry;
891 if (IsModuleActive(moduleIndex)) {
892 activeData.insert(std::make_pair(address, entry));
897 u32 SymbolMap::GetDataStart(u32 address) const {
898 lock_guard guard(lock_);
899 auto it = activeData.upper_bound(address);
900 if (it == activeData.end())
902 // check last element
903 auto rit = activeData.rbegin();
905 if (rit != activeData.rend())
907 u32 start = rit->first;
908 u32 size = rit->second.size;
909 if (start <= address && start+size > address)
910 return start;
912 // otherwise there's no data that contains this address
913 return INVALID_ADDRESS;
916 if (it != activeData.begin()) {
917 it--;
918 u32 start = it->first;
919 u32 size = it->second.size;
920 if (start <= address && start+size > address)
921 return start;
924 return INVALID_ADDRESS;
927 u32 SymbolMap::GetDataSize(u32 startAddress) const {
928 lock_guard guard(lock_);
929 auto it = activeData.find(startAddress);
930 if (it == activeData.end())
931 return INVALID_ADDRESS;
932 return it->second.size;
935 u32 SymbolMap::GetDataModuleAddress(u32 startAddress) const {
936 lock_guard guard(lock_);
937 auto it = activeData.find(startAddress);
938 if (it == activeData.end())
939 return INVALID_ADDRESS;
940 return GetModuleAbsoluteAddr(0, it->second.module);
943 DataType SymbolMap::GetDataType(u32 startAddress) const {
944 lock_guard guard(lock_);
945 auto it = activeData.find(startAddress);
946 if (it == activeData.end())
947 return DATATYPE_NONE;
948 return it->second.type;
951 #if defined(_WIN32_NO_MINGW) && !defined(__LIBRETRO__)
953 void SymbolMap::getLabels(std::vector<LabelDefinition>& dest) const
955 lock_guard guard(lock_);
956 for (auto it = activeLabels.begin(); it != activeLabels.end(); it++) {
957 LabelDefinition entry;
958 entry.value = it->first;
959 entry.name = ConvertUTF8ToWString(it->second.name);
960 dest.push_back(entry);
964 #if defined(_WIN32)
966 struct DefaultSymbol {
967 u32 address;
968 const char* name;
971 static const DefaultSymbol defaultSymbols[]= {
972 { 0x08800000, "User memory" },
973 { 0x08804000, "Default load address" },
974 { 0x04000000, "VRAM" },
975 { 0x88000000, "Kernel memory" },
976 { 0x00010000, "Scratchpad" },
979 void SymbolMap::FillSymbolListBox(HWND listbox,SymbolType symType) const {
980 wchar_t temp[256];
981 lock_guard guard(lock_);
983 SendMessage(listbox, WM_SETREDRAW, FALSE, 0);
984 ListBox_ResetContent(listbox);
986 switch (symType) {
987 case ST_FUNCTION:
989 SendMessage(listbox, LB_INITSTORAGE, (WPARAM)activeFunctions.size(), (LPARAM)activeFunctions.size() * 30);
991 for (auto it = activeFunctions.begin(), end = activeFunctions.end(); it != end; ++it) {
992 const FunctionEntry& entry = it->second;
993 const char* name = GetLabelName(it->first);
994 if (name != NULL)
995 wsprintf(temp, L"%S", name);
996 else
997 wsprintf(temp, L"0x%08X", it->first);
998 int index = ListBox_AddString(listbox,temp);
999 ListBox_SetItemData(listbox,index,it->first);
1002 break;
1004 case ST_DATA:
1006 int count = ARRAYSIZE(defaultSymbols)+(int)activeData.size();
1007 SendMessage(listbox, LB_INITSTORAGE, (WPARAM)count, (LPARAM)count * 30);
1009 for (int i = 0; i < ARRAYSIZE(defaultSymbols); i++) {
1010 wsprintf(temp, L"0x%08X (%S)", defaultSymbols[i].address, defaultSymbols[i].name);
1011 int index = ListBox_AddString(listbox,temp);
1012 ListBox_SetItemData(listbox,index,defaultSymbols[i].address);
1015 for (auto it = activeData.begin(), end = activeData.end(); it != end; ++it) {
1016 const DataEntry& entry = it->second;
1017 const char* name = GetLabelName(it->first);
1019 if (name != NULL)
1020 wsprintf(temp, L"%S", name);
1021 else
1022 wsprintf(temp, L"0x%08X", it->first);
1024 int index = ListBox_AddString(listbox,temp);
1025 ListBox_SetItemData(listbox,index,it->first);
1028 break;
1031 SendMessage(listbox, WM_SETREDRAW, TRUE, 0);
1032 RedrawWindow(listbox, NULL, NULL, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
1035 #endif
1037 #endif