This is an archive of the discontinued LLVM Phabricator instance.

[libcxx] [test] Skip alloc counter checks for operations within the libc++ DLL
ClosedPublic

Authored by mstorsjo on Apr 9 2021, 11:32 AM.

Details

Summary

If libc++ is built as a DLL, calls to operator new within the DLL aren't
overridden if a user provides their own operator in calling code.
Therefore, the alloc counter doesn't pick up on allocations done within
std::string, so skip that check if running on windows. (Technically,
we could keep the checks if running on windows when not built as a DLL,
but trying to keep the conditionals simple.)

Diff Detail

Event Timeline

mstorsjo requested review of this revision.Apr 9 2021, 11:32 AM
mstorsjo created this revision.
Herald added a project: Restricted Project. · View Herald TranscriptApr 9 2021, 11:32 AM
Herald added a reviewer: Restricted Project. · View Herald Transcript

@curdeius This one is the next one for getting rid of LIBCXX-WINDOWS-FIXME in the filesystem tests (this one drops the number of remaining fixmes from 7 to 3). What do you think of this one? I've tried to keep an explanatory comment next to each case.

ldionne requested changes to this revision.Apr 27 2021, 6:24 AM
ldionne added a subscriber: ldionne.
ldionne added inline comments.
libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp
144–146

Should this be considered a bug in the Windows runtime? If so, it's not doing any good to work around it in our test suite, we should instead:

  1. File a bug report to get it fixed, and
  2. Mark the whole test as being broken until they fix it.
This revision now requires changes to proceed.Apr 27 2021, 6:24 AM
mstorsjo added inline comments.Apr 27 2021, 7:09 AM
libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp
144–146

It's not a bug in the Windows runtime that can be fixed reasonably, it's only between libc++ and the executable formats used on the platform.

The root cause is that PE-COFF DLLs are "sealed" two-level namespaces.

If you provide operator new in user code, this overrides libc++'s operator new within that executable, and within libc++ if it is linked statically.

If libc++ is linked as a DLL, all references to operator new within the DLL are hardwired at link time to the operator new provided there. It doesn't have the ELF/MachO feature of a GOT where the executable can override any symbol used in libraries loaded.

So here, the operator new that is overridden in the test, to count allocations, isn't invoked and doesn't count allocations that happen within the libc++ DLL. It does count the ones that are done by calls in the test executable.

mstorsjo added inline comments.Apr 27 2021, 7:18 AM
libcxx/test/std/input.output/filesystems/class.path/path.member/path.concat.pass.cpp
144–146

If you'd prefer, I could narrow it down to the windows+dll case - that'd be a bit more verbose, but should be doable.

mstorsjo updated this revision to Diff 341411.Apr 28 2021, 11:07 PM

Narrowed down the condition to only when specifically built as DLL, included another file with the same issue.

mstorsjo updated this revision to Diff 341617.Apr 29 2021, 1:04 PM

Folded yet another case of the same into the same patch.

ldionne accepted this revision.Apr 30 2021, 2:37 PM

Thanks for the explanation. That sounds like a bug in the object format, basically, cause that means we can't implement C++ properly (which requires being able to override operator new).

This revision is now accepted and ready to land.Apr 30 2021, 2:37 PM

Thanks for the explanation. That sounds like a bug in the object format, basically, cause that means we can't implement C++ properly (which requires being able to override operator new).

Yeah I guess so.

The same effect also means that one process can have multiple copies of the C runtime (there are, historically, multiple different ones that can be linked dynamically, and each DLL can also have a private copy of the C runtime linked in statically). Then one has to take care that the same runtime that e.g. allocated memory with malloc also frees it, and e.g. calls to functions like open/write/close are confined to the same instance of the runtime.