home *** CD-ROM | disk | FTP | other *** search
/ PC Extra Super CD 1998 January / PCPLUS131.iso / DJGPP / V2 / DJLSR201.ZIP / src / debug / common / v2load.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-07-23  |  9.6 KB  |  305 lines

  1. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
  2. /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
  3. /* Routine to load V2.0 format image.  Control is returned to the caller so
  4.    additional setup can be done before execution.
  5.    C. Sandmann Jan-94
  6.  */
  7. #include <libc/stubs.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <fcntl.h>
  13. #include <dpmi.h>
  14. #include <go32.h>
  15. #include <signal.h>
  16. #include <setjmp.h>
  17. #include <stubinfo.h>
  18. #include <debug/v2load.h>
  19. #include <libc/farptrgs.h>
  20. #include <sys/stat.h>
  21. #define SIMAGIC "go32stub"
  22.  
  23. AREAS areas[MAX_AREA];
  24.  
  25. extern char **environ;
  26.  
  27. static int read_section(int pf, unsigned ds, unsigned foffset, unsigned soffset, unsigned size)
  28. {
  29.   char buffer[32768];
  30.   int read_size;
  31.   int nr;
  32.   unsigned my_ss;
  33.  
  34.   size += (foffset & 0x1ff);    /* sector alignment */
  35.   foffset &= 0xfffffe00U;
  36.   soffset &= 0xfffffe00U;
  37.   lseek(pf, foffset, 0);
  38.   asm("mov %%ss,%w0" : "=g" (my_ss) );
  39.   while(size) {
  40.     read_size = (size > sizeof(buffer)) ? sizeof(buffer) : size;
  41.     nr = read(pf, buffer, read_size);
  42.     if(nr != read_size)
  43.       return -1;
  44.     movedata(my_ss, (unsigned)&buffer, ds, soffset, read_size);
  45.     size -= read_size;
  46.     soffset += read_size;
  47.   }
  48.   return 0;
  49. }
  50.  
  51. int v2loadimage(const char *program, const char *cmdline, jmp_buf load_state)
  52. {
  53.   unsigned short header[3];
  54.   int pf,i, envp;
  55.   unsigned coff_offset;
  56.   _GO32_StubInfo si;
  57.   unsigned long coffhdr[42];
  58.   unsigned start_eip, text_foffset, text_soffset, text_size, data_foffset;
  59.   unsigned data_soffset, data_size, bss_soffset, bss_size;
  60.   unsigned client_cs, client_ds, my_ds;
  61.   __dpmi_meminfo memblock;
  62.   unsigned new_env_selector;
  63.   char true_name[FILENAME_MAX];
  64.  
  65.   _truename(program, true_name);
  66.  
  67.   pf = open(program, O_RDONLY|O_BINARY);
  68.   if(pf < 0)
  69.     return -1;
  70.  
  71.   read(pf, header, sizeof(header));
  72.   if (header[0] == 0x5a4d) {        /* MZ exe signature, stubbed? */
  73.     coff_offset = (long)header[2]*512L;
  74.     if (header[1])
  75.       coff_offset += (long)header[1] - 512L;
  76.     lseek(pf, 512, 0);            /* Position of V2 stubinfo */
  77.     read(pf, si.magic, 8);
  78.     if (memcmp(SIMAGIC, si.magic, 8) != 0) {
  79.       close(pf);
  80.       return -1;                /* Not V2 image, show failure */
  81.     }
  82.     read(pf, &si.magic[8], sizeof(si)-8);    /* Rest of stubinfo */
  83.     /* Check for real image, (for now assume imbedded) */
  84.     lseek(pf, coff_offset, 0);
  85.     read(pf, header, sizeof(header));
  86.   } else {
  87.     coff_offset = 0;
  88.     strcpy(si.magic, "go32stub, V 2.00");
  89.     si.size = 0x44;
  90.     si.minstack = 0x40000;
  91.     si.minkeep = 16384;            /* transfer buffer size */
  92.     memset(&si.basename, 0, 24);    /* Asciiz strings */
  93.   }
  94.   if (header[0] != 0x014c) {        /* COFF? */
  95.     close(pf);
  96.     return -1;                /* Not V2 image, show failure */
  97.   }
  98.   lseek(pf, coff_offset, 0);
  99.   i = read(pf, coffhdr, 0x0a8);    
  100.   if (i != 0x0a8) {
  101.     close(pf);
  102.     return -1;                /* Not V2 image, show failure */
  103.   }
  104.  
  105.   start_eip = coffhdr[5 + 4];
  106.   text_foffset = coff_offset + coffhdr[12 + 5];    /* scnptr */
  107.   text_soffset = coffhdr[12 + 3];        /* vaddr */
  108.   text_size = coffhdr[12 + 4];            /* size */
  109.   areas[A_text].first_addr = text_soffset;
  110.   areas[A_text].last_addr = text_soffset + text_size - 1;
  111.   data_foffset = coff_offset + coffhdr[22 + 5];
  112.   data_soffset = coffhdr[22 + 3];
  113.   data_size = coffhdr[22 + 4];
  114.   areas[A_data].first_addr = data_soffset;
  115.   areas[A_data].last_addr = data_soffset + data_size - 1;
  116.   bss_soffset = coffhdr[32 + 3];
  117.   bss_size = coffhdr[32 + 4];
  118.   areas[A_bss].first_addr = bss_soffset;
  119.   areas[A_bss].last_addr = bss_soffset + bss_size - 1;
  120.   areas[A_stack].first_addr = bss_soffset + bss_size;
  121.   areas[A_stack].last_addr = areas[A_stack].first_addr + si.minstack - 1;
  122.   areas[A_arena].first_addr = areas[A_stack].last_addr + 1;
  123.   areas[A_arena].last_addr = (areas[A_arena].first_addr & ~0xffff) + 0xffff;
  124.  
  125.   si.initial_size = bss_soffset + bss_size;
  126.   if (si.initial_size <= 0x10001)
  127.     si.initial_size = 0x10001;
  128.   si.initial_size += 0xffff;
  129.   si.initial_size &= 0xffff0000U;
  130.  
  131.   si.env_size = 0;
  132.   for (i=0; environ[i]; i++)
  133.     si.env_size += strlen(environ[i])+1;
  134.   si.env_size += 4 + strlen(true_name);
  135.  
  136.   /* Allocate the dos memory for the environment and command line. */
  137.   i = __dpmi_allocate_dos_memory((si.env_size + 256) / 16, (int *)&new_env_selector);
  138.   if(i == -1)
  139.     return -1;
  140.  
  141.   envp = 0;
  142.   for (i=0; environ[i]; i++)
  143.   {
  144.     int len = strlen(environ[i])+1;
  145.     movedata(_my_ds(), (unsigned)environ[i], new_env_selector, envp, len);
  146.     envp += len;
  147.   }
  148.   _farpokeb(new_env_selector, envp++, 0);
  149.   _farpokeb(new_env_selector, envp++, 1);
  150.   _farpokeb(new_env_selector, envp++, 0);
  151.   movedata(_my_ds(), (unsigned)true_name, new_env_selector, envp, strlen(true_name)+1);
  152.  
  153.   /* Allocate the dos memory for the transfer buffer.  This nukes si.cs_selector,
  154.    but that's OK since we set it next. */
  155.   i = __dpmi_allocate_dos_memory((si.minkeep + 256) / 16, (int *)&si.psp_selector);
  156.   if(i == -1)
  157.     return -1;
  158.   si.ds_segment = i + (256/16);
  159.  
  160.   if((si.cs_selector = __dpmi_allocate_ldt_descriptors(1)) == 0xffff)
  161.     return -1;
  162.  
  163.   if(__dpmi_set_segment_base_address(si.cs_selector, si.ds_segment * 16) == -1)
  164.     return -1;
  165.  
  166.   /* Set the type as 16 bit, small */
  167.   if(__dpmi_set_descriptor_access_rights(si.cs_selector, ((si.cs_selector & 3) << 5) | 0x009b) == -1)
  168.     return -1;
  169.  
  170.   if(__dpmi_set_segment_limit(si.cs_selector, si.minkeep-1) == -1)
  171.     return -1;
  172.  
  173.   if((si.ds_selector = __dpmi_create_alias_descriptor(si.cs_selector)) == 0xffff)
  174.     return -1;
  175.  
  176.   if(__dpmi_set_descriptor_access_rights(si.ds_selector, ((si.cs_selector & 3) << 5) | 0x4093) == -1)
  177.     return -1;
  178.  
  179. #ifdef DEBUG
  180.   show_selector("ds16", si.ds_selector);
  181.   show_selector("cs16", si.cs_selector);
  182.   show_selector("psp16", si.psp_selector);
  183.   printf("mine:\n");
  184.   show_selector("ds16", _stubinfo->ds_selector);
  185.   show_selector("cs16", _stubinfo->cs_selector);
  186.   show_selector("psp16", _stubinfo->psp_selector);
  187.   printf("Initial size: 0x%lx\n",si.initial_size);
  188. #endif
  189.  
  190. /* Finished with 16 bit config, now for 32 bit setup */
  191.  
  192.   if((client_cs = __dpmi_allocate_ldt_descriptors(1)) == 0xffff)
  193.     return -1;
  194.  
  195.   memblock.size = si.initial_size;
  196.   if(__dpmi_allocate_memory(&memblock) == -1)
  197.     return -1;
  198.   si.memory_handle = memblock.handle;
  199.   
  200.   if(__dpmi_set_segment_base_address(client_cs, memblock.address) == -1)
  201.     return -1;
  202.  
  203.   /* Set the type as 32 bit, big */
  204.   if(__dpmi_set_descriptor_access_rights(client_cs, ((client_cs & 3) << 5) | 0xc09b) == -1)
  205.     return -1;
  206.  
  207.   if(__dpmi_set_segment_limit(client_cs, si.initial_size-1) == -1)
  208.     return -1;
  209.  
  210.   if((client_ds = __dpmi_create_alias_descriptor(client_cs)) == 0xffff)
  211.     return -1;
  212.  
  213. /* This shouldn't be necessary, but QDPMI does not clone the 32 bit properly
  214.    so we have to reset this stuff or it doesn't work when it is used as the
  215.    client's SS  :-( */
  216.   if(__dpmi_set_descriptor_access_rights(client_ds, ((client_cs & 3) << 5) | 0xc093) == -1)
  217.     return -1;
  218.  
  219.   if(__dpmi_set_segment_limit(client_ds, si.initial_size-1) == -1)
  220.     return -1;
  221. /* End should be unnecessary code */
  222.  
  223. /* Load image */
  224.   my_ds = 0;
  225.   asm("mov %%ds,%w0" : "=g" (my_ds) );
  226. #ifdef DEBUG
  227.   show_selector("my_ds", my_ds);
  228.   show_selector("client_ds",client_ds);
  229.   asm("mov %%cs,%w0" : "=g" (i) );
  230.   show_selector("my_cs",i);
  231.   show_selector("client_cs",client_cs);
  232.   printf("Load image...\n");
  233. #endif
  234.  
  235.   if(read_section(pf, client_ds, text_foffset, text_soffset, text_size) )
  236.     return -1;
  237.   if(read_section(pf, client_ds, data_foffset, data_soffset, data_size) )
  238.     return -1;
  239.   for (i=0; i+3<bss_size; i+= 4)
  240.     _farpokel(client_ds, bss_soffset+i, 0);
  241.   for (; i<bss_size; i++)
  242.     _farpokeb(client_ds, bss_soffset+i, 0);
  243.  
  244.   close(pf);
  245.   /* copy my psp into debug process */
  246.   movedata(_stubinfo->psp_selector, 0, si.psp_selector, 0, 128);
  247.  
  248.   _farpokew(si.psp_selector, 0x2c, new_env_selector);
  249.  
  250.   /* copy command arguments into debug process */
  251.   movedata(my_ds, (unsigned)cmdline, si.psp_selector, 128, 128);
  252.   /* copy si we built into debug process */
  253.   movedata(my_ds, (unsigned)&si, si.ds_selector, 0, sizeof(si));
  254.   load_state->__ds = client_ds;
  255.   load_state->__cs = client_cs;
  256.   load_state->__eip = start_eip;
  257.   load_state->__esp = si.minkeep;
  258.   load_state->__ss = si.ds_selector;
  259.   load_state->__fs = si.ds_selector;
  260.   load_state->__es = load_state->__gs = client_ds;
  261.   load_state->__eflags = 0x3202;
  262.   return 0;
  263. }
  264.  
  265. #ifdef TEST
  266. void main(int argc, char **argv)
  267. {
  268.   int i;
  269.   char cmdline[128];
  270.   jmp_buf load_state;
  271.  
  272.   if(argc < 2) {
  273.     printf("Usage: v2load imagename [args]\n");
  274.     exit(1);
  275.   }
  276.  
  277.   putenv("FOO=from-v2load");
  278.   
  279.   cmdline[1] = 0;
  280.   for(i=2; argv[i]; i++) {
  281.       strcat(cmdline+1, " ");
  282.       strcat(cmdline+1, argv[i]);
  283.   }
  284.   i = strlen(cmdline+1);
  285.   cmdline[0] = i;
  286.   cmdline[i+1] = 13;
  287.   if(v2loadimage(argv[1],cmdline,load_state)) {
  288.     printf("Load failed for %s\n",argv[1]);
  289.     exit(2);
  290.   }
  291.   printf("Program text ................: %08x - %08x\n",
  292.          areas[A_text].first_addr, areas[A_text].last_addr);
  293.   printf("Program data ................: %08x - %08x\n",
  294.          areas[A_data].first_addr, areas[A_data].last_addr);
  295.   printf("Program bss .................: %08x - %08x\n",
  296.          areas[A_bss].first_addr, areas[A_bss].last_addr);
  297.   printf("Program stack ...............: %08x - %08x\n",
  298.          areas[A_stack].first_addr, areas[A_stack].last_addr);
  299.   printf("Program arena ...............: %08x - %08x\n",
  300.          areas[A_arena].first_addr, areas[A_arena].last_addr);
  301.   printf("Jumping to image...\n");
  302.   longjmp(load_state, 0);
  303. }
  304. #endif
  305.