Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Linux: Update to DXC's null-invariant BSTR #11

Merged
merged 1 commit into from
May 5, 2021

Conversation

MarijnS95
Copy link
Member

@MarijnS95 MarijnS95 commented Nov 25, 2020

I keep forgetting to submit this change, which would cause segfaults in the long run when newer libdxcompiler.so builds are used (in conjunction with intellisense only, if that makes it any better...).

We recently fixed memory leaks when calling into the intellisense part of DXC and made the decision shortly after merging to implement null-invariant BSTRs properly in DXC's shimmed type for non-Windows, which was promptly accepted.

Currently our implementation of SysFreeString together with that PR segfaults because it frees the pointer at offset +4 of the allocation. That is corrected together with SysStringLen now reading the size of the string from this prefix instead of looking for a (wrong!) null character. At least our Windows and Linux implementation utils.rs is the same again.

Meanwhile there's a suggestion open at DXC to export these functions (CoTaskMemFree, SysFreeString etc) because the implementation is uniquely defined by DXC. We might want to hold off merging this PR (hence draft) until having confirmation whether that's acceptable. Otherwise we should coordinate this release with a version bump in DXC?

MarijnS95 added a commit that referenced this pull request Dec 29, 2020
DXC (all the Windows string types using WCHAR under the hood, really)
require wide strings to be terminated with a NUL character. If not,
they'd use a BSTR that has a sneaky length prefix (#11), otherwise the
length or ending of the string is unknown.

This has not caused any trouble before because into_vec performs the
exact same conversion as into_vec_with_nul, *except* that it pops off
the last character before returning the Vec. Only the size of it is
reduced, the underlying memory is not reallocated and the final NUL byte
is left in place.
However, in the event that a vector is shuffled around or modified we
cannot permit ourselves to loose that trailing NUL.
MarijnS95 added a commit that referenced this pull request Dec 29, 2020
DXC (all the Windows string types using WCHAR under the hood, really)
require wide strings to be terminated with a NUL character. If not,
they'd use a BSTR that has a sneaky length prefix (#11), otherwise the
length or ending of the string is unknown.

This has not caused any trouble before because into_vec performs the
exact same conversion as into_vec_with_nul, *except* that it pops off
the last character before returning the Vec. Only the size of it is
reduced, the underlying memory is not reallocated and the final NUL byte
is left in place.
However, in the event that a vector is shuffled around or modified we
cannot permit ourselves to loose that trailing NUL.
Jasper-Bekkers pushed a commit that referenced this pull request Dec 29, 2020
DXC (all the Windows string types using WCHAR under the hood, really)
require wide strings to be terminated with a NUL character. If not,
they'd use a BSTR that has a sneaky length prefix (#11), otherwise the
length or ending of the string is unknown.

This has not caused any trouble before because into_vec performs the
exact same conversion as into_vec_with_nul, *except* that it pops off
the last character before returning the Vec. Only the size of it is
reduced, the underlying memory is not reallocated and the final NUL byte
is left in place.
However, in the event that a vector is shuffled around or modified we
cannot permit ourselves to loose that trailing NUL.
@MarijnS95 MarijnS95 marked this pull request as ready for review February 8, 2021 08:37
@MarijnS95
Copy link
Member Author

MarijnS95 commented Feb 8, 2021

It's probably time to merge this in now. Aforementioned patch has been merged some time ago and is available under the 1.6.2012 release.

The suggestion to provide these helpers from DXC however has gone unnoticed...

We [recently] fixed memory leaks when calling into the intellisense part
of DXC and made the decision shortly after merging to [implement
null-invariant `BSTR`s properly] in DXC's shimmed type for non-Windows,
which was promptly accepted.

Currently our implementation of `SysFreeString` together with that PR
segfaults because it frees the pointer at offset `+4` of the allocation.
That is corrected together with `SysStringLen` now reading the size of
the string from this prefix instead of looking for a (wrong!) null
termination character.  At least our Windows and Linux implementation
`utils.rs` is the same again.

[recently]: #10
[implement null-invariant `BSTR`s properly]: microsoft/DirectXShaderCompiler#3250
@Jasper-Bekkers Jasper-Bekkers merged commit 9467024 into master May 5, 2021
@MarijnS95 MarijnS95 deleted the dxc-prefix-sized-BSTR branch May 5, 2021 15:44
MarijnS95 added a commit that referenced this pull request Jan 12, 2022
…of a panic

Not all file loading should be fallible; DXC usually invokes the loader
with multiple paths depending on relative includes, and happily accepts
and expects us to return `-2_147_024_894 // ERROR_FILE_NOT_FOUND /
0x80070002` for some.  As such the precedent should be to not panic but
let DXC decide if file loading failures should be critical or simply
result in a different path being tested.

In my case though the error seems to originate from DXIL compilation
being largely untested when ran on Linux systems through the WinAadapter
codepath.  In this particular stacktrace below DXC seems to "stat" (get
file information) for the current working directory, and somehow ends up
trying to open the directory as file through our include handler:

    #11 dxcutil::DxcArgsFileSystemImpl::TryFindOrOpen (this=<optimized out>, this@entry=0x5570a3b0ae10, lpFileName=lpFileName@entry=0x5570a3b5d0d0 L".../hassle-rs", index=<optimized out>)
        at .../DirectXShaderCompiler/tools/clang/tools/dxcompiler/dxcfilesystem.cpp:327
    #12 0x00007f6e64a41a8d in dxcutil::DxcArgsFileSystemImpl::GetFileAttributesW (this=0x5570a3b0ae10, lpFileName=0x5570a3b5d0d0 L".../hassle-rs")
        at .../DirectXShaderCompiler/tools/clang/tools/dxcompiler/dxcfilesystem.cpp:570
    #13 0x00007f6e64a42048 in dxcutil::DxcArgsFileSystemImpl::Stat (this=0x5570a3b0ae10, lpFileName=<optimized out>, Status=0x7fff9faec1e8)
        at .../DirectXShaderCompiler/tools/clang/tools/dxcompiler/dxcfilesystem.cpp:807
    #14 0x00007f6e64debc91 in llvm::sys::fs::status (Path=..., Result=...) at .../DirectXShaderCompiler/lib/Support/Unix/Path.inc:385
    #15 0x00007f6e64dec708 in llvm::sys::fs::current_path (result=...) at .../DirectXShaderCompiler/lib/Support/Unix/Path.inc:195
    #16 0x00007f6e64e64535 in clang::CodeGen::CGDebugInfo::getCurrentDirname (this=this@entry=0x5570a3b598f0)
        at .../DirectXShaderCompiler/tools/clang/lib/CodeGen/CGDebugInfo.cpp:301
    #17 0x00007f6e64e6230e in clang::CodeGen::CGDebugInfo::CreateCompileUnit (this=this@entry=0x5570a3b598f0)
        at .../DirectXShaderCompiler/tools/clang/lib/CodeGen/CGDebugInfo.cpp:369

This stacktrace originates from the following panic:

    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 21, kind: IsADirectory, message: "Is a directory" }', src/utils.rs:51:48
MarijnS95 added a commit that referenced this pull request Jan 25, 2022
…of a panic (#27)

Not all file loading should be fallible; DXC usually invokes the loader
with multiple paths depending on relative includes, and happily accepts
and expects us to return `-2_147_024_894 // ERROR_FILE_NOT_FOUND /
0x80070002` for some.  As such the precedent should be to not panic but
let DXC decide if file loading failures should be critical or simply
result in a different path being tested.

In my case though the error seems to originate from DXIL compilation
being largely untested when ran on Linux systems through the WinAadapter
codepath.  In this particular stacktrace below DXC seems to "stat" (get
file information) for the current working directory, and somehow ends up
trying to open the directory as file through our include handler:

    #11 dxcutil::DxcArgsFileSystemImpl::TryFindOrOpen (this=<optimized out>, this@entry=0x5570a3b0ae10, lpFileName=lpFileName@entry=0x5570a3b5d0d0 L".../hassle-rs", index=<optimized out>)
        at .../DirectXShaderCompiler/tools/clang/tools/dxcompiler/dxcfilesystem.cpp:327
    #12 0x00007f6e64a41a8d in dxcutil::DxcArgsFileSystemImpl::GetFileAttributesW (this=0x5570a3b0ae10, lpFileName=0x5570a3b5d0d0 L".../hassle-rs")
        at .../DirectXShaderCompiler/tools/clang/tools/dxcompiler/dxcfilesystem.cpp:570
    #13 0x00007f6e64a42048 in dxcutil::DxcArgsFileSystemImpl::Stat (this=0x5570a3b0ae10, lpFileName=<optimized out>, Status=0x7fff9faec1e8)
        at .../DirectXShaderCompiler/tools/clang/tools/dxcompiler/dxcfilesystem.cpp:807
    #14 0x00007f6e64debc91 in llvm::sys::fs::status (Path=..., Result=...) at .../DirectXShaderCompiler/lib/Support/Unix/Path.inc:385
    #15 0x00007f6e64dec708 in llvm::sys::fs::current_path (result=...) at .../DirectXShaderCompiler/lib/Support/Unix/Path.inc:195
    #16 0x00007f6e64e64535 in clang::CodeGen::CGDebugInfo::getCurrentDirname (this=this@entry=0x5570a3b598f0)
        at .../DirectXShaderCompiler/tools/clang/lib/CodeGen/CGDebugInfo.cpp:301
    #17 0x00007f6e64e6230e in clang::CodeGen::CGDebugInfo::CreateCompileUnit (this=this@entry=0x5570a3b598f0)
        at .../DirectXShaderCompiler/tools/clang/lib/CodeGen/CGDebugInfo.cpp:369

This stacktrace originates from the following panic:

    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 21, kind: IsADirectory, message: "Is a directory" }', src/utils.rs:51:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants