Dump the TLS address by default (#2847)

* tls: dump the tls address by default

Use a `dt tcbhead_t <tls_address>` if there is a `tcbhead_t`. If there
is not, use telescope to dump it

Refactor the tls tests and add some new ones based on the change.

* Update pwndbg/commands/tls.py

* Update pwndbg/commands/tls.py

* Update pwndbg/commands/tls.py

* Update tls.py

---------

Co-authored-by: Disconnect3d <dominik.b.czarnota@gmail.com>
pull/2851/head
davi 8 months ago committed by GitHub
parent 261fac8543
commit 42e5bd60b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -15,6 +15,7 @@ import pwndbg.aglib.vmmap
import pwndbg.color.memory as M
import pwndbg.commands
import pwndbg.commands.context
import pwndbg.commands.telescope
import pwndbg.dbg
from pwndbg.color import message
from pwndbg.commands import CommandCategory
@ -32,11 +33,13 @@ parser.add_argument(
help="Try to get the address of TLS by calling pthread_self().",
)
parser.add_argument("-a", "--all", action="store_true", help="Do not truncate the dump output.")
@pwndbg.commands.ArgparsedCommand(parser, category=CommandCategory.LINUX)
@pwndbg.commands.OnlyWhenRunning
@pwndbg.commands.OnlyWhenUserspace
def tls(pthread_self=False) -> None:
def tls(pthread_self=False, all: bool = False) -> None:
tls_base = (
pwndbg.aglib.tls.find_address_with_register()
if not pthread_self
@ -46,6 +49,46 @@ def tls(pthread_self=False) -> None:
print(message.success("Thread Local Storage (TLS) base: %#x" % tls_base))
print(message.success("TLS is located at:"))
print(message.notice(pwndbg.aglib.vmmap.find(tls_base)))
# Displaying `dt tcbhead_t <tls_base>` if possible
# If not, we will dump the tls with telescope
output = str(pwndbg.aglib.dt.dt("tcbhead_t", addr=tls_base))
print(message.success("Dumping the address:"))
if output == "Type not found.":
pwndbg.commands.telescope.telescope(tls_base, 10)
else:
lines = output.splitlines()
if all or len(lines) <= 10:
print(message.notice(output))
else:
index = None
for i, line in enumerate(lines):
if "__glibc_unused2" in line:
index = i
break
if index is not None:
end_index = index + 2
for line in lines[:end_index]:
print(message.notice(line))
print(message.notice("\t[...]"))
print(
message.hint(
"Output truncated. Rerun with option -a to display the full output."
)
)
# In case there is a tcbhead_t but there is no __glibc_unused2
else:
for line in lines[:10]:
print(message.notice(line))
print(message.notice("\t[...]"))
print(
message.hint(
"Output truncated. Rerun with option -a to display the full output."
)
)
return
print(message.error("Couldn't find Thread Local Storage (TLS) base."))
if not pthread_self:

@ -27,16 +27,27 @@ def test_tls_address_and_command(start_binary, binary):
assert pwndbg.aglib.tls.find_address_with_pthread_self() == expected_tls_address
output = gdb.execute("tls", to_string=True)
assert f"Thread Local Storage (TLS) base: {expected_tls_address:#x}" in output
assert "TLS is located at:\n" and f"{pwndbg.aglib.vmmap.find(expected_tls_address)}\n" in output
assert "Output truncated. Rerun with option -a to display the full output." in output
output_pthread = gdb.execute("tls --pthread-self", to_string=True)
assert f"Thread Local Storage (TLS) base: {expected_tls_address:#x}" in output_pthread
assert (
gdb.execute("tls", to_string=True)
== f"""Thread Local Storage (TLS) base: {expected_tls_address:#x}
TLS is located at:
{pwndbg.aglib.vmmap.find(expected_tls_address)}\n"""
"TLS is located at:"
and f"{pwndbg.aglib.vmmap.find(expected_tls_address)}\n" in output_pthread
)
assert "Output truncated. Rerun with option -a to display the full output." in output_pthread
# Argument `-a`
output_all = gdb.execute("tls --all", to_string=True)
assert f"Thread Local Storage (TLS) base: {expected_tls_address:#x}" in output_all
assert (
gdb.execute("tls --pthread-self", to_string=True)
== f"""Thread Local Storage (TLS) base: {expected_tls_address:#x}
TLS is located at:
{pwndbg.aglib.vmmap.find(expected_tls_address)}\n"""
"TLS is located at:\n"
and f"{pwndbg.aglib.vmmap.find(expected_tls_address)}\n" in output_all
)
assert "Output truncated. Rerun with option -a to display the full output." not in output_all

Loading…
Cancel
Save