From 79e4f2a56ac7cee477c2f84ff65f766814cc1836 Mon Sep 17 00:00:00 2001 From: Ruiyu Ni Date: Wed, 29 Aug 2018 11:39:06 +0800 Subject: EmulatorPkg: formalize line endings The patch is the result of running "BaseTools/Scripts/FormatDosFiles.py EmulatorPkg/" No functionality impact. Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Ruiyu Ni Reviewed-by: Hao A Wu Cc: Liming Gao --- EmulatorPkg/Unix/lldbefi.py | 1080 +++++++++++++++++++++---------------------- 1 file changed, 540 insertions(+), 540 deletions(-) (limited to 'EmulatorPkg/Unix/lldbefi.py') diff --git a/EmulatorPkg/Unix/lldbefi.py b/EmulatorPkg/Unix/lldbefi.py index 64549ce..a130cbe 100755 --- a/EmulatorPkg/Unix/lldbefi.py +++ b/EmulatorPkg/Unix/lldbefi.py @@ -1,540 +1,540 @@ -#!/usr/bin/python - -# -# Copyright 2014 Apple Inc. All righes reserved. -# -# This program and the accompanying materials -# are licensed and made available under the terms and conditions of the BSD License -# which accompanies this distribution. The full text of the license may be found at -# http://opensource.org/licenses/bsd-license.php. -# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -# - -import lldb -import os -import uuid -import string -import commands -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 reserach 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 formating 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') - - -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 contiue - frame.GetThread().GetProcess().Continue() - - debugger = frame.thread.process.target.debugger - if frame.FindVariable ("AddSymbolFlag").GetValueAsUnsigned() == 1: - LoadAddress = frame.FindVariable ("LoadAddress").GetValueAsUnsigned() - - 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 contiue - frame.thread.process.Continue() - -def GuidToCStructStr (guid, Name=False): - # - # Convert a 16-byte bytesarry (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 formaters - 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.' +#!/usr/bin/python + +# +# Copyright 2014 Apple Inc. All righes reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php. +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# + +import lldb +import os +import uuid +import string +import commands +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 reserach 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 formating 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') + + +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 contiue + frame.GetThread().GetProcess().Continue() + + debugger = frame.thread.process.target.debugger + if frame.FindVariable ("AddSymbolFlag").GetValueAsUnsigned() == 1: + LoadAddress = frame.FindVariable ("LoadAddress").GetValueAsUnsigned() + + 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 contiue + frame.thread.process.Continue() + +def GuidToCStructStr (guid, Name=False): + # + # Convert a 16-byte bytesarry (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 formaters + 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.' -- cgit v1.1