Home > Community > Blogs > System Design and Verification > the dwarf debugging file format
 
Login with a Cadence account.
Not a member yet?
Create a permanent login account to make interactions with Cadence more conveniennt.

Register | Membership benefits
Get email delivery of the System Design and Verification blog (individual posts).
 

Email

* Required Fields

Recipients email * (separate multiple addresses with commas)

Your name *

Your email *

Message *

Contact Us

* Required Fields
First Name *

Last Name *

Email *

Company / Institution *

Comments: *

The DWARF Debugging File Format

Comments(3)Filed under: System Design and Verification, debugging, ARM, ELF, DWARF

The Chronicles of Narnia has always been one my favorite series of books. Today, I'm not going to talk about dwarfs such as Trumpkin, the dwarf that appeared in Prince Caspian (check out the latest movie), but instead something called the DWARF Debugging Standard. DWARF is a file format used by compilers and debuggers to enable source level debugging. A compiler writes information into a generated executable file and a debugger reads the information so that when the program is run it can relate the execution back to the source code. These details are usually not important for somebody writing software for a workstation, but most engineers understand the basic concept that to use gdb to debug a program compiled with gcc they need to add -g on the gcc command line or they cannot see the source code when debugging. Often projects have a "debug" build that has -g and a "release" build that does not have -g (and maybe has more optimization flags turned on to get the highest performance).

We live in the world of SoC verification where the boundaries and dependencies between hardware and software make things more difficult. I have posted multiple times about topics that cause trouble. Posts like "Is anybody out there a software verification engineer?" and "Where's the Bridge to Cross the Great Divide?" are good examples. My conclusion is that software engineers generally know how to write and debug software. Hardware and hardware verification engineers generally know to create and verify hardware, but when these start mixing things get more difficult.

When working with customers we find that the most common model is for software engineers to hand off software to a logic simulation environment in the form of memory files, often in the Verilog readmemh format. The process goes something like this:

Take the C and assembly code and compile it, this example is an ARM compile flow.

armasm -32 -bigend -checkreglist -CPU 5T -keep -apcs /inter -g \

  -i include init.s -list init.lst -o init.o

armcc -ansi -c -cpu 5T -zo -bigend -fy -g -O2 -I include main.c -o main.o

The next step is to link the object files to create an executable file.

 armlink -debug -scatter link.txt -remove -noscanlib -info  \ 

sizes,totals,veneers,unused -map -symbols -xref main.o init.o \

/tools/ads11/common/lib/armlib/c_a__un.b   \ 

/tools/ads11/common/lib/armlib/f_a_m.b     \

/tools/ads11/common/lib/armlib/m_a_mu.b -list test.map -o test.elf

Mind the virtual and physical addresses used in the program are not important, but for embedded software the memory layout is important.. To make sure the code is placed into the correct areas of of memory a link map is used. Here is an example.

 

LR_1 0x0

{

        E_INIT_VEC 0x00

        {

                init.o(+RO)

        }

        E_RO +0

        {

                .ANY(+RO)

        }

 

       

        E_TABLE +0 UNINIT

        {

                main.o(image)

        }

        E_RW 0xFFFE0300

        {

       

                .ANY(+RW)

               

        }

        ER_ZI +0

        {

       

                *(+ZI)

               

        }

 

The final step is to take the ELF file and translate it into something that can be loaded into a simulation memory model.

 

% fromelf -vhx -32x1 test.elf -output rom.dat

The rom.dat file contains hex characters that can be loaded into a Verilog memory model when a simulation is run.

initial $readmemh(“rom.dat”, data);

Now let's get back to DWARF.The first thing to discuss is the ELF file. ELF stands for Executable and Linking Format. ELF files are object files produced by the compiler and linker that are binary representations of the programs intended to be executed directly on a CPU. The standard for ELF defines the file format including a header and different sections that allow the files to be easily identified and understood in a machine independent way. Understanding the details of the file format is not normally required to develop software for embedded systems, but some familiarity helps. In the example above the ELF file is test.elf. Of course, the elf extension is not needed, but I use it to make it more obvious. So if a Cadence AE or somebody from the ISX team asks about the name or location of the ELF file for the test, you can be confident you know what and where it is.

The next thing the same Cadence AE or ISX team member will ask is if your ELF file was compiled with DWARF. Normally this means nothing more than -g but since there are so many different compilers for embedded processors, the -g is not universal and the actual compiler switch could be anything. Newer compilers are likely to have DWARF support, but older compilers may not have it or have a very old version of it.

What is DWARF?

Here are three good places to start to get up to speed on DWARF:

Why do we care about DWARF?

DWARF is useful for debugging, but also for software verification. DWARF information can be used to learn many things about a software program. A good place to start is the dwarfdump utility that can be downloaded from DA's web page (part of libdwarf). If you have Specman installed then you have dwarfdump already available, just type dwarfdump at the prompt to get the usage message.

% dwarfdump
Usage:  dwarfdump <options> <object file>
options:       

-a   print all .debug_* sections
-b   print abbrev section
-c   print loc section
-d   dense: one line per entry (info section only)
-e   ellipsis: short names for tags, attrs etc.
-f    print dwarf frame section
-F   print gnu .eh_frame section
-g   (use incomplete loclist support)
-h   print exception tables
 -i   rint info section
-k[aerty]    check dwarf information
a    do all checks
e    examine attributes of pubnames
r     examine attr-tag relation
t     examine tag trees
y    examine type info
-l     print line section
-m   print macinfo section
-o    print relocation info
-p    print pubnames section
-r    print aranges section
-s   print string section
-t[afv] static:
a    print both sections
f     print static func section
v    print static var section
-u<file>   print sections only for specified file
-v            verbose: show more information
-x name=<path>    name dwarfdump.conf
-x abi=<abi>     name abi in dwarfdump.conf
-w      print weakname section
-y      print type section

 

I showed some output from dwarfdump -l in my last post.

DWARF is used in the SimVision Plugin Embedded Software Trace. For more information read the ISX User Guide or the reference in my post called "Embedded Software Bugging and Debugging".

DWARF is also used by ISX for functional verification of software to automatically create verification environments for C code. Many software test tools read the source code to find out the details of the functions and variables to be tested. This is a good start, but some details in embedded systems are architecture specific and can only be obtained from the object files. Sizes of basic data types are a good example of this. The example below has expected sizes for various data types on a 32-bit machine, but often embedded processors have different sizes for data types that are not explicitly defined by the C standard.DWARF also provides details for user defined data types.

LOCAL_SYMBOLS:


<1><   72>      DW_TAG_base_type
                DW_AT_name                  unsigned int
                DW_AT_byte_size             4
                DW_AT_encoding              DW_ATE_unsigned
<1><   79>      DW_TAG_base_type
                DW_AT_name                  unsigned char
                DW_AT_byte_size             1
                DW_AT_encoding              DW_ATE_unsigned_char
<1><   96>      DW_TAG_base_type
                DW_AT_name                  short unsigned int
                DW_AT_byte_size             2
                DW_AT_encoding              DW_ATE_unsigned
<1><  118>      DW_TAG_base_type
                DW_AT_name                  long unsigned int
                DW_AT_byte_size             4
                DW_AT_encoding              DW_ATE_unsigned
<1><  139>      DW_TAG_base_type
                DW_AT_name                  signed char
                DW_AT_byte_size             1
                DW_AT_encoding              DW_ATE_signed_char
 

Overall DWARF is useful to understand what is in an executable file. Just like other handy utilities like nm and strings, reading DWARF information with dwarfdump or readelf is another good trick to have in the bag.

Jason Andrews

Comments(3)

By Joerg Simon on June 18, 2009
Hi Jason,
I learned that several standards are out for DWARF, version 1,2 and 3. Are all the versions supported by ISX ?
Best Regards
JoergS

By jasona on June 18, 2009
In ISX we use only DWARF2 and DWARF3, the original DWARF (now called DWARF1) is completely different and obsolete. Some embedded compilers still may generate DWARF1, but all of them that are still actively maintained have also added DWARF2 or DWARF3 in the last few years. I would recommend to avoid DWARF1 due to interoperability issues.
Thanks for asking.

By Mohit Rawat on September 28, 2010
Hi! Jason,
How can i add DWARF debugging information into my current C code. Is it like at the time of Declaration/Definition of Variable I should add these DWARF type in my code or my compiler will automatically add these information in my c-code.
Regards,
Mohit

Leave a Comment


Name
E-mail (will not be published)
Comment
 I have read and agree to the Terms of use and Community Guidelines.
Community Guidelines
The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.