gaulthiergain-tools/srcs/binarytool/elf64core/elf_relocation.go
Gaulthier Gain f25637cdb7 Add binary analyser code to the toolchain
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>
2021-01-30 12:37:27 +01:00

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()
}