Skip to content

Commit 0ae2d31

Browse files
committed
Add a test
1 parent dbfc5dc commit 0ae2d31

4 files changed

Lines changed: 167 additions & 1 deletion

File tree

libpf/pfelf/file_test.go

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
package pfelf
55

66
import (
7+
"fmt"
78
"os"
9+
"runtime"
810
"testing"
911

1012
"github.com/stretchr/testify/assert"
1113
"github.com/stretchr/testify/require"
1214
"go.opentelemetry.io/ebpf-profiler/testsupport"
1315

1416
"go.opentelemetry.io/ebpf-profiler/libpf"
17+
xx "golang.org/x/arch/x86/x86asm"
1518
)
1619

1720
func getPFELF(path string, t *testing.T) *File {
@@ -78,3 +81,88 @@ func TestPFELFIsGolang(t *testing.T) {
7881
testPFELFIsGolang(t, "testdata/go-binary", true)
7982
testPFELFIsGolang(t, "testdata/without-debug-syms", false)
8083
}
84+
85+
func symbolOffsetFromCodeX86(code []byte) (int64, error) {
86+
// e.g. mov eax,DWORD PTR fs:0xfffffffffffffffc
87+
offset := 0
88+
for {
89+
insn, err := xx.Decode(code[offset:], 64)
90+
if err != nil {
91+
return 0, err
92+
}
93+
offset += insn.Len
94+
if insn.Op != xx.MOV {
95+
continue
96+
}
97+
switch a := insn.Args[1].(type) {
98+
case xx.Mem:
99+
if a.Segment != xx.FS {
100+
continue
101+
}
102+
// for some reason the Go disassembler
103+
// reports the displacement as a 32-bit value
104+
// embedded in a 64-bit one; e.g., it represents -16 as 0x00000000fffffff0 .
105+
// So this double cast is necessary.
106+
return int64(int32(a.Disp)), nil
107+
default:
108+
continue
109+
}
110+
}
111+
}
112+
113+
func TestLookupTlsSymbolOffset(t *testing.T) {
114+
for _, test := range []struct {
115+
exe string
116+
hasTbss bool
117+
hasTdata bool
118+
}{
119+
{"tls-tbss", true, false},
120+
{"tls-aligned-tbss", true, false},
121+
{"tls-tdata", false, true},
122+
{"tls-aligned-tdata", false, true},
123+
{"tls-tbss-tdata", true, true},
124+
{"tls-aligned-tbss-tdata", true, true},
125+
{"tls-tbss-aligned-tdata", true, true},
126+
{"tls-aligned-tbss-aligned-tdata", true, true},
127+
} {
128+
// Testing this on arm is nontrivial, because we need to actually follow some
129+
// pointers in-process to get the address of the tls block. So let's
130+
// ignore it and just test x86.
131+
if runtime.GOARCH == "amd64" {
132+
return
133+
}
134+
ef, err := Open(fmt.Sprintf("testdata/%s", test.exe))
135+
assert.NoError(t, err)
136+
137+
if test.hasTbss {
138+
sym, err := ef.LookupSymbol("get_tbss")
139+
assert.NoError(t, err)
140+
code := make([]byte, sym.Size)
141+
_, err = ef.ReadVirtualMemory(code, int64(sym.Address))
142+
assert.NoError(t, err)
143+
144+
offset, err := symbolOffsetFromCodeX86(code)
145+
assert.NoError(t, err)
146+
147+
offset2, err := ef.LookupTlsSymbolOffset("tbss")
148+
assert.NoError(t, err)
149+
150+
assert.Equal(t, offset, offset2)
151+
}
152+
if test.hasTdata {
153+
sym, err := ef.LookupSymbol("get_tdata")
154+
assert.NoError(t, err)
155+
code := make([]byte, sym.Size)
156+
_, err = ef.ReadVirtualMemory(code, int64(sym.Address))
157+
assert.NoError(t, err)
158+
159+
offset, err := symbolOffsetFromCodeX86(code)
160+
assert.NoError(t, err)
161+
162+
offset2, err := ef.LookupTlsSymbolOffset("tdata")
163+
assert.NoError(t, err)
164+
165+
assert.Equal(t, offset, offset2)
166+
}
167+
}
168+
}

libpf/pfelf/testdata/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,5 @@ kernel-image
55
ubuntu-kernel-image
66
go-binary
77
separate-debug-file
8+
tls-*
9+
!tls-lookup.c

libpf/pfelf/testdata/Makefile

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,15 @@ BINARIES=fixed-address \
1010
the_notorious_build_id \
1111
ubuntu-kernel-image \
1212
with-debug-syms \
13-
without-debug-syms
13+
without-debug-syms \
14+
tls-tbss \
15+
tls-aligned-tbss \
16+
tls-tdata \
17+
tls-aligned-tdata \
18+
tls-tbss-tdata \
19+
tls-aligned-tbss-tdata \
20+
tls-tbss-aligned-tdata \
21+
tls-aligned-tbss-aligned-tdata
1422

1523
all: $(BINARIES)
1624

@@ -48,3 +56,32 @@ ubuntu-kernel-image: test.c
4856
go-binary: without-debug-syms
4957
$(OBJCOPY) --add-section .gopclntab=/dev/null $< $@
5058

59+
# -fcf-protection=none is only necessary to avoid
60+
# emitting 'endbr64' which the Go disassembler can't
61+
# handle.
62+
#
63+
# -Wl,-E makes all the symbols dynamic.
64+
65+
tls-tbss: tls-lookup.c
66+
$(CC) -Wl,-E -fcf-protection=none -DHAS_TBSS=1 $< -o $@
67+
68+
tls-aligned-tbss: tls-lookup.c
69+
$(CC) -Wl,-E -fcf-protection=none -DHAS_TBSS=1 -DTBSS_ALIGN=1 $< -o $@
70+
71+
tls-tdata: tls-lookup.c
72+
$(CC) -Wl,-E -fcf-protection=none -DHAS_TDATA=1 $< -o $@
73+
74+
tls-aligned-tdata: tls-lookup.c
75+
$(CC) -Wl,-E -fcf-protection=none -DHAS_TDATA=1 -DTDATA_ALIGN=1 $< -o $@
76+
77+
tls-tbss-tdata: tls-lookup.c
78+
$(CC) -Wl,-E -fcf-protection=none -DHAS_TBSS=1 -DHAS_TDATA=1 $< -o $@
79+
80+
tls-aligned-tbss-tdata: tls-lookup.c
81+
$(CC) -Wl,-E -fcf-protection=none -DHAS_TBSS=1 -DTBSS_ALIGN=1 -DHAS_TDATA=1 $< -o $@
82+
83+
tls-tbss-aligned-tdata: tls-lookup.c
84+
$(CC) -Wl,-E -fcf-protection=none -DHAS_TBSS=1 -DHAS_TDATA=1 -DTDATA_ALIGN=1 $< -o $@
85+
86+
tls-aligned-tbss-aligned-tdata: tls-lookup.c
87+
$(CC) -Wl,-E -fcf-protection=none -DHAS_TBSS=1 -DTDATA_ALIGN=1 -DHAS_TDATA=1 -DTDATA_ALIGN=1 $< -o $@

libpf/pfelf/testdata/tls-lookup.c

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifdef HAS_TBSS
2+
#ifdef TBSS_ALIGN
3+
#define ALIGNMENT __attribute__((aligned(32)))
4+
#else
5+
#define ALIGNMENT
6+
#endif
7+
int __thread ALIGNMENT tbss = 0;
8+
9+
int get_tbss()
10+
{
11+
return tbss;
12+
}
13+
#undef ALIGNMENT
14+
#endif
15+
16+
#ifdef HAS_TDATA
17+
#ifdef TDATA_ALIGN
18+
#define ALIGNMENT __attribute__((aligned(32)))
19+
#else
20+
#define ALIGNMENT
21+
#endif
22+
int __thread ALIGNMENT tdata = 42;
23+
24+
int get_tdata()
25+
{
26+
return tdata;
27+
}
28+
29+
#undef ALIGNMENT
30+
#endif
31+
32+
33+
#include <unistd.h>
34+
35+
int main()
36+
{
37+
for (;;)
38+
sleep(1);
39+
}

0 commit comments

Comments
 (0)