crosire / blink

A tool which allows you to edit source code of any MSVC C++ project live at runtime

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

blink.exe crash when editing program built with the /bigobj flag

Ybalrid opened this issue ยท comments

I just found out about this project and it looks really interesting. ๐Ÿ˜ƒ

I'm trying to see if I can edit code from a little game engine project I have and see the result right away with blink.

The target program is built in Debug mode.

I attach blink.exe to the program by giving it the PID.

When I modify a file, I have a debug assertion triggered inside vector's operator().

This occurs in blink::application::build_compile_command_line() when creating
std::vector<char> debug_data(section->SizeOfRawData);

section here is an iterator returned by the std::find_if function that seems to look for a section of the name .debug$S but doesn't find it.

The value of the iterator is never checked before de-referencing it.

I'm currently trying to understand why my program doesn't have a "debug" section here, but I really feel like the following code should only be executed after testing section != sections.end() to check if it was found... ๐Ÿค”

(It seems that this function in blink just returns an empty string when an error is found. I'm going to add an additional check before attempting to use the section)

Looking at the log, it does find all the necessary source files and everything, and it watches for the modifications. But when you save your changes to the file, it seems it tries to invoke the compiler (cl.exe) but doesn't find it:

Starting file system watcher for 'e:\git\sdl_base' ...
Detected modification to: e:\git\sdl_base\build\enc_temp_folder\dea695625b187ed511a9541fdb327a1\application.cpp
'cl.exe' is not recognized as an internal or external command,
operable program or batch file. <--- I suppose here lies the issue
Finished compiling "e:\git\sdl_base\build\enc_temp_folder\dea695625b187ed511a9541fdb327a1\application.temp.obj" with code 9009.
Detected modification to: e:\git\sdl_base\src\application.cpp

Okay, launching blink.exe from the Visual Studio developer command prompt (a place where cl.exe is in the path) doesn't resolve the issue.

blink mainly becomes useful if it can automatically deduce the compile command-line from the input object files. The default command-line does not have any SDK paths or defines set, so would most likely fail to compile regardless of whether cl.exe is in your PATH or not. You'd have to manually change the fallback command-line in source code to suit your specific application.

So the real issue here is finding out why your object files do not have a .debug$S section. This should be standard when compiling with debug symbols enabled (/Zi or /ZI). It is however missing when compiling with /Z7 so make sure you use one of the other two!! See also #6 (comment).

Hi, the project is built with the standard configuration for "Debug" (as generated by CMake) and /Zi is enabled

So, I'm trying to understand the problem, here's the raw output of dumpbin on the .obj file associated with the changed source file

e:\git\sdl_base\build\test_project_exe.dir\Debug>dumpbin application.obj
Microsoft (R) COFF/PE Dumper Version 14.16.27027.1
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file application.obj

File Type: EXTENDED COFF OBJECT

  Summary

          38 .CRT$XCU
          75 .bss
       17D50 .chks64
         CAD .data$r
       F7B94 .debug$S
          58 .debug$T
          F6 .drectve
        83B8 .pdata
        E8DD .rdata
        154C .rdata$r
           8 .rtc$IMZ
           8 .rtc$TMZ
         194 .text$di
       42D71 .text$mn
        4F73 .text$x
          27 .text$yd
        B468 .xdata
         288 .xdata$x

e:\git\sdl_base\build\test_project_exe.dir\Debug>

Seems there's a .debug$S section in this .obj file ๐Ÿค”

So, I set a breakpoint in blink.cpp while debugging my program (after blink did it's little process injection thing)

This is clearly the file being opened at this point :
image

While stepping through with the debugger, when reading the number of section after the first call to ReadFile, the number of section in the header is set to 0xffff this doesn't seem normal...

I'm suspecting it's not reading the object file properly at this point. If I have any more info, I'll post here. If somehow I fix it myself, I'll PR.

Do you have any idea why it is not picking up the sections in the file properly?

okay so, the file is indeed read properly (this would be strange)
image

Maybe that object file is not of the right format?

Now that I think about it, the project is linking to some pretty big header only libraries (ChaiScript, GLM) in some of it's compilation units, and I had to add the /bigobj to my build options. Reading MSDN, this increase the possible number of sections in the file to a 32bit value. So, what's probably happening here is that blink is not reading the header properly because... Well, it's not a normal COFF header anyway...! ๐Ÿ˜ฎ


update when a symbol has been built with /bigobj, the header is an extended one. the Win32 API has a structure called ANON_OBJECT_HEADER_BIGOBJ that has the correct layout. I need to confirm this, but it's possible to test the difference by checking in the header (read normally) if the machine type is 0x0000 and the number of sections is 0xFFFF.

Gonna do some more testing, but I feel like I'm onto something


update 2 I have a patch where now it finds and read correctly the .debug$S section from the file, I'm going to pull request it soon.

Now I'm facing another issue where it is not finding the compiler command line inside the section.

using dumpbin, it seems that the strings "cdw" or "cl." or "-Zi" aren't present in this section of the object file.

Doing a full dump, nowhere in that file you can find these strings either.

Correct me if I'm wrong, but shoudln't I be able to find the compilation command of an object file if it has been build with /Zi ?

it seems that the compilation command is stored in the object file only with /ZI , not with /Zi in this specific case

Nice findings! Yeah, it seems like the command-line is only stored with /ZI after all (kinda makes sense given what that option is meant for). It used to be that this information was stored in the PDB file itself, but that was dropped with current Visual C++ versions. So for now the only automatic way to gather information about how to compile the input files is with /ZI. Bit unfortunate considering that the rest of blink should work with the other PDB options too.

Yes. Now I'm currently trying to fix the linker for this usecase in #25. Right now it's crashing because some symbol somewhere is reffering to a section number that is way higher that the actual number of sections in the object file...

update: It seems that I4m still reading garbage inside the link() function when reading the symblols table, despite using the correct PointerToSymbolTable value, but I'm having trouble getting VisualStudio's debugger to cooperate right now ;-)

So, the first symbol seems to be read mostly properly, at least it has the correct name. So I now suspect that in this non-normal COFF file format, we need another struct than "IMAGE_SYMBOL" too.

The problem is, the documentation from microsoft on this is praticularly lacking. Somone even complained about this on the microsoft forums... xD
https://developercommunity.visualstudio.com/idea/408610/pecoff-format-specification-issues.html

And the help about the /bigobj compiler flag only mention that it permits to have more sections and symbols in object files.

So I'm mostly going blind on this, but since it's so close to work, I'm not going to stop there...

Okay, so in the one symbol that has the right name, both it's section number and type are at 0xFFFF. I need to find the "modified" version of the header that matches this, somewhere.

While I try to piece the differences together by reading header files and "trying stuff", I left some feedback to Microsoft because the exact effect of this compiler switch are poorly documented, and the documentation about the COFF file format is lacking. https://github.com/MicrosoftDocs/cpp-docs/issues/873

found that there's a IMAGE_SYMBOL_EX. It's a bigger sutrcutre. It's probably what I was looking for. I can't find much documentation about it, but it uses a LONG for the section number instead of a SHORT, so it has to be this.

I need to do some refactor of the linker code to be able to use this... ๐Ÿ˜“

I fixed it for bigobj. (see #25)

There's 2 things that changes when object files are "big" objects files :

1 - the COFF header is an extended version
2 - Each symbols uses an extended version that occupies more than the 18 bytes of the regular one.

What I did is that I refactored the "link" function past the problematic point to some templated things around the type of the symbol records.

All of the reallocation logic is the same.