mirror of
https://github.com/jimeh/rbheap.git
synced 2026-02-19 12:56:46 +00:00
Initial work to get full output format working
This commit is contained in:
20
entry.go
Normal file
20
entry.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
func NewEntry(inputJSON []byte) (*Entry, error) {
|
||||||
|
obj, err := NewObject(inputJSON)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Entry{
|
||||||
|
Object: obj,
|
||||||
|
Index: obj.Index(),
|
||||||
|
}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Entry is a parsed heap item object
|
||||||
|
type Entry struct {
|
||||||
|
Object *Object
|
||||||
|
Offset int64
|
||||||
|
Index string
|
||||||
|
}
|
||||||
71
heap_dump.go
71
heap_dump.go
@@ -1,9 +1,11 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"bufio"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewHeapDump(file string) (*HeapDump, error) {
|
func NewHeapDump(file string) (*HeapDump, error) {
|
||||||
@@ -16,7 +18,7 @@ func NewHeapDump(file string) (*HeapDump, error) {
|
|||||||
type HeapDump struct {
|
type HeapDump struct {
|
||||||
File string
|
File string
|
||||||
Index []string
|
Index []string
|
||||||
Entries map[string]*HeapEntry
|
Entries map[string]*Entry
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process processes the heap dump
|
// Process processes the heap dump
|
||||||
@@ -28,20 +30,71 @@ func (s *HeapDump) Process() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Entries = map[string]*HeapEntry{}
|
s.Entries = map[string]*Entry{}
|
||||||
|
|
||||||
d := json.NewDecoder(file)
|
reader := bufio.NewReader(file)
|
||||||
|
var offset int64 = -1
|
||||||
for {
|
for {
|
||||||
var e HeapEntry
|
offset++
|
||||||
if err := d.Decode(&e); err == io.EOF {
|
line, err := reader.ReadBytes(byte('\n'))
|
||||||
|
if err == io.EOF {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
index := e.Address + ":" + e.Type
|
|
||||||
s.Entries[index] = &e
|
entry, err := NewEntry(line)
|
||||||
s.Index = append(s.Index, index)
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.Offset = offset
|
||||||
|
s.Entries[entry.Index] = entry
|
||||||
|
s.Index = append(s.Index, entry.Index)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *HeapDump) PrintMatchingJSON(indexes *[]string) error {
|
||||||
|
file, err := os.Open(s.File)
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
reader := bufio.NewReader(file)
|
||||||
|
offsets := s.matchingOffsets(indexes)
|
||||||
|
|
||||||
|
var current int64 = 0
|
||||||
|
var offset int64 = -1
|
||||||
|
|
||||||
|
for {
|
||||||
|
offset++
|
||||||
|
line, err := reader.ReadBytes(byte('\n'))
|
||||||
|
if err == io.EOF {
|
||||||
|
break
|
||||||
|
} else if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if offset == offsets[current] {
|
||||||
|
current++
|
||||||
|
fmt.Print(string(line))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *HeapDump) matchingOffsets(indexes *[]string) []int64 {
|
||||||
|
var offsets []int64
|
||||||
|
|
||||||
|
for _, index := range *indexes {
|
||||||
|
offsets = append(offsets, s.Entries[index].Offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
sort.Slice(offsets, func(i, j int) bool { return offsets[i] < offsets[j] })
|
||||||
|
return offsets
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
//go:generate easyjson -all heap_entry.go
|
|
||||||
|
|
||||||
// HeapEntry is a parsed heap item object
|
|
||||||
type HeapEntry struct {
|
|
||||||
Address string `json:"address"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
22
main.go
22
main.go
@@ -49,14 +49,6 @@ func versionString() string {
|
|||||||
return buffer.String()
|
return buffer.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func printHexDiff(leaked *[]string, dump *HeapDump) {
|
|
||||||
for _, index := range *leaked {
|
|
||||||
if item, ok := dump.Entries[index]; ok {
|
|
||||||
fmt.Printf("%s\n", item.Address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func logMsg(msg string) {
|
func logMsg(msg string) {
|
||||||
if !*silentFlag {
|
if !*silentFlag {
|
||||||
fmt.Println(msg)
|
fmt.Println(msg)
|
||||||
@@ -70,6 +62,14 @@ func loadDump(filePath string) (*HeapDump, error) {
|
|||||||
return dump, err
|
return dump, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func printHexDiff(leaked *[]string, dump *HeapDump) {
|
||||||
|
for _, index := range *leaked {
|
||||||
|
if entry, ok := dump.Entries[index]; ok {
|
||||||
|
fmt.Println(entry.Object.Address)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
kingpin.Version(versionString())
|
kingpin.Version(versionString())
|
||||||
kingpin.Parse()
|
kingpin.Parse()
|
||||||
@@ -93,7 +93,7 @@ func main() {
|
|||||||
|
|
||||||
if *formatFlag == "hex" {
|
if *formatFlag == "hex" {
|
||||||
printHexDiff(leaked, dump2)
|
printHexDiff(leaked, dump2)
|
||||||
} // else if *formatFlag == 'full' {
|
} else if *formatFlag == "full" {
|
||||||
// printFullDiff(leaked, dump2)
|
dump2.PrintMatchingJSON(leaked)
|
||||||
// }
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
21
object.go
Normal file
21
object.go
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import "encoding/json"
|
||||||
|
|
||||||
|
//go:generate easyjson -all object.go
|
||||||
|
|
||||||
|
func NewObject(inputJSON []byte) (*Object, error) {
|
||||||
|
var obj Object
|
||||||
|
err := json.Unmarshal(inputJSON, &obj)
|
||||||
|
|
||||||
|
return &obj, err
|
||||||
|
}
|
||||||
|
|
||||||
|
type Object struct {
|
||||||
|
Address string `json:"address"`
|
||||||
|
Type string `json:"type"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Object) Index() string {
|
||||||
|
return s.Address + ":" + s.Type
|
||||||
|
}
|
||||||
@@ -17,7 +17,7 @@ var (
|
|||||||
_ easyjson.Marshaler
|
_ easyjson.Marshaler
|
||||||
)
|
)
|
||||||
|
|
||||||
func easyjson48125c2bDecodeGithubComJimehRbheapleak(in *jlexer.Lexer, out *HeapEntry) {
|
func easyjsonE44bcf2dDecodeGithubComJimehRbheapleak(in *jlexer.Lexer, out *Object) {
|
||||||
isTopLevel := in.IsStart()
|
isTopLevel := in.IsStart()
|
||||||
if in.IsNull() {
|
if in.IsNull() {
|
||||||
if isTopLevel {
|
if isTopLevel {
|
||||||
@@ -50,7 +50,7 @@ func easyjson48125c2bDecodeGithubComJimehRbheapleak(in *jlexer.Lexer, out *HeapE
|
|||||||
in.Consumed()
|
in.Consumed()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func easyjson48125c2bEncodeGithubComJimehRbheapleak(out *jwriter.Writer, in HeapEntry) {
|
func easyjsonE44bcf2dEncodeGithubComJimehRbheapleak(out *jwriter.Writer, in Object) {
|
||||||
out.RawByte('{')
|
out.RawByte('{')
|
||||||
first := true
|
first := true
|
||||||
_ = first
|
_ = first
|
||||||
@@ -78,25 +78,25 @@ func easyjson48125c2bEncodeGithubComJimehRbheapleak(out *jwriter.Writer, in Heap
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON supports json.Marshaler interface
|
// MarshalJSON supports json.Marshaler interface
|
||||||
func (v HeapEntry) MarshalJSON() ([]byte, error) {
|
func (v Object) MarshalJSON() ([]byte, error) {
|
||||||
w := jwriter.Writer{}
|
w := jwriter.Writer{}
|
||||||
easyjson48125c2bEncodeGithubComJimehRbheapleak(&w, v)
|
easyjsonE44bcf2dEncodeGithubComJimehRbheapleak(&w, v)
|
||||||
return w.Buffer.BuildBytes(), w.Error
|
return w.Buffer.BuildBytes(), w.Error
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalEasyJSON supports easyjson.Marshaler interface
|
// MarshalEasyJSON supports easyjson.Marshaler interface
|
||||||
func (v HeapEntry) MarshalEasyJSON(w *jwriter.Writer) {
|
func (v Object) MarshalEasyJSON(w *jwriter.Writer) {
|
||||||
easyjson48125c2bEncodeGithubComJimehRbheapleak(w, v)
|
easyjsonE44bcf2dEncodeGithubComJimehRbheapleak(w, v)
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalJSON supports json.Unmarshaler interface
|
// UnmarshalJSON supports json.Unmarshaler interface
|
||||||
func (v *HeapEntry) UnmarshalJSON(data []byte) error {
|
func (v *Object) UnmarshalJSON(data []byte) error {
|
||||||
r := jlexer.Lexer{Data: data}
|
r := jlexer.Lexer{Data: data}
|
||||||
easyjson48125c2bDecodeGithubComJimehRbheapleak(&r, v)
|
easyjsonE44bcf2dDecodeGithubComJimehRbheapleak(&r, v)
|
||||||
return r.Error()
|
return r.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
|
// UnmarshalEasyJSON supports easyjson.Unmarshaler interface
|
||||||
func (v *HeapEntry) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
func (v *Object) UnmarshalEasyJSON(l *jlexer.Lexer) {
|
||||||
easyjson48125c2bDecodeGithubComJimehRbheapleak(l, v)
|
easyjsonE44bcf2dDecodeGithubComJimehRbheapleak(l, v)
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user