180 lines
4.7 KiB
Go
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()
|
|
}
|
|
}
|