scripts/gdb/linux/pgtable.py

Source file repositories/reference/linux-study-clean/scripts/gdb/linux/pgtable.py

File Facts

System
Linux kernel
Corpus path
scripts/gdb/linux/pgtable.py
Extension
.py
Size
10161 bytes
Lines
221
Domain
Support Tooling And Documentation
Bucket
scripts
Inferred role
Support Tooling And Documentation: scripts
Status
atlas-only

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

# SPDX-License-Identifier: GPL-2.0-only
#
# gdb helper commands and functions for Linux kernel debugging
#
#  routines to introspect page table
#
# Authors:
#  Dmitrii Bundin <dmitrii.bundin.a@gmail.com>
#

import gdb

from linux import utils

PHYSICAL_ADDRESS_MASK = gdb.parse_and_eval('0xfffffffffffff')


def page_mask(level=1):
    # 4KB
    if level == 1:
        return gdb.parse_and_eval('(u64) ~0xfff')
    # 2MB
    elif level == 2:
        return gdb.parse_and_eval('(u64) ~0x1fffff')
    # 1GB
    elif level == 3:
        return gdb.parse_and_eval('(u64) ~0x3fffffff')
    else:
        raise Exception(f'Unknown page level: {level}')


def _page_offset_base():
    pob_symbol = gdb.lookup_global_symbol('page_offset_base')
    pob = pob_symbol.name
    return gdb.parse_and_eval(pob)


def is_bit_defined_tupled(data, offset):
    return offset, bool(data >> offset & 1)

def content_tupled(data, bit_start, bit_end):
    return (bit_start, bit_end), data >> bit_start & ((1 << (1 + bit_end - bit_start)) - 1)

def entry_va(level, phys_addr, translating_va):
        def start_bit(level):
            if level == 5:
                return 48
            elif level == 4:
                return 39
            elif level == 3:
                return 30
            elif level == 2:
                return 21
            elif level == 1:
                return 12
            else:
                raise Exception(f'Unknown level {level}')

        entry_offset =  ((translating_va >> start_bit(level)) & 511) * 8
        entry_va = _page_offset_base() + phys_addr + entry_offset
        return entry_va

class Cr3():
    def __init__(self, cr3, page_levels):
        self.cr3 = cr3
        self.page_levels = page_levels
        self.page_level_write_through = is_bit_defined_tupled(cr3, 3)
        self.page_level_cache_disabled = is_bit_defined_tupled(cr3, 4)
        self.next_entry_physical_address = cr3 & PHYSICAL_ADDRESS_MASK & page_mask()

Annotation

Implementation Notes