github.com/notti/go-dynamic@v0.0.0-20190619201224-fc443047424c/steps/3_goffi/rewrite.go (about) 1 package main 2 3 import ( 4 "bytes" 5 "debug/elf" 6 "encoding/binary" 7 "errors" 8 "io" 9 "log" 10 "os" 11 "sort" 12 "strings" 13 ) 14 15 const ( 16 in = "main" 17 out = "dyn" 18 interp = "/lib64/ld-linux-x86-64.so.2" 19 ) 20 21 var libs = []string{"libc.so.6", "libpthread.so.0", "libcalltest.so.1"} 22 23 func doCopy() { 24 src, err := os.Open(in) 25 if err != nil { 26 log.Fatal("couldn't open", in, ":", err) 27 } 28 defer src.Close() 29 dst, err := os.OpenFile(out, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0777) 30 if err != nil { 31 log.Fatal("couldn't create", out, ":", err) 32 } 33 defer dst.Close() 34 _, err = io.Copy(dst, src) 35 if err != nil { 36 log.Fatal("couldn't copy:", err) 37 } 38 } 39 40 type elfFile struct { 41 f *os.File 42 e *elf.File 43 phoff uint64 44 phentsize uint64 45 shoff uint64 46 shentsize uint64 47 shstrndx uint64 48 buffer [1024]byte 49 } 50 51 func openElfFile(name string) (*elfFile, error) { 52 ret := &elfFile{} 53 var err error 54 ret.f, err = os.OpenFile(name, os.O_RDWR, 0777) 55 if err != nil { 56 return nil, err 57 } 58 ret.e, err = elf.NewFile(ret.f) 59 if err != nil { 60 return nil, err 61 } 62 63 _, err = ret.Seek(0, io.SeekCurrent) 64 if err != nil { 65 return nil, err 66 } 67 68 switch ret.e.Class { 69 case elf.ELFCLASS32: 70 var hdr elf.Header32 71 err = ret.ReadData(&hdr) 72 if err != nil { 73 return nil, err 74 } 75 ret.phoff = uint64(hdr.Phoff) 76 ret.phentsize = uint64(hdr.Phentsize) 77 ret.shoff = uint64(hdr.Shoff) 78 ret.shentsize = uint64(hdr.Shentsize) 79 ret.shstrndx = uint64(hdr.Shstrndx) 80 case elf.ELFCLASS64: 81 var hdr elf.Header64 82 err = ret.ReadData(&hdr) 83 if err != nil { 84 return nil, err 85 } 86 ret.phoff = hdr.Phoff 87 ret.phentsize = uint64(hdr.Phentsize) 88 ret.shoff = hdr.Shoff 89 ret.shentsize = uint64(hdr.Shentsize) 90 ret.shstrndx = uint64(hdr.Shstrndx) 91 } 92 93 return ret, nil 94 } 95 96 func (e *elfFile) Seek(where int64, whence int) (int64, error) { 97 return e.f.Seek(where, whence) 98 } 99 100 func (e *elfFile) ReadData(data interface{}) error { 101 return binary.Read(e.f, e.e.ByteOrder, data) 102 } 103 104 func (e *elfFile) WriteData(data interface{}) error { 105 return binary.Write(e.f, e.e.ByteOrder, data) 106 } 107 108 func (e *elfFile) Write(b []byte) error { 109 _, err := e.f.Write(b) 110 return err 111 } 112 113 func (e *elfFile) WriteAt(b []byte, off uint64) error { 114 _, err := e.f.WriteAt(b, int64(off)) 115 return err 116 } 117 118 func (e *elfFile) Read8() (uint8, error) { 119 _, err := e.f.Read(e.buffer[:1]) 120 return e.buffer[0], err 121 } 122 123 func (e *elfFile) Read16() (uint16, error) { 124 _, err := e.f.Read(e.buffer[:2]) 125 return e.e.ByteOrder.Uint16(e.buffer[:]), err 126 } 127 128 func (e *elfFile) Read32() (uint32, error) { 129 _, err := e.f.Read(e.buffer[:4]) 130 return e.e.ByteOrder.Uint32(e.buffer[:]), err 131 } 132 133 func (e *elfFile) Read64() (uint64, error) { 134 _, err := e.f.Read(e.buffer[:8]) 135 return e.e.ByteOrder.Uint64(e.buffer[:]), err 136 } 137 138 func (e *elfFile) Read8At(where int64) (uint8, error) { 139 _, err := e.f.ReadAt(e.buffer[:1], where) 140 return e.buffer[0], err 141 } 142 143 func (e *elfFile) Read16At(where int64) (uint16, error) { 144 _, err := e.f.ReadAt(e.buffer[:2], where) 145 return e.e.ByteOrder.Uint16(e.buffer[:]), err 146 } 147 148 func (e *elfFile) Read32At(where int64) (uint32, error) { 149 _, err := e.f.ReadAt(e.buffer[:4], where) 150 return e.e.ByteOrder.Uint32(e.buffer[:]), err 151 } 152 153 func (e *elfFile) Read64At(where int64) (uint64, error) { 154 _, err := e.f.ReadAt(e.buffer[:8], where) 155 return e.e.ByteOrder.Uint64(e.buffer[:]), err 156 } 157 158 func (e *elfFile) Write8(data uint8) error { 159 _, err := e.f.Write([]byte{data}) 160 return err 161 } 162 163 func (e *elfFile) Write16(data uint16) error { 164 e.e.ByteOrder.PutUint16(e.buffer[:], data) 165 _, err := e.f.Write(e.buffer[:2]) 166 return err 167 } 168 169 func (e *elfFile) Write32(data uint32) error { 170 e.e.ByteOrder.PutUint32(e.buffer[:], data) 171 _, err := e.f.Write(e.buffer[:4]) 172 return err 173 } 174 175 func (e *elfFile) Write64(data uint64) error { 176 e.e.ByteOrder.PutUint64(e.buffer[:], data) 177 _, err := e.f.Write(e.buffer[:8]) 178 return err 179 } 180 181 func (e *elfFile) Write8At(data uint8, where uint64) error { 182 return e.WriteAt([]byte{data}, where) 183 } 184 185 func (e *elfFile) Write16At(data uint16, where uint64) error { 186 e.e.ByteOrder.PutUint16(e.buffer[:], data) 187 return e.WriteAt(e.buffer[:2], where) 188 } 189 190 func (e *elfFile) Write32At(data uint32, where uint64) error { 191 e.e.ByteOrder.PutUint32(e.buffer[:], data) 192 return e.WriteAt(e.buffer[:4], where) 193 } 194 195 func (e *elfFile) Write64At(data uint64, where uint64) error { 196 e.e.ByteOrder.PutUint64(e.buffer[:], data) 197 return e.WriteAt(e.buffer[:8], where) 198 } 199 200 func (e *elfFile) WriteSections() error { 201 if _, err := e.f.Seek(int64(e.shoff), io.SeekStart); err != nil { 202 return err 203 } 204 shstrtab := 0 205 shstrtabpos := e.shoff 206 names := make([]uint64, len(e.e.Sections)) 207 for i, sec := range e.e.Sections { 208 names[i] = e.shoff - shstrtabpos 209 if err := e.Write(append([]byte(sec.Name), 0)); err != nil { 210 return err 211 } 212 e.shoff += uint64(len(sec.Name)) + 1 213 if sec.Name == ".shstrtab" { 214 shstrtab = i 215 } 216 } 217 e.e.Sections[shstrtab].Offset = shstrtabpos 218 e.e.Sections[shstrtab].FileSize = e.shoff - shstrtabpos 219 220 for i, sec := range e.e.Sections { 221 if err := e.WriteSection(sec.SectionHeader, names[i]); err != nil { 222 return err 223 } 224 } 225 switch e.e.Class { 226 case elf.ELFCLASS32: 227 if err := e.Write32At(uint32(e.shoff), 0x20); err != nil { 228 return err 229 } 230 if err := e.Write16At(uint16(len(e.e.Sections)), 0x30); err != nil { 231 return err 232 } 233 case elf.ELFCLASS64: 234 if err := e.Write64At(e.shoff, 0x28); err != nil { 235 return err 236 } 237 if err := e.Write16At(uint16(len(e.e.Sections)), 0x3C); err != nil { 238 return err 239 } 240 } 241 return nil 242 } 243 244 func (e *elfFile) WriteSection(sh elf.SectionHeader, name uint64) error { 245 switch e.e.Class { 246 case elf.ELFCLASS32: 247 hdr := elf.Section32{ 248 Name: uint32(name), 249 Type: uint32(sh.Type), 250 Flags: uint32(sh.Flags), 251 Addr: uint32(sh.Addr), 252 Off: uint32(sh.Offset), 253 Size: uint32(sh.FileSize), 254 Link: sh.Link, 255 Info: sh.Info, 256 Addralign: uint32(sh.Addralign), 257 Entsize: uint32(sh.Entsize), 258 } 259 return e.WriteData(hdr) 260 case elf.ELFCLASS64: 261 hdr := elf.Section64{ 262 Name: uint32(name), 263 Type: uint32(sh.Type), 264 Flags: uint64(sh.Flags), 265 Addr: sh.Addr, 266 Off: sh.Offset, 267 Size: sh.FileSize, 268 Link: sh.Link, 269 Info: sh.Info, 270 Addralign: sh.Addralign, 271 Entsize: sh.Entsize, 272 } 273 return e.WriteData(hdr) 274 } 275 // compression header not handeled 276 return errors.New("Unknown elf bit size") 277 } 278 279 func (e *elfFile) WritePrograms() error { 280 if _, err := e.Seek(int64(e.phoff), io.SeekStart); err != nil { 281 return err 282 } 283 for _, prog := range e.e.Progs { 284 if err := e.WriteProgram(prog.ProgHeader); err != nil { 285 return err 286 } 287 } 288 switch e.e.Class { 289 case elf.ELFCLASS32: 290 if err := e.Write32At(uint32(e.phoff), 0x1C); err != nil { 291 return err 292 } 293 if err := e.Write16At(uint16(len(e.e.Progs)), 0x2C); err != nil { 294 return err 295 } 296 case elf.ELFCLASS64: 297 if err := e.Write64At(e.phoff, 0x20); err != nil { 298 return err 299 } 300 if err := e.Write16At(uint16(len(e.e.Progs)), 0x38); err != nil { 301 return err 302 } 303 } 304 return nil 305 } 306 307 func (e *elfFile) WriteProgram(ph elf.ProgHeader) error { 308 switch e.e.Class { 309 case elf.ELFCLASS32: 310 hdr := elf.Prog32{ 311 Type: uint32(ph.Type), 312 Flags: uint32(ph.Flags), 313 Off: uint32(ph.Off), 314 Vaddr: uint32(ph.Vaddr), 315 Paddr: uint32(ph.Paddr), 316 Filesz: uint32(ph.Filesz), 317 Memsz: uint32(ph.Memsz), 318 Align: uint32(ph.Align), 319 } 320 return e.WriteData(hdr) 321 case elf.ELFCLASS64: 322 hdr := elf.Prog64{ 323 Type: uint32(ph.Type), 324 Flags: uint32(ph.Flags), 325 Off: ph.Off, 326 Vaddr: ph.Vaddr, 327 Paddr: ph.Paddr, 328 Filesz: ph.Filesz, 329 Memsz: ph.Memsz, 330 Align: ph.Align, 331 } 332 return e.WriteData(hdr) 333 } 334 return errors.New("Unknown elf bit size") 335 } 336 337 func (e *elfFile) Read(b []byte) error { 338 _, err := e.f.Read(b) 339 return err 340 } 341 342 func (e *elfFile) Copy(src, dst int64, length int) error { 343 buffer := make([]byte, length) 344 _, err := e.Seek(src, io.SeekStart) 345 if err != nil { 346 return err 347 } 348 err = e.Read(buffer) 349 if err != nil { 350 return err 351 } 352 _, err = e.Seek(dst, io.SeekStart) 353 if err != nil { 354 return err 355 } 356 err = e.Write(buffer) 357 if err != nil { 358 return err 359 } 360 return nil 361 } 362 363 func (e *elfFile) Close() error { 364 return e.f.Close() 365 } 366 367 // Dyn contains a single entry of the dynamic table 368 type Dyn struct { 369 Tag elf.DynTag 370 Val uint64 371 } 372 373 func padding(addr, align uint64) uint64 { 374 align1 := align - 1 375 return (align - (addr & align1)) & align1 376 } 377 378 // DynSymbol represents a dynamic symbol 379 type DynSymbol struct { 380 Name string 381 Value uint64 382 Size uint64 383 Bind elf.SymBind 384 Type elf.SymType 385 Vis elf.SymVis 386 Section int 387 } 388 389 func (e *elfFile) makeDynsym(elements []DynSymbol) (dynsym, dynstr []byte) { 390 sym := &bytes.Buffer{} 391 str := &bytes.Buffer{} 392 for _, elem := range elements { 393 namei := str.Len() 394 str.Write(append([]byte(elem.Name), 0)) 395 switch e.e.Class { 396 case elf.ELFCLASS32: 397 binary.Write(sym, e.e.ByteOrder, elf.Sym32{ 398 Name: uint32(namei), 399 Value: uint32(elem.Value), 400 Size: uint32(elem.Size), 401 Info: byte(elem.Bind)<<4 | byte(elem.Type)&0x0f, 402 Other: byte(elem.Vis) & 0x03, 403 Shndx: uint16(elem.Section), 404 }) 405 case elf.ELFCLASS64: 406 binary.Write(sym, e.e.ByteOrder, elf.Sym64{ 407 Name: uint32(namei), 408 Value: uint64(elem.Value), 409 Size: uint64(elem.Size), 410 Info: byte(elem.Bind)<<4 | byte(elem.Type)&0x0f, 411 Other: byte(elem.Vis) & 0x03, 412 Shndx: uint16(elem.Section), 413 }) 414 } 415 } 416 if str.Len() == 0 { 417 str.WriteByte(0) 418 } 419 return sym.Bytes(), str.Bytes() 420 } 421 422 func (e *elfFile) makeDynsec(elements []Dyn) []byte { 423 ret := &bytes.Buffer{} 424 switch e.e.Class { 425 case elf.ELFCLASS32: 426 var secs []elf.Dyn32 427 for _, sec := range elements { 428 secs = append(secs, elf.Dyn32{ 429 Tag: int32(sec.Tag), 430 Val: uint32(sec.Val), 431 }) 432 } 433 binary.Write(ret, e.e.ByteOrder, secs) 434 case elf.ELFCLASS64: 435 var secs []elf.Dyn64 436 for _, sec := range elements { 437 secs = append(secs, elf.Dyn64{ 438 Tag: int64(sec.Tag), 439 Val: uint64(sec.Val), 440 }) 441 } 442 binary.Write(ret, e.e.ByteOrder, secs) 443 } 444 return ret.Bytes() 445 } 446 447 // RelSymbol represents a symbol in need of relocation 448 type RelSymbol struct { 449 Off uint64 450 SymNo uint64 451 } 452 453 func (e *elfFile) makeDynRel(symbols []RelSymbol) ([]byte, bool, uint64) { 454 ret := &bytes.Buffer{} 455 var rela bool 456 var relt uint64 457 switch e.e.Machine { 458 case elf.EM_386: 459 rela = false 460 relt = uint64(elf.R_386_JMP_SLOT) 461 case elf.EM_X86_64: 462 rela = true 463 relt = uint64(elf.R_X86_64_JMP_SLOT) 464 default: 465 log.Fatal("Unknown machine type ", e.e.Machine) 466 } 467 468 var relsz uint64 469 470 switch e.e.Class { 471 case elf.ELFCLASS32: 472 if rela { 473 for _, symbol := range symbols { 474 binary.Write(ret, e.e.ByteOrder, elf.Rela32{ 475 Off: uint32(symbol.Off), 476 Info: uint32(symbol.SymNo<<8 | relt), 477 }) 478 } 479 relsz = 12 480 } else { 481 for _, symbol := range symbols { 482 483 binary.Write(ret, e.e.ByteOrder, elf.Rel32{ 484 Off: uint32(symbol.Off), 485 Info: uint32(symbol.SymNo<<8 | relt), 486 }) 487 } 488 relsz = 8 489 } 490 case elf.ELFCLASS64: 491 if rela { 492 for _, symbol := range symbols { 493 binary.Write(ret, e.e.ByteOrder, elf.Rela64{ 494 Off: symbol.Off, 495 Info: symbol.SymNo<<32 | relt, 496 }) 497 } 498 relsz = 24 499 } else { 500 for _, symbol := range symbols { 501 binary.Write(ret, e.e.ByteOrder, elf.Rel64{ 502 Off: symbol.Off, 503 Info: symbol.SymNo<<32 | relt, 504 }) 505 } 506 relsz = 16 507 } 508 } 509 return ret.Bytes(), rela, relsz 510 } 511 512 func main() { 513 doCopy() 514 f, err := openElfFile(out) 515 if err != nil { 516 log.Fatal(err) 517 } 518 519 /* 520 KEEP EXEC (we are not dyn after all) 521 try to put new program headers, dyn, interp into first 4k 522 0 -+-----------------------------------+-- 523 | ELF | 524 +-----------------------------------+ 525 | program headers | 526 +-----------------------------------+ 527 | interp | 528 +-----------------------------------+ 529 should be | dyn stuff | 530 below 4k ->+-----------------------------------+ 531 | other stuff that needs relocation | 532 +-----------------------------------+<- ensure mapping until here 533 +-----------------------------------+ 534 entry -> | Everything else (e.g., text) | 535 +-----------------------------------+ 536 | .shstrtab | 537 +-----------------------------------+ 538 | Section headers | 539 +-----------------------------------+ 540 */ 541 542 // First some sanity checks - and checks if we can do our meddling, after all we don't support everything in this POC 543 544 if f.e.Type != elf.ET_EXEC { 545 log.Fatal("only static binaries not using an interp supported") 546 } 547 548 var base uint64 549 var baseProg int 550 551 for i, prog := range f.e.Progs { 552 if prog.Type == elf.PT_INTERP || prog.Type == elf.PT_DYNAMIC { 553 log.Fatal("only static binaries not using an interp supported") 554 } 555 if prog.Type == elf.PT_LOAD { 556 if base == 0 { 557 base = prog.Vaddr 558 baseProg = i 559 } else if prog.Vaddr < base { 560 base = prog.Vaddr 561 baseProg = i 562 } 563 } 564 } 565 566 if uint64(f.phoff+f.phentsize*uint64(len(f.e.Progs))) > f.e.Entry { 567 log.Fatal("Not enough space before entry point") 568 } 569 570 interpProg := len(f.e.Progs) 571 572 f.e.Progs = append(f.e.Progs, &elf.Prog{ 573 ProgHeader: elf.ProgHeader{ 574 Type: elf.PT_INTERP, 575 Flags: elf.PF_R, 576 Off: 0, // fill later 577 Vaddr: 0, // fill later 578 Paddr: 0, // fill later 579 Filesz: 0, // fill later 580 Memsz: 0, // fill later 581 Align: 1, 582 }}) 583 584 dynsecProg := len(f.e.Progs) 585 586 f.e.Progs = append(f.e.Progs, &elf.Prog{ 587 ProgHeader: elf.ProgHeader{ 588 Type: elf.PT_DYNAMIC, 589 Flags: elf.PF_R | elf.PF_W, 590 Off: 0, // fill later 591 Vaddr: 0, // fill later 592 Paddr: 0, // fill later 593 Filesz: 0, // fill later 594 Memsz: 0, // fill later 595 Align: 8, 596 }}) 597 598 interpPos := f.phoff + f.phentsize*uint64(len(f.e.Progs)) 599 interpB := append([]byte(interp), 0) 600 interpLen := uint64(len(interpB)) 601 602 f.e.Progs[interpProg].Off = interpPos 603 f.e.Progs[interpProg].Vaddr = interpPos + base 604 f.e.Progs[interpProg].Paddr = interpPos + base 605 f.e.Progs[interpProg].Filesz = interpLen 606 f.e.Progs[interpProg].Memsz = interpLen 607 608 hashPos := interpPos + interpLen 609 hashPos += padding(hashPos, 8) 610 hash := make([]byte, 8*4) // Empty 64bit DT_HASH 611 hashLen := uint64(len(hash)) 612 613 var relList []RelSymbol 614 615 var symsection int 616 617 symbolList, err := f.e.Symbols() 618 if err != nil { 619 log.Fatal(err) 620 } 621 622 var symdefs []DynSymbol 623 624 symdefs = append(symdefs, DynSymbol{ 625 Name: "", 626 Value: 0, 627 Size: 0, 628 Bind: elf.STB_LOCAL, 629 Type: elf.STT_NOTYPE, 630 Vis: elf.STV_DEFAULT, 631 Section: int(elf.SHN_UNDEF), 632 }) 633 634 x_cgo_init := uint64(0) 635 _cgo_init := uint64(0) 636 _cgo_size := uint64(0) 637 638 for _, sym := range symbolList { 639 if strings.HasSuffix(sym.Name, "__dynload") { 640 parts := strings.Split(sym.Name, ".") 641 name := parts[len(parts)-1] 642 dynsym := name[:len(name)-9] 643 644 symsection = int(sym.Section) 645 relList = append(relList, RelSymbol{ 646 Off: sym.Value, 647 SymNo: uint64(len(symdefs)), 648 }) 649 symdefs = append(symdefs, DynSymbol{ 650 Name: dynsym, 651 Value: 0, 652 Size: 0, 653 Bind: elf.STB_GLOBAL, 654 Type: elf.STT_FUNC, 655 Vis: elf.STV_DEFAULT, 656 Section: int(elf.SHN_UNDEF), 657 }) 658 } 659 if sym.Name == "x_cgo_init" { 660 x_cgo_init = sym.Value 661 } 662 if sym.Name == "_cgo_init" { 663 sec := f.e.Sections[sym.Section] 664 _cgo_init = sym.Value - sec.Addr + sec.Offset 665 _cgo_size = sym.Size 666 } 667 } 668 669 if x_cgo_init != 0 && _cgo_init != 0 && _cgo_size != 0 { 670 switch _cgo_size { 671 case 4: 672 f.Write32At(uint32(x_cgo_init), _cgo_init) 673 case 8: 674 f.Write64At(x_cgo_init, _cgo_init) 675 default: 676 log.Fatalln("Unknown symbol size", _cgo_size) 677 } 678 } 679 680 dynsym, dynstr := f.makeDynsym(symdefs) 681 682 var libOffsets []uint64 683 684 for _, l := range libs { 685 libOffsets = append(libOffsets, uint64(len(dynstr))) 686 dynstr = append(dynstr, []byte(l)...) 687 dynstr = append(dynstr, 0) 688 } 689 690 dynsymLocal := 0 691 dynstrPos := hashPos + hashLen 692 dynstrLen := uint64(len(dynstr)) 693 694 dynsymPos := dynstrPos + dynstrLen 695 dynsymPos += padding(dynsymPos, 8) 696 dynsymLen := uint64(len(dynsym)) 697 698 // TODO: DT_BIND_NOW? 699 700 dynrel, rela, relsz := f.makeDynRel(relList) 701 dynrelPos := dynsymPos + dynsymLen 702 dynrelPos += padding(dynrelPos, 8) 703 dynrelLen := uint64(len(dynrel)) 704 705 var dynsecs []Dyn 706 for _, offset := range libOffsets { 707 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_NEEDED, Val: uint64(offset)}) 708 } 709 710 if rela { 711 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELA, Val: uint64(base + dynrelPos)}) 712 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELASZ, Val: uint64(dynrelLen)}) 713 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELAENT, Val: uint64(relsz)}) 714 } else { 715 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_REL, Val: uint64(base + dynrelPos)}) 716 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELSZ, Val: uint64(dynrelLen)}) 717 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELENT, Val: uint64(relsz)}) 718 } 719 720 dynsecs = append(dynsecs, []Dyn{ 721 {Tag: elf.DT_STRTAB, Val: base + dynstrPos}, 722 {Tag: elf.DT_STRSZ, Val: dynstrLen}, 723 {Tag: elf.DT_SYMTAB, Val: base + dynsymPos}, 724 {Tag: elf.DT_SYMENT, Val: dynsymLen}, 725 {Tag: elf.DT_HASH, Val: hashPos + base}, 726 {Tag: elf.DT_BIND_NOW, Val: 0}, 727 {Tag: elf.DT_NULL, Val: 0}, 728 }...) 729 730 dynsec := f.makeDynsec(dynsecs) 731 dynsecPos := dynrelPos + dynrelLen 732 dynsecPos += padding(dynsecPos, 8) 733 dynsecLen := uint64(len(dynsec)) 734 735 f.e.Progs[dynsecProg].Off = dynsecPos 736 f.e.Progs[dynsecProg].Vaddr = dynsecPos + base 737 f.e.Progs[dynsecProg].Paddr = dynsecPos + base 738 f.e.Progs[dynsecProg].Filesz = dynsecLen 739 f.e.Progs[dynsecProg].Memsz = dynsecLen 740 741 afterDynsec := dynsecPos + dynsecLen 742 743 relPos := afterDynsec 744 var torelocate []*elf.Section 745 relocated := make(map[int]bool) 746 747 for { 748 var newRelocate []*elf.Section 749 for i, sec := range f.e.Sections { 750 if sec.Type == elf.SHT_NULL { 751 continue 752 } 753 if sec.Offset < relPos && !relocated[i] { 754 newRelocate = append(newRelocate, sec) 755 relocated[i] = true 756 } 757 } 758 if len(newRelocate) == 0 { 759 break 760 } 761 torelocate = append(torelocate, newRelocate...) 762 763 sort.Slice(torelocate, func(i, j int) bool { return torelocate[i].Offset < torelocate[j].Offset }) 764 relPos = afterDynsec 765 for _, sec := range torelocate { 766 relPos += sec.Size 767 if sec.Addralign > 1 { 768 relPos += padding(relPos, sec.Addralign) 769 } 770 } 771 } 772 773 for _, sec := range torelocate { 774 data := make([]byte, sec.Size) 775 if _, err := f.f.ReadAt(data, int64(sec.Offset)); err != nil { 776 log.Fatal(err) 777 } 778 if sec.Addralign > 1 { 779 afterDynsec += padding(afterDynsec, sec.Addralign) 780 } 781 if err := f.WriteAt(data, afterDynsec); err != nil { 782 log.Fatal(err) 783 } 784 for _, prog := range f.e.Progs { 785 if prog.Off == sec.Offset { 786 prog.Off = afterDynsec 787 } 788 if prog.Vaddr == sec.Offset+base { 789 prog.Vaddr = afterDynsec + base 790 prog.Paddr = afterDynsec + base 791 } 792 } 793 794 sec.Addr += afterDynsec - sec.Offset // or base + offset 795 sec.Offset, afterDynsec = afterDynsec, afterDynsec+sec.Offset 796 } 797 798 if afterDynsec > f.e.Entry { 799 log.Fatal("not enough space before entry point") 800 } 801 802 if f.e.Progs[baseProg].Filesz < afterDynsec { 803 f.e.Progs[baseProg].Filesz = afterDynsec 804 f.e.Progs[baseProg].Memsz = afterDynsec 805 } 806 807 if err := f.WritePrograms(); err != nil { 808 log.Fatal(err) 809 } 810 811 if err := f.WriteAt(interpB, interpPos); err != nil { 812 log.Fatal(err) 813 } 814 815 if err := f.WriteAt(hash, hashPos); err != nil { 816 log.Fatal(err) 817 } 818 819 if err := f.WriteAt(dynstr, dynstrPos); err != nil { 820 log.Fatal(err) 821 } 822 823 if err := f.WriteAt(dynsym, dynsymPos); err != nil { 824 log.Fatal(err) 825 } 826 827 if err := f.WriteAt(dynrel, dynrelPos); err != nil { 828 log.Fatal(err) 829 } 830 831 if err := f.WriteAt(dynsec, dynsecPos); err != nil { 832 log.Fatal(err) 833 } 834 835 f.e.Sections = append(f.e.Sections, &elf.Section{ 836 SectionHeader: elf.SectionHeader{ 837 Name: ".interp", 838 Type: elf.SHT_PROGBITS, 839 Flags: elf.SHF_ALLOC, 840 Addr: base + interpPos, 841 Offset: interpPos, 842 FileSize: interpLen, 843 Addralign: 1, 844 }}) 845 846 dynstrI := len(f.e.Sections) 847 848 f.e.Sections = append(f.e.Sections, &elf.Section{ 849 SectionHeader: elf.SectionHeader{ 850 Name: ".dynstr", 851 Type: elf.SHT_STRTAB, 852 Flags: elf.SHF_ALLOC, 853 Addr: base + dynstrPos, 854 Offset: dynstrPos, 855 FileSize: dynstrLen, 856 Addralign: 1, 857 }}) 858 859 entSize := uint64(24) 860 if f.e.Class == elf.ELFCLASS32 { 861 entSize = 16 862 } 863 864 dynsymSec := len(f.e.Sections) 865 866 f.e.Sections = append(f.e.Sections, &elf.Section{ 867 SectionHeader: elf.SectionHeader{ 868 Name: ".dynsym", 869 Type: elf.SHT_DYNSYM, 870 Flags: elf.SHF_ALLOC, 871 Addr: base + dynsymPos, 872 Offset: dynsymPos, 873 FileSize: dynsymLen, 874 Addralign: 8, 875 Link: uint32(dynstrI), 876 Entsize: entSize, 877 Info: uint32(dynsymLocal + 1), 878 }}) 879 880 entSize = uint64(16) 881 if f.e.Class == elf.ELFCLASS32 { 882 entSize = 8 883 } 884 885 f.e.Sections = append(f.e.Sections, &elf.Section{ 886 SectionHeader: elf.SectionHeader{ 887 Name: ".dynamic", 888 Type: elf.SHT_DYNAMIC, 889 Flags: elf.SHF_ALLOC | elf.SHF_WRITE, 890 Addr: base + dynsecPos, 891 Offset: dynsecPos, 892 FileSize: dynsecLen, 893 Addralign: 8, 894 Link: uint32(dynstrI), 895 Entsize: entSize, 896 }}) 897 898 dynname := ".rel" 899 if rela { 900 dynname = ".rela" 901 } 902 dynname += f.e.Sections[symsection].Name 903 904 shtype := elf.SHT_REL 905 if rela { 906 shtype = elf.SHT_RELA 907 } 908 909 f.e.Sections = append(f.e.Sections, &elf.Section{ 910 SectionHeader: elf.SectionHeader{ 911 Name: dynname, 912 Type: shtype, 913 Flags: elf.SHF_ALLOC, 914 Addr: base + dynrelPos, 915 Offset: dynrelPos, 916 FileSize: dynrelLen, 917 Addralign: 8, 918 Link: uint32(dynsymSec), 919 Info: uint32(symsection), 920 Entsize: relsz, 921 }}) 922 923 f.e.Sections = append(f.e.Sections, &elf.Section{ 924 SectionHeader: elf.SectionHeader{ 925 Name: ".hash", 926 Type: elf.SHT_HASH, 927 Flags: elf.SHF_ALLOC, 928 Addr: base + hashPos, 929 Offset: hashPos, 930 FileSize: hashLen, 931 Addralign: 8, 932 Link: uint32(dynsymSec), 933 }}) 934 935 shoff, err := f.f.Seek(0, io.SeekEnd) 936 if err != nil { 937 log.Fatal(err) 938 } 939 f.shoff = uint64(shoff) 940 941 if err := f.WriteSections(); err != nil { 942 log.Fatal(err) 943 } 944 945 f.Close() 946 }