2016-03-01 22:57:46 +00:00
// Copyright 2013 The Go Authors. All rights reserved.
2015-02-27 22:57:28 -05:00
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ld
import (
2017-04-18 12:53:25 -07:00
"cmd/internal/objabi"
2017-03-04 07:09:33 -08:00
"cmd/internal/src"
2018-10-04 16:32:21 -07:00
"cmd/internal/sys"
2017-10-04 17:54:04 -04:00
"cmd/link/internal/sym"
2015-02-27 22:57:28 -05:00
"log"
2015-12-29 10:16:40 -05:00
"os"
"path/filepath"
2018-06-11 16:46:23 -07:00
"strings"
2015-02-27 22:57:28 -05:00
)
// iteration over encoded pcdata tables.
func getvarint ( pp * [ ] byte ) uint32 {
2015-03-02 12:35:15 -05:00
v := uint32 ( 0 )
p := * pp
for shift := 0 ; ; shift += 7 {
2015-02-27 22:57:28 -05:00
v |= uint32 ( p [ 0 ] & 0x7F ) << uint ( shift )
tmp4 := p
p = p [ 1 : ]
if tmp4 [ 0 ] & 0x80 == 0 {
break
}
}
* pp = p
return v
}
func pciternext ( it * Pciter ) {
it . pc = it . nextpc
if it . done != 0 {
return
}
if - cap ( it . p ) >= - cap ( it . d . P [ len ( it . d . P ) : ] ) {
it . done = 1
return
}
// value delta
2015-03-02 12:35:15 -05:00
v := getvarint ( & it . p )
2015-02-27 22:57:28 -05:00
if v == 0 && it . start == 0 {
it . done = 1
return
}
it . start = 0
2015-03-02 12:35:15 -05:00
dv := int32 ( v >> 1 ) ^ ( int32 ( v << 31 ) >> 31 )
2015-02-27 22:57:28 -05:00
it . value += dv
// pc delta
v = getvarint ( & it . p )
it . nextpc = it . pc + v * it . pcscale
}
2017-10-04 17:54:04 -04:00
func pciterinit ( ctxt * Link , it * Pciter , d * sym . Pcdata ) {
2015-02-27 22:57:28 -05:00
it . d = * d
it . p = it . d . P
it . pc = 0
it . nextpc = 0
it . value = - 1
it . start = 1
it . done = 0
2016-04-06 12:01:40 -07:00
it . pcscale = uint32 ( ctxt . Arch . MinLC )
2015-02-27 22:57:28 -05:00
pciternext ( it )
}
2017-10-04 17:54:04 -04:00
func addvarint ( d * sym . Pcdata , val uint32 ) {
2015-03-02 12:35:15 -05:00
n := int32 ( 0 )
for v := val ; v >= 0x80 ; v >>= 7 {
2015-02-27 22:57:28 -05:00
n ++
}
n ++
old := len ( d . P )
for cap ( d . P ) < len ( d . P ) + int ( n ) {
d . P = append ( d . P [ : cap ( d . P ) ] , 0 )
}
d . P = d . P [ : old + int ( n ) ]
2015-03-02 12:35:15 -05:00
p := d . P [ old : ]
var v uint32
2015-02-27 22:57:28 -05:00
for v = val ; v >= 0x80 ; v >>= 7 {
p [ 0 ] = byte ( v | 0x80 )
p = p [ 1 : ]
}
p [ 0 ] = byte ( v )
}
2017-10-04 17:54:04 -04:00
func addpctab ( ctxt * Link , ftab * sym . Symbol , off int32 , d * sym . Pcdata ) int32 {
2015-06-28 22:26:35 -04:00
var start int32
if len ( d . P ) > 0 {
start = int32 ( len ( ftab . P ) )
2017-09-30 15:06:44 +00:00
ftab . AddBytes ( d . P )
2015-06-28 22:26:35 -04:00
}
2017-09-30 15:06:44 +00:00
return int32 ( ftab . SetUint32 ( ctxt . Arch , int64 ( off ) , uint32 ( start ) ) )
2015-02-27 22:57:28 -05:00
}
2019-04-11 18:05:19 -07:00
func ftabaddstring ( ftab * sym . Symbol , s string ) int32 {
start := len ( ftab . P )
ftab . Grow ( int64 ( start + len ( s ) + 1 ) ) // make room for s plus trailing NUL
2015-02-27 22:57:28 -05:00
copy ( ftab . P [ start : ] , s )
2019-04-11 18:05:19 -07:00
return int32 ( start )
2015-02-27 22:57:28 -05:00
}
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
// numberfile assigns a file number to the file if it hasn't been assigned already.
2017-10-04 17:54:04 -04:00
func numberfile ( ctxt * Link , file * sym . Symbol ) {
if file . Type != sym . SFILEPATH {
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
ctxt . Filesyms = append ( ctxt . Filesyms , file )
file . Value = int64 ( len ( ctxt . Filesyms ) )
2017-10-04 17:54:04 -04:00
file . Type = sym . SFILEPATH
2017-03-04 07:09:33 -08:00
path := file . Name [ len ( src . FileSymPrefix ) : ]
2017-02-17 16:20:52 -05:00
file . Name = expandGoroot ( path )
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
}
}
2017-10-04 17:54:04 -04:00
func renumberfiles ( ctxt * Link , files [ ] * sym . Symbol , d * sym . Pcdata ) {
2015-02-27 22:57:28 -05:00
// Give files numbers.
2018-04-06 21:41:06 +01:00
for _ , f := range files {
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
numberfile ( ctxt , f )
2015-02-27 22:57:28 -05:00
}
2015-03-02 12:35:15 -05:00
newval := int32 ( - 1 )
2017-10-04 17:54:04 -04:00
var out sym . Pcdata
2015-03-02 12:35:15 -05:00
var it Pciter
2015-02-27 22:57:28 -05:00
for pciterinit ( ctxt , & it , d ) ; it . done == 0 ; pciternext ( & it ) {
// value delta
2016-04-20 14:22:20 -04:00
oldval := it . value
2015-02-27 22:57:28 -05:00
2016-04-20 14:22:20 -04:00
var val int32
2015-02-27 22:57:28 -05:00
if oldval == - 1 {
val = - 1
} else {
if oldval < 0 || oldval >= int32 ( len ( files ) ) {
log . Fatalf ( "bad pcdata %d" , oldval )
}
val = int32 ( files [ oldval ] . Value )
}
2016-04-20 14:22:20 -04:00
dv := val - newval
2015-02-27 22:57:28 -05:00
newval = val
2016-04-20 14:22:20 -04:00
v := ( uint32 ( dv ) << 1 ) ^ uint32 ( dv >> 31 )
2015-02-27 22:57:28 -05:00
addvarint ( & out , v )
// pc delta
addvarint ( & out , ( it . nextpc - it . pc ) / it . pcscale )
}
// terminating value delta
addvarint ( & out , 0 )
* d = out
}
2018-06-11 16:46:23 -07:00
// onlycsymbol reports whether this is a symbol that is referenced by C code.
2017-10-04 17:54:04 -04:00
func onlycsymbol ( s * sym . Symbol ) bool {
2016-12-10 13:30:13 -05:00
switch s . Name {
2019-02-20 16:52:35 +01:00
case "_cgo_topofstack" , "__cgo_topofstack" , "_cgo_panic" , "crosscall2" :
2016-12-10 13:30:13 -05:00
return true
}
2018-06-11 16:46:23 -07:00
if strings . HasPrefix ( s . Name , "_cgoexp_" ) {
return true
}
2016-12-10 13:30:13 -05:00
return false
}
2017-10-05 10:20:17 -04:00
func emitPcln ( ctxt * Link , s * sym . Symbol ) bool {
2016-12-10 13:30:13 -05:00
if s == nil {
2017-08-28 15:00:49 +09:00
return true
2016-12-10 13:30:13 -05:00
}
2017-10-07 13:49:44 -04:00
if ctxt . BuildMode == BuildModePlugin && ctxt . HeadType == objabi . Hdarwin && onlycsymbol ( s ) {
2017-08-28 15:00:49 +09:00
return false
2016-12-10 13:30:13 -05:00
}
2015-02-27 22:57:28 -05:00
// We want to generate func table entries only for the "lowest level" symbols,
// not containers of subsymbols.
2019-03-06 17:57:35 -05:00
return ! s . Attr . Container ( )
2015-02-27 22:57:28 -05:00
}
// pclntab initializes the pclntab symbol with
// runtime function and file name information.
2017-10-04 17:54:04 -04:00
var pclntabZpcln sym . FuncInfo
2015-02-27 22:57:28 -05:00
2015-04-07 12:55:02 +12:00
// These variables are used to initialize runtime.firstmoduledata, see symtab.go:symtab.
2015-03-16 11:53:08 +13:00
var pclntabNfunc int32
var pclntabFiletabOffset int32
var pclntabPclntabOffset int32
2017-10-04 17:54:04 -04:00
var pclntabFirstFunc * sym . Symbol
var pclntabLastFunc * sym . Symbol
2015-03-16 11:53:08 +13:00
2016-08-19 22:40:38 -04:00
func ( ctxt * Link ) pclntab ( ) {
2016-08-22 10:33:13 -04:00
funcdataBytes := int64 ( 0 )
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
ftab := ctxt . Syms . Lookup ( "runtime.pclntab" , 0 )
2017-10-04 17:54:04 -04:00
ftab . Type = sym . SPCLNTAB
ftab . Attr |= sym . AttrReachable
2015-02-27 22:57:28 -05:00
// See golang.org/s/go12symtab for the format. Briefly:
// 8-byte header
// nfunc [thearch.ptrsize bytes]
// function table, alternating PC and offset to func struct [each entry thearch.ptrsize bytes]
// end PC [thearch.ptrsize bytes]
// offset to file table [4 bytes]
2015-03-02 12:35:15 -05:00
nfunc := int32 ( 0 )
2015-02-27 22:57:28 -05:00
2017-10-16 14:20:01 +13:00
// Find container symbols and mark them as such.
2016-08-19 22:40:38 -04:00
for _ , s := range ctxt . Textp {
2016-04-19 14:02:21 -04:00
if s . Outer != nil {
2017-10-16 14:20:01 +13:00
s . Outer . Attr |= sym . AttrContainer
2015-06-27 12:57:06 -07:00
}
}
2016-08-19 22:40:38 -04:00
for _ , s := range ctxt . Textp {
2017-10-05 10:20:17 -04:00
if emitPcln ( ctxt , s ) {
2015-02-27 22:57:28 -05:00
nfunc ++
}
}
2015-03-16 11:53:08 +13:00
pclntabNfunc = nfunc
2017-09-30 15:06:44 +00:00
ftab . Grow ( 8 + int64 ( ctxt . Arch . PtrSize ) + int64 ( nfunc ) * 2 * int64 ( ctxt . Arch . PtrSize ) + int64 ( ctxt . Arch . PtrSize ) + 4 )
ftab . SetUint32 ( ctxt . Arch , 0 , 0xfffffffb )
ftab . SetUint8 ( ctxt . Arch , 6 , uint8 ( ctxt . Arch . MinLC ) )
ftab . SetUint8 ( ctxt . Arch , 7 , uint8 ( ctxt . Arch . PtrSize ) )
ftab . SetUint ( ctxt . Arch , 8 , uint64 ( nfunc ) )
2017-09-30 21:10:49 +00:00
pclntabPclntabOffset = int32 ( 8 + ctxt . Arch . PtrSize )
2015-02-27 22:57:28 -05:00
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
funcnameoff := make ( map [ string ] int32 )
nameToOffset := func ( name string ) int32 {
nameoff , ok := funcnameoff [ name ]
if ! ok {
2019-04-11 18:05:19 -07:00
nameoff = ftabaddstring ( ftab , name )
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
funcnameoff [ name ] = nameoff
}
return nameoff
}
2015-02-27 22:57:28 -05:00
nfunc = 0
2017-10-04 17:54:04 -04:00
var last * sym . Symbol
2016-09-17 10:01:17 -04:00
for _ , s := range ctxt . Textp {
last = s
2017-10-05 10:20:17 -04:00
if ! emitPcln ( ctxt , s ) {
2015-02-27 22:57:28 -05:00
continue
}
2016-09-17 10:01:17 -04:00
pcln := s . FuncInfo
2015-02-27 22:57:28 -05:00
if pcln == nil {
2016-08-22 10:33:13 -04:00
pcln = & pclntabZpcln
2015-02-27 22:57:28 -05:00
}
2015-03-16 11:53:08 +13:00
if pclntabFirstFunc == nil {
2016-09-17 10:01:17 -04:00
pclntabFirstFunc = s
2015-03-16 11:53:08 +13:00
}
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
if len ( pcln . InlTree ) > 0 {
2017-04-18 12:53:25 -07:00
if len ( pcln . Pcdata ) <= objabi . PCDATA_InlTreeIndex {
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
// Create inlining pcdata table.
2017-10-04 17:54:04 -04:00
pcdata := make ( [ ] sym . Pcdata , objabi . PCDATA_InlTreeIndex + 1 )
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
copy ( pcdata , pcln . Pcdata )
pcln . Pcdata = pcdata
}
2017-04-18 12:53:25 -07:00
if len ( pcln . Funcdataoff ) <= objabi . FUNCDATA_InlTree {
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
// Create inline tree funcdata.
2017-10-04 17:54:04 -04:00
funcdata := make ( [ ] * sym . Symbol , objabi . FUNCDATA_InlTree + 1 )
2017-04-18 12:53:25 -07:00
funcdataoff := make ( [ ] int64 , objabi . FUNCDATA_InlTree + 1 )
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
copy ( funcdata , pcln . Funcdata )
copy ( funcdataoff , pcln . Funcdataoff )
pcln . Funcdata = funcdata
pcln . Funcdataoff = funcdataoff
}
}
2016-04-20 14:22:20 -04:00
funcstart := int32 ( len ( ftab . P ) )
2017-09-30 21:10:49 +00:00
funcstart += int32 ( - len ( ftab . P ) ) & ( int32 ( ctxt . Arch . PtrSize ) - 1 )
2015-02-27 22:57:28 -05:00
2017-09-30 15:06:44 +00:00
ftab . SetAddr ( ctxt . Arch , 8 + int64 ( ctxt . Arch . PtrSize ) + int64 ( nfunc ) * 2 * int64 ( ctxt . Arch . PtrSize ) , s )
ftab . SetUint ( ctxt . Arch , 8 + int64 ( ctxt . Arch . PtrSize ) + int64 ( nfunc ) * 2 * int64 ( ctxt . Arch . PtrSize ) + int64 ( ctxt . Arch . PtrSize ) , uint64 ( funcstart ) )
2015-02-27 22:57:28 -05:00
2016-12-14 13:24:21 -05:00
// Write runtime._func. Keep in sync with ../../../../runtime/runtime2.go:/_func
// and package debug/gosym.
2015-02-27 22:57:28 -05:00
// fixed size of struct, checked below
2016-04-20 14:22:20 -04:00
off := funcstart
2015-02-27 22:57:28 -05:00
2017-09-30 21:10:49 +00:00
end := funcstart + int32 ( ctxt . Arch . PtrSize ) + 3 * 4 + 5 * 4 + int32 ( len ( pcln . Pcdata ) ) * 4 + int32 ( len ( pcln . Funcdata ) ) * int32 ( ctxt . Arch . PtrSize )
if len ( pcln . Funcdata ) > 0 && ( end & int32 ( ctxt . Arch . PtrSize - 1 ) != 0 ) {
2015-02-27 22:57:28 -05:00
end += 4
}
2017-09-30 15:06:44 +00:00
ftab . Grow ( int64 ( end ) )
2015-02-27 22:57:28 -05:00
// entry uintptr
2017-09-30 15:06:44 +00:00
off = int32 ( ftab . SetAddr ( ctxt . Arch , int64 ( off ) , s ) )
2015-02-27 22:57:28 -05:00
// name int32
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
nameoff := nameToOffset ( s . Name )
2017-09-30 15:06:44 +00:00
off = int32 ( ftab . SetUint32 ( ctxt . Arch , int64 ( off ) , uint32 ( nameoff ) ) )
2015-02-27 22:57:28 -05:00
// args int32
// TODO: Move into funcinfo.
2016-04-11 22:19:34 +03:00
args := uint32 ( 0 )
2016-09-17 10:01:17 -04:00
if s . FuncInfo != nil {
args = uint32 ( s . FuncInfo . Args )
2016-04-11 22:19:34 +03:00
}
2017-09-30 15:06:44 +00:00
off = int32 ( ftab . SetUint32 ( ctxt . Arch , int64 ( off ) , args ) )
2015-02-27 22:57:28 -05:00
2018-09-11 15:14:28 -07:00
// deferreturn
deferreturn := uint32 ( 0 )
2018-10-04 16:32:21 -07:00
lastWasmAddr := uint32 ( 0 )
2018-09-11 15:14:28 -07:00
for _ , r := range s . R {
2018-10-04 16:32:21 -07:00
if ctxt . Arch . Family == sys . Wasm && r . Type == objabi . R_ADDR {
// Wasm does not have a live variable set at the deferreturn
// call itself. Instead it has one identified by the
// resumption point immediately preceding the deferreturn.
// The wasm code has a R_ADDR relocation which is used to
// set the resumption point to PC_B.
lastWasmAddr = uint32 ( r . Add )
}
2018-09-11 15:14:28 -07:00
if r . Sym != nil && r . Sym . Name == "runtime.deferreturn" && r . Add == 0 {
2018-10-04 16:32:21 -07:00
if ctxt . Arch . Family == sys . Wasm {
deferreturn = lastWasmAddr
} else {
// Note: the relocation target is in the call instruction, but
// is not necessarily the whole instruction (for instance, on
// x86 the relocation applies to bytes [1:5] of the 5 byte call
// instruction).
deferreturn = uint32 ( r . Off )
}
2018-09-11 15:14:28 -07:00
break // only need one
}
2018-03-14 15:21:37 -07:00
}
2018-09-11 15:14:28 -07:00
off = int32 ( ftab . SetUint32 ( ctxt . Arch , int64 ( off ) , deferreturn ) )
2015-02-27 22:57:28 -05:00
2016-08-22 10:33:13 -04:00
if pcln != & pclntabZpcln {
2016-08-19 22:40:38 -04:00
renumberfiles ( ctxt , pcln . File , & pcln . Pcfile )
2015-02-27 22:57:28 -05:00
if false {
// Sanity check the new numbering
2016-04-20 14:22:20 -04:00
var it Pciter
2016-08-19 22:40:38 -04:00
for pciterinit ( ctxt , & it , & pcln . Pcfile ) ; it . done == 0 ; pciternext ( & it ) {
if it . value < 1 || it . value > int32 ( len ( ctxt . Filesyms ) ) {
2016-09-17 10:01:17 -04:00
Errorf ( s , "bad file number in pcfile: %d not in range [1, %d]\n" , it . value , len ( ctxt . Filesyms ) )
2015-04-09 07:37:17 -04:00
errorexit ( )
2015-02-27 22:57:28 -05:00
}
}
}
}
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
if len ( pcln . InlTree ) > 0 {
inlTreeSym := ctxt . Syms . Lookup ( "inltree." + s . Name , 0 )
2017-10-04 17:54:04 -04:00
inlTreeSym . Type = sym . SRODATA
inlTreeSym . Attr |= sym . AttrReachable | sym . AttrDuplicateOK
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
for i , call := range pcln . InlTree {
// Usually, call.File is already numbered since the file
// shows up in the Pcfile table. However, two inlined calls
// might overlap exactly so that only the innermost file
// appears in the Pcfile table. In that case, this assigns
// the outer file a number.
numberfile ( ctxt , call . File )
nameoff := nameToOffset ( call . Func . Name )
2018-12-04 07:58:18 -08:00
inlTreeSym . SetUint16 ( ctxt . Arch , int64 ( i * 20 + 0 ) , uint16 ( call . Parent ) )
inlTreeSym . SetUint8 ( ctxt . Arch , int64 ( i * 20 + 2 ) , uint8 ( objabi . GetFuncID ( call . Func . Name , call . Func . File ) ) )
// byte 3 is unused
inlTreeSym . SetUint32 ( ctxt . Arch , int64 ( i * 20 + 4 ) , uint32 ( call . File . Value ) )
inlTreeSym . SetUint32 ( ctxt . Arch , int64 ( i * 20 + 8 ) , uint32 ( call . Line ) )
inlTreeSym . SetUint32 ( ctxt . Arch , int64 ( i * 20 + 12 ) , uint32 ( nameoff ) )
inlTreeSym . SetUint32 ( ctxt . Arch , int64 ( i * 20 + 16 ) , uint32 ( call . ParentPC ) )
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
}
2017-04-18 12:53:25 -07:00
pcln . Funcdata [ objabi . FUNCDATA_InlTree ] = inlTreeSym
pcln . Pcdata [ objabi . PCDATA_InlTreeIndex ] = pcln . Pcinline
cmd/compile,link: generate PC-value tables with inlining information
In order to generate accurate tracebacks, the runtime needs to know the
inlined call stack for a given PC. This creates two tables per function
for this purpose. The first table is the inlining tree (stored in the
function's funcdata), which has a node containing the file, line, and
function name for every inlined call. The second table is a PC-value
table that maps each PC to a node in the inlining tree (or -1 if the PC
is not the result of inlining).
To give the appearance that inlining hasn't happened, the runtime also
needs the original source position information of inlined AST nodes.
Previously the compiler plastered over the line numbers of inlined AST
nodes with the line number of the call. This meant that the PC-line
table mapped each PC to line number of the outermost call in its inlined
call stack, with no way to access the innermost line number.
Now the compiler retains line numbers of inlined AST nodes and writes
the innermost source position information to the PC-line and PC-file
tables. Some tools and tests expect to see outermost line numbers, so we
provide the OutermostLine function for displaying line info.
To keep track of the inlined call stack for an AST node, we extend the
src.PosBase type with an index into a global inlining tree. Every time
the compiler inlines a call, it creates a node in the global inlining
tree for the call, and writes its index to the PosBase of every inlined
AST node. The parent of this node is the inlining tree index of the
call. -1 signifies no parent.
For each function, the compiler creates a local inlining tree and a
PC-value table mapping each PC to an index in the local tree. These are
written to an object file, which is read by the linker. The linker
re-encodes these tables compactly by deduplicating function names and
file names.
This change increases the size of binaries by 4-5%. For example, this is
how the go1 benchmark binary is impacted by this change:
section old bytes new bytes delta
.text 3.49M ± 0% 3.49M ± 0% +0.06%
.rodata 1.12M ± 0% 1.21M ± 0% +8.21%
.gopclntab 1.50M ± 0% 1.68M ± 0% +11.89%
.debug_line 338k ± 0% 435k ± 0% +28.78%
Total 9.21M ± 0% 9.58M ± 0% +4.01%
Updates #19348.
Change-Id: Ic4f180c3b516018138236b0c35e0218270d957d3
Reviewed-on: https://go-review.googlesource.com/37231
Run-TryBot: David Lazar <lazard@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Austin Clements <austin@google.com>
2017-02-17 12:28:05 -05:00
}
2015-02-27 22:57:28 -05:00
// pcdata
2016-08-19 22:40:38 -04:00
off = addpctab ( ctxt , ftab , off , & pcln . Pcsp )
2015-02-27 22:57:28 -05:00
2016-08-19 22:40:38 -04:00
off = addpctab ( ctxt , ftab , off , & pcln . Pcfile )
off = addpctab ( ctxt , ftab , off , & pcln . Pcline )
2017-09-30 15:06:44 +00:00
off = int32 ( ftab . SetUint32 ( ctxt . Arch , int64 ( off ) , uint32 ( len ( pcln . Pcdata ) ) ) )
2018-09-11 15:14:28 -07:00
// funcID uint8
2018-12-04 07:58:18 -08:00
var file string
if s . FuncInfo != nil && len ( s . FuncInfo . File ) > 0 {
file = s . FuncInfo . File [ 0 ] . Name
2018-09-11 15:14:28 -07:00
}
2018-12-04 07:58:18 -08:00
funcID := objabi . GetFuncID ( s . Name , file )
2018-09-11 15:14:28 -07:00
off = int32 ( ftab . SetUint8 ( ctxt . Arch , int64 ( off ) , uint8 ( funcID ) ) )
// unused
off += 2
// nfuncdata must be the final entry.
off = int32 ( ftab . SetUint8 ( ctxt . Arch , int64 ( off ) , uint8 ( len ( pcln . Funcdata ) ) ) )
2018-04-06 21:41:06 +01:00
for i := range pcln . Pcdata {
2016-08-19 22:40:38 -04:00
off = addpctab ( ctxt , ftab , off , & pcln . Pcdata [ i ] )
2015-02-27 22:57:28 -05:00
}
// funcdata, must be pointer-aligned and we're only int32-aligned.
// Missing funcdata will be 0 (nil pointer).
2016-03-23 14:02:36 +02:00
if len ( pcln . Funcdata ) > 0 {
2017-09-30 21:10:49 +00:00
if off & int32 ( ctxt . Arch . PtrSize - 1 ) != 0 {
2015-02-27 22:57:28 -05:00
off += 4
}
2018-04-06 21:41:06 +01:00
for i := range pcln . Funcdata {
2015-02-27 22:57:28 -05:00
if pcln . Funcdata [ i ] == nil {
2017-09-30 15:06:44 +00:00
ftab . SetUint ( ctxt . Arch , int64 ( off ) + int64 ( ctxt . Arch . PtrSize ) * int64 ( i ) , uint64 ( pcln . Funcdataoff [ i ] ) )
2015-02-27 22:57:28 -05:00
} else {
// TODO: Dedup.
2016-08-22 10:33:13 -04:00
funcdataBytes += pcln . Funcdata [ i ] . Size
2015-02-27 22:57:28 -05:00
2017-09-30 15:06:44 +00:00
ftab . SetAddrPlus ( ctxt . Arch , int64 ( off ) + int64 ( ctxt . Arch . PtrSize ) * int64 ( i ) , pcln . Funcdata [ i ] , pcln . Funcdataoff [ i ] )
2015-02-27 22:57:28 -05:00
}
}
2017-09-30 21:10:49 +00:00
off += int32 ( len ( pcln . Funcdata ) ) * int32 ( ctxt . Arch . PtrSize )
2015-02-27 22:57:28 -05:00
}
if off != end {
2017-09-30 21:10:49 +00:00
Errorf ( s , "bad math in functab: funcstart=%d off=%d but end=%d (npcdata=%d nfuncdata=%d ptrsize=%d)" , funcstart , off , end , len ( pcln . Pcdata ) , len ( pcln . Funcdata ) , ctxt . Arch . PtrSize )
2015-04-09 07:37:17 -04:00
errorexit ( )
2015-02-27 22:57:28 -05:00
}
nfunc ++
}
2015-03-16 11:53:08 +13:00
pclntabLastFunc = last
2015-02-27 22:57:28 -05:00
// Final entry of table is just end pc.
2017-09-30 15:06:44 +00:00
ftab . SetAddrPlus ( ctxt . Arch , 8 + int64 ( ctxt . Arch . PtrSize ) + int64 ( nfunc ) * 2 * int64 ( ctxt . Arch . PtrSize ) , last , last . Size )
2015-02-27 22:57:28 -05:00
// Start file table.
2015-03-02 12:35:15 -05:00
start := int32 ( len ( ftab . P ) )
2015-02-27 22:57:28 -05:00
2017-09-30 21:10:49 +00:00
start += int32 ( - len ( ftab . P ) ) & ( int32 ( ctxt . Arch . PtrSize ) - 1 )
2015-03-16 11:53:08 +13:00
pclntabFiletabOffset = start
2017-09-30 15:06:44 +00:00
ftab . SetUint32 ( ctxt . Arch , 8 + int64 ( ctxt . Arch . PtrSize ) + int64 ( nfunc ) * 2 * int64 ( ctxt . Arch . PtrSize ) + int64 ( ctxt . Arch . PtrSize ) , uint32 ( start ) )
2015-02-27 22:57:28 -05:00
2017-09-30 15:06:44 +00:00
ftab . Grow ( int64 ( start ) + ( int64 ( len ( ctxt . Filesyms ) ) + 1 ) * 4 )
ftab . SetUint32 ( ctxt . Arch , int64 ( start ) , uint32 ( len ( ctxt . Filesyms ) + 1 ) )
2016-08-19 22:40:38 -04:00
for i := len ( ctxt . Filesyms ) - 1 ; i >= 0 ; i -- {
s := ctxt . Filesyms [ i ]
2019-04-11 18:05:19 -07:00
ftab . SetUint32 ( ctxt . Arch , int64 ( start ) + s . Value * 4 , uint32 ( ftabaddstring ( ftab , s . Name ) ) )
2015-02-27 22:57:28 -05:00
}
ftab . Size = int64 ( len ( ftab . P ) )
2016-08-21 18:25:28 -04:00
if ctxt . Debugvlog != 0 {
2017-04-18 12:53:25 -07:00
ctxt . Logf ( "%5.2f pclntab=%d bytes, funcdata total %d bytes\n" , Cputime ( ) , ftab . Size , funcdataBytes )
2015-02-27 22:57:28 -05:00
}
}
cmd/link: set runtime.GOROOT default during link
Suppose you build the Go toolchain in directory A,
move the whole thing to directory B, and then use
it from B to build a new program hello.exe, and then
run hello.exe, and hello.exe crashes with a stack
trace into the standard library.
Long ago, you'd have seen hello.exe print file names
in the A directory tree, even though the files had moved
to the B directory tree. About two years ago we changed
the compiler to write down these files with the name
"$GOROOT" (that literal string) instead of A, so that the
final link from B could replace "$GOROOT" with B,
so that hello.exe's crash would show the correct source
file paths in the stack trace. (golang.org/cl/18200)
Now suppose that you do the same thing but hello.exe
doesn't crash: it prints fmt.Println(runtime.GOROOT()).
And you run hello.exe after clearing $GOROOT from the
environment.
Long ago, you'd have seen hello.exe print A instead of B.
Before this CL, you'd still see hello.exe print A instead of B.
This case is the one instance where a moved toolchain
still divulges its origin. Not anymore. After this CL, hello.exe
will print B, because the linker sets runtime/internal/sys.DefaultGoroot
with the effective GOROOT from link time.
This makes the default result of runtime.GOROOT once again
match the file names recorded in the binary, after two years
of divergence.
With that cleared up, we can reintroduce GOROOT into the
link action ID and also reenable TestExecutableGOROOT/RelocatedExe.
When $GOROOT_FINAL is set during link, it is used
in preference to $GOROOT, as always, but it was easier
to explain the behavior above without introducing that
complication.
Fixes #22155.
Fixes #20284.
Fixes #22475.
Change-Id: Ifdaeb77fd4678fdb337cf59ee25b2cd873ec1016
Reviewed-on: https://go-review.googlesource.com/86835
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2018-01-08 11:59:29 -05:00
func gorootFinal ( ) string {
root := objabi . GOROOT
if final := os . Getenv ( "GOROOT_FINAL" ) ; final != "" {
root = final
}
return root
}
2015-12-29 10:16:40 -05:00
func expandGoroot ( s string ) string {
const n = len ( "$GOROOT" )
if len ( s ) >= n + 1 && s [ : n ] == "$GOROOT" && ( s [ n ] == '/' || s [ n ] == '\\' ) {
cmd/link: set runtime.GOROOT default during link
Suppose you build the Go toolchain in directory A,
move the whole thing to directory B, and then use
it from B to build a new program hello.exe, and then
run hello.exe, and hello.exe crashes with a stack
trace into the standard library.
Long ago, you'd have seen hello.exe print file names
in the A directory tree, even though the files had moved
to the B directory tree. About two years ago we changed
the compiler to write down these files with the name
"$GOROOT" (that literal string) instead of A, so that the
final link from B could replace "$GOROOT" with B,
so that hello.exe's crash would show the correct source
file paths in the stack trace. (golang.org/cl/18200)
Now suppose that you do the same thing but hello.exe
doesn't crash: it prints fmt.Println(runtime.GOROOT()).
And you run hello.exe after clearing $GOROOT from the
environment.
Long ago, you'd have seen hello.exe print A instead of B.
Before this CL, you'd still see hello.exe print A instead of B.
This case is the one instance where a moved toolchain
still divulges its origin. Not anymore. After this CL, hello.exe
will print B, because the linker sets runtime/internal/sys.DefaultGoroot
with the effective GOROOT from link time.
This makes the default result of runtime.GOROOT once again
match the file names recorded in the binary, after two years
of divergence.
With that cleared up, we can reintroduce GOROOT into the
link action ID and also reenable TestExecutableGOROOT/RelocatedExe.
When $GOROOT_FINAL is set during link, it is used
in preference to $GOROOT, as always, but it was easier
to explain the behavior above without introducing that
complication.
Fixes #22155.
Fixes #20284.
Fixes #22475.
Change-Id: Ifdaeb77fd4678fdb337cf59ee25b2cd873ec1016
Reviewed-on: https://go-review.googlesource.com/86835
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2018-01-08 11:59:29 -05:00
return filepath . ToSlash ( filepath . Join ( gorootFinal ( ) , s [ n : ] ) )
2015-12-29 10:16:40 -05:00
}
return s
}
2015-02-27 22:57:28 -05:00
const (
BUCKETSIZE = 256 * MINFUNC
SUBBUCKETS = 16
SUBBUCKETSIZE = BUCKETSIZE / SUBBUCKETS
NOIDX = 0x7fffffff
)
// findfunctab generates a lookup table to quickly find the containing
2016-03-01 23:21:55 +00:00
// function for a pc. See src/runtime/symtab.go:findfunc for details.
2016-08-19 22:40:38 -04:00
func ( ctxt * Link ) findfunctab ( ) {
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
t := ctxt . Syms . Lookup ( "runtime.findfunctab" , 0 )
2017-10-04 17:54:04 -04:00
t . Type = sym . SRODATA
t . Attr |= sym . AttrReachable
t . Attr |= sym . AttrLocal
2015-02-27 22:57:28 -05:00
// find min and max address
2016-08-19 22:40:38 -04:00
min := ctxt . Textp [ 0 ] . Value
2018-11-19 11:24:12 +08:00
lastp := ctxt . Textp [ len ( ctxt . Textp ) - 1 ]
max := lastp . Value + lastp . Size
2015-02-27 22:57:28 -05:00
// for each subbucket, compute the minimum of all symbol indexes
// that map to that subbucket.
2015-03-02 12:35:15 -05:00
n := int32 ( ( max - min + SUBBUCKETSIZE - 1 ) / SUBBUCKETSIZE )
2015-02-27 22:57:28 -05:00
2015-03-02 12:35:15 -05:00
indexes := make ( [ ] int32 , n )
for i := int32 ( 0 ) ; i < n ; i ++ {
2015-02-27 22:57:28 -05:00
indexes [ i ] = NOIDX
}
2015-03-02 12:35:15 -05:00
idx := int32 ( 0 )
2016-08-19 22:40:38 -04:00
for i , s := range ctxt . Textp {
2017-10-05 10:20:17 -04:00
if ! emitPcln ( ctxt , s ) {
2015-02-27 22:57:28 -05:00
continue
}
2016-04-19 14:02:21 -04:00
p := s . Value
2017-10-04 17:54:04 -04:00
var e * sym . Symbol
2016-04-19 14:02:21 -04:00
i ++
2016-08-19 22:40:38 -04:00
if i < len ( ctxt . Textp ) {
e = ctxt . Textp [ i ]
2016-04-19 14:02:21 -04:00
}
2017-10-05 10:20:17 -04:00
for ! emitPcln ( ctxt , e ) && i < len ( ctxt . Textp ) {
2016-08-19 22:40:38 -04:00
e = ctxt . Textp [ i ]
2016-04-19 14:02:21 -04:00
i ++
2015-02-27 22:57:28 -05:00
}
2016-04-19 14:02:21 -04:00
q := max
2015-02-27 22:57:28 -05:00
if e != nil {
q = e . Value
}
//print("%d: [%lld %lld] %s\n", idx, p, q, s->name);
for ; p < q ; p += SUBBUCKETSIZE {
2016-04-19 14:02:21 -04:00
i = int ( ( p - min ) / SUBBUCKETSIZE )
2015-02-27 22:57:28 -05:00
if indexes [ i ] > idx {
indexes [ i ] = idx
}
}
2016-04-19 14:02:21 -04:00
i = int ( ( q - 1 - min ) / SUBBUCKETSIZE )
2015-02-27 22:57:28 -05:00
if indexes [ i ] > idx {
indexes [ i ] = idx
}
idx ++
}
// allocate table
2015-03-02 12:35:15 -05:00
nbuckets := int32 ( ( max - min + BUCKETSIZE - 1 ) / BUCKETSIZE )
2015-02-27 22:57:28 -05:00
2017-09-30 15:06:44 +00:00
t . Grow ( 4 * int64 ( nbuckets ) + int64 ( n ) )
2015-02-27 22:57:28 -05:00
// fill in table
2015-03-02 12:35:15 -05:00
for i := int32 ( 0 ) ; i < nbuckets ; i ++ {
2016-04-19 14:02:21 -04:00
base := indexes [ i * SUBBUCKETS ]
2015-02-27 22:57:28 -05:00
if base == NOIDX {
2016-09-17 09:39:33 -04:00
Errorf ( nil , "hole in findfunctab" )
2015-02-27 22:57:28 -05:00
}
2017-09-30 15:06:44 +00:00
t . SetUint32 ( ctxt . Arch , int64 ( i ) * ( 4 + SUBBUCKETS ) , uint32 ( base ) )
2016-04-19 14:02:21 -04:00
for j := int32 ( 0 ) ; j < SUBBUCKETS && i * SUBBUCKETS + j < n ; j ++ {
2015-02-27 22:57:28 -05:00
idx = indexes [ i * SUBBUCKETS + j ]
if idx == NOIDX {
2016-09-17 09:39:33 -04:00
Errorf ( nil , "hole in findfunctab" )
2015-02-27 22:57:28 -05:00
}
if idx - base >= 256 {
2016-09-17 09:39:33 -04:00
Errorf ( nil , "too many functions in a findfunc bucket! %d/%d %d %d" , i , nbuckets , j , idx - base )
2015-02-27 22:57:28 -05:00
}
2017-09-30 15:06:44 +00:00
t . SetUint8 ( ctxt . Arch , int64 ( i ) * ( 4 + SUBBUCKETS ) + 4 + int64 ( j ) , uint8 ( idx - base ) )
2015-02-27 22:57:28 -05:00
}
}
}