Pull kgdb updates from Daniel Thompson: "Changes for kgdb/kdb this cycle are dominated by a change from Sumit that removes as small (256K) private heap from kdb. This is change I've hoped for ever since I discovered how few users of this heap remained in the kernel, so many thanks to Sumit for hunting these down. The other change is an incremental step towards SPDX headers" * tag 'kgdb-5.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/danielt/linux: kernel: debug: Convert to SPDX identifier kdb: Rename members of struct kdbtab_t kdb: Simplify kdb_defcmd macro logic kdb: Get rid of redundant kdb_register_flags() kdb: Rename struct defcmd_set to struct kdb_macro kdb: Get rid of custom debug heap allocator
Unified · Split
| @@ -13,6 +13,8 @@ · 12 unmodified lines | ||
| 13 | 13 | * Copyright (C) 2009 Jason Wessel <jason.wessel@windriver.com> |
| 14 | 14 | */ |
| 15 | 15 | |
| 16 | +#include <linux/list.h> | |
| 17 | + | |
| 16 | 18 | /* Shifted versions of the command enable bits are be used if the command |
| 17 | 19 | * has no arguments (see kdb_check_flags). This allows commands, such as |
| 18 | 20 | * go, to have different permissions depending upon whether it is called |
| @@ -64,6 +66,17 @@ typedef enum { · 45 unmodified lines | ||
| 64 | 66 | |
| 65 | 67 | typedef int (*kdb_func_t)(int, const char **); |
| 66 | 68 | |
| 69 | +/* The KDB shell command table */ | |
| 70 | +typedef struct _kdbtab { | |
| 71 | + char *name; /* Command name */ | |
| 72 | + kdb_func_t func; /* Function to execute command */ | |
| 73 | + char *usage; /* Usage String for this command */ | |
| 74 | + char *help; /* Help message for this command */ | |
| 75 | + short minlen; /* Minimum legal # cmd chars required */ | |
| 76 | + kdb_cmdflags_t flags; /* Command behaviour flags */ | |
| 77 | + struct list_head list_node; /* Command list */ | |
| 78 | +} kdbtab_t; | |
| 79 | + | |
| 67 | 80 | #ifdef CONFIG_KGDB_KDB |
| 68 | 81 | #include <linux/init.h> |
| 69 | 82 | #include <linux/sched.h> |
| @@ -193,19 +206,13 @@ static inline const char *kdb_walk_kallsyms(loff_t *pos) · 123 unmodified lines | ||
| 193 | 206 | #endif /* ! CONFIG_KALLSYMS */ |
| 194 | 207 | |
| 195 | 208 | /* Dynamic kdb shell command registration */ |
| 196 | −extern int kdb_register(char *, kdb_func_t, char *, char *, short); | |
| 197 | −extern int kdb_register_flags(char *, kdb_func_t, char *, char *, | |
| 198 | − short, kdb_cmdflags_t); | |
| 199 | −extern int kdb_unregister(char *); | |
| 209 | +extern int kdb_register(kdbtab_t *cmd); | |
| 210 | +extern void kdb_unregister(kdbtab_t *cmd); | |
| 200 | 211 | #else /* ! CONFIG_KGDB_KDB */ |
| 201 | 212 | static inline __printf(1, 2) int kdb_printf(const char *fmt, ...) { return 0; } |
| 202 | 213 | static inline void kdb_init(int level) {} |
| 203 | −static inline int kdb_register(char *cmd, kdb_func_t func, char *usage, | |
| 204 | − char *help, short minlen) { return 0; } | |
| 205 | −static inline int kdb_register_flags(char *cmd, kdb_func_t func, char *usage, | |
| 206 | − char *help, short minlen, | |
| 207 | − kdb_cmdflags_t flags) { return 0; } | |
| 208 | −static inline int kdb_unregister(char *cmd) { return 0; } | |
| 214 | +static inline int kdb_register(kdbtab_t *cmd) { return 0; } | |
| 215 | +static inline void kdb_unregister(kdbtab_t *cmd) {} | |
| 209 | 216 | #endif /* CONFIG_KGDB_KDB */ |
| 210 | 217 | enum { |
| 211 | 218 | KDB_NOT_INITIALIZED, |
| @@ -1,3 +1,4 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 1 | 2 | /* |
| 2 | 3 | * Kernel Debug Core |
| 3 | 4 | * |
| @@ -22,10 +23,6 @@ · 18 unmodified lines | ||
| 22 | 23 | * |
| 23 | 24 | * Original KGDB stub: David Grothe <dave@gcom.com>, |
| 24 | 25 | * Tigran Aivazian <tigran@sco.com> |
| 25 | − * | |
| 26 | − * This file is licensed under the terms of the GNU General Public License | |
| 27 | − * version 2. This program is licensed "as is" without any warranty of any | |
| 28 | − * kind, whether express or implied. | |
| 29 | 26 | */ |
| 30 | 27 | |
| 31 | 28 | #define pr_fmt(fmt) "KGDB: " fmt |
| @@ -1,3 +1,4 @@ | ||
| 1 | +// SPDX-License-Identifier: GPL-2.0-only | |
| 1 | 2 | /* |
| 2 | 3 | * Kernel Debug Core |
| 3 | 4 | * |
| @@ -22,10 +23,6 @@ · 18 unmodified lines | ||
| 22 | 23 | * |
| 23 | 24 | * Original KGDB stub: David Grothe <dave@gcom.com>, |
| 24 | 25 | * Tigran Aivazian <tigran@sco.com> |
| 25 | − * | |
| 26 | − * This file is licensed under the terms of the GNU General Public License | |
| 27 | − * version 2. This program is licensed "as is" without any warranty of any | |
| 28 | − * kind, whether express or implied. | |
| 29 | 26 | */ |
| 30 | 27 | |
| 31 | 28 | #include <linux/kernel.h> |
| @@ -523,51 +523,51 @@ static int kdb_ss(int argc, const char **argv) · 522 unmodified lines | ||
| 523 | 523 | } |
| 524 | 524 | |
| 525 | 525 | static kdbtab_t bptab[] = { |
| 526 | − { .cmd_name = "bp", | |
| 527 | − .cmd_func = kdb_bp, | |
| 528 | − .cmd_usage = "[<vaddr>]", | |
| 529 | − .cmd_help = "Set/Display breakpoints", | |
| 530 | − .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, | |
| 526 | + { .name = "bp", | |
| 527 | + .func = kdb_bp, | |
| 528 | + .usage = "[<vaddr>]", | |
| 529 | + .help = "Set/Display breakpoints", | |
| 530 | + .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, | |
| 531 | 531 | }, |
| 532 | − { .cmd_name = "bl", | |
| 533 | − .cmd_func = kdb_bp, | |
| 534 | − .cmd_usage = "[<vaddr>]", | |
| 535 | − .cmd_help = "Display breakpoints", | |
| 536 | − .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, | |
| 532 | + { .name = "bl", | |
| 533 | + .func = kdb_bp, | |
| 534 | + .usage = "[<vaddr>]", | |
| 535 | + .help = "Display breakpoints", | |
| 536 | + .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, | |
| 537 | 537 | }, |
| 538 | − { .cmd_name = "bc", | |
| 539 | − .cmd_func = kdb_bc, | |
| 540 | − .cmd_usage = "<bpnum>", | |
| 541 | − .cmd_help = "Clear Breakpoint", | |
| 542 | − .cmd_flags = KDB_ENABLE_FLOW_CTRL, | |
| 538 | + { .name = "bc", | |
| 539 | + .func = kdb_bc, | |
| 540 | + .usage = "<bpnum>", | |
| 541 | + .help = "Clear Breakpoint", | |
| 542 | + .flags = KDB_ENABLE_FLOW_CTRL, | |
| 543 | 543 | }, |
| 544 | − { .cmd_name = "be", | |
| 545 | − .cmd_func = kdb_bc, | |
| 546 | − .cmd_usage = "<bpnum>", | |
| 547 | − .cmd_help = "Enable Breakpoint", | |
| 548 | − .cmd_flags = KDB_ENABLE_FLOW_CTRL, | |
| 544 | + { .name = "be", | |
| 545 | + .func = kdb_bc, | |
| 546 | + .usage = "<bpnum>", | |
| 547 | + .help = "Enable Breakpoint", | |
| 548 | + .flags = KDB_ENABLE_FLOW_CTRL, | |
| 549 | 549 | }, |
| 550 | − { .cmd_name = "bd", | |
| 551 | − .cmd_func = kdb_bc, | |
| 552 | − .cmd_usage = "<bpnum>", | |
| 553 | − .cmd_help = "Disable Breakpoint", | |
| 554 | − .cmd_flags = KDB_ENABLE_FLOW_CTRL, | |
| 550 | + { .name = "bd", | |
| 551 | + .func = kdb_bc, | |
| 552 | + .usage = "<bpnum>", | |
| 553 | + .help = "Disable Breakpoint", | |
| 554 | + .flags = KDB_ENABLE_FLOW_CTRL, | |
| 555 | 555 | }, |
| 556 | − { .cmd_name = "ss", | |
| 557 | − .cmd_func = kdb_ss, | |
| 558 | − .cmd_usage = "", | |
| 559 | − .cmd_help = "Single Step", | |
| 560 | − .cmd_minlen = 1, | |
| 561 | − .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, | |
| 556 | + { .name = "ss", | |
| 557 | + .func = kdb_ss, | |
| 558 | + .usage = "", | |
| 559 | + .help = "Single Step", | |
| 560 | + .minlen = 1, | |
| 561 | + .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, | |
| 562 | 562 | }, |
| 563 | 563 | }; |
| 564 | 564 | |
| 565 | 565 | static kdbtab_t bphcmd = { |
| 566 | − .cmd_name = "bph", | |
| 567 | − .cmd_func = kdb_bp, | |
| 568 | − .cmd_usage = "[<vaddr>]", | |
| 569 | − .cmd_help = "[datar [length]|dataw [length]] Set hw brk", | |
| 570 | − .cmd_flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, | |
| 566 | + .name = "bph", | |
| 567 | + .func = kdb_bp, | |
| 568 | + .usage = "[<vaddr>]", | |
| 569 | + .help = "[datar [length]|dataw [length]] Set hw brk", | |
| 570 | + .flags = KDB_ENABLE_FLOW_CTRL | KDB_REPEAT_NO_ARGS, | |
| 571 | 571 | }; |
| 572 | 572 | |
| 573 | 573 | /* Initialize the breakpoint table and register breakpoint commands. */ |
| @@ -140,7 +140,6 @@ int kdb_stub(struct kgdb_state *ks) · 139 unmodified lines | ||
| 140 | 140 | */ |
| 141 | 141 | kdb_common_deinit_state(); |
| 142 | 142 | KDB_STATE_CLEAR(PAGER); |
| 143 | − kdbnearsym_cleanup(); | |
| 144 | 143 | if (error == KDB_CMD_KGDB) { |
| 145 | 144 | if (KDB_STATE(DOING_KGDB)) |
| 146 | 145 | KDB_STATE_CLEAR(DOING_KGDB); |
| @@ -33,7 +33,6 @@ · 32 unmodified lines | ||
| 33 | 33 | #include <linux/kallsyms.h> |
| 34 | 34 | #include <linux/kgdb.h> |
| 35 | 35 | #include <linux/kdb.h> |
| 36 | −#include <linux/list.h> | |
| 37 | 36 | #include <linux/notifier.h> |
| 38 | 37 | #include <linux/interrupt.h> |
| 39 | 38 | #include <linux/delay.h> |
| @@ -654,16 +653,17 @@ static void kdb_cmderror(int diag) · 614 unmodified lines | ||
| 654 | 653 | * Returns: |
| 655 | 654 | * zero for success, a kdb diagnostic if error |
| 656 | 655 | */ |
| 657 | −struct defcmd_set { | |
| 658 | − int count; | |
| 659 | − bool usable; | |
| 660 | − char *name; | |
| 661 | − char *usage; | |
| 662 | − char *help; | |
| 663 | − char **command; | |
| 656 | +struct kdb_macro { | |
| 657 | + kdbtab_t cmd; /* Macro command */ | |
| 658 | + struct list_head statements; /* Associated statement list */ | |
| 664 | 659 | }; |
| 665 | −static struct defcmd_set *defcmd_set; | |
| 666 | −static int defcmd_set_count; | |
| 660 | + | |
| 661 | +struct kdb_macro_statement { | |
| 662 | + char *statement; /* Statement text */ | |
| 663 | + struct list_head list_node; /* Statement list node */ | |
| 664 | +}; | |
| 665 | + | |
| 666 | +static struct kdb_macro *kdb_macro; | |
| 667 | 667 | static bool defcmd_in_progress; |
| 668 | 668 | |
| 669 | 669 | /* Forward references */ |
| @@ -671,53 +671,55 @@ static int kdb_exec_defcmd(int argc, const char **argv); · 1 unmodified line | ||
| 671 | 671 | |
| 672 | 672 | static int kdb_defcmd2(const char *cmdstr, const char *argv0) |
| 673 | 673 | { |
| 674 | − struct defcmd_set *s = defcmd_set + defcmd_set_count - 1; | |
| 675 | − char **save_command = s->command; | |
| 674 | + struct kdb_macro_statement *kms; | |
| 675 | + | |
| 676 | + if (!kdb_macro) | |
| 677 | + return KDB_NOTIMP; | |
| 678 | + | |
| 676 | 679 | if (strcmp(argv0, "endefcmd") == 0) { |
| 677 | 680 | defcmd_in_progress = false; |
| 678 | − if (!s->count) | |
| 679 | − s->usable = false; | |
| 680 | − if (s->usable) | |
| 681 | − /* macros are always safe because when executed each | |
| 682 | − * internal command re-enters kdb_parse() and is | |
| 683 | − * safety checked individually. | |
| 684 | − */ | |
| 685 | − kdb_register_flags(s->name, kdb_exec_defcmd, s->usage, | |
| 686 | − s->help, 0, | |
| 687 | − KDB_ENABLE_ALWAYS_SAFE); | |
| 681 | + if (!list_empty(&kdb_macro->statements)) | |
| 682 | + kdb_register(&kdb_macro->cmd); | |
| 688 | 683 | return 0; |
| 689 | 684 | } |
| 690 | − if (!s->usable) | |
| 691 | − return KDB_NOTIMP; | |
| 692 | − s->command = kcalloc(s->count + 1, sizeof(*(s->command)), GFP_KDB); | |
| 693 | − if (!s->command) { | |
| 694 | − kdb_printf("Could not allocate new kdb_defcmd table for %s\n", | |
| 685 | + | |
| 686 | + kms = kmalloc(sizeof(*kms), GFP_KDB); | |
| 687 | + if (!kms) { | |
| 688 | + kdb_printf("Could not allocate new kdb macro command: %s\n", | |
| 695 | 689 | cmdstr); |
| 696 | − s->usable = false; | |
| 697 | 690 | return KDB_NOTIMP; |
| 698 | 691 | } |
| 699 | − memcpy(s->command, save_command, s->count * sizeof(*(s->command))); | |
| 700 | − s->command[s->count++] = kdb_strdup(cmdstr, GFP_KDB); | |
| 701 | − kfree(save_command); | |
| 692 | + | |
| 693 | + kms->statement = kdb_strdup(cmdstr, GFP_KDB); | |
| 694 | + list_add_tail(&kms->list_node, &kdb_macro->statements); | |
| 695 | + | |
| 702 | 696 | return 0; |
| 703 | 697 | } |
| 704 | 698 | |
| 705 | 699 | static int kdb_defcmd(int argc, const char **argv) |
| 706 | 700 | { |
| 707 | − struct defcmd_set *save_defcmd_set = defcmd_set, *s; | |
| 701 | + kdbtab_t *mp; | |
| 702 | + | |
| 708 | 703 | if (defcmd_in_progress) { |
| 709 | 704 | kdb_printf("kdb: nested defcmd detected, assuming missing " |
| 710 | 705 | "endefcmd\n"); |
| 711 | 706 | kdb_defcmd2("endefcmd", "endefcmd"); |
| 712 | 707 | } |
| 713 | 708 | if (argc == 0) { |
| 714 | − int i; | |
| 715 | − for (s = defcmd_set; s < defcmd_set + defcmd_set_count; ++s) { | |
| 716 | − kdb_printf("defcmd %s \"%s\" \"%s\"\n", s->name, | |
| 717 | − s->usage, s->help); | |
| 718 | − for (i = 0; i < s->count; ++i) | |
| 719 | − kdb_printf("%s", s->command[i]); | |
| 720 | − kdb_printf("endefcmd\n"); | |
| 709 | + kdbtab_t *kp; | |
| 710 | + struct kdb_macro *kmp; | |
| 711 | + struct kdb_macro_statement *kms; | |
| 712 | + | |
| 713 | + list_for_each_entry(kp, &kdb_cmds_head, list_node) { | |
| 714 | + if (kp->func == kdb_exec_defcmd) { | |
| 715 | + kdb_printf("defcmd %s \"%s\" \"%s\"\n", | |
| 716 | + kp->name, kp->usage, kp->help); | |
| 717 | + kmp = container_of(kp, struct kdb_macro, cmd); | |
| 718 | + list_for_each_entry(kms, &kmp->statements, | |
| 719 | + list_node) | |
| 720 | + kdb_printf("%s", kms->statement); | |
| 721 | + kdb_printf("endefcmd\n"); | |
| 722 | + } | |
| 721 | 723 | } |
| 722 | 724 | return 0; |
| 723 | 725 | } |
| @@ -727,45 +729,43 @@ static int kdb_defcmd(int argc, const char **argv) · 3 unmodified lines | ||
| 727 | 729 | kdb_printf("Command only available during kdb_init()\n"); |
| 728 | 730 | return KDB_NOTIMP; |
| 729 | 731 | } |
| 730 | − defcmd_set = kmalloc_array(defcmd_set_count + 1, sizeof(*defcmd_set), | |
| 731 | − GFP_KDB); | |
| 732 | − if (!defcmd_set) | |
| 732 | + kdb_macro = kzalloc(sizeof(*kdb_macro), GFP_KDB); | |
| 733 | + if (!kdb_macro) | |
| 733 | 734 | goto fail_defcmd; |
| 734 | − memcpy(defcmd_set, save_defcmd_set, | |
| 735 | − defcmd_set_count * sizeof(*defcmd_set)); | |
| 736 | − s = defcmd_set + defcmd_set_count; | |
| 737 | − memset(s, 0, sizeof(*s)); | |
| 738 | − s->usable = true; | |
| 739 | − s->name = kdb_strdup(argv[1], GFP_KDB); | |
| 740 | − if (!s->name) | |
| 735 | + | |
| 736 | + mp = &kdb_macro->cmd; | |
| 737 | + mp->func = kdb_exec_defcmd; | |
| 738 | + mp->minlen = 0; | |
| 739 | + mp->flags = KDB_ENABLE_ALWAYS_SAFE; | |
| 740 | + mp->name = kdb_strdup(argv[1], GFP_KDB); | |
| 741 | + if (!mp->name) | |
| 741 | 742 | goto fail_name; |
| 742 | − s->usage = kdb_strdup(argv[2], GFP_KDB); | |
| 743 | − if (!s->usage) | |
| 743 | + mp->usage = kdb_strdup(argv[2], GFP_KDB); | |
| 744 | + if (!mp->usage) | |
| 744 | 745 | goto fail_usage; |
| 745 | − s->help = kdb_strdup(argv[3], GFP_KDB); | |
| 746 | − if (!s->help) | |
| 746 | + mp->help = kdb_strdup(argv[3], GFP_KDB); | |
| 747 | + if (!mp->help) | |
| 747 | 748 | goto fail_help; |
| 748 | − if (s->usage[0] == '"') { | |
| 749 | − strcpy(s->usage, argv[2]+1); | |
| 750 | − s->usage[strlen(s->usage)-1] = '\0'; | |
| 749 | + if (mp->usage[0] == '"') { | |
| 750 | + strcpy(mp->usage, argv[2]+1); | |
| 751 | + mp->usage[strlen(mp->usage)-1] = '\0'; | |
| 751 | 752 | } |
| 752 | − if (s->help[0] == '"') { | |
| 753 | − strcpy(s->help, argv[3]+1); | |
| 754 | − s->help[strlen(s->help)-1] = '\0'; | |
| 753 | + if (mp->help[0] == '"') { | |
| 754 | + strcpy(mp->help, argv[3]+1); | |
| 755 | + mp->help[strlen(mp->help)-1] = '\0'; | |
| 755 | 756 | } |
| 756 | − ++defcmd_set_count; | |
| 757 | + | |
| 758 | + INIT_LIST_HEAD(&kdb_macro->statements); | |
| 757 | 759 | defcmd_in_progress = true; |
| 758 | − kfree(save_defcmd_set); | |
| 759 | 760 | return 0; |
| 760 | 761 | fail_help: |
| 761 | − kfree(s->usage); | |
| 762 | + kfree(mp->usage); | |
| 762 | 763 | fail_usage: |
| 763 | − kfree(s->name); | |
| 764 | + kfree(mp->name); | |
| 764 | 765 | fail_name: |
| 765 | − kfree(defcmd_set); | |
| 766 | + kfree(kdb_macro); | |
| 766 | 767 | fail_defcmd: |
| 767 | − kdb_printf("Could not allocate new defcmd_set entry for %s\n", argv[1]); | |
| 768 | − defcmd_set = save_defcmd_set; | |
| 768 | + kdb_printf("Could not allocate new kdb_macro entry for %s\n", argv[1]); | |
| 769 | 769 | return KDB_NOTIMP; |
| 770 | 770 | } |
| 771 | 771 | |
| @@ -780,25 +780,31 @@ fail_defcmd: · 8 unmodified lines | ||
| 780 | 780 | */ |
| 781 | 781 | static int kdb_exec_defcmd(int argc, const char **argv) |
| 782 | 782 | { |
| 783 | − int i, ret; | |
| 784 | − struct defcmd_set *s; | |
| 783 | + int ret; | |
| 784 | + kdbtab_t *kp; | |
| 785 | + struct kdb_macro *kmp; | |
| 786 | + struct kdb_macro_statement *kms; | |
| 787 | + | |
| 785 | 788 | if (argc != 0) |
| 786 | 789 | return KDB_ARGCOUNT; |
| 787 | − for (s = defcmd_set, i = 0; i < defcmd_set_count; ++i, ++s) { | |
| 788 | − if (strcmp(s->name, argv[0]) == 0) | |
| 790 | + | |
| 791 | + list_for_each_entry(kp, &kdb_cmds_head, list_node) { | |
| 792 | + if (strcmp(kp->name, argv[0]) == 0) | |
| 789 | 793 | break; |
| 790 | 794 | } |
| 791 | − if (i == defcmd_set_count) { | |
| 795 | + if (list_entry_is_head(kp, &kdb_cmds_head, list_node)) { | |
| 792 | 796 | kdb_printf("kdb_exec_defcmd: could not find commands for %s\n", |
| 793 | 797 | argv[0]); |
| 794 | 798 | return KDB_NOTIMP; |
| 795 | 799 | } |
| 796 | − for (i = 0; i < s->count; ++i) { | |
| 797 | − /* Recursive use of kdb_parse, do not use argv after | |
| 798 | − * this point */ | |
| 800 | + kmp = container_of(kp, struct kdb_macro, cmd); | |
| 801 | + list_for_each_entry(kms, &kmp->statements, list_node) { | |
| 802 | + /* | |
| 803 | + * Recursive use of kdb_parse, do not use argv after this point. | |
| 804 | + */ | |
| 799 | 805 | argv = NULL; |
| 800 | − kdb_printf("[%s]kdb> %s\n", s->name, s->command[i]); | |
| 801 | − ret = kdb_parse(s->command[i]); | |
| 806 | + kdb_printf("[%s]kdb> %s\n", kmp->cmd.name, kms->statement); | |
| 807 | + ret = kdb_parse(kms->statement); | |
| 802 | 808 | if (ret) |
| 803 | 809 | return ret; |
| 804 | 810 | } |
| @@ -1009,11 +1015,11 @@ int kdb_parse(const char *cmdstr) · 204 unmodified lines | ||
| 1009 | 1015 | * If this command is allowed to be abbreviated, |
| 1010 | 1016 | * check to see if this is it. |
| 1011 | 1017 | */ |
| 1012 | − if (tp->cmd_minlen && (strlen(argv[0]) <= tp->cmd_minlen) && | |
| 1013 | − (strncmp(argv[0], tp->cmd_name, tp->cmd_minlen) == 0)) | |
| 1018 | + if (tp->minlen && (strlen(argv[0]) <= tp->minlen) && | |
| 1019 | + (strncmp(argv[0], tp->name, tp->minlen) == 0)) | |
| 1014 | 1020 | break; |
| 1015 | 1021 | |
| 1016 | − if (strcmp(argv[0], tp->cmd_name) == 0) | |
| 1022 | + if (strcmp(argv[0], tp->name) == 0) | |
| 1017 | 1023 | break; |
| 1018 | 1024 | } |
| 1019 | 1025 | |
| @@ -1024,8 +1030,7 @@ int kdb_parse(const char *cmdstr) · 4 unmodified lines | ||
| 1024 | 1030 | */ |
| 1025 | 1031 | if (list_entry_is_head(tp, &kdb_cmds_head, list_node)) { |
| 1026 | 1032 | list_for_each_entry(tp, &kdb_cmds_head, list_node) { |
| 1027 | − if (strncmp(argv[0], tp->cmd_name, | |
| 1028 | − strlen(tp->cmd_name)) == 0) | |
| 1033 | + if (strncmp(argv[0], tp->name, strlen(tp->name)) == 0) | |
| 1029 | 1034 | break; |
| 1030 | 1035 | } |
| 1031 | 1036 | } |
| @@ -1033,19 +1038,19 @@ int kdb_parse(const char *cmdstr) · 1 unmodified line | ||
| 1033 | 1038 | if (!list_entry_is_head(tp, &kdb_cmds_head, list_node)) { |
| 1034 | 1039 | int result; |
| 1035 | 1040 | |
| 1036 | − if (!kdb_check_flags(tp->cmd_flags, kdb_cmd_enabled, argc <= 1)) | |
| 1041 | + if (!kdb_check_flags(tp->flags, kdb_cmd_enabled, argc <= 1)) | |
| 1037 | 1042 | return KDB_NOPERM; |
| 1038 | 1043 | |
| 1039 | 1044 | KDB_STATE_SET(CMD); |
| 1040 | − result = (*tp->cmd_func)(argc-1, (const char **)argv); | |
| 1045 | + result = (*tp->func)(argc-1, (const char **)argv); | |
| 1041 | 1046 | if (result && ignore_errors && result > KDB_CMD_GO) |
| 1042 | 1047 | result = 0; |
| 1043 | 1048 | KDB_STATE_CLEAR(CMD); |
| 1044 | 1049 | |
| 1045 | − if (tp->cmd_flags & KDB_REPEAT_WITH_ARGS) | |
| 1050 | + if (tp->flags & KDB_REPEAT_WITH_ARGS) | |
| 1046 | 1051 | return result; |
| 1047 | 1052 | |
| 1048 | − argc = tp->cmd_flags & KDB_REPEAT_NO_ARGS ? 1 : 0; | |
| 1053 | + argc = tp->flags & KDB_REPEAT_NO_ARGS ? 1 : 0; | |
| 1049 | 1054 | if (argv[argc]) |
| 1050 | 1055 | *(argv[argc]) = '\0'; |
| 1051 | 1056 | return result; |
| @@ -2412,12 +2417,12 @@ static int kdb_help(int argc, const char **argv) · 1360 unmodified lines | ||
| 2412 | 2417 | char *space = ""; |
| 2413 | 2418 | if (KDB_FLAG(CMD_INTERRUPT)) |
| 2414 | 2419 | return 0; |
| 2415 | − if (!kdb_check_flags(kt->cmd_flags, kdb_cmd_enabled, true)) | |
| 2420 | + if (!kdb_check_flags(kt->flags, kdb_cmd_enabled, true)) | |
| 2416 | 2421 | continue; |
| 2417 | − if (strlen(kt->cmd_usage) > 20) | |
| 2422 | + if (strlen(kt->usage) > 20) | |
| 2418 | 2423 | space = "\n "; |
| 2419 | − kdb_printf("%-15.15s %-20s%s%s\n", kt->cmd_name, | |
| 2420 | − kt->cmd_usage, space, kt->cmd_help); | |
| 2424 | + kdb_printf("%-15.15s %-20s%s%s\n", kt->name, | |
| 2425 | + kt->usage, space, kt->help); | |
| 2421 | 2426 | } |
| 2422 | 2427 | return 0; |
| 2423 | 2428 | } |
| @@ -2613,56 +2618,32 @@ static int kdb_grep_help(int argc, const char **argv) · 189 unmodified lines | ||
| 2613 | 2618 | return 0; |
| 2614 | 2619 | } |
| 2615 | 2620 | |
| 2616 | −/* | |
| 2617 | − * kdb_register_flags - This function is used to register a kernel | |
| 2618 | − * debugger command. | |
| 2619 | − * Inputs: | |
| 2620 | − * cmd Command name | |
| 2621 | − * func Function to execute the command | |
| 2622 | − * usage A simple usage string showing arguments | |
| 2623 | − * help A simple help string describing command | |
| 2624 | − * repeat Does the command auto repeat on enter? | |
| 2625 | − * Returns: | |
| 2626 | − * zero for success, one if a duplicate command. | |
| 2621 | +/** | |
| 2622 | + * kdb_register() - This function is used to register a kernel debugger | |
| 2623 | + * command. | |
| 2624 | + * @cmd: pointer to kdb command | |
| 2625 | + * | |
| 2626 | + * Note that it's the job of the caller to keep the memory for the cmd | |
| 2627 | + * allocated until unregister is called. | |
| 2627 | 2628 | */ |
| 2628 | −int kdb_register_flags(char *cmd, | |
| 2629 | − kdb_func_t func, | |
| 2630 | − char *usage, | |
| 2631 | − char *help, | |
| 2632 | − short minlen, | |
| 2633 | − kdb_cmdflags_t flags) | |
| 2629 | +int kdb_register(kdbtab_t *cmd) | |
| 2634 | 2630 | { |
| 2635 | 2631 | kdbtab_t *kp; |
| 2636 | 2632 | |
| 2637 | 2633 | list_for_each_entry(kp, &kdb_cmds_head, list_node) { |
| 2638 | − if (strcmp(kp->cmd_name, cmd) == 0) { | |
| 2639 | − kdb_printf("Duplicate kdb command registered: " | |
| 2640 | − "%s, func %px help %s\n", cmd, func, help); | |
| 2634 | + if (strcmp(kp->name, cmd->name) == 0) { | |
| 2635 | + kdb_printf("Duplicate kdb cmd: %s, func %p help %s\n", | |
| 2636 | + cmd->name, cmd->func, cmd->help); | |
| 2641 | 2637 | return 1; |
| 2642 | 2638 | } |
| 2643 | 2639 | } |
| 2644 | 2640 | |
| 2645 | − kp = kmalloc(sizeof(*kp), GFP_KDB); | |
| 2646 | − if (!kp) { | |
| 2647 | − kdb_printf("Could not allocate new kdb_command table\n"); | |
| 2648 | − return 1; | |
| 2649 | − } | |
| 2650 | − | |
| 2651 | − kp->cmd_name = cmd; | |
| 2652 | − kp->cmd_func = func; | |
| 2653 | − kp->cmd_usage = usage; | |
| 2654 | − kp->cmd_help = help; | |
| 2655 | − kp->cmd_minlen = minlen; | |
| 2656 | − kp->cmd_flags = flags; | |
| 2657 | − kp->is_dynamic = true; | |
| 2658 | − | |
| 2659 | − list_add_tail(&kp->list_node, &kdb_cmds_head); | |
| 2660 | − | |
| 2641 | + list_add_tail(&cmd->list_node, &kdb_cmds_head); | |
| 2661 | 2642 | return 0; |
| 2662 | 2643 | } |
| 2663 | −EXPORT_SYMBOL_GPL(kdb_register_flags); | |
| 2644 | +EXPORT_SYMBOL_GPL(kdb_register); | |
| 2664 | 2645 | |
| 2665 | −/* | |
| 2646 | +/** | |
| 2666 | 2647 | * kdb_register_table() - This function is used to register a kdb command |
| 2667 | 2648 | * table. |
| 2668 | 2649 | * @kp: pointer to kdb command table |
| @@ -2676,266 +2657,231 @@ void kdb_register_table(kdbtab_t *kp, size_t len) · 7 unmodified lines | ||
| 2676 | 2657 | } |
| 2677 | 2658 | } |
| 2678 | 2659 | |
| 2679 | −/* | |
| 2680 | − * kdb_register - Compatibility register function for commands that do | |
| 2681 | − * not need to specify a repeat state. Equivalent to | |
| 2682 | − * kdb_register_flags with flags set to 0. | |
| 2683 | − * Inputs: | |
| 2684 | − * cmd Command name | |
| 2685 | − * func Function to execute the command | |
| 2686 | − * usage A simple usage string showing arguments | |
| 2687 | − * help A simple help string describing command | |
| 2688 | − * Returns: | |
| 2689 | − * zero for success, one if a duplicate command. | |
| 2660 | +/** | |
| 2661 | + * kdb_unregister() - This function is used to unregister a kernel debugger | |
| 2662 | + * command. It is generally called when a module which | |
| 2663 | + * implements kdb command is unloaded. | |
| 2664 | + * @cmd: pointer to kdb command | |
| 2690 | 2665 | */ |
| 2691 | −int kdb_register(char *cmd, | |
| 2692 | − kdb_func_t func, | |
| 2693 | − char *usage, | |
| 2694 | − char *help, | |
| 2695 | − short minlen) | |
| 2666 | +void kdb_unregister(kdbtab_t *cmd) | |
| 2696 | 2667 | { |
| 2697 | − return kdb_register_flags(cmd, func, usage, help, minlen, 0); | |
| 2698 | −} | |
| 2699 | −EXPORT_SYMBOL_GPL(kdb_register); | |
| 2700 | − | |
| 2701 | −/* | |
| 2702 | − * kdb_unregister - This function is used to unregister a kernel | |
| 2703 | − * debugger command. It is generally called when a module which | |
| 2704 | − * implements kdb commands is unloaded. | |
| 2705 | − * Inputs: | |
| 2706 | − * cmd Command name | |
| 2707 | − * Returns: | |
| 2708 | − * zero for success, one command not registered. | |
| 2709 | − */ | |
| 2710 | −int kdb_unregister(char *cmd) | |
| 2711 | −{ | |
| 2712 | − kdbtab_t *kp; | |
| 2713 | − | |
| 2714 | − /* | |
| 2715 | − * find the command. | |
| 2716 | − */ | |
| 2717 | − list_for_each_entry(kp, &kdb_cmds_head, list_node) { | |
| 2718 | − if (strcmp(kp->cmd_name, cmd) == 0) { | |
| 2719 | − list_del(&kp->list_node); | |
| 2720 | − if (kp->is_dynamic) | |
| 2721 | − kfree(kp); | |
| 2722 | − return 0; | |
| 2723 | − } | |
| 2724 | − } | |
| 2725 | − | |
| 2726 | − /* Couldn't find it. */ | |
| 2727 | − return 1; | |
| 2668 | + list_del(&cmd->list_node); | |
| 2728 | 2669 | } |
| 2729 | 2670 | EXPORT_SYMBOL_GPL(kdb_unregister); |
| 2730 | 2671 | |
| 2731 | 2672 | static kdbtab_t maintab[] = { |
| 2732 | − { .cmd_name = "md", | |
| 2733 | − .cmd_func = kdb_md, | |
| 2734 | − .cmd_usage = "<vaddr>", | |
| 2735 | − .cmd_help = "Display Memory Contents, also mdWcN, e.g. md8c1", | |
| 2736 | − .cmd_minlen = 1, | |
| 2737 | − .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, | |
| 2673 | + { .name = "md", | |
| 2674 | + .func = kdb_md, | |
| 2675 | + .usage = "<vaddr>", | |
| 2676 | + .help = "Display Memory Contents, also mdWcN, e.g. md8c1", | |
| 2677 | + .minlen = 1, | |
| 2678 | + .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, | |
| 2738 | 2679 | }, |
| 2739 | − { .cmd_name = "mdr", | |
| 2740 | − .cmd_func = kdb_md, | |
| 2741 | − .cmd_usage = "<vaddr> <bytes>", | |
| 2742 | − .cmd_help = "Display Raw Memory", | |
| 2743 | − .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, | |
| 2680 | + { .name = "mdr", | |
| 2681 | + .func = kdb_md, | |
| 2682 | + .usage = "<vaddr> <bytes>", | |
| 2683 | + .help = "Display Raw Memory", | |
| 2684 | + .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, | |
| 2744 | 2685 | }, |
| 2745 | − { .cmd_name = "mdp", | |
| 2746 | − .cmd_func = kdb_md, | |
| 2747 | − .cmd_usage = "<paddr> <bytes>", | |
| 2748 | − .cmd_help = "Display Physical Memory", | |
| 2749 | − .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, | |
| 2686 | + { .name = "mdp", | |
| 2687 | + .func = kdb_md, | |
| 2688 | + .usage = "<paddr> <bytes>", | |
| 2689 | + .help = "Display Physical Memory", | |
| 2690 | + .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, | |
| 2750 | 2691 | }, |
| 2751 | − { .cmd_name = "mds", | |
| 2752 | − .cmd_func = kdb_md, | |
| 2753 | − .cmd_usage = "<vaddr>", | |
| 2754 | − .cmd_help = "Display Memory Symbolically", | |
| 2755 | − .cmd_flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, | |
| 2692 | + { .name = "mds", | |
| 2693 | + .func = kdb_md, | |
| 2694 | + .usage = "<vaddr>", | |
| 2695 | + .help = "Display Memory Symbolically", | |
| 2696 | + .flags = KDB_ENABLE_MEM_READ | KDB_REPEAT_NO_ARGS, | |
| 2756 | 2697 | }, |
| 2757 | − { .cmd_name = "mm", | |
| 2758 | − .cmd_func = kdb_mm, | |
| 2759 | − .cmd_usage = "<vaddr> <contents>", | |
| 2760 | − .cmd_help = "Modify Memory Contents", | |
| 2761 | − .cmd_flags = KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS, | |
| 2698 | + { .name = "mm", | |
| 2699 | + .func = kdb_mm, | |
| 2700 | + .usage = "<vaddr> <contents>", | |
| 2701 | + .help = "Modify Memory Contents", | |
| 2702 | + .flags = KDB_ENABLE_MEM_WRITE | KDB_REPEAT_NO_ARGS, | |
| 2762 | 2703 | }, |
| 2763 | − { .cmd_name = "go", | |
| 2764 | − .cmd_func = kdb_go, | |
| 2765 | − .cmd_usage = "[<vaddr>]", | |
| 2766 | − .cmd_help = "Continue Execution", | |
| 2767 | − .cmd_minlen = 1, | |
| 2768 | − .cmd_flags = KDB_ENABLE_REG_WRITE | | |
| 2704 | + { .name = "go", | |
| 2705 | + .func = kdb_go, | |
| 2706 | + .usage = "[<vaddr>]", | |
| 2707 | + .help = "Continue Execution", | |
| 2708 | + .minlen = 1, | |
| 2709 | + .flags = KDB_ENABLE_REG_WRITE | | |
| 2769 | 2710 | KDB_ENABLE_ALWAYS_SAFE_NO_ARGS, |
| 2770 | 2711 | }, |
| 2771 | − { .cmd_name = "rd", | |
| 2772 | − .cmd_func = kdb_rd, | |
| 2773 | − .cmd_usage = "", | |
| 2774 | − .cmd_help = "Display Registers", | |
| 2775 | − .cmd_flags = KDB_ENABLE_REG_READ, | |
| 2712 | + { .name = "rd", | |
| 2713 | + .func = kdb_rd, | |
| 2714 | + .usage = "", | |
| 2715 | + .help = "Display Registers", | |
| 2716 | + .flags = KDB_ENABLE_REG_READ, | |
| 2776 | 2717 | }, |
| 2777 | − { .cmd_name = "rm", | |
| 2778 | − .cmd_func = kdb_rm, | |
| 2779 | − .cmd_usage = "<reg> <contents>", | |
| 2780 | − .cmd_help = "Modify Registers", | |
| 2781 | − .cmd_flags = KDB_ENABLE_REG_WRITE, | |
| 2718 | + { .name = "rm", | |
| 2719 | + .func = kdb_rm, | |
| 2720 | + .usage = "<reg> <contents>", | |
| 2721 | + .help = "Modify Registers", | |
| 2722 | + .flags = KDB_ENABLE_REG_WRITE, | |
| 2782 | 2723 | }, |
| 2783 | − { .cmd_name = "ef", | |
| 2784 | − .cmd_func = kdb_ef, | |
| 2785 | − .cmd_usage = "<vaddr>", | |
| 2786 | − .cmd_help = "Display exception frame", | |
| 2787 | − .cmd_flags = KDB_ENABLE_MEM_READ, | |
| 2724 | + { .name = "ef", | |
| 2725 | + .func = kdb_ef, | |
| 2726 | + .usage = "<vaddr>", | |
| 2727 | + .help = "Display exception frame", | |
| 2728 | + .flags = KDB_ENABLE_MEM_READ, | |
| 2788 | 2729 | }, |
| 2789 | − { .cmd_name = "bt", | |
| 2790 | − .cmd_func = kdb_bt, | |
| 2791 | − .cmd_usage = "[<vaddr>]", | |
| 2792 | − .cmd_help = "Stack traceback", | |
| 2793 | − .cmd_minlen = 1, | |
| 2794 | − .cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS, | |
| 2730 | + { .name = "bt", | |
| 2731 | + .func = kdb_bt, | |
| 2732 | + .usage = "[<vaddr>]", | |
| 2733 | + .help = "Stack traceback", | |
| 2734 | + .minlen = 1, | |
| 2735 | + .flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS, | |
| 2795 | 2736 | }, |
| 2796 | − { .cmd_name = "btp", | |
| 2797 | − .cmd_func = kdb_bt, | |
| 2798 | − .cmd_usage = "<pid>", | |
| 2799 | − .cmd_help = "Display stack for process <pid>", | |
| 2800 | − .cmd_flags = KDB_ENABLE_INSPECT, | |
| 2737 | + { .name = "btp", | |
| 2738 | + .func = kdb_bt, | |
| 2739 | + .usage = "<pid>", | |
| 2740 | + .help = "Display stack for process <pid>", | |
| 2741 | + .flags = KDB_ENABLE_INSPECT, | |
| 2801 | 2742 | }, |
| 2802 | − { .cmd_name = "bta", | |
| 2803 | − .cmd_func = kdb_bt, | |
| 2804 | − .cmd_usage = "[D|R|S|T|C|Z|E|U|I|M|A]", | |
| 2805 | − .cmd_help = "Backtrace all processes matching state flag", | |
| 2806 | − .cmd_flags = KDB_ENABLE_INSPECT, | |
| 2743 | + { .name = "bta", | |
| 2744 | + .func = kdb_bt, | |
| 2745 | + .usage = "[D|R|S|T|C|Z|E|U|I|M|A]", | |
| 2746 | + .help = "Backtrace all processes matching state flag", | |
| 2747 | + .flags = KDB_ENABLE_INSPECT, | |
| 2807 | 2748 | }, |
| 2808 | − { .cmd_name = "btc", | |
| 2809 | − .cmd_func = kdb_bt, | |
| 2810 | − .cmd_usage = "", | |
| 2811 | − .cmd_help = "Backtrace current process on each cpu", | |
| 2812 | − .cmd_flags = KDB_ENABLE_INSPECT, | |
| 2749 | + { .name = "btc", | |
| 2750 | + .func = kdb_bt, | |
| 2751 | + .usage = "", | |
| 2752 | + .help = "Backtrace current process on each cpu", | |
| 2753 | + .flags = KDB_ENABLE_INSPECT, | |
| 2813 | 2754 | }, |
| 2814 | − { .cmd_name = "btt", | |
| 2815 | − .cmd_func = kdb_bt, | |
| 2816 | − .cmd_usage = "<vaddr>", | |
| 2817 | − .cmd_help = "Backtrace process given its struct task address", | |
| 2818 | − .cmd_flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS, | |
| 2755 | + { .name = "btt", | |
| 2756 | + .func = kdb_bt, | |
| 2757 | + .usage = "<vaddr>", | |
| 2758 | + .help = "Backtrace process given its struct task address", | |
| 2759 | + .flags = KDB_ENABLE_MEM_READ | KDB_ENABLE_INSPECT_NO_ARGS, | |
| 2819 | 2760 | }, |
| 2820 | − { .cmd_name = "env", | |
| 2821 | − .cmd_func = kdb_env, | |
| 2822 | − .cmd_usage = "", | |
| 2823 | − .cmd_help = "Show environment variables", | |
| 2824 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2761 | + { .name = "env", | |
| 2762 | + .func = kdb_env, | |
| 2763 | + .usage = "", | |
| 2764 | + .help = "Show environment variables", | |
| 2765 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2825 | 2766 | }, |
| 2826 | − { .cmd_name = "set", | |
| 2827 | − .cmd_func = kdb_set, | |
| 2828 | − .cmd_usage = "", | |
| 2829 | − .cmd_help = "Set environment variables", | |
| 2830 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2767 | + { .name = "set", | |
| 2768 | + .func = kdb_set, | |
| 2769 | + .usage = "", | |
| 2770 | + .help = "Set environment variables", | |
| 2771 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2831 | 2772 | }, |
| 2832 | − { .cmd_name = "help", | |
| 2833 | − .cmd_func = kdb_help, | |
| 2834 | − .cmd_usage = "", | |
| 2835 | − .cmd_help = "Display Help Message", | |
| 2836 | − .cmd_minlen = 1, | |
| 2837 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2773 | + { .name = "help", | |
| 2774 | + .func = kdb_help, | |
| 2775 | + .usage = "", | |
| 2776 | + .help = "Display Help Message", | |
| 2777 | + .minlen = 1, | |
| 2778 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2838 | 2779 | }, |
| 2839 | − { .cmd_name = "?", | |
| 2840 | − .cmd_func = kdb_help, | |
| 2841 | − .cmd_usage = "", | |
| 2842 | − .cmd_help = "Display Help Message", | |
| 2843 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2780 | + { .name = "?", | |
| 2781 | + .func = kdb_help, | |
| 2782 | + .usage = "", | |
| 2783 | + .help = "Display Help Message", | |
| 2784 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2844 | 2785 | }, |
| 2845 | − { .cmd_name = "cpu", | |
| 2846 | − .cmd_func = kdb_cpu, | |
| 2847 | − .cmd_usage = "<cpunum>", | |
| 2848 | − .cmd_help = "Switch to new cpu", | |
| 2849 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE_NO_ARGS, | |
| 2786 | + { .name = "cpu", | |
| 2787 | + .func = kdb_cpu, | |
| 2788 | + .usage = "<cpunum>", | |
| 2789 | + .help = "Switch to new cpu", | |
| 2790 | + .flags = KDB_ENABLE_ALWAYS_SAFE_NO_ARGS, | |
| 2850 | 2791 | }, |
| 2851 | − { .cmd_name = "kgdb", | |
| 2852 | − .cmd_func = kdb_kgdb, | |
| 2853 | − .cmd_usage = "", | |
| 2854 | − .cmd_help = "Enter kgdb mode", | |
| 2855 | − .cmd_flags = 0, | |
| 2792 | + { .name = "kgdb", | |
| 2793 | + .func = kdb_kgdb, | |
| 2794 | + .usage = "", | |
| 2795 | + .help = "Enter kgdb mode", | |
| 2796 | + .flags = 0, | |
| 2856 | 2797 | }, |
| 2857 | − { .cmd_name = "ps", | |
| 2858 | − .cmd_func = kdb_ps, | |
| 2859 | − .cmd_usage = "[<flags>|A]", | |
| 2860 | − .cmd_help = "Display active task list", | |
| 2861 | − .cmd_flags = KDB_ENABLE_INSPECT, | |
| 2798 | + { .name = "ps", | |
| 2799 | + .func = kdb_ps, | |
| 2800 | + .usage = "[<flags>|A]", | |
| 2801 | + .help = "Display active task list", | |
| 2802 | + .flags = KDB_ENABLE_INSPECT, | |
| 2862 | 2803 | }, |
| 2863 | − { .cmd_name = "pid", | |
| 2864 | − .cmd_func = kdb_pid, | |
| 2865 | − .cmd_usage = "<pidnum>", | |
| 2866 | − .cmd_help = "Switch to another task", | |
| 2867 | − .cmd_flags = KDB_ENABLE_INSPECT, | |
| 2804 | + { .name = "pid", | |
| 2805 | + .func = kdb_pid, | |
| 2806 | + .usage = "<pidnum>", | |
| 2807 | + .help = "Switch to another task", | |
| 2808 | + .flags = KDB_ENABLE_INSPECT, | |
| 2868 | 2809 | }, |
| 2869 | − { .cmd_name = "reboot", | |
| 2870 | − .cmd_func = kdb_reboot, | |
| 2871 | − .cmd_usage = "", | |
| 2872 | − .cmd_help = "Reboot the machine immediately", | |
| 2873 | − .cmd_flags = KDB_ENABLE_REBOOT, | |
| 2810 | + { .name = "reboot", | |
| 2811 | + .func = kdb_reboot, | |
| 2812 | + .usage = "", | |
| 2813 | + .help = "Reboot the machine immediately", | |
| 2814 | + .flags = KDB_ENABLE_REBOOT, | |
| 2874 | 2815 | }, |
| 2875 | 2816 | #if defined(CONFIG_MODULES) |
| 2876 | − { .cmd_name = "lsmod", | |
| 2877 | − .cmd_func = kdb_lsmod, | |
| 2878 | − .cmd_usage = "", | |
| 2879 | − .cmd_help = "List loaded kernel modules", | |
| 2880 | − .cmd_flags = KDB_ENABLE_INSPECT, | |
| 2817 | + { .name = "lsmod", | |
| 2818 | + .func = kdb_lsmod, | |
| 2819 | + .usage = "", | |
| 2820 | + .help = "List loaded kernel modules", | |
| 2821 | + .flags = KDB_ENABLE_INSPECT, | |
| 2881 | 2822 | }, |
| 2882 | 2823 | #endif |
| 2883 | 2824 | #if defined(CONFIG_MAGIC_SYSRQ) |
| 2884 | − { .cmd_name = "sr", | |
| 2885 | − .cmd_func = kdb_sr, | |
| 2886 | − .cmd_usage = "<key>", | |
| 2887 | − .cmd_help = "Magic SysRq key", | |
| 2888 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2825 | + { .name = "sr", | |
| 2826 | + .func = kdb_sr, | |
| 2827 | + .usage = "<key>", | |
| 2828 | + .help = "Magic SysRq key", | |
| 2829 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2889 | 2830 | }, |
| 2890 | 2831 | #endif |
| 2891 | 2832 | #if defined(CONFIG_PRINTK) |
| 2892 | − { .cmd_name = "dmesg", | |
| 2893 | − .cmd_func = kdb_dmesg, | |
| 2894 | − .cmd_usage = "[lines]", | |
| 2895 | − .cmd_help = "Display syslog buffer", | |
| 2896 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2833 | + { .name = "dmesg", | |
| 2834 | + .func = kdb_dmesg, | |
| 2835 | + .usage = "[lines]", | |
| 2836 | + .help = "Display syslog buffer", | |
| 2837 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2897 | 2838 | }, |
| 2898 | 2839 | #endif |
| 2899 | − { .cmd_name = "defcmd", | |
| 2900 | − .cmd_func = kdb_defcmd, | |
| 2901 | − .cmd_usage = "name \"usage\" \"help\"", | |
| 2902 | − .cmd_help = "Define a set of commands, down to endefcmd", | |
| 2903 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2840 | + { .name = "defcmd", | |
| 2841 | + .func = kdb_defcmd, | |
| 2842 | + .usage = "name \"usage\" \"help\"", | |
| 2843 | + .help = "Define a set of commands, down to endefcmd", | |
| 2844 | + /* | |
| 2845 | + * Macros are always safe because when executed each | |
| 2846 | + * internal command re-enters kdb_parse() and is safety | |
| 2847 | + * checked individually. | |
| 2848 | + */ | |
| 2849 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2904 | 2850 | }, |
| 2905 | − { .cmd_name = "kill", | |
| 2906 | − .cmd_func = kdb_kill, | |
| 2907 | − .cmd_usage = "<-signal> <pid>", | |
| 2908 | − .cmd_help = "Send a signal to a process", | |
| 2909 | − .cmd_flags = KDB_ENABLE_SIGNAL, | |
| 2851 | + { .name = "kill", | |
| 2852 | + .func = kdb_kill, | |
| 2853 | + .usage = "<-signal> <pid>", | |
| 2854 | + .help = "Send a signal to a process", | |
| 2855 | + .flags = KDB_ENABLE_SIGNAL, | |
| 2910 | 2856 | }, |
| 2911 | − { .cmd_name = "summary", | |
| 2912 | − .cmd_func = kdb_summary, | |
| 2913 | − .cmd_usage = "", | |
| 2914 | − .cmd_help = "Summarize the system", | |
| 2915 | − .cmd_minlen = 4, | |
| 2916 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2857 | + { .name = "summary", | |
| 2858 | + .func = kdb_summary, | |
| 2859 | + .usage = "", | |
| 2860 | + .help = "Summarize the system", | |
| 2861 | + .minlen = 4, | |
| 2862 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2917 | 2863 | }, |
| 2918 | − { .cmd_name = "per_cpu", | |
| 2919 | − .cmd_func = kdb_per_cpu, | |
| 2920 | − .cmd_usage = "<sym> [<bytes>] [<cpu>]", | |
| 2921 | − .cmd_help = "Display per_cpu variables", | |
| 2922 | − .cmd_minlen = 3, | |
| 2923 | − .cmd_flags = KDB_ENABLE_MEM_READ, | |
| 2864 | + { .name = "per_cpu", | |
| 2865 | + .func = kdb_per_cpu, | |
| 2866 | + .usage = "<sym> [<bytes>] [<cpu>]", | |
| 2867 | + .help = "Display per_cpu variables", | |
| 2868 | + .minlen = 3, | |
| 2869 | + .flags = KDB_ENABLE_MEM_READ, | |
| 2924 | 2870 | }, |
| 2925 | − { .cmd_name = "grephelp", | |
| 2926 | − .cmd_func = kdb_grep_help, | |
| 2927 | − .cmd_usage = "", | |
| 2928 | − .cmd_help = "Display help on | grep", | |
| 2929 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2871 | + { .name = "grephelp", | |
| 2872 | + .func = kdb_grep_help, | |
| 2873 | + .usage = "", | |
| 2874 | + .help = "Display help on | grep", | |
| 2875 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2930 | 2876 | }, |
| 2931 | 2877 | }; |
| 2932 | 2878 | |
| 2933 | 2879 | static kdbtab_t nmicmd = { |
| 2934 | − .cmd_name = "disable_nmi", | |
| 2935 | − .cmd_func = kdb_disable_nmi, | |
| 2936 | − .cmd_usage = "", | |
| 2937 | − .cmd_help = "Disable NMI entry to KDB", | |
| 2938 | − .cmd_flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2880 | + .name = "disable_nmi", | |
| 2881 | + .func = kdb_disable_nmi, | |
| 2882 | + .usage = "", | |
| 2883 | + .help = "Disable NMI entry to KDB", | |
| 2884 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 2939 | 2885 | }; |
| 2940 | 2886 | |
| 2941 | 2887 | /* Initialize the kdb command table. */ |
| @@ -109,7 +109,6 @@ extern int kdbgetaddrarg(int, const char **, int*, unsigned long *, · 108 unmodified lines | ||
| 109 | 109 | long *, char **); |
| 110 | 110 | extern int kdbgetsymval(const char *, kdb_symtab_t *); |
| 111 | 111 | extern int kdbnearsym(unsigned long, kdb_symtab_t *); |
| 112 | −extern void kdbnearsym_cleanup(void); | |
| 113 | 112 | extern char *kdb_strdup(const char *str, gfp_t type); |
| 114 | 113 | extern void kdb_symbol_print(unsigned long, const kdb_symtab_t *, unsigned int); |
| 115 | 114 | |
| @@ -165,19 +164,6 @@ typedef struct _kdb_bp { · 49 unmodified lines | ||
| 165 | 164 | #ifdef CONFIG_KGDB_KDB |
| 166 | 165 | extern kdb_bp_t kdb_breakpoints[/* KDB_MAXBPT */]; |
| 167 | 166 | |
| 168 | −/* The KDB shell command table */ | |
| 169 | −typedef struct _kdbtab { | |
| 170 | − char *cmd_name; /* Command name */ | |
| 171 | − kdb_func_t cmd_func; /* Function to execute command */ | |
| 172 | − char *cmd_usage; /* Usage String for this command */ | |
| 173 | − char *cmd_help; /* Help message for this command */ | |
| 174 | − short cmd_minlen; /* Minimum legal # command | |
| 175 | − * chars required */ | |
| 176 | − kdb_cmdflags_t cmd_flags; /* Command behaviour flags */ | |
| 177 | − struct list_head list_node; /* Command list */ | |
| 178 | − bool is_dynamic; /* Command table allocation type */ | |
| 179 | −} kdbtab_t; | |
| 180 | − | |
| 181 | 167 | extern void kdb_register_table(kdbtab_t *kp, size_t len); |
| 182 | 168 | extern int kdb_bt(int, const char **); /* KDB display back trace */ |
| 183 | 169 | |
| @@ -233,10 +219,6 @@ extern struct task_struct *kdb_curr_task(int); · 49 unmodified lines | ||
| 233 | 219 | |
| 234 | 220 | #define GFP_KDB (in_dbg_master() ? GFP_ATOMIC : GFP_KERNEL) |
| 235 | 221 | |
| 236 | −extern void *debug_kmalloc(size_t size, gfp_t flags); | |
| 237 | −extern void debug_kfree(void *); | |
| 238 | −extern void debug_kusage(void); | |
| 239 | − | |
| 240 | 222 | extern struct task_struct *kdb_current_task; |
| 241 | 223 | extern struct pt_regs *kdb_current_regs; |
| 242 | 224 | |
| @@ -51,48 +51,48 @@ int kdbgetsymval(const char *symname, kdb_symtab_t *symtab) · 50 unmodified lines | ||
| 51 | 51 | } |
| 52 | 52 | EXPORT_SYMBOL(kdbgetsymval); |
| 53 | 53 | |
| 54 | −static char *kdb_name_table[100]; /* arbitrary size */ | |
| 55 | − | |
| 56 | −/* | |
| 57 | − * kdbnearsym - Return the name of the symbol with the nearest address | |
| 58 | − * less than 'addr'. | |
| 54 | +/** | |
| 55 | + * kdbnearsym() - Return the name of the symbol with the nearest address | |
| 56 | + * less than @addr. | |
| 57 | + * @addr: Address to check for near symbol | |
| 58 | + * @symtab: Structure to receive results | |
| 59 | 59 | * |
| 60 | − * Parameters: | |
| 61 | − * addr Address to check for symbol near | |
| 62 | − * symtab Structure to receive results | |
| 63 | − * Returns: | |
| 64 | − * 0 No sections contain this address, symtab zero filled | |
| 65 | − * 1 Address mapped to module/symbol/section, data in symtab | |
| 66 | − * Remarks: | |
| 67 | − * 2.6 kallsyms has a "feature" where it unpacks the name into a | |
| 68 | − * string. If that string is reused before the caller expects it | |
| 69 | − * then the caller sees its string change without warning. To | |
| 70 | − * avoid cluttering up the main kdb code with lots of kdb_strdup, | |
| 71 | − * tests and kfree calls, kdbnearsym maintains an LRU list of the | |
| 72 | − * last few unique strings. The list is sized large enough to | |
| 73 | − * hold active strings, no kdb caller of kdbnearsym makes more | |
| 74 | − * than ~20 later calls before using a saved value. | |
| 60 | + * WARNING: This function may return a pointer to a single statically | |
| 61 | + * allocated buffer (namebuf). kdb's unusual calling context (single | |
| 62 | + * threaded, all other CPUs halted) provides us sufficient locking for | |
| 63 | + * this to be safe. The only constraint imposed by the static buffer is | |
| 64 | + * that the caller must consume any previous reply prior to another call | |
| 65 | + * to lookup a new symbol. | |
| 66 | + * | |
| 67 | + * Note that, strictly speaking, some architectures may re-enter the kdb | |
| 68 | + * trap if the system turns out to be very badly damaged and this breaks | |
| 69 | + * the single-threaded assumption above. In these circumstances successful | |
| 70 | + * continuation and exit from the inner trap is unlikely to work and any | |
| 71 | + * user attempting this receives a prominent warning before being allowed | |
| 72 | + * to progress. In these circumstances we remain memory safe because | |
| 73 | + * namebuf[KSYM_NAME_LEN-1] will never change from '\0' although we do | |
| 74 | + * tolerate the possibility of garbled symbol display from the outer kdb | |
| 75 | + * trap. | |
| 76 | + * | |
| 77 | + * Return: | |
| 78 | + * * 0 - No sections contain this address, symtab zero filled | |
| 79 | + * * 1 - Address mapped to module/symbol/section, data in symtab | |
| 75 | 80 | */ |
| 76 | 81 | int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab) |
| 77 | 82 | { |
| 78 | 83 | int ret = 0; |
| 79 | 84 | unsigned long symbolsize = 0; |
| 80 | 85 | unsigned long offset = 0; |
| 81 | −#define knt1_size 128 /* must be >= kallsyms table size */ | |
| 82 | − char *knt1 = NULL; | |
| 86 | + static char namebuf[KSYM_NAME_LEN]; | |
| 83 | 87 | |
| 84 | 88 | kdb_dbg_printf(AR, "addr=0x%lx, symtab=%px\n", addr, symtab); |
| 85 | 89 | memset(symtab, 0, sizeof(*symtab)); |
| 86 | 90 | |
| 87 | 91 | if (addr < 4096) |
| 88 | 92 | goto out; |
| 89 | − knt1 = debug_kmalloc(knt1_size, GFP_ATOMIC); | |
| 90 | − if (!knt1) { | |
| 91 | − kdb_func_printf("addr=0x%lx cannot kmalloc knt1\n", addr); | |
| 92 | − goto out; | |
| 93 | − } | |
| 93 | + | |
| 94 | 94 | symtab->sym_name = kallsyms_lookup(addr, &symbolsize , &offset, |
| 95 | − (char **)(&symtab->mod_name), knt1); | |
| 95 | + (char **)(&symtab->mod_name), namebuf); | |
| 96 | 96 | if (offset > 8*1024*1024) { |
| 97 | 97 | symtab->sym_name = NULL; |
| 98 | 98 | addr = offset = symbolsize = 0; |
| @@ -101,63 +101,14 @@ int kdbnearsym(unsigned long addr, kdb_symtab_t *symtab) · 2 unmodified lines | ||
| 101 | 101 | symtab->sym_end = symtab->sym_start + symbolsize; |
| 102 | 102 | ret = symtab->sym_name != NULL && *(symtab->sym_name) != '\0'; |
| 103 | 103 | |
| 104 | − if (ret) { | |
| 105 | − int i; | |
| 106 | − /* Another 2.6 kallsyms "feature". Sometimes the sym_name is | |
| 107 | − * set but the buffer passed into kallsyms_lookup is not used, | |
| 108 | − * so it contains garbage. The caller has to work out which | |
| 109 | − * buffer needs to be saved. | |
| 110 | − * | |
| 111 | − * What was Rusty smoking when he wrote that code? | |
| 112 | − */ | |
| 113 | − if (symtab->sym_name != knt1) { | |
| 114 | − strncpy(knt1, symtab->sym_name, knt1_size); | |
| 115 | − knt1[knt1_size-1] = '\0'; | |
| 116 | − } | |
| 117 | − for (i = 0; i < ARRAY_SIZE(kdb_name_table); ++i) { | |
| 118 | − if (kdb_name_table[i] && | |
| 119 | − strcmp(kdb_name_table[i], knt1) == 0) | |
| 120 | − break; | |
| 121 | − } | |
| 122 | − if (i >= ARRAY_SIZE(kdb_name_table)) { | |
| 123 | − debug_kfree(kdb_name_table[0]); | |
| 124 | − memmove(kdb_name_table, kdb_name_table+1, | |
| 125 | − sizeof(kdb_name_table[0]) * | |
| 126 | − (ARRAY_SIZE(kdb_name_table)-1)); | |
| 127 | − } else { | |
| 128 | − debug_kfree(knt1); | |
| 129 | − knt1 = kdb_name_table[i]; | |
| 130 | − memmove(kdb_name_table+i, kdb_name_table+i+1, | |
| 131 | − sizeof(kdb_name_table[0]) * | |
| 132 | − (ARRAY_SIZE(kdb_name_table)-i-1)); | |
| 133 | − } | |
| 134 | − i = ARRAY_SIZE(kdb_name_table) - 1; | |
| 135 | − kdb_name_table[i] = knt1; | |
| 136 | − symtab->sym_name = kdb_name_table[i]; | |
| 137 | − knt1 = NULL; | |
| 138 | − } | |
| 139 | − | |
| 140 | 104 | if (symtab->mod_name == NULL) |
| 141 | 105 | symtab->mod_name = "kernel"; |
| 142 | 106 | kdb_dbg_printf(AR, "returns %d symtab->sym_start=0x%lx, symtab->mod_name=%px, symtab->sym_name=%px (%s)\n", |
| 143 | 107 | ret, symtab->sym_start, symtab->mod_name, symtab->sym_name, symtab->sym_name); |
| 144 | − | |
| 145 | 108 | out: |
| 146 | − debug_kfree(knt1); | |
| 147 | 109 | return ret; |
| 148 | 110 | } |
| 149 | 111 | |
| 150 | −void kdbnearsym_cleanup(void) | |
| 151 | −{ | |
| 152 | − int i; | |
| 153 | − for (i = 0; i < ARRAY_SIZE(kdb_name_table); ++i) { | |
| 154 | − if (kdb_name_table[i]) { | |
| 155 | − debug_kfree(kdb_name_table[i]); | |
| 156 | − kdb_name_table[i] = NULL; | |
| 157 | − } | |
| 158 | − } | |
| 159 | −} | |
| 160 | − | |
| 161 | 112 | static char ks_namebuf[KSYM_NAME_LEN+1], ks_namebuf_prev[KSYM_NAME_LEN+1]; |
| 162 | 113 | |
| 163 | 114 | /* |
| @@ -655,230 +606,6 @@ unsigned long kdb_task_state(const struct task_struct *p, unsigned long mask) · 491 unmodified lines | ||
| 655 | 606 | return (mask & kdb_task_state_string(state)) != 0; |
| 656 | 607 | } |
| 657 | 608 | |
| 658 | −/* Last ditch allocator for debugging, so we can still debug even when | |
| 659 | − * the GFP_ATOMIC pool has been exhausted. The algorithms are tuned | |
| 660 | − * for space usage, not for speed. One smallish memory pool, the free | |
| 661 | − * chain is always in ascending address order to allow coalescing, | |
| 662 | − * allocations are done in brute force best fit. | |
| 663 | − */ | |
| 664 | − | |
| 665 | −struct debug_alloc_header { | |
| 666 | − u32 next; /* offset of next header from start of pool */ | |
| 667 | − u32 size; | |
| 668 | − void *caller; | |
| 669 | −}; | |
| 670 | − | |
| 671 | −/* The memory returned by this allocator must be aligned, which means | |
| 672 | − * so must the header size. Do not assume that sizeof(struct | |
| 673 | − * debug_alloc_header) is a multiple of the alignment, explicitly | |
| 674 | − * calculate the overhead of this header, including the alignment. | |
| 675 | − * The rest of this code must not use sizeof() on any header or | |
| 676 | − * pointer to a header. | |
| 677 | − */ | |
| 678 | −#define dah_align 8 | |
| 679 | −#define dah_overhead ALIGN(sizeof(struct debug_alloc_header), dah_align) | |
| 680 | − | |
| 681 | −static u64 debug_alloc_pool_aligned[256*1024/dah_align]; /* 256K pool */ | |
| 682 | −static char *debug_alloc_pool = (char *)debug_alloc_pool_aligned; | |
| 683 | −static u32 dah_first, dah_first_call = 1, dah_used, dah_used_max; | |
| 684 | − | |
| 685 | −/* Locking is awkward. The debug code is called from all contexts, | |
| 686 | − * including non maskable interrupts. A normal spinlock is not safe | |
| 687 | − * in NMI context. Try to get the debug allocator lock, if it cannot | |
| 688 | − * be obtained after a second then give up. If the lock could not be | |
| 689 | − * previously obtained on this cpu then only try once. | |
| 690 | − * | |
| 691 | − * sparse has no annotation for "this function _sometimes_ acquires a | |
| 692 | − * lock", so fudge the acquire/release notation. | |
| 693 | − */ | |
| 694 | −static DEFINE_SPINLOCK(dap_lock); | |
| 695 | −static int get_dap_lock(void) | |
| 696 | − __acquires(dap_lock) | |
| 697 | −{ | |
| 698 | − static int dap_locked = -1; | |
| 699 | − int count; | |
| 700 | − if (dap_locked == smp_processor_id()) | |
| 701 | − count = 1; | |
| 702 | − else | |
| 703 | − count = 1000; | |
| 704 | − while (1) { | |
| 705 | − if (spin_trylock(&dap_lock)) { | |
| 706 | − dap_locked = -1; | |
| 707 | − return 1; | |
| 708 | − } | |
| 709 | − if (!count--) | |
| 710 | − break; | |
| 711 | − udelay(1000); | |
| 712 | − } | |
| 713 | − dap_locked = smp_processor_id(); | |
| 714 | − __acquire(dap_lock); | |
| 715 | − return 0; | |
| 716 | −} | |
| 717 | − | |
| 718 | −void *debug_kmalloc(size_t size, gfp_t flags) | |
| 719 | −{ | |
| 720 | − unsigned int rem, h_offset; | |
| 721 | − struct debug_alloc_header *best, *bestprev, *prev, *h; | |
| 722 | − void *p = NULL; | |
| 723 | − if (!get_dap_lock()) { | |
| 724 | − __release(dap_lock); /* we never actually got it */ | |
| 725 | − return NULL; | |
| 726 | − } | |
| 727 | − h = (struct debug_alloc_header *)(debug_alloc_pool + dah_first); | |
| 728 | − if (dah_first_call) { | |
| 729 | − h->size = sizeof(debug_alloc_pool_aligned) - dah_overhead; | |
| 730 | − dah_first_call = 0; | |
| 731 | − } | |
| 732 | − size = ALIGN(size, dah_align); | |
| 733 | − prev = best = bestprev = NULL; | |
| 734 | − while (1) { | |
| 735 | − if (h->size >= size && (!best || h->size < best->size)) { | |
| 736 | − best = h; | |
| 737 | − bestprev = prev; | |
| 738 | − if (h->size == size) | |
| 739 | − break; | |
| 740 | − } | |
| 741 | − if (!h->next) | |
| 742 | − break; | |
| 743 | − prev = h; | |
| 744 | − h = (struct debug_alloc_header *)(debug_alloc_pool + h->next); | |
| 745 | − } | |
| 746 | − if (!best) | |
| 747 | − goto out; | |
| 748 | − rem = best->size - size; | |
| 749 | − /* The pool must always contain at least one header */ | |
| 750 | − if (best->next == 0 && bestprev == NULL && rem < dah_overhead) | |
| 751 | − goto out; | |
| 752 | − if (rem >= dah_overhead) { | |
| 753 | − best->size = size; | |
| 754 | − h_offset = ((char *)best - debug_alloc_pool) + | |
| 755 | − dah_overhead + best->size; | |
| 756 | − h = (struct debug_alloc_header *)(debug_alloc_pool + h_offset); | |
| 757 | − h->size = rem - dah_overhead; | |
| 758 | − h->next = best->next; | |
| 759 | − } else | |
| 760 | − h_offset = best->next; | |
| 761 | − best->caller = __builtin_return_address(0); | |
| 762 | − dah_used += best->size; | |
| 763 | − dah_used_max = max(dah_used, dah_used_max); | |
| 764 | − if (bestprev) | |
| 765 | − bestprev->next = h_offset; | |
| 766 | − else | |
| 767 | − dah_first = h_offset; | |
| 768 | − p = (char *)best + dah_overhead; | |
| 769 | − memset(p, POISON_INUSE, best->size - 1); | |
| 770 | − *((char *)p + best->size - 1) = POISON_END; | |
| 771 | −out: | |
| 772 | − spin_unlock(&dap_lock); | |
| 773 | − return p; | |
| 774 | −} | |
| 775 | − | |
| 776 | −void debug_kfree(void *p) | |
| 777 | −{ | |
| 778 | − struct debug_alloc_header *h; | |
| 779 | − unsigned int h_offset; | |
| 780 | − if (!p) | |
| 781 | − return; | |
| 782 | − if ((char *)p < debug_alloc_pool || | |
| 783 | − (char *)p >= debug_alloc_pool + sizeof(debug_alloc_pool_aligned)) { | |
| 784 | − kfree(p); | |
| 785 | − return; | |
| 786 | − } | |
| 787 | − if (!get_dap_lock()) { | |
| 788 | − __release(dap_lock); /* we never actually got it */ | |
| 789 | − return; /* memory leak, cannot be helped */ | |
| 790 | − } | |
| 791 | − h = (struct debug_alloc_header *)((char *)p - dah_overhead); | |
| 792 | − memset(p, POISON_FREE, h->size - 1); | |
| 793 | − *((char *)p + h->size - 1) = POISON_END; | |
| 794 | − h->caller = NULL; | |
| 795 | − dah_used -= h->size; | |
| 796 | − h_offset = (char *)h - debug_alloc_pool; | |
| 797 | − if (h_offset < dah_first) { | |
| 798 | − h->next = dah_first; | |
| 799 | − dah_first = h_offset; | |
| 800 | − } else { | |
| 801 | − struct debug_alloc_header *prev; | |
| 802 | − unsigned int prev_offset; | |
| 803 | − prev = (struct debug_alloc_header *)(debug_alloc_pool + | |
| 804 | − dah_first); | |
| 805 | − while (1) { | |
| 806 | − if (!prev->next || prev->next > h_offset) | |
| 807 | − break; | |
| 808 | − prev = (struct debug_alloc_header *) | |
| 809 | − (debug_alloc_pool + prev->next); | |
| 810 | − } | |
| 811 | − prev_offset = (char *)prev - debug_alloc_pool; | |
| 812 | − if (prev_offset + dah_overhead + prev->size == h_offset) { | |
| 813 | − prev->size += dah_overhead + h->size; | |
| 814 | − memset(h, POISON_FREE, dah_overhead - 1); | |
| 815 | − *((char *)h + dah_overhead - 1) = POISON_END; | |
| 816 | − h = prev; | |
| 817 | − h_offset = prev_offset; | |
| 818 | − } else { | |
| 819 | − h->next = prev->next; | |
| 820 | − prev->next = h_offset; | |
| 821 | − } | |
| 822 | − } | |
| 823 | − if (h_offset + dah_overhead + h->size == h->next) { | |
| 824 | − struct debug_alloc_header *next; | |
| 825 | − next = (struct debug_alloc_header *) | |
| 826 | − (debug_alloc_pool + h->next); | |
| 827 | − h->size += dah_overhead + next->size; | |
| 828 | − h->next = next->next; | |
| 829 | − memset(next, POISON_FREE, dah_overhead - 1); | |
| 830 | − *((char *)next + dah_overhead - 1) = POISON_END; | |
| 831 | − } | |
| 832 | − spin_unlock(&dap_lock); | |
| 833 | −} | |
| 834 | − | |
| 835 | −void debug_kusage(void) | |
| 836 | −{ | |
| 837 | − struct debug_alloc_header *h_free, *h_used; | |
| 838 | −#ifdef CONFIG_IA64 | |
| 839 | − /* FIXME: using dah for ia64 unwind always results in a memory leak. | |
| 840 | − * Fix that memory leak first, then set debug_kusage_one_time = 1 for | |
| 841 | − * all architectures. | |
| 842 | − */ | |
| 843 | − static int debug_kusage_one_time; | |
| 844 | −#else | |
| 845 | − static int debug_kusage_one_time = 1; | |
| 846 | −#endif | |
| 847 | − if (!get_dap_lock()) { | |
| 848 | − __release(dap_lock); /* we never actually got it */ | |
| 849 | − return; | |
| 850 | − } | |
| 851 | − h_free = (struct debug_alloc_header *)(debug_alloc_pool + dah_first); | |
| 852 | − if (dah_first == 0 && | |
| 853 | − (h_free->size == sizeof(debug_alloc_pool_aligned) - dah_overhead || | |
| 854 | − dah_first_call)) | |
| 855 | − goto out; | |
| 856 | − if (!debug_kusage_one_time) | |
| 857 | − goto out; | |
| 858 | − debug_kusage_one_time = 0; | |
| 859 | − kdb_func_printf("debug_kmalloc memory leak dah_first %d\n", dah_first); | |
| 860 | − if (dah_first) { | |
| 861 | − h_used = (struct debug_alloc_header *)debug_alloc_pool; | |
| 862 | − kdb_func_printf("h_used %px size %d\n", h_used, h_used->size); | |
| 863 | − } | |
| 864 | − do { | |
| 865 | − h_used = (struct debug_alloc_header *) | |
| 866 | − ((char *)h_free + dah_overhead + h_free->size); | |
| 867 | − kdb_func_printf("h_used %px size %d caller %px\n", | |
| 868 | − h_used, h_used->size, h_used->caller); | |
| 869 | − h_free = (struct debug_alloc_header *) | |
| 870 | − (debug_alloc_pool + h_free->next); | |
| 871 | − } while (h_free->next); | |
| 872 | − h_used = (struct debug_alloc_header *) | |
| 873 | − ((char *)h_free + dah_overhead + h_free->size); | |
| 874 | − if ((char *)h_used - debug_alloc_pool != | |
| 875 | − sizeof(debug_alloc_pool_aligned)) | |
| 876 | − kdb_func_printf("h_used %px size %d caller %px\n", | |
| 877 | − h_used, h_used->size, h_used->caller); | |
| 878 | −out: | |
| 879 | − spin_unlock(&dap_lock); | |
| 880 | −} | |
| 881 | − | |
| 882 | 609 | /* Maintain a small stack of kdb_flags to allow recursion without disturbing |
| 883 | 610 | * the global kdb state. |
| 884 | 611 | */ |
| @@ -147,11 +147,17 @@ static int kdb_ftdump(int argc, const char **argv) · 146 unmodified lines | ||
| 147 | 147 | return 0; |
| 148 | 148 | } |
| 149 | 149 | |
| 150 | +static kdbtab_t ftdump_cmd = { | |
| 151 | + .name = "ftdump", | |
| 152 | + .func = kdb_ftdump, | |
| 153 | + .usage = "[skip_#entries] [cpu]", | |
| 154 | + .help = "Dump ftrace log; -skip dumps last #entries", | |
| 155 | + .flags = KDB_ENABLE_ALWAYS_SAFE, | |
| 156 | +}; | |
| 157 | + | |
| 150 | 158 | static __init int kdb_ftrace_register(void) |
| 151 | 159 | { |
| 152 | − kdb_register_flags("ftdump", kdb_ftdump, "[skip_#entries] [cpu]", | |
| 153 | − "Dump ftrace log; -skip dumps last #entries", 0, | |
| 154 | − KDB_ENABLE_ALWAYS_SAFE); | |
| 160 | + kdb_register(&ftdump_cmd); | |
| 155 | 161 | return 0; |
| 156 | 162 | } |
| 157 | 163 | |
| @@ -28,28 +28,26 @@ static int kdb_hello_cmd(int argc, const char **argv) · 27 unmodified lines | ||
| 28 | 28 | return 0; |
| 29 | 29 | } |
| 30 | 30 | |
| 31 | +static kdbtab_t hello_cmd = { | |
| 32 | + .name = "hello", | |
| 33 | + .func = kdb_hello_cmd, | |
| 34 | + .usage = "[string]", | |
| 35 | + .help = "Say Hello World or Hello [string]", | |
| 36 | +}; | |
| 31 | 37 | |
| 32 | 38 | static int __init kdb_hello_cmd_init(void) |
| 33 | 39 | { |
| 34 | 40 | /* |
| 35 | 41 | * Registration of a dynamically added kdb command is done with |
| 36 | − * kdb_register() with the arguments being: | |
| 37 | − * 1: The name of the shell command | |
| 38 | − * 2: The function that processes the command | |
| 39 | − * 3: Description of the usage of any arguments | |
| 40 | − * 4: Descriptive text when you run help | |
| 41 | − * 5: Number of characters to complete the command | |
| 42 | − * 0 == type the whole command | |
| 43 | − * 1 == match both "g" and "go" for example | |
| 42 | + * kdb_register(). | |
| 44 | 43 | */ |
| 45 | − kdb_register("hello", kdb_hello_cmd, "[string]", | |
| 46 | − "Say Hello World or Hello [string]", 0); | |
| 44 | + kdb_register(&hello_cmd); | |
| 47 | 45 | return 0; |
| 48 | 46 | } |
| 49 | 47 | |
| 50 | 48 | static void __exit kdb_hello_cmd_exit(void) |
| 51 | 49 | { |
| 52 | − kdb_unregister("hello"); | |
| 50 | + kdb_unregister(&hello_cmd); | |
| 53 | 51 | } |
| 54 | 52 | |
| 55 | 53 | module_init(kdb_hello_cmd_init); |