From 33a274464386c408f833d81a57636c26532a3680 Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Sun, 24 Sep 2017 20:04:11 +0200 Subject: [PATCH] Take responsibility: don't use standard crtbegin/end anymore, now that we control the linker script --- Elf2Mac/Elf2Mac.h | 2 +- Elf2Mac/LdScript.cc | 123 ++++++++++++++++++++++++------- TestApps/ExceptionTest.cc | 9 ++- gcc/gcc/config.gcc | 9 +++ gcc/gcc/config/m68k/m68k-macos.h | 10 +++ gcc/gcc/config/m68k/m68k.h | 2 - libretro/relocate.c | 59 ++++++++++++--- 7 files changed, 172 insertions(+), 42 deletions(-) create mode 100644 gcc/gcc/config/m68k/m68k-macos.h diff --git a/Elf2Mac/Elf2Mac.h b/Elf2Mac/Elf2Mac.h index c56150a603..4fcd5711dd 100644 --- a/Elf2Mac/Elf2Mac.h +++ b/Elf2Mac/Elf2Mac.h @@ -22,6 +22,6 @@ #include -void CreateLdScript(std::ofstream& out); +void CreateLdScript(std::ostream& out); #endif // ELF2MAC_H diff --git a/Elf2Mac/LdScript.cc b/Elf2Mac/LdScript.cc index 8157ba68d4..f1760b3d64 100644 --- a/Elf2Mac/LdScript.cc +++ b/Elf2Mac/LdScript.cc @@ -19,18 +19,26 @@ #include "Elf2Mac.h" -#include +#include +#include +#include -const char * defaultLdScript = R"ld(/* ld script for Elf2Mac */ +using std::string; + +const char * scriptStart = R"ld(/* ld script for Elf2Mac */ ENTRY( _start ) SECTIONS { +)ld"; + +const char * textSection = R"ld(/* ld script for Elf2Mac */ .text : { _stext = . ; PROVIDE(_rsrc_start = .); *(.rsrcheader) . = ALIGN (2); _entry_trampoline = .; + SHORT(DEFINED(__break_on_entry) ? 0xA9FF : 0x4e71); LONG(0x61000002); /* bsr *+2 */ SHORT(0x0697); /* addi.l #_, (a7) */ @@ -57,8 +65,10 @@ SECTIONS KEEP (*(.fini)) __fini_section_end = . ; - *(.eh_frame_hdr) + __EH_FRAME_BEGIN__ = .; KEEP(*(.eh_frame)) + LONG(0); + KEEP(*(.gcc_except_table)) KEEP(*(.gcc_except_table.*)) @@ -68,6 +78,67 @@ SECTIONS . = ALIGN(0x4) ; _etext = . ; } +)ld"; + +const char * code1Section = R"ld(/* ld script for Elf2Mac */ + .code1 : { + _stext = . ; + PROVIDE(_rsrc_start = .); + . = ALIGN (2); + _entry_trampoline = .; + SHORT(DEFINED(__break_on_entry) ? 0xA9FF : 0x4e71); + LONG(0x61000002); /* bsr *+2 */ + SHORT(0x0697); /* addi.l #_, (a7) */ + LONG(_start - _entry_trampoline - 6); + PROVIDE(_start = .); /* fallback entry point to a safe spot - needed for libretro bootstrap */ + SHORT(0x4e75); /* rts */ + + *(.relocvars) + */libretrocrt.a:start.c.obj(.text*) + */libretrocrt.a:relocate.c.obj(.text*) + + . = ALIGN (4) ; + __init_section = . ; + KEEP (*(.init)) + __init_section_end = . ; + __fini_section = . ; + KEEP (*(.fini)) + __fini_section_end = . ; + + __EH_FRAME_BEGIN__ = .; + LONG(0); + + . = ALIGN(0x4) ; + _etext = . ; + } +)ld"; +const char * codeSectionTemplate = R"ld(/* ld script for Elf2Mac */ + .code@N@ : { + @FILTER@(.text*) + + @EXTRA@ + + . = ALIGN (4) ; + + KEEP(@FILTER@(.eh_frame)) + LONG(0); + KEEP(@FILTER@(.gcc_except_table)) + KEEP(@FILTER@(.gcc_except_table.*)) + + . = ALIGN(0x4) ; + } +)ld"; + +const char * lastCodeExtra = R"ld( + *(.stub) + *(.gnu.linkonce.t*) + *(.glue_7t) + *(.glue_7) + *(.jcr) +)ld"; + + +const char * scriptEnd = R"ld( .data : { _sdata = . ; *(.got.plt) @@ -86,29 +157,19 @@ SECTIONS *(.gnu.linkonce.d*) . = ALIGN(4) ; - /* 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.*))) + __CTOR_LIST__ = .; KEEP (*(.ctors)) - KEEP (*crtbegin*.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) + KEEP (*(SORT(.ctors.*))) + __CTOR_END__ = .; + LONG(0); + + . = ALIGN(0x4); + __DTOR_LIST__ = .; KEEP (*(.dtors)) - - *(.tm_clone_table) + KEEP (*(SORT(.dtors.*))) + __DTOR_END__ = .; + LONG(0); + . = ALIGN(0x4); _edata = . ; } @@ -171,7 +232,17 @@ SECTIONS )ld"; -void CreateLdScript(std::ofstream& out) +void CreateLdScript(std::ostream& out) { - out << defaultLdScript; +#if 1 + out << scriptStart << textSection << scriptEnd; +#else + out << scriptStart << code1Section; + string code = codeSectionTemplate; + boost::replace_all(code, "@N@", "2"); + boost::replace_all(code, "@FILTER@", "*"); + boost::replace_all(code, "@EXTRA@", lastCodeExtra); + out << code; + out << scriptEnd; +#endif } diff --git a/TestApps/ExceptionTest.cc b/TestApps/ExceptionTest.cc index 91a39bc6f3..0597be65eb 100644 --- a/TestApps/ExceptionTest.cc +++ b/TestApps/ExceptionTest.cc @@ -32,6 +32,8 @@ void foobar() int main(int argc, char** argv) { + bool throwFail = false; + bool catchFail = true; for(int i = 0; i < 5; i++) { int n = i == 0 ? 1 : 100; @@ -39,13 +41,18 @@ int main(int argc, char** argv) long start = TickCount(); for(int j = 0; j < n; j++) { - try { foobar(); } catch(...) {} + try { foobar(); throwFail = true; } catch(...) { catchFail = false; } } long end = TickCount(); printf("%g ms per throw/catch\n",(end-start)*1000 / 60.0 / n); } + if(throwFail) + printf("******** FAILURE: throw didn't really throw\n"); + if(catchFail) + printf("******** FAILURE: catch block never entered\n"); + const int n = 3; printf("Click mouse %d times...\n", n); for(int i = 0; i < n; i++) diff --git a/gcc/gcc/config.gcc b/gcc/gcc/config.gcc index b60b2ebe9a..91fec3798f 100644 --- a/gcc/gcc/config.gcc +++ b/gcc/gcc/config.gcc @@ -1934,6 +1934,15 @@ m68k-*-elf* | fido-*-elf*) esac ;; m68k-*-macos* | fido-*-elf*) + default_m68k_cpu=68020 + default_cf_cpu=5206 + tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68k-macos.h" + tm_defines="${tm_defines} MOTOROLA=1" + tmake_file="m68k/t-floatlib m68k/t-m68kbare m68k/t-m68kelf" + tmake_file="$tmake_file m68k/t-mlibs" + ;; + +fido-*-elf*) default_m68k_cpu=68020 default_cf_cpu=5206 tm_file="${tm_file} m68k/m68k-none.h m68k/m68kelf.h dbxelf.h elfos.h newlib-stdint.h m68k/m68kemb.h m68k/m68020-elf.h" diff --git a/gcc/gcc/config/m68k/m68k-macos.h b/gcc/gcc/config/m68k/m68k-macos.h new file mode 100644 index 0000000000..5e8d528571 --- /dev/null +++ b/gcc/gcc/config/m68k/m68k-macos.h @@ -0,0 +1,10 @@ + +#define LIBGCC_SPEC "-lretrocrt -lgcc" +#define LINK_SPEC "-elf2mac -q -undefined=_consolewrite" + + +#undef STARTFILE_SPEC +#define STARTFILE_SPEC "" +#undef ENDFILE_SPEC +#define ENDFILE_SPEC "" + diff --git a/gcc/gcc/config/m68k/m68k.h b/gcc/gcc/config/m68k/m68k.h index f8e72b2d87..c7ef427c0e 100644 --- a/gcc/gcc/config/m68k/m68k.h +++ b/gcc/gcc/config/m68k/m68k.h @@ -54,8 +54,6 @@ along with GCC; see the file COPYING3. If not see #define SUBTARGET_EXTRA_SPECS -#define LIBGCC_SPEC "-lretrocrt -lgcc" -#define LINK_SPEC "-elf2mac -q -undefined=_consolewrite" /* Note that some other tm.h files include this one and then override many of the definitions that relate to assembler syntax. */ diff --git a/libretro/relocate.c b/libretro/relocate.c index 9fc03c1114..efd19f86e7 100644 --- a/libretro/relocate.c +++ b/libretro/relocate.c @@ -51,6 +51,22 @@ extern uint8_t __fini_section, __fini_section_end; // usually equal to _stext, but can be overridden. extern uint8_t _rsrc_start; +extern voidFunction __CTOR_LIST__, __DTOR_LIST__; +extern uint8_t __EH_FRAME_BEGIN__; + +/* + struct object is an internal data structure in libgcc. + Comments in unwind-dw2-fde.h imply that it will not + increase in size. + */ +struct object { long space[8]; }; + +extern void __register_frame_info (const void *, struct object *) + __attribute__ ((weak)); +extern void *__deregister_frame_info (const void *) + __attribute__ ((weak)); + + typedef struct Retro68RelocState { Ptr bssPtr; @@ -240,26 +256,45 @@ void Retro68Relocate() void Retro68CallConstructors() { - uint8_t *p = &__init_section; - uint8_t *e = &__init_section_end; - p += 2; - while( p < e ) + static struct object object; + if (__register_frame_info) + __register_frame_info(&__EH_FRAME_BEGIN__, &object); { - (*(voidFunction)(*(long*)p))(); - p += 6; + uint8_t *p = &__init_section; + uint8_t *e = &__init_section_end; + p += 2; + while( p < e ) + { + (*(voidFunction)(*(long*)p))(); + p += 6; + } + } + { + voidFunction *p, f; + for(p = &__CTOR_LIST__; (f = *p); p++) + f(); } } void Retro68CallDestructors() { - uint8_t *p = &__fini_section; - uint8_t *e = &__fini_section_end; - p += 2; - while( p < e ) { - (*(voidFunction)(*(long*)p))(); - p += 6; + voidFunction *p, f; + for(p = &__DTOR_LIST__; (f = *p); p++) + f(); } + { + uint8_t *p = &__fini_section; + uint8_t *e = &__fini_section_end; + p += 2; + while( p < e ) + { + (*(voidFunction)(*(long*)p))(); + p += 6; + } + } + if (__deregister_frame_info) + __deregister_frame_info(&__EH_FRAME_BEGIN__); }