1#!/usr/bin/env python3
2#
3# Copyright (c) 2017 Intel Corporation.
4#
5# SPDX-License-Identifier: Apache-2.0
6#
7
8"""
9This script scans a specified object file and generates a header file
10that defined macros for the offsets of various found structure members
11(particularly symbols ending with ``_OFFSET`` or ``_SIZEOF``), primarily
12intended for use in assembly code.
13"""
14
15from elftools.elf.elffile import ELFFile
16from elftools.elf.sections import SymbolTableSection
17import argparse
18import sys
19
20
21def get_symbol_table(obj):
22    for section in obj.iter_sections():
23        if isinstance(section, SymbolTableSection):
24            return section
25
26    raise LookupError("Could not find symbol table")
27
28
29def gen_offset_header(input_name, input_file, output_file):
30    include_guard = "__GEN_OFFSETS_H__"
31    output_file.write("""/* THIS FILE IS AUTO GENERATED.  PLEASE DO NOT EDIT.
32 *
33 * This header file provides macros for the offsets of various structure
34 * members.  These offset macros are primarily intended to be used in
35 * assembly code.
36 */
37
38#ifndef %s
39#define %s\n\n""" % (include_guard, include_guard))
40
41    obj = ELFFile(input_file)
42    for sym in get_symbol_table(obj).iter_symbols():
43        if isinstance(sym.name, bytes):
44            sym.name = str(sym.name, 'ascii')
45
46        if not sym.name.endswith(('_OFFSET', '_SIZEOF')):
47            continue
48        if sym.entry['st_shndx'] != 'SHN_ABS':
49            continue
50        if sym.entry['st_info']['bind'] != 'STB_GLOBAL':
51            continue
52
53        output_file.write(
54            "#define %s 0x%x\n" %
55            (sym.name, sym.entry['st_value']))
56
57    output_file.write("\n#endif /* %s */\n" % include_guard)
58
59    return 0
60
61
62if __name__ == '__main__':
63    parser = argparse.ArgumentParser(
64        description=__doc__,
65        formatter_class=argparse.RawDescriptionHelpFormatter, allow_abbrev=False)
66
67    parser.add_argument(
68        "-i",
69        "--input",
70        required=True,
71        help="Input object file")
72    parser.add_argument(
73        "-o",
74        "--output",
75        required=True,
76        help="Output header file")
77
78    args = parser.parse_args()
79
80    input_file = open(args.input, 'rb')
81    output_file = open(args.output, 'w')
82
83    ret = gen_offset_header(args.input, input_file, output_file)
84    sys.exit(ret)
85