Skip to content

[lldb][Windows] Metadata cache corruption in modules with sparse symbol info #12891

Description

@speednoisemovement

TypeRefBuilder uses a cache when fetching field metadata, with the symbol's mangled name as the key. On the first access, the cache is filled for each metadata record in the loaded image.

The cache has two paths:

  • A fast path, which uses LLDBMemoryReader::resolvePointerAsSymbol
  • A slow path which walks the metadata.

Crucially, LLDBMemoryReader::resolvePointerAsSymbol does not require the pointer to point at the beginning of the symbol. This means that when using incomplete symbol information, every address between known symbols A and B resolves to A. Since the cache uses the mangled name as the key, A's record in the cache will be overwritten by the last symbol encountered!

On Windows, swiftCore.dll does not ship with PDBs, leaving us to rely on the COFF exports table. As a result, it's very easy to corrupt the cache, and we do. For example:

main.swift:

let d = ["Hello": "World"]
print(d)

swiftc -g -debug-info-format=dwarf main.swift -Xlinker /debug -use-ld=lld -o main.exe

lldb.exe main.exe
(lldb) b main.swift:2
(lldb) fr v
([String : String]) d = <failed to update hashed container>

(also repros with PDB)

We should probably ship PDBs for redistributables but I personally think LLDBMemoryReader::resolvePointerAsSymbol's behavior in this context isn't what I would expect. It might make sense to add a check on Windows that the pointer points at the beginning of a symbol. We're already no-oping the method on Linux (possibly for similar reasons?) so tightening it up seems safe to me.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions