@@ -234,9 +234,10 @@ def pe_headers(self, imagebase):
234
234
# Returns a dictionary with PE sections.
235
235
#
236
236
237
- def pe_sections (self , opt , file , _ ):
237
+ def pe_sections (self , combined , file , _ ):
238
238
sect_t = self .ptype ('EFI_IMAGE_SECTION_HEADER' )
239
- sections_addr = opt .GetLoadAddress () + opt .GetByteSize ()
239
+ common = self .get_child_member_with_name (combined , 'CommonHeader' )
240
+ sections_addr = common .GetLoadAddress () + common .GetByteSize () + self .get_field (file , 'SizeOfOptionalHeader' )
240
241
sections = self .typed_ptr (sect_t , sections_addr )
241
242
sects = OrderedDict ()
242
243
for i in range (self .get_field (file , 'NumberOfSections' )):
@@ -253,7 +254,7 @@ def pe_sections(self, opt, file, _):
253
254
#
254
255
255
256
def pe_is_64 (self , pe_headers ):
256
- magic = pe_headers .GetValueForExpressionPath ('.Pe32.OptionalHeader. Magic' ).GetValueAsUnsigned ()
257
+ magic = pe_headers .GetValueForExpressionPath ('.Pe32.Magic' ).GetValueAsUnsigned ()
257
258
return magic == self .PE32PLUS_MAGIC
258
259
259
260
#
@@ -271,21 +272,20 @@ def pe_file(self, pe):
271
272
# Returns the PE (not so) optional header.
272
273
#
273
274
274
- def pe_optional (self , pe ):
275
+ def pe_combined (self , pe ):
275
276
if self .pe_is_64 (pe ):
276
- obj = self .get_child_member_with_name (pe , 'Pe32Plus' )
277
+ return self .get_child_member_with_name (pe , 'Pe32Plus' )
277
278
else :
278
- obj = self .get_child_member_with_name (pe , 'Pe32' )
279
- return self .get_child_member_with_name (obj , 'OptionalHeader' )
279
+ return self .get_child_member_with_name (pe , 'Pe32' )
280
280
281
281
#
282
282
# Returns the symbol file name for a PE image.
283
283
#
284
284
285
285
def pe_parse_debug (self , base ):
286
286
pe = self .pe_headers (base )
287
- opt = self .pe_optional (pe )
288
- debug_dir_entry = opt .GetValueForExpressionPath ('.DataDirectory[6]' )
287
+ combined = self .pe_combined (pe )
288
+ debug_dir_entry = combined .GetValueForExpressionPath ('.DataDirectory[6]' )
289
289
dep = self .get_field (debug_dir_entry , 'VirtualAddress' ) + base
290
290
dep = self .typed_ptr (self .ptype ('EFI_IMAGE_DEBUG_DIRECTORY_ENTRY' ), dep )
291
291
cvp = self .get_field (dep , 'RVA' ) + base
@@ -303,10 +303,10 @@ def pe_parse_debug(self, base):
303
303
return self .EINVAL
304
304
305
305
#
306
- # Prepares symbol load command with proper section information .
306
+ # Prepares lldb symbol load command.
307
307
# Currently supports Mach-O and single-section files.
308
308
#
309
- def get_sym_cmd (self , filename , orgbase , * _ ):
309
+ def get_sym_cmd (self , filename , orgbase ):
310
310
if filename .endswith ('.pdb' ):
311
311
dll_file = filename .replace ('.pdb' , '.dll' )
312
312
module_cmd = f'target modules add -s { filename } { dll_file } '
@@ -324,19 +324,19 @@ def get_sym_cmd(self, filename, orgbase, *_):
324
324
#
325
325
326
326
def parse_image (self , image , syms ):
327
- orgbase = base = self .get_field (image , 'ImageBase' )
327
+ base = self .get_field (image , 'ImageBase' )
328
328
pe = self .pe_headers (base )
329
- opt = self .pe_optional (pe )
330
- file = self .pe_file (pe )
329
+ combined = self .pe_combined (pe )
331
330
sym_address = self .pe_parse_debug (base )
332
- sections = self .pe_sections (opt , file , base )
333
331
334
332
if sym_address == 0 :
335
333
# llvm-objcopy --add-gnu-debuglink=a/x.debug a/x.dll does not update
336
334
# DataDirectory with any data, instead it creates a new section
337
335
# with a /\d+ name containing:
338
336
# - ASCII debug file name (x.debug) padded by 4 bytes
339
337
# - CRC32
338
+ file = self .pe_file (pe )
339
+ sections = self .pe_sections (combined , file , base )
340
340
last_section = next (reversed (sections ))
341
341
if re .match (r'^/\d+$' , last_section ):
342
342
sym_address = sections [last_section ]
@@ -352,8 +352,15 @@ def parse_image(self, image, syms):
352
352
353
353
# For ELF and Mach-O-derived images...
354
354
if self .offset_by_headers :
355
- base = base + self .get_field (opt , 'SizeOfHeaders' )
355
+ base = base + self .get_field (combined , 'SizeOfHeaders' )
356
356
if sym_name != self .EINVAL :
357
+ self .add_sym (sym_name , base , syms )
358
+
359
+ #
360
+ # Add symbol load command with additional processing for correct file location.
361
+ #
362
+
363
+ def add_sym (self , sym_name , base , syms ):
357
364
macho = os .path .isdir (sym_name + '.dSYM' )
358
365
if macho :
359
366
real_sym = sym_name
@@ -370,10 +377,24 @@ def parse_image(self, image, syms):
370
377
break
371
378
372
379
if real_sym :
373
- syms .append (self .get_sym_cmd (real_sym , orgbase , sections , macho , base ))
380
+ syms .append (self .get_sym_cmd (real_sym , base ))
374
381
else :
375
382
print (f'No symbol file { sym_name } ' )
376
383
384
+ #
385
+ # Use debug info from new image loader.
386
+ #
387
+
388
+ def use_new_debug_info (self , entry , syms ):
389
+ sym_address = self .get_child_member_with_name (entry , 'PdbPath' )
390
+ if sym_address :
391
+ sym_ptr = self .cast_ptr (self .ptype ('char' ), sym_address )
392
+ sym_name = UefiMisc .parse_utf8 (self .get_field (sym_ptr ))
393
+ debug_base = self .get_field (entry , 'DebugBase' )
394
+ self .add_sym (sym_name , debug_base , syms )
395
+ else :
396
+ print ('No symbol file' )
397
+
377
398
#
378
399
# Parses table EFI_DEBUG_IMAGE_INFO structures, builds
379
400
# a list of add-symbol-file commands, and reloads debugger
@@ -390,6 +411,9 @@ def parse_edii(self, edii, count):
390
411
if image_type == 1 :
391
412
entry = self .get_child_member_with_name (entry , 'NormalImage' )
392
413
self .parse_image (self .get_child_member_with_name (entry , 'LoadedImageProtocolInstance' ), syms )
414
+ elif image_type == 2 :
415
+ entry = self .get_child_member_with_name (entry , 'NormalImage2' )
416
+ self .use_new_debug_info (entry , syms )
393
417
else :
394
418
print (f'Skipping unknown EFI_DEBUG_IMAGE_INFO (ImageInfoType { image_type } )' )
395
419
index = index + 1
@@ -399,6 +423,7 @@ def parse_edii(self, edii, count):
399
423
self .debugger .HandleCommand (sym [0 ])
400
424
print (sym [1 ])
401
425
self .debugger .HandleCommand (sym [1 ])
426
+
402
427
#
403
428
# Parses EFI_DEBUG_IMAGE_INFO_TABLE_HEADER, in order to load
404
429
# image symbols.
@@ -420,7 +445,7 @@ def parse_dh(self, dh):
420
445
def parse_est (self , est ):
421
446
est_t = self .ptype ('EFI_SYSTEM_TABLE' )
422
447
est = self .cast_ptr (est_t , est )
423
- print (f"Connected to { UefiMisc .parse_utf16 (self .get_field (est , 'FirmwareVendor' ))} (Rev. 0x{ self .get_field (est , 'FirmwareRevision' ):x} " )
448
+ print (f"Connected to { UefiMisc .parse_utf16 (self .get_field (est , 'FirmwareVendor' ))} (Rev. 0x{ self .get_field (est , 'FirmwareRevision' ):x} ) " )
424
449
print (f"ConfigurationTable @ 0x{ self .get_field (est , 'ConfigurationTable' ):x} , 0x{ self .get_field (est , 'NumberOfTableEntries' ):x} entries" )
425
450
dh = self .search_config (self .get_child_member_with_name (est , 'ConfigurationTable' ), self .get_field (est , 'NumberOfTableEntries' ), self .DEBUG_GUID )
426
451
if dh == self .EINVAL :
0 commit comments