// isRuntimeDepPkg reports whether pkg is the runtime package or its dependency. func isRuntimeDepPkg(pkg string) bool { … } // Estimate the max size needed to hold any new trampolines created for this function. This // is used to determine when the section can be split if it becomes too large, to ensure that // the trampolines are in the same section as the function that uses them. func maxSizeTrampolines(ctxt *Link, ldr *loader.Loader, s loader.Sym, isTramp bool) uint64 { … } // Detect too-far jumps in function s, and add trampolines if necessary. // ARM, LOONG64, PPC64, PPC64LE and RISCV64 support trampoline insertion for internal // and external linking. On PPC64 and PPC64LE the text sections might be split // but will still insert trampolines where necessary. func trampoline(ctxt *Link, s loader.Sym) { … } // whether rt is a (host object) relocation that will be turned into // a call to PLT. func isPLTCall(arch *sys.Arch, rt objabi.RelocType) bool { … } // FoldSubSymbolOffset computes the offset of symbol s to its top-level outer // symbol. Returns the top-level symbol and the offset. // This is used in generating external relocations. func FoldSubSymbolOffset(ldr *loader.Loader, s loader.Sym) (loader.Sym, int64) { … } // relocsym resolve relocations in "s", updating the symbol's content // in "P". // The main loop walks through the list of relocations attached to "s" // and resolves them where applicable. Relocations are often // architecture-specific, requiring calls into the 'archreloc' and/or // 'archrelocvariant' functions for the architecture. When external // linking is in effect, it may not be possible to completely resolve // the address/offset for a symbol, in which case the goal is to lay // the groundwork for turning a given relocation into an external reloc // (to be applied by the external linker). For more on how relocations // work in general, see // // "Linkers and Loaders", by John R. Levine (Morgan Kaufmann, 1999), ch. 7 // // This is a performance-critical function for the linker; be careful // to avoid introducing unnecessary allocations in the main loop. func (st *relocSymState) relocsym(s loader.Sym, P []byte) { … } // Convert a Go relocation to an external relocation. func extreloc(ctxt *Link, ldr *loader.Loader, s loader.Sym, r loader.Reloc) (loader.ExtReloc, bool) { … } // ExtrelocSimple creates a simple external relocation from r, with the same // symbol and addend. func ExtrelocSimple(ldr *loader.Loader, r loader.Reloc) loader.ExtReloc { … } // ExtrelocViaOuterSym creates an external relocation from r targeting the // outer symbol and folding the subsymbol's offset into the addend. func ExtrelocViaOuterSym(ldr *loader.Loader, r loader.Reloc, s loader.Sym) loader.ExtReloc { … } type relocSymState … // makeRelocSymState creates a relocSymState container object to // pass to relocsym(). If relocsym() calls happen in parallel, // each parallel thread should have its own state object. func (ctxt *Link) makeRelocSymState() *relocSymState { … } // windynrelocsym examines a text symbol 's' and looks for relocations // from it that correspond to references to symbols defined in DLLs, // then fixes up those relocations as needed. A reference to a symbol // XYZ from some DLL will fall into one of two categories: an indirect // ref via "__imp_XYZ", or a direct ref to "XYZ". Here's an example of // an indirect ref (this is an excerpt from objdump -ldr): // // 1c1: 48 89 c6 movq %rax, %rsi // 1c4: ff 15 00 00 00 00 callq *(%rip) // 00000000000001c6: IMAGE_REL_AMD64_REL32 __imp__errno // // In the assembly above, the code loads up the value of __imp_errno // and then does an indirect call to that value. // // Here is what a direct reference might look like: // // 137: e9 20 06 00 00 jmp 0x75c <pow+0x75c> // 13c: e8 00 00 00 00 callq 0x141 <pow+0x141> // 000000000000013d: IMAGE_REL_AMD64_REL32 _errno // // The assembly below dispenses with the import symbol and just makes // a direct call to _errno. // // The code below handles indirect refs by redirecting the target of // the relocation from "__imp_XYZ" to "XYZ" (since the latter symbol // is what the Windows loader is expected to resolve). For direct refs // the call is redirected to a stub, where the stub first loads the // symbol and then direct an indirect call to that value. // // Note that for a given symbol (as above) it is perfectly legal to // have both direct and indirect references. func windynrelocsym(ctxt *Link, rel *loader.SymbolBuilder, s loader.Sym) error { … } // windynrelocsyms generates jump table to C library functions that will be // added later. windynrelocsyms writes the table into .rel symbol. func (ctxt *Link) windynrelocsyms() { … } func dynrelocsym(ctxt *Link, s loader.Sym) { … } func (state *dodataState) dynreloc(ctxt *Link) { … } func CodeblkPad(ctxt *Link, out *OutBuf, addr int64, size int64, pad []byte) { … } const blockSize … // writeBlocks writes a specified chunk of symbols to the output buffer. It // breaks the write up into ≥blockSize chunks to write them out, and schedules // as many goroutines as necessary to accomplish this task. This call then // blocks, waiting on the writes to complete. Note that we use the sem parameter // to limit the number of concurrent writes taking place. func writeBlocks(ctxt *Link, out *OutBuf, sem chan int, ldr *loader.Loader, syms []loader.Sym, addr, size int64, pad []byte) { … } func writeBlock(ctxt *Link, out *OutBuf, ldr *loader.Loader, syms []loader.Sym, addr, size int64, pad []byte) { … } type writeFn … // writeParallel handles scheduling parallel execution of data write functions. func writeParallel(wg *sync.WaitGroup, fn writeFn, ctxt *Link, seek, vaddr, length uint64) { … } func datblk(ctxt *Link, out *OutBuf, addr, size int64) { … } // Used only on Wasm for now. func DatblkBytes(ctxt *Link, addr int64, size int64) []byte { … } func writeDatblkToOutBuf(ctxt *Link, out *OutBuf, addr int64, size int64) { … } func dwarfblk(ctxt *Link, out *OutBuf, addr int64, size int64) { … } func pdatablk(ctxt *Link, out *OutBuf, addr int64, size int64) { … } func xdatablk(ctxt *Link, out *OutBuf, addr int64, size int64) { … } var ( covCounterDataStartOff … covCounterDataLen … ) var zeros … var strdata … var strnames … func addstrdata1(ctxt *Link, arg string) { … } // addstrdata sets the initial value of the string variable name to value. func addstrdata(arch *sys.Arch, l *loader.Loader, name, value string) { … } func (ctxt *Link) dostrdata() { … } // addgostring adds str, as a Go string value, to s. symname is the name of the // symbol used to define the string data and must be unique per linked object. func addgostring(ctxt *Link, ldr *loader.Loader, s *loader.SymbolBuilder, symname, str string) { … } func addinitarrdata(ctxt *Link, ldr *loader.Loader, s loader.Sym) { … } // symalign returns the required alignment for the given symbol s. func symalign(ldr *loader.Loader, s loader.Sym) int32 { … } func aligndatsize(state *dodataState, datsize int64, s loader.Sym) int64 { … } const debugGCProg … type GCProg … func (p *GCProg) Init(ctxt *Link, name string) { … } func (p *GCProg) writeByte() func(x byte) { … } func (p *GCProg) End(size int64) { … } func (p *GCProg) AddSym(s loader.Sym) { … } const cutoff … // check accumulated size of data sections func (state *dodataState) checkdatsize(symn sym.SymKind) { … } func checkSectSize(sect *sym.Section) { … } // fixZeroSizedSymbols gives a few special symbols with zero size some space. func fixZeroSizedSymbols(ctxt *Link) { … } // makeRelroForSharedLib creates a section of readonly data if necessary. func (state *dodataState) makeRelroForSharedLib(target *Link) { … } type dodataState … // symType returns the (possibly overridden) type of 's'. func (state *dodataState) symType(s loader.Sym) sym.SymKind { … } // setSymType sets a new override type for 's'. func (state *dodataState) setSymType(s loader.Sym, kind sym.SymKind) { … } func (ctxt *Link) dodata(symGroupType []sym.SymKind) { … } // allocateDataSectionForSym creates a new sym.Section into which a // single symbol will be placed. Here "seg" is the segment into which // the section will go, "s" is the symbol to be placed into the new // section, and "rwx" contains permissions for the section. func (state *dodataState) allocateDataSectionForSym(seg *sym.Segment, s loader.Sym, rwx int) *sym.Section { … } // allocateNamedDataSection creates a new sym.Section for a category // of data symbols. Here "seg" is the segment into which the section // will go, "sName" is the name to give to the section, "types" is a // range of symbol types to be put into the section, and "rwx" // contains permissions for the section. func (state *dodataState) allocateNamedDataSection(seg *sym.Segment, sName string, types []sym.SymKind, rwx int) *sym.Section { … } // assignDsymsToSection assigns a collection of data symbols to a // newly created section. "sect" is the section into which to place // the symbols, "syms" holds the list of symbols to assign, // "forceType" (if non-zero) contains a new sym type to apply to each // sym during the assignment, and "aligner" is a hook to call to // handle alignment during the assignment process. func (state *dodataState) assignDsymsToSection(sect *sym.Section, syms []loader.Sym, forceType sym.SymKind, aligner func(state *dodataState, datsize int64, s loader.Sym) int64) { … } func (state *dodataState) assignToSection(sect *sym.Section, symn sym.SymKind, forceType sym.SymKind) { … } // allocateSingleSymSections walks through the bucketed data symbols // with type 'symn', creates a new section for each sym, and assigns // the sym to a newly created section. Section name is set from the // symbol name. "Seg" is the segment into which to place the new // section, "forceType" is the new sym.SymKind to assign to the symbol // within the section, and "rwx" holds section permissions. func (state *dodataState) allocateSingleSymSections(seg *sym.Segment, symn sym.SymKind, forceType sym.SymKind, rwx int) { … } // allocateNamedSectionAndAssignSyms creates a new section with the // specified name, then walks through the bucketed data symbols with // type 'symn' and assigns each of them to this new section. "Seg" is // the segment into which to place the new section, "secName" is the // name to give to the new section, "forceType" (if non-zero) contains // a new sym type to apply to each sym during the assignment, and // "rwx" holds section permissions. func (state *dodataState) allocateNamedSectionAndAssignSyms(seg *sym.Segment, secName string, symn sym.SymKind, forceType sym.SymKind, rwx int) *sym.Section { … } // allocateDataSections allocates sym.Section objects for data/rodata // (and related) symbols, and then assigns symbols to those sections. func (state *dodataState) allocateDataSections(ctxt *Link) { … } // allocateDwarfSections allocates sym.Section objects for DWARF // symbols, and assigns symbols to sections. func (state *dodataState) allocateDwarfSections(ctxt *Link) { … } // allocateSEHSections allocate a sym.Section object for SEH // symbols, and assigns symbols to sections. func (state *dodataState) allocateSEHSections(ctxt *Link) { … } type symNameSize … func (state *dodataState) dodataSect(ctxt *Link, symn sym.SymKind, syms []loader.Sym) (result []loader.Sym, maxAlign int32) { … } // Add buildid to beginning of text segment, on non-ELF systems. // Non-ELF binary formats are not always flexible enough to // give us a place to put the Go build ID. On those systems, we put it // at the very beginning of the text segment. // This “header” is read by cmd/go. func (ctxt *Link) textbuildid() { … } func (ctxt *Link) buildinfo() { … } // appendString appends s to data, prefixed by its varint-encoded length. func appendString(data []byte, s string) []byte { … } // assign addresses to text func (ctxt *Link) textaddress() { … } // assigns address for a text symbol, returns (possibly new) section, its number, and the address. func assignAddress(ctxt *Link, sect *sym.Section, n int, s loader.Sym, va uint64, isTramp, big bool) (*sym.Section, int, uint64) { … } func resetAddress(ctxt *Link, s loader.Sym) { … } // Return whether we may need to split text sections. // // On PPC64x, when external linking, a text section should not be // larger than 2^25 bytes due to the size of call target offset field // in the 'bl' instruction. Splitting into smaller text sections // smaller than this limit allows the system linker to modify the long // calls appropriately. The limit allows for the space needed for // tables inserted by the linker. // // The same applies to Darwin/ARM64, with 2^27 byte threshold. // // Similarly for ARM, we split sections (at 2^25 bytes) to avoid // inconsistencies between the Go linker's reachability calculations // (e.g. will direct call from X to Y need a trampoline) and similar // machinery in the external linker; see #58425 for more on the // history here. func splitTextSections(ctxt *Link) bool { … } const wasmMinDataAddr … // address assigns virtual addresses to all segments and sections and // returns all segments in file order. func (ctxt *Link) address() []*sym.Segment { … } // layout assigns file offsets and lengths to the segments in order. // Returns the file size containing all the segments. func (ctxt *Link) layout(order []*sym.Segment) uint64 { … } // add a trampoline with symbol s (to be laid down after the current function) func (ctxt *Link) AddTramp(s *loader.SymbolBuilder) { … } // compressSyms compresses syms and returns the contents of the // compressed section. If the section would get larger, it returns nil. func compressSyms(ctxt *Link, syms []loader.Sym) []byte { … }