brintos

brintos / llvm-project-archived public Read only

0
0
Text · 2.5 KiB · d458ad1 Raw
107 lines · c
1//===-- ptrace_example.c --------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include <asm/ptrace.h>10#include <linux/elf.h>11#include <stdint.h>12#include <stdio.h>13#include <sys/prctl.h>14#include <sys/ptrace.h>15#include <sys/uio.h>16#include <sys/wait.h>17#include <unistd.h>18 19// The demo program shows how to do basic ptrace operations without lldb20// or lldb-server. For the purposes of experimentation or reporting bugs21// in kernels.22//23// It is AArch64 Linux specific, adapt as needed.24//25// Expected output:26// Before breakpoint27// After breakpoint28 29void inferior() {30  if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {31    perror("ptrace");32    return;33  }34 35  printf("Before breakpoint\n");36 37  // Go into debugger. Instruction replaced with nop later.38  // We write 2 instuctions because POKETEXT works with39  // 64 bit values and we don't want to overwrite the40  // call to printf accidentally.41  asm volatile("BRK #0 \n nop");42 43  printf("After breakpoint\n");44}45 46void debugger(pid_t child) {47  int wait_status;48  // Wait until it hits the breakpoint.49  wait(&wait_status);50 51  while (WIFSTOPPED(wait_status)) {52    if (WIFEXITED(wait_status)) {53      printf("inferior exited normally\n");54      return;55    }56 57    // Read general purpose registers to find the PC value.58    struct user_pt_regs regs;59    struct iovec io;60    io.iov_base = &regs;61    io.iov_len = sizeof(regs);62    if (ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &io) < 0) {63      printf("getregset failed\n");64      return;65    }66 67    // Replace brk #0 / nop with nop / nop by writing to memory68    // at the current PC.69    uint64_t replace = 0xd503201fd503201f;70    if (ptrace(PTRACE_POKETEXT, child, regs.pc, replace) < 0) {71      printf("replacing bkpt failed\n");72      return;73    }74 75    // Single step over where the brk was.76    if (ptrace(PTRACE_SINGLESTEP, child, 0, 0) < 0) {77      perror("ptrace");78      return;79    }80 81    // Wait for single step to be done.82    wait(&wait_status);83 84    // Run to completion.85    if (ptrace(PTRACE_CONT, child, 0, 0) < 0) {86      perror("ptrace");87      return;88    }89 90    // Wait to see that the inferior exited.91    wait(&wait_status);92  }93}94 95int main() {96  pid_t child = fork();97 98  if (child == 0)99    inferior();100  else if (child > 0)101    debugger(child);102  else103    return -1;104 105  return 0;106}107