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