1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2 Contributed by Oracle.
3
4 This file is part of GNU Binutils.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3, or (at your option)
9 any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, 51 Franklin Street - Fifth Floor, Boston,
19 MA 02110-1301, USA. */
20
21 #include "config.h"
22 #include <assert.h>
23 #include <string.h>
24 #include <ctype.h>
25
26 #include "demangle.h"
27 #include "util.h"
28 #include "DbeSession.h"
29 #include "Function.h"
30 #include "Module.h"
31 #include "LoadObject.h"
32 #include "Settings.h"
33 #include "DbeFile.h"
34 #include "DbeView.h"
35
36 struct SrcInfo
37 {
38 DbeLine *src_line;
39 SrcInfo *included_from;
40 SrcInfo *next;
41 };
42
43 struct PCInfo
44 {
45 int64_t offset;
46 int64_t size;
47 SrcInfo *src_info;
48 };
49
Function(uint64_t _id)50 Function::Function (uint64_t _id)
51 {
52 id = _id;
53 instr_id = id << 32;
54 derivedNode = NULL;
55 module = NULL;
56 line_first = line_last = -1;
57 isOutlineFunction = false;
58 name = NULL;
59 mangled_name = NULL;
60 match_name = NULL;
61 comparable_name = NULL;
62 img_fname = NULL;
63 img_offset = 0;
64 chksum = 0;
65 flags = 0;
66 size = 0;
67 save_addr = FUNC_NO_SAVE;
68 linetab = NULL;
69 def_source = NULL;
70 indexStabsLink = NULL;
71 elfSym = NULL;
72 sources = NULL;
73 instrs = new Vector<DbeInstr*>;
74 addrs = NULL;
75 name_buf = NULL;
76 current_name_format = Histable::NA;
77 curr_srcinfo = NULL;
78 curr_srcfile = NULL;
79 srcinfo_list = NULL;
80 defaultDbeLine = NULL;
81 usrfunc = NULL;
82 alias = NULL;
83 instHTable = NULL;
84 addrIndexHTable = NULL;
85 isUsed = false;
86 isHideFunc = false;
87 inlinedSubr = NULL;
88 inlinedSubrCnt = 0;
89 }
90
~Function()91 Function::~Function ()
92 {
93 free (mangled_name);
94 free (match_name);
95 free (comparable_name);
96 free (name_buf);
97 Destroy (linetab);
98 Destroy (instrs);
99
100 while (srcinfo_list)
101 {
102 SrcInfo *t = srcinfo_list;
103 srcinfo_list = t->next;
104 delete t;
105 }
106 delete sources;
107 delete addrs;
108 delete[] instHTable;
109 delete[] addrIndexHTable;
110 if (indexStabsLink)
111 // Remove a link to the current function
112 indexStabsLink->indexStabsLink = NULL;
113 }
114
115 char *
get_name(NameFormat nfmt)116 Function::get_name (NameFormat nfmt)
117 {
118 if (nfmt == Histable::NA)
119 {
120 DbeView *dbeView = dbeSession->getView (0);
121 if (dbeView)
122 nfmt = dbeView->get_name_format ();
123 }
124 if (name_buf && (nfmt == current_name_format || nfmt == Histable::NA))
125 return name_buf;
126 free (name_buf);
127 current_name_format = nfmt;
128
129 bool soname_fmt = Histable::soname_fmt (nfmt);
130 int fname_fmt = Histable::fname_fmt (nfmt);
131 if (fname_fmt == Histable::MANGLED)
132 name_buf = strdup (mangled_name);
133 else
134 {
135 if (module && module->is_fortran ()
136 && (streq (name, "MAIN") || streq (name, "MAIN_")))
137 name_buf = strdup (match_name);
138 else
139 name_buf = strdup (name);
140
141 if (fname_fmt == Histable::SHORT)
142 {
143 int i = get_paren (name_buf);
144 if (i != -1)
145 name_buf[i] = (char) 0;
146 }
147 }
148 if (soname_fmt)
149 {
150 char *fname = dbe_sprintf (NTXT ("%s [%s]"), name_buf, module->loadobject->get_name ());
151 free (name_buf);
152 name_buf = fname;
153 }
154 return name_buf;
155 }
156
157 uint64_t
get_addr()158 Function::get_addr ()
159 {
160 LoadObject *lo = module ? module->loadobject : NULL;
161 int seg_idx = lo ? lo->seg_idx : -1;
162 return MAKE_ADDRESS (seg_idx, img_offset);
163 }
164
165 Histable *
convertto(Histable_type type,Histable * obj)166 Function::convertto (Histable_type type, Histable *obj)
167 {
168 Histable *res = NULL;
169 SourceFile *source = (SourceFile*) obj;
170 switch (type)
171 {
172 case INSTR:
173 res = find_dbeinstr (0, 0);
174 break;
175 case LINE:
176 {
177 // mapPCtoLine will implicitly read line info if necessary
178 res = mapPCtoLine (0, source);
179 break;
180 }
181 case FUNCTION:
182 res = this;
183 break;
184 case SOURCEFILE:
185 res = def_source;
186 break;
187 default:
188 assert (0);
189 }
190 return res;
191 }
192
193 void
set_name(char * string)194 Function::set_name (char *string)
195 {
196 if (string == NULL)
197 return;
198 set_mangled_name (string);
199
200 // strip away any globalization prefix, and save result for matching
201 char *mname = string;
202 if (strncmp (string, "$X", 2) == 0 || strncmp (string, ".X", 2) == 0)
203 {
204 // name was globalized
205 char *n = strchr (string + 2, (int) '.');
206 if (n != NULL)
207 mname = n + 1;
208 }
209 set_match_name (mname);
210 name = NULL;
211 if (module)
212 {
213 if (name == NULL && *match_name == '_')
214 {
215 int flag = DMGL_PARAMS;
216 if (module->lang_code == Sp_lang_java)
217 flag |= DMGL_JAVA;
218 name = cplus_demangle (match_name, flag);
219 }
220 }
221 if (name == NULL) // got demangled string
222 name = dbe_strdup (match_name);
223 set_comparable_name (name);
224 }
225
226 void
set_mangled_name(const char * string)227 Function::set_mangled_name (const char *string)
228 {
229 if (string)
230 {
231 free (mangled_name);
232 mangled_name = dbe_strdup (string);
233 }
234 }
235
236 void
set_match_name(const char * string)237 Function::set_match_name (const char *string)
238 {
239 if (string)
240 {
241 free (match_name);
242 match_name = dbe_strdup (string);
243 }
244 }
245
246 void
set_comparable_name(const char * string)247 Function::set_comparable_name (const char *string)
248 {
249 if (string)
250 {
251 free (comparable_name);
252 comparable_name = dbe_strdup (string);
253
254 // remove blanks from comparable_name
255 for (char *s = comparable_name, *s1 = comparable_name;;)
256 {
257 if (*s == 0)
258 {
259 *s1 = 0;
260 break;
261 }
262 else if (*s != ' ')
263 {
264 *s1 = *s;
265 s1++;
266 }
267 s++;
268 }
269 }
270 }
271
272 // This function looks at the name of a function, and determines whether
273 // or not it may be a derived function -- outline, mtask, or clone --
274 // If it is, it writes the function name as demangled,
275 // and sets a pointer to the function from which it was derived
276 void
findDerivedFunctions()277 Function::findDerivedFunctions ()
278
279 {
280 MPFuncTypes ftype;
281 int index;
282 Function *fitem;
283 unsigned long long line_no;
284 char *namefmt;
285 char *subname = mangled_name;
286 char *demname;
287
288 // see if we've already done this
289 if ((flags & FUNC_FLAG_RESDER) != 0)
290 return;
291
292 // set flag for future
293 flags = flags | FUNC_FLAG_RESDER;
294 if (module == NULL)
295 return;
296 if (*subname != '_' || subname[1] != '$') // Not a specially named function
297 return;
298
299 // look for the current versions of naming
300 if (strncmp (subname + 2, NTXT ("d1"), 2) == 0) // doall function
301 ftype = MPF_DOALL;
302 else if (strncmp (subname + 2, "p1", 2) == 0) // parallel region function
303 ftype = MPF_PAR;
304 else if (strncmp (subname + 2, "l1", 2) == 0) // single thread loop setup
305 ftype = MPF_DOALL;
306 else if (strncmp (subname + 2, "s1", 2) == 0) // parallel section function
307 ftype = MPF_SECT;
308 else if (strncmp (subname + 2, "t1", 2) == 0) // task function
309 ftype = MPF_TASK;
310 else if (strncmp (subname + 2, "o1", 2) == 0) // outline function
311 {
312 ftype = MPF_OUTL;
313 isOutlineFunction = true;
314 }
315 else if (strncmp (subname + 2, "c1", 2) == 0) // clone function
316 ftype = MPF_CLONE;
317 else // Not an encoded name, just return
318 return;
319
320 // we know it's one of the above prefixes
321 char *sub = dbe_strdup (name + 4); // starting with base-26 number
322 char *p = sub;
323
324 // skip the base-26 number, and extract the line number
325 while (isalpha ((int) (*p)) != 0 && *p != 0)
326 p++;
327 line_no = atoll (p);
328
329 // skip past the number to to the .
330 while (*p != '.' && *p != 0)
331 p++;
332 if (*p == 0)
333 {
334 // can't be right
335 free (sub);
336 return;
337 }
338 // skip the trailing .
339 p++;
340 subname = p;
341 bool foundmatch = false;
342
343 // Find the function from which it is derived -- the one that matched subname
344 Vec_loop (Function*, module->functions, index, fitem)
345 {
346 if (streq (subname, fitem->mangled_name))
347 { // found it
348 foundmatch = true;
349 usrfunc = fitem;
350
351 // set the derived node
352 if ((fitem->flags & FUNC_FLAG_RESDER) == 0)
353 // ensure that it, too, is resolved if derived
354 fitem->findDerivedFunctions ();
355
356 // Build a demangled name
357 switch (ftype)
358 {
359 case MPF_OUTL:
360 isOutlineFunction = true;
361 namefmt = GTXT ("%s -- outline code from line %lld [%s]");
362 derivedNode = fitem->find_dbeinstr (PCLineFlag, line_no);
363 break;
364 case MPF_PAR:
365 namefmt = GTXT ("%s -- OMP parallel region from line %lld [%s]");
366 break;
367 case MPF_DOALL:
368 namefmt = GTXT ("%s -- Parallel loop from line %lld [%s]");
369 break;
370 case MPF_SECT:
371 namefmt = GTXT ("%s -- OMP sections from line %lld [%s]");
372 break;
373 case MPF_CLONE:
374 // Note that clones are handled differently -- no line number and
375 // clones are NOT shown as called from the original
376 // so after constructing the name, just return
377 // later, establish link from clone to parent
378 demname = dbe_sprintf (GTXT ("%s -- cloned version [%s]"),
379 fitem->get_name (), name);
380 free (name);
381 // set the name to the demangled version
382 name = demname;
383 free (sub);
384 derivedNode = fitem->find_dbeinstr (PCLineFlag, line_no);
385 return;
386 case MPF_TASK:
387 namefmt = GTXT ("%s -- OMP task from line %lld [%s]");
388 break;
389 default:
390 free (sub);
391 return;
392
393 }
394
395 // Finally, construct the demangled name
396 demname = dbe_sprintf (namefmt, fitem->get_name (), line_no, name);
397 free (name);
398 name = demname;
399 setLineFirst ((int) line_no);
400 break;
401 }
402 }
403
404 if (foundmatch == false && ftype == MPF_OUTL)
405 {
406 // Even if derived node was not found, we can demangle
407 demname = dbe_sprintf (GTXT ("%s -- outline code [%s]"), subname,
408 mangled_name);
409 free (name);
410 name = demname;
411 }
412 free (sub);
413 }
414
415 SrcInfo *
new_srcInfo()416 Function::new_srcInfo ()
417 {
418 SrcInfo *t = new SrcInfo ();
419 t->next = srcinfo_list;
420 srcinfo_list = t;
421 return t;
422 }
423
424 void
pushSrcFile(SourceFile * source,int)425 Function::pushSrcFile (SourceFile* source, int /*lineno*/)
426 {
427 // create new file stack
428 if (curr_srcfile == NULL)
429 {
430 curr_srcfile = source;
431 return;
432 }
433
434 SrcInfo *src_info = new_srcInfo ();
435 // In the ideal world, we need a DbeLine(III) here,
436 // but right now it would make us later believe that there are
437 // instructions generated for #include lines. To avoid that,
438 // we ask for a DbeLine(II).
439 src_info->src_line = curr_srcfile->find_dbeline (this, 0 /*lineno*/);
440 if (src_info->src_line)
441 {
442 src_info->included_from = curr_srcinfo;
443 curr_srcinfo = src_info;
444 }
445 curr_srcfile = source;
446 setSource ();
447 }
448
449 SourceFile *
popSrcFile()450 Function::popSrcFile ()
451 {
452 if (curr_srcinfo != NULL)
453 {
454 curr_srcfile = curr_srcinfo->src_line->sourceFile;
455 curr_srcinfo = curr_srcinfo->included_from;
456 }
457 else
458 curr_srcfile = NULL;
459 return curr_srcfile;
460 }
461
462 void
copy_PCInfo(Function * from)463 Function::copy_PCInfo (Function *from)
464 {
465 if (line_first <= 0)
466 line_first = from->line_first;
467 if (line_last <= 0)
468 line_last = from->line_last;
469 if (def_source == NULL)
470 def_source = from->def_source;
471 for (int i = 0, sz = from->linetab ? from->linetab->size () : 0; i < sz; i++)
472 {
473 PCInfo *pcinf = from->linetab->fetch (i);
474 DbeLine *dbeLine = pcinf->src_info->src_line;
475 add_PC_info (pcinf->offset, dbeLine->lineno, dbeLine->sourceFile);
476 }
477 }
478
479 void
add_PC_info(uint64_t offset,int lineno,SourceFile * cur_src)480 Function::add_PC_info (uint64_t offset, int lineno, SourceFile *cur_src)
481 {
482 if (lineno <= 0 || size < 0 || offset >= (uint64_t) size)
483 return;
484 if (cur_src == NULL)
485 cur_src = curr_srcfile ? curr_srcfile : def_source;
486 if (linetab == NULL)
487 linetab = new Vector<PCInfo*>;
488
489 int left = 0;
490 int right = linetab->size () - 1;
491 DbeLine *dbeline;
492 while (left <= right)
493 {
494 int x = (left + right) / 2;
495 PCInfo *pcinf = linetab->fetch (x);
496 uint64_t pcinf_offset = ((uint64_t) pcinf->offset);
497 if (offset == pcinf_offset)
498 {
499 dbeline = cur_src->find_dbeline (this, lineno);
500 dbeline->init_Offset (offset);
501 pcinf->src_info->src_line = dbeline;
502 // Ignore duplicate offset
503 return;
504 }
505 else if (offset > pcinf_offset)
506 left = x + 1;
507 else
508 right = x - 1;
509 }
510 PCInfo *pcinfo = new PCInfo;
511 pcinfo->offset = offset;
512
513 // Form new SrcInfo
514 SrcInfo *srcInfo = new_srcInfo ();
515 dbeline = cur_src->find_dbeline (this, lineno);
516 dbeline->init_Offset (offset);
517 srcInfo->src_line = dbeline;
518 // For now don't build included_from list.
519 // We need better compiler support for that.
520 //srcInfo->included_from = curr_srcinfo;
521 srcInfo->included_from = NULL;
522 pcinfo->src_info = srcInfo;
523
524 // Update the size of the current line in both structures:
525 // current PCInfo and corresponding DbeLine.
526 if (left < linetab->size ())
527 pcinfo->size = linetab->fetch (left)->offset - offset;
528 else
529 pcinfo->size = size - offset;
530 pcinfo->src_info->src_line->size += pcinfo->size;
531
532 // If not the first line, update the size of the previous line
533 if (left > 0)
534 {
535 PCInfo *pcinfo_prev = linetab->fetch (left - 1);
536 int64_t delta = (offset - pcinfo_prev->offset) - pcinfo_prev->size;
537 pcinfo_prev->size += delta;
538 pcinfo_prev->src_info->src_line->size += delta;
539 }
540
541 linetab->insert (left, pcinfo);
542 if (cur_src == def_source)
543 {
544 if (line_first <= 0)
545 setLineFirst (lineno);
546 if (line_last <= 0 || lineno > line_last)
547 line_last = lineno;
548 }
549 }
550
551 PCInfo *
lookup_PCInfo(uint64_t offset)552 Function::lookup_PCInfo (uint64_t offset)
553 {
554 module->read_stabs ();
555 if (linetab == NULL)
556 linetab = new Vector<PCInfo*>;
557
558 int left = 0;
559 int right = linetab->size () - 1;
560 while (left <= right)
561 {
562 int x = (left + right) / 2;
563 PCInfo *pcinfo = linetab->fetch (x);
564 if (offset >= ((uint64_t) pcinfo->offset))
565 {
566 if (offset < (uint64_t) (pcinfo->offset + pcinfo->size))
567 return pcinfo;
568 left = x + 1;
569 }
570 else
571 right = x - 1;
572 }
573 return NULL;
574 }
575
576 DbeInstr*
mapLineToPc(DbeLine * dbeLine)577 Function::mapLineToPc (DbeLine *dbeLine)
578 {
579 if (dbeLine && linetab)
580 {
581 DbeLine *dbl = dbeLine->dbeline_base;
582 for (int i = 0, sz = linetab->size (); i < sz; i++)
583 {
584 PCInfo *pcinfo = linetab->get (i);
585 if (pcinfo->src_info
586 && (pcinfo->src_info->src_line->dbeline_base == dbl))
587 {
588 DbeInstr *dbeInstr = find_dbeinstr (PCLineFlag, pcinfo->offset);
589 if (dbeInstr)
590 {
591 dbeInstr->lineno = dbeLine->lineno;
592 return dbeInstr;
593 }
594 }
595 }
596 }
597 return NULL;
598 }
599
600 DbeLine*
mapPCtoLine(uint64_t addr,SourceFile * src)601 Function::mapPCtoLine (uint64_t addr, SourceFile *src)
602 {
603 PCInfo *pcinfo = lookup_PCInfo (addr);
604 if (pcinfo == NULL)
605 {
606 if (defaultDbeLine == NULL)
607 defaultDbeLine = getDefSrc ()->find_dbeline (this, 0);
608 return defaultDbeLine;
609 }
610 DbeLine *dbeline = pcinfo->src_info->src_line;
611
612 // If source-context is not specified return the line
613 // from which this pc has been generated.
614 if (src == NULL)
615 return dbeline;
616 if (dbeline->sourceFile == src)
617 return dbeline->dbeline_base;
618 return src->find_dbeline (this, 0);
619 }
620
621 DbeInstr *
find_dbeinstr(int flag,uint64_t addr)622 Function::find_dbeinstr (int flag, uint64_t addr)
623 {
624 DbeInstr *instr;
625
626 enum
627 {
628 FuncInstHTableSize = 128
629 };
630
631 int hash = (((int) addr) >> 2) & (FuncInstHTableSize - 1);
632 if (instHTable == NULL)
633 {
634 if (size > 2048)
635 {
636 instHTable = new DbeInstr*[FuncInstHTableSize];
637 for (int i = 0; i < FuncInstHTableSize; i++)
638 instHTable[i] = NULL;
639 }
640 }
641 else
642 {
643 instr = instHTable[hash];
644 if (instr && instr->addr == addr && instr->flags == flag)
645 return instr;
646 }
647
648 int left = 0;
649 int right = instrs->size () - 1;
650 while (left <= right)
651 {
652 int index = (left + right) / 2;
653 instr = instrs->fetch (index);
654 if (addr < instr->addr)
655 right = index - 1;
656 else if (addr > instr->addr)
657 left = index + 1;
658 else
659 {
660 if (flag == instr->flags)
661 {
662 if (instHTable)
663 instHTable[hash] = instr;
664 return instr;
665 }
666 else if (flag < instr->flags)
667 right = index - 1;
668 else
669 left = index + 1;
670 }
671 }
672
673 // None found, create a new one
674 instr = new DbeInstr (instr_id++, flag, this, addr);
675 instrs->insert (left, instr);
676 if (instHTable)
677 instHTable[hash] = instr;
678 return instr;
679 }
680
681 // LIBRARY_VISIBILITY
682 DbeInstr *
create_hide_instr(DbeInstr * instr)683 Function::create_hide_instr (DbeInstr *instr)
684 {
685 DbeInstr *new_instr = new DbeInstr (instr_id++, 0, this, instr->addr);
686 return new_instr;
687 }
688
689 uint64_t
find_previous_addr(uint64_t addr)690 Function::find_previous_addr (uint64_t addr)
691 {
692 if (addrs == NULL)
693 {
694 addrs = module->getAddrs (this);
695 if (addrs == NULL)
696 return addr;
697 }
698
699 int index = -1, not_found = 1;
700
701 enum
702 {
703 FuncAddrIndexHTableSize = 128
704 };
705 int hash = (((int) addr) >> 2) & (FuncAddrIndexHTableSize - 1);
706 if (addrIndexHTable == NULL)
707 {
708 if (size > 2048)
709 {
710 addrIndexHTable = new int[FuncAddrIndexHTableSize];
711 for (int i = 0; i < FuncAddrIndexHTableSize; i++)
712 addrIndexHTable[i] = -1;
713 }
714 }
715 else
716 {
717 index = addrIndexHTable[hash];
718 if (index >= 0 && addrs->fetch (index) == addr)
719 not_found = 0;
720 }
721
722 int left = 0;
723 int right = addrs->size () - 1;
724 while (not_found && left <= right)
725 {
726 index = (left + right) / 2;
727 uint64_t addr_test = addrs->fetch (index);
728 if (addr < addr_test)
729 right = index - 1;
730 else if (addr > addr_test)
731 left = index + 1;
732 else
733 {
734 if (addrIndexHTable)
735 addrIndexHTable[hash] = index;
736 not_found = 0;
737 }
738 }
739 if (not_found)
740 return addr;
741 if (index > 0)
742 index--;
743 return addrs->fetch (index);
744 }
745
746 void
setSource()747 Function::setSource ()
748 {
749 SourceFile *sf = module->getIncludeFile ();
750 if (sf == NULL)
751 sf = getDefSrc ();
752 if (def_source == NULL)
753 setDefSrc (sf);
754 if (sf == def_source)
755 return;
756 if (sources == NULL)
757 {
758 sources = new Vector<SourceFile*>;
759 sources->append (def_source);
760 sources->append (sf);
761 }
762 else if (sources->find (sf) < 0)
763 sources->append (sf);
764 }
765
766 void
setDefSrc(SourceFile * sf)767 Function::setDefSrc (SourceFile *sf)
768 {
769 if (sf)
770 {
771 def_source = sf;
772 if (line_first > 0)
773 add_PC_info (0, line_first, def_source);
774 }
775 }
776
777 void
setLineFirst(int lineno)778 Function::setLineFirst (int lineno)
779 {
780 if (lineno > 0)
781 {
782 line_first = lineno;
783 if (line_last <= 0)
784 line_last = lineno;
785 if (def_source)
786 add_PC_info (0, line_first, def_source);
787 }
788 }
789
790 Vector<SourceFile*> *
get_sources()791 Function::get_sources ()
792 {
793 if (module)
794 module->read_stabs ();
795 if (sources == NULL)
796 {
797 sources = new Vector<SourceFile*>;
798 sources->append (getDefSrc ());
799 }
800 return sources;
801 }
802
803 SourceFile*
getDefSrc()804 Function::getDefSrc ()
805 {
806 if (module)
807 module->read_stabs ();
808 if (def_source == NULL)
809 setDefSrc (module->getMainSrc ());
810 return def_source;
811 }
812
813 char *
getDefSrcName()814 Function::getDefSrcName ()
815 {
816 SourceFile *sf = getDefSrc ();
817 if (sf)
818 return sf->dbeFile->getResolvedPath ();
819 if (module)
820 return module->file_name;
821 sf = dbeSession->get_Unknown_Source ();
822 return sf->get_name ();
823 }
824
825 #define cmpValue(a, b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1)
826
827 int
func_cmp(Function * func,SourceFile * srcContext)828 Function::func_cmp (Function *func, SourceFile *srcContext)
829 {
830 if (def_source != func->def_source)
831 {
832 if (srcContext == NULL)
833 srcContext = getDefSrc ();
834 if (def_source == srcContext)
835 return -1;
836 if (func->def_source == srcContext)
837 return 1;
838 return cmpValue (img_offset, func->img_offset);
839 }
840
841 if (line_first == func->line_first)
842 return cmpValue (img_offset, func->img_offset);
843 if (line_first <= 0)
844 {
845 if (func->line_first > 0)
846 return 1;
847 return cmpValue (img_offset, func->img_offset);
848 }
849 if (func->line_first <= 0)
850 return -1;
851 return cmpValue (line_first, func->line_first);
852 }
853
854 Vector<Histable*> *
get_comparable_objs()855 Function::get_comparable_objs ()
856 {
857 update_comparable_objs ();
858 if (comparable_objs || dbeSession->expGroups->size () <= 1 || module == NULL)
859 return comparable_objs;
860 if (module == NULL || module->loadobject == NULL)
861 return NULL;
862 Vector<Histable*> *comparableModules = module->get_comparable_objs ();
863 if (comparableModules == NULL)
864 {
865 return NULL;
866 }
867 comparable_objs = new Vector<Histable*>(comparableModules->size ());
868 for (long i = 0, sz = comparableModules->size (); i < sz; i++)
869 {
870 Function *func = NULL;
871 comparable_objs->store (i, func);
872 Module *mod = (Module*) comparableModules->fetch (i);
873 if (mod == NULL)
874 continue;
875 if (mod == module)
876 func = this;
877 else
878 {
879 for (long i1 = 0, sz1 = VecSize (mod->functions); i1 < sz1; i1++)
880 {
881 Function *f = mod->functions->get (i1);
882 if ((f->comparable_objs == NULL)
883 && (strcmp (f->comparable_name, comparable_name) == 0))
884 {
885 func = f;
886 func->comparable_objs = comparable_objs;
887 break;
888 }
889 }
890 }
891 comparable_objs->store (i, func);
892 }
893 Vector<Histable*> *comparableLoadObjs =
894 module->loadobject->get_comparable_objs ();
895 if (VecSize (comparableLoadObjs) == VecSize (comparable_objs))
896 {
897 for (long i = 0, sz = VecSize (comparableLoadObjs); i < sz; i++)
898 {
899 LoadObject *lo = (LoadObject *) comparableLoadObjs->get (i);
900 Function *func = (Function *) comparable_objs->get (i);
901 if (func || (lo == NULL))
902 continue;
903 if (module->loadobject == lo)
904 func = this;
905 else
906 {
907 for (long i1 = 0, sz1 = VecSize (lo->functions); i1 < sz1; i1++)
908 {
909 Function *f = lo->functions->fetch (i1);
910 if ((f->comparable_objs == NULL)
911 && (strcmp (f->comparable_name, comparable_name) == 0))
912 {
913 func = f;
914 func->comparable_objs = comparable_objs;
915 break;
916 }
917 }
918 }
919 comparable_objs->store (i, func);
920 }
921 }
922 dump_comparable_objs ();
923 return comparable_objs;
924 }
925
JMethod(uint64_t _id)926 JMethod::JMethod (uint64_t _id) : Function (_id)
927 {
928 mid = 0LL;
929 addr = (Vaddr) 0;
930 signature = NULL;
931 jni_function = NULL;
932 }
933
~JMethod()934 JMethod::~JMethod ()
935 {
936 free (signature);
937 }
938
939 uint64_t
get_addr()940 JMethod::get_addr ()
941 {
942 if (addr != (Vaddr) 0)
943 return addr;
944 else
945 return Function::get_addr ();
946 }
947
948 typedef struct
949 {
950 size_t used_in;
951 size_t used_out;
952 } MethodField;
953
954 static void
write_buf(char * buf,char * str)955 write_buf (char* buf, char* str)
956 {
957 while ((*buf++ = *str++));
958 }
959
960 /** Translate one field from the nane buffer.
961 * return how many chars were read from name and how many bytes were used in buf.
962 */
963 static MethodField
translate_method_field(const char * name,char * buf)964 translate_method_field (const char* name, char* buf)
965 {
966 MethodField out, t;
967 switch (*name)
968 {
969 case 'L':
970 name++;
971 out.used_in = 1;
972 out.used_out = 0;
973 while (*name != ';')
974 {
975 *buf = *name++;
976 if (*buf == '/')
977 *buf = '.';
978 buf++;
979 out.used_in++;
980 out.used_out++;
981 }
982 out.used_in++; /* the ';' is also used. */
983 break;
984 case 'Z':
985 write_buf (buf, NTXT ("boolean"));
986 out.used_out = 7;
987 out.used_in = 1;
988 break;
989 case 'B':
990 write_buf (buf, NTXT ("byte"));
991 out.used_out = 4;
992 out.used_in = 1;
993 break;
994 case 'C':
995 write_buf (buf, NTXT ("char"));
996 out.used_out = 4;
997 out.used_in = 1;
998 break;
999 case 'S':
1000 write_buf (buf, NTXT ("short"));
1001 out.used_out = 5;
1002 out.used_in = 1;
1003 break;
1004 case 'I':
1005 write_buf (buf, NTXT ("int"));
1006 out.used_out = 3;
1007 out.used_in = 1;
1008 break;
1009 case 'J':
1010 write_buf (buf, NTXT ("long"));
1011 out.used_out = 4;
1012 out.used_in = 1;
1013 break;
1014 case 'F':
1015 write_buf (buf, NTXT ("float"));
1016 out.used_out = 5;
1017 out.used_in = 1;
1018 break;
1019 case 'D':
1020 write_buf (buf, NTXT ("double"));
1021 out.used_out = 6;
1022 out.used_in = 1;
1023 break;
1024 case 'V':
1025 write_buf (buf, NTXT ("void"));
1026 out.used_out = 4;
1027 out.used_in = 1;
1028 break;
1029 case '[':
1030 t = translate_method_field (name + 1, buf);
1031 write_buf (buf + t.used_out, NTXT ("[]"));
1032 out.used_out = t.used_out + 2;
1033 out.used_in = t.used_in + 1;
1034 break;
1035 default:
1036 out.used_out = 0;
1037 out.used_in = 0;
1038 }
1039 return out;
1040 }
1041
1042 /**
1043 * translate method name to full method signature
1044 * into the output buffer (buf).
1045 * ret_type - true for printing result type
1046 */
1047 static bool
translate_method(char * mname,char * signature,bool ret_type,char * buf)1048 translate_method (char* mname, char *signature, bool ret_type, char* buf)
1049 {
1050 MethodField p;
1051 size_t l;
1052 int first = 1;
1053 if (signature == NULL)
1054 return false;
1055
1056 const char *c = strchr (signature, ')');
1057 if (c == NULL)
1058 return false;
1059 if (ret_type)
1060 {
1061 p = translate_method_field (++c, buf);
1062 buf += p.used_out;
1063 *buf++ = ' ';
1064 }
1065
1066 l = strlen (mname);
1067 memcpy (buf, mname, l + 1);
1068 buf += l;
1069 // *buf++ = ' '; // space before ()
1070 *buf++ = '(';
1071
1072 c = signature + 1;
1073 while (*c != ')')
1074 {
1075 if (!first)
1076 {
1077 *buf++ = ',';
1078 *buf++ = ' ';
1079 }
1080 first = 0;
1081 p = translate_method_field (c, buf);
1082 c += p.used_in;
1083 buf += p.used_out;
1084 }
1085
1086 *buf++ = ')';
1087 *buf = '\0';
1088 return true;
1089 }
1090
1091 void
set_name(char * string)1092 JMethod::set_name (char *string)
1093 {
1094 if (string == NULL)
1095 return;
1096 set_mangled_name (string);
1097
1098 char buf[MAXDBUF];
1099 *buf = '\0';
1100 if (translate_method (string, signature, false, buf))
1101 {
1102 name = dbe_strdup (buf); // got translated string
1103 Dprintf (DUMP_JCLASS_READER,
1104 "JMethod::set_name: true name=%s string=%s signature=%s\n",
1105 STR (name), STR (string), STR (signature));
1106 }
1107 else
1108 {
1109 name = dbe_strdup (string);
1110 Dprintf (DUMP_JCLASS_READER,
1111 "JMethod::set_name: false name=%s signature=%s\n",
1112 STR (name), STR (signature));
1113 }
1114 set_match_name (name);
1115 set_comparable_name (name);
1116 }
1117
1118 bool
jni_match(Function * func)1119 JMethod::jni_match (Function *func)
1120 {
1121 if (func == NULL || (func->flags & FUNC_NOT_JNI) != 0)
1122 return false;
1123 if (jni_function == func)
1124 return true;
1125
1126 char *fname = func->get_name ();
1127 if ((func->flags & FUNC_JNI_CHECKED) == 0)
1128 {
1129 func->flags |= FUNC_JNI_CHECKED;
1130 if (strncmp (func->get_name (), NTXT ("Java_"), 5) != 0)
1131 {
1132 func->flags |= FUNC_NOT_JNI;
1133 return false;
1134 }
1135 }
1136
1137 char *d = name;
1138 char *s = fname + 5;
1139 while (*d && *d != '(' && *d != ' ')
1140 {
1141 if (*d == '.')
1142 {
1143 if (*s++ != '_')
1144 return false;
1145 d++;
1146 }
1147 else if (*d == '_')
1148 {
1149 if (*s++ != '_')
1150 return false;
1151 if (*s++ != '1')
1152 return false;
1153 d++;
1154 }
1155 else if (*d++ != *s++)
1156 return false;
1157 }
1158 jni_function = func;
1159 return true;
1160 }
1161