brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.7 KiB · ff1fcca Raw
109 lines · cpp
1#include <errno.h>2#include <fcntl.h>3#include <signal.h>4#include <stdio.h>5#include <stdlib.h>6#include <string.h>7#include <unistd.h>8 9#include <sys/types.h>10#include <sys/ptrace.h>11#include <sys/stat.h>12#include <sys/wait.h>13 14#if defined(PTRACE_ATTACH)15#define ATTACH_REQUEST PTRACE_ATTACH16#define DETACH_REQUEST PTRACE_DETACH17#elif defined(PT_ATTACH)18#define ATTACH_REQUEST PT_ATTACH19#define DETACH_REQUEST PT_DETACH20#else21#error "Unsupported platform"22#endif23 24bool writePid (const char* file_name, const pid_t pid)25{26    char *tmp_file_name = (char *)malloc(strlen(file_name) + 16);27    strcpy(tmp_file_name, file_name);28    strcat(tmp_file_name, "_tmp");29    int fd = open (tmp_file_name, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);30    if (fd == -1)31    {32        fprintf (stderr, "open(%s) failed: %s\n", tmp_file_name, strerror (errno));33        free(tmp_file_name);34        return false;35    }36    char buffer[64];37    snprintf (buffer, sizeof(buffer), "%ld", (long)pid);38 39    bool res = true;40    if (write (fd, buffer, strlen (buffer)) == -1)41    {42        fprintf (stderr, "write(%s) failed: %s\n", buffer, strerror (errno));43        res = false;44    }45    close (fd);46 47    if (rename (tmp_file_name, file_name) == -1)48    {49        fprintf (stderr, "rename(%s, %s) failed: %s\n", tmp_file_name, file_name, strerror (errno));50        res = false;51    }52    free(tmp_file_name);53 54    return res;55}56 57void signal_handler (int)58{59}60 61int main (int argc, char const *argv[])62{63    if (argc < 2)64    {65        fprintf (stderr, "invalid number of command line arguments\n");66        return 1;67    }68 69    const pid_t pid = fork ();70    if (pid == -1)71    {72        fprintf (stderr, "fork failed: %s\n", strerror (errno));73        return 1;74    }75 76    if (pid > 0)77    {78        // Make pause call to return when a signal is received. Normally this happens when the79        // test runner tries to terminate us.80        signal (SIGHUP, signal_handler);81        signal (SIGTERM, signal_handler);82        if (ptrace (ATTACH_REQUEST, pid, NULL, 0) == -1)83        {84            fprintf (stderr, "ptrace(ATTACH) failed: %s\n", strerror (errno));85        }86        else87        {88            if (writePid (argv[1], pid))89                pause ();  // Waiting for the debugger trying attach to the child.90 91            if (ptrace (DETACH_REQUEST, pid, NULL, 0) != 0)92                fprintf (stderr, "ptrace(DETACH) failed: %s\n", strerror (errno));93        }94 95        kill (pid, SIGTERM);96        int status = 0;97        if (waitpid (pid, &status, 0) == -1)98            fprintf (stderr, "waitpid failed: %s\n", strerror (errno));99    }100    else101    {102        // child inferior.103        pause ();104    }105 106    printf ("Exiting now\n");107    return 0;108}109