ArmPlatformPkg/Scripts: Added ARM DS-5 scripts to debug UEFI

These scripts allow to automatically load the symbols using either the
report file created by the BaseTools or using the memory regions
defined in the arguments.

This is the scripts for DS-5 prior to DS5 v5.12.

Signed-off-by: Olivier Martin <olivier.martin@arm.com>



git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13874 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
oliviermartin 2012-10-22 14:01:38 +00:00
parent 6f6c7857c2
commit a8e812dea5
5 changed files with 792 additions and 0 deletions

View File

@ -0,0 +1,54 @@
#
# Copyright (c) 2011-2012, ARM Limited. All rights 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 re
class BuildReport:
PCDs = {}
def parse_platform_summary(self, file):
pass
def parse_pcd_report(self, report_file):
pcd_reg = re.compile(" (\*P|\*F|\*M| ) (\w+)(\ +)\: (.*) \((\w+)\) = (.*)\n")
for line in report_file.xreadlines():
stripped_line = line.strip()
if re.match("\<=+\>", stripped_line):
return
elif re.match("g.*Guid", stripped_line):
guid = stripped_line
self.PCDs[guid] = {}
else:
m = pcd_reg.match(line)
if m:
self.PCDs[guid][m.group(2)] = (m.group(6).strip(),m.group(5))
def parse_firmware_device(self, file):
pass
def parse_module_summary(self, file):
#print "Module Summary"
pass
CONST_SECTION_HEADERS = [('Platform Summary', parse_platform_summary),
('Platform Configuration Database Report',parse_pcd_report),
('Firmware Device (FD)',parse_firmware_device),
('Module Summary',parse_module_summary)]
def __init__(self, filename = 'report.log'):
report_file = open(filename, 'r')
for line in report_file.xreadlines():
for section_header in BuildReport.CONST_SECTION_HEADERS:
if line.strip() == section_header[0]:
section_header[1](self, report_file)
#print self.PCDs

View File

@ -0,0 +1,100 @@
#
# Copyright (c) 2011-2012, ARM Limited. All rights 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.
#
from arm_ds.debugger_v1 import Debugger
from arm_ds.debugger_v1 import DebugException
import re, sys, getopt
import edk2_debugger
# Reload external classes
reload(edk2_debugger)
def usage():
print "-a,--all: Load all symbols"
print "-l,--report=: Filename for the EDK2 report log"
print "-m,--sysmem=(base,size): System Memory region"
print "-f,--fv=(base,size): Firmware region"
print "-r,--rom=(base,size): ROM region"
load_all = False
report_file = None
regions = []
opts,args = getopt.getopt(sys.argv[1:], "har:vm:vr:vf:v", ["help","all","report=","sysmem=","rom=","fv="])
if (opts is None) or (not opts):
report_file = '../../../report.log'
else:
region_reg = re.compile("\((.*),(.*)\)")
base_reg = re.compile("(.*)")
for o,a in opts:
region_type = None
regex = None
m = None
if o in ("-h","--help"):
usage()
sys.exit()
elif o in ("-a","--all"):
load_all = True
elif o in ("-l","--report"):
report_file = a
elif o in ("-m","--sysmem"):
region_type = edk2_debugger.ArmPlatformDebugger.REGION_TYPE_SYSMEM
regex = region_reg
elif o in ("-f","--fv"):
region_type = edk2_debugger.ArmPlatformDebugger.REGION_TYPE_FV
regex = region_reg
elif o in ("-r","--rom"):
region_type = edk2_debugger.ArmPlatformDebugger.REGION_TYPE_ROM
regex = region_reg
else:
assert False, "Unhandled option"
if region_type:
m = regex.match(a)
if m:
if regex.groups == 1:
regions.append((region_type,int(m.group(1),0),0))
else:
regions.append((region_type,int(m.group(1),0),int(m.group(2),0)))
else:
if regex.groups == 1:
raise Exception('cmd_load_symbols', "Expect a base address")
else:
raise Exception('cmd_load_symbols', "Expect a region format as (base,size)")
# Debugger object for accessing the debugger
debugger = Debugger()
# Initialisation commands
ec = debugger.getExecutionContext(0)
ec.getExecutionService().stop()
ec.getExecutionService().waitForStop()
# in case the execution context reference is out of date
ec = debugger.getExecutionContext(0)
armplatform_debugger = edk2_debugger.ArmPlatformDebugger(ec, report_file, regions)
try:
armplatform_debugger = edk2_debugger.ArmPlatformDebugger(ec, report_file, regions)
if load_all:
armplatform_debugger.load_all_symbols()
else:
armplatform_debugger.load_current_symbols()
except IOError, (ErrorNumber, ErrorMessage):
print "Error: %s" % ErrorMessage
except Exception, (ErrorClass, ErrorMessage):
print "Error(%s): %s" % (ErrorClass, ErrorMessage)
except DebugException, de:
print "DebugError: %s" % (de.getMessage())

View File

@ -0,0 +1,212 @@
#
# Copyright (c) 2011-2012, ARM Limited. All rights 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 os
import firmware_volume
import build_report
import system_table
# Reload external classes
reload(firmware_volume)
reload(build_report)
reload(system_table)
def readMem32(executionContext, address):
bytes = executionContext.getMemoryService().read(address, 4, 32)
return struct.unpack('<I',bytes)[0]
def dump_fv(ec, fv_base, fv_size):
fv = firmware_volume.FirmwareVolume(ec,
int(build.PCDs['gArmTokenSpaceGuid']['PcdFvBaseAddress'][0],16),
int(build.PCDs['gArmTokenSpaceGuid']['PcdFvSize'][0],16))
ffs = fv.get_next_ffs()
while ffs != None:
print "# %s" % ffs
section = ffs.get_next_section()
while section != None:
print "\t%s" % section
try:
print "\t\t- %s" % section.get_debug_filepath()
except Exception:
pass
section = ffs.get_next_section(section)
ffs = fv.get_next_ffs(ffs)
def dump_system_table(ec, mem_base, mem_size):
st = system_table.SystemTable(ec, mem_base, mem_size)
debug_info_table_base = st.get_configuration_table(system_table.DebugInfoTable.CONST_DEBUG_INFO_TABLE_GUID)
debug_info_table = system_table.DebugInfoTable(ec, debug_info_table_base)
debug_info_table.dump()
def load_symbol_from_file(ec, filename, address):
try:
ec.executeDSCommand("discard-symbol-file \'%s\'" % filename)
except:
pass
ec.executeDSCommand("add-symbol-file \'%s\' 0x%X" % (filename, address))
class ArmPlatform:
def __init__(self, sysmembase=None, sysmemsize=None, fvs={}):
self.sysmembase = sysmembase
self.sysmemsize = sysmemsize
self.fvs = fvs
class ArmPlatformDebugger:
system_table = None
firmware_volumes = {}
REGION_TYPE_SYSMEM = 1
REGION_TYPE_ROM = 2
REGION_TYPE_FV = 3
def __init__(self, ec, report_log, regions):
self.ec = ec
fvs = []
sysmem_base = None
sysmem_size = None
if report_log and os.path.isfile(report_log):
try:
self.build = build_report.BuildReport(report_log)
except IOError:
raise IOError(2, 'Report \'%s\' isnot valid' % report_log)
# Generate list of supported Firmware Volumes
if self.build.PCDs['gArmTokenSpaceGuid'].has_key('PcdFvSize') and int(self.build.PCDs['gArmTokenSpaceGuid']['PcdFvSize'][0],16) != 0:
fvs.append((int(self.build.PCDs['gArmTokenSpaceGuid']['PcdFvBaseAddress'][0],16),int(self.build.PCDs['gArmTokenSpaceGuid']['PcdFvSize'][0],16)))
if self.build.PCDs['gArmTokenSpaceGuid'].has_key('PcdSecureFvSize') and int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSecureFvSize'][0],16) != 0:
fvs.append((int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSecureFvBaseAddress'][0],16),int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSecureFvSize'][0],16)))
if self.build.PCDs['gArmTokenSpaceGuid'].has_key('PcdHypFvSize') and int(self.build.PCDs['gArmTokenSpaceGuid']['PcdHypFvSize'][0],16) != 0:
fvs.append((int(self.build.PCDs['gArmTokenSpaceGuid']['PcdHypFvBaseAddress'][0],16),int(self.build.PCDs['gArmTokenSpaceGuid']['PcdHypFvSize'][0],16)))
sysmem_base = int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSystemMemoryBase'][0],16)
sysmem_size = int(self.build.PCDs['gArmTokenSpaceGuid']['PcdSystemMemorySize'][0],16)
else:
for region in regions:
if region[0] == ArmPlatformDebugger.REGION_TYPE_SYSMEM:
sysmem_base = region[1]
sysmem_size = region[2]
elif region[0] == ArmPlatformDebugger.REGION_TYPE_FV:
fvs.append((region[1],region[2]))
elif region[0] == ArmPlatformDebugger.REGION_TYPE_ROM:
for base in xrange(region[1], region[1] + region[2], 0x400000):
signature = struct.unpack("cccc", self.ec.getMemoryService().read(base, 4, 32))
if signature == FirmwareVolume.CONST_FV_SIGNATURE:
fvs.append((base,0))
else:
print "Region type '%d' Not Supported" % region[0]
self.platform = ArmPlatform(sysmem_base, sysmem_size, fvs)
def in_sysmem(self, addr):
return (self.platform.sysmembase is not None) and (self.platform.sysmembase <= addr) and (addr < self.platform.sysmembase + self.platform.sysmemsize)
def in_fv(self, addr):
return (self.get_fv_at(addr) != None)
def get_fv_at(self, addr):
for fv in self.platform.fvs:
if (fv[0] <= addr) and (addr < fv[0] + fv[1]):
return fv
return None
def load_current_symbols(self):
pc = int(self.ec.getRegisterService().getValue('PC')) & 0xFFFFFFFF
if self.in_fv(pc):
debug_infos = []
(fv_base, fv_size) = self.get_fv_at(pc)
if self.firmware_volumes.has_key(fv_base) == False:
self.firmware_volumes[fv_base] = firmware_volume.FirmwareVolume(self.ec, fv_base, fv_size)
stack_frame = self.ec.getTopLevelStackFrame()
info = self.firmware_volumes[fv_base].load_symbols_at(int(stack_frame.getRegisterService().getValue('PC')) & 0xFFFFFFFF)
debug_infos.append(info)
while stack_frame.next() is not None:
stack_frame = stack_frame.next()
# Stack frame attached to 'PC'
pc = int(stack_frame.getRegisterService().getValue('PC')) & 0xFFFFFFFF
# Check if the symbols for this stack frame have already been loaded
found = False
for debug_info in debug_infos:
if (pc >= debug_info[0]) and (pc < debug_info[0] + debug_info[1]):
found = True
if found == False:
info = self.firmware_volumes[fv_base].load_symbols_at(pc)
debug_infos.append(info)
#self.firmware_volumes[fv_base].load_symbols_at(pc)
elif self.in_sysmem(pc):
debug_infos = []
if self.system_table is None:
# Find the System Table
self.system_table = system_table.SystemTable(self.ec, self.platform.sysmembase, self.platform.sysmemsize)
# Find the Debug Info Table
debug_info_table_base = self.system_table.get_configuration_table(system_table.DebugInfoTable.CONST_DEBUG_INFO_TABLE_GUID)
self.debug_info_table = system_table.DebugInfoTable(self.ec, debug_info_table_base)
stack_frame = self.ec.getTopLevelStackFrame()
info = self.debug_info_table.load_symbols_at(int(stack_frame.getRegisterService().getValue('PC')) & 0xFFFFFFFF)
debug_infos.append(info)
while stack_frame.next() is not None:
stack_frame = stack_frame.next()
# Stack frame attached to 'PC'
pc = int(stack_frame.getRegisterService().getValue('PC')) & 0xFFFFFFFF
# Check if the symbols for this stack frame have already been loaded
found = False
for debug_info in debug_infos:
if (pc >= debug_info[0]) and (pc < debug_info[0] + debug_info[1]):
found = True
if found == False:
info = self.debug_info_table.load_symbols_at(pc)
debug_infos.append(info)
#self.debug_info_table.load_symbols_at(pc)
else:
raise Exception('ArmPlatformDebugger', "Not supported region")
def load_all_symbols(self):
# Load all the XIP symbols attached to the Firmware Volume
for (fv_base, fv_size) in self.platform.fvs:
if self.firmware_volumes.has_key(fv_base) == False:
self.firmware_volumes[fv_base] = firmware_volume.FirmwareVolume(self.ec, fv_base, fv_size)
self.firmware_volumes[fv_base].load_all_symbols()
try:
# Load all symbols of module loaded into System Memory
if self.system_table is None:
# Find the System Table
self.system_table = system_table.SystemTable(self.ec, self.platform.sysmembase, self.platform.sysmemsize)
# Find the Debug Info Table
debug_info_table_base = self.system_table.get_configuration_table(system_table.DebugInfoTable.CONST_DEBUG_INFO_TABLE_GUID)
self.debug_info_table = system_table.DebugInfoTable(self.ec, debug_info_table_base)
self.debug_info_table.load_all_symbols()
except:
# Debugger exception could be excepted if DRAM has not been initialized or if we have not started to run from DRAM yet
print "Note: no symbols have been found in System Memory (possible cause: the UEFI permanent memory has been installed yet)"
pass

View File

@ -0,0 +1,299 @@
#
# Copyright (c) 2011-2012, ARM Limited. All rights 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.
#
from arm_ds.debugger_v1 import DebugException
import struct
import string
class EfiFileSection(object):
EFI_SECTION_PE32 = 0x10
EFI_SECTION_PIC = 0x11
EFI_SECTION_TE = 0x12
EFI_IMAGE_DEBUG_TYPE_CODEVIEW = 0x2
SIZEOF_EFI_FFS_FILE_HEADER = 0x28
def __init__(self, ec, base):
self.base = base
self.ec = ec
def __str__(self):
return "FileSection(type:0x%X, size:0x%x)" % (self.get_type(), self.get_size())
def get_base(self):
return self.base
def get_type(self):
return struct.unpack("B", self.ec.getMemoryService().read(self.base + 0x3, 1, 8))[0]
def get_size(self):
return (struct.unpack("<I", self.ec.getMemoryService().read(self.base, 4, 32))[0] & 0x00ffffff)
def get_debug_filepath(self):
type = self.get_type()
if type == EfiFileSection.EFI_SECTION_TE:
section = EfiSectionTE(self, ec, self.base + 0x4)
elif type == EfiFileSection.EFI_SECTION_PE32:
section = EfiSectionPE32(self, ec, self.base + 0x4)
else:
raise Exception("EfiFileSection", "No debug section")
return section.get_debug_filepath()
class EfiSectionTE:
SIZEOF_EFI_TE_IMAGE_HEADER = 0x28
EFI_TE_IMAGE_SIGNATURE = ('V','Z')
def __init__(self, ec, base_te):
self.ec = ec
self.base_te = int(base_te)
te_sig = struct.unpack("cc", self.ec.getMemoryService().read(self.base_te, 2, 32))
if te_sig != EfiSectionTE.EFI_TE_IMAGE_SIGNATURE:
raise Exception("EfiFileSectionTE","TE Signature incorrect")
def get_debug_filepath(self):
stripped_size = struct.unpack("<H", self.ec.getMemoryService().read(self.base_te + 0x6, 2, 32))[0]
stripped_size -= EfiSectionTE.SIZEOF_EFI_TE_IMAGE_HEADER
debug_dir_entry_rva = self.ec.getMemoryService().readMemory32(self.base_te + 0x20)
if debug_dir_entry_rva == 0:
raise Exception("EfiFileSectionTE","No debug directory for image")
debug_dir_entry_rva -= stripped_size
debug_type = self.ec.getMemoryService().readMemory32(self.base_te + debug_dir_entry_rva + 0xC)
if (debug_type != 0xdf) and (debug_type != EfiFileSection.EFI_IMAGE_DEBUG_TYPE_CODEVIEW):
raise Exception("EfiFileSectionTE","Debug type is not dwarf")
debug_rva = self.ec.getMemoryService().readMemory32(self.base_te + debug_dir_entry_rva + 0x14)
debug_rva -= stripped_size
dwarf_sig = struct.unpack("cccc", self.ec.getMemoryService().read(self.base_te + debug_rva, 4, 32))
if (dwarf_sig != 0x66727764) and (dwarf_sig != FirmwareFile.CONST_NB10_SIGNATURE):
raise Exception("EfiFileSectionTE","Dwarf debug signature not found")
if dwarf_sig == 0x66727764:
filename = self.base_te + debug_rva + 0xc
else:
filename = self.base_te + debug_rva + 0x10
filename = struct.unpack("200s", self.ec.getMemoryService().read(filename, 200, 32))[0]
return filename[0:string.find(filename,'\0')]
def get_debug_elfbase(self):
stripped_size = struct.unpack("<H", self.ec.getMemoryService().read(self.base_te + 0x6, 2, 32))[0]
stripped_size -= EfiSectionTE.SIZEOF_EFI_TE_IMAGE_HEADER
base_of_code = self.ec.getMemoryService().readMemory32(self.base_te + 0xC)
return self.base_te + base_of_code - stripped_size
class EfiSectionPE32:
def __init__(self, ec, base_pe32):
self.ec = ec
self.base_pe32 = base_pe32
def get_debug_filepath(self):
# Offset from dos hdr to PE file hdr
file_header_offset = self.ec.getMemoryService().readMemory32(self.base_pe32 + 0x3C)
# Offset to debug dir in PE hdrs
debug_dir_entry_rva = self.ec.getMemoryService().readMemory32(self.base_pe32 + file_header_offset + 0xA8)
if debug_dir_entry_rva == 0:
raise Exception("EfiFileSectionPE32","No Debug Directory")
debug_type = self.ec.getMemoryService().readMemory32(self.base_pe32 + debug_dir_entry_rva + 0xC)
if (debug_type != 0xdf) and (debug_type != EfiFileSection.EFI_IMAGE_DEBUG_TYPE_CODEVIEW):
raise Exception("EfiFileSectionPE32","Debug type is not dwarf")
debug_rva = self.ec.getMemoryService().readMemory32(self.base_pe32 + debug_dir_entry_rva + 0x14)
dwarf_sig = struct.unpack("cccc", self.ec.getMemoryService().read(str(self.base_pe32 + debug_rva), 4, 32))
if (dwarf_sig != 0x66727764) and (dwarf_sig != FirmwareFile.CONST_NB10_SIGNATURE):
raise Exception("EfiFileSectionPE32","Dwarf debug signature not found")
if dwarf_sig == 0x66727764:
filename = self.base_pe32 + debug_rva + 0xc
else:
filename = self.base_pe32 + debug_rva + 0x10
filename = struct.unpack("200s", self.ec.getMemoryService().read(str(filename), 200, 32))[0]
return filename[0:string.find(filename,'\0')]
def get_debug_elfbase(self):
# Offset from dos hdr to PE file hdr
pe_file_header = self.base_pe32 + self.ec.getMemoryService().readMemory32(self.base_pe32 + 0x3C)
base_of_code = self.base_pe32 + self.ec.getMemoryService().readMemory32(pe_file_header + 0x28)
base_of_data = self.base_pe32 + self.ec.getMemoryService().readMemory32(pe_file_header + 0x2C)
if (base_of_code < base_of_data) and (base_of_code != 0):
return base_of_code
else:
return base_of_data
class FirmwareFile:
EFI_FV_FILETYPE_RAW = 0x01
EFI_FV_FILETYPE_FREEFORM = 0x02
EFI_FV_FILETYPE_SECURITY_CORE = 0x03
EFI_FV_FILETYPE_PEI_CORE = 0x04
EFI_FV_FILETYPE_DXE_CORE = 0x05
EFI_FV_FILETYPE_PEIM = 0x06
EFI_FV_FILETYPE_DRIVER = 0x07
EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER = 0x08
EFI_FV_FILETYPE_APPLICATION = 0x09
EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE = 0x0B
EFI_FV_FILETYPE_FFS_MIN = 0xF0
CONST_NB10_SIGNATURE = ('N','B','1','0')
def __init__(self, fv, base, ec):
self.fv = fv
self.base = base
self.ec = ec
def __str__(self):
return "FFS(state:0x%x, type:0x%X, size:0x%x)" % (self.get_state(), self.get_type(), self.get_size())
def get_base(self):
return self.base
def get_size(self):
size = (self.ec.getMemoryService().readMemory32(self.base + 0x14) & 0x00ffffff)
# Occupied size is the size considering the alignment
return size + ((0x8 - (size & 0x7)) & 0x7)
def get_type(self):
return self.ec.getMemoryService().readMemory8(self.base + 0x12)
def get_state(self):
state = self.ec.getMemoryService().readMemory8(self.base + 0x17)
polarity = self.fv.get_polarity()
if polarity:
state = ~state
highest_bit = 0x80;
while (highest_bit != 0) and ((highest_bit & state) == 0):
highest_bit >>= 1
return highest_bit
def get_next_section(self, section=None):
if section == None:
if self.get_type() != FirmwareFile.EFI_FV_FILETYPE_FFS_MIN:
section_base = self.get_base() + 0x18;
else:
return None
else:
section_base = int(section.get_base() + section.get_size())
# Align to next 4 byte boundary
if (section_base & 0x3) != 0:
section_base = section_base + 0x4 - (section_base & 0x3)
if section_base < self.get_base() + self.get_size():
return EfiFileSection(self.ec, section_base)
else:
return None
class FirmwareVolume:
CONST_FV_SIGNATURE = ('_','F','V','H')
EFI_FVB2_ERASE_POLARITY = 0x800
DebugInfos = []
def __init__(self, ec, fv_base, fv_size):
self.ec = ec
self.fv_base = fv_base
self.fv_size = fv_size
try:
signature = struct.unpack("cccc", self.ec.getMemoryService().read(fv_base + 0x28, 4, 32))
except DebugException:
raise Exception("FirmwareVolume", "Not possible to access the defined firmware volume at [0x%X,0x%X]. Could be the used build report does not correspond to your current debugging context." % (int(fv_base),int(fv_base+fv_size)))
if signature != FirmwareVolume.CONST_FV_SIGNATURE:
raise Exception("FirmwareVolume", "This is not a valid firmware volume")
def get_size(self):
return self.ec.getMemoryService().readMemory32(self.fv_base + 0x20)
def get_attributes(self):
return self.ec.getMemoryService().readMemory32(self.fv_base + 0x2C)
def get_polarity(self):
attributes = self.get_attributes()
if attributes & FirmwareVolume.EFI_FVB2_ERASE_POLARITY:
return 1
else:
return 0
def get_next_ffs(self, ffs=None):
if ffs == None:
# Get the offset of the first FFS file from the FV header
ffs_base = self.fv_base + self.ec.getMemoryService().readMemory16(self.fv_base + 0x30)
else:
# Goto the next FFS file
ffs_base = int(ffs.get_base() + ffs.get_size())
# Align to next 8 byte boundary
if (ffs_base & 0x7) != 0:
ffs_base = ffs_base + 0x8 - (ffs_base & 0x7)
if ffs_base < self.fv_base + self.get_size():
return FirmwareFile(self, ffs_base, self.ec)
else:
return None
def get_debug_info(self):
self.DebugInfos = []
ffs = self.get_next_ffs()
while ffs != None:
section = ffs.get_next_section()
while section != None:
type = section.get_type()
if (type == EfiFileSection.EFI_SECTION_TE) or (type == EfiFileSection.EFI_SECTION_PE32):
self.DebugInfos.append((section.get_base(), section.get_size(), section.get_type()))
section = ffs.get_next_section(section)
ffs = self.get_next_ffs(ffs)
def load_symbols_at(self, addr):
if self.DebugInfos == []:
self.get_debug_info()
for debug_info in self.DebugInfos:
if (addr >= debug_info[0]) and (addr < debug_info[0] + debug_info[1]):
if debug_info[2] == EfiFileSection.EFI_SECTION_TE:
section = EfiSectionTE(self.ec, debug_info[0] + 0x4)
elif debug_info[2] == EfiFileSection.EFI_SECTION_PE32:
section = EfiSectionPE32(self.ec, debug_info[0] + 0x4)
else:
raise Exception('FirmwareVolume','Section Type not supported')
edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase())
return debug_info
def load_all_symbols(self):
if self.DebugInfos == []:
self.get_debug_info()
for debug_info in self.DebugInfos:
if debug_info[2] == EfiFileSection.EFI_SECTION_TE:
section = EfiSectionTE(self.ec, debug_info[0] + 0x4)
elif debug_info[2] == EfiFileSection.EFI_SECTION_PE32:
section = EfiSectionPE32(self.ec, debug_info[0] + 0x4)
else:
continue
edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase())

View File

@ -0,0 +1,127 @@
#
# Copyright (c) 2011-2012, ARM Limited. All rights 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.
#
from arm_ds.debugger_v1 import DebugException
import firmware_volume
import struct
class DebugInfoTable:
CONST_DEBUG_INFO_TABLE_GUID = ( 0x49152E77L, 0x47641ADAL, 0xFE7AA2B7L, 0x8B5ED9FEL)
DebugInfos = []
def __init__(self, ec, debug_info_table_header_offset):
self.ec = ec
self.base = debug_info_table_header_offset
def get_debug_info(self):
count = self.ec.getMemoryService().readMemory32(self.base + 0x4)
debug_info_table_base = self.ec.getMemoryService().readMemory32(self.base + 0x8)
self.DebugInfos = []
for i in range(0, count):
# Get the address of the structure EFI_DEBUG_IMAGE_INFO
debug_info = self.ec.getMemoryService().readMemory32(debug_info_table_base + (i * 4))
if debug_info:
debug_info_type = self.ec.getMemoryService().readMemory32(debug_info)
# Normal Debug Info Type
if debug_info_type == 1:
# Get the base address of the structure EFI_LOADED_IMAGE_PROTOCOL
loaded_image_protocol = self.ec.getMemoryService().readMemory32(debug_info + 0x4)
image_base = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x20)
image_size = self.ec.getMemoryService().readMemory32(loaded_image_protocol + 0x28)
self.DebugInfos.append((image_base,image_size))
# Return (base, size)
def load_symbols_at(self, addr):
if self.DebugInfos == []:
self.get_debug_info()
found = False
for debug_info in self.DebugInfos:
if (addr >= debug_info[0]) and (addr < debug_info[0] + debug_info[1]):
section = firmware_volume.EfiSectionPE32(self.ec, debug_info[0])
edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase())
found = True
return debug_info
if found == False:
raise Exception('DebugInfoTable','No symbol found at 0x%x' % addr)
def load_all_symbols(self):
if self.DebugInfos == []:
self.get_debug_info()
for debug_info in self.DebugInfos:
section = firmware_volume.EfiSectionPE32(self.ec, debug_info[0])
edk2_debugger.load_symbol_from_file(self.ec, section.get_debug_filepath(), section.get_debug_elfbase())
def dump(self):
self.get_debug_info()
for debug_info in self.DebugInfos:
base_pe32 = debug_info[0]
section = firmware_volume.EfiSectionPE32(self.ec, base_pe32)
print section.get_debug_filepath()
class SystemTable:
CONST_ST_SIGNATURE = ('I','B','I',' ','S','Y','S','T')
def __init__(self, ec, membase, memsize):
self.membase = membase
self.memsize = memsize
self.ec = ec
found = False
# Start from the top of the memory
offset = self.membase + self.memsize
# Align to highest 4MB boundary
offset = offset & ~0x3FFFFF
# We should not have a System Table at the top of the System Memory
offset = offset - 0x400000
# Start at top and look on 4MB boundaries for system table ptr structure
while offset > self.membase:
try:
signature = struct.unpack("cccccccc", self.ec.getMemoryService().read(str(offset), 8, 32))
except DebugException:
raise Exception('SystemTable','Fail to access System Memory. Ensure all the memory in the region [0x%x;0x%X] is accessible.' % (membase,membase+memsize))
if signature == SystemTable.CONST_ST_SIGNATURE:
found = True
self.system_table_base = self.ec.getMemoryService().readMemory32(offset + 0x8)
break
offset = offset - 0x400000
if not found:
raise Exception('SystemTable','System Table not found in System Memory [0x%x;0x%X]' % (membase,membase+memsize))
def get_configuration_table(self, conf_table_guid):
# Number of configuration Table entry
conf_table_entry_count = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x40)
# Get location of the Configuration Table entries
conf_table_offset = self.ec.getMemoryService().readMemory32(self.system_table_base + 0x44)
for i in range(0, conf_table_entry_count):
offset = conf_table_offset + (i * 0x14)
guid = struct.unpack("<IIII", self.ec.getMemoryService().read(str(offset), 16, 32))
if guid == conf_table_guid:
return self.ec.getMemoryService().readMemory32(offset + 0x10)
raise Exception('SystemTable','Configuration Table not found')