Esempio n. 1
0
// parseSubs parses the graph representations of the given high-level control
// flow primitives. If unable to locate a subgraph, a second attempt is made by
// prepending $GOPATH/src/decomp.org/decomp/cmd/restructure/primitives/ to the
// subgraph path.
func parseSubs(subPaths []string) (subs []*graphs.SubGraph, err error) {
	// Prepend $GOPATH/src/decomp.org/decomp/cmd/restructure/primitives/ to the path
	// of missing subgraphs.
	subDir, err := goutil.SrcDir("decomp.org/decomp/cmd/restructure/primitives")
	if err != nil {
		return nil, errutil.Err(err)
	}
	for i, subPath := range subPaths {
		if ok, _ := osutil.Exists(subPath); !ok {
			subPath = filepath.Join(subDir, subPath)
			subPaths[i] = subPath
		}
	}

	// Parse subgraphs representing control flow primitives.
	for _, subPath := range subPaths {
		sub, err := graphs.ParseSubGraph(subPath)
		if err != nil {
			return nil, errutil.Err(err)
		}
		subs = append(subs, sub)
	}

	return subs, nil
}
Esempio n. 2
0
File: iso.go Progetto: decomp/decomp
// locate parses the provided graphs and tries to locate isomorphisms of the
// subgraph in the graph.
func locate(graphPath, subPath string) error {
	// Parse graph.
	graph, err := dot.ParseFile(graphPath)
	if err != nil {
		return errutil.Err(err)
	}

	// Search for subgraph in GOPATH if not found.
	if ok, _ := osutil.Exists(subPath); !ok {
		dir, err := goutil.SrcDir("decomp.org/decomp/graphs/testdata/primitives")
		if err != nil {
			return errutil.Err(err)
		}
		subPath = filepath.Join(dir, subPath)
	}
	sub, err := graphs.ParseSubGraph(subPath)
	if err != nil {
		return errutil.Err(err)
	}

	// Locate isomorphisms.
	found := false
	if len(flagStart) > 0 {
		// Locate an isomorphism of sub in graph which starts at the node
		// specified by the "-start" flag.
		m, ok := iso.Isomorphism(graph, flagStart, sub)
		if ok {
			found = true
			printMapping(graph, sub, m)
		}
	} else {
		// Locate all isomorphisms of sub in graph.
		var names []string
		for name := range graph.Nodes.Lookup {
			names = append(names, name)
		}
		sort.Strings(names)
		for _, name := range names {
			m, ok := iso.Isomorphism(graph, name, sub)
			if !ok {
				continue
			}
			found = true
			printMapping(graph, sub, m)
		}
	}
	if !found {
		fmt.Println("not found.")
	}

	return nil
}
Esempio n. 3
0
// storeFile stores the given Go source code to the provided file path.
func storeFile(goPath string, file *ast.File) error {
	// Don't force overwrite Go output file.
	if !flagForce {
		if ok, _ := osutil.Exists(goPath); ok {
			return errutil.Newf("output file %q already exists", goPath)
		}
	}
	f, err := os.Create(goPath)
	if err != nil {
		return err
	}
	defer f.Close()
	fset := token.NewFileSet()
	return printer.Fprint(f, fset, file)
}
Esempio n. 4
0
// flac2wav converts the provided FLAC file to a WAV file.
func flac2wav(path string) error {
	// Open FLAC file.
	stream, err := flac.Open(path)
	if err != nil {
		return err
	}
	defer stream.Close()

	// Create WAV file.
	wavPath := pathutil.TrimExt(path) + ".wav"
	if !flagForce {
		exists, err := osutil.Exists(wavPath)
		if err != nil {
			return err
		}
		if exists {
			return fmt.Errorf("the file %q exists already", wavPath)
		}
	}
	fw, err := os.Create(wavPath)
	if err != nil {
		return err
	}
	defer fw.Close()

	// Create WAV encoder.
	conf := audio.Config{
		Channels:   int(stream.Info.NChannels),
		SampleRate: int(stream.Info.SampleRate),
	}
	enc, err := wav.NewEncoder(fw, conf)
	if err != nil {
		return err
	}
	defer enc.Close()

	for {
		// Decode FLAC audio samples.
		frame, err := stream.ParseNext()
		if err != nil {
			if err == io.EOF {
				break
			}
			return err
		}

		// Encode WAV audio samples.
		samples := make(audio.Int16, 1)
		for i := 0; i < int(frame.BlockSize); i++ {
			for _, subframe := range frame.Subframes {
				samples[0] = int16(subframe.Samples[i])
				_, err = enc.Write(samples)
				if err != nil {
					return err
				}
			}
		}
	}

	return nil
}
Esempio n. 5
0
// ll2go parses the provided LLVM IR assembly file and decompiles it to Go
// source code.
func ll2go(llPath string) error {
	// File name and file path without extension.
	baseName := pathutil.FileName(llPath)
	basePath := pathutil.TrimExt(llPath)

	// TODO: Create graphs in /tmp/xxx_graphs/*.dot

	// Create temporary foo.dot file, e.g.
	//
	//    foo.ll -> foo_graphs/*.dot
	dotDir := basePath + "_graphs"
	if ok, _ := osutil.Exists(dotDir); !ok {
		if !flagQuiet {
			log.Printf("Creating control flow graphs for %q.\n", filepath.Base(llPath))
		}
		cmd := exec.Command("ll2dot", "-q", "-funcs", flagFuncs, "-f", llPath)
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		err := cmd.Run()
		if err != nil {
			return errutil.Err(err)
		}
	}

	// Create temporary foo.bc file, e.g.
	//
	//    foo.ll -> foo.bc
	bcPath := fmt.Sprintf("/tmp/%s.bc", baseName)
	cmd := exec.Command("llvm-as", "-o", bcPath, llPath)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	err := cmd.Run()
	if err != nil {
		return errutil.Err(err)
	}

	// Remove temporary foo.bc file.
	defer func() {
		err = os.Remove(bcPath)
		if err != nil {
			log.Fatalln(errutil.Err(err))
		}
	}()

	// Parse foo.bc
	module, err := llvm.ParseBitcodeFile(bcPath)
	if err != nil {
		return errutil.Err(err)
	}
	defer module.Dispose()

	// Get function names.
	var funcNames []string
	if len(flagFuncs) > 0 {
		// Get function names from command line flag:
		//
		//    -funcs="foo,bar"
		funcNames = strings.Split(flagFuncs, ",")
	} else {
		// Get all function names.
		for llFunc := module.FirstFunction(); !llFunc.IsNil(); llFunc = llvm.NextFunction(llFunc) {
			if llFunc.IsDeclaration() {
				// Ignore function declarations (e.g. functions without bodies).
				continue
			}
			funcNames = append(funcNames, llFunc.Name())
		}
	}

	// Locate package name.
	pkgName := flagPkgName
	if len(flagPkgName) == 0 {
		pkgName = baseName
		for _, funcName := range funcNames {
			if funcName == "main" {
				pkgName = "main"
				break
			}
		}
	}

	// Create foo.go.
	file := &ast.File{
		Name: newIdent(pkgName),
	}

	// TODO: Implement support for global variables.

	// Parse each function.
	for _, funcName := range funcNames {
		if !flagQuiet {
			log.Printf("Parsing function: %q\n", funcName)
		}
		graph, err := parseCFG(basePath, funcName)
		if err != nil {
			return errutil.Err(err)
		}

		// Structure the CFG.
		dotDir := basePath + "_graphs"
		dotName := funcName + ".dot"
		dotPath := path.Join(dotDir, dotName)
		jsonName := funcName + ".json"
		jsonPath := path.Join(dotDir, jsonName)
		if ok, _ := osutil.Exists(jsonPath); !ok {
			cmd := exec.Command("restructure", "-o", jsonPath, dotPath)
			cmd.Stdout = os.Stdout
			cmd.Stderr = os.Stderr
			if !flagQuiet {
				log.Printf("Structuring function: %q\n", funcName)
			}
			err = cmd.Run()
			if err != nil {
				return errutil.Err(err)
			}
		}
		var hprims []*xprimitive.Primitive
		fr, err := os.Open(jsonPath)
		if err != nil {
			return errutil.Err(err)
		}
		defer fr.Close()
		dec := json.NewDecoder(fr)
		err = dec.Decode(&hprims)
		if err != nil {
			return errutil.Err(err)
		}

		f, err := parseFunc(graph, module, funcName, hprims)
		if err != nil {
			return errutil.Err(err)
		}
		file.Decls = append(file.Decls, f)
		if flagVerbose && !flagQuiet {
			printFunc(f)
		}
	}

	// Store Go source code to file.
	goPath := basePath + ".go"
	if !flagQuiet {
		log.Printf("Creating: %q\n", goPath)
	}
	return storeFile(goPath, file)
}
Esempio n. 6
0
func initialize() (err error) {
	Updates = make(map[string]bool)

	// Will set nyfiken root differently depending on operating system.
	setNyfikenRoot()
	ConfigPath = NyfikenRoot + "/config.ini"
	PagesPath = NyfikenRoot + "/pages.ini"
	UpdatesPath = NyfikenRoot + "/updates.gob"

	CacheRoot = NyfikenRoot + "/cache/"
	ReadRoot = NyfikenRoot + "/read/"
	DebugRoot = NyfikenRoot + "/debug/"
	DebugCacheRoot = NyfikenRoot + "/debug/cache/"
	DebugReadRoot = NyfikenRoot + "/debug/read/"

	// Load uncleared updates from last execution.
	err = LoadUpdates()
	if err != nil {
		return errutil.Err(err)
	}

	// Create a nyfiken config folder if it doesn't exist.
	found, err := osutil.Exists(NyfikenRoot)
	if err != nil {
		return errutil.Err(err)
	}
	if !found {
		err := os.Mkdir(NyfikenRoot, DefaultFolderPerms)
		if err != nil {
			return errutil.Err(err)
		}
	}

	found, err = osutil.Exists(CacheRoot)
	if err != nil {
		return errutil.Err(err)
	}
	if !found {
		err := os.Mkdir(CacheRoot, DefaultFolderPerms)
		if err != nil {
			return errutil.Err(err)
		}
	}

	found, err = osutil.Exists(ReadRoot)
	if err != nil {
		return errutil.Err(err)
	}
	if !found {
		err := os.Mkdir(ReadRoot, DefaultFolderPerms)
		if err != nil {
			return errutil.Err(err)
		}
	}

	found, err = osutil.Exists(DebugRoot)
	if err != nil {
		return errutil.Err(err)
	}
	if !found {
		err := os.Mkdir(DebugRoot, DefaultFolderPerms)
		if err != nil {
			return errutil.Err(err)
		}
	}

	found, err = osutil.Exists(DebugCacheRoot)
	if err != nil {
		return errutil.Err(err)
	}
	if !found {
		err := os.Mkdir(DebugCacheRoot, DefaultFolderPerms)
		if err != nil {
			return errutil.Err(err)
		}
	}

	found, err = osutil.Exists(DebugReadRoot)
	if err != nil {
		return errutil.Err(err)
	}
	if !found {
		err := os.Mkdir(DebugReadRoot, DefaultFolderPerms)
		if err != nil {
			return errutil.Err(err)
		}
	}

	return nil
}
Esempio n. 7
0
// flac2wav converts the provided FLAC file to a WAV file.
func flac2wav(path string) error {
	// Open FLAC file.
	fr, err := os.Open(path)
	if err != nil {
		return err
	}
	defer fr.Close()

	// Create FLAC decoder.
	dec, magic, err := audio.NewDecoder(fr)
	if err != nil {
		return err
	}
	fmt.Println("magic:", magic)
	conf := dec.Config()
	fmt.Println("conf:", conf)

	// Create WAV file.
	wavPath := pathutil.TrimExt(path) + ".wav"
	if !flagForce {
		exists, err := osutil.Exists(wavPath)
		if err != nil {
			return err
		}
		if exists {
			return fmt.Errorf("the file %q exists already", wavPath)
		}
	}
	fw, err := os.Create(wavPath)
	if err != nil {
		return err
	}
	defer fw.Close()

	// Create WAV encoder.
	enc, err := wav.NewEncoder(fw, conf)
	if err != nil {
		return err
	}
	defer enc.Close()

	// Encode WAV audio samples copied from the FLAC decoder.
	// TODO(u): Replace with audio.Copy as soon as that doesn't cause audio
	// sample conversions.
	buf := make(audio.PCM16Samples, (32*1024)/8)
	for {
		nr, er := dec.Read(buf)
		if nr > 0 {
			nw, ew := enc.Write(buf[0:nr])
			if ew != nil {
				return ew
			}
			if nr != nw {
				return audio.ErrShortWrite
			}
		}
		if er == audio.EOS {
			return nil
		}
		if er != nil {
			return er
		}
	}
}
Esempio n. 8
0
// locateAndMerge parses the provided graphs and tries to merge isomorphisms of
// the subgraph in the graph into single nodes.
func locateAndMerge(graphPath, subPath string) error {
	// Parse graph.
	graph, err := dot.ParseFile(graphPath)
	if err != nil {
		return errutil.Err(err)
	}

	// Search for subgraph in GOPATH if not found.
	if ok, _ := osutil.Exists(subPath); !ok {
		dir, err := goutil.SrcDir("decomp.org/decomp/graphs/testdata/primitives")
		if err != nil {
			return errutil.Err(err)
		}
		subPath = filepath.Join(dir, subPath)
	}
	sub, err := graphs.ParseSubGraph(subPath)
	if err != nil {
		return errutil.Err(err)
	}

	// Merge isomorphisms.
	found := false
	if len(flagStart) > 0 {
		// Merge an isomorphism of sub in graph which starts at the node
		// specified by the "-start" flag.
		m, ok := iso.Isomorphism(graph, flagStart, sub)
		if ok {
			found = true
			printMapping(graph, sub, m)
			_, err := merge.Merge(graph, m, sub)
			if err != nil {
				return errutil.Err(err)
			}
		}
	} else {
		// Merge all isomorphisms of sub in graph.
		for {
			m, ok := iso.Search(graph, sub)
			if !ok {
				break
			}
			found = true
			printMapping(graph, sub, m)
			_, err := merge.Merge(graph, m, sub)
			if err != nil {
				return errutil.Err(err)
			}
		}
	}

	// Store DOT and PNG representation of graph.
	if found {
		err = dump(graph)
		if err != nil {
			return errutil.Err(err)
		}
	} else {
		fmt.Println("not found.")
	}

	return nil
}