浏览代码

Prefer nm based function names to addr2line based names.

The names produced by addr2line are often incomplete.  Fix this by
falling back to nm to get function names and using the nm-provided
name if it is longer.
Raul Silvera 9 年前
父节点
当前提交
d933d09123
共有 3 个文件被更改,包括 30 次插入1 次删除
  1. 22
    0
      internal/binutils/addr2liner.go
  2. 7
    0
      internal/binutils/binutils.go
  3. 1
    1
      internal/binutils/binutils_test.go

+ 22
- 0
internal/binutils/addr2liner.go 查看文件

38
 type addr2Liner struct {
38
 type addr2Liner struct {
39
 	rw   lineReaderWriter
39
 	rw   lineReaderWriter
40
 	base uint64
40
 	base uint64
41
+
42
+	// nm holds an NM based addr2Liner which can provide
43
+	// better full names compared to addr2line, which often drops
44
+	// namespaces etc. from the names it returns.
45
+	nm *addr2LinerNM
41
 }
46
 }
42
 
47
 
43
 // lineReaderWriter is an interface to abstract the I/O to an addr2line
48
 // lineReaderWriter is an interface to abstract the I/O to an addr2line
193
 			stack = append(stack, frame)
198
 			stack = append(stack, frame)
194
 		}
199
 		}
195
 	}
200
 	}
201
+
202
+	// Get better name from nm if possible.
203
+	if len(stack) > 0 && d.nm != nil {
204
+		nm, err := d.nm.addrInfo(addr)
205
+		if err == nil && len(nm) > 0 {
206
+			// Last entry in frame list should match since
207
+			// it is non-inlined.  As a simple heuristic,
208
+			// we only switch to the nm-based name if it
209
+			// is longer.
210
+			nmName := nm[len(nm)-1].Func
211
+			a2lName := stack[len(stack)-1].Func
212
+			if len(nmName) > len(a2lName) {
213
+				stack[len(stack)-1].Func = nmName
214
+			}
215
+		}
216
+	}
217
+
196
 	return stack, nil
218
 	return stack, nil
197
 }
219
 }

+ 7
- 0
internal/binutils/binutils.go 查看文件

245
 			return nil, err
245
 			return nil, err
246
 		}
246
 		}
247
 		f.addr2liner = addr2liner
247
 		f.addr2liner = addr2liner
248
+
249
+		// When addr2line encounters some gcc compiled binaries, it
250
+		// drops interesting parts of names in anonymous namespaces.
251
+		// Fallback to NM for better function names.
252
+		if nm, err := newAddr2LinerNM(f.b.nm, f.name, f.base); err == nil {
253
+			f.addr2liner.nm = nm
254
+		}
248
 	}
255
 	}
249
 	return f.addr2liner.addrInfo(addr)
256
 	return f.addr2liner.addrInfo(addr)
250
 }
257
 }

+ 1
- 1
internal/binutils/binutils_test.go 查看文件

37
 func TestAddr2Liner(t *testing.T) {
37
 func TestAddr2Liner(t *testing.T) {
38
 	const offset = 0x500
38
 	const offset = 0x500
39
 
39
 
40
-	a := addr2Liner{&mockAddr2liner{}, offset}
40
+	a := addr2Liner{&mockAddr2liner{}, offset, nil}
41
 	for i := 1; i < 8; i++ {
41
 	for i := 1; i < 8; i++ {
42
 		addr := i*0x1000 + offset
42
 		addr := i*0x1000 + offset
43
 		s, err := a.addrInfo(uint64(addr))
43
 		s, err := a.addrInfo(uint64(addr))