Skip to content

Commit

Permalink
Add sysinfo helper
Browse files Browse the repository at this point in the history
Signed-off-by: Sharad Raykhere <[email protected]>
  • Loading branch information
srd-17 committed Nov 8, 2023
1 parent 7e791a9 commit 87a07d1
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 0 deletions.
7 changes: 7 additions & 0 deletions doc/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,10 @@ drgn_tools.cpuinfo

.. automodule:: drgn_tools.cpuinfo
:members:


drgn_tools.sys
-----------------------

.. automodule:: drgn_tools.sys
:members:
145 changes: 145 additions & 0 deletions drgn_tools/sys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
# Copyright (c) 2023, Oracle and/or its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
"""
Helper to view sysinfo data
"""
import argparse
import datetime
import time

from drgn import Architecture
from drgn import Program
from drgn import ProgramFlags
from drgn.helpers.linux import for_each_task
from drgn.helpers.linux.sched import loadavg

try:
# drgn v0.21.0+
from drgn.helpers.common import escape_ascii_string
except ImportError:
# drgn <v0.21.0
from drgn.helpers import escape_ascii_string

from drgn_tools.corelens import CorelensModule
from drgn_tools.mm import totalram_pages
from drgn_tools.util import human_bytes
from drgn_tools.table import print_dictionary
from drgn_tools.cpuinfo import x86_get_cpu_info
from drgn_tools.cpuinfo import aarch64_get_cpu_info


def uts_to_string(s):
return escape_ascii_string(s.string_(), escape_backslash=True)


def load_average(prog: Program) -> str:
"""
Return system load averaged over 1, 5 and 15 minutes as a string.
"""
load_avg = loadavg(prog)
return "{:0.2f} , {:0.2f} , {:0.2f}".format(
load_avg[0],
load_avg[1],
load_avg[2],
)


def get_mem(prog: Program) -> str:
"""
Returns the total memory of the system, as a human-readable string
"""
total_pages = totalram_pages(prog)
pagesize = int(prog["PAGE_SIZE"])
return human_bytes(total_pages * pagesize)


def task_info(prog: Program) -> str:
"""
Returns the task info of system as a string
"""
task_running = 0
task_int = 0
task_unint = 0
tasks_count = prog["nr_cpu_ids"]
for task in for_each_task(prog):
tasks_count += 1
try:
if prog.type("struct task_struct").has_member("__state"):
task_state = task.__state
else:
task_state = task.state
except LookupError:
task_state = task.__state
if task_state == 0:
task_running += 1
elif task_state == 1:
task_int += 1
elif task_state == 2:
task_unint += 1
return f"{int(tasks_count)} [R:{task_running} D:{task_unint} S:{task_int}]"


def sysinfo(prog: Program) -> None:
"""
Prints the sysinfo of the system
"""
if ProgramFlags.IS_LIVE in prog.flags:
mode = "Live kernel"
else:
mode = "VMCORE File"
if "system_utsname" in prog:
uts = prog["system_utsname"]
elif "init_uts_ns" in prog:
uts = prog["init_uts_ns"]
else:
raise Exception("error: could not find utsname information")
timekeeper = prog["shadow_timekeeper"]
date = time.ctime(timekeeper.xtime_sec)
uptime = str(datetime.timedelta(seconds=int(timekeeper.ktime_sec)))
jiffies = int(prog["jiffies"])
nodename = uts_to_string(uts.name.nodename)
release = uts_to_string(uts.name.release)
version = uts_to_string(uts.name.version)
machine = uts_to_string(uts.name.machine)
load_avg = load_average(prog)
memory = get_mem(prog)
tasks = task_info(prog)
data_sysinfo = {
"MODE": mode,
"DATE": date,
"NODENAME": nodename,
"RELEASE": release,
"VERSION": version,
"MACHINE": machine,
"UPTIME": uptime,
"LOAD AVERAGE": load_avg,
"JIFFIES": jiffies,
"MEMORY": memory,
"TASKS": tasks,
}
print_dictionary(data_sysinfo)
if prog.platform.arch == Architecture.X86_64:
cpuinfo_data = x86_get_cpu_info(prog)
if "CPU FLAGS" in cpuinfo_data:
del cpuinfo_data["CPU FLAGS"]
if "BUG FLAGS" in cpuinfo_data:
del cpuinfo_data["BUG FLAGS"]
print_dictionary(cpuinfo_data)

elif prog.platform.arch == Architecture.AARCH64:
cpuinfo_data = aarch64_get_cpu_info(prog)
print_dictionary(cpuinfo_data)

else:
print(f"Not supported for {prog.platform.arch.name}")


class SysInfo(CorelensModule):
"""
Corelens Module for sysinfo
"""

name = "sys"

def run(self, prog: Program, args: argparse.Namespace) -> None:
sysinfo(prog)
7 changes: 7 additions & 0 deletions tests/test_sys.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Copyright (c) 2023, Oracle and/or its affiliates.
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/
from drgn_tools import sys


def test_sysinfo(prog):
sys.sysinfo(prog)

0 comments on commit 87a07d1

Please sign in to comment.