Skip to content

Commit

Permalink
drgn.helpers.linux.mm: have cmdline() and environ() return None for k…
Browse files Browse the repository at this point in the history
…ernel tasks

Sometimes I need to enumerate all tasks in the system and print their
command lines, among other information. This fails for kernel tasks
(i.e. tasks without mm):

Traceback (most recent call last):
  File "<console>", line 2, in <module>
  File "[...]/drgn/helpers/linux/mm.py", line 1276, in cmdline
    arg_start = mm.arg_start.value_()
                ^^^^^^^^^^^^^^^^^^^^^
_drgn.FaultError: address is not mapped: 0x140

It seems reasonable for this not to cause an exception but rather
to return a value that the caller can conveniently recover from
(consider also the behavior of `cat /proc/2/cmdline`). Therefore,
change cmdline() to return None for kernel tasks. Do the same for
environ() for consistency.

Signed-off-by: Peter Collingbourne <[email protected]>
  • Loading branch information
pcc authored and osandov committed Nov 29, 2023
1 parent 4054a68 commit 94ecc33
Showing 1 changed file with 8 additions and 4 deletions.
12 changes: 8 additions & 4 deletions drgn/helpers/linux/mm.py
Original file line number Diff line number Diff line change
Expand Up @@ -1320,9 +1320,9 @@ def access_remote_vm(mm: Object, address: IntegerLike, size: IntegerLike) -> byt
return _linux_helper_read_vm(mm.prog_, mm.pgd, address, size)


def cmdline(task: Object) -> List[bytes]:
def cmdline(task: Object) -> Optional[List[bytes]]:
"""
Get the list of command line arguments of a task.
Get the list of command line arguments of a task, or ``None`` for kernel tasks.
>>> cmdline(find_task(prog, 1495216))
[b'vim', b'drgn/helpers/linux/mm.py']
Expand All @@ -1335,14 +1335,16 @@ def cmdline(task: Object) -> List[bytes]:
:param task: ``struct task_struct *``
"""
mm = task.mm.read_()
if not mm:
return None
arg_start = mm.arg_start.value_()
arg_end = mm.arg_end.value_()
return access_remote_vm(mm, arg_start, arg_end - arg_start).split(b"\0")[:-1]


def environ(task: Object) -> List[bytes]:
def environ(task: Object) -> Optional[List[bytes]]:
"""
Get the list of environment variables of a task.
Get the list of environment variables of a task, or ``None`` for kernel tasks.
>>> environ(find_task(prog, 1497797))
[b'HOME=/root', b'PATH=/usr/local/sbin:/usr/local/bin:/usr/bin', b'LOGNAME=root']
Expand All @@ -1357,6 +1359,8 @@ def environ(task: Object) -> List[bytes]:
:param task: ``struct task_struct *``
"""
mm = task.mm.read_()
if not mm:
return None
env_start = mm.env_start.value_()
env_end = mm.env_end.value_()
return access_remote_vm(mm, env_start, env_end - env_start).split(b"\0")[:-1]
Expand Down

0 comments on commit 94ecc33

Please sign in to comment.