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

htle.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      htle.cc
00004  *
00005  *      Copyright (C) 1999-2002 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 "errno.h"
00022 #include <stdlib.h>
00023 
00024 #include "htendian.h"
00025 #include "htle.h"
00026 #include "htlehead.h"
00027 #include "htleimg.h"
00028 #include "htleobj.h"
00029 #include "htleent.h"
00030 #include "htlepage.h"
00031 #include "htlevxd.h"
00032 #include "htiobox.h"
00033 #include "htnewexe.h"
00034 #include "lestruct.h"
00035 #include "log.h"
00036 #include "tools.h"
00037 
00038 #define LE_SEG_ADDR(i) (LE_shared->objmap.header[(i)].page_map_index-1) *\
00039                         LE_shared->hdr.pagesize + LE_BASE_ADDR
00040 
00041 static format_viewer_if *htle_ifs[] = {
00042         &htleheader_if,
00043         &htlevxd_if,
00044         &htlepagemaps_if,
00045         &htleobjects_if,
00046         &htleentrypoints_if,
00047         &htleimage_if,
00048         0
00049 };
00050 
00051 static ht_view *htle_init(bounds *b, ht_streamfile *file, ht_format_group *format_group)
00052 {
00053         byte lemagic[2];
00054         FILEOFS h=get_newexe_header_ofs(file);
00055         file->seek(h);
00056         file->read(lemagic, 2);
00057         if ((lemagic[0]!=LE_MAGIC0) || (lemagic[1]!=LE_MAGIC1)) return 0;
00058 
00059         ht_le *g=new ht_le();
00060         g->init(b, file, htle_ifs, format_group, h);
00061         return g;
00062 }
00063 
00064 format_viewer_if htle_if = {
00065         htle_init,
00066         0
00067 };
00068 
00069 void ht_le::init(bounds *b, ht_streamfile *file, format_viewer_if **ifs, ht_format_group *format_group, FILEOFS h)
00070 {
00071         ht_format_group::init(b, VO_BROWSABLE | VO_SELECTABLE | VO_RESIZE, DESC_LE, file, false, true, 0, format_group);
00072         VIEW_DEBUG_NAME("ht_le");
00073 
00074         LOG("%s: LE: found header at %08x", file->get_filename(), h);
00075         ht_le_shared_data *le_shared = (ht_le_shared_data*)malloc(sizeof(ht_le_shared_data));
00076         shared_data = le_shared;
00077         le_shared->v_header = NULL;
00078         le_shared->v_objects = NULL;
00079         le_shared->v_pagemaps = NULL;
00080         le_shared->v_image = NULL;
00081         le_shared->v_le_vxd = NULL;
00082         le_shared->hdr_ofs = h;
00083         le_shared->linear_file = NULL;
00084         le_shared->reloc_file = NULL;
00085         le_shared->best_entrypoint = LE_ADDR_INVALID;
00086 
00087         // FIXME: byteorder handling...
00088         le_shared->byteorder = little_endian;
00089 
00090         /* read LE header */
00091         file->seek(h);
00092         file->read(&le_shared->hdr, sizeof le_shared->hdr);
00093         create_host_struct(&le_shared->hdr, LE_HEADER_struct, le_shared->byteorder);
00094 
00095         le_shared->is_vxd = (le_shared->hdr.winresoff) ||
00096                 (le_shared->hdr.winreslen) ||
00097                 (le_shared->hdr.devid) ||
00098                 (le_shared->hdr.ddkver);
00099 
00100         read_pagemap();
00101         read_objects();
00102 
00103         ht_le_page_file *lfile = new ht_le_page_file();
00104         lfile->init(file, false, &le_shared->pagemap, le_shared->pagemap.count,
00105                 le_shared->hdr.pagesize);
00106         le_shared->linear_file = lfile;
00107 
00108         do_fixups();
00109         check_vxd();
00110 
00111         ht_format_group::init_ifs(ifs);
00112 }
00113 
00114 void ht_le::done()
00115 {
00116         ht_format_group::done();
00117 
00118         ht_le_shared_data *le_shared=(ht_le_shared_data*)shared_data;
00119         
00120         if (le_shared->objmap.header) free(le_shared->objmap.header);
00121         if (le_shared->objmap.vsize) free(le_shared->objmap.vsize);
00122         if (le_shared->objmap.psize) free(le_shared->objmap.psize);
00123         
00124         if (le_shared->pagemap.offset) free(le_shared->pagemap.offset);
00125         if (le_shared->pagemap.vsize) free(le_shared->pagemap.vsize);
00126         if (le_shared->pagemap.psize) free(le_shared->pagemap.psize);
00127 
00128         if (le_shared->linear_file) {
00129                 le_shared->linear_file->done();
00130                 delete le_shared->linear_file;
00131         }
00132 
00133         if (le_shared->reloc_file) {
00134                 le_shared->reloc_file->done();
00135                 delete le_shared->reloc_file;
00136         }
00137 
00138         free(le_shared);
00139 }
00140 
00141 void ht_le::do_fixups()
00142 {
00143         ht_le_shared_data *le_shared = (ht_le_shared_data*)shared_data;
00144         FILEOFS h = le_shared->hdr_ofs;
00145 
00146         uint32 *page_fixup_ofs = (uint32*)malloc(sizeof (uint32) * (le_shared->hdr.pagecnt+1));
00147         uint32 *page_fixup_size = (uint32*)malloc(sizeof (uint32) * (le_shared->hdr.pagecnt));
00148 
00149         file->seek(h+le_shared->hdr.fpagetab);
00150         for (UINT i=0; i<le_shared->hdr.pagecnt+1; i++) {
00151                 char buf[4];
00152                 file->read(buf, 4);
00153                 uint32 ofs = create_host_int(buf, 4, little_endian);
00154                 page_fixup_ofs[i] = ofs;
00155         }
00156 
00157         for (UINT i=0; i<le_shared->hdr.pagecnt; i++) {
00158                 page_fixup_size[i] = page_fixup_ofs[i+1] - page_fixup_ofs[i];
00159         }
00160 
00161         ht_le_reloc_file *rfile = new ht_le_reloc_file();
00162         rfile->init(le_shared->linear_file, false, le_shared);
00163 
00164         le_shared->reloc_file = rfile;
00165 
00166         UINT error_count = 0;
00167 
00168         for (UINT i=0; i<le_shared->hdr.pagecnt; i++) {
00169                 // size of fixup record table for segment
00170                 uint32 size = page_fixup_size[i];
00171                 UINT obj_ofs = i * le_shared->hdr.pagesize;
00172 
00173                 file->seek(h+le_shared->hdr.frectab+page_fixup_ofs[i]);
00174                 bool error = false;
00175                 while (size>0 && !error) {
00176                         // addr_type + reloc_type
00177                         LE_FIXUP f;
00178                         if (sizeof f > size) { error = true; break; }
00179                         size -= sizeof f;
00180                         file->read(&f, sizeof f);
00181                         create_host_struct(&f, LE_FIXUP_struct, le_shared->byteorder);
00182                         /* only internal references (16/32) supported for now... */
00183                         if ((f.reloc_type != 0) && (f.reloc_type != 16)) {
00184                                 error = true;
00185                                 break;
00186                         }
00187 
00188                         // is address_type supported ?
00189                         switch (f.address_type & LE_FIXUP_ADDR_TYPE_MASK) {
00190                                 case LE_FIXUP_ADDR_TYPE_0_8:
00191                                 case LE_FIXUP_ADDR_TYPE_16_0:
00192                                 case LE_FIXUP_ADDR_TYPE_16_16:
00193                                 case LE_FIXUP_ADDR_TYPE_0_16:
00194                                 case LE_FIXUP_ADDR_TYPE_16_32:
00195                                 case LE_FIXUP_ADDR_TYPE_0_32:
00196                                 case LE_FIXUP_ADDR_TYPE_REL32:
00197                                         break;
00198                                 default:
00199                                         error = true;
00200                                         break;
00201                         }
00202                         if (error) break;
00203 
00204                         UINT multi_count = 0;
00205                         uint16 src_ofs;
00206                         bool multi_ofs = (f.address_type & LE_FIXUP_ADDR_MULTIPLE);
00207                         if (multi_ofs) {
00208                                 // number of entries in offset table
00209                                 char buf[1];
00210                                 if (sizeof buf > size) { error = true; break; }
00211                                 size -= sizeof buf;
00212                                 file->read(buf, sizeof buf);
00213                                 multi_count = create_host_int(buf, 1, little_endian);
00214                         } else {
00215                                 // single source offset
00216                                 char buf[2];
00217                                 if (sizeof buf > size) { error = true; break; }
00218                                 size -= sizeof buf;
00219                                 file->read(buf, sizeof buf);
00220                                 src_ofs = create_host_int(buf, 2, little_endian);
00221                         }
00222 
00223                         switch (f.reloc_type & LE_FIXUP_RELOC_TYPE_MASK) {
00224                                 case LE_FIXUP_RELOC_TYPE_INTERNAL:
00225                                         uint16 target_seg;
00226                                         uint32 target_ofs;
00227                                         if (f.reloc_type & LE_FIXUP_RELOC_TARGET32) {
00228                                                 LE_FIXUP_INTERNAL32 x;
00229                                                 if (sizeof x > size) { error = true; break; }
00230                                                 size -= sizeof x;
00231                                                 file->read(&x, sizeof x);
00232                                                 create_host_struct(&x, LE_FIXUP_INTERNAL32_struct, le_shared->byteorder);
00233                                                 target_seg = x.seg-1;
00234                                                 target_ofs = x.ofs;
00235                                         } else {
00236                                                 LE_FIXUP_INTERNAL16 x;
00237                                                 if (sizeof x > size) { error = true; break; }
00238                                                 size -= sizeof x;
00239                                                 file->read(&x, sizeof x);
00240                                                 create_host_struct(&x, LE_FIXUP_INTERNAL16_struct, le_shared->byteorder);
00241                                                 target_seg = x.seg-1;
00242                                                 target_ofs = x.ofs;
00243                                         }
00244 
00245                                         if (multi_ofs) {
00246                                                 for (UINT j=0; j<multi_count; j++) {
00247                                                         char buf[2];
00248                                                         if (sizeof buf > size) { error = true; break; }
00249                                                         size -= sizeof buf;
00250                                                         file->read(buf, sizeof buf);
00251                                                         src_ofs = create_host_int(buf, sizeof buf, little_endian);
00252                                                         rfile->insert_reloc(obj_ofs + src_ofs, new ht_le_reloc_entry(obj_ofs + src_ofs, target_seg, LE_MAKE_ADDR(le_shared, target_seg, target_ofs), f.address_type, f.reloc_type));
00253                                                 }
00254                                         } else {
00255                                                 rfile->insert_reloc(obj_ofs + src_ofs, new ht_le_reloc_entry(obj_ofs + src_ofs, target_seg, LE_MAKE_ADDR(le_shared, target_seg, target_ofs), f.address_type, f.reloc_type));
00256                                         }
00257                                         break;
00258                                 case LE_FIXUP_RELOC_TYPE_IMPORT_ORD:
00259                                         error = true;
00260                                         break;
00261                                 case LE_FIXUP_RELOC_TYPE_IMPORT_NAME:
00262                                         error = true;
00263                                         break;
00264                                 case LE_FIXUP_RELOC_TYPE_OSFIXUP:
00265                                         error = true;
00266                                         break;
00267                         }
00268                 }
00269                 if (error) error_count++;
00270         }
00271 
00272         free(page_fixup_ofs);
00273         free(page_fixup_size);
00274 
00275         if (error_count) {
00276                 // FIXME: once complete:
00277                 // "%s: NE relocations seem to be corrupted.", file->get_filename());
00278                 LOG_EX(LOG_WARN, "%s: LE: invalid and/or unsupported relocations found.", file->get_filename());
00279                 errorbox("%s: LE: invalid and/or unsupported relocations found.", file->get_filename());
00280         } else {
00281                 LOG("%s: LE: relocations present, relocation simulation layer enabled", file->get_filename());
00282         }
00283         rfile->finalize();
00284 }
00285 
00286 void ht_le::check_vxd()
00287 {
00288         ht_le_shared_data *le_shared = (ht_le_shared_data*)shared_data;
00289         FILEOFS h = le_shared->hdr_ofs;
00290 
00291         /* VxD */
00292         if (le_shared->is_vxd) {
00293                 /* test if really VxD and find VxD descriptor */
00294                 LE_ENTRYPOINT_BUNDLE b;
00295                 file->seek(h+le_shared->hdr.enttab);
00296                 file->read(&b, sizeof b);
00297                 le_shared->is_vxd = false;
00298                 if ((b.entry_count == 1) && (b.flags & LE_ENTRYPOINT_BUNDLE_VALID) &&
00299                 (b.flags & LE_ENTRYPOINT_BUNDLE_32BIT) && (b.obj_index == 1)) {
00300                         LE_ENTRYPOINT32 e;
00301                         file->read(&e, sizeof e);
00302                         create_host_struct(&e, LE_ENTRYPOINT32_struct, le_shared->byteorder);
00303                         if (e.flags & LE_ENTRYPOINT_EXPORTED) {
00304                                 /* linearized address for ht_le_page_file */
00305                                 uint32 vxd_desc_ofs = (le_shared->objmap.header[0].
00306                                         page_map_index-1)*le_shared->hdr.pagesize + e.offset;
00307 
00308                                 le_shared->reloc_file->seek(vxd_desc_ofs);
00309                                 le_shared->reloc_file->read(&le_shared->vxd_desc, sizeof le_shared->vxd_desc);
00310                                 create_host_struct(&le_shared->vxd_desc, LE_VXD_DESCRIPTOR_struct, le_shared->byteorder);
00311 
00312                                 le_shared->vxd_desc_linear_ofs = vxd_desc_ofs;
00313                                 le_shared->is_vxd = true;
00314                         }
00315                 }
00316         }
00317 }
00318 
00319 void ht_le::read_pagemap()
00320 {
00321         ht_le_shared_data *le_shared = (ht_le_shared_data*)shared_data;
00322         FILEOFS h = le_shared->hdr_ofs;
00323 
00324         le_shared->pagemap.count=le_shared->hdr.pagecnt;
00325         le_shared->pagemap.offset=(dword*)malloc(le_shared->pagemap.count*sizeof *le_shared->pagemap.offset);
00326         le_shared->pagemap.psize=(dword*)malloc(le_shared->pagemap.count*sizeof *le_shared->pagemap.psize);
00327         le_shared->pagemap.vsize=(dword*)malloc(le_shared->pagemap.count*sizeof *le_shared->pagemap.vsize);
00328 
00329         dword last_page_offset=0, last_page=0;
00330         for (dword i=0; i<le_shared->hdr.pagecnt; i++) {
00331                 LE_PAGE_MAP_ENTRY e;
00332                 file->seek(h+le_shared->hdr.pagemap+i*4);
00333                 file->read(&e, sizeof e);
00334                 create_host_struct(&e, LE_PAGE_MAP_ENTRY_struct, le_shared->byteorder);
00335                 
00336                 /* FIXME: is this formula correct ? it comes straight from my docs... */
00337                 dword eofs=(e.high+e.low-1)*le_shared->hdr.pagesize+le_shared->hdr.datapage;
00338                 le_shared->pagemap.offset[i] = eofs;
00339 
00340                 if (le_shared->pagemap.offset[i]>last_page_offset) {
00341                         last_page_offset = le_shared->pagemap.offset[i];
00342                         last_page = i;
00343                 }
00344         }
00345 
00346         for (dword i=0; i<le_shared->hdr.pagecnt; i++) {
00347                 le_shared->pagemap.vsize[i]=0;  /* filled by read_objects() */
00348                 if (i==last_page)
00349                         le_shared->pagemap.psize[i]=le_shared->hdr.lastpagesize;
00350                 else
00351                         le_shared->pagemap.psize[i]=le_shared->hdr.pagesize;
00352         }
00353 }
00354 
00355 void ht_le::read_objects()
00356 {
00357         ht_le_shared_data *le_shared = (ht_le_shared_data*)shared_data;
00358         FILEOFS h = le_shared->hdr_ofs;
00359 
00360         le_shared->objmap.count = le_shared->hdr.objcnt;
00361         le_shared->objmap.header = (LE_OBJECT*)malloc(le_shared->objmap.count*sizeof *le_shared->objmap.header);
00362         le_shared->objmap.vsize = (UINT*)malloc(le_shared->objmap.count * sizeof *le_shared->objmap.vsize);
00363         le_shared->objmap.psize = (UINT*)malloc(le_shared->objmap.count * sizeof *le_shared->objmap.psize);
00364 
00365         for (UINT i=0; i<le_shared->hdr.objcnt; i++) {
00366                 file->seek(h+le_shared->hdr.objtab+i*24);
00367                 file->read(&le_shared->objmap.header[i], sizeof *le_shared->objmap.header);
00368                 create_host_struct(&le_shared->objmap.header[i], LE_OBJECT_HEADER_struct, le_shared->byteorder);
00369 
00370                 /* sum up page sizes to find object's physical size */
00371                 UINT psize = 0;
00372                 for (UINT j=0; j<le_shared->objmap.header[i].page_map_count; j++) {
00373                         psize += le_shared->pagemap.psize[j+le_shared->objmap.header[i].page_map_index-1];
00374                         /* FIXME: security hole: array-index uncontrolled */
00375                         if (j == le_shared->objmap.header[i].page_map_count-1)
00376                                 le_shared->pagemap.vsize[j+le_shared->objmap.header[i].page_map_index-1]=le_shared->objmap.header[i].vsize % le_shared->hdr.pagesize;
00377                         else
00378                                 le_shared->pagemap.vsize[j+le_shared->objmap.header[i].page_map_index-1]=le_shared->hdr.pagesize;
00379                 }
00380 // FIXME: alternative which one is right ???
00381 #if 1
00382                 le_shared->objmap.psize[i] = MIN(psize, le_shared->objmap.header[i].vsize);
00383                 le_shared->objmap.vsize[i] = MIN(psize, le_shared->objmap.header[i].vsize);
00384 #else
00385                 le_shared->objmap.psize[i] = le_shared->objmap.header[i].vsize;
00386                 le_shared->objmap.vsize[i] = le_shared->objmap.header[i].vsize;
00387 #endif
00388         }
00389 
00390 /* create temporary address space for LEAddress's */
00391 /*      le_shared->le_addr = (LEAddress*)malloc(sizeof *le_shared->le_addr * le_shared->objmap.count);
00392         UINT a = 0;
00393         for (UINT i = 0; i<le_shared->objmap.count; i++) {
00394                 le_shared->le_addr[i] = a;
00395                 a += le_shared->objmap.header[i].page_map_count * le_shared->hdr.pagesize;
00396         }*/
00397 }
00398 
00399 void ht_le::loc_enum_start()
00400 {
00401 //      loc_enum=true;
00402 }
00403 
00404 bool ht_le::loc_enum_next(ht_format_loc *loc)
00405 {
00406 #if 0
00407         ht_le_shared_data *sh=(ht_le_shared_data*)shared_data;
00408         if (loc_enum) {
00409                 loc->name="le";
00410                 loc->start=sh->hdr_ofs;
00411                 loc->length=file->get_size()-loc->start;        /* FIXME: ENOTOK */
00412                 
00413                 loc_enum=false;
00414                 return true;
00415         }
00416 #endif  
00417         return false;
00418 }
00419 
00420 /*
00421  *      CLASS ht_le_page_file
00422  */
00423 
00424 void ht_le_page_file::init(ht_streamfile *file, bool own_file, ht_le_pagemap *pm, dword pms, dword ps)
00425 {
00426         ht_layer_streamfile::init(file, own_file);
00427         pagemap = pm;
00428         pagemapsize = pms;
00429         page_size = ps;
00430         ofs = 0;
00431 }
00432 
00433 bool ht_le_page_file::isdirty(FILEOFS offset, UINT range)
00434 {
00435         FILEOFS mofs;
00436         UINT msize;
00437         while (range) {
00438                 dword s=range;
00439                 if (!map_ofs(offset, &mofs, &msize)) break;
00440                 if (s>msize) s=msize;
00441                 bool isdirty;
00442                 streamfile->cntl(FCNTL_MODS_IS_DIRTY, mofs, s, &isdirty);
00443                 if (isdirty) return 1;
00444                 range-=s;
00445                 ofs+=s;
00446         }
00447         return 0;
00448 }
00449 
00454 bool ht_le_page_file::map_ofs(UINT lofs, FILEOFS *pofs, UINT *maxsize)
00455 {
00456         UINT i = lofs/page_size, j = lofs % page_size;
00457         if (i < pagemapsize) {
00458                 if (j < pagemap->vsize[i]) {
00459                         *pofs = pagemap->offset[i]+j;
00460                         *maxsize = pagemap->vsize[i]-j;
00461                         return true;
00462                 }
00463         }
00464         return false;
00465 }
00466 
00467 bool ht_le_page_file::unmap_ofs(FILEOFS pofs, UINT *lofs)
00468 {
00469         for (UINT i=0; i<pagemapsize; i++) {
00470                 if ((pofs >= pagemap->offset[i]) && (pofs < pagemap->offset[i]+pagemap->vsize[i])) {
00471                         *lofs = pofs - pagemap->offset[i] + i*page_size;
00472                         return true;
00473                 }
00474         }
00475         return false;
00476 }
00477 
00478 UINT ht_le_page_file::read(void *aBuf, UINT size)
00479 {
00480         FILEOFS mofs;
00481         UINT msize;
00482         int c = 0;
00483         byte *buf = (byte *)aBuf;
00484         while (size) {
00485                 UINT s = size;
00486                 if (!map_ofs(ofs, &mofs, &msize)) break;
00487                 if (s>msize) s = msize;
00488                 streamfile->seek(mofs);
00489                 s = streamfile->read(buf, s);
00490                 if (!s) break;
00491                 buf += s;
00492                 size -= s;
00493                 c += s;
00494                 ofs += s;
00495         }
00496         return c;
00497 }
00498 
00499 int ht_le_page_file::seek(FILEOFS offset)
00500 {
00501         ofs = offset;
00502         return 0;
00503 }
00504 
00505 FILEOFS ht_le_page_file::tell()
00506 {
00507         return ofs;
00508 }
00509 
00510 int ht_le_page_file::vcntl(UINT cmd, va_list vargs)
00511 {
00512         switch (cmd) {
00513                 case FCNTL_MODS_CLEAR_DIRTY_RANGE: {
00514                         FILEOFS o = va_arg(vargs, FILEOFS);
00515                         UINT s = va_arg(vargs, UINT);
00516                         UINT ts, ms;
00517                         int e;
00518 
00519                         do {
00520                                 if (!map_ofs(o, &o, &ms)) return EINVAL;
00521                                 ts = (s < ms) ? s : ms;
00522                                 e = streamfile->cntl(cmd, o, ts);
00523                                 if (e) return e;
00524                                 s -= ts;
00525                         } while (s);
00526                         return 0;
00527                 }
00528                 case FCNTL_MODS_IS_DIRTY: {
00529                         FILEOFS o = va_arg(vargs, FILEOFS);
00530                         UINT s = va_arg(vargs, UINT);
00531                         bool *b = va_arg(vargs, bool*);
00532                         UINT ts, ms;
00533                         int e;
00534 
00535                         *b = false;
00536                         do {
00537                                 if (!map_ofs(o, &o, &ms)) return EINVAL;
00538                                 ts = (s < ms) ? s : ms;
00539                                 e = streamfile->cntl(cmd, o, ts, b);
00540                                 if (e) return e;
00541                                 if (*b) break;
00542                                 s -= ts;
00543                         } while (s);
00544                         return 0;
00545                 }
00546         }
00547         return ht_layer_streamfile::vcntl(cmd, vargs);
00548 }
00549 
00550 UINT ht_le_page_file::write(const void *aBuf, UINT size)
00551 {
00552         FILEOFS mofs;
00553         UINT msize;
00554         int c = 0;
00555         const byte *buf = (const byte *)aBuf;
00556         while (size) {
00557                 UINT s = size;
00558                 if (!map_ofs(ofs, &mofs, &msize)) break;
00559                 if (s>msize) s = msize;
00560                 streamfile->seek(mofs);
00561                 buf += streamfile->write(buf, s);
00562                 size -= s;
00563                 c += s;
00564                 ofs += s;
00565         }
00566         return c;
00567 }
00568 
00569 /*
00570  *      CLASS ht_le_reloc_entry
00571  */
00572 
00573 ht_le_reloc_entry::ht_le_reloc_entry(UINT o, UINT s, LEAddress a, uint8 at, uint8 rt)
00574 {
00575         ofs = o;
00576         seg = s;
00577         addr = a;
00578         address_type = at;
00579         reloc_type = rt;
00580 }
00581 
00582 /*
00583  *      CLASS ht_le_reloc_file
00584  */
00585 
00586 void ht_le_reloc_file::init(ht_streamfile *s, bool os, ht_le_shared_data *d)
00587 {
00588         ht_reloc_file::init(s, os);
00589         data = d;
00590 }
00591 
00592 void ht_le_reloc_file::reloc_apply(Object *reloc, byte *data)
00593 {
00594         ht_le_reloc_entry *e = (ht_le_reloc_entry*)reloc;
00595 
00596         switch (e->address_type & LE_FIXUP_ADDR_TYPE_MASK) {
00597                 case LE_FIXUP_ADDR_TYPE_0_8:
00598                         create_foreign_int(data, e->addr, 1, little_endian);
00599                         break;
00600                 case LE_FIXUP_ADDR_TYPE_16_0:
00601                         create_foreign_int(data, e->seg, 2, little_endian);
00602                         break;
00603                 case LE_FIXUP_ADDR_TYPE_16_16:
00604                         create_foreign_int(data, e->addr, 2, little_endian);
00605                         create_foreign_int(data, e->seg, 2, little_endian);
00606                         break;
00607                 case LE_FIXUP_ADDR_TYPE_0_16:
00608                         create_foreign_int(data, e->addr, 2, little_endian);
00609                         break;
00610                 case LE_FIXUP_ADDR_TYPE_16_32:
00611                         create_foreign_int(data, e->addr, 4, little_endian);
00612                         create_foreign_int(data, e->seg, 2, little_endian);
00613                         break;
00614                 case LE_FIXUP_ADDR_TYPE_0_32:
00615                         create_foreign_int(data, e->addr, 4, little_endian);
00616                         break;
00617                 case LE_FIXUP_ADDR_TYPE_REL32:
00618                         create_foreign_int(data, e->addr - LE_BASE_ADDR - e->ofs - 4, 4, little_endian);
00619                         break;
00620         }
00621 }
00622 
00623 bool ht_le_reloc_file::reloc_unapply(Object *reloc, byte *data)
00624 {
00625         return false;
00626 }
00627 
00628 /*
00629  *
00630  */
00631 
00632 FILEOFS LE_get_seg_ofs(ht_le_shared_data *LE_shared, UINT i)
00633 {
00634         assert(i<LE_shared->objmap.count);
00635         return LE_SEG_ADDR(i) - LE_BASE_ADDR;
00636 }
00637 
00638 LEAddress LE_get_seg_addr(ht_le_shared_data *LE_shared, UINT i)
00639 {
00640         assert(i<LE_shared->objmap.count);
00641         return LE_SEG_ADDR(i);
00642 }
00643 
00644 UINT LE_get_seg_psize(ht_le_shared_data *LE_shared, UINT i)
00645 {
00646         assert(i<LE_shared->objmap.count);
00647         return LE_shared->objmap.psize[i];
00648 }
00649 
00650 UINT LE_get_seg_vsize(ht_le_shared_data *LE_shared, UINT i)
00651 {
00652         assert(i<LE_shared->objmap.count);
00653         return LE_shared->objmap.vsize[i];
00654 }
00655 
00656 bool LE_addr_to_segment(ht_le_shared_data *LE_shared, LEAddress Addr, int *segment)
00657 {
00658         for (UINT i = 0; i < LE_shared->objmap.count; i++) {
00659                 LEAddress base = LE_get_seg_addr(LE_shared, i);
00660                 UINT evsize = MAX(LE_get_seg_vsize(LE_shared, i), LE_get_seg_psize(LE_shared, i));
00661                 if ((Addr >= base) && (Addr < base + evsize)) {
00662                         *segment = i;
00663                         return true;
00664                 }
00665         }
00666         return false;
00667 }
00668 
00669 bool LE_addr_is_physical(ht_le_shared_data *LE_shared, LEAddress Addr)
00670 {
00671         for (UINT i = 0; i < LE_shared->objmap.count; i++) {
00672                 LEAddress base = LE_get_seg_addr(LE_shared, i);
00673                 UINT psize = LE_get_seg_psize(LE_shared, i);
00674                 if ((Addr >= base) && (Addr < base + psize)) return true;
00675         }
00676         return false;
00677 }
00678 
00679 bool LE_addr_to_ofs(ht_le_shared_data *LE_shared, LEAddress Addr, FILEOFS *ofs)
00680 {
00681         for (UINT i = 0; i < LE_shared->objmap.count; i++) {
00682                 LEAddress base = LE_get_seg_addr(LE_shared, i);
00683                 UINT psize = LE_get_seg_psize(LE_shared, i);
00684                 if ((Addr >= base) && (Addr < base + psize)) {
00685                         *ofs = Addr - LE_BASE_ADDR;
00686                         return true;
00687                 }
00688         }
00689         return false;
00690 }
00691 
00692 bool LE_ofs_to_addr(ht_le_shared_data *LE_shared, FILEOFS ofs, LEAddress *Addr)
00693 {
00694         for (UINT i = 0; i < LE_shared->objmap.count; i++) {
00695                 FILEOFS sofs = LE_get_seg_ofs(LE_shared, i);
00696                 if ((ofs >= sofs) && (ofs < sofs + LE_get_seg_psize(LE_shared, i))) {
00697                         *Addr = LE_BASE_ADDR + ofs;
00698                         return true;
00699                 }
00700         }
00701         return false;
00702 }
00703 
00704 LEAddress LE_MAKE_ADDR(ht_le_shared_data *LE_shared, uint16 seg, uint32 ofs)
00705 {
00706         return LE_SEG_ADDR(seg) + ofs;
00707 }
00708 
00709 uint16 LE_ADDR_SEG(ht_le_shared_data *LE_shared, LEAddress a)
00710 {
00711         for (UINT i = 0; i<LE_shared->objmap.count; i++) {
00712                 LEAddress addr = LE_SEG_ADDR(i);
00713                 if ((a >= addr) && (a < addr + LE_shared->objmap.vsize[i])) {
00714                         return i;
00715                 }
00716         }
00717         return 0xffff;
00718 }
00719 
00720 uint32 LE_ADDR_OFS(ht_le_shared_data *LE_shared, LEAddress a)
00721 {
00722         for (UINT i = 0; i<LE_shared->objmap.count; i++) {
00723                 LEAddress addr = LE_SEG_ADDR(i);
00724                 if ((a >= addr) && (a < addr + LE_shared->objmap.vsize[i])) {
00725                         return a-addr;
00726                 }
00727         }
00728         return 0;
00729 }
00730 

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