From ac2debcd00dd78ad77f58d0c448862b76619ea61 Mon Sep 17 00:00:00 2001 From: Amlal El Mahrouss Date: Thu, 9 Jan 2025 13:12:48 +0100 Subject: ADD: Minor improvements and refactors. Signed-off-by: Amlal El Mahrouss --- dev/LibCompiler/src/Assembler64x0.cc | 54 +- dev/LibCompiler/src/AssemblerAMD64.cc | 58 +- dev/LibCompiler/src/AssemblerARM64.cc | 26 +- dev/LibCompiler/src/AssemblerPower.cc | 44 +- dev/LibCompiler/src/CCompiler64x0.cc | 30 +- dev/LibCompiler/src/CCompilerARM64.cc | 30 +- dev/LibCompiler/src/CCompilerPower64.cc | 30 +- dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc | 30 +- .../src/CPlusPlusCompilerPreProcessor.cc | 48 +- dev/LibCompiler/src/CPlusPlusLinkerELF.cc | 92 --- dev/LibCompiler/src/CPlusPlusLinkerPEF.cc | 774 --------------------- dev/LibCompiler/src/Detail/AsmUtils.h | 12 +- dev/LibCompiler/src/DynamicLinkerELF.cc | 85 +++ dev/LibCompiler/src/DynamicLinkerPEF.cc | 774 +++++++++++++++++++++ 14 files changed, 1040 insertions(+), 1047 deletions(-) delete mode 100644 dev/LibCompiler/src/CPlusPlusLinkerELF.cc delete mode 100644 dev/LibCompiler/src/CPlusPlusLinkerPEF.cc create mode 100644 dev/LibCompiler/src/DynamicLinkerELF.cc create mode 100644 dev/LibCompiler/src/DynamicLinkerPEF.cc (limited to 'dev/LibCompiler/src') diff --git a/dev/LibCompiler/src/Assembler64x0.cc b/dev/LibCompiler/src/Assembler64x0.cc index b04d50f..a0cb734 100644 --- a/dev/LibCompiler/src/Assembler64x0.cc +++ b/dev/LibCompiler/src/Assembler64x0.cc @@ -72,7 +72,7 @@ static const std::string kRelocSymbol = ":RuntimeSymbol:"; // \brief forward decl. static bool asm_read_attributes(std::string& line); -namespace Details +namespace Detail { void print_error(std::string reason, std::string file) noexcept { @@ -103,7 +103,7 @@ namespace Details kStdOut << kYellow << "[ TQC++ ] " << kWhite << reason << kBlank << std::endl; } -} // namespace Details +} // namespace Detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -201,7 +201,7 @@ LIBCOMPILER_MODULE(AssemblerMain64x0) { if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { - Details::print_error(ln, argv[i]); + Detail::print_error(ln, argv[i]); continue; } @@ -215,7 +215,7 @@ LIBCOMPILER_MODULE(AssemblerMain64x0) if (kVerbose) { std::string what = e.what(); - Details::print_warning("exit because of: " + what, "LibCompiler"); + Detail::print_warning("exit because of: " + what, "LibCompiler"); } std::filesystem::remove(object_output); @@ -347,7 +347,7 @@ static bool asm_read_attributes(std::string& line) { if (kOutputAsBinary) { - Details::print_error("Invalid extern_segment directive in flat binary mode.", + Detail::print_error("Invalid extern_segment directive in flat binary mode.", "LibCompiler"); throw std::runtime_error("invalid_extern_segment_bin"); } @@ -357,7 +357,7 @@ static bool asm_read_attributes(std::string& line) /// sanity check to avoid stupid linker errors. if (name.size() == 0) { - Details::print_error("Invalid extern_segment", "power-as"); + Detail::print_error("Invalid extern_segment", "power-as"); throw std::runtime_error("invalid_extern_segment"); } @@ -420,7 +420,7 @@ static bool asm_read_attributes(std::string& line) { if (kOutputAsBinary) { - Details::print_error("Invalid public_segment directive in flat binary mode.", + Detail::print_error("Invalid public_segment directive in flat binary mode.", "LibCompiler"); throw std::runtime_error("invalid_public_segment_bin"); } @@ -493,7 +493,7 @@ static bool asm_read_attributes(std::string& line) // \brief algorithms and helpers. -namespace Details::algorithm +namespace Detail::algorithm { // \brief authorize a brief set of characters. static inline bool is_not_alnum_space(char c) @@ -508,7 +508,7 @@ namespace Details::algorithm { return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); } -} // namespace Details::algorithm +} // namespace Detail::algorithm ///////////////////////////////////////////////////////////////////////////////////////// @@ -536,7 +536,7 @@ std::string LibCompiler::Encoder64x0::CheckLine(std::string& line, else { // now check the line for validity - if (!Details::algorithm::is_valid_64x0(line)) + if (!Detail::algorithm::is_valid_64x0(line)) { err_str = "Line contains non alphanumeric characters.\nhere -> "; err_str += line; @@ -546,7 +546,7 @@ std::string LibCompiler::Encoder64x0::CheckLine(std::string& line, return err_str; } - if (!Details::algorithm::is_valid_64x0(line)) + if (!Detail::algorithm::is_valid_64x0(line)) { err_str = "Line contains non alphanumeric characters.\nhere -> "; err_str += line; @@ -664,7 +664,7 @@ bool LibCompiler::Encoder64x0::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid hex number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid hex number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_hex_number"); } } @@ -691,7 +691,7 @@ bool LibCompiler::Encoder64x0::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid binary number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid binary number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_bin"); } } @@ -718,7 +718,7 @@ bool LibCompiler::Encoder64x0::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid octal number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid octal number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_octal"); } } @@ -786,7 +786,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, { // strict check here if (LibCompiler::find_word(line, opcode64x0.fName) && - Details::algorithm::is_valid_64x0(line)) + Detail::algorithm::is_valid_64x0(line)) { std::string name(opcode64x0.fName); std::string jump_label, cpy_jump_label; @@ -830,7 +830,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, isdigit(line[line_index + 2])) { reg_str += line[line_index + 3]; - Details::print_error( + Detail::print_error( "invalid register index, r" + reg_str + "\nnote: The 64x0 accepts registers from r0 to r20.", file); @@ -843,7 +843,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, if (reg_index > kAsmRegisterLimit) { - Details::print_error("invalid register index, r" + reg_str, + Detail::print_error("invalid register index, r" + reg_str, file); throw std::runtime_error("invalid_register_index"); } @@ -866,7 +866,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, // remember! register to register! if (found_some == 1) { - Details::print_error( + Detail::print_error( "Too few registers.\ntip: each Assembler64x0 register " "starts with 'r'.\nline: " + line, @@ -878,21 +878,21 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, if (found_some < 1 && name != "ldw" && name != "lda" && name != "stw") { - Details::print_error( + Detail::print_error( "invalid combination of opcode and registers.\nline: " + line, file); throw std::runtime_error("invalid_comb_op_reg"); } else if (found_some == 1 && name == "add") { - Details::print_error( + Detail::print_error( "invalid combination of opcode and registers.\nline: " + line, file); throw std::runtime_error("invalid_comb_op_reg"); } else if (found_some == 1 && name == "sub") { - Details::print_error( + Detail::print_error( "invalid combination of opcode and registers.\nline: " + line, file); throw std::runtime_error("invalid_comb_op_reg"); @@ -900,7 +900,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, if (found_some > 0 && name == "pop") { - Details::print_error( + Detail::print_error( "invalid combination for opcode 'pop'.\ntip: it expects " "nothing.\nline: " + line, @@ -941,7 +941,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, { if (found_sym) { - Details::print_error( + Detail::print_error( "invalid combination of opcode and operands.\nhere -> " + jump_label, file); @@ -974,7 +974,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, // sta expects this: sta 0x000000, r0 if (name == "sta") { - Details::print_error( + Detail::print_error( "invalid combination of opcode and operands.\nHere ->" + line, file); throw std::runtime_error("invalid_comb_op_ops"); @@ -985,7 +985,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, if (name == "sta" && cpy_jump_label.find("extern_segment ") != std::string::npos) { - Details::print_error("invalid usage extern_segment on 'sta', here: " + line, + Detail::print_error("invalid usage extern_segment on 'sta', here: " + line, file); throw std::runtime_error("invalid_sta_usage"); } @@ -1007,7 +1007,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, if (name == "sta") { - Details::print_error("extern_segment is not allowed on a sta operation.", + Detail::print_error("extern_segment is not allowed on a sta operation.", file); throw std::runtime_error("extern_segment_sta_op"); } @@ -1067,7 +1067,7 @@ bool LibCompiler::Encoder64x0::WriteLine(std::string& line, if (cpy_jump_label.size() < 1) { - Details::print_error("label is empty, can't jump on it.", file); + Detail::print_error("label is empty, can't jump on it.", file); throw std::runtime_error("label_empty"); } diff --git a/dev/LibCompiler/src/AssemblerAMD64.cc b/dev/LibCompiler/src/AssemblerAMD64.cc index 330931e..0ec8c3e 100644 --- a/dev/LibCompiler/src/AssemblerAMD64.cc +++ b/dev/LibCompiler/src/AssemblerAMD64.cc @@ -230,7 +230,7 @@ LIBCOMPILER_MODULE(AssemblerMainAMD64) { if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { - Details::print_error(ln, argv[i]); + Detail::print_error(ln, argv[i]); continue; } @@ -244,7 +244,7 @@ LIBCOMPILER_MODULE(AssemblerMainAMD64) if (kVerbose) { std::string what = e.what(); - Details::print_warning("exit because of: " + what, "LibCompiler"); + Detail::print_warning("exit because of: " + what, "LibCompiler"); } try @@ -391,7 +391,7 @@ static bool asm_read_attributes(std::string& line) { if (kOutputAsBinary) { - Details::print_error("Invalid directive in flat binary mode.", "LibCompiler"); + Detail::print_error("Invalid directive in flat binary mode.", "LibCompiler"); throw std::runtime_error("invalid_extern_segment_bin"); } @@ -399,7 +399,7 @@ static bool asm_read_attributes(std::string& line) if (name.size() == 0) { - Details::print_error("Invalid extern_segment", "power-as"); + Detail::print_error("Invalid extern_segment", "power-as"); throw std::runtime_error("invalid_extern_segment"); } @@ -462,7 +462,7 @@ static bool asm_read_attributes(std::string& line) { if (kOutputAsBinary) { - Details::print_error("Invalid directive in flat binary mode.", "LibCompiler"); + Detail::print_error("Invalid directive in flat binary mode.", "LibCompiler"); throw std::runtime_error("invalid_public_segment_bin"); } @@ -479,7 +479,7 @@ static bool asm_read_attributes(std::string& line) if (std::find(kDefinedSymbols.begin(), kDefinedSymbols.end(), name) != kDefinedSymbols.end()) { - Details::print_error("Symbol already defined.", "LibCompiler"); + Detail::print_error("Symbol already defined.", "LibCompiler"); throw std::runtime_error("invalid_public_segment_bin"); } @@ -543,7 +543,7 @@ static bool asm_read_attributes(std::string& line) // \brief algorithms and helpers. -namespace Details::algorithm +namespace Detail::algorithm { // \brief authorize a brief set of characters. static inline bool is_not_valid(char c) @@ -561,7 +561,7 @@ namespace Details::algorithm { return std::find_if(str.begin(), str.end(), is_not_valid) == str.end(); } -} // namespace Details::algorithm +} // namespace Detail::algorithm ///////////////////////////////////////////////////////////////////////////////////////// @@ -586,7 +586,7 @@ std::string LibCompiler::EncoderAMD64::CheckLine(std::string& line, else { // now check the line for validity - if (!Details::algorithm::is_valid_amd64(line)) + if (!Detail::algorithm::is_valid_amd64(line)) { err_str = "Line contains non valid characters.\nhere -> "; err_str += line; @@ -666,7 +666,7 @@ bool LibCompiler::EncoderAMD64::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid hex number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid hex number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_hex"); } } @@ -696,7 +696,7 @@ bool LibCompiler::EncoderAMD64::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid binary number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid binary number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_bin"); } } @@ -726,7 +726,7 @@ bool LibCompiler::EncoderAMD64::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid octal number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid octal number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_octal"); } } @@ -919,7 +919,7 @@ bool LibCompiler::EncoderAMD64::WriteNumber16(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid hex number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid hex number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_hex"); } } @@ -949,7 +949,7 @@ bool LibCompiler::EncoderAMD64::WriteNumber16(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid binary number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid binary number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_bin"); } } @@ -979,7 +979,7 @@ bool LibCompiler::EncoderAMD64::WriteNumber16(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid octal number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid octal number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_octal"); } } @@ -1051,7 +1051,7 @@ bool LibCompiler::EncoderAMD64::WriteNumber8(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid hex number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid hex number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_hex"); } } @@ -1075,7 +1075,7 @@ bool LibCompiler::EncoderAMD64::WriteNumber8(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid binary number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid binary number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_bin"); } } @@ -1099,7 +1099,7 @@ bool LibCompiler::EncoderAMD64::WriteNumber8(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid octal number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid octal number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_octal"); } } @@ -1187,7 +1187,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, { // strict check here if (LibCompiler::find_word(line, opcodeAMD64.fName) && - Details::algorithm::is_valid_amd64(line)) + Detail::algorithm::is_valid_amd64(line)) { foundInstruction = true; std::string name(opcodeAMD64.fName); @@ -1202,7 +1202,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, if (substr.find(",") == std::string::npos) { - Details::print_error("Syntax error: missing right operand.", "LibCompiler"); + Detail::print_error("Syntax error: missing right operand.", "LibCompiler"); throw std::runtime_error("syntax_err"); } @@ -1231,7 +1231,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, { if (registerName[0] == 'r') { - Details::print_error( + Detail::print_error( "invalid size for register, current bit width is: " + std::to_string(kRegisterBitWidth), file); @@ -1286,7 +1286,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, { if (hasRBasedRegs) { - Details::print_error( + Detail::print_error( "Invalid combination of operands and registers.", "LibCompiler"); throw std::runtime_error("comb_op_reg"); } @@ -1323,7 +1323,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, if (currentRegList[1].fName[0] == 'r' && currentRegList[0].fName[0] == 'e') { - Details::print_error("Invalid combination of operands and registers.", + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); throw std::runtime_error("comb_op_reg"); } @@ -1331,7 +1331,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, if (currentRegList[0].fName[0] == 'r' && currentRegList[1].fName[0] == 'e') { - Details::print_error("Invalid combination of operands and registers.", + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); throw std::runtime_error("comb_op_reg"); } @@ -1341,7 +1341,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, if (currentRegList[0].fName[0] == 'r' || currentRegList[0].fName[0] == 'e') { - Details::print_error("Invalid combination of operands and registers.", + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); throw std::runtime_error("comb_op_reg"); } @@ -1349,7 +1349,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, if (currentRegList[1].fName[0] == 'r' || currentRegList[1].fName[0] == 'e') { - Details::print_error("Invalid combination of operands and registers.", + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); throw std::runtime_error("comb_op_reg"); } @@ -1359,7 +1359,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, if (currentRegList[0].fName[0] != 'r' || currentRegList[0].fName[0] == 'e') { - Details::print_error("Invalid combination of operands and registers.", + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); throw std::runtime_error("comb_op_reg"); } @@ -1367,7 +1367,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, if (currentRegList[1].fName[0] != 'r' || currentRegList[1].fName[0] == 'e') { - Details::print_error("Invalid combination of operands and registers.", + Detail::print_error("Invalid combination of operands and registers.", "LibCompiler"); throw std::runtime_error("comb_op_reg"); } @@ -1413,7 +1413,7 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string& line, { if (foundInstruction) { - Details::print_error("Syntax error: " + line, "LibCompiler"); + Detail::print_error("Syntax error: " + line, "LibCompiler"); throw std::runtime_error("syntax_err"); } diff --git a/dev/LibCompiler/src/AssemblerARM64.cc b/dev/LibCompiler/src/AssemblerARM64.cc index 1429f58..0fef663 100644 --- a/dev/LibCompiler/src/AssemblerARM64.cc +++ b/dev/LibCompiler/src/AssemblerARM64.cc @@ -171,7 +171,7 @@ LIBCOMPILER_MODULE(AssemblerMainARM64) { if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { - Details::print_error(ln, argv[i]); + Detail::print_error(ln, argv[i]); continue; } @@ -185,7 +185,7 @@ LIBCOMPILER_MODULE(AssemblerMainARM64) if (kVerbose) { std::string what = e.what(); - Details::print_warning("exit because of: " + what, "LibCompiler"); + Detail::print_warning("exit because of: " + what, "LibCompiler"); } std::filesystem::remove(object_output); @@ -317,7 +317,7 @@ static bool asm_read_attributes(std::string& line) { if (kOutputAsBinary) { - Details::print_error("Invalid extern_segment directive in flat binary mode.", + Detail::print_error("Invalid extern_segment directive in flat binary mode.", "LibCompiler"); throw std::runtime_error("invalid_extern_segment_bin"); } @@ -326,7 +326,7 @@ static bool asm_read_attributes(std::string& line) if (name.size() == 0) { - Details::print_error("Invalid extern_segment", "LibCompiler"); + Detail::print_error("Invalid extern_segment", "LibCompiler"); throw std::runtime_error("invalid_extern_segment"); } @@ -389,7 +389,7 @@ static bool asm_read_attributes(std::string& line) { if (kOutputAsBinary) { - Details::print_error("Invalid public_segment directive in flat binary mode.", + Detail::print_error("Invalid public_segment directive in flat binary mode.", "LibCompiler"); throw std::runtime_error("invalid_public_segment_bin"); } @@ -462,7 +462,7 @@ static bool asm_read_attributes(std::string& line) // \brief algorithms and helpers. -namespace Details::algorithm +namespace Detail::algorithm { // \brief authorize a brief set of characters. static inline bool is_not_alnum_space(char c) @@ -477,7 +477,7 @@ namespace Details::algorithm { return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); } -} // namespace Details::algorithm +} // namespace Detail::algorithm ///////////////////////////////////////////////////////////////////////////////////////// @@ -505,7 +505,7 @@ std::string LibCompiler::EncoderARM64::CheckLine(std::string& line, else { /// does the line contains valid input? - if (!Details::algorithm::is_valid_arm64(line)) + if (!Detail::algorithm::is_valid_arm64(line)) { err_str = "Line contains non alphanumeric characters.\nhere -> "; err_str += line; @@ -515,7 +515,7 @@ std::string LibCompiler::EncoderARM64::CheckLine(std::string& line, return err_str; } - if (!Details::algorithm::is_valid_arm64(line)) + if (!Detail::algorithm::is_valid_arm64(line)) { err_str = "Line contains non alphanumeric characters.\nhere -> "; err_str += line; @@ -584,7 +584,7 @@ bool LibCompiler::EncoderARM64::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid hex number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid hex number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_hex"); } } @@ -611,7 +611,7 @@ bool LibCompiler::EncoderARM64::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid binary number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid binary number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_bin"); } } @@ -638,7 +638,7 @@ bool LibCompiler::EncoderARM64::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid octal number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid octal number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_octal"); } } @@ -702,7 +702,7 @@ bool LibCompiler::EncoderARM64::WriteLine(std::string& line, if (LibCompiler::find_word(line, "public_segment")) return false; - if (!Details::algorithm::is_valid_arm64(line)) + if (!Detail::algorithm::is_valid_arm64(line)) return false; diff --git a/dev/LibCompiler/src/AssemblerPower.cc b/dev/LibCompiler/src/AssemblerPower.cc index a98e3e8..e2bc76d 100644 --- a/dev/LibCompiler/src/AssemblerPower.cc +++ b/dev/LibCompiler/src/AssemblerPower.cc @@ -171,7 +171,7 @@ LIBCOMPILER_MODULE(AssemblerMainPower64) { if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { - Details::print_error(ln, argv[i]); + Detail::print_error(ln, argv[i]); continue; } @@ -185,7 +185,7 @@ LIBCOMPILER_MODULE(AssemblerMainPower64) if (kVerbose) { std::string what = e.what(); - Details::print_warning("exit because of: " + what, "LibCompiler"); + Detail::print_warning("exit because of: " + what, "LibCompiler"); } std::filesystem::remove(object_output); @@ -317,7 +317,7 @@ static bool asm_read_attributes(std::string& line) { if (kOutputAsBinary) { - Details::print_error("Invalid extern_segment directive in flat binary mode.", + Detail::print_error("Invalid extern_segment directive in flat binary mode.", "LibCompiler"); throw std::runtime_error("invalid_extern_segment_bin"); } @@ -326,7 +326,7 @@ static bool asm_read_attributes(std::string& line) if (name.size() == 0) { - Details::print_error("Invalid extern_segment", "LibCompiler"); + Detail::print_error("Invalid extern_segment", "LibCompiler"); throw std::runtime_error("invalid_extern_segment"); } @@ -389,7 +389,7 @@ static bool asm_read_attributes(std::string& line) { if (kOutputAsBinary) { - Details::print_error("Invalid public_segment directive in flat binary mode.", + Detail::print_error("Invalid public_segment directive in flat binary mode.", "LibCompiler"); throw std::runtime_error("invalid_public_segment_bin"); } @@ -462,7 +462,7 @@ static bool asm_read_attributes(std::string& line) // \brief algorithms and helpers. -namespace Details::algorithm +namespace Detail::algorithm { // \brief authorize a brief set of characters. static inline bool is_not_alnum_space(char c) @@ -477,7 +477,7 @@ namespace Details::algorithm { return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); } -} // namespace Details::algorithm +} // namespace Detail::algorithm ///////////////////////////////////////////////////////////////////////////////////////// @@ -505,7 +505,7 @@ std::string LibCompiler::EncoderPowerPC::CheckLine(std::string& line, else { /// does the line contains valid input? - if (!Details::algorithm::is_valid_power64(line)) + if (!Detail::algorithm::is_valid_power64(line)) { err_str = "Line contains non alphanumeric characters.\nhere -> "; err_str += line; @@ -515,7 +515,7 @@ std::string LibCompiler::EncoderPowerPC::CheckLine(std::string& line, return err_str; } - if (!Details::algorithm::is_valid_power64(line)) + if (!Detail::algorithm::is_valid_power64(line)) { err_str = "Line contains non alphanumeric characters.\nhere -> "; err_str += line; @@ -630,7 +630,7 @@ bool LibCompiler::EncoderPowerPC::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid hex number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid hex number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_hex"); } } @@ -657,7 +657,7 @@ bool LibCompiler::EncoderPowerPC::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid binary number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid binary number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_bin"); } } @@ -684,7 +684,7 @@ bool LibCompiler::EncoderPowerPC::WriteNumber(const std::size_t& pos, { if (errno != 0) { - Details::print_error("invalid octal number: " + jump_label, "LibCompiler"); + Detail::print_error("invalid octal number: " + jump_label, "LibCompiler"); throw std::runtime_error("invalid_octal"); } } @@ -747,7 +747,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, { if (LibCompiler::find_word(line, "public_segment")) return false; - if (!Details::algorithm::is_valid_power64(line)) + if (!Detail::algorithm::is_valid_power64(line)) return false; for (auto& opcode_risc : kOpcodesPowerPC) @@ -820,7 +820,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, isdigit(line[line_index + 2])) { reg_str += line[line_index + 3]; - Details::print_error( + Detail::print_error( "invalid register index, r" + reg_str + "\nnote: The POWER accepts registers from r0 to r32.", file); @@ -832,7 +832,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, if (reg_index > kAsmRegisterLimit) { - Details::print_error("invalid register index, r" + reg_str, + Detail::print_error("invalid register index, r" + reg_str, file); throw std::runtime_error("invalid_register_index"); } @@ -858,7 +858,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, { if (num.number[i] > 0) { - Details::print_warning("number overflow on li operation.", + Detail::print_warning("number overflow on li operation.", file); break; } @@ -948,7 +948,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, if (found_some_count > 3) { - Details::print_error("Too much registers. -> " + line, file); + Detail::print_error("Too much registers. -> " + line, file); throw std::runtime_error("too_much_regs"); } } @@ -959,7 +959,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, if (found_some_count > 3) { - Details::print_error("Too much registers. -> " + line, file); + Detail::print_error("Too much registers. -> " + line, file); throw std::runtime_error("too_much_regs"); } } @@ -980,7 +980,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, if (found_some_count > 1) { - Details::print_error("Too much registers. -> " + line, file); + Detail::print_error("Too much registers. -> " + line, file); throw std::runtime_error("too_much_regs"); } @@ -1052,7 +1052,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, { if (register_count == 1) { - Details::print_error("Too few registers. -> " + line, file); + Detail::print_error("Too few registers. -> " + line, file); throw std::runtime_error("too_few_registers"); } } @@ -1063,7 +1063,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, // remember! register to register! if (found_some_count == 1) { - Details::print_error( + Detail::print_error( "Unrecognized register found.\ntip: each AssemblerPower register " "starts with 'r'.\nline: " + line, @@ -1075,7 +1075,7 @@ bool LibCompiler::EncoderPowerPC::WriteLine(std::string& line, if (found_some_count < 1 && name[0] != 'l' && name[0] != 's') { - Details::print_error( + Detail::print_error( "invalid combination of opcode and registers.\nline: " + line, file); throw std::runtime_error("invalid_comb_op_reg"); diff --git a/dev/LibCompiler/src/CCompiler64x0.cc b/dev/LibCompiler/src/CCompiler64x0.cc index 23bd11a..fee8f08 100644 --- a/dev/LibCompiler/src/CCompiler64x0.cc +++ b/dev/LibCompiler/src/CCompiler64x0.cc @@ -50,7 +50,7 @@ ///////////////////////////////////// -namespace Details +namespace Detail { // \brief Register map structure, used to keep track of each variable's registers. struct CompilerRegisterMap final @@ -87,14 +87,14 @@ namespace Details std::string fLastError; bool fVerbose; }; -} // namespace Details +} // namespace Detail -static Details::CompilerState kState; +static Detail::CompilerState kState; static SizeType kErrorLimit = 100; static std::string kIfFunction = ""; static Int32 kAcceptableErrors = 0; -namespace Details +namespace Detail { /// @brief prints an error into stdout. /// @param reason the reason of the error. @@ -106,7 +106,7 @@ namespace Details std::string fName; std::string fValue; }; -} // namespace Details +} // namespace Detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -159,11 +159,11 @@ public: }; static CompilerFrontend64x0* kCompilerFrontend = nullptr; -static std::vector kCompilerVariables; +static std::vector kCompilerVariables; static std::vector kCompilerFunctions; -static std::vector kCompilerTypes; +static std::vector kCompilerTypes; -namespace Details +namespace Detail { union number_cast final { public: @@ -191,7 +191,7 @@ namespace Details float _Raw; }; -} // namespace Details +} // namespace Detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -223,7 +223,7 @@ bool CompilerFrontend64x0::Compile(std::string text_, const std::string file) auto gen = uuids::uuid_random_generator{generator}; uuids::uuid out = gen(); - Details::number_cast time_off = (UInt64)out.as_bytes().data(); + Detail::number_cast time_off = (UInt64)out.as_bytes().data(); if (!typeFound) { @@ -402,7 +402,7 @@ bool CompilerFrontend64x0::Compile(std::string text_, const std::string file) if (text[text_index] == '=' && kInStruct) { - Details::print_error("assignement of value in struct " + text, + Detail::print_error("assignement of value in struct " + text, file); continue; } @@ -565,7 +565,7 @@ bool CompilerFrontend64x0::Compile(std::string text_, const std::string file) auto var_to_find = std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), - [&](Details::CompilerType type) { + [&](Detail::CompilerType type) { return type.fName.find(substr) != std::string::npos; }); @@ -1360,7 +1360,7 @@ public: } else { - Details::print_error(err, src.data()); + Detail::print_error(err, src.data()); } } @@ -1567,7 +1567,7 @@ LIBCOMPILER_MODULE(ZkaOSCompilerCLang64x0) std::string err = "Unknown command: "; err += argv[index]; - Details::print_error(err, "cc"); + Detail::print_error(err, "cc"); continue; } @@ -1580,7 +1580,7 @@ LIBCOMPILER_MODULE(ZkaOSCompilerCLang64x0) { if (kState.fVerbose) { - Details::print_error(srcFile + " is not a valid C source.\n", "cc"); + Detail::print_error(srcFile + " is not a valid C source.\n", "cc"); } return 1; diff --git a/dev/LibCompiler/src/CCompilerARM64.cc b/dev/LibCompiler/src/CCompilerARM64.cc index 476596d..1f48311 100644 --- a/dev/LibCompiler/src/CCompilerARM64.cc +++ b/dev/LibCompiler/src/CCompilerARM64.cc @@ -50,7 +50,7 @@ ///////////////////////////////////// -namespace Details +namespace Detail { // \brief Register map structure, used to keep track of each variable's registers. struct CompilerRegisterMap final @@ -87,14 +87,14 @@ namespace Details std::string fLastError; bool fVerbose; }; -} // namespace Details +} // namespace Detail -static Details::CompilerState kState; +static Detail::CompilerState kState; static SizeType kErrorLimit = 100; static std::string kIfFunction = ""; static Int32 kAcceptableErrors = 0; -namespace Details +namespace Detail { /// @brief prints an error into stdout. /// @param reason the reason of the error. @@ -106,7 +106,7 @@ namespace Details std::string fName; std::string fValue; }; -} // namespace Details +} // namespace Detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -159,11 +159,11 @@ public: }; static CompilerFrontendARM64* kCompilerFrontend = nullptr; -static std::vector kCompilerVariables; +static std::vector kCompilerVariables; static std::vector kCompilerFunctions; -static std::vector kCompilerTypes; +static std::vector kCompilerTypes; -namespace Details +namespace Detail { union number_cast final { public: @@ -191,7 +191,7 @@ namespace Details float _Raw; }; -} // namespace Details +} // namespace Detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -221,7 +221,7 @@ bool CompilerFrontendARM64::Compile(std::string text, const std::string file) auto gen = uuids::uuid_random_generator{generator}; uuids::uuid out = gen(); - Details::number_cast time_off = (UInt64)out.as_bytes().data(); + Detail::number_cast time_off = (UInt64)out.as_bytes().data(); if (!typeFound) { @@ -400,7 +400,7 @@ bool CompilerFrontendARM64::Compile(std::string text, const std::string file) if (text[text_index] == '=' && kInStruct) { - Details::print_error("assignement of value in struct " + text, + Detail::print_error("assignement of value in struct " + text, file); continue; } @@ -563,7 +563,7 @@ bool CompilerFrontendARM64::Compile(std::string text, const std::string file) auto var_to_find = std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), - [&](Details::CompilerType type) { + [&](Detail::CompilerType type) { return type.fName.find(substr) != std::string::npos; }); @@ -1358,7 +1358,7 @@ public: } else { - Details::print_error(err, src.data()); + Detail::print_error(err, src.data()); } } @@ -1565,7 +1565,7 @@ LIBCOMPILER_MODULE(ZkaOSCompilerCLangARM64) std::string err = "Unknown command: "; err += argv[index]; - Details::print_error(err, "cc"); + Detail::print_error(err, "cc"); continue; } @@ -1578,7 +1578,7 @@ LIBCOMPILER_MODULE(ZkaOSCompilerCLangARM64) { if (kState.fVerbose) { - Details::print_error(srcFile + " is not a valid C source.\n", "cc"); + Detail::print_error(srcFile + " is not a valid C source.\n", "cc"); } return 1; diff --git a/dev/LibCompiler/src/CCompilerPower64.cc b/dev/LibCompiler/src/CCompilerPower64.cc index 4338c68..9ef1646 100644 --- a/dev/LibCompiler/src/CCompilerPower64.cc +++ b/dev/LibCompiler/src/CCompilerPower64.cc @@ -41,7 +41,7 @@ ///////////////////////////////////// -namespace Details +namespace Detail { // \brief name to register struct. struct CompilerRegisterMap final @@ -78,14 +78,14 @@ namespace Details std::string fLastError; bool fVerbose; }; -} // namespace Details +} // namespace Detail -static Details::CompilerState kState; +static Detail::CompilerState kState; static SizeType kErrorLimit = 100; static std::string kIfFunction = ""; static Int32 kAcceptableErrors = 0; -namespace Details +namespace Detail { /// @brief prints an error into stdout. /// @param reason the reason of the error. @@ -97,7 +97,7 @@ namespace Details std::string fName; std::string fValue; }; -} // namespace Details +} // namespace Detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -150,11 +150,11 @@ public: }; static CompilerFrontendPower64* kCompilerFrontend = nullptr; -static std::vector kCompilerVariables; +static std::vector kCompilerVariables; static std::vector kCompilerFunctions; -static std::vector kCompilerTypes; +static std::vector kCompilerTypes; -namespace Details +namespace Detail { union number_cast final { public: @@ -182,7 +182,7 @@ namespace Details float _Raw; }; -} // namespace Details +} // namespace Detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -214,7 +214,7 @@ bool CompilerFrontendPower64::Compile(std::string text_, const std::string file) auto gen = uuids::uuid_random_generator{generator}; uuids::uuid out = gen(); - Details::number_cast time_off = (UInt64)out.as_bytes().data(); + Detail::number_cast time_off = (UInt64)out.as_bytes().data(); if (!typeFound) { @@ -413,7 +413,7 @@ bool CompilerFrontendPower64::Compile(std::string text_, const std::string file) if (text[text_index] == '=' && kInStruct) { - Details::print_error( + Detail::print_error( "assignement of value inside a struct " + text, file); continue; } @@ -576,7 +576,7 @@ bool CompilerFrontendPower64::Compile(std::string text_, const std::string file) auto var_to_find = std::find_if(kCompilerVariables.cbegin(), kCompilerVariables.cend(), - [&](Details::CompilerType type) { + [&](Detail::CompilerType type) { return type.fName.find(substr) != std::string::npos; }); @@ -1383,7 +1383,7 @@ public: } else { - Details::print_error(err, src.data()); + Detail::print_error(err, src.data()); } } @@ -1587,7 +1587,7 @@ LIBCOMPILER_MODULE(ZkaOSCompilerCLangPowerPC) std::string err = "Unknown command: "; err += argv[index]; - Details::print_error(err, "cc"); + Detail::print_error(err, "cc"); continue; } @@ -1600,7 +1600,7 @@ LIBCOMPILER_MODULE(ZkaOSCompilerCLangPowerPC) { if (kState.fVerbose) { - Details::print_error(srcFile + " is not a valid C source.\n", "cc"); + Detail::print_error(srcFile + " is not a valid C source.\n", "cc"); } return 1; diff --git a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc index e2b66f2..7a85c24 100644 --- a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc +++ b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc @@ -52,7 +52,7 @@ ///////////////////////////////////// /// @internal -namespace Details +namespace Detail { std::filesystem::path expand_home(const std::filesystem::path& p) { @@ -104,14 +104,14 @@ namespace Details std::string fLastError; bool fVerbose; }; -} // namespace Details +} // namespace Detail -static Details::CompilerState kState; +static Detail::CompilerState kState; static SizeType kErrorLimit = 100; static Int32 kAcceptableErrors = 0; -namespace Details +namespace Detail { /// @brief prints an error into stdout. /// @param reason the reason of the error. @@ -123,7 +123,7 @@ namespace Details std::string fName; std::string fValue; }; -} // namespace Details +} // namespace Detail ///////////////////////////////////////////////////////////////////////////////////////// @@ -278,7 +278,7 @@ bool CompilerFrontendCPlusPlus::Compile(const std::string text, { if (isalnum(text[i])) { - Details::print_error("syntax error: " + text, file); + Detail::print_error("syntax error: " + text, file); return false; } } @@ -413,7 +413,7 @@ bool CompilerFrontendCPlusPlus::Compile(const std::string text, if (text.ends_with(";")) goto tk_write_assembly; else if (text.size() <= indexFnName) - Details::print_error("Invalid function name: " + fnName, file); + Detail::print_error("Invalid function name: " + fnName, file); indexFnName = 0; @@ -423,10 +423,10 @@ bool CompilerFrontendCPlusPlus::Compile(const std::string text, ch == '\t') { if (fnName[indexFnName - 1] != ')') - Details::print_error("Invalid function name: " + fnName, file); + Detail::print_error("Invalid function name: " + fnName, file); if ((indexFnName + 1) != fnName.size()) - Details::print_error("Extra characters after function name: " + fnName, file); + Detail::print_error("Extra characters after function name: " + fnName, file); } ++indexFnName; @@ -611,7 +611,7 @@ tk_write_assembly: goto done; } - Details::print_error("Variable not declared: " + varName, file); + Detail::print_error("Variable not declared: " + varName, file); return false; } @@ -727,7 +727,7 @@ tk_write_assembly: if (syntax_tree.fUserValue.empty()) { - Details::print_error("Variable not declared: " + varErrCpy, file); + Detail::print_error("Variable not declared: " + varErrCpy, file); } break; @@ -758,7 +758,7 @@ tk_write_assembly: if (syntax_tree.fUserValue.empty()) { - Details::print_error("Variable not declared: " + subText, file); + Detail::print_error("Variable not declared: " + subText, file); } } else @@ -857,7 +857,7 @@ public: std::filesystem::path path = std::filesystem::path("./"); - while (path != Details::expand_home(std::filesystem::path("~"))) + while (path != Detail::expand_home(std::filesystem::path("~"))) { for (auto const& dir_entry : std::filesystem::recursive_directory_iterator{path}) { @@ -1048,7 +1048,7 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusX8664) std::string err = "Unknown option: "; err += argv[index]; - Details::print_error(err, "c++-drv"); + Detail::print_error(err, "c++-drv"); continue; } @@ -1073,7 +1073,7 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusX8664) { if (kState.fVerbose) { - Details::print_error(argv_i + " is not a valid C++ source.\n", "c++-drv"); + Detail::print_error(argv_i + " is not a valid C++ source.\n", "c++-drv"); } return 1; diff --git a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc b/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc index 90db68b..713405b 100644 --- a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc +++ b/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc @@ -32,7 +32,7 @@ typedef Int32 (*bpp_parser_fn_t)(std::string& line, std::ifstream& hdr_file, std ///////////////////////////////////////////////////////////////////////////////////////// -namespace Details +namespace Detail { enum { @@ -79,10 +79,10 @@ namespace Details std::string fMacroName; bpp_parser_fn_t fParse; }; -} // namespace Details +} // namespace Detail static std::vector kFiles; -static std::vector kMacros; +static std::vector kMacros; static std::vector kIncludes; static std::string kWorkingDir; @@ -100,13 +100,13 @@ static std::vector kKeywords = { ///////////////////////////////////////////////////////////////////////////////////////// -int32_t bpp_parse_if_condition(Details::bpp_macro_condition& cond, - Details::bpp_macro& macro, +int32_t bpp_parse_if_condition(Detail::bpp_macro_condition& cond, + Detail::bpp_macro& macro, bool& inactive_code, bool& defined, std::string& macro_str) { - if (cond.fType == Details::kEqual) + if (cond.fType == Detail::kEqual) { auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); @@ -127,7 +127,7 @@ int32_t bpp_parse_if_condition(Details::bpp_macro_condition& cond, return 1; } } - else if (cond.fType == Details::kNotEqual) + else if (cond.fType == Detail::kNotEqual) { auto substr_macro = macro_str.substr(macro_str.find(macro.fName) + macro.fName.size()); @@ -223,7 +223,7 @@ int32_t bpp_parse_if_condition(Details::bpp_macro_condition& cond, lhs = atol(number.c_str()); } - if (cond.fType == Details::kGreaterThan) + if (cond.fType == Detail::kGreaterThan) { if (lhs < rhs) { @@ -236,7 +236,7 @@ int32_t bpp_parse_if_condition(Details::bpp_macro_condition& cond, return 0; } - if (cond.fType == Details::kGreaterEqThan) + if (cond.fType == Detail::kGreaterEqThan) { if (lhs <= rhs) { @@ -249,7 +249,7 @@ int32_t bpp_parse_if_condition(Details::bpp_macro_condition& cond, return 0; } - if (cond.fType == Details::kLesserEqThan) + if (cond.fType == Detail::kLesserEqThan) { if (lhs >= rhs) { @@ -262,7 +262,7 @@ int32_t bpp_parse_if_condition(Details::bpp_macro_condition& cond, return 0; } - if (cond.fType == Details::kLesserThan) + if (cond.fType == Detail::kLesserThan) { if (lhs > rhs) { @@ -516,7 +516,7 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) } } - Details::bpp_macro macro; + Detail::bpp_macro macro; macro.fArgs = args; macro.fName = macro_key; @@ -663,29 +663,29 @@ void bpp_parse_file(std::ifstream& hdr_file, std::ofstream& pp_out) { inactive_code = true; - std::vector bpp_macro_condition_list = { + std::vector bpp_macro_condition_list = { { - .fType = Details::kEqual, + .fType = Detail::kEqual, .fTypeName = "==", }, { - .fType = Details::kNotEqual, + .fType = Detail::kNotEqual, .fTypeName = "!=", }, { - .fType = Details::kLesserThan, + .fType = Detail::kLesserThan, .fTypeName = "<", }, { - .fType = Details::kGreaterThan, + .fType = Detail::kGreaterThan, .fTypeName = ">", }, { - .fType = Details::kLesserEqThan, + .fType = Detail::kLesserEqThan, .fTypeName = "<=", }, { - .fType = Details::kGreaterEqThan, + .fType = Detail::kGreaterEqThan, .fTypeName = ">=", }, }; @@ -915,28 +915,28 @@ LIBCOMPILER_MODULE(CPlusPlusPreprocessorMain) bool skip = false; bool double_skip = false; - Details::bpp_macro macro_1; + Detail::bpp_macro macro_1; macro_1.fName = "__true"; macro_1.fValue = "1"; kMacros.push_back(macro_1); - Details::bpp_macro macro_0; + Detail::bpp_macro macro_0; macro_0.fName = "__false"; macro_0.fValue = "0"; kMacros.push_back(macro_0); - Details::bpp_macro macro_zka; + Detail::bpp_macro macro_zka; macro_zka.fName = "__LIBCOMPILER__"; macro_zka.fValue = "1"; kMacros.push_back(macro_zka); - Details::bpp_macro macro_size_t; + Detail::bpp_macro macro_size_t; macro_size_t.fName = "__SIZE_TYPE__"; macro_size_t.fValue = "unsigned long long int"; @@ -1028,7 +1028,7 @@ LIBCOMPILER_MODULE(CPlusPlusPreprocessorMain) if (is_string) macro_value += "\""; - Details::bpp_macro macro; + Detail::bpp_macro macro; macro.fName = macro_key; macro.fValue = macro_value; diff --git a/dev/LibCompiler/src/CPlusPlusLinkerELF.cc b/dev/LibCompiler/src/CPlusPlusLinkerELF.cc deleted file mode 100644 index de7cbd1..0000000 --- a/dev/LibCompiler/src/CPlusPlusLinkerELF.cc +++ /dev/null @@ -1,92 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024 Theater Quality Corp, all rights reserved - - @file DynamicLinker64PEF.cc - @brief: C++ 64-Bit PEF Linker. - -------------------------------------------- */ - -/// @author EL Mahrouss Amlal (amlel) -/// @brief TQ 64-bit PEF Linker. -/// Last Rev: Sat Feb 24 CET 2024 -/// @note Do not look up for anything with .code64/.data64/.zero64! -/// It will be loaded when the program loader will start the image. - -//! Toolchain Kit. -#include - -#include - -//! Assembler Kit -#include - -//! Preferred Executable Format -#include -#include - -//! Release macros. -#include - -//! Advanced Executable Object Format. -#include -#include - -#define kLinkerVersionStr "TQ 64-Bit Linker (ELF) %s, (c) Theater Quality Corp. 2024, all rights reserved.\n" - -#define MemoryCopy(DST, SRC, SZ) memcpy(DST, SRC, SZ) -#define StringCompare(DST, SRC) strcmp(DST, SRC) - -#define kPefNoCpu 0U -#define kPefNoSubCpu 0U - -#define kWhite "\e[0;97m" - -#define kStdOut (std::cout << kWhite << "ld64: ") - -#define kLinkerDefaultOrigin kPefBaseOrigin -#define kLinkerId (0x5046FF) -#define kLinkerAbiContainer "Container:ABI:" - -/// @brief PEF stack size symbol. -#define kLinkerStackSizeSymbol "SizeOfReserveStack" - -namespace Details -{ -struct DynamicLinkerBlob final -{ - std::vector mBlob; // PEF code/bss/data blob. - std::uintptr_t mObjOffset; // the offset of the PEF container header.. -}; -} - -enum -{ - kABITypeStart = 0x1010, /* Invalid ABI start of ABI list. */ - kABITypeZKA = 0x5046, /* PF (ZKA PEF ABI) */ - kABITypeInvalid = 0xFFFF, -}; - -static Bool kFatBinaryEnable = false; -static Bool kStartFound = false; -static Bool kDuplicateSymbols = false; -static Bool kVerbose = false; - -/* object code and list. */ -static std::vector kObjectList; -static std::vector kObjectBytes; - -static uintptr_t kMIBCount = 8; -static uintptr_t kByteCount = 1024; - -#define kPrintF printf -#define kLinkerSplash() kPrintF(kWhite kLinkerVersionStr, kDistVersion) - -/// @brief ZKA 64-bit Linker. -/// @note This linker is made for XCOFF executable, thus ZKA based OSes. -LIBCOMPILER_MODULE(DynamicLinker64XCOFF) -{ - return EXIT_SUCCESS; -} - -// Last rev 13-1-24 diff --git a/dev/LibCompiler/src/CPlusPlusLinkerPEF.cc b/dev/LibCompiler/src/CPlusPlusLinkerPEF.cc deleted file mode 100644 index a7abc92..0000000 --- a/dev/LibCompiler/src/CPlusPlusLinkerPEF.cc +++ /dev/null @@ -1,774 +0,0 @@ -/* ------------------------------------------- - - Copyright (C) 2024 Theater Quality Corp, all rights reserved - - @file DynamicLinker64PEF.cc - @brief: C++ 64-Bit PEF Linker. - -------------------------------------------- */ - -/// @author EL Mahrouss Amlal (amlel) -/// @brief TQ 64-bit PEF Linker. -/// Last Rev: Sat Feb 24 CET 2024 -/// @note Do not look up for anything with .code64/.data64/.zero64! -/// It will be loaded when the program loader will start the image. - -//! Toolchain Kit. -#include - -#include - -//! Assembler Kit -#include - -//! Preferred Executable Format -#include -#include - -//! Release macros. -#include - -//! Advanced Executable Object Format. -#include -#include - -#define kLinkerVersionStr "TQ 64-Bit Linker (Preferred Executable) %s, (c) Theater Quality Corp. 2024, all rights reserved.\n" - -#define MemoryCopy(DST, SRC, SZ) memcpy(DST, SRC, SZ) -#define StringCompare(DST, SRC) strcmp(DST, SRC) - -#define kPefNoCpu 0U -#define kPefNoSubCpu 0U - -#define kWhite "\e[0;97m" - -#define kStdOut (std::cout << kWhite << "ld64: ") - -#define kLinkerDefaultOrigin kPefBaseOrigin -#define kLinkerId (0x5046FF) -#define kLinkerAbiContainer "Container:ABI:" - -/// @brief PEF stack size symbol. -#define kLinkerStackSizeSymbol "SizeOfReserveStack" - -namespace Details -{ -struct DynamicLinkerBlob final -{ - std::vector mBlob; // PEF code/bss/data blob. - std::uintptr_t mObjOffset; // the offset of the PEF container header.. -}; -} - -enum -{ - kABITypeStart = 0x1010, /* Invalid ABI start of ABI list. */ - kABITypeZKA = 0x5046, /* PF (ZKA PEF ABI) */ - kABITypeInvalid = 0xFFFF, -}; - -static LibCompiler::String kOutput = ""; -static Int32 kAbi = kABITypeZKA; -static Int32 kSubArch = kPefNoSubCpu; -static Int32 kArch = LibCompiler::kPefArchInvalid; -static Bool kFatBinaryEnable = false; -static Bool kStartFound = false; -static Bool kDuplicateSymbols = false; -static Bool kVerbose = false; - -/* ld64 is to be found, mld is to be found at runtime. */ -static const char* kLdDefineSymbol = ":UndefinedSymbol:"; -static const char* kLdDynamicSym = ":RuntimeSymbol:"; - -/* object code and list. */ -static std::vector kObjectList; -static std::vector kObjectBytes; - -static uintptr_t kMIBCount = 8; -static uintptr_t kByteCount = 1024; - -#define kPrintF printf -#define kLinkerSplash() kPrintF(kWhite kLinkerVersionStr, kDistVersion) - -/// @brief ZKA 64-bit Linker. -/// @note This linker is made for PEF executable, thus ZKA based OSes. -LIBCOMPILER_MODULE(DynamicLinker64PEF) -{ - bool is_executable = true; - - /** - * @brief parse flags and trigger options. - */ - for (size_t linker_arg = 1; linker_arg < argc; ++linker_arg) - { - if (StringCompare(argv[linker_arg], "--ld64:help") == 0) - { - kLinkerSplash(); - - kStdOut << "--ld64:ver: Show linker version.\n"; - kStdOut << "--ld64:?: Show linker help.\n"; - kStdOut << "--ld64:verbose: Enable linker trace.\n"; - kStdOut << "--ld64:dylib: Output as a Dylib PEF.\n"; - kStdOut << "--ld64:fat: Output as a FAT PEF.\n"; - kStdOut << "--ld64:32k: Output as a 32x0 PEF.\n"; - kStdOut << "--ld64:64k: Output as a 64x0 PEF.\n"; - kStdOut << "--ld64:amd64: Output as a AMD64 PEF.\n"; - kStdOut << "--ld64:rv64: Output as a RISC-V PEF.\n"; - kStdOut << "--ld64:power64: Output as a POWER PEF.\n"; - kStdOut << "--ld64:arm64: Output as a ARM64 PEF.\n"; - kStdOut << "--ld64:output: Select the output file name.\n"; - - return EXIT_SUCCESS; - } - else if (StringCompare(argv[linker_arg], "--ld64:version") == 0) - { - kLinkerSplash(); - return EXIT_SUCCESS; - } - else if (StringCompare(argv[linker_arg], "--ld64:fat-binary") == 0) - { - kFatBinaryEnable = true; - - continue; - } - else if (StringCompare(argv[linker_arg], "--ld64:64k") == 0) - { - kArch = LibCompiler::kPefArch64000; - - continue; - } - else if (StringCompare(argv[linker_arg], "--ld64:amd64") == 0) - { - kArch = LibCompiler::kPefArchAMD64; - - continue; - } - else if (StringCompare(argv[linker_arg], "--ld64:32k") == 0) - { - kArch = LibCompiler::kPefArch32000; - - continue; - } - else if (StringCompare(argv[linker_arg], "--ld64:power64") == 0) - { - kArch = LibCompiler::kPefArchPowerPC; - - continue; - } - else if (StringCompare(argv[linker_arg], "--ld64:riscv64") == 0) - { - kArch = LibCompiler::kPefArchRISCV; - - continue; - } - else if (StringCompare(argv[linker_arg], "--ld64:arm64") == 0) - { - kArch = LibCompiler::kPefArchARM64; - - continue; - } - else if (StringCompare(argv[linker_arg], "--ld64:verbose") == 0) - { - kVerbose = true; - - continue; - } - else if (StringCompare(argv[linker_arg], "--ld64:dylib") == 0) - { - if (kOutput.empty()) - { - continue; - } - - if (kOutput.find(kPefExt) != LibCompiler::String::npos) - kOutput.erase(kOutput.find(kPefExt), strlen(kPefExt)); - - kOutput += kPefDylibExt; - - is_executable = false; - - continue; - } - else if (StringCompare(argv[linker_arg], "--ld64:output") == 0) - { - kOutput = argv[linker_arg + 1]; - ++linker_arg; - - continue; - } - else - { - if (argv[linker_arg][0] == '-') - { - kStdOut << "unknown flag: " << argv[linker_arg] << "\n"; - return EXIT_FAILURE; - } - - kObjectList.emplace_back(argv[linker_arg]); - - continue; - } - } - - if (kOutput.empty()) - { - kStdOut << "no output filename set." << std::endl; - return LIBCOMPILER_EXEC_ERROR; - } - - // sanity check. - if (kObjectList.empty()) - { - kStdOut << "no input files." << std::endl; - return LIBCOMPILER_EXEC_ERROR; - } - else - { - namespace fs = std::filesystem; - - // check for existing files, if they don't throw an error. - for (auto& obj : kObjectList) - { - if (!fs::exists(obj)) - { - // if filesystem doesn't find file - // -> throw error. - kStdOut << "no such file: " << obj << std::endl; - return LIBCOMPILER_EXEC_ERROR; - } - } - } - - // PEF expects a valid target architecture when outputing a binary. - if (kArch == 0) - { - kStdOut << "no target architecture set, can't continue." << std::endl; - return LIBCOMPILER_EXEC_ERROR; - } - - LibCompiler::PEFContainer pef_container{}; - - int32_t archs = kArch; - - pef_container.Count = 0UL; - pef_container.Kind = is_executable ? LibCompiler::kPefKindExec : LibCompiler::kPefKindDylib; - pef_container.SubCpu = kSubArch; - pef_container.Linker = kLinkerId; // Theater Quality Corp. Linker - pef_container.Abi = kAbi; // Multi-Processor UX ABI - pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; - pef_container.Magic[1] = kPefMagic[1]; - pef_container.Magic[2] = kPefMagic[kFatBinaryEnable ? 0 : 2]; - pef_container.Magic[3] = kPefMagic[3]; - pef_container.Version = kPefVersion; - - // specify the start address, can be 0x10000 - pef_container.Start = kLinkerDefaultOrigin; - pef_container.HdrSz = sizeof(LibCompiler::PEFContainer); - - std::ofstream output_fc(kOutput, std::ofstream::binary); - - if (output_fc.bad()) - { - if (kVerbose) - { - kStdOut << "error: " << strerror(errno) << "\n"; - } - - return LIBCOMPILER_FILE_NOT_FOUND; - } - - //! Read AE to convert as PEF. - - std::vector command_headers; - LibCompiler::Utils::AEReadableProtocol reader_protocol{}; - - for (const auto& objectFile : kObjectList) - { - if (!std::filesystem::exists(objectFile)) - continue; - - LibCompiler::AEHeader hdr{}; - - reader_protocol.FP = std::ifstream(objectFile, std::ifstream::binary); - reader_protocol.FP >> hdr; - - auto ae_header = hdr; - - if (ae_header.fMagic[0] == kAEMag0 && ae_header.fMagic[1] == kAEMag1 && - ae_header.fSize == sizeof(LibCompiler::AEHeader)) - { - if (ae_header.fArch != kArch) - { - if (kVerbose) - kStdOut << "info: is this a FAT binary? : "; - - if (!kFatBinaryEnable) - { - if (kVerbose) - kStdOut << "No.\n"; - - kStdOut << "error: object " << objectFile - << " is a different kind of architecture and output isn't " - "treated as a FAT binary." - << std::endl; - - return LIBCOMPILER_FAT_ERROR; - } - else - { - if (kVerbose) - { - kStdOut << "Architecture matches what we expect.\n"; - } - } - } - - // append arch type to archs varaible. - archs |= ae_header.fArch; - std::size_t cnt = ae_header.fCount; - - if (kVerbose) - kStdOut << "object header found, record count: " << cnt << "\n"; - - pef_container.Count = cnt; - - char_type* raw_ae_records = - new char_type[cnt * sizeof(LibCompiler::AERecordHeader)]; - - memset(raw_ae_records, 0, cnt * sizeof(LibCompiler::AERecordHeader)); - - auto* ae_records = reader_protocol.Read(raw_ae_records, cnt); - - for (size_t ae_record_index = 0; ae_record_index < cnt; - ++ae_record_index) - { - LibCompiler::PEFCommandHeader command_header{0}; - std::size_t offset_of_obj = ae_records[ae_record_index].fOffset; - - MemoryCopy(command_header.Name, ae_records[ae_record_index].fName, - kPefNameLen); - - LibCompiler::String cmd_hdr_name(command_header.Name); - - // check this header if it's any valid. - if (cmd_hdr_name.find(kPefCode64) == - LibCompiler::String::npos && - cmd_hdr_name.find(kPefData64) == - LibCompiler::String::npos && - cmd_hdr_name.find(kPefZero64) == - LibCompiler::String::npos) - { - if (cmd_hdr_name.find(kPefStart) == - LibCompiler::String::npos && - *command_header.Name == 0) - { - if (cmd_hdr_name.find(kLdDefineSymbol) != - LibCompiler::String::npos) - { - goto ld_mark_header; - } - else - { - continue; - } - } - } - - if (cmd_hdr_name.find(kPefStart) != - LibCompiler::String::npos && - cmd_hdr_name.find(kPefCode64) != - LibCompiler::String::npos) - { - kStartFound = true; - } - - ld_mark_header: - command_header.Offset = offset_of_obj; - command_header.Kind = ae_records[ae_record_index].fKind; - command_header.Size = ae_records[ae_record_index].fSize; - command_header.Cpu = ae_header.fArch; - command_header.SubCpu = ae_header.fSubArch; - - if (kVerbose) - { - kStdOut << "Record: " - << ae_records[ae_record_index].fName << " is marked.\n"; - - kStdOut << "Record offset: " << command_header.Offset << "\n"; - } - - command_headers.emplace_back(command_header); - } - - delete[] raw_ae_records; - - std::vector bytes; - bytes.resize(ae_header.fCodeSize); - - // TODO: Port this to NeFS. - - reader_protocol.FP.seekg(std::streamsize(ae_header.fStartCode)); - reader_protocol.FP.read(bytes.data(), std::streamsize(ae_header.fCodeSize)); - - for (auto& byte : bytes) - { - kObjectBytes.push_back({ .mBlob = bytes, .mObjOffset = ae_header.fStartCode }); - } - - reader_protocol.FP.close(); - - continue; - } - - kStdOut << "Not an object container: " << objectFile << std::endl; - // don't continue, it is a fatal error. - return LIBCOMPILER_EXEC_ERROR; - } - - pef_container.Cpu = archs; - - output_fc << pef_container; - - if (kVerbose) - { - kStdOut << "Wrote container header.\n"; - } - - output_fc.seekp(std::streamsize(pef_container.HdrSz)); - - std::vector not_found; - std::vector symbols; - - // step 2: check for errors (multiple symbols, undefined ones) - - for (auto& command_hdr : command_headers) - { - // check if this symbol needs to be resolved. - if (LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) != - LibCompiler::String::npos && - LibCompiler::String(command_hdr.Name).find(kLdDynamicSym) == LibCompiler::String::npos) - { - if (kVerbose) - kStdOut << "Found undefined symbol: " << command_hdr.Name << "\n"; - - if (auto it = std::find(not_found.begin(), not_found.end(), - LibCompiler::String(command_hdr.Name)); - it == not_found.end()) - { - not_found.emplace_back(command_hdr.Name); - } - } - - symbols.emplace_back(command_hdr.Name); - } - - // Now try to solve these symbols. - - for (size_t not_found_idx = 0; not_found_idx < command_headers.size(); - ++not_found_idx) - { - if (const auto it = std::find(not_found.begin(), not_found.end(), - LibCompiler::String(command_headers[not_found_idx].Name)); - it != not_found.end()) - { - LibCompiler::String symbol_imp = *it; - - if (symbol_imp.find(kLdDefineSymbol) == LibCompiler::String::npos) - continue; - - // erase the lookup prefix. - symbol_imp.erase( - 0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol)); - - // demangle everything. - while (symbol_imp.find('$') != LibCompiler::String::npos) - symbol_imp.erase(symbol_imp.find('$'), 1); - - // the reason we do is because, this may not match the symbol, and we need - // to look for other matching symbols. - for (auto& command_hdr : command_headers) - { - if (LibCompiler::String(command_hdr.Name).find(symbol_imp) != - LibCompiler::String::npos && - LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) == - LibCompiler::String::npos) - { - LibCompiler::String undefined_symbol = command_hdr.Name; - auto result_of_sym = - undefined_symbol.substr(undefined_symbol.find(symbol_imp)); - - for (int i = 0; result_of_sym[i] != 0; ++i) - { - if (result_of_sym[i] != symbol_imp[i]) - goto ld_continue_search; - } - - not_found.erase(it); - - if (kVerbose) - kStdOut << "found symbol: " << command_hdr.Name << "\n"; - - break; - } - } - - ld_continue_search: - continue; - } - } - - // step 3: check for errors (recheck if we have those symbols.) - - if (!kStartFound && is_executable) - { - if (kVerbose) - kStdOut - << "undefined entrypoint: " << kPefStart << ", you may have forget to ld64 " - "against your compiler's runtime library.\n"; - - kStdOut << "undefined entrypoint " << kPefStart - << " for executable: " << kOutput << "\n"; - } - - // step 4: write all PEF commands. - - LibCompiler::PEFCommandHeader date_cmd_hdr{}; - - time_t timestamp = time(nullptr); - - LibCompiler::String timeStampStr = "Container:BuildEpoch:"; - timeStampStr += std::to_string(timestamp); - - strncpy(date_cmd_hdr.Name, timeStampStr.c_str(), timeStampStr.size()); - - date_cmd_hdr.Flags = 0; - date_cmd_hdr.Kind = LibCompiler::kPefZero; - date_cmd_hdr.Offset = output_fc.tellp(); - date_cmd_hdr.Size = timeStampStr.size(); - - command_headers.push_back(date_cmd_hdr); - - LibCompiler::PEFCommandHeader abi_cmd_hdr{}; - - LibCompiler::String abi = kLinkerAbiContainer; - - switch (kArch) - { - case LibCompiler::kPefArchAMD64: { - abi += "MSFT"; - break; - } - case LibCompiler::kPefArchPowerPC: { - abi += "SYSV"; - break; - } - case LibCompiler::kPefArch32000: - case LibCompiler::kPefArch64000: { - abi += " ZWS"; - break; - } - default: { - abi += " IDK"; - break; - } - } - - MemoryCopy(abi_cmd_hdr.Name, abi.c_str(), abi.size()); - - abi_cmd_hdr.Size = abi.size(); - abi_cmd_hdr.Offset = output_fc.tellp(); - abi_cmd_hdr.Flags = 0; - abi_cmd_hdr.Kind = LibCompiler::kPefLinkerID; - - command_headers.push_back(abi_cmd_hdr); - - LibCompiler::PEFCommandHeader stack_cmd_hdr{0}; - - stack_cmd_hdr.Cpu = kArch; - stack_cmd_hdr.Flags = 0; - stack_cmd_hdr.Size = sizeof(uintptr_t); - stack_cmd_hdr.Offset = 0; - - MemoryCopy(stack_cmd_hdr.Name, kLinkerStackSizeSymbol, strlen(kLinkerStackSizeSymbol)); - - command_headers.push_back(stack_cmd_hdr); - - LibCompiler::PEFCommandHeader uuid_cmd_hdr{}; - - std::random_device rd; - - auto seedData = std::array{}; - std::generate(std::begin(seedData), std::end(seedData), std::ref(rd)); - std::seed_seq seq(std::begin(seedData), std::end(seedData)); - std::mt19937 generator(seq); - - auto gen = uuids::uuid_random_generator{generator}; - uuids::uuid id = gen(); - auto uuidStr = uuids::to_string(id); - - MemoryCopy(uuid_cmd_hdr.Name, "Container:GUID:4:", strlen("Container:GUID:4:")); - MemoryCopy(uuid_cmd_hdr.Name + strlen("Container:GUID:4:"), uuidStr.c_str(), - uuidStr.size()); - - uuid_cmd_hdr.Size = strlen(uuid_cmd_hdr.Name); - uuid_cmd_hdr.Offset = output_fc.tellp(); - uuid_cmd_hdr.Flags = LibCompiler::kPefLinkerID; - uuid_cmd_hdr.Kind = LibCompiler::kPefZero; - - command_headers.push_back(uuid_cmd_hdr); - - // prepare a symbol vector. - std::vector undef_symbols; - std::vector dupl_symbols; - std::vector resolve_symbols; - - constexpr Int32 cPaddingOffset = 16; - - size_t previous_offset = (command_headers.size() * sizeof(LibCompiler::PEFCommandHeader)) + cPaddingOffset; - - // Finally write down the command headers. - // And check for any duplications - for (size_t commandHeaderIndex = 0UL; - commandHeaderIndex < command_headers.size(); ++commandHeaderIndex) - { - if (LibCompiler::String(command_headers[commandHeaderIndex].Name) - .find(kLdDefineSymbol) != LibCompiler::String::npos && - LibCompiler::String(command_headers[commandHeaderIndex].Name) - .find(kLdDynamicSym) == LibCompiler::String::npos) - { - // ignore :UndefinedSymbol: headers, they do not contain code. - continue; - } - - LibCompiler::String symbol_name = command_headers[commandHeaderIndex].Name; - - if (!symbol_name.empty()) - { - undef_symbols.emplace_back(symbol_name); - } - - command_headers[commandHeaderIndex].Offset += previous_offset; - previous_offset += command_headers[commandHeaderIndex].Size; - - LibCompiler::String 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. - /// this chunk of code updates the pef_container.Start with the updated offset. - if (name.find(kPefStart) != LibCompiler::String::npos && - name.find(kPefCode64) != LibCompiler::String::npos) - { - pef_container.Start = command_headers[commandHeaderIndex].Offset; - auto tellCurPos = output_fc.tellp(); - - output_fc.seekp(0); - output_fc << pef_container; - - output_fc.seekp(tellCurPos); - } - - if (kVerbose) - { - kStdOut << "Command header name: " << name << "\n"; - kStdOut << "Real address of command header content: " << command_headers[commandHeaderIndex].Offset << "\n"; - } - - output_fc << command_headers[commandHeaderIndex]; - - for (size_t sub_command_header_index = 0UL; - sub_command_header_index < command_headers.size(); - ++sub_command_header_index) - { - if (sub_command_header_index == commandHeaderIndex) - continue; - - if (LibCompiler::String(command_headers[sub_command_header_index].Name) - .find(kLdDefineSymbol) != LibCompiler::String::npos && - LibCompiler::String(command_headers[sub_command_header_index].Name) - .find(kLdDynamicSym) == LibCompiler::String::npos) - { - if (kVerbose) - { - kStdOut << "ignore :UndefinedSymbol: command header...\n"; - } - - // ignore :UndefinedSymbol: headers, they do not contain code. - continue; - } - - auto& command_hdr = command_headers[sub_command_header_index]; - - if (command_hdr.Name == - LibCompiler::String(command_headers[commandHeaderIndex].Name)) - { - if (std::find(dupl_symbols.cbegin(), dupl_symbols.cend(), - command_hdr.Name) == dupl_symbols.cend()) - { - dupl_symbols.emplace_back(command_hdr.Name); - } - - if (kVerbose) - kStdOut << "found duplicate symbol: " << command_hdr.Name - << "\n"; - - kDuplicateSymbols = true; - } - } - } - - if (!dupl_symbols.empty()) - { - for (auto& symbol : dupl_symbols) - { - kStdOut << "Multiple symbols of " << symbol << ".\n"; - } - - return LIBCOMPILER_EXEC_ERROR; - } - - // step 2.5: write program bytes. - - for (auto& struct_of_blob : kObjectBytes) - { - output_fc.write(struct_of_blob.mBlob.data(), struct_of_blob.mBlob.size()); - } - - if (kVerbose) - kStdOut << "wrote contents of: " << kOutput << "\n"; - - // step 3: check if we have those symbols - - std::vector unreferenced_symbols; - - for (auto& command_hdr : command_headers) - { - if (auto it = std::find(not_found.begin(), not_found.end(), - LibCompiler::String(command_hdr.Name)); - it != not_found.end()) - { - unreferenced_symbols.emplace_back(command_hdr.Name); - } - } - - if (!unreferenced_symbols.empty()) - { - for (auto& unreferenced_symbol : unreferenced_symbols) - { - kStdOut << "undefined symbol " << unreferenced_symbol << "\n"; - } - } - - if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) || - !unreferenced_symbols.empty()) - { - if (kVerbose) - kStdOut << "file: " << kOutput - << ", is corrupt, removing file...\n"; - - return LIBCOMPILER_EXEC_ERROR; - } - - return EXIT_SUCCESS; -} - -// Last rev 13-1-24 diff --git a/dev/LibCompiler/src/Detail/AsmUtils.h b/dev/LibCompiler/src/Detail/AsmUtils.h index 4168dea..91ee940 100644 --- a/dev/LibCompiler/src/Detail/AsmUtils.h +++ b/dev/LibCompiler/src/Detail/AsmUtils.h @@ -11,11 +11,11 @@ using namespace LibCompiler; -namespace Details +namespace Detail { extern void print_error(std::string reason, std::string file) noexcept; extern void print_warning(std::string reason, std::string file) noexcept; -} // namespace Details +} // namespace Detail /// @brief Get Number from lineBuffer. /// @param lineBuffer the lineBuffer to fetch from. @@ -37,7 +37,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey) { if (errno != 0) { - Details::print_error("invalid hex number: " + lineBuffer, "LibCompiler"); + Detail::print_error("invalid hex number: " + lineBuffer, "LibCompiler"); throw std::runtime_error("invalid_hex"); } } @@ -57,7 +57,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey) { if (errno != 0) { - Details::print_error("invalid binary number:" + lineBuffer, "LibCompiler"); + Detail::print_error("invalid binary number:" + lineBuffer, "LibCompiler"); throw std::runtime_error("invalid_bin"); } } @@ -77,7 +77,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey) { if (errno != 0) { - Details::print_error("invalid octal number: " + lineBuffer, "LibCompiler"); + Detail::print_error("invalid octal number: " + lineBuffer, "LibCompiler"); throw std::runtime_error("invalid_octal"); } } @@ -97,7 +97,7 @@ static NumberCast32 GetNumber32(std::string lineBuffer, std::string numberKey) { if (errno != 0) { - Details::print_error("invalid hex number: " + lineBuffer, "LibCompiler"); + Detail::print_error("invalid hex number: " + lineBuffer, "LibCompiler"); throw std::runtime_error("invalid_hex"); } } diff --git a/dev/LibCompiler/src/DynamicLinkerELF.cc b/dev/LibCompiler/src/DynamicLinkerELF.cc new file mode 100644 index 0000000..7dd3440 --- /dev/null +++ b/dev/LibCompiler/src/DynamicLinkerELF.cc @@ -0,0 +1,85 @@ +/* ------------------------------------------- + + Copyright (C) 2024 Theater Quality Corp, all rights reserved + + @file DynamicLinker64PEF.cc + @brief: C++ 64-Bit PEF Linker. + +------------------------------------------- */ + +/// @author EL Mahrouss Amlal (amlel) +/// @brief TQ 64-bit PEF Linker. +/// Last Rev: Sat Feb 24 CET 2024 +/// @note Do not look up for anything with .code64/.data64/.zero64! +/// It will be loaded when the program loader will start the image. + +//! Toolchain Kit. +#include + +#include + +//! Assembler Kit +#include + +//! Preferred Executable Format +#include +#include + +//! Release macros. +#include + +//! Advanced Executable Object Format. +#include +#include + +#define kLinkerVersionStr "TQ 64-Bit Linker (ELF) %s, (c) Theater Quality Corp. 2024, all rights reserved.\n" + +#define MemoryCopy(DST, SRC, SZ) memcpy(DST, SRC, SZ) +#define StringCompare(DST, SRC) strcmp(DST, SRC) + +#define kPefNoCpu 0U +#define kPefNoSubCpu 0U + +#define kWhite "\e[0;97m" + +#define kStdOut (std::cout << kWhite << "ld64: ") + +#define kLinkerDefaultOrigin kPefBaseOrigin +#define kLinkerId (0x5046FF) +#define kLinkerAbiContainer "Container:ABI:" + +/// @brief PEF stack size symbol. +#define kLinkerStackSizeSymbol "SizeOfReserveStack" + +namespace Detail +{ +struct DynamicLinkerBlob final +{ + std::vector mBlob{}; // PEF code/bss/data blob. + UIntPtr mObjOffset{0UL}; // the offset of the PEF container header.. +}; +} + +static Bool kFatBinaryEnable = false; +static Bool kStartFound = false; +static Bool kDuplicateSymbols = false; +static Bool kVerbose = false; + +/* object code and list. */ +static std::vector kObjectList; +static std::vector kObjectBytes; + +static uintptr_t kMIBCount = 8; +static uintptr_t kByteCount = 1024; + +#define kPrintF printf +#define kLinkerSplash() kPrintF(kWhite kLinkerVersionStr, kDistVersion) + +/// @brief ZKA 64-bit Linker. +/// @note This linker is made for XCOFF executable, thus ZKA based OSes. +LIBCOMPILER_MODULE(DynamicLinker64XCOFF) +{ + return EXIT_SUCCESS; +} + +// Last rev 13-1-24 diff --git a/dev/LibCompiler/src/DynamicLinkerPEF.cc b/dev/LibCompiler/src/DynamicLinkerPEF.cc new file mode 100644 index 0000000..d00feaf --- /dev/null +++ b/dev/LibCompiler/src/DynamicLinkerPEF.cc @@ -0,0 +1,774 @@ +/* ------------------------------------------- + + Copyright (C) 2024 Theater Quality Corp, all rights reserved + + @file DynamicLinker64PEF.cc + @brief: C++ 64-Bit PEF Linker. + +------------------------------------------- */ + +/// @author EL Mahrouss Amlal (amlel) +/// @brief TQ 64-bit PEF Linker. +/// Last Rev: Sat Feb 24 CET 2024 +/// @note Do not look up for anything with .code64/.data64/.zero64! +/// It will be loaded when the program loader will start the image. + +//! Toolchain Kit. +#include + +#include + +//! Assembler Kit +#include + +//! Preferred Executable Format +#include +#include + +//! Release macros. +#include + +//! Advanced Executable Object Format. +#include +#include + +#define kLinkerVersionStr "TQ 64-Bit Linker (Preferred Executable) %s, (c) Theater Quality Corp. 2024, all rights reserved.\n" + +#define MemoryCopy(DST, SRC, SZ) memcpy(DST, SRC, SZ) +#define StringCompare(DST, SRC) strcmp(DST, SRC) + +#define kPefNoCpu 0U +#define kPefNoSubCpu 0U + +#define kWhite "\e[0;97m" + +#define kStdOut (std::cout << kWhite << "ld64: ") + +#define kLinkerDefaultOrigin kPefBaseOrigin +#define kLinkerId (0x5046FF) +#define kLinkerAbiContainer "Container:ABI:" + +/// @brief PEF stack size symbol. +#define kLinkerStackSizeSymbol "SizeOfReserveStack" + +namespace Detail +{ +struct DynamicLinkerBlob final +{ + std::vector mBlob{}; // PEF code/bss/data blob. + UIntPtr mObjOffset{0UL}; // the offset of the PEF container header.. +}; +} + +enum +{ + kABITypeStart = 0x1010, /* Invalid ABI start of ABI list. */ + kABITypeZKA = 0x5046, /* PF (ZKA PEF ABI) */ + kABITypeInvalid = 0xFFFF, +}; + +static LibCompiler::String kOutput = ""; +static Int32 kAbi = kABITypeZKA; +static Int32 kSubArch = kPefNoSubCpu; +static Int32 kArch = LibCompiler::kPefArchInvalid; +static Bool kFatBinaryEnable = false; +static Bool kStartFound = false; +static Bool kDuplicateSymbols = false; +static Bool kVerbose = false; + +/* ld64 is to be found, mld is to be found at runtime. */ +static const char* kLdDefineSymbol = ":UndefinedSymbol:"; +static const char* kLdDynamicSym = ":RuntimeSymbol:"; + +/* object code and list. */ +static std::vector kObjectList; +static std::vector kObjectBytes; + +static uintptr_t kMIBCount = 8; +static uintptr_t kByteCount = 1024; + +#define kPrintF printf +#define kLinkerSplash() kPrintF(kWhite kLinkerVersionStr, kDistVersion) + +/// @brief ZKA 64-bit Linker. +/// @note This linker is made for PEF executable, thus ZKA based OSes. +LIBCOMPILER_MODULE(DynamicLinker64PEF) +{ + bool is_executable = true; + + /** + * @brief parse flags and trigger options. + */ + for (size_t linker_arg = 1; linker_arg < argc; ++linker_arg) + { + if (StringCompare(argv[linker_arg], "--ld64:help") == 0) + { + kLinkerSplash(); + + kStdOut << "--ld64:ver: Show linker version.\n"; + kStdOut << "--ld64:?: Show linker help.\n"; + kStdOut << "--ld64:verbose: Enable linker trace.\n"; + kStdOut << "--ld64:dylib: Output as a Dylib PEF.\n"; + kStdOut << "--ld64:fat: Output as a FAT PEF.\n"; + kStdOut << "--ld64:32k: Output as a 32x0 PEF.\n"; + kStdOut << "--ld64:64k: Output as a 64x0 PEF.\n"; + kStdOut << "--ld64:amd64: Output as a AMD64 PEF.\n"; + kStdOut << "--ld64:rv64: Output as a RISC-V PEF.\n"; + kStdOut << "--ld64:power64: Output as a POWER PEF.\n"; + kStdOut << "--ld64:arm64: Output as a ARM64 PEF.\n"; + kStdOut << "--ld64:output: Select the output file name.\n"; + + return EXIT_SUCCESS; + } + else if (StringCompare(argv[linker_arg], "--ld64:version") == 0) + { + kLinkerSplash(); + return EXIT_SUCCESS; + } + else if (StringCompare(argv[linker_arg], "--ld64:fat-binary") == 0) + { + kFatBinaryEnable = true; + + continue; + } + else if (StringCompare(argv[linker_arg], "--ld64:64k") == 0) + { + kArch = LibCompiler::kPefArch64000; + + continue; + } + else if (StringCompare(argv[linker_arg], "--ld64:amd64") == 0) + { + kArch = LibCompiler::kPefArchAMD64; + + continue; + } + else if (StringCompare(argv[linker_arg], "--ld64:32k") == 0) + { + kArch = LibCompiler::kPefArch32000; + + continue; + } + else if (StringCompare(argv[linker_arg], "--ld64:power64") == 0) + { + kArch = LibCompiler::kPefArchPowerPC; + + continue; + } + else if (StringCompare(argv[linker_arg], "--ld64:riscv64") == 0) + { + kArch = LibCompiler::kPefArchRISCV; + + continue; + } + else if (StringCompare(argv[linker_arg], "--ld64:arm64") == 0) + { + kArch = LibCompiler::kPefArchARM64; + + continue; + } + else if (StringCompare(argv[linker_arg], "--ld64:verbose") == 0) + { + kVerbose = true; + + continue; + } + else if (StringCompare(argv[linker_arg], "--ld64:dylib") == 0) + { + if (kOutput.empty()) + { + continue; + } + + if (kOutput.find(kPefExt) != LibCompiler::String::npos) + kOutput.erase(kOutput.find(kPefExt), strlen(kPefExt)); + + kOutput += kPefDylibExt; + + is_executable = false; + + continue; + } + else if (StringCompare(argv[linker_arg], "--ld64:output") == 0) + { + kOutput = argv[linker_arg + 1]; + ++linker_arg; + + continue; + } + else + { + if (argv[linker_arg][0] == '-') + { + kStdOut << "unknown flag: " << argv[linker_arg] << "\n"; + return EXIT_FAILURE; + } + + kObjectList.emplace_back(argv[linker_arg]); + + continue; + } + } + + if (kOutput.empty()) + { + kStdOut << "no output filename set." << std::endl; + return LIBCOMPILER_EXEC_ERROR; + } + + // sanity check. + if (kObjectList.empty()) + { + kStdOut << "no input files." << std::endl; + return LIBCOMPILER_EXEC_ERROR; + } + else + { + namespace fs = std::filesystem; + + // check for existing files, if they don't throw an error. + for (auto& obj : kObjectList) + { + if (!fs::exists(obj)) + { + // if filesystem doesn't find file + // -> throw error. + kStdOut << "no such file: " << obj << std::endl; + return LIBCOMPILER_EXEC_ERROR; + } + } + } + + // PEF expects a valid target architecture when outputing a binary. + if (kArch == 0) + { + kStdOut << "no target architecture set, can't continue." << std::endl; + return LIBCOMPILER_EXEC_ERROR; + } + + LibCompiler::PEFContainer pef_container{}; + + int32_t archs = kArch; + + pef_container.Count = 0UL; + pef_container.Kind = is_executable ? LibCompiler::kPefKindExec : LibCompiler::kPefKindDylib; + pef_container.SubCpu = kSubArch; + pef_container.Linker = kLinkerId; // Theater Quality Corp. Linker + pef_container.Abi = kAbi; // Multi-Processor UX ABI + pef_container.Magic[0] = kPefMagic[kFatBinaryEnable ? 2 : 0]; + pef_container.Magic[1] = kPefMagic[1]; + pef_container.Magic[2] = kPefMagic[kFatBinaryEnable ? 0 : 2]; + pef_container.Magic[3] = kPefMagic[3]; + pef_container.Version = kPefVersion; + + // specify the start address, can be 0x10000 + pef_container.Start = kLinkerDefaultOrigin; + pef_container.HdrSz = sizeof(LibCompiler::PEFContainer); + + std::ofstream output_fc(kOutput, std::ofstream::binary); + + if (output_fc.bad()) + { + if (kVerbose) + { + kStdOut << "error: " << strerror(errno) << "\n"; + } + + return LIBCOMPILER_FILE_NOT_FOUND; + } + + //! Read AE to convert as PEF. + + std::vector command_headers; + LibCompiler::Utils::AEReadableProtocol reader_protocol{}; + + for (const auto& objectFile : kObjectList) + { + if (!std::filesystem::exists(objectFile)) + continue; + + LibCompiler::AEHeader hdr{}; + + reader_protocol.FP = std::ifstream(objectFile, std::ifstream::binary); + reader_protocol.FP >> hdr; + + auto ae_header = hdr; + + if (ae_header.fMagic[0] == kAEMag0 && ae_header.fMagic[1] == kAEMag1 && + ae_header.fSize == sizeof(LibCompiler::AEHeader)) + { + if (ae_header.fArch != kArch) + { + if (kVerbose) + kStdOut << "info: is this a FAT binary? : "; + + if (!kFatBinaryEnable) + { + if (kVerbose) + kStdOut << "No.\n"; + + kStdOut << "error: object " << objectFile + << " is a different kind of architecture and output isn't " + "treated as a FAT binary." + << std::endl; + + return LIBCOMPILER_FAT_ERROR; + } + else + { + if (kVerbose) + { + kStdOut << "Architecture matches what we expect.\n"; + } + } + } + + // append arch type to archs varaible. + archs |= ae_header.fArch; + std::size_t cnt = ae_header.fCount; + + if (kVerbose) + kStdOut << "object header found, record count: " << cnt << "\n"; + + pef_container.Count = cnt; + + char_type* raw_ae_records = + new char_type[cnt * sizeof(LibCompiler::AERecordHeader)]; + + memset(raw_ae_records, 0, cnt * sizeof(LibCompiler::AERecordHeader)); + + auto* ae_records = reader_protocol.Read(raw_ae_records, cnt); + + for (size_t ae_record_index = 0; ae_record_index < cnt; + ++ae_record_index) + { + LibCompiler::PEFCommandHeader command_header{0}; + std::size_t offset_of_obj = ae_records[ae_record_index].fOffset; + + MemoryCopy(command_header.Name, ae_records[ae_record_index].fName, + kPefNameLen); + + LibCompiler::String cmd_hdr_name(command_header.Name); + + // check this header if it's any valid. + if (cmd_hdr_name.find(kPefCode64) == + LibCompiler::String::npos && + cmd_hdr_name.find(kPefData64) == + LibCompiler::String::npos && + cmd_hdr_name.find(kPefZero64) == + LibCompiler::String::npos) + { + if (cmd_hdr_name.find(kPefStart) == + LibCompiler::String::npos && + *command_header.Name == 0) + { + if (cmd_hdr_name.find(kLdDefineSymbol) != + LibCompiler::String::npos) + { + goto ld_mark_header; + } + else + { + continue; + } + } + } + + if (cmd_hdr_name.find(kPefStart) != + LibCompiler::String::npos && + cmd_hdr_name.find(kPefCode64) != + LibCompiler::String::npos) + { + kStartFound = true; + } + + ld_mark_header: + command_header.Offset = offset_of_obj; + command_header.Kind = ae_records[ae_record_index].fKind; + command_header.Size = ae_records[ae_record_index].fSize; + command_header.Cpu = ae_header.fArch; + command_header.SubCpu = ae_header.fSubArch; + + if (kVerbose) + { + kStdOut << "Record: " + << ae_records[ae_record_index].fName << " is marked.\n"; + + kStdOut << "Record offset: " << command_header.Offset << "\n"; + } + + command_headers.emplace_back(command_header); + } + + delete[] raw_ae_records; + + std::vector bytes; + bytes.resize(ae_header.fCodeSize); + + // TODO: Port this to NeFS. + + reader_protocol.FP.seekg(std::streamsize(ae_header.fStartCode)); + reader_protocol.FP.read(bytes.data(), std::streamsize(ae_header.fCodeSize)); + + for (auto& byte : bytes) + { + kObjectBytes.push_back({ .mBlob = bytes, .mObjOffset = ae_header.fStartCode }); + } + + reader_protocol.FP.close(); + + continue; + } + + kStdOut << "Not an object container: " << objectFile << std::endl; + // don't continue, it is a fatal error. + return LIBCOMPILER_EXEC_ERROR; + } + + pef_container.Cpu = archs; + + output_fc << pef_container; + + if (kVerbose) + { + kStdOut << "Wrote container header.\n"; + } + + output_fc.seekp(std::streamsize(pef_container.HdrSz)); + + std::vector not_found; + std::vector symbols; + + // step 2: check for errors (multiple symbols, undefined ones) + + for (auto& command_hdr : command_headers) + { + // check if this symbol needs to be resolved. + if (LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) != + LibCompiler::String::npos && + LibCompiler::String(command_hdr.Name).find(kLdDynamicSym) == LibCompiler::String::npos) + { + if (kVerbose) + kStdOut << "Found undefined symbol: " << command_hdr.Name << "\n"; + + if (auto it = std::find(not_found.begin(), not_found.end(), + LibCompiler::String(command_hdr.Name)); + it == not_found.end()) + { + not_found.emplace_back(command_hdr.Name); + } + } + + symbols.emplace_back(command_hdr.Name); + } + + // Now try to solve these symbols. + + for (size_t not_found_idx = 0; not_found_idx < command_headers.size(); + ++not_found_idx) + { + if (const auto it = std::find(not_found.begin(), not_found.end(), + LibCompiler::String(command_headers[not_found_idx].Name)); + it != not_found.end()) + { + LibCompiler::String symbol_imp = *it; + + if (symbol_imp.find(kLdDefineSymbol) == LibCompiler::String::npos) + continue; + + // erase the lookup prefix. + symbol_imp.erase( + 0, symbol_imp.find(kLdDefineSymbol) + strlen(kLdDefineSymbol)); + + // demangle everything. + while (symbol_imp.find('$') != LibCompiler::String::npos) + symbol_imp.erase(symbol_imp.find('$'), 1); + + // the reason we do is because, this may not match the symbol, and we need + // to look for other matching symbols. + for (auto& command_hdr : command_headers) + { + if (LibCompiler::String(command_hdr.Name).find(symbol_imp) != + LibCompiler::String::npos && + LibCompiler::String(command_hdr.Name).find(kLdDefineSymbol) == + LibCompiler::String::npos) + { + LibCompiler::String undefined_symbol = command_hdr.Name; + auto result_of_sym = + undefined_symbol.substr(undefined_symbol.find(symbol_imp)); + + for (int i = 0; result_of_sym[i] != 0; ++i) + { + if (result_of_sym[i] != symbol_imp[i]) + goto ld_continue_search; + } + + not_found.erase(it); + + if (kVerbose) + kStdOut << "found symbol: " << command_hdr.Name << "\n"; + + break; + } + } + + ld_continue_search: + continue; + } + } + + // step 3: check for errors (recheck if we have those symbols.) + + if (!kStartFound && is_executable) + { + if (kVerbose) + kStdOut + << "undefined entrypoint: " << kPefStart << ", you may have forget to ld64 " + "against your compiler's runtime library.\n"; + + kStdOut << "undefined entrypoint " << kPefStart + << " for executable: " << kOutput << "\n"; + } + + // step 4: write all PEF commands. + + LibCompiler::PEFCommandHeader date_cmd_hdr{}; + + time_t timestamp = time(nullptr); + + LibCompiler::String timeStampStr = "Container:BuildEpoch:"; + timeStampStr += std::to_string(timestamp); + + strncpy(date_cmd_hdr.Name, timeStampStr.c_str(), timeStampStr.size()); + + date_cmd_hdr.Flags = 0; + date_cmd_hdr.Kind = LibCompiler::kPefZero; + date_cmd_hdr.Offset = output_fc.tellp(); + date_cmd_hdr.Size = timeStampStr.size(); + + command_headers.push_back(date_cmd_hdr); + + LibCompiler::PEFCommandHeader abi_cmd_hdr{}; + + LibCompiler::String abi = kLinkerAbiContainer; + + switch (kArch) + { + case LibCompiler::kPefArchAMD64: { + abi += "MSFT"; + break; + } + case LibCompiler::kPefArchPowerPC: { + abi += "SYSV"; + break; + } + case LibCompiler::kPefArch32000: + case LibCompiler::kPefArch64000: { + abi += " ZWS"; + break; + } + default: { + abi += " IDK"; + break; + } + } + + MemoryCopy(abi_cmd_hdr.Name, abi.c_str(), abi.size()); + + abi_cmd_hdr.Size = abi.size(); + abi_cmd_hdr.Offset = output_fc.tellp(); + abi_cmd_hdr.Flags = 0; + abi_cmd_hdr.Kind = LibCompiler::kPefLinkerID; + + command_headers.push_back(abi_cmd_hdr); + + LibCompiler::PEFCommandHeader stack_cmd_hdr{0}; + + stack_cmd_hdr.Cpu = kArch; + stack_cmd_hdr.Flags = 0; + stack_cmd_hdr.Size = sizeof(uintptr_t); + stack_cmd_hdr.Offset = 0; + + MemoryCopy(stack_cmd_hdr.Name, kLinkerStackSizeSymbol, strlen(kLinkerStackSizeSymbol)); + + command_headers.push_back(stack_cmd_hdr); + + LibCompiler::PEFCommandHeader uuid_cmd_hdr{}; + + std::random_device rd; + + auto seedData = std::array{}; + std::generate(std::begin(seedData), std::end(seedData), std::ref(rd)); + std::seed_seq seq(std::begin(seedData), std::end(seedData)); + std::mt19937 generator(seq); + + auto gen = uuids::uuid_random_generator{generator}; + uuids::uuid id = gen(); + auto uuidStr = uuids::to_string(id); + + MemoryCopy(uuid_cmd_hdr.Name, "Container:GUID:4:", strlen("Container:GUID:4:")); + MemoryCopy(uuid_cmd_hdr.Name + strlen("Container:GUID:4:"), uuidStr.c_str(), + uuidStr.size()); + + uuid_cmd_hdr.Size = strlen(uuid_cmd_hdr.Name); + uuid_cmd_hdr.Offset = output_fc.tellp(); + uuid_cmd_hdr.Flags = LibCompiler::kPefLinkerID; + uuid_cmd_hdr.Kind = LibCompiler::kPefZero; + + command_headers.push_back(uuid_cmd_hdr); + + // prepare a symbol vector. + std::vector undef_symbols; + std::vector dupl_symbols; + std::vector resolve_symbols; + + constexpr Int32 cPaddingOffset = 16; + + size_t previous_offset = (command_headers.size() * sizeof(LibCompiler::PEFCommandHeader)) + cPaddingOffset; + + // Finally write down the command headers. + // And check for any duplications + for (size_t commandHeaderIndex = 0UL; + commandHeaderIndex < command_headers.size(); ++commandHeaderIndex) + { + if (LibCompiler::String(command_headers[commandHeaderIndex].Name) + .find(kLdDefineSymbol) != LibCompiler::String::npos && + LibCompiler::String(command_headers[commandHeaderIndex].Name) + .find(kLdDynamicSym) == LibCompiler::String::npos) + { + // ignore :UndefinedSymbol: headers, they do not contain code. + continue; + } + + LibCompiler::String symbol_name = command_headers[commandHeaderIndex].Name; + + if (!symbol_name.empty()) + { + undef_symbols.emplace_back(symbol_name); + } + + command_headers[commandHeaderIndex].Offset += previous_offset; + previous_offset += command_headers[commandHeaderIndex].Size; + + LibCompiler::String 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. + /// this chunk of code updates the pef_container.Start with the updated offset. + if (name.find(kPefStart) != LibCompiler::String::npos && + name.find(kPefCode64) != LibCompiler::String::npos) + { + pef_container.Start = command_headers[commandHeaderIndex].Offset; + auto tellCurPos = output_fc.tellp(); + + output_fc.seekp(0); + output_fc << pef_container; + + output_fc.seekp(tellCurPos); + } + + if (kVerbose) + { + kStdOut << "Command header name: " << name << "\n"; + kStdOut << "Real address of command header content: " << command_headers[commandHeaderIndex].Offset << "\n"; + } + + output_fc << command_headers[commandHeaderIndex]; + + for (size_t sub_command_header_index = 0UL; + sub_command_header_index < command_headers.size(); + ++sub_command_header_index) + { + if (sub_command_header_index == commandHeaderIndex) + continue; + + if (LibCompiler::String(command_headers[sub_command_header_index].Name) + .find(kLdDefineSymbol) != LibCompiler::String::npos && + LibCompiler::String(command_headers[sub_command_header_index].Name) + .find(kLdDynamicSym) == LibCompiler::String::npos) + { + if (kVerbose) + { + kStdOut << "ignore :UndefinedSymbol: command header...\n"; + } + + // ignore :UndefinedSymbol: headers, they do not contain code. + continue; + } + + auto& command_hdr = command_headers[sub_command_header_index]; + + if (command_hdr.Name == + LibCompiler::String(command_headers[commandHeaderIndex].Name)) + { + if (std::find(dupl_symbols.cbegin(), dupl_symbols.cend(), + command_hdr.Name) == dupl_symbols.cend()) + { + dupl_symbols.emplace_back(command_hdr.Name); + } + + if (kVerbose) + kStdOut << "found duplicate symbol: " << command_hdr.Name + << "\n"; + + kDuplicateSymbols = true; + } + } + } + + if (!dupl_symbols.empty()) + { + for (auto& symbol : dupl_symbols) + { + kStdOut << "Multiple symbols of " << symbol << ".\n"; + } + + return LIBCOMPILER_EXEC_ERROR; + } + + // step 2.5: write program bytes. + + for (auto& struct_of_blob : kObjectBytes) + { + output_fc.write(struct_of_blob.mBlob.data(), struct_of_blob.mBlob.size()); + } + + if (kVerbose) + kStdOut << "wrote contents of: " << kOutput << "\n"; + + // step 3: check if we have those symbols + + std::vector unreferenced_symbols; + + for (auto& command_hdr : command_headers) + { + if (auto it = std::find(not_found.begin(), not_found.end(), + LibCompiler::String(command_hdr.Name)); + it != not_found.end()) + { + unreferenced_symbols.emplace_back(command_hdr.Name); + } + } + + if (!unreferenced_symbols.empty()) + { + for (auto& unreferenced_symbol : unreferenced_symbols) + { + kStdOut << "undefined symbol " << unreferenced_symbol << "\n"; + } + } + + if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) || + !unreferenced_symbols.empty()) + { + if (kVerbose) + kStdOut << "file: " << kOutput + << ", is corrupt, removing file...\n"; + + return LIBCOMPILER_EXEC_ERROR; + } + + return EXIT_SUCCESS; +} + +// Last rev 13-1-24 -- cgit v1.2.3