Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

htcoff.cc

Go to the documentation of this file.
00001 /*
00002  *      HT Editor
00003  *      htcoff.cc
00004  *
00005  *      Copyright (C) 1999-2003 Stefan Weyergraf (stefan@weyergraf.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
00010  *
00011  *      This program is distributed in the hope that it will be useful,
00012  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *      GNU General Public License for more details.
00015  *
00016  *      You should have received a copy of the GNU General Public License
00017  *      along with this program; if not, write to the Free Software
00018  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
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         // unfortunately COFF has no magic (urgs). so we have to guess
00042         // a little bit.
00043         COFF_HEADER h;
00044         bool machine_found = false;
00045         endianess end;
00046 
00047         // FIXME: I'm not sure little/big-endian assignment for CPUs is incorrect...
00048 
00049         // LITTLE-ENDIAN machines
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 //              case COFF_MACHINE_IA64:         // COFF64 not supported
00066                 case COFF_MACHINE_MIPS16:
00067                 case COFF_MACHINE_68k:
00068 //              case COFF_MACHINE_ALPHA_AXP_64: // COFF64 not supported
00069                 case COFF_MACHINE_MIPSf:
00070                 case COFF_MACHINE_MIPS16f:
00071                         end = little_endian;
00072                         machine_found = true;
00073         }
00074 
00075         // BIG-ENDIAN machines
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         /* test symbol_table_offset */
00089 //      if ((h.symbol_table_offset>=size) || (h.symbol_table_offset<ofs+sizeof h)) return 0;
00090 
00091         /* test size of optional header */
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         /* all tests have completed successfully -> it's a COFF (probably) */
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         /* look for pure coff */
00111         if (!is_coff(file, end, h = 0)) {
00112                 /* look for dj-coff */
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  *      CLASS ht_coff
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         /* headers */
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         /* read section headers */
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  *      rva conversion routines
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  *      ofs conversion routines
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 }

Generated on Fri May 7 21:15:31 2004 by doxygen 1.3.5