blob: 58eae343563e8749e1c1eb7e2e253f86ea829eca [file] [log] [blame]
/* 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 <fcntl.h>
#include <libelf.h>
#include <libdwarf.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int
main (int argc, char *argv[])
{
int cnt;
for (cnt = 1; cnt < argc; ++cnt)
{
int fd = open (argv[cnt], O_RDONLY);
Dwarf_Debug dbg;
Dwarf_Signed cie_cnt;
Dwarf_Cie *cie_data;
Dwarf_Signed fde_cnt;
Dwarf_Fde *fde_data;
Dwarf_Error err;
if (dwarf_init (fd, DW_DLC_READ, NULL, NULL, &dbg, &err) != DW_DLV_OK)
{
printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (err));
continue;
}
else if (dwarf_get_fde_list_eh (dbg, &cie_data, &cie_cnt, &fde_data,
&fde_cnt, &err) != DW_DLV_OK)
printf ("cannot get CIEs and FDEs from %s: %s\n", argv[cnt],
dwarf_errmsg (err));
else
{
Dwarf_Addr low_pc;
Dwarf_Addr high_pc;
Dwarf_Unsigned func_length;
Dwarf_Ptr fde_bytes;
Dwarf_Unsigned fde_byte_length;
Dwarf_Off cie_offset;
Dwarf_Signed cie_index;
Dwarf_Off fde_offset;
Dwarf_Fde fde;
int i;
printf ("%s has %lld CIEs and %lld FDEs\n",
basename (argv[cnt]),
(long long int) cie_cnt, (long long int) fde_cnt);
for (i = 0; i < cie_cnt; ++i)
{
Dwarf_Unsigned bytes_in_cie;
Dwarf_Small version;
char *augmenter;
Dwarf_Unsigned code_alignment_factor;
Dwarf_Signed data_alignment_factor;
Dwarf_Half return_address_register;
Dwarf_Ptr initial_instructions;
Dwarf_Unsigned initial_instructions_length;
if (dwarf_get_cie_info (cie_data[i], &bytes_in_cie, &version,
&augmenter, &code_alignment_factor,
&data_alignment_factor,
&return_address_register,
&initial_instructions,
&initial_instructions_length, &err)
!= DW_DLV_OK)
printf ("cannot get info for CIE %d: %s\n", i,
dwarf_errmsg (err));
else
{
size_t j;
printf ("CIE[%d]: bytes_in_cie = %llu, version = %hhd, augmenter = \"%s\"\n",
i, (unsigned long long int) bytes_in_cie, version,
augmenter);
printf ("CIE[%d]: code_alignment_factor = %llx\n"
"CIE[%d]: data_alignment_factor = %llx\n"
"CIE[%d]: return_address_register = %hu\n"
"CIE[%d]: bytes =",
i, (unsigned long long int) code_alignment_factor,
i, (unsigned long long int) data_alignment_factor,
i, return_address_register, i);
for (j = 0; j < initial_instructions_length; ++j)
printf (" %02hhx",
((unsigned char *) initial_instructions)[j]);
putchar ('\n');
}
}
for (i = 0; i < fde_cnt; ++i)
{
Dwarf_Cie cie;
if (dwarf_get_fde_range (fde_data[i], &low_pc, &func_length,
&fde_bytes, &fde_byte_length,
&cie_offset, &cie_index, &fde_offset,
&err) != DW_DLV_OK)
printf ("cannot get range of FDE %d: %s\n", i,
dwarf_errmsg (err));
else
{
size_t j;
Dwarf_Ptr instrs;
Dwarf_Unsigned len;
printf ("FDE[%d]: low_pc = %#llx, length = %llu\n", i,
(unsigned long long int) low_pc,
(unsigned long long int) func_length);
printf ("FDE[%d]: bytes =", i);
for (j = 0; j < fde_byte_length; ++j)
printf (" %02hhx", ((unsigned char *) fde_bytes)[j]);
printf ("\nFDE[%d]: cie_offset = %lld, cie_index = %lld, fde_offset = %lld\n",
i, (long long int) cie_offset,
(long long int) cie_index,
(long long int) fde_offset);
if (dwarf_get_fde_instr_bytes (fde_data[i], &instrs, &len,
&err) != DW_DLV_OK)
printf ("cannot get instructions of FDE %d: %s\n", i,
dwarf_errmsg (err));
else
{
printf ("FDE[%d]: instructions =", i);
for (j = 0; j < len; ++j)
printf (" %02hhx", ((unsigned char *) instrs)[j]);
putchar ('\n');
}
/* Consistency check. */
if (dwarf_get_cie_of_fde (fde_data[i], &cie, &err)
!= DW_DLV_OK)
printf ("cannot get CIE of FDE %d: %s\n", i,
dwarf_errmsg (err));
else if (cie_data[cie_index] != cie)
puts ("cie_index for FDE[%d] does not match dwarf_get_cie_of_fde result");
}
if (dwarf_get_fde_n (fde_data, i, &fde, &err) != DW_DLV_OK)
printf ("dwarf_get_fde_n for FDE[%d] failed\n", i);
else if (fde != fde_data[i])
printf ("dwarf_get_fde_n for FDE[%d] didn't return the right value\n", i);
}
if (dwarf_get_fde_n (fde_data, fde_cnt, &fde, &err)
!= DW_DLV_NO_ENTRY)
puts ("dwarf_get_fde_n for invalid index doesn't return DW_DLV_NO_ENTRY");
{
const unsigned int addrs[] =
{
0x8048400, 0x804842c, 0x8048454, 0x8048455, 0x80493fc
};
const int naddrs = sizeof (addrs) / sizeof (addrs[0]);
for (i = 0; i < naddrs; ++i)
if (dwarf_get_fde_at_pc (fde_data, addrs[i], &fde, &low_pc,
&high_pc, &err) != DW_DLV_OK)
printf ("no FDE at %x\n", addrs[i]);
else
{
Dwarf_Addr other_low_pc;
if (dwarf_get_fde_range (fde, &other_low_pc, &func_length,
&fde_bytes, &fde_byte_length,
&cie_offset, &cie_index,
&fde_offset, &err) != DW_DLV_OK)
printf ("cannot get range of FDE returned by dwarf_get_fde_at_pc for %u: %s\n",
addrs[i], dwarf_errmsg (err));
else
{
printf ("FDE[@%x]: cie_offset = %lld, cie_index = %lld, fde_offset = %lld\n",
addrs[i],
(long long int) cie_offset,
(long long int) cie_index,
(long long int) fde_offset);
if (low_pc != other_low_pc)
printf ("low_pc returned by dwarf_get_fde_at_pc for %x and dwarf_get_fde_range differs",
addrs[i]);
if (high_pc != low_pc + func_length - 1)
printf ("high_pc returned by dwarf_get_fde_at_pc for %x and dwarf_get_fde_range differs",
addrs[i]);
}
}
}
}
if (dwarf_finish (dbg, &err) != DW_DLV_OK)
printf ("dwarf_finish failed for %s: %s\n", argv[cnt],
dwarf_errmsg (err));
close (fd);
}
return 0;
}