【问题标题】:Extract detailed symbol information (struct members) from elf file compiled with ARM-GCC从使用 ARM-GCC 编译的 elf 文件中提取详细的符号信息(结构成员)
【发布时间】:2018-03-14 02:36:19
【问题描述】:

我正在使用 ARM-GCC 4.7.4 为 Cortex-M4 编译代码。对于我们的调试工具,我需要有关人类可读格式(例如 .txt)的所有变量的名称、类型和地址的知识。地图文件提供了大部分信息,不幸的是,不适用于如下结构内容:

typedef struct {    float32_t   Ref;        // Input:   Reference Value
            float32_t   Fdb;        // Variable:    Feedback Value
            float32_t   Err;        // Input:   Control Error
            float32_t   Kp;     // Parameter:   Gain of the Proportional Part
            float32_t   Up;         // Output:  Output of Proportional Part
            float32_t   Ki;     // Parameter:   Gain of the Integral Part
            float32_t   Ui;     // Output:  Output of the Integral Part
            float32_t   OutPreSat;  // Output:  Not saturated Output
            float32_t   OutMax;     // Parameter:   Maximum Output
            float32_t   OutMin;     // Parameter:   Minimum Output
            float32_t   Out;        // Output:  Saturated Output
        } PI_REG;

 PI_REG BU_Uctrl_Udc_PI_Reg = BU_UCTRL_UDC_PI_REG_INIT;

因此,我尝试使用 nm、readelf 和 objdump 工具从 .elf 文件中获取一些内容,该文件使用参数 –g3 以 dwarf-2 格式编译。只有使用 objdump 我才能找到我搜索的信息:

objdump –Wi myfile.elf >symbols.txt

关于typedef PI_REG的以下信息可以在symbol.txt文件中找到:

 <1><38883>: Abbrev Number: 2 (DW_TAG_base_type)
    <38884>   DW_AT_byte_size   : 4
    <38885>   DW_AT_encoding    : 4 (float)
    <38886>   DW_AT_name        : (indirect string, offset: 0x2c63e): float 
 <1><38891>: Abbrev Number: 11 (DW_TAG_typedef)
    <38892>   DW_AT_name        : (indirect string, offset: 0xb336d): float32_t
    <38896>   DW_AT_decl_file   : 4 
    <38897>   DW_AT_decl_line   : 370   
    <38899>   DW_AT_type        : <0x38883>
 <1><390d7>: Abbrev Number: 14 (DW_TAG_structure_type)
    <390d8>   DW_AT_byte_size   : 44    
    <390d9>   DW_AT_decl_file   : 6 
    <390da>   DW_AT_decl_line   : 26    
    <390db>   DW_AT_sibling     : <0x39176> 
 <2><390df>: Abbrev Number: 16 (DW_TAG_member)
    <390e0>   DW_AT_name        : Ref   
    <390e4>   DW_AT_decl_file   : 6 
    <390e5>   DW_AT_decl_line   : 26    
    <390e6>   DW_AT_type        : <0x38891> 
    <390ea>   DW_AT_data_member_location: 2 byte block: 23 0 (DW_OP_plus_uconst: 0) 
 <2><390ed>: Abbrev Number: 16 (DW_TAG_member)
    <390ee>   DW_AT_name        : Fdb   
    <390f2>   DW_AT_decl_file   : 6 
    <390f3>   DW_AT_decl_line   : 27    
    <390f4>   DW_AT_type        : <0x38891> 
    <390f8>   DW_AT_data_member_location: 2 byte block: 23 4 (DW_OP_plus_uconst: 4)

[遗漏了偏移量为 6-32 的结构成员]

 <2><39159>: Abbrev Number: 15 (DW_TAG_member)
    <3915a>   DW_AT_name        : (indirect string, offset: 0xc1d9a): OutMin    
    <3915e>   DW_AT_decl_file   : 6 
    <3915f>   DW_AT_decl_line   : 35    
    <39160>   DW_AT_type        : <0x38891>
    <39164>   DW_AT_data_member_location: 2 byte block: 23 24 (DW_OP_plus_uconst: 36) 
 <2><39167>: Abbrev Number: 16 (DW_TAG_member)
    <39168>   DW_AT_name        : Out   
    <3916c>   DW_AT_decl_file   : 6 
    <3916d>   DW_AT_decl_line   : 36    
    <3916e>   DW_AT_type        : <0x38891>
    <39172>   DW_AT_data_member_location: 2 byte block: 23 28 (DW_OP_plus_uconst: 40) 
 <1><39176>: Abbrev Number: 3 (DW_TAG_typedef)
    <39177>   DW_AT_name        : (indirect string, offset: 0xc00d0): PI_REG    
    <3917b>   DW_AT_decl_file   : 6 
    <3917c>   DW_AT_decl_line   : 37    
    <3917d>   DW_AT_type        : <0x390d7> 

 <1><3c348>: Abbrev Number: 29 (DW_TAG_variable)
    <3c349>   DW_AT_name        : (indirect string, offset: 0xc3ece): BU_Uctrl_Udc_PI_Reg
    <3c34d>   DW_AT_decl_file   : 1 
    <3c34e>   DW_AT_decl_line   : 40    
    <3c34f>   DW_AT_type        : <0x39176> 
    <3c353>   DW_AT_external    : 1 
    <3c354>   DW_AT_location    : 5 byte block: 3 fc 67 0 20 (DW_OP_addr: 200067fc)

如果我想获取有关变量的信息,例如BU_Uctrl_Udc_PI_Reg 的结构,我必须做到以下几点:

Find an entry called “DW_TAG_variable” and gather following information:
------------------------------------------------------------------------
 - DW_AT_name: The name is BU_Uctrl_Udc_PI_Reg
 - DW_OP_addr: Base address is 200067fc
 - DW_AT_type: The data type can be found at line 39176 

Search line 39176 and gather following information:
-----------------------------------------------------
 - It is a typedef (DW_TAG_typedef)
 - DW_AT_name: The typedef name is PI_REG
 - DW_AT_type: The definition can be found at line 390d7

Search line 390d7 and gather following information:
---------------------------------------------------
 - It is a structure (DW_TAG_structure_type) 
 - DW_AT_byte_size: It is 44 bytes wide

Search the structure Members in upcoming lines until 44 bytes are reached:
--------------------------------------------------------

1. Member (DW_TAG_member):
 - DW_AT_name: Ref
 - DW_AT_data_member_location: 200067fc + 0
 - DW_AT_type: The data type can be found at line 38891:
 - DW_TAG_typedef: float32_t
 - DW_AT_type: The data type can be found at line 38883: 
 - DW_TAG_base_type: float
 - DW_AT_byte_size: 4 bytes

2. Member (DW_TAG_member):
 - DW_AT_name: Fdb
 - DW_AT_data_member_location: 200067fc + 4
 - DW_AT_type: The data type can be found at line 38891:
 - DW_TAG_typedef: float32_t
 - DW_AT_type: The data type can be found at line 38883:
 - DW_TAG_base_type: float
 - DW_AT_byte_size: 4 bytes

[left out Members 3-9]

10. Member (DW_TAG_member):
 - DW_AT_name: OutMin
 - DW_AT_data_member_location: 200067fc + 36
 - DW_AT_type: The data type can be found at line 38891:
 - DW_TAG_typedef: float32_t
 - DW_AT_type: The data type can be found at line 38883:
 - DW_TAG_base_type: float
 - DW_AT_byte_size: 4 bytes

 11. Member (DW_TAG_member):
 - DW_AT_name: Out
 - DW_AT_data_member_location: 200067fc + 40
 - DW_AT_type: The data type can be found at line 38891:
 - DW_TAG_typedef: float32_t
 - DW_AT_type: The data type can be found at line 38883:
 - DW_TAG_base_type: float
 - DW_AT_byte_size: 4 bytes

坦率地说,自动收集上述信息的脚本文件会比我的应用程序更复杂。此外,我不得不承认我真的不知道如何编写这样的脚本。有没有更简单的方法来获取此类信息? objdump 是否有一些参数可以帮助我解决这个问题,尽管我认为我尝试了所有相关的参数?或者是否存在能够做到这一点的工具?最后,我需要一个这样的表(此外,最好有所有枚举,当然也可以在 .elf 文件中找到):

0x200067fc  float   BU_Uctrl_Udc_PI_Reg.Ref
0x20006800  float   BU_Uctrl_Udc_PI_Reg.Fdb
[…]
0x20006832  float   BU_Uctrl_Udc_PI_Reg.OutMin
0x20006836  float   BU_Uctrl_Udc_PI_Reg.Out

带有参数--text 的工具 Fromelf http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0477c/index.html(包含在 Keil µVision 中)正好提供了这样一个表格,但不幸的是我不能使用它,因为它应该需要 .elf 或在这种情况下称为 .axf 文件使用 Arm Compiler Toolchain 编译以工作。此外还有许可证问题。

感谢任何提示。

【问题讨论】:

  • Linux 内核源代码中有一个脚本和示例。 Kbuild's sed-y and cmd_offsets,样本输入为 asm-offsets.c。 'C' 被编译为汇编器(使用-S),并使用sed 命令对其进行处理以生成偏移列表。
  • @artless noise 谢谢你的评论。我试图熟悉 Kbuild sed-y 和 cmd_offsets,但遗憾的是它对我来说都是希腊语。如果有一个简单的解决方案可以被像我这样的浅脑 Windows 用户使用和理解,我仍然会很感激任何建议。此外,确定没有这样简单的解决方案会有所帮助。

标签: debugging gcc arm elf objdump


【解决方案1】:

您应该可以要求 GDB 为您打印此信息,例如

gdb -q a.out
(gdb) ptype PI_REG

【讨论】:

  • 感谢您的回答。 ptype PI_REG 有效地提供了我在问题开头所述的结构。缺点是,我没有地址,而且我必须知道每个结构或变量的名称。我需要的是一个包含所有全局符号的表,就像我在问题末尾所说的那样,它是在构建后自动生成的(独立于各个名称的知识)。不过,您对 GDB 的提示开启了许多新的可能性,也许我会在数千个 GDB 命令中找到 ONE。我很感激任何进一步的提示。
【解决方案2】:

pahole 是你需要的吗?它可以转储具有大小和偏移量的可变结构。

pahole −−reorganize −C foo xxx.out

struct foo {
int a; / 0 4 /
char c[4]; / 4 4 /
void b; / 8 8 /
long g; / 16 8 /
}; / size: 24, cachelines: 1 /
/ last cacheline: 24 bytes /
/ saved 8 bytes! /

【讨论】:

    【解决方案3】:

    您可以使用 eclipse CDT 的 gdb mi 接口以编程方式获取此信息。

    private def loadElfFile(String elfFilePath) {
        var plugin = new MIPlugin
    
        var file = new File(elfFilePath)
    
        var cmdFactory = new CommandFactory("mi2")
        session = plugin.createSession(
            MISession::PROGRAM,
            'gdb',
            cmdFactory,
            file,
            #[],
            true,
            new NullProgressMonitor
        )
    }
    

    您可以在此处查询全局变量及其类型。地址存储在值的 hexAddress 属性中。

    这种方法的问题是速度慢。一个有 50 个成员的结构需要将近 10 秒的时间来处理。查询所有结构需要几分钟。对于 IDE 工具用例(如模型转换),这是不切实际的。您必须深入了解精灵和矮人。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多