GDB Refactor [4/N]: Split abi into lib/ and gdblib/ (#1120)

* Remove tips.py

* Split android.py into lib/ and gdb/

* Split abi.py into lib/ and gdblib/
This commit is contained in:
Gulshan Singh 2022-09-05 10:58:57 -07:00 committed by GitHub
parent 36aa539f62
commit 692c4b82f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 85 additions and 80 deletions

View File

@ -6,7 +6,6 @@ import gdb
from capstone import CS_GRP_CALL from capstone import CS_GRP_CALL
from capstone import CS_GRP_INT from capstone import CS_GRP_INT
import pwndbg.abi
import pwndbg.chain import pwndbg.chain
import pwndbg.color.nearpc as N import pwndbg.color.nearpc as N
import pwndbg.constants import pwndbg.constants
@ -14,6 +13,7 @@ import pwndbg.disasm
import pwndbg.gdblib.arch import pwndbg.gdblib.arch
import pwndbg.gdblib.typeinfo import pwndbg.gdblib.typeinfo
import pwndbg.ida import pwndbg.ida
import pwndbg.lib.abi
import pwndbg.lib.funcparser import pwndbg.lib.funcparser
import pwndbg.lib.functions import pwndbg.lib.functions
import pwndbg.memory import pwndbg.memory
@ -52,7 +52,7 @@ def get_syscall_name(instruction):
if CS_GRP_INT not in instruction.groups: if CS_GRP_INT not in instruction.groups:
return None return None
syscall_register = pwndbg.abi.ABI.syscall().syscall_register syscall_register = pwndbg.lib.abi.ABI.syscall().syscall_register
# If we are on x86/x64, return no syscall name for other instructions than syscall and int 0x80 # If we are on x86/x64, return no syscall name for other instructions than syscall and int 0x80
if syscall_register in ("eax", "rax"): if syscall_register in ("eax", "rax"):
@ -81,7 +81,7 @@ def get(instruction):
if CS_GRP_CALL in instruction.groups: if CS_GRP_CALL in instruction.groups:
try: try:
abi = pwndbg.abi.ABI.default() abi = pwndbg.lib.abi.ABI.default()
except KeyError: except KeyError:
return [] return []
@ -100,7 +100,7 @@ def get(instruction):
elif CS_GRP_INT in instruction.groups: elif CS_GRP_INT in instruction.groups:
# Get the syscall number and name # Get the syscall number and name
name = get_syscall_name(instruction) name = get_syscall_name(instruction)
abi = pwndbg.abi.ABI.syscall() abi = pwndbg.lib.abi.ABI.syscall()
target = None target = None
if name is None: if name is None:
@ -162,7 +162,7 @@ def get(instruction):
def argname(n, abi=None): def argname(n, abi=None):
abi = abi or pwndbg.abi.ABI.default() abi = abi or pwndbg.lib.abi.ABI.default()
regs = abi.register_arguments regs = abi.register_arguments
if n < len(regs): if n < len(regs):
@ -177,7 +177,7 @@ def argument(n, abi=None):
instruction. instruction.
Works only for ABIs that use registers for arguments. Works only for ABIs that use registers for arguments.
""" """
abi = abi or pwndbg.abi.ABI.default() abi = abi or pwndbg.lib.abi.ABI.default()
regs = abi.register_arguments regs = abi.register_arguments
if n < len(regs): if n < len(regs):
@ -195,7 +195,7 @@ def arguments(abi=None):
Yields (arg_name, arg_value) tuples for arguments from a given ABI. Yields (arg_name, arg_value) tuples for arguments from a given ABI.
Works only for ABIs that use registers for arguments. Works only for ABIs that use registers for arguments.
""" """
abi = abi or pwndbg.abi.ABI.default() abi = abi or pwndbg.lib.abi.ABI.default()
regs = abi.register_arguments regs = abi.register_arguments
for i in range(len(regs)): for i in range(len(regs)):

View File

@ -1,8 +1,8 @@
import gdb import gdb
import pwndbg.abi
import pwndbg.gdblib.arch import pwndbg.gdblib.arch
import pwndbg.gdblib.events import pwndbg.gdblib.events
import pwndbg.lib.abi
import pwndbg.memory import pwndbg.memory
import pwndbg.regs import pwndbg.regs
@ -20,7 +20,7 @@ envc = None
@pwndbg.gdblib.events.start @pwndbg.gdblib.events.start
@pwndbg.abi.LinuxOnly() @pwndbg.gdblib.abi.LinuxOnly()
def update(): def update():
global argc global argc
global argv global argv

View File

@ -4,7 +4,7 @@ import sys
import gdb import gdb
import pwndbg.abi import pwndbg.gdblib.abi
import pwndbg.gdblib.arch import pwndbg.gdblib.arch
import pwndbg.gdblib.events import pwndbg.gdblib.events
import pwndbg.gdblib.typeinfo import pwndbg.gdblib.typeinfo
@ -146,7 +146,7 @@ def find_stack_boundary(addr):
def walk_stack(): def walk_stack():
if not pwndbg.abi.linux: if not pwndbg.gdblib.abi.linux:
return None return None
if pwndbg.qemu.is_qemu_kernel(): if pwndbg.qemu.is_qemu_kernel():
return None return None

View File

@ -1,10 +1,10 @@
import gdb import gdb
import pwndbg.abi
import pwndbg.color.chain as C import pwndbg.color.chain as C
import pwndbg.color.memory as M import pwndbg.color.memory as M
import pwndbg.color.theme as theme import pwndbg.color.theme as theme
import pwndbg.enhance import pwndbg.enhance
import pwndbg.gdblib.abi
import pwndbg.gdblib.typeinfo import pwndbg.gdblib.typeinfo
import pwndbg.memory import pwndbg.memory
import pwndbg.symbol import pwndbg.symbol
@ -56,7 +56,7 @@ def get(
# Avoid redundant dereferences in bare metal mode by checking # Avoid redundant dereferences in bare metal mode by checking
# if address is in any of vmmap pages # if address is in any of vmmap pages
if not pwndbg.abi.linux and not pwndbg.vmmap.find(address): if not pwndbg.gdblib.abi.linux and not pwndbg.vmmap.find(address):
break break
next_address = int(pwndbg.memory.poi(pwndbg.gdblib.typeinfo.ppvoid, address)) next_address = int(pwndbg.memory.poi(pwndbg.gdblib.typeinfo.ppvoid, address))

View File

@ -15,9 +15,9 @@ import gdb
from elftools.elf.constants import SH_FLAGS from elftools.elf.constants import SH_FLAGS
from elftools.elf.elffile import ELFFile from elftools.elf.elffile import ELFFile
import pwndbg.abi
import pwndbg.auxv import pwndbg.auxv
import pwndbg.elftypes import pwndbg.elftypes
import pwndbg.gdblib.abi
import pwndbg.gdblib.arch import pwndbg.gdblib.arch
import pwndbg.gdblib.events import pwndbg.gdblib.events
import pwndbg.info import pwndbg.info
@ -266,7 +266,7 @@ def get_ehdr(pointer):
if base is None: if base is None:
# For non linux ABI, the ELF header may not exist at all # For non linux ABI, the ELF header may not exist at all
if pwndbg.abi.linux: if pwndbg.gdblib.abi.linux:
print("ERROR: Could not find ELF base!") print("ERROR: Could not find ELF base!")
return None, None return None, None

67
pwndbg/gdblib/abi.py Normal file
View File

@ -0,0 +1,67 @@
import functools
import gdb
import pwndbg.color.message as M
import pwndbg.gdblib.events
abi = None
linux = False
# TODO: Maybe move this to hooks.py?
@pwndbg.gdblib.events.start
def update():
global abi
global linux
# Detect current ABI of client side by 'show osabi'
#
# Examples of strings returned by `show osabi`:
# 'The current OS ABI is "auto" (currently "GNU/Linux").\nThe default OS ABI is "GNU/Linux".\n'
# 'The current OS ABI is "GNU/Linux".\nThe default OS ABI is "GNU/Linux".\n'
# 'El actual SO ABI es «auto» (actualmente «GNU/Linux»).\nEl SO ABI predeterminado es «GNU/Linux».\n'
# 'The current OS ABI is "auto" (currently "none")'
#
# As you can see, there might be GDBs with different language versions
# and so we have to support it there too.
# Lets assume and hope that `current osabi` is returned in first line in all languages...
abi = gdb.execute("show osabi", to_string=True).split("\n")[0]
# Currently we support those osabis:
# 'GNU/Linux': linux
# 'none': bare metal
linux = "GNU/Linux" in abi
if not linux:
msg = M.warn(
"The bare metal debugging is enabled since gdb's osabi is '%s' which is not 'GNU/Linux'.\n"
"Ex. the page resolving and memory de-referencing ONLY works on known pages.\n"
"This option is based on gdb client compile arguments (by default) and will be corrected if you load an ELF with a '.note.ABI-tag' section.\n"
"If you are debugging a program that runs on the Linux ABI, please select the correct gdb client."
% abi
)
print(msg)
def LinuxOnly(default=None):
"""Create a decorator that the function will be called when ABI is Linux.
Otherwise, return `default`.
"""
def decorator(func):
@functools.wraps(func)
def caller(*args, **kwargs):
if linux:
return func(*args, **kwargs)
else:
return default
return caller
return decorator
# Update when starting the gdb to show warning message for non-Linux ABI user.
update()

View File

@ -1,8 +1,3 @@
import functools
import gdb
import pwndbg.color.message as M
import pwndbg.gdblib.arch import pwndbg.gdblib.arch
@ -114,60 +109,3 @@ linux_arm_sigreturn = SigreturnABI(["r7"], 4, 0)
linux_i386_srop = ABI(["eax"], 4, 0) linux_i386_srop = ABI(["eax"], 4, 0)
linux_amd64_srop = ABI(["rax"], 4, 0) linux_amd64_srop = ABI(["rax"], 4, 0)
linux_arm_srop = ABI(["r7"], 4, 0) linux_arm_srop = ABI(["r7"], 4, 0)
@pwndbg.gdblib.events.start
def update():
global abi
global linux
# Detect current ABI of client side by 'show osabi'
#
# Examples of strings returned by `show osabi`:
# 'The current OS ABI is "auto" (currently "GNU/Linux").\nThe default OS ABI is "GNU/Linux".\n'
# 'The current OS ABI is "GNU/Linux".\nThe default OS ABI is "GNU/Linux".\n'
# 'El actual SO ABI es «auto» (actualmente «GNU/Linux»).\nEl SO ABI predeterminado es «GNU/Linux».\n'
# 'The current OS ABI is "auto" (currently "none")'
#
# As you can see, there might be GDBs with different language versions
# and so we have to support it there too.
# Lets assume and hope that `current osabi` is returned in first line in all languages...
abi = gdb.execute("show osabi", to_string=True).split("\n")[0]
# Currently we support those osabis:
# 'GNU/Linux': linux
# 'none': bare metal
linux = "GNU/Linux" in abi
if not linux:
msg = M.warn(
"The bare metal debugging is enabled since gdb's osabi is '%s' which is not 'GNU/Linux'.\n"
"Ex. the page resolving and memory de-referencing ONLY works on known pages.\n"
"This option is based on gdb client compile arguments (by default) and will be corrected if you load an ELF with a '.note.ABI-tag' section.\n"
"If you are debugging a program that runs on the Linux ABI, please select the correct gdb client."
% abi
)
print(msg)
def LinuxOnly(default=None):
"""Create a decorator that the function will be called when ABI is Linux.
Otherwise, return `default`.
"""
def decorator(func):
@functools.wraps(func)
def caller(*args, **kwargs):
if linux:
return func(*args, **kwargs)
else:
return default
return caller
return decorator
# Update when starting the gdb to show warning message for non-Linux ABI user.
update()

View File

@ -41,7 +41,7 @@ def find_upper_stack_boundary(stack_ptr, max_pages=1024):
# We can't get the stack size from stack layout and page fault on bare metal mode, # We can't get the stack size from stack layout and page fault on bare metal mode,
# so we return current page as a walkaround. # so we return current page as a walkaround.
if not pwndbg.abi.linux: if not pwndbg.gdblib.abi.linux:
return stack_ptr + pwndbg.memory.PAGE_SIZE return stack_ptr + pwndbg.memory.PAGE_SIZE
return pwndbg.memory.find_upper_boundary(stack_ptr, max_pages) return pwndbg.memory.find_upper_boundary(stack_ptr, max_pages)

View File

@ -11,9 +11,9 @@ import sys
import gdb import gdb
import pwndbg.abi
import pwndbg.elf import pwndbg.elf
import pwndbg.file import pwndbg.file
import pwndbg.gdblib.abi
import pwndbg.gdblib.events import pwndbg.gdblib.events
import pwndbg.gdblib.typeinfo import pwndbg.gdblib.typeinfo
import pwndbg.lib.memoize import pwndbg.lib.memoize
@ -107,7 +107,7 @@ def find(address):
return explore(address) return explore(address)
@pwndbg.abi.LinuxOnly() @pwndbg.gdblib.abi.LinuxOnly()
def explore(address_maybe): def explore(address_maybe):
""" """
Given a potential address, check to see what permissions it has. Given a potential address, check to see what permissions it has.