main.c

Go to the documentation of this file.
00001 /***************************************************************************/
00007 /*
00008  * DeadStrip
00009  * 
00010  * Created by Dorian Weber.
00011  * 
00012  * No warranties given, not even implied ones, use this tool at your own risk.
00013  *
00014  */
00015 
00016 #include <stdio.h>
00017 #include <stdlib.h>
00018 #include <string.h>
00019 
00020 #include "list.h"
00021 #include "objectFile.h"
00022 
00023 /* modify those, if you're migrating onto a new system */
00024 #define SO_LINKER   "ld"         
00025 #define SO_DUMPER   "objdump"    
00026 #define SO_DPARAM   "-rh"        
00027 #define SO_DFILE    ".-"         
00028 #define SO_REMOVER  "objcopy"    
00029 #define SO_RRMV     "-R"         
00030 #define SO_PIPE     ">"          
00032 static const char* hlp = "Usage: deadstrip [options] file...\n"
00033     "Options:\n"
00034     "  --help                display this HELP\n"
00035     "  --dcmd                Dumps the ComManD line\n"
00036     "  --ddis                Dumps DIScarted sections\n"
00037     "  --duse                Dumps USEd sections\n"
00038     "  --dmap                Dump the dependency MAP\n"
00039     "  --linker <filename>   use alternative LINKER (default: "SO_LINKER")\n"
00040     "  --dnrm                Do Not ReMove any sections\n"
00041     "  --save <item>         SAVE an item and its dependencies\n"
00042     "    > just pass the decorated variable/function name, not the section\n"
00043     "    > the main function gets saved by default\n"
00044     "\n"
00045     "Version 1.1\n"
00046     "Last compiled on "__DATE__".\n";
00047 
00048 #define SO_DUMP_CMDLN      1
00049 #define SO_DUMP_DISCARTED  2
00050 #define SO_DUMP_USED       4
00051 #define SO_OBJECTS         8
00052 #define SO_HELP           16
00053 #define SO_DUMP_MAP       32
00054 #define SO_DNRM           64
00055 #define SO_COLLECT       128
00056 
00057 /* SC == StreamCopy, ~StarCraft */
00058 #define SO_SC(tar, txt) \
00059 {\
00060   const char* data = txt;\
00061   while ((*tar = *data++))\
00062     ++tar;\
00063 }
00064 
00065 int main(int argc, const char* argv[])
00066 {
00067     const char* linker = SO_LINKER, dumper[] = SO_DUMPER " " SO_DPARAM;
00068     char** largs = (char**) malloc(sizeof(char*) * argc);
00069     int i = argc, li = 0, llen = strlen(linker) + 2, olen = sizeof(dumper)
00070         + sizeof(SO_PIPE SO_DFILE), len;
00071     unsigned long flags = 0;
00072     list *lObject = newList(), *lSeed = newList();
00073     
00074     
00075     /* add main procedure as seed for the graph coloring algorithm */
00076     listAdd(lSeed, "main");
00077     
00078     
00079     /* extract infos */
00080     while (--i > 0)
00081     {
00082         ++argv;
00083         if (**argv == '-')
00084         {
00085             flags &= ~SO_COLLECT;
00086             if (argv[0][1] == '-')
00087             {
00088                 if (!strcmp(*argv, "--save"))
00089                 {
00090                     ++argv;
00091                     
00092                     if (--i)
00093                         listAdd(lSeed, *argv);
00094                     
00095                     continue;
00096                 }
00097                 else if (!strcmp(*argv, "--help"))
00098                 {
00099                     flags |= SO_HELP;
00100                     continue;
00101                 }
00102                 else if (!strcmp(*argv, "--dcmd"))
00103                 {
00104                     flags |= SO_DUMP_CMDLN;
00105                     continue;
00106                 }
00107                 else if (!strcmp(*argv, "--ddis"))
00108                 {
00109                     flags |= SO_DUMP_DISCARTED;
00110                     continue;
00111                 }
00112                 else if (!strcmp(*argv, "--duse"))
00113                 {
00114                     flags |= SO_DUMP_USED;
00115                     continue;
00116                 }
00117                 else if (!strcmp(*argv, "--dmap"))
00118                 {
00119                     flags |= SO_DUMP_MAP;
00120                     continue;
00121                 }
00122                 else if (!strcmp(*argv, "--linker"))
00123                 {
00124                     ++argv;
00125                     if (--i)
00126                     {
00127                         llen += strlen(*argv) - strlen(linker);
00128                         linker = *argv;
00129                     }
00130                     continue;
00131                 }
00132                 else if (!strcmp(*argv, "--dnrm"))
00133                 {
00134                     flags |= SO_DNRM;
00135                     continue;
00136                 }
00137             }
00138             else if (!strncmp(*argv, "-o", sizeof("-o") - 1))
00139             {
00140                 flags |= SO_COLLECT | SO_OBJECTS;
00141                 
00142                 
00143                 /* command line looks like -o Executable */
00144                 if (!argv[0][sizeof("-o") - 1])
00145                 {
00146                     /* collect linker arguments */
00147                     llen += sizeof("-o");
00148                     largs[li++] = (char*) *argv;
00149                     continue;
00150                 }
00151             }
00152         }
00153 
00154         len = strlen(*argv) + 1;
00155         
00156         
00157         /* collect objectfiles */
00158         if (flags & SO_COLLECT)
00159         {
00160             listAdd(lObject, objectFileCreate(*argv));
00161             olen += len;
00162         }
00163         
00164         /* collect linker arguments */
00165         llen += len;
00166         largs[li++] = (char*) *argv;
00167     }
00168 
00169     argv -= argc - 1;
00170     largs[li] = 0;
00171     
00172     if (flags & SO_HELP)
00173         printf(hlp);
00174     
00175     
00176     /* perform analysis */
00177     if (flags & SO_OBJECTS)
00178     {
00179         /* the first object file is always the exe, so we skip that */
00180         listStart(lObject);
00181         listNext(lObject);
00182         olen -= strlen(objectFileGetName((objectFile*) listGet(lObject))) + 1;
00183         listRemove(lObject);
00184         
00185         
00186         /* command is: link an executable using no object files */
00187         if (listIsEmpty(lObject))
00188         {
00189             fprintf(stderr, "ERROR: You can't link an executable without "
00190                 "providing object files.");
00191             return -1;
00192         }
00193         
00194         /* collect interesting sections */
00195         
00196         /* generate objdump */
00197         {
00198             char* cmdLn = (char*) malloc(sizeof(char) * olen);
00199             
00200             SO_SC(cmdLn, dumper);
00201             SO_SC(cmdLn, " ");
00202 
00203             listStart(lObject);
00204             while (listNext(lObject))
00205             {
00206                 SO_SC(cmdLn, objectFileGetName((objectFile*)listGet(lObject)));
00207                 SO_SC(cmdLn, " ");
00208             }
00209             
00210             SO_SC(cmdLn, SO_PIPE SO_DFILE);
00211             cmdLn -= olen - 1;
00212             
00213             system(cmdLn);
00214             free(cmdLn);
00215         }
00216         
00217         /* process */
00218         {
00219             FILE* objDump = fopen(SO_DFILE, "r");
00220             
00221             if (objDump)
00222             {
00223                 
00224                 /* read all the sections from the file */
00225                 listStart(lObject);
00226                 while (listNext(lObject))
00227                 {
00228                     objectFile* obj = (objectFile*) listGet(lObject);
00229                     objectFileCollect(obj, objDump);
00230                 }
00231                 
00232                 /* compute the dependency graph */
00233                 rewind(objDump);
00234                 objectFileCompute(lObject, objDump);
00235                 
00236                 /* colorize all seeds */
00237                 listStart(lSeed);
00238                 while (listNext(lSeed))
00239                     objectFileColorize((const char*) listGet(lSeed), 1);
00240                 
00241                 fclose(objDump);
00242                 remove(SO_DFILE);
00243             }
00244             else
00245                 fprintf(stderr, "ERROR: Couldn't compute dependency graph, because "
00246                     "dumpfile could not be opened.\n");
00247         }
00248         
00249         /* now remove unused sections */
00250         if (!(flags & SO_DNRM))
00251         {
00252             char* cmdLn = 0;
00253             
00254             listStart(lObject);
00255             while (listNext(lObject))
00256             {
00257                 objectFile* obj = (objectFile*) listGet(lObject);
00258                 const char* file = objectFileGetName(obj);
00259                 unsigned long size = sizeof(SO_REMOVER " ") + strlen(file);
00260                 list* nonDepends = (list*) objectFileGetUnused(obj);
00261                 
00262                 if (listIsEmpty(nonDepends))
00263                     continue;
00264                 
00265                 /* it's safer to calculate the size first */
00266                 listStart(nonDepends);
00267                 while (listNext(nonDepends))
00268                     size += sizeof(SO_RRMV " ") + strlen((char*) listGet(nonDepends));
00269                 
00270                 cmdLn = (char*) realloc(cmdLn, size);
00271                 SO_SC(cmdLn, SO_REMOVER " ");
00272 
00273                 listStart(nonDepends);
00274                 while (listNext(nonDepends))
00275                 {
00276                     SO_SC(cmdLn, SO_RRMV " ");
00277                     SO_SC(cmdLn, (char*)listGet(nonDepends));
00278                     SO_SC(cmdLn, " ");
00279                 }
00280                 SO_SC(cmdLn, file);
00281                 cmdLn -= size - 1;
00282                 
00283                 system(cmdLn);
00284                 deleteList(nonDepends);
00285             }
00286             
00287             free(cmdLn);
00288         }
00289         
00290         
00291         /* call linker */
00292         {
00293             char* cmdLn = (char*) malloc(sizeof(char) * llen);
00294             
00295             SO_SC(cmdLn, linker);
00296             SO_SC(cmdLn, " ");
00297 
00298             i = 0;
00299             while (i < li)
00300             {
00301                 SO_SC(cmdLn, largs[i]);
00302                 SO_SC(cmdLn, " ");
00303                 ++i;
00304             }
00305             cmdLn -= llen - 1;
00306             
00307             system(cmdLn);
00308             free(cmdLn);
00309         }
00310     }
00311     else if (!(flags & SO_HELP))
00312         printf(hlp);
00313     
00314     
00315     /* dump command line */
00316     if (flags & SO_DUMP_CMDLN)
00317     {
00318         printf("\nCOMMAND LINE:\n%s ", *argv++);
00319         while (--argc)
00320             printf("%s ", *argv++);
00321         printf("\n");
00322     }
00323     
00324     if (flags & SO_OBJECTS)
00325     {
00326         /* dump generated dependency graph */
00327         if (flags & SO_DUMP_MAP)
00328             objectFileDumpMap(lObject);
00329         
00330         
00331         /* dump used sections */
00332         if (flags & SO_DUMP_USED)
00333             objectFileDumpUsed(lObject);
00334         
00335         
00336         /* dump unused sections */
00337         if (flags & SO_DUMP_DISCARTED)
00338             objectFileDumpUnused(lObject);
00339     }
00340     
00341     /* just to be clean, although not really necessary */
00342     free(largs);
00343     deleteList(lObject);
00344     deleteList(lSeed);
00345     
00346     return 0;
00347 }

Generated on Fri Jun 5 15:31:57 2009 for DeadStrip Utility by  doxygen 1.5.8