Question

Je suis en train d'écrire un enregistreur de bibliothèque en C et je suis en train d'essayer d'obtenir un meilleur retour de trace de la sortie en utilisant addr2line.Pour ce faire, j'ai besoin d'être en mesure d'obtenir le chemin d'accès de l'exécutable en cours.Pour le moment, je suis juste inquiet à propos de linux, mais sera en tournage pour Mac OS soutien.

Pour la prise en charge de linux, je suis en train d'utiliser readlink() et /proc/self/exe pour résoudre l'exécutable en cours de chemin:

static char** getPrettyBacktrace( void* addresses[], int array_size ) {
    // Used to return the strings generated from the addresses
    char** backtrace_strings = (char**)malloc( sizeof( char ) * array_size );
    for( int i = 0; i < array_size; i ++ ) {
        backtrace_strings[i] = (char*)malloc( sizeof( char ) * 255 );
    }

    // Will hold the command to be used
    char* command_string    = (char*)malloc( 255 );
    char* exe_path          = (char*)malloc( 255 );

    // Used to check if an error occured while setting up command
    bool error = false;

    // Check if we are running on Mac OS or not, and select appropriate command
    char* command;
    #ifdef __APPLE__
        // Check if 'gaddr2line' function is available, if not exit
        if( !system( "which gaddr2line > /dev/null 2>&1" ) ) {
            command = "gaddr2line -Cfspe";
            // TODO: get path for mac with 'proc_pidpath'
        } else {
            writeLog( SIMPLOG_LOGGER, "Function 'gaddr2line' unavailable. Defaulting to standard backtrace. Please install package 'binutils' for better stacktrace output." );
            error = true;
        }
    #else
        // Check if 'addr2line' function is available, if not exit
        if( !system( "which addr2line > /dev/null 2>&1" ) ) {
            command = "addr2line -Cfspe";
            if( readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) ) < 0 ) {
                writeLog( SIMPLOG_LOGGER, "Unable to get execution path. Defaulting to standard backtrace." );
                error = true;
            }
        } else {
            writeLog( SIMPLOG_LOGGER, "Function 'addr2line' unavailable. Defaulting to standard backtrace. Please install package 'binutils' for better stacktrace output." );
            error = true;
        }
    #endif

    // If an error occured, exit now
    if( error ) {
        free( backtrace_strings );
        free( command_string );
        free( exe_path );
        return NULL;
    }

    for( int i = 0; i < array_size; i++ ) {
        // Compose the complete command to execute
        sprintf( command_string, "%s %s %X", command, exe_path, addresses[i] );

        // Execute the command
        FILE* line = popen( command_string, "r" );

        // Get the size of the command output
        int line_size = fseek( line, 0, SEEK_END );

        // Read the output into the return string
        fgets( backtrace_strings[i] , line_size, line );

        // Close the command pipe
        pclose( line );
    }

    return backtrace_strings;
}

Le chemin retourné par readlink() est: /home/nax��?.la première partie est correcte: /home/na, mais tout ce qui suit est du pur charabia.

Pourquoi suis-je incapable d'obtenir l'exécution en cours de chemin dans ce sens?

Était-ce utile?

La solution

char* exe_path          = (char*)malloc( 255 );
// ...
readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) )

exe_path est un pointeur, donc c'est la taille sera égal à sizeof(char*) (4 ou 8), pas 255.

changement exe_path pour char[255] ou de modification de l'appel à sizeof

btw, readlink ne pas ajouter de l'octet NUL, de sorte que vous devriez faire quelque chose comme ceci:

len = readlink( "/proc/self/exe", exe_path, sizeof( exe_path ) )
exe_path[len] = 0;
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top