]> Cypherpunks.ru repositories - gostls13.git/blob - src/cmd/link/internal/ld/pcln.go
internal/buildcfg: move build configuration out of cmd/internal/objabi
[gostls13.git] / src / cmd / link / internal / ld / pcln.go
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.
4
5 package ld
6
7 import (
8         "cmd/internal/goobj"
9         "cmd/internal/objabi"
10         "cmd/internal/sys"
11         "cmd/link/internal/loader"
12         "cmd/link/internal/sym"
13         "fmt"
14         "internal/buildcfg"
15         "os"
16         "path/filepath"
17 )
18
19 // pclntab holds the state needed for pclntab generation.
20 type pclntab struct {
21         // The size of the func object in the runtime.
22         funcSize uint32
23
24         // The first and last functions found.
25         firstFunc, lastFunc loader.Sym
26
27         // Running total size of pclntab.
28         size int64
29
30         // runtime.pclntab's symbols
31         carrier     loader.Sym
32         pclntab     loader.Sym
33         pcheader    loader.Sym
34         funcnametab loader.Sym
35         findfunctab loader.Sym
36         cutab       loader.Sym
37         filetab     loader.Sym
38         pctab       loader.Sym
39
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
44         // runtime.
45         //
46         // On most platforms this is the number of reachable functions.
47         nfunc int32
48
49         // The number of filenames in runtime.filetab.
50         nfiles uint32
51 }
52
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))
57         state.size += size
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)
62         return s
63 }
64
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
68 // generate pclntab.
69 func makePclntab(ctxt *Link, container loader.Bitmap) (*pclntab, []*sym.CompilationUnit, []loader.Sym) {
70         ldr := ctxt.loader
71
72         state := &pclntab{
73                 // This is the size of the _func object in runtime/runtime2.go.
74                 funcSize: uint32(ctxt.Arch.PtrSize + 9*4),
75         }
76
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{}
82
83         for _, s := range ctxt.Textp {
84                 if !emitPcln(ctxt, s, container) {
85                         continue
86                 }
87                 funcs = append(funcs, s)
88                 state.nfunc++
89                 if state.firstFunc == 0 {
90                         state.firstFunc = s
91                 }
92                 state.lastFunc = s
93                 ss := ldr.SymSect(s)
94                 if ss != prevSect {
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
99                         // the hole.
100                         state.nfunc++
101                         prevSect = ss
102                 }
103
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.
106                 cu := ldr.SymUnit(s)
107                 if _, ok := seenCUs[cu]; cu != nil && !ok {
108                         seenCUs[cu] = struct{}{}
109                         cu.PclnIndex = len(compUnits)
110                         compUnits = append(compUnits, cu)
111                 }
112         }
113         return state, compUnits, funcs
114 }
115
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)
120 }
121
122 func computeDeferReturn(ctxt *Link, deferReturnSym, s loader.Sym) uint32 {
123         ldr := ctxt.loader
124         target := ctxt.Target
125         deferreturn := uint32(0)
126         lastWasmAddr := uint32(0)
127
128         relocs := ldr.Relocs(s)
129         for ri := 0; ri < relocs.Count(); ri++ {
130                 r := relocs.At(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())
138                 }
139                 if r.Type().IsDirectCall() && (r.Sym() == deferReturnSym || ldr.IsDeferReturnTramp(r.Sym())) {
140                         if target.IsWasm() {
141                                 deferreturn = lastWasmAddr - 1
142                         } else {
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
146                                 // instruction).
147                                 deferreturn = uint32(r.Off())
148                                 switch target.Arch.Family {
149                                 case sys.AMD64, sys.I386:
150                                         deferreturn--
151                                 case sys.PPC64, sys.ARM, sys.ARM64, sys.MIPS, sys.MIPS64:
152                                         // no change
153                                 case sys.RISCV64:
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.
157                                         deferreturn -= 4
158                                 case sys.S390X:
159                                         deferreturn -= 2
160                                 default:
161                                         panic(fmt.Sprint("Unhandled architecture:", target.Arch.Family))
162                                 }
163                         }
164                         break // only need one
165                 }
166         }
167         return deferreturn
168 }
169
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 {
173         ldr := ctxt.loader
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)
185                 val := call.File
186                 nameoff, ok := nameOffsets[call.Func]
187                 if !ok {
188                         panic("couldn't find function name offset")
189                 }
190
191                 inlTreeSym.SetUint16(arch, int64(i*20+0), uint16(call.Parent))
192                 inlFunc := ldr.FuncInfo(call.Func)
193
194                 var funcID objabi.FuncID
195                 if inlFunc.Valid() {
196                         funcID = inlFunc.FuncID()
197                 }
198                 inlTreeSym.SetUint8(arch, int64(i*20+2), uint8(funcID))
199
200                 // byte 3 is unused
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))
205         }
206         return its
207 }
208
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 {
211         ldr := ctxt.loader
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() {
216                         fi.Preload()
217                         if fi.NumInlTree() > 0 {
218                                 inlSyms[s] = genInlTreeSym(ctxt, ldr.SymUnit(s), fi, ctxt.Arch, nameOffsets)
219                         }
220                 }
221         }
222         return inlSyms
223 }
224
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) {
229                 ldr := ctxt.loader
230                 header := ctxt.loader.MakeSymbolUpdater(s)
231
232                 writeSymOffset := func(off int64, ws loader.Sym) int64 {
233                         diff := ldr.SymValue(ws) - ldr.SymValue(s)
234                         if diff <= 0 {
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)))
237                         }
238                         return header.SetUintptr(ctxt.Arch, off, uintptr(diff))
239                 }
240
241                 // Write header.
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)
253         }
254
255         size := int64(8 + 7*ctxt.Arch.PtrSize)
256         state.pcheader = state.addGeneratedSym(ctxt, "runtime.pcheader", size, writeHeader)
257 }
258
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)) {
262         ldr := ctxt.loader
263         seen := make(map[loader.Sym]struct{})
264         for _, s := range funcs {
265                 if _, ok := seen[s]; !ok {
266                         f(s)
267                         seen[s] = struct{}{}
268                 }
269
270                 fi := ldr.FuncInfo(s)
271                 if !fi.Valid() {
272                         continue
273                 }
274                 fi.Preload()
275                 for i, ni := 0, fi.NumInlTree(); i < int(ni); i++ {
276                         call := fi.InlTree(i).Func
277                         if _, ok := seen[call]; !ok {
278                                 f(call)
279                                 seen[call] = struct{}{}
280                         }
281                 }
282         }
283 }
284
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)
289
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))
295                 }
296         }
297
298         // Loop through the CUs, and calculate the size needed.
299         var size int64
300         walkFuncs(ctxt, funcs, func(s loader.Sym) {
301                 nameOffsets[s] = uint32(size)
302                 size += int64(ctxt.loader.SymNameLen(s)) + 1 // NULL terminate
303         })
304
305         state.funcnametab = state.addGeneratedSym(ctxt, "runtime.funcnametab", size, writeFuncNameTab)
306         return nameOffsets
307 }
308
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)) {
312         ldr := ctxt.loader
313
314         // Loop through all functions, finding the filenames we need.
315         for _, s := range funcs {
316                 fi := ldr.FuncInfo(s)
317                 if !fi.Valid() {
318                         continue
319                 }
320                 fi.Preload()
321
322                 cu := ldr.SymUnit(s)
323                 for i, nf := 0, int(fi.NumFile()); i < nf; i++ {
324                         f(cu, fi.File(i))
325                 }
326                 for i, ninl := 0, int(fi.NumInlTree()); i < ninl; i++ {
327                         call := fi.InlTree(i)
328                         f(cu, call.File)
329                 }
330         }
331 }
332
333 // generateFilenameTabs creates LUTs needed for filename lookup. Returns a slice
334 // of the index at which each CU begins in runtime.cutab.
335 //
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:
339 //
340 //  runtime.cutab:
341 //    CU[M]
342 //     offsetToFilename[0]
343 //     offsetToFilename[1]
344 //     ..
345 //
346 //  runtime.filetab
347 //     filename[0]
348 //     filename[1]
349 //
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.
357         //
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.
363         //
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)
369
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.
374         var fileSize int64
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
382                 }
383
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
387                 }
388         })
389
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)
399         }
400
401         // Write cutab.
402         writeCutab := func(ctxt *Link, s loader.Sym) {
403                 sb := ctxt.loader.MakeSymbolUpdater(s)
404
405                 var off int64
406                 for i, max := range cuEntries {
407                         // Write the per CU LUT.
408                         cu := compUnits[i]
409                         for j := goobj.CUFileIndex(0); j < max; j++ {
410                                 fileOffset, ok := fileOffsets[cu.FileTable[j]]
411                                 if !ok {
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)
416                                 }
417                                 off = sb.SetUint32(ctxt.Arch, off, fileOffset)
418                         }
419                 }
420         }
421         state.cutab = state.addGeneratedSym(ctxt, "runtime.cutab", int64(totalEntries*4), writeCutab)
422
423         // Write filetab.
424         writeFiletab := func(ctxt *Link, s loader.Sym) {
425                 sb := ctxt.loader.MakeSymbolUpdater(s)
426
427                 // Write the strings.
428                 for filename, loc := range fileOffsets {
429                         sb.AddStringAt(int64(loc), expandFile(filename))
430                 }
431         }
432         state.nfiles = uint32(len(fileOffsets))
433         state.filetab = state.addGeneratedSym(ctxt, "runtime.filetab", fileSize, writeFiletab)
434
435         return cuOffsets
436 }
437
438 // generatePctab creates the runtime.pctab variable, holding all the
439 // deduplicated pcdata.
440 func (state *pclntab) generatePctab(ctxt *Link, funcs []loader.Sym) {
441         ldr := ctxt.loader
442
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.
446         size := int64(1)
447
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)
453                         if datSize != 0 {
454                                 ldr.SetSymValue(pcSym, size)
455                         } else {
456                                 // Invalid PC data, record as zero.
457                                 ldr.SetSymValue(pcSym, 0)
458                         }
459                         size += datSize
460                         seen[pcSym] = struct{}{}
461                 }
462         }
463         for _, s := range funcs {
464                 fi := ldr.FuncInfo(s)
465                 if !fi.Valid() {
466                         continue
467                 }
468                 fi.Preload()
469
470                 pcSyms := []loader.Sym{fi.Pcsp(), fi.Pcfile(), fi.Pcline()}
471                 for _, pcSym := range pcSyms {
472                         saveOffset(pcSym)
473                 }
474                 for _, pcSym := range fi.Pcdata() {
475                         saveOffset(pcSym)
476                 }
477                 if fi.NumInlTree() > 0 {
478                         saveOffset(fi.Pcinline())
479                 }
480         }
481
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) {
487                 ldr := ctxt.loader
488                 sb := ldr.MakeSymbolUpdater(s)
489                 for sym := range seen {
490                         sb.SetBytesAt(ldr.SymValue(sym), ldr.Data(sym))
491                 }
492         }
493
494         state.pctab = state.addGeneratedSym(ctxt, "runtime.pctab", size, writePctab)
495 }
496
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 {
500         if !fi.Valid() {
501                 return 0
502         }
503         numPCData := uint32(len(fi.Pcdata()))
504         if fi.NumInlTree() > 0 {
505                 if numPCData < objabi.PCDATA_InlTreeIndex+1 {
506                         numPCData = objabi.PCDATA_InlTreeIndex + 1
507                 }
508         }
509         return numPCData
510 }
511
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
515
516 // generateFunctab creates the runtime.functab
517 //
518 // runtime.functab contains two things:
519 //
520 //   - pc->func look up table.
521 //   - array of func objects, interleaved with pcdata and funcdata
522 //
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.
528 //   3) The funcdata.
529 // (1) and (2) are handled in walkPCToFunc. (3) is handled in walkFuncdata.
530 //
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)
536
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.
540         //
541         // This boolean just helps us figure out which callback to use.
542         useSymValue := ctxt.IsExe() && ctxt.IsInternal()
543
544         writePcln := func(ctxt *Link, s loader.Sym) {
545                 ldr := ctxt.loader
546                 sb := ldr.MakeSymbolUpdater(s)
547
548                 // Create our callbacks.
549                 var setAddr pclnSetAddr
550                 if useSymValue {
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))
555                                 }
556                                 return 0
557                         }
558                 } else {
559                         // We already wrote relocations.
560                         setAddr = func(s *loader.SymbolBuilder, arch *sys.Arch, off int64, tgt loader.Sym, add int64) int64 { return 0 }
561                 }
562
563                 // Write the data.
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)
567         }
568
569         state.pclntab = state.addGeneratedSym(ctxt, "runtime.functab", size, writePcln)
570
571         // Create the relocations we need.
572         ldr := ctxt.loader
573         sb := ldr.MakeSymbolUpdater(state.pclntab)
574
575         var setAddr pclnSetAddr
576         if useSymValue {
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)
581                         }
582                         return 0
583                 }
584         } else {
585                 // If we're externally linking, write a relocation.
586                 setAddr = (*loader.SymbolBuilder).SetAddrPlus
587         }
588         setUintNOP := func(*loader.SymbolBuilder, *sys.Arch, int64, uint64) int64 { return 0 }
589         writePcToFunc(ctxt, sb, funcs, startLocations, setAddr, setUintNOP)
590         if !useSymValue {
591                 // Generate relocations for funcdata when externally linking.
592                 state.writeFuncData(ctxt, sb, funcs, inlSyms, startLocations, setAddr, setUintNOP)
593         }
594 }
595
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
599 // cleaner.
600 //
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.
604 //
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]
609         if fi.Valid() {
610                 numOffsets := int(fi.NumFuncdataoff())
611                 for i := 0; i < numOffsets; i++ {
612                         fdOffs = append(fdOffs, fi.Funcdataoff(i))
613                 }
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))...)
619                         }
620                         fdSyms[objabi.FUNCDATA_InlTree] = inlSym
621                 }
622         }
623         return fdSyms, fdOffs
624 }
625
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) {
629         ldr := ctxt.loader
630         startLocations := make([]uint32, len(funcs))
631
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)
636
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)
645                 if fi.Valid() {
646                         fi.Preload()
647                         numFuncData := int(fi.NumFuncdataoff())
648                         if fi.NumInlTree() > 0 {
649                                 if numFuncData < objabi.FUNCDATA_InlTree+1 {
650                                         numFuncData = objabi.FUNCDATA_InlTree + 1
651                                 }
652                         }
653                         size += int64(numPCData(fi) * 4)
654                         if numFuncData > 0 { // Func data is aligned.
655                                 size = Rnd(size, int64(ctxt.Arch.PtrSize))
656                         }
657                         size += int64(numFuncData * ctxt.Arch.PtrSize)
658                 }
659         }
660
661         return size, startLocations
662 }
663
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) {
668         ldr := ctxt.loader
669         var prevFunc loader.Sym
670         prevSect := ldr.SymSect(funcs[0])
671         funcIndex := 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))
680                         funcIndex++
681                         prevSect = thisSect
682                 }
683                 prevFunc = s
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]))
690                 funcIndex++
691
692                 // Write the entry location.
693                 setAddr(sb, ctxt.Arch, int64(startLocations[i]), s, 0)
694         }
695
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))
698 }
699
700 // writeFuncData writes the funcdata tables.
701 //
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
705 // build modes.
706 //
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
709 // generateFunctab.
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) {
711         ldr := ctxt.loader
712         funcdata, funcdataoff := []loader.Sym{}, []int64{}
713         for i, s := range funcs {
714                 fi := ldr.FuncInfo(s)
715                 if !fi.Valid() {
716                         continue
717                 }
718                 fi.Preload()
719
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]))
730                                         continue
731                                 }
732                                 // TODO: Does this need deduping?
733                                 setAddr(sb, ctxt.Arch, dataoff, funcdata[j], funcdataoff[j])
734                         }
735                 }
736         }
737 }
738
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) {
741         ldr := ctxt.loader
742         deferReturnSym := ldr.Lookup("runtime.deferreturn", sym.SymVerABIInternal)
743         funcdata, funcdataoff := []loader.Sym{}, []int64{}
744
745         // Write the individual func objects.
746         for i, s := range funcs {
747                 fi := ldr.FuncInfo(s)
748                 if fi.Valid() {
749                         fi.Preload()
750                 }
751
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
754                 // relocation.
755                 off := startLocations[i] + uint32(ctxt.Arch.PtrSize) // entry
756
757                 // name int32
758                 nameoff, ok := nameOffsets[s]
759                 if !ok {
760                         panic("couldn't find function name offset")
761                 }
762                 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(nameoff)))
763
764                 // args int32
765                 // TODO: Move into funcinfo.
766                 args := uint32(0)
767                 if fi.Valid() {
768                         args = uint32(fi.Args())
769                 }
770                 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), args))
771
772                 // deferreturn
773                 deferreturn := computeDeferReturn(ctxt, deferReturnSym, s)
774                 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), deferreturn))
775
776                 // pcdata
777                 if fi.Valid() {
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()))))
781                 } else {
782                         off += 12
783                 }
784                 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), uint32(numPCData(fi))))
785
786                 // Store the offset to compilation unit's file table.
787                 cuIdx := ^uint32(0)
788                 if cu := ldr.SymUnit(s); cu != nil {
789                         cuIdx = cuOffsets[cu.PclnIndex]
790                 }
791                 off = uint32(sb.SetUint32(ctxt.Arch, int64(off), cuIdx))
792
793                 // funcID uint8
794                 var funcID objabi.FuncID
795                 if fi.Valid() {
796                         funcID = fi.FuncID()
797                 }
798                 off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(funcID)))
799
800                 // flag uint8
801                 var flag objabi.FuncFlag
802                 if fi.Valid() {
803                         flag = fi.FuncFlag()
804                 }
805                 off = uint32(sb.SetUint8(ctxt.Arch, int64(off), uint8(flag)))
806
807                 off += 1 // pad
808
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))))
812
813                 // Output the pcdata.
814                 if fi.Valid() {
815                         for j, pcSym := range fi.Pcdata() {
816                                 sb.SetUint32(ctxt.Arch, int64(off+uint32(j*4)), uint32(ldr.SymValue(pcSym)))
817                         }
818                         if fi.NumInlTree() > 0 {
819                                 sb.SetUint32(ctxt.Arch, int64(off+objabi.PCDATA_InlTreeIndex*4), uint32(ldr.SymValue(fi.Pcinline())))
820                         }
821                 }
822         }
823 }
824
825 // pclntab initializes the pclntab symbol with
826 // runtime function and file name information.
827
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.
832         //
833         // As of August 2020, here's the layout of pclntab:
834         //
835         //  .gopclntab/__gopclntab [elf/macho section]
836         //    runtime.pclntab
837         //      Carrier symbol for the entire pclntab section.
838         //
839         //      runtime.pcheader  (see: runtime/symtab.go:pcHeader)
840         //        8-byte magic
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
844         //
845         //      runtime.funcnametab
846         //        []list of null terminated function names
847         //
848         //      runtime.cutab
849         //        for i=0..#CUs
850         //          for j=0..#max used file index in CU[i]
851         //            uint32 offset into runtime.filetab for the filename[j]
852         //
853         //      runtime.filetab
854         //        []null terminated filename strings
855         //
856         //      runtime.pctab
857         //        []byte of deduplicated pc data.
858         //
859         //      runtime.functab
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.
863
864         state, compUnits, funcs := makePclntab(ctxt, container)
865
866         ldr := ctxt.loader
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)
871
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)
878
879         return state
880 }
881
882 func gorootFinal() string {
883         root := buildcfg.GOROOT
884         if final := os.Getenv("GOROOT_FINAL"); final != "" {
885                 root = final
886         }
887         return root
888 }
889
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:]))
894         }
895         return s
896 }
897
898 const (
899         BUCKETSIZE    = 256 * MINFUNC
900         SUBBUCKETS    = 16
901         SUBBUCKETSIZE = BUCKETSIZE / SUBBUCKETS
902         NOIDX         = 0x7fffffff
903 )
904
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) {
908         ldr := ctxt.loader
909
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)
914
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)
918
919         nbuckets := int32((max - min + BUCKETSIZE - 1) / BUCKETSIZE)
920
921         size := 4*int64(nbuckets) + int64(n)
922
923         writeFindFuncTab := func(_ *Link, s loader.Sym) {
924                 t := ldr.MakeSymbolUpdater(s)
925
926                 indexes := make([]int32, n)
927                 for i := int32(0); i < n; i++ {
928                         indexes[i] = NOIDX
929                 }
930                 idx := int32(0)
931                 for i, s := range ctxt.Textp {
932                         if !emitPcln(ctxt, s, container) {
933                                 continue
934                         }
935                         p := ldr.SymValue(s)
936                         var e loader.Sym
937                         i++
938                         if i < len(ctxt.Textp) {
939                                 e = ctxt.Textp[i]
940                         }
941                         for e != 0 && !emitPcln(ctxt, e, container) && i < len(ctxt.Textp) {
942                                 e = ctxt.Textp[i]
943                                 i++
944                         }
945                         q := max
946                         if e != 0 {
947                                 q = ldr.SymValue(e)
948                         }
949
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 {
954                                         indexes[i] = idx
955                                 }
956                         }
957
958                         i = int((q - 1 - min) / SUBBUCKETSIZE)
959                         if indexes[i] > idx {
960                                 indexes[i] = idx
961                         }
962                         idx++
963                 }
964
965                 // fill in table
966                 for i := int32(0); i < nbuckets; i++ {
967                         base := indexes[i*SUBBUCKETS]
968                         if base == NOIDX {
969                                 Errorf(nil, "hole in findfunctab")
970                         }
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]
974                                 if idx == NOIDX {
975                                         Errorf(nil, "hole in findfunctab")
976                                 }
977                                 if idx-base >= 256 {
978                                         Errorf(nil, "too many functions in a findfunc bucket! %d/%d %d %d", i, nbuckets, j, idx-base)
979                                 }
980
981                                 t.SetUint8(ctxt.Arch, int64(i)*(4+SUBBUCKETS)+4+int64(j), uint8(idx-base))
982                         }
983                 }
984         }
985
986         state.findfunctab = ctxt.createGeneratorSymbol("runtime.findfunctab", 0, sym.SRODATA, size, writeFindFuncTab)
987         ldr.SetAttrReachable(state.findfunctab, true)
988         ldr.SetAttrLocal(state.findfunctab, true)
989 }
990
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 {
994         ldr := ctxt.loader
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)
999                 if outer != 0 {
1000                         container.Set(outer)
1001                 }
1002         }
1003         return container
1004 }