Source code for libdebug.utils.debugging_utils
#
# This file is part of libdebug Python library (https://github.com/libdebug/libdebug).
# Copyright (c) 2023-2024 Gabriele Digregorio, Roberto Alessandro Bertolini. All rights reserved.
# Licensed under the MIT license. See LICENSE file in the project root for details.
#
from libdebug.data.memory_map import MemoryMap
from libdebug.liblog import liblog
from libdebug.utils.elf_utils import is_pie, resolve_address, resolve_symbol
[docs]
def check_absolute_address(address: int, maps: list[MemoryMap]) -> bool:
    """Checks if the specified address is an absolute address.
    Returns:
        bool: True if the specified address is an absolute address, False otherwise.
    """
    return any(vmap.start <= address < vmap.end for vmap in maps) 
[docs]
def normalize_and_validate_address(address: int, maps: list[MemoryMap]) -> int:
    """Normalizes and validates the specified address.
    Returns:
        int: The normalized address.
    Throws:
        ValueError: If the specified address does not belong to any memory map.
    """
    if address < maps[0].start:
        # The address is lower than the base address of the lowest map. Suppose it is a relative address for a PIE binary.
        address += maps[0].start
    for vmap in maps:
        if vmap.start <= address < vmap.end:
            return address
    raise ValueError(f"Address {hex(address)} does not belong to any memory map.") 
[docs]
def resolve_symbol_in_maps(symbol: str, maps: list[MemoryMap]) -> int:
    """Returns the address of the specified symbol in the specified memory maps.
    Args:
        symbol (str): The symbol whose address should be returned.
        maps (list[MemoryMap]): The memory maps.
    Returns:
        int: The address of the specified symbol in the specified memory maps.
    Throws:
        ValueError: If the specified symbol does not belong to any memory map.
    """
    mapped_files = {}
    if "+" in symbol:
        symbol, offset_str = symbol.split("+")
        offset = int(offset_str, 16)
    else:
        offset = 0
    for vmap in maps:
        if vmap.backing_file and vmap.backing_file not in mapped_files and vmap.backing_file[0] != "[":
            mapped_files[vmap.backing_file] = vmap.start
    for file, base_address in mapped_files.items():
        try:
            address = resolve_symbol(file, symbol)
            if is_pie(file):
                address += base_address
            return address + offset
        except OSError as e:
            liblog.debugger(f"Error while resolving symbol {symbol} in {file}: {e}")
        except ValueError:
            pass
    raise ValueError(f"Symbol {symbol} not found in the specified mapped file. Please specify a valid symbol.") 
[docs]
def resolve_address_in_maps(address: int, maps: list[MemoryMap]) -> str:
    """Returns the symbol corresponding to the specified address in the specified memory maps.
    Args:
        address (int): The address whose symbol should be returned.
        maps (list[MemoryMap]): The memory maps.
    Returns:
        str: The symbol corresponding to the specified address in the specified memory maps.
    Throws:
        ValueError: If the specified address does not belong to any memory map.
    """
    mapped_files = {}
    for vmap in maps:
        file = vmap.backing_file
        if not file or file[0] == "[":
            continue
        if file not in mapped_files:
            mapped_files[file] = (vmap.start, vmap.end)
        else:
            mapped_files[file] = (mapped_files[file][0], vmap.end)
    for file, (base_address, top_address) in mapped_files.items():
        # Check if the address is in the range of the current section
        if address < base_address or address >= top_address:
            continue
        try:
            return resolve_address(file, address - base_address) if is_pie(file) else resolve_address(file, address)
        except OSError as e:
            liblog.debugger(f"Error while resolving address {hex(address)} in {file}: {e}")
        except ValueError:
            pass
    return hex(address)