~ubuntu-branches/ubuntu/trusty/enigmail/trusty-updates

« back to all changes in this revision

Viewing changes to tools/rb/fix-macosx-stack.pl

  • Committer: Package Import Robot
  • Author(s): Chris Coulson
  • Date: 2011-06-07 14:35:53 UTC
  • mfrom: (0.12.1 upstream)
  • Revision ID: package-import@ubuntu.com-20110607143553-fbgqhhvh8g8h6j1y
Tags: 2:1.2~a2~cvs20110606t2200-0ubuntu1
* Update to latest trunk snapshot for Thunderbird beta compat

* Remove build/pgo/profileserver.py from debian/clean. The new build
  system has a target depending on this
  - update debian/clean
* Drop debian/patches/autoconf.diff, just generate this at build time
* Refresh debian/patches/build_system_dont_link_libxul.diff
* libipc seems to be renamed to libipc-pipe. Fix genxpi and chrome.manifest
  to fix this 
  - add debian/patches/ipc-pipe_rename.diff
  - update debian/patches/series
* The makefiles in extensions/enigmail/ipc have an incorrect DEPTH
  attribute. Fix this so that they can find the rest of the build system
  - add debian/patches/makefile_depth.diff
  - update debian/patches/series
* Drop debian/patches/makefile-in-empty-xpcom-fix.diff - fixed in the
  current version
* Don't register a class ID multiple times, as this breaks enigmail entirely
  - add debian/patches/dont_register_cids_multiple_times.diff
  - update debian/patches/series
* Look for the Thunderbird 5 SDK
  - update debian/rules
  - update debian/control
* Run autoconf2.13 at build time
  - update debian/rules
  - update debian/control
* Add useless mesa-common-dev build-dep, just to satisfy the build system.
  We should just patch this out entirely really, but that's for another upload
  - update debian/control

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/perl
 
2
# vim:sw=4:ts=4:et:
 
3
# ***** BEGIN LICENSE BLOCK *****
 
4
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
5
#
 
6
# The contents of this file are subject to the Mozilla Public License Version
 
7
# 1.1 (the "License"); you may not use this file except in compliance with
 
8
# the License. You may obtain a copy of the License at
 
9
# http://www.mozilla.org/MPL/
 
10
#
 
11
# Software distributed under the License is distributed on an "AS IS" basis,
 
12
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
13
# for the specific language governing rights and limitations under the
 
14
# License.
 
15
#
 
16
# The Original Code is fix-linux-stack.pl.
 
17
#
 
18
# The Initial Developer of the Original Code is L. David Baron.
 
19
# Portions created by the Initial Developer are Copyright (C) 2003
 
20
# the Initial Developer. All Rights Reserved.
 
21
#
 
22
# Contributor(s):
 
23
#   L. David Baron <dbaron@dbaron.org> (original author)
 
24
#
 
25
# Alternatively, the contents of this file may be used under the terms of
 
26
# either the GNU General Public License Version 2 or later (the "GPL"), or
 
27
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
28
# in which case the provisions of the GPL or the LGPL are applicable instead
 
29
# of those above. If you wish to allow use of your version of this file only
 
30
# under the terms of either the GPL or the LGPL, and not to allow others to
 
31
# use your version of this file under the terms of the MPL, indicate your
 
32
# decision by deleting the provisions above and replace them with the notice
 
33
# and other provisions required by the GPL or the LGPL. If you do not delete
 
34
# the provisions above, a recipient may use your version of this file under
 
35
# the terms of any one of the MPL, the GPL or the LGPL.
 
36
#
 
37
# ***** END LICENSE BLOCK *****
 
38
 
 
39
# $Id: fix-macosx-stack.pl,v 1.6 2007/08/17 06:26:09 dbaron%dbaron.org Exp $
 
40
#
 
41
# This script processes the output of nsTraceRefcnt's Mac OS X stack
 
42
# walking code.  This is useful for two things:
 
43
#  (1) Getting line number information out of
 
44
#      |nsTraceRefcntImpl::WalkTheStack|'s output in debug builds.
 
45
#  (2) Getting function names out of |nsTraceRefcntImpl::WalkTheStack|'s
 
46
#      output on all builds (where it mostly prints UNKNOWN because only
 
47
#      a handful of symbols are exported from component libraries).
 
48
#
 
49
# Use the script by piping output containing stacks (such as raw stacks
 
50
# or make-tree.pl balance trees) through this script.
 
51
 
 
52
use strict;
 
53
use IPC::Open2;
 
54
 
 
55
sub separate_debug_file_for($) {
 
56
    my ($file) = @_;
 
57
    return '';
 
58
}
 
59
 
 
60
my %address_adjustments;
 
61
sub address_adjustment($) {
 
62
    my ($file) = @_;
 
63
    unless (exists $address_adjustments{$file}) {
 
64
        my $result = -1;
 
65
 
 
66
        open(OTOOL, '-|', 'otool', '-l', $file);
 
67
        while (<OTOOL>) {
 
68
            if (/^  segname __TEXT$/) {
 
69
                if (<OTOOL> =~ /^   vmaddr (0x[0-9a-f]{8})$/) {
 
70
                    $result = hex($1);
 
71
                    last;
 
72
                } else {
 
73
                    die "Bad output from otool";
 
74
                }
 
75
            }
 
76
        }
 
77
        close(OTOOL);
 
78
 
 
79
        $result >= 0 || die "Bad output from otool";
 
80
 
 
81
        $address_adjustments{$file} = $result;
 
82
    }
 
83
 
 
84
    return $address_adjustments{$file};
 
85
}
 
86
 
 
87
sub add_info($$$) {
 
88
    my ($array, $address, $data) = @_;
 
89
 
 
90
    # only remember the last item at a given address
 
91
    pop @{$array} if ($#{$array} >= 0 && $array->[$#{$array}]->[0] == $address);
 
92
 
 
93
    push @{$array}, [ $address, $data ];
 
94
}
 
95
 
 
96
sub sort_by_address() {
 
97
    return $a->[0] <=> $b->[0];
 
98
}
 
99
 
 
100
# Return a reference to a hash whose {read} and {write} entries are a
 
101
# bidirectional pipe to an addr2line process that gives symbol
 
102
# information for a file.
 
103
my %nmstructs;
 
104
sub nmstruct_for($) {
 
105
    my ($file) = @_;
 
106
    my $nmstruct;
 
107
    my $curdir;
 
108
    unless (exists $nmstructs{$file}) {
 
109
        $nmstruct = { symbols => [], files => [], lines => [] };
 
110
 
 
111
        my $debug_file = separate_debug_file_for($file);
 
112
        $debug_file = $file if ($debug_file eq '');
 
113
 
 
114
        open(NM, '-|', 'nm', '-an', $debug_file);
 
115
        while (<NM>) {
 
116
            chomp;
 
117
            my ($addr, $ty, $rest) = ($_ =~ /^([0-9a-f ]{8}) (.) (.*)$/);
 
118
            $addr = hex($addr);
 
119
            if ($ty eq 't' || $ty eq 'T') {
 
120
                my $sym = $rest;
 
121
                if (substr($sym, 0, 1) eq '_') {
 
122
                    # symbols on Mac have an extra leading _
 
123
                    $sym = substr($sym, 1);
 
124
                }
 
125
                add_info($nmstruct->{symbols}, $addr, $sym);
 
126
            } elsif ($ty eq '-') {
 
127
                # nm gives us stabs debugging information
 
128
                my ($n1, $n2, $ty2, $rest2) =
 
129
                    ($rest =~ /^([0-9a-f]{2}) ([0-9a-f]{4}) (.{5}) (.*)$/);
 
130
                # ignore $ty2 == '  FUN'
 
131
                if ($ty2 eq 'SLINE') {
 
132
                    add_info($nmstruct->{lines}, $addr, hex($n2));
 
133
                } elsif ($ty2 eq '  SOL') {
 
134
                    # We get SOL lines within the code for a source
 
135
                    # file.  They always have file names.
 
136
                    my $file = $rest2;
 
137
                    if (!($file =~ /^\//)) {
 
138
                        # resolve relative paths
 
139
                        $file = $curdir . $file;
 
140
                    }
 
141
                    add_info($nmstruct->{files}, $addr, $file);
 
142
                } elsif ($ty2 eq '   SO') {
 
143
                    # We get SO lines at the beginning of the code for a
 
144
                    # source file, for:
 
145
                    #  * the directory of the compilation
 
146
                    #  * the file
 
147
                    #  * sometimes a blank line
 
148
                    if ($rest2 =~ /\/$/) {
 
149
                        $curdir = $rest2;
 
150
                    } elsif ($rest2 ne '') {
 
151
                        add_info($nmstruct->{files}, $addr, $rest2);
 
152
                    }
 
153
                }
 
154
            }
 
155
        }
 
156
        close(NM);
 
157
 
 
158
        # nm -n Doesn't sort across .o files.
 
159
        @{$nmstruct->{symbols}} = sort sort_by_address @{$nmstruct->{symbols}};
 
160
        @{$nmstruct->{lines}} = sort sort_by_address @{$nmstruct->{lines}};
 
161
        @{$nmstruct->{files}} = sort sort_by_address @{$nmstruct->{files}};
 
162
 
 
163
        $nmstructs{$file} = $nmstruct;
 
164
    } else {
 
165
        $nmstruct = $nmstructs{$file};
 
166
    }
 
167
    return $nmstruct;
 
168
}
 
169
 
 
170
my $cxxfilt_pipe;
 
171
sub cxxfilt($) {
 
172
    my ($sym) = @_;
 
173
 
 
174
    unless($cxxfilt_pipe) {
 
175
        my $pid = open2($cxxfilt_pipe->{read}, $cxxfilt_pipe->{write},
 
176
                        'c++filt', '--no-strip-underscores',
 
177
                                   '--format', 'gnu-v3');
 
178
    }
 
179
    my $out = $cxxfilt_pipe->{write};
 
180
    my $in = $cxxfilt_pipe->{read};
 
181
    print {$out} $sym . "\n";
 
182
    chomp(my $fixedsym = <$in>);
 
183
    return $fixedsym;
 
184
}
 
185
 
 
186
# binary search the array for the address
 
187
sub array_lookup($$) {
 
188
    my ($array, $address) = @_;
 
189
 
 
190
    my $start = 0;
 
191
    my $end = $#{$array};
 
192
 
 
193
    return [ -1 , "" ] if ($end == -1);
 
194
 
 
195
    while ($start != $end) {
 
196
        my $test = int(($start + $end + 1) / 2); # may equal $end
 
197
        # Since we're processing stack traces, and the addresses in
 
198
        # stack traces are the instructions to return to, and we really
 
199
        # want the instruction that made the call (the previous
 
200
        # instruction), use > instead of >=.
 
201
        if ($address > $array->[$test]->[0]) {
 
202
            $start = $test;
 
203
        } else {
 
204
            $end = $test - 1;
 
205
        }
 
206
    }
 
207
 
 
208
    return $array->[$start];
 
209
}
 
210
 
 
211
sub nm_lookup($$) {
 
212
    my ($nmstruct, $address) = @_;
 
213
    my $sym = array_lookup($nmstruct->{symbols}, $address);
 
214
    return {
 
215
             symbol => cxxfilt($sym->[1]),
 
216
             symbol_offset => ($address - $sym->[0]),
 
217
             file => array_lookup($nmstruct->{files}, $address)->[1],
 
218
             line => array_lookup($nmstruct->{lines}, $address)->[1]
 
219
           };
 
220
}
 
221
 
 
222
select STDOUT; $| = 1; # make STDOUT unbuffered
 
223
while (<>) {
 
224
    my $line = $_;
 
225
    if ($line =~ /^([ \|0-9-]*)(.*) ?\[([^ ]*) \+(0x[0-9A-F]{1,8})\](.*)$/) {
 
226
        my $before = $1; # allow preservation of balance trees
 
227
        my $badsymbol = $2;
 
228
        my $file = $3;
 
229
        my $address = hex($4);
 
230
        my $after = $5; # allow preservation of counts
 
231
 
 
232
        if (-f $file) {
 
233
            my $nmstruct = nmstruct_for($file);
 
234
            $address += address_adjustment($file);
 
235
 
 
236
            my $info = nm_lookup($nmstruct, $address);
 
237
            my $symbol = $info->{symbol};
 
238
            my $fileandline = $info->{file} . ':' . $info->{line};
 
239
 
 
240
            # I'm not sure if it's possible for dlsym to have gotten
 
241
            # better information, but just in case:
 
242
            if (my ($offset) = ($badsymbol =~ /\+0x([0-9A-F]{8})/)) { # FIXME: add $
 
243
                if (hex($offset) < $info->{symbol_offset}) {
 
244
                    $symbol = $badsymbol;
 
245
                }
 
246
            }
 
247
 
 
248
            if ($fileandline eq ':') { $fileandline = $file; }
 
249
            print "$before$symbol ($fileandline)$after\n";
 
250
        } else {
 
251
            print STDERR "Warning: File \"$file\" does not exist.\n";
 
252
            print $line;
 
253
        }
 
254
 
 
255
    } else {
 
256
        print $line;
 
257
    }
 
258
}