Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion pkg/aflow/tool/codesearcher/codesearcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ For example, how a function works, what precondition error checks it has, etc.
aflow.NewFuncTool("codesearch-find-references", findReferences, `
Tool finds and lists all references to (uses of) the given entity.
Entity can be function, struct, or global variable.
If can be used to find all calls or other uses of the given function.
If can be used to find all calls or other uses of the given function,
definition of the given struct/union/enum,
or all reads/writes of the given struct/union field.
To find field references use 'struct_name::field_name' syntax.
`),
}

Expand Down
12 changes: 9 additions & 3 deletions pkg/codesearch/codesearch.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,14 @@ type ReferenceInfo struct {

func (index *Index) FindReferences(contextFile, name, srcPrefix string, contextLines, outputLimit int) (
[]ReferenceInfo, int, error) {
// Just in case LLM decides to reference structs/fields with the tag.
name = strings.TrimSpace(strings.TrimPrefix(strings.TrimPrefix(strings.TrimSpace(name),
"struct "), "union "))
// We don't export each field as a separate definition,
// so we do just name-based match for them.
isField := strings.Contains(name, "::")
target := index.findDefinition(contextFile, name)
if target == nil {
if target == nil && !isField {
return nil, 0, aflow.BadCallError("requested entity does not exist")
}
if srcPrefix != "" {
Expand All @@ -278,8 +284,8 @@ func (index *Index) FindReferences(contextFile, name, srcPrefix string, contextL
// the target is a non-static 'foo' in some file,
// the reference is in another file and refers to a static 'foo'
// defined in that file (which is not the target 'foo').
if ref.EntityKind != target.Kind || ref.Name != target.Name ||
target.IsStatic && target.Body.File != def.Body.File {
if ref.Name != name || !isField && (ref.EntityKind != target.Kind ||
target.IsStatic && target.Body.File != def.Body.File) {
continue
}
totalCount++
Expand Down
4 changes: 2 additions & 2 deletions pkg/codesearch/codesearch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ func testCommand(t *testing.T, index *Index, covered map[string]bool, file strin
cmd := fields[0]
var args []string
for _, arg := range fields[1:] {
if arg == `""` {
arg = ""
if len(arg) >= 2 && arg[0] == '"' && arg[len(arg)-1] == '"' {
arg = arg[1 : len(arg)-1]
}
args = append(args, arg)
}
Expand Down
6 changes: 6 additions & 0 deletions pkg/codesearch/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ const (
EntityKindMacro
EntityKindEnum
EntityKindTypedef
EntityKindField
entityKindLast
)

Expand All @@ -68,6 +69,7 @@ var entityKindNames = [...]string{
EntityKindMacro: "macro",
EntityKindEnum: "enum",
EntityKindTypedef: "typedef",
EntityKindField: "field",
}

var entityKindBytes = func() [entityKindLast][]byte {
Expand Down Expand Up @@ -103,13 +105,17 @@ const (
refKindInvalid RefKind = iota
RefKindUses
RefKindCall
RefKindRead
RefKindWrite
RefKindTakesAddr
refKindLast
)

var refKindNames = [...]string{
RefKindUses: "uses",
RefKindCall: "calls",
RefKindRead: "reads",
RefKindWrite: "writes",
RefKindTakesAddr: "takes-address-of",
}

Expand Down
3 changes: 2 additions & 1 deletion pkg/codesearch/testdata/query-def-source-struct7
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ union some_union is defined in source0.h:
40: union some_union {
41: int x;
42: void* p;
43: };
43: struct some_struct s;
44: };
8 changes: 4 additions & 4 deletions pkg/codesearch/testdata/query-def-source-struct8
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ def-source source0.c some_enum yes

enum some_enum is defined in source0.h:

45: enum some_enum {
46: enum_foo = 1,
47: enum_bar = 2,
48: };
46: enum some_enum {
47: enum_foo = 1,
48: enum_bar = 2,
49: };
2 changes: 1 addition & 1 deletion pkg/codesearch/testdata/query-def-source-struct9
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@ def-source source0.c some_enum_t yes

typedef some_enum_t is defined in source0.h:

50: typedef enum some_enum some_enum_t;
51: typedef enum some_enum some_enum_t;
1 change: 1 addition & 0 deletions pkg/codesearch/testdata/query-file-index-source
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ file-index source0.c
file source0.c defines the following entities:

function close
function field_refs
function func_accepting_a_struct
function function_with_comment_in_header
function function_with_quotes_in_type
Expand Down
34 changes: 34 additions & 0 deletions pkg/codesearch/testdata/query-find-references-field0
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
find-references source0.c some_struct::x "" 1 10

some_struct::x has 5 references:

function field_refs writes it at source0.c:41
40: {
41: p->x = p->y;
42: *(&p->x) = 1;


function field_refs takes-address-of it at source0.c:42
41: p->x = p->y;
42: *(&p->x) = 1;
43: u->p = 0;


function field_refs writes it at source0.c:44
43: u->p = 0;
44: u->s.x = 2;
45: return p->x;


function field_refs reads it at source0.c:45
44: u->s.x = 2;
45: return p->x;
46: }


function func_accepting_a_struct reads it at source0.c:31
30: {
31: return ((some_struct_t*)p)->x +
32: ((union some_union*)p)->x;


10 changes: 10 additions & 0 deletions pkg/codesearch/testdata/query-find-references-field1
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
find-references source0.c some_struct::y "" 1 10

some_struct::y has 1 references:

function field_refs reads it at source0.c:41
40: {
41: p->x = p->y;
42: *(&p->x) = 1;


10 changes: 10 additions & 0 deletions pkg/codesearch/testdata/query-find-references-field2
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
find-references source0.c some_union::p "" 1 10

some_union::p has 1 references:

function field_refs writes it at source0.c:43
42: *(&p->x) = 1;
43: u->p = 0;
44: u->s.x = 2;


7 changes: 6 additions & 1 deletion pkg/codesearch/testdata/query-find-references-struct
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
find-references source0.c some_struct "" 1 10

some_struct has 2 references:
some_struct has 3 references:

function field_refs uses it at source0.c:39
39: int field_refs(struct some_struct* p, union some_union* u)
40: {


function func_accepting_a_struct uses it at source0.c:29
29: int func_accepting_a_struct(struct some_struct* p)
Expand Down
9 changes: 9 additions & 0 deletions pkg/codesearch/testdata/source0.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,12 @@ int func_accepting_a_struct(struct some_struct* p)
void function_with_quotes_in_type(void __attribute__((btf_type_tag("user"))) *)
{
}

int field_refs(struct some_struct* p, union some_union* u)
{
p->x = p->y;
*(&p->x) = 1;
u->p = 0;
u->s.x = 2;
return p->x;
}
89 changes: 84 additions & 5 deletions pkg/codesearch/testdata/source0.c.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,73 @@
},
"comment": {}
},
{
"name": "field_refs",
"type": "int (struct some_struct *, union some_union *)",
"kind": "function",
"body": {
"file": "source0.c",
"start_line": 39,
"end_line": 46
},
"comment": {},
"refs": [
{
"name": "some_struct",
"kind": "uses",
"entity_kind": "struct",
"line": 39
},
{
"name": "some_union",
"kind": "uses",
"entity_kind": "union",
"line": 39
},
{
"name": "some_struct::x",
"kind": "writes",
"entity_kind": "field",
"line": 41
},
{
"name": "some_struct::y",
"kind": "reads",
"entity_kind": "field",
"line": 41
},
{
"name": "some_struct::x",
"kind": "takes-address-of",
"entity_kind": "field",
"line": 42
},
{
"name": "some_union::p",
"kind": "writes",
"entity_kind": "field",
"line": 43
},
{
"name": "some_struct::x",
"kind": "writes",
"entity_kind": "field",
"line": 44
},
{
"name": "some_union::s",
"kind": "reads",
"entity_kind": "field",
"line": 44
},
{
"name": "some_struct::x",
"kind": "reads",
"entity_kind": "field",
"line": 45
}
]
},
{
"name": "func_accepting_a_struct",
"type": "int (struct some_struct *)",
Expand All @@ -28,6 +95,12 @@
"entity_kind": "struct",
"line": 29
},
{
"name": "some_struct::x",
"kind": "reads",
"entity_kind": "field",
"line": 31
},
{
"name": "some_struct_t",
"kind": "uses",
Expand All @@ -40,6 +113,12 @@
"entity_kind": "struct",
"line": 31
},
{
"name": "some_union::x",
"kind": "reads",
"entity_kind": "field",
"line": 32
},
{
"name": "some_union",
"kind": "uses",
Expand Down Expand Up @@ -155,7 +234,7 @@
"body": {
"file": "source0.h",
"start_line": 40,
"end_line": 43
"end_line": 44
},
"comment": {}
},
Expand All @@ -164,8 +243,8 @@
"kind": "enum",
"body": {
"file": "source0.h",
"start_line": 45,
"end_line": 48
"start_line": 46,
"end_line": 49
},
"comment": {}
},
Expand All @@ -184,8 +263,8 @@
"kind": "typedef",
"body": {
"file": "source0.h",
"start_line": 50,
"end_line": 50
"start_line": 51,
"end_line": 51
},
"comment": {}
},
Expand Down
1 change: 1 addition & 0 deletions pkg/codesearch/testdata/source0.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ typedef struct another_struct {
union some_union {
int x;
void* p;
struct some_struct s;
};

enum some_enum {
Expand Down
Loading
Loading