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