llvm / llvm/llvm-project

[lld]lld-link -debug emits zero-characteristic PE sections

Open
#224,534 0 comments 0 reactions 0 assignees View on GitHub
lld
Dominant language
LLVM
Stars
40.5k
Forks
18.7k
PR merge metrics
PR metrics pending

Description

## Summary

With `clang-cl /Zi -fuse-ld=lld`, lld-link emits `_guard_c`, `_guard_d`,
and `memcpy_` with `IMAGE_SECTION_HEADER.Characteristics = 0x00000000`.
Windows then does not use large-page image mapping:
`_PEB.ImageUsesLargePages` is `0y0` with IFEO `UseLargePages=1` enabled.

Verbose-driver output shows that `clang-cl /Zi` invokes `lld-link -debug`.
Without `/Zi`, the same link succeeds (`ImageUsesLargePages = 0y1`).

## Environment

* OS: Windows [fill in version/build]; x64
* lld-link version: LLD 19.1.1
* Compiler driver: MSYS2 MinGW64 `clang-cl` 21.1.8 (`x86_64-pc-windows-msvc`)
* MSVC toolset: 14.43.34808

## Reproduction

Set IFEO `UseLargePages=1` for `stockfish.exe` and grant the test user the
`Lock pages in memory` right. Build with:

```bat
clang-cl /nologo /TC /c /Fomain.obj main.c
clang-cl /nologo /TC /c /Fospecrand.obj specrand.c
clang-cl /nologo /Zi -fuse-ld=lld main.obj specrand.obj ^
/Felld_zi.exe /link /force:multiple /largeaddressaware
```

Rename or copy the executable to `stockfish.exe`, then run:

```bat
cdb -c "dt _PEB @$peb ImageUsesLargePages; q" stockfish.exe
```

## Actual result

```text
_guard_c Characteristics = 0x00000000
_guard_d Characteristics = 0x00000000
memcpy_ Characteristics = 0x00000000
```

`dt _PEB @$peb ImageUsesLargePages` prints `0y0`.

## Expected result

Every output section should have at least one of `IMAGE_SCN_MEM_READ`,
`IMAGE_SCN_MEM_WRITE`, or `IMAGE_SCN_MEM_EXECUTE`. In this case the three
sections can be read-only initialized data (`0x40000040`), allowing
`ImageUsesLargePages = 0y1`.

## Controls

| Linker and flags | `ImageUsesLargePages` |
| --- | --- |
| `clang-cl /Zi -fuse-ld=lld` | `0y0` |
| Same command without `/Zi` | `0y1` |
| MSVC `link.exe /debug` | `0y1` |

## Investigation

The source CRT COMDATs have `Characteristics = 0x00001000`
(`IMAGE_SCN_LNK_COMDAT`) only. `SectionChunk::getOutputCharacteristics()`
in `lld/COFF/Chunks.h` masks characteristics with `permMask | typeMask`;
that mask removes `IMAGE_SCN_LNK_COMDAT`, yielding zero. `Writer.cpp`
normalizes some known section names, but not these ones.

## Possible fix

Assign a sensible default when the masked result is zero, or normalize
these sections as read-only initialized data. A regression test should
assert that emitted PE sections have at least one memory-protection bit.

Contributor guide

Open the contributing guide

Research direction

Start in lld/COFF/Chunks.h at SectionChunk::getOutputCharacteristics(), then compare the section-name normalization in Writer.cpp. Add a regression test covering the /debug or /Zi link case and verify that the affected PE sections have at least one memory-protection bit and that large-page mapping remains enabled.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
compilers, operating-systems, testing
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
72/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.