2 # Copyright (c) 2011-2012, ARM Limited. All rights reserved.
4 # This program and the accompanying materials
5 # are licensed and made available under the terms and conditions of the BSD License
6 # which accompanies this distribution. The full text of the license may be found at
7 # http://opensource.org/licenses/bsd-license.php
9 # THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 # WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 import firmware_volume
19 # Reload external classes
20 reload(firmware_volume
)
24 def readMem32(executionContext
, address
):
25 bytes
= executionContext
.getMemoryService().read(address
, 4, 32)
26 return struct
.unpack('<I',bytes
)[0]
28 def dump_fv(ec
, fv_base
, fv_size
):
29 fv
= firmware_volume
.FirmwareVolume(ec
,
30 int(build
.PCDs
['gArmTokenSpaceGuid']['PcdFvBaseAddress'][0],16),
31 int(build
.PCDs
['gArmTokenSpaceGuid']['PcdFvSize'][0],16))
33 ffs
= fv
.get_next_ffs()
37 section
= ffs
.get_next_section()
38 while section
!= None:
39 print "\t%s" % section
41 print "\t\t- %s" % section
.get_debug_filepath()
44 section
= ffs
.get_next_section(section
)
46 ffs
= fv
.get_next_ffs(ffs
)
48 def dump_system_table(ec
, mem_base
, mem_size
):
49 st
= system_table
.SystemTable(ec
, mem_base
, mem_size
)
51 debug_info_table_base
= st
.get_configuration_table(system_table
.DebugInfoTable
.CONST_DEBUG_INFO_TABLE_GUID
)
53 debug_info_table
= system_table
.DebugInfoTable(ec
, debug_info_table_base
)
54 debug_info_table
.dump()
56 def load_symbol_from_file(ec
, filename
, address
):
58 ec
.getImageService().addSymbols(filename
, address
)
61 # We could get an exception if the symbols are already loaded
62 ec
.getImageService().unloadSymbols(filename
)
63 ec
.getImageService().addSymbols(filename
, address
)
65 print "Warning: not possible to load symbols from %s" % filename
69 def __init__(self
, sysmembase
=None, sysmemsize
=None, fvs
={}):
70 self
.sysmembase
= sysmembase
71 self
.sysmemsize
= sysmemsize
74 class ArmPlatformDebugger
:
78 REGION_TYPE_SYSMEM
= 1
82 def __init__(self
, ec
, report_log
, regions
):
88 if report_log
and os
.path
.isfile(report_log
):
90 self
.build
= build_report
.BuildReport(report_log
)
92 raise IOError(2, 'Report \'%s\' isnot valid' % report_log
)
94 # Generate list of supported Firmware Volumes
95 if self
.build
.PCDs
['gArmTokenSpaceGuid'].has_key('PcdFvSize') and int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdFvSize'][0],16) != 0:
96 fvs
.append((int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdFvBaseAddress'][0],16),int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdFvSize'][0],16)))
97 if self
.build
.PCDs
['gArmTokenSpaceGuid'].has_key('PcdSecureFvSize') and int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdSecureFvSize'][0],16) != 0:
98 fvs
.append((int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdSecureFvBaseAddress'][0],16),int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdSecureFvSize'][0],16)))
99 if self
.build
.PCDs
['gArmTokenSpaceGuid'].has_key('PcdHypFvSize') and int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdHypFvSize'][0],16) != 0:
100 fvs
.append((int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdHypFvBaseAddress'][0],16),int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdHypFvSize'][0],16)))
102 sysmem_base
= int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdSystemMemoryBase'][0],16)
103 sysmem_size
= int(self
.build
.PCDs
['gArmTokenSpaceGuid']['PcdSystemMemorySize'][0],16)
105 for region
in regions
:
106 if region
[0] == ArmPlatformDebugger
.REGION_TYPE_SYSMEM
:
107 sysmem_base
= region
[1]
108 sysmem_size
= region
[2]
109 elif region
[0] == ArmPlatformDebugger
.REGION_TYPE_FV
:
110 fvs
.append((region
[1],region
[2]))
111 elif region
[0] == ArmPlatformDebugger
.REGION_TYPE_ROM
:
112 for base
in xrange(region
[1], region
[1] + region
[2], 0x400000):
113 signature
= struct
.unpack("cccc", self
.ec
.getMemoryService().read(base
, 4, 32))
114 if signature
== FirmwareVolume
.CONST_FV_SIGNATURE
:
117 print "Region type '%d' Not Supported" % region
[0]
119 self
.platform
= ArmPlatform(sysmem_base
, sysmem_size
, fvs
)
121 def in_sysmem(self
, addr
):
122 return (self
.platform
.sysmembase
is not None) and (self
.platform
.sysmembase
<= addr
) and (addr
< self
.platform
.sysmembase
+ self
.platform
.sysmemsize
)
124 def in_fv(self
, addr
):
125 return (self
.get_fv_at(addr
) != None)
127 def get_fv_at(self
, addr
):
128 for fv
in self
.platform
.fvs
:
129 if (fv
[0] <= addr
) and (addr
< fv
[0] + fv
[1]):
133 def load_current_symbols(self
):
134 pc
= int(self
.ec
.getRegisterService().getValue('PC')) & 0xFFFFFFFF
138 (fv_base
, fv_size
) = self
.get_fv_at(pc
)
140 if self
.firmware_volumes
.has_key(fv_base
) == False:
141 self
.firmware_volumes
[fv_base
] = firmware_volume
.FirmwareVolume(self
.ec
, fv_base
, fv_size
)
143 stack_frame
= self
.ec
.getTopLevelStackFrame()
144 info
= self
.firmware_volumes
[fv_base
].load_symbols_at(int(stack_frame
.getRegisterService().getValue('PC')) & 0xFFFFFFFF)
145 debug_infos
.append(info
)
146 while stack_frame
.next() is not None:
147 stack_frame
= stack_frame
.next()
149 # Stack frame attached to 'PC'
150 pc
= int(stack_frame
.getRegisterService().getValue('PC')) & 0xFFFFFFFF
152 # Check if the symbols for this stack frame have already been loaded
154 for debug_info
in debug_infos
:
155 if (pc
>= debug_info
[0]) and (pc
< debug_info
[0] + debug_info
[1]):
158 info
= self
.firmware_volumes
[fv_base
].load_symbols_at(pc
)
159 debug_infos
.append(info
)
161 #self.firmware_volumes[fv_base].load_symbols_at(pc)
162 elif self
.in_sysmem(pc
):
165 if self
.system_table
is None:
166 # Find the System Table
167 self
.system_table
= system_table
.SystemTable(self
.ec
, self
.platform
.sysmembase
, self
.platform
.sysmemsize
)
169 # Find the Debug Info Table
170 debug_info_table_base
= self
.system_table
.get_configuration_table(system_table
.DebugInfoTable
.CONST_DEBUG_INFO_TABLE_GUID
)
171 self
.debug_info_table
= system_table
.DebugInfoTable(self
.ec
, debug_info_table_base
)
173 stack_frame
= self
.ec
.getTopLevelStackFrame()
174 info
= self
.debug_info_table
.load_symbols_at(int(stack_frame
.getRegisterService().getValue('PC')) & 0xFFFFFFFF)
175 debug_infos
.append(info
)
176 while stack_frame
.next() is not None:
177 stack_frame
= stack_frame
.next()
179 # Stack frame attached to 'PC'
180 pc
= int(stack_frame
.getRegisterService().getValue('PC')) & 0xFFFFFFFF
182 # Check if the symbols for this stack frame have already been loaded
184 for debug_info
in debug_infos
:
185 if (pc
>= debug_info
[0]) and (pc
< debug_info
[0] + debug_info
[1]):
188 info
= self
.debug_info_table
.load_symbols_at(pc
)
189 debug_infos
.append(info
)
191 #self.debug_info_table.load_symbols_at(pc)
193 raise Exception('ArmPlatformDebugger', "Not supported region")
195 def load_all_symbols(self
):
196 # Load all the XIP symbols attached to the Firmware Volume
197 for (fv_base
, fv_size
) in self
.platform
.fvs
:
198 if self
.firmware_volumes
.has_key(fv_base
) == False:
199 self
.firmware_volumes
[fv_base
] = firmware_volume
.FirmwareVolume(self
.ec
, fv_base
, fv_size
)
200 self
.firmware_volumes
[fv_base
].load_all_symbols()
203 # Load all symbols of module loaded into System Memory
204 if self
.system_table
is None:
205 # Find the System Table
206 self
.system_table
= system_table
.SystemTable(self
.ec
, self
.platform
.sysmembase
, self
.platform
.sysmemsize
)
209 # Find the Debug Info Table
210 debug_info_table_base
= self
.system_table
.get_configuration_table(system_table
.DebugInfoTable
.CONST_DEBUG_INFO_TABLE_GUID
)
211 self
.debug_info_table
= system_table
.DebugInfoTable(self
.ec
, debug_info_table_base
)
213 self
.debug_info_table
.load_all_symbols()
215 # Debugger exception could be excepted if DRAM has not been initialized or if we have not started to run from DRAM yet
216 print "Note: no symbols have been found in System Memory (possible cause: the UEFI permanent memory has been installed yet)"