From patchwork Sun Jan 31 21:44:52 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ales Novak X-Patchwork-Id: 10676 Received: (qmail 97704 invoked by alias); 31 Jan 2016 21:45:37 -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 97491 invoked by uid 89); 31 Jan 2016 21:45:35 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.6 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=sk:get_sym, snprintf, ait, cfg X-HELO: mx2.suse.de Received: from mx2.suse.de (HELO mx2.suse.de) (195.135.220.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Sun, 31 Jan 2016 21:45:16 +0000 Received: from relay1.suse.de (charybdis-ext.suse.de [195.135.220.254]) by mx2.suse.de (Postfix) with ESMTP id B8719AAB4 for ; Sun, 31 Jan 2016 21:45:05 +0000 (UTC) Received: by linux-2znx.site (Postfix, from userid 1001) id 50DA7783E8B; Sun, 31 Jan 2016 22:45:05 +0100 (CET) From: Ales Novak To: gdb-patches@sourceware.org Cc: Ales Novak Subject: [PATCH 4/4] Minor cleanups Date: Sun, 31 Jan 2016 22:44:52 +0100 Message-Id: <1454276692-7119-5-git-send-email-alnovak@suse.cz> In-Reply-To: <1454276692-7119-1-git-send-email-alnovak@suse.cz> References: <1454276692-7119-1-git-send-email-alnovak@suse.cz> X-IsSubscribed: yes --- gdb/kdump.c | 393 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 215 insertions(+), 178 deletions(-) diff --git a/gdb/kdump.c b/gdb/kdump.c index e231559..5c1c5a7 100644 --- a/gdb/kdump.c +++ b/gdb/kdump.c @@ -159,7 +159,7 @@ typedef enum { ARCH_NONE, ARCH_X86_64, ARCH_S390X, - ARCH_PPC64LE, + ARCH_PPC64, } t_arch; struct cpuinfo { @@ -419,6 +419,23 @@ enum { T_REF }; +//static int ppc64_retregs_active(struct task_info *task_info, struct regcache *rc, kdump_reg_t rsp, int cpu); + +struct t_kdump_arch { + char *kdident; + char *gdbident; + int flags; + t_arch arch; + int (*init_func)(const struct t_kdump_arch *, int *); + int (*retregs_active_func)(struct task_info *task_info, + struct regcache *rc, kdump_reg_t rsp, int cpu); + int (*retregs_scheduled_func)(struct task_info *task_info, + struct regcache *rc, kdump_reg_t rsp); +} ; + +static const struct t_kdump_arch *kdump_arch = NULL; + + static void free_task_info(struct private_thread_info *addr) { struct task_info *ti = (struct task_info*)addr; @@ -1191,6 +1208,169 @@ static int get_process_cpu(offset task) return -1; } +static int x86_retregs_active(struct task_info *task_info, struct regcache *rc, kdump_reg_t rsp, int cpu) +{ + kdump_reg_t rip, val, _b, *b = &_b; + long long regs[64]; + kdump_reg_t reg; + +#ifdef _DEBUG + printf("task %p is running on %d\n", (void*)task_info->task_struct, cpu); +#endif + +#define REG(en,mem) kdump_read_reg(dump_ctx, cpu, GET_REGISTER_OFFSET(mem), ®); regcache_raw_supply(rc, en, ®) + + REG(reg_RSP,sp); + task_info->sp = reg; + REG(reg_RIP,ip); + task_info->ip = reg; + REG(reg_RAX,ax); + REG(reg_RCX,cx); + REG(reg_RDX,dx); + REG(reg_RBX,bx); + REG(reg_RBP,bp); + REG(reg_RSI,si); + REG(reg_RDI,di); + REG(reg_R8,r8); + REG(reg_R9,r9); + REG(reg_R10,r10); + REG(reg_R11,r11); + REG(reg_R12,r12); + REG(reg_R13,r13); + REG(reg_R14,r14); + REG(reg_R15,r15); + REG(reg_RFLAGS,flags); + REG(reg_ES,es); + REG(reg_CS,cs); + REG(reg_SS,ss); + REG(reg_DS,ds); + REG(reg_FS,fs); + REG(reg_GS,gs); +#undef REG + return 0; +} +static int x86_retregs_scheduled(struct task_info *task_info, struct regcache *rc, kdump_reg_t rsp) +{ + kdump_reg_t rip, val, _b, *b = &_b; + long long regs[64]; + + if (KDUMP_TYPE_GET(_voidp, rsp, b)) return -2; + rip = kt_ptr_value(b); + + /* + * So we're gonna skip its stackframe + * FIXME: use the size obtained from debuginfo + */ + rsp += 0x148; + if (target_read_raw_memory(rsp - 0x8 * (1 + 6), (void*)regs, 0x8 * 6)) + warning(_("Could not read regs\n")); + + regcache_raw_supply(rc, 15, ®s[5]); + regcache_raw_supply(rc, 14, ®s[4]); + regcache_raw_supply(rc, 13, ®s[3]); + regcache_raw_supply(rc, 12, ®s[2]); + regcache_raw_supply(rc, 6, ®s[1]); + regcache_raw_supply(rc, 3, ®s[0]); + + KDUMP_TYPE_GET(_voidp, rsp, b); + rip = kt_ptr_value(b); + rsp += 8; + + regcache_raw_supply(rc, 7, &rsp); + regcache_raw_supply(rc, 16, &rip); + + task_info->sp = rsp; + task_info->ip = rip; + + return 0; +} +static int ppc64_retregs_active(struct task_info *task_info, struct regcache *rc, kdump_reg_t rsp, int cpu) +{ + kdump_reg_t val; + kdump_reg_t reg; + int i; + long long regs[64]; + for (i = 0; i < 32; i ++) { + kdump_read_reg(dump_ctx, cpu, i, ®); + val = htobe64(reg); + regcache_raw_supply(rc, i, &val); + // kdump_read_reg(dump_ctx, cpu, 32, ®); regcache_raw_supply(rc, 32, &val); + // kdump_read_reg(dump_ctx, cpu, 1, ®); regcache_raw_supply(rc, 1, &val); + } + for (i = 32; i < 49; i ++) { + kdump_read_reg(dump_ctx, cpu, i, ®); + val = htobe64(reg); + regcache_raw_supply(rc, i+32, &val); + } + kdump_read_reg(dump_ctx, cpu, 32, ®); + task_info->ip = reg; + kdump_read_reg(dump_ctx, cpu, 1, ®); + task_info->sp = reg; + for (i = 0; i < 129; i ++) { + val = i; + // regcache_raw_supply(rc, i, &val); + } + + return 0; +} + +static int ppc64_retregs_scheduled(struct task_info *task_info, struct regcache *rc, kdump_reg_t rsp) +{ + return 0; +} + +static int s390x_retregs_active(struct task_info *task_info, struct regcache *rc, kdump_reg_t rsp, int cpu) +{ + kdump_reg_t rip, val, _b, *b = &_b; + + if (! KDUMP_TYPE_GET(_voidp, rsp+136, b)) + rip = kt_ptr_value(b); + if (KDUMP_TYPE_GET(_voidp, rsp+144, b)) return -3; + rsp = kt_ptr_value(b); + task_info->sp = rsp; + task_info->ip = rip; + + val = be64toh(rip); + regcache_raw_supply(rc, 1, &val); + + return 0; +} + +static int s390x_retregs_scheduled(struct task_info *task_info, struct regcache *rc, kdump_reg_t rsp) +{ + kdump_reg_t rip, val, _b, *b = &_b; + + if (! KDUMP_TYPE_GET(_voidp, rsp+136, b)) + rip = kt_ptr_value(b); + if (KDUMP_TYPE_GET(_voidp, rsp+144, b)) return -3; + rsp = kt_ptr_value(b); + task_info->sp = rsp; + task_info->ip = rip; + + val = be64toh(rip); + regcache_raw_supply(rc, 1, &val); + + if (! KDUMP_TYPE_GET(_voidp, rsp+136, b)) regcache_raw_supply(rc, S390_R14_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+128, b)) regcache_raw_supply(rc, S390_R13_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+120, b)) regcache_raw_supply(rc, S390_R12_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+112, b)) regcache_raw_supply(rc, S390_R11_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+104, b)) regcache_raw_supply(rc, S390_R10_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+96, b)) regcache_raw_supply(rc, S390_R9_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+88, b)) regcache_raw_supply(rc, S390_R8_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+80, b)) regcache_raw_supply(rc, S390_R7_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+72, b)) regcache_raw_supply(rc, S390_R6_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+64, b)) regcache_raw_supply(rc, S390_R5_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+56, b)) regcache_raw_supply(rc, S390_R4_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+48, b)) regcache_raw_supply(rc, S390_R3_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+40, b)) regcache_raw_supply(rc, S390_R2_REGNUM, b); + if (! KDUMP_TYPE_GET(_voidp, rsp+32, b)) regcache_raw_supply(rc, S390_R1_REGNUM, b); + + val = be64toh(rsp); + regcache_raw_supply(rc, S390_R15_REGNUM, &val); + + return 0; +} + static int add_task(offset off_task, int *pid_reserve, char *task); static int add_task(offset off_task, int *pid_reserve, char *task) { @@ -1202,19 +1382,16 @@ static int add_task(offset off_task, int *pid_reserve, char *task) offset stack; offset o_init_task; int state; - int i, cpu; + int cpu; int hashsize; struct task_info *task_info; - struct thread_info *info; int pid; ptid_t tt; struct regcache *rc; - long long val; b = _b; - state = kt_int_value(task + MEMBER_OFFSET(task_struct,state)); pid = kt_int_value(task + MEMBER_OFFSET(task_struct,pid)); stack = kt_ptr_value(task + MEMBER_OFFSET(task_struct,stack)); @@ -1228,17 +1405,6 @@ static int add_task(offset off_task, int *pid_reserve, char *task) task_info->pid = pid; task_info->cpu = -1; - if (types.arch == ARCH_S390X) { - if (! KDUMP_TYPE_GET(_voidp, rsp+136, b)) - rip = kt_ptr_value(b); - if (KDUMP_TYPE_GET(_voidp, rsp+144, b)) return -3; - rsp = kt_ptr_value(b); - task_info->sp = rsp; - task_info->ip = rip; - } else { - if (KDUMP_TYPE_GET(_voidp, rsp, b)) return -2; - rip = kt_ptr_value(b); - } #ifdef _DEBUG fprintf(stdout, "TASK %llx,%llx,rsp=%llx,rip=%llx,pid=%d,state=%d,name=%s\n", off_task, stack, rsp, rip, pid, state, task + MEMBER_OFFSET(task_struct,comm)); #endif @@ -1257,146 +1423,16 @@ static int add_task(offset off_task, int *pid_reserve, char *task) inferior_ptid = tt; info->name = strdup(task + MEMBER_OFFSET(task_struct,comm)); - val = 0; - rc = get_thread_regcache (tt); - if (types.arch == ARCH_S390X) { - - if (((cpu = get_process_cpu(off_task)) != -1)) { -#ifdef _DEBUG - printf("task %p is running on %d\n", (void*)task_info->task_struct, cpu); -#endif - } - /* - * TODO: implement retrieval of register values from lowcore - */ - val = be64toh(rip); - regcache_raw_supply(rc, 1, &val); - - if (! KDUMP_TYPE_GET(_voidp, _rsp+136, b)) regcache_raw_supply(rc, S390_R14_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+128, b)) regcache_raw_supply(rc, S390_R13_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+120, b)) regcache_raw_supply(rc, S390_R12_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+112, b)) regcache_raw_supply(rc, S390_R11_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+104, b)) regcache_raw_supply(rc, S390_R10_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+96, b)) regcache_raw_supply(rc, S390_R9_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+88, b)) regcache_raw_supply(rc, S390_R8_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+80, b)) regcache_raw_supply(rc, S390_R7_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+72, b)) regcache_raw_supply(rc, S390_R6_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+64, b)) regcache_raw_supply(rc, S390_R5_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+56, b)) regcache_raw_supply(rc, S390_R4_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+48, b)) regcache_raw_supply(rc, S390_R3_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+40, b)) regcache_raw_supply(rc, S390_R2_REGNUM, b); - if (! KDUMP_TYPE_GET(_voidp, _rsp+32, b)) regcache_raw_supply(rc, S390_R1_REGNUM, b); - - val = be64toh(rsp); - regcache_raw_supply(rc, S390_R15_REGNUM, &val); - } else if (types.arch == ARCH_X86_64) { - /* - * The task is not running - e.g. crash would show it's stuck in schedule() - * Yet schedule() is not on its stack. - * - */ - cpu = 0; - if (((cpu = get_process_cpu(off_task)) == -1)) { - long long regs[64]; - - /* - * So we're gonna skip its stackframe - * FIXME: use the size obtained from debuginfo - */ - rsp += 0x148; - if (target_read_raw_memory(rsp - 0x8 * (1 + 6), (void*)regs, 0x8 * 6)) - warning(_("Could not read regs\n")); - - regcache_raw_supply(rc, 15, ®s[5]); - regcache_raw_supply(rc, 14, ®s[4]); - regcache_raw_supply(rc, 13, ®s[3]); - regcache_raw_supply(rc, 12, ®s[2]); - regcache_raw_supply(rc, 6, ®s[1]); - regcache_raw_supply(rc, 3, ®s[0]); - - KDUMP_TYPE_GET(_voidp, rsp, b); - rip = kt_ptr_value(b); - rsp += 8; - - regcache_raw_supply(rc, 7, &rsp); - regcache_raw_supply(rc, 16, &rip); - - task_info->sp = rsp; - task_info->ip = rip; - } else { - kdump_reg_t reg; - - task_info->cpu = cpu; -#ifdef _DEBUG - printf("task %p is running on %d\n", (void*)task_info->task_struct, cpu); -#endif - -#define REG(en,mem) kdump_read_reg(dump_ctx, cpu, GET_REGISTER_OFFSET(mem), ®); regcache_raw_supply(rc, en, ®) - - REG(reg_RSP,sp); - task_info->sp = reg; - REG(reg_RIP,ip); - task_info->ip = reg; - REG(reg_RAX,ax); - REG(reg_RCX,cx); - REG(reg_RDX,dx); - REG(reg_RBX,bx); - REG(reg_RBP,bp); - REG(reg_RSI,si); - REG(reg_RDI,di); - REG(reg_R8,r8); - REG(reg_R9,r9); - REG(reg_R10,r10); - REG(reg_R11,r11); - REG(reg_R12,r12); - REG(reg_R13,r13); - REG(reg_R14,r14); - REG(reg_R15,r15); - REG(reg_RFLAGS,flags); - REG(reg_ES,es); - REG(reg_CS,cs); - REG(reg_SS,ss); - REG(reg_DS,ds); - REG(reg_FS,fs); - REG(reg_GS,gs); -#undef REG + if (((cpu = get_process_cpu(off_task)) != -1)) { + task_info->cpu = cpu; + if (kdump_arch->retregs_active_func(task_info, rc, rsp, cpu)) { + warning("Cannot retrieve registers of active task %d\n", pid); } - } else if (types.arch == ARCH_PPC64LE) { - if (((cpu = get_process_cpu(off_task)) == -1)) { - val = 789; - regcache_raw_supply(rc, 1, &val); - val = 456; - regcache_raw_supply(rc, 64, &val); - for (i = 0; i < 169; i ++) { - val = htobe64(i); - regcache_raw_supply(rc, i, &val); - } - } else { - kdump_reg_t reg; - task_info->cpu = cpu; - long long regs[64]; - for (i = 0; i < 32; i ++) { - kdump_read_reg(dump_ctx, cpu, i, ®); - val = htobe64(reg); - regcache_raw_supply(rc, i, &val); - // kdump_read_reg(dump_ctx, cpu, 32, ®); regcache_raw_supply(rc, 32, &val); - // kdump_read_reg(dump_ctx, cpu, 1, ®); regcache_raw_supply(rc, 1, &val); - } - for (i = 32; i < 49; i ++) { - kdump_read_reg(dump_ctx, cpu, i, ®); - val = htobe64(reg); - regcache_raw_supply(rc, i+32, &val); - } - kdump_read_reg(dump_ctx, cpu, 32, ®); - task_info->ip = reg; - kdump_read_reg(dump_ctx, cpu, 1, ®); - task_info->sp = reg; - for (i = 0; i < 129; i ++) { - val = i; - // regcache_raw_supply(rc, i, &val); - } + } else { + if (kdump_arch->retregs_scheduled_func(task_info, rc, rsp)) { + warning("Cannot retrieve registers of scheduled task %d\n", pid); } } @@ -2091,9 +2127,6 @@ static void check_kmem_caches(void) } } - - - static struct page read_page(offset o_page) { char b_page[GET_TYPE_SIZE(page)]; @@ -2217,20 +2250,30 @@ static int init_memmap(void) //FIXME: why are all NULL? cfg = kdump_vmcoreinfo_row(dump_ctx, "CONFIG_FLATMEM"); +#ifdef _DEBUG printf("CONFIG_FLATMEM=%s\n", cfg ? cfg : "(null)"); +#endif cfg = kdump_vmcoreinfo_row(dump_ctx, "CONFIG_DISCONTIGMEM"); +#ifdef _DEBUG printf("CONFIG_DISCONTIGMEM=%s\n", cfg ? cfg : "(null)"); +#endif cfg = kdump_vmcoreinfo_row(dump_ctx, "CONFIG_SPARSEMEM_VMEMMAP"); +#ifdef _DEBUG printf("CONFIG_SPARSEMEM_VMEMMAP=%s\n", cfg ? cfg : "(null)"); +#endif o_mem_map = get_symbol_value("mem_map"); +#ifdef _DEBUG printf("memmap: %llx\n", o_mem_map); +#endif if (o_mem_map) { p_memmap = kt_ptr_value_off(o_mem_map); +#ifdef _DEBUG printf("memmap is pointer to: %llx\n", p_memmap); +#endif if (p_memmap != -1) memmap = p_memmap; } @@ -2269,7 +2312,7 @@ static int init_values(void) struct list_iter iter; s = NULL; - + b = KDUMP_TYPE_ALLOC(_voidp); if (!b) goto error; @@ -2315,16 +2358,13 @@ static int init_values(void) list_for_each_from(iter, o_tasks) { - struct thread_info *info; int pid; ptid_t tt; struct regcache *rc; long long val; - offset main_tasks, mt; struct list_iter iter_thr; offset o_threads; - //fprintf(stderr, __FILE__":%d: ok\n", __LINE__); off_task = off - MEMBER_OFFSET(task_struct,tasks); if (KDUMP_TYPE_GET(task_struct, off_task, task)) continue; @@ -2349,9 +2389,11 @@ static int init_values(void) printf_unfiltered(_("Loaded processes: %d\n"), cnt); init_memmap(); -// check_kmem_caches(); -// check_slab_obj(0xffff880138bedf40UL); -// check_slab_obj(0xffff8801359734c0UL); +#ifdef _DEBUG + check_kmem_caches(); + check_slab_obj(0xffff880138bedf40UL); + check_slab_obj(0xffff8801359734c0UL); +#endif return 0; error: @@ -2361,14 +2403,6 @@ error: return 1; } -struct t_kdump_arch { - char *kdident; - char *gdbident; - int flags; - t_arch arch; - int (*init_func)(const struct t_kdump_arch *, int *); -} ; - static int kdump_ppc64_init(const struct t_kdump_arch *a, int *flags) { *flags = F_BIG_ENDIAN; @@ -2376,9 +2410,12 @@ static int kdump_ppc64_init(const struct t_kdump_arch *a, int *flags) } static const struct t_kdump_arch archlist[] = { - {"x86_64", "i386:x86-64", F_LITTLE_ENDIAN, ARCH_X86_64, NULL}, - {"s390x", "s390:64-bit", F_BIG_ENDIAN, ARCH_S390X, NULL}, - {"ppc64", "powerpc:common64", F_UNKN_ENDIAN, ARCH_PPC64LE, kdump_ppc64_init}, + {"x86_64", "i386:x86-64", F_LITTLE_ENDIAN, ARCH_X86_64, NULL, + x86_retregs_active, x86_retregs_scheduled}, + {"s390x", "s390:64-bit", F_BIG_ENDIAN, ARCH_S390X, NULL, + s390x_retregs_active, s390x_retregs_scheduled}, + {"ppc64", "powerpc:common64", F_UNKN_ENDIAN, ARCH_PPC64, kdump_ppc64_init, + ppc64_retregs_active, ppc64_retregs_scheduled}, {NULL} }; @@ -2416,6 +2453,7 @@ static int kdump_do_init(void) gai.bfd_arch_info = ait; garch = gdbarch_find_by_info(gai); kdump_gdbarch = garch; + kdump_arch = a; #ifdef _DEBUG fprintf(stderr, "arch=%s,ait=%p,garch=%p\n", selected_architecture_name(), ait, garch); #endif @@ -2423,6 +2461,7 @@ static int kdump_do_init(void) if (a->init_func) { if ((ret = a->init_func(a, &flags)) != 0) { error(_("Architecture %s init_func()=%d"), a->kdident, ret); + kdump_arch = NULL; return -5; } } @@ -2430,7 +2469,7 @@ static int kdump_do_init(void) inf = current_inferior(); types.arch = a->arch; - + if (init_types(flags)) { warning(_("kdump: Cannot init types!\n")); } @@ -2935,7 +2974,7 @@ static void kdumpmodules_command (char *filename, int from_tty) section_addrs, flags); add_target_sections_of_objfile (objf); } - + error: if (v) free(v); @@ -2958,9 +2997,7 @@ static void kdumpps_command(char *fn, int from_tty) if (!task) continue; if (task->cpu == -1) cpu[0] = '\0'; else snprintf(cpu, 5, "% 4d", task->cpu); -#ifdef _DEBUG printf_filtered(_("% 7d %llx %llx %llx %-4s %s\n"), task->pid, task->task_struct, task->ip, task->sp, cpu, tp->name); -#endif } }