gaulthiergain-tools/srcs/binarytool/run_binarytool.go
2021-12-07 10:24:33 +01:00

180 lines
4.7 KiB
Go

// Copyright 2019 The UNICORE Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file
//
// Author: Gaulthier Gain <gaulthier.gain@uliege.be>
package binarytool
import (
"errors"
"fmt"
"os"
"strings"
"tools/srcs/binarytool/elf64analyser"
"tools/srcs/binarytool/ukManager"
u "tools/srcs/common"
)
const diffPath = "diff" + u.SEP
const pagesPath = "pages" + u.SEP
// RunBinaryAnalyser allows to run the binary analyser tool (which is out of the
// UNICORE toolchain).
func RunBinaryAnalyser(homeDir string) {
// Init and parse local arguments
args := new(u.Arguments)
p, err := args.InitArguments()
if err != nil {
u.PrintErr(err)
}
if err := parseLocalArguments(p, args); err != nil {
u.PrintErr(err)
}
// Check if a json file is used or if it is via command line
manager := new(ukManager.Manager)
if len(*args.StringArg[listArg]) > 0 {
manager.Unikernels = new(ukManager.Unikernels)
manager.Unikernels.Unikernel = make([]ukManager.Unikernel, len(*args.StringArg[listArg]))
mapping := false
if *args.BoolArg[mappingArg] {
mapping = true
}
list := strings.Split(*args.StringArg[listArg], ",")
for i, arg := range list {
manager.Unikernels.Unikernel[i] = ukManager.Unikernel{
BuildPath: arg,
DisplayMapping: mapping,
}
}
} else if len(*args.StringArg[filesArg]) > 0 {
var err error
manager.Unikernels, err = ukManager.ReadJsonFile(*args.StringArg[filesArg])
if err != nil {
u.PrintErr(err)
}
} else {
u.PrintErr(errors.New("argument(s) must be provided"))
}
var comparison elf64analyser.ComparisonElf
comparison.GroupFileSegment = make([]*elf64analyser.ElfFileSegment, 0)
for i, uk := range manager.Unikernels.Unikernel {
uk.Analyser = new(elf64analyser.ElfAnalyser)
if len(uk.BuildPath) > 0 {
if uk.BuildPath[len(uk.BuildPath)-1] != os.PathSeparator {
uk.BuildPath += u.SEP
}
if err := uk.GetFiles(); err != nil {
u.PrintErr(err)
}
// Perform the inspection of micro-libs since we have the buildPath
uk.Analyser.InspectMappingList(uk.ElfFile, uk.ListObjs)
} else {
if err := uk.GetKernel(); err != nil {
u.PrintErr(err)
}
}
if len(uk.DisplayElfFile) > 0 {
uk.DisplayElfInfo()
}
if uk.DisplayMapping && len(uk.BuildPath) > 0 {
fmt.Printf("==========[(%d): %s]==========\n", i, uk.BuildPath)
uk.Analyser.DisplayMapping()
fmt.Println("=====================================================")
}
if uk.ComputeLibsMapping && len(uk.LibsMapping) > 0 {
if err != nil {
u.PrintErr(err)
} else {
uk.Analyser.ComputeAlignedMapping(uk.ElfFile, uk.LibsMapping)
}
}
if uk.DisplayStatSize {
uk.Analyser.DisplayStatSize(uk.ElfFile)
}
if len(uk.DisplaySectionInfo) > 0 {
uk.Analyser.DisplaySectionInfo(uk.ElfFile, uk.DisplaySectionInfo)
}
if len(uk.FindSectionByAddress) > 0 {
uk.Analyser.FindSectionByAddress(uk.ElfFile, uk.FindSectionByAddress)
}
if uk.CompareGroup > 0 {
foundSection := false
section := uk.SectionSplit
for _, s := range uk.ElfFile.SectionsTable.DataSect {
if s.Name == section {
foundSection = true
break
}
}
if foundSection && len(uk.SectionSplit) > 0 {
path := homeDir + u.SEP + pagesPath
if _, err := os.Stat(path); os.IsNotExist(err) {
err := os.Mkdir(path, os.ModePerm)
if err != nil {
u.PrintErr(err)
}
}
u.PrintInfo(fmt.Sprintf("Splitting %s section of %s into pages...", section, uk.ElfFile.Name))
uk.Analyser.SplitIntoPagesBySection(uk.ElfFile, section)
out := path + section[1:] + u.SEP
if _, err := os.Stat(out); os.IsNotExist(err) {
err := os.Mkdir(out, os.ModePerm)
if err != nil {
u.PrintErr(err)
}
}
if err := elf64analyser.SavePagesToFile(uk.Analyser.ElfPage, out+uk.ElfFile.Name+".txt", false); err != nil {
u.PrintErr(err)
}
u.PrintOk(fmt.Sprintf("Pages of section %s (%s) are saved into %s", section, uk.ElfFile.Name, out))
comparison.GroupFileSegment = append(comparison.GroupFileSegment,
&elf64analyser.ElfFileSegment{Filename: uk.ElfFile.Name,
NbPages: len(uk.Analyser.ElfPage), Pages: uk.Analyser.ElfPage})
} else {
u.PrintWarning("Section '" + section + "' is not found in the ELF file")
}
}
}
if len(comparison.GroupFileSegment) > 1 {
// Perform the comparison
path := homeDir + u.SEP + diffPath
if _, err := os.Stat(path); os.IsNotExist(err) {
err := os.Mkdir(path, os.ModePerm)
if err != nil {
u.PrintErr(err)
}
}
comparison.ComparePageTables()
if err := comparison.DiffComparison(path); err != nil {
u.PrintWarning(err)
}
comparison.DisplayComparison()
}
}