From fddb8d24eccdcf467a8c777a9a22f4a1e54bf7dd Mon Sep 17 00:00:00 2001 From: Artem Kopotev Date: Tue, 15 Jun 2021 16:11:16 +0100 Subject: ArmPlatformPkg/Scripts: Infer dll load address from console output cmd_load_symbols.py can only load symbols from FV. Add the possibility to use UEFI console output to calculate dll load address and send add-symbol-file commands directly to ArmDS debugger dll load address can't be used directly from UEFI output, see comment in DebugPeCoffExtraActionLib: "This may not work correctly if you generate PE/COFF directly as then the Offset would not be required". 1) Use objdump -S module.dll | grep <_ModuleEntryPoint> to get offset in dll (offset) 2) Use Entrypoint=
from UEFI console output (entrypoint) 3) dll load address is (entrypoint)-(offset) Signed-off-by: Artem Kopotev Tested-by: Pierre Gondois --- ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py | 17 ++++++- ArmPlatformPkg/Scripts/Ds5/console_loader.py | 68 ++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 ArmPlatformPkg/Scripts/Ds5/console_loader.py diff --git a/ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py b/ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py index de4332edc7..89d2f28ba2 100644 --- a/ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py +++ b/ArmPlatformPkg/Scripts/Ds5/cmd_load_symbols.py @@ -1,5 +1,5 @@ # -# Copyright (c) 2011-2013, ARM Limited. All rights reserved. +# Copyright (c) 2011-2021, Arm Limited. All rights reserved. # # SPDX-License-Identifier: BSD-2-Clause-Patent # @@ -7,6 +7,8 @@ from arm_ds.debugger_v1 import Debugger from arm_ds.debugger_v1 import DebugException +from console_loader import load_symbol_from_console + import re, sys, getopt import edk2_debugger @@ -21,12 +23,16 @@ def usage(): print "-m,--sysmem=(base,size): System Memory region" print "-f,--fv=(base,size): Firmware region" print "-r,--rom=(base,size): ROM region" + print "-i,--input=: Filename for the EDK2 console output" + print "-o,--objdump=: Path to the objdump tool" verbose = False load_all = False report_file = None +input_file = None +objdump = None regions = [] -opts,args = getopt.getopt(sys.argv[1:], "hvar:vm:vr:vf:v", ["help","verbose","all","report=","sysmem=","rom=","fv="]) +opts,args = getopt.getopt(sys.argv[1:], "hvar:i:o:vm:vr:vf:v", ["help","verbose","all","report=","sysmem=","rom=","fv=","input=","objdump="]) if (opts is None) or (not opts): report_file = '../../../report.log' else: @@ -55,6 +61,10 @@ else: elif o in ("-r","--rom"): region_type = edk2_debugger.ArmPlatformDebugger.REGION_TYPE_ROM regex = region_reg + elif o in ("-i","--input"): + input_file = a + elif o in ("-o", "--objdump"): + objdump = a else: assert False, "Unhandled option (%s)" % o @@ -94,3 +104,6 @@ except Exception, (ErrorClass, ErrorMessage): print "Error(%s): %s" % (ErrorClass, ErrorMessage) except DebugException, de: print "DebugError: %s" % (de.getMessage()) + +if input_file: + load_symbol_from_console(ec, input_file, objdump, verbose) diff --git a/ArmPlatformPkg/Scripts/Ds5/console_loader.py b/ArmPlatformPkg/Scripts/Ds5/console_loader.py new file mode 100644 index 0000000000..e9c52d51f6 --- /dev/null +++ b/ArmPlatformPkg/Scripts/Ds5/console_loader.py @@ -0,0 +1,68 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# + +from arm_ds.debugger_v1 import DebugException + +import subprocess, os, edk2_debugger, re + +def get_module_name(line): + path = line.rsplit(' ')[1] + return os.path.splitext(os.path.basename(path))[0] + +def get_module_path(line): + return line.rsplit(' ')[1] + +def get_module_entrypoint(list, module_name): + line = [i for i in list if module_name in i and re.search(r'\b'+module_name+r'\b', i)] + if len(line) == 0: + # Module was not loaded using DxeDispatcher or PeiDispatcher. It is a SEC module + # Symbols for these modules are loaded from FV, not from console log + return None + + entrypoint_str = line[0].rsplit(' ')[4] + return entrypoint_str.rsplit('=')[1] + +def load_symbol_from_console(ec, console_file, objdump, verbose): + if objdump is None: + print "Error: A path to objdump tool is not specified, but -i parameter is provided" + elif not os.path.exists(objdump): + print "Error: Provided path to objdump is invalid: %s" % objdump + elif not os.path.exists(console_file): + print "Error: UEFI console file is not found: %s" % console_file + else: + + full_list = open(console_file).read().splitlines() + + efi_list = [i for i in full_list if "EntryPoint=" in i] + + full_list = dict.fromkeys(full_list) + full_list = [i for i in full_list if "add-symbol-file" in i] + + module_dict = {} + + for line in full_list: + name = get_module_name(line) + module_dict[name] = (get_module_path(line), get_module_entrypoint(efi_list, name)) + + for module in module_dict: + entrypoint_addr = module_dict[module][1] + + if entrypoint_addr is not None: + path = module_dict[module][0] + if not os.path.exists(path): + print "Module not found: " + path + ". Skipping..." + continue + + sp = subprocess.Popen([objdump,'-S', path], stdout = subprocess.PIPE) + + objdump_out = sp.stdout.readlines() + entrypoint_record = [i for i in objdump_out if "<_ModuleEntryPoint>" in i] + + entrypoint_offset = entrypoint_record[0].split(' ')[0] + + load_addr = int(entrypoint_addr, 16) - int(entrypoint_offset, 16) + + edk2_debugger.load_symbol_from_file(ec, path, load_addr, verbose) -- cgit v1.2.3