From 0b65861943827066492283797b5c195795d96cbe Mon Sep 17 00:00:00 2001
From: pompolic <pompolic@special-circumstanc.es>
Date: Wed, 11 Aug 2021 00:37:12 +0200
Subject: [PATCH] WIP commit

Fixes:
- missing parenthesis in ActionEnv
- ord() instead of int() in ChEnv
- VTTypes() needs to be initialized in InitParserBreakpoint, to get the correct gdb frame. Also keep references in TopLevelParse
---
 gdb-port/parser-name-instrumentation-gdb.py | 11 +++++++++--
 gdb-port/parser-type-instrumentation-gdb.py | 21 +++++++++++----------
 2 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/gdb-port/parser-name-instrumentation-gdb.py b/gdb-port/parser-name-instrumentation-gdb.py
index 6d55b62..bf886b2 100644
--- a/gdb-port/parser-name-instrumentation-gdb.py
+++ b/gdb-port/parser-name-instrumentation-gdb.py
@@ -122,6 +122,12 @@ class TopLevelParse:
 		# Holds 32 characters starting at state->input_stream[index], used by the GUI
 		self.current_input_chunk = ''
 		self.current_parser_env = ''
+		self.vt_types = None
+		self.parser_decombinator = None
+
+	def init_parser(self):
+		self.vt_types = VTTypes()
+		self.parser_decombinator = ParserDecombinator(self.vt_types)
 
 	# Called from h_packrat_parse()'s handler, where the parse state and arena get initialized
 	def enter_h_packrat_parse(self, parser):
@@ -160,8 +166,8 @@ class TopLevelParse:
 
 		parser_stack = self.peek_parserstack()
 		parser_stack.push(parser_obj)
-		if parser_decombinator:
-			p_env = parser_decombinator.decompose_parser(parser_obj, self)
+		if self.parser_decombinator:
+			p_env = self.parser_decombinator.decompose_parser(parser_obj, self)
 			self.set_parser_env(str(p_env))
 		return parser_obj
 
@@ -345,6 +351,7 @@ class InitParserBreakpoint(gdb.Breakpoint):
 	def stop(self):
 		frame = gdb.selected_frame()
 		block = frame.block()
+		top_level_parse.init_parser()
 		
 		# This will also catch locals that aren't parsers, but it's not a problem in practice,
 		# since h_parse() will never be called on them
diff --git a/gdb-port/parser-type-instrumentation-gdb.py b/gdb-port/parser-type-instrumentation-gdb.py
index 59c4b26..93a017d 100644
--- a/gdb-port/parser-type-instrumentation-gdb.py
+++ b/gdb-port/parser-type-instrumentation-gdb.py
@@ -39,6 +39,7 @@ parser_name_defaults = {
 }
 
 class VTTypes:
+	# Intended to be initialized in InitParserBreakpoint
 	def __init__(self):
 		self.vt_symbols = {int(gdb.lookup_symbol(key)[0].value().address) : gdb.lookup_symbol(key)[0] for key in parser_name_defaults.keys()}
 
@@ -52,11 +53,12 @@ class VTTypes:
 		except KeyError:
 			return None
 
-vt_types = VTTypes()
+#vt_types = VTTypes()
 
 class HParserEnv:
 	def __init__(self, parser, top_level_parse):
 		print("HParserEnv constructed") # DEBUG
+		self.vt_types = top_level_parse.vt_types # Memoize parser type list
 
 	# parser is expected to be a Parser object
 	def name_from_vtable(self, parser):
@@ -65,7 +67,7 @@ class HParserEnv:
 		# perhaps using gdb.Value would be the best
 		vtable_p = gdb.parse_and_eval("((HParser*) " + str(parser_addr) + ")->vtable")
 		try:
-			name = parser_name_defaults[vt_types.lookup_by_address(vtable_p).name]
+			name = parser_name_defaults[self.vt_types.lookup_by_address(vtable_p).name]
 		# if lookup_by_address() returns None
 		except AttributeError:
 			name = "(Unknown parser type (vtable symbol not found in lookup)"
@@ -130,14 +132,14 @@ class ActionEnv(HParserEnv):
 	def __init__(self, parser, top_level_parse):
 		self.parser = parser
 
-		member_parser_p = gdb.parse_and_eval("((HParseAction*) parser->env)->p");
+		member_parser_p = gdb.parse_and_eval("((HParseAction*) parser->env)->p")
 		parser_obj = top_level_parse.add_or_get_parser(member_parser_p)
 		self.member_parser = parser_obj
 
 		# should return a HAction
-		action = gdb.parse_and_eval("((HParseAction*) parser->env)->action");
+		action = gdb.parse_and_eval("((HParseAction*) parser->env)->action")
 		self.action = int(action)
-		user_data_p = gdb.parse_and_eval("(HParseAction*) parser->env)->user_data");
+		user_data_p = gdb.parse_and_eval("((HParseAction*) parser->env)->user_data")
 		self.user_data_p = int(user_data_p)
 
 	def __str__(self):
@@ -159,7 +161,7 @@ class ChEnv(HParserEnv):
 		self.parser = parser
 
 		self.ch_arg = gdb.parse_and_eval("(uint8_t) parser->env")
-		self.ch_value = ord(self.ch_arg.value())
+		self.ch_value = int(self.ch_arg)
 
 	def __str__(self):
 		return str(self.ch_value)
@@ -549,21 +551,20 @@ vtable_to_env = {
 # ParserDecomposer?
 
 class ParserDecombinator:
-	def __init__(self):
+	def __init__(self, vt_types):
 		# TODO: make a better data structure than vtable_to_env + parser_name_defaults + this
 		self.vt_envs = { k : (v,vtable_to_env[k]) for k,v in parser_name_defaults.items() }
+		self.vt_types = vt_types
 
 	def decompose_parser(self, parser, top_level_parse):
 		# Sadly, this is stringly typed for now
 		parser_addr = parser.address
 		vtable_p = gdb.parse_and_eval("((HParser*) " + str(parser_addr) + ")->vtable")
 		try:
-			vtable_sym = vt_types.lookup_by_address(vtable_p)
+			vtable_sym = self.vt_types.lookup_by_address(vtable_p)
 			envClass = vtable_to_env[vtable_sym.name]
 		except KeyError:
 			print("Unknown vtable: " + str(vtable_p))
 			return None
 
 		return envClass(parser, top_level_parse)
-
-parser_decombinator = ParserDecombinator()
-- 
GitLab