diff --git a/internal/pkg/asm.go b/internal/pkg/asm.go deleted file mode 100644 index 73c63040..00000000 --- a/internal/pkg/asm.go +++ /dev/null @@ -1,293 +0,0 @@ -package pkg - -import ( - "encoding/binary" - "fmt" - "io" - "strconv" - "strings" - "unique" -) - -type AsmMessage struct { - data AsmData - sig AsmSig -} -type AsmGenerator struct { - i uintptr - as chan AsmMessage - lbl []uintptr -} -type AsmSig int - -const ( - AsmSigEnd AsmSig = iota - AsmSigLbl - AsmSigHead - AsmSigVal -) - -// GenerateAll collects all asm sent to this generator and outputs formatted data to the given [io.Writer]. -func (g *AsmGenerator) GenerateAll(w io.Writer) error { - for a := <-g.as; a.sig != AsmSigEnd; a = <-g.as { - switch a.sig { - case AsmSigLbl: - - break - case AsmSigHead: - - break - case AsmSigVal: - _, err := w.Write([]byte(a.data.Line(g))) - if err != nil { - return err - } - break - default: - panic("invalid asm signal") - } - } - return nil -} - -type AsmFormatter struct { - // if false, generate labels. if true, bare idents will be shown. - Real bool - // if true, header data and the dependencies list will be shown. - ShowHeader bool - // if true, don't generate raw byte data (only generate raw assembly). - Raw bool -} -type AsmData interface { - Line(*AsmGenerator) string - Offset(int) -} - -type AsmDataNone struct{} - -func (a AsmDataNone) Line(*AsmGenerator) string { - return "" -} -func (a AsmDataNone) Offset(int) {} - -type AsmLine struct { - pos int - word int - kindData int64 - valueData []byte - indent int - kind string - value string -} - -func (l AsmLine) Line(gen *AsmGenerator) string { - return "" -} -func (l AsmLine) Offset(offset int) { - l.pos += offset -} - -type AsmHeaderLine struct { - pos int - kind string - kindData int64 - label string - id unique.Handle[ID] -} - -var spacingLine = AsmLine{ - pos: -1, - kindData: -1, - valueData: nil, - indent: 0, - kind: "", - value: "", -} - -func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) (s string, err error) { - var lines []AsmLine - sb := new(strings.Builder) - header := true - pos := new(int) - - for err == nil { - if header { - var kind uint64 - var size uint64 - var bsize []byte - p := *pos - if _, kind, err = nextUint64(r, pos); err != nil { - break - } - if bsize, size, err = nextUint64(r, pos); err != nil { - break - } - if showHeader { - lines = append(lines, AsmLine{p, 8, int64(kind), bsize, 0, "head " + intToKind(kind), ""}) - } - for i := 0; uint64(i) < size; i++ { - var did ID - var dkind uint64 - p := *pos - if _, dkind, err = nextUint64(r, pos); err != nil { - break - } - if _, did, err = nextIdent(r, pos); err != nil { - break - } - if showHeader { - lines = append(lines, AsmLine{p, 8, int64(dkind), nil, 1, intToKind(dkind), Encode(did)}) - } - } - header = false - } - var k uint32 - p := *pos - if _, k, err = nextUint32(r, pos); err != nil { - break - } - kind := IRValueKind(k) - switch kind { - case IRKindEnd: - var a uint32 - var ba []byte - if ba, a, err = nextUint32(r, pos); err != nil { - break - } - if a&1 != 0 { - var sum Checksum - if _, sum, err = nextIdent(r, pos); err != nil { - break - } - lines = append(lines, AsmLine{p, 4, int64(kind), ba, 1, "end ", Encode(sum)}) - } else { - lines = append(lines, AsmLine{p, 4, int64(kind), []byte{0, 0, 0, 0}, 1, "end ", ""}) - } - lines = append(lines, spacingLine) - header = true - continue - - case IRKindIdent: - var a []byte - // discard ancillary - if a, _, err = nextUint32(r, pos); err != nil { - break - } - var id ID - if _, id, err = nextIdent(r, pos); err != nil { - break - } - - lines = append(lines, AsmLine{p, 4, int64(kind), a, 1, "id ", Encode(id)}) - continue - case IRKindUint32: - var i uint32 - var bi []byte - if bi, i, err = nextUint32(r, pos); err != nil { - break - } - lines = append(lines, AsmLine{p, 4, int64(kind), bi, 1, "int ", strconv.FormatUint(uint64(i), 10)}) - case IRKindString: - var l uint32 - var bl []byte - if bl, l, err = nextUint32(r, pos); err != nil { - break - } - s := make([]byte, l+(wordSize-(l)%wordSize)%wordSize) - var n int - if n, err = r.Read(s); err != nil { - break - } - *pos = *pos + n - - lines = append(lines, AsmLine{p, 4, int64(kind), bl, 1, "str ", strconv.Quote(string(s[:l]))}) - continue - default: - var bi []byte - if bi, _, err = nextUint32(r, pos); err != nil { - break - } - lines = append(lines, AsmLine{p, 4, int64(kind), bi, 1, "????", ""}) - } - } - if err != io.EOF { - return - } - err = nil - for _, line := range lines { - if raw { - if line.pos != -1 { - sb.WriteString(fmt.Sprintf("%s\t%s\n", line.kind, line.value)) - } - } else { - if line.pos == -1 { - sb.WriteString("\n") - } else if line.word == 4 { - sb.WriteString(fmt.Sprintf("%06x: %04x %04x%s %s %s\n", line.pos, binary.LittleEndian.AppendUint32(nil, uint32(line.kindData)), line.valueData, headerSpacing(showHeader), line.kind, line.value)) - } else { - kind := binary.LittleEndian.AppendUint64(nil, uint64(line.kindData)) - value := line.valueData - if len(value) == 8 { - sb.WriteString(fmt.Sprintf("%06x: %04x %04x %04x %04x %s %s\n", line.pos, kind[:4], kind[4:], value[:4], value[4:], line.kind, line.value)) - } else { - sb.WriteString(fmt.Sprintf("%06x: %04x %04x %s %s\n", line.pos, kind[:4], kind[4:], line.kind, line.value)) - } - - } - } - - } - return sb.String(), err -} -func nextUint32(r io.Reader, pos *int) ([]byte, uint32, error) { - i := make([]byte, 4) - _, err := r.Read(i) - if err != nil { - return i, 0, err - } - p := *pos + 4 - *pos = p - return i, binary.LittleEndian.Uint32(i), nil -} -func nextUint64(r io.Reader, pos *int) ([]byte, uint64, error) { - i := make([]byte, 8) - _, err := r.Read(i) - if err != nil { - return i, 0, err - } - p := *pos + 8 - *pos = p - return i, binary.LittleEndian.Uint64(i), nil -} -func nextIdent(r io.Reader, pos *int) ([]byte, ID, error) { - i := make([]byte, 48) - if _, err := r.Read(i); err != nil { - return i, ID{}, err - } - p := *pos + 48 - *pos = p - return i, ID(i), nil -} -func intToKind(i uint64) string { - switch Kind(i) { - case KindHTTPGet: - return "http" - case KindTar: - return "tar " - case KindExec: - return "exec" - case KindExecNet: - return "exen" - case KindFile: - return "file" - default: - return fmt.Sprintf("$%d ", i-KindCustomOffset) - } -} -func headerSpacing(showHeader bool) string { - if showHeader { - return " " - } - - return "" -}