Hi, I noticed that klibc started crashing on 64-bit MIPS and in my quest to fix the bug I got a bit carried away and fixed a few other things as well. Here are various miscellaneous MIPS patches, although the first patch is the important one. Thanks, James *** BLURB HERE *** James Cowgill (5): mips64: compile with -mno-abicalls mips: use -Ttext-segment when linking shared library mips/mips64: simplify crt0 code mips: don't save floating point registers in setjmp / longjmp mips64: remove __unused from __jmp_buf usr/include/arch/mips/klibc/archsetjmp.h | 14 -- usr/include/arch/mips64/klibc/archsetjmp.h | 1 - usr/klibc/arch/mips/MCONFIG | 7 +- usr/klibc/arch/mips/crt0.S | 13 +- usr/klibc/arch/mips/klibc.ld | 214 ----------------------------- usr/klibc/arch/mips/setjmp.S | 30 ---- usr/klibc/arch/mips64/MCONFIG | 12 +- usr/klibc/arch/mips64/crt0.S | 20 +-- 8 files changed, 27 insertions(+), 284 deletions(-) delete mode 100644 usr/klibc/arch/mips/klibc.ld -- 2.16.2
James Cowgill
2018-Mar-02 16:33 UTC
[klibc] [PATCH 1/5] mips64: compile with -mno-abicalls
By default, the MIPS toolchain compiles all code as PIC. Since klibc links everything at static addresses, we don't need PIC code so use -mno-abicalls to disable it. To fix subsequent link errors, use -Ttext-segment to adjust the base address of klibc to a more sensible location. This fixes a bug in the shared library form of klibc where programs would segfault in the syscall handler because we tried to store into the "errno" variable without setting up the gp register. This is only required under the PIC ABI. Signed-off-by: James Cowgill <james.cowgill at mips.com> --- usr/klibc/arch/mips64/MCONFIG | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/usr/klibc/arch/mips64/MCONFIG b/usr/klibc/arch/mips64/MCONFIG index b37cc6a7..6a4b41b2 100644 --- a/usr/klibc/arch/mips64/MCONFIG +++ b/usr/klibc/arch/mips64/MCONFIG @@ -7,7 +7,17 @@ # accordingly. # +KLIBCARCHREQFLAGS = -fno-pic -mno-abicalls -G 0 KLIBCOPTFLAGS += -Os KLIBCBITSIZE = 64 -KLIBCSHAREDFLAGS = -T $(src)/arch/mips/klibc.ld +# Extra linkflags when building the shared version of the library +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 4862 MB - normal binaries start at 4608 MB. Non-PIC jumps usually +# use the JAL instruction which requires a destination within the same +# 256M aligned region. Since we can't put ourselves below the normal +# load address, use the very top of the 256M region (minus 2MB) +# +# Use -Ttext-segment so that the special .MIPS* sections are moved as well. +KLIBCSHAREDFLAGS = -Ttext-segment 0x12FE00000 -- 2.16.2
James Cowgill
2018-Mar-02 16:33 UTC
[klibc] [PATCH 2/5] mips: use -Ttext-segment when linking shared library
Most architectures use the -Ttext option to move the klibc shared library out of the way of the normal load address. Unfortunately MIPS has some extra sections which are positioned before the .text section and are therefore not repositioned by the -Ttext option. Fix this by using the -Ttext-segment option. Instead of changing the address of the .text section, this option changes the .text segment which happens to include all the special MIPS sections. After this we can drop the linker script which we no longer need. Signed-off-by: James Cowgill <james.cowgill at mips.com> --- usr/klibc/arch/mips/MCONFIG | 7 +- usr/klibc/arch/mips/klibc.ld | 214 ------------------------------------------- 2 files changed, 6 insertions(+), 215 deletions(-) delete mode 100644 usr/klibc/arch/mips/klibc.ld diff --git a/usr/klibc/arch/mips/MCONFIG b/usr/klibc/arch/mips/MCONFIG index c6331a1d..7ad65232 100644 --- a/usr/klibc/arch/mips/MCONFIG +++ b/usr/klibc/arch/mips/MCONFIG @@ -12,4 +12,9 @@ KLIBCOPTFLAGS += -Os KLIBCBITSIZE = 32 # Extra linkflags when building the shared version of the library -KLIBCSHAREDFLAGS = -T $(src)/arch/$(KLIBCARCH)/klibc.ld +# This address needs to be reachable using normal inter-module +# calls, and work on the memory models for this architecture +# 2 MB - normal binaries start at 4 MB +# +# Use -Ttext-segment so that the special .MIPS* sections are moved as well. +KLIBCSHAREDFLAGS = -Ttext-segment 0x00200000 diff --git a/usr/klibc/arch/mips/klibc.ld b/usr/klibc/arch/mips/klibc.ld deleted file mode 100644 index 5a2a7a64..00000000 --- a/usr/klibc/arch/mips/klibc.ld +++ /dev/null @@ -1,214 +0,0 @@ -/* Linker script for klibc.so, needed because of the the damned - GNU ld script headers problem */ - -ENTRY(__start) -SECTIONS -{ - /* Read-only sections, merged into text segment: */ - /* This address needs to be reachable using normal inter-module - calls, and work on the memory models for this architecture */ - /* 2 MB -- the normal starting point for text is 4 MB */ - . = 0x00200400; - .interp : { *(.interp) } - .reginfo : { *(.reginfo) } - .dynamic : { *(.dynamic) } - .hash : { *(.hash) } - .dynsym : { *(.dynsym) } - .dynstr : { *(.dynstr) } - .gnu.version : { *(.gnu.version) } - .gnu.version_d : { *(.gnu.version_d) } - .gnu.version_r : { *(.gnu.version_r) } - .rel.dyn : - { - *(.rel.init) - *(.rel.text .rel.text.* .rel.gnu.linkonce.t.*) - *(.rel.fini) - *(.rel.rodata .rel.rodata.* .rel.gnu.linkonce.r.*) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - *(.rel.tdata .rel.tdata.* .rel.gnu.linkonce.td.*) - *(.rel.tbss .rel.tbss.* .rel.gnu.linkonce.tb.*) - *(.rel.ctors) - *(.rel.dtors) - *(.rel.got) - *(.rel.sdata .rel.sdata.* .rel.gnu.linkonce.s.*) - *(.rel.sbss .rel.sbss.* .rel.gnu.linkonce.sb.*) - *(.rel.sdata2 .rel.sdata2.* .rel.gnu.linkonce.s2.*) - *(.rel.sbss2 .rel.sbss2.* .rel.gnu.linkonce.sb2.*) - *(.rel.bss .rel.bss.* .rel.gnu.linkonce.b.*) - } - .rela.dyn : - { - *(.rela.init) - *(.rela.text .rela.text.* .rela.gnu.linkonce.t.*) - *(.rela.fini) - *(.rela.rodata .rela.rodata.* .rela.gnu.linkonce.r.*) - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - *(.rela.tdata .rela.tdata.* .rela.gnu.linkonce.td.*) - *(.rela.tbss .rela.tbss.* .rela.gnu.linkonce.tb.*) - *(.rela.ctors) - *(.rela.dtors) - *(.rela.got) - *(.rela.sdata .rela.sdata.* .rela.gnu.linkonce.s.*) - *(.rela.sbss .rela.sbss.* .rela.gnu.linkonce.sb.*) - *(.rela.sdata2 .rela.sdata2.* .rela.gnu.linkonce.s2.*) - *(.rela.sbss2 .rela.sbss2.* .rela.gnu.linkonce.sb2.*) - *(.rela.bss .rela.bss.* .rela.gnu.linkonce.b.*) - } - .rel.plt : { *(.rel.plt) } - .rela.plt : { *(.rela.plt) } - .init : - { - KEEP (*(.init)) - } =0 - .plt : { *(.plt) } - .text : - { - _ftext = . ; - *(.text .stub .text.* .gnu.linkonce.t.*) - /* .gnu.warning sections are handled specially by elf32.em. */ - *(.gnu.warning) - *(.mips16.fn.*) *(.mips16.call.*) - } =0 - .fini : - { - KEEP (*(.fini)) - } =0 - PROVIDE (__etext = .); - PROVIDE (_etext = .); - PROVIDE (etext = .); - .rodata : { *(.rodata .rodata.* .gnu.linkonce.r.*) } - .rodata1 : { *(.rodata1) } - .sdata2 : { *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) } - .sbss2 : { *(.sbss2 .sbss2.* .gnu.linkonce.sb2.*) } - .eh_frame_hdr : { *(.eh_frame_hdr) } - /* Adjust the address for the data segment. We want to adjust up to - the same address within the page on the next page up. */ - . = ALIGN(8192); - /* Ensure the __preinit_array_start label is properly aligned. We - could instead move the label definition inside the section, but - the linker would then create the section even if it turns out to - be empty, which isn't pretty. */ - . = ALIGN(32 / 8); - PROVIDE (__preinit_array_start = .); - .preinit_array : { *(.preinit_array) } - PROVIDE (__preinit_array_end = .); - PROVIDE (__init_array_start = .); - .init_array : { *(.init_array) } - PROVIDE (__init_array_end = .); - PROVIDE (__fini_array_start = .); - .fini_array : { *(.fini_array) } - PROVIDE (__fini_array_end = .); - .data : - { - _fdata = . ; - *(.data .data.* .gnu.linkonce.d.*) - SORT(CONSTRUCTORS) - } - .data1 : { *(.data1) } - .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } - .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } - .eh_frame : { KEEP (*(.eh_frame)) } - .gcc_except_table : { *(.gcc_except_table) } - .ctors : - { - /* gcc uses crtbegin.o to find the start of - the constructors, so we make sure it is - first. Because this is a wildcard, it - doesn't matter if the user does not - actually link against crtbegin.o; the - linker won't look for a file to match a - wildcard. The wildcard also means that it - doesn't matter which directory crtbegin.o - is in. */ - KEEP (*crtbegin*.o(.ctors)) - /* We don't want to include the .ctor section from - from the crtend.o file until after the sorted ctors. - The .ctor section from the crtend file contains the - end of ctors marker and it must be last */ - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .ctors)) - KEEP (*(SORT(.ctors.*))) - KEEP (*(.ctors)) - } - .dtors : - { - KEEP (*crtbegin*.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) - } - .jcr : { KEEP (*(.jcr)) } - _gp = ALIGN(16) + 0x7ff0; - .got : { *(.got.plt) *(.got) } - /* We want the small data sections together, so single-instruction offsets - can access them all, and initialized data all before uninitialized, so - we can shorten the on-disk segment size. */ - .sdata : - { - *(.sdata .sdata.* .gnu.linkonce.s.*) - } - .lit8 : { *(.lit8) } - .lit4 : { *(.lit4) } - _edata = .; - PROVIDE (edata = .); - __bss_start = .; - _fbss = .; - .sbss : - { - PROVIDE (__sbss_start = .); - PROVIDE (___sbss_start = .); - *(.dynsbss) - *(.sbss .sbss.* .gnu.linkonce.sb.*) - *(.scommon) - PROVIDE (__sbss_end = .); - PROVIDE (___sbss_end = .); - } - .bss : - { - *(.dynbss) - *(.bss .bss.* .gnu.linkonce.b.*) - *(COMMON) - /* Align here to ensure that the .bss section occupies space up to - _end. Align after .bss to ensure correct alignment even if the - .bss section disappears because there are no input sections. */ - . = ALIGN(32 / 8); - } - . = ALIGN(32 / 8); - _end = .; - PROVIDE (end = .); - /* Stabs debugging sections. */ - .stab 0 : { *(.stab) } - .stabstr 0 : { *(.stabstr) } - .stab.excl 0 : { *(.stab.excl) } - .stab.exclstr 0 : { *(.stab.exclstr) } - .stab.index 0 : { *(.stab.index) } - .stab.indexstr 0 : { *(.stab.indexstr) } - .comment 0 : { *(.comment) } - /* DWARF debug sections. - Symbols in the DWARF debugging sections are relative to the beginning - of the section so we begin them at 0. */ - /* DWARF 1 */ - .debug 0 : { *(.debug) } - .line 0 : { *(.line) } - /* GNU DWARF 1 extensions */ - .debug_srcinfo 0 : { *(.debug_srcinfo) } - .debug_sfnames 0 : { *(.debug_sfnames) } - /* DWARF 1.1 and DWARF 2 */ - .debug_aranges 0 : { *(.debug_aranges) } - .debug_pubnames 0 : { *(.debug_pubnames) } - /* DWARF 2 */ - .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } - .debug_abbrev 0 : { *(.debug_abbrev) } - .debug_line 0 : { *(.debug_line) } - .debug_frame 0 : { *(.debug_frame) } - .debug_str 0 : { *(.debug_str) } - .debug_loc 0 : { *(.debug_loc) } - .debug_macinfo 0 : { *(.debug_macinfo) } - /* SGI/MIPS DWARF 2 extensions */ - .debug_weaknames 0 : { *(.debug_weaknames) } - .debug_funcnames 0 : { *(.debug_funcnames) } - .debug_typenames 0 : { *(.debug_typenames) } - .debug_varnames 0 : { *(.debug_varnames) } - .gptab.sdata : { *(.gptab.data) *(.gptab.sdata) } - .gptab.sbss : { *(.gptab.bss) *(.gptab.sbss) } - /DISCARD/ : { *(.note.GNU-stack) } -} -- 2.16.2
Various simplifications and adjustments to the MIPS crt0 files: - Use NESTED(__start, 0, ra) - this has no effect on the code, but is arguably more correct since we have no real stack frame. - Don't allocate extra stack space. We need none on 64-bit, and only 16 bytes on 32-bit. - Align the stack pointer in the (unlikely) event it is misaligned. - Don't load the gp register - it is useless in non-PIC code. - Use jal in 64-bit code. - Crash if __libc_start returns (teq should causes a trap exception). Signed-off-by: James Cowgill <james.cowgill at mips.com> --- usr/klibc/arch/mips/crt0.S | 13 +++++-------- usr/klibc/arch/mips64/crt0.S | 20 +++++--------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/usr/klibc/arch/mips/crt0.S b/usr/klibc/arch/mips/crt0.S index 142d9f26..47d7d8fd 100644 --- a/usr/klibc/arch/mips/crt0.S +++ b/usr/klibc/arch/mips/crt0.S @@ -10,16 +10,13 @@ #include <machine/asm.h> -NESTED(__start, 32, sp) - subu sp, 32 - sw zero, 16(sp) - - lui gp, %hi(_gp) # Initialize gp - addiu gp, gp, _gp - - addiu a0, sp, 32 # Pointer to ELF entry structure +NESTED(__start, 0, ra) + move a0, sp # Pointer to ELF entry structure move a1, v0 # Kernel-provided atexit() pointer + and sp, -8 # Align stack to 8 bytes + subu sp, 16 # Allocate 16 bytes for function call jal __libc_init + teq zero, zero # Crash if we return END(__start) diff --git a/usr/klibc/arch/mips64/crt0.S b/usr/klibc/arch/mips64/crt0.S index 775a9192..3f1c2a9a 100644 --- a/usr/klibc/arch/mips64/crt0.S +++ b/usr/klibc/arch/mips64/crt0.S @@ -10,22 +10,12 @@ #include <machine/asm.h> -NESTED(__start, 64, sp) - daddiu sp,sp,-64 - sd zero, 32(sp) - - # Initialize gp - lui gp,%highest(_gp) # load highest "halfword" - daddiu gp,gp,%higher(_gp) # merge next "halfword" - dsll gp,gp,16 # shift by one halfword - daddiu gp,gp,%hi(_gp) # merge next "halfword" - dsll gp,gp,16 # shift into final position - daddiu gp,gp,%lo(_gp) # merge lowest "halfword" - - daddiu a0, sp, 64 # Pointer to ELF entry structure +NESTED(__start, 0, ra) + move a0, sp # Pointer to ELF entry structure move a1, v0 # Kernel-provided atexit() pointer + and sp, -16 # Align stack to 16 bytes - ld t9, %call16(__libc_init)(gp) - jalr t9 + jal __libc_init + teq zero, zero # Crash if we return END(__start) -- 2.16.2
James Cowgill
2018-Mar-02 16:33 UTC
[klibc] [PATCH 4/5] mips: don't save floating point registers in setjmp / longjmp
Don't bother saving any floating point registers in setjmp or restoring them in longjmp. This causes issues when compiling for the FPXX ABI, and is unnessesary as klibc does not support floating point code. Additionally, remove the unused parts of __jmp_buf. Signed-off-by: James Cowgill <james.cowgill at mips.com> --- This patch is similar to a prvious patch written by Yunqiang Su, however I also added some extra cleanups. We don't need to save the floating point control register (fcr31) and we can remove the extra space allocated in __jmp_buf. Also remove __unused which I assume was only there for alignment purposes. --- usr/include/arch/mips/klibc/archsetjmp.h | 14 -------------- usr/klibc/arch/mips/setjmp.S | 30 ------------------------------ 2 files changed, 44 deletions(-) diff --git a/usr/include/arch/mips/klibc/archsetjmp.h b/usr/include/arch/mips/klibc/archsetjmp.h index 1fbe83ef..eeadffce 100644 --- a/usr/include/arch/mips/klibc/archsetjmp.h +++ b/usr/include/arch/mips/klibc/archsetjmp.h @@ -18,20 +18,6 @@ struct __jmp_buf { unsigned long __sp; unsigned long __s8; unsigned long __ra; - unsigned long __f20; - unsigned long __f21; - unsigned long __f22; - unsigned long __f23; - unsigned long __f24; - unsigned long __f25; - unsigned long __f26; - unsigned long __f27; - unsigned long __f28; - unsigned long __f29; - unsigned long __f30; - unsigned long __f31; - unsigned long __fcr31; - unsigned long __unused; } __attribute__ ((aligned(8))); typedef struct __jmp_buf jmp_buf[1]; diff --git a/usr/klibc/arch/mips/setjmp.S b/usr/klibc/arch/mips/setjmp.S index 68eed19d..9145dbc0 100644 --- a/usr/klibc/arch/mips/setjmp.S +++ b/usr/klibc/arch/mips/setjmp.S @@ -9,8 +9,6 @@ # sp # s8 # ra -# f20..f31 -# fcr31 # #include <machine/asm.h> @@ -28,20 +26,6 @@ LEAF(setjmp) sw sp, 36(a0) sw s8, 40(a0) sw ra, 44(a0) - cfc1 t0,$31 - swc1 $f20,48(a0) - swc1 $f21,52(a0) - swc1 $f22,56(a0) - swc1 $f23,60(a0) - swc1 $f24,64(a0) - swc1 $f25,68(a0) - swc1 $f26,72(a0) - swc1 $f27,76(a0) - swc1 $f28,80(a0) - swc1 $f29,84(a0) - swc1 $f30,88(a0) - swc1 $f31,92(a0) - sw t0,96(a0) move v0,zero jr ra @@ -60,20 +44,6 @@ LEAF(longjmp) lw sp, 36(a0) lw s8, 40(a0) lw ra, 44(a0) - lw t0, 96(a0) - lwc1 $f20,48(a0) - lwc1 $f21,52(a0) - lwc1 $f22,56(a0) - lwc1 $f23,60(a0) - lwc1 $f24,64(a0) - lwc1 $f25,68(a0) - lwc1 $f26,72(a0) - lwc1 $f27,76(a0) - lwc1 $f28,80(a0) - lwc1 $f29,84(a0) - lwc1 $f30,88(a0) - lwc1 $f31,92(a0) - ctc1 t0,$31 move v0,a1 jr ra -- 2.16.2
James Cowgill
2018-Mar-02 16:36 UTC
[klibc] [PATCH 5/5] mips64: remove __unused from __jmp_buf
This field is not needed. Probably it was copied straight from the 32-bit mips __jmp_buf. Signed-off-by: James Cowgill <james.cowgill at mips.com> --- usr/include/arch/mips64/klibc/archsetjmp.h | 1 - 1 file changed, 1 deletion(-) diff --git a/usr/include/arch/mips64/klibc/archsetjmp.h b/usr/include/arch/mips64/klibc/archsetjmp.h index c4587dc3..bfca7776 100644 --- a/usr/include/arch/mips64/klibc/archsetjmp.h +++ b/usr/include/arch/mips64/klibc/archsetjmp.h @@ -18,7 +18,6 @@ struct __jmp_buf { unsigned long __sp; unsigned long __s8; unsigned long __ra; - unsigned long __unused; } __attribute__ ((aligned(8))); typedef struct __jmp_buf jmp_buf[1]; -- 2.16.2
Reasonably Related Threads
- [PATCH] add mips64 support
- [klibc 28/43] mips support for klibc
- [klibc 00/31] klibc as a historyless patchset (updated and reorganized)
- [klibc:master] mips: use -Ttext-segment when linking shared library
- [PATCH] mips/setjmp.S don't save and restore float point registers