size命令的sysv和berkeley格式差别

size命令使用说明#

size命令用于显示二进制文件的段(节)大小,其功能类似于readelf -S,详细的说明如下:

Copy
用法:size [选项] [文件] 显示二进制文件中节的大小 没有给出输入文件,默认为 a.out The options are: -A|-B --format={sysv|berkeley} Select output style (default is berkeley) -o|-d|-x --radix={8|10|16} Display numbers in octal, decimal or hex -t --totals Display the total sizes (Berkeley only) --common Display total size for *COM* syms --target=<bfdname> Set the binary file format @<file> Read options from <file> -h --help Display this information -v --version Display the program's version size:支持的目标: elf64-x86-64 elf32-i386 elf32-x86-64 a.out-i386-linux pei-i386 pei-x86-64 elf64-l1om elf64-k1om elf64-little elf64-big elf32-little elf32-big pe-x86-64 pe-i386 plugin srec symbolsrec verilog tekhex binary ihex

背景#

size支持两种输出格式sysvberkeley,对同一个文件,看看执行效果有什么差异

Copy
[GMPY@11:41 tmp]$size test text data bss dec hex filename 1810 584 8 2402 962 test [GMPY@11:41 tmp]$size --format=sysv test test : section size addr ... .text 640 4195616 ... .data 16 6295624 .bss 8 6295640 ... Total 2496

为了方便了解,这里补充以下3个重要段的功能:

段名 功能
BSS 存放程序中未初始化的全局变量的一块内存区域
DATA 存放程序中已初始化的全局变量的一块内存区域
TEXT/CODE 存放程序执行代码的一块内存区域

可以发现,test/data/bss段的大小不一致呀,我该相信哪一个?

源码#

size命令是binutils软件包提供的子命令,在GNU的官网中找到其最新源码(2.32)

废话不多说,下载,解压,直接看源码(binutils/size.c)

Copy
static void print_sizes (bfd *file) { if (show_common) calculate_common_size (file); if (berkeley_format) print_berkeley_format (file); else print_sysv_format (file); }

根据不同格式选择不同的打印方式,妥了,直接对比print_berkeley_formatprint_sysv_format

对比print_berkeley_format与print_sysv_format#

berkeley格式

Copy
static void print_berkeley_format (bfd *abfd) { ... bsssize = 0; datasize = 0; textsize = 0; /* * 获取bss/data/text段大小 * 找不到bfd_map_over_sections的定义,但猜测是一个宏 * 功能:对每一个段调用berkeley_sum函数进行处理 */ bfd_map_over_sections (abfd, berkeley_sum, NULL); /* 打印信息头 */ if (files_seen++ == 0) puts ((radix == octal) ? " text\t data\t bss\t oct\t hex\tfilename" : " text\t data\t bss\t dec\t hex\tfilename"); /* 打印具体的数值 */ rprint_number (7, textsize); putchar ('\t'); rprint_number (7, datasize); putchar ('\t'); rprint_number (7, bsssize); printf (((radix == octal) ? "\t%7lo\t%7lx\t" : "\t%7lu\t%7lx\t"), (unsigned long) total, (unsigned long) total); ... }

sysv格式

Copy
static void print_sysv_format (bfd *file) { svi_total = 0; svi_maxvma = 0; svi_namelen = 0; /* * 获取bss/data/text段大小 * 找不到bfd_map_over_sections的定义,但猜测是一个宏 * 功能:对每一个段调用sysv_internal_printer函数进行处理 */ bfd_map_over_sections (file, sysv_internal_printer, NULL); if (show_common) { svi_total += common_size; sysv_one_line ("*COM*", common_size, 0); } ...... }

好吧,我们关注的是两者的数值差异,需要进一步对比子函数berkeley_sumsysv_internal_printer

对比berkeley_sum和sysv_internal_printer#

berkeley格式

Copy
static void berkeley_sum (bfd *abfd ATTRIBUTE_UNUSED, sec_ptr sec, void *ignore ATTRIBUTE_UNUSED) { flagword flags; bfd_size_type size; flags = bfd_get_section_flags (abfd, sec); if ((flags & SEC_ALLOC) == 0) return; size = bfd_get_section_size (sec); /* 根据不同段的属性,进行不同类别的累加 */ if ((flags & SEC_CODE) != 0 || (flags & SEC_READONLY) != 0) /* text/code 段 */ textsize += size; else if ((flags & SEC_HAS_CONTENTS) != 0) /* data 段 */ datasize += size; else /* bss 段 */ bsssize += size; }

sysv格式:

Copy
static void sysv_one_line (const char *name, bfd_size_type size, bfd_vma vma) { printf ("%-*s ", svi_namelen, name); rprint_number (svi_sizelen, size); printf (" "); rprint_number (svi_vmalen, vma); printf ("\n"); } static void sysv_internal_printer (bfd *file ATTRIBUTE_UNUSED, sec_ptr sec, void *ignore ATTRIBUTE_UNUSED) { bfd_size_type size = bfd_section_size (file, sec); if ( ! bfd_is_abs_section (sec) && ! bfd_is_com_section (sec) && ! bfd_is_und_section (sec)) { svi_total += size; /* 分别打印出每一个段的信息 */ sysv_one_line (bfd_section_name (file, sec), size, bfd_section_vma (file, sec)); } }

结论#

实锤了,berkeley格式与sysv格式下的bss/data/text是不同的含义,其中

  • sysv是实打实的打印出每一个段的大小,等效于readelf -S
  • berkeley是统计的结果,把代码段和只读的段统计到text段,把有内容的段统计到data段,其他全归属bss段

在只需要知道分类的统计结果时用berkelay格式,在需要明细到每一个段时采用sysv格式

posted @   广漠飘羽  阅读(1039)  评论(0编辑  收藏  举报
编辑推荐:
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
· .NET 9 new features-C#13新的锁类型和语义
· Linux系统下SQL Server数据库镜像配置全流程详解
阅读排行:
· Sdcb Chats 技术博客:数据库 ID 选型的曲折之路 - 从 Guid 到自增 ID,再到
· 语音处理 开源项目 EchoSharp
· 《HelloGitHub》第 106 期
· Huawei LiteOS基于Cortex-M4 GD32F4平台移植
· mysql8.0无备份通过idb文件恢复数据过程、idb文件修复和tablespace id不一致处
点击右上角即可分享
微信分享提示
CONTENTS