diff options
Diffstat (limited to 'libelf/elf_getscn.c')
-rw-r--r-- | libelf/elf_getscn.c | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/libelf/elf_getscn.c b/libelf/elf_getscn.c index 9f7213b4..e1fbaaaa 100644 --- a/libelf/elf_getscn.c +++ b/libelf/elf_getscn.c @@ -59,6 +59,38 @@ elf_getscn (Elf *elf, size_t idx) || (offsetof (struct Elf, state.elf32.scns) == offsetof (struct Elf, state.elf64.scns)) ? &elf->state.elf32.scns : &elf->state.elf64.scns); + + /* Section zero is special. It always exists even if there is no + "first" section. And it is needed to store "overflow" values + from the Elf header. */ + if (idx == 0 && runp->cnt == 0 && runp->max > 0) + { + Elf_Scn *scn0 = &runp->data[0]; + if (elf->class == ELFCLASS32) + { + scn0->shdr.e32 = (Elf32_Shdr *) calloc (1, sizeof (Elf32_Shdr)); + if (scn0->shdr.e32 == NULL) + { + __libelf_seterrno (ELF_E_NOMEM); + goto out; + } + } + else + { + scn0->shdr.e64 = (Elf64_Shdr *) calloc (1, sizeof (Elf64_Shdr)); + if (scn0->shdr.e64 == NULL) + { + __libelf_seterrno (ELF_E_NOMEM); + goto out; + } + } + scn0->elf = elf; + scn0->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED; + scn0->list = elf->state.elf.scns_last; + scn0->data_read = 1; + runp->cnt = 1; + } + while (1) { if (idx < runp->max) @@ -80,6 +112,7 @@ elf_getscn (Elf *elf, size_t idx) } } + out: rwlock_unlock (elf->lock); return result; |