home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gccfindhit-1.2-src.tgz / tar.out / contrib / GccFindHit / GccFindHit.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  7KB  |  300 lines

  1. /* GccFindHit V1.2, 30/12/95
  2. *
  3. *  The same than FindHit by Michael Sinz, but for GCC users
  4. *  Usage: GccFindHit <executable file> <list of offsets in hexadecimal>
  5. *  The file should have been linked with the '-g' flag passed to gcc
  6. *  to turn on debugging information (the 'stabs')
  7. *
  8. *  GccFindHit outputs the line numbers matching with the offsets given by
  9. *  Enforcer (or whatever). Currently, there is no need
  10. *  to provide the hunk number because it should always be zero.
  11. *
  12. *  Copyright (C) 1995 Daniel Verite -- daniel@brainstorm.eu.org
  13. *  This program is distributed under the General GNU Public License version 2
  14. *  See the file COPYING for information about the GPL
  15. *
  16. *  v1.2, 30/12/95
  17. *
  18. *    Daniel Verite, daniel@brainstorm.eu.org:
  19. *  o added handling of HUNK_NAME
  20. *  o fixed a small glitch in the strings seeks
  21. *
  22. *  v1.1, 28/09/95
  23. *
  24. *    Hans Verkuil, hans@wyst.hobby.nl:
  25. *  o GccFindHit no longer reads the strings into memory, but seek()s them
  26. *    instead, saving lots of memory.
  27. *  o added version string.
  28. *
  29. *  v1.0, 22/05/95
  30. *
  31. *    First release
  32. */
  33.  
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #include <fcntl.h>
  37. #include <unistd.h>
  38. #include <string.h>
  39.  
  40. #include "defs.h"
  41.  
  42. extern int errno;
  43.  
  44. int ExeFile,NbOffs;
  45. unsigned long *SearchOffs;
  46.  
  47. static const char version_id[] = "\000$VER: GccFindHit 1.2 (30.12.95)";
  48.  
  49. int Read4 (long *buf)
  50. {
  51.   if (read (ExeFile,buf,4)==4) {
  52.     *buf = GETLONG(*buf);
  53.     return 1;
  54.   }
  55.   else
  56.     return 0;
  57. }
  58.  
  59. struct Header *ReadHeader ()
  60. {
  61.   long nb,size;
  62.   struct Header *h;
  63.   int i;
  64.  
  65.   /* skip hunk names */
  66.   while (Read4 (&size) && size)
  67.     lseek (ExeFile, size<<2, SEEK_CUR);
  68.  
  69.   /* reads the number of hunks */
  70.   if (!Read4(&nb))
  71.     return NULL;
  72.   h = (struct Header*)malloc(sizeof(struct Header)+(nb-1)*sizeof(long));
  73.   if (!h)
  74.     return NULL;
  75.   h->nb_hunks = nb;
  76.   if (Read4 (&h->first) && Read4 (&h->last)) {
  77.     for (i=0; i<nb; i++)
  78.       if (!Read4 (&h->sizes[i])) {
  79.     free (h);
  80.     return NULL;
  81.       }
  82.   }
  83.   return h;
  84. } /* ReadHeader() */
  85.  
  86. int long_cmp (long *e1,long *e2)
  87. {
  88.   return (*e1)<(*e2);
  89. }
  90.  
  91. void SkipRelocation ()
  92. {
  93.   unsigned long no; /* number of offsets */
  94.   long h;  /* hunk number */
  95.   while (Read4 (&no) && no && Read4 (&h))
  96.     lseek (ExeFile, no<<2, SEEK_CUR);
  97. }
  98.  
  99. /* this function hasn't been tested; AFAIK, ld won't output short relocs,
  100.    so it's useless for now */
  101. void SkipShortRel ()
  102. {
  103.   unsigned long no;
  104.   short h;
  105.   while (Read4 (&no) && no && read (ExeFile, &h, sizeof h))
  106.     lseek (ExeFile, no<<1, SEEK_CUR);
  107. }
  108.  
  109. /* can be slow if I/O buffering doesn't do some read-ahead */
  110. void SkipSymbols ()
  111. {
  112.   long nl; /* name length in long words */
  113.   while (Read4 (&nl) && nl) {
  114.     /* skips the name + the value */
  115.     lseek (ExeFile, (nl+1)<<2, SEEK_CUR);
  116.   }
  117. }
  118.  
  119. /* skip hunks such as HUNK_NAME that have their size in the first long */
  120. void SkipHunk ()
  121. {
  122.   unsigned long size;
  123.   if (Read4 (&size))
  124.     lseek (ExeFile, size<<2, SEEK_CUR);
  125. }
  126.  
  127. char *get_string(long offset)
  128. {
  129.   static char buf[256];
  130.  
  131.   lseek(ExeFile, offset, SEEK_SET);
  132.   read(ExeFile, buf, 255);
  133.   buf[255] = 0;
  134.   return buf;
  135. }
  136.  
  137. void GetLines (long symsz, BSD_SYM *syms, long string_offset)
  138. {
  139.   long nbsyms = symsz / sizeof(BSD_SYM);
  140.   BSD_SYM *sym = syms;
  141.   unsigned char prev_type;
  142.   long srcname = 0, prev_src = 0;
  143.   unsigned short prev_line = 0;
  144.   unsigned long offs , prev_offs = -1UL;
  145.   int i;
  146.  
  147.   while (nbsyms--) {
  148.     switch (sym->type) {
  149.     case N_SO:
  150.     case N_SOL:
  151.       srcname = GETLONG (sym->strx);
  152.       break;
  153.     case N_SLINE:
  154.       offs = OFFSET_N_SLINE (GETLONG (sym->value));
  155.       for (i = 0; i < NbOffs; i++) {
  156.     if (SearchOffs[i] >= prev_offs && SearchOffs[i] < offs) {
  157.       printf ("%s: line %hd, offset 0x%lx\n",
  158.                   get_string(prev_src + string_offset), prev_line,
  159.           prev_offs);
  160.     }
  161.       }
  162.       prev_offs = offs;
  163.       prev_line = GETWORD (sym->desc);
  164.       prev_src = srcname;
  165.       break;
  166.     }
  167.     prev_type = sym->type;
  168.     sym++;
  169.   }
  170.   /* the last SLINE is a special case */
  171.   for (i = 0; i < NbOffs; i++) {
  172.     if (SearchOffs[i] == prev_offs) {
  173.       printf ("%s: line %hd, offset 0x%lx\n",
  174.               get_string(prev_src + string_offset), prev_line,
  175.           prev_offs);
  176.     }
  177.   }
  178. }
  179.  
  180. void HunkDebug (void)
  181. {
  182.   long hunksz, symsz, strsz;
  183.   struct bsd_header hdr;
  184.   long pos, init_pos = lseek (ExeFile, 0, SEEK_CUR);
  185.   char *syms;
  186.  
  187.   if (init_pos < 0)
  188.     return;
  189.   if (Read4(&hunksz) && read (ExeFile, &hdr, sizeof(hdr)) == sizeof(hdr)) {
  190.     if (GETLONG(hdr.magic)==ZMAGIC) {
  191.       /* seems to be gcc-compiled */
  192.       strsz = GETLONG (hdr.strsz);
  193.       symsz = GETLONG (hdr.symsz);
  194.       if (strsz + symsz != 0) {
  195.     syms = (char*)malloc (symsz);
  196.     if (syms) {
  197.       if (read (ExeFile, syms, symsz) == symsz) {
  198.         pos = lseek(ExeFile, strsz, SEEK_CUR);
  199.             if (pos > 0)
  200.           GetLines (symsz, (BSD_SYM*)syms, pos - strsz);
  201.       }
  202.       free (syms);
  203.     }
  204.       }
  205.     }
  206.   }
  207.   /* go to the end of the hunk whatever happened before */
  208.   lseek (ExeFile, init_pos+((hunksz+1)<<2), SEEK_SET);
  209. }
  210.  
  211. void DoHunks (struct Header *h)
  212. {
  213.   long hnum,size,nsec=0;
  214.   while (Read4 (&hnum)) {
  215.     switch (hnum) {
  216.     case HUNK_NAME:
  217.       SkipHunk ();
  218.       break;
  219.     case HUNK_CODE:
  220.     case HUNK_DATA:
  221.       if (Read4 (&size)) {
  222.     nsec++;
  223.     lseek (ExeFile, (size&0x3fffffff)<<2, SEEK_CUR);
  224.       }
  225.       break;
  226.     case HUNK_BSS:
  227.       nsec++;
  228.       Read4 (&size);
  229.     case HUNK_END:
  230.     case HUNK_BREAK:
  231.       break;
  232.     case HUNK_RELOC32:
  233.     case HUNK_RELOC16:
  234.     case HUNK_RELOC8:
  235.     case HUNK_DRELOC32:
  236.     case HUNK_DRELOC16:
  237.     case HUNK_DRELOC8:
  238.       SkipRelocation();
  239.       break;
  240.     case HUNK_RELOC32SHORT:
  241.       SkipShortRel ();
  242.       break;
  243.     case HUNK_SYMBOL:
  244.       SkipSymbols();
  245.       break;
  246.     case HUNK_DEBUG: /* here we are... */
  247.       HunkDebug ();
  248.       break;
  249.     default:
  250.       fprintf (stderr, "Unexpected hunk 0x%lx\n", hnum);
  251.       return;
  252.     }
  253.   }
  254. } /* DoHunks() */
  255.  
  256. void Out(int code)
  257. {
  258.   if (ExeFile>0) close (ExeFile);
  259.   if (SearchOffs) free (SearchOffs);
  260.   exit (code);
  261. }
  262.  
  263. int main(int argc,char **argv)
  264. {
  265.   long HunkNum;
  266.   struct Header *header=NULL;
  267.   int i;
  268.  
  269.   if (argc<3) {
  270.     fprintf (stderr,"Usage: %s <file> <hex offsets>\n",argv[0]);
  271.     Out (1);
  272.   }
  273.   ExeFile = open (argv[1], O_RDONLY);
  274.   if (ExeFile<0) {
  275.     fprintf (stderr,"can't open %s:%s\n", argv[1], strerror (errno));
  276.     Out (1);
  277.   }
  278.   NbOffs = argc-2;
  279.   SearchOffs = (long*)malloc (sizeof (long)*NbOffs);
  280.   if (!SearchOffs) {
  281.     fprintf (stderr,"No memory\n");
  282.     Out (1);
  283.   }
  284.   for (i=0; i<NbOffs; i++) {
  285.     if (sscanf (argv[i+2],"%lx",&SearchOffs[i])!=1) {
  286.       fprintf (stderr, "Operand %s is not an hex offset\n", argv[i+2]);
  287.       Out (1);
  288.     }
  289.   }
  290.   if (!Read4(&HunkNum) || HunkNum!=HUNK_HEADER || !(header=ReadHeader())) {
  291.     fprintf (stderr, "%s is not an amigaos executable\n", argv[1]);
  292.     Out (1);
  293.   }
  294.   DoHunks (header);
  295.   free (header);
  296.   Out (0);
  297.   return 0; /* another brick in the -Wall */
  298. } /* main() */
  299.  
  300.