Revert "ANDROID: init: ensure initcall ordering with LTO"
This reverts commit 6c5ad8b10e
as the LTO
feature causes merge issues with 5.8-rc1. So remove it for now and
allow the developer to add the latest version of the patches later on.
Cc: Sami Tolvanen <samitolvanen@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Change-Id: I0b67a8a0d4b54c5be30f0bfc5abdd1422b7ab2f1
This commit is contained in:
@@ -1,250 +0,0 @@
|
||||
#!/usr/bin/env perl
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
#
|
||||
# Generates a linker script that specifies the correct initcall order.
|
||||
#
|
||||
# Copyright (C) 2019 Google LLC
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
use IO::Handle;
|
||||
|
||||
my $nm = $ENV{'LLVM_NM'} || "llvm-nm";
|
||||
my $ar = $ENV{'AR'} || "llvm-ar";
|
||||
my $objtree = $ENV{'objtree'} || ".";
|
||||
|
||||
## list of all object files to process, in link order
|
||||
my @objects;
|
||||
## currently active child processes
|
||||
my $jobs = {}; # child process pid -> file handle
|
||||
## results from child processes
|
||||
my $results = {}; # object index -> { level, function }
|
||||
|
||||
## reads _NPROCESSORS_ONLN to determine the number of processes to start
|
||||
sub get_online_processors {
|
||||
open(my $fh, "getconf _NPROCESSORS_ONLN 2>/dev/null |")
|
||||
or die "$0: failed to execute getconf: $!";
|
||||
my $procs = <$fh>;
|
||||
close($fh);
|
||||
|
||||
if (!($procs =~ /^\d+$/)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return int($procs);
|
||||
}
|
||||
|
||||
## finds initcalls defined in an object file, parses level and function name,
|
||||
## and prints it out to the parent process
|
||||
sub find_initcalls {
|
||||
my ($object) = @_;
|
||||
|
||||
die "$0: object file $object doesn't exist?" if (! -f $object);
|
||||
|
||||
open(my $fh, "\"$nm\" -just-symbol-name -defined-only \"$object\" 2>/dev/null |")
|
||||
or die "$0: failed to execute \"$nm\": $!";
|
||||
|
||||
my $initcalls = {};
|
||||
|
||||
while (<$fh>) {
|
||||
chomp;
|
||||
|
||||
my ($counter, $line, $symbol) = $_ =~ /^__initcall_(\d+)_(\d+)_(.*)$/;
|
||||
|
||||
if (!defined($counter) || !defined($line) || !defined($symbol)) {
|
||||
next;
|
||||
}
|
||||
|
||||
my ($function, $level) = $symbol =~
|
||||
/^(.*)((early|rootfs|con|security|[0-9])s?)$/;
|
||||
|
||||
die "$0: duplicate initcall counter value in object $object: $_"
|
||||
if exists($initcalls->{$counter});
|
||||
|
||||
$initcalls->{$counter} = {
|
||||
'level' => $level,
|
||||
'line' => $line,
|
||||
'function' => $function
|
||||
};
|
||||
}
|
||||
|
||||
close($fh);
|
||||
|
||||
# sort initcalls in each object file numerically by the counter value
|
||||
# to ensure they are in the order they were defined
|
||||
foreach my $counter (sort { $a <=> $b } keys(%{$initcalls})) {
|
||||
print $initcalls->{$counter}->{"level"} . " " .
|
||||
$counter . " " .
|
||||
$initcalls->{$counter}->{"line"} . " " .
|
||||
$initcalls->{$counter}->{"function"} . "\n";
|
||||
}
|
||||
}
|
||||
|
||||
## waits for any child process to complete, reads the results, and adds them to
|
||||
## the $results array for later processing
|
||||
sub wait_for_results {
|
||||
my $pid = wait();
|
||||
if ($pid > 0) {
|
||||
my $fh = $jobs->{$pid};
|
||||
|
||||
# the child process prints out results in the following format:
|
||||
# line 1: <object file index>
|
||||
# line 2..n: <level> <counter> <line> <function>
|
||||
|
||||
my $index = <$fh>;
|
||||
chomp($index);
|
||||
|
||||
if (!($index =~ /^\d+$/)) {
|
||||
die "$0: child $pid returned an invalid index: $index";
|
||||
}
|
||||
$index = int($index);
|
||||
|
||||
while (<$fh>) {
|
||||
chomp;
|
||||
my ($level, $counter, $line, $function) = $_ =~
|
||||
/^([^\ ]+)\ (\d+)\ (\d+)\ (.*)$/;
|
||||
|
||||
if (!defined($level) ||
|
||||
!defined($counter) ||
|
||||
!defined($line) ||
|
||||
!defined($function)) {
|
||||
die "$0: child $pid returned invalid data";
|
||||
}
|
||||
|
||||
if (!exists($results->{$index})) {
|
||||
$results->{$index} = [];
|
||||
}
|
||||
|
||||
push (@{$results->{$index}}, {
|
||||
'level' => $level,
|
||||
'counter' => $counter,
|
||||
'line' => $line,
|
||||
'function' => $function
|
||||
});
|
||||
}
|
||||
|
||||
close($fh);
|
||||
delete($jobs->{$pid});
|
||||
}
|
||||
}
|
||||
|
||||
## launches child processes to find initcalls from the object files, waits for
|
||||
## each process to complete and collects the results
|
||||
sub process_objects {
|
||||
my $index = 0; # link order index of the object file
|
||||
my $njobs = get_online_processors();
|
||||
|
||||
while (scalar(@objects) > 0) {
|
||||
my $object = shift(@objects);
|
||||
|
||||
# fork a child process and read it's stdout
|
||||
my $pid = open(my $fh, '-|');
|
||||
|
||||
if (!defined($pid)) {
|
||||
die "$0: failed to fork: $!";
|
||||
} elsif ($pid) {
|
||||
# save the child process pid and the file handle
|
||||
$jobs->{$pid} = $fh;
|
||||
} else {
|
||||
STDOUT->autoflush(1);
|
||||
print "$index\n";
|
||||
find_initcalls("$objtree/$object");
|
||||
exit;
|
||||
}
|
||||
|
||||
$index++;
|
||||
|
||||
# if we reached the maximum number of processes, wait for one
|
||||
# to complete before launching new ones
|
||||
if (scalar(keys(%{$jobs})) >= $njobs && scalar(@objects) > 0) {
|
||||
wait_for_results();
|
||||
}
|
||||
}
|
||||
|
||||
# wait for the remaining children to complete
|
||||
while (scalar(keys(%{$jobs})) > 0) {
|
||||
wait_for_results();
|
||||
}
|
||||
}
|
||||
|
||||
## gets a list of actual object files from thin archives, and adds them to
|
||||
## @objects in link order
|
||||
sub find_objects {
|
||||
while (my $file = shift(@ARGV)) {
|
||||
my $pid = open (my $fh, "\"$ar\" t \"$file\" 2>/dev/null |")
|
||||
or die "$0: failed to execute $ar: $!";
|
||||
|
||||
my @output;
|
||||
|
||||
while (<$fh>) {
|
||||
chomp;
|
||||
push(@output, $_);
|
||||
}
|
||||
|
||||
close($fh);
|
||||
|
||||
# if $ar failed, assume we have an object file
|
||||
if ($? != 0) {
|
||||
push(@objects, $file);
|
||||
next;
|
||||
}
|
||||
|
||||
# if $ar succeeded, read the list of object files
|
||||
foreach (@output) {
|
||||
push(@objects, $_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
## START
|
||||
find_objects();
|
||||
process_objects();
|
||||
|
||||
## process results and add them to $sections in the correct order
|
||||
my $sections = {};
|
||||
|
||||
foreach my $index (sort { $a <=> $b } keys(%{$results})) {
|
||||
foreach my $result (@{$results->{$index}}) {
|
||||
my $level = $result->{'level'};
|
||||
|
||||
if (!exists($sections->{$level})) {
|
||||
$sections->{$level} = [];
|
||||
}
|
||||
|
||||
my $fsname = $result->{'counter'} . '_' .
|
||||
$result->{'line'} . '_' .
|
||||
$result->{'function'};
|
||||
|
||||
push(@{$sections->{$level}}, $fsname);
|
||||
}
|
||||
}
|
||||
|
||||
if (!keys(%{$sections})) {
|
||||
exit(0); # no initcalls...?
|
||||
}
|
||||
|
||||
## print out a linker script that defines the order of initcalls for each
|
||||
## level
|
||||
print "SECTIONS {\n";
|
||||
|
||||
foreach my $level (sort(keys(%{$sections}))) {
|
||||
my $section;
|
||||
|
||||
if ($level eq 'con') {
|
||||
$section = '.con_initcall.init';
|
||||
} elsif ($level eq 'security') {
|
||||
$section = '.security_initcall.init';
|
||||
} else {
|
||||
$section = ".initcall${level}.init";
|
||||
}
|
||||
|
||||
print "\t${section} : {\n";
|
||||
|
||||
foreach my $fsname (@{$sections->{$level}}) {
|
||||
print "\t\t*(${section}..${fsname}) ;\n"
|
||||
}
|
||||
|
||||
print "\t}\n";
|
||||
}
|
||||
|
||||
print "}\n";
|
Reference in New Issue
Block a user