diff --git a/bolt/test/merge-fdata-bat-no-lbr.test b/bolt/test/merge-fdata-bat-no-lbr.test index 5176286bf24e..b4ac3b59aab5 100644 --- a/bolt/test/merge-fdata-bat-no-lbr.test +++ b/bolt/test/merge-fdata-bat-no-lbr.test @@ -8,13 +8,13 @@ # CHECK: boltedcollection # CHECK: no_lbr -# CHECK: 1 main 2 +# CHECK: 1 main 0 2 #--- a.fdata boltedcollection no_lbr -1 main 1 +1 main 0 1 #--- b.fdata boltedcollection no_lbr -1 main 1 +1 main 0 1 diff --git a/bolt/test/merge-fdata-mixed-bat-no-lbr.test b/bolt/test/merge-fdata-mixed-bat-no-lbr.test index eb8c8114b41b..35ddadac81f6 100644 --- a/bolt/test/merge-fdata-mixed-bat-no-lbr.test +++ b/bolt/test/merge-fdata-mixed-bat-no-lbr.test @@ -10,7 +10,7 @@ #--- a.fdata boltedcollection no_lbr -1 main 1 +1 main 0 1 #--- b.fdata no_lbr -1 main 1 +1 main 0 1 diff --git a/bolt/test/merge-fdata-mixed-mode.test b/bolt/test/merge-fdata-mixed-mode.test index 731e84664756..5fc1af50d47d 100644 --- a/bolt/test/merge-fdata-mixed-mode.test +++ b/bolt/test/merge-fdata-mixed-mode.test @@ -10,6 +10,6 @@ #--- a.fdata no_lbr -1 main 1 +1 main 0 1 #--- b.fdata -1 main 1 +1 main 0 1 diff --git a/bolt/test/merge-fdata-no-lbr-mode.test b/bolt/test/merge-fdata-no-lbr-mode.test index 5b417e74ce94..9bd5b3c9ce90 100644 --- a/bolt/test/merge-fdata-no-lbr-mode.test +++ b/bolt/test/merge-fdata-no-lbr-mode.test @@ -8,11 +8,11 @@ # RUN: FileCheck %s --input-file %t/merged.fdata # CHECK: no_lbr -# CHECK: 1 main 2 +# CHECK: 1 main 0 2 #--- a.fdata no_lbr -1 main 1 +1 main 0 1 #--- b.fdata no_lbr -1 main 1 +1 main 0 1 diff --git a/bolt/test/merge-fdata-skip-truncated.test b/bolt/test/merge-fdata-skip-truncated.test new file mode 100644 index 000000000000..79606980c428 --- /dev/null +++ b/bolt/test/merge-fdata-skip-truncated.test @@ -0,0 +1,20 @@ +## Check that merge-fdata skips truncated lines with a warning + +# REQUIRES: system-linux + +# RUN: split-file %s %t +# RUN: merge-fdata %t/a.fdata %t/b.fdata -o %t/merged.fdata 2>&1 | \ +# RUN: FileCheck -check-prefix=CHECK-WARN %s +# RUN: FileCheck %s --input-file %t/merged.fdata + +# CHECK-WARN: WARNING: {{.*}}b.fdata: ignoring malformed entry + +## Only the valid entry should appear in the merged output +# CHECK: 1 main 0 1 main 2 1 3 +# CHECK-NOT: trunc + +#--- a.fdata +1 main 0 1 main 2 0 1 +#--- b.fdata +1 main 0 1 main 2 1 2 +1 trunc 0 1 diff --git a/bolt/tools/merge-fdata/merge-fdata.cpp b/bolt/tools/merge-fdata/merge-fdata.cpp index 55e3dd5a2718..23b178eee17b 100644 --- a/bolt/tools/merge-fdata/merge-fdata.cpp +++ b/bolt/tools/merge-fdata/merge-fdata.cpp @@ -318,11 +318,33 @@ void mergeLegacyProfiles(const SmallVectorImpl &Filenames) { do { StringRef Line(FdataLine); + Line = Line.rtrim(); + if (Line.empty()) + continue; CounterTy Count; unsigned Type = 0; if (Line.split(' ').first.getAsInteger(10, Type)) report_error(Filename, "Malformed / corrupted entry type"); bool IsBranchEntry = Type < 3; + + // Validate the number of fields in the line. Count only unescaped spaces + // as field separators, since function names may contain escaped spaces, + // like "foo\ bar". + size_t NumFields = 1; + for (size_t I = 0; I < Line.size(); ++I) { + if (Line[I] == '\\') + ++I; + else if (Line[I] == ' ') + ++NumFields; + } + size_t ExpectedFields = + IsBranchEntry ? (NoLBRCollection.value_or(false) ? 4 : 8) : 7; + if (NumFields != ExpectedFields) { + errs() << "WARNING: " << Filename << ": ignoring malformed entry with " + << NumFields << " fields (expected " << ExpectedFields << ")\n"; + continue; + } + auto [Signature, ExecCount] = Line.rsplit(' '); if (ExecCount.getAsInteger(10, Count.Exec)) report_error(Filename, "Malformed / corrupted execution count");