mirror of
https://github.com/wiiu-env/wut.git
synced 2025-01-23 19:21:12 +01:00
tools: Add rplexportgen to produce SHT_RPL_EXPORTS.
This commit is contained in:
parent
c98c7e39e4
commit
61a84c50b6
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
|
9
tools/rplexportgen/CMakeLists.txt
Normal file
9
tools/rplexportgen/CMakeLists.txt
Normal 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")
|
166
tools/rplexportgen/rplexportgen.cpp
Normal file
166
tools/rplexportgen/rplexportgen.cpp
Normal 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;
|
||||||
|
}
|
@ -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")
|
|
9
tools/rplimportgen/CMakeLists.txt
Normal file
9
tools/rplimportgen/CMakeLists.txt
Normal 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")
|
Loading…
x
Reference in New Issue
Block a user