From c791c2de8bdcd89035dd004b73d05217e40e179c Mon Sep 17 00:00:00 2001 From: Amlal Date: Sat, 26 Apr 2025 08:56:59 +0200 Subject: dev: codebase has been improved in terms of cli and consistency. Signed-off-by: Amlal --- dev/LibCompiler/src/AssemblerPowerPC.cc | 910 ++++++++++++++++++++++++++++++++ 1 file changed, 910 insertions(+) create mode 100644 dev/LibCompiler/src/AssemblerPowerPC.cc (limited to 'dev/LibCompiler/src/AssemblerPowerPC.cc') diff --git a/dev/LibCompiler/src/AssemblerPowerPC.cc b/dev/LibCompiler/src/AssemblerPowerPC.cc new file mode 100644 index 0000000..ffe5c6a --- /dev/null +++ b/dev/LibCompiler/src/AssemblerPowerPC.cc @@ -0,0 +1,910 @@ +/* ------------------------------------------- + + Copyright (C) 2024-2025 Amlal EL Mahrous, all rights reserved + +------------------------------------------- */ + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @file AssemblerPower.cxx +/// @author EL Mahrouss Amlal +/// @brief POWER Assembler. + +/// REMINDER: when dealing with an undefined symbol use (string +/// size):LinkerFindSymbol:(string) so that li will look for it. + +///////////////////////////////////////////////////////////////////////////////////////// + +#define __ASM_NEED_PPC__ 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +///////////////////// + +// ANSI ESCAPE CODES + +///////////////////// + +#define kBlank "\e[0;30m" +#define kRed "\e[0;31m" +#define kWhite "\e[0;97m" +#define kYellow "\e[0;33m" + +#define kStdOut (std::cout << kWhite) +#define kStdErr (std::cout << kRed) + +constexpr auto cPowerIPAlignment = 0x4U; + +static CharType kOutputArch = LibCompiler::kPefArchPowerPC; + +static std::size_t kCounter = 1UL; + +static std::uintptr_t kOrigin = kPefBaseOrigin; +static std::vector> kOriginLabel; + +static std::vector kBytes; + +static LibCompiler::AERecordHeader kCurrentRecord{ + .fName = "", .fKind = LibCompiler::kPefCode, .fSize = 0, .fOffset = 0}; + +static std::vector kRecords; +static std::vector kUndefinedSymbols; + +static const std::string kUndefinedSymbol = ":UndefinedSymbol:"; +static const std::string kRelocSymbol = ":RuntimeSymbol:"; + +// \brief forward decl. +static bool asm_read_attributes(std::string line); + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @brief POWER assembler entrypoint, the program/module starts here. + +///////////////////////////////////////////////////////////////////////////////////////// + +LIBCOMPILER_MODULE(AssemblerMainPower64) { + for (size_t i = 1; i < argc; ++i) { + if (argv[i][0] == '-') { + if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) { + kStdOut << "AssemblerPower: POWER64 Assembler Driver.\nAssemblerPower: " << kDistVersion + << "\nAssemblerPower: " + "Copyright (c) " + "Amlal El Mahrouss\n"; + return 0; + } else if (strcmp(argv[i], "--h") == 0) { + kStdOut << "AssemblerPower: POWER64 Assembler Driver.\nAssemblerPower: Copyright (c) 2024 " + "Amlal El Mahrouss\n"; + kStdOut << "--version,/v: print program version.\n"; + kStdOut << "--verbose: print verbose output.\n"; + kStdOut << "--binary: output as flat binary.\n"; + + return 0; + } else if (strcmp(argv[i], "--binary") == 0) { + kOutputAsBinary = true; + continue; + } else if (strcmp(argv[i], "--verbose") == 0) { + kVerbose = true; + continue; + } + + kStdOut << "AssemblerPower: ignore " << argv[i] << "\n"; + continue; + } + + if (!std::filesystem::exists(argv[i])) { + kStdOut << "AssemblerPower: can't open: " << argv[i] << std::endl; + goto asm_fail_exit; + } + + std::string object_output(argv[i]); + + for (auto& ext : kAsmFileExts) { + if (object_output.find(ext) != std::string::npos) { + object_output.erase(object_output.find(ext), std::strlen(ext)); + } + } + + object_output += kOutputAsBinary ? kBinaryFileExt : kObjectFileExt; + + std::ifstream file_ptr(argv[i]); + std::ofstream file_ptr_out(object_output, std::ofstream::binary); + + if (file_ptr_out.bad()) { + if (kVerbose) { + kStdOut << "AssemblerPower: error: " << strerror(errno) << "\n"; + } + } + + std::string line; + + LibCompiler::AEHeader hdr{0}; + + memset(hdr.fPad, kAENullType, kAEPad); + + hdr.fMagic[0] = kAEMag0; + hdr.fMagic[1] = kAEMag1; + hdr.fSize = sizeof(LibCompiler::AEHeader); + hdr.fArch = kOutputArch; + + ///////////////////////////////////////////////////////////////////////////////////////// + + // COMPILATION LOOP + + ///////////////////////////////////////////////////////////////////////////////////////// + + LibCompiler::EncoderPowerPC asm64; + + while (std::getline(file_ptr, line)) { + if (auto ln = asm64.CheckLine(line, argv[i]); !ln.empty()) { + Detail::print_error(ln, argv[i]); + continue; + } + + try { + asm_read_attributes(line); + asm64.WriteLine(line, argv[i]); + } catch (const std::exception& e) { + if (kVerbose) { + std::string what = e.what(); + Detail::print_warning("exit because of: " + what, "LibCompiler"); + } + + std::filesystem::remove(object_output); + goto asm_fail_exit; + } + } + + if (!kOutputAsBinary) { + if (kVerbose) { + kStdOut << "AssemblerPower: Writing object file...\n"; + } + + // this is the final step, write everything to the file. + + auto pos = file_ptr_out.tellp(); + + hdr.fCount = kRecords.size() + kUndefinedSymbols.size(); + + file_ptr_out << hdr; + + if (kRecords.empty()) { + kStdErr << "AssemblerPower: At least one record is needed to write an object " + "file.\nAssemblerPower: Make one using `public_segment .code64 foo_bar`.\n"; + + std::filesystem::remove(object_output); + return 1; + } + + kRecords[kRecords.size() - 1].fSize = kBytes.size(); + + std::size_t record_count = 0UL; + + for (auto& record_hdr : kRecords) { + record_hdr.fFlags |= LibCompiler::kKindRelocationAtRuntime; + record_hdr.fOffset = record_count; + ++record_count; + + file_ptr_out << record_hdr; + + if (kVerbose) kStdOut << "AssemblerPower: Wrote record " << record_hdr.fName << "...\n"; + } + + // increment once again, so that we won't lie about the kUndefinedSymbols. + ++record_count; + + for (auto& sym : kUndefinedSymbols) { + LibCompiler::AERecordHeader undefined_sym{0}; + + if (kVerbose) kStdOut << "AssemblerPower: Wrote symbol " << sym << " to file...\n"; + + undefined_sym.fKind = kAENullType; + undefined_sym.fSize = sym.size(); + undefined_sym.fOffset = record_count; + + ++record_count; + + memset(undefined_sym.fPad, kAENullType, kAEPad); + memcpy(undefined_sym.fName, sym.c_str(), sym.size()); + + file_ptr_out << undefined_sym; + + ++kCounter; + } + + auto pos_end = file_ptr_out.tellp(); + + file_ptr_out.seekp(pos); + + hdr.fStartCode = pos_end; + hdr.fCodeSize = kBytes.size(); + + file_ptr_out << hdr; + + file_ptr_out.seekp(pos_end); + } else { + if (kVerbose) { + kStdOut << "AssemblerPower: Write raw binary...\n"; + } + } + + // byte from byte, we write this. + for (auto& byte : kBytes) { + file_ptr_out.write(reinterpret_cast(&byte), sizeof(byte)); + } + + if (kVerbose) kStdOut << "AssemblerPower: Wrote file with program in it.\n"; + + file_ptr_out.flush(); + file_ptr_out.close(); + + if (kVerbose) kStdOut << "AssemblerPower: Exit succeeded.\n"; + + return 0; + } + +asm_fail_exit: + + if (kVerbose) kStdOut << "AssemblerPower: Exit failed.\n"; + + return LIBCOMPILER_EXEC_ERROR; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Check for attributes +// returns true if any was found. + +///////////////////////////////////////////////////////////////////////////////////////// + +static bool asm_read_attributes(std::string line) { + // extern_segment is the opposite of public_segment, it signals to the li + // that we need this symbol. + if (LibCompiler::find_word(line, "extern_segment")) { + if (kOutputAsBinary) { + Detail::print_error("Invalid extern_segment directive in flat binary mode.", "LibCompiler"); + throw std::runtime_error("invalid_extern_segment_bin"); + } + + auto name = line.substr(line.find("extern_segment") + strlen("extern_segment") + 1); + + if (name.size() == 0) { + Detail::print_error("Invalid extern_segment", "LibCompiler"); + throw std::runtime_error("invalid_extern_segment"); + } + + std::string result = std::to_string(name.size()); + result += kUndefinedSymbol; + + // mangle this + for (char& j : name) { + if (j == ' ' || j == ',') j = '$'; + } + + result += name; + + if (name.find(".code64") != std::string::npos) { + // data is treated as code. + kCurrentRecord.fKind = LibCompiler::kPefCode; + } else if (name.find(".data64") != std::string::npos) { + // no code will be executed from here. + kCurrentRecord.fKind = LibCompiler::kPefData; + } else if (name.find(".zero64") != std::string::npos) { + // this is a bss section. + kCurrentRecord.fKind = LibCompiler::kPefZero; + } + + // this is a special case for the start stub. + // we want this so that li can find it. + + if (name == kPefStart) { + kCurrentRecord.fKind = LibCompiler::kPefCode; + } + + // now we can tell the code size of the previous kCurrentRecord. + + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); + + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, result.c_str(), result.size()); + + ++kCounter; + + memset(kCurrentRecord.fPad, kAENullType, kAEPad); + + kRecords.emplace_back(kCurrentRecord); + + return true; + } + // public_segment is a special keyword used by AssemblerPower to tell the AE output stage to + // mark this section as a header. it currently supports .code64, .data64., + // .zero64 + else if (LibCompiler::find_word(line, "public_segment")) { + if (kOutputAsBinary) { + Detail::print_error("Invalid public_segment directive in flat binary mode.", "LibCompiler"); + throw std::runtime_error("invalid_public_segment_bin"); + } + + auto name = line.substr(line.find("public_segment") + strlen("public_segment")); + + std::string name_copy = name; + + for (char& j : name) { + if (j == ' ') j = '$'; + } + + if (name.find(".code64") != std::string::npos) { + // data is treated as code. + + name_copy.erase(name_copy.find(".code64"), strlen(".code64")); + kCurrentRecord.fKind = LibCompiler::kPefCode; + } else if (name.find(".data64") != std::string::npos) { + // no code will be executed from here. + + name_copy.erase(name_copy.find(".data64"), strlen(".data64")); + kCurrentRecord.fKind = LibCompiler::kPefData; + } else if (name.find(".zero64") != std::string::npos) { + // this is a bss section. + + name_copy.erase(name_copy.find(".zero64"), strlen(".zero64")); + kCurrentRecord.fKind = LibCompiler::kPefZero; + } + + // this is a special case for the start stub. + // we want this so that li can find it. + + if (name == kPefStart) { + kCurrentRecord.fKind = LibCompiler::kPefCode; + } + + while (name_copy.find(" ") != std::string::npos) name_copy.erase(name_copy.find(" "), 1); + + kOriginLabel.push_back(std::make_pair(name_copy, kOrigin)); + ++kOrigin; + + // now we can tell the code size of the previous kCurrentRecord. + + if (!kRecords.empty()) kRecords[kRecords.size() - 1].fSize = kBytes.size(); + + memset(kCurrentRecord.fName, 0, kAESymbolLen); + memcpy(kCurrentRecord.fName, name.c_str(), name.size()); + + ++kCounter; + + memset(kCurrentRecord.fPad, kAENullType, kAEPad); + + kRecords.emplace_back(kCurrentRecord); + + return true; + } + + return false; +} + +// \brief algorithms and helpers. + +namespace Detail::algorithm { +// \brief authorize a brief set of characters. +static inline bool is_not_alnum_space(char c) { + return !(isalpha(c) || isdigit(c) || (c == ' ') || (c == '\t') || (c == ',') || (c == '(') || + (c == ')') || (c == '"') || (c == '\'') || (c == '[') || (c == ']') || (c == '+') || + (c == '_') || (c == ':') || (c == '@') || (c == '.')); +} + +bool is_valid_power64(std::string str) { + return std::find_if(str.begin(), str.end(), is_not_alnum_space) == str.end(); +} +} // namespace Detail::algorithm + +///////////////////////////////////////////////////////////////////////////////////////// + +// @brief Check for line (syntax check) + +///////////////////////////////////////////////////////////////////////////////////////// + +std::string LibCompiler::EncoderPowerPC::CheckLine(std::string line, std::string file) { + std::string err_str; + + if (line.empty() || LibCompiler::find_word(line, "extern_segment") || + LibCompiler::find_word(line, "public_segment") || line.find('#') != std::string::npos || + LibCompiler::find_word(line, ";")) { + if (line.find('#') != std::string::npos) { + line.erase(line.find('#')); + } else if (line.find(';') != std::string::npos) { + line.erase(line.find(';')); + } else { + /// does the line contains valid input? + if (!Detail::algorithm::is_valid_power64(line)) { + err_str = "Line contains non alphanumeric characters.\nhere -> "; + err_str += line; + } + } + + return err_str; + } + + if (!Detail::algorithm::is_valid_power64(line)) { + err_str = "Line contains non alphanumeric characters.\nhere -> "; + err_str += line; + + return err_str; + } + + // check for a valid instruction format. + + if (line.find(',') != std::string::npos) { + if (line.find(',') + 1 == line.size()) { + err_str += "\nInstruction lacks right register, here -> "; + err_str += line.substr(line.find(',')); + + return err_str; + } else { + bool nothing_on_right = true; + + if (line.find(',') + 1 > line.size()) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; + + return err_str; + } + + auto substr = line.substr(line.find(',') + 1); + + for (auto& ch : substr) { + if (ch != ' ' && ch != '\t') { + nothing_on_right = false; + } + } + + // this means we found nothing after that ',' . + if (nothing_on_right) { + err_str += "\nInstruction not complete, here -> "; + err_str += line; + + return err_str; + } + } + } + + // these do take an argument. + std::vector operands_inst = {"stw", "li"}; + + // these don't. + std::vector filter_inst = {"blr", "bl", "sc"}; + + for (auto& opcode_risc : kOpcodesPowerPC) { + if (LibCompiler::find_word(line, opcode_risc.name)) { + for (auto& op : operands_inst) { + // if only the instruction was found. + if (line == op) { + err_str += "\nMalformed "; + err_str += op; + err_str += " instruction, here -> "; + err_str += line; + } + } + + // if it is like that -> addr1, 0x0 + if (auto it = std::find(filter_inst.begin(), filter_inst.end(), opcode_risc.name); + it == filter_inst.cend()) { + if (LibCompiler::find_word(line, opcode_risc.name)) { + if (!isspace(line[line.find(opcode_risc.name) + strlen(opcode_risc.name)])) { + err_str += "\nMissing space between "; + err_str += opcode_risc.name; + err_str += " and operands.\nhere -> "; + err_str += line; + } + } + } + + return err_str; + } + } + + err_str += "Unrecognized instruction: " + line; + + return err_str; +} + +bool LibCompiler::EncoderPowerPC::WriteNumber(const std::size_t& pos, std::string& jump_label) { + if (!isdigit(jump_label[pos])) return false; + + switch (jump_label[pos + 1]) { + case 'x': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16); !res) { + if (errno != 0) { + Detail::print_error("invalid hex number: " + jump_label, "LibCompiler"); + throw std::runtime_error("invalid_hex"); + } + } + + LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 16)); + + for (char& i : num.number) { + kBytes.push_back(i); + } + + if (kVerbose) { + kStdOut << "AssemblerPower: found a base 16 number here: " << jump_label.substr(pos) + << "\n"; + } + + return true; + } + case 'b': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2); !res) { + if (errno != 0) { + Detail::print_error("invalid binary number: " + jump_label, "LibCompiler"); + throw std::runtime_error("invalid_bin"); + } + } + + LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 2)); + + if (kVerbose) { + kStdOut << "AssemblerPower: found a base 2 number here: " << jump_label.substr(pos) << "\n"; + } + + for (char& i : num.number) { + kBytes.push_back(i); + } + + return true; + } + case 'o': { + if (auto res = strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7); !res) { + if (errno != 0) { + Detail::print_error("invalid octal number: " + jump_label, "LibCompiler"); + throw std::runtime_error("invalid_octal"); + } + } + + LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos + 2).c_str(), nullptr, 7)); + + if (kVerbose) { + kStdOut << "AssemblerPower: found a base 8 number here: " << jump_label.substr(pos) << "\n"; + } + + for (char& i : num.number) { + kBytes.push_back(i); + } + + return true; + } + default: { + break; + } + } + + /* check for errno and stuff like that */ + if (auto res = strtol(jump_label.substr(pos).c_str(), nullptr, 10); !res) { + if (errno != 0) { + return false; + } + } + + LibCompiler::NumberCast64 num(strtol(jump_label.substr(pos).c_str(), nullptr, 10)); + + for (char& i : num.number) { + kBytes.push_back(i); + } + + if (kVerbose) { + kStdOut << "AssemblerPower: found a base 10 number here: " << jump_label.substr(pos) << "\n"; + } + + return true; +} + +///////////////////////////////////////////////////////////////////////////////////////// + +/// @brief Read and write an instruction to the output array. + +///////////////////////////////////////////////////////////////////////////////////////// + +bool LibCompiler::EncoderPowerPC::WriteLine(std::string line, std::string file) { + if (LibCompiler::find_word(line, "public_segment")) return false; + if (!Detail::algorithm::is_valid_power64(line)) return false; + + for (auto& opcode_risc : kOpcodesPowerPC) { + // strict check here + if (LibCompiler::find_word(line, opcode_risc.name)) { + std::string name(opcode_risc.name); + std::string jump_label, cpy_jump_label; + std::vector found_registers_index; + + // check funct7 type. + switch (opcode_risc.ops->type) { + default: { + NumberCast32 num(opcode_risc.opcode); + + for (auto ch : num.number) { + kBytes.emplace_back(ch); + } + break; + } + case BADDR: + case PCREL: { + auto num = GetNumber32(line, name); + + kBytes.emplace_back(num.number[0]); + kBytes.emplace_back(num.number[1]); + kBytes.emplace_back(num.number[2]); + kBytes.emplace_back(0x48); + + break; + } + /// General purpose, float, vector operations. Everything that involve + /// registers. + case G0REG: + case FREG: + case VREG: + case GREG: { + // \brief how many registers we found. + std::size_t found_some_count = 0UL; + std::size_t register_count = 0UL; + std::string opcodeName = opcode_risc.name; + std::size_t register_sum = 0; + + NumberCast64 num(opcode_risc.opcode); + + for (size_t line_index = 0UL; line_index < line.size(); line_index++) { + if (line[line_index] == kAsmRegisterPrefix[0] && isdigit(line[line_index + 1])) { + std::string register_syntax = kAsmRegisterPrefix; + register_syntax += line[line_index + 1]; + + if (isdigit(line[line_index + 2])) register_syntax += line[line_index + 2]; + + std::string reg_str; + reg_str += line[line_index + 1]; + + if (isdigit(line[line_index + 2])) reg_str += line[line_index + 2]; + + // it ranges from r0 to r19 + // something like r190 doesn't exist in the instruction set. + if (isdigit(line[line_index + 3]) && isdigit(line[line_index + 2])) { + reg_str += line[line_index + 3]; + Detail::print_error("invalid register index, r" + reg_str + + "\nnote: The POWER accepts registers from r0 to r32.", + file); + throw std::runtime_error("invalid_register_index"); + } + + // finally cast to a size_t + std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10); + + if (reg_index > kAsmRegisterLimit) { + Detail::print_error("invalid register index, r" + reg_str, file); + throw std::runtime_error("invalid_register_index"); + } + + if (opcodeName == "li") { + char numIndex = 0; + + for (size_t i = 0; i != reg_index; i++) { + numIndex += 0x20; + } + + auto num = GetNumber32(line, reg_str); + + kBytes.push_back(num.number[0]); + kBytes.push_back(num.number[1]); + kBytes.push_back(numIndex); + kBytes.push_back(0x38); + + // check if bigger than two. + for (size_t i = 2; i < 4; i++) { + if (num.number[i] > 0) { + Detail::print_warning("number overflow on li operation.", file); + break; + } + } + + break; + } + + if ((opcodeName[0] == 's' && opcodeName[1] == 't')) { + if (register_sum == 0) { + for (size_t indexReg = 0UL; indexReg < reg_index; ++indexReg) { + register_sum += 0x20; + } + } else { + register_sum += reg_index; + } + } + + if (opcodeName == "mr") { + switch (register_count) { + case 0: { + kBytes.push_back(0x78); + + char numIndex = 0x3; + + for (size_t i = 0; i != reg_index; i++) { + numIndex += 0x8; + } + + kBytes.push_back(numIndex); + + break; + } + case 1: { + char numIndex = 0x1; + + for (size_t i = 0; i != reg_index; i++) { + numIndex += 0x20; + } + + for (size_t i = 0; i != reg_index; i++) { + kBytes[kBytes.size() - 1] += 0x8; + } + + kBytes[kBytes.size() - 1] -= 0x8; + + kBytes.push_back(numIndex); + + if (reg_index >= 10 && reg_index < 20) + kBytes.push_back(0x7d); + else if (reg_index >= 20 && reg_index < 30) + kBytes.push_back(0x7e); + else if (reg_index >= 30) + kBytes.push_back(0x7f); + else + kBytes.push_back(0x7c); + + break; + } + default: + break; + } + + ++register_count; + ++found_some_count; + } + + if (opcodeName == "addi") { + if (found_some_count == 2 || found_some_count == 0) + kBytes.emplace_back(reg_index); + else if (found_some_count == 1) + kBytes.emplace_back(0x00); + + ++found_some_count; + + if (found_some_count > 3) { + Detail::print_error("Too much registers. -> " + line, file); + throw std::runtime_error("too_much_regs"); + } + } + + if (opcodeName.find("cmp") != std::string::npos) { + ++found_some_count; + + if (found_some_count > 3) { + Detail::print_error("Too much registers. -> " + line, file); + throw std::runtime_error("too_much_regs"); + } + } + + if (opcodeName.find("mf") != std::string::npos || + opcodeName.find("mt") != std::string::npos) { + char numIndex = 0; + + for (size_t i = 0; i != reg_index; i++) { + numIndex += 0x20; + } + + num.number[2] += numIndex; + + ++found_some_count; + + if (found_some_count > 1) { + Detail::print_error("Too much registers. -> " + line, file); + throw std::runtime_error("too_much_regs"); + } + + if (kVerbose) { + kStdOut << "AssemblerPower: Found register: " << register_syntax << "\n"; + kStdOut << "AssemblerPower: Amount of registers in instruction: " + << found_some_count << "\n"; + } + + if (reg_index >= 10 && reg_index < 20) + num.number[3] = 0x7d; + else if (reg_index >= 20 && reg_index < 30) + num.number[3] = 0x7e; + else if (reg_index >= 30) + num.number[3] = 0x7f; + else + num.number[3] = 0x7c; + + for (auto ch : num.number) { + kBytes.emplace_back(ch); + } + } + + found_registers_index.push_back(reg_index); + } + } + + if (opcodeName == "addi") { + kBytes.emplace_back(0x38); + } + + if (opcodeName.find("cmp") != std::string::npos) { + char rightReg = 0x0; + + for (size_t i = 0; i != found_registers_index[1]; i++) { + rightReg += 0x08; + } + + kBytes.emplace_back(0x00); + kBytes.emplace_back(rightReg); + kBytes.emplace_back(found_registers_index[0]); + kBytes.emplace_back(0x7c); + } + + if ((opcodeName[0] == 's' && opcodeName[1] == 't')) { + size_t offset = 0UL; + + if (line.find('+') != std::string::npos) { + auto number = GetNumber32(line.substr(line.find("+")), "+"); + offset = number.raw; + } + + kBytes.push_back(offset); + kBytes.push_back(0x00); + kBytes.push_back(register_sum); + + kBytes.emplace_back(0x90); + } + + if (opcodeName == "mr") { + if (register_count == 1) { + Detail::print_error("Too few registers. -> " + line, file); + throw std::runtime_error("too_few_registers"); + } + } + + // we're not in immediate addressing, reg to reg. + if (opcode_risc.ops->type != GREG) { + // remember! register to register! + if (found_some_count == 1) { + Detail::print_error( + "Unrecognized register found.\ntip: each AssemblerPower register " + "starts with 'r'.\nline: " + + line, + file); + + throw std::runtime_error("not_a_register"); + } + } + + if (found_some_count < 1 && name[0] != 'l' && name[0] != 's') { + Detail::print_error("invalid combination of opcode and registers.\nline: " + line, + file); + throw std::runtime_error("invalid_comb_op_reg"); + } + + break; + } + } + + kOrigin += cPowerIPAlignment; + break; + } + } + + return true; +} + +// Last rev 13-1-24 -- cgit v1.2.3 From 35ac989886dcab70ff4ba6bc6a1359d1290560ad Mon Sep 17 00:00:00 2001 From: Amlal Date: Thu, 1 May 2025 08:35:38 +0200 Subject: ld64: Make linker more robust, and extend PEF to version 4. Signed-off-by: Amlal --- dev/LibCompiler/Detail/ClUtils.h | 8 ++ dev/LibCompiler/PEF.h | 10 +- dev/LibCompiler/src/Assembler32x0.cc | 1 + dev/LibCompiler/src/Assembler64x0.cc | 2 + dev/LibCompiler/src/AssemblerAMD64.cc | 2 + dev/LibCompiler/src/AssemblerARM64.cc | 2 + dev/LibCompiler/src/AssemblerPowerPC.cc | 2 + dev/LibCompiler/src/CCompiler64x0.cc | 5 +- dev/LibCompiler/src/CCompilerARM64.cc | 5 +- dev/LibCompiler/src/CCompilerPower64.cc | 5 +- dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc | 10 +- .../src/CPlusPlusCompilerPreProcessor.cc | 9 +- dev/LibCompiler/src/DynamicLinkerPEF.cc | 137 ++++++++++++--------- 13 files changed, 120 insertions(+), 78 deletions(-) (limited to 'dev/LibCompiler/src/AssemblerPowerPC.cc') diff --git a/dev/LibCompiler/Detail/ClUtils.h b/dev/LibCompiler/Detail/ClUtils.h index 1f31be7..224e4d3 100644 --- a/dev/LibCompiler/Detail/ClUtils.h +++ b/dev/LibCompiler/Detail/ClUtils.h @@ -9,6 +9,7 @@ #include #include #include +#include #define kZero64Section ".zero64" #define kCode64Section ".code64" @@ -47,4 +48,11 @@ inline void print_warning(std::string reason, std::string file) noexcept { kStdOut << kYellow << "drv: " << kWhite << reason << kBlank << std::endl; } + +/// @internal +inline void segfault_handler(std::int32_t _) { + pfd::notify("NeKernel Compiler Driver System", + "Driver just crashed, please report this to the developers."); + std::exit(LIBCOMPILER_EXEC_ERROR); +} } // namespace Detail \ No newline at end of file diff --git a/dev/LibCompiler/PEF.h b/dev/LibCompiler/PEF.h index f32d830..6e8d288 100644 --- a/dev/LibCompiler/PEF.h +++ b/dev/LibCompiler/PEF.h @@ -31,7 +31,7 @@ #define kPefMagicLen (5) -#define kPefVersion (3) +#define kPefVersion (4) #define kPefNameLen (255) #define kPefBaseOrigin (0x40000000) @@ -53,7 +53,7 @@ enum { }; enum { - kPefSubArchAMD, + kPefSubArchAMD = 200, kPefSubArchIntel, kPefSubArchARM, kPefSubArchGeneric, @@ -61,7 +61,7 @@ enum { }; enum { - kPefKindExec = 1, /* .o */ + kPefKindExec = 1, /* .exec */ kPefKindDylib = 2, /* .dylib */ kPefKindObject = 4, /* .obj */ kPefKindDebug = 5, /* .dbg */ @@ -72,7 +72,7 @@ enum { /* PEF container */ typedef struct PEFContainer final { CharType Magic[kPefMagicLen]; - UInt32 Linker; + UInt32 Linker; /* Linker used to link executable */ UInt32 Version; UInt32 Kind; UInt32 Abi; @@ -81,6 +81,7 @@ typedef struct PEFContainer final { UIntPtr Start; /* Origin of code */ SizeType HdrSz; /* Size of header */ SizeType Count; /* container header count */ + UInt32 Checksum; /* Whole binary checksum */ } PACKED PEFContainer, *PEFContainerPtr; /* First PEFCommandHeader starts after PEFContainer */ @@ -95,6 +96,7 @@ typedef struct PEFCommandHeader final { UInt32 Flags; /* container flags */ UInt16 Kind; /* container kind */ UIntPtr Offset; /* file offset */ + UIntPtr VMAddress; /* VM offset */ SizeType Size; /* file size */ } PACKED PEFCommandHeader, *PEFCommandHeaderPtr; diff --git a/dev/LibCompiler/src/Assembler32x0.cc b/dev/LibCompiler/src/Assembler32x0.cc index ac24946..a5a435c 100644 --- a/dev/LibCompiler/src/Assembler32x0.cc +++ b/dev/LibCompiler/src/Assembler32x0.cc @@ -45,5 +45,6 @@ ///////////////////////////////////////////////////////////////////////////////////////// LIBCOMPILER_MODULE(NEAssemblerMain32000) { + return 0; } diff --git a/dev/LibCompiler/src/Assembler64x0.cc b/dev/LibCompiler/src/Assembler64x0.cc index 6d4d31a..4707be2 100644 --- a/dev/LibCompiler/src/Assembler64x0.cc +++ b/dev/LibCompiler/src/Assembler64x0.cc @@ -67,6 +67,8 @@ static bool asm_read_attributes(std::string line); ///////////////////////////////////////////////////////////////////////////////////////// LIBCOMPILER_MODULE(AssemblerMain64x0) { + ::signal(SIGSEGV, Detail::segfault_handler); + for (size_t i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) { diff --git a/dev/LibCompiler/src/AssemblerAMD64.cc b/dev/LibCompiler/src/AssemblerAMD64.cc index f8772b8..72e8015 100644 --- a/dev/LibCompiler/src/AssemblerAMD64.cc +++ b/dev/LibCompiler/src/AssemblerAMD64.cc @@ -88,6 +88,8 @@ static bool asm_read_attributes(std::string line); LIBCOMPILER_MODULE(AssemblerMainAMD64) { //////////////// CPU OPCODES BEGIN //////////////// + ::signal(SIGSEGV, Detail::segfault_handler); + std::string opcodes_jump[kJumpLimit] = {"ja", "jae", "jb", "jbe", "jc", "je", "jg", "jge", "jl", "jle", "jna", "jnae", "jnb", "jnbe", "jnc", "jne", "jng", "jnge", "jnl", "jnle", "jno", "jnp", "jns", "jnz", diff --git a/dev/LibCompiler/src/AssemblerARM64.cc b/dev/LibCompiler/src/AssemblerARM64.cc index eb3e915..ab2c89e 100644 --- a/dev/LibCompiler/src/AssemblerARM64.cc +++ b/dev/LibCompiler/src/AssemblerARM64.cc @@ -74,6 +74,8 @@ static bool asm_read_attributes(std::string line); ///////////////////////////////////////////////////////////////////////////////////////// LIBCOMPILER_MODULE(AssemblerMainARM64) { + ::signal(SIGSEGV, Detail::segfault_handler); + for (size_t i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) { diff --git a/dev/LibCompiler/src/AssemblerPowerPC.cc b/dev/LibCompiler/src/AssemblerPowerPC.cc index ffe5c6a..bd44e6e 100644 --- a/dev/LibCompiler/src/AssemblerPowerPC.cc +++ b/dev/LibCompiler/src/AssemblerPowerPC.cc @@ -74,6 +74,8 @@ static bool asm_read_attributes(std::string line); ///////////////////////////////////////////////////////////////////////////////////////// LIBCOMPILER_MODULE(AssemblerMainPower64) { + ::signal(SIGSEGV, Detail::segfault_handler); + for (size_t i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) { diff --git a/dev/LibCompiler/src/CCompiler64x0.cc b/dev/LibCompiler/src/CCompiler64x0.cc index 6fa05fb..c43abfe 100644 --- a/dev/LibCompiler/src/CCompiler64x0.cc +++ b/dev/LibCompiler/src/CCompiler64x0.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -86,9 +87,7 @@ struct CompilerState final { } // namespace Detail static Detail::CompilerState kState; -static SizeType kErrorLimit = 100; static std::string kIfFunction = ""; -static Int32 kAcceptableErrors = 0; namespace Detail { /// @brief prints an error into stdout. @@ -1201,6 +1200,8 @@ static void cc_print_help() { #define kExt ".c" LIBCOMPILER_MODULE(NeOSCompilerCLang64x0) { + ::signal(SIGSEGV, Detail::segfault_handler); + kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); diff --git a/dev/LibCompiler/src/CCompilerARM64.cc b/dev/LibCompiler/src/CCompilerARM64.cc index b2f36e9..26867f1 100644 --- a/dev/LibCompiler/src/CCompilerARM64.cc +++ b/dev/LibCompiler/src/CCompilerARM64.cc @@ -13,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -86,9 +87,7 @@ struct CompilerState final { } // namespace Detail static Detail::CompilerState kState; -static SizeType kErrorLimit = 100; static std::string kIfFunction = ""; -static Int32 kAcceptableErrors = 0; namespace Detail { /// @brief prints an error into stdout. @@ -1201,6 +1200,8 @@ static void cc_print_help() { #define kCExtension ".c" LIBCOMPILER_MODULE(NeOSCompilerCLangARM64) { + ::signal(SIGSEGV, Detail::segfault_handler); + kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); diff --git a/dev/LibCompiler/src/CCompilerPower64.cc b/dev/LibCompiler/src/CCompilerPower64.cc index ee9c5a4..f10aa79 100644 --- a/dev/LibCompiler/src/CCompilerPower64.cc +++ b/dev/LibCompiler/src/CCompilerPower64.cc @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -77,9 +78,7 @@ struct CompilerState final { } // namespace Detail static Detail::CompilerState kState; -static SizeType kErrorLimit = 100; static std::string kIfFunction = ""; -static Int32 kAcceptableErrors = 0; namespace Detail { /// @brief prints an error into stdout. @@ -1220,6 +1219,8 @@ static void cc_print_help() { #define kExt ".c" LIBCOMPILER_MODULE(NeOSCompilerCLangPowerPC) { + ::signal(SIGSEGV, Detail::segfault_handler); + kCompilerTypes.push_back({.fName = "void", .fValue = "void"}); kCompilerTypes.push_back({.fName = "char", .fValue = "byte"}); kCompilerTypes.push_back({.fName = "short", .fValue = "hword"}); diff --git a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc index 8597d41..b4725a4 100644 --- a/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc +++ b/dev/LibCompiler/src/CPlusPlusCompilerAMD64.cc @@ -20,7 +20,6 @@ #include #include #include -#include #include @@ -50,13 +49,6 @@ ///////////////////////////////////// -/// @internal -static void cxxdrv_chaos_handler(std::int32_t _) { - pfd::notify("NeKernel C++ Compiler Driver", - "CxxDrv just crashed, please report this to the developers."); - std::exit(LIBCOMPILER_EXEC_ERROR); -} - /// @internal namespace Detail { std::filesystem::path expand_home(const std::filesystem::path& p) { @@ -939,7 +931,7 @@ LIBCOMPILER_MODULE(CompilerCPlusPlusAMD64) { kFactory.Mount(new AssemblyCPlusPlusInterface()); kCompilerFrontend = new CompilerFrontendCPlusPlus(); - ::signal(SIGSEGV, cxxdrv_chaos_handler); + ::signal(SIGSEGV, Detail::segfault_handler); for (auto index = 1UL; index < argc; ++index) { if (argv[index][0] == '-') { diff --git a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc b/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc index d2194a8..5d035da 100644 --- a/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc +++ b/dev/LibCompiler/src/CPlusPlusCompilerPreProcessor.cc @@ -751,6 +751,13 @@ LIBCOMPILER_MODULE(CPlusPlusPreprocessorMain) { kMacros.push_back(macro_unreachable); + Detail::bpp_macro macro_unused; + + macro_unreachable.fName = "__unused"; + macro_unreachable.fValue = "__libcompiler_unused"; + + kMacros.push_back(macro_unused); + Detail::bpp_macro macro_0; macro_0.fName = "__false"; @@ -784,7 +791,7 @@ LIBCOMPILER_MODULE(CPlusPlusPreprocessorMain) { kMacros.push_back(macro_size_t); macro_size_t.fName = "__UINTPTR_TYPE__"; - macro_size_t.fValue = "unsigned int"; + macro_size_t.fValue = "unsigned long long int"; kMacros.push_back(macro_size_t); diff --git a/dev/LibCompiler/src/DynamicLinkerPEF.cc b/dev/LibCompiler/src/DynamicLinkerPEF.cc index fb2403f..0def365 100644 --- a/dev/LibCompiler/src/DynamicLinkerPEF.cc +++ b/dev/LibCompiler/src/DynamicLinkerPEF.cc @@ -37,6 +37,12 @@ //! Format header. #include +//! LibCompiler utils. +#include + +//! I/O stream from std c++ +#include + #define kLinkerVersionStr \ "NeKernel 64-Bit Linker (Preferred Executable Format) {}, (c) Amlal El Mahrouss " \ "2024-2025 " \ @@ -48,18 +54,18 @@ #define kPefNoCpu (0U) #define kPefNoSubCpu (0U) -#define kStdOut (std::cout << "\e[0;31m" << "ld64: " << "\e[0;97m") - #define kLinkerDefaultOrigin kPefBaseOrigin #define kLinkerId (0x5046FF) #define kLinkerAbiContainer "__PEFContainer:ABI:" #define kPrintF printf -#define kLinkerSplash() kStdOut << std::format(kLinkerVersionStr, kDistVersion) +#define kLinkerSplash() kOutCon << std::format(kLinkerVersionStr, kDistVersion) /// @brief PEF stack size symbol. #define kLinkerStackSizeSymbol "__PEFSizeOfReserveStack" +#define kOutCon (std::cout << "\e[0;31m" << "ld64: " << "\e[0;97m") + namespace Detail { struct DynamicLinkerBlob final { std::vector mBlob{}; // PEF code/bss/data blob. @@ -68,19 +74,19 @@ struct DynamicLinkerBlob final { } // namespace Detail enum { + kABITypeNull = 0, kABITypeStart = 0x1010, /* Invalid ABI start of ABI list. */ kABITypeNE = 0x5046, /* PF (NeKernel's PEF ABI) */ kABITypeInvalid = 0xFFFF, }; -static LibCompiler::String kOutput = "a.out"; +static LibCompiler::String kOutput = "a" kPefExt; static Int32 kAbi = kABITypeNE; 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 CharType* kLdDefineSymbol = ":UndefinedSymbol:"; @@ -90,14 +96,13 @@ static const CharType* kLdDynamicSym = ":RuntimeSymbol:"; static std::vector kObjectList; static std::vector kObjectBytes; -static uintptr_t kMIBCount = 8; -static uintptr_t kByteCount = 1024; - /// @brief NE 64-bit Linker. /// @note This linker is made for PEF executable, thus NE based OSes. LIBCOMPILER_MODULE(DynamicLinker64PEF) { bool is_executable = true; + ::signal(SIGSEGV, Detail::segfault_handler); + /** * @brief parse flags and trigger options. */ @@ -105,18 +110,18 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (StringCompare(argv[linker_arg], "-help") == 0) { kLinkerSplash(); - kStdOut << "-version: Show linker version.\n"; - kStdOut << "-help: Show linker help.\n"; - kStdOut << "-ld-verbose: Enable linker trace.\n"; - kStdOut << "-dylib: Output as a Dynamic PEF.\n"; - kStdOut << "-fat: Output as a FAT PEF.\n"; - kStdOut << "-32k: Output as a 32x0 PEF.\n"; - kStdOut << "-64k: Output as a 64x0 PEF.\n"; - kStdOut << "-amd64: Output as a AMD64 PEF.\n"; - kStdOut << "-rv64: Output as a RISC-V PEF.\n"; - kStdOut << "-power64: Output as a POWER PEF.\n"; - kStdOut << "-arm64: Output as a ARM64 PEF.\n"; - kStdOut << "-output: Select the output file name.\n"; + kOutCon << "-version: Show linker version.\n"; + kOutCon << "-help: Show linker help.\n"; + kOutCon << "-ld-verbose: Enable linker trace.\n"; + kOutCon << "-dylib: Output as a Dynamic PEF.\n"; + kOutCon << "-fat: Output as a FAT PEF.\n"; + kOutCon << "-32k: Output as a 32x0 PEF.\n"; + kOutCon << "-64k: Output as a 64x0 PEF.\n"; + kOutCon << "-amd64: Output as a AMD64 PEF.\n"; + kOutCon << "-rv64: Output as a RISC-V PEF.\n"; + kOutCon << "-power64: Output as a POWER PEF.\n"; + kOutCon << "-arm64: Output as a ARM64 PEF.\n"; + kOutCon << "-output: Select the output file name.\n"; return EXIT_SUCCESS; } else if (StringCompare(argv[linker_arg], "-version") == 0) { @@ -176,7 +181,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { continue; } else { if (argv[linker_arg][0] == '-') { - kStdOut << "unknown flag: " << argv[linker_arg] << "\n"; + kOutCon << "unknown flag: " << argv[linker_arg] << "\n"; return EXIT_FAILURE; } @@ -187,10 +192,10 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { } if (kOutput.empty()) { - kStdOut << "no output filename set." << std::endl; + kOutCon << "no output filename set." << std::endl; return LIBCOMPILER_EXEC_ERROR; } else if (kObjectList.empty()) { - kStdOut << "no input files." << std::endl; + kOutCon << "no input files." << std::endl; return LIBCOMPILER_EXEC_ERROR; } else { namespace FS = std::filesystem; @@ -200,7 +205,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (!FS::exists(obj)) { // if filesystem doesn't find file // -> throw error. - kStdOut << "no such file: " << obj << std::endl; + kOutCon << "no such file: " << obj << std::endl; return LIBCOMPILER_EXEC_ERROR; } } @@ -208,7 +213,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { // PEF expects a valid target architecture when outputing a binary. if (kArch == 0) { - kStdOut << "no target architecture set, can't continue." << std::endl; + kOutCon << "no target architecture set, can't continue." << std::endl; return LIBCOMPILER_EXEC_ERROR; } @@ -230,12 +235,13 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { // specify the start address, can be 0x10000 pef_container.Start = kLinkerDefaultOrigin; pef_container.HdrSz = sizeof(LibCompiler::PEFContainer); + pef_container.Checksum = 0UL; std::ofstream output_fc(kOutput, std::ofstream::binary); if (output_fc.bad()) { if (kVerbose) { - kStdOut << "error: " << strerror(errno) << "\n"; + kOutCon << "error: " << strerror(errno) << "\n"; } return LIBCOMPILER_FILE_NOT_FOUND; @@ -259,12 +265,12 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { 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 (kVerbose) kOutCon << "Info: is this a FAT binary? : "; if (!kFatBinaryEnable) { - if (kVerbose) kStdOut << "No.\n"; + if (kVerbose) kOutCon << "No.\n"; - kStdOut << "error: object " << objectFile + kOutCon << "Error: object " << objectFile << " is a different kind of architecture and output isn't " "treated as a FAT binary." << std::endl; @@ -272,7 +278,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { return LIBCOMPILER_FAT_ERROR; } else { if (kVerbose) { - kStdOut << "Architecture matches what we expect.\n"; + kOutCon << "Architecture matches what we expect.\n"; } } } @@ -281,20 +287,22 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { archs |= ae_header.fArch; std::size_t cnt = ae_header.fCount; - if (kVerbose) kStdOut << "object header found, record count: " << cnt << "\n"; + if (kVerbose) kOutCon << "Object header found, record count: " << cnt << "\n"; pef_container.Count = cnt; char_type* raw_ae_records = new char_type[cnt * sizeof(LibCompiler::AERecordHeader)]; if (!raw_ae_records) { - if (kVerbose) kStdOut << "allocation failure for records of n: " << cnt << "\n"; + if (kVerbose) kOutCon << "Allocation failure for records of count: " << cnt << "\n"; } memset(raw_ae_records, 0, cnt * sizeof(LibCompiler::AERecordHeader)); auto* ae_records = reader_protocol.Read(raw_ae_records, cnt); + auto org = kLinkerDefaultOrigin; + 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; @@ -327,12 +335,15 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { 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.VMAddress = org; /// TODO: command_header.SubCpu = ae_header.fSubArch; + org += command_header.Size; + if (kVerbose) { - kStdOut << "Record: " << ae_records[ae_record_index].fName << " is marked.\n"; + kOutCon << "Record: " << ae_records[ae_record_index].fName << " is marked.\n"; - kStdOut << "Record offset: " << command_header.Offset << "\n"; + kOutCon << "Offset: " << command_header.Offset << "\n"; } command_headers.emplace_back(command_header); @@ -344,8 +355,6 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { 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)); @@ -358,7 +367,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { continue; } - kStdOut << "Not an object container: " << objectFile << std::endl; + kOutCon << "Not an container: " << objectFile << std::endl; // don't continue, it is a fatal error. return LIBCOMPILER_EXEC_ERROR; } @@ -368,7 +377,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { output_fc << pef_container; if (kVerbose) { - kStdOut << "Wrote container header.\n"; + kOutCon << "Wrote container to: " << output_fc.tellp() << ".\n"; } output_fc.seekp(std::streamsize(pef_container.HdrSz)); @@ -382,7 +391,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { // 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 (kVerbose) kOutCon << "Found undefined symbol: " << command_hdr.Name << "\n"; if (auto it = std::find(not_found.begin(), not_found.end(), LibCompiler::String(command_hdr.Name)); @@ -426,7 +435,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { not_found.erase(it); - if (kVerbose) kStdOut << "found symbol: " << command_hdr.Name << "\n"; + if (kVerbose) kOutCon << "Found symbol: " << command_hdr.Name << "\n"; break; } @@ -441,11 +450,11 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (!kStartFound && is_executable) { if (kVerbose) - kStdOut << "undefined entrypoint: " << kPefStart + kOutCon << "Undefined entrypoint: " << kPefStart << ", you may have forget to link " - "against your compiler's runtime library.\n"; + "against the C++ runtime library.\n"; - kStdOut << "undefined entrypoint " << kPefStart << " for executable: " << kOutput << "\n"; + kOutCon << "Undefined entrypoint " << kPefStart << " for executable: " << kOutput << "\n"; } // step 4: write all PEF commands. @@ -481,11 +490,11 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { } case LibCompiler::kPefArch32000: case LibCompiler::kPefArch64000: { - abi += " ZWS"; + abi += "_NEP"; break; } default: { - abi += " IDK"; + abi += "_IDK"; break; } } @@ -538,10 +547,22 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { std::vector dupl_symbols; std::vector resolve_symbols; - constexpr Int32 cPaddingOffset = 16; + constexpr Int32 kPaddingOffset = 16; size_t previous_offset = - (command_headers.size() * sizeof(LibCompiler::PEFCommandHeader)) + cPaddingOffset; + (command_headers.size() * sizeof(LibCompiler::PEFCommandHeader)) + kPaddingOffset; + + LibCompiler::PEFCommandHeader end_exec_hdr; + + end_exec_hdr.Offset = output_fc.tellp(); + end_exec_hdr.Flags = LibCompiler::kPefLinkerID; + end_exec_hdr.Kind = LibCompiler::kPefZero; + + MemoryCopy(end_exec_hdr.Name, "Container:Exec:END", strlen("Container:Exec:END")); + + end_exec_hdr.Size = strlen(end_exec_hdr.Name); + + command_headers.push_back(end_exec_hdr); // Finally write down the command headers. // And check for any duplications @@ -581,9 +602,9 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { } if (kVerbose) { - kStdOut << "Command header name: " << name << "\n"; - kStdOut << "Real address of command header content: " - << command_headers[commandHeaderIndex].Offset << "\n"; + kOutCon << "Command name: " << name << "\n"; + kOutCon << "VMAddress of command content: " << command_headers[commandHeaderIndex].Offset + << "\n"; } output_fc << command_headers[commandHeaderIndex]; @@ -597,7 +618,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { LibCompiler::String(command_headers[sub_command_header_index].Name).find(kLdDynamicSym) == LibCompiler::String::npos) { if (kVerbose) { - kStdOut << "ignore :UndefinedSymbol: command header...\n"; + kOutCon << "Ignoring :UndefinedSymbol: headers...\n"; } // ignore :UndefinedSymbol: headers, they do not contain code. @@ -612,7 +633,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { dupl_symbols.emplace_back(command_hdr.Name); } - if (kVerbose) kStdOut << "found duplicate symbol: " << command_hdr.Name << "\n"; + if (kVerbose) kOutCon << "Found duplicate symbols of: " << command_hdr.Name << "\n"; kDuplicateSymbols = true; } @@ -621,7 +642,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (!dupl_symbols.empty()) { for (auto& symbol : dupl_symbols) { - kStdOut << "Multiple symbols of: " << symbol << " detected, cannot continue.\n"; + kOutCon << "Multiple symbols of: " << symbol << " detected, cannot continue.\n"; } return LIBCOMPILER_EXEC_ERROR; @@ -634,7 +655,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { } if (kVerbose) { - kStdOut << "wrote contents of: " << kOutput << "\n"; + kOutCon << "Wrote contents of: " << kOutput << "\n"; } // step 3: check if we have those symbols @@ -651,16 +672,16 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { if (!unreferenced_symbols.empty()) { for (auto& unreferenced_symbol : unreferenced_symbols) { - kStdOut << "undefined symbol " << unreferenced_symbol << "\n"; + kOutCon << "Undefined symbol " << unreferenced_symbol << "\n"; } return LIBCOMPILER_EXEC_ERROR; } - if (!kStartFound || kDuplicateSymbols && std::filesystem::exists(kOutput) || - !unreferenced_symbols.empty()) { + if ((!kStartFound || kDuplicateSymbols) && + (std::filesystem::exists(kOutput) || !unreferenced_symbols.empty())) { if (kVerbose) { - kStdOut << "file: " << kOutput << ", is corrupt, removing file...\n"; + kOutCon << "File: " << kOutput << ", is corrupt, removing file...\n"; } return LIBCOMPILER_EXEC_ERROR; -- cgit v1.2.3 From fb12b9730d78052f5cafbd84fbc9a830a22cec17 Mon Sep 17 00:00:00 2001 From: Amlal Date: Thu, 1 May 2025 08:50:44 +0200 Subject: dev, LibCompiler: format codebase. Signed-off-by: Amlal --- dev/LibCompiler/PEF.h | 8 ++++---- dev/LibCompiler/src/Assembler32x0.cc | 1 - dev/LibCompiler/src/Assembler64x0.cc | 2 +- dev/LibCompiler/src/AssemblerAMD64.cc | 2 +- dev/LibCompiler/src/AssemblerARM64.cc | 2 +- dev/LibCompiler/src/AssemblerPowerPC.cc | 2 +- dev/LibCompiler/src/CCompiler64x0.cc | 4 ++-- dev/LibCompiler/src/CCompilerARM64.cc | 4 ++-- dev/LibCompiler/src/CCompilerPower64.cc | 4 ++-- dev/LibCompiler/src/DynamicLinkerPEF.cc | 18 +++++++++--------- 10 files changed, 23 insertions(+), 24 deletions(-) (limited to 'dev/LibCompiler/src/AssemblerPowerPC.cc') diff --git a/dev/LibCompiler/PEF.h b/dev/LibCompiler/PEF.h index 6e8d288..fe6cfe1 100644 --- a/dev/LibCompiler/PEF.h +++ b/dev/LibCompiler/PEF.h @@ -77,10 +77,10 @@ typedef struct PEFContainer final { UInt32 Kind; UInt32 Abi; UInt32 Cpu; - UInt32 SubCpu; /* Cpu specific information */ - UIntPtr Start; /* Origin of code */ - SizeType HdrSz; /* Size of header */ - SizeType Count; /* container header count */ + UInt32 SubCpu; /* Cpu specific information */ + UIntPtr Start; /* Origin of code */ + SizeType HdrSz; /* Size of header */ + SizeType Count; /* container header count */ UInt32 Checksum; /* Whole binary checksum */ } PACKED PEFContainer, *PEFContainerPtr; diff --git a/dev/LibCompiler/src/Assembler32x0.cc b/dev/LibCompiler/src/Assembler32x0.cc index a5a435c..ac24946 100644 --- a/dev/LibCompiler/src/Assembler32x0.cc +++ b/dev/LibCompiler/src/Assembler32x0.cc @@ -45,6 +45,5 @@ ///////////////////////////////////////////////////////////////////////////////////////// LIBCOMPILER_MODULE(NEAssemblerMain32000) { - return 0; } diff --git a/dev/LibCompiler/src/Assembler64x0.cc b/dev/LibCompiler/src/Assembler64x0.cc index 4707be2..e1fa1b5 100644 --- a/dev/LibCompiler/src/Assembler64x0.cc +++ b/dev/LibCompiler/src/Assembler64x0.cc @@ -68,7 +68,7 @@ static bool asm_read_attributes(std::string line); LIBCOMPILER_MODULE(AssemblerMain64x0) { ::signal(SIGSEGV, Detail::segfault_handler); - + for (size_t i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) { diff --git a/dev/LibCompiler/src/AssemblerAMD64.cc b/dev/LibCompiler/src/AssemblerAMD64.cc index 72e8015..5e9a7cd 100644 --- a/dev/LibCompiler/src/AssemblerAMD64.cc +++ b/dev/LibCompiler/src/AssemblerAMD64.cc @@ -89,7 +89,7 @@ LIBCOMPILER_MODULE(AssemblerMainAMD64) { //////////////// CPU OPCODES BEGIN //////////////// ::signal(SIGSEGV, Detail::segfault_handler); - + std::string opcodes_jump[kJumpLimit] = {"ja", "jae", "jb", "jbe", "jc", "je", "jg", "jge", "jl", "jle", "jna", "jnae", "jnb", "jnbe", "jnc", "jne", "jng", "jnge", "jnl", "jnle", "jno", "jnp", "jns", "jnz", diff --git a/dev/LibCompiler/src/AssemblerARM64.cc b/dev/LibCompiler/src/AssemblerARM64.cc index ab2c89e..8686edb 100644 --- a/dev/LibCompiler/src/AssemblerARM64.cc +++ b/dev/LibCompiler/src/AssemblerARM64.cc @@ -75,7 +75,7 @@ static bool asm_read_attributes(std::string line); LIBCOMPILER_MODULE(AssemblerMainARM64) { ::signal(SIGSEGV, Detail::segfault_handler); - + for (size_t i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) { diff --git a/dev/LibCompiler/src/AssemblerPowerPC.cc b/dev/LibCompiler/src/AssemblerPowerPC.cc index bd44e6e..f2c3be3 100644 --- a/dev/LibCompiler/src/AssemblerPowerPC.cc +++ b/dev/LibCompiler/src/AssemblerPowerPC.cc @@ -75,7 +75,7 @@ static bool asm_read_attributes(std::string line); LIBCOMPILER_MODULE(AssemblerMainPower64) { ::signal(SIGSEGV, Detail::segfault_handler); - + for (size_t i = 1; i < argc; ++i) { if (argv[i][0] == '-') { if (strcmp(argv[i], "--ver") == 0 || strcmp(argv[i], "--v") == 0) { diff --git a/dev/LibCompiler/src/CCompiler64x0.cc b/dev/LibCompiler/src/CCompiler64x0.cc index c43abfe..c100e96 100644 --- a/dev/LibCompiler/src/CCompiler64x0.cc +++ b/dev/LibCompiler/src/CCompiler64x0.cc @@ -11,9 +11,9 @@ /// TODO: none #include +#include #include #include -#include #include #include #include @@ -87,7 +87,7 @@ struct CompilerState final { } // namespace Detail static Detail::CompilerState kState; -static std::string kIfFunction = ""; +static std::string kIfFunction = ""; namespace Detail { /// @brief prints an error into stdout. diff --git a/dev/LibCompiler/src/CCompilerARM64.cc b/dev/LibCompiler/src/CCompilerARM64.cc index 26867f1..a992349 100644 --- a/dev/LibCompiler/src/CCompilerARM64.cc +++ b/dev/LibCompiler/src/CCompilerARM64.cc @@ -11,9 +11,9 @@ /// TODO: none #include +#include #include #include -#include #include #include #include @@ -87,7 +87,7 @@ struct CompilerState final { } // namespace Detail static Detail::CompilerState kState; -static std::string kIfFunction = ""; +static std::string kIfFunction = ""; namespace Detail { /// @brief prints an error into stdout. diff --git a/dev/LibCompiler/src/CCompilerPower64.cc b/dev/LibCompiler/src/CCompilerPower64.cc index f10aa79..c65f575 100644 --- a/dev/LibCompiler/src/CCompilerPower64.cc +++ b/dev/LibCompiler/src/CCompilerPower64.cc @@ -8,9 +8,9 @@ */ #include +#include #include #include -#include #include #include #include @@ -78,7 +78,7 @@ struct CompilerState final { } // namespace Detail static Detail::CompilerState kState; -static std::string kIfFunction = ""; +static std::string kIfFunction = ""; namespace Detail { /// @brief prints an error into stdout. diff --git a/dev/LibCompiler/src/DynamicLinkerPEF.cc b/dev/LibCompiler/src/DynamicLinkerPEF.cc index 0def365..1b2418f 100644 --- a/dev/LibCompiler/src/DynamicLinkerPEF.cc +++ b/dev/LibCompiler/src/DynamicLinkerPEF.cc @@ -233,8 +233,8 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { pef_container.Version = kPefVersion; // specify the start address, can be 0x10000 - pef_container.Start = kLinkerDefaultOrigin; - pef_container.HdrSz = sizeof(LibCompiler::PEFContainer); + pef_container.Start = kLinkerDefaultOrigin; + pef_container.HdrSz = sizeof(LibCompiler::PEFContainer); pef_container.Checksum = 0UL; std::ofstream output_fc(kOutput, std::ofstream::binary); @@ -331,12 +331,12 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { } 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.VMAddress = org; /// TODO: - command_header.SubCpu = ae_header.fSubArch; + 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.VMAddress = org; /// TODO: + command_header.SubCpu = ae_header.fSubArch; org += command_header.Size; @@ -560,7 +560,7 @@ LIBCOMPILER_MODULE(DynamicLinker64PEF) { MemoryCopy(end_exec_hdr.Name, "Container:Exec:END", strlen("Container:Exec:END")); - end_exec_hdr.Size = strlen(end_exec_hdr.Name); + end_exec_hdr.Size = strlen(end_exec_hdr.Name); command_headers.push_back(end_exec_hdr); -- cgit v1.2.3