00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
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
00031 #include "x86dis.h"
00032
00033 #include <string.h>
00034
00035 #undef DPRINTF
00036 #define DPRINTF(msg...)
00037 #define DPRINTF2(msg...)
00038
00039
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
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
00182
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
00212
00213
00214
00215
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
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
00235 bool collapsed_xrefs = false;
00236 if (analy->mode & ANALY_COLLAPSE_XREFS) {
00237
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
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
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
00311 Location *next_addr = analy->enumLocations(addr);
00312 int op_len;
00313
00314
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
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
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
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
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
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
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
00499
00500 UINT wr = strlen(buffer);
00501 if (out->write(buffer, wr) != wr) return OUTPUT_GENERATE_ERR_STREAM;
00502
00503
00504 int len;
00505 if (getLineByteLength(len, from, line)) {
00506 from->add(len);
00507 }
00508
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
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
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
00655
00656
00657
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
00666
00667 if (cmp<0 || (cmp == 0 && line==0)) {
00668 DPRINTF2("geht nicht\n");
00669 return 0;
00670 }
00671
00672
00673
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
00687
00688
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
00703
00704
00705 Address *search_addr = DUP_ADDR(Addr);
00706 if (!search_addr->add(-l) || search_addr->compareTo(min)<0) {
00707
00708
00709
00710 delete search_addr;
00711 search_addr = DUP_ADDR(min);
00712 }
00713
00714
00715
00716
00717
00718 Location *prev = analy->enumLocationsReverse(Addr);
00719 if (prev) {
00720
00721
00722
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
00730
00731
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
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