1 // Copyright 2013 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
11 "cmd/link/internal/loader"
12 "cmd/link/internal/sym"
19 // pclntab holds the state needed for pclntab generation.
21 // The size of the func object in the runtime.
24 // The first and last functions found.
25 firstFunc, lastFunc loader.Sym
27 // Running total size of pclntab.
30 // runtime.pclntab's symbols
34 funcnametab loader.Sym
35 findfunctab loader.Sym
40 // The number of functions + number of TEXT sections - 1. This is such an
41 // unexpected value because platforms that have more than one TEXT section
42 // get a dummy function inserted between because the external linker can place
43 // functions in those areas. We mark those areas as not covered by the Go
46 // On most platforms this is the number of reachable functions.
49 // The number of filenames in runtime.filetab.
53 // addGeneratedSym adds a generator symbol to pclntab, returning the new Sym.
54 // It is the caller's responsibility to save they symbol in state.
55 func (state *pclntab) addGeneratedSym(ctxt *Link, name string, size int64, f generatorFunc) loader.Sym {
56 size = Rnd(size, int64(ctxt.Arch.PtrSize))
58 s := ctxt.createGeneratorSymbol(name, 0, sym.SPCLNTAB, size, f)
59 ctxt.loader.SetAttrReachable(s, true)
60 ctxt.loader.SetCarrierSym(s, state.carrier)
61 ctxt.loader.SetAttrNotInSymbolTable(s, true)
65 // makePclntab makes a pclntab object, and assembles all the compilation units
66 // we'll need to write pclntab. Returns the pclntab structure, a slice of the
67 // CompilationUnits we need, and a slice of the function symbols we need to
69 func makePclntab(ctxt *Link, container loader.Bitmap) (*pclntab, []*sym.CompilationUnit, []loader.Sym) {
73 // This is the size of the _func object in runtime/runtime2.go.
74 funcSize: uint32(ctxt.Arch.PtrSize + 9*4),
77 // Gather some basic stats and info.
78 seenCUs := make(map[*sym.CompilationUnit]struct{})
79 prevSect := ldr.SymSect(ctxt.Textp[0])
80 compUnits := []*sym.CompilationUnit{}
81 funcs := []loader.Sym{}
83 for _, s := range ctxt.Textp {
84 if !emitPcln(ctxt, s, container) {
87 funcs = append(funcs, s)
89 if state.firstFunc == 0 {
95 // With multiple text sections, the external linker may
96 // insert functions between the sections, which are not
97 // known by Go. This leaves holes in the PC range covered
98 // by the func table. We need to generate an entry to mark
104 // We need to keep track of all compilation units we see. Some symbols
105 // (eg, go.buildid, _cgoexp_, etc) won't have a compilation unit.
107 if _, ok := seenCUs[cu]; cu != nil && !ok {
108 seenCUs[cu] = struct{}{}
109 cu.PclnIndex = len(compUnits)
110 compUnits = append(compUnits, cu)
113 return state, compUnits, funcs
116 func emitPcln(ctxt *Link, s loader.Sym, container loader.Bitmap) bool {
117 // We want to generate func table entries only for the "lowest
118 // level" symbols, not containers of subsymbols.
119 return !container.Has(s)
122 func computeDeferReturn(ctxt *Link, deferReturnSym, s loader.Sym) uint32 {
124 target := ctxt.Target
125 deferreturn := uint32(0)
126 lastWasmAddr := uint32(0)
128 relocs := ldr.Relocs(s)
129 for ri := 0; ri < relocs.Count(); ri++ {
131 if target.IsWasm() && r.Type() == objabi.R_ADDR {
132 // Wasm does not have a live variable set at the deferreturn
133 // call itself. Instead it has one identified by the
134 // resumption point immediately preceding the deferreturn.
135 // The wasm code has a R_ADDR relocation which is used to
136 // set the resumption point to PC_B.
137 lastWasmAddr = uint32(r.Add())
139 if r.Type().IsDirectCall() && (r.Sym() == deferReturnSym || ldr.IsDeferReturnTramp(r.Sym())) {
141 deferreturn = lastWasmAddr - 1
143 // Note: the relocation target is in the call instruction, but
144 // is not necessarily the whole instruction (for instance, on
145 // x86 the relocation applies to bytes [1:5] of the 5 byte call
147 deferreturn = uint32(r.Off())
148 switch target.Arch.Family {
149 case sys.AMD64, sys.I386:
151 case sys.PPC64, sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64:
154 // TODO(jsing): The JALR instruction is marked with
155 // R_CALLRISCV, whereas the actual reloc is currently
156 // one instruction earlier starting with the AUIPC.
161 panic(fmt.Sprint("Unhandled architecture:", target.Arch.Family))
164 break // only need one
170 // genInlTreeSym generates the InlTree sym for a function with the
171 // specified FuncInfo.
172 func genInlTreeSym(ctxt *Link, cu *sym.CompilationUnit, fi loader.FuncInfo, arch *sys.Arch, nameOffsets map[loader.Sym]uint32) loader.Sym {
174 its := ldr.CreateExtSym("", 0)
175 inlTreeSym := ldr.MakeSymbolUpdater(its)
176 // Note: the generated symbol is given a type of sym.SGOFUNC, as a
177 // signal to the symtab() phase that it needs to be grouped in with
178 // other similar symbols (gcdata, etc); the dodata() phase will
179 // eventually switch the type back to SRODATA.
180 inlTreeSym.SetType(sym.SGOFUNC)
181 ldr.SetAttrReachable(its, true)
182 ninl := fi.NumInlTree()
183 for i := 0; i < int(ninl); i++ {
184 call := fi.InlTree(i)
186 nameoff, ok := nameOffsets[call.Func]
188 panic("couldn't find function name offset")
191 inlTreeSym.SetUint16(arch, int64(i*20+0), uint16(call.Parent))
192 inlFunc := ldr.FuncInfo(call.Func)
194 var funcID objabi.FuncID
196 funcID = inlFunc.FuncID()
198 inlTreeSym.SetUint8(arch, int64(i*20+2), uint8(funcID))
201 inlTreeSym.SetUint32(arch, int64(i*20+4), uint32(val))
202 inlTreeSym.SetUint32(arch, int64(i*20+8), uint32(call.Line))
203 inlTreeSym.SetUint32(arch, int64(i*20+12), uint32(nameoff))
204 inlTreeSym.SetUint32(arch, int64(i*20+16), uint32(call.ParentPC))
209 // makeInlSyms returns a map of loader.Sym that are created inlSyms.
210 func makeInlSyms(ctxt *Link, funcs []loader.Sym, nameOffsets map[loader.Sym]uint32) map[loader.Sym]loader.Sym {
212 // Create the inline symbols we need.
213 inlSyms := make(map[loader.Sym]loader.Sym)
214 for _, s := range funcs {
215 if fi := ldr.FuncInfo(s); fi.Valid() {
217 if fi.NumInlTree() > 0 {
218 inlSyms[s] = genInlTreeSym(ctxt, ldr.SymUnit(s), fi, ctxt.Arch, nameOffsets)
225 // generatePCHeader creates the runtime.pcheader symbol, setting it up as a
226 // generator to fill in its data later.
227 func (state *pclntab) generatePCHeader(ctxt *Link) {
228 writeHeader := func(ctxt *Link, s loader.Sym) {
230 header := ctxt.loader.MakeSymbolUpdater(s)
232 writeSymOffset := func(off int64, ws loader.Sym) int64 {
233 diff := ldr.SymValue(ws) - ldr.SymValue(s)
235 name := ldr.SymName(ws)
236 panic(fmt.Sprintf("expected runtime.pcheader(%x) to be placed before %s(%x)", ldr.SymValue(s), name, ldr.SymValue(ws)))
238 return header.SetUintptr(ctxt.Arch, off, uintptr(diff))
242 // Keep in sync with runtime/symtab.go:pcHeader.
243 header.SetUint32(ctxt.Arch, 0, 0xfffffffa)
244 header.SetUint8(ctxt.Arch, 6, uint8(ctxt.Arch.MinLC))
245 header.SetUint8(ctxt.Arch, 7, uint8(ctxt.Arch.PtrSize))
246 off := header.SetUint(ctxt.Arch, 8, uint64(state.nfunc))
247 off = header.SetUint(ctxt.Arch, off, uint64(state.nfiles))
248 off = writeSymOffset(off, state.funcnametab)
249 off = writeSymOffset(off, state.cutab)
250 off = writeSymOffset(off, state.filetab)
251 off = writeSymOffset(off, state.pctab)
252 off = writeSymOffset(off, state.pclntab)
255 size := int64(8 + 7*ctxt.Arch.PtrSize)
256 state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, writeHeader)
259 // walkFuncs iterates over the funcs, calling a function for each unique
260 // function and inlined function.
261 func walkFuncs(ctxt *Link, funcs []loader.Sym, f func(loader.Sym)) {
263 seen := make(map[loader.Sym]struct{})
264 for _, s := range funcs {
265 if _, ok := seen[s]; !ok {
270 fi := ldr.FuncInfo(s)
275 for i, ni := 0, fi.NumInlTree(); i < int(ni); i++ {
276 call := fi.InlTree(i).Func
277 if _, ok := seen[call]; !ok {
279 seen[call] = struct{}{}
285 // generateFuncnametab creates the function name table. Returns a map of
286 // func symbol to the name offset in runtime.funcnamtab.
287 func (state *pclntab) generateFuncnametab(ctxt *Link, funcs []loader.Sym) map[loader.Sym]uint32 {
288 nameOffsets := make(map[loader.Sym]uint32, state.nfunc)
290 // Write the null terminated strings.
291 writeFuncNameTab := func(ctxt *Link, s loader.Sym) {
292 symtab := ctxt.loader.MakeSymbolUpdater(s)
293 for s, off := range nameOffsets {
294 symtab.AddStringAt(int64(off), ctxt.loader.SymName(s))
298 // Loop through the CUs, and calculate the size needed.
300 walkFuncs(ctxt, funcs, func(s loader.Sym) {
301 nameOffsets[s] = uint32(size)
302 size += int64(ctxt.loader.SymNameLen(s)) + 1 // NULL terminate
305 state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, writeFuncNameTab)
309 // walkFilenames walks funcs, calling a function for each filename used in each
310 // function's line table.
311 func walkFilenames(ctxt *Link, funcs []loader.Sym, f func(*sym.CompilationUnit, goobj.CUFileIndex)) {
314 // Loop through all functions, finding the filenames we need.
315 for _, s := range funcs {
316 fi := ldr.FuncInfo(s)
323 for i, nf := 0, int(fi.NumFile()); i < nf; i++ {
326 for i, ninl := 0, int(fi.NumInlTree()); i < ninl; i++ {
327 call := fi.InlTree(i)
333 // generateFilenameTabs creates LUTs needed for filename lookup. Returns a slice
334 // of the index at which each CU begins in runtime.cutab.
336 // Function objects keep track of the files they reference to print the stack.
337 // This function creates a per-CU list of filenames if CU[M] references
338 // files[1-N], the following is generated:
342 // offsetToFilename[0]
343 // offsetToFilename[1]
350 // Looking up a filename then becomes:
351 // 0) Given a func, and filename index [K]
352 // 1) Get Func.CUIndex: M := func.cuOffset
353 // 2) Find filename offset: fileOffset := runtime.cutab[M+K]
354 // 3) Get the filename: getcstring(runtime.filetab[fileOffset])
355 func (state *pclntab) generateFilenameTabs(ctxt *Link, compUnits []*sym.CompilationUnit, funcs []loader.Sym) []uint32 {
356 // On a per-CU basis, keep track of all the filenames we need.
358 // Note, that we store the filenames in a separate section in the object
359 // files, and deduplicate based on the actual value. It would be better to
360 // store the filenames as symbols, using content addressable symbols (and
361 // then not loading extra filenames), and just use the hash value of the
362 // symbol name to do this cataloging.
364 // TODO: Store filenames as symbols. (Note this would be easiest if you
365 // also move strings to ALWAYS using the larger content addressable hash
366 // function, and use that hash value for uniqueness testing.)
367 cuEntries := make([]goobj.CUFileIndex, len(compUnits))
368 fileOffsets := make(map[string]uint32)
370 // Walk the filenames.
371 // We store the total filename string length we need to load, and the max
372 // file index we've seen per CU so we can calculate how large the
373 // CU->global table needs to be.
375 walkFilenames(ctxt, funcs, func(cu *sym.CompilationUnit, i goobj.CUFileIndex) {
376 // Note we use the raw filename for lookup, but use the expanded filename
377 // when we save the size.
378 filename := cu.FileTable[i]
379 if _, ok := fileOffsets[filename]; !ok {
380 fileOffsets[filename] = uint32(fileSize)
381 fileSize += int64(len(expandFile(filename)) + 1) // NULL terminate
384 // Find the maximum file index we've seen.
385 if cuEntries[cu.PclnIndex] < i+1 {
386 cuEntries[cu.PclnIndex] = i + 1 // Store max + 1
390 // Calculate the size of the runtime.cutab variable.
391 var totalEntries uint32
392 cuOffsets := make([]uint32, len(cuEntries))
393 for i, entries := range cuEntries {
394 // Note, cutab is a slice of uint32, so an offset to a cu's entry is just the
395 // running total of all cu indices we've needed to store so far, not the
396 // number of bytes we've stored so far.
397 cuOffsets[i] = totalEntries
398 totalEntries += uint32(entries)
402 writeCutab := func(ctxt *Link, s loader.Sym) {
403 sb := ctxt.loader.MakeSymbolUpdater(s)
406 for i, max := range cuEntries {
407 // Write the per CU LUT.
409 for j := goobj.CUFileIndex(0); j < max; j++ {
410 fileOffset, ok := fileOffsets[cu.FileTable[j]]
412 // We're looping through all possible file indices. It's possible a file's
413 // been deadcode eliminated, and although it's a valid file in the CU, it's
414 // not needed in this binary. When that happens, use an invalid offset.
415 fileOffset = ^uint32(0)
417 off = sb.SetUint32(ctxt.Arch, off, fileOffset)
421 state.cutab = state.addGeneratedSym(ctxt, "runtime.cutab", int64(totalEntries*4), writeCutab)
424 writeFiletab := func(ctxt *Link, s loader.Sym) {
425 sb := ctxt.loader.MakeSymbolUpdater(s)
427 // Write the strings.
428 for filename, loc := range fileOffsets {
429 sb.AddStringAt(int64(loc), expandFile(filename))
432 state.nfiles = uint32(len(fileOffsets))
433 state.filetab = state.addGeneratedSym(ctxt, "runtime.filetab", fileSize, writeFiletab)
438 // generatePctab creates the runtime.pctab variable, holding all the
439 // deduplicated pcdata.
440 func (state *pclntab) generatePctab(ctxt *Link, funcs []loader.Sym) {
443 // Pctab offsets of 0 are considered invalid in the runtime. We respect
444 // that by just padding a single byte at the beginning of runtime.pctab,
445 // that way no real offsets can be zero.
448 // Walk the functions, finding offset to store each pcdata.
449 seen := make(map[loader.Sym]struct{})
450 saveOffset := func(pcSym loader.Sym) {
451 if _, ok := seen[pcSym]; !ok {
452 datSize := ldr.SymSize(pcSym)
454 ldr.SetSymValue(pcSym, size)
456 // Invalid PC data, record as zero.
457 ldr.SetSymValue(pcSym, 0)
460 seen[pcSym] = struct{}{}
463 for _, s := range funcs {
464 fi := ldr.FuncInfo(s)
470 pcSyms := []loader.Sym{fi.Pcsp(), fi.Pcfile(), fi.Pcline()}
471 for _, pcSym := range pcSyms {
474 for _, pcSym := range fi.Pcdata() {
477 if fi.NumInlTree() > 0 {
478 saveOffset(fi.Pcinline())
482 // TODO: There is no reason we need a generator for this variable, and it
483 // could be moved to a carrier symbol. However, carrier symbols containing
484 // carrier symbols don't work yet (as of Aug 2020). Once this is fixed,
485 // runtime.pctab could just be a carrier sym.
486 writePctab := func(ctxt *Link, s loader.Sym) {
488 sb := ldr.MakeSymbolUpdater(s)
489 for sym := range seen {
490 sb.SetBytesAt(ldr.SymValue(sym), ldr.Data(sym))
494 state.pctab = state.addGeneratedSym(ctxt, "runtime.pctab", size, writePctab)
497 // numPCData returns the number of PCData syms for the FuncInfo.
498 // NB: Preload must be called on valid FuncInfos before calling this function.
499 func numPCData(fi loader.FuncInfo) uint32 {
503 numPCData := uint32(len(fi.Pcdata()))
504 if fi.NumInlTree() > 0 {
505 if numPCData < objabi.PCDATA_InlTreeIndex+1 {
506 numPCData = objabi.PCDATA_InlTreeIndex + 1
512 // Helper types for iterating pclntab.
513 type pclnSetAddr func(*loader.SymbolBuilder, *sys.Arch, int64, loader.Sym, int64) int64
514 type pclnSetUint func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64
516 // generateFunctab creates the runtime.functab
518 // runtime.functab contains two things:
520 // - pc->func look up table.
521 // - array of func objects, interleaved with pcdata and funcdata
523 // Because of timing in the linker, generating this table takes two passes.
524 // The first pass is executed early in the link, and it creates any needed
525 // relocations to layout the data. The pieces that need relocations are:
526 // 1) the PC->func table.
527 // 2) The entry points in the func objects.
529 // (1) and (2) are handled in walkPCToFunc. (3) is handled in walkFuncdata.
531 // After relocations, once we know where to write things in the output buffer,
532 // we execute the second pass, which is actually writing the data.
533 func (state *pclntab) generateFunctab(ctxt *Link, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) {
534 // Calculate the size of the table.
535 size, startLocations := state.calculateFunctabSize(ctxt, funcs)
537 // If we are internally linking a static executable, the function addresses
538 // are known, so we can just use them instead of emitting relocations. For
539 // other cases we still need to emit relocations.
541 // This boolean just helps us figure out which callback to use.
542 useSymValue := ctxt.IsExe() && ctxt.IsInternal()
544 writePcln := func(ctxt *Link, s loader.Sym) {
546 sb := ldr.MakeSymbolUpdater(s)
548 // Create our callbacks.
549 var setAddr pclnSetAddr
551 // We need to write the offset.
552 setAddr = func(s *loader.SymbolBuilder, arch *sys.Arch, off int64, tgt loader.Sym, add int64) int64 {
553 if v := ldr.SymValue(tgt); v != 0 {
554 s.SetUint(arch, off, uint64(v+add))
559 // We already wrote relocations.
560 setAddr = func(s *loader.SymbolBuilder, arch *sys.Arch, off int64, tgt loader.Sym, add int64) int64 { return 0 }
564 writePcToFunc(ctxt, sb, funcs, startLocations, setAddr, (*loader.SymbolBuilder).SetUint)
565 writeFuncs(ctxt, sb, funcs, inlSyms, startLocations, cuOffsets, nameOffsets)
566 state.writeFuncData(ctxt, sb, funcs, inlSyms, startLocations, setAddr, (*loader.SymbolBuilder).SetUint)
569 state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, writePcln)
571 // Create the relocations we need.
573 sb := ldr.MakeSymbolUpdater(state.pclntab)
575 var setAddr pclnSetAddr
577 // If we should use the symbol value, and we don't have one, write a relocation.
578 setAddr = func(sb *loader.SymbolBuilder, arch *sys.Arch, off int64, tgt loader.Sym, add int64) int64 {
579 if v := ldr.SymValue(tgt); v == 0 {
580 sb.SetAddrPlus(arch, off, tgt, add)
585 // If we're externally linking, write a relocation.
586 setAddr = (*loader.SymbolBuilder).SetAddrPlus
588 setUintNOP := func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 { return 0 }
589 writePcToFunc(ctxt, sb, funcs, startLocations, setAddr, setUintNOP)
591 // Generate relocations for funcdata when externally linking.
592 state.writeFuncData(ctxt, sb, funcs, inlSyms, startLocations, setAddr, setUintNOP)
596 // funcData returns the funcdata and offsets for the FuncInfo.
597 // The funcdata and offsets are written into runtime.functab after each func
598 // object. This is a helper function to make querying the FuncInfo object
601 // Note, the majority of fdOffsets are 0, meaning there is no offset between
602 // the compiler's generated symbol, and what the runtime needs. They are
603 // plumbed through for no loss of generality.
605 // NB: Preload must be called on the FuncInfo before calling.
606 // NB: fdSyms and fdOffs are used as scratch space.
607 func funcData(fi loader.FuncInfo, inlSym loader.Sym, fdSyms []loader.Sym, fdOffs []int64) ([]loader.Sym, []int64) {
608 fdSyms, fdOffs = fdSyms[:0], fdOffs[:0]
610 numOffsets := int(fi.NumFuncdataoff())
611 for i := 0; i < numOffsets; i++ {
612 fdOffs = append(fdOffs, fi.Funcdataoff(i))
614 fdSyms = fi.Funcdata(fdSyms)
615 if fi.NumInlTree() > 0 {
616 if len(fdSyms) < objabi.FUNCDATA_InlTree+1 {
617 fdSyms = append(fdSyms, make([]loader.Sym, objabi.FUNCDATA_InlTree+1-len(fdSyms))...)
618 fdOffs = append(fdOffs, make([]int64, objabi.FUNCDATA_InlTree+1-len(fdOffs))...)
620 fdSyms[objabi.FUNCDATA_InlTree] = inlSym
623 return fdSyms, fdOffs
626 // calculateFunctabSize calculates the size of the pclntab, and the offsets in
627 // the output buffer for individual func entries.
628 func (state pclntab) calculateFunctabSize(ctxt *Link, funcs []loader.Sym) (int64, []uint32) {
630 startLocations := make([]uint32, len(funcs))
632 // Allocate space for the pc->func table. This structure consists of a pc
633 // and an offset to the func structure. After that, we have a single pc
634 // value that marks the end of the last function in the binary.
635 size := int64(int(state.nfunc)*2*ctxt.Arch.PtrSize + ctxt.Arch.PtrSize)
637 // Now find the space for the func objects. We do this in a running manner,
638 // so that we can find individual starting locations, and because funcdata
639 // requires alignment.
640 for i, s := range funcs {
641 size = Rnd(size, int64(ctxt.Arch.PtrSize))
642 startLocations[i] = uint32(size)
643 fi := ldr.FuncInfo(s)
644 size += int64(state.funcSize)
647 numFuncData := int(fi.NumFuncdataoff())
648 if fi.NumInlTree() > 0 {
649 if numFuncData < objabi.FUNCDATA_InlTree+1 {
650 numFuncData = objabi.FUNCDATA_InlTree + 1
653 size += int64(numPCData(fi) * 4)
654 if numFuncData > 0 { // Func data is aligned.
655 size = Rnd(size, int64(ctxt.Arch.PtrSize))
657 size += int64(numFuncData * ctxt.Arch.PtrSize)
661 return size, startLocations
664 // writePcToFunc writes the PC->func lookup table.
665 // This function walks the pc->func lookup table, executing callbacks
666 // to generate relocations and writing the values for the table.
667 func writePcToFunc(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, startLocations []uint32, setAddr pclnSetAddr, setUint pclnSetUint) {
669 var prevFunc loader.Sym
670 prevSect := ldr.SymSect(funcs[0])
672 for i, s := range funcs {
673 if thisSect := ldr.SymSect(s); thisSect != prevSect {
674 // With multiple text sections, there may be a hole here in the
675 // address space. We use an invalid funcoff value to mark the hole.
676 // See also runtime/symtab.go:findfunc
677 prevFuncSize := int64(ldr.SymSize(prevFunc))
678 setAddr(sb, ctxt.Arch, int64(funcIndex*2*ctxt.Arch.PtrSize), prevFunc, prevFuncSize)
679 setUint(sb, ctxt.Arch, int64((funcIndex*2+1)*ctxt.Arch.PtrSize), ^uint64(0))
684 // TODO: We don't actually need these relocations, provided we go to a
685 // module->func look-up-table like we do for filenames. We could have a
686 // single relocation for the module, and have them all laid out as
687 // offsets from the beginning of that module.
688 setAddr(sb, ctxt.Arch, int64(funcIndex*2*ctxt.Arch.PtrSize), s, 0)
689 setUint(sb, ctxt.Arch, int64((funcIndex*2+1)*ctxt.Arch.PtrSize), uint64(startLocations[i]))
692 // Write the entry location.
693 setAddr(sb, ctxt.Arch, int64(startLocations[i]), s, 0)
696 // Final entry of table is just end pc.
697 setAddr(sb, ctxt.Arch, int64(funcIndex)*2*int64(ctxt.Arch.PtrSize), prevFunc, ldr.SymSize(prevFunc))
700 // writeFuncData writes the funcdata tables.
702 // This function executes a callback for each funcdata needed in
703 // runtime.functab. It should be called once for internally linked static
704 // binaries, or twice (once to generate the needed relocations) for other
707 // Note the output of this function is interwoven with writeFuncs, but this is
708 // a separate function, because it's needed in different passes in
710 func (state *pclntab) writeFuncData(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations []uint32, setAddr pclnSetAddr, setUint pclnSetUint) {
712 funcdata, funcdataoff := []loader.Sym{}, []int64{}
713 for i, s := range funcs {
714 fi := ldr.FuncInfo(s)
720 // funcdata, must be pointer-aligned and we're only int32-aligned.
721 // Missing funcdata will be 0 (nil pointer).
722 funcdata, funcdataoff := funcData(fi, inlSyms[s], funcdata, funcdataoff)
723 if len(funcdata) > 0 {
724 off := int64(startLocations[i] + state.funcSize + numPCData(fi)*4)
725 off = Rnd(off, int64(ctxt.Arch.PtrSize))
726 for j := range funcdata {
727 dataoff := off + int64(ctxt.Arch.PtrSize*j)
728 if funcdata[j] == 0 {
729 setUint(sb, ctxt.Arch, dataoff, uint64(funcdataoff[j]))
732 // TODO: Does this need deduping?
733 setAddr(sb, ctxt.Arch, dataoff, funcdata[j], funcdataoff[j])
739 // writeFuncs writes the func structures and pcdata to runtime.functab.
740 func writeFuncs(ctxt *Link, sb *loader.SymbolBuilder, funcs []loader.Sym, inlSyms map[loader.Sym]loader.Sym, startLocations, cuOffsets []uint32, nameOffsets map[loader.Sym]uint32) {
742 deferReturnSym := ldr.Lookup("runtime.deferreturn", sym.SymVerABIInternal)
743 funcdata, funcdataoff := []loader.Sym{}, []int64{}
745 // Write the individual func objects.
746 for i, s := range funcs {
747 fi := ldr.FuncInfo(s)
752 // Note we skip the space for the entry value -- that's handled inn
753 // walkPCToFunc. We don't write it here, because it might require a
755 off := startLocations[i] + uint32(ctxt.Arch.PtrSize) // entry
758 nameoff, ok := nameOffsets[s]
760 panic("couldn't find function name offset")
762 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(nameoff)))
765 // TODO: Move into funcinfo.
768 args = uint32(fi.Args())
770 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), args))
773 deferreturn := computeDeferReturn(ctxt, deferReturnSym, s)
774 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), deferreturn))
778 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcsp()))))
779 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcfile()))))
780 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(ldr.SymValue(fi.Pcline()))))
784 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(numPCData(fi))))
786 // Store the offset to compilation unit's file table.
788 if cu := ldr.SymUnit(s); cu != nil {
789 cuIdx = cuOffsets[cu.PclnIndex]
791 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), cuIdx))
794 var funcID objabi.FuncID
798 off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(funcID)))
801 var flag objabi.FuncFlag
805 off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(flag)))
809 // nfuncdata must be the final entry.
810 funcdata, funcdataoff = funcData(fi, 0, funcdata, funcdataoff)
811 off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(len(funcdata))))
813 // Output the pcdata.
815 for j, pcSym := range fi.Pcdata() {
816 sb.SetUint32(ctxt.Arch, int64(off+uint32(j*4)), uint32(ldr.SymValue(pcSym)))
818 if fi.NumInlTree() > 0 {
819 sb.SetUint32(ctxt.Arch, int64(off+objabi.PCDATA_InlTreeIndex*4), uint32(ldr.SymValue(fi.Pcinline())))
825 // pclntab initializes the pclntab symbol with
826 // runtime function and file name information.
828 // pclntab generates the pcln table for the link output.
829 func (ctxt *Link) pclntab(container loader.Bitmap) *pclntab {
830 // Go 1.2's symtab layout is documented in golang.org/s/go12symtab, but the
831 // layout and data has changed since that time.
833 // As of August 2020, here's the layout of pclntab:
835 // .gopclntab/__gopclntab [elf/macho section]
837 // Carrier symbol for the entire pclntab section.
839 // runtime.pcheader (see: runtime/symtab.go:pcHeader)
841 // nfunc [thearch.ptrsize bytes]
842 // offset to runtime.funcnametab from the beginning of runtime.pcheader
843 // offset to runtime.pclntab_old from beginning of runtime.pcheader
845 // runtime.funcnametab
846 // []list of null terminated function names
850 // for j=0..#max used file index in CU[i]
851 // uint32 offset into runtime.filetab for the filename[j]
854 // []null terminated filename strings
857 // []byte of deduplicated pc data.
860 // function table, alternating PC and offset to func struct [each entry thearch.ptrsize bytes]
861 // end PC [thearch.ptrsize bytes]
862 // func structures, pcdata offsets, func data.
864 state, compUnits, funcs := makePclntab(ctxt, container)
867 state.carrier = ldr.LookupOrCreateSym("runtime.pclntab", 0)
868 ldr.MakeSymbolUpdater(state.carrier).SetType(sym.SPCLNTAB)
869 ldr.SetAttrReachable(state.carrier, true)
870 setCarrierSym(sym.SPCLNTAB, state.carrier)
872 state.generatePCHeader(ctxt)
873 nameOffsets := state.generateFuncnametab(ctxt, funcs)
874 cuOffsets := state.generateFilenameTabs(ctxt, compUnits, funcs)
875 state.generatePctab(ctxt, funcs)
876 inlSyms := makeInlSyms(ctxt, funcs, nameOffsets)
877 state.generateFunctab(ctxt, funcs, inlSyms, cuOffsets, nameOffsets)
882 func gorootFinal() string {
883 root := buildcfg.GOROOT
884 if final := os.Getenv("GOROOT_FINAL"); final != "" {
890 func expandGoroot(s string) string {
891 const n = len("$GOROOT")
892 if len(s) >= n+1 && s[:n] == "$GOROOT" && (s[n] == '/' || s[n] == '\\') {
893 return filepath.ToSlash(filepath.Join(gorootFinal(), s[n:]))
899 BUCKETSIZE = 256 * MINFUNC
901 SUBBUCKETSIZE = BUCKETSIZE / SUBBUCKETS
905 // findfunctab generates a lookup table to quickly find the containing
906 // function for a pc. See src/runtime/symtab.go:findfunc for details.
907 func (ctxt *Link) findfunctab(state *pclntab, container loader.Bitmap) {
910 // find min and max address
911 min := ldr.SymValue(ctxt.Textp[0])
912 lastp := ctxt.Textp[len(ctxt.Textp)-1]
913 max := ldr.SymValue(lastp) + ldr.SymSize(lastp)
915 // for each subbucket, compute the minimum of all symbol indexes
916 // that map to that subbucket.
917 n := int32((max - min + SUBBUCKETSIZE - 1) / SUBBUCKETSIZE)
919 nbuckets := int32((max - min + BUCKETSIZE - 1) / BUCKETSIZE)
921 size := 4*int64(nbuckets) + int64(n)
923 writeFindFuncTab := func(_ *Link, s loader.Sym) {
924 t := ldr.MakeSymbolUpdater(s)
926 indexes := make([]int32, n)
927 for i := int32(0); i < n; i++ {
931 for i, s := range ctxt.Textp {
932 if !emitPcln(ctxt, s, container) {
938 if i < len(ctxt.Textp) {
941 for e != 0 && !emitPcln(ctxt, e, container) && i < len(ctxt.Textp) {
950 //print("%d: [%lld %lld] %s\n", idx, p, q, s->name);
951 for ; p < q; p += SUBBUCKETSIZE {
952 i = int((p - min) / SUBBUCKETSIZE)
953 if indexes[i] > idx {
958 i = int((q - 1 - min) / SUBBUCKETSIZE)
959 if indexes[i] > idx {
966 for i := int32(0); i < nbuckets; i++ {
967 base := indexes[i*SUBBUCKETS]
969 Errorf(nil, "hole in findfunctab")
971 t.SetUint32(ctxt.Arch, int64(i)*(4+SUBBUCKETS), uint32(base))
972 for j := int32(0); j < SUBBUCKETS && i*SUBBUCKETS+j < n; j++ {
973 idx = indexes[i*SUBBUCKETS+j]
975 Errorf(nil, "hole in findfunctab")
978 Errorf(nil, "too many functions in a findfunc bucket! %d/%d %d %d", i, nbuckets, j, idx-base)
981 t.SetUint8(ctxt.Arch, int64(i)*(4+SUBBUCKETS)+4+int64(j), uint8(idx-base))
986 state.findfunctab = ctxt.createGeneratorSymbol("runtime.findfunctab", 0, sym.SRODATA, size, writeFindFuncTab)
987 ldr.SetAttrReachable(state.findfunctab, true)
988 ldr.SetAttrLocal(state.findfunctab, true)
991 // findContainerSyms returns a bitmap, indexed by symbol number, where there's
992 // a 1 for every container symbol.
993 func (ctxt *Link) findContainerSyms() loader.Bitmap {
995 container := loader.MakeBitmap(ldr.NSym())
996 // Find container symbols and mark them as such.
997 for _, s := range ctxt.Textp {
998 outer := ldr.OuterSym(s)
1000 container.Set(outer)