There are demons hiding in binutils with regard to the size of the data section that needs to be copied in XIP platforms. It's easy to mess up and get a mismatch between the linker data output and the runtime addresses. Add a cheap check to discover this early when it occurs. Jira: ZEP-955 Change-Id: If1c61fe8712221c6450b5b89f5f8af006b41b3fe Signed-off-by: Andy Ross <andrew.j.ross@intel.com>
64 lines
1.8 KiB
Perl
Executable File
64 lines
1.8 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
use warnings;
|
|
use strict;
|
|
|
|
# Linker address generation validity checker. By default, GNU ld is
|
|
# broken when faced with sections where the load address (i.e. the
|
|
# spot in the XIP program binary where initialized data lives) differs
|
|
# from the virtual address (i.e. the location in RAM where that data
|
|
# will live at runtime. We need to be sure we're using the
|
|
# ALIGN_WITH_INPUT feature correctly everywhere, which is hard --
|
|
# especially so given that many of these bugs are semi-invisible at
|
|
# runtime (most initialized data is still a bunch of zeros and often
|
|
# "works" even if it's wrong).
|
|
#
|
|
# This quick test just checks the offsets between sequential segments
|
|
# with separate VMA/LMA addresses and verifies that the size deltas
|
|
# are identical.
|
|
#
|
|
# Note that this is assuming that the address generation is always
|
|
# in-order and that there is only one "ROM" LMA block. It's possible
|
|
# to write a valid linker script that will fail this script, but we
|
|
# don't have such a use case and one isn't forseen.
|
|
|
|
# Skip the header stuff
|
|
while(<>) { last if /Linker script and memory map/; }
|
|
|
|
|
|
my ($last_sec, $last_vma, $last_lma);
|
|
while(<>) {
|
|
next if ! /^([a-zA-Z0-9_\.]+) \s+ # name
|
|
(0x[0-9a-f]+) \s+ # addr
|
|
(0x[0-9a-f]+) \s+ # size
|
|
/x;
|
|
|
|
my ($sec, $vma, $sz) = ($1, $2, $3);
|
|
|
|
my $lma = "";
|
|
if(/load address (0x[0-9a-f]+)/) {
|
|
$lma = $1;
|
|
} else {
|
|
$last_sec = undef;
|
|
next;
|
|
}
|
|
|
|
$vma = eval $vma;
|
|
$lma = eval $lma;
|
|
|
|
if(defined $last_sec) {
|
|
my $dv = $vma - $last_vma;
|
|
my $dl = $lma - $last_lma;
|
|
if($dv != $dl) {
|
|
print STDERR
|
|
"ERROR: section $last_sec is $dv bytes "
|
|
. "in the virtual/runtime address space, "
|
|
. "but only $dl in the loaded/XIP section!\n";
|
|
exit 1;
|
|
}
|
|
}
|
|
|
|
$last_sec = $sec;
|
|
$last_vma = $vma;
|
|
$last_lma = $lma;
|
|
}
|