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 )
{