From a8cf1a0352a080b62c3eee1d3aac213bf9d6b416 Mon Sep 17 00:00:00 2001 From: Amir Ayupov Date: Mon, 6 Apr 2026 14:41:21 -0700 Subject: [PATCH] [BOLT] Allow empty buildid in pre-aggregated profile addresses (#190675) Allow `parseString()` to return an empty `StringRef` when the delimiter appears at position 0. This enables parsing pre-aggregated profile addresses with an omitted buildid but preserved colon (`:addr` format), where the empty buildid corresponds to the main binary. Previously, `parseString()` rejected zero-length fields by treating `StringEnd == 0` the same as `StringRef::npos` (delimiter not found). These are distinct situations: `npos` means no delimiter exists, while `0` means the field before the delimiter is empty. The fix removes the `StringEnd == 0` sub-condition so only the missing-delimiter case errors. The existing test for buildid-prefixed addresses is extended to also verify that `:addr` input produces identical output to the plain-address and non-empty-buildid variants. Test Plan: Added empty-buildid input file and extended `pre-aggregated-perf-buildid.test` to run perf2bolt with `:addr` format and diff the fdata output against the existing buildid-prefixed result. --- bolt/lib/Profile/DataReader.cpp | 3 +-- bolt/test/X86/Inputs/pre-aggregated-buildid-empty.txt | 9 +++++++++ bolt/test/X86/pre-aggregated-perf-buildid.test | 8 ++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 bolt/test/X86/Inputs/pre-aggregated-buildid-empty.txt diff --git a/bolt/lib/Profile/DataReader.cpp b/bolt/lib/Profile/DataReader.cpp index ef4a65bb03b9..d3bea76daa5b 100644 --- a/bolt/lib/Profile/DataReader.cpp +++ b/bolt/lib/Profile/DataReader.cpp @@ -834,8 +834,7 @@ ErrorOr DataReader::parseString(char EndChar, bool EndNl) { size_t StringEnd = 0; do { StringEnd = ParsingBuf.find_first_of(EndChars, StringEnd); - if (StringEnd == StringRef::npos || - (StringEnd == 0 && ParsingBuf[StringEnd] != '\\')) { + if (StringEnd == StringRef::npos) { reportError("malformed field"); return make_error_code(llvm::errc::io_error); } diff --git a/bolt/test/X86/Inputs/pre-aggregated-buildid-empty.txt b/bolt/test/X86/Inputs/pre-aggregated-buildid-empty.txt new file mode 100644 index 000000000000..3cfe11a6510c --- /dev/null +++ b/bolt/test/X86/Inputs/pre-aggregated-buildid-empty.txt @@ -0,0 +1,9 @@ +B deadbeefaabbccdd:7f36d18d60c0 :400bbc 2 0 +B :400ad1 :400e00 2 0 +B :400b10 :4005f0 1 0 +B :400bb7 :400610 1 0 +B :4005f0 cafebabe01234567:7f36d18f2ce0 1 0 +B :4011a0 :4011a9 33 4 +B :4011ad :401180 58 0 +F :401170 :4011b2 22 +B :400dae :400d90 1 0 diff --git a/bolt/test/X86/pre-aggregated-perf-buildid.test b/bolt/test/X86/pre-aggregated-perf-buildid.test index 85c7c8b64f03..29ea0852a184 100644 --- a/bolt/test/X86/pre-aggregated-perf-buildid.test +++ b/bolt/test/X86/pre-aggregated-perf-buildid.test @@ -30,6 +30,14 @@ CHECK-FDATA: 1 usqrt 35 1 usqrt 39 0 22 CHECK-FDATA: 1 usqrt 3d 1 usqrt 10 0 58 CHECK-FDATA: 1 usqrt 3d 1 usqrt 3f 0 22 +## Test with empty buildid prefix on main binary addresses (`:addr` format). +## An omitted buildid with a preserved colon should be treated as the main +## binary. The output should be identical to the non-empty buildid version. +RUN: perf2bolt %t.exe -o %t.fdata2 --pa \ +RUN: -p %p/Inputs/pre-aggregated-buildid-empty.txt \ +RUN: --profile-format=fdata 2>&1 | FileCheck %s --check-prefix=CHECK-BUILDID +RUN: diff %t.fdata %t.fdata2 + ## Test YAML output with buildid-prefixed input. RUN: perf2bolt %t.exe -o %t.yaml --pa -p %p/Inputs/pre-aggregated-buildid.txt \ RUN: --profile-format=yaml --profile-use-dfs 2>&1