Update
This commit is contained in:
parent
fa9c5399a9
commit
75162aa119
8 changed files with 468 additions and 130 deletions
86
lds/common.ld
Normal file
86
lds/common.ld
Normal file
|
@ -0,0 +1,86 @@
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
. = 0x100000;
|
||||||
|
_text = .;
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
KEEP (*(.data.boot))
|
||||||
|
*(.text.boot)
|
||||||
|
*(.text)
|
||||||
|
*(.text.*) /* uncomment it to dissagregate functions */
|
||||||
|
}
|
||||||
|
|
||||||
|
<END_TEXT_REPLACE_LOCATION>
|
||||||
|
_etext = .;
|
||||||
|
. = ALIGN((1 << 12)); __eh_frame_start = .; .eh_frame : { *(.eh_frame) *(.eh_frame.*) } __eh_frame_end = .; __eh_frame_hdr_start = .; .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_hdr.*) } __eh_frame_hdr_end = .;
|
||||||
|
. = ALIGN((1 << 12)); uk_ctortab_start = .; .uk_ctortab : { KEEP(*(SORT_BY_NAME(.uk_ctortab[0-9]))) } uk_ctortab_end = .;
|
||||||
|
<UK_INIT_REPLACE_LOCATION> uk_inittab_start = .; .uk_inittab : { KEEP(*(SORT_BY_NAME(.uk_inittab[1-6][0-9]))) } uk_inittab_end = .;
|
||||||
|
|
||||||
|
<RODATA_REPLACE_LOCATION>
|
||||||
|
. = ALIGN((1 << 12));
|
||||||
|
_rodata = .;
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
<INNER_RODATA>
|
||||||
|
*(.rodata)
|
||||||
|
*(.rodata.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
<ERODATA_REPLACE_LOCATION>
|
||||||
|
_erodata = .;
|
||||||
|
. = ALIGN(0x8);
|
||||||
|
_ctors = .;
|
||||||
|
.preinit_array : {
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
. = ALIGN(0x8);
|
||||||
|
.init_array : {
|
||||||
|
PROVIDE_HIDDEN (__init_array_start = .);
|
||||||
|
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
|
||||||
|
KEEP (*(.init_array .ctors))
|
||||||
|
PROVIDE_HIDDEN (__init_array_end = .);
|
||||||
|
}
|
||||||
|
_ectors = .;
|
||||||
|
. = ALIGN(0x8); _tls_start = .; .tdata : { *(.tdata) *(.tdata.*) *(.gnu.linkonce.td.*) } _etdata = .;
|
||||||
|
|
||||||
|
<DATA_REPLACE_LOCATION>
|
||||||
|
. = ALIGN((1 << 12));
|
||||||
|
_data = .;
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
<INNER_DATA>
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
}
|
||||||
|
|
||||||
|
<EDATA_REPLACE_LOCATION>
|
||||||
|
_edata = .;
|
||||||
|
. = ALIGN((1 << 12));
|
||||||
|
|
||||||
|
<BSS_REPLACE_LOCATION>
|
||||||
|
__bss_start = .;
|
||||||
|
.bss :
|
||||||
|
{
|
||||||
|
<INNER_BSS>
|
||||||
|
*(.bss)
|
||||||
|
*(.bss.*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN((1 << 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
<TBSS_REPLACE_LOCATION>
|
||||||
|
.tbss : { *(.tbss) *(.tbss.*) *(.gnu.linkonce.tb.*) . = ALIGN(0x8); } _tls_end = . + SIZEOF(.tbss);
|
||||||
|
|
||||||
|
<INTRSTACK_REPLACE_LOCATION>
|
||||||
|
.intrstack :
|
||||||
|
{
|
||||||
|
*(.intrstack)
|
||||||
|
. = ALIGN((1 << 12));
|
||||||
|
}
|
||||||
|
_end = .;
|
||||||
|
.comment 0 : { *(.comment) }
|
||||||
|
.debug 0 : { *(.debug) } .line 0 : { *(.line) } .debug_srcinfo 0 : { *(.debug_srcinfo) } .debug_sfnames 0 : { *(.debug_sfnames) } .debug_aranges 0 : { *(.debug_aranges) } .debug_pubnames 0 : { *(.debug_pubnames) } .debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) } .debug_abbrev 0 : { *(.debug_abbrev) } .debug_line 0 : { *(.debug_line .debug_line.* .debug_line_end ) } .debug_frame 0 : { *(.debug_frame) } .debug_str 0 : { *(.debug_str) } .debug_loc 0 : { *(.debug_loc) } .debug_macinfo 0 : { *(.debug_macinfo) } .debug_weaknames 0 : { *(.debug_weaknames) } .debug_funcnames 0 : { *(.debug_funcnames) } .debug_typenames 0 : { *(.debug_typenames) } .debug_varnames 0 : { *(.debug_varnames) } .debug_pubtypes 0 : { *(.debug_pubtypes) } .debug_ranges 0 : { *(.debug_ranges) } .debug_macro 0 : { *(.debug_macro) } .gnu.attributes 0 : { KEEP (*(.gnu.attributes)) }
|
||||||
|
/DISCARD/ : { *(.note.gnu.build-id) }
|
||||||
|
}
|
|
@ -7,8 +7,6 @@
|
||||||
package elf64analyser
|
package elf64analyser
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/sha256"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -19,8 +17,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ElfAnalyser struct {
|
type ElfAnalyser struct {
|
||||||
ElfLibs []ElfLibs
|
ElfLibs []ElfLibs
|
||||||
ElfPage []*ElfPage
|
ElfPage []*ElfPage
|
||||||
|
MapElfLibs map[string]*ElfLibs
|
||||||
}
|
}
|
||||||
|
|
||||||
type ElfLibs struct {
|
type ElfLibs struct {
|
||||||
|
@ -29,6 +28,10 @@ type ElfLibs struct {
|
||||||
EndAddr uint64
|
EndAddr uint64
|
||||||
Size uint64
|
Size uint64
|
||||||
NbSymbols int
|
NbSymbols int
|
||||||
|
|
||||||
|
RodataSize uint64
|
||||||
|
DataSize uint64
|
||||||
|
BssSize uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (analyser *ElfAnalyser) DisplayMapping() {
|
func (analyser *ElfAnalyser) DisplayMapping() {
|
||||||
|
@ -151,30 +154,11 @@ func compareFunctions(elf *elf64core.ELF64File, obj *elf64core.ELF64File) (uint6
|
||||||
elfFuncsAll[len(elfFuncsAll)-1].Addr, len(elfFuncsAll)
|
elfFuncsAll[len(elfFuncsAll)-1].Addr, len(elfFuncsAll)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (analyser *ElfAnalyser) InspectMapping(elf *elf64core.ELF64File, objs ...interface{}) {
|
func getSectionSize(name string, obj *elf64core.ELF64File) uint64 {
|
||||||
|
if index, ok := obj.IndexSections[name]; ok {
|
||||||
if len(objs) == 0 {
|
return obj.SectionsTable.DataSect[index].Elf64section.Size
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
return 0
|
||||||
analyser.ElfLibs = make([]ElfLibs, 0)
|
|
||||||
for _, iobj := range objs {
|
|
||||||
obj := iobj.(*elf64core.ELF64File)
|
|
||||||
start, end, nbSymbols := compareFunctions(elf, obj)
|
|
||||||
analyser.ElfLibs = append(analyser.ElfLibs, ElfLibs{
|
|
||||||
Name: obj.Name,
|
|
||||||
StartAddr: start,
|
|
||||||
EndAddr: end,
|
|
||||||
Size: end - start,
|
|
||||||
NbSymbols: nbSymbols,
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// sort functions
|
|
||||||
sort.Slice(analyser.ElfLibs, func(i, j int) bool {
|
|
||||||
return analyser.ElfLibs[i].StartAddr < analyser.ElfLibs[j].StartAddr
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (analyser *ElfAnalyser) InspectMappingList(elf *elf64core.ELF64File,
|
func (analyser *ElfAnalyser) InspectMappingList(elf *elf64core.ELF64File,
|
||||||
|
@ -184,16 +168,25 @@ func (analyser *ElfAnalyser) InspectMappingList(elf *elf64core.ELF64File,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
analyser.ElfLibs = make([]ElfLibs, 0)
|
analyser.ElfLibs = make([]ElfLibs, len(objs))
|
||||||
for _, obj := range objs {
|
analyser.MapElfLibs = make(map[string]*ElfLibs, len(analyser.ElfLibs))
|
||||||
|
for i, obj := range objs {
|
||||||
|
|
||||||
start, end, nbSymbols := compareFunctions(elf, obj)
|
start, end, nbSymbols := compareFunctions(elf, obj)
|
||||||
analyser.ElfLibs = append(analyser.ElfLibs, ElfLibs{
|
lib := ElfLibs{
|
||||||
Name: obj.Name,
|
Name: obj.Name,
|
||||||
StartAddr: start,
|
StartAddr: start,
|
||||||
EndAddr: end,
|
EndAddr: end,
|
||||||
Size: end - start,
|
Size: end - start,
|
||||||
NbSymbols: nbSymbols,
|
NbSymbols: nbSymbols,
|
||||||
})
|
// Get size of data, rodata and bss from object file
|
||||||
|
RodataSize: getSectionSize(".rodata", obj),
|
||||||
|
DataSize: getSectionSize(".data", obj),
|
||||||
|
BssSize: getSectionSize(".bss", obj),
|
||||||
|
}
|
||||||
|
analyser.ElfLibs[i] = lib
|
||||||
|
// Map for direct access
|
||||||
|
analyser.MapElfLibs[lib.Name] = &lib
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort functions by start address.
|
// sort functions by start address.
|
||||||
|
@ -202,6 +195,7 @@ func (analyser *ElfAnalyser) InspectMappingList(elf *elf64core.ELF64File,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
func (analyser *ElfAnalyser) SplitIntoPagesBySection(elfFile *elf64core.ELF64File, sectionName string) {
|
func (analyser *ElfAnalyser) SplitIntoPagesBySection(elfFile *elf64core.ELF64File, sectionName string) {
|
||||||
|
|
||||||
if len(analyser.ElfPage) == 0 {
|
if len(analyser.ElfPage) == 0 {
|
||||||
|
@ -211,8 +205,7 @@ func (analyser *ElfAnalyser) SplitIntoPagesBySection(elfFile *elf64core.ELF64Fil
|
||||||
if strings.Contains(sectionName, elf64core.TextSection) {
|
if strings.Contains(sectionName, elf64core.TextSection) {
|
||||||
// An ELF might have several text sections
|
// An ELF might have several text sections
|
||||||
for _, indexSection := range elfFile.TextSectionIndex {
|
for _, indexSection := range elfFile.TextSectionIndex {
|
||||||
sectionName := elfFile.SectionsTable.DataSect[indexSection].Name
|
analyser.computePage(elfFile, elfFile.SectionsTable.DataSect[indexSection].Name, indexSection)
|
||||||
analyser.computePage(elfFile, sectionName, indexSection)
|
|
||||||
}
|
}
|
||||||
} else if indexSection, ok := elfFile.IndexSections[sectionName]; ok {
|
} else if indexSection, ok := elfFile.IndexSections[sectionName]; ok {
|
||||||
analyser.computePage(elfFile, sectionName, indexSection)
|
analyser.computePage(elfFile, sectionName, indexSection)
|
||||||
|
@ -221,6 +214,7 @@ func (analyser *ElfAnalyser) SplitIntoPagesBySection(elfFile *elf64core.ELF64Fil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func CreateNewPage(startAddress uint64, k int, raw []byte) *ElfPage {
|
func CreateNewPage(startAddress uint64, k int, raw []byte) *ElfPage {
|
||||||
byteArray := make([]byte, PageSize)
|
byteArray := make([]byte, PageSize)
|
||||||
b := raw
|
b := raw
|
||||||
|
@ -253,3 +247,4 @@ func (analyser *ElfAnalyser) computePage(elfFile *elf64core.ELF64File, section s
|
||||||
k++
|
k++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -54,12 +54,6 @@ func (p *ElfPage) pageContentToString() string {
|
||||||
|
|
||||||
func (p *ElfPage) displayPageContent(mw io.Writer) {
|
func (p *ElfPage) displayPageContent(mw io.Writer) {
|
||||||
|
|
||||||
/*
|
|
||||||
hexStartAddr, err := strconv.ParseInt(p.startAddress, 16, 64);
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
for i, entry := range p.contentByteArray {
|
for i, entry := range p.contentByteArray {
|
||||||
|
|
||||||
if i > 0 && i%4 == 0 {
|
if i > 0 && i%4 == 0 {
|
||||||
|
|
|
@ -37,14 +37,14 @@ func RunBinaryAnalyser(homeDir string) {
|
||||||
manager := new(ukManager.Manager)
|
manager := new(ukManager.Manager)
|
||||||
manager.MicroLibs = make(map[string]*ukManager.MicroLib)
|
manager.MicroLibs = make(map[string]*ukManager.MicroLib)
|
||||||
if len(*args.StringArg[listArg]) > 0 {
|
if len(*args.StringArg[listArg]) > 0 {
|
||||||
manager.Unikernels = make([]ukManager.Unikernel, len(*args.StringArg[listArg]))
|
manager.Unikernels = make([]*ukManager.Unikernel, len(*args.StringArg[listArg]))
|
||||||
mapping := false
|
mapping := false
|
||||||
if *args.BoolArg[mappingArg] {
|
if *args.BoolArg[mappingArg] {
|
||||||
mapping = true
|
mapping = true
|
||||||
}
|
}
|
||||||
list := strings.Split(*args.StringArg[listArg], ",")
|
list := strings.Split(*args.StringArg[listArg], ",")
|
||||||
for i, arg := range list {
|
for i, arg := range list {
|
||||||
manager.Unikernels[i] = ukManager.Unikernel{
|
manager.Unikernels[i] = &ukManager.Unikernel{
|
||||||
BuildPath: arg,
|
BuildPath: arg,
|
||||||
DisplayMapping: mapping,
|
DisplayMapping: mapping,
|
||||||
}
|
}
|
||||||
|
@ -62,10 +62,9 @@ func RunBinaryAnalyser(homeDir string) {
|
||||||
var comparison elf64analyser.ComparisonElf
|
var comparison elf64analyser.ComparisonElf
|
||||||
comparison.GroupFileSegment = make([]*elf64analyser.ElfFileSegment, 0)
|
comparison.GroupFileSegment = make([]*elf64analyser.ElfFileSegment, 0)
|
||||||
|
|
||||||
for i, _ := range manager.Unikernels {
|
for i, uk := range manager.Unikernels {
|
||||||
|
|
||||||
manager.Unikernels[i].Analyser = new(elf64analyser.ElfAnalyser)
|
uk.Analyser = new(elf64analyser.ElfAnalyser)
|
||||||
uk := manager.Unikernels[i]
|
|
||||||
if len(uk.BuildPath) > 0 {
|
if len(uk.BuildPath) > 0 {
|
||||||
if uk.BuildPath[len(uk.BuildPath)-1] != os.PathSeparator {
|
if uk.BuildPath[len(uk.BuildPath)-1] != os.PathSeparator {
|
||||||
uk.BuildPath += u.SEP
|
uk.BuildPath += u.SEP
|
||||||
|
@ -104,7 +103,7 @@ func RunBinaryAnalyser(homeDir string) {
|
||||||
uk.Analyser.FindSectionByAddress(uk.ElfFile, uk.FindSectionByAddress)
|
uk.Analyser.FindSectionByAddress(uk.ElfFile, uk.FindSectionByAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
manager.ComputeAlignment(uk)
|
manager.ComputeAlignment(*uk)
|
||||||
|
|
||||||
/*if uk.CompareGroup > 0 {
|
/*if uk.CompareGroup > 0 {
|
||||||
|
|
||||||
|
|
103
srcs/binarytool/ukManager/elf_linker.go
Normal file
103
srcs/binarytool/ukManager/elf_linker.go
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
package ukManager
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"tools/srcs/binarytool/elf64analyser"
|
||||||
|
"tools/srcs/binarytool/elf64core"
|
||||||
|
)
|
||||||
|
|
||||||
|
type LinkerInfo struct {
|
||||||
|
ldsString string
|
||||||
|
rodataAddr uint64
|
||||||
|
dataAddr uint64
|
||||||
|
bssAddr uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
endtext_location = "<END_TEXT_REPLACE_LOCATION>"
|
||||||
|
rodata_location = "<RODATA_REPLACE_LOCATION>"
|
||||||
|
data_location = "<DATA_REPLACE_LOCATION>"
|
||||||
|
erodata_location = "<ERODATA_REPLACE_LOCATION>"
|
||||||
|
edata_location = "<EDATA_REPLACE_LOCATION>"
|
||||||
|
bss_location = "<BSS_REPLACE_LOCATION>"
|
||||||
|
tbss_location = "<TBSS_REPLACE_LOCATION>"
|
||||||
|
intrstack_location = "<INTRSTACK_REPLACE_LOCATION>"
|
||||||
|
ukinit_location = "<UK_INIT_REPLACE_LOCATION>"
|
||||||
|
|
||||||
|
inner_rodata = "<INNER_RODATA>"
|
||||||
|
inner_data = "<INNER_DATA>"
|
||||||
|
inner_bss = "<INNER_BSS>"
|
||||||
|
)
|
||||||
|
|
||||||
|
func readLdsContent(filename string) string {
|
||||||
|
|
||||||
|
strBuilder := strings.Builder{}
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(file)
|
||||||
|
// optionally, resize scanner's capacity for lines over 64K, see next example
|
||||||
|
for scanner.Scan() {
|
||||||
|
strBuilder.WriteString(scanner.Text() + "\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return strBuilder.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func processLdsFile(locationCnt uint64, maxValSection map[string]uint64) LinkerInfo {
|
||||||
|
|
||||||
|
type sectionLoc struct {
|
||||||
|
sec string
|
||||||
|
loc string
|
||||||
|
}
|
||||||
|
|
||||||
|
linkerInfo := LinkerInfo{}
|
||||||
|
|
||||||
|
// Use an array to preserver order
|
||||||
|
arrSection := []sectionLoc{
|
||||||
|
{sec: elf64core.RodataSection, loc: rodata_location},
|
||||||
|
{sec: elf64core.DataSection, loc: data_location},
|
||||||
|
{sec: elf64core.BssSection, loc: bss_location},
|
||||||
|
{sec: elf64core.TbssSection, loc: tbss_location}}
|
||||||
|
|
||||||
|
ldsString := readLdsContent("lds/common.ld")
|
||||||
|
// Update end of text
|
||||||
|
ldsString = strings.Replace(ldsString, endtext_location, fmt.Sprintf(". = 0x%x;", locationCnt), -1)
|
||||||
|
// Update ukinit
|
||||||
|
ldsString = strings.Replace(ldsString, ukinit_location, fmt.Sprintf(". = 0x%x;", locationCnt+0x40), -1)
|
||||||
|
|
||||||
|
locationCnt += elf64analyser.PageSize
|
||||||
|
for _, sect := range arrSection {
|
||||||
|
if sect.sec == elf64core.RodataSection {
|
||||||
|
linkerInfo.rodataAddr = locationCnt
|
||||||
|
} else if sect.sec == elf64core.DataSection {
|
||||||
|
// Update erodata just before data
|
||||||
|
ldsString = strings.Replace(ldsString, erodata_location, fmt.Sprintf(". = 0x%x;", locationCnt), -1)
|
||||||
|
locationCnt += elf64analyser.PageSize
|
||||||
|
linkerInfo.dataAddr = locationCnt
|
||||||
|
} else if sect.sec == elf64core.BssSection {
|
||||||
|
// Update edata just before bss
|
||||||
|
ldsString = strings.Replace(ldsString, edata_location, fmt.Sprintf(". = 0x%x;", locationCnt), -1)
|
||||||
|
locationCnt += elf64analyser.PageSize
|
||||||
|
linkerInfo.bssAddr = locationCnt
|
||||||
|
}
|
||||||
|
// Update rodata, data, bss, tbss
|
||||||
|
ldsString = strings.Replace(ldsString, sect.loc, fmt.Sprintf(". = 0x%x;", locationCnt), -1)
|
||||||
|
locationCnt += maxValSection[sect.sec]
|
||||||
|
locationCnt = roundAddr(locationCnt, elf64analyser.PageSize)
|
||||||
|
}
|
||||||
|
// Update intrstack
|
||||||
|
linkerInfo.ldsString = strings.Replace(ldsString, intrstack_location, fmt.Sprintf(". = 0x%x;", locationCnt), -1)
|
||||||
|
|
||||||
|
return linkerInfo
|
||||||
|
}
|
|
@ -7,27 +7,9 @@
|
||||||
package ukManager
|
package ukManager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
||||||
return unikernels.Unikernel, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringInSlice(name string, plats []string) bool {
|
func stringInSlice(name string, plats []string) bool {
|
||||||
for _, plat := range plats {
|
for _, plat := range plats {
|
||||||
if strings.Contains(name, plat) {
|
if strings.Contains(name, plat) {
|
||||||
|
|
|
@ -4,12 +4,16 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"tools/srcs/binarytool/elf64analyser"
|
"tools/srcs/binarytool/elf64analyser"
|
||||||
|
"tools/srcs/binarytool/elf64core"
|
||||||
u "tools/srcs/common"
|
u "tools/srcs/common"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ukbootMain = "libukboot_main.ld.o"
|
||||||
|
|
||||||
type Manager struct {
|
type Manager struct {
|
||||||
Unikernels []Unikernel
|
Unikernels []*Unikernel
|
||||||
MicroLibs map[string]*MicroLib
|
MicroLibs map[string]*MicroLib
|
||||||
SortedMicroLibs []*MicroLib //Used for the display
|
SortedMicroLibs []*MicroLib //Used for the display
|
||||||
}
|
}
|
||||||
|
@ -19,24 +23,38 @@ type MicroLib struct {
|
||||||
startAddr uint64
|
startAddr uint64
|
||||||
size uint64
|
size uint64
|
||||||
instance int
|
instance int
|
||||||
sectionSize SectionMicroLibs
|
sectionSize *SectionMicroLibs
|
||||||
}
|
}
|
||||||
|
|
||||||
type SectionMicroLibs struct {
|
type SectionMicroLibs struct {
|
||||||
rodataSize uint64
|
rodataSize uint64
|
||||||
dataSize uint64
|
dataSize uint64
|
||||||
BssSize uint64
|
bssSize uint64
|
||||||
|
|
||||||
|
rodataAddr uint64
|
||||||
|
dataAddr uint64
|
||||||
|
bssAddr uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *Manager) ComputeAlignment(unikernel Unikernel) {
|
func (manager *Manager) ComputeAlignment(unikernel Unikernel) {
|
||||||
|
|
||||||
for _, libs := range unikernel.Analyser.ElfLibs {
|
for _, libs := range unikernel.Analyser.ElfLibs {
|
||||||
|
|
||||||
|
// Ignore ukbootMain to place it to specific position
|
||||||
|
if libs.Name == ukbootMain {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add microlib to a global map per instance
|
||||||
if val, ok := manager.MicroLibs[libs.Name]; ok {
|
if val, ok := manager.MicroLibs[libs.Name]; ok {
|
||||||
if manager.MicroLibs[libs.Name].size != libs.Size {
|
if manager.MicroLibs[libs.Name].size != libs.Size {
|
||||||
//u.PrintWarning(fmt.Sprintf("Different size between %s (0x%x) (0x%x)", libs.Name, libs.Size, val.size))
|
//u.PrintWarning(fmt.Sprintf("Different size between %s (0x%x) (0x%x)", libs.Name, libs.Size, val.size))
|
||||||
if val.size < libs.Size {
|
if val.size < libs.Size {
|
||||||
u.PrintWarning(fmt.Sprintf("Bigger size found %s (0x%x) > (0x%x)", libs.Name, libs.Size, val.size))
|
u.PrintWarning(fmt.Sprintf("Bigger size found %s (0x%x) > (0x%x)", libs.Name, libs.Size, val.size))
|
||||||
manager.MicroLibs[libs.Name].size = libs.Size
|
manager.MicroLibs[libs.Name].size = libs.Size
|
||||||
|
manager.MicroLibs[libs.Name].sectionSize.rodataSize = libs.RodataSize
|
||||||
|
manager.MicroLibs[libs.Name].sectionSize.dataSize = libs.DataSize
|
||||||
|
manager.MicroLibs[libs.Name].sectionSize.bssSize = libs.BssSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
manager.MicroLibs[libs.Name].instance += 1
|
manager.MicroLibs[libs.Name].instance += 1
|
||||||
|
@ -46,6 +64,11 @@ func (manager *Manager) ComputeAlignment(unikernel Unikernel) {
|
||||||
startAddr: libs.StartAddr,
|
startAddr: libs.StartAddr,
|
||||||
size: libs.Size,
|
size: libs.Size,
|
||||||
instance: 1,
|
instance: 1,
|
||||||
|
sectionSize: &SectionMicroLibs{
|
||||||
|
rodataSize: libs.RodataSize,
|
||||||
|
dataSize: libs.DataSize,
|
||||||
|
bssSize: libs.BssSize,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
manager.MicroLibs[libs.Name] = mlib
|
manager.MicroLibs[libs.Name] = mlib
|
||||||
}
|
}
|
||||||
|
@ -58,7 +81,6 @@ func (manager *Manager) sortMicroLibs() {
|
||||||
instance int
|
instance int
|
||||||
addr uint64
|
addr uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
i := 0
|
i := 0
|
||||||
var kvSlice = make([]kv, len(manager.MicroLibs))
|
var kvSlice = make([]kv, len(manager.MicroLibs))
|
||||||
for k, v := range manager.MicroLibs {
|
for k, v := range manager.MicroLibs {
|
||||||
|
@ -74,71 +96,142 @@ func (manager *Manager) sortMicroLibs() {
|
||||||
})
|
})
|
||||||
|
|
||||||
manager.SortedMicroLibs = make([]*MicroLib, len(manager.MicroLibs))
|
manager.SortedMicroLibs = make([]*MicroLib, len(manager.MicroLibs))
|
||||||
for i, lib := range kvSlice {
|
for k, lib := range kvSlice {
|
||||||
manager.SortedMicroLibs[i] = manager.MicroLibs[lib.key]
|
manager.SortedMicroLibs[k] = manager.MicroLibs[lib.key]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *Manager) DisplayMicroLibs() {
|
func (manager *Manager) DisplayMicroLibs() {
|
||||||
manager.sortMicroLibs()
|
if manager.SortedMicroLibs == nil {
|
||||||
for i, lib := range manager.SortedMicroLibs {
|
manager.sortMicroLibs()
|
||||||
|
}
|
||||||
|
|
||||||
if lib.instance < len(manager.Unikernels) {
|
for i, lib := range manager.SortedMicroLibs {
|
||||||
fmt.Printf("%d %s: %x - %x - %d\n", i, lib.name, lib.startAddr, lib.size, lib.instance)
|
fmt.Printf("%d %s: %x - %x - %d\n", i, lib.name, lib.startAddr, lib.size, lib.instance)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (manager *Manager) PerformAlignement() {
|
func (manager *Manager) PerformAlignement() {
|
||||||
|
|
||||||
var startValue uint64 = 0x106000
|
var startValue uint64 = 0x106000
|
||||||
//manager.Unikernels[0].Analyser.ElfLibs
|
var locationCnt = startValue
|
||||||
|
|
||||||
manager.sortMicroLibs()
|
|
||||||
commonMicroLibs := make([]*MicroLib, 0)
|
commonMicroLibs := make([]*MicroLib, 0)
|
||||||
for _, lib := range manager.SortedMicroLibs {
|
|
||||||
|
// Sort micro-libs per instance (usage) and per addresses (descending order)
|
||||||
|
if manager.SortedMicroLibs == nil {
|
||||||
|
manager.sortMicroLibs()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update micro-libs mapping globally and per unikernels
|
||||||
|
for i, lib := range manager.SortedMicroLibs {
|
||||||
if lib.instance == len(manager.Unikernels) {
|
if lib.instance == len(manager.Unikernels) {
|
||||||
lib.startAddr = startValue
|
// micro-libs common to all instances
|
||||||
|
lib.startAddr = locationCnt
|
||||||
commonMicroLibs = append(commonMicroLibs, lib)
|
commonMicroLibs = append(commonMicroLibs, lib)
|
||||||
//fmt.Printf("%s -> 0x%x (0x%x) - 0x%x\n", lib.name, startValue, startValue, startValue+lib.size)
|
locationCnt += lib.size
|
||||||
startValue += lib.size
|
|
||||||
} else if lib.instance > 1 {
|
} else if lib.instance > 1 {
|
||||||
//fmt.Printf("---%s -> 0x%x (0x%x) - 0x%x\n", lib.name, startValue, startValue, startValue+lib.size)
|
// micro-libs common to particular instances
|
||||||
startValue = roundAddr(startValue)
|
if manager.SortedMicroLibs[i-1].instance == len(manager.Unikernels) {
|
||||||
for i, _ := range manager.Unikernels {
|
// Add ukboot main after all common micro-libs
|
||||||
if manager.Unikernels[i].alignedLibs == nil {
|
locationCnt = roundAddr(locationCnt, elf64analyser.PageSize)
|
||||||
// Init structure
|
ukbootMainLib := &MicroLib{
|
||||||
manager.Unikernels[i].InitAlignment()
|
name: ukbootMain,
|
||||||
|
startAddr: locationCnt,
|
||||||
|
size: 0,
|
||||||
|
instance: len(manager.Unikernels),
|
||||||
|
sectionSize: &SectionMicroLibs{},
|
||||||
}
|
}
|
||||||
manager.Unikernels[i].AddAlignedMicroLibs(startValue, lib)
|
commonMicroLibs = append(commonMicroLibs, ukbootMainLib)
|
||||||
}
|
}
|
||||||
startValue += lib.size
|
|
||||||
//fmt.Printf("%s -> 0x%x (0x%x) - 0x%x\n", lib.name, startValue, roundAddr(startValue), startValue+lib.size)
|
locationCnt = roundAddr(locationCnt, elf64analyser.PageSize)
|
||||||
|
for _, uk := range manager.Unikernels {
|
||||||
|
if uk.alignedLibs == nil {
|
||||||
|
uk.InitAlignment()
|
||||||
|
}
|
||||||
|
uk.AddAlignedMicroLibs(locationCnt, lib)
|
||||||
|
}
|
||||||
|
locationCnt += lib.size
|
||||||
} else if lib.instance == 1 {
|
} else if lib.instance == 1 {
|
||||||
for i, _ := range manager.Unikernels {
|
// micro-libs to only single instance
|
||||||
manager.Unikernels[i].AddSingleMicroLibs(roundAddr(startValue), lib)
|
for _, uk := range manager.Unikernels {
|
||||||
|
uk.AddSingleMicroLibs(roundAddr(locationCnt, elf64analyser.PageSize), lib)
|
||||||
}
|
}
|
||||||
//fmt.Printf("%s -> 0x%x (0x%x) - 0x%x\n", lib.name, startValue, roundAddr(startValue), startValue+lib.size)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find max value through unikernels
|
maxValSection := make(map[string]uint64, 3)
|
||||||
for i, _ := range manager.Unikernels {
|
sections := []string{elf64core.RodataSection, elf64core.DataSection, elf64core.TbssSection, elf64core.BssSection}
|
||||||
manager.Unikernels[i].alignedLibs.AllCommonMicroLibs = commonMicroLibs
|
|
||||||
if startValue < manager.Unikernels[i].alignedLibs.startValueUk {
|
|
||||||
startValue = manager.Unikernels[i].alignedLibs.startValueUk
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("END SECTIONS: 0x%x\n", roundAddr(startValue))
|
// Find max location counter value through unikernels
|
||||||
|
|
||||||
/*println(commonMicroLibs.String())
|
|
||||||
for _, uk := range manager.Unikernels {
|
for _, uk := range manager.Unikernels {
|
||||||
println(uk.microLibsInstance.String())
|
|
||||||
}*/
|
// Update the locationCnt by finding the maximum one from unikernel (the biggest size)
|
||||||
|
uk.alignedLibs.AllCommonMicroLibs = commonMicroLibs
|
||||||
|
if locationCnt < uk.alignedLibs.startValueUk {
|
||||||
|
locationCnt = uk.alignedLibs.startValueUk
|
||||||
|
}
|
||||||
|
|
||||||
|
// Analyse sections to find the biggest section sizes (rodata, data, tbss, bss)
|
||||||
|
for _, section := range sections {
|
||||||
|
findMaxValue(section, uk, maxValSection)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the common lds file with new location counter
|
||||||
|
locationCnt = roundAddr(locationCnt, elf64analyser.PageSize)
|
||||||
|
linkerInfo := processLdsFile(locationCnt, maxValSection)
|
||||||
|
|
||||||
|
// Use temporary variable to keep linkerInfo unchanged
|
||||||
|
linkerInfoGlobal := &LinkerInfo{
|
||||||
|
ldsString: "",
|
||||||
|
rodataAddr: linkerInfo.rodataAddr,
|
||||||
|
dataAddr: linkerInfo.dataAddr,
|
||||||
|
bssAddr: linkerInfo.bssAddr,
|
||||||
|
}
|
||||||
|
// Redo a pass on micro-libs to align inner rodata, data and bss
|
||||||
|
for _, lib := range manager.SortedMicroLibs {
|
||||||
|
|
||||||
|
if lib.instance > 1 {
|
||||||
|
// Update inner rodata location counter
|
||||||
|
lib.sectionSize.rodataAddr = linkerInfoGlobal.rodataAddr
|
||||||
|
linkerInfoGlobal.rodataAddr += roundAddr(lib.sectionSize.rodataSize, 32)
|
||||||
|
|
||||||
|
// Update inner dataAddr location counter
|
||||||
|
lib.sectionSize.dataAddr = linkerInfoGlobal.dataAddr
|
||||||
|
linkerInfoGlobal.dataAddr += roundAddr(lib.sectionSize.dataSize, 32)
|
||||||
|
|
||||||
|
// Update inner bssAddr location counter
|
||||||
|
lib.sectionSize.bssAddr = linkerInfoGlobal.bssAddr
|
||||||
|
linkerInfoGlobal.bssAddr += roundAddr(lib.sectionSize.bssSize, 32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update per unikernel
|
||||||
|
for _, uk := range manager.Unikernels {
|
||||||
|
uk.writeTextAlignment(startValue)
|
||||||
|
|
||||||
|
// todo remove and replace per uk.buildpath
|
||||||
|
lib := strings.Replace(strings.Split(uk.BuildPath, "/")[5], "lib-", "", -1)
|
||||||
|
dst := "/Users/gaulthiergain/Desktop/memory_dedup/gcc/lds/common_optimized_app_dce_size/link64_" + lib + ".lds"
|
||||||
|
|
||||||
|
uk.writeLdsToFile(dst, linkerInfo)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func roundAddr(value uint64) uint64 {
|
func findMaxValue(section string, uk *Unikernel, maxValSection map[string]uint64) {
|
||||||
x := float64(value)
|
index := uk.ElfFile.IndexSections[section]
|
||||||
unit := float64(elf64analyser.PageSize)
|
size := uk.ElfFile.SectionsTable.DataSect[index].Elf64section.Size
|
||||||
return uint64(math.Round(x/unit+0.5) * unit)
|
if val, ok := maxValSection[section]; ok {
|
||||||
|
if val < size {
|
||||||
|
maxValSection[section] = size
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
maxValSection[section] = size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func roundAddr(v uint64, round uint64) uint64 {
|
||||||
|
return uint64(math.Round(float64(v/round))*float64(round)) + round
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,8 +7,10 @@
|
||||||
package ukManager
|
package ukManager
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"tools/srcs/binarytool/elf64analyser"
|
"tools/srcs/binarytool/elf64analyser"
|
||||||
|
@ -19,7 +21,6 @@ import (
|
||||||
const (
|
const (
|
||||||
makefile = "Makefile"
|
makefile = "Makefile"
|
||||||
config = "config"
|
config = "config"
|
||||||
objExt = ".o"
|
|
||||||
ldExt = ".ld.o"
|
ldExt = ".ld.o"
|
||||||
dbgExt = ".dbg"
|
dbgExt = ".dbg"
|
||||||
)
|
)
|
||||||
|
@ -52,15 +53,37 @@ type Unikernel struct {
|
||||||
Analyser *elf64analyser.ElfAnalyser
|
Analyser *elf64analyser.ElfAnalyser
|
||||||
|
|
||||||
alignedLibs *AlignedLibs
|
alignedLibs *AlignedLibs
|
||||||
|
strBuilder strings.Builder
|
||||||
}
|
}
|
||||||
|
|
||||||
type AlignedLibs struct {
|
type AlignedLibs struct {
|
||||||
startValueUk uint64
|
startValueUk uint64
|
||||||
|
startValueInit uint64
|
||||||
AllCommonMicroLibs []*MicroLib
|
AllCommonMicroLibs []*MicroLib
|
||||||
OnlyFewMicroLibs []*MicroLib
|
OnlyFewMicroLibs []*MicroLib
|
||||||
SingleMicroLibs []*MicroLib
|
SingleMicroLibs []*MicroLib
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
func parseFile(path, name string) (*elf64core.ELF64File, error) {
|
func parseFile(path, name string) (*elf64core.ELF64File, error) {
|
||||||
var elfFile *elf64core.ELF64File
|
var elfFile *elf64core.ELF64File
|
||||||
elfFile = new(elf64core.ELF64File)
|
elfFile = new(elf64core.ELF64File)
|
||||||
|
@ -118,7 +141,7 @@ func (uk *Unikernel) GetFiles() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(uk.Kernel) > 0 {
|
if len(uk.Kernel) > 0 {
|
||||||
u.PrintInfo("Use specified ELF file: " + uk.ElfFile.Name)
|
u.PrintInfo("Use specified ELF file: " + uk.ElfFile.Name + "(" + uk.BuildPath + ")")
|
||||||
} else {
|
} else {
|
||||||
u.PrintInfo("Use ELF file found in build folder: " + uk.ElfFile.Name)
|
u.PrintInfo("Use ELF file found in build folder: " + uk.ElfFile.Name)
|
||||||
}
|
}
|
||||||
|
@ -171,35 +194,98 @@ func (uk *Unikernel) DisplayElfInfo() {
|
||||||
func (uk *Unikernel) InitAlignment() {
|
func (uk *Unikernel) InitAlignment() {
|
||||||
uk.alignedLibs = &AlignedLibs{
|
uk.alignedLibs = &AlignedLibs{
|
||||||
startValueUk: 0,
|
startValueUk: 0,
|
||||||
AllCommonMicroLibs: make([]*MicroLib, 0), //todo update with fixed entry
|
startValueInit: 0,
|
||||||
|
AllCommonMicroLibs: make([]*MicroLib, 0),
|
||||||
OnlyFewMicroLibs: make([]*MicroLib, 0),
|
OnlyFewMicroLibs: make([]*MicroLib, 0),
|
||||||
SingleMicroLibs: make([]*MicroLib, 0),
|
SingleMicroLibs: make([]*MicroLib, 0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uk *Unikernel) AddAlignedMicroLibs(startValue uint64, lib *MicroLib) {
|
func (uk *Unikernel) AddAlignedMicroLibs(startValue uint64, lib *MicroLib) {
|
||||||
|
if _, ok := uk.Analyser.MapElfLibs[lib.name]; ok {
|
||||||
for _, ukLibs := range uk.Analyser.ElfLibs {
|
lib.startAddr = startValue
|
||||||
if ukLibs.Name == lib.name {
|
uk.alignedLibs.OnlyFewMicroLibs = append(uk.alignedLibs.OnlyFewMicroLibs, lib)
|
||||||
fmt.Printf("%s -> 0x%x - 0x%x\n", lib.name, startValue, startValue+lib.size)
|
|
||||||
uk.alignedLibs.OnlyFewMicroLibs = append(uk.alignedLibs.SingleMicroLibs, lib)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (uk *Unikernel) AddSingleMicroLibs(startValue uint64, lib *MicroLib) {
|
func (uk *Unikernel) AddSingleMicroLibs(startValue uint64, lib *MicroLib) {
|
||||||
|
if _, ok := uk.Analyser.MapElfLibs[lib.name]; ok {
|
||||||
|
|
||||||
for _, ukLibs := range uk.Analyser.ElfLibs {
|
uk.alignedLibs.SingleMicroLibs = append(uk.alignedLibs.SingleMicroLibs, lib)
|
||||||
if ukLibs.Name == lib.name {
|
if uk.alignedLibs.startValueInit == 0 {
|
||||||
|
uk.alignedLibs.startValueInit = startValue
|
||||||
uk.alignedLibs.SingleMicroLibs = append(uk.alignedLibs.SingleMicroLibs, lib)
|
uk.alignedLibs.startValueUk = startValue
|
||||||
if uk.alignedLibs.startValueUk == 0 {
|
|
||||||
uk.alignedLibs.startValueUk = startValue
|
|
||||||
}
|
|
||||||
fmt.Printf("%s -> 0x%x - 0x%x\n", lib.name, uk.alignedLibs.startValueUk, uk.alignedLibs.startValueUk+lib.size)
|
|
||||||
uk.alignedLibs.startValueUk += lib.size
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
|
uk.alignedLibs.startValueUk += lib.size
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (uk *Unikernel) writeTextAlignment(startValue uint64) {
|
||||||
|
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue