From 975c1f31c32c007f189e91ae149a697ec5c1d556 Mon Sep 17 00:00:00 2001 From: Wolfgang Thaller Date: Sat, 23 Sep 2017 22:36:47 +0200 Subject: [PATCH] Some cleanups --- Elf2Mac/LdScript.cc | 230 ++++++++++++++++++----------------- libretro/CMakeLists.txt | 2 + libretro/PoorMansDebugging.h | 83 +++++++++++++ libretro/relocate.c | 154 ++++++----------------- 4 files changed, 241 insertions(+), 228 deletions(-) create mode 100644 libretro/PoorMansDebugging.h diff --git a/Elf2Mac/LdScript.cc b/Elf2Mac/LdScript.cc index 49f9dc1287..74d14ad5d8 100644 --- a/Elf2Mac/LdScript.cc +++ b/Elf2Mac/LdScript.cc @@ -25,126 +25,130 @@ const char * defaultLdScript = R"ld(/* ld script for Elf2Mac */ ENTRY( _start ) SECTIONS { - .text : { - _stext = . ; + .text : { + _stext = . ; + PROVIDE(_rsrc_start = .); */libretrocrt.a:*(.text*) - *(.text*) + *(.text*) - *(.stub) - *(.gnu.linkonce.t*) - *(.glue_7t) - *(.glue_7) - *(.jcr) - . = ALIGN (4) ; - __init_section = . ; - KEEP (*(.init)) - __init_section_end = . ; - __fini_section = . ; - KEEP (*(.fini)) - __fini_section_end = . ; + *(.stub) + *(.gnu.linkonce.t*) + *(.glue_7t) + *(.glue_7) + *(.jcr) + . = ALIGN (4) ; + __init_section = . ; + KEEP (*(.init)) + __init_section_end = . ; + __fini_section = . ; + KEEP (*(.fini)) + __fini_section_end = . ; - *(.eh_frame_hdr) - KEEP(*(.eh_frame)) - KEEP(*(.gcc_except_table)) - KEEP(*(.gcc_except_table.*)) - . = ALIGN(0x4) ; - _etext = . ; - } - .data : { - _sdata = . ; - *(.got.plt) - *(.got) - FILL(0) ; - . = ALIGN(0x20) ; - LONG(-1) - . = ALIGN(0x20) ; - *(.rodata) - *(.rodata1) - *(.rodata.*) - *(.gnu.linkonce.r*) - *(.data) - *(.data1) - *(.data.*) - *(.gnu.linkonce.d*) + *(.eh_frame_hdr) + KEEP(*(.eh_frame)) + KEEP(*(.gcc_except_table)) + KEEP(*(.gcc_except_table.*)) + . = ALIGN(0x4) ; + _etext = . ; + } + .data : { + _sdata = . ; + *(.got.plt) + *(.got) + FILL(0) ; + . = ALIGN(0x20) ; + LONG(-1) + . = ALIGN(0x20) ; + *(.rodata) + *(.rodata1) + *(.rodata.*) + *(.gnu.linkonce.r*) + *(.data) + *(.data1) + *(.data.*) + *(.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.*))) - KEEP (*(.ctors)) - KEEP (*crtbegin*.o(.dtors)) - KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) - KEEP (*(SORT(.dtors.*))) - KEEP (*(.dtors)) + . = 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.*))) + KEEP (*(.ctors)) + KEEP (*crtbegin*.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend*.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) - *(.tm_clone_table) + *(.tm_clone_table) . = ALIGN(0x4); - _edata = . ; - } - .bss ALIGN(0x4) : { - _sbss = .; - *(.dynsbss) - *(.sbss) - *(.sbss.*) - *(.scommon) - *(.dynbss) - *(.bss) - *(.bss.*) - *(.bss*) - *(.gnu.linkonce.b*) - *(COMMON) - . = ALIGN(0x10) ; - _ebss = . ; - } - /DISCARD/ : { *(.note.GNU-stack) } - /* 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) } + _edata = . ; + } + .bss ALIGN(0x4) : { + _sbss = .; + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.bss*) + *(.gnu.linkonce.b*) + *(COMMON) + . = ALIGN(0x10) ; + _ebss = . ; + } - /* /DISCARD/ : { *(*) } */ + + /* **** Debugging information sections. + * Keep them for now, they are discarded by Elf2Mac. */ + + /DISCARD/ : { *(.note.GNU-stack) } + /* 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) } } )ld"; diff --git a/libretro/CMakeLists.txt b/libretro/CMakeLists.txt index c11f8635f0..d31e1d72c1 100644 --- a/libretro/CMakeLists.txt +++ b/libretro/CMakeLists.txt @@ -35,12 +35,14 @@ if(CMAKE_SYSTEM_NAME MATCHES Retro68) Retro68Runtime.h start.c relocate.c + PoorMansDebugging.h # glue.c ${CMAKE_CURRENT_BINARY_DIR}/Interface.s qdglobals.c Retro68.r Retro68APPL.r ) + install(FILES Retro68Runtime.h DESTINATION include) install(FILES Retro68.r Retro68APPL.r DESTINATION RIncludes) elseif(CMAKE_SYSTEM_NAME MATCHES RetroPPC) diff --git a/libretro/PoorMansDebugging.h b/libretro/PoorMansDebugging.h new file mode 100644 index 0000000000..bfa50ee364 --- /dev/null +++ b/libretro/PoorMansDebugging.h @@ -0,0 +1,83 @@ +/* + Copyright 2017 Wolfgang Thaller. + + This file is part of Retro68. + + Retro68 is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Retro68 is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + Under Section 7 of GPL version 3, you are granted additional + permissions described in the GCC Runtime Library Exception, version + 3.1, as published by the Free Software Foundation. + + You should have received a copy of the GNU General Public License and + a copy of the GCC Runtime Library Exception along with this program; + see the files COPYING and COPYING.RUNTIME respectively. If not, see + . +*/ + +#define ENABLE_ASSERT 1 +#define ENABLE_LOG 0 + +/* a simple version of assert - on failure, the line number is output + * using DebugStr. + + * It is implimented as a dependency-free macro so it can be used in the + * earliest stages of program startup. + */ + + +#if !ENABLE_ASSERT +#define assert(x) do { } while(0) +#else +#define assert(x) do { \ + if(!(x)) {\ + unsigned char str[6]; \ + int i; \ + int l = __LINE__; \ + for(i = 1; i < 6; i++) \ + str[i] = ' '; \ + str[0] = 5; \ + str[5] = '0'; \ + for(i = 5; l && i > 0; i--) \ + { \ + str[i] = '0' + (l % 10); \ + l /= 10; \ + } \ + DebugStr(str); \ + } \ + } while(0) +#endif + +#if !ENABLE_LOG +#define log(x) do { } while(0) +#else +#define log(x) do { \ + {\ + unsigned char str[10]; \ + int ___i; \ + unsigned l = (x); \ + for(___i = 2; ___i < 10; ___i++) \ + str[___i] = ' '; \ + str[0] = 9; \ + str[1] = 'L'; \ + str[9] = '0'; \ + for(___i = 8; l && ___i > 1; ___i--) \ + { \ + str[___i] = '0' + (l & 0xF); \ + if((l & 0xF) >= 0xA) \ + str[___i] = 'A' - 10 + (l&0xF); \ + l >>= 4; \ + } \ + DebugStr(str); \ + } \ + } while(0) + +#endif diff --git a/libretro/relocate.c b/libretro/relocate.c index bf15f229f3..28443f574a 100644 --- a/libretro/relocate.c +++ b/libretro/relocate.c @@ -1,5 +1,5 @@ /* - Copyright 2015 Wolfgang Thaller. + Copyright 2017 Wolfgang Thaller. This file is part of Retro68. @@ -33,97 +33,27 @@ #include #include "Retro68Runtime.h" - - -struct flat_hdr { - char magic[4]; - unsigned long rev; /* version */ - unsigned long entry; /* Offset of first executable instruction - with text segment from beginning of file */ - unsigned long data_start; /* Offset of data segment from beginning of - file */ - unsigned long data_end; /* Offset of end of data segment - from beginning of file */ - unsigned long bss_end; /* Offset of end of bss segment from beginning - of file */ - - /* (It is assumed that data_end through bss_end forms the bss segment.) */ - - unsigned long stack_size; /* Size of stack, in bytes */ - unsigned long reloc_start; /* Offset of relocation records from - beginning of file */ - unsigned long reloc_count; /* Number of relocation records */ - unsigned long flags; - unsigned long filler[6]; /* Reserved, set to zero */ -}; +#include "PoorMansDebugging.h" typedef void (*voidFunction)(void); -extern void __init_section(void); -extern void __init_section_end(void); -extern void __fini_section(void); -extern void __fini_section_end(void); +/* + Linker-defined addresses in the binary; + */ +extern uint8_t _stext, _etext, _sdata, _edata, _sbss, _ebss; +extern uint8_t __init_section, __init_section_end; +extern uint8_t __fini_section, __fini_section_end; typedef struct Retro68RelocState { Ptr bssPtr; Handle codeHandle; } Retro68RelocState; -extern uint8_t _stext, _etext, _sdata, _edata, _sbss, _ebss; static Retro68RelocState relocState __attribute__ ((nocommon, section(".text"))) = { NULL, NULL }; - /* a simple version of assert - on failure, the line number is output - * using DebugStr. */ -#if 0 -#define assert(x) do { } while(0) -#else -#define assert(x) do { \ - if(!(x)) {\ - unsigned char str[6]; \ - int i; \ - int l = __LINE__; \ - for(i = 1; i < 6; i++) \ - str[i] = ' '; \ - str[0] = 5; \ - str[5] = '0'; \ - for(i = 5; l && i > 0; i--) \ - { \ - str[i] = '0' + (l % 10); \ - l /= 10; \ - } \ - DebugStr(str); \ - } \ - } while(0) -#endif - -#if 1 -#define log(x) do { } while(0) -#else -#define log(x) do { \ - {\ - unsigned char str[10]; \ - int ___i; \ - unsigned l = (x); \ - for(___i = 2; ___i < 10; ___i++) \ - str[___i] = ' '; \ - str[0] = 9; \ - str[1] = 'L'; \ - str[9] = '0'; \ - for(___i = 8; l && ___i > 1; ___i--) \ - { \ - str[___i] = '0' + (l & 0xF); \ - if((l & 0xF) >= 0xA) \ - str[___i] = 'A' - 10 + (l&0xF); \ - l >>= 4; \ - } \ - DebugStr(str); \ - } \ - } while(0) - -#endif #define GET_VIRTUAL_ADDRESS(NAME, SYM) \ do { \ @@ -135,6 +65,18 @@ static Retro68RelocState relocState __attribute__ ((nocommon, section(".text"))) NAME = StripAddress24(NAME); \ } while(0) +#define READ_UNALIGNED_LONGWORD(ptr) \ + (((((((ptr)[0] << 8) | (ptr)[1]) << 8) | (ptr)[2]) << 8) | (ptr)[3]) +#define WRITE_UNALIGNED_LONGWORD(ptr, val) \ + do { \ + uint32_t _a = (val); \ + uint8_t *_ptr = (ptr); \ + _ptr[3] = _a; \ + _ptr[2] = (_a >>= 8); \ + _ptr[1] = (_a >>= 8); \ + _ptr[0] = (_a >>= 8); \ + } while(0) + void Retro68Relocate() { @@ -206,18 +148,17 @@ void Retro68Relocate() log(orig_sbss); log(orig_ebss); - uint8_t *base = (uint8_t*) (orig_stext + displacement); - struct flat_hdr *header = ((struct flat_hdr*) (orig_stext + displacement)) - 1; + uint8_t *base = orig_stext + displacement; // Recover the handle to the code resource by looking at the // longword before the FLT header. The resource templates in Retro68.r store the offset // from the beginning of the code resource there. - uint32_t headerOffsetInResource = ((uint32_t*)header)[-1]; + uint32_t offsetInResource = *(uint32_t*)(base - 0x44) + 0x40; - if(headerOffsetInResource < 4096) + if(offsetInResource < 4096) // Arbitrary magic number. We expect the offset to be small, just a few header bytes before it. // if it's out of range, assume the longword before the header is not the offset we're looking for. { - Handle h = RecoverHandle((Ptr) header - headerOffsetInResource); + Handle h = RecoverHandle((Ptr) base - offsetInResource); if(MemError() == noErr && h) { // Make sure the code is locked. Only relevant for some code resources. @@ -226,29 +167,22 @@ void Retro68Relocate() } } - long bss_size = &_ebss - &_sbss; - - - long n = header->reloc_count; - uint32_t text_and_data_size = orig_edata - orig_stext; - uint32_t total_size = orig_ebss - orig_stext; // FIXME: not true for repeated reloc + long bss_size = orig_ebss - orig_sbss; - - - assert(text_and_data_size == header->data_end - sizeof(*header)); - assert(total_size == header->bss_end - sizeof(*header)); + //uint32_t total_size = orig_ebss - orig_stext; // FIXME: not true for repeated reloc + //assert(total_size == header->bss_end - sizeof(*header)); long bss_displacement = 0; // Allocate BSS section (uninitialized/zero-initialized global data) if(!rState->bssPtr) { THz zone = ApplicationZone(); - if(!zone || (uint8_t*)header < (uint8_t*)zone) + if(!zone || base < (uint8_t*)zone) rState->bssPtr = NewPtrSysClear(bss_size); else rState->bssPtr = NewPtrClear(bss_size); - bss_displacement = (uint8_t*)rState->bssPtr - &_sbss; + bss_displacement = (uint8_t*)rState->bssPtr - orig_sbss; } long i; @@ -258,19 +192,13 @@ void Retro68Relocate() *reloc != -1; ++reloc) { - //Debugger(); uint8_t *addrPtr = base + *reloc; - uint32_t addr; + uint8_t *addr; - /*log(relocs + i); - log(relocs[i]);*/ - assert((Ptr)addrPtr >= (Ptr)base); - assert((Ptr)addrPtr < (Ptr)base + text_and_data_size); + assert(addrPtr >= base); + assert(addrPtr < base + text_and_data_size); - //addr = *(uint32_t*)addrPtr; - addr = (((((addrPtr[0] << 8) | addrPtr[1]) << 8) | addrPtr[2]) << 8) | addrPtr[3]; - - //log(addr); + addr = (uint8_t*) READ_UNALIGNED_LONGWORD(addrPtr); /* Check whether addresses are in range. * This doesn't seem to work because exception handling tables @@ -279,17 +207,13 @@ void Retro68Relocate() /*assert((uint8_t*)addr >= orig_stext); // TODO: not right for repeated reloc assert((uint8_t*)addr <= orig_stext + total_size);*/ - addr += (addr - (uint32_t)orig_stext) >= text_and_data_size ? + addr += (addr - orig_stext) >= text_and_data_size ? bss_displacement : displacement; /*assert((Ptr)addr >= (Ptr)base && (Ptr)addr <= (Ptr)base + text_and_data_size || (Ptr)addr >= rState->bssPtr && (Ptr)addr <= rState->bssPtr + bss_size);*/ - addrPtr[3] = addr; - addrPtr[2] = (addr >>= 8); - addrPtr[1] = (addr >>= 8); - addrPtr[0] = (addr >>= 8); - //*(uint32_t*)addrPtr = addr; + WRITE_UNALIGNED_LONGWORD(addrPtr, (uint32_t) addr); } // We're basically done. @@ -314,8 +238,8 @@ void Retro68Relocate() void Retro68CallConstructors() { - char *p = (char*)&__init_section; - char *e = (char*)&__init_section_end; + uint8_t *p = &__init_section; + uint8_t *e = &__init_section_end; p += 2; while( p < e ) { @@ -326,8 +250,8 @@ void Retro68CallConstructors() void Retro68CallDestructors() { - char *p = (char*)&__fini_section; - char *e = (char*)&__fini_section_end; + uint8_t *p = &__fini_section; + uint8_t *e = &__fini_section_end; p += 2; while( p < e ) {