diff options
Diffstat (limited to 'toolchain.old/akibabuilder/main.zig')
| -rw-r--r-- | toolchain.old/akibabuilder/main.zig | 119 |
1 files changed, 119 insertions, 0 deletions
diff --git a/toolchain.old/akibabuilder/main.zig b/toolchain.old/akibabuilder/main.zig new file mode 100644 index 0000000..8bd07fa --- /dev/null +++ b/toolchain.old/akibabuilder/main.zig @@ -0,0 +1,119 @@ +const std = @import("std"); + +// Akiba magic signature +const AKIBA_MAGIC = [8]u8{ 'A', 'K', 'I', 'B', 'A', 'E', 'L', 'F' }; +const AKIBA_VERSION: u32 = 1; + +// Executable types +const AKIBA_TYPE_CLI: u32 = 0; +const AKIBA_TYPE_GUI: u32 = 1; +const AKIBA_TYPE_SERVICE: u32 = 2; +const AKIBA_TYPE_LIBRARY: u32 = 3; + +// Akiba executable header (64 bytes) +const AkibaHeader = extern struct { + magic: [8]u8, + version: u32, + exec_type: u32, + elf_offset: u64, + elf_size: u64, + metadata_offset: u64, + metadata_size: u64, + entry_point: u64, + reserved: [16]u8, +}; + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + + const args = try std.process.argsAlloc(allocator); + defer std.process.argsFree(allocator, args); + + if (args.len < 3) { + std.debug.print("Usage: akibabuilder <input.elf> <output.akiba> [type]\n", .{}); + std.debug.print("Types: cli (default), gui, service, library\n", .{}); + return; + } + + const input_path = args[1]; + const output_path = args[2]; + const exec_type = if (args.len >= 4) parse_type(args[3]) else AKIBA_TYPE_CLI; + + try wrap_elf(allocator, input_path, output_path, exec_type); +} + +fn parse_type(type_str: []const u8) u32 { + if (std.mem.eql(u8, type_str, "gui")) return AKIBA_TYPE_GUI; + if (std.mem.eql(u8, type_str, "service")) return AKIBA_TYPE_SERVICE; + if (std.mem.eql(u8, type_str, "library")) return AKIBA_TYPE_LIBRARY; + return AKIBA_TYPE_CLI; +} + +fn wrap_elf(allocator: std.mem.Allocator, input_path: []const u8, output_path: []const u8, exec_type: u32) !void { + // Read ELF file + const elf_data = try std.fs.cwd().readFileAlloc(allocator, input_path, 10 * 1024 * 1024); + defer allocator.free(elf_data); + + std.debug.print("Read {d} bytes from {s}\n", .{ elf_data.len, input_path }); + + // Parse ELF to get entry point + const entry_point = try parse_elf_entry(elf_data); + std.debug.print("Entry point: 0x{X:0>16}\n", .{entry_point}); + + // Create Akiba header + const header = AkibaHeader{ + .magic = AKIBA_MAGIC, + .version = AKIBA_VERSION, + .exec_type = exec_type, + .elf_offset = @sizeOf(AkibaHeader), + .elf_size = elf_data.len, + .metadata_offset = 0, + .metadata_size = 0, + .entry_point = entry_point, + .reserved = [_]u8{0} ** 16, + }; + + // Write output file + const output_file = try std.fs.cwd().createFile(output_path, .{}); + defer output_file.close(); + + // Write header as bytes + const header_bytes = std.mem.asBytes(&header); + try output_file.writeAll(header_bytes); + + // Write ELF data + try output_file.writeAll(elf_data); + + std.debug.print("Created {s} ({d} bytes)\n", .{ output_path, header_bytes.len + elf_data.len }); + std.debug.print("Type: {s}\n", .{type_name(exec_type)}); +} + +fn parse_elf_entry(elf_data: []const u8) !u64 { + if (elf_data.len < 32) return error.TooSmall; + + // ELF magic check + if (elf_data[0] != 0x7F or elf_data[1] != 'E' or elf_data[2] != 'L' or elf_data[3] != 'F') { + return error.NotELF; + } + + // Check 64-bit + if (elf_data[4] != 2) { + return error.Not64Bit; + } + + // Entry point is at offset 24 for ELF64 + const entry_bytes = elf_data[24..32]; + return std.mem.readInt(u64, entry_bytes[0..8], .little); +} + +fn type_name(exec_type: u32) []const u8 { + return switch (exec_type) { + AKIBA_TYPE_CLI => "CLI", + AKIBA_TYPE_GUI => "GUI", + AKIBA_TYPE_SERVICE => "Service", + AKIBA_TYPE_LIBRARY => "Library", + else => "Unknown", + }; +} |
