Skip to content

fix: drcov2lcov read all dumps per log file so post-popen coverage not dropped - #7974

Open
pavelbazika wants to merge 8 commits into
DynamoRIO:masterfrom
pavelbazika:i1390-drcov2lcov
Open

fix: drcov2lcov read all dumps per log file so post-popen coverage not dropped#7974
pavelbazika wants to merge 8 commits into
DynamoRIO:masterfrom
pavelbazika:i1390-drcov2lcov

Conversation

@pavelbazika

Copy link
Copy Markdown

When taking coverage of following program popen.c

#include <stdio.h>

int main() {
    printf("before\n");
    FILE *f  = popen("ls /home/pavelbazika", "r");
    pclose(f);
    printf("after\n");
}

running

drrun -t drcov -logdir $COVERAGE_DIR -- popen
drcov2lcov -dir "$COVERAGE_DIR" -mod_filter "" -output "$COVERAGE_DIR/coverage.info"

the report ends on popen line, although the program run to it's end

SF:popen.c
DA:3,1
DA:4,1
DA:5,1
DA:6,0
DA:7,0
DA:8,0
end_of_record

There's a related issue for this: #1390 (comment)

Please review the fix carefully, it was generated by AI and I don't know dynamorio. However, it works for me, with the fixed drcov2lcov I get complete coverage for this sample and also for the real project where the issue originaly occured.

@derekbruening derekbruening left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution. The main missing piece is adding a test.

* the process image is replaced), and again when the process or thread
* exits. Normally those two dumps land in different files, but
* posix_spawn() and popen() use a vfork-style clone that shares the
* parent's address space. The "execve" dump from the child therefore gets

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the only trigger was vfork, I'd say DR itself should provide a new-logfile mechanism and then this code would only ever see one dump. But since multiple dumps in the same file also happens with a failed execve, it probably is worth handling multiple dumps here.

return false;
}
ptr = move_to_next_line(ptr);
if ((size_t)(ptr - map) + (size_t)num_bbs * sizeof(bb_entry_t) > map_size) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer C++-style casts in C++ code.

/* read_bb_list() frees tables. */
if (read_bb_list(ptr, tables, num_mods, num_bbs))
any_bb = true;
ptr += (size_t)num_bbs * sizeof(bb_entry_t);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer C++-style casts in C++ code.

ptr = map;
map_end = map + (size_t)file_size;
while (ptr < map_end) {
const char *hdr = read_file_header(ptr);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find it confusing to use this new var hdr here: simpler and clearer to use ptr as in all the other calls advancing ptr.

@@ -969,40 +969,85 @@ static bool
read_drcov_file(const char *input)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a regression test. It can be the exact code you have in the PR description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants