From patchwork Thu Jan 12 11:32:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Philipp Rudo X-Patchwork-Id: 18873 Received: (qmail 109789 invoked by alias); 12 Jan 2017 11:32:36 -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 109675 invoked by uid 89); 12 Jan 2017 11:32:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.1 required=5.0 tests=AWL, BAYES_20, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=sk:read_me, inferiorh, inferior.h, UD:inferior.h 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; Thu, 12 Jan 2017 11:32:30 +0000 Received: from pps.filterd (m0098420.ppops.net [127.0.0.1]) by mx0b-001b2d01.pphosted.com (8.16.0.17/8.16.0.17) with SMTP id v0CBSt5R055326 for ; Thu, 12 Jan 2017 06:32:28 -0500 Received: from e06smtp13.uk.ibm.com (e06smtp13.uk.ibm.com [195.75.94.109]) by mx0b-001b2d01.pphosted.com with ESMTP id 27x4812c82-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Thu, 12 Jan 2017 06:32:28 -0500 Received: from localhost by e06smtp13.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 12 Jan 2017 11:32:26 -0000 Received: from d06dlp03.portsmouth.uk.ibm.com (9.149.20.15) by e06smtp13.uk.ibm.com (192.168.101.143) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 12 Jan 2017 11:32:24 -0000 Received: from b06cxnps4076.portsmouth.uk.ibm.com (d06relay13.portsmouth.uk.ibm.com [9.149.109.198]) by d06dlp03.portsmouth.uk.ibm.com (Postfix) with ESMTP id 02F981B08061; Thu, 12 Jan 2017 11:35:06 +0000 (GMT) Received: from d06av21.portsmouth.uk.ibm.com (d06av21.portsmouth.uk.ibm.com [9.149.105.232]) by b06cxnps4076.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v0CBWOKs27984068; Thu, 12 Jan 2017 11:32:24 GMT Received: from d06av21.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id B01FB52049; Thu, 12 Jan 2017 10:30:53 +0000 (GMT) Received: from tuxmaker.boeblingen.de.ibm.com (unknown [9.152.85.9]) by d06av21.portsmouth.uk.ibm.com (Postfix) with ESMTPS id 81CBB52043; Thu, 12 Jan 2017 10:30:53 +0000 (GMT) From: Philipp Rudo To: gdb-patches@sourceware.org Cc: peter.griffin@linaro.org, yao.qi@arm.com, arnez@linux.vnet.ibm.com Subject: [RFC 5/7] Add commands for linux-kernel target Date: Thu, 12 Jan 2017 12:32:15 +0100 In-Reply-To: <20170112113217.48852-1-prudo@linux.vnet.ibm.com> References: <20170112113217.48852-1-prudo@linux.vnet.ibm.com> X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 17011211-0012-0000-0000-000004B61C44 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17011211-0013-0000-0000-000016DF2CA4 Message-Id: <20170112113217.48852-6-prudo@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-01-12_08:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=43 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1701120162 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. (COMMON_OBS): Add lk-cmds.o. --- gdb/Makefile.in | 4 + gdb/lk-cmds.c | 248 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ gdb/lk-cmds.h | 25 ++++++ gdb/lk-low.c | 3 + gdb/typeprint.c | 8 +- gdb/typeprint.h | 2 + 6 files changed, 283 insertions(+), 7 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 be8a91d..10dce6a 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -1092,6 +1092,7 @@ SFILES = \ jit.c \ language.c \ linespec.c \ + lk-cmds.c \ lk-lists.c \ lk-low.c \ lk-modules.c \ @@ -1341,6 +1342,7 @@ HFILES_NO_SRCDIR = \ linux-nat.h \ linux-record.h \ linux-tdep.h \ + lk-cmds.h \ lk-lists.h \ lk-low.h \ lk-modules.h \ @@ -1702,6 +1704,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $(YYOBJ) \ jit.o \ language.o \ linespec.o \ + lk-cmds.o \ lk-lists.o \ lk-modules.o \ location.o \ @@ -2535,6 +2538,7 @@ ALLDEPFILES = \ linux-fork.c \ linux-record.c \ linux-tdep.c \ + lk-cmds.c \ lk-lists.c \ lk-low.c \ lk-modules.c \ diff --git a/gdb/lk-cmds.c b/gdb/lk-cmds.c new file mode 100644 index 0000000..a47aad9 --- /dev/null +++ b/gdb/lk-cmds.c @@ -0,0 +1,248 @@ +/* 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 "lk-lists.h" +#include "lk-low.h" +#include "lk-modules.h" +#include "typeprint.h" +#include "valprint.h" + + +/* Print line for module MOD to UIOUT for lsmod command. */ + +static bool +lk_lsmod_print_single_module (struct ui_out *uiout, CORE_ADDR mod) +{ + char *src_list, name[LK_MODULE_NAME_LEN + 2]; + CORE_ADDR next, src_list_addr; + size_t src_num, src_size, list_len; + bool loaded; + struct cleanup *ui_chain; + + + /* Get name. */ + 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'; + + /* Get size. */ + if (LK_FIELD (module, module_core)) + { + src_size = lk_read_uint (mod + LK_OFFSET (module, init_size)); + src_size += lk_read_uint (mod + LK_OFFSET (module, core_size)); + } + else + { + src_size = lk_read_uint (mod + LK_OFFSET (module, init_layout) + + LK_OFFSET (module_layout, size)); + src_size += lk_read_uint (mod + LK_OFFSET (module, core_layout) + + LK_OFFSET (module_layout, size)); + } + + /* Get number of sources and list of their names. */ + src_num = 0; + src_list_addr = mod + LK_OFFSET (module, source_list); + src_list = xstrdup (""); + list_len = 0; + + lk_list_for_each (next, src_list_addr, module, source_list) + { + char src_name[LK_MODULE_NAME_LEN + 1]; + CORE_ADDR src_mod, src_addr; + + src_addr = (LK_CONTAINER_OF (next, module_use, source_list) + + LK_OFFSET (module_use, source)); + src_mod = lk_read_addr (src_addr); + read_memory_string (src_mod + LK_OFFSET (module, name), src_name, + LK_MODULE_NAME_LEN); + + /* 2 = strlen (", "). */ + list_len += strlen (src_name) + 2; + src_list = reconcat (src_list, src_list, src_name, ", ", NULL); + + src_num++; + } + /* Remove trailing comma. */ + src_list [list_len - 2] = '\0'; + + ui_chain = make_cleanup_ui_out_tuple_begin_end (uiout, NULL); + + uiout->field_fmt ("addr", "%#lx", mod); + uiout->field_string ("module", name); + uiout->field_int ("size", src_size); + uiout->field_int ("src_num", src_num); + uiout->field_string ("src_list", src_list); + uiout->text ("\n"); + + do_cleanups (ui_chain); + 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 '*'. */ + +void +lk_lsmod (char *args, int from_tty) +{ + struct ui_out *uiout; + struct cleanup *ui_chain; + CORE_ADDR modules, next; + bool all_loaded = true; + + uiout = current_uiout; + ui_chain = make_cleanup_ui_out_table_begin_end (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 (); + + modules = LK_ADDR (modules); + lk_list_for_each (next, modules, module, list) + { + CORE_ADDR mod; + mod = LK_CONTAINER_OF (next, module, list); + all_loaded &= lk_lsmod_print_single_module (uiout, mod); + } + if (!all_loaded) + uiout->text ("(*) Missing debug info for module.\n"); + + do_cleanups (ui_chain); +} + +static void +lk_print_struct (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); +} + +#include "gdbtypes.h" +void +lk_print_offset (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 0000000..63e4246 --- /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 81ff61c..4211825 100644 --- a/gdb/lk-low.c +++ b/gdb/lk-low.c @@ -27,6 +27,7 @@ #include "gdbthread.h" #include "gdbtypes.h" #include "inferior.h" +#include "lk-cmds.h" #include "lk-lists.h" #include "lk-low.h" #include "lk-modules.h" @@ -825,6 +826,8 @@ lk_try_push_target () if (!target_is_pushed (linux_kernel_ops)) push_target (linux_kernel_ops); + lk_init_cmds (); + set_solib_ops (gdbarch, lk_modules_so_ops); } diff --git a/gdb/typeprint.c b/gdb/typeprint.c index 56e993e..f30f5dc 100644 --- a/gdb/typeprint.c +++ b/gdb/typeprint.c @@ -39,12 +39,6 @@ extern void _initialize_typeprint (void); -static void ptype_command (char *, int); - -static void whatis_command (char *, int); - -static void whatis_exp (char *, int); - const struct type_print_options type_print_raw_options = { 1, /* raw */ @@ -396,7 +390,7 @@ type_to_string (struct type *type) /* Print type of EXP, or last thing in value history if EXP == NULL. show is passed to type_print. */ -static void +void whatis_exp (char *exp, int show) { struct value *val; diff --git a/gdb/typeprint.h b/gdb/typeprint.h index 72da7f4..4cbe189 100644 --- a/gdb/typeprint.h +++ b/gdb/typeprint.h @@ -78,4 +78,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 (char *exp, int show); + #endif