Blame dwarfdump/print_reloc.c

Packit cdaae3
/*
Packit cdaae3
  Copyright (C) 2000,2004,2005 Silicon Graphics, Inc.  All Rights Reserved.
Packit cdaae3
  Portions Copyright (C) 2007-2012 David Anderson. All Rights Reserved.
Packit cdaae3
  Portions Copyright (C) 2011-2012 SN Systems Ltd. All Rights Reserved
Packit cdaae3
Packit cdaae3
  This program is free software; you can redistribute it and/or modify it
Packit cdaae3
  under the terms of version 2 of the GNU General Public License as
Packit cdaae3
  published by the Free Software Foundation.
Packit cdaae3
Packit cdaae3
  This program is distributed in the hope that it would be useful, but
Packit cdaae3
  WITHOUT ANY WARRANTY; without even the implied warranty of
Packit cdaae3
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Packit cdaae3
Packit cdaae3
  Further, this software is distributed without any warranty that it is
Packit cdaae3
  free of the rightful claim of any third person regarding infringement
Packit cdaae3
  or the like.  Any license provided herein, whether implied or
Packit cdaae3
  otherwise, applies only to this software file.  Patent licenses, if
Packit cdaae3
  any, provided herein do not apply to combinations of this program with
Packit cdaae3
  other software, or any other product whatsoever.
Packit cdaae3
Packit cdaae3
  You should have received a copy of the GNU General Public License along
Packit cdaae3
  with this program; if not, write the Free Software Foundation, Inc., 51
Packit cdaae3
  Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
Packit cdaae3
Packit cdaae3
*/
Packit cdaae3
#include "globals.h"
Packit cdaae3
#define DWARF_RELOC_MIPS
Packit cdaae3
#define DWARF_RELOC_PPC
Packit cdaae3
#define DWARF_RELOC_PPC64
Packit cdaae3
#define DWARF_RELOC_ARM
Packit cdaae3
#define DWARF_RELOC_X86_64
Packit cdaae3
#define DWARF_RELOC_386
Packit cdaae3
Packit cdaae3
#include "print_reloc.h"
Packit cdaae3
#include "section_bitmaps.h"
Packit cdaae3
#include "esb.h"
Packit cdaae3
Packit cdaae3
/*  Include Section type, to be able to deal with all the
Packit cdaae3
    Elf32_Rel, Elf32_Rela, Elf64_Rel, Elf64_Rela relocation types
Packit cdaae3
    print_error does not return, so the following esb_destructor()
Packit cdaae3
    call is unnecessary but reads well  :-) */
Packit cdaae3
#define SECT_DATA_SET(x,t,n,sout,r2) {                        \
Packit cdaae3
    data = elf_getdata(scn, 0);                               \
Packit cdaae3
    if (!data || !data->d_size) {                             \
Packit cdaae3
        struct esb_s data_disaster;                           \
Packit cdaae3
        esb_constructor(&data_disaster);                      \
Packit cdaae3
        esb_append(&data_disaster,(n));                       \
Packit cdaae3
        esb_append(&data_disaster," null");                   \
Packit cdaae3
        print_error(dbg,esb_get_string(&data_disaster),DW_DLV_OK, err); \
Packit cdaae3
        esb_destructor(&data_disaster);                       \
Packit cdaae3
    }                                                         \
Packit cdaae3
    sout[(r2)]      = sect_data[(x)];                         \
Packit cdaae3
    sout[(r2)].buf  = data->d_buf;                            \
Packit cdaae3
    sout[(r2)].size = data->d_size;                           \
Packit cdaae3
    sout[(r2)].type = (t);                                    \
Packit cdaae3
    sout[(r2)].name = (n);                                    \
Packit cdaae3
    }
Packit cdaae3
/* Record the relocation table name information */
Packit cdaae3
static const char **reloc_type_names = NULL;
Packit cdaae3
static Dwarf_Small number_of_reloc_type_names = 0;
Packit cdaae3
Packit cdaae3
/* Set the relocation names based on the machine type */
Packit cdaae3
static void
Packit cdaae3
set_relocation_table_names(Dwarf_Small machine_type)
Packit cdaae3
{
Packit cdaae3
    reloc_type_names = 0;
Packit cdaae3
    number_of_reloc_type_names = 0;
Packit cdaae3
    switch (machine_type) {
Packit cdaae3
    case EM_MIPS:
Packit cdaae3
#ifdef DWARF_RELOC_MIPS
Packit cdaae3
        reloc_type_names = reloc_type_names_MIPS;
Packit cdaae3
        number_of_reloc_type_names =
Packit cdaae3
            sizeof(reloc_type_names_MIPS) / sizeof(char *);
Packit cdaae3
#endif /* DWARF_RELOC_MIPS */
Packit cdaae3
        break;
Packit cdaae3
    case EM_PPC:
Packit cdaae3
#ifdef DWARF_RELOC_PPC
Packit cdaae3
        reloc_type_names = reloc_type_names_PPC;
Packit cdaae3
        number_of_reloc_type_names =
Packit cdaae3
            sizeof(reloc_type_names_PPC) / sizeof(char *);
Packit cdaae3
#endif /* DWARF_RELOC_PPC */
Packit cdaae3
        break;
Packit cdaae3
    case EM_PPC64:
Packit cdaae3
#ifdef DWARF_RELOC_PPC64
Packit cdaae3
        reloc_type_names = reloc_type_names_PPC64;
Packit cdaae3
        number_of_reloc_type_names =
Packit cdaae3
            sizeof(reloc_type_names_PPC64) / sizeof(char *);
Packit cdaae3
#endif /* DWARF_RELOC_PPC64 */
Packit cdaae3
        break;
Packit cdaae3
    case EM_ARM:
Packit cdaae3
#ifdef DWARF_RELOC_ARM
Packit cdaae3
        reloc_type_names = reloc_type_names_ARM;
Packit cdaae3
        number_of_reloc_type_names =
Packit cdaae3
            sizeof(reloc_type_names_ARM) / sizeof(char *);
Packit cdaae3
#endif /* DWARF_RELOC_ARM */
Packit cdaae3
        break;
Packit cdaae3
    case EM_386:
Packit cdaae3
#ifdef DWARF_RELOC_386
Packit cdaae3
        reloc_type_names = reloc_type_names_386;
Packit cdaae3
        number_of_reloc_type_names =
Packit cdaae3
            sizeof(reloc_type_names_386) / sizeof(char *);
Packit cdaae3
#endif /* DWARF_RELOC_X86_64 */
Packit cdaae3
        break;
Packit cdaae3
    case EM_X86_64:
Packit cdaae3
#ifdef DWARF_RELOC_X86_64
Packit cdaae3
        reloc_type_names = reloc_type_names_X86_64;
Packit cdaae3
        number_of_reloc_type_names =
Packit cdaae3
            sizeof(reloc_type_names_X86_64) / sizeof(char *);
Packit cdaae3
#endif /* DWARF_RELOC_X86_64 */
Packit cdaae3
        break;
Packit cdaae3
    default:
Packit cdaae3
        /* We don't have others covered. */
Packit cdaae3
        reloc_type_names = 0;
Packit cdaae3
        number_of_reloc_type_names = 0;
Packit cdaae3
        break;
Packit cdaae3
  }
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*
Packit cdaae3
    Return valid reloc type names.
Packit cdaae3
    If buf is used, it is static, so beware: it
Packit cdaae3
    will be overwritten by the next call.
Packit cdaae3
*/
Packit cdaae3
static const char *
Packit cdaae3
get_reloc_type_names(int index)
Packit cdaae3
{
Packit cdaae3
    static char buf[100];
Packit cdaae3
    const char *retval = 0;
Packit cdaae3
Packit cdaae3
    if (index < 0 || index >= number_of_reloc_type_names) {
Packit cdaae3
        if (number_of_reloc_type_names == 0) {
Packit cdaae3
            /* No table provided. */
Packit cdaae3
            sprintf(buf, "reloc type %d", (int) index);
Packit cdaae3
        } else {
Packit cdaae3
            /* Table incomplete? */
Packit cdaae3
            sprintf(buf, "reloc type %d unknown", (int) index);
Packit cdaae3
        }
Packit cdaae3
        retval = buf;
Packit cdaae3
    } else {
Packit cdaae3
        retval = reloc_type_names[index];
Packit cdaae3
    }
Packit cdaae3
    return retval;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
#ifndef HAVE_ELF64_GETEHDR
Packit cdaae3
#define Elf64_Addr  long
Packit cdaae3
#define Elf64_Word  unsigned long
Packit cdaae3
#define Elf64_Xword unsigned long
Packit cdaae3
#define Elf64_Sym   long
Packit cdaae3
#endif
Packit cdaae3
Packit cdaae3
struct sect_data_s {
Packit cdaae3
    Dwarf_Small *buf;
Packit cdaae3
    Dwarf_Unsigned size;
Packit cdaae3
    Dwarf_Bool display; /* Display reloc if TRUE */
Packit cdaae3
    const char *name;   /* Section name */
Packit cdaae3
    Elf64_Xword type;   /* To cover 32 and 64 records types */
Packit cdaae3
};
Packit cdaae3
static struct sect_data_s sect_data[DW_SECTION_REL_ARRAY_SIZE];
Packit cdaae3
Packit cdaae3
Packit cdaae3
typedef size_t indx_type;
Packit cdaae3
Packit cdaae3
typedef struct {
Packit cdaae3
    indx_type indx;
Packit cdaae3
    char *name;
Packit cdaae3
    Elf32_Addr value;
Packit cdaae3
    Elf32_Word size;
Packit cdaae3
    int type;
Packit cdaae3
    int bind;
Packit cdaae3
    unsigned char other;
Packit cdaae3
    Elf32_Half shndx;
Packit cdaae3
} SYM;
Packit cdaae3
Packit cdaae3
Packit cdaae3
typedef struct {
Packit cdaae3
    indx_type indx;
Packit cdaae3
    char *name;
Packit cdaae3
    Elf64_Addr value;
Packit cdaae3
    Elf64_Xword size;
Packit cdaae3
    int type;
Packit cdaae3
    int bind;
Packit cdaae3
    unsigned char other;
Packit cdaae3
    unsigned short shndx;
Packit cdaae3
} SYM64;
Packit cdaae3
Packit cdaae3
static void print_reloc_information_64(int section_no,
Packit cdaae3
    Dwarf_Small * buf,
Packit cdaae3
    Dwarf_Unsigned size,
Packit cdaae3
    Elf64_Xword type,
Packit cdaae3
    char **scn_names,
Packit cdaae3
    int scn_names_count);
Packit cdaae3
static void print_reloc_information_32(int section_no,
Packit cdaae3
    Dwarf_Small * buf,
Packit cdaae3
    Dwarf_Unsigned size,
Packit cdaae3
    Elf64_Xword type,
Packit cdaae3
    char **scn_names,
Packit cdaae3
    int scn_names_count);
Packit cdaae3
static SYM *readsyms(Elf32_Sym * data, size_t num, Elf * elf,
Packit cdaae3
    Elf32_Word link);
Packit cdaae3
static SYM64 *read_64_syms(Elf64_Sym * data, size_t num, Elf * elf,
Packit cdaae3
    Elf64_Word link);
Packit cdaae3
static void *get_scndata(Elf_Scn * fd_scn, size_t * scn_size);
Packit cdaae3
static void print_relocinfo_64(Dwarf_Debug dbg, Elf * elf);
Packit cdaae3
static void print_relocinfo_32(Dwarf_Debug dbg, Elf * elf);
Packit cdaae3
Packit cdaae3
static SYM   *sym_data;
Packit cdaae3
static SYM64 *sym_data_64;
Packit cdaae3
static unsigned long   sym_data_entry_count;
Packit cdaae3
static unsigned long   sym_data_64_entry_count;
Packit cdaae3
Packit cdaae3
typedef struct {
Packit cdaae3
    indx_type index;
Packit cdaae3
    char *name_rel;     /* .rel.debug_* names  */
Packit cdaae3
    char *name_rela;    /* .rela.debug_* names */
Packit cdaae3
} REL_INFO;
Packit cdaae3
Packit cdaae3
/*  If the incoming scn_name is known, record the name
Packit cdaae3
    in our reloc section names table.
Packit cdaae3
    For a given (debug) section there can be a .rel or a .rela,
Packit cdaae3
    not both.
Packit cdaae3
    The name-to-index in this table is fixed, invariant.
Packit cdaae3
Packit cdaae3
*/
Packit cdaae3
static REL_INFO rel_info[DW_SECTION_REL_ARRAY_SIZE] = {
Packit cdaae3
    {0,0,0},
Packit cdaae3
    {/*1*/ DW_SECTION_REL_DEBUG_INFO,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_INFO,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_INFO},
Packit cdaae3
Packit cdaae3
    {/*2*/ DW_SECTION_REL_DEBUG_LINE,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_LINE,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_LINE},
Packit cdaae3
Packit cdaae3
    {/*3*/ DW_SECTION_REL_DEBUG_PUBNAMES,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_PUBNAMES,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_PUBNAMES},
Packit cdaae3
Packit cdaae3
    {/*4*/ DW_SECTION_REL_DEBUG_ABBREV,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_ABBREV,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_ABBREV},
Packit cdaae3
Packit cdaae3
    {/*5*/ DW_SECTION_REL_DEBUG_ARANGES,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_ARANGES,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_ARANGES},
Packit cdaae3
Packit cdaae3
    {/*6*/ DW_SECTION_REL_DEBUG_FRAME,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_FRAME,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_FRAME},
Packit cdaae3
Packit cdaae3
    {/*7*/ DW_SECTION_REL_DEBUG_LOC,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_LOC,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_LOC},
Packit cdaae3
Packit cdaae3
    {/*8*/ DW_SECTION_REL_DEBUG_LOCLISTS,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_LOCLISTS,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_LOCLISTS},
Packit cdaae3
Packit cdaae3
    {/*9*/ DW_SECTION_REL_DEBUG_RANGES,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_RANGES,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_RANGES},
Packit cdaae3
Packit cdaae3
    {/*10*/ DW_SECTION_REL_DEBUG_RNGLISTS,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_RNGLISTS,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_RNGLISTS},
Packit cdaae3
Packit cdaae3
    {/*11*/ DW_SECTION_REL_DEBUG_TYPES,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_TYPES,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_TYPES},
Packit cdaae3
Packit cdaae3
    {/*12*/ DW_SECTION_REL_DEBUG_STR_OFFSETS,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_STR_OFFSETS,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_STR_OFFSETS},
Packit cdaae3
Packit cdaae3
    {/*13*/ DW_SECTION_REL_DEBUG_PUBTYPES,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_PUBTYPES,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_PUBTYPES},
Packit cdaae3
Packit cdaae3
    {/*14*/ DW_SECTION_REL_GDB_INDEX,
Packit cdaae3
    DW_SECTNAME_REL_GDB_INDEX,
Packit cdaae3
    DW_SECTNAME_RELA_GDB_INDEX},
Packit cdaae3
Packit cdaae3
    {/*15*/ DW_SECTION_REL_EH_FRAME,
Packit cdaae3
    DW_SECTNAME_REL_EH_FRAME,
Packit cdaae3
    DW_SECTNAME_RELA_EH_FRAME},
Packit cdaae3
Packit cdaae3
    {/*16*/ DW_SECTION_REL_DEBUG_SUP,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_SUP,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_SUP},
Packit cdaae3
Packit cdaae3
    {/*17*/ DW_SECTION_REL_DEBUG_MACINFO,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_MACINFO,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_MACINFO},
Packit cdaae3
Packit cdaae3
    {/*18*/ DW_SECTION_REL_DEBUG_MACRO,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_MACRO,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_MACRO},
Packit cdaae3
Packit cdaae3
    {/*19*/ DW_SECTION_REL_DEBUG_NAMES,
Packit cdaae3
    DW_SECTNAME_REL_DEBUG_NAMES,
Packit cdaae3
    DW_SECTNAME_RELA_DEBUG_NAMES},
Packit cdaae3
};
Packit cdaae3
Packit cdaae3
#ifndef SELFTEST
Packit cdaae3
Packit cdaae3
static void
Packit cdaae3
get_reloc_section(Dwarf_Debug dbg,
Packit cdaae3
    Elf_Scn *scn,
Packit cdaae3
    char *scn_name,
Packit cdaae3
    Elf64_Word sh_type,
Packit cdaae3
    struct sect_data_s * printable_sect,
Packit cdaae3
    unsigned sectnum)
Packit cdaae3
{
Packit cdaae3
    Elf_Data *data;
Packit cdaae3
    int index;
Packit cdaae3
    /*  Check for reloc records we are interested in. */
Packit cdaae3
    for (index = 1; index < DW_SECTION_REL_ARRAY_SIZE; ++index) {
Packit cdaae3
        const char *n = rel_info[index].name_rel;
Packit cdaae3
        const char *na = rel_info[index].name_rela;
Packit cdaae3
        Dwarf_Error err = 0;
Packit cdaae3
Packit cdaae3
        if (strcmp(scn_name, n) == 0) {
Packit cdaae3
            SECT_DATA_SET(rel_info[index].index,sh_type,n,
Packit cdaae3
                printable_sect,sectnum)
Packit cdaae3
            return;
Packit cdaae3
        }
Packit cdaae3
        if (strcmp(scn_name, na) == 0) {
Packit cdaae3
            SECT_DATA_SET(rel_info[index].index,sh_type,na,
Packit cdaae3
                printable_sect,sectnum)
Packit cdaae3
            return;
Packit cdaae3
        }
Packit cdaae3
    }
Packit cdaae3
    return;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
void
Packit cdaae3
print_relocinfo(Dwarf_Debug dbg, char * reloc_map)
Packit cdaae3
{
Packit cdaae3
    Elf *elf;
Packit cdaae3
    char *endr_ident;
Packit cdaae3
    int is_64bit;
Packit cdaae3
    int res;
Packit cdaae3
    int i;
Packit cdaae3
    Dwarf_Error err = 0;
Packit cdaae3
Packit cdaae3
    for (i = 1; i < DW_SECTION_REL_ARRAY_SIZE; i++) {
Packit cdaae3
        sect_data[i].display = reloc_map[i];
Packit cdaae3
        sect_data[i].buf = 0;
Packit cdaae3
        sect_data[i].size = 0;
Packit cdaae3
        sect_data[i].type = SHT_NULL;
Packit cdaae3
    }
Packit cdaae3
    res = dwarf_get_elf(dbg, &elf, &err;;
Packit cdaae3
    if (res != DW_DLV_OK) {
Packit cdaae3
        print_error(dbg, "dwarf_get_elf error", res, err);
Packit cdaae3
    }
Packit cdaae3
    endr_ident = elf_getident(elf, NULL);
Packit cdaae3
    if (!endr_ident) {
Packit cdaae3
        print_error(dbg, "DW_ELF_GETIDENT_ERROR", res, err);
Packit cdaae3
    }
Packit cdaae3
    is_64bit = (endr_ident[EI_CLASS] == ELFCLASS64);
Packit cdaae3
    if (is_64bit) {
Packit cdaae3
        print_relocinfo_64(dbg, elf);
Packit cdaae3
    } else {
Packit cdaae3
        print_relocinfo_32(dbg, elf);
Packit cdaae3
    }
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
static void
Packit cdaae3
print_relocinfo_64(Dwarf_Debug dbg, Elf * elf)
Packit cdaae3
{
Packit cdaae3
#ifdef HAVE_ELF64_GETEHDR
Packit cdaae3
    Elf_Scn *scn = NULL;
Packit cdaae3
    unsigned sect_number = 0;
Packit cdaae3
    Elf64_Ehdr *ehdr64 = 0;
Packit cdaae3
    Elf64_Shdr *shdr64 = 0;
Packit cdaae3
    char *scn_name = 0;
Packit cdaae3
    int i = 0;
Packit cdaae3
    Elf64_Sym *sym_64 = 0;
Packit cdaae3
    char **scn_names = 0;
Packit cdaae3
    struct sect_data_s *printable_sects = 0;
Packit cdaae3
Packit cdaae3
    int scn_names_cnt = 0;
Packit cdaae3
    Dwarf_Error err = 0;
Packit cdaae3
Packit cdaae3
    ehdr64 = elf64_getehdr(elf);
Packit cdaae3
    if (ehdr64 == NULL) {
Packit cdaae3
        print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err);
Packit cdaae3
    }
Packit cdaae3
Packit cdaae3
    /*  Make the section name array big enough
Packit cdaae3
        that we don't need to check for overrun in the loop. */
Packit cdaae3
    scn_names_cnt = ehdr64->e_shnum + 1;
Packit cdaae3
    scn_names = (char **)calloc(scn_names_cnt, sizeof(char *));
Packit cdaae3
    if (!scn_names) {
Packit cdaae3
        print_error(dbg, "Out of malloc space in relocation print names",
Packit cdaae3
            DW_DLV_OK, err);
Packit cdaae3
    }
Packit cdaae3
    printable_sects = (struct sect_data_s *)calloc(scn_names_cnt,
Packit cdaae3
        sizeof(struct sect_data_s));
Packit cdaae3
    if (!printable_sects) {
Packit cdaae3
        free(scn_names);
Packit cdaae3
        print_error(dbg, "Out of malloc space in relocation print sects",
Packit cdaae3
            DW_DLV_OK, err);
Packit cdaae3
    }
Packit cdaae3
Packit cdaae3
    /*  First nextscn returns section 1 */
Packit cdaae3
    while ((scn = elf_nextscn(elf, scn)) != NULL) {
Packit cdaae3
        ++sect_number;
Packit cdaae3
        shdr64 = elf64_getshdr(scn);
Packit cdaae3
        if (shdr64 == NULL) {
Packit cdaae3
            free(scn_names);
Packit cdaae3
            free(printable_sects);
Packit cdaae3
            print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err);
Packit cdaae3
        }
Packit cdaae3
        scn_name = elf_strptr(elf, ehdr64->e_shstrndx, shdr64->sh_name);
Packit cdaae3
        if (scn_name  == NULL) {
Packit cdaae3
            print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err);
Packit cdaae3
        }
Packit cdaae3
            /* elf_nextscn() skips section with index '0' */
Packit cdaae3
        scn_names[sect_number] = scn_name;
Packit cdaae3
        if (shdr64->sh_type == SHT_SYMTAB) {
Packit cdaae3
            size_t sym_size = 0;
Packit cdaae3
            size_t count = 0;
Packit cdaae3
Packit cdaae3
            sym_64 = (Elf64_Sym *) get_scndata(scn, &sym_size);
Packit cdaae3
            if (sym_64 == NULL) {
Packit cdaae3
                free(scn_names);
Packit cdaae3
                free(printable_sects);
Packit cdaae3
                print_error(dbg, "no Elf64 symbol table data", DW_DLV_OK,
Packit cdaae3
                    err);
Packit cdaae3
            }
Packit cdaae3
            count = sym_size / sizeof(Elf64_Sym);
Packit cdaae3
            if(sym_size%sizeof(Elf64_Sym)) {
Packit cdaae3
                print_error(dbg, "Elf64 problem reading .symtab data",
Packit cdaae3
                    DW_DLV_OK, err);
Packit cdaae3
            }
Packit cdaae3
            sym_64++;
Packit cdaae3
            count--;
Packit cdaae3
            free(sym_data_64);
Packit cdaae3
            sym_data_64 = 0;
Packit cdaae3
            sym_data_64 = read_64_syms(sym_64, count, elf, shdr64->sh_link);
Packit cdaae3
            sym_data_64_entry_count = count;
Packit cdaae3
            if (sym_data_64  == NULL) {
Packit cdaae3
                free(scn_names);
Packit cdaae3
                free(printable_sects);
Packit cdaae3
                print_error(dbg, "problem reading Elf64 symbol table data",
Packit cdaae3
                    DW_DLV_OK, err);
Packit cdaae3
            }
Packit cdaae3
        } else  {
Packit cdaae3
            get_reloc_section(dbg,scn,scn_name,shdr64->sh_type,
Packit cdaae3
                printable_sects,sect_number);
Packit cdaae3
        }
Packit cdaae3
    }
Packit cdaae3
Packit cdaae3
    /* Set the relocation names based on the machine type */
Packit cdaae3
    set_relocation_table_names(ehdr64->e_machine);
Packit cdaae3
Packit cdaae3
    for (i = 1; i < ehdr64->e_shnum + 1; i++) {
Packit cdaae3
        if (printable_sects[i].display &&
Packit cdaae3
            printable_sects[i].buf != NULL &&
Packit cdaae3
            printable_sects[i].size > 0) {
Packit cdaae3
            print_reloc_information_64(i,
Packit cdaae3
                printable_sects[i].buf,
Packit cdaae3
                printable_sects[i].size,
Packit cdaae3
                printable_sects[i].type,
Packit cdaae3
                scn_names,scn_names_cnt);
Packit cdaae3
        }
Packit cdaae3
    }
Packit cdaae3
    free(printable_sects);
Packit cdaae3
    free(scn_names);
Packit cdaae3
    scn_names = 0;
Packit cdaae3
    scn_names_cnt = 0;
Packit cdaae3
#endif
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
static void
Packit cdaae3
print_relocinfo_32(Dwarf_Debug dbg, Elf * elf)
Packit cdaae3
{
Packit cdaae3
    Elf_Scn *scn = NULL;
Packit cdaae3
    Elf32_Ehdr *ehdr32 = 0;
Packit cdaae3
    Elf32_Shdr *shdr32 = 0;
Packit cdaae3
    unsigned sect_number = 0;
Packit cdaae3
    char *scn_name = 0;
Packit cdaae3
    int i = 0;
Packit cdaae3
    Elf32_Sym  *sym = 0;
Packit cdaae3
    char **scn_names = 0;
Packit cdaae3
    int scn_names_cnt = 0;
Packit cdaae3
    Dwarf_Error err = 0;
Packit cdaae3
    struct sect_data_s *printable_sects = 0;
Packit cdaae3
Packit cdaae3
    ehdr32 = elf32_getehdr(elf);
Packit cdaae3
    if (ehdr32 == NULL) {
Packit cdaae3
        print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err);
Packit cdaae3
    }
Packit cdaae3
Packit cdaae3
    /*  Make the section name array big enough
Packit cdaae3
        that we don't need to check for overrun in the loop. */
Packit cdaae3
    scn_names_cnt = ehdr32->e_shnum + 1;
Packit cdaae3
    scn_names = (char **)calloc(scn_names_cnt, sizeof(char *));
Packit cdaae3
    if (!scn_names) {
Packit cdaae3
        print_error(dbg, "Out of malloc space in relocation print names",
Packit cdaae3
            DW_DLV_OK, err);
Packit cdaae3
    }
Packit cdaae3
    printable_sects = (struct sect_data_s *)calloc(scn_names_cnt,
Packit cdaae3
        sizeof(struct sect_data_s));
Packit cdaae3
    if (!printable_sects) {
Packit cdaae3
        free(scn_names);
Packit cdaae3
        print_error(dbg, "Out of malloc space in relocation print sects",
Packit cdaae3
            DW_DLV_OK, err);
Packit cdaae3
    }
Packit cdaae3
Packit cdaae3
    while ((scn = elf_nextscn(elf, scn)) != NULL) {
Packit cdaae3
        ++sect_number;
Packit cdaae3
        shdr32 = elf32_getshdr(scn);
Packit cdaae3
        if (shdr32 == NULL) {
Packit cdaae3
            free(printable_sects);
Packit cdaae3
            free(scn_names);
Packit cdaae3
            print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err);
Packit cdaae3
        }
Packit cdaae3
        scn_name = elf_strptr(elf, ehdr32->e_shstrndx, shdr32->sh_name);
Packit cdaae3
        if (scn_name == NULL) {
Packit cdaae3
            free(printable_sects);
Packit cdaae3
            free(scn_names);
Packit cdaae3
            print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err);
Packit cdaae3
        }
Packit cdaae3
Packit cdaae3
        scn_names[sect_number] = scn_name;
Packit cdaae3
        if (shdr32->sh_type == SHT_SYMTAB) {
Packit cdaae3
            size_t sym_size = 0;
Packit cdaae3
            size_t count = 0;
Packit cdaae3
Packit cdaae3
            sym = (Elf32_Sym *) get_scndata(scn, &sym_size);
Packit cdaae3
            if (sym == NULL) {
Packit cdaae3
                free(printable_sects);
Packit cdaae3
                free(scn_names);
Packit cdaae3
                print_error(dbg, "No Elf32 symbol table data", DW_DLV_OK,
Packit cdaae3
                    err);
Packit cdaae3
            }
Packit cdaae3
            count = sym_size / sizeof(Elf32_Sym);
Packit cdaae3
            if(sym_size%sizeof(Elf32_Sym)) {
Packit cdaae3
                print_error(dbg, "Elf32 problem reading .symtab data",
Packit cdaae3
                    DW_DLV_OK, err);
Packit cdaae3
            }
Packit cdaae3
            sym++;
Packit cdaae3
            count--;
Packit cdaae3
            free(sym_data);
Packit cdaae3
            sym_data = 0;
Packit cdaae3
            sym_data = readsyms(sym, count, elf, shdr32->sh_link);
Packit cdaae3
            sym_data_entry_count = count;
Packit cdaae3
            if (sym_data  == NULL) {
Packit cdaae3
                free(printable_sects);
Packit cdaae3
                free(scn_names);
Packit cdaae3
                print_error(dbg, "problem reading Elf32 symbol table data",
Packit cdaae3
                    DW_DLV_OK, err);
Packit cdaae3
            }
Packit cdaae3
        } else {
Packit cdaae3
            get_reloc_section(dbg,scn,scn_name,shdr32->sh_type,
Packit cdaae3
                printable_sects,sect_number);
Packit cdaae3
        }
Packit cdaae3
    }  /* End while. */
Packit cdaae3
Packit cdaae3
    /* Set the relocation names based on the machine type */
Packit cdaae3
    set_relocation_table_names(ehdr32->e_machine);
Packit cdaae3
    for (i = 1; i < ehdr32->e_shnum + 1; i++) {
Packit cdaae3
        if (printable_sects[i].display &&
Packit cdaae3
            printable_sects[i].buf != NULL &&
Packit cdaae3
            printable_sects[i].size > 0) {
Packit cdaae3
            print_reloc_information_32(i,
Packit cdaae3
                printable_sects[i].buf,
Packit cdaae3
                printable_sects[i].size,
Packit cdaae3
                printable_sects[i].type,
Packit cdaae3
                scn_names,scn_names_cnt);
Packit cdaae3
        }
Packit cdaae3
    }
Packit cdaae3
    free(printable_sects);
Packit cdaae3
    free(scn_names);
Packit cdaae3
    scn_names = 0;
Packit cdaae3
    scn_names_cnt = 0;
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
#if HAVE_ELF64_R_INFO
Packit cdaae3
#ifndef ELF64_R_TYPE
Packit cdaae3
#define ELF64_R_TYPE(x) 0       /* FIXME */
Packit cdaae3
#endif
Packit cdaae3
#ifndef ELF64_R_SYM
Packit cdaae3
#define ELF64_R_SYM(x) 0        /* FIXME */
Packit cdaae3
#endif
Packit cdaae3
#ifndef ELF64_ST_TYPE
Packit cdaae3
#define ELF64_ST_TYPE(x) 0      /* FIXME */
Packit cdaae3
#endif
Packit cdaae3
#ifndef ELF64_ST_BIND
Packit cdaae3
#define ELF64_ST_BIND(x) 0      /* FIXME */
Packit cdaae3
#endif
Packit cdaae3
#endif /* HAVE_ELF64_R_INFO */
Packit cdaae3
Packit cdaae3
Packit cdaae3
static void
Packit cdaae3
print_reloc_information_64(int section_no, Dwarf_Small * buf,
Packit cdaae3
    Dwarf_Unsigned size, Elf64_Xword type,
Packit cdaae3
    char **scn_names,int scn_names_count)
Packit cdaae3
{
Packit cdaae3
    /* Include support for Elf64_Rel and Elf64_Rela */
Packit cdaae3
    Dwarf_Unsigned add = 0;
Packit cdaae3
    Dwarf_Half rel_size = SHT_RELA == type ?
Packit cdaae3
        sizeof(Elf64_Rela) : sizeof(Elf64_Rel);
Packit cdaae3
    Dwarf_Unsigned off = 0;
Packit cdaae3
    struct esb_s tempesb;
Packit cdaae3
Packit cdaae3
    printf("\n[%3d] %s:\n",section_no, sanitized(scn_names[section_no]));
Packit cdaae3
    /* Print some headers and change the order for better reading */
Packit cdaae3
    printf("Offset     Addend     %-26s Index   Symbol Name\n","Reloc Type");
Packit cdaae3
Packit cdaae3
#if HAVE_ELF64_GETEHDR
Packit cdaae3
    for (off = 0; off < size; off += rel_size) {
Packit cdaae3
#if HAVE_ELF64_R_INFO
Packit cdaae3
        /* This works for the Elf64_Rel in linux */
Packit cdaae3
        Elf64_Rel *p = (Elf64_Rel *) (buf + off);
Packit cdaae3
        char *name = 0;
Packit cdaae3
Packit cdaae3
        /*  We subtract 1 from sym indexes since we left
Packit cdaae3
            symtab entry 0 out of the sym_data[_64] array */
Packit cdaae3
        if (sym_data ) {
Packit cdaae3
            size_t index = ELF64_R_SYM(p->r_info) - 1;
Packit cdaae3
            if (index < sym_data_entry_count) {
Packit cdaae3
                name = sym_data[index].name;
Packit cdaae3
            }
Packit cdaae3
        } else if (sym_data_64) {
Packit cdaae3
            size_t index = ELF64_R_SYM(p->r_info) - 1;
Packit cdaae3
            if (index < sym_data_64_entry_count) {
Packit cdaae3
                name = sym_data_64[index].name;
Packit cdaae3
            }
Packit cdaae3
        }
Packit cdaae3
Packit cdaae3
        /*  When the name is not available, use the
Packit cdaae3
            section name as a reference for the name.*/
Packit cdaae3
        if (!name || !name[0]) {
Packit cdaae3
            size_t index = ELF64_R_SYM(p->r_info) - 1;
Packit cdaae3
            if (index < sym_data_64_entry_count) {
Packit cdaae3
                SYM64 *sym_64 = &sym_data_64[index];
Packit cdaae3
                if (sym_64->type == STT_SECTION &&
Packit cdaae3
                    sym_64->shndx < scn_names_count) {
Packit cdaae3
                    name = scn_names[sym_64->shndx];
Packit cdaae3
                }
Packit cdaae3
            }
Packit cdaae3
        }
Packit cdaae3
        if (!name || !name[0]) {
Packit cdaae3
            name = "<no name>";
Packit cdaae3
        }
Packit cdaae3
Packit cdaae3
        if (SHT_RELA == type) {
Packit cdaae3
            Elf64_Rela *pa = (Elf64_Rela *)p;
Packit cdaae3
            add = pa->r_addend;
Packit cdaae3
        }
Packit cdaae3
        esb_constructor(&tempesb);
Packit cdaae3
        esb_append(&tempesb,sanitized(
Packit cdaae3
            get_reloc_type_names(ELF64_R_TYPE(p->r_info))));
Packit cdaae3
        /* sanitized uses a static buffer, call just once here */
Packit cdaae3
        printf("0x%08lx 0x%08lx %-26s <%5ld> %s\n",
Packit cdaae3
            (unsigned long int) (p->r_offset),
Packit cdaae3
            (unsigned long int) (add),
Packit cdaae3
            esb_get_string(&tempesb),
Packit cdaae3
            (long)ELF64_R_SYM(p->r_info),
Packit cdaae3
            sanitized(name));
Packit cdaae3
        esb_destructor(&tempesb);
Packit cdaae3
#else
Packit cdaae3
        /*  sgi/mips -64 does not have r_info in the 64bit relocations,
Packit cdaae3
            but seperate fields, with 3 types, actually. Only one of
Packit cdaae3
            which prints here, as only one really used with dwarf */
Packit cdaae3
        Elf64_Rel *p = (Elf64_Rel *) (buf + off);
Packit cdaae3
        char *name = 0;
Packit cdaae3
Packit cdaae3
        /*  We subtract 1 from sym indexes since we left
Packit cdaae3
            symtab entry 0 out of the sym_data[_64] array */
Packit cdaae3
        if (sym_data ) {
Packit cdaae3
            size_t index = p->r_sym - 1;
Packit cdaae3
            if (index < sym_data_entry_count) {
Packit cdaae3
                name = sym_data[index].name;
Packit cdaae3
            }
Packit cdaae3
        } else if (sym_data_64) {
Packit cdaae3
            size_t index = p->r_sym - 1;
Packit cdaae3
            if (index < sym_data_64_entry_count) {
Packit cdaae3
                name = sym_data_64[index].name;
Packit cdaae3
            }
Packit cdaae3
        }
Packit cdaae3
        if (!name || !name[0]) {
Packit cdaae3
            name = "<no name>";
Packit cdaae3
        }
Packit cdaae3
Packit cdaae3
        /* sanitized uses a static buffer, call just once here */
Packit cdaae3
        esb_constructor(&tempesb);
Packit cdaae3
        esb_append(&tempesb, sanitized(
Packit cdaae3
            get_reloc_type_names(p->r_type)));
Packit cdaae3
        /* sanitized uses a static buffer, call just once here */
Packit cdaae3
        printf("%5" DW_PR_DUu " %-26s <%3ld> %s\n",
Packit cdaae3
            (Dwarf_Unsigned) (p->r_offset),
Packit cdaae3
            esb_get_string(&tempesb),
Packit cdaae3
            (long)p->r_sym,
Packit cdaae3
            sanitized(name));
Packit cdaae3
        esb_destructor(&tempesb);
Packit cdaae3
#endif
Packit cdaae3
    }
Packit cdaae3
#endif /* HAVE_ELF64_GETEHDR */
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
static void
Packit cdaae3
print_reloc_information_32(int section_no, Dwarf_Small * buf,
Packit cdaae3
   Dwarf_Unsigned size, Elf64_Xword type, char **scn_names,
Packit cdaae3
   int scn_names_count)
Packit cdaae3
{
Packit cdaae3
    /*  Include support for Elf32_Rel and Elf32_Rela */
Packit cdaae3
    Dwarf_Unsigned add = 0;
Packit cdaae3
    Dwarf_Half rel_size = SHT_RELA == type ?
Packit cdaae3
        sizeof(Elf32_Rela) : sizeof(Elf32_Rel);
Packit cdaae3
    Dwarf_Unsigned off = 0;
Packit cdaae3
    struct esb_s tempesb;
Packit cdaae3
Packit cdaae3
    printf("\n[%3d] %s:\n",section_no, sanitized(scn_names[section_no]));
Packit cdaae3
Packit cdaae3
    /* Print some headers and change the order for better reading. */
Packit cdaae3
    printf("Offset     Addend     %-26s Index   Symbol Name\n","Reloc Type");
Packit cdaae3
Packit cdaae3
    for (off = 0; off < size; off += rel_size) {
Packit cdaae3
        Elf32_Rel *p = (Elf32_Rel *) (buf + off);
Packit cdaae3
        char *name = 0;
Packit cdaae3
Packit cdaae3
        /*  We subtract 1 from sym indexes since we left
Packit cdaae3
            symtab entry 0 out of the sym_data[_64] array */
Packit cdaae3
        if (sym_data) {
Packit cdaae3
            size_t index = ELF32_R_SYM(p->r_info) - 1;
Packit cdaae3
            if (index < sym_data_entry_count) {
Packit cdaae3
                name = sym_data[index].name;
Packit cdaae3
            }
Packit cdaae3
        }
Packit cdaae3
Packit cdaae3
        /*  When the name is not available, use the
Packit cdaae3
            section name as a reference for the name. */
Packit cdaae3
        if (!name || !name[0]) {
Packit cdaae3
            size_t index = ELF32_R_SYM(p->r_info) - 1;
Packit cdaae3
            if (index < sym_data_entry_count) {
Packit cdaae3
                SYM *sym = &sym_data[index];
Packit cdaae3
                if (sym->type == STT_SECTION&&
Packit cdaae3
                    sym->shndx < scn_names_count) {
Packit cdaae3
                    name = scn_names[sym->shndx];
Packit cdaae3
                }
Packit cdaae3
            }
Packit cdaae3
        }
Packit cdaae3
        if (!name || !name[0]) {
Packit cdaae3
            name = "<no name>";
Packit cdaae3
        }
Packit cdaae3
        if (SHT_RELA == type) {
Packit cdaae3
            Elf32_Rela *pa = (Elf32_Rela *)p;
Packit cdaae3
            add = pa->r_addend;
Packit cdaae3
        }
Packit cdaae3
        esb_constructor(&tempesb);
Packit cdaae3
        esb_append(&tempesb,sanitized(
Packit cdaae3
            get_reloc_type_names(ELF32_R_TYPE(p->r_info))));
Packit cdaae3
        printf("0x%08lx 0x%08lx %-26s <%5ld> %s\n",
Packit cdaae3
            (unsigned long int) (p->r_offset),
Packit cdaae3
            (unsigned long int) (add),
Packit cdaae3
            esb_get_string(&tempesb),
Packit cdaae3
            (long)ELF32_R_SYM(p->r_info),
Packit cdaae3
            sanitized(name));
Packit cdaae3
        esb_destructor(&tempesb);
Packit cdaae3
    }
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*  We are only reading and saving syms 1...num-1. */
Packit cdaae3
static SYM *
Packit cdaae3
readsyms(Elf32_Sym * data, size_t num, Elf * elf, Elf32_Word link)
Packit cdaae3
{
Packit cdaae3
    SYM *s      = 0;
Packit cdaae3
    SYM *buf    = 0;
Packit cdaae3
    indx_type i = 0;
Packit cdaae3
Packit cdaae3
    buf = (SYM *) calloc(num, sizeof(SYM));
Packit cdaae3
    if (buf == NULL) {
Packit cdaae3
        return NULL;
Packit cdaae3
    }
Packit cdaae3
    s = buf; /* save pointer to head of array */
Packit cdaae3
    for (i = 0; i < num; i++, data++, buf++) {
Packit cdaae3
        buf->indx = i;
Packit cdaae3
        buf->name = (char *) elf_strptr(elf, link, data->st_name);
Packit cdaae3
        buf->value = data->st_value;
Packit cdaae3
        buf->size = data->st_size;
Packit cdaae3
        buf->type = ELF32_ST_TYPE(data->st_info);
Packit cdaae3
        buf->bind = ELF32_ST_BIND(data->st_info);
Packit cdaae3
        buf->other = data->st_other;
Packit cdaae3
        buf->shndx = data->st_shndx;
Packit cdaae3
    }   /* end for loop */
Packit cdaae3
    return (s);
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/*  We are only reading and saving syms 1...num-1. */
Packit cdaae3
static SYM64 *
Packit cdaae3
read_64_syms(Elf64_Sym * data, size_t num, Elf * elf, Elf64_Word link)
Packit cdaae3
{
Packit cdaae3
#ifdef HAVE_ELF64_GETEHDR
Packit cdaae3
Packit cdaae3
    SYM64 *s    = 0;
Packit cdaae3
    SYM64 *buf  = 0;
Packit cdaae3
    indx_type i = 0;
Packit cdaae3
Packit cdaae3
    buf = (SYM64 *) calloc(num, sizeof(SYM64));
Packit cdaae3
    if (buf == NULL) {
Packit cdaae3
        return NULL;
Packit cdaae3
    }
Packit cdaae3
    s = buf;                    /* save pointer to head of array */
Packit cdaae3
    for (i = 0; i < num; i++, data++, buf++) {
Packit cdaae3
        buf->indx = i;
Packit cdaae3
        buf->name = (char *) elf_strptr(elf, link, data->st_name);
Packit cdaae3
        buf->value = data->st_value;
Packit cdaae3
        buf->size = data->st_size;
Packit cdaae3
        buf->type = ELF64_ST_TYPE(data->st_info);
Packit cdaae3
        buf->bind = ELF64_ST_BIND(data->st_info);
Packit cdaae3
        buf->other = data->st_other;
Packit cdaae3
        buf->shndx = data->st_shndx;
Packit cdaae3
    }                           /* end for loop */
Packit cdaae3
    return (s);
Packit cdaae3
#else
Packit cdaae3
    return 0;
Packit cdaae3
#endif /* HAVE_ELF64_GETEHDR */
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
static void *
Packit cdaae3
get_scndata(Elf_Scn * fd_scn, size_t * scn_size)
Packit cdaae3
{
Packit cdaae3
    Elf_Data *p_data;
Packit cdaae3
Packit cdaae3
    p_data = 0;
Packit cdaae3
    if ((p_data = elf_getdata(fd_scn, p_data)) == 0 ||
Packit cdaae3
        p_data->d_size == 0) {
Packit cdaae3
        return NULL;
Packit cdaae3
    }
Packit cdaae3
    *scn_size = p_data->d_size;
Packit cdaae3
    return (p_data->d_buf);
Packit cdaae3
}
Packit cdaae3
Packit cdaae3
/* Cleanup of malloc space (some of the pointers will be 0 here)
Packit cdaae3
   so dwarfdump looks 'clean' to a malloc checker.
Packit cdaae3
*/
Packit cdaae3
void
Packit cdaae3
clean_up_syms_malloc_data()
Packit cdaae3
{
Packit cdaae3
    free(sym_data);
Packit cdaae3
    sym_data = 0;
Packit cdaae3
    free(sym_data_64);
Packit cdaae3
    sym_data_64 = 0;
Packit cdaae3
    sym_data_64_entry_count = 0;
Packit cdaae3
    sym_data_entry_count = 0;
Packit cdaae3
}
Packit cdaae3
#endif /* !SELFTEST */
Packit cdaae3
Packit cdaae3
#ifdef SELFTEST
Packit cdaae3
/*  SELFTEST here is just to check on table
Packit cdaae3
    internal consistency. */
Packit cdaae3
int
Packit cdaae3
main()
Packit cdaae3
{
Packit cdaae3
    int failcount = 0;
Packit cdaae3
    unsigned long i = 1;
Packit cdaae3
    for ( ; i < DW_SECTION_REL_ARRAY_SIZE; ++i) {
Packit cdaae3
        if (rel_info[i].index != i) {
Packit cdaae3
            printf(" FAIL rel_info check, i = %lu vs %lu\n",
Packit cdaae3
                i,
Packit cdaae3
                (unsigned long)rel_info[i].index);
Packit cdaae3
            ++failcount;
Packit cdaae3
        }
Packit cdaae3
    }
Packit cdaae3
    if(failcount) {
Packit cdaae3
        printf("FAIL print_reloc selftest\n");
Packit cdaae3
        exit(1);
Packit cdaae3
    }
Packit cdaae3
    printf("PASS print_reloc selftest\n");
Packit cdaae3
    return 0;
Packit cdaae3
}
Packit cdaae3
#endif /* SELFTEST*/