/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
Written by Ulrich Drepper <drepper@redhat.com>, 1998.
This program is Open Source software; you can redistribute it and/or
modify it under the terms of the Open Software License version 1.0 as
published by the Open Source Initiative.
You should have received a copy of the Open Software License along
with this program; if not, you may obtain a copy of the Open Software
License version 1.0 from http://www.opensource.org/licenses/osl.php or
by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
3001 King Ranch Road, Ukiah, CA 95482. */
#include <config.h>
#include <errno.h>
#include <error.h>
#include <fcntl.h>
#include <gelf.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* Prototypes for local functions. */
static int handle_section (Elf *elf, Elf_Scn *scn);
static void print_bytes (Elf_Data *data);
static void print_symtab (Elf *elf, Elf_Data *data);
int
main (int argc, char *argv[])
{
Elf *elf;
int fd;
int cnt;
if (argc <= 1)
exit (1);
/* Open the test file. This is given as the first parameter to the
program. */
fd = open (argv[1], O_RDONLY);
if (fd == -1)
error (EXIT_FAILURE, errno, "cannot open input file `%s'", argv[1]);
/* Set the library versio we expect. */
elf_version (EV_CURRENT);
/* Create the ELF descriptor. */
elf = elf_begin (fd, ELF_C_READ, NULL);
if (elf == NULL)
error (EXIT_FAILURE, 0, "cannot create ELF descriptor: %s",
elf_errmsg (0));
/* Now proces all the sections mentioned in the rest of the command line. */
for (cnt = 2; cnt < argc; ++cnt)
if (handle_section (elf, elf_getscn (elf, atoi (argv[cnt]))) != 0)
/* When we encounter an error stop immediately. */
error (EXIT_FAILURE, 0, "while processing section %d: %s", cnt,
elf_errmsg (0));
/* Close the descriptor. */
if (elf_end (elf) != 0)
error (EXIT_FAILURE, 0, "failure while closing ELF descriptor: %s",
elf_errmsg (0));
return 0;
}
static int
handle_section (Elf *elf, Elf_Scn *scn)
{
GElf_Ehdr *ehdr;
GElf_Ehdr ehdr_mem;
GElf_Shdr *shdr;
GElf_Shdr shdr_mem;
Elf_Data *data;
/* First get the ELF and section header. */
ehdr = gelf_getehdr (elf, &ehdr_mem);
shdr = gelf_getshdr (scn, &shdr_mem);
if (ehdr == NULL || shdr == NULL)
return 1;
/* Print the information from the ELF section header. */
printf ("name = %s\n"
"type = %" PRId32 "\n"
"flags = %" PRIx64 "\n"
"addr = %" PRIx64 "\n"
"offset = %" PRIx64 "\n"
"size = %" PRId64 "\n"
"link = %" PRId32 "\n"
"info = %" PRIx32 "\n"
"addralign = %" PRIx64 "\n"
"entsize = %" PRId64 "\n",
elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
shdr->sh_type,
shdr->sh_flags,
shdr->sh_addr,
shdr->sh_offset,
shdr->sh_size,
shdr->sh_link,
shdr->sh_info,
shdr->sh_addralign,
shdr->sh_entsize);
/* Get the section data now. */
data = elf_getdata (scn, NULL);
if (data == NULL)
return 1;
/* Now proces the different section types accordingly. */
switch (shdr->sh_type)
{
case SHT_SYMTAB:
print_symtab (elf, data);
break;
case SHT_PROGBITS:
default:
print_bytes (data);
break;
}
/* Separate form the next section. */
puts ("");
/* All done correctly. */
return 0;
}
static void
print_bytes (Elf_Data *data)
{
size_t size = data->d_size;
off_t offset = data->d_off;
unsigned char *buf = (unsigned char *) data->d_buf;
size_t cnt;
for (cnt = 0; cnt < size; cnt += 16)
{
size_t inner;
printf ("%*Zx: ", sizeof (size_t) == 4 ? 8 : 16, (size_t) offset + cnt);
for (inner = 0; inner < 16 && cnt + inner < size; ++inner)
printf (" %02hhx", buf[cnt + inner]);
puts ("");
}
}
static void
print_symtab (Elf *elf, Elf_Data *data)
{
int class = gelf_getclass (elf);
size_t nsym = data->d_size / (class == ELFCLASS32
? sizeof (Elf32_Sym) : sizeof (Elf64_Sym));
size_t cnt;
for (cnt = 0; cnt < nsym; ++cnt)
{
GElf_Sym sym_mem;
GElf_Sym *sym = gelf_getsym (data, cnt, &sym_mem);
printf ("%5Zu: %*" PRIx64 " %6" PRIx64 " %4d\n",
cnt,
class == ELFCLASS32 ? 8 : 16,
sym->st_value,
sym->st_size,
GELF_ST_TYPE (sym->st_info));
}
}