home *** CD-ROM | disk | FTP | other *** search
/ Amiga GigaPD 3 / Amiga_GigaPD_v3_3of3.iso / netbsd / incoming / binpatch.array.c < prev    next >
C/C++ Source or Header  |  1993-06-25  |  9KB  |  357 lines

  1. #include <sys/types.h>
  2. #include <a.out.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <unistd.h>
  8.  
  9.  
  10. static char synusage[] = "
  11. NAME
  12. \t%s - Allows the patching of BSD binaries
  13. SYNOPSIS
  14. \t%s [-HELP] [-b|-w|-l] [-o offset] {-s symbol | -a address} [-r value] binary
  15. ";
  16. static char desusage[] = "
  17. DESCRIPTION
  18. \tAllows the patching of BSD binaries, for example,a distributed
  19. \tkernel. To go into details, read the source.
  20. OPTIONS
  21. \t-a patch variable by specifying address
  22. \t-b symbol or address to be patched is 1 byte in size
  23. \t-l symbol or address to be patched is 4 bytes in size(The default)
  24. \t-o offset to begin patching value relative to symbol or address,
  25. \t-r replace value, and print out previous value to stdout
  26. \t-s patch variable by specifying symbol name. Use '[]'
  27. \t   to specify the 'index'. If '-b, -w or -l' not specified
  28. \t   then index value is used like an offset. 
  29. \t-w symbol or address to be patched is 2 bytes in size
  30. EXAMPLES
  31. \tThis should print 100 (this is a nice reality check...)
  32. \t\tbinpatch -l -s _hz vmunix
  33. \tNow it gets more advanced, replace the value:
  34. \t\tbinpatch -l -s _scsi_debug -r 1 vmunix
  35. \tNow patch a variable at a given 'index' not offset,
  36. \t for a variable declared 'short view [10]', note the use of '':
  37. \t\tbinpatch -w -s '_view[4]' -r 0 a.out
  38. \tsame as
  39. \t\tbinpatch -w -o 8 -s _view -r 0 a.out
  40. \tAnother example of using []
  41. \t\tbinpatch -s '_view[4]' -r 0 a.out
  42. \tsame as
  43. \t\tbipatch -o 4 -s _view -r 0 a.out
  44. \tSo if kernel cannot finding your drives, you could enable all available
  45. \tdebugging options helping to shed light on that problem.
  46. \t\tbinpatch -l -s _scsi_debug -r 1 vmunix    scsi-level
  47. \t\tbinpatch -l -s _sddebug -r 1 vmunix    sd-level (disk-driver)
  48. \t\tbinpatch -l -s _acdebug -r 1 vmunix    autoconfig-level
  49. ";
  50.  
  51. extern char *optarg;
  52. extern int optind;
  53.  
  54. volatile void error (char *);
  55. static void Synopsis(char *program_name);
  56. static void Usage(char *program_name);
  57. static void FindOffset(char *symbol,u_long *index);
  58. /* The variables are so binpatch can be tested on itself */
  59. int test = 1;
  60. int testbss;
  61. char foo = 23;
  62. char  viewc[10] = {0,0,1,0,1,1,0,1,1,1};
  63. short views[10] = {0,0,1,0,1,1,0,1,1,1};
  64. long  viewl[10] = {0,0,1,0,1,1,0,1,1,1};
  65. /* End of test binpatch variables */
  66. int
  67. main(int argc, char *argv[])
  68. {
  69.   struct exec e;
  70.   int c;
  71.   u_long addr = 0, offset = 0;
  72.   u_long index = 0;/* Related to offset by: offset = index *size */
  73.   u_long replace = 0, do_replace = 0;
  74.   char *symbol = 0;
  75.   char size = 4;  /* default to long */
  76.   char size_opt = 0; /* Flag to say size option was set, used with index */
  77.   char *fname;
  78.   char *pgname = argv[0]; /* Program name */
  79.   int fd;
  80.   int type, off;
  81.   u_long  lval;
  82.   u_short sval;
  83.   u_char  cval;
  84.   
  85.  
  86.   while ((c = getopt (argc, argv, "H:a:bwlr:s:o:")) != EOF)
  87.     switch (c)
  88.       {
  89.       case 'H':
  90.         Usage(argv[0]);
  91.         break;
  92.       case 'a':
  93.     if (addr || symbol)
  94.       error ("only one address/symbol allowed");
  95.     if (! strncmp (optarg, "0x", 2))
  96.       sscanf (optarg, "%x", &addr);
  97.     else
  98.       addr = atoi (optarg);
  99.     if (! addr)
  100.       error ("invalid address");
  101.     break;
  102.  
  103.       case 'b':
  104.     size = 1;
  105.         size_opt = 1;
  106.     break;
  107.  
  108.       case 'w':
  109.     size = 2;
  110.         size_opt = 1;
  111.     break;
  112.  
  113.       case 'l':
  114.     size = 4;
  115.         size_opt = 1;
  116.     break;
  117.  
  118.       case 'r':
  119.     do_replace = 1;
  120.     if (! strncmp (optarg, "0x", 2))
  121.       sscanf (optarg, "%x", &replace);
  122.     else
  123.       replace = atoi (optarg);
  124.     break;
  125.  
  126.       case 's':
  127.     if (addr || symbol)
  128.       error ("only one address/symbol allowed");
  129.     symbol = optarg;
  130.     break;
  131.  
  132.       case 'o':
  133.     if (offset)
  134.       error ("only one offset allowed");
  135.     if (! strncmp (optarg, "0x", 2))
  136.       sscanf (optarg, "%x", &offset);
  137.     else
  138.           offset = atoi (optarg);
  139.         break;
  140.       }/* while switch() */
  141.   
  142.   if (argc > 1)
  143.   {
  144.     if (addr || symbol)
  145.     {
  146.       argv += optind;
  147.       argc -= optind;
  148.  
  149.       if (argc < 1)
  150.         error ("No file to patch.");
  151.  
  152.       fname = argv[0];
  153.       if ((fd = open (fname, 0)) < 0)
  154.         error ("Can't open file");
  155.  
  156.       if (read (fd, &e, sizeof (e)) != sizeof (e)
  157.         || N_BADMAG (e))
  158.         error ("Not a valid executable.");
  159.  
  160.       /* fake mid, so the N_ macros work on the amiga.. */
  161.       e.a_midmag |= 127 << 16;
  162.  
  163.       if (symbol)
  164.       {
  165.         struct nlist nl[2];
  166.         if (offset == 0)
  167.     {
  168.             FindOffset(symbol,&index);
  169.             if (size_opt)
  170.                offset = index*size;
  171.             else
  172.                offset = index; /* Treat index like an offset */
  173.     }
  174.         nl[0].n_un.n_name = symbol;
  175.         nl[1].n_un.n_name = 0;
  176.         if (nlist (fname, nl) != 0)
  177.     {
  178.           printf("Symbol is %s ",symbol);
  179.       error ("Symbol not found.");
  180.         }
  181.         addr = nl[0].n_value;
  182.         type = nl[0].n_type & N_TYPE;
  183.       }
  184.       else
  185.       {
  186.         type = N_UNDF;
  187.         if (addr >= N_TXTADDR(e) && addr < N_DATADDR(e))
  188.       type = N_TEXT;
  189.         else if (addr >= N_DATADDR(e) && addr < N_DATADDR(e) + e.a_data)
  190.       type = N_DATA;
  191.       }
  192.       addr += offset;
  193.  
  194.       /* if replace-mode, have to reopen the file for writing.
  195.          Can't do that from the beginning, or nlist() will not 
  196.          work (at least not under AmigaDOS) */
  197.       if (do_replace)
  198.       {
  199.         close (fd);
  200.         if ((fd = open (fname, 2)) == -1)
  201.       error ("Can't reopen file for writing.");
  202.       }
  203.  
  204.       if (type != N_TEXT && type != N_DATA)
  205.         error ("address/symbol is not in text or data section.");
  206.  
  207.       if (type == N_TEXT)
  208.         off = addr - N_TXTADDR(e) + N_TXTOFF(e);
  209.       else
  210.         off = addr - N_DATADDR(e) + N_DATOFF(e);
  211.  
  212.       if (lseek (fd, off, 0) == -1)
  213.         error ("lseek");
  214.  
  215.       /* not beautiful, but works on big and little endian machines */
  216.       switch (size)
  217.         {
  218.         case 1:
  219.           if (read (fd, &cval, 1) != 1)
  220.         error ("cread");
  221.           lval = cval;
  222.           break;
  223.  
  224.         case 2:
  225.           if (read (fd, &sval, 2) != 2)
  226.         error ("sread");
  227.           lval = sval;
  228.           break;
  229.  
  230.         case 4:
  231.           if (read (fd, &lval, 4) != 4)
  232.         error ("lread");
  233.           break;
  234.         }/* switch size */
  235.  
  236.       
  237.       if (symbol)
  238.         printf ("%s(0x%x): %d (0x%x)\n", symbol, addr, lval, lval);
  239.       else
  240.         printf ("0x%x: %d (0x%x)\n", addr, lval, lval);
  241.  
  242.       if (do_replace)
  243.       {
  244.         if (lseek (fd, off, 0) == -1)
  245.       error ("write-lseek");
  246.         switch (size)
  247.       {
  248.       case 1:
  249.         cval = replace;
  250.         if (cval != replace)
  251.           error ("byte-value overflow.");
  252.         if (write (fd, &cval, 1) != 1)
  253.           error ("cwrite");
  254.         break;
  255.  
  256.       case 2:
  257.         sval = replace;
  258.         if (sval != replace)
  259.           error ("word-value overflow.");
  260.         if (write (fd, &sval, 2) != 2)
  261.           error ("swrite");
  262.         break;
  263.  
  264.       case 4:
  265.         if (write (fd, &replace, 4) != 4)
  266.           error ("lwrite");
  267.         break;
  268.       }/* switch(size) */
  269.       }/* if (do_replace) */
  270.  
  271.       close (fd);
  272.     }/* if(addr || symbol ) */
  273.     else
  274.     {
  275.       error("Must specify either address or symbol.");
  276.     }
  277.   }/* if argc < 1 */
  278.   else
  279.   {
  280.     Synopsis(pgname);
  281.   }
  282.   return(0);
  283. }/* main () */
  284.  
  285.  
  286.  
  287. volatile void error (char *str)
  288. {
  289.   fprintf (stderr, "%s\n", str);
  290.   exit (1);
  291. }
  292.  
  293. /* Give user very short help to avoid scrolling screen much */
  294. static void Synopsis(char *pgname)
  295. {
  296.   fprintf(stdout,synusage,pgname,pgname);
  297. }
  298.  
  299.  
  300. static void Usage(char *pgname)
  301. {
  302.   Synopsis(pgname);
  303.   fprintf(stdout,desusage);
  304.   exit(0);
  305. }
  306.  
  307.  
  308. /* FindOffset() - Determine if there is an offset, (not index!)
  309.                  embedded in the symbol.
  310.                  If there is, return the offset, and 
  311.                  truncate symbol to exclude the [...].
  312.                  Example: If view is declared as short view[10],
  313.                           and we want to index the 3rd. element.
  314.                           which is offset = (3 -1)*sizeof(short)
  315.                  we would use view[4], which becomes view,4.
  316. */ 
  317. static void FindOffset(char *symbol,u_long *index)
  318. {
  319.   char *sb=strchr(symbol,'['); /* Start of '[' */
  320.   char *eb=strchr(symbol,']'); /* End of ']' */
  321.   short sz=strlen(symbol);   /* symbol size */
  322.   if (sb)
  323.   {
  324.     if (eb && (eb > sb))
  325.     {
  326.       if ((eb - symbol) == (sz - 1))
  327.       {
  328.         char *sindex; /* Start of index */
  329.         u_long newindex = 0;
  330.         /* In the future we could get fancy and parse the
  331.            sindex string for mathmatical expressions like:
  332.            (3 - 1)*2 = 4 from above example,
  333.            ugh forget I mentioned ot :-) !
  334.         */
  335.         sindex = sb + 1;
  336.         *eb = '\0';
  337.         newindex = (u_long)atoi(sindex);
  338.         if (*index == 0)
  339.         {
  340.           *index = newindex;
  341.           *sb = '\0'; /* Make _view[3] look like _view */
  342.         }
  343.         else
  344.           fprintf(stderr,"Error index can only be specified once!\n");
  345.       }
  346.       else
  347.       {
  348.         fprintf(stderr,"Error: Garbage trailing ']'\n");
  349.       } 
  350.     }
  351.     else
  352.     {
  353.        fprintf(stderr,"Error ']' in symbol before '[' !\n");
  354.     }
  355.   }/* if sb != 0 */
  356. }/* FindOffset */
  357.