summaryrefslogtreecommitdiff
path: root/src/elfops/last-section-in-segment.c
blob: 53323f66e6da9d3de64ce565c9f1e2007c6e5cd5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include <stdio.h>
#include <stdlib.h>

#include <libelf.h>
#include <gelf.h>

#include <libelfu/libelfu.h>


/*
 * Returns the first section that  is contained in the segment and
 * ends as close to its memory image of as possible (the "last"
 * section in the segment).
 *
 * If no section fits, NULL is returned.
 */
Elf_Scn* elfu_lastSectionInSegment(Elf *e, GElf_Phdr *phdr)
{
  Elf_Scn *last = NULL;
  Elf_Scn *scn;


  scn = elf_getscn(e, 1);
  while (scn) {
    GElf_Shdr shdr;

    if (gelf_getshdr(scn, &shdr) != &shdr) {
      fprintf(stderr, "gelf_getshdr() failed: %s\n", elf_errmsg(-1));
      continue;
    }

    if (elfu_segmentContainsSection(phdr, &shdr)) {
      if (!last) {
        last = scn;
      } else {
        GElf_Shdr shdrOld;

        if (gelf_getshdr(last, &shdrOld) != &shdrOld) {
          continue;
        }

        if (shdr.sh_offset + shdr.sh_size
            > shdrOld.sh_offset + shdrOld.sh_size) {
          // TODO: Check (leftover space in memory image) < (p_align)
          last = scn;
        }
      }
    }

    scn = elf_nextscn(e, scn);
  }

  return last;
}