I made changes to a function in a COM DLL. I've been unable to figure out how to debug the changes I made.
Background:
I recently inherited a Visual Studio 2012 C++ project that dates back many
years. I'm running Win7 Professional 64-bit.
The top-level design of the project is this:
The code that does most of the work is encapsulated in COM DLLs.
For each DLL there's a separate wrapper function that calls:
(1) CoInitialize
(2) CoCreateInstance
(3) CoUninitialize
There's a main program that presents a dialog to allow a user to select an option. Based on the selected option, the main program calls the appropriate wrapper function, which then runs the code in the corresponding COM DLL.
Problem Details:
(1) I've been unable to step through the code in the Visual Studio debugger.
(Trying to run in the debugger produces the error "Unable to start program
", where the named DLL is different from the modified one.)
(2) I put "fprintf(stderr, ...)" calls in the modified DLL code, but didn't get any output from the "fprintf" calls. (I do see output from "fprintf" calls I added to the wrapper function that invokes the DLL.)
I also tried opening a temporary debug file using "fopen", writing debug statements to the file, then fflush, and fclose. Also no output.
(3) I noticed a post (Calling fprintf from dynamic library (c++)) that suggested that, although "fprintf(stderr, ...)" should work, it would be better to implement a callback to a debug function in the main program. I attempted to do that.
The changes compile, but the linker reports an undefined reference to the name of the function in the DLL that was intended to allow the main program
to pass in a pointer to a callback function.
I'm confused by the undefined reference, because the modified DLL has a different exported function that the linker is able to resolve.
Specifically:
__declspec(dllexport) void SetLogFunc(LogFunc LogFuncPtr) [The new function.]
__declspec(dllexport) BOOL DoRosSum(SRosSumData* pRosSumData) [The existing function.]
I used the "ack" utility to search the entire codebase for the project,
including Visual Studio project files and binary files, looking for
references to "DoRosSum", and can't find any place where there's a reference
to "DoRosSum", but not also a reference to "SetLogFunc".
("SetLogFunc" is listed by "dumpbin" as an exported function.)
I should also mention that I reverted all my changes except for:
the "SetLogFunc" function in the COM DLL,
the callback debug function in the main program, and
the call to ""SetLogFunc"" in the main program.
so I don't think the problem I'm having getting debug output, or running in the VS2012 debugger, is related to the modification I originally made to the DLL code.
Apologies for the long post. In recent years I've mostly been working in C#, or working on linux systems. I have no experience with COM DLLs, so I may be
missing something simple.
If anyone has any thoughts on how to proceed I would appreciate it.
For the first question,
https://learn.microsoft.com/en-us/visualstudio/debugger/how-to-debug-from-a-dll-project?view=vs-2017
I think you can check if you have done this yet. Usually, if you haven't set up command correctly in project property/debugging, running debugger in VC always show you the message:
Unable to start program '......\your DLL'.
Since DLL need to be execute with an executable(.exe).
I noticed that you said the error message 'the named DLL is different from the modified one'.
Your main program will run with multiple DLL right? I think you also need to make sure you put other DLL(.dll) file in the folder of your main program application.
For undefined reference issue,
If you can compile the functions in DLL sides, it means the logic here is ok. However, linker report undefined error then it should be some issues for exporting this function to main program side.
I suppose you to first check in main program side to see if you include the correct header file.
Like right clicking the function name in main program "Go to Definition" will show you the header file. You can then see if the header file is the correct one.
Then you can check if you export functions correctly. You need to make sure main program link to the new compiled Object File Library(.lib). Every time you compile your DLL project you need to make sure main program link to the new compiled .lib and .dll and include the new header file.
Hope these helps.
Related
I am trying to write a plugin for a popular program whose code and compilation process I do not have control over. The program is written in C. However, I have written parts of my plugin in C++, since I use the QT5 library for graphics capabilities. The functions that the C program calls are written in C.
When the C program tries to load the plugin (shared library), it produces this error:
dlopen('build/libfoo.so') failed: build/libfoo.so: undefined symbol: _ZTV13JoystickPanel
JoystickPanel is a class in the C++ part of the program.
I've tried rewriting parts of the program in C, but the error was unaffected. I know that I could rewrite the entire program in C, but I'd rather not have to switch to another, more C-friendly GUI framework. I've also opened up libfoo.so in a text editor and search for JoystickPanel, but it appears to be mangled as _ZN13JoystickPanel.
Are there any compiler options or solutions that I'm missing?
I have no idea what _ZN13JoystickPanel means, since it's not apparently a valid mangled C++ name. It should perhaps be _ZN13JoystickPanelE, which would translate to JoystickPanel. That'd be symbol name for sure, but without much meaning anyway. You must have truncated something: I tried quite a bit and just can't generate an object file that would include _ZN13JoystickPanel as the complete symbol. It's just a prefix, there should be a "second half" attached to it - was there?
But _ZTV13JoystickPanel is the vtable for the JoystickPanel class. It's missing because you didn't provide implementations for all the virtual methods of the JoystickPanel class. Most likely, you didn't invoke moc properly, or forgot to compile and link its output.
You need to show a complete build script for your plugin at the very least (the .pro file, or CMakeLists.txt). You'll also need to provide a github link to your project (I presume it's open source).
The symbols you want to find in the compiled output are at least _ZTV13JoystickPanelD#Ev - virtual destructors, where # is a digit, _ZTV13JoystickPanel - the virtual method table,
Those symbols may be absent when compiled with optimization and/or LTCG, but also absent will be references to them.
You may wish to delete the build folder and rebuild your project, just to be sure. qmake is bad at dependency generation for the makefiles it produces, so if you use it, I suggest switching to cmake + ninja.
Apparently, I'd forgetten to put the #include "moc_controller.cpp" line at the bottom of a file that needed it.
For anyone else chasing this issue while using Qt on CMake, consider making sure that the proper lines are added.
The problem
I have a C++ (*.cpp) file, which is part of a static library project that I can't put an active breakpoint. When I do, it gives me the notification seen in the title of this post. I can put breakpoints in any other C++ file in that same project and it will be hit during debugging. There's nothing special about this C++ file. I use CMake to generate the projects and I also refer to the class in the executable project. There are no linking errors, just that debugger says that no debug symbols have been loaded for that source file. I have tried several ways to try and diagnose what's wrong and I don't have a good answer as to what's going on in my case.
What I have tried
Compare this file with other *.cpp files in the same project: I cross-check the compiler flags between this and other files that I tested to verify are able to put a valid breakpoint. There's nothing different.
Rebuild the entire solution: As you might've guess, this didn't help
Recreate the entire solution using CMake: This didn't make any difference either.
Included the file in the source file that had main() and referred to the class in that file: This made the difference. I was able to put breakpoint in the class and its code was getting executed, while previously, it wasn't.
More Information about code
The C++ file I'm referring to is RoCreateCharacterSuccess.cpp
The job of roREGISTER_PACKET is to register this packet class with another class (RoPacketTranslator) when the application initializes.
The constructor of RoCreateCharacterSuccess gets invoked when registering the packet class.
When the breakpoint isn't active, this constructor doesn't get invoked. I know this because this packet class doesn't exist in the class that it's supposed to be registered with. It's like RoCreateCharacterSuccess.cpp is never part of the static library it's supposed to be in. But if I purposefully change the file to introduce a syntax error, the library fails to build.
To make this file be able to have active breakpoints, I have to manually register the packet with the translator in the application.
Has anyone else seen such an issues? I'm stumped at this point trying to understand what's happening. Any help in shedding light into what's happening here would be great! Thanks for your time reading this question.
EDIT: I forgot to mention that this problem was diagnosed because I was trying to diagnose why the character creation packet didn't get translated into RoCreateCharacterSuccess object when the character gets successfully created. I later found that RoCreateCharacterSuccess class was not getting registered with RoPacketTranslator class. Trying to put a breakpoint to check if the constructor was called lead to this question.
Solution
Thanks to #user1, I figured out what was happening. So, in my executable, where I refer to this class (or an instance of it), I was only accessing RoCreateCharacterSuccess::getCharacter(), which is in the header-file and probably got inline'd by the compiler into the executable. As far as the compiler could see, that was my only interaction with that class. I wasn't invoking its constructor, which was defined in the cpp file. This means that the compiler has the opportunity to optimize that part of the code away (I did have that option turned on).
The solution: I moved the definition of the only method I interact with, RoCreateCharacterSuccess::getCharacter(), into the cpp file, therefore avoiding inline'ing and forcing the compiler to link to that part of the static library that defined RoCreateCharacterSuccess class, thereby triggering the act of registering RoCreateCharacterSuccess class with the translator class.
First of all, I don't see any issue here. This is not a problem with C++ compiler or linker.
I can put breakpoints in any other C++ file in that same project and
it will be hit during debugging. There's nothing special about this
C++ file. I use CMake to generate the projects and I also refer to the
class in the executable project. There are no linking errors, just
that debugger says that no debug symbols have been loaded for that
source file.
What going on here really is, When your executable program doesn't see explicit call to module - RoCreateCharacterSuccess.cpp in your static library, It will not link to the module.
If the program required a symbol defined in the module, that module would get linked; if not, it would be skipped. Thus any functions, symbols in RoCreateCharacterSuccess.cpp module will never exist.
RoCreateCharacterSuccess.cpp is considered an unused module.
Since symbols have not been loaded for the module, Visual Studio ends up reporting that the breakpoints will not be hit. Which is obvious.
To make this file be able to have active breakpoints, I have to
manually register the packet with the translator in the application.
When you manually registered the packet with the translator module in application, RoCreateCharacterSuccess.cpp module got linked and the breakpoint was available. You were able to hit the breakpoints in that module.
It's like RoCreateCharacterSuccess.cpp is never part of the static
library it's supposed to be in. But if I purposefully change the file
to introduce a syntax error, the library fails to build.
BTW, This is true for any program, any syntax errors will result in compilation failure. I understand you did that to check if your program was loading correct module, but that really is not the problem.
Update #Vite Falcon I'm glad my answer gave you hint to find out why the breakpoint wasn't active. Evidently, It was compiler who was optimising inline function calls and breaking the connection between the module and program.
I'm not too sure of how to ask this, so please comment if I'm being unclear about something.
I have a project which uses a custom class called CManager. Most of my classes in this project inherit from this one and in CManager() (constructor), I add one to the count of CManager object, the count being a static variable in this class. Now, this project used to be compiled as a .dll (dynamic library), but my employer asked me to compile it as a .lib this time, while stripping away a lot of code. Now I have stripped away all the code that wasn't needed and compile it without error... But, when I am creating a .lib, I get an error when I try to execute the program saying that there is an unhandled access violation reading. Here is the code
int CManager::m_count = 0;
CManager::CManager()
{
++m_count; <- Exception here
}
I don't know why I have this error. m_count is a private static int variable declared in the .h.
Since I didn't understand why it wasn't working, I tried compiling the project as a .dll, just so I wouldn'd be doing nothing. And for some reason... it worked. It compiles AND execute (run, wtv).
Now my question is... why is this happening? What explains this?
PS: This project has to include 5 other projects' .lib (or dll), but it work either ways. This project is included by my main, and it is when I try to execute my main that I get the error. The project is just a bunch of algorithms, my main app being the GUI. My main app is an MFC app.
Thanks!
EDIT 1:
While debugging, I found out that if I import the project using a static lib, when passing from my main's function call to the .lib implementation, I loose the object: I call a function on my object, and when I'm in the function, the value of this (refering the object) is null.
If I used a dll, it works perfectly. The object keep its value when a function is called on it.
But I still want to use a .lib, so I don't really know why this happens and how to fix it.
I found it. Like Mark Ransom said in the comments, the problem was not in the code, it was in my project properties. I was creating a .lib instead of dll, but didn't change the runtime library accordingly. So in Project Properties -> C/C++ -> All Options -> Runtime Library, I started using MD and it worked.
Also make sure Runtime Library and general use of MFC are compatible, look here for details.
I'm still not to sure of how using MT created problems, but at least I can run my program now.
I'm writing a trivial windows console application that links to a bunch of static libraries via a
#pragma comment(lib, "SomeLibrary.lib");
(Amongst these libaries is SQLite3.lib)
When I start my program, the code in my main function doesn't seem to be executed, but instead the command line propt of the sqlite console application appears. Strange, isn't it? The only thing I can imagine causing this is that somehow another main function is defined somewhere else (supposedly in the static sqlite library) and that one is exectuted.
Is that possible? Is there some way to find out if there's a main function defined in a static library? And is there some way to give my main function precedence over the other one?
The sqlite3.lib library has a main function because you compiled the source code of the SQLite command-line shell into it.
Compile that library without shell.c.
It should contain nothing but sqlite3.c.
So, I have an interesting issue. I am working with a proprietary set of dlls that I ,obviously, don't have the source for. The goal is to write an intermediate dll that groups together a large series of funnction calls from the proprietary dlls. The problem I am having, when compiling with g++, is that I get errors for the original dlls along the lines of:
cannot export libname_NULL_THUNK_DATA. Symbol not found.
If I add a main and just compile to an executable everything works as expected. I'm using mingw for compilation. Thanks for any help.
In response to the first reply: Either I'm confused about what you're saying or I didn't word my question very well. I'm not explicitly trying to export anything from my wrapper I am just calling functions from their dlls. The problem is that I get errors that it can't export these specific symbols from the dll to my wrapper. The issue is that I'm not even entirely sure what these _NULL_THUNK_DATA symbols are for. I did a search and read somewhere that they shouldn't be exported because they're internal symbols that windows uses. I have tried using the --exclude-symbols directive to the linker but it didn't seem to do anything. I apologize if I'm completely misunderstanding what you're trying to say.
So, I think my issue was related to this. When just compiling a standard executable that uses a dll I was able to include the headers and directly call the functions for example:
#include :3rdparty.h
int main(){
dostuff(); // a function in the 3rdparty.dll
}
this would compile and run fine. I just needed to link the libraries in the g++ command.
When linking with the -shared flag I would get these errors (with main removed of course). I think it has something to do with the fact that by default g++ attempts to import all symbols from the dll. What I didn't understand is why this happens in the dll vs in an executable. I will try doing it using GetProcAddress(). Thank you!
it should be as easy as you think it should be.
eg:
your dll code needs:
void doStuff()
{
3rdparty.login();
3rdparty.dostuff();
3rdparty.logoff();
};
so far - so good, you've included the right headers .... (if you have them, if you don't then you need to import the library using LoadLibrary(), then create a function pointer to each exported dll entrypoint using GetProcAddress() and then call that function pointer)
You then link with the 3rd party lib and that's it. Occasionally you will have to wrap the definitions with 'extern "C"' in order to get the linkage name mangling correct.
As you say you're using g++, you can't be getting confused with __declspec(dllimport) which is a MS VC extension.
"Compiling" tells me that you're approaching this from the wrong end. Your DLL should not export its own wrapper functions, but directly refer to exports from other DLLs.
E.g. in a Windows Kernel32.DEF file, the following forward exists:
EXPORTS
...
HeapAlloc = NTDLL.RtlAllocHeap
There's no code for the HeapAlloc function.