ElfUnitTestParser.py 3.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. # SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
  2. # SPDX-License-Identifier: Apache-2.0
  3. import argparse
  4. import os
  5. import subprocess
  6. import sys
  7. from typing import Dict, List
  8. import yaml
  9. try:
  10. import CreateSectionTable
  11. except ImportError:
  12. sys.path.append(os.path.expandvars(os.path.join('$IDF_PATH', 'tools', 'unit-test-app', 'tools')))
  13. import CreateSectionTable
  14. def get_target_objdump(idf_target: str) -> str:
  15. toolchain_for_target = {
  16. 'esp32': 'xtensa-esp32-elf-',
  17. 'esp32s2': 'xtensa-esp32s2-elf-',
  18. 'esp32s3': 'xtensa-esp32s3-elf-',
  19. 'esp32c2': 'riscv32-esp-elf-',
  20. 'esp32c3': 'riscv32-esp-elf-',
  21. }
  22. return toolchain_for_target.get(idf_target, '') + 'objdump'
  23. def parse_elf_test_cases(elf_file: str, idf_target: str) -> List[Dict]:
  24. objdump = get_target_objdump(idf_target)
  25. try:
  26. subprocess.check_output('{} -s {} > section_table.tmp'.format(objdump, elf_file), shell=True)
  27. table = CreateSectionTable.SectionTable('section_table.tmp')
  28. except subprocess.CalledProcessError:
  29. raise Exception('Can\'t resolve elf file. File not found.')
  30. finally:
  31. os.remove('section_table.tmp')
  32. bin_test_cases = []
  33. try:
  34. subprocess.check_output('{} -t {} | grep test_desc > case_address.tmp'.format(objdump, elf_file),
  35. shell=True)
  36. with open('case_address.tmp', 'rb') as input_f:
  37. for line in input_f:
  38. # process symbol table like: "3ffb4310 l O .dram0.data 00000018 test_desc_33$5010"
  39. sections = line.split()
  40. test_addr = int(sections[0], 16)
  41. section = sections[3]
  42. name_addr = table.get_unsigned_int(section, test_addr, 4)
  43. desc_addr = table.get_unsigned_int(section, test_addr + 4, 4)
  44. tc = {
  45. 'name': table.get_string('any', name_addr),
  46. 'desc': table.get_string('any', desc_addr),
  47. 'function_count': table.get_unsigned_int(section, test_addr + 20, 4),
  48. }
  49. bin_test_cases.append(tc)
  50. except subprocess.CalledProcessError:
  51. raise Exception('Test cases not found')
  52. finally:
  53. os.remove('case_address.tmp')
  54. return bin_test_cases
  55. if __name__ == '__main__':
  56. parser = argparse.ArgumentParser()
  57. parser.add_argument('elf_file', help='Elf file to parse')
  58. parser.add_argument('-t', '--idf_target',
  59. type=str, default=os.environ.get('IDF_TARGET', ''),
  60. help='Target of the elf, e.g. esp32s2')
  61. parser.add_argument('-o', '--output_file',
  62. type=str, default='elf_test_cases.yml',
  63. help='Target of the elf, e.g. esp32s2')
  64. args = parser.parse_args()
  65. assert args.idf_target
  66. test_cases = parse_elf_test_cases(args.elf_file, args.idf_target)
  67. with open(args.output_file, 'w') as out_file:
  68. yaml.dump(test_cases, out_file, default_flow_style=False)