www.delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1997/04/09/04:52:17

From: "Anthony.Appleyard" <MCLSSAA2 AT fs2 DOT mt DOT umist DOT ac DOT uk>
Organization: Materials Science Centre
To: DJGPP AT DELORIE DOT COM
Date: Wed, 9 Apr 1997 09:36:14 GMT-1
Subject: a program to find unused global symbols in a multi-file program
Reply-to: Anthony DOT Appleyard AT umist DOT ac DOT uk
Message-ID: <7969206701@fs2.mt.umist.ac.uk>

  I wrote this Gnu C program (WEEDSYMS.C) to find unused global symbols in a
multi-file djgpp program. To use it:-
  (1) Compile all the program's component files with `gcc ... -S' to produce
*.S files. (In the case of the text editor AAEMACS that I wrote, that will
produce files CC.S MAIN.S EM.S DISPLAY.S MACROS.S KEYF.S ZIP.S .)
  (2) EITHER call WEEDSYMS.EXE with all these *.S filenames as its args, e.g.
       WEEDSYMS CC.S MAIN.S EM.S DISPLAY.S MACROS.S KEYF.S ZIP.S
      OR type e.g.        WEEDSYMS @ARGFILE
    where the file ARGFILE contains all the *.S filenames, one per line.
  (3) The list of unused global symbols will now be on the file _.O (in
`mangled' form, if the *.S files were compiled by C++), one per line. If a
symbol started with an underline, that underline is printed out as space, to
produce the correct input form for the demangler CXXFILT.
  -------------------------------------------------------
    It will not find unused inlined functions (unless you un-inline them by
inserting or #include'ing `#define inline' at the top of each source file).
    It will not output line numbers correctly unless the *.S files were
compiled with the -g option.
  -------------------------------------------------------
#include<stdio.h>
#include<string.h>
#include<std.h>
#include<sys/stat.h>
#define uns unsigned
/*-----*//* the args should be names of *.S files created by `djgpp -S' */
int main(int nargs,char**arg){
FILE*F; int i,j,k,l,m,n=0; uns short*lnaddr=0;
uns char*sw,**sym; char L[1024],*arg0,*unused,*s;
if(nargs==2) if(arg[1][0]=='@') {       /* if the args are on a file */
    struct stat B;
    arg0=arg[0];
    if(stat(sw=arg[1]+1,&B)) {printf("I can't find file `%s'\n",sw); return 1;}
    F=fopen(sw,"r");    /* open the file */
    sw=(char*)malloc((j=B.st_size)+1);  /* make array to hold whole file */
    fread(sw,1,j,F);    /* read file */
    fclose(F);
    sw[j]=0;
    for(k=i=0;i<j;i++) if(sw[i]=='\n') {sw[i]=0; k++;}  /* there are k args */
    arg=(char**)malloc(k*sizeof(char*));
    arg[0]=arg0;
    k=1;        /* set up array arg pointing to the args */
    if(sw[0]) arg[k++]=sw;
    for(i=0;i<j;i++) if(!sw[i]) if(sw[i+1]) arg[k++]=sw+i+1; nargs=k;}
puts("READING DEFINED SYMBOLS");
sym=(uns char**)(malloc(0x10000)); /* allow <= 0x10000 global symbols */
for(m=1;m<nargs;m++) {  /* loop for each file */
    F=fopen(arg[m],"r"); puts(arg[m]);
    while(fgets(L,1024,F),!feof(F)) {
        if(!strncmp(L,"\011.def\011",6)) {      /* look for line number */
            s=strstr(L,".line\011");
            if(s) if(lnaddr) {*lnaddr=atoi(s+6); lnaddr=0;}
            continue;}
        if(!strncmp(L,".globl ",7)) {   /* global symbol declaration found */
            if((j=strlen(L))) if(L[j-1]=='\n') L[--j]=0;        /* remove \n */
            sym[n++]=(char*)malloc(j+4);        /* list the symbol */
            if(j-=7,j>1) strcpy(sym[n-1],L+7); else sym[n-1][0]=0;
            sw=sym[n-1]+j;
            sw[1]=m;    /* it is in the mth file */
            sw[2]=sw[3]=0;      /* for the line number */
            lnaddr=(uns short*)&sw[2];}}
    fclose(F);}
for(k=i=n-1;k;i--) for(k=j=0;j<i;j++) if(strcmp(sym[j],sym[j+1])>0) {
        sw=sym[j+1]; sym[j+1]=sym[j]; sym[j]=sw; k=1;}  /* bubble sort */
for(i=n-1;i>0;i--) if(!strcmp(sym[i-1],sym[i])) sym[i][0]=0;
/* find duplicates */
unused=(char*)malloc(n);
for(i=0;i<n;i++) unused[i]=1;
puts("LOOKING FOR USES OF SYMBOLS");
for(m=1;m<nargs;m++) {  /* for each *.S file */
    F=fopen(arg[m],"r");
    puts(arg[m]);       /* tell him how far I've got */
    while(fgets(L,1024,F),!feof(F))     /* for each line */
     if(L[0]==9)        /* ignore label & .globl lines */
      if(strncmp(L+1,".def",4)) {       /* ignore .def lines */
        j=strlen(L);
        for(i=0;i<j;i++) if((k=L[i])!='$') if(k!='_') if(k<'0'?:k>'9')
            if(k<'0'?:k>'9') if(k<'A'?:k>'Z') if(k<'a'?:k>'z') L[i]=0;
/* replace all non-symbol chars by ascii 0 */
        for(i=0;i<j;i++) if(L[i]) if(L[i]!='$') {
/* look for symbols, ignore leading $ */
            k=strlen(L+i);
            if(L[i]=='_') for(l=0;l<n;l++) if(*sym[l]) if(!strcmp(L+i,sym[l])) {
                unused[l]=0; break;}    /* if in symbol list, mark as used */
            i+=k;}}
    fclose(F);}
F=fopen("_.o","w");
fprintf(F,"SYMBOLS DEFINED BUT NOT USED\n");
for(i=0;i<n;i++) if(unused[i]) if((sw=sym[i])[0]) {
    if(*sw=='_') fprintf(F," %s",sw+1); else fprintf(F,"%s",sw);
Y:  sw+=strlen(sw);
    fprintf(F,", in %s, line %1d of source",arg[sw[1]],*(uns short*)(sw+2));
    if(i+1<n) if(!sym[i+1][0]) {
        sw=sym[++i]; sw[0]='_'; fprintf(F,"\n           "); goto Y;}
    fprintf(F,"\n");}
fclose(F); free(sym); free(unused); return 0;}

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019