From patchwork Thu Feb 25 19:15:06 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kieran Bingham X-Patchwork-Id: 62908 Delivered-To: patch@linaro.org Received: by 10.112.199.169 with SMTP id jl9csp328879lbc; Thu, 25 Feb 2016 11:16:22 -0800 (PST) X-Received: by 10.98.79.28 with SMTP id d28mr64518461pfb.77.1456427782188; Thu, 25 Feb 2016 11:16:22 -0800 (PST) Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id ez9si1028909pab.20.2016.02.25.11.16.21 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 25 Feb 2016 11:16:22 -0800 (PST) Received-SPF: pass (google.com: domain of gdb-patches-return-129943-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; spf=pass (google.com: domain of gdb-patches-return-129943-patch=linaro.org@sourceware.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gdb-patches-return-129943-patch=linaro.org@sourceware.org; dkim=pass header.i=@sourceware.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; q=dns; s=default; b=cVfHPB9D07TXdjt1utVOR/yv4z/4mHv Mu+WAgFibESJk4AO8Hip/c/wBgpFmk6F3EfplveWbHFydaCtvPYCxcpyCO3akoEp x84clP6GeO0UVw//R8RDcyFqrxkj8cRA9wfDndQ22mch/RJO4r9sR0he3vflv1vB DzaWPbF/Kfzs= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=sourceware.org; h=list-id :list-unsubscribe:list-subscribe:list-archive:list-post :list-help:sender:from:to:cc:subject:date:message-id:in-reply-to :references; s=default; bh=vQhHeBwsLrwv78w56HGcynn3d9M=; b=BwlG5 c5JWSIshAaXmGRIoG97+OculNcoOQIl8BtQ75IXl6bn0N6bVXJuem0MC8WCuSkwh i+wriuDA1S987OFLnTQIF6KWHGIo685FSn+b9iEB5IkgHnJyY5GHKqIoexh7YG8L AY8wqEu3mN6JGR/pDfvr8wP9rK0mH5pCi6v6JI= Received: (qmail 23846 invoked by alias); 25 Feb 2016 19:15:50 -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 23564 invoked by uid 89); 25 Feb 2016 19:15:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.9 required=5.0 tests=AWL, BAYES_00, SPF_PASS autolearn=ham version=3.3.2 spammy=esac, DEBUG, COMPILE, sk:frame_r X-HELO: mail-wm0-f54.google.com Received: from mail-wm0-f54.google.com (HELO mail-wm0-f54.google.com) (74.125.82.54) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Thu, 25 Feb 2016 19:15:39 +0000 Received: by mail-wm0-f54.google.com with SMTP id b205so44924092wmb.1 for ; Thu, 25 Feb 2016 11:15:38 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=YSoypmihfDg0GBZZsyCTA7vAJWhFR8kmx88hw2c8eys=; b=JReIFQiktIUf1jd0RWJiyTwWjVhwEd17QtzKpqtU2r91yCJHVN3PtrVENTJD4BBFvP SO7hlsDQZoloWANrF9CC4A/fM62MmFM0j1BcplYKSObAgE0yiSX+jn/4YXODhT/mbkgf AP1x2w881nIZrjfTOjVU22tWMEg2rbjxERXUjsxwQZKt4a+gbdHwmpcHh8gmou2j0jDa KQVcdNVwiWeAPCfnkbwJhVQcIrlejnSx7NaqXEfvw/xJkJJ+RvQ1Zt+EQXTweZhLNW7c ItN13kN7E5iG2nnYHHUKm3q5qGWbV+HE6frozHG7qFq/dsOqVkzMqHLBoyNBORevQceB MY8g== X-Gm-Message-State: AG10YORnlCgdHRMIvxbdnBNIzh+HtgT+ORVH+9reM0AQzhmwDJbDtzgCTg25HHZzqGXdqn/c X-Received: by 10.194.192.36 with SMTP id hd4mr44250075wjc.85.1456427736503; Thu, 25 Feb 2016 11:15:36 -0800 (PST) Received: from localhost.localdomain (cpc87017-aztw30-2-0-cust65.18-1.cable.virginm.net. [92.232.232.66]) by smtp.gmail.com with ESMTPSA id i10sm4506874wmf.14.2016.02.25.11.15.35 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Thu, 25 Feb 2016 11:15:36 -0800 (PST) From: Kieran Bingham To: gdb-patches@sourceware.org Cc: arnez@linux.vnet.ibm.com, jeffm@suse.com, peter.griffin@linaro.org, lee.jones@linaro.org, yao.qi@linaro.org, russell.wayman@linaro.org, kernel@stlinux.com, Kieran Bingham Subject: [PATCH 4/4] lkd: Add an Architecture Layer for ARMv7 targets Date: Thu, 25 Feb 2016 19:15:06 +0000 Message-Id: <1456427706-30077-5-git-send-email-kieran.bingham@linaro.org> In-Reply-To: <1456427706-30077-1-git-send-email-kieran.bingham@linaro.org> References: <1456427706-30077-1-git-send-email-kieran.bingham@linaro.org> This layer provides the architecture specific code for thread awarenes on an ARMv7 or compatible target There is still more that could be stripped out, but it serves to highlight the implementation detail --- gdb/Makefile.in | 5 +- gdb/configure.tgt | 4 + gdb/lkd/lkd-arm.c | 312 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 320 insertions(+), 1 deletion(-) create mode 100644 gdb/lkd/lkd-arm.c -- 2.5.0 diff --git a/gdb/Makefile.in b/gdb/Makefile.in index ff324c393f23..7b368d7b8a22 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -722,7 +722,8 @@ ALL_TARGET_OBS = \ windows-tdep.o \ linux-record.o \ ravenscar-thread.o \ - lkd-main.o lkd-process.o + lkd-main.o lkd-process.o \ + lkd-arm.o # Host-dependent makefile fragment comes in here. @host_makefile_frag@ @@ -2728,6 +2729,8 @@ py-varobj.o: $(srcdir)/python/py-varobj.c lkd-main.o: $(srcdir)/lkd/lkd-main.c lkd-process.o: $(srcdir)/lkd/lkd-process.c +lkd-arm.o: $(srcdir)/lkd/lkd-arm.c + # Generalised lkd-compile rule lkd-%: $(COMPILE) $< diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 8a685afe5c1e..ea0d0d2a540c 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -730,6 +730,10 @@ done # Add linux kernel awareness obs and set no default OS ABI if test x"$enable_linux_kernel_aware" = xyes; then gdb_target_obs="$gdb_target_obs lkd-main.o lkd-process.o" + case "${targ}" in + arm*-*-linux*) + gdb_target_obs="$gdb_target_obs lkd-arm.o" ;; + esac gdb_osabi= fi diff --git a/gdb/lkd/lkd-arm.c b/gdb/lkd/lkd-arm.c new file mode 100644 index 000000000000..f734b3cb89df --- /dev/null +++ b/gdb/lkd/lkd-arm.c @@ -0,0 +1,312 @@ +/* + Copyright 2011-2013 STMicroelectronics. + + This file contains the ARM specific part of the Linux + Awareness layer for GDB. + + The Linux Awareness layer allows GDB boot or attach-to and debug + a Linux kernel through a H/W link (presumably JTAG). + + see file linux-awareness.c for more details. +*/ + +#include "defs.h" +#include "block.h" +#include "command.h" +#include "frame.h" +#include "frame-unwind.h" +#include "gdb_assert.h" +#include "gdbarch.h" +#include "gdbcmd.h" +#include "gdbcore.h" +#include "gdbtypes.h" +#include "gdb_obstack.h" +#include "inferior.h" +#include "objfiles.h" +#include "regcache.h" +#include "user-regs.h" +#include "symtab.h" +#include "target.h" +#include "top.h" +#include "value.h" +#include "gdbthread.h" + +#include "arm-tdep.h" + +#include "lkd.h" +#include "lkd-process.h" + +/* Addresses used by the ARM specific linux awareness. */ + +DECLARE_ADDR (ret_from_fork); +DECLARE_ADDR (ret_fast_syscall); + +/* Fields used by the ARM specific linux awareness. */ +DECLARE_FIELD (mm_struct, pgd); +DECLARE_FIELD (task_struct, mm); +DECLARE_FIELD (task_struct, thread); +DECLARE_FIELD (task_struct, stack); +DECLARE_FIELD (thread_info, cpu_context); + + +struct pt_regs +{ + uint32_t uregs[18]; +}; + +static int +arch_can_write (CORE_ADDR addr, CORE_ADDR task_struct) +{ + return 0; +} + +static inline int +is_special_addr (CORE_ADDR addr) +{ + /* ret_fast_syscall is a special address (both sp _and_ pc) + used to link user and kernel spaces */ + return HAS_ADDR (ret_fast_syscall) && addr == ADDR (ret_fast_syscall); +} + +static int +arch_is_user_address (CORE_ADDR addr) +{ + return (addr < linux_awareness_ops->kernel_offset) + || is_special_addr (addr); +} + +static int +arch_is_kernel_address (CORE_ADDR addr) +{ + return !arch_is_user_address (addr) || is_special_addr (addr); +} + + +/*****************************************************************************/ +/* TASK AWARENESS */ +/*****************************************************************************/ + +/* This function gets the register values that the schedule() routine + * has stored away to be able to restart an asleep task later. + * this must match the layout in arm/include/asm/thread_info.h + * + **/ +static CORE_ADDR +fetch_context_register_real (CORE_ADDR task_struct) +{ + struct regcache *regcache; + int offset = 0, val, i; + uint32_t thread_info_addr; + uint32_t cpsr; + struct cpu_context_save + { + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t sl; + uint32_t fp; + uint32_t sp; + uint32_t pc; + } cpu_cxt; + + /*get thread_info address */ + thread_info_addr = read_unsigned_field (task_struct, task_struct, stack); + + /*get cpu_context as saved by scheduled */ + read_memory ((CORE_ADDR) thread_info_addr + + F_OFFSET (thread_info, cpu_context), + (gdb_byte *) & cpu_cxt, sizeof (struct cpu_context_save)); + + DEBUG (TASK, 4, "fetch_context_register_real (%x)\n", thread_info_addr); + + regcache = get_current_regcache (); + + regcache_raw_supply (regcache, ARM_PC_REGNUM, &cpu_cxt.pc); + regcache_raw_supply (regcache, ARM_SP_REGNUM, &cpu_cxt.sp); + regcache_raw_supply (regcache, ARM_FP_REGNUM, &cpu_cxt.fp); + + /*general purpose registers */ + regcache_raw_supply (regcache, 10, &cpu_cxt.sl); + regcache_raw_supply (regcache, 9, &cpu_cxt.r9); + regcache_raw_supply (regcache, 8, &cpu_cxt.r8); + regcache_raw_supply (regcache, 7, &cpu_cxt.r7); + regcache_raw_supply (regcache, 6, &cpu_cxt.r6); + regcache_raw_supply (regcache, 5, &cpu_cxt.r5); + regcache_raw_supply (regcache, 4, &cpu_cxt.r4); + + /* Fake a value for cpsr:T bit. */ +#define IS_THUMB_ADDR(addr) ((addr) & 1) + cpsr = IS_THUMB_ADDR(cpu_cxt.pc) ? arm_psr_thumb_bit (target_gdbarch ()) : 0; + regcache_raw_supply (regcache, ARM_PS_REGNUM, &cpsr); + + for (i = 0; i < gdbarch_num_regs (target_gdbarch ()); i++) + if (REG_VALID != regcache_register_status (regcache, i)) + /* Mark other registers as unavailable. */ + regcache_invalidate (regcache, i); + + return cpu_cxt.pc; +} + +static int +arch_fetch_context_register (int regno, CORE_ADDR task_struct) +{ + CORE_ADDR pc; + DEBUG (TASK, 4, "fetch_context_register(%i,%x)\n", + regno, (unsigned int) task_struct); + + if (REG_VALID != regcache_register_status (get_current_regcache (), + ARM_PC_REGNUM)) + { + + pc = fetch_context_register_real (task_struct); + + if (lkd_params.skip_schedule_frame + && !(HAS_ADDR (ret_from_fork) && pc == ADDR (ret_from_fork))) + { + int arm_num_regs = gdbarch_num_regs (target_gdbarch ()); + struct frame_info *f = get_current_frame (); + int level = frame_relative_level(f); + + /* skip this frame, unwind to the next + **/ + while (f && (level++ < lkd_params.skip_schedule_frame)) + f = get_prev_frame (f); + + if (f != NULL) + { + int i; + gdb_byte buf[12]; + int optimized, unavailable; + CORE_ADDR addr; + int realnum; + enum lval_type lval; + unsigned long *new_registers = xcalloc (arm_num_regs, + sizeof (unsigned long)); + char *new_registers_valid = xcalloc (arm_num_regs, 1); + + for (i = 0; i < arm_num_regs; ++i) + { + frame_register_unwind (f, i, &optimized, &unavailable, + &lval, &addr, &realnum, buf); + if (!optimized && !unavailable) + { + memcpy (&new_registers[i], buf, 4); + new_registers_valid[i] = 1; + } + } + + reinit_frame_cache (); + + for (i = 0; i < arm_num_regs; ++i) + { + if (new_registers_valid[i]) + regcache_raw_supply + (get_current_regcache (), i, &new_registers[i]); + else + /* Mark other registers as unavailable. */ + regcache_invalidate (get_current_regcache (), i); + } + + xfree (new_registers); + xfree (new_registers_valid); + } + } + } + + return 1; +} + +// FIXME +static int +arch_store_context_register (int regno, CORE_ADDR task_struct) +{ + DEBUG (TASK, 3, "store_context_register(%i,%x)\n", + regno, (unsigned int) task_struct); + warning ("ARM/store_context_register not implemented yet"); + return 1; +} + +static void +arch_clear_cache (void) +{ +} + + +static void +arch_close (void) +{ + arch_clear_cache (); +} + + +/* + * default op handler for STGDI (non-remote) + **/ +static void +arch_post_load (char *prog, int fromtty) +{ + CORE_ADDR addr_phys_offset; + + DEBUG (D_INIT, 1, "ARM: arch_post_load\n"); + + + DEBUG (TARGET, 1, "Assuming 0x%08x as MODULES_VADDR.\n", + linux_awareness_ops->kernel_offset); + + /* this installs what ever LKD specific handling is required + * in the gdb arch data. */ + + /* lkd_params.loaded will be set later */ +} + +static int +arch_init (void) +{ + DEBUG (D_INIT, 1, "ARM: arch_init.\n"); + + return 1; +} + +static int +arch_check_kernel (void) +{ + int res = HAS_FIELD (mm_struct, pgd) + && HAS_FIELD (task_struct, stack) + && HAS_FIELD (task_struct, thread) + && HAS_FIELD (task_struct, mm) && HAS_FIELD (thread_info, cpu_context); + return res; +} + +//#define ARMv7_PAGESHIFT 12 + +struct linux_awareness_ops arm_linux_awareness_ops = { + .name = "armv7", + .lo_check_kernel = arch_check_kernel, + .lo_init = arch_init, + .lo_close = arch_close, + .lo_post_load = arch_post_load, + .lo_can_write = arch_can_write, + .lo_is_user_address = arch_is_user_address, + .lo_is_kernel_address = arch_is_kernel_address, + .lo_single_step_destination = NULL, + .lo_clear_cache = arch_clear_cache, + .lo_fetch_context_register = arch_fetch_context_register, + .lo_store_context_register = arch_store_context_register, + .kernel_offset = 0x0, +}; + + +/* -Wmissing-prototypes */ +extern initialize_file_ftype _initialize_armv7_lkd; + +/* _initialize_xxx routines are added to the ugly autogenerates init code + * see gdb makefile. + **/ +void +_initialize_armv7_lkd (void) +{ + linux_awareness_ops = &arm_linux_awareness_ops; +}