configuration.py 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. #!/usr/bin/env python3
  2. #
  3. # SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
  4. # SPDX-License-Identifier: Apache-2.0
  5. import argparse
  6. import csv
  7. import os
  8. import subprocess
  9. import sys
  10. import re
  11. from io import StringIO
  12. OPT_MIN_LEN = 7
  13. espidf_objdump = None
  14. espidf_missing_function_info = True
  15. class sdkconfig_c:
  16. def __init__(self, path):
  17. lines = open(path).read().splitlines()
  18. config = dict()
  19. for l in lines:
  20. if len(l) > OPT_MIN_LEN and l[0] != '#':
  21. mo = re.match( r'(.*)=(.*)', l, re.M|re.I)
  22. if mo:
  23. config[mo.group(1)]=mo.group(2).replace('"', '')
  24. self.config = config
  25. def index(self, i):
  26. return self.config[i]
  27. def check(self, options):
  28. options = options.replace(' ', '')
  29. if '&&' in options:
  30. for i in options.split('&&'):
  31. if i[0] == '!':
  32. i = i[1:]
  33. if i in self.config:
  34. return False
  35. else:
  36. if i not in self.config:
  37. return False
  38. else:
  39. i = options
  40. if i[0] == '!':
  41. i = i[1:]
  42. if i in self.config:
  43. return False
  44. else:
  45. if i not in self.config:
  46. return False
  47. return True
  48. class object_c:
  49. def read_dump_info(self, pathes):
  50. new_env = os.environ.copy()
  51. new_env['LC_ALL'] = 'C'
  52. dumps = list()
  53. print('pathes:', pathes)
  54. for path in pathes:
  55. try:
  56. dump = StringIO(subprocess.check_output([espidf_objdump, '-t', path], env=new_env).decode())
  57. dumps.append(dump.readlines())
  58. except subprocess.CalledProcessError as e:
  59. raise RuntimeError('cmd:%s result:%s'%(e.cmd, e.returncode))
  60. return dumps
  61. def get_func_section(self, dumps, func):
  62. for dump in dumps:
  63. for l in dump:
  64. if ' %s'%(func) in l and '*UND*' not in l:
  65. m = re.match(r'(\S*)\s*([glw])\s*([F|O])\s*(\S*)\s*(\S*)\s*(\S*)\s*', l, re.M|re.I)
  66. if m and m[6] == func:
  67. return m[4].replace('.text.', '')
  68. if espidf_missing_function_info:
  69. print('%s failed to find section'%(func))
  70. return None
  71. else:
  72. raise RuntimeError('%s failed to find section'%(func))
  73. def __init__(self, name, pathes, libray):
  74. self.name = name
  75. self.libray = libray
  76. self.funcs = dict()
  77. self.pathes = pathes
  78. self.dumps = self.read_dump_info(pathes)
  79. def append(self, func):
  80. section = self.get_func_section(self.dumps, func)
  81. if section != None:
  82. self.funcs[func] = section
  83. def functions(self):
  84. nlist = list()
  85. for i in self.funcs:
  86. nlist.append(i)
  87. return nlist
  88. def sections(self):
  89. nlist = list()
  90. for i in self.funcs:
  91. nlist.append(self.funcs[i])
  92. return nlist
  93. class library_c:
  94. def __init__(self, name, path):
  95. self.name = name
  96. self.path = path
  97. self.objs = dict()
  98. def append(self, obj, path, func):
  99. if obj not in self.objs:
  100. self.objs[obj] = object_c(obj, path, self.name)
  101. self.objs[obj].append(func)
  102. class libraries_c:
  103. def __init__(self):
  104. self.libs = dict()
  105. def append(self, lib, lib_path, obj, obj_path, func):
  106. if lib not in self.libs:
  107. self.libs[lib] = library_c(lib, lib_path)
  108. self.libs[lib].append(obj, obj_path, func)
  109. def dump(self):
  110. for libname in self.libs:
  111. lib = self.libs[libname]
  112. for objname in lib.objs:
  113. obj = lib.objs[objname]
  114. print('%s, %s, %s, %s'%(libname, objname, obj.path, obj.funcs))
  115. class paths_c:
  116. def __init__(self):
  117. self.paths = dict()
  118. def append(self, lib, obj, path):
  119. if '$IDF_PATH' in path:
  120. path = path.replace('$IDF_PATH', os.environ['IDF_PATH'])
  121. if lib not in self.paths:
  122. self.paths[lib] = dict()
  123. if obj not in self.paths[lib]:
  124. self.paths[lib][obj] = list()
  125. self.paths[lib][obj].append(path)
  126. def index(self, lib, obj):
  127. if lib not in self.paths:
  128. return None
  129. if '*' in self.paths[lib]:
  130. obj = '*'
  131. return self.paths[lib][obj]
  132. def generator(library_file, object_file, function_file, sdkconfig_file, missing_function_info, objdump='riscv32-esp-elf-objdump'):
  133. global espidf_objdump, espidf_missing_function_info
  134. espidf_objdump = objdump
  135. espidf_missing_function_info = missing_function_info
  136. sdkconfig = sdkconfig_c(sdkconfig_file)
  137. lib_paths = paths_c()
  138. for p in csv.DictReader(open(library_file, 'r')):
  139. lib_paths.append(p['library'], '*', p['path'])
  140. obj_paths = paths_c()
  141. for p in csv.DictReader(open(object_file, 'r')):
  142. obj_paths.append(p['library'], p['object'], p['path'])
  143. libraries = libraries_c()
  144. for d in csv.DictReader(open(function_file, 'r')):
  145. if d['option'] and sdkconfig.check(d['option']) == False:
  146. print('skip %s(%s)'%(d['function'], d['option']))
  147. continue
  148. lib_path = lib_paths.index(d['library'], '*')
  149. obj_path = obj_paths.index(d['library'], d['object'])
  150. if not obj_path:
  151. obj_path = lib_path
  152. libraries.append(d['library'], lib_path[0], d['object'], obj_path, d['function'])
  153. return libraries
  154. def main():
  155. argparser = argparse.ArgumentParser(description='Libraries management')
  156. argparser.add_argument(
  157. '--library', '-l',
  158. help='Library description file',
  159. type=str)
  160. argparser.add_argument(
  161. '--object', '-b',
  162. help='Object description file',
  163. type=str)
  164. argparser.add_argument(
  165. '--function', '-f',
  166. help='Function description file',
  167. type=str)
  168. argparser.add_argument(
  169. '--sdkconfig', '-s',
  170. help='sdkconfig file',
  171. type=str)
  172. args = argparser.parse_args()
  173. libraries = generator(args.library, args.object, args.function, args.sdkconfig)
  174. # libraries.dump()
  175. if __name__ == '__main__':
  176. main()