68 lines
1.5 KiB
Go
68 lines
1.5 KiB
Go
// Package ldd retrieves linker information by invoking ldd from glibc or musl and parsing its output.
|
|
package ldd
|
|
|
|
import (
|
|
"fmt"
|
|
"math"
|
|
"path"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
type Entry struct {
|
|
Name string `json:"name,omitempty"`
|
|
Path string `json:"path,omitempty"`
|
|
Location uint64 `json:"location"`
|
|
}
|
|
|
|
func Parse(stdout fmt.Stringer) ([]*Entry, error) {
|
|
payload := strings.Split(strings.TrimSpace(stdout.String()), "\n")
|
|
result := make([]*Entry, len(payload))
|
|
|
|
for i, ent := range payload {
|
|
if len(ent) == 0 {
|
|
return nil, ErrUnexpectedNewline
|
|
}
|
|
|
|
segment := strings.SplitN(ent, " ", 5)
|
|
|
|
// location index
|
|
var iL int
|
|
|
|
switch len(segment) {
|
|
case 2: // /lib/ld-musl-x86_64.so.1 (0x7f04d14ef000)
|
|
iL = 1
|
|
result[i] = &Entry{Name: segment[0]}
|
|
case 4: // libc.musl-x86_64.so.1 => /lib/ld-musl-x86_64.so.1 (0x7f04d14ef000)
|
|
iL = 3
|
|
if segment[1] != "=>" {
|
|
return nil, ErrUnexpectedSeparator
|
|
}
|
|
if !path.IsAbs(segment[2]) {
|
|
return nil, ErrPathNotAbsolute
|
|
}
|
|
result[i] = &Entry{
|
|
Name: segment[0],
|
|
Path: segment[2],
|
|
}
|
|
default:
|
|
return nil, EntryUnexpectedSegmentsError(ent)
|
|
}
|
|
|
|
if loc, err := parseLocation(segment[iL]); err != nil {
|
|
return nil, err
|
|
} else {
|
|
result[i].Location = loc
|
|
}
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func parseLocation(s string) (uint64, error) {
|
|
if len(s) < 4 || s[len(s)-1] != ')' || s[:3] != "(0x" {
|
|
return math.MaxUint64, ErrBadLocationFormat
|
|
}
|
|
return strconv.ParseUint(s[3:len(s)-1], 16, 64)
|
|
}
|