tags:

views:

114

answers:

1

This is a most singular problem, with many interdisciplinary ramifications.

It focuses on this piece of code (file name mainpp.c):


#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
  int status;
  if (fork()) 
    {
      FILE *f=fopen("/tmp/gcc-trace","a");
      fprintf(f,"----------------------------------------------------------------\n");
      int i;
      for(i=0;i<argc;i++)
        {

          fprintf(f,"%s:",argv[i]);
        }
      wait(&status);
      fprintf(f,"\nstatus=%d",status);
      fprintf(f,"\n");
      fclose(f);
    }
  else 
    {
      execv("g++.old",argv);
    }
  sleep(10);
  return status;
}

This is used with a bash script:

#!/bin/sh

gcc -g main.c -o gcc
gcc -g mainpp.c -o g++
mv /usr/bin/gcc /usr/bin/gcc.old
mv /usr/bin/g++ /usr/bin/g++.old
cp ./gcc /usr/bin/gcc
cp ./g++ /usr/bin/g++

The purpose of this code ( and a corresponding main.c for gcc) is hopefully clear. it replaces g++ and logs calls to g++ plus all commandline arguments, it then proceeds to call the g++ compiler ( now called g++.old ).

The plan is use this to log all the calls to g++/gcc. ( Since make -n does not trace recursive makes, this is a way of capturing calls "in the wild". )

I tried this out on several programs and it worked well. ( Including compiling the program itself. ) I then tried it out on the project I was interested in, libapt-pkg-dev ( Ubuntu repository ).

The build seemed to go well but when I checked some executables were missing. Counting files in the project directory I find that an unlogged version produces 1373 whereas a logged version produces 1294. Making a list of these files, I discover that all the missing files are executables, shared libraries or object files.

Capturing the standard out of both logged makes and unlogged makes gives the same output. The recorded return value of all processes called by exec is 0.

I've placed sleeps in various positions in the code. They do not seem to make any difference. ( The code with the traced version seems to compile much faster per file. I suspected that the exec might have caused the program to terminate while leaving gcc running. I thought that might cause failure because some object files might not be finishing when others need them. )

I have only one more diagnostic to run to see if I can diagnose the problem and then I am out of ideas. Suggestions?

A: 

I'm not sure if this if this will solve your problem, but have you considered using strace instead of your custom code?

strace executes a command (or attaches to a running process) and lists all the system calls it makes. So for instance, instead of running make directly, you might run:

strace -f -q -e trace=execve make
  • -f means attach to new processes as they are forked
  • -q means suppress attach/detach messages
  • -e trace=execve means only report calls to execve

You can then grep through the output for messages about /usr/bin/gcc.

Jay Conrod
Actually i tried strace before I did this. Each gcc/g++ call had (IIRC) around 64 arguments, so the argument list was terminated.Nice try though, and one thing I didn't tray was doing an strace on the logged version. That might give me a hint as to the problems.
HandyGandy