Update year range in gprofng copyright notices
[binutils-gdb.git] / gprofng / src / Function.cc
blob5f07b520e155a7b5711dd060c03e5561085294b6
1 /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
2 Contributed by Oracle.
4 This file is part of GNU Binutils.
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.
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.
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. */
21 #include "config.h"
22 #include <assert.h>
23 #include <string.h>
24 #include <ctype.h>
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"
36 struct SrcInfo
38 DbeLine *src_line;
39 SrcInfo *included_from;
40 SrcInfo *next;
43 struct PCInfo
45 int64_t offset;
46 int64_t size;
47 SrcInfo *src_info;
50 Function::Function (uint64_t _id)
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;
91 Function::~Function ()
93 free (mangled_name);
94 free (match_name);
95 free (comparable_name);
96 free (name_buf);
97 Destroy (linetab);
98 Destroy (instrs);
100 while (srcinfo_list)
102 SrcInfo *t = srcinfo_list;
103 srcinfo_list = t->next;
104 delete t;
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;
115 char *
116 Function::get_name (NameFormat nfmt)
118 if (nfmt == Histable::NA)
120 DbeView *dbeView = dbeSession->getView (0);
121 if (dbeView)
122 nfmt = dbeView->get_name_format ();
124 if (name_buf && (nfmt == current_name_format || nfmt == Histable::NA))
125 return name_buf;
126 free (name_buf);
127 current_name_format = nfmt;
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
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);
141 if (fname_fmt == Histable::SHORT)
143 int i = get_paren (name_buf);
144 if (i != -1)
145 name_buf[i] = (char) 0;
148 if (soname_fmt)
150 char *fname = dbe_sprintf (NTXT ("%s [%s]"), name_buf, module->loadobject->get_name ());
151 free (name_buf);
152 name_buf = fname;
154 return name_buf;
157 uint64_t
158 Function::get_addr ()
160 LoadObject *lo = module ? module->loadobject : NULL;
161 int seg_idx = lo ? lo->seg_idx : -1;
162 return MAKE_ADDRESS (seg_idx, img_offset);
165 Histable *
166 Function::convertto (Histable_type type, Histable *obj)
168 Histable *res = NULL;
169 SourceFile *source = (SourceFile*) obj;
170 switch (type)
172 case INSTR:
173 res = find_dbeinstr (0, 0);
174 break;
175 case LINE:
177 // mapPCtoLine will implicitly read line info if necessary
178 res = mapPCtoLine (0, source);
179 break;
181 case FUNCTION:
182 res = this;
183 break;
184 case SOURCEFILE:
185 res = def_source;
186 break;
187 default:
188 assert (0);
190 return res;
193 void
194 Function::set_name (char *string)
196 if (string == NULL)
197 return;
198 set_mangled_name (string);
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)
204 // name was globalized
205 char *n = strchr (string + 2, (int) '.');
206 if (n != NULL)
207 mname = n + 1;
209 set_match_name (mname);
210 name = NULL;
211 if (module)
213 if (name == NULL && *match_name == '_')
215 int flag = DMGL_PARAMS;
216 if (module->lang_code == Sp_lang_java)
217 flag |= DMGL_JAVA;
218 name = cplus_demangle (match_name, flag);
221 if (name == NULL) // got demangled string
222 name = dbe_strdup (match_name);
223 set_comparable_name (name);
226 void
227 Function::set_mangled_name (const char *string)
229 if (string)
231 free (mangled_name);
232 mangled_name = dbe_strdup (string);
236 void
237 Function::set_match_name (const char *string)
239 if (string)
241 free (match_name);
242 match_name = dbe_strdup (string);
246 void
247 Function::set_comparable_name (const char *string)
249 if (string)
251 free (comparable_name);
252 comparable_name = dbe_strdup (string);
254 // remove blanks from comparable_name
255 for (char *s = comparable_name, *s1 = comparable_name;;)
257 if (*s == 0)
259 *s1 = 0;
260 break;
262 else if (*s != ' ')
264 *s1 = *s;
265 s1++;
267 s++;
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
277 Function::findDerivedFunctions ()
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;
288 // see if we've already done this
289 if ((flags & FUNC_FLAG_RESDER) != 0)
290 return;
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;
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
312 ftype = MPF_OUTL;
313 isOutlineFunction = true;
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;
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;
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);
329 // skip past the number to to the .
330 while (*p != '.' && *p != 0)
331 p++;
332 if (*p == 0)
334 // can't be right
335 free (sub);
336 return;
338 // skip the trailing .
339 p++;
340 subname = p;
341 bool foundmatch = false;
343 // Find the function from which it is derived -- the one that matched subname
344 Vec_loop (Function*, module->functions, index, fitem)
346 if (streq (subname, fitem->mangled_name))
347 { // found it
348 foundmatch = true;
349 usrfunc = fitem;
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 ();
356 // Build a demangled name
357 switch (ftype)
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;
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;
404 if (foundmatch == false && ftype == MPF_OUTL)
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;
412 free (sub);
415 SrcInfo *
416 Function::new_srcInfo ()
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;
426 void
427 Function::pushSrcFile (SourceFile* source, int /*lineno*/)
429 // create new file stack
430 if (curr_srcfile == NULL)
432 curr_srcfile = source;
433 return;
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)
444 src_info->included_from = curr_srcinfo;
445 curr_srcinfo = src_info;
447 curr_srcfile = source;
448 setSource ();
451 SourceFile *
452 Function::popSrcFile ()
454 if (curr_srcinfo != NULL)
456 curr_srcfile = curr_srcinfo->src_line->sourceFile;
457 curr_srcinfo = curr_srcinfo->included_from;
459 else
460 curr_srcfile = NULL;
461 return curr_srcfile;
464 void
465 Function::copy_PCInfo (Function *from)
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++)
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);
481 void
482 Function::add_PC_info (uint64_t offset, int lineno, SourceFile *cur_src)
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*>;
491 int left = 0;
492 int right = linetab->size () - 1;
493 DbeLine *dbeline;
494 while (left <= right)
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)
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;
507 else if (offset > pcinf_offset)
508 left = x + 1;
509 else
510 right = x - 1;
512 PCInfo *pcinfo = new PCInfo;
513 pcinfo->offset = offset;
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;
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;
534 // If not the first line, update the size of the previous line
535 if (left > 0)
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;
543 linetab->insert (left, pcinfo);
544 if (cur_src == def_source)
546 if (line_first <= 0)
547 setLineFirst (lineno);
548 if (line_last <= 0 || lineno > line_last)
549 line_last = lineno;
553 PCInfo *
554 Function::lookup_PCInfo (uint64_t offset)
556 module->read_stabs ();
557 if (linetab == NULL)
558 linetab = new Vector<PCInfo*>;
560 int left = 0;
561 int right = linetab->size () - 1;
562 while (left <= right)
564 int x = (left + right) / 2;
565 PCInfo *pcinfo = linetab->fetch (x);
566 if (offset >= ((uint64_t) pcinfo->offset))
568 if (offset < (uint64_t) (pcinfo->offset + pcinfo->size))
569 return pcinfo;
570 left = x + 1;
572 else
573 right = x - 1;
575 return NULL;
578 DbeInstr*
579 Function::mapLineToPc (DbeLine *dbeLine)
581 if (dbeLine && linetab)
583 DbeLine *dbl = dbeLine->dbeline_base;
584 for (int i = 0, sz = linetab->size (); i < sz; i++)
586 PCInfo *pcinfo = linetab->get (i);
587 if (pcinfo->src_info
588 && (pcinfo->src_info->src_line->dbeline_base == dbl))
590 DbeInstr *dbeInstr = find_dbeinstr (PCLineFlag, pcinfo->offset);
591 if (dbeInstr)
593 dbeInstr->lineno = dbeLine->lineno;
594 return dbeInstr;
599 return NULL;
602 DbeLine*
603 Function::mapPCtoLine (uint64_t addr, SourceFile *src)
605 PCInfo *pcinfo = lookup_PCInfo (addr);
606 if (pcinfo == NULL)
608 if (defaultDbeLine == NULL)
609 defaultDbeLine = getDefSrc ()->find_dbeline (this, 0);
610 return defaultDbeLine;
612 DbeLine *dbeline = pcinfo->src_info->src_line;
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);
623 DbeInstr *
624 Function::find_dbeinstr (int flag, uint64_t addr)
626 DbeInstr *instr;
628 enum
630 FuncInstHTableSize = 128
633 int hash = (((int) addr) >> 2) & (FuncInstHTableSize - 1);
634 if (instHTable == NULL)
636 if (size > 2048)
638 instHTable = new DbeInstr*[FuncInstHTableSize];
639 for (int i = 0; i < FuncInstHTableSize; i++)
640 instHTable[i] = NULL;
643 else
645 instr = instHTable[hash];
646 if (instr && instr->addr == addr && instr->flags == flag)
647 return instr;
650 int left = 0;
651 int right = instrs->size () - 1;
652 while (left <= right)
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
662 if (flag == instr->flags)
664 if (instHTable)
665 instHTable[hash] = instr;
666 return instr;
668 else if (flag < instr->flags)
669 right = index - 1;
670 else
671 left = index + 1;
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;
683 // LIBRARY_VISIBILITY
684 DbeInstr *
685 Function::create_hide_instr (DbeInstr *instr)
687 DbeInstr *new_instr = new DbeInstr (instr_id++, 0, this, instr->addr);
688 return new_instr;
691 uint64_t
692 Function::find_previous_addr (uint64_t addr)
694 if (addrs == NULL)
696 addrs = module->getAddrs (this);
697 if (addrs == NULL)
698 return addr;
701 int index = -1, not_found = 1;
703 enum
705 FuncAddrIndexHTableSize = 128
707 int hash = (((int) addr) >> 2) & (FuncAddrIndexHTableSize - 1);
708 if (addrIndexHTable == NULL)
710 if (size > 2048)
712 addrIndexHTable = new int[FuncAddrIndexHTableSize];
713 for (int i = 0; i < FuncAddrIndexHTableSize; i++)
714 addrIndexHTable[i] = -1;
717 else
719 index = addrIndexHTable[hash];
720 if (index >= 0 && addrs->fetch (index) == addr)
721 not_found = 0;
724 int left = 0;
725 int right = addrs->size () - 1;
726 while (not_found && left <= right)
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
736 if (addrIndexHTable)
737 addrIndexHTable[hash] = index;
738 not_found = 0;
741 if (not_found)
742 return addr;
743 if (index > 0)
744 index--;
745 return addrs->fetch (index);
748 void
749 Function::setSource ()
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)
760 sources = new Vector<SourceFile*>;
761 sources->append (def_source);
762 sources->append (sf);
764 else if (sources->find (sf) < 0)
765 sources->append (sf);
768 void
769 Function::setDefSrc (SourceFile *sf)
771 if (sf)
773 def_source = sf;
774 if (line_first > 0)
775 add_PC_info (0, line_first, def_source);
779 void
780 Function::setLineFirst (int lineno)
782 if (lineno > 0)
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);
792 Vector<SourceFile*> *
793 Function::get_sources ()
795 if (module)
796 module->read_stabs ();
797 if (sources == NULL)
799 sources = new Vector<SourceFile*>;
800 sources->append (getDefSrc ());
802 return sources;
805 SourceFile*
806 Function::getDefSrc ()
808 if (module)
809 module->read_stabs ();
810 if (def_source == NULL)
811 setDefSrc (module->getMainSrc ());
812 return def_source;
815 char *
816 Function::getDefSrcName ()
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 ();
827 #define cmpValue(a, b) ((a) > (b) ? 1 : (a) == (b) ? 0 : -1)
830 Function::func_cmp (Function *func, SourceFile *srcContext)
832 if (def_source != func->def_source)
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);
843 if (line_first == func->line_first)
844 return cmpValue (img_offset, func->img_offset);
845 if (line_first <= 0)
847 if (func->line_first > 0)
848 return 1;
849 return cmpValue (img_offset, func->img_offset);
851 if (func->line_first <= 0)
852 return -1;
853 return cmpValue (line_first, func->line_first);
856 Vector<Histable*> *
857 Function::get_comparable_objs ()
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)
867 return NULL;
869 comparable_objs = new Vector<Histable*>(comparableModules->size ());
870 for (long i = 0, sz = comparableModules->size (); i < sz; i++)
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
881 for (long i1 = 0, sz1 = VecSize (mod->functions); i1 < sz1; i1++)
883 Function *f = mod->functions->get (i1);
884 if ((f->comparable_objs == NULL)
885 && (strcmp (f->comparable_name, comparable_name) == 0))
887 func = f;
888 func->comparable_objs = comparable_objs;
889 break;
893 comparable_objs->store (i, func);
895 Vector<Histable*> *comparableLoadObjs =
896 module->loadobject->get_comparable_objs ();
897 if (VecSize (comparableLoadObjs) == VecSize (comparable_objs))
899 for (long i = 0, sz = VecSize (comparableLoadObjs); i < sz; i++)
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
909 for (long i1 = 0, sz1 = VecSize (lo->functions); i1 < sz1; i1++)
911 Function *f = lo->functions->fetch (i1);
912 if ((f->comparable_objs == NULL)
913 && (strcmp (f->comparable_name, comparable_name) == 0))
915 func = f;
916 func->comparable_objs = comparable_objs;
917 break;
921 comparable_objs->store (i, func);
924 dump_comparable_objs ();
925 return comparable_objs;
928 JMethod::JMethod (uint64_t _id) : Function (_id)
930 mid = 0LL;
931 addr = (Vaddr) 0;
932 signature = NULL;
933 jni_function = NULL;
936 JMethod::~JMethod ()
938 free (signature);
941 uint64_t
942 JMethod::get_addr ()
944 if (addr != (Vaddr) 0)
945 return addr;
946 else
947 return Function::get_addr ();
950 typedef struct
952 size_t used_in;
953 size_t used_out;
954 } MethodField;
956 static void
957 write_buf (char* buf, char* str)
959 while ((*buf++ = *str++));
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.
965 static MethodField
966 translate_method_field (const char* name, char* buf)
968 MethodField out, t;
969 switch (*name)
971 case 'L':
972 name++;
973 out.used_in = 1;
974 out.used_out = 0;
975 while (*name != ';')
977 *buf = *name++;
978 if (*buf == '/')
979 *buf = '.';
980 buf++;
981 out.used_in++;
982 out.used_out++;
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;
1041 return out;
1045 * translate method name to full method signature
1046 * into the output buffer (buf).
1047 * ret_type - true for printing result type
1049 static bool
1050 translate_method (char* mname, char *signature, bool ret_type, char* buf)
1052 MethodField p;
1053 size_t l;
1054 int first = 1;
1055 if (signature == NULL)
1056 return false;
1058 const char *c = strchr (signature, ')');
1059 if (c == NULL)
1060 return false;
1061 if (ret_type)
1063 p = translate_method_field (++c, buf);
1064 buf += p.used_out;
1065 *buf++ = ' ';
1068 l = strlen (mname);
1069 memcpy (buf, mname, l + 1);
1070 buf += l;
1071 // *buf++ = ' '; // space before ()
1072 *buf++ = '(';
1074 c = signature + 1;
1075 while (*c != ')')
1077 if (!first)
1079 *buf++ = ',';
1080 *buf++ = ' ';
1082 first = 0;
1083 p = translate_method_field (c, buf);
1084 c += p.used_in;
1085 buf += p.used_out;
1088 *buf++ = ')';
1089 *buf = '\0';
1090 return true;
1093 void
1094 JMethod::set_name (char *string)
1096 if (string == NULL)
1097 return;
1098 set_mangled_name (string);
1100 char buf[MAXDBUF];
1101 *buf = '\0';
1102 if (translate_method (string, signature, false, buf))
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));
1109 else
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));
1116 set_match_name (name);
1117 set_comparable_name (name);
1120 bool
1121 JMethod::jni_match (Function *func)
1123 if (func == NULL || (func->flags & FUNC_NOT_JNI) != 0)
1124 return false;
1125 if (jni_function == func)
1126 return true;
1128 char *fname = func->get_name ();
1129 if ((func->flags & FUNC_JNI_CHECKED) == 0)
1131 func->flags |= FUNC_JNI_CHECKED;
1132 if (strncmp (func->get_name (), NTXT ("Java_"), 5) != 0)
1134 func->flags |= FUNC_NOT_JNI;
1135 return false;
1139 char *d = name;
1140 char *s = fname + 5;
1141 while (*d && *d != '(' && *d != ' ')
1143 if (*d == '.')
1145 if (*s++ != '_')
1146 return false;
1147 d++;
1149 else if (*d == '_')
1151 if (*s++ != '_')
1152 return false;
1153 if (*s++ != '1')
1154 return false;
1155 d++;
1157 else if (*d++ != *s++)
1158 return false;
1160 jni_function = func;
1161 return true;