// Write header.
// Keep in sync with runtime/symtab.go:pcHeader and package debug/gosym.
- header.SetUint32(ctxt.Arch, 0, 0xfffffff1)
+ header.SetUint32(ctxt.Arch, 0, uint32(abi.CurrentPCLnTabMagic))
header.SetUint8(ctxt.Arch, 6, uint8(ctxt.Arch.MinLC))
header.SetUint8(ctxt.Arch, 7, uint8(ctxt.Arch.PtrSize))
off := header.SetUint(ctxt.Arch, 8, uint64(state.nfunc))
import (
"bytes"
"encoding/binary"
+ "internal/abi"
"sort"
"sync"
)
return t.version >= ver12
}
-const (
- go12magic = 0xfffffffb
- go116magic = 0xfffffffa
- go118magic = 0xfffffff0
- go120magic = 0xfffffff1
-)
-
// uintptr returns the pointer-sized value encoded at b.
// The pointer size is dictated by the table being read.
func (t *LineTable) uintptr(b []byte) uint64 {
}
var possibleVersion version
- leMagic := binary.LittleEndian.Uint32(t.Data)
- beMagic := binary.BigEndian.Uint32(t.Data)
+
+ // The magic numbers are chosen such that reading the value with
+ // a different endianness does not result in the same value.
+ // That lets us the magic number to determine the endianness.
+ leMagic := abi.PCLnTabMagic(binary.LittleEndian.Uint32(t.Data))
+ beMagic := abi.PCLnTabMagic(binary.BigEndian.Uint32(t.Data))
+
switch {
- case leMagic == go12magic:
+ case leMagic == abi.Go12PCLnTabMagic:
t.binary, possibleVersion = binary.LittleEndian, ver12
- case beMagic == go12magic:
+ case beMagic == abi.Go12PCLnTabMagic:
t.binary, possibleVersion = binary.BigEndian, ver12
- case leMagic == go116magic:
+ case leMagic == abi.Go116PCLnTabMagic:
t.binary, possibleVersion = binary.LittleEndian, ver116
- case beMagic == go116magic:
+ case beMagic == abi.Go116PCLnTabMagic:
t.binary, possibleVersion = binary.BigEndian, ver116
- case leMagic == go118magic:
+ case leMagic == abi.Go118PCLnTabMagic:
t.binary, possibleVersion = binary.LittleEndian, ver118
- case beMagic == go118magic:
+ case beMagic == abi.Go118PCLnTabMagic:
t.binary, possibleVersion = binary.BigEndian, ver118
- case leMagic == go120magic:
+ case leMagic == abi.Go120PCLnTabMagic:
t.binary, possibleVersion = binary.LittleEndian, ver120
- case beMagic == go120magic:
+ case beMagic == abi.Go120PCLnTabMagic:
t.binary, possibleVersion = binary.BigEndian, ver120
default:
return
package abi
+// PCLnTabMagic is the version at the start of the PC/line table.
+// This is the start of the .pclntab section, and is also runtime.pcHeader.
+// The magic numbers are chosen such that reading the value with
+// a different endianness does not result in the same value.
+// That lets us the magic number to determine the endianness.
+type PCLnTabMagic uint32
+
+const (
+ // Initial PCLnTabMagic value used in Go 1.2 through Go 1.15.
+ Go12PCLnTabMagic PCLnTabMagic = 0xfffffffb
+ // PCLnTabMagic value used in Go 1.16 through Go 1.17.
+ // Several fields added to header (CL 241598).
+ Go116PCLnTabMagic PCLnTabMagic = 0xfffffffa
+ // PCLnTabMagic value used in Go 1.18 through Go 1.19.
+ // Entry PC of func data changed from address to offset (CL 351463).
+ Go118PCLnTabMagic PCLnTabMagic = 0xfffffff0
+ // PCLnTabMagic value used in Go 1.20 and later.
+ // A ":" was added to generated symbol names (#37762).
+ Go120PCLnTabMagic PCLnTabMagic = 0xfffffff1
+
+ // CurrentPCLnTabMagic is the value emitted by the current toolchain.
+ // This is written by the linker to the pcHeader and read by the
+ // runtime and debug/gosym (and external tools like Delve).
+ //
+ // Change this value when updating the pclntab version.
+ // Changing this exported value is OK because is an
+ // internal package.
+ CurrentPCLnTabMagic = Go120PCLnTabMagic
+)
+
// A FuncFlag records bits about a function, passed to the runtime.
type FuncFlag uint8
// pcHeader holds data used by the pclntab lookups.
type pcHeader struct {
- magic uint32 // 0xFFFFFFF1
- pad1, pad2 uint8 // 0,0
- minLC uint8 // min instruction size
- ptrSize uint8 // size of a ptr in bytes
- nfunc int // number of functions in the module
- nfiles uint // number of entries in the file tab
+ magic abi.PCLnTabMagic // abi.Go1NNPcLnTabMagic
+ pad1, pad2 uint8 // 0,0
+ minLC uint8 // min instruction size
+ ptrSize uint8 // size of a ptr in bytes
+ nfunc int // number of functions in the module
+ nfiles uint // number of entries in the file tab
// The next field used to be textStart. This is no longer stored
// as it requires a relocation. Code should use the moduledata text
func moduledataverify1(datap *moduledata) {
// Check that the pclntab's format is valid.
hdr := datap.pcHeader
- if hdr.magic != 0xfffffff1 || hdr.pad1 != 0 || hdr.pad2 != 0 ||
+ if hdr.magic != abi.CurrentPCLnTabMagic || hdr.pad1 != 0 || hdr.pad2 != 0 ||
hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize {
println("runtime: pcHeader: magic=", hex(hdr.magic), "pad1=", hdr.pad1, "pad2=", hdr.pad2,
"minLC=", hdr.minLC, "ptrSize=", hdr.ptrSize, "pluginpath=", datap.pluginpath)