From patchwork Mon Mar 12 15:31:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Rudo X-Patchwork-Id: 26290 Received: (qmail 5438 invoked by alias); 12 Mar 2018 15:31:39 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 5315 invoked by uid 89); 12 Mar 2018 15:31:38 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.3 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, KAM_SHORT, RCVD_IN_DNSWL_LOW autolearn=ham version=3.3.2 spammy=crude X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0b-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.158.5) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 12 Mar 2018 15:31:34 +0000 Received: from pps.filterd (m0098420.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.22/8.16.0.22) with SMTP id w2CFTq4X086606 for ; Mon, 12 Mar 2018 11:31:32 -0400 Received: from e06smtp15.uk.ibm.com (e06smtp15.uk.ibm.com [195.75.94.111]) by mx0b-001b2d01.pphosted.com with ESMTP id 2gnsfkramx-1 (version=TLSv1.2 cipher=AES256-SHA256 bits=256 verify=NOT) for ; Mon, 12 Mar 2018 11:31:29 -0400 Received: from localhost by e06smtp15.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 12 Mar 2018 15:31:27 -0000 Received: from b06cxnps4075.portsmouth.uk.ibm.com (9.149.109.197) by e06smtp15.uk.ibm.com (192.168.101.145) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 12 Mar 2018 15:31:24 -0000 Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps4075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id w2CFVOPV55640076; Mon, 12 Mar 2018 15:31:24 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 989F952043; Mon, 12 Mar 2018 14:22:56 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTPS id 621AF5204B; Mon, 12 Mar 2018 14:22:56 +0000 (GMT) From: Philipp Rudo To: gdb-patches@sourceware.org Cc: Omair Javaid , Yao Qi , arnez@linux.vnet.ibm.com Subject: [RFC PATCH v5 6/9] Add commands for linux-kernel target Date: Mon, 12 Mar 2018 16:31:12 +0100 In-Reply-To: <20180312153115.47321-1-prudo@linux.vnet.ibm.com> References: <20180312153115.47321-1-prudo@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 x-cbid: 18031215-0020-0000-0000-000004026C8E X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 18031215-0021-0000-0000-00004296BDD2 Message-Id: <20180312153115.47321-7-prudo@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2018-03-12_09:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 priorityscore=1501 malwarescore=0 suspectscore=43 phishscore=0 bulkscore=0 spamscore=0 clxscore=1015 lowpriorityscore=0 impostorscore=0 adultscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1709140000 definitions=main-1803120176 X-IsSubscribed: yes This patch implements a "lsmod", "struct" and, "offset" command to work with the new linux-kernel target. The commands are a handy byproduct from development and crude hacks. I don't expect them to be accepted in the current state. Nevertheless there needs to be an discussion on how and where (see gdb/python scrips in kernel sources) to implement them. So here is the start for it. gdb/Changelog: * lk-cmds.h: New file. * lk-cmds.c: New file. * lk-low.c: Include lk-cmds.h. (lk_try_push_target): Init commands. * typeprint.c: Remove unnecessary forward declarations. (whatis_exp): Remove static. * typeprint.h (whatis_exp): New export. * Makefile.in (SFILES, ALLDEPFILES): Add lk-cmds.c. (HFILES_NO_SRCDIR): Add lk-cmds.h. (ALL_TARGET_OBS): Add lk-cmds.o. * configure.tgt (lk_target_obs): Add lk-cmds.o. --- gdb/Makefile.in | 3 + gdb/configure.tgt | 2 +- gdb/lk-cmds.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/lk-cmds.h | 25 ++++++ gdb/lk-low.c | 3 + gdb/typeprint.c | 2 +- gdb/typeprint.h | 2 + 7 files changed, 289 insertions(+), 2 deletions(-) create mode 100644 gdb/lk-cmds.c create mode 100644 gdb/lk-cmds.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index afa8039a95..2029c933af 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -715,6 +715,7 @@ ALL_TARGET_OBS = \ iq2000-tdep.o \ linux-record.o \ linux-tdep.o \ + lk-cmds.o \ lk-low.o \ lk-modules.o \ lm32-tdep.o \ @@ -1278,6 +1279,7 @@ HFILES_NO_SRCDIR = \ linux-nat.h \ linux-record.h \ linux-tdep.h \ + lk-cmds.h \ lk-low.h \ lk-modules.h \ location.h \ @@ -2260,6 +2262,7 @@ ALLDEPFILES = \ linux-fork.c \ linux-record.c \ linux-tdep.c \ + lk-cmds.c \ lk-low.c \ lk-modules.c \ lm32-tdep.c \ diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 39b2144e00..680b3b2e42 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -42,7 +42,7 @@ amd64_tobjs="amd64-tdep.o arch/amd64.o" # List of objectfiles for Linux kernel support. To be included into *-linux* # targets wich support Linux kernel debugging. -lk_tobjs="lk-low.o lk-modules.o" +lk_tobjs="lk-cmds.o lk-low.o lk-modules.o" # Here are three sections to get a list of target specific object # files according to target triplet $TARG. diff --git a/gdb/lk-cmds.c b/gdb/lk-cmds.c new file mode 100644 index 0000000000..4046077e2b --- /dev/null +++ b/gdb/lk-cmds.c @@ -0,0 +1,254 @@ +/* Commands for Linux kernel target. + + Copyright (C) 2016 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include "defs.h" + +#include "cli/cli-decode.h" +#include "gdbcore.h" +#include "gdbtypes.h" +#include "inferior.h" +#include "lk-list.h" +#include "lk-low.h" +#include "lk-modules.h" +#include "typeprint.h" +#include "valprint.h" + + +static bool +lk_lsmod_print_name (struct ui_out *uiout, CORE_ADDR mod) +{ + char name[LK_MODULE_NAME_LEN + 2]; + bool loaded; + + read_memory_string (mod + lk_offset ("module->name"), name + 1, + LK_MODULE_NAME_LEN); + loaded = lk_modules_debug_info_loaded (name + 1); + name[0] = loaded ? ' ' : '*' ; + name[LK_MODULE_NAME_LEN + 1] = '\0'; + uiout->field_string ("module", name); + + return loaded; +} + +static void +lk_lsmod_print_size (struct ui_out *uiout, CORE_ADDR mod) +{ + size_t size; + + if (lk_ops->has_field ("module->module_core")) + { + size = lk_read_uint (mod + lk_offset ("module->init_size")); + size += lk_read_uint (mod + lk_offset ("module->core_size")); + } + else + { + size = lk_read_uint (mod + lk_offset ("module->init_layout->size")); + size += lk_read_uint (mod + lk_offset ("module->core_layout->size")); + } + + uiout->field_int ("size", size); +} + + +static void +lk_lsmod_print_sources (struct ui_out *uiout, CORE_ADDR mod) +{ + CORE_ADDR src_list; + int num_sources = 0; + std::string sources; + + src_list = mod + lk_offset ("module->source_list"); + for (CORE_ADDR src : lk_list (src_list, "module_use->source_list", false)) + { + char buf[LK_MODULE_NAME_LEN + 1]; + + if (!sources.empty ()) + sources += ", "; + + src = lk_read_addr (src + lk_offset ("module_use->source")); + read_memory_string (src + lk_offset ("module->name"), + buf, LK_MODULE_NAME_LEN); + + sources += buf; + } + + uiout->field_int ("src_num", num_sources); + uiout->field_string ("src_list", sources.c_str ()); +} + +/* Print line for module MOD to UIOUT for lsmod command. */ + +static bool +lk_lsmod_print_single_module (struct ui_out *uiout, CORE_ADDR mod) +{ + bool loaded; + + ui_out_emit_tuple tuple_emitter (uiout, NULL); + + uiout->field_fmt ("addr", "0x%s", + phex(mod, lk_builtin_type_size (unsigned_long))); + loaded = lk_lsmod_print_name (uiout, mod); + lk_lsmod_print_size (uiout, mod); + lk_lsmod_print_sources (uiout, mod); + uiout->text ("\n"); + + return loaded; +} + +/* Print information about loaded kernel modules. Output equivalent to + lsmod, but also prints the address of the corrensponfing struct module. + Marks modules with missing debug info with an asterix '*'. */ + +static void +lk_lsmod (const char *args, int from_tty) +{ + if (!lk_ifdef (LK_CONFIG_MODULES)) + { + printf_unfiltered (_("Kernel was compiled without module support.\n")); + return; + } + + struct ui_out *uiout = current_uiout; + ui_out_emit_table table_emitter (uiout, 5, -1, "ModuleTable"); + uiout->table_header (14, ui_left, "addr", "ADDR"); + uiout->table_header (20, ui_left, "module", "Module"); + uiout->table_header (7, ui_right, "size", "Size"); + uiout->table_header (4, ui_right, "src_num", ""); + uiout->table_header (40, ui_left, "src_list", "Used by"); + + uiout->table_body (); + + bool all_loaded = true; + for (CORE_ADDR mod : lk_list ("modules", "module->list")) + all_loaded &= lk_lsmod_print_single_module (uiout, mod); + + if (!all_loaded) + uiout->text ("(*) Missing debug info for module.\n"); +} + +static void +lk_print_struct (const char *args_, int from_tty) +{ + struct format_data fmt; + size_t pos; + print_command_parse_format ((const char **) &args_, "print", &fmt); + + if (!args_) + return; + + std::string args (args_); + /* No address given default to behave like ptype. */ + if ((pos = args.find (" ")) == std::string::npos) + { + args = "struct " + args; + char *tmp = xstrdup (args.c_str ()); + whatis_exp (tmp, 1); + xfree (tmp); + return; + } + + + std::string type = args.substr (0, pos); + std::string addr = args.substr (args.find_first_not_of (" ", pos)); + + if ((pos = type.find ("."))!= std::string::npos) + { + std::string field = type.substr (pos + 1); + type = type.substr (0, pos); + args = "((struct " + type + " *) " + addr + ")->" + field; + } + else if ((pos = type.find ("->"))!= std::string::npos) + { + std::string field = type.substr (pos + 2); + type = type.substr (0, pos); + args = "((struct " + type + " *) " + addr + ")->" + field; + } + else + args = "*(struct " + type + " *) " + addr; + + expression_up expr = parse_expression (args.c_str ()); + struct value *val = evaluate_expression (expr.get ()); + + print_value (val, &fmt); +} + +static void +lk_print_offset (const char *args_, int from_tty) +{ + std::string args (args_); + std::string type, field; + size_t pos; + + if ((pos = args.find ('.')) != std::string::npos) + { + type = "struct " + args.substr (0, pos); + field = args.substr (pos + 1); + } + else if ((pos = args.find ("->")) != std::string::npos) + { + type = "struct " + args.substr (0, pos); + field = args.substr (pos + 2); + } + else + return; + + expression_up expr = parse_expression (type.c_str ()); + struct type *tp = value_type (evaluate_type (expr.get ())); + + struct field *first = TYPE_FIELDS (tp); + struct field *last = first + TYPE_NFIELDS (tp); + + for (; first != last; first++) + if (field.compare (first->name) == 0) + break; + + if (first == last) + return; + + size_t offset = FIELD_BITPOS (*first); + + if (offset % TARGET_CHAR_BIT) + printf_unfiltered ("offset = %lu + %lu\n", offset / 8, offset % TARGET_CHAR_BIT); + else + printf_unfiltered ("offset = %lu\n", offset / 8); +} + + +void +lk_init_cmds () +{ + add_com ("lsmod", class_vars, lk_lsmod, "\n\ + lsmod\n\n\ +List kernel modules as known by the kernel. The address belongs to the \ +corresponding struct module. \ +"); + + add_com ("struct", class_vars, lk_print_struct, "\n\ + struct .
\n\n\ +Print content of field in structure for structure located\n\ +at address
. If no field is given prints entire content of\n\ +. If neither nor
is given prints type definition\n\ +of (equivalent to ptype).\ +"); + + add_com ("offset", class_vars, lk_print_offset, "\n\ + offset .\n\n\ +Print offset of field in structure in byte (+ bit for bit fields).\n\ +"); +} diff --git a/gdb/lk-cmds.h b/gdb/lk-cmds.h new file mode 100644 index 0000000000..63e424636d --- /dev/null +++ b/gdb/lk-cmds.h @@ -0,0 +1,25 @@ +/* Commands for Linux kernel target. + + Copyright (C) 2016 Free Software Foundation, Inc. + + This file is part of GDB. + + 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 3 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. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#ifndef __LK_CMDS_H__ +#define __LK_CMDS_H__ + +extern void lk_init_cmds (); + +#endif /* __LK_CMDS_H__ */ diff --git a/gdb/lk-low.c b/gdb/lk-low.c index 54d3b6272d..c61361b687 100644 --- a/gdb/lk-low.c +++ b/gdb/lk-low.c @@ -28,6 +28,7 @@ #include "gdbtypes.h" #include "inferior.h" #include "lk-bitmap.h" +#include "lk-cmds.h" #include "lk-list.h" #include "lk-low.h" #include "lk-modules.h" @@ -821,6 +822,8 @@ lk_try_push_target () else warning (_("Could not find all symbols for module support. " "Module support turned off.")); + + lk_init_cmds (); } /* Function for targets to_open hook. */ diff --git a/gdb/typeprint.c b/gdb/typeprint.c index c098a3f426..3121fffbf7 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -402,7 +402,7 @@ error_unknown_type (const char *sym_print_name) /* Print type of EXP, or last thing in value history if EXP == NULL. show is passed to type_print. */ -static void +void whatis_exp (const char *exp, int show) { struct value *val; diff --git a/gdb/typeprint.h b/gdb/typeprint.h index ba9588a118..df96e35a53 100644 --- a/gdb/typeprint.h +++ b/gdb/typeprint.h @@ -107,4 +107,6 @@ extern void val_print_not_allocated (struct ui_file *stream); extern void val_print_not_associated (struct ui_file *stream); +extern void whatis_exp (const char *exp, int show); + #endif