00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "globals.h"
00037
00038
00039 #define DW_SECTION_REL_DEBUG_INFO 0
00040 #define DW_SECTION_REL_DEBUG_LINE 1
00041 #define DW_SECTION_REL_DEBUG_PUBNAME 2
00042 #define DW_SECTION_REL_DEBUG_ABBREV 3
00043 #define DW_SECTION_REL_DEBUG_ARANGES 4
00044 #define DW_SECTION_REL_DEBUG_FRAME 5
00045 #define DW_SECTION_REL_DEBUG_NUM 6
00046
00047 #define DW_SECTNAME_REL_DEBUG_INFO ".rel.debug_info"
00048 #define DW_SECTNAME_REL_DEBUG_LINE ".rel.debug_line"
00049 #define DW_SECTNAME_REL_DEBUG_PUBNAME ".rel.debug_pubname"
00050 #define DW_SECTNAME_REL_DEBUG_ABBREV ".rel.debug_abbrev"
00051 #define DW_SECTNAME_REL_DEBUG_ARANGES ".rel.debug_aranges"
00052 #define DW_SECTNAME_REL_DEBUG_FRAME ".rel.debug_frame"
00053
00054 #define STRING_FOR_DUPLICATE " duplicate"
00055 #define STRING_FOR_NULL " null"
00056
00057 static char *sectnames[ ] = {
00058 DW_SECTNAME_REL_DEBUG_INFO,
00059 DW_SECTNAME_REL_DEBUG_LINE,
00060 DW_SECTNAME_REL_DEBUG_PUBNAME,
00061 DW_SECTNAME_REL_DEBUG_ABBREV,
00062 DW_SECTNAME_REL_DEBUG_ARANGES,
00063 DW_SECTNAME_REL_DEBUG_FRAME,
00064 };
00065
00066 static char *error_msg_duplicate[ ] = {
00067 DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_DUPLICATE,
00068 DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_DUPLICATE,
00069 DW_SECTNAME_REL_DEBUG_PUBNAME STRING_FOR_DUPLICATE,
00070 DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_DUPLICATE,
00071 DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_DUPLICATE,
00072 DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_DUPLICATE,
00073 };
00074
00075 static char *error_msg_null[ ] = {
00076 DW_SECTNAME_REL_DEBUG_INFO STRING_FOR_NULL,
00077 DW_SECTNAME_REL_DEBUG_LINE STRING_FOR_NULL,
00078 DW_SECTNAME_REL_DEBUG_PUBNAME STRING_FOR_NULL,
00079 DW_SECTNAME_REL_DEBUG_ABBREV STRING_FOR_NULL,
00080 DW_SECTNAME_REL_DEBUG_ARANGES STRING_FOR_NULL,
00081 DW_SECTNAME_REL_DEBUG_FRAME STRING_FOR_NULL,
00082 };
00083
00084 #define SECT_DATA_SET(x) { \
00085 if (sect_data[(x)].buf != NULL) { \
00086 print_error(dbg, error_msg_duplicate[(x)],DW_DLV_OK, err); \
00087 } \
00088 if ((data = elf_getdata(scn, 0)) == NULL || data->d_size == 0) { \
00089 print_error(dbg, error_msg_null[(x)],DW_DLV_OK, err); \
00090 } \
00091 sect_data[(x)].buf = data -> d_buf; \
00092 sect_data[(x)].size = data -> d_size; \
00093 }
00094
00095 static char *reloc_type_names[ ] = {
00096 "R_MIPS_NONE", "R_MIPS_16", "R_MIPS_32", "R_MIPS_REL32",
00097 "R_MIPS_26", "R_MIPS_HI16", "R_MIPS_LO16", "R_MIPS_GPREL16",
00098 "R_MIPS_LITERAL", "R_MIPS_GOT16", "R_MIPS_PC16", "R_MIPS_CALL16",
00099 "R_MIPS_GPREL32",
00100 "reloc type 13?", "reloc type 14?", "reloc type 15?",
00101 "R_MIPS_SHIFT5",
00102 "R_MIPS_SHIFT6",
00103 "R_MIPS_64",
00104 "R_MIPS_GOT_DISP",
00105 "R_MIPS_GOT_PAGE",
00106 "R_MIPS_GOT_OFST",
00107 "R_MIPS_GOT_HI16",
00108 "R_MIPS_GOT_LO16",
00109 "R_MIPS_SUB",
00110 "R_MIPS_INSERT_A",
00111 "R_MIPS_INSERT_B",
00112 "R_MIPS_DELETE",
00113 "R_MIPS_HIGHER",
00114 "R_MIPS_HIGHEST",
00115 "R_MIPS_CALL_HI16",
00116 "R_MIPS_CALL_LO16",
00117 "R_MIPS_SCN_DISP",
00118 "R_MIPS_REL16",
00119 "R_MIPS_ADD_IMMEDIATE",
00120 };
00121
00122
00123
00124
00125
00126
00127 static char *
00128 get_reloc_type_names(int index)
00129 {
00130 static char buf[100];
00131 int arysiz = sizeof(reloc_type_names)/sizeof(char *);
00132 char* retval;
00133
00134 if(index < 0 || index >= arysiz ) {
00135 sprintf(buf,"reloc type %d unknown",(int)index);
00136 retval = buf;
00137 } else {
00138 retval = reloc_type_names[index];
00139 }
00140 return retval;
00141 }
00142
00143
00144 static struct {
00145 Dwarf_Small *buf;
00146 Dwarf_Unsigned size;
00147 } sect_data[DW_SECTION_REL_DEBUG_NUM];
00148
00149 #ifndef HAVE_ELF64_GETEHDR
00150 #define Elf64_Addr long
00151 #define Elf64_Word unsigned long
00152 #define Elf64_Sym long
00153 #endif
00154
00155 typedef struct {
00156 int indx;
00157 char *name;
00158 Elf32_Addr value;
00159 Elf32_Word size;
00160 int type;
00161 int bind;
00162 unsigned char other;
00163 Elf32_Half shndx;
00164 } SYM;
00165
00166
00167 typedef struct {
00168 int indx;
00169 char *name;
00170 Elf64_Addr value;
00171 Elf64_Word size;
00172 int type;
00173 int bind;
00174 unsigned char other;
00175 unsigned short shndx;
00176 } SYM64;
00177
00178 static void print_reloc_information_64(int section_no, Dwarf_Small *buf,
00179 Dwarf_Unsigned size);
00180 static void print_reloc_information_32(int section_no, Dwarf_Small *buf,
00181 Dwarf_Unsigned size);
00182 static SYM *readsyms(Elf32_Sym *data, size_t num, Elf *elf, Elf32_Word link);
00183 static SYM64 *read_64_syms(Elf64_Sym *data, size_t num, Elf *elf,
00184 Elf64_Word link);
00185 static void *get_scndata(Elf_Scn *fd_scn, size_t *scn_size);
00186 static void print_relocinfo_64 (Dwarf_Debug dbg, Elf *elf);
00187 static void print_relocinfo_32 (Dwarf_Debug dbg, Elf *elf);
00188
00189 static Elf32_Sym *sym;
00190 static Elf64_Sym *sym_64;
00191 static SYM *sym_data;
00192 static SYM64 *sym_data_64;
00193
00194 void print_relocinfo (Dwarf_Debug dbg)
00195 {
00196 Elf *elf;
00197 char *endr_ident;
00198 int is_64bit;
00199 int res;
00200 int i;
00201
00202 for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i ++) {
00203 sect_data[i].buf = 0;
00204 sect_data[i].size = 0;
00205 }
00206 res = dwarf_get_elf(dbg,&elf, &err);
00207 if(res != DW_DLV_OK) {
00208 print_error(dbg, "dwarf_get_elf error",res, err);
00209 }
00210 if ((endr_ident = elf_getident(elf, NULL)) == NULL) {
00211 print_error(dbg, "DW_ELF_GETIDENT_ERROR",res, err);
00212 }
00213 is_64bit = (endr_ident[EI_CLASS] == ELFCLASS64);
00214 if (is_64bit) {
00215 print_relocinfo_64(dbg, elf);
00216 }
00217 else {
00218 print_relocinfo_32(dbg, elf);
00219 }
00220 }
00221
00222 static void print_relocinfo_64 (Dwarf_Debug dbg, Elf *elf)
00223 {
00224 #ifdef HAVE_ELF64_GETEHDR
00225 Elf_Scn *scn = NULL;
00226 Elf_Data *data;
00227 Elf64_Ehdr *ehdr64;
00228 Elf64_Shdr *shdr64;
00229 char *scn_name;
00230 int i;
00231
00232 if ((ehdr64 = elf64_getehdr(elf)) == NULL) {
00233 print_error(dbg, "DW_ELF_GETEHDR_ERROR",DW_DLV_OK, err);
00234 }
00235
00236 while ((scn = elf_nextscn(elf, scn)) != NULL) {
00237
00238 if ((shdr64 = elf64_getshdr(scn)) == NULL) {
00239 print_error(dbg, "DW_ELF_GETSHDR_ERROR",DW_DLV_OK, err);
00240 }
00241 if ((scn_name = elf_strptr(elf,ehdr64->e_shstrndx, shdr64->sh_name))
00242 == NULL) {
00243 print_error(dbg, "DW_ELF_STRPTR_ERROR",DW_DLV_OK, err);
00244 }
00245 if (shdr64->sh_type == SHT_SYMTAB) {
00246 size_t sym_size = 0;
00247 size_t count = 0;
00248 if ((sym_64 = (Elf64_Sym *) get_scndata(scn, &sym_size)) == NULL) {
00249 print_error(dbg, "no symbol table data",DW_DLV_OK, err);
00250 }
00251 count = sym_size / sizeof (Elf64_Sym);
00252 sym_64 ++;
00253 if ((sym_data_64 = read_64_syms(sym_64, count, elf,
00254 shdr64->sh_link)) == NULL) {
00255 print_error(dbg, "problem reading symbol table data",DW_DLV_OK, err);
00256 }
00257 }
00258 else if (strncmp(scn_name, ".rel.debug_", 11))
00259 continue;
00260 else if (strcmp(scn_name, ".rel.debug_info") == 0) {
00261 SECT_DATA_SET(DW_SECTION_REL_DEBUG_INFO)
00262 }
00263 else if (strcmp(scn_name, ".rel.debug_line") == 0) {
00264 SECT_DATA_SET(DW_SECTION_REL_DEBUG_LINE)
00265 }
00266 else if (strcmp(scn_name, ".rel.debug_pubname") == 0) {
00267 SECT_DATA_SET(DW_SECTION_REL_DEBUG_PUBNAME)
00268 }
00269 else if (strcmp(scn_name, ".rel.debug_aranges") == 0) {
00270 SECT_DATA_SET(DW_SECTION_REL_DEBUG_ARANGES)
00271 }
00272 else if (strcmp(scn_name, ".rel.debug_abbrev") == 0) {
00273 SECT_DATA_SET(DW_SECTION_REL_DEBUG_ABBREV)
00274 }
00275 else if (strcmp(scn_name, ".rel.debug_frame") == 0) {
00276 SECT_DATA_SET(DW_SECTION_REL_DEBUG_FRAME)
00277 }
00278 }
00279
00280 for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i ++) {
00281 if (sect_data[i].buf != NULL && sect_data[i].size > 0) {
00282 print_reloc_information_64(i, sect_data[i].buf, sect_data[i].size);
00283 }
00284 }
00285 #endif
00286 }
00287
00288 static void print_relocinfo_32 (Dwarf_Debug dbg, Elf *elf)
00289 {
00290 Elf_Scn *scn = NULL;
00291 Elf_Data *data;
00292 Elf32_Ehdr *ehdr32;
00293 Elf32_Shdr *shdr32;
00294 char *scn_name;
00295 int i;
00296
00297 if ((ehdr32 = elf32_getehdr(elf)) == NULL) {
00298 print_error(dbg, "DW_ELF_GETEHDR_ERROR",DW_DLV_OK, err);
00299 }
00300 while ((scn = elf_nextscn(elf, scn)) != NULL) {
00301 if ((shdr32 = elf32_getshdr(scn)) == NULL) {
00302 print_error(dbg, "DW_ELF_GETSHDR_ERROR",DW_DLV_OK, err);
00303 }
00304 if ((scn_name = elf_strptr(elf,ehdr32->e_shstrndx, shdr32->sh_name)
00305 ) == NULL) {
00306 print_error(dbg, "DW_ELF_STRPTR_ERROR",DW_DLV_OK, err);
00307 }
00308 if (shdr32->sh_type == SHT_SYMTAB) {
00309 size_t sym_size = 0;
00310 size_t count = 0;
00311 if ((sym = (Elf32_Sym *) get_scndata(scn, &sym_size)) == NULL) {
00312 print_error(dbg, "no symbol table data",DW_DLV_OK, err);
00313 }
00314 sym = (Elf32_Sym *) get_scndata(scn, &sym_size);
00315 count = sym_size / sizeof (Elf32_Sym);
00316 sym ++;
00317 if ((sym_data = readsyms(sym, count, elf,
00318 shdr32->sh_link)) == NULL) {
00319 print_error(dbg, "problem reading symbol table data",DW_DLV_OK, err);
00320 }
00321 }
00322 else if (strncmp(scn_name, ".rel.debug_", 11))
00323 continue;
00324 else if (strcmp(scn_name, ".rel.debug_info") == 0) {
00325 SECT_DATA_SET(DW_SECTION_REL_DEBUG_INFO)
00326 }
00327 else if (strcmp(scn_name, ".rel.debug_line") == 0) {
00328 SECT_DATA_SET(DW_SECTION_REL_DEBUG_LINE)
00329 }
00330 else if (strcmp(scn_name, ".rel.debug_pubname") == 0) {
00331 SECT_DATA_SET(DW_SECTION_REL_DEBUG_PUBNAME)
00332 }
00333 else if (strcmp(scn_name, ".rel.debug_aranges") == 0) {
00334 SECT_DATA_SET(DW_SECTION_REL_DEBUG_ARANGES)
00335 }
00336 else if (strcmp(scn_name, ".rel.debug_abbrev") == 0) {
00337 SECT_DATA_SET(DW_SECTION_REL_DEBUG_ABBREV)
00338 }
00339 else if (strcmp(scn_name, ".rel.debug_frame") == 0) {
00340 SECT_DATA_SET(DW_SECTION_REL_DEBUG_FRAME)
00341 }
00342 }
00343
00344 for (i = 0; i < DW_SECTION_REL_DEBUG_NUM; i ++) {
00345 if (sect_data[i].buf != NULL && sect_data[i].size > 0) {
00346 print_reloc_information_32(i, sect_data[i].buf, sect_data[i].size);
00347 }
00348 }
00349 }
00350
00351 #if HAVE_ELF64_R_INFO
00352 #ifndef ELF64_R_TYPE
00353 #define ELF64_R_TYPE(x) 0
00354 #endif
00355 #ifndef ELF64_R_SYM
00356 #define ELF64_R_SYM(x) 0
00357 #endif
00358 #ifndef ELF64_ST_TYPE
00359 #define ELF64_ST_TYPE(x) 0
00360 #endif
00361 #ifndef ELF64_ST_BIND
00362 #define ELF64_ST_BIND(x) 0
00363 #endif
00364 #endif
00365
00366
00367 static void print_reloc_information_64(int section_no, Dwarf_Small *buf,
00368 Dwarf_Unsigned size)
00369 {
00370 Dwarf_Unsigned off;
00371 printf("\n%s:\n", sectnames[section_no]);
00372 #if HAVE_ELF64_GETEHDR
00373 for (off = 0; off < size; off += sizeof (Elf64_Rel)) {
00374 #if HAVE_ELF64_R_INFO
00375
00376
00377 Elf64_Rel *p = (Elf64_Rel *) (buf + off);
00378 printf("%5lu\t<%3lld> %-34s%s\n", (unsigned long int) (p->r_offset),
00379 (long long) ELF64_R_SYM(p->r_info),
00380 sym_data[ELF64_R_SYM(p->r_info) - 1].name,
00381 get_reloc_type_names(ELF64_R_TYPE(p->r_info)));
00382 #else
00383
00384
00385
00386
00387
00388 Elf64_Rel *p = (Elf64_Rel *) (buf + off);
00389 printf("%5llu\t<%3d> %-34s%s\n",
00390 (unsigned long long int) (p -> r_offset),
00391 p -> r_sym, sym_data_64[p -> r_sym - 1] . name,
00392 get_reloc_type_names(p -> r_type));
00393 #endif
00394 }
00395 #endif
00396 }
00397
00398 static void print_reloc_information_32(int section_no, Dwarf_Small *buf,
00399 Dwarf_Unsigned size)
00400 {
00401 Dwarf_Unsigned off;
00402 printf("\n%s:\n", sectnames[section_no]);
00403 for (off = 0; off < size; off += sizeof (Elf32_Rel)) {
00404 Elf32_Rel *p = (Elf32_Rel *) (buf + off);
00405 printf("%5lu\t<%3d> %-34s%s\n", (unsigned long int) (p->r_offset),
00406 (int)ELF32_R_SYM(p->r_info),
00407 sym_data[ELF32_R_SYM(p->r_info) - 1].name,
00408 get_reloc_type_names(ELF32_R_TYPE(p->r_info)));
00409 }
00410 }
00411
00412 static SYM *
00413 readsyms(Elf32_Sym *data, size_t num, Elf *elf, Elf32_Word link)
00414 {
00415 SYM *s, *buf;
00416 size_t i;
00417 if((buf = (SYM *)calloc(num, sizeof(SYM)) ) == NULL) {
00418 return NULL;
00419 }
00420 s = buf;
00421 for(i=1; i<num; i++,data++,buf++) {
00422 buf->indx = i;
00423 buf->name = (char *)elf_strptr(elf, link, data->st_name);
00424 buf->value = data->st_value;
00425 buf->size = data->st_size;
00426 buf->type = ELF32_ST_TYPE(data->st_info);
00427 buf->bind = ELF32_ST_BIND(data->st_info);
00428 buf->other = data->st_other;
00429 buf->shndx = data->st_shndx;
00430 }
00431 return(s);
00432 }
00433
00434 static SYM64 *
00435 read_64_syms(Elf64_Sym *data, size_t num, Elf *elf, Elf64_Word link)
00436 {
00437 #ifdef HAVE_ELF64_GETEHDR
00438
00439 SYM64 *s, *buf;
00440 size_t i;
00441 if( (buf = (SYM64 *)calloc(num, sizeof(SYM64)) ) == NULL) {
00442 return NULL;
00443 }
00444 s = buf;
00445 for(i=1; i<num; i++,data++,buf++) {
00446 buf->indx = i;
00447 buf->name = (char *)elf_strptr(elf, link, data->st_name);
00448 buf->value = data->st_value;
00449 buf->size = data->st_size;
00450 buf->type = ELF64_ST_TYPE(data->st_info);
00451 buf->bind = ELF64_ST_BIND(data->st_info);
00452 buf->other = data->st_other;
00453 buf->shndx = data->st_shndx;
00454 }
00455 return(s);
00456 #else
00457 return 0;
00458 #endif
00459 }
00460
00461 static void *
00462 get_scndata( Elf_Scn *fd_scn, size_t *scn_size)
00463 {
00464 Elf_Data *p_data;
00465 p_data = 0;
00466 if((p_data = elf_getdata(fd_scn, p_data)) == 0 ||
00467 p_data->d_size == 0) {
00468 return NULL;
00469 }
00470 *scn_size = p_data->d_size;
00471 return( p_data->d_buf );
00472 }