cb424d7448
verify-patch-sanity.py validates every active recipe .patch has internally- consistent hunk line counts — catching the 'malformed patch at line N' failure at commit/CI/preflight time instead of hours into a cook. This cycle hit that class three times (qtwaylandscanner, sddm, xwayland), each only discovered when cookbook tried to apply the patch. Running it across the repo found 29 latent malformed patches (validated against GNU patch: e.g. relibc/P3-sysv-ipc reproduces 'malformed patch at line 22'). They were harmless only because they sit in vendored recipes (baked, not re- applied) — but would fail on any version-bump re-derivation. --fix recounts the hunk headers (body untouched) and repaired all 29. Wired into build-preflight.sh (Phase 1.0D) and redbear-ci.yml, with a unit test (test-patch-sanity.sh). Skips archived/legacy trees and unvalidatable formats (empty placeholders, bare-@@ git hunks).
107 lines
2.5 KiB
C
107 lines
2.5 KiB
C
//===-- ptrace_example.c --------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#include <asm/ptrace.h>
|
|
#include <linux/elf.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <sys/prctl.h>
|
|
#include <sys/ptrace.h>
|
|
#include <sys/uio.h>
|
|
#include <sys/wait.h>
|
|
#include <unistd.h>
|
|
|
|
// The demo program shows how to do basic ptrace operations without lldb
|
|
// or lldb-server. For the purposes of experimentation or reporting bugs
|
|
// in kernels.
|
|
//
|
|
// It is AArch64 Linux specific, adapt as needed.
|
|
//
|
|
// Expected output:
|
|
// Before breakpoint
|
|
// After breakpoint
|
|
|
|
void inferior() {
|
|
if (ptrace(PTRACE_TRACEME, 0, 0, 0) < 0) {
|
|
perror("ptrace");
|
|
return;
|
|
}
|
|
|
|
printf("Before breakpoint\n");
|
|
|
|
// Go into debugger. Instruction replaced with nop later.
|
|
// We write 2 instuctions because POKETEXT works with
|
|
// 64 bit values and we don't want to overwrite the
|
|
// call to printf accidentally.
|
|
asm volatile("BRK #0 \n nop");
|
|
|
|
printf("After breakpoint\n");
|
|
}
|
|
|
|
void debugger(pid_t child) {
|
|
int wait_status;
|
|
// Wait until it hits the breakpoint.
|
|
wait(&wait_status);
|
|
|
|
while (WIFSTOPPED(wait_status)) {
|
|
if (WIFEXITED(wait_status)) {
|
|
printf("inferior exited normally\n");
|
|
return;
|
|
}
|
|
|
|
// Read general purpose registers to find the PC value.
|
|
struct user_pt_regs regs;
|
|
struct iovec io;
|
|
io.iov_base = ®s;
|
|
io.iov_len = sizeof(regs);
|
|
if (ptrace(PTRACE_GETREGSET, child, NT_PRSTATUS, &io) < 0) {
|
|
printf("getregset failed\n");
|
|
return;
|
|
}
|
|
|
|
// Replace brk #0 / nop with nop / nop by writing to memory
|
|
// at the current PC.
|
|
uint64_t replace = 0xd503201fd503201f;
|
|
if (ptrace(PTRACE_POKETEXT, child, regs.pc, replace) < 0) {
|
|
printf("replacing bkpt failed\n");
|
|
return;
|
|
}
|
|
|
|
// Single step over where the brk was.
|
|
if (ptrace(PTRACE_SINGLESTEP, child, 0, 0) < 0) {
|
|
perror("ptrace");
|
|
return;
|
|
}
|
|
|
|
// Wait for single step to be done.
|
|
wait(&wait_status);
|
|
|
|
// Run to completion.
|
|
if (ptrace(PTRACE_CONT, child, 0, 0) < 0) {
|
|
perror("ptrace");
|
|
return;
|
|
}
|
|
|
|
// Wait to see that the inferior exited.
|
|
wait(&wait_status);
|
|
}
|
|
}
|
|
|
|
int main() {
|
|
pid_t child = fork();
|
|
|
|
if (child == 0)
|
|
inferior();
|
|
else if (child > 0)
|
|
debugger(child);
|
|
else
|
|
return -1;
|
|
|
|
return 0;
|
|
}
|