Repository: wolfpld/tracy
File: client/TracySysTrace.cpp (C++)

Code before:
            char buf[8] = { 0 };
            int read_len = read( read_end, buf, sizeof buf );
            if (read_len >= 2) {
                success = !memcmp(buf, "0\n", 2 );
            }
            close( read_end );
            waitpid( pid, nullptr, 0 );
        }
    }
    return success;
}

// Enum identifying a method for running a command as root.
enum class HowToRunAsRoot {
    // Our process is already root (getuid()==0). Nothing else is needed.
    AlreadyRunningAsRoot,
    // The way to run a command as root is: `su -c 'command'`.
    // In this case, `command` is interpreted by a shell (not just exec'd).
    SuDashC,
    // The way to run a command as root is: `su root 'command'`.
    // In this case, `command` is just exec'd. If any interpretation by a
    // shell is needed, it needs to be done explicitly, like:
    //   `su root sh -c 'command'`.
    SuRoot,
    // We don't know how to run a command as root on this device.
    DontKnow
};

// Internal implementation helper for GetHowToRunAsRoot.
//
// Functionally equivalent to it, but much more expensive (no caching).
static HowToRunAsRoot ExpensivelyDetermineHowToRunAsRoot() {
    if (getuid() == 0) {
        return HowToRunAsRoot::AlreadyRunningAsRoot;
    }
    if (TrySuCommandFlag("-c")) {
        return HowToRunAsRoot::SuDashC;
    }
    if (TrySuCommandFlag("root")) {
        return HowToRunAsRoot::SuRoot;
    }
    return HowToRunAsRoot::DontKnow;
}

// Internal implementation helper for ExeclpAsRoot and SystemAsRoot.
//
// Returns how to run a command as root. Determines that once, then
// caches the result. Reentrant thanks to C++11 specifying the
// initialization of static locals as reentrant.
static HowToRunAsRoot GetHowToRunAsRoot() {
    static const HowToRunAsRoot value = ExpensivelyDetermineHowToRunAsRoot();

Review comment (bug):
This should be handled as a failure to setup kernel tracing, in `SysTraceStart()`.

Code after:
            {
                close( pipefd[0] );
                execlp( "su", "su", "root", "sh", "-c", "cat > /data/tracy_systrace", (char*)nullptr );
                exit( 1 );
            }
        }
        else if( pid > 0 )
        {
            // parent
            close( pipefd[0] );

#ifdef __aarch64__
            write( pipefd[1], tracy_systrace_aarch64_data, tracy_systrace_aarch64_size );
#else
            write( pipefd[1], tracy_systrace_armv7_data, tracy_systrace_armv7_size );
#endif
            close( pipefd[1] );
            waitpid( pid, nullptr, 0 );

            system( "su root sh -c 'chmod 700 /data/tracy_systrace'" );
        }
    }
}
#endif

bool SysTraceStart( int64_t& samplingPeriod )
{
#ifndef CLOCK_MONOTONIC_RAW
    return false;
#endif

    if( !TraceWrite( TracingOn, sizeof( TracingOn ), "0", 2 ) ) return false;
    if( !TraceWrite( CurrentTracer, sizeof( CurrentTracer ), "nop", 4 ) ) return false;
    TraceWrite( TraceOptions, sizeof( TraceOptions ), "norecord-cmd", 13 );
    TraceWrite( TraceOptions, sizeof( TraceOptions ), "norecord-tgid", 14 );
    TraceWrite( TraceOptions, sizeof( TraceOptions ), "noirq-info", 11 );
    TraceWrite( TraceOptions, sizeof( TraceOptions ), "noannotate", 11 );
#if defined TRACY_HW_TIMER && ( defined __i386 || defined _M_IX86 || defined __x86_64__ || defined _M_X64 )
    if( !TraceWrite( TraceClock, sizeof( TraceClock ), "x86-tsc", 8 ) ) return false;
#else
    if( !TraceWrite( TraceClock, sizeof( TraceClock ), "mono_raw", 9 ) ) return false;
#endif
    if( !TraceWrite( SchedSwitch, sizeof( SchedSwitch ), "1", 2 ) ) return false;
    if( !TraceWrite( SchedWakeup, sizeof( SchedWakeup ), "1", 2 ) ) return false;
    if( !TraceWrite( BufferSizeKb, sizeof( BufferSizeKb ), "4096", 5 ) ) return false;

#if defined __ANDROID__ && ( defined __aarch64__ || defined __ARM_ARCH )
    SysTraceInjectPayload();
#endif

    if( !TraceWrite( TracingOn, sizeof( TracingOn ), "1", 2 ) ) return false;