00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "coff_s.h"
00022 #include "log.h"
00023 #include "htcoff.h"
00024 #include "htcoffhd.h"
00025 #include "htcoffimg.h"
00026 #include "htendian.h"
00027 #include "mzstruct.h"
00028 #include "stream.h"
00029
00030 #include <stdlib.h>
00031 #include <string.h>
00032
00033 format_viewer_if *htcoff_ifs[] = {
00034 &htcoffheader_if,
00035 &htcoffimage_if,
00036 0
00037 };
00038
00039 static bool is_coff(ht_streamfile *file, endianess &endian, FILEOFS ofs)
00040 {
00041
00042
00043 COFF_HEADER h;
00044 bool machine_found = false;
00045 endianess end;
00046
00047
00048
00049
00050 file->seek(ofs);
00051 if (file->read(&h, sizeof h) != sizeof h) return false;
00052 create_host_struct(&h, COFF_HEADER_struct, little_endian);
00053 switch (h.machine) {
00054 case COFF_MACHINE_I386:
00055 case COFF_MACHINE_I486:
00056 case COFF_MACHINE_I586:
00057 case COFF_MACHINE_R3000:
00058 case COFF_MACHINE_R4000:
00059 case COFF_MACHINE_R10000:
00060 case COFF_MACHINE_ALPHA:
00061 case COFF_MACHINE_SH3:
00062 case COFF_MACHINE_SH4:
00063 case COFF_MACHINE_ARM:
00064 case COFF_MACHINE_POWERPC_LE:
00065
00066 case COFF_MACHINE_MIPS16:
00067 case COFF_MACHINE_68k:
00068
00069 case COFF_MACHINE_MIPSf:
00070 case COFF_MACHINE_MIPS16f:
00071 end = little_endian;
00072 machine_found = true;
00073 }
00074
00075
00076 if (!machine_found) {
00077 file->seek(ofs);
00078 if (file->read(&h, sizeof h)!=sizeof h) return 0;
00079 create_host_struct(&h, COFF_HEADER_struct, big_endian);
00080 switch (h.machine) {
00081 case COFF_MACHINE_R3000BE:
00082 case COFF_MACHINE_POWERPC_BE:
00083 end = big_endian;
00084 machine_found = true;
00085 }
00086 }
00087 if (!machine_found) return false;
00088
00089
00090
00091
00092 switch (h.optional_header_size) {
00093 case COFF_OPTSIZE_0:
00094 case COFF_OPTSIZE_COFF32:
00095 case COFF_OPTSIZE_XCOFF32:
00096 break;
00097 default:
00098 return false;
00099 }
00100
00101
00102 endian = end;
00103 return true;
00104 }
00105
00106 static ht_view *htcoff_init(bounds *b, ht_streamfile *file, ht_format_group *format_group)
00107 {
00108 FILEOFS h;
00109 endianess end;
00110
00111 if (!is_coff(file, end, h = 0)) {
00112
00113 byte mz[2];
00114 file->seek(0);
00115 if (file->read(mz, 2) != 2) return 0;
00116 if ((mz[0] != IMAGE_MZ_MAGIC0) || (mz[1] != IMAGE_MZ_MAGIC1) ||
00117 (!is_coff(file, end, h = 0x800)))
00118 return 0;
00119 }
00120
00121 ht_coff *g = new ht_coff();
00122 g->init(b, file, htcoff_ifs, format_group, h, end);
00123 return g;
00124 }
00125
00126 format_viewer_if htcoff_if = {
00127 htcoff_init,
00128 0
00129 };
00130
00131
00132
00133
00134 void ht_coff::init(bounds *b, ht_streamfile *file, format_viewer_if **ifs, ht_format_group *format_group, FILEOFS h, endianess end)
00135 {
00136 ht_format_group::init(b, VO_BROWSABLE | VO_SELECTABLE | VO_RESIZE, DESC_COFF, file, false, true, 0, format_group);
00137 VIEW_DEBUG_NAME("ht_coff");
00138
00139 LOG("%s: COFF: found header at %08x", file->get_filename(), h);
00140 coff_shared = (ht_coff_shared_data *)malloc(sizeof(*coff_shared));
00141 coff_shared->hdr_ofs = h;
00142 coff_shared->sections.hdr_ofs = h;
00143 coff_shared->v_image = NULL;
00144 coff_shared->v_header = NULL;
00145 coff_shared->endian = end;
00146
00147
00148 file->seek(h);
00149 file->read(&coff_shared->coffheader, sizeof coff_shared->coffheader);
00150 create_host_struct(&coff_shared->coffheader, COFF_HEADER_struct, end);
00151 coff_shared->opt_magic = 0;
00152 if (coff_shared->coffheader.optional_header_size >= 2) {
00153 file->read(&coff_shared->opt_magic, sizeof coff_shared->opt_magic);
00154 file->seek(h + sizeof coff_shared->coffheader);
00155 coff_shared->opt_magic = create_host_int(&coff_shared->opt_magic, 2, end);
00156 switch (coff_shared->opt_magic) {
00157 case COFF_OPTMAGIC_COFF32:
00158 file->read(&coff_shared->coff32header, sizeof coff_shared->coff32header);
00159 create_host_struct(&coff_shared->coff32header, COFF_OPTIONAL_HEADER32_struct, end);
00160 break;
00161 }
00162 }
00163
00164
00165 int os = coff_shared->coffheader.optional_header_size;
00166 coff_shared->sections.section_count = coff_shared->coffheader.section_count;
00167
00168 h -= 4;
00169
00170 file->seek(h+os+24);
00171 coff_shared->sections.sections=(COFF_SECTION_HEADER*)malloc(coff_shared->sections.section_count * sizeof *coff_shared->sections.sections);
00172 file->read(coff_shared->sections.sections, coff_shared->sections.section_count*sizeof *coff_shared->sections.sections);
00173 for (UINT i=0; i<coff_shared->sections.section_count; i++) {
00174 create_host_struct(&coff_shared->sections.sections[i], COFF_SECTION_HEADER_struct, end);
00175 }
00176
00177 shared_data = coff_shared;
00178
00179 ht_format_group::init_ifs(ifs);
00180 }
00181
00182 void ht_coff::done()
00183 {
00184 ht_format_group::done();
00185 free(shared_data);
00186 }
00187
00188
00189
00190
00191
00192 int coff_rva_to_section(coff_section_headers *section_headers, RVA rva, int *section)
00193 {
00194 COFF_SECTION_HEADER *s=section_headers->sections;
00195 for (UINT i=0; i<section_headers->section_count; i++) {
00196 if ((rva >= s->data_address) && (rva < s->data_address+s->data_size)) {
00197 *section = i;
00198 return 1;
00199 }
00200 s++;
00201 }
00202 return 0;
00203 }
00204
00205 int coff_rva_to_ofs(coff_section_headers *section_headers, RVA rva, dword *ofs)
00206 {
00207 COFF_SECTION_HEADER *s=section_headers->sections;
00208 for (UINT i=0; i<section_headers->section_count; i++) {
00209 if (s->data_offset && (rva >= s->data_address) &&
00210 (rva < s->data_address+s->data_size)) {
00211 *ofs = rva-s->data_address+s->data_offset+section_headers->hdr_ofs;
00212 return 1;
00213 }
00214 s++;
00215 }
00216 return 0;
00217 }
00218
00219 int coff_rva_is_valid(coff_section_headers *section_headers, RVA rva)
00220 {
00221 COFF_SECTION_HEADER *s=section_headers->sections;
00222 for (UINT i=0; i<section_headers->section_count; i++) {
00223 if ((rva >= s->data_address) && (rva < s->data_address+s->data_size)) {
00224 return 1;
00225 }
00226 s++;
00227 }
00228 return 0;
00229 }
00230
00231 int coff_rva_is_physical(coff_section_headers *section_headers, RVA rva)
00232 {
00233 COFF_SECTION_HEADER *s=section_headers->sections;
00234 for (UINT i=0; i<section_headers->section_count; i++) {
00235 if (s->data_offset && (rva >= s->data_address) &&
00236 (rva < s->data_address+s->data_size)) {
00237 return 1;
00238 }
00239 s++;
00240 }
00241 return 0;
00242 }
00243
00244
00245
00246
00247
00248 int coff_ofs_to_rva(coff_section_headers *section_headers, dword ofs, RVA *rva)
00249 {
00250 COFF_SECTION_HEADER *s=section_headers->sections;
00251 for (UINT i=0; i<section_headers->section_count; i++) {
00252 if ((ofs>=s->data_offset+section_headers->hdr_ofs) &&
00253 (ofs<s->data_offset+section_headers->hdr_ofs+s->data_size)) {
00254 *rva=ofs-(s->data_offset+section_headers->hdr_ofs)+s->data_address;
00255 return 1;
00256 }
00257 s++;
00258 }
00259 return 0;
00260 }
00261
00262 int coff_ofs_to_section(coff_section_headers *section_headers, dword ofs, UINT *section)
00263 {
00264 COFF_SECTION_HEADER *s=section_headers->sections;
00265 for (UINT i=0; i<section_headers->section_count; i++) {
00266 if ((ofs>=s->data_offset+section_headers->hdr_ofs) &&
00267 (ofs<s->data_offset+section_headers->hdr_ofs+s->data_size)) {
00268 *section=i;
00269 return 1;
00270 }
00271 s++;
00272 }
00273 return 0;
00274 }
00275
00276 int coff_ofs_to_rva_and_section(coff_section_headers *section_headers, dword ofs, RVA *rva, UINT *section)
00277 {
00278 int r=coff_ofs_to_rva(section_headers, ofs, rva);
00279 if (r) {
00280 r=coff_ofs_to_section(section_headers, ofs, section);
00281 }
00282 return r;
00283 }
00284
00285 int coff_ofs_is_valid(coff_section_headers *section_headers, dword ofs)
00286 {
00287 RVA rva;
00288 return coff_ofs_to_rva(section_headers, ofs, &rva);
00289 }