Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /* Copyright (C) 1999 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1997 DJ Delorie, see COPYING.DJ for details */
  3. #include <libc/stubs.h>
  4. #include <stdlib.h>
  5. #include <sys/system.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8. #include <fcntl.h>
  9.  
  10. #define STUB_INFO_MAGIC "StubInfoMagic!!"
  11.  
  12. static _v2_prog_type type;
  13. static int type_initialized = 0;
  14.  
  15. static
  16. const _v2_prog_type *_check_v2_prog_internal (int pf);
  17.  
  18. const _v2_prog_type *_check_v2_prog(const char *program, int pf)
  19. {
  20.   const _v2_prog_type *prog_type;
  21.  
  22.   if (type_initialized && type.stubinfo)
  23.     free(type.stubinfo);
  24.   type_initialized = 1;
  25.  
  26.   memset(&type, 0, sizeof(type));
  27.  
  28.   if (program)
  29.   {
  30.     pf = open(program, O_RDONLY|O_BINARY);
  31.     if (pf < 0)
  32.       return &type;
  33.   }
  34.  
  35.   prog_type = _check_v2_prog_internal(pf);
  36.  
  37.   if (program)
  38.     close(pf);
  39.  
  40.   if (prog_type)
  41.     type.valid = 1;
  42.   return &type;
  43. }
  44.  
  45. static
  46. const _v2_prog_type *_check_v2_prog_internal (int pf)
  47. {
  48.   unsigned short header[5];
  49.   lseek(pf, 0, SEEK_SET);
  50.   if (read(pf, header, sizeof(header)) != sizeof(header))
  51.     return NULL;
  52.   if (header[0] == 0x010b || header[0] == 0x014c)
  53.   {
  54.     unsigned char firstbytes[1];
  55.     unsigned long coffhdr[40];
  56.  
  57.     /* Seems to be an unstubbed COFF.  See what the first opcode
  58.        is to determine if it's v1.x or v2 COFF (or an impostor).
  59.  
  60.        FIXME: the code here assumes that any COFF that's not a V1
  61.        can only be V2.  What about other compilers that use COFF?  */
  62.     type.object_format = _V2_OBJECT_FORMAT_COFF;
  63.     if (lseek(pf, 2, 1) < 0
  64.         || read(pf, coffhdr, sizeof(coffhdr)) != sizeof(coffhdr)
  65.         || lseek(pf, coffhdr[10 + 5], 0) < 0
  66.         || read(pf, firstbytes, 1) != 1) /* scnptr */
  67.         /* "Aha! An impostor!" (The Adventure game) */
  68.       type.object_format = _V2_OBJECT_FORMAT_UNKNOWN;
  69.     else if (firstbytes[0] != 0xa3) /* opcode of movl %eax, 0x12345678 (V1) */
  70.            type.version.v.major = 2;
  71.          else
  72.            type.version.v.major = 1;
  73.     type.exec_format = _V2_EXEC_FORMAT_COFF;
  74.   }
  75.   else if (header[0] == 0x5a4d) /* "MZ" */
  76.   {
  77.     char go32stub[9];
  78.     unsigned long coff_start = (unsigned long)header[2]*512L;
  79.     unsigned long exe_start;
  80.     type.exec_format = _V2_EXEC_FORMAT_EXE;
  81.     if (header[1])
  82.       coff_start += (long)header[1] - 512L;
  83.     exe_start = (unsigned long)header[4]*16L;
  84.     if (lseek(pf, exe_start, SEEK_SET) != exe_start)
  85.       return NULL;
  86.     if (read(pf, go32stub, 8) != 8)
  87.       return NULL;
  88.     go32stub[8] = 0;
  89.     if (strcmp(go32stub, "go32stub") == 0)
  90.     {
  91.       type.version.v.major = 2;
  92.       type.object_format = _V2_OBJECT_FORMAT_COFF;
  93.       type.exec_format = _V2_EXEC_FORMAT_STUBCOFF;
  94.     }
  95.     else
  96.     {
  97.       int stub_offset;
  98.       char magic[16];
  99.       int struct_length;
  100.       unsigned short coff_id;
  101.       type.version.v.major = 1;
  102.       if (lseek(pf, coff_start - 4, SEEK_SET) != coff_start-4)
  103.         return NULL;
  104.       if (read(pf, &stub_offset, 4) != 4)
  105.         return NULL;
  106.       if (read(pf, &coff_id, 2) != 2)
  107.         return NULL;
  108.       if (coff_id == 0x010b || coff_id == 0x014c)
  109.       {
  110.         type.object_format = _V2_OBJECT_FORMAT_COFF;
  111.         type.exec_format = _V2_EXEC_FORMAT_STUBCOFF;
  112.       }
  113.       if (lseek(pf, stub_offset, 0) != stub_offset)
  114.         return NULL;
  115.       if (read(pf, magic, 16) != 16)
  116.         return NULL;
  117.       if (memcmp(STUB_INFO_MAGIC, magic, 16) == 0)
  118.       {
  119.         if (read(pf, &struct_length, 4) != 4)
  120.           return NULL;
  121.         type.stubinfo = (_v1_stubinfo *)malloc(struct_length);
  122.         memcpy(type.stubinfo->magic, magic, 16);
  123.         type.stubinfo->struct_length = struct_length;
  124.         if (read(pf, type.stubinfo->go32, struct_length - 20)
  125.             != struct_length - 20)
  126.           return NULL;
  127.         type.has_stubinfo = 1;
  128.       }
  129.     }
  130.   }
  131.   else if (header[0] == 0x2123) /* "#!" */
  132.   {
  133.     type.exec_format = _V2_EXEC_FORMAT_UNIXSCRIPT;
  134.   }
  135.   return &type;
  136. }
  137.  
  138.