section header output kinda working
diff --git a/elftools/elf/constants.py b/elftools/elf/constants.py
index 1d49d2b..df75e16 100644
--- a/elftools/elf/constants.py
+++ b/elftools/elf/constants.py
@@ -32,6 +32,7 @@
     SHF_GROUP=0x200
     SHF_TLS=0x400
     SHF_MASKOS=0x0ff00000
+    SHF_EXCLUDE=0x80000000
     SHF_MASKPROC=0xf0000000
 
 
diff --git a/elftools/elf/descriptions.py b/elftools/elf/descriptions.py
index 258fc67..688ee61 100644
--- a/elftools/elf/descriptions.py
+++ b/elftools/elf/descriptions.py
@@ -7,7 +7,7 @@
 # This code is in the public domain
 #-------------------------------------------------------------------------------
 from .enums import ENUM_E_VERSION
-from .constants import P_FLAGS
+from .constants import P_FLAGS, SH_FLAGS
 
 
 def describe_ei_class(x):
@@ -43,6 +43,19 @@
         s += _DESCR_P_FLAGS[flag] if (x & flag) else ' ' 
     return s
 
+def describe_sh_type(x):
+    return _DESCR_SH_TYPE.get(x, _unknown())
+
+def describe_sh_flags(x):
+    s = ''
+    for flag in (
+            SH_FLAGS.SHF_WRITE, SH_FLAGS.SHF_ALLOC, SH_FLAGS.SHF_EXECINSTR,
+            SH_FLAGS.SHF_MERGE, SH_FLAGS.SHF_STRINGS, SH_FLAGS.SHF_INFO_LINK,
+            SH_FLAGS.SHF_LINK_ORDER, SH_FLAGS.SHF_OS_NONCONFORMING,
+            SH_FLAGS.SHF_GROUP, SH_FLAGS.SHF_TLS, SH_FLAGS.SHF_EXCLUDE):
+        s += _DESCR_SH_FLAGS[flag] if (x & flag) else ''
+    return s
+
 
 #-------------------------------------------------------------------------------
 def _unknown():
@@ -126,4 +139,42 @@
     P_FLAGS.PF_W: 'W',
 }
 
+_DESCR_SH_TYPE = dict(
+    SHT_NULL='NULL',
+    SHT_PROGBITS='PROGBITS',
+    SHT_SYMTAB='SYMTAB',
+    SHT_STRTAB='STRTAB',
+    SHT_RELA='RELA',
+    SHT_HASH='HASH',
+    SHT_DYNAMIC='DYNAMIC',
+    SHT_NOTE='NOTE',
+    SHT_NOBITS='NOBITS',
+    SHT_REL='REL',
+    SHT_SHLIB='SHLIB',
+    SHT_DYNSYM='DYNSYM',
+    SHT_INIT_ARRAY='INIT_ARRAY',
+    SHT_FINI_ARRAY='FINI_ARRAY',
+    SHT_PREINIT_ARRAY='PREINIT_ARRAY',
+    SHT_GNU_HASH='GNU_HASH',
+    SHT_GROUP='GROUP',
+    SHT_SYMTAB_SHNDX='SYMTAB SECTION INDICIES',
+    SHT_GNU_verdef='VERDEF',
+    SHT_GNU_verneed='VERNEED',
+    SHT_GNU_versym='VERSYM',
+    SHT_GNU_LIBLIST='GNU_LIBLIST',
+)
+
+_DESCR_SH_FLAGS = {
+    SH_FLAGS.SHF_WRITE: 'W',
+    SH_FLAGS.SHF_ALLOC: 'A',
+    SH_FLAGS.SHF_EXECINSTR: 'X',
+    SH_FLAGS.SHF_MERGE: 'M',
+    SH_FLAGS.SHF_STRINGS: 'S',
+    SH_FLAGS.SHF_INFO_LINK: 'I',
+    SH_FLAGS.SHF_LINK_ORDER: 'L',
+    SH_FLAGS.SHF_OS_NONCONFORMING: 'O',
+    SH_FLAGS.SHF_GROUP: 'G',
+    SH_FLAGS.SHF_TLS: 'T',
+    SH_FLAGS.SHF_EXCLUDE: 'E',
+}
 
diff --git a/elftools/elf/enums.py b/elftools/elf/enums.py
index 8715bf1..dadf5d4 100644
--- a/elftools/elf/enums.py
+++ b/elftools/elf/enums.py
@@ -100,7 +100,10 @@
     SHT_SYMTAB_SHNDX=18,
     SHT_NUM=19,
     SHT_LOOS=0x60000000,
-    SHT_HIOS=0x6fffffff,
+    SHT_GNU_HASH=0x6ffffff6,
+    SHT_GNU_verdef=0x6ffffffd,
+    SHT_GNU_verneed=0x6ffffffe,
+    SHT_GNU_versym=0x6fffffff,
     SHT_LOPROC=0x70000000,
     SHT_HIPROC=0x7fffffff,
     SHT_LOUSER=0x80000000,
diff --git a/scripts/readelf.py b/scripts/readelf.py
index e6addb7..ede8738 100644
--- a/scripts/readelf.py
+++ b/scripts/readelf.py
@@ -24,7 +24,7 @@
     describe_ei_class, describe_ei_data, describe_ei_version,
     describe_ei_osabi, describe_e_type, describe_e_machine,
     describe_e_version_numeric, describe_p_type, describe_p_flags,
-
+    describe_sh_type, describe_sh_flags,
     )
 
 
@@ -95,11 +95,13 @@
         self._emitline()
         elfheader = self.elffile.header
         self._emitline('Elf file type is %s' %
-                describe_e_type(elfheader['e_type']))
+            describe_e_type(elfheader['e_type']))
         self._emitline('Entry point is %s' %
-                self._format_hex(elfheader['e_entry']))
+            self._format_hex(elfheader['e_entry']))
+        # readelf weirness - why isn't e_phoff printed as hex? (for section
+        # headers, it is...)
         self._emitline('There are %s program headers, starting at offset %s' % (
-                elfheader['e_phnum'], elfheader['e_phoff']))
+            elfheader['e_phnum'], elfheader['e_phoff']))
 
         self._emitline('\nProgram headers:')
 
@@ -165,9 +167,57 @@
 
             self._emitline('')
 
+    def display_section_headers(self):
+        """ Display the ELF section headers
+        """
+        elfheader = self.elffile.header
+        self._emitline('There are %s section headers, starting at offset %s' % (
+            elfheader['e_shnum'], self._format_hex(elfheader['e_shoff'])))
 
+        self._emitline('\nSection header%s:' % (
+            's' if elfheader['e_shnum'] > 1 else ''))
 
-        
+        # Different formatting constraints of 32-bit and 64-bit addresses
+        #
+        if self.elffile.elfclass == 32:
+            self._emitline('  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al')
+        else:
+            self._emitline('  [Nr] Name              Type             Address           Offset')
+            self._emitline('       Size              EntSize          Flags  Link  Info  Align')
+
+        # Now the entries
+        #
+        for nsec, section in enumerate(self.elffile.iter_sections()):
+            self._emit('  [%2u] %-17.17s %-15.15s ' % (
+                nsec, section.name, describe_sh_type(section['sh_type'])))
+
+            if self.elffile.elfclass == 32:
+                self._emitline('%s %s %s %s %3s %2s %3s %2s' % (
+                    self._format_hex(section['sh_addr'], fieldsize=8, lead0x=False),
+                    self._format_hex(section['sh_offset'], fieldsize=6, lead0x=False),
+                    self._format_hex(section['sh_size'], fieldsize=6, lead0x=False),
+                    self._format_hex(section['sh_entsize'], fieldsize=2, lead0x=False),
+                    describe_sh_flags(section['sh_flags']),
+                    section['sh_link'], section['sh_info'],
+                    section['sh_addralign']))
+            else: # 64
+                self._emitline(' %s  %s' % (
+                    self._format_hex(section['sh_addr'], fullhex=True, lead0x=False),
+                    self._format_hex(section['sh_offset'],
+                        fieldsize=16 if section['sh_offset'] > 0xffffffff else 8,
+                        lead0x=False)))
+                self._emitline('       %s  %s %3s      %2s   %3s     %s' % (
+                    self._format_hex(section['sh_size'], fullhex=True, lead0x=False),
+                    self._format_hex(section['sh_entsize'], fullhex=True, lead0x=False),
+                    describe_sh_flags(section['sh_flags']),
+                    section['sh_link'], section['sh_info'],
+                    section['sh_addralign']))
+
+        self._emitline('Key to Flags:')
+        self._emitline('  W (write), A (alloc), X (execute), M (merge), S (strings)')
+        self._emitline('  I (info), L (link order), G (group), x (unknown)')
+        self._emitline('  O (extra OS processing required) o (OS specific), p (processor specific)')
+
     def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True):
         """ Format an address into a hexadecimal string.
 
@@ -213,7 +263,8 @@
             readelf = ReadElf(file, sys.stdout)
             readelf.display_file_header()
             print '----'
-            readelf.display_program_headers()
+            #readelf.display_program_headers()
+            readelf.display_section_headers()
         except ELFError as ex:
             sys.stderr.write('ELF read error: %s\n' % ex)
             sys.exit(1)