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