kopia lustrzana https://github.com/espressif/esp-idf
95 wiersze
3.6 KiB
Python
95 wiersze
3.6 KiB
Python
![]() |
#!/usr/bin/env python
|
||
|
#
|
||
|
# 'check_for_file_paths.py' is a CI tool that checks all the unlinked object files
|
||
|
# in a CMake build directory for embedded copies of IDF_PATH.
|
||
|
#
|
||
|
# Designed to be run in CI as a check that __FILE__ macros haven't snuck into any source code.
|
||
|
#
|
||
|
# Checking the unlinked object files means we don't rely on anything being actually linked into the binary,
|
||
|
# just anything which could potentially be linked.
|
||
|
#
|
||
|
# Usage:
|
||
|
# ./check_for_file_paths.py <IDF_PATH> <BUILD_DIR>
|
||
|
#
|
||
|
#
|
||
|
#
|
||
|
# Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||
|
#
|
||
|
# 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 os
|
||
|
import re
|
||
|
import sys
|
||
|
|
||
|
from elftools.elf.elffile import ELFFile
|
||
|
|
||
|
# If an ESP-IDF source file has no option but to include __FILE__ macros, name it here (as re expression).
|
||
|
#
|
||
|
# IMPORTANT: This should only be used for upstream code where there is no other
|
||
|
# option. ESP-IDF code should avoid embedding file names as much as possible to
|
||
|
# limit the binary size and support reproducible builds
|
||
|
#
|
||
|
# Note: once ESP-IDF moves to Python >=3.6 then this can be simplified to use 'glob' and '**'
|
||
|
EXCEPTIONS = [
|
||
|
r'openssl/.+/ssl_pm.c.obj$', # openssl API requires __FILE__ in error reporting functions, as per upstream API
|
||
|
r'openssl/.+/ssl_bio.c.obj$',
|
||
|
r'unity/.+/unity_runner.c.obj$', # unity is not for production use, has __FILE__ for test information
|
||
|
]
|
||
|
|
||
|
|
||
|
def main(): # type: () -> None
|
||
|
idf_path = sys.argv[1]
|
||
|
build_dir = sys.argv[2]
|
||
|
|
||
|
assert os.path.exists(idf_path)
|
||
|
assert os.path.exists(build_dir)
|
||
|
|
||
|
print('Checking object files in {} for mentions of {}...'.format(build_dir, idf_path))
|
||
|
|
||
|
# note: once ESP-IDF moves to Python >=3.6 then this can be simplified to use 'glob' and f'{build_dir}**/*.obj'
|
||
|
files = []
|
||
|
for (dirpath, _, filepaths) in os.walk(build_dir):
|
||
|
files += [os.path.join(dirpath, filepath) for filepath in filepaths if filepath.endswith('.obj')]
|
||
|
|
||
|
print('Found {} object files...'.format(len(files)))
|
||
|
|
||
|
idf_path_binary = idf_path.encode() # we're going to be checking binary streams (note: probably non-ascii IDF_PATH will not match OK)
|
||
|
|
||
|
failures = 0
|
||
|
for obj_file in files:
|
||
|
if not any(re.search(exception, obj_file) for exception in EXCEPTIONS):
|
||
|
failures += check_file(obj_file, idf_path_binary)
|
||
|
if failures > 0:
|
||
|
raise SystemExit('{} source files are embedding file paths, see list above.'.format(failures))
|
||
|
print('No embedded file paths found')
|
||
|
|
||
|
|
||
|
def check_file(obj_file, idf_path): # type: (str, bytes) -> int
|
||
|
failures = 0
|
||
|
with open(obj_file, 'rb') as f:
|
||
|
elf = ELFFile(f)
|
||
|
for sec in elf.iter_sections():
|
||
|
# can't find a better way to filter out only sections likely to contain strings,
|
||
|
# and exclude debug sections. .dram matches DRAM_STR, which links to .dram1
|
||
|
if '.rodata' in sec.name or '.dram' in sec.name:
|
||
|
contents = sec.data()
|
||
|
if idf_path in contents:
|
||
|
print('error: {} contains an unwanted __FILE__ macro'.format(obj_file))
|
||
|
failures += 1
|
||
|
break
|
||
|
return failures
|
||
|
|
||
|
|
||
|
if __name__ == '__main__':
|
||
|
main()
|