FuncNodes.cpp

Go to the documentation of this file.
00001 /*
00002  *      FuncNodes.cpp -
00003  *
00004  *  Copyright (C) 2002-2003 The Pentagram Team
00005  *
00006  *  This program is free software; you can redistribute it and/or modify
00007  *  it under the terms of the GNU General Public License as published by
00008  *  the Free Software Foundation; either version 2 of the License, or
00009  *  (at your option) any later version.
00010  *
00011  *  This program is distributed in the hope that it will be useful,
00012  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  *  GNU General Public License for more details.
00015  *
00016  *  You should have received a copy of the GNU General Public License
00017  *  along with this program; if not, write to the Free Software
00018  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00019  */
00020 
00021 #include "pent_include.h"
00022 
00023 #include "FuncNodes.h"
00024 #include "Folder.h"
00025 #include "VarNodes.h"
00026 
00027 #include <deque>
00028 using   std::deque;
00029 
00030 /****************************************************************************
00031         FuncMutatorNode
00032  ****************************************************************************/
00033 
00034 void FuncMutatorNode::print_unk(Console &o, const uint32 isize, const bool comment) const
00035 {
00036         /* if we're in a comment, then we're actually going to output, else we silently
00037                 do nothing. This is to handle the cases where we don't want this data
00038                 such as in non-debugging situations */
00039         if(!comment && mtype!=SUSPEND) return;
00040         
00041         assert(rtype().type()==Type::T_INVALID);
00042         switch(mtype)
00043         {
00044                 case RET:       CANT_HAPPEN(); break;
00045                 case INIT:      CANT_HAPPEN(); break;
00046                 case LINE_NUMBER:
00047                         Node::print_linenum_unk(o, isize);
00048                         #if 0
00049                         o.Printf(" /* Line No: %d */ ", _linenum);
00050                         #else
00051                         o.Printf("/*%d*/", _linenum);
00052                         #endif
00053                         break;
00054                 case SYMBOL_INFO:
00055                         Node::print_linenum_unk(o, isize);
00056                         o.Printf("symbol_info_NOPRINT(0x%04X, \"%s\")", _symboloffset, _classname.c_str());
00057                         break;
00058                 case SUSPEND:
00059                         o.Printf("suspend");
00060                         break;
00061                 case END:       CANT_HAPPEN(); break;
00062                 default: assert(print_assert(this)); // can't happen
00063         }
00064 }
00065 
00066 void FuncMutatorNode::print_asm(Console &o) const
00067 {
00068         assert(rtype().type()==Type::T_INVALID);
00069 
00070         Node::print_linenum_asm(o);
00071         Node::print_asm(o);
00072         
00073         switch(mtype)
00074         {
00075                 case RET:         print_assert(this); CANT_HAPPEN(); break;
00076                 case INIT:        print_assert(this); CANT_HAPPEN(); break;
00077                 case LINE_NUMBER: o.Printf("line number\t%i (%04Xh)", _linenum, _linenum); break;
00078                 case SYMBOL_INFO: o.Printf("symbol info\toffset %04Xh = \"%s\"", _symboloffset, _classname.c_str()); break;
00079                 case SUSPEND:     o.Printf("suspend"); break;
00080                 case END:         CANT_HAPPEN(); break;
00081                 default: assert(print_assert(this)); // can't happen
00082         }
00083 }
00084 
00085 void FuncMutatorNode::print_bin(ODequeDataSource &o) const
00086 {
00087         assert(rtype().type()==Type::T_INVALID);
00088         Node::print_linenum_bin(o);
00089         switch(mtype)
00090         {
00091                 case RET:                       CANT_HAPPEN(); break;
00092                 case INIT:                      CANT_HAPPEN(); break;
00093                 case LINE_NUMBER: o.write1(0x5B); o.write2(_linenum); break;
00094                 case SYMBOL_INFO: o.write1(0x5C); o.write2(_symboloffset - _offset - 3); o.write(_classname.c_str(), _classname.size(), 9); break;
00095                 case SUSPEND:     o.write1(0x53); break;
00096                 case END:                       CANT_HAPPEN(); break;
00097                 default: assert(print_assert(this)); // can't happen
00098         }
00099 }
00100 
00101 bool FuncMutatorNode::fold(DCUnit *unit, std::deque<Node *> &nodes)
00102 {
00103         fold_linenum(nodes);
00104         
00105         if(mtype==SYMBOL_INFO)
00106         {
00107                 unit->setDebugOffset(_symboloffset);
00108                 unit->setClassName(_classname);
00109         }
00110         else if(mtype==END)
00111         {
00112                 // got to do a bit of juggling...
00113                 // ... remove ourselves from the back...
00114                 //assert((nodes.size()>0 && nodes.back()->opcode()==0x7A) || print_assert(this, unit));
00115                 //Node *n = nodes.back();
00116                 //nodes.pop_back();
00117                 //assert(n==this);
00118                 // ... grab the function node...
00119                 assert((nodes.size()>0 && nodes.back()->opcode()==0xFFFF) || print_assert(this, unit));
00120                 DCFuncNode *funcnode=static_cast<DCFuncNode *>(nodes.back());
00121                 funcnode->addEnd(this);
00122                 // ... add ourselves...
00123                 //nodes.push_back(this);
00124                 // ... call the func node's fold with the appriprate parameters...
00125                 //funcnode->fold(unit, nodes);
00126                 return false;
00127         }
00128         
00129         return true;
00130 }
00131 
00132 /****************************************************************************
00133         DCFuncNode
00134  ****************************************************************************/
00135 #define DEBUG_COMMENTS
00136 
00137 void DCFuncNode::print_unk_funcheader(Console &o, const uint32 isize) const
00138 {
00139         // do the obvious and spit out 'process'
00140         // for obvious reason's we're just assuming if a function has a 'process exclude'
00141         // op at the beginning, it's... a process!
00142         indent(o, isize);
00143         if(has_procexclude)
00144                 o.Printf("process ");
00145 
00146         o.Putchar('\n');
00147 }
00148 
00149 void DCFuncNode::print_unk(Console &o, const uint32 isize) const
00150 {
00151         #ifdef DEBUG_COMMENTS
00152         indent(o, isize); o.Print("/*"); // prelude
00153 
00154         // 'init'
00155         indent(o, 1);
00156         o.Printf("Function Start Offset:\t0x%04X\n", func_start_offset);
00157         indent(o, isize+1);
00158         o.Printf("Locals Datasize:\t0x%02X\n", locals_datasize);
00159         // 'set info'
00160         indent(o, isize+1);
00161         o.Printf("Process Type:\t\t0x%04X", process_type);
00162 
00163         assert(debug_thisp==true);      
00164         //indent(o, isize+1);
00165         //setinfonode->print_unk(o, isize+1, true);
00166         
00167         indent(o, 1); o.Print("*/\n"); // postfix
00168         #endif
00169         
00170         //indent(o, isize);
00171         //procexcludenode->print_unk(o, isize);
00172         //o.Putchar('\n');
00173 
00174         for(std::deque<Node *>::const_iterator i=funcnodes.begin(); i!=funcnodes.end(); ++i)
00175         {
00176                 indent(o, isize);
00177                 (*i)->print_unk(o, isize);
00178                 o.Putchar('\n');
00179         }
00180 
00181         assert(debug_ret_offset!=0); // 'ret'
00182         assert(debug_end_offset!=0); // 'end'
00183 
00184         #if 0 // not much use until we've got something to stuff at the end of the function
00185         //#ifdef DEBUG_COMMENTS
00186         indent(o, isize); o.Print("/*"); // prelude
00187 
00188         //indent(o, 1);
00189         //retnode->print_unk(o, isize+1, true);
00190         //o.Putchar('\n');
00191         
00192         //indent(o, isize+1);
00193         //endnode->print_unk(o, isize+1, true);
00194         
00195         indent(o, 1); o.Print("*/\n"); // postfix
00196         #endif
00197 }
00198 
00199 void DCFuncNode::print_asm(Console &o) const
00200 {
00201         // 'init'
00202         print_asm_header(o, func_start_offset, 0x5A);
00203         o.Printf("init\t\t%02X\n", locals_datasize);
00204         
00205         setinfonode->print_asm(o);
00206         o.Putchar('\n');
00207         
00208         // 'process exclude'
00209         print_asm_header(o, debug_procexclude_offset, 0x78);
00210         o.Printf("process exclude\n");
00211         //procexcludenode->print_asm(o);
00212         //o.Putchar('\n');
00213         
00214         for(std::deque<Node *>::const_iterator i=funcnodes.begin(); i!=funcnodes.end(); ++i)
00215         {
00216                 (*i)->print_asm(o);
00217                 o.Putchar('\n');
00218         }
00219         
00220         // 'ret'
00221         print_asm_header(o, debug_ret_offset, 0x50);
00222         o.Printf("ret\n");
00223         
00224         // 'end'
00225         print_asm_header(o, debug_end_offset, 0x7A);
00226         o.Printf("end\n");
00227 }
00228 
00229 void DCFuncNode::print_bin(ODequeDataSource &o) const
00230 {
00231         // 'init'
00232         print_mac_header(con, func_start_offset, 0x5A);
00233         o.write1(0x5A);
00234         o.write1(locals_datasize);
00235         
00236         assert(setinfonode!=0);
00237         setinfonode->print_mac(con);
00238         setinfonode->print_bin(o);
00239         
00240         // 'process exclude'
00241         print_mac_header(con, debug_procexclude_offset, 0x78);
00242         o.write1(0x78);
00243         //assert(procexcludenode!=0);
00244         //procexcludenode->print_mac(con);
00245         //procexcludenode->print_bin(o);
00246         
00247         for(std::deque<Node *>::const_iterator i=funcnodes.begin(); i!=funcnodes.end(); ++i)
00248         {
00249                 o.clear();
00250                 (*i)->print_mac(con);
00251                 (*i)->print_bin(o);
00252                 // FIXME: The following is a bit of a hack, just so we get some 'real' output
00253                 for(std::deque<char>::const_iterator i=o.buf().begin(); i!=o.buf().end(); ++i)
00254                         con.Printf("%02X ", static_cast<uint8>(*i));
00255                 con.Putchar('\n');
00256         }
00257         
00258         // 'ret'
00259         print_mac_header(con, debug_ret_offset, 0x50);
00260         o.write1(0x50);
00261 
00262         // 'end'
00263         print_mac_header(con, debug_ret_offset, 0x7A);
00264         o.write1(0x7A);
00265 }
00266 
00267 bool DCFuncNode::fold(DCUnit *unit, std::deque<Node *> &nodes)
00268 {
00269         assert(nodes.size()>0);
00270         
00271         // we get our 'end' later...
00272         
00273         // ... get our 'ret'
00274         fold_ret(unit, nodes);
00275 
00276         // while we haven't gotten init
00277         while(nodes.size() && !acceptOp(nodes.back()->opcode(), 0x78))
00278         {
00279                 /*switch(nodes.back()->opcode())
00280                 {
00281                         case 0x5A:
00282                                 assert(initnode==0);
00283                                 initnode = nodes.back();
00284                                 read_last=true;
00285                                 break;
00286                         default:*/
00287                                 funcnodes.push_front(nodes.back());
00288                 //}
00289                 nodes.pop_back();
00290         }
00291 
00292         // ... and our 'process exclude'
00293         fold_procexclude(unit, nodes);
00294 
00295         // ... and our 'set info'
00296         fold_setinfo(unit, nodes);
00297 
00298         // ... and our 'init'
00299         fold_init(unit, nodes);
00300         
00301         // FIXME: This will obviously be false when we're finally implementing
00302         // inline functions.
00303         assert((nodes.size()==0) || print_assert(0, unit));
00304         
00305         return true;
00306 }
00307 
00308 void DCFuncNode::fold_init(DCUnit * /*unit*/, std::deque<Node *> &nodes)
00309 {
00310         assert(nodes.size() && nodes.back()->opcode()==0x5A);
00311         FuncMutatorNode *initnode = static_cast<FuncMutatorNode *>(nodes.back());
00312         nodes.pop_back();
00313         
00314         locals_datasize = initnode->a_initsize();
00315         func_start_offset = initnode->offset();
00316         
00317         FORGET_OBJECT(initnode);
00318 }
00319 
00320 void DCFuncNode::fold_ret(DCUnit * /*unit*/, std::deque<Node *> &nodes)
00321 {
00322         assert(nodes.size() && nodes.back()->opcode()==0x50);
00323         FuncMutatorNode *retnode = static_cast<FuncMutatorNode *>(nodes.back());
00324         nodes.pop_back();
00325 
00326         debug_ret_offset = retnode->offset();
00327 
00328         FORGET_OBJECT(retnode);
00329 }
00330 
00331 void DCFuncNode::fold_setinfo(DCUnit * /*unit*/, std::deque<Node *> &nodes)
00332 {
00333         assert(nodes.size() && nodes.back()->opcode()==0x77);
00334         /*DCCallMutatorNode **/setinfonode = static_cast<DCCallMutatorNode *>(nodes.back());
00335         nodes.pop_back();
00336         
00337         // chain of assertions...
00338         assert(setinfonode->a_lnode()->opcode()==0x0B); // 'push word'
00339         process_type = static_cast<const PushVarNode *>(setinfonode->a_lnode())->dtype().value();
00340         debug_processtype_offset= static_cast<const PushVarNode *>(setinfonode->a_lnode())->dtype().value();
00341         
00342         assert(setinfonode->a_rnode()->opcode()==0x4C);
00343         const DCCallMutatorNode *temp_push_indirect = static_cast<const DCCallMutatorNode *>(setinfonode->a_rnode());
00344         // make sure we're a '*this'
00345         assert(temp_push_indirect->a_lnode()->rtype()==Type::T_DWORD);
00346         assert(static_cast<const PushVarNode *>(temp_push_indirect->a_lnode())->dtype().value()==0x06);
00347         debug_thisp=true;
00348 
00349         //FORGET_OBJECT(setinfonode); 
00350 }
00351 
00352 void DCFuncNode::fold_procexclude(DCUnit * /*unit*/, std::deque<Node *> &nodes)
00353 {
00354         assert(nodes.size() && nodes.back()->opcode()==0x78);
00355         DCCallMutatorNode *procexcludenode = static_cast<DCCallMutatorNode *>(nodes.back());
00356         nodes.pop_back();
00357 
00358         // nice and simple!
00359         has_procexclude=true;
00360         debug_procexclude_offset = procexcludenode->offset();
00361 
00362         FORGET_OBJECT(procexcludenode);
00363 }
00364 
00365 
00366 
00367 

Generated on Fri Jul 27 22:27:15 2007 for pentagram by  doxygen 1.4.7