github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/cmd/link/internal/ld/xcoff.go (about) 1 // Copyright 2018 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 "bytes" 9 "cmd/internal/objabi" 10 "cmd/link/internal/sym" 11 "encoding/binary" 12 "strings" 13 ) 14 15 // This file handles all algorithms related to XCOFF files generation. 16 // Most of them are adaptations of the ones in cmd/link/internal/pe.go 17 // as PE and XCOFF are based on COFF files. 18 // XCOFF files generated are 64 bits. 19 20 const ( 21 // Total amount of space to reserve at the start of the file 22 // for File Header, Auxiliary Header, and Section Headers. 23 // May waste some. 24 XCOFFHDRRESERVE = FILHSZ_64 + AOUTHSZ_EXEC64 + SCNHSZ_64*23 25 XCOFFSECTALIGN int64 = 32 // base on dump -o 26 27 // XCOFF binaries should normally have all its sections position-independent. 28 // However, this is not yet possible for .text because of some R_ADDR relocations 29 // inside RODATA symbols. 30 // .data and .bss are position-independent so their address start inside a unreachable 31 // segment during execution to force segfault if something is wrong. 32 XCOFFTEXTBASE = 0x100000000 // Start of text address 33 XCOFFDATABASE = 0x200000000 // Start of data address 34 ) 35 36 // File Header 37 type XcoffFileHdr64 struct { 38 Fmagic uint16 // Target machine 39 Fnscns uint16 // Number of sections 40 Ftimedat int32 // Time and date of file creation 41 Fsymptr uint64 // Byte offset to symbol table start 42 Fopthdr uint16 // Number of bytes in optional header 43 Fflags uint16 // Flags 44 Fnsyms int32 // Number of entries in symbol table 45 } 46 47 const ( 48 U64_TOCMAGIC = 0767 // AIX 64-bit XCOFF 49 ) 50 51 // Flags that describe the type of the object file. 52 const ( 53 F_RELFLG = 0x0001 54 F_EXEC = 0x0002 55 F_LNNO = 0x0004 56 F_FDPR_PROF = 0x0010 57 F_FDPR_OPTI = 0x0020 58 F_DSA = 0x0040 59 F_VARPG = 0x0100 60 F_DYNLOAD = 0x1000 61 F_SHROBJ = 0x2000 62 F_LOADONLY = 0x4000 63 ) 64 65 // Auxiliary Header 66 type XcoffAoutHdr64 struct { 67 Omagic int16 // Flags - Ignored If Vstamp Is 1 68 Ovstamp int16 // Version 69 Odebugger uint32 // Reserved For Debugger 70 Otextstart uint64 // Virtual Address Of Text 71 Odatastart uint64 // Virtual Address Of Data 72 Otoc uint64 // Toc Address 73 Osnentry int16 // Section Number For Entry Point 74 Osntext int16 // Section Number For Text 75 Osndata int16 // Section Number For Data 76 Osntoc int16 // Section Number For Toc 77 Osnloader int16 // Section Number For Loader 78 Osnbss int16 // Section Number For Bss 79 Oalgntext int16 // Max Text Alignment 80 Oalgndata int16 // Max Data Alignment 81 Omodtype [2]byte // Module Type Field 82 Ocpuflag uint8 // Bit Flags - Cputypes Of Objects 83 Ocputype uint8 // Reserved for CPU type 84 Otextpsize uint8 // Requested text page size 85 Odatapsize uint8 // Requested data page size 86 Ostackpsize uint8 // Requested stack page size 87 Oflags uint8 // Flags And TLS Alignment 88 Otsize uint64 // Text Size In Bytes 89 Odsize uint64 // Data Size In Bytes 90 Obsize uint64 // Bss Size In Bytes 91 Oentry uint64 // Entry Point Address 92 Omaxstack uint64 // Max Stack Size Allowed 93 Omaxdata uint64 // Max Data Size Allowed 94 Osntdata int16 // Section Number For Tdata Section 95 Osntbss int16 // Section Number For Tbss Section 96 Ox64flags uint16 // Additional Flags For 64-Bit Objects 97 Oresv3a int16 // Reserved 98 Oresv3 [2]int32 // Reserved 99 100 } 101 102 // Section Header 103 type XcoffScnHdr64 struct { 104 Sname [8]byte // Section Name 105 Spaddr uint64 // Physical Address 106 Svaddr uint64 // Virtual Address 107 Ssize uint64 // Section Size 108 Sscnptr uint64 // File Offset To Raw Data 109 Srelptr uint64 // File Offset To Relocation 110 Slnnoptr uint64 // File Offset To Line Numbers 111 Snreloc uint32 // Number Of Relocation Entries 112 Snlnno uint32 // Number Of Line Number Entries 113 Sflags uint32 // flags 114 } 115 116 // Flags defining the section type. 117 const ( 118 STYP_DWARF = 0x0010 119 STYP_TEXT = 0x0020 120 STYP_DATA = 0x0040 121 STYP_BSS = 0x0080 122 STYP_EXCEPT = 0x0100 123 STYP_INFO = 0x0200 124 STYP_TDATA = 0x0400 125 STYP_TBSS = 0x0800 126 STYP_LOADER = 0x1000 127 STYP_DEBUG = 0x2000 128 STYP_TYPCHK = 0x4000 129 STYP_OVRFLO = 0x8000 130 ) 131 const ( 132 SSUBTYP_DWINFO = 0x10000 // DWARF info section 133 SSUBTYP_DWLINE = 0x20000 // DWARF line-number section 134 SSUBTYP_DWPBNMS = 0x30000 // DWARF public names section 135 SSUBTYP_DWPBTYP = 0x40000 // DWARF public types section 136 SSUBTYP_DWARNGE = 0x50000 // DWARF aranges section 137 SSUBTYP_DWABREV = 0x60000 // DWARF abbreviation section 138 SSUBTYP_DWSTR = 0x70000 // DWARF strings section 139 SSUBTYP_DWRNGES = 0x80000 // DWARF ranges section 140 SSUBTYP_DWLOC = 0x90000 // DWARF location lists section 141 SSUBTYP_DWFRAME = 0xA0000 // DWARF frames section 142 SSUBTYP_DWMAC = 0xB0000 // DWARF macros section 143 ) 144 145 // Headers size 146 const ( 147 FILHSZ_32 = 20 148 FILHSZ_64 = 24 149 AOUTHSZ_EXEC32 = 72 150 AOUTHSZ_EXEC64 = 120 151 SCNHSZ_32 = 40 152 SCNHSZ_64 = 72 153 LDHDRSZ_32 = 32 154 LDHDRSZ_64 = 56 155 LDSYMSZ_64 = 24 156 ) 157 158 // Symbol Table Entry 159 type XcoffSymEnt64 struct { 160 Nvalue uint64 // Symbol value 161 Noffset uint32 // Offset of the name in string table or .debug section 162 Nscnum int16 // Section number of symbol 163 Ntype uint16 // Basic and derived type specification 164 Nsclass uint8 // Storage class of symbol 165 Nnumaux int8 // Number of auxiliary entries 166 } 167 168 const SYMESZ = 18 169 170 const ( 171 // Nscnum 172 N_DEBUG = -2 173 N_ABS = -1 174 N_UNDEF = 0 175 176 //Ntype 177 SYM_V_INTERNAL = 0x1000 178 SYM_V_HIDDEN = 0x2000 179 SYM_V_PROTECTED = 0x3000 180 SYM_V_EXPORTED = 0x4000 181 SYM_TYPE_FUNC = 0x0020 // is function 182 ) 183 184 // Storage Class. 185 const ( 186 C_NULL = 0 // Symbol table entry marked for deletion 187 C_EXT = 2 // External symbol 188 C_STAT = 3 // Static symbol 189 C_BLOCK = 100 // Beginning or end of inner block 190 C_FCN = 101 // Beginning or end of function 191 C_FILE = 103 // Source file name and compiler information 192 C_HIDEXT = 107 // Unnamed external symbol 193 C_BINCL = 108 // Beginning of include file 194 C_EINCL = 109 // End of include file 195 C_WEAKEXT = 111 // Weak external symbol 196 C_DWARF = 112 // DWARF symbol 197 C_GSYM = 128 // Global variable 198 C_LSYM = 129 // Automatic variable allocated on stack 199 C_PSYM = 130 // Argument to subroutine allocated on stack 200 C_RSYM = 131 // Register variable 201 C_RPSYM = 132 // Argument to function or procedure stored in register 202 C_STSYM = 133 // Statically allocated symbol 203 C_BCOMM = 135 // Beginning of common block 204 C_ECOML = 136 // Local member of common block 205 C_ECOMM = 137 // End of common block 206 C_DECL = 140 // Declaration of object 207 C_ENTRY = 141 // Alternate entry 208 C_FUN = 142 // Function or procedure 209 C_BSTAT = 143 // Beginning of static block 210 C_ESTAT = 144 // End of static block 211 C_GTLS = 145 // Global thread-local variable 212 C_STTLS = 146 // Static thread-local variable 213 ) 214 215 // File Auxiliary Entry 216 type XcoffAuxFile64 struct { 217 Xfname [8]byte // Name or offset inside string table 218 Xftype uint8 // Source file string type 219 Xauxtype uint8 // Type of auxiliary entry 220 } 221 222 // Function Auxiliary Entry 223 type XcoffAuxFcn64 struct { 224 Xlnnoptr uint64 // File pointer to line number 225 Xfsize uint32 // Size of function in bytes 226 Xendndx uint32 // Symbol table index of next entry 227 Xpad uint8 // Unused 228 Xauxtype uint8 // Type of auxiliary entry 229 } 230 231 // csect Auxiliary Entry. 232 type XcoffAuxCSect64 struct { 233 Xscnlenlo uint32 // Lower 4 bytes of length or symbol table index 234 Xparmhash uint32 // Offset of parameter type-check string 235 Xsnhash uint16 // .typchk section number 236 Xsmtyp uint8 // Symbol alignment and type 237 Xsmclas uint8 // Storage-mapping class 238 Xscnlenhi uint32 // Upper 4 bytes of length or symbol table index 239 Xpad uint8 // Unused 240 Xauxtype uint8 // Type of auxiliary entry 241 } 242 243 // Auxiliary type 244 const ( 245 _AUX_EXCEPT = 255 246 _AUX_FCN = 254 247 _AUX_SYM = 253 248 _AUX_FILE = 252 249 _AUX_CSECT = 251 250 _AUX_SECT = 250 251 ) 252 253 // Xftype field 254 const ( 255 XFT_FN = 0 // Source File Name 256 XFT_CT = 1 // Compile Time Stamp 257 XFT_CV = 2 // Compiler Version Number 258 XFT_CD = 128 // Compiler Defined Information/ 259 260 ) 261 262 // Symbol type field. 263 const ( 264 XTY_ER = 0 // External reference 265 XTY_SD = 1 // Section definition 266 XTY_LD = 2 // Label definition 267 XTY_CM = 3 // Common csect definition 268 XTY_WK = 0x8 // Weak symbol 269 XTY_EXP = 0x10 // Exported symbol 270 XTY_ENT = 0x20 // Entry point symbol 271 XTY_IMP = 0x40 // Imported symbol 272 ) 273 274 // Storage-mapping class. 275 const ( 276 XMC_PR = 0 // Program code 277 XMC_RO = 1 // Read-only constant 278 XMC_DB = 2 // Debug dictionary table 279 XMC_TC = 3 // TOC entry 280 XMC_UA = 4 // Unclassified 281 XMC_RW = 5 // Read/Write data 282 XMC_GL = 6 // Global linkage 283 XMC_XO = 7 // Extended operation 284 XMC_SV = 8 // 32-bit supervisor call descriptor 285 XMC_BS = 9 // BSS class 286 XMC_DS = 10 // Function descriptor 287 XMC_UC = 11 // Unnamed FORTRAN common 288 XMC_TC0 = 15 // TOC anchor 289 XMC_TD = 16 // Scalar data entry in the TOC 290 XMC_SV64 = 17 // 64-bit supervisor call descriptor 291 XMC_SV3264 = 18 // Supervisor call descriptor for both 32-bit and 64-bit 292 XMC_TL = 20 // Read/Write thread-local data 293 XMC_UL = 21 // Read/Write thread-local data (.tbss) 294 XMC_TE = 22 // TOC entry 295 ) 296 297 // Loader Header 298 type XcoffLdHdr64 struct { 299 Lversion int32 // Loader section version number 300 Lnsyms int32 // Number of symbol table entries 301 Lnreloc int32 // Number of relocation table entries 302 Listlen uint32 // Length of import file ID string table 303 Lnimpid int32 // Number of import file IDs 304 Lstlen uint32 // Length of string table 305 Limpoff uint64 // Offset to start of import file IDs 306 Lstoff uint64 // Offset to start of string table 307 Lsymoff uint64 // Offset to start of symbol table 308 Lrldoff uint64 // Offset to start of relocation entries 309 } 310 311 // Loader Symbol 312 type XcoffLdSym64 struct { 313 Lvalue uint64 // Address field 314 Loffset uint32 // Byte offset into string table of symbol name 315 Lscnum int16 // Section number containing symbol 316 Lsmtype int8 // Symbol type, export, import flags 317 Lsmclas int8 // Symbol storage class 318 Lifile int32 // Import file ID; ordinal of import file IDs 319 Lparm uint32 // Parameter type-check field 320 } 321 322 type xcoffLoaderSymbol struct { 323 sym *sym.Symbol 324 smtype int8 325 smclas int8 326 } 327 328 type XcoffLdImportFile64 struct { 329 Limpidpath string 330 Limpidbase string 331 Limpidmem string 332 } 333 334 type XcoffLdRel64 struct { 335 Lvaddr uint64 // Address Field 336 Lrtype uint16 // Relocation Size and Type 337 Lrsecnm int16 // Section Number being relocated 338 Lsymndx int32 // Loader-Section symbol table index 339 } 340 341 // xcoffLoaderReloc holds information about a relocation made by the loader. 342 type xcoffLoaderReloc struct { 343 sym *sym.Symbol 344 rel *sym.Reloc 345 rtype uint16 346 symndx int32 347 } 348 349 const ( 350 XCOFF_R_POS = 0x00 // A(sym) Positive Relocation 351 ) 352 353 type XcoffLdStr64 struct { 354 size uint16 355 name string 356 } 357 358 // xcoffFile is used to build XCOFF file. 359 type xcoffFile struct { 360 xfhdr XcoffFileHdr64 361 xahdr XcoffAoutHdr64 362 sections []*XcoffScnHdr64 363 stringTable xcoffStringTable 364 sectNameToScnum map[string]int16 365 loaderSize uint64 366 symtabOffset int64 // offset to the start of symbol table 367 symbolCount uint32 // number of symbol table records written 368 dynLibraries map[string]int // Dynamic libraries in .loader section. The integer represents its import file number (- 1) 369 loaderSymbols []*xcoffLoaderSymbol // symbols inside .loader symbol table 370 loaderReloc []*xcoffLoaderReloc // Reloc that must be made inside loader 371 } 372 373 // Var used by XCOFF Generation algorithms 374 var ( 375 xfile xcoffFile 376 ) 377 378 // xcoffStringTable is a XCOFF string table. 379 type xcoffStringTable struct { 380 strings []string 381 stringsLen int 382 } 383 384 // size returns size of string table t. 385 func (t *xcoffStringTable) size() int { 386 // string table starts with 4-byte length at the beginning 387 return t.stringsLen + 4 388 } 389 390 // add adds string str to string table t. 391 func (t *xcoffStringTable) add(str string) int { 392 off := t.size() 393 t.strings = append(t.strings, str) 394 t.stringsLen += len(str) + 1 // each string will have 0 appended to it 395 return off 396 } 397 398 // write writes string table t into the output file. 399 func (t *xcoffStringTable) write(out *OutBuf) { 400 out.Write32(uint32(t.size())) 401 for _, s := range t.strings { 402 out.WriteString(s) 403 out.Write8(0) 404 } 405 } 406 407 // write writes XCOFF section sect into the output file. 408 func (sect *XcoffScnHdr64) write(ctxt *Link) { 409 binary.Write(ctxt.Out, binary.BigEndian, sect) 410 ctxt.Out.Write32(0) // Add 4 empty bytes at the end to match alignment 411 } 412 413 // addSection adds section to the XCOFF file f. 414 func (f *xcoffFile) addSection(name string, addr uint64, size uint64, fileoff uint64, flags uint32) *XcoffScnHdr64 { 415 sect := &XcoffScnHdr64{ 416 Spaddr: addr, 417 Svaddr: addr, 418 Ssize: size, 419 Sscnptr: fileoff, 420 Sflags: flags, 421 } 422 copy(sect.Sname[:], name) // copy string to [8]byte 423 f.sections = append(f.sections, sect) 424 f.sectNameToScnum[name] = int16(len(f.sections)) 425 return sect 426 } 427 428 // addDwarfSection adds a dwarf section to the XCOFF file f. 429 // This function is similar to addSection, but Dwarf section names 430 // must be modified to conventional names and they are various subtypes. 431 func (f *xcoffFile) addDwarfSection(s *sym.Section) *XcoffScnHdr64 { 432 newName, subtype := xcoffGetDwarfSubtype(s.Name) 433 return f.addSection(newName, 0, s.Length, s.Seg.Fileoff+s.Vaddr-s.Seg.Vaddr, STYP_DWARF|subtype) 434 } 435 436 // xcoffGetDwarfSubtype returns the XCOFF name of the DWARF section str 437 // and its subtype constant. 438 func xcoffGetDwarfSubtype(str string) (string, uint32) { 439 switch str { 440 default: 441 Exitf("unknown DWARF section name for XCOFF: %s", str) 442 case ".debug_abbrev": 443 return ".dwabrev", SSUBTYP_DWABREV 444 case ".debug_info": 445 return ".dwinfo", SSUBTYP_DWINFO 446 case ".debug_frame": 447 return ".dwframe", SSUBTYP_DWFRAME 448 case ".debug_line": 449 return ".dwline", SSUBTYP_DWLINE 450 case ".debug_loc": 451 return ".dwloc", SSUBTYP_DWLOC 452 case ".debug_pubnames": 453 return ".dwpbnms", SSUBTYP_DWPBNMS 454 case ".debug_pubtypes": 455 return ".dwpbtyp", SSUBTYP_DWPBTYP 456 case ".debug_ranges": 457 return ".dwrnge", SSUBTYP_DWRNGES 458 } 459 // never used 460 return "", 0 461 } 462 463 // getXCOFFscnum returns the XCOFF section number of a Go section. 464 func (f *xcoffFile) getXCOFFscnum(sect *sym.Section) int16 { 465 switch sect.Seg { 466 case &Segtext: 467 return f.sectNameToScnum[".text"] 468 case &Segdata: 469 if sect.Name == ".noptrdata" || sect.Name == ".data" { 470 return f.sectNameToScnum[".data"] 471 } 472 if sect.Name == ".noptrbss" || sect.Name == ".bss" { 473 return f.sectNameToScnum[".bss"] 474 } 475 Errorf(nil, "unknown XCOFF segment data section: %s", sect.Name) 476 case &Segdwarf: 477 name, _ := xcoffGetDwarfSubtype(sect.Name) 478 return f.sectNameToScnum[name] 479 } 480 Errorf(nil, "getXCOFFscnum not implemented for section %s", sect.Name) 481 return -1 482 } 483 484 // Xcoffinit initialised some internal value and setups 485 // already known header information 486 func Xcoffinit(ctxt *Link) { 487 xfile.dynLibraries = make(map[string]int) 488 489 HEADR = int32(Rnd(XCOFFHDRRESERVE, XCOFFSECTALIGN)) 490 if *FlagTextAddr != -1 { 491 Errorf(nil, "-T not available on AIX") 492 } 493 *FlagTextAddr = XCOFFTEXTBASE + int64(HEADR) 494 *FlagDataAddr = 0 495 if *FlagRound != -1 { 496 Errorf(nil, "-R not available on AIX") 497 } 498 *FlagRound = int(XCOFFSECTALIGN) 499 500 } 501 502 // SYMBOL TABLE 503 504 // type records C_FILE information needed for genasmsym in XCOFF. 505 type xcoffSymSrcFile struct { 506 name string 507 fileSymNb uint32 // Symbol number of this C_FILE 508 csectSymNb uint64 // Symbol number for the current .csect 509 csectSize int64 510 } 511 512 var ( 513 currDwscnoff = make(map[string]uint64) // Needed to create C_DWARF symbols 514 currSymSrcFile xcoffSymSrcFile 515 ) 516 517 // writeSymbol writes a symbol or an auxiliary symbol entry on ctxt.out. 518 func (f *xcoffFile) writeSymbol(out *OutBuf, byteOrder binary.ByteOrder, sym interface{}) { 519 binary.Write(out, byteOrder, sym) 520 f.symbolCount++ 521 } 522 523 // Write symbols needed when a new file appared : 524 // - a C_FILE with one auxiliary entry for its name 525 // - C_DWARF symbols to provide debug information 526 // - a C_HIDEXT which will be a csect containing all of its functions 527 // It needs several parameters to create .csect symbols such as its entry point and its section number. 528 // 529 // Currently, a new file is in fact a new package. It seems to be OK, but it might change 530 // in the future. 531 func (f *xcoffFile) writeSymbolNewFile(ctxt *Link, name string, firstEntry uint64, extnum int16) { 532 /* C_FILE */ 533 s := &XcoffSymEnt64{ 534 Noffset: uint32(f.stringTable.add(".file")), 535 Nsclass: C_FILE, 536 Nscnum: N_DEBUG, 537 Ntype: 0, // Go isn't inside predefined language. 538 Nnumaux: 1, 539 } 540 f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s) 541 542 // Auxiliary entry for file name. 543 ctxt.Out.Write32(0) 544 ctxt.Out.Write32(uint32(f.stringTable.add(name))) 545 ctxt.Out.Write32(0) // 6 bytes empty 546 ctxt.Out.Write16(0) 547 ctxt.Out.Write8(XFT_FN) 548 ctxt.Out.Write16(0) // 2 bytes empty 549 ctxt.Out.Write8(_AUX_FILE) 550 f.symbolCount++ 551 552 /* Dwarf */ 553 for _, sect := range Segdwarf.Sections { 554 // Find the size of this corresponding package DWARF compilation unit. 555 // This size is set during DWARF generation (see dwarf.go). 556 dwsize := getDwsectCUSize(sect.Name, name) 557 // .debug_abbrev is commun to all packages and not found with the previous function 558 if sect.Name == ".debug_abbrev" { 559 s := ctxt.Syms.Lookup(sect.Name, 0) 560 dwsize = uint64(s.Size) 561 } 562 563 // get XCOFF name 564 name, _ := xcoffGetDwarfSubtype(sect.Name) 565 s := &XcoffSymEnt64{ 566 Nvalue: currDwscnoff[sect.Name], 567 Noffset: uint32(f.stringTable.add(name)), 568 Nsclass: C_DWARF, 569 Nscnum: f.getXCOFFscnum(sect), 570 Nnumaux: 1, 571 } 572 f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s) 573 574 // update the DWARF section offset in this file 575 if sect.Name != ".debug_abbrev" { 576 currDwscnoff[sect.Name] += dwsize 577 } 578 579 // Auxiliary dwarf section 580 ctxt.Out.Write64(dwsize) // section length 581 ctxt.Out.Write64(0) // nreloc 582 ctxt.Out.Write8(0) // pad 583 ctxt.Out.Write8(_AUX_SECT) 584 f.symbolCount++ 585 } 586 587 /* .csect */ 588 // Check if extnum is in text. 589 // This is temporary and only here to check if this algorithm is correct. 590 if extnum != 1 { 591 Exitf("XCOFF symtab: A new file was detected with its first symbol not in .text") 592 } 593 594 currSymSrcFile.csectSymNb = uint64(f.symbolCount) 595 currSymSrcFile.csectSize = 0 596 597 // No offset because no name 598 s = &XcoffSymEnt64{ 599 Nvalue: firstEntry, 600 Nscnum: extnum, 601 Nsclass: C_HIDEXT, 602 Ntype: 0, // check visibility ? 603 Nnumaux: 1, 604 } 605 f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s) 606 607 aux := &XcoffAuxCSect64{ 608 Xsmclas: XMC_PR, 609 Xsmtyp: XTY_SD | 5<<3, // align = 5 610 Xauxtype: _AUX_CSECT, 611 } 612 f.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, aux) 613 614 } 615 616 // Update values for the previous package. 617 // - Svalue of the C_FILE symbol: if it is the last one, this Svalue must be -1 618 // - Xsclen of the csect symbol. 619 func (f *xcoffFile) updatePreviousFile(ctxt *Link, last bool) { 620 // first file 621 if currSymSrcFile.fileSymNb == 0 { 622 return 623 } 624 625 prevOff := f.symtabOffset + int64(currSymSrcFile.fileSymNb*SYMESZ) 626 currOff := ctxt.Out.Offset() 627 628 // Update C_FILE 629 ctxt.Out.SeekSet(prevOff) 630 if last { 631 ctxt.Out.Write64(0xFFFFFFFFFFFFFFFF) 632 } else { 633 ctxt.Out.Write64(uint64(f.symbolCount)) 634 } 635 636 // update csect scnlen in this auxiliary entry 637 prevOff = f.symtabOffset + int64((currSymSrcFile.csectSymNb+1)*SYMESZ) 638 ctxt.Out.SeekSet(prevOff) 639 ctxt.Out.Write32(uint32(currSymSrcFile.csectSize & 0xFFFFFFFF)) 640 prevOff += 12 641 ctxt.Out.SeekSet(prevOff) 642 ctxt.Out.Write32(uint32(currSymSrcFile.csectSize >> 32)) 643 644 ctxt.Out.SeekSet(currOff) 645 646 } 647 648 // Write symbol representing a .text function. 649 // The symbol table is split with C_FILE corresponding to each package 650 // and not to each source file as it should be. 651 func (f *xcoffFile) writeSymbolFunc(ctxt *Link, x *sym.Symbol) []interface{} { 652 // New XCOFF symbols which will be written. 653 syms := []interface{}{} 654 655 // Check if a new file is detected. 656 if x.File == "" { // Undefined global symbol 657 // If this happens, the algorithme must be redone. 658 if currSymSrcFile.name != "" { 659 Exitf("undefined global symbol found inside another file") 660 } 661 } else { 662 // Current file has changed. New C_FILE, C_DWARF, etc must be generated. 663 if currSymSrcFile.name != x.File { 664 // update previous file values 665 xfile.updatePreviousFile(ctxt, false) 666 currSymSrcFile.name = x.File 667 currSymSrcFile.fileSymNb = f.symbolCount 668 f.writeSymbolNewFile(ctxt, x.File, uint64(x.Value), xfile.getXCOFFscnum(x.Sect)) 669 } 670 } 671 672 s := &XcoffSymEnt64{ 673 Nsclass: C_EXT, 674 Noffset: uint32(xfile.stringTable.add(x.Name)), 675 Nvalue: uint64(x.Value), 676 Nscnum: f.getXCOFFscnum(x.Sect), 677 Ntype: SYM_TYPE_FUNC, 678 Nnumaux: 2, 679 } 680 681 if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() { 682 s.Nsclass = C_HIDEXT 683 } 684 685 syms = append(syms, s) 686 687 // Update current csect size 688 currSymSrcFile.csectSize += x.Size 689 690 // create auxiliary entries 691 a2 := &XcoffAuxFcn64{ 692 Xfsize: uint32(x.Size), 693 Xlnnoptr: 0, // TODO 694 Xendndx: xfile.symbolCount + 3, // this symbol + 2 aux entries 695 Xauxtype: _AUX_FCN, 696 } 697 syms = append(syms, a2) 698 699 a4 := &XcoffAuxCSect64{ 700 Xscnlenlo: uint32(currSymSrcFile.csectSymNb & 0xFFFFFFFF), 701 Xscnlenhi: uint32(currSymSrcFile.csectSymNb >> 32), 702 Xsmclas: XMC_PR, // Program Code 703 Xsmtyp: XTY_LD, // label definition (based on C) 704 Xauxtype: _AUX_CSECT, 705 } 706 syms = append(syms, a4) 707 return syms 708 } 709 710 // put function used by genasmsym to write symbol table 711 func putaixsym(ctxt *Link, x *sym.Symbol, str string, t SymbolType, addr int64, go_ *sym.Symbol) { 712 713 // All XCOFF symbols generated by this GO symbols 714 // Can be a symbol entry or a auxiliary entry 715 syms := []interface{}{} 716 717 switch t { 718 default: 719 return 720 721 case TextSym: 722 if x.FuncInfo != nil { 723 // Function within a file 724 syms = xfile.writeSymbolFunc(ctxt, x) 725 } else { 726 // Only runtime.text and runtime.etext come through this way 727 if x.Name != "runtime.text" && x.Name != "runtime.etext" && x.Name != "go.buildid" { 728 Exitf("putaixsym: unknown text symbol %s", x.Name) 729 } 730 s := &XcoffSymEnt64{ 731 Nsclass: C_HIDEXT, 732 Noffset: uint32(xfile.stringTable.add(str)), 733 Nvalue: uint64(x.Value), 734 Nscnum: xfile.getXCOFFscnum(x.Sect), 735 Ntype: SYM_TYPE_FUNC, 736 Nnumaux: 1, 737 } 738 syms = append(syms, s) 739 740 size := uint64(x.Size) 741 a4 := &XcoffAuxCSect64{ 742 Xauxtype: _AUX_CSECT, 743 Xscnlenlo: uint32(size & 0xFFFFFFFF), 744 Xscnlenhi: uint32(size >> 32), 745 Xsmclas: XMC_PR, 746 Xsmtyp: XTY_SD, 747 } 748 syms = append(syms, a4) 749 750 } 751 752 case DataSym, BSSSym: 753 s := &XcoffSymEnt64{ 754 Nsclass: C_EXT, 755 Noffset: uint32(xfile.stringTable.add(str)), 756 Nvalue: uint64(x.Value), 757 Nscnum: xfile.getXCOFFscnum(x.Sect), 758 Nnumaux: 1, 759 } 760 761 if x.Version != 0 || x.Attr.VisibilityHidden() || x.Attr.Local() { 762 // There is more symbols in the case of a global data 763 // which are related to the assembly generated 764 // to access such symbols. 765 // But as Golang as its own way to check if a symbol is 766 // global or local (the capital letter), we don't need to 767 // implement them yet. 768 s.Nsclass = C_HIDEXT 769 } 770 771 syms = append(syms, s) 772 773 // Create auxiliary entry 774 775 // Normally, size should be the size of csect containing all 776 // the data and bss symbols of one file/package. 777 // However, it's easier to just have a csect for each symbol. 778 // It might change 779 size := uint64(x.Size) 780 a4 := &XcoffAuxCSect64{ 781 Xauxtype: _AUX_CSECT, 782 Xscnlenlo: uint32(size & 0xFFFFFFFF), 783 Xscnlenhi: uint32(size >> 32), 784 } 785 // Read only data 786 if x.Type >= sym.STYPE && x.Type <= sym.SPCLNTAB { 787 a4.Xsmclas = XMC_RO 788 } else { 789 a4.Xsmclas = XMC_RW 790 } 791 if t == DataSym { 792 a4.Xsmtyp |= XTY_SD 793 } else { 794 a4.Xsmtyp |= XTY_CM 795 } 796 797 syms = append(syms, a4) 798 799 case UndefinedSym: 800 if x.Type != sym.SDYNIMPORT && x.Type != sym.SHOSTOBJ { 801 return 802 } 803 s := &XcoffSymEnt64{ 804 Nsclass: C_EXT, 805 Noffset: uint32(xfile.stringTable.add(str)), 806 Nnumaux: 1, 807 } 808 syms = append(syms, s) 809 810 a4 := &XcoffAuxCSect64{ 811 Xauxtype: _AUX_CSECT, 812 Xsmclas: XMC_DS, 813 Xsmtyp: XTY_ER | XTY_IMP, 814 } 815 816 if x.Name == "__n_pthreads" { 817 // Currently, all imported symbols made by cgo_import_dynamic are 818 // syscall functions, except __n_pthreads which is a variable. 819 // TODO(aix): Find a way to detect variables imported by cgo. 820 a4.Xsmclas = XMC_RW 821 } 822 823 syms = append(syms, a4) 824 } 825 826 for _, s := range syms { 827 xfile.writeSymbol(ctxt.Out, ctxt.Arch.ByteOrder, s) 828 } 829 } 830 831 // Generate XCOFF Symbol table and XCOFF String table 832 func (f *xcoffFile) asmaixsym(ctxt *Link) { 833 // write symbol table 834 genasmsym(ctxt, putaixsym) 835 836 // update last file Svalue 837 xfile.updatePreviousFile(ctxt, true) 838 839 // write string table 840 xfile.stringTable.write(ctxt.Out) 841 } 842 843 func (f *xcoffFile) genDynSym(ctxt *Link) { 844 var dynsyms []*sym.Symbol 845 for _, s := range ctxt.Syms.Allsym { 846 if s.Type != sym.SHOSTOBJ && s.Type != sym.SDYNIMPORT { 847 continue 848 } 849 dynsyms = append(dynsyms, s) 850 } 851 852 for _, s := range dynsyms { 853 f.adddynimpsym(ctxt, s) 854 855 if _, ok := f.dynLibraries[s.Dynimplib()]; !ok { 856 f.dynLibraries[s.Dynimplib()] = len(f.dynLibraries) 857 } 858 859 } 860 861 } 862 863 // (*xcoffFile)adddynimpsym adds the dynamic symbol "s" to a XCOFF file. 864 // A new symbol named s.Extname() is created to be the actual dynamic symbol 865 // in the .loader section and in the symbol table as an External Reference. 866 // The symbol "s" is transformed to SXCOFFTOC to end up in .data section. 867 // However, there is no writing protection on those symbols and 868 // it might need to be added. 869 // TODO(aix): Handles dynamic symbols without library. 870 func (f *xcoffFile) adddynimpsym(ctxt *Link, s *sym.Symbol) { 871 // Check that library name is given. 872 // Pattern is already checked when compiling. 873 if s.Dynimplib() == "" { 874 Errorf(s, "imported symbol must have a given library") 875 } 876 877 s.Type = sym.SXCOFFTOC 878 879 // Create new dynamic symbol 880 extsym := ctxt.Syms.Lookup(s.Extname(), 0) 881 extsym.Type = sym.SDYNIMPORT 882 extsym.Attr |= sym.AttrReachable 883 extsym.SetDynimplib(s.Dynimplib()) 884 extsym.SetExtname(s.Extname()) 885 extsym.SetDynimpvers(s.Dynimpvers()) 886 887 // Add loader symbol 888 lds := &xcoffLoaderSymbol{ 889 sym: extsym, 890 smtype: XTY_IMP, 891 smclas: XMC_DS, 892 } 893 if s.Name == "__n_pthreads" { 894 // Currently, all imported symbols made by cgo_import_dynamic are 895 // syscall functions, except __n_pthreads which is a variable. 896 // TODO(aix): Find a way to detect variables imported by cgo. 897 lds.smclas = XMC_RW 898 } 899 f.loaderSymbols = append(f.loaderSymbols, lds) 900 901 // Relocation to retrieve the external address 902 s.AddBytes(make([]byte, 8)) 903 s.SetAddr(ctxt.Arch, 0, extsym) 904 905 } 906 907 // Xcoffadddynrel adds a dynamic relocation in a XCOFF file. 908 // This relocation will be made by the loader. 909 func Xcoffadddynrel(ctxt *Link, s *sym.Symbol, r *sym.Reloc) bool { 910 if s.Type <= sym.SPCLNTAB { 911 Errorf(s, "cannot have a relocation to %s in a text section symbol", r.Sym.Name) 912 return false 913 } 914 915 ldr := &xcoffLoaderReloc{ 916 sym: s, 917 rel: r, 918 } 919 920 switch r.Type { 921 default: 922 Errorf(s, "unexpected .loader relocation to symbol: %s (type: %s)", r.Sym.Name, r.Type.String()) 923 return false 924 case objabi.R_ADDR: 925 if s.Type == sym.SXCOFFTOC && r.Sym.Type == sym.SDYNIMPORT { 926 // Imported symbol relocation 927 for i, dynsym := range xfile.loaderSymbols { 928 if dynsym.sym.Name == r.Sym.Name { 929 ldr.symndx = int32(i + 3) // +3 because of 3 section symbols 930 break 931 } 932 } 933 } else if s.Type == sym.SDATA { 934 switch r.Sym.Sect.Seg { 935 default: 936 Errorf(s, "unknown segment for .loader relocation with symbol %s", r.Sym.Name) 937 case &Segtext: 938 case &Segrodata: 939 ldr.symndx = 0 // .text 940 case &Segdata: 941 if r.Sym.Type == sym.SBSS || r.Sym.Type == sym.SNOPTRBSS { 942 ldr.symndx = 2 // .bss 943 } else { 944 ldr.symndx = 1 // .data 945 } 946 947 } 948 949 } else { 950 Errorf(s, "unexpected type for .loader relocation R_ADDR for symbol %s: %s to %s", r.Sym.Name, s.Type, r.Sym.Type) 951 return false 952 } 953 954 ldr.rtype = 0x3F<<8 + XCOFF_R_POS 955 } 956 957 xfile.loaderReloc = append(xfile.loaderReloc, ldr) 958 return true 959 } 960 961 func (ctxt *Link) doxcoff() { 962 if *FlagD { 963 // All XCOFF files have dynamic symbols because of the syscalls. 964 Exitf("-d is not available on AIX") 965 } 966 967 // Initial map used to store compilation unit size for each DWARF section (see dwarf.go). 968 dwsectCUSize = make(map[string]uint64) 969 970 // TOC 971 toc := ctxt.Syms.Lookup("TOC", 0) 972 toc.Type = sym.SXCOFFTOC 973 toc.Attr |= sym.AttrReachable 974 975 // XCOFF does not allow relocations of data symbol address to a text symbol. 976 // Such case occurs when a RODATA symbol retrieves a data symbol address. 977 // When it happens, this RODATA symbol is moved to .data section. 978 // runtime.algarray is a readonly symbol but stored inside .data section. 979 // If it stays in .data, all type symbols will be moved to .data which 980 // cannot be done. 981 algarray := ctxt.Syms.Lookup("runtime.algarray", 0) 982 algarray.Type = sym.SRODATA 983 for { 984 again := false 985 for _, s := range ctxt.Syms.Allsym { 986 if s.Type != sym.SRODATA { 987 continue 988 } 989 for ri := range s.R { 990 r := &s.R[ri] 991 if r.Type != objabi.R_ADDR { 992 continue 993 } 994 if r.Sym.Type != sym.Sxxx && r.Sym.Type != sym.STEXT && r.Sym.Type != sym.SRODATA { 995 s.Type = sym.SDATA 996 again = true 997 break 998 } 999 } 1000 1001 } 1002 if !again { 1003 break 1004 } 1005 } 1006 1007 // Add entry point to .loader symbols. 1008 ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0) 1009 if !ep.Attr.Reachable() { 1010 Exitf("wrong entry point") 1011 } 1012 xfile.loaderSymbols = append(xfile.loaderSymbols, &xcoffLoaderSymbol{ 1013 sym: ep, 1014 smtype: XTY_ENT | XTY_SD, 1015 smclas: XMC_DS, 1016 }) 1017 1018 xfile.genDynSym(ctxt) 1019 1020 for _, s := range ctxt.Syms.Allsym { 1021 if strings.HasPrefix(s.Name, "TOC.") { 1022 s.Type = sym.SXCOFFTOC 1023 } 1024 } 1025 } 1026 1027 // Loader section 1028 // Currently, this section is created from scratch when assembling the XCOFF file 1029 // according to information retrieved in xfile object. 1030 1031 // Create loader section and returns its size 1032 func Loaderblk(ctxt *Link, off uint64) { 1033 xfile.writeLdrScn(ctxt, off) 1034 } 1035 1036 func (f *xcoffFile) writeLdrScn(ctxt *Link, globalOff uint64) { 1037 var symtab []*XcoffLdSym64 1038 var strtab []*XcoffLdStr64 1039 var importtab []*XcoffLdImportFile64 1040 var reloctab []*XcoffLdRel64 1041 var dynimpreloc []*XcoffLdRel64 1042 1043 // As the string table is updated in any loader subsection, 1044 // its length must be computed at the same time. 1045 stlen := uint32(0) 1046 1047 // Loader Header 1048 hdr := &XcoffLdHdr64{ 1049 Lversion: 2, 1050 Lsymoff: LDHDRSZ_64, 1051 } 1052 1053 /* Symbol table */ 1054 for _, s := range f.loaderSymbols { 1055 lds := &XcoffLdSym64{ 1056 Loffset: uint32(stlen + 2), 1057 Lsmtype: s.smtype, 1058 Lsmclas: s.smclas, 1059 } 1060 switch s.smtype { 1061 default: 1062 Errorf(s.sym, "unexpected loader symbol type: 0x%x", s.smtype) 1063 case XTY_ENT | XTY_SD: 1064 lds.Lvalue = uint64(s.sym.Value) 1065 lds.Lscnum = f.getXCOFFscnum(s.sym.Sect) 1066 case XTY_IMP: 1067 lds.Lifile = int32(f.dynLibraries[s.sym.Dynimplib()] + 1) 1068 } 1069 ldstr := &XcoffLdStr64{ 1070 size: uint16(len(s.sym.Name) + 1), // + null terminator 1071 name: s.sym.Name, 1072 } 1073 stlen += uint32(2 + ldstr.size) // 2 = sizeof ldstr.size 1074 symtab = append(symtab, lds) 1075 strtab = append(strtab, ldstr) 1076 1077 } 1078 1079 hdr.Lnsyms = int32(len(symtab)) 1080 hdr.Lrldoff = hdr.Lsymoff + uint64(24*hdr.Lnsyms) // 24 = sizeof one symbol 1081 off := hdr.Lrldoff // current offset is the same of reloc offset 1082 1083 /* Reloc */ 1084 ep := ctxt.Syms.ROLookup(*flagEntrySymbol, 0) 1085 ldr := &XcoffLdRel64{ 1086 Lvaddr: uint64(ep.Value), 1087 Lrtype: 0x3F00, 1088 Lrsecnm: f.getXCOFFscnum(ep.Sect), 1089 Lsymndx: 0, 1090 } 1091 off += 16 1092 reloctab = append(reloctab, ldr) 1093 1094 off += uint64(16 * len(f.loaderReloc)) 1095 for _, r := range f.loaderReloc { 1096 ldr = &XcoffLdRel64{ 1097 Lvaddr: uint64(r.sym.Value + int64(r.rel.Off)), 1098 Lrtype: r.rtype, 1099 Lsymndx: r.symndx, 1100 } 1101 1102 if r.sym.Sect != nil { 1103 ldr.Lrsecnm = f.getXCOFFscnum(r.sym.Sect) 1104 } 1105 1106 reloctab = append(reloctab, ldr) 1107 } 1108 1109 off += uint64(16 * len(dynimpreloc)) 1110 reloctab = append(reloctab, dynimpreloc...) 1111 1112 hdr.Lnreloc = int32(len(reloctab)) 1113 hdr.Limpoff = off 1114 1115 /* Import */ 1116 // Default import: /usr/lib:/lib 1117 ldimpf := &XcoffLdImportFile64{ 1118 Limpidpath: "/usr/lib:/lib", 1119 } 1120 off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3) // + null delimiter 1121 importtab = append(importtab, ldimpf) 1122 1123 // The map created by adddynimpsym associates the name to a number 1124 // This number represents the librairie index (- 1) in this import files section 1125 // Therefore, they must be sorted before being put inside the section 1126 libsOrdered := make([]string, len(f.dynLibraries)) 1127 for key, val := range f.dynLibraries { 1128 if libsOrdered[val] != "" { 1129 continue 1130 } 1131 libsOrdered[val] = key 1132 } 1133 1134 for _, lib := range libsOrdered { 1135 // lib string is defined as base.a/mem.o or path/base.a/mem.o 1136 n := strings.Split(lib, "/") 1137 path := "" 1138 base := n[len(n)-2] 1139 mem := n[len(n)-1] 1140 if len(n) > 2 { 1141 path = lib[:len(lib)-len(base)-len(mem)-2] 1142 1143 } 1144 ldimpf = &XcoffLdImportFile64{ 1145 Limpidpath: path, 1146 Limpidbase: base, 1147 Limpidmem: mem, 1148 } 1149 off += uint64(len(ldimpf.Limpidpath) + len(ldimpf.Limpidbase) + len(ldimpf.Limpidmem) + 3) // + null delimiter 1150 importtab = append(importtab, ldimpf) 1151 } 1152 1153 hdr.Lnimpid = int32(len(importtab)) 1154 hdr.Listlen = uint32(off - hdr.Limpoff) 1155 hdr.Lstoff = off 1156 hdr.Lstlen = stlen 1157 1158 /* Writing */ 1159 ctxt.Out.SeekSet(int64(globalOff)) 1160 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, hdr) 1161 1162 for _, s := range symtab { 1163 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, s) 1164 1165 } 1166 for _, r := range reloctab { 1167 binary.Write(ctxt.Out, ctxt.Arch.ByteOrder, r) 1168 } 1169 for _, f := range importtab { 1170 ctxt.Out.WriteString(f.Limpidpath) 1171 ctxt.Out.Write8(0) 1172 ctxt.Out.WriteString(f.Limpidbase) 1173 ctxt.Out.Write8(0) 1174 ctxt.Out.WriteString(f.Limpidmem) 1175 ctxt.Out.Write8(0) 1176 } 1177 for _, s := range strtab { 1178 ctxt.Out.Write16(s.size) 1179 ctxt.Out.WriteString(s.name) 1180 ctxt.Out.Write8(0) // null terminator 1181 } 1182 1183 f.loaderSize = off + uint64(stlen) 1184 ctxt.Out.Flush() 1185 1186 /* again for printing */ 1187 if !*flagA { 1188 return 1189 } 1190 1191 ctxt.Logf("\n.loader section") 1192 // write in buf 1193 var buf bytes.Buffer 1194 1195 binary.Write(&buf, ctxt.Arch.ByteOrder, hdr) 1196 for _, s := range symtab { 1197 binary.Write(&buf, ctxt.Arch.ByteOrder, s) 1198 1199 } 1200 for _, f := range importtab { 1201 buf.WriteString(f.Limpidpath) 1202 buf.WriteByte(0) 1203 buf.WriteString(f.Limpidbase) 1204 buf.WriteByte(0) 1205 buf.WriteString(f.Limpidmem) 1206 buf.WriteByte(0) 1207 } 1208 for _, s := range strtab { 1209 binary.Write(&buf, ctxt.Arch.ByteOrder, s.size) 1210 buf.WriteString(s.name) 1211 buf.WriteByte(0) // null terminator 1212 } 1213 1214 // Log buffer 1215 ctxt.Logf("\n\t%.8x|", globalOff) 1216 for i, b := range buf.Bytes() { 1217 if i > 0 && i%16 == 0 { 1218 ctxt.Logf("\n\t%.8x|", uint64(globalOff)+uint64(i)) 1219 } 1220 ctxt.Logf(" %.2x", b) 1221 } 1222 ctxt.Logf("\n") 1223 1224 } 1225 1226 // XCOFF assembling and writing file 1227 1228 func (f *xcoffFile) writeFileHeader(ctxt *Link) { 1229 // File header 1230 f.xfhdr.Fmagic = U64_TOCMAGIC 1231 f.xfhdr.Fnscns = uint16(len(f.sections)) 1232 f.xfhdr.Ftimedat = 0 1233 1234 if !*FlagS { 1235 f.xfhdr.Fsymptr = uint64(f.symtabOffset) 1236 f.xfhdr.Fnsyms = int32(f.symbolCount) 1237 } 1238 1239 if ctxt.BuildMode == BuildModeExe { 1240 f.xfhdr.Fopthdr = AOUTHSZ_EXEC64 1241 f.xfhdr.Fflags = F_EXEC 1242 1243 // auxiliary header 1244 f.xahdr.Ovstamp = 1 // based on dump -o 1245 f.xahdr.Omagic = 0x10b 1246 copy(f.xahdr.Omodtype[:], "1L") 1247 entry := ctxt.Syms.ROLookup(*flagEntrySymbol, 0) 1248 f.xahdr.Oentry = uint64(entry.Value) 1249 f.xahdr.Osnentry = f.getXCOFFscnum(entry.Sect) 1250 toc := ctxt.Syms.ROLookup("TOC", 0) 1251 f.xahdr.Otoc = uint64(toc.Value) 1252 f.xahdr.Osntoc = f.getXCOFFscnum(toc.Sect) 1253 1254 // Based on dump -o 1255 f.xahdr.Oalgntext = 0x5 1256 f.xahdr.Oalgndata = 0x5 1257 1258 binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr) 1259 binary.Write(ctxt.Out, binary.BigEndian, &f.xahdr) 1260 } else { 1261 f.xfhdr.Fopthdr = 0 1262 binary.Write(ctxt.Out, binary.BigEndian, &f.xfhdr) 1263 } 1264 1265 } 1266 1267 func xcoffwrite(ctxt *Link) { 1268 ctxt.Out.SeekSet(0) 1269 1270 xfile.writeFileHeader(ctxt) 1271 1272 for _, sect := range xfile.sections { 1273 sect.write(ctxt) 1274 } 1275 } 1276 1277 // Generate XCOFF assembly file 1278 func Asmbxcoff(ctxt *Link, fileoff int64) { 1279 xfile.sectNameToScnum = make(map[string]int16) 1280 1281 // Add sections 1282 s := xfile.addSection(".text", Segtext.Vaddr, Segtext.Length, Segtext.Fileoff, STYP_TEXT) 1283 xfile.xahdr.Otextstart = s.Svaddr 1284 xfile.xahdr.Osntext = xfile.sectNameToScnum[".text"] 1285 xfile.xahdr.Otsize = s.Ssize 1286 1287 s = xfile.addSection(".data", Segdata.Vaddr, Segdata.Filelen, Segdata.Fileoff, STYP_DATA) 1288 xfile.xahdr.Odatastart = s.Svaddr 1289 xfile.xahdr.Osndata = xfile.sectNameToScnum[".data"] 1290 xfile.xahdr.Odsize = s.Ssize 1291 1292 s = xfile.addSection(".bss", Segdata.Vaddr+Segdata.Filelen, Segdata.Length-Segdata.Filelen, 0, STYP_BSS) 1293 xfile.xahdr.Osnbss = xfile.sectNameToScnum[".bss"] 1294 xfile.xahdr.Obsize = s.Ssize 1295 1296 // add dwarf sections 1297 for _, sect := range Segdwarf.Sections { 1298 xfile.addDwarfSection(sect) 1299 } 1300 1301 // add and write remaining sections 1302 if ctxt.LinkMode == LinkInternal { 1303 // Loader section 1304 if ctxt.BuildMode == BuildModeExe { 1305 Loaderblk(ctxt, uint64(fileoff)) 1306 s = xfile.addSection(".loader", 0, xfile.loaderSize, uint64(fileoff), STYP_LOADER) 1307 xfile.xahdr.Osnloader = xfile.sectNameToScnum[".loader"] 1308 } 1309 } else { 1310 // TODO: Relocation 1311 } 1312 1313 // Write symbol table 1314 symo := Rnd(ctxt.Out.Offset(), int64(*FlagRound)) 1315 xfile.symtabOffset = symo 1316 ctxt.Out.SeekSet(int64(symo)) 1317 xfile.asmaixsym(ctxt) 1318 1319 // write headers 1320 xcoffwrite(ctxt) 1321 }