# Trying to get variable dependencies with libclang
![](https://hackmd.io/_uploads/B1t4zvjAn.png)
如何用 libclang 的前端解析所有的.c .cpp 展開ast tree,目前進度只有 callee 和caller 的關係,還有參數 ,function variable 的資訊
假設你有安裝llvm 應該會在
```bash=
find /usr/lib/x86_64-linux-gnu -name libclang*
/usr/lib/x86_64-linux-gnu/libclang-10.so.1
/usr/lib/x86_64-linux-gnu/libclang-11.so.1
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.10
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11
ln -s libclang.so.1 libclang.so
/usr/lib/x86_64-linux-gnu/libclang-10.so.1
/usr/lib/x86_64-linux-gnu/libclang-11.so.1
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.10
/usr/lib/x86_64-linux-gnu/libclang-cpp.so.11
/usr/lib/x86_64-linux-gnu/libclang.so <=== 請產生這個檔案 ,到這邊libclang 應該就可以用了
```
透過 clang 前端本來想要找出 variable 之間的依賴關係,嘗試了蠻多種方式,後來發現有cindex.CompilationDatabase.fromDirectory
這邊也有用 compiledb 將 makefile 裡面的database 給libclang看建立有ast依賴關係的tree 不過還是不太行 ,不過可以得到該專案裡面的所有.c .cpp 建立call graph ,加上一些資訊應該可以更好的看出variable引用關係.
照理說應該在compiler處理應該比較正確哈哈
/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/compile_commands.json
```python=
# Import necessary libraries
import clang.cindex as cindex
import json
import os
# Initialize libclang
function_name = ""
index = cindex.Index.create()
# Specify the path to the compile_commands.json file
compile_commands_file = '/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/compile_commands.json'
# Read the compile_commands.json file
with open(compile_commands_file, 'r') as f:
compile_commands_data = json.load(f)
# Create a set to store all .c and .cpp files
source_files = set()
# Iterate through each compilation command
for command_data in compile_commands_data:
# Get the source file path from the compilation command
source_file = command_data['file']
# Check if the file extension is .c or .cpp
if source_file.endswith('.c') or source_file.endswith('.cpp'):
source_files.add("/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/" + source_file)
# Create a dictionary to store function call relationships
function_calls = {}
# Iterate through the paths of all .c and .cpp files
for source_file in source_files:
print(f"Analyzing {source_file}...")
compile_commands = cindex.CompilationDatabase.fromDirectory('/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/')
# Get the compilation commands
commands = compile_commands.getCompileCommands(source_file)
# Create a list to store compilation options
file_args = []
for command in commands:
for argument in command.arguments:
if str(argument).find("-I") >= 0:
file_args.append(argument)
# Parse the source code file
translationUnit = index.parse(
source_file,
args=file_args,
options=cindex.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD
)
if not translationUnit:
print(f"Failed to parse translation unit for {source_file}")
else:
# Get the root node of the abstract syntax tree (AST)
rootCursor = translationUnit.cursor
# Recursive function for traversing every node in the AST
def visit(cursor, depth=0):
global function_name
if cursor.kind == cindex.CursorKind.FUNCTION_DECL:
# When a function declaration is found
function_name = cursor.displayname
if function_name not in function_calls:
function_calls[function_name] = set()
# Print other functions called by this function
for child in cursor.get_children():
if child.kind == cindex.CursorKind.CALL_EXPR:
callee = child.referenced
if callee:
callee_name = callee.displayname
function_calls[function_name].add(callee_name)
for child in cursor.get_children():
visit(child, depth + 1)
# Call the traversal function
visit(rootCursor)
function_calls_record = []
# Function to print function calls
def print_function_calls(caller, depth=1):
if caller in function_calls_record:
return
else:
function_calls_record.append(caller)
for callee in function_calls[caller]:
if callee in function_calls_record:
return
else:
function_calls_record.append(callee)
indent = " " * depth
print(f"{indent}Function Declaration: {caller}")
print(f"{indent} Callee: {callee}")
print_function_calls(callee, depth + 1)
total_call_record = []
# Function to print function call stacks
def print_function_calls(caller, depth=0):
global function_calls_record
if caller in function_calls_record:
return
else:
function_calls_record.append(caller)
indent = " " * depth
print(f"{indent}Caller: {caller}")
if caller in function_calls:
for callee in function_calls[caller]:
if callee in function_calls_record:
return
else:
function_calls_record.append(callee)
indent = " " * (depth+1)
print(f"{indent}Callee: {callee}")
if callee in function_calls:
for x in function_calls[callee]:
print_function_calls(x, depth + 2)
# Traverse all functions and record function call stacks
function_calls_record = []
for caller in function_calls:
function_calls_record = []
print_function_calls(caller)
total_call_record.append(function_calls_record)
# possible_callers = [] # Use a list to store possible callers
# Function to find possible callers of a target function
# def find_possible_callers(target_function):
# global possible_callers
# for call_record in total_call_record:
# if target_function in call_record:
# if target_function not in possible_callers:
# possible_callers.append(target_function)
# for x in call_record[call_record.index(target_function):]:
# if x != target_function and x not in possible_callers:
# possible_callers.append(x)
# find_possible_callers(x)
# return possible_callers
# # Example: Find possible callers of the "matrix_test" function
# target_function = 'matrix_test(ee_u32, MATRES *, MATDAT *, MATDAT *, MATDAT)'
# possible_callers = find_possible_callers(target_function)
# if possible_callers:
# print(f"Possible callers of {target_function}:")
# for caller in possible_callers:
# print(f" {caller}")
# else:
# print(f"No possible callers found for {target_function}")
```
```outpu=
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/utils.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/stubs/isatty.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/stubs/fstat.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/stubs/read.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/stubs/write.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/reset.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/stubs/close.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/stubs/_exit.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/stubs/write_hex.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/uart.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/platform.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/stubs/lseek.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/platform/stubs/sbrk.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_util.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_state.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_matrix.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_portme.c...
Analyzing /home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_main.c...
Caller: remove(const char *)
Caller: rename(const char *, const char *)
Caller: renameat(int, const char *, int, const char *)
Caller: tmpfile()
Caller: tmpnam(char *)
Caller: tmpnam_r(char *)
Caller: tempnam(const char *, const char *)
Caller: fclose(FILE *)
Caller: fflush(FILE *)
Caller: fflush_unlocked(FILE *)
Caller: fopen(const char *restrict, const char *restrict)
Caller: freopen(const char *restrict, const char *restrict, FILE *restrict)
Caller: fdopen(int, const char *)
Caller: fmemopen(void *, int, const char *)
Caller: open_memstream(char **, int *)
Caller: setbuf(FILE *restrict, char *restrict)
Caller: setvbuf(FILE *restrict, char *restrict, int, int)
Caller: setbuffer(FILE *restrict, char *restrict, int)
Caller: setlinebuf(FILE *)
Caller: fprintf(FILE *restrict, const char *restrict, ...)
Caller: printf(const char *restrict, ...)
Caller: sprintf(char *restrict, const char *restrict, ...)
Caller: vfprintf(FILE *restrict, const char *restrict, int)
Caller: vprintf(const char *restrict, int)
Caller: vsprintf(char *restrict, const char *restrict, int)
Caller: snprintf(char *restrict, int, const char *restrict, ...)
Caller: vsnprintf(char *restrict, int, const char *restrict, int)
Caller: vdprintf(int, const char *restrict, int)
Caller: dprintf(int, const char *restrict, ...)
Caller: fscanf(FILE *restrict, const char *restrict, ...)
Caller: scanf(const char *restrict, ...)
Caller: sscanf(const char *restrict, const char *restrict, ...)
Caller: vfscanf(FILE *restrict, const char *restrict, int)
Caller: vscanf(const char *restrict, int)
Caller: vsscanf(const char *restrict, const char *restrict, int)
Caller: fgetc(FILE *)
Caller: getc(FILE *)
Caller: getchar()
Caller: getc_unlocked(FILE *)
Caller: getchar_unlocked()
Caller: fgetc_unlocked(FILE *)
Caller: fputc(int, FILE *)
Caller: putc(int, FILE *)
Caller: putchar(int)
Caller: fputc_unlocked(int, FILE *)
Caller: putc_unlocked(int, FILE *)
Caller: putchar_unlocked(int)
Caller: getw(FILE *)
Caller: putw(int, FILE *)
Caller: fgets(char *restrict, int, FILE *restrict)
Caller: __getdelim(char **restrict, int *restrict, int, FILE *restrict)
Caller: getdelim(char **restrict, int *restrict, int, FILE *restrict)
Caller: getline(char **restrict, int *restrict, FILE *restrict)
Caller: fputs(const char *restrict, FILE *restrict)
Caller: puts(const char *)
Caller: ungetc(int, FILE *)
Caller: fread(void *restrict, int, int, FILE *restrict)
Caller: fwrite(const void *restrict, int, int, FILE *restrict)
Caller: fread_unlocked(void *restrict, int, int, FILE *restrict)
Caller: fwrite_unlocked(const void *restrict, int, int, FILE *restrict)
Caller: fseek(FILE *, long, int)
Caller: ftell(FILE *)
Caller: rewind(FILE *)
Caller: fseeko(FILE *, __off_t, int)
Caller: ftello(FILE *)
Caller: fgetpos(FILE *restrict, fpos_t *restrict)
Caller: fsetpos(FILE *, const fpos_t *)
Caller: clearerr(FILE *)
Caller: feof(FILE *)
Caller: ferror(FILE *)
Caller: clearerr_unlocked(FILE *)
Caller: feof_unlocked(FILE *)
Caller: ferror_unlocked(FILE *)
Caller: perror(const char *)
Caller: fileno(FILE *)
Caller: fileno_unlocked(FILE *)
Caller: popen(const char *, const char *)
Caller: pclose(FILE *)
Caller: ctermid(char *)
Caller: flockfile(FILE *)
Caller: ftrylockfile(FILE *)
Caller: funlockfile(FILE *)
Caller: __uflow(FILE *)
Caller: __overflow(FILE *, int)
Caller: get_timer_freq()
Caller: get_timer_value()
Caller: access(const char *, int)
Caller: faccessat(int, const char *, int, int)
Caller: lseek(int, __off_t, int)
Caller: close(int)
Caller: read(int, void *, int)
Caller: write(int, const void *, int)
Caller: pread(int, void *, int, __off_t)
Caller: pwrite(int, const void *, int, __off_t)
Caller: pipe(int *)
Caller: alarm(unsigned int)
Caller: sleep(unsigned int)
Caller: ualarm(__useconds_t, __useconds_t)
Caller: usleep(__useconds_t)
Caller: pause()
Caller: chown(const char *, __uid_t, __gid_t)
Caller: fchown(int, __uid_t, __gid_t)
Caller: lchown(const char *, __uid_t, __gid_t)
Caller: fchownat(int, const char *, __uid_t, __gid_t, int)
Caller: chdir(const char *)
Caller: fchdir(int)
Caller: getcwd(char *, int)
Caller: getwd(char *)
Caller: dup(int)
Caller: dup2(int, int)
Caller: execve(const char *, char *const *, char *const *)
Caller: fexecve(int, char *const *, char *const *)
Caller: execv(const char *, char *const *)
Caller: execle(const char *, const char *, ...)
Caller: execl(const char *, const char *, ...)
Caller: execvp(const char *, char *const *)
Caller: execlp(const char *, const char *, ...)
Caller: nice(int)
Caller: _exit(int)
Callee: write_hex(int, unsigned long)
Caller: pathconf(const char *, int)
Caller: fpathconf(int, int)
Caller: sysconf(int)
Caller: confstr(int, char *, int)
Caller: getpid()
Caller: getppid()
Caller: getpgrp()
Caller: __getpgid(__pid_t)
Caller: getpgid(__pid_t)
Caller: setpgid(__pid_t, __pid_t)
Caller: setpgrp()
Caller: setsid()
Caller: getsid(__pid_t)
Caller: getuid()
Caller: geteuid()
Caller: getgid()
Caller: getegid()
Caller: getgroups(int, __gid_t *)
Caller: setuid(__uid_t)
Caller: setreuid(__uid_t, __uid_t)
Caller: seteuid(__uid_t)
Caller: setgid(__gid_t)
Caller: setregid(__gid_t, __gid_t)
Caller: setegid(__gid_t)
Caller: fork()
Caller: vfork()
Caller: ttyname(int)
Caller: ttyname_r(int, char *, int)
Caller: isatty(int)
Caller: ttyslot()
Caller: link(const char *, const char *)
Caller: linkat(int, const char *, int, const char *, int)
Caller: symlink(const char *, const char *)
Caller: readlink(const char *restrict, char *restrict, int)
Caller: symlinkat(const char *, int, const char *)
Caller: readlinkat(int, const char *restrict, char *restrict, int)
Caller: unlink(const char *)
Caller: unlinkat(int, const char *, int)
Caller: rmdir(const char *)
Caller: tcgetpgrp(int)
Caller: tcsetpgrp(int, __pid_t)
Caller: getlogin()
Caller: getlogin_r(char *, int)
Caller: setlogin(const char *)
Caller: getopt(int, char *const *, const char *)
Caller: gethostname(char *, int)
Caller: sethostname(const char *, int)
Caller: sethostid(long)
Caller: getdomainname(char *, int)
Caller: setdomainname(const char *, int)
Caller: vhangup()
Caller: revoke(const char *)
Caller: profil(unsigned short *, int, int, unsigned int)
Caller: acct(const char *)
Caller: getusershell()
Caller: endusershell()
Caller: setusershell()
Caller: daemon(int, int)
Caller: chroot(const char *)
Caller: getpass(const char *)
Caller: fsync(int)
Caller: gethostid()
Caller: sync()
Caller: getpagesize()
Caller: getdtablesize()
Caller: truncate(const char *, __off_t)
Caller: ftruncate(int, __off_t)
Caller: brk(void *)
Caller: sbrk(intptr_t)
Caller: syscall(long, ...)
Caller: lockf(int, int, __off_t)
Caller: fdatasync(int)
Caller: crypt(const char *, const char *)
Caller: getentropy(void *, int)
Caller: write_hex(int, unsigned long)
Caller: _stub(int)
Caller: _isatty(int)
Caller: __errno_location()
Caller: stat(const char *restrict, struct stat *restrict)
Caller: fstat(int, struct stat *)
Caller: fstatat(int, const char *restrict, struct stat *restrict, int)
Caller: lstat(const char *restrict, struct stat *restrict)
Caller: chmod(const char *, __mode_t)
Caller: lchmod(const char *, __mode_t)
Caller: fchmod(int, __mode_t)
Caller: fchmodat(int, const char *, __mode_t, int)
Caller: umask(__mode_t)
Caller: mkdir(const char *, __mode_t)
Caller: mkdirat(int, const char *, __mode_t)
Caller: mknod(const char *, __mode_t, __dev_t)
Caller: mknodat(int, const char *, __mode_t, __dev_t)
Caller: mkfifo(const char *, __mode_t)
Caller: mkfifoat(int, const char *, __mode_t)
Caller: utimensat(int, const char *, const struct timespec *, int)
Caller: futimens(int, const struct timespec *)
Caller: __fxstat(int, int, struct stat *)
Caller: __xstat(int, const char *, struct stat *)
Caller: __lxstat(int, const char *, struct stat *)
Caller: __fxstatat(int, int, const char *, struct stat *, int)
Caller: __xmknod(int, const char *, __mode_t, __dev_t *)
Caller: __xmknodat(int, int, const char *, __mode_t, __dev_t *)
Caller: _fstat(int, struct stat *)
Callee: isatty(int)
Callee: _stub(int)
Caller: __bswap_16(__uint16_t)
Caller: __bswap_32(__uint32_t)
Caller: __bswap_64(__uint64_t)
Caller: __uint16_identity(__uint16_t)
Caller: __uint32_identity(__uint32_t)
Caller: __uint64_identity(__uint64_t)
Caller: select(int, fd_set *restrict, fd_set *restrict, fd_set *restrict, struct timeval *restrict)
Caller: pselect(int, fd_set *restrict, fd_set *restrict, fd_set *restrict, const struct timespec *restrict, const __sigset_t *restrict)
Caller: _read(int, void *, int)
Callee: _stub(int)
Caller: memcpy(void *restrict, const void *restrict, int)
Caller: memmove(void *, const void *, int)
Caller: memccpy(void *restrict, const void *restrict, int, int)
Caller: memset(void *, int, int)
Caller: memcmp(const void *, const void *, int)
Caller: memchr(const void *, int, int)
Caller: strcpy(char *restrict, const char *restrict)
Caller: strncpy(char *restrict, const char *restrict, int)
Caller: strcat(char *restrict, const char *restrict)
Caller: strncat(char *restrict, const char *restrict, int)
Caller: strcmp(const char *, const char *)
Caller: strncmp(const char *, const char *, int)
Caller: strcoll(const char *, const char *)
Caller: strxfrm(char *restrict, const char *restrict, int)
Caller: strcoll_l(const char *, const char *, locale_t)
Caller: strxfrm_l(char *, const char *, int, locale_t)
Caller: strdup(const char *)
Caller: strndup(const char *, int)
Caller: strchr(const char *, int)
Caller: strrchr(const char *, int)
Caller: strcspn(const char *, const char *)
Caller: strspn(const char *, const char *)
Caller: strpbrk(const char *, const char *)
Caller: strstr(const char *, const char *)
Caller: strtok(char *restrict, const char *restrict)
Caller: __strtok_r(char *restrict, const char *restrict, char **restrict)
Caller: strtok_r(char *restrict, const char *restrict, char **restrict)
Caller: strlen(const char *)
Caller: strnlen(const char *, int)
Caller: strerror(int)
Caller: strerror_r(int, char *, int)
Caller: strerror_l(int, locale_t)
Caller: bcmp(const void *, const void *, int)
Caller: bcopy(const void *, void *, int)
Caller: bzero(void *, int)
Caller: index(const char *, int)
Caller: rindex(const char *, int)
Caller: ffs(int)
Caller: ffsl(long)
Caller: ffsll(long long)
Caller: strcasecmp(const char *, const char *)
Caller: strncasecmp(const char *, const char *, int)
Caller: strcasecmp_l(const char *, const char *, locale_t)
Caller: strncasecmp_l(const char *, const char *, int, locale_t)
Caller: explicit_bzero(void *, int)
Caller: strsep(char **restrict, const char *restrict)
Caller: strsignal(int)
Caller: __stpcpy(char *restrict, const char *restrict)
Caller: stpcpy(char *restrict, const char *restrict)
Caller: __stpncpy(char *restrict, const char *restrict, int)
Caller: stpncpy(char *restrict, const char *restrict, int)
Caller: _put_char(int)
Caller: _write(int, const void *, int)
Callee: _stub(int)
Caller: c_startup()
Callee: __builtin_memcpy(void *, const void *, unsigned long)
Callee: __builtin_memset(void *, int, unsigned long)
Caller: system_init()
Callee: uart_init(unsigned int)
Caller: main()
Callee: portable_fini(core_portable *)
Callee: core_init_matrix(ee_u32, void *, ee_s32, mat_params *)
Callee: get_seed_32(int)
Callee: core_init_state(ee_u32, ee_s16, ee_u8 *)
Callee: stop_time()
Caller: get_timer_value()
Callee: start_time()
Caller: printf(const char *restrict, ...)
Caller: reset_handler()
Callee: c_startup()
Caller: __builtin_memcpy(void *, const void *, unsigned long)
Caller: __builtin_memset(void *, int, unsigned long)
Callee: system_init()
Caller: uart_init(unsigned int)
Caller: _close(int)
Callee: _stub(int)
Caller: exit(int)
Caller: uart_init(unsigned int)
Caller: uart_putc(int)
Caller: uart_puts(const char *)
Callee: uart_putc(int)
Caller: outbyte(int)
Callee: uart_putc(int)
Caller: reset_vector()
Caller: memory_init()
Callee: __builtin_constant_p()
Caller: portable_init(core_portable *, int *, char **)
Caller: portable_fini(core_portable *)
Caller: iterate(void *)
Callee: core_bench_list(core_results *, ee_s16)
Caller: core_list_find(list_head *, list_data *)
Caller: core_list_remove(list_head *)
Caller: core_list_reverse(list_head *)
Caller: crc16(ee_s16, ee_u16)
Callee: crcu16(ee_u16, ee_u16)
Caller: crcu8(ee_u8, ee_u16)
Caller: core_list_mergesort(list_head *, list_cmp, core_results *)
Callee: cmp
Caller: core_list_undo_remove(list_head *, list_head *)
Caller: start_time()
Callee: printf(const char *restrict, ...)
Callee: get_timer_value()
Caller: stop_time()
Callee: get_timer_value()
Caller: get_time()
Caller: time_in_secs(uint64_t)
Caller: crcu8(ee_u8, ee_u16)
Caller: crc16(ee_s16, ee_u16)
Callee: crcu16(ee_u16, ee_u16)
Caller: crcu8(ee_u8, ee_u16)
Caller: crcu16(ee_u16, ee_u16)
Callee: crcu8(ee_u8, ee_u16)
Caller: crcu32(ee_u32, ee_u16)
Callee: crc16(ee_s16, ee_u16)
Caller: crcu16(ee_u16, ee_u16)
Callee: crcu8(ee_u8, ee_u16)
Caller: check_data_types()
Callee: printf(const char *restrict, ...)
Caller: portable_malloc(ee_size_t)
Caller: portable_free(void *)
Caller: parseval(char *)
Caller: core_list_init(ee_u32, list_head *, ee_s16)
Callee: core_list_insert_new(list_head *, list_data *, list_head **, list_data **, list_head *, list_data *)
Caller: copy_info(list_data *, list_data *)
Caller: core_bench_list(core_results *, ee_s16)
Callee: core_list_find(list_head *, list_data *)
Callee: core_list_remove(list_head *)
Callee: core_list_reverse(list_head *)
Callee: crc16(ee_s16, ee_u16)
Caller: crcu16(ee_u16, ee_u16)
Callee: crcu8(ee_u8, ee_u16)
Callee: core_list_mergesort(list_head *, list_cmp, core_results *)
Caller: cmp
Callee: core_list_undo_remove(list_head *, list_head *)
Caller: core_init_state(ee_u32, ee_s16, ee_u8 *)
Caller: core_bench_state(ee_u32, ee_u8 *, ee_s16, ee_s16, ee_s16, ee_u16)
Callee: crcu32(ee_u32, ee_u16)
Caller: crc16(ee_s16, ee_u16)
Callee: crcu16(ee_u16, ee_u16)
Caller: crcu8(ee_u8, ee_u16)
Callee: core_state_transition(ee_u8 **, ee_u32 *)
Caller: ee_isdigit(ee_u8)
Caller: core_init_matrix(ee_u32, void *, ee_s32, mat_params *)
Caller: core_bench_matrix(mat_params *, ee_s16, ee_u16)
Callee: matrix_test(ee_u32, MATRES *, MATDAT *, MATDAT *, MATDAT)
Caller: matrix_sum(ee_u32, MATRES *, MATDAT)
Caller: matrix_mul_const(ee_u32, MATRES *, MATDAT *, MATDAT)
Caller: matrix_mul_matrix_bitextract(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: matrix_mul_matrix(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: crc16(ee_s16, ee_u16)
Callee: crcu16(ee_u16, ee_u16)
Caller: crcu8(ee_u8, ee_u16)
Caller: matrix_add_const(ee_u32, MATDAT *, MATDAT)
Caller: matrix_mul_vect(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: core_list_find(list_head *, list_data *)
Caller: core_list_reverse(list_head *)
Caller: core_list_remove(list_head *)
Caller: core_list_undo_remove(list_head *, list_head *)
Caller: core_list_insert_new(list_head *, list_data *, list_head **, list_data **, list_head *, list_data *)
Callee: copy_info(list_data *, list_data *)
Caller: core_list_mergesort(list_head *, list_cmp, core_results *)
Callee: cmp
Caller: calc_func(ee_s16 *, core_results *)
Callee: core_bench_state(ee_u32, ee_u8 *, ee_s16, ee_s16, ee_s16, ee_u16)
Caller: crcu32(ee_u32, ee_u16)
Callee: crc16(ee_s16, ee_u16)
Caller: crcu16(ee_u16, ee_u16)
Callee: crcu8(ee_u8, ee_u16)
Caller: core_state_transition(ee_u8 **, ee_u32 *)
Callee: ee_isdigit(ee_u8)
Caller: cmp_complex(list_data *, list_data *, core_results *)
Callee: calc_func(ee_s16 *, core_results *)
Caller: core_bench_state(ee_u32, ee_u8 *, ee_s16, ee_s16, ee_s16, ee_u16)
Callee: crcu32(ee_u32, ee_u16)
Caller: crc16(ee_s16, ee_u16)
Callee: crcu16(ee_u16, ee_u16)
Caller: crcu8(ee_u8, ee_u16)
Callee: core_state_transition(ee_u8 **, ee_u32 *)
Caller: ee_isdigit(ee_u8)
Caller: core_bench_matrix(mat_params *, ee_s16, ee_u16)
Callee: matrix_test(ee_u32, MATRES *, MATDAT *, MATDAT *, MATDAT)
Caller: matrix_sum(ee_u32, MATRES *, MATDAT)
Caller: matrix_mul_const(ee_u32, MATRES *, MATDAT *, MATDAT)
Caller: matrix_mul_matrix_bitextract(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: matrix_mul_matrix(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: matrix_add_const(ee_u32, MATDAT *, MATDAT)
Caller: matrix_mul_vect(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: cmp_idx(list_data *, list_data *, core_results *)
Caller: copy_info(list_data *, list_data *)
Caller: _lseek(int, off_t, int)
Callee: isatty(int)
Callee: _stub(int)
Caller: _sbrk(int)
Caller: get_seed_32(int)
Caller: core_state_transition(ee_u8 **, ee_u32 *)
Callee: ee_isdigit(ee_u8)
Caller: ee_isdigit(ee_u8)
Caller: matrix_test(ee_u32, MATRES *, MATDAT *, MATDAT *, MATDAT)
Callee: matrix_sum(ee_u32, MATRES *, MATDAT)
Callee: matrix_mul_const(ee_u32, MATRES *, MATDAT *, MATDAT)
Callee: matrix_mul_matrix_bitextract(ee_u32, MATRES *, MATDAT *, MATDAT *)
Callee: matrix_mul_matrix(ee_u32, MATRES *, MATDAT *, MATDAT *)
Callee: crc16(ee_s16, ee_u16)
Caller: crcu16(ee_u16, ee_u16)
Callee: crcu8(ee_u8, ee_u16)
Callee: matrix_add_const(ee_u32, MATDAT *, MATDAT)
Callee: matrix_mul_vect(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: matrix_sum(ee_u32, MATRES *, MATDAT)
Caller: matrix_mul_const(ee_u32, MATRES *, MATDAT *, MATDAT)
Caller: matrix_mul_vect(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: matrix_mul_matrix(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: matrix_mul_matrix_bitextract(ee_u32, MATRES *, MATDAT *, MATDAT *)
Caller: matrix_add_const(ee_u32, MATDAT *, MATDAT)
Caller: __ctype_get_mb_cur_max()
Caller: atof(const char *)
Caller: atoi(const char *)
Caller: atol(const char *)
Caller: atoll(const char *)
Caller: strtod(const char *restrict, char **restrict)
Caller: strtof(const char *restrict, char **restrict)
Caller: strtold(const char *restrict, char **restrict)
Caller: strtol(const char *restrict, char **restrict, int)
Caller: strtoul(const char *restrict, char **restrict, int)
Caller: strtoq(const char *restrict, char **restrict, int)
Caller: strtouq(const char *restrict, char **restrict, int)
Caller: strtoll(const char *restrict, char **restrict, int)
Caller: strtoull(const char *restrict, char **restrict, int)
Caller: l64a(long)
Caller: a64l(const char *)
Caller: random()
Caller: srandom(unsigned int)
Caller: initstate(unsigned int, char *, int)
Caller: setstate(char *)
Caller: random_r(struct random_data *restrict, int32_t *restrict)
Caller: srandom_r(unsigned int, struct random_data *)
Caller: initstate_r(unsigned int, char *restrict, int, struct random_data *restrict)
Caller: setstate_r(char *restrict, struct random_data *restrict)
Caller: rand()
Caller: srand(unsigned int)
Caller: rand_r(unsigned int *)
Caller: drand48()
Caller: erand48(unsigned short *)
Caller: lrand48()
Caller: nrand48(unsigned short *)
Caller: mrand48()
Caller: jrand48(unsigned short *)
Caller: srand48(long)
Caller: seed48(unsigned short *)
Caller: lcong48(unsigned short *)
Caller: drand48_r(struct drand48_data *restrict, double *restrict)
Caller: erand48_r(unsigned short *, struct drand48_data *restrict, double *restrict)
Caller: lrand48_r(struct drand48_data *restrict, long *restrict)
Caller: nrand48_r(unsigned short *, struct drand48_data *restrict, long *restrict)
Caller: mrand48_r(struct drand48_data *restrict, long *restrict)
Caller: jrand48_r(unsigned short *, struct drand48_data *restrict, long *restrict)
Caller: srand48_r(long, struct drand48_data *)
Caller: seed48_r(unsigned short *, struct drand48_data *)
Caller: lcong48_r(unsigned short *, struct drand48_data *)
Caller: malloc(int)
Caller: calloc(int, int)
Caller: realloc(void *, int)
Caller: reallocarray(void *, int, int)
Caller: free(void *)
Caller: alloca(int)
Caller: valloc(int)
Caller: posix_memalign(void **, int, int)
Caller: aligned_alloc(int, int)
Caller: abort()
Caller: atexit(void (*)(void))
Caller: at_quick_exit(void (*)(void))
Caller: on_exit(void (*)(int, void *), void *)
Caller: quick_exit(int)
Caller: _Exit(int)
Caller: getenv(const char *)
Caller: putenv(char *)
Caller: setenv(const char *, const char *, int)
Caller: unsetenv(const char *)
Caller: clearenv()
Caller: mktemp(char *)
Caller: mkstemp(char *)
Caller: mkstemps(char *, int)
Caller: mkdtemp(char *)
Caller: system(const char *)
Caller: realpath(const char *restrict, char *restrict)
Caller: bsearch(const void *, const void *, int, int, __compar_fn_t)
Caller: qsort(void *, int, int, __compar_fn_t)
Caller: abs(int)
Caller: labs(long)
Caller: llabs(long long)
Caller: div(int, int)
Caller: ldiv(long, long)
Caller: lldiv(long long, long long)
Caller: ecvt(double, int, int *restrict, int *restrict)
Caller: fcvt(double, int, int *restrict, int *restrict)
Caller: gcvt(double, int, char *)
Caller: qecvt(long double, int, int *restrict, int *restrict)
Caller: qfcvt(long double, int, int *restrict, int *restrict)
Caller: qgcvt(long double, int, char *)
Caller: ecvt_r(double, int, int *restrict, int *restrict, char *restrict, int)
Caller: fcvt_r(double, int, int *restrict, int *restrict, char *restrict, int)
Caller: qecvt_r(long double, int, int *restrict, int *restrict, char *restrict, int)
Caller: qfcvt_r(long double, int, int *restrict, int *restrict, char *restrict, int)
Caller: mblen(const char *, int)
Caller: mbtowc(int *restrict, const char *restrict, int)
Caller: wctomb(char *, int)
Caller: mbstowcs(int *restrict, const char *restrict, int)
Caller: wcstombs(char *restrict, const int *restrict, int)
Caller: rpmatch(const char *)
Caller: getsubopt(char **restrict, char *const *restrict, char **restrict)
Caller: getloadavg(double *, int)
```
再加料一下印出 variable 和 function param
``` python
import clang.cindex as cindex
import json
import os
function_name = ""
# Initialize libclang
index = cindex.Index.create()
# Specify the path to the compile_commands.json file
compile_commands_file = '/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/compile_commands.json'
# Read the compile_commands.json file
with open(compile_commands_file, 'r') as f:
compile_commands_data = json.load(f)
# Create a collection to store all .c and .cpp files
source_files = set()
# Iterate through each compilation command
for command_data in compile_commands_data:
# Get the source file path from the compilation command
source_file = command_data['file']
# Check if the file extension is .c or .cpp
if source_file.endswith('.c') or source_file.endswith('.cpp'):
source_files.add("/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/" + source_file)
# Create a dictionary to store function call relationships
function_calls = {}
function_variable = {}
function_param = {}
# Iterate through the paths of all .c and .cpp files
for source_file in source_files:
print(f"Analyzing {source_file}...")
# Create a CompilationDatabase for the specified directory
compile_commands = cindex.CompilationDatabase.fromDirectory('/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/')
# Get the compilation commands
commands = compile_commands.getCompileCommands(source_file)
# Create a list to store compilation options
file_args = []
for command in commands:
for argument in command.arguments:
if str(argument).find("-I") >= 0:
file_args.append(argument)
# Parse the source code file
translationUnit = index.parse(
source_file,
args=file_args,
options=cindex.TranslationUnit.PARSE_DETAILED_PROCESSING_RECORD
)
if not translationUnit:
print(f"Failed to parse translation unit for {source_file}")
else:
# Get the root node of the abstract syntax tree
rootCursor = translationUnit.cursor
# Recursive function to traverse each node in the abstract syntax tree
def visit(cursor, depth=0):
global function_name
if cursor.kind == cindex.CursorKind.FUNCTION_DECL:
# When a function declaration is found
function_name = cursor.displayname
if function_name not in function_calls:
function_calls[function_name] = set()
if function_name not in function_variable:
function_variable[function_name] = set()
if function_name not in function_param:
function_param[function_name] = set()
# Get function parameter information
for param in cursor.get_children():
if param.kind == cindex.CursorKind.PARM_DECL:
param_name = param.displayname
param_type = param.type.spelling
param_info = f" Parameter Name: {param_name} | Parameter Type: {param_type}"
function_param[function_name].add(param_info)
# Print other functions called by this function
for child in cursor.get_children():
if child.kind == cindex.CursorKind.CALL_EXPR:
callee = child.referenced
if callee:
callee_name = callee.displayname
function_calls[function_name].add(callee_name)
if child.kind:
# Get variable declarations referenced by DECL_REF_EXPR
var_decl = child.get_definition()
if var_decl and var_decl.kind == cindex.CursorKind.VAR_DECL:
output = " Variable Name:"+ str(child.displayname) + "|Variable Location:"+ str(var_decl.location.file.name)+ ":"+ str(var_decl.location.line)+ ":"+ str(var_decl.location.column)
function_variable[function_name].add(output)
for child in cursor.get_children():
visit(child, depth + 1)
# Call the traversal function
visit(rootCursor)
# Record of function calls
function_calls_record = []
def print_function_calls(caller, depth=1):
if caller in function_calls_record:
return
else:
function_calls_record.append(caller)
for callee in function_calls[caller]:
if callee in function_calls_record:
return
else:
function_calls_record.append(callee)
indent = " " * depth
print(f"{indent}Function Declaration: {caller}")
print(f"{indent} Callee: {callee}")
print_function_calls(callee, depth + 1)
total_call_record = []
def print_function_param(function_name, depth):
if function_name in function_param:
get_function_param= function_param[function_name]
indent = " " * depth
for x in get_function_param:
print(f"{indent} {x}")
def print_function_variable(function_name, depth):
if function_name in function_variable:
get_function_variable = function_variable[function_name]
indent = " " * depth
for x in get_function_variable:
print(f"{indent} {x}")
def print_function_calls(caller, depth=0):
global function_calls_record
if caller in function_calls_record:
return
else:
function_calls_record.append(caller)
indent = " " * depth
print(f"{indent} Caller: {caller}")
print_function_param(caller, depth)
print_function_variable(caller, depth)
if caller in function_calls:
for callee in function_calls[caller]:
if callee in function_calls_record:
return
else:
function_calls_record.append(callee)
indent = " " * (depth + 1)
print(f"{indent} Callee: {callee}")
print_function_param(callee, depth+ 1)
print_function_variable(caller, depth+ 1)
if callee in function_calls:
for x in function_calls[callee]:
print_function_calls(x, depth + 2)
# Iterate through all functions and record function call stacks
function_calls_record = []
for caller in function_calls:
function_calls_record = []
print_function_calls(caller)
print("------------------------------------------------")
total_call_record.append(function_calls_record)
```
output
```
------------------------------------------------
Caller: calc_func(ee_s16 *, core_results *)
Parameter Name: pdata | Parameter Type: ee_s16 *
Parameter Name: res | Parameter Type: core_results *
Variable Name:data|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:72:12
Variable Name:flag|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:81:16
Variable Name:retval|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:73:12
Variable Name:dtype|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:82:16
Variable Name:optype|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:74:12
Callee: core_bench_matrix(mat_params *, ee_s16, ee_u16)
Parameter Name: crc | Parameter Type: ee_u16
Parameter Name: seed | Parameter Type: ee_s16
Parameter Name: p | Parameter Type: mat_params *
Variable Name:data|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:72:12
Variable Name:flag|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:81:16
Variable Name:retval|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:73:12
Variable Name:dtype|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:82:16
Variable Name:optype|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_list_join.c:74:12
Caller: crc16(ee_s16, ee_u16)
Parameter Name: crc | Parameter Type: ee_u16
Parameter Name: newval | Parameter Type: ee_s16
Callee: crcu16(ee_u16, ee_u16)
Parameter Name: crc | Parameter Type: ee_u16
Parameter Name: newval | Parameter Type: ee_u16
Caller: crcu8(ee_u8, ee_u16)
Parameter Name: crc | Parameter Type: ee_u16
Parameter Name: data | Parameter Type: ee_u8
Variable Name:i|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_util.c:167:11
Variable Name:carry|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_util.c:167:27
Variable Name:x16|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_util.c:167:18
Caller: matrix_test(ee_u32, MATRES *, MATDAT *, MATDAT *, MATDAT)
Parameter Name: val | Parameter Type: MATDAT
Parameter Name: B | Parameter Type: MATDAT *
Parameter Name: N | Parameter Type: ee_u32
Parameter Name: A | Parameter Type: MATDAT *
Parameter Name: C | Parameter Type: MATRES *
Variable Name:crc|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_matrix.c:132:12
Variable Name:clipval|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_matrix.c:133:12
Callee: matrix_mul_matrix_bitextract(ee_u32, MATRES *, MATDAT *, MATDAT *)
Parameter Name: B | Parameter Type: MATDAT *
Parameter Name: N | Parameter Type: ee_u32
Parameter Name: A | Parameter Type: MATDAT *
Parameter Name: C | Parameter Type: MATRES *
Variable Name:crc|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_matrix.c:132:12
Variable Name:clipval|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_matrix.c:133:12
Callee: matrix_mul_vect(ee_u32, MATRES *, MATDAT *, MATDAT *)
Parameter Name: B | Parameter Type: MATDAT *
Parameter Name: N | Parameter Type: ee_u32
Parameter Name: A | Parameter Type: MATDAT *
Parameter Name: C | Parameter Type: MATRES *
Variable Name:crc|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_matrix.c:132:12
Variable Name:clipval|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_matrix.c:133:12
Callee: matrix_mul_const(ee_u32, MATRES *, MATDAT *, MATDAT)
Parameter Name: val | Parameter Type: MATDAT
Parameter Name: N | Parameter Type: ee_u32
Parameter Name: A | Parameter Type: MATDAT *
Parameter Name: C | Parameter Type: MATRES *
Variable Name:crc|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_matrix.c:132:12
Variable Name:clipval|Variable Location:/home/x213212/cpptest/cppcheck/addons/CoreMark-V5/demo/core_matrix.c:133:12
------------------------------------------------
```