00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "elfstruc.h"
00022 #include "htatom.h"
00023 #include "htelf.h"
00024 #include "htelfrel.h"
00025 #include "httag.h"
00026 #include "formats.h"
00027 #include "snprintf.h"
00028
00029 #include <stdlib.h>
00030
00031 static int_hash elf_r_386_type[] =
00032 {
00033 {ELF_R_386_NONE, "ELF_R_386_NONE"},
00034 {ELF_R_386_32, "ELF_R_386_32"},
00035 {ELF_R_386_PC32, "ELF_R_386_PC32"},
00036 {ELF_R_386_GOT32, "ELF_R_386_GOT32"},
00037 {ELF_R_386_PLT32, "ELF_R_386_PLT32"},
00038 {ELF_R_386_COPY, "ELF_R_386_COPY"},
00039 {ELF_R_386_GLOB_DAT, "ELF_R_386_GLOB_DAT"},
00040 {ELF_R_386_JMP_SLOT, "ELF_R_386_JMP_SLOT"},
00041 {ELF_R_386_RELATIVE, "ELF_R_386_RELATIVE"},
00042 {ELF_R_386_GOTOFF, "ELF_R_386_GOTOFF"},
00043 {ELF_R_386_GOTPC, "ELF_R_386_GOTPC"},
00044 {0, 0}
00045 };
00046
00047 static ht_view *htelfreloctable_init(bounds *b, ht_streamfile *file, ht_format_group *group)
00048 {
00049 ht_elf_shared_data *elf_shared=(ht_elf_shared_data *)group->get_shared_data();
00050
00051 if ((elf_shared->ident.e_ident[ELF_EI_CLASS]!=ELFCLASS32) ||
00052 (elf_shared->ident.e_ident[ELF_EI_DATA]!=ELFDATA2LSB) ||
00053 (elf_shared->header32.e_machine!=ELF_EM_386)) return NULL;
00054
00055 UINT skip = elf_shared->reloctables;
00056 UINT reloctab_shidx = ELF_SHN_UNDEF;
00057 UINT reloctab_sh_type = ELF_SHT_NULL;
00058 for (UINT i=1; i<elf_shared->sheaders.count; i++) {
00059 if ((elf_shared->sheaders.sheaders32[i].sh_type==ELF_SHT_REL) || (elf_shared->sheaders.sheaders32[i].sh_type==ELF_SHT_RELA)) {
00060 if (!skip--) {
00061 reloctab_sh_type=elf_shared->sheaders.sheaders32[i].sh_type;
00062 reloctab_shidx=i;
00063 break;
00064 }
00065 }
00066 }
00067 if (!isValidELFSectionIdx(elf_shared, reloctab_shidx)) return NULL;
00068
00069 FILEOFS h=elf_shared->sheaders.sheaders32[reloctab_shidx].sh_offset;
00070
00071
00072 int si_symbol=elf_shared->sheaders.sheaders32[reloctab_shidx].sh_link;
00073
00074
00075 int si_dest=elf_shared->sheaders.sheaders32[reloctab_shidx].sh_info;
00076
00077 char *reloctab_name;
00078 if (!isValidELFSectionIdx(elf_shared, elf_shared->header32.e_shstrndx)
00079 || file->seek(elf_shared->sheaders.sheaders32[elf_shared->header32.
00080 e_shstrndx].sh_offset+elf_shared->sheaders.sheaders32[reloctab_shidx].sh_name)
00081 || !((reloctab_name=fgetstrz(file))))
00082 reloctab_name = "?";
00083 char desc[128];
00084 ht_snprintf(desc, sizeof desc, DESC_ELF_RELOCTAB, reloctab_name, reloctab_shidx);
00085 free(reloctab_name);
00086
00087 ht_uformat_viewer *v=new ht_uformat_viewer();
00088 v->init(b, desc, VC_EDIT, file, group);
00089
00090 ht_mask_sub *m=new ht_mask_sub();
00091 m->init(file, 0);
00092
00093 register_atom(ATOM_ELF_R_386_TYPE, elf_r_386_type);
00094
00095 char t[256];
00096 ht_snprintf(t, sizeof t, "* ELF relocation table at offset %08x, relocates section %d, symtab %d", h, si_dest, si_symbol);
00097
00098 m->add_mask(t);
00099
00100 bool elf_bigendian = (elf_shared->ident.e_ident[ELF_EI_DATA] == ELFDATA2MSB);
00101
00102 switch (reloctab_sh_type) {
00103 case ELF_SHT_REL: {
00104 m->add_mask("destofs symidx type");
00105 UINT relnum=elf_shared->sheaders.sheaders32[reloctab_shidx].sh_size / sizeof (ELF_REL32);
00106 for (UINT i=0; i<relnum; i++) {
00107 char *tt=t;
00108
00109 tt=tag_make_edit_dword(tt, h+i*sizeof (ELF_REL32), elf_bigendian ? tag_endian_big : tag_endian_little);
00110 *tt++=' ';
00111
00112 tt=tag_make_edit_word(tt, h+i*sizeof (ELF_REL32)+4+1, elf_bigendian ? tag_endian_big : tag_endian_little);
00113 *tt++=' ';
00114 *tt++=' ';
00115 *tt++=' ';
00116
00117 tt=tag_make_edit_byte(tt, h+i*sizeof (ELF_REL32)+4);
00118 *tt++='(';
00119
00120 tt=tag_make_desc_byte(tt, h+i*sizeof (ELF_REL32)+4, ATOM_ELF_R_386_TYPE);
00121 *tt++=')';
00122 *tt=0;
00123 m->add_mask(t);
00124 }
00125 break;
00126 }
00127 case ELF_SHT_RELA: {
00128 m->add_mask("destofs symidx addend type");
00129 UINT relnum=elf_shared->sheaders.sheaders32[reloctab_shidx].sh_size / sizeof (ELF_RELA32);
00130 for (UINT i=0; i<relnum; i++) {
00131 char *tt=t;
00132
00133 tt=tag_make_edit_dword(tt, h+i*sizeof (ELF_RELA32), elf_bigendian ? tag_endian_big : tag_endian_little);
00134 *tt++=' ';
00135
00136 tt=tag_make_edit_word(tt, h+i*sizeof (ELF_RELA32)+4+1, elf_bigendian ? tag_endian_big : tag_endian_little);
00137 *tt++=' ';
00138 *tt++=' ';
00139 *tt++=' ';
00140
00141 tt=tag_make_edit_dword(tt, h+i*sizeof (ELF_RELA32)+4+4, elf_bigendian ? tag_endian_big : tag_endian_little);
00142 *tt++=' ';
00143
00144 tt=tag_make_edit_byte(tt, h+i*sizeof (ELF_RELA32)+4);
00145 *tt++='(';
00146
00147 tt=tag_make_desc_byte(tt, h+i*sizeof (ELF_RELA32)+4, ATOM_ELF_R_386_TYPE);
00148 *tt++=')';
00149 *tt=0;
00150 m->add_mask(t);
00151 }
00152 break;
00153 }
00154 }
00155
00156 v->insertsub(m);
00157 return v;
00158 }
00159
00160 format_viewer_if htelfreloctable_if = {
00161 htelfreloctable_init,
00162 0
00163 };