1// Copyright 2009 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 5package ld 6 7import ( 8 "cmd/internal/notsha256" 9 "cmd/internal/objabi" 10 "cmd/internal/sys" 11 "cmd/link/internal/loader" 12 "cmd/link/internal/sym" 13 "debug/elf" 14 "encoding/binary" 15 "encoding/hex" 16 "fmt" 17 "internal/buildcfg" 18 "os" 19 "path/filepath" 20 "runtime" 21 "sort" 22 "strings" 23) 24 25/* 26 * Derived from: 27 * $FreeBSD: src/sys/sys/elf32.h,v 1.8.14.1 2005/12/30 22:13:58 marcel Exp $ 28 * $FreeBSD: src/sys/sys/elf64.h,v 1.10.14.1 2005/12/30 22:13:58 marcel Exp $ 29 * $FreeBSD: src/sys/sys/elf_common.h,v 1.15.8.1 2005/12/30 22:13:58 marcel Exp $ 30 * $FreeBSD: src/sys/alpha/include/elf.h,v 1.14 2003/09/25 01:10:22 peter Exp $ 31 * $FreeBSD: src/sys/amd64/include/elf.h,v 1.18 2004/08/03 08:21:48 dfr Exp $ 32 * $FreeBSD: src/sys/arm/include/elf.h,v 1.5.2.1 2006/06/30 21:42:52 cognet Exp $ 33 * $FreeBSD: src/sys/i386/include/elf.h,v 1.16 2004/08/02 19:12:17 dfr Exp $ 34 * $FreeBSD: src/sys/powerpc/include/elf.h,v 1.7 2004/11/02 09:47:01 ssouhlal Exp $ 35 * $FreeBSD: src/sys/sparc64/include/elf.h,v 1.12 2003/09/25 01:10:26 peter Exp $ 36 * 37 * Copyright (c) 1996-1998 John D. Polstra. All rights reserved. 38 * Copyright (c) 2001 David E. O'Brien 39 * Portions Copyright 2009 The Go Authors. All rights reserved. 40 * 41 * Redistribution and use in source and binary forms, with or without 42 * modification, are permitted provided that the following conditions 43 * are met: 44 * 1. Redistributions of source code must retain the above copyright 45 * notice, this list of conditions and the following disclaimer. 46 * 2. Redistributions in binary form must reproduce the above copyright 47 * notice, this list of conditions and the following disclaimer in the 48 * documentation and/or other materials provided with the distribution. 49 * 50 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 51 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 52 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 53 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 54 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 55 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 56 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 57 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 58 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 59 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 60 * SUCH DAMAGE. 61 * 62 */ 63 64/* 65 * ELF definitions that are independent of architecture or word size. 66 */ 67 68/* 69 * Note header. The ".note" section contains an array of notes. Each 70 * begins with this header, aligned to a word boundary. Immediately 71 * following the note header is n_namesz bytes of name, padded to the 72 * next word boundary. Then comes n_descsz bytes of descriptor, again 73 * padded to a word boundary. The values of n_namesz and n_descsz do 74 * not include the padding. 75 */ 76type elfNote struct { 77 nNamesz uint32 78 nDescsz uint32 79 nType uint32 80} 81 82/* For accessing the fields of r_info. */ 83 84/* For constructing r_info from field values. */ 85 86/* 87 * Relocation types. 88 */ 89const ( 90 ARM_MAGIC_TRAMP_NUMBER = 0x5c000003 91) 92 93/* 94 * Symbol table entries. 95 */ 96 97/* For accessing the fields of st_info. */ 98 99/* For constructing st_info from field values. */ 100 101/* For accessing the fields of st_other. */ 102 103/* 104 * ELF header. 105 */ 106type ElfEhdr elf.Header64 107 108/* 109 * Section header. 110 */ 111type ElfShdr struct { 112 elf.Section64 113 shnum elf.SectionIndex 114} 115 116/* 117 * Program header. 118 */ 119type ElfPhdr elf.ProgHeader 120 121/* For accessing the fields of r_info. */ 122 123/* For constructing r_info from field values. */ 124 125/* 126 * Symbol table entries. 127 */ 128 129/* For accessing the fields of st_info. */ 130 131/* For constructing st_info from field values. */ 132 133/* For accessing the fields of st_other. */ 134 135/* 136 * Go linker interface 137 */ 138const ( 139 ELF64HDRSIZE = 64 140 ELF64PHDRSIZE = 56 141 ELF64SHDRSIZE = 64 142 ELF64RELSIZE = 16 143 ELF64RELASIZE = 24 144 ELF64SYMSIZE = 24 145 ELF32HDRSIZE = 52 146 ELF32PHDRSIZE = 32 147 ELF32SHDRSIZE = 40 148 ELF32SYMSIZE = 16 149 ELF32RELSIZE = 8 150) 151 152/* 153 * The interface uses the 64-bit structures always, 154 * to avoid code duplication. The writers know how to 155 * marshal a 32-bit representation from the 64-bit structure. 156 */ 157 158var elfstrdat, elfshstrdat []byte 159 160/* 161 * Total amount of space to reserve at the start of the file 162 * for Header, PHeaders, SHeaders, and interp. 163 * May waste some. 164 * On FreeBSD, cannot be larger than a page. 165 */ 166const ( 167 ELFRESERVE = 4096 168) 169 170/* 171 * We use the 64-bit data structures on both 32- and 64-bit machines 172 * in order to write the code just once. The 64-bit data structure is 173 * written in the 32-bit format on the 32-bit machines. 174 */ 175const ( 176 NSECT = 400 177) 178 179var ( 180 Nelfsym = 1 181 182 elf64 bool 183 // Either ".rel" or ".rela" depending on which type of relocation the 184 // target platform uses. 185 elfRelType string 186 187 ehdr ElfEhdr 188 phdr [NSECT]*ElfPhdr 189 shdr [NSECT]*ElfShdr 190 191 interp string 192) 193 194// ELFArch includes target-specific hooks for ELF targets. 195// This is initialized by the target-specific Init function 196// called by the linker's main function in cmd/link/main.go. 197type ELFArch struct { 198 // TODO: Document these fields. 199 200 Androiddynld string 201 Linuxdynld string 202 LinuxdynldMusl string 203 Freebsddynld string 204 Netbsddynld string 205 Openbsddynld string 206 Dragonflydynld string 207 Solarisdynld string 208 209 Reloc1 func(*Link, *OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int, int64) bool 210 RelocSize uint32 // size of an ELF relocation record, must match Reloc1. 211 SetupPLT func(ctxt *Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) 212 213 // DynamicReadOnly can be set to true to make the .dynamic 214 // section read-only. By default it is writable. 215 // This is used by MIPS targets. 216 DynamicReadOnly bool 217} 218 219type Elfstring struct { 220 s string 221 off int 222} 223 224var elfstr [100]Elfstring 225 226var nelfstr int 227 228var buildinfo []byte 229 230/* 231Initialize the global variable that describes the ELF header. It will be updated as 232we write section and prog headers. 233*/ 234func Elfinit(ctxt *Link) { 235 ctxt.IsELF = true 236 237 if ctxt.Arch.InFamily(sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.PPC64, sys.RISCV64, sys.S390X) { 238 elfRelType = ".rela" 239 } else { 240 elfRelType = ".rel" 241 } 242 243 switch ctxt.Arch.Family { 244 // 64-bit architectures 245 case sys.PPC64, sys.S390X: 246 if ctxt.Arch.ByteOrder == binary.BigEndian && ctxt.HeadType != objabi.Hopenbsd { 247 ehdr.Flags = 1 /* Version 1 ABI */ 248 } else { 249 ehdr.Flags = 2 /* Version 2 ABI */ 250 } 251 fallthrough 252 case sys.AMD64, sys.ARM64, sys.Loong64, sys.MIPS64, sys.RISCV64: 253 if ctxt.Arch.Family == sys.MIPS64 { 254 ehdr.Flags = 0x20000004 /* MIPS 3 CPIC */ 255 } 256 if ctxt.Arch.Family == sys.Loong64 { 257 ehdr.Flags = 0x43 /* DOUBLE_FLOAT, OBJABI_V1 */ 258 } 259 if ctxt.Arch.Family == sys.RISCV64 { 260 ehdr.Flags = 0x4 /* RISCV Float ABI Double */ 261 } 262 elf64 = true 263 264 ehdr.Phoff = ELF64HDRSIZE /* Must be ELF64HDRSIZE: first PHdr must follow ELF header */ 265 ehdr.Shoff = ELF64HDRSIZE /* Will move as we add PHeaders */ 266 ehdr.Ehsize = ELF64HDRSIZE /* Must be ELF64HDRSIZE */ 267 ehdr.Phentsize = ELF64PHDRSIZE /* Must be ELF64PHDRSIZE */ 268 ehdr.Shentsize = ELF64SHDRSIZE /* Must be ELF64SHDRSIZE */ 269 270 // 32-bit architectures 271 case sys.ARM, sys.MIPS: 272 if ctxt.Arch.Family == sys.ARM { 273 // we use EABI on linux/arm, freebsd/arm, netbsd/arm. 274 if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd || ctxt.HeadType == objabi.Hnetbsd { 275 // We set a value here that makes no indication of which 276 // float ABI the object uses, because this is information 277 // used by the dynamic linker to compare executables and 278 // shared libraries -- so it only matters for cgo calls, and 279 // the information properly comes from the object files 280 // produced by the host C compiler. parseArmAttributes in 281 // ldelf.go reads that information and updates this field as 282 // appropriate. 283 ehdr.Flags = 0x5000002 // has entry point, Version5 EABI 284 } 285 } else if ctxt.Arch.Family == sys.MIPS { 286 ehdr.Flags = 0x50001004 /* MIPS 32 CPIC O32*/ 287 } 288 fallthrough 289 default: 290 ehdr.Phoff = ELF32HDRSIZE 291 /* Must be ELF32HDRSIZE: first PHdr must follow ELF header */ 292 ehdr.Shoff = ELF32HDRSIZE /* Will move as we add PHeaders */ 293 ehdr.Ehsize = ELF32HDRSIZE /* Must be ELF32HDRSIZE */ 294 ehdr.Phentsize = ELF32PHDRSIZE /* Must be ELF32PHDRSIZE */ 295 ehdr.Shentsize = ELF32SHDRSIZE /* Must be ELF32SHDRSIZE */ 296 } 297} 298 299// Make sure PT_LOAD is aligned properly and 300// that there is no gap, 301// correct ELF loaders will do this implicitly, 302// but buggy ELF loaders like the one in some 303// versions of QEMU and UPX won't. 304func fixElfPhdr(e *ElfPhdr) { 305 frag := int(e.Vaddr & (e.Align - 1)) 306 307 e.Off -= uint64(frag) 308 e.Vaddr -= uint64(frag) 309 e.Paddr -= uint64(frag) 310 e.Filesz += uint64(frag) 311 e.Memsz += uint64(frag) 312} 313 314func elf64phdr(out *OutBuf, e *ElfPhdr) { 315 if e.Type == elf.PT_LOAD { 316 fixElfPhdr(e) 317 } 318 319 out.Write32(uint32(e.Type)) 320 out.Write32(uint32(e.Flags)) 321 out.Write64(e.Off) 322 out.Write64(e.Vaddr) 323 out.Write64(e.Paddr) 324 out.Write64(e.Filesz) 325 out.Write64(e.Memsz) 326 out.Write64(e.Align) 327} 328 329func elf32phdr(out *OutBuf, e *ElfPhdr) { 330 if e.Type == elf.PT_LOAD { 331 fixElfPhdr(e) 332 } 333 334 out.Write32(uint32(e.Type)) 335 out.Write32(uint32(e.Off)) 336 out.Write32(uint32(e.Vaddr)) 337 out.Write32(uint32(e.Paddr)) 338 out.Write32(uint32(e.Filesz)) 339 out.Write32(uint32(e.Memsz)) 340 out.Write32(uint32(e.Flags)) 341 out.Write32(uint32(e.Align)) 342} 343 344func elf64shdr(out *OutBuf, e *ElfShdr) { 345 out.Write32(e.Name) 346 out.Write32(uint32(e.Type)) 347 out.Write64(uint64(e.Flags)) 348 out.Write64(e.Addr) 349 out.Write64(e.Off) 350 out.Write64(e.Size) 351 out.Write32(e.Link) 352 out.Write32(e.Info) 353 out.Write64(e.Addralign) 354 out.Write64(e.Entsize) 355} 356 357func elf32shdr(out *OutBuf, e *ElfShdr) { 358 out.Write32(e.Name) 359 out.Write32(uint32(e.Type)) 360 out.Write32(uint32(e.Flags)) 361 out.Write32(uint32(e.Addr)) 362 out.Write32(uint32(e.Off)) 363 out.Write32(uint32(e.Size)) 364 out.Write32(e.Link) 365 out.Write32(e.Info) 366 out.Write32(uint32(e.Addralign)) 367 out.Write32(uint32(e.Entsize)) 368} 369 370func elfwriteshdrs(out *OutBuf) uint32 { 371 if elf64 { 372 for i := 0; i < int(ehdr.Shnum); i++ { 373 elf64shdr(out, shdr[i]) 374 } 375 return uint32(ehdr.Shnum) * ELF64SHDRSIZE 376 } 377 378 for i := 0; i < int(ehdr.Shnum); i++ { 379 elf32shdr(out, shdr[i]) 380 } 381 return uint32(ehdr.Shnum) * ELF32SHDRSIZE 382} 383 384func elfsetstring(ctxt *Link, s loader.Sym, str string, off int) { 385 if nelfstr >= len(elfstr) { 386 ctxt.Errorf(s, "too many elf strings") 387 errorexit() 388 } 389 390 elfstr[nelfstr].s = str 391 elfstr[nelfstr].off = off 392 nelfstr++ 393} 394 395func elfwritephdrs(out *OutBuf) uint32 { 396 if elf64 { 397 for i := 0; i < int(ehdr.Phnum); i++ { 398 elf64phdr(out, phdr[i]) 399 } 400 return uint32(ehdr.Phnum) * ELF64PHDRSIZE 401 } 402 403 for i := 0; i < int(ehdr.Phnum); i++ { 404 elf32phdr(out, phdr[i]) 405 } 406 return uint32(ehdr.Phnum) * ELF32PHDRSIZE 407} 408 409func newElfPhdr() *ElfPhdr { 410 e := new(ElfPhdr) 411 if ehdr.Phnum >= NSECT { 412 Errorf(nil, "too many phdrs") 413 } else { 414 phdr[ehdr.Phnum] = e 415 ehdr.Phnum++ 416 } 417 if elf64 { 418 ehdr.Shoff += ELF64PHDRSIZE 419 } else { 420 ehdr.Shoff += ELF32PHDRSIZE 421 } 422 return e 423} 424 425func newElfShdr(name int64) *ElfShdr { 426 e := new(ElfShdr) 427 e.Name = uint32(name) 428 e.shnum = elf.SectionIndex(ehdr.Shnum) 429 if ehdr.Shnum >= NSECT { 430 Errorf(nil, "too many shdrs") 431 } else { 432 shdr[ehdr.Shnum] = e 433 ehdr.Shnum++ 434 } 435 436 return e 437} 438 439func getElfEhdr() *ElfEhdr { 440 return &ehdr 441} 442 443func elf64writehdr(out *OutBuf) uint32 { 444 out.Write(ehdr.Ident[:]) 445 out.Write16(uint16(ehdr.Type)) 446 out.Write16(uint16(ehdr.Machine)) 447 out.Write32(uint32(ehdr.Version)) 448 out.Write64(ehdr.Entry) 449 out.Write64(ehdr.Phoff) 450 out.Write64(ehdr.Shoff) 451 out.Write32(ehdr.Flags) 452 out.Write16(ehdr.Ehsize) 453 out.Write16(ehdr.Phentsize) 454 out.Write16(ehdr.Phnum) 455 out.Write16(ehdr.Shentsize) 456 out.Write16(ehdr.Shnum) 457 out.Write16(ehdr.Shstrndx) 458 return ELF64HDRSIZE 459} 460 461func elf32writehdr(out *OutBuf) uint32 { 462 out.Write(ehdr.Ident[:]) 463 out.Write16(uint16(ehdr.Type)) 464 out.Write16(uint16(ehdr.Machine)) 465 out.Write32(uint32(ehdr.Version)) 466 out.Write32(uint32(ehdr.Entry)) 467 out.Write32(uint32(ehdr.Phoff)) 468 out.Write32(uint32(ehdr.Shoff)) 469 out.Write32(ehdr.Flags) 470 out.Write16(ehdr.Ehsize) 471 out.Write16(ehdr.Phentsize) 472 out.Write16(ehdr.Phnum) 473 out.Write16(ehdr.Shentsize) 474 out.Write16(ehdr.Shnum) 475 out.Write16(ehdr.Shstrndx) 476 return ELF32HDRSIZE 477} 478 479func elfwritehdr(out *OutBuf) uint32 { 480 if elf64 { 481 return elf64writehdr(out) 482 } 483 return elf32writehdr(out) 484} 485 486/* Taken directly from the definition document for ELF64. */ 487func elfhash(name string) uint32 { 488 var h uint32 489 for i := 0; i < len(name); i++ { 490 h = (h << 4) + uint32(name[i]) 491 if g := h & 0xf0000000; g != 0 { 492 h ^= g >> 24 493 } 494 h &= 0x0fffffff 495 } 496 return h 497} 498 499func elfWriteDynEntSym(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) { 500 Elfwritedynentsymplus(ctxt, s, tag, t, 0) 501} 502 503func Elfwritedynent(arch *sys.Arch, s *loader.SymbolBuilder, tag elf.DynTag, val uint64) { 504 if elf64 { 505 s.AddUint64(arch, uint64(tag)) 506 s.AddUint64(arch, val) 507 } else { 508 s.AddUint32(arch, uint32(tag)) 509 s.AddUint32(arch, uint32(val)) 510 } 511} 512 513func Elfwritedynentsymplus(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym, add int64) { 514 if elf64 { 515 s.AddUint64(ctxt.Arch, uint64(tag)) 516 } else { 517 s.AddUint32(ctxt.Arch, uint32(tag)) 518 } 519 s.AddAddrPlus(ctxt.Arch, t, add) 520} 521 522func elfwritedynentsymsize(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) { 523 if elf64 { 524 s.AddUint64(ctxt.Arch, uint64(tag)) 525 } else { 526 s.AddUint32(ctxt.Arch, uint32(tag)) 527 } 528 s.AddSize(ctxt.Arch, t) 529} 530 531func elfinterp(sh *ElfShdr, startva uint64, resoff uint64, p string) int { 532 interp = p 533 n := len(interp) + 1 534 sh.Addr = startva + resoff - uint64(n) 535 sh.Off = resoff - uint64(n) 536 sh.Size = uint64(n) 537 538 return n 539} 540 541func elfwriteinterp(out *OutBuf) int { 542 sh := elfshname(".interp") 543 out.SeekSet(int64(sh.Off)) 544 out.WriteString(interp) 545 out.Write8(0) 546 return int(sh.Size) 547} 548 549// member of .gnu.attributes of MIPS for fpAbi 550const ( 551 // No floating point is present in the module (default) 552 MIPS_FPABI_NONE = 0 553 // FP code in the module uses the FP32 ABI for a 32-bit ABI 554 MIPS_FPABI_ANY = 1 555 // FP code in the module only uses single precision ABI 556 MIPS_FPABI_SINGLE = 2 557 // FP code in the module uses soft-float ABI 558 MIPS_FPABI_SOFT = 3 559 // FP code in the module assumes an FPU with FR=1 and has 12 560 // callee-saved doubles. Historic, no longer supported. 561 MIPS_FPABI_HIST = 4 562 // FP code in the module uses the FPXX ABI 563 MIPS_FPABI_FPXX = 5 564 // FP code in the module uses the FP64 ABI 565 MIPS_FPABI_FP64 = 6 566 // FP code in the module uses the FP64A ABI 567 MIPS_FPABI_FP64A = 7 568) 569 570func elfMipsAbiFlags(sh *ElfShdr, startva uint64, resoff uint64) int { 571 n := 24 572 sh.Addr = startva + resoff - uint64(n) 573 sh.Off = resoff - uint64(n) 574 sh.Size = uint64(n) 575 sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS) 576 sh.Flags = uint64(elf.SHF_ALLOC) 577 578 return n 579} 580 581// Layout is given by this C definition: 582// 583// typedef struct 584// { 585// /* Version of flags structure. */ 586// uint16_t version; 587// /* The level of the ISA: 1-5, 32, 64. */ 588// uint8_t isa_level; 589// /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise. */ 590// uint8_t isa_rev; 591// /* The size of general purpose registers. */ 592// uint8_t gpr_size; 593// /* The size of co-processor 1 registers. */ 594// uint8_t cpr1_size; 595// /* The size of co-processor 2 registers. */ 596// uint8_t cpr2_size; 597// /* The floating-point ABI. */ 598// uint8_t fp_abi; 599// /* Processor-specific extension. */ 600// uint32_t isa_ext; 601// /* Mask of ASEs used. */ 602// uint32_t ases; 603// /* Mask of general flags. */ 604// uint32_t flags1; 605// uint32_t flags2; 606// } Elf_Internal_ABIFlags_v0; 607func elfWriteMipsAbiFlags(ctxt *Link) int { 608 sh := elfshname(".MIPS.abiflags") 609 ctxt.Out.SeekSet(int64(sh.Off)) 610 ctxt.Out.Write16(0) // version 611 ctxt.Out.Write8(32) // isaLevel 612 ctxt.Out.Write8(1) // isaRev 613 ctxt.Out.Write8(1) // gprSize 614 ctxt.Out.Write8(1) // cpr1Size 615 ctxt.Out.Write8(0) // cpr2Size 616 if buildcfg.GOMIPS == "softfloat" { 617 ctxt.Out.Write8(MIPS_FPABI_SOFT) // fpAbi 618 } else { 619 // Go cannot make sure non odd-number-fpr is used (ie, in load a double from memory). 620 // So, we mark the object is MIPS I style paired float/double register scheme, 621 // aka MIPS_FPABI_ANY. If we mark the object as FPXX, the kernel may use FR=1 mode, 622 // then we meet some problem. 623 // Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage. 624 // It is not for 'ANY'. 625 // TODO: switch to FPXX after be sure that no odd-number-fpr is used. 626 ctxt.Out.Write8(MIPS_FPABI_ANY) // fpAbi 627 } 628 ctxt.Out.Write32(0) // isaExt 629 ctxt.Out.Write32(0) // ases 630 ctxt.Out.Write32(0) // flags1 631 ctxt.Out.Write32(0) // flags2 632 return int(sh.Size) 633} 634 635func elfnote(sh *ElfShdr, startva uint64, resoff uint64, sizes ...int) int { 636 n := resoff % 4 637 // if section contains multiple notes (as is the case with FreeBSD signature), 638 // multiple note sizes can be specified 639 for _, sz := range sizes { 640 n += 3*4 + uint64(sz) 641 } 642 643 sh.Type = uint32(elf.SHT_NOTE) 644 sh.Flags = uint64(elf.SHF_ALLOC) 645 sh.Addralign = 4 646 sh.Addr = startva + resoff - n 647 sh.Off = resoff - n 648 sh.Size = n - resoff%4 649 650 return int(n) 651} 652 653func elfwritenotehdr(out *OutBuf, str string, namesz uint32, descsz uint32, tag uint32) *ElfShdr { 654 sh := elfshname(str) 655 656 // Write Elf_Note header. 657 out.SeekSet(int64(sh.Off)) 658 659 out.Write32(namesz) 660 out.Write32(descsz) 661 out.Write32(tag) 662 663 return sh 664} 665 666// NetBSD Signature (as per sys/exec_elf.h) 667const ( 668 ELF_NOTE_NETBSD_NAMESZ = 7 669 ELF_NOTE_NETBSD_DESCSZ = 4 670 ELF_NOTE_NETBSD_TAG = 1 671 ELF_NOTE_NETBSD_VERSION = 700000000 /* NetBSD 7.0 */ 672) 673 674var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00") 675 676func elfnetbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int { 677 n := int(Rnd(ELF_NOTE_NETBSD_NAMESZ, 4) + Rnd(ELF_NOTE_NETBSD_DESCSZ, 4)) 678 return elfnote(sh, startva, resoff, n) 679} 680 681func elfwritenetbsdsig(out *OutBuf) int { 682 // Write Elf_Note header. 683 sh := elfwritenotehdr(out, ".note.netbsd.ident", ELF_NOTE_NETBSD_NAMESZ, ELF_NOTE_NETBSD_DESCSZ, ELF_NOTE_NETBSD_TAG) 684 685 if sh == nil { 686 return 0 687 } 688 689 // Followed by NetBSD string and version. 690 out.Write(ELF_NOTE_NETBSD_NAME) 691 out.Write8(0) 692 out.Write32(ELF_NOTE_NETBSD_VERSION) 693 694 return int(sh.Size) 695} 696 697// The race detector can't handle ASLR (address space layout randomization). 698// ASLR is on by default for NetBSD, so we turn the ASLR off explicitly 699// using a magic elf Note when building race binaries. 700 701func elfnetbsdpax(sh *ElfShdr, startva uint64, resoff uint64) int { 702 n := int(Rnd(4, 4) + Rnd(4, 4)) 703 return elfnote(sh, startva, resoff, n) 704} 705 706func elfwritenetbsdpax(out *OutBuf) int { 707 sh := elfwritenotehdr(out, ".note.netbsd.pax", 4 /* length of PaX\x00 */, 4 /* length of flags */, 0x03 /* PaX type */) 708 if sh == nil { 709 return 0 710 } 711 out.Write([]byte("PaX\x00")) 712 out.Write32(0x20) // 0x20 = Force disable ASLR 713 return int(sh.Size) 714} 715 716// OpenBSD Signature 717const ( 718 ELF_NOTE_OPENBSD_NAMESZ = 8 719 ELF_NOTE_OPENBSD_DESCSZ = 4 720 ELF_NOTE_OPENBSD_TAG = 1 721 ELF_NOTE_OPENBSD_VERSION = 0 722) 723 724var ELF_NOTE_OPENBSD_NAME = []byte("OpenBSD\x00") 725 726func elfopenbsdsig(sh *ElfShdr, startva uint64, resoff uint64) int { 727 n := ELF_NOTE_OPENBSD_NAMESZ + ELF_NOTE_OPENBSD_DESCSZ 728 return elfnote(sh, startva, resoff, n) 729} 730 731func elfwriteopenbsdsig(out *OutBuf) int { 732 // Write Elf_Note header. 733 sh := elfwritenotehdr(out, ".note.openbsd.ident", ELF_NOTE_OPENBSD_NAMESZ, ELF_NOTE_OPENBSD_DESCSZ, ELF_NOTE_OPENBSD_TAG) 734 735 if sh == nil { 736 return 0 737 } 738 739 // Followed by OpenBSD string and version. 740 out.Write(ELF_NOTE_OPENBSD_NAME) 741 742 out.Write32(ELF_NOTE_OPENBSD_VERSION) 743 744 return int(sh.Size) 745} 746 747// FreeBSD Signature (as per sys/elf_common.h) 748const ( 749 ELF_NOTE_FREEBSD_NAMESZ = 8 750 ELF_NOTE_FREEBSD_DESCSZ = 4 751 ELF_NOTE_FREEBSD_ABI_TAG = 1 752 ELF_NOTE_FREEBSD_NOINIT_TAG = 2 753 ELF_NOTE_FREEBSD_FEATURE_CTL_TAG = 4 754 ELF_NOTE_FREEBSD_VERSION = 1203000 // 12.3-RELEASE 755 ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE = 0x1 756) 757 758const ELF_NOTE_FREEBSD_NAME = "FreeBSD\x00" 759 760func elffreebsdsig(sh *ElfShdr, startva uint64, resoff uint64) int { 761 n := ELF_NOTE_FREEBSD_NAMESZ + ELF_NOTE_FREEBSD_DESCSZ 762 // FreeBSD signature section contains 3 equally sized notes 763 return elfnote(sh, startva, resoff, n, n, n) 764} 765 766// elfwritefreebsdsig writes FreeBSD .note section. 767// 768// See https://www.netbsd.org/docs/kernel/elf-notes.html for the description of 769// a Note element format and 770// https://github.com/freebsd/freebsd-src/blob/main/sys/sys/elf_common.h#L790 771// for the FreeBSD-specific values. 772func elfwritefreebsdsig(out *OutBuf) int { 773 sh := elfshname(".note.tag") 774 if sh == nil { 775 return 0 776 } 777 out.SeekSet(int64(sh.Off)) 778 779 // NT_FREEBSD_ABI_TAG 780 out.Write32(ELF_NOTE_FREEBSD_NAMESZ) 781 out.Write32(ELF_NOTE_FREEBSD_DESCSZ) 782 out.Write32(ELF_NOTE_FREEBSD_ABI_TAG) 783 out.WriteString(ELF_NOTE_FREEBSD_NAME) 784 out.Write32(ELF_NOTE_FREEBSD_VERSION) 785 786 // NT_FREEBSD_NOINIT_TAG 787 out.Write32(ELF_NOTE_FREEBSD_NAMESZ) 788 out.Write32(ELF_NOTE_FREEBSD_DESCSZ) 789 out.Write32(ELF_NOTE_FREEBSD_NOINIT_TAG) 790 out.WriteString(ELF_NOTE_FREEBSD_NAME) 791 out.Write32(0) 792 793 // NT_FREEBSD_FEATURE_CTL 794 out.Write32(ELF_NOTE_FREEBSD_NAMESZ) 795 out.Write32(ELF_NOTE_FREEBSD_DESCSZ) 796 out.Write32(ELF_NOTE_FREEBSD_FEATURE_CTL_TAG) 797 out.WriteString(ELF_NOTE_FREEBSD_NAME) 798 if *flagRace { 799 // The race detector can't handle ASLR, turn the ASLR off when compiling with -race. 800 out.Write32(ELF_NOTE_FREEBSD_FCTL_ASLR_DISABLE) 801 } else { 802 out.Write32(0) 803 } 804 805 return int(sh.Size) 806} 807 808func addbuildinfo(ctxt *Link) { 809 val := *flagHostBuildid 810 if val == "gobuildid" { 811 buildID := *flagBuildid 812 if buildID == "" { 813 Exitf("-B gobuildid requires a Go build ID supplied via -buildid") 814 } 815 816 if ctxt.IsDarwin() { 817 buildinfo = uuidFromGoBuildId(buildID) 818 return 819 } 820 821 hashedBuildID := notsha256.Sum256([]byte(buildID)) 822 buildinfo = hashedBuildID[:20] 823 824 return 825 } 826 827 if !strings.HasPrefix(val, "0x") { 828 Exitf("-B argument must start with 0x: %s", val) 829 } 830 ov := val 831 val = val[2:] 832 833 maxLen := 32 834 if ctxt.IsDarwin() { 835 maxLen = 16 836 } 837 if hex.DecodedLen(len(val)) > maxLen { 838 Exitf("-B option too long (max %d digits): %s", maxLen, ov) 839 } 840 841 b, err := hex.DecodeString(val) 842 if err != nil { 843 if err == hex.ErrLength { 844 Exitf("-B argument must have even number of digits: %s", ov) 845 } 846 if inv, ok := err.(hex.InvalidByteError); ok { 847 Exitf("-B argument contains invalid hex digit %c: %s", byte(inv), ov) 848 } 849 Exitf("-B argument contains invalid hex: %s", ov) 850 } 851 852 buildinfo = b 853} 854 855// Build info note 856const ( 857 ELF_NOTE_BUILDINFO_NAMESZ = 4 858 ELF_NOTE_BUILDINFO_TAG = 3 859) 860 861var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00") 862 863func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int { 864 n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4)) 865 return elfnote(sh, startva, resoff, n) 866} 867 868func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int { 869 n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(*flagBuildid)), 4)) 870 return elfnote(sh, startva, resoff, n) 871} 872 873func elfwritebuildinfo(out *OutBuf) int { 874 sh := elfwritenotehdr(out, ".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG) 875 if sh == nil { 876 return 0 877 } 878 879 out.Write(ELF_NOTE_BUILDINFO_NAME) 880 out.Write(buildinfo) 881 var zero = make([]byte, 4) 882 out.Write(zero[:int(Rnd(int64(len(buildinfo)), 4)-int64(len(buildinfo)))]) 883 884 return int(sh.Size) 885} 886 887func elfwritegobuildid(out *OutBuf) int { 888 sh := elfwritenotehdr(out, ".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(*flagBuildid)), ELF_NOTE_GOBUILDID_TAG) 889 if sh == nil { 890 return 0 891 } 892 893 out.Write(ELF_NOTE_GO_NAME) 894 out.Write([]byte(*flagBuildid)) 895 var zero = make([]byte, 4) 896 out.Write(zero[:int(Rnd(int64(len(*flagBuildid)), 4)-int64(len(*flagBuildid)))]) 897 898 return int(sh.Size) 899} 900 901// Go specific notes 902const ( 903 ELF_NOTE_GOPKGLIST_TAG = 1 904 ELF_NOTE_GOABIHASH_TAG = 2 905 ELF_NOTE_GODEPS_TAG = 3 906 ELF_NOTE_GOBUILDID_TAG = 4 907) 908 909var ELF_NOTE_GO_NAME = []byte("Go\x00\x00") 910 911var elfverneed int 912 913type Elfaux struct { 914 next *Elfaux 915 num int 916 vers string 917} 918 919type Elflib struct { 920 next *Elflib 921 aux *Elfaux 922 file string 923} 924 925func addelflib(list **Elflib, file string, vers string) *Elfaux { 926 var lib *Elflib 927 928 for lib = *list; lib != nil; lib = lib.next { 929 if lib.file == file { 930 goto havelib 931 } 932 } 933 lib = new(Elflib) 934 lib.next = *list 935 lib.file = file 936 *list = lib 937 938havelib: 939 for aux := lib.aux; aux != nil; aux = aux.next { 940 if aux.vers == vers { 941 return aux 942 } 943 } 944 aux := new(Elfaux) 945 aux.next = lib.aux 946 aux.vers = vers 947 lib.aux = aux 948 949 return aux 950} 951 952func elfdynhash(ctxt *Link) { 953 if !ctxt.IsELF { 954 return 955 } 956 957 nsym := Nelfsym 958 ldr := ctxt.loader 959 s := ldr.CreateSymForUpdate(".hash", 0) 960 s.SetType(sym.SELFROSECT) 961 962 i := nsym 963 nbucket := 1 964 for i > 0 { 965 nbucket++ 966 i >>= 1 967 } 968 969 var needlib *Elflib 970 need := make([]*Elfaux, nsym) 971 chain := make([]uint32, nsym) 972 buckets := make([]uint32, nbucket) 973 974 for _, sy := range ldr.DynidSyms() { 975 976 dynid := ldr.SymDynid(sy) 977 if ldr.SymDynimpvers(sy) != "" { 978 need[dynid] = addelflib(&needlib, ldr.SymDynimplib(sy), ldr.SymDynimpvers(sy)) 979 } 980 981 name := ldr.SymExtname(sy) 982 hc := elfhash(name) 983 984 b := hc % uint32(nbucket) 985 chain[dynid] = buckets[b] 986 buckets[b] = uint32(dynid) 987 } 988 989 // s390x (ELF64) hash table entries are 8 bytes 990 if ctxt.Arch.Family == sys.S390X { 991 s.AddUint64(ctxt.Arch, uint64(nbucket)) 992 s.AddUint64(ctxt.Arch, uint64(nsym)) 993 for i := 0; i < nbucket; i++ { 994 s.AddUint64(ctxt.Arch, uint64(buckets[i])) 995 } 996 for i := 0; i < nsym; i++ { 997 s.AddUint64(ctxt.Arch, uint64(chain[i])) 998 } 999 } else { 1000 s.AddUint32(ctxt.Arch, uint32(nbucket)) 1001 s.AddUint32(ctxt.Arch, uint32(nsym)) 1002 for i := 0; i < nbucket; i++ { 1003 s.AddUint32(ctxt.Arch, buckets[i]) 1004 } 1005 for i := 0; i < nsym; i++ { 1006 s.AddUint32(ctxt.Arch, chain[i]) 1007 } 1008 } 1009 1010 dynstr := ldr.CreateSymForUpdate(".dynstr", 0) 1011 1012 // version symbols 1013 gnuVersionR := ldr.CreateSymForUpdate(".gnu.version_r", 0) 1014 s = gnuVersionR 1015 i = 2 1016 nfile := 0 1017 for l := needlib; l != nil; l = l.next { 1018 nfile++ 1019 1020 // header 1021 s.AddUint16(ctxt.Arch, 1) // table version 1022 j := 0 1023 for x := l.aux; x != nil; x = x.next { 1024 j++ 1025 } 1026 s.AddUint16(ctxt.Arch, uint16(j)) // aux count 1027 s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(l.file))) // file string offset 1028 s.AddUint32(ctxt.Arch, 16) // offset from header to first aux 1029 if l.next != nil { 1030 s.AddUint32(ctxt.Arch, 16+uint32(j)*16) // offset from this header to next 1031 } else { 1032 s.AddUint32(ctxt.Arch, 0) 1033 } 1034 1035 for x := l.aux; x != nil; x = x.next { 1036 x.num = i 1037 i++ 1038 1039 // aux struct 1040 s.AddUint32(ctxt.Arch, elfhash(x.vers)) // hash 1041 s.AddUint16(ctxt.Arch, 0) // flags 1042 s.AddUint16(ctxt.Arch, uint16(x.num)) // other - index we refer to this by 1043 s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(x.vers))) // version string offset 1044 if x.next != nil { 1045 s.AddUint32(ctxt.Arch, 16) // offset from this aux to next 1046 } else { 1047 s.AddUint32(ctxt.Arch, 0) 1048 } 1049 } 1050 } 1051 1052 // version references 1053 gnuVersion := ldr.CreateSymForUpdate(".gnu.version", 0) 1054 s = gnuVersion 1055 1056 for i := 0; i < nsym; i++ { 1057 if i == 0 { 1058 s.AddUint16(ctxt.Arch, 0) // first entry - no symbol 1059 } else if need[i] == nil { 1060 s.AddUint16(ctxt.Arch, 1) // global 1061 } else { 1062 s.AddUint16(ctxt.Arch, uint16(need[i].num)) 1063 } 1064 } 1065 1066 s = ldr.CreateSymForUpdate(".dynamic", 0) 1067 1068 var dtFlags1 elf.DynFlag1 1069 if *flagBindNow { 1070 dtFlags1 |= elf.DF_1_NOW 1071 Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS, uint64(elf.DF_BIND_NOW)) 1072 } 1073 if ctxt.BuildMode == BuildModePIE { 1074 dtFlags1 |= elf.DF_1_PIE 1075 } 1076 Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS_1, uint64(dtFlags1)) 1077 1078 elfverneed = nfile 1079 if elfverneed != 0 { 1080 elfWriteDynEntSym(ctxt, s, elf.DT_VERNEED, gnuVersionR.Sym()) 1081 Elfwritedynent(ctxt.Arch, s, elf.DT_VERNEEDNUM, uint64(nfile)) 1082 elfWriteDynEntSym(ctxt, s, elf.DT_VERSYM, gnuVersion.Sym()) 1083 } 1084 1085 sy := ldr.CreateSymForUpdate(elfRelType+".plt", 0) 1086 if sy.Size() > 0 { 1087 if elfRelType == ".rela" { 1088 Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_RELA)) 1089 } else { 1090 Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_REL)) 1091 } 1092 elfwritedynentsymsize(ctxt, s, elf.DT_PLTRELSZ, sy.Sym()) 1093 elfWriteDynEntSym(ctxt, s, elf.DT_JMPREL, sy.Sym()) 1094 } 1095 1096 Elfwritedynent(ctxt.Arch, s, elf.DT_NULL, 0) 1097} 1098 1099func elfphload(seg *sym.Segment) *ElfPhdr { 1100 ph := newElfPhdr() 1101 ph.Type = elf.PT_LOAD 1102 if seg.Rwx&4 != 0 { 1103 ph.Flags |= elf.PF_R 1104 } 1105 if seg.Rwx&2 != 0 { 1106 ph.Flags |= elf.PF_W 1107 } 1108 if seg.Rwx&1 != 0 { 1109 ph.Flags |= elf.PF_X 1110 } 1111 ph.Vaddr = seg.Vaddr 1112 ph.Paddr = seg.Vaddr 1113 ph.Memsz = seg.Length 1114 ph.Off = seg.Fileoff 1115 ph.Filesz = seg.Filelen 1116 ph.Align = uint64(*FlagRound) 1117 1118 return ph 1119} 1120 1121func elfphrelro(seg *sym.Segment) { 1122 ph := newElfPhdr() 1123 ph.Type = elf.PT_GNU_RELRO 1124 ph.Flags = elf.PF_R 1125 ph.Vaddr = seg.Vaddr 1126 ph.Paddr = seg.Vaddr 1127 ph.Memsz = seg.Length 1128 ph.Off = seg.Fileoff 1129 ph.Filesz = seg.Filelen 1130 ph.Align = uint64(*FlagRound) 1131} 1132 1133func elfshname(name string) *ElfShdr { 1134 for i := 0; i < nelfstr; i++ { 1135 if name != elfstr[i].s { 1136 continue 1137 } 1138 off := elfstr[i].off 1139 for i = 0; i < int(ehdr.Shnum); i++ { 1140 sh := shdr[i] 1141 if sh.Name == uint32(off) { 1142 return sh 1143 } 1144 } 1145 return newElfShdr(int64(off)) 1146 } 1147 Exitf("cannot find elf name %s", name) 1148 return nil 1149} 1150 1151// Create an ElfShdr for the section with name. 1152// Create a duplicate if one already exists with that name. 1153func elfshnamedup(name string) *ElfShdr { 1154 for i := 0; i < nelfstr; i++ { 1155 if name == elfstr[i].s { 1156 off := elfstr[i].off 1157 return newElfShdr(int64(off)) 1158 } 1159 } 1160 1161 Errorf(nil, "cannot find elf name %s", name) 1162 errorexit() 1163 return nil 1164} 1165 1166func elfshalloc(sect *sym.Section) *ElfShdr { 1167 sh := elfshname(sect.Name) 1168 sect.Elfsect = sh 1169 return sh 1170} 1171 1172func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr { 1173 var sh *ElfShdr 1174 1175 if sect.Name == ".text" { 1176 if sect.Elfsect == nil { 1177 sect.Elfsect = elfshnamedup(sect.Name) 1178 } 1179 sh = sect.Elfsect.(*ElfShdr) 1180 } else { 1181 sh = elfshalloc(sect) 1182 } 1183 1184 // If this section has already been set up as a note, we assume type_ and 1185 // flags are already correct, but the other fields still need filling in. 1186 if sh.Type == uint32(elf.SHT_NOTE) { 1187 if linkmode != LinkExternal { 1188 // TODO(mwhudson): the approach here will work OK when 1189 // linking internally for notes that we want to be included 1190 // in a loadable segment (e.g. the abihash note) but not for 1191 // notes that we do not want to be mapped (e.g. the package 1192 // list note). The real fix is probably to define new values 1193 // for Symbol.Type corresponding to mapped and unmapped notes 1194 // and handle them in dodata(). 1195 Errorf(nil, "sh.Type == SHT_NOTE in elfshbits when linking internally") 1196 } 1197 sh.Addralign = uint64(sect.Align) 1198 sh.Size = sect.Length 1199 sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr 1200 return sh 1201 } 1202 if sh.Type > 0 { 1203 return sh 1204 } 1205 1206 if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen { 1207 switch sect.Name { 1208 case ".init_array": 1209 sh.Type = uint32(elf.SHT_INIT_ARRAY) 1210 default: 1211 sh.Type = uint32(elf.SHT_PROGBITS) 1212 } 1213 } else { 1214 sh.Type = uint32(elf.SHT_NOBITS) 1215 } 1216 sh.Flags = uint64(elf.SHF_ALLOC) 1217 if sect.Rwx&1 != 0 { 1218 sh.Flags |= uint64(elf.SHF_EXECINSTR) 1219 } 1220 if sect.Rwx&2 != 0 { 1221 sh.Flags |= uint64(elf.SHF_WRITE) 1222 } 1223 if sect.Name == ".tbss" { 1224 sh.Flags |= uint64(elf.SHF_TLS) 1225 sh.Type = uint32(elf.SHT_NOBITS) 1226 } 1227 if linkmode != LinkExternal { 1228 sh.Addr = sect.Vaddr 1229 } 1230 1231 if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") { 1232 sh.Flags = 0 1233 sh.Addr = 0 1234 if sect.Compressed { 1235 sh.Flags |= uint64(elf.SHF_COMPRESSED) 1236 } 1237 } 1238 1239 sh.Addralign = uint64(sect.Align) 1240 sh.Size = sect.Length 1241 if sect.Name != ".tbss" { 1242 sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr 1243 } 1244 1245 return sh 1246} 1247 1248func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr { 1249 // If main section is SHT_NOBITS, nothing to relocate. 1250 // Also nothing to relocate in .shstrtab or notes. 1251 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { 1252 return nil 1253 } 1254 if sect.Name == ".shstrtab" || sect.Name == ".tbss" { 1255 return nil 1256 } 1257 if sect.Elfsect.(*ElfShdr).Type == uint32(elf.SHT_NOTE) { 1258 return nil 1259 } 1260 1261 typ := elf.SHT_REL 1262 if elfRelType == ".rela" { 1263 typ = elf.SHT_RELA 1264 } 1265 1266 sh := elfshname(elfRelType + sect.Name) 1267 // There could be multiple text sections but each needs 1268 // its own .rela.text. 1269 1270 if sect.Name == ".text" { 1271 if sh.Info != 0 && sh.Info != uint32(sect.Elfsect.(*ElfShdr).shnum) { 1272 sh = elfshnamedup(elfRelType + sect.Name) 1273 } 1274 } 1275 1276 sh.Type = uint32(typ) 1277 sh.Entsize = uint64(arch.RegSize) * 2 1278 if typ == elf.SHT_RELA { 1279 sh.Entsize += uint64(arch.RegSize) 1280 } 1281 sh.Link = uint32(elfshname(".symtab").shnum) 1282 sh.Info = uint32(sect.Elfsect.(*ElfShdr).shnum) 1283 sh.Off = sect.Reloff 1284 sh.Size = sect.Rellen 1285 sh.Addralign = uint64(arch.RegSize) 1286 return sh 1287} 1288 1289func elfrelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) { 1290 // If main section is SHT_NOBITS, nothing to relocate. 1291 // Also nothing to relocate in .shstrtab. 1292 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { 1293 return 1294 } 1295 if sect.Name == ".shstrtab" { 1296 return 1297 } 1298 1299 ldr := ctxt.loader 1300 for i, s := range syms { 1301 if !ldr.AttrReachable(s) { 1302 panic("should never happen") 1303 } 1304 if uint64(ldr.SymValue(s)) >= sect.Vaddr { 1305 syms = syms[i:] 1306 break 1307 } 1308 } 1309 1310 eaddr := sect.Vaddr + sect.Length 1311 for _, s := range syms { 1312 if !ldr.AttrReachable(s) { 1313 continue 1314 } 1315 if ldr.SymValue(s) >= int64(eaddr) { 1316 break 1317 } 1318 1319 // Compute external relocations on the go, and pass to 1320 // ELF.Reloc1 to stream out. 1321 relocs := ldr.Relocs(s) 1322 for ri := 0; ri < relocs.Count(); ri++ { 1323 r := relocs.At(ri) 1324 rr, ok := extreloc(ctxt, ldr, s, r) 1325 if !ok { 1326 continue 1327 } 1328 if rr.Xsym == 0 { 1329 ldr.Errorf(s, "missing xsym in relocation") 1330 continue 1331 } 1332 esr := ElfSymForReloc(ctxt, rr.Xsym) 1333 if esr == 0 { 1334 ldr.Errorf(s, "reloc %d (%s) to non-elf symbol %s (outer=%s) %d (%s)", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(r.Sym()), ldr.SymName(rr.Xsym), ldr.SymType(r.Sym()), ldr.SymType(r.Sym()).String()) 1335 } 1336 if !ldr.AttrReachable(rr.Xsym) { 1337 ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(rr.Xsym)) 1338 } 1339 if !thearch.ELF.Reloc1(ctxt, out, ldr, s, rr, ri, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) { 1340 ldr.Errorf(s, "unsupported obj reloc %d (%s)/%d to %s", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), r.Siz(), ldr.SymName(r.Sym())) 1341 } 1342 } 1343 } 1344 1345 // sanity check 1346 if uint64(out.Offset()) != sect.Reloff+sect.Rellen { 1347 panic(fmt.Sprintf("elfrelocsect: size mismatch %d != %d + %d", out.Offset(), sect.Reloff, sect.Rellen)) 1348 } 1349} 1350 1351func elfEmitReloc(ctxt *Link) { 1352 for ctxt.Out.Offset()&7 != 0 { 1353 ctxt.Out.Write8(0) 1354 } 1355 1356 sizeExtRelocs(ctxt, thearch.ELF.RelocSize) 1357 relocSect, wg := relocSectFn(ctxt, elfrelocsect) 1358 1359 for _, sect := range Segtext.Sections { 1360 if sect.Name == ".text" { 1361 relocSect(ctxt, sect, ctxt.Textp) 1362 } else { 1363 relocSect(ctxt, sect, ctxt.datap) 1364 } 1365 } 1366 1367 for _, sect := range Segrodata.Sections { 1368 relocSect(ctxt, sect, ctxt.datap) 1369 } 1370 for _, sect := range Segrelrodata.Sections { 1371 relocSect(ctxt, sect, ctxt.datap) 1372 } 1373 for _, sect := range Segdata.Sections { 1374 relocSect(ctxt, sect, ctxt.datap) 1375 } 1376 for i := 0; i < len(Segdwarf.Sections); i++ { 1377 sect := Segdwarf.Sections[i] 1378 si := dwarfp[i] 1379 if si.secSym() != loader.Sym(sect.Sym) || 1380 ctxt.loader.SymSect(si.secSym()) != sect { 1381 panic("inconsistency between dwarfp and Segdwarf") 1382 } 1383 relocSect(ctxt, sect, si.syms) 1384 } 1385 wg.Wait() 1386} 1387 1388func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) { 1389 ldr := ctxt.loader 1390 s := ldr.CreateSymForUpdate(sectionName, 0) 1391 s.SetType(sym.SELFROSECT) 1392 // namesz 1393 s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME))) 1394 // descsz 1395 s.AddUint32(ctxt.Arch, uint32(len(desc))) 1396 // tag 1397 s.AddUint32(ctxt.Arch, tag) 1398 // name + padding 1399 s.AddBytes(ELF_NOTE_GO_NAME) 1400 for len(s.Data())%4 != 0 { 1401 s.AddUint8(0) 1402 } 1403 // desc + padding 1404 s.AddBytes(desc) 1405 for len(s.Data())%4 != 0 { 1406 s.AddUint8(0) 1407 } 1408 s.SetSize(int64(len(s.Data()))) 1409 s.SetAlign(4) 1410} 1411 1412func (ctxt *Link) doelf() { 1413 ldr := ctxt.loader 1414 1415 /* predefine strings we need for section headers */ 1416 1417 addshstr := func(s string) int { 1418 off := len(elfshstrdat) 1419 elfshstrdat = append(elfshstrdat, s...) 1420 elfshstrdat = append(elfshstrdat, 0) 1421 return off 1422 } 1423 1424 shstrtabAddstring := func(s string) { 1425 off := addshstr(s) 1426 elfsetstring(ctxt, 0, s, int(off)) 1427 } 1428 1429 shstrtabAddstring("") 1430 shstrtabAddstring(".text") 1431 shstrtabAddstring(".noptrdata") 1432 shstrtabAddstring(".data") 1433 shstrtabAddstring(".bss") 1434 shstrtabAddstring(".noptrbss") 1435 shstrtabAddstring(".go.fuzzcntrs") 1436 shstrtabAddstring(".go.buildinfo") 1437 if ctxt.IsMIPS() { 1438 shstrtabAddstring(".MIPS.abiflags") 1439 shstrtabAddstring(".gnu.attributes") 1440 } 1441 1442 // generate .tbss section for dynamic internal linker or external 1443 // linking, so that various binutils could correctly calculate 1444 // PT_TLS size. See https://golang.org/issue/5200. 1445 if !*FlagD || ctxt.IsExternal() { 1446 shstrtabAddstring(".tbss") 1447 } 1448 if ctxt.IsNetbsd() { 1449 shstrtabAddstring(".note.netbsd.ident") 1450 if *flagRace { 1451 shstrtabAddstring(".note.netbsd.pax") 1452 } 1453 } 1454 if ctxt.IsOpenbsd() { 1455 shstrtabAddstring(".note.openbsd.ident") 1456 } 1457 if ctxt.IsFreebsd() { 1458 shstrtabAddstring(".note.tag") 1459 } 1460 if len(buildinfo) > 0 { 1461 shstrtabAddstring(".note.gnu.build-id") 1462 } 1463 if *flagBuildid != "" { 1464 shstrtabAddstring(".note.go.buildid") 1465 } 1466 shstrtabAddstring(".elfdata") 1467 shstrtabAddstring(".rodata") 1468 // See the comment about data.rel.ro.FOO section names in data.go. 1469 relro_prefix := "" 1470 if ctxt.UseRelro() { 1471 shstrtabAddstring(".data.rel.ro") 1472 relro_prefix = ".data.rel.ro" 1473 } 1474 shstrtabAddstring(relro_prefix + ".typelink") 1475 shstrtabAddstring(relro_prefix + ".itablink") 1476 shstrtabAddstring(relro_prefix + ".gosymtab") 1477 shstrtabAddstring(relro_prefix + ".gopclntab") 1478 1479 if ctxt.IsExternal() { 1480 *FlagD = true 1481 1482 shstrtabAddstring(elfRelType + ".text") 1483 shstrtabAddstring(elfRelType + ".rodata") 1484 shstrtabAddstring(elfRelType + relro_prefix + ".typelink") 1485 shstrtabAddstring(elfRelType + relro_prefix + ".itablink") 1486 shstrtabAddstring(elfRelType + relro_prefix + ".gosymtab") 1487 shstrtabAddstring(elfRelType + relro_prefix + ".gopclntab") 1488 shstrtabAddstring(elfRelType + ".noptrdata") 1489 shstrtabAddstring(elfRelType + ".data") 1490 if ctxt.UseRelro() { 1491 shstrtabAddstring(elfRelType + ".data.rel.ro") 1492 } 1493 shstrtabAddstring(elfRelType + ".go.buildinfo") 1494 if ctxt.IsMIPS() { 1495 shstrtabAddstring(elfRelType + ".MIPS.abiflags") 1496 shstrtabAddstring(elfRelType + ".gnu.attributes") 1497 } 1498 1499 // add a .note.GNU-stack section to mark the stack as non-executable 1500 shstrtabAddstring(".note.GNU-stack") 1501 1502 if ctxt.IsShared() { 1503 shstrtabAddstring(".note.go.abihash") 1504 shstrtabAddstring(".note.go.pkg-list") 1505 shstrtabAddstring(".note.go.deps") 1506 } 1507 } 1508 1509 hasinitarr := ctxt.linkShared 1510 1511 /* shared library initializer */ 1512 switch ctxt.BuildMode { 1513 case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin: 1514 hasinitarr = true 1515 } 1516 1517 if hasinitarr { 1518 shstrtabAddstring(".init_array") 1519 shstrtabAddstring(elfRelType + ".init_array") 1520 } 1521 1522 if !*FlagS { 1523 shstrtabAddstring(".symtab") 1524 shstrtabAddstring(".strtab") 1525 } 1526 if !*FlagW { 1527 dwarfaddshstrings(ctxt, shstrtabAddstring) 1528 } 1529 1530 shstrtabAddstring(".shstrtab") 1531 1532 if !*FlagD { /* -d suppresses dynamic loader format */ 1533 shstrtabAddstring(".interp") 1534 shstrtabAddstring(".hash") 1535 shstrtabAddstring(".got") 1536 if ctxt.IsPPC64() { 1537 shstrtabAddstring(".glink") 1538 } 1539 shstrtabAddstring(".got.plt") 1540 shstrtabAddstring(".dynamic") 1541 shstrtabAddstring(".dynsym") 1542 shstrtabAddstring(".dynstr") 1543 shstrtabAddstring(elfRelType) 1544 shstrtabAddstring(elfRelType + ".plt") 1545 1546 shstrtabAddstring(".plt") 1547 shstrtabAddstring(".gnu.version") 1548 shstrtabAddstring(".gnu.version_r") 1549 1550 /* dynamic symbol table - first entry all zeros */ 1551 dynsym := ldr.CreateSymForUpdate(".dynsym", 0) 1552 1553 dynsym.SetType(sym.SELFROSECT) 1554 if elf64 { 1555 dynsym.SetSize(dynsym.Size() + ELF64SYMSIZE) 1556 } else { 1557 dynsym.SetSize(dynsym.Size() + ELF32SYMSIZE) 1558 } 1559 1560 /* dynamic string table */ 1561 dynstr := ldr.CreateSymForUpdate(".dynstr", 0) 1562 1563 dynstr.SetType(sym.SELFROSECT) 1564 if dynstr.Size() == 0 { 1565 dynstr.Addstring("") 1566 } 1567 1568 /* relocation table */ 1569 s := ldr.CreateSymForUpdate(elfRelType, 0) 1570 s.SetType(sym.SELFROSECT) 1571 1572 /* global offset table */ 1573 got := ldr.CreateSymForUpdate(".got", 0) 1574 if ctxt.UseRelro() { 1575 got.SetType(sym.SELFRELROSECT) 1576 } else { 1577 got.SetType(sym.SELFGOT) // writable 1578 } 1579 1580 /* ppc64 glink resolver */ 1581 if ctxt.IsPPC64() { 1582 s := ldr.CreateSymForUpdate(".glink", 0) 1583 s.SetType(sym.SELFRXSECT) 1584 } 1585 1586 /* hash */ 1587 hash := ldr.CreateSymForUpdate(".hash", 0) 1588 hash.SetType(sym.SELFROSECT) 1589 1590 gotplt := ldr.CreateSymForUpdate(".got.plt", 0) 1591 if ctxt.UseRelro() && *flagBindNow { 1592 gotplt.SetType(sym.SELFRELROSECT) 1593 } else { 1594 gotplt.SetType(sym.SELFSECT) // writable 1595 } 1596 1597 plt := ldr.CreateSymForUpdate(".plt", 0) 1598 if ctxt.IsPPC64() { 1599 // In the ppc64 ABI, .plt is a data section 1600 // written by the dynamic linker. 1601 plt.SetType(sym.SELFSECT) 1602 } else { 1603 plt.SetType(sym.SELFRXSECT) 1604 } 1605 1606 s = ldr.CreateSymForUpdate(elfRelType+".plt", 0) 1607 s.SetType(sym.SELFROSECT) 1608 1609 s = ldr.CreateSymForUpdate(".gnu.version", 0) 1610 s.SetType(sym.SELFROSECT) 1611 1612 s = ldr.CreateSymForUpdate(".gnu.version_r", 0) 1613 s.SetType(sym.SELFROSECT) 1614 1615 /* define dynamic elf table */ 1616 dynamic := ldr.CreateSymForUpdate(".dynamic", 0) 1617 switch { 1618 case thearch.ELF.DynamicReadOnly: 1619 dynamic.SetType(sym.SELFROSECT) 1620 case ctxt.UseRelro(): 1621 dynamic.SetType(sym.SELFRELROSECT) 1622 default: 1623 dynamic.SetType(sym.SELFSECT) 1624 } 1625 1626 if ctxt.IsS390X() { 1627 // S390X uses .got instead of .got.plt 1628 gotplt = got 1629 } 1630 thearch.ELF.SetupPLT(ctxt, ctxt.loader, plt, gotplt, dynamic.Sym()) 1631 1632 /* 1633 * .dynamic table 1634 */ 1635 elfWriteDynEntSym(ctxt, dynamic, elf.DT_HASH, hash.Sym()) 1636 1637 elfWriteDynEntSym(ctxt, dynamic, elf.DT_SYMTAB, dynsym.Sym()) 1638 if elf64 { 1639 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF64SYMSIZE) 1640 } else { 1641 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF32SYMSIZE) 1642 } 1643 elfWriteDynEntSym(ctxt, dynamic, elf.DT_STRTAB, dynstr.Sym()) 1644 elfwritedynentsymsize(ctxt, dynamic, elf.DT_STRSZ, dynstr.Sym()) 1645 if elfRelType == ".rela" { 1646 rela := ldr.LookupOrCreateSym(".rela", 0) 1647 elfWriteDynEntSym(ctxt, dynamic, elf.DT_RELA, rela) 1648 elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELASZ, rela) 1649 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELAENT, ELF64RELASIZE) 1650 } else { 1651 rel := ldr.LookupOrCreateSym(".rel", 0) 1652 elfWriteDynEntSym(ctxt, dynamic, elf.DT_REL, rel) 1653 elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELSZ, rel) 1654 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELENT, ELF32RELSIZE) 1655 } 1656 1657 if rpath.val != "" { 1658 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RUNPATH, uint64(dynstr.Addstring(rpath.val))) 1659 } 1660 1661 if ctxt.IsPPC64() { 1662 elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, plt.Sym()) 1663 } else { 1664 elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, gotplt.Sym()) 1665 } 1666 1667 if ctxt.IsPPC64() { 1668 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_PPC64_OPT, 0) 1669 } 1670 1671 // Solaris dynamic linker can't handle an empty .rela.plt if 1672 // DT_JMPREL is emitted so we have to defer generation of elf.DT_PLTREL, 1673 // DT_PLTRELSZ, and elf.DT_JMPREL dynamic entries until after we know the 1674 // size of .rel(a).plt section. 1675 1676 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_DEBUG, 0) 1677 } 1678 1679 if ctxt.IsShared() { 1680 // The go.link.abihashbytes symbol will be pointed at the appropriate 1681 // part of the .note.go.abihash section in data.go:func address(). 1682 s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0) 1683 sb := ldr.MakeSymbolUpdater(s) 1684 ldr.SetAttrLocal(s, true) 1685 sb.SetType(sym.SRODATA) 1686 ldr.SetAttrSpecial(s, true) 1687 sb.SetReachable(true) 1688 sb.SetSize(notsha256.Size) 1689 1690 sort.Sort(byPkg(ctxt.Library)) 1691 h := notsha256.New() 1692 for _, l := range ctxt.Library { 1693 h.Write(l.Fingerprint[:]) 1694 } 1695 addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{})) 1696 addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote) 1697 var deplist []string 1698 for _, shlib := range ctxt.Shlibs { 1699 deplist = append(deplist, filepath.Base(shlib.Path)) 1700 } 1701 addgonote(ctxt, ".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n"))) 1702 } 1703 1704 if ctxt.LinkMode == LinkExternal && *flagBuildid != "" { 1705 addgonote(ctxt, ".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(*flagBuildid)) 1706 } 1707 1708 //type mipsGnuAttributes struct { 1709 // version uint8 // 'A' 1710 // length uint32 // 15 including itself 1711 // gnu [4]byte // "gnu\0" 1712 // tag uint8 // 1:file, 2: section, 3: symbol, 1 here 1713 // taglen uint32 // tag length, including tag, 7 here 1714 // tagfp uint8 // 4 1715 // fpAbi uint8 // see .MIPS.abiflags 1716 //} 1717 if ctxt.IsMIPS() { 1718 gnuattributes := ldr.CreateSymForUpdate(".gnu.attributes", 0) 1719 gnuattributes.SetType(sym.SELFROSECT) 1720 gnuattributes.SetReachable(true) 1721 gnuattributes.AddUint8('A') // version 'A' 1722 gnuattributes.AddUint32(ctxt.Arch, 15) // length 15 including itself 1723 gnuattributes.AddBytes([]byte("gnu\x00")) // "gnu\0" 1724 gnuattributes.AddUint8(1) // 1:file, 2: section, 3: symbol, 1 here 1725 gnuattributes.AddUint32(ctxt.Arch, 7) // tag length, including tag, 7 here 1726 gnuattributes.AddUint8(4) // 4 for FP, 8 for MSA 1727 if buildcfg.GOMIPS == "softfloat" { 1728 gnuattributes.AddUint8(MIPS_FPABI_SOFT) 1729 } else { 1730 // Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage. 1731 // It is not for 'ANY'. 1732 // TODO: switch to FPXX after be sure that no odd-number-fpr is used. 1733 gnuattributes.AddUint8(MIPS_FPABI_ANY) 1734 } 1735 } 1736} 1737 1738// Do not write DT_NULL. elfdynhash will finish it. 1739func shsym(sh *ElfShdr, ldr *loader.Loader, s loader.Sym) { 1740 if s == 0 { 1741 panic("bad symbol in shsym2") 1742 } 1743 addr := ldr.SymValue(s) 1744 if sh.Flags&uint64(elf.SHF_ALLOC) != 0 { 1745 sh.Addr = uint64(addr) 1746 } 1747 sh.Off = uint64(datoff(ldr, s, addr)) 1748 sh.Size = uint64(ldr.SymSize(s)) 1749} 1750 1751func phsh(ph *ElfPhdr, sh *ElfShdr) { 1752 ph.Vaddr = sh.Addr 1753 ph.Paddr = ph.Vaddr 1754 ph.Off = sh.Off 1755 ph.Filesz = sh.Size 1756 ph.Memsz = sh.Size 1757 ph.Align = sh.Addralign 1758} 1759 1760func Asmbelfsetup() { 1761 /* This null SHdr must appear before all others */ 1762 elfshname("") 1763 1764 for _, sect := range Segtext.Sections { 1765 // There could be multiple .text sections. Instead check the Elfsect 1766 // field to determine if already has an ElfShdr and if not, create one. 1767 if sect.Name == ".text" { 1768 if sect.Elfsect == nil { 1769 sect.Elfsect = elfshnamedup(sect.Name) 1770 } 1771 } else { 1772 elfshalloc(sect) 1773 } 1774 } 1775 for _, sect := range Segrodata.Sections { 1776 elfshalloc(sect) 1777 } 1778 for _, sect := range Segrelrodata.Sections { 1779 elfshalloc(sect) 1780 } 1781 for _, sect := range Segdata.Sections { 1782 elfshalloc(sect) 1783 } 1784 for _, sect := range Segdwarf.Sections { 1785 elfshalloc(sect) 1786 } 1787} 1788 1789func asmbElf(ctxt *Link) { 1790 var symo int64 1791 symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen) 1792 symo = Rnd(symo, int64(ctxt.Arch.PtrSize)) 1793 ctxt.Out.SeekSet(symo) 1794 if *FlagS { 1795 ctxt.Out.Write(elfshstrdat) 1796 } else { 1797 ctxt.Out.SeekSet(symo) 1798 asmElfSym(ctxt) 1799 ctxt.Out.Write(elfstrdat) 1800 ctxt.Out.Write(elfshstrdat) 1801 if ctxt.IsExternal() { 1802 elfEmitReloc(ctxt) 1803 } 1804 } 1805 ctxt.Out.SeekSet(0) 1806 1807 ldr := ctxt.loader 1808 eh := getElfEhdr() 1809 switch ctxt.Arch.Family { 1810 default: 1811 Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family) 1812 case sys.MIPS, sys.MIPS64: 1813 eh.Machine = uint16(elf.EM_MIPS) 1814 case sys.Loong64: 1815 eh.Machine = uint16(elf.EM_LOONGARCH) 1816 case sys.ARM: 1817 eh.Machine = uint16(elf.EM_ARM) 1818 case sys.AMD64: 1819 eh.Machine = uint16(elf.EM_X86_64) 1820 case sys.ARM64: 1821 eh.Machine = uint16(elf.EM_AARCH64) 1822 case sys.I386: 1823 eh.Machine = uint16(elf.EM_386) 1824 case sys.PPC64: 1825 eh.Machine = uint16(elf.EM_PPC64) 1826 case sys.RISCV64: 1827 eh.Machine = uint16(elf.EM_RISCV) 1828 case sys.S390X: 1829 eh.Machine = uint16(elf.EM_S390) 1830 } 1831 1832 elfreserve := int64(ELFRESERVE) 1833 1834 numtext := int64(0) 1835 for _, sect := range Segtext.Sections { 1836 if sect.Name == ".text" { 1837 numtext++ 1838 } 1839 } 1840 1841 // If there are multiple text sections, extra space is needed 1842 // in the elfreserve for the additional .text and .rela.text 1843 // section headers. It can handle 4 extra now. Headers are 1844 // 64 bytes. 1845 1846 if numtext > 4 { 1847 elfreserve += elfreserve + numtext*64*2 1848 } 1849 1850 startva := *FlagTextAddr - int64(HEADR) 1851 resoff := elfreserve 1852 1853 var pph *ElfPhdr 1854 var pnote *ElfPhdr 1855 getpnote := func() *ElfPhdr { 1856 if pnote == nil { 1857 pnote = newElfPhdr() 1858 pnote.Type = elf.PT_NOTE 1859 pnote.Flags = elf.PF_R 1860 } 1861 return pnote 1862 } 1863 if *flagRace && ctxt.IsNetbsd() { 1864 sh := elfshname(".note.netbsd.pax") 1865 resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff))) 1866 phsh(getpnote(), sh) 1867 } 1868 if ctxt.LinkMode == LinkExternal { 1869 /* skip program headers */ 1870 eh.Phoff = 0 1871 1872 eh.Phentsize = 0 1873 1874 if ctxt.BuildMode == BuildModeShared { 1875 sh := elfshname(".note.go.pkg-list") 1876 sh.Type = uint32(elf.SHT_NOTE) 1877 sh = elfshname(".note.go.abihash") 1878 sh.Type = uint32(elf.SHT_NOTE) 1879 sh.Flags = uint64(elf.SHF_ALLOC) 1880 sh = elfshname(".note.go.deps") 1881 sh.Type = uint32(elf.SHT_NOTE) 1882 } 1883 1884 if *flagBuildid != "" { 1885 sh := elfshname(".note.go.buildid") 1886 sh.Type = uint32(elf.SHT_NOTE) 1887 sh.Flags = uint64(elf.SHF_ALLOC) 1888 } 1889 1890 goto elfobj 1891 } 1892 1893 /* program header info */ 1894 pph = newElfPhdr() 1895 1896 pph.Type = elf.PT_PHDR 1897 pph.Flags = elf.PF_R 1898 pph.Off = uint64(eh.Ehsize) 1899 pph.Vaddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off 1900 pph.Paddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off 1901 pph.Align = uint64(*FlagRound) 1902 1903 /* 1904 * PHDR must be in a loaded segment. Adjust the text 1905 * segment boundaries downwards to include it. 1906 */ 1907 { 1908 o := int64(Segtext.Vaddr - pph.Vaddr) 1909 Segtext.Vaddr -= uint64(o) 1910 Segtext.Length += uint64(o) 1911 o = int64(Segtext.Fileoff - pph.Off) 1912 Segtext.Fileoff -= uint64(o) 1913 Segtext.Filelen += uint64(o) 1914 } 1915 1916 if !*FlagD { /* -d suppresses dynamic loader format */ 1917 /* interpreter */ 1918 sh := elfshname(".interp") 1919 1920 sh.Type = uint32(elf.SHT_PROGBITS) 1921 sh.Flags = uint64(elf.SHF_ALLOC) 1922 sh.Addralign = 1 1923 1924 if interpreter == "" && buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH && buildcfg.GO_LDSO != "" { 1925 interpreter = buildcfg.GO_LDSO 1926 } 1927 1928 if interpreter == "" { 1929 switch ctxt.HeadType { 1930 case objabi.Hlinux: 1931 if buildcfg.GOOS == "android" { 1932 interpreter = thearch.ELF.Androiddynld 1933 if interpreter == "" { 1934 Exitf("ELF interpreter not set") 1935 } 1936 } else { 1937 interpreter = thearch.ELF.Linuxdynld 1938 // If interpreter does not exist, try musl instead. 1939 // This lets the same cmd/link binary work on 1940 // both glibc-based and musl-based systems. 1941 if _, err := os.Stat(interpreter); err != nil { 1942 if musl := thearch.ELF.LinuxdynldMusl; musl != "" { 1943 if _, err := os.Stat(musl); err == nil { 1944 interpreter = musl 1945 } 1946 } 1947 } 1948 } 1949 1950 case objabi.Hfreebsd: 1951 interpreter = thearch.ELF.Freebsddynld 1952 1953 case objabi.Hnetbsd: 1954 interpreter = thearch.ELF.Netbsddynld 1955 1956 case objabi.Hopenbsd: 1957 interpreter = thearch.ELF.Openbsddynld 1958 1959 case objabi.Hdragonfly: 1960 interpreter = thearch.ELF.Dragonflydynld 1961 1962 case objabi.Hsolaris: 1963 interpreter = thearch.ELF.Solarisdynld 1964 } 1965 } 1966 1967 resoff -= int64(elfinterp(sh, uint64(startva), uint64(resoff), interpreter)) 1968 1969 ph := newElfPhdr() 1970 ph.Type = elf.PT_INTERP 1971 ph.Flags = elf.PF_R 1972 phsh(ph, sh) 1973 } 1974 1975 if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd || ctxt.HeadType == objabi.Hfreebsd { 1976 var sh *ElfShdr 1977 switch ctxt.HeadType { 1978 case objabi.Hnetbsd: 1979 sh = elfshname(".note.netbsd.ident") 1980 resoff -= int64(elfnetbsdsig(sh, uint64(startva), uint64(resoff))) 1981 1982 case objabi.Hopenbsd: 1983 sh = elfshname(".note.openbsd.ident") 1984 resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff))) 1985 1986 case objabi.Hfreebsd: 1987 sh = elfshname(".note.tag") 1988 resoff -= int64(elffreebsdsig(sh, uint64(startva), uint64(resoff))) 1989 } 1990 // NetBSD, OpenBSD and FreeBSD require ident in an independent segment. 1991 pnotei := newElfPhdr() 1992 pnotei.Type = elf.PT_NOTE 1993 pnotei.Flags = elf.PF_R 1994 phsh(pnotei, sh) 1995 } 1996 1997 if len(buildinfo) > 0 { 1998 sh := elfshname(".note.gnu.build-id") 1999 resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff))) 2000 phsh(getpnote(), sh) 2001 } 2002 2003 if *flagBuildid != "" { 2004 sh := elfshname(".note.go.buildid") 2005 resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff))) 2006 phsh(getpnote(), sh) 2007 } 2008 2009 // Additions to the reserved area must be above this line. 2010 2011 elfphload(&Segtext) 2012 if len(Segrodata.Sections) > 0 { 2013 elfphload(&Segrodata) 2014 } 2015 if len(Segrelrodata.Sections) > 0 { 2016 elfphload(&Segrelrodata) 2017 elfphrelro(&Segrelrodata) 2018 } 2019 elfphload(&Segdata) 2020 2021 /* Dynamic linking sections */ 2022 if !*FlagD { 2023 sh := elfshname(".dynsym") 2024 sh.Type = uint32(elf.SHT_DYNSYM) 2025 sh.Flags = uint64(elf.SHF_ALLOC) 2026 if elf64 { 2027 sh.Entsize = ELF64SYMSIZE 2028 } else { 2029 sh.Entsize = ELF32SYMSIZE 2030 } 2031 sh.Addralign = uint64(ctxt.Arch.RegSize) 2032 sh.Link = uint32(elfshname(".dynstr").shnum) 2033 2034 // sh.info is the index of first non-local symbol (number of local symbols) 2035 s := ldr.Lookup(".dynsym", 0) 2036 i := uint32(0) 2037 for sub := s; sub != 0; sub = ldr.SubSym(sub) { 2038 i++ 2039 if !ldr.AttrLocal(sub) { 2040 break 2041 } 2042 } 2043 sh.Info = i 2044 shsym(sh, ldr, s) 2045 2046 sh = elfshname(".dynstr") 2047 sh.Type = uint32(elf.SHT_STRTAB) 2048 sh.Flags = uint64(elf.SHF_ALLOC) 2049 sh.Addralign = 1 2050 shsym(sh, ldr, ldr.Lookup(".dynstr", 0)) 2051 2052 if elfverneed != 0 { 2053 sh := elfshname(".gnu.version") 2054 sh.Type = uint32(elf.SHT_GNU_VERSYM) 2055 sh.Flags = uint64(elf.SHF_ALLOC) 2056 sh.Addralign = 2 2057 sh.Link = uint32(elfshname(".dynsym").shnum) 2058 sh.Entsize = 2 2059 shsym(sh, ldr, ldr.Lookup(".gnu.version", 0)) 2060 2061 sh = elfshname(".gnu.version_r") 2062 sh.Type = uint32(elf.SHT_GNU_VERNEED) 2063 sh.Flags = uint64(elf.SHF_ALLOC) 2064 sh.Addralign = uint64(ctxt.Arch.RegSize) 2065 sh.Info = uint32(elfverneed) 2066 sh.Link = uint32(elfshname(".dynstr").shnum) 2067 shsym(sh, ldr, ldr.Lookup(".gnu.version_r", 0)) 2068 } 2069 2070 if elfRelType == ".rela" { 2071 sh := elfshname(".rela.plt") 2072 sh.Type = uint32(elf.SHT_RELA) 2073 sh.Flags = uint64(elf.SHF_ALLOC) 2074 sh.Entsize = ELF64RELASIZE 2075 sh.Addralign = uint64(ctxt.Arch.RegSize) 2076 sh.Link = uint32(elfshname(".dynsym").shnum) 2077 sh.Info = uint32(elfshname(".plt").shnum) 2078 shsym(sh, ldr, ldr.Lookup(".rela.plt", 0)) 2079 2080 sh = elfshname(".rela") 2081 sh.Type = uint32(elf.SHT_RELA) 2082 sh.Flags = uint64(elf.SHF_ALLOC) 2083 sh.Entsize = ELF64RELASIZE 2084 sh.Addralign = 8 2085 sh.Link = uint32(elfshname(".dynsym").shnum) 2086 shsym(sh, ldr, ldr.Lookup(".rela", 0)) 2087 } else { 2088 sh := elfshname(".rel.plt") 2089 sh.Type = uint32(elf.SHT_REL) 2090 sh.Flags = uint64(elf.SHF_ALLOC) 2091 sh.Entsize = ELF32RELSIZE 2092 sh.Addralign = 4 2093 sh.Link = uint32(elfshname(".dynsym").shnum) 2094 shsym(sh, ldr, ldr.Lookup(".rel.plt", 0)) 2095 2096 sh = elfshname(".rel") 2097 sh.Type = uint32(elf.SHT_REL) 2098 sh.Flags = uint64(elf.SHF_ALLOC) 2099 sh.Entsize = ELF32RELSIZE 2100 sh.Addralign = 4 2101 sh.Link = uint32(elfshname(".dynsym").shnum) 2102 shsym(sh, ldr, ldr.Lookup(".rel", 0)) 2103 } 2104 2105 if elf.Machine(eh.Machine) == elf.EM_PPC64 { 2106 sh := elfshname(".glink") 2107 sh.Type = uint32(elf.SHT_PROGBITS) 2108 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR) 2109 sh.Addralign = 4 2110 shsym(sh, ldr, ldr.Lookup(".glink", 0)) 2111 } 2112 2113 sh = elfshname(".plt") 2114 sh.Type = uint32(elf.SHT_PROGBITS) 2115 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR) 2116 if elf.Machine(eh.Machine) == elf.EM_X86_64 { 2117 sh.Entsize = 16 2118 } else if elf.Machine(eh.Machine) == elf.EM_S390 { 2119 sh.Entsize = 32 2120 } else if elf.Machine(eh.Machine) == elf.EM_PPC64 { 2121 // On ppc64, this is just a table of addresses 2122 // filled by the dynamic linker 2123 sh.Type = uint32(elf.SHT_NOBITS) 2124 2125 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE) 2126 sh.Entsize = 8 2127 } else { 2128 sh.Entsize = 4 2129 } 2130 sh.Addralign = sh.Entsize 2131 shsym(sh, ldr, ldr.Lookup(".plt", 0)) 2132 2133 // On ppc64, .got comes from the input files, so don't 2134 // create it here, and .got.plt is not used. 2135 if elf.Machine(eh.Machine) != elf.EM_PPC64 { 2136 sh := elfshname(".got") 2137 sh.Type = uint32(elf.SHT_PROGBITS) 2138 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE) 2139 sh.Entsize = uint64(ctxt.Arch.RegSize) 2140 sh.Addralign = uint64(ctxt.Arch.RegSize) 2141 shsym(sh, ldr, ldr.Lookup(".got", 0)) 2142 2143 sh = elfshname(".got.plt") 2144 sh.Type = uint32(elf.SHT_PROGBITS) 2145 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE) 2146 sh.Entsize = uint64(ctxt.Arch.RegSize) 2147 sh.Addralign = uint64(ctxt.Arch.RegSize) 2148 shsym(sh, ldr, ldr.Lookup(".got.plt", 0)) 2149 } 2150 2151 sh = elfshname(".hash") 2152 sh.Type = uint32(elf.SHT_HASH) 2153 sh.Flags = uint64(elf.SHF_ALLOC) 2154 sh.Entsize = 4 2155 sh.Addralign = uint64(ctxt.Arch.RegSize) 2156 sh.Link = uint32(elfshname(".dynsym").shnum) 2157 shsym(sh, ldr, ldr.Lookup(".hash", 0)) 2158 2159 /* sh and elf.PT_DYNAMIC for .dynamic section */ 2160 sh = elfshname(".dynamic") 2161 2162 sh.Type = uint32(elf.SHT_DYNAMIC) 2163 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE) 2164 sh.Entsize = 2 * uint64(ctxt.Arch.RegSize) 2165 sh.Addralign = uint64(ctxt.Arch.RegSize) 2166 sh.Link = uint32(elfshname(".dynstr").shnum) 2167 shsym(sh, ldr, ldr.Lookup(".dynamic", 0)) 2168 ph := newElfPhdr() 2169 ph.Type = elf.PT_DYNAMIC 2170 ph.Flags = elf.PF_R + elf.PF_W 2171 phsh(ph, sh) 2172 2173 /* 2174 * Thread-local storage segment (really just size). 2175 */ 2176 tlssize := uint64(0) 2177 for _, sect := range Segdata.Sections { 2178 if sect.Name == ".tbss" { 2179 tlssize = sect.Length 2180 } 2181 } 2182 if tlssize != 0 { 2183 ph := newElfPhdr() 2184 ph.Type = elf.PT_TLS 2185 ph.Flags = elf.PF_R 2186 ph.Memsz = tlssize 2187 ph.Align = uint64(ctxt.Arch.RegSize) 2188 } 2189 } 2190 2191 if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd { 2192 ph := newElfPhdr() 2193 ph.Type = elf.PT_GNU_STACK 2194 ph.Flags = elf.PF_W + elf.PF_R 2195 ph.Align = uint64(ctxt.Arch.RegSize) 2196 } else if ctxt.HeadType == objabi.Hopenbsd { 2197 ph := newElfPhdr() 2198 ph.Type = elf.PT_OPENBSD_NOBTCFI 2199 ph.Flags = elf.PF_X 2200 } else if ctxt.HeadType == objabi.Hsolaris { 2201 ph := newElfPhdr() 2202 ph.Type = elf.PT_SUNWSTACK 2203 ph.Flags = elf.PF_W + elf.PF_R 2204 } 2205 2206elfobj: 2207 sh := elfshname(".shstrtab") 2208 eh.Shstrndx = uint16(sh.shnum) 2209 2210 if ctxt.IsMIPS() { 2211 sh = elfshname(".MIPS.abiflags") 2212 sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS) 2213 sh.Flags = uint64(elf.SHF_ALLOC) 2214 sh.Addralign = 8 2215 resoff -= int64(elfMipsAbiFlags(sh, uint64(startva), uint64(resoff))) 2216 2217 ph := newElfPhdr() 2218 ph.Type = elf.PT_MIPS_ABIFLAGS 2219 ph.Flags = elf.PF_R 2220 phsh(ph, sh) 2221 2222 sh = elfshname(".gnu.attributes") 2223 sh.Type = uint32(elf.SHT_GNU_ATTRIBUTES) 2224 sh.Addralign = 1 2225 ldr := ctxt.loader 2226 shsym(sh, ldr, ldr.Lookup(".gnu.attributes", 0)) 2227 } 2228 2229 // put these sections early in the list 2230 if !*FlagS { 2231 elfshname(".symtab") 2232 elfshname(".strtab") 2233 } 2234 elfshname(".shstrtab") 2235 2236 for _, sect := range Segtext.Sections { 2237 elfshbits(ctxt.LinkMode, sect) 2238 } 2239 for _, sect := range Segrodata.Sections { 2240 elfshbits(ctxt.LinkMode, sect) 2241 } 2242 for _, sect := range Segrelrodata.Sections { 2243 elfshbits(ctxt.LinkMode, sect) 2244 } 2245 for _, sect := range Segdata.Sections { 2246 elfshbits(ctxt.LinkMode, sect) 2247 } 2248 for _, sect := range Segdwarf.Sections { 2249 elfshbits(ctxt.LinkMode, sect) 2250 } 2251 2252 if ctxt.LinkMode == LinkExternal { 2253 for _, sect := range Segtext.Sections { 2254 elfshreloc(ctxt.Arch, sect) 2255 } 2256 for _, sect := range Segrodata.Sections { 2257 elfshreloc(ctxt.Arch, sect) 2258 } 2259 for _, sect := range Segrelrodata.Sections { 2260 elfshreloc(ctxt.Arch, sect) 2261 } 2262 for _, sect := range Segdata.Sections { 2263 elfshreloc(ctxt.Arch, sect) 2264 } 2265 for _, si := range dwarfp { 2266 sect := ldr.SymSect(si.secSym()) 2267 elfshreloc(ctxt.Arch, sect) 2268 } 2269 // add a .note.GNU-stack section to mark the stack as non-executable 2270 sh := elfshname(".note.GNU-stack") 2271 2272 sh.Type = uint32(elf.SHT_PROGBITS) 2273 sh.Addralign = 1 2274 sh.Flags = 0 2275 } 2276 2277 var shstroff uint64 2278 if !*FlagS { 2279 sh := elfshname(".symtab") 2280 sh.Type = uint32(elf.SHT_SYMTAB) 2281 sh.Off = uint64(symo) 2282 sh.Size = uint64(symSize) 2283 sh.Addralign = uint64(ctxt.Arch.RegSize) 2284 sh.Entsize = 8 + 2*uint64(ctxt.Arch.RegSize) 2285 sh.Link = uint32(elfshname(".strtab").shnum) 2286 sh.Info = uint32(elfglobalsymndx) 2287 2288 sh = elfshname(".strtab") 2289 sh.Type = uint32(elf.SHT_STRTAB) 2290 sh.Off = uint64(symo) + uint64(symSize) 2291 sh.Size = uint64(len(elfstrdat)) 2292 sh.Addralign = 1 2293 shstroff = sh.Off + sh.Size 2294 } else { 2295 shstroff = uint64(symo) 2296 } 2297 2298 sh = elfshname(".shstrtab") 2299 sh.Type = uint32(elf.SHT_STRTAB) 2300 sh.Off = shstroff 2301 sh.Size = uint64(len(elfshstrdat)) 2302 sh.Addralign = 1 2303 2304 /* Main header */ 2305 copy(eh.Ident[:], elf.ELFMAG) 2306 2307 var osabi elf.OSABI 2308 switch ctxt.HeadType { 2309 case objabi.Hfreebsd: 2310 osabi = elf.ELFOSABI_FREEBSD 2311 case objabi.Hnetbsd: 2312 osabi = elf.ELFOSABI_NETBSD 2313 case objabi.Hopenbsd: 2314 osabi = elf.ELFOSABI_OPENBSD 2315 case objabi.Hdragonfly: 2316 osabi = elf.ELFOSABI_NONE 2317 } 2318 eh.Ident[elf.EI_OSABI] = byte(osabi) 2319 2320 if elf64 { 2321 eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS64) 2322 } else { 2323 eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS32) 2324 } 2325 if ctxt.Arch.ByteOrder == binary.BigEndian { 2326 eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2MSB) 2327 } else { 2328 eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2LSB) 2329 } 2330 eh.Ident[elf.EI_VERSION] = byte(elf.EV_CURRENT) 2331 2332 if ctxt.LinkMode == LinkExternal { 2333 eh.Type = uint16(elf.ET_REL) 2334 } else if ctxt.BuildMode == BuildModePIE { 2335 eh.Type = uint16(elf.ET_DYN) 2336 } else { 2337 eh.Type = uint16(elf.ET_EXEC) 2338 } 2339 2340 if ctxt.LinkMode != LinkExternal { 2341 eh.Entry = uint64(Entryvalue(ctxt)) 2342 } 2343 2344 eh.Version = uint32(elf.EV_CURRENT) 2345 2346 if pph != nil { 2347 pph.Filesz = uint64(eh.Phnum) * uint64(eh.Phentsize) 2348 pph.Memsz = pph.Filesz 2349 } 2350 2351 ctxt.Out.SeekSet(0) 2352 a := int64(0) 2353 a += int64(elfwritehdr(ctxt.Out)) 2354 a += int64(elfwritephdrs(ctxt.Out)) 2355 a += int64(elfwriteshdrs(ctxt.Out)) 2356 if !*FlagD { 2357 a += int64(elfwriteinterp(ctxt.Out)) 2358 } 2359 if ctxt.IsMIPS() { 2360 a += int64(elfWriteMipsAbiFlags(ctxt)) 2361 } 2362 2363 if ctxt.LinkMode != LinkExternal { 2364 if ctxt.HeadType == objabi.Hnetbsd { 2365 a += int64(elfwritenetbsdsig(ctxt.Out)) 2366 } 2367 if ctxt.HeadType == objabi.Hopenbsd { 2368 a += int64(elfwriteopenbsdsig(ctxt.Out)) 2369 } 2370 if ctxt.HeadType == objabi.Hfreebsd { 2371 a += int64(elfwritefreebsdsig(ctxt.Out)) 2372 } 2373 if len(buildinfo) > 0 { 2374 a += int64(elfwritebuildinfo(ctxt.Out)) 2375 } 2376 if *flagBuildid != "" { 2377 a += int64(elfwritegobuildid(ctxt.Out)) 2378 } 2379 } 2380 if *flagRace && ctxt.IsNetbsd() { 2381 a += int64(elfwritenetbsdpax(ctxt.Out)) 2382 } 2383 2384 if a > elfreserve { 2385 Errorf(nil, "ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext) 2386 } 2387 2388 // Verify the amount of space allocated for the elf header is sufficient. The file offsets are 2389 // already computed in layout, so we could spill into another section. 2390 if a > int64(HEADR) { 2391 Errorf(nil, "HEADR too small: %d > %d with %d text sections", a, HEADR, numtext) 2392 } 2393} 2394 2395func elfadddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) { 2396 ldr.SetSymDynid(s, int32(Nelfsym)) 2397 Nelfsym++ 2398 d := ldr.MakeSymbolUpdater(syms.DynSym) 2399 name := ldr.SymExtname(s) 2400 dstru := ldr.MakeSymbolUpdater(syms.DynStr) 2401 st := ldr.SymType(s) 2402 cgoeStatic := ldr.AttrCgoExportStatic(s) 2403 cgoeDynamic := ldr.AttrCgoExportDynamic(s) 2404 cgoexp := (cgoeStatic || cgoeDynamic) 2405 2406 d.AddUint32(target.Arch, uint32(dstru.Addstring(name))) 2407 2408 if elf64 { 2409 2410 /* type */ 2411 var t uint8 2412 2413 if cgoexp && st == sym.STEXT { 2414 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC) 2415 } else { 2416 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT) 2417 } 2418 d.AddUint8(t) 2419 2420 /* reserved */ 2421 d.AddUint8(0) 2422 2423 /* section where symbol is defined */ 2424 if st == sym.SDYNIMPORT { 2425 d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF)) 2426 } else { 2427 d.AddUint16(target.Arch, 1) 2428 } 2429 2430 /* value */ 2431 if st == sym.SDYNIMPORT { 2432 d.AddUint64(target.Arch, 0) 2433 } else { 2434 d.AddAddrPlus(target.Arch, s, 0) 2435 } 2436 2437 /* size of object */ 2438 d.AddUint64(target.Arch, uint64(len(ldr.Data(s)))) 2439 2440 dil := ldr.SymDynimplib(s) 2441 2442 if !cgoeDynamic && dil != "" && !seenlib[dil] { 2443 du := ldr.MakeSymbolUpdater(syms.Dynamic) 2444 Elfwritedynent(target.Arch, du, elf.DT_NEEDED, uint64(dstru.Addstring(dil))) 2445 seenlib[dil] = true 2446 } 2447 } else { 2448 2449 /* value */ 2450 if st == sym.SDYNIMPORT { 2451 d.AddUint32(target.Arch, 0) 2452 } else { 2453 d.AddAddrPlus(target.Arch, s, 0) 2454 } 2455 2456 /* size of object */ 2457 d.AddUint32(target.Arch, uint32(len(ldr.Data(s)))) 2458 2459 /* type */ 2460 var t uint8 2461 2462 // TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386. 2463 if target.Arch.Family == sys.I386 && cgoexp && st == sym.STEXT { 2464 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC) 2465 } else if target.Arch.Family == sys.ARM && cgoeDynamic && st == sym.STEXT { 2466 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC) 2467 } else { 2468 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT) 2469 } 2470 d.AddUint8(t) 2471 d.AddUint8(0) 2472 2473 /* shndx */ 2474 if st == sym.SDYNIMPORT { 2475 d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF)) 2476 } else { 2477 d.AddUint16(target.Arch, 1) 2478 } 2479 } 2480} 2481