symbolize

package
v0.0.0-...-bbc9ce3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 6, 2021 License: BSD-2-Clause Imports: 22 Imported by: 0

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func ComposePostProcessors

func ComposePostProcessors(ctx context.Context, input <-chan OutputLine, posts ...PostProcessor) <-chan OutputLine

ComposePostProcessors takes several PostProcessors and runs them in sequence

func ComposePreProcessors

func ComposePreProcessors(ctx context.Context, input <-chan InputLine, pres ...PreProcessor) <-chan InputLine

ComposePreProcessors takes several PreProcessors and runs them in sequence

func ComposeProcessors

func ComposeProcessors(ctx context.Context, input <-chan InputLine, proc Processor) <-chan OutputLine

Compose takes a single Processor and causes it to start transforming Input into Output

func Consume

func Consume(input <-chan OutputLine)

Consume eats and forgets all input from a channel. This is useful for keeping a goroutine alive until a pipeline has finished processing to completion.

func GetLineJson

func GetLineJson(line []Node) ([]byte, error)

func StartParsing

func StartParsing(ctx context.Context, reader io.Reader) <-chan InputLine

Types

type BacktraceElement

type BacktraceElement struct {
	// contains filtered or unexported fields
}

func (*BacktraceElement) Accept

func (b *BacktraceElement) Accept(visitor NodeVisitor)

type BacktracePresenter

type BacktracePresenter struct {
	// contains filtered or unexported fields
}

BacktracePresenter intercepts backtrace elements on their own line and presents them in text. Inlines are output as separate lines. A PostProcessor is taken as an input to synchronously compose another PostProcessor

func NewBacktracePresenter

func NewBacktracePresenter(out io.Writer, next PostProcessor) *BacktracePresenter

NewBacktracePresenter constructs a BacktracePresenter.

Example
// mock the input and outputs of llvm-symbolizer
symbo := newMockSymbolizer([]mockModule{
	{
		filepath.Join(*testDataDir, "libc.elf"),
		map[uint64][]SourceLocation{
			0x429c0: {{NewOptStr("math.h"), 51, NewOptStr("__DOUBLE_FLOAT")}, {NewOptStr("atan2.c"), 49, NewOptStr("atan2")}},
			0x43680: {{NewOptStr("pow.c"), 23, NewOptStr("pow")}},
			0x44987: {{NewOptStr("memcpy.c"), 76, NewOptStr("memcpy")}},
		},
	},
	{
		filepath.Join(*testDataDir, "libcrypto.elf"),
		map[uint64][]SourceLocation{
			0x81000: {{NewOptStr("rsa.c"), 101, NewOptStr("mod_exp")}},
			0x82000: {{NewOptStr("aes.c"), 17, NewOptStr("gf256_mul")}},
			0x83000: {{NewOptStr("aes.c"), 560, NewOptStr("gf256_div")}},
		},
	},
})

// make a demuxer
demuxer := NewDemuxer(getTestBinaries(), symbo)

// define a little message that will need to be parsed
msg := "[131.200] 1234.5678> {{{module:1:libc.so:elf:4fcb712aa6387724a9f465a32cd8c14b}}}\n" +
	"[131.301] 1234.5678> {{{module:9:libcrypto.so:elf:12ef5c50b3ed3599c07c02d4509311be}}}\n" +
	"[131.301] 1234.5678> {{{module:3:libmissing.no:elf:deadbeef}}}\n" +
	"[131.402] 1234.5678> {{{mmap:0x12345000:0xcf6bc:load:1:rx:0x0}}}\n" +
	"[131.503] 1234.5678> {{{mmap:0x23456000:0x83c80:load:09:rx:0x80000}}}\n" +
	"[131.503] 1234.5678> {{{mmap:0x34567000:0x1000:load:3:rx:0x0}}}\n" +
	"[131.604] 1234.5678> Backtrace:\n" +
	"[131.604] 1234.5678> {{{bt:0:0x12388680}}}\n" +
	"[131.604] 1234.5678> {{{bt:1:0x23457000}}}\n" +
	"[131.604] 1234.5678> {{{bt:2:0x123879c0}}}\n" +
	"[131.705] 1234.5678> {{{bt:3:0x34567042}}}\n"

// start sending InputLines to the demuxer
ctx := context.Background()
in := StartParsing(ctx, strings.NewReader(msg))
// start the demuxer which will cause filters to send output lines to 'out'
out := demuxer.Start(ctx, in)

Consume(ComposePostProcessors(ctx, out,
	&ContextPresenter{},
	NewBacktracePresenter(os.Stdout, NewBasicPresenter(os.Stdout, false))))
Output:

[131.604] 01234.05678> [[[ELF module #0x1 "libc.so" BuildID=4fcb712aa6387724a9f465a32cd8c14b 0x12345000]]]
[131.604] 01234.05678> [[[ELF module #0x3 "libmissing.no" BuildID=deadbeef 0x34567000]]]
[131.604] 01234.05678> [[[ELF module #0x9 "libcrypto.so" BuildID=12ef5c50b3ed3599c07c02d4509311be 0x23456000]]]
[131.604] 01234.05678> Backtrace:
[131.604] 01234.05678>    #0    0x0000000012388680 in pow pow.c:23 <libc.so>+0x43680
[131.604] 01234.05678>    #1    0x0000000023457000 in mod_exp rsa.c:101 <libcrypto.so>+0x81000
[131.604] 01234.05678>    #2.1  0x00000000123879c0 in __DOUBLE_FLOAT math.h:51 <libc.so>+0x429c0
[131.604] 01234.05678>    #2    0x00000000123879c0 in atan2 atan2.c:49 <libc.so>+0x429c0
[131.705] 01234.05678>    #3    0x0000000034567042 in <libmissing.no>+0x42

func (*BacktracePresenter) Process

func (b *BacktracePresenter) Process(line OutputLine, out chan<- OutputLine)

type BasicPresenter

type BasicPresenter struct {
	// contains filtered or unexported fields
}

BasicPresenter is a presenter to output very basic uncolored output

func NewBasicPresenter

func NewBasicPresenter(output io.Writer, enableColor bool) *BasicPresenter

func (*BasicPresenter) Process

func (b *BasicPresenter) Process(res OutputLine, out chan<- OutputLine)

type CloudRepo

type CloudRepo struct {
	// contains filtered or unexported fields
}

CloudRepo represents a repository stored in a GCS path.

func NewCloudRepo

func NewCloudRepo(ctx context.Context, gcsURL string, cache *cache.FileCache) (*CloudRepo, error)

NewCloudRepo creates a CloudRepo using gcsURL. The connection to the bucket will be ended when ctx is canceled. No timeout on GetBuildObject is set until SetTimeout is called.

func (*CloudRepo) GetBuildObject

func (c *CloudRepo) GetBuildObject(buildID string) (FileCloser, error)

GetBuildObject checks the cache for the debug object. If available it uses that. Otherwise it downloads the object, adds it to the cache, and returns the local reference.

func (*CloudRepo) SetTimeout

func (c *CloudRepo) SetTimeout(t time.Duration)

SetTimeout sets the maximum duration that GetBuildObject will wait before canceling the download from GCS.

type ColorCode

type ColorCode struct {
	// contains filtered or unexported fields
}

TODO(jakehehrlich): Make this semantic rather than literal (e.g. keep track of color/bold information directly) ColorCode is an AST node representing a colored part of the markup

func (*ColorCode) Accept

func (c *ColorCode) Accept(visitor NodeVisitor)

type CompositeRepo

type CompositeRepo struct {
	// contains filtered or unexported fields
}

func (*CompositeRepo) AddRepo

func (c *CompositeRepo) AddRepo(repo Repository)

AddRepo adds a repo to be checked that has lower priority than any other previouslly added repo. This operation is not thread safe.

func (*CompositeRepo) GetBuildObject

func (c *CompositeRepo) GetBuildObject(buildID string) (FileCloser, error)

type ContextPresenter

type ContextPresenter map[LineSource]map[uint64]dsoInfo

func (ContextPresenter) Process

func (c ContextPresenter) Process(line OutputLine, out chan<- OutputLine)

type Demuxer

type Demuxer struct {
	// contains filtered or unexported fields
}

Demuxer demultiplexes incomming input lines, spins up new filters, and sends them input lines.

func NewDemuxer

func NewDemuxer(repo Repository, symbo Symbolizer) *Demuxer

NewDemuxer creates a new demuxer.

func (*Demuxer) Start

func (d *Demuxer) Start(ctx context.Context, input <-chan InputLine) <-chan OutputLine

Start tells the demuxer to start consuming input and dispatching to the filters.

type DummySource

type DummySource struct{}

type DumpEntry

type DumpEntry struct {
	Modules  []Module  `json:"modules"`
	Segments []Segment `json:"segments"`
	Type     string    `json:"type"`
	Name     string    `json:"name"`
}

type DumpHandler

type DumpHandler struct {
	// contains filtered or unexported fields
}

func (*DumpHandler) HandleDump

func (d *DumpHandler) HandleDump(dump *DumpfileElement)

func (*DumpHandler) Write

func (d *DumpHandler) Write(buf io.Writer) error

type DumpfileElement

type DumpfileElement struct {
	// contains filtered or unexported fields
}

func (*DumpfileElement) Accept

func (d *DumpfileElement) Accept(visitor NodeVisitor)

func (*DumpfileElement) Context

func (d *DumpfileElement) Context() TriggerContext

func (*DumpfileElement) Name

func (d *DumpfileElement) Name() string

func (*DumpfileElement) SinkType

func (d *DumpfileElement) SinkType() string

type Entry

type Entry struct {
	SymbolPath string
	BuildDir   string
}

type FileCloser

type FileCloser interface {
	String() string
	Close() error
}

FileCloser holds a reference to a file and prevents it from being deleted until after Close() is called. The filename can be retrieved via String()

type Filter

type Filter struct {
	// contains filtered or unexported fields
}

Filter represents the state needed to process a log.

func NewFilter

func NewFilter(repo Repository, symbo Symbolizer) *Filter

NewFilter creates a new filter

func (*Filter) Start

func (f *Filter) Start(ctx context.Context, input <-chan InputLine) <-chan OutputLine

Start tells the filter to start consuming input and produce output.

type IDsTxtRepo

type IDsTxtRepo struct {
	// contains filtered or unexported fields
}

idsSource is a BinaryFileSource parsed from ids.txt

func NewIDsTxtRepo

func NewIDsTxtRepo(pathToIDs string, rel bool) *IDsTxtRepo

func (*IDsTxtRepo) GetBuildObject

func (i *IDsTxtRepo) GetBuildObject(buildID string) (FileCloser, error)

type Index

type Index []Entry

func LoadIndex

func LoadIndex(reader io.Reader) (Index, error)

type InputLine

type InputLine struct {
	LogLine
	// contains filtered or unexported fields
}

type LLVMSymbolizeResult

type LLVMSymbolizeResult struct {
	Locs []SourceLocation
	Err  error
}

type LLVMSymbolizer

type LLVMSymbolizer struct {
	// contains filtered or unexported fields
}

func NewLLVMSymbolizer

func NewLLVMSymbolizer(llvmSymboPath string, restartInterval uint) *LLVMSymbolizer

func (*LLVMSymbolizer) FindSrcLoc

func (s *LLVMSymbolizer) FindSrcLoc(file, build string, modRelAddr uint64) <-chan LLVMSymbolizeResult

func (*LLVMSymbolizer) Start

func (s *LLVMSymbolizer) Start(ctx context.Context) error

type LineHeader

type LineHeader interface {
	Present() string
}

type LineSource

type LineSource interface{}

TODO (jakehehrlich): LineSource is now a part of the public interface. This is needed to allow for the proper construction of triggers since triggers need to know where a triggering element came from. Right now this is just an empty interface. It would be nice if the user could do soemthing other than cast this.

type LogLine

type LogLine struct {
	// contains filtered or unexported fields
}

type MappingElement

type MappingElement struct {
	// contains filtered or unexported fields
}

MappingElement represents an mmap element in the markup

func (*MappingElement) Accept

func (s *MappingElement) Accept(visitor NodeVisitor)

type Module

type Module struct {
	Name  string `json:"name"`
	Build string `json:"build"`
	Id    uint64 `json:"id"`
}

type ModuleElement

type ModuleElement struct {
	// contains filtered or unexported fields
}

ModuleElement represents a module element in the markup

func (*ModuleElement) Accept

func (m *ModuleElement) Accept(visitor NodeVisitor)

type NewBuildIDRepo

type NewBuildIDRepo string

func (NewBuildIDRepo) GetBuildObject

func (b NewBuildIDRepo) GetBuildObject(buildID string) (FileCloser, error)

type Node

type Node interface {
	Accept(visitor NodeVisitor)
}

type NodeVisitor

type NodeVisitor interface {
	VisitBt(elem *BacktraceElement)
	VisitPc(elem *PCElement)
	VisitColor(node *ColorCode)
	VisitText(node *Text)
	VisitDump(elem *DumpfileElement)
	VisitReset(elem *ResetElement)
	VisitModule(elem *ModuleElement)
	VisitMapping(elem *MappingElement)
}

NodeVisitor is a visitor for all Node types

type NopFileCloser

type NopFileCloser string

func (NopFileCloser) Close

func (d NopFileCloser) Close() error

func (NopFileCloser) String

func (d NopFileCloser) String() string

type OptStr

type OptStr struct {
	// contains filtered or unexported fields
}

OptionalString implements possibly missing strings from llvm-symbolizer

func EmptyOptStr

func EmptyOptStr() OptStr

func NewOptStr

func NewOptStr(s string) OptStr

func (OptStr) Format

func (o OptStr) Format(f fmt.State, c rune)

func (OptStr) IsEmpty

func (o OptStr) IsEmpty() bool

func (OptStr) MarshalJSON

func (o OptStr) MarshalJSON() ([]byte, error)

func (OptStr) String

func (o OptStr) String() string

func (*OptStr) Unwrap

func (o *OptStr) Unwrap(def string) string

type OptimizeColor

type OptimizeColor struct {
}

OptimizeColor attempts to transform output elements to use as few color transisitions as is possible

func (*OptimizeColor) Process

func (o *OptimizeColor) Process(line OutputLine, out chan<- OutputLine)

type OutputLine

type OutputLine struct {
	LogLine
	// contains filtered or unexported fields
}

type PCElement

type PCElement struct {
	// contains filtered or unexported fields
}

PcElement is an AST node representing a pc element in the markup

func (*PCElement) Accept

func (p *PCElement) Accept(visitor NodeVisitor)

type ParseLineFunc

type ParseLineFunc func(msg string) []Node

func GetLineParser

func GetLineParser() ParseLineFunc

type PostProcessor

type PostProcessor interface {
	Process(OutputLine, chan<- OutputLine)
}

PostProcessor is the type of modifications to a stream of OutputLines

type PreProcessor

type PreProcessor interface {
	Process(InputLine, chan<- InputLine)
}

PreProcessor is the type of modifications to a stream of InputLines

type Process

type Process uint64

type Processor

type Processor interface {
	Process(InputLine, chan<- OutputLine)
}

Processor is the type of transformations from OutputLines to InputLines

type Repository

type Repository interface {
	// GetBuildObject takes a build ID and returns the corresponding file
	// reference via a FileCloser.
	GetBuildObject(buildID string) (FileCloser, error)
}

Repository represents a collection of debug binaries referable to by filepath and indexed by their build ID.

type ResetElement

type ResetElement struct{}

func (*ResetElement) Accept

func (r *ResetElement) Accept(visitor NodeVisitor)

type Segment

type Segment struct {
	Mod        uint64 `json:"mod"`
	Vaddr      uint64 `json:"vaddr"`
	Size       uint64 `json:"size"`
	Flags      string `json:"flags"`
	ModRelAddr uint64 `json:"mod_rel_addr"`
}

Later this will be more general.

type SourceLocation

type SourceLocation struct {
	// contains filtered or unexported fields
}

SourceLocation represents a location in a source file

type Symbolizer

type Symbolizer interface {
	FindSrcLoc(file, build string, modRelAddr uint64) <-chan LLVMSymbolizeResult
}

Symbolizer is an interface to an object that maps addresses in a bianry to source locations

type Text

type Text struct {
	// contains filtered or unexported fields
}

Text represents text between the special parts of the markup

func (*Text) Accept

func (t *Text) Accept(visitor NodeVisitor)

type TriggerContext

type TriggerContext struct {
	Source LineSource
	Mods   []Module
	Segs   []Segment
}

TriggerHandler is a visitor for Node types that can trigger actions

type TriggerTap

type TriggerTap struct {
	// contains filtered or unexported fields
}

TriggerTap is a nop on the pipeline that reads trigger information out

func NewTriggerTap

func NewTriggerTap() *TriggerTap

func (*TriggerTap) AddHandler

func (t *TriggerTap) AddHandler(handler func(*DumpfileElement))

func (*TriggerTap) Process

func (t *TriggerTap) Process(line OutputLine, out chan<- OutputLine)

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL