Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12:Update
crash.4081
crash-fix_for_dis_at_highest_module_symbol.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File crash-fix_for_dis_at_highest_module_symbol.patch of Package crash.4081
commit 0c47739aee0f1b36a3d45db2c547912c3d6dfd01 Author: Dave Anderson <anderson@redhat.com> Date: Thu Mar 31 16:58:55 2016 -0400 Fix for the "dis <function | address>" option if the function or address is the highest text symbol value in a kernel module. Without the patch, the disassembly may continue past the end of the function, or may show nothing at all. The patch utilizes in-kernel kallsyms symbol size information instead of disassembling until reaching the address of the next symbol in the module. (anderson@redhat.com) --- symbols.c | 115 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 111 insertions(+), 4 deletions(-) Index: crash-7.0.5/symbols.c =================================================================== --- crash-7.0.5.orig/symbols.c +++ crash-7.0.5/symbols.c @@ -1,8 +1,8 @@ /* symbols.c - core analysis suite * * Copyright (C) 1999, 2000, 2001, 2002 Mission Critical Linux, Inc. - * Copyright (C) 2002-2014 David Anderson - * Copyright (C) 2002-2014 Red Hat, Inc. All rights reserved. + * Copyright (C) 2002-2016 David Anderson + * Copyright (C) 2002-2016 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 @@ -37,6 +37,7 @@ static void symbol_dump(ulong, char *); static void check_for_dups(struct load_module *); static int symbol_name_count(char *); static struct syment *kallsyms_module_symbol(struct load_module *, symbol_info *); +static int kallsyms_module_function_size(struct syment *, struct load_module *, ulong *); static void store_load_module_symbols \ (bfd *, int, void *, long, uint, ulong, char *); static int load_module_index(struct syment *); @@ -1937,22 +1938,27 @@ struct elf_common { ulong st_value; ulong st_shndx; unsigned char st_info; + ulong st_size; }; -static void Elf32_Sym_to_common(Elf32_Sym *e32, struct elf_common *ec) +static void +Elf32_Sym_to_common(Elf32_Sym *e32, struct elf_common *ec) { ec->st_name = (ulong)e32->st_name; ec->st_value = (ulong)e32->st_value; ec->st_shndx = (ulong)e32->st_shndx; ec->st_info = e32->st_info; + ec->st_size = (ulong)e32->st_size; } -static void Elf64_Sym_to_common(Elf64_Sym *e64, struct elf_common *ec) +static void +Elf64_Sym_to_common(Elf64_Sym *e64, struct elf_common *ec) { ec->st_name = (ulong)e64->st_name; ec->st_value = (ulong)e64->st_value; ec->st_shndx = (ulong)e64->st_shndx; ec->st_info = e64->st_info; + ec->st_size = (ulong)e64->st_size; } static int @@ -2662,10 +2668,20 @@ get_text_function_range(ulong vaddr, ulo { struct syment *sp; struct gnu_request gnu_request, *req = &gnu_request; + struct load_module *lm; + ulong size; if (!(sp = value_search(vaddr, NULL))) return FALSE; + if (module_symbol(vaddr, NULL, &lm, NULL, 0)) { + if (kallsyms_module_function_size(sp, lm, &size)) { + *low = sp->value; + *high = sp->value + size; + return TRUE; + } + } + BZERO(req, sizeof(struct gnu_request)); req->command = GNU_GET_FUNCTION_RANGE; req->pc = sp->value; @@ -2684,6 +2700,97 @@ get_text_function_range(ulong vaddr, ulo } /* + * Get the text size of a module function from kallsyms. + */ +static int +kallsyms_module_function_size(struct syment *sp, struct load_module *lm, ulong *size) +{ + int i; + ulong nksyms, ksymtab, st_size; + char *ptr, *module_buf, *module_buf_init, *modbuf, *locsymtab; + struct elf_common elf_common, *ec; + + if (!(lm->mod_flags & MOD_KALLSYMS) || !(kt->flags & KALLSYMS_V2)) + return FALSE; + + module_buf = GETBUF(lm->mod_size); + modbuf = module_buf + (lm->module_struct - lm->mod_base); + + if (!readmem(lm->mod_base, KVADDR, module_buf, lm->mod_size, + "module (kallsyms)", RETURN_ON_ERROR|QUIET)) { + FREEBUF(module_buf); + return FALSE; + } + + if (lm->mod_init_size > 0) { + module_buf_init = GETBUF(lm->mod_init_size); + if (!readmem(lm->mod_init_module_ptr, KVADDR, module_buf_init, + lm->mod_init_size, "module init (kallsyms)", + RETURN_ON_ERROR|QUIET)) { + FREEBUF(module_buf_init); + module_buf_init = NULL; + } + } else + module_buf_init = NULL; + + if (THIS_KERNEL_VERSION >= LINUX(2,6,27)) + nksyms = UINT(modbuf + OFFSET(module_num_symtab)); + else + nksyms = ULONG(modbuf + OFFSET(module_num_symtab)); + + ksymtab = ULONG(modbuf + OFFSET(module_symtab)); + if (!IN_MODULE(ksymtab, lm) && !IN_MODULE_INIT(ksymtab, lm)) { + FREEBUF(module_buf); + if (module_buf_init) + FREEBUF(module_buf_init); + return FALSE; + } + + if (IN_MODULE(ksymtab, lm)) + locsymtab = module_buf + (ksymtab - lm->mod_base); + else + locsymtab = module_buf_init + (ksymtab - lm->mod_init_module_ptr); + + st_size = 0; + ec = &elf_common; + BZERO(&elf_common, sizeof(struct elf_common)); + + for (i = 1; i < nksyms; i++) { /* ELF starts real symbols at 1 */ + switch (BITS()) + { + case 32: + ptr = locsymtab + (i * sizeof(Elf32_Sym)); + Elf32_Sym_to_common((Elf32_Sym *)ptr, ec); + break; + case 64: + ptr = locsymtab + (i * sizeof(Elf64_Sym)); + Elf64_Sym_to_common((Elf64_Sym *)ptr, ec); + break; + } + + if (sp->value == ec->st_value) { + if (CRASHDEBUG(1)) + fprintf(fp, "kallsyms_module_function_size: " + "st_value: %lx st_size: %ld\n", + ec->st_value, ec->st_size); + st_size = ec->st_size; + break; + } + } + + if (module_buf_init) + FREEBUF(module_buf_init); + FREEBUF(module_buf); + + if (st_size) { + *size = st_size; + return TRUE; + } + + return FALSE; +} + +/* * "help -s" output */ void
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor