diff options
Diffstat (limited to 'pkg/symbolizer')
| -rw-r--r-- | pkg/symbolizer/nm.go | 27 | ||||
| -rw-r--r-- | pkg/symbolizer/nm_test.go | 37 |
2 files changed, 40 insertions, 24 deletions
diff --git a/pkg/symbolizer/nm.go b/pkg/symbolizer/nm.go index 01d23ab94..caa246629 100644 --- a/pkg/symbolizer/nm.go +++ b/pkg/symbolizer/nm.go @@ -18,7 +18,7 @@ type Symbol struct { // ReadSymbols returns list of text symbols in the binary bin. func ReadSymbols(bin string) (map[string][]Symbol, error) { - cmd := osutil.Command("nm", "-nS", bin) + cmd := osutil.Command("nm", "-Ptx", bin) stdout, err := cmd.StdoutPipe() if err != nil { return nil, err @@ -32,32 +32,39 @@ func ReadSymbols(bin string) (map[string][]Symbol, error) { s := bufio.NewScanner(stdout) text := [][]byte{[]byte(" t "), []byte(" T ")} for s.Scan() { - // A line looks as: "ffffffff8104db90 0000000000000059 t snb_uncore_msr_enable_box" + // A line looks as: "snb_uncore_msr_enable_box t ffffffff8104db90 0000000000000059" ln := s.Bytes() if !bytes.Contains(ln, text[0]) && !bytes.Contains(ln, text[1]) { continue } + sp1 := bytes.IndexByte(ln, ' ') if sp1 == -1 { continue } - sp2 := bytes.IndexByte(ln[sp1+1:], ' ') - if sp2 == -1 { + if !bytes.HasPrefix(ln[sp1:], text[0]) && !bytes.HasPrefix(ln[sp1:], text[1]) { continue } - sp2 += sp1 + 1 - if !bytes.HasPrefix(ln[sp2:], text[0]) && !bytes.HasPrefix(ln[sp2:], text[1]) { + + sp2 := sp1 + len(text[0]) + sp3 := bytes.IndexByte(ln[sp2:], ' ') + if sp3 == -1 { continue } - addr, err := strconv.ParseUint(string(ln[:sp1]), 16, 64) + sp3 += sp2 + + addr, err := strconv.ParseUint(string(ln[sp2:sp3]), 16, 64) if err != nil { continue } - size, err := strconv.ParseUint(string(ln[sp1+1:sp2]), 16, 64) - if err != nil { + + size, err := strconv.ParseUint(string(ln[sp3+1:]), 16, 64) + if err != nil || size == 0 { continue } - name := string(ln[sp2+len(text[0]):]) + + name := string(ln[:sp1]) + // Note: sizes reported by kernel do not match nm. // Kernel probably subtracts address of this symbol from address of the next symbol. // We could do the same, but for now we just round up size to 16. diff --git a/pkg/symbolizer/nm_test.go b/pkg/symbolizer/nm_test.go index 7aca6cb67..44a02f3cc 100644 --- a/pkg/symbolizer/nm_test.go +++ b/pkg/symbolizer/nm_test.go @@ -4,15 +4,10 @@ package symbolizer import ( - "runtime" "testing" ) func TestSymbols(t *testing.T) { - if runtime.GOOS != "linux" { - // On openbsd it fails because nm does not have -S flag. - t.Skipf("broken on %v", runtime.GOOS) - } symbols, err := ReadSymbols("testdata/nm.test.out") if err != nil { t.Fatalf("failed to read symbols: %v", err) @@ -37,17 +32,31 @@ func TestSymbols(t *testing.T) { if len(s) != 2 { t.Fatalf("got %v foobar symbols, want 2", len(s)) } - if s[0].Addr != 0x4004ed { - t.Fatalf("bad foobar[0] address: 0x%x", s[0].Addr) - } - if s[0].Size != 0x10 { - t.Fatalf("bad foobar[0] size: 0x%x", s[0].Size) + want := []Symbol{ + { + Addr: 0x4004fa, + Size: 0x10, + }, + { + Addr: 0x4004ed, + Size: 0x10, + }, } - if s[1].Addr != 0x4004fa { - t.Fatalf("bad foobar[1] address: 0x%x", s[1].Addr) + if !symcmp(want[0], s[0]) && !symcmp(want[0], s[1]) { + t.Fatalf("foobar symbol %+v not found", want[0]) } - if s[1].Size != 0x10 { - t.Fatalf("bad foobar[1] size: 0x%x", s[1].Size) + if !symcmp(want[1], s[0]) && !symcmp(want[1], s[1]) { + t.Fatalf("foobar symbol %+v not found", want[1]) } } } + +func symcmp(want Symbol, got Symbol) bool { + if want.Addr != got.Addr { + return false + } + if want.Size != got.Size { + return false + } + return true +} |
