Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
db018bf7
Commit
db018bf7
authored
Mar 04, 2013
by
Carl Shapiro
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
runtime: restrict stack root scan to locals and arguments
R=rsc CC=golang-dev
https://golang.org/cl/7301062
parent
6a752520
Changes
7
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
77 additions
and
57 deletions
+77
-57
src/pkg/runtime/mgc0.c
src/pkg/runtime/mgc0.c
+30
-29
src/pkg/runtime/mprof.goc
src/pkg/runtime/mprof.goc
+1
-1
src/pkg/runtime/proc.c
src/pkg/runtime/proc.c
+1
-1
src/pkg/runtime/runtime.h
src/pkg/runtime/runtime.h
+1
-1
src/pkg/runtime/sigqueue.goc
src/pkg/runtime/sigqueue.goc
+2
-1
src/pkg/runtime/traceback_arm.c
src/pkg/runtime/traceback_arm.c
+19
-10
src/pkg/runtime/traceback_x86.c
src/pkg/runtime/traceback_x86.c
+23
-14
No files found.
src/pkg/runtime/mgc0.c
View file @
db018bf7
...
...
@@ -1299,52 +1299,53 @@ addroot(Obj obj)
work
.
nroot
++
;
}
static
void
addframeroots
(
Func
*
f
,
byte
*
,
byte
*
sp
,
void
*
)
{
if
(
f
->
frame
>
sizeof
(
uintptr
))
addroot
((
Obj
){
sp
,
f
->
frame
-
sizeof
(
uintptr
),
0
});
if
(
f
->
args
>
0
)
addroot
((
Obj
){
sp
+
f
->
frame
,
f
->
args
,
0
});
}
static
void
addstackroots
(
G
*
gp
)
{
M
*
mp
;
int32
n
;
Stktop
*
stk
;
byte
*
sp
,
*
guard
;
stk
=
(
Stktop
*
)
gp
->
stackbase
;
guard
=
(
byte
*
)
gp
->
stackguard
;
Func
*
f
;
byte
*
sp
,
*
pc
;
if
(
gp
==
g
)
{
// Scanning our own stack: start at &gp.
sp
=
(
byte
*
)
&
gp
;
pc
=
runtime
·
getcallerpc
(
&
gp
);
}
else
if
((
mp
=
gp
->
m
)
!=
nil
&&
mp
->
helpgc
)
{
// gchelper's stack is in active use and has no interesting pointers.
return
;
}
else
if
(
gp
->
gcstack
!=
(
uintptr
)
nil
)
{
// Scanning another goroutine that is about to enter or might
// have just exited a system call. It may be executing code such
// as schedlock and may have needed to start a new stack segment.
// Use the stack segment and stack pointer at the time of
// the system call instead, since that won't change underfoot.
sp
=
(
byte
*
)
gp
->
gcsp
;
pc
=
gp
->
gcpc
;
}
else
{
// Scanning another goroutine's stack.
// The goroutine is usually asleep (the world is stopped).
sp
=
(
byte
*
)
gp
->
sched
.
sp
;
// The exception is that if the goroutine is about to enter or might
// have just exited a system call, it may be executing code such
// as schedlock and may have needed to start a new stack segment.
// Use the stack segment and stack pointer at the time of
// the system call instead, since that won't change underfoot.
if
(
gp
->
gcstack
!=
(
uintptr
)
nil
)
{
stk
=
(
Stktop
*
)
gp
->
gcstack
;
sp
=
(
byte
*
)
gp
->
gcsp
;
guard
=
(
byte
*
)
gp
->
gcguard
;
}
}
n
=
0
;
while
(
stk
)
{
if
(
sp
<
guard
-
StackGuard
||
(
byte
*
)
stk
<
sp
)
{
runtime
·
printf
(
"scanstack inconsistent: g%D#%d sp=%p not in [%p,%p]
\n
"
,
gp
->
goid
,
n
,
sp
,
guard
-
StackGuard
,
stk
);
runtime
·
throw
(
"scanstack"
);
pc
=
gp
->
sched
.
pc
;
if
(
pc
==
(
byte
*
)
runtime
·
goexit
&&
gp
->
fnstart
!=
nil
)
{
// The goroutine has not started. Its incoming
// arguments are at the top of the stack and must
// be scanned. No other data on the stack.
f
=
runtime
·
findfunc
((
uintptr
)
gp
->
fnstart
->
fn
);
if
(
f
->
args
>
0
)
addroot
((
Obj
){
sp
,
f
->
args
,
0
});
return
;
}
addroot
((
Obj
){
sp
,
(
byte
*
)
stk
-
sp
,
0
});
sp
=
(
byte
*
)
stk
->
gobuf
.
sp
;
guard
=
stk
->
stackguard
;
stk
=
(
Stktop
*
)
stk
->
stackbase
;
n
++
;
}
runtime
·
gentraceback
(
pc
,
sp
,
nil
,
gp
,
0
,
nil
,
0x7fffffff
,
addframeroots
,
nil
);
}
static
void
...
...
src/pkg/runtime/mprof.goc
View file @
db018bf7
...
...
@@ -511,7 +511,7 @@ saveg(byte *pc, byte *sp, G *gp, TRecord *r)
{
int32
n
;
n
=
runtime
·
gentraceback
(
pc
,
sp
,
0
,
gp
,
0
,
r
->
stk
,
nelem
(
r
->
stk
));
n
=
runtime
·
gentraceback
(
pc
,
sp
,
0
,
gp
,
0
,
r
->
stk
,
nelem
(
r
->
stk
)
,
nil
,
nil
);
if
(
n
<
nelem
(
r
->
stk
))
r
->
stk
[
n
]
=
0
;
}
...
...
src/pkg/runtime/proc.c
View file @
db018bf7
...
...
@@ -1710,7 +1710,7 @@ runtime·sigprof(uint8 *pc, uint8 *sp, uint8 *lr, G *gp)
runtime
·
unlock
(
&
prof
);
return
;
}
n
=
runtime
·
gentraceback
(
pc
,
sp
,
lr
,
gp
,
0
,
prof
.
pcbuf
,
nelem
(
prof
.
pcbuf
));
n
=
runtime
·
gentraceback
(
pc
,
sp
,
lr
,
gp
,
0
,
prof
.
pcbuf
,
nelem
(
prof
.
pcbuf
)
,
nil
,
nil
);
if
(
n
>
0
)
prof
.
fn
(
prof
.
pcbuf
,
n
);
runtime
·
unlock
(
&
prof
);
...
...
src/pkg/runtime/runtime.h
View file @
db018bf7
...
...
@@ -748,7 +748,7 @@ void runtime·exitsyscall(void);
G
*
runtime
·
newproc1
(
FuncVal
*
,
byte
*
,
int32
,
int32
,
void
*
);
bool
runtime
·
sigsend
(
int32
sig
);
int32
runtime
·
callers
(
int32
,
uintptr
*
,
int32
);
int32
runtime
·
gentraceback
(
byte
*
,
byte
*
,
byte
*
,
G
*
,
int32
,
uintptr
*
,
int32
);
int32
runtime
·
gentraceback
(
byte
*
,
byte
*
,
byte
*
,
G
*
,
int32
,
uintptr
*
,
int32
,
void
(
*
fn
)(
Func
*
,
byte
*
,
byte
*
,
void
*
),
void
*
arg
);
int64
runtime
·
nanotime
(
void
);
void
runtime
·
dopanic
(
int32
);
void
runtime
·
startpanic
(
void
);
...
...
src/pkg/runtime/sigqueue.goc
View file @
db018bf7
...
...
@@ -83,7 +83,8 @@ runtime·sigsend(int32 s)
func
signal_recv
()
(
m
uint32
)
{
static
uint32
recv
[
nelem
(
sig
.
mask
)];
uint32
i
,
old
,
new
;
g
->
issystem
=
true
;
for
(;;)
{
//
Serve
from
local
copy
if
there
are
bits
left
.
for
(
i
=
0
;
i
<
NSIG
;
i
++)
{
...
...
src/pkg/runtime/traceback_arm.c
View file @
db018bf7
...
...
@@ -17,9 +17,9 @@ void _divu(void);
void
_modu
(
void
);
int32
runtime
·
gentraceback
(
byte
*
pc0
,
byte
*
sp
,
byte
*
lr0
,
G
*
gp
,
int32
skip
,
uintptr
*
pcbuf
,
int32
max
)
runtime
·
gentraceback
(
byte
*
pc0
,
byte
*
sp
,
byte
*
lr0
,
G
*
gp
,
int32
skip
,
uintptr
*
pcbuf
,
int32
max
,
void
(
*
fn
)(
Func
*
,
byte
*
,
byte
*
,
void
*
),
void
*
arg
)
{
int32
i
,
n
,
iter
;
int32
i
,
n
;
uintptr
pc
,
lr
,
tracepc
,
x
;
byte
*
fp
;
bool
waspanic
;
...
...
@@ -46,7 +46,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
n
=
0
;
stk
=
(
Stktop
*
)
gp
->
stackbase
;
for
(
iter
=
0
;
iter
<
100
&&
n
<
max
;
iter
++
)
{
// iter avoids looping forever
while
(
n
<
max
)
{
// Typically:
// pc is the PC of the running function.
// sp is the stack pointer at that program counter.
...
...
@@ -60,14 +60,17 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
sp
=
(
byte
*
)
stk
->
gobuf
.
sp
;
lr
=
0
;
fp
=
nil
;
if
(
pcbuf
==
nil
&&
runtime
·
showframe
(
nil
,
gp
==
m
->
curg
))
if
(
pcbuf
==
nil
&&
fn
==
nil
&&
runtime
·
showframe
(
nil
,
gp
==
m
->
curg
))
runtime
·
printf
(
"----- stack segment boundary -----
\n
"
);
stk
=
(
Stktop
*
)
stk
->
stackbase
;
continue
;
}
if
(
pc
<=
0x1000
||
(
f
=
runtime
·
findfunc
(
pc
))
==
nil
)
if
(
pc
<=
0x1000
||
(
f
=
runtime
·
findfunc
(
pc
))
==
nil
)
{
if
(
fn
!=
nil
)
runtime
·
throw
(
"unknown pc"
);
break
;
}
// Found an actual function.
if
(
lr
==
0
)
...
...
@@ -82,6 +85,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
skip
--
;
else
if
(
pcbuf
!=
nil
)
pcbuf
[
n
++
]
=
pc
;
else
if
(
fn
!=
nil
)
(
*
fn
)(
f
,
(
byte
*
)
pc
,
sp
,
arg
);
else
{
if
(
runtime
·
showframe
(
f
,
gp
==
m
->
curg
))
{
// Print during crash.
...
...
@@ -113,7 +118,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
waspanic
=
f
->
entry
==
(
uintptr
)
runtime
·
sigpanic
;
if
(
pcbuf
==
nil
&&
f
->
entry
==
(
uintptr
)
runtime
·
newstack
&&
gp
==
m
->
g0
)
{
if
(
pcbuf
==
nil
&&
f
n
==
nil
&&
f
->
entry
==
(
uintptr
)
runtime
·
newstack
&&
gp
==
m
->
g0
)
{
runtime
·
printf
(
"----- newstack called from goroutine %D -----
\n
"
,
m
->
curg
->
goid
);
pc
=
(
uintptr
)
m
->
morepc
;
sp
=
(
byte
*
)
m
->
moreargp
-
sizeof
(
void
*
);
...
...
@@ -124,7 +129,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
continue
;
}
if
(
pcbuf
==
nil
&&
f
->
entry
==
(
uintptr
)
runtime
·
lessstack
&&
gp
==
m
->
g0
)
{
if
(
pcbuf
==
nil
&&
f
n
==
nil
&&
f
->
entry
==
(
uintptr
)
runtime
·
lessstack
&&
gp
==
m
->
g0
)
{
runtime
·
printf
(
"----- lessstack called from goroutine %D -----
\n
"
,
m
->
curg
->
goid
);
gp
=
m
->
curg
;
stk
=
(
Stktop
*
)
gp
->
stackbase
;
...
...
@@ -135,6 +140,10 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
continue
;
}
// Do not unwind past the bottom of the stack.
if
(
pc
==
(
uintptr
)
runtime
·
goexit
)
break
;
// Unwind to next frame.
pc
=
lr
;
lr
=
0
;
...
...
@@ -162,7 +171,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
}
}
if
(
pcbuf
==
nil
&&
(
pc
=
gp
->
gopc
)
!=
0
&&
(
f
=
runtime
·
findfunc
(
pc
))
!=
nil
if
(
pcbuf
==
nil
&&
fn
==
nil
&&
(
pc
=
gp
->
gopc
)
!=
0
&&
(
f
=
runtime
·
findfunc
(
pc
))
!=
nil
&&
runtime
·
showframe
(
f
,
gp
==
m
->
curg
)
&&
gp
->
goid
!=
1
)
{
runtime
·
printf
(
"created by %S
\n
"
,
f
->
name
);
tracepc
=
pc
;
// back up to CALL instruction for funcline.
...
...
@@ -186,7 +195,7 @@ runtime·traceback(byte *pc0, byte *sp, byte *lr, G *gp)
sp
=
(
byte
*
)
gp
->
sched
.
sp
;
lr
=
nil
;
}
runtime
·
gentraceback
(
pc0
,
sp
,
lr
,
gp
,
0
,
nil
,
100
);
runtime
·
gentraceback
(
pc0
,
sp
,
lr
,
gp
,
0
,
nil
,
100
,
nil
,
nil
);
}
// func caller(n int) (pc uintptr, file string, line int, ok bool)
...
...
@@ -198,5 +207,5 @@ runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
sp
=
runtime
·
getcallersp
(
&
skip
);
pc
=
runtime
·
getcallerpc
(
&
skip
);
return
runtime
·
gentraceback
(
pc
,
sp
,
0
,
g
,
skip
,
pcbuf
,
m
);
return
runtime
·
gentraceback
(
pc
,
sp
,
0
,
g
,
skip
,
pcbuf
,
m
,
nil
,
nil
);
}
src/pkg/runtime/traceback_x86.c
View file @
db018bf7
...
...
@@ -17,14 +17,14 @@ void runtime·sigpanic(void);
// This code is also used for the 386 tracebacks.
// Use uintptr for an appropriate word-sized integer.
// Generic traceback. Handles runtime stack prints (pcbuf == nil)
//
as well as the runtime.Callers function (pcbuf != nil).
//
A little clunky to merge the two but avoids duplicating
// the code and all its subtlety.
// Generic traceback. Handles runtime stack prints (pcbuf == nil)
,
//
the runtime.Callers function (pcbuf != nil), as well as the garbage
//
collector (fn != nil). A little clunky to merge the two but avoids
//
duplicating
the code and all its subtlety.
int32
runtime
·
gentraceback
(
byte
*
pc0
,
byte
*
sp
,
byte
*
lr0
,
G
*
gp
,
int32
skip
,
uintptr
*
pcbuf
,
int32
max
)
runtime
·
gentraceback
(
byte
*
pc0
,
byte
*
sp
,
byte
*
lr0
,
G
*
gp
,
int32
skip
,
uintptr
*
pcbuf
,
int32
max
,
void
(
*
fn
)(
Func
*
,
byte
*
,
byte
*
,
void
*
),
void
*
arg
)
{
int32
i
,
n
,
iter
,
sawnewstack
;
int32
i
,
n
,
sawnewstack
;
uintptr
pc
,
lr
,
tracepc
;
byte
*
fp
;
Stktop
*
stk
;
...
...
@@ -54,7 +54,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
n
=
0
;
sawnewstack
=
0
;
stk
=
(
Stktop
*
)
gp
->
stackbase
;
for
(
iter
=
0
;
iter
<
100
&&
n
<
max
;
iter
++
)
{
// iter avoids looping forever
while
(
n
<
max
)
{
// Typically:
// pc is the PC of the running function.
// sp is the stack pointer at that program counter.
...
...
@@ -68,13 +68,16 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
sp
=
(
byte
*
)
stk
->
gobuf
.
sp
;
lr
=
0
;
fp
=
nil
;
if
(
pcbuf
==
nil
&&
runtime
·
showframe
(
nil
,
gp
==
m
->
curg
))
if
(
pcbuf
==
nil
&&
fn
==
nil
&&
runtime
·
showframe
(
nil
,
gp
==
m
->
curg
))
runtime
·
printf
(
"----- stack segment boundary -----
\n
"
);
stk
=
(
Stktop
*
)
stk
->
stackbase
;
continue
;
}
if
(
pc
<=
0x1000
||
(
f
=
runtime
·
findfunc
(
pc
))
==
nil
)
if
(
pc
<=
0x1000
||
(
f
=
runtime
·
findfunc
(
pc
))
==
nil
)
{
if
(
fn
!=
nil
)
runtime
·
throw
(
"unknown pc"
);
break
;
}
// Found an actual function.
if
(
fp
==
nil
)
{
...
...
@@ -91,6 +94,8 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
skip
--
;
else
if
(
pcbuf
!=
nil
)
pcbuf
[
n
++
]
=
pc
;
else
if
(
fn
!=
nil
)
(
*
fn
)(
f
,
(
byte
*
)
pc
,
sp
,
arg
);
else
{
if
(
runtime
·
showframe
(
f
,
gp
==
m
->
curg
))
{
// Print during crash.
...
...
@@ -129,7 +134,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
if
(
f
->
entry
==
(
uintptr
)
runtime
·
newstack
)
sawnewstack
=
1
;
if
(
pcbuf
==
nil
&&
f
->
entry
==
(
uintptr
)
runtime
·
morestack
&&
gp
==
m
->
g0
&&
sawnewstack
)
{
if
(
pcbuf
==
nil
&&
f
n
==
nil
&&
f
->
entry
==
(
uintptr
)
runtime
·
morestack
&&
gp
==
m
->
g0
&&
sawnewstack
)
{
// The fact that we saw newstack means that morestack
// has managed to record its information in m, so we can
// use it to keep unwinding the stack.
...
...
@@ -144,7 +149,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
continue
;
}
if
(
pcbuf
==
nil
&&
f
->
entry
==
(
uintptr
)
runtime
·
lessstack
&&
gp
==
m
->
g0
)
{
if
(
pcbuf
==
nil
&&
f
n
==
nil
&&
f
->
entry
==
(
uintptr
)
runtime
·
lessstack
&&
gp
==
m
->
g0
)
{
// Lessstack is running on scheduler stack. Switch to original goroutine.
runtime
·
printf
(
"----- lessstack called from goroutine %D -----
\n
"
,
m
->
curg
->
goid
);
gp
=
m
->
curg
;
...
...
@@ -156,6 +161,10 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
continue
;
}
// Do not unwind past the bottom of the stack.
if
(
pc
==
(
uintptr
)
runtime
·
goexit
)
break
;
// Unwind to next frame.
pc
=
lr
;
lr
=
0
;
...
...
@@ -164,7 +173,7 @@ runtime·gentraceback(byte *pc0, byte *sp, byte *lr0, G *gp, int32 skip, uintptr
}
// Show what created goroutine, except main goroutine (goid 1).
if
(
pcbuf
==
nil
&&
(
pc
=
gp
->
gopc
)
!=
0
&&
(
f
=
runtime
·
findfunc
(
pc
))
!=
nil
if
(
pcbuf
==
nil
&&
fn
==
nil
&&
(
pc
=
gp
->
gopc
)
!=
0
&&
(
f
=
runtime
·
findfunc
(
pc
))
!=
nil
&&
runtime
·
showframe
(
f
,
gp
==
m
->
curg
)
&&
gp
->
goid
!=
1
)
{
runtime
·
printf
(
"created by %S
\n
"
,
f
->
name
);
tracepc
=
pc
;
// back up to CALL instruction for funcline.
...
...
@@ -187,7 +196,7 @@ runtime·traceback(byte *pc0, byte *sp, byte*, G *gp)
pc0
=
gp
->
sched
.
pc
;
sp
=
(
byte
*
)
gp
->
sched
.
sp
;
}
runtime
·
gentraceback
(
pc0
,
sp
,
nil
,
gp
,
0
,
nil
,
100
);
runtime
·
gentraceback
(
pc0
,
sp
,
nil
,
gp
,
0
,
nil
,
100
,
nil
,
nil
);
}
int32
...
...
@@ -199,5 +208,5 @@ runtime·callers(int32 skip, uintptr *pcbuf, int32 m)
sp
=
(
byte
*
)
&
skip
;
pc
=
runtime
·
getcallerpc
(
&
skip
);
return
runtime
·
gentraceback
(
pc
,
sp
,
nil
,
g
,
skip
,
pcbuf
,
m
);
return
runtime
·
gentraceback
(
pc
,
sp
,
nil
,
g
,
skip
,
pcbuf
,
m
,
nil
,
nil
);
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment