libvirt/scripts/mock-noinline.py
Daniel P. Berrangé ba6d9264c6 src: add G_GNUC_NO_INLINE annotations for mocked symbols
We should prevent inlining of symbols from the driver .so files that are
mocked, as well as those in the main libvirt.so

This isn't fixing any currently known problem, just trying to prevent
future issues.

Reviewed-by: Ján Tomko <jtomko@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
2020-08-04 17:58:08 +01:00

82 lines
2.5 KiB
Python

#!/usr/bin/env python3
#
# Copyright (C) 2017-2019 Red Hat, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library. If not, see
# <http://www.gnu.org/licenses/>.
import re
import sys
noninlined = {}
mocked = {}
# Functions in public header don't get the noinline annotation
noninlined["virEventAddTimeout"] = True
# This one confuses the script as its defined in the mock file
# but is actually just a local helper
noninlined["virMockStatRedirect"] = True
def scan_annotations(filename):
with open(filename, "r") as fh:
func = None
for line in fh:
m = re.search(r'''^\s*(\w+)\(''', line)
if m is None:
m = re.search(r'''^(?:\w+\*?\s+)+(?:\*\s*)?(\w+)\(''', line)
if m is not None:
name = m.group(1)
if "ATTRIBUTE" not in name and "G_GNUC_" not in name:
func = name
elif line.isspace():
func = None
if "G_GNUC_NO_INLINE" in line:
if func is not None:
noninlined[func] = True
def scan_overrides(filename):
with open(filename, "r") as fh:
lineno = 0
for line in fh:
lineno = lineno + 1
m = re.search(r'''^(\w+)\(''', line)
if m is None:
m = re.search(r'''^\w+\s*(?:\*\s*)?(\w+)\(''', line)
if m is not None:
name = m.group(1)
if name.startswith("vir") or name.startswith("qemu") or name.startswith("libxl"):
mocked[name] = "%s:%d" % (filename, lineno)
for filename in sys.argv[1:]:
if filename.endswith(".h"):
scan_annotations(filename)
elif filename.endswith("mock.c"):
scan_overrides(filename)
warned = False
for func in mocked.keys():
if func not in noninlined:
warned = True
print("%s is mocked at %s but missing noinline annotation" %
(func, mocked[func]), file=sys.stderr)
if warned:
sys.exit(1)
sys.exit(0)