Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Fix many things: less crashes, more stable (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
chase authored Nov 28, 2023
2 parents f9248b9 + 28d6568 commit 2066f10
Show file tree
Hide file tree
Showing 69 changed files with 3,897 additions and 1,892 deletions.
25 changes: 25 additions & 0 deletions .clangd
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
CompileFlags:
Add:
- '-std=c++17' # these are standard among the flags
- '-Wall'
- '-Werror'
- '-Wextra'
- '-Wimplicit-fallthrough'
- '-Wunreachable-code-aggressive'
- '-Wthread-safety'
- '-Wno-missing-field-initializers'
- '-Wno-unused-parameter'
- '-Wloop-analysis'
- '-Wno-unneeded-internal-declaration'
- '-Wenum-compare-conditional'
- '-Wno-psabi'
- '-Wno-ignored-pragma-optimize'
- '-Wno-unqualified-std-cast-call'
- '-Wmax-tokens'
- '-Wshadow'
- '-Wno-builtin-macro-redefined'
- '-Wheader-hygiene'
- '-Wstring-conversion'
- '-Wtautological-overlap-compare'
- '-Wno-deprecated-builtins' # parts of //base flag incorrectly
Compiler: clang++
32 changes: 25 additions & 7 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,33 @@
"type": "lldb",
"request": "attach",
"name": "Debug (Attach)",
"program": "${workspaceFolder}/src/out/Default/Electron.app/Contents/Frameworks/Electron Helper (Renderer).app/Contents/MacOS/Electron Helper (Renderer)",
"osx": {
"program": "${workspaceFolder}/src/out/Default/Electron.app/Contents/Frameworks/Electron Helper (Renderer).app/Contents/MacOS/Electron Helper (Renderer)",
},
"linux": {
"program": "${workspaceFolder}/src/out/Default/electron",
},
"windows": {
"program": "${workspaceFolder}/src/out/Default/Electron.exe",
},
"initCommands": [
"settings set target.source-map ../.. ${workspaceFolder}/src",
"settings set target.exec-search-paths ${workspaceFolder}/src/out/Default",
"settings set target.env-vars CHROMIUM_LLDBINIT_SOURCED=1"
// make sure we have all the symbols
"settings set target.exec-search-paths '${workspaceFolder}/src/out/Default' '${workspaceFolder}/src/third_party/libreofficekit/instdir'",
// ready now
"settings set target.env-vars CHROMIUM_LLDBINIT_SOURCED=1",
],
"postRunCommands": [
// force loading C++ symbols
"command script import ${workspaceFolder}/eloklldb/libcxx_chrome_fix.py",
],
"pid": "${command:pickProcess}",
"relativePathBase": "${workspaceFolder}/src/out/Default",
"breakpointMode": "file"
}
"sourceLanguages": [
"c++"
],
"breakpointMode": "file",
"sourceMap": {
"../..": "${workspaceFolder}/src"
},
},
]
}
1 change: 1 addition & 0 deletions eloklldb/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
__pycache__
Empty file added eloklldb/__init__.py
Empty file.
29 changes: 29 additions & 0 deletions eloklldb/add_dsyms.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import lldb
import glob
import os.path

# This shouldn't be necessary in most cases!

OUT_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'src', 'out', 'Default')

def add_symbols(debugger):
files = glob.glob(os.path.join(OUT_DIR, '*'))
file = glob.glob(os.path.join(OUT_DIR, '*.dSYM'))
wanted_binaries = set([
m.GetFileSpec().GetFilename()
for m in debugger.GetSelectedTarget().module_iter()
])
wanted_dsyms = set([
m.GetFileSpec().GetFilename() + ".dSYM"
for m in debugger.GetSelectedTarget().module_iter()
])
for file in file:
if os.path.basename(file) in wanted_dsyms:
debugger.HandleCommand('target symbols add "{}"'.format(file))
for file in file:
if os.path.basename(file) in wanted_binaries:
debugger.HandleCommand('target symbols add "{}"'.format(file))

def __lldb_init_module(debugger, internal_dict):
add_symbols(debugger)

7 changes: 7 additions & 0 deletions eloklldb/formatters.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import lldb
from .lok import uno, string, cppu

def __lldb_init_module(debugger: lldb.SBDebugger, _internal_dict):
print("Loading LOK formatters...")
for formatter in {uno, string, cppu}:
formatter.register_formatters(debugger)
157 changes: 157 additions & 0 deletions eloklldb/libcxx_chrome_fix.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# Copyright (c) 2022 Macro
# Use of this source code is governed by the MIT license that can be
# found in the LICENSE file.
# -*- coding: utf-8 -*-

"""\
This is a bit of nightmare!
Chrome uses a non-standard namespace std::Cr, where the standard picked up by
LLDB is std::__[0-9a-zA-Z]+. So we do our best to copy what we can find and
adapt.
"""
import lldb
import time

tries_after_breakpoint = 0


def breakpoint_callback(
frame: lldb.SBFrame, bp_loc: lldb.SBBreakpointLocation, _dict
) -> bool:
global tries_after_breakpoint
# It might fire once, but never trust LLDB
breakpoint = bp_loc.GetBreakpoint()
target = breakpoint.GetTarget()
target.BreakpointDelete(breakpoint.id)

tries_after_breakpoint += 1
debugger: lldb.SBDebugger = target.GetDebugger()
frame.get_locals()
frame.get_arguments()
duplicate_and_modify_formatters(debugger, tries_after_breakpoint)
time.sleep(0.5)
# Access an instance variable to try force loading C++ plugin
process = target.GetProcess()
if process.GetState() == lldb.eStateStopped:
process.Continue()

return True # False means it won't actually stop


def attempt_after_breakpoint(debugger: lldb.SBDebugger):
"""This should force the cplusplus plugin to load"""
target: lldb.SBTarget = debugger.GetSelectedTarget()
process: lldb.SBProcess = target.GetProcess()
stopped = False
if process.GetState() == lldb.eStateRunning:
stopped = True
process.Stop()

# Break inside of the main loop, since it's frequent
breakpoint: lldb.SBBreakpoint = target.BreakpointCreateByLocation(
"message_pump_default.cc", 41
)
breakpoint.SetIgnoreCount(1) # Don't break immediately, let the symbols load
breakpoint.SetOneShot(True) # -o true
breakpoint.SetThreadName("electron") # -T electron
breakpoint.SetScriptCallbackFunction("libcxx_chrome_fix.breakpoint_callback")
if stopped:
process.Continue()


def crfix(
debugger: lldb.SBDebugger,
_command: str,
_result: lldb.SBCommandReturnObject,
_internal_dict: dict,
):
duplicate_and_modify_formatters(debugger, 10)


def fallback_to_command(debugger: lldb.SBDebugger):
debugger.HandleCommand(f"command script add -f {__name__}.crfix crfix")


def fix_name(name: str) -> str:
return name.replace("std::__1", "std::Cr").replace("std::__[[:alnum:]]+", "std::Cr")


def duplicate_and_modify_formatters(debugger: lldb.SBDebugger, depth=0):
"""Takes the original C++ formatters and makes them work with std::Cr"""
# This is the category with all the goodies inside, libcxx libstdcpp all that
original_category: lldb.SBTypeCategory = debugger.GetCategory("cplusplus")

if not original_category:
if depth == 0:
print("After stopping at a breakpoint, run this command: crfix")
fallback_to_command(debugger)
# elif depth == 0:
# print("Could not get C++ types, attempting after breakpoint")
# attempt_after_breakpoint(debugger)
elif depth > 3:
print("Command failed! Try using it after stopping at a breakpoint")
else:
print("Trying again...")
attempt_after_breakpoint(debugger)
return

# Create or get the 'cpplusplus_chrome' category
new_category = debugger.GetCategory("cpplusplus_chrome") or debugger.CreateCategory(
"cpplusplus_chrome"
)

# Make mutated copies of summary formatters
for i in range(original_category.GetNumSummaries()):
summary = original_category.GetSummaryAtIndex(i)
specifier = original_category.GetTypeNameSpecifierForSummaryAtIndex(i)
if not specifier:
continue
name = str(specifier.name)
if not name:
continue
modified_typename = fix_name(name)

# didn't replace anything, don't want to accidentally override that
if name == modified_typename:
continue

# Create a new typename specifier with the modified name
new_typename_specifier = lldb.SBTypeNameSpecifier(
modified_typename, specifier.IsRegex()
)

new_category.AddTypeSummary(new_typename_specifier, summary)

# Make mutated copies of synthetic formatters
for i in range(original_category.GetNumSynthetics()):
synthetic: lldb.SBTypeSynthetic = original_category.GetSyntheticAtIndex(i)
specifier: lldb.SBTypeNameSpecifier = (
original_category.GetTypeNameSpecifierForSyntheticAtIndex(i)
)
if not specifier:
continue
name = str(specifier.name)
if not name:
continue

modified_typename = fix_name(name)

# didn't replace anything, don't want to accidentally override that
if name == modified_typename:
continue

# Create a new typename specifier with the modified name
new_typename_specifier = lldb.SBTypeNameSpecifier(
modified_typename, specifier.IsRegex()
)

new_category.AddTypeSynthetic(new_typename_specifier, synthetic)

new_category.AddLanguage(lldb.eLanguageTypeC_plus_plus)
new_category.SetEnabled(True)
print("Finished fixing formatters")


def __lldb_init_module(debugger: lldb.SBDebugger, internal_dict):
print("Please wait while we fix C++ formatting")
duplicate_and_modify_formatters(debugger)
Loading

0 comments on commit 2066f10

Please sign in to comment.