#!/usr/bin/python | |
# | |
# Copyright 2014 Apple Inc. All rights reserved. | |
# | |
# SPDX-License-Identifier: BSD-2-Clause-Patent | |
# | |
import lldb | |
import os | |
import uuid | |
import string | |
import optparse | |
import shlex | |
guid_dict = {} | |
def EFI_GUID_TypeSummary (valobj,internal_dict): | |
""" Type summary for EFI GUID, print C Name if known | |
""" | |
# typedef struct { | |
# UINT32 Data1; | |
# UINT16 Data2; | |
# UINT16 Data3; | |
# UINT8 Data4[8]; | |
# } EFI_GUID; | |
SBError = lldb.SBError() | |
data1_val = valobj.GetChildMemberWithName('Data1') | |
data1 = data1_val.GetValueAsUnsigned(0) | |
data2_val = valobj.GetChildMemberWithName('Data2') | |
data2 = data2_val.GetValueAsUnsigned(0) | |
data3_val = valobj.GetChildMemberWithName('Data3') | |
data3 = data3_val.GetValueAsUnsigned(0) | |
str = "%x-%x-%x-" % (data1, data2, data3) | |
data4_val = valobj.GetChildMemberWithName('Data4') | |
for i in range (data4_val.num_children): | |
if i == 2: | |
str +='-' | |
str += "%02x" % data4_val.GetChildAtIndex(i).data.GetUnsignedInt8(SBError, 0) | |
return guid_dict.get (str.upper(), '') | |
EFI_STATUS_Dict = { | |
(0x8000000000000000 | 1): "Load Error", | |
(0x8000000000000000 | 2): "Invalid Parameter", | |
(0x8000000000000000 | 3): "Unsupported", | |
(0x8000000000000000 | 4): "Bad Buffer Size", | |
(0x8000000000000000 | 5): "Buffer Too Small", | |
(0x8000000000000000 | 6): "Not Ready", | |
(0x8000000000000000 | 7): "Device Error", | |
(0x8000000000000000 | 8): "Write Protected", | |
(0x8000000000000000 | 9): "Out of Resources", | |
(0x8000000000000000 | 10): "Volume Corrupt", | |
(0x8000000000000000 | 11): "Volume Full", | |
(0x8000000000000000 | 12): "No Media", | |
(0x8000000000000000 | 13): "Media changed", | |
(0x8000000000000000 | 14): "Not Found", | |
(0x8000000000000000 | 15): "Access Denied", | |
(0x8000000000000000 | 16): "No Response", | |
(0x8000000000000000 | 17): "No mapping", | |
(0x8000000000000000 | 18): "Time out", | |
(0x8000000000000000 | 19): "Not started", | |
(0x8000000000000000 | 20): "Already started", | |
(0x8000000000000000 | 21): "Aborted", | |
(0x8000000000000000 | 22): "ICMP Error", | |
(0x8000000000000000 | 23): "TFTP Error", | |
(0x8000000000000000 | 24): "Protocol Error", | |
0 : "Success", | |
1 : "Warning Unknown Glyph", | |
2 : "Warning Delete Failure", | |
3 : "Warning Write Failure", | |
4 : "Warning Buffer Too Small", | |
(0x80000000 | 1): "Load Error", | |
(0x80000000 | 2): "Invalid Parameter", | |
(0x80000000 | 3): "Unsupported", | |
(0x80000000 | 4): "Bad Buffer Size", | |
(0x80000000 | 5): "Buffer Too Small", | |
(0x80000000 | 6): "Not Ready", | |
(0x80000000 | 7): "Device Error", | |
(0x80000000 | 8): "Write Protected", | |
(0x80000000 | 9): "Out of Resources", | |
(0x80000000 | 10): "Volume Corrupt", | |
(0x80000000 | 11): "Volume Full", | |
(0x80000000 | 12): "No Media", | |
(0x80000000 | 13): "Media changed", | |
(0x80000000 | 14): "Not Found", | |
(0x80000000 | 15): "Access Denied", | |
(0x80000000 | 16): "No Response", | |
(0x80000000 | 17): "No mapping", | |
(0x80000000 | 18): "Time out", | |
(0x80000000 | 19): "Not started", | |
(0x80000000 | 20): "Already started", | |
(0x80000000 | 21): "Aborted", | |
(0x80000000 | 22): "ICMP Error", | |
(0x80000000 | 23): "TFTP Error", | |
(0x80000000 | 24): "Protocol Error", | |
} | |
def EFI_STATUS_TypeSummary (valobj,internal_dict): | |
# | |
# Return summary string for EFI_STATUS from dictionary | |
# | |
Status = valobj.GetValueAsUnsigned(0) | |
return EFI_STATUS_Dict.get (Status, '') | |
def EFI_TPL_TypeSummary (valobj,internal_dict): | |
# | |
# Return TPL values | |
# | |
if valobj.TypeIsPointerType(): | |
return "" | |
Tpl = valobj.GetValueAsUnsigned(0) | |
if Tpl < 4: | |
Str = "%d" % Tpl | |
elif Tpl == 6: | |
Str = "TPL_DRIVER (Obsolete Concept in edk2)" | |
elif Tpl < 8: | |
Str = "TPL_APPLICATION" | |
if Tpl - 4 > 0: | |
Str += " + " + "%d" % (Tpl - 4) | |
elif Tpl < 16: | |
Str = "TPL_CALLBACK" | |
if Tpl - 8 > 0: | |
Str += " + " + "%d" % (Tpl - 4) | |
elif Tpl < 31: | |
Str = "TPL_NOTIFY" | |
if Tpl - 16 > 0: | |
Str += " + " + "%d" % (Tpl - 4) | |
elif Tpl == 31: | |
Str = "TPL_HIGH_LEVEL" | |
else: | |
Str = "Invalid TPL" | |
return Str | |
def CHAR16_TypeSummary (valobj,internal_dict): | |
# | |
# Display EFI CHAR16 'unsigned short' as string | |
# | |
SBError = lldb.SBError() | |
Str = '' | |
if valobj.TypeIsPointerType(): | |
if valobj.GetValueAsUnsigned () == 0: | |
return "NULL" | |
# CHAR16 * max string size 1024 | |
for i in range (1024): | |
Char = valobj.GetPointeeData(i,1).GetUnsignedInt16(SBError, 0) | |
if SBError.fail or Char == 0: | |
break | |
Str += unichr (Char) | |
Str = 'L"' + Str + '"' | |
return Str.encode ('utf-8', 'replace') | |
if valobj.num_children == 0: | |
# CHAR16 | |
if chr (valobj.unsigned) in string.printable: | |
Str = "L'" + unichr (valobj.unsigned) + "'" | |
return Str.encode ('utf-8', 'replace') | |
else: | |
# CHAR16 [] | |
for i in range (valobj.num_children): | |
Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt16(SBError, 0) | |
if Char == 0: | |
break | |
Str += unichr (Char) | |
Str = 'L"' + Str + '"' | |
return Str.encode ('utf-8', 'replace') | |
return Str | |
def CHAR8_TypeSummary (valobj,internal_dict): | |
# | |
# Display EFI CHAR8 'signed char' as string | |
# unichr() is used as a junk string can produce an error message like this: | |
# UnicodeEncodeError: 'ascii' codec can't encode character u'\x90' in position 1: ordinal not in range(128) | |
# | |
SBError = lldb.SBError() | |
Str = '' | |
if valobj.TypeIsPointerType(): | |
if valobj.GetValueAsUnsigned () == 0: | |
return "NULL" | |
# CHAR8 * max string size 1024 | |
for i in range (1024): | |
Char = valobj.GetPointeeData(i,1).GetUnsignedInt8(SBError, 0) | |
if SBError.fail or Char == 0: | |
break | |
Str += unichr (Char) | |
Str = '"' + Str + '"' | |
return Str.encode ('utf-8', 'replace') | |
if valobj.num_children == 0: | |
# CHAR8 | |
if chr (valobj.unsigned) in string.printable: | |
Str = '"' + unichr (valobj.unsigned) + '"' | |
return Str.encode ('utf-8', 'replace') | |
else: | |
# CHAR8 [] | |
for i in range (valobj.num_children): | |
Char = valobj.GetChildAtIndex(i).data.GetUnsignedInt8(SBError, 0) | |
if Char == 0: | |
break | |
Str += unichr (Char) | |
Str = '"' + Str + '"' | |
return Str.encode ('utf-8', 'replace') | |
return Str | |
device_path_dict = { | |
(0x01, 0x01): "PCI_DEVICE_PATH", | |
(0x01, 0x02): "PCCARD_DEVICE_PATH", | |
(0x01, 0x03): "MEMMAP_DEVICE_PATH", | |
(0x01, 0x04): "VENDOR_DEVICE_PATH", | |
(0x01, 0x05): "CONTROLLER_DEVICE_PATH", | |
(0x02, 0x01): "ACPI_HID_DEVICE_PATH", | |
(0x02, 0x02): "ACPI_EXTENDED_HID_DEVICE_PATH", | |
(0x02, 0x03): "ACPI_ADR_DEVICE_PATH", | |
(0x03, 0x01): "ATAPI_DEVICE_PATH", | |
(0x03, 0x12): "SATA_DEVICE_PATH", | |
(0x03, 0x02): "SCSI_DEVICE_PATH", | |
(0x03, 0x03): "FIBRECHANNEL_DEVICE_PATH", | |
(0x03, 0x04): "F1394_DEVICE_PATH", | |
(0x03, 0x05): "USB_DEVICE_PATH", | |
(0x03, 0x0f): "USB_CLASS_DEVICE_PATH", | |
(0x03, 0x10): "FW_SBP2_UNIT_LUN_DEVICE_PATH", | |
(0x03, 0x11): "DEVICE_LOGICAL_UNIT_DEVICE_PATH", | |
(0x03, 0x06): "I2O_DEVICE_PATH", | |
(0x03, 0x0b): "MAC_ADDR_DEVICE_PATH", | |
(0x03, 0x0c): "IPv4_DEVICE_PATH", | |
(0x03, 0x09): "INFINIBAND_DEVICE_PATH", | |
(0x03, 0x0e): "UART_DEVICE_PATH", | |
(0x03, 0x0a): "VENDOR_DEVICE_PATH", | |
(0x03, 0x13): "ISCSI_DEVICE_PATH", | |
(0x04, 0x01): "HARDDRIVE_DEVICE_PATH", | |
(0x04, 0x02): "CDROM_DEVICE_PATH", | |
(0x04, 0x03): "VENDOR_DEVICE_PATH", | |
(0x04, 0x04): "FILEPATH_DEVICE_PATH", | |
(0x04, 0x05): "MEDIA_PROTOCOL_DEVICE_PATH", | |
(0x05, 0x01): "BBS_BBS_DEVICE_PATH", | |
(0x7F, 0xFF): "EFI_DEVICE_PATH_PROTOCOL", | |
(0xFF, 0xFF): "EFI_DEVICE_PATH_PROTOCOL", | |
} | |
def EFI_DEVICE_PATH_PROTOCOL_TypeSummary (valobj,internal_dict): | |
# | |
# | |
# | |
if valobj.TypeIsPointerType(): | |
# EFI_DEVICE_PATH_PROTOCOL * | |
return "" | |
Str = "" | |
if valobj.num_children == 3: | |
# EFI_DEVICE_PATH_PROTOCOL | |
Type = valobj.GetChildMemberWithName('Type').unsigned | |
SubType = valobj.GetChildMemberWithName('SubType').unsigned | |
if (Type, SubType) in device_path_dict: | |
TypeStr = device_path_dict[Type, SubType] | |
else: | |
TypeStr = "" | |
LenLow = valobj.GetChildMemberWithName('Length').GetChildAtIndex(0).unsigned | |
LenHigh = valobj.GetChildMemberWithName('Length').GetChildAtIndex(1).unsigned | |
Len = LenLow + (LenHigh >> 8) | |
Address = long ("%d" % valobj.addr) | |
if (Address == lldb.LLDB_INVALID_ADDRESS): | |
# Need to research this, it seems to be the nested struct case | |
ExprStr = "" | |
elif (Type & 0x7f == 0x7f): | |
ExprStr = "End Device Path" if SubType == 0xff else "End This Instance" | |
else: | |
ExprStr = "expr *(%s *)0x%08x" % (TypeStr, Address) | |
Str = " {\n" | |
Str += " (UINT8) Type = 0x%02x // %s\n" % (Type, "END" if (Type & 0x7f == 0x7f) else "") | |
Str += " (UINT8) SubType = 0x%02x // %s\n" % (SubType, ExprStr) | |
Str += " (UINT8 [2]) Length = { // 0x%04x (%d) bytes\n" % (Len, Len) | |
Str += " (UINT8) [0] = 0x%02x\n" % LenLow | |
Str += " (UINT8) [1] = 0x%02x\n" % LenHigh | |
Str += " }\n" | |
if (Type & 0x7f == 0x7f) and (SubType == 0xff): | |
pass | |
elif ExprStr != "": | |
NextNode = Address + Len | |
Str += "// Next node 'expr *(EFI_DEVICE_PATH_PROTOCOL *)0x%08x'\n" % NextNode | |
return Str | |
def TypePrintFormating(debugger): | |
# | |
# Set the default print formatting for EFI types in lldb. | |
# seems lldb defaults to decimal. | |
# | |
category = debugger.GetDefaultCategory() | |
FormatBool = lldb.SBTypeFormat(lldb.eFormatBoolean) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("BOOLEAN"), FormatBool) | |
FormatHex = lldb.SBTypeFormat(lldb.eFormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT64"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT64"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT32"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT32"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT16"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT16"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINT8"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("INT8"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("UINTN"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("INTN"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR8"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("CHAR16"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_PHYSICAL_ADDRESS"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("PHYSICAL_ADDRESS"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_STATUS"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_TPL"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_LBA"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_BOOT_MODE"), FormatHex) | |
category.AddTypeFormat(lldb.SBTypeNameSpecifier("EFI_FV_FILETYPE"), FormatHex) | |
# | |
# Smart type printing for EFI | |
# | |
debugger.HandleCommand("type summary add EFI_GUID --python-function lldbefi.EFI_GUID_TypeSummary") | |
debugger.HandleCommand("type summary add EFI_STATUS --python-function lldbefi.EFI_STATUS_TypeSummary") | |
debugger.HandleCommand("type summary add EFI_TPL --python-function lldbefi.EFI_TPL_TypeSummary") | |
debugger.HandleCommand("type summary add EFI_DEVICE_PATH_PROTOCOL --python-function lldbefi.EFI_DEVICE_PATH_PROTOCOL_TypeSummary") | |
debugger.HandleCommand("type summary add CHAR16 --python-function lldbefi.CHAR16_TypeSummary") | |
debugger.HandleCommand('type summary add --regex "CHAR16 \[[0-9]+\]" --python-function lldbefi.CHAR16_TypeSummary') | |
debugger.HandleCommand("type summary add CHAR8 --python-function lldbefi.CHAR8_TypeSummary") | |
debugger.HandleCommand('type summary add --regex "CHAR8 \[[0-9]+\]" --python-function lldbefi.CHAR8_TypeSummary') | |
debugger.HandleCommand( | |
'setting set frame-format "frame #${frame.index}: ${frame.pc}' | |
'{ ${module.file.basename}{:${function.name}()${function.pc-offset}}}' | |
'{ at ${line.file.fullpath}:${line.number}}\n"' | |
) | |
gEmulatorBreakWorkaroundNeeded = True | |
def LoadEmulatorEfiSymbols(frame, bp_loc , internal_dict): | |
# | |
# This is an lldb breakpoint script, and assumes the breakpoint is on a | |
# function with the same prototype as SecGdbScriptBreak(). The | |
# argument names are important as lldb looks them up. | |
# | |
# VOID | |
# SecGdbScriptBreak ( | |
# char *FileName, | |
# int FileNameLength, | |
# long unsigned int LoadAddress, | |
# int AddSymbolFlag | |
# ) | |
# { | |
# return; | |
# } | |
# | |
# When the emulator loads a PE/COFF image, it calls the stub function with | |
# the filename of the symbol file, the length of the FileName, the | |
# load address and a flag to indicate if this is a load or unload operation | |
# | |
global gEmulatorBreakWorkaroundNeeded | |
if gEmulatorBreakWorkaroundNeeded: | |
# turn off lldb debug prints on SIGALRM (EFI timer tick) | |
frame.thread.process.target.debugger.HandleCommand("process handle SIGALRM -n false") | |
gEmulatorBreakWorkaroundNeeded = False | |
# Convert C string to Python string | |
Error = lldb.SBError() | |
FileNamePtr = frame.FindVariable ("FileName").GetValueAsUnsigned() | |
FileNameLen = frame.FindVariable ("FileNameLength").GetValueAsUnsigned() | |
FileName = frame.thread.process.ReadCStringFromMemory (FileNamePtr, FileNameLen, Error) | |
if not Error.Success(): | |
print("!ReadCStringFromMemory() did not find a %d byte C string at %x" % (FileNameLen, FileNamePtr)) | |
# make breakpoint command continue | |
return False | |
debugger = frame.thread.process.target.debugger | |
if frame.FindVariable ("AddSymbolFlag").GetValueAsUnsigned() == 1: | |
LoadAddress = frame.FindVariable ("LoadAddress").GetValueAsUnsigned() - 0x240 | |
debugger.HandleCommand ("target modules add %s" % FileName) | |
print("target modules load --slid 0x%x %s" % (LoadAddress, FileName)) | |
debugger.HandleCommand ("target modules load --slide 0x%x --file %s" % (LoadAddress, FileName)) | |
else: | |
target = debugger.GetSelectedTarget() | |
for SBModule in target.module_iter(): | |
ModuleName = SBModule.GetFileSpec().GetDirectory() + '/' | |
ModuleName += SBModule.GetFileSpec().GetFilename() | |
if FileName == ModuleName or FileName == SBModule.GetFileSpec().GetFilename(): | |
target.ClearModuleLoadAddress (SBModule) | |
if not target.RemoveModule (SBModule): | |
print("!lldb.target.RemoveModule (%s) FAILED" % SBModule) | |
# make breakpoint command continue | |
return False | |
def GuidToCStructStr (guid, Name=False): | |
# | |
# Convert a 16-byte bytesarray (or bytearray compat object) to C guid string | |
# { 0xB402621F, 0xA940, 0x1E4A, { 0x86, 0x6B, 0x4D, 0xC9, 0x16, 0x2B, 0x34, 0x7C } } | |
# | |
# Name=True means lookup name in GuidNameDict and us it if you find it | |
# | |
if not isinstance (guid, bytearray): | |
# convert guid object to UUID, and UUID to bytearray | |
Uuid = uuid.UUID(guid) | |
guid = bytearray (Uuid.bytes_le) | |
return "{ 0x%02.2X%02.2X%02.2X%02.2X, 0x%02.2X%02.2X, 0x%02.2X%02.2X, { 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X, 0x%02.2X } }" % \ | |
(guid[3], guid[2], guid[1], guid[0], guid[5], guid[4], guid[7], guid[6], guid[8], guid[9], guid[10], guid[11], guid[12], guid[13], guid[14], guid[15]) | |
def ParseGuidString(GuidStr): | |
# | |
# Error check and convert C Guid init to string | |
# ParseGuidString("49152E77-1ADA-4764-B7A2-7AFEFED95E8B") | |
# ParseGuidString("{ 0xBA24B391, 0x73FD, 0xC54C, { 0x9E, 0xAF, 0x0C, 0xA7, 0x8A, 0x35, 0x46, 0xD1 } }") | |
# | |
if "{" in GuidStr : | |
# convert C form "{ 0xBA24B391, 0x73FD, 0xC54C, { 0x9E, 0xAF, 0x0C, 0xA7, 0x8A, 0x35, 0x46, 0xD1 } }" | |
# to string form BA24B391-73FD-C54C-9EAF-0CA78A3546D1 | |
# make a list of Hex numbers like: ['0xBA24B391', '0x73FD', '0xC54C', '0x9E', '0xAF', '0x0C', '0xA7', '0x8A', '0x35', '0x46', '0xD1'] | |
Hex = ''.join(x for x in GuidStr if x not in '{,}').split() | |
Str = "%08X-%04X-%04X-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X" % \ | |
(int(Hex[0], 0), int(Hex[1], 0), int(Hex[2], 0), int(Hex[3], 0), int(Hex[4], 0), \ | |
int(Hex[5], 0), int(Hex[6], 0), int(Hex[7], 0), int(Hex[8], 0), int(Hex[9], 0), int(Hex[10], 0)) | |
elif GuidStr.count('-') == 4: | |
# validate "49152E77-1ADA-4764-B7A2-7AFEFED95E8B" form | |
Check = "%s" % str(uuid.UUID(GuidStr)).upper() | |
if GuidStr.upper() == Check: | |
Str = GuidStr.upper() | |
else: | |
Ste = "" | |
else: | |
Str = "" | |
return Str | |
def create_guid_options(): | |
usage = "usage: %prog [data]" | |
description='''lookup EFI_GUID by CName, C struct, or GUID string and print out all three. | |
''' | |
parser = optparse.OptionParser(description=description, prog='guid',usage=usage) | |
return parser | |
def efi_guid_command(debugger, command, result, dict): | |
# Use the Shell Lexer to properly parse up command options just like a | |
# shell would | |
command_args = shlex.split(command) | |
parser = create_guid_options() | |
try: | |
(options, args) = parser.parse_args(command_args) | |
if len(args) >= 1: | |
if args[0] == "{": | |
# caller forgot to quote the string" | |
# mark arg[0] a string containing all args[n] | |
args[0] = ' '.join(args) | |
GuidStr = ParseGuidString (args[0]) | |
if GuidStr == "": | |
# return Key of GuidNameDict for value args[0] | |
GuidStr = [Key for Key, Value in guid_dict.iteritems() if Value == args[0]][0] | |
GuidStr = GuidStr.upper() | |
except: | |
# if you don't handle exceptions, passing an incorrect argument to the OptionParser will cause LLDB to exit | |
# (courtesy of OptParse dealing with argument errors by throwing SystemExit) | |
result.SetError ("option parsing failed") | |
return | |
if len(args) >= 1: | |
if GuidStr in guid_dict: | |
print("%s = %s" % (guid_dict[GuidStr], GuidStr)) | |
print("%s = %s" % (guid_dict[GuidStr], GuidToCStructStr (GuidStr))) | |
else: | |
print(GuidStr) | |
else: | |
# dump entire dictionary | |
width = max(len(v) for k,v in guid_dict.iteritems()) | |
for value in sorted(guid_dict, key=guid_dict.get): | |
print('%-*s %s %s' % (width, guid_dict[value], value, GuidToCStructStr(value))) | |
return | |
# | |
########## Code that runs when this script is imported into LLDB ########### | |
# | |
def __lldb_init_module (debugger, internal_dict): | |
# This initializer is being run from LLDB in the embedded command interpreter | |
# Make the options so we can generate the help text for the new LLDB | |
# command line command prior to registering it with LLDB below | |
global guid_dict | |
# Source Guid.xref file if we can find it | |
inputfile = os.getcwd() | |
inputfile += os.sep + os.pardir + os.sep + 'FV' + os.sep + 'Guid.xref' | |
with open(inputfile) as f: | |
for line in f: | |
data = line.split(' ') | |
if len(data) >= 2: | |
guid_dict[data[0].upper()] = data[1].strip('\n') | |
# init EFI specific type formatters | |
TypePrintFormating (debugger) | |
# add guid command | |
parser = create_guid_options() | |
efi_guid_command.__doc__ = parser.format_help() | |
debugger.HandleCommand('command script add -f lldbefi.efi_guid_command guid') | |
Target = debugger.GetTargetAtIndex(0) | |
if Target: | |
Breakpoint = Target.BreakpointCreateByName('SecGdbScriptBreak') | |
if Breakpoint.GetNumLocations() == 1: | |
# Set the emulator breakpoints, if we are in the emulator | |
debugger.HandleCommand("breakpoint command add -s python -F lldbefi.LoadEmulatorEfiSymbols {id}".format(id=Breakpoint.GetID())) | |
print('Type r to run emulator. SecLldbScriptBreak armed. EFI modules should now get source level debugging in the emulator.') |