Hacktoberfest 2026 : les issues que les mainteneurs ont marquées pour octobre, ouvertes et accessibles aux débutants. Parcourir les issues Hacktoberfest

DWARF line table rows with line 0 are dropped, so code gets attributed to the wrong line

Ouverte
#9,164 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

Les mainteneurs répondent en général sous 1 jour

@cpunion y travaille déjà.

Depuis le 2/10/2026.

  • #9192 par @cpunion — ouverte

Évaluation

Difficulté
3/5
Temps estimé
1-2 jours
Accessibilité débutants
76/100
Type d'issue
Bug
Clarté
Clairement spécifiée
Activité
Active
Stack technique
cpp, wasm
Domaine
compilers

Piste de recherche

Start in src/wasm/wasm-debug.cpp at LineState::needToEmit and review the DWARF line-table handling. Run the clang, wasm-ld, wasm-opt, and llvm-dwarfdump reproduction from the issue, then verify that line 0 rows remain mapped and llvm-dwarfdump --lookup=0x0b reports line 0 after wasm-opt -g.

Rédigé par le modèle d'indexation à partir du texte de l'issue.

Description

While working on some debugger related fixes in TinyGo, I discovered what I think is an issue, and also a possible fix. The following is an edited version of the automated analysis.

Thank you for looking it over.

Analysis

When wasm-opt rewrites the DWARF line table, it drops every row that has line 0, even when no passes run. In DWARF, line 0 means the code has no source line, for example code LLVM merged from two places. Once the line 0 row is gone, the previous row covers that code, so debuggers and profilers attribute it to the wrong line.

The check is in LineState::needToEmit (wasm-debug.cpp):

bool needToEmit() {
  // Zero values imply we can ignore this line.
  // https://github.com/WebAssembly/debugging/issues/9#issuecomment-567720872
  return line != 0 && addr != 0;
}

The linked comment explains why address 0 is reserved for dead code removed by the linker. It does not mention line 0. The code is the same on main.

Repro

t.c:

int g(int);

int f(int x) {
  int r = 0;
  if (x > 10)
    r = g(x);
  else
    r = g(x + 1);
  return r * 3;
}
clang --target=wasm32 -O2 -g -c t.c -o t.o
wasm-ld --no-entry --export=f --allow-undefined t.o -o t.wasm
wasm-opt -g t.wasm -o out.wasm
llvm-dwarfdump --debug-line t.wasm
llvm-dwarfdump --debug-line out.wasm

LLVM merges the two calls to g and marks the call with line 0. Input line table:

Address            Line   Column File   ISA Discriminator OpIndex Flags
0x0000000000000002      3      0      1   0             0       0  is_stmt
0x0000000000000007      5      9      1   0             0       0  is_stmt prologue_end
0x0000000000000008      5      7      1   0             0       0
0x000000000000000b      0      0      1   0             0       0
0x0000000000000013      9     12      1   0             0       0  is_stmt
0x0000000000000014      9      3      1   0             0       0
0x0000000000000015      9      3      1   0             0       0  end_sequence

Output line table after wasm-opt -g with no passes:

Address            Line   Column File   ISA Discriminator OpIndex Flags
0x0000000000000002      3      0      1   0             0       0  is_stmt
0x0000000000000007      5      9      1   0             0       0  is_stmt prologue_end
0x0000000000000008      5      7      1   0             0       0
0x000000000000000f      9     12      1   0             0       0  is_stmt
0x0000000000000010      9      3      1   0             0       0
0x0000000000000011      9      3      1   0             0       0  end_sequence

The call is at 0x0b in both files. llvm-dwarfdump --lookup=0x0b gives line 0 for t.wasm and line 5, column 7 (the if condition) for out.wasm.

Tested with wasm-opt version 133 and clang 18.1.2 from wasi-sdk.

Impact

We found this in TinyGo, where a no-op round trip through wasm-opt -g removes all 21,756 line 0 rows from a small program. It gets worse with --asyncify, since code it adds in the middle of a function also ends up under the previous source line. See https://github.com/tinygo-org/tinygo/issues/5736.

Possible fix

Keep line 0 rows and only skip rows with address 0. Line 0 rows would still need their address mapped like any other row.

Langage dominant
WebAssembly
Étoiles
8.7k
Forks
900
Merge moyen
2 j 5 h
PR mergées (30 j)
93

Préparer son environnement

Par où commencer

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. Ouvrez une pull request qui référence le numéro de l'issue.

Autres issues de WebAssembly/binaryen

Toutes les issues de WebAssembly/binaryen

Issues similaires

Plus d'issues Compilers

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.