diff options
| author | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2003-01-23 04:48:34 +0000 |
|---|---|---|
| committer | andersen <andersen@69ca8d6d-28ef-0310-b511-8ec308f3f277> | 2003-01-23 04:48:34 +0000 |
| commit | 45a135a3297bb0f3d9ea3c5885cc944fef84b233 (patch) | |
| tree | cc128ffae1d15623a9c81956fa854e3365247494 /modutils | |
| parent | 5754689c5e5ee2592214b7ad9f17157c320012a4 (diff) | |
| download | busybox-w32-45a135a3297bb0f3d9ea3c5885cc944fef84b233.tar.gz busybox-w32-45a135a3297bb0f3d9ea3c5885cc944fef84b233.tar.bz2 busybox-w32-45a135a3297bb0f3d9ea3c5885cc944fef84b233.zip | |
Patch from Joel Vallier to add modules symbols to the kernel symbol
table in order to obtain better debug output from ksymoops.
git-svn-id: svn://busybox.net/trunk/busybox@6427 69ca8d6d-28ef-0310-b511-8ec308f3f277
Diffstat (limited to 'modutils')
| -rw-r--r-- | modutils/Config.in | 11 | ||||
| -rw-r--r-- | modutils/insmod.c | 176 |
2 files changed, 185 insertions, 2 deletions
diff --git a/modutils/Config.in b/modutils/Config.in index 9af0ad6dc..98aef0032 100644 --- a/modutils/Config.in +++ b/modutils/Config.in | |||
| @@ -40,6 +40,17 @@ config CONFIG_FEATURE_INSMOD_VERSION_CHECKING | |||
| 40 | help | 40 | help |
| 41 | Please submit a patch to add help text for this item. | 41 | Please submit a patch to add help text for this item. |
| 42 | 42 | ||
| 43 | config CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS | ||
| 44 | bool " Add module symbols to kernel symbol table" | ||
| 45 | default n | ||
| 46 | depends on CONFIG_INSMOD | ||
| 47 | help | ||
| 48 | By adding module symbols to the kernel symbol table, Oops messages | ||
| 49 | occuring within kernel modules can be properly debugged. By enabling | ||
| 50 | this feature, module symbols will always be added to the kernel symbol | ||
| 51 | table for properly debugging support. If you are not interested in | ||
| 52 | Oops messages from kernel modules, say N. | ||
| 53 | |||
| 43 | config CONFIG_FEATURE_INSMOD_LOADINKMEM | 54 | config CONFIG_FEATURE_INSMOD_LOADINKMEM |
| 44 | bool " In kernel memory optimization (uClinux only)" | 55 | bool " In kernel memory optimization (uClinux only)" |
| 45 | default n | 56 | default n |
diff --git a/modutils/insmod.c b/modutils/insmod.c index eda4e1a48..db9e1997e 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c | |||
| @@ -234,7 +234,7 @@ | |||
| 234 | #ifndef MODUTILS_MODULE_H | 234 | #ifndef MODUTILS_MODULE_H |
| 235 | static const int MODUTILS_MODULE_H = 1; | 235 | static const int MODUTILS_MODULE_H = 1; |
| 236 | 236 | ||
| 237 | #ident "$Id: insmod.c,v 1.92 2002/11/28 11:27:27 aaronl Exp $" | 237 | #ident "$Id: insmod.c,v 1.93 2003/01/23 04:48:34 andersen Exp $" |
| 238 | 238 | ||
| 239 | /* This file contains the structures used by the 2.0 and 2.1 kernels. | 239 | /* This file contains the structures used by the 2.0 and 2.1 kernels. |
| 240 | We do not use the kernel headers directly because we do not wish | 240 | We do not use the kernel headers directly because we do not wish |
| @@ -455,7 +455,7 @@ int delete_module(const char *); | |||
| 455 | #ifndef MODUTILS_OBJ_H | 455 | #ifndef MODUTILS_OBJ_H |
| 456 | static const int MODUTILS_OBJ_H = 1; | 456 | static const int MODUTILS_OBJ_H = 1; |
| 457 | 457 | ||
| 458 | #ident "$Id: insmod.c,v 1.92 2002/11/28 11:27:27 aaronl Exp $" | 458 | #ident "$Id: insmod.c,v 1.93 2003/01/23 04:48:34 andersen Exp $" |
| 459 | 459 | ||
| 460 | /* The relocatable object is manipulated using elfin types. */ | 460 | /* The relocatable object is manipulated using elfin types. */ |
| 461 | 461 | ||
| @@ -2654,6 +2654,37 @@ static int new_create_this_module(struct obj_file *f, const char *m_name) | |||
| 2654 | return 1; | 2654 | return 1; |
| 2655 | } | 2655 | } |
| 2656 | 2656 | ||
| 2657 | #ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS | ||
| 2658 | /* add an entry to the __ksymtab section, creating it if necessary */ | ||
| 2659 | static void new_add_ksymtab(struct obj_file *f, struct obj_symbol *sym) | ||
| 2660 | { | ||
| 2661 | struct obj_section *sec; | ||
| 2662 | ElfW(Addr) ofs; | ||
| 2663 | |||
| 2664 | /* ensure __ksymtab is allocated, EXPORT_NOSYMBOLS creates a non-alloc section. | ||
| 2665 | * If __ksymtab is defined but not marked alloc, x out the first character | ||
| 2666 | * (no obj_delete routine) and create a new __ksymtab with the correct | ||
| 2667 | * characteristics. | ||
| 2668 | */ | ||
| 2669 | sec = obj_find_section(f, "__ksymtab"); | ||
| 2670 | if (sec && !(sec->header.sh_flags & SHF_ALLOC)) { | ||
| 2671 | *((char *)(sec->name)) = 'x'; /* override const */ | ||
| 2672 | sec = NULL; | ||
| 2673 | } | ||
| 2674 | if (!sec) | ||
| 2675 | sec = obj_create_alloced_section(f, "__ksymtab", | ||
| 2676 | tgt_sizeof_void_p, 0); | ||
| 2677 | if (!sec) | ||
| 2678 | return; | ||
| 2679 | sec->header.sh_flags |= SHF_ALLOC; | ||
| 2680 | sec->header.sh_addralign = tgt_sizeof_void_p; /* Empty section might | ||
| 2681 | be byte-aligned */ | ||
| 2682 | ofs = sec->header.sh_size; | ||
| 2683 | obj_symbol_patch(f, sec->idx, ofs, sym); | ||
| 2684 | obj_string_patch(f, sec->idx, ofs + tgt_sizeof_void_p, sym->name); | ||
| 2685 | obj_extend_section(sec, 2 * tgt_sizeof_char_p); | ||
| 2686 | } | ||
| 2687 | #endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */ | ||
| 2657 | 2688 | ||
| 2658 | static int new_create_module_ksymtab(struct obj_file *f) | 2689 | static int new_create_module_ksymtab(struct obj_file *f) |
| 2659 | { | 2690 | { |
| @@ -2811,6 +2842,7 @@ new_init_module(const char *m_name, struct obj_file *f, | |||
| 2811 | 2842 | ||
| 2812 | #define new_init_module(x, y, z) TRUE | 2843 | #define new_init_module(x, y, z) TRUE |
| 2813 | #define new_create_this_module(x, y) 0 | 2844 | #define new_create_this_module(x, y) 0 |
| 2845 | #define new_add_ksymtab(x, y) -1 | ||
| 2814 | #define new_create_module_ksymtab(x) | 2846 | #define new_create_module_ksymtab(x) |
| 2815 | #define query_module(v, w, x, y, z) -1 | 2847 | #define query_module(v, w, x, y, z) -1 |
| 2816 | 2848 | ||
| @@ -3538,6 +3570,142 @@ static void check_tainted_module(struct obj_file *f, char *m_name) | |||
| 3538 | #define check_tainted_module(x, y) do { } while(0); | 3570 | #define check_tainted_module(x, y) do { } while(0); |
| 3539 | #endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */ | 3571 | #endif /* CONFIG_FEATURE_CHECK_TAINTED_MODULE */ |
| 3540 | 3572 | ||
| 3573 | #ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS | ||
| 3574 | /* add module source, timestamp, kernel version and a symbol for the | ||
| 3575 | * start of some sections. this info is used by ksymoops to do better | ||
| 3576 | * debugging. | ||
| 3577 | */ | ||
| 3578 | static int | ||
| 3579 | get_module_version(struct obj_file *f, char str[STRVERSIONLEN]) | ||
| 3580 | { | ||
| 3581 | #ifdef CONFIG_FEATURE_INSMOD_VERSION_CHECKING | ||
| 3582 | if (get_modinfo_value(f, "kernel_version") == NULL) | ||
| 3583 | return old_get_module_version(f, str); | ||
| 3584 | else | ||
| 3585 | return new_get_module_version(f, str); | ||
| 3586 | #else /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */ | ||
| 3587 | strncpy(str, "???", sizeof(str)); | ||
| 3588 | return -1; | ||
| 3589 | #endif /* CONFIG_FEATURE_INSMOD_VERSION_CHECKING */ | ||
| 3590 | } | ||
| 3591 | |||
| 3592 | /* add module source, timestamp, kernel version and a symbol for the | ||
| 3593 | * start of some sections. this info is used by ksymoops to do better | ||
| 3594 | * debugging. | ||
| 3595 | */ | ||
| 3596 | static void | ||
| 3597 | add_ksymoops_symbols(struct obj_file *f, const char *filename, | ||
| 3598 | const char *m_name) | ||
| 3599 | { | ||
| 3600 | static const char symprefix[] = "__insmod_"; | ||
| 3601 | struct obj_section *sec; | ||
| 3602 | struct obj_symbol *sym; | ||
| 3603 | char *name, *absolute_filename; | ||
| 3604 | char str[STRVERSIONLEN], real[PATH_MAX]; | ||
| 3605 | int i, l, lm_name, lfilename, use_ksymtab, version; | ||
| 3606 | struct stat statbuf; | ||
| 3607 | |||
| 3608 | static const char *section_names[] = { | ||
| 3609 | ".text", | ||
| 3610 | ".rodata", | ||
| 3611 | ".data", | ||
| 3612 | ".bss" | ||
| 3613 | ".sbss" | ||
| 3614 | }; | ||
| 3615 | |||
| 3616 | if (realpath(filename, real)) { | ||
| 3617 | absolute_filename = xstrdup(real); | ||
| 3618 | } | ||
| 3619 | else { | ||
| 3620 | int save_errno = errno; | ||
| 3621 | error_msg("cannot get realpath for %s", filename); | ||
| 3622 | errno = save_errno; | ||
| 3623 | perror(""); | ||
| 3624 | absolute_filename = xstrdup(filename); | ||
| 3625 | } | ||
| 3626 | |||
| 3627 | lm_name = strlen(m_name); | ||
| 3628 | lfilename = strlen(absolute_filename); | ||
| 3629 | |||
| 3630 | /* add to ksymtab if it already exists or there is no ksymtab and other symbols | ||
| 3631 | * are not to be exported. otherwise leave ksymtab alone for now, the | ||
| 3632 | * "export all symbols" compatibility code will export these symbols later. | ||
| 3633 | */ | ||
| 3634 | use_ksymtab = obj_find_section(f, "__ksymtab") || !flag_export; | ||
| 3635 | |||
| 3636 | if ((sec = obj_find_section(f, ".this"))) { | ||
| 3637 | /* tag the module header with the object name, last modified | ||
| 3638 | * timestamp and module version. worst case for module version | ||
| 3639 | * is 0xffffff, decimal 16777215. putting all three fields in | ||
| 3640 | * one symbol is less readable but saves kernel space. | ||
| 3641 | */ | ||
| 3642 | l = sizeof(symprefix)+ /* "__insmod_" */ | ||
| 3643 | lm_name+ /* module name */ | ||
| 3644 | 2+ /* "_O" */ | ||
| 3645 | lfilename+ /* object filename */ | ||
| 3646 | 2+ /* "_M" */ | ||
| 3647 | 2*sizeof(statbuf.st_mtime)+ /* mtime in hex */ | ||
| 3648 | 2+ /* "_V" */ | ||
| 3649 | 8+ /* version in dec */ | ||
| 3650 | 1; /* nul */ | ||
| 3651 | name = xmalloc(l); | ||
| 3652 | if (stat(absolute_filename, &statbuf) != 0) | ||
| 3653 | statbuf.st_mtime = 0; | ||
| 3654 | version = get_module_version(f, str); /* -1 if not found */ | ||
| 3655 | snprintf(name, l, "%s%s_O%s_M%0*lX_V%d", | ||
| 3656 | symprefix, m_name, absolute_filename, | ||
| 3657 | (int)(2*sizeof(statbuf.st_mtime)), statbuf.st_mtime, | ||
| 3658 | version); | ||
| 3659 | sym = obj_add_symbol(f, name, -1, | ||
| 3660 | ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE), | ||
| 3661 | sec->idx, sec->header.sh_addr, 0); | ||
| 3662 | if (use_ksymtab) | ||
| 3663 | new_add_ksymtab(f, sym); | ||
| 3664 | } | ||
| 3665 | free(absolute_filename); | ||
| 3666 | #ifdef _NOT_SUPPORTED_ | ||
| 3667 | /* record where the persistent data is going, same address as previous symbol */ | ||
| 3668 | |||
| 3669 | if (f->persist) { | ||
| 3670 | l = sizeof(symprefix)+ /* "__insmod_" */ | ||
| 3671 | lm_name+ /* module name */ | ||
| 3672 | 2+ /* "_P" */ | ||
| 3673 | strlen(f->persist)+ /* data store */ | ||
| 3674 | 1; /* nul */ | ||
| 3675 | name = xmalloc(l); | ||
| 3676 | snprintf(name, l, "%s%s_P%s", | ||
| 3677 | symprefix, m_name, f->persist); | ||
| 3678 | sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE), | ||
| 3679 | sec->idx, sec->header.sh_addr, 0); | ||
| 3680 | if (use_ksymtab) | ||
| 3681 | new_add_ksymtab(f, sym); | ||
| 3682 | } | ||
| 3683 | #endif /* _NOT_SUPPORTED_ */ | ||
| 3684 | /* tag the desired sections if size is non-zero */ | ||
| 3685 | |||
| 3686 | for (i = 0; i < sizeof(section_names)/sizeof(section_names[0]); ++i) { | ||
| 3687 | if ((sec = obj_find_section(f, section_names[i])) && | ||
| 3688 | sec->header.sh_size) { | ||
| 3689 | l = sizeof(symprefix)+ /* "__insmod_" */ | ||
| 3690 | lm_name+ /* module name */ | ||
| 3691 | 2+ /* "_S" */ | ||
| 3692 | strlen(sec->name)+ /* section name */ | ||
| 3693 | 2+ /* "_L" */ | ||
| 3694 | 8+ /* length in dec */ | ||
| 3695 | 1; /* nul */ | ||
| 3696 | name = xmalloc(l); | ||
| 3697 | snprintf(name, l, "%s%s_S%s_L%ld", | ||
| 3698 | symprefix, m_name, sec->name, | ||
| 3699 | (long)sec->header.sh_size); | ||
| 3700 | sym = obj_add_symbol(f, name, -1, ELFW(ST_INFO) (STB_GLOBAL, STT_NOTYPE), | ||
| 3701 | sec->idx, sec->header.sh_addr, 0); | ||
| 3702 | if (use_ksymtab) | ||
| 3703 | new_add_ksymtab(f, sym); | ||
| 3704 | } | ||
| 3705 | } | ||
| 3706 | } | ||
| 3707 | #endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */ | ||
| 3708 | |||
| 3541 | extern int insmod_main( int argc, char **argv) | 3709 | extern int insmod_main( int argc, char **argv) |
| 3542 | { | 3710 | { |
| 3543 | int opt; | 3711 | int opt; |
| @@ -3788,6 +3956,10 @@ extern int insmod_main( int argc, char **argv) | |||
| 3788 | arch_create_got(f); | 3956 | arch_create_got(f); |
| 3789 | hide_special_symbols(f); | 3957 | hide_special_symbols(f); |
| 3790 | 3958 | ||
| 3959 | #ifdef CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS | ||
| 3960 | add_ksymoops_symbols(f, m_filename, m_name); | ||
| 3961 | #endif /* CONFIG_FEATURE_INSMOD_KSYMOOPS_SYMBOLS */ | ||
| 3962 | |||
| 3791 | if (k_new_syscalls) | 3963 | if (k_new_syscalls) |
| 3792 | new_create_module_ksymtab(f); | 3964 | new_create_module_ksymtab(f); |
| 3793 | 3965 | ||
