Go to main content

man pages section 1: User Commands

Exit Print View

Updated: Wednesday, July 27, 2022
 
 

elfdiff(1)

Name

elfdiff - compare twoELFfiles

Synopsis

elfdiff [-DeRuV] [-c | -h] [-i section[=class],...]
    [-r checksum-signature-range] [-s section,...]
    file1 file2

Description

The elfdiff utility analyzes two ELF files and reports the significant differences between them. This utility is targeted at diagnosing the underlying changes that occur within an ELF file through a series of development updates.

ELF files contain a variety of data structures and associated information, with the most basic building block being a section. Although many types of ELF section exist, sections fall into two main categories.

  • Sections that contain program data, whose interpretation is meaningful only to the application. These sections include the program .text instructions and the associated data sections such as .rodata and .data.

  • Sections that contain link-editing information, such as the symbol table information found in the .symtab and .strtab sections, and relocation information such as the .rela.text section.

Software changes typically consist of the addition, deletion or change to program data. These changes can manifest themselves as changes to the link-editing information, such as the symbols that are made available from the ELF file. However, these changes can also propagate though many sections within the ELF file, resulting in different section sizes and offsets. The simple addition of a new function definition or data item can ripple through the ELF file and result in many differences. Trying to extrapolate the underlying cause of a difference between two ELF files, amongst all the differences that exist, can be overwhelming.

The elfdiff utility analyzes a file in a number of phases, constraining the data in an attempt to present the highlights of what differences exist, and reduce diagnostic noise. The following phases of analysis occur.

  • ELF Class Verification

  • Checksum Verification

  • ELF Header Analysis

  • Symbol Table Analysis

  • Section Analysis

  • Program Header Analysis

See USAGE for details.

In general, elfdiff without any arguments should be sufficient to diagnose the basic differences between two ELF files.

In some build environments, one or two sections might always change from build to build. For example, a .comment section might change because of an embedded date stamp. Sections like these can be ignored with the –i option.

Some section differences can provoke an interest in diagnosing the section in more detail. Sections like these can be isolated for analysis with the –s option.

The –u option can be used to capture all differences, either for the entire file, or for specific sections defined using the –s option. Use of the –u option is well suited for collecting all differences in a file for further processing.

Options

The following options are supported.

–D

Provides more detailed information regarding the range of data processed within each file to determine the associated checksum. This option can be useful to analyze signature generation, but is generally unnecessary for normal elfdiff use.

–c

Produce and compare a SHA256 checksum for each file, with no further analysis of the files.

–h

Print a summary of the command line options on the standard output and exit.

–e

Apply heuristics in an attempt to elide differences due to offsets or addresses. For example, should a section differ in size between the two files, all sections that follow will differ in their offset and address. The –e option suppresses diagnosing such differences.

–i section[=class],...

Ignore diagnosing any differences of the class of information for the named section. Without a specified class, any diagnosis of differences related to the named section are ignored. Specifying a class allows refinement of the differences to ignore.

data

Ignore diagnosing any differences related to the data of the named section.

shdr

Ignore diagnosing any differences related to the section header of the named section.

Although the –i option suppresses diagnosing the differences between two sections, the option does not suppress the diagnosis of a section that only exists in one file.

–r checksum-signature-range

Define the checksum range. The range tokens are a representation of the ELF_SR_* types defined by elf32_sign_range(3ELF). The following range tokens are supported.

checksum

As used by elf32_checksum(3ELF).

file

The whole file. This is the default.

interpret

Select the range based on the file type.

relobj

Treat the file as a relocatable object.

signed-interpret

Select the range based on the file type, with the addition of any signature section.

This option provides a means of exercising the available signature range permutations, but is generally unnecessary for normal elfdiff use.

–R

Diagnose section data differences as raw data. This option can be useful to uncover difference details that might not be evident from formatted differences. See LIMITATIONS.

–s section,...

Diagnose differences only for the named section.

–u

By default, elfdiff limits the number of differences that are diagnosed during symbol table analysis and section data analysis. The –u option disables any limitation.

–V
–-version

Print version information and immediately exit.

–?
–-help

Print usage message and immediately exit.

OUTPUT CONVENTIONS

Each analysis phase is introduced with a title preceded with the string '***', and separated from previous differences with a blank line.

Differences for sections containing program instructions are shown in a display format similar to the dis(1) utility. Differences for sections containing program data are shown in a display format similar to the od(1) utility. Differences for ELF constructs are shown in the display format similar to the elfdump(1) utility.

Differences for file1 are prefixed with a '<' character, and differences for file2 are prefixed with '>', in the style similar to that used by the diff(1) utility.

If the section data difference can be associated with a symbol, the symbol name is displayed first, followed by the data difference. The data difference is prefixed with the offset within the section of the start of the difference, the symbol, denoted by the token '<sym>', and the offset within the symbol of the start of the difference.

Diagnostics that can be associated to the same symbol for both sections are introduced with the symbol name.

--- <sym>: func():
<     0x288:<sym>+0x10:    ...
>     0x288:<sym>+0x10:    ...

Diagnostics that are associated to different symbols identify each symbol.

<   <sym>: data1
<     0x1024:<sym>+0x40:    ...
>   <sym>: data2
>     0x1024:<sym>+0x40:    ...

Multiple diagnostics within the same section are separated with the string '---'.

Usage

The following descriptions outline each phase of elfdiff analysis, with examples of the diagnostics that can be produced by each phase.

ELF Header Class Verification

The ELF header resides at the beginning of the file and describes the file's organization, and defines the machine type and class of the file. elfdiff first determines that the two files have the same class. Incompatible classes result in an error diagnostic and termination of any further analysis.

$ elfdiff null.amd64.o null.i386.o
*** ehdr: information differs
<   ei_class:   ELFCLASS64          ei_data:       ELFDATA2LSB
>   ei_class:   ELFCLASS32          ei_data:       ELFDATA2LSB
ehdr: incompatible ELF classes, no further analysis is possible
Checksum Verification

Following class verification, a SHA256 checksum is calculated for each file. If the checksums are equal no further analysis is required. The range of data processed to obtain a checksum follows the model of elf32_sign_range(3ELF), and can be controlled by the –r option. The default behavior is to checksum the whole file.

ELF Header Analysis

If checksum verification indicates that the two files differ, a more complete comparison of the ELF header entries is carried out, and any difference diagnosed.

$ elfdiff null.i386 null.sparc
*** ehdr: information differs
<   ei_class:   ELFCLASS32          ei_data:       ELFDATA2LSB
>   ei_class:   ELFCLASS32          ei_data:       ELFDATA2MSB
---
<   e_machine:  EM_386              e_version:     EV_CURRENT
>   e_machine:  EM_SPARC32PLUS      e_version:     EV_CURRENT
---
<   e_flags:                     0
>   e_flags:    [ EF_SPARC_32PLUS ]

If the –e option is in affect, the entries e_entry, e_shstrndx, e_shoff, and e_shnum are omitted from this analysis. These entries can differ based on section number or offset differences, and can be better diagnosed in later phases.

For more information regarding the ELF header elements see ELF Header in Oracle Solaris 11.4 Linkers and Libraries Guide.

Symbol Table Analysis

Most program data is associated with symbols. Following ELF header analysis, elfdiff analyzes as much symbol table information as is available in the files, and diagnoses any differences. This phase of analysis often conveys sufficient data to inform you of the most important differences between two files.

Symbol table entries are sorted, and displayed in ascending section-index/value order. This ordering matches the layout of the sections within an ELF file. Symbols with no section-index or value, are typically less significant, and are ordered last.

$ elfdiff null.1 null.2
*** symbols: differ
<    [59]  0x80508a8  0x7  OBJT GLOB  D    0 .rodata name
>    [58]  0x80508a8  0x9  OBJT GLOB  D    0 .rodata name
---
>    [60]  0x8050b10  0xd  FUNC GLOB  D    0 .text   two
---
<    [56]  0x8050b10 0x2a  FUNC GLOB  D    0 .text   main
>    [55]  0x8050b20 0x24  FUNC GLOB  D    0 .text   main
---
<    [47]  0x8060d48  0x4  OBJT GLOB  D    0 .data   one
<     [1]          0    0  FILE LOCL  D    0 ABS     null.1
---
>     [1]          0    0  FILE LOCL  D    0 ABS     null.2

For more information regarding symbol table entries see Symbol Table Section in Oracle Solaris 11.4 Linkers and Libraries Guide.

Section Analysis

Following symbol table analysis, elfdiff analyzes the sections of each file, first diagnosing any section header information, followed by any section data differences.

Section headers are first analyzed to determine those that are common to both files, and those that are unique. Common sections that are found to differ, and sections that are unique, are diagnosed.

Common sections that differ are identified with the section name, and the section index, together with the differences found between each section header.

$ elfdiff null.1 null.2
...
*** section: [12].text: shdr information differs
<     sh_size:      0x215           sh_type:    [ SHT_PROGBITS ]
>     sh_size:      0x21f           sh_type:    [ SHT_PROGBITS ]

If two common sections have different section indexes, then both indexes are displayed, separated with a "<>" token to indicate the association to each file.

$ elfdiff null.1 null.2
...
*** section: [15 <> 16].data: shdr information differs
<     sh_size:      0x412           sh_type:    [ SHT_PROGBITS ]
>     sh_size:      0x460           sh_type:    [ SHT_PROGBITS ]

Sections that are unique are identified with the section name, and the section index, together with all the section header information.

$ elfdiff null.1 null.2
...
*** section: [21].comment: shdr is unique to one file
<     sh_addr:      0               sh_flags:   0
<     sh_size:      0xb1            sh_type:    [ SHT_PROGBITS ]
<     sh_offset:    0x1322          sh_entsize: 0
<     sh_link:      0               sh_info:    0
<     sh_addralign: 0x1

Following each section header diagnostic are any differences in section data. If any symbol table entries for the section were collected during symbol table analysis, the differences for the symbols associated with this section are displayed. Each symbol that was diagnosed as part of symbol table analysis, has its data difference displayed. If no symbol from this section was diagnosed as part of symbol table analysis, only the first symbol collected during this analysis is diagnosed. If no symbol table entries have been diagnosed for this section, then the first difference in the section data is diagnosed.

$ elfdiff null.1 null.2
...
*** section: [12].text: shdr information differs
...
*** section: [12].text: data information differs
--- <sym>: _start()
<     0xd:<sym>+0xd:     81 c3 44 02 01 00  addl   $0x10244,%ebx
>     0xd:<sym>+0xd:     81 c3 4c 02 01 00  addl   $0x1024c,%ebx
...
*** section: [13].rodata: data information differs
--- <sym>: title_string
<     0x0:<sym>:   T   i   t   l   e   _   O   l   d   :   \0
>     0x0:<sym>:   T   i   t   l   e   _   N   e   w   :   \0

Section data differences that can not be associated with a symbol name are diagnosed prefixed by the offset in the section of the difference.

$ elfdiff null.1 null.2
...
*** section: [20].strtab: data information differs
<     0x20:    \0   n   u   l   l   .   1  \0
>     0x20:    \0   n   u   l   l   .   2  \0 

Note, if the –e option is in affect, and individual symbol entries were diagnosed during the symbol table analysis phase, no further diagnosis of any symbol table section is carried out. However, any string table sections that might provide symbol table entry names are processed. These string tables can often contain addition strings besides symbol table entry names.

For more information regarding the section header entries see Section Headers in Oracle Solaris 11.4 Linkers and Libraries Guide.

Program Header Analysis

Following section analysis, elfdiff analyses the program headers to determine those that are common to both files, and those that are unique. Common program headers that are found to differ, and program headers that are unique are displayed.

Many program headers encapsulate ranges of sections, and thus their data would have already been more fully described by the preceding section analysis phase.

Common program headers that differ are identified with the header index, the header type, and then the differences found between each program header.

$ elfdiff null.1 null.2
...
*** phdr: [3]: PT_LOAD: phdr information differs
<     p_filesz:     0xb6f       p_memsz:    0xb6f
>     p_filesz:     0xb77       p_memsz:    0xb77

Program headers that are unique are identified with the header index, the header type, and then all the program header information.

$ elfdiff null.1 null.2
...
*** phdr: [5]: SUNW_UNWIND is unique to one file
>     p_vaddr:      0x4001a8    p_flags:    [ PF_R ]
>     p_paddr:      0           p_type:     [ PT_SUNW_UNWIND ]
>     p_filesz:     0x1c        p_memsz:    0x1c
>     p_offset:     0x1a8       p_align:    0x8

For more information regarding the program header entries see Program Header in Oracle Solaris 11.4 Linkers and Libraries Guide.

LIMITATIONS

elfdiff is not a panacea for discovering fine grained differences between two files. The goal of elfdiff is to identify the differences between two files that could be caused by software changes you control. At the same time, diagnosing changes to the ELF data that has changed as a result of your software changes, is kept to a minimum.

Any ELF section that differs between the two files results in a diagnostic to indicate that differences exist. However, the differences can be subtle. Entries within many ELF sections define offsets within other ELF sections. The difference between two sections may be that only the offset references differ. It could be argued that nothing substantial had changed between the two sections, however elfdiff diagnoses the first difference between the sections to indicate that differences exist.

Further complications can occur for differences that follow the format of elfdump(1) output. elfdump can embellish raw data, such as symbolically representing symbol and section names. In addition, alignment constraints for ELF data structures can require the presence of holes or padding, which is not evident from an elfdiff style of display. Should conditions like these exist, elfdiff style diagnostics for the data can look identical. The –R option can be used to suppress any attempt to provide formatted differences, and instead present the raw data.

If you want more fine grained detail of the differences between two ELF files, use elfdiff as a starting point. Further analysis can be carried out with tools like dis(1), elfdump(1), and od(1).

Exit Status

The following exit values are returned.

0

No differences were found between the files.

1

Differences were found between the files.

>1

An error occurred.

Note, if the –s option is used to explicitly define a section to analyze, and no differences are diagnosed, elfdump will still return 1 if the two files differ in any other manner.

Examples

Example 1 Basic Usage

The following provides an example of comparing two versions of a shared object.

$ elfdiff -e foo.so.1 foo.so.2
*** symbols: differ
<    [9287]  0x935c0 0x1bd  FUNC GLOB  D  0 .text   device_offline
>    [9287]  0x935c0 0x1f5  FUNC GLOB  D  0 .text   device_offline
---
<   [10233] 0x111240  0x20  FUNC GLOB  D  0 .text   new_device_A
<   [10010] 0x111260  0x64  FUNC GLOB  D  0 .text   new_device_B
---
>   [15317]        0     0  NOTY GLOB  D  0 UNDEF   __assfailline__13

*** section: [1].SUNW_cap: shdr information differs
<     sh_size:      0xe0                sh_type:    [ SHT_SUNW_cap ]
>     sh_size:      0x120               sh_type:    [ SHT_SUNW_cap ]
*** section: [1].SUNW_cap: data information differs
<     0x80:    [8]  CA_SUNW_ID    0x2317      i86pc-clmul
>     0x80:    [8]  CA_SUNW_ID    0x1f59      i86pc-avx2

*** section: [6].text: shdr information differs
<     sh_size:      0x38e205            sh_type:    [ SHT_PROGBITS ]
>     sh_size:      0x38e245            sh_type:    [ SHT_PROGBITS ]
*** section: [6].text: data information differs
--- <sym>: device_offline()
<     0x935d9:<sym>+0x19:  48 8b df           movq   %rdi,%rbx
>     0x935d9:<sym>+0x19:  4c 8b e7           movq   %rdi,%r12
---
<   <sym>: new_device_A
<     0x111240:<sym>:      55                 push   %rbp
---
<   <sym>: new_device_B
<     0x111260:<sym>:      55                 push   %rbp

*** section: [9].strtab: shdr information differs
<     sh_size:      0x642c5             sh_type:    [ SHT_STRTAB ]
>     sh_size:      0x642d9             sh_type:    [ SHT_STRTAB ]
*** section: [9].strtab: data information differs
<     0x42297:     n   e   _   _   1   3   8   5  \0   _   _    ...
>     0x42297:     n   e   _   _   1   3   8   4  \0   _   _    ...

*** section: [13].rela.text: shdr information differs
<     sh_size:      0x36d398            sh_type:    [ SHT_RELA ]
>     sh_size:      0x36d428            sh_type:    [ SHT_RELA ]
*** section: [13].rela.text: data information differs
<     0x0:    [0]  R_AMD64_32S  0x1635f4 0x1638b4  .text   
>     0x0:    [0]  R_AMD64_32S  0x163634 0x1638f4  .text

*** section: [33].SUNW_ctf: shdr information differs
<     sh_size:      0xb33c              sh_type:    [ SHT_PROGBITS ]
>     sh_size:      0xb4e4              sh_type:    [ SHT_PROGBITS ]
*** section: [33].SUNW_ctf: data information differs
<     0xd:    \0  \0  \0 \08  \0  \0  \0 \b2 \03  \0  \0   D   ...
>     0xd:    \0  \0  \0 \08  \0  \0  \0 \ba \03  \0  \0   $   ...

*** section: [34].SUNW_signature: data information differs
<     0x73:     j   o   h   n   d   o   e  \t \93 \ab \ff \fa ...
>     0x73:     j   o   h   n   d   o   e \c2 \c5 \98   r   a ...
Example 2 Suppressing Section Differences

In the previous example, the .SUNW_ctf section is known to change size and content from one build to another, and the .SUNW_signature section is known to change content from one build to another. These two diagnostics can be suppressed using the –i option, while ensuring that the addition or deletion of either of these sections remains diagnosed.

$ elfdiff -e -i.SUNW_signature=data,.SUNW_ctf foo.so.1 foo.so.2
Example 3 Inspecting a Specific Section

In the previous example, the difference in the .SUNW_cap section is of interest, and the full extent of the differences of that section can be analyzed with the –s option.

$ elfdiff -e -u -s.SUNW_cap foo.so.1 foo.so.2
*** section: [1].SUNW_cap: shdr information differs
<     sh_size:      0xe0                sh_type:    [ SHT_SUNW_cap ]
>     sh_size:      0x120               sh_type:    [ SHT_SUNW_cap ]
*** section: [1].SUNW_cap: data information differs
<     0x80:    [8]  CA_SUNW_ID    0x2317      i86pc-clmul
>     0x80:    [8]  CA_SUNW_ID    0x1f59      i86pc-avx2
---
<     0x90:    [9]  CA_SUNW_HW_1  0x8001000   [ PCLMULQDQ SSE2 ]
>     0x90:    [9]  CA_SUNW_HW_2  0x40        [ AVX2 ]
---
<     0xa0:   [10]  CA_SUNW_NULL  0           [ 0x0 ]
>     0xa0:   [10]  CA_SUNW_HW_1  0x20401000  [ AVX SSSE3 SSE2 ]
---
<     0xb0:   [11]  CA_SUNW_ID    0x24e5      i86pc-ssse3
>     0xb0:   [11]  CA_SUNW_NULL  0           [ 0x0 ]
---
<     0xc0:   [12]  CA_SUNW_HW_1  0x401000    [ SSSE3 SSE2 ]
>     0xc0:   [12]  CA_SUNW_ID    0x24f7      i86pc-clmul
---
<     0xd0:   [13]  CA_SUNW_NULL  0           [ 0x0 ]
>     0xd0:   [13]  CA_SUNW_HW_1  0x8001000   [ PCLMULQDQ SSE2 ]
---
>     0xe0:   [14]  CA_SUNW_NULL  0           [ 0x0 ]
>     0xf0:   [15]  CA_SUNW_ID    0x26c5      i86pc-ssse3
>     0x100:  [16]  CA_SUNW_HW_1  0x401000    [ SSSE3 SSE2 ]
>     0x110:  [17]  CA_SUNW_NULL  0           [ 0x0 ]

Attributes

See attributes(7) for descriptions of the following attributes:

ATTRIBUTE TYPE
ATTRIBUTE VALUE
Availability
system/linker
Interface Stability
See below.

The human readable output is Uncommitted. The options are Committed.

See Also

diff(1), dis(1), elfdump(1), od(1), elf(3ELF), elf32_checksum(3ELF), elf64_checksum(3ELF), elf32_sign_range(3ELF), elf64_sign_range(3ELF), attributes(7)

Oracle Solaris 11.4 Linkers and Libraries Guide