Skip to content

Commit d17fdd9

Browse files
authored
dyninst/irgen: name the unsupported operation in condition errors (#54601)
### What does this PR do? When a logpoint's condition uses an operation the Go debugger doesn't implement, the resulting error now names that operation. Also an unsupported operation can appear in two places, on its own or nested inside a comparison. Both now report the operation by name. ### Motivation A logpoint was created in staging against a Go service with a condition using `startsWith`, which Go does not implement. It never activated. The person debugging was told the target had passed validation but the service had not applied the logpoint. ### Describe how you validated your changes Added eight test probes covering every operation the shared expression language accepts but Go does not implement, in both positions an operation can occupy, and confirmed in the regenerated snapshots that each reports its own name. Ran the generator test suite and the eBPF integration test for the affected test program, to confirm the added failing probes don't disturb the probes that do attach. Co-authored-by: grant.seltzerrichman <grant.seltzerrichman@datadoghq.com>
1 parent 83cb817 commit d17fdd9

10 files changed

Lines changed: 1213 additions & 11 deletions

pkg/dyninst/irgen/irgen.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -891,7 +891,7 @@ func analyzeCondition(
891891
if len(leaves) == 0 {
892892
return nil, ir.Issue{
893893
Kind: ir.IssueKindUnsupportedFeature,
894-
Message: fmt.Sprintf("unsupported condition expression type: %T", condExpr),
894+
Message: conditionUnsupportedMessage(condExpr),
895895
}
896896
}
897897
// Validate every leaf is a supported shape first so error messages
@@ -901,7 +901,7 @@ func analyzeCondition(
901901
if !ok {
902902
return nil, ir.Issue{
903903
Kind: ir.IssueKindUnsupportedFeature,
904-
Message: fmt.Sprintf("unsupported condition expression type: %T", leaf),
904+
Message: conditionUnsupportedMessage(leaf),
905905
}
906906
}
907907
// A condition leaf's LHS must be a variable-derived path
@@ -1100,6 +1100,8 @@ func checkConditionLHS(expr exprlang.Expr) error {
11001100
)
11011101
case *exprlang.LiteralExpr:
11021102
return errors.New("condition leaf LHS may not be a literal")
1103+
case *exprlang.UnsupportedExpr:
1104+
return errors.New(conditionUnsupportedMessage(e))
11031105
default:
11041106
return fmt.Errorf("unsupported condition leaf LHS type: %T", expr)
11051107
}
@@ -1162,6 +1164,14 @@ func conditionLeafSubExpr(leaf exprlang.Expr) (exprlang.Expr, bool) {
11621164
}
11631165
}
11641166

1167+
func conditionUnsupportedMessage(e exprlang.Expr) string {
1168+
if unsupported, ok := e.(*exprlang.UnsupportedExpr); ok {
1169+
return "unsupported condition operation: " + unsupported.Operation
1170+
}
1171+
// we don't expect to reach this return
1172+
return fmt.Sprintf("unsupported condition expression type: %T", e)
1173+
}
1174+
11651175
// rewriteReturnRefs rewrites every @return reference in expr to reference
11661176
// a concrete return variable.
11671177
//
@@ -4422,7 +4432,7 @@ func exploreTypesForExpressions(
44224432
if !ok {
44234433
ap.conditionIssue = ir.Issue{
44244434
Kind: ir.IssueKindUnsupportedFeature,
4425-
Message: fmt.Sprintf("unsupported condition expression type: %T", leaf),
4435+
Message: conditionUnsupportedMessage(leaf),
44264436
}
44274437
ap.condition = nil
44284438
break

pkg/dyninst/irgen/testdata/snapshot/simple.arch=amd64,toolchain=go1.23.11.yaml

Lines changed: 137 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26114,7 +26114,7 @@ Issues:
2611426114
captureSnapshot: true
2611526115
issue:
2611626116
Kind: 3
26117-
Message: 'unsupported condition expression type: *exprlang.UnsupportedExpr'
26117+
Message: 'unsupported condition operation: not_a_valid_op'
2611826118
- probe_definition:
2611926119
id: condErr_bare_ref
2612026120
version: 0
@@ -26130,6 +26130,57 @@ Issues:
2613026130
issue:
2613126131
Kind: 3
2613226132
Message: 'unsupported condition expression type: *exprlang.RefExpr'
26133+
- probe_definition:
26134+
id: condErr_count_operand
26135+
version: 0
26136+
type: LOG_PROBE
26137+
where: {methodName: main.condString}
26138+
tags: ['issue:UnsupportedFeature']
26139+
when:
26140+
dsl: count(tag) == 3
26141+
json: {eq: [{count: {ref: tag}}, 3]}
26142+
capture: {maxReferenceDepth: 1}
26143+
sampling: {snapshotsPerSecond: 10}
26144+
template: ""
26145+
segments: []
26146+
captureSnapshot: true
26147+
issue:
26148+
Kind: 3
26149+
Message: 'unsupported condition operation: count'
26150+
- probe_definition:
26151+
id: condErr_endsWith
26152+
version: 0
26153+
type: LOG_PROBE
26154+
where: {methodName: main.condString}
26155+
tags: ['issue:UnsupportedFeature']
26156+
when:
26157+
dsl: endsWith(tag, "post")
26158+
json: {endsWith: [{ref: tag}, post]}
26159+
capture: {maxReferenceDepth: 1}
26160+
sampling: {snapshotsPerSecond: 10}
26161+
template: ""
26162+
segments: []
26163+
captureSnapshot: true
26164+
issue:
26165+
Kind: 3
26166+
Message: 'unsupported condition operation: endsWith'
26167+
- probe_definition:
26168+
id: condErr_instanceof
26169+
version: 0
26170+
type: LOG_PROBE
26171+
where: {methodName: main.condString}
26172+
tags: ['issue:UnsupportedFeature']
26173+
when:
26174+
dsl: tag instanceof "string"
26175+
json: {instanceof: [{ref: tag}, string]}
26176+
capture: {maxReferenceDepth: 1}
26177+
sampling: {snapshotsPerSecond: 10}
26178+
template: ""
26179+
segments: []
26180+
captureSnapshot: true
26181+
issue:
26182+
Kind: 3
26183+
Message: 'unsupported condition operation: instanceof'
2613326184
- probe_definition:
2613426185
id: condErr_int8_overflow
2613526186
version: 0
@@ -26145,6 +26196,23 @@ Issues:
2614526196
issue:
2614626197
Kind: 8
2614726198
Message: 'failed to resolve condition: condition: literal 128 out of range for int8 (8-bit)'
26199+
- probe_definition:
26200+
id: condErr_isDefined
26201+
version: 0
26202+
type: LOG_PROBE
26203+
where: {methodName: main.condString}
26204+
tags: ['issue:UnsupportedFeature']
26205+
when:
26206+
dsl: isDefined(tag)
26207+
json: {isDefined: {ref: tag}}
26208+
capture: {maxReferenceDepth: 1}
26209+
sampling: {snapshotsPerSecond: 10}
26210+
template: ""
26211+
segments: []
26212+
captureSnapshot: true
26213+
issue:
26214+
Kind: 3
26215+
Message: 'unsupported condition operation: isDefined'
2614826216
- probe_definition:
2614926217
id: condErr_map
2615026218
version: 0
@@ -26160,6 +26228,40 @@ Issues:
2616026228
issue:
2616126229
Kind: 8
2616226230
Message: 'failed to resolve condition: Eq: type map[string]int can only be compared to null'
26231+
- probe_definition:
26232+
id: condErr_matches
26233+
version: 0
26234+
type: LOG_PROBE
26235+
where: {methodName: main.condString}
26236+
tags: ['issue:UnsupportedFeature']
26237+
when:
26238+
dsl: matches(tag, "[0-9]+")
26239+
json: {matches: [{ref: tag}, '[0-9]+']}
26240+
capture: {maxReferenceDepth: 1}
26241+
sampling: {snapshotsPerSecond: 10}
26242+
template: ""
26243+
segments: []
26244+
captureSnapshot: true
26245+
issue:
26246+
Kind: 3
26247+
Message: 'unsupported condition operation: matches'
26248+
- probe_definition:
26249+
id: condErr_not_startsWith
26250+
version: 0
26251+
type: LOG_PROBE
26252+
where: {methodName: main.condString}
26253+
tags: ['issue:UnsupportedFeature']
26254+
when:
26255+
dsl: '!startsWith(tag, "pre")'
26256+
json: {not: {startsWith: [{ref: tag}, pre]}}
26257+
capture: {maxReferenceDepth: 1}
26258+
sampling: {snapshotsPerSecond: 10}
26259+
template: ""
26260+
segments: []
26261+
captureSnapshot: true
26262+
issue:
26263+
Kind: 3
26264+
Message: 'unsupported condition operation: startsWith'
2616326265
- probe_definition:
2616426266
id: condErr_rhs_ref
2616526267
version: 0
@@ -26190,6 +26292,23 @@ Issues:
2619026292
issue:
2619126293
Kind: 8
2619226294
Message: 'failed to resolve condition: Eq: type []int can only be compared to null'
26295+
- probe_definition:
26296+
id: condErr_startsWith
26297+
version: 0
26298+
type: LOG_PROBE
26299+
where: {methodName: main.condString}
26300+
tags: ['issue:UnsupportedFeature']
26301+
when:
26302+
dsl: startsWith(tag, "pre")
26303+
json: {startsWith: [{ref: tag}, pre]}
26304+
capture: {maxReferenceDepth: 1}
26305+
sampling: {snapshotsPerSecond: 10}
26306+
template: ""
26307+
segments: []
26308+
captureSnapshot: true
26309+
issue:
26310+
Kind: 3
26311+
Message: 'unsupported condition operation: startsWith'
2619326312
- probe_definition:
2619426313
id: condErr_string_vs_int
2619526314
version: 0
@@ -26220,6 +26339,23 @@ Issues:
2622026339
issue:
2622126340
Kind: 8
2622226341
Message: 'failed to resolve condition: Eq: unsupported LHS type *ir.StructureType for comparison'
26342+
- probe_definition:
26343+
id: condErr_substring_operand
26344+
version: 0
26345+
type: LOG_PROBE
26346+
where: {methodName: main.condString}
26347+
tags: ['issue:UnsupportedFeature']
26348+
when:
26349+
dsl: substring(tag, 0, 3) == "abc"
26350+
json: {eq: [{substring: [{ref: tag}, 0, 3]}, abc]}
26351+
capture: {maxReferenceDepth: 1}
26352+
sampling: {snapshotsPerSecond: 10}
26353+
template: ""
26354+
segments: []
26355+
captureSnapshot: true
26356+
issue:
26357+
Kind: 3
26358+
Message: 'unsupported condition operation: substring'
2622326359
- probe_definition:
2622426360
id: condErr_uint32_negative
2622526361
version: 0

0 commit comments

Comments
 (0)