summaryrefslogtreecommitdiffstats
path: root/libelf/elf_getscn.c
diff options
context:
space:
mode:
Diffstat (limited to 'libelf/elf_getscn.c')
-rw-r--r--libelf/elf_getscn.c33
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;