Skip to content

Instantly share code, notes, and snippets.

@alexander-hanel
Last active April 23, 2021 23:58
Show Gist options
  • Save alexander-hanel/98bca0aefec7f3b6bd5585d9eb64146a to your computer and use it in GitHub Desktop.
Save alexander-hanel/98bca0aefec7f3b6bd5585d9eb64146a to your computer and use it in GitHub Desktop.
Go 1.16 File Update Notes

New moduledata format

type moduledata struct {
	pcHeader     *pcHeader
	funcnametab  []byte
	cutab        []uint32
	filetab      []byte
	pctab        []byte
	pclntable    []byte
	ftab         []functab
	findfunctab  uintptr
	minpc, maxpc uintptr

	text, etext           uintptr
	noptrdata, enoptrdata uintptr
	data, edata           uintptr
	bss, ebss             uintptr
	noptrbss, enoptrbss   uintptr
	end, gcdata, gcbss    uintptr
	types, etypes         uintptr

	textsectmap []textsect
	typelinks   []int32 // offsets from types
	itablinks   []*itab

	ptab []ptabEntry

	pluginpath string
	pkghashes  []modulehash

	modulename   string
	modulehashes []modulehash

	hasmain uint8 // 1 if module contains the main function, 0 otherwise

	gcdatamask, gcbssmask bitvector

	typemap map[typeOff]*_type // offset to *_rtype in previous module

	bad bool // module failed to load and should be ignored

	next *moduledata
}

https://github.com/golang/go/blob/a54f7fc0fde79e8edc696de002fe8a73604f077f/src/runtime/symtab.go#L378

New Magic Value

go116magic 
magic          uint32  // 0xFFFFFFFA

New PCHeader

type pcHeader struct {
	magic          uint32  // 0xFFFFFFFA
	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.
	funcnameOffset uintptr // offset to the funcnametab variable from pcHeader
	cuOffset       uintptr // offset to the cutab variable from pcHeader
	filetabOffset  uintptr // offset to the filetab variable from pcHeader
	pctabOffset    uintptr // offset to the pctab varible from pcHeader
	pclnOffset     uintptr // offset to the pclntab variable from pcHeader
}

https://github.com/golang/go/blob/a54f7fc0fde79e8edc696de002fe8a73604f077f/src/runtime/symtab.go#L359

runtime.cutab

Creates two new symbols: runtime.cutab, and runtime.filetab, and strips the filenames out of runtime.pclntab_old.

https://github.com/golang/go/commit/9ae8f71c9431d287893443fa2b7fbdb72a9b56a2

Logic to parse the different formats

	// Check header: 4-byte magic, two zeros, pc quantum, pointer size.
	if len(t.Data) < 16 || t.Data[4] != 0 || t.Data[5] != 0 ||
		(t.Data[6] != 1 && t.Data[6] != 2 && t.Data[6] != 4) || // pc quantum
		(t.Data[7] != 4 && t.Data[7] != 8) { // pointer size
		return
	}

	var possibleVersion version
	leMagic := binary.LittleEndian.Uint32(t.Data)
	beMagic := binary.BigEndian.Uint32(t.Data)
	switch {
	case leMagic == go12magic:
		t.binary, possibleVersion = binary.LittleEndian, ver12
	case beMagic == go12magic:
		t.binary, possibleVersion = binary.BigEndian, ver12
	case leMagic == go116magic:
		t.binary, possibleVersion = binary.LittleEndian, ver116
	case beMagic == go116magic:
		t.binary, possibleVersion = binary.BigEndian, ver116
	default:
		return
	}

	// quantum and ptrSize are the same between 1.2 and 1.16
	t.quantum = uint32(t.Data[6])
	t.ptrsize = uint32(t.Data[7])

	switch possibleVersion {
	case ver116:
		t.nfunctab = uint32(t.uintptr(t.Data[8:]))
		t.nfiletab = uint32(t.uintptr(t.Data[8+t.ptrsize:]))
		offset := t.uintptr(t.Data[8+2*t.ptrsize:])
		t.funcnametab = t.Data[offset:]
		offset = t.uintptr(t.Data[8+3*t.ptrsize:])
		t.cutab = t.Data[offset:]
		offset = t.uintptr(t.Data[8+4*t.ptrsize:])
		t.filetab = t.Data[offset:]
		offset = t.uintptr(t.Data[8+5*t.ptrsize:])
		t.pctab = t.Data[offset:]
		offset = t.uintptr(t.Data[8+6*t.ptrsize:])
		t.funcdata = t.Data[offset:]
		t.functab = t.Data[offset:]
		functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
		t.functab = t.functab[:functabsize]
	case ver12:
		t.nfunctab = uint32(t.uintptr(t.Data[8:]))
		t.funcdata = t.Data
		t.funcnametab = t.Data
		t.functab = t.Data[8+t.ptrsize:]
		t.pctab = t.Data
		functabsize := t.nfunctab*2*t.ptrsize + t.ptrsize
		fileoff := t.binary.Uint32(t.functab[functabsize:])
		t.functab = t.functab[:functabsize]
		t.filetab = t.Data[fileoff:]
		t.nfiletab = t.binary.Uint32(t.filetab)
		t.filetab = t.filetab[:t.nfiletab*4]
	default:
		panic("unreachable")
	}
	t.version = possibleVersion

https://github.com/golang/go/blob/master/src/debug/gosym/pclntab.go

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment