github.com/notti/go-dynamic@v0.0.0-20190619201224-fc443047424c/steps/2_go/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"} 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.Panic("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 | dyn stuff | 530 +-----------------------------------+ 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.Panic("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.Panic("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.Panic("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 for _, sym := range symbolList { 635 if strings.HasSuffix(sym.Name, "__dynload") { 636 parts := strings.Split(sym.Name, ".") 637 name := parts[len(parts)-1] 638 dynsym := name[:len(name)-9] 639 640 symsection = int(sym.Section) 641 relList = append(relList, RelSymbol{ 642 Off: sym.Value, 643 SymNo: uint64(len(symdefs)), 644 }) 645 symdefs = append(symdefs, DynSymbol{ 646 Name: dynsym, 647 Value: 0, 648 Size: 0, 649 Bind: elf.STB_GLOBAL, 650 Type: elf.STT_FUNC, 651 Vis: elf.STV_DEFAULT, 652 Section: int(elf.SHN_UNDEF), 653 }) 654 } 655 } 656 657 dynsym, dynstr := f.makeDynsym(symdefs) 658 659 var libOffsets []uint64 660 661 for _, l := range libs { 662 libOffsets = append(libOffsets, uint64(len(dynstr))) 663 dynstr = append(dynstr, []byte(l)...) 664 dynstr = append(dynstr, 0) 665 } 666 667 dynsymLocal := 0 668 dynstrPos := hashPos + hashLen 669 dynstrLen := uint64(len(dynstr)) 670 671 dynsymPos := dynstrPos + dynstrLen 672 dynsymPos += padding(dynsymPos, 8) 673 dynsymLen := uint64(len(dynsym)) 674 675 // TODO: DT_BIND_NOW? 676 677 dynrel, rela, relsz := f.makeDynRel(relList) 678 dynrelPos := dynsymPos + dynsymLen 679 dynrelPos += padding(dynrelPos, 8) 680 dynrelLen := uint64(len(dynrel)) 681 682 var dynsecs []Dyn 683 for _, offset := range libOffsets { 684 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_NEEDED, Val: uint64(offset)}) 685 } 686 687 if rela { 688 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELA, Val: uint64(base + dynrelPos)}) 689 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELASZ, Val: uint64(dynrelLen)}) 690 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELAENT, Val: uint64(relsz)}) 691 } else { 692 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_REL, Val: uint64(base + dynrelPos)}) 693 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELSZ, Val: uint64(dynrelLen)}) 694 dynsecs = append(dynsecs, Dyn{Tag: elf.DT_RELENT, Val: uint64(relsz)}) 695 } 696 697 dynsecs = append(dynsecs, []Dyn{ 698 {Tag: elf.DT_STRTAB, Val: base + dynstrPos}, 699 {Tag: elf.DT_STRSZ, Val: dynstrLen}, 700 {Tag: elf.DT_SYMTAB, Val: base + dynsymPos}, 701 {Tag: elf.DT_SYMENT, Val: dynsymLen}, 702 {Tag: elf.DT_HASH, Val: hashPos + base}, 703 {Tag: elf.DT_NULL, Val: 0}, 704 }...) 705 706 dynsec := f.makeDynsec(dynsecs) 707 dynsecPos := dynrelPos + dynrelLen 708 dynsecPos += padding(dynsecPos, 8) 709 dynsecLen := uint64(len(dynsec)) 710 711 f.e.Progs[dynsecProg].Off = dynsecPos 712 f.e.Progs[dynsecProg].Vaddr = dynsecPos + base 713 f.e.Progs[dynsecProg].Paddr = dynsecPos + base 714 f.e.Progs[dynsecProg].Filesz = dynsecLen 715 f.e.Progs[dynsecProg].Memsz = dynsecLen 716 717 afterDynsec := dynsecPos + dynsecLen 718 719 relPos := afterDynsec 720 var torelocate []*elf.Section 721 relocated := make(map[int]bool) 722 723 for { 724 var newRelocate []*elf.Section 725 for i, sec := range f.e.Sections { 726 if sec.Type == elf.SHT_NULL { 727 continue 728 } 729 if sec.Offset < relPos && !relocated[i] { 730 newRelocate = append(newRelocate, sec) 731 relocated[i] = true 732 } 733 } 734 if len(newRelocate) == 0 { 735 break 736 } 737 torelocate = append(torelocate, newRelocate...) 738 739 sort.Slice(torelocate, func(i, j int) bool { return torelocate[i].Offset < torelocate[j].Offset }) 740 relPos = afterDynsec 741 for _, sec := range torelocate { 742 relPos += sec.Size 743 if sec.Addralign > 1 { 744 relPos += padding(relPos, sec.Addralign) 745 } 746 } 747 } 748 749 for _, sec := range torelocate { 750 data := make([]byte, sec.Size) 751 if _, err := f.f.ReadAt(data, int64(sec.Offset)); err != nil { 752 log.Fatal(err) 753 } 754 if sec.Addralign > 1 { 755 afterDynsec += padding(afterDynsec, sec.Addralign) 756 } 757 if err := f.WriteAt(data, afterDynsec); err != nil { 758 log.Fatal(err) 759 } 760 for _, prog := range f.e.Progs { 761 if prog.Off == sec.Offset { 762 prog.Off = afterDynsec 763 } 764 if prog.Vaddr == sec.Offset+base { 765 prog.Vaddr = afterDynsec + base 766 prog.Paddr = afterDynsec + base 767 } 768 } 769 770 sec.Addr += afterDynsec - sec.Offset // or base + offset 771 sec.Offset, afterDynsec = afterDynsec, afterDynsec+sec.Offset 772 } 773 774 if afterDynsec > f.e.Entry { 775 log.Fatal("not enough space before entry point") 776 } 777 778 if f.e.Progs[baseProg].Filesz < afterDynsec { 779 f.e.Progs[baseProg].Filesz = afterDynsec 780 f.e.Progs[baseProg].Memsz = afterDynsec 781 } 782 783 if err := f.WritePrograms(); err != nil { 784 log.Fatal(err) 785 } 786 787 if err := f.WriteAt(interpB, interpPos); err != nil { 788 log.Fatal(err) 789 } 790 791 if err := f.WriteAt(hash, hashPos); err != nil { 792 log.Fatal(err) 793 } 794 795 if err := f.WriteAt(dynstr, dynstrPos); err != nil { 796 log.Fatal(err) 797 } 798 799 if err := f.WriteAt(dynsym, dynsymPos); err != nil { 800 log.Fatal(err) 801 } 802 803 if err := f.WriteAt(dynrel, dynrelPos); err != nil { 804 log.Fatal(err) 805 } 806 807 if err := f.WriteAt(dynsec, dynsecPos); err != nil { 808 log.Fatal(err) 809 } 810 811 f.e.Sections = append(f.e.Sections, &elf.Section{ 812 SectionHeader: elf.SectionHeader{ 813 Name: ".interp", 814 Type: elf.SHT_PROGBITS, 815 Flags: elf.SHF_ALLOC, 816 Addr: base + interpPos, 817 Offset: interpPos, 818 FileSize: interpLen, 819 Addralign: 1, 820 }}) 821 822 dynstrI := len(f.e.Sections) 823 824 f.e.Sections = append(f.e.Sections, &elf.Section{ 825 SectionHeader: elf.SectionHeader{ 826 Name: ".dynstr", 827 Type: elf.SHT_STRTAB, 828 Flags: elf.SHF_ALLOC, 829 Addr: base + dynstrPos, 830 Offset: dynstrPos, 831 FileSize: dynstrLen, 832 Addralign: 1, 833 }}) 834 835 entSize := uint64(24) 836 if f.e.Class == elf.ELFCLASS32 { 837 entSize = 16 838 } 839 840 dynsymSec := len(f.e.Sections) 841 842 f.e.Sections = append(f.e.Sections, &elf.Section{ 843 SectionHeader: elf.SectionHeader{ 844 Name: ".dynsym", 845 Type: elf.SHT_DYNSYM, 846 Flags: elf.SHF_ALLOC, 847 Addr: base + dynsymPos, 848 Offset: dynsymPos, 849 FileSize: dynsymLen, 850 Addralign: 8, 851 Link: uint32(dynstrI), 852 Entsize: entSize, 853 Info: uint32(dynsymLocal + 1), 854 }}) 855 856 entSize = uint64(16) 857 if f.e.Class == elf.ELFCLASS32 { 858 entSize = 8 859 } 860 861 f.e.Sections = append(f.e.Sections, &elf.Section{ 862 SectionHeader: elf.SectionHeader{ 863 Name: ".dynamic", 864 Type: elf.SHT_DYNAMIC, 865 Flags: elf.SHF_ALLOC | elf.SHF_WRITE, 866 Addr: base + dynsecPos, 867 Offset: dynsecPos, 868 FileSize: dynsecLen, 869 Addralign: 8, 870 Link: uint32(dynstrI), 871 Entsize: entSize, 872 }}) 873 874 dynname := ".rel" 875 if rela { 876 dynname = ".rela" 877 } 878 dynname += f.e.Sections[symsection].Name 879 880 shtype := elf.SHT_REL 881 if rela { 882 shtype = elf.SHT_RELA 883 } 884 885 f.e.Sections = append(f.e.Sections, &elf.Section{ 886 SectionHeader: elf.SectionHeader{ 887 Name: dynname, 888 Type: shtype, 889 Flags: elf.SHF_ALLOC, 890 Addr: base + dynrelPos, 891 Offset: dynrelPos, 892 FileSize: dynrelLen, 893 Addralign: 8, 894 Link: uint32(dynsymSec), 895 Info: uint32(symsection), 896 Entsize: relsz, 897 }}) 898 899 f.e.Sections = append(f.e.Sections, &elf.Section{ 900 SectionHeader: elf.SectionHeader{ 901 Name: ".hash", 902 Type: elf.SHT_HASH, 903 Flags: elf.SHF_ALLOC, 904 Addr: base + hashPos, 905 Offset: hashPos, 906 FileSize: hashLen, 907 Addralign: 8, 908 Link: uint32(dynsymSec), 909 }}) 910 911 shoff, err := f.f.Seek(0, io.SeekEnd) 912 if err != nil { 913 log.Fatal(err) 914 } 915 f.shoff = uint64(shoff) 916 917 if err := f.WriteSections(); err != nil { 918 log.Fatal(err) 919 } 920 921 f.Close() 922 }