1/* Copyright (C) 2012 Red Hat, Inc.
2   This file is part of elfutils.
3
4   This file is free software; you can redistribute it and/or modify
5   it under the terms of the GNU General Public License as published by
6   the Free Software Foundation; either version 3 of the License, or
7   (at your option) any later version.
8
9   elfutils is distributed in the hope that it will be useful, but
10   WITHOUT ANY WARRANTY; without even the implied warranty of
11   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12   GNU General Public License for more details.
13
14   You should have received a copy of the GNU General Public License
15   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
16
17#include <sys/types.h>
18#include <sys/stat.h>
19#include <stdio.h>
20#include <stdlib.h>
21#include <unistd.h>
22#include <errno.h>
23#include <string.h>
24#include <fcntl.h>
25#include <gelf.h>
26#include <libelf.h>
27#include <stdbool.h>
28#include <inttypes.h>
29
30int
31main (int argc, char *argv[])
32{
33  if (argc != 3)
34    {
35      fprintf (stderr, "Needs two arguments.\n");
36      fprintf (stderr, "First needs to be 'READ', 'MMAP' or 'FDREAD'\n");
37      fprintf (stderr, "Second is the ELF file to read.\n");
38      exit (2); /* user error */
39    }
40
41  bool do_mmap = false;
42  bool close_fd = false;
43  if (strcmp (argv[1], "READ") == 0)
44    {
45      do_mmap = false;
46      close_fd = false;
47    }
48  else if (strcmp (argv[1], "MMAP") == 0)
49    {
50      do_mmap = true;
51      close_fd = false;
52    }
53  else if  (strcmp (argv[1], "FDREAD") == 0)
54    {
55      do_mmap = false;
56      close_fd = true;
57    }
58  else
59    {
60      fprintf (stderr, "First arg needs to be 'READ', 'MMAP' or 'FDREAD'\n");
61      exit (2); /* user error */
62    }
63
64  elf_version (EV_CURRENT);
65
66  int fd = open (argv[2], O_RDONLY);
67  if (fd < 0)
68    {
69      fprintf (stderr, "Cannot open input file %s: %s\n", argv[2],
70	       strerror (errno));
71      exit (2);
72    }
73
74  Elf *elf = elf_begin (fd, do_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
75  if (elf == NULL)
76    {
77      fprintf (stderr, "elf_begin failed for %s: %s\n", argv[2],
78	       elf_errmsg (-1));
79      exit (2);
80    }
81
82  if (! do_mmap && close_fd)
83    {
84      if (elf_cntl (elf, ELF_C_FDREAD) < 0)
85	{
86	  fprintf (stderr, "elf_cntl failed for %s: %s\n", argv[2],
87		   elf_errmsg (-1));
88	  exit (1);
89	}
90      close (fd);
91    }
92
93  Elf_Scn *scn = NULL;
94  while ((scn = elf_nextscn (elf, scn)) != NULL)
95    {
96      GElf_Shdr shdr_mem;
97      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
98      printf ("Section at offset %#0" PRIx64 "\n", shdr->sh_offset);
99    }
100
101  elf_end (elf);
102  exit (0);
103}
104