TinyInst icon indicating copy to clipboard operation
TinyInst copied to clipboard

How to generate coverage.txt normally when instrumenting a continuously running background process

Open yongL1nk opened this issue 4 months ago • 3 comments

Hello. Thank you for your excellent work. I am attempting to run the Attach mode on x86 or arm64 Linux to instrument some .so files under a specific process. I used the following command:

./litecov -coverage_file coverage.txt -trace_basic_blocks -trace_debug_events -trace_module_entries -instrument_module libtest.so -pid <pid>

During execution, the following messages were generated:

TRACE: Entered module libtest.so at address 0x7139afe99119, offset 1119
Debugger: Breakpoint at 0x7139afe8a009
TRACE: Executing basic block, original at 0x7139afe99119, instrumented at 0x7139afe8a009
Debugger: Breakpoint at 0x7139afe8a046
TRACE: Executing basic block, original at 0x7139afe99050, instrumented at 0x7139afe8a046
Debugger: Breakpoint at 0x7139afe8a077
TRACE: Executing basic block, original at 0x7139afe99144, instrumented at 0x7139afe8a077...

The target process is an infinite-loop process (simulating a situation where the instrumented target process runs continuously). However, the coverage.txt does not generate as expected. But following command in Run mode can work, ./main will spawn the process used in the command line above.

./litecov -coverage_file coverage.txt -trace_basic_blocks -trace_debug_events -trace_module_entries -instrument_module libtest.so -- ./main

The generated message is as following and coverage.txt generates normally:

...
Debugger: Breakpoint at 0x7af2e03df21c
TRACE: Executing basic block, original at 0x7af2e03ee148, instrumented at 0x7af2e03df21c
Debugger: Thread 97781 exit
Process finished normally
Found 12 new offsets in libtest.so

Could you please advise how can I ensure that coverage message is correctly written to coverage.txt when instrumenting specific .so files in a process that runs continuously in the background?

yongL1nk avatar Aug 22 '25 09:08 yongL1nk

litecov binary will write coverage_file when either

  • process exits. Since that never happens for continuously running process, it never gets written.
  • target_method exits.

So, in your case, that means you should probably define target_method (and target_module).

Note however that

  • When target_method is defined, target won't actually be instrumented (and collect coverage) until target_method is reached. You might be able to get around that by adding -instrument_modules_on_load flag.
  • When target_method exits, the process will get killed. See https://github.com/googleprojectzero/TinyInst/blob/master/tinyinst-coverage.cpp#L176

ifratric avatar Aug 22 '25 13:08 ifratric

Thank you for your reply. Actually, I hope to perform relatively comprehensive instrumentation on the target dynamic library file. And I need to obtain the function names through decompilation, so it seems there will be some difficulties in specifying them using -target_method. The background process can actually be killed. Now I am considering adding some mechanisms to the Watchdog so that the target process will be terminated after the fuzz testing is completed. This way the coverage.txt file can be generated normally. However, occasionally the following error is thrown in arm64:

[-] PROGRAM ABORT : Error reading target memory         Location : RemoteRead(), /home/TinyInst/Linux/debugger.cpp

In fact, this method works most of the time, and it is my current solution. Do you have any better suggestions?

yongL1nk avatar Aug 26 '25 03:08 yongL1nk

An alternative to -target_method is via method offset inside the module, with -target_offset. Not sure if that works better for you.

Are you saying you are getting the Error reading target memory after killing the background process or at other times as well? Could you attach a debugger to the TinyInst process and provide the full stack trace when that abort happens?

ifratric avatar Aug 26 '25 07:08 ifratric