怎样使用Joern生成Program Dependence Graph并和源码中的行号对应起来

这个问题我已经想搞清楚很久了,不得不说,很多开发工具(或者说开源项目)的人,脑子都是一团浆糊,虽然标榜自己可用于科研,但是完全不知道科研人员的需求在哪,写出来的文档也是乱七八糟。

按照以前的Joern的文档,我根本没搞清楚怎么生成PDG,现在算是清楚了:https://docs.joern.io/exporting/

我们以一个别人论文里的例子来说明,例如我要生成下面这个Example.c文件的PDG:

int main(int argc, char **argv)
{
    char *items[] = {"boat", "car", "truck", "train"};
    int index = Untrusted();
    printf("You selected %s\n", items[index-1]);
    int upbound = sizeof(items) / sizeof(items[0]);
    printf("Last item %s\n", items[upbound - 1]);
}

这个文件是没法编译的,但是通过island grammar,Joern是可以分析它的,在安装好了Joern之后,我们运行:

./joern-parse Example.c
./joern-export --repr pdg --out Example

就可以生成一个Example的目录,并且在目录下面有0-pdg.dot,1-pdg.dot,2-pdg.dot这些文件,我们一般只关心第一个即可,可以看看这个文件长什么样:

digraph main {  
"1000100" [label = "(METHOD,main)" ]
"1000135" [label = "(METHOD_RETURN,int)" ]
"1000101" [label = "(PARAM,int argc)" ]
"1000102" [label = "(PARAM,char **argv)" ]
"1000105" [label = "(.assignment,*items[] = {\"boat\", \"car\", \"truck\", \"train\"})" ]
"1000108" [label = "(.assignment,index = Untrusted())" ]
"1000111" [label = "(printf,printf(\"You selected %s\n\", items[index-1]))" ]
"1000115" [label = "(.subtraction,index-1)" ]
"1000119" [label = "(.assignment,upbound = sizeof(items) / sizeof(items[0]))" ]
"1000121" [label = "(.division,sizeof(items) / sizeof(items[0]))" ]
"1000122" [label = "(.sizeOf,sizeof(items))" ]
"1000124" [label = "(.sizeOf,sizeof(items[0]))" ]
"1000128" [label = "(printf,printf(\"Last item %s\n\", items[upbound - 1]))" ]
"1000132" [label = "(.subtraction,upbound - 1)" ]
  "1000119" -> "1000135"  [ label = "DDG: sizeof(items) / sizeof(items[0])"] 
  "1000128" -> "1000135"  [ label = "DDG: items[upbound - 1]"] 
  "1000102" -> "1000135"  [ label = "DDG: argv"] 
  "1000124" -> "1000135"  [ label = "DDG: items[0]"] 
  "1000101" -> "1000135"  [ label = "DDG: argc"] 
  "1000111" -> "1000135"  [ label = "DDG: printf(\"You selected %s\n\", items[index-1])"] 
  "1000122" -> "1000135"  [ label = "DDG: items"] 
  "1000111" -> "1000135"  [ label = "DDG: items[index-1]"] 
  "1000128" -> "1000135"  [ label = "DDG: printf(\"Last item %s\n\", items[upbound - 1])"] 
  "1000108" -> "1000135"  [ label = "DDG: Untrusted()"] 
  "1000132" -> "1000135"  [ label = "DDG: upbound"] 
  "1000115" -> "1000135"  [ label = "DDG: index"] 
  "1000100" -> "1000101"  [ label = "DDG: "] 
  "1000100" -> "1000102"  [ label = "DDG: "] 
  "1000100" -> "1000105"  [ label = "DDG: "] 
  "1000100" -> "1000108"  [ label = "DDG: "] 
  "1000100" -> "1000111"  [ label = "DDG: "] 
  "1000105" -> "1000111"  [ label = "DDG: items"] 
  "1000108" -> "1000115"  [ label = "DDG: index"] 
  "1000100" -> "1000115"  [ label = "DDG: "] 
  "1000100" -> "1000119"  [ label = "DDG: "] 
  "1000100" -> "1000121"  [ label = "DDG: "] 
  "1000100" -> "1000122"  [ label = "DDG: "] 
  "1000100" -> "1000128"  [ label = "DDG: "] 
  "1000119" -> "1000132"  [ label = "DDG: upbound"] 
  "1000100" -> "1000132"  [ label = "DDG: "] 
}

如果我们运行:

dot -Tpng 0-pdg.dot -o 0-pdg.png

就可以生成下面这个图:

可以很明显地看到,这个图并不是以语句为节点单位的,而是更细粒度的类似于AST节点的node。但是,往往我们在分析源码的时候,需要和某一行对应起来(例如Diff是以一行作为单位的),那怎么办呢?抱歉,Joern的文档是不会给我们答案的。例如这里有人也提了这个问题:https://gitter.im/joern-code-analyzer/community

怎样使用Joern生成Program Dependence Graph并和源码中的行号对应起来_第1张图片

呵呵呵,但是并没有人回复他。所以得自己想想办法。

按照这里的介绍,我们是可以query所生成的CPG(Code Property Graph)的所有信息的:https://docs.joern.io/quickstart#querying-the-code-property-graph

例如我们可以通过:

cpg.method.name.l

来返回所分析代码中的所有function name,按道理说,看上面的0-pdg.dot文件,每一个节点都有一个唯一的编号,那我们应该能把其行号输出出来:

最方便起见,我们可以用:

cpg.all.l

可以看到是包含所有的节点行号的,但是似乎不太好分析,看到这里介绍:https://docs.joern.io/cpgql/reference-card#execution-directives

除了用.l之外,我们可以输出成Json,这样就好分析了(顺便吐槽一下这个.l,你前面都没简写,后面不能用个.list吗,非得用个.l,让人和.1傻傻分不清):

cpg.all.toJsonPretty |> "Json.txt"

如果我们要批量分析很多个源码文件呢,那显然用这种interactive的方式就不行了,我们需要借助于:https://docs.joern.io/interpreter

例如我们保存一个test.sc文件:

@main def exec() = {
   loadCpg("cpg.bin")
   cpg.all.toJsonPretty |> "Temp.json"
}

然后运行:

./joern --script test.sc

就可以将Json文件输出了:

[
  {
    "overlays":[
      "semanticcpg",
      "dataflowOss"
    ],
    "version":"0.1",
    "language":"C",
    "_label":"META_DATA",
    "id":1
  },
  {
    "name":"",
    "fullName":"",
    "id":2,
    "_label":"NAMESPACE_BLOCK",
    "order":1,
    "filename":""
  },
  {
    "name":"char *",
    "fullName":"char *",
    "typeDeclFullName":"char *",
    "id":100,
    "_label":"TYPE"
  },
  {
    "name":"char * *",
    "fullName":"char * *",
    "typeDeclFullName":"char * *",
    "id":101,
    "_label":"TYPE"
  },
  {
    "name":"char * [ ]",
    "fullName":"char * [ ]",
    "typeDeclFullName":"char * [ ]",
    "id":102,
    "_label":"TYPE"
  },
  {
    "name":"int",
    "fullName":"int",
    "typeDeclFullName":"int",
    "id":103,
    "_label":"TYPE"
  },
  {
    "name":"void",
    "fullName":"void",
    "typeDeclFullName":"void",
    "id":104,
    "_label":"TYPE"
  },
  {
    "name":"",
    "fullName":"/home/yu/bin/joern/Example.c:",
    "id":1000099,
    "_label":"NAMESPACE_BLOCK",
    "order":1,
    "filename":"/home/yu/bin/joern/Example.c"
  },
  {
    "name":"main",
    "astParentFullName":"",
    "columnNumberEnd":0,
    "fullName":"main",
    "signature":"int main (int,char * *)",
    "astParentType":"",
    "columnNumber":0,
    "lineNumberEnd":8,
    "_label":"METHOD",
    "code":"int main (int argc,char **argv)",
    "isExternal":false,
    "lineNumber":1,
    "id":1000100,
    "order":1,
    "filename":"/home/yu/bin/joern/Example.c"
  },
  {
    "name":"argc",
    "evaluationStrategy":"BY_VALUE",
    "code":"int argc",
    "typeFullName":"int",
    "columnNumber":9,
    "order":1,
    "_label":"METHOD_PARAMETER_IN",
    "lineNumber":1,
    "id":1000101
  },
  {
    "name":"argv",
    "evaluationStrategy":"BY_VALUE",
    "code":"char **argv",
    "typeFullName":"char * *",
    "columnNumber":19,
    "order":2,
    "_label":"METHOD_PARAMETER_IN",
    "lineNumber":1,
    "id":1000102
  },
  {
    "code":"",
    "typeFullName":"void",
    "columnNumber":0,
    "order":3,
    "_label":"BLOCK",
    "argumentIndex":3,
    "lineNumber":2,
    "id":1000103
  },
  {
    "name":"items",
    "typeFullName":"char * [ ]",
    "order":1,
    "_label":"LOCAL",
    "code":"items",
    "id":1000104
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".assignment",
    "signature":"TODO",
    "code":"*items[] = {\"boat\", \"car\", \"truck\", \"train\"}",
    "typeFullName":"",
    "columnNumber":9,
    "order":2,
    "methodFullName":".assignment",
    "_label":"CALL",
    "argumentIndex":2,
    "lineNumber":3,
    "id":1000105
  },
  {
    "name":"items",
    "code":"items",
    "typeFullName":"char * [ ]",
    "columnNumber":10,
    "order":1,
    "_label":"IDENTIFIER",
    "argumentIndex":1,
    "lineNumber":3,
    "id":1000106
  },
  {
    "name":"index",
    "typeFullName":"int",
    "order":3,
    "_label":"LOCAL",
    "code":"index",
    "id":1000107
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".assignment",
    "signature":"TODO",
    "code":"index = Untrusted()",
    "typeFullName":"",
    "columnNumber":8,
    "order":4,
    "methodFullName":".assignment",
    "_label":"CALL",
    "argumentIndex":4,
    "lineNumber":4,
    "id":1000108
  },
  {
    "name":"index",
    "code":"index",
    "typeFullName":"int",
    "columnNumber":8,
    "order":1,
    "_label":"IDENTIFIER",
    "argumentIndex":1,
    "lineNumber":4,
    "id":1000109
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":"Untrusted",
    "signature":"TODO",
    "code":"Untrusted()",
    "typeFullName":"",
    "columnNumber":16,
    "order":2,
    "methodFullName":"Untrusted",
    "_label":"CALL",
    "argumentIndex":2,
    "lineNumber":4,
    "id":1000110
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":"printf",
    "signature":"TODO",
    "code":"printf(\"You selected %s\\n\", items[index-1])",
    "typeFullName":"",
    "columnNumber":4,
    "order":5,
    "methodFullName":"printf",
    "_label":"CALL",
    "argumentIndex":5,
    "lineNumber":5,
    "id":1000111
  },
  {
    "code":"\"You selected %s\\n\"",
    "typeFullName":"char *",
    "columnNumber":11,
    "order":1,
    "_label":"LITERAL",
    "argumentIndex":1,
    "lineNumber":5,
    "id":1000112
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".indirectIndexAccess",
    "signature":"TODO",
    "code":"items[index-1]",
    "typeFullName":"",
    "columnNumber":32,
    "order":2,
    "methodFullName":".indirectIndexAccess",
    "_label":"CALL",
    "argumentIndex":2,
    "lineNumber":5,
    "id":1000113
  },
  {
    "name":"items",
    "code":"items",
    "typeFullName":"char * [ ]",
    "columnNumber":32,
    "order":1,
    "_label":"IDENTIFIER",
    "argumentIndex":1,
    "lineNumber":5,
    "id":1000114
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".subtraction",
    "signature":"TODO",
    "code":"index-1",
    "typeFullName":"",
    "columnNumber":38,
    "order":2,
    "methodFullName":".subtraction",
    "_label":"CALL",
    "argumentIndex":2,
    "lineNumber":5,
    "id":1000115
  },
  {
    "name":"index",
    "code":"index",
    "typeFullName":"int",
    "columnNumber":38,
    "order":1,
    "_label":"IDENTIFIER",
    "argumentIndex":1,
    "lineNumber":5,
    "id":1000116
  },
  {
    "code":"1",
    "typeFullName":"int",
    "columnNumber":44,
    "order":2,
    "_label":"LITERAL",
    "argumentIndex":2,
    "lineNumber":5,
    "id":1000117
  },
  {
    "name":"upbound",
    "typeFullName":"int",
    "order":6,
    "_label":"LOCAL",
    "code":"upbound",
    "id":1000118
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".assignment",
    "signature":"TODO",
    "code":"upbound = sizeof(items) / sizeof(items[0])",
    "typeFullName":"",
    "columnNumber":8,
    "order":7,
    "methodFullName":".assignment",
    "_label":"CALL",
    "argumentIndex":7,
    "lineNumber":6,
    "id":1000119
  },
  {
    "name":"upbound",
    "code":"upbound",
    "typeFullName":"int",
    "columnNumber":8,
    "order":1,
    "_label":"IDENTIFIER",
    "argumentIndex":1,
    "lineNumber":6,
    "id":1000120
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".division",
    "signature":"TODO",
    "code":"sizeof(items) / sizeof(items[0])",
    "typeFullName":"",
    "columnNumber":18,
    "order":2,
    "methodFullName":".division",
    "_label":"CALL",
    "argumentIndex":2,
    "lineNumber":6,
    "id":1000121
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".sizeOf",
    "signature":"TODO",
    "code":"sizeof(items)",
    "typeFullName":"",
    "columnNumber":18,
    "order":1,
    "methodFullName":".sizeOf",
    "_label":"CALL",
    "argumentIndex":1,
    "lineNumber":6,
    "id":1000122
  },
  {
    "name":"items",
    "code":"items",
    "typeFullName":"char * [ ]",
    "columnNumber":25,
    "order":1,
    "_label":"IDENTIFIER",
    "argumentIndex":1,
    "lineNumber":6,
    "id":1000123
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".sizeOf",
    "signature":"TODO",
    "code":"sizeof(items[0])",
    "typeFullName":"",
    "columnNumber":34,
    "order":2,
    "methodFullName":".sizeOf",
    "_label":"CALL",
    "argumentIndex":2,
    "lineNumber":6,
    "id":1000124
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".indirectIndexAccess",
    "signature":"TODO",
    "code":"items[0]",
    "typeFullName":"",
    "columnNumber":41,
    "order":1,
    "methodFullName":".indirectIndexAccess",
    "_label":"CALL",
    "argumentIndex":1,
    "lineNumber":6,
    "id":1000125
  },
  {
    "name":"items",
    "code":"items",
    "typeFullName":"char * [ ]",
    "columnNumber":41,
    "order":1,
    "_label":"IDENTIFIER",
    "argumentIndex":1,
    "lineNumber":6,
    "id":1000126
  },
  {
    "code":"0",
    "typeFullName":"int",
    "columnNumber":47,
    "order":2,
    "_label":"LITERAL",
    "argumentIndex":2,
    "lineNumber":6,
    "id":1000127
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":"printf",
    "signature":"TODO",
    "code":"printf(\"Last item %s\\n\", items[upbound - 1])",
    "typeFullName":"",
    "columnNumber":4,
    "order":8,
    "methodFullName":"printf",
    "_label":"CALL",
    "argumentIndex":8,
    "lineNumber":7,
    "id":1000128
  },
  {
    "code":"\"Last item %s\\n\"",
    "typeFullName":"char *",
    "columnNumber":11,
    "order":1,
    "_label":"LITERAL",
    "argumentIndex":1,
    "lineNumber":7,
    "id":1000129
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".indirectIndexAccess",
    "signature":"TODO",
    "code":"items[upbound - 1]",
    "typeFullName":"",
    "columnNumber":29,
    "order":2,
    "methodFullName":".indirectIndexAccess",
    "_label":"CALL",
    "argumentIndex":2,
    "lineNumber":7,
    "id":1000130
  },
  {
    "name":"items",
    "code":"items",
    "typeFullName":"char * [ ]",
    "columnNumber":29,
    "order":1,
    "_label":"IDENTIFIER",
    "argumentIndex":1,
    "lineNumber":7,
    "id":1000131
  },
  {
    "dispatchType":"STATIC_DISPATCH",
    "name":".subtraction",
    "signature":"TODO",
    "code":"upbound - 1",
    "typeFullName":"",
    "columnNumber":35,
    "order":2,
    "methodFullName":".subtraction",
    "_label":"CALL",
    "argumentIndex":2,
    "lineNumber":7,
    "id":1000132
  },
  {
    "name":"upbound",
    "code":"upbound",
    "typeFullName":"int",
    "columnNumber":35,
    "order":1,
    "_label":"IDENTIFIER",
    "argumentIndex":1,
    "lineNumber":7,
    "id":1000133
  },
  {
    "code":"1",
    "typeFullName":"int",
    "columnNumber":45,
    "order":2,
    "_label":"LITERAL",
    "argumentIndex":2,
    "lineNumber":7,
    "id":1000134
  },
  {
    "evaluationStrategy":"BY_VALUE",
    "code":"int",
    "typeFullName":"int",
    "columnNumber":0,
    "order":4,
    "_label":"METHOD_RETURN",
    "lineNumber":1,
    "id":1000135
  },
  {
    "inheritsFromTypeFullName":[
      
    ],
    "name":"char *",
    "astParentFullName":"",
    "fullName":"char *",
    "astParentType":"NAMESPACE_BLOCK",
    "isExternal":true,
    "id":1000137,
    "_label":"TYPE_DECL",
    "order":-1,
    "filename":""
  },
  {
    "inheritsFromTypeFullName":[
      
    ],
    "name":"char * *",
    "astParentFullName":"",
    "fullName":"char * *",
    "astParentType":"NAMESPACE_BLOCK",
    "isExternal":true,
    "id":1000138,
    "_label":"TYPE_DECL",
    "order":-1,
    "filename":""
  },
  {
    "inheritsFromTypeFullName":[
      
    ],
    "name":"char * [ ]",
    "astParentFullName":"",
    "fullName":"char * [ ]",
    "astParentType":"NAMESPACE_BLOCK",
    "isExternal":true,
    "id":1000139,
    "_label":"TYPE_DECL",
    "order":-1,
    "filename":""
  },
  {
    "inheritsFromTypeFullName":[
      
    ],
    "name":"int",
    "astParentFullName":"",
    "fullName":"int",
    "astParentType":"NAMESPACE_BLOCK",
    "isExternal":true,
    "id":1000140,
    "_label":"TYPE_DECL",
    "order":-1,
    "filename":""
  },
  {
    "inheritsFromTypeFullName":[
      
    ],
    "name":"void",
    "astParentFullName":"",
    "fullName":"void",
    "astParentType":"NAMESPACE_BLOCK",
    "isExternal":true,
    "id":1000141,
    "_label":"TYPE_DECL",
    "order":-1,
    "filename":""
  },
  {
    "name":"Untrusted",
    "astParentFullName":"",
    "fullName":"Untrusted",
    "signature":"TODO",
    "astParentType":"NAMESPACE_BLOCK",
    "_label":"METHOD",
    "code":"",
    "isExternal":true,
    "id":1000142,
    "order":0,
    "filename":""
  },
  {
    "evaluationStrategy":"BY_VALUE",
    "code":"RET",
    "typeFullName":"ANY",
    "order":-1,
    "_label":"METHOD_RETURN",
    "id":1000143
  },
  {
    "code":"",
    "typeFullName":"ANY",
    "order":1,
    "_label":"BLOCK",
    "argumentIndex":1,
    "id":1000144
  },
  {
    "name":".division",
    "astParentFullName":"",
    "fullName":".division",
    "signature":"TODO",
    "astParentType":"NAMESPACE_BLOCK",
    "_label":"METHOD",
    "code":"",
    "isExternal":true,
    "id":1000145,
    "order":0,
    "filename":""
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000146
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000147
  },
  {
    "evaluationStrategy":"BY_VALUE",
    "code":"RET",
    "typeFullName":"ANY",
    "order":-1,
    "_label":"METHOD_RETURN",
    "id":1000148
  },
  {
    "code":"",
    "typeFullName":"ANY",
    "order":1,
    "_label":"BLOCK",
    "argumentIndex":1,
    "id":1000149
  },
  {
    "name":".subtraction",
    "astParentFullName":"",
    "fullName":".subtraction",
    "signature":"TODO",
    "astParentType":"NAMESPACE_BLOCK",
    "_label":"METHOD",
    "code":"",
    "isExternal":true,
    "id":1000150,
    "order":0,
    "filename":""
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000151
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000152
  },
  {
    "evaluationStrategy":"BY_VALUE",
    "code":"RET",
    "typeFullName":"ANY",
    "order":-1,
    "_label":"METHOD_RETURN",
    "id":1000153
  },
  {
    "code":"",
    "typeFullName":"ANY",
    "order":1,
    "_label":"BLOCK",
    "argumentIndex":1,
    "id":1000154
  },
  {
    "name":".indirectIndexAccess",
    "astParentFullName":"",
    "fullName":".indirectIndexAccess",
    "signature":"TODO",
    "astParentType":"NAMESPACE_BLOCK",
    "_label":"METHOD",
    "code":"",
    "isExternal":true,
    "id":1000155,
    "order":0,
    "filename":""
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000156
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000157
  },
  {
    "evaluationStrategy":"BY_VALUE",
    "code":"RET",
    "typeFullName":"ANY",
    "order":-1,
    "_label":"METHOD_RETURN",
    "id":1000158
  },
  {
    "code":"",
    "typeFullName":"ANY",
    "order":1,
    "_label":"BLOCK",
    "argumentIndex":1,
    "id":1000159
  },
  {
    "name":"printf",
    "astParentFullName":"",
    "fullName":"printf",
    "signature":"TODO",
    "astParentType":"NAMESPACE_BLOCK",
    "_label":"METHOD",
    "code":"",
    "isExternal":true,
    "id":1000160,
    "order":0,
    "filename":""
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000161
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000162
  },
  {
    "evaluationStrategy":"BY_VALUE",
    "code":"RET",
    "typeFullName":"ANY",
    "order":-1,
    "_label":"METHOD_RETURN",
    "id":1000163
  },
  {
    "code":"",
    "typeFullName":"ANY",
    "order":1,
    "_label":"BLOCK",
    "argumentIndex":1,
    "id":1000164
  },
  {
    "name":".assignment",
    "astParentFullName":"",
    "fullName":".assignment",
    "signature":"TODO",
    "astParentType":"NAMESPACE_BLOCK",
    "_label":"METHOD",
    "code":"",
    "isExternal":true,
    "id":1000165,
    "order":0,
    "filename":""
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000166
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000167
  },
  {
    "evaluationStrategy":"BY_VALUE",
    "code":"RET",
    "typeFullName":"ANY",
    "order":-1,
    "_label":"METHOD_RETURN",
    "id":1000168
  },
  {
    "code":"",
    "typeFullName":"ANY",
    "order":1,
    "_label":"BLOCK",
    "argumentIndex":1,
    "id":1000169
  },
  {
    "name":".sizeOf",
    "astParentFullName":"",
    "fullName":".sizeOf",
    "signature":"TODO",
    "astParentType":"NAMESPACE_BLOCK",
    "_label":"METHOD",
    "code":"",
    "isExternal":true,
    "id":1000170,
    "order":0,
    "filename":""
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_IN",
    "id":1000171
  },
  {
    "evaluationStrategy":"BY_VALUE",
    "code":"RET",
    "typeFullName":"ANY",
    "order":-1,
    "_label":"METHOD_RETURN",
    "id":1000172
  },
  {
    "code":"",
    "typeFullName":"ANY",
    "order":1,
    "_label":"BLOCK",
    "argumentIndex":1,
    "id":1000173
  },
  {
    "name":"argc",
    "evaluationStrategy":"BY_VALUE",
    "code":"int argc",
    "typeFullName":"int",
    "columnNumber":9,
    "order":1,
    "_label":"METHOD_PARAMETER_OUT",
    "lineNumber":1,
    "id":1000174
  },
  {
    "name":"argv",
    "evaluationStrategy":"BY_VALUE",
    "code":"char **argv",
    "typeFullName":"char * *",
    "columnNumber":19,
    "order":2,
    "_label":"METHOD_PARAMETER_OUT",
    "lineNumber":1,
    "id":1000175
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000176
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000177
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000178
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000179
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000180
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000181
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000182
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000183
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000184
  },
  {
    "name":"p2",
    "evaluationStrategy":"BY_VALUE",
    "code":"p2",
    "typeFullName":"ANY",
    "order":2,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000185
  },
  {
    "name":"p1",
    "evaluationStrategy":"BY_VALUE",
    "code":"p1",
    "typeFullName":"ANY",
    "order":1,
    "_label":"METHOD_PARAMETER_OUT",
    "id":1000186
  },
  {
    "name":"",
    "order":0,
    "_label":"FILE",
    "id":1000187
  },
  {
    "name":"/home/yu/bin/joern/Example.c",
    "order":0,
    "_label":"FILE",
    "id":1000188
  },
  {
    "id":1000189,
    "name":"",
    "order":-1,
    "_label":"NAMESPACE"
  }
]

像这种记录:

  {
    "name":"argc",
    "evaluationStrategy":"BY_VALUE",
    "code":"int argc",
    "typeFullName":"int",
    "columnNumber":9,
    "order":1,
    "_label":"METHOD_PARAMETER_IN",
    "lineNumber":1,
    "id":1000101
  },

就包含了节点1000101的Line Number,通过这种命令行的方式,我们就可以实现批量处理了。不得不说,Joern这个项目的开发人员脑子太不清楚了,这么简单的需求,难道不是应该一个命令搞定的事情么?Anyway,还是要真诚感谢为大家开源做贡献的人。

你可能感兴趣的:(科研工具,论文点评)