
    [
#g͍              	          d dl Z d dlZd dlZd dlZd dlZd dlmZmZmZm	Z	m
Z
mZ d dlmZ d dlmZ d dlmZmZ d dlmZ d dlmZ d dlmZ  e j2                  e      Z	  G d	 d
ej8                        Z G d dej<                        Z G d de      Z  G d de e      Z! G d de      Z" G d de"e      Z#	  G d d      Z$ G d d      Z%dde&dede&de&fdZ'y)    N)OptionalDictAnyListIterableTuple)Enum)classproperty)
interfaces
exceptions)requirements)linear)	path_joinc                       e Zd Zy)AArch64ExceptionN__name__
__module____qualname__     R/home/panchajanya/Development/work/volatility3/volatility3/framework/layers/arm.pyr   r   ,       r   r   c                       e Zd ZdZ ej
                  dd iddiej                  j                  j                        Z	dZ
e
dz  ZdZeZg dg dg d	d
Z	 d=dej                  j                   dededeeeef      ddf
 fdZd>dZededededee   fd       Zedededeee      fd       Zdedeeeef   fdZdedeeeef   fdZ e jB                  d      dedee"   fd       Z#	 d?ded ed!ede$eeeeeef      fd"Z%	 d?ded ed!ede$eeeeeef      fd#Z&dee   fd$Z'd@ded edefd%Z(dedefd&Z)d'edefd(Z*e+ e jB                         defd)              Z,e+ e jB                         defd*              Z-e+ e jB                         defd+              Z.e/ e jB                         defd,              Z0e+ e jB                         defd-              Z1e+ e jB                         defd.              Z2	 d?d/e3d!edefd0Z4ed1e5de5fd2       Z6d3edefd4Z7d3edefd5Z8e9	 d=d6ed7ed8ed9ee   def
d:       Z:e+dee   fd;       Z;edeejx                  jz                     fd<       Z> xZ?S )AAArch64zTranslation Layer for the Arm AArch64 memory mapping.

    This layer can be instantiated in two contexts : Low space (user land), High space (kernel land).
    architecturemappedT@      ))3   0   )/   '   )&      )      )      ))r    r"   ).   $   )#      )      ))r    *   ))   r&   )      )   r3   r   Ncontextconfig_pathnamemetadatareturnc                 (	   t         |   ||||       i | _        t        j                  j
                  t        j                  j
                  t        j                  j
                  fD ]:  }| j                  j                  |      s| j                  |   | j                  |<   < | j                  | j                        | _        | j                  d   | _        | j                  j                  dd      | _        | j                  j                  dd      | _        | j                  d   | _        | j                  d   | _        | j#                  t        j                  j$                        | _        | j#                  t        j                  j(                        | j#                  t        j                  j*                        g| _        t.        j1                  | j#                  t        j                  j2                              t.        j5                  | j#                  t        j                  j6                              g| _        t;        | j                   | j&                  k(        | _        d| j,                  | j<                     z
  | _        | j8                  | j<                     | _         | j@                  d	z  | _!        | jB                  jE                         d
z
  | _#        	 | j>                  dk  rdnd| _$        | jH                  r,| j@                  dv rd| _%        n| j@                  dk(  rd| _%        | jM                  | j@                  | j>                        | _'        | jQ                  | j@                  | jN                  | jH                        | _)        | jU                         | _+        | jY                  d
| jZ                  z  d
z
  | jZ                  | j>                  d      | _.        t_        j`                  | j                        | _1        | jB                  | jb                  z  | _2        | j#                  t        j                  jf                  d      }|rt.        ji                  |      | _5        nd | _5        | j                  r| jm                          y y )N)r5   r6   r7   r8   entry_formatlayer_debugFtranslation_debugmemory_layerpage_map_offsetr   i      r3   Tr4   r3   )	   r   )   r)   r   )7super__init__	_cpu_regsAArch64RegMapTCR_EL1r   	TTBR1_EL1ID_AA64MMFR1_EL1configget_map_reg_values_cpu_regs_mapped_entry_format_layer_debug_translation_debug_base_layer_page_map_offset_read_register_fieldBADDR_page_map_offset_kernelT0SZT1SZ
_ttbs_tnszAArch64RegFieldValues_get_ttbr0_el1_granule_sizeTG0_get_ttbr1_el1_granule_sizeTG1_ttbs_granulesint_virtual_addr_space_ttb_bitsize_ttb_granule
_page_size
bit_length_page_size_in_bits
_is_52bits_ta_51_x_bits_determine_ttb_lookup_indexes_ttb_lookup_indexes_determine_ttb_descriptor_bits_ttb_descriptor_bits_get_virtual_addr_range_virtual_addr_range_mask_bits_per_register_canonical_prefixstructcalcsize_entry_size_entry_numberHAFDBS_get_feature_HAFDBS_feat_hafdbs_print_layer_debug_informations)selfr5   r6   r7   r8   registerhafdbs	__class__s          r   rE   zAArch64.__init__K   s    	4( 	 	
 !!**##,,**33
H {{x(+/;;x+@x(
 !% 4 4T^^ D![[8 KKOOM5A"&++//2Eu"M;;~6 $,= >'+'@'@##))(
$ %%m&;&;&@&@A%%m&;&;&@&@A

 "==))-*?*?*C*CD "==))-*?*?*C*CD	
 $'!!T%A%AA$
 
 1I1I!JJ //0H0HI++d2"&//"<"<">"B	 #'"3"3b"8$e??  G+%+"""b(%-" $(#E#Et00$
  %)$G$Gt77%
! $(#?#?#A !%$)))Q.##	"
 "??4+=+=>!__0@0@@ **=+I+I+P+PRVW 5 I I& QD $D002 r   c                 f   t         j                  d| j                          t         j                  d| j                  rdnd        t         j                  dt	        | j                         D cg c]  }t        |       c}              t         j                  d| j                          t         j                  d| j                   d| j                          t         j                  d	t        | j                                t         j                  d
| j                          y c c}w )NzBase layer : zVirtual address space : kerneluserz Virtual addresses space range : zPage size : TzSZ : zPage map offset : zTranslation mappings : )vollogdebugrR   ra   tuplerm   hexrc   rb   rS   rj   )rz   xs     r   ry   z'AArch64._print_layer_debug_informations   s    }T%5%5$678&43K3KxQW&XY	
 	.udFbFbFd5ec!f5e/f.gh	
 	|D$5$5#678q112%8I8I7JKL)#d.C.C*D)EFG.t/G/G.HIJ 6fs   0D.ttb_granulettb_lookup_indexes	is_52bitsc                 &    |dv r|rdnd|d   d   fS )zReturns the descriptor bits to extract from a descriptor (high and low)

        Example with granule = 4 kB without 52 bits :
            (47,12)
        Example with granule = 16 kB and 52 bits :
            (49,14)
        rA   1   r"   r@   r   )clsr   r   r   s       r   rk   z&AArch64._determine_ttb_descriptor_bits   s)     (YBBr"1%
 	
r   ttb_bitsizec                 x    | j                   |   D cg c]  }||d   kD  r| }}|dz
  |d   d   f|d<   |S c c}w )a  Returns the bits to extract from a translation address (highs and lows)

        Example with bitsize = 47 and granule = 4 kB :
            indexes = [(51, 48), (47, 39), (38, 30), (29, 21), (20, 12)]
            result = [(46, 39), (38, 30), (29, 21), (20, 12)]
        r@   r   )_granules_indexes)r   r   r   indexindexess        r   ri   z%AArch64._determine_ttb_lookup_indexes   s^     ..{;
U1X% 
 

 "Aowqz!}5

s   7virtual_offsetc                     | j                  |      \  }}}| j                  ||dz
  d      }||z   }|d|z  | j                  fS )zTranslates a specific offset based on paging tables.

        Returns the translated offset, the contiguous pagesize that the
        translated address lives in and the layer_name that the address
        lives in
        r@   r      )_translate_entryro   rR   )rz   r   table_addressposition_offset_within_pagephysical_offsets          r   
_translatezAArch64._translate   sT     &*%:%:>%J"x!ZZ1aH'*<<8T-=-===r   c                    | j                   j                  | j                     }| j                  |dd      }|| j                  k7  r!t        j                  | j                  |      | j                  }t        | j                        dz
  }t        | j                        D ]  \  }\  }}| j                  |||      }	t        j                  | j                  |j                  ||	| j                   z  z   | j                               \  }
d}| j"                  rC| j                  |
| j$                  d   | j$                  d         }|d|j'                         z
  z  }| j                  |
dd      }||k  r{|dk(  rv|| j                  |
| j(                  d   | j(                  d         | j(                  d   z  z  }| j+                  |      *t        j,                  | j                  |||
      ||k  r-|dk(  r(|| j                  |
| j(                  d   |      |z  z  } np||k(  rG|dk(  rB|| j                  |
| j(                  d   | j(                  d         | j(                  d   z  z  } n$t        j,                  | j                  |||
       | j.                  rYt0        j3                  dt5        |       d	t5        |       d
t5        | j                  |dz
  d             dt5        
              |
fS )zTranslates a virtual offset to a physical one within this segment
        Returns the translated address, the maximum offset within the block and the page
        the translated address lives in
        7   
layer_nameinvalid_addressr@   r   4      )r   r   invalid_bitsentryzVirtual z lives in page frame z at offset z with descriptor )r5   layersrR   ro   ra   r   InvalidAddressExceptionr7   rS   lenrj   	enumeraterr   unpackrO   read_register_sizerg   rh   re   rl   _get_valid_tablePagedInvalidAddressExceptionrQ   r   r   r   )rz   r   
base_layerttb_selectorr   	max_levellevelhigh_bitlow_bitr   
descriptorta_51_xdescriptor_types                r   r   zAArch64._translate_entry   sj   
 \\(()9)9:
 zz."b9 43334499 . 
 --001A5	*3D4L4L*M&E&HgJJ~xAE"MM""!UT-@-@%@A4CVCVMZ M**&&q)&&q)
 !(B1C1C1E,E F #jjQ:Oy _%<JJ"11!411!4
 0034 ((7?$AA#'99(6%,(	  "$'>JJ"11!4
  )#4(?JJ"11!411!4
 0034  !==#yy$2!($	 { +NH ""LL3~.//DSEWDXXcdghlhrhr  tB  DK  LM  DM  OP  iQ  eR  dS  Sd  eh  is  et  du  v gz11r   i  base_addressc                     | j                   j                  j                  | j                  || j                        }||d| j
                   | j                  z  k(  ry|S )zJExtracts the translation table, validates it and returns it if it's valid.N)_contextr   r   rR   	page_sizert   ru   )rz   r   tables      r   r   zAArch64._get_valid_tableM  sZ     $$))lDNN
 E,D,,-0B0BBBr   offsetlengthignore_errorsc              #      K   dx}x}x}x}}| j                  |||      D ]?  \  }}	}
}}|||z   |k7  s||z   |
k7  s||k7  r|	|||||f |}|
}|	}|}|}6||	z  }||z  }A |||||
|||||f yyyyyyw)zReturns a sorted iterable of (offset, sublength, mapped_offset, mapped_length, layer)
        mappings.

        This allows translation layers to provide maps of contiguous
        regions in one layer
        N)_mapping)rz   r   r   r   stashed_offsetstashed_mapped_offsetstashed_sizestashed_mapped_sizestashed_map_layersizemapped_offsetmapped_size	map_layers                r   mappingzAArch64.mappingY  s     	 	. 	 	@SCG==FMD
?FD-i &"\1V;),??=P%2 "-(,8MObduuu!'(5%#&1#$-! $#{2#+D
0 &%1(#/!- ,0EGZ\mmm . 0 ) 2 's   A9A;c              #   .  K   |dk(  r`	 | j                  |      \  }}}| j                  j                  |   j                  |      st	        j
                  ||      	 |||||f y|dkD  r	 | j                  |      \  }}}t        |||z  z
  |      }	| j                  j                  |   j                  ||	      st	        j
                  ||      	 ||	||	|f ||	z  }||	z  }|dkD  ryy# t        j
                  $ r |s Y yw xY w# t        j                  t        j
                  f$ rb}
	 |s t        |
t        j                        rd|
j                  z  dz
  }nd| j                  z  dz
  }|dz   ||z  z
  }||z  }||z  }Y d}
~
d}
~
ww xY ww)a  Returns a sorted iterable of (offset, sublength, mapped_offset, mapped_length, layer)
        mappings.This allows translation layers to provide maps of contiguous regions in one layer.

            A bit of lexical definition : "page" means "virtual page" (i.e. a chunk of virtual address space) and "page frame" means "physical page" (i.e. a chunk of physical memory).

            What this is actually doing :
                - translate a virtual offset to a physical offset
                - determine the page size the virtual offset lives in (page_size)
                - based on the position of the offset in the page, calculate how many bytes to add to get to the end of the page (chunk_size)
                - add the chunk_size to the virtual offset, so that we can point to the start of the next page

            Example (assume page size is 4096):
            -> 0xffff800000f92140 lives in page 0xfffffc0000170640 at offset 0x140, which maps to page frame 0x45c19000 at offset 0x140
                -> 4096 - 0x140 = 3776
                -> 0xffff800000f92140 + 3776 = 0xffff800000f93000
                -> we know the start of the next page is at virtual offset 0xffff800000f93000, so we can directly jump to it (no need to translate every byte in between)
            -> 0xffff800000f93000 lives in page 0xfffffc0000087040 at offset 0x0, which maps to page frame 0x421c1000 at offset 0x0
                -> 4096 - 0x0 = 4096
                -> 0xffff800000f93000 + 4096 = 0xffff800000f94000
            etc. while "length" > 0
        r   r   Nr@   )r   r   r   is_validr   r   minr   
isinstancer   
page_shift)rz   r   r   r   r   r   r   chunk_offsetr   
chunk_sizeexcpmasklength_diffs                r   r   zAArch64._mapping  s    2 Q;	/3v/F,q*}}++J7@@O$<<#-}  P &-CCqj%6:oof6M3i lY.F!GP
}}++J7@@ * %<<#-| 0 j,
JNN*$*$= qj 55 $" 7722 & %dJ$K$KL!2!22a7D0A5D"Qh&4-8+%+%!&s[   FAC1 F.A'D F/F1D
F	D

F#F0AFFFFc                     | j                   dk(  r d}d| j                  dz
  z  }||dz
  z   }||fS d}d| j                  dz
  z  }||dz
  z
  }||fS )zVReturns the virtual address space range for the current context (user or kernel space)r   r@   l    )ra   rb   )rz   	ttb_startttb_sizettb_ends       r   rm   zAArch64._get_virtual_addr_range  s|     ##q(IT..23H8a<0G 7##	  GT..23H8a<0I7##r   c                     	 t        | j                  ||      D cg c]0  \  }}}}}| j                  j                  |   j	                  |      2 c}}}      S c c}}}w # t
        j                  $ r Y yw xY w)zPReturns whether the address offset can be translated to a valid
        address.F)allr   r   r   r   r   r   )rz   r   r   r   r   layers         r   r   zAArch64.is_valid  s    		 :>ff9U 51mQ MM((/88G 
 11 		s"   A" 5AA" A" "A87A8c                 H    | j                  | j                  |      d         S )z2Returns whether the page at offset is marked dirtyr   )_page_is_dirtyr   )rz   r   s     r   is_dirtyzAArch64.is_dirty  s#    ""4#8#8#@#CDDr   r   c                 \    | j                   rt        |dz  xr |dz         S t        d      )uw  
        Hardware management of the dirty state (only >= Armv8.1-A).

        General documentation :
         https://developer.arm.com/documentation/102376/0200/Access-Flag/Dirty-state

        Technical documentation :
         [1], see D8.4.6, page 5877 : "Hardware management of the dirty state"
         [1], see D8-16 and page 5861 : "Stage 1 attribute fields in Block and Page descriptors"

        > For the purpose of FEAT_HAFDBS, a Block descriptor or Page descriptor can be described as having one of the following states:
            • Non-writeable.
            • Writeable-clean.
            • Writeable-dirty.

        [1], see D8-41, page 5868 :
            AP[2]  | Access permission
            -------|------------------
            0      | Read/write
            1      | Read-only

         AF=0. Region not accessed.
         AF=1. Region accessed.
        l         @    zHardware updates to Access flag and Dirty state in translation tables are not available. Please try using a software based implementation of dirty state management.)rx   boolNotImplementedError)rz   r   s     r   r   zAArch64._page_is_dirty  s?    2  '*FUf5E0FGG% w r   c                     | j                   S )zlPage shift for this layer, which is the page size bit length.
        - Typical values : 12, 14, 16
        )rf   rz   s    r   r   zAArch64.page_shift  s     &&&r   c                     | j                   S )zZPage size for this layer, in bytes.
        - Typical values : 4096, 16384, 65536
        )rd   r   s    r   r   zAArch64.page_size  s     r   c                 "    | j                   dz
   S zPage mask for this layer.r@   r   r   s    r   	page_maskzAArch64.page_mask   s     !#$$r   c                     | j                   S )z[Returns the bits_per_register to determine the range of an
        AArch64TranslationLayer.)rp   r   s    r   bits_per_registerzAArch64.bits_per_register&  s    
 %%%r   c                      | j                   d   S )Nr   rn   r   s    r   minimum_addresszAArch64.minimum_address-       ''**r   c                      | j                   d   S )Nr@   r   r   s    r   maximum_addresszAArch64.maximum_address2  r   r   register_fieldc                 v    t        |      }	 | j                  |   S # t        $ r |rY y t        | d      w xY w)Nz8 register field wasn't provided to this layer initially.)strrN   KeyError)rz   r   r   reg_field_paths       r   rT   zAArch64._read_register_field7  sR     ^,	((88 	!""Z[ 	s    88registers_valuesc                 D   i }t        j                  t        t         j                        D ]r  \  }}t	        |t
              s||j                         v s*||   }|D ]?  }t        ||j                        }|j                  \  }}	| j                  |||	      }
|
||<   A t |S )a  Generates a dict of dot joined AArch64 CPU registers and fields.
        Iterates over every mapped register in AArch64RegMap,
        check if a register value was provided to this layer,
        mask every field accordingly and store the result.

        Example return value :
         {'TCR_EL1.TG1': 3, 'TCR_EL1.T1SZ': 12, 'TCR_EL1.TG0': 1,
          'TCR_EL1.T0SZ': 12, 'TTBR1_EL1.ASID': 0, 'TTBR1_EL1.BADDR': 1092419584,
          'TTBR1_EL1.CnP': 0}
        )inspect
getmembersrG   isclass
issubclassr	   keysr   r7   valuero   )r   r   masked_treesmm_cls_namemm_cls	reg_valuefield
dot_joinedr   r   masked_values              r   rM   zAArch64._map_reg_valuesD  s     #*#5#5mW__#UK&$'K;K;P;P;R,R,[9	#E!*;

!CJ(-%Hg#&99Y'#JL/;L,	 $ $V r   addrc                     | j                   | j                  k  r|| j                  z  S |d| j                  dz
  z  k  r|S | j                  || j                  d      | j                  z  S )z[Canonicalizes an address by performing an appropiate sign extension on the higher addressesr@   r   )rp   rb   address_maskro   rq   rz   r  s     r   canonicalizezAArch64.canonicalize\  sh    ""d&7&77$++++Q$++a//0Kzz$ 1 1158N8NNNr   c                 N    |d| j                   dz
  z  k  r|S || j                  z  S )zRemoves canonicalization to ensure an adress fits within the correct range if it has been canonicalized

        This will produce an address outside the range if the canonicalization is incorrect
        r@   )rb   rq   r  s     r   decanonicalizezAArch64.decanonicalized  s2    
 1))A--.Kd,,,,r   r   r   r   shiftc                 J    ||}d|dz   z  dz
  }d|z  dz
  }||z  }| |z  |z	  S )zAReturns the bits of a value between highbit and lowbit inclusive.r@   r   )r   r   r   r  	high_masklow_maskr   s          r   ro   zAArch64._maskm  sH    
 =E8a<(A-	LA%8#&&r   c                     | j                   gS )zRReturns a list of the lower layer names that this layer is dependent
        upon.)rR   r   s    r   dependencieszAArch64.dependenciesy  s       !!r   c                 f   t        j                  dd      t        j                  ddd      t        j                  ddd      t        j                  d	d
dd      t        j                  dd
dd      t        j                  dd
d      t        j                  dd
d      t        j                  t
        j                  j                  dd      t        j                  t
        j                  j                  dd      t        j                  t
        j                  j                  d
dd       g
S )Nr>   F)r7   optionalr?   zJDTB of the target context (either "kernel space" or "user space process").)r7   r  descriptionr;   zOFormat and byte order of table descriptors, represented in the "struct" format.r<   TzLSpecify if debugging informations about the layer should be printed to user.)r7   r  r  defaultr=   zHSpecify if translation debugging informations should be printed to user.kernel_virtual_offsetzASLR offsetkernel_bannerz\Kernel unique identifier, including compiler name and version, kernel version, compile time.zTCR_EL1 registerzTTBR1_EL1 registerzID_AA64MMFR1_EL1 register)
r   TranslationLayerRequirementIntRequirementStringRequirementBooleanRequirementrG   rH   r   rI   rJ   r   s    r   get_requirementszAArch64.get_requirements  s.    44#e ''&h
 **#m
 ++"j	 ++(f	 '',t **$z
 ''"**33.
 ''",,550
 ''"33<<7	Y2
 2	
r   )N)r9   NF)r@   )@r   r   r   __doc__collectionsChainMapr   r   TranslationLayerInterface_direct_metadatarp   r   _maxphyaddr_maxvirtaddrr   r5   ContextInterfacer   r   r   r   rE   ry   classmethodr`   r   r   rk   r   ri   r   r   	functools	lru_cachebytesr   r   r   r   rm   r   r   r   propertyr   r   r   r
   r   r   r   r	   rT   dictrM   r  r  staticmethodro   r  configurationRequirementInterfacer  __classcell__r}   s   @r   r   r   0   s   
 ,{++	#	433DD '1,N KL >4* .2a3##44a3 a3 	a3
 4S>*a3 
a3F 

36
CG
	s
 
" ,/	eCj	 $> >sC}1E >\2s \2uS#s]7K \2| Y	S 	Xe_ 	 	 ?D*n*n#&*n7;*n	%S#sC/0	1*nZ ?DD%D%#&D%7;D%	%S#sC/0	1D%L$	s$"s C  Es Et E C  D  D Y'C '  ' Y3    Y%3 %  % Y&# &  &
 Y+ +  + Y+ +  + ;@"37	 t   .O O O-3 -3 - HL	'	'!	',/	'8@	'		' 	' "d3i " "
 3
j&>&>&S&S!T 3
 3
r   r   c                   (     e Zd Zdedef fdZ xZS )LinuxAArch64Mixinr   r9   c                 n    t        |dz        }	 t        | 	  |      }|xs |S # t        $ r |cY S w xY w)a  Returns whether a particular page is dirty based on its (page table) entry.
        The bit indicates that its associated block of memory
        has been modified and has not been saved to storage yet.

        The following is based on Linux software AArch64 dirty bit management.
         [2], see arch/arm64/include/asm/pgtable-prot.h#L18
         [2], see pte_wrprotect()
         [3], see page 12-25
         https://lkml.org/lkml/2023/7/7/77 -> Linux implementation detail
        l          r   rD   r   r   rz   r   sw_dirtyhw_dirtyr}   s       r   r   z LinuxAArch64Mixin._page_is_dirty  sG     )*	w-e4H'x'" 	O	s   & 44r   r   r   r`   r   r   r2  r3  s   @r   r5  r5    s    C D  r   r5  c                       e Zd Zy)LinuxAArch64Nr   r   r   r   r=  r=    r   r   r=  c                   (     e Zd Zdedef fdZ xZS )WindowsAArch64Mixinr   r9   c                 ~    t        |dz  xr |dz         }	 t        | 	  |      }|xs |S # t        $ r |cY S w xY w)a  Returns whether a particular page is dirty based on its (page table) entry.
        The bit indicates that its associated block of memory
        has been modified and has not been saved to storage yet.

        The following is based on the Windows kernel function MiMarkPteDirty().
        Capabilities are initialized in MiInitializeSystemDefaults().
        When marking a PTE dirty, MiMarkPteDirty() will:
         - set AF to 1 (ACCESSED) manually if hardware does not support it;
         - set AP to 0 (RW) manually if hardware does not support it.
        In the end, we need to detect if the DBM is software (56) or hardware (51),
        and if in any scenario the AP bit is set to 0.
        l          r   r7  r8  s       r   r   z"WindowsAArch64Mixin._page_is_dirty  sT     '*FUf5E0FG	w-e4H'x'" 	O	s   . <<r;  r3  s   @r   r?  r?    s    C D  r   r?  c                       e Zd ZdZdZe ej                         defd              Z	e ej                         defd              Z
e ej                         defd              Zy)WindowsAArch64zAs Windows (AArch64) page size is constant,
    we take advantage of the @classproperty decorator,
    because @property is dynamic and breaks static accesses
    in windows automagic.
    i   r9   c                 <    | j                   j                         dz
  S )z=Page shift for this layer, which is the page size bit length.r@   )r   re   r   s    r   r   zWindowsAArch64.page_shift  s     }}'')A--r   c                     | j                   S )z#Page size for this layer, in bytes.)_windows_fixed_page_sizer   s    r   r   zWindowsAArch64.page_size  s     +++r   c                 "    | j                   dz
   S r   r   r   s    r   r   zWindowsAArch64.page_mask  s     "##r   N)r   r   r   r!  rE  r
   r*  r+  r`   r   r   r   r   r   r   rB  rB    s      &Y.3 .  . Y,# ,  , Y$# $  $r   rB  c                   h    e Zd ZdZ G d de      Z G d de      Z G d de      Z G d d	e      Zy
)rG   z
    List of static Enum's, binding fields (high bit, low bit) of AArch64 CPU registers.
    Prevents the use of hardcoded string values by unifying everything here.
    Contains only essential mappings, needed by the framework.
    c                   &    e Zd ZdZdZ	 dZ	 dZ	 dZy)AArch64RegMap.TCR_EL1zTCR_EL1, Translation Control Register (EL1).
        The control register for stage 1 of the EL1&0 translation regime.
         [1], see D19.2.139, page 7071
        )   r%   )r'   r3   )rC   r/   )   r   N)r   r   r   r!  r^   rX   r\   rW   r   r   r   rH   rI  
  s)    	
 )m)mr   rH   c                        e Zd ZdZdZ	 dZ	 dZy)AArch64RegMap.TTBR0_EL1ap  TTBR0_EL1, Translation Table Base Register 0 (EL1)
        Holds the base address of the translation table for the initial lookup for stage 1 of the translation of an address from the lower VA range in the EL1&0 translation regime, and other information for this translation regime.         [1], see D19.2.155, page 7152
         [1], see D19.2.152, page 7139
        ?   r!   r"   r@   r   r   Nr   r   r   r!  ASIDrU   CnPr   r   r   	TTBR0_EL1rM    !    	
 9)r   rU  c                        e Zd ZdZdZ	 dZ	 dZy)AArch64RegMap.TTBR1_EL1aS  TTBR1_EL1, Translation Table Base Register 1 (EL1)
        Holds the base address of the translation table for the initial lookup for stage 1 of the translation of an address from the higher VA range in the EL1&0 stage 1 translation regime, and other information for this translation regime.
         [1], see D19.2.155, page 7152
        rN  rP  rQ  NrR  r   r   r   rI   rX  &  rV  r   rI   c                       e Zd ZdZdZy)AArch64RegMap.ID_AA64MMFR1_EL1z_ID_AA64MMFR1_EL1, AArch64 Memory Model Feature Register 1.
        [1], see D19.2.65, page 6781)r   r   N)r   r   r   r!  rv   r   r   r   rJ   rZ  3  s    	( Pr   rJ   N)	r   r   r   r!  r	   rH   rU  rI   rJ   r   r   r   rG   rG     s;    n$ nD D Q4 Qr   rG   c            	           e Zd Ze	 d
dededefd       Zededefd       Zed
dedefd       Z	e	 d
dedede
e   fd       Zy	)rZ   r   lookup_tablereverse_lookupc                     |r#|j                         D ci c]  \  }}||
 }}}|j                  |d       d k7  r||   S t        d| d|       c c}}w )NValue z+ could not be mapped inside lookup_table : )itemsrL   r   )r   r   r\  r]  kvs         r   _table_lookupz#AArch64RegFieldValues._table_lookup<  so     -9-?-?-ABTQAqDBLBE4(D0&&J<.Y 	 Cs   Ar9   c                     |dk\  S )z~
        Hardware updates to Access flag and Dirty state in translation tables.
         [1], see D19.2.65, page 6784
        r   r   )r   r   s     r   rw   z)AArch64RegFieldValues._get_feature_HAFDBSI  s     }r   c                 4    dddd}| j                  |||      S )z1
        Granule size for the TTBR0_EL1.
        r4   r   r3   )r   r@   r   rc  r   r   r]  r\  s       r   r[   z1AArch64RegFieldValues._get_ttbr0_el1_granule_sizeQ  s+     

   nEEr   c                 4    dddd}| j                  |||      S )z1
        Granule size for the TTBR1_EL1.
        r3   r4   r   )r@   r   r   rf  rg  s       r   r]   z1AArch64RegFieldValues._get_ttbr1_el1_granule_size]  s+     

   nEEr   Nr   )r   r   r   r)  r`   r.  r   rc  rw   r[   r   r]   r   r   r   rZ   rZ   ;  s    DI

'+
=A
 
     	F 	FT 	F 	F 05FF)-F	#F Fr   rZ   r   	reg_fieldr  r9   c           	          |j                   d   }|j                   d   }||z
  dz   }d|z  dz
  }| |kD  rt        d|  d| d| d      d|z  dz
  }|||z   z  }|| |z  |z  z  }|S )a  Sets the bits from high_bit to low_bit (inclusive) in "reg_value" to the given value.
    Allows to manipulate the bits at arbitrary positions inside a register.

    Args:
        value: The value to set in the specified bit range.
        reg_field: The register field to update, inside the register.
        reg_value: The register value to modify (default is 0).

    Returns:
        The modified integer with the specified bits set.

    Raises:
        ValueError: If the value is too large to fit in the specified bit range.
    r@   r   r_  z is too large to fit in z bits (max value is z).)r   
ValueError)r   ri  r  r   r   num_bits	max_valuer   s           r   set_reg_bitsrn  l  s     q!Hooa G !A%H h!#I yUG3H:=QR[Q\\^_
 	

 MQD 48#$$I %$,8++Ir   )r   )(loggingr*  r"  r   rr   typingr   r   r   r   r   r   enumr	   volatility3r
   volatility3.frameworkr   r   #volatility3.framework.configurationr   volatility3.framework.layersr   .volatility3.framework.interfaces.configurationr   	getLoggerr   r   LayerExceptionr   LinearlyMappedLayerr   r5  r=  r?  rB  rG   rZ   r`   rn  r   r   r   <module>rz     s   
      = =  % 8 < / D			8	$.	z00 	C

f(( C

L (	$g 	' ,$(' $8 <5Q 5Qp.F .Fb' ' ' 'S 'r   