Rod Evans — Thursday February 01, 2018

Surfing with the Linker-Aliens

Frequently it is desirable to compare two ELF files. As someone who makes changes to the link-editor, comparing large numbers of built objects is a vital part of verifying any changes. In addition, determining what objects have changed from one build to another, can reduce object distribution to only those objects that have changed. Often, it is simply enlightening to know "what did I change in this ELF file to make it different?".

Various tools exist to compare ELF files, often being scripts that call upon tools like elfdump(1), dis(1), and od(1), to analyze sections in more detail. These tools can be rather slow and produce voluminous output.

ELF files have an inherent problem when trying to analyze differences — even a small change to a section within an object, ie. code changes to .text, .data or .rodata, can result in offset changes that ripple through the ELF file affecting many sections and the data these sections contain. Trying to extrapolate the underlying cause of a difference between two ELF files, amongst all the differences that exist, can be overwhelming.

elfdiff(1) attempts to analyze two ELF files and diagnose the most important changes. Typically, the most significant changes to an object can be conveyed from changes to the symbol table. Functions and data items get added or deleted, or change size. Most of the time this can be sufficient to know/confirm what has changed.

After providing any symbol information, elfdiff continues to grovel down into individual sections, and indicate what might have changed. The output style of the diagnostics are a mix of dis(1) for function diffs, od(1) for data diffs, and elfdump(1) style for sections that elfdump understands and provides high level formatted displays for.

The output is limited. A handful of symbols are displayed first. Sections report a single line of difference, or a single line of difference for each symbol already diagnosed. The styles of each difference, and the order in which they are displayed is covered in the elfdiff(1) man page.

This is an overview diff, appropriate for answering questions such as "What are the high level differences between two nightly builds". It does not replace lower level tools such as elfdump(1), but rather, provides a higher level analysis that might then be used to guide the use of lower level tools.

Some files may contain sections that always change from one build to another, things like comment or signature sections. These can be ignored with the -i option. Sometimes only one or two sections are of interested. These can be specified with the -s option. If you really want to see all the differences between two files, use the -u option. But be careful, the output can be excessive.

The following provides an example of comparing two versions of a shared object, and is lifted directly from the elfdiff(1) man page.

  $ 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 ...
Surfing with the Linker-Aliens

Published Elsewhere


Surfing with the Linker-Aliens

[30] Symbol Capabilities
Blog Index (rie)
[1] Hello there