Hi, Sorry I for some reason could not reply to the original thread here to follow up: https://www.mail-archive.com/elfutils-devel@sourceware.org/msg04076.html
But I am facing the same issue, adding the section to a very simple ELF file fails with Assertion `shdr != NULL'. I am new to this so I am sure I am doing something wrong, but not exactly certain what it is. I have also tried to open ELF with ELF_C_WRITE as opposed to ELF_C_RDWR but then my error is "elf_newdata() failed: executable header not created first" so I am not sure what the proper sequence of events would be to add a section. Below is my code and a run with the message. Thank you! Elfutils 0.186-1 - Debian testing ============= sample test.c I want to add a section to ========================= #include <stdio.h> int main(int argc, char **argv){ printf("Hello world"); return 0; } =========== test.c ELF Sections before adding section =========== (Intel x86-64) Program header table entries: 11 (40 - 2A8) 0 P r-- 40 268 00000040 6 D rw- 2DF8 1E0 00003DF8 1 I "/lib64/ld-linux-x86-64.so.2" 7 N "GNU" 2 B r-- 0 568 00000000 8 U r-- 2010 3C 00002010 3 B r-s 1000 1DD 00001000 9 . rw- 0 0 00000000 4 B r-- 2000 158 00002000 10 R r-- 2DE8 218 00003DE8 5 B rw- 2DE8 248 00003DE8 +8 Section header table entries: 30 (3728 - 3EA8) 0 (null) 15 B r-x 11D4 9 .fini 1 I "/lib64/ld-linux-x86-64.so.2" 16 B r-- 2000 10 .rodata 2 N "GNU" 17 U r-- 2010 3C .eh_frame_hdr 3 N "GNU" 18 U r-- 2050 108 .eh_frame 4 H r-- 308 24 .gnu.hash [5] 19 ? rw- 2DE8 8 .init_array 5 S r-- 330 A8 .dynsym [6] 20 ? rw- 2DF0 8 .fini_array 6 $ r-- 3D8 84 .dynstr 21 D rw- 2DF8 1E0 .dynamic [6] 7 V r-- 45C E .gnu.version [5] 22 O rw- 2FD8 28 .got 8 V r-- 470 20 .gnu.version_r [6] 23 P rw- 3000 20 .got.plt 9 R r-- 490 C0 .rela.dyn:0 [5] 24 B rw- 3020 10 .data 10 R r-- 550 18 .rela.plt:23 [5] 25 0 rw- 3030 8 .bss 11 B r-x 1000 17 .init 26 C "GCC: (Debian 11.2.0-10) 11.2.0" 12 P r-x 1020 20 .plt 27 S --- 3050 3C0 .symtab [28] 13 B r-x 1040 8 .plt.got 28 $ --- 3410 210 .strtab 14 B r-x 1050 181 .text 29 $ --- 3620 107 .shstrtab [S] ============= add_section.c =========================== int main(int argc, char **argv) { // Parameters char *bin_path = NULL; char *data_file = NULL; char *section_name = NULL; // Elf section and data unsigned char *section_data_raw = NULL; // Section Data buffer content int fd = -1; // File descriptor for the ELF file Elf *e = NULL; // ELF struct Elf64_Addr sec_start_addr = 0; // Section Start Address Elf64_Xword sec_sz = 0; // Section size uint64_t sec_data_offset = 0; // Data Offset from start of section size_t sec_data_sz = 0; // Date size Elf_Scn *scn; Elf_Data *data; Elf64_Shdr *shdr; size_t scn_idx; off_t fsize = -1; if (argc < 4) { printf("secinject <file> <section> <data_file>\n"); exit(EXIT_FAILURE); } if (check_bin_path(argv[1], &bin_path) == FALSE) { err(EXIT_FAILURE, "RW Access to \"%s\" failed", argv[1]); } section_name = argv[2]; if (check_data_path(argv[3], &data_file) == FALSE) { err(EXIT_FAILURE, "Read Access to \"%s\" failed", argv[3]); } ssize_t nread = read_file_to_buffer(data_file, §ion_data_raw); if (elf_version(EV_CURRENT) == EV_NONE) errx(EXIT_FAILURE, "ELF library initialization failed: %s", elf_errmsg(-1)); // Open file rw if ((fd = open(argv[1], O_RDWR, 0)) < 0) err(EXIT_FAILURE, "open \"%s\" RW failed", bin_path); // Open ELF readwrite if ((e = elf_begin(fd, ELF_C_RDWR, NULL)) == NULL) errx(EXIT_FAILURE, "elf_begin() failed: %s.", elf_errmsg(-1)); // 2. Create new section if ((scn = elf_newscn(e)) == NULL) errx(EXIT_FAILURE, "elf_newscn() failed: %s.", elf_errmsg(-1)); if ((data = elf_newdata(scn)) == NULL) errx(EXIT_FAILURE, "elf_newdata() failed: %s.", elf_errmsg(-1)); data->d_align = 4; data->d_buf = section_data_raw; data->d_off = 0LL; data->d_size = nread; data->d_type = ELF_T_DYN; data->d_version = EV_CURRENT; scn_idx = elf_ndxscn(scn); printf("New Section index: %zu\n", scn_idx); scn = elf_getscn(e, scn_idx); if ((shdr = elf64_getshdr(scn)) == NULL ){ err(EXIT_FAILURE, "elf64_getshdr() failed: %s.", elf_errmsg(-1)); } shdr->sh_name = scn_idx; shdr->sh_type = SHT_PROGBITS; shdr->sh_flags = SHF_ALLOC | SHF_WRITE; shdr->sh_entsize = 0; if (elf_update(e , ELF_C_NULL ) < 0) { err(EXIT_FAILURE, "elf_update() failed: %s.", elf_errmsg(-1)); } (void) elf_flagshdr(scn, ELF_C_SET, ELF_F_DIRTY); (void) elf_flagscn(scn, ELF_C_SET, ELF_F_DIRTY); (void) elf_flagdata(data, ELF_C_SET, ELF_F_DIRTY); (void) elf_flagehdr(e, ELF_C_SET, ELF_F_DIRTY); (void) elf_flagelf(e, ELF_C_SET, ELF_F_DIRTY); if (elf_update(e, ELF_C_WRITE ) < 0) { err(EXIT_FAILURE, "elf_update() failed: %s.", elf_errmsg(-1)); } if (e != NULL) elf_end(e); if (fd != -1) close(fd); exit(EXIT_SUCCESS); } ============= Run ====================== New Section index: 30 secinject: elf32_updatenull.c:214: __elf64_updatenull_wrlock: Assertion `shdr != NULL' failed. Aborted =========== GDB shdr check ================= Breakpoint 1, main (argc=4, argv=0x7ffe136cb9e8) at secinject.c:86 86 if (elf_update(e , ELF_C_NULL ) < 0) { (gdb) p scn $1 = (Elf_Scn *) 0x55799dbd6510 (gdb) p shdr $2 = (Elf64_Shdr *) 0x55799dbd7560 (gdb) p e $3 = (Elf *) 0x55799dbd46b0 (gdb) p shdr->sh_name $4 = 36 ========== Error in: elfutils-0.183/libelf/elf32_updatenull.c: 214: ======== /* Load the section headers if necessary. This loads the headers for all sections. */ if (scn1 != NULL && scn1->shdr.ELFW(e,LIBELFBITS) == NULL) (void) __elfw2(LIBELFBITS,getshdr_wrlock) (scn1); do { for (size_t cnt = first == true; cnt < list->cnt; ++cnt) { Elf_Scn *scn = &list->data[cnt]; ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS); int64_t offset = 0; 214: assert (shdr != NULL); ElfW2(LIBELFBITS,SizeWord) sh_entsize = shdr->sh_entsize; ElfW2(LIBELFBITS,SizeWord) sh_align = shdr->sh_addralign ?: 1;