title: Extract detailed symbol information (struct members) from elf file compiled with ARM-GCC
body: <p>I’m using ARM-GCC 4.7.4 to compile Code for a Cortex-M4. For our Debug tool I need knowledge about names, types and addresses of all variables in human readable format (e.g. .txt). The map file provides most of the information, unfortunately not for structure contents like below: </p>
  
  <pre><code>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;
  </code></pre>
  
  <p>Therefore I tried the tools nm, readelf and objdump to get something out of the .elf file which is compiled with parameter –g3 in dwarf-2 format. Only with objdump I could find the information I searched for:</p>
  
  <pre><code>objdump –Wi myfile.elf &gt;symbols.txt
  </code></pre>
  
  <p>The following information about the typedef PI_REG can be found in symbols.txt file:</p>
  
  <pre><code> &lt;1&gt;&lt;38883&gt;: Abbrev Number: 2 (DW_TAG_base_type)
      &lt;38884&gt;   DW_AT_byte_size   : 4
      &lt;38885&gt;   DW_AT_encoding    : 4 (float)
      &lt;38886&gt;   DW_AT_name        : (indirect string, offset: 0x2c63e): float 
   &lt;1&gt;&lt;38891&gt;: Abbrev Number: 11 (DW_TAG_typedef)
      &lt;38892&gt;   DW_AT_name        : (indirect string, offset: 0xb336d): float32_t
      &lt;38896&gt;   DW_AT_decl_file   : 4 
      &lt;38897&gt;   DW_AT_decl_line   : 370   
      &lt;38899&gt;   DW_AT_type        : &lt;0x38883&gt;
   &lt;1&gt;&lt;390d7&gt;: Abbrev Number: 14 (DW_TAG_structure_type)
      &lt;390d8&gt;   DW_AT_byte_size   : 44    
      &lt;390d9&gt;   DW_AT_decl_file   : 6 
      &lt;390da&gt;   DW_AT_decl_line   : 26    
      &lt;390db&gt;   DW_AT_sibling     : &lt;0x39176&gt; 
   &lt;2&gt;&lt;390df&gt;: Abbrev Number: 16 (DW_TAG_member)
      &lt;390e0&gt;   DW_AT_name        : Ref   
      &lt;390e4&gt;   DW_AT_decl_file   : 6 
      &lt;390e5&gt;   DW_AT_decl_line   : 26    
      &lt;390e6&gt;   DW_AT_type        : &lt;0x38891&gt; 
      &lt;390ea&gt;   DW_AT_data_member_location: 2 byte block: 23 0 (DW_OP_plus_uconst: 0) 
   &lt;2&gt;&lt;390ed&gt;: Abbrev Number: 16 (DW_TAG_member)
      &lt;390ee&gt;   DW_AT_name        : Fdb   
      &lt;390f2&gt;   DW_AT_decl_file   : 6 
      &lt;390f3&gt;   DW_AT_decl_line   : 27    
      &lt;390f4&gt;   DW_AT_type        : &lt;0x38891&gt; 
      &lt;390f8&gt;   DW_AT_data_member_location: 2 byte block: 23 4 (DW_OP_plus_uconst: 4)
  </code></pre>
  
  <p>[left out structure members with offsets 6-32]</p>
  
  <pre><code> &lt;2&gt;&lt;39159&gt;: Abbrev Number: 15 (DW_TAG_member)
      &lt;3915a&gt;   DW_AT_name        : (indirect string, offset: 0xc1d9a): OutMin    
      &lt;3915e&gt;   DW_AT_decl_file   : 6 
      &lt;3915f&gt;   DW_AT_decl_line   : 35    
      &lt;39160&gt;   DW_AT_type        : &lt;0x38891&gt;
      &lt;39164&gt;   DW_AT_data_member_location: 2 byte block: 23 24 (DW_OP_plus_uconst: 36) 
   &lt;2&gt;&lt;39167&gt;: Abbrev Number: 16 (DW_TAG_member)
      &lt;39168&gt;   DW_AT_name        : Out   
      &lt;3916c&gt;   DW_AT_decl_file   : 6 
      &lt;3916d&gt;   DW_AT_decl_line   : 36    
      &lt;3916e&gt;   DW_AT_type        : &lt;0x38891&gt;
      &lt;39172&gt;   DW_AT_data_member_location: 2 byte block: 23 28 (DW_OP_plus_uconst: 40) 
   &lt;1&gt;&lt;39176&gt;: Abbrev Number: 3 (DW_TAG_typedef)
      &lt;39177&gt;   DW_AT_name        : (indirect string, offset: 0xc00d0): PI_REG    
      &lt;3917b&gt;   DW_AT_decl_file   : 6 
      &lt;3917c&gt;   DW_AT_decl_line   : 37    
      &lt;3917d&gt;   DW_AT_type        : &lt;0x390d7&gt; 
  
   &lt;1&gt;&lt;3c348&gt;: Abbrev Number: 29 (DW_TAG_variable)
      &lt;3c349&gt;   DW_AT_name        : (indirect string, offset: 0xc3ece): BU_Uctrl_Udc_PI_Reg
      &lt;3c34d&gt;   DW_AT_decl_file   : 1 
      &lt;3c34e&gt;   DW_AT_decl_line   : 40    
      &lt;3c34f&gt;   DW_AT_type        : &lt;0x39176&gt; 
      &lt;3c353&gt;   DW_AT_external    : 1 
      &lt;3c354&gt;   DW_AT_location    : 5 byte block: 3 fc 67 0 20 (DW_OP_addr: 200067fc)
  </code></pre>
  
  <p>If I want to get information about variables, e.g. the structure BU_Uctrl_Udc_PI_Reg, I have to do the following:</p>
  
  <pre><code>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
  </code></pre>
  
  <p>Frankly speaking, a script file, which automatically gathers the information as above mentioned, would be more complex than my application. Additionally I have to admit that I not really know how I could write such a script. Is there a more easy way to get this type of information? Is there maybe some parameter for the objdump which would help me with that, although I think I tried all the relevant ones? Or does a tool exist which is able to do this? In the end I need a table like this (additionally it would be nice to have all the enums which of course can also be found within the .elf file):</p>
  
  <pre><code>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
  </code></pre>
  
  <p>The tool Fromelf <a href="http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0477c/index.html" rel="noreferrer" title="Fromelf">http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0477c/index.html</a> (included in Keil µVision) with the parameter --text exactly delivers such a table, but unfortunately I can’t use this because it supposedly needs the .elf or in this case called .axf files compiled with Arm Compiler Toolchain to work. Additionally there are license issues.</p>
  
  <p>Thanks for any hints.</p>