#include #include #include #include #include int write_elf(char* restrict file, size_t opcodes_len, char* restrict opcodes) { int error = 0; Elf64_Phdr header_program[] = { //{ // .p_type = PT_LOAD, // .p_flags = PF_R, // .p_offset = 0, /* Segment file offset */ // .p_vaddr = 0x400000, /* Segment virtual address */ // .p_paddr = 0x400000, /* Segment physical address */ // .p_filesz = 0xb0, /* Segment size in file */ // .p_memsz = 0xb0, /* Segment size in memory */ // .p_align = 0x1000, /* Segment alignment */ //}, { .p_type = PT_LOAD, .p_flags = PF_X | PF_R, .p_offset = 0x1000, /* Segment file offset */ .p_vaddr = 0x400000 + 0x1000, /* Segment virtual address */ .p_paddr = 0x400000 + 0x1000, /* Segment physical address */ .p_filesz = opcodes_len, /* Segment size in file */ .p_memsz = opcodes_len, /* Segment size in memory */ .p_align = 0x1, /* Segment alignment */ }, }; unsigned char string_header_table[] = {0, '.', 'i', 'n', 'i', 't', 0, '.', 's', 'h', 's', 't', 'r', 't', 'a', 'b', 0}; Elf64_Shdr header_section[] = { {0}, // NULL { // .init // Index in section header string table .sh_name = 1, .sh_type = SHT_PROGBITS, .sh_flags = SHF_ALLOC | SHF_EXECINSTR, .sh_addr = 0x401000, .sh_offset = 0x1000, .sh_size = opcodes_len, /* todo: deps on type */ .sh_link = 0, /* todo: deps on type */ .sh_info = 0, .sh_addralign = 4, .sh_entsize = 0, }, { // .shstrtab Section Header String Table // Index in section header string table .sh_name = 7, .sh_type = SHT_STRTAB, .sh_flags = 0, .sh_addr = 0x0, .sh_offset = 0x2000, .sh_size = sizeof(string_header_table) / sizeof(string_header_table[0]), /* todo: deps on type */ .sh_link = 0, /* todo: deps on type */ .sh_info = 0, .sh_addralign = 1, .sh_entsize = 0, }, }; Elf64_Ehdr header = { // memset(&header, 0, sizeof(Elf64_Ehdr)); .e_ident = {ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, ELFCLASS64, ELFDATA2LSB, EV_CURRENT, ELFOSABI_SYSV}, .e_type = ET_EXEC, .e_machine = EM_X86_64, .e_version = EV_CURRENT, // point to VIRTUAL address of _start .e_entry = 0x400000 + 0x1000, // Program header table offset .e_phoff = sizeof(Elf64_Ehdr), // Section header table offset .e_shoff = sizeof(Elf64_Ehdr) + sizeof(header_program), .e_flags = 0, .e_ehsize = sizeof(Elf64_Ehdr), .e_phentsize = sizeof(Elf64_Phdr), // If larger than PN_XNUM, then set to PN_XNUM and store real number in // sh_info of first program header entry .e_phnum = 1, .e_shentsize = sizeof(header_section[0]), // If larger than SHN_LORESERVE, then set to 0 and store real number in // sh_size of first section header entry .e_shnum = sizeof(header_section) / sizeof(header_section[0]), // If larger than SHN_LORESERVE, then set to SHN_XINDEX and store real // index // in sh_link of first section header entry // "Section Header string-table-index .e_shstrndx = 2, }; size_t bytes_written = 0; FILE* fd = fopen(file, "w"); fwrite(&header, sizeof(Elf64_Ehdr), 1, fd); fwrite(&header_program, sizeof(Elf64_Phdr), sizeof(header_program) / sizeof(header_program[0]), fd); fwrite(&header_section, sizeof(Elf64_Shdr), sizeof(header_section) / sizeof(header_section[0]), fd); fseek(fd, 0x1000, SEEK_SET); do { bytes_written += fwrite(opcodes, sizeof(char), opcodes_len, fd); } while (bytes_written != opcodes_len); fseek(fd, 0x2000, SEEK_SET); fwrite(string_header_table, sizeof(char), sizeof(string_header_table) / sizeof(string_header_table[0]), fd); error = fclose(fd); if (error) { err(EXIT_FAILURE, "no way"); } return 0; }