Skip to content

Commit 4db2c40

Browse files
authored
Merge pull request #251 from delphix/master
Merge branch 'master' into '6.0/stage'
2 parents 5aec34f + f0aa360 commit 4db2c40

21 files changed

+1342
-1267
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,7 @@ jobs:
9494
# comes with Ubuntu is 0.75 which has a couple of bugs triggered
9595
# by our codebase (they've been resolved on trunk though so we
9696
# may want to change this soon).
97-
# [2] We supply --allow-untyped-calls because even though drgn has
98-
# stubs on typeshed now, there are still some untyped functions
99-
# (mainly in the helper API).
100-
# [3] We supply --ignore-missing-imports to the tests package because
97+
# [2] We supply --ignore-missing-imports to the tests package because
10198
# pytest doesn't provide stubs on typeshed.
10299
#
103100
mypy:
@@ -109,7 +106,7 @@ jobs:
109106
python-version: '3.6'
110107
- run: ./.github/scripts/install-drgn.sh
111108
- run: python3 -m pip install mypy==0.730
112-
- run: python3 -m mypy --strict --allow-untyped-calls --show-error-codes -p sdb
109+
- run: python3 -m mypy --strict --show-error-codes -p sdb
113110
- run: python3 -m mypy --strict --ignore-missing-imports --show-error-codes -p tests
114111
#
115112
# Verify that "shfmt" ran successfully against our shell scripts.

sdb/command.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -643,13 +643,13 @@ def _call(self, objs: Iterable[drgn.Object]) -> Iterable[drgn.Object]:
643643
the types as we go.
644644
"""
645645
assert self.input_type is not None
646-
type_ = target.get_type(self.input_type)
646+
expected_type = type_canonicalize_name(self.input_type)
647647
for obj in objs:
648-
if obj.type_ != type_:
648+
if type_canonical_name(obj.type_) != expected_type:
649649
raise CommandError(
650650
self.name,
651651
'expected input of type {}, but received {}'.format(
652-
type_, obj.type_))
652+
expected_type, type_canonical_name(obj.type_)))
653653

654654
yield from self.walk(obj)
655655

sdb/commands/internal/util.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,46 @@ def get_valid_type_by_name(cmd: sdb.Command, tname: str) -> drgn.Type:
2424
"""
2525
Given a type name in string form (`tname`) without any C keyword
2626
prefixes (e.g. 'struct', 'enum', 'class', 'union'), return the
27-
corresponding drgn.Type object.
27+
corresponding drgn.Type object. If `tname` starts with a C keyword
28+
we just return the type as is.
2829
2930
This function is used primarily by commands that accept a type
3031
name as an argument and exist only to save keystrokes for the
3132
user.
3233
"""
33-
if tname in ['struct', 'enum', 'union', 'class']:
34+
TYPE_KEYWORDS = ['struct', 'enum', 'union', 'class']
35+
36+
tokens = tname.split()
37+
if len(tokens) > 2:
38+
#
39+
# drgn fails in all kinds of ways when we pass it an
40+
# invalid type that consists of more than 2 text tokens.
41+
#
42+
raise sdb.CommandError(cmd.name,
43+
f"input '{tname}' is not a valid type name")
44+
45+
if len(tokens) == 2:
46+
if tokens[0] not in TYPE_KEYWORDS or tokens[1] in TYPE_KEYWORDS:
47+
#
48+
# For the same reason mentioned in the above comment
49+
# we also ensure that someone may not invalid two-token
50+
# input that has the following errors:
51+
# 1] Doesn't start with a type keyword - e.g "bogus type"
52+
# 2] Has a type keyword as its type name (also see
53+
# comment below) - e.g. struct struct
54+
#
55+
raise sdb.CommandError(cmd.name,
56+
f"input '{tname}' is not a valid type name")
57+
try:
58+
return sdb.get_type(tname)
59+
except LookupError as err:
60+
raise sdb.CommandError(cmd.name,
61+
f"couldn't find type '{tname}'") from err
62+
except SyntaxError as err:
63+
raise sdb.CommandError(
64+
cmd.name, f"input '{tname}' is not a valid type name") from err
65+
66+
if tname in TYPE_KEYWORDS:
3467
#
3568
# Note: We have to do this because currently in drgn
3669
# prog.type('struct') returns a different error than
@@ -82,9 +115,12 @@ def get_valid_type_by_name(cmd: sdb.Command, tname: str) -> drgn.Type:
82115
# it is a structure, an enum, or a union.
83116
#
84117
pass
85-
for prefix in ["struct ", "enum ", "union "]:
118+
except SyntaxError as err:
119+
raise sdb.CommandError(
120+
cmd.name, f"input '{tname}' is not a valid type name") from err
121+
for prefix in TYPE_KEYWORDS:
86122
try:
87-
return sdb.get_type(f"{prefix}{tname}")
123+
return sdb.get_type(f"{prefix} {tname}")
88124
except LookupError:
89125
pass
90126
raise sdb.CommandError(

sdb/commands/ptype.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,16 +50,15 @@ class PType(sdb.Command):
5050
5151
Print enums and unions:
5252
53-
sdb> ptype zfs_case v_t thread_union
53+
sdb> ptype zfs_case 'struct v' thread_union
5454
enum zfs_case {
5555
ZFS_CASE_SENSITIVE = 0,
5656
ZFS_CASE_INSENSITIVE = 1,
5757
ZFS_CASE_MIXED = 2,
5858
}
59-
typedef union {
60-
iv_t e;
61-
uint8_t b[8];
62-
} v_t
59+
struct v {
60+
uint8_t b[16];
61+
}
6362
union thread_union {
6463
struct task_struct task;
6564
unsigned long stack[2048];

sdb/commands/threads.py

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,40 @@
1616

1717
# pylint: disable=missing-docstring
1818

19+
from textwrap import shorten
1920
from typing import Callable, Dict, Iterable, Union
2021

2122
import drgn
2223
from drgn.helpers.linux.pid import for_each_task
24+
from drgn.helpers.linux.mm import cmdline
2325

2426
import sdb
2527
from sdb.commands.internal.table import Table
2628
from sdb.commands.stacks import Stacks
2729

2830

31+
def _cmdline(obj: drgn.Object) -> str:
32+
try:
33+
s = " ".join(map(lambda s: s.decode("utf-8"), cmdline(obj)))
34+
35+
#
36+
# The command line for a given thread can be obnoxiously long,
37+
# so (by default) we limit it to 50 characters here. This helps
38+
# preserve the readability of the command's output, but comes at
39+
# the cost of not always showing the full command line of a
40+
# thread.
41+
#
42+
return shorten(s, width=50)
43+
except drgn.FaultError:
44+
#
45+
# The command line information is contained in the user address
46+
# space of each thread, rather than in the kernel's address
47+
# space. Thus, often, it may not be possible to retreive the
48+
# thread's command line; e.g. when reading from a core dump.
49+
#
50+
return ""
51+
52+
2953
class Threads(sdb.Locator, sdb.PrettyPrinter):
3054
"""
3155
Locate and print information about threads (task_stuct)
@@ -36,16 +60,16 @@ class Threads(sdb.Locator, sdb.PrettyPrinter):
3660
pid - the pid of the thread's process
3761
prio - the priority of the thread
3862
comm - the thread's command
63+
cmdline - the thread's command line (when available)
3964
4065
EXAMPLE
4166
sdb> threads | filter 'obj.comm == "java"' | threads
42-
task state pid prio comm
43-
------------------ ------------- ---- ---- ----
44-
0xffff95d48b0e8000 INTERRUPTIBLE 4386 120 java
45-
0xffff95d48b0e96c0 INTERRUPTIBLE 4388 120 java
46-
0xffff95d48b0ead80 INTERRUPTIBLE 4387 120 java
47-
0xffff95d48b0edb00 INTERRUPTIBLE 4304 120 java
48-
0xffff95d4af20ad80 INTERRUPTIBLE 4395 120 java
67+
task state pid prio comm cmdline
68+
------------------ ------------- ---- ---- ---- ----------------------------------------
69+
0xffff8c96a7c70000 INTERRUPTIBLE 3029 120 java /usr/bin/java -Ddelphix.debug=true [...]
70+
0xffff8c96a7c71740 INTERRUPTIBLE 3028 120 java /usr/bin/java -Ddelphix.debug=true [...]
71+
0xffff8c96a7c75d00 INTERRUPTIBLE 3024 120 java /usr/bin/java -Ddelphix.debug=true [...]
72+
0xffff8c9715808000 INTERRUPTIBLE 3027 120 java /usr/bin/java -Ddelphix.debug=true [...]
4973
"""
5074

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

6388
def pretty_print(self, objs: Iterable[drgn.Object]) -> None:
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sdb: ptype: input '$abc' is not a valid type name
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sdb: ptype: input 'a b c' is not a valid type name
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sdb: ptype: input 'bogus union' is not a valid type name
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sdb: ptype: couldn't find type 'struct bogus'
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
sdb: ptype: input 'struct union' is not a valid type name

0 commit comments

Comments
 (0)