summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAmlal <amlal@nekernel.org>2025-08-12 15:25:04 +0200
committerAmlal <amlal@nekernel.org>2025-08-12 15:25:04 +0200
commita2d091a55cdc465a4f90181f2b404bdd062dbad6 (patch)
tree9c62d0c14aafb6ee4f520bfc7cbef00816ea200e
parentb77d1d0a876b845d98c8828da27b2d828378138f (diff)
feat: Linker test and improvements to the linker.
Signed-off-by: Amlal <amlal@nekernel.org>
-rw-r--r--dev/CompilerKit/ck-posix.json4
-rw-r--r--dev/CompilerKit/src/Linker/DynamicLinker64PEF.cc23
-rw-r--r--tests/test_02_linker/CMakeLists.txt23
-rw-r--r--tests/test_02_linker/linker_test.cc24
-rw-r--r--tests/test_02_linker/sample/sample.cc3
-rw-r--r--tests/test_02_linker/sample/sample.cc.pp3
6 files changed, 71 insertions, 9 deletions
diff --git a/dev/CompilerKit/ck-posix.json b/dev/CompilerKit/ck-posix.json
index e80ce65..e3ff231 100644
--- a/dev/CompilerKit/ck-posix.json
+++ b/dev/CompilerKit/ck-posix.json
@@ -11,7 +11,7 @@
"src/*.cc",
"src/*/*.cc"
],
- "output_name": "/usr/local/lib/libCompilerKit.so",
+ "output_name": "/usr/lib/libCompilerKit.so",
"compiler_flags": [
"-fPIC",
"-shared"
@@ -21,4 +21,4 @@
"CK_USE_STRUCTS=1",
"kDistReleaseBranch=$(git rev-parse --abbrev-ref HEAD)-$(uuidgen)"
]
-} \ No newline at end of file
+}
diff --git a/dev/CompilerKit/src/Linker/DynamicLinker64PEF.cc b/dev/CompilerKit/src/Linker/DynamicLinker64PEF.cc
index 6c8ca95..917b592 100644
--- a/dev/CompilerKit/src/Linker/DynamicLinker64PEF.cc
+++ b/dev/CompilerKit/src/Linker/DynamicLinker64PEF.cc
@@ -62,6 +62,8 @@ static Bool kDuplicateSymbols = false;
static const Char* kLdDefineSymbol = ":UndefinedSymbol:";
static const Char* kLdDynamicSym = ":RuntimeSymbol:";
+static CompilerKit::STLString kLinkerStart = kPefStart;
+
/* object code and list. */
static std::vector<CompilerKit::STLString> kObjectList;
static std::vector<Detail::DynamicLinkerBlob> kObjectBytes;
@@ -71,7 +73,7 @@ static std::vector<Detail::DynamicLinkerBlob> kObjectBytes;
NECTI_MODULE(DynamicLinker64PEF) {
bool is_executable = true;
- ::signal(SIGSEGV, Detail::drvi_crash_handler);
+ CompilerKit::install_signal(SIGSEGV, Detail::drvi_crash_handler);
/**
* @brief parse flags and trigger options.
@@ -110,6 +112,13 @@ NECTI_MODULE(DynamicLinker64PEF) {
kArch = CompilerKit::kPefArchAMD64;
continue;
+ } else if (std::strcmp(argv[linker_arg], "-start") == 0) {
+ if (argv[linker_arg + 1] == nullptr || argv[linker_arg][0] == '-') continue;
+
+ kLinkerStart = argv[linker_arg + 1];
+ linker_arg += 2;
+
+ continue;
} else if (std::strcmp(argv[linker_arg], "-32k") == 0) {
kArch = CompilerKit::kPefArch32000;
@@ -284,7 +293,7 @@ NECTI_MODULE(DynamicLinker64PEF) {
if (cmd_hdr_name.find(kPefCode64) == CompilerKit::STLString::npos &&
cmd_hdr_name.find(kPefData64) == CompilerKit::STLString::npos &&
cmd_hdr_name.find(kPefZero64) == CompilerKit::STLString::npos) {
- if (cmd_hdr_name.find(kPefStart) == CompilerKit::STLString::npos &&
+ if (cmd_hdr_name.find(kLinkerStart) == CompilerKit::STLString::npos &&
*command_header.Name == 0) {
if (cmd_hdr_name.find(kLdDefineSymbol) != CompilerKit::STLString::npos) {
goto ld_mark_header;
@@ -294,7 +303,7 @@ NECTI_MODULE(DynamicLinker64PEF) {
}
}
- if (cmd_hdr_name.find(kPefStart) != CompilerKit::STLString::npos &&
+ if (cmd_hdr_name.find(kLinkerStart) != CompilerKit::STLString::npos &&
cmd_hdr_name.find(kPefCode64) != CompilerKit::STLString::npos) {
kStartFound = true;
}
@@ -422,11 +431,11 @@ NECTI_MODULE(DynamicLinker64PEF) {
if (!kStartFound && is_executable) {
if (kVerbose)
- kConsoleOut << "Undefined entrypoint: " << kPefStart
+ kConsoleOut << "Undefined entrypoint: " << kLinkerStart
<< ", you may have forget to link "
"against the C++ runtime library.\n";
- kConsoleOut << "Undefined entrypoint " << kPefStart << " for executable: " << kOutput << "\n";
+ kConsoleOut << "Undefined entrypoint " << kLinkerStart << " for executable: " << kOutput << "\n";
}
// step 4: write all PEF commands.
@@ -560,9 +569,9 @@ NECTI_MODULE(DynamicLinker64PEF) {
CompilerKit::STLString name = command_headers[commandHeaderIndex].Name;
/// so this is valid when we get to the entrypoint.
- /// it is always a code64 container. And should equal to kPefStart as well.
+ /// it is always a code64 container. And should equal to kLinkerStart as well.
/// this chunk of code updates the pef_container.Start with the updated offset.
- if (name.find(kPefStart) != CompilerKit::STLString::npos &&
+ if (name.find(kLinkerStart) != CompilerKit::STLString::npos &&
name.find(kPefCode64) != CompilerKit::STLString::npos) {
pef_container.Start = command_headers[commandHeaderIndex].Offset;
auto tellCurPos = output_fc.tellp();
diff --git a/tests/test_02_linker/CMakeLists.txt b/tests/test_02_linker/CMakeLists.txt
new file mode 100644
index 0000000..f3493fc
--- /dev/null
+++ b/tests/test_02_linker/CMakeLists.txt
@@ -0,0 +1,23 @@
+cmake_minimum_required(VERSION 3.10)
+project(NeCTILinkerTest)
+
+include(FetchContent)
+FetchContent_Declare(
+ googletest
+ URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip
+)
+
+# For Windows: Prevent overriding the parent project's compiler/linker settings
+set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
+FetchContent_MakeAvailable(googletest)
+
+enable_testing()
+
+add_executable(LinkerTestBasic linker_test.cc)
+target_link_libraries(LinkerTestBasic gtest_main)
+
+set_property(TARGET LinkerTestBasic PROPERTY CXX_STANDARD 20)
+target_include_directories(LinkerTestBasic PUBLIC ../../)
+
+include(GoogleTest)
+gtest_discover_tests(LinkerTestBasic)
diff --git a/tests/test_02_linker/linker_test.cc b/tests/test_02_linker/linker_test.cc
new file mode 100644
index 0000000..88d51de
--- /dev/null
+++ b/tests/test_02_linker/linker_test.cc
@@ -0,0 +1,24 @@
+/* -------------------------------------------
+
+ Copyright (C) 2024-2025 Amlal EL Mahrouss, all rights reserved
+
+ ------------------------------------------- */
+
+
+/// @brief Linker Unit test, from the C++ unit to the final executable.
+/// @author Amlal El Mahrouss
+
+#include <gtest/gtest.h>
+
+TEST(LinkerTest, BasicLinkTest)
+{
+ /// @note this is the driver, it will look for a .cc.pp (.pp stands for pre-processed)
+ auto expr = std::system("pef-amd64-cxxdrv sample/sample.cc");
+ EXPECT_TRUE(expr == 0) << "C++ Driver did not compile the easy C++ unit.";
+
+ expr = std::system("asm -asm:x64 sample/sample.cc.pp.masm");
+ EXPECT_TRUE(expr == 0) << "Assembler did not assemble the easy asm unit.";
+
+ expr = std::system("ld64 -fat-binary sample/sample.cc.pp.obj -start __NECTI_main -output main.exec");
+ EXPECT_TRUE(expr == 0) << "Linker did not link the easy object.";
+}
diff --git a/tests/test_02_linker/sample/sample.cc b/tests/test_02_linker/sample/sample.cc
new file mode 100644
index 0000000..4cce7f6
--- /dev/null
+++ b/tests/test_02_linker/sample/sample.cc
@@ -0,0 +1,3 @@
+int main() {
+ return 0;
+}
diff --git a/tests/test_02_linker/sample/sample.cc.pp b/tests/test_02_linker/sample/sample.cc.pp
new file mode 100644
index 0000000..cb3f748
--- /dev/null
+++ b/tests/test_02_linker/sample/sample.cc.pp
@@ -0,0 +1,3 @@
+int main() {
+ return 0;
+}