mirror of
https://github.com/google/pebble.git
synced 2025-03-15 08:41:21 +00:00
103 lines
3.3 KiB
Python
103 lines
3.3 KiB
Python
# Copyright 2024 Google LLC
|
|
#
|
|
# Licensed 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.
|
|
|
|
import gdb
|
|
import re
|
|
from collections import defaultdict
|
|
|
|
INFO_LINE_RE = re.compile(r'(.+\s)*(\S+)\s+(\S+);')
|
|
INFO_FILE_RE = re.compile(r'File ([^:]+):$')
|
|
|
|
def _do_info_line_match(line):
|
|
m = INFO_LINE_RE.match(line)
|
|
if not m:
|
|
return None
|
|
_type = m.group(2)
|
|
if _type.startswith('0x'):
|
|
# This is the address rather than the type
|
|
_type = None
|
|
symbol = m.group(3)
|
|
if symbol.startswith('*'):
|
|
symbol = symbol[1:]
|
|
if _type is not None:
|
|
_type += ' *'
|
|
|
|
paren_loc = symbol.find('[')
|
|
if paren_loc > 0:
|
|
symbol = symbol[:paren_loc]
|
|
symbol = "'{}'".format(symbol)
|
|
return (_type, symbol)
|
|
|
|
def _find_match_for_file(gdb_output, _file):
|
|
matches = []
|
|
in_file = False
|
|
for line in gdb_output.split('\n'):
|
|
if not in_file:
|
|
# matching file
|
|
m = INFO_FILE_RE.match(line)
|
|
if m and m.group(1).endswith(_file):
|
|
in_file = True
|
|
else:
|
|
if not line.strip():
|
|
break # Done the file
|
|
result = _do_info_line_match(line)
|
|
if result is not None:
|
|
matches.append(result)
|
|
if len(matches) == 0:
|
|
return (None, None)
|
|
if len(matches) > 1:
|
|
raise Exception('Error: Multiple statics by same name')
|
|
return matches[0]
|
|
|
|
def _find_match(gdb_output, _file=None):
|
|
if _file is not None:
|
|
return _find_match_for_file(gdb_output, _file)
|
|
matches = []
|
|
for line in gdb_output.split('\n'):
|
|
result = _do_info_line_match(line)
|
|
if result is not None:
|
|
matches.append(result)
|
|
if len(matches) == 0:
|
|
return (None, None)
|
|
if len(matches) > 1:
|
|
raise Exception('Error: Multiple statics by same name')
|
|
return matches[0]
|
|
|
|
def _run_info(symbol_name, _type):
|
|
out = gdb.execute('info {} {}\\b'.format(_type, symbol_name), False, True)
|
|
return out
|
|
|
|
def get_static_variable(variable_name, _file=None, ref=False):
|
|
if get_static_variable.cache[_file][variable_name]:
|
|
return get_static_variable.cache[_file][variable_name]
|
|
|
|
out = _run_info(variable_name, 'variables')
|
|
(_type, symbol) = _find_match(out, _file)
|
|
if symbol is None:
|
|
raise Exception('Error: Symbol matching "{}" DNE.'.format(variable_name))
|
|
if ref:
|
|
symbol = '&' + symbol
|
|
if _type is not None:
|
|
_type += ' *'
|
|
if _type:
|
|
ret = '(({}){})'.format(_type, symbol)
|
|
ret = '({})'.format(symbol)
|
|
get_static_variable.cache[_file][variable_name] = ret
|
|
return ret
|
|
get_static_variable.cache = defaultdict(lambda: defaultdict(lambda: {}))
|
|
|
|
def get_static_function(function_name):
|
|
out = _run_info(function_name, 'functions')
|
|
# TODO: Figure out what we need to do to properly find matches here.
|
|
raise Exception('Not yet implemented.')
|