Skip to content

Commit 31078db

Browse files
committed
[gdb] Better module handling
This makes GDB's module handling behave more similar to the one in Windows: - With all GDB versions, we check if a module is loaded before looking it up in GDB. - In GDB 8.4+ (not yet released), we only look for a type/symbol in the requested module (this is not possible in older GDB versions).
1 parent 96084b1 commit 31078db

File tree

2 files changed

+77
-20
lines changed

2 files changed

+77
-20
lines changed

server/JsDbg.Gdb/JsDbg.py

Lines changed: 65 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,42 @@ def __init__(self, symbol, frame):
6060
GdbSymbolResult(symbol, frame))
6161

6262

63+
def FindObjfileForName(name):
64+
for objfile in gdb.objfiles():
65+
if JsDbgBase.FormatModule(objfile.filename) == name:
66+
return objfile
67+
return None
68+
69+
70+
def FindGdbSymbol(module, symbol):
71+
objfile = FindObjfileForName(module)
72+
if objfile is None:
73+
return None
74+
# GDB 8.4 and later let us look up symbols per-objfile; use that if
75+
# possible. Also, only 8.4 and later let us look for symbols with static
76+
# linkage. So in older versions we have to use gdb.lookup_symbol.
77+
if hasattr(objfile, 'lookup_static_symbol'):
78+
# We try static first, because in practice most of the symbols we look
79+
# up here are static (or in an anonymous namespace, which is equivalent)
80+
sym = objfile.lookup_static_symbol(symbol)
81+
if sym is None:
82+
sym = objfile.lookup_global_symbol(symbol)
83+
else:
84+
(sym, _) = gdb.lookup_symbol(symbol)
85+
return sym
86+
87+
88+
def FindGdbType(module, type_name):
89+
# Types are also symbols, so we just look them up as symbols. This is
90+
# what GDB does internally.
91+
type_symbol = FindGdbSymbol(module, type_name)
92+
if type_symbol is None:
93+
return None
94+
if type_symbol.addr_class != gdb.SYMBOL_LOC_TYPEDEF:
95+
return None
96+
return type_symbol.type
97+
98+
6399
def DebuggerQuery(tag, command):
64100
# pi exec('print(\\'{0}~\\' + str({1}))')
65101
try:
@@ -114,7 +150,10 @@ def ExecuteGdbCommand(cmd):
114150

115151

116152
def GetAllFields(module, type, includeBaseTypes):
117-
t = gdb.lookup_type(type)
153+
t = FindGdbType(module, type)
154+
if t is None:
155+
return None
156+
118157
fields = t.fields()
119158
resultFields = []
120159
for field in fields:
@@ -167,20 +206,24 @@ def GetBaseTypesFromGdbType(module, type, extra_bitoffset=0):
167206

168207

169208
def GetBaseTypes(module, type_name):
170-
try:
171-
t = gdb.lookup_type(type_name)
172-
except:
209+
t = FindGdbType(module, type_name)
210+
if t is None:
173211
# Type is a base type?
174-
return [JsDbgTypes.BaseTypeResult(module, type_name, 0)]
212+
return [JsDbgTypes.SBaseTypeResult(module, type_name, 0)]
175213

176214
return GetBaseTypesFromGdbType(module, t)
177215

178216
def IsTypeEnum(module, type):
179-
t = gdb.lookup_type(type)
217+
t = FindGdbType(module, type)
218+
if t is None:
219+
return False
180220
return t.code == gdb.TYPE_CODE_ENUM
181221

182222
def LookupField(module, type, field):
183-
t = gdb.lookup_type(type)
223+
t = FindGdbType(module, type)
224+
if t is None:
225+
return None
226+
184227
fields = t.fields()
185228
while fields:
186229
match = list(filter(lambda x: x.name == field, fields))
@@ -200,21 +243,18 @@ def LookupField(module, type, field):
200243
fields = [f for m in match for f in m.type.fields()]
201244

202245
def LookupGlobalSymbol(module, symbol):
203-
# We can't use lookup_global_symbol because that does not work for symbols
204-
# with local linkage, such as those in an anonymous namespace.
205-
# https://sourceware.org/bugzilla/show_bug.cgi?id=24474
206-
(sym, _) = gdb.lookup_symbol(symbol)
246+
sym = FindGdbSymbol(module, symbol)
207247
if sym is None:
208248
return None
209249
return GdbSymbolResult(sym)
210250

211251

212252
def GetModuleForName(module):
213-
for objfile in gdb.objfiles():
214-
if JsDbgBase.FormatModule(objfile.filename) == module:
215-
# Python has no API to find the base address
216-
# https://sourceware.org/bugzilla/show_bug.cgi?id=24481
217-
return JsDbgTypes.SModule(module, 0)
253+
objfile = FindObjfileForName(module)
254+
if objfile:
255+
# Python has no API to find the base address
256+
# https://sourceware.org/bugzilla/show_bug.cgi?id=24481
257+
return JsDbgTypes.SModule(module, 0)
218258
return None
219259

220260

@@ -252,12 +292,16 @@ def LookupTypeSize(module, typename):
252292
if (typename.endswith("*")):
253293
t = gdb.lookup_type("void")
254294
return t.reference().sizeof
255-
t = gdb.lookup_type(typename)
295+
t = FindGdbType(module, typename)
296+
if t is None:
297+
return None
256298
return t.sizeof
257299

258300

259301
def LookupConstants(module, type, value):
260-
type = gdb.lookup_type(type)
302+
type = FindGdbType(module, type)
303+
if type is None:
304+
return None
261305
if type.code != gdb.TYPE_CODE_ENUM:
262306
return None
263307
values = []
@@ -275,7 +319,9 @@ def LookupConstants(module, type, value):
275319

276320
def LookupConstant(module, typename, constantName):
277321
if typename:
278-
type = gdb.lookup_type(typename)
322+
type = FindGdbType(module, typename)
323+
if type is None:
324+
return None
279325
# Values in enum classes are stored as type::eFoo;
280326
# regular enums as just eFoo.
281327
matches = [f for f in type.fields() if f.name.endswith("::" + constantName) or f.name == constantName]

server/JsDbg.Stdio/StdioDebugger.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ public async Task<IEnumerable<SFieldResult>> GetAllFields(string module, string
113113
NotifyDebuggerMessage(String.Format("Looking up fields for {0}...", typename));
114114

115115
string pythonResult = await this.QueryDebuggerPython(String.Format("GetAllFields(\"{0}\",\"{1}\",{2})",module, typename, includeBaseTypes ? "True" : "False"));
116+
if (pythonResult == "None")
117+
throw new DebuggerException(String.Format("No type {0}!{1}", module, typename));
116118

117119
List<string> objects = ParsePythonObjectArrayToStrings(pythonResult);
118120
List<SFieldResult> result = new List<SFieldResult>();
@@ -139,6 +141,8 @@ public async Task<IEnumerable<SBaseTypeResult>> GetBaseTypes(string module, stri
139141
NotifyDebuggerMessage(String.Format("Looking up base types for {0}...", typeName));
140142

141143
string pythonResult = await this.QueryDebuggerPython(String.Format("GetBaseTypes(\"{0}\",\"{1}\")", module, typeName));
144+
if (pythonResult == "None")
145+
throw new DebuggerException(String.Format("No type {0}!{1}", module, typeName));
142146

143147
List<string> objects = ParsePythonObjectArrayToStrings(pythonResult);
144148
List<SBaseTypeResult> result = new List<SBaseTypeResult>();
@@ -177,6 +181,8 @@ public async Task<IEnumerable<SConstantResult>> LookupConstants(string module, s
177181
NotifyDebuggerMessage(String.Format("Looking up name for {0}({1})...", type, constantValue));
178182

179183
string pythonResult = await this.QueryDebuggerPython(String.Format("LookupConstants(\"{0}\", \"{1}\", {2})", module, type, constantValue));
184+
if (pythonResult == "None")
185+
throw new DebuggerException(String.Format("Error looking up constant value {0} on {1}!{2}", constantValue, module, type));
180186

181187
List<string> objects = ParsePythonObjectArrayToStrings(pythonResult);
182188
List<SConstantResult> result = new List<SConstantResult>();
@@ -198,6 +204,8 @@ public async Task<SConstantResult> LookupConstant(string module, string type, st
198204
NotifyDebuggerMessage(String.Format("Looking up value for constant {0}...", constantName));
199205

200206
string response = await this.QueryDebuggerPython(String.Format("LookupConstant(\"{0}\",\"{1}\",\"{2}\")", module, type == null ? "None" : type , constantName));
207+
if (response == "None")
208+
throw new DebuggerException(String.Format("Error looking up constant {0} on {1}!{2}", constantName, module, type));
201209

202210
SConstantResult result = new SConstantResult();
203211
result.ConstantName = constantName;
@@ -262,6 +270,8 @@ public async Task<SSymbolResult> LookupGlobalSymbol(string module, string symbol
262270

263271
public async Task<SModule> GetModuleForName(string module) {
264272
string pythonResult = await this.QueryDebuggerPython(String.Format("GetModuleForName(\"{0}\")", module));
273+
if (pythonResult == "None")
274+
throw new DebuggerException(String.Format("No module {0}", module));
265275

266276
Debug.Assert(pythonResult[0] == '{');
267277
int fieldEndIndex = pythonResult.IndexOf('}');
@@ -335,7 +345,6 @@ public async Task<SSymbolNameAndDisplacement> LookupSymbolName(ulong pointer) {
335345
NotifyDebuggerMessage(String.Format("Looking up symbol at 0x{0:x}...", pointer));
336346

337347
string response = await this.QueryDebuggerPython(String.Format("LookupSymbolName(0x{0:x})",pointer));
338-
339348
if (response == "None")
340349
throw new DebuggerException(String.Format("Address 0x{0:x} is not a symbol", pointer));
341350

@@ -365,6 +374,8 @@ public async Task<uint> LookupTypeSize(string module, string typename) {
365374
NotifyDebuggerMessage(String.Format("Looking up sizeof({0})...", typename));
366375

367376
string pythonResponse = await this.QueryDebuggerPython(String.Format("LookupTypeSize(\"{0}\",\"{1}\")", module, typename));
377+
if (pythonResponse == "None")
378+
throw new DebuggerException(String.Format("No type {0}!{1}", module, typename));
368379

369380
return UInt32.Parse(pythonResponse);
370381
}

0 commit comments

Comments
 (0)