obj analysis2

本文介绍了GCC环境下的几个实用工具:ar、nm和objdump。ar用于库文件操作,nm用于列出目标文件的符号清单,objdump则提供强大的对象文件内容查看功能。通过这些工具,开发者可以更好地理解和控制编译生成的对象文件。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近由于工作需要,研究了以下gcc环境的相关工具。从wtzmax的专栏上发现了这篇 文章非常不错。 前言 如果普通编程不需要了解这些东西,如果想精确控制你的对象文件的格式或者你想查看一下文件对象里的内容以便作出某种判断,刚你可以看一下下面 的工具:objdump, nm, ar。当然,本文不可能非常详细的说明它们的使用方法和功能。如果你觉得本文不够清楚,你可以使用:man. 我的计划只是想让更多的人了解这些工具,以后在今后 的编程过程中能有所帮助。 操作系统: Linux 开始
  1. 库文件操作命令:ar ----非常好的东东。。让你能查看函数库里的详细情况和用多个对象文件生成一个库文件。
    1. 经常用法:
      1. ar -t libname.a //显示所有对象文件(.o文件)的列表.例: # ar t libtest.a libtest1.o libtest2.o
      2. ar -rv libname.a  objfile1.o objfile2.o ... objfilen.o  //把objfile1.o--objfilen.o打包成一个库文件
    2. ar 选项 d:从库中删除模块。按模块原来的文件名指定要删除的模块。如果使用了任选项v则列出被删除的每个模块。 m:该操作是在一个库中移动成员。当库中如果有若干模块有相同的符号定义(如函数定义),则成员的位置顺序很重要。如果没有指定任选项,任何指定的成员将移到库的最后。也可以使用'a','b',或'I'任选项移动到指定的位置。 p:显示库中指定的成员到标准输出。如果指定任选项v,则在输出成员的内容前,将显示成员的名字。如果没有指定成员的名字,所有库中的文件将显示出来。 q:快速追加。增加新模块到库的结尾处。并不检查是否需要替换。'a','b',或'I'任选项对此操作没有影响,模块总是追加的库的结尾处。如果使用了任选项v则列出每个模块。 这时,库的符号表没有更新,可以用'ar s'或ranlib来更新库的符号表索引。 r:在库中插入模块(替换)。当插入的模块名已经在库中存在,则替换同名的模块。如果若干模块中有一个模块在库中不存在,ar显示一个错误消息,并不替换其他同名模块。默认的情况下,新的成员增加在库的结尾处,可以使用其他任选项来改变增加的位置。 t:显示库的模块表清单。一般只显示模块名。 x:从库中提取一个成员。如果不指定要提取的模块,则提取库中所有的模块。   下面在看看可与操作选项结合使用的任选项: a:在库的一个已经存在的成员后面增加一个新的文件。如果使用任选项a,则应该为命令行中membername参数指定一个已经存在的成员名。 b:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项b,则应该为命令行中membername参数指定一个已经存在的成员名。 c:创建一个库。不管库是否存在,都将创建。 f:在库中截短指定的名字。缺省情况下,文件名的长度是不受限制的,可以使用此参数将文件名截短,以保证与其它系统的兼容。 i:在库的一个已经存在的成员前面增加一个新的文件。如果使用任选项i,则应该为命令行中membername参数指定一个已经存在的成员名(类似任选项b)。 l:暂未使用 N:与count参数一起使用,在库中有多个相同的文件名时指定提取或输出的个数。 o:当提取成员时,保留成员的原始数据。如果不指定该任选项,则提取出的模块的时间将标为提取出的时间。 P:进行文件名匹配时使用全路径名。ar在创建库时不能使用全路径名(这样的库文件不符合POSIX标准),但是有些工具可以。 s:写入一个目标文件索引到库中,或者更新一个存在的目标文件索引。甚至对于没有任何变化的库也作该动作。对一个库做ar s等同于对该库做ranlib。 S:不创建目标文件索引,这在创建较大的库时能加快时间。 u:一般说来,命令ar r...插入所有列出的文件到库中,如果你只想插入列出文件中那些比库中同名文件新的文件,就可以使用该任选项。该任选项只用于r操作选项。 v:该选项用来显示执行操作选项的附加信息。 V:显示ar的版本.
  2. nm --列出目标文件(.o)的符号清单。。NND,太激动了。刚知道此命令时让我三天没睡好觉。我就使劲用了一把。
    1. 常用法:
      1. nm -s filename.a/filename.o/a.out  里边所有的符号列表一清二楚。例: # nm -s a.out 080495b8 A __bss_start 08048334 t call_gmon_start 080495b8 b completed.5751 080494b8 d __CTOR_END__ 080494b4 d __CTOR_LIST__ 080495ac D __data_start 080495ac W data_start 08048450 t __do_global_ctors_aux 08048360 t __do_global_dtors_aux 080495b0 D __dso_handle 080494c0 d __DTOR_END__ 080494bc d __DTOR_LIST__ 080494c8 d _DYNAMIC 080495b8 A _edata 080495bc A _end 0804847c T _fini 08048498 R _fp_hw 08048390 t frame_dummy 080484b0 r __FRAME_END__ 08049594 d _GLOBAL_OFFSET_TABLE_          w __gmon_start__ 0804844c T __i686.get_pc_thunk.bx 080482b8 T _init 080494b4 a __init_array_end 080494b4 a __init_array_start 0804849c R _IO_stdin_used 080494c4 d __JCR_END__ 080494c4 d __JCR_LIST__          w _Jv_RegisterClasses 080483e0 T __libc_csu_fini 080483f0 T __libc_csu_init          U __libc_start_main@@GLIBC_2.0 080483b4 T main 080495b4 d p.5749          U puts@@GLIBC_2.0 08048310 T _start
    2. 选项/属性: -a或--debug-syms:显示调试符号。 -B:等同于--format=bsd,用来兼容MIPS的nm。 -C或--demangle:将低级符号名解码(demangle)成用户级名字。这样可以使得C++函数名具有可读性。 -D或--dynamic:显示动态符号。该任选项仅对于动态目标(例如特定类型的共享库)有意义。 -f format:使用format格式输出。format可以选取bsd、sysv或posix,该选项在GNU的nm中有用。默认为bsd。 -g或--extern-only:仅显示外部符号。 -n、-v或--numeric-sort:按符号对应地址的顺序排序,而非按符号名的字符顺序。 -p或--no-sort:按目标文件中遇到的符号顺序显示,不排序。 -P或--portability:使用POSIX.2标准输出格式代替默认的输出格式。等同于使用任选项-f posix。 -s或--print-armap:当列出库中成员的符号时,包含索引。索引的内容包含:哪些模块包含哪些名字的映射。 -r或--reverse-sort:反转排序的顺序(例如,升序变为降序)。 --size-sort:按大小排列符号顺序。该大小是按照一个符号的值与它下一个符号的值进行计算的。 -t radix或--radix=radix:使用radix进制显示符号值。radix只能为"d"表示十进制、"o"表示八进制或"x"表示十六进制。 --target=bfdname:指定一个目标代码的格式,而非使用系统的默认格式。 -u或--undefined-only:仅显示没有定义的符号(那些外部符号)。 -l或--line-numbers:对每个符号,使用调试信息来试图找到文件名和行号。对于已定义的符号,查找符号地址的行号。对于未定义符号,查找指向符号重定位入口的行号。如果可以找到行号信息,显示在符号信息之后。 -V或--version:显示nm的版本号。 --help:显示nm的任选项。
  3. objdump  文件命令功能强的惊人。能实现上述两个命令(ar,nm)的很多功能。它主要是查看对象文件的内容信息。
    1. 常用法:
      1. objdump -h file<.o,.a,.out>//查看对象文件所有的节sections.例如: # objdump -h libtest1.o libtest1.o:     file format elf32-i386 Sections: Idx Name          Size      VMA       LMA       File off  Algn   0 .text         00000014  00000000  00000000  00000034  2**2                   CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE   1 .data         00000000  00000000  00000000  00000048  2**2                   CONTENTS, ALLOC, LOAD, DATA   2 .bss          00000000  00000000  00000000  00000048  2**2                   ALLOC   3 .rodata       0000000e  00000000  00000000  00000048  2**0                   CONTENTS, ALLOC, LOAD, READONLY, DATA   4 .comment      0000001f  00000000  00000000  00000056  2**0                   CONTENTS, READONLY   5 .note.GNU-stack 00000000  00000000  00000000  00000075  2**0                   CONTENTS, READONLY
      2. objdump -t 查看对象文件所有的符号列表,相当于 nm -s objfilename,如: # objdump -t libtest1.o libtest1.o:     file format elf32-i386 SYMBOL TABLE: 00000000 l    df *ABS*  00000000 libtest1.c 00000000 l    d  .text  00000000 .text 00000000 l    d  .data  00000000 .data 00000000 l    d  .bss   00000000 .bss 00000000 l    d  .rodata        00000000 .rodata 00000000 l    d  .note.GNU-stack        00000000 .note.GNU-stack 00000000 l    d  .comment       00000000 .comment 00000000 g     F .text  00000014 print_test1 00000000         *UND*  00000000 puts
    2. 更多信息请查看选项: --archive-headers -a 显示档案库的成员信息,与 ar tv 类似     objdump -a libpcap.a     和 ar -tv libpcap.a 显示结果比较比较     显然这个选项没有什么意思。 --adjust-vma=offset     When  dumping  information, first add offset to all     the section addresses.  This is useful if the  sec-     tion  addresses  do  not correspond  to the symbol     table, which can happen when  putting  sections  at     particular  addresses when using a format which can     not represent section addresses, such as a.out. -b bfdname --target=bfdname     指定目标码格式。这不是必须的,objdump能自动识别许多格式,     比如:objdump -b oasys -m vax -h fu.o     显示fu.o的头部摘要信息,明确指出该文件是Vax系统下用Oasys     编译器生成的目标文件。objdump -i将给出这里可以指定的     目标码格式列表 --demangle -C 将底层的符号名解码成用户级名字,除了去掉所有开头    的下划线之外,还使得C++函数名以可理解的方式显示出来。 --debugging     显示调试信息。企图解析保存在文件中的调试信息并以C语言     的语法显示出来。仅仅支持某些类型的调试信息。 --disassemble -d 反汇编那些应该还有指令机器码的section --disassemble-all -D 与 -d 类似,但反汇编所有section --prefix-addresses     反汇编的时候,显示每一行的完整地址。这是一种比较老的反汇编格式。     显示效果并不理想,但可能会用到其中的某些显示,自己可以对比。 --disassemble-zeroes     一般反汇编输出将省略大块的零,该选项使得这些零块也被反汇编。 -EB -EL --endian={big|little}     这个选项将影响反汇编出来的指令。     little-endian就是我们当年在dos下玩汇编的时候常说的高位在高地址,     x86都是这种。 --file-headers -f 显示objfile中每个文件的整体头部摘要信息。 --section-headers --headers -h 显示目标文件各个section的头部摘要信息。 --help 简短的帮助信息。 --info -i 显示对于 -b 或者 -m 选项可用的架构和目标格式列表。 --section=name -j name 仅仅显示指定section的信息 --line-numbers -l 用文件名和行号标注相应的目标代码,仅仅和-d、-D或者-r一起使用    使用-ld和使用-d的区别不是很大,在源码级调试的时候有用,要求    编译时使用了-g之类的调试编译选项。 --architecture=machine -m machine     指定反汇编目标文件时使用的架构,当待反汇编文件本身没有描述     架构信息的时候(比如S-records),这个选项很有用。可以用-i选项     列出这里能够指定的架构 --reloc -r 显示文件的重定位入口。如果和-d或者-D一起使用,重定位部分以反汇    编后的格式显示出来。 --dynamic-reloc -R 显示文件的动态重定位入口,仅仅对于动态目标文件有意义,比如某些    共享库。 --full-contents -s 显示指定section的完整内容。     objdump --section=.text -s inet.o | more --source -S 尽可能反汇编出源代码,尤其当编译的时候指定了-g这种调试参数时,    效果比较明显。隐含了-d参数。 --show-raw-insn     反汇编的时候,显示每条汇编指令对应的机器码,除非指定了     --prefix-addresses,这将是缺省选项。 --no-show-raw-insn     反汇编时,不显示汇编指令的机器码,这是指定 --prefix-addresses     选项时的缺省设置。 --stabs     Display the contents of the .stab, .stab.index, and     .stab.excl sections from an ELF file.  This is only     useful  on  systems  (such as Solaris 2.0) in which     .stab debugging symbol-table entries are carried in     an ELF section.  In most other file formats, debug-     ging  symbol-table  entries  are interleaved  with     linkage symbols, and are visible in the --syms output. --start-address=address     从指定地址开始显示数据,该选项影响-d、-r和-s选项的输出。 --stop-address=address     显示数据直到指定地址为止,该选项影响-d、-r和-s选项的输出。 --syms -t 显示文件的符号表入口。类似于nm -s提供的信息 --dynamic-syms -T 显示文件的动态符号表入口,仅仅对动态目标文件有意义,比如某些    共享库。它显示的信息类似于 nm -D|--dynamic 显示的信息。 --version 版本信息     objdump --version --all-headers -x 显示所有可用的头信息,包括符号表、重定位入口。-x 等价于    -a -f -h -r -t 同时指定。     objdump -x inet.o
### 解决 'reliability_analysis' 对象不可下标的问题 当遇到 `'reliability_analysis'` 对象不可下标的错误时,通常是因为尝试像访问列表或字典那样使用索引来访问对象属性。Python 中的对象只有在其定义中实现了 `__getitem__()` 方法的情况下才支持通过方括号 `[ ]` 访问。 如果希望修复此问题并能够按预期工作,则可以考虑以下几种方法: #### 方法一:修改类实现 确保 `ReliabilityAnalysis` 类已经重写了 `__getitem__()` 方法来允许基于键或索引的访问方式。例如: ```python class ReliabilityAnalysis: def __init__(self, data): self.data = data def __getitem__(self, key): return self.data[key] # 使用实例化后的可靠性分析对象 analysis_instance = ReliabilityAnalysis({'key': 'value'}) print(analysis_instance['key']) ``` 这种方法使得可以直接利用方括号语法获取内部存储的数据[^1]。 #### 方法二:转换为可迭代数据结构 另一种解决方案是将 `reliability_analysis` 转换成一个更易于操作的形式,比如将其转成 DataFrame 或者字典等容器类型后再做进一步处理。这可以通过调用相应的方法或将整个对象序列化到 JSON 字符串再解析回来完成。 ```python import json def convert_to_dict(reliability_analysis_obj): # 假设 reliability_analysis_obj 有一个 to_json() 方法用于导出其状态 as_string = reliability_analysis_obj.to_json() converted_data = json.loads(as_string) return converted_data converted_reliability_analysis = convert_to_dict(reliability_analysis) # 现在可以从转换后的字典中提取所需的信息 for k, v in converted_reliability_analysis.items(): print(f"{k}: {v}") ``` 上述代码片段展示了如何先将自定义类型的对象转化为标准 Python 数据结构以便于后续的操作[^2]。 #### 方法三:检查现有 API 接口 有时开发者可能误解了库函数的实际用途而试图以不恰当的方式对其进行操作。因此建议查阅官方文档确认是否有提供其他更适合当前需求的功能接口可用。对于某些特定情况下,或许根本不需要直接对原始对象执行切片操作而是应该寻找替代方案。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值