123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113 |
- package main
- import (
- "bufio"
- "debug/elf"
- "flag"
- "fmt"
- "io"
- "math"
- "os"
- "path"
- )
- var dry = flag.Bool("dryrun", true, "don't really do it")
- func gencode(w io.Writer, n, t string, m []byte, start, end uint64) {
- fmt.Fprintf(os.Stderr, "Write %v %v start %v end %v\n", n, t, start, end)
- fmt.Fprintf(w, "int %v_%v_start = %v;\n", n, t, start)
- fmt.Fprintf(w, "int %v_%v_end = %v;\n", n, t, end)
- fmt.Fprintf(w, "int %v_%v_len = %v;\n", n, t, end-start)
- fmt.Fprintf(w, "uint8_t %v_%v_out[] = {\n", n, t)
- for i := uint64(start); i < end; i += 16 {
- for j := uint64(0); i+j < end && j < 16; j++ {
- fmt.Fprintf(w, "0x%02x, ", m[j+i])
- }
- fmt.Fprintf(w, "\n")
- }
- fmt.Fprintf(w, "};\n")
- }
- func main() {
- flag.Parse()
- a := flag.Args()
- for _, n := range a {
- f, err := elf.Open(n)
- if err != nil {
- fmt.Printf("%v %v\n", n, err)
- continue
- }
- var dataend, codeend, end uint64
- var datastart, codestart, start uint64
- datastart, codestart, start = math.MaxUint64, math.MaxUint64, math.MaxUint64
- mem := []byte{}
- for _, v := range f.Progs {
- if v.Type != elf.PT_LOAD {
- continue
- }
- fmt.Fprintf(os.Stderr, "processing %v\n", v)
- // MUST alignt to 2M page boundary.
- // then MUST allocate a []byte that
- // is the right size. And MUST
- // see if by some off chance it
- // joins to a pre-existing segment.
- // It's easier than it seems. We produce ONE text
- // array and ONE data array. So it's a matter of creating
- // a virtual memory space with an assumed starting point of
- // 0x200000, and filling it. We just grow that as needed.
- curstart := v.Vaddr & ^uint64(0xfff) // 0x1fffff)
- curend := v.Vaddr + v.Memsz
- fmt.Fprintf(os.Stderr, "s %x e %x\n", curstart, curend)
- if curend > end {
- nmem := make([]byte, curend)
- copy(nmem, mem)
- mem = nmem
- }
- if curstart < start {
- start = curstart
- }
- if v.Flags&elf.PF_X == elf.PF_X {
- if curstart < codestart {
- codestart = curstart
- }
- if curend > codeend {
- codeend = curend
- }
- fmt.Fprintf(os.Stderr, "code s %v e %v\n", codestart, codeend)
- } else {
- if curstart < datastart {
- datastart = curstart
- }
- if curend > dataend {
- dataend = curend
- }
- fmt.Fprintf(os.Stderr, "data s %v e %v\n", datastart, dataend)
- }
- for i := uint64(0); i < v.Filesz; i++ {
- if amt, err := v.ReadAt(mem[v.Vaddr+i:], int64(i)); err != nil && err != io.EOF {
- fmt.Fprintf(os.Stderr, "%v: %v\n", amt, err)
- os.Exit(1)
- } else if amt == 0 {
- if i < v.Filesz {
- fmt.Fprintf(os.Stderr, "%v: Short read: %v of %v\n", v, i, v.Filesz)
- os.Exit(1)
- }
- break
- } else {
- i = i + uint64(amt)
- fmt.Fprintf(os.Stderr, "i now %v\n", i)
- }
- }
- fmt.Fprintf(os.Stderr, "Processed %v\n", v)
- }
- fmt.Fprintf(os.Stderr, "gencode\n")
- // Gen code to stdout. For each file, create an array, a start, and an end variable.
- w := bufio.NewWriter(os.Stdout)
- _, file := path.Split(n)
- gencode(w, file, "code", mem, codestart, codeend)
- gencode(w, file, "data", mem, datastart, dataend)
- w.Flush()
- }
- }
|