tools: Add rplexportgen to produce SHT_RPL_EXPORTS.

This commit is contained in:
James Benton 2018-05-30 18:54:41 +01:00
parent c98c7e39e4
commit 61a84c50b6
11 changed files with 213 additions and 25 deletions

View File

@ -40,10 +40,10 @@ externalproject_add(cafe
CMAKE_CACHE_ARGS CMAKE_CACHE_ARGS
-DDEVKITPPC:string=${DEVKITPPC} -DDEVKITPPC:string=${DEVKITPPC}
-DWUT_ROOT:filepath=${WUT_ROOT} -DWUT_ROOT:filepath=${WUT_ROOT}
-DWUT_RPLGEN:filepath=$<TARGET_FILE:rplgen> -DWUT_RPLIMPORTGEN:filepath=$<TARGET_FILE:rplimportgen>
-DCMAKE_TOOLCHAIN_FILE:filepath=${WUT_TOOLCHAIN} -DCMAKE_TOOLCHAIN_FILE:filepath=${WUT_TOOLCHAIN}
-DCMAKE_INSTALL_PREFIX:string=<INSTALL_DIR> -DCMAKE_INSTALL_PREFIX:string=<INSTALL_DIR>
DEPENDS rplgen DEPENDS rplimportgen
BUILD_ALWAYS 1) BUILD_ALWAYS 1)
externalproject_add(libraries externalproject_add(libraries

View File

@ -5,7 +5,7 @@ enable_language(ASM)
macro(add_cafe_library target) macro(add_cafe_library target)
add_custom_command( add_custom_command(
OUTPUT ${target}.s 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) DEPENDS ${target}/exports.def)
add_library(${target} STATIC ${target}.s) add_library(${target} STATIC ${target}.s)

View File

@ -21,9 +21,24 @@ macro(wut_enable_stdcpp target)
LINK_FLAGS " -Wl,--whole-archive -lwutstdc++ -Wl,--no-whole-archive") LINK_FLAGS " -Wl,--whole-archive -lwutstdc++ -Wl,--no-whole-archive")
endmacro(wut_enable_stdcpp) 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) function(wut_create_rpl target source)
set(RPL_OPTIONS IS_RPX) set(RPL_OPTIONS IS_RPX)
set(RPL_SINGLE_ARGS EXPORTS_FILE) set(RPL_SINGLE_ARGS "")
set(RPL_MULTI_ARGS "") set(RPL_MULTI_ARGS "")
cmake_parse_arguments(RPL "${RPL_OPTIONS}" "${RPL_SINGLE_ARGS}" "${RPL_MULTI_ARGS}" "${ARGN}") 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) set(ELF2RPL_FLAGS ${ELF2RPL_FLAGS} --rpl)
endif() 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} target_link_libraries(${source}
wutcrt wutcrt
coreinit) coreinit)

View File

@ -151,6 +151,13 @@ SECTIONS
} > relmem } > relmem
. = ORIGIN(loadmem); . = ORIGIN(loadmem);
.fexports ALIGN(32) : {
*(.fexports)
} > loadmem
.dexports ALIGN(32) : {
*(.dexports)
} > loadmem
.fimport_coreinit ALIGN(16) : { .fimport_coreinit ALIGN(16) : {
*(.fimport_coreinit) *(.fimport_coreinit)
} > loadmem } > loadmem

View File

@ -41,6 +41,7 @@ set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
# Tools # Tools
set(WUT_ELF2RPL "${WUT_ROOT}/bin/elf2rpl${CMAKE_EXECUTABLE_SUFFIX}" CACHE PATH "") 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 # Flags
set(WUT TRUE) set(WUT TRUE)

View File

@ -13,5 +13,6 @@ add_subdirectory(libraries)
include_directories(common) include_directories(common)
add_subdirectory(elf2rpl) add_subdirectory(elf2rpl)
add_subdirectory(readrpl) add_subdirectory(readrpl)
add_subdirectory(rplgen) add_subdirectory(rplimportgen)
add_subdirectory(rplexportgen)
add_subdirectory(udplogserver) add_subdirectory(udplogserver)

View File

@ -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")

View File

@ -0,0 +1,166 @@
#include "utils.h"
#include <array>
#include <algorithm>
#include <cctype>
#include <cstring>
#include <cstdint>
#include <iostream>
#include <functional>
#include <fstream>
#include <locale>
#include <vector>
#include <string>
#include <zlib.h>
/*
.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<std::string> &exports)
{
// Calculate signature
uint32_t signature = crc32(0, Z_NULL, 0);
for (const auto &name : exports) {
signature = crc32(signature, reinterpret_cast<const Bytef *>(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<std::string> funcExports, dataExports;
ReadMode readMode = ReadMode::INVALID;
if (argc < 3) {
std::cout << argv[0] << " <exports.def> <output.S>" << 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;
}

View File

@ -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")

View File

@ -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")