GNU GCC

编译器下载

  1. arm-linux-gcc下载  https://www.linaro.org/downloads/
  2. 解压添加bin到环境变量

gcc组件

c++

gcc 的一个版本,默认语言设置为 C++,而且在连接的时候自动包含标准 C++库。这和g++一样

g++

gcc 的一个版本,默认语言设置为 C++,而且在链接的时候自动包含标准 C++库。这和 c++ 是一样的

gcc

该驱动程序用于执行编译程序和连接程序以产生需要的输出

gcc使用

gcc参数

选项

描述

-c

只编译不链接。

会明确指示 GCC 去编译源代码,在硬盘上留下目标文件,且跳过将目标文件连接到可执行程序这一步。

缺省情况下, GCC通过用`.o'替换源文件名后缀`.c', `.i', `.s',等产生目标文件名.可以使用-o选项选择其他名字.

GCC忽略-c选项后面任何无法识别的输入文件(他们不需要编译或汇编).

如:gcc -c hello.c

-Dmacro定义指定的宏,使它能够通过源码中的#ifdef进行检验

-o file

指定输出的文件名

如果没有使用 `-o' 选项,默认的输出结果是:可执行文件为`a.out'。如gcc -c hello.c -o hello.o

-S

指示编译程序生成汇编语言代码,然后停止。

缺省情况下, GCC通过用 `.o' 替换源文件名后缀 `.c'、`.i' 等等,产生 目标文件名。可以使用-o选项选择其他名字。

汇编语言的形式依赖于编译程序的目标平台。如果编译多个源文件,会为每个源文件都生成一个汇编语言模块。

GCC忽略任何不需要编译的输入文件。

gcc -S helloworld.c

-E

预处理后即停止,不进行编译。预处理后的代码送往标准输出

GCC忽略任何不需要预处理的输入文件.

gcc -E helloworld.c

gcc -E helloworld.c -o helloworld.i

-C

告诉预处理器不要丢弃注释,配合 `-E' 选项使用。

-P

告诉预处理器不要产生 `#line' 命令,配合 `-E' 选项使用

-v

(在标准错误)显示执行编译阶段的命令.同时显示编译器驱动程序,预处理器,编译器的版本号.

-ldl

表示生成的对象模块需要用到共享库:$ gcc say.c -ldl -o say

主要是用到了 dlopen 等函数需要用到此选项

-I

指定头文件路径

-e name

指定 name 为程序的入口地址

-ffreestanding

编译独立的程序,不会自动链接 C 运行库、启动文件等;他隐含声明了 `-fno-builtin' 选项,而且对main函数没有特别要求。

-finline-functions

-fno-inline-funcitons

启用内联函数

关闭内联函数

-g

以操作系统的本地格式(stabs,COFF,XCOFF 或 DWARF)产生调试信息,GDB能够使用这些调试信息。

-ggdb

以本地格式(如果支持)输出调试信息,尽可能包括GDB扩展。

-L <directory>

指定链接时查找路径,多个路径之间用冒号隔开

-static

在支持动态连接(dynamic linking)的系统上阻止连接共享库。即只能使用静态链接。

-shared 

生成一个共享目标文件,他可以和其他目标文件链接产生可执行文件。

-O
-O1

优化。对于大函数,优化编译占用稍微多的时间和相当大的内存。

不使用 `-O' 选项时,编译器的目标是减少编译的开销,使编译结果能够调试。

语句是独立的:如果在两条语句之间用断点中止程序,可以对任何变量重新赋值,或者在函数体内把程序计数器指到其他语句,以及从源程序中精确地获取你期待的结果。

不使用 `-O' 选项时,只有声明了register的变量才分配使用寄存器。编译结果比不用 `-O' 选项的GCC要略逊一筹.

使用了 `-O' 选项,编译器会试图减少目标码的大小和执行时间。

如果指定了`-O'选项,,`-fthread-jumps' 和 `-fdefer-pop' 选项将被打开。

-O2

多优化一些。

除了涉及空间和速度交换的优化选项,执行几乎所有的优化工作。例如不进行循环展开(loop unrolling)和函数内嵌(inlining)。

和 -O 选项比较,这个选项既增加了编译时间,也提高了生成代码的运行效果。

-O3

优化的更多。除了打开 -O2所做的一切,它还打开了-finline-functions选项。

-O0

不优化。如果指定了多个 -O选项,不管带不带数字,最后一个选项才是生效的选项。

-Wall

对源代码中的多数编译警告进行启用

-fpic

如果支持这种目标机,编译器就生成位置无关目标码。适用于共享库(shared library)。

-fPIC

如果支持这种目标机,编译器就输出位置无关目标码。适用于动态连接(dynamic linking),即使分支需要大范围转移。

-fPIE

使用地址无关代码模式编译可执行文件 随机分配地址

-Xlinker option

把选项option传递给连接器,可以用他传递系统特定的连接选项, GNU CC无法识别这些选项。

如果需要传递携带参数的选项,必须使用两次 `-Xlinker',一次传递选项,另一次传递他的参数。

例如,如果传递 `-assert definitions',必须写成 `-Xlinker -assert -Xlinker definitions',而不能写成 `-Xlinker "-assert definitions"',因为这样会把整个字符串当做一个参数传递,显然这不是连接器期待的。

-Wl option

把选项option传递给连接器。如果option中含有逗号,就在逗号处分割成多个选项。

-ffunction-sections

将每个函数编译到独立的代码段

-fdata-sections

将全局/静态变量编译到独立的数据段

动态库

//单文件
gcc -fPIC -shared xxx.c -o libxxx.so
//多文件
gcc -fPIC -shared xxx1.c xxx2.c xxx3.c -o libxxx.so

使用
编译:
gcc -fPIC -shared hello.c -o libhello.so  
gcc main.c -L. -lhello -o main  

静态库

1 gcc hello.c -o hello.o  #这里没有使用-shared  
2 ar -crv libhello.a hello.o  #这里的ar相当于tar的作用,将多个目标打包。 

gcc main.c libhello.a -L. -o main  
或
gcc main.c -lhello -L. -static -o main  

gcc工具集

addr2line

给出一个可执行文件的内部地址,addr2line 使用文件中的调试信息将地址翻译成源代码文件名和行号。

ar

这是一个程序,可通过从文档中增加、删除和析取文件来维护库文件。通常使用该工具是为了创建和管理连接程序使用的目标库文档。

as

GNU 汇编器。实际上它是一族汇编器,因为它可以被编译或能够在各种不同平台上工作。

c++filt

程序接受被 C++编译程序转换过的名字(不是被重载的) ,而且将该名字翻译成初始形式。

elfedit

更新 ELF 文件的 ELF 头。

gprof

该程序会监督编译程序的执行过程,并报告程序中各个函数的运行时间,可以根据所提供的配置文件来优化程序。

ld

GNU 连接程序。该程序将目标文件的集合组合成可执行程序。

ld.bfd

到 ld 的硬链接。

libbfd

二进制文件描述器库。该程序是 binutils 包的一部分

libiberty

包含多个 GNU 程序会使用的途径,包括 getoptobstackstrerrorstrtol 和 strtoul。

libopcodes

一个库,用于处理 opcodes——处理器指令的 "可读文本" 版本;用于编制 objdump 这样的工具。

nlmconv

将可重定位的目标文件转换成 NetWare 可加载模块(NetWare Loadable Module,NLM) 。

nm

列出目标文件中定义的符号。

objcopy

将目标文件从一种二进制格式复制和翻译到另外一种。

objdump

显示一个或多个目标文件中保存的多种不同信息。

ranlib

创建和添加到 ar 文档的索引。该索引被 ld 使用来定位库中的模块。

readelf

从 ELF 格式的目标文件显示信息

size

列出目标文件中每个部分的名字和尺寸。

strings

浏览所有类型的文件,析取出用于显示的字符串。

strip

从目标文件或文档库中去掉符号表,以及其他调试所需的信息。

windres

Window 资源文件编译程序。

ld -Ttext 0x4000000 -c -o led.o led.c   指定text段地址

查看对应地址函数名 行号
addrline2 4005100 -e a.out -f

查看elf头信息
readelf -h a.out
查看所有信息
readelf -a a.out

列出文件中符号
nm main.o

objdump -d a.out 反汇编
objdump -D a.out 列出详细内容
objdump -x a.out 显示所有头文件信息
objdump -f a.out 查看入口文件

反汇bin格式文件

objdump -D -b binary -m i386 test.bin
objdump -D -b binary -m arm text.bin

objcopy目标格式转化

转化u-boot为二进制
objcopy --gap-fill=0xff -O binary u-boot u-boot.bin

size a.out 列出文件个段大小

strings a.out 列出可打印信息
strip  a.out 瘦身

file a.out 列出文件信息

链接脚本

描述

SECTIONS {
    ...
    secname start BLOCK(align) (NOLOAD):AT(ldard)
    {
        contents
    } > region:phdr=fill
}

secname段名
contents 决定哪些内容放在本段,可以是整个目标文件,也可以是目标文件中的某段(代码段、数据段等)

start      运行地址
AT(ldadr)  定义本段加载地址

例子
SECTIONS { 
    firtst 0x00000000 : { head.o init.o } 
    second 0x30000000 : AT(4096) { main.o } 
}

main.o放在4096(0x1000,是AT指定的,存储地址)开始处,但是它的运行地址在0x30000000,运行之前需要从0x1000(加载处)复制到0x30000000(运行处),此过程也就用到了读取Nand flash。

ld -Txxx.lds 
ld -Ttext 0x300000000

OUTPUT_FORMAT(DEFAULT,BIG,LITTLE) : 定义三种输出文件的格式(大小端)
OUTPUT_FORMAT("elf32&shy;littlearm", "elf32&shy;littlearm", "elf32&shy;littlearm")
;指定输出可执行文件是elf格式,32位ARM指令,小端
OUTPUT_ARCH(arm)
;指定输出可执行文件的平台为ARM
ENTRY(_start)
指定输出可执行文件的起始代码段为_start.

SECTIONS
{
        . = 0x00000000 ; 从0x0位置开始
        . = ALIGN(4) ; 代码以4字节对齐
        .text : ;指定代码段
        {
          cpu/arm920t/start.o (.text) ; 代码的第一个代码部分
          *(.text) ;其它代码部分
        }
        . = ALIGN(4) 
        .rodata : { *(.rodata) } ;指定只读数据段
        . = ALIGN(4);
        .data : { *(.data) } ;指定读/写数据段
        . = ALIGN(4);
        .got : { *(.got) } ;指定got段, got段式是uboot自定义的一个段, 非标准段
        __u_boot_cmd_start = . ;把__u_boot_cmd_start赋值为当前位置, 即起始位置
        .u_boot_cmd : { *(.u_boot_cmd) } ;指定u_boot_cmd段, uboot把所有的uboot命令放在该段.
        __u_boot_cmd_end = .;把__u_boot_cmd_end赋值为当前位置,即结束位置
        . = ALIGN(4);
        __bss_start = .; 把__bss_start赋值为当前位置,即bss段的开始位置
        .bss : { *(.bss) }; 指定bss段
        _end = .; 把_end赋值为当前位置,即bss段的结束位置
}

//内存区域描述
MEMORY
{
    rom (rx) : ORIGIN = 0, LENGTH = 256K
    ram (!rx) : org = 0×40000000, l = 4M
}


 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值