hostShell Migration¶
Introduction¶
From VxWorks 7, the hostShell
tool has been replaced with wrdbg
. The
existing languages supported by the hostShell
were :
- C
- gdb
- tcl
With wrdbg
, supported languages are :
- gdb
- python
Migrating from hostShell
to wrdbg
should then be a matter of:
- converting C shell code to gdb commands or python
- converting tcl code to python
This should allow to have both the gdb commands and python scripting language.
Migrating hostShell
scripts to wrdbg
script is a matter of transforming
the C and tcl calls into python.
Using Python¶
WorkBench 4 comes with python
shell with the additional greenlet
module
(allowing cache consistency mechanisms) where part of the GDB Python APIs have
been implemented.
To migrate from hostShell
scripts, the gdb.execute()
and gdb.STDOUT
are
the only interfaces needed. Both GDB commands and python knowledge are required.
gdb.execute¶
gdb.
execute
(command, from_tty=False, to_string=False, interpreter=False)[source]¶Execute a GDB command.
Evaluate command, a
basestring
, as a GDB CLI command.Parameter from_tty specifies whether GDB ought to consider this command as having originated from the user invoking it interactively. It must be a
bool
value. If omitted, it defaults to False.By default, any output produced by command is sent to GDB’s standard output. If the to_string parameter is True, then output will be collected by
gdb.execute()
and returned as abasestring
. The default is False, in which case the return value is None.See also
Using GDB¶
WorkBench 4 comes with wrdbg
shell, which is a shell emulating the GDB
commands to connect and debug a VxWorks 7 target.
Using the wrdbg
Commands it is possible to debug a VxWorks 7 target, but
data processing of this data is not very easy, we recommand to use the python
way to read/parse data from the target.
Migration¶
For the migration chapter, only the python way is considered.
Target connection¶
With the
hostShell
, the way to connect to a target was:
- boot the target
- start a target server
- start the
hostShell
connected to the target serverUsing
wrdbg
, it should be:
- boot the target
- start
python
and connect using the target connect – Connect to a target machine command.import gdb connection = gdb.execute('target connect vxworks7:127.0.0.1:44552 '\ '-kernel ~/tmp/vxWorks -logdir ~/tmp', False, True)
Module load¶
The module load – Load a module from FILE gdb command replaces:
- tcl’s
wtxObjModuleLoad
- C’s
ld
When loading a module, a memory space must be attached. For VxWorks 7, memory spaces at Real Time Processes (the Kernel is a Real Time Process).
Once connected to a target, loading a module can be done like:
... # Load module in the Kernel memory space. Attach to Kernel first. # Assuming 'module' is the host path to the module we want to load. gdb.execute('attach Kernel') gdb.execute('module load ' + module) ... # Unload the module we loaded earlier gdb.execute('module unload ' + module) ... # Detach from kernel gdb.execute('detach') ...
Load options¶
The module load – Load a module from FILE command uses options set through the set module load – Set module load options command.
To know the possible options, you have to be attached to the memory space you want to load the module in and issue the
help set module load
command.Current options value may be retrieved using show module load – Show the specified module load option command.
Note
The list of options and values may depend on the OS version and the memory space attached.
The result of the show module load – Show the specified module load option command when attached to the Kernel can look like:
LD_SYMBOLS is all LD_COMMONS is match_all LD_CPP is auto LD_MISC is ignore_if_identical LD_INIT is auto LD_WEAK is none
Load errors¶
Module loading may fail, or succeed but return an error message. On failure, the
gdb.execute()
command raises anException
.When module load succeeded but errors have been detected in the module, the message returned by module load – Load a module from FILE describes the error.
Undefined symbols¶
A simple processing of the load command output and the use of
info modules
command should help getting the list of undefined symbols for a given module.# Attach to the kernel gdb.execute('attach Kernel') # Check that module does not have undefined symbols. loadResult = gdb.execute('module load ' + module, False, True) if 'Error text: S_loadLib_UNDEFINED_REFERENCES' in loadResult: undefs = gdb.execute('info modules ' + module + ' -print undef', False, True) with open(errfile, 'w') as f: f.write(undefs) gdb.execute('module unload ' + module) # Detach from Kernel gdb.execute('detach') # Disconnect from the target gdb.execute('target disconnect') quit()
Module unload¶
The module unload – Unload a module FILE gdb command replaces:
- tcl’s
wtxObjModuleUnload
- C’s
unld
Unloading a module may be done by: - module path – all modules with given path are unloaded - module ID – only the module with given ID is unloaded
The list of modules loaded so far is retrieved calling for the
info modules
command.... # Load module in the Kernel memory space. Attach to Kernel first. # Assuming 'module' is the host path to the module we want to load. gdb.execute('attach Kernel') gdb.execute('module load ' + module) ...The list of modules could then look like:
info modules vxMod.0.6.P2 : vxWorks vxMod.10929208.1.P2 : C:\tmp\phil.oThe module loaded above (
phil.o
) could then be removed like:# Unload the module we loaded earlier gdb.execute('module unload ' + module) ... # Detach from kernel gdb.execute('detach') ...or:
# Unload the module we loaded earlier gdb.execute('module unload vxMod.10929208.1.P2) ... # Detach from kernel gdb.execute('detach') ...
Unload options¶
The module unload – Unload a module FILE command uses options set through the set module unload – Set module unload options command.
To know the possible options, you have to be attached to the memory space you want to unload the module from and issue the
help set module unload
command.Current options value may be retrieved using show module unload – Show the specified module unload option command.
Note
The list of options and values may depend on the OS version and the memory space attached.
The result of the show module unload – Show the specified module unload option command when attached to the Kernel can look like:
UNLD_CPLUS_XTOR is auto UNLD_TERM is auto UNLD_STRATEGY is 0
Task creation¶
Using the
hostShell
, spawning a task was done through the Csp()
command. Withwrdbg
, the appropriate command is thread create – Create a thread.If the task to be started needs a module load, please see the Module load section.
Once the module is loaded in the appropriate memory space, it is possible to start the task using the thread create – Create a thread command. As we want to be as close to GDB pardigm, we used the
thread
fortask
. It is possible to modify that by using thealias
command though :gdb.execute('alias task=thread') gdb.execute('help task create')When starting task, the entrypoint (the symbol to spwan task at, e.g.
main
) must be provided. If the entrypoint has parameters, they may be passed to the thread create – Create a thread command.A task is created stopped at entrypoint, it won’t start until the continue command is used.
To keep track of the created task, it is recommended to get the command output, using the to_string argument of the
gdb.execute()
function set to True.... gdb.execute('alias task=thread') task = gdb.execute('task create ' + entrypoint + ' 1 2 0', False, True) taskID = task.split('id = ')[1].split(',')[0] taskName = task.split('name = ')[1].split(',')[0]It is also possible to define a function which does that all, and call it for any task spawned:
def taskSpawn(entrypoint, *args): # Create task arguments list arguments = '' for arg in args: arguments += ' ' + str(arg) # Spawn the task, and get its ID and name. task = gdb.execute('thread create ' + entrypoint + arguments, False, True) taskID = task.split('id = ')[1].split(',')[0] taskName = task.split('name = ')[1].split(',')[0] # Wait for the task to be spawned and stopped before issuing any further # command waitfor = (entrypoint + ' (', ' at ') matchesall = False timeout = 30 waits = 0 # The task is stopped when the "<entrypoint> (.*) at " appears in the # thread info of our task (meaning it is stopped at <entrypoint> while not matchesall: matchesall = True cmdix = gdb.STDOUT.tell() gdb.execute('info thread') output = gdb.STDOUT.getvalue()[cmdix:] for match in waitfor: if not match in output: matchesall = False if not matchesall: time.sleep(1) waits += 1 # Do not wait forever ... if waits > timeout: raise Exception('Thread never created') # XXX: fle : to emulate the sp() behavior, we should add the following line # here: # # gdb.execute('continue &') # # This would require changes in the code handling this task though. return (taskID.strip(), taskName.strip())
Task options¶
The task entrypoint and arguments are the only parameters accepted by the thread create – Create a thread command, but it is also possible to set some task options using the set thread create – Set thread arguments command.
Current options value may be retrieved using show thread create – Show a thread option command.
Note
The list of options and values may depend on the OS version and the memory space attached.
The result of the show thread create – Show a thread option command when attached to the Kernel can look like:
AttachChildren is true StackSize is 20480 ThreadOptions is VX_COPROCS_ALL_TASK
Task debug¶
A task can be debugged only it has been attached or created (see Task creation).
To attach to a task, use the thread attach – Attach to a thread command.
The list of attachable tasks is given by the
ps
command:ps P2 Kernel P2.282207560 ipcom_syslogd P2.278455768 tNetConf P2.278604944 ipcom_tickd P2.278487248 t8Once created or attached, breakpoints can be added (see Set a breakpoint). Once the breakpoint has been added, it is possible to run the task up until it hits the breakpoint like:
def bpAdd(symbol): bp = gdb.execute('break ' + symbol, False, True) # Extract the breakpoint id from returned breakpoint string, it # should be the second word of the result. bpID = bp.split(' ')[1] return bpID def taskSpawn(entrypoint, *args): # Create task arguments list arguments = '' for arg in args: arguments += ' ' + str(arg) # Spawn the task, and get its ID and name. task = gdb.execute('thread create ' + entrypoint + arguments, False, True) taskID = task.split('id = ')[1].split(',')[0] taskName = task.split('name = ')[1].split(',')[0] # Wait for the task to be spawned and stopped before issuing any further # command waitfor = (entrypoint + ' (', ' at ') matchesall = False timeout = 30 waits = 0 # The task is stopped when the "<entrypoint> (.*) at " appears in the # thread info of our task (meaning it is stopped at <entrypoint> while not matchesall: matchesall = True cmdix = gdb.STDOUT.tell() gdb.execute('info thread') output = gdb.STDOUT.getvalue()[cmdix:] for match in waitfor: if not match in output: matchesall = False if not matchesall: time.sleep(1) waits += 1 # Do not wait forever ... if waits > timeout: raise Exception('Thread never created') # XXX: fle : to emulate the sp() behavior, we should add the following line # here: # # gdb.execute('continue &') # # This would require changes in the code handling this task though. return (taskID.strip(), taskName.strip()) ... bpID = bpAdd(symbol) taskID, taskName = taskSpawn(entrypoint, 1, 2, 0) # Run this task up until we hit our breakpoint while True: hit = gdb.execute('continue', False, True) if 'Breakpoint ' + bpID in hit: break
Task IOs¶
Unfortunately, there is no way for now to track the task Inputs/Outputs. Still, as the target agent has the Host FileSystem service, writing a file in the mounted device would make it possible to read it on the host once the task is done.
Unix host¶
The
info hostfs
command show the hostf mounted devices:info hostfs Host Path : Target Path ----------------------- / : /wrdbg/root/With the example above, if a task on the target writes its IOs to
/wrdbg/root/home/myhome/logs/taskios.txt
, the file is also readable on the host at/home/myhome/logs/taskios.txt
Windows host¶
On a Windows host, the output of
info hostfs
could look like:info hostfs Host Path : Target Path ----------------------- C:\ : /wrdbg/root/C/ D:\ : /wrdbg/root/D/ E:\ : /wrdbg/root/E/ G:\ : /wrdbg/root/G/ H:\ : /wrdbg/root/H/ I:\ : /wrdbg/root/I/ J:\ : /wrdbg/root/J/Using the following code sample:
# Hostf use example hostfsmaps = gdb.execute('info hostfs', False, True) # Remove the first two lines of the "info hostfs" command to use the output for hostfsmap in hostfsmaps.split('\n')[2:]: try: hostpath, targetpath = hostfsmap.split(' : ', 1) # Only use the host paths on C: and D: or / if hostpath.lower().startswith('c:') or \ hostpath.lower().startswith('d:') or \ hostpath == '/': print targetpath + ' -> ' + hostpath except: # Ignore when map does not say "hostpath : targetpath" passWould give an output like:
/wrdbg/root/C/ -> C:\ /wrdbg/root/D/ -> D:\It is then possible to use the
info hostfs
command to give an argument to a task, and exploit the target file on the host. Something like a task which would do:void openFile ( char * path /* Target path to write to */ ) { FILE * tgtstream = open (path, "w"); fprintf (tgtstream, "From target task !\n"); fclose (tgtstream); }Getting the file content from the host could look like:
def taskSpawn(entrypoint, *args): # Create task arguments list arguments = '' for arg in args: arguments += ' ' + str(arg) # Spawn the task, and get its ID and name. task = gdb.execute('thread create ' + entrypoint + arguments, False, True) taskID = task.split('id = ')[1].split(',')[0] taskName = task.split('name = ')[1].split(',')[0] # Wait for the task to be spawned and stopped before issuing any further # command waitfor = (entrypoint + ' (', ' at ') matchesall = False timeout = 30 waits = 0 # The task is stopped when the "<entrypoint> (.*) at " appears in the # thread info of our task (meaning it is stopped at <entrypoint> while not matchesall: matchesall = True cmdix = gdb.STDOUT.tell() gdb.execute('info thread') output = gdb.STDOUT.getvalue()[cmdix:] for match in waitfor: if not match in output: matchesall = False if not matchesall: time.sleep(1) waits += 1 # Do not wait forever ... if waits > timeout: gdb.execute('target disconnect') vxsimStop() raise Exception('Thread never created') # XXX: fle : to emulate the sp() behavior, we should add the following line # here: # # gdb.execute('continue &') # # This would require changes in the code handling this task though. return (taskID.strip(), taskName.strip()) def taskWait(taskID, taskName): """Wait for a task to exit.""" cmdix = gdb.STDOUT.tell() taskexited = '[Thread ' + taskID + ' exited]' while True: # First, check that the task is stopped. If it is, send a "continue" taskstates = gdb.execute('info threads', False, True) for state in taskstates.split('\n'): if taskID in state and taskName in state and ' at ' in state: gdb.execute('continue') # Check if the output contains [Thread <taskID> exited]. If not, wait # for a second. cmdoutput = gdb.STDOUT.getvalue()[cmdix:] if taskexited in cmdoutput: return time.sleep(1) ... tgtfile = '/wrdbg/root/C/tmp/out.txt' taskID, taskName = taskSpawn('openFile', tgtfile) gdb.execute('continue', False, True) print 'Waiting for ' + taskName + ' to end ...' taskWait(taskID, taskName) # Now read the file on host hostpath = 'C:\tmp\out.txt' with open(hostpath, 'r') as f: print f.read() ...
Task deletion¶
The use of
hostShell
’std
has been replace by the thread kill – Kill a thread gdb command.In confirm mode, the command asks for confirmation when trying to kill a running task. In that case, it is safer to define a python function to handle that gracefully:
def taskKill(taskID): # Kill the task. If the task was running or pending, the string # 'Kill the thread being debugged?' appears in the result. If the # string '[answered y; input not from terminal]' does not also # appear in the result, the 'y' command (for 'yes') is awaited. cmdix = gdb.STDOUT.tell() gdb.execute('thread kill ' + taskID) cmdoutput = gdb.STDOUT.getvalue()[cmdix:] if 'Kill the thread being debugged?' in cmdoutput and \ '[answered y; input not from terminal]' not in cmdoutput: gdb.execute('y')
Breakpoints¶
While using C’sb
andbd
with thehostShell
, breakpoints are handled using break and delete breakpoints – Delete some breakpoints or auto-display expressions GDB commands.
Set a breakpoint¶
Using break allows to set a breakpoint at a given location. The command returns a string like
Breakpoint 1 at 0x1092d858: file ../../src/kernel/phil.c, line 487.
from which the breakpoint ID may be extracted like:symbol = 'main' bpDesc = gdb.execute('break ' + symbol, False, True) bpID = bpDesc.split(' ')[1]A python function may be written to do that:
def bpAdd(symbol): bp = gdb.execute('break ' + symbol, False, True) # Extract the breakpoint id from returned breakpoint string, it should be # the second word of the result. bpID = bp.split(' ')[1] return bpIDNote
Using
tbreak
instead of break creates a temporary breakpoint removed as soon as it is hit.
Remove a breakpoint¶
A breakpoint created by the break command may be removed by the delete breakpoints – Delete some breakpoints or auto-display expressions command.
def bpAdd(symbol): bp = gdb.execute('break ' + symbol, False, True) # Extract the breakpoint id from returned breakpoint string, it # should be the second word of the result. bpID = bp.split(' ')[1] return bpID ... symbol = 'main' bpID = bpAdd(symbol) ... gdb.execute('delete breakpoints ' bpID)
Remove all breakpoints¶
Removing all the breakpoints is done by using the delete breakpoints – Delete some breakpoints or auto-display expressions command with no breakpoint ID.
def bpAdd(symbol): bp = gdb.execute('break ' + symbol, False, True) # Extract the breakpoint id from returned breakpoint string, it # should be the second word of the result. bpID = bp.split(' ')[1] return bpID ... symbol = 'main' symbol2 = 'main2' bpID1 = bpAdd(symbol) bpID1 = bpAdd(symbol2) ... gdb.execute('delete breakpoints')In confirm mode, the command asks for confirmation when trying to delete all breakpoints. In that case, it is safer to define a python function to handle that gracefully:
def bpRemove(bpIDs=[]): # If bpIDs is a basetring, assume it is only one breakpoint ID, else, # create a string of all breakpoint IDs. if bpIDs and isinstance(bpIDs, basestring): ids = bpIDs elif bpIDs: ids = ' '.join(bpIDs) else: ids = '' cmdix = gdb.STDOUT.tell() gdb.execute('delete breakpoints ' + ids) cmdoutput = gdb.STDOUT.getvalue()[cmdix:] if 'Delete all breakpoints?' in cmdoutput and \ '[answered y; input not from terminal]' not in cmdoutput: gdb.execute('y')
Path mapping¶
When objects have been compiled on a given path, but that path is not available from the host debugging the object, path mapping should be used.
For example, if
mytest.c
has been compiled in/tmp/test
, but is debugged on a Windows host wheremytest.c
resides inC:\test
, a path mapping must be created to access the source file.gdb.execute('pathmap add /tmp/text C:\\test')Note
The
pathmap add
command may be called only after the target connect – Connect to a target machine.
Logging¶
The target server connection allowed to turn on WTX or WDB loggers. Using
wrdbg
the equivalent is the TCF agent logger. To collect the target->tools communication, two possible ways:
- use the
-logverbosity
option of the target connect – Connect to a target machine command. In that case, all TCF logs are written in the directory specified by the-logdir
option. Forvxworks7
platform, setting the log verbosity to 2 enables maximum logging.- use the various
set agentlog
commands.import gdb import windriver.utils.utils as wrutils agentlog = wrutils.fullpath(('~', 'tmp', 'agent-log.txt')) gdb.execute('set agentlog file ' + agentlog)When done, you may turn on or off the debug log with:
... gdb.execute('set agentlog save on') ... gdb.execute('set agentlog save off') ...
Migration overview¶
Code example¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 | # task.py - WindRiver gdb interface example for vxworks7 connection.
# Copyright (c) 2014-2015 Wind River Systems, Inc.
#
# The right to copy, distribute, modify, or otherwise make use
# of this software may be licensed only pursuant to the terms
# of an applicable Wind River license agreement.
import argparse
import gdb
import os
import random
import subprocess
import sys
import time
import windriver.utils.utils as wrutils
_vxsimStarted = False
def bpAdd(symbol):
bp = gdb.execute('break ' + symbol, False, True)
# Extract the breakpoint id from returned breakpoint string, it should be
# the second word of the result.
bpID = bp.split(' ')[1]
return bpID
def bpRemove(bpIDs=[]):
# If bpIDs is a basetring, assume it is only one breakpoint ID, else,
# create a string of all breakpoint IDs.
if bpIDs and isinstance(bpIDs, str):
ids = bpIDs
elif bpIDs:
ids = ' '.join(bpIDs)
else:
ids = ''
cmdix = gdb.STDOUT.tell() # @UndefinedVariable
gdb.execute('delete breakpoints ' + ids)
cmdoutput = gdb.STDOUT.getvalue()[cmdix:] # @UndefinedVariable
if 'Delete all breakpoints?' in cmdoutput and \
'[answered y; input not from terminal]' not in cmdoutput:
gdb.execute('y')
def taskSpawn(entrypoint, *args):
# Create task arguments list
arguments = ''
for arg in args:
arguments += ' ' + str(arg)
# Spawn the task, and get its ID and name.
task = gdb.execute('thread create ' + entrypoint + arguments, False, True)
taskID = task.split('id = ')[1].split(',')[0]
taskName = task.split('name = ')[1].split(',')[0]
# Wait for the task to be spawned and stopped before issuing any further
# command
waitfor = (entrypoint + ' (', ' at ')
matchesall = False
timeout = 30
waits = 0
# The task is stopped when the "<entrypoint> (.*) at " appears in the
# thread info of our task (meaning it is stopped at <entrypoint>
while not matchesall:
matchesall = True
cmdix = gdb.STDOUT.tell() # @UndefinedVariable
gdb.execute('info threads')
output = gdb.STDOUT.getvalue()[cmdix:] # @UndefinedVariable
for match in waitfor:
if match not in output:
matchesall = False
if not matchesall:
time.sleep(1)
waits += 1
# Do not wait forever ...
if waits > timeout:
gdb.execute('target disconnect')
vxsimStop()
raise Exception('Thread never created')
# XXX: fle : to emulate the sp() behavior, we should add the following line
# here:
#
# gdb.execute('continue &')
#
# This would require changes in the code handling this task though.
return (taskID.strip(), taskName.strip())
def taskWait(taskID, taskName):
"""Wait for a task to exit."""
cmdix = gdb.STDOUT.tell() # @UndefinedVariable
taskexited = '[Thread ' + taskID + ' exited]'
while True:
# First, check that the task is stopped. If it is, send a "continue"
taskstates = gdb.execute('info threads', False, True)
for state in taskstates.split('\n'):
if taskID in state and taskName in state and ' at ' in state:
gdb.execute('continue')
# Check if the output contains [Thread <taskID> exited]. If not, wait
# for a second.
cmdoutput = gdb.STDOUT.getvalue()[cmdix:] # @UndefinedVariable
if taskexited in cmdoutput:
return
time.sleep(1)
def taskKill(taskID):
# Kill the task. If the task was running or pending, the string
# 'Kill the thread being debugged?' appears in the result. If the string
# '[answered y; input not from terminal]' does not also appear in the
# result, the 'y' command (for 'yes') is awaited.
cmdix = gdb.STDOUT.tell() # @UndefinedVariable
gdb.execute('thread kill ' + taskID)
cmdoutput = gdb.STDOUT.getvalue()[cmdix:] # @UndefinedVariable
if 'Kill the thread being debugged?' in cmdoutput and \
'[answered y; input not from terminal]' not in cmdoutput:
gdb.execute('y')
def vxsimStart(kernel, logdir):
"""Start vxsim 0 with given kernel."""
global _vxsimStarted
tcfport = 5000 + int(random.random() * 60000)
url = 'vxworks7:127.0.0.1:' + str(tcfport)
logfile = wrutils.fullpath((logdir, 'vxsim-log.txt'))
# Build vxsim command line
cmd = ['vxsim', '-p', '0', '-d', 'simnet_nat', '-add_nat_redir',
'tcp:1534:' + str(tcfport), '-f', kernel, '-lc', '-l', logfile]
subprocess.Popen(cmd)
# Wait a bit for the simulator to be started
time.sleep(5)
_vxsimStarted = True
return url
def vxsimStop():
"""Stop the vxsim 0."""
# Build vxsim kill command line. Assume vxsim processor is 0.
global _vxsimStarted
if _vxsimStarted:
cmd = ['vxsim', '-kill', '0']
subprocess.Popen(cmd)
# ------------------------- user defined variables -------------------------- #
bpsymbol = 'level4'
errfile = 'vxworks_undef_sym.txt'
module = 'bklevel.o'
taskentry = 'bklevel'
# Source path mappings (if needed)
# pmapsrc = <path to source at compile time>
pmapsrc = None
# pmapdest = <path to source at run time>
pmapdest = None
# ----------------------------- Parse arguments ----------------------------- #
parser = argparse.ArgumentParser(description='Task sample',)
parser.add_argument('-kernel', required=True, help='Target kernel path.')
parser.add_argument('-logdir', default='~/tmp/samples', help='Log directory.')
parser.add_argument('-objdir', required=True, help='Objects directory.')
parser.add_argument('agentid', nargs=argparse.REMAINDER,
help='Target agent URL (ID). If argument is not '
'provided, a vxsim is started using KERNEL')
# Print help message if user forgot to give arguments
if len(sys.argv) == 1:
parser.parse_args(['-h'])
parsed = parser.parse_args(sys.argv[1:])
kernel = wrutils.fullpath(parsed.kernel)
logdir = wrutils.fullpath(parsed.logdir)
objdir = wrutils.fullpath(parsed.objdir)
agentlog = wrutils.fullpath((logdir, 'agent-log.txt'))
if not parsed.agentid:
url = vxsimStart(kernel, logdir)
else:
url = parsed.agentid[0]
# --------------------------------------------------------------------------- #
if not os.path.exists(logdir):
os.makedirs(logdir)
os.chdir(objdir)
try:
# Connect to the target
gdb.execute('set agentlog file ' + agentlog)
gdb.execute('target connect ' + url + ' -kernel ' + kernel + ' -logdir ' +
logdir)
# gdb.execute('set agentlog save on')
if pmapsrc and pmapdest:
gdb.execute('pathmap add ' + pmapsrc + ' ' + pmapdest)
gdb.execute('info pathmap')
# Attach to the kernel
gdb.execute('attach Kernel')
# Check that module does not have undefined symbols.
loadResult = gdb.execute('module load ' + module, False, True)
if 'Error text: S_loadLib_UNDEFINED_REFERENCES' in loadResult:
undefs = gdb.execute('info modules ' + module + ' -print undef', False,
True)
with open(errfile, 'w') as f:
f.write(undefs)
gdb.execute('module unload ' + module)
# Detach from Kernel
gdb.execute('detach')
# Disconnect from the target
gdb.execute('target disconnect')
quit()
gdb.execute('module load ' + module)
bpID = bpAdd(bpsymbol)
taskID, taskName = taskSpawn(taskentry)
# Run this task up until we hit our breakpoint
while True:
hit = gdb.execute('continue', False, True)
if 'Breakpoint ' + bpID in hit:
break
# Remove the breakpoint
bpRemove(bpID)
taskKill(taskID)
gdb.execute('module unload ' + module)
# Detach from Kernel
gdb.execute('detach')
# Disconnect from the target
gdb.execute('target disconnect')
except Exception as e:
sys.stderr.write('*** ERROR ***\n' + str(e) + '\n')
# Stop the target if needed
vxsimStop()
# Save outputs to log file.
consolelog = wrutils.fullpath((logdir, 'gdb-console.txt'))
with open(consolelog, 'w') as f:
f.write(gdb.STDOUT.getvalue()) # @UndefinedVariable
print('Logs saved in ' + consolelog)
quit()
|