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

src,win: informative stack traces #23822

Merged
merged 1 commit into from
Oct 30, 2018
Merged

Conversation

refack
Copy link
Contributor

@refack refack commented Oct 22, 2018

Refresh Win32SymbolDebuggingContext::LookupSymbol to use more APIs
Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address
Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-undecorated-symbol-names

Before:

DEV D:\code\node>Debug\node.exe test\parallel\test-fs-stat-bigint.js
C:\WINDOWS\system32\cmd.exe - Debug\node.exe  test\parallel\test-fs-stat-bigint.js [37304]: d:\code\node\deps\gsl\gsl\gsl_assert:132: Assertion `unknown' failed.
 1: 00007FF7A3B9F67A
 2: 00007FF7A3B0A1B7
 3: 00007FF7A3B0A307
 4: 00007FF7A394BB25
 5: 00007FF7A394B844
 6: 00007FF7A394AC6A
 7: 00007FF7A394BF91
 8: 00007FF7A3A7C36B
 9: 00007FF7A480D165
10: 00007FF7A480BB5C
11: 00007FF7A480CE1B
12: 00007FF7A480C6C3
13: 0000039475106628

After (with PDB available):

DEV D:\code\node>Debug\node.exe test\parallel\test-fs-stat-bigint.js
C:\WINDOWS\system32\cmd.exe - Debug\node.exe  test\parallel\test-fs-stat-bigint.js [38392]: d:\code\node\deps\gsl\gsl\gsl_assert:132: Assertion `unknown' failed.
 1: 00007FF7A3B9F67A node::DumpBacktrace [d:\code\node\src\debug_utils.cc]:L237+138
 2: 00007FF7A3B0A1B7 node::Abort [d:\code\node\src\node.cc]:L1030+39
 3: 00007FF7A3B0A307 node::Assert [d:\code\node\src\node.cc]:L1049+295
 4: 00007FF7A394BB25 gsl::details::throw_exception<gsl::narrowing_error> [d:\code\node\deps\gsl\gsl\gsl_assert]:L137+149
 5: 00007FF7A394B844 gsl::narrow<double,unsigned __int64> [d:\code\node\deps\gsl\gsl\gsl_util]:L117+148
 6: 00007FF7A394AC6A node::FillStatsArray<double,v8::Float64Array> [d:\code\node\src\node_internals.h]:L328+634
 7: 00007FF7A394BF91 node::FillGlobalStatsArray [d:\code\node\src\node_internals.h]:L360+129
 8: 00007FF7A3A7C36B node::fs::LStat [d:\code\node\src\node_file.cc]:L985+1083
 9: 00007FF7A480D165 v8::internal::FunctionCallbackArguments::Call [d:\code\node\deps\v8\src\api-arguments-inl.h]:L120+469
10: 00007FF7A480BB5C v8::internal::`anonymous namespace'::HandleApiCallHelper<0> [d:\code\node\deps\v8\src\builtins\builtins-api.cc]:L111+684
11: 00007FF7A480CE1B v8::internal::Builtin_Impl_HandleApiCall [d:\code\node\deps\v8\src\builtins\builtins-api.cc]:L139+507
12: 00007FF7A480C6C3 v8::internal::Builtin_HandleApiCall [d:\code\node\deps\v8\src\builtins\builtins-api.cc]:L127+451
13: 000003BBE9486628

Fallback with no PDB loaded:

 1: 00007FF7A3B9F67A AES_cbc_encrypt+5220586
 2: 00007FF7A3B0A1B7 AES_cbc_encrypt+4609063
 3: 00007FF7A3B0A307 AES_cbc_encrypt+4609399
 4: 00007FF7A394BB25 AES_cbc_encrypt+2780565
 5: 00007FF7A394B844 AES_cbc_encrypt+2779828
 6: 00007FF7A394AC6A AES_cbc_encrypt+2776794
 7: 00007FF7A394BF91 AES_cbc_encrypt+2781697
 8: 00007FF7A3A7C36B AES_cbc_encrypt+4027867
 9: 00007FF7A480D165 AES_cbc_encrypt+18252757
10: 00007FF7A480BB5C AES_cbc_encrypt+18247116
11: 00007FF7A480CE1B AES_cbc_encrypt+18251915
12: 00007FF7A480C6C3 AES_cbc_encrypt+18250035
13: 0000039475106628
Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines

@refack refack self-assigned this Oct 22, 2018
@refack refack added c++ Issues and PRs that require attention from people who are familiar with C++. windows Issues and PRs related to the Windows platform. post-mortem Issues and PRs related to the post-mortem diagnostics of Node.js. labels Oct 22, 2018
@refack
Copy link
Contributor Author

refack commented Oct 22, 2018

CI: https://ci.nodejs.org/job/node-test-pull-request/18049/
CI: https://ci.nodejs.org/job/node-test-commit/22540/
/CC @nodejs/platform-windows @nodejs/diagnostics

class Win32SymbolDebuggingContext final : public NativeSymbolDebuggingContext {
public:
Win32SymbolDebuggingContext() {
explicit Win32SymbolDebuggingContext(void* out) {
out_ = reinterpret_cast<FILE*>(out);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not just take a FILE* as input parameter?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Polymorphism with the POSIX class:
https://github.com/nodejs/node/blob/0b565eb7f7404fb8774865826afba10c1919788f/src/debug_utils.cc#L253
I could move the cast to https://github.com/nodejs/node/blob/0b565eb7f7404fb8774865826afba10c1919788f/src/debug_utils.cc#L232-L235
(Now that I see it I could assume it's always stderr and eliminate the argument).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is only used for printing diagnostic information, I don’t think an extra parameter is necessary at all; we can always just use stderr

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

src/debug_utils.cc Outdated Show resolved Hide resolved
// Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address
// Patches:
// * Use `fprintf(out, ` instead of `printf`
// * `sym ~= line` on success
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does the ~= mean?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assign almost all fields... I'll rephrase
(I might have used more fields in an earlier imp)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rephrased

char demangled[MAX_SYM_NAME];
using NameAndDisplacement = std::pair<std::string, DWORD64>;
NameAndDisplacement WrappedSymFromAddr(DWORD64 dwAddress) const {
HANDLE hProcess = current_process_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

snake_case for variables.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// Refs: https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address
// Patches:
// * Use `fprintf(out_, ` instead of `printf`
// * `sym.filename = pSymbol->Name` on success
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel this information about what you changed isn’t particularly useful. Both of the patches are fairly trivial. This also apply to the other places.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd rather keep the comment, AFAIK more comment never hurt...
Also they might be useful since the examples on MSDN change from time to time (for example they changed since the last time this code was lifted, and I had to reverse engineer the patches).

Copy link
Member

@addaleax addaleax Oct 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also they might be useful since the examples on MSDN change from time to time

Wouldn’t that be a good reason to drop the comment, since the diff can change on both sides, and so the Patches: list can grow out of date?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll sleep on it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since MSDN does have a history, I'm thinking the comments might still be useful.
Anyway they are free, and IMHO more info is almost always better then missing info...
I did go over them to make sure they are uniform, and not too obfuscated.

// * `sym ~= line` on success

// Patch: made into arg - DWORD64 dwAddress;
DWORD dwDisplacement;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: one space after DWORD.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack.

@richardlau
Copy link
Member

cc @gireeshpunathil There may be opportunities here to reuse some code for Windows backtraces w.r.t. node-report in core and this PR.

oss << "+" << dis;
}
return oss.str();
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we put this back in the .cc file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.
But may I ask why?

src/debug_utils.cc Show resolved Hide resolved
class Win32SymbolDebuggingContext final : public NativeSymbolDebuggingContext {
public:
Win32SymbolDebuggingContext() {
explicit Win32SymbolDebuggingContext(void* out) {
out_ = reinterpret_cast<FILE*>(out);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since this is only used for printing diagnostic information, I don’t think an extra parameter is necessary at all; we can always just use stderr

} else {
// SymFromAddr failed
const DWORD error = GetLastError();
#ifdef _DEBUG
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When is #ifdef _DEBUG defined? Is it the same as our #ifdef DEBUG?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'defines': [ 'DEBUG', '_DEBUG', 'V8_ENABLE_CHECKS' ],

I picked it arbitrarily... I'll change

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since I don’t know much about the Windows debugging stuff … how common would these errors be? i.e. do we only print them in debug mode because they would otherwise appear relatively frequently?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i.e. do we only print them in debug mode because they would otherwise appear relatively frequently?

Yes very frequent. If the *.pdb is not available, or is partial. Also the last (deepest) frame almost always fails to resolve.

Done /s/_DEBUG/DEBUG


SymbolInfo LookupSymbol(void* address) override {
auto dwAddress = reinterpret_cast<DWORD64>(address);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DWORD64 dw_address

Copy link
Contributor Author

@refack refack Oct 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack.
But the type stated explicitly on the rhs.
And the name is copied from the example, which I'd rather not change...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ack.

@refack
Copy link
Contributor Author

refack commented Oct 23, 2018

@refack
Copy link
Contributor Author

refack commented Oct 23, 2018

i.e. do we only print them in debug mode because they would otherwise appear relatively frequently?

Yes very frequent. If the *.pdb is not available, or is partial. Also the last (deepest) frame almost always fails to resolve.

Debug mode exe:

Example output with .pdb present:

DEV D:\code\node>Debug\node.exe test\parallel\test-fs-stat-bigint.js
C:\WINDOWS\system32\cmd.exe - Debug\node.exe  test\parallel\test-fs-stat-bigint.js [37716]: d:\code\node\src\node_file.cc:962: Assertion `(argc) >= (11)' failed.
 1: 00007FF61F72EE8A node::DumpBacktrace+138 [d:\code\node\src\debug_utils.cc]:L254
 2: 00007FF61F6999C7 node::Abort+39 [d:\code\node\src\node.cc]:L1030
 3: 00007FF61F699B17 node::Assert+295 [d:\code\node\src\node.cc]:L1049
 4: 00007FF61F60B7AC node::fs::LStat+108 [d:\code\node\src\node_file.cc]:L962
 5: 00007FF62039C925 v8::internal::FunctionCallbackArguments::Call+469 [d:\code\node\deps\v8\src\api-arguments-inl.h]:L120
 6: 00007FF62039B31C v8::internal::`anonymous namespace'::HandleApiCallHelper<0>+684 [d:\code\node\deps\v8\src\builtins\builtins-api.cc]:L111
 7: 00007FF62039C5DB v8::internal::Builtin_Impl_HandleApiCall+507 [d:\code\node\deps\v8\src\builtins\builtins-api.cc]:L139
 8: 00007FF62039BE83 v8::internal::Builtin_HandleApiCall+451 [d:\code\node\deps\v8\src\builtins\builtins-api.cc]:L127
SymGetLineFromAddr64 returned error : 126
SymFromAddr returned error : 126
 9: 000003B89AE86628

Without .pdb

DEV D:\code\node>Debug\node.exe test\parallel\test-fs-stat-bigint.js
C:\WINDOWS\system32\cmd.exe - Debug\node.exe  test\parallel\test-fs-stat-bigint.js [37020]: d:\code\node\src\node_file.cc:962: Assertion `(argc) >= (11)' failed.
SymGetLineFromAddr64 returned error : 487
 1: 00007FF61F72EE8A AES_cbc_encrypt+5218554
SymGetLineFromAddr64 returned error : 487
 2: 00007FF61F6999C7 AES_cbc_encrypt+4607031
SymGetLineFromAddr64 returned error : 487
 3: 00007FF61F699B17 AES_cbc_encrypt+4607367
SymGetLineFromAddr64 returned error : 487
 4: 00007FF61F60B7AC AES_cbc_encrypt+4024860
SymGetLineFromAddr64 returned error : 487
 5: 00007FF62039C925 AES_cbc_encrypt+18250645
SymGetLineFromAddr64 returned error : 487
 6: 00007FF62039B31C AES_cbc_encrypt+18245004
SymGetLineFromAddr64 returned error : 487
 7: 00007FF62039C5DB AES_cbc_encrypt+18249803
SymGetLineFromAddr64 returned error : 487
 8: 00007FF62039BE83 AES_cbc_encrypt+18247923
SymGetLineFromAddr64 returned error : 126
SymFromAddr returned error : 126
 9: 00000074D8C06628

@refack
Copy link
Contributor Author

refack commented Oct 28, 2018

All comments addressed, PTAL.

// UnDecorateSymbolName returned success
return szUndName;
} else {
// UnDecorateSymbolName failed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not a fan of this type of comment: What happens is obvious in both branches, and the branches themselves are short. (And I think we have a convention of ending comments with a period.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code was lifter verbatim from https://docs.microsoft.com/en-us/windows/desktop/Debug/retrieving-symbol-information-by-address
I would rather keep changes to minimon, for future reverse engineering.

// Patches:
// Use `fprintf(stderr, ` instead of `printf`.
// Assign values to `sym` on success.
// `current_process_` instead of `hProcess.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am still not sure whether this is going to help us at some point, I suspect it won't.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment are free.
Personally I have not been in a situation where I said "I wish there was less comments"

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tend to agree, but someone will either change our code or the original, and updating the comment will mostly be a maintenance burden at that point from my perspective.

Copy link
Member

@tniessen tniessen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM either way, even though I don't see much value in some of the comments.

@refack refack merged commit 247b513 into nodejs:master Oct 30, 2018
@refack refack removed their assignment Oct 30, 2018
@refack refack deleted the win-native-stacks branch October 30, 2018 01:54
targos pushed a commit that referenced this pull request Nov 2, 2018
BridgeAR added a commit that referenced this pull request Nov 14, 2018
Notable changes:

* child_process:
  * All child processes will again open up a new Window on Windows by
    default. [#24034](#24034)
* deps:
  * A new and fast experimental HTTP parser (`llhttp`) is now supported.
    [#24059](#24059)
* **Windows**
  * A crashing process will now show the names of stack frames if the
    node.pdb file is available.
    [#23822](#23822)
* Added new collaborators:
  * [oyyd](https://github.com/oyyd) - Ouyang Yadong.
    [#24300](#24300)
  * [psmarshall](https://github.com/psmarshall) - Peter Marshall.
    [#24170](#24170)
  * [shisama](https://github.com/shisama) - Masashi Hirano.
    [#24136](#24136)
@BridgeAR BridgeAR added the notable-change PRs with changes that should be highlighted in changelogs. label Nov 15, 2018
targos pushed a commit that referenced this pull request Nov 15, 2018
Notable changes:

* deps:
  * A new experimental HTTP parser (`llhttp`) is now supported.
    #24059
* timers:
  * Fixed an issue that could cause setTimeout to stop working as
    expected. #24322
* Windows
  * A crashing process will now show the names of stack frames if the
    node.pdb file is available.
    #23822
  * Continued effort to improve the installer's new stage that installs
    native build tools.
    #23987,
    #24348
  * child_process:
    * On Windows the `windowsHide` option default was restored to
      `false`. This means `detached` child processes and GUI apps will
      once again start in a new window.
      #24034
* Added new collaborators:
  * [oyyd](https://github.com/oyyd) - Ouyang Yadong.
    #24300
  * [psmarshall](https://github.com/psmarshall) - Peter Marshall.
    #24170
  * [shisama](https://github.com/shisama) - Masashi Hirano.
    #24136
targos pushed a commit that referenced this pull request Nov 15, 2018
Notable changes:

* deps:
  * A new experimental HTTP parser (`llhttp`) is now supported.
    #24059
* timers:
  * Fixed an issue that could cause setTimeout to stop working as
    expected. #24322
* Windows
  * A crashing process will now show the names of stack frames if the
    node.pdb file is available.
    #23822
  * Continued effort to improve the installer's new stage that installs
    native build tools.
    #23987,
    #24348
  * child_process:
    * On Windows the `windowsHide` option default was restored to
      `false`. This means `detached` child processes and GUI apps will
      once again start in a new window.
      #24034
* Added new collaborators:
  * [oyyd](https://github.com/oyyd) - Ouyang Yadong.
    #24300
  * [psmarshall](https://github.com/psmarshall) - Peter Marshall.
    #24170
  * [shisama](https://github.com/shisama) - Masashi Hirano.
    #24136

PR-URL: #24350
MylesBorins pushed a commit that referenced this pull request Nov 27, 2018
@MylesBorins
Copy link
Contributor

This does not land cleanly in v8.x LTS. Please feel free to manually backport by following the guide. Please also feel free to replace do-not-land if it is being backported

@codebytere codebytere mentioned this pull request Nov 27, 2018
rvagg pushed a commit that referenced this pull request Nov 28, 2018
MylesBorins pushed a commit that referenced this pull request Nov 29, 2018
@codebytere codebytere mentioned this pull request Nov 29, 2018
MylesBorins pushed a commit that referenced this pull request Dec 6, 2018
Notable changes:

* deps:
  * upgrade to c-ares v1.15.0 (Ben Noordhuis)
    #23854
* Windows:
  * A crashing process will now show the names of stack frames if the node.pdb
    file is available. (Refael Ackermann)
    #23822
* Added new collaborators:
  * Peter Marshall. #24170
  * Masashi Hirano. #24136

PR-URL: #24727
MylesBorins pushed a commit that referenced this pull request Dec 11, 2018
Notable changes:

* deps:
  * upgrade to c-ares v1.15.0 (Ben Noordhuis)
    #23854
* Windows:
  * A crashing process will now show the names of stack frames if the node.pdb
    file is available. (Refael Ackermann)
    #23822
* Added new collaborators:
  * Peter Marshall. #24170
  * Masashi Hirano. #24136

PR-URL: #24727
refack pushed a commit to refack/node that referenced this pull request Jan 14, 2019
Notable changes:

* deps:
  * upgrade to c-ares v1.15.0 (Ben Noordhuis)
    nodejs#23854
* Windows:
  * A crashing process will now show the names of stack frames if the node.pdb
    file is available. (Refael Ackermann)
    nodejs#23822
* Added new collaborators:
  * Peter Marshall. nodejs#24170
  * Masashi Hirano. nodejs#24136

PR-URL: nodejs#24727
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c++ Issues and PRs that require attention from people who are familiar with C++. notable-change PRs with changes that should be highlighted in changelogs. post-mortem Issues and PRs related to the post-mortem diagnostics of Node.js. windows Issues and PRs related to the Windows platform.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants