/* help.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. * Copyright (C) 2002-2020 David Anderson * Copyright (C) 2002-2020 Red Hat, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include "defs.h" static void reshuffle_cmdlist(void); static int sort_command_name(const void *, const void *); static void display_commands(void); static void display_copying_info(void); static void display_warranty_info(void); static void display_output_info(void); static void display_input_info(void); static void display_README(void); static char *gnu_public_license[]; static char *gnu_public_license_v3[]; static char *version_info[]; static char *output_info[]; static char *input_info[]; static char *README[]; static void dump_registers(void); #define GPLv2 2 #define GPLv3 3 #if defined(GDB_5_3) || defined(GDB_6_0) || defined(GDB_6_1) static int GPL_version = GPLv2; #else static int GPL_version = GPLv3; #endif static char *program_usage_info[] = { "", "USAGE:", "", " crash [OPTION]... NAMELIST MEMORY-IMAGE[@ADDRESS] (dumpfile form)", " crash [OPTION]... [NAMELIST] (live system form)", "", "OPTIONS:", "", " NAMELIST", " This is a pathname to an uncompressed kernel image (a vmlinux", " file), or a Xen hypervisor image (a xen-syms file) which has", " been compiled with the \"-g\" option. If using the dumpfile form,", " a vmlinux file may be compressed in either gzip or bzip2 formats.", "", " MEMORY-IMAGE", " A kernel core dump file created by the netdump, diskdump, LKCD", " kdump, xendump or kvmdump facilities.", "", " If a MEMORY-IMAGE argument is not entered, the session will be", " invoked on the live system, which typically requires root privileges", " because of the device file used to access system RAM. By default, ", " /dev/crash will be used if it exists. If it does not exist, then ", " /dev/mem will be used; but if the kernel has been configured with ", " CONFIG_STRICT_DEVMEM, then /proc/kcore will be used. It is permissible", " to explicitly enter /dev/crash, /dev/mem or /proc/kcore.", "", " An @ADDRESS value must be appended to the MEMORY-IMAGE if the dumpfile", " is a raw RAM dumpfile that has no header information describing the file", " contents. Multiple MEMORY-IMAGE@ADDRESS ordered pairs may be entered,", " with each dumpfile containing a contiguous block of RAM, where the ADDRESS", " value is the physical start address of the block expressed in hexadecimal.", " The physical address value(s) will be used to create a temporary ELF header", " in /var/tmp, which will only exist during the crash session. If a raw RAM", " dumpfile represents a live memory source, such as that specified by the QEMU", " mem-path argument of a memory-backend-file object, then \"live:\" must be", " prepended to the MEMORY-IMAGE name.", "", " mapfile", " If the NAMELIST file is not the same kernel that is running", " (live system form), or the kernel that was running when the system", " crashed (dumpfile form), then the System.map file of the original ", " kernel should be entered on the command line.", "", " -h [option]", " --help [option]", " Without an option argument, display a crash usage help message.", " If the option argument is a crash command name, the help page", " for that command is displayed. If it is the string \"input\", a", " page describing the various crash command line input options is", " displayed. If it is the string \"output\", a page describing command", " line output options is displayed. If it is the string \"all\", then", " all of the possible help messages are displayed. After the help", " message is displayed, crash exits.", "", " -s ", " Silently proceed directly to the \"crash>\" prompt without displaying", " any version, GPL, or crash initialization data during startup, and by", " default, runtime command output is not passed to any scrolling command.", "", " -i file", " Execute the command(s) contained in \"file\" prior to displaying ", " the \"crash>\" prompt for interactive user input.", "", " -d num ", " Set the internal debug level. The higher the number, the more", " debugging data will be printed when crash initializes and runs.", "", " -S ", " Use /boot/System.map as the mapfile.", "", " -e vi | emacs", " Set the readline(3) command line editing mode to \"vi\" or \"emacs\". ", " The default editing mode is \"vi\".", "", " -f ", " Force the usage of a compressed vmlinux file if its original", " name does not start with \"vmlinux\".", "", " -k ", " Indicate that the NAMELIST file is an LKCD \"Kerntypes\" debuginfo file.", "", " -g [namelist]", " Determine if a vmlinux or xen-syms namelist file contains debugging data.", "", " -t ", " Display the system-crash timestamp and exit.", "", " -L ", " Attempt to lock all of its virtual address space into memory by", " calling mlockall(MCL_CURRENT|MCL_FUTURE) during initialization.", " If the system call fails, an error message will be displayed,", " but the session continues.", "", " -c tty-device", " Open the tty-device as the console used for debug messages.", "", " -p page-size", " If a processor's page size cannot be determined by the dumpfile, ", " and the processor default cannot be used, use page-size.", "", " -o filename", " Only used with the MEMORY-IMAGE@ADDRESS format for raw RAM dumpfiles,", " specifies a filename of a new ELF vmcore that will be created and used", " as the dumpfile. It will be saved to allow future use as a standalone", " vmcore, replacing the original raw RAM dumpfile.", "", " -m option=value", " --machdep option=value", " Pass an option and value pair to machine-dependent code. These", " architecture-specific option/pairs should only be required in", " very rare circumstances:", "", " X86_64:", " phys_base=", " irq_eframe_link=", " irq_stack_gap=", " max_physmem_bits=", " kernel_image_size=", " vm=orig (pre-2.6.11 virtual memory address ranges)", " vm=2.6.11 (2.6.11 and later virtual memory address ranges)", " vm=xen (Xen kernel virtual memory address ranges)", " vm=xen-rhel4 (RHEL4 Xen kernel virtual address ranges)", " vm=5level (5-level page tables)", " page_offset=", " PPC64:", " vm=orig", " vm=2.6.14 (4-level page tables)", " IA64:", " phys_start=", " init_stack_size=", " vm=4l (4-level page tables)", " ARM:", " phys_base=", " ARM64:", " phys_offset=", " kimage_voffset=", " max_physmem_bits=", " vabits_actual=", " X86:", " page_offset=", "", " -x ", " Automatically load extension modules from a particular directory.", " The directory is determined by the following order of precedence:", "", " (1) the directory specified in the CRASH_EXTENSIONS shell ", " environment variable", " (2) /usr/lib64/crash/extensions (64-bit architectures)", " (3) /usr/lib/crash/extensions (32-bit architectures)", " (4) the ./extensions subdirectory of the current directory", "", " --active", " Track only the active task on each cpu.", "", " --buildinfo", " Display the crash binary's build date, the user ID of the builder,", " the hostname of the machine where the build was done, the target", " architecture, the version number, and the compiler version.", "", " --memory_module modname", " Use the modname as an alternative kernel module to the crash.ko", " module that creates the /dev/crash device.", "", " --memory_device device", " Use device as an alternative device to the /dev/crash, /dev/mem", " or /proc/kcore devices.", "", " --log dumpfile", " Dump the contents of the kernel log buffer. A kernel namelist", " argument is not necessary, but the dumpfile must contain the", " VMCOREINFO data taken from the original /proc/vmcore ELF header.", " Note: this option is deprecated and will no longer work for", " kernel(>=v5.10).", "", " --no_kallsyms", " Do not use kallsyms-generated symbol information contained within", " kernel module object files.", "", " --no_modules", " Do not access or display any kernel module related information.", "", " --no_ikconfig", " Do not attempt to read configuration data that was built into", " kernels configured with CONFIG_IKCONFIG.", "", " --no_data_debug", " Do not verify the validity of all structure member offsets and", " structure sizes that it uses.", "", " --no_kmem_cache", " Do not initialize the kernel's slab cache infrastructure, and", " commands that use kmem_cache-related data will not work.", "", " --no_elf_notes", " Do not use the registers from the ELF NT_PRSTATUS notes saved", " in a compressed kdump header for backtraces.", "", " --kmem_cache_delay", " Delay the initialization of the kernel's slab cache infrastructure", " until it is required by a run-time command.", "", " --readnow", " Pass this flag to the embedded gdb module, which will override", " the two-stage strategy that it uses for reading symbol tables", " from the NAMELIST. If module symbol tables are loaded during", " runtime with the \"mod\" command, the same override will occur.", "", " --smp ", " Specify that the system being analyzed is an SMP kernel.", "", " -v", " --version", " Display the version of the crash utility, the version of the", " embedded gdb module, GPL information, and copyright notices.", "", " --cpus number", " Specify the number of cpus in the SMP system being analyzed.", "", " --osrelease dumpfile", " Display the OSRELEASE vmcoreinfo string from a kdump dumpfile", " header.", "", " --hyper", " Force the session to be that of a Xen hypervisor.", "", " --p2m_mfn pfn", " When a Xen Hypervisor or its dom0 kernel crashes, the dumpfile", " is typically analyzed with either the Xen hypervisor or the dom0", " kernel. It is also possible to analyze any of the guest domU", " kernels if the pfn_to_mfn_list_list pfn value of the guest kernel", " is passed on the command line along with its NAMELIST and the ", " dumpfile.", "", " --xen_phys_start physical-address", " Supply the base physical address of the Xen hypervisor's text", " and static data for older xendump dumpfiles that did not pass", " that information in the dumpfile header.", "", " --zero_excluded", " If the makedumpfile(8) facility has filtered a compressed kdump", " dumpfile to exclude various types of non-essential pages, or has", " marked a compressed or ELF kdump dumpfile as incomplete due to", " an ENOSPC or other error during its creation, any attempt to", " read missing pages will fail. With this flag, reads from any", " of those pages will return zero-filled memory.", "", " --no_panic", " Do not attempt to find the task that was running when the kernel", " crashed. Set the initial context to that of the \"swapper\" task", " on cpu 0.", "", " --more ", " Use /bin/more as the command output scroller, overriding the", " default of /usr/bin/less and any settings in either ./.crashrc", " or $HOME/.crashrc.", "", " --less ", " Use /usr/bin/less as the command output scroller, overriding any", " settings in either ./.crashrc or $HOME/.crashrc.", "", " --CRASHPAGER", " Use the output paging command defined in the CRASHPAGER shell", " environment variable, overriding any settings in either ./.crashrc ", " or $HOME/.crashrc.", "", " --no_scroll", " Do not pass run-time command output to any scrolling command.", "", " --no_strip", " Do not strip cloned kernel text symbol names.", "", " --no_crashrc", " Do not execute the commands in either $HOME/.crashrc or ./.crashrc.", "", " --mod directory", " When loading the debuginfo data of kernel modules with the \"mod -S\"", " command, search for their object files in directory instead of in ", " the standard location.", "", " --src directory", " Search for the kernel source code in directory instead of in the", " standard location that is compiled into the debuginfo data.", "", " --reloc size", " When analyzing live x86 kernels configured with a CONFIG_PHYSICAL_START ", " value that is larger than its CONFIG_PHYSICAL_ALIGN value, then it will", " be necessary to enter a relocation size equal to the difference between", " the two values.", "", " --hash count", " Set the number of internal hash queue heads used for list gathering", " and verification. The default count is 32768.", "", " --kaslr offset | auto", " If x86, x86_64, s390x or loongarch64 kernel was configured with", " CONFIG_RANDOMIZE_BASE, the offset value is equal to the difference", " between the symbol values compiled into the vmlinux file and their", " relocated KASLR value. If set to auto, the KASLR offset value will", " be automatically calculated.", "", " --minimal", " Bring up a session that is restricted to the log, dis, rd, sym,", " eval, set and exit commands. This option may provide a way to", " extract some minimal/quick information from a corrupted or truncated", " dumpfile, or in situations where one of the several kernel subsystem ", " initialization routines would abort the crash session.", "", " --kvmhost [32|64]", " When examining an x86 KVM guest dumpfile, this option specifies", " that the KVM host that created the dumpfile was an x86 (32-bit)", " or an x86_64 (64-bit) machine, overriding the automatically", " determined value.", "", " --kvmio ", " override the automatically-calculated KVM guest I/O hole size.", "", " --offline [show|hide]", " Show or hide command output that is associated with offline cpus,", " overriding any settings in either ./.crashrc or $HOME/.crashrc.", "", "FILES:", "", " .crashrc", " Initialization commands. The file can be located in the user's", " HOME directory and/or the current directory. Commands found in", " the .crashrc file in the HOME directory are executed before", " those in the current directory's .crashrc file.", "", "ENVIRONMENT VARIABLES:", "", " EDITOR ", " Command input is read using readline(3). If EDITOR is set to", " emacs or vi then suitable keybindings are used. If EDITOR is", " not set, then vi is used. This can be overridden by \"set vi\" or", " \"set emacs\" commands located in a .crashrc file, or by entering", " \"-e emacs\" on the crash command line.", "", " CRASHPAGER", " If CRASHPAGER is set, its value is used as the name of the program", " to which command output will be sent. If not, then command output", " output is sent to \"/usr/bin/less -E -X\" by default.", "", " CRASH_MODULE_PATH", " Specifies an alternative directory tree to search for kernel", " module object files.", "", " CRASH_EXTENSIONS", " Specifies a directory containing extension modules that will be", " loaded automatically if the -x command line option is used.", "", NULL }; void program_usage(int form) { if (form == SHORT_FORM) { fprintf(fp, "\nUsage:\n\n"); fprintf(fp, "%s\n%s\n", program_usage_info[3], program_usage_info[4]); fprintf(fp, "\nEnter \"%s -h\" for details.\n", pc->program_name); clean_exit(1); } else { FILE *scroll; char *scroll_command; char **p; if ((scroll_command = setup_scroll_command()) && (scroll = popen(scroll_command, "w"))) fp = scroll; else scroll = NULL; for (p = program_usage_info; *p; p++) { fprintf(fp, *p, pc->program_name); fprintf(fp, "\n"); } fflush(fp); if (scroll) pclose(scroll); clean_exit(0); } } /* * Get an updated count of commands for subsequent help menu display, * reshuffling the deck if this is the first time or if something's changed. */ void help_init(void) { struct command_table_entry *cp; struct extension_table *ext; for (pc->ncmds = 0, cp = pc->cmd_table; cp->name; cp++) { if (!(cp->flags & HIDDEN_COMMAND)) pc->ncmds++; } for (ext = extension_table; ext; ext = ext->next) { for (cp = ext->command_table; cp->name; cp++) { if (!(cp->flags & (CLEANUP|HIDDEN_COMMAND))) pc->ncmds++; } } if (!pc->cmdlist) { pc->cmdlistsz = pc->ncmds; if ((pc->cmdlist = (char **) malloc(sizeof(char *) * pc->cmdlistsz)) == NULL) error(FATAL, "cannot malloc command list space\n"); } else if (pc->ncmds > pc->cmdlistsz) { pc->cmdlistsz = pc->ncmds; if ((pc->cmdlist = (char **)realloc(pc->cmdlist, sizeof(char *) * pc->cmdlistsz)) == NULL) error(FATAL, "cannot realloc command list space\n"); } reshuffle_cmdlist(); } /* * If the command list is modified during runtime, re-shuffle the list * for proper help menu display. */ static void reshuffle_cmdlist(void) { int i, cnt; struct command_table_entry *cp; struct extension_table *ext; for (i = 0; i < pc->cmdlistsz; i++) pc->cmdlist[i] = NULL; for (cnt = 0, cp = pc->cmd_table; cp->name; cp++) { if (!(cp->flags & HIDDEN_COMMAND)) pc->cmdlist[cnt++] = cp->name; } for (ext = extension_table; ext; ext = ext->next) { for (cp = ext->command_table; cp->name; cp++) { if (!(cp->flags & (CLEANUP|HIDDEN_COMMAND))) pc->cmdlist[cnt++] = cp->name; } } if (cnt > pc->cmdlistsz) error(FATAL, "help table malfunction!\n"); qsort((void *)pc->cmdlist, (size_t)cnt, sizeof(char *), sort_command_name); } /* * The help list is in alphabetical order, with exception of the "q" command, * which has historically always been the last command in the list. */ static int sort_command_name(const void *name1, const void *name2) { char **s1, **s2; s1 = (char **)name1; s2 = (char **)name2; if (STREQ(*s1, "q")) return 1; return strcmp(*s1, *s2); } /* * Get help for a command, to dump an internal table, or the GNU public * license copying/warranty information. */ void cmd_help(void) { int c; int oflag; oflag = 0; while ((c = getopt(argcnt, args, "efNDdmM:ngcaBbHhkKsvVoptTzLOr")) != EOF) { switch(c) { case 'e': dump_extension_table(VERBOSE); return; case 'f': dump_filesys_table(VERBOSE); return; case 'n': case 'D': dumpfile_memory(DUMPFILE_MEM_DUMP); return; case 'd': dump_dev_table(); return; case 'M': dump_machdep_table(stol(optarg, FAULT_ON_ERROR, NULL)); return; case 'm': dump_machdep_table(0); return; case 'g': dump_gdb_data(); return; case 'N': dump_net_table(); return; case 'a': dump_alias_data(); return; case 'b': dump_shared_bufs(); return; case 'B': dump_build_data(); return; case 'c': dump_numargs_cache(); return; case 'H': dump_hash_table(VERBOSE); return; case 'h': dump_hash_table(!VERBOSE); return; case 'k': dump_kernel_table(!VERBOSE); return; case 'K': dump_kernel_table(VERBOSE); return; case 's': dump_symbol_table(); return; case 'V': dump_vm_table(VERBOSE); return; case 'v': dump_vm_table(!VERBOSE); return; case 'O': dump_offset_table(NULL, TRUE); return; case 'o': oflag = TRUE; break; case 'T': dump_task_table(VERBOSE); return; case 't': dump_task_table(!VERBOSE); return; case 'p': dump_program_context(); return; case 'z': fprintf(fp, "help options:\n"); fprintf(fp, " -a - alias data\n"); fprintf(fp, " -b - shared buffer data\n"); fprintf(fp, " -B - build data\n"); fprintf(fp, " -c - numargs cache\n"); fprintf(fp, " -d - device table\n"); fprintf(fp, " -D - dumpfile contents/statistics\n"); fprintf(fp, " -e - extension table data\n"); fprintf(fp, " -f - filesys table\n"); fprintf(fp, " -g - gdb data\n"); fprintf(fp, " -h - hash_table data\n"); fprintf(fp, " -H - hash_table data (verbose)\n"); fprintf(fp, " -k - kernel_table\n"); fprintf(fp, " -K - kernel_table (verbose)\n"); fprintf(fp, " -L - LKCD page cache environment\n"); fprintf(fp, " -M machine specific\n"); fprintf(fp, " -m - machdep_table\n"); fprintf(fp, " -N - net_table\n"); fprintf(fp, " -n - dumpfile contents/statistics\n"); fprintf(fp, " -o - offset_table and size_table\n"); fprintf(fp, " -p - program_context\n"); fprintf(fp, " -r - dump registers from dumpfile header\n"); fprintf(fp, " -s - symbol table data\n"); fprintf(fp, " -t - task_table\n"); fprintf(fp, " -T - task_table plus context_array\n"); fprintf(fp, " -v - vm_table\n"); fprintf(fp, " -V - vm_table (verbose)\n"); fprintf(fp, " -z - help options\n"); return; case 'L': dumpfile_memory(DUMPFILE_ENVIRONMENT); return; case 'r': dump_registers(); return; default: argerrs++; break; } } if (argerrs) cmd_usage(pc->curcmd, COMPLETE_HELP); if (!args[optind]) { if (oflag) dump_offset_table(NULL, FALSE); else display_help_screen(""); return; } do { if (oflag) dump_offset_table(args[optind], FALSE); else cmd_usage(args[optind], COMPLETE_HELP|MUST_HELP); optind++; } while (args[optind]); } static void dump_registers(void) { if (pc->flags2 & QEMU_MEM_DUMP_ELF) { dump_registers_for_qemu_mem_dump(); return; } else if (DISKDUMP_DUMPFILE()) { dump_registers_for_compressed_kdump(); return; } else if (NETDUMP_DUMPFILE() || KDUMP_DUMPFILE()) { dump_registers_for_elf_dumpfiles(); return; } else if (VMSS_DUMPFILE()) { dump_registers_for_vmss_dump(); return; } error(FATAL, "-r option not supported on %s\n", ACTIVE() ? "a live system" : "this dumpfile type"); } /* * Format and display the help menu. */ void display_help_screen(char *indent) { int i, j, rows; char **namep; help_init(); fprintf(fp, "\n%s", indent); rows = (pc->ncmds + (HELP_COLUMNS-1)) / HELP_COLUMNS; for (i = 0; i < rows; i++) { namep = &pc->cmdlist[i]; for (j = 0; j < HELP_COLUMNS; j++) { fprintf(fp,"%-15s", *namep); namep += rows; if ((namep - pc->cmdlist) >= pc->ncmds) break; } fprintf(fp,"\n%s", indent); } fprintf(fp, "\n%s%s version: %-6s gdb version: %s\n", indent, pc->program_name, pc->program_version, pc->gdb_version); fprintf(fp, "%sFor help on any command above, enter \"help \".\n", indent); fprintf(fp, "%sFor help on input options, enter \"help input\".\n", indent); fprintf(fp, "%sFor help on output options, enter \"help output\".\n", indent); #ifdef NO_LONGER_TRUE fprintf(fp, "%sFor the most recent version: " "http://www.missioncriticallinux.com/download\n\n", indent); #else fprintf(fp, "\n"); #endif } /* * Used for generating HTML pages, dump the commands in the order * they would be seen on the help menu, i.e., from left-to-right, row-by-row. * Line ends are signaled with a "BREAK" string. */ static void display_commands(void) { int i, j, rows; char **namep; help_init(); rows = (pc->ncmds + (HELP_COLUMNS-1)) / HELP_COLUMNS; for (i = 0; i < rows; i++) { namep = &pc->cmdlist[i]; for (j = 0; j < HELP_COLUMNS; j++) { fprintf(fp,"%s\n", *namep); namep += rows; if ((namep - pc->cmdlist) >= pc->ncmds) { fprintf(fp, "BREAK\n"); break; } } } } /* * Help data for a command must be formatted using the following template: "command-name", "command description line", "argument-usage line", "description...", "description...", "description...", NULL, * The first line is concatenated with the second line, and will follow the * help command's "NAME" header. * The first and third lines will also be concatenated, and will follow the * help command's "SYNOPSIS" header. If the command has no arguments, enter * a string consisting of a space, i.e., " ". * The fourth and subsequent lines will follow the help command's "DESCRIPTION" * header. * * The program name can be referenced by using the %%s format. The final * entry in each command's help data string list must be a NULL. */ char *help_foreach[] = { "foreach", "display command data for multiple tasks in the system", "[[pid | taskp | name | state | [kernel | user | gleader]] ...]\n" " command [flag] [argument]", " This command allows for an examination of various kernel data associated", " with any, or all, tasks in the system, without having to set the context", " to each targeted task.\n", " pid perform the command(s) on this PID.", " taskp perform the command(s) on task referenced by this hexadecimal", " task_struct pointer.", " name perform the command(s) on all tasks with this name. If the", " task name can be confused with a foreach command name, then", " precede the name string with a \"\\\". If the name string is", " enclosed within \"'\" characters, then the encompassed string", " must be a POSIX extended regular expression that will be used", " to match task names.", " user perform the command(s) on all user (non-kernel) threads.", " gleader perform the command(s) on all user (non-kernel) thread group leaders.", " kernel perform the command(s) on all kernel threads.", " active perform the command(s) on the active thread on each CPU.", " state perform the command(s) on all tasks in the specified state, which", " may be one of: RU, IN, UN, ST, ZO, TR, SW, DE, WA, PA, ID or NE.\n", " If none of the task-identifying arguments above are entered, the command", " will be performed on all tasks.\n", " command select one or more of the following commands to be run on the tasks", " selected, or on all tasks:\n", " bt run the \"bt\" command (optional flags: -r -t -l -e -R -f -F", " -o -s -x -d)", " vm run the \"vm\" command (optional flags: -p -v -m -R -d -x)", " task run the \"task\" command (optional flags: -R -d -x)", " files run the \"files\" command (optional flag: -c -R)", " net run the \"net\" command (optional flags: -s -S -R -d -x)", " set run the \"set\" command", " ps run the \"ps\" command (optional flags: -G -s -p -c -t -l -a", " -g -r -y)", " sig run the \"sig\" command (optional flag: -g)", " vtop run the \"vtop\" command (optional flags: -c -u -k)\n", " flag Pass this optional flag to the command selected.", " argument Pass this argument to the command selected.", " ", " A header containing the PID, task address, cpu and command name will be", " pre-pended before the command output for each selected task. Consult the", " help page of each of the command types above for details.", "\nEXAMPLES", " Display the stack traces for all tasks:\n", " %s> foreach bt", " PID: 4752 TASK: c7680000 CPU: 1 COMMAND: \"xterm\"", " #0 [c7681edc] schedule at c01135f6", " (void)", " #1 [c7681f34] schedule_timeout at c01131ff", " (24)", " #2 [c7681f64] do_select at c0132838", " (5, c7681fa4, c7681fa0)", " #3 [c7681fbc] sys_select at c0132dad", " (5, 8070300, 8070380, 0, 0)", " #4 [bffffb0c] system_call at c0109944", " EAX: 0000008e EBX: 00000005 ECX: 08070300 EDX: 08070380 ", " DS: 002b ESI: 00000000 ES: 002b EDI: 00000000 ", " SS: 002b ESP: bffffadc EBP: bffffb0c ", " CS: 0023 EIP: 402259ee ERR: 0000008e EFLAGS: 00000246 ", " ", " PID: 557 TASK: c5600000 CPU: 0 COMMAND: \"nfsd\"", " #0 [c5601f38] schedule at c01135f6", " (void)", " #1 [c5601f90] schedule_timeout at c01131ff", " (c5600000)", " #2 [c5601fb8] svc_recv at c805363a", " (c0096f40, c5602800, 7fffffff, 100, c65c9f1c)", " #3 [c5601fec] (nfsd module) at c806e303", " (c5602800, c5602800, c0096f40, 6c6e0002, 50)", " #4 [c65c9f24] kernel_thread at c010834f", " (0, 0, ext2_file_inode_operations)", " ", " PID: 824 TASK: c7c84000 CPU: 0 COMMAND: \"mingetty\"", " ...\n", " Display the task_struct structure for each \"bash\" command:\n", " %s> foreach bash task", " ...\n", " Display the open files for all tasks:\n", " %s> foreach files", " ...\n", " Display the state of tasks whose name contains a match to \"event.*\":\n", " %s> foreach 'event.*' task -R state", " PID: 99 TASK: ffff8804750d5500 CPU: 0 COMMAND: \"events/0\"", " state = 1,", " ", " PID: 100 TASK: ffff8804750d4ac0 CPU: 1 COMMAND: \"events/1\"", " state = 1,", " ", " PID: 101 TASK: ffff8804750d4080 CPU: 2 COMMAND: \"events/2\"", " state = 1,", " ...\n", " Display the stack traces for all blocked (TASK_UNINTERRUPTIBLE) tasks:\n", " %s> foreach UN bt", " PID: 428 TASK: ffff880036b6c560 CPU: 1 COMMAND: \"jbd2/dm-1-8\"", " #0 [ffff880035779a70] __schedule at ffffffff815df272", " #1 [ffff880035779b08] schedule at ffffffff815dfacf", " #2 [ffff880035779b18] io_schedule at ffffffff815dfb7f", " #3 [ffff880035779b38] sleep_on_page at ffffffff81119a4e", " #4 [ffff880035779b48] __wait_on_bit at ffffffff815e039f", " #5 [ffff880035779b98] wait_on_page_bit at ffffffff81119bb8", " #6 [ffff880035779be8] filemap_fdatawait_range at ffffffff81119ccc", " #7 [ffff880035779cd8] filemap_fdatawait at ffffffff81119d8b", " #8 [ffff880035779ce8] jbd2_journal_commit_transaction at ffffffff8123a99c", " #9 [ffff880035779e58] kjournald2 at ffffffff8123ee7b", " #10 [ffff880035779ee8] kthread at ffffffff8108fb9c", " #11 [ffff880035779f48] kernel_thread_helper at ffffffff815ebaf4", " ...\n", NULL }; char *help_ascii[] = { "ascii", "translate a hexadecimal string to ASCII", "value ...", " Translates 32-bit or 64-bit hexadecimal values to ASCII. If no argument", " is entered, an ASCII chart is displayed.", "\nEXAMPLES", " Translate the hexadecimal value of 0x62696c2f7273752f to ASCII:", "\n %s> ascii 62696c2f7273752f", " 62696c2f7273752f: /usr/lib", "\n Display an ASCII chart:", "\n %s> ascii", " ", " 0 1 2 3 4 5 6 7", " +-------------------------------", " 0 | NUL DLE SP 0 @ P ' p", " 1 | SOH DC1 ! 1 A Q a q", " 2 | STX DC2 \" 2 B R b r", " 3 | ETX DC3 # 3 C S c s", " 4 | EOT DC4 $ 4 D T d t", " 5 | ENQ NAK \% 5 E U e u", " 6 | ACK SYN & 6 F V f v", " 7 | BEL ETB ` 7 G W g w", " 8 | BS CAN ( 8 H X h x", " 9 | HT EM ) 9 I Y i y", " A | LF SUB * : J Z j z", " B | VT ESC + ; K [ k {", " C | FF FS , < L \\ l |", " D | CR GS _ = M ] m }", " E | SO RS . > N ^ n ~", " F | SI US / ? O - o DEL", NULL }; char *help_sbitmapq[] = { "sbitmapq", "sbitmap_queue struct contents", "[-s struct[.member[,member]] -a address [-p] [-v]] -[x|d] address", " The command dumps the contents of the sbitmap_queue structure and", " the used bits in the bitmap. Also, it shows the dump of a structure", " array associated with the sbitmap_queue.", "", " The arguments are as follows:", "", " -s struct name of a C-code structure, that is stored in an array", " associated with sbitmap_queue structure. Use the", " \"struct.member\" format in order to display a particular", " member of the structure. -s option requires -a option", " -a address address of a structure array associated with sbitmap_queue", " structure. The set bits in sbitmap are used for the index", " in an associated array.", " -p associated with sbitmap_queue array contains the points of", " structure.", " -x override default output format with hexadecimal format.", " -d override default output format with decimal format.", " -v By default, the sbitmap command shows only a used sbitmap", " index and a structure address in the associated array.", " This flag says to print a formatted display of the", " contents of a structure in an associated array. -v option", " requires of -s.", "", "EXAMPLES", "", " All examples are shown on the base of Linux Target system with iSCSI", " transport.", "", " Display the common sbitmap information for target session:", "", " %s> struct -oh se_session 0xc0000000e118c760 | grep sbitmap_queue", " [c0000000e118c808] struct sbitmap_queue sess_tag_pool;", " %s>", " %s> sbitmapq c0000000e118c808", " depth = 136", " busy = 4", " cleared = 26", " bits_per_word = 32", " map_nr = 5", " alloc_hint = {74, 36, 123, 101}", " wake_batch = 8", " wake_index = 0", " ws_active = 0", " ws = {", " { .wait_cnt = 8, .wait = inactive },", " { .wait_cnt = 8, .wait = inactive },", " { .wait_cnt = 8, .wait = inactive },", " { .wait_cnt = 8, .wait = inactive },", " { .wait_cnt = 8, .wait = inactive },", " { .wait_cnt = 8, .wait = inactive },", " { .wait_cnt = 8, .wait = inactive },", " { .wait_cnt = 8, .wait = inactive },", " }", " round_robin = 0", " min_shallow_depth = 4294967295", "", " 00000000: 0000 0000 0000 0000 0030 0000 0000 0000", " 00000010: 00", "", " Display the addresses of structure are associated with", " sbitmap_queue (for iscsi it is 'iscsi_cmd' structure):", "", " %s> struct se_session 0xc0000000e118c760 | grep sess_cmd_map", " sess_cmd_map = 0xc0000000671c0000,", " %s>", " %s> sbitmapq -s iscsi_cmd -a 0xc0000000671c0000 c0000000e118c808", " 76: 0xc0000000671d5600", " 77: 0xc0000000671d5a80", "", " Dump of formatted content of structures:", "", " %s> sbitmapq -s iscsi_cmd -a 0xc0000000671c0000 -v c0000000e118c808", " 76 (0xc0000000671d5600):", " struct iscsi_cmd {", " dataout_timer_flags = 0,", " dataout_timeout_retries = 0 '\\000',", " error_recovery_count = 0 '\\000',", " deferred_i_state = ISTATE_NO_STATE,", " i_state = ISTATE_SENT_STATUS,", " ...", " first_data_sg = 0xc0000000e306b080,", " first_data_sg_off = 0,", " kmapped_nents = 1,", " sense_reason = 0", " }", " 77 (0xc0000000671d5a80):", " struct iscsi_cmd {", " dataout_timer_flags = 0,", " dataout_timeout_retries = 0 '\\000',", " error_recovery_count = 0 '\\000',", " deferred_i_state = ISTATE_NO_STATE,", " i_state = ISTATE_NEW_CMD,", " ...", " first_data_sg = 0x0,", " first_data_sg_off = 0,", " kmapped_nents = 0,", " sense_reason = 0", " }", NULL }; char *help_quit[] = { "quit", "exit this session", " ", " Bail out of the current %s session.", "\nNOTE", " This command is equivalent to the \"exit\" command.", NULL }; char *help_exit[] = { "exit", "exit this session", " ", " Bail out of the current %s session.", "\nNOTE", " This command is equivalent to the \"q\" command.", NULL }; char *help_help[] = { "help", "get help", "[command | all] [-