Giter Site home page Giter Site logo

nodejs / llnode Goto Github PK

View Code? Open in Web Editor NEW
1.1K 40.0 98.0 1.17 MB

An lldb plugin for Node.js and V8, which enables inspection of JavaScript states for insights into Node.js processes and their core dumps.

License: Other

Makefile 0.34% C++ 74.18% Python 2.71% JavaScript 22.77% C 0.01%
nodejs node

llnode's Introduction

llnode

npm ci coverage

Node.js v10.x+ C++ plugin for the LLDB debugger.

The llnode plugin adds the ability to inspect JavaScript stack frames, objects, source code and more to the standard C/C++ debugging facilities when working with Node.js processes or core dumps in LLDB.

Demo

https://asciinema.org/a/29589

Quick start

Start an LLDB session with the llnode plugin automatically loaded:

npm install -g llnode
llnode `which node` -c /path/to/core/dump
  • Never install llnode with sudo as it can easily lead to errors during installation and execution.
  • For more details on starting llnode see the Usage section.
  • To get started with the llnode commands see the Commands section.

Install Instructions

Prerequisites: Official, active Node.js version

llnode only supports currently active Node.js versions installed via official channels. We recommend installing Node.js with nvm as it allows users to install global packages without sudo by default, and it always installs the official executables from https://nodejs.org.

Do not install Node.js from the default Ubuntu/Debian apt repositories (or from the default repositories of other Linux distributions), llnode is not compatible with Node.js installed that way. If you still want to install Node.js via apt-get, take a look at nodesource/distributions.

Prerequisites: Install LLDB and its Library

To use llnode you need to have the LLDB debugger installed. The recommended version is LLDB 3.9 and above.

  • OS X/macOS

    • You can install Xcode and use the LLDB that comes with it.

    • Optionally, you can install newer versions of lldb using Homebrew with

      brew update && brew install --with-lldb --with-toolchain llvm

      and make sure /usr/local/opt/llvm/bin gets searched before /usr/bin/ on your PATH. llnode will link to the LLDB installation returned by llvm-config if available.

  • Linux

    • You can install the lldb package using the package manager of your distribution. You may need to install additional packages for liblldb as well.

    • For example, on Ubuntu 18.04 you can install the prerequisites with

      apt-get install lldb-8 liblldb-8-dev
  • FreeBSD

    # Install llvm with lldb and headers
    pkg install llvm39
    rm -f /usr/bin/lldb
    ln -s /usr/local/bin/lldb39 /usr/bin/lldb
  • Windows

    • You can install a binary distribution of LLVM directly or using Chocolatey:

      cinst -y visualstudio2017buildtools visualstudio2017-workload-vctools llvm git

      Visual Studio is required for MSBuild and headers when building llnode. Git is required to download the lldb headers.

  • Android / Termux (Experimental)

    • Install Termux (https://termux.com)

    • Install Termux Packages

      • pkg install clang lldb lldb-dev make
      • pkg install nodejs-lts nodejs-lts-dev
    • To debug:

    llnode -- /data/data/com.termux/files/usr/bin/node --abort_on_uncaught_exception script.js
    (llnode) run
    

Install the Plugin

Install llnode globally via npm

If you have lldb available on your PATH, simply run:

npm install -g llnode

To build llnode against a specific lldb version matching an lldb executable, use the --lldb_exe npm option. For example, on Linux the executable on the PATH might be lldb-3.9:

npm install --lldb_exe=`which lldb-3.9` -g llnode

After installing with npm, llnode should be available on your PATH as a shortcut for running LLDB with the llnode plugin.

Optional: Install with Homebrew (OS X/macOS)

brew install llnode

Loading the llnode Plugin

There are several ways to load the llnode plugin:

1. Using the llnode shortcut

If you install llnode globally via npm (npm install -g llnode), you can use the llnode shortcut script. This starts lldb and automatically issues the plugin load command. All parameters to the llnode script are passed directly to lldb. If you it's not a local installation, the shortcut will be in node_modules/.bin/llnode.

2. Using ~/.lldbinit to load the Plugin Automatically

To tell LLDB to load llnode automatically regardless of the version of lldb that you are running, add this line to ~/.lldbinit:

plugin load /path/to/the/llnode/plugin

The path to the llnode plugin should be printed when the installation is finished. On OS X/macOS the plugin is typically node_modules/llnode/llnode.dylib, on Linux it's node_modules/llnode/llnode.so.

3. Loading the Plugin Manually

The llnode plugin can also be manually loaded into LLDB using the plugin load command within lldb.

It does not matter whether the plugin load command is issued before or after loading a core dump or attaching to a process.

4. Install the Plugin to the LLDB System Plugin Directory

Similar to the ~/.lldbinit approach, this way LLDB will also load the plugin automatically on start-up. Doing this may require additional permissions to be able to copy the plugin library to the system plugin directory.

On Linux, run make install-linux in the project directory, or if installing with npm, copy node_modules/llnode/llnode.so to /usr/lib/lldb/plugins or create a link there.

On OS X/macOS, run make install-osx in the project directory, or if installing with npm, copy node_modules/llnode/llnode.dylib to ~/Library/Application\ Support/LLDB/PlugIns/ or create a link there.

Usage

To use llnode with a core dump the core dump needs to be loaded into lldb along with the exact executable that created the core dump. The executable contains information that lldb and the llnode plugin need to make sense of the data in the core dump.

To load a core dump when starting llnode use:

llnode /path/to/bin/node -c /path/to/core

or to load the core dump after starting lldb:

(llnode) target create /path/to/bin/node -c /path/to/core

To use llnode against a live process:

llnode -- /path/to/bin/node script.js
(llnode) run

This is ideal for debugging an npm package with native code. To debug a Node.js crash on uncaught exception:

llnode -- /path/to/bin/node --abort_on_uncaught_exception script.js
(llnode) run

lldb will stop your process when it crashes. To see where it stopped use the v8 bt command. See the Commands section below for more commands.

Commands

(llnode) v8 help
     Node.js helpers

Syntax: v8

The following subcommands are supported:

      bt              -- Show a backtrace with node.js JavaScript functions and their args. An optional argument is accepted; if
                         that argument is a number, it specifies the number of frames to display. Otherwise all frames will be
                         dumped.

                         Syntax: v8 bt [number]
      findjsinstances -- List every object with the specified type name.
                         Use -v or --verbose to display detailed `v8 inspect` output for each object.
                         Accepts the same options as `v8 inspect`
      findjsobjects   -- List all object types and instance counts grouped by typename and sorted by instance count. Use
                         -d or --detailed to get an output grouped by type name, properties, and array length, as well as
                         more information regarding each type.
      findrefs        -- Finds all the object properties which meet the search criteria.
                         The default is to list all the object properties that reference the specified value.
                         Flags:

                          * -v, --value expr     - all properties that refer to the specified JavaScript object (default)
                          * -n, --name  name     - all properties with the specified name
                          * -s, --string string  - all properties that refer to the specified JavaScript string value

      getactivehandles  -- Print all pending handles in the queue. Equivalent to running process._getActiveHandles() on
                           the living process.

      getactiverequests -- Print all pending requests in the queue. Equivalent to running process._getActiveRequests() on
                           the living process.

      inspect         -- Print detailed description and contents of the JavaScript value.

                         Possible flags (all optional):

                          * -F, --full-string    - print whole string without adding ellipsis
                          * -m, --print-map      - print object's map address
                          * -s, --print-source   - print source code for function objects
                          * -l num, --length num - print maximum of `num` elements from string/array

                         Syntax: v8 inspect [flags] expr
      nodeinfo        -- Print information about Node.js
      print           -- Print short description of the JavaScript value.

                         Syntax: v8 print expr
      source list     -- Print source lines around the currently selected
                         JavaScript frame.
                         Syntax: v8 source list [flags]
                         Flags:
                         * -l <line> - Print source code below line <line>.

For more help on any particular subcommand, type 'help <command> <subcommand>'.

Develop and Test

Configure and Build

The easiest way to build the plugin:

# Clone this repo
git clone https://github.com/nodejs/llnode.git && cd llnode

# Configure and build the plugin with npm
npm install
# To configure and build the plugin without npm
node scripts/configure.js && node scripts/install.js && node scripts/cleanup.js
# Or use make
make plugin

# To configure and build both the plugin and the addon
npm install --llnode_build_addon=true
# To configure and build with a specific path to headers
npm install --llnode_lldb_include_dir=/path/to/lldb/include

# Without npm
LLNODE_BUILD_ADDON=true node scripts/configure.js && node scripts/install.js && node scripts/cleanup.js
# Or use make
make addon # Builds the addon
make       # Builds both the addon and the plugin

To configure the build yourself:

# Detect available lldb installation and download headers if necessary
node scripts/configure.js
# To build the addon, set the environment variable LLNODE_BUILD_ADDON=true

# To configure with the detected lldb installation
node-gyp configure
# To configure with a specified path to headers, where `$lldb_include_dir`
# contains the <lldb/*/*.h> headers
node-gyp configure -- -Dlldb_include_dir=/usr/local/Cellar/llvm/5.0.0/include
# To configure with a specified path to the libraries, where `$lldb_lib_dir`
# contains `liblldb.so` or `liblldb.dylib`
node-gyp configure -- -Dlldb_lib_dir=/usr/lib/llvm-3.9/lib

# Build the plugin (and the addon if LLNODE_BUILD_ADDON=true)
node-gyp build

# Move the built plugin to the project directory
node scripts/cleanup.js

Test

To run the tests, if lldb is an executable on the PATH:

npm run test-all    # Run both addon and plugin tests
npm run test-plugin # Run plugin tests
npm run test-addon    # Run addon tests

If the LLDB executable is named differently, point TEST_LLDB_BINARY to it before running the tests:

TEST_LLDB_BINARY=`which lldb-4.0` npm run test-all

Useful Environment Variables

  • LLNODE_DEBUG=true to see additional debug info from llnode
  • TEST_LLNODE_DEBUG=true to see additional debug info coming from the tests
  • LLNODE_CORE=/path/to/core/dump LLNODE_NODE_EXE=/path/to/node to use a prepared core dump instead of generating one on-the-fly when running the tests.

For example, to inspect the process of inspect-scenario.js, run:

LLNODE_DEBUG=true lldb -- \
  node --abort_on_uncaught_exception --expose_externalize_string \
  test/fixtures/inspect-scenario.js
(lldb) run

To debug test/scan-test.js with a prepared core dump:

LLNODE_DEBUG=true TEST_LLNODE_DEBUG=true \
  LLNODE_CORE=/path/to/core/dump/of/inspect/scenario.js \
  LLNODE_NODE_EXE=/path/to/node \
  node test/scan-test.js

LICENSE

This software is licensed under the MIT License.

Copyright Fedor Indutny, 2016.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

llnode's People

Contributors

bmeck avatar bnb avatar bnoordhuis avatar brendangregg avatar cjihrig avatar drieger avatar evanlucas avatar fanatid avatar gibfahn avatar hardfist avatar hhellyer avatar indutny avatar jason-cooke avatar jimgambale avatar joaocgreis avatar joyeecheung avatar kvakil avatar lpinca avatar mhdawson avatar mmarchini avatar no9 avatar oyyd avatar priyank-p avatar raissasf avatar rickyes avatar rnchamberlain avatar stefannilsson avatar trxcllnt avatar watson avatar yjhjstz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

llnode's Issues

npm install -g llnode fails

It's common practice to install tools using the-goption, but this seems to fail with llnode:

rchamberlain@ThinkCentre-M57p:~/test$ npm install -g llnode

> [email protected] preinstall /home/rchamberlain/node-v7.7.3-linux-x64/lib/node_modules/.staging/llnode-4a7a78c7
> node scripts/configure.js

Build dir is: /home/rchamberlain/node-v7.7.3-linux-x64/lib/node_modules/.staging/llnode-4a7a78c7
Checking for headers, version is 3.9
Installing llnode for /usr/lib/llvm-3.9/bin/lldb, lldb version 3.9
Linking lldb to include directory /usr/lib/llvm-3.9
npm ERR! Linux 4.4.0-72-generic
npm ERR! argv "/home/rchamberlain/node-v7.7.3-linux-x64/bin/node" "/home/rchamberlain/node-v7.7.3-linux-x64/bin/npm" "explore" "node-gyp" "pwd"
npm ERR! node v7.7.3
npm ERR! npm  v4.1.2

npm ERR! It doesn't look like node-gyp is installed.
npm ERR! 
npm ERR! If you need help, you may report this error at:
npm ERR!     <https://github.com/npm/npm/issues>

npm ERR! Please include the following file with any support request:
npm ERR!     /home/rchamberlain/node-v7.7.3-linux-x64/lib/node_modules/npm/npm-debug.log
npm ERR! weird error 1
child_process.js:512
    throw err;
    ^
Error: Command failed: npm -g explore npm npm explore node-gyp pwd

Problem seems to be this line in the config.js script: https://github.com/nodejs/llnode/blob/master/scripts/configure.js#L89

Using npm install llnode without the -g option works fine.

Release

Would anyone mind if I'll do a release, and add it to homebrew? Given that node v8 was just released, it seems beneficial to publish the version that supports it (thanks to @bnoordhuis )

Linux lldb 3.8 hangs on live cores, update docs

I suspect we've hit this known and fixed bug with lldb 3.8:

With a live core dump, lldb hangs:

# lldb -f /usr/bin/node -c /var/cores/core.node.30833
(lldb) target create "/usr/bin/node" --core "/var/cores/core.node.30833"
[...hang...]

Could the install instructions for Linux note this and the fix? Would the current fix be an lldb build from source, or is it packaged with the patch yet in lldb 3.8 or 3.9?

error message for a node binary to core file mismatch

Is it possible to detect that there is a version mismatch between node and the core file, and print an error or warning? Here I'm using the wrong version of node with a core file, and it doesn't complain, but it would be helpful if it did.

(lldb) target create "node" --core "core.3397"
Core file '/mnt/core.3397' (x86_64) was loaded.
(lldb) v8 nodeinfo
No process objects found.

Advice on how to debug llnode plugin?

This isn't so much an issue, as just a request for advice.

I'm interested in hacking on llnode, but I'm brand new to lldb. Do you have any advice on how to debug the llnode extension while it's running inside lldb on a node corefile. I did a search for debugging lldb under lldb, but didn't turn up anything obvious.

Thanks.

npm i llnode

I think this should be possible to install on a global install via npm scripts, @indutny is there any reason you didn't go this route?

Post-mortem test suite

I'd like to set up tests running llnode against coredumps. I've noticed that the current suite only tests attaching to a running process, and I'd like to extend it to run the same tests on an aborted process (I think the simplest method would be to run with --abort-on-uncaught-exception and then run the existing suite on the dump).

Does anyone have any views on how this should look (or how this should be implemented)?

v8 bt skips some frames

Maybe there's a good reason for this, but notice we're skipping frames 1-4:

(lldb) v8 bt
 * thread #1: tid = 13, 0x00007fda23874d44 libpthread.so.0`__GI___pthread_mutex_lock + 4, name = 'node', stop reason = signal SIGSEGV
  * frame #0: 0x00007fda23874d44 libpthread.so.0`__GI___pthread_mutex_lock + 4
    frame #5: 0x00007fda20ffe212 node`v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) + 290
[...]

They do show up with the normal bt:

(lldb) bt
* thread #1, name = 'node', stop reason = signal SIGSEGV
  * frame #0: 0x00007fda23874d44 libpthread.so.0`__GI___pthread_mutex_lock + 4
    frame #1: 0x00007fda20b0ed19 node
    frame #2: 0x00007fda20ac5e39 node
    frame #3: 0x00007fda20a9dd4b node
    frame #4: 0x00007fda20a9c9f6 node
    frame #5: 0x00007fda20ffe212 node`v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) + 290
[...]

Should "v8 bt" be skipping them?

v8 list

it would be nice to see the source of JS function frames during bt.

IE:

> bt
#1 ... foo.js:2:3
> list
console.log(2)
console.log(3)

where foo.js is

console.log(1)
console.log(2)
console.log(3)

LLNode Windows support

I thought I’d open this issue to discuss whether Windows support for LLNode is something anyone wants.

I’ve got and LLDB build up and running on Windows so I had a chance to try building LLNode on Windows. Running gyp_llnode worked fairly well.

The resulting Visual Studio project created by gyp required a little tweaking (mostly things I could google for). The main issue was that LLNode uses the getopt library which isn’t on Windows by default. Given that the getopt problem could probably be fixed running LLNode on Windows looks do-able but would need a bit of work and would probably break fairly quickly unless someone was using it regularly.

There’s two reasons why someone might want to do this:

  • To debug issues with versions of Node running on Windows.
  • To debug issues with core dumps generated on Linux. (LLDB is able to open Linux ELF cores even when it’s running on Mac or Windows.)

I’m not sure how important the first scenario is but the second one might be useful to developers with Windows machines who deploy to Linux. Of course you do have to get LLDB for Windows, probably by building it yourself, which isn’t hard but it is quite time consuming. (Developers with Mac’s who deploy to Linux are effectively already supported.)

Any thoughts? Does anyone else have a strong need for this? (I’m using a Mac so I’m neutral.)

otool2segments does not work anymore

$ ~/Code/indutny/llnode/scripts/otool2segments.py ./core
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/objdump: './core': Invalid argument.
fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/otool: internal objdump command failed

cc @hhellyer

Strings missing from findjsobjects output.

The current implementation of the findjsobjects command doesn't include JavaScript strings as part of the totals. This is a bit of a problem if you are trying to use the output to diagnose what is filling the heap as strings are usually the largest consumer of heap space.

Example:

(lldb) v8 findjsobjects
 Instances  Total Size Name
 ---------- ---------- ----
          1         24 (anonymous)
          1         24 JSON
          1         24 process
          1         40 Arguments
          1         56 DefineError.aV
          1         56 MathConstructor
          1         56 RangeError
          1         96 MyObject
          1        104 TypeError
          1        136 Module
          6        336 Error
         10        800 (ArrayBufferView)
         13       1768 PropertyDescriptor
         16        392 (Object)
         17        544 ContextifyScript
         19       1064 NativeModule
        101       3232 (Array)
        314      17056 Object
       6013      47920 (String)

I've pushed a branch with a patch for this (I'll add the PR in a moment). There might be a reason for not including strings in that output but I think not including them is more likely to be misleading for users trying to understand what is filling the heap.

Javascript API for llnode?

@indutny @hhellyer
Hi Fedor, we've been discussing the possibility of an NPM/Javascript API on top of llnode, so that diagnostic tools could be written that exploit the llnode+lldb libraries. An alternative to using the line-mode lldb debugger + plugin itself to read a core dump. For example, an interactive web viewer for core dumps that are stored on a node server. Also possibility of user add-ons written in Javascript.

Here's a very basic prototype, just to load a core dump and list the thread stacks:
indutny/llnode@master...rnchamberlain:llnode_api

Any thoughts? Would need to design the API, make the calls async etc etc

Update headers for Mac OS X installation to pick up 3.9+ headers

Xcode recently updated lldb on my system. Now lldb reports:
$ lldb -v
lldb-370.0.40
Swift-3.1

However this doesn't match up to the actual lldb levels so I forced the installation script to use 3.9 headers. This built and as a result I was able to run v8 findjsobjects without needing to run one of the scripts to generate memory regions.

This simplifies the usage of llnode a lot so I will update the npm install scripts. Ideally I need to find a table that maps Xcode versions to 'real' lldb releases from the lldb git repository.

Reading contents of an Array/ArrayBufferView

Hi, at the moment when doing v8 inspect <address-of-an-array> llnode would only print the length (and offset & backstore address) of an Array (ArrayBufferView). Are there any support for reading the elements of an Array/ArrayBufferView? Thanks.

v8 inspect command returns error

Using lldb 3.8 on Ubuntu 16.04 (4.4.0-34 kernel) with latest llnode. Running on node v6.6.0 Release build.

Getting error: Failed to evaluate expression when attempting to inspect a function address. Here's an abbreviated log:

node_v6 ((v6.6.0)) $ lldb-3.8 -- ./node -e 'Buffer(1024).indexOf(Buffer(3))'
(lldb) target create "./node"
Current executable set to './node' (x86_64).
(lldb) settings set -- target.run-args  "-e" "Buffer(1024).indexOf(Buffer(3))"
(lldb) b 'node::Buffer::IndexOfBuffer(v8::FunctionCallbackInfo<v8::Value> const&)'
Breakpoint 1: where = node`node::Buffer::IndexOfBuffer(v8::FunctionCallbackInfo<v8::Value> const&), address = 0x0000000000f53b40

(lldb) v8 bt 7
 * thread #1: tid = 2513, 0x0000000000f53b40 node`node::Buffer::IndexOfBuffer(v8::FunctionCallbackInfo<v8::Value> const&), name = 'node', stop reason = breakpoint 1.1
    frame #0: 0x0000000000f53b40 node`node::Buffer::IndexOfBuffer(v8::FunctionCallbackInfo<v8::Value> const&)
    frame #1: 0x000000000090107c node`v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) + 348
    frame #2: 0x000000000093530c node`v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>) + 1052
    frame #3: 0x000000000093f4e8 node`v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) + 456
    frame #4: 0x00000ccd50e092a7 <exit>
    frame #5: 0x00000ccd50f3fa52 bidirectionalIndexOf(this=0x00001b416de04381:<undefined>, 0x00003628897e5029:<ArrayBufferView 0x0000000001baad40+0:1024>, 0x00003628897e52c1:<ArrayBufferView 0x0000000001baad40+1024:3>, <Smi: 0>, 0x00001b416de04381:<undefined>, 0x00001b416de043c1:<true>) at buffer.js:559:30 fn=0x000036288973e9a9
  * frame #6: 0x00000ccd50f3f401 indexOf(this=0x00003628897e5029:<ArrayBufferView 0x0000000001baad40+0:1024>, 0x00003628897e52c1:<ArrayBufferView 0x0000000001baad40+1024:3>, 0x00001b416de04381:<undefined>, 0x00001b416de04381:<undefined>) at buffer.js:622:44 fn=0x00002272434079c1
(lldb) v8 print 0x00002272434079c1
0x00002272434079c1:<function: indexOf at buffer.js:622:44>
(lldb) v8 inspect 0x00003628897e5029
0x00003628897e5029:<ArrayBufferView 0x0000000001baad40+0:1024>
(lldb) v8 inspect 0x00002272434079c1
error: Failed to evaluate expression

At the end I also show that print works on a fn address, and inspect works on an object.

v8 source list - segmentation fault regression - lldb 4.0 on FreeBSD-11.0

Hi - Just taking this for a drive on FreeBSD 11.0-RELEASE
Build went smoothly following a tweaked set of the linux instructions

* Clone this repo
# git clone https://github.com/nodejs/llnode.git && cd llnode

* Install llvm with lldb pieces
# pkg install llvm40
# rm -fr /usr/bin/lldb 
# ln -s /usr/local/bin/lldb40 /usr/bin/lldb

* Initialize GYP
# git clone https://chromium.googlesource.com/external/gyp.git tools/gyp

* Configure
# ./gyp_llnode -Dlldb_dir=/usr/local/llvm40/

* Build
# gmake -C out/ -j9

Anyway when I follow this tutorial https://developer.ibm.com/node/2016/08/15/exploring-node-js-core-dumps-using-the-llnode-plugin-for-lldb/ (thanks @hhellyer) I get a segmentation fault (core dump) when I try the v8 source list command after selecting the frame.

Interestingly I down graded my llvm to 3.9 and everything worked as expected so the issue does seem to be introduced with 4.0.

# uname -a 
FreeBSD  11.0-RELEASE-p9 FreeBSD 11.0-RELEASE-p9 #0: Tue Apr 11 08:48:40 UTC 2017 
[email protected]:/usr/obj/usr/src/sys/GENERIC  amd64
# lldb -v
 lldb version 4.0.0

The one that works is

# uname -a 
FreeBSD  11.0-RELEASE-p9 FreeBSD 11.0-RELEASE-p9 #0: Tue Apr 11 08:48:40 UTC 2017 
[email protected]:/usr/obj/usr/src/sys/GENERIC  amd64

# lldb -v 
lldb version 3.9.1 ( revision )

I tried loading the core dump lldb lldb -c lldb-4.0.0.core but I got error: '/usr/bin/lldb' doesn't contain any 'host' platform architectures: x86_64, i386 and don't know how to get any further with diagnosing this but as it's a regression I thought I had better log something.

How to build lldb-mi

Hello,
I need your help for building lldb-mi static library in mac os.
Many thanks

v8 code-map

Should dump all Code instances and their function names. Should be useful for on-demand profiling.

cc @brendangregg

include string.h

had to add:

#include <string.h>

to src/llnode.cc after code list change.

findrefs performance improvement

Currently findrefs has to rescan the entire heap each time. Could an index or some cache be added to improve performance of this when using it multiple times?

Prepare for node 8.0

Wouldn't it be nice if llnode worked out of the box with node 8? Indeed it would but it won't happen without some even-toed ungulate clipping1. Here is what needs to be done:

  • update tools/gen-postmortem-metadata.py in upstream V8
  • back-port changes to nodejs/node
  • update llnode to support new object layouts

Bonus points if llnode is taught to print something sensible for WASM and Ignition stack frames/code objects/etc.

1yak shaving

Unable to read all frames even V8 ones in core dump taken

Hi I have been interested in debugging nodejs in prod for a while but having to install mdb was quite an issue, it’s really awesome that there is llnode.

I installed llnode on my mac with brew for practice taking core dumps, analyzing points of failure etc it all worked, so I tried setting up with “a real project” using the simple code here so everything is predictable but with a docker container. The idea was to get the core dump move it to my machine and debugging, like I would hope to do in production

This is what I got after moving it to my machine, I’d like to know what I might have done wrong

screen shot 2017-04-11 at 2 35 14 pm

"v8 bt" does nothing on OS X 10.10.5

> 
lldb ../node/node mock-http-server.js 
(lldb) target create "../node/node"
Current executable set to '../node/node' (x86_64).
(lldb) settings set -- target.run-args  "mock-http-server.js"
(lldb) r
Process 4374 launched: '../node/node' (x86_64)
/Users/Jeremiah/Documents/node/out/Release/node[4374]: ../src/async-wrap.cc:115:void node::SetupHooks(const FunctionCallbackInfo<v8::Value> &): Assertion `env->async_hooks_init_function().IsEmpty()' failed.
 1: node::Abort() [/Users/Jeremiah/Documents/here-be-dragons/../node/node]
 2: node::RunMicrotasks(v8::FunctionCallbackInfo<v8::Value> const&) [/Users/Jeremiah/Documents/here-be-dragons/../node/node]
 3: node::SetupHooks(v8::FunctionCallbackInfo<v8::Value> const&) [/Users/Jeremiah/Documents/here-be-dragons/../node/node]
 4: v8::internal::FunctionCallbackArguments::Call(void (*)(v8::FunctionCallbackInfo<v8::Value> const&)) [/Users/Jeremiah/Documents/here-be-dragons/../node/node]
 5: v8::internal::MaybeHandle<v8::internal::Object> v8::internal::(anonymous namespace)::HandleApiCallHelper<false>(v8::internal::Isolate*, v8::internal::(anonymous namespace)::BuiltinArguments<(v8::internal::BuiltinExtraArguments)1>) [/Users/Jeremiah/Documents/here-be-dragons/../node/node]
 6: v8::internal::Builtin_HandleApiCall(int, v8::internal::Object**, v8::internal::Isolate*) [/Users/Jeremiah/Documents/here-be-dragons/../node/node]
 7: 0x2dba51c092a7
Process 4374 stopped
* thread #1: tid = 0x612c, 0x00007fff86137286 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
    frame #0: 0x00007fff86137286 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill:
->  0x7fff86137286 <+10>: jae    0x7fff86137290            ; <+20>
    0x7fff86137288 <+12>: movq   %rax, %rdi
    0x7fff8613728b <+15>: jmp    0x7fff86132c53            ; cerror_nocancel
    0x7fff86137290 <+20>: retq   
(lldb) v8 bt
(lldb)

ping @indutny ?

v8 inspect and strings

It makes sense to cut off strings when executing v8 inspect <string address> since most strings are very long, but I'd like to be able to override this via an option.
In some cases (like when looking at a path var, i.e. fs.read) it's crucial to see the whole string.

Right now I get:

(lldb) v8 i 0x00002f51fd0bf901
0x00002f51fd0bf901:<String: "/Users/thlorenz/...">

But I'd like that to be:

(lldb) v8 i 0x00002f51fd0bf901
0x00002f51fd0bf901:<String: "/Users/thlorenz/dev/talks/debugging-profiling-nodejs/demos/demo-3/fs-read.js">

Not sure if this could be a setting that one would change globally that would affect every inspect or if should be another inspect, i.e. deepinspect.

README asks to install a seemingly incompatible lldb version

Hi!

The current llnode README documentation states that the lldb version to install is 3.8. Well... I copy/pasted the README installation instructions, but all I got when trying to load a coredump is another coredump from lldb.

The coredump I try to load is generated by a process running either under node 4.6.1 or 6.9.1 (I tried both):

$ lldb-3.8 node -c core
(lldb) target create "node" --core "core"
Segmentation fault (core dumped)

Same thing happens with:

  • lldb 4.0
  • with or without llnode installed
  • with or without C++ node modules used by the project being coredumped
  • Debian Jessie and Ubuntu Xenial

Note that gdb has no problem loading my coredumps files. Of course I can't do much with gdb. :-)

It's when I stumbled upon this PR that I realized that you yourselves use lldb 3.6. So I tried that version, and now everything work fine.

This issue is more about the README documentation than anything but, if needs be, I will be happy to provide any additional information you need to pinpoint where the problem is.

automatic LLNODE_RANGESFILE

Currently we do this for v8 findjsobjects to work:

# ./scripts/readelf2segments.py /var/cores/core.node.30833.1468367170 > core.30833.ranges
# export LLNODE_RANGESFILE=core.30833.ranges

It might be nice if llnode could do this automatically, even if it means llnode shelling out to call readelf and scraping the output (if that's possible in lldb).

`v8 bt` does not work

llnode: v1.2.0


OS X: 10.10.5

uname -a
Darwin Jeremiahs-MacBook-Pro.local 14.5.0 Darwin Kernel Version 14.5.0: Sun Sep 25 22:07:15 PDT 2016; root:xnu-2782.50.9~1/RELEASE_X86_64 x86_64

lldb -v
lldb-340.4.119

XCode version: 7.2 (7C68)

Linux lldb system plugin directory has changed

See https://reviews.llvm.org/D19516. The lldb system plugins directory for linux is now /usr/lib/lldb/plugins. I think this happened in lldb v3.9. So it no longer finds the llnode plugin if it is installed in /usr/lib/lldb (which is where the current llnode makefile install target puts it).

They say that earlier lldb versions do a recursive scan from /usr/lib/lldb, so lldb v3.8 should still find our plugin if we install it in /usr/lib/lldb/plugins

finding references?

mdb_v8 supports findjsobject -r, which will print out all objects that refer to a specific object. This is especially helpful for debugging memory leaks, as you can use it to walk a leaking object all the way back to its root reference.

Does this exist for llnode, and if not will you be open to implementing it?

Creating flame graphs from core dumps taken

I have created a docker image that can be used by literally anyone that picks it up for debugging node in prod, I have been able to configure llnode , lldb, perf with help from @hhellyer all that needs to be done is for the user to copy the generated core dump and binary of node that was running on the process into docker see here I'd like to take it a step further and explore the possibility of also generating flame graphs from the core dump

CentOS 7 support

Compile will fail, here is the log output

../src/llv8.cc: In member function ‘std::string llnode::v8::JSFrame::Inspect(bool, llnode::v8::Error&)’:
../src/llv8.cc:245:43: error: expected ‘)’ before ‘PRIx64’
   snprintf(tmp, sizeof(tmp), " fn=0x%016" PRIx64, fn.raw());

I tried add #define __STDC_FORMAT_MACROS preprocess, then compile passed.
But, when I open lldb, help v8 command get nothing subcommands.

(lldb) v8
The following subcommands are supported:

The following subcommands are supported:

My g++ version

$ g++ --version
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

lldb version

$ lldb --version
lldb version 3.4.2 ( revision )

Unchecked `sberror`

Many of lldb errors are left unchecked in the source code, all of them should be checked for the failure. Proper error reporting should be in place.

lldb 3.8 workaround for live hangs

#92 tracks documenting the problem, but... maybe there's a workaround for this that we can use for lldb 3.8? Just wanted to post this as an issue in case someone figures it out. I don't know how far away it will be for lldb 4.0 to be widely available.

findjsobjects

Great work Fedor. Any idea whether it's possible within LLDB to find heap objects? Something along the lines of https://github.com/joyent/mdb_v8/blob/master/docs/usage.md#finding-javascript-objects would be extremely helpful.

Actually, now that I think about it, what about porting some of the functionality over from mdb_v8 to lldb? The code for mdb_v8 is already open source, I wonder if it would be easier to try and port that library? In any case we should talk about your work with llnode here at an upcoming nodejs post mortem working group meeting.

Internal fields

It would be lovely if we could inspect C++ from object's internal fields. This will require some additional constants to be exported.

workqueue command

Would it make sense to have a "v8 workqueue" or "libuv workqueue" command, that showed what was waiting and their callbacks?

Maybe something that made use of process._getActiveHandles(), process._getActiveRequests(), or process::getActiveHandles.

Enable llnode to build against a local build of lldb.

On this branch https://github.com/hhellyer/llnode/tree/build_with_latest_lldb I have updated llnode.gyp so that you can build llnode against a locally built version of lldb. (I did this so I can test out my LLDB API changes to add memory region information but it's generally useful and might help other people who hit weird API problems.)

Mac OSX has stricter linking than Linux and requires that you link the dynamic library against any other libraries it will use. Linux only needs the headers.

This difference means the build procedure on Linux only requires -Dlldb_dir to be updated to the location containing your lldb source. (If you have checked out the source it should be <llvm_dir>/tools/lldb.)

The LLVM build process places the built binaries out side the source tree so to build on Mac OSX you need to specify -Dlldb_dir (as on Linux) and a new parameter -Dlldb_build_dir. If you have followed the standard lldb build setup this is likely to be llvm_dir/../build.

-Dlldb_lib can still be used to override the name of the lldb library file but as it liblldb is generally soft-linked to liblldb. it is usually safe to omit it.

(A side effect of these changes is that you don’t need to pass -Dlldb_lib on Linux any more.)

The Mac configure step, when using a local build of lldb is:

./gyp_llnode -Dlldb_dir=some_path/llvm/tools/lldb -Dlldb_build_dir=some_path/build

The Linux config step is:
./gyp_llnode -Dlldb_dir=some_path/llvm/tools/lldb

The normal build instructions are unchanged.

If this seems reasonable I'll create a pull request but it seemed better to discuss it here first.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.