5

objdump man page says,

-r
--reloc
      Print the relocation entries of the file.  If used with -d or -D,
      the relocations are printed interspersed with the disassembly.

-R
--dynamic-reloc
      Print the dynamic relocation entries of the file. This is only
      meaningful for dynamic objects, such as certain types of shared
      libraries. As for -r, if used with -d or -D, the relocations are
      printed interspersed with the disassembly.

Can anybody please explain how do these two options differ? What's the difference between relocation and dynamic relocation entries?

2 Answers 2

3

Ordinary object file

As the notes say, the -R is only meaningful for dynamic objects. For ordinary .o files from simple programs, the -r will show the relocation entries. As an example, this simple program:

#include <stdio.h>
int main() {
    puts("Hello, world!\");
}

We can produce an object file with this:

cc -Wall -Wextra -pedantic -std=c11   -c -o sample.o sample.c

Produces this output when we run the command objdump -r sample.o:

sample.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]:
OFFSET           TYPE              VALUE 
0000000000000005 R_X86_64_32       .rodata
000000000000000a R_X86_64_PC32     puts-0x0000000000000004


RELOCATION RECORDS FOR [.eh_frame]:
OFFSET           TYPE              VALUE 
0000000000000020 R_X86_64_PC32     .text

(This is an x86_64 Linux box.)

With objdump -R sample.o we get this:

objdump: sample.o: not a dynamic object
objdump: sample.o: Invalid operation

This is expected since this is not a shared library.

Shared library

By contrast, we can use this code:

#include <stdio.h>
int hello() {
    return puts("Hello, world!\n");
}

And create a library with this:

gcc -Wall -Wextra -pedantic -std=c11 -fPIC -shared -o libsample.so sample.c

Now the -R makes sense:

objdump -R libsample.so 

Output:

libsample.so:     file format elf64-x86-64

DYNAMIC RELOCATION RECORDS
OFFSET           TYPE              VALUE 
0000000000200df8 R_X86_64_RELATIVE  *ABS*+0x0000000000000660
0000000000200e00 R_X86_64_RELATIVE  *ABS*+0x0000000000000620
0000000000200e10 R_X86_64_RELATIVE  *ABS*+0x0000000000200e10
0000000000200fd8 R_X86_64_GLOB_DAT  _ITM_deregisterTMCloneTable
0000000000200fe0 R_X86_64_GLOB_DAT  __gmon_start__
0000000000200fe8 R_X86_64_GLOB_DAT  _Jv_RegisterClasses
0000000000200ff0 R_X86_64_GLOB_DAT  _ITM_registerTMCloneTable
0000000000200ff8 R_X86_64_GLOB_DAT  __cxa_finalize@GLIBC_2.2.5
0000000000201018 R_X86_64_JUMP_SLOT  puts@GLIBC_2.2.5

Playing games

There are two other utilities: readelf and elfedit that allows us to look at and modify the binary in more detail. If we create a shared object as shown above, but on a 32-bit Linux machine and then run readelf -a libsample.so the output is long, but starts with this:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x3f0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          5884 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         7
  Size of section headers:           40 (bytes)
  Number of section headers:         29
  Section header string table index: 26

We can then play games such as changing the file to a EXEC type instead of a DYN type:

elfedit --output-type=EXEC test.so

Now if we rerun readelf, everything is the same except for that tag:

ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x3f0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          5884 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         7
  Size of section headers:           40 (bytes)
  Number of section headers:         29
  Section header string table index: 26

Although the type has changed, it will still function as a shared library.

2
  • On this binary (not a shared object), -r doesn't work while -R works. How can you explain that?
    – sherlock
    Commented Dec 20, 2016 at 16:49
  • I've added to my answer to show exactly how that's done.
    – Edward
    Commented Dec 20, 2016 at 18:00
2

Dynamic relocations are relocations applied by the dynamic linker (usually ld.so or equivalent), as opposed to the link editor (e.g. ld) for the object files' relocations. They are pointed to by the dynamic section entries such as DT_REL, DT_RELA and DT_JMPREL. The dynamic linker often supports only a limited set of relocations. Not only shared objects but also dynamic (non-static) executables may have dynamic relocations. Unstripped binaries may also have remaining non-dynamic relocations but those are not used by the dynamic linker.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.