对于每一个段,输出了 Offset、VirtAddr 等描述当前段的信息。Offset 表示当前段在二进制文件中的开始位置,FileSiz 表示当前段的大小。...回忆前面我们在 ELF 文件头中看到 Entry point address 显示的入口地址为 0x401040。这说明,程序的入口地址就是 .text 段的地址。...4.4 执行 Segment 加载 接下来,加载器会将 ELF 文件中的 LOAD 类型的 Segment 都加载到内存里来。使用 elf_map 在虚拟地址空间中为其分配虚拟内存。...这个参数有这么几种可能 值为 0,就是直接按照 ELF 文件中的地址在内存中进行映射 值为对齐到整数页的开始,物理文件中可能为了可执行文件的大小足够紧凑,而不考虑对齐的问题。...对于 ELF 文件来说,它的加载器在内核中的定义为 elf_format,其二进制加载入口是 load_elf_binary 函数。
我们先从镜像的结构开始,后面逐一介绍 ROM->SPL->UBoot->Kernel 的全过程。 ELF 文件 在介绍加载镜像之前,需要先了解下 ELF 文件的格式定义。...有 3 种类型的 ELF 文件: 目标文件:被链接器读取,用来产生一个可执行文件或者共享库文件; 可执行文件:被操作系统中的加载器从硬盘上读取,载入到内存中去执行; 共享库文件:在动态链接的时候,由 ld-linux.so...data 段 数据段,通常是指用来存放程序中已初始化的全局变量的一块内存区域。数据段属于静态内存分配。 bss 段 通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。...文件 vmlinux 的分布: 镜像的生成 ELF 文件格式是 Linux 环境下的可执行文件格式,在 Linux 环境下,加载器根据 ELF 文件里的地址信息,就可以把它加载到内存指定的地址运行,...但是系统启动过程中并没有 ELF 文件的执行环境,需要将 ELF 文件转换为二进制纯指令文件,即 Image。
例如lib*.o文件。 2.2 可执行目标文件(a.out文件) 包含二进制代码和数据,可直接被加载器加载执行。例如编译好的可执行文件a.out。...2.如果用于加载执行(可执行文件),则加载器则将把ELF文件看作是程序头表描述的段的集合,一个段可能包含多个节,节头表可选。 4....从程序执行角度看ELF文件 与可重定位目标文件不同: 1.ELF头中,字段 e_entry给出执行程序时第一条指令的地址,而在可重定位文件中,此字段为0。 ...第二可装入段:第0xe10 ~0x104f的长度为0x240字节的.data节和磁盘中不占存储空间的.bss节,映射到虚拟地址0x600e10开始长度为0x248字节的存储区域,在0x248=584B存储区中...从编译链接角度看,可重定位目标文件中包含ELF头、各个节以及节头表。可执行目标文件中包含ELF头、程序头表(段头表)以及各种节组成的段。
编译完成之后,需要的步骤就是 链接.编译仅仅转换源代码到二进制的机器码,但是并没有把程序运行需要的所有资源整合到一起,所以编译后的"目标文件"是没办法直接运行的;在实际的项目中,通常是由多个源代码文件,...这些目标文件 和需要的其他资源被整合到一起,最终才生成我们常见的程序(典型的比如windows下的各种exe文件,linux 下的elf LSB executable 文件,linux 下的elf LSB...链接后的文件既有segment head ,也有section head信息;以/usr/bin/cat 这个程序为例,着重了解下segment的地址怎么计算: [root@www ~]# readelf...上述的结果中有一个叫做: VirtAddr的值,这个字段表示 segment对应的“程序虚拟地址”, 也有叫做“文件虚拟地址”的,我觉得都是一个意思:就是说 这个segment 是从这个 虚拟地址开始的...链接后的文件有segment的描述,也有section描述,而编译后的文件只有section. 2. 只有type 为“LOAD”的segment 会在程序加载的时候被载入内存 3.
大家好,我是张晋涛。 我们用 Go 构建的二进制文件中默认包含了很多有用的信息。...其实 Linux 系统中二进制文件包含额外的信息并非 Go 所特有的,下面我将具体介绍其内部原理和实现。当然,用 Go 构建的二进制文件仍是本文的主角。...64 位可执行文件使用的 ELF 文件格式的结构和 Linux 内核源码中对它的定义。...具体实现 在前面的内容中,关于如何使用 readelf 和 objdump 命令获取二进制文件的的 Go 版本和 Module 信息就已经涉及到了其具体的原理。这里我来介绍下 Go 代码的实现。...mod = mod[16 : len(mod)-16] } else { mod = "" } 总结 我在这篇文章中分享了如何从 Go 的二进制文件中获取构建它时所用的 Go 版本及它依赖的模块信息
近期研究了一下elf文件格式,发现好多资料写的都比較繁琐,可能会严重打击学习者的热情,我把自己研究的结果和大家分享,希望我的描写叙述可以简洁一些。...进程的创建和执行进程的创建和执行: 大致经历了下面步骤 1.用户请求执行程序时,操作系统会读取存储在磁盘上的可执行文件,在linux系统上这个文件就是我们的elf格式文件,为用户分配...依据文件的信息指示,把不同的文件内容放到为你分配的这3G虚拟内存 3....是0,FileSiz是0x0,MemSiz是0xbc, VirtAddr是0x400000,Flags是R E,表示载入起将把elf文件里从0字节開始直到oxbc处的内容载入到虚拟内存中的0x400000...设置该内存的权限是RE(可读,可运行) 为什么数据段的事实上地址是0x6000bc,而不是0x6000000呢,这是由Align决定的,Align决定内存和磁盘以1M为单位进行映射,在文件里
在本文中,我将尝试解释在Linux系统中动态加载共享库的内部工作原理。 这边文章不是一个如何引导,尽管它确实展示了如何编译和调试共享库和可执行文件。为了解动态加载的内部工作方式进行了优化。...可以静态地执行此操作-并将random库中的所有符号直接加载到main可执行文件中。 我们告诉编译器我们要使用librandom文件。由于它是动态加载的,为什么我们在编译时需要它?...总之,ELF文件包含: ELF Header 文件数据,可能包含: 程序header表(段头列表) 段头表(列表章节标题) 以上两个标题指向的数据 ELF标头指定程序标头表中段的大小和数量,以及节标头表中段的大小和数量...每个这样的表都由固定大小的条目组成(我使用该条目在适当的表中描述段标题或节标题)。条目是标题,并且包含指向该段或节的实际主体位置的指针(文件中的偏移量)。该主体存在于文件的数据部分中。...在他们的:因为我们感兴趣的是这个文件的特定部分,我解释这个程序头表,ELF文件可以有(和共享特别库必须具有)段头一个描述段型的PT_DYNAMIC。
vmlinux 属于 ELF 文件,要想了解如何启动 vmlinux,首先需要知道 ELF 的格式。 ELF text段 代码段,通常是指用来存放程序执行代码的一块内存区域。...bss段 通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。BSS段属于静态内存分配。...init段 linux定义的一种初始化过程中才会用到的段,一旦初始化完成,那么这些段所占用的内存会被释放掉,后续会继续说明。...aarch64 架构平台的 ELF 可执行文件,其程序入口的地址为 0xffff800010000000,此段对应的 section 为.head.text .text .got.plt.........接下来的代码是: 上图中的宏 HEAD_TEXT 定义在文件 include/asm-generic/vmlinux.lds.S 中,其定义为 .head.text 文本段。
但是可能大多数人并不清楚为什么会发生段错误,那么本篇文章就来说说:从只读数据被映射到进程的虚拟地址空间到写访问发生段错误的整个过程,力求让大家搞清楚这里面的底层内核原理,讲完整个过程之后我们来通过一个示例代码让修改只读数据变得合法...也可以发现编译器将.text和.rodata 放在一个段中,然后用一个程序头表项来描述,段的类型为load(需要加载到进程地址空间), Flags为只读可执行。...elf_prot, elf_flags, total_size); //通过mmap映射vma 在load_elf_binary中会解析可执行文件的文件头,找到程序头表,然后解析程序头表的每一个表项,...对每一个可加载的段进行映射,这里有两个段(上面通过readelf -l工具可以看到), 分配映射为只读可执行和可读可写不可执行,然后我们就可以通过cat /proc/1727/maps 看到我们映射的段...我写只读数据试试 映射好了vma只能说明我们有一段虚拟内存关联了可执行文件的一个段,并没有分配物理内存,实际上这个过程发生在第一次访问只读数据或者访问.text的时候发生预读等操作的时候。
大家好,又见面了,我是你们的朋友全栈君。 简单了解下ELF文件的格式。...x e_phnum,如果文件中没有程序头表该项为0; e_shentsize:节表中单项的大小,表中每一项的大小相同; e_shnum:节表中项的数量; e_shstrndx:节表中节名的索引,如果文件没有该表则该项为...(5):保留段; PT_PHDR(6):保存程序头表本身的位置和大小,当前段不能在文件中出现一次以上,且仅仅当程序表头为内存映像的一部分时起作用,它必须在所有加载项目之前; [PT_LPROC(0x70000000...可加载的进程段的p_vaddr和- p_offset取值必须合适,相对于对页面大小的取模而言; 0和1表示不需要对齐; 其他值必须为2的幂次方,且必须 p _ a d d r ∣ p _ a l i...如果文件具有包含重定位的可加载段,则这些部分的属性将包括 SHF_ALLOC 位;否则,该位将关闭。通常,名称由 重定位适用的部分。
中,因此当内核的elf可执行文件被加载时,.rodata,.data和.bss节都会被合并为一个data段。...段表是ELF文件中除了文件头以外最重要的结构,它描述了ELF的各个段的信息,比如每个段的段名、段的长度、在文件中的偏移、读写权限及段的其他属性。...ELF文件中,段的权限往往只有为数不多的几种组合,基本上是三种: 以代码段为代表的权限为可读可执行的段。 以数据段和BSS段为代表的权限为可读可写的段。 以只读数据段为代表的权限为只读的段。...ELF二进制文件以四个字节的“幻数”0x7F、“E”、“L”、“F”或ELF_MAGIC开始(*kernel/elf.h*:3)。如果ELF头有正确的幻数,exec假设二进制文件格式良好。...exec将ELF文件中的字节加载到ELF文件指定地址的内存中。用户或进程可以将他们想要的任何地址放入ELF文件中。因此exec是有风险的,因为ELF文件中的地址可能会意外或故意的引用内核。
如果用于加载执行(可执行文件),则加载器则将把elf文件看作是程序头表描述的段的集合,一个段可能包含多个节,节头表可选。 如果是共享文件,则两者都含有。...-t 或 --section-details:显示节的详细信息(-S的)。 -s 或 --syms 或 --symbols:显示符号表段中的项(如果有的话)。...-u 或 --unwind:显示unwind段信息。当前只支持IA64 ELF的unwind段信息。 -d 或 --dynamic:显示动态段的信息。...-D 或 --use-dynamic:使用动态段中的符号表显示符号,而不是使用符号段。...-x 或 --hex-dump=:以16进制方式显示指定段内内容。number指定段表中段的索引,或字符串指定文件中的段名。
在我之前的系列文章中,我介绍了eBPF 生态系统的基本构建模块,简要介绍了XDP,并展示了它与 eBPF 基础设施如何密切合作,以便在网络堆栈中引入一个快速处理的数据路径。...只要符号表可用,就可以对二进制文本段中出现的任何符号应用动态跟踪。在运行的二进制文件上检测 Go 或 Rust stdlib 函数调用就是通过这种方式完成的。...两个宏都接受两个强制参数,如提供者/探测名称,后面跟着你希望从跟踪点查询的任何值。编译器将把USDT 跟踪点塞进目标二进制文件 ELF 段中 。...编译器和跟踪工具之间规定了 USDT 元数据所在的位置必须存在 .note.stapstd 段。 USDT 跟踪工具检查 ELF 段,并在被转为 int3 中断的跟踪点位置上放置一个断点。...Java语言 现代 JVM 版本自带对 USDT 的内置支持。所有探针都是用 libjvm 共享对象带来的。我们可以在 ELF 段中到可用的追踪点。
elf header相关的做的比较挫,求其他大神思路。 FPU优化k计算 普通md5一般使用预计算的K实现,而64个uint32_t就导致了,额外256字节的空间。...这些完全可以省掉,由于进程执行时,已经完全将自身镜像加载到内存地址。因此可以直接从汇编的基址读取内存,即为文件内容。 避免memcpy 正常md5流程中,需要对message进行padding。...因此需要按64字节为一块,一块一块拷贝到临时buffer中单独处理。...这里可以通过将program header中的flags设置为可写,并将memsize设置的比filesize大一些,方便直接在内存中原地做padding。...在代码中include这个额外生成的汇编文件,最后直接赋值就可以了。
漏洞点 参考资料 我们先通过详情来看漏洞点,根据漏洞详情中的介绍,该漏洞位于 glibc 的elf/dl-tunables.c文件中的parse_tunables函数: static void parse_tunables...= '\0') p += len + 1; } } 调用该函数的代码位于该文件的__tunables_init函数中: void __tunables_init (char **envp...我对这种利用方式深感好奇,认为这一利用思路非常巧妙,仅需覆盖一个栈地址即可替换 libc 的加载路径。 4.接下来我花一些时间去一步步调试,最后理解清楚该利用思路。...而漏洞发现者找到的利用链,利用到了link_map->l_info[DT_RPATH]成员变量,相关代码位于elf/dl-load.c文件的_dl_init_paths函数: void _dl_init_paths...,我们构造的link_map结构是没问题的,但是怎么让link_map申请的内存段为我们设置好的这段呢?
e_phoff:八个字节,40 00 00 00 00 00 00 00表示程序头表的偏移地址在 00 00 00 00 00 00 00 40处(这个地址是相对于本示例中的elf文件hellowrold...e_phentsize:两个字节,38 00表示重定位文件每个程序头表大小为00 38(56字节,从上面的e_phoff这个字段可以看出,程序表头是在elf文件头的后面)。...e_ehentsize:两个字节,40 00 表示段头大小为00 40(64字节),section header table中每个header的大小。...e_shstrndx:两个字节,1b 00 表示段表字符串在段表中的索引号,.shstrab段的段表索引号为00 1b,即27。...可执行文件中,一个program header描述的内容称为一个段(segment)。
这个时候,使用readelf工具来查看这个可执行文件中的段信息(segment): 上图中的红色矩形框中,第二个段的地址为什么是 0x080e_9f5c?...这里就不再赘述了,只要记住2点: 从编译器的角度看,ELF 文件是由很多的节(Section)组成的; 从程序加载器的角度看,ELF 文件是又很多的段(Segment)组成的; 其实它俩没有本质区别,只不过是链接器在链接阶段...从内存映射的角度来看: 操作系统在把一个可执行程序加载到系统中时,把ELF文件中每个段的内容读取到物理内存中,然后把这个物理内存映射到该段对应的虚拟地址上(VirtAddr)。...由于操作系统在把test文件读取到物理内存的时候,从文件开始代码段的0x00000地址开始读取,按照4KB为一个单位存放到一个物理页中。...readelf工具读所显示的:数据段加载到虚拟地址空间中的开始地址,如下所示: 至此,就解释了文章开头提出的问题!
如何将二进制文件作为数据添加到自己程序中?...》 一种方法是将想二进制文件生成c代码,与项目一起编译,这方法对于小数据没问题,但如果二进制文件太大,生成的c代码更是巨大,增加编译器负担,好处就是完全没有跨平台问题。...objcopy本身就提供了二进制数据转成obj文件的能力 执行如下指令即可将 file.bin 生成 elf32-i386 格式的obj文件 file.o objcopy -I binary -O elf32...显示ld默认的输出格式 NDK 在NDK(NDK 19c)下需要找到正确的ld或objcopy才行, 之前我使用 $android-ndk-r19c/toolchains/llvm/prebuilt\...上的bin2coff(我没测试)。
可以看出来:这个 Section 在 ELF 文件中的偏移地址是 0x0016ed,长度是 0x00010a 个字节。 下面,我们从 ELF header 的二进制数据中,来推断这信息。...p_type: 段的类型,1: 表示这个段需要加载到内存中; p_offset: 段在 ELF 文件中的偏移地址,这里值为 0,表示这个段从 ELF 文件的头部开始; p_vaddr:段加载到内存中的虚拟地址...0x08048000; p_paddr:段加载的物理地址,与虚拟地址相同; p_filesz: 这个段在 ELF 文件中,占据的字节数,0x0744 = 1860 个字节; p_memsz:这个段加载到内存中...注意:有些段是不需要加载到内存中的; 经过上述分析,我们就知道:从 ELF 文件的第 1 到 第 1860 个字节,都是属于这个 LOAD 段的内容。...在被执行时,这个段需要被加载到内存中虚拟地址为 0x08048000 这个地方,从这里开始,又是一个全新的故事了。
领取专属 10元无门槛券
手把手带您无忧上云