Recommendations for strip(1)? Was: gdb: "No line number info...."
Recommendations for strip(1)? Was: gdb: "No line number info...."
- Subject: Recommendations for strip(1)? Was: gdb: "No line number info...."
- From: Jerry Krinock <email@hidden>
- Date: Sat, 15 Aug 2009 23:31:13 -0700
On 2009 Jul 29, at 06:48, Thierry Faucounau wrote:
This will happen for me if I build Release twice in a row without
deleting the application in between. What happens is...
Thierry hit the nail on the head here, although I'm unable to always
reproduce the problem on the second build -- sometimes it takes
three. With several dependent frameworks and bundles producing a half
dozen dSYM files, accounting gets pretty complicated. I filed a bug,
7145893 [1].
So we conclude that the "strip" settings in Xcode 3.1.2 are broken/
dangerous, and we have two proposed workarounds:
Thierry's workaround:
build [only] after a full clean (or at least delete the application
binary so Xcode re-links it and puts the symbols back in)
Alastair's workaround:
copy the built product into a separate folder and then strip it there
I like Alastair's better. I presume that I would do this using
strip(1), i.e. /Developer/usr/bin/strip. Correct? But reading in man
strip I see the following statement which implies that ld(1) can do a
better job of stripping than strip(1):
"The link editor ld(1) is the only program that can strip relocation
entries and know if it is safe to do so."
I've not read enough to understand that yet. Does this weakness of
strip(1) relative to stripping by ld(1) concern anyone?
Also, if someone would like to share which of the half dozen or so
"stripping strength" options of strip(1) are recommended for a plain
old Cocoa application, and/or for private frameworks and helpers
within such a Cocoa application, it would provide some nice data
points :)
Jerry Krinock
P.S. Probably I'm fighting the last war, but in testing this I put
together and have attached a little Perl script which will check the
dSYM files for the constituent executable files in an app bundle:
#!/usr/bin/perl
use strict ;
require File::Util ;
if (@ARGV != 1) {
die "Usage:\n checkdSYMS.pl /path/to/MyApp.app\nThis .app's parent directory should also contain the .dSYM files for the app's main executable and any constituent auxiliary executables, frameworks, loadable bundles, etc. This is of course where they are normally deposited, if the parent directory is your Xcode \"Builds\" directory. Specifically, this script will find executables in all the \"normal\" places -- the main executable, auxiliary executables in Contents/MacOS, auxiliary executables in Contents/Helpers, frameworks in Contents/Frameworks, and helpers or loadable bundles in Contents/Resources. If you've got something weird like nested frameworks, it won't find those.\n" ;
}
my @components = split ("/", $ARGV[0]) ;
my $appName = @components[@components - 1] ;
$appName = substr($appName, 0, length($appName) - 4) ;
my $buildsReleasePath = substr($ARGV[0], 0, length($ARGV[0]) - 4 - length($appName)) ;
printf ("Will check dSYM files for executables in $appName.app\n") ;
printf (" in directory: $buildsReleasePath\n") ;
# Extract architectures from main executable
my $mainAppExecutable = "$buildsReleasePath$appName.app/Contents/MacOS/$appName" ;
my $otoolOutput = `/Developer/usr/bin/otool -fv "$mainAppExecutable"` ;
my @otoolLines = split("\n", $otoolOutput) ;
my @archLines = grep(/architecture /, @otoolLines) ;
my @architectures ;
foreach my $archLine (@archLines) {
$archLine =~ s/architecture // ;
push (@architectures, $archLine) ;
}
print "Main Executable \"$appName\" supports architectures:\n" ;
foreach my $arch (@architectures) {
printf " $arch\n" ;
}
my $fileUtil = File::Util->new() ;
my @rawNames ;
my $i ;
my @dSymNames ;
# Next, the executables in Contents/MacOS. This directory had better exist, so we don't check for it.
my @executableNames ;
push @dSymNames, "$appName.app" ;
my $dirPath = "$buildsReleasePath$appName.app/Contents/MacOS" ;
# Script will fail here if Contents/MacOS does not exist:
my @rawNames = $fileUtil->list_dir($dirPath, qw/--no-fsdots --files-only/) ;
for ($i=0; $i<@rawNames; $i++) {
# Exclude the application itself, because we've already got it -- with a .app extension
if ($rawNames[$i] ne $appName) {
push @dSymNames, $rawNames[$i] ;
}
}
# Next, any executables in Contents/Helpers
$dirPath = "$buildsReleasePath$appName.app/Contents/Helpers" ;
if ($fileUtil->existent($dirPath)) {
@rawNames = $fileUtil->list_dir($dirPath, qw/--no-fsdots --files-only/) ;
for ($i=0; $i<@rawNames; $i++) {
push @dSymNames, $rawNames[$i] ;
}
}
# Next, any helper apps or loadable bundles in Contents/Resources
$dirPath = "$buildsReleasePath$appName.app/Contents/Resources" ;
if ($fileUtil->existent($dirPath)) {
@rawNames = $fileUtil->list_dir($dirPath, qw/--no-fsdots --dirs-only/) ;
my $dotApp = ".app" ;
my $dotAppLength = length($dotApp) ;
my $dotBundle = ".bundle" ;
my $dotBundleLength = length($dotBundle) ;
for ($i=0; $i<@rawNames; $i++) {
# Only process names that have suffix $dotApp or $dotBundle
if (index($rawNames[$i], $dotApp, length($rawNames[$i]) - $dotAppLength) > 0) {
push @dSymNames, $rawNames[$i] ;
}
elsif (index($rawNames[$i], $dotBundle, length($rawNames[$i]) - $dotBundleLength) > 0) {
push @dSymNames, $rawNames[$i] ;
}
}
}
# Next, any executables in the Contents/Frameworks
$dirPath = "$buildsReleasePath$appName.app/Contents/Frameworks" ;
if ($fileUtil->existent($dirPath)) {
my @frameworkNames = $fileUtil->list_dir($dirPath, qw/--no-fsdots --dirs-only/) ;
for ($i=0; $i<@frameworkNames; $i++) {
my $frameworkDirPath = $dirPath . "/" . $frameworkNames[$i] ;
@rawNames = $fileUtil->list_dir($frameworkDirPath, qw/--no-fsdots --files-only/) ;
for (my $j=0; $j<@rawNames; $j++) {
push @dSymNames, ($rawNames[$j] . ".framework") ;
}
}
}
my $n = @dSymNames ;
print "Checking dSYM files...\n" ;
my $trouble = 0 ;
foreach my $dSymName (@dSymNames) {
printf " $dSymName\n" ;
my $dSymPath = $buildsReleasePath . $dSymName . ".dSYM" ;
if ($fileUtil->existent($dSymPath)) {
my $firstArch = 1 ;
my $nSourceFiles ;
foreach my $arch (@architectures) {
my $nSourceFilesThis = 0 ;
my $dwarfDump ;
$_ = `/Developer/usr/bin/dwarfdump --arch=$arch -r0 "$dSymPath"` ;
# Count the number of occurrences of the string "Compile Unit: "
$nSourceFilesThis = s/Compile Unit: //g ;
if (length($nSourceFilesThis) == 0) {
$nSourceFilesThis = 0 ;
$trouble = 1 ;
printf " Whoops! 0 source files dSYMed for arch=$arch.\n" ;
}
else {
printf " $nSourceFilesThis source files dSYMed for arch=$arch.\n" ;
}
if ($firstArch) {
$nSourceFiles = $nSourceFilesThis ;
$firstArch = 0 ;
}
elsif ($nSourceFiles != $nSourceFilesThis) {
printf " Whoops! Different arch has dSYMed different count of source files.\n" ;
$trouble = 1 ;
}
}
}
else {
printf " Whoops! No dSYM file for $dSymName\n" ;
$trouble = 1 ;
}
}
print("\n") ;
if ($trouble) {
printf "You've got trouble with one or more dSYM files! (See above.)\n" ;
exit(1) ;
}
printf "All dSYM files appear to be OK.\n" ;
[1] Apple Bug 7145893
Summary: Xcode can produce empty dSYM files in normal usage. I have
shipped products thinking I had dSYM files but then have been unable
to symbolize.
Steps to Reproduce:
1. Create an application project containing several private
frameworks, loadable code bundles, etc.
2. Set configuration to Release.
3. In the application target's Build Settings, set the Release
configuration of the application project to strip the executables, and
produce DWARF dSYM files.
4. Clean the target.
5. Build the target. Result: You get a stripped product, and dSYM
files populated with symbols.
6. Build the application one or sometimes two more times.
Expected Results:
A stripped product, and dSYM files populated with symbols.
Actual Results: Some of the dSYM files have no symbols in them.
Notes: Sometimes you get a warning of "No debug symbols in executable"
in the Build Transcript, and sometimes you don't. But this warning is
not good enough anyhow. This should "just work". Here is one of the
ways that this can happen: The first command to build will build and
link the application, then create dSYM files, and then strip the
application. The second or third build command will skip building and
linking since it is up to date, but will sometimes still create one or
more dSYM files which will be empty since the executables have now
been stripped.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Xcode-users mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden