2020-09-18 12:21:04 -04:00

53 lines
1.6 KiB
Python

#!/usr/bin/env python
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
import gdb
from typing import List, Tuple, Dict
import os
def get_symbol_addresses(symbol: str) -> List[int]:
raw = gdb.execute("info variables %s" % symbol, False, True)
addresses = [int(x.split(" ")[0], 0) for x in raw.split("\n") if x.startswith("0x")]
return addresses
def get_filename(addr: int) -> str:
path = gdb.execute("info symbol %d" % addr, False, True).split(" ")[-1].strip()
return os.path.basename(path)
def get_tables() -> Dict[str, Tuple[int, int]]:
starts = get_symbol_addresses("__start___sancov_cntrs")
stops = get_symbol_addresses("__stop___sancov_cntrs")
if len(starts) != len(stops):
raise Exception("start and stop sancov cntrs do not match")
tables = {get_filename(x): (x, y - x) for (x, y) in zip(starts, stops)}
return tables
class CoverageCommand(gdb.Command):
def __init__(self):
super(self.__class__, self).__init__("coverage", gdb.COMMAND_DATA)
def invoke(self, arg, _):
argv = gdb.string_to_argv(arg)
(exe, test_input, result_path) = argv
gdb.execute("file {}".format(exe))
gdb.Breakpoint("exit")
gdb.execute("r {} 2>&1 >/dev/null".format(test_input))
tables = get_tables()
for (module, (addr, length)) in tables.items():
mem = gdb.selected_inferior().read_memory(addr, length)
with open(os.path.join(result_path, module + ".cov"), "wb") as handle:
handle.write(mem)
CoverageCommand()