Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) #!/usr/bin/env perl
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4) # Generates a list of Control-Flow Integrity (CFI) jump table symbols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5) # for kallsyms.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7) # Copyright (C) 2021 Google LLC
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) use strict;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) use warnings;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) ## parameters
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) my $ismodule = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) my $file;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) foreach (@ARGV) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) 	if ($_ eq '--module') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) 		$ismodule = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) 	} elsif (!defined($file)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 		$file = $_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) 		die "$0: usage $0 [--module] binary";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) ## environment
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) my $readelf = $ENV{'READELF'} || die "$0: ERROR: READELF not set?";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) my $objdump = $ENV{'OBJDUMP'} || die "$0: ERROR: OBJDUMP not set?";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) my $nm = $ENV{'NM'} || die "$0: ERROR: NM not set?";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) ## jump table addresses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) my $cfi_jt = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) ## text symbols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) my $text_symbols = {};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) ## parser state
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) use constant {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 	UNKNOWN => 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	SYMBOL	=> 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 	HINT	=> 2,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 	BRANCH	=> 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 	RELOC	=> 4
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) ## trims leading zeros from a string
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) sub trim_zeros {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 	my ($n) = @_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 	$n =~ s/^0+//;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 	$n = 0 if ($n eq '');
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 	return $n;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) ## finds __cfi_jt_* symbols from the binary to locate the start and end of the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) ## jump table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) sub find_cfi_jt {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) 	open(my $fh, "\"$readelf\" --symbols \"$file\" 2>/dev/null | grep __cfi_jt_ |")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 		or die "$0: ERROR: failed to execute \"$readelf\": $!";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 	while (<$fh>) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 		chomp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 		my ($addr, $name) = $_ =~ /\:.*([a-f0-9]{16}).*\s__cfi_jt_(.*)/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 		if (defined($addr) && defined($name)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 			$cfi_jt->{$name} = $addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	close($fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	die "$0: ERROR: __cfi_jt_start symbol missing" if !exists($cfi_jt->{"start"});
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	die "$0: ERROR: __cfi_jt_end symbol missing"   if !exists($cfi_jt->{"end"});
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) my $last = UNKNOWN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) my $last_symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) my $last_hint_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) my $last_branch_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) my $last_branch_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) my $last_reloc_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) sub is_symbol {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 	my ($line) = @_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 	my ($addr, $symbol) = $_ =~ /^([a-f0-9]{16})\s<([^>]+)>\:/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 	if (defined($addr) && defined($symbol)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 		$last = SYMBOL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 		$last_symbol = $symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) sub is_hint {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	my ($line) = @_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	my ($hint) = $_ =~ /^\s*([a-f0-9]+)\:.*\s+hint\s+#/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	if (defined($hint)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		$last = HINT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 		$last_hint_addr = $hint;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) sub find_text_symbol {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	my ($target) = @_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	my ($symbol, $expr, $offset) = $target =~ /^(\S*)([-\+])0x([a-f0-9]+)?$/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	if (!defined($symbol) || !defined(!$expr) || !defined($offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		return $target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	if ($symbol =~ /^\.((init|exit)\.)?text$/ && $expr eq '+') {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		$offset = trim_zeros($offset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		my $actual = $text_symbols->{"$symbol+$offset"};
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 		if (!defined($actual)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 			die "$0: unknown symbol at $symbol+0x$offset";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 		$symbol = $actual;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	return $symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) sub is_branch {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 	my ($line) = @_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 	my ($addr, $instr, $branch_target) = $_ =~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 		/^\s*([a-f0-9]+)\:.*(b|jmpq?)\s+0x[a-f0-9]+\s+<([^>]+)>/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 	if (defined($addr) && defined($instr) && defined($branch_target)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 		if ($last eq HINT) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 			$last_branch_addr = $last_hint_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 			$last_branch_addr = $addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 		$last = BRANCH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 		$last_branch_target = find_text_symbol($branch_target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) sub is_branch_reloc {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 	my ($line) = @_;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 	if ($last ne BRANCH) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 		return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 	my ($addr, $type, $reloc_target) = /\s*([a-f0-9]{16})\:\s+R_(\S+)\s+(\S+)$/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 	if (defined($addr) && defined($type) && defined($reloc_target)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 		$last = RELOC;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 		$last_reloc_target = find_text_symbol($reloc_target);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		return 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) ## walks through the jump table looking for branches and prints out a jump
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ## table symbol for each branch if one is missing
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) sub print_missing_symbols {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	my @symbols;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 	open(my $fh, "\"$objdump\" -d -r " .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 		"--start-address=0x" . $cfi_jt->{"start"} .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 		" --stop-address=0x" . $cfi_jt->{"end"} .
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		" \"$file\" 2>/dev/null |")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		or die "$0: ERROR: failed to execute \"$objdump\": $!";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 	while (<$fh>) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		chomp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		if (is_symbol($_) || is_hint($_)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 		my $cfi_jt_symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		if (is_branch($_)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 			if ($ismodule) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 				next; # wait for the relocation
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 			$cfi_jt_symbol = $last_branch_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 		} elsif (is_branch_reloc($_)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 			$cfi_jt_symbol = $last_reloc_target;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 			next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 		# ignore functions with a canonical jump table
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 		if ($cfi_jt_symbol =~ /\.cfi$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		$cfi_jt_symbol .= ".cfi_jt";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) 		$cfi_jt->{$last_branch_addr} = $cfi_jt_symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) 		if (defined($last_symbol) && $last_symbol eq $cfi_jt_symbol) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) 			next; # already exists
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		# print out the symbol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 		if ($ismodule) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 			push(@symbols, "\t\t$cfi_jt_symbol = . + 0x$last_branch_addr;");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 			push(@symbols, "$last_branch_addr t $cfi_jt_symbol");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 	close($fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 	if (!scalar(@symbols)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 		return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	if ($ismodule) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 		print "SECTIONS {\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 		# With -fpatchable-function-entry, LLD isn't happy without this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 		print "\t__patchable_function_entries : { *(__patchable_function_entries) }\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 		print "\t.text : {\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	foreach (@symbols) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 		print "$_\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 	if ($ismodule) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		print "\t}\n}\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) ## reads defined text symbols from the file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) sub read_symbols {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 	open(my $fh, "\"$objdump\" --syms \"$file\" 2>/dev/null |")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		or die "$0: ERROR: failed to execute \"$nm\": $!";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 	while (<$fh>) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 		chomp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		# llvm/tools/llvm-objdump/objdump.cpp:objdump::printSymbol
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		my ($addr, $debug, $section, $ref, $symbol) = $_ =~
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 			/^([a-f0-9]{16})\s.{5}(.).{2}(\S+)\s[a-f0-9]{16}(\s\.\S+)?\s(.*)$/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 		if (defined($addr) && defined($section) && defined($symbol)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 			if (!($section =~ /^\.((init|exit)\.)?text$/)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 				next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 			# skip arm mapping symbols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 			if ($symbol =~ /^\$[xd]\.\d+$/) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 				next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 			if (defined($debug) && $debug eq "d") {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 				next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			$addr = trim_zeros($addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			$text_symbols->{"$section+$addr"} = $symbol;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 	close($fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) ## prints out the remaining symbols from nm -n, filtering out the unnecessary
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) ## __typeid__ symbols aliasing the jump table symbols we added
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) sub print_kallsyms {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 	open(my $fh, "\"$nm\" -n \"$file\" 2>/dev/null |")
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 		or die "$0: ERROR: failed to execute \"$nm\": $!";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 	while (<$fh>) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 		chomp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 		my ($addr, $symbol) = $_ =~ /^([a-f0-9]{16})\s.\s(.*)$/;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 		if (defined($addr) && defined($symbol)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 			# drop duplicate __typeid__ symbols
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 			if ($symbol =~ /^__typeid__.*_global_addr$/ &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 				exists($cfi_jt->{$addr})) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 				next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 		print "$_\n";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 	close($fh);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ## main
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) find_cfi_jt();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) if ($ismodule) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	read_symbols();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	print_missing_symbols();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	print_missing_symbols();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	print_kallsyms();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) }