Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,10 +94,7 @@ jobs:
# comes with Ubuntu is 0.75 which has a couple of bugs triggered
# by our codebase (they've been resolved on trunk though so we
# may want to change this soon).
# [2] We supply --allow-untyped-calls because even though drgn has
# stubs on typeshed now, there are still some untyped functions
# (mainly in the helper API).
# [3] We supply --ignore-missing-imports to the tests package because
# [2] We supply --ignore-missing-imports to the tests package because
# pytest doesn't provide stubs on typeshed.
#
mypy:
Expand All @@ -109,7 +106,7 @@ jobs:
python-version: '3.6'
- run: ./.github/scripts/install-drgn.sh
- run: python3 -m pip install mypy==0.730
- run: python3 -m mypy --strict --allow-untyped-calls --show-error-codes -p sdb
- run: python3 -m mypy --strict --show-error-codes -p sdb
- run: python3 -m mypy --strict --ignore-missing-imports --show-error-codes -p tests
#
# Verify that "shfmt" ran successfully against our shell scripts.
Expand Down
6 changes: 3 additions & 3 deletions sdb/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -643,13 +643,13 @@ def _call(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
the types as we go.
"""
assert self.input_type is not None
type_ = target.get_type(self.input_type)
expected_type = type_canonicalize_name(self.input_type)
for obj in objs:
if obj.type_ != type_:
if type_canonical_name(obj.type_) != expected_type:
raise CommandError(
self.name,
'expected input of type {}, but received {}'.format(
type_, obj.type_))
expected_type, type_canonical_name(obj.type_)))

yield from self.walk(obj)

Expand Down
44 changes: 40 additions & 4 deletions sdb/commands/internal/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,46 @@ def get_valid_type_by_name(cmd: sdb.Command, tname: str) -> drgn.Type:
"""
Given a type name in string form (`tname`) without any C keyword
prefixes (e.g. 'struct', 'enum', 'class', 'union'), return the
corresponding drgn.Type object.
corresponding drgn.Type object. If `tname` starts with a C keyword
we just return the type as is.

This function is used primarily by commands that accept a type
name as an argument and exist only to save keystrokes for the
user.
"""
if tname in ['struct', 'enum', 'union', 'class']:
TYPE_KEYWORDS = ['struct', 'enum', 'union', 'class']

tokens = tname.split()
if len(tokens) > 2:
#
# drgn fails in all kinds of ways when we pass it an
# invalid type that consists of more than 2 text tokens.
#
raise sdb.CommandError(cmd.name,
f"input '{tname}' is not a valid type name")

if len(tokens) == 2:
if tokens[0] not in TYPE_KEYWORDS or tokens[1] in TYPE_KEYWORDS:
#
# For the same reason mentioned in the above comment
# we also ensure that someone may not invalid two-token
# input that has the following errors:
# 1] Doesn't start with a type keyword - e.g "bogus type"
# 2] Has a type keyword as its type name (also see
# comment below) - e.g. struct struct
#
raise sdb.CommandError(cmd.name,
f"input '{tname}' is not a valid type name")
try:
return sdb.get_type(tname)
except LookupError as err:
raise sdb.CommandError(cmd.name,
f"couldn't find type '{tname}'") from err
except SyntaxError as err:
raise sdb.CommandError(
cmd.name, f"input '{tname}' is not a valid type name") from err

if tname in TYPE_KEYWORDS:
#
# Note: We have to do this because currently in drgn
# prog.type('struct') returns a different error than
Expand Down Expand Up @@ -82,9 +115,12 @@ def get_valid_type_by_name(cmd: sdb.Command, tname: str) -> drgn.Type:
# it is a structure, an enum, or a union.
#
pass
for prefix in ["struct ", "enum ", "union "]:
except SyntaxError as err:
raise sdb.CommandError(
cmd.name, f"input '{tname}' is not a valid type name") from err
for prefix in TYPE_KEYWORDS:
try:
return sdb.get_type(f"{prefix}{tname}")
return sdb.get_type(f"{prefix} {tname}")
except LookupError:
pass
raise sdb.CommandError(
Expand Down
9 changes: 4 additions & 5 deletions sdb/commands/ptype.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,15 @@ class PType(sdb.Command):

Print enums and unions:

sdb> ptype zfs_case v_t thread_union
sdb> ptype zfs_case 'struct v' thread_union
enum zfs_case {
ZFS_CASE_SENSITIVE = 0,
ZFS_CASE_INSENSITIVE = 1,
ZFS_CASE_MIXED = 2,
}
typedef union {
iv_t e;
uint8_t b[8];
} v_t
struct v {
uint8_t b[16];
}
union thread_union {
struct task_struct task;
unsigned long stack[2048];
Expand Down
39 changes: 32 additions & 7 deletions sdb/commands/threads.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,40 @@

# pylint: disable=missing-docstring

from textwrap import shorten
from typing import Callable, Dict, Iterable, Union

import drgn
from drgn.helpers.linux.pid import for_each_task
from drgn.helpers.linux.mm import cmdline

import sdb
from sdb.commands.internal.table import Table
from sdb.commands.stacks import Stacks


def _cmdline(obj: drgn.Object) -> str:
try:
s = " ".join(map(lambda s: s.decode("utf-8"), cmdline(obj)))

#
# The command line for a given thread can be obnoxiously long,
# so (by default) we limit it to 50 characters here. This helps
# preserve the readability of the command's output, but comes at
# the cost of not always showing the full command line of a
# thread.
#
return shorten(s, width=50)
except drgn.FaultError:
#
# The command line information is contained in the user address
# space of each thread, rather than in the kernel's address
# space. Thus, often, it may not be possible to retreive the
# thread's command line; e.g. when reading from a core dump.
#
return ""


class Threads(sdb.Locator, sdb.PrettyPrinter):
"""
Locate and print information about threads (task_stuct)
Expand All @@ -36,16 +60,16 @@ class Threads(sdb.Locator, sdb.PrettyPrinter):
pid - the pid of the thread's process
prio - the priority of the thread
comm - the thread's command
cmdline - the thread's command line (when available)

EXAMPLE
sdb> threads | filter 'obj.comm == "java"' | threads
task state pid prio comm
------------------ ------------- ---- ---- ----
0xffff95d48b0e8000 INTERRUPTIBLE 4386 120 java
0xffff95d48b0e96c0 INTERRUPTIBLE 4388 120 java
0xffff95d48b0ead80 INTERRUPTIBLE 4387 120 java
0xffff95d48b0edb00 INTERRUPTIBLE 4304 120 java
0xffff95d4af20ad80 INTERRUPTIBLE 4395 120 java
task state pid prio comm cmdline
------------------ ------------- ---- ---- ---- ----------------------------------------
0xffff8c96a7c70000 INTERRUPTIBLE 3029 120 java /usr/bin/java -Ddelphix.debug=true [...]
0xffff8c96a7c71740 INTERRUPTIBLE 3028 120 java /usr/bin/java -Ddelphix.debug=true [...]
0xffff8c96a7c75d00 INTERRUPTIBLE 3024 120 java /usr/bin/java -Ddelphix.debug=true [...]
0xffff8c9715808000 INTERRUPTIBLE 3027 120 java /usr/bin/java -Ddelphix.debug=true [...]
"""

names = ["threads", "thread"]
Expand All @@ -58,6 +82,7 @@ class Threads(sdb.Locator, sdb.PrettyPrinter):
"pid": lambda obj: int(obj.pid),
"prio": lambda obj: int(obj.prio),
"comm": lambda obj: str(obj.comm.string_().decode("utf-8")),
"cmdline": _cmdline,
}

def pretty_print(self, objs: Iterable[drgn.Object]) -> None:
Expand Down
1 change: 1 addition & 0 deletions tests/integration/data/regression_output/core/ptype $abc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdb: ptype: input '$abc' is not a valid type name
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdb: ptype: input 'a b c' is not a valid type name
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdb: ptype: input 'bogus union' is not a valid type name
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdb: ptype: couldn't find type 'struct bogus'
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdb: ptype: input 'struct union' is not a valid type name
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdb: ptype: skip keyword 'struct' or quote your type "struct <typename>"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdb: ptype: input 'union struct struct' is not a valid type name
1 change: 1 addition & 0 deletions tests/integration/data/regression_output/core/ptype 2abc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdb: ptype: input '2abc' is not a valid type name
1 change: 1 addition & 0 deletions tests/integration/data/regression_output/core/ptype @
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sdb: ptype: input '@' is not a valid type name
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ enum zfs_case {
ZFS_CASE_INSENSITIVE = 1,
ZFS_CASE_MIXED = 2,
}
typedef union {
iv_t e;
uint8_t b[8];
} v_t
struct v {
uint8_t b[16];
}
union thread_union {
struct task_struct task;
unsigned long stack[2048];
Expand Down
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
task state pid prio comm
---- ----- --- ---- ----
task state pid prio comm cmdline
---- ----- --- ---- ---- -------
Original file line number Diff line number Diff line change
@@ -1 +1 @@
sdb: cpu_counter_sum: invalid memory access: could not read memory from kdump: Cannot get page I/O address: PDPT table not present: pgd[0] = 0x0: 0x8
sdb: cpu_counter_sum: invalid memory access: could not read memory from kdump: Cannot get page I/O address: PDPT table not present: p4d[0] = 0x0: 0x8
Loading