[PATCH] Add llvm-pdbdump to tools
Aaron Ballman
aaron.ballman at gmail.com
Fri Jan 23 15:13:55 PST 2015
On Fri, Jan 23, 2015 at 5:59 PM, Zachary Turner <zturner at google.com> wrote:
> Thanks for the detailed review! Comments inline, and a new patch incoming
> soon.
>
> On Fri Jan 23 2015 at 2:39:49 PM Aaron Ballman <aaron.ballman at gmail.com>
> wrote:
>>
>> Additional thoughts and comments to what Chandler posted.
>>
>> > Index: tools/CMakeLists.txt
>> > ===================================================================
>> > --- tools/CMakeLists.txt
>> > +++ tools/CMakeLists.txt
>> > @@ -61,6 +61,10 @@
>> >
>> > add_llvm_tool_subdirectory(llvm-go)
>> >
>> > +if(MSVC)
>> > + add_llvm_tool_subdirectory(llvm-pdbdump)
>> > +endif()
>> > +
>> > if(NOT CYGWIN AND LLVM_ENABLE_PIC)
>> > add_llvm_tool_subdirectory(lto)
>> > add_llvm_tool_subdirectory(llvm-lto)
>> > Index: tools/LLVMBuild.txt
>> > ===================================================================
>> > --- tools/LLVMBuild.txt
>> > +++ tools/LLVMBuild.txt
>> > @@ -16,7 +16,7 @@
>> >
>> > ;===------------------------------------------------------------------------===;
>> >
>> > [common]
>> > -subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer
>> > llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener
>> > llvm-link llvm-lto llvm-mc llvm-nm llvm-objdump llvm-profdata llvm-rtdyld
>> > llvm-size macho-dump opt llvm-mcmarkup verify-uselistorder dsymutil
>> > +subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer
>> > llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener
>> > llvm-link llvm-lto llvm-mc llvm-nm llvm-objdump llvm-pdbdump llvm-profdata
>> > llvm-rtdyld llvm-size macho-dump opt llvm-mcmarkup verify-uselistorder
>> > dsymutil
>> >
>> > [component_0]
>> > type = Group
>> > Index: tools/llvm-pdbdump/CMakeLists.txt
>> > ===================================================================
>> > --- /dev/null
>> > +++ tools/llvm-pdbdump/CMakeLists.txt
>> > @@ -0,0 +1,16 @@
>> > +set(LLVM_LINK_COMPONENTS
>> > + Support
>> > + )
>> > +
>> > +set(MSVC_DIA_SDK_DIR "$ENV{VSINSTALLDIR}DIA SDK")
>> > +include_directories(${MSVC_DIA_SDK_DIR}/include)
>> > +if (CMAKE_SIZEOF_VOID_P EQUAL 8)
>> > + link_directories(${MSVC_DIA_SDK_DIR}/lib/amd64)
>> > +else()
>> > + link_directories(${MSVC_DIA_SDK_DIR}/lib)
>> > +endif()
>> > +
>> > +add_llvm_tool(llvm-pdbdump
>> > + llvm-pdbdump.cpp
>> > + )
>> > +target_link_libraries(llvm-pdbdump diaguids)
>> > \ No newline at end of file
>> > Index: tools/llvm-pdbdump/COMExtras.h
>> > ===================================================================
>> > --- /dev/null
>> > +++ tools/llvm-pdbdump/COMExtras.h
>> > @@ -0,0 +1,264 @@
>> > +//===- COMExtras.h - Helper files for COM operations -------------*-
>> > C++-*-===//
>> > +//
>> > +// The LLVM Compiler Infrastructure
>> > +//
>> > +// This file is distributed under the University of Illinois Open
>> > Source
>> > +// License. See LICENSE.TXT for details.
>> > +//
>> >
>> > +//===----------------------------------------------------------------------===//
>> > +
>> > +#ifndef LLVM_TOOLS_LLVM_PDBDUMP_COMEXTRAS_H
>> > +#define LLVM_TOOLS_LLVM_PDBDUMP_COMEXTRAS_H
>> > +
>> > +#include "llvm/ADT/ArrayRef.h"
>> > +#include "llvm/ADT/SmallVector.h"
>> > +
>> > +template <class F> struct function_traits;
>>
>> This nit applies to the entire patch: prefer typename over class in
>> template delcarations. Also, this should all be namespaced.
>>
>> > +
>> > +template <class R, class... Args>
>> > +struct function_traits<R (*)(Args...)> : public
>> > function_traits<R(Args...)> {};
>>
>> Variadic templates will be a problem until we drop MSVC 2012 support.
>
> Since this is intended only to support my use case of COM, and ultimately
> doesn't need to be completely generic, I'm going to add a codepath for the
> case of no variadic template support that only provides a 3 and 5 argument
> version.
With a giant FIXME that mentions the correct way to do it? ;-)
>
>
>>
>>
>> > +};
>> > +
>> > +template <class C, class R, class... Args>
>> > +struct function_traits<R (__stdcall C::*)(Args...)>
>> > + : public function_traits<R(Args...)> {};
>> > +
>> > +template <class FuncTraits, std::size_t arg> struct function_arg {
>> > + // Writing function_arg as a separate class that accesses the tuple
>> > from
>> > + // function_traits is necessary due to what appears to be a bug in
>> > MSVC.
>> > + // If you write a nested class inside function_traits like this:
>> > + // template<std::size_t ArgIndex>
>> > + // struct Argument
>> > + // {
>> > + // typedef typename
>> > + // std::tuple_element<ArgIndex, std::tuple<Args...>>::type type;
>> > + // };
>> > + // MSVC encounters a parsing error.
>>
>> What parsing error does MSVC hit?
>
> This is the smallest repro I could come up with:
>
> #include <tuple>
>
> class FooClass
> {
> public:
> int __stdcall FooFunc(int a, double b, float c)
> {
> return 0;
> }
> };
>
> template <class F> struct function_traits;
>
> template <class R, class... Args>
> struct function_traits<R (*)(Args...)> : public function_traits<R(Args...)>
> {};
>
> template <class R, class... Args> struct function_traits<R(Args...)> {
> using return_type = R;
>
> using args_tuple = std::tuple<Args...>;
>
> template<std::size_t N>
> struct Argument
> {
> typedef typename std::tuple_element<N, std::tuple<Args...>>::type type;
> };
> };
>
> template <class C, class R, class... Args>
> struct function_traits<R (__stdcall C::*)(Args...)>
> : public function_traits < R(Args...) > {};
>
> template <typename ClassType>
> struct TestClass
> {
> typedef typename
> function_traits<decltype(&ClassType::FooFunc)>::Argument<2>::type mytype;
> };
>
> int _tmain(int argc, _TCHAR* argv[])
> {
> TestClass<FooClass> test;
>
> return 0;
> }
>
>
> 1>c:\users\zachary\documents\visual studio
> 2013\projects\debuginfotest\debuginfotest.cpp(40): error C2059: syntax error
> : '<'
> 1> c:\users\zachary\documents\visual studio
> 2013\projects\debuginfotest\debuginfotest.cpp(41) : see reference to class
> template instantiation 'TestClass<ClassType>' being compiled
> 1>c:\users\zachary\documents\visual studio
> 2013\projects\debuginfotest\debuginfotest.cpp(40): error C2238: unexpected
> token(s) preceding ';'
>
> I don't consider myself a C++ expert, but note the same line works if I pull
> it out of TestClass and replace ClassType with FooClass.
Huh, that's neat. Thank you for sharing!
>
>>
>> >
>> > +//=============================================================================
>> > +template <class EnumeratorType> class ComDataRecordIterator {
>> > +public:
>> > + explicit ComDataRecordIterator(CComPtr<EnumeratorType> enumerator,
>> > + uint32_t currentRecord)
>> > + : Enumerator(enumerator), CurrentRecord(currentRecord) {}
>> > + ComDataRecordIterator() {}
>> > +
>> > + ComDataRecordIterator &operator++() {
>> > + // Release the current item so that Enumerator->Next() is happy.
>> > + ++CurrentRecord;
>> > + ReadNextRecord();
>>
>> This weirds me out a bit. Since ReadNextRecord can fail, but you are
>> incrementing CurrentRecord regardless, doesn't this mean you can get
>> to end() but not compare equal to something returned by end()?
>
>
> Presumably, but isn't incrementing end() undefined behavior anyway?
It is, but I am talking about:
auto i = blah.begin(); // Succeeds
i++; // Fails for some reason
if (i == end()) // ??
;
>
>>
>> > +
>> > +private:
>> > + void ReadNextRecord() {
>> > + RecordData.clear();
>> > + ULONG Count = 0;
>> > + DWORD RequiredBufferSize;
>> > + HRESULT hr = Enumerator->Next(1, 0, &RequiredBufferSize, nullptr,
>> > &Count);
>> > + if (hr == S_OK) {
>>
>> Please use the SUCCEEDED macro.
>
> Specifically here, that won't work.
> https://msdn.microsoft.com/en-us/library/64c9d90x.aspx It returns S_OK if
> it succeeds, and S_FALSE if it fails. Note that SUCCEEDED(S_FALSE) is true.
Ughhhhhh! I forgot about that horribleness. :-/
>
>>
>>
>> > + RecordData.resize(RequiredBufferSize);
>> > + DWORD BytesRead = 0;
>> > + hr = Enumerator->Next(1, RequiredBufferSize, &BytesRead,
>> > + RecordData.data(), &Count);
>> > + }
>> > + if (hr == S_FALSE) {
>>
>> Please use the FAILED macro. This code will fail to end the
>> enumeration if Next() fails for any reason other than S_FALSE.
>
> Same issue as before, in that FAILED(S_FALSE) is false. But your point is
> still valid, that other error cases aren't being handled here. So I think I
> need to check hr == S_FALSE || FAILED(hr)
Yes, and same facedesking from me. ;-)
>
>>
>>
>> > + // This is the end of the enumeration.
>> > + RecordData.clear();
>> > + }
>> > + }
>> > +
>> > + CComPtr<EnumeratorType> Enumerator;
>> > + uint32_t CurrentRecord;
>> > + llvm::SmallVector<uint8_t, 128> RecordData;
>>
>> Why 128? It seems rather large, and like something the caller might
>> have a much better idea over.
>
> You're right it's probably large. 32 or 64 might be better. Some
> experiments show that most records are 16, 32, or 40 bytes. I didn't know
> that until I wrote this and ran my first dump though. On the other hand,
> letting the caller specify it clutters up the template argument list, which
> is kind of unfortunate. Perhaps best to just err on the smaller side with
> something like 32?
For generality, I think it would make sense to allow the consumer to
pick it, but since this seems to be only for use with llvm-pdbdump, I
think it's fine to set to 32 for right now.
>
>>
>> > +
>> > +namespace llvm {
>> > +namespace sys {
>> > +namespace windows {
>> > +extern std::error_code UTF8ToUTF16(StringRef utf8,
>> > + SmallVectorImpl<wchar_t> &utf16);
>> > +extern std::error_code UTF16ToUTF8(const wchar_t *utf16, size_t
>> > utf16_len,
>> > + SmallVectorImpl<char> &utf8);
>>
>> Ugh, this really needs to find a reasonable home. I'm starting to
>> suspect that now is the time.
>
> Noo!!!!!!!!!!!!!!! Don't make me do it :) Or at least, lemme get this
> change in first. I agree that it's unfortunate. Months ago I pushed for
> allowing windows-specific stuff in Support to be exposed through headers,
> but it seemed like there was considerable resistance to it. This is exactly
> the kind of thing I was worried about.
I would be fine doing it as a secondary step to clean this code up,
but this code (and other places where it's used) certainly provide a
compelling case for the refactoring.
~Aaron
More information about the llvm-commits
mailing list