1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
// Copyright 2009 The Go 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 ogle
import (
"eval";
"ptrace";
"reflect";
"os";
"sym";
)
// A FormatError indicates a failure to process information in or
// about a remote process, such as unexpected or missing information
// in the object file or runtime structures.
type FormatError string
func (e FormatError) String() string {
return string(e);
}
// An UnknownArchitecture occurs when trying to load an object file
// that indicates an architecture not supported by the debugger.
type UnknownArchitecture sym.ElfMachine
func (e UnknownArchitecture) String() string {
return "unknown architecture: " + sym.ElfMachine(e).String();
}
// A Process represents a remote attached process.
type Process struct {
Arch;
ptrace.Process;
// The symbol table of this process
syms *sym.GoSymTable;
// Current thread
thread ptrace.Thread;
// Current frame, or nil if the current thread is not stopped
frame *frame;
// Types parsed from the remote process
types map[ptrace.Word] *remoteType;
// Types and values from the remote runtime package
runtime runtimeValues;
// Runtime field indexes
f runtimeIndexes;
}
// NewProcess constructs a new remote process around a ptrace'd
// process, an architecture, and a symbol table.
func NewProcess(proc ptrace.Process, arch Arch, syms *sym.GoSymTable) *Process {
p := &Process{
Arch: arch,
Process: proc,
syms: syms,
thread: proc.Threads()[0],
types: make(map[ptrace.Word] *remoteType),
};
// TODO(austin) Set p.frame if proc is stopped
p.bootstrap();
return p;
}
// NewProcessElf constructs a new remote process around a ptrace'd
// process and the process' ELF object.
func NewProcessElf(proc ptrace.Process, elf *sym.Elf) (*Process, os.Error) {
syms, err := sym.ElfGoSyms(elf);
if err != nil {
return nil, err;
}
if syms == nil {
return nil, FormatError("Failed to find symbol table");
}
var arch Arch;
switch elf.Machine {
case sym.ElfX86_64:
arch = Amd64;
default:
return nil, UnknownArchitecture(elf.Machine);
}
return NewProcess(proc, arch, syms), nil;
}
// bootstrap constructs the runtime structure of a remote process.
func (p *Process) bootstrap() {
// Manually construct runtime types
p.runtime.String = newManualType(eval.TypeOfNative(rt1String{}), p.Arch);
p.runtime.Slice = newManualType(eval.TypeOfNative(rt1Slice{}), p.Arch);
p.runtime.Eface = newManualType(eval.TypeOfNative(rt1Eface{}), p.Arch);
p.runtime.Type = newManualType(eval.TypeOfNative(rt1Type{}), p.Arch);
p.runtime.CommonType = newManualType(eval.TypeOfNative(rt1CommonType{}), p.Arch);
p.runtime.UncommonType = newManualType(eval.TypeOfNative(rt1UncommonType{}), p.Arch);
p.runtime.StructField = newManualType(eval.TypeOfNative(rt1StructField{}), p.Arch);
p.runtime.StructType = newManualType(eval.TypeOfNative(rt1StructType{}), p.Arch);
p.runtime.PtrType = newManualType(eval.TypeOfNative(rt1PtrType{}), p.Arch);
p.runtime.ArrayType = newManualType(eval.TypeOfNative(rt1ArrayType{}), p.Arch);
p.runtime.SliceType = newManualType(eval.TypeOfNative(rt1SliceType{}), p.Arch);
p.runtime.Stktop = newManualType(eval.TypeOfNative(rt1Stktop{}), p.Arch);
p.runtime.Gobuf = newManualType(eval.TypeOfNative(rt1Gobuf{}), p.Arch);
p.runtime.G = newManualType(eval.TypeOfNative(rt1G{}), p.Arch);
// Get addresses of type·*runtime.XType for discrimination.
rtv := reflect.Indirect(reflect.NewValue(&p.runtime)).(*reflect.StructValue);
rtvt := rtv.Type().(*reflect.StructType);
for i := 0; i < rtv.NumField(); i++ {
n := rtvt.Field(i).Name;
if n[0] != 'P' || n[1] < 'A' || n[1] > 'Z' {
continue;
}
sym := p.syms.SymFromName("type·*runtime." + n[1:len(n)]);
if sym == nil {
continue;
}
rtv.Field(i).(*reflect.Uint64Value).Set(sym.Common().Value);
}
// Get field indexes
fillRuntimeIndexes(&p.runtime, &p.f);
}
|