--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tools/elf4rom/libs/dwarf-20071209/dwarfdump/print_reloc.c Fri Jan 15 09:07:44 2010 +0000
@@ -0,0 +1,512 @@
+/*
+ Copyright (C) 2000,2004,2005 Silicon Graphics, Inc. All Rights Reserved.
+ Portions Copyright (C) 2007 David Anderson. All Rights Reserved.
+
+ This program is free software; you can redistribute it and/or modify it
+ under the terms of version 2 of the GNU General Public License as
+ published by the Free Software Foundation.
+
+ This program is distributed in the hope that it would be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+ Further, this software is distributed without any warranty that it is
+ free of the rightful claim of any third person regarding infringement
+ or the like. Any license provided herein, whether implied or
+ otherwise, applies only to this software file. Patent licenses, if
+ any, provided herein do not apply to combinations of this program with
+ other software, or any other product whatsoever.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write the Free Software Foundation, Inc., 51
+ Franklin Street - Fifth Floor, Boston MA 02110-1301, USA.
+
+ Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
+ Mountain View, CA 94043, or:
+
+ http://www.sgi.com
+
+ For further information regarding this notice, see:
+
+ http://oss.sgi.com/projects/GenInfo/NoticeExplan
+
+
+
+$Header: /plroot/cmplrs.src/v7.4.5m/.RCS/PL/dwarfdump/RCS/print_reloc.c,v 1.11 2005/08/04 05:09:37 davea Exp $ */
+
+/* The address of the Free Software Foundation is
+ Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+ SGI has moved from the Crittenden Lane address.
+*/
+
+
+
+
+#include "globals.h"
+
+
+#define DW_SECTION_REL_DEBUG_INFO 0
+#define DW_SECTION_REL_DEBUG_LINE 1
+#define DW_SECTION_REL_DEBUG_PUBNAME 2
+#define DW_SECTION_REL_DEBUG_ABBREV 3
+#define DW_SECTION_REL_DEBUG_ARANGES 4
+#define DW_SECTION_REL_DEBUG_FRAME 5
+#define DW_SECTION_REL_DEBUG_NUM 6
+
+#define DW_SECTNAME_REL_DEBUG_INFO ".rel.debug_info"
+#define DW_SECTNAME_REL_DEBUG_LINE ".rel.debug_line"
+#define DW_SECTNAME_REL_DEBUG_PUBNAME ".rel.debug_pubname"
+#define DW_SECTNAME_REL_DEBUG_ABBREV ".rel.debug_abbrev"
+#define DW_SECTNAME_REL_DEBUG_ARANGES ".rel.debug_aranges"
+#define DW_SECTNAME_REL_DEBUG_FRAME ".rel.debug_frame"
+
+#define STRING_FOR_DUPLICATE " duplicate"
+#define STRING_FOR_NULL " null"
+
+static char *sectnames[] = {
+ DW_SECTNAME_REL_DEBUG_INFO,
+ DW_SECTNAME_REL_DEBUG_LINE,
+ DW_SECTNAME_REL_DEBUG_PUBNAME,
+ DW_SECTNAME_REL_DEBUG_ABBREV,
+ DW_SECTNAME_REL_DEBUG_ARANGES,
+ DW_SECTNAME_REL_DEBUG_FRAME,
+};
+
+static char *error_msg_duplicate[] = {
+ DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_PUBNAME STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_DUPLICATE,
+ DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_DUPLICATE,
+};
+
+static char *error_msg_null[] = {
+ DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_PUBNAME STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_NULL,
+ DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_NULL,
+};
+
+#define SECT_DATA_SET(x) { \
+ if (sect_data[(x)].buf != NULL) { \
+ print_error(dbg, error_msg_duplicate[(x)],DW_DLV_OK, err); \
+ } \
+ if ((data = elf_getdata(scn, 0)) == NULL || data->d_size == 0) { \
+ print_error(dbg, error_msg_null[(x)],DW_DLV_OK, err); \
+ } \
+ sect_data[(x)].buf = data -> d_buf; \
+ sect_data[(x)].size = data -> d_size; \
+ }
+
+static char *reloc_type_names[] = {
+ "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32", "R_MIPS_REL32",
+ "R_MIPS_26", "R_MIPS_HI16", "R_MIPS_LO16", "R_MIPS_GPREL16",
+ "R_MIPS_LITERAL", "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16",
+ "R_MIPS_GPREL32", /* 12 */
+ "reloc type 13?", "reloc type 14?", "reloc type 15?",
+ "R_MIPS_SHIFT5", /* 16 */
+ "R_MIPS_SHIFT6", /* 17 */
+ "R_MIPS_64", /* 18 */
+ "R_MIPS_GOT_DISP", /* 19 */
+ "R_MIPS_GOT_PAGE", /* 20 */
+ "R_MIPS_GOT_OFST", /* 21 */
+ "R_MIPS_GOT_HI16", /* 22 */
+ "R_MIPS_GOT_LO16", /* 23 */
+ "R_MIPS_SUB", /* 24 */
+ "R_MIPS_INSERT_A", /* 25 */
+ "R_MIPS_INSERT_B", /* 26 */
+ "R_MIPS_DELETE", /* 27 */
+ "R_MIPS_HIGHER", /* 28 */
+ "R_MIPS_HIGHEST", /* 29 */
+ "R_MIPS_CALL_HI16", /* 30 */
+ "R_MIPS_CALL_LO16", /* 31 */
+ "R_MIPS_SCN_DISP", /* 32 */
+ "R_MIPS_REL16", /* 33 */
+ "R_MIPS_ADD_IMMEDIATE", /* 34 */
+};
+
+/*
+ return valid reloc type names.
+ if buf is used, it is static, so beware it
+ will be overrwritten by the next call.
+*/
+static char *
+get_reloc_type_names(int index)
+{
+ static char buf[100];
+ int arysiz = sizeof(reloc_type_names) / sizeof(char *);
+ char *retval;
+
+ if (index < 0 || index >= arysiz) {
+ sprintf(buf, "reloc type %d unknown", (int) index);
+ retval = buf;
+ } else {
+ retval = reloc_type_names[index];
+ }
+ return retval;
+}
+
+
+static struct {
+ Dwarf_Small *buf;
+ Dwarf_Unsigned size;
+} sect_data[DW_SECTION_REL_DEBUG_NUM];
+
+#ifndef HAVE_ELF64_GETEHDR
+#define Elf64_Addr long
+#define Elf64_Word unsigned long
+#define Elf64_Xword unsigned long
+#define Elf64_Sym long
+#endif
+
+typedef size_t indx_type;
+
+typedef struct {
+ indx_type indx;
+ char *name;
+ Elf32_Addr value;
+ Elf32_Word size;
+ int type;
+ int bind;
+ unsigned char other;
+ Elf32_Half shndx;
+} SYM;
+
+
+typedef struct {
+ indx_type indx;
+ char *name;
+ Elf64_Addr value;
+ Elf64_Xword size;
+ int type;
+ int bind;
+ unsigned char other;
+ unsigned short shndx;
+} SYM64;
+
+static void print_reloc_information_64(int section_no,
+ Dwarf_Small * buf,
+ Dwarf_Unsigned size);
+static void print_reloc_information_32(int section_no,
+ Dwarf_Small * buf,
+ Dwarf_Unsigned size);
+static SYM *readsyms(Elf32_Sym * data, size_t num, Elf * elf,
+ Elf32_Word link);
+static SYM64 *read_64_syms(Elf64_Sym * data, size_t num, Elf * elf,
+ Elf64_Word link);
+static void *get_scndata(Elf_Scn * fd_scn, size_t * scn_size);
+static void print_relocinfo_64(Dwarf_Debug dbg, Elf * elf);
+static void print_relocinfo_32(Dwarf_Debug dbg, Elf * elf);
+
+static SYM *sym_data;
+static SYM64 *sym_data_64;
+
+void
+print_relocinfo(Dwarf_Debug dbg)
+{
+ Elf *elf;
+ char *endr_ident;
+ int is_64bit;
+ int res;
+ int i;
+ Elf32_Sym *sym = 0;
+
+ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) {
+ sect_data[i].buf = 0;
+ sect_data[i].size = 0;
+ }
+ res = dwarf_get_elf(dbg, &elf, &err);
+ if (res != DW_DLV_OK) {
+ print_error(dbg, "dwarf_get_elf error", res, err);
+ }
+ if ((endr_ident = elf_getident(elf, NULL)) == NULL) {
+ print_error(dbg, "DW_ELF_GETIDENT_ERROR", res, err);
+ }
+ is_64bit = (endr_ident[EI_CLASS] == ELFCLASS64);
+ if (is_64bit) {
+ print_relocinfo_64(dbg, elf);
+ } else {
+ print_relocinfo_32(dbg, elf);
+ }
+}
+
+static void
+print_relocinfo_64(Dwarf_Debug dbg, Elf * elf)
+{
+#ifdef HAVE_ELF64_GETEHDR
+ Elf_Scn *scn = NULL;
+ Elf_Data *data;
+ Elf64_Ehdr *ehdr64;
+ Elf64_Shdr *shdr64;
+ char *scn_name;
+ int i;
+ Elf64_Sym *sym_64 = 0;
+
+ if ((ehdr64 = elf64_getehdr(elf)) == NULL) {
+ print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err);
+ }
+
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+
+ if ((shdr64 = elf64_getshdr(scn)) == NULL) {
+ print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err);
+ }
+ if ((scn_name =
+ elf_strptr(elf, ehdr64->e_shstrndx, shdr64->sh_name))
+ == NULL) {
+ print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err);
+ }
+ if (shdr64->sh_type == SHT_SYMTAB) {
+ size_t sym_size = 0;
+ size_t count = 0;
+
+ if ((sym_64 =
+ (Elf64_Sym *) get_scndata(scn, &sym_size)) == NULL) {
+ print_error(dbg, "no symbol table data", DW_DLV_OK,
+ err);
+ }
+ count = sym_size / sizeof(Elf64_Sym);
+ sym_64++;
+ free(sym_data_64);
+ sym_data_64 = read_64_syms(sym_64, count, elf, shdr64->sh_link);
+ if (sym_data_64 == NULL) {
+ print_error(dbg, "problem reading symbol table data",
+ DW_DLV_OK, err);
+ }
+ } else if (strncmp(scn_name, ".rel.debug_", 11))
+ continue;
+ else if (strcmp(scn_name, ".rel.debug_info") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_INFO)
+ } else if (strcmp(scn_name, ".rel.debug_line") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_LINE)
+ } else if (strcmp(scn_name, ".rel.debug_pubname") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_PUBNAME)
+ } else if (strcmp(scn_name, ".rel.debug_aranges") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_ARANGES)
+ } else if (strcmp(scn_name, ".rel.debug_abbrev") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_ABBREV)
+ } else if (strcmp(scn_name, ".rel.debug_frame") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_FRAME)
+ }
+ } /* while */
+
+ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) {
+ if (sect_data[i].buf != NULL && sect_data[i].size > 0) {
+ print_reloc_information_64(i, sect_data[i].buf,
+ sect_data[i].size);
+ }
+ }
+#endif
+}
+
+static void
+print_relocinfo_32(Dwarf_Debug dbg, Elf * elf)
+{
+ Elf_Scn *scn = NULL;
+ Elf_Data *data;
+ Elf32_Ehdr *ehdr32;
+ Elf32_Shdr *shdr32;
+ char *scn_name;
+ int i;
+ Elf32_Sym *sym = 0;
+
+ if ((ehdr32 = elf32_getehdr(elf)) == NULL) {
+ print_error(dbg, "DW_ELF_GETEHDR_ERROR", DW_DLV_OK, err);
+ }
+ while ((scn = elf_nextscn(elf, scn)) != NULL) {
+ if ((shdr32 = elf32_getshdr(scn)) == NULL) {
+ print_error(dbg, "DW_ELF_GETSHDR_ERROR", DW_DLV_OK, err);
+ }
+ if ((scn_name =
+ elf_strptr(elf, ehdr32->e_shstrndx, shdr32->sh_name)
+ ) == NULL) {
+ print_error(dbg, "DW_ELF_STRPTR_ERROR", DW_DLV_OK, err);
+ }
+ if (shdr32->sh_type == SHT_SYMTAB) {
+ size_t sym_size = 0;
+ size_t count = 0;
+
+ if ((sym =
+ (Elf32_Sym *) get_scndata(scn, &sym_size)) == NULL) {
+ print_error(dbg, "no symbol table data", DW_DLV_OK,
+ err);
+ }
+ sym = (Elf32_Sym *) get_scndata(scn, &sym_size);
+ count = sym_size / sizeof(Elf32_Sym);
+ sym++;
+ free(sym_data);
+ sym_data = readsyms(sym, count, elf, shdr32->sh_link);
+ if (sym_data == NULL) {
+ print_error(dbg, "problem reading symbol table data",
+ DW_DLV_OK, err);
+ }
+ } else if (strncmp(scn_name, ".rel.debug_", 11))
+ continue;
+ else if (strcmp(scn_name, ".rel.debug_info") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_INFO)
+ } else if (strcmp(scn_name, ".rel.debug_line") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_LINE)
+ } else if (strcmp(scn_name, ".rel.debug_pubname") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_PUBNAME)
+ } else if (strcmp(scn_name, ".rel.debug_aranges") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_ARANGES)
+ } else if (strcmp(scn_name, ".rel.debug_abbrev") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_ABBREV)
+ } else if (strcmp(scn_name, ".rel.debug_frame") == 0) {
+ SECT_DATA_SET(DW_SECTION_REL_DEBUG_FRAME)
+ }
+ } /* while */
+
+ for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i++) {
+ if (sect_data[i].buf != NULL && sect_data[i].size > 0) {
+ print_reloc_information_32(i, sect_data[i].buf,
+ sect_data[i].size);
+ }
+ }
+}
+
+#if HAVE_ELF64_R_INFO
+#ifndef ELF64_R_TYPE
+#define ELF64_R_TYPE(x) 0 /* FIXME */
+#endif
+#ifndef ELF64_R_SYM
+#define ELF64_R_SYM(x) 0 /* FIXME */
+#endif
+#ifndef ELF64_ST_TYPE
+#define ELF64_ST_TYPE(x) 0 /* FIXME */
+#endif
+#ifndef ELF64_ST_BIND
+#define ELF64_ST_BIND(x) 0 /* FIXME */
+#endif
+#endif /* HAVE_ELF64_R_INFO */
+
+
+static void
+print_reloc_information_64(int section_no, Dwarf_Small * buf,
+ Dwarf_Unsigned size)
+{
+ Dwarf_Unsigned off;
+
+ printf("\n%s:\n", sectnames[section_no]);
+#if HAVE_ELF64_GETEHDR
+ for (off = 0; off < size; off += sizeof(Elf64_Rel)) {
+#if HAVE_ELF64_R_INFO
+ /* This works for the Elf64_Rel in linux */
+ Elf64_Rel *p = (Elf64_Rel *) (buf + off);
+
+ printf("%5lu\t<%3ld> %-34s%s\n",
+ (unsigned long int) (p->r_offset),
+ (long)ELF64_R_SYM(p->r_info),
+ sym_data[ELF64_R_SYM(p->r_info) - 1].name,
+ get_reloc_type_names(ELF64_R_TYPE(p->r_info)));
+#else
+ /* sgi/mips -64 does not have r_info in the 64bit relocations,
+ but seperate fields, with 3 types, actually. Only one of
+ which prints here, as only one really used with dwarf */
+ Elf64_Rel *p = (Elf64_Rel *) (buf + off);
+
+ printf("%5llu\t<%3d> %-34s%s\n",
+ (unsigned long long int) (p->r_offset),
+ (long)p->r_sym, sym_data_64[p->r_sym - 1].name,
+ get_reloc_type_names(p->r_type));
+#endif
+ }
+#endif /* HAVE_ELF64_GETEHDR */
+}
+
+static void
+print_reloc_information_32(int section_no, Dwarf_Small * buf,
+ Dwarf_Unsigned size)
+{
+ Dwarf_Unsigned off;
+
+ printf("\n%s:\n", sectnames[section_no]);
+ for (off = 0; off < size; off += sizeof(Elf32_Rel)) {
+ Elf32_Rel *p = (Elf32_Rel *) (buf + off);
+
+ printf("%5lu\t<%3d> %-34s%s\n",
+ (unsigned long int) (p->r_offset),
+ ELF32_R_SYM(p->r_info),
+ sym_data[ELF32_R_SYM(p->r_info) - 1].name,
+ get_reloc_type_names(ELF32_R_TYPE(p->r_info)));
+ }
+}
+
+static SYM *
+readsyms(Elf32_Sym * data, size_t num, Elf * elf, Elf32_Word link)
+{
+ SYM *s, *buf;
+ indx_type i;
+
+ if ((buf = (SYM *) calloc(num, sizeof(SYM))) == NULL) {
+ return NULL;
+ }
+ s = buf; /* save pointer to head of array */
+ for (i = 1; i < num; i++, data++, buf++) {
+ buf->indx = i;
+ buf->name = (char *) elf_strptr(elf, link, data->st_name);
+ buf->value = data->st_value;
+ buf->size = data->st_size;
+ buf->type = ELF32_ST_TYPE(data->st_info);
+ buf->bind = ELF32_ST_BIND(data->st_info);
+ buf->other = data->st_other;
+ buf->shndx = data->st_shndx;
+ } /* end for loop */
+ return (s);
+}
+
+static SYM64 *
+read_64_syms(Elf64_Sym * data, size_t num, Elf * elf, Elf64_Word link)
+{
+#ifdef HAVE_ELF64_GETEHDR
+
+ SYM64 *s, *buf;
+ indx_type i;
+
+ if ((buf = (SYM64 *) calloc(num, sizeof(SYM64))) == NULL) {
+ return NULL;
+ }
+ s = buf; /* save pointer to head of array */
+ for (i = 1; i < num; i++, data++, buf++) {
+ buf->indx = i;
+ buf->name = (char *) elf_strptr(elf, link, data->st_name);
+ buf->value = data->st_value;
+ buf->size = data->st_size;
+ buf->type = ELF64_ST_TYPE(data->st_info);
+ buf->bind = ELF64_ST_BIND(data->st_info);
+ buf->other = data->st_other;
+ buf->shndx = data->st_shndx;
+ } /* end for loop */
+ return (s);
+#else
+ return 0;
+#endif /* HAVE_ELF64_GETEHDR */
+}
+
+static void *
+get_scndata(Elf_Scn * fd_scn, size_t * scn_size)
+{
+ Elf_Data *p_data;
+
+ p_data = 0;
+ if ((p_data = elf_getdata(fd_scn, p_data)) == 0 ||
+ p_data->d_size == 0) {
+ return NULL;
+ }
+ *scn_size = p_data->d_size;
+ return (p_data->d_buf);
+}
+
+/* Cleanup of malloc space (some of the pointers will be 0 here)
+ so dwarfdump looks 'clean' to a malloc checker.
+*/
+void
+clean_up_syms_malloc_data()
+{
+ free(sym_data);
+ free(sym_data_64);
+}