UnivesalDisassembler(2003)

uda.cc

Go to the documentation of this file.
00001 // uda.cc
00002 //
00003 // uda - universal disassembler
00004 // Date: 2003-05-04
00005 //
00006 // Copyright (c) 2002-2003 Ales Smrcka 
00007 //
00008 // This program is licensed under GNU Library GPL. See the file COPYING.
00009 //
00010 // Main program.
00011 //
00012 
00013 #include <string>
00014 #include <iomanip>
00015 #include <iostream>
00016 #include <libgen.h>
00017 #include "shared.h"
00018 #include "plugins.h"
00019 #include "sections.h"
00020 #include "symtable.h"
00021 #include "instrset.h"
00022 #include "decoder.h"
00023 using namespace std;
00024 
00025 // Parse parameters
00026 int load_parameters(int &argc, char **&argv);
00027 
00028 Parameters params;
00029 Parameters *Params=&params;
00030 
00031 const char *defaultbasedir="/usr/share/uda/";
00032 string basedir;
00033 
00034 const char *par_binfile="-b";
00035 
00036 const char *sec_alldata="*data";
00037 const char *sec_allexec="*exec";
00038 const char *sec_all="*";
00039 
00040 extern const char *syntax;
00041 extern const char *options;
00042 typedef vector<string> str_list;
00043 
00044 //locates address
00045 void locate_address(BinaryFile &binaryfile, const string address);
00046 //prints all sections
00047 void print_sections(BinaryFile &binaryfile);
00048 //prints section's content
00049 void print_content(BinaryFile &binaryfile, const string section);
00050 //prints all symbols from executable
00051 void print_symbols(BinaryFile &binaryfile);
00052 //disassemble section
00053 void disassemble(BinaryFile &binaryfile, const string section, const string scanned);
00054 
00055 void set_base_dir(char *dir)
00056 {
00057     basedir = string(dirname(dir))+"/";
00058     if (!directory_exists(basedir+instrsetdirectory))
00059         if (directory_exists(defaultbasedir))
00060             basedir = defaultbasedir;
00061 }
00062 
00064 // M A I N
00065 int main(int argc, char *argv[])
00066 {
00067     if (sizeof(unsigned)<4)
00068     {
00069         cerr<<"This program must be compiled for min. 32bit architecture!\n";
00070         return 1;
00071     }
00072     set_base_dir(argv[0]);
00073     if (!load_parameters(argc, argv))
00074         return 1;
00075     //open plugins
00076     OpenPlugins();
00077     if (pdefined("--help"))
00078     {
00079         cout<<syntax;
00080         cout<<options;
00081         PluginsInfo();
00082         return 0;
00083     }
00084     //prepare binary file
00085     BinaryFile binaryfile(params[par_binfile]);
00086     decinfo.binfile=&binaryfile;
00087     //find appop plugin and load all sections
00088     if (binaryfile.Init())
00089     { // binary file loaded
00090         decinfo.onlyname = pdefined("--onlyname");
00091         decinfo.address = !pdefined("--noaddress");
00092         decinfo.hexdump = !pdefined("--nohexdump");
00093         decinfo.symbolic = !pdefined("--nosymbolic");
00094         try
00095         {
00096             //create symbols and load it from binary file
00097             symbols = new Symbols(binaryfile.bfdata);
00098             debug(":loading symbol table from binary file\n");
00099             symbols->Load();
00100             //load instruction set 
00101             instructionset.Load(params["-P"]);            
00102             if (pdefined("-m")) //load symbols from user symbol table
00103             {
00104                 debug(":loading symbol table from "<<params["-m"]<<endl);
00105                 symbols->Load(params["-m"].c_str());
00106             }
00107             bool symboldefined;
00108             if (pdefined("-start")) // new starting address
00109             {
00110                 decinfo.start=symbols->findaddress(params["-start"], symboldefined);
00111                 if (!symboldefined)
00112                     decinfo.start=hex2uint(params["-start"]);
00113             }
00114             if (pdefined("-stop")) // new stopping address
00115             {
00116                 decinfo.stop=symbols->findaddress(params["-stop"], symboldefined);
00117                 if (!symboldefined)
00118                     decinfo.stop=hex2uint(params["-stop"]);
00119             }
00120             else
00121             if (pdefined("-size")) // new stopping address (by size from start)
00122                 decinfo.size=number2uint(params["-size"]);
00123             if (pdefined("-p") || pdefined("--printsymbols")) //print all symbols
00124                 print_symbols(binaryfile);
00125             else
00126             if (pdefined("-c")) //print content of section
00127                 print_content(binaryfile, params["-c"]);
00128             else
00129             if (pdefined("--sections")) //print all sections' informations
00130                 print_sections(binaryfile);
00131             else
00132             if (pdefined("-l")) //locate address
00133                 locate_address(binaryfile, params["-l"]);
00134             else
00135             if (pdefined("-d")) //disassemble section
00136             
00137                 disassemble(binaryfile, params["-d"], params["-s"]);
00138             else
00139             if (pdefined("-f")) //print founded symbols
00140             {
00141                 decinfo.print=false;
00142                 disassemble(binaryfile, params["-f"], params["-s"]);
00143                 print_symbols(binaryfile);
00144             }
00145             else
00146                 disassemble(binaryfile, ".text", params["-s"]);
00147         }
00148         catch(Exception &exception)
00149         {
00150             delete symbols;
00151             exception.Print();
00152         }
00153     }
00154     else
00155         cerr<<"Can not open file "<<params[par_binfile]<<endl;
00156     ClosePlugins();
00157     debug(":Plugins::Close() ok\n");
00158     return 0;
00159 }
00160 // M A I N
00162 
00163 // Loads and process all parameters
00164 int load_parameters(int &argc, char **&argv)
00165 {
00166     int actarg=1;
00167     if (argc>actarg)
00168         if (argv[actarg][0]!='-')
00169             params[par_binfile]=argv[actarg++];
00170     while (argc>actarg)
00171         if (argv[actarg][0]=='-')
00172             if (argc>actarg+1)
00173                 if (string(argv[actarg])==par_binfile || argv[actarg+1][0]!='-')
00174                 {
00175                     params[argv[actarg]]=argv[actarg+1];
00176                     actarg+=2;
00177                 }
00178                 else
00179                     params[argv[actarg++]]="";
00180             else
00181                 params[argv[actarg++]]="";
00182         else
00183             params[par_binfile]=argv[actarg++];
00184     if ((!pdefined(par_binfile) || params[par_binfile]=="") && !pdefined("--help"))
00185     {
00186         cout<<syntax;
00187         return 0;
00188     }
00189     return 1;
00190 }
00191 
00192 str_list parse_sectionname(BinaryFile &binaryfile, const string section)
00193 {
00194     str_list sec;
00195     bool only_data = section==sec_alldata || section==sec_all;
00196     bool only_executable =  section==sec_allexec || section==sec_all;
00197     if (only_data || only_executable)
00198     {
00199         MSections::iterator i;
00200         for (i=binaryfile.sections.begin();i!=binaryfile.sections.end();i++)
00201             if ((i->second.data->executable && only_executable) || (!i->second.data->executable && only_data))
00202                 sec.push_back(i->second.data->name);
00203     }
00204     else
00205     {
00206         string s;
00207         const char *c=section.c_str();
00208         while (*c)
00209         {
00210             s="";
00211             while (*c && *c!=',')
00212                 s+=*c++;
00213             sec.push_back(s);
00214             if (*c)
00215                 c++;
00216         }
00217     }
00218     return sec;    
00219 }
00220 
00221 void print_sections_header()
00222 {
00223     cout<<"no.   section name        start       size (hex)  size (dec)  executable"<<endl;
00224 }
00225 
00226 void print_sections_info(unsigned n, const string name, Address start, unsigned size, bool executable)
00227 {
00228     cout<<"["<<setw(2)<<dec<<setfill('0')<<n<<"]  "<<name;
00229     int j=20-name.length();
00230     for (;j>0;j--)
00231         cout<<" ";
00232     cout<<"0x"<<setw(8)<<setfill('0')<<hex<<start<<
00233     "  0x"<<setw(8)<<setfill('0')<<hex<<size<<"  "<<
00234     setw(8)<<setfill(' ')<<dec<<size<<"        ";
00235     if (executable)
00236         cout<<"Y";
00237     else
00238         cout<<"N";
00239     cout<<endl;
00240 }
00241 
00242 //locates address
00243 void locate_address(BinaryFile &binaryfile, const string address)
00244 {
00245     MSections::iterator i;
00246     bool symboldefined;
00247     Address addr;
00248     // find as symbol
00249     addr=symbols->findaddress(address, symboldefined);
00250     // not found -> use as address
00251     if (!symboldefined)
00252         addr=hex2uint(address);
00253     int n=1;
00254     for (i=binaryfile.sections.begin();i!=binaryfile.sections.end();i++,n++)
00255         if (addr>=i->second.data->addr && addr<i->second.data->addr+i->second.data->size)
00256         {
00257             if (pdefined("-v"))
00258             {
00259                 cout<<"Symbol "<<address;
00260                 if (symboldefined)
00261                     cout<<"(0x"<<hex<<setw(8)<<setfill('0')<<addr<<")";
00262                 cout<<" belongs to the section "<<i->first<<endl<<"Section information:"<<endl;
00263                 print_sections_header();
00264                 print_sections_info(n, i->first, i->second.data->addr, i->second.data->size, i->second.data->executable);
00265             }
00266             else
00267                 cout<<i->first<<endl;
00268             break;
00269         }
00270 }
00271 
00272 //prints all sections
00273 void print_sections(BinaryFile &binaryfile)
00274 {
00275     MSections::iterator i;
00276     int n=1;
00277     print_sections_header();
00278     for (i=binaryfile.sections.begin();i!=binaryfile.sections.end();i++)
00279         print_sections_info(n++, i->first, i->second.data->addr, i->second.data->size, i->second.data->executable);
00280 }
00281 
00282 //prints section's content
00283 void print_content(BinaryFile &binaryfile, const string sec)
00284 {
00285     if (binaryfile.sections.find(sec)!=binaryfile.sections.end())
00286     {
00287         Section &section=binaryfile[sec];
00288         Address addr=section.data->addr;
00289         while (section.ValidAddress(addr))
00290             cout<<section[addr++];
00291     }
00292 }
00293 
00294 //prints all symbols from executable
00295 void print_symbols(BinaryFile &binaryfile)
00296 {
00297     typedef MSymbols::iterator it;
00298     for (it i=symbols->symbols.begin();i!=symbols->symbols.end();i++)
00299         cout<<"0x"<<hex<<i->first<<"=\""<<i->second<<"\";"<<endl;
00300 }
00301 
00302 //disassemble section
00303 void disasm_section(BinaryFile &binaryfile, const string section)
00304 {
00305     debug(":disassembling section "<<section<<endl);
00306     if (decinfo.print)
00307     {
00308         for (int i=0;i<78;i++)
00309             cout<<'#';
00310         cout<<endl<<"section "<<section<<":"<<endl;
00311     }
00312     decinfo.section = &binaryfile[section];
00313     decoder.Decode();
00314 }
00315 
00316 // disassemble section(s)
00317 void disassemble(BinaryFile &binaryfile, const string section, const string scanned)
00318 {
00319     str_list scan = parse_sectionname(binaryfile, scanned); // e.g. from "*exec" to (.text .init .plt)
00320     str_list s = parse_sectionname(binaryfile, section);
00321     str_list::iterator i;
00322     for (i=scan.begin();i!=scan.end();i++)
00323         binaryfile[*i]->scanaddress=true;
00324     for (i=s.begin();i!=s.end();i++)
00325         disasm_section(binaryfile, *i);
00326 }
00327 
00328 const char *syntax = "\
00329 Usage: uda binary [options]\n\
00330        uda --help\n";
00331 
00332 const char *options = "\
00333 Options:\n\
00334     -b binary       use this when you can't use binary as the first parameter\n\
00335     -m mapfile      use mapfile as an additional symbol table\n\
00336     -p              load symbols from binary file (if found\n\
00337                     corresponding plugin) and print them on standart output\n\
00338     -d section(s)   disassemble section(s)\n\
00339     -f section(s)   find all handled addresses and print them\n\
00340                     on standart output\n\
00341     -s section(s)   scan addresses as immediate data for theese sections\n\
00342     -l address, -l symbol\n\
00343                     print a section containing this address/symbol\n\
00344     -c section      print a content of section\n\
00345     --sections      print the sections informations\n\
00346     -start address, -start symbol\n\
00347                     start disassembling from this address\n\
00348     -stop address, -stop symbol\n\
00349                     stop disassembling at this address\n\
00350     -size number    disassemble this number of bytes\n\
00351     --noaddress     print disassembling info without addresses\n\
00352     --nohexdump     print disassembling info without hexdump\n\
00353     --nosymbolic    print disassembling info without symbolic instruction\n\
00354     --onlyname      in symbolic address print only symbolic name\n\
00355     -v              verbosely print the process information\n\
00356     --debug         print all debug informations\n\
00357     --help          print uda options and plugins' informations\n\
00358 sections could be:\n\
00359     section               section with name \"section\"\n\
00360     .fini,.init,.text     three sections (.fini, .init and .text)\n\
00361     *data                 all data sections\n\
00362     *exec                 all executable sections\n\
00363     *                     all sections\n";