mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 15:11:08 +08:00
libgo: Use libbacktrace rather than debug/elf registration.
From-SVN: r191831
This commit is contained in:
parent
d10402b413
commit
0e56e59065
@ -1,3 +1,9 @@
|
||||
2012-09-28 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* Makefile.def: Make all-target-libgo depend on
|
||||
all-target-libbacktrace.
|
||||
* Makefile.in: Rebuild.
|
||||
|
||||
2012-09-26 Ian Lance Taylor <iant@google.com>
|
||||
|
||||
* Makefile.def: Make all-gcc depend on all-libbacktrace.
|
||||
|
@ -491,6 +491,7 @@ dependencies = { module=configure-target-fastjar; on=configure-target-zlib; };
|
||||
dependencies = { module=all-target-fastjar; on=all-target-zlib; };
|
||||
dependencies = { module=configure-target-libgo; on=configure-target-libffi; };
|
||||
dependencies = { module=configure-target-libgo; on=all-target-libstdc++-v3; };
|
||||
dependencies = { module=all-target-libgo; on=all-target-libbacktrace; };
|
||||
dependencies = { module=all-target-libgo; on=all-target-libffi; };
|
||||
dependencies = { module=configure-target-libjava; on=configure-target-zlib; };
|
||||
dependencies = { module=configure-target-libjava; on=configure-target-boehm-gc; };
|
||||
|
@ -45348,6 +45348,7 @@ configure-target-fastjar: maybe-configure-target-zlib
|
||||
all-target-fastjar: maybe-all-target-zlib
|
||||
configure-target-libgo: maybe-configure-target-libffi
|
||||
configure-target-libgo: maybe-all-target-libstdc++-v3
|
||||
all-target-libgo: maybe-all-target-libbacktrace
|
||||
all-target-libgo: maybe-all-target-libffi
|
||||
configure-target-libjava: maybe-configure-target-zlib
|
||||
configure-target-libjava: maybe-configure-target-boehm-gc
|
||||
|
@ -39,7 +39,8 @@ ACLOCAL_AMFLAGS = -I ./config -I ../config
|
||||
|
||||
AM_CFLAGS = -fexceptions -fplan9-extensions $(SPLIT_STACK) $(WARN_CFLAGS) \
|
||||
$(STRINGOPS_FLAG) $(OSCFLAGS) \
|
||||
-I $(srcdir)/../libgcc -I $(MULTIBUILDTOP)../../gcc/include
|
||||
-I $(srcdir)/../libgcc -I $(srcdir)/../libbacktrace \
|
||||
-I $(MULTIBUILDTOP)../../gcc/include
|
||||
|
||||
if USING_SPLIT_STACK
|
||||
AM_LDFLAGS = -XCClinker $(SPLIT_STACK)
|
||||
@ -1062,8 +1063,7 @@ go_debug_dwarf_files = \
|
||||
go/debug/dwarf/unit.go
|
||||
go_debug_elf_files = \
|
||||
go/debug/elf/elf.go \
|
||||
go/debug/elf/file.go \
|
||||
go/debug/elf/runtime.go
|
||||
go/debug/elf/file.go
|
||||
go_debug_gosym_files = \
|
||||
go/debug/gosym/pclntab.go \
|
||||
go/debug/gosym/symtab.go
|
||||
@ -1782,7 +1782,8 @@ libgo_la_SOURCES = $(runtime_files)
|
||||
libgo_la_LDFLAGS = $(PTHREAD_CFLAGS) $(AM_LDFLAGS)
|
||||
|
||||
libgo_la_LIBADD = \
|
||||
$(libgo_go_objs) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
|
||||
$(libgo_go_objs) ../libbacktrace/libbacktrace.la \
|
||||
$(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
|
||||
|
||||
libgobegin_a_SOURCES = \
|
||||
runtime/go-main.c
|
||||
|
@ -169,7 +169,8 @@ am__DEPENDENCIES_2 = bufio.lo bytes.lo bytes/index.lo crypto.lo \
|
||||
text/tabwriter.lo text/template.lo text/template/parse.lo \
|
||||
testing/iotest.lo testing/quick.lo unicode/utf16.lo \
|
||||
unicode/utf8.lo
|
||||
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \
|
||||
libgo_la_DEPENDENCIES = $(am__DEPENDENCIES_2) \
|
||||
../libbacktrace/libbacktrace.la $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
|
||||
$(am__DEPENDENCIES_1)
|
||||
@LIBGO_IS_LINUX_FALSE@am__objects_1 = lock_sema.lo thread-sema.lo
|
||||
@ -435,7 +436,8 @@ AM_CPPFLAGS = -I $(srcdir)/runtime $(LIBFFIINCS) $(PTHREAD_CFLAGS)
|
||||
ACLOCAL_AMFLAGS = -I ./config -I ../config
|
||||
AM_CFLAGS = -fexceptions -fplan9-extensions $(SPLIT_STACK) $(WARN_CFLAGS) \
|
||||
$(STRINGOPS_FLAG) $(OSCFLAGS) \
|
||||
-I $(srcdir)/../libgcc -I $(MULTIBUILDTOP)../../gcc/include
|
||||
-I $(srcdir)/../libgcc -I $(srcdir)/../libbacktrace \
|
||||
-I $(MULTIBUILDTOP)../../gcc/include
|
||||
|
||||
@USING_SPLIT_STACK_TRUE@AM_LDFLAGS = -XCClinker $(SPLIT_STACK)
|
||||
|
||||
@ -1287,8 +1289,7 @@ go_debug_dwarf_files = \
|
||||
|
||||
go_debug_elf_files = \
|
||||
go/debug/elf/elf.go \
|
||||
go/debug/elf/file.go \
|
||||
go/debug/elf/runtime.go
|
||||
go/debug/elf/file.go
|
||||
|
||||
go_debug_gosym_files = \
|
||||
go/debug/gosym/pclntab.go \
|
||||
@ -1932,7 +1933,8 @@ libgo_go_objs = \
|
||||
libgo_la_SOURCES = $(runtime_files)
|
||||
libgo_la_LDFLAGS = $(PTHREAD_CFLAGS) $(AM_LDFLAGS)
|
||||
libgo_la_LIBADD = \
|
||||
$(libgo_go_objs) $(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
|
||||
$(libgo_go_objs) ../libbacktrace/libbacktrace.la \
|
||||
$(LIBFFI) $(PTHREAD_LIBS) $(MATH_LIBS) $(NET_LIBS)
|
||||
|
||||
libgobegin_a_SOURCES = \
|
||||
runtime/go-main.c
|
||||
|
@ -2,10 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package elf_test
|
||||
package elf
|
||||
|
||||
import (
|
||||
. "debug/elf"
|
||||
"fmt"
|
||||
"testing"
|
||||
)
|
||||
|
@ -2,11 +2,10 @@
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package elf_test
|
||||
package elf
|
||||
|
||||
import (
|
||||
"debug/dwarf"
|
||||
. "debug/elf"
|
||||
"encoding/binary"
|
||||
"net"
|
||||
"os"
|
||||
|
@ -1,161 +0,0 @@
|
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// This is gccgo-specific code that uses DWARF information to fetch
|
||||
// file/line information for PC values. This package registers itself
|
||||
// with the runtime package.
|
||||
|
||||
package elf
|
||||
|
||||
import (
|
||||
"debug/dwarf"
|
||||
"debug/macho"
|
||||
"os"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Register our lookup functions with the runtime package.
|
||||
runtime.RegisterDebugLookup(funcFileLine, symbolValue)
|
||||
}
|
||||
|
||||
// The file struct holds information for a specific file that is part
|
||||
// of the execution.
|
||||
type file struct {
|
||||
elf *File // If ELF
|
||||
macho *macho.File // If Mach-O
|
||||
dwarf *dwarf.Data // DWARF information
|
||||
|
||||
symsByName []sym // Sorted by name
|
||||
symsByAddr []sym // Sorted by address
|
||||
}
|
||||
|
||||
// Sort symbols by name.
|
||||
type symsByName []sym
|
||||
|
||||
func (s symsByName) Len() int { return len(s) }
|
||||
func (s symsByName) Less(i, j int) bool { return s[i].name < s[j].name }
|
||||
func (s symsByName) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// Sort symbols by address.
|
||||
type symsByAddr []sym
|
||||
|
||||
func (s symsByAddr) Len() int { return len(s) }
|
||||
func (s symsByAddr) Less(i, j int) bool { return s[i].addr < s[j].addr }
|
||||
func (s symsByAddr) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
|
||||
|
||||
// The sym structure holds the information we care about for a symbol,
|
||||
// namely name and address.
|
||||
type sym struct {
|
||||
name string
|
||||
addr uintptr
|
||||
}
|
||||
|
||||
// Open an input file.
|
||||
func open(name string) (*file, error) {
|
||||
efile, err := Open(name)
|
||||
var mfile *macho.File
|
||||
if err != nil {
|
||||
var merr error
|
||||
mfile, merr = macho.Open(name)
|
||||
if merr != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
r := &file{elf: efile, macho: mfile}
|
||||
|
||||
if efile != nil {
|
||||
r.dwarf, err = efile.DWARF()
|
||||
} else {
|
||||
r.dwarf, err = mfile.DWARF()
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var syms []sym
|
||||
if efile != nil {
|
||||
esyms, err := efile.Symbols()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
syms = make([]sym, 0, len(esyms))
|
||||
for _, s := range esyms {
|
||||
if ST_TYPE(s.Info) == STT_FUNC {
|
||||
syms = append(syms, sym{s.Name, uintptr(s.Value)})
|
||||
}
|
||||
}
|
||||
} else {
|
||||
syms = make([]sym, 0, len(mfile.Symtab.Syms))
|
||||
for _, s := range mfile.Symtab.Syms {
|
||||
syms = append(syms, sym{s.Name, uintptr(s.Value)})
|
||||
}
|
||||
}
|
||||
|
||||
r.symsByName = make([]sym, len(syms))
|
||||
copy(r.symsByName, syms)
|
||||
sort.Sort(symsByName(r.symsByName))
|
||||
|
||||
r.symsByAddr = syms
|
||||
sort.Sort(symsByAddr(r.symsByAddr))
|
||||
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// The main executable
|
||||
var executable *file
|
||||
|
||||
// Only open the executable once.
|
||||
var executableOnce sync.Once
|
||||
|
||||
func openExecutable() {
|
||||
executableOnce.Do(func() {
|
||||
f, err := open("/proc/self/exe")
|
||||
if err != nil {
|
||||
f, err = open(os.Args[0])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
executable = f
|
||||
})
|
||||
}
|
||||
|
||||
// The funcFileLine function looks up the function name, file name,
|
||||
// and line number for a PC value.
|
||||
func funcFileLine(pc uintptr, function *string, file *string, line *int) bool {
|
||||
openExecutable()
|
||||
if executable == nil || executable.dwarf == nil {
|
||||
return false
|
||||
}
|
||||
f, ln, err := executable.dwarf.FileLine(uint64(pc))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
*file = f
|
||||
*line = ln
|
||||
|
||||
*function = ""
|
||||
if len(executable.symsByAddr) > 0 && pc >= executable.symsByAddr[0].addr {
|
||||
i := sort.Search(len(executable.symsByAddr),
|
||||
func(i int) bool { return executable.symsByAddr[i].addr > pc })
|
||||
*function = executable.symsByAddr[i-1].name
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// The symbolValue function fetches the value of a symbol.
|
||||
func symbolValue(name string, val *uintptr) bool {
|
||||
i := sort.Search(len(executable.symsByName),
|
||||
func(i int) bool { return executable.symsByName[i].name >= name })
|
||||
if i >= len(executable.symsByName) || executable.symsByName[i].name != name {
|
||||
return false
|
||||
}
|
||||
*val = executable.symsByName[i].addr
|
||||
return true
|
||||
}
|
@ -35,7 +35,6 @@ package pprof
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
_ "debug/elf"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io"
|
||||
|
@ -6,7 +6,6 @@ package net
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "debug/elf"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"testing"
|
||||
|
@ -8,7 +8,6 @@ package debug
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
_ "debug/elf"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
@ -11,7 +11,6 @@ package pprof
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
_ "debug/elf"
|
||||
"fmt"
|
||||
"io"
|
||||
"runtime"
|
||||
|
@ -79,7 +79,6 @@
|
||||
package testing
|
||||
|
||||
import (
|
||||
_ "debug/elf"
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
@ -8,41 +8,99 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "backtrace.h"
|
||||
|
||||
#include "runtime.h"
|
||||
#include "go-string.h"
|
||||
|
||||
/* Get the function name, file name, and line number for a PC value.
|
||||
We use the DWARF debug information to get this. Rather than write
|
||||
a whole new library in C, we use the existing Go library.
|
||||
Unfortunately, the Go library is only available if the debug/elf
|
||||
package is imported (we use debug/elf for both ELF and Mach-O, in
|
||||
this case). We arrange for the debug/elf package to register
|
||||
itself, and tweak the various packages that need this information
|
||||
to import debug/elf where possible. */
|
||||
We use the backtrace library to get this. */
|
||||
|
||||
/* The function that returns function/file/line information. */
|
||||
/* Data structure to gather file/line information. */
|
||||
|
||||
typedef _Bool (*infofn_type) (uintptr_t, struct __go_string *,
|
||||
struct __go_string *, int *);
|
||||
static infofn_type infofn;
|
||||
|
||||
/* The function that returns the value of a symbol, used to get the
|
||||
entry address of a function. */
|
||||
|
||||
typedef _Bool (*symvalfn_type) (struct __go_string, uintptr_t *);
|
||||
static symvalfn_type symvalfn;
|
||||
|
||||
/* This is called by debug/elf to register the function that returns
|
||||
function/file/line information. */
|
||||
|
||||
void RegisterDebugLookup (infofn_type, symvalfn_type)
|
||||
__asm__ ("runtime.RegisterDebugLookup");
|
||||
|
||||
void
|
||||
RegisterDebugLookup (infofn_type pi, symvalfn_type ps)
|
||||
struct caller
|
||||
{
|
||||
infofn = pi;
|
||||
symvalfn = ps;
|
||||
struct __go_string fn;
|
||||
struct __go_string file;
|
||||
int line;
|
||||
};
|
||||
|
||||
/* Collect file/line information for a PC value. If this is called
|
||||
more than once, due to inlined functions, we use the last call, as
|
||||
that is usually the most useful one. */
|
||||
|
||||
static int
|
||||
callback (void *data, uintptr_t pc __attribute__ ((unused)),
|
||||
const char *filename, int lineno, const char *function)
|
||||
{
|
||||
struct caller *c = (struct caller *) data;
|
||||
|
||||
if (function == NULL)
|
||||
{
|
||||
c->fn.__data = NULL;
|
||||
c->fn.__length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *s;
|
||||
|
||||
c->fn.__length = __builtin_strlen (function);
|
||||
s = runtime_malloc (c->fn.__length);
|
||||
__builtin_memcpy (s, function, c->fn.__length);
|
||||
c->fn.__data = (unsigned char *) s;
|
||||
}
|
||||
|
||||
if (filename == NULL)
|
||||
{
|
||||
c->file.__data = NULL;
|
||||
c->file.__length = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *s;
|
||||
|
||||
c->file.__length = __builtin_strlen (filename);
|
||||
s = runtime_malloc (c->file.__length);
|
||||
__builtin_memcpy (s, filename, c->file.__length);
|
||||
c->file.__data = (unsigned char *) s;
|
||||
}
|
||||
|
||||
c->line = lineno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The error callback for backtrace_pcinfo and backtrace_syminfo. */
|
||||
|
||||
static void
|
||||
error_callback (void *data __attribute__ ((unused)),
|
||||
const char *msg, int errnum)
|
||||
{
|
||||
if (errnum == -1)
|
||||
return;
|
||||
if (errnum > 0)
|
||||
runtime_printf ("%s errno %d\n", msg, errnum);
|
||||
runtime_throw (msg);
|
||||
}
|
||||
|
||||
/* The backtrace library state. */
|
||||
|
||||
static void *back_state;
|
||||
|
||||
/* A lock to control creating back_state. */
|
||||
|
||||
static Lock back_state_lock;
|
||||
|
||||
/* Fetch back_state, creating it if necessary. */
|
||||
|
||||
struct backtrace_state *
|
||||
__go_get_backtrace_state ()
|
||||
{
|
||||
runtime_lock (&back_state_lock);
|
||||
if (back_state == NULL)
|
||||
back_state = backtrace_create_state (NULL, 1, error_callback, NULL);
|
||||
runtime_unlock (&back_state_lock);
|
||||
return back_state;
|
||||
}
|
||||
|
||||
/* Return function/file/line information for PC. */
|
||||
@ -51,19 +109,38 @@ _Bool
|
||||
__go_file_line (uintptr pc, struct __go_string *fn, struct __go_string *file,
|
||||
int *line)
|
||||
{
|
||||
if (infofn == NULL)
|
||||
return 0;
|
||||
return infofn (pc, fn, file, line);
|
||||
struct caller c;
|
||||
|
||||
runtime_memclr (&c, sizeof c);
|
||||
backtrace_pcinfo (__go_get_backtrace_state (), pc, callback,
|
||||
error_callback, &c);
|
||||
*fn = c.fn;
|
||||
*file = c.file;
|
||||
*line = c.line;
|
||||
return c.file.__length > 0;
|
||||
}
|
||||
|
||||
/* Return the value of a symbol. */
|
||||
/* Collect symbol information. */
|
||||
|
||||
_Bool
|
||||
__go_symbol_value (struct __go_string sym, uintptr_t *val)
|
||||
static void
|
||||
syminfo_callback (void *data, uintptr_t pc __attribute__ ((unused)),
|
||||
const char *symname __attribute__ ((unused)),
|
||||
uintptr_t address)
|
||||
{
|
||||
if (symvalfn == NULL)
|
||||
return 0;
|
||||
return symvalfn (sym, val);
|
||||
uintptr_t *pval = (uintptr_t *) data;
|
||||
|
||||
*pval = address;
|
||||
}
|
||||
|
||||
/* Set *VAL to the value of the symbol for PC. */
|
||||
|
||||
static _Bool
|
||||
__go_symbol_value (uintptr_t pc, uintptr_t *val)
|
||||
{
|
||||
*val = 0;
|
||||
backtrace_syminfo (__go_get_backtrace_state (), pc, syminfo_callback,
|
||||
error_callback, &val);
|
||||
return *val != 0;
|
||||
}
|
||||
|
||||
/* The values returned by runtime.Caller. */
|
||||
@ -112,12 +189,15 @@ FuncForPC (uintptr_t pc)
|
||||
|
||||
if (!__go_file_line (pc, &fn, &file, &line))
|
||||
return NULL;
|
||||
if (!__go_symbol_value (fn, &val))
|
||||
return NULL;
|
||||
|
||||
ret = (Func *) runtime_malloc (sizeof (*ret));
|
||||
ret->name = fn;
|
||||
ret->entry = val;
|
||||
|
||||
if (__go_symbol_value (pc, &val))
|
||||
ret->entry = val;
|
||||
else
|
||||
ret->entry = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -6,64 +6,56 @@
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "unwind.h"
|
||||
#include "backtrace.h"
|
||||
|
||||
#include "runtime.h"
|
||||
|
||||
/* Argument passed to backtrace function. */
|
||||
/* Argument passed to callback function. */
|
||||
|
||||
struct callers_data
|
||||
{
|
||||
int skip;
|
||||
uintptr *pcbuf;
|
||||
int index;
|
||||
int max;
|
||||
};
|
||||
|
||||
static _Unwind_Reason_Code
|
||||
backtrace (struct _Unwind_Context *context, void *varg)
|
||||
/* Callback function for backtrace_simple. Just collect the PC
|
||||
values. Return zero to continue, non-zero to stop. */
|
||||
|
||||
static int
|
||||
callback (void *data, uintptr_t pc)
|
||||
{
|
||||
struct callers_data *arg = (struct callers_data *) varg;
|
||||
uintptr pc;
|
||||
int ip_before_insn = 0;
|
||||
struct callers_data *arg = (struct callers_data *) data;
|
||||
|
||||
#ifdef HAVE_GETIPINFO
|
||||
pc = _Unwind_GetIPInfo (context, &ip_before_insn);
|
||||
#else
|
||||
pc = _Unwind_GetIP (context);
|
||||
#endif
|
||||
|
||||
/* FIXME: If PC is in the __morestack routine, we should ignore
|
||||
it. */
|
||||
|
||||
if (arg->skip > 0)
|
||||
--arg->skip;
|
||||
else if (arg->index >= arg->max)
|
||||
return _URC_END_OF_STACK;
|
||||
else
|
||||
{
|
||||
/* Here PC will be the return address. We actually want the
|
||||
address of the call instruction, so back up one byte and
|
||||
count on the lookup routines handling that correctly. */
|
||||
if (!ip_before_insn)
|
||||
--pc;
|
||||
arg->pcbuf[arg->index] = pc;
|
||||
++arg->index;
|
||||
}
|
||||
return _URC_NO_REASON;
|
||||
arg->pcbuf[arg->index] = pc;
|
||||
++arg->index;
|
||||
return arg->index >= arg->max;
|
||||
}
|
||||
|
||||
/* Error callback. */
|
||||
|
||||
static void
|
||||
error_callback (void *data __attribute__ ((unused)),
|
||||
const char *msg, int errnum)
|
||||
{
|
||||
if (errnum != 0)
|
||||
runtime_printf ("%s errno %d\n", msg, errnum);
|
||||
runtime_throw (msg);
|
||||
}
|
||||
|
||||
/* Gather caller PC's. */
|
||||
|
||||
int32
|
||||
runtime_callers (int32 skip, uintptr *pcbuf, int32 m)
|
||||
{
|
||||
struct callers_data arg;
|
||||
struct callers_data data;
|
||||
|
||||
arg.skip = skip + 1;
|
||||
arg.pcbuf = pcbuf;
|
||||
arg.index = 0;
|
||||
arg.max = m;
|
||||
_Unwind_Backtrace (backtrace, &arg);
|
||||
return arg.index;
|
||||
data.pcbuf = pcbuf;
|
||||
data.index = 0;
|
||||
data.max = m;
|
||||
backtrace_simple (__go_get_backtrace_state (), skip + 1, callback,
|
||||
error_callback, &data);
|
||||
return data.index;
|
||||
}
|
||||
|
||||
int Callers (int, struct __go_open_array)
|
||||
|
@ -517,6 +517,8 @@ void __go_register_gc_roots(struct root_list*);
|
||||
// the stacks are allocated by the splitstack library.
|
||||
extern uintptr runtime_stacks_sys;
|
||||
|
||||
extern _Bool __go_file_line (uintptr, String*, String*, int *);
|
||||
struct backtrace_state;
|
||||
extern struct backtrace_state *__go_get_backtrace_state(void);
|
||||
extern _Bool __go_file_line(uintptr, String*, String*, int *);
|
||||
|
||||
int32 getproccount(void);
|
||||
|
Loading…
x
Reference in New Issue
Block a user