mirror of https://github.com/golang/go.git
Compare commits
9 Commits
1f4758a159
...
e3c24e406c
| Author | SHA1 | Date |
|---|---|---|
|
|
e3c24e406c | |
|
|
49cdf0c42e | |
|
|
3bf1eecbd3 | |
|
|
8ed23a2936 | |
|
|
ef60769b46 | |
|
|
cefd445939 | |
|
|
a2c54efd5f | |
|
|
182a289ef3 | |
|
|
900bf7e125 |
|
|
@ -176,22 +176,34 @@ func dumpGlobalConst(n *ir.Name) {
|
|||
return
|
||||
}
|
||||
// only export integer constants for now
|
||||
if !t.IsInteger() {
|
||||
if !t.IsInteger() && !t.IsString() {
|
||||
return
|
||||
}
|
||||
v := n.Val()
|
||||
if t.IsUntyped() {
|
||||
// Export untyped integers as int (if they fit).
|
||||
t = types.Types[types.TINT]
|
||||
if ir.ConstOverflow(v, t) {
|
||||
return
|
||||
if t.IsInteger() {
|
||||
// Export untyped integers as int (if they fit).
|
||||
t = types.Types[types.TINT]
|
||||
if ir.ConstOverflow(v, t) {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
t = types.Types[types.TSTRING]
|
||||
}
|
||||
} else {
|
||||
// If the type of the constant is an instantiated generic, we need to emit
|
||||
// that type so the linker knows about it. See issue 51245.
|
||||
_ = reflectdata.TypeLinksym(t)
|
||||
if t.IsInteger() {
|
||||
// If the type of the constant is an instantiated generic, we need to emit
|
||||
// that type so the linker knows about it. See issue 51245.
|
||||
_ = reflectdata.TypeLinksym(t)
|
||||
}
|
||||
// For const string, type:string isn't the real type.
|
||||
}
|
||||
|
||||
if t.IsInteger() {
|
||||
base.Ctxt.DwarfIntConst(n.Sym().Name, types.TypeSymName(t), ir.IntVal(t, v))
|
||||
} else if t.IsString() {
|
||||
base.Ctxt.DwarfStringConst(n.Sym().Name, types.TypeSymName(t), ir.StringVal(n))
|
||||
}
|
||||
base.Ctxt.DwarfIntConst(n.Sym().Name, types.TypeSymName(t), ir.IntVal(t, v))
|
||||
}
|
||||
|
||||
// addGCLocals adds gcargs, gclocals, gcregs, and stack object symbols to Ctxt.Data.
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ const InfoPrefix = "go:info."
|
|||
// entries that contain constants.
|
||||
const ConstInfoPrefix = "go:constinfo."
|
||||
|
||||
// ConstStringInfoPrefix is the prefix for all symbols containing
|
||||
// DWARF info entries that are referred by string constants.
|
||||
const ConstStringInfoPrefix = "$const."
|
||||
|
||||
// CUInfoPrefix is the prefix for symbols containing information to
|
||||
// populate the DWARF compilation unit info entries.
|
||||
const CUInfoPrefix = "go:cuinfo."
|
||||
|
|
@ -336,6 +340,7 @@ const (
|
|||
DW_ABRV_INLINED_SUBROUTINE_RANGES
|
||||
DW_ABRV_VARIABLE
|
||||
DW_ABRV_INT_CONSTANT
|
||||
DW_ABRV_STRING_CONSTANT
|
||||
DW_ABRV_LEXICAL_BLOCK_RANGES
|
||||
DW_ABRV_LEXICAL_BLOCK_SIMPLE
|
||||
DW_ABRV_STRUCTFIELD
|
||||
|
|
@ -354,6 +359,7 @@ const (
|
|||
DW_ABRV_BARE_PTRTYPE // only for void*, no DW_AT_type attr to please gdb 6.
|
||||
DW_ABRV_SLICETYPE
|
||||
DW_ABRV_STRINGTYPE
|
||||
DW_ABRV_CONSTANT_STRINGTYPE
|
||||
DW_ABRV_STRUCTTYPE
|
||||
DW_ABRV_TYPEDECL
|
||||
DW_ABRV_DICT_INDEX
|
||||
|
|
@ -575,7 +581,7 @@ var abbrevs = []dwAbbrev{
|
|||
},
|
||||
},
|
||||
|
||||
/* INT CONSTANT */
|
||||
/* INT_CONSTANT */
|
||||
{
|
||||
DW_TAG_constant,
|
||||
DW_CHILDREN_no,
|
||||
|
|
@ -586,6 +592,17 @@ var abbrevs = []dwAbbrev{
|
|||
},
|
||||
},
|
||||
|
||||
/* STRING_CONSTANT */
|
||||
{
|
||||
DW_TAG_constant,
|
||||
DW_CHILDREN_no,
|
||||
[]dwAttrForm{
|
||||
{DW_AT_name, DW_FORM_string},
|
||||
{DW_AT_type, DW_FORM_ref_addr},
|
||||
{DW_AT_const_value, DW_FORM_block1},
|
||||
},
|
||||
},
|
||||
|
||||
/* LEXICAL_BLOCK_RANGES */
|
||||
{
|
||||
DW_TAG_lexical_block,
|
||||
|
|
@ -807,6 +824,16 @@ var abbrevs = []dwAbbrev{
|
|||
},
|
||||
},
|
||||
|
||||
/* CONSTANT_STRINGTYPE */
|
||||
{
|
||||
DW_TAG_string_type,
|
||||
DW_CHILDREN_no,
|
||||
[]dwAttrForm{
|
||||
{DW_AT_name, DW_FORM_string},
|
||||
{DW_AT_byte_size, DW_FORM_udata},
|
||||
},
|
||||
},
|
||||
|
||||
/* STRUCTTYPE */
|
||||
{
|
||||
DW_TAG_structure_type,
|
||||
|
|
@ -1031,6 +1058,14 @@ func PutIntConst(ctxt Context, info, typ Sym, name string, val int64) {
|
|||
putattr(ctxt, info, DW_ABRV_INT_CONSTANT, DW_FORM_sdata, DW_CLS_CONSTANT, val, nil)
|
||||
}
|
||||
|
||||
// PutStringConst writes a DIE for a string constant
|
||||
func PutStringConst(ctxt Context, info, typ Sym, name string, val string) {
|
||||
Uleb128put(ctxt, info, DW_ABRV_STRING_CONSTANT)
|
||||
putattr(ctxt, info, DW_ABRV_STRING_CONSTANT, DW_FORM_string, DW_CLS_STRING, int64(len(name)), name)
|
||||
putattr(ctxt, info, DW_ABRV_STRING_CONSTANT, DW_FORM_ref_addr, DW_CLS_REFERENCE, 0, typ)
|
||||
putattr(ctxt, info, DW_ABRV_STRING_CONSTANT, DW_FORM_block1, DW_CLS_BLOCK, int64(len(val)), []byte(val))
|
||||
}
|
||||
|
||||
// PutGlobal writes a DIE for a global variable.
|
||||
func PutGlobal(ctxt Context, info, typ, gvar Sym, name string) {
|
||||
Uleb128put(ctxt, info, DW_ABRV_VARIABLE)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import (
|
|||
"cmd/internal/src"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
|
@ -393,18 +394,38 @@ func (ctxt *Link) populateDWARF(curfn Func, s *LSym) {
|
|||
ctxt.generateDebugLinesSymbol(s, lines)
|
||||
}
|
||||
|
||||
// DwarfIntConst creates a link symbol for an integer constant with the
|
||||
// given name, type and value.
|
||||
func (ctxt *Link) DwarfIntConst(name, typename string, val int64) {
|
||||
// ensureConstInfoSym ensures that the DWARF constant info symbol exists
|
||||
func (ctxt *Link) ensureConstInfoSym() *LSym {
|
||||
myimportpath := ctxt.Pkgpath
|
||||
if myimportpath == "" {
|
||||
return
|
||||
return nil
|
||||
}
|
||||
s := ctxt.LookupInit(dwarf.ConstInfoPrefix+myimportpath, func(s *LSym) {
|
||||
s.Type = objabi.SDWARFCONST
|
||||
ctxt.Data = append(ctxt.Data, s)
|
||||
})
|
||||
dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), myimportpath+"."+name, val)
|
||||
return s
|
||||
}
|
||||
|
||||
// DwarfIntConst creates a link symbol for an integer constant with the
|
||||
// given name, type and value.
|
||||
func (ctxt *Link) DwarfIntConst(name, typename string, val int64) {
|
||||
s := ctxt.ensureConstInfoSym()
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
dwarf.PutIntConst(dwCtxt{ctxt}, s, ctxt.Lookup(dwarf.InfoPrefix+typename), ctxt.Pkgpath+"."+name, val)
|
||||
}
|
||||
|
||||
// DwarfStringConst creates a link symbol for a string constant with the
|
||||
// given name and value.
|
||||
func (ctxt *Link) DwarfStringConst(name, typename, value string) {
|
||||
s := ctxt.ensureConstInfoSym()
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
typSym := ctxt.Lookup(dwarf.InfoPrefix + dwarf.ConstStringInfoPrefix + typename + "." + strconv.Itoa(len(value)))
|
||||
dwarf.PutStringConst(dwCtxt{ctxt}, s, typSym, ctxt.Pkgpath+"."+name, value)
|
||||
}
|
||||
|
||||
// DwarfGlobal creates a link symbol containing a DWARF entry for
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import (
|
|||
"path"
|
||||
"runtime"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
|
@ -285,13 +286,16 @@ func (d *dwctxt) newdie(parent *dwarf.DWDie, abbrev int, name string) *dwarf.DWD
|
|||
die.Link = parent.Child
|
||||
parent.Child = die
|
||||
|
||||
newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(name)), name)
|
||||
|
||||
// Sanity check: all DIEs created in the linker should be named.
|
||||
if name == "" {
|
||||
panic("nameless DWARF DIE")
|
||||
}
|
||||
|
||||
// for constant string types, we emit the nams later since it didn't use symbol name as DW_AT_name
|
||||
if abbrev != dwarf.DW_ABRV_CONSTANT_STRINGTYPE {
|
||||
newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(name)), name)
|
||||
}
|
||||
|
||||
var st sym.SymKind
|
||||
switch abbrev {
|
||||
case dwarf.DW_ABRV_FUNCTYPEPARAM, dwarf.DW_ABRV_FUNCTYPEOUTPARAM, dwarf.DW_ABRV_DOTDOTDOT, dwarf.DW_ABRV_STRUCTFIELD, dwarf.DW_ABRV_ARRAYRANGE:
|
||||
|
|
@ -1183,6 +1187,24 @@ func getCompilationDir() string {
|
|||
return "."
|
||||
}
|
||||
|
||||
func (d *dwctxt) genConstStringType(name string) {
|
||||
if d.find(name) != 0 {
|
||||
return
|
||||
}
|
||||
i := strings.LastIndex(name, ".")
|
||||
if i < 0 {
|
||||
log.Fatalf("error: invalid constant string type name %q", name)
|
||||
}
|
||||
size, err := strconv.ParseInt(name[i+1:], 10, 64)
|
||||
if err != nil {
|
||||
log.Fatalf("error: invalid constant string type name %q: %v", name, err)
|
||||
}
|
||||
atname := name[len(dwarf.ConstStringInfoPrefix):i]
|
||||
die := d.newdie(&dwtypes, dwarf.DW_ABRV_CONSTANT_STRINGTYPE, name)
|
||||
newattr(die, dwarf.DW_AT_name, dwarf.DW_CLS_STRING, int64(len(atname)), atname)
|
||||
newattr(die, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, size, 0)
|
||||
}
|
||||
|
||||
func (d *dwctxt) importInfoSymbol(dsym loader.Sym) {
|
||||
d.ldr.SetAttrReachable(dsym, true)
|
||||
d.ldr.SetAttrNotInSymbolTable(dsym, true)
|
||||
|
|
@ -1207,6 +1229,15 @@ func (d *dwctxt) importInfoSymbol(dsym loader.Sym) {
|
|||
// symbol name here?
|
||||
sn := d.ldr.SymName(rsym)
|
||||
tn := sn[len(dwarf.InfoPrefix):]
|
||||
|
||||
// If the symbol is a constant string type, we generate it
|
||||
// These types do not exist in go,
|
||||
// but can tell gdb how to interpret the corresponding values
|
||||
if strings.HasPrefix(tn, dwarf.ConstStringInfoPrefix) {
|
||||
d.genConstStringType(tn)
|
||||
continue
|
||||
}
|
||||
|
||||
ts := d.ldr.Lookup("type:"+tn, 0)
|
||||
d.defgotype(ts)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ func newGCM(cipher Block, nonceSize, tagSize int) (AEAD, error) {
|
|||
|
||||
// NewGCMWithRandomNonce returns the given cipher wrapped in Galois Counter
|
||||
// Mode, with randomly-generated nonces. The cipher must have been created by
|
||||
// [aes.NewCipher].
|
||||
// [crypto/aes.NewCipher].
|
||||
//
|
||||
// It generates a random 96-bit nonce, which is prepended to the ciphertext by Seal,
|
||||
// and is extracted from the ciphertext by Open. The NonceSize of the AEAD is zero,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
PACKAGE issue62640
|
||||
|
||||
IMPORTPATH
|
||||
testdata/issue62640
|
||||
|
||||
FILENAMES
|
||||
testdata/issue62640.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type E struct{}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (E) F()
|
||||
|
||||
//
|
||||
type S struct {
|
||||
E
|
||||
F int
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//
|
||||
PACKAGE issue62640
|
||||
|
||||
IMPORTPATH
|
||||
testdata/issue62640
|
||||
|
||||
FILENAMES
|
||||
testdata/issue62640.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type E struct{}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (E) F()
|
||||
|
||||
//
|
||||
type S struct {
|
||||
E
|
||||
F int
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//
|
||||
PACKAGE issue62640
|
||||
|
||||
IMPORTPATH
|
||||
testdata/issue62640
|
||||
|
||||
FILENAMES
|
||||
testdata/issue62640.go
|
||||
|
||||
TYPES
|
||||
//
|
||||
type E struct{}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (E) F()
|
||||
|
||||
//
|
||||
type S struct {
|
||||
E
|
||||
F int
|
||||
}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (S) F()
|
||||
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2025 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.
|
||||
|
||||
package issue62640
|
||||
|
||||
type E struct{}
|
||||
|
||||
// F should be hidden within S because of the S.F field.
|
||||
func (E) F() {}
|
||||
|
||||
type S struct {
|
||||
E
|
||||
F int
|
||||
}
|
||||
|
|
@ -312,8 +312,10 @@ type heapArena struct {
|
|||
// during marking.
|
||||
pageSpecials [pagesPerArena / 8]uint8
|
||||
|
||||
// pageUseSpanDartboard is a bitmap that indicates which spans are
|
||||
// heap spans and also gcUsesSpanDartboard.
|
||||
// pageUseSpanInlineMarkBits is a bitmap where each bit corresponds
|
||||
// to a span, as only spans one page in size can have inline mark bits.
|
||||
// The bit indicates that the span has a spanInlineMarkBits struct
|
||||
// stored directly at the top end of the span's memory.
|
||||
pageUseSpanInlineMarkBits [pagesPerArena / 8]uint8
|
||||
|
||||
// checkmarks stores the debug.gccheckmark state. It is only
|
||||
|
|
|
|||
|
|
@ -662,6 +662,9 @@ package main
|
|||
const aConstant int = 42
|
||||
const largeConstant uint64 = ^uint64(0)
|
||||
const minusOne int64 = -1
|
||||
const typedS string = "typed string"
|
||||
const untypedS = "untyped string"
|
||||
const nulS string = "\x00str"
|
||||
|
||||
func main() {
|
||||
println("hello world")
|
||||
|
|
@ -700,6 +703,9 @@ func TestGdbConst(t *testing.T) {
|
|||
"-ex", "print main.minusOne",
|
||||
"-ex", "print 'runtime.mSpanInUse'",
|
||||
"-ex", "print 'runtime._PageSize'",
|
||||
"-ex", "print main.typedS",
|
||||
"-ex", "print main.untypedS",
|
||||
"-ex", "print main.nulS",
|
||||
filepath.Join(dir, "a.exe"),
|
||||
}
|
||||
gdbArgsFixup(args)
|
||||
|
|
@ -711,7 +717,14 @@ func TestGdbConst(t *testing.T) {
|
|||
|
||||
sgot := strings.ReplaceAll(string(got), "\r\n", "\n")
|
||||
|
||||
if !strings.Contains(sgot, "\n$1 = 42\n$2 = 18446744073709551615\n$3 = -1\n$4 = 1 '\\001'\n$5 = 8192") {
|
||||
if !strings.Contains(sgot, `$1 = 42
|
||||
$2 = 18446744073709551615
|
||||
$3 = -1
|
||||
$4 = 1 '\001'
|
||||
$5 = 8192
|
||||
$6 = "typed string"
|
||||
$7 = "untyped string"
|
||||
$8 = "\000str"`) {
|
||||
t.Fatalf("output mismatch")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2025 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.
|
||||
|
||||
package synctest_test
|
||||
|
||||
import "testing"
|
||||
|
||||
// helperLog is a t.Helper which logs.
|
||||
// Since it is a helper, the log prefix should contain
|
||||
// the caller's file, not helper_test.go.
|
||||
func helperLog(t *testing.T, s string) {
|
||||
t.Helper()
|
||||
t.Log(s)
|
||||
}
|
||||
|
|
@ -140,6 +140,18 @@ func TestRun(t *testing.T) {
|
|||
})
|
||||
}
|
||||
|
||||
func TestHelper(t *testing.T) {
|
||||
runTest(t, []string{"-test.v"}, func() {
|
||||
synctest.Test(t, func(t *testing.T) {
|
||||
helperLog(t, "log in helper")
|
||||
})
|
||||
}, `^=== RUN TestHelper
|
||||
synctest_test.go:.* log in helper
|
||||
--- PASS: TestHelper.*
|
||||
PASS
|
||||
$`)
|
||||
}
|
||||
|
||||
func wantPanic(t *testing.T, want string) {
|
||||
if e := recover(); e != nil {
|
||||
if got := fmt.Sprint(e); got != want {
|
||||
|
|
|
|||
|
|
@ -1261,6 +1261,9 @@ func (c *common) Skipped() bool {
|
|||
// When printing file and line information, that function will be skipped.
|
||||
// Helper may be called simultaneously from multiple goroutines.
|
||||
func (c *common) Helper() {
|
||||
if c.isSynctest {
|
||||
c = c.parent
|
||||
}
|
||||
c.mu.Lock()
|
||||
defer c.mu.Unlock()
|
||||
if c.helperPCs == nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue