diff --git a/CMakeLists.txt b/CMakeLists.txt index 91f8417..2927b3c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -40,10 +40,10 @@ externalproject_add(cafe CMAKE_CACHE_ARGS -DDEVKITPPC:string=${DEVKITPPC} -DWUT_ROOT:filepath=${WUT_ROOT} - -DWUT_RPLGEN:filepath=$ + -DWUT_RPLIMPORTGEN:filepath=$ -DCMAKE_TOOLCHAIN_FILE:filepath=${WUT_TOOLCHAIN} -DCMAKE_INSTALL_PREFIX:string= - DEPENDS rplgen + DEPENDS rplimportgen BUILD_ALWAYS 1) externalproject_add(libraries diff --git a/cafe/CMakeLists.txt b/cafe/CMakeLists.txt index a7547ec..f3b6b86 100644 --- a/cafe/CMakeLists.txt +++ b/cafe/CMakeLists.txt @@ -5,7 +5,7 @@ enable_language(ASM) macro(add_cafe_library target) add_custom_command( OUTPUT ${target}.s - COMMAND ${WUT_RPLGEN} ${CMAKE_CURRENT_SOURCE_DIR}/${target}/exports.def ${target}.s + COMMAND ${WUT_RPLIMPORTGEN} ${CMAKE_CURRENT_SOURCE_DIR}/${target}/exports.def ${target}.s DEPENDS ${target}/exports.def) add_library(${target} STATIC ${target}.s) diff --git a/share/wut.cmake b/share/wut.cmake index 2fe9612..54c5d1e 100644 --- a/share/wut.cmake +++ b/share/wut.cmake @@ -21,9 +21,24 @@ macro(wut_enable_stdcpp target) LINK_FLAGS " -Wl,--whole-archive -lwutstdc++ -Wl,--no-whole-archive") endmacro(wut_enable_stdcpp) +macro(wut_add_exports target exports_file) + set(RPL_EXPORTS_FILE ${exports_file}) + if(NOT IS_ABSOLUTE ${exports_file}) + set(RPL_EXPORTS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${exports_file}") + endif() + + add_custom_command( + OUTPUT rpl_exports.s + COMMAND ${WUT_RPLEXPORTGEN} ${RPL_EXPORTS_FILE} rpl_exports.s + DEPENDS ${RPL_EXPORTS_FILE}) + target_sources(${target} PRIVATE rpl_exports.s) + + set_source_files_properties(rpl_exports.s PROPERTIES LANGUAGE C) +endmacro(wut_add_exports) + function(wut_create_rpl target source) set(RPL_OPTIONS IS_RPX) - set(RPL_SINGLE_ARGS EXPORTS_FILE) + set(RPL_SINGLE_ARGS "") set(RPL_MULTI_ARGS "") cmake_parse_arguments(RPL "${RPL_OPTIONS}" "${RPL_SINGLE_ARGS}" "${RPL_MULTI_ARGS}" "${ARGN}") @@ -31,14 +46,6 @@ function(wut_create_rpl target source) set(ELF2RPL_FLAGS ${ELF2RPL_FLAGS} --rpl) endif() - if(RPL_EXPORTS_FILE) - if(NOT IS_ABSOLUTE ${RPL_EXPORTS_FILE}) - set(RPL_EXPORTS_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${RPL_EXPORTS_FILE}") - endif() - - set(ELF2RPL_FLAGS ${ELF2RPL_FLAGS} --exports ${RPL_EXPORTS_FILE}) - endif() - target_link_libraries(${source} wutcrt coreinit) diff --git a/share/wut.ld b/share/wut.ld index c76359a..fea0e0b 100644 --- a/share/wut.ld +++ b/share/wut.ld @@ -151,6 +151,13 @@ SECTIONS } > relmem . = ORIGIN(loadmem); + .fexports ALIGN(32) : { + *(.fexports) + } > loadmem + .dexports ALIGN(32) : { + *(.dexports) + } > loadmem + .fimport_coreinit ALIGN(16) : { *(.fimport_coreinit) } > loadmem diff --git a/share/wut.toolchain.cmake b/share/wut.toolchain.cmake index 3325127..816f365 100644 --- a/share/wut.toolchain.cmake +++ b/share/wut.toolchain.cmake @@ -41,6 +41,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) # Tools set(WUT_ELF2RPL "${WUT_ROOT}/bin/elf2rpl${CMAKE_EXECUTABLE_SUFFIX}" CACHE PATH "") +set(WUT_RPLEXPORTGEN "${WUT_ROOT}/bin/rplexportgen${CMAKE_EXECUTABLE_SUFFIX}" CACHE PATH "") # Flags set(WUT TRUE) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index c75ea28..275a0c5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -13,5 +13,6 @@ add_subdirectory(libraries) include_directories(common) add_subdirectory(elf2rpl) add_subdirectory(readrpl) -add_subdirectory(rplgen) +add_subdirectory(rplimportgen) +add_subdirectory(rplexportgen) add_subdirectory(udplogserver) diff --git a/tools/rplexportgen/CMakeLists.txt b/tools/rplexportgen/CMakeLists.txt new file mode 100644 index 0000000..ddb89ef --- /dev/null +++ b/tools/rplexportgen/CMakeLists.txt @@ -0,0 +1,9 @@ +project(rplexportgen) + +add_executable(rplexportgen + rplexportgen.cpp) + +target_link_libraries(rplexportgen + zlib) + +install(TARGETS rplexportgen RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") diff --git a/tools/rplexportgen/rplexportgen.cpp b/tools/rplexportgen/rplexportgen.cpp new file mode 100644 index 0000000..897eb1a --- /dev/null +++ b/tools/rplexportgen/rplexportgen.cpp @@ -0,0 +1,166 @@ +#include "utils.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* +.extern __preinit_user + +.section .fexports, "", @0x80000001 +.align 4 + +.long 1 +.long 0x13371337 + +.long __preinit_user +.long 0x10 + +.string "__preinit_user" +.byte 0 + */ + +enum class ReadMode +{ + INVALID, + TEXT, + DATA +}; + +void +writeExports(std::ofstream &out, + bool isData, + const std::vector &exports) +{ + // Calculate signature + uint32_t signature = crc32(0, Z_NULL, 0); + for (const auto &name : exports) { + signature = crc32(signature, reinterpret_cast(name.data()), name.size() + 1); + } + + // Write out .extern to declare the symbols + for (const auto &name : exports) { + out << ".extern " << name << std::endl; + } + out << std::endl; + + // Write out header + if (isData) { + out << ".section .dexports, \"a\", @0x80000001" << std::endl; + } else { + out << ".section .fexports, \"ax\", @0x80000001" << std::endl; + } + + out << ".align 4" << std::endl; + out << std::endl; + + out << ".long " << exports.size() << std::endl; + out << ".long 0x" << std::hex << signature << std::endl; + out << std::endl; + + // Write out each export + auto nameOffset = 8 + 8 * exports.size(); + for (const auto &name : exports) { + out << ".long " << name << std::endl; + out << ".long 0x" << std::hex << nameOffset << std::endl; + nameOffset += name.size() + 1; + } + out << std::endl; + + // Write out the strings + for (const auto &name : exports) { + out << ".string \"" << name << "\"" << std::endl; + out << ".byte 0" << std::endl; + nameOffset += name.size() + 1; + } + out << std::endl; +} + +int main(int argc, char **argv) +{ + std::vector funcExports, dataExports; + ReadMode readMode = ReadMode::INVALID; + + if (argc < 3) { + std::cout << argv[0] << " " << std::endl; + return 0; + } + + { + std::ifstream in; + in.open(argv[1]); + + if (!in.is_open()) { + std::cout << "Could not open file " << argv[1] << " for reading" << std::endl; + return -1; + } + + std::string line; + while (std::getline(in, line)) { + // Trim comments + std::size_t commentOffset = line.find("//"); + if (commentOffset != std::string::npos) { + line = line.substr(0, commentOffset); + } + + // Trim whitespace + line = trim(line); + + // Skip blank lines + if (line.length() == 0) { + continue; + } + + // Look for section headers + if (line[0] == ':') { + if (line.substr(1) == "TEXT") { + readMode = ReadMode::TEXT; + } else if (line.substr(1) == "DATA") { + readMode = ReadMode::DATA; + } else { + std::cout << "Unexpected section type" << std::endl; + return -1; + } + continue; + } + + if (readMode == ReadMode::TEXT) { + funcExports.push_back(line); + } else if (readMode == ReadMode::DATA) { + dataExports.push_back(line); + } else { + std::cout << "Unexpected section data" << std::endl; + return -1; + } + } + } + + { + std::ofstream out; + out.open(argv[2]); + + if (!out.is_open()) { + std::cout << "Could not open file " << argv[2] << " for writing" << std::endl; + return -1; + } + + if (funcExports.size() > 0) { + writeExports(out, false, funcExports); + } + + if (dataExports.size() > 0) { + writeExports(out, true, dataExports); + } + } + + return 0; +} diff --git a/tools/rplgen/CMakeLists.txt b/tools/rplgen/CMakeLists.txt deleted file mode 100644 index 243b173..0000000 --- a/tools/rplgen/CMakeLists.txt +++ /dev/null @@ -1,12 +0,0 @@ -project(rplgen) - -file(GLOB_RECURSE SOURCE_FILES *.cpp) -file(GLOB_RECURSE HEADER_FILES *.h) - -add_executable(rplgen - ${SOURCE_FILES} ${HEADER_FILES}) - -target_link_libraries(rplgen - zlib) - -install(TARGETS rplgen RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") diff --git a/tools/rplimportgen/CMakeLists.txt b/tools/rplimportgen/CMakeLists.txt new file mode 100644 index 0000000..1969666 --- /dev/null +++ b/tools/rplimportgen/CMakeLists.txt @@ -0,0 +1,9 @@ +project(rplimportgen) + +add_executable(rplimportgen + rplimportgen.cpp) + +target_link_libraries(rplimportgen + zlib) + +install(TARGETS rplimportgen RUNTIME DESTINATION "${CMAKE_INSTALL_PREFIX}/bin") diff --git a/tools/rplgen/rplgen.cpp b/tools/rplimportgen/rplimportgen.cpp similarity index 100% rename from tools/rplgen/rplgen.cpp rename to tools/rplimportgen/rplimportgen.cpp