Skip to content

Commit 6178ec4

Browse files
authored
fix: create fallback symbols for mappings without BuildIDs (#4527)
* fix: create fallback symbols for mappings without BuildIDs
1 parent d31fcc1 commit 6178ec4

File tree

2 files changed

+37
-21
lines changed

2 files changed

+37
-21
lines changed

pkg/symbolizer/symbolizer.go

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,7 @@ func (s *Symbolizer) SymbolizePprof(ctx context.Context, profile *googlev1.Profi
9999
return fmt.Errorf("extract build ID: %w", err)
100100
}
101101

102-
if buildID == "" {
103-
continue
104-
}
105-
106102
req := s.createSymbolizationRequest(binaryName, buildID, locations)
107-
108103
s.symbolize(ctx, &req)
109104

110105
for i, loc := range locations {
@@ -247,33 +242,39 @@ func (s *Symbolizer) updateAllSymbolsInProfile(
247242
}
248243

249244
func (s *Symbolizer) symbolize(ctx context.Context, req *request) {
250-
var table *lidia.Table
251-
var err error
245+
if req.buildID == "" {
246+
s.metrics.debugSymbolResolutionErrors.WithLabelValues("empty_build_id").Inc()
247+
s.setFallbackSymbols(req)
248+
return
249+
}
252250

253251
lidiaBytes, err := s.getLidiaBytes(ctx, req.buildID)
254252
if err != nil {
255253
level.Warn(s.logger).Log("msg", "Failed to get debug info", "buildID", req.buildID, "err", err)
256-
for _, loc := range req.locations {
257-
loc.lines = s.createNotFoundSymbols(req.binaryName, loc)
258-
}
254+
s.setFallbackSymbols(req)
259255
return
260256
}
261257

262258
lidiaReader := NewReaderAtCloser(lidiaBytes)
263-
table, err = lidia.OpenReader(lidiaReader, lidia.WithCRC())
259+
table, err := lidia.OpenReader(lidiaReader, lidia.WithCRC())
264260
if err != nil {
265261
s.metrics.debugSymbolResolutionErrors.WithLabelValues("lidia_error").Inc()
266262
level.Warn(s.logger).Log("msg", "Failed to open Lidia file", "err", err)
267-
for _, loc := range req.locations {
268-
loc.lines = s.createNotFoundSymbols(req.binaryName, loc)
269-
}
263+
s.setFallbackSymbols(req)
270264
return
271265
}
272266
defer table.Close()
273267

274268
s.symbolizeWithTable(table, req)
275269
}
276270

271+
// setFallbackSymbols sets fallback symbols for all locations in the request
272+
func (s *Symbolizer) setFallbackSymbols(req *request) {
273+
for _, loc := range req.locations {
274+
loc.lines = s.createFallbackSymbol(req.binaryName, loc)
275+
}
276+
}
277+
277278
func (s *Symbolizer) symbolizeWithTable(table *lidia.Table, req *request) {
278279
var framesBuf []lidia.SourceInfoFrame
279280

@@ -285,12 +286,12 @@ func (s *Symbolizer) symbolizeWithTable(table *lidia.Table, req *request) {
285286
for _, loc := range req.locations {
286287
frames, err := table.Lookup(framesBuf, loc.address)
287288
if err != nil {
288-
loc.lines = s.createNotFoundSymbols(req.binaryName, loc)
289+
loc.lines = s.createFallbackSymbol(req.binaryName, loc)
289290
continue
290291
}
291292

292293
if len(frames) == 0 {
293-
loc.lines = s.createNotFoundSymbols(req.binaryName, loc)
294+
loc.lines = s.createFallbackSymbol(req.binaryName, loc)
294295
continue
295296
}
296297

@@ -406,7 +407,7 @@ func (s *Symbolizer) processELFData(data []byte) (lidiaData []byte, err error) {
406407
return memBuffer.Bytes(), nil
407408
}
408409

409-
func (s *Symbolizer) createNotFoundSymbols(binaryName string, loc *location) []lidia.SourceInfoFrame {
410+
func (s *Symbolizer) createFallbackSymbol(binaryName string, loc *location) []lidia.SourceInfoFrame {
410411
prefix := "unknown"
411412
if binaryName != "" {
412413
prefix = binaryName

pkg/symbolizer/symbolizer_test.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,16 +96,31 @@ func TestSymbolizePprof(t *testing.T) {
9696
},
9797
},
9898
{
99-
name: "empty build ID",
99+
name: "empty build ID creates fallback symbols",
100100
profile: &googlev1.Profile{
101101
Mapping: []*googlev1.Mapping{{
102-
BuildId: 1,
102+
Id: 1,
103+
Filename: 2,
104+
BuildId: 1,
103105
}},
104-
StringTable: []string{"", ""},
106+
Location: []*googlev1.Location{
107+
{Id: 1, MappingId: 1, Address: 0xa4c},
108+
{Id: 2, MappingId: 1, Address: 0x9f0},
109+
},
110+
StringTable: []string{"", "", "linux-vdso.1.so"},
105111
},
106112
setupMock: func(mockClient *mocksymbolizer.MockDebuginfodClient, mockBucket *mockobjstore.MockBucket) {},
107113
validate: func(t *testing.T, p *googlev1.Profile) {
108-
require.False(t, p.Mapping[0].HasFunctions)
114+
require.True(t, p.Mapping[0].HasFunctions)
115+
require.Len(t, p.Location[0].Line, 1)
116+
require.Len(t, p.Location[1].Line, 1)
117+
118+
fn1 := p.StringTable[p.Function[p.Location[0].Line[0].FunctionId-1].Name]
119+
fn2 := p.StringTable[p.Function[p.Location[1].Line[0].FunctionId-1].Name]
120+
require.Contains(t, fn1, "linux-vdso.1.so")
121+
require.Contains(t, fn1, "0xa4c")
122+
require.Contains(t, fn2, "linux-vdso.1.so")
123+
require.Contains(t, fn2, "0x9f0")
109124
},
110125
},
111126
{

0 commit comments

Comments
 (0)