Implement a way to print mongo shell stacktrace from a coredump

XMLWordPrintableJSON

    • Type: Improvement
    • Resolution: Unresolved
    • Priority: Major - P3
    • None
    • Affects Version/s: None
    • Component/s: None
    • None
    • DevProd Build
    • None
    • None
    • None
    • None
    • None
    • None
    • None

      Debugging mongo shell coredumps can be quite difficult to do as we cannot tell what line is the shell executing nor the previous stackframes.

      However, there is nothing actually preventing us from doing so if we manage to get our hands on the latest frame being executed if I understand the code correctly.

      This is because each frame will contain a reference to a JSScript object which contains in its extent the chunk of code it's referencing. Particularly it does provide the line start of the chunk so it can give us an overview of the chunk of code being run.

      However, this doesn't include the filename which must be acquired from the source object. To do so we can get to it from the object via gdb with the following commands:

      (gdb) print sourceObject_
      $1 = {
        <js::WriteBarriered<js::ScriptSourceObject*>> = {
          <js::BarrieredBase<js::ScriptSourceObject*>> = {
            value = 0x3be459b59cb8
          },
          <js::WrappedPtrOperations<js::ScriptSourceObject*, js::WriteBarriered<js::ScriptSourceObject*>, void>> = {<No data fields>}, <No data fields>}, <No data fields>}
      (gdb) print sourceObject_.value
      $2 = (js::ScriptSourceObject *) 0x3be459b59cb8
      (gdb) print ((unsigned long) $2) + sizeof(js::NativeObject)
      $3 = 65851943656656
      (gdb) print ((JS::Value*)$3)->asBits_
      $4 = 18642296189824
      (gdb) print *((js::ScriptSource*)$4)->filename_.box_
      $5 = {
        chars_ = {
          mTuple = {
            <mozilla::detail::CompactPairHelper<char*, JS::FreePolicy, (mozilla::detail::StorageType)1, (mozilla::detail::StorageType)0>> = {
              <JS::FreePolicy> = {<No data fields>},
              members of mozilla::detail::CompactPairHelper<char*, JS::FreePolicy, (mozilla::detail::StorageType)1, (mozilla::detail::StorageType)0>:
              mFirstA = 0x10f47f70ec60 "/data/mci/26b64ca440e3c32af2c38d41c2c9764a/src/jstests/third_party/fast_check/fc-3.1.0.js"
            }, <No data fields>}
        },
        length_ = 90,
        cache_ = 0x10f47f6afd00,
        refcount = 1
      }
      

      From this we can tell the filename is /data/mci/26b64ca440e3c32af2c38d41c2c9764a/src/jstests/third_party/fast_check/fc-3.1.0.js

      This step can be repeated for the previous stackframes since each stackframe contains a reference to the previous one in order to produce a semi-stacktrace of sorts that shows the general location of where we are.

      A very simple GDB script implementation would be:

      // Assume $frame is set to a (js::InterpreterFrame*)
      while ($frame)
        // This prints the filename
        print ((js::ScriptSource*)(((JS::Value*)((unsigned long) ($frame->script_->sourceObject_.value) + sizeof(js::NativeObject)))->asBits_))->filename_.box_->chars_.mTuple.mFirstA
        // This prints the "line number"
        print $frame->script_->extent_.lineno
        set $frame=$frame->prev_
      end
      

            Assignee:
            Unassigned
            Reporter:
            Jordi Olivares Provencio
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

              Created:
              Updated: