diff --git a/Elf2Mac/Elf2Mac.cc b/Elf2Mac/Elf2Mac.cc index 47bb99872a..0e5a0efcab 100644 --- a/Elf2Mac/Elf2Mac.cc +++ b/Elf2Mac/Elf2Mac.cc @@ -54,21 +54,30 @@ size_t mainStringTableIdx = (size_t)-1; class Symtab; class Section; +Elf *elf; std::vector relocs; unique_ptr symtab; unordered_map> sections; unordered_map> sectionsByElfIndex; std::vector> codeSections; -shared_ptr
dataSection; +shared_ptr
dataSection, bssSection; enum class SectionKind { undefined = -1, + code = 0, + data, + bss +}; + +enum class RelocBase +{ code = 0, data, bss, - jumptable + jumptable, + code1 }; class Symbol : public GElf_Sym @@ -77,9 +86,14 @@ public: bool valid; bool referencedExternally; SectionKind sectionKind; + bool needsJT; + int jtIndex; + shared_ptr
section; Symbol(); - Symbol(GElf_Sym sym); + Symbol(const GElf_Sym& sym); + + string GetName(); }; class Symtab @@ -94,6 +108,15 @@ public: Symbol& GetSym(int idx); }; +class Reloc : public GElf_Rela +{ +public: + RelocBase relocBase; + + Reloc(); + Reloc(const GElf_Rela& rela); +}; + class Section { public: @@ -102,17 +125,24 @@ public: SectionKind kind; Elf_Scn *elfsec, *relasec; Elf_Data *data; + GElf_Shdr shdr; + uint32_t outputBase; - std::vector relocs; + int codeID; + + std::vector relocs; + std::vector jtEntries; + int firstJTEntryIndex; Section(string name, int idx, SectionKind kind, Elf_Scn *elfsec); void SetRela(Elf_Scn *scn); uint32_t GetSize(); string GetData(); - string GetAbsRelocations(bool suppressTerminatingEntry = false); + string GetAbsRelocations(bool useOffsets, bool suppressTerminatingEntry = false); void ScanRelocs(); + void FixRelocs(); }; Symbol::Symbol() @@ -120,17 +150,24 @@ Symbol::Symbol() { } -Symbol::Symbol(GElf_Sym sym) +Symbol::Symbol(const GElf_Sym &sym) : GElf_Sym(sym), valid(true), referencedExternally(false), - sectionKind(SectionKind::undefined) + sectionKind(SectionKind::undefined), + needsJT(false) { - if(st_shndx != SHN_UNDEF) + if(st_shndx != SHN_UNDEF && st_shndx < SHN_LORESERVE) { - sectionKind = sectionsByElfIndex[st_shndx]->kind; + section = sectionsByElfIndex[st_shndx]; + sectionKind = section->kind; } } +string Symbol::GetName() +{ + return elf_strptr(elf, mainStringTableIdx, st_name); +} + Symtab::Symtab(Elf_Scn *elfsec) : elfsec(elfsec) { @@ -157,10 +194,23 @@ Symbol &Symtab::GetSym(int idx) } } + +Reloc::Reloc() +{ +} + +Reloc::Reloc(const GElf_Rela &rela) + : GElf_Rela(rela) +{ +} + Section::Section(string name, int idx, SectionKind kind, Elf_Scn *elfsec) - : name(name), idx(idx), kind(kind), elfsec(elfsec), relasec(NULL) + : name(name), idx(idx), kind(kind), elfsec(elfsec), relasec(NULL), + codeID(-1), firstJTEntryIndex(0) { data = elf_getdata(elfsec, NULL); + gelf_getshdr(elfsec, &shdr); + outputBase = shdr.sh_addr; } void Section::SetRela(Elf_Scn *scn) @@ -192,10 +242,8 @@ string Section::GetData() return string((char*)data->d_buf, (char*)data->d_buf + data->d_size); } -string Section::GetAbsRelocations(bool suppressTerminatingEntry) +string Section::GetAbsRelocations(bool useOffsets, bool suppressTerminatingEntry) { - if(!relasec) - return ""; std::ostringstream out; for(auto& rela : relocs) @@ -208,14 +256,21 @@ string Section::GetAbsRelocations(bool suppressTerminatingEntry) Symbol& sym = symtab->GetSym(symidx); - if(sym.st_shndx == SHN_UNDEF) + if(sym.st_shndx == SHN_UNDEF || sym.st_shndx >= SHN_LORESERVE) + continue; + if(sym.sectionKind == SectionKind::undefined) continue; if(GELF_R_TYPE(rela.r_info) == R_68K_32) { assert(sym.sectionKind != SectionKind::undefined); - longword(out, rela.r_offset | ((int)sym.sectionKind << 24)); + uint32_t offset = rela.r_offset; + if(useOffsets) + offset -= shdr.sh_addr; + + + longword(out, offset | ((int)rela.relocBase << 24)); } } if(!suppressTerminatingEntry) @@ -241,6 +296,84 @@ void Section::ScanRelocs() } } +void Section::FixRelocs() +{ + //bool first_reloc = true; + for(Reloc& rela : relocs) + { + if(GELF_R_TYPE(rela.r_info) != R_68K_32) + continue; + + int symidx = GELF_R_SYM(rela.r_info); + if(symidx == 0) + continue; + Symbol& sym = symtab->GetSym(symidx); + + if(sym.sectionKind == SectionKind::undefined) + continue; + + RelocBase relocBase; + switch(sym.sectionKind) + { + case SectionKind::code: + relocBase = RelocBase::code; + if(sym.needsJT) + { + if(rela.r_addend == 0) + { + relocBase = RelocBase::jumptable; + } + else + { + if(sym.section.get() != this) + { + std::cerr << "Invalid ref from " + << name << ":" << std::hex << rela.r_offset-shdr.sh_addr << std::dec + << " to " << sym.section->name + << "(" << sym.GetName() << ")" + << "+" << rela.r_offset << std::endl; + } + assert(sym.section.get() == this); + } + } + break; + case SectionKind::data: + relocBase = RelocBase::data; + break; + case SectionKind::bss: + relocBase = RelocBase::bss; + break; + } + rela.relocBase = relocBase; + + uint8_t *relocand = ((uint8_t*) data->d_buf + rela.r_offset - shdr.sh_addr); + /*if(first_reloc) + { + std::cout << "sec kind: " << (int)sym.sectionKind << std::endl; + std::cout << "reloc addr:" << rela.r_offset << std::endl; + }*/ + + + if(relocBase == RelocBase::jumptable) + { + uint32_t dst = 0x20 + sym.jtIndex * 8 + 2; + relocand[0] = dst >> 24; + relocand[1] = dst >> 16; + relocand[2] = dst >> 8; + relocand[3] = dst; + } + else + { + uint32_t orig = (relocand[0] << 24) | (relocand[1] << 16) | (relocand[2] << 8) | relocand[3]; + uint32_t dst = orig + sym.section->outputBase - sym.section->shdr.sh_addr; + relocand[0] = dst >> 24; + relocand[1] = dst >> 16; + relocand[2] = dst >> 8; + relocand[3] = dst; + } + } +} + void GrokELF(string input) { @@ -248,15 +381,13 @@ void GrokELF(string input) errx(EXIT_FAILURE , "ELF library initialization failed: %s", elf_errmsg( -1)); int fd = open(input.c_str(), O_RDONLY, 0); - Elf *elf = elf_begin(fd, ELF_C_READ, NULL); + elf = elf_begin(fd, ELF_C_READ, NULL); elf_getshdrstrndx(elf, §ionHeaderStringTableIdx); GElf_Ehdr ehdr; gelf_getehdr(elf, &ehdr); - Elf_Scn* bssSection = NULL; - int idx = 1; for(Elf_Scn *scn = NULL; (scn = elf_nextscn(elf, scn)) != NULL; idx++) { @@ -299,12 +430,11 @@ void GrokELF(string input) } if(shdr.sh_type == SHT_NOBITS) { - bssSection = scn; // Currently, the bss section is used // to know when to start skipping debug info sections. // (What's the official way to distinguish a debug info section from a "real" section?) - sections[name] = sectionsByElfIndex[idx] = + bssSection = sections[name] = sectionsByElfIndex[idx] = make_shared
(name, idx, SectionKind::bss, scn); } } @@ -321,8 +451,8 @@ void FlatCode(std::ostream& out) out << dataSection->GetData(); for(auto sec : codeSections) - out << sec->GetAbsRelocations(true); - out << dataSection->GetAbsRelocations(); + out << sec->GetAbsRelocations(false, true); + out << dataSection->GetAbsRelocations(false); } @@ -401,39 +531,134 @@ void MultiSegmentApp(string output) ResourceFile file(output); Resources& rsrc = file.resources; - for(auto sec : codeSections) + for(auto namedSec : sections) { - sec->ScanRelocs(); + namedSec.second->ScanRelocs(); } - rsrc.addResource(Resource(ResType("CODE"), 0, - fromhex( - "00000028 00000000 00000008 00000020" - "0000 3F3C 0001 A9F0" - ) - )); + int jtEntryCount = 0; + unordered_map> jtEntries; + for(Symbol& sym : symtab->symbols) + { + if(sym.valid) + { + if(sym.referencedExternally && sym.sectionKind == SectionKind::code) + { + sym.needsJT = true; + sym.jtIndex = -1; + sym.section->jtEntries.push_back(&sym); + ++jtEntryCount; + } + } + } + uint32_t data_and_bss_size = dataSection->shdr.sh_size + bssSection->shdr.sh_size; + + { + std::ostringstream code0; + longword(code0, 0x20 + 8 * (jtEntryCount+2)); + longword(code0, data_and_bss_size); + longword(code0, 8 * (jtEntryCount+2)); + longword(code0, 0x20); + + code0 << fromhex("0000 3F3C 0001 A9F0"); // jt entry for entrypoint + code0 << fromhex("0000 FFFF 0000 0000"); // 32-bit entries start from here + + int jtIndex = 2; + int id = 1; + for(auto sec : codeSections) + { + sec->codeID = id; + + sec->firstJTEntryIndex = jtIndex; + + GElf_Shdr &shdr = sec->shdr; + + for(Symbol* jtEntry : sec->jtEntries) + { + word(code0, id); + word(code0, 0xA9F0); + uint32_t offset = jtEntry->st_value - shdr.sh_addr; + if(id == 1) + offset += 4; + else + offset += 40; + longword(code0, offset); + + jtEntry->jtIndex = jtIndex++; + + //std::cout << "JT Entry " << jtEntry->jtIndex << ": " << jtEntry->GetName() << std::endl; + } + + id++; + } + + std::cout << "CODE 0: " << code0.str().size() << " bytes\n"; + std::cout << "above A5: " << 0x20 + 8 * (jtEntryCount+2) << " bytes\n"; + std::cout << "below A5: " << data_and_bss_size << " bytes\n"; + std::cout << ".data: " << dataSection->shdr.sh_size << " bytes at A5-" + << std::hex << data_and_bss_size << std::dec << "\n"; + std::cout << ".bss: " << bssSection->shdr.sh_size << " bytes at A5-" + << std::hex << bssSection->shdr.sh_size << std::dec << "\n"; + + rsrc.addResource(Resource(ResType("CODE"), 0, code0.str())); + } - int id = 1; for(auto sec : codeSections) { + int id = sec->codeID; + if(id == 1) + sec->outputBase = 4; // standard 'CODE' header + else + sec->outputBase = 40; // far-model 'CODE' header + } + dataSection->outputBase = -data_and_bss_size; + bssSection->outputBase = -bssSection->shdr.sh_size; + + + for(auto namedSec : sections) + { + namedSec.second->FixRelocs(); + } + + for(auto sec : codeSections) + { + int id = sec->codeID; std::ostringstream code; - word(code, 0); //FIXME: header - word(code, 1); + if(id == 1) + { + word(code, 0); + word(code, 1); + } + else + { + word(code, 0xFFFF); + word(code, 0); + longword(code, 0); + longword(code, 0); + longword(code, 0x20 + 8 * sec->firstJTEntryIndex ); + longword(code, sec->jtEntries.size()); + longword(code, 0); // reloc info for A5 + longword(code, 0); // assumed address for A5 + longword(code, 0); // reloc info for code + longword(code, 0); // assumed address for start of code resource + longword(code, 0); + } code << sec->GetData(); + std::cout << "CODE " << id << ": " << code.str().size() << " bytes\n"; + rsrc.addResource(Resource(ResType("CODE"), id, code.str())); - rsrc.addResource(Resource(ResType("RELA"),id, sec->GetAbsRelocations())); - id++; + rsrc.addResource(Resource(ResType("RELA"),id, sec->GetAbsRelocations(true))); } rsrc.addResource(Resource(ResType("DATA"),0, dataSection->GetData())); + rsrc.addResource(Resource(ResType("RELA"),0, dataSection->GetAbsRelocations(true))); - - + std::cout << "DATA 0: " << dataSection->shdr.sh_size << " bytes\n"; file.creator = ResType("????"); file.type = ResType("APPL"); @@ -497,7 +722,7 @@ int main(int argc, char *argv[]) string outputFile = "a.out"; bool elf2mac = false; bool flatoutput = false; - bool segments = false; + bool segments = true; vector args2; for(auto p = args.begin(), e = args.end(); p != e; ++p) @@ -575,9 +800,10 @@ int main(int argc, char *argv[]) if(argc != 2) errx(EXIT_FAILURE, "usage : %s file-name ", argv[0]); GrokELF(argv[1]); - FlatCode("out.flt"); + MultiSegmentApp("out.bin"); } return 0; } + diff --git a/Elf2Mac/LdScript.cc b/Elf2Mac/LdScript.cc index 3421064606..5160254a0a 100644 --- a/Elf2Mac/LdScript.cc +++ b/Elf2Mac/LdScript.cc @@ -37,13 +37,16 @@ const char * textSection = R"ld(/* ld script for Elf2Mac */ PROVIDE(_rsrc_start = .); *(.rsrcheader) . = ALIGN (2); + + /* The entry point. */ _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 */ + Retro68InitMultisegApp = .; /* override this for the single-segment case */ SHORT(0x4e75); /* rts */ *(.relocvars) @@ -83,9 +86,11 @@ const char * textSection = R"ld(/* ld script for Elf2Mac */ const char * code1Section = R"ld(/* ld script for Elf2Mac */ .code1 : { _stext = . ; + FILL(0x4E71); PROVIDE(_rsrc_start = .); . = ALIGN (2); _entry_trampoline = .; + __break_on_entry = 1; SHORT(DEFINED(__break_on_entry) ? 0xA9FF : 0x4e71); LONG(0x61000002); /* bsr *+2 */ SHORT(0x0697); /* addi.l #_, (a7) */ @@ -96,7 +101,10 @@ const char * code1Section = R"ld(/* ld script for Elf2Mac */ *(.relocvars) */libretrocrt.a:start.c.obj(.text*) */libretrocrt.a:relocate.c.obj(.text*) - + */libretrocrt.a:*(.text*) + */libgcc.a:*(.text*) + */libc.a:*(.text*) + . = ALIGN (4) ; __init_section = . ; KEEP (*(.init)) @@ -114,16 +122,17 @@ const char * code1Section = R"ld(/* ld script for Elf2Mac */ )ld"; const char * codeSectionTemplate = R"ld(/* ld script for Elf2Mac */ .code@N@ : { + FILL(0x4E71); @FILTER@(.text*) @EXTRA@ . = ALIGN (4) ; - KEEP(@FILTER@(.eh_frame)) + /* KEEP(@FILTER@(.eh_frame)) LONG(0); KEEP(@FILTER@(.gcc_except_table)) - KEEP(@FILTER@(.gcc_except_table.*)) + KEEP(@FILTER@(.gcc_except_table.*)) */ . = ALIGN(0x4) ; } @@ -227,6 +236,8 @@ const char * scriptEnd = R"ld( .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } + + /DISCARD/ : { *(*) } } )ld"; @@ -236,6 +247,7 @@ void CreateLdScript(std::ostream& out, bool segments) { if(segments) { + out << "_MULTISEG_APP = 1;\n"; out << scriptStart << code1Section; string code = codeSectionTemplate; boost::replace_all(code, "@N@", "2"); @@ -245,5 +257,8 @@ void CreateLdScript(std::ostream& out, bool segments) out << scriptEnd; } else + { + out << "_MULTISEG_APP = 0;\n"; out << scriptStart << textSection << scriptEnd; + } } diff --git a/libretro/CMakeLists.txt b/libretro/CMakeLists.txt index d31e1d72c1..7ea19e6cc8 100644 --- a/libretro/CMakeLists.txt +++ b/libretro/CMakeLists.txt @@ -36,6 +36,8 @@ if(CMAKE_SYSTEM_NAME MATCHES Retro68) start.c relocate.c PoorMansDebugging.h + MultiSegApp.c + LoadSeg.s # glue.c ${CMAKE_CURRENT_BINARY_DIR}/Interface.s qdglobals.c @@ -45,6 +47,7 @@ if(CMAKE_SYSTEM_NAME MATCHES Retro68) install(FILES Retro68Runtime.h DESTINATION include) install(FILES Retro68.r Retro68APPL.r DESTINATION RIncludes) + elseif(CMAKE_SYSTEM_NAME MATCHES RetroPPC) enable_language(ASM) set(ARCH_FILES diff --git a/libretro/Retro68Runtime.h b/libretro/Retro68Runtime.h index 7dfadb3a5d..c70b3ca008 100644 --- a/libretro/Retro68Runtime.h +++ b/libretro/Retro68Runtime.h @@ -23,6 +23,8 @@ . */ +#include + #define _RETRO68_GET_DISPLACEMENT(DISPLACEMENT, STRIP) \ do { \ char *virtualstart, *realstart; \ @@ -63,5 +65,7 @@ void Retro68Relocate(); void Retro68CallConstructors(); void Retro68CallDestructors(); void Retro68FreeGlobals(); +void Retro68InitMultisegApp(); +void Retro68ApplyRelocations(uint8_t *base, uint32_t size, void *relocations, uint32_t displacements[]); #define RETRO68_RELOCATE() RETRO68_CALL_UNRELOCATED(Retro68Relocate,()) diff --git a/libretro/relocate.c b/libretro/relocate.c index 594f19077e..ea11c345d0 100644 --- a/libretro/relocate.c +++ b/libretro/relocate.c @@ -31,6 +31,7 @@ #include #include #include +#include #include "Retro68Runtime.h" #include "PoorMansDebugging.h" @@ -41,6 +42,10 @@ typedef void (*voidFunction)(void); Linker-defined addresses in the binary; */ + // absolute address 0x1 for multiseg applications, + // absolute address NULL (or undefined) for code resources +extern uint8_t _MULTISEG_APP __attribute__ ((weak)); + // section boundaries extern uint8_t _stext, _etext, _sdata, _edata, _sbss, _ebss; // constructor list: @@ -101,6 +106,26 @@ static Retro68RelocState relocState __attribute__ ((section(".relocvars"))) = { } while(0) +void Retro68ApplyRelocations(uint8_t *base, uint32_t size, void *relocations, uint32_t displacements[]) +{ + uint32_t *reloc = (uint32_t*) relocations; + // Process relocation records + for(;*reloc != -1;++reloc) + { + uint32_t r = *reloc; + uint8_t *addrPtr = base + (r & 0xFFFFFF); + uint8_t *addr; + uint8_t kind = r >> 24; + + assert(addrPtr >= base); + assert(addrPtr < base + size); + + addr = (uint8_t*) READ_UNALIGNED_LONGWORD(addrPtr); + addr += displacements[kind]; + WRITE_UNALIGNED_LONGWORD(addrPtr, (uint32_t) addr); + } +} + void Retro68Relocate() { // memory address to retrieve the ROM type (64K or a later ROM) @@ -128,7 +153,7 @@ void Retro68Relocate() if (hasStripAddr) { - RETRO68_GET_DISPLACEMENT_STRIP(displacement); + RETRO68_GET_DISPLACEMENT_STRIP(displacement); } else { @@ -172,38 +197,47 @@ void Retro68Relocate() log(orig_ebss); uint8_t *base = orig_stext + displacement; - - { - uint8_t *orig_rsrc_start; - GET_VIRTUAL_ADDRESS(orig_rsrc_start, _rsrc_start); - uint8_t *rsrc_start = orig_rsrc_start + displacement; - - Handle h = RecoverHandle((Ptr) rsrc_start); - if(MemError() == noErr && h) - { - // Make sure the code is locked. Only relevant for some code resources. - HLock(h); - rState->codeHandle = h; - } - } - - uint32_t text_and_data_size = orig_edata - orig_stext; - long bss_size = orig_ebss - orig_sbss; - - //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) + long data_displacement = 0; + long jt_displacement = 0; + + if(&_MULTISEG_APP) { - THz zone = ApplicationZone(); - if(!zone || base < (uint8_t*)zone) - rState->bssPtr = NewPtrSysClear(bss_size); - else - rState->bssPtr = NewPtrClear(bss_size); - bss_displacement = (uint8_t*)rState->bssPtr - orig_sbss; + uint8_t * a5 = (uint8_t*) SetCurrentA5(); + bss_displacement = a5 - orig_ebss; + data_displacement = a5 - orig_ebss; + jt_displacement = a5 - (uint8_t*)NULL; } + else + { + data_displacement = displacement; + { + uint8_t *orig_rsrc_start; + GET_VIRTUAL_ADDRESS(orig_rsrc_start, _rsrc_start); + uint8_t *rsrc_start = orig_rsrc_start + displacement; + + Handle h = RecoverHandle((Ptr) rsrc_start); + if(MemError() == noErr && h) + { + // Make sure the code is locked. Only relevant for some code resources. + HLock(h); + rState->codeHandle = h; + } + } + + // Allocate BSS section (uninitialized/zero-initialized global data) + if(!rState->bssPtr) + { + uint32_t bss_size = orig_ebss - orig_sbss; + THz zone = ApplicationZone(); + if(!zone || base < (uint8_t*)zone) + rState->bssPtr = NewPtrSysClear(bss_size); + else + rState->bssPtr = NewPtrClear(bss_size); + bss_displacement = (uint8_t*)rState->bssPtr - orig_sbss; + } + } /* Relocation records consist of 4 bytes each. @@ -214,40 +248,33 @@ void Retro68Relocate() */ long displacements[4] = { displacement, // code - displacement, // data (contiguous with code) - bss_displacement, // bss (allocated separately) - SetCurrentA5() // jump table (TODO) + data_displacement, + bss_displacement, + jt_displacement }; - // Process relocation records - for(long *reloc = (long*)( base + text_and_data_size ); - *reloc != -1; - ++reloc) + void *reloc; + Handle RELA = NULL; + uint32_t relocatableSize; + if(&_MULTISEG_APP) { - uint32_t r = *reloc; - uint8_t *addrPtr = base + (r & 0xFFFFFF); - uint8_t *addr; - uint8_t kind = r >> 24; - - assert(addrPtr >= base); - assert(addrPtr < base + text_and_data_size); - - addr = (uint8_t*) READ_UNALIGNED_LONGWORD(addrPtr); - - /* Check whether addresses are in range. - * This doesn't seem to work because exception handling tables - * seem to contain strange things. - */ - /*assert((uint8_t*)addr >= orig_stext); // TODO: not right for repeated reloc - assert((uint8_t*)addr <= orig_stext + total_size);*/ - - addr += displacements[kind]; - - /*assert((Ptr)addr >= (Ptr)base && (Ptr)addr <= (Ptr)base + text_and_data_size - || (Ptr)addr >= rState->bssPtr && (Ptr)addr <= rState->bssPtr + bss_size);*/ - - WRITE_UNALIGNED_LONGWORD(addrPtr, (uint32_t) addr); + RELA = Get1Resource('RELA', 1); + assert(RELA); + reloc = *RELA; + uint32_t text_size = orig_etext - orig_stext; + relocatableSize = text_size; } + else + { + uint32_t text_and_data_size = orig_edata - orig_stext; + reloc = base + text_and_data_size; + relocatableSize = text_and_data_size; + } + + typedef typeof(&Retro68ApplyRelocations) ApplyRelocationsPtr; + ApplyRelocationsPtr RealApplyRelocations; + RealApplyRelocations = (ApplyRelocationsPtr) ((uint8_t*)&Retro68ApplyRelocations + displacement); + RealApplyRelocations(base, relocatableSize, reloc, displacements); // We're basically done. // Now check whether we're on 68040 or later and need to flush the cache. @@ -265,15 +292,22 @@ void Retro68Relocate() FlushCodeCache(); } } - + // accessing globals and calling functions is OK below here. + // ... as long as it is in the current segment. + + Retro68InitMultisegApp(); + + // Now we're set. + // Someone still needs to invoke Retro68CallConstructors + // ... but that's the job of _start(). } void Retro68CallConstructors() { - static struct object object; + /*static struct object object; if (__register_frame_info) - __register_frame_info(&__EH_FRAME_BEGIN__, &object); + __register_frame_info(&__EH_FRAME_BEGIN__, &object);*/ { uint8_t *p = &__init_section; uint8_t *e = &__init_section_end; @@ -308,8 +342,8 @@ void Retro68CallDestructors() p += 6; } } - if (__deregister_frame_info) - __deregister_frame_info(&__EH_FRAME_BEGIN__); +/* if (__deregister_frame_info) + __deregister_frame_info(&__EH_FRAME_BEGIN__);*/ }