merge
diff --git a/elftools/elf/descriptions.py b/elftools/elf/descriptions.py
index 35232b9..f404898 100644
--- a/elftools/elf/descriptions.py
+++ b/elftools/elf/descriptions.py
@@ -6,15 +6,15 @@
 # Eli Bendersky (eliben@gmail.com)
 # This code is in the public domain
 #-------------------------------------------------------------------------------
-from .enums import ENUM_E_VERSION
+from .enums import ENUM_E_VERSION, ENUM_RELOC_TYPE_i386, ENUM_RELOC_TYPE_x64
 from .constants import P_FLAGS, SH_FLAGS
 
 
 def describe_ei_class(x):
-    return _DESCR_EI_CLASS.get(x, _unknown())
+    return _DESCR_EI_CLASS.get(x, _unknown)
 
 def describe_ei_data(x):
-    return _DESCR_EI_DATA.get(x, _unknown())
+    return _DESCR_EI_DATA.get(x, _unknown)
 
 def describe_ei_version(x):
     s = '%d' % ENUM_E_VERSION[x]
@@ -23,19 +23,19 @@
     return s
     
 def describe_ei_osabi(x):
-    return _DESCR_EI_OSABI.get(x, _unknown())
+    return _DESCR_EI_OSABI.get(x, _unknown)
 
 def describe_e_type(x):
-    return _DESCR_E_TYPE.get(x, _unknown())
+    return _DESCR_E_TYPE.get(x, _unknown)
 
 def describe_e_machine(x):
-    return _DESCR_E_MACHINE.get(x, _unknown())
+    return _DESCR_E_MACHINE.get(x, _unknown)
 
 def describe_e_version_numeric(x):
     return '0x%x' % ENUM_E_VERSION[x]
 
 def describe_p_type(x):
-    return _DESCR_P_TYPE.get(x, _unknown())
+    return _DESCR_P_TYPE.get(x, _unknown)
 
 def describe_p_flags(x):
     s = ''
@@ -44,7 +44,7 @@
     return s
 
 def describe_sh_type(x):
-    return _DESCR_SH_TYPE.get(x, _unknown())
+    return _DESCR_SH_TYPE.get(x, _unknown)
 
 def describe_sh_flags(x):
     s = ''
@@ -57,21 +57,28 @@
     return s
 
 def describe_symbol_type(x):
-    return _DESCR_ST_INFO_TYPE.get(x, _unknown())
+    return _DESCR_ST_INFO_TYPE.get(x, _unknown)
 
 def describe_symbol_bind(x):
-    return _DESCR_ST_INFO_BIND.get(x, _unknown())
+    return _DESCR_ST_INFO_BIND.get(x, _unknown)
 
 def describe_symbol_visibility(x):
-    return _DESCR_ST_VISIBILITY.get(x, _unknown())
+    return _DESCR_ST_VISIBILITY.get(x, _unknown)
 
 def describe_symbol_shndx(x):
     return _DESCR_ST_SHNDX.get(x, '%3s' % x)
 
+def describe_reloc_type(x, e_machine):
+    if e_machine in ('EM_386', 'EM_486'):
+        return _DESCR_RELOC_TYPE_i386.get(x, _unknown)
+    elif e_machine in ('EM_X86_64', 'EM_L10M'):
+        return _DESCR_RELOC_TYPE_x64.get(x, _unknown)
+    else:
+        return 'unrecognized: %-7x' % (x & 0xFFFFFFFF)
+
 
 #-------------------------------------------------------------------------------
-def _unknown():
-    return '<unknown>'
+_unknown = '<unknown>'
 
     
 _DESCR_EI_CLASS = dict(
@@ -222,4 +229,10 @@
     SHN_COMMON='COM',
 )
 
+_DESCR_RELOC_TYPE_i386 = dict(
+        (v, k) for k, v in ENUM_RELOC_TYPE_i386.iteritems())
+
+_DESCR_RELOC_TYPE_x64 = dict(
+        (v, k) for k, v in ENUM_RELOC_TYPE_x64.iteritems())
+
 
diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py
index c13d15f..78302ae 100644
--- a/elftools/elf/enums.py
+++ b/elftools/elf/enums.py
@@ -73,6 +73,7 @@
     EM_386=3,
     EM_68K=4,
     EM_88K=5,
+    EM_486=6,
     EM_860=7,
     EM_MIPS=8,
     EM_S370=9,
@@ -80,6 +81,7 @@
     EM_IA_64=50,
     EM_X86_64=62,
     EM_AVR=83,
+    EM_L10M=180,
     _default_=Pass,
 )
 
@@ -184,3 +186,92 @@
     _default_=Pass,
 )
 
+ENUM_RELOC_TYPE_i386 = dict(
+    R_386_NONE=0,
+    R_386_32=1,
+    R_386_PC32=2,
+    R_386_GOT32=3,
+    R_386_PLT32=4,
+    R_386_COPY=5,
+    R_386_GLOB_DAT=6,
+    R_386_JUMP_SLOT=7,
+    R_386_RELATIVE=8,
+    R_386_GOTOFF=9,
+    R_386_GOTPC=10,
+    R_386_32PLT=11,
+    R_386_TLS_TPOFF=14,
+    R_386_TLS_IE=15,
+    R_386_TLS_GOTIE=16,
+    R_386_TLS_LE=17,
+    R_386_TLS_GD=18,
+    R_386_TLS_LDM=19,
+    R_386_16=20,
+    R_386_PC16=21,
+    R_386_8=22,
+    R_386_PC8=23,
+    R_386_TLS_GD_32=24,
+    R_386_TLS_GD_PUSH=25,
+    R_386_TLS_GD_CALL=26,
+    R_386_TLS_GD_POP=27,
+    R_386_TLS_LDM_32=28,
+    R_386_TLS_LDM_PUSH=29,
+    R_386_TLS_LDM_CALL=30,
+    R_386_TLS_LDM_POP=31,
+    R_386_TLS_LDO_32=32,
+    R_386_TLS_IE_32=33,
+    R_386_TLS_LE_32=34,
+    R_386_TLS_DTPMOD32=35,
+    R_386_TLS_DTPOFF32=36,
+    R_386_TLS_TPOFF32=37,
+    R_386_TLS_GOTDESC=39,
+    R_386_TLS_DESC_CALL=40,
+    R_386_TLS_DESC=41,
+    R_386_IRELATIVE=42,
+    R_386_USED_BY_INTEL_200=200,
+    R_386_GNU_VTINHERIT=250,
+    R_386_GNU_VTENTRY=251,
+    _default_=Pass,
+)
+
+ENUM_RELOC_TYPE_x64 = dict(
+    R_X86_64_NONE=0,
+    R_X86_64_64=1,
+    R_X86_64_PC32=2,
+    R_X86_64_GOT32=3,
+    R_X86_64_PLT32=4,
+    R_X86_64_COPY=5,
+    R_X86_64_GLOB_DAT=6,
+    R_X86_64_JUMP_SLOT=7,
+    R_X86_64_RELATIVE=8,
+    R_X86_64_GOTPCREL=9,
+    R_X86_64_32=10,
+    R_X86_64_32S=11,
+    R_X86_64_16=12,
+    R_X86_64_PC16=13,
+    R_X86_64_8=14,
+    R_X86_64_PC8=15,
+    R_X86_64_DTPMOD64=16,
+    R_X86_64_DTPOFF64=17,
+    R_X86_64_TPOFF64=18,
+    R_X86_64_TLSGD=19,
+    R_X86_64_TLSLD=20,
+    R_X86_64_DTPOFF32=21,
+    R_X86_64_GOTTPOFF=22,
+    R_X86_64_TPOFF32=23,
+    R_X86_64_PC64=24,
+    R_X86_64_GOTOFF64=25,
+    R_X86_64_GOTPC32=26,
+    R_X86_64_GOT64=27,
+    R_X86_64_GOTPCREL64=28,
+    R_X86_64_GOTPC64=29,
+    R_X86_64_GOTPLT64=30,
+    R_X86_64_PLTOFF64=31,
+    R_X86_64_GOTPC32_TLSDESC=34,
+    R_X86_64_TLSDESC_CALL=35,
+    R_X86_64_TLSDESC=36,
+    R_X86_64_IRELATIVE=37,
+    R_X86_64_GNU_VTINHERIT=250,
+    R_X86_64_GNU_VTENTRY=251,
+    _default_=Pass,
+)
+
diff --git a/elftools/elf/sections.py b/elftools/elf/sections.py
index 59c85b7..10b99f9 100644
--- a/elftools/elf/sections.py
+++ b/elftools/elf/sections.py
@@ -121,6 +121,11 @@
             self.header['sh_entsize'] == expected_size,
             'Expected sh_entsize of SHT_REL section to be %s' % expected_size)
 
+    def is_RELA(self):
+        """ Is this a RELA relocation section? If not, it's REL.
+        """
+        return self.header['sh_type'] == 'SHT_RELA'
+
     def num_relocations(self):
         """ Number of relocations in the section
         """
@@ -169,6 +174,11 @@
     def __init__(self, entry):
         self.entry = entry
         
+    def is_RELA(self):
+        """ Is this a RELA relocation? If not, it's REL.
+        """
+        return 'r_addend' in self.entry
+        
     def __getitem__(self, name):
         """ Dict-like access to entries
         """
diff --git a/elftools/elf/structs.py b/elftools/elf/structs.py
index a8d3497..d2d6e69 100644
--- a/elftools/elf/structs.py
+++ b/elftools/elf/structs.py
@@ -136,34 +136,30 @@
         )
     
     def _create_rel(self):
-        # r_info is hierarchical. To access the type, use
-        # container['r_info']['type']
+        # r_info is also taken apart into r_info_sym and r_info_type.
+        # This is done in Value to avoid endianity issues while parsing.
         if self.elfclass == 32:
-            r_info_struct = BitStruct('r_info',
-                BitField('sym', 24),
-                BitField('type', 8))
+            r_info_sym = Value('r_info_sym',
+                lambda ctx: (ctx['r_info'] >> 8) & 0xFFFFFF)
+            r_info_type = Value('r_info_type',
+                lambda ctx: ctx['r_info'] & 0xFF)
         else: # 64
-            r_info_struct = BitStruct('r_info',
-                BitField('sym', 32),
-                Padding(24),
-                BitField('type', 8))
-
-        # Since the raw value of r_info is also needed, it's being re-computed
-        # in 'r_info_raw'
-        r_info_raw = Value('r_info_raw',
-                lambda ctx: 
-                    (ctx['r_info']['sym'] << 8 if self.elfclass == 32 else 32) +
-                    ctx['r_info']['type'])
+            r_info_sym = Value('r_info_sym',
+                lambda ctx: (ctx['r_info'] >> 32) & 0xFFFFFFFF)
+            r_info_type = Value('r_info_type',
+                lambda ctx: ctx['r_info'] & 0xFFFFFFFF)
 
         self.Elf_Rel = Struct('Elf_Rel',
             self.Elf_addr('r_offset'),
-            r_info_struct,
-            r_info_raw,
+            self.Elf_xword('r_info'),
+            r_info_sym,
+            r_info_type,
         )
         self.Elf_Rela = Struct('Elf_Rela',
             self.Elf_addr('r_offset'),
-            r_info_struct,
-            r_info_raw,
+            self.Elf_xword('r_info'),
+            r_info_sym,
+            r_info_type,
             self.Elf_sxword('r_addend'),
         )
 
diff --git a/scripts/readelf.py b/scripts/readelf.py
index 46caa11..69293cc 100755
--- a/scripts/readelf.py
+++ b/scripts/readelf.py
@@ -31,7 +31,7 @@
     describe_e_version_numeric, describe_p_type, describe_p_flags,
     describe_sh_type, describe_sh_flags,
     describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
-    describe_symbol_shndx,
+    describe_symbol_shndx, describe_reloc_type,
     )
 
 
@@ -279,11 +279,36 @@
                 section.name,
                 self._format_hex(section['sh_offset']),
                 section.num_relocations()))
+            if section.is_RELA():
+                self._emitline("  Offset          Info           Type           Sym. Value    Sym. Name + Addend")
+            else:
+                self._emitline(" Offset     Info    Type            Sym.Value  Sym. Name")
+
+            # The symbol table section pointed to in sh_link
+            symtable = self.elffile.get_section(section['sh_link'])
+
             for rel in section.iter_relocations():
-                self._emitline('%s %s' % (
-                    self._format_hex(rel['r_offset'], fullhex=True, lead0x=False),
-                    self._format_hex(rel['r_info_raw'], fullhex=True, lead0x=False)))
-                #print rel, rel.entry
+                hexwidth = 8 if self.elffile.elfclass == 32 else 12
+                symbol = symtable.get_symbol(rel['r_info_sym'])
+                self._emit('%s  %s %-17.17s %s %s%s' % (
+                    self._format_hex(rel['r_offset'], 
+                        fieldsize=hexwidth, lead0x=False),
+                    self._format_hex(rel['r_info'], 
+                        fieldsize=hexwidth, lead0x=False),
+                    describe_reloc_type(
+                        rel['r_info_type'], self.elffile['e_machine']),
+                    self._format_hex(
+                        symbol['st_value'],
+                        fullhex=True, lead0x=False),
+                    '  ' if self.elffile.elfclass == 32 else '',
+                    symbol.name,
+                    ))
+
+                if section.is_RELA():
+                    self._emit(' %s %x' % (
+                        '+' if rel['r_addend'] >= 0 else '-',
+                        abs(rel['r_addend'])))
+                self._emitline()
 
         if not has_relocation_sections:
             self._emitline('\nThere are no relocations in this file.')
diff --git a/tests/run_tests.py b/tests/run_tests.py
index 24f4015..a369b5e 100755
--- a/tests/run_tests.py
+++ b/tests/run_tests.py
@@ -49,7 +49,7 @@
     """
     success = True
     testlog.info("Running test on file '%s'" % filename)
-    for option in ['-e', '-s', '-x.text', '-p.shstrtab']:
+    for option in ['-e', '-s', '-r', '-x.text', '-p.shstrtab']:
         testlog.info("..option='%s'" % option)
         # stdouts will be a 2-element list: output of readelf and output 
         # of scripts/readelf.py