15f9996aaSopenharmony_ci#!/usr/bin/env python3
25f9996aaSopenharmony_ci# -*- coding: utf-8 -*-
35f9996aaSopenharmony_ci
45f9996aaSopenharmony_ci#
55f9996aaSopenharmony_ci# Copyright (c) 2022 Huawei Device Co., Ltd.
65f9996aaSopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
75f9996aaSopenharmony_ci# you may not use this file except in compliance with the License.
85f9996aaSopenharmony_ci# You may obtain a copy of the License at
95f9996aaSopenharmony_ci#
105f9996aaSopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
115f9996aaSopenharmony_ci#
125f9996aaSopenharmony_ci# Unless required by applicable law or agreed to in writing, software
135f9996aaSopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
145f9996aaSopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
155f9996aaSopenharmony_ci# See the License for the specific language governing permissions and
165f9996aaSopenharmony_ci# limitations under the License.
175f9996aaSopenharmony_ci#
185f9996aaSopenharmony_ci
195f9996aaSopenharmony_ciimport sys
205f9996aaSopenharmony_ciimport argparse
215f9996aaSopenharmony_ciimport os
225f9996aaSopenharmony_ciimport platform
235f9996aaSopenharmony_ciimport subprocess
245f9996aaSopenharmony_ci
255f9996aaSopenharmony_ci
265f9996aaSopenharmony_cidef gen_symbols(tmp_file, sort_lines, symbols_path):
275f9996aaSopenharmony_ci    with os.fdopen(os.open(tmp_file, os.O_RDWR | os.O_CREAT), 'w', encoding='utf-8') as output_file:
285f9996aaSopenharmony_ci        for item in sort_lines:
295f9996aaSopenharmony_ci            output_file.write('{}\n'.format(item))
305f9996aaSopenharmony_ci
315f9996aaSopenharmony_ci    with os.fdopen(os.open(symbols_path, os.O_RDWR | os.O_CREAT), 'w', encoding='utf-8') as output_file:
325f9996aaSopenharmony_ci        cmd = 'sort {}'.format(tmp_file)
335f9996aaSopenharmony_ci        subprocess.run(cmd.split(), stdout=output_file)
345f9996aaSopenharmony_ci
355f9996aaSopenharmony_ci
365f9996aaSopenharmony_cidef create_mini_debug_info(binary_path, stripped_binary_path, root_path, clang_base_dir):
375f9996aaSopenharmony_ci    # temporary file path
385f9996aaSopenharmony_ci    dynsyms_path = stripped_binary_path + ".dynsyms"
395f9996aaSopenharmony_ci    funcsysms_path = stripped_binary_path + ".funcsyms"
405f9996aaSopenharmony_ci    keep_path = stripped_binary_path + ".keep"
415f9996aaSopenharmony_ci    debug_path = stripped_binary_path + ".debug"
425f9996aaSopenharmony_ci    mini_debug_path = stripped_binary_path + ".minidebug"
435f9996aaSopenharmony_ci
445f9996aaSopenharmony_ci    # llvm tools path
455f9996aaSopenharmony_ci    host_platform = platform.uname().system.lower()
465f9996aaSopenharmony_ci    host_cpu = platform.uname().machine.lower()
475f9996aaSopenharmony_ci    llvm_dir_path = os.path.join(
485f9996aaSopenharmony_ci        clang_base_dir, host_platform + '-' + host_cpu, 'llvm/bin')
495f9996aaSopenharmony_ci    if not os.path.exists(llvm_dir_path):
505f9996aaSopenharmony_ci        llvm_dir_path = os.path.join(root_path, 'out/llvm-install/bin')
515f9996aaSopenharmony_ci    llvm_nm_path = os.path.join(llvm_dir_path, "llvm-nm")
525f9996aaSopenharmony_ci    llvm_objcopy_path = os.path.join(llvm_dir_path, "llvm-objcopy")
535f9996aaSopenharmony_ci
545f9996aaSopenharmony_ci    cmd_list = []
555f9996aaSopenharmony_ci
565f9996aaSopenharmony_ci    gen_symbols_cmd = llvm_nm_path + " -D " + binary_path + " --format=posix --defined-only"
575f9996aaSopenharmony_ci    gen_func_symbols_cmd = llvm_nm_path + " " + binary_path + " --format=posix --defined-only"
585f9996aaSopenharmony_ci    gen_keep_symbols_cmd = "comm -13 " + dynsyms_path + " " + funcsysms_path
595f9996aaSopenharmony_ci    gen_keep_debug_cmd = llvm_objcopy_path + \
605f9996aaSopenharmony_ci        " --only-keep-debug " + binary_path + " " + debug_path
615f9996aaSopenharmony_ci    gen_mini_debug_cmd = llvm_objcopy_path + " -S --remove-section .gdb_index --remove-section .comment --keep-symbols=" + \
625f9996aaSopenharmony_ci        keep_path + " " + debug_path + " " + mini_debug_path
635f9996aaSopenharmony_ci    compress_debuginfo = "xz " + mini_debug_path
645f9996aaSopenharmony_ci    gen_stripped_binary = llvm_objcopy_path + " --add-section .gnu_debugdata=" + \
655f9996aaSopenharmony_ci        mini_debug_path + ".xz " + stripped_binary_path
665f9996aaSopenharmony_ci
675f9996aaSopenharmony_ci
685f9996aaSopenharmony_ci    tmp_file1 = '{}.tmp1'.format(dynsyms_path)
695f9996aaSopenharmony_ci    tmp_file2 = '{}.tmp2'.format(dynsyms_path)
705f9996aaSopenharmony_ci    with os.fdopen(os.open(tmp_file1, os.O_RDWR | os.O_CREAT), 'w', encoding='utf-8') as output_file:
715f9996aaSopenharmony_ci        subprocess.run(gen_symbols_cmd.split(), stdout=output_file)
725f9996aaSopenharmony_ci
735f9996aaSopenharmony_ci    with os.fdopen(os.open(tmp_file1, os.O_RDWR | os.O_CREAT), 'r', encoding='utf-8') as output_file:
745f9996aaSopenharmony_ci        lines = output_file.readlines()
755f9996aaSopenharmony_ci        sort_lines = []
765f9996aaSopenharmony_ci        for line in lines:
775f9996aaSopenharmony_ci            columns = line.strip().split()
785f9996aaSopenharmony_ci            if columns:
795f9996aaSopenharmony_ci                sort_lines.append(columns[0])
805f9996aaSopenharmony_ci
815f9996aaSopenharmony_ci    gen_symbols(tmp_file2, sort_lines, dynsyms_path)
825f9996aaSopenharmony_ci    os.remove(tmp_file1)
835f9996aaSopenharmony_ci    os.remove(tmp_file2)
845f9996aaSopenharmony_ci
855f9996aaSopenharmony_ci
865f9996aaSopenharmony_ci    tmp_file1 = '{}.tmp1'.format(funcsysms_path)
875f9996aaSopenharmony_ci    tmp_file2 = '{}.tmp2'.format(funcsysms_path)
885f9996aaSopenharmony_ci    with os.fdopen(os.open(tmp_file1, os.O_RDWR | os.O_CREAT), 'w', encoding='utf-8') as output_file:
895f9996aaSopenharmony_ci        subprocess.run(gen_func_symbols_cmd.split(), stdout=output_file)
905f9996aaSopenharmony_ci
915f9996aaSopenharmony_ci    with os.fdopen(os.open(tmp_file1, os.O_RDWR | os.O_CREAT), 'r', encoding='utf-8') as output_file:
925f9996aaSopenharmony_ci        lines = output_file.readlines()
935f9996aaSopenharmony_ci        sort_lines = []
945f9996aaSopenharmony_ci        for line in lines:
955f9996aaSopenharmony_ci            columns = line.strip().split()
965f9996aaSopenharmony_ci            if len(columns) > 2 and ('t' in columns[1] or 'T' in columns[1] or 'd' in columns[1]):
975f9996aaSopenharmony_ci                sort_lines.append(columns[0])
985f9996aaSopenharmony_ci
995f9996aaSopenharmony_ci    gen_symbols(tmp_file2, sort_lines, funcsysms_path)
1005f9996aaSopenharmony_ci    os.remove(tmp_file1)
1015f9996aaSopenharmony_ci    os.remove(tmp_file2)
1025f9996aaSopenharmony_ci
1035f9996aaSopenharmony_ci
1045f9996aaSopenharmony_ci    with os.fdopen(os.open(keep_path, os.O_RDWR | os.O_CREAT), 'w', encoding='utf-8') as output_file:
1055f9996aaSopenharmony_ci        subprocess.run(gen_keep_symbols_cmd.split(), stdout=output_file)
1065f9996aaSopenharmony_ci
1075f9996aaSopenharmony_ci
1085f9996aaSopenharmony_ci    cmd_list.append(gen_keep_debug_cmd)
1095f9996aaSopenharmony_ci    cmd_list.append(gen_mini_debug_cmd)
1105f9996aaSopenharmony_ci    cmd_list.append(compress_debuginfo)
1115f9996aaSopenharmony_ci    cmd_list.append(gen_stripped_binary)
1125f9996aaSopenharmony_ci
1135f9996aaSopenharmony_ci    # execute each cmd to generate temporary file
1145f9996aaSopenharmony_ci    # which .gnu_debugdata section depends on
1155f9996aaSopenharmony_ci    for cmd in cmd_list:
1165f9996aaSopenharmony_ci        subprocess.call(cmd.split(), shell=False)
1175f9996aaSopenharmony_ci
1185f9996aaSopenharmony_ci    # remove temporary file
1195f9996aaSopenharmony_ci    os.remove(dynsyms_path)
1205f9996aaSopenharmony_ci    os.remove(funcsysms_path)
1215f9996aaSopenharmony_ci    os.remove(keep_path)
1225f9996aaSopenharmony_ci    os.remove(debug_path)
1235f9996aaSopenharmony_ci    os.remove(mini_debug_path + ".xz")
1245f9996aaSopenharmony_ci
1255f9996aaSopenharmony_ci
1265f9996aaSopenharmony_cidef main():
1275f9996aaSopenharmony_ci    parser = argparse.ArgumentParser(description=__doc__)
1285f9996aaSopenharmony_ci    parser.add_argument("--unstripped-path",
1295f9996aaSopenharmony_ci                        help="unstripped binary path")
1305f9996aaSopenharmony_ci    parser.add_argument("--stripped-path",
1315f9996aaSopenharmony_ci                        help="stripped binary path")
1325f9996aaSopenharmony_ci    parser.add_argument("--root-path",
1335f9996aaSopenharmony_ci                        help="root path is used to search llvm toolchain")
1345f9996aaSopenharmony_ci    parser.add_argument("--clang-base-dir", help="")
1355f9996aaSopenharmony_ci    args = parser.parse_args()
1365f9996aaSopenharmony_ci
1375f9996aaSopenharmony_ci    create_mini_debug_info(args.unstripped_path,
1385f9996aaSopenharmony_ci                           args.stripped_path, args.root_path, args.clang_base_dir)
1395f9996aaSopenharmony_ci
1405f9996aaSopenharmony_ci
1415f9996aaSopenharmony_ciif __name__ == "__main__":
1425f9996aaSopenharmony_ci    sys.exit(main())
143