7 def ReadPhysInt(phys_addr
, bitsize 
= 64, cpuval 
= None): 
   8     """ Read a physical memory data based on address. 
  10             phys_addr : int - Physical address to read 
  11             bitsize   : int - defines how many bytes to read. defaults to 64 bit 
  12             cpuval    : None (optional) 
  14             int - int value read from memory. in case of failure 0xBAD10AD is returned. 
  16     if "kdp" == GetConnectionProtocol(): 
  17         return KDPReadPhysMEM(phys_addr
, bitsize
) 
  19     #NO KDP. Attempt to use physical memory 
  20     paddr_in_kva 
= kern
.PhysToKernelVirt(long(phys_addr
)) 
  23             return kern
.GetValueFromAddress(paddr_in_kva
, 'uint64_t *').GetSBValue().Dereference().GetValueAsUnsigned() 
  25             return kern
.GetValueFromAddress(paddr_in_kva
, 'uint32_t *').GetSBValue().Dereference().GetValueAsUnsigned() 
  27             return kern
.GetValueFromAddress(paddr_in_kva
, 'uint16_t *').GetSBValue().Dereference().GetValueAsUnsigned() 
  29             return kern
.GetValueFromAddress(paddr_in_kva
, 'uint8_t *').GetSBValue().Dereference().GetValueAsUnsigned() 
  32 @lldb_command('readphys') 
  33 def ReadPhys(cmd_args 
= None): 
  34     """ Reads the specified untranslated address 
  35         The argument is interpreted as a physical address, and the 64-bit word 
  36         addressed is displayed. 
  37         usage: readphys <nbits> <address> 
  39         address: 1234 or 0x1234 
  41     if cmd_args 
== None or len(cmd_args
) < 2: 
  42         print "Insufficient arguments.", ReadPhys
.__doc
__ 
  45         nbits 
= ArgumentStringToInt(cmd_args
[0]) 
  46         phys_addr 
= ArgumentStringToInt(cmd_args
[1]) 
  47         print "{0: <#x}".format(ReadPhysInt(phys_addr
, nbits
)) 
  50 lldb_alias('readphys8', 'readphys 8 ') 
  51 lldb_alias('readphys16', 'readphys 16 ') 
  52 lldb_alias('readphys32', 'readphys 32 ') 
  53 lldb_alias('readphys64', 'readphys 64 ') 
  55 def KDPReadPhysMEM(address
, bits
): 
  56     """ Setup the state for READPHYSMEM64 commands for reading data via kdp 
  58             address : int - address where to read the data from 
  59             bits : int - number of bits in the intval (8/16/32/64) 
  61             int: read value from memory. 
  62             0xBAD10AD: if failed to read data. 
  65     if "kdp" != GetConnectionProtocol(): 
  66         print "Target is not connected over kdp. Nothing to do here." 
  69     if "hwprobe" == KDPMode(): 
  70         # Send the proper KDP command and payload to the bare metal debug tool via a KDP server 
  71         addr_for_kdp 
= struct
.unpack("<Q", struct
.pack(">Q", address
))[0] 
  72         byte_count 
= struct
.unpack("<I", struct
.pack(">I", bits
/8))[0] 
  73         packet 
= "{0:016x}{1:08x}{2:04x}".format(addr_for_kdp
, byte_count
, 0x0) 
  75         ret_obj 
= lldb
.SBCommandReturnObject() 
  76         ci 
= lldb
.debugger
.GetCommandInterpreter() 
  77         ci
.HandleCommand('process plugin packet send -c 25 -p {0}'.format(packet
), ret_obj
) 
  79         if ret_obj
.Succeeded(): 
  80             value 
= ret_obj
.GetOutput() 
  95             retval 
= struct
.unpack(unpack_fmt
, struct
.pack(pack_fmt
, int(value
[-((bits
/4)+1):], 16)))[0] 
  98         input_address 
= unsigned(addressof(kern
.globals.manual_pkt
.input)) 
  99         len_address 
= unsigned(addressof(kern
.globals.manual_pkt
.len)) 
 100         data_address 
= unsigned(addressof(kern
.globals.manual_pkt
.data
)) 
 102         if not WriteInt32ToMemoryAddress(0, input_address
): 
 105         kdp_pkt_size 
= GetType('kdp_readphysmem64_req_t').GetByteSize() 
 106         if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
): 
 109         data_addr 
= int(addressof(kern
.globals.manual_pkt
)) 
 110         pkt 
= kern
.GetValueFromAddress(data_addr
, 'kdp_readphysmem64_req_t *') 
 112         header_value 
=GetKDPPacketHeaderInt(request
=GetEnumValue('kdp_req_t::KDP_READPHYSMEM64'), length
=kdp_pkt_size
) 
 114         if ( WriteInt64ToMemoryAddress((header_value
), int(addressof(pkt
.hdr
))) and 
 115              WriteInt64ToMemoryAddress(address
, int(addressof(pkt
.address
))) and 
 116              WriteInt32ToMemoryAddress((bits
/8), int(addressof(pkt
.nbytes
))) and 
 117              WriteInt16ToMemoryAddress(xnudefines
.lcpu_self
, int(addressof(pkt
.lcpu
))) 
 120             if WriteInt32ToMemoryAddress(1, input_address
): 
 121                 # now read data from the kdp packet 
 122                 data_address 
= unsigned(addressof(kern
.GetValueFromAddress(int(addressof(kern
.globals.manual_pkt
.data
)), 'kdp_readphysmem64_reply_t *').data
)) 
 124                     retval 
=  kern
.GetValueFromAddress(data_address
, 'uint64_t *').GetSBValue().Dereference().GetValueAsUnsigned() 
 126                     retval 
=  kern
.GetValueFromAddress(data_address
, 'uint32_t *').GetSBValue().Dereference().GetValueAsUnsigned() 
 128                     retval 
=  kern
.GetValueFromAddress(data_address
, 'uint16_t *').GetSBValue().Dereference().GetValueAsUnsigned() 
 130                     retval 
=  kern
.GetValueFromAddress(data_address
, 'uint8_t *').GetSBValue().Dereference().GetValueAsUnsigned() 
 135 def KDPWritePhysMEM(address
, intval
, bits
): 
 136     """ Setup the state for WRITEPHYSMEM64 commands for saving data in kdp 
 138             address : int - address where to save the data 
 139             intval : int - integer value to be stored in memory 
 140             bits : int - number of bits in the intval (8/16/32/64) 
 142             boolean: True if the write succeeded. 
 144     if "kdp" != GetConnectionProtocol(): 
 145         print "Target is not connected over kdp. Nothing to do here." 
 148     if "hwprobe" == KDPMode(): 
 149         # Send the proper KDP command and payload to the bare metal debug tool via a KDP server 
 150         addr_for_kdp 
= struct
.unpack("<Q", struct
.pack(">Q", address
))[0] 
 151         byte_count 
= struct
.unpack("<I", struct
.pack(">I", bits
/8))[0] 
 166         data_val 
= struct
.unpack(unpack_fmt
, struct
.pack(pack_fmt
, intval
))[0] 
 168         packet 
= "{0:016x}{1:08x}{2:04x}{3:016x}".format(addr_for_kdp
, byte_count
, 0x0, data_val
) 
 170         ret_obj 
= lldb
.SBCommandReturnObject() 
 171         ci 
= lldb
.debugger
.GetCommandInterpreter() 
 172         ci
.HandleCommand('process plugin packet send -c 26 -p {0}'.format(packet
), ret_obj
) 
 174         if ret_obj
.Succeeded(): 
 180         input_address 
= unsigned(addressof(kern
.globals.manual_pkt
.input)) 
 181         len_address 
= unsigned(addressof(kern
.globals.manual_pkt
.len)) 
 182         data_address 
= unsigned(addressof(kern
.globals.manual_pkt
.data
)) 
 183         if not WriteInt32ToMemoryAddress(0, input_address
): 
 186         kdp_pkt_size 
= GetType('kdp_writephysmem64_req_t').GetByteSize() + (bits 
/ 8) 
 187         if not WriteInt32ToMemoryAddress(kdp_pkt_size
, len_address
): 
 190         data_addr 
= int(addressof(kern
.globals.manual_pkt
)) 
 191         pkt 
= kern
.GetValueFromAddress(data_addr
, 'kdp_writephysmem64_req_t *') 
 193         header_value 
=GetKDPPacketHeaderInt(request
=GetEnumValue('kdp_req_t::KDP_WRITEPHYSMEM64'), length
=kdp_pkt_size
) 
 195         if ( WriteInt64ToMemoryAddress((header_value
), int(addressof(pkt
.hdr
))) and 
 196              WriteInt64ToMemoryAddress(address
, int(addressof(pkt
.address
))) and 
 197              WriteInt32ToMemoryAddress((bits
/8), int(addressof(pkt
.nbytes
))) and 
 198              WriteInt16ToMemoryAddress(xnudefines
.lcpu_self
, int(addressof(pkt
.lcpu
))) 
 202                 if not WriteInt8ToMemoryAddress(intval
, int(addressof(pkt
.data
))): 
 205                 if not WriteInt16ToMemoryAddress(intval
, int(addressof(pkt
.data
))): 
 208                 if not WriteInt32ToMemoryAddress(intval
, int(addressof(pkt
.data
))): 
 211                 if not WriteInt64ToMemoryAddress(intval
, int(addressof(pkt
.data
))): 
 213             if WriteInt32ToMemoryAddress(1, input_address
): 
 218 def WritePhysInt(phys_addr
, int_val
, bitsize 
= 64): 
 219     """ Write and integer value in a physical memory data based on address. 
 221             phys_addr : int - Physical address to read 
 222             int_val   : int - int value to write in memory 
 223             bitsize   : int - defines how many bytes to read. defaults to 64 bit 
 225             bool - True if write was successful. 
 227     if "kdp" == GetConnectionProtocol(): 
 228         if not KDPWritePhysMEM(phys_addr
, int_val
, bitsize
): 
 229             print "Failed to write via KDP." 
 232     #We are not connected via KDP. So do manual math and savings. 
 233     print "Failed: Write to physical memory is not supported for %s connection." % GetConnectionProtocol() 
 236 @lldb_command('writephys') 
 237 def WritePhys(cmd_args
=None): 
 238     """ writes to the specified untranslated address 
 239         The argument is interpreted as a physical address, and the 64-bit word 
 240         addressed is displayed. 
 241         usage: writephys <nbits> <address> <value> 
 243         address: 1234 or 0x1234 
 244         value: int value to be written 
 245         ex. (lldb)writephys 16 0x12345abcd 0x25 
 247     if cmd_args 
== None or len(cmd_args
) < 3: 
 248         print "Invalid arguments.", WritePhys
.__doc
__ 
 250         nbits 
= ArgumentStringToInt(cmd_args
[0]) 
 251         phys_addr 
= ArgumentStringToInt(cmd_args
[1]) 
 252         int_value 
= ArgumentStringToInt(cmd_args
[2]) 
 253         print WritePhysInt(phys_addr
, int_value
, nbits
) 
 256 lldb_alias('writephys8', 'writephys 8 ') 
 257 lldb_alias('writephys16', 'writephys 16 ') 
 258 lldb_alias('writephys32', 'writephys 32 ') 
 259 lldb_alias('writephys64', 'writephys 64 ') 
 262 def _PT_Step(paddr
, index
, verbose_level 
= vSCRIPT
): 
 264      Step to lower-level page table and print attributes 
 265        paddr: current page table entry physical address 
 266        index: current page table entry index (0..511) 
 267        verbose_level:    vHUMAN: print nothing 
 268                          vSCRIPT: print basic information 
 269                          vDETAIL: print basic information and hex table dump 
 270      returns: (pt_paddr, pt_valid, pt_large) 
 271        pt_paddr: next level page table entry physical address 
 273        pt_valid: 1 if $kgm_pt_paddr is valid, 0 if the walk 
 275        pt_large: 1 if kgm_pt_paddr is a page frame address 
 276                       of a large page and not another page table entry 
 278     entry_addr 
= paddr 
+ (8 * index
) 
 279     entry 
= ReadPhysInt(entry_addr
, 64, xnudefines
.lcpu_self 
) 
 281     if verbose_level 
>= vDETAIL
: 
 282         for pte_loop 
in range(0, 512): 
 283             paddr_tmp 
= paddr 
+ (8 * pte_loop
) 
 284             out_string 
+= "{0: <#020x}:\t {1: <#020x}\n".format(paddr_tmp
, ReadPhysInt(paddr_tmp
, 64, xnudefines
.lcpu_self
)) 
 285     paddr_mask 
= ~
((0xfff<<52) | 
0xfff) 
 286     paddr_large_mask 
=  ~
((0xfff<<52) | 
0x1fffff) 
 290     if verbose_level 
< vSCRIPT
: 
 294             pt_paddr 
= entry 
& paddr_mask
 
 295             if entry 
& (0x1 <<7): 
 297                 pt_paddr 
= entry 
& paddr_large_mask
 
 299         out_string
+= "{0: <#020x}:\n\t{1:#020x}\n\t".format(entry_addr
, entry
) 
 301             out_string 
+= " valid" 
 302             pt_paddr 
= entry 
& paddr_mask
 
 305             out_string 
+= " invalid" 
 308             if entry 
& (0x1 << 62): 
 309                 out_string 
+= " compressed" 
 310             #Stop decoding other bits 
 312         if entry 
& (0x1 << 1): 
 313             out_string 
+= " writable" 
 315             out_string 
+= " read-only" 
 317         if entry 
& (0x1 << 2): 
 318             out_string 
+= " user" 
 320             out_string 
+= " supervisor" 
 322         if entry 
& (0x1 << 3): 
 325         if entry 
& (0x1 << 4): 
 328         if entry 
& (0x1 << 5): 
 329             out_string 
+= " accessed" 
 331         if entry 
& (0x1 << 6): 
 332             out_string 
+= " dirty" 
 334         if entry 
& (0x1 << 7): 
 335             out_string 
+= " large" 
 340         if entry 
& (0x1 << 8): 
 341             out_string 
+= " global" 
 343         if entry 
& (0x3 << 9): 
 344             out_string 
+= " avail:{0:x}".format((entry 
>> 9) & 0x3) 
 346         if entry 
& (0x1 << 63): 
 347             out_string 
+= " noexec" 
 349     return (pt_paddr
, pt_valid
, pt_large
) 
 351 def _PT_StepEPT(paddr
, index
, verbose_level 
= vSCRIPT
): 
 353      Step to lower-level page table and print attributes for EPT pmap 
 354        paddr: current page table entry physical address 
 355        index: current page table entry index (0..511) 
 356        verbose_level:    vHUMAN: print nothing 
 357                          vSCRIPT: print basic information 
 358                          vDETAIL: print basic information and hex table dump 
 359      returns: (pt_paddr, pt_valid, pt_large) 
 360        pt_paddr: next level page table entry physical address 
 362        pt_valid: 1 if $kgm_pt_paddr is valid, 0 if the walk 
 364        pt_large: 1 if kgm_pt_paddr is a page frame address 
 365                       of a large page and not another page table entry 
 367     entry_addr 
= paddr 
+ (8 * index
) 
 368     entry 
= ReadPhysInt(entry_addr
, 64, xnudefines
.lcpu_self 
) 
 370     if verbose_level 
>= vDETAIL
: 
 371         for pte_loop 
in range(0, 512): 
 372             paddr_tmp 
= paddr 
+ (8 * pte_loop
) 
 373             out_string 
+= "{0: <#020x}:\t {1: <#020x}\n".format(paddr_tmp
, ReadPhysInt(paddr_tmp
, 64, xnudefines
.lcpu_self
)) 
 374     paddr_mask 
= ~
((0xfff<<52) | 
0xfff) 
 375     paddr_large_mask 
=  ~
((0xfff<<52) | 
0x1fffff) 
 379     if verbose_level 
< vSCRIPT
: 
 383             pt_paddr 
= entry 
& paddr_mask
 
 384             if entry 
& (0x1 <<7): 
 386                 pt_paddr 
= entry 
& paddr_large_mask
 
 388         out_string
+= "{0: <#020x}:\n\t{1:#020x}\n\t".format(entry_addr
, entry
) 
 390             out_string 
+= "valid" 
 391             pt_paddr 
= entry 
& paddr_mask
 
 394             out_string 
+= "invalid" 
 397             if entry 
& (0x1 << 62): 
 398                 out_string 
+= " compressed" 
 399             #Stop decoding other bits 
 402             out_string 
+= " readable" 
 404             out_string 
+= " no read" 
 405         if entry 
& (0x1 << 1): 
 406             out_string 
+= " writable" 
 408             out_string 
+= " no write" 
 410         if entry 
& (0x1 << 2): 
 411             out_string 
+= " executable" 
 413             out_string 
+= " no exec" 
 417             out_string 
+= " cache-WB" 
 419             out_string 
+= " cache-WP" 
 421             out_string 
+= " cache-WT" 
 423             out_string 
+= " cache-WC" 
 425             out_string 
+= " cache-NC" 
 427         if (entry 
& 0x40) == 0x40: 
 428             out_string 
+= " Ignore-PTA" 
 430         if (entry 
& 0x100) == 0x100: 
 431             out_string 
+= " accessed" 
 433         if (entry 
& 0x200) == 0x200: 
 434             out_string 
+= " dirty" 
 436         if entry 
& (0x1 << 7): 
 437             out_string 
+= " large" 
 442     return (pt_paddr
, pt_valid
, pt_large
) 
 444 def _PmapL4Walk(pmap_addr_val
,vaddr
, ept_pmap
, verbose_level 
= vSCRIPT
): 
 445     """ Walk the l4 pmap entry. 
 446         params: pmap_addr_val - core.value representing kernel data of type pmap_addr_t 
 447         vaddr : int - virtual address to walk 
 449     pt_paddr 
= unsigned(pmap_addr_val
) 
 450     pt_valid 
= (unsigned(pmap_addr_val
) != 0) 
 454         # Lookup bits 47:39 of linear address in PML4T 
 455         pt_index 
= (vaddr 
>> 39) & 0x1ff 
 456         pframe_offset 
= vaddr 
& 0x7fffffffff 
 457         if verbose_level 
> vHUMAN 
: 
 458             print "pml4 (index {0:d}):".format(pt_index
) 
 460             (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
) 
 462             (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
) 
 464         # Lookup bits 38:30 of the linear address in PDPT 
 465         pt_index 
= (vaddr 
>> 30) & 0x1ff 
 466         pframe_offset 
= vaddr 
& 0x3fffffff 
 467         if verbose_level 
> vHUMAN
: 
 468             print "pdpt (index {0:d}):".format(pt_index
) 
 470             (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
) 
 472             (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
) 
 473     if pt_valid 
and not pt_large
: 
 474         #Lookup bits 29:21 of the linear address in PDPT 
 475         pt_index 
= (vaddr 
>> 21) & 0x1ff 
 476         pframe_offset 
= vaddr 
& 0x1fffff 
 477         if verbose_level 
> vHUMAN
: 
 478             print "pdt (index {0:d}):".format(pt_index
) 
 480             (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
) 
 482             (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
) 
 483     if pt_valid 
and not pt_large
: 
 484         #Lookup bits 20:21 of linear address in PT 
 485         pt_index 
= (vaddr 
>> 12) & 0x1ff 
 486         pframe_offset 
= vaddr 
& 0xfff 
 487         if verbose_level 
> vHUMAN
: 
 488             print "pt (index {0:d}):".format(pt_index
) 
 490             (pt_paddr
, pt_valid
, pt_large
) = _PT_Step(pt_paddr
, pt_index
, verbose_level
) 
 492             (pt_paddr
, pt_valid
, pt_large
) = _PT_StepEPT(pt_paddr
, pt_index
, verbose_level
) 
 494     paddr_isvalid 
= False 
 496         paddr 
= pt_paddr 
+ pframe_offset
 
 499     if verbose_level 
> vHUMAN
: 
 501             pvalue 
= ReadPhysInt(paddr
, 32, xnudefines
.lcpu_self
) 
 502             print "phys {0: <#020x}: {1: <#020x}".format(paddr
, pvalue
) 
 504             print "no translation" 
 508 def PmapDecodeTTEARM(tte
, level
, verbose_level
): 
 509     """ Display the bits of an ARM translation table or page table entry 
 510         in human-readable form. 
 511         tte: integer value of the TTE/PTE 
 512         level: translation table level.  Valid values are 1 or 2. 
 513         verbose_level: verbosity. vHUMAN, vSCRIPT, vDETAIL 
 516     if level 
== 1 and (tte 
& 0x3) == 0x2: 
 517         if verbose_level 
< vSCRIPT
: 
 520         #bit [1:0] evaluated in PmapWalkARM 
 522         b_bit 
= (tte 
& 0x4) >> 2 
 524         c_bit 
= (tte 
& 0x8) >> 3 
 527             out_string 
+= "no-execute" 
 529             out_string 
+= "execute" 
 530         #Domain bit [8:5] if not supersection 
 531         if (tte 
& 0x40000) == 0x0: 
 532             out_string 
+= " domain ({:d})".format(((tte 
& 0x1e0) >> 5) ) 
 534         out_string 
+= " imp({:d})".format( ((tte 
& 0x200) >> 9) ) 
 535         # AP bit 15 and [11:10] merged to a single 3 bit value 
 536         access 
= ( (tte 
& 0xc00) >> 10 ) | 
((tte 
& 0x8000) >> 13) 
 537         out_string 
+= xnudefines
.arm_level2_access_strings
[access
] 
 540         tex_bits 
= ((tte 
& 0x7000) >> 12) 
 541         #Print TEX, C , B all together 
 542         out_string 
+= " TEX:C:B({:d}{:d}{:d}:{:d}:{:d})".format( 
 543                                                                     1 if (tex_bits 
& 0x4) else 0, 
 544                                                                     1 if (tex_bits 
& 0x2) else 0, 
 545                                                                     1 if (tex_bits 
& 0x1) else 0, 
 551             out_string 
+= " shareable" 
 553             out_string 
+= " not-shareable" 
 556             out_string 
+= " not-global" 
 558             out_string 
+= " global" 
 559         # Supersection bit 18 
 561             out_string 
+= " supersection" 
 563             out_string 
+= " section" 
 566             out_string 
+= " no-secure" 
 568             out_string 
+= " secure" 
 570     elif level 
== 1 and (tte 
& 0x3) == 0x1: 
 572         if verbose_level 
>= vSCRIPT
: 
 573             # bit [1:0] evaluated in PmapWalkARM 
 576                 out_string 
+= ' no-secure' 
 578                 out_string 
+= ' secure' 
 580             out_string 
+= " domain({:d})".format(((tte 
& 0x1e0) >> 5)) 
 582             out_string 
+= " imp({:d})".format( ((tte 
& 0x200) >> 9)) 
 587         if verbose_level 
>= vSCRIPT
: 
 588             if (pte 
& 0x3) == 0x0: 
 589                 out_string 
+= " invalid" 
 591                 if (pte 
& 0x3) == 0x1: 
 592                     out_string 
+= " large" 
 594                     if pte 
& 0x8000 == 0x8000: 
 595                         out_string
+= " no-execute" 
 597                         out_string 
+= " execute" 
 599                     out_string 
+= " small" 
 601                     if (pte 
& 0x1) == 0x01: 
 602                         out_string 
+= " no-execute" 
 604                         out_string 
+= " execute" 
 606                 b_bit 
= (pte 
& 0x4) >> 2 
 607                 c_bit 
= (pte 
& 0x8) >> 3 
 608                 # AP bit 9 and [5:4], merged to a single 3-bit value 
 609                 access 
= (pte 
& 0x30) >> 4 | 
(pte 
& 0x200) >> 7 
 610                 out_string 
+= xnudefines
.arm_level2_access_strings
[access
] 
 612                 #TEX bit [14:12] for large, [8:6] for small 
 613                 tex_bits 
= ((pte 
& 0x1c0) >> 6) 
 614                 if (pte 
& 0x3) == 0x1: 
 615                     tex_bits 
= ((pte 
& 0x7000) >> 12) 
 617                 # Print TEX, C , B alltogether 
 618                 out_string 
+= " TEX:C:B({:d}{:d}{:d}:{:d}:{:d})".format( 
 619                                                                         1 if (tex_bits 
& 0x4) else 0, 
 620                                                                         1 if (tex_bits 
& 0x2) else 0, 
 621                                                                         1 if (tex_bits 
& 0x1) else 0, 
 627                     out_string 
+= " shareable" 
 629                     out_string 
+= " not-shareable" 
 633                     out_string 
+= " not-global" 
 635                     out_string 
+= " global" 
 640 def _PmapWalkARMLevel1Section(tte
, vaddr
, verbose_level 
= vSCRIPT
): 
 642     #Supersection or just section? 
 643     if (tte 
& 0x40000) == 0x40000: 
 644         paddr 
= ( (tte 
& 0xFF000000) | 
(vaddr 
& 0x00FFFFFF) ) 
 646         paddr 
= ( (tte 
& 0xFFF00000) | 
(vaddr 
& 0x000FFFFF) ) 
 648     if verbose_level 
>= vSCRIPT
: 
 649         print "{0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(tte
), tte
), 
 651     PmapDecodeTTEARM(tte
, 1, verbose_level
) 
 657 def _PmapWalkARMLevel2(tte
, vaddr
, verbose_level 
= vSCRIPT
): 
 658     """ Pmap walk the level 2 tte. 
 662         returns: str - description of the tte + additional informaiton based on verbose_level 
 664     pte_base 
= kern
.PhysToKernelVirt(tte 
& 0xFFFFFC00) 
 665     pte_index 
= (vaddr 
>> 12) & 0xFF 
 666     pte_base_val 
= kern
.GetValueFromAddress(pte_base
, 'pt_entry_t *') 
 667     pte 
= pte_base_val
[pte_index
] 
 671         paddr 
= (unsigned(pte
) & 0xFFFFF000) | 
(vaddr 
& 0xFFF) 
 673     if verbose_level 
>= vSCRIPT
: 
 674         print "{0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(tte
), tte
), 
 676     PmapDecodeTTEARM(tte
, 1, verbose_level
) 
 677     if verbose_level 
>= vSCRIPT
: 
 678         print "second-level table (index {:d}):".format(pte_index
) 
 679     if verbose_level 
>= vDETAIL
: 
 681             tmp 
= pte_base_val
[i
] 
 682             print "{0: <#020x}:\t{1: <#020x}".format(addressof(tmp
), unsigned(tmp
)) 
 684     if verbose_level 
>= vSCRIPT
: 
 685         print " {0: <#020x}\n\t{1: <#020x}\n\t".format(addressof(pte
), unsigned(pte
)), 
 687     PmapDecodeTTEARM(pte
, 2, verbose_level
) 
 690     #end of level 2 walking of arm 
 693 def PmapWalkARM(pmap
, vaddr
, verbose_level 
= vHUMAN
): 
 694     """ Pmap walking for ARM kernel. 
 696           pmapval: core.value - representing pmap_t in kernel 
 697           vaddr:  int     - integer representing virtual address to walk 
 700     # shift by TTESHIFT (20) to get tte index 
 701     # Assume all L1 indexing starts at VA 0...for our purposes it does, 
 702     # as that's where all user pmaps start, and the kernel pmap contains 
 703     # 4 L1 pages (the lower 2 of which are unused after bootstrap) 
 704     tte_index 
= vaddr 
>> 20 
 705     tte 
= pmap
.tte
[tte_index
] 
 706     if verbose_level 
>= vSCRIPT
: 
 707         print "First-level table (index {:d}):".format(tte_index
) 
 708     if verbose_level 
>= vDETAIL
: 
 709         for i 
in range(0, pmap
.tte_index_max
): 
 710             ptr 
= unsigned(addressof(pmap
.tte
[i
])) 
 711             val 
= unsigned(pmap
.tte
[i
]) 
 712             print "{0: <#020x}:\t {1: <#020x}".format(ptr
, val
) 
 713     if (tte 
& 0x3) == 0x1: 
 714         paddr 
= _PmapWalkARMLevel2(tte
, vaddr
, verbose_level
) 
 715     elif (tte 
& 0x3) == 0x2 : 
 716         paddr 
= _PmapWalkARMLevel1Section(tte
, vaddr
, verbose_level
) 
 719         if verbose_level 
>= vSCRIPT
: 
 720             print "Invalid First-Level Translation Table Entry: {0: #020x}".format(tte
) 
 722     if verbose_level 
>= vHUMAN
: 
 724             print "Translation of {:#x} is {:#x}.".format(vaddr
, paddr
) 
 726             print "(no translation)" 
 730 def PmapWalkX86_64(pmapval
, vaddr
, verbose_level 
= vSCRIPT
): 
 732         params: pmapval - core.value representing pmap_t in kernel 
 733         vaddr:  int     - int representing virtual address to walk 
 735     if pmapval
.pm_cr3 
!= 0: 
 736         if verbose_level 
> vHUMAN
: 
 737             print "Using normal Intel PMAP from pm_cr3\n" 
 738         return _PmapL4Walk(pmapval
.pm_cr3
, vaddr
, 0, config
['verbosity']) 
 740         if verbose_level 
> vHUMAN
: 
 741             print "Using EPT pmap from pm_eptp\n" 
 742         return _PmapL4Walk(pmapval
.pm_eptp
, vaddr
, 1, config
['verbosity']) 
 744 def assert_64bit(val
): 
 749 ARM64_VMADDR_BITS 
= 48 
 751 def PmapBlockOffsetMaskARM64(level
): 
 752     assert level 
>= 1 and level 
<= 3 
 753     page_size 
= kern
.globals.arm_hardware_page_size
 
 754     ttentries 
= (page_size 
/ ARM64_TTE_SIZE
) 
 755     return page_size 
* (ttentries 
** (3 - level
)) - 1 
 757 def PmapBlockBaseMaskARM64(level
): 
 758     assert level 
>= 1 and level 
<= 3 
 759     page_size 
= kern
.globals.arm_hardware_page_size
 
 760     return ((1 << ARM64_VMADDR_BITS
) - 1) & ~
PmapBlockOffsetMaskARM64(level
) 
 762 def PmapIndexMaskARM64(level
): 
 763     assert level 
>= 1 and level 
<= 3 
 764     page_size 
= kern
.globals.arm_hardware_page_size
 
 765     ttentries 
= (page_size 
/ ARM64_TTE_SIZE
) 
 766     return page_size 
* (ttentries 
** (3 - level
) * (ttentries 
- 1)) 
 768 def PmapIndexDivideARM64(level
): 
 769     assert level 
>= 1 and level 
<= 3 
 770     page_size 
= kern
.globals.arm_hardware_page_size
 
 771     ttentries 
= (page_size 
/ ARM64_TTE_SIZE
) 
 772     return page_size 
* (ttentries 
** (3 - level
)) 
 774 def PmapTTnIndexARM64(vaddr
, level
): 
 775     assert(type(vaddr
) in (long, int)) 
 778     return (vaddr 
& PmapIndexMaskARM64(level
)) // PmapIndexDivideARM64(level
) 
 780 def PmapDecodeTTEARM64(tte
, level
): 
 781     """ Display the bits of an ARM64 translation table or page table entry 
 782         in human-readable form. 
 783         tte: integer value of the TTE/PTE 
 784         level: translation table level.  Valid values are 1, 2, or 3. 
 786     assert(type(tte
) == long) 
 787     assert(type(level
) == int) 
 791         if (tte 
& 0x2 == 0x2) and (level 
!= 0x3): 
 792             print "Type       = Table pointer." 
 793             print "Table addr = {:#x}.".format(tte 
& 0xfffffffff000) 
 794             print "PXN        = {:#x}.".format((tte 
>> 59) & 0x1) 
 795             print "XN         = {:#x}.".format((tte 
>> 60) & 0x1) 
 796             print "AP         = {:#x}.".format((tte 
>> 61) & 0x3) 
 797             print "NS         = {:#x}".format(tte 
>> 63) 
 799             print "Type       = Block." 
 800             print "AttrIdx    = {:#x}.".format((tte 
>> 2) & 0x7) 
 801             print "NS         = {:#x}.".format((tte 
>> 5) & 0x1) 
 802             print "AP         = {:#x}.".format((tte 
>> 6) & 0x3) 
 803             print "SH         = {:#x}.".format((tte 
>> 8) & 0x3) 
 804             print "AF         = {:#x}.".format((tte 
>> 10) & 0x1) 
 805             print "nG         = {:#x}.".format((tte 
>> 11) & 0x1) 
 806             print "HINT       = {:#x}.".format((tte 
>> 52) & 0x1) 
 807             print "PXN        = {:#x}.".format((tte 
>> 53) & 0x1) 
 808             print "XN         = {:#x}.".format((tte 
>> 54) & 0x1) 
 809             print "SW Use     = {:#x}.".format((tte 
>> 55) & 0xf) 
 815 def PmapWalkARM64(pmap
, vaddr
, verbose_level 
= vHUMAN
): 
 816     assert(type(pmap
) == core
.cvalue
.value
) 
 817     assert(type(vaddr
) in (long, int)) 
 818     page_size 
= kern
.globals.arm_hardware_page_size
 
 819     page_offset_mask 
= (page_size 
- 1) 
 820     page_base_mask 
= ((1 << ARM64_VMADDR_BITS
) - 1) & (~page_offset_mask
) 
 826     tt1_index 
= PmapTTnIndexARM64(vaddr
, 1) 
 827     tt2_index 
= PmapTTnIndexARM64(vaddr
, 2) 
 828     tt3_index 
= PmapTTnIndexARM64(vaddr
, 3) 
 830     # The pmap starts at a page tabel level that is defined by register 
 831     # values; the kernel exports the root level for LLDB 
 832     level 
= kern
.globals.arm64_root_pgtable_level
 
 836         root_tt_index 
= tt0_index
 
 838         root_tt_index 
= tt1_index
 
 840         root_tt_index 
= tt2_index
 
 842         root_tt_index 
= tt3_index
 
 844     # If the root of the page table is not a full page, we need to 
 846     root_tt_index 
= root_tt_index 
% unsigned(kern
.globals.arm64_root_pgtable_num_ttes
) 
 848     tte 
= long(unsigned(pmap
.tte
[root_tt_index
])) 
 849     assert(type(tte
) == long) 
 855             # This is unsupported at the moment, as no kernel configurations use L0 
 860             if verbose_level 
>= vSCRIPT
: 
 861                 print "L1 entry: {:#x}".format(tte
) 
 862             if verbose_level 
>= vDETAIL
: 
 863                 PmapDecodeTTEARM64(tte
, 1) 
 866                 # Check for L1 block entry 
 868                     # Handle L1 block entry 
 869                     paddr 
= tte 
& PmapBlockBaseMaskARM64(1) 
 870                     paddr 
= paddr | 
(vaddr 
& PmapBlockOffsetMaskARM64(1)) 
 871                     print "phys: {:#x}".format(paddr
) 
 874                     # Handle L1 table entry 
 875                     l2_phys 
= (tte 
& page_base_mask
) + (ARM64_TTE_SIZE 
* tt2_index
) 
 876                     assert(type(l2_phys
) == long) 
 878                     l2_virt 
= kern
.PhysToKernelVirt(l2_phys
) 
 879                     assert(type(l2_virt
) == long) 
 881                     if verbose_level 
>= vDETAIL
: 
 882                         print "L2 physical address: {:#x}. L2 virtual address: {:#x}".format(l2_phys
, l2_virt
) 
 884                     ttep 
= kern
.GetValueFromAddress(l2_virt
, "tt_entry_t*") 
 885                     tte 
= long(unsigned(dereference(ttep
))) 
 886                     assert(type(tte
) == long) 
 887             elif verbose_level 
>= vHUMAN
: 
 888                 print "L1 entry invalid: {:#x}\n".format(tte
) 
 892             if verbose_level 
>= vSCRIPT
: 
 893                 print "L2 entry: {:#0x}".format(tte
) 
 894             if verbose_level 
>= vDETAIL
: 
 895                 PmapDecodeTTEARM64(tte
, 2) 
 898                 # Check for L2 block entry 
 900                     # Handle L2 block entry 
 901                     paddr 
= tte 
& PmapBlockBaseMaskARM64(2) 
 902                     paddr 
= paddr | 
(vaddr 
& PmapBlockOffsetMaskARM64(2)) 
 905                     # Handle L2 table entry 
 906                     l3_phys 
= (tte 
& page_base_mask
) + (ARM64_TTE_SIZE 
* tt3_index
) 
 907                     assert(type(l3_phys
) == long) 
 909                     l3_virt 
= kern
.PhysToKernelVirt(l3_phys
) 
 910                     assert(type(l3_virt
) == long) 
 912                     if verbose_level 
>= vDETAIL
: 
 913                         print "L3 physical address: {:#x}. L3 virtual address: {:#x}".format(l3_phys
, l3_virt
) 
 915                     ttep 
= kern
.GetValueFromAddress(l3_virt
, "tt_entry_t*") 
 916                     tte 
= long(unsigned(dereference(ttep
))) 
 917                     assert(type(tte
) == long) 
 918             elif verbose_level 
>= vHUMAN
: # tte & 0x1 == 0x1 
 919                 print "L2 entry invalid: {:#x}\n".format(tte
) 
 923             if verbose_level 
>= vSCRIPT
: 
 924                 print "L3 entry: {:#0x}".format(tte
) 
 925             if verbose_level 
>= vDETAIL
: 
 926                 PmapDecodeTTEARM64(tte
, 3) 
 929                 paddr 
= tte 
& page_base_mask
 
 930                 paddr 
= paddr | 
(vaddr 
& page_offset_mask
) 
 931             elif verbose_level 
>= vHUMAN
: 
 932                 print "L3 entry invalid: {:#x}\n".format(tte
) 
 934             # This was the leaf page table page for this request; we're done 
 937         # We've parsed one level, so go to the next level 
 941     if verbose_level 
>= vHUMAN
: 
 943             print "Translation of {:#x} is {:#x}.".format(vaddr
, paddr
) 
 945             print "(no translation)" 
 949 def PmapWalk(pmap
, vaddr
, verbose_level 
= vHUMAN
): 
 950     if kern
.arch 
== 'x86_64': 
 951         return PmapWalkX86_64(pmap
, vaddr
, verbose_level
) 
 952     elif kern
.arch 
== 'arm': 
 953         return PmapWalkARM(pmap
, vaddr
, verbose_level
) 
 954     elif kern
.arch
.startswith('arm64'): 
 955         return PmapWalkARM64(pmap
, vaddr
, verbose_level
) 
 957         raise NotImplementedError("PmapWalk does not support {0}".format(kern
.arch
)) 
 959 @lldb_command('pmap_walk') 
 960 def PmapWalkHelper(cmd_args
=None): 
 961     """ Perform a page-table walk in <pmap> for <virtual_address>. 
 962         Syntax: (lldb) pmap_walk <pmap> <virtual_address> [-v] [-e] 
 963             Multiple -v's can be specified for increased verbosity 
 965     if cmd_args 
== None or len(cmd_args
) < 2: 
 966         raise ArgumentError("Too few arguments to pmap_walk.") 
 968     pmap 
= kern
.GetValueAsType(cmd_args
[0], 'pmap_t') 
 969     addr 
= unsigned(kern
.GetValueFromAddress(cmd_args
[1], 'void *')) 
 970     PmapWalk(pmap
, addr
, config
['verbosity']) 
 973 @lldb_command('decode_tte') 
 974 def DecodeTTE(cmd_args
=None): 
 975     """ Decode the bits in the TTE/PTE value specified <tte_val> for translation level <level> 
 976         Syntax: (lldb) decode_tte <tte_val> <level> 
 978     if cmd_args 
== None or len(cmd_args
) < 2: 
 979         raise ArgumentError("Too few arguments to decode_tte.") 
 980     if kern
.arch 
== 'arm': 
 981         PmapDecodeTTEARM(kern
.GetValueFromAddress(cmd_args
[0], "unsigned long"), ArgumentStringToInt(cmd_args
[1]), vSCRIPT
) 
 982     elif kern
.arch
.startswith('arm64'): 
 983         PmapDecodeTTEARM64(long(kern
.GetValueFromAddress(cmd_args
[0], "unsigned long")), ArgumentStringToInt(cmd_args
[1])) 
 985         raise NotImplementedError("decode_tte does not support {0}".format(kern
.arch
)) 
 988 PVH_HIGH_FLAGS_ARM64 
= (1 << 62) | 
(1 << 61) | 
(1 << 60) | 
(1 << 59) 
 989 PVH_HIGH_FLAGS_ARM32 
= (1 << 31) 
 992     """ Walk a physical-to-virtual reverse mapping list maintained by the arm pmap 
 993         pa: physical address (NOT page number).  Does not need to be page-aligned  
 995     vm_first_phys 
= unsigned(kern
.globals.vm_first_phys
) 
 996     vm_last_phys 
= unsigned(kern
.globals.vm_last_phys
) 
 997     if pa 
< vm_first_phys 
or pa 
>= vm_last_phys
: 
 998         raise ArgumentError("PA {:#x} is outside range of managed physical addresses: [{:#x}, {:#x})".format(pa
, vm_first_phys
, vm_last_phys
)) 
 999     page_size 
= kern
.globals.page_size
 
1000     pn 
= (pa 
- unsigned(kern
.globals.vm_first_phys
)) / page_size
 
1001     pvh 
= unsigned(kern
.globals.pv_head_table
[pn
]) 
1002     pvh_type 
= pvh 
& 0x3 
1003     print "PVH raw value: ({:#x})".format(pvh
) 
1004     if kern
.arch
.startswith('arm64'): 
1006         iommu_table_flag 
= 1 << 63 
1007         pvh 
= pvh | PVH_HIGH_FLAGS_ARM64
 
1010         iommu_table_flag 
= 0  
1011         pvh 
= pvh | PVH_HIGH_FLAGS_ARM32
 
1013         print "PVH type: NULL" 
1016         print "PVH type: page-table descriptor ({:#x})".format(pvh 
& ~
0x3) 
1021         print "PVH type: single PTE" 
1022         if ptep 
& iommu_flag
: 
1023             ptep 
= ptep 
& ~iommu_flag
 
1024             if ptep 
& iommu_table_flag
: 
1025                 pte_str 
= ' (IOMMU table), entry' 
1027                 pte_str 
= ' (IOMMU state), descriptor' 
1028                 ptep 
= ptep | iommu_table_flag
 
1029         print "PTE {:#x}{:s}: {:#x}".format(ptep
, pte_str
, dereference(kern
.GetValueFromAddress(ptep
, 'pt_entry_t *'))) 
1032         print "PVH type: PTE list" 
1034             pve 
= kern
.GetValueFromAddress(pvep
, "pv_entry_t *") 
1035             if unsigned(pve
.pve_next
) & 0x1: 
1036                 pve_str 
= ' (alt acct) ' 
1040             pvep 
= unsigned(pve
.pve_next
) & ~
0x1 
1041             ptep 
= unsigned(pve
.pve_ptep
) & ~
0x3 
1042             if ptep 
& iommu_flag
: 
1043                 ptep 
= ptep 
& ~iommu_flag
 
1044                 if ptep 
& iommu_table_flag
: 
1045                     pve_str 
= ' (IOMMU table), entry' 
1047                     pve_str 
= ' (IOMMU state), descriptor' 
1048                     ptep 
= ptep | iommu_table_flag
 
1049             print "PVE {:#x}, PTE {:#x}{:s}: {:#x}".format(current_pvep
, ptep
, pve_str
, dereference(kern
.GetValueFromAddress(ptep
, 'pt_entry_t *'))) 
1051 @lldb_command('pv_walk') 
1052 def PVWalk(cmd_args
=None): 
1053     """ Show mappings for <physical_address> tracked in the PV list. 
1054         Syntax: (lldb) pv_walk <physical_address> 
1056     if cmd_args 
== None or len(cmd_args
) < 1: 
1057         raise ArgumentError("Too few arguments to pv_walk.") 
1058     if not kern
.arch
.startswith('arm'): 
1059         raise NotImplementedError("pv_walk does not support {0}".format(kern
.arch
)) 
1060     PVWalkARM(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long')) 
1062 @lldb_command('kvtophys') 
1063 def KVToPhys(cmd_args
=None): 
1064     """ Translate a kernel virtual address to the corresponding physical address. 
1065         Assumes the virtual address falls within the kernel static region. 
1066         Syntax: (lldb) kvtophys <kernel virtual address> 
1068     if cmd_args 
== None or len(cmd_args
) < 1: 
1069         raise ArgumentError("Too few arguments to kvtophys.") 
1070     if kern
.arch
.startswith('arm'): 
1071         print "{:#x}".format(KVToPhysARM(long(unsigned(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long'))))) 
1072     elif kern
.arch 
== 'x86_64': 
1073         print "{:#x}".format(long(unsigned(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long'))) - unsigned(kern
.globals.physmap_base
)) 
1075 @lldb_command('phystokv') 
1076 def PhysToKV(cmd_args
=None): 
1077     """ Translate a physical address to the corresponding static kernel virtual address. 
1078         Assumes the physical address corresponds to managed DRAM. 
1079         Syntax: (lldb) phystokv <physical address> 
1081     if cmd_args 
== None or len(cmd_args
) < 1: 
1082         raise ArgumentError("Too few arguments to phystokv.") 
1083     print "{:#x}".format(kern
.PhysToKernelVirt(long(unsigned(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long'))))) 
1085 def KVToPhysARM(addr
): 
1086     if kern
.arch
.startswith('arm64'): 
1087         ptov_table 
= kern
.globals.ptov_table
 
1088         for i 
in range(0, kern
.globals.ptov_index
): 
1089             if (addr 
>= long(unsigned(ptov_table
[i
].va
))) and (addr 
< (long(unsigned(ptov_table
[i
].va
)) + long(unsigned(ptov_table
[i
].len)))): 
1090                 return (addr 
- long(unsigned(ptov_table
[i
].va
)) + long(unsigned(ptov_table
[i
].pa
))) 
1091     return (addr 
- unsigned(kern
.globals.gVirtBase
) + unsigned(kern
.globals.gPhysBase
)) 
1093 def ShowPTEARM(pte
): 
1094     """ Display vital information about an ARM page table entry 
1095         pte: kernel virtual address of the PTE.  Should be L3 PTE.  May also work with L2 TTEs for certain devices. 
1097     page_size 
= kern
.globals.arm_hardware_page_size
 
1098     pn 
= (KVToPhysARM(pte
) - unsigned(kern
.globals.vm_first_phys
)) / page_size
 
1099     pvh 
= unsigned(kern
.globals.pv_head_table
[pn
]) 
1100     if kern
.arch
.startswith('arm64'): 
1101         pvh 
= pvh | PVH_HIGH_FLAGS_ARM64
 
1103         pvh 
= pvh | PVH_HIGH_FLAGS_ARM32
 
1104     pvh_type 
= pvh 
& 0x3 
1106         raise ValueError("PV head {:#x} does not correspond to a page-table descriptor".format(pvh
)) 
1107     ptd 
= kern
.GetValueFromAddress(pvh 
& ~
0x3, 'pt_desc_t *') 
1108     print "descriptor: {:#x}".format(ptd
) 
1109     print "pmap: {:#x}".format(ptd
.pmap
) 
1110     pt_index 
= (pte 
% kern
.globals.page_size
) / page_size
 
1111     pte_pgoff 
= pte 
% page_size
 
1112     if kern
.arch
.startswith('arm64'): 
1113         pte_pgoff 
= pte_pgoff 
/ 8 
1114         nttes 
= page_size 
/ 8 
1116         pte_pgoff 
= pte_pgoff 
/ 4 
1117         nttes 
= page_size 
/ 4 
1118     if ptd
.ptd_info
[pt_index
].refcnt 
== 0x4000: 
1120         granule 
= nttes 
* page_size
 
1124     print "maps VA: {:#x}".format(long(unsigned(ptd
.ptd_info
[pt_index
].va
)) + (pte_pgoff 
* granule
)) 
1125     pteval 
= long(unsigned(dereference(kern
.GetValueFromAddress(unsigned(pte
), 'pt_entry_t *')))) 
1126     print "value: {:#x}".format(pteval
) 
1127     if kern
.arch
.startswith('arm64'): 
1128         print "level: {:d}".format(level
) 
1129         PmapDecodeTTEARM64(pteval
, level
) 
1130     elif kern
.arch 
== 'arm': 
1131         PmapDecodeTTEARM(pteval
, 2, vSCRIPT
) 
1133 @lldb_command('showpte') 
1134 def ShowPTE(cmd_args
=None): 
1135     """ Display vital information about the page table entry at VA <pte> 
1136         Syntax: (lldb) showpte <pte_va> 
1138     if cmd_args 
== None or len(cmd_args
) < 1: 
1139         raise ArgumentError("Too few arguments to showpte.") 
1140     if not kern
.arch
.startswith('arm'): 
1141         raise NotImplementedError("showpte does not support {0}".format(kern
.arch
)) 
1142     ShowPTEARM(kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long')) 
1144 def FindMappingAtLevelARM(pmap
, tt
, nttes
, level
, action
): 
1145     """ Perform the specified action for all valid mappings in an ARM translation table 
1146         pmap: owner of the translation table 
1147         tt: translation table or page table 
1148         nttes: number of entries in tt 
1149         level: translation table level, 1 or 2 
1150         action: callback for each valid TTE 
1152     for i 
in range(nttes
): 
1156                 if tte 
& 0x3 == 0x1: 
1159                     paddr 
= tte 
& 0xFFFFFC00 
1160                 elif tte 
& 0x3 == 0x2: 
1162                     if (tte 
& 0x40000) == 0x40000: 
1164                         paddr 
= tte 
& 0xFF000000 
1167                         paddr 
= tte 
& 0xFFF00000 
1170             elif (tte 
& 0x3) == 0x1: 
1173                 paddr 
= tte 
& 0xFFFF0000 
1174             elif (tte 
& 0x3) != 0: 
1177                 paddr 
= tte 
& 0xFFFFF000 
1180             action(pmap
, level
, type, addressof(tt
[i
]), paddr
, granule
) 
1181             if level 
== 1 and (tte 
& 0x3) == 0x1: 
1182                 tt_next 
= kern
.GetValueFromAddress(kern
.PhysToKernelVirt(paddr
), 'tt_entry_t *') 
1183                 FindMappingAtLevelARM(pmap
, tt_next
, granule 
/ 4, level 
+ 1, action
) 
1184         except Exception as exc
: 
1185             print "Unable to access tte {:#x}".format(unsigned(addressof(tt
[i
]))) 
1187 def FindMappingAtLevelARM64(pmap
, tt
, nttes
, level
, action
): 
1188     """ Perform the specified action for all valid mappings in an ARM64 translation table 
1189         pmap: owner of the translation table 
1190         tt: translation table or page table 
1191         nttes: number of entries in tt 
1192         level: translation table level, 1 2 or 3 
1193         action: callback for each valid TTE 
1195     page_size 
= kern
.globals.arm_hardware_page_size
 
1196     page_offset_mask 
= (page_size 
- 1) 
1197     page_base_mask 
= ((1 << ARM64_VMADDR_BITS
) - 1) & (~page_offset_mask
) 
1198     for i 
in range(nttes
): 
1201             if tte 
& 0x1 == 0x1: 
1202                 if tte 
& 0x2 == 0x2: 
1208                     paddr 
= tte 
& page_base_mask
 
1211                     granule 
= PmapBlockOffsetMaskARM64(level
) + 1 
1212                     paddr 
= tte 
& PmapBlockBaseMaskARM64(level
) 
1215                 action(pmap
, level
, type, addressof(tt
[i
]), paddr
, granule
) 
1216                 if level 
< 3 and (tte 
& 0x2 == 0x2): 
1217                     tt_next 
= kern
.GetValueFromAddress(kern
.PhysToKernelVirt(paddr
), 'tt_entry_t *') 
1218                     FindMappingAtLevelARM64(pmap
, tt_next
, granule 
/ ARM64_TTE_SIZE
, level 
+ 1, action
) 
1219         except Exception as exc
: 
1220             print "Unable to access tte {:#x}".format(unsigned(addressof(tt
[i
])))  
1222 def ScanPageTables(action
, targetPmap
=None): 
1223     """ Perform the specified action for all valid mappings in all page tables, 
1224         optionally restricted to a single pmap. 
1225         pmap: pmap whose page table should be scanned.  If None, all pmaps on system will be scanned. 
1227     print "Scanning all available translation tables.  This may take a long time..." 
1228     def ScanPmap(pmap
, action
): 
1229         if kern
.arch
.startswith('arm64'): 
1230             granule 
= kern
.globals.arm64_root_pgtable_num_ttes 
* 8 
1231         elif kern
.arch 
== 'arm': 
1232             granule 
= pmap
.tte_index_max 
* 4 
1233         action(pmap
, 1, 'root', pmap
.tte
, unsigned(pmap
.ttep
), granule
) 
1234         if kern
.arch
.startswith('arm64'): 
1235             FindMappingAtLevelARM64(pmap
, pmap
.tte
, kern
.globals.arm64_root_pgtable_num_ttes
, kern
.globals.arm64_root_pgtable_level
, action
) 
1236         elif kern
.arch 
== 'arm': 
1237             FindMappingAtLevelARM(pmap
, pmap
.tte
, pmap
.tte_index_max
, 1, action
) 
1239     if targetPmap 
is not None: 
1240         ScanPmap(kern
.GetValueFromAddress(targetPmap
, 'pmap_t'), action
) 
1242         for pmap 
in IterateQueue(kern
.globals.map_pmap_list
, 'pmap_t', 'pmaps'): 
1243             ScanPmap(pmap
, action
)         
1245 @lldb_command('showallmappings') 
1246 def ShowAllMappings(cmd_args
=None): 
1247     """ Find and display all available mappings on the system for 
1248         <physical_address>.  Optionally only searches the pmap 
1249         specified by [<pmap>] 
1250         Syntax: (lldb) showallmappings <physical_address> [<pmap>] 
1251         WARNING: this macro can take a long time (up to 30min.) to complete! 
1253     if cmd_args 
== None or len(cmd_args
) < 1: 
1254         raise ArgumentError("Too few arguments to showallmappings.") 
1255     if not kern
.arch
.startswith('arm'): 
1256         raise NotImplementedError("showallmappings does not support {0}".format(kern
.arch
)) 
1257     pa 
= kern
.GetValueFromAddress(cmd_args
[0], 'unsigned long') 
1259     if len(cmd_args
) > 1: 
1260         targetPmap 
= cmd_args
[1] 
1261     def printMatchedMapping(pmap
, level
, type, tte
, paddr
, granule
): 
1262         if paddr 
<= pa 
< (paddr 
+ granule
): 
1263             print "pmap: {:#x}: L{:d} {:s} at {:#x}: [{:#x}, {:#x})".format(pmap
, level
, type, unsigned(tte
), paddr
, paddr 
+ granule
) 
1264     ScanPageTables(printMatchedMapping
, targetPmap
) 
1266 def checkPVList(pmap
, level
, type, tte
, paddr
, granule
): 
1267     """ Checks an ARM physical-to-virtual mapping list for consistency errors. 
1268         pmap: owner of the translation table 
1269         level: translation table level.  PV lists will only be checked for L2 (arm32) or L3 (arm64) tables. 
1271         tte: KVA of PTE to check for presence in PV list.  If None, presence check will be skipped. 
1272         paddr: physical address whose PV list should be checked.  Need not be page-aligned. 
1275     vm_first_phys 
= unsigned(kern
.globals.vm_first_phys
) 
1276     vm_last_phys 
= unsigned(kern
.globals.vm_last_phys
) 
1277     page_size 
= kern
.globals.page_size
 
1278     if kern
.arch
.startswith('arm64'): 
1279         page_offset_mask 
= (page_size 
- 1) 
1280         page_base_mask 
= ((1 << ARM64_VMADDR_BITS
) - 1) & (~page_offset_mask
) 
1281         paddr 
= paddr 
& page_base_mask
 
1283         pvh_set_bits 
= PVH_HIGH_FLAGS_ARM64
 
1284     elif kern
.arch 
== 'arm': 
1285         page_base_mask 
= 0xFFFFF000 
1286         paddr 
= paddr 
& page_base_mask
 
1288         pvh_set_bits 
= PVH_HIGH_FLAGS_ARM32
 
1289     if level 
< max_level 
or paddr 
< vm_first_phys 
or paddr 
>= vm_last_phys
: 
1291     pn 
= (paddr 
- vm_first_phys
) / page_size
 
1292     pvh 
= unsigned(kern
.globals.pv_head_table
[pn
]) | pvh_set_bits
 
1293     pvh_type 
= pvh 
& 0x3 
1294     if pmap 
is not None: 
1295         pmap_str 
= "pmap: {:#x}: ".format(pmap
) 
1299         tte_str 
= "pte {:#x} ({:#x}): ".format(unsigned(tte
), paddr
) 
1301         tte_str 
= "paddr {:#x}: ".format(paddr
)  
1302     if pvh_type 
== 0 or pvh_type 
== 3: 
1303         print "{:s}{:s}unexpected PVH type {:d}".format(pmap_str
, tte_str
, pvh_type
) 
1306         if tte 
is not None and ptep 
!= unsigned(tte
): 
1307             print "{:s}{:s}PVH mismatch ({:#x})".format(pmap_str
, tte_str
, ptep
) 
1309             pte 
= long(unsigned(dereference(kern
.GetValueFromAddress(ptep
, 'pt_entry_t *')))) & page_base_mask 
 
1311                 print "{:s}{:s}PVH {:#x} maps wrong page ({:#x}) ".format(pmap_str
, tte_str
, ptep
, pte
) 
1312         except Exception as exc
: 
1313             print "{:s}{:s}Unable to read PVH {:#x}".format(pmap_str
, tte_str
, ptep
) 
1318             pve 
= kern
.GetValueFromAddress(pvep
, "pv_entry_t *") 
1319             pvep 
= unsigned(pve
.pve_next
) & ~
0x1 
1320             ptep 
= unsigned(pve
.pve_ptep
) & ~
0x3 
1321             if tte 
is not None and ptep 
== unsigned(tte
): 
1324                 pte 
= long(unsigned(dereference(kern
.GetValueFromAddress(ptep
, 'pt_entry_t *')))) & page_base_mask 
 
1326                     print "{:s}{:s}PVE {:#x} maps wrong page ({:#x}) ".format(pmap_str
, tte_str
, ptep
, pte
) 
1327             except Exception as exc
: 
1328                 print "{:s}{:s}Unable to read PVE {:#x}".format(pmap_str
, tte_str
, ptep
) 
1329         if tte 
is not None and not tte_match
: 
1330             print "{:s}{:s}not found in PV list".format(pmap_str
, tte_str
, paddr
) 
1332 @lldb_command('pv_check', 'P') 
1333 def PVCheck(cmd_args
=None, cmd_options
={}): 
1334     """ Check the physical-to-virtual mapping for a given PTE or physical address 
1335         Syntax: (lldb) pv_check <addr> [-p] 
1336             -P        : Interpret <addr> as a physical address rather than a PTE 
1338     if cmd_args 
== None or len(cmd_args
) < 1: 
1339         raise ArgumentError("Too few arguments to pv_check.") 
1340     if kern
.arch 
== 'arm': 
1342     elif kern
.arch
.startswith('arm64'): 
1345         raise NotImplementedError("showallmappings does not support {0}".format(kern
.arch
)) 
1346     if "-P" in cmd_options
: 
1348         pa 
= long(unsigned(kern
.GetValueFromAddress(cmd_args
[0], "unsigned long"))) 
1350         pte 
= kern
.GetValueFromAddress(cmd_args
[0], 'pt_entry_t *') 
1351         pa 
= long(unsigned(dereference(pte
))) 
1352     checkPVList(None, level
, None, pte
, pa
, None) 
1354 @lldb_command('check_pmaps') 
1355 def CheckPmapIntegrity(cmd_args
=None): 
1356     """ Performs a system-wide integrity check of all PTEs and associated PV lists. 
1357         Optionally only checks the pmap specified by [<pmap>] 
1358         Syntax: (lldb) check_pmaps [<pmap>] 
1359         WARNING: this macro can take a HUGE amount of time (several hours) if you do not 
1360         specify [pmap] to limit it to a single pmap.  It will also give false positives 
1361         for kernel_pmap, as we do not create PV entries for static kernel mappings on ARM. 
1362         Use of this macro without the [<pmap>] argument is heavily discouraged. 
1364     if not kern
.arch
.startswith('arm'): 
1365         raise NotImplementedError("showallmappings does not support {0}".format(kern
.arch
)) 
1367     if len(cmd_args
) > 0: 
1368         targetPmap 
= cmd_args
[0] 
1369     ScanPageTables(checkPVList
, targetPmap
) 
1371 @lldb_command('pmapsforledger') 
1372 def PmapsForLedger(cmd_args
=None): 
1373     """ Find and display all pmaps currently using <ledger>. 
1374         Syntax: (lldb) pmapsforledger <ledger> 
1376     if cmd_args 
== None or len(cmd_args
) < 1: 
1377         raise ArgumentError("Too few arguments to pmapsforledger.") 
1378     if not kern
.arch
.startswith('arm'): 
1379         raise NotImplementedError("pmapsforledger does not support {0}".format(kern
.arch
)) 
1380     ledger 
= kern
.GetValueFromAddress(cmd_args
[0], 'ledger_t') 
1381     for pmap 
in IterateQueue(kern
.globals.map_pmap_list
, 'pmap_t', 'pmaps'): 
1382         if pmap
.ledger 
== ledger
: 
1383             print "pmap: {:#x}".format(pmap
)