1 /* Copyright (C) 2021-2024 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->src_line = NULL;
420 t->included_from = NULL;
421 t->next = srcinfo_list;
422 srcinfo_list = t;
423 return t;
424 }
425
426 void
pushSrcFile(SourceFile * source,int)427 Function::pushSrcFile (SourceFile* source, int /*lineno*/)
428 {
429 // create new file stack
430 if (curr_srcfile == NULL)
431 {
432 curr_srcfile = source;
433 return;
434 }
435
436 SrcInfo *src_info = new_srcInfo ();
437 // In the ideal world, we need a DbeLine(III) here,
438 // but right now it would make us later believe that there are
439 // instructions generated for #include lines. To avoid that,
440 // we ask for a DbeLine(II).
441 src_info->src_line = curr_srcfile->find_dbeline (this, 0 /*lineno*/);
442 if (src_info->src_line)
443 {
444 src_info->included_from = curr_srcinfo;
445 curr_srcinfo = src_info;
446 }
447 curr_srcfile = source;
448 setSource ();
449 }
450
451 SourceFile *
popSrcFile()452 Function::popSrcFile ()
453 {
454 if (curr_srcinfo != NULL)
455 {
456 curr_srcfile = curr_srcinfo->src_line->sourceFile;
457 curr_srcinfo = curr_srcinfo->included_from;
458 }
459 else
460 curr_srcfile = NULL;
461 return curr_srcfile;
462 }
463
464 void
copy_PCInfo(Function * from)465 Function::copy_PCInfo (Function *from)
466 {
467 if (line_first <= 0)
468 line_first = from->line_first;
469 if (line_last <= 0)
470 line_last = from->line_last;
471 if (def_source == NULL)
472 def_source = from->def_source;
473 for (int i = 0, sz = from->linetab ? from->linetab->size () : 0; i < sz; i++)
474 {
475 PCInfo *pcinf = from->linetab->fetch (i);
476 DbeLine *dbeLine = pcinf->src_info->src_line;
477 add_PC_info (pcinf->offset, dbeLine->lineno, dbeLine->sourceFile);
478 }
479 }
480
481 void
add_PC_info(uint64_t offset,int lineno,SourceFile * cur_src)482 Function::add_PC_info (uint64_t offset, int lineno, SourceFile *cur_src)
483 {
484 if (lineno <= 0 || size < 0 || offset >= (uint64_t) size)
485 return;
486 if (cur_src == NULL)
487 cur_src = curr_srcfile ? curr_srcfile : def_source;
488 if (linetab == NULL)
489 linetab = new Vector<PCInfo*>;
490
491 int left = 0;
492 int right = linetab->size () - 1;
493 DbeLine *dbeline;
494 while (left <= right)
495 {
496 int x = (left + right) / 2;
497 PCInfo *pcinf = linetab->fetch (x);
498 uint64_t pcinf_offset = ((uint64_t) pcinf->offset);
499 if (offset == pcinf_offset)
500 {
501 dbeline = cur_src->find_dbeline (this, lineno);
502 dbeline->init_Offset (offset);
503 pcinf->src_info->src_line = dbeline;
504 // Ignore duplicate offset
505 return;
506 }
507 else if (offset > pcinf_offset)
508 left = x + 1;
509 else
510 right = x - 1;
511 }
512 PCInfo *pcinfo = new PCInfo;
513 pcinfo->offset = offset;
514
515 // Form new SrcInfo
516 SrcInfo *srcInfo = new_srcInfo ();
517 dbeline = cur_src->find_dbeline (this, lineno);
518 dbeline->init_Offset (offset);
519 srcInfo->src_line = dbeline;
520 // For now don't build included_from list.
521 // We need better compiler support for that.
522 //srcInfo->included_from = curr_srcinfo;
523 srcInfo->included_from = NULL;
524 pcinfo->src_info = srcInfo;
525
526 // Update the size of the current line in both structures:
527 // current PCInfo and corresponding DbeLine.
528 if (left < linetab->size ())
529 pcinfo->size = linetab->fetch (left)->offset - offset;
530 else
531 pcinfo->size = size - offset;
532 pcinfo->src_info->src_line->size += pcinfo->size;
533
534 // If not the first line, update the size of the previous line
535 if (left > 0)
536 {
537 PCInfo *pcinfo_prev = linetab->fetch (left - 1);
538 int64_t delta = (offset - pcinfo_prev->offset) - pcinfo_prev->size;
539 pcinfo_prev->size += delta;
540 pcinfo_prev->src_info->src_line->size += delta;
541 }
542
543 linetab->insert (left, pcinfo);
544 if (cur_src == def_source)
545 {
546 if (line_first <= 0)
547 setLineFirst (lineno);
548 if (line_last <= 0 || lineno > line_last)
549 line_last = lineno;
550 }
551 }
552
553 PCInfo *
lookup_PCInfo(uint64_t offset)554 Function::lookup_PCInfo (uint64_t offset)
555 {
556 module->read_stabs ();
557 if (linetab == NULL)
558 linetab = new Vector<PCInfo*>;
559
560 int left = 0;
561 int right = linetab->size () - 1;
562 while (left <= right)
563 {
564 int x = (left + right) / 2;
565 PCInfo *pcinfo = linetab->fetch (x);
566 if (offset >= ((uint64_t) pcinfo->offset))
567 {
568 if (offset < (uint64_t) (pcinfo->offset + pcinfo->size))
569 return pcinfo;
570 left = x + 1;
571 }
572 else
573 right = x - 1;
574 }
575 return NULL;
576 }
577
578 DbeInstr*
mapLineToPc(DbeLine * dbeLine)579 Function::mapLineToPc (DbeLine *dbeLine)
580 {
581 if (dbeLine && linetab)
582 {
583 DbeLine *dbl = dbeLine->dbeline_base;
584 for (int i = 0, sz = linetab->size (); i < sz; i++)
585 {
586 PCInfo *pcinfo = linetab->get (i);
587 if (pcinfo->src_info
588 && (pcinfo->src_info->src_line->dbeline_base == dbl))
589 {
590 DbeInstr *dbeInstr = find_dbeinstr (PCLineFlag, pcinfo->offset);
591 if (dbeInstr)
592 {
593 dbeInstr->lineno = dbeLine->lineno;
594 return dbeInstr;
595 }
596 }
597 }
598 }
599 return NULL;
600 }
601
602 DbeLine*
mapPCtoLine(uint64_t addr,SourceFile * src)603 Function::mapPCtoLine (uint64_t addr, SourceFile *src)
604 {
605 PCInfo *pcinfo = lookup_PCInfo (addr);
606 if (pcinfo == NULL)
607 {
608 if (defaultDbeLine == NULL)
609 defaultDbeLine = getDefSrc ()->find_dbeline (this, 0);
610 return defaultDbeLine;
611 }
612 DbeLine *dbeline = pcinfo->src_info->src_line;
613
614 // If source-context is not specified return the line
615 // from which this pc has been generated.
616 if (src == NULL)
617 return dbeline;
618 if (dbeline->sourceFile == src)
619 return dbeline->dbeline_base;
620 return src->find_dbeline (this, 0);
621 }
622
623 DbeInstr *
find_dbeinstr(int flag,uint64_t addr)624 Function::find_dbeinstr (int flag, uint64_t addr)
625 {
626 DbeInstr *instr;
627
628 enum
629 {
630 FuncInstHTableSize = 128
631 };
632
633 int hash = (((int) addr) >> 2) & (FuncInstHTableSize - 1);
634 if (instHTable == NULL)
635 {
636 if (size > 2048)
637 {
638 instHTable = new DbeInstr*[FuncInstHTableSize];
639 for (int i = 0; i < FuncInstHTableSize; i++)
640 instHTable[i] = NULL;
641 }
642 }
643 else
644 {
645 instr = instHTable[hash];
646 if (instr && instr->addr == addr && instr->flags == flag)
647 return instr;
648 }
649
650 int left = 0;
651 int right = instrs->size () - 1;
652 while (left <= right)
653 {
654 int index = (left + right) / 2;
655 instr = instrs->fetch (index);
656 if (addr < instr->addr)
657 right = index - 1;
658 else if (addr > instr->addr)
659 left = index + 1;
660 else
661 {
662 if (flag == instr->flags)
663 {
664 if (instHTable)
665 instHTable[hash] = instr;
666 return instr;
667 }
668 else if (flag < instr->flags)
669 right = index - 1;
670 else
671 left = index + 1;
672 }
673 }
674
675 // None found, create a new one
676 instr = new DbeInstr (instr_id++, flag, this, addr);
677 instrs->insert (left, instr);
678 if (instHTable)
679 instHTable[hash] = instr;
680 return instr;
681 }
682
683 // LIBRARY_VISIBILITY
684 DbeInstr *
create_hide_instr(DbeInstr * instr)685 Function::create_hide_instr (DbeInstr *instr)
686 {
687 DbeInstr *new_instr = new DbeInstr (instr_id++, 0, this, instr->addr);
688 return new_instr;
689 }
690
691 uint64_t
find_previous_addr(uint64_t addr)692 Function::find_previous_addr (uint64_t addr)
693 {
694 if (addrs == NULL)
695 {
696 addrs = module->getAddrs (this);
697 if (addrs == NULL)
698 return addr;
699 }
700
701 int index = -1, not_found = 1;
702
703 enum
704 {
705 FuncAddrIndexHTableSize = 128
706 };
707 int hash = (((int) addr) >> 2) & (FuncAddrIndexHTableSize - 1);
708 if (addrIndexHTable == NULL)
709 {
710 if (size > 2048)
711 {
712 addrIndexHTable = new int[FuncAddrIndexHTableSize];
713 for (int i = 0; i < FuncAddrIndexHTableSize; i++)
714 addrIndexHTable[i] = -1;
715 }
716 }
717 else
718 {
719 index = addrIndexHTable[hash];
720 if (index >= 0 && addrs->fetch (index) == addr)
721 not_found = 0;
722 }
723
724 int left = 0;
725 int right = addrs->size () - 1;
726 while (not_found && left <= right)
727 {
728 index = (left + right) / 2;
729 uint64_t addr_test = addrs->fetch (index);
730 if (addr < addr_test)
731 right = index - 1;
732 else if (addr > addr_test)
733 left = index + 1;
734 else
735 {
736 if (addrIndexHTable)
737 addrIndexHTable[hash] = index;
738 not_found = 0;
739 }
740 }
741 if (not_found)
742 return addr;
743 if (index > 0)
744 index--;
745 return addrs->fetch (index);
746 }
747
748 void
setSource()749 Function::setSource ()
750 {
751 SourceFile *sf = module->getIncludeFile ();
752 if (sf == NULL)
753 sf = getDefSrc ();
754 if (def_source == NULL)
755 setDefSrc (sf);
756 if (sf == def_source)
757 return;
758 if (sources == NULL)
759 {
760 sources = new Vector<SourceFile*>;
761 sources->append (def_source);
762 sources->append (sf);
763 }
764 else if (sources->find (sf) < 0)
765 sources->append (sf);
766 }
767
768 void
setDefSrc(SourceFile * sf)769 Function::setDefSrc (SourceFile *sf)
770 {
771 if (sf)
772 {
773 def_source = sf;
774 if (line_first > 0)
775 add_PC_info (0, line_first, def_source);
776 }
777 }
778
779 void
setLineFirst(int lineno)780 Function::setLineFirst (int lineno)
781 {
782 if (lineno > 0)
783 {
784 line_first = lineno;
785 if (line_last <= 0)
786 line_last = lineno;
787 if (def_source)
788 add_PC_info (0, line_first, def_source);
789 }
790 }
791
792 Vector<SourceFile*> *
get_sources()793 Function::get_sources ()
794 {
795 if (module)
796 module->read_stabs ();
797 if (sources == NULL)
798 {
799 sources = new Vector<SourceFile*>;
800 sources->append (getDefSrc ());
801 }
802 return sources;
803 }
804
805 SourceFile*
getDefSrc()806 Function::getDefSrc ()
807 {
808 if (module)
809 module->read_stabs ();
810 if (def_source == NULL)
811 setDefSrc (module->getMainSrc ());
812 return def_source;
813 }
814
815 char *
getDefSrcName()816 Function::getDefSrcName ()
817 {
818 SourceFile *sf = getDefSrc ();
819 if (sf)
820 return sf->dbeFile->getResolvedPath ();
821 if (module)
822 return module->file_name;
823 sf = dbeSession->get_Unknown_Source ();
824 return sf->get_name ();
825 }
826
827 #define cmpValue(a, b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1)
828
829 int
func_cmp(Function * func,SourceFile * srcContext)830 Function::func_cmp (Function *func, SourceFile *srcContext)
831 {
832 if (def_source != func->def_source)
833 {
834 if (srcContext == NULL)
835 srcContext = getDefSrc ();
836 if (def_source == srcContext)
837 return -1;
838 if (func->def_source == srcContext)
839 return 1;
840 return cmpValue (img_offset, func->img_offset);
841 }
842
843 if (line_first == func->line_first)
844 return cmpValue (img_offset, func->img_offset);
845 if (line_first <= 0)
846 {
847 if (func->line_first > 0)
848 return 1;
849 return cmpValue (img_offset, func->img_offset);
850 }
851 if (func->line_first <= 0)
852 return -1;
853 return cmpValue (line_first, func->line_first);
854 }
855
856 Vector<Histable*> *
get_comparable_objs()857 Function::get_comparable_objs ()
858 {
859 update_comparable_objs ();
860 if (comparable_objs || dbeSession->expGroups->size () <= 1 || module == NULL)
861 return comparable_objs;
862 if (module == NULL || module->loadobject == NULL)
863 return NULL;
864 Vector<Histable*> *comparableModules = module->get_comparable_objs ();
865 if (comparableModules == NULL)
866 {
867 return NULL;
868 }
869 comparable_objs = new Vector<Histable*>(comparableModules->size ());
870 for (long i = 0, sz = comparableModules->size (); i < sz; i++)
871 {
872 Function *func = NULL;
873 comparable_objs->store (i, func);
874 Module *mod = (Module*) comparableModules->fetch (i);
875 if (mod == NULL)
876 continue;
877 if (mod == module)
878 func = this;
879 else
880 {
881 for (long i1 = 0, sz1 = VecSize (mod->functions); i1 < sz1; i1++)
882 {
883 Function *f = mod->functions->get (i1);
884 if ((f->comparable_objs == NULL)
885 && (strcmp (f->comparable_name, comparable_name) == 0))
886 {
887 func = f;
888 func->comparable_objs = comparable_objs;
889 break;
890 }
891 }
892 }
893 comparable_objs->store (i, func);
894 }
895 Vector<Histable*> *comparableLoadObjs =
896 module->loadobject->get_comparable_objs ();
897 if (VecSize (comparableLoadObjs) == VecSize (comparable_objs))
898 {
899 for (long i = 0, sz = VecSize (comparableLoadObjs); i < sz; i++)
900 {
901 LoadObject *lo = (LoadObject *) comparableLoadObjs->get (i);
902 Function *func = (Function *) comparable_objs->get (i);
903 if (func || (lo == NULL))
904 continue;
905 if (module->loadobject == lo)
906 func = this;
907 else
908 {
909 for (long i1 = 0, sz1 = VecSize (lo->functions); i1 < sz1; i1++)
910 {
911 Function *f = lo->functions->fetch (i1);
912 if ((f->comparable_objs == NULL)
913 && (strcmp (f->comparable_name, comparable_name) == 0))
914 {
915 func = f;
916 func->comparable_objs = comparable_objs;
917 break;
918 }
919 }
920 }
921 comparable_objs->store (i, func);
922 }
923 }
924 dump_comparable_objs ();
925 return comparable_objs;
926 }
927
JMethod(uint64_t _id)928 JMethod::JMethod (uint64_t _id) : Function (_id)
929 {
930 mid = 0LL;
931 addr = (Vaddr) 0;
932 signature = NULL;
933 jni_function = NULL;
934 }
935
~JMethod()936 JMethod::~JMethod ()
937 {
938 free (signature);
939 }
940
941 uint64_t
get_addr()942 JMethod::get_addr ()
943 {
944 if (addr != (Vaddr) 0)
945 return addr;
946 else
947 return Function::get_addr ();
948 }
949
950 typedef struct
951 {
952 size_t used_in;
953 size_t used_out;
954 } MethodField;
955
956 static void
write_buf(char * buf,char * str)957 write_buf (char* buf, char* str)
958 {
959 while ((*buf++ = *str++));
960 }
961
962 /** Translate one field from the nane buffer.
963 * return how many chars were read from name and how many bytes were used in buf.
964 */
965 static MethodField
translate_method_field(const char * name,char * buf)966 translate_method_field (const char* name, char* buf)
967 {
968 MethodField out, t;
969 switch (*name)
970 {
971 case 'L':
972 name++;
973 out.used_in = 1;
974 out.used_out = 0;
975 while (*name != ';')
976 {
977 *buf = *name++;
978 if (*buf == '/')
979 *buf = '.';
980 buf++;
981 out.used_in++;
982 out.used_out++;
983 }
984 out.used_in++; /* the ';' is also used. */
985 break;
986 case 'Z':
987 write_buf (buf, NTXT ("boolean"));
988 out.used_out = 7;
989 out.used_in = 1;
990 break;
991 case 'B':
992 write_buf (buf, NTXT ("byte"));
993 out.used_out = 4;
994 out.used_in = 1;
995 break;
996 case 'C':
997 write_buf (buf, NTXT ("char"));
998 out.used_out = 4;
999 out.used_in = 1;
1000 break;
1001 case 'S':
1002 write_buf (buf, NTXT ("short"));
1003 out.used_out = 5;
1004 out.used_in = 1;
1005 break;
1006 case 'I':
1007 write_buf (buf, NTXT ("int"));
1008 out.used_out = 3;
1009 out.used_in = 1;
1010 break;
1011 case 'J':
1012 write_buf (buf, NTXT ("long"));
1013 out.used_out = 4;
1014 out.used_in = 1;
1015 break;
1016 case 'F':
1017 write_buf (buf, NTXT ("float"));
1018 out.used_out = 5;
1019 out.used_in = 1;
1020 break;
1021 case 'D':
1022 write_buf (buf, NTXT ("double"));
1023 out.used_out = 6;
1024 out.used_in = 1;
1025 break;
1026 case 'V':
1027 write_buf (buf, NTXT ("void"));
1028 out.used_out = 4;
1029 out.used_in = 1;
1030 break;
1031 case '[':
1032 t = translate_method_field (name + 1, buf);
1033 write_buf (buf + t.used_out, NTXT ("[]"));
1034 out.used_out = t.used_out + 2;
1035 out.used_in = t.used_in + 1;
1036 break;
1037 default:
1038 out.used_out = 0;
1039 out.used_in = 0;
1040 }
1041 return out;
1042 }
1043
1044 /**
1045 * translate method name to full method signature
1046 * into the output buffer (buf).
1047 * ret_type - true for printing result type
1048 */
1049 static bool
translate_method(char * mname,char * signature,bool ret_type,char * buf)1050 translate_method (char* mname, char *signature, bool ret_type, char* buf)
1051 {
1052 MethodField p;
1053 size_t l;
1054 int first = 1;
1055 if (signature == NULL)
1056 return false;
1057
1058 const char *c = strchr (signature, ')');
1059 if (c == NULL)
1060 return false;
1061 if (ret_type)
1062 {
1063 p = translate_method_field (++c, buf);
1064 buf += p.used_out;
1065 *buf++ = ' ';
1066 }
1067
1068 l = strlen (mname);
1069 memcpy (buf, mname, l + 1);
1070 buf += l;
1071 // *buf++ = ' '; // space before ()
1072 *buf++ = '(';
1073
1074 c = signature + 1;
1075 while (*c != ')')
1076 {
1077 if (!first)
1078 {
1079 *buf++ = ',';
1080 *buf++ = ' ';
1081 }
1082 first = 0;
1083 p = translate_method_field (c, buf);
1084 c += p.used_in;
1085 buf += p.used_out;
1086 }
1087
1088 *buf++ = ')';
1089 *buf = '\0';
1090 return true;
1091 }
1092
1093 void
set_name(char * string)1094 JMethod::set_name (char *string)
1095 {
1096 if (string == NULL)
1097 return;
1098 set_mangled_name (string);
1099
1100 char buf[MAXDBUF];
1101 *buf = '\0';
1102 if (translate_method (string, signature, false, buf))
1103 {
1104 name = dbe_strdup (buf); // got translated string
1105 Dprintf (DUMP_JCLASS_READER,
1106 "JMethod::set_name: true name=%s string=%s signature=%s\n",
1107 STR (name), STR (string), STR (signature));
1108 }
1109 else
1110 {
1111 name = dbe_strdup (string);
1112 Dprintf (DUMP_JCLASS_READER,
1113 "JMethod::set_name: false name=%s signature=%s\n",
1114 STR (name), STR (signature));
1115 }
1116 set_match_name (name);
1117 set_comparable_name (name);
1118 }
1119
1120 bool
jni_match(Function * func)1121 JMethod::jni_match (Function *func)
1122 {
1123 if (func == NULL || (func->flags & FUNC_NOT_JNI) != 0)
1124 return false;
1125 if (jni_function == func)
1126 return true;
1127
1128 char *fname = func->get_name ();
1129 if ((func->flags & FUNC_JNI_CHECKED) == 0)
1130 {
1131 func->flags |= FUNC_JNI_CHECKED;
1132 if (strncmp (func->get_name (), NTXT ("Java_"), 5) != 0)
1133 {
1134 func->flags |= FUNC_NOT_JNI;
1135 return false;
1136 }
1137 }
1138
1139 char *d = name;
1140 char *s = fname + 5;
1141 while (*d && *d != '(' && *d != ' ')
1142 {
1143 if (*d == '.')
1144 {
1145 if (*s++ != '_')
1146 return false;
1147 d++;
1148 }
1149 else if (*d == '_')
1150 {
1151 if (*s++ != '_')
1152 return false;
1153 if (*s++ != '1')
1154 return false;
1155 d++;
1156 }
1157 else if (*d++ != *s++)
1158 return false;
1159 }
1160 jni_function = func;
1161 return true;
1162 }
1163