| // Copyright 2018 The Fuchsia 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 elflib |
| |
| import ( |
| "debug/dwarf" |
| "debug/elf" |
| "fmt" |
| "io" |
| ) |
| |
| // ListSources reads the DWARF information in a given binary to determine the |
| // source locations that comprise it. The returned sources are deduped, but are |
| // in no particular order. |
| func ListSources(binary string) ([]string, error) { |
| f, err := elf.Open(binary) |
| if err != nil { |
| return nil, fmt.Errorf("failed to open binary: %w", err) |
| } |
| defer f.Close() |
| |
| data, err := f.DWARF() |
| if err != nil { |
| return nil, fmt.Errorf("failed to obtain DWARF information: %w", err) |
| } |
| |
| r := data.Reader() |
| var srcs []string |
| seen := make(map[string]bool) |
| for { |
| entry, err := r.Next() |
| if err != nil { |
| return nil, fmt.Errorf("failed to read entry: %w", err) |
| } else if entry == nil { |
| break // Last entry. |
| } |
| lr, err := data.LineReader(entry) |
| if err != nil { |
| return nil, fmt.Errorf("failed to create a line table reader: %w", err) |
| } else if lr == nil { |
| continue // No line table. |
| } |
| |
| le := new(dwarf.LineEntry) |
| for { |
| err = lr.Next(le) |
| if err == io.EOF { |
| break // End of line table. |
| } else if err != nil { |
| return nil, fmt.Errorf("failed to read line table entry: %w", err) |
| } |
| for _, lf := range lr.Files() { |
| if lf == nil { // First entry is always nil. |
| continue |
| } else if _, ok := seen[lf.Name]; ok { |
| continue |
| } |
| srcs = append(srcs, lf.Name) |
| seen[lf.Name] = true |
| } |
| } |
| } |
| return srcs, nil |
| } |