Archived
2
0
This repository has been archived on 2025-06-08. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
gpl/DIR819/tools/rsdk-linux-lstrip
2025-06-04 20:36:23 -03:00

513 lines
9.3 KiB
Perl
Executable File

#!/usr/bin/perl
#
# Realtek Semiconductor Corp.
#
# rsdk-linux-lstrip: target fs libstrip
#
# Tony Wu (tonywu@realtek.com)
# Jan. 10, 2009
$| = 1;
use Cwd 'abs_path';
use File::Basename;
use Getopt::Long;
my @ROMFS_EXES = ();
my %ROMFS_LIBS = ();
my @LDS = ();
my $dir_rsdk;
my $dir_romfs;
my $var_lib_size1;
my $var_lib_size2;
my $var_bin_size1;
my $var_bin_size2;
my $ldscript;
my $libgcc;
my $endian;
##
## parse argument
##
&print_header();
if ($#ARGV != 0) {
&print_usage;
exit -1;
}
$dir_romfs = $ARGV[0];
print "INFO: shrinking ", $dir_romfs, "\n";
##
## 0.0
##
&list_romfs_exes;
&list_romfs_libs;
&list_used_libs;
$var_lib_size1 = &check_size("$dir_romfs/lib");
$var_bin_size1 = &check_size("$dir_romfs/bin");
##
## 0. locate RSDK directory/check libgcc/check endian
##
&check_rsdk('rsdk-linux-gcc');
&check_endian;
&check_libgcc;
##
## 2. regenerate libraries
##
&lib_makeover;
&lib_cleanup;
##
## strip/sstrip libraries and executables
##
&romfs_strip;
##
##
##
$var_lib_size2 = &check_size("$dir_romfs/lib");
$var_bin_size2 = &check_size("$dir_romfs/bin");
print "INFO: romfs stripping completed", "\n\n";
print "INFO: romfs/bin size reduced from $var_bin_size1 to $var_bin_size2", "\n";
print "INFO: romfs/lib size reduced from $var_lib_size1 to $var_lib_size2", "\n";
exit 0;
##
## EXE
##
sub list_used_libs
{
local($lib);
local($exe);
local($line);
local(@libs);
foreach $exe (@ROMFS_EXES) {
$line = &list_needed_libs($exe);
@libs = split(/:/, $line);
foreach $lib (@libs) {
$ROMFS_LIBS{$lib} .= $exe . ':';
}
}
while (1) {
$count = 0;
foreach $lib (keys(%ROMFS_LIBS)) {
next if ($ROMFS_LIBS{$lib} eq '');
$line = &list_needed_libs($lib);
@libs = split(/:/, $line);
foreach $exe (@libs) {
next if (index($ROMFS_LIBS{$exe}, $lib) != -1);
$ROMFS_LIBS{$exe} .= $lib . ':';
$count++;
}
}
last if ($count == 0);
}
}
sub list_romfs_exes
{
local(@FILE);
local($file);
print "INFO: listing romfs executables", "\n";
@FILE = ();
unshift @FILE, glob("$dir_romfs/bin/*")
if (!-l $dir_romfs . "/bin");
unshift @FILE, glob("$dir_romfs/usr/bin/*")
if (!-l $dir_romfs . "/usr" and !-l $dir_romfs . "/usr/bin");
unshift @FILE, glob("$dir_romfs/usr/sbin/*")
if (!-l $dir_romfs . "/usr" and !-l $dir_romfs . "/usr/sbin");
unshift @FILE, glob("$dir_romfs/sbin/*")
if (!-l $dir_romfs . "/sbin");
foreach $file (@FILE) {
next if (-l $file || !-B $file);
unshift @ROMFS_EXES, $file if (&test_if_elf($file));
}
}
sub list_romfs_libs
{
local(@FILE);
local($lib);
local($exe);
print "INFO: listing romfs shared libraries", "\n";
@FILE = ();
unshift @FILE, glob("$dir_romfs/lib/*.so*");
foreach $file (@FILE) {
next if (-l $file || !-B $file);
$ROMFS_LIBS{$file} = '' if (&test_if_elf($file));
}
}
sub list_needed_libs
{
local($lexe) = shift;
local($line) = '';
open(PIPE, "rsdk-linux-readelf -d $lexe 2>&1 | grep NEEDED |");
while (<PIPE>) {
chomp;
#0x00000001 (NEEDED) Shared library: [libc.so.0]
next if (!m|0x\d{8} \(NEEDED\).+Shared library: \[(.*)\]|);
$name = $1;
$file = $dir_romfs . '/lib/' . $name;
if (-l $file) {
$file = readlink($file);
$file = $dir_romfs . '/lib/' . $file;
}
next if (index($line, $file) != -1);
$line .= $file . ':';
}
close (PIPE);
return $line;
}
sub list_symbols
{
local(@exes) = @_;
local(%syms) = ();
local($exe);
local($sym);
%syms = ();
foreach $exe (@exes) {
open(PIPE, "rsdk-linux-nm --dynamic $exe 2>&1 |");
while (<PIPE>) {
if (m|rsdk-linux-nm:.*: No symbols|) {
print "WARNING: $exe contains no dynamic symbols", "\n";
%syms = ();
return %syms;
}
chomp;
if (m|^.{8} [BUV] (.+)|) {
$sym = $1;
$syms{$sym} = 1;
}
}
close(PIPE);
}
return %syms;
}
##
## library subroutines
##
sub generate_lds
{
local($lib_file) = shift;
local($lib_name) = shift;
local(%syms) = ();
local(@exes) = ();
local($line) = '';
##
## list symbols
##
$line = $ROMFS_LIBS{$lib_file};
@exes = split(/:/, $line);
%syms = &list_symbols(@exes);
if (%syms == ()) {
return -1;
}
##
## generate linker script
##
open(PIPE, ">$lib_name.lds");
print PIPE "INCLUDE $dir_rsdk/$ldscript", "\n";
for $sym (keys(%syms)) {
print PIPE "EXTERN($sym)", "\n" if ($syms{$sym} == 1);
}
close(PIPE);
unshift @LDS, "$lib_name.lds";
return 0;
}
sub generate_lib
{
local($lib_file) = shift;
local($lib_name) = shift;
local($sofile, $solink, $soname, @solibs);
local($line);
local($lcmd);
local($llib);
$sofile = $lib_file;
$solink = $lib_name . '.lds';
@solibs = ();
##
## list linked libraries
##
$line = &list_needed_libs($lib_file);
@solibs = split(/:/, $line);
##
## rebuild library
##
if ($lib_name eq 'libuClibc') {
$soname = 'libc.so.0';
unshift @solibs, $dir_rsdk . '/lib/uclibc_nonshared.a';
unshift @solibs, $dir_rsdk . '/lib/libc.a';
unshift @solibs, $libgcc unless ($libgcc eq '');
}
elsif ($lib_name =~ m|^libgcc|) {
return;
}
elsif ($lib_name =~ m|^ld|) {
return;
}
elsif ($lib_name =~ m|^libdl|) {
return;
}
elsif ($lib_name =~ m|^libpthread|) {
print "skipping $lib_name .\n";
return;
}
else {
$soname = $lib_name . '.so.0';
unshift @solibs, $dir_rsdk . '/lib/' . $lib_name . '.a';
unshift @solibs, $libgcc unless ($libgcc eq '');
}
##
## make sure each solib exists before we do regen.
##
foreach $llib (@solibs) {
if ($llib ne '' and !-e $llib) {
print "WARNING: $llib does not exist", "\n";
print "WARNING: skipping $lib_file regeneration", "\n";
return;
}
}
$lcmd = "rsdk-linux-gcc -nostdlib -Wl,-warn-common -shared -o $sofile ";
$lcmd .= "-Wl,-soname,$soname -Wl,--script=$solink @solibs";
system($lcmd);
}
sub lib_makeover
{
print "INFO: recreating shared libraries ...", "\n";
foreach $lib_file (keys(%ROMFS_LIBS)) {
if ($ROMFS_LIBS{$lib_file} eq '') {
next if ($lib_file =~ m/ld-uClibc/);
print "----> removing ", $lib_file, "\n";
system("rm -f $lib_file");
next;
}
print "----> shrinking ", $lib_file, "\n";
$lib_name = basename $lib_file;
$lib_name =~ m/^([^-\.]*)[-\.]/;
$lib_name = $1;
##
## generate LDS
##
$ret = &generate_lds($lib_file, $lib_name);
if ($ret < 0) {
print "WARNING: cannot rebuild library $lib_file, skipped", "\n";
next;
}
##
## generate LIB
##
&generate_lib($lib_file, $lib_name);
}
}
sub lib_cleanup
{
local(@FILE);
local($lib);
local($exe);
print "INFO: cleanup shared library links", "\n";
@FILE = ();
unshift @FILE, glob("$dir_romfs/lib/*.so*");
foreach $file (@FILE) {
if (-l $file) {
if (!-B $file) {
print "----> removing dangling link ", $file, "\n";
system("rm -f $file");
}
next;
}
unshift @ROMFS_EXES, $file if (&test_if_elf($file));
}
foreach $lds (@LDS) {
print "----> removing ldscript ", $lds, "\n";
system("rm -f $lds");
}
}
sub romfs_strip
{
local($file);
print "INFO: stripping executables and libraries", "\n";
foreach $file (@ROMFS_EXES) {
print "----> stripping ", $file, "\n";
system("rsdk-linux-strip $file");
system("rsdk-linux-sstrip $file");
}
}
##
## supporter functions
##
sub print_header
{
print "\n";
print "Realtek Semiconductor Corp.", "\n";
print "Shared Library Shrinker, v1.0", "\n";
print "Tony Wu (tonywu\@realtek.com)", "\n";
print "\n";
}
sub print_usage
{
print "\n";
print "usage: $0 dir_romfs", "\n";
print "\n";
}
sub check_rsdk
{
local($prog) = shift;
local($line);
$line = `which $prog 2>/dev/null`;
chomp $line;
if (!-f $line) {
print "ERROR: unable to allocate RSDK", "\n";
exit 1;
}
$line = `dirname $line`;
chomp $line;
if ($line eq '') {
print "ERROR: unable to allocate RSDK", "\n";
exit 1;
}
$dir_rsdk = abs_path($line . '/..');
print "INFO: RSDK -> ", $dir_rsdk, "\n";
}
sub check_endian
{
local($exe);
local($line);
print "INFO: checking romfs endian ... ";
$exe = $ROMFS_EXES[0];
if ($exe eq '') {
exit -1;
}
$line = `rsdk-linux-readelf -h $exe`;
if ($line =~ m/little endian/) {
$ldscript = "lib/ldscripts/elf32ltsmip.xs";
print "little endian";
}
if ($line =~ m/big endian/) {
$ldscript = "lib/ldscripts/elf32btsmip.xs";
print "big endian";
}
print "\n";
}
sub check_libgcc
{
local($lib);
print "INFO: checking libgcc ... ";
foreach $lib (keys(%ROMFS_LIBS)) {
if ($lib =~ m|libgcc|) {
print "shared", "\n";
$libgcc = ''; # follow shared libaray's instinct
return;
}
}
print "static", "\n";
$libgcc = $dir_rsdk . '/lib/libgcc.a';
}
sub check_size
{
local($line) = shift;
local($size, $rest);
return 0 if (!-d $line);
open(PIPE, "du -s $line |");
$line = <PIPE>;
close(PIPE);
($size, $rest) = split(/[\s\t]+/, $line);
return $size;
}
sub test_if_elf
{
local($file) = shift;
open(PIPE, $file);
read(PIPE, $line, 4);
close(PIPE);
if ($line eq "\x7FELF") {
return 1;
}
return 0;
}