From b4ec1b2a0d90b209bc5f4a0e779e633f7ed069ce Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Sat, 4 Nov 2023 16:41:23 +0000 Subject: [PATCH] Speed up line filtering for large codebases --- Src/loadelf.c | 110 ++++++++++++++++++++++++++--------------------- Src/readsource.c | 54 ++++++++++++----------- 2 files changed, 90 insertions(+), 74 deletions(-) diff --git a/Src/loadelf.c b/Src/loadelf.c index 4ac4ffc9..60fb1f7c 100644 --- a/Src/loadelf.c +++ b/Src/loadelf.c @@ -357,7 +357,7 @@ void _dwarf_print( void *p, const char *line ) static void _processFunctionDie( struct symbol *p, Dwarf_Debug dbg, Dwarf_Die die, int filenameN, int producerN, Dwarf_Addr cu_base_addr ) { - char *name = ""; + char *name = NULL; Dwarf_Addr h = 0; Dwarf_Addr l = 0; enum Dwarf_Form_Class formclass; @@ -368,12 +368,12 @@ static void _processFunctionDie( struct symbol *p, Dwarf_Debug dbg, Dwarf_Die di struct symbolFunctionStore *newFunc; attr_tag = DW_AT_inline; - + /* if ( dwarf_attr( die, attr_tag, &attr_data, 0 ) == DW_DLV_OK ) { return; } - + */ /* See if this is an inline die usage */ attr_tag = DW_AT_abstract_origin; @@ -386,7 +386,7 @@ static void _processFunctionDie( struct symbol *p, Dwarf_Debug dbg, Dwarf_Die di dwarf_attr( die, attr_tag, &attr_data, 0 ); dwarf_global_formref( attr_data, &abstract_origin_offset, 0 ); dwarf_offdie_b( dbg, abstract_origin_offset, IS_INFO, &abstract_origin_die, 0 ); - fprintf( stderr, "Instance at %08x...%08x\n\n\n", ( uint32_t )l, ( uint32_t )h ); + // fprintf( stderr, "Instance at %08x...%08x\n\n\n", ( uint32_t )l, ( uint32_t )h ); isinline = true; } else @@ -400,27 +400,27 @@ static void _processFunctionDie( struct symbol *p, Dwarf_Debug dbg, Dwarf_Die di h += l; } - if ( l && ( l != h ) ) - { - if ( DW_DLV_OK != dwarf_diename( die, &name, 0 ) ) - { - /* Name will be hidden in a specification reference */ - attr_tag = DW_AT_specification; - - if ( dwarf_attr( die, attr_tag, &attr_data, 0 ) == DW_DLV_OK ) - { - Dwarf_Off specification_offset; - Dwarf_Die specification_die; - dwarf_attr( die, attr_tag, &attr_data, 0 ); - - if ( DW_DLV_OK == dwarf_global_formref( attr_data, &specification_offset, 0 ) ) - { - dwarf_offdie_b( dbg, specification_offset, IS_INFO, &specification_die, 0 ); - dwarf_diename( specification_die, &name, 0 ); - } + if ( DW_DLV_OK != dwarf_diename( die, &name, 0 ) ) + { + /* Name will be hidden in a specification reference */ + attr_tag = DW_AT_specification; + + if ( dwarf_attr( die, attr_tag, &attr_data, 0 ) == DW_DLV_OK ) + { + Dwarf_Off specification_offset; + Dwarf_Die specification_die; + dwarf_attr( die, attr_tag, &attr_data, 0 ); + + if ( DW_DLV_OK == dwarf_global_formref( attr_data, &specification_offset, 0 ) ) + { + dwarf_offdie_b( dbg, specification_offset, IS_INFO, &specification_die, 0 ); + dwarf_diename( specification_die, &name, 0 ); + } } } + if ( name && l && h ) + { p->func = ( struct symbolFunctionStore ** )realloc( p->func, sizeof( struct symbolFunctionStore * ) * ( p->nfunc + 1 ) ); newFunc = p->func[p->nfunc] = ( struct symbolFunctionStore * )calloc( 1, sizeof( struct symbolFunctionStore ) ); newFunc->isinline = isinline; @@ -450,6 +450,8 @@ static void _processFunctionDie( struct symbol *p, Dwarf_Debug dbg, Dwarf_Die di dwarf_formudata( attr_data, &no, 0 ); newFunc->startcol = no; } + + // fprintf(stderr,"%s %08x %08x %d,%d\n",name,l,h,newFunc->startline,newFunc->startcol); } } @@ -609,46 +611,53 @@ static bool _readLines( struct symbol *p ) qsort( p->func, p->nfunc, sizeof( struct symbolFunctionStore * ), _compareFunc ); /* Combine addresses in the lines table which have the same memory location...those aren't too useful for us */ + + int nlines = 0; + struct symbolLineStore **nls = NULL; + for ( int i = 1; i < p->nlines; i++ ) { - while ( ( i < p->nlines ) && ( ( p->line[i]->filename == p->line[i - 1]->filename ) ) && ( ( p->line[i]->lowaddr == p->line[i - 1]->lowaddr ) ) ) - { - /* This line needs to be freed in memory 'cos otherwise there is no reference to it anywhere */ - free( p->line[i - 1] ); - - /* ...and move the following lines down */ - for ( int j = i; j < p->nlines; j++ ) - { - p->line[j - 1] = p->line[j]; + nls = ( struct symbolLineStore ** )realloc( nls, sizeof( struct symbolLineStore * ) * ( nlines + 1 ) ); + struct symbolLineStore *nl = nls[nlines++] = ( struct symbolLineStore * )calloc( 1, sizeof( struct symbolLineStore ) ); + + while ( ( i < p->nlines ) && + ( ( p->line[i]->filename == p->line[i - 1]->filename ) ) && + ( ( p->line[i]->lowaddr == p->line[i - 1]->lowaddr ) ) ) + { + /* This line needs to be freed in memory 'cos otherwise there is no reference to it anywhere */ + free( p->line[i - 1] ); + i++; } - - p->nlines--; - } + nl = p->line[i]; } + free(p->line); + p->line = nls; + p->nlines = nlines; + nlines = 0; + nls = NULL; + /* Now do the same for lines with the same line number and file */ /* We can also set the high memory extent for each line here */ for ( int i = 1; i < p->nlines; i++ ) { - while ( ( i < p->nlines ) && - ( p->line[i]->startline == p->line[i - 1]->startline ) && - ( p->line[i]->filename == p->line[i - 1]->filename ) ) + nls = ( struct symbolLineStore ** )realloc( nls, sizeof( struct symbolLineStore * ) * ( nlines + 1 ) ); + struct symbolLineStore *nl = nls[nlines++] = ( struct symbolLineStore * )calloc( 1, sizeof( struct symbolLineStore ) ); + nl = p->line[i]; + + while ( ( i < p->nlines ) && + ( p->line[i]->startline == nl->startline ) && + ( p->line[i]->filename == nl->filename ) ) { - - p->line[i]->lowaddr = p->line[i - 1]->lowaddr; - free( p->line[i - 1] ); - - for ( int j = i; j < p->nlines; j++ ) - { - p->line[j - 1] = p->line[j]; - } - - p->nlines--; - } - - p->line[i - 1]->highaddr = p->line[i]->lowaddr - 1; + free(p->line[i]); + i++; + } } + free(p->line); + p->line = nls; + p->nlines = nlines; + if ( !p->nlines ) { fprintf( stderr, "No lines found in file\n" ); @@ -1246,6 +1255,7 @@ void main( int argc, char *argv[] ) exit( -1 ); } + fprintf( stderr, "Got functions" EOL); _listFunctions( p, false ); exit( -1 ); diff --git a/Src/readsource.c b/Src/readsource.c index ca9b7adb..c564e709 100644 --- a/Src/readsource.c +++ b/Src/readsource.c @@ -53,36 +53,42 @@ char *readsourcefile( char *path, size_t *l ) /* Return either a malloced buffer containing the source file, or NULL if the file isn't available */ { - FILE *fd; + FILE *fd = NULL; + static bool prettyPrinterTested = false; char commandLine[MAX_LINE_LEN]; bool isProcess = true; - char *retBuffer; - - size_t insize; - - /* Try and grab the file via a prettyprinter. If that doesn't work, grab it via cat */ - if ( getenv( "ORB_PRETTYPRINTER" ) ) - { - /* We have an environment variable containing the prettyprinter...lets use that */ - snprintf( commandLine, MAX_LINE_LEN, "%s %s", getenv( "ORB_PRETTYPRINTER" ), path ); - } - else - { - /* No environment variable, use the default */ - snprintf( commandLine, MAX_LINE_LEN, "source-highlight -f esc -o STDOUT -i %s 2>/dev/null", path ); - } - - fd = popen( commandLine, "r" ); - - /* Perform a single read...this will lead to a zero length read if the command wasn't valid */ - retBuffer = ( char * )malloc( BLOCKSIZE ); - insize = fread( retBuffer, 1, BLOCKSIZE, fd ); - + char *retBuffer = ( char * )malloc( BLOCKSIZE ); + size_t insize = 0; + + if (!prettyPrinterTested) + { + /* Try and grab the file via a prettyprinter. If that doesn't work, grab it via cat */ + if ( getenv( "ORB_PRETTYPRINTER" ) ) + { + /* We have an environment variable containing the prettyprinter...lets use that */ + snprintf( commandLine, MAX_LINE_LEN, "%s %s", getenv( "ORB_PRETTYPRINTER" ), path ); + } + else + { + /* No environment variable, use the default */ + snprintf( commandLine, MAX_LINE_LEN, "source-highlight -f esc -o STDOUT -i %s 2>/dev/null", path ); + } + + fd = popen( commandLine, "r" ); + + /* Perform a single read...this will lead to a zero length read if the command wasn't valid */ + insize = fread( retBuffer, 1, BLOCKSIZE, fd ); + } + if ( !insize ) { - pclose( fd ); + if (fd) + { + pclose( fd ); + } isProcess = false; + prettyPrinterTested = true; if ( ( fd = fopen( path, "r" ) ) ) {