hartmannathan commented on code in PR #14854:
URL: https://github.com/apache/nuttx/pull/14854#discussion_r1852703815


##########
tools/gdb/macros.py:
##########
@@ -0,0 +1,214 @@
+############################################################################
+# tools/gdb/macros.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# NOTE: GDB stores macro information based on the current stack frame's scope,
+# including the source file and line number. Therefore, there may be missing
+# macro definitions when you are at different stack frames.
+#
+# To resolve this issue, we need to retrieve all macro information from the 
ELF file
+# then parse and evaluate it by ourselves.
+#
+# There might be two ways to achieve this, one is to leverage the C 
preprocessor
+# to directly preprocess all the macros instereted into python constants

Review Comment:
   ```suggestion
   # to directly preprocess all the macros inserted into python constants
   ```



##########
tools/gdb/macros.py:
##########
@@ -0,0 +1,214 @@
+############################################################################
+# tools/gdb/macros.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# NOTE: GDB stores macro information based on the current stack frame's scope,
+# including the source file and line number. Therefore, there may be missing
+# macro definitions when you are at different stack frames.
+#
+# To resolve this issue, we need to retrieve all macro information from the 
ELF file
+# then parse and evaluate it by ourselves.
+#
+# There might be two ways to achieve this, one is to leverage the C 
preprocessor
+# to directly preprocess all the macros instereted into python constants
+# gcc -E -x c -P <file_with_macros> -I/path/to/nuttx/include
+#
+# While the other way is to leverage the dwarf info stored in the ELF file,
+# with -g3 switch, we have a `.debug_macro` section containing all the 
information
+# about the macros.
+#
+# Currently, we using the second method.
+
+import os
+import re
+import subprocess
+import tempfile
+
+PUNCTUATORS = [
+    "\[",
+    "\]",
+    "\(",
+    "\)",
+    "\{",
+    "\}",
+    "\?",
+    ";",
+    ",",
+    "~",
+    "\.\.\.",
+    "\.",
+    "\-\>",
+    "\-\-",
+    "\-\=",
+    "\-",
+    "\+\+",
+    "\+\=",
+    "\+",
+    "\*\=",
+    "\*",
+    "\!\=",
+    "\!",
+    "\&\&",
+    "\&\=",
+    "\&",
+    "\/\=",
+    "\/",
+    "\%\>",
+    "%:%:",
+    "%:",
+    "%=",
+    "%",
+    "\^\=",
+    "\^",
+    "\#\#",
+    "\#",
+    "\:\>",
+    "\:",
+    "\|\|",
+    "\|\=",
+    "\|",
+    "<<=",
+    "<<",
+    "<=",
+    "<:",
+    "<%",
+    "<",
+    ">>=",
+    ">>",
+    ">=",
+    ">",
+    "\=\=",
+    "\=",
+]
+
+
+def parse_macro(line, macros, pattern):
+    # grep name, value
+    # the first group matches the token, the second matches the replacement
+    m = pattern.match(line)
+    if not m:
+        return False
+
+    name, value = m.group(1), m.group(2)
+
+    if name in macros:
+        # FIXME: what should we do if we got a redefinition/duplication here?
+        # for now I think it's ok just overwrite the old value
+        pass
+
+    # emplace, for all undefined macros we evalute it to zero
+    macros[name] = value if value else "0"
+
+    return True
+
+
+def fetch_macro_info(file):
+    if not os.path.isfile(file):
+        raise FileNotFoundError("No given ELF target found")
+
+    # FIXME: we don't use subprocess here because
+    # it's broken on some GDB distribution :(, I haven't
+    # found a solution to it.
+
+    with tempfile.NamedTemporaryFile(delete=False) as f1:
+
+        # # os.system(f"readelf -wm {file} > {output}")
+        process = subprocess.Popen(
+            f"readelf -wm {file}", shell=True, stdout=f1, 
stderr=subprocess.STDOUT
+        )
+
+        process.communicate()
+        errcode = process.returncode
+
+        f1.close()
+
+        if errcode != 0:
+            return {}
+
+        p = re.compile(".*macro[ ]*:[ ]*([\S]+\(.*?\)|[\w]+)[ ]*(.*)")
+        macros = {}
+
+        with open(f1.name, "rb") as f2:
+            for line in f2.readlines():
+                line = line.decode("utf-8")
+                if not line.startswith(" DW_MACRO_define") and not 
line.startswith(
+                    " DW_MACRO_undef"
+                ):
+                    continue
+
+                if not parse_macro(line, macros, p):
+                    print(f"Failed to parse {line}")
+
+    return macros
+
+
+def split_tokens(expr):
+    p = "(" + "|".join(PUNCTUATORS) + ")"
+    res = list(
+        filter(lambda e: e != "", map(lambda e: e.rstrip().lstrip(), 
re.split(p, expr)))
+    )
+    return res
+
+
+def do_expand(expr, macro_map):
+    if expr in PUNCTUATORS:
+        return expr
+
+    tokens = split_tokens(expr)
+
+    res = []
+
+    for t in tokens:
+        if t not in macro_map:
+            res.append(t)
+            continue
+        res += do_expand(macro_map[t], macro_map)
+
+    return res
+
+
+# NOTE: Implement a fully functional parser which can
+# preprocessing all the C marcos according to ISO 9899 standard
+# may be an overkill, what we really care about are those
+# macros that can be evaluted to an constant value.

Review Comment:
   ```suggestion
   # macros that can be evaluated to a constant value.
   ```



##########
tools/gdb/macros.py:
##########
@@ -0,0 +1,214 @@
+############################################################################
+# tools/gdb/macros.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# NOTE: GDB stores macro information based on the current stack frame's scope,
+# including the source file and line number. Therefore, there may be missing
+# macro definitions when you are at different stack frames.
+#
+# To resolve this issue, we need to retrieve all macro information from the 
ELF file
+# then parse and evaluate it by ourselves.
+#
+# There might be two ways to achieve this, one is to leverage the C 
preprocessor
+# to directly preprocess all the macros instereted into python constants
+# gcc -E -x c -P <file_with_macros> -I/path/to/nuttx/include
+#
+# While the other way is to leverage the dwarf info stored in the ELF file,
+# with -g3 switch, we have a `.debug_macro` section containing all the 
information
+# about the macros.
+#
+# Currently, we using the second method.
+
+import os
+import re
+import subprocess
+import tempfile
+
+PUNCTUATORS = [
+    "\[",
+    "\]",
+    "\(",
+    "\)",
+    "\{",
+    "\}",
+    "\?",
+    ";",
+    ",",
+    "~",
+    "\.\.\.",
+    "\.",
+    "\-\>",
+    "\-\-",
+    "\-\=",
+    "\-",
+    "\+\+",
+    "\+\=",
+    "\+",
+    "\*\=",
+    "\*",
+    "\!\=",
+    "\!",
+    "\&\&",
+    "\&\=",
+    "\&",
+    "\/\=",
+    "\/",
+    "\%\>",
+    "%:%:",
+    "%:",
+    "%=",
+    "%",
+    "\^\=",
+    "\^",
+    "\#\#",
+    "\#",
+    "\:\>",
+    "\:",
+    "\|\|",
+    "\|\=",
+    "\|",
+    "<<=",
+    "<<",
+    "<=",
+    "<:",
+    "<%",
+    "<",
+    ">>=",
+    ">>",
+    ">=",
+    ">",
+    "\=\=",
+    "\=",
+]
+
+
+def parse_macro(line, macros, pattern):
+    # grep name, value
+    # the first group matches the token, the second matches the replacement
+    m = pattern.match(line)
+    if not m:
+        return False
+
+    name, value = m.group(1), m.group(2)
+
+    if name in macros:
+        # FIXME: what should we do if we got a redefinition/duplication here?
+        # for now I think it's ok just overwrite the old value
+        pass
+
+    # emplace, for all undefined macros we evalute it to zero
+    macros[name] = value if value else "0"
+
+    return True
+
+
+def fetch_macro_info(file):
+    if not os.path.isfile(file):
+        raise FileNotFoundError("No given ELF target found")
+
+    # FIXME: we don't use subprocess here because
+    # it's broken on some GDB distribution :(, I haven't
+    # found a solution to it.
+
+    with tempfile.NamedTemporaryFile(delete=False) as f1:
+
+        # # os.system(f"readelf -wm {file} > {output}")
+        process = subprocess.Popen(
+            f"readelf -wm {file}", shell=True, stdout=f1, 
stderr=subprocess.STDOUT
+        )
+
+        process.communicate()
+        errcode = process.returncode
+
+        f1.close()
+
+        if errcode != 0:
+            return {}
+
+        p = re.compile(".*macro[ ]*:[ ]*([\S]+\(.*?\)|[\w]+)[ ]*(.*)")
+        macros = {}
+
+        with open(f1.name, "rb") as f2:
+            for line in f2.readlines():
+                line = line.decode("utf-8")
+                if not line.startswith(" DW_MACRO_define") and not 
line.startswith(
+                    " DW_MACRO_undef"
+                ):
+                    continue
+
+                if not parse_macro(line, macros, p):
+                    print(f"Failed to parse {line}")
+
+    return macros
+
+
+def split_tokens(expr):
+    p = "(" + "|".join(PUNCTUATORS) + ")"
+    res = list(
+        filter(lambda e: e != "", map(lambda e: e.rstrip().lstrip(), 
re.split(p, expr)))
+    )
+    return res
+
+
+def do_expand(expr, macro_map):
+    if expr in PUNCTUATORS:
+        return expr
+
+    tokens = split_tokens(expr)
+
+    res = []
+
+    for t in tokens:
+        if t not in macro_map:
+            res.append(t)
+            continue
+        res += do_expand(macro_map[t], macro_map)
+
+    return res
+
+
+# NOTE: Implement a fully functional parser which can
+# preprocessing all the C marcos according to ISO 9899 standard

Review Comment:
   ```suggestion
   # preprocess all the C macros according to ISO 9899 standard
   ```



##########
tools/gdb/macros.py:
##########
@@ -0,0 +1,214 @@
+############################################################################
+# tools/gdb/macros.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# NOTE: GDB stores macro information based on the current stack frame's scope,
+# including the source file and line number. Therefore, there may be missing
+# macro definitions when you are at different stack frames.
+#
+# To resolve this issue, we need to retrieve all macro information from the 
ELF file
+# then parse and evaluate it by ourselves.
+#
+# There might be two ways to achieve this, one is to leverage the C 
preprocessor
+# to directly preprocess all the macros instereted into python constants
+# gcc -E -x c -P <file_with_macros> -I/path/to/nuttx/include
+#
+# While the other way is to leverage the dwarf info stored in the ELF file,
+# with -g3 switch, we have a `.debug_macro` section containing all the 
information
+# about the macros.
+#
+# Currently, we using the second method.

Review Comment:
   ```suggestion
   # Currently, we are using the second method.
   ```



##########
tools/gdb/macros.py:
##########
@@ -0,0 +1,214 @@
+############################################################################
+# tools/gdb/macros.py
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.  The
+# ASF licenses this file to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance with the
+# License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+# License for the specific language governing permissions and limitations
+# under the License.
+#
+############################################################################
+
+# NOTE: GDB stores macro information based on the current stack frame's scope,
+# including the source file and line number. Therefore, there may be missing
+# macro definitions when you are at different stack frames.
+#
+# To resolve this issue, we need to retrieve all macro information from the 
ELF file
+# then parse and evaluate it by ourselves.
+#
+# There might be two ways to achieve this, one is to leverage the C 
preprocessor
+# to directly preprocess all the macros instereted into python constants
+# gcc -E -x c -P <file_with_macros> -I/path/to/nuttx/include
+#
+# While the other way is to leverage the dwarf info stored in the ELF file,
+# with -g3 switch, we have a `.debug_macro` section containing all the 
information
+# about the macros.
+#
+# Currently, we using the second method.
+
+import os
+import re
+import subprocess
+import tempfile
+
+PUNCTUATORS = [
+    "\[",
+    "\]",
+    "\(",
+    "\)",
+    "\{",
+    "\}",
+    "\?",
+    ";",
+    ",",
+    "~",
+    "\.\.\.",
+    "\.",
+    "\-\>",
+    "\-\-",
+    "\-\=",
+    "\-",
+    "\+\+",
+    "\+\=",
+    "\+",
+    "\*\=",
+    "\*",
+    "\!\=",
+    "\!",
+    "\&\&",
+    "\&\=",
+    "\&",
+    "\/\=",
+    "\/",
+    "\%\>",
+    "%:%:",
+    "%:",
+    "%=",
+    "%",
+    "\^\=",
+    "\^",
+    "\#\#",
+    "\#",
+    "\:\>",
+    "\:",
+    "\|\|",
+    "\|\=",
+    "\|",
+    "<<=",
+    "<<",
+    "<=",
+    "<:",
+    "<%",
+    "<",
+    ">>=",
+    ">>",
+    ">=",
+    ">",
+    "\=\=",
+    "\=",
+]
+
+
+def parse_macro(line, macros, pattern):
+    # grep name, value
+    # the first group matches the token, the second matches the replacement
+    m = pattern.match(line)
+    if not m:
+        return False
+
+    name, value = m.group(1), m.group(2)
+
+    if name in macros:
+        # FIXME: what should we do if we got a redefinition/duplication here?
+        # for now I think it's ok just overwrite the old value
+        pass
+
+    # emplace, for all undefined macros we evalute it to zero
+    macros[name] = value if value else "0"
+
+    return True
+
+
+def fetch_macro_info(file):
+    if not os.path.isfile(file):
+        raise FileNotFoundError("No given ELF target found")
+
+    # FIXME: we don't use subprocess here because
+    # it's broken on some GDB distribution :(, I haven't
+    # found a solution to it.
+
+    with tempfile.NamedTemporaryFile(delete=False) as f1:
+
+        # # os.system(f"readelf -wm {file} > {output}")
+        process = subprocess.Popen(
+            f"readelf -wm {file}", shell=True, stdout=f1, 
stderr=subprocess.STDOUT
+        )
+
+        process.communicate()
+        errcode = process.returncode
+
+        f1.close()
+
+        if errcode != 0:
+            return {}
+
+        p = re.compile(".*macro[ ]*:[ ]*([\S]+\(.*?\)|[\w]+)[ ]*(.*)")
+        macros = {}
+
+        with open(f1.name, "rb") as f2:
+            for line in f2.readlines():
+                line = line.decode("utf-8")
+                if not line.startswith(" DW_MACRO_define") and not 
line.startswith(
+                    " DW_MACRO_undef"
+                ):
+                    continue
+
+                if not parse_macro(line, macros, p):
+                    print(f"Failed to parse {line}")
+
+    return macros
+
+
+def split_tokens(expr):
+    p = "(" + "|".join(PUNCTUATORS) + ")"
+    res = list(
+        filter(lambda e: e != "", map(lambda e: e.rstrip().lstrip(), 
re.split(p, expr)))
+    )
+    return res
+
+
+def do_expand(expr, macro_map):
+    if expr in PUNCTUATORS:
+        return expr
+
+    tokens = split_tokens(expr)
+
+    res = []
+
+    for t in tokens:
+        if t not in macro_map:
+            res.append(t)
+            continue
+        res += do_expand(macro_map[t], macro_map)
+
+    return res
+
+
+# NOTE: Implement a fully functional parser which can
+# preprocessing all the C marcos according to ISO 9899 standard
+# may be an overkill, what we really care about are those
+# macros that can be evaluted to an constant value.
+#
+# #define A (B + C + D)
+# #define B 1
+# #define C 2
+# #define D 3
+# invoking try_expand('A', macro_map) will give you "(1 + 2 + 3)"
+#
+# However,
+# #define SUM(B,C,D) (B + C + D)
+# invoking try_expand('SUM(1,2,3)', macro_map) will give you "SUM(1,2,3)"
+#
+# We have not implemented this feature as we have not found a practical
+# use case for it in our GDB plugin.
+#
+# However, you can switch to the correct stack frame that has this macro 
defined
+# and let GDB expand and evaluate it for you if you really want to evalue some 
very

Review Comment:
   ```suggestion
   # and let GDB expand and evaluate it for you if you really want to evaluate 
some very
   ```



##########
tools/gdb/utils.py:
##########
@@ -83,6 +100,147 @@ def invoke(self, ptr, typename, elementname):
 ContainerOf()
 
 
+def gdb_eval_or_none(expresssion):
+    """Evaluate an expression and return None if it fails"""
+    try:
+        return gdb.parse_and_eval(expresssion)
+    except gdb.error:
+        return None
+
+
+def get_symbol_value(name, locspec="nx_start", cacheable=True):
+    """Return the value of a symbol value etc: Variable, Marco"""

Review Comment:
   ```suggestion
       """Return the value of a symbol value etc: Variable, Macro"""
   ```



##########
tools/gdb/utils.py:
##########
@@ -155,23 +338,37 @@ def read_ulong(buffer, offset):
 target_arch = None
 
 
-def is_target_arch(arch):
-    """Return True if the target architecture is ARCH"""
+def is_target_arch(arch, exact=False):
+    """
+    For non exactly match, this function will

Review Comment:
   ```suggestion
       For non exact match, this function will
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to