<commit_before>
#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <unistd.h>

#include <list>
#include <map>
#include <sstream>


// This is an example of using ptrace() to log syscalls called by a
// child process.

namespace {

// Flag which is set in the signal number for syscall entry/exit when
// the option PTRACE_O_TRACESYSGOOD is enabled.
const int kSysFlag = 0x80;

const char *SyscallName(int sysnum) {
  switch (sysnum) {
#define MAP(name) case __NR_##name: return #name;
    MAP(access)
    MAP(arch_prctl)
    MAP(brk)
    MAP(close)
    MAP(execve)
    MAP(exit)
    MAP(exit_group)
    MAP(fstat)
    MAP(mmap)
    MAP(mprotect)
    MAP(munmap)
    MAP(open)
    MAP(read)
    MAP(write)
    default: return "?";
  }
}

uintptr_t RoundUpPageSize(uintptr_t val) {
  uintptr_t page_size = getpagesize();
  return (val + page_size - 1) & ~(page_size - 1);
}

class MmapInfo {
 public:
  uintptr_t addr;
  size_t size;
  int prot;
  std::string filename;
  uint64_t file_offset;
};

class Ptracer {
  int pid_;
  std::list<MmapInfo> mappings_;
  std::map<int, std::string> fds_;
  FILE *info_fp_;

  uintptr_t ReadWord(uintptr_t addr) {
    errno = 0;
    uintptr_t value = ptrace(PTRACE_PEEKDATA, pid_, addr, 0);
    assert(errno == 0);
    return value;
  }

  char ReadByte(uintptr_t addr) {
    uintptr_t mask = sizeof(uintptr_t) - 1;
    uintptr_t word = ReadWord(addr & ~mask);
    return word >> ((addr & mask) * 8);
  }

  std::string ReadString(uintptr_t addr) {
    // TODO: Reading one byte at a time is inefficient (though reading
    // one word at a time is not great either).
    std::stringbuf buf;
    for (;;) {
      char ch = ReadByte(addr++);
      if (!ch)
        break;
      buf.sputc(ch);
    }
    return buf.str();
  }

 public:
  Ptracer(int pid): pid_(pid) {}

  void HandleSyscall(struct user_regs_struct *regs) {
    uintptr_t sysnum = regs->orig_rax;
    uintptr_t syscall_result = regs->rax;
    uintptr_t arg1 = regs->rdi;
    uintptr_t arg2 = regs->rsi;
    uintptr_t arg3 = regs->rdx;
    // uintptr_t arg4 = regs->r10;
    uintptr_t arg5 = regs->r8;
    uintptr_t arg6 = regs->r9;
    printf("syscall=%s (%i)\n", SyscallName(sysnum), (int) sysnum);

    if (syscall_result > -(uintptr_t) 0x1000) {
      // Syscall returned an error so should have had no effect.
      return;
    }

    switch (sysnum) {
      case __NR_open: {
        std::string filename(ReadString(arg1));
        printf("open: %s\n", filename.c_str());
        int fd_result = syscall_result;
        if (fd_result >= 0)
          fds_[fd_result] = filename;
        break;
      }
      case __NR_mmap: {
        MmapInfo map;
        map.addr = syscall_result;
        map.size = RoundUpPageSize(arg2);
        map.prot = arg3;
        // assert(arg4 == (MAP_ANON | MAP_PRIVATE));
        int fd_arg = arg5;
        if (fd_arg != -1) {
          assert(fds_.find(fd_arg) != fds_.end());
          map.filename = fds_[fd_arg];
        }
        map.file_offset = arg6;
        mappings_.push_back(map);
        break;
      }
    }
  }

  void Put(uint64_t val) {
    fwrite(&val, sizeof(val), 1, info_fp_);
  }

  void PutString(const std::string &str) {
    Put(str.size());
    fwrite(str.c_str(), str.size() + 1, 1, info_fp_);
  }

  void Dump() {
    FILE *mapfile = fopen("out_pages", "w");
    assert(mapfile);
    uintptr_t mapfile_offset = 0;

    info_fp_ = fopen("out_info", "w");
    assert(info_fp_);

    struct user_regs_struct regs;
    int rc = ptrace(PTRACE_GETREGS, pid_, 0, &regs);
    assert(rc == 0);
    Put(regs.rip);

    Put(mappings_.size());
    for (auto map : mappings_) {
      Put(map.addr);
      Put(map.size);
      Put(map.prot);<commit_msg>Implement close() and check that no FDs have been left open<commit_after>
#include <assert.h>
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <unistd.h>

#include <list>
#include <map>
#include <sstream>


// This is an example of using ptrace() to log syscalls called by a
// child process.

namespace {

// Flag which is set in the signal number for syscall entry/exit when
// the option PTRACE_O_TRACESYSGOOD is enabled.
const int kSysFlag = 0x80;

const char *SyscallName(int sysnum) {
  switch (sysnum) {
#define MAP(name) case __NR_##name: return #name;
    MAP(access)
    MAP(arch_prctl)
    MAP(brk)
    MAP(close)
    MAP(execve)
    MAP(exit)
    MAP(exit_group)
    MAP(fstat)
    MAP(mmap)
    MAP(mprotect)
    MAP(munmap)
    MAP(open)
    MAP(read)
    MAP(write)
    default: return "?";
  }
}

uintptr_t RoundUpPageSize(uintptr_t val) {
  uintptr_t page_size = getpagesize();
  return (val + page_size - 1) & ~(page_size - 1);
}

class MmapInfo {
 public:
  uintptr_t addr;
  size_t size;
  int prot;
  std::string filename;
  uint64_t file_offset;
};

class Ptracer {
  int pid_;
  std::list<MmapInfo> mappings_;
  std::map<int, std::string> fds_;
  FILE *info_fp_;

  uintptr_t ReadWord(uintptr_t addr) {
    errno = 0;
    uintptr_t value = ptrace(PTRACE_PEEKDATA, pid_, addr, 0);
    assert(errno == 0);
    return value;
  }

  char ReadByte(uintptr_t addr) {
    uintptr_t mask = sizeof(uintptr_t) - 1;
    uintptr_t word = ReadWord(addr & ~mask);
    return word >> ((addr & mask) * 8);
  }

  std::string ReadString(uintptr_t addr) {
    // TODO: Reading one byte at a time is inefficient (though reading
    // one word at a time is not great either).
    std::stringbuf buf;
    for (;;) {
      char ch = ReadByte(addr++);
      if (!ch)
        break;
      buf.sputc(ch);
    }
    return buf.str();
  }

 public:
  Ptracer(int pid): pid_(pid) {}

  void HandleSyscall(struct user_regs_struct *regs) {
    uintptr_t sysnum = regs->orig_rax;
    uintptr_t syscall_result = regs->rax;
    uintptr_t arg1 = regs->rdi;
    uintptr_t arg2 = regs->rsi;
    uintptr_t arg3 = regs->rdx;
    // uintptr_t arg4 = regs->r10;
    uintptr_t arg5 = regs->r8;
    uintptr_t arg6 = regs->r9;
    printf("syscall=%s (%i)\n", SyscallName(sysnum), (int) sysnum);

    if (syscall_result > -(uintptr_t) 0x1000) {
      // Syscall returned an error so should have had no effect.
      return;
    }

    switch (sysnum) {
      case __NR_open: {
        std::string filename(ReadString(arg1));
        printf("open: %s\n", filename.c_str());
        int fd_result = syscall_result;
        if (fd_result >= 0)
          fds_[fd_result] = filename;
        break;
      }
      case __NR_close: {
        fds_.erase(arg1);
        break;
      }
      case __NR_mmap: {
        MmapInfo map;
        map.addr = syscall_result;
        map.size = RoundUpPageSize(arg2);
        map.prot = arg3;
        // assert(arg4 == (MAP_ANON | MAP_PRIVATE));
        int fd_arg = arg5;
        if (fd_arg != -1) {
          assert(fds_.find(fd_arg) != fds_.end());
          map.filename = fds_[fd_arg];
        }
        map.file_offset = arg6;
        mappings_.push_back(map);
        break;
      }
    }
  }

  void Put(uint64_t val) {
    fwrite(&val, sizeof(val), 1, info_fp_);
  }

  void PutString(const std::string &str) {
    Put(str.size());
    fwrite(str.c_str(), str.size() + 1, 1, info_fp_);
  }

  void Dump() {
    // We don't support restoring FDs yet, so no FDs must be left open.
    assert(fds_.size() == 0);

    FILE *mapfile = fopen("out_pages", "w");
    assert(mapfile);
    uintptr_t mapfile_offset = 0;

    info_fp_ = fopen("out_info", "w");
    assert(info_fp_);

    struct user_regs_struct regs;
    int rc = ptrace(PTRACE_GETREGS, pid_, 0, &regs);
    assert(rc == 0);
    Put(regs.rip);

    Put(mappings_.size());
    for (auto map : mappings_) {
      Put(map.addr);
      Put(map.size);
      Put(map.prot);
{'fraction_non_alphanumeric': 0.13724007561436674, 'fraction_numerical': 0.011090107120352867, 'mean_word_length': 2.6706753006475488, 'pattern_counts': {'":': 0, '<': 33, '<?xml version=': 0, '>': 57, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1483580', 'n_tokens_mistral': 3119, 'n_tokens_neox': 2937, 'n_words': 712}