~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/scripts/gdb/linux/pgtable.py

Version: ~ [ linux-6.12-rc7 ] ~ [ linux-6.11.7 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.60 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.116 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.171 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.229 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.285 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.323 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.12 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

Diff markup

Differences between /scripts/gdb/linux/pgtable.py (Version linux-6.12-rc7) and /scripts/gdb/linux/pgtable.py (Version linux-6.11.7)


  1 # SPDX-License-Identifier: GPL-2.0-only             1 # SPDX-License-Identifier: GPL-2.0-only
  2 #                                                   2 #
  3 # gdb helper commands and functions for Linux       3 # gdb helper commands and functions for Linux kernel debugging
  4 #                                                   4 #
  5 #  routines to introspect page table                5 #  routines to introspect page table
  6 #                                                   6 #
  7 # Authors:                                          7 # Authors:
  8 #  Dmitrii Bundin <dmitrii.bundin.a@gmail.com>       8 #  Dmitrii Bundin <dmitrii.bundin.a@gmail.com>
  9 #                                                   9 #
 10                                                    10 
 11 import gdb                                         11 import gdb
 12                                                    12 
 13 from linux import utils                            13 from linux import utils
 14                                                    14 
 15 PHYSICAL_ADDRESS_MASK = gdb.parse_and_eval('0x     15 PHYSICAL_ADDRESS_MASK = gdb.parse_and_eval('0xfffffffffffff')
 16                                                    16 
 17                                                    17 
 18 def page_mask(level=1):                            18 def page_mask(level=1):
 19     # 4KB                                          19     # 4KB
 20     if level == 1:                                 20     if level == 1:
 21         return gdb.parse_and_eval('(u64) ~0xff     21         return gdb.parse_and_eval('(u64) ~0xfff')
 22     # 2MB                                          22     # 2MB
 23     elif level == 2:                               23     elif level == 2:
 24         return gdb.parse_and_eval('(u64) ~0x1f     24         return gdb.parse_and_eval('(u64) ~0x1fffff')
 25     # 1GB                                          25     # 1GB
 26     elif level == 3:                               26     elif level == 3:
 27         return gdb.parse_and_eval('(u64) ~0x3f     27         return gdb.parse_and_eval('(u64) ~0x3fffffff')
 28     else:                                          28     else:
 29         raise Exception(f'Unknown page level:      29         raise Exception(f'Unknown page level: {level}')
 30                                                    30 
 31                                                    31 
 32 #page_offset_base in case CONFIG_DYNAMIC_MEMOR     32 #page_offset_base in case CONFIG_DYNAMIC_MEMORY_LAYOUT is disabled
 33 POB_NO_DYNAMIC_MEM_LAYOUT = '0xffff88800000000     33 POB_NO_DYNAMIC_MEM_LAYOUT = '0xffff888000000000'
 34 def _page_offset_base():                           34 def _page_offset_base():
 35     pob_symbol = gdb.lookup_global_symbol('pag     35     pob_symbol = gdb.lookup_global_symbol('page_offset_base')
 36     pob = pob_symbol.name if pob_symbol else P     36     pob = pob_symbol.name if pob_symbol else POB_NO_DYNAMIC_MEM_LAYOUT
 37     return gdb.parse_and_eval(pob)                 37     return gdb.parse_and_eval(pob)
 38                                                    38 
 39                                                    39 
 40 def is_bit_defined_tupled(data, offset):           40 def is_bit_defined_tupled(data, offset):
 41     return offset, bool(data >> offset & 1)        41     return offset, bool(data >> offset & 1)
 42                                                    42 
 43 def content_tupled(data, bit_start, bit_end):      43 def content_tupled(data, bit_start, bit_end):
 44     return (bit_start, bit_end), data >> bit_s     44     return (bit_start, bit_end), data >> bit_start & ((1 << (1 + bit_end - bit_start)) - 1)
 45                                                    45 
 46 def entry_va(level, phys_addr, translating_va)     46 def entry_va(level, phys_addr, translating_va):
 47         def start_bit(level):                      47         def start_bit(level):
 48             if level == 5:                         48             if level == 5:
 49                 return 48                          49                 return 48
 50             elif level == 4:                       50             elif level == 4:
 51                 return 39                          51                 return 39
 52             elif level == 3:                       52             elif level == 3:
 53                 return 30                          53                 return 30
 54             elif level == 2:                       54             elif level == 2:
 55                 return 21                          55                 return 21
 56             elif level == 1:                       56             elif level == 1:
 57                 return 12                          57                 return 12
 58             else:                                  58             else:
 59                 raise Exception(f'Unknown leve     59                 raise Exception(f'Unknown level {level}')
 60                                                    60 
 61         entry_offset =  ((translating_va >> st     61         entry_offset =  ((translating_va >> start_bit(level)) & 511) * 8
 62         entry_va = _page_offset_base() + phys_     62         entry_va = _page_offset_base() + phys_addr + entry_offset
 63         return entry_va                            63         return entry_va
 64                                                    64 
 65 class Cr3():                                       65 class Cr3():
 66     def __init__(self, cr3, page_levels):          66     def __init__(self, cr3, page_levels):
 67         self.cr3 = cr3                             67         self.cr3 = cr3
 68         self.page_levels = page_levels             68         self.page_levels = page_levels
 69         self.page_level_write_through = is_bit     69         self.page_level_write_through = is_bit_defined_tupled(cr3, 3)
 70         self.page_level_cache_disabled = is_bi     70         self.page_level_cache_disabled = is_bit_defined_tupled(cr3, 4)
 71         self.next_entry_physical_address = cr3     71         self.next_entry_physical_address = cr3 & PHYSICAL_ADDRESS_MASK & page_mask()
 72                                                    72 
 73     def next_entry(self, va):                      73     def next_entry(self, va):
 74         next_level = self.page_levels              74         next_level = self.page_levels
 75         return PageHierarchyEntry(entry_va(nex     75         return PageHierarchyEntry(entry_va(next_level, self.next_entry_physical_address, va), next_level)
 76                                                    76 
 77     def mk_string(self):                           77     def mk_string(self):
 78             return f"""\                           78             return f"""\
 79 cr3:                                               79 cr3:
 80     {'cr3 binary data': <30} {hex(self.cr3)}       80     {'cr3 binary data': <30} {hex(self.cr3)}
 81     {'next entry physical address': <30} {hex(     81     {'next entry physical address': <30} {hex(self.next_entry_physical_address)}
 82     ---                                            82     ---
 83     {'bit' : <4} {self.page_level_write_throug     83     {'bit' : <4} {self.page_level_write_through[0]: <10} {'page level write through': <30} {self.page_level_write_through[1]}
 84     {'bit' : <4} {self.page_level_cache_disabl     84     {'bit' : <4} {self.page_level_cache_disabled[0]: <10} {'page level cache disabled': <30} {self.page_level_cache_disabled[1]}
 85 """                                                85 """
 86                                                    86 
 87                                                    87 
 88 class PageHierarchyEntry():                        88 class PageHierarchyEntry():
 89     def __init__(self, address, level):            89     def __init__(self, address, level):
 90         data = int.from_bytes(                     90         data = int.from_bytes(
 91             memoryview(gdb.selected_inferior()     91             memoryview(gdb.selected_inferior().read_memory(address, 8)),
 92             "little"                               92             "little"
 93         )                                          93         )
 94         if level == 1:                             94         if level == 1:
 95             self.is_page = True                    95             self.is_page = True
 96             self.entry_present = is_bit_define     96             self.entry_present = is_bit_defined_tupled(data, 0)
 97             self.read_write = is_bit_defined_t     97             self.read_write = is_bit_defined_tupled(data, 1)
 98             self.user_access_allowed = is_bit_     98             self.user_access_allowed = is_bit_defined_tupled(data, 2)
 99             self.page_level_write_through = is     99             self.page_level_write_through = is_bit_defined_tupled(data, 3)
100             self.page_level_cache_disabled = i    100             self.page_level_cache_disabled = is_bit_defined_tupled(data, 4)
101             self.entry_was_accessed = is_bit_d    101             self.entry_was_accessed = is_bit_defined_tupled(data, 5)
102             self.dirty = is_bit_defined_tupled    102             self.dirty = is_bit_defined_tupled(data, 6)
103             self.pat = is_bit_defined_tupled(d    103             self.pat = is_bit_defined_tupled(data, 7)
104             self.global_translation = is_bit_d    104             self.global_translation = is_bit_defined_tupled(data, 8)
105             self.page_physical_address = data     105             self.page_physical_address = data & PHYSICAL_ADDRESS_MASK & page_mask(level)
106             self.next_entry_physical_address =    106             self.next_entry_physical_address = None
107             self.hlat_restart_with_ordinary =     107             self.hlat_restart_with_ordinary = is_bit_defined_tupled(data, 11)
108             self.protection_key = content_tupl    108             self.protection_key = content_tupled(data, 59, 62)
109             self.executed_disable = is_bit_def    109             self.executed_disable = is_bit_defined_tupled(data, 63)
110         else:                                     110         else:
111             page_size = is_bit_defined_tupled(    111             page_size = is_bit_defined_tupled(data, 7)
112             page_size_bit = page_size[1]          112             page_size_bit = page_size[1]
113             self.is_page = page_size_bit          113             self.is_page = page_size_bit
114             self.entry_present = is_bit_define    114             self.entry_present = is_bit_defined_tupled(data, 0)
115             self.read_write = is_bit_defined_t    115             self.read_write = is_bit_defined_tupled(data, 1)
116             self.user_access_allowed = is_bit_    116             self.user_access_allowed = is_bit_defined_tupled(data, 2)
117             self.page_level_write_through = is    117             self.page_level_write_through = is_bit_defined_tupled(data, 3)
118             self.page_level_cache_disabled = i    118             self.page_level_cache_disabled = is_bit_defined_tupled(data, 4)
119             self.entry_was_accessed = is_bit_d    119             self.entry_was_accessed = is_bit_defined_tupled(data, 5)
120             self.page_size = page_size            120             self.page_size = page_size
121             self.dirty = is_bit_defined_tupled    121             self.dirty = is_bit_defined_tupled(
122                 data, 6) if page_size_bit else    122                 data, 6) if page_size_bit else None
123             self.global_translation = is_bit_d    123             self.global_translation = is_bit_defined_tupled(
124                 data, 8) if page_size_bit else    124                 data, 8) if page_size_bit else None
125             self.pat = is_bit_defined_tupled(     125             self.pat = is_bit_defined_tupled(
126                 data, 12) if page_size_bit els    126                 data, 12) if page_size_bit else None
127             self.page_physical_address = data     127             self.page_physical_address = data & PHYSICAL_ADDRESS_MASK & page_mask(level) if page_size_bit else None
128             self.next_entry_physical_address =    128             self.next_entry_physical_address = None if page_size_bit else data & PHYSICAL_ADDRESS_MASK & page_mask()
129             self.hlat_restart_with_ordinary =     129             self.hlat_restart_with_ordinary = is_bit_defined_tupled(data, 11)
130             self.protection_key = content_tupl    130             self.protection_key = content_tupled(data, 59, 62) if page_size_bit else None
131             self.executed_disable = is_bit_def    131             self.executed_disable = is_bit_defined_tupled(data, 63)
132         self.address = address                    132         self.address = address
133         self.page_entry_binary_data = data        133         self.page_entry_binary_data = data
134         self.page_hierarchy_level = level         134         self.page_hierarchy_level = level
135                                                   135 
136     def next_entry(self, va):                     136     def next_entry(self, va):
137         if self.is_page or not self.entry_pres    137         if self.is_page or not self.entry_present[1]:
138             return None                           138             return None
139                                                   139 
140         next_level = self.page_hierarchy_level    140         next_level = self.page_hierarchy_level - 1
141         return PageHierarchyEntry(entry_va(nex    141         return PageHierarchyEntry(entry_va(next_level, self.next_entry_physical_address, va), next_level)
142                                                   142 
143                                                   143 
144     def mk_string(self):                          144     def mk_string(self):
145         if not self.entry_present[1]:             145         if not self.entry_present[1]:
146             return f"""\                          146             return f"""\
147 level {self.page_hierarchy_level}:                147 level {self.page_hierarchy_level}:
148     {'entry address': <30} {hex(self.address)}    148     {'entry address': <30} {hex(self.address)}
149     {'page entry binary data': <30} {hex(self.    149     {'page entry binary data': <30} {hex(self.page_entry_binary_data)}
150     ---                                           150     ---
151     PAGE ENTRY IS NOT PRESENT!                    151     PAGE ENTRY IS NOT PRESENT!
152 """                                               152 """
153         elif self.is_page:                        153         elif self.is_page:
154             def page_size_line(ps_bit, ps, lev    154             def page_size_line(ps_bit, ps, level):
155                 return "" if level == 1 else f    155                 return "" if level == 1 else f"{'bit': <3} {ps_bit: <5} {'page size': <30} {ps}"
156                                                   156 
157             return f"""\                          157             return f"""\
158 level {self.page_hierarchy_level}:                158 level {self.page_hierarchy_level}:
159     {'entry address': <30} {hex(self.address)}    159     {'entry address': <30} {hex(self.address)}
160     {'page entry binary data': <30} {hex(self.    160     {'page entry binary data': <30} {hex(self.page_entry_binary_data)}
161     {'page size': <30} {'1GB' if self.page_hie    161     {'page size': <30} {'1GB' if self.page_hierarchy_level == 3 else '2MB' if self.page_hierarchy_level == 2 else '4KB' if self.page_hierarchy_level == 1 else 'Unknown page size for level:' + self.page_hierarchy_level}
162     {'page physical address': <30} {hex(self.p    162     {'page physical address': <30} {hex(self.page_physical_address)}
163     ---                                           163     ---
164     {'bit': <4} {self.entry_present[0]: <10} {    164     {'bit': <4} {self.entry_present[0]: <10} {'entry present': <30} {self.entry_present[1]}
165     {'bit': <4} {self.read_write[0]: <10} {'re    165     {'bit': <4} {self.read_write[0]: <10} {'read/write access allowed': <30} {self.read_write[1]}
166     {'bit': <4} {self.user_access_allowed[0]:     166     {'bit': <4} {self.user_access_allowed[0]: <10} {'user access allowed': <30} {self.user_access_allowed[1]}
167     {'bit': <4} {self.page_level_write_through    167     {'bit': <4} {self.page_level_write_through[0]: <10} {'page level write through': <30} {self.page_level_write_through[1]}
168     {'bit': <4} {self.page_level_cache_disable    168     {'bit': <4} {self.page_level_cache_disabled[0]: <10} {'page level cache disabled': <30} {self.page_level_cache_disabled[1]}
169     {'bit': <4} {self.entry_was_accessed[0]: <    169     {'bit': <4} {self.entry_was_accessed[0]: <10} {'entry has been accessed': <30} {self.entry_was_accessed[1]}
170     {"" if self.page_hierarchy_level == 1 else    170     {"" if self.page_hierarchy_level == 1 else f"{'bit': <4} {self.page_size[0]: <10} {'page size': <30} {self.page_size[1]}"}
171     {'bit': <4} {self.dirty[0]: <10} {'page di    171     {'bit': <4} {self.dirty[0]: <10} {'page dirty': <30} {self.dirty[1]}
172     {'bit': <4} {self.global_translation[0]: <    172     {'bit': <4} {self.global_translation[0]: <10} {'global translation': <30} {self.global_translation[1]}
173     {'bit': <4} {self.hlat_restart_with_ordina    173     {'bit': <4} {self.hlat_restart_with_ordinary[0]: <10} {'restart to ordinary': <30} {self.hlat_restart_with_ordinary[1]}
174     {'bit': <4} {self.pat[0]: <10} {'pat': <30    174     {'bit': <4} {self.pat[0]: <10} {'pat': <30} {self.pat[1]}
175     {'bits': <4} {str(self.protection_key[0]):    175     {'bits': <4} {str(self.protection_key[0]): <10} {'protection key': <30} {self.protection_key[1]}
176     {'bit': <4} {self.executed_disable[0]: <10    176     {'bit': <4} {self.executed_disable[0]: <10} {'execute disable': <30} {self.executed_disable[1]}
177 """                                               177 """
178         else:                                     178         else:
179             return f"""\                          179             return f"""\
180 level {self.page_hierarchy_level}:                180 level {self.page_hierarchy_level}:
181     {'entry address': <30} {hex(self.address)}    181     {'entry address': <30} {hex(self.address)}
182     {'page entry binary data': <30} {hex(self.    182     {'page entry binary data': <30} {hex(self.page_entry_binary_data)}
183     {'next entry physical address': <30} {hex(    183     {'next entry physical address': <30} {hex(self.next_entry_physical_address)}
184     ---                                           184     ---
185     {'bit': <4} {self.entry_present[0]: <10} {    185     {'bit': <4} {self.entry_present[0]: <10} {'entry present': <30} {self.entry_present[1]}
186     {'bit': <4} {self.read_write[0]: <10} {'re    186     {'bit': <4} {self.read_write[0]: <10} {'read/write access allowed': <30} {self.read_write[1]}
187     {'bit': <4} {self.user_access_allowed[0]:     187     {'bit': <4} {self.user_access_allowed[0]: <10} {'user access allowed': <30} {self.user_access_allowed[1]}
188     {'bit': <4} {self.page_level_write_through    188     {'bit': <4} {self.page_level_write_through[0]: <10} {'page level write through': <30} {self.page_level_write_through[1]}
189     {'bit': <4} {self.page_level_cache_disable    189     {'bit': <4} {self.page_level_cache_disabled[0]: <10} {'page level cache disabled': <30} {self.page_level_cache_disabled[1]}
190     {'bit': <4} {self.entry_was_accessed[0]: <    190     {'bit': <4} {self.entry_was_accessed[0]: <10} {'entry has been accessed': <30} {self.entry_was_accessed[1]}
191     {'bit': <4} {self.page_size[0]: <10} {'pag    191     {'bit': <4} {self.page_size[0]: <10} {'page size': <30} {self.page_size[1]}
192     {'bit': <4} {self.hlat_restart_with_ordina    192     {'bit': <4} {self.hlat_restart_with_ordinary[0]: <10} {'restart to ordinary': <30} {self.hlat_restart_with_ordinary[1]}
193     {'bit': <4} {self.executed_disable[0]: <10    193     {'bit': <4} {self.executed_disable[0]: <10} {'execute disable': <30} {self.executed_disable[1]}
194 """                                               194 """
195                                                   195 
196                                                   196 
197 class TranslateVM(gdb.Command):                   197 class TranslateVM(gdb.Command):
198     """Prints the entire paging structure used    198     """Prints the entire paging structure used to translate a given virtual address.
199                                                   199 
200 Having an address space of the currently execu    200 Having an address space of the currently executed process translates the virtual address
201 and prints detailed information of all paging     201 and prints detailed information of all paging structure levels used for the transaltion.
202 Currently supported arch: x86"""                  202 Currently supported arch: x86"""
203                                                   203 
204     def __init__(self):                           204     def __init__(self):
205         super(TranslateVM, self).__init__('tra    205         super(TranslateVM, self).__init__('translate-vm', gdb.COMMAND_USER)
206                                                   206 
207     def invoke(self, arg, from_tty):              207     def invoke(self, arg, from_tty):
208         if utils.is_target_arch("x86"):           208         if utils.is_target_arch("x86"):
209             vm_address = gdb.parse_and_eval(f'    209             vm_address = gdb.parse_and_eval(f'{arg}')
210             cr3_data = gdb.parse_and_eval('$cr    210             cr3_data = gdb.parse_and_eval('$cr3')
211             cr4 = gdb.parse_and_eval('$cr4')      211             cr4 = gdb.parse_and_eval('$cr4')
212             page_levels = 5 if cr4 & (1 << 12)    212             page_levels = 5 if cr4 & (1 << 12) else 4
213             page_entry = Cr3(cr3_data, page_le    213             page_entry = Cr3(cr3_data, page_levels)
214             while page_entry:                     214             while page_entry:
215                 gdb.write(page_entry.mk_string    215                 gdb.write(page_entry.mk_string())
216                 page_entry = page_entry.next_e    216                 page_entry = page_entry.next_entry(vm_address)
217         else:                                     217         else:
218             gdb.GdbError("Virtual address tran    218             gdb.GdbError("Virtual address translation is not"
219                          "supported for this a    219                          "supported for this arch")
220                                                   220 
221                                                   221 
222 TranslateVM()                                     222 TranslateVM()
                                                      

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php