1/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
2   This file is part of Red Hat elfutils.
3   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
4
5   Red Hat elfutils is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published by the
7   Free Software Foundation; version 2 of the License.
8
9   Red Hat 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 GNU
12   General Public License for more details.
13
14   You should have received a copy of the GNU General Public License along
15   with Red Hat elfutils; if not, write to the Free Software Foundation,
16   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
17
18   Red Hat elfutils is an included package of the Open Invention Network.
19   An included package of the Open Invention Network is a package for which
20   Open Invention Network licensees cross-license their patents.  No patent
21   license is granted, either expressly or impliedly, by designation as an
22   included package.  Should you wish to participate in the Open Invention
23   Network licensing program, please visit www.openinventionnetwork.com
24   <http://www.openinventionnetwork.com>.  */
25
26#include <config.h>
27
28#include <errno.h>
29#include <error.h>
30#include <fcntl.h>
31#include <gelf.h>
32#include <inttypes.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <unistd.h>
36
37
38/* Prototypes for local functions.  */
39static int handle_section (Elf *elf, Elf_Scn *scn);
40static void print_bytes (Elf_Data *data);
41static void print_symtab (Elf *elf, Elf_Data *data);
42
43
44int
45main (int argc, char *argv[])
46{
47  Elf *elf;
48  int fd;
49  int cnt;
50
51  if (argc <= 1)
52    exit (1);
53
54  /* Open the test file.  This is given as the first parameter to the
55     program.  */
56  fd = open (argv[1], O_RDONLY);
57  if (fd == -1)
58    error (EXIT_FAILURE, errno, "cannot open input file `%s'", argv[1]);
59
60  /* Set the library versio we expect.  */
61  elf_version (EV_CURRENT);
62
63  /* Create the ELF descriptor.  */
64  elf = elf_begin (fd, ELF_C_READ, NULL);
65  if (elf == NULL)
66    error (EXIT_FAILURE, 0, "cannot create ELF descriptor: %s",
67	   elf_errmsg (0));
68
69  /* Now proces all the sections mentioned in the rest of the command line.  */
70  for (cnt = 2; cnt < argc; ++cnt)
71    if (handle_section (elf, elf_getscn (elf, atoi (argv[cnt]))) != 0)
72      /* When we encounter an error stop immediately.  */
73      error (EXIT_FAILURE, 0, "while processing section %d: %s", cnt,
74	   elf_errmsg (0));
75
76  /* Close the descriptor.  */
77  if (elf_end (elf) != 0)
78    error (EXIT_FAILURE, 0, "failure while closing ELF descriptor: %s",
79	   elf_errmsg (0));
80
81  return 0;
82}
83
84
85static int
86handle_section (Elf *elf, Elf_Scn *scn)
87{
88  GElf_Ehdr *ehdr;
89  GElf_Ehdr ehdr_mem;
90  GElf_Shdr *shdr;
91  GElf_Shdr shdr_mem;
92  Elf_Data *data;
93
94  /* First get the ELF and section header.  */
95  ehdr = gelf_getehdr (elf, &ehdr_mem);
96  shdr = gelf_getshdr (scn, &shdr_mem);
97  if (ehdr == NULL || shdr == NULL)
98    return 1;
99
100  /* Print the information from the ELF section header.   */
101  printf ("name      = %s\n"
102	  "type      = %" PRId32 "\n"
103	  "flags     = %" PRIx64 "\n"
104	  "addr      = %" PRIx64 "\n"
105	  "offset    = %" PRIx64 "\n"
106	  "size      = %" PRId64 "\n"
107	  "link      = %" PRId32 "\n"
108	  "info      = %" PRIx32 "\n"
109	  "addralign = %" PRIx64 "\n"
110	  "entsize   = %" PRId64 "\n",
111	  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
112	  shdr->sh_type,
113	  shdr->sh_flags,
114	  shdr->sh_addr,
115	  shdr->sh_offset,
116	  shdr->sh_size,
117	  shdr->sh_link,
118	  shdr->sh_info,
119	  shdr->sh_addralign,
120	  shdr->sh_entsize);
121
122  /* Get the section data now.  */
123  data = elf_getdata (scn, NULL);
124  if (data == NULL)
125    return 1;
126
127  /* Now proces the different section types accordingly.  */
128  switch (shdr->sh_type)
129    {
130    case SHT_SYMTAB:
131      print_symtab (elf, data);
132      break;
133
134    case SHT_PROGBITS:
135    default:
136      print_bytes (data);
137      break;
138    }
139
140  /* Separate form the next section.  */
141  puts ("");
142
143  /* All done correctly.  */
144  return 0;
145}
146
147
148static void
149print_bytes (Elf_Data *data)
150{
151  size_t size = data->d_size;
152  off_t offset = data->d_off;
153  unsigned char *buf = (unsigned char *) data->d_buf;
154  size_t cnt;
155
156  for (cnt = 0; cnt < size; cnt += 16)
157    {
158      size_t inner;
159
160      printf ("%*Zx: ", sizeof (size_t) == 4 ? 8 : 16, (size_t) offset + cnt);
161
162      for (inner = 0; inner < 16 && cnt + inner < size; ++inner)
163	printf (" %02hhx", buf[cnt + inner]);
164
165      puts ("");
166    }
167}
168
169
170static void
171print_symtab (Elf *elf, Elf_Data *data)
172{
173  int class = gelf_getclass (elf);
174  size_t nsym = data->d_size / (class == ELFCLASS32
175				? sizeof (Elf32_Sym) : sizeof (Elf64_Sym));
176  size_t cnt;
177
178  for (cnt = 0; cnt < nsym; ++cnt)
179    {
180      GElf_Sym sym_mem;
181      GElf_Sym *sym = gelf_getsym (data, cnt, &sym_mem);
182
183      printf ("%5Zu: %*" PRIx64 " %6" PRIx64 " %4d\n",
184	      cnt,
185	      class == ELFCLASS32 ? 8 : 16,
186	      sym->st_value,
187	      sym->st_size,
188	      GELF_ST_TYPE (sym->st_info));
189    }
190}
191