valinor-1.1.4/0000777000000000000000000000000013463771202011326 5ustar 00000000000000valinor-1.1.4/LICENSE0000666000000000000000000002607413463042175012344 0ustar 00000000000000Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. valinor-1.1.4/MANIFEST.in0000666000000000000000000000005013463042175013057 0ustar 00000000000000include readme.md LICENSE docs/pypi.txt valinor-1.1.4/PKG-INFO0000666000000000000000000000120513463771202012421 0ustar 00000000000000Metadata-Version: 1.1 Name: valinor Version: 1.1.4 Summary: Generate IDE project files to debug ELF files. Home-page: https://github.com/ARMmbed/valinor Author: Martin Kojtal, James Crosby Author-email: c0170@rocketmail.com, James.Crosby@arm.com License: Apache-2.0 Description: valinor ------- Generate IDE project files to debug ELF files. Keywords: debug c cpp project generator embedded Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Topic :: Utilities Classifier: License :: OSI Approved :: Apache Software License Classifier: Environment :: Console valinor-1.1.4/docs/0000777000000000000000000000000013463771202012256 5ustar 00000000000000valinor-1.1.4/docs/pypi.txt0000666000000000000000000000010113463042175013770 0ustar 00000000000000valinor ------- Generate IDE project files to debug ELF files. valinor-1.1.4/readme.md0000666000000000000000000000362413463042175013112 0ustar 00000000000000##valinor [![Circle CI](https://circleci.com/gh/ARMmbed/valinor.svg?style=svg&circle-token=d70b5c2db296d7886f68383cb07c79e7d7bcce14)](https://circleci.com/gh/ARMmbed/valinor) Generate debugger project files, and launch a debugger, to debug an ELF file. valinor is designed to be used as a proxy debug command for yotta targets to provide as their `scripts.debug` command. See the [yotta targets guide](http://docs.yottabuild.org/tutorial/targets.html#debug-support) for more details about debug support in yotta. ### Usage ```sh valinor [-t IDE_TOOL] [-d PROJECT_DIR] [-n] --target TARGET executable ``` * **`TARGET`** is a target name that project_generator will accept, for example K64F. * **`-t IDE_TOOL, --tool IDE_TOOL`** The Debug tool (IDE) to generate for. If omitted, a debug project will be generated for an IDE detected on your system, defaulting to opening a GDB debug session, if no known IDEs are detected. * **`-d PROJECT_DIR, --project-dir PROJECT_DIR`** The directory in which to generate any necessary project files. Defaults to the directory of the executable argument. * **`-n, --no-open`** Do not open the debug session, just generate the necessary files to enable debugging, and print the command that would be necessary to proceed. * **`--target TARGET`** The target board to generate a project file for (e.g. K64F). This name is passed to [`project_generator`](https://github.com/project-generator/project_generator), so any name that `project_generator` accepts will work. * `executable` Path to an ELF file (with debug symbols) to debug. ### Using in yotta target descriptions To use valinor to add debug support to a yotta target description add this to your target.json file (replacing K64F with the project_generator target ID for the chip or board on your target): ```json "scripts":{ "debug": ["valinor", "--target", "frdm-k64f", "$program"] } ``` valinor-1.1.4/setup.cfg0000666000000000000000000000005213463771202013144 0ustar 00000000000000[egg_info] tag_build = tag_date = 0 valinor-1.1.4/setup.py0000666000000000000000000000253613463771064013054 0ustar 00000000000000# Copyright 2014-2015 ARM Limited # # Licensed under the Apache License, Version 2.0 # See LICENSE file for details. import os from setuptools import setup, find_packages def read(fname): with open(os.path.join(os.path.dirname(__file__), fname)) as f: return f.read() return None setup( name = "valinor", version = "1.1.4", author = 'Martin Kojtal, James Crosby', author_email = "c0170@rocketmail.com, James.Crosby@arm.com", description = ("Generate IDE project files to debug ELF files."), license = "Apache-2.0", keywords = "debug c cpp project generator embedded", url = "https://github.com/ARMmbed/valinor", packages=find_packages(), package_data={ }, long_description=read('docs/pypi.txt'), classifiers=[ "Development Status :: 3 - Alpha", "Topic :: Utilities", "License :: OSI Approved :: Apache Software License", "Environment :: Console", ], entry_points={ "console_scripts": [ "valinor=valinor:main", ], }, test_suite = 'nose.collector', install_requires=[ 'pyyaml>=5.1,<6.0', 'Jinja2>=2.7.0,<3', 'setuptools', 'colorama>=0.3,<0.4', 'pyOCD>=0.3,<1.0', 'project_generator>=0.8.0,<0.9.0', 'pyelftools==0.23', ], tests_require=[ 'nose', ] ) valinor-1.1.4/valinor/0000777000000000000000000000000013463771202013000 5ustar 00000000000000valinor-1.1.4/valinor/__init__.py0000666000000000000000000000017413463042175015113 0ustar 00000000000000# Copyright 2015 ARM Limited # # Licensed under the Apache License, Version 2.0 # See LICENSE file from .main import main valinor-1.1.4/valinor/elf.py0000666000000000000000000000261513463042175014124 0ustar 00000000000000# Copyright 2015 ARM Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import logging from elftools.elf.elffile import ELFFile from elftools.common.exceptions import ELFError def get_files_from_executable(filename): with open(filename, 'rb') as f: # ELFFile looks for magic number, if there's none, ELFError is raised try: elffile = ELFFile(f) except ELFError: logging.info("%s is invalid elf file" % filename) return [] if not elffile.has_dwarf_info(): logging.info("File does not have dwarf info, no sources in the project file") return dwarfinfo = elffile.get_dwarf_info() files = [] # Go over all the line programs in the DWARF information and get source files paths for CU in dwarfinfo.iter_CUs(): top_DIE = CU.get_top_DIE() files.append(top_DIE.get_full_path()) return files valinor-1.1.4/valinor/gdb.py0000666000000000000000000000660613463042175014116 0ustar 00000000000000#!/usr/bin/env python # Copyright 2015 ARM Limited # # Licensed under the Apache License, Version 2.0 # See LICENSE file for details. import subprocess import logging import threading import signal import traceback try: import Queue except ImportError: import queue as Queue logger = logging.getLogger('gdb') def _ignoreSignal(signum, frame): logging.debug('ignoring signal %s, traceback:\n%s' % ( signum, ''.join(traceback.format_list(traceback.extract_stack(frame))) )) def _launchPyOCDGDBServer(msg_queue): logger.info('preparing PyOCD gdbserver...') from pyOCD.gdbserver import GDBServer from pyOCD.board import MbedBoard gdb = None try: logger.info('finding connected board...') board_selected = MbedBoard.chooseBoard(blocking=False) if board_selected is not None: with board_selected as board: logger.info('starting PyOCD gdbserver...') gdb = GDBServer( board, 3333, { 'break_at_hardfault': True, 'step_into_interrupt': False, 'break_on_reset': False, } ) if gdb.isAlive(): msg_queue.put('alive') while gdb.isAlive(): gdb.join(timeout = 0.5) # check for a "kill" message from the parent process: try: msg = msg_queue.get(False) if msg == 'kill': gdb.stop() break except Queue.Empty: pass else: logger.error('failed to find a connected board') except Exception as e: logger.error('exception in GDB server thread: %s', e) if gdb != None: gdb.stop() raise msg_queue.put('dead') def launcher(gdb_exe): def launch_gdb(projectfiles, executable): # the "projectfiles" for gdb are really command files that we should # execute to set up the debug session: cmd = [gdb_exe] for f in projectfiles: cmd += ['-x', f] cmd.append(executable) # ignore Ctrl-C while gdb is running: signal.signal(signal.SIGINT, _ignoreSignal); child = subprocess.Popen(cmd) child.wait() return launch_gdb def arm_none_eabi_launcher(gdb_exe): gdb_launcher = launcher(gdb_exe) def launch_arm_gdb(projectfiles, executable): queue = Queue.Queue() t = threading.Thread(target=_launchPyOCDGDBServer, args=(queue,)) try: t.start() # wait for an 'alive' message from the server before starting gdb # itself: msg = None while msg != 'alive': try: msg = queue.get(timeout=1.0) except Queue.Empty as e: msg = None pass if msg == 'dead' or not t.is_alive(): raise Exception('gdb server failed to start') except KeyboardInterrupt as e: logger.error('stopped by user') queue.put('kill') t.join() raise gdb_launcher(projectfiles, executable) queue.put('kill') t.join() return launch_arm_gdb valinor-1.1.4/valinor/ide_detection.py0000666000000000000000000001055013463042175016152 0ustar 00000000000000#!/usr/bin/env python # Copyright 2015 ARM Limited # # Licensed under the Apache License, Version 2.0 # See LICENSE file for details. import subprocess import logging import os from distutils.spawn import find_executable from project_generator import tools_supported from project_generator_definitions.definitions import ProGenDef from valinor.gdb import launcher as gdb_launcher from valinor.gdb import arm_none_eabi_launcher as arm_none_eabi_gdb_launcher # cache the detected IDEs, (map of ide name to a function(projectfiles, # executable) that will launch it) IDE_Launchers = { } IDEs_Scanned = False # preferred order of IDEs if multiple are available IDE_Preference = [ 'uvision', 'uvision5', 'arm_none_eabi_gdb', 'gdb' ] logger = logging.getLogger('ide_detect') def _read_hklm_reg_value(key_path, value_name): ''' read a value from a registry key under HKEY_LOCAL_MACHINE ''' if os.name != 'nt': return None import _winreg as winreg k = None value = None try: k = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, key_path) v = winreg.QueryValueEx(k, value_name) return v[0] except WindowsError: if k: winreg.CloseKey(k) return value def _find_uvision(): found = find_executable('UV4') if found: return found if os.name == 'nt': found_pathdir = _read_hklm_reg_value(r'Software\Keil\Products\MDK', 'Path') if not found_pathdir: found_pathdir = _read_hklm_reg_value(r'Software\Wow6432Node\Keil\Products\MDK', 'Path') if found_pathdir: found = os.path.join(found_pathdir, '..', 'UV4', 'UV4.exe') if os.path.isfile(found): return os.path.normpath(found) return None def _find_generic_gdb(): return find_executable('gdb') def _find_arm_none_eabi_gdb(): return find_executable('arm-none-eabi-gdb') def _uvision_launcher(uvision_exe): def launch_uvision(projectfiles, executable): uvproj = [ x for x in projectfiles if x.endswith('.uvproj') or x.endswith('.uvprojx') ] if len(uvproj) != 1: raise Exception('Exactly one project file must be provided') logger.info("launching uvision: %s %s", uvision_exe, uvproj[0]) child = subprocess.Popen( [uvision_exe, uvproj[0]], ) child.wait() return launch_uvision IDE_Scanners = { 'uvision': (_find_uvision, _uvision_launcher), 'uvision5': (_find_uvision, _uvision_launcher), 'gdb': (_find_generic_gdb, gdb_launcher), 'arm_none_eabi_gdb': (_find_arm_none_eabi_gdb, arm_none_eabi_gdb_launcher), } def _ensure_IDEs_scanned(): global IDEs_Scanned, IDE_Launchers if IDEs_Scanned: return # !!! could scan in parallel, should be worth it as scanners are # likely highly io-bound for ide, (scanner, launcher) in IDE_Scanners.items(): logger.debug('scanning for %s: %s', ide, (scanner, launcher)) detected = scanner() logger.debug('scanning for %s... %sfound', ide, ('not ', '')[bool(detected)]) if detected: IDE_Launchers[ide] = launcher(detected) # make sure we have a preference order for all detected IDEs, even # if the list hasn't been updated: if ide not in IDE_Preference: IDE_Preference.append(ide) IDEs_Scanned = True def available(): ''' return a list of available IDEs on this platform ''' _ensure_IDEs_scanned() return [k for k in IDE_Launchers.keys()] def select(available_ides, target, project_settings): ''' select the preferred option out of the available IDEs to debug the selected target, or None ''' possible_ides = [] for ide in available_ides: tool = tools_supported.ToolsSupported().get_tool(ide) if not tool.is_supported_by_default(target): if ProGenDef(ide).is_supported(target): possible_ides.append(ide) else: possible_ides.append(ide) if len(possible_ides): return sorted(possible_ides, key=lambda x:IDE_Preference.index(x))[0] else: return None def get_launcher(ide): ''' return a function(projectfiles) that will launch the specified IDE when called, or None if that IDE cannot be found ''' if ide in IDE_Launchers: return IDE_Launchers[ide] else: return None valinor-1.1.4/valinor/logging_setup.py0000666000000000000000000000540113463042175016220 0ustar 00000000000000# Copyright 2014-2015 ARM Limited # # Licensed under the Apache License, Version 2.0 # See LICENSE file for details. # standard library modules, , , import logging # colorama, BSD 3-Clause license, cross-platform terminal colours, pip install colorama import colorama # colorama replaces stdout and stderr with objects that do switch colour # sequences to the appropriate windows ones, we do most of our stdout through # logging, so setup that proxying here: colorama.init() class Formatter(logging.Formatter): def __init__(self): super(Formatter, self).__init__() def levelStyle(self, record): if record.levelno <= logging.DEBUG: return colorama.Style.DIM + colorama.Fore.RESET elif record.levelno >= logging.CRITICAL: return colorama.Style.BRIGHT + colorama.Fore.RED elif record.levelno >= logging.ERROR: return colorama.Style.BRIGHT + colorama.Fore.RED elif record.levelno >= logging.WARNING: return colorama.Style.BRIGHT + colorama.Fore.YELLOW return colorama.Style.NORMAL + colorama.Fore.GREEN def messageStyle(self, record): if record.levelno <= logging.DEBUG: return colorama.Style.DIM + colorama.Fore.RESET elif record.levelno >= logging.CRITICAL: return colorama.Style.BRIGHT + colorama.Fore.RED elif record.levelno >= logging.ERROR: return colorama.Style.NORMAL + colorama.Fore.RED elif record.levelno >= logging.WARNING: return colorama.Style.NORMAL + colorama.Fore.YELLOW return colorama.Style.NORMAL + colorama.Fore.RESET def format(self, record): s = '' s += self.levelStyle(record) s += record.levelname.lower() s += colorama.Fore.RESET + ':' if record.levelno <= logging.DEBUG: s += record.name + ': ' else: s += ' ' s += self.messageStyle(record) s += record.getMessage() s += colorama.Style.RESET_ALL return s def init(level=0, enable_subsystems=[]): level = int(round(level)) # once logging.something has been called you have to remove all logging # handlers before re-configing... root = logging.getLogger() if root.handlers: for handler in root.handlers: root.removeHandler(handler) # set new handler with our formatter handler = logging.StreamHandler() handler.setFormatter(Formatter()) root.addHandler(handler) # set appropriate levels on subsystem loggers - maybe selective logging # should use filters instead? if enable_subsystems and len(enable_subsystems): for subsys in enable_subsystems: logging.getLogger(subsys).setLevel(level) else: logging.getLogger().setLevel(level) valinor-1.1.4/valinor/main.py0000666000000000000000000001315313463042175014301 0ustar 00000000000000# Copyright 2015 ARM Ltd # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import logging import argparse import os import sys import pkg_resources import shutil import valinor.logging_setup as logging_setup import valinor.ide_detection as ide_detection import valinor.elf as elf from project_generator.project import Project from project_generator.generate import Generator from project_generator.settings import ProjectSettings def main(): logging_setup.init() logging.getLogger().setLevel(logging.INFO) p = argparse.ArgumentParser() p.add_argument('--version', dest='show_version', action='version', version=pkg_resources.require("valinor")[0].version, help='display the version' ) p.add_argument('-t', '--tool', dest='ide_tool', default=None, help='Debug tool (IDE) to generate for. If omitted, a debug project '+ 'will be generated for an IDE detected on your system, '+ 'defaulting to opening a GDB debug session, if no known IDEs '+ 'are detected' ) p.add_argument('-d', '--project-dir', dest='project_dir', default=None, help='The directory in which to generate any necessary project files. '+ 'Defaults to the directory of the executable argument.' ) p.add_argument('-n', '--no-open', dest='start_session', default=True, action='store_false', help='Do not open the debug session, just generate the necessary '+ 'files to enable debugging, and print the command that would be '+ 'necessary to proceed.' ) p.add_argument('--target', dest='target', required=True, help='The target board to generate a project file for (e.g. K64F).' ) p.add_argument('executable', help='Path to the executable to debug.' ) args = p.parse_args() # check that the executable exists before we proceed, so we get a nice # error message if it doesn't if not os.path.isfile(args.executable): logging.error('cannot debug file "%s" that does not exist' % args.executable) sys.exit(1) # Get setttings and generator (it updates targets def prior select) projects = { 'projects' : {} } generator = Generator(projects) project_settings = ProjectSettings() available_ides = ide_detection.available() ide_tool = args.ide_tool if not ide_tool: ide_tool = ide_detection.select(available_ides, args.target, project_settings) if ide_tool is None: if len(available_ides): logging.error('None of the detected IDEs supports "%s"', args.target) else: logging.error('No IDEs were detected on this system!') logging.info('Searched for:\n %s', '\n '.join(ide_detection.IDE_Preference)) if ide_tool is None: logging.error( 'No IDE tool available for target "%s". Please see '+ 'https://github.com/project-generator/project_generator for details '+ 'on adding support.', args.target ) sys.exit(1) file_name = os.path.split(args.executable)[1] file_base_name = os.path.splitext(file_name)[0] executable_dir = os.path.dirname(args.executable) projectfile_dir = args.project_dir or executable_dir files = elf.get_files_from_executable(args.executable) # pass empty data to the tool for things we don't care about when just # debugging (in the future we could add source files by reading the debug # info from the file being debugged) project_data = { 'common': { 'target': [args.target], # target 'build_dir': ['.'], 'linker_file': ['None'], 'export_dir': ['.' + os.path.sep + projectfile_dir], 'output_dir': { 'rel_path' : [''], 'path' : [os.path.relpath(executable_dir, projectfile_dir) + os.path.sep], }, 'sources': {'Source_Files':sorted([f for f in files], key=lambda file: os.path.basename(file))}, } } project = Project(file_base_name, [project_data], project_settings) project.generate(ide_tool) # perform any modifications to the executable itself that are necessary to # debug it (for example, to debug an ELF with Keil uVision, it must be # renamed to have the .axf extension) executable = args.executable if ide_tool in ('uvision', 'uvision5'): new_exe_path = args.executable + '.axf' shutil.copy(args.executable, new_exe_path) executable = new_exe_path projectfiles = project.get_generated_project_files(ide_tool) if not projectfiles: logging.error("failed to generate project files") sys.exit(1) if args.start_session: launch_fn = ide_detection.get_launcher(ide_tool) if launch_fn is not None: try: launch_fn(projectfiles['files'], executable) except Exception as e: logging.error('failed to launch debugger: %s', e) else: logging.warning('failed to open IDE') print('project files have been generated in: %s' % os.path.join(os.getcwd(), os.path.normpath(projectfiles['path']))) valinor-1.1.4/valinor/test/0000777000000000000000000000000013463771202013757 5ustar 00000000000000valinor-1.1.4/valinor/test/__init__.py0000666000000000000000000000016013463042175016065 0ustar 00000000000000# Copyright 2015 ARM Limited # # Licensed under the Apache License, Version 2.0 # See LICENSE file for details. valinor-1.1.4/valinor/test/cli.py0000666000000000000000000000141413463042175015100 0ustar 00000000000000#!/usr/bin/env python # Copyright 2014-2015 ARM Limited # # Licensed under the Apache License, Version 2.0 # See LICENSE file for details. # standard library modules, , , import sys import subprocess import os def run(arguments, cwd='.'): progdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '..', '..') runprog = [ sys.executable, '-c', "import sys; sys.path.insert(0, '%s'); import valinor; valinor.main()" % progdir ] child = subprocess.Popen( args = runprog + arguments, cwd = cwd, stdout = subprocess.PIPE, stderr = subprocess.PIPE, stdin = subprocess.PIPE ) out, err = child.communicate() return out.decode('utf-8'), err.decode('utf-8'), child.returncode valinor-1.1.4/valinor/test/test_exporter.py0000666000000000000000000000145513463042175017245 0ustar 00000000000000# Copyright 2014 Matthew Else # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. from nose.tools import * from project_generator.tools.tool import Builder # Makes sure that exporting using generic builder will fail. @raises(NotImplementedError) def test_exporter_location(): b = Builder() b.build_project() valinor-1.1.4/valinor/test/test_outputdir.py0000666000000000000000000000456013463042175017434 0ustar 00000000000000#!/usr/bin/env python # Copyright 2014-2015 ARM Limited # # Licensed under the Apache License, Version 2.0 # See LICENSE file for details. # standard library modules, , , import unittest import os import tempfile import shutil # internal modules: from . import cli class TestCLIOutputDirectory(unittest.TestCase): def setUp(self): self.workingdir = tempfile.mkdtemp() exedir = os.path.join(self.workingdir, 'some', 'long', 'path') os.makedirs(exedir) self.exe_path = os.path.join(exedir, 'myexe') with open(self.exe_path, 'w') as f: f.write('ELF') def tearDown(self): shutil.rmtree(self.workingdir) def runCheck(self, args): out, err, status = cli.run(args, cwd = self.workingdir) print(out) print(err) self.assertEqual(status, 0) return err or out def testUVision(self): def runWithDir(d=None): args = [ '--tool', 'uvision', '--target', 'K64F', os.path.relpath(self.exe_path, self.workingdir), '-n' ] if d: args += ['-d', d] out = self.runCheck(args) runWithDir() self.assertTrue(os.path.isfile(self.exe_path + '.uvproj')) runWithDir('somesubdir') self.assertTrue(os.path.isfile(os.path.join(self.workingdir, 'somesubdir', 'myexe.uvproj'))) runWithDir(os.path.join('somesubdir','anotherdir') + os.path.sep) self.assertTrue(os.path.isfile(os.path.join(self.workingdir, 'somesubdir', 'anotherdir', 'myexe.uvproj'))) def testARMNoneEABIGDB(self): def runWithDir(d=None): args = [ '--tool', 'arm_none_eabi_gdb', '--target', 'K64F', os.path.relpath(self.exe_path, self.workingdir), '-n' ] if d: args += ['-d', d] out = self.runCheck(args) runWithDir() self.assertTrue(os.path.isfile(self.exe_path + '.gdbstartup')) runWithDir('somesubdir') self.assertTrue(os.path.isfile(os.path.join(self.workingdir, 'somesubdir', 'myexe.gdbstartup'))) runWithDir(os.path.join('somesubdir','anotherdir') + os.path.sep) self.assertTrue(os.path.isfile(os.path.join(self.workingdir, 'somesubdir', 'anotherdir', 'myexe.gdbstartup'))) valinor-1.1.4/valinor.egg-info/0000777000000000000000000000000013463771202014472 5ustar 00000000000000valinor-1.1.4/valinor.egg-info/PKG-INFO0000666000000000000000000000120513463771202015565 0ustar 00000000000000Metadata-Version: 1.1 Name: valinor Version: 1.1.4 Summary: Generate IDE project files to debug ELF files. Home-page: https://github.com/ARMmbed/valinor Author: Martin Kojtal, James Crosby Author-email: c0170@rocketmail.com, James.Crosby@arm.com License: Apache-2.0 Description: valinor ------- Generate IDE project files to debug ELF files. Keywords: debug c cpp project generator embedded Platform: UNKNOWN Classifier: Development Status :: 3 - Alpha Classifier: Topic :: Utilities Classifier: License :: OSI Approved :: Apache Software License Classifier: Environment :: Console valinor-1.1.4/valinor.egg-info/SOURCES.txt0000666000000000000000000000071613463771202016362 0ustar 00000000000000LICENSE MANIFEST.in readme.md setup.py docs/pypi.txt valinor/__init__.py valinor/elf.py valinor/gdb.py valinor/ide_detection.py valinor/logging_setup.py valinor/main.py valinor.egg-info/PKG-INFO valinor.egg-info/SOURCES.txt valinor.egg-info/dependency_links.txt valinor.egg-info/entry_points.txt valinor.egg-info/requires.txt valinor.egg-info/top_level.txt valinor/test/__init__.py valinor/test/cli.py valinor/test/test_exporter.py valinor/test/test_outputdir.pyvalinor-1.1.4/valinor.egg-info/dependency_links.txt0000666000000000000000000000000113463771202020540 0ustar 00000000000000 valinor-1.1.4/valinor.egg-info/entry_points.txt0000666000000000000000000000005213463771202017765 0ustar 00000000000000[console_scripts] valinor = valinor:main valinor-1.1.4/valinor.egg-info/requires.txt0000666000000000000000000000020113463771202017063 0ustar 00000000000000pyyaml<6.0,>=5.1 Jinja2<3,>=2.7.0 setuptools colorama<0.4,>=0.3 pyOCD<1.0,>=0.3 project_generator<0.9.0,>=0.8.0 pyelftools==0.23 valinor-1.1.4/valinor.egg-info/top_level.txt0000666000000000000000000000001013463771202017213 0ustar 00000000000000valinor