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_INT
import pwndbg.abi
import pwndbg.chain
import pwndbg.color.nearpc as N
import pwndbg.constants
@ -14,6 +13,7 @@ import pwndbg.disasm
import pwndbg.gdblib.arch
import pwndbg.gdblib.typeinfo
import pwndbg.ida
import pwndbg.lib.abi
import pwndbg.lib.funcparser
import pwndbg.lib.functions
import pwndbg.memory
@ -52,7 +52,7 @@ def get_syscall_name(instruction):
if CS_GRP_INT not in instruction.groups:
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 syscall_register in ("eax", "rax"):
@ -81,7 +81,7 @@ def get(instruction):
if CS_GRP_CALL in instruction.groups:
try:
abi = pwndbg.abi.ABI.default()
abi = pwndbg.lib.abi.ABI.default()
except KeyError:
return []
@ -100,7 +100,7 @@ def get(instruction):
elif CS_GRP_INT in instruction.groups:
# Get the syscall number and name
name = get_syscall_name(instruction)
abi = pwndbg.abi.ABI.syscall()
abi = pwndbg.lib.abi.ABI.syscall()
target = None
if name is None:
@ -162,7 +162,7 @@ def get(instruction):
def argname(n, abi=None):
abi = abi or pwndbg.abi.ABI.default()
abi = abi or pwndbg.lib.abi.ABI.default()
regs = abi.register_arguments
if n < len(regs):
@ -177,7 +177,7 @@ def argument(n, abi=None):
instruction.
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
if n < len(regs):
@ -195,7 +195,7 @@ def arguments(abi=None):
Yields (arg_name, arg_value) tuples for arguments from a given ABI.
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
for i in range(len(regs)):

View File

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

View File

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

View File

@ -1,10 +1,10 @@
import gdb
import pwndbg.abi
import pwndbg.color.chain as C
import pwndbg.color.memory as M
import pwndbg.color.theme as theme
import pwndbg.enhance
import pwndbg.gdblib.abi
import pwndbg.gdblib.typeinfo
import pwndbg.memory
import pwndbg.symbol
@ -56,7 +56,7 @@ def get(
# Avoid redundant dereferences in bare metal mode by checking
# 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
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.elffile import ELFFile
import pwndbg.abi
import pwndbg.auxv
import pwndbg.elftypes
import pwndbg.gdblib.abi
import pwndbg.gdblib.arch
import pwndbg.gdblib.events
import pwndbg.info
@ -266,7 +266,7 @@ def get_ehdr(pointer):
if base is None:
# 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!")
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
@ -114,60 +109,3 @@ linux_arm_sigreturn = SigreturnABI(["r7"], 4, 0)
linux_i386_srop = ABI(["eax"], 4, 0)
linux_amd64_srop = ABI(["rax"], 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,
# 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 pwndbg.memory.find_upper_boundary(stack_ptr, max_pages)

View File

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