Add C version of recordmcount for MIPS
cover Add C version of recordmcount for MIPS
From: Wu Zhangjin <[email protected]>
This patchset adds the C Version of recordmcount for MIPS, it includes the necessary fixups for the MIPS64 support and module support of the old recordmcount.c.
To add MIPS64 support, John has introduced function pointers which can be overriden by specific e_machine(.e.g. EM_MIPS, EM_xx) in do_file() of scripts/recordmcount.c. this method helps a lot, when migrating from the old Perl recordmcount, the left Archs may possibly apply this method to add their specific support. Maciej has simplified the MIPS specific ELF64_Rel.r_info and the related functions.
The module support for MIPS is such a good application of John's method, it adds MIPS_is_fake_mcount() to filter one of the two _mcount symbol of the long mcount call, a function pointer: is_fake_mcount() points to the default 'empty' fn_is_fake_mcount(), we overrides it by MIPS_is_fake_mcount() for EM_MIPS in do_file().
At last, HAVE_C_RECORDMCOUNT is selected for MIPS to enable the C version of recordmcount.
The whole support has been tested on my YeeLoong laptop(MIPS, Litten Endian),
including: 32bit kernel and moduels, 64bit kernel and modules.
Here is part of the testing log:
-------
root@yeeloong:~# lsmod Module Size Used by yeeloong_laptop 16142 0 sparse_keymap 3803 1 yeeloong_laptop hwmon 1841 1 yeeloong_laptop backlight 5627 1 yeeloong_laptop power_supply 9512 1 yeeloong_laptop output 2524 1 yeeloong_laptop
1. 32bit kernel and module
root@yeeloong:~# uname -a Linux yeeloong 2.6.36-ftrace+ #71 PREEMPT Wed Oct 27 15:03:02 CST 2010 mips GNU/Linux root@yeeloong:~# mount -t debugfs nodev /debug root@yeeloong:~# echo function > /debug/tracing/current_tracer root@yeeloong:~# echo 1 > /debug/tracing/tracing_enabled root@yeeloong:~# sleep 1 root@yeeloong:~# echo 0 > /debug/tracing/tracing_enabled root@yeeloong:~# head -20 /debug/tracing/trace # tracer: function # # TASK-PID CPU# TIMESTAMP FUNCTION # | | | | | Xorg-1443 [000] 132.196336: remove_wait_queue <-poll_freewait Xorg-1443 [000] 132.196337: fput <-poll_freewait Xorg-1443 [000] 132.196338: remove_wait_queue <-poll_freewait Xorg-1443 [000] 132.196339: fput <-poll_freewait Xorg-1443 [000] 132.196340: remove_wait_queue <-poll_freewait Xorg-1443 [000] 132.196341: fput <-poll_freewait Xorg-1443 [000] 132.196342: remove_wait_queue <-poll_freewait Xorg-1443 [000] 132.196343: fput <-poll_freewait Xorg-1443 [000] 132.196344: remove_wait_queue <-poll_freewait Xorg-1443 [000] 132.196345: fput <-poll_freewait Xorg-1443 [000] 132.196346: remove_wait_queue <-poll_freewait Xorg-1443 [000] 132.196347: fput <-poll_freewait Xorg-1443 [000] 132.196348: remove_wait_queue <-poll_freewait Xorg-1443 [000] 132.196349: fput <-poll_freewait Xorg-1443 [000] 132.196351: poll_select_copy_remaining <-sys_select Xorg-1443 [000] 132.196352: ktime_get_ts <-poll_select_copy_remaining root@yeeloong:~# echo *yeeloong* > /debug/tracing/setKset_ftrace_filter root@yeeloong:~# echo 1 > /debug/tracing/tracing_enabled root@yeeloong:~# (Press Fn + Up/Down to trigger the functions in yeeloong_laptop module) root@yeeloong:~# echo 0 > /tracing/tracing_enabled root@yeeloong:~# head -20 /debug/tracing/trace # tracer: function # # TASK-PID CPU# TIMESTAMP FUNCTION # | | | | | hald-addon-gene-1397 [000] 168.904096: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 170.414572: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 170.625428: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 170.806029: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 170.977210: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 171.262519: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 171.271132: yeeloong_set_brightness <-backlight_store_brightness hald-addon-gene-1397 [000] 171.545363: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 171.679358: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 171.825652: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 171.996121: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 172.246240: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 172.383859: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 172.532963: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 172.844048: yeeloong_get_brightness <-backlight_show_actual_brightness hald-addon-gene-1397 [000] 172.851410: yeeloong_set_brightness <-backlight_store_brightness root@yeeloong:~# exit
2. 64bit kernel and module
root@yeeloong:~# uname -a
Linux yeeloong 2.6.36-ftrace+ #75 PREEMPT Wed Oct 27 16:12:20 CST 2010 mips64 GNU/Linux
root@yeeloong:~# mount -t debugfs nodev /debug
root@yeeloong:~# echo function > /debug/tracing/current_tracer
root@yeeloong:~# echo 1 > /debug/tracing/tracing_enabled
root@yeeloong:~# ls
[snip]
root@yeeloong:~# echo 0 > /debug/tracing/tracing_enabled
root@yeeloong:~# cat /debug/tracing/trace | head -20
# tracer: function
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
<idle>-0 [000] 389.507465: complete <-usb_stor_blocking_completion
<idle>-0 [000] 389.507466: default_wake_function <-complete
<idle>-0 [000] 389.507467: try_to_wake_up <-default_wake_function
<idle>-0 [000] 389.507468: enqueue_task_fair <-try_to_wake_up
<idle>-0 [000] 389.507469: T.1160 <-enqueue_task_fair
<idle>-0 [000] 389.507470: check_preempt_curr_idle <-try_to_wake_up
<idle>-0 [000] 389.507472: usb_free_urb <-usb_hcd_giveback_urb
<idle>-0 [000] 389.507473: dma_pool_free <-qh_completions
<idle>-0 [000] 389.507475: mod_timer <-scan_async
<idle>-0 [000] 389.507476: usb_hcd_irq <-handle_IRQ_event
<idle>-0 [000] 389.507477: ohci_irq <-usb_hcd_irq
<idle>-0 [000] 389.507481: note_interrupt <-handle_level_irq
<idle>-0 [000] 389.507482: compat_irq_unmask <-handle_level_irq
<idle>-0 [000] 389.507483: enable_8259A_irq <-compat_irq_unmask
<idle>-0 [000] 389.507484: irq_exit <-do_IRQ
<idle>-0 [000] 389.507485: rcu_irq_exit <-irq_exit
root@yeeloong:~# echo *yeeloong* > /debug/tracing/set_ftrace_filter
root@yeeloong:~# echo 1 > /debug/tracing/tracing_enabled
root@yeeloong:~# (Press Fn + Up/Down here to trigger the kernel functions called in yeeloong_laptop module)
root@yeeloong:~# echo 0 > /debug/tracing/tracing_enabled
root@yeeloong:~# cat /debug/tracing/trace | head -20
# tracer: function
#
# TASK-PID CPU# TIMESTAMP FUNCTION
# | | | | |
hald-1378 [000] 414.479887: yeeloong_get_bat_props <-power_supply_show_property
hald-1378 [000] 414.480143: yeeloong_get_bat_props <-power_supply_show_property
hald-1378 [000] 414.480327: yeeloong_get_bat_props <-power_supply_show_property
hald-1378 [000] 414.480486: yeeloong_get_bat_props <-power_supply_show_property
hald-1378 [000] 414.480602: yeeloong_get_bat_props <-power_supply_show_property
hald-1378 [000] 414.480741: yeeloong_get_bat_props <-power_supply_show_property
hald-1378 [000] 414.480860: yeeloong_get_bat_props <-power_supply_show_property
upowerd-1656 [000] 414.481609: yeeloong_get_bat_props <-power_supply_show_property
upowerd-1656 [000] 414.482058: yeeloong_get_bat_props <-power_supply_show_property
upowerd-1656 [000] 414.482185: yeeloong_get_bat_props <-power_supply_show_property
upowerd-1656 [000] 414.482257: yeeloong_get_bat_props <-power_supply_show_property
upowerd-1656 [000] 414.482333: yeeloong_get_bat_props <-power_supply_show_property
upowerd-1656 [000] 414.482414: yeeloong_get_bat_props <-power_supply_show_property
hald-addon-gene-1409 [000] 415.412442: yeeloong_get_brightness <-backlight_show_actual_brightness
hald-addon-gene-1409 [000] 416.135571: yeeloong_get_brightness <-backlight_show_actual_brightness
hald-addon-gene-1409 [000] 416.381292: yeeloong_get_brightness <-backlight_show_actual_brightness--------
Thanks all.
Best Regards,
Wu Zhangjin
Wu Zhangjin (3):
ftrace/MIPS: Add MIPS64 support for C version of recordmcount ftrace/MIPS: Add module support for C version of recordmcount ftrace/MIPS: Enable C Version of recordmcount
arch/mips/Kconfig | 1 + scripts/recordmcount.c | 44 ++++++++++++++++++++++++ scripts/recordmcount.h | 86 +++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 126 insertions(+), 5 deletions(-)
PATCH 1/3 ftrace/MIPS: Add MIPS64 support for C version of recordmcount
From: Wu Zhangjin <[email protected]>
MIPS64 has 'weird' Elf64_Rel.r_info[1,2], which must be used instead of the generic Elf64_Rel.r_info, otherwise, the C version of recordmcount will not work for "segmentation fault".
----
[1] http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
[2] arch/mips/include/asm/module.h
--- scripts/recordmcount.c | 41 +++++++++++++++++++++++++++++++++++++++++ scripts/recordmcount.h | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 4 deletions(-)
scripts/recordmcount.c +41 -0
@@ -217,6 +217,39 @@ is_mcounted_section_name(char const *const txtname)#define RECORD_MCOUNT_64 #include "recordmcount.h" +/* 64-bit EM_MIPS has weird ELF64_Rela.r_info. +* http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf +* We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40] +* to imply the order of the members; the spec does not say so. +* typedef unsigned char Elf64_Byte; +* fails on MIPS64 because their <elf.h> already has it! +*/ + +typedef uint8_t myElf64_Byte ;/* Type for a 8-bit quantity. */ + +union mips_r_info { +Elf64_Xword r_info; +struct { +Elf64_Word r_sym;/* Symbol index. */ +myElf64_Byte r_ssym;/* Special symbol. */ +myElf64_Byte r_type3;/* Third relocation. */ +myElf64_Byte r_type2;/* Second relocation. */ +myElf64_Byte r_type;/* First relocation. */ + } r_mips; +}; + +static uint64_t MIPS64_r_sym (Elf64_Rel const *rp) +{ +return w (((union mips_r_info ){ .r_info = rp->r_info }).r_mips.r_sym); +} + +static void MIPS64_r_info (Elf64_Rel *const rp,unsigned sym,unsigned type) +{ + rp->r_info = ((union mips_r_info ){ + .r_mips = { .r_sym =w (sym), .r_type = type } + }).r_info; +} +static void do_file (char const *const fname) {
@@ -268,6 +301,7 @@ do_file(char const *const fname)case EM_386 : reltype =R_386_32 ;break ;case EM_ARM : reltype =R_ARM_ABS32 ;break ;case EM_IA_64 : reltype =R_IA64_IMM64 ; gpfx ='_' ;break ; +case EM_MIPS :/* reltype: e_class */ gpfx ='_' ;break ;case EM_PPC : reltype =R_PPC_ADDR32 ; gpfx ='_' ;break ;case EM_PPC64 : reltype =R_PPC64_ADDR64 ; gpfx ='_' ;break ;case EM_S390 :/* reltype: e_class */ gpfx ='_' ;break ;
@@ -291,6 +325,8 @@ do_file(char const *const fname) }if (EM_S390 ==w2 (ehdr->e_machine)) reltype =R_390_32 ; +if (EM_MIPS ==w2 (ehdr->e_machine)) + reltype =R_MIPS_32 ;do32 (ehdr, fname, reltype); }break ;case ELFCLASS64 : {
@@ -303,6 +339,11 @@ do_file(char const *const fname) }if (EM_S390 ==w2 (ghdr->e_machine)) reltype =R_390_64 ; +if (EM_MIPS ==w2 (ghdr->e_machine)) { + reltype =R_MIPS_64 ; + Elf64_r_sym = MIPS64_r_sym; + Elf64_r_info = MIPS64_r_info; + }do64 (ghdr, fname, reltype); }break ; }/* end switch */
scripts/recordmcount.h +30 -4
@@ -31,8 +31,12 @@#undef Elf_Rela#undef Elf_Sym#undef ELF_R_SYM +#undef Elf_r_sym#undef ELF_R_INFO +#undef Elf_r_info#undef ELF_ST_BIND +#undef fn_ELF_R_SYM +#undef fn_ELF_R_INFO#undef uint_t#undef _w#undef _align
@@ -52,8 +56,12 @@# define Elf_Rela Elf64_Rela# define Elf_Sym Elf64_Sym# define ELF_R_SYM ELF64_R_SYM +# define Elf_r_sym Elf64_r_sym# define ELF_R_INFO ELF64_R_INFO +# define Elf_r_info Elf64_r_info# define ELF_ST_BIND ELF64_ST_BIND +# define fn_ELF_R_SYM fn_ELF64_R_SYM +# define fn_ELF_R_INFO fn_ELF64_R_INFO# define uint_t uint64_t# define _w w8# define _align 7u
@@ -72,14 +80,32 @@# define Elf_Rela Elf32_Rela# define Elf_Sym Elf32_Sym# define ELF_R_SYM ELF32_R_SYM +# define Elf_r_sym Elf32_r_sym# define ELF_R_INFO ELF32_R_INFO +# define Elf_r_info Elf32_r_info# define ELF_ST_BIND ELF32_ST_BIND +# define fn_ELF_R_SYM fn_ELF32_R_SYM +# define fn_ELF_R_INFO fn_ELF32_R_INFO# define uint_t uint32_t# define _w w# define _align 3u# define _size 4#endif +/* Functions and pointers that 64-bit EM_MIPS can override. */ +static uint_t fn_ELF_R_SYM (Elf_Rel const *rp) +{ +return ELF_R_SYM (_w (rp->r_info)); +} +static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM; + +static void fn_ELF_R_INFO (Elf_Rel *const rp,unsigned sym,unsigned type) +{ + rp->r_info =ELF_R_INFO (sym, type); +} +static void (*Elf_r_info)(Elf_Rel *const rp,unsigned sym,unsigned type) = fn_ELF_R_INFO; + +/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ static void append_func(Elf_Ehdr *const ehdr, Elf_Shdr *const shstr,
@@ -197,22 +223,22 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,for (t = nrel; t; --t) {if (!mcountsym) {Elf_Sym const *const symp = - &sym0[ELF_R_SYM (_w (relp->r_info))]; + &sym0[Elf_r_sym (relp)];char const *symname = &str0[w (symp->st_name)];if ('.' == symname[0 ]) ++symname;/* ppc64 hack */ if (0 ==strcmp ((('_' == gpfx) ?"_mcount" :"mcount" ), symname)) - mcountsym =ELF_R_SYM (_w (relp->r_info)); + mcountsym =Elf_r_sym (relp); } -if (mcountsym ==ELF_R_SYM (_w (relp->r_info))) { +if (mcountsym ==Elf_r_sym (relp)) {uint_t const addend =_w (_w (relp->r_offset) - recval); mrelp->r_offset =_w (offbase + ((void *)mlocp - (void *)mloc0)); - mrelp->r_info =_w (ELF_R_INFO (recsym, reltype)); +Elf_r_info (mrelp, recsym, reltype);if (sizeof (Elf_Rela) == rel_entsize) { ((Elf_Rela *)mrelp)->r_addend = addend; *mlocp++ =0 ;
Signature · 1 line
1.7.1
Re: [PATCH 1/3] ftrace/MIPS: Add MIPS64 support for C version of recordmcount
Quoted 1 line · Wu Zhangjin
From: Wu Zhangjin <[email protected]>
The From above states that you wrote this. Did you modify what John and Maciej did? If so, please state clearly what each author has done, and how you modified it. If you did not write this, please change the From to the correct author.
If you did modify it, then state something like this in the change log.
Original version written by John Reiser <[email protected]>
Usage of "union mips_r_info" and the functions MIPS64_r_sym() and MIPS64_r_info() written by Maciej W. Rozycki <[email protected]>
Then state the changes you made.
Quoted 5 lines
MIPS64 has 'weird' Elf64_Rel.r_info[1,2], which must be used instead of the generic Elf64_Rel.r_info, otherwise, the C version of recordmcount will not work for "segmentation fault".
Quoted 7 lines
----
[1] http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
[2]arch/mips/include/asm/module.hSigned-off-by John Reiser <[email protected]>Signed-off-by Maciej W. Rozycki <[email protected]>Tested-by Wu Zhangjin <[email protected]>
Again, if you made changes, you need a SoB yourself.
Thanks!
-- Steve
Quoted 168 lines
--- scripts/recordmcount.c | 41 +++++++++++++++++++++++++++++++++++++++++ scripts/recordmcount.h | 34 ++++++++++++++++++++++++++++++---- 2 files changed, 71 insertions(+), 4 deletions(-)scripts/recordmcount.c +41
-0@@ -217,6 +217,39 @@ is_mcounted_section_name(char const *const txtname)#define RECORD_MCOUNT_64 #include "recordmcount.h" +/* 64-bit EM_MIPS has weird ELF64_Rela.r_info. +* http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf +* We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40] +* to imply the order of the members; the spec does not say so. +* typedef unsigned char Elf64_Byte; +* fails on MIPS64 because their <elf.h> already has it! +*/ + +typedef uint8_t myElf64_Byte ;/* Type for a 8-bit quantity. */ + +union mips_r_info { +Elf64_Xword r_info; +struct { +Elf64_Word r_sym;/* Symbol index. */ +myElf64_Byte r_ssym;/* Special symbol. */ +myElf64_Byte r_type3;/* Third relocation. */ +myElf64_Byte r_type2;/* Second relocation. */ +myElf64_Byte r_type;/* First relocation. */ + } r_mips; +}; + +static uint64_t MIPS64_r_sym (Elf64_Rel const *rp) +{ +return w (((union mips_r_info ){ .r_info = rp->r_info }).r_mips.r_sym); +} + +static void MIPS64_r_info (Elf64_Rel *const rp,unsigned sym,unsigned type) +{ + rp->r_info = ((union mips_r_info ){ + .r_mips = { .r_sym =w (sym), .r_type = type } + }).r_info; +} +static void do_file (char const *const fname) {@@ -268,6 +301,7 @@ do_file(char const *const fname)case EM_386 : reltype =R_386_32 ;break ;case EM_ARM : reltype =R_ARM_ABS32 ;break ;case EM_IA_64 : reltype =R_IA64_IMM64 ; gpfx ='_' ;break ; +case EM_MIPS :/* reltype: e_class */ gpfx ='_' ;break ;case EM_PPC : reltype =R_PPC_ADDR32 ; gpfx ='_' ;break ;case EM_PPC64 : reltype =R_PPC64_ADDR64 ; gpfx ='_' ;break ;case EM_S390 :/* reltype: e_class */ gpfx ='_' ;break ;@@ -291,6 +325,8 @@ do_file(char const *const fname) }if (EM_S390 ==w2 (ehdr->e_machine)) reltype =R_390_32 ; +if (EM_MIPS ==w2 (ehdr->e_machine)) + reltype =R_MIPS_32 ;do32 (ehdr, fname, reltype); }break ;case ELFCLASS64 : {@@ -303,6 +339,11 @@ do_file(char const *const fname) }if (EM_S390 ==w2 (ghdr->e_machine)) reltype =R_390_64 ; +if (EM_MIPS ==w2 (ghdr->e_machine)) { + reltype =R_MIPS_64 ; + Elf64_r_sym = MIPS64_r_sym; + Elf64_r_info = MIPS64_r_info; + }do64 (ghdr, fname, reltype); }break ; }/* end switch */ scripts/recordmcount.h +30
-4@@ -31,8 +31,12 @@#undef Elf_Rela#undef Elf_Sym#undef ELF_R_SYM +#undef Elf_r_sym#undef ELF_R_INFO +#undef Elf_r_info#undef ELF_ST_BIND +#undef fn_ELF_R_SYM +#undef fn_ELF_R_INFO#undef uint_t#undef _w#undef _align@@ -52,8 +56,12 @@# define Elf_Rela Elf64_Rela# define Elf_Sym Elf64_Sym# define ELF_R_SYM ELF64_R_SYM +# define Elf_r_sym Elf64_r_sym# define ELF_R_INFO ELF64_R_INFO +# define Elf_r_info Elf64_r_info# define ELF_ST_BIND ELF64_ST_BIND +# define fn_ELF_R_SYM fn_ELF64_R_SYM +# define fn_ELF_R_INFO fn_ELF64_R_INFO# define uint_t uint64_t# define _w w8# define _align 7u@@ -72,14 +80,32 @@# define Elf_Rela Elf32_Rela# define Elf_Sym Elf32_Sym# define ELF_R_SYM ELF32_R_SYM +# define Elf_r_sym Elf32_r_sym# define ELF_R_INFO ELF32_R_INFO +# define Elf_r_info Elf32_r_info# define ELF_ST_BIND ELF32_ST_BIND +# define fn_ELF_R_SYM fn_ELF32_R_SYM +# define fn_ELF_R_INFO fn_ELF32_R_INFO# define uint_t uint32_t# define _w w# define _align 3u# define _size 4#endif +/* Functions and pointers that 64-bit EM_MIPS can override. */ +static uint_t fn_ELF_R_SYM (Elf_Rel const *rp) +{ +return ELF_R_SYM (_w (rp->r_info)); +} +static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM; + +static void fn_ELF_R_INFO (Elf_Rel *const rp,unsigned sym,unsigned type) +{ + rp->r_info =ELF_R_INFO (sym, type); +} +static void (*Elf_r_info)(Elf_Rel *const rp,unsigned sym,unsigned type) = fn_ELF_R_INFO; + +/* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ static void append_func(Elf_Ehdr *const ehdr, Elf_Shdr *const shstr,@@ -197,22 +223,22 @@ static uint_t *sift_rel_mcount(uint_t *mlocp,for (t = nrel; t; --t) {if (!mcountsym) {Elf_Sym const *const symp = - &sym0[ELF_R_SYM (_w (relp->r_info))]; + &sym0[Elf_r_sym (relp)];char const *symname = &str0[w (symp->st_name)];if ('.' == symname[0 ]) ++symname;/* ppc64 hack */ if (0 ==strcmp ((('_' == gpfx) ?"_mcount" :"mcount" ), symname)) - mcountsym =ELF_R_SYM (_w (relp->r_info)); + mcountsym =Elf_r_sym (relp); } -if (mcountsym ==ELF_R_SYM (_w (relp->r_info))) { +if (mcountsym ==Elf_r_sym (relp)) {uint_t const addend =_w (_w (relp->r_offset) - recval); mrelp->r_offset =_w (offbase + ((void *)mlocp - (void *)mloc0)); - mrelp->r_info =_w (ELF_R_INFO (recsym, reltype)); +Elf_r_info (mrelp, recsym, reltype);if (sizeof (Elf_Rela) == rel_entsize) { ((Elf_Rela *)mrelp)->r_addend = addend; *mlocp++ =0 ;
Re: [PATCH 1/3] ftrace/MIPS: Add MIPS64 support for C version of recordmcount
Quoted 8 lines · Steven Rostedt
Quoted 1 line · Wu Zhangjin
From: Wu Zhangjin <[email protected]>
The From above states that you wrote this. Did you modify what John and Maciej did? If so, please state clearly what each author has done, and how you modified it. If you did not write this, please change the From to the correct author.
Quoted 7 lines
If you did modify it, then state something like this in the change log.
Original version written by John Reiser <[email protected]>
Usage of "union
mips_r_info" and the functionsMIPS64_r_sym()andMIPS64_r_info()written by Maciej W. Rozycki <[email protected]>
yeah, that is true above.
Quoted 1 line
Then state the changes you made.
I didn't change it, just added the comments in the patch log and tested it.
Should I resend the patch with the change log information about John and Maciej?
Regards,
Wu Zhangjin
Quoted 192 lines
Quoted 6 lines
MIPS64 has 'weird' Elf64_Rel.r_info[1,2], which must be used instead of the generic Elf64_Rel.r_info, otherwise, the C version of recordmcount will not work for "segmentation fault".
Quoted 7 lines
----
[1] http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf
[2]arch/mips/include/asm/module.hSigned-off-by John Reiser <[email protected]>Signed-off-by Maciej W. Rozycki <[email protected]>Tested-by Wu Zhangjin <[email protected]>Again, if you made changes, you need a SoB yourself.
Thanks!
-- Steve
Quoted 168 lines
---
scripts/recordmcount.c | 41 +++++++++++++++++++++++++++++++++++++++++scripts/recordmcount.h| 34 ++++++++++++++++++++++++++++++----2 files changed, 71 insertions(+), 4 deletions(-)scripts/recordmcount.c +33
-0@@ -217,6 +217,39 @@ is_mcounted_section_name(char const *const txtname) #define RECORD_MCOUNT_64 #include "recordmcount.h" +/* 64-bit EM_MIPS has weird ELF64_Rela.r_info. +* http://techpubs.sgi.com/library/manuals/4000/007-4658-001/pdf/007-4658-001.pdf +* We interpret Table 29 Relocation Operation (Elf64_Rel, Elf64_Rela) [p.40] +* to imply the order of the members; the spec does not say so. +* typedef unsigned char Elf64_Byte; +* fails on MIPS64 because their <elf.h> already has it! +*/ + +typedef uint8_t myElf64_Byte; /* Type for a 8-bit quantity. */ + +union mips_r_info { + Elf64_Xword r_info; + struct { + Elf64_Word r_sym; /* Symbol index. */ + myElf64_Byte r_ssym; /* Special symbol. */ + myElf64_Byte r_type3; /* Third relocation. */ + myElf64_Byte r_type2; /* Second relocation. */ + myElf64_Byte r_type; /* First relocation. */ + } r_mips; +}; + +static uint64_t MIPS64_r_sym (Elf64_Rel const *rp) +{ + return w(((union mips_r_info){ .r_info = rp->r_info }).r_mips.r_sym); +} + +static void MIPS64_r_info (Elf64_Rel *const rp,unsigned sym,unsigned type) +{ + rp->r_info = ((union mips_r_info){ + .r_mips = { .r_sym = w(sym), .r_type = type } + }).r_info; +} +static void
do_file(char const *const fname)
{scripts/recordmcount.c +8
-0@@ -268,6 +301,7 @@ do_file(char const *const fname) case EM_386: reltype = R_386_32; break; case EM_ARM: reltype = R_ARM_ABS32; break; case EM_IA_64: reltype = R_IA64_IMM64; gpfx = '_'; break; + case EM_MIPS: /* reltype: e_class */ gpfx = '_'; break; case EM_PPC: reltype = R_PPC_ADDR32; gpfx = '_'; break; case EM_PPC64: reltype = R_PPC64_ADDR64; gpfx = '_'; break; case EM_S390: /* reltype: e_class */ gpfx = '_'; break;@@ -291,6 +325,8 @@ do_file(char const *const fname) } if (EM_S390 == w2(ehdr->e_machine)) reltype = R_390_32; + if (EM_MIPS == w2(ehdr->e_machine)) + reltype = R_MIPS_32; do32(ehdr, fname, reltype); } break; case ELFCLASS64: {@@ -303,6 +339,11 @@ do_file(char const *const fname) } if (EM_S390 == w2(ghdr->e_machine)) reltype = R_390_64; + if (EM_MIPS == w2(ghdr->e_machine)) { + reltype = R_MIPS_64; + Elf64_r_sym = MIPS64_r_sym; + Elf64_r_info = MIPS64_r_info; + } do64(ghdr, fname, reltype); } break; } /* end switch */scripts/recordmcount.h +26
-0@@ -31,8 +31,12 @@ #undef Elf_Rela #undef Elf_Sym #undef ELF_R_SYM +#undef Elf_r_sym #undef ELF_R_INFO +#undef Elf_r_info #undef ELF_ST_BIND +#undef fn_ELF_R_SYM +#undef fn_ELF_R_INFO #undef uint_t #undef _w #undef _align@@ -52,8 +56,12 @@ # define Elf_Rela Elf64_Rela # define Elf_Sym Elf64_Sym # define ELF_R_SYM ELF64_R_SYM +# define Elf_r_sym Elf64_r_sym # define ELF_R_INFO ELF64_R_INFO +# define Elf_r_info Elf64_r_info # define ELF_ST_BIND ELF64_ST_BIND +# define fn_ELF_R_SYM fn_ELF64_R_SYM +# define fn_ELF_R_INFO fn_ELF64_R_INFO # define uint_t uint64_t # define _w w8 # define _align 7u@@ -72,14 +80,32 @@ # define Elf_Rela Elf32_Rela # define Elf_Sym Elf32_Sym # define ELF_R_SYM ELF32_R_SYM +# define Elf_r_sym Elf32_r_sym # define ELF_R_INFO ELF32_R_INFO +# define Elf_r_info Elf32_r_info # define ELF_ST_BIND ELF32_ST_BIND +# define fn_ELF_R_SYM fn_ELF32_R_SYM +# define fn_ELF_R_INFO fn_ELF32_R_INFO # define uint_t uint32_t # define _w w # define _align 3u # define _size 4 #endif +/* Functions and pointers that 64-bit EM_MIPS can override. */ +static uint_t fn_ELF_R_SYM (Elf_Rel const *rp) +{ + return ELF_R_SYM(_w(rp->r_info)); +} +static uint_t (*Elf_r_sym)(Elf_Rel const *rp) = fn_ELF_R_SYM; + +static void fn_ELF_R_INFO (Elf_Rel *const rp,unsigned sym,unsigned type) +{ + rp->r_info = ELF_R_INFO(sym, type); +} +static void (*Elf_r_info)(Elf_Rel *const rp,unsigned sym,unsigned type) = fn_ELF_R_INFO; + + /* Append the new shstrtab, Elf_Shdr[], __mcount_loc and its relocations. */ static void append_func(Elf_Ehdr *const ehdr, Elf_Shdr *const shstr,@@ -197,22 +223,22 @@ static uint_t *sift_rel_mcount(uint_t *mlocp, for (t = nrel; t; --t) { if (!mcountsym) {
Elf_Symconst *const symp =
- &sym0[ELF_R_SYM(_w(relp->r_info))];
+ &sym0[Elf_r_sym(relp)]; char const *symname = &str0[w(symp->st_name)];if ('.' == symname[0])
++symname; /* ppc64 hack */
if (0 ==strcmp((('_' == gpfx) ? "_mcount" : "mcount"), symname))
- mcountsym = ELF_R_SYM(_w(relp->r_info));
+ mcountsym =Elf_r_sym(relp);
}- if (mcountsym == ELF_R_SYM(_w(relp->r_info))) {
+ if (mcountsym ==Elf_r_sym(relp)) {
uint_tconst addend =_w(_w(relp->r_offset) - recval);
mrelp->r_offset= _w(offbase
+ ((void *)mlocp - (void *)mloc0));
-mrelp->r_info=_w(ELF_R_INFO(recsym, reltype));
+Elf_r_info(mrelp, recsym, reltype); if (sizeof(Elf_Rela)==rel_entsize) { ((Elf_Rela*)mrelp)->r_addend = addend; *mlocp++ = 0;
Re: [PATCH 1/3] ftrace/MIPS: Add MIPS64 support for C version of recordmcount
Quoted 17 lines · wu zhangjin
Quoted 8 lines · Steven Rostedt
Quoted 1 line · Wu Zhangjin
From: Wu Zhangjin <[email protected]>
The From above states that you wrote this. Did you modify what John and Maciej did? If so, please state clearly what each author has done, and how you modified it. If you did not write this, please change the From to the correct author.
Quoted 7 lines
If you did modify it, then state something like this in the change log.
Original version written by John Reiser <[email protected]>
Usage of "union
mips_r_info" and the functionsMIPS64_r_sym()andMIPS64_r_info()written by Maciej W. Rozycki <[email protected]>
Quoted 8 lines
yeah, that is true above.
Quoted 1 line
Then state the changes you made.
I didn't change it, just added the comments in the patch log and tested it.
Should I resend the patch with the change log information about John and Maciej?
I can make the changes.
Then the patch is originally John's, right?
I'll make him the author, with the comment about Maciej, and keep you as the Tested-by.
-- Steve
Re: [PATCH 1/3] ftrace/MIPS: Add MIPS64 support for C version of recordmcount
Quoted 20 lines · Steven Rostedt
Quoted 19 lines · wu zhangjin
Quoted 8 lines · Steven Rostedt
Quoted 1 line · Wu Zhangjin
From: Wu Zhangjin <[email protected]>
The From above states that you wrote this. Did you modify what John and Maciej did? If so, please state clearly what each author has done, and how you modified it. If you did not write this, please change the From to the correct author.
Quoted 7 lines
If you did modify it, then state something like this in the change log.
Original version written by John Reiser <[email protected]>
Usage of "union
mips_r_info" and the functionsMIPS64_r_sym()andMIPS64_r_info()written by Maciej W. Rozycki <[email protected]>yeah, that is true above.
Quoted 9 lines
Quoted 6 lines
Quoted 1 line
Then state the changes you made.
I didn't change it, just added the comments in the patch log and tested it.
Should I resend the patch with the change log information about John and Maciej?
I can make the changes.
ok, thanks.
Quoted 2 lines
Then the patch is originally John's, right?
Yes, John write it.
Quoted 2 lines
I'll make him the author, with the comment about Maciej, and keep you as the Tested-by.
ok, Macjej has simplified the r_info of MIPS there, so perhaps we need to add SoB for him and he told me to add that line.
For me, Tested-by: is ok.
Regards,
Wu Zhangjin
PATCH 2/3 ftrace/MIPS: Add module support for C version of recordmcount
In reply to Wu ZhangjinFrom: Wu Zhangjin <[email protected]>
Since MIPS modules' address space differs from the core kernel space, to access the _mcount in the core kernel, the kernel functions in modules must use long call (-mlong-calls): load the _mcount address into one register and jump to the address stored by the register:
c: 3c030000 lui v1,0x0 <--------> b label
c: R_MIPS_HI16 _mcount
c: R_MIPS_NONE *ABS*
c: R_MIPS_NONE *ABS*
10: 64630000 daddiu v1,v1,0
10: R_MIPS_LO16 _mcount
10: R_MIPS_NONE *ABS*
10: R_MIPS_NONE *ABS*14: 03e0082d move at,ra
18: 0060f809 jalr v1
label:
In the old Perl version of recordmcount, we only need to record the position of the 1st R_MIPS_HI16 type of _mcount, and later, in ftrace_make_nop(), replace the instruction in this position by a "b label" and in ftrace_make_call(), replace it back.
But, the default C version of recordmcount records all of the _mcount symbols, so, we must filter the 2nd _mcount like the Perl version of recordmcount does.
The C version of recordmcount copes with the symbols before they are linked, So It doesn't know the type of the symbols and therefore can not filter the symbols as the Perl version of recordmcount does. But as we can see above, the 2nd _mcount symbols of the long call alawys follows the 1st _mcount symbol of the same long call, which means the offset from the 1st to the 2nd is fixed, it is 0x10-0xc = 4 here, 4 is the length of the 1st load instruciton, for MIPS has fixed length of instructions, this offset is always 4.
And as we know, the _mcount is inserted into the entry of every kernel function, the offset between the other _mcount's is expected to be always bigger than 4. So, to filter the 2ns _mcount symbol of the long call, we can simply check the offset between two _mcount symbols, If it is 4, then, filter the 2nd _mcount symbol.
To avoid touching too much code, an 'empty' function fn_is_fake_mcount() is added for all of the archs, and the specific archs can override it via chaning the function pointer: is_fake_mcount in do_file() with the e_machine. e.g. This patch adds MIPS_is_fake_mcount() to override the default fn_is_fake_mcount() pointed by is_fake_mcount.
This fn_is_fake_mcount() checks if the _mcount symbol is fake, e.g. the 2nd _mcount symbol of the long call is fake, for there are 2 _mcount symbols mapped to one real mcount call, so, one of them is fake and must be filtered.
This fn_is_fake_mcount() is called in sift_rel_mcount() after finding the _mcount symbols and before adding the _mcount symbol into mrelp, so, it can prevent the fake mcount symbol going into the last __mcount_loc table.
--- scripts/recordmcount.c | 5 +++- scripts/recordmcount.h | 56 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 4 deletions(-)
scripts/recordmcount.c +4 -1
@@ -325,8 +325,10 @@ do_file(char const *const fname) }if (EM_S390 ==w2 (ehdr->e_machine)) reltype =R_390_32 ; -if (EM_MIPS ==w2 (ehdr->e_machine)) +if (EM_MIPS ==w2 (ehdr->e_machine)) { reltype =R_MIPS_32 ; + is_fake_mcount32 = MIPS32_is_fake_mcount; + }do32 (ehdr, fname, reltype); }break ;case ELFCLASS64 : {
@@ -343,6 +345,7 @@ do_file(char const *const fname) reltype =R_MIPS_64 ; Elf64_r_sym = MIPS64_r_sym; Elf64_r_info = MIPS64_r_info; + is_fake_mcount64 = MIPS64_is_fake_mcount; }do64 (ghdr, fname, reltype); }break ;
scripts/recordmcount.h +53 -3
104 lines not on this page · raw message
Signature · 1 line
1.7.1
PATCH 3/3 ftrace/MIPS: Enable C Version of recordmcount
In reply to Wu ZhangjinFrom: Wu Zhangjin <[email protected]>
Selects HAVE_C_RECORDMCOUNT to use the C version of the recordmcount intead of the old Perl Version of recordmcount.
--- arch/mips/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)
arch/mips/Kconfig +1 -0
@@ -9,6 +9,7 @@ config MIPS select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_C_RECORDMCOUNT select HAVE_FUNCTION_GRAPH_TRACER select HAVE_KPROBES select HAVE_KRETPROBES
Signature · 1 line
1.7.1
Re: [PATCH 3/3] ftrace/MIPS: Enable C Version of recordmcount
Quoted 6 lines · Wu Zhangjin
From: Wu Zhangjin <[email protected]>
Selects
HAVE_C_RECORDMCOUNTto use the C version of the recordmcount intead of the old Perl Version of recordmcount.Signed-off-by Wu Zhangjin <[email protected]>
I'd like to get an Acked-by from Ralf and Maciej on this.
Thanks,
-- Steve
Quoted 16 lines
--- arch/mips/Kconfig | 1 + 1 files changed, 1 insertions(+), 0 deletions(-)arch/mips/Kconfig +1
-0@@ -9,6 +9,7 @@ config MIPS select HAVE_FUNCTION_TRACE_MCOUNT_TEST select HAVE_DYNAMIC_FTRACE select HAVE_FTRACE_MCOUNT_RECORD + select HAVE_C_RECORDMCOUNT select HAVE_FUNCTION_GRAPH_TRACER select HAVE_KPROBES select HAVE_KRETPROBES
Maciej W. Rozycki
Acked-byRe: [PATCH 3/3] ftrace/MIPS: Enable C Version of recordmcount
Quoted 9 lines · Steven Rostedt
Quoted 6 lines · Wu Zhangjin
From: Wu Zhangjin <[email protected]>
Selects
HAVE_C_RECORDMCOUNTto use the C version of the recordmcount intead of the old Perl Version of recordmcount.Signed-off-by Wu Zhangjin <[email protected]>I'd like to get an Acked-by from Ralf and Maciej on this.
I have looked through it and spotted nothing obviously wrong, but I can't
afford any further testing, especially at run time, sorry.
One point to note -- it seems to me the code currently assumes a 32-bit
model, i.e. the use of the -msym32 GCC option suitable for a 64-bit kernel loaded to a CKSEG0 address (cf. KBUILD_SYM32 in arch/mips/Makefile), tools support permitting. That means it does not (correctly) support kernels loaded to an XPHYS address as required for some platforms (or otherwise chosen for testing such a configuration; modulo some processor errata and bootloader limitations, it is generally OK to run the kernel from XPHYS on 64-bit chips even if the entire RAM fits into CKSEG0).
For the avoidance of doubt -- I'm just mentioning it to emphasise a
possible future direction for improvement of this code -- not an objection against this submission, that is certainly a good foundation for future development.
Thanks to everybody involved.
Maciej