1 /* Copyright (C) 2021-2023 Free Software Foundation, Inc.
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)
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. */
28 #include "DbeSession.h"
31 #include "LoadObject.h"
39 SrcInfo
*included_from
;
50 Function::Function (uint64_t _id
)
56 line_first
= line_last
= -1;
57 isOutlineFunction
= false;
61 comparable_name
= NULL
;
67 save_addr
= FUNC_NO_SAVE
;
70 indexStabsLink
= NULL
;
73 instrs
= new Vector
<DbeInstr
*>;
76 current_name_format
= Histable::NA
;
80 defaultDbeLine
= NULL
;
84 addrIndexHTable
= NULL
;
91 Function::~Function ()
95 free (comparable_name
);
102 SrcInfo
*t
= srcinfo_list
;
103 srcinfo_list
= t
->next
;
109 delete[] addrIndexHTable
;
111 // Remove a link to the current function
112 indexStabsLink
->indexStabsLink
= NULL
;
116 Function::get_name (NameFormat nfmt
)
118 if (nfmt
== Histable::NA
)
120 DbeView
*dbeView
= dbeSession
->getView (0);
122 nfmt
= dbeView
->get_name_format ();
124 if (name_buf
&& (nfmt
== current_name_format
|| nfmt
== Histable::NA
))
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
);
135 if (module
&& module
->is_fortran ()
136 && (streq (name
, "MAIN") || streq (name
, "MAIN_")))
137 name_buf
= strdup (match_name
);
139 name_buf
= strdup (name
);
141 if (fname_fmt
== Histable::SHORT
)
143 int i
= get_paren (name_buf
);
145 name_buf
[i
] = (char) 0;
150 char *fname
= dbe_sprintf (NTXT ("%s [%s]"), name_buf
, module
->loadobject
->get_name ());
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
);
166 Function::convertto (Histable_type type
, Histable
*obj
)
168 Histable
*res
= NULL
;
169 SourceFile
*source
= (SourceFile
*) obj
;
173 res
= find_dbeinstr (0, 0);
177 // mapPCtoLine will implicitly read line info if necessary
178 res
= mapPCtoLine (0, source
);
194 Function::set_name (char *string
)
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) '.');
209 set_match_name (mname
);
213 if (name
== NULL
&& *match_name
== '_')
215 int flag
= DMGL_PARAMS
;
216 if (module
->lang_code
== Sp_lang_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
);
227 Function::set_mangled_name (const char *string
)
232 mangled_name
= dbe_strdup (string
);
237 Function::set_match_name (const char *string
)
242 match_name
= dbe_strdup (string
);
247 Function::set_comparable_name (const char *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
;;)
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
277 Function::findDerivedFunctions ()
283 unsigned long long line_no
;
285 char *subname
= mangled_name
;
288 // see if we've already done this
289 if ((flags
& FUNC_FLAG_RESDER
) != 0)
292 // set flag for future
293 flags
= flags
| FUNC_FLAG_RESDER
;
296 if (*subname
!= '_' || subname
[1] != '$') // Not a specially named function
299 // look for the current versions of naming
300 if (strncmp (subname
+ 2, NTXT ("d1"), 2) == 0) // doall function
302 else if (strncmp (subname
+ 2, "p1", 2) == 0) // parallel region function
304 else if (strncmp (subname
+ 2, "l1", 2) == 0) // single thread loop setup
306 else if (strncmp (subname
+ 2, "s1", 2) == 0) // parallel section function
308 else if (strncmp (subname
+ 2, "t1", 2) == 0) // task function
310 else if (strncmp (subname
+ 2, "o1", 2) == 0) // outline function
313 isOutlineFunction
= true;
315 else if (strncmp (subname
+ 2, "c1", 2) == 0) // clone function
317 else // Not an encoded name, just return
320 // we know it's one of the above prefixes
321 char *sub
= dbe_strdup (name
+ 4); // starting with base-26 number
324 // skip the base-26 number, and extract the line number
325 while (isalpha ((int) (*p
)) != 0 && *p
!= 0)
329 // skip past the number to to the .
330 while (*p
!= '.' && *p
!= 0)
338 // skip the trailing .
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
))
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
360 isOutlineFunction
= true;
361 namefmt
= GTXT ("%s -- outline code from line %lld [%s]");
362 derivedNode
= fitem
->find_dbeinstr (PCLineFlag
, line_no
);
365 namefmt
= GTXT ("%s -- OMP parallel region from line %lld [%s]");
368 namefmt
= GTXT ("%s -- Parallel loop from line %lld [%s]");
371 namefmt
= GTXT ("%s -- OMP sections from line %lld [%s]");
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
);
381 // set the name to the demangled version
384 derivedNode
= fitem
->find_dbeinstr (PCLineFlag
, line_no
);
387 namefmt
= GTXT ("%s -- OMP task from line %lld [%s]");
395 // Finally, construct the demangled name
396 demname
= dbe_sprintf (namefmt
, fitem
->get_name (), line_no
, name
);
399 setLineFirst ((int) line_no
);
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
,
416 Function::new_srcInfo ()
418 SrcInfo
*t
= new SrcInfo ();
420 t
->included_from
= NULL
;
421 t
->next
= srcinfo_list
;
427 Function::pushSrcFile (SourceFile
* source
, int /*lineno*/)
429 // create new file stack
430 if (curr_srcfile
== NULL
)
432 curr_srcfile
= source
;
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
;
452 Function::popSrcFile ()
454 if (curr_srcinfo
!= NULL
)
456 curr_srcfile
= curr_srcinfo
->src_line
->sourceFile
;
457 curr_srcinfo
= curr_srcinfo
->included_from
;
465 Function::copy_PCInfo (Function
*from
)
468 line_first
= from
->line_first
;
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
);
482 Function::add_PC_info (uint64_t offset
, int lineno
, SourceFile
*cur_src
)
484 if (lineno
<= 0 || size
< 0 || offset
>= (uint64_t) size
)
487 cur_src
= curr_srcfile
? curr_srcfile
: def_source
;
489 linetab
= new Vector
<PCInfo
*>;
492 int right
= linetab
->size () - 1;
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
507 else if (offset
> pcinf_offset
)
512 PCInfo
*pcinfo
= new PCInfo
;
513 pcinfo
->offset
= offset
;
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
;
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
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
)
547 setLineFirst (lineno
);
548 if (line_last
<= 0 || lineno
> line_last
)
554 Function::lookup_PCInfo (uint64_t offset
)
556 module
->read_stabs ();
558 linetab
= new Vector
<PCInfo
*>;
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
))
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
);
588 && (pcinfo
->src_info
->src_line
->dbeline_base
== dbl
))
590 DbeInstr
*dbeInstr
= find_dbeinstr (PCLineFlag
, pcinfo
->offset
);
593 dbeInstr
->lineno
= dbeLine
->lineno
;
603 Function::mapPCtoLine (uint64_t addr
, SourceFile
*src
)
605 PCInfo
*pcinfo
= lookup_PCInfo (addr
);
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.
618 if (dbeline
->sourceFile
== src
)
619 return dbeline
->dbeline_base
;
620 return src
->find_dbeline (this, 0);
624 Function::find_dbeinstr (int flag
, uint64_t addr
)
630 FuncInstHTableSize
= 128
633 int hash
= (((int) addr
) >> 2) & (FuncInstHTableSize
- 1);
634 if (instHTable
== NULL
)
638 instHTable
= new DbeInstr
*[FuncInstHTableSize
];
639 for (int i
= 0; i
< FuncInstHTableSize
; i
++)
640 instHTable
[i
] = NULL
;
645 instr
= instHTable
[hash
];
646 if (instr
&& instr
->addr
== addr
&& instr
->flags
== flag
)
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
)
658 else if (addr
> instr
->addr
)
662 if (flag
== instr
->flags
)
665 instHTable
[hash
] = instr
;
668 else if (flag
< instr
->flags
)
675 // None found, create a new one
676 instr
= new DbeInstr (instr_id
++, flag
, this, addr
);
677 instrs
->insert (left
, instr
);
679 instHTable
[hash
] = instr
;
683 // LIBRARY_VISIBILITY
685 Function::create_hide_instr (DbeInstr
*instr
)
687 DbeInstr
*new_instr
= new DbeInstr (instr_id
++, 0, this, instr
->addr
);
692 Function::find_previous_addr (uint64_t addr
)
696 addrs
= module
->getAddrs (this);
701 int index
= -1, not_found
= 1;
705 FuncAddrIndexHTableSize
= 128
707 int hash
= (((int) addr
) >> 2) & (FuncAddrIndexHTableSize
- 1);
708 if (addrIndexHTable
== NULL
)
712 addrIndexHTable
= new int[FuncAddrIndexHTableSize
];
713 for (int i
= 0; i
< FuncAddrIndexHTableSize
; i
++)
714 addrIndexHTable
[i
] = -1;
719 index
= addrIndexHTable
[hash
];
720 if (index
>= 0 && addrs
->fetch (index
) == addr
)
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
)
732 else if (addr
> addr_test
)
737 addrIndexHTable
[hash
] = index
;
745 return addrs
->fetch (index
);
749 Function::setSource ()
751 SourceFile
*sf
= module
->getIncludeFile ();
754 if (def_source
== NULL
)
756 if (sf
== def_source
)
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
);
769 Function::setDefSrc (SourceFile
*sf
)
775 add_PC_info (0, line_first
, def_source
);
780 Function::setLineFirst (int lineno
)
788 add_PC_info (0, line_first
, def_source
);
792 Vector
<SourceFile
*> *
793 Function::get_sources ()
796 module
->read_stabs ();
799 sources
= new Vector
<SourceFile
*>;
800 sources
->append (getDefSrc ());
806 Function::getDefSrc ()
809 module
->read_stabs ();
810 if (def_source
== NULL
)
811 setDefSrc (module
->getMainSrc ());
816 Function::getDefSrcName ()
818 SourceFile
*sf
= getDefSrc ();
820 return sf
->dbeFile
->getResolvedPath ();
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
)
838 if (func
->def_source
== srcContext
)
840 return cmpValue (img_offset
, func
->img_offset
);
843 if (line_first
== func
->line_first
)
844 return cmpValue (img_offset
, func
->img_offset
);
847 if (func
->line_first
> 0)
849 return cmpValue (img_offset
, func
->img_offset
);
851 if (func
->line_first
<= 0)
853 return cmpValue (line_first
, func
->line_first
);
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
)
864 Vector
<Histable
*> *comparableModules
= module
->get_comparable_objs ();
865 if (comparableModules
== 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
);
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))
888 func
->comparable_objs
= comparable_objs
;
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
))
905 if (module
->loadobject
== lo
)
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))
916 func
->comparable_objs
= comparable_objs
;
921 comparable_objs
->store (i
, func
);
924 dump_comparable_objs ();
925 return comparable_objs
;
928 JMethod::JMethod (uint64_t _id
) : Function (_id
)
944 if (addr
!= (Vaddr
) 0)
947 return Function::get_addr ();
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.
966 translate_method_field (const char* name
, char* buf
)
984 out
.used_in
++; /* the ';' is also used. */
987 write_buf (buf
, NTXT ("boolean"));
992 write_buf (buf
, NTXT ("byte"));
997 write_buf (buf
, NTXT ("char"));
1002 write_buf (buf
, NTXT ("short"));
1007 write_buf (buf
, NTXT ("int"));
1012 write_buf (buf
, NTXT ("long"));
1017 write_buf (buf
, NTXT ("float"));
1022 write_buf (buf
, NTXT ("double"));
1027 write_buf (buf
, NTXT ("void"));
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;
1045 * translate method name to full method signature
1046 * into the output buffer (buf).
1047 * ret_type - true for printing result type
1050 translate_method (char* mname
, char *signature
, bool ret_type
, char* buf
)
1055 if (signature
== NULL
)
1058 const char *c
= strchr (signature
, ')');
1063 p
= translate_method_field (++c
, buf
);
1069 memcpy (buf
, mname
, l
+ 1);
1071 // *buf++ = ' '; // space before ()
1083 p
= translate_method_field (c
, buf
);
1094 JMethod::set_name (char *string
)
1098 set_mangled_name (string
);
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
));
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
);
1121 JMethod::jni_match (Function
*func
)
1123 if (func
== NULL
|| (func
->flags
& FUNC_NOT_JNI
) != 0)
1125 if (jni_function
== func
)
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
;
1140 char *s
= fname
+ 5;
1141 while (*d
&& *d
!= '(' && *d
!= ' ')
1157 else if (*d
++ != *s
++)
1160 jni_function
= func
;