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 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 is_cpu64_bit
= int(kern
.globals.cpu_64bit
)
385 pt_paddr
= unsigned(pmap_addr_val
)
386 pt_valid
= (unsigned(pmap_addr_val
) != 0)
389 if pt_valid
and is_cpu64_bit
:
390 # Lookup bits 47:39 of linear address in PML4T
391 pt_index
= (vaddr
>> 39) & 0x1ff
392 pframe_offset
= vaddr
& 0x7fffffffff
393 if verbose_level
> vHUMAN
:
394 print "pml4 (index {0:d}):".format(pt_index
)
396 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
398 (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
)
400 # Lookup bits 38:30 of the linear address in PDPT
401 pt_index
= (vaddr
>> 30) & 0x1ff
402 pframe_offset
= vaddr
& 0x3fffffff
403 if verbose_level
> vHUMAN
:
404 print "pdpt (index {0:d}):".format(pt_index
)
406 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
408 (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
)
409 if pt_valid
and not pt_large
:
410 #Lookup bits 29:21 of the linear address in PDPT
411 pt_index
= (vaddr
>> 21) & 0x1ff
412 pframe_offset
= vaddr
& 0x1fffff
413 if verbose_level
> vHUMAN
:
414 print "pdt (index {0:d}):".format(pt_index
)
416 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
418 (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
)
419 if pt_valid
and not pt_large
:
420 #Lookup bits 20:21 of linear address in PT
421 pt_index
= (vaddr
>> 12) & 0x1ff
422 pframe_offset
= vaddr
& 0xfff
423 if verbose_level
> vHUMAN
:
424 print "pt (index {0:d}):".format(pt_index
)
426 (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
)
428 (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
)
430 paddr_isvalid
= False
432 paddr
= pt_paddr
+ pframe_offset
435 if verbose_level
> vHUMAN
:
437 pvalue
= ReadPhysInt(paddr
, 32, xnudefines
.lcpu_self
)
438 print "phys {0: <#020x}: {1: <#020x}".format(paddr
, pvalue
)
440 print "no translation"
444 def _PmapWalkARMLevel1Section(tte
, vaddr
, verbose_level
= vSCRIPT
):
447 #Supersection or just section?
448 if (tte
& 0x40000) == 0x40000:
449 paddr
= ( (tte
& 0xFF000000) |
(vaddr
& 0x00FFFFFF) )
451 paddr
= ( (tte
& 0xFFF00000) |
(vaddr
& 0x000FFFFF) )
453 if verbose_level
>= vSCRIPT
:
454 out_string
+= "{0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(tte
), tte
)
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"
510 def _PmapWalkARMLevel2(tte
, vaddr
, verbose_level
= vSCRIPT
):
511 """ Pmap walk the level 2 tte.
515 returns: str - description of the tte + additional informaiton based on verbose_level
517 pte_base
= kern
.PhysToKernelVirt(tte
& 0xFFFFFC00)
518 pte_index
= (vaddr
>> 12) & 0xFF
519 pte_base_val
= kern
.GetValueFromAddress(pte_base
, 'pt_entry_t *')
520 pte
= pte_base_val
[pte_index
]
522 if verbose_level
>= vSCRIPT
:
523 out_string
+= "{0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(tte
), tte
)
524 # bit [1:0] evaluated in PmapWalkARM
527 out_string
+= ' no-secure'
529 out_string
+= ' secure'
531 out_string
+= " domain({:d})".format(((tte
& 0x1e0) >> 5))
533 out_string
+= " imp({:d})".format( ((tte
& 0x200) >> 9))
535 if verbose_level
>= vSCRIPT
:
536 out_string
+= "second-level table (index {:d}):\n".format(pte_index
)
537 if verbose_level
>= vDETAIL
:
539 tmp
= pte_base_val
[i
]
540 out_string
+= "{0: <#020x}:\t{1: <#020x}\n".format(addressof(tmp
), unsigned(tmp
))
544 paddr
= (unsigned(pte
) & 0xFFFFF000) |
(vaddr
& 0xFFF)
546 if verbose_level
>= vSCRIPT
:
547 out_string
+= " {0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(pte
), unsigned(pte
))
548 if (pte
& 0x3) == 0x0:
549 out_string
+= " invalid"
551 if (pte
& 0x3) == 0x1:
552 out_string
+= " large"
554 if pte
& 0x8000 == 0x8000:
555 out_string
+= " no-execute"
557 out_string
+= " execute"
559 out_string
+= " small"
561 if (pte
& 0x1) == 0x01:
562 out_string
+= " no-execute"
564 out_string
+= " execute"
566 b_bit
= (pte
& 0x4) >> 2
567 c_bit
= (pte
& 0x8) >> 3
568 # AP bit 9 and [5:4], merged to a single 3-bit value
569 access
= (pte
& 0x30) >> 4 |
(pte
& 0x200) >> 7
570 out_string
+= xnudefines
.arm_level2_access_strings
[access
]
572 #TEX bit [14:12] for large, [8:6] for small
573 tex_bits
= ((pte
& 0x1c0) >> 6)
574 if (pte
& 0x3) == 0x1:
575 tex_bits
= ((pte
& 0x7000) >> 12)
577 # Print TEX, C , B alltogether
578 out_string
+= " TEX:C:B({:d}{:d}{:d}:{:d}:{:d})".format(
579 1 if (tex_bits
& 0x4) else 0,
580 1 if (tex_bits
& 0x2) else 0,
581 1 if (tex_bits
& 0x1) else 0,
587 out_string
+= " shareable"
589 out_string
+= " not-shareable"
593 out_string
+= " not-global"
595 out_string
+= " global"
598 #end of level 2 walking of arm
601 def PmapWalkARM(pmap
, vaddr
, verbose_level
= vHUMAN
):
602 """ Pmap walking for ARM kernel.
604 pmapval: core.value - representing pmap_t in kernel
605 vaddr: int - integer representing virtual address to walk
608 # shift by TTESHIFT (20) to get tte index
609 tte_index
= ((vaddr
- unsigned(pmap
.min)) >> 20 )
610 tte
= pmap
.tte
[tte_index
]
611 if verbose_level
>= vSCRIPT
:
612 print "First-level table (index {:d}):".format(tte_index
)
613 if verbose_level
>= vDETAIL
:
614 for i
in range(0, 4096):
615 ptr
= unsigned(addressof(pmap
.tte
[i
]))
616 val
= unsigned(pmap
.tte
[i
])
617 print "{0: <#020x}:\t {1: <#020x}".format(ptr
, val
)
618 if (tte
& 0x3) == 0x1:
619 paddr
= _PmapWalkARMLevel2(tte
, vaddr
, verbose_level
)
620 elif (tte
& 0x3) == 0x2 :
621 paddr
= _PmapWalkARMLevel1Section(tte
, vaddr
, verbose_level
)
624 if verbose_level
>= vSCRIPT
:
625 print "Invalid First-Level Translation Table Entry: {0: #020x}".format(tte
)
627 if verbose_level
>= vHUMAN
:
629 print "Translation of {:#x} is {:#x}.".format(vaddr
, paddr
)
631 print "(no translation)"
635 def PmapWalkX86_64(pmapval
, vaddr
, verbose_level
= vSCRIPT
):
637 params: pmapval - core.value representing pmap_t in kernel
638 vaddr: int - int representing virtual address to walk
640 if pmapval
.pm_cr3
!= 0:
641 if verbose_level
> vHUMAN
:
642 print "Using normal Intel PMAP from pm_cr3\n"
643 return _PmapL4Walk(pmapval
.pm_cr3
, vaddr
, 0, config
['verbosity'])
645 if verbose_level
> vHUMAN
:
646 print "Using EPT pmap from pm_eptp\n"
647 return _PmapL4Walk(pmapval
.pm_eptp
, vaddr
, 1, config
['verbosity'])
649 def assert_64bit(val
):
653 ARM64_VMADDR_BITS
= 48
655 def PmapBlockOffsetMaskARM64(level
):
656 assert level
>= 1 and level
<= 3
657 page_size
= kern
.globals.arm_hardware_page_size
658 ttentries
= (page_size
/ ARM64_TTE_SIZE
)
659 return page_size
* (ttentries
** (3 - level
)) - 1
661 def PmapBlockBaseMaskARM64(level
):
662 assert level
>= 1 and level
<= 3
663 page_size
= kern
.globals.arm_hardware_page_size
664 return ((1 << ARM64_VMADDR_BITS
) - 1) & ~
PmapBlockOffsetMaskARM64(level
)
666 def PmapIndexMaskARM64(level
):
667 assert level
>= 1 and level
<= 3
668 page_size
= kern
.globals.arm_hardware_page_size
669 ttentries
= (page_size
/ ARM64_TTE_SIZE
)
670 return page_size
* (ttentries
** (3 - level
) * (ttentries
- 1))
672 def PmapIndexDivideARM64(level
):
673 assert level
>= 1 and level
<= 3
674 page_size
= kern
.globals.arm_hardware_page_size
675 ttentries
= (page_size
/ ARM64_TTE_SIZE
)
676 return page_size
* (ttentries
** (3 - level
))
678 def PmapTTnIndexARM64(vaddr
, level
):
679 assert(type(vaddr
) in (long, int))
682 return (vaddr
& PmapIndexMaskARM64(level
)) // PmapIndexDivideARM64(level
)
684 def PmapDecodeTTEARM64(tte
, level
):
685 assert(type(tte
) == long)
686 assert(type(level
) == int)
690 if (tte
& 0x2 == 0x2) and (level
!= 0x3):
691 print "Type = Table pointer."
692 print "Table addr = {:#x}.".format(tte
& 0xfffffffff000)
693 print "PXN = {:#x}.".format((tte
>> 59) & 0x1)
694 print "XN = {:#x}.".format((tte
>> 60) & 0x1)
695 print "AP = {:#x}.".format((tte
>> 61) & 0x3)
696 print "NS = {:#x}".format(tte
>> 63)
698 print "Type = Block."
699 print "AttrIdx = {:#x}.".format((tte
>> 2) & 0x7)
700 print "NS = {:#x}.".format((tte
>> 5) & 0x1)
701 print "AP = {:#x}.".format((tte
>> 6) & 0x3)
702 print "SH = {:#x}.".format((tte
>> 8) & 0x3)
703 print "AF = {:#x}.".format((tte
>> 10) & 0x1)
704 print "nG = {:#x}.".format((tte
>> 11) & 0x1)
705 print "HINT = {:#x}.".format((tte
>> 52) & 0x1)
706 print "PXN = {:#x}.".format((tte
>> 53) & 0x1)
707 print "XN = {:#x}.".format((tte
>> 54) & 0x1)
708 print "SW Use = {:#x}.".format((tte
>> 55) & 0xf)
714 def PmapWalkARM64(pmap
, vaddr
, verbose_level
= vHUMAN
):
715 assert(type(pmap
) == core
.cvalue
.value
)
716 assert(type(vaddr
) in (long, int))
717 page_size
= kern
.globals.arm_hardware_page_size
718 page_offset_mask
= (page_size
- 1)
719 page_base_mask
= ((1 << ARM64_VMADDR_BITS
) - 1) & (~page_offset_mask
)
724 tt1_index
= PmapTTnIndexARM64(vaddr
, 1)
725 tt2_index
= PmapTTnIndexARM64(vaddr
, 2)
726 tt3_index
= PmapTTnIndexARM64(vaddr
, 3)
729 tte
= long(unsigned(pmap
.tte
[tt1_index
]))
730 assert(type(tte
) == long)
733 if verbose_level
>= vSCRIPT
:
734 print "L1 entry: {:#x}".format(tte
)
735 if verbose_level
>= vDETAIL
:
736 PmapDecodeTTEARM64(tte
, 1)
739 # Check for L1 block entry
741 # Handle L1 block entry
742 paddr
= tte
& PmapBlockBaseMaskARM64(1)
743 paddr
= paddr |
(vaddr
& PmapBlockOffsetMaskARM64(1))
744 print "phys: {:#x}".format(paddr
)
746 # Handle L1 table entry
747 l2_phys
= (tte
& page_base_mask
) + (ARM64_TTE_SIZE
* tt2_index
)
748 assert(type(l2_phys
) == long)
750 l2_virt
= kern
.PhysToKernelVirt(l2_phys
)
751 assert(type(l2_virt
) == long)
753 if verbose_level
>= vDETAIL
:
754 print "L2 physical address: {:#x}. L2 virtual address: {:#x}".format(l2_phys
, l2_virt
)
757 ttep
= kern
.GetValueFromAddress(l2_virt
, "tt_entry_t*")
758 tte
= long(unsigned(dereference(ttep
)))
759 assert(type(tte
) == long)
761 if verbose_level
>= vSCRIPT
:
762 print "L2 entry: {:#0x}".format(tte
)
763 if verbose_level
>= vDETAIL
:
764 PmapDecodeTTEARM64(tte
, 2)
767 # Check for L2 block entry
769 # Handle L2 block entry
770 paddr
= tte
& PmapBlockBaseMaskARM64(2)
771 paddr
= paddr |
(vaddr
& PmapBlockOffsetMaskARM64(2))
773 # Handle L2 table entry
774 l3_phys
= (tte
& page_base_mask
) + (ARM64_TTE_SIZE
* tt3_index
)
775 assert(type(l3_phys
) == long)
777 l3_virt
= kern
.PhysToKernelVirt(l3_phys
)
778 assert(type(l3_virt
) == long)
780 if verbose_level
>= vDETAIL
:
781 print "L3 physical address: {:#x}. L3 virtual address: {:#x}".format(l3_phys
, l3_virt
)
784 ttep
= kern
.GetValueFromAddress(l3_virt
, "tt_entry_t*")
785 tte
= long(unsigned(dereference(ttep
)))
786 assert(type(tte
) == long)
788 if verbose_level
>= vSCRIPT
:
789 print "L3 entry: {:#0x}".format(tte
)
790 if verbose_level
>= vDETAIL
:
791 PmapDecodeTTEARM64(tte
, 3)
794 paddr
= tte
& page_base_mask
795 paddr
= paddr |
(vaddr
& page_offset_mask
)
796 elif verbose_level
>= vHUMAN
:
797 print "L3 entry invalid: {:#x}\n".format(tte
)
798 elif verbose_level
>= vHUMAN
: # tte & 0x1 == 0x1
799 print "L2 entry invalid: {:#x}\n".format(tte
)
800 elif verbose_level
>= vHUMAN
:
801 print "L1 entry invalid: {:#x}\n".format(tte
)
803 if verbose_level
>= vHUMAN
:
805 print "Translation of {:#x} is {:#x}.".format(vaddr
, paddr
)
807 print "(no translation)"
811 def PmapWalk(pmap
, vaddr
, verbose_level
= vHUMAN
):
812 if kern
.arch
== 'x86_64':
813 return PmapWalkX86_64(pmap
, vaddr
, verbose_level
)
814 elif kern
.arch
== 'arm':
815 return PmapWalkARM(pmap
, vaddr
, verbose_level
)
816 elif kern
.arch
== 'arm64':
817 return PmapWalkARM64(pmap
, vaddr
, verbose_level
)
819 raise NotImplementedError("PmapWalk does not support {0}".format(kern
.arch
))
821 @lldb_command('pmap_walk')
822 def PmapWalkHelper(cmd_args
=None):
823 """ Perform a page-table walk in <pmap> for <virtual_address>.
824 Syntax: (lldb) pmap_walk <pmap> <virtual_address> [-v] [-e]
825 Multiple -v's can be specified for increased verbosity
827 if cmd_args
== None or len(cmd_args
) < 2:
828 raise ArgumentError("Too few arguments to pmap_walk.")
830 pmap
= kern
.GetValueAsType(cmd_args
[0], 'pmap_t')
831 addr
= unsigned(kern
.GetValueFromAddress(cmd_args
[1], 'void *'))
832 PmapWalk(pmap
, addr
, config
['verbosity'])