Cont.: Adding a new section to an ELF file aborts with Assertion `shdr != NULL'
P.B.
poundbang@gmail.com
Fri Dec 24 20:42:05 GMT 2021
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;
More information about the Elfutils-devel
mailing list