home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / trash / part04 / process.c < prev   
Encoding:
C/C++ Source or Header  |  1992-03-22  |  24.4 KB  |  1,311 lines

  1. #include    <fcntl.h>
  2. #include    <stdio.h>
  3. #include    <unistd.h>
  4. #include    <filehdr.h>
  5. #include    <scnhdr.h>
  6. #include    <syms.h>
  7. #include    <ldfcn.h>
  8. #include    <aouthdr.h>
  9. #include    <errno.h>
  10. #include    "register.h"
  11. #include    "symtab.h"
  12. #include    "diblock.h"
  13. #include    "instrn.h"
  14. #include    "process.h"
  15. #include    "wcache.h"
  16. #include    "nels.h"
  17.  
  18. #if    0
  19. #endif    /* 0 */
  20. #define    SPECIAL_MEMCPY
  21.  
  22. #if    defined(SPECIAL_MEMCPY)
  23. #define    Wmemcpy(to,from,n) \
  24. { \
  25.     if \
  26.     ( \
  27.         (n) == sizeof(unsigned long) \
  28.         && \
  29.         (((unsigned long)(from)) & 0x3) == 0x0 \
  30.         && \
  31.         (((unsigned long)(to)) & 0x3) == 0x0 \
  32.     ) \
  33.         *(unsigned long *)(to) = *(unsigned long *)(from); \
  34.     else \
  35.         (void)memcpy((to), (from), (n)); \
  36. }
  37. #else    /* defined(SPECIAL_MEMCPY) */
  38. #define    Wmemcpy(to,from,n)    (void)memcpy((to), (from), (n))
  39. #endif    /* defined(SPECIAL_MEMCPY) */
  40.  
  41. extern void            couldnot();
  42. extern void            warning();
  43. extern char            *strdup();
  44. extern char            *say_register();
  45. extern int            symtab_open();
  46. extern int            symtab_close();
  47. extern char            *symtab_text_address();
  48. extern LDFILE            *my_ldopen();
  49. extern int            histo_init();
  50. extern char            *proc_text_address();
  51. extern int            clear_decoded_page();
  52.  
  53. extern int            errno;
  54.  
  55. extern FILE            *outfp;
  56.  
  57. extern int            Cflag;
  58. extern int            Hflag;
  59. extern int            Vflag;
  60.  
  61. process                P;
  62. int                give_warnings        = 1;
  63.  
  64. static int            ld_section_read();
  65. static int            procimput();
  66.  
  67. int
  68. procopen(adotout)
  69. char    *adotout;
  70. {
  71.     FILE        *fp;
  72.     LDFILE        *ldptr;
  73.     struct filehdr    *fhp;
  74.     unsigned short    sectindx;
  75.     SCNHDR        secthead;
  76.     AOUTHDR        adotout_header;
  77.     int        i;
  78.     int        length;
  79.  
  80.     if ((P.p_adotout = strdup(adotout)) == (char *)0)
  81.         return -1;
  82.  
  83.     P.p_pid = getpid();
  84.  
  85.     /*
  86.      * Read the executable and initialise
  87.      * our memory image of it.
  88.      */
  89.  
  90.     if ((ldptr = my_ldopen(adotout, (LDFILE *)0)) == (LDFILE *)0)
  91.         return -1;
  92.  
  93.     if (ISARCHIVE(TYPE(ldptr)))
  94.     {
  95.         vcouldnot("interpret contents of archive \"%s\"", adotout);
  96.         (void)ldclose(ldptr);
  97.         return -1;
  98.     }
  99.  
  100.     fhp = &HEADER(ldptr);
  101.  
  102.     if (!ISCOFF(fhp->f_magic))
  103.     {
  104.         vcouldnot("interpret contents of non-COFF executable \"%s\"", adotout);
  105.         (void)ldclose(ldptr);
  106.         return -1;
  107.     }
  108.  
  109.     /*
  110.      * Determine the entry point of the process.
  111.      */
  112.     if (ldohseek(ldptr) != SUCCESS)
  113.     {
  114.         vcouldnot("seek to start of optional header structure in executable \"%s\"", adotout);
  115.         (void)ldclose(ldptr);
  116.         return -1;
  117.     }
  118.  
  119.     if (FREAD(&adotout_header, sizeof(adotout_header), 1, ldptr) != 1)
  120.     {
  121.         vcouldnot("read optional header structure from executable \"%s\"", adotout);
  122.         (void)ldclose(ldptr);
  123.         return -1;
  124.     }
  125.  
  126.     if (Vflag)
  127.     {
  128.         fprintf(outfp, "magic == 0%o\n", adotout_header.magic);
  129.         fprintf(outfp, "vstamp == 0x%x(%d)\n", adotout_header.vstamp, adotout_header.vstamp);
  130.         fprintf(outfp, "tsize == 0x%x(%d)\n", adotout_header.tsize, adotout_header.tsize);
  131.         fprintf(outfp, "dsize == 0x%x(%d)\n", adotout_header.dsize, adotout_header.dsize);
  132.         fprintf(outfp, "bsize == 0x%x(%d)\n", adotout_header.bsize, adotout_header.bsize);
  133.         fprintf(outfp, "entry == 0x%x(%d)\n", adotout_header.entry, adotout_header.entry);
  134.         fprintf(outfp, "text_start == 0x%x(%d)\n", adotout_header.text_start, adotout_header.text_start);
  135.         fprintf(outfp, "data_start == 0x%x(%d)\n", adotout_header.data_start, adotout_header.data_start);
  136.         fprintf(outfp, "bss_start == 0x%x(%d)\n", adotout_header.bss_start, adotout_header.bss_start);
  137.         fprintf(outfp, "gprmask == 0x%x(%d)\n", adotout_header.gprmask, adotout_header.gprmask);
  138.         fprintf(outfp, "gp_value == 0x%x(%d)\n", adotout_header.gp_value, adotout_header.gp_value);
  139.     }
  140.  
  141.     if (adotout_header.magic == OMAGIC)
  142.         P.p_text_region_is_readonly = 0;
  143.     else
  144.         P.p_text_region_is_readonly = 1;
  145.  
  146.     /*
  147.      * Initialise the PC as the process's entry point.
  148.      */
  149.     P.p_entry_point = adotout_header.entry;
  150.  
  151.     P.p_text_region_min = adotout_header.text_start;
  152.     P.p_text_region_limit = P.p_text_region_min + adotout_header.tsize - 1;
  153.     P.p_text_region_wlimit = P.p_text_region_limit + 1 - sizeof(unsigned long);
  154.     P.p_text_region = calloc(adotout_header.tsize / sizeof(unsigned long), sizeof(unsigned long));
  155.     if (P.p_text_region == (unsigned char *)0)
  156.     {
  157.         vcouldnot("grow text space to size %d bytes", adotout_header.tsize);
  158.         (void)ldclose(ldptr);
  159.         return -1;
  160.     }
  161.  
  162.     P.p_data_region_min = adotout_header.data_start;
  163.  
  164.     /*
  165.      * Initialise GP to the process's gp value.
  166.      */
  167.     if (quiet_procsput(R_GP, adotout_header.gp_value) == -1)
  168.     {
  169.         (void)ldclose(ldptr);
  170.         return -1;
  171.     }
  172.  
  173.     /*
  174.      * Read each COFF section in turn, copying the data of those
  175.      * that are required to memory.
  176.      */
  177.     sectindx = 1;
  178.     while (ldshread(ldptr, sectindx, §head) == SUCCESS)
  179.     {
  180.         if (Vflag)
  181.         {
  182.             fprintf
  183.             (
  184.                 outfp,
  185.                 "read section %d: name=\"%s\",paddr=0x%x,vaddr=0x%x,size=%d,scnptr=%d,relptr=%d,lnnoptr=%d,nreloc=%d,nlnno=%d,flags=0x%x\n",
  186.                 sectindx,
  187.                 §head.s_name[0],
  188.                 secthead.s_paddr,
  189.                 secthead.s_vaddr,
  190.                 secthead.s_size,
  191.                 secthead.s_scnptr,
  192.                 secthead.s_relptr,
  193.                 secthead.s_lnnoptr,
  194.                 secthead.s_nreloc,
  195.                 secthead.s_nlnno,
  196.                 secthead.s_flags
  197.             );
  198.         }
  199.  
  200.         switch (secthead.s_flags & 0xF)
  201.         {
  202.         case STYP_REG:
  203.             if (Vflag)
  204.                 fprintf(outfp, "STYP_REG: allocated, relocated, loaded\n");
  205.             break;
  206.  
  207.         case STYP_DSECT:
  208.             if (Vflag)
  209.                 fprintf(outfp, "STYP_DSECT: not allocated, relocated, not loaded\n");
  210.             break;
  211.  
  212.         case STYP_NOLOAD:
  213.             if (Vflag)
  214.                 fprintf(outfp, "STYP_NOLOAD: allocated, relocated, not loaded\n");
  215.             break;
  216.  
  217.         case STYP_GROUP:
  218.             if (Vflag)
  219.                 fprintf(outfp, "STYP_GROUP: grouped\n");
  220.             break;
  221.  
  222.         case STYP_PAD:
  223.             if (Vflag)
  224.                 fprintf(outfp, "STYP_PAD: not allocated, not relocated, loaded\n");
  225.             break;
  226.  
  227.         default:
  228.             vcouldnot("recognise section type 0x%x", secthead.s_flags & 0xF);
  229.             (void)ldclose(ldptr);
  230.             return -1;
  231.         }
  232.  
  233.         switch (secthead.s_flags & ~0xF)
  234.         {
  235.         case STYP_COPY:
  236.             if (Vflag)
  237.                 fprintf(outfp, "STYP_COPY: not allocated, not relocated, loaded\n");
  238.             break;
  239.  
  240.         case STYP_TEXT:
  241.             if (Vflag)
  242.                 fprintf(outfp, "STYP_TEXT: text only\n");
  243.             break;
  244.  
  245.         case STYP_DATA:
  246.             if (Vflag)
  247.                 fprintf(outfp, "STYP_DATA: data only\n");
  248.             break;
  249.  
  250.         case STYP_BSS:
  251.             if (Vflag)
  252.                 fprintf(outfp, "STYP_BSS: bss only\n");
  253.             break;
  254.  
  255.         case STYP_RDATA:
  256.             if (Vflag)
  257.                 fprintf(outfp, "STYP_RDATA: read only data only\n");
  258.             break;
  259.  
  260.         case STYP_SDATA:
  261.             if (Vflag)
  262.                 fprintf(outfp, "STYP_SDATA: small data only\n");
  263.             break;
  264.  
  265.         case STYP_SBSS:
  266.             if (Vflag)
  267.                 fprintf(outfp, "STYP_SBSS: small bss only\n");
  268.             break;
  269.  
  270.         case STYP_UCODE:
  271.             if (Vflag)
  272.                 fprintf(outfp, "STYP_UCODE: ucode only\n");
  273.             break;
  274.  
  275.         case STYP_LIT8:
  276.             if (Vflag)
  277.                 fprintf(outfp, "STYP_LIT8: literal pool for 8-byte literals\n");
  278.             break;
  279.  
  280.         case STYP_LIT4:
  281.             if (Vflag)
  282.                 fprintf(outfp, "STYP_LIT4: literal pool for 4-byte literals\n");
  283.             break;
  284.  
  285.         case S_NRELOC_OVFL:
  286.             if (Vflag)
  287.                 fprintf(outfp, "S_NRELOC_OVFL: s_nreloc overflowed, the value is in v_addr of the first entry\n");
  288.             break;
  289.  
  290.         case STYP_LIB:
  291.             if (Vflag)
  292.                 fprintf(outfp, "STYP_LIB: section is a .lib section\n");
  293.             break;
  294.  
  295.         case STYP_INIT:
  296.             if (Vflag)
  297.                 fprintf(outfp, "STYP_INIT: section only contains the text instructions for the .init sec.\n");
  298.             break;
  299.  
  300.         default:
  301.             vcouldnot("recognise section type 0x%x", secthead.s_flags & ~0xF);
  302.             (void)ldclose(ldptr);
  303.             return -1;
  304.         }
  305.  
  306.         if (strcmp(§head.s_name[0], ".lib") == 0)
  307.         {
  308.             vcouldnot("handle executable containing a .lib (call to shared library) section");
  309.             return -1;
  310.         }
  311.         else if (strcmp(§head.s_name[0], ".data") == 0)
  312.         {
  313.             /*
  314.              * Initialise the start of the writable data.
  315.              */
  316.             if (quiet_procwrdataput(secthead.s_vaddr) == -1)
  317.             {
  318.                 (void)ldclose(ldptr);
  319.                 return -1;
  320.             }
  321.         }
  322.         else if (strcmp(§head.s_name[0], ".bss") == 0)
  323.         {
  324.             /*
  325.              * Initialise The Break.
  326.              */
  327.             if (procbreakput(secthead.s_vaddr + secthead.s_size) == -1)
  328.             {
  329.                 vcouldnot("set break to 0x%x", secthead.s_vaddr + secthead.s_size);
  330.                 (void)ldclose(ldptr);
  331.                 return -1;
  332.             }
  333.         }
  334.  
  335.         if (ld_section_read(ldptr, secthead.s_scnptr, secthead.s_vaddr, secthead.s_size) == -1)
  336.         {
  337.             (void)ldclose(ldptr);
  338.             return -1;
  339.         }
  340.  
  341.         sectindx++;
  342.     }
  343.  
  344.     if (symtab_open(ldptr, adotout, &P.p_symtab) == -1)
  345.     {
  346.         (void)ldclose(ldptr);
  347.         return -1;
  348.     }
  349.  
  350.     /*
  351.      * Close the executable file.
  352.      */
  353.     if (ldclose(ldptr) != SUCCESS)
  354.     {
  355.         vcouldnot("close executable \"%s\"", adotout);
  356.         return -1;
  357.     }
  358.  
  359.     if (Hflag)
  360.     {
  361.         if (histo_init(P.p_text_region_min, P.p_text_region_limit + 1 - P.p_text_region_min) == -1)
  362.             return -1;
  363.     }
  364.  
  365.     P.p_stack_region_min = STACK_MAX + 1;
  366.  
  367.     return 0;
  368. }
  369.  
  370. static
  371. int
  372. ld_section_read(srce_ldptr, srce_offset, dest_offset, count)
  373. LDFILE    *srce_ldptr;
  374. long    srce_offset;
  375. long    dest_offset;
  376. long    count;
  377. {
  378.     unsigned char    buf[64 * 1024];
  379.  
  380.     if (srce_offset == (long)0)
  381.         (void)memset(&buf[0], 0x00, sizeof(buf));
  382.     else
  383.     {
  384.         if (FSEEK(srce_ldptr, srce_offset, SEEK_SET) != 0)
  385.         {
  386.             vcouldnot("FSEEK to offset %d in source file in ld_section_read()", srce_offset);
  387.             return -1;
  388.         }
  389.     }
  390.  
  391.     while (count > 0)
  392.     {
  393.         int    chunk;
  394.  
  395.         chunk = (count >= sizeof(buf)) ? sizeof(buf) : count;
  396.  
  397.         if (srce_offset != (long)0)
  398.         {
  399.             if (FREAD(&buf[0], chunk, 1, srce_ldptr) != 1)
  400.             {
  401.                 vcouldnot("FREAD from source file in ld_section_read()");
  402.                 return -1;
  403.             }
  404.         }
  405.  
  406.         if (procimput(dest_offset, &buf[0], chunk) == -1)
  407.             return -1;
  408.  
  409.         count -= chunk;
  410.         dest_offset += chunk;
  411.     }
  412.  
  413.     return 0;
  414. }
  415.  
  416. int
  417. procclose()
  418. {
  419.     FILE    *fp;
  420.     int    mi;
  421.     int    i;
  422.  
  423.     if (P.p_stack_region != (unsigned char *)0)
  424.         (void)free(P.p_stack_region);
  425.  
  426.     if (P.p_data_region != (unsigned char *)0)
  427.         (void)free(P.p_data_region);
  428.  
  429.     if (P.p_text_region != (unsigned char *)0)
  430.         (void)free(P.p_text_region);
  431.  
  432.     if (symtab_close(&P.p_symtab) == -1)
  433.         return -1;
  434.  
  435.     if (P.p_adotout != (char *)0)
  436.     {
  437.         (void)free(P.p_adotout);
  438.         P.p_adotout = (char *)0;
  439.     }
  440.  
  441.     (void)fflush(outfp);
  442.  
  443.     return 0;
  444. }
  445.  
  446. void
  447. procsput_trace(regi, v)
  448. int        regi;
  449. unsigned long    v;
  450. {
  451.     if (Cflag)
  452.     {
  453.         switch (regi)
  454.         {
  455.         case R_0:
  456.             break;
  457.  
  458.         case R_GP:
  459.         case R_RA:
  460.         case R_SP:
  461.             fprintf(outfp, "%6d:\t%s = %s;\n", P.p_pid, say_register(regi), proc_text_address(v));
  462.             break;
  463.  
  464.         default:
  465.             fprintf(outfp, "%6d:\t%s = 0x%08x;\n", P.p_pid, say_register(regi), v);
  466.             break;
  467.         }
  468.     }
  469.     else
  470.         fprintf(outfp, "\t\tprocsput(%d, %s, %d)\n", P.p_pid, say_register(regi), v);
  471. }
  472.  
  473. void
  474. procsget_trace(regi, r)
  475. int        regi;
  476. unsigned long    r;
  477. {
  478.     if (Cflag)
  479.     {
  480. #if    0
  481.         switch (regi)
  482.         {
  483.         case R_RA:
  484.             fprintf(outfp, "%6d:\t? = %s /* %s */;\n", P.p_pid, say_register(regi), proc_text_address(r));
  485.             break;
  486.  
  487.         default:
  488.             fprintf(outfp, "%6d:\t? = %s /* 0x%08x */;\n", P.p_pid, say_register(regi), r);
  489.             break;
  490.         }
  491. #endif    /* 0 */
  492.     }
  493.     else
  494.         fprintf(outfp, "\t\tprocsget(%d, %s, %d)\n", P.p_pid, say_register(regi), r);
  495. }
  496.  
  497. void
  498. procmput_trace(offset, cp, length)
  499. unsigned long    offset;
  500. char        *cp;
  501. int        length;
  502. {
  503.     if (Cflag)
  504.     {
  505.         while (length >= sizeof(int))
  506.         {
  507.             fprintf(outfp, "%6d:\t*(int *)%s = 0x%08x;\n", P.p_pid, proc_text_address(offset), *(int *)cp);
  508.             length -= sizeof(int);
  509.             cp += sizeof(int);
  510.             offset += sizeof(int);
  511.         }
  512.  
  513.         while (length >= sizeof(short))
  514.         {
  515.             fprintf(outfp, "%6d:\t*(short *)%s = 0x%04x;\n", P.p_pid, proc_text_address(offset), *(short *)cp);
  516.             length -= sizeof(short);
  517.             cp += sizeof(short);
  518.             offset += sizeof(short);
  519.         }
  520.  
  521.         while (length >= sizeof(char))
  522.         {
  523.             fprintf(outfp, "%6d:\t*(char *)%s = 0x%02x;\n", P.p_pid, proc_text_address(offset), *(unsigned char *)cp);
  524.             length -= sizeof(char);
  525.             cp += sizeof(char);
  526.             offset += sizeof(char);
  527.         }
  528.     }
  529.     else
  530.         fprintf(outfp, "\t\t\tprocmput(pid=%d,offset=%d,length=%d)\n", P.p_pid, offset, length);
  531. }
  532.  
  533. void
  534. procmget_trace(offset, cp, length)
  535. unsigned long    offset;
  536. char        *cp;
  537. int        length;
  538. {
  539.     if (Cflag)
  540.     {
  541. #if    0
  542.         while (length >= sizeof(int))
  543.         {
  544.             fprintf(outfp, "%6d:\t? = *(int *)%s /* 0x%08x */;\n", P.p_pid, proc_text_address(offset), *(int *)cp);
  545.             length -= sizeof(int);
  546.             cp += sizeof(int);
  547.             offset += sizeof(int);
  548.         }
  549.  
  550.         while (length >= sizeof(short))
  551.         {
  552.             fprintf(outfp, "%6d:\t? = *(short *)%s /* 0x%04x */;\n", P.p_pid, proc_text_address(offset), *(short *)cp);
  553.             length -= sizeof(short);
  554.             cp += sizeof(short);
  555.             offset += sizeof(short);
  556.         }
  557.  
  558.         while (length >= sizeof(char))
  559.         {
  560.             fprintf(outfp, "%6d:\t? = *(char *)%s /* 0x%02x */;\n", P.p_pid, proc_text_address(offset), *(unsigned char *)cp);
  561.             length -= sizeof(char);
  562.             cp += sizeof(char);
  563.             offset += sizeof(char);
  564.         }
  565. #endif    /* 0 */
  566.     }
  567.     else
  568.         fprintf(outfp, "\t\t\tprocmget(pid=%d,offset=%d,length=%d)\n", P.p_pid, offset, length);
  569. }
  570.  
  571. void
  572. procsget_warning(regi)
  573. int    regi;
  574. {
  575.     warning("read from kernel-reserved register %s", say_register(regi));
  576. }
  577.  
  578. int
  579. procbreakput(newbrk)
  580. unsigned long    newbrk;
  581. {
  582.     unsigned long    new_region_size;
  583.     unsigned char    *new_region;
  584.  
  585.     wcache_clear();
  586.  
  587.     new_region_size = newbrk - P.p_data_region_min;
  588.  
  589.     if ((new_region = calloc(new_region_size, 1)) == (unsigned char *)0)
  590.         return -1;
  591.  
  592.     if (P.p_data_region != (unsigned char *)0)
  593.     {
  594.         unsigned long    p_data_region_size;
  595.  
  596.         p_data_region_size = P.p_data_region_limit + 1 - P.p_data_region_min;
  597.  
  598.         (void)memcpy(new_region, P.p_data_region, (new_region_size < p_data_region_size) ? new_region_size : p_data_region_size);
  599.         (void)free(P.p_data_region);
  600.     }
  601.  
  602.     P.p_data_region = new_region;
  603.     P.p_data_region_limit = newbrk - 1;
  604.     P.p_data_region_wlimit = P.p_data_region_limit + 1 - sizeof(unsigned long);
  605.  
  606.     return 0;
  607. }
  608.  
  609. int
  610. procbreakget(oldbrkp)
  611. unsigned long    *oldbrkp;
  612. {
  613.     *oldbrkp = P.p_data_region_limit + 1;
  614.  
  615.     return 0;
  616. }
  617.  
  618. int
  619. procwrdataput(newwrdata)
  620. unsigned long    newwrdata;
  621. {
  622.     P.p_writable_data = newwrdata;
  623.  
  624.     return 0;
  625. }
  626.  
  627. int
  628. procwrdataget(oldwrdatap)
  629. unsigned long    *oldwrdatap;
  630. {
  631.     *oldwrdatap = P.p_writable_data;
  632.  
  633.     return 0;
  634. }
  635.  
  636. static
  637. int
  638. procimput(offset, cp, length)
  639. unsigned long    offset;
  640. unsigned char    *cp;
  641. int        length;
  642. {
  643.     unsigned long    limit;
  644.     int        i;
  645.  
  646.     limit = offset + length - 1;
  647.  
  648.     if (limit <= P.p_text_region_limit)
  649.     {
  650.         if ((i = offset - P.p_text_region_min) < 0)
  651.         {
  652.             vcouldnot("write %d byte%s at text address 0x%x: illegal (too small) address", length, (length == 1) ? "" : "s", offset);
  653.             return -1;
  654.         }
  655.  
  656.         Wmemcpy(&P.p_text_region[i], cp, length);
  657.     }
  658.     else if (limit <= DATA_MAX)
  659.     {
  660.         if ((i = offset - P.p_data_region_min) < 0)
  661.         {
  662.             vcouldnot("write %d byte%s at data address 0x%x: illegal (too small) address", length, (length == 1) ? "" : "s", offset);
  663.             return -1;
  664.         }
  665.  
  666.         if (limit > P.p_data_region_limit)
  667.         {
  668.             if (procbreakput(limit + 1) == -1)
  669.             {
  670.                 vcouldnot("set break to 0x%x", limit + 1);
  671.                 return -1;
  672.             }
  673.         }
  674.  
  675.         Wmemcpy(&P.p_data_region[i], cp, length);
  676.     }
  677.     else
  678.     {
  679.         /*
  680.          * Stack space or above.
  681.          */
  682.         vcouldnot("write %d byte%s at non-text, non-data address 0x%x: illegal (too big) address", length, (length == 1) ? "" : "s", offset);
  683.         return -1;
  684.     }
  685.  
  686.     return 0;
  687. }
  688.  
  689. /*
  690.  * Grow the stack down to include 'offset'.
  691.  */
  692. int
  693. proc_grow_stack(dipc, offset)
  694. dinstrn        *dipc;
  695. unsigned long    offset;
  696. {
  697.     unsigned long    new_stack_region_size;
  698.     unsigned char    *new_stack_region;
  699.  
  700.     wcache_clear();
  701.  
  702.     if (offset < STACK_MIN)
  703.     {
  704.         GLOBALdipc = dipc;
  705.         vcouldnot("grow stack to address 0x%x: below 0x%x", offset, STACK_MIN);
  706.         return -1;
  707.     }
  708.  
  709.     new_stack_region_size = STACK_MAX + 1 - offset;
  710.     new_stack_region_size += 4096;    /* slop */
  711.     new_stack_region_size &= ~0xF;    /* Quadword aligned */
  712.  
  713.     if ((new_stack_region = calloc(new_stack_region_size / 16, sizeof(unsigned char) * 16)) == (unsigned char *)0)
  714.     {
  715.         GLOBALdipc = dipc;
  716.         vcouldnot("grow stack to %d bytes", new_stack_region_size);
  717.         return -1;
  718.     }
  719.  
  720.     if (P.p_stack_region != (unsigned char *)0)
  721.     {
  722.         unsigned long    p_stack_region_size;
  723.  
  724.         p_stack_region_size = STACK_MAX + 1 - P.p_stack_region_min;
  725.  
  726.         (void)memcpy(&new_stack_region[new_stack_region_size - p_stack_region_size], P.p_stack_region, p_stack_region_size);
  727.         (void)free(P.p_stack_region);
  728.     }
  729.  
  730.     P.p_stack_region = new_stack_region;
  731.     P.p_stack_region_min = STACK_MAX + 1 - new_stack_region_size;
  732.  
  733.     return 0;
  734. }
  735.  
  736. int
  737. quiet_procmget(dipc, offset, cp, length)
  738. dinstrn        *dipc;
  739. unsigned long    offset;
  740. unsigned char    *cp;
  741. int        length;
  742. {
  743.     unsigned long    limit;
  744.     int        i;
  745.  
  746.     if (length == 0)
  747.         return 0;
  748.  
  749.     limit = offset + length - 1;
  750.  
  751.     if (limit <= P.p_text_region_limit)
  752.     {
  753.         if ((i = offset - P.p_text_region_min) < 0)
  754.         {
  755.             GLOBALdipc = dipc;
  756.             vcouldnot("read %d byte%s at text address 0x%x: illegal (too small) address", length, (length == 1) ? "" : "s", offset);
  757.             return -1;
  758.         }
  759.  
  760.         Wmemcpy(cp, &P.p_text_region[i], length);
  761.     }
  762.     else if (limit <= P.p_data_region_limit)
  763.     {
  764.         if ((i = offset - P.p_data_region_min) < 0)
  765.         {
  766.             GLOBALdipc = dipc;
  767.             vcouldnot("read %d byte%s at data address 0x%x: illegal (too small) address", length, (length == 1) ? "" : "s", offset);
  768.             return -1;
  769.         }
  770.  
  771.         Wmemcpy(cp, &P.p_data_region[i], length);
  772.     }
  773.     else if (limit <= STACK_MAX)
  774.     {
  775.         if ((i = offset - P.p_stack_region_min) < 0)
  776.         {
  777.             if (proc_grow_stack(dipc, offset) == -1)
  778.                 return -1;
  779.  
  780.             i = offset - P.p_stack_region_min;
  781.         }
  782.  
  783.         Wmemcpy(cp, &P.p_stack_region[i], length);
  784.     }
  785.     else
  786.     {
  787.         /*
  788.          * Hole above Stack space.
  789.          */
  790.         GLOBALdipc = dipc;
  791.         vcouldnot("read %d byte%s at data address 0x%x: illegal (i.e. too big) address", length, (length == 1) ? "" : "s", offset);
  792.         return -1;
  793.     }
  794.  
  795.     return 0;
  796. }
  797.  
  798. int
  799. procmget(dipc, offset, cp, length)
  800. dinstrn        *dipc;
  801. unsigned long    offset;
  802. unsigned char    *cp;
  803. int        length;
  804. {
  805.     int    result;
  806.  
  807.     result = quiet_procmget(dipc, offset, cp, length);
  808.  
  809.     if (Mflag)
  810.         procmget_trace(offset, cp, length);
  811.  
  812.     return result;
  813. }
  814.  
  815. int
  816. proc_mem_contiguous(offset, length, p)
  817. unsigned long    offset;
  818. int        length;
  819. char        **p;
  820. {
  821.     unsigned long    limit;
  822.  
  823.     limit = offset + length - 1;
  824.  
  825.     if
  826.     (
  827.         offset >= P.p_text_region_min
  828.         &&
  829.         limit <= P.p_text_region_limit
  830.     )
  831.     {
  832.         if (p != (char **)0)
  833.             *p = &P.p_text_region[offset - P.p_text_region_min];
  834.         return 1;
  835.     }
  836.  
  837.     if
  838.     (
  839.         offset >= P.p_data_region_min
  840.         &&
  841.         limit <= P.p_data_region_limit
  842.     )
  843.     {
  844.         if (p != (char **)0)
  845.             *p = &P.p_data_region[offset - P.p_data_region_min];
  846.         return 1;
  847.     }
  848.  
  849.     if
  850.     (
  851.         offset >= P.p_stack_region_min
  852.         &&
  853.         limit <= STACK_MAX
  854.     )
  855.     {
  856.         if (p != (char **)0)
  857.             *p = &P.p_stack_region[offset - P.p_stack_region_min];
  858.         return 1;
  859.     }
  860.  
  861.     return 0;
  862. }
  863.  
  864. int
  865. quiet_procmput(dipc, offset, cp, length)
  866. dinstrn        *dipc;
  867. unsigned long    offset;
  868. unsigned char    *cp;
  869. int        length;
  870. {
  871.     unsigned long    limit;
  872.     int        i;
  873.  
  874.     if (length == 0)
  875.         return 0;
  876.  
  877.     limit = offset + length - 1;
  878.  
  879.     if (offset < P.p_text_region_min)
  880.     {
  881.         /*
  882.          * Hole before text.
  883.          */
  884.         GLOBALdipc = dipc;
  885.         vcouldnot("write %d byte%s at address 0x%x: illegal (i.e. too small) address", length, (length == 1) ? "" : "s", offset);
  886.         return -1;
  887.     }
  888.  
  889.     if (offset <= P.p_text_region_limit)
  890.     {
  891.         int    tlength;
  892.  
  893.         /*
  894.          * Text (or Readonly Data?) space.
  895.          */
  896.         if (P.p_text_region_is_readonly)
  897.         {
  898.             GLOBALdipc = dipc;
  899.             vcouldnot("write %d byte%s at address 0x%x: readonly (text or data) address", length, (length == 1) ? "" : "s", offset);
  900.             return -1;
  901.         }
  902.  
  903.         if (limit > P.p_text_region_limit)
  904.             tlength = P.p_text_region_limit + 1 - offset;
  905.         else
  906.             tlength = length;
  907.  
  908.         Wmemcpy(&P.p_text_region[offset - P.p_text_region_min], cp, tlength);
  909.  
  910.         /*
  911.          * Disable decoded instructions for this range.
  912.          */
  913.         {
  914.             int        t;
  915.             unsigned long    o;
  916.  
  917.             t = tlength;
  918.             o = offset;
  919.  
  920.             while (t > 0)
  921.             {
  922.                 int    remainder;
  923.  
  924.                 if (clear_decoded_page(dipc, o, &remainder) == -1)
  925.                     return -1;
  926.  
  927.                 o += remainder;
  928.                 t -= remainder;
  929.             }
  930.         }
  931.  
  932.         offset += tlength;
  933.         cp += tlength;
  934.         length -= tlength;
  935.  
  936.         if (length == 0)
  937.             return 0;
  938.     }
  939.  
  940.     if ((i = offset - P.p_data_region_min) < 0)
  941.     {
  942.         /*
  943.          * Hole between text and data.
  944.          */
  945.         GLOBALdipc = dipc;
  946.         vcouldnot("write %d byte%s at address 0x%x: illegal (i.e. unmapped) address between text and data regions", length, (length == 1) ? "" : "s", offset);
  947.         return -1;
  948.     }
  949.  
  950.     if (limit <= P.p_data_region_limit)
  951.     {
  952.         /*
  953.          * Data space.
  954.          */
  955.         Wmemcpy(&P.p_data_region[i], cp, length);
  956.         return 0;
  957.     }
  958.  
  959.     if (limit <= STACK_MAX)
  960.     {
  961.         /*
  962.          * Stack space.
  963.          */
  964.         if ((i = offset - P.p_stack_region_min) < 0)
  965.         {
  966.             if (proc_grow_stack(dipc, offset) == -1)
  967.                 return -1;
  968.  
  969.             i = offset - P.p_stack_region_min;
  970.         }
  971.  
  972.         Wmemcpy(&P.p_stack_region[i], cp, length);
  973.         return 0;
  974.     }
  975.  
  976.     /*
  977.      * Hole above Stack space.
  978.      */
  979.     GLOBALdipc = dipc;
  980.     vcouldnot("write %d byte%s starting at address 0x%x: illegal (i.e. too big) address", length, (length == 1) ? "" : "s", offset);
  981.     return -1;
  982. }
  983.  
  984. int
  985. procmput(dipc, offset, cp, length)
  986. dinstrn        *dipc;
  987. unsigned long    offset;
  988. unsigned char    *cp;
  989. int        length;
  990. {
  991.     if (Mflag)
  992.         procmput_trace(offset, cp, length);
  993.  
  994.     return quiet_procmput(dipc, offset, cp, length);
  995. }
  996.  
  997. char    *
  998. proc_text_address(text_address)
  999. unsigned long    text_address;
  1000. {
  1001.     return symtab_text_address((P.p_adotout == (char *)0) ? (symtab *)0 : &P.p_symtab, text_address);
  1002. }
  1003.  
  1004. int
  1005. quiet_procsget(r, v)
  1006. int        r;
  1007. unsigned long    *v;
  1008. {
  1009.     int    saved_Rflag;
  1010.  
  1011.     saved_Rflag = Rflag;
  1012.     Rflag = 0;
  1013.     procsget(r, *v);
  1014.     Rflag = saved_Rflag;
  1015.  
  1016.     return 0;
  1017. }
  1018.  
  1019. int
  1020. quiet_procsput(r, v)
  1021. int        r;
  1022. unsigned long    v;
  1023. {
  1024.     int    saved_Rflag;
  1025.  
  1026.     saved_Rflag = Rflag;
  1027.     Rflag = 0;
  1028.     procsput(r, v);
  1029.     Rflag = saved_Rflag;
  1030.  
  1031.     return 0;
  1032. }
  1033.  
  1034. int
  1035. quiet_procbreakget(v)
  1036. unsigned long    *v;
  1037. {
  1038.     int    result;
  1039.     int    saved_Rflag;
  1040.  
  1041.     saved_Rflag = Rflag;
  1042.     Rflag = 0;
  1043.     result = procbreakget(v);
  1044.     Rflag = saved_Rflag;
  1045.  
  1046.     return result;
  1047. }
  1048.  
  1049. int
  1050. quiet_procbreakput(v)
  1051. unsigned long    v;
  1052. {
  1053.     int    result;
  1054.     int    saved_Rflag;
  1055.  
  1056.     saved_Rflag = Rflag;
  1057.     Rflag = 0;
  1058.     result = procbreakput(v);
  1059.     Rflag = saved_Rflag;
  1060.  
  1061.     return result;
  1062. }
  1063.  
  1064. int
  1065. quiet_procwrdataput(v)
  1066. unsigned long    v;
  1067. {
  1068.     int    result;
  1069.     int    saved_Rflag;
  1070.  
  1071.     saved_Rflag = Rflag;
  1072.     Rflag = 0;
  1073.     result = procwrdataput(v);
  1074.     Rflag = saved_Rflag;
  1075.  
  1076.     return result;
  1077. }
  1078.  
  1079. int
  1080. magic_ok(filename)
  1081. char    *filename;
  1082. {
  1083.     int        fd;
  1084.     int        saved_errno;
  1085.     unsigned short    smagic;
  1086.  
  1087.     saved_errno = errno;
  1088.  
  1089.     if ((fd = open(filename, O_RDONLY)) == -1)
  1090.         return 0;
  1091.  
  1092.     if (read(fd, (unsigned char *)&smagic, sizeof(smagic)) != sizeof(smagic))
  1093.     {
  1094.         saved_errno = errno;
  1095.         (void)close(fd);
  1096.         errno = saved_errno;
  1097.         return 0;
  1098.     }
  1099.  
  1100.     (void)close(fd);
  1101.  
  1102.     if
  1103.     (
  1104.         smagic == MIPSEBMAGIC
  1105.         ||
  1106.         smagic == MIPSELMAGIC
  1107.         ||
  1108.         smagic == SMIPSEBMAGIC
  1109.         ||
  1110.         smagic == SMIPSELMAGIC
  1111.         ||
  1112.         smagic == MIPSEBUMAGIC
  1113.         ||
  1114.         smagic == MIPSELUMAGIC
  1115.         ||
  1116.         smagic == MIPSEBMAGIC_2
  1117.         ||
  1118.         smagic == MIPSELMAGIC_2
  1119.         ||
  1120.         smagic == SMIPSEBMAGIC_2
  1121.         ||
  1122.         smagic == SMIPSELMAGIC_2
  1123.         ||
  1124.         smagic == MIPSEBMAGIC_3
  1125.         ||
  1126.         smagic == MIPSELMAGIC_3
  1127.         ||
  1128.         smagic == SMIPSEBMAGIC_3
  1129.         ||
  1130.         smagic == SMIPSELMAGIC_3
  1131.     )
  1132.     {
  1133.         errno = saved_errno;
  1134.         return 1;
  1135.     }
  1136.  
  1137.     if
  1138.     (
  1139.         ((unsigned char *)&smagic)[0] == '#'
  1140.         &&
  1141.         ((unsigned char *)&smagic)[1] == '!'
  1142.     )
  1143.     {
  1144.         errno = saved_errno;
  1145.         return 2;
  1146.     }
  1147.  
  1148.     errno = ENOEXEC;
  1149.  
  1150.     return 0;
  1151. }
  1152.  
  1153. int
  1154. interpreter_ok(filename)
  1155. char    *filename;
  1156. {
  1157.     int    fd;
  1158.     int    saved_errno;
  1159.     char    interpreter_data[64 + 1];
  1160.     char    *new_filename;
  1161.     char    *cp;
  1162.  
  1163.     saved_errno = errno;
  1164.  
  1165.     if ((fd = open(filename, O_RDONLY)) == -1)
  1166.         return 0;
  1167.  
  1168.     /*
  1169.      * Skip the magic number -- we know
  1170.      * it looks ok.
  1171.      */
  1172.     if (lseek(fd, 2, 0) == -1)
  1173.     {
  1174.         saved_errno = errno;
  1175.         (void)close(fd);
  1176.         errno = saved_errno;
  1177.         return 0;
  1178.     }
  1179.  
  1180.     bzero(&interpreter_data[0], sizeof(interpreter_data));
  1181.  
  1182.     if (read(fd, &interpreter_data[0], sizeof(interpreter_data) - 1) <= 0)
  1183.     {
  1184.         saved_errno = errno;
  1185.         (void)close(fd);
  1186.         errno = saved_errno;
  1187.         return 0;
  1188.     }
  1189.  
  1190.     (void)close(fd);
  1191.  
  1192.     /*
  1193.      * Skip leading white space.
  1194.      */
  1195.     for (new_filename = &interpreter_data[0]; *new_filename == ' ' || *new_filename == '\t'; new_filename++)
  1196.         ;
  1197.  
  1198.     /*
  1199.      * Terminate the filename with a '\0'.
  1200.      */
  1201.     for (cp = new_filename; *cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0'; cp++)
  1202.         ;
  1203.  
  1204.     *cp = '\0';
  1205.  
  1206.     if (magic_ok(new_filename) == 1)
  1207.     {
  1208.         errno = saved_errno;
  1209.         return 1;
  1210.     }
  1211.  
  1212.     errno = ENOEXEC;
  1213.  
  1214.     return 0;
  1215. }
  1216.  
  1217. int
  1218. get_interpreter_data(filename, interpreter_namep, interpreter_argp)
  1219. char    *filename;
  1220. char    **interpreter_namep;
  1221. char    **interpreter_argp;
  1222. {
  1223.     int        saved_errno;
  1224.     int        fd;
  1225.     static char    interpreter_data[64 + 1];
  1226.     char        *new_filename;
  1227.     char        *cp;
  1228.     int        savedc;
  1229.  
  1230.     saved_errno = errno;
  1231.  
  1232.     if ((fd = open(filename, O_RDONLY)) == -1)
  1233.     {
  1234.         (void)close(fd);
  1235.         errno = saved_errno;
  1236.         return -1;
  1237.     }
  1238.  
  1239.     bzero(&interpreter_data[0], sizeof(interpreter_data));
  1240.  
  1241.     if (read(fd, &interpreter_data[0], sizeof(interpreter_data) - 1) < 3)
  1242.     {
  1243.         (void)close(fd);
  1244.         errno = saved_errno;
  1245.         return -1;
  1246.     }
  1247.  
  1248.     (void)close(fd);
  1249.  
  1250.     errno = saved_errno;
  1251.  
  1252.     if
  1253.     (
  1254.         interpreter_data[0] != '#'
  1255.         ||
  1256.         interpreter_data[1] != '!'
  1257.     )
  1258.         return -1;
  1259.  
  1260.     /*
  1261.      * Skip leading white space.
  1262.      */
  1263.     for (new_filename = &interpreter_data[2]; *new_filename == ' ' || *new_filename == '\t'; new_filename++)
  1264.         ;
  1265.  
  1266.     *interpreter_namep = new_filename;
  1267.  
  1268.     /*
  1269.      * Terminate the filename with a '\0'.
  1270.      */
  1271.     for (cp = new_filename; *cp != ' ' && *cp != '\t' && *cp != '\n' && *cp != '\0'; cp++)
  1272.         ;
  1273.  
  1274.     savedc = *cp;
  1275.     *cp++ = '\0';
  1276.  
  1277.     if (savedc == '\n' || savedc == '\0')
  1278.         return 0;
  1279.  
  1280.     /*
  1281.      * Skip any further white space.
  1282.      */
  1283.     while (*cp == ' ' || *cp == '\t')
  1284.         cp++;
  1285.  
  1286.     if (*cp == '\n' || *cp == '\0')
  1287.         return 0;
  1288.  
  1289.     *interpreter_argp = cp;
  1290.  
  1291.     /*
  1292.      * Terminate the argument with a '\0'.
  1293.      */
  1294.     while (*cp != '\n' && *cp != '\0')
  1295.         cp++;
  1296.  
  1297.     *cp = '\0';
  1298.  
  1299.     return 0;
  1300. }
  1301.  
  1302. int
  1303. is_a_shared_library(filename)
  1304. char    *filename;
  1305. {
  1306.     /*
  1307.      * TODO: check for shared libraries.
  1308.      */
  1309.     return 0;
  1310. }
  1311.