嵌入式系统裸机程序开发与调试

19 篇文章 1 订阅

🌹1.GUN工具的使用

GUN是一个开源的组织,给我们带来了很多开源软件和编译工具,如我们常用的

  • C编译器 :gcc
  • 预处理器 :cpp
  • C++编译器 g++
  • 汇编器 :as
  • 链接器 :ld
  • 二进制工具集 :objcopy
    二进制工具集的含义:他们专门用于控制和将二进制目标代码从一种格式转换为另一种格式,这些工具被称作为objcopy和objdump,许多linux机器使用的底层软件在编译阶段都非常依赖这些工具。调试的时候也需要他们。objcopy用于从一个文件拷贝目标代码到另一个文件,并在这个过程中进行转换。这样外面可以在不同的目标代码格式之间进行自动的转换并操纵这个过程中的内容。他们可以任何方式来操作二进制文件。

🚀1.1符号显示器nm

可通过arm-linux-gcc -v 查看是否有arm-linux-gcc这个编译器

显示符号 $nm -n main_elf
显示内容:
Ø第一列为符号地址
Ø第二列为符号所在段
Ø第三列为符号名称
比如我执行arm-linux -nm -n demo,demo是我的一个可执行程序,会出现如下信息
在这里插入图片描述
这些符号的含义如下图所示:
在这里插入图片描述

这个符号显示器很有用,可以看到绝大部分的信息,但是局部变量是看不到的,因为他分配在栈里面

💒1.2objdump:信息查看器

objdump 有点像那个快速查看之类的工具,就是以一种可阅读的格式让你更多地了解二进制文件可能带有的附加信息。对于一般只想让自己程序跑起来的程序员,这个命令没有更多意义,对于想进一步了解系统的程序员,应该掌握这种工具,至少你可以自己写写shellcode了,或者看看人家给的 exploit 中的 shellcode 是什么东西。

Ø 查看所有段信息 $objdump -h main_elf
Ø 查看文件头信息 $objdump -f main_elf
Ø 查看反汇编 $objdump -d main_elf
Ø 查看内嵌反汇编 $objdump -S -d main_elf
我一一演示一遍这些命令的使用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

🎪1.3objcopy:段剪辑器

objcopy被用来复制一个目标文件的内容到另一个文件中,可以使用不同于源文件的格式来输出目的文件,即可以进行格式转换

去除elf格式信息
$objcopy -O binary -S main_elf main.bin

⚡️2.程序编译过程

程序编译4步骤:
在这里插入图片描述
(1)预处理
C/C++源文件中,以“#”开头的命令被称为预处理命令,如包含命令“#include”、宏定义命令“#define”、条件编译命令“#if”、“#ifdef”等。预处理就是将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些东西输出到一个“.i”文件中等待进一步处理。
(2)编译
编译就是把C/C++代码(比如上述的“.i”文件)“翻译”成汇编代码。
(3)汇编
汇编就是将第二步输出的汇编代码翻译成符合一定格式的机器代码,在Linux系统上一般表现为ELF目标文件(OBJ文件)。“反汇编”是指将机器代码转换为汇编代码,这在调试程序时常常用到。
(4)链接
链接就是将上步生成的OBJ文件和系统库的OBJ文件、库文件链接起来,最终生成了可以在特定平台运行的可执行文件。

  • 一个标准应用程序通常都由链接器采用默认链接脚本(arm-linux-ld --verbose)将“用户程序” 和“库” 共同链接生成可执行程序

♐2.1程序链接过程

链接过程中需要一个标号(_start)作为程序入口
标号(_start)的作用是: 将用户程序从汇编带到了C语言程序入口, 即main()函数, 从此开始我们的应用程序之旅

2.2指定头文件

头文件在哪里?

  • 系统目录

    • 系统目录在哪?工具链里的某个include目录

    • 怎么确定?

      echo 'main(){}'| gcc -E -v -  // 它会列出头文件目录、库目录(LIBRARY_PATH)
      
    • 可以不使用系统include目录吗?可以,编译时指定参数-nostdinc

  • 可以自己指定头文件目录

-I <头文件目录>

🎪2.3 指定库文件

库文件在哪里?

  • 系统目录

    • 系统目录在哪?工具链里的某个lib目录

    • 怎么确定?

      echo 'main(){}'| gcc -E -v -  // 它会列出头文件目录、库目录(LIBRARY_PATH)
      
    • 可以不使用系统lib目录吗?可以,编译时指定参数-nostdlib

  • 可以自己指定库文件目录

-L <库文件目录>
  • 指定库文件
-l  <abc>   // 链接 libabc.so 或 lib.a

⌛3.裸机开发流程

*假设你写了一个程序名字为uart_test.c

  1. 使用命令编译:arm-linux-gcc uart_test.c -c -o uart.o

  2. 链接并强行指定main入口为0x48000000:arm-none-linux-gnueabi-ld uart.o -o uart-test -e main -Ttext=0x48000000

  3. 把elf文件变为bin结尾的二进制文件arm-none-linux-gnueabi-objcopy -O binary -S uart

  4. 把生成的.bin结尾的文件放到windows

  5. linux板子终端进入uboot修改环境变量执行setenv loadaddr 0x48000000修改并通过saveenv进行保存,注意环境变量的地址为你强行指定main函数的地址在这里插入图片描述

  6. 在uboot敲loadb命令等待文件传输

  7. 打开超级终端serucecrt把.bin文件传输到板子里在这里插入图片描述

  8. 通过go 0x48000000 执行main函数,这时一个完整的程序就可以执行了,可以在里面执行最简单的点灯操作,如下图所示
    在这里插入图片描述

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

魔动山霸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值