github.com/bir3/gocompiler@v0.9.2202/src/cmd/link/internal/ld/elf.go (about) 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 5 package ld 6 7 import ( 8 "github.com/bir3/gocompiler/src/cmd/internal/notsha256" 9 "github.com/bir3/gocompiler/src/cmd/internal/objabi" 10 "github.com/bir3/gocompiler/src/cmd/internal/sys" 11 "github.com/bir3/gocompiler/src/cmd/link/internal/loader" 12 "github.com/bir3/gocompiler/src/cmd/link/internal/sym" 13 "debug/elf" 14 "encoding/binary" 15 "encoding/hex" 16 "fmt" 17 "github.com/bir3/gocompiler/src/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 */ 76 type 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 */ 89 const ( 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 */ 106 type ElfEhdr elf.Header64 107 108 /* 109 * Section header. 110 */ 111 type ElfShdr struct { 112 elf.Section64 113 shnum elf.SectionIndex 114 } 115 116 /* 117 * Program header. 118 */ 119 type 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 */ 138 const ( 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 158 var 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 */ 166 const ( 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 */ 175 const ( 176 NSECT = 400 177 ) 178 179 var ( 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. 197 type 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 219 type Elfstring struct { 220 s string 221 off int 222 } 223 224 var elfstr [100]Elfstring 225 226 var nelfstr int 227 228 var buildinfo []byte 229 230 /* 231 Initialize the global variable that describes the ELF header. It will be updated as 232 we write section and prog headers. 233 */ 234 func 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. 304 func 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 314 func 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 329 func 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 344 func 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 357 func 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 370 func 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 384 func 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 395 func 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 409 func 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 425 func 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 439 func getElfEhdr() *ElfEhdr { 440 return &ehdr 441 } 442 443 func 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 461 func 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 479 func 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. */ 487 func 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 499 func elfWriteDynEntSym(ctxt *Link, s *loader.SymbolBuilder, tag elf.DynTag, t loader.Sym) { 500 Elfwritedynentsymplus(ctxt, s, tag, t, 0) 501 } 502 503 func 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 513 func 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 522 func 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 531 func 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 541 func 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 550 const ( 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 570 func 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; 607 func 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 635 func 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 653 func 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) 667 const ( 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 674 var ELF_NOTE_NETBSD_NAME = []byte("NetBSD\x00") 675 676 func 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 681 func 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 701 func 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 706 func 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 717 const ( 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 724 var ELF_NOTE_OPENBSD_NAME = []byte("OpenBSD\x00") 725 726 func 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 731 func 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) 748 const ( 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 758 const ELF_NOTE_FREEBSD_NAME = "FreeBSD\x00" 759 760 func 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. 772 func 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 808 func addbuildinfo(val string) { 809 if val == "gobuildid" { 810 buildID := *flagBuildid 811 if buildID == "" { 812 Exitf("-B gobuildid requires a Go build ID supplied via -buildid") 813 } 814 815 hashedBuildID := notsha256.Sum256([]byte(buildID)) 816 buildinfo = hashedBuildID[:20] 817 818 return 819 } 820 821 if !strings.HasPrefix(val, "0x") { 822 Exitf("-B argument must start with 0x: %s", val) 823 } 824 825 ov := val 826 val = val[2:] 827 828 const maxLen = 32 829 if hex.DecodedLen(len(val)) > maxLen { 830 Exitf("-B option too long (max %d digits): %s", maxLen, ov) 831 } 832 833 b, err := hex.DecodeString(val) 834 if err != nil { 835 if err == hex.ErrLength { 836 Exitf("-B argument must have even number of digits: %s", ov) 837 } 838 if inv, ok := err.(hex.InvalidByteError); ok { 839 Exitf("-B argument contains invalid hex digit %c: %s", byte(inv), ov) 840 } 841 Exitf("-B argument contains invalid hex: %s", ov) 842 } 843 844 buildinfo = b 845 } 846 847 // Build info note 848 const ( 849 ELF_NOTE_BUILDINFO_NAMESZ = 4 850 ELF_NOTE_BUILDINFO_TAG = 3 851 ) 852 853 var ELF_NOTE_BUILDINFO_NAME = []byte("GNU\x00") 854 855 func elfbuildinfo(sh *ElfShdr, startva uint64, resoff uint64) int { 856 n := int(ELF_NOTE_BUILDINFO_NAMESZ + Rnd(int64(len(buildinfo)), 4)) 857 return elfnote(sh, startva, resoff, n) 858 } 859 860 func elfgobuildid(sh *ElfShdr, startva uint64, resoff uint64) int { 861 n := len(ELF_NOTE_GO_NAME) + int(Rnd(int64(len(*flagBuildid)), 4)) 862 return elfnote(sh, startva, resoff, n) 863 } 864 865 func elfwritebuildinfo(out *OutBuf) int { 866 sh := elfwritenotehdr(out, ".note.gnu.build-id", ELF_NOTE_BUILDINFO_NAMESZ, uint32(len(buildinfo)), ELF_NOTE_BUILDINFO_TAG) 867 if sh == nil { 868 return 0 869 } 870 871 out.Write(ELF_NOTE_BUILDINFO_NAME) 872 out.Write(buildinfo) 873 var zero = make([]byte, 4) 874 out.Write(zero[:int(Rnd(int64(len(buildinfo)), 4)-int64(len(buildinfo)))]) 875 876 return int(sh.Size) 877 } 878 879 func elfwritegobuildid(out *OutBuf) int { 880 sh := elfwritenotehdr(out, ".note.go.buildid", uint32(len(ELF_NOTE_GO_NAME)), uint32(len(*flagBuildid)), ELF_NOTE_GOBUILDID_TAG) 881 if sh == nil { 882 return 0 883 } 884 885 out.Write(ELF_NOTE_GO_NAME) 886 out.Write([]byte(*flagBuildid)) 887 var zero = make([]byte, 4) 888 out.Write(zero[:int(Rnd(int64(len(*flagBuildid)), 4)-int64(len(*flagBuildid)))]) 889 890 return int(sh.Size) 891 } 892 893 // Go specific notes 894 const ( 895 ELF_NOTE_GOPKGLIST_TAG = 1 896 ELF_NOTE_GOABIHASH_TAG = 2 897 ELF_NOTE_GODEPS_TAG = 3 898 ELF_NOTE_GOBUILDID_TAG = 4 899 ) 900 901 var ELF_NOTE_GO_NAME = []byte("Go\x00\x00") 902 903 var elfverneed int 904 905 type Elfaux struct { 906 next *Elfaux 907 num int 908 vers string 909 } 910 911 type Elflib struct { 912 next *Elflib 913 aux *Elfaux 914 file string 915 } 916 917 func addelflib(list **Elflib, file string, vers string) *Elfaux { 918 var lib *Elflib 919 920 for lib = *list; lib != nil; lib = lib.next { 921 if lib.file == file { 922 goto havelib 923 } 924 } 925 lib = new(Elflib) 926 lib.next = *list 927 lib.file = file 928 *list = lib 929 930 havelib: 931 for aux := lib.aux; aux != nil; aux = aux.next { 932 if aux.vers == vers { 933 return aux 934 } 935 } 936 aux := new(Elfaux) 937 aux.next = lib.aux 938 aux.vers = vers 939 lib.aux = aux 940 941 return aux 942 } 943 944 func elfdynhash(ctxt *Link) { 945 if !ctxt.IsELF { 946 return 947 } 948 949 nsym := Nelfsym 950 ldr := ctxt.loader 951 s := ldr.CreateSymForUpdate(".hash", 0) 952 s.SetType(sym.SELFROSECT) 953 954 i := nsym 955 nbucket := 1 956 for i > 0 { 957 nbucket++ 958 i >>= 1 959 } 960 961 var needlib *Elflib 962 need := make([]*Elfaux, nsym) 963 chain := make([]uint32, nsym) 964 buckets := make([]uint32, nbucket) 965 966 for _, sy := range ldr.DynidSyms() { 967 968 dynid := ldr.SymDynid(sy) 969 if ldr.SymDynimpvers(sy) != "" { 970 need[dynid] = addelflib(&needlib, ldr.SymDynimplib(sy), ldr.SymDynimpvers(sy)) 971 } 972 973 name := ldr.SymExtname(sy) 974 hc := elfhash(name) 975 976 b := hc % uint32(nbucket) 977 chain[dynid] = buckets[b] 978 buckets[b] = uint32(dynid) 979 } 980 981 // s390x (ELF64) hash table entries are 8 bytes 982 if ctxt.Arch.Family == sys.S390X { 983 s.AddUint64(ctxt.Arch, uint64(nbucket)) 984 s.AddUint64(ctxt.Arch, uint64(nsym)) 985 for i := 0; i < nbucket; i++ { 986 s.AddUint64(ctxt.Arch, uint64(buckets[i])) 987 } 988 for i := 0; i < nsym; i++ { 989 s.AddUint64(ctxt.Arch, uint64(chain[i])) 990 } 991 } else { 992 s.AddUint32(ctxt.Arch, uint32(nbucket)) 993 s.AddUint32(ctxt.Arch, uint32(nsym)) 994 for i := 0; i < nbucket; i++ { 995 s.AddUint32(ctxt.Arch, buckets[i]) 996 } 997 for i := 0; i < nsym; i++ { 998 s.AddUint32(ctxt.Arch, chain[i]) 999 } 1000 } 1001 1002 dynstr := ldr.CreateSymForUpdate(".dynstr", 0) 1003 1004 // version symbols 1005 gnuVersionR := ldr.CreateSymForUpdate(".gnu.version_r", 0) 1006 s = gnuVersionR 1007 i = 2 1008 nfile := 0 1009 for l := needlib; l != nil; l = l.next { 1010 nfile++ 1011 1012 // header 1013 s.AddUint16(ctxt.Arch, 1) // table version 1014 j := 0 1015 for x := l.aux; x != nil; x = x.next { 1016 j++ 1017 } 1018 s.AddUint16(ctxt.Arch, uint16(j)) // aux count 1019 s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(l.file))) // file string offset 1020 s.AddUint32(ctxt.Arch, 16) // offset from header to first aux 1021 if l.next != nil { 1022 s.AddUint32(ctxt.Arch, 16+uint32(j)*16) // offset from this header to next 1023 } else { 1024 s.AddUint32(ctxt.Arch, 0) 1025 } 1026 1027 for x := l.aux; x != nil; x = x.next { 1028 x.num = i 1029 i++ 1030 1031 // aux struct 1032 s.AddUint32(ctxt.Arch, elfhash(x.vers)) // hash 1033 s.AddUint16(ctxt.Arch, 0) // flags 1034 s.AddUint16(ctxt.Arch, uint16(x.num)) // other - index we refer to this by 1035 s.AddUint32(ctxt.Arch, uint32(dynstr.Addstring(x.vers))) // version string offset 1036 if x.next != nil { 1037 s.AddUint32(ctxt.Arch, 16) // offset from this aux to next 1038 } else { 1039 s.AddUint32(ctxt.Arch, 0) 1040 } 1041 } 1042 } 1043 1044 // version references 1045 gnuVersion := ldr.CreateSymForUpdate(".gnu.version", 0) 1046 s = gnuVersion 1047 1048 for i := 0; i < nsym; i++ { 1049 if i == 0 { 1050 s.AddUint16(ctxt.Arch, 0) // first entry - no symbol 1051 } else if need[i] == nil { 1052 s.AddUint16(ctxt.Arch, 1) // global 1053 } else { 1054 s.AddUint16(ctxt.Arch, uint16(need[i].num)) 1055 } 1056 } 1057 1058 s = ldr.CreateSymForUpdate(".dynamic", 0) 1059 if ctxt.BuildMode == BuildModePIE { 1060 // https://github.com/bminor/glibc/blob/895ef79e04a953cac1493863bcae29ad85657ee1/elf/elf.h#L986 1061 const DTFLAGS_1_PIE = 0x08000000 1062 Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS_1, uint64(DTFLAGS_1_PIE)) 1063 } 1064 elfverneed = nfile 1065 if elfverneed != 0 { 1066 elfWriteDynEntSym(ctxt, s, elf.DT_VERNEED, gnuVersionR.Sym()) 1067 Elfwritedynent(ctxt.Arch, s, elf.DT_VERNEEDNUM, uint64(nfile)) 1068 elfWriteDynEntSym(ctxt, s, elf.DT_VERSYM, gnuVersion.Sym()) 1069 } 1070 1071 sy := ldr.CreateSymForUpdate(elfRelType+".plt", 0) 1072 if sy.Size() > 0 { 1073 if elfRelType == ".rela" { 1074 Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_RELA)) 1075 } else { 1076 Elfwritedynent(ctxt.Arch, s, elf.DT_PLTREL, uint64(elf.DT_REL)) 1077 } 1078 elfwritedynentsymsize(ctxt, s, elf.DT_PLTRELSZ, sy.Sym()) 1079 elfWriteDynEntSym(ctxt, s, elf.DT_JMPREL, sy.Sym()) 1080 } 1081 1082 Elfwritedynent(ctxt.Arch, s, elf.DT_NULL, 0) 1083 } 1084 1085 func elfphload(seg *sym.Segment) *ElfPhdr { 1086 ph := newElfPhdr() 1087 ph.Type = elf.PT_LOAD 1088 if seg.Rwx&4 != 0 { 1089 ph.Flags |= elf.PF_R 1090 } 1091 if seg.Rwx&2 != 0 { 1092 ph.Flags |= elf.PF_W 1093 } 1094 if seg.Rwx&1 != 0 { 1095 ph.Flags |= elf.PF_X 1096 } 1097 ph.Vaddr = seg.Vaddr 1098 ph.Paddr = seg.Vaddr 1099 ph.Memsz = seg.Length 1100 ph.Off = seg.Fileoff 1101 ph.Filesz = seg.Filelen 1102 ph.Align = uint64(*FlagRound) 1103 1104 return ph 1105 } 1106 1107 func elfphrelro(seg *sym.Segment) { 1108 ph := newElfPhdr() 1109 ph.Type = elf.PT_GNU_RELRO 1110 ph.Vaddr = seg.Vaddr 1111 ph.Paddr = seg.Vaddr 1112 ph.Memsz = seg.Length 1113 ph.Off = seg.Fileoff 1114 ph.Filesz = seg.Filelen 1115 ph.Align = uint64(*FlagRound) 1116 } 1117 1118 func elfshname(name string) *ElfShdr { 1119 for i := 0; i < nelfstr; i++ { 1120 if name != elfstr[i].s { 1121 continue 1122 } 1123 off := elfstr[i].off 1124 for i = 0; i < int(ehdr.Shnum); i++ { 1125 sh := shdr[i] 1126 if sh.Name == uint32(off) { 1127 return sh 1128 } 1129 } 1130 return newElfShdr(int64(off)) 1131 } 1132 Exitf("cannot find elf name %s", name) 1133 return nil 1134 } 1135 1136 // Create an ElfShdr for the section with name. 1137 // Create a duplicate if one already exists with that name. 1138 func elfshnamedup(name string) *ElfShdr { 1139 for i := 0; i < nelfstr; i++ { 1140 if name == elfstr[i].s { 1141 off := elfstr[i].off 1142 return newElfShdr(int64(off)) 1143 } 1144 } 1145 1146 Errorf(nil, "cannot find elf name %s", name) 1147 errorexit() 1148 return nil 1149 } 1150 1151 func elfshalloc(sect *sym.Section) *ElfShdr { 1152 sh := elfshname(sect.Name) 1153 sect.Elfsect = sh 1154 return sh 1155 } 1156 1157 func elfshbits(linkmode LinkMode, sect *sym.Section) *ElfShdr { 1158 var sh *ElfShdr 1159 1160 if sect.Name == ".text" { 1161 if sect.Elfsect == nil { 1162 sect.Elfsect = elfshnamedup(sect.Name) 1163 } 1164 sh = sect.Elfsect.(*ElfShdr) 1165 } else { 1166 sh = elfshalloc(sect) 1167 } 1168 1169 // If this section has already been set up as a note, we assume type_ and 1170 // flags are already correct, but the other fields still need filling in. 1171 if sh.Type == uint32(elf.SHT_NOTE) { 1172 if linkmode != LinkExternal { 1173 // TODO(mwhudson): the approach here will work OK when 1174 // linking internally for notes that we want to be included 1175 // in a loadable segment (e.g. the abihash note) but not for 1176 // notes that we do not want to be mapped (e.g. the package 1177 // list note). The real fix is probably to define new values 1178 // for Symbol.Type corresponding to mapped and unmapped notes 1179 // and handle them in dodata(). 1180 Errorf(nil, "sh.Type == SHT_NOTE in elfshbits when linking internally") 1181 } 1182 sh.Addralign = uint64(sect.Align) 1183 sh.Size = sect.Length 1184 sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr 1185 return sh 1186 } 1187 if sh.Type > 0 { 1188 return sh 1189 } 1190 1191 if sect.Vaddr < sect.Seg.Vaddr+sect.Seg.Filelen { 1192 switch sect.Name { 1193 case ".init_array": 1194 sh.Type = uint32(elf.SHT_INIT_ARRAY) 1195 default: 1196 sh.Type = uint32(elf.SHT_PROGBITS) 1197 } 1198 } else { 1199 sh.Type = uint32(elf.SHT_NOBITS) 1200 } 1201 sh.Flags = uint64(elf.SHF_ALLOC) 1202 if sect.Rwx&1 != 0 { 1203 sh.Flags |= uint64(elf.SHF_EXECINSTR) 1204 } 1205 if sect.Rwx&2 != 0 { 1206 sh.Flags |= uint64(elf.SHF_WRITE) 1207 } 1208 if sect.Name == ".tbss" { 1209 sh.Flags |= uint64(elf.SHF_TLS) 1210 sh.Type = uint32(elf.SHT_NOBITS) 1211 } 1212 if linkmode != LinkExternal { 1213 sh.Addr = sect.Vaddr 1214 } 1215 1216 if strings.HasPrefix(sect.Name, ".debug") || strings.HasPrefix(sect.Name, ".zdebug") { 1217 sh.Flags = 0 1218 sh.Addr = 0 1219 if sect.Compressed { 1220 sh.Flags |= uint64(elf.SHF_COMPRESSED) 1221 } 1222 } 1223 1224 sh.Addralign = uint64(sect.Align) 1225 sh.Size = sect.Length 1226 if sect.Name != ".tbss" { 1227 sh.Off = sect.Seg.Fileoff + sect.Vaddr - sect.Seg.Vaddr 1228 } 1229 1230 return sh 1231 } 1232 1233 func elfshreloc(arch *sys.Arch, sect *sym.Section) *ElfShdr { 1234 // If main section is SHT_NOBITS, nothing to relocate. 1235 // Also nothing to relocate in .shstrtab or notes. 1236 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { 1237 return nil 1238 } 1239 if sect.Name == ".shstrtab" || sect.Name == ".tbss" { 1240 return nil 1241 } 1242 if sect.Elfsect.(*ElfShdr).Type == uint32(elf.SHT_NOTE) { 1243 return nil 1244 } 1245 1246 typ := elf.SHT_REL 1247 if elfRelType == ".rela" { 1248 typ = elf.SHT_RELA 1249 } 1250 1251 sh := elfshname(elfRelType + sect.Name) 1252 // There could be multiple text sections but each needs 1253 // its own .rela.text. 1254 1255 if sect.Name == ".text" { 1256 if sh.Info != 0 && sh.Info != uint32(sect.Elfsect.(*ElfShdr).shnum) { 1257 sh = elfshnamedup(elfRelType + sect.Name) 1258 } 1259 } 1260 1261 sh.Type = uint32(typ) 1262 sh.Entsize = uint64(arch.RegSize) * 2 1263 if typ == elf.SHT_RELA { 1264 sh.Entsize += uint64(arch.RegSize) 1265 } 1266 sh.Link = uint32(elfshname(".symtab").shnum) 1267 sh.Info = uint32(sect.Elfsect.(*ElfShdr).shnum) 1268 sh.Off = sect.Reloff 1269 sh.Size = sect.Rellen 1270 sh.Addralign = uint64(arch.RegSize) 1271 return sh 1272 } 1273 1274 func elfrelocsect(ctxt *Link, out *OutBuf, sect *sym.Section, syms []loader.Sym) { 1275 // If main section is SHT_NOBITS, nothing to relocate. 1276 // Also nothing to relocate in .shstrtab. 1277 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { 1278 return 1279 } 1280 if sect.Name == ".shstrtab" { 1281 return 1282 } 1283 1284 ldr := ctxt.loader 1285 for i, s := range syms { 1286 if !ldr.AttrReachable(s) { 1287 panic("should never happen") 1288 } 1289 if uint64(ldr.SymValue(s)) >= sect.Vaddr { 1290 syms = syms[i:] 1291 break 1292 } 1293 } 1294 1295 eaddr := sect.Vaddr + sect.Length 1296 for _, s := range syms { 1297 if !ldr.AttrReachable(s) { 1298 continue 1299 } 1300 if ldr.SymValue(s) >= int64(eaddr) { 1301 break 1302 } 1303 1304 // Compute external relocations on the go, and pass to 1305 // ELF.Reloc1 to stream out. 1306 relocs := ldr.Relocs(s) 1307 for ri := 0; ri < relocs.Count(); ri++ { 1308 r := relocs.At(ri) 1309 rr, ok := extreloc(ctxt, ldr, s, r) 1310 if !ok { 1311 continue 1312 } 1313 if rr.Xsym == 0 { 1314 ldr.Errorf(s, "missing xsym in relocation") 1315 continue 1316 } 1317 esr := ElfSymForReloc(ctxt, rr.Xsym) 1318 if esr == 0 { 1319 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()) 1320 } 1321 if !ldr.AttrReachable(rr.Xsym) { 1322 ldr.Errorf(s, "unreachable reloc %d (%s) target %v", r.Type(), sym.RelocName(ctxt.Arch, r.Type()), ldr.SymName(rr.Xsym)) 1323 } 1324 if !thearch.ELF.Reloc1(ctxt, out, ldr, s, rr, ri, int64(uint64(ldr.SymValue(s)+int64(r.Off()))-sect.Vaddr)) { 1325 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())) 1326 } 1327 } 1328 } 1329 1330 // sanity check 1331 if uint64(out.Offset()) != sect.Reloff+sect.Rellen { 1332 panic(fmt.Sprintf("elfrelocsect: size mismatch %d != %d + %d", out.Offset(), sect.Reloff, sect.Rellen)) 1333 } 1334 } 1335 1336 func elfEmitReloc(ctxt *Link) { 1337 for ctxt.Out.Offset()&7 != 0 { 1338 ctxt.Out.Write8(0) 1339 } 1340 1341 sizeExtRelocs(ctxt, thearch.ELF.RelocSize) 1342 relocSect, wg := relocSectFn(ctxt, elfrelocsect) 1343 1344 for _, sect := range Segtext.Sections { 1345 if sect.Name == ".text" { 1346 relocSect(ctxt, sect, ctxt.Textp) 1347 } else { 1348 relocSect(ctxt, sect, ctxt.datap) 1349 } 1350 } 1351 1352 for _, sect := range Segrodata.Sections { 1353 relocSect(ctxt, sect, ctxt.datap) 1354 } 1355 for _, sect := range Segrelrodata.Sections { 1356 relocSect(ctxt, sect, ctxt.datap) 1357 } 1358 for _, sect := range Segdata.Sections { 1359 relocSect(ctxt, sect, ctxt.datap) 1360 } 1361 for i := 0; i < len(Segdwarf.Sections); i++ { 1362 sect := Segdwarf.Sections[i] 1363 si := dwarfp[i] 1364 if si.secSym() != loader.Sym(sect.Sym) || 1365 ctxt.loader.SymSect(si.secSym()) != sect { 1366 panic("inconsistency between dwarfp and Segdwarf") 1367 } 1368 relocSect(ctxt, sect, si.syms) 1369 } 1370 wg.Wait() 1371 } 1372 1373 func addgonote(ctxt *Link, sectionName string, tag uint32, desc []byte) { 1374 ldr := ctxt.loader 1375 s := ldr.CreateSymForUpdate(sectionName, 0) 1376 s.SetType(sym.SELFROSECT) 1377 // namesz 1378 s.AddUint32(ctxt.Arch, uint32(len(ELF_NOTE_GO_NAME))) 1379 // descsz 1380 s.AddUint32(ctxt.Arch, uint32(len(desc))) 1381 // tag 1382 s.AddUint32(ctxt.Arch, tag) 1383 // name + padding 1384 s.AddBytes(ELF_NOTE_GO_NAME) 1385 for len(s.Data())%4 != 0 { 1386 s.AddUint8(0) 1387 } 1388 // desc + padding 1389 s.AddBytes(desc) 1390 for len(s.Data())%4 != 0 { 1391 s.AddUint8(0) 1392 } 1393 s.SetSize(int64(len(s.Data()))) 1394 s.SetAlign(4) 1395 } 1396 1397 func (ctxt *Link) doelf() { 1398 ldr := ctxt.loader 1399 1400 /* predefine strings we need for section headers */ 1401 1402 addshstr := func(s string) int { 1403 off := len(elfshstrdat) 1404 elfshstrdat = append(elfshstrdat, s...) 1405 elfshstrdat = append(elfshstrdat, 0) 1406 return off 1407 } 1408 1409 shstrtabAddstring := func(s string) { 1410 off := addshstr(s) 1411 elfsetstring(ctxt, 0, s, int(off)) 1412 } 1413 1414 shstrtabAddstring("") 1415 shstrtabAddstring(".text") 1416 shstrtabAddstring(".noptrdata") 1417 shstrtabAddstring(".data") 1418 shstrtabAddstring(".bss") 1419 shstrtabAddstring(".noptrbss") 1420 shstrtabAddstring(".go.fuzzcntrs") 1421 shstrtabAddstring(".go.buildinfo") 1422 if ctxt.IsMIPS() { 1423 shstrtabAddstring(".MIPS.abiflags") 1424 shstrtabAddstring(".gnu.attributes") 1425 } 1426 1427 // generate .tbss section for dynamic internal linker or external 1428 // linking, so that various binutils could correctly calculate 1429 // PT_TLS size. See https://golang.org/issue/5200. 1430 if !*FlagD || ctxt.IsExternal() { 1431 shstrtabAddstring(".tbss") 1432 } 1433 if ctxt.IsNetbsd() { 1434 shstrtabAddstring(".note.netbsd.ident") 1435 if *flagRace { 1436 shstrtabAddstring(".note.netbsd.pax") 1437 } 1438 } 1439 if ctxt.IsOpenbsd() { 1440 shstrtabAddstring(".note.openbsd.ident") 1441 } 1442 if ctxt.IsFreebsd() { 1443 shstrtabAddstring(".note.tag") 1444 } 1445 if len(buildinfo) > 0 { 1446 shstrtabAddstring(".note.gnu.build-id") 1447 } 1448 if *flagBuildid != "" { 1449 shstrtabAddstring(".note.go.buildid") 1450 } 1451 shstrtabAddstring(".elfdata") 1452 shstrtabAddstring(".rodata") 1453 // See the comment about data.rel.ro.FOO section names in data.go. 1454 relro_prefix := "" 1455 if ctxt.UseRelro() { 1456 shstrtabAddstring(".data.rel.ro") 1457 relro_prefix = ".data.rel.ro" 1458 } 1459 shstrtabAddstring(relro_prefix + ".typelink") 1460 shstrtabAddstring(relro_prefix + ".itablink") 1461 shstrtabAddstring(relro_prefix + ".gosymtab") 1462 shstrtabAddstring(relro_prefix + ".gopclntab") 1463 1464 if ctxt.IsExternal() { 1465 *FlagD = true 1466 1467 shstrtabAddstring(elfRelType + ".text") 1468 shstrtabAddstring(elfRelType + ".rodata") 1469 shstrtabAddstring(elfRelType + relro_prefix + ".typelink") 1470 shstrtabAddstring(elfRelType + relro_prefix + ".itablink") 1471 shstrtabAddstring(elfRelType + relro_prefix + ".gosymtab") 1472 shstrtabAddstring(elfRelType + relro_prefix + ".gopclntab") 1473 shstrtabAddstring(elfRelType + ".noptrdata") 1474 shstrtabAddstring(elfRelType + ".data") 1475 if ctxt.UseRelro() { 1476 shstrtabAddstring(elfRelType + ".data.rel.ro") 1477 } 1478 shstrtabAddstring(elfRelType + ".go.buildinfo") 1479 if ctxt.IsMIPS() { 1480 shstrtabAddstring(elfRelType + ".MIPS.abiflags") 1481 shstrtabAddstring(elfRelType + ".gnu.attributes") 1482 } 1483 1484 // add a .note.GNU-stack section to mark the stack as non-executable 1485 shstrtabAddstring(".note.GNU-stack") 1486 1487 if ctxt.IsShared() { 1488 shstrtabAddstring(".note.go.abihash") 1489 shstrtabAddstring(".note.go.pkg-list") 1490 shstrtabAddstring(".note.go.deps") 1491 } 1492 } 1493 1494 hasinitarr := ctxt.linkShared 1495 1496 /* shared library initializer */ 1497 switch ctxt.BuildMode { 1498 case BuildModeCArchive, BuildModeCShared, BuildModeShared, BuildModePlugin: 1499 hasinitarr = true 1500 } 1501 1502 if hasinitarr { 1503 shstrtabAddstring(".init_array") 1504 shstrtabAddstring(elfRelType + ".init_array") 1505 } 1506 1507 if !*FlagS { 1508 shstrtabAddstring(".symtab") 1509 shstrtabAddstring(".strtab") 1510 } 1511 if !*FlagW { 1512 dwarfaddshstrings(ctxt, shstrtabAddstring) 1513 } 1514 1515 shstrtabAddstring(".shstrtab") 1516 1517 if !*FlagD { /* -d suppresses dynamic loader format */ 1518 shstrtabAddstring(".interp") 1519 shstrtabAddstring(".hash") 1520 shstrtabAddstring(".got") 1521 if ctxt.IsPPC64() { 1522 shstrtabAddstring(".glink") 1523 } 1524 shstrtabAddstring(".got.plt") 1525 shstrtabAddstring(".dynamic") 1526 shstrtabAddstring(".dynsym") 1527 shstrtabAddstring(".dynstr") 1528 shstrtabAddstring(elfRelType) 1529 shstrtabAddstring(elfRelType + ".plt") 1530 1531 shstrtabAddstring(".plt") 1532 shstrtabAddstring(".gnu.version") 1533 shstrtabAddstring(".gnu.version_r") 1534 1535 /* dynamic symbol table - first entry all zeros */ 1536 dynsym := ldr.CreateSymForUpdate(".dynsym", 0) 1537 1538 dynsym.SetType(sym.SELFROSECT) 1539 if elf64 { 1540 dynsym.SetSize(dynsym.Size() + ELF64SYMSIZE) 1541 } else { 1542 dynsym.SetSize(dynsym.Size() + ELF32SYMSIZE) 1543 } 1544 1545 /* dynamic string table */ 1546 dynstr := ldr.CreateSymForUpdate(".dynstr", 0) 1547 1548 dynstr.SetType(sym.SELFROSECT) 1549 if dynstr.Size() == 0 { 1550 dynstr.Addstring("") 1551 } 1552 1553 /* relocation table */ 1554 s := ldr.CreateSymForUpdate(elfRelType, 0) 1555 s.SetType(sym.SELFROSECT) 1556 1557 /* global offset table */ 1558 got := ldr.CreateSymForUpdate(".got", 0) 1559 got.SetType(sym.SELFGOT) // writable 1560 1561 /* ppc64 glink resolver */ 1562 if ctxt.IsPPC64() { 1563 s := ldr.CreateSymForUpdate(".glink", 0) 1564 s.SetType(sym.SELFRXSECT) 1565 } 1566 1567 /* hash */ 1568 hash := ldr.CreateSymForUpdate(".hash", 0) 1569 hash.SetType(sym.SELFROSECT) 1570 1571 gotplt := ldr.CreateSymForUpdate(".got.plt", 0) 1572 gotplt.SetType(sym.SELFSECT) // writable 1573 1574 plt := ldr.CreateSymForUpdate(".plt", 0) 1575 if ctxt.IsPPC64() { 1576 // In the ppc64 ABI, .plt is a data section 1577 // written by the dynamic linker. 1578 plt.SetType(sym.SELFSECT) 1579 } else { 1580 plt.SetType(sym.SELFRXSECT) 1581 } 1582 1583 s = ldr.CreateSymForUpdate(elfRelType+".plt", 0) 1584 s.SetType(sym.SELFROSECT) 1585 1586 s = ldr.CreateSymForUpdate(".gnu.version", 0) 1587 s.SetType(sym.SELFROSECT) 1588 1589 s = ldr.CreateSymForUpdate(".gnu.version_r", 0) 1590 s.SetType(sym.SELFROSECT) 1591 1592 /* define dynamic elf table */ 1593 dynamic := ldr.CreateSymForUpdate(".dynamic", 0) 1594 if thearch.ELF.DynamicReadOnly { 1595 dynamic.SetType(sym.SELFROSECT) 1596 } else { 1597 dynamic.SetType(sym.SELFSECT) 1598 } 1599 1600 if ctxt.IsS390X() { 1601 // S390X uses .got instead of .got.plt 1602 gotplt = got 1603 } 1604 thearch.ELF.SetupPLT(ctxt, ctxt.loader, plt, gotplt, dynamic.Sym()) 1605 1606 /* 1607 * .dynamic table 1608 */ 1609 elfWriteDynEntSym(ctxt, dynamic, elf.DT_HASH, hash.Sym()) 1610 1611 elfWriteDynEntSym(ctxt, dynamic, elf.DT_SYMTAB, dynsym.Sym()) 1612 if elf64 { 1613 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF64SYMSIZE) 1614 } else { 1615 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_SYMENT, ELF32SYMSIZE) 1616 } 1617 elfWriteDynEntSym(ctxt, dynamic, elf.DT_STRTAB, dynstr.Sym()) 1618 elfwritedynentsymsize(ctxt, dynamic, elf.DT_STRSZ, dynstr.Sym()) 1619 if elfRelType == ".rela" { 1620 rela := ldr.LookupOrCreateSym(".rela", 0) 1621 elfWriteDynEntSym(ctxt, dynamic, elf.DT_RELA, rela) 1622 elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELASZ, rela) 1623 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELAENT, ELF64RELASIZE) 1624 } else { 1625 rel := ldr.LookupOrCreateSym(".rel", 0) 1626 elfWriteDynEntSym(ctxt, dynamic, elf.DT_REL, rel) 1627 elfwritedynentsymsize(ctxt, dynamic, elf.DT_RELSZ, rel) 1628 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RELENT, ELF32RELSIZE) 1629 } 1630 1631 if rpath.val != "" { 1632 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_RUNPATH, uint64(dynstr.Addstring(rpath.val))) 1633 } 1634 1635 if ctxt.IsPPC64() { 1636 elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, plt.Sym()) 1637 } else { 1638 elfWriteDynEntSym(ctxt, dynamic, elf.DT_PLTGOT, gotplt.Sym()) 1639 } 1640 1641 if ctxt.IsPPC64() { 1642 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_PPC64_OPT, 0) 1643 } 1644 1645 // Solaris dynamic linker can't handle an empty .rela.plt if 1646 // DT_JMPREL is emitted so we have to defer generation of elf.DT_PLTREL, 1647 // DT_PLTRELSZ, and elf.DT_JMPREL dynamic entries until after we know the 1648 // size of .rel(a).plt section. 1649 1650 Elfwritedynent(ctxt.Arch, dynamic, elf.DT_DEBUG, 0) 1651 } 1652 1653 if ctxt.IsShared() { 1654 // The go.link.abihashbytes symbol will be pointed at the appropriate 1655 // part of the .note.go.abihash section in data.go:func address(). 1656 s := ldr.LookupOrCreateSym("go:link.abihashbytes", 0) 1657 sb := ldr.MakeSymbolUpdater(s) 1658 ldr.SetAttrLocal(s, true) 1659 sb.SetType(sym.SRODATA) 1660 ldr.SetAttrSpecial(s, true) 1661 sb.SetReachable(true) 1662 sb.SetSize(notsha256.Size) 1663 1664 sort.Sort(byPkg(ctxt.Library)) 1665 h := notsha256.New() 1666 for _, l := range ctxt.Library { 1667 h.Write(l.Fingerprint[:]) 1668 } 1669 addgonote(ctxt, ".note.go.abihash", ELF_NOTE_GOABIHASH_TAG, h.Sum([]byte{})) 1670 addgonote(ctxt, ".note.go.pkg-list", ELF_NOTE_GOPKGLIST_TAG, pkglistfornote) 1671 var deplist []string 1672 for _, shlib := range ctxt.Shlibs { 1673 deplist = append(deplist, filepath.Base(shlib.Path)) 1674 } 1675 addgonote(ctxt, ".note.go.deps", ELF_NOTE_GODEPS_TAG, []byte(strings.Join(deplist, "\n"))) 1676 } 1677 1678 if ctxt.LinkMode == LinkExternal && *flagBuildid != "" { 1679 addgonote(ctxt, ".note.go.buildid", ELF_NOTE_GOBUILDID_TAG, []byte(*flagBuildid)) 1680 } 1681 1682 //type mipsGnuAttributes struct { 1683 // version uint8 // 'A' 1684 // length uint32 // 15 including itself 1685 // gnu [4]byte // "gnu\0" 1686 // tag uint8 // 1:file, 2: section, 3: symbol, 1 here 1687 // taglen uint32 // tag length, including tag, 7 here 1688 // tagfp uint8 // 4 1689 // fpAbi uint8 // see .MIPS.abiflags 1690 //} 1691 if ctxt.IsMIPS() { 1692 gnuattributes := ldr.CreateSymForUpdate(".gnu.attributes", 0) 1693 gnuattributes.SetType(sym.SELFROSECT) 1694 gnuattributes.SetReachable(true) 1695 gnuattributes.AddUint8('A') // version 'A' 1696 gnuattributes.AddUint32(ctxt.Arch, 15) // length 15 including itself 1697 gnuattributes.AddBytes([]byte("gnu\x00")) // "gnu\0" 1698 gnuattributes.AddUint8(1) // 1:file, 2: section, 3: symbol, 1 here 1699 gnuattributes.AddUint32(ctxt.Arch, 7) // tag length, including tag, 7 here 1700 gnuattributes.AddUint8(4) // 4 for FP, 8 for MSA 1701 if buildcfg.GOMIPS == "softfloat" { 1702 gnuattributes.AddUint8(MIPS_FPABI_SOFT) 1703 } else { 1704 // Note: MIPS_FPABI_ANY is bad naming: in fact it is MIPS I style FPR usage. 1705 // It is not for 'ANY'. 1706 // TODO: switch to FPXX after be sure that no odd-number-fpr is used. 1707 gnuattributes.AddUint8(MIPS_FPABI_ANY) 1708 } 1709 } 1710 } 1711 1712 // Do not write DT_NULL. elfdynhash will finish it. 1713 func shsym(sh *ElfShdr, ldr *loader.Loader, s loader.Sym) { 1714 if s == 0 { 1715 panic("bad symbol in shsym2") 1716 } 1717 addr := ldr.SymValue(s) 1718 if sh.Flags&uint64(elf.SHF_ALLOC) != 0 { 1719 sh.Addr = uint64(addr) 1720 } 1721 sh.Off = uint64(datoff(ldr, s, addr)) 1722 sh.Size = uint64(ldr.SymSize(s)) 1723 } 1724 1725 func phsh(ph *ElfPhdr, sh *ElfShdr) { 1726 ph.Vaddr = sh.Addr 1727 ph.Paddr = ph.Vaddr 1728 ph.Off = sh.Off 1729 ph.Filesz = sh.Size 1730 ph.Memsz = sh.Size 1731 ph.Align = sh.Addralign 1732 } 1733 1734 func Asmbelfsetup() { 1735 /* This null SHdr must appear before all others */ 1736 elfshname("") 1737 1738 for _, sect := range Segtext.Sections { 1739 // There could be multiple .text sections. Instead check the Elfsect 1740 // field to determine if already has an ElfShdr and if not, create one. 1741 if sect.Name == ".text" { 1742 if sect.Elfsect == nil { 1743 sect.Elfsect = elfshnamedup(sect.Name) 1744 } 1745 } else { 1746 elfshalloc(sect) 1747 } 1748 } 1749 for _, sect := range Segrodata.Sections { 1750 elfshalloc(sect) 1751 } 1752 for _, sect := range Segrelrodata.Sections { 1753 elfshalloc(sect) 1754 } 1755 for _, sect := range Segdata.Sections { 1756 elfshalloc(sect) 1757 } 1758 for _, sect := range Segdwarf.Sections { 1759 elfshalloc(sect) 1760 } 1761 } 1762 1763 func asmbElf(ctxt *Link) { 1764 var symo int64 1765 symo = int64(Segdwarf.Fileoff + Segdwarf.Filelen) 1766 symo = Rnd(symo, int64(ctxt.Arch.PtrSize)) 1767 ctxt.Out.SeekSet(symo) 1768 if *FlagS { 1769 ctxt.Out.Write(elfshstrdat) 1770 } else { 1771 ctxt.Out.SeekSet(symo) 1772 asmElfSym(ctxt) 1773 ctxt.Out.Write(elfstrdat) 1774 ctxt.Out.Write(elfshstrdat) 1775 if ctxt.IsExternal() { 1776 elfEmitReloc(ctxt) 1777 } 1778 } 1779 ctxt.Out.SeekSet(0) 1780 1781 ldr := ctxt.loader 1782 eh := getElfEhdr() 1783 switch ctxt.Arch.Family { 1784 default: 1785 Exitf("unknown architecture in asmbelf: %v", ctxt.Arch.Family) 1786 case sys.MIPS, sys.MIPS64: 1787 eh.Machine = uint16(elf.EM_MIPS) 1788 case sys.Loong64: 1789 eh.Machine = uint16(elf.EM_LOONGARCH) 1790 case sys.ARM: 1791 eh.Machine = uint16(elf.EM_ARM) 1792 case sys.AMD64: 1793 eh.Machine = uint16(elf.EM_X86_64) 1794 case sys.ARM64: 1795 eh.Machine = uint16(elf.EM_AARCH64) 1796 case sys.I386: 1797 eh.Machine = uint16(elf.EM_386) 1798 case sys.PPC64: 1799 eh.Machine = uint16(elf.EM_PPC64) 1800 case sys.RISCV64: 1801 eh.Machine = uint16(elf.EM_RISCV) 1802 case sys.S390X: 1803 eh.Machine = uint16(elf.EM_S390) 1804 } 1805 1806 elfreserve := int64(ELFRESERVE) 1807 1808 numtext := int64(0) 1809 for _, sect := range Segtext.Sections { 1810 if sect.Name == ".text" { 1811 numtext++ 1812 } 1813 } 1814 1815 // If there are multiple text sections, extra space is needed 1816 // in the elfreserve for the additional .text and .rela.text 1817 // section headers. It can handle 4 extra now. Headers are 1818 // 64 bytes. 1819 1820 if numtext > 4 { 1821 elfreserve += elfreserve + numtext*64*2 1822 } 1823 1824 startva := *FlagTextAddr - int64(HEADR) 1825 resoff := elfreserve 1826 1827 var pph *ElfPhdr 1828 var pnote *ElfPhdr 1829 getpnote := func() *ElfPhdr { 1830 if pnote == nil { 1831 pnote = newElfPhdr() 1832 pnote.Type = elf.PT_NOTE 1833 pnote.Flags = elf.PF_R 1834 } 1835 return pnote 1836 } 1837 if *flagRace && ctxt.IsNetbsd() { 1838 sh := elfshname(".note.netbsd.pax") 1839 resoff -= int64(elfnetbsdpax(sh, uint64(startva), uint64(resoff))) 1840 phsh(getpnote(), sh) 1841 } 1842 if ctxt.LinkMode == LinkExternal { 1843 /* skip program headers */ 1844 eh.Phoff = 0 1845 1846 eh.Phentsize = 0 1847 1848 if ctxt.BuildMode == BuildModeShared { 1849 sh := elfshname(".note.go.pkg-list") 1850 sh.Type = uint32(elf.SHT_NOTE) 1851 sh = elfshname(".note.go.abihash") 1852 sh.Type = uint32(elf.SHT_NOTE) 1853 sh.Flags = uint64(elf.SHF_ALLOC) 1854 sh = elfshname(".note.go.deps") 1855 sh.Type = uint32(elf.SHT_NOTE) 1856 } 1857 1858 if *flagBuildid != "" { 1859 sh := elfshname(".note.go.buildid") 1860 sh.Type = uint32(elf.SHT_NOTE) 1861 sh.Flags = uint64(elf.SHF_ALLOC) 1862 } 1863 1864 goto elfobj 1865 } 1866 1867 /* program header info */ 1868 pph = newElfPhdr() 1869 1870 pph.Type = elf.PT_PHDR 1871 pph.Flags = elf.PF_R 1872 pph.Off = uint64(eh.Ehsize) 1873 pph.Vaddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off 1874 pph.Paddr = uint64(*FlagTextAddr) - uint64(HEADR) + pph.Off 1875 pph.Align = uint64(*FlagRound) 1876 1877 /* 1878 * PHDR must be in a loaded segment. Adjust the text 1879 * segment boundaries downwards to include it. 1880 */ 1881 { 1882 o := int64(Segtext.Vaddr - pph.Vaddr) 1883 Segtext.Vaddr -= uint64(o) 1884 Segtext.Length += uint64(o) 1885 o = int64(Segtext.Fileoff - pph.Off) 1886 Segtext.Fileoff -= uint64(o) 1887 Segtext.Filelen += uint64(o) 1888 } 1889 1890 if !*FlagD { /* -d suppresses dynamic loader format */ 1891 /* interpreter */ 1892 sh := elfshname(".interp") 1893 1894 sh.Type = uint32(elf.SHT_PROGBITS) 1895 sh.Flags = uint64(elf.SHF_ALLOC) 1896 sh.Addralign = 1 1897 1898 if interpreter == "" && buildcfg.GOOS == runtime.GOOS && buildcfg.GOARCH == runtime.GOARCH && buildcfg.GO_LDSO != "" { 1899 interpreter = buildcfg.GO_LDSO 1900 } 1901 1902 if interpreter == "" { 1903 switch ctxt.HeadType { 1904 case objabi.Hlinux: 1905 if buildcfg.GOOS == "android" { 1906 interpreter = thearch.ELF.Androiddynld 1907 if interpreter == "" { 1908 Exitf("ELF interpreter not set") 1909 } 1910 } else { 1911 interpreter = thearch.ELF.Linuxdynld 1912 // If interpreter does not exist, try musl instead. 1913 // This lets the same cmd/link binary work on 1914 // both glibc-based and musl-based systems. 1915 if _, err := os.Stat(interpreter); err != nil { 1916 if musl := thearch.ELF.LinuxdynldMusl; musl != "" { 1917 if _, err := os.Stat(musl); err == nil { 1918 interpreter = musl 1919 } 1920 } 1921 } 1922 } 1923 1924 case objabi.Hfreebsd: 1925 interpreter = thearch.ELF.Freebsddynld 1926 1927 case objabi.Hnetbsd: 1928 interpreter = thearch.ELF.Netbsddynld 1929 1930 case objabi.Hopenbsd: 1931 interpreter = thearch.ELF.Openbsddynld 1932 1933 case objabi.Hdragonfly: 1934 interpreter = thearch.ELF.Dragonflydynld 1935 1936 case objabi.Hsolaris: 1937 interpreter = thearch.ELF.Solarisdynld 1938 } 1939 } 1940 1941 resoff -= int64(elfinterp(sh, uint64(startva), uint64(resoff), interpreter)) 1942 1943 ph := newElfPhdr() 1944 ph.Type = elf.PT_INTERP 1945 ph.Flags = elf.PF_R 1946 phsh(ph, sh) 1947 } 1948 1949 if ctxt.HeadType == objabi.Hnetbsd || ctxt.HeadType == objabi.Hopenbsd || ctxt.HeadType == objabi.Hfreebsd { 1950 var sh *ElfShdr 1951 switch ctxt.HeadType { 1952 case objabi.Hnetbsd: 1953 sh = elfshname(".note.netbsd.ident") 1954 resoff -= int64(elfnetbsdsig(sh, uint64(startva), uint64(resoff))) 1955 1956 case objabi.Hopenbsd: 1957 sh = elfshname(".note.openbsd.ident") 1958 resoff -= int64(elfopenbsdsig(sh, uint64(startva), uint64(resoff))) 1959 1960 case objabi.Hfreebsd: 1961 sh = elfshname(".note.tag") 1962 resoff -= int64(elffreebsdsig(sh, uint64(startva), uint64(resoff))) 1963 } 1964 // NetBSD, OpenBSD and FreeBSD require ident in an independent segment. 1965 pnotei := newElfPhdr() 1966 pnotei.Type = elf.PT_NOTE 1967 pnotei.Flags = elf.PF_R 1968 phsh(pnotei, sh) 1969 } 1970 1971 if len(buildinfo) > 0 { 1972 sh := elfshname(".note.gnu.build-id") 1973 resoff -= int64(elfbuildinfo(sh, uint64(startva), uint64(resoff))) 1974 phsh(getpnote(), sh) 1975 } 1976 1977 if *flagBuildid != "" { 1978 sh := elfshname(".note.go.buildid") 1979 resoff -= int64(elfgobuildid(sh, uint64(startva), uint64(resoff))) 1980 phsh(getpnote(), sh) 1981 } 1982 1983 // Additions to the reserved area must be above this line. 1984 1985 elfphload(&Segtext) 1986 if len(Segrodata.Sections) > 0 { 1987 elfphload(&Segrodata) 1988 } 1989 if len(Segrelrodata.Sections) > 0 { 1990 elfphload(&Segrelrodata) 1991 elfphrelro(&Segrelrodata) 1992 } 1993 elfphload(&Segdata) 1994 1995 /* Dynamic linking sections */ 1996 if !*FlagD { 1997 sh := elfshname(".dynsym") 1998 sh.Type = uint32(elf.SHT_DYNSYM) 1999 sh.Flags = uint64(elf.SHF_ALLOC) 2000 if elf64 { 2001 sh.Entsize = ELF64SYMSIZE 2002 } else { 2003 sh.Entsize = ELF32SYMSIZE 2004 } 2005 sh.Addralign = uint64(ctxt.Arch.RegSize) 2006 sh.Link = uint32(elfshname(".dynstr").shnum) 2007 2008 // sh.info is the index of first non-local symbol (number of local symbols) 2009 s := ldr.Lookup(".dynsym", 0) 2010 i := uint32(0) 2011 for sub := s; sub != 0; sub = ldr.SubSym(sub) { 2012 i++ 2013 if !ldr.AttrLocal(sub) { 2014 break 2015 } 2016 } 2017 sh.Info = i 2018 shsym(sh, ldr, s) 2019 2020 sh = elfshname(".dynstr") 2021 sh.Type = uint32(elf.SHT_STRTAB) 2022 sh.Flags = uint64(elf.SHF_ALLOC) 2023 sh.Addralign = 1 2024 shsym(sh, ldr, ldr.Lookup(".dynstr", 0)) 2025 2026 if elfverneed != 0 { 2027 sh := elfshname(".gnu.version") 2028 sh.Type = uint32(elf.SHT_GNU_VERSYM) 2029 sh.Flags = uint64(elf.SHF_ALLOC) 2030 sh.Addralign = 2 2031 sh.Link = uint32(elfshname(".dynsym").shnum) 2032 sh.Entsize = 2 2033 shsym(sh, ldr, ldr.Lookup(".gnu.version", 0)) 2034 2035 sh = elfshname(".gnu.version_r") 2036 sh.Type = uint32(elf.SHT_GNU_VERNEED) 2037 sh.Flags = uint64(elf.SHF_ALLOC) 2038 sh.Addralign = uint64(ctxt.Arch.RegSize) 2039 sh.Info = uint32(elfverneed) 2040 sh.Link = uint32(elfshname(".dynstr").shnum) 2041 shsym(sh, ldr, ldr.Lookup(".gnu.version_r", 0)) 2042 } 2043 2044 if elfRelType == ".rela" { 2045 sh := elfshname(".rela.plt") 2046 sh.Type = uint32(elf.SHT_RELA) 2047 sh.Flags = uint64(elf.SHF_ALLOC) 2048 sh.Entsize = ELF64RELASIZE 2049 sh.Addralign = uint64(ctxt.Arch.RegSize) 2050 sh.Link = uint32(elfshname(".dynsym").shnum) 2051 sh.Info = uint32(elfshname(".plt").shnum) 2052 shsym(sh, ldr, ldr.Lookup(".rela.plt", 0)) 2053 2054 sh = elfshname(".rela") 2055 sh.Type = uint32(elf.SHT_RELA) 2056 sh.Flags = uint64(elf.SHF_ALLOC) 2057 sh.Entsize = ELF64RELASIZE 2058 sh.Addralign = 8 2059 sh.Link = uint32(elfshname(".dynsym").shnum) 2060 shsym(sh, ldr, ldr.Lookup(".rela", 0)) 2061 } else { 2062 sh := elfshname(".rel.plt") 2063 sh.Type = uint32(elf.SHT_REL) 2064 sh.Flags = uint64(elf.SHF_ALLOC) 2065 sh.Entsize = ELF32RELSIZE 2066 sh.Addralign = 4 2067 sh.Link = uint32(elfshname(".dynsym").shnum) 2068 shsym(sh, ldr, ldr.Lookup(".rel.plt", 0)) 2069 2070 sh = elfshname(".rel") 2071 sh.Type = uint32(elf.SHT_REL) 2072 sh.Flags = uint64(elf.SHF_ALLOC) 2073 sh.Entsize = ELF32RELSIZE 2074 sh.Addralign = 4 2075 sh.Link = uint32(elfshname(".dynsym").shnum) 2076 shsym(sh, ldr, ldr.Lookup(".rel", 0)) 2077 } 2078 2079 if elf.Machine(eh.Machine) == elf.EM_PPC64 { 2080 sh := elfshname(".glink") 2081 sh.Type = uint32(elf.SHT_PROGBITS) 2082 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR) 2083 sh.Addralign = 4 2084 shsym(sh, ldr, ldr.Lookup(".glink", 0)) 2085 } 2086 2087 sh = elfshname(".plt") 2088 sh.Type = uint32(elf.SHT_PROGBITS) 2089 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_EXECINSTR) 2090 if elf.Machine(eh.Machine) == elf.EM_X86_64 { 2091 sh.Entsize = 16 2092 } else if elf.Machine(eh.Machine) == elf.EM_S390 { 2093 sh.Entsize = 32 2094 } else if elf.Machine(eh.Machine) == elf.EM_PPC64 { 2095 // On ppc64, this is just a table of addresses 2096 // filled by the dynamic linker 2097 sh.Type = uint32(elf.SHT_NOBITS) 2098 2099 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE) 2100 sh.Entsize = 8 2101 } else { 2102 sh.Entsize = 4 2103 } 2104 sh.Addralign = sh.Entsize 2105 shsym(sh, ldr, ldr.Lookup(".plt", 0)) 2106 2107 // On ppc64, .got comes from the input files, so don't 2108 // create it here, and .got.plt is not used. 2109 if elf.Machine(eh.Machine) != elf.EM_PPC64 { 2110 sh := elfshname(".got") 2111 sh.Type = uint32(elf.SHT_PROGBITS) 2112 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE) 2113 sh.Entsize = uint64(ctxt.Arch.RegSize) 2114 sh.Addralign = uint64(ctxt.Arch.RegSize) 2115 shsym(sh, ldr, ldr.Lookup(".got", 0)) 2116 2117 sh = elfshname(".got.plt") 2118 sh.Type = uint32(elf.SHT_PROGBITS) 2119 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE) 2120 sh.Entsize = uint64(ctxt.Arch.RegSize) 2121 sh.Addralign = uint64(ctxt.Arch.RegSize) 2122 shsym(sh, ldr, ldr.Lookup(".got.plt", 0)) 2123 } 2124 2125 sh = elfshname(".hash") 2126 sh.Type = uint32(elf.SHT_HASH) 2127 sh.Flags = uint64(elf.SHF_ALLOC) 2128 sh.Entsize = 4 2129 sh.Addralign = uint64(ctxt.Arch.RegSize) 2130 sh.Link = uint32(elfshname(".dynsym").shnum) 2131 shsym(sh, ldr, ldr.Lookup(".hash", 0)) 2132 2133 /* sh and elf.PT_DYNAMIC for .dynamic section */ 2134 sh = elfshname(".dynamic") 2135 2136 sh.Type = uint32(elf.SHT_DYNAMIC) 2137 sh.Flags = uint64(elf.SHF_ALLOC + elf.SHF_WRITE) 2138 sh.Entsize = 2 * uint64(ctxt.Arch.RegSize) 2139 sh.Addralign = uint64(ctxt.Arch.RegSize) 2140 sh.Link = uint32(elfshname(".dynstr").shnum) 2141 shsym(sh, ldr, ldr.Lookup(".dynamic", 0)) 2142 ph := newElfPhdr() 2143 ph.Type = elf.PT_DYNAMIC 2144 ph.Flags = elf.PF_R + elf.PF_W 2145 phsh(ph, sh) 2146 2147 /* 2148 * Thread-local storage segment (really just size). 2149 */ 2150 tlssize := uint64(0) 2151 for _, sect := range Segdata.Sections { 2152 if sect.Name == ".tbss" { 2153 tlssize = sect.Length 2154 } 2155 } 2156 if tlssize != 0 { 2157 ph := newElfPhdr() 2158 ph.Type = elf.PT_TLS 2159 ph.Flags = elf.PF_R 2160 ph.Memsz = tlssize 2161 ph.Align = uint64(ctxt.Arch.RegSize) 2162 } 2163 } 2164 2165 if ctxt.HeadType == objabi.Hlinux || ctxt.HeadType == objabi.Hfreebsd { 2166 ph := newElfPhdr() 2167 ph.Type = elf.PT_GNU_STACK 2168 ph.Flags = elf.PF_W + elf.PF_R 2169 ph.Align = uint64(ctxt.Arch.RegSize) 2170 } else if ctxt.HeadType == objabi.Hsolaris { 2171 ph := newElfPhdr() 2172 ph.Type = elf.PT_SUNWSTACK 2173 ph.Flags = elf.PF_W + elf.PF_R 2174 } 2175 2176 elfobj: 2177 sh := elfshname(".shstrtab") 2178 eh.Shstrndx = uint16(sh.shnum) 2179 2180 if ctxt.IsMIPS() { 2181 sh = elfshname(".MIPS.abiflags") 2182 sh.Type = uint32(elf.SHT_MIPS_ABIFLAGS) 2183 sh.Flags = uint64(elf.SHF_ALLOC) 2184 sh.Addralign = 8 2185 resoff -= int64(elfMipsAbiFlags(sh, uint64(startva), uint64(resoff))) 2186 2187 ph := newElfPhdr() 2188 ph.Type = elf.PT_MIPS_ABIFLAGS 2189 ph.Flags = elf.PF_R 2190 phsh(ph, sh) 2191 2192 sh = elfshname(".gnu.attributes") 2193 sh.Type = uint32(elf.SHT_GNU_ATTRIBUTES) 2194 sh.Addralign = 1 2195 ldr := ctxt.loader 2196 shsym(sh, ldr, ldr.Lookup(".gnu.attributes", 0)) 2197 } 2198 2199 // put these sections early in the list 2200 if !*FlagS { 2201 elfshname(".symtab") 2202 elfshname(".strtab") 2203 } 2204 elfshname(".shstrtab") 2205 2206 for _, sect := range Segtext.Sections { 2207 elfshbits(ctxt.LinkMode, sect) 2208 } 2209 for _, sect := range Segrodata.Sections { 2210 elfshbits(ctxt.LinkMode, sect) 2211 } 2212 for _, sect := range Segrelrodata.Sections { 2213 elfshbits(ctxt.LinkMode, sect) 2214 } 2215 for _, sect := range Segdata.Sections { 2216 elfshbits(ctxt.LinkMode, sect) 2217 } 2218 for _, sect := range Segdwarf.Sections { 2219 elfshbits(ctxt.LinkMode, sect) 2220 } 2221 2222 if ctxt.LinkMode == LinkExternal { 2223 for _, sect := range Segtext.Sections { 2224 elfshreloc(ctxt.Arch, sect) 2225 } 2226 for _, sect := range Segrodata.Sections { 2227 elfshreloc(ctxt.Arch, sect) 2228 } 2229 for _, sect := range Segrelrodata.Sections { 2230 elfshreloc(ctxt.Arch, sect) 2231 } 2232 for _, sect := range Segdata.Sections { 2233 elfshreloc(ctxt.Arch, sect) 2234 } 2235 for _, si := range dwarfp { 2236 sect := ldr.SymSect(si.secSym()) 2237 elfshreloc(ctxt.Arch, sect) 2238 } 2239 // add a .note.GNU-stack section to mark the stack as non-executable 2240 sh := elfshname(".note.GNU-stack") 2241 2242 sh.Type = uint32(elf.SHT_PROGBITS) 2243 sh.Addralign = 1 2244 sh.Flags = 0 2245 } 2246 2247 var shstroff uint64 2248 if !*FlagS { 2249 sh := elfshname(".symtab") 2250 sh.Type = uint32(elf.SHT_SYMTAB) 2251 sh.Off = uint64(symo) 2252 sh.Size = uint64(symSize) 2253 sh.Addralign = uint64(ctxt.Arch.RegSize) 2254 sh.Entsize = 8 + 2*uint64(ctxt.Arch.RegSize) 2255 sh.Link = uint32(elfshname(".strtab").shnum) 2256 sh.Info = uint32(elfglobalsymndx) 2257 2258 sh = elfshname(".strtab") 2259 sh.Type = uint32(elf.SHT_STRTAB) 2260 sh.Off = uint64(symo) + uint64(symSize) 2261 sh.Size = uint64(len(elfstrdat)) 2262 sh.Addralign = 1 2263 shstroff = sh.Off + sh.Size 2264 } else { 2265 shstroff = uint64(symo) 2266 } 2267 2268 sh = elfshname(".shstrtab") 2269 sh.Type = uint32(elf.SHT_STRTAB) 2270 sh.Off = shstroff 2271 sh.Size = uint64(len(elfshstrdat)) 2272 sh.Addralign = 1 2273 2274 /* Main header */ 2275 copy(eh.Ident[:], elf.ELFMAG) 2276 2277 var osabi elf.OSABI 2278 switch ctxt.HeadType { 2279 case objabi.Hfreebsd: 2280 osabi = elf.ELFOSABI_FREEBSD 2281 case objabi.Hnetbsd: 2282 osabi = elf.ELFOSABI_NETBSD 2283 case objabi.Hopenbsd: 2284 osabi = elf.ELFOSABI_OPENBSD 2285 case objabi.Hdragonfly: 2286 osabi = elf.ELFOSABI_NONE 2287 } 2288 eh.Ident[elf.EI_OSABI] = byte(osabi) 2289 2290 if elf64 { 2291 eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS64) 2292 } else { 2293 eh.Ident[elf.EI_CLASS] = byte(elf.ELFCLASS32) 2294 } 2295 if ctxt.Arch.ByteOrder == binary.BigEndian { 2296 eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2MSB) 2297 } else { 2298 eh.Ident[elf.EI_DATA] = byte(elf.ELFDATA2LSB) 2299 } 2300 eh.Ident[elf.EI_VERSION] = byte(elf.EV_CURRENT) 2301 2302 if ctxt.LinkMode == LinkExternal { 2303 eh.Type = uint16(elf.ET_REL) 2304 } else if ctxt.BuildMode == BuildModePIE { 2305 eh.Type = uint16(elf.ET_DYN) 2306 } else { 2307 eh.Type = uint16(elf.ET_EXEC) 2308 } 2309 2310 if ctxt.LinkMode != LinkExternal { 2311 eh.Entry = uint64(Entryvalue(ctxt)) 2312 } 2313 2314 eh.Version = uint32(elf.EV_CURRENT) 2315 2316 if pph != nil { 2317 pph.Filesz = uint64(eh.Phnum) * uint64(eh.Phentsize) 2318 pph.Memsz = pph.Filesz 2319 } 2320 2321 ctxt.Out.SeekSet(0) 2322 a := int64(0) 2323 a += int64(elfwritehdr(ctxt.Out)) 2324 a += int64(elfwritephdrs(ctxt.Out)) 2325 a += int64(elfwriteshdrs(ctxt.Out)) 2326 if !*FlagD { 2327 a += int64(elfwriteinterp(ctxt.Out)) 2328 } 2329 if ctxt.IsMIPS() { 2330 a += int64(elfWriteMipsAbiFlags(ctxt)) 2331 } 2332 2333 if ctxt.LinkMode != LinkExternal { 2334 if ctxt.HeadType == objabi.Hnetbsd { 2335 a += int64(elfwritenetbsdsig(ctxt.Out)) 2336 } 2337 if ctxt.HeadType == objabi.Hopenbsd { 2338 a += int64(elfwriteopenbsdsig(ctxt.Out)) 2339 } 2340 if ctxt.HeadType == objabi.Hfreebsd { 2341 a += int64(elfwritefreebsdsig(ctxt.Out)) 2342 } 2343 if len(buildinfo) > 0 { 2344 a += int64(elfwritebuildinfo(ctxt.Out)) 2345 } 2346 if *flagBuildid != "" { 2347 a += int64(elfwritegobuildid(ctxt.Out)) 2348 } 2349 } 2350 if *flagRace && ctxt.IsNetbsd() { 2351 a += int64(elfwritenetbsdpax(ctxt.Out)) 2352 } 2353 2354 if a > elfreserve { 2355 Errorf(nil, "ELFRESERVE too small: %d > %d with %d text sections", a, elfreserve, numtext) 2356 } 2357 2358 // Verify the amount of space allocated for the elf header is sufficient. The file offsets are 2359 // already computed in layout, so we could spill into another section. 2360 if a > int64(HEADR) { 2361 Errorf(nil, "HEADR too small: %d > %d with %d text sections", a, HEADR, numtext) 2362 } 2363 } 2364 2365 func elfadddynsym(ldr *loader.Loader, target *Target, syms *ArchSyms, s loader.Sym) { 2366 ldr.SetSymDynid(s, int32(Nelfsym)) 2367 Nelfsym++ 2368 d := ldr.MakeSymbolUpdater(syms.DynSym) 2369 name := ldr.SymExtname(s) 2370 dstru := ldr.MakeSymbolUpdater(syms.DynStr) 2371 st := ldr.SymType(s) 2372 cgoeStatic := ldr.AttrCgoExportStatic(s) 2373 cgoeDynamic := ldr.AttrCgoExportDynamic(s) 2374 cgoexp := (cgoeStatic || cgoeDynamic) 2375 2376 d.AddUint32(target.Arch, uint32(dstru.Addstring(name))) 2377 2378 if elf64 { 2379 2380 /* type */ 2381 var t uint8 2382 2383 if cgoexp && st == sym.STEXT { 2384 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC) 2385 } else { 2386 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT) 2387 } 2388 d.AddUint8(t) 2389 2390 /* reserved */ 2391 d.AddUint8(0) 2392 2393 /* section where symbol is defined */ 2394 if st == sym.SDYNIMPORT { 2395 d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF)) 2396 } else { 2397 d.AddUint16(target.Arch, 1) 2398 } 2399 2400 /* value */ 2401 if st == sym.SDYNIMPORT { 2402 d.AddUint64(target.Arch, 0) 2403 } else { 2404 d.AddAddrPlus(target.Arch, s, 0) 2405 } 2406 2407 /* size of object */ 2408 d.AddUint64(target.Arch, uint64(len(ldr.Data(s)))) 2409 2410 dil := ldr.SymDynimplib(s) 2411 2412 if !cgoeDynamic && dil != "" && !seenlib[dil] { 2413 du := ldr.MakeSymbolUpdater(syms.Dynamic) 2414 Elfwritedynent(target.Arch, du, elf.DT_NEEDED, uint64(dstru.Addstring(dil))) 2415 seenlib[dil] = true 2416 } 2417 } else { 2418 2419 /* value */ 2420 if st == sym.SDYNIMPORT { 2421 d.AddUint32(target.Arch, 0) 2422 } else { 2423 d.AddAddrPlus(target.Arch, s, 0) 2424 } 2425 2426 /* size of object */ 2427 d.AddUint32(target.Arch, uint32(len(ldr.Data(s)))) 2428 2429 /* type */ 2430 var t uint8 2431 2432 // TODO(mwhudson): presumably the behavior should actually be the same on both arm and 386. 2433 if target.Arch.Family == sys.I386 && cgoexp && st == sym.STEXT { 2434 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC) 2435 } else if target.Arch.Family == sys.ARM && cgoeDynamic && st == sym.STEXT { 2436 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_FUNC) 2437 } else { 2438 t = elf.ST_INFO(elf.STB_GLOBAL, elf.STT_OBJECT) 2439 } 2440 d.AddUint8(t) 2441 d.AddUint8(0) 2442 2443 /* shndx */ 2444 if st == sym.SDYNIMPORT { 2445 d.AddUint16(target.Arch, uint16(elf.SHN_UNDEF)) 2446 } else { 2447 d.AddUint16(target.Arch, 1) 2448 } 2449 } 2450 }