1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 学了这么多年C语言 你真的知道全局变量 局部变量 静态变量 本地函数 外部函数是

学了这么多年C语言 你真的知道全局变量 局部变量 静态变量 本地函数 外部函数是

时间:2020-01-10 06:21:31

相关推荐

学了这么多年C语言 你真的知道全局变量 局部变量 静态变量 本地函数 外部函数是

动态库内容分析

文章目录

动态库内容分析1. 动态库编译1.1 第一个C文件:basic.c1.2第二个C文件:demo.c1.3第三个C文件:main.c2.动态库编译3.二进制内容分析3.1 libbasic.so分析3.1.1 basic.c内容汇总3.1.2 libbasic.so符号表3.1.3 小结3.2 libdemo.so分析3.2.1 demo.c内容汇总3.2.2 demo.so符号表3.2.3 小结3.3 可执行文件a.out分析3.3.1 main.c内容汇总3.3.2 a.out符号表3.3.3 小结4.总结

1. 动态库编译

基本思路为:

先编写两个C文件,其中各自实现几个函数,变量,然后将其分别编译为动态库;再编写一个实现main函数的C文件,分别调用上述第一步动态库中的函数;分析最后的可执行文件和动态库文件的符号表;

1.1 第一个C文件:basic.c

这个C文件只定义并实现了四个不同形参的函数、五个静态变量、一个全局变量。由于只关心符号表或者其他二进制内容,因此不具体实现特定功能。

/*************************************************************************> File Name: basic.c> Author: Toney Sun> Mail: vip_13031075266@> Created Time: 04月20日 星期一 09时50分51秒************************************************************************/#include<stdio.h>int basic_func=4;static char *Author="Toney Sun";void func1(){int tmp_var;static char *Mail="vip_13031075266@";}void func2(int x){static char *Mail="vip_13031075266@";}int func3(char *a){static char *Mail="vip_13031075266@";}char * func4(int x, int y){static char *Mail="vip_13031075266@";}

1.2第二个C文件:demo.c

​ 在demo.c中我定义一个结构体udphdr。然后分别定义了两个全局变量,实现了三个函数:func5, func6, fun7。

/*************************************************************************> File Name: demo.c> Author: Toney Sun> Mail: vip_13031075266@> Created Time: 04月19日 星期日 22时33分39秒************************************************************************/#include<stdio.h>struct udphdr{short dstport;short srcport;short checksum;short length;};enum Date{Monday,Tuesday,Wensday,Thursday,Friday,Saturday,Sunday,};struct udphdr udp1;enum Date today = Monday;int iphdr1=10;extern void func1();extern void func2(int x);extern int func3(char *);extern char * func4(int x, int y);int fun5(int a){struct udphdr udp2;func1();printf("aaaaaaaaaaa\n");}int fun6(char *a){static struct udphdr udp1;func2(10);printf("aaaaaaaaaaa\n");}int fun7(int a, char *b){func3("test");printf("aaaaaaaaaaa\n");}

1.3第三个C文件:main.c

​ main.c主要用来实现main函数,并调用其他C文件中实现的函数和全局变量。从而观察对比不同的函数、变量在符号表中的异同。

/*************************************************************************> File Name: main.c> Author: Toney Sun> Mail: vip_13031075266@> Created Time: 04月20日 星期一 09时44分38秒************************************************************************/#include<stdio.h>extern void func1();extern int fun5(int a); extern int fun6(char *a);extern int fun7(int a, char *b);extern struct udphdr udp;extern int iphdr;int myAge=25;char *mail="vip_13031075266@";int show(){printf("Author: Toney Sun\n");}int main(int argc, char **argv){int a=10;int b=11;fun5(a);fun6("aaaaa");fun7(a, "Toney Sun");show();udp.srcport=4500;iphdr=10;return 0;}

2.动态库编译

使用gcc工具将basic.c编译为libbasic.so;

使用gcc工具将demo.c编译为libdemo.so

使用gcc工具将main.c链接上述两个动态库后编译为a.out

**注意:**我们不是为了执行该a.out, 而是想查看上述三个二进制文件的内容(符号表)。

toney@ubantu$ gcc -shared -fpic -o libdemo.so demo.c toney@ubantu$ gcc -shared -fpic -o libbasic.so basic.c toney@ubantu$ gcc main.c -L./ -ldemo -lbasictoney@ubantu$ ls -ltotal 35-rwxrwxrwx 1 root root 8552 4月 20 10:18 a.out-rwxrwxrwx 1 root root 454 4月 20 09:52 basic.c-rwxrwxrwx 1 root root 763 4月 20 09:49 demo.c-rwxrwxrwx 1 root root 8016 4月 20 09:43 demo.so-rwxrwxrwx 1 root root 7528 4月 20 10:17 libbasic.so-rwxrwxrwx 1 root root 8128 4月 20 10:17 libdemo.so-rwxrwxrwx 1 root root 846 4月 20 10:18 main.c

链接怎么还有个顺序问题:(

toney@ubantu$ gcc main.c -L./ -lbasic -ldemo.//libdemo.so: undefined reference to `func3'.//libdemo.so: undefined reference to `func1'.//libdemo.so: undefined reference to `func2'collect2: error: ld returned 1 exit statustoney@ubantu$ gcc main.c -L./ -ldemo -lbasictoney@ubantu$

3.二进制内容分析

3.1 libbasic.so分析

3.1.1 basic.c内容汇总
3.1.2 libbasic.so符号表
使用nm工具查看符号表内容(当然也可以使用其他工具查看,例如objdump, readelf, ldd等):

toney@ubantu$ nm libbasic.so 000000000028 d Author==================全局静态变量=================000000000020 D basic_func====================全局变量==================000000000050 B __bss_start000000000050 b completed.7698w __cxa_finalize00000000000005a0 t deregister_tm_clones0000000000000630 t __do_global_dtors_aux0000000000200e88 t __do_global_dtors_aux_fini_array_entry000000000018 d __dso_handle0000000000200e90 d _DYNAMIC000000000050 D _edata000000000058 B _end00000000000006a4 T _fini0000000000000670 t frame_dummy0000000000200e80 t __frame_dummy_init_array_entry00000000000007e8 r __FRAME_END__000000000000067a T func1===================实现函数===================0000000000000681 T func2===================实现函数===================000000000000068b T func3===================实现函数===================0000000000000696 T func4===================实现函数===================000000000000 d _GLOBAL_OFFSET_TABLE_w __gmon_start__00000000000006d0 r __GNU_EH_FRAME_HDR0000000000000568 T _initw _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTable000000000030 d Mail.2252================局部静态变量===================000000000038 d Mail.2256================局部静态变量===================000000000040 d Mail.2260================局部静态变量===================000000000048 d Mail.2265================局部静态变量===================00000000000005e0 t register_tm_clones000000000050 d __TMC_END__

使用nm -Da 查看本动态库定义的内容信息

toney@ubantu$ nm -Da libbasic.so 000000000020 D basic_func----------------1----------------000000000050 B __bss_startw __cxa_finalize000000000050 D _edata000000000058 B _end00000000000006a4 T _fini000000000000067a T func1----------------2----------------0000000000000681 T func2----------------3----------------000000000000068b T func3----------------4----------------0000000000000696 T func4----------------5----------------w __gmon_start__0000000000000568 T _initw _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTable

3.1.3 小结
本文件内定义的全局变量用‘D’来表示;本文件内定义的全局静态变量用‘d’来表示;本文件内实现的函数用‘T’来表示;不同函数内定义的静态变量在符号表中的符号有所差别,因此不会出现混淆的问题。从上述内容可以猜测:使用‘d’表示的变量不能被其他文件引用(上述‘d’标识的都是静态变量,这也比较合理)

3.2 libdemo.so分析

3.2.1 demo.c内容汇总
3.2.2 demo.so符号表

同样的,我们使用nm工具来查看动态库符号表信息:

toney@ubantu$ nm libdemo.so 000000000044 B __bss_start000000000048 b completed.7698w __cxa_finalize@@GLIBC_2.2.500000000000006b0 t deregister_tm_clones0000000000000740 t __do_global_dtors_aux0000000000200e18 t __do_global_dtors_aux_fini_array_entry000000000038 d __dso_handle0000000000200e20 d _DYNAMIC000000000044 D _edata000000000068 B _end0000000000000800 T _fini0000000000000780 t frame_dummy0000000000200e10 t __frame_dummy_init_array_entry0000000000000908 r __FRAME_END__000000000000078a T fun5=============================00000000000007ae T fun6=============================00000000000007d3 T fun7=============================U func1=============================U func2=============================U func3=============================000000000000 d _GLOBAL_OFFSET_TABLE_w __gmon_start__000000000000081c r __GNU_EH_FRAME_HDR0000000000000638 T _init000000000040 D iphdr1=============================w _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTableU puts@@GLIBC_2.2.500000000000006f0 t register_tm_clones000000000048 d __TMC_END__000000000050 B today=============================000000000060 B udp1=============================000000000058 b udp1.2278=============================

3.2.3 小结
结构体变量(非基本型变量)使用‘B’或‘b’来标识。全局结构体变量使用‘B’标识局部静态结构体变量使用‘b’标识局部变量不会显示在符号表中本文件内使用的函数使用‘T’标识引用其他文件的函数使用‘U’标识

3.3 可执行文件a.out分析

3.3.1 main.c内容汇总
3.3.2 a.out符号表

同样使用nm工具进行查看:

toney@ubantu$ nm a.out 000000000020 B __bss_start000000000030 b completed.7698w __cxa_finalize@@GLIBC_2.2.5000000000000 D __data_start000000000000 W data_start00000000000007a0 t deregister_tm_clones0000000000000830 t __do_global_dtors_aux0000000000200d88 t __do_global_dtors_aux_fini_array_entry000000000008 D __dso_handle0000000000200d90 d _DYNAMIC000000000020 D _edata000000000038 B _end0000000000000974 T _fini0000000000000870 t frame_dummy0000000000200d80 t __frame_dummy_init_array_entry0000000000000b2c r __FRAME_END__U fun5============1==============U fun6============2==============U fun7============3==============0000000000200fa0 d _GLOBAL_OFFSET_TABLE_w __gmon_start__00000000000009c0 r __GNU_EH_FRAME_HDR00000000000006f8 T _init0000000000200d88 t __init_array_end0000000000200d80 t __init_array_start0000000000000980 R _IO_stdin_used000000000020 B iphdr1============4=============w _ITM_deregisterTMCloneTablew _ITM_registerTMCloneTable0000000000000970 T __libc_csu_fini0000000000000900 T __libc_csu_initU __libc_start_main@@GLIBC_2.2.5000000000018 d mail============5==============000000000000088d T main============6==============000000000010 D myAge============7==============U puts@@GLIBC_2.2.500000000000007e0 t register_tm_clones000000000000087a T show============8==============0000000000000770 T _start000000000020 D __TMC_END__000000000028 B udp1============9==============

3.3.3 小结
引用的外部函数使用‘U’来标识全局变量使用‘D’来标识全局静态变量使用‘d’来标识引用的外部全局变量(简单类型和复杂类型)使用‘B’来标识

4.总结

对符号表中常见的变量、函数标识总结如下:

学了这么多年C语言 你真的知道全局变量 局部变量 静态变量 本地函数 外部函数是如何区分标识的吗?

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。