Main Page | Class Hierarchy | Class List | File List | Class Members | File Members

out.cc

Go to the documentation of this file.
00001 /* 
00002  *      HT Editor
00003  *      out.cc
00004  *
00005  *      Copyright (C) 1999-2002 Sebastian Biallas (sb@web-productions.de)
00006  *
00007  *      This program is free software; you can redistribute it and/or modify
00008  *      it under the terms of the GNU General Public License version 2 as
00009  *      published by the Free Software Foundation.
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., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  */
00020 
00021 #include "analy.h"
00022 #include "analy_names.h"
00023 #include "global.h"
00024 #include "htdebug.h"
00025 #include "htstring.h"
00026 #include "snprintf.h"
00027 #include "tools.h"
00028 #include "out.h"
00029 
00030 // FIXME: grrrrrrrrrrr
00031 #include "x86dis.h"
00032 
00033 #include <string.h>
00034 
00035 #undef DPRINTF
00036 #define DPRINTF(msg...)
00037 #define DPRINTF2(msg...)
00038 //#define DPRINTF(msg...) printf(##msg)
00039 //#define DPRINTF2(msg...) printf(##msg)
00040 
00041 int compare_keys_addresses_delinear(Object *key_a, Object *key_b)
00042 {
00043         return ((Address*)key_a)->compareDelinear((Address*)key_b);
00044 }
00045 
00046 /*
00047  *
00048  */
00049 OutLine::OutLine(byte *Text, int Textlen, int Bytes)
00050 {
00051         textlen = Textlen;
00052         text = (byte*)malloc(Textlen);
00053         memcpy(text, Text, textlen);
00054         bytes = Bytes;
00055 }
00056 
00057 OutLine::~OutLine()
00058 {
00059         free(text);
00060 }
00061 
00062 
00063 /*
00064  *
00065  */
00066 OutAddr::OutAddr(Address *Addr, UINT Time)
00067 {
00068         addr = DUP_ADDR(Addr);
00069         updateTime(Time);
00070         lines = new ht_clist();
00071         lines->init();
00072         size = 0;
00073         bytes = 0;
00074         
00075 }
00076 
00077 OutAddr::~OutAddr()
00078 {
00079         delete addr;
00080         lines->destroy();
00081         delete lines;
00082 }
00083 
00084 void OutAddr::appendLine(OutLine *l)
00085 {
00086         lines->insert(l);
00087         bytes += l->bytes;
00088         size += l->textlen;
00089 }
00090 
00091 void OutAddr::clear()
00092 {
00093         lines->empty();
00094         bytes = 0;
00095         size = 0;
00096 }
00097 
00098 OutLine *OutAddr::getLine(int i)
00099 {
00100         return (OutLine*)lines->get(i);
00101 }
00102 
00103 void OutAddr::updateTime(UINT Time)
00104 {
00105         time = Time;
00106 }
00107 
00108 /*
00109  *
00110  */
00111 void    AnalyserOutput::init(Analyser *Analy)
00112 {
00113         analy = Analy;
00114         addr = new InvalidAddress();
00115         cur_addr = NULL;
00116         cur_out_addr = NULL;
00117         out_addrs = new ht_dtree();
00118         out_addrs->init(compare_keys_addresses_delinear);
00119         bytes_addr = 0;
00120         bytes_line = 0;
00121         size = 0;
00122         current_time = 0;
00123         work_buffer_start = (byte*)malloc(WORKBUF_LEN);
00124         work_buffer = work_buffer_start;
00125         temp_buffer = (byte*)malloc(WORKBUF_LEN);
00126         dis_style = DIS_STYLE_HIGHLIGHT+DIS_STYLE_HEX_NOZEROPAD+DIS_STYLE_HEX_ASMSTYLE+X86DIS_STYLE_OPTIMIZE_ADDR;
00127         changeConfig();
00128 }
00129 
00130 void AnalyserOutput::done()
00131 {
00132         out_addrs->destroy();
00133         delete out_addrs;
00134         delete addr;
00135         free(work_buffer_start);
00136         free(temp_buffer);
00137 }
00138 
00139 void    AnalyserOutput::beginAddr()
00140 {
00141         bytes_addr = 0;
00142         line = 0;
00143 }
00144 
00145 void    AnalyserOutput::beginLine()
00146 {
00147         work_buffer = work_buffer_start;
00148         bytes_line = 0;
00149 }
00150 
00151 void    AnalyserOutput::changeConfig()
00152 {
00153 }
00154 
00155 int     AnalyserOutput::elementLength(const char *s)
00156 {
00157         return strlen(s);
00158 }
00159 
00160 void    AnalyserOutput::endAddr()
00161 {
00162 }
00163 
00164 void    AnalyserOutput::endLine()
00165 {
00166         cur_out_addr->appendLine(new OutLine(work_buffer_start, (work_buffer-work_buffer_start), bytes_line));
00167         bytes_addr += bytes_line;
00168         line++;
00169 }
00170 
00171 void AnalyserOutput::footer()
00172 {
00173         // STUB
00174 }
00175 
00176 static char *analyser_output_addr_sym_func(CPU_ADDR Addr, int *symstrlen, void *context)
00177 {
00178         AnalyserOutput *output = (AnalyserOutput *) context;
00179         char *buf;
00180         Address *addr = output->analy->createAddress();
00181 /*     if (Addr.addr32.offset == 0xaea) {
00182                 int as=0;
00183         }*/
00184         addr->getFromCPUAddress(&Addr);
00185         Location *loc = output->analy->getLocationByAddress(addr);
00186         
00187         if (loc && loc->label) {
00188                 buf = output->link(loc->label->name, addr);
00189                 if (symstrlen) *symstrlen = output->elementLength(buf);
00190                 delete addr;
00191                 return buf;
00192         } else {
00193                 if (output->analy->validAddress(addr, scvalid)) {
00194                         char m[90];
00195                         addr->stringify(m, sizeof m, ADDRESS_STRING_FORMAT_COMPACT | ADDRESS_STRING_FORMAT_ADD_H);
00196                         buf = output->link(m, addr);
00197                         if (symstrlen) *symstrlen = output->elementLength(buf);
00198                         delete addr;
00199                         return buf;
00200                 }
00201         }
00202         delete addr;
00203         return NULL;
00204 }
00205 
00206 void AnalyserOutput::generateAddr(Address *Addr, OutAddr *oa)
00207 {
00208 #define LABELINDENT 32
00209 #define MAX_XREF_COLS 3
00210 #define MAX_XREF_LINES 7
00211 /*               char tbuf[1024];
00212                         Addr->stringify(tbuf, 1024, 0);
00213         printf("generate_addr(%s, ", tbuf);
00214                         addr->stringify(tbuf, 1024, 0);
00215                         printf("%s)\n", tbuf);*/
00216         cur_addr = analy->getLocationByAddress(addr);
00217         cur_out_addr = oa;
00218         cur_out_addr->clear();
00219         
00220         beginAddr();
00221 
00222         if (cur_addr) {
00223                 int xref_count = cur_addr->xrefs ? cur_addr->xrefs->count() : 0;
00224                 // comments
00225                 CommentList *c = cur_addr->comments;
00226                 if (c && (analy->mode & ANALY_SHOW_COMMENTS)) {
00227                         int c1 = c->count();
00228                         for (int i=0; i < c1; i++) {
00229                                 beginLine();
00230                                 putElement(ELEMENT_TYPE_PRE_COMMENT, c->getName(i));
00231                                 endLine();
00232                         }
00233                 }
00234                 // label && xrefs
00235                 bool collapsed_xrefs = false;
00236                 if (analy->mode & ANALY_COLLAPSE_XREFS) {
00237                         // count xrefs
00238                         if (xref_count>=(MAX_XREF_COLS*MAX_XREF_LINES)) {
00239                                 collapsed_xrefs = true;
00240                         }
00241                 }               
00242                 if ((cur_addr->label && (analy->mode & ANALY_SHOW_LABELS)) || (cur_addr->xrefs && (analy->mode & ANALY_SHOW_XREFS))) {
00243                         beginLine();
00244                         // label
00245                         int labellength = (cur_addr->label) ? strlen(cur_addr->label->name) : 0;
00246                         if (labellength && (analy->mode & ANALY_SHOW_LABELS)) {
00247                                 putElement(ELEMENT_TYPE_LABEL, cur_addr->label->name);
00248                                 write(":");
00249                                 labellength++;
00250                         }
00251                         // xrefs
00252                         if (labellength >= LABELINDENT && cur_addr->xrefs) {
00253                                 endLine();
00254                                 beginLine();
00255                                 labellength = 0;
00256                         }
00257                         if (collapsed_xrefs) {
00258                                 for (int j=labellength; j<LABELINDENT; j++) write(" ");
00259                                 char b[32];
00260                                 sprintf(b, "<< show xrefs (%d) >>", xref_count);
00261                                 char *t;
00262                                 if (Addr->byteSize()==4) {
00263                                         dword d;
00264                                         Addr->putIntoArray((byte*)&d);
00265                                         t = externalLink(b, d, 0, 0, 1, NULL);
00266                                 } else {
00267                                         qword d;
00268                                         Addr->putIntoArray((byte*)&d);
00269                                         t = externalLink(b, d.hi, d.lo, 0, 1, NULL);
00270                                 }
00271                                 write(t);
00272                         } else {
00273                                 ht_tree *x_tree = cur_addr->xrefs;
00274                                 if (x_tree) {
00275                                         int i=0;
00276                                         AddrXRef *x;
00277                                         Address *xa = (Address*)x_tree->enum_next((Object**)&x, NULL);
00278                                         while (xa) {
00279                                                 if ((i % (MAX_XREF_COLS+1))!=0) {
00280                                                         char buf3[90];
00281                                                         sprintf(buf3, " %c", xref_type_short(x->type));
00282                                                         write(buf3);
00283                                                         xa->stringify(buf3, 1024, ADDRESS_STRING_FORMAT_COMPACT);
00284                                                         write(link(buf3, xa));
00285                                                         xa = (Address*)x_tree->enum_next((Object**)&x, xa);
00286                                                 } else {
00287                                                         if (i!=0) {
00288                                                                 endLine();
00289                                                                 beginLine();
00290                                                         }
00291                                                         for (int j=labellength; j<LABELINDENT; j++) write(" ");
00292                                                         labellength = 0;
00293                                                         putElement(ELEMENT_TYPE_COMMENT, ";xref");
00294                                                 }
00295                                                 i++;
00296                                         }
00297                                 }
00298                         }
00299                         endLine();
00300                 }
00301         }
00302         
00303         beginLine();
00304 
00305         bool is_valid_ini_addr = analy->validAddress(addr, scinitialized);
00306         bool is_valid_code_addr = analy->validCodeAddress(addr);
00307         
00308         if (is_valid_ini_addr && ((cur_addr && ((cur_addr->type.type == dt_code) || ((cur_addr->type.type == dt_unknown) && (is_valid_code_addr))))
00309         || (!cur_addr && is_valid_code_addr))) {
00310                 // code
00311                 Location *next_addr = analy->enumLocations(addr);
00312                 int op_len;
00313                 
00314                 // max. length of current opcode
00315                 if (next_addr) {
00316                         int d=255;
00317                         next_addr->addr->difference(d, addr);
00318                         op_len = MIN((dword)analy->max_opcode_length, (UINT)d);
00319                 } else {
00320                         op_len = analy->max_opcode_length;
00321                 }
00322 
00323                 byte buf[16];
00324                 int buffer_size = analy->bufPtr(addr, buf, sizeof(buf));
00325                 if (analy->disasm && buffer_size) {
00326                         OPCODE *o=analy->disasm->decode(buf, MIN(buffer_size, op_len), analy->mapAddr(Addr));
00327                         /* inits for addr-sym transformations */
00328                         addr_sym_func_context = this;
00329                         if (analy->mode & ANALY_TRANSLATE_SYMBOLS) addr_sym_func = &analyser_output_addr_sym_func;
00330 
00331                         bool s;
00332                         do {
00333                                 char *x = analy->disasm->str(o, dis_style);
00334                                 putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, x);
00335                                 if ((s = analy->disasm->selectNext(o))) {
00336                                         endLine();
00337                                         beginLine();
00338                                 }
00339                         } while (s);
00340                         
00341                         bytes_line += analy->disasm->getSize(o);
00342                         /* deinits for addr-sym transformations */
00343                         addr_sym_func_context = NULL;
00344                         addr_sym_func = NULL;
00345                 } else {
00346                         if (buffer_size >= 1) {
00347                                 char buff[20];
00348                                 sprintf(buff, "db      \\@n%02xh", buf[0]);
00349                                 putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, buff);
00350                                 sprintf(buff, " ; '%c'", (buf[0]<32)?' ':buf[0]);
00351                                 putElement(ELEMENT_TYPE_COMMENT, buff);
00352 
00353                         } else {
00354                                 putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, "db      ??");
00355                         }
00356                         bytes_line++;
00357                 }
00358                 
00359         } else {
00360                 // data
00361                 if (analy->validAddress(addr, scvalid)) {
00362                         if (cur_addr && (cur_addr->type.type != dt_unknown)
00363                         && (cur_addr->type.type != dt_unknown_data)
00364                         && (cur_addr->type.type != dt_code)) {
00365                                 switch (cur_addr->type.type) {
00366                                         case dt_int: {
00367                                                 bytes_line += cur_addr->type.length;
00368                                                 assert(cur_addr->type.length);
00369                                                 if (analy->validAddress(addr, scinitialized)) {
00370                                                         char buf[50];
00371                                                         switch (cur_addr->type.int_subtype) {
00372                                                                 case dst_iword: {
00373                                                                         word c;
00374                                                                         analy->bufPtr(addr, (byte *)&c, 2);
00375                                                                         sprintf(buf, "dw      \\@n%04xh", c);
00376                                                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, buf);
00377                                                                         break;
00378                                                                 }
00379                                                                 case dst_idword: {
00380                                                                         dword c;
00381                                                                         analy->bufPtr(addr, (byte *)&c, 4);
00382                                                                         sprintf(buf, "dd      \\@n%08xh", c);
00383                                                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, buf);
00384                                                                         break;
00385                                                                 }
00386                                                                 case dst_iqword: {
00387                                                                         qword c;
00388                                                                         analy->bufPtr(addr, (byte *)&c, 8);
00389                                                                         ht_snprintf(buf, sizeof buf, "dq      \\@n%016qxh", &c);
00390                                                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, buf);
00391                                                                         break;
00392                                                                 }
00393                                                                 case dst_ibyte:
00394                                                                 default: {
00395                                                                         byte c;
00396                                                                         if (analy->bufPtr(addr, (byte *)&c, 1)==1) {
00397                                                                                 sprintf(buf, "db      \\@n%02xh ", c);
00398                                                                                 putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, buf);
00399                                                                                 sprintf(buf, "; '%c'", (c<32)?32:c);
00400                                                                                 putElement(ELEMENT_TYPE_COMMENT, buf);
00401                                                                         } else {
00402                                                                                 putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, "db      ??");
00403                                                                         }
00404                                                                 }
00405                                                         }
00406                                                 } else {
00407                                                         // not initialized
00408                                                         switch (cur_addr->type.int_subtype) {
00409                                                                 case dst_iword:
00410                                                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, "dw      ????");
00411                                                                         break;
00412                                                                 case dst_idword:
00413                                                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, "dd      ????????");
00414                                                                         break;
00415                                                                 case dst_ibyte:
00416                                                                 default:
00417                                                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, "db      ??");
00418                                                         }
00419                                                 }
00420                                                 break;
00421                                         }
00422                                         case dt_array: {
00423                                                 if (analy->validAddress(addr, scinitialized)) {
00424                                                         switch (cur_addr->type.array_subtype) {
00425                                                                 case dst_string: {
00426                                                                         char buf[1024];
00427                                                                         byte bufread[1024];
00428                                                                         char *b;
00429                                                                         int r = analy->bufPtr(addr, bufread, MIN(cur_addr->type.length, 1024));
00430                                                                         strcpy(buf, "db      \\@s\"");
00431                                                                         b = buf + 12 + escape_special(buf+12, 100, bufread, r, "\"", false);
00432                                                                         *b = '\"'; b++; *b = 0;
00433                                                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, buf);
00434                                                                         bytes_line += cur_addr->type.length;
00435                                                                         break;                                             
00436                                                                 }
00437                                                                 default: {assert(0);}
00438                                                         }
00439                                                 } else {
00440                                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, "db      ?");
00441                                                 }
00442                                                 break;
00443                                         }                         
00444                                         default: {
00445                                                 assert(0);
00446                                         }
00447                                 }
00448                         } else {
00449                                 // not a known address
00450                                 bytes_line++;
00451                                 byte c;
00452                                 if (analy->validAddress(addr, scinitialized) && (analy->bufPtr(addr, &c, 1)==1)) {
00453                                         char buf[20];
00454                                         sprintf(buf, "db      \\@n%02xh ", c);
00455                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, buf);
00456                                         sprintf(buf, "; '%c'", (c<32)?32:c);
00457                                         putElement(ELEMENT_TYPE_COMMENT, buf);
00458                                 } else {
00459                                         putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, "db      ??");
00460                                 }
00461                         }
00462                 } else {
00463                         // invalid addr
00464                         Address *next = analy->nextValid(Addr);
00465                         int d;
00466                         if (next && next->isValid() && next->difference(d, Addr)) {
00467                                 bytes_line += d;
00468                                 char buf[100];
00469                                 sprintf(buf, "db      ?? * %d", d);
00470                                 putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, buf);
00471                         } else {
00472                                 bytes_line += 1;
00473                                 putElement(ELEMENT_TYPE_HIGHLIGHT_DATA_CODE, "db      ??");
00474                         }
00475                 }
00476         }
00477         
00478         endLine();
00479         endAddr();
00480 }
00481 
00482 ht_stream *AnalyserOutput::getGenerateStream()
00483 {
00484         return NULL;
00485 }
00486 
00487 int     AnalyserOutput::generateFile(Address *from, Address *to)
00488 {
00489         if (analy->active) return OUTPUT_GENERATE_ERR_ANALYSER_NOT_FINISHED;
00490         if (!from->isValid() || !to->isValid()) return OUTPUT_GENERATE_ERR_INVAL;
00491         ht_stream *out = getGenerateStream();
00492         if (!out) return OUTPUT_GENERATE_ERR_INVAL;
00493         header();
00494         int line = 0;
00495         while (from->compareTo(to) <= 0) {
00496                 char buffer[1024];
00497                 if (getLineString(buffer, sizeof buffer, from, line)) {
00498                         // write buffer
00499                         // FIXME: remove strlen
00500                         UINT wr = strlen(buffer);
00501                         if (out->write(buffer, wr) != wr) return OUTPUT_GENERATE_ERR_STREAM;
00502                         
00503                         // update address
00504                         int len;
00505                         if (getLineByteLength(len, from, line)) {
00506                                 from->add(len);
00507                         }
00508                         // update line
00509                         line++;
00510                 } else {
00511                         line = 0;
00512                 }
00513         }
00514         footer();
00515         return OUTPUT_GENERATE_ERR_OK;
00516 }
00517 
00518 void    AnalyserOutput::generatePage(Address *from, int lines)
00519 {
00520 
00521 }
00522 
00523 OutAddr *AnalyserOutput::getAddr(Address *Addr)
00524 {
00525         char tbuf[1024];
00526         Addr->stringify(tbuf, 1024, 0);
00527         DPRINTF("%s -- ",tbuf);
00528         if (!addr->isValid() || Addr->compareTo(addr) != 0) {
00529                 assert(addr != Addr);
00530                 DPRINTF("not cached1 --");
00531                 delete addr;
00532                 addr = DUP_ADDR(Addr);
00533                 OutAddr *oa = (OutAddr*)out_addrs->get(Addr);
00534                 if (!oa) {
00535                         DPRINTF("generate\n");
00536                         if (out_addrs->count() > 1024) {
00537                                 reset();
00538                                 addr = DUP_ADDR(Addr);
00539                         }
00540                         oa = new OutAddr(Addr, current_time);
00541                         generateAddr(Addr, oa);
00542                         out_addrs->insert(DUP_ADDR(Addr), oa);
00543                 } else {
00544                         DPRINTF("but cached2 ");
00545                         if (oa->time != current_time) {
00546                                 DPRINTF("(and generate)");
00547                                 generateAddr(Addr, oa);
00548                                 oa->updateTime(current_time);
00549                         }
00550                         DPRINTF("\n");
00551                 }
00552                 cur_out_addr = oa;
00553         } else {
00554                 DPRINTF("Cached! ");
00555                 if (cur_out_addr->time != current_time) {
00556                         DPRINTF("(but generate)");
00557                         generateAddr(Addr, cur_out_addr);
00558                         cur_out_addr->updateTime(current_time);
00559                 }
00560                 DPRINTF("\n");
00561         }
00562         return cur_out_addr;
00563 }
00564 
00565 OutLine *AnalyserOutput::getLine(Address *Addr, int line)
00566 {
00567         return getAddr(Addr)->getLine(line);
00568 }
00569 
00570 bool AnalyserOutput::getLineString(char *buf, int maxlen, Address *Addr, int line)
00571 {
00572         OutLine *ol = getLine(Addr, line);
00573         if (ol) {
00574                 if (maxlen>0) {
00575                         int len = MIN(ol->textlen+1, maxlen);
00576                         len--;
00577                         memcpy(buf, ol->text, len);
00578                         buf[len] = 0;
00579                 }
00580                 return true;
00581         } else {
00582                 return false;
00583         }
00584 }
00585 
00586 bool AnalyserOutput::getLineByteLength(int &len, Address *Addr, int line)
00587 {
00588         OutLine *ol = getLine(Addr, line);
00589         if (ol) {
00590                 len = ol->bytes;
00591                 return true;
00592         } else {
00593                 return false;
00594         }
00595 }
00596 
00597 int AnalyserOutput::getLineCount(Address *Addr)
00598 {
00599     return getAddr(Addr)->lines->count();
00600 }
00601 
00602 int AnalyserOutput::getAddrByteLength(Address *Addr)
00603 {
00604         return getAddr(Addr)->bytes;
00605 }
00606 
00607 void    AnalyserOutput::header()
00608 {
00609         // STUB
00610 }
00611 
00612 char *AnalyserOutput::link(char *s, Address *Addr)
00613 {
00614         strcpy((char*)temp_buffer, s);
00615         return (char*)temp_buffer;
00616 }
00617 
00618 char *AnalyserOutput::externalLink(char *s, int type1, int type2, int type3, int type4, void *special)
00619 {
00620         strcpy((char*)temp_buffer, s);
00621         return (char*)temp_buffer;
00622 }
00623 
00624 void    AnalyserOutput::invalidateCache()
00625 {
00626         DPRINTF("invalidateCache()\n");
00627         current_time++;
00628         if ((current_time % 50)==0) {
00629                 // collect garbage
00630                 reset();
00631         }
00632 }
00633 
00634 int     AnalyserOutput::nextLine(Address *&Addr, int &line, int n, Address *max)
00635 {
00636         int res = 0;
00637         int len;
00638         while (n--) {
00639                 if (getLineByteLength(len, Addr, line + 1)) {
00640                         line++;
00641                 } else {
00642                         getLineByteLength(len, Addr, line);
00643                         if (Addr->compareTo(max) >= 0) return res;
00644                         if (!Addr->add(len)) return res;
00645                         line = 0;
00646                 }
00647                 res++;
00648         }
00649         return res;
00650 }
00651 
00652 int     AnalyserOutput::prevLine(Address *&Addr, int &line, int n, Address *min)
00653 {
00654 //      fprintf(stdout, "prev_line(%x, %d, %d)\n", *Addr, *line, n);
00655 //#undef DPRINTF2
00656 //#define DPRINTF2(msg...) {ht_snprintf(tbuf, 1024, ##msg); fprintf(stderr, "%s", tbuf);}
00657 //      char tbuf[1024];
00658         DPRINTF2("prev_line(%y, %d, %d, %y)\n", Addr, line, n, min);
00659 
00660         int res = 0;
00661         int cmp = Addr->compareTo(min);
00662         
00663         DPRINTF2("cmp=%d\n", cmp);
00664         /*
00665          *      If we have reached |min| and line==0, we're on top
00666          */
00667         if (cmp<0 || (cmp == 0 && line==0)) {
00668                 DPRINTF2("geht nicht\n");
00669                 return 0;
00670         }
00671         /*
00672          *      A simple case: no address-change, only line-changes.
00673          *      Go up while line > 0
00674          */
00675         while (n && line) {
00676                 DPRINTF2("simple\n");
00677                 n--;
00678                 line--;
00679                 res++;
00680         }
00681         DPRINTF2("test\n");     
00682         if (!n) return res;
00683         DPRINTF2("test2\n");
00684 
00685         /*
00686          *      Now it gets complicated. We have to go to an other address.
00687          *      First we have to figure out, where we should start to search for
00688          *      the previous address.
00689          */
00690         int min_length, max_length, min_look_ahead, avg_look_ahead, addr_align;
00691         if (analy->disasm) {
00692                 analy->disasm->getOpcodeMetrics(min_length, max_length, min_look_ahead, avg_look_ahead, addr_align);
00693         } else {
00694                 min_look_ahead=1;
00695                 avg_look_ahead=1;
00696         }
00697         
00698         int l = n*avg_look_ahead;
00699         if (l < min_look_ahead) l = min_look_ahead;
00700 
00701         /*
00702          *      The disassember whats us to go |l| bytes back
00703          */
00704          
00705         Address *search_addr = DUP_ADDR(Addr);
00706         if (!search_addr->add(-l) || search_addr->compareTo(min)<0) {
00707                 /*
00708                  *      It isnt possible, to go |l| bytes back. So we start at |min|.
00709                  */
00710                 delete search_addr;
00711                 search_addr = DUP_ADDR(min);
00712         }
00713 
00714         /*
00715          *      |prev| contains the previous "logical" location.
00716          *      That is some address known to be "atomic".
00717          */
00718         Location *prev = analy->enumLocationsReverse(Addr);
00719         if (prev) {
00720                 /*
00721                  *      |prevnext| contains the "end address" of |prev|.
00722                  *      So we know how long (how much bytes) prev is.
00723                  */
00724                 Address *prevnext = DUP_ADDR(prev->addr);
00725                 if (prevnext->add(getAddrByteLength(prev->addr))) {
00726                         DPRINTF2("mid-test\n");
00727                         if (prevnext->compareTo(Addr) > 0) {
00728                                 /*
00729                                  *   We were in the middle of a location.
00730                                  *      We solve this situation, by starting a new search
00731                                  *      with |prev->addr|. This is counted as "one line up".
00732                                  */
00733                                 delete Addr;
00734                                 delete search_addr;
00735                                 delete prevnext;
00736                                 Addr = DUP_ADDR(prev->addr);
00737                                 line = 0;
00738                                 res++;
00739                                 DPRINTF2("mid\n");
00740                                 return prevLine(Addr, line, n-1, min)+res;
00741                         }
00742                         if (prevnext->compareTo(Addr) == 0) {
00743                                 delete Addr;
00744                                 delete search_addr;
00745                                 delete prevnext;
00746                                 Addr = DUP_ADDR(prev->addr);
00747                                 line = getLineCount(prev->addr)-1;
00748                                 res++;
00749                                 DPRINTF2("mid2\n");
00750                                 return prevLine(Addr, line, n-1, min)+res;
00751                         }
00752                         DPRINTF2("prev: %y prevnext: %y search_addr: %y\n", prev->addr, prevnext, search_addr);
00753                         Address *oldprevnext = DUP_ADDR(prevnext);
00754                         if (prevnext->add(l) && prevnext->compareTo(Addr) >= 0) {
00755                                 delete search_addr;
00756                                 search_addr = oldprevnext;
00757                                 DPRINTF2("prevnext: %y Addr: %y\n", prevnext, Addr);
00758                                 DPRINTF2("search_addr: %y\n", search_addr);
00759                                 DPRINTF2("mid3\n");
00760                         } else {
00761                                 delete oldprevnext;
00762                         }
00763                 }
00764                 delete prevnext;
00765         }
00766 
00767         int search_line = 0;
00768         if (search_addr->compareTo(min) < 0) {
00769                 /*
00770                  *      We have to start the search at |min|.
00771                  */
00772                 DPRINTF2("search_addr < min\n");
00773                 delete search_addr;
00774                 search_addr = DUP_ADDR(min);
00775         }
00776 
00777         Address *addrbuf[1024];
00778         int linebuf[1024];
00779         int i = 0;
00780         int len;
00781 
00782         Address *next_addr = DUP_ADDR(search_addr);
00783         while (1) {
00784                 DPRINTF2("search_addr: (%y, %d) ", search_addr, search_line);
00785                 DPRINTF2("next_addr: %y \n", next_addr);
00786                 if (search_addr->compareTo(Addr) >= 0) {
00787                         if (search_line >= line || (search_addr->compareTo(Addr) > 0)) break;
00788                 }
00789                 if (getLineByteLength(len, search_addr, search_line)) {
00790                         next_addr->add(len);
00791                         search_line++;
00792                 } else {
00793                         delete search_addr;
00794                         search_addr = DUP_ADDR(next_addr);
00795                         search_line = 0;
00796                         continue;
00797                 }
00798                 assert(i<1024);
00799                 addrbuf[i & 1023] = DUP_ADDR(search_addr);
00800                 linebuf[i & 1023] = search_line-1;
00801                 i++;
00802         }
00803 
00804         delete next_addr;
00805         delete search_addr;
00806         
00807         if (!i) {
00808                 DPRINTF2("no i!\n");
00809                 return res;
00810         }
00811         delete Addr;
00812         if (i >= n) {
00813                 Addr = DUP_ADDR(addrbuf[(i-n) & 1023]);
00814                 line = linebuf[(i-n) & 1023];
00815                 res += n;
00816                 n = 0;
00817         } else {
00818                 Addr = DUP_ADDR(addrbuf[0]);
00819                 line = linebuf[0];
00820                 res += i;
00821                 n -= i;
00822         }
00823 
00824         for (int j=0; j<i; j++) delete addrbuf[j];
00825 
00826         if (n) return prevLine(Addr, line, n, min)+res;
00827         return res;
00828 }
00829 
00830 void AnalyserOutput::putElement(int element_type, const char *element)
00831 {
00832         write(element);
00833 }
00834 
00835 void    AnalyserOutput::reset()
00836 {
00837         delete addr;
00838         addr = new InvalidAddress;
00839         cur_out_addr = NULL;
00840         out_addrs->empty();
00841 }
00842 
00843 void    AnalyserOutput::write(const char *s)
00844 {
00845         int len = elementLength(s);
00846         len = MIN(len, WORKBUF_LEN-(work_buffer-work_buffer_start));
00847         memcpy(work_buffer, s, len);
00848         work_buffer += len;
00849 }
00850 
00851 void AnalyserOutput::write(const char *s, int n)
00852 {
00853         n = MIN(n, WORKBUF_LEN-(work_buffer-work_buffer_start));
00854         memcpy(work_buffer, s, n);
00855         work_buffer += n;
00856 }
00857 
00858 

Generated on Fri May 7 21:15:41 2004 by doxygen 1.3.5