Warning Bogus LBR data
- Dominant language
- C++
- Stars
- 619
- Forks
- 127
- PR merge metrics
- No merged PRs in 30d
Description
# probem
Recently, commit `623c777` **upgraded perf_data_converter**. There are some changes in the `PerfParser::MapBranchStack`. In the new version, even if the mapping of from_ip fails, the mapping process for `to_ip` will still proceed. This may lead to a situation where `from.offset_` equals the initial value 0 when `from_ip` mapping fails, and `to.offset_` equals the **actual offset** when `to_ip` mapping succeeds. In addition, in my test, these unmatched IPs are very large kernel stack addresses such as `0xffffffffa9400ac7`. This inconsistency may cause the subsequent check to erroneously warn about "Bogus LBR data". A large number of such warnings during use are more likely to cause confusion and need to be filtered in advance.
Here is my solution #201 . **If from does not match, continue in advance**, probably not the best solution.
# test case output
```log
mapped
WARNING: Logging before InitGoogleLogging() is written to STDERR
W20240712 19:35:47.081317 388180 sample_reader.cc:343] Bogus LBR data (duplicated top entry)
W20240712 19:35:47.081511 388180 sample_reader.cc:343] Bogus LBR data (duplicated top entry)
W20240712 19:35:47.081524 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=2
W20240712 19:35:47.081542 388180 sample_reader.cc:343] Bogus LBR data (duplicated top entry)
W20240712 19:35:47.081550 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=2
W20240712 19:35:47.081559 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=3
W20240712 19:35:47.081569 388180 sample_reader.cc:343] Bogus LBR data (duplicated top entry)
W20240712 19:35:47.081578 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=2
W20240712 19:35:47.081586 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=3
W20240712 19:35:47.081594 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=4
W20240712 19:35:47.081605 388180 sample_reader.cc:343] Bogus LBR data (duplicated top entry)
W20240712 19:35:47.081614 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=2
W20240712 19:35:47.081622 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=3
W20240712 19:35:47.081630 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=4
W20240712 19:35:47.081638 388180 sample_reader.cc:352] Bogus LBR data (range is negative): 1895->0 index=5
I20240712 19:35:47.085575 388180 symbol_map.cc:477] Adding loadable exec segment: offset=0 vaddr=200000
```
# test case
```shell
set -e
echo "**** init test file"
test_file=test_warning.cc
cat << EOF >${test_file}
#include
#include
#include
#include
#include
using namespace std;
class Base {
public:
long long v_;
Base(long long v) : v_(v) {}
virtual void test_func(long long) = 0;
virtual ~Base() = default;
};
class Child1 : public Base {
public:
Child1(long long v) : Base(v) {}
void test_func(long long v) override {
v_ += v + 1;
}
};
class Child2 : public Base {
public:
Child2(long long v) : Base(v) {}
void test_func(long long v) override {
v_ += v + 2;
}
};
class Child3 : public Base {
public:
Child3(long long v) : Base(v) {}
void test_func(long long v) override {
v_ += v + 3;
}
};
int class_type = 1;
void test_pgo(Base *p, const vector &arry) {
if (arry.empty())
return;
long long end = arry.back(), idx = 0;
for (long long i = 0; i < end; ++i) {
if (i > arry[idx])
++idx;
long long add_val = 0;
long long mod = arry[idx] % 4;
if (mod == 3) {
add_val = i;
} else if (mod == 1) {
add_val = -i;
} else if (mod == 0) {
add_val = i / 2;
} else if (mod == 2) {
add_val = i * 2;
}
p->test_func(add_val);
}
printf("%lld\n", p->v_);
}
vector read_data() {
std::ifstream file("data.txt");
vector ret;
std::string line;
while (std::getline(file, line)) {
std::cout << line << std::endl;
ret.push_back(atoll(line.c_str()));
}
file.close();
return ret;
}
void test() {
Base *p = nullptr;
switch (class_type) {
case 1:
p = new Child1(0);
break;
case 2:
p = new Child2(0);
break;
case 3:
p = new Child3(0);
break;
default:
p = new Child1(0);
}
vector arry = read_data();
for (int i = 0; i < 1; ++i)
test_pgo(p, arry);
}
int main(int argc, char** argv) {
printf("------begin\n");
if (argc > 1) {
class_type = atoi(argv[1]);
}
test();
}
EOF
cat << EOF >data.txt
3
3000
300000
500000000
2000000000
5000000000
EOF
clang="/home/distcc/clang-11.1.0/bin/clang++"
create_llvm_prof="build/create_llvm_prof"
cppflags="-O2 -fuse-ld=lld -fPIC -ggdb -Wl,--build-id -funique-internal-linkage-names -fdebug-info-for-profiling"
ldflags="-Wl,--no-rosegment "
# build clang-11
echo "**** build clang-11 test"
set -x
${clang} ${test_file} -o test_clang_pgo_before ${cppflags} ${ldflags}
# The test program is relatively simple. Sometimes perf cannot collect samples and needs to be executed several times.
size_threshold=$((1 * 1024 * 512)) # 512K in bytes
max_attempts=10
attempt=1
while [ $attempt -le $max_attempts ]
do
echo "Attempt #$attempt: Running perf..."
perf record -F2000 -e cycles:up -j any,u -o clang_perf.data ./test_clang_pgo_before
actual_size=$(stat --format=%s "clang_perf.data")
if [ $actual_size -lt $size_threshold ]; then
echo "Output file size is less than 512KB. Retrying..."
((attempt++))
else
echo "Output file size is sufficient."
break
fi
done
${create_llvm_prof} --profile clang_perf.data --binary test_clang_pgo_before --out=clang.llvm.prof
```
Contributor guide
Assessment
This issue has not been assessed yet.