2021-01-30 12:37:27 +01:00
|
|
|
// 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>
|
|
|
|
|
2021-12-07 10:24:33 +01:00
|
|
|
package ukManager
|
2021-01-30 12:37:27 +01:00
|
|
|
|
|
|
|
import (
|
2021-12-10 20:00:22 +01:00
|
|
|
"encoding/json"
|
2021-12-07 21:33:17 +01:00
|
|
|
"fmt"
|
2021-01-30 12:37:27 +01:00
|
|
|
"io/ioutil"
|
2021-12-10 20:00:22 +01:00
|
|
|
"os"
|
2021-01-30 12:37:27 +01:00
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
"tools/srcs/binarytool/elf64analyser"
|
|
|
|
"tools/srcs/binarytool/elf64core"
|
|
|
|
u "tools/srcs/common"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
makefile = "Makefile"
|
|
|
|
config = "config"
|
|
|
|
ldExt = ".ld.o"
|
|
|
|
dbgExt = ".dbg"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Unikernels struct {
|
|
|
|
Unikernel []Unikernel `json:"unikernels"`
|
|
|
|
}
|
|
|
|
|
|
|
|
type Unikernel struct {
|
2021-12-07 10:24:33 +01:00
|
|
|
BuildPath string `json:"buildPath"`
|
|
|
|
Kernel string `json:"kernel"`
|
|
|
|
SectionSplit string `json:"splitSection"`
|
|
|
|
DisplayMapping bool `json:"displayMapping"`
|
|
|
|
DisplayStatSize bool `json:"displayStatSize"`
|
|
|
|
ComputeLibsMapping bool `json:"computeLibsMapping"`
|
|
|
|
|
|
|
|
IgnoredPlats []string `json:"ignoredPlats"`
|
|
|
|
DisplayElfFile []string `json:"displayElfFile"`
|
|
|
|
DisplaySectionInfo []string `json:"displaySectionInfo"`
|
|
|
|
|
2021-01-30 12:37:27 +01:00
|
|
|
FindSectionByAddress []string `json:"findSectionByAddress"`
|
|
|
|
CompareGroup int `json:"compareGroup"`
|
|
|
|
|
2021-12-07 10:24:33 +01:00
|
|
|
// Used to generate new link.lds file
|
|
|
|
ComputeTextAddr string `json:"computeTextAddr"`
|
|
|
|
LibsMapping []string `json:"LibsMapping"`
|
|
|
|
|
2021-01-30 12:37:27 +01:00
|
|
|
ElfFile *elf64core.ELF64File
|
|
|
|
ListObjs []*elf64core.ELF64File
|
|
|
|
Analyser *elf64analyser.ElfAnalyser
|
2021-12-07 21:33:17 +01:00
|
|
|
|
|
|
|
alignedLibs *AlignedLibs
|
2021-12-10 20:00:22 +01:00
|
|
|
strBuilder strings.Builder
|
2021-12-07 21:33:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
type AlignedLibs struct {
|
|
|
|
startValueUk uint64
|
2021-12-10 20:00:22 +01:00
|
|
|
startValueInit uint64
|
2021-12-07 21:33:17 +01:00
|
|
|
AllCommonMicroLibs []*MicroLib
|
|
|
|
OnlyFewMicroLibs []*MicroLib
|
|
|
|
SingleMicroLibs []*MicroLib
|
2021-01-30 12:37:27 +01:00
|
|
|
}
|
|
|
|
|
2021-12-10 20:00:22 +01:00
|
|
|
func ReadJsonFile(path string) ([]*Unikernel, error) {
|
|
|
|
jsonFile, err := os.Open(path)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
defer jsonFile.Close()
|
|
|
|
byteValue, _ := ioutil.ReadAll(jsonFile)
|
|
|
|
unikernels := new(Unikernels)
|
|
|
|
if err := json.Unmarshal(byteValue, unikernels); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
uks := make([]*Unikernel, len(unikernels.Unikernel))
|
|
|
|
for i, _ := range unikernels.Unikernel {
|
|
|
|
uks[i] = &unikernels.Unikernel[i]
|
|
|
|
}
|
|
|
|
unikernels = nil
|
|
|
|
return uks, nil
|
|
|
|
}
|
|
|
|
|
2021-01-30 12:37:27 +01:00
|
|
|
func parseFile(path, name string) (*elf64core.ELF64File, error) {
|
|
|
|
var elfFile *elf64core.ELF64File
|
|
|
|
elfFile = new(elf64core.ELF64File)
|
|
|
|
if err := elfFile.ParseAll(path, name); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return elfFile, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uk *Unikernel) GetKernel() error {
|
|
|
|
var err error
|
|
|
|
uk.ElfFile, err = parseFile("", uk.Kernel)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uk *Unikernel) GetFiles() error {
|
|
|
|
files, err := ioutil.ReadDir(uk.BuildPath)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
uk.ListObjs = make([]*elf64core.ELF64File, 0)
|
|
|
|
foundExec := false
|
|
|
|
for _, f := range files {
|
|
|
|
|
|
|
|
if f.IsDir() || strings.Contains(f.Name(), makefile) ||
|
2021-12-06 20:13:18 +01:00
|
|
|
strings.Contains(f.Name(), config) {
|
2021-01-30 12:37:27 +01:00
|
|
|
continue
|
|
|
|
}
|
2021-12-06 20:13:18 +01:00
|
|
|
|
|
|
|
if strings.Contains(f.Name(), ldExt) &&
|
2021-01-30 12:37:27 +01:00
|
|
|
!stringInSlice(f.Name(), uk.IgnoredPlats) {
|
|
|
|
objFile, err := parseFile(uk.BuildPath, f.Name())
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
uk.ListObjs = append(uk.ListObjs, objFile)
|
|
|
|
} else if filepath.Ext(strings.TrimSpace(f.Name())) == dbgExt &&
|
|
|
|
!stringInSlice(f.Name(), uk.IgnoredPlats) && !foundExec {
|
|
|
|
|
|
|
|
execName := f.Name()
|
|
|
|
if len(uk.Kernel) > 0 {
|
|
|
|
execName = uk.Kernel
|
|
|
|
}
|
|
|
|
uk.ElfFile, err = parseFile(uk.BuildPath, execName)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
foundExec = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(uk.Kernel) > 0 {
|
2021-12-10 20:00:22 +01:00
|
|
|
u.PrintInfo("Use specified ELF file: " + uk.ElfFile.Name + "(" + uk.BuildPath + ")")
|
2021-01-30 12:37:27 +01:00
|
|
|
} else {
|
|
|
|
u.PrintInfo("Use ELF file found in build folder: " + uk.ElfFile.Name)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uk *Unikernel) displayAllElfInfo() {
|
|
|
|
uk.ElfFile.Header.DisplayHeader()
|
|
|
|
uk.ElfFile.SectionsTable.DisplaySections()
|
|
|
|
uk.ElfFile.DisplayRelocationTables()
|
|
|
|
uk.ElfFile.DisplaySymbolsTables()
|
|
|
|
uk.ElfFile.DynamicTable.DisplayDynamicEntries()
|
|
|
|
uk.ElfFile.SegmentsTable.DisplayProgramHeader()
|
|
|
|
uk.ElfFile.SegmentsTable.DisplaySegmentSectionMapping()
|
|
|
|
uk.ElfFile.DisplayNotes()
|
|
|
|
uk.ElfFile.DisplayFunctionsTables(false)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uk *Unikernel) DisplayElfInfo() {
|
|
|
|
|
|
|
|
if len(uk.DisplayElfFile) == 1 && uk.DisplayElfFile[0] == "all" {
|
|
|
|
uk.displayAllElfInfo()
|
|
|
|
} else {
|
|
|
|
for _, d := range uk.DisplayElfFile {
|
|
|
|
if d == "header" {
|
|
|
|
uk.ElfFile.Header.DisplayHeader()
|
|
|
|
} else if d == "sections" {
|
|
|
|
uk.ElfFile.SectionsTable.DisplaySections()
|
|
|
|
} else if d == "relocations" {
|
|
|
|
uk.ElfFile.DisplayRelocationTables()
|
|
|
|
} else if d == "symbols" {
|
|
|
|
uk.ElfFile.DisplaySymbolsTables()
|
|
|
|
} else if d == "dynamics" {
|
|
|
|
uk.ElfFile.DynamicTable.DisplayDynamicEntries()
|
|
|
|
} else if d == "segments" {
|
|
|
|
uk.ElfFile.SegmentsTable.DisplayProgramHeader()
|
|
|
|
} else if d == "mapping" {
|
|
|
|
uk.ElfFile.SegmentsTable.DisplaySegmentSectionMapping()
|
|
|
|
} else if d == "notes" {
|
|
|
|
uk.ElfFile.DisplayNotes()
|
|
|
|
} else if d == "functions" {
|
|
|
|
uk.ElfFile.DisplayFunctionsTables(false)
|
|
|
|
} else {
|
|
|
|
u.PrintWarning("No display configuration found for argument: " + d)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-07 21:33:17 +01:00
|
|
|
|
|
|
|
func (uk *Unikernel) InitAlignment() {
|
|
|
|
uk.alignedLibs = &AlignedLibs{
|
|
|
|
startValueUk: 0,
|
2021-12-10 20:00:22 +01:00
|
|
|
startValueInit: 0,
|
|
|
|
AllCommonMicroLibs: make([]*MicroLib, 0),
|
2021-12-07 21:33:17 +01:00
|
|
|
OnlyFewMicroLibs: make([]*MicroLib, 0),
|
|
|
|
SingleMicroLibs: make([]*MicroLib, 0),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uk *Unikernel) AddAlignedMicroLibs(startValue uint64, lib *MicroLib) {
|
2021-12-10 20:00:22 +01:00
|
|
|
if _, ok := uk.Analyser.MapElfLibs[lib.name]; ok {
|
|
|
|
lib.startAddr = startValue
|
|
|
|
uk.alignedLibs.OnlyFewMicroLibs = append(uk.alignedLibs.OnlyFewMicroLibs, lib)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uk *Unikernel) AddSingleMicroLibs(startValue uint64, lib *MicroLib) {
|
|
|
|
if _, ok := uk.Analyser.MapElfLibs[lib.name]; ok {
|
2021-12-07 21:33:17 +01:00
|
|
|
|
2021-12-10 20:00:22 +01:00
|
|
|
uk.alignedLibs.SingleMicroLibs = append(uk.alignedLibs.SingleMicroLibs, lib)
|
|
|
|
if uk.alignedLibs.startValueInit == 0 {
|
|
|
|
uk.alignedLibs.startValueInit = startValue
|
|
|
|
uk.alignedLibs.startValueUk = startValue
|
2021-12-07 21:33:17 +01:00
|
|
|
}
|
2021-12-10 20:00:22 +01:00
|
|
|
uk.alignedLibs.startValueUk += lib.size
|
2021-12-07 21:33:17 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-10 20:00:22 +01:00
|
|
|
func (uk *Unikernel) writeTextAlignment(startValue uint64) {
|
2021-12-07 21:33:17 +01:00
|
|
|
|
2021-12-10 20:00:22 +01:00
|
|
|
uk.strBuilder = strings.Builder{}
|
|
|
|
uk.strBuilder.WriteString("SECTIONS\n{\n")
|
|
|
|
uk.strBuilder.WriteString(fmt.Sprintf(" . = 0x%x;\n", startValue))
|
|
|
|
for _, lib := range uk.alignedLibs.AllCommonMicroLibs {
|
|
|
|
uk.strBuilder.WriteString(fmt.Sprintf(" .text.%s : {\n\t %s(.text);\n }\n", strings.Replace(lib.name, ldExt, "", -1), lib.name))
|
|
|
|
}
|
2021-12-07 21:33:17 +01:00
|
|
|
|
2021-12-10 20:00:22 +01:00
|
|
|
for _, lib := range uk.alignedLibs.OnlyFewMicroLibs {
|
|
|
|
uk.strBuilder.WriteString(fmt.Sprintf(" .text.%s 0x%x: {\n\t %s(.text);\n }\n", strings.Replace(lib.name, ldExt, "", -1), lib.startAddr, lib.name))
|
|
|
|
}
|
|
|
|
|
|
|
|
uk.strBuilder.WriteString(fmt.Sprintf(" . = 0x%x;\n", uk.alignedLibs.startValueInit))
|
|
|
|
|
|
|
|
for _, lib := range uk.alignedLibs.SingleMicroLibs {
|
|
|
|
uk.strBuilder.WriteString(fmt.Sprintf(" .text.%s : {\n\t %s(.text);\n }\n", strings.Replace(lib.name, ldExt, "", -1), lib.name))
|
|
|
|
}
|
|
|
|
|
|
|
|
uk.strBuilder.WriteString("}\n")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uk *Unikernel) sectionsObjs(linkerInfo LinkerInfo) string {
|
|
|
|
|
|
|
|
// 0: rodata, 1: data, 2: bss
|
|
|
|
strBuilder := [3]strings.Builder{}
|
|
|
|
for _, obj := range uk.alignedLibs.AllCommonMicroLibs {
|
|
|
|
if obj.name == ukbootMain {
|
|
|
|
// Ignore ukbootMain
|
|
|
|
continue
|
2021-12-07 21:33:17 +01:00
|
|
|
}
|
2021-12-10 20:00:22 +01:00
|
|
|
strBuilder[0].WriteString(fmt.Sprintf("%s (.rodata);\n", obj.name))
|
|
|
|
strBuilder[1].WriteString(fmt.Sprintf("%s (.data);\n", obj.name))
|
|
|
|
strBuilder[2].WriteString(fmt.Sprintf("%s (.bss);\n", obj.name))
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, obj := range uk.alignedLibs.OnlyFewMicroLibs {
|
|
|
|
strBuilder[0].WriteString(fmt.Sprintf(". = ABSOLUTE(0x%x);\n%s (.rodata);\n", obj.sectionSize.rodataAddr, obj.name))
|
|
|
|
strBuilder[1].WriteString(fmt.Sprintf(". = ABSOLUTE(0x%x);\n%s (.data);\n", obj.sectionSize.dataAddr, obj.name))
|
|
|
|
strBuilder[2].WriteString(fmt.Sprintf(". = ABSOLUTE(0x%x);\n%s (.bss);\n", obj.sectionSize.bssAddr, obj.name))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Add ukbootMain before single microlibs
|
|
|
|
strBuilder[0].WriteString(fmt.Sprintf("%s (.rodata);\n", ukbootMain))
|
|
|
|
strBuilder[1].WriteString(fmt.Sprintf("%s (.data);\n", ukbootMain))
|
|
|
|
strBuilder[2].WriteString(fmt.Sprintf("%s (.bss);\n", ukbootMain))
|
|
|
|
|
|
|
|
for _, obj := range uk.alignedLibs.SingleMicroLibs {
|
|
|
|
strBuilder[0].WriteString(fmt.Sprintf("%s (.rodata);\n", obj.name))
|
|
|
|
strBuilder[1].WriteString(fmt.Sprintf("%s (.data);\n", obj.name))
|
|
|
|
strBuilder[2].WriteString(fmt.Sprintf("%s (.bss);\n", obj.name))
|
|
|
|
}
|
|
|
|
|
|
|
|
arrLoc := []string{inner_rodata, inner_data, inner_bss}
|
|
|
|
for i, builder := range strBuilder {
|
|
|
|
linkerInfo.ldsString = strings.Replace(linkerInfo.ldsString, arrLoc[i], builder.String(), -1)
|
|
|
|
}
|
|
|
|
|
|
|
|
return linkerInfo.ldsString
|
|
|
|
}
|
|
|
|
|
|
|
|
func (uk *Unikernel) writeLdsToFile(filename string, linkerInfo LinkerInfo) {
|
|
|
|
|
|
|
|
// Replace rodata, data,bss from object section
|
|
|
|
linkerInfo.ldsString = uk.sectionsObjs(linkerInfo)
|
|
|
|
if err := os.WriteFile(filename, []byte(uk.strBuilder.String()+linkerInfo.ldsString), 0644); err != nil {
|
|
|
|
u.PrintErr(err)
|
2021-12-07 21:33:17 +01:00
|
|
|
}
|
|
|
|
}
|