本文共 2872 字,大约阅读时间需要 9 分钟。
嵌入式开发中的时间分配:
问题:如何提高开发效率?
addr2line示例:定位0地址访问
注意事项
段标识说明
int* g_pointer;int a;char c;void func(void){ *g_pointer = (int)"hello, lemon";}执行如下命令:gcc -g -c func.cnm fun.o运行结果如下:00000004 C a(对于段标识为C来说,4指的是所占内存的字节数,如下同理)00000001 C c00000000 T func00000004 C g_pointer
代码如下:#includeint main(void){ printf("All is well...\n"); return 0;}执行如下命令:gcc -c test.c -o test.onm test.onm的结果如下:00000000 T main U putsprintf函数怎么变成了puts函数呢?这里发生了什么呢?执行的命令如下:gcc test.c -o test.outnm test.outnm的结果如下:0804a020 B __bss_start0804a020 b completed.68770804a018 D __data_start0804a018 W data_start08048360 t deregister_tm_clones080483d0 t __do_global_dtors_aux08049f0c t __do_global_dtors_aux_fini_array_entry0804a01c D __dso_handle08049f14 d _DYNAMIC0804a020 D _edata0804a024 B _end080484c4 T _fini080484d8 R _fp_hw080483f0 t frame_dummy08049f08 t __frame_dummy_init_array_entry080485d4 r __FRAME_END__0804a000 d _GLOBAL_OFFSET_TABLE_ w __gmon_start__080482b0 T _init08049f0c t __init_array_end08049f08 t __init_array_start080484dc R _IO_stdin_used w _ITM_deregisterTMCloneTable w _ITM_registerTMCloneTable08049f10 d __JCR_END__08049f10 d __JCR_LIST__ w _Jv_RegisterClasses080484c0 T __libc_csu_fini08048450 T __libc_csu_init U __libc_start_main@@GLIBC_2.00804841b T main U puts@@GLIBC_2.008048390 t register_tm_clones08048320 T _start0804a020 D __TMC_END__08048350 T __x86.get_pc_thunk.bx已经完成了链接工作,为什么还有这么多未定义的标识符呢?
反汇编目标文件,查看汇编到源码的映射
查看目标文件中的详细信息
objdump -h输出说明
可执行程序是如何加载到内存中的?
三个重要的概念:虚存地址(VMA)、加载地址(LMA)、运行地址桌面环境 :test.out(可执行文件),执行test.out会为其创建一个进程。首先会分配虚存,然后将相应的段加载到段所对应的虚存地址,这个虚存地址是在编译时确定的。这个虚存地址也就是加载目标地址,是终点的地址,简称加载地址。 最后执行应用程序。运行地址是指实地址。
嵌入式环境:源代码交叉编译得到test.bin,然后烧写到device的flash中。当flash为nandflash时,由于nand flash 只能存储代码不能执行代码,所以需要将代码从flash加载到ram中。 从flash的地址将代码拷贝到ram中,这个地址就叫加载地址,指的是起点。vma不等于lma ,这里的运行地址为实地址;当flash为norflash时, 代码可以直接在norflash中执行, 加载地址就是运行地址,虚存地址可能没有。