6 def ReadPhysInt(phys_addr
, bitsize
= 64, cpuval
= None):
7 """ Read a physical memory data based on address.
9 phys_addr : int - Physical address to read
10 bitsize : int - defines how many bytes to read. defaults to 64 bit
11 cpuval : None (optional)
13 int - int value read from memory. in case of failure 0xBAD10AD is returned.
15 if "kdp" == GetConnectionProtocol():
16 return KDPReadPhysMEM(phys_addr
, bitsize
)
18 #NO KDP. Attempt to use physical memory
19 paddr_in_kva
= kern
.PhysToKernelVirt(long(phys_addr
))
22 return kern
.GetValueFromAddress(paddr_in_kva
, 'uint64_t *').GetSBValue().Dereference().GetValueAsUnsigned()
24 return kern
.GetValueFromAddress(paddr_in_kva
, 'uint32_t *').GetSBValue().Dereference().GetValueAsUnsigned()
26 return kern
.GetValueFromAddress(paddr_in_kva
, 'uint16_t *').GetSBValue().Dereference().GetValueAsUnsigned()
28 return kern
.GetValueFromAddress(paddr_in_kva
, 'uint8_t *').GetSBValue().Dereference().GetValueAsUnsigned()
31 @lldb_command('readphys')
32 def ReadPhys(cmd_args
= None):
33 """ Reads the specified untranslated address
34 The argument is interpreted as a physical address, and the 64-bit word
35 addressed is displayed.
36 usage: readphys <nbits> <address>
38 address: 1234 or 0x1234
40 if cmd_args
== None or len(cmd_args
) < 2:
41 print "Insufficient arguments.", ReadPhys
.__doc
__
44 nbits
= ArgumentStringToInt(cmd_args
[0])
45 phys_addr
= ArgumentStringToInt(cmd_args
[1])
46 print "{0: <#x}".format(ReadPhysInt(phys_addr
, nbits
))
49 lldb_alias('readphys8', 'readphys 8 ')
50 lldb_alias('readphys16', 'readphys 16 ')
51 lldb_alias('readphys32', 'readphys 32 ')
52 lldb_alias('readphys64', 'readphys 64 ')
54 def KDPReadPhysMEM(address
, bits
):
55 """ Setup the state for READPHYSMEM64 commands for reading data via kdp
57 address : int - address where to read the data from
58 bits : int - number of bits in the intval (8/16/32/64)
60 int: read value from memory.
61 0xBAD10AD: if failed to read data.
64 if "kdp" != GetConnectionProtocol():
65 print "Target is not connected over kdp. Nothing to do here."
68 input_address
= unsigned(addressof(kern
.globals.manual_pkt
.input))
69 len_address
= unsigned(addressof(kern
.globals.manual_pkt
.len))
70 data_address
= unsigned(addressof(kern
.globals.manual_pkt
.data
))
71 if not WriteInt32ToMemoryAddress(0, input_address
):
74 kdp_pkt_size
= GetType('kdp_readphysmem64_req_t').GetByteSize()
75 if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
):
78 data_addr
= int(addressof(kern
.globals.manual_pkt
))
79 pkt
= kern
.GetValueFromAddress(data_addr
, 'kdp_readphysmem64_req_t *')
81 header_value
=GetKDPPacketHeaderInt(request
=GetEnumValue('kdp_req_t::KDP_READPHYSMEM64'), length
=kdp_pkt_size
)
83 if ( WriteInt64ToMemoryAddress((header_value
), int(addressof(pkt
.hdr
))) and
84 WriteInt64ToMemoryAddress(address
, int(addressof(pkt
.address
))) and
85 WriteInt32ToMemoryAddress((bits
/8), int(addressof(pkt
.nbytes
))) and
86 WriteInt16ToMemoryAddress(xnudefines
.lcpu_self
, int(addressof(pkt
.lcpu
)))
89 if WriteInt32ToMemoryAddress(1, input_address
):
90 # now read data from the kdp packet
91 data_address
= unsigned(addressof(kern
.GetValueFromAddress(int(addressof(kern
.globals.manual_pkt
.data
)), 'kdp_readphysmem64_reply_t *').data
))
93 retval
= kern
.GetValueFromAddress(data_address
, 'uint64_t *').GetSBValue().Dereference().GetValueAsUnsigned()
95 retval
= kern
.GetValueFromAddress(data_address
, 'uint32_t *').GetSBValue().Dereference().GetValueAsUnsigned()
97 retval
= kern
.GetValueFromAddress(data_address
, 'uint16_t *').GetSBValue().Dereference().GetValueAsUnsigned()
99 retval
= kern
.GetValueFromAddress(data_address
, 'uint8_t *').GetSBValue().Dereference().GetValueAsUnsigned()
103 def KDPWritePhysMEM(address
, intval
, bits
):
104 """ Setup the state for WRITEPHYSMEM64 commands for saving data in kdp
106 address : int - address where to save the data
107 intval : int - integer value to be stored in memory
108 bits : int - number of bits in the intval (8/16/32/64)
110 boolean: True if the write succeeded.
112 if "kdp" != GetConnectionProtocol():
113 print "Target is not connected over kdp. Nothing to do here."
115 input_address
= unsigned(addressof(kern
.globals.manual_pkt
.input))
116 len_address
= unsigned(addressof(kern
.globals.manual_pkt
.len))
117 data_address
= unsigned(addressof(kern
.globals.manual_pkt
.data
))
118 if not WriteInt32ToMemoryAddress(0, input_address
):
121 kdp_pkt_size
= GetType('kdp_writephysmem64_req_t').GetByteSize()
122 if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
):
125 data_addr
= int(addressof(kern
.globals.manual_pkt
))
126 pkt
= kern
.GetValueFromAddress(data_addr
, 'kdp_writephysmem64_req_t *')
128 header_value
=GetKDPPacketHeaderInt(request
=GetEnumValue('kdp_req_t::KDP_WRITEPHYSMEM64'), length
=kdp_pkt_size
)
130 if ( WriteInt64ToMemoryAddress((header_value
), int(addressof(pkt
.hdr
))) and
131 WriteInt64ToMemoryAddress(address
, int(addressof(pkt
.address
))) and
132 WriteInt32ToMemoryAddress((bits
/8), int(addressof(pkt
.nbytes
))) and
133 WriteInt16ToMemoryAddress(xnudefines
.lcpu_self
, int(addressof(pkt
.lcpu
)))
137 if not WriteInt8ToMemoryAddress(intval
, int(addressof(pkt
.data
))):
140 if not WriteInt16ToMemoryAddress(intval
, int(addressof(pkt
.data
))):
143 if not WriteInt32ToMemoryAddress(intval
, int(addressof(pkt
.data
))):
146 if not WriteInt64ToMemoryAddress(intval
, int(addressof(pkt
.data
))):
148 if WriteInt32ToMemoryAddress(1, input_address
):
153 def WritePhysInt(phys_addr
, int_val
, bitsize
= 64):
154 """ Write and integer value in a physical memory data based on address.
156 phys_addr : int - Physical address to read
157 int_val : int - int value to write in memory
158 bitsize : int - defines how many bytes to read. defaults to 64 bit
160 bool - True if write was successful.
162 if "kdp" == GetConnectionProtocol():
163 if not KDPWritePhysMEM(phys_addr
, int_val
, bitsize
):
164 print "Failed to write via KDP."
167 #We are not connected via KDP. So do manual math and savings.
168 print "Failed: Write to physical memory is not supported for %s connection." % GetConnectionProtocol()
171 @lldb_command('writephys')
172 def WritePhys(cmd_args
=None):
173 """ writes to the specified untranslated address
174 The argument is interpreted as a physical address, and the 64-bit word
175 addressed is displayed.
176 usage: writephys <nbits> <address> <value>
178 address: 1234 or 0x1234
179 value: int value to be written
180 ex. (lldb)writephys 16 0x12345abcd 0x25
182 if cmd_args
== None or len(cmd_args
) < 3:
183 print "Invalid arguments.", WritePhys
.__doc
__
185 nbits
= ArgumentStringToInt(cmd_args
[0])
186 phys_addr
= ArgumentStringToInt(cmd_args
[1])
187 int_value
= ArgumentStringToInt(cmd_args
[2])
188 print WritePhysInt(phys_addr
, int_value
, nbits
)
191 lldb_alias('writephys8', 'writephys 8 ')
192 lldb_alias('writephys16', 'writephys 16 ')
193 lldb_alias('writephys32', 'writephys 32 ')
194 lldb_alias('writephys64', 'writephys 64 ')
197 def _PT_Step(paddr
, index
, verbose_level
= vSCRIPT
):
199 Step to lower-level page table and print attributes
200 paddr: current page table entry physical address
201 index: current page table entry index (0..511)
202 verbose_level: vHUMAN: print nothing
203 vSCRIPT: print basic information
204 vDETAIL: print basic information and hex table dump
205 returns: (pt_paddr, pt_valid, pt_large)
206 pt_paddr: next level page table entry physical address
208 pt_valid: 1 if $kgm_pt_paddr is valid, 0 if the walk
210 pt_large: 1 if kgm_pt_paddr is a page frame address
211 of a large page and not another page table entry
213 entry_addr
= paddr
+ (8 * index
)
214 entry
= ReadPhysInt(entry_addr
, 64, xnudefines
.lcpu_self
)
216 if verbose_level
>= vDETAIL
:
217 for pte_loop
in range(0, 512):
218 paddr_tmp
= paddr
+ (8 * pte_loop
)
219 out_string
+= "{0: <#020x}:\t {1: <#020x}\n".format(paddr_tmp
, ReadPhysInt(paddr_tmp
, 64, xnudefines
.lcpu_self
))
220 paddr_mask
= ~
((0xfff<<52) |
0xfff)
221 paddr_large_mask
= ~
((0xfff<<52) |
0x1fffff)
225 if verbose_level
< vSCRIPT
:
229 pt_paddr
= entry
& paddr_mask
230 if entry
& (0x1 <<7):
232 pt_paddr
= entry
& paddr_large_mask
234 out_string
+= "{0: <#020x}:\n\t{1:#020x}\n\t".format(entry_addr
, entry
)
236 out_string
+= " valid"
237 pt_paddr
= entry
& paddr_mask
240 out_string
+= " invalid"
243 #Stop decoding other bits
245 if entry
& (0x1 << 1):
246 out_string
+= " writable"
248 out_string
+= " read-only"
250 if entry
& (0x1 << 2):
251 out_string
+= " user"
253 out_string
+= " supervisor"
255 if entry
& (0x1 << 3):
258 if entry
& (0x1 << 4):
261 if entry
& (0x1 << 5):
262 out_string
+= " accessed"
264 if entry
& (0x1 << 6):
265 out_string
+= " dirty"
267 if entry
& (0x1 << 7):
268 out_string
+= " large"
273 if entry
& (0x1 << 8):
274 out_string
+= " global"
276 if entry
& (0x3 << 9):
277 out_string
+= " avail:{0:x}".format((entry
>> 9) & 0x3)
279 if entry
& (0x1 << 63):
280 out_string
+= " noexec"
282 return (pt_paddr
, pt_valid
, pt_large
)
287 def _PmapL4Walk(pmap_addr_val
,vaddr
, verbose_level
= vSCRIPT
):
288 """ Walk the l4 pmap entry.
289 params: pmap_addr_val - core.value representing kernel data of type pmap_addr_t
290 vaddr : int - virtual address to walk
292 is_cpu64_bit
= int(kern
.globals.cpu_64bit
)
293 pt_paddr
= unsigned(pmap_addr_val
)
294 pt_valid
= (unsigned(pmap_addr_val
) != 0)
297 if pt_valid
and is_cpu64_bit
:
298 # Lookup bits 47:39 of linear address in PML4T
299 pt_index
= (vaddr
>> 39) & 0x1ff
300 pframe_offset
= vaddr
& 0x7fffffffff
301 if verbose_level
> vHUMAN
:
302 print "pml4 (index {0:d}):".format(pt_index
)
303 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
305 # Lookup bits 38:30 of the linear address in PDPT
306 pt_index
= (vaddr
>> 30) & 0x1ff
307 pframe_offset
= vaddr
& 0x3fffffff
308 if verbose_level
> vHUMAN
:
309 print "pdpt (index {0:d}):".format(pt_index
)
310 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
311 if pt_valid
and not pt_large
:
312 #Lookup bits 29:21 of the linear address in PDPT
313 pt_index
= (vaddr
>> 21) & 0x1ff
314 pframe_offset
= vaddr
& 0x1fffff
315 if verbose_level
> vHUMAN
:
316 print "pdt (index {0:d}):".format(pt_index
)
317 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
318 if pt_valid
and not pt_large
:
319 #Lookup bits 20:21 of linear address in PT
320 pt_index
= (vaddr
>> 12) & 0x1ff
321 pframe_offset
= vaddr
& 0xfff
322 if verbose_level
> vHUMAN
:
323 print "pt (index {0:d}):".format(pt_index
)
324 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
326 paddr_isvalid
= False
328 paddr
= pt_paddr
+ pframe_offset
331 if verbose_level
> vHUMAN
:
333 pvalue
= ReadPhysInt(paddr
, 32, xnudefines
.lcpu_self
)
334 print "phys {0: <#020x}: {1: <#020x}".format(paddr
, pvalue
)
336 print "no translation"
340 def _PmapWalkARMLevel1Section(tte
, vaddr
, verbose_level
= vSCRIPT
):
343 #Supersection or just section?
344 if (tte
& 0x40000) == 0x40000:
345 paddr
= ( (tte
& 0xFF000000) |
(vaddr
& 0x00FFFFFF) )
347 paddr
= ( (tte
& 0xFFF00000) |
(vaddr
& 0x000FFFFF) )
349 if verbose_level
>= vSCRIPT
:
350 out_string
+= "{0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(tte
), tte
)
351 #bit [1:0] evaluated in PmapWalkARM
353 b_bit
= (tte
& 0x4) >> 2
355 c_bit
= (tte
& 0x8) >> 3
358 out_string
+= "no-execute"
360 out_string
+= "execute"
361 #Domain bit [8:5] if not supersection
362 if (tte
& 0x40000) == 0x0:
363 out_string
+= " domain ({:d})".format(((tte
& 0x1e0) >> 5) )
365 out_string
+= " imp({:d})".format( ((tte
& 0x200) >> 9) )
366 # AP bit 15 and [11:10] merged to a single 3 bit value
367 access
= ( (tte
& 0xc00) >> 10 ) |
((tte
& 0x8000) >> 13)
368 out_string
+= xnudefines
.arm_level2_access_strings
[access
]
371 tex_bits
= ((tte
& 0x7000) >> 12)
372 #Print TEX, C , B all together
373 out_string
+= " TEX:C:B({:d}{:d}{:d}:{:d}:{:d})".format(
374 1 if (tex_bits
& 0x4) else 0,
375 1 if (tex_bits
& 0x2) else 0,
376 1 if (tex_bits
& 0x1) else 0,
382 out_string
+= " shareable"
384 out_string
+= " not-shareable"
387 out_string
+= " not-global"
389 out_string
+= " global"
390 # Supersection bit 18
392 out_string
+= " supersection"
394 out_string
+= " section"
397 out_string
+= " no-secure"
399 out_string
+= " secure"
406 def _PmapWalkARMLevel2(tte
, vaddr
, verbose_level
= vSCRIPT
):
407 """ Pmap walk the level 2 tte.
411 returns: str - description of the tte + additional informaiton based on verbose_level
413 pte_base
= kern
.PhysToKernelVirt(tte
& 0xFFFFFC00)
414 pte_index
= (vaddr
>> 12) & 0xFF
415 pte_base_val
= kern
.GetValueFromAddress(pte_base
, 'pt_entry_t *')
416 pte
= pte_base_val
[pte_index
]
418 if verbose_level
>= vSCRIPT
:
419 out_string
+= "{0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(tte
), tte
)
420 # bit [1:0] evaluated in PmapWalkARM
423 out_string
+= ' no-secure'
425 out_string
+= ' secure'
427 out_string
+= " domain({:d})".format(((tte
& 0x1e0) >> 5))
429 out_string
+= " imp({:d})".format( ((tte
& 0x200) >> 9))
431 if verbose_level
>= vSCRIPT
:
432 out_string
+= "second-level table (index {:d}):\n".format(pte_index
)
433 if verbose_level
>= vDETAIL
:
435 tmp
= pte_base_val
[i
]
436 out_string
+= "{0: <#020x}:\t{1: <#020x}\n".format(addressof(tmp
), unsigned(tmp
))
440 paddr
= (unsigned(pte
) & 0xFFFFF000) |
(vaddr
& 0xFFF)
442 if verbose_level
>= vSCRIPT
:
443 out_string
+= " {0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(pte
), unsigned(pte
))
444 if (pte
& 0x3) == 0x0:
445 out_string
+= " invalid"
447 if (pte
& 0x3) == 0x1:
448 out_string
+= " large"
450 if pte
& 0x8000 == 0x8000:
451 out_string
+= " no-execute"
453 out_string
+= " execute"
455 out_string
+= " small"
457 if (pte
& 0x1) == 0x01:
458 out_string
+= " no-execute"
460 out_string
+= " execute"
462 b_bit
= (pte
& 0x4) >> 2
463 c_bit
= (pte
& 0x8) >> 3
464 # AP bit 9 and [5:4], merged to a single 3-bit value
465 access
= (pte
& 0x30) >> 4 |
(pte
& 0x200) >> 7
466 out_string
+= xnudefines
.arm_level2_access_strings
[access
]
468 #TEX bit [14:12] for large, [8:6] for small
469 tex_bits
= ((pte
& 0x1c0) >> 6)
470 if (pte
& 0x3) == 0x1:
471 tex_bits
= ((pte
& 0x7000) >> 12)
473 # Print TEX, C , B alltogether
474 out_string
+= " TEX:C:B({:d}{:d}{:d}:{:d}:{:d})".format(
475 1 if (tex_bits
& 0x4) else 0,
476 1 if (tex_bits
& 0x2) else 0,
477 1 if (tex_bits
& 0x1) else 0,
483 out_string
+= " shareable"
485 out_string
+= " not-shareable"
489 out_string
+= " not-global"
491 out_string
+= " global"
494 #end of level 2 walking of arm
497 def PmapWalkARM(pmap
, vaddr
, verbose_level
= vHUMAN
):
498 """ Pmap walking for ARM kernel.
500 pmapval: core.value - representing pmap_t in kernel
501 vaddr: int - integer representing virtual address to walk
504 # shift by TTESHIFT (20) to get tte index
505 tte_index
= ((vaddr
- unsigned(pmap
.min)) >> 20 )
506 tte
= pmap
.tte
[tte_index
]
507 if verbose_level
>= vSCRIPT
:
508 print "First-level table (index {:d}):".format(tte_index
)
509 if verbose_level
>= vDETAIL
:
510 for i
in range(0, 4096):
511 ptr
= unsigned(addressof(pmap
.tte
[i
]))
512 val
= unsigned(pmap
.tte
[i
])
513 print "{0: <#020x}:\t {1: <#020x}".format(ptr
, val
)
514 if (tte
& 0x3) == 0x1:
515 paddr
= _PmapWalkARMLevel2(tte
, vaddr
, verbose_level
)
516 elif (tte
& 0x3) == 0x2 :
517 paddr
= _PmapWalkARMLevel1Section(tte
, vaddr
, verbose_level
)
520 if verbose_level
>= vSCRIPT
:
521 print "Invalid First-Level Translation Table Entry: {0: #020x}".format(tte
)
523 if verbose_level
>= vHUMAN
:
525 print "Translation of {:#x} is {:#x}.".format(vaddr
, paddr
)
527 print "(no translation)"
531 def PmapWalkX86_64(pmapval
, vaddr
):
533 params: pmapval - core.value representing pmap_t in kernel
534 vaddr: int - int representing virtual address to walk
536 return _PmapL4Walk(pmapval
.pm_cr3
, vaddr
, config
['verbosity'])
538 def assert_64bit(val
):
542 ARM64_VMADDR_BITS
= 48
544 def PmapBlockOffsetMaskARM64(level
):
545 assert level
>= 1 and level
<= 3
546 page_size
= kern
.globals.page_size
547 ttentries
= (page_size
/ ARM64_TTE_SIZE
)
548 return page_size
* (ttentries
** (3 - level
)) - 1
550 def PmapBlockBaseMaskARM64(level
):
551 assert level
>= 1 and level
<= 3
552 page_size
= kern
.globals.page_size
553 return ((1 << ARM64_VMADDR_BITS
) - 1) & ~
PmapBlockOffsetMaskARM64(level
)
555 def PmapIndexMaskARM64(level
):
556 assert level
>= 1 and level
<= 3
557 page_size
= kern
.globals.page_size
558 ttentries
= (page_size
/ ARM64_TTE_SIZE
)
559 return page_size
* (ttentries
** (3 - level
) * (ttentries
- 1))
561 def PmapIndexDivideARM64(level
):
562 assert level
>= 1 and level
<= 3
563 page_size
= kern
.globals.page_size
564 ttentries
= (page_size
/ ARM64_TTE_SIZE
)
565 return page_size
* (ttentries
** (3 - level
))
567 def PmapTTnIndexARM64(vaddr
, level
):
568 assert(type(vaddr
) in (long, int))
571 return (vaddr
& PmapIndexMaskARM64(level
)) // PmapIndexDivideARM64(level
)
573 def PmapDecodeTTEARM64(tte
, level
):
574 assert(type(tte
) == long)
575 assert(type(level
) == int)
579 if (tte
& 0x2 == 0x2) and (level
!= 0x3):
580 print "Type = Table pointer."
581 print "Table addr = {:#x}.".format(tte
& 0xfffffffff000)
582 print "PXN = {:#x}.".format((tte
>> 59) & 0x1)
583 print "XN = {:#x}.".format((tte
>> 60) & 0x1)
584 print "AP = {:#x}.".format((tte
>> 61) & 0x3)
585 print "NS = {:#x}".format(tte
>> 63)
587 print "Type = Block."
588 print "AttrIdx = {:#x}.".format((tte
>> 2) & 0x7)
589 print "NS = {:#x}.".format((tte
>> 5) & 0x1)
590 print "AP = {:#x}.".format((tte
>> 6) & 0x3)
591 print "SH = {:#x}.".format((tte
>> 8) & 0x3)
592 print "AF = {:#x}.".format((tte
>> 10) & 0x1)
593 print "nG = {:#x}.".format((tte
>> 11) & 0x1)
594 print "HINT = {:#x}.".format((tte
>> 52) & 0x1)
595 print "PXN = {:#x}.".format((tte
>> 53) & 0x1)
596 print "XN = {:#x}.".format((tte
>> 54) & 0x1)
597 print "SW Use = {:#x}.".format((tte
>> 55) & 0xf)
603 def PmapWalkARM64(pmap
, vaddr
, verbose_level
= vHUMAN
):
604 assert(type(pmap
) == core
.cvalue
.value
)
605 assert(type(vaddr
) in (long, int))
606 page_size
= kern
.globals.page_size
607 page_offset_mask
= (page_size
- 1)
608 page_base_mask
= ((1 << ARM64_VMADDR_BITS
) - 1) & (~page_offset_mask
)
613 tt1_index
= PmapTTnIndexARM64(vaddr
, 1)
614 tt2_index
= PmapTTnIndexARM64(vaddr
, 2)
615 tt3_index
= PmapTTnIndexARM64(vaddr
, 3)
618 tte
= long(unsigned(pmap
.tte
[tt1_index
]))
619 assert(type(tte
) == long)
622 if verbose_level
>= vSCRIPT
:
623 print "L1 entry: {:#x}".format(tte
)
624 if verbose_level
>= vDETAIL
:
625 PmapDecodeTTEARM64(tte
, 1)
628 # Check for L1 block entry
630 # Handle L1 block entry
631 paddr
= tte
& PmapBlockBaseMaskARM64(1)
632 paddr
= paddr |
(vaddr
& PmapBlockOffsetMaskARM64(1))
633 print "phys: {:#x}".format(paddr
)
635 # Handle L1 table entry
636 l2_phys
= (tte
& page_base_mask
) + (ARM64_TTE_SIZE
* tt2_index
)
637 assert(type(l2_phys
) == long)
639 l2_virt
= kern
.PhysToKernelVirt(l2_phys
)
640 assert(type(l2_virt
) == long)
642 if verbose_level
>= vDETAIL
:
643 print "L2 physical address: {:#x}. L2 virtual address: {:#x}".format(l2_phys
, l2_virt
)
646 ttep
= kern
.GetValueFromAddress(l2_virt
, "tt_entry_t*")
647 tte
= long(unsigned(dereference(ttep
)))
648 assert(type(tte
) == long)
650 if verbose_level
>= vSCRIPT
:
651 print "L2 entry: {:#0x}".format(tte
)
652 if verbose_level
>= vDETAIL
:
653 PmapDecodeTTEARM64(tte
, 2)
656 # Check for L2 block entry
658 # Handle L2 block entry
659 paddr
= tte
& PmapBlockBaseMaskARM64(2)
660 paddr
= paddr |
(vaddr
& PmapBlockOffsetMaskARM64(2))
662 # Handle L2 table entry
663 l3_phys
= (tte
& page_base_mask
) + (ARM64_TTE_SIZE
* tt3_index
)
664 assert(type(l3_phys
) == long)
666 l3_virt
= kern
.PhysToKernelVirt(l3_phys
)
667 assert(type(l3_virt
) == long)
669 if verbose_level
>= vDETAIL
:
670 print "L3 physical address: {:#x}. L3 virtual address: {:#x}".format(l3_phys
, l3_virt
)
673 ttep
= kern
.GetValueFromAddress(l3_virt
, "tt_entry_t*")
674 tte
= long(unsigned(dereference(ttep
)))
675 assert(type(tte
) == long)
677 if verbose_level
>= vSCRIPT
:
678 print "L3 entry: {:#0x}".format(tte
)
679 if verbose_level
>= vDETAIL
:
680 PmapDecodeTTEARM64(tte
, 3)
683 paddr
= tte
& page_base_mask
684 paddr
= paddr |
(vaddr
& page_offset_mask
)
685 elif verbose_level
>= vHUMAN
:
686 print "L3 entry invalid: {:#x}\n".format(tte
)
687 elif verbose_level
>= vHUMAN
: # tte & 0x1 == 0x1
688 print "L2 entry invalid: {:#x}\n".format(tte
)
689 elif verbose_level
>= vHUMAN
:
690 print "L1 entry invalid: {:#x}\n".format(tte
)
692 if verbose_level
>= vHUMAN
:
694 print "Translation of {:#x} is {:#x}.".format(vaddr
, paddr
)
696 print "(no translation)"
700 def PmapWalk(pmap
, vaddr
, verbose_level
= vHUMAN
):
701 if kern
.arch
== 'x86_64':
702 return PmapWalkX86_64(pmap
, vaddr
)
703 elif kern
.arch
== 'arm':
704 return PmapWalkARM(pmap
, vaddr
, verbose_level
)
705 elif kern
.arch
== 'arm64':
706 return PmapWalkARM64(pmap
, vaddr
, verbose_level
)
708 raise NotImplementedError("PmapWalk does not support {0}".format(kern
.arch
))
710 @lldb_command('pmap_walk')
711 def PmapWalkHelper(cmd_args
=None):
712 """ Perform a page-table walk in <pmap> for <virtual_address>.
713 Syntax: (lldb) pmap_walk <pmap> <virtual_address> [-v]
714 Multiple -v's can be specified for increased verbosity
716 if cmd_args
== None or len(cmd_args
) < 2:
717 raise ArgumentError("Too few arguments to pmap_walk.")
719 pmap
= kern
.GetValueAsType(cmd_args
[0], 'pmap_t')
720 addr
= unsigned(kern
.GetValueFromAddress(cmd_args
[1], 'void *'))
721 PmapWalk(pmap
, addr
, config
['verbosity'])