Line data Source code
1 : #include "fd_svm_elfgen.h" 2 : #include "../../../ballet/elf/fd_elf64.h" 3 : 4 : static char const shstrtab[] = "\0.text\0.rodata\0.shstrtab\0"; 5 6 : #define SHSTRTAB_OFF_TEXT 1 /* byte offset of ".text" in shstrtab */ 6 6 : #define SHSTRTAB_OFF_RODATA 7 /* byte offset of ".rodata" in shstrtab */ 7 6 : #define SHSTRTAB_OFF_SHSTR 15 /* byte offset of ".shstrtab" in shstrtab */ 8 : 9 : ulong 10 : fd_svm_elfgen_sz( ulong text_sz, 11 6 : ulong rodata_sz ) { 12 6 : ulong phdr_file_off = sizeof(fd_elf64_ehdr); 13 6 : ulong text_file_off = fd_ulong_align_up( phdr_file_off + sizeof(fd_elf64_phdr), 8UL ); 14 6 : ulong rodata_file_off = text_file_off + text_sz; 15 6 : ulong shstrtab_file_off = rodata_file_off + rodata_sz; 16 6 : ulong shdr_file_off = fd_ulong_align_up( shstrtab_file_off + sizeof(shstrtab), 8UL ); 17 6 : ulong total_sz = shdr_file_off + 4UL * sizeof(fd_elf64_shdr); 18 6 : return total_sz; 19 6 : } 20 : 21 : void 22 : fd_svm_elfgen( uchar * buf, 23 : ulong buf_sz, 24 : uchar const * text_data, 25 : ulong text_sz, 26 : uchar const * rodata, 27 6 : ulong rodata_sz ) { 28 6 : ulong phdr_file_off = sizeof(fd_elf64_ehdr); 29 6 : ulong text_file_off = fd_ulong_align_up( phdr_file_off + sizeof(fd_elf64_phdr), 8UL ); 30 6 : ulong rodata_file_off = text_file_off + text_sz; 31 6 : ulong segment_sz = text_sz + rodata_sz; 32 6 : ulong shstrtab_file_off = rodata_file_off + rodata_sz; 33 6 : ulong shdr_file_off = fd_ulong_align_up( shstrtab_file_off + sizeof(shstrtab), 8UL ); 34 6 : ulong total_sz = shdr_file_off + 4UL * sizeof(fd_elf64_shdr); 35 : 36 6 : FD_TEST( total_sz <= buf_sz ); 37 6 : memset( buf, 0, total_sz ); 38 : 39 6 : FD_STORE( fd_elf64_ehdr, buf, ((fd_elf64_ehdr) { 40 6 : .e_ident = { 0x7f,'E','L','F', FD_ELF_CLASS_64, FD_ELF_DATA_LE, 1, FD_ELF_OSABI_NONE }, 41 6 : .e_type = FD_ELF_ET_DYN, 42 6 : .e_machine = FD_ELF_EM_BPF, 43 6 : .e_version = 1, 44 6 : .e_entry = text_file_off, 45 6 : .e_phoff = phdr_file_off, 46 6 : .e_shoff = shdr_file_off, 47 6 : .e_flags = 0, 48 6 : .e_ehsize = sizeof(fd_elf64_ehdr), 49 6 : .e_phentsize = sizeof(fd_elf64_phdr), 50 6 : .e_phnum = 1, 51 6 : .e_shentsize = sizeof(fd_elf64_shdr), 52 6 : .e_shnum = 4, 53 6 : .e_shstrndx = 3 54 6 : }) ); 55 : 56 : /* Single PT_LOAD segment covering .text and .rodata */ 57 6 : fd_elf64_phdr * phdr = (fd_elf64_phdr *)(buf + phdr_file_off); 58 6 : phdr->p_type = FD_ELF_PT_LOAD; 59 6 : phdr->p_flags = 5; 60 6 : phdr->p_offset = text_file_off; 61 6 : phdr->p_vaddr = text_file_off; 62 6 : phdr->p_paddr = text_file_off; 63 6 : phdr->p_filesz = segment_sz; 64 6 : phdr->p_memsz = segment_sz; 65 6 : phdr->p_align = 8; 66 : 67 : /* Section 1: .text (sh_addr must equal sh_offset for the loader) */ 68 6 : fd_elf64_shdr * shdr_text = (fd_elf64_shdr *)(buf + shdr_file_off + sizeof(fd_elf64_shdr)); 69 6 : shdr_text->sh_name = SHSTRTAB_OFF_TEXT; 70 6 : shdr_text->sh_type = FD_ELF_SHT_PROGBITS; 71 6 : shdr_text->sh_flags = 0x6; 72 6 : shdr_text->sh_addr = text_file_off; 73 6 : shdr_text->sh_offset = text_file_off; 74 6 : shdr_text->sh_size = text_sz; 75 6 : shdr_text->sh_addralign = 8; 76 : 77 : /* Section 2: .rodata */ 78 6 : fd_elf64_shdr * shdr_ro = (fd_elf64_shdr *)(buf + shdr_file_off + 2UL * sizeof(fd_elf64_shdr)); 79 6 : shdr_ro->sh_name = SHSTRTAB_OFF_RODATA; 80 6 : shdr_ro->sh_type = FD_ELF_SHT_PROGBITS; 81 6 : shdr_ro->sh_flags = 0x2; 82 6 : shdr_ro->sh_addr = rodata_file_off; 83 6 : shdr_ro->sh_offset = rodata_file_off; 84 6 : shdr_ro->sh_size = rodata_sz; 85 6 : shdr_ro->sh_addralign = 1; 86 : 87 : /* Section 3: .shstrtab */ 88 6 : fd_elf64_shdr * shdr_strtab = (fd_elf64_shdr *)(buf + shdr_file_off + 3UL * sizeof(fd_elf64_shdr)); 89 6 : shdr_strtab->sh_name = SHSTRTAB_OFF_SHSTR; 90 6 : shdr_strtab->sh_type = FD_ELF_SHT_STRTAB; 91 6 : shdr_strtab->sh_offset = shstrtab_file_off; 92 6 : shdr_strtab->sh_size = sizeof(shstrtab); 93 6 : shdr_strtab->sh_addralign = 1; 94 : 95 6 : memcpy( buf + text_file_off, text_data, text_sz ); 96 6 : if( rodata_sz ) memcpy( buf + rodata_file_off, rodata, rodata_sz ); 97 6 : memcpy( buf + shstrtab_file_off, shstrtab, sizeof(shstrtab) ); 98 6 : }