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() + (bits
/ 8)
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 if entry
& (0x1 << 62):
244 out_string
+= " compressed"
245 #Stop decoding other bits
247 if entry
& (0x1 << 1):
248 out_string
+= " writable"
250 out_string
+= " read-only"
252 if entry
& (0x1 << 2):
253 out_string
+= " user"
255 out_string
+= " supervisor"
257 if entry
& (0x1 << 3):
260 if entry
& (0x1 << 4):
263 if entry
& (0x1 << 5):
264 out_string
+= " accessed"
266 if entry
& (0x1 << 6):
267 out_string
+= " dirty"
269 if entry
& (0x1 << 7):
270 out_string
+= " large"
275 if entry
& (0x1 << 8):
276 out_string
+= " global"
278 if entry
& (0x3 << 9):
279 out_string
+= " avail:{0:x}".format((entry
>> 9) & 0x3)
281 if entry
& (0x1 << 63):
282 out_string
+= " noexec"
284 return (pt_paddr
, pt_valid
, pt_large
)
286 def _PT_StepEPT(paddr
, index
, verbose_level
= vSCRIPT
):
288 Step to lower-level page table and print attributes for EPT pmap
289 paddr: current page table entry physical address
290 index: current page table entry index (0..511)
291 verbose_level: vHUMAN: print nothing
292 vSCRIPT: print basic information
293 vDETAIL: print basic information and hex table dump
294 returns: (pt_paddr, pt_valid, pt_large)
295 pt_paddr: next level page table entry physical address
297 pt_valid: 1 if $kgm_pt_paddr is valid, 0 if the walk
299 pt_large: 1 if kgm_pt_paddr is a page frame address
300 of a large page and not another page table entry
302 entry_addr
= paddr
+ (8 * index
)
303 entry
= ReadPhysInt(entry_addr
, 64, xnudefines
.lcpu_self
)
305 if verbose_level
>= vDETAIL
:
306 for pte_loop
in range(0, 512):
307 paddr_tmp
= paddr
+ (8 * pte_loop
)
308 out_string
+= "{0: <#020x}:\t {1: <#020x}\n".format(paddr_tmp
, ReadPhysInt(paddr_tmp
, 64, xnudefines
.lcpu_self
))
309 paddr_mask
= ~
((0xfff<<52) |
0xfff)
310 paddr_large_mask
= ~
((0xfff<<52) |
0x1fffff)
314 if verbose_level
< vSCRIPT
:
318 pt_paddr
= entry
& paddr_mask
319 if entry
& (0x1 <<7):
321 pt_paddr
= entry
& paddr_large_mask
323 out_string
+= "{0: <#020x}:\n\t{1:#020x}\n\t".format(entry_addr
, entry
)
325 out_string
+= "valid"
326 pt_paddr
= entry
& paddr_mask
329 out_string
+= "invalid"
332 if entry
& (0x1 << 62):
333 out_string
+= " compressed"
334 #Stop decoding other bits
337 out_string
+= " readable"
339 out_string
+= " no read"
340 if entry
& (0x1 << 1):
341 out_string
+= " writable"
343 out_string
+= " no write"
345 if entry
& (0x1 << 2):
346 out_string
+= " executable"
348 out_string
+= " no exec"
352 out_string
+= " cache-WB"
354 out_string
+= " cache-WP"
356 out_string
+= " cache-WT"
358 out_string
+= " cache-WC"
360 out_string
+= " cache-NC"
362 if (entry
& 0x40) == 0x40:
363 out_string
+= " Ignore-PTA"
365 if (entry
& 0x100) == 0x100:
366 out_string
+= " accessed"
368 if (entry
& 0x200) == 0x200:
369 out_string
+= " dirty"
371 if entry
& (0x1 << 7):
372 out_string
+= " large"
377 return (pt_paddr
, pt_valid
, pt_large
)
379 def _PmapL4Walk(pmap_addr_val
,vaddr
, ept_pmap
, verbose_level
= vSCRIPT
):
380 """ Walk the l4 pmap entry.
381 params: pmap_addr_val - core.value representing kernel data of type pmap_addr_t
382 vaddr : int - virtual address to walk
384 pt_paddr
= unsigned(pmap_addr_val
)
385 pt_valid
= (unsigned(pmap_addr_val
) != 0)
389 # Lookup bits 47:39 of linear address in PML4T
390 pt_index
= (vaddr
>> 39) & 0x1ff
391 pframe_offset
= vaddr
& 0x7fffffffff
392 if verbose_level
> vHUMAN
:
393 print "pml4 (index {0:d}):".format(pt_index
)
395 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
397 (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
)
399 # Lookup bits 38:30 of the linear address in PDPT
400 pt_index
= (vaddr
>> 30) & 0x1ff
401 pframe_offset
= vaddr
& 0x3fffffff
402 if verbose_level
> vHUMAN
:
403 print "pdpt (index {0:d}):".format(pt_index
)
405 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
407 (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
)
408 if pt_valid
and not pt_large
:
409 #Lookup bits 29:21 of the linear address in PDPT
410 pt_index
= (vaddr
>> 21) & 0x1ff
411 pframe_offset
= vaddr
& 0x1fffff
412 if verbose_level
> vHUMAN
:
413 print "pdt (index {0:d}):".format(pt_index
)
415 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
417 (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
)
418 if pt_valid
and not pt_large
:
419 #Lookup bits 20:21 of linear address in PT
420 pt_index
= (vaddr
>> 12) & 0x1ff
421 pframe_offset
= vaddr
& 0xfff
422 if verbose_level
> vHUMAN
:
423 print "pt (index {0:d}):".format(pt_index
)
425 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
427 (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
)
429 paddr_isvalid
= False
431 paddr
= pt_paddr
+ pframe_offset
434 if verbose_level
> vHUMAN
:
436 pvalue
= ReadPhysInt(paddr
, 32, xnudefines
.lcpu_self
)
437 print "phys {0: <#020x}: {1: <#020x}".format(paddr
, pvalue
)
439 print "no translation"
443 def PmapDecodeTTEARM(tte
, level
, verbose_level
):
444 """ Display the bits of an ARM translation table or page table entry
445 in human-readable form.
446 tte: integer value of the TTE/PTE
447 level: translation table level. Valid values are 1 or 2.
448 verbose_level: verbosity. vHUMAN, vSCRIPT, vDETAIL
451 if level
== 1 and (tte
& 0x3) == 0x2:
452 if verbose_level
< vSCRIPT
:
455 #bit [1:0] evaluated in PmapWalkARM
457 b_bit
= (tte
& 0x4) >> 2
459 c_bit
= (tte
& 0x8) >> 3
462 out_string
+= "no-execute"
464 out_string
+= "execute"
465 #Domain bit [8:5] if not supersection
466 if (tte
& 0x40000) == 0x0:
467 out_string
+= " domain ({:d})".format(((tte
& 0x1e0) >> 5) )
469 out_string
+= " imp({:d})".format( ((tte
& 0x200) >> 9) )
470 # AP bit 15 and [11:10] merged to a single 3 bit value
471 access
= ( (tte
& 0xc00) >> 10 ) |
((tte
& 0x8000) >> 13)
472 out_string
+= xnudefines
.arm_level2_access_strings
[access
]
475 tex_bits
= ((tte
& 0x7000) >> 12)
476 #Print TEX, C , B all together
477 out_string
+= " TEX:C:B({:d}{:d}{:d}:{:d}:{:d})".format(
478 1 if (tex_bits
& 0x4) else 0,
479 1 if (tex_bits
& 0x2) else 0,
480 1 if (tex_bits
& 0x1) else 0,
486 out_string
+= " shareable"
488 out_string
+= " not-shareable"
491 out_string
+= " not-global"
493 out_string
+= " global"
494 # Supersection bit 18
496 out_string
+= " supersection"
498 out_string
+= " section"
501 out_string
+= " no-secure"
503 out_string
+= " secure"
505 elif level
== 1 and (tte
& 0x3) == 0x1:
507 if verbose_level
>= vSCRIPT
:
508 # bit [1:0] evaluated in PmapWalkARM
511 out_string
+= ' no-secure'
513 out_string
+= ' secure'
515 out_string
+= " domain({:d})".format(((tte
& 0x1e0) >> 5))
517 out_string
+= " imp({:d})".format( ((tte
& 0x200) >> 9))
522 if verbose_level
>= vSCRIPT
:
523 if (pte
& 0x3) == 0x0:
524 out_string
+= " invalid"
526 if (pte
& 0x3) == 0x1:
527 out_string
+= " large"
529 if pte
& 0x8000 == 0x8000:
530 out_string
+= " no-execute"
532 out_string
+= " execute"
534 out_string
+= " small"
536 if (pte
& 0x1) == 0x01:
537 out_string
+= " no-execute"
539 out_string
+= " execute"
541 b_bit
= (pte
& 0x4) >> 2
542 c_bit
= (pte
& 0x8) >> 3
543 # AP bit 9 and [5:4], merged to a single 3-bit value
544 access
= (pte
& 0x30) >> 4 |
(pte
& 0x200) >> 7
545 out_string
+= xnudefines
.arm_level2_access_strings
[access
]
547 #TEX bit [14:12] for large, [8:6] for small
548 tex_bits
= ((pte
& 0x1c0) >> 6)
549 if (pte
& 0x3) == 0x1:
550 tex_bits
= ((pte
& 0x7000) >> 12)
552 # Print TEX, C , B alltogether
553 out_string
+= " TEX:C:B({:d}{:d}{:d}:{:d}:{:d})".format(
554 1 if (tex_bits
& 0x4) else 0,
555 1 if (tex_bits
& 0x2) else 0,
556 1 if (tex_bits
& 0x1) else 0,
562 out_string
+= " shareable"
564 out_string
+= " not-shareable"
568 out_string
+= " not-global"
570 out_string
+= " global"
575 def _PmapWalkARMLevel1Section(tte
, vaddr
, verbose_level
= vSCRIPT
):
577 #Supersection or just section?
578 if (tte
& 0x40000) == 0x40000:
579 paddr
= ( (tte
& 0xFF000000) |
(vaddr
& 0x00FFFFFF) )
581 paddr
= ( (tte
& 0xFFF00000) |
(vaddr
& 0x000FFFFF) )
583 if verbose_level
>= vSCRIPT
:
584 print "{0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(tte
), tte
),
586 PmapDecodeTTEARM(tte
, 1, verbose_level
)
592 def _PmapWalkARMLevel2(tte
, vaddr
, verbose_level
= vSCRIPT
):
593 """ Pmap walk the level 2 tte.
597 returns: str - description of the tte + additional informaiton based on verbose_level
599 pte_base
= kern
.PhysToKernelVirt(tte
& 0xFFFFFC00)
600 pte_index
= (vaddr
>> 12) & 0xFF
601 pte_base_val
= kern
.GetValueFromAddress(pte_base
, 'pt_entry_t *')
602 pte
= pte_base_val
[pte_index
]
606 paddr
= (unsigned(pte
) & 0xFFFFF000) |
(vaddr
& 0xFFF)
608 if verbose_level
>= vSCRIPT
:
609 print "{0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(tte
), tte
),
611 PmapDecodeTTEARM(tte
, 1, verbose_level
)
612 if verbose_level
>= vSCRIPT
:
613 print "second-level table (index {:d}):".format(pte_index
)
614 if verbose_level
>= vDETAIL
:
616 tmp
= pte_base_val
[i
]
617 print "{0: <#020x}:\t{1: <#020x}".format(addressof(tmp
), unsigned(tmp
))
619 if verbose_level
>= vSCRIPT
:
620 print " {0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(pte
), unsigned(pte
)),
622 PmapDecodeTTEARM(pte
, 2, verbose_level
)
625 #end of level 2 walking of arm
628 def PmapWalkARM(pmap
, vaddr
, verbose_level
= vHUMAN
):
629 """ Pmap walking for ARM kernel.
631 pmapval: core.value - representing pmap_t in kernel
632 vaddr: int - integer representing virtual address to walk
635 # shift by TTESHIFT (20) to get tte index
636 # Assume all L1 indexing starts at VA 0...for our purposes it does,
637 # as that's where all user pmaps start, and the kernel pmap contains
638 # 4 L1 pages (the lower 2 of which are unused after bootstrap)
639 tte_index
= vaddr
>> 20
640 tte
= pmap
.tte
[tte_index
]
641 if verbose_level
>= vSCRIPT
:
642 print "First-level table (index {:d}):".format(tte_index
)
643 if verbose_level
>= vDETAIL
:
644 for i
in range(0, pmap
.tte_index_max
):
645 ptr
= unsigned(addressof(pmap
.tte
[i
]))
646 val
= unsigned(pmap
.tte
[i
])
647 print "{0: <#020x}:\t {1: <#020x}".format(ptr
, val
)
648 if (tte
& 0x3) == 0x1:
649 paddr
= _PmapWalkARMLevel2(tte
, vaddr
, verbose_level
)
650 elif (tte
& 0x3) == 0x2 :
651 paddr
= _PmapWalkARMLevel1Section(tte
, vaddr
, verbose_level
)
654 if verbose_level
>= vSCRIPT
:
655 print "Invalid First-Level Translation Table Entry: {0: #020x}".format(tte
)
657 if verbose_level
>= vHUMAN
:
659 print "Translation of {:#x} is {:#x}.".format(vaddr
, paddr
)
661 print "(no translation)"
665 def PmapWalkX86_64(pmapval
, vaddr
, verbose_level
= vSCRIPT
):
667 params: pmapval - core.value representing pmap_t in kernel
668 vaddr: int - int representing virtual address to walk
670 if pmapval
.pm_cr3
!= 0:
671 if verbose_level
> vHUMAN
:
672 print "Using normal Intel PMAP from pm_cr3\n"
673 return _PmapL4Walk(pmapval
.pm_cr3
, vaddr
, 0, config
['verbosity'])
675 if verbose_level
> vHUMAN
:
676 print "Using EPT pmap from pm_eptp\n"
677 return _PmapL4Walk(pmapval
.pm_eptp
, vaddr
, 1, config
['verbosity'])
679 def assert_64bit(val
):
684 ARM64_VMADDR_BITS
= 48
686 def PmapBlockOffsetMaskARM64(level
):
687 assert level
>= 1 and level
<= 3
688 page_size
= kern
.globals.arm_hardware_page_size
689 ttentries
= (page_size
/ ARM64_TTE_SIZE
)
690 return page_size
* (ttentries
** (3 - level
)) - 1
692 def PmapBlockBaseMaskARM64(level
):
693 assert level
>= 1 and level
<= 3
694 page_size
= kern
.globals.arm_hardware_page_size
695 return ((1 << ARM64_VMADDR_BITS
) - 1) & ~
PmapBlockOffsetMaskARM64(level
)
697 def PmapIndexMaskARM64(level
):
698 assert level
>= 1 and level
<= 3
699 page_size
= kern
.globals.arm_hardware_page_size
700 ttentries
= (page_size
/ ARM64_TTE_SIZE
)
701 return page_size
* (ttentries
** (3 - level
) * (ttentries
- 1))
703 def PmapIndexDivideARM64(level
):
704 assert level
>= 1 and level
<= 3
705 page_size
= kern
.globals.arm_hardware_page_size
706 ttentries
= (page_size
/ ARM64_TTE_SIZE
)
707 return page_size
* (ttentries
** (3 - level
))
709 def PmapTTnIndexARM64(vaddr
, level
):
710 assert(type(vaddr
) in (long, int))
713 return (vaddr
& PmapIndexMaskARM64(level
)) // PmapIndexDivideARM64(level
)
715 def PmapDecodeTTEARM64(tte
, level
):
716 """ Display the bits of an ARM64 translation table or page table entry
717 in human-readable form.
718 tte: integer value of the TTE/PTE
719 level: translation table level. Valid values are 1, 2, or 3.
721 assert(type(tte
) == long)
722 assert(type(level
) == int)
726 if (tte
& 0x2 == 0x2) and (level
!= 0x3):
727 print "Type = Table pointer."
728 print "Table addr = {:#x}.".format(tte
& 0xfffffffff000)
729 print "PXN = {:#x}.".format((tte
>> 59) & 0x1)
730 print "XN = {:#x}.".format((tte
>> 60) & 0x1)
731 print "AP = {:#x}.".format((tte
>> 61) & 0x3)
732 print "NS = {:#x}".format(tte
>> 63)
734 print "Type = Block."
735 print "AttrIdx = {:#x}.".format((tte
>> 2) & 0x7)
736 print "NS = {:#x}.".format((tte
>> 5) & 0x1)
737 print "AP = {:#x}.".format((tte
>> 6) & 0x3)
738 print "SH = {:#x}.".format((tte
>> 8) & 0x3)
739 print "AF = {:#x}.".format((tte
>> 10) & 0x1)
740 print "nG = {:#x}.".format((tte
>> 11) & 0x1)
741 print "HINT = {:#x}.".format((tte
>> 52) & 0x1)
742 print "PXN = {:#x}.".format((tte
>> 53) & 0x1)
743 print "XN = {:#x}.".format((tte
>> 54) & 0x1)
744 print "SW Use = {:#x}.".format((tte
>> 55) & 0xf)
750 def PmapWalkARM64(pmap
, vaddr
, verbose_level
= vHUMAN
):
751 assert(type(pmap
) == core
.cvalue
.value
)
752 assert(type(vaddr
) in (long, int))
753 page_size
= kern
.globals.arm_hardware_page_size
754 page_offset_mask
= (page_size
- 1)
755 page_base_mask
= ((1 << ARM64_VMADDR_BITS
) - 1) & (~page_offset_mask
)
761 tt1_index
= PmapTTnIndexARM64(vaddr
, 1)
762 tt2_index
= PmapTTnIndexARM64(vaddr
, 2)
763 tt3_index
= PmapTTnIndexARM64(vaddr
, 3)
765 # The pmap starts at a page tabel level that is defined by register
766 # values; the kernel exports the root level for LLDB
767 level
= kern
.globals.arm64_root_pgtable_level
771 root_tt_index
= tt0_index
773 root_tt_index
= tt1_index
775 root_tt_index
= tt2_index
777 root_tt_index
= tt3_index
779 # If the root of the page table is not a full page, we need to
781 root_tt_index
= root_tt_index
% unsigned(kern
.globals.arm64_root_pgtable_num_ttes
)
783 tte
= long(unsigned(pmap
.tte
[root_tt_index
]))
784 assert(type(tte
) == long)
790 # This is unsupported at the moment, as no kernel configurations use L0
795 if verbose_level
>= vSCRIPT
:
796 print "L1 entry: {:#x}".format(tte
)
797 if verbose_level
>= vDETAIL
:
798 PmapDecodeTTEARM64(tte
, 1)
801 # Check for L1 block entry
803 # Handle L1 block entry
804 paddr
= tte
& PmapBlockBaseMaskARM64(1)
805 paddr
= paddr |
(vaddr
& PmapBlockOffsetMaskARM64(1))
806 print "phys: {:#x}".format(paddr
)
809 # Handle L1 table entry
810 l2_phys
= (tte
& page_base_mask
) + (ARM64_TTE_SIZE
* tt2_index
)
811 assert(type(l2_phys
) == long)
813 l2_virt
= kern
.PhysToKernelVirt(l2_phys
)
814 assert(type(l2_virt
) == long)
816 if verbose_level
>= vDETAIL
:
817 print "L2 physical address: {:#x}. L2 virtual address: {:#x}".format(l2_phys
, l2_virt
)
819 ttep
= kern
.GetValueFromAddress(l2_virt
, "tt_entry_t*")
820 tte
= long(unsigned(dereference(ttep
)))
821 assert(type(tte
) == long)
822 elif verbose_level
>= vHUMAN
:
823 print "L1 entry invalid: {:#x}\n".format(tte
)
827 if verbose_level
>= vSCRIPT
:
828 print "L2 entry: {:#0x}".format(tte
)
829 if verbose_level
>= vDETAIL
:
830 PmapDecodeTTEARM64(tte
, 2)
833 # Check for L2 block entry
835 # Handle L2 block entry
836 paddr
= tte
& PmapBlockBaseMaskARM64(2)
837 paddr
= paddr |
(vaddr
& PmapBlockOffsetMaskARM64(2))
840 # Handle L2 table entry
841 l3_phys
= (tte
& page_base_mask
) + (ARM64_TTE_SIZE
* tt3_index
)
842 assert(type(l3_phys
) == long)
844 l3_virt
= kern
.PhysToKernelVirt(l3_phys
)
845 assert(type(l3_virt
) == long)
847 if verbose_level
>= vDETAIL
:
848 print "L3 physical address: {:#x}. L3 virtual address: {:#x}".format(l3_phys
, l3_virt
)
850 ttep
= kern
.GetValueFromAddress(l3_virt
, "tt_entry_t*")
851 tte
= long(unsigned(dereference(ttep
)))
852 assert(type(tte
) == long)
853 elif verbose_level
>= vHUMAN
: # tte & 0x1 == 0x1
854 print "L2 entry invalid: {:#x}\n".format(tte
)
858 if verbose_level
>= vSCRIPT
:
859 print "L3 entry: {:#0x}".format(tte
)
860 if verbose_level
>= vDETAIL
:
861 PmapDecodeTTEARM64(tte
, 3)
864 paddr
= tte
& page_base_mask
865 paddr
= paddr |
(vaddr
& page_offset_mask
)
866 elif verbose_level
>= vHUMAN
:
867 print "L3 entry invalid: {:#x}\n".format(tte
)
869 # This was the leaf page table page for this request; we're done
872 # We've parsed one level, so go to the next level
876 if verbose_level
>= vHUMAN
:
878 print "Translation of {:#x} is {:#x}.".format(vaddr
, paddr
)
880 print "(no translation)"
884 def PmapWalk(pmap
, vaddr
, verbose_level
= vHUMAN
):
885 if kern
.arch
== 'x86_64':
886 return PmapWalkX86_64(pmap
, vaddr
, verbose_level
)
887 elif kern
.arch
== 'arm':
888 return PmapWalkARM(pmap
, vaddr
, verbose_level
)
889 elif kern
.arch
.startswith('arm64'):
890 return PmapWalkARM64(pmap
, vaddr
, verbose_level
)
892 raise NotImplementedError("PmapWalk does not support {0}".format(kern
.arch
))
894 @lldb_command('pmap_walk')
895 def PmapWalkHelper(cmd_args
=None):
896 """ Perform a page-table walk in <pmap> for <virtual_address>.
897 Syntax: (lldb) pmap_walk <pmap> <virtual_address> [-v] [-e]
898 Multiple -v's can be specified for increased verbosity
900 if cmd_args
== None or len(cmd_args
) < 2:
901 raise ArgumentError("Too few arguments to pmap_walk.")
903 pmap
= kern
.GetValueAsType(cmd_args
[0], 'pmap_t')
904 addr
= unsigned(kern
.GetValueFromAddress(cmd_args
[1], 'void *'))
905 PmapWalk(pmap
, addr
, config
['verbosity'])
908 @lldb_command('decode_tte')
909 def DecodeTTE(cmd_args
=None):
910 """ Decode the bits in the TTE/PTE value specified <tte_val> for translation level <level>
911 Syntax: (lldb) decode_tte <tte_val> <level>
913 if cmd_args
== None or len(cmd_args
) < 2:
914 raise ArgumentError("Too few arguments to decode_tte.")
915 if kern
.arch
== 'arm':
916 PmapDecodeTTEARM(kern
.GetValueFromAddress(cmd_args
[0], "unsigned long"), ArgumentStringToInt(cmd_args
[1]), vSCRIPT
)
917 elif kern
.arch
.startswith('arm64'):
918 PmapDecodeTTEARM64(long(kern
.GetValueFromAddress(cmd_args
[0], "unsigned long")), ArgumentStringToInt(cmd_args
[1]))
920 raise NotImplementedError("decode_tte does not support {0}".format(kern
.arch
))
923 PVH_HIGH_FLAGS_ARM64
= (1 << 62) |
(1 << 61) |
(1 << 60) |
(1 << 59)
924 PVH_HIGH_FLAGS_ARM32
= (1 << 31)
927 """ Walk a physical-to-virtual reverse mapping list maintained by the arm pmap
928 pa: physical address (NOT page number). Does not need to be page-aligned
930 vm_first_phys
= unsigned(kern
.globals.vm_first_phys
)
931 vm_last_phys
= unsigned(kern
.globals.vm_last_phys
)
932 if pa
< vm_first_phys
or pa
>= vm_last_phys
:
933 raise ArgumentError("PA {:#x} is outside range of managed physical addresses: [{:#x}, {:#x})".format(pa
, vm_first_phys
, vm_last_phys
))
934 page_size
= kern
.globals.page_size
935 pn
= (pa
- unsigned(kern
.globals.vm_first_phys
)) / page_size
936 pvh
= unsigned(kern
.globals.pv_head_table
[pn
])
938 print "PVH raw value: ({:#x})".format(pvh
)
939 if kern
.arch
.startswith('arm64'):
941 iommu_table_flag
= 1 << 63
942 pvh
= pvh | PVH_HIGH_FLAGS_ARM64
946 pvh
= pvh | PVH_HIGH_FLAGS_ARM32
948 print "PVH type: NULL"
951 print "PVH type: page-table descriptor ({:#x})".format(pvh
& ~
0x3)
956 print "PVH type: single PTE"
957 if ptep
& iommu_flag
:
958 ptep
= ptep
& ~iommu_flag
959 if ptep
& iommu_table_flag
:
960 pte_str
= ' (IOMMU table), entry'
962 pte_str
= ' (IOMMU state), descriptor'
963 ptep
= ptep | iommu_table_flag
964 print "PTE {:#x}{:s}: {:#x}".format(ptep
, pte_str
, dereference(kern
.GetValueFromAddress(ptep
, 'pt_entry_t *')))
967 print "PVH type: PTE list"
969 pve
= kern
.GetValueFromAddress(pvep
, "pv_entry_t *")
970 if unsigned(pve
.pve_next
) & 0x1:
971 pve_str
= ' (alt acct) '
975 pvep
= unsigned(pve
.pve_next
) & ~
0x1
976 ptep
= unsigned(pve
.pve_ptep
) & ~
0x3
977 if ptep
& iommu_flag
:
978 ptep
= ptep
& ~iommu_flag
979 if ptep
& iommu_table_flag
:
980 pve_str
= ' (IOMMU table), entry'
982 pve_str
= ' (IOMMU state), descriptor'
983 ptep
= ptep | iommu_table_flag
984 print "PVE {:#x}, PTE {:#x}{:s}: {:#x}".format(current_pvep
, ptep
, pve_str
, dereference(kern
.GetValueFromAddress(ptep
, 'pt_entry_t *')))
986 @lldb_command('pv_walk')
987 def PVWalk(cmd_args
=None):
988 """ Show mappings for <physical_address> tracked in the PV list.
989 Syntax: (lldb) pv_walk <physical_address>
991 if cmd_args
== None or len(cmd_args
) < 1:
992 raise ArgumentError("Too few arguments to pv_walk.")
993 if not kern
.arch
.startswith('arm'):
994 raise NotImplementedError("pv_walk does not support {0}".format(kern
.arch
))
995 PVWalkARM(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long'))
997 @lldb_command('kvtophys')
998 def KVToPhys(cmd_args
=None):
999 """ Translate a kernel virtual address to the corresponding physical address.
1000 Assumes the virtual address falls within the kernel static region.
1001 Syntax: (lldb) kvtophys <kernel virtual address>
1003 if cmd_args
== None or len(cmd_args
) < 1:
1004 raise ArgumentError("Too few arguments to kvtophys.")
1005 if kern
.arch
.startswith('arm'):
1006 print "{:#x}".format(KVToPhysARM(long(unsigned(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long')))))
1007 elif kern
.arch
== 'x86_64':
1008 print "{:#x}".format(long(unsigned(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long'))) - unsigned(kern
.globals.physmap_base
))
1010 @lldb_command('phystokv')
1011 def PhysToKV(cmd_args
=None):
1012 """ Translate a physical address to the corresponding static kernel virtual address.
1013 Assumes the physical address corresponds to managed DRAM.
1014 Syntax: (lldb) phystokv <physical address>
1016 if cmd_args
== None or len(cmd_args
) < 1:
1017 raise ArgumentError("Too few arguments to phystokv.")
1018 print "{:#x}".format(kern
.PhysToKernelVirt(long(unsigned(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long')))))
1020 def KVToPhysARM(addr
):
1021 if kern
.arch
.startswith('arm64'):
1022 ptov_table
= kern
.globals.ptov_table
1023 for i
in range(0, kern
.globals.ptov_index
):
1024 if (addr
>= long(unsigned(ptov_table
[i
].va
))) and (addr
< (long(unsigned(ptov_table
[i
].va
)) + long(unsigned(ptov_table
[i
].len)))):
1025 return (addr
- long(unsigned(ptov_table
[i
].va
)) + long(unsigned(ptov_table
[i
].pa
)))
1026 return (addr
- unsigned(kern
.globals.gVirtBase
) + unsigned(kern
.globals.gPhysBase
))
1028 def ShowPTEARM(pte
):
1029 """ Display vital information about an ARM page table entry
1030 pte: kernel virtual address of the PTE. Should be L3 PTE. May also work with L2 TTEs for certain devices.
1032 page_size
= kern
.globals.arm_hardware_page_size
1033 pn
= (KVToPhysARM(pte
) - unsigned(kern
.globals.vm_first_phys
)) / page_size
1034 pvh
= unsigned(kern
.globals.pv_head_table
[pn
])
1035 if kern
.arch
.startswith('arm64'):
1036 pvh
= pvh | PVH_HIGH_FLAGS_ARM64
1038 pvh
= pvh | PVH_HIGH_FLAGS_ARM32
1039 pvh_type
= pvh
& 0x3
1041 raise ValueError("PV head {:#x} does not correspond to a page-table descriptor".format(pvh
))
1042 ptd
= kern
.GetValueFromAddress(pvh
& ~
0x3, 'pt_desc_t *')
1043 print "descriptor: {:#x}".format(ptd
)
1044 print "pmap: {:#x}".format(ptd
.pmap
)
1045 pt_index
= (pte
% kern
.globals.page_size
) / page_size
1046 pte_pgoff
= pte
% page_size
1047 if kern
.arch
.startswith('arm64'):
1048 pte_pgoff
= pte_pgoff
/ 8
1049 nttes
= page_size
/ 8
1051 pte_pgoff
= pte_pgoff
/ 4
1052 nttes
= page_size
/ 4
1053 if ptd
.pt_cnt
[pt_index
].refcnt
== 0x4000:
1055 granule
= nttes
* page_size
1059 print "maps VA: {:#x}".format(long(unsigned(ptd
.pt_map
[pt_index
].va
)) + (pte_pgoff
* granule
))
1060 pteval
= long(unsigned(dereference(kern
.GetValueFromAddress(unsigned(pte
), 'pt_entry_t *'))))
1061 print "value: {:#x}".format(pteval
)
1062 if kern
.arch
.startswith('arm64'):
1063 print "level: {:d}".format(level
)
1064 PmapDecodeTTEARM64(pteval
, level
)
1065 elif kern
.arch
== 'arm':
1066 PmapDecodeTTEARM(pteval
, 2, vSCRIPT
)
1068 @lldb_command('showpte')
1069 def ShowPTE(cmd_args
=None):
1070 """ Display vital information about the page table entry at VA <pte>
1071 Syntax: (lldb) showpte <pte_va>
1073 if cmd_args
== None or len(cmd_args
) < 1:
1074 raise ArgumentError("Too few arguments to showpte.")
1075 if not kern
.arch
.startswith('arm'):
1076 raise NotImplementedError("showpte does not support {0}".format(kern
.arch
))
1077 ShowPTEARM(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long'))
1079 def FindMappingAtLevelARM(pmap
, tt
, nttes
, level
, action
):
1080 """ Perform the specified action for all valid mappings in an ARM translation table
1081 pmap: owner of the translation table
1082 tt: translation table or page table
1083 nttes: number of entries in tt
1084 level: translation table level, 1 or 2
1085 action: callback for each valid TTE
1087 for i
in range(nttes
):
1091 if tte
& 0x3 == 0x1:
1094 paddr
= tte
& 0xFFFFFC00
1095 elif tte
& 0x3 == 0x2:
1097 if (tte
& 0x40000) == 0x40000:
1099 paddr
= tte
& 0xFF000000
1102 paddr
= tte
& 0xFFF00000
1105 elif (tte
& 0x3) == 0x1:
1108 paddr
= tte
& 0xFFFF0000
1109 elif (tte
& 0x3) != 0:
1112 paddr
= tte
& 0xFFFFF000
1115 action(pmap
, level
, type, addressof(tt
[i
]), paddr
, granule
)
1116 if level
== 1 and (tte
& 0x3) == 0x1:
1117 tt_next
= kern
.GetValueFromAddress(kern
.PhysToKernelVirt(paddr
), 'tt_entry_t *')
1118 FindMappingAtLevelARM(pmap
, tt_next
, granule
/ 4, level
+ 1, action
)
1119 except Exception as exc
:
1120 print "Unable to access tte {:#x}".format(unsigned(addressof(tt
[i
])))
1122 def FindMappingAtLevelARM64(pmap
, tt
, nttes
, level
, action
):
1123 """ Perform the specified action for all valid mappings in an ARM64 translation table
1124 pmap: owner of the translation table
1125 tt: translation table or page table
1126 nttes: number of entries in tt
1127 level: translation table level, 1 2 or 3
1128 action: callback for each valid TTE
1130 page_size
= kern
.globals.arm_hardware_page_size
1131 page_offset_mask
= (page_size
- 1)
1132 page_base_mask
= ((1 << ARM64_VMADDR_BITS
) - 1) & (~page_offset_mask
)
1133 for i
in range(nttes
):
1136 if tte
& 0x1 == 0x1:
1137 if tte
& 0x2 == 0x2:
1143 paddr
= tte
& page_base_mask
1146 granule
= PmapBlockOffsetMaskARM64(level
) + 1
1147 paddr
= tte
& PmapBlockBaseMaskARM64(level
)
1150 action(pmap
, level
, type, addressof(tt
[i
]), paddr
, granule
)
1151 if level
< 3 and (tte
& 0x2 == 0x2):
1152 tt_next
= kern
.GetValueFromAddress(kern
.PhysToKernelVirt(paddr
), 'tt_entry_t *')
1153 FindMappingAtLevelARM64(pmap
, tt_next
, granule
/ ARM64_TTE_SIZE
, level
+ 1, action
)
1154 except Exception as exc
:
1155 print "Unable to access tte {:#x}".format(unsigned(addressof(tt
[i
])))
1157 def ScanPageTables(action
, targetPmap
=None):
1158 """ Perform the specified action for all valid mappings in all page tables,
1159 optionally restricted to a single pmap.
1160 pmap: pmap whose page table should be scanned. If None, all pmaps on system will be scanned.
1162 print "Scanning all available translation tables. This may take a long time..."
1163 def ScanPmap(pmap
, action
):
1164 if kern
.arch
.startswith('arm64'):
1165 granule
= kern
.globals.arm64_root_pgtable_num_ttes
* 8
1166 elif kern
.arch
== 'arm':
1167 granule
= pmap
.tte_index_max
* 4
1168 action(pmap
, 1, 'root', pmap
.tte
, unsigned(pmap
.ttep
), granule
)
1169 if kern
.arch
.startswith('arm64'):
1170 FindMappingAtLevelARM64(pmap
, pmap
.tte
, kern
.globals.arm64_root_pgtable_num_ttes
, kern
.globals.arm64_root_pgtable_level
, action
)
1171 elif kern
.arch
== 'arm':
1172 FindMappingAtLevelARM(pmap
, pmap
.tte
, pmap
.tte_index_max
, 1, action
)
1174 if targetPmap
is not None:
1175 ScanPmap(kern
.GetValueFromAddress(targetPmap
, 'pmap_t'), action
)
1177 for pmap
in IterateQueue(kern
.globals.map_pmap_list
, 'pmap_t', 'pmaps'):
1178 ScanPmap(pmap
, action
)
1180 @lldb_command('showallmappings')
1181 def ShowAllMappings(cmd_args
=None):
1182 """ Find and display all available mappings on the system for
1183 <physical_address>. Optionally only searches the pmap
1184 specified by [<pmap>]
1185 Syntax: (lldb) showallmappings <physical_address> [<pmap>]
1186 WARNING: this macro can take a long time (up to 30min.) to complete!
1188 if cmd_args
== None or len(cmd_args
) < 1:
1189 raise ArgumentError("Too few arguments to showallmappings.")
1190 if not kern
.arch
.startswith('arm'):
1191 raise NotImplementedError("showallmappings does not support {0}".format(kern
.arch
))
1192 pa
= kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long')
1194 if len(cmd_args
) > 1:
1195 targetPmap
= cmd_args
[1]
1196 def printMatchedMapping(pmap
, level
, type, tte
, paddr
, granule
):
1197 if paddr
<= pa
< (paddr
+ granule
):
1198 print "pmap: {:#x}: L{:d} {:s} at {:#x}: [{:#x}, {:#x})".format(pmap
, level
, type, unsigned(tte
), paddr
, paddr
+ granule
)
1199 ScanPageTables(printMatchedMapping
, targetPmap
)
1201 def checkPVList(pmap
, level
, type, tte
, paddr
, granule
):
1202 """ Checks an ARM physical-to-virtual mapping list for consistency errors.
1203 pmap: owner of the translation table
1204 level: translation table level. PV lists will only be checked for L2 (arm32) or L3 (arm64) tables.
1206 tte: KVA of PTE to check for presence in PV list. If None, presence check will be skipped.
1207 paddr: physical address whose PV list should be checked. Need not be page-aligned.
1210 vm_first_phys
= unsigned(kern
.globals.vm_first_phys
)
1211 vm_last_phys
= unsigned(kern
.globals.vm_last_phys
)
1212 page_size
= kern
.globals.page_size
1213 if kern
.arch
.startswith('arm64'):
1214 page_offset_mask
= (page_size
- 1)
1215 page_base_mask
= ((1 << ARM64_VMADDR_BITS
) - 1) & (~page_offset_mask
)
1216 paddr
= paddr
& page_base_mask
1218 pvh_set_bits
= PVH_HIGH_FLAGS_ARM64
1219 elif kern
.arch
== 'arm':
1220 page_base_mask
= 0xFFFFF000
1221 paddr
= paddr
& page_base_mask
1223 pvh_set_bits
= PVH_HIGH_FLAGS_ARM32
1224 if level
< max_level
or paddr
< vm_first_phys
or paddr
>= vm_last_phys
:
1226 pn
= (paddr
- vm_first_phys
) / page_size
1227 pvh
= unsigned(kern
.globals.pv_head_table
[pn
]) | pvh_set_bits
1228 pvh_type
= pvh
& 0x3
1229 if pmap
is not None:
1230 pmap_str
= "pmap: {:#x}: ".format(pmap
)
1234 tte_str
= "pte {:#x} ({:#x}): ".format(unsigned(tte
), paddr
)
1236 tte_str
= "paddr {:#x}: ".format(paddr
)
1237 if pvh_type
== 0 or pvh_type
== 3:
1238 print "{:s}{:s}unexpected PVH type {:d}".format(pmap_str
, tte_str
, pvh_type
)
1241 if tte
is not None and ptep
!= unsigned(tte
):
1242 print "{:s}{:s}PVH mismatch ({:#x})".format(pmap_str
, tte_str
, ptep
)
1244 pte
= long(unsigned(dereference(kern
.GetValueFromAddress(ptep
, 'pt_entry_t *')))) & page_base_mask
1246 print "{:s}{:s}PVH {:#x} maps wrong page ({:#x}) ".format(pmap_str
, tte_str
, ptep
, pte
)
1247 except Exception as exc
:
1248 print "{:s}{:s}Unable to read PVH {:#x}".format(pmap_str
, tte_str
, ptep
)
1253 pve
= kern
.GetValueFromAddress(pvep
, "pv_entry_t *")
1254 pvep
= unsigned(pve
.pve_next
) & ~
0x1
1255 ptep
= unsigned(pve
.pve_ptep
) & ~
0x3
1256 if tte
is not None and ptep
== unsigned(tte
):
1259 pte
= long(unsigned(dereference(kern
.GetValueFromAddress(ptep
, 'pt_entry_t *')))) & page_base_mask
1261 print "{:s}{:s}PVE {:#x} maps wrong page ({:#x}) ".format(pmap_str
, tte_str
, ptep
, pte
)
1262 except Exception as exc
:
1263 print "{:s}{:s}Unable to read PVE {:#x}".format(pmap_str
, tte_str
, ptep
)
1264 if tte
is not None and not tte_match
:
1265 print "{:s}{:s}not found in PV list".format(pmap_str
, tte_str
, paddr
)
1267 @lldb_command('pv_check', 'P')
1268 def PVCheck(cmd_args
=None, cmd_options
={}):
1269 """ Check the physical-to-virtual mapping for a given PTE or physical address
1270 Syntax: (lldb) pv_check <addr> [-p]
1271 -P : Interpret <addr> as a physical address rather than a PTE
1273 if cmd_args
== None or len(cmd_args
) < 1:
1274 raise ArgumentError("Too few arguments to pv_check.")
1275 if kern
.arch
== 'arm':
1277 elif kern
.arch
.startswith('arm64'):
1280 raise NotImplementedError("showallmappings does not support {0}".format(kern
.arch
))
1281 if "-P" in cmd_options
:
1283 pa
= long(unsigned(kern
.GetValueFromAddress(cmd_args
[0], "unsigned long")))
1285 pte
= kern
.GetValueFromAddress(cmd_args
[0], 'pt_entry_t *')
1286 pa
= long(unsigned(dereference(pte
)))
1287 checkPVList(None, level
, None, pte
, pa
, None)
1289 @lldb_command('check_pmaps')
1290 def CheckPmapIntegrity(cmd_args
=None):
1291 """ Performs a system-wide integrity check of all PTEs and associated PV lists.
1292 Optionally only checks the pmap specified by [<pmap>]
1293 Syntax: (lldb) check_pmaps [<pmap>]
1294 WARNING: this macro can take a HUGE amount of time (several hours) if you do not
1295 specify [pmap] to limit it to a single pmap. It will also give false positives
1296 for kernel_pmap, as we do not create PV entries for static kernel mappings on ARM.
1297 Use of this macro without the [<pmap>] argument is heavily discouraged.
1299 if not kern
.arch
.startswith('arm'):
1300 raise NotImplementedError("showallmappings does not support {0}".format(kern
.arch
))
1302 if len(cmd_args
) > 0:
1303 targetPmap
= cmd_args
[0]
1304 ScanPageTables(checkPVList
, targetPmap
)
1306 @lldb_command('pmapsforledger')
1307 def PmapsForLedger(cmd_args
=None):
1308 """ Find and display all pmaps currently using <ledger>.
1309 Syntax: (lldb) pmapsforledger <ledger>
1311 if cmd_args
== None or len(cmd_args
) < 1:
1312 raise ArgumentError("Too few arguments to pmapsforledger.")
1313 if not kern
.arch
.startswith('arm'):
1314 raise NotImplementedError("pmapsforledger does not support {0}".format(kern
.arch
))
1315 ledger
= kern
.GetValueFromAddress(cmd_args
[0], 'ledger_t')
1316 for pmap
in IterateQueue(kern
.globals.map_pmap_list
, 'pmap_t', 'pmaps'):
1317 if pmap
.ledger
== ledger
:
1318 print "pmap: {:#x}".format(pmap
)