Skip to content

Commit 94adb30

Browse files
committed
Bug 1062709 (part 2, attempt 2) - Clean up stack printing and fixing. r=dbaron.
--HG-- extra : rebase_source : 626fd23a14ec90cfc9807c3d555169ec6463d19d
1 parent 2eb5600 commit 94adb30

File tree

11 files changed

+119
-144
lines changed

11 files changed

+119
-144
lines changed

security/sandbox/win/src/warnonlysandbox/wosCallbacks.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,9 @@ StackFrameToOStringStream(uint32_t aFrameNumber, void* aPC, void* aSP,
6666
nsCodeAddressDetails details;
6767
char buf[1024];
6868
NS_DescribeCodeAddress(aPC, &details);
69-
NS_FormatCodeAddressDetails(aFrameNumber, aPC, &details, buf, sizeof(buf));
70-
*stream << "--" << buf;
69+
NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
70+
*stream << "--" << buf << '\n';
71+
stream->flush();
7172
}
7273
#endif
7374

toolkit/xre/nsSigHandlers.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,9 @@ static void PrintStackFrame(uint32_t aFrameNumber, void *aPC, void *aSP,
6363
nsCodeAddressDetails details;
6464

6565
NS_DescribeCodeAddress(aPC, &details);
66-
NS_FormatCodeAddressDetails(aFrameNumber, aPC, &details, buf, sizeof(buf));
67-
fputs(buf, stdout);
66+
NS_FormatCodeAddressDetails(buf, sizeof(buf), aFrameNumber, aPC, &details);
67+
fprintf(stdout, "%s\n", buf);
68+
fflush(stdout);
6869
}
6970

7071
}

tools/rb/fix_linux_stack.py

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -4,18 +4,9 @@
44
# License, v. 2.0. If a copy of the MPL was not distributed with this
55
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
66

7-
# This script uses addr2line (part of binutils) to process the output of
8-
# nsTraceRefcnt's Linux stack walking code. This is useful for two
9-
# things:
10-
# (1) Getting line number information out of
11-
# |nsTraceRefcnt::WalkTheStack|'s output in debug builds.
12-
# (2) Getting function names out of |nsTraceRefcnt::WalkTheStack|'s
13-
# output on optimized builds (where it mostly prints UNKNOWN
14-
# because only a handful of symbols are exported from component
15-
# libraries).
16-
#
17-
# Use the script by piping output containing stacks (such as raw stacks
18-
# or make-tree.pl balance trees) through this script.
7+
# This script uses addr2line (part of binutils) to post-process the entries
8+
# produced by NS_FormatCodeAddress(), which on Linux often lack a function
9+
# name, a file name and a line number.
1910

2011
import subprocess
2112
import sys
@@ -296,25 +287,20 @@ def addressToSymbol(file, address):
296287
cache[address] = result
297288
return result
298289

299-
line_re = re.compile("^(.*) ?\[([^ ]*) \+(0x[0-9A-F]{1,8})\](.*)$")
300-
balance_tree_re = re.compile("^([ \|0-9-]*)(.*)$")
290+
# Matches lines produced by NS_FormatCodeAddress().
291+
line_re = re.compile("^(.*#\d+: )(.+)\[(.+) \+(0x[0-9A-Fa-f]+)\](.*)$")
301292

302293
def fixSymbols(line):
303294
result = line_re.match(line)
304295
if result is not None:
305-
# before allows preservation of balance trees
306-
# after allows preservation of counts
307-
(before, file, address, after) = result.groups()
296+
(before, fn, file, address, after) = result.groups()
308297

309298
if os.path.exists(file) and os.path.isfile(file):
310-
# throw away the bad symbol, but keep balance tree structure
311-
(before, badsymbol) = balance_tree_re.match(before).groups()
312-
313299
(name, fileline) = addressToSymbol(file, address)
314300

315301
# If addr2line gave us something useless, keep what we had before.
316302
if name == "??":
317-
name = badsymbol
303+
name = fn
318304
if fileline == "??:0" or fileline == "??:?":
319305
fileline = file
320306

tools/rb/fix_macosx_stack.py

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,9 @@
44
# License, v. 2.0. If a copy of the MPL was not distributed with this
55
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
66

7-
# This script uses atos to process the output of nsTraceRefcnt's Mac OS
8-
# X stack walking code. This is useful for two things:
9-
# (1) Getting line number information out of
10-
# |nsTraceRefcnt::WalkTheStack|'s output in debug builds.
11-
# (2) Getting function names out of |nsTraceRefcnt::WalkTheStack|'s
12-
# output on all builds (where it mostly prints UNKNOWN because only
13-
# a handful of symbols are exported from component libraries).
14-
#
15-
# Use the script by piping output containing stacks (such as raw stacks
16-
# or make-tree.pl balance trees) through this script.
7+
# This script uses |atos| to post-process the entries produced by
8+
# NS_FormatCodeAddress(), which on Mac often lack a file name and a line
9+
# number.
1710

1811
import subprocess
1912
import sys
@@ -99,16 +92,14 @@ def cxxfilt(sym):
9992
cxxfilt_proc.stdin.write(sym + "\n")
10093
return cxxfilt_proc.stdout.readline().rstrip("\n")
10194

102-
line_re = re.compile("^(.*) ?\[([^ ]*) \+(0x[0-9a-fA-F]{1,8})\](.*)$")
103-
balance_tree_re = re.compile("^([ \|0-9-]*)")
95+
# Matches lines produced by NS_FormatCodeAddress().
96+
line_re = re.compile("^(.*#\d+: )(.+)\[(.+) \+(0x[0-9A-Fa-f]+)\](.*)$")
10497
atos_name_re = re.compile("^(.+) \(in ([^)]+)\) \((.+)\)$")
10598

10699
def fixSymbols(line):
107100
result = line_re.match(line)
108101
if result is not None:
109-
# before allows preservation of balance trees
110-
# after allows preservation of counts
111-
(before, file, address, after) = result.groups()
102+
(before, fn, file, address, after) = result.groups()
112103
address = int(address, 16)
113104

114105
if os.path.exists(file) and os.path.isfile(file):
@@ -129,9 +120,6 @@ def fixSymbols(line):
129120
name = cxxfilt(name)
130121
info = "%s (%s, in %s)" % (name, fileline, library)
131122

132-
# throw away the bad symbol, but keep balance tree structure
133-
before = balance_tree_re.match(before).groups()[0]
134-
135123
nl = '\n' if line[-1] == '\n' else ''
136124
return before + info + after + nl
137125
else:

tools/rb/fix_stack_using_bpsyms.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@
44
# License, v. 2.0. If a copy of the MPL was not distributed with this
55
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
66

7+
# This script uses breakpad symbols to post-process the entries produced by
8+
# NS_FormatCodeAddress(), which on TBPL builds often lack a file name and a
9+
# line number (and on Linux even the symbol is often bad).
10+
711
from __future__ import with_statement
812

913
import sys
@@ -112,18 +116,14 @@ def addressToSymbol(file, address, symbolsDir):
112116
else:
113117
return ""
114118

115-
line_re = re.compile("^(.*) ?\[([^ ]*) \+(0x[0-9A-F]{1,16})\](.*)$")
116-
balance_tree_re = re.compile("^([ \|0-9-]*)")
119+
# Matches lines produced by NS_FormatCodeAddress().
120+
line_re = re.compile("^(.*#\d+: )(.+)\[(.+) \+(0x[0-9A-Fa-f]+)\](.*)$")
117121

118122
def fixSymbols(line, symbolsDir):
119123
result = line_re.match(line)
120124
if result is not None:
121-
# before allows preservation of balance trees
122-
# after allows preservation of counts
123-
(before, file, address, after) = result.groups()
125+
(before, fn, file, address, after) = result.groups()
124126
address = int(address, 16)
125-
# throw away the bad symbol, but keep balance tree structure
126-
before = balance_tree_re.match(before).groups()[0]
127127
symbol = addressToSymbol(file, address, symbolsDir)
128128
if not symbol:
129129
symbol = "%s + 0x%x" % (os.path.basename(file), address)

tools/rb/make-tree.pl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,16 @@ ($$$)
9797

9898
my $cnt = shift(@fields);
9999

100-
# Collect the remaining lines to create a stack trace.
100+
# Collect the remaining lines to create a stack trace. We need to
101+
# filter out the frame numbers so that frames that differ only in
102+
# their frame number are considered equivalent. However, we need to
103+
# keep a frame number on each line so that the fix*.py scripts can
104+
# parse the output. So we set the frame number to 0 for every frame.
101105
my @stack;
102106
CALLSITE: while (<$INFILE>) {
103107
chomp;
104108
last CALLSITE if (/^$/);
109+
$_ =~ s/#\d+: /#00: /; # replace frame number with 0
105110
$stack[++$#stack] = $_;
106111
}
107112

xpcom/base/CodeAddressService.h

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -89,12 +89,9 @@ class CodeAddressService
8989

9090
// Convert "" to nullptr. Otherwise, make a copy of the name.
9191
StringAlloc::free(mFunction);
92-
mFunction =
93-
!aFunction[0] ? nullptr : StringAlloc::copy(aFunction);
92+
mFunction = !aFunction[0] ? nullptr : StringAlloc::copy(aFunction);
9493
StringAlloc::free(mFileName);
95-
mFileName =
96-
!aFileName[0] ? nullptr : StringAlloc::copy(aFileName);
97-
94+
mFileName = !aFileName[0] ? nullptr : StringAlloc::copy(aFileName);
9895

9996
mLibrary = aLibrary;
10097
mLOffset = aLOffset;
@@ -166,26 +163,9 @@ class CodeAddressService
166163

167164
MOZ_ASSERT(entry.mPc == aPc);
168165

169-
uintptr_t entryPc = (uintptr_t)(entry.mPc);
170-
// Sometimes we get nothing useful. Just print "???" for the entire entry
171-
// so that fix_linux_stack.py doesn't complain about an empty filename.
172-
if (!entry.mFunction && !entry.mLibrary[0] && entry.mLOffset == 0) {
173-
snprintf(aBuf, aBufLen, "??? 0x%" PRIxPTR, entryPc);
174-
} else {
175-
// Use "???" for unknown functions.
176-
const char* entryFunction = entry.mFunction ? entry.mFunction : "???";
177-
if (entry.mFileName) {
178-
// On Windows we can get the filename and line number at runtime.
179-
snprintf(aBuf, aBufLen, "%s (%s:%u) 0x%" PRIxPTR,
180-
entryFunction, entry.mFileName, entry.mLineNo, entryPc);
181-
} else {
182-
// On Linux and Mac we cannot get the filename and line number at
183-
// runtime, so we print the offset in a form that fix_linux_stack.py and
184-
// fix_macosx_stack.py can post-process.
185-
snprintf(aBuf, aBufLen, "%s[%s +0x%" PRIXPTR "] 0x%" PRIxPTR,
186-
entryFunction, entry.mLibrary, entry.mLOffset, entryPc);
187-
}
188-
}
166+
NS_FormatCodeAddress(aBuf, aBufLen, aFrameNumber, entry.mPc,
167+
entry.mFunction, entry.mLibrary, entry.mLOffset,
168+
entry.mFileName, entry.mLineNo);
189169
}
190170

191171
size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const

xpcom/base/nsStackWalk.cpp

Lines changed: 42 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313

1414
#include "nsStackWalk.h"
1515

16+
#ifdef XP_WIN
17+
#define snprintf _snprintf
18+
#endif
19+
1620
using namespace mozilla;
1721

1822
// The presence of this address is the stack must stop the stack walk. If
@@ -827,39 +831,6 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
827831
return NS_OK;
828832
}
829833

830-
EXPORT_XPCOM_API(nsresult)
831-
NS_FormatCodeAddressDetails(uint32_t aFrameNumber, void* aPC,
832-
const nsCodeAddressDetails* aDetails,
833-
char* aBuffer, uint32_t aBufferSize)
834-
{
835-
if (aDetails->function[0]) {
836-
_snprintf(aBuffer, aBufferSize, "%s+0x%08lX [%s +0x%016lX]",
837-
aDetails->function, aDetails->foffset,
838-
aDetails->library, aDetails->loffset);
839-
} else if (aDetails->library[0]) {
840-
_snprintf(aBuffer, aBufferSize, "UNKNOWN [%s +0x%016lX]",
841-
aDetails->library, aDetails->loffset);
842-
} else {
843-
_snprintf(aBuffer, aBufferSize, "UNKNOWN 0x%016lX", aPC);
844-
}
845-
846-
aBuffer[aBufferSize - 1] = '\0';
847-
848-
uint32_t len = strlen(aBuffer);
849-
if (aDetails->filename[0]) {
850-
_snprintf(aBuffer + len, aBufferSize - len, " (%s, line %d)\n",
851-
aDetails->filename, aDetails->lineno);
852-
} else {
853-
aBuffer[len] = '\n';
854-
if (++len != aBufferSize) {
855-
aBuffer[len] = '\0';
856-
}
857-
}
858-
aBuffer[aBufferSize - 2] = '\n';
859-
aBuffer[aBufferSize - 1] = '\0';
860-
return NS_OK;
861-
}
862-
863834
// i386 or PPC Linux stackwalking code
864835
#elif HAVE_DLADDR && (HAVE__UNWIND_BACKTRACE || NSSTACKWALK_SUPPORTS_LINUX || NSSTACKWALK_SUPPORTS_MACOSX)
865836

@@ -1102,25 +1073,6 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
11021073
return NS_OK;
11031074
}
11041075

1105-
EXPORT_XPCOM_API(nsresult)
1106-
NS_FormatCodeAddressDetails(uint32_t aFrameNumber, void* aPC,
1107-
const nsCodeAddressDetails* aDetails,
1108-
char* aBuffer, uint32_t aBufferSize)
1109-
{
1110-
if (!aDetails->library[0]) {
1111-
snprintf(aBuffer, aBufferSize, "UNKNOWN %p\n", aPC);
1112-
} else if (!aDetails->function[0]) {
1113-
snprintf(aBuffer, aBufferSize, "UNKNOWN [%s +0x%08" PRIXPTR "]\n",
1114-
aDetails->library, aDetails->loffset);
1115-
} else {
1116-
snprintf(aBuffer, aBufferSize, "%s+0x%08" PRIXPTR
1117-
" [%s +0x%08" PRIXPTR "]\n",
1118-
aDetails->function, aDetails->foffset,
1119-
aDetails->library, aDetails->loffset);
1120-
}
1121-
return NS_OK;
1122-
}
1123-
11241076
#else // unsupported platform.
11251077

11261078
EXPORT_XPCOM_API(nsresult)
@@ -1154,13 +1106,44 @@ NS_DescribeCodeAddress(void* aPC, nsCodeAddressDetails* aDetails)
11541106
return NS_ERROR_NOT_IMPLEMENTED;
11551107
}
11561108

1157-
EXPORT_XPCOM_API(nsresult)
1158-
NS_FormatCodeAddressDetails(uint32_t aFrameNumber, void* aPC,
1159-
const nsCodeAddressDetails* aDetails,
1160-
char* aBuffer, uint32_t aBufferSize)
1109+
#endif
1110+
1111+
EXPORT_XPCOM_API(void)
1112+
NS_FormatCodeAddressDetails(char* aBuffer, uint32_t aBufferSize,
1113+
uint32_t aFrameNumber, void* aPC,
1114+
const nsCodeAddressDetails* aDetails)
11611115
{
1162-
aBuffer[0] = '\0';
1163-
return NS_ERROR_NOT_IMPLEMENTED;
1116+
NS_FormatCodeAddress(aBuffer, aBufferSize,
1117+
aFrameNumber, aPC, aDetails->function,
1118+
aDetails->library, aDetails->loffset,
1119+
aDetails->filename, aDetails->lineno);
1120+
}
1121+
1122+
EXPORT_XPCOM_API(void)
1123+
NS_FormatCodeAddress(char* aBuffer, uint32_t aBufferSize, uint32_t aFrameNumber,
1124+
const void* aPC, const char* aFunction,
1125+
const char* aLibrary, ptrdiff_t aLOffset,
1126+
const char* aFileName, uint32_t aLineNo)
1127+
{
1128+
const char* function = aFunction && aFunction[0] ? aFunction : "???";
1129+
if (aFileName && aFileName[0]) {
1130+
// We have a filename and (presumably) a line number. Use them.
1131+
snprintf(aBuffer, aBufferSize,
1132+
"#%02u: %s (%s:%u)",
1133+
aFrameNumber, function, aFileName, aLineNo);
1134+
} else if (aLibrary && aLibrary[0]) {
1135+
// We have no filename, but we do have a library name. Use it and the
1136+
// library offset, and print them in a way that scripts like
1137+
// fix_{linux,macosx}_stacks.py can easily post-process.
1138+
snprintf(aBuffer, aBufferSize,
1139+
"#%02u: %s[%s +0x%" PRIxPTR "]",
1140+
aFrameNumber, function, aLibrary, aLOffset);
1141+
} else {
1142+
// We have nothing useful to go on. (The format string is split because
1143+
// '??)' is a trigraph and causes a warning, sigh.)
1144+
snprintf(aBuffer, aBufferSize,
1145+
"#%02u: ??? (???:???" ")",
1146+
aFrameNumber);
1147+
}
11641148
}
11651149

1166-
#endif

0 commit comments

Comments
 (0)