This file is indexed.

/usr/bin/tos-set-symbols is in tinyos-tools 1.4.2-3.

This file is owned by root:root, with mode 0o755.

The actual contents of the file can be viewed below.

  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
#!/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 => 1,
  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";
  }

}