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).
140 lines
5.0 KiB
Python
Executable File
140 lines
5.0 KiB
Python
Executable File
#!/usr/bin/env python
|
|
|
|
# ----------------------------------------------------------------------
|
|
# Be sure to add the python path that points to the LLDB shared library.
|
|
# On MacOSX csh, tcsh:
|
|
# setenv PYTHONPATH /Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python
|
|
# On MacOSX sh, bash:
|
|
# export PYTHONPATH=/Developer/Library/PrivateFrameworks/LLDB.framework/Resources/Python
|
|
# ----------------------------------------------------------------------
|
|
|
|
import lldb
|
|
import os
|
|
import sys
|
|
|
|
|
|
def disassemble_instructions(insts):
|
|
for i in insts:
|
|
print(i)
|
|
|
|
|
|
def usage():
|
|
print("Usage: disasm.py [-n name] executable-image")
|
|
print(" By default, it breaks at and disassembles the 'main' function.")
|
|
sys.exit(0)
|
|
|
|
|
|
if len(sys.argv) == 2:
|
|
fname = "main"
|
|
exe = sys.argv[1]
|
|
elif len(sys.argv) == 4:
|
|
if sys.argv[1] != "-n":
|
|
usage()
|
|
else:
|
|
fname = sys.argv[2]
|
|
exe = sys.argv[3]
|
|
else:
|
|
usage()
|
|
|
|
# Create a new debugger instance
|
|
debugger = lldb.SBDebugger.Create()
|
|
|
|
# When we step or continue, don't return from the function until the process
|
|
# stops. We do this by setting the async mode to false.
|
|
debugger.SetAsync(False)
|
|
|
|
# Create a target from a file and arch
|
|
print("Creating a target for '%s'" % exe)
|
|
|
|
target = debugger.CreateTargetWithFileAndArch(exe, lldb.LLDB_ARCH_DEFAULT)
|
|
|
|
if target:
|
|
# If the target is valid set a breakpoint at main
|
|
main_bp = target.BreakpointCreateByName(fname, target.GetExecutable().GetFilename())
|
|
|
|
print(main_bp)
|
|
|
|
# Launch the process. Since we specified synchronous mode, we won't return
|
|
# from this function until we hit the breakpoint at main
|
|
process = target.LaunchSimple(None, None, os.getcwd())
|
|
|
|
# Make sure the launch went ok
|
|
if process:
|
|
# Print some simple process info
|
|
state = process.GetState()
|
|
print(process)
|
|
if state == lldb.eStateStopped:
|
|
# Get the first thread
|
|
thread = process.GetThreadAtIndex(0)
|
|
if thread:
|
|
# Print some simple thread info
|
|
print(thread)
|
|
# Get the first frame
|
|
frame = thread.GetFrameAtIndex(0)
|
|
if frame:
|
|
# Print some simple frame info
|
|
print(frame)
|
|
function = frame.GetFunction()
|
|
# See if we have debug info (a function)
|
|
if function:
|
|
# We do have a function, print some info for the
|
|
# function
|
|
print(function)
|
|
# Now get all instructions for this function and print
|
|
# them
|
|
insts = function.GetInstructions(target)
|
|
disassemble_instructions(insts)
|
|
else:
|
|
# See if we have a symbol in the symbol table for where
|
|
# we stopped
|
|
symbol = frame.GetSymbol()
|
|
if symbol:
|
|
# We do have a symbol, print some info for the
|
|
# symbol
|
|
print(symbol)
|
|
# Now get all instructions for this symbol and
|
|
# print them
|
|
insts = symbol.GetInstructions(target)
|
|
disassemble_instructions(insts)
|
|
|
|
registerList = frame.GetRegisters()
|
|
print(
|
|
"Frame registers (size of register set = %d):"
|
|
% registerList.GetSize()
|
|
)
|
|
for value in registerList:
|
|
# print value
|
|
print(
|
|
"%s (number of children = %d):"
|
|
% (value.GetName(), value.GetNumChildren())
|
|
)
|
|
for child in value:
|
|
print(
|
|
"Name: ", child.GetName(), " Value: ", child.GetValue()
|
|
)
|
|
|
|
print(
|
|
"Hit the breakpoint at main, enter to continue and wait for program to exit or 'Ctrl-D'/'quit' to terminate the program"
|
|
)
|
|
next = sys.stdin.readline()
|
|
if not next or next.rstrip("\n") == "quit":
|
|
print("Terminating the inferior process...")
|
|
process.Kill()
|
|
else:
|
|
# Now continue to the program exit
|
|
process.Continue()
|
|
# When we return from the above function we will hopefully be at the
|
|
# program exit. Print out some process info
|
|
print(process)
|
|
elif state == lldb.eStateExited:
|
|
print("Didn't hit the breakpoint at main, program has exited...")
|
|
else:
|
|
print(
|
|
"Unexpected process state: %s, killing process..."
|
|
% debugger.StateAsCString(state)
|
|
)
|
|
process.Kill()
|
|
|
|
|
|
lldb.SBDebugger.Terminate()
|