Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/Common/GhidraClient.h
3185 views
1
#pragma once
2
3
#include <atomic>
4
#include <mutex>
5
#include <string>
6
#include <thread>
7
#include <unordered_map>
8
#include <vector>
9
10
// Represents symbol from a Ghidra's program.
11
// A symbol can be for example a data label, instruction label or a function.
12
struct GhidraSymbol {
13
u32 address = 0;
14
std::string name;
15
bool label;
16
bool userDefined;
17
std::string dataTypePathName;
18
};
19
20
// Possible kinds of data types, such as enum, structures or built-ins (Ghidra's primitive types).
21
enum GhidraTypeKind {
22
ENUM,
23
TYPEDEF,
24
POINTER,
25
ARRAY,
26
STRUCTURE,
27
UNION,
28
FUNCTION_DEFINITION,
29
BUILT_IN,
30
UNKNOWN,
31
};
32
33
// Describes single member of an enum type.
34
struct GhidraEnumMember {
35
std::string name;
36
u64 value = 0;
37
std::string comment;
38
};
39
40
// Describes single member of a composite (structure or union) type.
41
struct GhidraCompositeMember {
42
std::string fieldName;
43
u32 ordinal = 0;
44
u32 offset = 0;
45
int length = 0;
46
std::string typePathName;
47
std::string comment;
48
};
49
50
// Describes data type from Ghidra. Note that some fields of this structure will only be populated depending on the
51
// type's kind. Each type has a display name that is suitable for displaying to the user and a path name that
52
// unambiguously identifies this type.
53
struct GhidraType {
54
GhidraTypeKind kind;
55
std::string displayName;
56
std::string pathName;
57
int length = 0;
58
int alignedLength = 0;
59
bool zeroLength = false;
60
std::string description;
61
62
std::vector<GhidraCompositeMember> compositeMembers;
63
std::vector<GhidraEnumMember> enumMembers;
64
bool enumBitfield = false; // Determined from a simple heuristic check
65
std::string pointerTypePathName;
66
std::string typedefTypePathName;
67
std::string typedefBaseTypePathName;
68
std::string arrayTypePathName;
69
int arrayElementLength = 0;
70
u32 arrayElementCount = 0;
71
std::string functionPrototypeString;
72
std::string builtInGroup;
73
};
74
75
// GhidraClient implements fetching data (such as symbols or types) from a remote Ghidra project.
76
//
77
// This client uses unofficial API provided by the third party "ghidra-rest-api" extension. The extension is
78
// available at https://github.com/kotcrab/ghidra-rest-api.
79
//
80
// This class doesn't fetch data from every possible endpoint, only those that are actually used by PPSSPP.
81
//
82
// How to use:
83
// 1. The client is created in the Idle status.
84
// 2. To start fetching data call the FetchAll() method. The client goes to Pending status and the data is fetched
85
// in a background thread so your code remains unblocked.
86
// 3. Periodically check with the Ready() method is the operation has completed. (i.e. check if the client
87
// is in the Ready status)
88
// 4. If the client is ready call UpdateResult() to update result field with new data.
89
// 5. The client is now back to Idle status, and you can call FetchAll() again later if needed.
90
class GhidraClient {
91
enum class Status {
92
Idle,
93
Pending,
94
Ready,
95
};
96
97
public:
98
struct Result {
99
std::vector<GhidraSymbol> symbols;
100
std::unordered_map<std::string, GhidraType> types;
101
std::string error;
102
};
103
104
// Current result of the client. Your thread is safe to access this regardless of client status.
105
Result result;
106
107
GhidraClient() : status_(Status::Idle) {}
108
~GhidraClient();
109
110
// If client is idle then asynchronously starts fetching data from Ghidra.
111
void FetchAll(const std::string &host, int port);
112
113
// If client is ready then updates the result field with newly fetched data.
114
// This must be called from the thread using the result.
115
void UpdateResult();
116
117
bool Idle() const { return status_ == Status::Idle; }
118
119
bool Ready() const { return status_ == Status::Ready; }
120
121
bool Failed() const { return !result.error.empty(); }
122
123
private:
124
std::thread thread_;
125
std::mutex mutex_;
126
std::atomic<Status> status_;
127
Result pendingResult_;
128
std::string host_;
129
int port_ = 0;
130
131
bool FetchAllDo(const std::string &host, int port);
132
133
bool FetchSymbols();
134
135
bool FetchTypes();
136
137
bool FetchResource(const std::string &path, std::string &outResult);
138
};
139
140