Commit f5b600f7 authored by Pietro Gagliardi's avatar Pietro Gagliardi Committed by Ian Lance Taylor

debug/elf: add (*File).DynamicSymbols, ErrNoSymbols, and tests for...

debug/elf: add (*File).DynamicSymbols, ErrNoSymbols, and tests for (*File).Symbols and (*File).DynamicSymbols, and formalize symbol order.

Added a complement to (*File).Symbols for the dynamic symbol table.
Would be useful, for instance, if seraching for certain shared objects
compatible with certain libraries (for instance, LADSPA requires an
exported symbol "ladspa_descriptor").

Added a variable ErrNoSymbols that canonicalizes a return from
(*File).Symbols and (*File).DyanmicSymbols if the file has no symbols.

Added tests for both (*File).Symbols and (*File).DynamicSymbols;
there was never a test for (*File).Symbols at all. A small C program using
libelf, included in the test data, was used to produce the golden
symbols to compare against.

As part of the requirements for testing, (*File).Symbols and (*File).DynamicSymbols now document the order in which the symbol tables are returned (in the order the symbols appear in the file).

All tests currently pass.

LGTM=iant
R=golang-codereviews, iant
CC=golang-codereviews
https://golang.org/cl/107530043
parent 54d0b5ab
...@@ -405,10 +405,14 @@ func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) { ...@@ -405,10 +405,14 @@ func (f *File) getSymbols(typ SectionType) ([]Symbol, []byte, error) {
return nil, nil, errors.New("not implemented") return nil, nil, errors.New("not implemented")
} }
// ErrNoSymbols is returned by File.Symbols and File.DynamicSymbols
// if there is no such section in the File.
var ErrNoSymbols = errors.New("no symbol section")
func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
symtabSection := f.SectionByType(typ) symtabSection := f.SectionByType(typ)
if symtabSection == nil { if symtabSection == nil {
return nil, nil, errors.New("no symbol section") return nil, nil, ErrNoSymbols
} }
data, err := symtabSection.Data() data, err := symtabSection.Data()
...@@ -451,7 +455,7 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) { ...@@ -451,7 +455,7 @@ func (f *File) getSymbols32(typ SectionType) ([]Symbol, []byte, error) {
func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) { func (f *File) getSymbols64(typ SectionType) ([]Symbol, []byte, error) {
symtabSection := f.SectionByType(typ) symtabSection := f.SectionByType(typ)
if symtabSection == nil { if symtabSection == nil {
return nil, nil, errors.New("no symbol section") return nil, nil, ErrNoSymbols
} }
data, err := symtabSection.Data() data, err := symtabSection.Data()
...@@ -698,7 +702,8 @@ func (f *File) DWARF() (*dwarf.Data, error) { ...@@ -698,7 +702,8 @@ func (f *File) DWARF() (*dwarf.Data, error) {
return d, nil return d, nil
} }
// Symbols returns the symbol table for f. // Symbols returns the symbol table for f. The symbols will be listed in the order
// they appear in f.
// //
// For compatibility with Go 1.0, Symbols omits the null symbol at index 0. // For compatibility with Go 1.0, Symbols omits the null symbol at index 0.
// After retrieving the symbols as symtab, an externally supplied index x // After retrieving the symbols as symtab, an externally supplied index x
...@@ -708,6 +713,17 @@ func (f *File) Symbols() ([]Symbol, error) { ...@@ -708,6 +713,17 @@ func (f *File) Symbols() ([]Symbol, error) {
return sym, err return sym, err
} }
// DynamicSymbols returns the dynamic symbol table for f. The symbols
// will be listed in the order they appear in f.
//
// For compatibility with Symbols, DynamicSymbols omits the null symbol at index 0.
// After retrieving the symbols as symtab, an externally supplied index x
// corresponds to symtab[x-1], not symtab[x].
func (f *File) DynamicSymbols() ([]Symbol, error) {
sym, _, err := f.getSymbols(SHT_DYNSYM)
return sym, err
}
type ImportedSymbol struct { type ImportedSymbol struct {
Name string Name string
Version string Version string
......
// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package elf
import (
"io"
"path"
"reflect"
"testing"
)
// TODO: remove duplicate code
func TestSymbols(t *testing.T) {
do := func(file string, ts []Symbol, getfunc func(*File) ([]Symbol, error)) {
var f *File
var err error
if path.Ext(file) == ".gz" {
var r io.ReaderAt
if r, err = decompress(file); err == nil {
f, err = NewFile(r)
}
} else {
f, err = Open(file)
}
if err != nil {
t.Errorf("TestSymbols: cannot open file %s: %v", file, err)
return
}
defer f.Close()
fs, err := getfunc(f)
if err != nil && err != ErrNoSymbols {
t.Error(err)
return
} else if err == ErrNoSymbols {
fs = []Symbol{}
}
if !reflect.DeepEqual(ts, fs) {
t.Errorf("%s: Symbols = %v, want %v", file, ts, fs)
}
}
for file, ts := range symbolsGolden {
do(file, ts, (*File).Symbols)
}
for file, ts := range dynamicSymbolsGolden {
do(file, ts, (*File).DynamicSymbols)
}
}
// golden symbol table data generated by testdata/getgoldsym.c
var symbolsGolden = map[string][]Symbol{
"testdata/gcc-amd64-linux-exec": {
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x1,
Value: 0x400200,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x2,
Value: 0x40021C,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x3,
Value: 0x400240,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x4,
Value: 0x400268,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x5,
Value: 0x400288,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x6,
Value: 0x4002E8,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x7,
Value: 0x400326,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x8,
Value: 0x400330,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x9,
Value: 0x400350,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xA,
Value: 0x400368,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xB,
Value: 0x400398,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xC,
Value: 0x4003B0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xD,
Value: 0x4003E0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xE,
Value: 0x400594,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xF,
Value: 0x4005A4,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x10,
Value: 0x4005B8,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x11,
Value: 0x4005E0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x12,
Value: 0x600688,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x13,
Value: 0x600698,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x14,
Value: 0x6006A8,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x15,
Value: 0x6006B0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x16,
Value: 0x600850,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x17,
Value: 0x600858,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x18,
Value: 0x600880,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x19,
Value: 0x600898,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x1A,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x1B,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x1C,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x1D,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x1E,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x1F,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x20,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x21,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "init.c",
Info: 0x4,
Other: 0x0,
Section: 0xFFF1,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "initfini.c",
Info: 0x4,
Other: 0x0,
Section: 0xFFF1,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "call_gmon_start",
Info: 0x2,
Other: 0x0,
Section: 0xD,
Value: 0x40040C,
Size: 0x0,
},
Symbol{
Name: "crtstuff.c",
Info: 0x4,
Other: 0x0,
Section: 0xFFF1,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "__CTOR_LIST__",
Info: 0x1,
Other: 0x0,
Section: 0x12,
Value: 0x600688,
Size: 0x0,
},
Symbol{
Name: "__DTOR_LIST__",
Info: 0x1,
Other: 0x0,
Section: 0x13,
Value: 0x600698,
Size: 0x0,
},
Symbol{
Name: "__JCR_LIST__",
Info: 0x1,
Other: 0x0,
Section: 0x14,
Value: 0x6006A8,
Size: 0x0,
},
Symbol{
Name: "__do_global_dtors_aux",
Info: 0x2,
Other: 0x0,
Section: 0xD,
Value: 0x400430,
Size: 0x0,
},
Symbol{
Name: "completed.6183",
Info: 0x1,
Other: 0x0,
Section: 0x19,
Value: 0x600898,
Size: 0x1,
},
Symbol{
Name: "p.6181",
Info: 0x1,
Other: 0x0,
Section: 0x18,
Value: 0x600890,
Size: 0x0,
},
Symbol{
Name: "frame_dummy",
Info: 0x2,
Other: 0x0,
Section: 0xD,
Value: 0x400470,
Size: 0x0,
},
Symbol{
Name: "crtstuff.c",
Info: 0x4,
Other: 0x0,
Section: 0xFFF1,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "__CTOR_END__",
Info: 0x1,
Other: 0x0,
Section: 0x12,
Value: 0x600690,
Size: 0x0,
},
Symbol{
Name: "__DTOR_END__",
Info: 0x1,
Other: 0x0,
Section: 0x13,
Value: 0x6006A0,
Size: 0x0,
},
Symbol{
Name: "__FRAME_END__",
Info: 0x1,
Other: 0x0,
Section: 0x11,
Value: 0x400680,
Size: 0x0,
},
Symbol{
Name: "__JCR_END__",
Info: 0x1,
Other: 0x0,
Section: 0x14,
Value: 0x6006A8,
Size: 0x0,
},
Symbol{
Name: "__do_global_ctors_aux",
Info: 0x2,
Other: 0x0,
Section: 0xD,
Value: 0x400560,
Size: 0x0,
},
Symbol{
Name: "initfini.c",
Info: 0x4,
Other: 0x0,
Section: 0xFFF1,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "hello.c",
Info: 0x4,
Other: 0x0,
Section: 0xFFF1,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "_GLOBAL_OFFSET_TABLE_",
Info: 0x1,
Other: 0x2,
Section: 0x17,
Value: 0x600858,
Size: 0x0,
},
Symbol{
Name: "__init_array_end",
Info: 0x0,
Other: 0x2,
Section: 0x12,
Value: 0x600684,
Size: 0x0,
},
Symbol{
Name: "__init_array_start",
Info: 0x0,
Other: 0x2,
Section: 0x12,
Value: 0x600684,
Size: 0x0,
},
Symbol{
Name: "_DYNAMIC",
Info: 0x1,
Other: 0x2,
Section: 0x15,
Value: 0x6006B0,
Size: 0x0,
},
Symbol{
Name: "data_start",
Info: 0x20,
Other: 0x0,
Section: 0x18,
Value: 0x600880,
Size: 0x0,
},
Symbol{
Name: "__libc_csu_fini",
Info: 0x12,
Other: 0x0,
Section: 0xD,
Value: 0x4004C0,
Size: 0x2,
},
Symbol{
Name: "_start",
Info: 0x12,
Other: 0x0,
Section: 0xD,
Value: 0x4003E0,
Size: 0x0,
},
Symbol{
Name: "__gmon_start__",
Info: 0x20,
Other: 0x0,
Section: 0x0,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "_Jv_RegisterClasses",
Info: 0x20,
Other: 0x0,
Section: 0x0,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "puts@@GLIBC_2.2.5",
Info: 0x12,
Other: 0x0,
Section: 0x0,
Value: 0x0,
Size: 0x18C,
},
Symbol{
Name: "_fini",
Info: 0x12,
Other: 0x0,
Section: 0xE,
Value: 0x400594,
Size: 0x0,
},
Symbol{
Name: "__libc_start_main@@GLIBC_2.2.5",
Info: 0x12,
Other: 0x0,
Section: 0x0,
Value: 0x0,
Size: 0x1C2,
},
Symbol{
Name: "_IO_stdin_used",
Info: 0x11,
Other: 0x0,
Section: 0xF,
Value: 0x4005A4,
Size: 0x4,
},
Symbol{
Name: "__data_start",
Info: 0x10,
Other: 0x0,
Section: 0x18,
Value: 0x600880,
Size: 0x0,
},
Symbol{
Name: "__dso_handle",
Info: 0x11,
Other: 0x2,
Section: 0x18,
Value: 0x600888,
Size: 0x0,
},
Symbol{
Name: "__libc_csu_init",
Info: 0x12,
Other: 0x0,
Section: 0xD,
Value: 0x4004D0,
Size: 0x89,
},
Symbol{
Name: "__bss_start",
Info: 0x10,
Other: 0x0,
Section: 0xFFF1,
Value: 0x600898,
Size: 0x0,
},
Symbol{
Name: "_end",
Info: 0x10,
Other: 0x0,
Section: 0xFFF1,
Value: 0x6008A0,
Size: 0x0,
},
Symbol{
Name: "_edata",
Info: 0x10,
Other: 0x0,
Section: 0xFFF1,
Value: 0x600898,
Size: 0x0,
},
Symbol{
Name: "main",
Info: 0x12,
Other: 0x0,
Section: 0xD,
Value: 0x400498,
Size: 0x1B,
},
Symbol{
Name: "_init",
Info: 0x12,
Other: 0x0,
Section: 0xB,
Value: 0x400398,
Size: 0x0,
},
},
"testdata/go-relocation-test-clang-x86.obj": {
Symbol{
Name: "go-relocation-test-clang.c",
Info: 0x4,
Other: 0x0,
Section: 0xFFF1,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: ".Linfo_string0",
Info: 0x0,
Other: 0x0,
Section: 0xC,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: ".Linfo_string1",
Info: 0x0,
Other: 0x0,
Section: 0xC,
Value: 0x2C,
Size: 0x0,
},
Symbol{
Name: ".Linfo_string2",
Info: 0x0,
Other: 0x0,
Section: 0xC,
Value: 0x47,
Size: 0x0,
},
Symbol{
Name: ".Linfo_string3",
Info: 0x0,
Other: 0x0,
Section: 0xC,
Value: 0x4C,
Size: 0x0,
},
Symbol{
Name: ".Linfo_string4",
Info: 0x0,
Other: 0x0,
Section: 0xC,
Value: 0x4E,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x1,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x2,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x3,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x4,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x6,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x7,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x8,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xA,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xC,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xD,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xE,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0xF,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "",
Info: 0x3,
Other: 0x0,
Section: 0x10,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "v",
Info: 0x11,
Other: 0x0,
Section: 0xFFF2,
Value: 0x4,
Size: 0x4,
},
},
"testdata/hello-world-core.gz": {},
}
var dynamicSymbolsGolden = map[string][]Symbol{
"testdata/gcc-amd64-linux-exec": {
Symbol{
Name: "__gmon_start__",
Info: 0x20,
Other: 0x0,
Section: 0x0,
Value: 0x0,
Size: 0x0,
},
Symbol{
Name: "puts",
Info: 0x12,
Other: 0x0,
Section: 0x0,
Value: 0x0,
Size: 0x18C,
},
Symbol{
Name: "__libc_start_main",
Info: 0x12,
Other: 0x0,
Section: 0x0,
Value: 0x0,
Size: 0x1C2,
},
},
"testdata/go-relocation-test-clang-x86.obj": {},
"testdata/hello-world-core.gz": {},
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment