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)
24 #if defined(_WIN32) && !defined(__MINGW32__)
25 #define _WIN32_NO_MINGW
26 #define _WIN32_USING_UNICODE
29 #ifdef _WIN32_NO_MINGW
30 #include "Common/CommonWindows.h"
38 #include "util/text/utf8.h"
40 #include "Common/CommonTypes.h"
41 #include "Common/FileUtil.h"
42 #include "Core/MemMap.h"
43 #include "Core/Debugger/SymbolMap.h"
47 void SymbolMap::SortSymbols() {
48 lock_guard
guard(lock_
);
50 AssignFunctionIndices();
53 void SymbolMap::Clear() {
54 lock_guard
guard(lock_
);
58 activeFunctions
.clear();
61 activeModuleEnds
.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");
73 gzFile f
= gzopen(filename
, "r");
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); // -----------------------
86 bool hasModules
= false;
89 char line
[512], temp
[256] = {0};
90 char *p
= gzgets(f
, line
, 512);
94 // Chop any newlines off.
95 for (size_t i
= strlen(line
) - 1; i
> 0; i
--) {
96 if (line
[i
] == '\r' || line
[i
] == '\n') {
101 if (strlen(line
) < 4 || sscanf(line
, "%s", temp
) != 1)
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;
127 char name
[128] = {0};
129 if (sscanf(line
, ".module %x %08x %08x %127c", &moduleIndex
, &address
, &size
, name
) == 4) {
130 // Found a module definition.
132 mod
.index
= moduleIndex
;
133 strcpy(mod
.name
, name
);
136 modules
.push_back(mod
);
141 sscanf(line
, "%08x %08x %x %i %127c", &address
, &size
, &vaddress
, &typeInt
, name
);
142 type
= (SymbolType
) typeInt
;
144 if (!Memory::IsValidAddress(vaddress
)) {
145 ERROR_LOG(LOADER
, "Invalid address in symbol file: %08x (%s)", vaddress
, name
);
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
);
158 if (type
== ST_DATA
&& size
== 0)
161 if (!strcmp(name
, ".text") || !strcmp(name
, ".init") || strlen(name
) <= 1) {
167 AddFunction(name
, vaddress
, size
, moduleIndex
);
170 AddData(vaddress
,size
,DATATYPE_BYTE
, moduleIndex
);
172 AddLabel(name
, vaddress
, moduleIndex
);
176 // Shouldn't be possible.
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()) {
194 #ifdef _WIN32_USING_UNICODE
195 gzFile f
= gzopen_w(ConvertUTF8ToWString(filename
).c_str(), "w9");
197 gzFile f
= gzopen(filename
, "w9");
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
));
222 bool SymbolMap::LoadNocashSym(const char *filename
) {
223 lock_guard
guard(lock_
);
224 FILE *f
= File::OpenCFile(filename
, "r");
229 char line
[256], value
[256] = {0};
230 char *p
= fgets(line
, 256, f
);
235 if (sscanf(line
, "%08X %s", &address
, value
) != 2)
237 if (address
== 0 && strcmp(value
, "0") == 0)
240 if (value
[0] == '.') {
242 char* s
= strchr(value
, ':');
247 if (sscanf(s
+ 1, "%04X", &size
) != 1)
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);
262 char* seperator
= strchr(value
, ',');
263 if (seperator
!= NULL
) {
265 sscanf(seperator
+1,"%08X",&size
);
269 AddFunction(value
, address
,size
, 0);
271 AddLabel(value
, address
, 0);
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()) {
288 FILE* f
= fopen(filename
, "w");
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
);
301 SymbolType
SymbolMap::GetSymbolType(u32 address
) const {
302 lock_guard
guard(lock_
);
303 if (activeFunctions
.find(address
) != activeFunctions
.end())
305 if (activeData
.find(address
) != activeData
.end())
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
) {
320 info
->type
= ST_FUNCTION
;
321 info
->address
= functionAddress
;
322 info
->size
= GetFunctionSize(functionAddress
);
323 info
->moduleAddress
= GetFunctionModuleAddress(functionAddress
);
330 if (symmask
& ST_DATA
) {
331 dataAddress
= GetDataStart(address
);
333 if (dataAddress
!= INVALID_ADDRESS
) {
335 info
->type
= ST_DATA
;
336 info
->address
= dataAddress
;
337 info
->size
= GetDataSize(dataAddress
);
338 info
->moduleAddress
= GetDataModuleAddress(dataAddress
);
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
)
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
);
373 u32 dataStart
= GetDataStart(address
);
374 if (dataStart
!= INVALID_ADDRESS
)
375 labelName
= GetLabelName(dataStart
);
378 if (labelName
!= NULL
)
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
++) {
393 entry
.address
= it
->first
;
394 entry
.size
= GetFunctionSize(entry
.address
);
395 const char* name
= GetLabelName(entry
.address
);
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
++) {
406 entry
.address
= it
->first
;
407 entry
.size
= GetDataSize(entry
.address
);
408 const char* name
= GetLabelName(entry
.address
);
411 result
.push_back(entry
);
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.
426 activeModuleEnds
.insert(std::make_pair(it
->start
+ it
->size
, *it
));
427 UpdateActiveSymbols();
433 strncpy(mod
.name
, name
, ARRAY_SIZE(mod
.name
));
434 mod
.name
[ARRAY_SIZE(mod
.name
) - 1] = '\0';
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
;
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
;
474 int SymbolMap::GetModuleIndex(u32 address
) const {
475 lock_guard
guard(lock_
);
476 auto iter
= activeModuleEnds
.upper_bound(address
);
477 if (iter
== activeModuleEnds
.end())
479 return iter
->second
.index
;
482 bool SymbolMap::IsModuleActive(int moduleIndex
) const {
483 if (moduleIndex
== 0) {
487 lock_guard
guard(lock_
);
488 for (auto it
= activeModuleEnds
.begin(), end
= activeModuleEnds
.end(); it
!= end
; ++it
) {
489 if (it
->second
.index
== moduleIndex
) {
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
++) {
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();
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
));
551 func
.start
= relAddress
;
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
)
577 // otherwise there's no function that contains this address
578 return INVALID_ADDRESS
;
581 if (it
!= activeFunctions
.begin()) {
583 u32 start
= it
->first
;
584 u32 size
= it
->second
.size
;
585 if (start
<= address
&& start
+size
> address
)
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()) {
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_
);
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();
653 // On startup and shutdown, we can skip the rest. Tiny optimization.
654 if (activeModuleEnds
.empty() || (functions
.empty() && labels
.empty() && data
.empty())) {
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
710 bool SymbolMap::RemoveFunction(u32 startAddress
, bool removeName
) {
711 lock_guard
guard(lock_
);
713 auto it
= activeFunctions
.find(startAddress
);
714 if (it
== activeFunctions
.end())
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
);
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
);
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
));
776 label
.addr
= relAddress
;
777 label
.module
= moduleIndex
;
778 strncpy(label
.name
, name
, 128);
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
);
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())
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())
825 return it
->second
.name
;
828 std::string
SymbolMap::GetLabelString(u32 address
) const {
829 lock_guard
guard(lock_
);
830 const char *label
= GetLabelName(address
);
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) {
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
));
885 entry
.start
= relAddress
;
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
)
912 // otherwise there's no data that contains this address
913 return INVALID_ADDRESS
;
916 if (it
!= activeData
.begin()) {
918 u32 start
= it
->first
;
919 u32 size
= it
->second
.size
;
920 if (start
<= address
&& start
+size
> address
)
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
);
966 struct DefaultSymbol
{
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 {
981 lock_guard
guard(lock_
);
983 SendMessage(listbox
, WM_SETREDRAW
, FALSE
, 0);
984 ListBox_ResetContent(listbox
);
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
);
995 wsprintf(temp
, L
"%S", name
);
997 wsprintf(temp
, L
"0x%08X", it
->first
);
998 int index
= ListBox_AddString(listbox
,temp
);
999 ListBox_SetItemData(listbox
,index
,it
->first
);
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
);
1020 wsprintf(temp
, L
"%S", name
);
1022 wsprintf(temp
, L
"0x%08X", it
->first
);
1024 int index
= ListBox_AddString(listbox
,temp
);
1025 ListBox_SetItemData(listbox
,index
,it
->first
);
1031 SendMessage(listbox
, WM_SETREDRAW
, TRUE
, 0);
1032 RedrawWindow(listbox
, NULL
, NULL
, RDW_ERASE
| RDW_FRAME
| RDW_INVALIDATE
| RDW_ALLCHILDREN
);