github.com/sbinet/go@v0.0.0-20160827155028-54d7de7dd62b/src/cmd/link/internal/s390x/asm.go (about) 1 // Inferno utils/5l/asm.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5l/asm.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 package s390x 32 33 import ( 34 "cmd/internal/obj" 35 "cmd/link/internal/ld" 36 "debug/elf" 37 "fmt" 38 ) 39 40 // gentext generates assembly to append the local moduledata to the global 41 // moduledata linked list at initialization time. This is only done if the runtime 42 // is in a different module. 43 // 44 // <go.link.addmoduledata>: 45 // larl %r2, <local.moduledata> 46 // jg <runtime.addmoduledata@plt> 47 // undef 48 // 49 // The job of appending the moduledata is delegated to runtime.addmoduledata. 50 func gentext(ctxt *ld.Link) { 51 if !ctxt.DynlinkingGo() { 52 return 53 } 54 addmoduledata := ld.Linklookup(ctxt, "runtime.addmoduledata", 0) 55 if addmoduledata.Type == obj.STEXT { 56 // we're linking a module containing the runtime -> no need for 57 // an init function 58 return 59 } 60 addmoduledata.Attr |= ld.AttrReachable 61 initfunc := ld.Linklookup(ctxt, "go.link.addmoduledata", 0) 62 initfunc.Type = obj.STEXT 63 initfunc.Attr |= ld.AttrLocal 64 initfunc.Attr |= ld.AttrReachable 65 66 // larl %r2, <local.moduledata> 67 ld.Adduint8(ctxt, initfunc, 0xc0) 68 ld.Adduint8(ctxt, initfunc, 0x20) 69 lmd := ld.Addrel(initfunc) 70 lmd.Off = int32(initfunc.Size) 71 lmd.Siz = 4 72 lmd.Sym = ctxt.Moduledata 73 lmd.Type = obj.R_PCREL 74 lmd.Variant = ld.RV_390_DBL 75 lmd.Add = 2 + int64(lmd.Siz) 76 ld.Adduint32(ctxt, initfunc, 0) 77 78 // jg <runtime.addmoduledata[@plt]> 79 ld.Adduint8(ctxt, initfunc, 0xc0) 80 ld.Adduint8(ctxt, initfunc, 0xf4) 81 rel := ld.Addrel(initfunc) 82 rel.Off = int32(initfunc.Size) 83 rel.Siz = 4 84 rel.Sym = ld.Linklookup(ctxt, "runtime.addmoduledata", 0) 85 rel.Type = obj.R_CALL 86 rel.Variant = ld.RV_390_DBL 87 rel.Add = 2 + int64(rel.Siz) 88 ld.Adduint32(ctxt, initfunc, 0) 89 90 // undef (for debugging) 91 ld.Adduint32(ctxt, initfunc, 0) 92 93 ctxt.Textp = append(ctxt.Textp, initfunc) 94 initarray_entry := ld.Linklookup(ctxt, "go.link.addmoduledatainit", 0) 95 initarray_entry.Attr |= ld.AttrLocal 96 initarray_entry.Attr |= ld.AttrReachable 97 initarray_entry.Type = obj.SINITARR 98 ld.Addaddr(ctxt, initarray_entry, initfunc) 99 } 100 101 func adddynrel(ctxt *ld.Link, s *ld.Symbol, r *ld.Reloc) { 102 targ := r.Sym 103 ctxt.Cursym = s 104 105 switch r.Type { 106 default: 107 if r.Type >= 256 { 108 ctxt.Diag("unexpected relocation type %d", r.Type) 109 return 110 } 111 112 // Handle relocations found in ELF object files. 113 case 256 + ld.R_390_12, 114 256 + ld.R_390_GOT12: 115 ctxt.Diag("s390x 12-bit relocations have not been implemented (relocation type %d)", r.Type-256) 116 return 117 118 case 256 + ld.R_390_8, 119 256 + ld.R_390_16, 120 256 + ld.R_390_32, 121 256 + ld.R_390_64: 122 if targ.Type == obj.SDYNIMPORT { 123 ctxt.Diag("unexpected R_390_nn relocation for dynamic symbol %s", targ.Name) 124 } 125 r.Type = obj.R_ADDR 126 return 127 128 case 256 + ld.R_390_PC16, 129 256 + ld.R_390_PC32, 130 256 + ld.R_390_PC64: 131 if targ.Type == obj.SDYNIMPORT { 132 ctxt.Diag("unexpected R_390_PCnn relocation for dynamic symbol %s", targ.Name) 133 } 134 if targ.Type == 0 || targ.Type == obj.SXREF { 135 ctxt.Diag("unknown symbol %s in pcrel", targ.Name) 136 } 137 r.Type = obj.R_PCREL 138 r.Add += int64(r.Siz) 139 return 140 141 case 256 + ld.R_390_GOT16, 142 256 + ld.R_390_GOT32, 143 256 + ld.R_390_GOT64: 144 ctxt.Diag("unimplemented S390x relocation: %v", r.Type-256) 145 return 146 147 case 256 + ld.R_390_PLT16DBL, 148 256 + ld.R_390_PLT32DBL: 149 r.Type = obj.R_PCREL 150 r.Variant = ld.RV_390_DBL 151 r.Add += int64(r.Siz) 152 if targ.Type == obj.SDYNIMPORT { 153 addpltsym(ctxt, targ) 154 r.Sym = ld.Linklookup(ctxt, ".plt", 0) 155 r.Add += int64(targ.Plt) 156 } 157 return 158 159 case 256 + ld.R_390_PLT32, 160 256 + ld.R_390_PLT64: 161 r.Type = obj.R_PCREL 162 r.Add += int64(r.Siz) 163 if targ.Type == obj.SDYNIMPORT { 164 addpltsym(ctxt, targ) 165 r.Sym = ld.Linklookup(ctxt, ".plt", 0) 166 r.Add += int64(targ.Plt) 167 } 168 return 169 170 case 256 + ld.R_390_COPY: 171 ctxt.Diag("unimplemented S390x relocation: %v", r.Type-256) 172 173 case 256 + ld.R_390_GLOB_DAT: 174 ctxt.Diag("unimplemented S390x relocation: %v", r.Type-256) 175 176 case 256 + ld.R_390_JMP_SLOT: 177 ctxt.Diag("unimplemented S390x relocation: %v", r.Type-256) 178 179 case 256 + ld.R_390_RELATIVE: 180 ctxt.Diag("unimplemented S390x relocation: %v", r.Type-256) 181 182 case 256 + ld.R_390_GOTOFF: 183 if targ.Type == obj.SDYNIMPORT { 184 ctxt.Diag("unexpected R_390_GOTOFF relocation for dynamic symbol %s", targ.Name) 185 } 186 r.Type = obj.R_GOTOFF 187 return 188 189 case 256 + ld.R_390_GOTPC: 190 r.Type = obj.R_PCREL 191 r.Sym = ld.Linklookup(ctxt, ".got", 0) 192 r.Add += int64(r.Siz) 193 return 194 195 case 256 + ld.R_390_PC16DBL, 196 256 + ld.R_390_PC32DBL: 197 r.Type = obj.R_PCREL 198 r.Variant = ld.RV_390_DBL 199 r.Add += int64(r.Siz) 200 if targ.Type == obj.SDYNIMPORT { 201 ctxt.Diag("unexpected R_390_PCnnDBL relocation for dynamic symbol %s", targ.Name) 202 } 203 return 204 205 case 256 + ld.R_390_GOTPCDBL: 206 r.Type = obj.R_PCREL 207 r.Variant = ld.RV_390_DBL 208 r.Sym = ld.Linklookup(ctxt, ".got", 0) 209 r.Add += int64(r.Siz) 210 return 211 212 case 256 + ld.R_390_GOTENT: 213 addgotsym(ctxt, targ) 214 215 r.Type = obj.R_PCREL 216 r.Variant = ld.RV_390_DBL 217 r.Sym = ld.Linklookup(ctxt, ".got", 0) 218 r.Add += int64(targ.Got) 219 r.Add += int64(r.Siz) 220 return 221 } 222 // Handle references to ELF symbols from our own object files. 223 if targ.Type != obj.SDYNIMPORT { 224 return 225 } 226 227 ctxt.Diag("unsupported relocation for dynamic symbol %s (type=%d stype=%d)", targ.Name, r.Type, targ.Type) 228 } 229 230 func elfreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) int { 231 ld.Thearch.Vput(uint64(sectoff)) 232 233 elfsym := r.Xsym.ElfsymForReloc() 234 switch r.Type { 235 default: 236 return -1 237 238 case obj.R_TLS_LE: 239 switch r.Siz { 240 default: 241 return -1 242 case 4: 243 // WARNING - silently ignored by linker in ELF64 244 ld.Thearch.Vput(ld.R_390_TLS_LE32 | uint64(elfsym)<<32) 245 case 8: 246 // WARNING - silently ignored by linker in ELF32 247 ld.Thearch.Vput(ld.R_390_TLS_LE64 | uint64(elfsym)<<32) 248 } 249 250 case obj.R_TLS_IE: 251 switch r.Siz { 252 default: 253 return -1 254 case 4: 255 ld.Thearch.Vput(ld.R_390_TLS_IEENT | uint64(elfsym)<<32) 256 } 257 258 case obj.R_ADDR: 259 switch r.Siz { 260 default: 261 return -1 262 case 4: 263 ld.Thearch.Vput(ld.R_390_32 | uint64(elfsym)<<32) 264 case 8: 265 ld.Thearch.Vput(ld.R_390_64 | uint64(elfsym)<<32) 266 } 267 268 case obj.R_GOTPCREL: 269 if r.Siz == 4 { 270 ld.Thearch.Vput(ld.R_390_GOTENT | uint64(elfsym)<<32) 271 } else { 272 return -1 273 } 274 275 case obj.R_PCREL, obj.R_PCRELDBL, obj.R_CALL: 276 elfrel := ld.R_390_NONE 277 isdbl := r.Variant&ld.RV_TYPE_MASK == ld.RV_390_DBL 278 // TODO(mundaym): all DBL style relocations should be 279 // signalled using the variant - see issue 14218. 280 switch r.Type { 281 case obj.R_PCRELDBL, obj.R_CALL: 282 isdbl = true 283 } 284 if r.Xsym.Type == obj.SDYNIMPORT && (r.Xsym.ElfType == elf.STT_FUNC || r.Type == obj.R_CALL) { 285 if isdbl { 286 switch r.Siz { 287 case 2: 288 elfrel = ld.R_390_PLT16DBL 289 case 4: 290 elfrel = ld.R_390_PLT32DBL 291 } 292 } else { 293 switch r.Siz { 294 case 4: 295 elfrel = ld.R_390_PLT32 296 case 8: 297 elfrel = ld.R_390_PLT64 298 } 299 } 300 } else { 301 if isdbl { 302 switch r.Siz { 303 case 2: 304 elfrel = ld.R_390_PC16DBL 305 case 4: 306 elfrel = ld.R_390_PC32DBL 307 } 308 } else { 309 switch r.Siz { 310 case 2: 311 elfrel = ld.R_390_PC16 312 case 4: 313 elfrel = ld.R_390_PC32 314 case 8: 315 elfrel = ld.R_390_PC64 316 } 317 } 318 } 319 if elfrel == ld.R_390_NONE { 320 return -1 // unsupported size/dbl combination 321 } 322 ld.Thearch.Vput(uint64(elfrel) | uint64(elfsym)<<32) 323 } 324 325 ld.Thearch.Vput(uint64(r.Xadd)) 326 return 0 327 } 328 329 func elfsetupplt(ctxt *ld.Link) { 330 plt := ld.Linklookup(ctxt, ".plt", 0) 331 got := ld.Linklookup(ctxt, ".got", 0) 332 if plt.Size == 0 { 333 // stg %r1,56(%r15) 334 ld.Adduint8(ctxt, plt, 0xe3) 335 ld.Adduint8(ctxt, plt, 0x10) 336 ld.Adduint8(ctxt, plt, 0xf0) 337 ld.Adduint8(ctxt, plt, 0x38) 338 ld.Adduint8(ctxt, plt, 0x00) 339 ld.Adduint8(ctxt, plt, 0x24) 340 // larl %r1,_GLOBAL_OFFSET_TABLE_ 341 ld.Adduint8(ctxt, plt, 0xc0) 342 ld.Adduint8(ctxt, plt, 0x10) 343 ld.Addpcrelplus(ctxt, plt, got, 6) 344 // mvc 48(8,%r15),8(%r1) 345 ld.Adduint8(ctxt, plt, 0xd2) 346 ld.Adduint8(ctxt, plt, 0x07) 347 ld.Adduint8(ctxt, plt, 0xf0) 348 ld.Adduint8(ctxt, plt, 0x30) 349 ld.Adduint8(ctxt, plt, 0x10) 350 ld.Adduint8(ctxt, plt, 0x08) 351 // lg %r1,16(%r1) 352 ld.Adduint8(ctxt, plt, 0xe3) 353 ld.Adduint8(ctxt, plt, 0x10) 354 ld.Adduint8(ctxt, plt, 0x10) 355 ld.Adduint8(ctxt, plt, 0x10) 356 ld.Adduint8(ctxt, plt, 0x00) 357 ld.Adduint8(ctxt, plt, 0x04) 358 // br %r1 359 ld.Adduint8(ctxt, plt, 0x07) 360 ld.Adduint8(ctxt, plt, 0xf1) 361 // nopr %r0 362 ld.Adduint8(ctxt, plt, 0x07) 363 ld.Adduint8(ctxt, plt, 0x00) 364 // nopr %r0 365 ld.Adduint8(ctxt, plt, 0x07) 366 ld.Adduint8(ctxt, plt, 0x00) 367 // nopr %r0 368 ld.Adduint8(ctxt, plt, 0x07) 369 ld.Adduint8(ctxt, plt, 0x00) 370 371 // assume got->size == 0 too 372 ld.Addaddrplus(ctxt, got, ld.Linklookup(ctxt, ".dynamic", 0), 0) 373 374 ld.Adduint64(ctxt, got, 0) 375 ld.Adduint64(ctxt, got, 0) 376 } 377 } 378 379 func machoreloc1(ctxt *ld.Link, r *ld.Reloc, sectoff int64) int { 380 return -1 381 } 382 383 func archreloc(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, val *int64) int { 384 if ld.Linkmode == ld.LinkExternal { 385 return -1 386 } 387 388 switch r.Type { 389 case obj.R_CONST: 390 *val = r.Add 391 return 0 392 393 case obj.R_GOTOFF: 394 *val = ld.Symaddr(ctxt, r.Sym) + r.Add - ld.Symaddr(ctxt, ld.Linklookup(ctxt, ".got", 0)) 395 return 0 396 } 397 398 return -1 399 } 400 401 func archrelocvariant(ctxt *ld.Link, r *ld.Reloc, s *ld.Symbol, t int64) int64 { 402 switch r.Variant & ld.RV_TYPE_MASK { 403 default: 404 ctxt.Diag("unexpected relocation variant %d", r.Variant) 405 return t 406 407 case ld.RV_NONE: 408 return t 409 410 case ld.RV_390_DBL: 411 if (t & 1) != 0 { 412 ctxt.Diag("%s+%v is not 2-byte aligned", r.Sym.Name, r.Sym.Value) 413 } 414 return t >> 1 415 } 416 } 417 418 func addpltsym(ctxt *ld.Link, s *ld.Symbol) { 419 if s.Plt >= 0 { 420 return 421 } 422 423 ld.Adddynsym(ctxt, s) 424 425 if ld.Iself { 426 plt := ld.Linklookup(ctxt, ".plt", 0) 427 got := ld.Linklookup(ctxt, ".got", 0) 428 rela := ld.Linklookup(ctxt, ".rela.plt", 0) 429 if plt.Size == 0 { 430 elfsetupplt(ctxt) 431 } 432 // larl %r1,_GLOBAL_OFFSET_TABLE_+index 433 434 ld.Adduint8(ctxt, plt, 0xc0) 435 ld.Adduint8(ctxt, plt, 0x10) 436 ld.Addpcrelplus(ctxt, plt, got, got.Size+6) // need variant? 437 438 // add to got: pointer to current pos in plt 439 ld.Addaddrplus(ctxt, got, plt, plt.Size+8) // weird but correct 440 // lg %r1,0(%r1) 441 ld.Adduint8(ctxt, plt, 0xe3) 442 ld.Adduint8(ctxt, plt, 0x10) 443 ld.Adduint8(ctxt, plt, 0x10) 444 ld.Adduint8(ctxt, plt, 0x00) 445 ld.Adduint8(ctxt, plt, 0x00) 446 ld.Adduint8(ctxt, plt, 0x04) 447 // br %r1 448 ld.Adduint8(ctxt, plt, 0x07) 449 ld.Adduint8(ctxt, plt, 0xf1) 450 // basr %r1,%r0 451 ld.Adduint8(ctxt, plt, 0x0d) 452 ld.Adduint8(ctxt, plt, 0x10) 453 // lgf %r1,12(%r1) 454 ld.Adduint8(ctxt, plt, 0xe3) 455 ld.Adduint8(ctxt, plt, 0x10) 456 ld.Adduint8(ctxt, plt, 0x10) 457 ld.Adduint8(ctxt, plt, 0x0c) 458 ld.Adduint8(ctxt, plt, 0x00) 459 ld.Adduint8(ctxt, plt, 0x14) 460 // jg .plt 461 ld.Adduint8(ctxt, plt, 0xc0) 462 ld.Adduint8(ctxt, plt, 0xf4) 463 464 ld.Adduint32(ctxt, plt, uint32(-((plt.Size - 2) >> 1))) // roll-your-own relocation 465 //.plt index 466 ld.Adduint32(ctxt, plt, uint32(rela.Size)) // rela size before current entry 467 468 // rela 469 ld.Addaddrplus(ctxt, rela, got, got.Size-8) 470 471 ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_390_JMP_SLOT)) 472 ld.Adduint64(ctxt, rela, 0) 473 474 s.Plt = int32(plt.Size - 32) 475 476 } else { 477 ctxt.Diag("addpltsym: unsupported binary format") 478 } 479 } 480 481 func addgotsym(ctxt *ld.Link, s *ld.Symbol) { 482 if s.Got >= 0 { 483 return 484 } 485 486 ld.Adddynsym(ctxt, s) 487 got := ld.Linklookup(ctxt, ".got", 0) 488 s.Got = int32(got.Size) 489 ld.Adduint64(ctxt, got, 0) 490 491 if ld.Iself { 492 rela := ld.Linklookup(ctxt, ".rela", 0) 493 ld.Addaddrplus(ctxt, rela, got, int64(s.Got)) 494 ld.Adduint64(ctxt, rela, ld.ELF64_R_INFO(uint32(s.Dynid), ld.R_390_GLOB_DAT)) 495 ld.Adduint64(ctxt, rela, 0) 496 } else { 497 ctxt.Diag("addgotsym: unsupported binary format") 498 } 499 } 500 501 func asmb(ctxt *ld.Link) { 502 if ctxt.Debugvlog != 0 { 503 ctxt.Logf("%5.2f asmb\n", obj.Cputime()) 504 } 505 506 if ld.Iself { 507 ld.Asmbelfsetup(ctxt) 508 } 509 510 sect := ld.Segtext.Sect 511 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 512 ld.Codeblk(ctxt, int64(sect.Vaddr), int64(sect.Length)) 513 for sect = sect.Next; sect != nil; sect = sect.Next { 514 ld.Cseek(int64(sect.Vaddr - ld.Segtext.Vaddr + ld.Segtext.Fileoff)) 515 ld.Datblk(ctxt, int64(sect.Vaddr), int64(sect.Length)) 516 } 517 518 if ld.Segrodata.Filelen > 0 { 519 if ctxt.Debugvlog != 0 { 520 ctxt.Logf("%5.2f rodatblk\n", obj.Cputime()) 521 } 522 523 ld.Cseek(int64(ld.Segrodata.Fileoff)) 524 ld.Datblk(ctxt, int64(ld.Segrodata.Vaddr), int64(ld.Segrodata.Filelen)) 525 } 526 527 if ctxt.Debugvlog != 0 { 528 ctxt.Logf("%5.2f datblk\n", obj.Cputime()) 529 } 530 531 ld.Cseek(int64(ld.Segdata.Fileoff)) 532 ld.Datblk(ctxt, int64(ld.Segdata.Vaddr), int64(ld.Segdata.Filelen)) 533 534 ld.Cseek(int64(ld.Segdwarf.Fileoff)) 535 ld.Dwarfblk(ctxt, int64(ld.Segdwarf.Vaddr), int64(ld.Segdwarf.Filelen)) 536 537 /* output symbol table */ 538 ld.Symsize = 0 539 540 ld.Lcsize = 0 541 symo := uint32(0) 542 if !*ld.FlagS { 543 if !ld.Iself { 544 ctxt.Diag("unsupported executable format") 545 } 546 if ctxt.Debugvlog != 0 { 547 ctxt.Logf("%5.2f sym\n", obj.Cputime()) 548 } 549 symo = uint32(ld.Segdwarf.Fileoff + ld.Segdwarf.Filelen) 550 symo = uint32(ld.Rnd(int64(symo), int64(*ld.FlagRound))) 551 552 ld.Cseek(int64(symo)) 553 if ctxt.Debugvlog != 0 { 554 ctxt.Logf("%5.2f elfsym\n", obj.Cputime()) 555 } 556 ld.Asmelfsym(ctxt) 557 ld.Cflush() 558 ld.Cwrite(ld.Elfstrdat) 559 560 if ctxt.Debugvlog != 0 { 561 ctxt.Logf("%5.2f dwarf\n", obj.Cputime()) 562 } 563 564 if ld.Linkmode == ld.LinkExternal { 565 ld.Elfemitreloc(ctxt) 566 } 567 } 568 569 ctxt.Cursym = nil 570 if ctxt.Debugvlog != 0 { 571 ctxt.Logf("%5.2f header\n", obj.Cputime()) 572 } 573 ld.Cseek(0) 574 switch ld.HEADTYPE { 575 default: 576 ctxt.Diag("unsupported operating system") 577 case obj.Hlinux: 578 ld.Asmbelf(ctxt, int64(symo)) 579 } 580 581 ld.Cflush() 582 if *ld.FlagC { 583 fmt.Printf("textsize=%d\n", ld.Segtext.Filelen) 584 fmt.Printf("datsize=%d\n", ld.Segdata.Filelen) 585 fmt.Printf("bsssize=%d\n", ld.Segdata.Length-ld.Segdata.Filelen) 586 fmt.Printf("symsize=%d\n", ld.Symsize) 587 fmt.Printf("lcsize=%d\n", ld.Lcsize) 588 fmt.Printf("total=%d\n", ld.Segtext.Filelen+ld.Segdata.Length+uint64(ld.Symsize)+uint64(ld.Lcsize)) 589 } 590 }