Another long delay in updates as I’ve spent so much time on fixing one simple problem. The problem of jump tables being added to the end of objdump files. There was a lot of detective work in gdb that I don’t have anything tangible to show for the time spent. The amount of code needed to solve the problem was minimal. As with all the other phases of the project I’ve spent most of my time figuring out how the pieces of the puzzle fit together and reading other peoples code. This may be just the nature of large coding projects, as opposed to small college projects where a lot of code is written and there is no interaction with existing code.

INFO messages, that were once error messages, would appear showing size mismatches in the same symbols from different exe’s.

INFO: DesiredSymbols::createCoverageMap - Attempt to create unified
coverage maps for TOD_TICKS_PER_SECOND_method with different sizes
(/home/cpod/coverage_test/leon3/coverage/fsrfsbitmap01.exe/40 !=
/home/cpod/coverage_test/leon3/coverage/block01.exe/92)
INFO: DesiredSymbols::createCoverageMap - Attempt to create unified
coverage maps for TOD_TICKS_PER_SECOND_method with different sizes
(/home/cpod/coverage_test/leon3/coverage/fsrofs01.exe/92 !=
/home/cpod/coverage_test/leon3/coverage/block01.exe/40)
INFO: DesiredSymbols::createCoverageMap - Attempt to create unified
coverage maps for _Thread_queue_Extract_with_proxy with different
sizes (/home/cpod/coverage_test/leon3/coverage/ftp01.exe/12 !=
/home/cpod/coverage_test/leon3/coverage/base_sp.exe/248)
INFO: DesiredSymbols::createCoverageMap - Attempt to create unified
coverage maps for _Thread_queue_Extract_with_proxy with different
sizes (/home/cpod/coverage_test/leon3/coverage/gxx01.exe/248 !=
/home/cpod/coverage_test/leon3/coverage/base_sp.exe/12)
INFO: DesiredSymbols::createCoverageMap - Attempt to create unified
coverage maps for _Heap_Walk with different sizes
(/home/cpod/coverage_test/leon3/coverage/heapwalk.exe/1656 !=
/home/cpod/coverage_test/leon3/coverage/fileio.exe/1600)
...

They were mostly about block01.exe and base_sp.exe being matched with other exe’s. So I would pair those with other exe’s and try and produce just just one instance of the INFO message and then examine the objdumps and compare the symbols with the discrepancies.

block01.exe is 40 bytes

36363 4001659c <TOD_TICKS_PER_SECOND_method>:
36364
36365 uint32_t TOD_TICKS_PER_SECOND_method(void)
36366 {
36367   return (TOD_MICROSECONDS_PER_SECOND /
36368       rtems_configuration_get_microseconds_per_tick());
36369 }
36370 4001659c:   11 00 03 d0     sethi  %hi(0xf4000), %o0
36371 400165a0:   90 12 22 40     or  %o0, 0x240, %o0 ! f4240 <_TLS_Alignment+0xf423      f>
36372 400165a4:   03 10 00 6e     sethi  %hi(0x4001b800), %g1
36373 400165a8:   81 80 20 00     wr  %g0, %y
36374 400165ac:   c4 00 62 84     ld  [ %g1 + 0x284 ], %g2
36375 400165b0:   01 00 00 00     nop
36376 400165b4:   01 00 00 00     nop
36377 400165b8:   84 72 00 02     udiv  %o0, %g2, %g2
36378 400165bc:   81 c3 e0 08     retl
36379 400165c0:   90 10 00 02     mov  %g2, %o0
36380
36381 400165c4 <atexit>:

fsrfsbitmap01.exe  92 bytes

54655 40022d38 <TOD_TICKS_PER_SECOND_method>:
54656
54657 uint32_t TOD_TICKS_PER_SECOND_method(void)
54658 {
54659   return (TOD_MICROSECONDS_PER_SECOND /
54660       rtems_configuration_get_microseconds_per_tick());
54661 }
54662 40022d38:   11 00 03 d0     sethi  %hi(0xf4000), %o0
54663 40022d3c:   90 12 22 40     or  %o0, 0x240, %o0 ! f4240 <_TLS_Alignment+0xf423      f>
54664 40022d40:   03 10 00 c0     sethi  %hi(0x40030000), %g1
54665 40022d44:   81 80 20 00     wr  %g0, %y
54666 40022d48:   c4 00 62 a0     ld  [ %g1 + 0x2a0 ], %g2
54667 40022d4c:   01 00 00 00     nop
54668 40022d50:   01 00 00 00     nop
54669 40022d54:   84 72 00 02     udiv  %o0, %g2, %g2
54670 40022d58:   81 c3 e0 08     retl
54671 40022d5c:   90 10 00 02     mov  %g2, %o0
54672 40022d60:   40 02 30 04     call  400aed70 <__end+0x77d70>
54673 40022d64:   40 02 2f 70     call  400aeb24 <__end+0x77b24>
54674 40022d68:   40 02 2f 64     call  400aeaf8 <__end+0x77af8>
54675 40022d6c:   40 02 2f 58     call  400aeacc <__end+0x77acc>
54676 40022d70:   40 02 2f 4c     call  400aeaa0 <__end+0x77aa0>
54677 40022d74:   40 02 2f 44     call  400aea84 <__end+0x77a84>
54678 40022d78:   40 02 2f 38     call  400aea58 <__end+0x77a58>
54679 40022d7c:   40 02 2f 2c     call  400aea2c <__end+0x77a2c>
54680 40022d80:   40 02 2f 20     call  400aea00 <__end+0x77a00>
54681 40022d84:   40 02 2f 18     call  400ae9e4 <__end+0x779e4>
54682 40022d88:   40 02 2f 0c     call  400ae9b8 <__end+0x779b8>
54683 40022d8c:   40 02 2f 00     call  400ae98c <__end+0x7798c>
54684 40022d90:   40 02 2e f4     call  400ae960 <__end+0x77960>
54685
54686 40022d94 <rtems_rfs_dir__hash>:

As can be seen above a jump table is added to the symbol TOD_TICKS_PER_SECOND_method in fsrfsbitmap01.exe which creates the byte size discrepancy as the code that is processing this is looking for the next symbol to start to finalise the current symbol as the (new symbols address - 1).

448       * Look for the start of a symbol's objdump and extract
449       * offset and symbol (i.e. offset <symbolname>:).
450       */
451       items = sscanf(
452         line.c_str(),
453         "%x <%[^>]>%c",
454         &offset, symbol, &terminator1
455       );
456
457      /*
458       * If all items found, we are at the beginning of a symbol's objdump.
459       */
460       if ( (items == 3) && (terminator1 == ':') ) {
461
462         endAddress = executableInformation->getLoadAddress() + offset - 1;
463
464        /*
465         * If we are currently processing a symbol, finalize it.
466         */
467         if ( processSymbol ) {
468           finalizeSymbol(
469             executableInformation,
470             currentSymbol,
471             startAddress,
472             endAddress,
473             theInstructions
474           );
475         }
476
477        /*
478         * Start processing of a new symbol.
479         */
480         startAddress = 0;
481         currentSymbol = "";
482         processSymbol = false;
483         theInstructions.clear();
484
485        /*
486         * See if the new symbol is one that we care about.
487        \*/
488         if ( SymbolsToAnalyze->isDesired( symbol ) ) {
489           startAddress = executableInformation->getLoadAddress() + offset;
490           currentSymbol = symbol;
491           processSymbol = true;
492           theInstructions.push_back( lineInfo );
493         }
494       }

The other processing statement detects regular instruction lines from the body of a symbol.

      else if (processSymbol) {

        // See if it is the dump of an instruction.
        items = sscanf(
          inputBuffer,
          "%x%c\t%*[^\t]%c",
          &instructionOffset, &terminator1, &terminator2
        );

        // If it looks like an instruction ...
        if ((items == 3) && (terminator1 == ':') && (terminator2 == '\t')) {

          // update the line's information, save it and ...
          lineInfo.address =
           executableInformation->getLoadAddress() + instructionOffset;
          lineInfo.isInstruction = true;
          lineInfo.isNop         = isNop( inputBuffer, lineInfo.nopSize );
          lineInfo.isBranch      = isBranchLine( inputBuffer );
        }

        // Always save the line.
        theInstructions.push_back( lineInfo );

The problem was to come up with a check that was restrictive enough to catch all jump tables but not too retrictive that it cuts symbols short. It looked as if checking just for ‘__end’ would be good enough and it did chop the jump tables at the correct location but I later realised that the branch information had disappeared in the report. It must have been too loose and chopping lines up in other places as well.

There were also other jump tables that didn’t have this structure so what ended up being universal was ‘call’ and ‘+0x’ were all found in all tables. Along with the normal checks for an instruction line, if all 5 were found it was a jump table. The symbol could then be finalised as normal. We also needed to set processSymbol = false, which keeps track if we are in the middle of a symbol or finished with it. Then along with the 5 items checked, we check processSymbol to make sure only one line of the jump table is processed and then nothing is done until a new symbol starts again.

The solution consists of this scanning check for the five items mentioned.

436      /*
437       * See if it is a jump table.
438       */
439       found = sscanf(
440         line.c_str(),
441         "%x%c\t%\*[^\t]%c%s %*x %*[^+]%s",
442         &instructionOffset, &terminatorOne, &terminator2, instruction, ID
443       );
444       call = instruction;
445       jumpTableID = ID;

and then the multiple check if statement which looks complicated but it’s as simple as I could get it.

495      /*
496       * If it looks like a jump table...
497       */
498       else if ( (found == 5) && (terminatorOne == ':') && (terminator2 == '\t')
499                && (call.find( "call" ) != std::string::npos)
500                && (jumpTableID.find( "+0x" ) != std::string::npos)
501                && processSymbol )
502       {
503
504           endAddress = executableInformation->getLoadAddress() + offset - 1;
505
506          /*
507           * If we are currently processing a symbol, finalize it.
508           */
509           if ( processSymbol ) {
510             finalizeSymbol(
511               executableInformation,
512               currentSymbol,
513               startAddress,
514               endAddress,
515               theInstructions
516             );
517           }
518           processSymbol = false;
519       }

In the end the solution was simple enough but there was a lot of sleuthing in gdb checking variables, following the program around and many, many iterations of the above solution that did not work.

All error messages are cleared up now and I’ve gone through a quick code review with simple changes that I implemented. A more in depth second review of which I have fixed all issues, one of the major blockers here was the use of symlink and copying files as the methods are not portable with Linux, BSD and Windows. I’m working on a third review at the moment, some of which are large changes that will have to be implemented post-GSOC. I’m hopeful that the critical changes are doable in the time left and the code will get merged soon.