Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
15 KiB

  1. @rem ='
  2. @echo off
  3. REM ------------------------------------------------------------------
  4. REM
  5. REM SYMCD.cmd
  6. REM Create Symbol CD.
  7. REM
  8. REM Copyright (c) Microsoft Corporation. All rights reserved.
  9. REM
  10. REM ------------------------------------------------------------------
  11. perl -x "%~f0" %*
  12. goto :EOF
  13. REM ';
  14. #!perl
  15. use strict;
  16. use lib $ENV{RAZZLETOOLPATH} . "\\PostBuildScripts";
  17. use lib $ENV{RAZZLETOOLPATH};
  18. use PbuildEnv;
  19. use ParseArgs;
  20. use File::Basename;
  21. use IO::File;
  22. use Win32;
  23. use File::Path;
  24. use File::Copy;
  25. use IO::File;
  26. use Logmsg;
  27. #
  28. # SFS: SYMBOL FILESPECS
  29. # SFN: SYMBOL FILENAMES
  30. # ST: SYMBOL TOOL
  31. # SDIR: SYMBOL DIRECTORIES
  32. # SOPT: SYMBOL OPTIONS
  33. # COPT: COMMAND OPTIONS
  34. #
  35. my (%SFS, %SFN, %ST, %SDIR, %SOPT, %COPT);
  36. my ($NTPostBld, $BuildArch, $BuildType, $RazzleToolPath, $BuildLogs, $Lang, $CoverageBuild,
  37. $MungePath, $SymbolCD, $CabSize, $SymbolCDHandle, $Delegate, $ARCH, %DontShip, %SymBad,
  38. $FileScope
  39. );
  40. sub Usage { print<<USAGE; exit(1) }
  41. Munge public symbols
  42. SymCD [-l lang] [-f filescope]
  43. -l lang to specify which language
  44. -f filescope to specify the filelist under pp directory
  45. USAGE
  46. #
  47. # parse the command line arguments
  48. #
  49. parseargs(
  50. 'l:' => \$Lang,
  51. # 'p:' => \$Project,
  52. 'f:' => \$FileScope,
  53. '?' => \&Usage,
  54. );
  55. &main;
  56. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  57. #
  58. # Munge public symbols
  59. #
  60. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  61. sub main
  62. {
  63. &Initial_Variables();
  64. &Munge_Public;
  65. }
  66. sub Munge_Public
  67. {
  68. my ($filename, $filepath, $fileext);
  69. my ($mySymbol, $mySymbolPath, $myBinary, $myMungePath, $oldMungePath, $newMungePath);
  70. my ($c_ext, @myCompOpt);
  71. my ($optCL, $optML, $optLINK);
  72. my @ppdirs = &Exists("$MungePath\\$FileScope");
  73. @myCompOpt = @ENV{qw(_CL_ _ML_ _LINK_)} if (lc$ENV{'_BuildArch'} eq 'x86');
  74. logmsg("Adding type info to some public pdb files for debugging...");
  75. for (@ppdirs) {
  76. next if (!-d);
  77. ($filename, $filepath, $fileext) = FileParse($_);
  78. if (length($fileext) ne '3') {
  79. errmsg("$_ name has the wrong format.");
  80. return;
  81. }
  82. $mySymbol = &SymbolPath("$NTPostBld\\symbols", "retail", "$filename\.$fileext");
  83. $mySymbolPath = &SymbolPath("$NTPostBld\\symbols", "retail");
  84. $myBinary = "$NTPostBld\\$filename\.$fileext";
  85. if (-f $mySymbol) {
  86. $myMungePath = "$MungePath\\$filename\.$fileext";
  87. ($oldMungePath, $newMungePath) = ("$myMungePath\\original", "$myMungePath\\updated");
  88. logmsg("Working on $filename\.$fileext");
  89. ## See if we need to do anything, or if the symbol file has already been updated
  90. ## If the symbol file passes symbol checking, with types present then don't update it.
  91. if (!&IsSymchkFailed($myBinary, $mySymbolPath, "/o")) {
  92. logmsg("Skipping $filename\.$fileext because it's public pdb already has type info in it.");
  93. next;
  94. }
  95. mkpath([$oldMungePath, $newMungePath]);
  96. ## See if the pdb, if it exists, in original matches the exe in binaries
  97. if (&IsSymchkFailed($myBinary, $oldMungePath, $SOPT{'PUB_SYM_FLAG'})) {
  98. logmsg("Saving a copy of $filename\.pdb to $oldMungePath");
  99. copy($mySymbol, $oldMungePath) or errmsg("copy $mySymbol to $oldMungePath failed.");
  100. if (&IsSymchkFailed($myBinary, $oldMungePath, $SOPT{'PUB_SYM_FLAG'})) {
  101. errmsg("cannot copy the correct pdb file to $oldMungePath\.");
  102. next;
  103. }
  104. }
  105. if (&Exists("$myMungePath\\*.*") > 0) {
  106. if (!copy("$oldMungePath\\$filename\.pdb", $newMungePath)) {
  107. errmsg("copy failed for $oldMungePath\\$filename\.pdb to $newMungePath\.");
  108. next;
  109. }
  110. logmsg("Pushing type info into the stripped $filename\.pdb");
  111. $c_ext = (-e "$myMungePath\\$filename\.c")? "c": "cpp";
  112. if (&IsVC7PDB("$newMungePath\\$filename\.pdb")) {
  113. logmsg("This is a vc7 pdb");
  114. @ENV{qw(_CL_ _ML_ _LINK_)} = ();
  115. } else {
  116. logmsg("This is a vc6 pdb");
  117. @ENV{qw(_CL_ _ML_ _LINK_)} = @myCompOpt;
  118. }
  119. logmsg("cl /nologo /Zi /Gz /c $myMungePath\\$filename\.$c_ext /Fd" . "$newMungePath\\$filename\.pdb /Fo" . "$newMungePath\\$filename\.obj");
  120. if (system("cl /nologo /Zi /Gz /c $myMungePath\\$filename\.$c_ext /Fd" . "$newMungePath\\$filename\.pdb /Fo" . "$newMungePath\\$filename\.obj") > 0) {
  121. errmsg("cl /Zi /Gz /c $myMungePath\\$filename\.$c_ext /Fd" . "$newMungePath\\$filename\.pdb had errors.");
  122. next;
  123. }
  124. if (&IsSymchkFailed($myBinary, $newMungePath, "/o $SOPT{'PUB_SYM_FLAG'}")) {
  125. errmsg("the munged $newMungePath\\$filename\.pdb doesn't match $myBinary.");
  126. next;
  127. }
  128. logmsg("Copying $newMungePath\\$filename\.pdb to $mySymbolPath\\$fileext");
  129. copy("$newMungePath\\$filename\.pdb", "$mySymbolPath\\$fileext");
  130. if (&IsSymchkFailed($myBinary, $mySymbolPath, "/o $SOPT{'PUB_SYM_FLAG'}")) {
  131. copy("$oldMungePath\\$filename\.pdb", "$mySymbolPath\\$fileext");
  132. errmsg("the munged $newMungePath\\$filename\.pdb didn't get copied to $mySymbolPath\\$fileext\.");
  133. logmsg("Copying the original pdb back to $mySymbolPath\\$fileext");
  134. copy("$oldMungePath\\$filename\.$fileext", "$mySymbolPath\\$fileext") or do {
  135. errmsg("cannot get $filename\.$fileext symbols copied to $mySymbolPath\\$fileext\.");
  136. next;
  137. }
  138. }
  139. }
  140. } else {
  141. logmsg("Skipping $filename\.$fileext because $mySymbol does not exist.");
  142. }
  143. }
  144. @ENV{qw(_CL_ _ML_ _LINK_)} = @myCompOpt if (lc$ENV{'_BuildArch'} eq 'x86');
  145. return;
  146. }
  147. ####################################################################################
  148. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  149. #
  150. # Initial variables
  151. #
  152. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  153. sub Initial_Variables
  154. {
  155. # Set Variables
  156. $Lang = $ENV{'LANG'} if ("$Lang" eq "");
  157. $ENV{'LANG'} = $Lang;
  158. $BuildArch = $ENV{'_BuildArch'};
  159. $BuildType = $ENV{'_BuildType'};
  160. $NTPostBld = $ENV{'_NTPostBld'};
  161. # $NTPostBld = "d:\\Ins_Sym\\$Project\\$Lang";
  162. $MungePath = "$NTPostBld\\pp";
  163. $SymbolCD = "$NTPostBld\\SymbolCD";
  164. $RazzleToolPath = $ENV{'RazzleToolPath'};
  165. $BuildLogs = "$NTPostBld\\build_logs";
  166. $CabSize = 60000000;
  167. $SymbolCDHandle = '';
  168. # $Delegate = new Delegate 3, $ENV{'NUMBER_OF_PROCESSORS'} * 4;
  169. # $ARCH = "\\\\arch\\archive\\ms\\windows\\windows_xp\\rtm\\2600\\$BuildType\\all\\$BuildArch\\pub";
  170. $ARCH = "d:\\Ins_Sym\\Win2k\\$Lang\\symbols";
  171. # $Symbol_Path_Creator = {
  172. # 'FULL' => \&Full_Package_Path,
  173. # 'UPDATE' => \&Update_Package_Path
  174. # };
  175. # SDIR: SYMBOL DIRECTORIES
  176. %SDIR = (
  177. 'SYMBOLCD' => $SymbolCD,
  178. 'PUBSYM' => "$NTPostBld\\Symbols",
  179. 'FULL_CD' => "$NTPostBld\\SymbolCD\\CD",
  180. # 'FULL_PKG' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType),
  181. # 'FULL_INF' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType),
  182. 'FULL_CAB' => "$SymbolCD\\CABs\\FULL",
  183. 'FULL_DDF' => "$SymbolCD\\DDF\\FULL",
  184. 'FULL_CDF' => "$SymbolCD\\DDF\\FULL",
  185. # 'FULL_CAT' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType),
  186. 'UPDATE_CD' => "$NTPostBld\\SymbolCD\\UPD",
  187. # 'UPDATE_PKG' => &{$Symbol_Path_Creator->{'UPDATE'}}("$NTPostBld\\SymbolCD\\UPD\\Symbols", $BuildArch, $BuildType),
  188. # 'UPDATE_INF' => &{$Symbol_Path_Creator->{'UPDATE'}}("$NTPostBld\\SymbolCD\\UPD\\Symbols", $BuildArch, $BuildType),
  189. 'UPDATE_CAB' => "$SymbolCD\\CABs\\UPDATE",
  190. 'UPDATE_DDF' => "$SymbolCD\\DDF\\UPDATE",
  191. 'UPDATE_CDF' => "$SymbolCD\\DDF\\UPDATE",
  192. # 'UPDATE_CAT' => &{$Symbol_Path_Creator->{'UPDATE'}}("$NTPostBld\\SymbolCD\\UPD\\Symbols", $BuildArch, $BuildType),
  193. );
  194. # SFS: SYMBOL FILESPECS
  195. %SFS = (
  196. 'CD' => $SDIR{'SYMBOLCD'} . '\\SymbolCD.txt',
  197. # 'BLDNUM' => &{$Symbol_Path_Creator->{'FULL'}}("$NTPostBld\\SymbolCD\\CD\\Symbols", $BuildArch, $BuildType) . "\\QFEnum.txt",
  198. 'LIST' => $SDIR{'SYMBOLCD'} . '\\SymList.txt',
  199. 'BAD' => $SDIR{'SYMBOLCD'} . '\\SymBad.txt',
  200. 'SYMUPD' => $SDIR{'SYMBOLCD'} . '\\SymUpd.txt',
  201. 'CAGENERR' => $SDIR{'SYMBOLCD'} . '\\cabgenerr.log',
  202. 'EXCLUDE' => $SDIR{'SYMBOLCD'} . '\\Exclude.txt',
  203. 'BINDIFF' => $BuildLogs . '\\bindiff.txt',
  204. 'WITHTYPES' => $SDIR{'SYMBOLCD'} . '\\SymbolsWithTypes.txt',
  205. 'DONTSHIP' => $SDIR{'SYMBOLCD'} . '\\SymDontShip.txt'
  206. );
  207. # SFN: SYMBOL FILENAMES
  208. %SFN = (
  209. 'FULL_INF' => 'Symbols',
  210. 'FULL_CAB' => 'Symbols',
  211. 'FULL_DDF' => 'Symbols',
  212. 'FULL_CDF' => 'Symbols',
  213. 'FULL_CAT' => 'Symbols',
  214. 'UPDATE_INF' => 'Symbols',
  215. 'UPDATE_CAB' => 'Symbols',
  216. 'UPDATE_DDF' => 'Symbols',
  217. 'UPDATE_CDF' => 'Symbols',
  218. 'UPDATE_CAT' => 'Symbols',
  219. );
  220. # ST: SYMBOL TOOL
  221. %ST = (
  222. 'MAKE' => "symmake.exe",
  223. 'PERL' => "perl.exe",
  224. 'CHECK' => "symchk.exe",
  225. 'BENCH' => "cabbench.exe",
  226. 'DUMP' => "pdbdump.exe",
  227. 'SIGN' => $RazzleToolPath . "\\ntsign.cmd",
  228. 'CAB' => $RazzleToolPath . "\\sp\\symcab.cmd"
  229. );
  230. # SOPT: SYMBOL OPTIONS
  231. #
  232. # the default option is doing all steps
  233. #
  234. %SOPT = (
  235. 'PUB_SYM_FLAG' => '/p',
  236. 'GOLD_BUILD' => 1,
  237. 'RUN_ALWAYS' => 1,
  238. 'NEED_MUNGE_PUBLIC' => 1,
  239. 'NEED_CREATE_SYMBOLCD_TXT' => undef,
  240. 'NEED_CREATE_MAKE_FILE' => 1,
  241. 'NEED_CREATE_SYMBOLCAT' => 1,
  242. 'NEED_CREATE_SYMBOLCAB' => 1,
  243. 'NEED_SIGN_FILES' => 1,
  244. 'NEED_FLAT_DIR' => 1,
  245. 'NEED_CLEAN_BUILD' => 1,
  246. 'FLAT_SYMBOL_PATH' => undef,
  247. 'USE_SYMLIST' => undef
  248. );
  249. if ((defined $COPT{'NEED_ALL'}) && (defined $COPT{'NEED_MUNGE_PUBLIC'})) {
  250. errmsg("Error options! Please specify either -m or -t");
  251. exit(1);
  252. }
  253. $FileScope = "*.*" if ("$FileScope" eq "");
  254. # if neither is official build machine, nor assign -t in command line,
  255. # or if is official build machine, but assign -m in command line,
  256. #
  257. # we will only munge public symbols
  258. #
  259. # if (((!exists $ENV{'OFFICIAL_BUILD_MACHINE'}) &&
  260. # (!defined $COPT{'NEED_ALL'})) ||
  261. # ((exists $ENV{'OFFICIAL_BUILD_MACHINE'}) &&
  262. # (defined $COPT{'NEED_MUNGE_PUBLIC'}))) {
  263. # @SOPT{qw(NEED_MUNGE_PUBLIC
  264. # NEED_CREATE_SYMBOLCD_TXT
  265. # NEED_CREATE_MAKE_FILE
  266. # NEED_CREATE_SYMBOLCAT
  267. # NEED_CREATE_SYMBOLCAB
  268. # NEED_SIGN_FILES)} = (1, undef, undef, undef, undef, undef);
  269. # }
  270. # if ($SOPT{'NEED_CLEAN_BUILD'}) {
  271. # rmtree([@SDIR{qw(FULL_DDF FULL_CD FULL_CAB UPDATE_DDF UPDATE_CD UPDATE_CAB)}]);
  272. # }
  273. }
  274. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  275. #
  276. # Small Subroutine
  277. #
  278. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  279. #
  280. # IsSymchkFailed($binary, $symbol, $extraopt)
  281. # - call symchk.exe to verify $binary matches with $symbol
  282. #
  283. sub IsSymchkFailed {
  284. my ($binary, $symbol, $extraopt) = @_;
  285. my ($fh, $record_error, $record_log, $result);
  286. local $_;
  287. if (defined $extraopt) {
  288. if ($extraopt =~ /2\>/) {
  289. $record_error = 1;
  290. }
  291. if ($extraopt =~ /[^2]\>/) {
  292. $record_log = 1;
  293. }
  294. $extraopt =~ s/2?\>.*$//g;
  295. }
  296. $fh = new IO::File "$ST{'CHECK'} /t $binary /s $symbol $extraopt |";
  297. while (<$fh>) {
  298. chomp;
  299. $result = $1 if /FAILED files = (\d+)/;
  300. logmsg($_) if ($record_log);
  301. logmsg($_) if (($record_error) && (/^ERROR/i));
  302. }
  303. undef $fh;
  304. return $result;
  305. }
  306. #
  307. # SymbolPath($root, $subdir, $filename)
  308. # - return the symbol path for the binary
  309. #
  310. sub SymbolPath
  311. {
  312. my ($root, $subdir, $filename) = @_;
  313. $root .= "\\$subdir" if (!$SOPT{'FLAT_SYMBOL_PATH'});
  314. if (defined $filename) {
  315. $filename =~ /\.([^\.]+)$/;
  316. $root .= "\\$1\\$`";
  317. return "$root\.pdb" if (-e "$root\.pdb");
  318. return "$root\.dbg" if (-e "$root\.dbg");
  319. $root .= ".pdb";
  320. }
  321. return $root;
  322. }
  323. #
  324. # Full_Package_Path($root, $myarch, $mytype)
  325. # - for compatible reason, we create a function to construct the path of the symbols.exe of the full package
  326. #
  327. sub Full_Package_Path
  328. {
  329. my ($root, $myarch, $mytype) = @_;
  330. $mytype =~ s/fre/retail/ig;
  331. $mytype =~ s/chk/debug/ig;
  332. return "$root\\$myarch\\$mytype"; # temporary
  333. }
  334. #
  335. # Update_Package_Path($root, $myarch, $mytype)
  336. # - for compatible reason, we create a function to construct the path of the symbols.exe of the update package
  337. #
  338. sub Update_Package_Path
  339. {
  340. my ($root, $myarch, $mytype) = @_;
  341. return $root; # \\$myarch\\$mytype"; # temporary
  342. }
  343. #
  344. # IsVC7PDB($pdbspec)
  345. # - because the MD5 hash value is 0000-0000-0000-000000000000 for the symbols built by VC6 or older
  346. # - we can use it to determine the pdb is VC7 or not
  347. #
  348. sub IsVC7PDB {
  349. my ($pdbspec) = shift;
  350. my $fh = new IO::File "$ST{'DUMP'} $pdbspec hdr |";
  351. local $_;
  352. while (<$fh>) {
  353. return 0 if /0000-0000-0000-000000000000/i;
  354. }
  355. return 1;
  356. }
  357. #
  358. # Check_Exist_File($filename, $logfile)
  359. # - this is a function generator, which generates a function for checking the $filename exist or not
  360. # - it also check if the $logfile has 'ERROR:' in it
  361. #
  362. sub Check_Exist_File
  363. {
  364. my ($filename, $logfile) = @_;
  365. return sub {
  366. if (-e $filename) {
  367. return 1;
  368. } else {
  369. my $fh = new IO::File $logfile;
  370. for (<$fh>) {
  371. chomp;
  372. next if (!/.+ERROR\: /i);
  373. errmsg("Error - $'");
  374. }
  375. $fh->close();
  376. logmsg("$filename did not get created.");
  377. return 0;
  378. }
  379. };
  380. }
  381. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  382. #
  383. # Common Subroutine
  384. #
  385. # * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
  386. sub FileParse
  387. {
  388. my ($name, $path, $ext) = fileparse(shift, '\.[^\.]+$');
  389. $ext =~ s/^\.//;
  390. return $name, $path, $ext;
  391. }
  392. sub IsUSA
  393. {
  394. # return (lc$ENV{'lang'} eq 'usa');
  395. return 1;
  396. }
  397. sub Exists
  398. {
  399. my @list = glob(shift);
  400. return (wantarray)?@list:$#list + 1;
  401. }
  402. 1;
  403. __END__