This commit adds the binary analyser code to the toolchain. This binary analyser adds various features such as gathering ELF information (e.g., functions, symbols, ...), micro-libs inspection, ELF comparison, ELF pages division, ... Note that it was developped with Unikraft structure in mind. The binary analyser can be used as an external tool with the '--binary' argument. A specific json file should be provided which contains specific fields (see 'bin_analysis_example.json'). Please, see the wiki for further information. Signed-off-by: Gaulthier Gain <gaulthier.gain@uliege.be>
126 lines
2.9 KiB
Go
126 lines
2.9 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 elf64core
|
|
|
|
import (
|
|
"bytes"
|
|
"debug/elf"
|
|
"encoding/binary"
|
|
"fmt"
|
|
"os"
|
|
"text/tabwriter"
|
|
u "tools/srcs/common"
|
|
)
|
|
|
|
type RelaTables struct {
|
|
nbEntries int
|
|
name string
|
|
dataRela []*dataRela
|
|
}
|
|
|
|
type dataRela struct {
|
|
name *string
|
|
elf64Rela Elf64Rela
|
|
}
|
|
|
|
type Elf64Rela struct {
|
|
Offset uint64
|
|
Type uint32
|
|
SymbolIndex uint32
|
|
Addend int64
|
|
}
|
|
|
|
func (elfFile *ELF64File) addRela(index int, relas []Elf64Rela) error {
|
|
|
|
var relocationTables RelaTables
|
|
relocationTables.nbEntries = len(relas)
|
|
relocationTables.name = elfFile.SectionsTable.DataSect[index].Name
|
|
relocationTables.dataRela = make([]*dataRela, relocationTables.nbEntries)
|
|
|
|
for i := range relas {
|
|
|
|
relocationTables.dataRela[i] = &dataRela{
|
|
elf64Rela: relas[i],
|
|
name: nil,
|
|
}
|
|
}
|
|
|
|
elfFile.RelaTables = append(elfFile.RelaTables, relocationTables)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (elfFile *ELF64File) parseRelocations(index int) error {
|
|
|
|
content, err := elfFile.GetSectionContent(uint16(index))
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("failed reading relocation table: %s", err)
|
|
}
|
|
|
|
rela := make([]Elf64Rela, len(content)/binary.Size(Elf64Rela{}))
|
|
if err := binary.Read(bytes.NewReader(content),
|
|
elfFile.Endianness, rela); err != nil {
|
|
return err
|
|
}
|
|
|
|
if err := elfFile.addRela(index, rela); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (elfFile *ELF64File) resolveRelocSymbolsName() error {
|
|
for _, table := range elfFile.RelaTables {
|
|
for _, s := range table.dataRela {
|
|
t := 0
|
|
if s.elf64Rela.Type == uint32(elf.R_X86_64_JMP_SLOT) ||
|
|
s.elf64Rela.Type == uint32(elf.R_X86_64_GLOB_DAT) ||
|
|
s.elf64Rela.Type == uint32(elf.R_X86_64_COPY) &&
|
|
len(elfFile.SymbolsTables) > 1 {
|
|
t++
|
|
}
|
|
|
|
symName, err := elfFile.SymbolsTables[t].getSymbolName(s.elf64Rela.SymbolIndex)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
s.name = &symName
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (table *RelaTables) displayRelocations(w *tabwriter.Writer) {
|
|
_, _ = fmt.Fprintf(w, "\nRelocation section '%s' contains %d entries:\n",
|
|
table.name, table.nbEntries)
|
|
_, _ = fmt.Fprintln(w, "Offset\tInfo\tType\tValue")
|
|
for _, r := range table.dataRela {
|
|
_, _ = fmt.Fprintf(w, "%.6x\t%.6d\t%s\t%s %x\n",
|
|
r.elf64Rela.Offset, r.elf64Rela.SymbolIndex,
|
|
rx86_64Strings[r.elf64Rela.Type], *r.name,
|
|
r.elf64Rela.Addend)
|
|
}
|
|
}
|
|
|
|
func (elfFile *ELF64File) DisplayRelocationTables() {
|
|
|
|
if len(elfFile.RelaTables) == 0 {
|
|
u.PrintWarning("Relocation table(s) are empty")
|
|
return
|
|
}
|
|
|
|
w := new(tabwriter.Writer)
|
|
w.Init(os.Stdout, 0, 8, 0, '\t', 0)
|
|
fmt.Println("-----------------------------------------------------------------------")
|
|
|
|
for _, table := range elfFile.RelaTables {
|
|
table.displayRelocations(w)
|
|
}
|
|
_ = w.Flush()
|
|
}
|