Commit 4341a243 authored by Reto Da Forno's avatar Reto Da Forno
Browse files

binary patching moved into separate function, now both symbols...

binary patching moved into separate function, now both symbols (FLOCKLAB_NODE_ID and TOS_NODE_ID) are patched
parent 6e99f08c
#!/usr/bin/perl -w
#
# This program changes the mote ID of a TinyOS image. It is used to
# install a program for a specific mote.
use strict;
my %G_opts = (
compat => 0,
objdump => 'avr-objdump',
objcopy => 'avr-objcopy',
target => 'srec',
readdata => 0,
);
# default to backward compatability mode
while( @ARGV && $ARGV[0] =~ /^-/ ) {
(my $opt = shift @ARGV) =~ s/^-+//;
if( $opt eq "srec" ) { $G_opts{compat} = 1; }
elsif( $opt eq "exe" ) { $G_opts{compat} = 0; }
elsif( $opt eq "read" ) { $G_opts{readdata} = 1; $G_opts{compat} = 0; }
elsif( exists $G_opts{$opt} ) { $G_opts{$opt} = shift @ARGV; }
else { die "Unknown command line option $opt\n"; }
}
# print usage if we have the wrong number of arguments
if( @ARGV < ($G_opts{readdata} ? 1 : 3) ) {
print "usage: tos-set-symbols --srec [--objcopy=...] [--objdump=...]\n";
print " [--target=TARGETFILETYPE]\n";
print " INFILE OUTFILE [SYMBOL=]VALUE...\n";
print " tos-set-symbols --exe [--objcopy=...] [--objdump=...]\n";
print " INFILE OUTFILE [SYMBOL]=VALUE...\n";
print " tos-set-symbols --read [--objdump=...] INFILE SYMBOL...\n";
print "\nNote: If omitted, SYMBOL defaults to TOS_LOCAL_ADDRESS.\n";
print "(for TinyOS 1.x compatibility).\n";
exit 0;
}
# get the args and default variables set up
my $exein = shift @ARGV;
my $exeout = $G_opts{readdata} ? $exein : shift @ARGV;
my %user_symbols = ();
if( $G_opts{readdata} ) {
for my $name (@ARGV) {
$name =~ s/\./\$/g;
$user_symbols{$name} = 1;
}
} else {
for my $value (@ARGV) {
my $name = 'TOS_LOCAL_ADDRESS';
($name,$value) = ($1,$2) if $value =~ /^([^=]+)=(.*)/;
$value = hex $value if $value =~ /^0x/;
$user_symbols{$name} = $value;
}
}
my $segment_vma = undef;
my $segment_lma = undef;
my $segment_off = undef;
# if in compatability mode, derive the names of the exes from the srecs
my $srecin = undef;
my $srecout = undef;
if( $G_opts{compat} ) {
$srecin = $exein;
$srecout = $exeout;
$exein =~ s/$G_opts{target}/exe/;
$exeout =~ s/$G_opts{target}/exe/;
}
# find the data section
open( SECTS, "$G_opts{objdump} -h $exein |" )
or die "Cannot extract section information: $!\n";
while(<SECTS>) {
if( /^\s*\d+\s+\.data\s+\S+\s+(\S+)\s+(\S+)\s+(\S+)/ ) {
$segment_vma = hex $1;
$segment_lma = hex $2;
$segment_off = hex $3;
last;
}
}
close(SECTS);
warn "Could not find data section in $exein, aborting.\n"
unless defined $segment_vma && defined $segment_lma && defined $segment_off;
# build a hash of all data segment symbols to their address and size
my %exe_symbols = ();
open( SYMBOL, "$G_opts{objdump} -t $exein |" )
or die "Cannot extract symbol information: $!\n";
while(<SYMBOL>) {
if( /^(\S+)\s+\S+\s+\S+\s+\.data\s+(\S+)\s+(\S+)\s*$/ ) {
$exe_symbols{$3} = { addr => hex($1), size => hex($2) };
}
}
close(SYMBOL);
# slurp the input exe
open (FILE_IN, "<$exein") or die "Could not open $exein: $!\n";
binmode FILE_IN;
my $exe = join("",<FILE_IN>);
close( FILE_IN );
if( $G_opts{readdata} ) {
my %nums = ( 1 => 'C', 2 => 'v', 4 => 'V' );
%user_symbols = %exe_symbols unless %user_symbols;
my $maxlen = 0;
for (keys %user_symbols) { $maxlen = length if length > $maxlen; }
for my $symbol (sort keys %user_symbols) {
if( defined $exe_symbols{$symbol} ) {
my $addr = $exe_symbols{$symbol}->{addr};
my $size = $exe_symbols{$symbol}->{size};
my $filepos = $segment_off + ($addr - $segment_vma);
my $value = substr( $exe, $filepos, $size );
(my $valbytes = $value) =~ s/(.)/sprintf('%02x ',ord $1)/eg;
$valbytes =~ s/\s+$//;
(my $valstr = $value) =~ s/[^\040-\200]/./g;
(my $symstr = $symbol) =~ s/\$/./g;
my $numstr = "";
if( $nums{length($value)} ) {
$numstr = sprintf( ' (%d)', unpack($nums{length($value)},$value) );
}
print sprintf("%-${maxlen}s : %s %s\n", $symstr, $valbytes, "[$valstr]$numstr" );
} else {
warn "Could not find symbol $symbol in $exein, ignoring symbol.\n";
}
}
} else {
# change the desired symbols at their file offsets
for my $symbol (sort keys %user_symbols) {
my $value = $user_symbols{$symbol};
if( defined $exe_symbols{$symbol} ) {
my $addr = $exe_symbols{$symbol}->{addr};
my $size = $exe_symbols{$symbol}->{size};
my $filepos = $segment_off + ($addr - $segment_vma);
my $bytes = substr( pack("V", $value) . ("\000" x $size), 0, $size );
substr( $exe, $filepos, $size ) = $bytes;
} else {
warn "Could not find symbol $symbol in $exein, ignoring symbol.\n";
}
}
# barf the output exe
open (FILE_OUT, ">$exeout") or die "Could not open $exeout: $!\n";
binmode FILE_OUT;
print FILE_OUT $exe;
close( FILE_OUT );
# if in compatability mode, convert the output exe to the output srec
if( $G_opts{compat} ) {
my $cmd = "$G_opts{objcopy} --output-target=$G_opts{target} $exeout $srecout";
system( $cmd ) == 0 or die "Command \"$cmd\" failed";
}
}
......@@ -275,127 +275,37 @@ def start_test(testid, cur, cn, obsdict_key, obsdict_id):
# Prepare image ---
(fd, imagepath) = tempfile.mkstemp()
binpath = "%s" %(os.path.splitext(imagepath)[0])
binpath = "%s.ihex" % (os.path.splitext(imagepath)[0])
imagefile = os.fdopen(fd, 'w+b')
imagefile.write(binary)
imagefile.close()
removeimage = True
logger.debug("Got target image ID %s for observer ID %s with node ID %s from database and wrote it to temp file %s (hash %s)" % (str(tgimage_key), str(obs_id), str(node_id), imagepath, hashlib.sha1(binary).hexdigest()))
# Convert image to binary format and, depending on operating system and platform architecture, write the node ID (if specified) to the image:
logger.debug("Found %s target architecture on platform %s for observer ID %s (node ID to be used: %s)." % (arch, platname, str(obs_id), str(node_id)))
set_symbols_tool = flocklab.config.get('targetimage', 'setsymbolsscript')
symbol_node_id = None
# binary patching
if (node_id != None):
# for backwards compatiblity: check whether symbol TOS_NODE_ID exists in the binary
p = subprocess.Popen(['objdump', '-t', imagepath], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
(out, err) = p.communicate()
if p.returncode == 0:
if "TOS_NODE_ID" in out:
logger.debug("Found symbol TOS_NODE_ID in binary file '%s'." % (imagepath))
symbol_node_id = "TOS_NODE_ID"
elif "FLOCKLAB_NODE_ID" in out:
logger.debug("Found symbol FLOCKLAB_NODE_ID in binary file '%s'." % (imagepath))
symbol_node_id = "FLOCKLAB_NODE_ID"
else:
logger.warn("Failed to search for TOS_NODE_ID in binary file '%s'." % (imagepath))
symbol_node_id = "TOS_NODE_ID"
# Convert ELF file to ihex and set node ID if necessary
if (arch == 'msp430'):
binutils_path = flocklab.config.get('targetimage', 'binutils_msp430')
binpath = "%s.ihex"%binpath
if symbol_node_id:
cmd = ['%s' % (set_symbols_tool), '--objcopy', '%s/msp430-objcopy' % (binutils_path), '--objdump', '%s/msp430-objdump' % (binutils_path), '--target', 'ihex', imagepath, binpath, '%s=%s' % (symbol_node_id, node_id), 'ActiveMessageAddressC$addr=%s' % (node_id), 'ActiveMessageAddressC__addr=%s' % (node_id)]
try:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
rs = p.wait()
if rs != 0:
logger.error("Error %d returned from %s" % (rs, set_symbols_tool))
logger.error("Tried to execute: %s" % (" ".join(cmd)))
errors.append("Could not set node ID %s for target image %s" %(str(node_id), str(tgimage_key)))
else:
logger.debug("Set symbols and converted file to ihex.")
# Remove the temporary exe file
os.remove("%s.exe"%imagepath)
#logger.debug("Removed intermediate image %s.exe" % (str(imagepath)))
except OSError as err:
msg = "Error in subprocess: tried calling %s. Error was: %s" % (str(cmd), str(err))
logger.error(msg)
errors.append(msg)
removeimage = False
else:
cmd = ['%s/msp430-objcopy' % (binutils_path), '--output-target', 'ihex', imagepath, binpath]
try:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
rs = p.wait()
if rs != 0:
logger.error("Error %d returned from msp430-objcopy" %rs)
logger.error("Tried to execute: %s" % (" ".join(cmd)))
errors.append("Could not convert target image %s to ihex" %str(tgimage_key))
else:
logger.debug("Converted file to ihex.")
except OSError as err:
msg = "Error in subprocess: tried calling %s. Error was: %s" % (str(cmd), str(err))
logger.error(msg)
errors.append(msg)
removeimage = False
elif (arch == 'arm'):
if (platname == 'dpp'):
imgformat = 'ihex'
binpath = "%s.ihex"%binpath
else:
imgformat = 'binary'
binpath = "%s.bin"%binpath
# Set library path for arm-binutils:
arm_binutils_path = flocklab.config.get('targetimage', 'binutils_arm')
arm_env = os.environ
if 'LD_LIBRARY_PATH' not in arm_env:
arm_env['LD_LIBRARY_PATH'] = ''
arm_env['LD_LIBRARY_PATH'] += ':%s/%s' % (arm_binutils_path, "usr/x86_64-linux-gnu/arm-linux-gnu/lib")
if symbol_node_id:
cmd = ['%s' % (set_symbols_tool), '--objcopy', '%s/%s' % (arm_binutils_path, "usr/bin/arm-linux-gnu-objcopy"), '--objdump', '%s/%s' % (arm_binutils_path, "usr/bin/arm-linux-gnu-objdump"), '--target', imgformat, imagepath, binpath, '%s=%s' % (symbol_node_id, node_id), 'ActiveMessageAddressC$addr=%s' % (node_id), 'ActiveMessageAddressC__addr=%s' % (node_id)]
try:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=arm_env)
rs = p.wait()
if rs != 0:
logger.error("Error %d returned from %s" % (rs, set_symbols_tool))
logger.error("Tried to execute: %s" % (" ".join(cmd)))
errors.append("Could not set node ID %s for target image %s" %(str(node_id), str(tgimage_key)))
else:
logger.debug("Set symbols and converted file to bin.")
except OSError as err:
msg = "Error in subprocess: tried calling %s. Error was: %s" % (str(cmd), str(err))
logger.error(msg)
errors.append(msg)
removeimage = False
else:
cmd = ['%s/%s' % (arm_binutils_path, "usr/bin/arm-linux-gnu-objcopy"), '--output-target', imgformat, imagepath, binpath]
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=arm_env)
rs = p.wait()
if rs != 0:
logger.error("Error %d returned from arm-linux-gnu-objcopy" %rs)
logger.error("Tried to execute: %s" % (" ".join(cmd)))
errors.append("Could not convert target image %s to bin" %str(tgimage_key))
else:
logger.debug("Converted file to bin.")
else:
msg = "Unknown architecture %s found. The original target image (ID %s) file will be used without modification." %(arch, str(tgimage_key))
# set node ID
if flocklab.patch_binary("FLOCKLAB_NODE_ID", node_id, imagepath, arch) != flocklab.SUCCESS:
msg = "Failed to patch symbol FLOCKLAB_NODE_ID in binary file %s." % (imagepath)
errors.append(msg)
logger.error(msg)
if flocklab.patch_binary("TOS_NODE_ID", node_id, imagepath, arch) != flocklab.SUCCESS:
msg = "Failed to patch symbol TOS_NODE_ID in binary file %s." % (imagepath)
errors.append(msg)
logger.error(msg)
# convert elf to intel hex
if flocklab.bin_to_hex(imagepath, arch, binpath) != flocklab.SUCCESS:
msg = "Failed to convert image file %s to Intel hex format." % (imagepath)
errors.append(msg)
logger.error(msg)
orig = open(imagepath, "r+b")
binfile = open(binpath, "w+b")
binfile.write(orig.read())
orig.close()
binfile.close()
logger.debug("Copied image to binary file without modification.")
shutil.move(imagepath, binpath)
logger.debug("Copied binary file without modification.")
# Remove the original file which is not used anymore:
if removeimage:
if os.path.exists(imagepath):
os.remove(imagepath)
#logger.debug("Removed image %s" % (str(imagepath)))
else:
logger.warn("Image %s has not been removed." % (str(imagepath)))
# Slot detection ---
# Find out which slot number to use on the observer.
......
......@@ -311,9 +311,9 @@ def batch_send_mail(subject="[FlockLab]", message="", recipients=[], attachments
if not recipients:
# no email provided -> extract all addresses from the database
try:
config = flocklab.get_config()
logger = flocklab.get_logger()
(cn, cur) = flocklab.connect_to_db()
config = get_config()
logger = get_logger()
(cn, cur) = connect_to_db()
cur.execute("""SELECT email FROM `tbl_serv_users` WHERE is_active=1;""")
ret = cur.fetchall()
if not ret:
......@@ -1279,3 +1279,107 @@ def parse_int(s):
logger.warn("Could not parse %s to int." % (str(s)))
return res
### END parse_int()
##############################################################################
#
# binary_has_symbol() checks whether a symbol exists in a binary file (ELF)
#
##############################################################################
def binary_has_symbol(symbol=None, binaryfile=None):
if symbol is None or binaryfile is None or not os.path.isfile(binaryfile):
return FAILED
p = subprocess.Popen(['objdump', '-t', imagepath], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
(out, err) = p.communicate()
if p.returncode == 0:
if symbol in out:
logger.debug("Found symbol %s in binary file '%s'." % (symbol, imagepath))
return True
return False
return FAILED
### END binary_has_symbol()
##############################################################################
#
# patch_binary() set / overwrite symbols in a binary file (ELF), input file = output file
#
##############################################################################
def patch_binary(symbol=None, value=None, binaryfile=None, arch=None):
if symbol is None or value is None or binaryfile is None or not os.path.isfile(binaryfile) or arch is None:
return FAILED
set_symbols_tool = config.get('targetimage', 'setsymbolsscript')
env = os.environ
if arch == 'msp430':
binutils_path = config.get('targetimage', 'binutils_msp430')
binutils_objcopy = "msp430-objcopy"
binutils_objdump = "msp430-objdump"
elif arch == 'arm':
binutils_path = config.get('targetimage', 'binutils_arm')
binutils_objcopy = "usr/bin/arm-linux-gnu-objcopy"
binutils_objdump = "usr/bin/arm-linux-gnu-objdump"
# TODO: check whether this is necessary
if 'LD_LIBRARY_PATH' not in env:
env['LD_LIBRARY_PATH'] = ''
env['LD_LIBRARY_PATH'] += ':%s/%s' % (binutils_path, "usr/x86_64-linux-gnu/arm-linux-gnu/lib")
cmd = ['%s' % (set_symbols_tool), '--objcopy', '%s/%s' % (binutils_path, binutils_objcopy), '--objdump', '%s/%s' % (binutils_path, binutils_objdump), '--target', 'elf', binaryfile, binaryfile, '%s=%s' % (symbol, value), 'ActiveMessageAddressC$addr=%s' % (value), 'ActiveMessageAddressC__addr=%s' % (value)]
try:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
rs = p.wait()
if rs != 0:
logger.error("Error %d returned from %s. Command was: %s" % (rs, set_symbols_tool, " ".join(cmd)))
return FAILED
except OSError as err:
msg = "Error in subprocess: tried calling %s. Error was: %s" % (str(cmd), str(err))
logger.error(msg)
return FAILED
return SUCCESS
### END patch_binary()
##############################################################################
#
# bin_to_hex() converts a binary (ELF) file to Intel hex format
#
##############################################################################
def bin_to_hex(binaryfile=None, arch=None, outputfile=None):
if arch is None or binaryfile is None or outputfile is None:
return FAILED
env = os.environ
if arch == 'msp430':
binutils_path = config.get('targetimage', 'binutils_msp430')
binutils_objcopy = "msp430-objcopy"
binutils_objdump = "msp430-objdump"
elif arch == 'arm':
binutils_path = config.get('targetimage', 'binutils_arm')
binutils_objcopy = "usr/bin/arm-linux-gnu-objcopy"
binutils_objdump = "usr/bin/arm-linux-gnu-objdump"
# TODO: check whether this is necessary
if 'LD_LIBRARY_PATH' not in env:
env['LD_LIBRARY_PATH'] = ''
env['LD_LIBRARY_PATH'] += ':%s/%s' % (binutils_path, "usr/x86_64-linux-gnu/arm-linux-gnu/lib")
cmd = ['%s/%s' % (binutils_path, binutils_objcopy), '--output-target', 'ihex', binaryfile, outputfile]
try:
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, env=env)
rs = p.wait()
if rs != 0:
logger.error("Command %s returned with error code %d." % (" ".join(cmd), rs))
return FAILED
else:
logger.debug("Converted file %s to ihex." % (binaryfile))
except OSError as err:
msg = "Error in subprocess: tried calling %s. Error was: %s" % (str(cmd), str(err))
logger.error(msg)
return FAILED
return SUCCESS
### END bin_to_hex()
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment