1// Copyright 2018 syzkaller project authors. All rights reserved. 2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4// imagegen generates syz_mount_image/syz_read_part_table calls from disk images. 5package main 6 7import ( 8 "bytes" 9 "encoding/hex" 10 "flag" 11 "fmt" 12 "io/ioutil" 13 "os" 14) 15 16type Segment struct { 17 offset int 18 data []byte 19} 20 21func main() { 22 flagV := flag.Bool("v", false, "verbose output") 23 flagImage := flag.String("image", "", "image file") 24 flagSkip := flag.Int("skip", 32, "min zero bytes to skip") 25 flagAlign := flag.Int("align", 32, "non-zero block alignment") 26 flagFS := flag.String("fs", "", "filesystem") 27 flag.Parse() 28 data, err := ioutil.ReadFile(*flagImage) 29 if err != nil { 30 fmt.Fprintf(os.Stderr, "failed to read input file: %v\n", err) 31 os.Exit(1) 32 } 33 data0 := data 34 zeros := make([]byte, *flagAlign+*flagSkip) 35 var segs []Segment 36 offset := 0 37 for len(data) != 0 { 38 pos := bytes.Index(data, zeros) 39 if pos == -1 { 40 segs = append(segs, Segment{offset, data}) 41 break 42 } 43 pos = (pos + *flagAlign - 1) & ^(*flagAlign - 1) 44 if pos != 0 { 45 segs = append(segs, Segment{offset, data[:pos]}) 46 } 47 for pos < len(data) && data[pos] == 0 { 48 pos++ 49 } 50 pos = pos & ^(*flagAlign - 1) 51 offset += pos 52 data = data[pos:] 53 } 54 totalData := 0 55 for _, seg := range segs { 56 totalData += len(seg.data) 57 } 58 fmt.Fprintf(os.Stderr, "image size: %v, segments: %v, data: %v\n", 59 len(data0), len(segs), totalData) 60 if *flagV { 61 for i, seg := range segs { 62 next := len(data0) 63 if i != len(segs)-1 { 64 next = segs[i+1].offset 65 } 66 skip := next - seg.offset - len(seg.data) 67 fmt.Fprintf(os.Stderr, "segment: %8v-%8v [%8v] -%8v\n", 68 seg.offset, seg.offset+len(seg.data), len(seg.data), skip) 69 } 70 } 71 restored := make([]byte, len(data0)) 72 for _, seg := range segs { 73 copy(restored[seg.offset:], seg.data) 74 } 75 if !bytes.Equal(data0, restored) { 76 fmt.Fprintf(os.Stderr, "restored data differs!\n") 77 os.Exit(1) 78 } 79 if *flagFS == "part" { 80 fmt.Printf(`syz_read_part_table(0x%x, 0x%x, &(0x7f0000000200)=[`, 81 len(data0), len(segs)) 82 addr := 0x7f0000010000 83 for i, seg := range segs { 84 if i != 0 { 85 fmt.Printf(", ") 86 } 87 fmt.Printf(`{&(0x%x)="%v", 0x%x, 0x%x}`, 88 addr, hex.EncodeToString(seg.data), len(seg.data), seg.offset) 89 addr = (addr + len(seg.data) + 0xff) & ^0xff 90 } 91 fmt.Printf("])\n") 92 } else { 93 syscallSuffix := *flagFS 94 if syscallSuffix == "ext2" || syscallSuffix == "ext3" { 95 syscallSuffix = "ext4" 96 } 97 fmt.Printf(`syz_mount_image$%v(&(0x7f0000000000)='%v\x00', &(0x7f0000000100)='./file0\x00',`+ 98 ` 0x%x, 0x%x, &(0x7f0000000200)=[`, 99 syscallSuffix, *flagFS, len(data0), len(segs)) 100 addr := 0x7f0000010000 101 for i, seg := range segs { 102 if i != 0 { 103 fmt.Printf(", ") 104 } 105 fmt.Printf(`{&(0x%x)="%v", 0x%x, 0x%x}`, 106 addr, hex.EncodeToString(seg.data), len(seg.data), seg.offset) 107 addr = (addr + len(seg.data) + 0xff) & ^0xff 108 } 109 fmt.Printf("], 0x0, &(0x%x))\n", addr) 110 } 111} 112