@@ -344,6 +344,7 @@ static Addr debug_cache_addr[DEBUG_CACHE_SIZE];
344344static file_node * debug_cache_file [DEBUG_CACHE_SIZE ];
345345static int debug_cache_line [DEBUG_CACHE_SIZE ];
346346static Bool debug_cache_info [DEBUG_CACHE_SIZE ];
347+ static const HChar * debug_cache_inlfn [DEBUG_CACHE_SIZE ];
347348
348349static __inline__
349350void init_debug_cache (void )
@@ -354,6 +355,7 @@ void init_debug_cache(void)
354355 debug_cache_file [i ] = 0 ;
355356 debug_cache_line [i ] = 0 ;
356357 debug_cache_info [i ] = 0 ;
358+ debug_cache_inlfn [i ] = 0 ;
357359 }
358360}
359361
@@ -386,6 +388,15 @@ Bool get_debug_pos(BBCC* bbcc, Addr addr, AddrPos* p)
386388 debug_cache_addr [cachepos ] = addr ;
387389 debug_cache_line [cachepos ] = p -> line ;
388390 debug_cache_file [cachepos ] = p -> file ;
391+
392+ /* Query inline info at the same time we query file/line */
393+ const HChar * inl_fn = 0 ;
394+ Bool has_inline = VG_ (get_inline_fnname )(ep , addr , & inl_fn );
395+ if (has_inline ) {
396+ debug_cache_inlfn [cachepos ] = inl_fn ;
397+ } else {
398+ debug_cache_inlfn [cachepos ] = (const HChar * )(-1 );
399+ }
389400 }
390401
391402 /* Address offset from bbcc start address */
@@ -399,6 +410,44 @@ Bool get_debug_pos(BBCC* bbcc, Addr addr, AddrPos* p)
399410 return found_file_line ;
400411}
401412
413+ /* Get inline function name for an address, with caching.
414+ * Returns True if address is in an inlined function, False otherwise.
415+ * If True, *inl_fn will be set to the inline function name.
416+ */
417+ static Bool get_inline_info (Addr addr , const HChar * * inl_fn )
418+ {
419+ int cachepos = addr % DEBUG_CACHE_SIZE ;
420+
421+ /* Check cache first - but only if inline info was already queried for this address */
422+ if (debug_cache_addr [cachepos ] == addr && debug_cache_inlfn [cachepos ] != 0 ) {
423+ /* We have cached inline info for this address */
424+ if (debug_cache_inlfn [cachepos ] == (const HChar * )(-1 )) {
425+ /* Special marker: no inline function at this address */
426+ * inl_fn = 0 ;
427+ return False ;
428+ }
429+ * inl_fn = debug_cache_inlfn [cachepos ];
430+ return True ;
431+ }
432+
433+ DiEpoch ep = VG_ (current_DiEpoch )();
434+ Bool has_inline = VG_ (get_inline_fnname )(ep , addr , inl_fn );
435+
436+ if (has_inline ) {
437+ /* Cache the inline function name */
438+ debug_cache_inlfn [cachepos ] = * inl_fn ;
439+ } else {
440+ * inl_fn = 0 ;
441+ /* Use special marker -1 to indicate "no inline function" */
442+ debug_cache_inlfn [cachepos ] = (const HChar * )(-1 );
443+ }
444+
445+ CLG_DEBUG (3 , " get_inline_info(%#lx): %s\n" ,
446+ addr , has_inline ? * inl_fn : "(not inlined)" );
447+
448+ return has_inline ;
449+ }
450+
402451
403452/* copy file position and init cost */
404453static void init_apos (AddrPos * p , Addr addr , Addr bbaddr , file_node * file )
@@ -426,13 +475,15 @@ static void init_fcost(AddrCost* c, Addr addr, Addr bbaddr, file_node* file)
426475 CLG_ (init_cost )( CLG_ (sets ).full , c -> cost );
427476}
428477
478+ /* Track last inline function to avoid repeated cfni= output */
479+ static const HChar * last_inline_fn = 0 ;
429480
430481/**
431482 * print position change inside of a BB (last -> curr)
432483 * this doesn't update last to curr!
433484 */
434485static void fprint_apos (VgFile * fp , AddrPos * curr , AddrPos * last ,
435- file_node * func_file )
486+ file_node * func_file , BBCC * bbcc )
436487{
437488 CLG_ASSERT (curr -> file != 0 );
438489 CLG_DEBUG (2 , " print_apos(file '%s', line %u, bb %#lx, addr %#lx) fnFile '%s'\n" ,
@@ -448,6 +499,24 @@ static void fprint_apos(VgFile *fp, AddrPos* curr, AddrPos* last,
448499 print_file (fp , "fi=" , curr -> file );
449500 }
450501
502+ /* Check inline function for this position and output cfni= if changed */
503+ if (bbcc ) {
504+ Addr curr_addr = curr -> addr + bbcc -> bb -> obj -> offset ;
505+ const HChar * inline_fn = 0 ;
506+ Bool is_inline = get_inline_info (curr_addr , & inline_fn );
507+
508+ /* Output cfni= if inline function changed */
509+ if (is_inline && inline_fn && inline_fn != last_inline_fn ) {
510+ VG_ (fprintf )(fp , "cfni=%s\n" , inline_fn );
511+ last_inline_fn = inline_fn ;
512+ }
513+ /* Clear last_inline_fn if we're no longer in inline code */
514+ else if (!is_inline && last_inline_fn ) {
515+ VG_ (fprintf )(fp , "cfni=???\n" );
516+ last_inline_fn = 0 ;
517+ }
518+ }
519+
451520 if (CLG_ (clo ).dump_bbs ) {
452521 if (curr -> line != last -> line ) {
453522 VG_ (fprintf )(fp , "ln=%u\n" , curr -> line );
@@ -704,8 +773,8 @@ static Bool fprint_bbcc(VgFile *fp, BBCC* bbcc, AddrPos* last)
704773 /* get debug info of current instruction address and dump cost
705774 * if CLG_(clo).dump_bbs or file/line has changed
706775 */
707- if (! get_debug_pos ( bbcc , bb_addr (bb ) + instr_info -> instr_offset ,
708- & (newCost -> p ))) {
776+ Addr instr_addr = bb_addr (bb ) + instr_info -> instr_offset ;
777+ if (! get_debug_pos ( bbcc , instr_addr , & (newCost -> p ))) {
709778 /* if we don't have debug info, don't switch to file "???" */
710779 newCost -> p .file = bbcc -> cxt -> fn [0 ]-> file ;
711780 }
@@ -716,8 +785,10 @@ static Bool fprint_bbcc(VgFile *fp, BBCC* bbcc, AddrPos* last)
716785
717786 if (!CLG_ (is_zero_cost )( CLG_ (sets ).full , currCost -> cost )) {
718787 something_written = True ;
719-
720- fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file );
788+
789+ /* Output file position and inline function markers */
790+ fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file , bbcc );
791+
721792 fprint_fcost (fp , currCost , last );
722793 }
723794
@@ -741,11 +812,11 @@ static Bool fprint_bbcc(VgFile *fp, BBCC* bbcc, AddrPos* last)
741812 if (jcc_count > 0 ) {
742813 if (!CLG_ (is_zero_cost )( CLG_ (sets ).full , currCost -> cost )) {
743814 /* no need to switch buffers, as position is the same */
744- fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file );
815+ fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file , bbcc );
745816 fprint_fcost (fp , currCost , last );
746817 }
747818 get_debug_pos (bbcc , bb_addr (bb )+ instr_info -> instr_offset , & (currCost -> p ));
748- fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file );
819+ fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file , bbcc );
749820 something_written = True ;
750821 for (jcc = bbcc -> jmp [jmp ].jcc_list ; jcc ; jcc = jcc -> next_from ) {
751822 if (((jcc -> jmpkind != jk_Call ) && (jcc -> call_counter > 0 )) ||
@@ -773,17 +844,17 @@ static Bool fprint_bbcc(VgFile *fp, BBCC* bbcc, AddrPos* last)
773844 }
774845
775846 if ( (bbcc -> skipped &&
776- !CLG_ (is_zero_cost )(CLG_ (sets ).full , bbcc -> skipped )) ||
847+ !CLG_ (is_zero_cost )(CLG_ (sets ).full , bbcc -> skipped )) ||
777848 (jcc_count > 0 ) ) {
778-
849+
779850 if (!CLG_ (is_zero_cost )( CLG_ (sets ).full , currCost -> cost )) {
780851 /* no need to switch buffers, as position is the same */
781- fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file );
852+ fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file , bbcc );
782853 fprint_fcost (fp , currCost , last );
783854 }
784855
785856 get_debug_pos (bbcc , bb_jmpaddr (bb ), & (currCost -> p ));
786- fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file );
857+ fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file , bbcc );
787858 something_written = True ;
788859
789860 /* first, print skipped costs for calls */
@@ -810,8 +881,8 @@ static Bool fprint_bbcc(VgFile *fp, BBCC* bbcc, AddrPos* last)
810881 if (CLG_ (clo ).dump_bbs || CLG_ (clo ).dump_bb ) {
811882 if (!CLG_ (is_zero_cost )( CLG_ (sets ).full , currCost -> cost )) {
812883 something_written = True ;
813-
814- fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file );
884+
885+ fprint_apos (fp , & (currCost -> p ), last , bbcc -> cxt -> fn [0 ]-> file , bbcc );
815886 fprint_fcost (fp , currCost , last );
816887 }
817888 if (CLG_ (clo ).dump_bbs ) VG_ (fprintf )(fp , "\n" );
@@ -1417,7 +1488,7 @@ static void print_bbccs_of_thread(thread_info* ti)
14171488 if (!CLG_ (is_zero_cost )( CLG_ (sets ).full , ccSum [currSum ].cost )) {
14181489 /* no need to switch buffers, as position is the same */
14191490 fprint_apos (print_fp , & (ccSum [currSum ].p ), & lastAPos ,
1420- lastFnPos .cxt -> fn [0 ]-> file );
1491+ lastFnPos .cxt -> fn [0 ]-> file , 0 );
14211492 fprint_fcost (print_fp , & ccSum [currSum ], & lastAPos );
14221493 }
14231494
@@ -1437,6 +1508,7 @@ static void print_bbccs_of_thread(thread_info* ti)
14371508 init_fcost (& ccSum [0 ], 0 , 0 , 0 );
14381509 init_fcost (& ccSum [1 ], 0 , 0 , 0 );
14391510 currSum = 0 ;
1511+ last_inline_fn = 0 ; /* reset inline function tracking */
14401512 }
14411513
14421514 if (CLG_ (clo ).dump_bbs ) {
0 commit comments