Windows-Server-2003/tools/postbuildscripts/symmungepublic.cmd

480 lines
14 KiB
Batchfile

@rem ='
@echo off
REM ------------------------------------------------------------------
REM
REM SYMCD.cmd
REM Create Symbol CD.
REM
REM Copyright (c) Microsoft Corporation. All rights reserved.
REM
REM ------------------------------------------------------------------
perl -x "%~f0" %*
goto :EOF
REM ';
#!perl
use strict;
use lib $ENV{RAZZLETOOLPATH} . "\\PostBuildScripts";
use lib $ENV{RAZZLETOOLPATH};
use PbuildEnv;
use ParseArgs;
use File::Basename;
use IO::File;
use Win32;
use File::Path;
use File::Copy;
use IO::File;
use Logmsg;
#
# SFS: SYMBOL FILESPECS
# SFN: SYMBOL FILENAMES
# ST: SYMBOL TOOL
# SDIR: SYMBOL DIRECTORIES
# SOPT: SYMBOL OPTIONS
# COPT: COMMAND OPTIONS
#
my (%SFS, %SFN, %ST, %SDIR, %SOPT, %COPT);
my ($NTPostBld, $BuildArch, $BuildType, $RazzleToolPath, $BuildLogs, $Lang, $CoverageBuild,
$MungePath, $SymbolCD, $CabSize, $SymbolCDHandle, $Delegate, $ARCH, %DontShip, %SymBad,
$FileScope
);
sub Usage { print<<USAGE; exit(1) }
Munge public symbols
SymCD [-l lang] [-f filescope]
-l lang to specify which language
-f filescope to specify the filelist under pp directory
USAGE
#
# parse the command line arguments
#
parseargs(
'l:' => \$Lang,
# 'p:' => \$Project,
'f:' => \$FileScope,
'?' => \&Usage,
);
&main;
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#
# Munge public symbols
#
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
sub main
{
&Initial_Variables();
&Munge_Public;
}
sub Munge_Public
{
my ($filename, $filepath, $fileext);
my ($mySymbol, $mySymbolPath, $myBinary, $myMungePath, $oldMungePath, $newMungePath);
my ($c_ext, @myCompOpt);
my ($optCL, $optML, $optLINK);
my @ppdirs = &Exists("$MungePath\\$FileScope");
@myCompOpt = @ENV{qw(_CL_ _ML_ _LINK_)} if (lc$ENV{'_BuildArch'} eq 'x86');
logmsg("Adding type info to some public pdb files for debugging...");
for (@ppdirs) {
next if (!-d);
($filename, $filepath, $fileext) = FileParse($_);
if (length($fileext) ne '3') {
errmsg("$_ name has the wrong format.");
return;
}
$mySymbol = &SymbolPath("$NTPostBld\\symbols", "retail", "$filename\.$fileext");
$mySymbolPath = &SymbolPath("$NTPostBld\\symbols", "retail");
$myBinary = "$NTPostBld\\$filename\.$fileext";
if (-f $mySymbol) {
$myMungePath = "$MungePath\\$filename\.$fileext";
($oldMungePath, $newMungePath) = ("$myMungePath\\original", "$myMungePath\\updated");
logmsg("Working on $filename\.$fileext");
## See if we need to do anything, or if the symbol file has already been updated
## If the symbol file passes symbol checking, with types present then don't update it.
if (!&IsSymchkFailed($myBinary, $mySymbolPath, "/o")) {
logmsg("Skipping $filename\.$fileext because it's public pdb already has type info in it.");
next;
}
mkpath([$oldMungePath, $newMungePath]);
## See if the pdb, if it exists, in original matches the exe in binaries
if (&IsSymchkFailed($myBinary, $oldMungePath, $SOPT{'PUB_SYM_FLAG'})) {
logmsg("Saving a copy of $filename\.pdb to $oldMungePath");
copy($mySymbol, $oldMungePath) or errmsg("copy $mySymbol to $oldMungePath failed.");
if (&IsSymchkFailed($myBinary, $oldMungePath, $SOPT{'PUB_SYM_FLAG'})) {
errmsg("cannot copy the correct pdb file to $oldMungePath\.");
next;
}
}
if (&Exists("$myMungePath\\*.*") > 0) {
if (!copy("$oldMungePath\\$filename\.pdb", $newMungePath)) {
errmsg("copy failed for $oldMungePath\\$filename\.pdb to $newMungePath\.");
next;
}
logmsg("Pushing type info into the stripped $filename\.pdb");
$c_ext = (-e "$myMungePath\\$filename\.c")? "c": "cpp";
if (&IsVC7PDB("$newMungePath\\$filename\.pdb")) {
logmsg("This is a vc7 pdb");
@ENV{qw(_CL_ _ML_ _LINK_)} = ();
} else {
logmsg("This is a vc6 pdb");
@ENV{qw(_CL_ _ML_ _LINK_)} = @myCompOpt;
}
logmsg("cl /nologo /Zi /Gz /c $myMungePath\\$filename\.$c_ext /Fd" . "$newMungePath\\$filename\.pdb /Fo" . "$newMungePath\\$filename\.obj");
if (system("cl /nologo /Zi /Gz /c $myMungePath\\$filename\.$c_ext /Fd" . "$newMungePath\\$filename\.pdb /Fo" . "$newMungePath\\$filename\.obj") > 0) {
errmsg("cl /Zi /Gz /c $myMungePath\\$filename\.$c_ext /Fd" . "$newMungePath\\$filename\.pdb had errors.");
next;
}
if (&IsSymchkFailed($myBinary, $newMungePath, "/o $SOPT{'PUB_SYM_FLAG'}")) {
errmsg("the munged $newMungePath\\$filename\.pdb doesn't match $myBinary.");
next;
}
logmsg("Copying $newMungePath\\$filename\.pdb to $mySymbolPath\\$fileext");
copy("$newMungePath\\$filename\.pdb", "$mySymbolPath\\$fileext");
if (&IsSymchkFailed($myBinary, $mySymbolPath, "/o $SOPT{'PUB_SYM_FLAG'}")) {
copy("$oldMungePath\\$filename\.pdb", "$mySymbolPath\\$fileext");
errmsg("the munged $newMungePath\\$filename\.pdb didn't get copied to $mySymbolPath\\$fileext\.");
logmsg("Copying the original pdb back to $mySymbolPath\\$fileext");
copy("$oldMungePath\\$filename\.$fileext", "$mySymbolPath\\$fileext") or do {
errmsg("cannot get $filename\.$fileext symbols copied to $mySymbolPath\\$fileext\.");
next;
}
}
}
} else {
logmsg("Skipping $filename\.$fileext because $mySymbol does not exist.");
}
}
@ENV{qw(_CL_ _ML_ _LINK_)} = @myCompOpt if (lc$ENV{'_BuildArch'} eq 'x86');
return;
}
####################################################################################
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#
# Initial variables
#
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
sub Initial_Variables
{
# Set Variables
$Lang = $ENV{'LANG'} if ("$Lang" eq "");
$ENV{'LANG'} = $Lang;
$BuildArch = $ENV{'_BuildArch'};
$BuildType = $ENV{'_BuildType'};
$NTPostBld = $ENV{'_NTPostBld'};
# $NTPostBld = "d:\\Ins_Sym\\$Project\\$Lang";
$MungePath = "$NTPostBld\\pp";
$SymbolCD = "$NTPostBld\\SymbolCD";
$RazzleToolPath = $ENV{'RazzleToolPath'};
$BuildLogs = "$NTPostBld\\build_logs";
$CabSize = 60000000;
$SymbolCDHandle = '';
# $Delegate = new Delegate 3, $ENV{'NUMBER_OF_PROCESSORS'} * 4;
# $ARCH = "\\\\arch\\archive\\ms\\windows\\windows_xp\\rtm\\2600\\$BuildType\\all\\$BuildArch\\pub";
$ARCH = "d:\\Ins_Sym\\Win2k\\$Lang\\symbols";
# $Symbol_Path_Creator = {
# 'FULL' => \&Full_Package_Path,
# 'UPDATE' => \&Update_Package_Path
# };
# SDIR: SYMBOL DIRECTORIES
%SDIR = (
'SYMBOLCD' => $SymbolCD,
'PUBSYM' => "$NTPostBld\\Symbols",
'FULL_CD' => "$NTPostBld\\SymbolCD\\CD",
# 'FULL_PKG' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType),
# 'FULL_INF' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType),
'FULL_CAB' => "$SymbolCD\\CABs\\FULL",
'FULL_DDF' => "$SymbolCD\\DDF\\FULL",
'FULL_CDF' => "$SymbolCD\\DDF\\FULL",
# 'FULL_CAT' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType),
'UPDATE_CD' => "$NTPostBld\\SymbolCD\\UPD",
# 'UPDATE_PKG' => &{$Symbol_Path_Creator->{'UPDATE'}}("$NTPostBld\\SymbolCD\\UPD\\Symbols", $BuildArch, $BuildType),
# 'UPDATE_INF' => &{$Symbol_Path_Creator->{'UPDATE'}}("$NTPostBld\\SymbolCD\\UPD\\Symbols", $BuildArch, $BuildType),
'UPDATE_CAB' => "$SymbolCD\\CABs\\UPDATE",
'UPDATE_DDF' => "$SymbolCD\\DDF\\UPDATE",
'UPDATE_CDF' => "$SymbolCD\\DDF\\UPDATE",
# 'UPDATE_CAT' => &{$Symbol_Path_Creator->{'UPDATE'}}("$NTPostBld\\SymbolCD\\UPD\\Symbols", $BuildArch, $BuildType),
);
# SFS: SYMBOL FILESPECS
%SFS = (
'CD' => $SDIR{'SYMBOLCD'} . '\\SymbolCD.txt',
# 'BLDNUM' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType) . "\\QFEnum.txt",
'LIST' => $SDIR{'SYMBOLCD'} . '\\SymList.txt',
'BAD' => $SDIR{'SYMBOLCD'} . '\\SymBad.txt',
'SYMUPD' => $SDIR{'SYMBOLCD'} . '\\SymUpd.txt',
'CAGENERR' => $SDIR{'SYMBOLCD'} . '\\cabgenerr.log',
'EXCLUDE' => $SDIR{'SYMBOLCD'} . '\\Exclude.txt',
'BINDIFF' => $BuildLogs . '\\bindiff.txt',
'WITHTYPES' => $SDIR{'SYMBOLCD'} . '\\SymbolsWithTypes.txt',
'DONTSHIP' => $SDIR{'SYMBOLCD'} . '\\SymDontShip.txt'
);
# SFN: SYMBOL FILENAMES
%SFN = (
'FULL_INF' => 'Symbols',
'FULL_CAB' => 'Symbols',
'FULL_DDF' => 'Symbols',
'FULL_CDF' => 'Symbols',
'FULL_CAT' => 'Symbols',
'UPDATE_INF' => 'Symbols',
'UPDATE_CAB' => 'Symbols',
'UPDATE_DDF' => 'Symbols',
'UPDATE_CDF' => 'Symbols',
'UPDATE_CAT' => 'Symbols',
);
# ST: SYMBOL TOOL
%ST = (
'MAKE' => "symmake.exe",
'PERL' => "perl.exe",
'CHECK' => "symchk.exe",
'BENCH' => "cabbench.exe",
'DUMP' => "pdbdump.exe",
'SIGN' => $RazzleToolPath . "\\ntsign.cmd",
'CAB' => $RazzleToolPath . "\\sp\\symcab.cmd"
);
# SOPT: SYMBOL OPTIONS
#
# the default option is doing all steps
#
%SOPT = (
'PUB_SYM_FLAG' => '/p',
'GOLD_BUILD' => 1,
'RUN_ALWAYS' => 1,
'NEED_MUNGE_PUBLIC' => 1,
'NEED_CREATE_SYMBOLCD_TXT' => undef,
'NEED_CREATE_MAKE_FILE' => 1,
'NEED_CREATE_SYMBOLCAT' => 1,
'NEED_CREATE_SYMBOLCAB' => 1,
'NEED_SIGN_FILES' => 1,
'NEED_FLAT_DIR' => 1,
'NEED_CLEAN_BUILD' => 1,
'FLAT_SYMBOL_PATH' => undef,
'USE_SYMLIST' => undef
);
if ((defined $COPT{'NEED_ALL'}) && (defined $COPT{'NEED_MUNGE_PUBLIC'})) {
errmsg("Error options! Please specify either -m or -t");
exit(1);
}
$FileScope = "*.*" if ("$FileScope" eq "");
# if neither is official build machine, nor assign -t in command line,
# or if is official build machine, but assign -m in command line,
#
# we will only munge public symbols
#
# if (((!exists $ENV{'OFFICIAL_BUILD_MACHINE'}) &&
# (!defined $COPT{'NEED_ALL'})) ||
# ((exists $ENV{'OFFICIAL_BUILD_MACHINE'}) &&
# (defined $COPT{'NEED_MUNGE_PUBLIC'}))) {
# @SOPT{qw(NEED_MUNGE_PUBLIC
# NEED_CREATE_SYMBOLCD_TXT
# NEED_CREATE_MAKE_FILE
# NEED_CREATE_SYMBOLCAT
# NEED_CREATE_SYMBOLCAB
# NEED_SIGN_FILES)} = (1, undef, undef, undef, undef, undef);
# }
# if ($SOPT{'NEED_CLEAN_BUILD'}) {
# rmtree([@SDIR{qw(FULL_DDF FULL_CD FULL_CAB UPDATE_DDF UPDATE_CD UPDATE_CAB)}]);
# }
}
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#
# Small Subroutine
#
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#
# IsSymchkFailed($binary, $symbol, $extraopt)
# - call symchk.exe to verify $binary matches with $symbol
#
sub IsSymchkFailed {
my ($binary, $symbol, $extraopt) = @_;
my ($fh, $record_error, $record_log, $result);
local $_;
if (defined $extraopt) {
if ($extraopt =~ /2\>/) {
$record_error = 1;
}
if ($extraopt =~ /[^2]\>/) {
$record_log = 1;
}
$extraopt =~ s/2?\>.*$//g;
}
$fh = new IO::File "$ST{'CHECK'} /t $binary /s $symbol $extraopt |";
while (<$fh>) {
chomp;
$result = $1 if /FAILED files = (\d+)/;
logmsg($_) if ($record_log);
logmsg($_) if (($record_error) && (/^ERROR/i));
}
undef $fh;
return $result;
}
#
# SymbolPath($root, $subdir, $filename)
# - return the symbol path for the binary
#
sub SymbolPath
{
my ($root, $subdir, $filename) = @_;
$root .= "\\$subdir" if (!$SOPT{'FLAT_SYMBOL_PATH'});
if (defined $filename) {
$filename =~ /\.([^\.]+)$/;
$root .= "\\$1\\$`";
return "$root\.pdb" if (-e "$root\.pdb");
return "$root\.dbg" if (-e "$root\.dbg");
$root .= ".pdb";
}
return $root;
}
#
# Full_Package_Path($root, $myarch, $mytype)
# - for compatible reason, we create a function to construct the path of the symbols.exe of the full package
#
sub Full_Package_Path
{
my ($root, $myarch, $mytype) = @_;
$mytype =~ s/fre/retail/ig;
$mytype =~ s/chk/debug/ig;
return "$root\\$myarch\\$mytype"; # temporary
}
#
# Update_Package_Path($root, $myarch, $mytype)
# - for compatible reason, we create a function to construct the path of the symbols.exe of the update package
#
sub Update_Package_Path
{
my ($root, $myarch, $mytype) = @_;
return $root; # \\$myarch\\$mytype"; # temporary
}
#
# IsVC7PDB($pdbspec)
# - because the MD5 hash value is 0000-0000-0000-000000000000 for the symbols built by VC6 or older
# - we can use it to determine the pdb is VC7 or not
#
sub IsVC7PDB {
my ($pdbspec) = shift;
my $fh = new IO::File "$ST{'DUMP'} $pdbspec hdr |";
local $_;
while (<$fh>) {
return 0 if /0000-0000-0000-000000000000/i;
}
return 1;
}
#
# Check_Exist_File($filename, $logfile)
# - this is a function generator, which generates a function for checking the $filename exist or not
# - it also check if the $logfile has 'ERROR:' in it
#
sub Check_Exist_File
{
my ($filename, $logfile) = @_;
return sub {
if (-e $filename) {
return 1;
} else {
my $fh = new IO::File $logfile;
for (<$fh>) {
chomp;
next if (!/.+ERROR\: /i);
errmsg("Error - $'");
}
$fh->close();
logmsg("$filename did not get created.");
return 0;
}
};
}
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
#
# Common Subroutine
#
# * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
sub FileParse
{
my ($name, $path, $ext) = fileparse(shift, '\.[^\.]+$');
$ext =~ s/^\.//;
return $name, $path, $ext;
}
sub IsUSA
{
# return (lc$ENV{'lang'} eq 'usa');
return 1;
}
sub Exists
{
my @list = glob(shift);
return (wantarray)?@list:$#list + 1;
}
1;
__END__