How to get a warning to use recursion?

Some rule sets and recommendations for developing firmware completely prohibit recursion. I use arm-none-eabi-gccwith an ARM Cortex-M4 based microcontroller.

I am looking for a static analysis tool that would warn me about using recursion in code. I have little experience with such tools. Is it possible to use clang-tidy or the clang static analyzer for this? If so, how can I configure them to warn about recursion?

(A quick look at the gcc options summary tells me that gcc cannot do this.)

Note:

  • Please do not tell me "just no recursion." The code base is large, not mine. I would like to be able to prove that there is no recursion in it.
    (This is similar to saying “just don’t look for a null pointer.” Although no one does this on purpose, there are tools to make sure this does not happen.)
+4
source share
2 answers

This is resolvable using callgraph data generated by Clang.

Step 1. Generate call schedule information with clang:

clang -S -emit-llvm SourceFile.c -o - | opt -analyze -print-callgraph 

(From Create a call graph for C ++ code , replacing -dot-callgraphwith -print-callgraph.)

To enter a type:

void a(){}
void b(){a();}
void c(){a(); b();}
void d(){a(); c();}
void e(){e();}

this will produce:

CallGraph Root is: <<null function: 0x0x7fdef25036c0>>
Call graph node <<null function>><<0x7fdef25036c0>>  #uses=0
  CS<0x0> calls function 'a'
  CS<0x0> calls function 'b'
  CS<0x0> calls function 'c'
  CS<0x0> calls function 'd'

Call graph node for function: 'a'<<0x7fdef2503750>>  #uses=4

Call graph node for function: 'b'<<0x7fdef25037d0>>  #uses=2
  CS<0x7fdef2500a38> calls function 'a'

Call graph node for function: 'c'<<0x7fdef2503870>>  #uses=2
  CS<0x7fdef2500cb8> calls function 'a'
  CS<0x7fdef2500d28> calls function 'b'

Call graph node for function: 'd'<<0x7fdef2503970>>  #uses=1
  CS<0x7fdef2500fe8> calls function 'a'
  CS<0x7fdef2501058> calls function 'c'

Call graph node for function: 'e'<<0x7f8912d03c10>>  #uses=2
  CS<0x7f8912d01318> calls function 'e'

( ++ c++filt; , .) , :

2. callgraph , callgraph.

class Graph(object):

  _callees = []

  def add_callee(self, f):
    self._callees.append(f)
    # etc

3. walk . - :

def walkGraph(node,f,stack):
  for callee in node._callees:
    if f == callee:
      print('Recursion!')
      dumpStack(stack,f)
    else:
      walkGraph(callee,f,stack.append(node))
+3

. , , , .

.

Roguewave: TotalView

0

Source: https://habr.com/ru/post/1681797/


All Articles