You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ipctool trace produces a near-empty trace when run against Majestic on a Hi3518EV200 camera with libsns_jxf22.so. Strace on the same camera, same binary, same ptrace primitive captures the full sensor I/O sequence (~79 register writes). Multiple ipctool fixes have been merged (#153 most recent) but the issue persists.
Trace stops after the first I2C_SLAVE_FORCE ioctl. No sensor_write_register lines despite Majestic logging ===soi_f22 sensor DVP 1080P30fps linear mode init success!===== to its own stderr.
Reference: what strace sees
Same camera, same Majestic invocation, with the static strace at /mnt/noc/sdk/strace:
Two distinct /dev/i2c-0 opens (fd 18 for Majestic's probe, fd 25 for libsns_jxf22.so's own handle).
79 write(25, ...) calls of 2 bytes each (1-byte reg + 1-byte value, jxf22 is 8-bit/8-bit).
Three TIDs total visible (1671, 1675, 1676), all writes attributed to the main TID 1671.
Critical observation: stracewithout-f also shows zero writes. strace -f shows 79. This points at clone-following being the determining factor, even though the writes are attributed to the original TID. Either strace -f and strace use materially different ptrace setups (likely — strace uses PTRACE_SEIZE + PTRACE_O_TRACECLONE only with -f), or thread-vs-process semantics are confounding the analysis.
ipctool processes ~2400 syscall events in 30 s of capture (vs ~7000 strace sees in 18 s — 3x slower)
Of those 2400, exactly zero are __NR_write (4) or __NR_writev (146) to a /dev/i2c-0 fd
The single writev that fires is to fd=2 (libc stdio to stderr)
The trace caught only the first/dev/i2c-0 open at fd 19 (Majestic's probe). The second open at fd 25 (libsns_jxf22.so's own handle) is the one we're missing.
What's likely the bug
Best hypothesis after the investigation:
After the first /dev/i2c-0 open + ioctl burst, Majestic does ~50 unrelated syscalls before the second /dev/i2c-0 open.
Somewhere in those ~50 syscalls, ipctool's wait loop loses track of the tracee in a way strace -f does not.
From that point on, our trace stream goes silent even though the kernel ptrace keeps generating events.
Areas to look at:
PTRACE_ATTACH vs PTRACE_SEIZE. ipctool uses PTRACE_ATTACH. strace uses PTRACE_SEIZE in modern builds. SEIZE has cleaner event-stop semantics (PTRACE_EVENT_STOP / PTRACE_LISTEN) and might be why strace -f succeeds where ipctool fails.
Whether __WALL is sufficient on this kernel. ipctool uses waitpid(-1, &status, __WALL); some old kernels need __WCLONE separately.
Reproduction
The OpenIPC lab has the camera at <your-hi3518ev200-camera>, NFS server 10.216.128.227:/srv/nfsroot (mountable as /mnt/noc on the host and /utils on the camera).
Build a fresh ipctool
# Toolchain
wget -qO- https://github.com/OpenIPC/firmware/releases/download/toolchain/toolchain.hisilicon-hi3516cv100.tgz \
| tar xzf - -C /tmp/openipc-tc
# Build + UPX-pack (UPX is mandatory for the V2 kernel)cd ipctool
PATH=/tmp/openipc-tc/arm-openipc-linux-musleabi_sdk-buildroot/bin:$PATH \
cmake -H. -Bbuild -DCMAKE_C_COMPILER=arm-openipc-linux-musleabi-gcc -DCMAKE_BUILD_TYPE=Release
PATH=/tmp/openipc-tc/arm-openipc-linux-musleabi_sdk-buildroot/bin:$PATH cmake --build build
upx --best build/ipctool -o /mnt/noc/ipctool-upx
Last resort: rebuild libsns_jxf22.so from OpenIPC/glutinium with extra printf instrumentation around each write() call, deploy, see whether the prints come through under ipctool but the writes don't.
Definition of done
The fix is complete when all of the following hold:
tools/capture_sensor.sh majestic --host openipc-hi3518ev200... --secs 25 produces a trace with at least 50 sensor_write_register lines (matching strace's 79-write count, modulo init incompleteness due to capture window).
The same trace, when fed through tools/trace_segment.py, produces a non-empty init phase with init_pattern set to a recognised family — or, if jxf22 uses a third pattern, a new entry in INIT_PATTERNS covers it.
tools/trace_to_driver.py emits a jxf22_linear_init (or similar) function that passes gcc -Wall -Wextra -fsyntax-only.
tools/trace_diff.py against OpenIPC/glutinium hi35xx_sensor_jxf22 (function sensor_linear_1080p30_init after collapsing the sensor_prog ROM table) reports ≥90% address match and ≥80% value match.
SC2315E regression diff stays at 100/100/100% against widgetii/smart_sc2315e.
CI test-extraction-pipeline job still passes; new test fixture or assertion added if appropriate.
Whatever ptrace-handling change made the difference is documented in docs/sensor-driver-extraction.md next to the existing "When the trace is empty anyway" section, with a one-paragraph explanation of why the previous code failed (so future researchers don't reintroduce the regression).
Summary
ipctool traceproduces a near-empty trace when run against Majestic on a Hi3518EV200 camera withlibsns_jxf22.so. Strace on the same camera, same binary, sameptraceprimitive captures the full sensor I/O sequence (~79 register writes). Multiple ipctool fixes have been merged (#153 most recent) but the issue persists.Affected configuration
<your-hi3518ev200-camera>in the OpenIPC test rig)/usr/lib/sensors/libsns_jxf22.soSymptom
Trace stops after the first
I2C_SLAVE_FORCEioctl. Nosensor_write_registerlines despite Majestic logging===soi_f22 sensor DVP 1080P30fps linear mode init success!=====to its own stderr.Reference: what strace sees
Same camera, same Majestic invocation, with the static strace at
/mnt/noc/sdk/strace:/dev/i2c-0opens (fd 18 for Majestic's probe, fd 25 forlibsns_jxf22.so's own handle).write(25, ...)calls of 2 bytes each (1-byte reg + 1-byte value, jxf22 is 8-bit/8-bit).Critical observation:
stracewithout-falso shows zero writes.strace -fshows 79. This points at clone-following being the determining factor, even though the writes are attributed to the original TID. Eitherstrace -fandstraceuse materially different ptrace setups (likely — strace usesPTRACE_SEIZE+PTRACE_O_TRACECLONEonly with-f), or thread-vs-process semantics are confounding the analysis.What's already been tried
All merged via #145 → #153:
--output=PATHflag (decouple trace from streamer stdout)i2c_write_exit_cbhandles 1+1 / 2+1 / 2+2 byte writes with chip-family endiannesshisi_gen2_ioctl_exit_cbdecodes V2I2C_SLAVE_FORCEsensor_i2c_change_addr(0x100)line we do seesyscall_writev_exitfor uClibcwrite→writevwrappingbroadcast_fd_open/broadcast_fd_closefor CLONE_FILES siblingsPTRACE_SYSCALLresumeSIGSTOP/SIGTSTP/SIGTTIN/SIGTTOUto avoid re-stopping cloned childrenPTRACE_EVENT_FORK/PTRACE_EVENT_VFORKeventsbreakon missing-PID lookup racePer-syscall instrumentation (temporarily) showed:
__NR_write(4) or__NR_writev(146) to a/dev/i2c-0fd/dev/i2c-0open at fd 19 (Majestic's probe). The second open at fd 25 (libsns_jxf22.so's own handle) is the one we're missing.What's likely the bug
Best hypothesis after the investigation:
/dev/i2c-0open + ioctl burst, Majestic does ~50 unrelated syscalls before the second/dev/i2c-0open.strace -fdoes not.Areas to look at:
PTRACE_ATTACH. strace usesPTRACE_SEIZEin modern builds. SEIZE has cleaner event-stop semantics (PTRACE_EVENT_STOP/PTRACE_LISTEN) and might be why strace -f succeeds where ipctool fails.PTRACE_ATTACH. Even with the SIGSTOP suppression in ptrace wait loop: signal forwarding, FORK/VFORK events, group-stop suppression #153, real group-stops (SIGSTOP/SIGTSTP) on a child are subtle under ATTACH — see ptrace(2) NOTES section.__WALLis sufficient on this kernel. ipctool useswaitpid(-1, &status, __WALL); some old kernels need__WCLONEseparately.Reproduction
The OpenIPC lab has the camera at
<your-hi3518ev200-camera>, NFS server10.216.128.227:/srv/nfsroot(mountable as/mnt/nocon the host and/utilson the camera).Build a fresh ipctool
Capture under ipctool
Capture under strace for comparison
Useful debug knobs (in order of cost)
exit_syscallinsrc/ptrace.cto confirm syscall events keep flowing post-i2c-banner.waitpidreturn + status in the wait loop — does the loop block onwaitpid -1indefinitely at some point?ptrace(PTRACE_SYSCALL, ...)return value — does it fail with ESRCH at some point?PTRACE_ATTACHwithPTRACE_SEIZE(changes the initial-stop and event semantics; closer to what strace does).tools/sns_init_probe.c(added in ptrace wait loop: signal forwarding, FORK/VFORK events, group-stop suppression #153) to loadlibsns_jxf22.sodirectly without Majestic — needs a uClibc-targeted toolchain matching the camera'sld-uClibc.so.0exactly.libsns_jxf22.sofrom OpenIPC/glutinium with extraprintfinstrumentation around eachwrite()call, deploy, see whether the prints come through under ipctool but the writes don't.Definition of done
The fix is complete when all of the following hold:
tools/capture_sensor.sh majestic --host openipc-hi3518ev200... --secs 25produces a trace with at least 50sensor_write_registerlines (matching strace's 79-write count, modulo init incompleteness due to capture window).tools/trace_segment.py, produces a non-emptyinitphase withinit_patternset to a recognised family — or, if jxf22 uses a third pattern, a new entry inINIT_PATTERNScovers it.tools/trace_to_driver.pyemits ajxf22_linear_init(or similar) function that passesgcc -Wall -Wextra -fsyntax-only.tools/trace_diff.pyagainst OpenIPC/glutinium hi35xx_sensor_jxf22 (functionsensor_linear_1080p30_initafter collapsing thesensor_progROM table) reports ≥90% address match and ≥80% value match.widgetii/smart_sc2315e.test-extraction-pipelinejob still passes; new test fixture or assertion added if appropriate.docs/sensor-driver-extraction.mdnext to the existing "When the trace is empty anyway" section, with a one-paragraph explanation of why the previous code failed (so future researchers don't reintroduce the regression).