llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
28.78k stars 11.9k forks source link

`CGDebugInfo` appends working directory to absolute path converted to relative with `DebugPrefixMap` #83174

Open noxwell opened 8 months ago

noxwell commented 8 months ago

Description

DWARF file entry consists of filename and directory. When filename is relative, it is relative to thedirectory, but when filename is absolute, directory should be empty. However, after being transformed through CGDebugInfo::remapDIPath, absolute filename may become relative, which leads to a bug, that it becomes relative to the current working directory, and the resulting DWARF file location points to a file that doesn't exist.

Steps to reproduce

WORKDIR=$PWD
CC=clang
mkdir -p src
echo "int main() { return 0; }" > src/main.c
mkdir -p out
cd out
$CC -g -ffile-prefix-map="$WORKDIR/=./" -S -emit-llvm -o main.ll "$WORKDIR/src/main.c"
$CC -g -ffile-prefix-map="$WORKDIR/=./" -o main.o -c "$WORKDIR/src/main.c"
cat main.ll | grep 'DIFile' | head -n 1
llvm-dwarfdump main.o | grep 'DW_AT_decl_file'

Expected output

!1 = !DIFile(filename: "./src/main.c", directory: "", checksumkind: CSK_MD5, checksum: "5c11ff1def313f2a87eabf3a30f130ad")
DW_AT_decl_file ("./src/main.c")

Actual output

!1 = !DIFile(filename: "./src/main.c", directory: "./out", checksumkind: CSK_MD5, checksum: "5c11ff1def313f2a87eabf3a30f130ad")
DW_AT_decl_file ("./out/./src/main.c")

How to fix

This case is already handled in CGDebugInfo::createFile. But CGDebugInfo::CreateCompileUnit uses DBuilder.createFile directly instead of calling CGDebugInfo::createFile wrapper, which leads to incorrect file entry.

llvmbot commented 8 months ago

@llvm/issue-subscribers-clang-codegen

Author: Aleksei Vetrov (noxwell)

### Description DWARF file entry consists of filename and directory. When `filename` is relative, it is relative to the`directory`, but when `filename` is absolute, `directory` should be empty. However, after being transformed through `CGDebugInfo::remapDIPath`, absolute `filename` may become relative, which leads to a bug, that it becomes relative to the current working directory, and the resulting DWARF file location points to a file that doesn't exist. ### Steps to reproduce ```bash WORKDIR=$PWD CC=clang mkdir -p src echo "int main() { return 0; }" > src/main.c mkdir -p out cd out $CC -g -ffile-prefix-map="$WORKDIR/=./" -S -emit-llvm -o main.ll "$WORKDIR/src/main.c" $CC -g -ffile-prefix-map="$WORKDIR/=./" -o main.o -c "$WORKDIR/src/main.c" cat main.ll | grep 'DIFile' | head -n 1 llvm-dwarfdump main.o | grep 'DW_AT_decl_file' ``` ### Expected output ``` !1 = !DIFile(filename: "./src/main.c", directory: "", checksumkind: CSK_MD5, checksum: "5c11ff1def313f2a87eabf3a30f130ad") DW_AT_decl_file ("./src/main.c") ``` ### Actual output ``` !1 = !DIFile(filename: "./src/main.c", directory: "./out", checksumkind: CSK_MD5, checksum: "5c11ff1def313f2a87eabf3a30f130ad") DW_AT_decl_file ("./out/./src/main.c") ``` ### How to fix This case is already handled in `CGDebugInfo::createFile`. But `CGDebugInfo::CreateCompileUnit` uses `DBuilder.createFile` directly instead of calling `CGDebugInfo::createFile` wrapper, which leads to incorrect file entry.
llvmbot commented 8 months ago

@llvm/issue-subscribers-debuginfo

Author: Aleksei Vetrov (noxwell)

### Description DWARF file entry consists of filename and directory. When `filename` is relative, it is relative to the`directory`, but when `filename` is absolute, `directory` should be empty. However, after being transformed through `CGDebugInfo::remapDIPath`, absolute `filename` may become relative, which leads to a bug, that it becomes relative to the current working directory, and the resulting DWARF file location points to a file that doesn't exist. ### Steps to reproduce ```bash WORKDIR=$PWD CC=clang mkdir -p src echo "int main() { return 0; }" > src/main.c mkdir -p out cd out $CC -g -ffile-prefix-map="$WORKDIR/=./" -S -emit-llvm -o main.ll "$WORKDIR/src/main.c" $CC -g -ffile-prefix-map="$WORKDIR/=./" -o main.o -c "$WORKDIR/src/main.c" cat main.ll | grep 'DIFile' | head -n 1 llvm-dwarfdump main.o | grep 'DW_AT_decl_file' ``` ### Expected output ``` !1 = !DIFile(filename: "./src/main.c", directory: "", checksumkind: CSK_MD5, checksum: "5c11ff1def313f2a87eabf3a30f130ad") DW_AT_decl_file ("./src/main.c") ``` ### Actual output ``` !1 = !DIFile(filename: "./src/main.c", directory: "./out", checksumkind: CSK_MD5, checksum: "5c11ff1def313f2a87eabf3a30f130ad") DW_AT_decl_file ("./out/./src/main.c") ``` ### How to fix This case is already handled in `CGDebugInfo::createFile`. But `CGDebugInfo::CreateCompileUnit` uses `DBuilder.createFile` directly instead of calling `CGDebugInfo::createFile` wrapper, which leads to incorrect file entry.
noxwell commented 8 months ago

A test may look like this:

// RUN: mkdir -p %t/src
// RUN: cp %s %t/src/debug-info-debug-prefix-map.c

// RUN: mkdir -p %t/out
// RUN: cd %t/out
// RUN: %clang_cc1 -debug-info-kind=limited -triple %itanium_abi_triple \
// RUN:   -fdebug-prefix-map="%t/=./" %t/src/debug-info-debug-prefix-map.c \
// RUN:   -emit-llvm -o - | FileCheck %s

void foo(void) {}

// Compile unit filename is transformed from absolute path %t/src... to
// a relative path ./src... But it should not be relative to directory "./out".

// CHECK: = distinct !DICompileUnit({{.*}}file: ![[#CUFILE:]]
// CHECK: ![[#CUFILE]] = !DIFile(
// CHECK-NOT:    directory: "./out"
// CHECK-SAME:   filename: "./src{{[^"]+}}"
// CHECK-NOT:    directory: "./out"
// CHECK-SAME: )