Port errno (#2552)

* commands/misc.py: port to aglib, commands: errno, pwndbg

* errno: fix message

* commands/misc.py: fix lint
pull/2559/head
patryk4815 1 year ago committed by GitHub
parent dda714883b
commit ae579e76e1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -715,7 +715,6 @@ def load_commands() -> None:
import pwndbg.commands.kversion
import pwndbg.commands.linkmap
import pwndbg.commands.memoize
import pwndbg.commands.misc
import pwndbg.commands.onegadget
import pwndbg.commands.pcplist
import pwndbg.commands.peda
@ -750,6 +749,7 @@ def load_commands() -> None:
import pwndbg.commands.hex2ptr
import pwndbg.commands.hexdump
import pwndbg.commands.leakfind
import pwndbg.commands.misc
import pwndbg.commands.mmap
import pwndbg.commands.mprotect
import pwndbg.commands.nearpc

@ -4,14 +4,13 @@ import argparse
import errno
from collections import defaultdict
import gdb
import pwndbg.aglib.memory
import pwndbg.aglib.regs
import pwndbg.aglib.vmmap
import pwndbg.color as C
import pwndbg.commands
import pwndbg.gdblib.regs
import pwndbg.gdblib.symbol
import pwndbg.dbg
from pwndbg.commands import CommandCategory
from pwndbg.gdblib.scheduler import parse_and_eval_with_scheduler_lock
# Manually add error code 0 for "OK"
errno.errorcode[0] = "OK" # type: ignore[index]
@ -28,40 +27,48 @@ parser.add_argument(
)
def _get_errno() -> int:
# Try to get the `errno` variable value
# if it does not exist, get the errno variable from its location
try:
return int(pwndbg.dbg.selected_frame().evaluate_expression("errno"))
except pwndbg.dbg_mod.Error:
pass
# We can't simply call __errno_location because its .plt.got entry may be uninitialized
# (e.g. if the binary was just started with `starti` command)
# So we have to check the got.plt entry first before calling it
errno_loc_gotplt = pwndbg.dbg.selected_inferior().symbol_address_from_name(
"__errno_location@got.plt"
)
if errno_loc_gotplt is not None:
page_loaded = pwndbg.aglib.vmmap.find(pwndbg.aglib.memory.pvoid(errno_loc_gotplt))
if page_loaded is None:
raise pwndbg.dbg_mod.Error(
"Could not determine error code automatically: the __errno_location@got.plt has no valid address yet (perhaps libc.so hasn't been loaded yet?)"
)
try:
return int(
pwndbg.dbg.selected_frame().evaluate_expression(
"*((int *(*) (void)) __errno_location) ()", lock_scheduler=True
)
)
except pwndbg.dbg_mod.Error as e:
raise pwndbg.dbg_mod.Error(
"Could not determine error code automatically: neither `errno` nor `__errno_location` symbols were provided (perhaps libc.so hasn't been not loaded yet?)"
) from e
@pwndbg.commands.ArgparsedCommand(parser, command_name="errno", category=CommandCategory.LINUX)
@pwndbg.commands.OnlyWhenRunning
def errno_(err) -> None:
if err is None:
# Try to get the `errno` variable value
# if it does not exist, get the errno variable from its location
try:
err = int(gdb.parse_and_eval("errno"))
except gdb.error:
try:
# We can't simply call __errno_location because its .plt.got entry may be uninitialized
# (e.g. if the binary was just started with `starti` command)
# So we have to check the got.plt entry first before calling it
errno_loc_gotplt = pwndbg.gdblib.symbol.address("__errno_location@got.plt")
# If the got.plt entry is not there (is None), it means the symbol is not used by the binary
if errno_loc_gotplt is None or pwndbg.gdblib.vmmap.find(
pwndbg.gdblib.memory.pvoid(errno_loc_gotplt)
):
err = int(
parse_and_eval_with_scheduler_lock(
"*((int *(*) (void)) __errno_location) ()"
)
)
else:
print(
"Could not determine error code automatically: the __errno_location@got.plt has no valid address yet (perhaps libc.so hasn't been loaded yet?)"
)
return
except gdb.error:
print(
"Could not determine error code automatically: neither `errno` nor `__errno_location` symbols were provided (perhaps libc.so hasn't been not loaded yet?)"
)
return
err = _get_errno()
except pwndbg.dbg_mod.Error as e:
print(str(e))
return
msg = errno.errorcode.get(int(err), "Unknown error code")
print(f"Errno {err}: {msg}")

Loading…
Cancel
Save